diff options
Diffstat (limited to 'rootston')
| -rw-r--r-- | rootston/cursor.c | 7 | ||||
| -rw-r--r-- | rootston/desktop.c | 98 | ||||
| -rw-r--r-- | rootston/layer_shell.c | 1 | ||||
| -rw-r--r-- | rootston/seat.c | 57 | 
4 files changed, 117 insertions, 46 deletions
diff --git a/rootston/cursor.c b/rootston/cursor.c index ac46ff5d..21e32a09 100644 --- a/rootston/cursor.c +++ b/rootston/cursor.c @@ -111,6 +111,9 @@ static void roots_passthrough_cursor(struct roots_cursor *cursor,  	if (surface) {  		client = wl_resource_get_client(surface->resource);  	} +	if (surface && !roots_seat_allow_input(cursor->seat, surface->resource)) { +		return; +	}  	if (cursor->cursor_client != client) {  		wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, @@ -327,7 +330,7 @@ void roots_cursor_handle_touch_down(struct roots_cursor *cursor,  			desktop, lx, ly, &sx, &sy, NULL);  	uint32_t serial = 0; -	if (surface) { +	if (surface && roots_seat_allow_input(cursor->seat, surface->resource)) {  		serial = wlr_seat_touch_notify_down(cursor->seat->seat, surface,  			event->time_msec, event->touch_id, sx, sy);  	} @@ -378,7 +381,7 @@ void roots_cursor_handle_touch_motion(struct roots_cursor *cursor,  	struct wlr_surface *surface = desktop_surface_at(  			desktop, lx, ly, &sx, &sy, NULL); -	if (surface) { +	if (surface && roots_seat_allow_input(cursor->seat, surface->resource)) {  		wlr_seat_touch_point_focus(cursor->seat->seat, surface,  			event->time_msec, event->touch_id, sx, sy);  		wlr_seat_touch_notify_motion(cursor->seat->seat, event->time_msec, diff --git a/rootston/desktop.c b/rootston/desktop.c index ab16ed3d..f1afe2c9 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -10,6 +10,7 @@  #include <wlr/types/wlr_gamma_control.h>  #include <wlr/types/wlr_idle.h>  #include <wlr/types/wlr_idle_inhibit_v1.h> +#include <wlr/types/wlr_input_inhibitor.h>  #include <wlr/types/wlr_layer_shell.h>  #include <wlr/types/wlr_linux_dmabuf.h>  #include <wlr/types/wlr_output_layout.h> @@ -19,6 +20,7 @@  #include <wlr/types/wlr_xcursor_manager.h>  #include <wlr/types/wlr_xdg_shell_v6.h>  #include <wlr/types/wlr_xdg_shell.h> +#include <wlr/types/wlr_xdg_output.h>  #include <wlr/util/log.h>  #include "rootston/layers.h"  #include "rootston/seat.h" @@ -576,42 +578,30 @@ static bool view_at(struct roots_view *view, double lx, double ly,  		view_sy = ry + (double)box.height/2;  	} -	if (view->type == ROOTS_XDG_SHELL_V6_VIEW) { -		double popup_sx, popup_sy; -		struct wlr_xdg_surface_v6 *popup = -			wlr_xdg_surface_v6_popup_at(view->xdg_surface_v6, -				view_sx, view_sy, &popup_sx, &popup_sy); - -		if (popup) { -			*sx = view_sx - popup_sx; -			*sy = view_sy - popup_sy; -			*surface = popup->surface; -			return true; -		} -	} - -	if (view->type == ROOTS_WL_SHELL_VIEW) { -		double popup_sx, popup_sy; -		struct wlr_wl_shell_surface *popup = -			wlr_wl_shell_surface_popup_at(view->wl_shell_surface, -				view_sx, view_sy, &popup_sx, &popup_sy); - -		if (popup) { -			*sx = view_sx - popup_sx; -			*sy = view_sy - popup_sy; -			*surface = popup->surface; -			return true; -		} -	} - -	double sub_x, sub_y; -	struct wlr_subsurface *subsurface = -		wlr_surface_subsurface_at(view->wlr_surface, -			view_sx, view_sy, &sub_x, &sub_y); -	if (subsurface) { -		*sx = view_sx - sub_x; -		*sy = view_sy - sub_y; -		*surface = subsurface->surface; +	double _sx, _sy; +	struct wlr_surface *_surface = NULL; +	switch (view->type) { +	case ROOTS_XDG_SHELL_V6_VIEW: +		_surface = wlr_xdg_surface_v6_surface_at(view->xdg_surface_v6, +			view_sx, view_sy, &_sx, &_sy); +		break; +	case ROOTS_XDG_SHELL_VIEW: +		_surface = wlr_xdg_surface_surface_at(view->xdg_surface, +			view_sx, view_sy, &_sx, &_sy); +		break; +	case ROOTS_WL_SHELL_VIEW: +		_surface = wlr_wl_shell_surface_surface_at(view->wl_shell_surface, +			view_sx, view_sy, &_sx, &_sy); +		break; +	case ROOTS_XWAYLAND_VIEW: +		_surface = wlr_surface_surface_at(view->wlr_surface, +			view_sx, view_sy, &_sx, &_sy); +		break; +	} +	if (_surface != NULL) { +		*sx = _sx; +		*sy = _sy; +		*surface = _surface;  		return true;  	} @@ -622,13 +612,6 @@ static bool view_at(struct roots_view *view, double lx, double ly,  		return true;  	} -	if (wlr_surface_point_accepts_input(view->wlr_surface, view_sx, view_sy)) { -		*sx = view_sx; -		*sy = view_sy; -		*surface = view->wlr_surface; -		return true; -	} -  	return false;  } @@ -755,6 +738,25 @@ static void handle_layout_change(struct wl_listener *listener, void *data) {  	}  } +static void input_inhibit_activate(struct wl_listener *listener, void *data) { +	struct roots_desktop *desktop = wl_container_of( +			listener, desktop, input_inhibit_activate); +	struct roots_seat *seat; +	wl_list_for_each(seat, &desktop->server->input->seats, link) { +		roots_seat_set_exclusive_client(seat, +				desktop->input_inhibit->active_client); +	} +} + +static void input_inhibit_deactivate(struct wl_listener *listener, void *data) { +	struct roots_desktop *desktop = wl_container_of( +			listener, desktop, input_inhibit_deactivate); +	struct roots_seat *seat; +	wl_list_for_each(seat, &desktop->server->input->seats, link) { +		roots_seat_set_exclusive_client(seat, NULL); +	} +} +  struct roots_desktop *desktop_create(struct roots_server *server,  		struct roots_config *config) {  	wlr_log(L_DEBUG, "Initializing roots desktop"); @@ -774,6 +776,7 @@ struct roots_desktop *desktop_create(struct roots_server *server,  	desktop->config = config;  	desktop->layout = wlr_output_layout_create(); +	wlr_xdg_output_manager_create(server->wl_display, desktop->layout);  	desktop->layout_change.notify = handle_layout_change;  	wl_signal_add(&desktop->layout->events.change, &desktop->layout_change); @@ -855,6 +858,15 @@ struct roots_desktop *desktop_create(struct roots_server *server,  	desktop->idle = wlr_idle_create(server->wl_display);  	desktop->idle_inhibit = wlr_idle_inhibit_v1_create(server->wl_display); +	desktop->input_inhibit = +		wlr_input_inhibit_manager_create(server->wl_display); +	desktop->input_inhibit_activate.notify = input_inhibit_activate; +	wl_signal_add(&desktop->input_inhibit->events.activate, +			&desktop->input_inhibit_activate); +	desktop->input_inhibit_deactivate.notify = input_inhibit_deactivate; +	wl_signal_add(&desktop->input_inhibit->events.deactivate, +			&desktop->input_inhibit_deactivate); +  	struct wlr_egl *egl = wlr_backend_get_egl(server->backend);  	desktop->linux_dmabuf = wlr_linux_dmabuf_create(server->wl_display, egl);  	return desktop; diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index 1cd93b3c..9794071b 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -281,6 +281,7 @@ static void handle_map(struct wl_listener *listener, void *data) {  	struct wlr_output *wlr_output = layer_surface->output;  	struct roots_output *output = wlr_output->data;  	wlr_output_damage_add_box(output->damage, &layer->geo); +	wlr_surface_send_enter(layer_surface->surface, wlr_output);  }  static void handle_unmap(struct wl_listener *listener, void *data) { diff --git a/rootston/seat.c b/rootston/seat.c index cfdeab00..e12df7d6 100644 --- a/rootston/seat.c +++ b/rootston/seat.c @@ -1,6 +1,8 @@ +#define _POSIX_C_SOURCE 199309L  #include <assert.h>  #include <stdlib.h>  #include <string.h> +#include <time.h>  #include <wayland-server.h>  #include <wlr/config.h>  #include <wlr/types/wlr_idle.h> @@ -716,7 +718,17 @@ struct roots_seat_view *roots_seat_view_from_view(  	return seat_view;  } +bool roots_seat_allow_input(struct roots_seat *seat, +		struct wl_resource *resource) { +	return !seat->exclusive_client || +			wl_resource_get_client(resource) == seat->exclusive_client; +} +  void roots_seat_set_focus(struct roots_seat *seat, struct roots_view *view) { +	if (view && !roots_seat_allow_input(seat, view->wlr_surface->resource)) { +		return; +	} +  	// Make sure the view will be rendered on top of others, even if it's  	// already focused in this seat  	if (view != NULL) { @@ -811,11 +823,14 @@ void roots_seat_set_focus(struct roots_seat *seat, struct roots_view *view) {   */  void roots_seat_set_focus_layer(struct roots_seat *seat,  		struct wlr_layer_surface *layer) { -	struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->seat);  	if (!layer) {  		seat->focused_layer = NULL;  		return;  	} +	struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->seat); +	if (!roots_seat_allow_input(seat, layer->resource)) { +		return; +	}  	if (seat->has_focus) {  		struct roots_view *prev_focus = roots_seat_get_focus(seat);  		wlr_seat_keyboard_clear_focus(seat->seat); @@ -835,6 +850,46 @@ void roots_seat_set_focus_layer(struct roots_seat *seat,  	}  } +void roots_seat_set_exclusive_client(struct roots_seat *seat, +		struct wl_client *client) { +	if (!client) { +		seat->exclusive_client = client; +		// Triggers a refocus of the topmost surface layer if necessary +		// TODO: Make layer surface focus per-output based on cursor position +		struct roots_output *output; +		wl_list_for_each(output, &seat->input->server->desktop->outputs, link) { +			arrange_layers(output); +		} +		return; +	} +	if (seat->focused_layer) { +		if (wl_resource_get_client(seat->focused_layer->resource) != client) { +			roots_seat_set_focus_layer(seat, NULL); +		} +	} +	if (seat->has_focus) { +		struct roots_view *focus = roots_seat_get_focus(seat); +		if (wl_resource_get_client(focus->wlr_surface->resource) != client) { +			roots_seat_set_focus(seat, NULL); +		} +	} +	if (seat->seat->pointer_state.focused_client) { +		if (seat->seat->pointer_state.focused_client->client != client) { +			wlr_seat_pointer_clear_focus(seat->seat); +		} +	} +	struct timespec now; +	clock_gettime(CLOCK_MONOTONIC, &now); +	struct wlr_touch_point *point; +	wl_list_for_each(point, &seat->seat->touch_state.touch_points, link) { +		if (point->client->client != client) { +			wlr_seat_touch_point_clear_focus(seat->seat, +					now.tv_nsec / 1000, point->touch_id); +		} +	} +	seat->exclusive_client = client; +} +  void roots_seat_cycle_focus(struct roots_seat *seat) {  	if (wl_list_empty(&seat->views)) {  		return;  | 
