summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2011-02-06 16:54:59 -0500
committerKristian Høgsberg <krh@bitplanet.net>2011-02-07 09:12:56 -0500
commitc9824ddf3524fd329e7de8870a20d62e673d3a4e (patch)
tree387f2dd4b6f2e3e9ce07136302d09d773a61c05b
parentf30c67eea63e04995a79b8ff7056de0975bad80d (diff)
compositor: Implement super-tab window switching
-rw-r--r--compositor/compositor.c108
-rw-r--r--compositor/compositor.h1
2 files changed, 99 insertions, 10 deletions
diff --git a/compositor/compositor.c b/compositor/compositor.c
index f016d935..535b3f1a 100644
--- a/compositor/compositor.c
+++ b/compositor/compositor.c
@@ -35,6 +35,12 @@
#include "wayland-server.h"
#include "compositor.h"
+struct wlsc_switcher {
+ struct wlsc_compositor *compositor;
+ struct wlsc_surface *current;
+ struct wl_listener listener;
+};
+
/* The plan here is to generate a random anonymous socket name and
* advertise that through a service on the session dbus.
*/
@@ -416,10 +422,18 @@ wlsc_output_repaint(struct wlsc_output *output)
else
glClear(GL_COLOR_BUFFER_BIT);
- wl_list_for_each_reverse(es, &ec->surface_list, link)
+ wl_list_for_each_reverse(es, &ec->surface_list, link) {
+ if (ec->switcher &&
+ ec->switcher->current == es)
+ continue;
+
wlsc_surface_draw(es, output);
+ }
}
+ if (ec->switcher)
+ wlsc_surface_draw(ec->switcher->current, output);
+
if (ec->focus)
wl_list_for_each(eid, &ec->input_device_list, link)
wlsc_surface_draw(eid->sprite, output);
@@ -763,6 +777,20 @@ notify_motion(struct wl_input_device *device, uint32_t time, int x, int y)
wlsc_compositor_schedule_repaint(ec);
}
+static void
+wlsc_surface_activate(struct wlsc_surface *surface,
+ struct wlsc_input_device *device, uint32_t time)
+{
+ wlsc_surface_raise(surface);
+ if (device->selection)
+ wlsc_selection_set_focus(device->selection,
+ &surface->surface, time);
+
+ wl_input_device_set_keyboard_focus(&device->input_device,
+ &surface->surface,
+ time);
+}
+
void
notify_button(struct wl_input_device *device,
uint32_t time, int32_t button, int32_t state)
@@ -777,18 +805,10 @@ notify_button(struct wl_input_device *device,
int32_t x, y;
if (state && surface && device->grab == NULL) {
- wlsc_surface_raise(surface);
-
- if (wd->selection)
- wlsc_selection_set_focus(wd->selection,
- &surface->surface, time);
-
+ wlsc_surface_activate(surface, wd, time);
wl_input_device_start_grab(device,
&device->motion_grab,
button, time);
- wl_input_device_set_keyboard_focus(device,
- &surface->surface,
- time);
}
if (state && surface && button == BTN_LEFT &&
@@ -829,6 +849,53 @@ notify_button(struct wl_input_device *device,
wl_input_device_end_grab(device, time);
}
+static void
+wlsc_switcher_next(struct wlsc_switcher *switcher)
+{
+ struct wl_list *l;
+
+ l = switcher->current->link.next;
+ if (l == &switcher->compositor->surface_list)
+ l = switcher->compositor->surface_list.next;
+ switcher->current = container_of(l, struct wlsc_surface, link);
+ wl_list_remove(&switcher->listener.link);
+ wl_list_insert(switcher->current->surface.destroy_listener_list.prev,
+ &switcher->listener.link);
+ wlsc_compositor_schedule_repaint(switcher->compositor);
+}
+
+static void
+switcher_handle_surface_destroy(struct wl_listener *listener,
+ struct wl_surface *surface, uint32_t time)
+{
+ struct wlsc_switcher *switcher =
+ container_of(listener, struct wlsc_switcher, listener);
+
+ wlsc_switcher_next(switcher);
+}
+
+static struct wlsc_switcher *
+wlsc_switcher_create(struct wlsc_compositor *compositor)
+{
+ struct wlsc_switcher *switcher;
+
+ switcher = malloc(sizeof *switcher);
+ switcher->compositor = compositor;
+ switcher->current = container_of(compositor->surface_list.next,
+ struct wlsc_surface, link);
+ switcher->listener.func = switcher_handle_surface_destroy;
+ wl_list_init(&switcher->listener.link);
+
+ return switcher;
+}
+
+static void
+wlsc_switcher_destroy(struct wlsc_switcher *switcher)
+{
+ wl_list_remove(&switcher->listener.link);
+ free(switcher);
+}
+
void
notify_key(struct wl_input_device *device,
uint32_t time, uint32_t key, uint32_t state)
@@ -843,6 +910,27 @@ notify_key(struct wl_input_device *device,
case KEY_BACKSPACE | MODIFIER_CTRL | MODIFIER_ALT:
wl_display_terminate(compositor->wl_display);
return;
+
+ case KEY_TAB | MODIFIER_SUPER:
+ if (!state)
+ return;
+ if (wl_list_empty(&compositor->surface_list))
+ return;
+ if (compositor->switcher == NULL)
+ compositor->switcher = wlsc_switcher_create(compositor);
+
+ wlsc_switcher_next(compositor->switcher);
+ return;
+
+ case KEY_LEFTMETA | MODIFIER_SUPER:
+ case KEY_RIGHTMETA | MODIFIER_SUPER:
+ if (compositor->switcher && !state) {
+ wlsc_surface_activate(compositor->switcher->current,
+ wd, time);
+ wlsc_switcher_destroy(compositor->switcher);
+ compositor->switcher = NULL;
+ }
+ break;
}
switch (key) {
diff --git a/compositor/compositor.h b/compositor/compositor.h
index b3dddda3..dfe99516 100644
--- a/compositor/compositor.h
+++ b/compositor/compositor.h
@@ -110,6 +110,7 @@ struct wlsc_compositor {
int repaint_on_timeout;
struct timespec previous_swap;
+ struct wlsc_switcher *switcher;
uint32_t focus;
void (*destroy)(struct wlsc_compositor *ec);