Merge pull request #54 from telent/lockdown

implement input_inhibit protocol, needed for swaylock
This commit is contained in:
Johan Malm 2021-08-24 21:56:13 +01:00 committed by GitHub
commit 824282dd2e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 195 additions and 8 deletions

View file

@ -105,6 +105,15 @@ set_cursor(struct server *server, const char *cursor_name)
server->seat.xcursor_manager, cursor_name, server->seat.cursor);
}
bool input_inhibit_blocks_surface(struct seat *seat,
struct wl_resource *resource)
{
struct wl_client * inhibiting_client =
seat->active_client_while_inhibited;
return (inhibiting_client != NULL) &&
inhibiting_client != wl_resource_get_client(resource);
}
static void
process_cursor_motion(struct server *server, uint32_t time)
{
@ -161,7 +170,8 @@ process_cursor_motion(struct server *server, uint32_t time)
/* Required for iconify/maximize/close button mouse-over deco */
damage_all_outputs(server);
if (surface) {
if (surface &&
! input_inhibit_blocks_surface(&server->seat, surface->resource)) {
bool focus_changed =
wlr_seat->pointer_state.focused_surface != surface;
/*

View file

@ -76,6 +76,9 @@ desktop_set_focus_view_only(struct seat *seat, struct view *view)
if (!view || view->minimized || !view->mapped) {
return;
}
if(input_inhibit_blocks_surface(seat, view->surface->resource))
return;
struct wlr_surface *prev_surface;
prev_surface = seat->seat->keyboard_state.focused_surface;
if (prev_surface == view->surface) {
@ -96,6 +99,9 @@ desktop_focus_view(struct seat *seat, struct view *view)
seat_focus_surface(seat, NULL);
return;
}
if(input_inhibit_blocks_surface(seat, view->surface->resource))
return;
if (view->minimized) {
/* this will unmap and then focus */
view_minimize(view, false);

View file

@ -41,14 +41,12 @@ handle_keybinding(struct server *server, uint32_t modifiers, xkb_keysym_t sym)
return false;
}
static void
keyboard_key_notify(struct wl_listener *listener, void *data)
static bool
handle_compositor_keybindings(struct wl_listener *listener,
struct wlr_event_keyboard_key *event)
{
/* This event is raised when a key is pressed or released. */
struct seat *seat = wl_container_of(listener, seat, keyboard_key);
struct server *server = seat->server;
struct wlr_event_keyboard_key *event = data;
struct wlr_seat *wlr_seat = server->seat.seat;
struct wlr_input_device *device = seat->keyboard_group->input_device;
/* Translate libinput keycode -> xkbcommon */
@ -68,13 +66,14 @@ keyboard_key_notify(struct wl_listener *listener, void *data)
/* end cycle */
desktop_focus_view(&server->seat, server->cycle_view);
server->cycle_view = NULL;
/* XXX should we handled=true here? */
} else if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
/* cycle to next */
server->cycle_view =
desktop_cycle_view(server, server->cycle_view);
osd_update(server);
damage_all_outputs(server);
return;
return true;
}
}
@ -95,8 +94,28 @@ keyboard_key_notify(struct wl_listener *listener, void *data)
}
}
}
return handled;
}
static void
keyboard_key_notify(struct wl_listener *listener, void *data)
{
/* XXX need to check if input inhibited before doing any
* compositor bindings
*/
/* This event is raised when a key is pressed or released. */
struct seat *seat = wl_container_of(listener, seat, keyboard_key);
struct server *server = seat->server;
struct wlr_event_keyboard_key *event = data;
struct wlr_seat *wlr_seat = server->seat.seat;
struct wlr_input_device *device = seat->keyboard_group->input_device;
bool handled = false;
if(!seat->active_client_while_inhibited)
/* ignore labwc keybindings if input is inhibited */
handled = handle_compositor_keybindings(listener, event);
/* Otherwise, pass it to the client. */
if (!handled) {
wlr_seat_set_keyboard(wlr_seat, device);
wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec,

View file

@ -5,6 +5,7 @@
#include <wlr/types/wlr_data_control_v1.h>
#include <wlr/types/wlr_export_dmabuf_v1.h>
#include <wlr/types/wlr_gamma_control_v1.h>
#include <wlr/types/wlr_input_inhibitor.h>
#include <wlr/types/wlr_primary_selection_v1.h>
#include <wlr/types/wlr_screencopy_v1.h>
#include "config/rcxml.h"
@ -78,6 +79,62 @@ drop_permissions(void)
}
}
static void seat_inhibit_input(struct seat *seat, struct wl_client *active_client)
{
seat->active_client_while_inhibited = active_client;
if(seat->focused_layer &&
(wl_resource_get_client(seat->focused_layer->resource) !=
active_client))
{
seat_set_focus_layer(seat, NULL);
}
struct wlr_surface * previous_kb_surface = seat->seat->keyboard_state.focused_surface;
if (previous_kb_surface &&
wl_resource_get_client(previous_kb_surface->resource) != active_client) {
seat_focus_surface(seat, NULL); /* keyboard focus */
}
struct wlr_seat_client * previous_ptr_client = seat->seat->pointer_state.focused_client;
if (previous_ptr_client &&
(previous_ptr_client->client != active_client)) {
wlr_seat_pointer_clear_focus(seat->seat);
}
}
static void seat_disinhibit_input(struct seat *seat)
{
seat->active_client_while_inhibited = NULL;
// Triggers a refocus of the topmost surface layer if necessary
// TODO: Make layer surface focus per-output based on cursor position
struct output *output;
wl_list_for_each(output, &seat->server->outputs, link)
arrange_layers(output);
}
static void handle_input_inhibit(struct wl_listener *listener, void *data) {
wlr_log(WLR_INFO, "activate input inhibit");
struct server *server = wl_container_of(
listener, server, input_inhibit_activate);
seat_inhibit_input(&server->seat,
server->input_inhibit->active_client);
}
static void handle_input_disinhibit(struct wl_listener *listener, void *data) {
wlr_log(WLR_INFO, "deactivate input inhibit");
struct server *server = wl_container_of(
listener, server, input_inhibit_deactivate);
seat_disinhibit_input(&server->seat);
}
void
server_init(struct server *server)
{
@ -203,6 +260,19 @@ server_init(struct server *server)
wlr_data_control_manager_v1_create(server->wl_display);
wlr_gamma_control_manager_v1_create(server->wl_display);
// struct wlr_input_inhibit_manager *input_inhibit_mgr = NULL;
server->input_inhibit = wlr_input_inhibit_manager_create(server->wl_display);
if (!server->input_inhibit) {
wlr_log(WLR_ERROR, "unable to create the input inhibit manager");
exit(EXIT_FAILURE);
}
wl_signal_add(&server->input_inhibit->events.activate, &server->input_inhibit_activate);
server->input_inhibit_activate.notify = handle_input_inhibit;
wl_signal_add(&server->input_inhibit->events.deactivate, &server->input_inhibit_deactivate);
server->input_inhibit_deactivate.notify = handle_input_disinhibit;
server->foreign_toplevel_manager =
wlr_foreign_toplevel_manager_v1_create(server->wl_display);