mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-11-03 09:01:42 -05:00
compositor: Implement super-tab window switching
This commit is contained in:
parent
f30c67eea6
commit
c9824ddf35
2 changed files with 99 additions and 10 deletions
|
|
@ -35,6 +35,12 @@
|
||||||
#include "wayland-server.h"
|
#include "wayland-server.h"
|
||||||
#include "compositor.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
|
/* The plan here is to generate a random anonymous socket name and
|
||||||
* advertise that through a service on the session dbus.
|
* advertise that through a service on the session dbus.
|
||||||
*/
|
*/
|
||||||
|
|
@ -416,9 +422,17 @@ wlsc_output_repaint(struct wlsc_output *output)
|
||||||
else
|
else
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
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);
|
wlsc_surface_draw(es, output);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ec->switcher)
|
||||||
|
wlsc_surface_draw(ec->switcher->current, output);
|
||||||
|
|
||||||
if (ec->focus)
|
if (ec->focus)
|
||||||
wl_list_for_each(eid, &ec->input_device_list, link)
|
wl_list_for_each(eid, &ec->input_device_list, link)
|
||||||
|
|
@ -763,6 +777,20 @@ notify_motion(struct wl_input_device *device, uint32_t time, int x, int y)
|
||||||
wlsc_compositor_schedule_repaint(ec);
|
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
|
void
|
||||||
notify_button(struct wl_input_device *device,
|
notify_button(struct wl_input_device *device,
|
||||||
uint32_t time, int32_t button, int32_t state)
|
uint32_t time, int32_t button, int32_t state)
|
||||||
|
|
@ -777,18 +805,10 @@ notify_button(struct wl_input_device *device,
|
||||||
int32_t x, y;
|
int32_t x, y;
|
||||||
|
|
||||||
if (state && surface && device->grab == NULL) {
|
if (state && surface && device->grab == NULL) {
|
||||||
wlsc_surface_raise(surface);
|
wlsc_surface_activate(surface, wd, time);
|
||||||
|
|
||||||
if (wd->selection)
|
|
||||||
wlsc_selection_set_focus(wd->selection,
|
|
||||||
&surface->surface, time);
|
|
||||||
|
|
||||||
wl_input_device_start_grab(device,
|
wl_input_device_start_grab(device,
|
||||||
&device->motion_grab,
|
&device->motion_grab,
|
||||||
button, time);
|
button, time);
|
||||||
wl_input_device_set_keyboard_focus(device,
|
|
||||||
&surface->surface,
|
|
||||||
time);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state && surface && button == BTN_LEFT &&
|
if (state && surface && button == BTN_LEFT &&
|
||||||
|
|
@ -829,6 +849,53 @@ notify_button(struct wl_input_device *device,
|
||||||
wl_input_device_end_grab(device, time);
|
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
|
void
|
||||||
notify_key(struct wl_input_device *device,
|
notify_key(struct wl_input_device *device,
|
||||||
uint32_t time, uint32_t key, uint32_t state)
|
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:
|
case KEY_BACKSPACE | MODIFIER_CTRL | MODIFIER_ALT:
|
||||||
wl_display_terminate(compositor->wl_display);
|
wl_display_terminate(compositor->wl_display);
|
||||||
return;
|
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) {
|
switch (key) {
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,7 @@ struct wlsc_compositor {
|
||||||
int repaint_on_timeout;
|
int repaint_on_timeout;
|
||||||
struct timespec previous_swap;
|
struct timespec previous_swap;
|
||||||
|
|
||||||
|
struct wlsc_switcher *switcher;
|
||||||
uint32_t focus;
|
uint32_t focus;
|
||||||
|
|
||||||
void (*destroy)(struct wlsc_compositor *ec);
|
void (*destroy)(struct wlsc_compositor *ec);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue