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 "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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue