/* if set, views cannot receive focus */
struct wlr_layer_surface_v1 *focused_layer;
+ struct wl_client *active_client_while_inhibited;
struct wl_list inputs;
struct wl_listener new_input;
struct wl_listener new_xwayland_surface;
#endif
+ struct wlr_input_inhibit_manager *input_inhibit;
+ struct wl_listener input_inhibit_activate;
+ struct wl_listener input_inhibit_deactivate;
+
struct wl_list views;
struct wl_list unmanaged_surfaces;
/* update onscreen display 'alt-tab' texture */
void osd_update(struct server *server);
+/* wlroots "input inhibitor" extension (required for swaylock) blocks
+ * any client other than the requesting client from receiving events
+ */
+bool input_inhibit_blocks_surface(struct seat *seat,
+ struct wl_resource *resource);
+
+
#endif /* __LABWC_H */
server_protocols = [
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
['wlr-layer-shell-unstable-v1.xml'],
+ ['wlr-input-inhibitor-unstable-v1.xml'],
]
server_protos_src = []
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="wlr_input_inhibit_unstable_v1">
+ <copyright>
+ Copyright © 2018 Drew DeVault
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that copyright notice and this permission
+ notice appear in supporting documentation, and that the name of
+ the copyright holders not be used in advertising or publicity
+ pertaining to distribution of the software without specific,
+ written prior permission. The copyright holders make no
+ representations about the suitability of this software for any
+ purpose. It is provided "as is" without express or implied
+ warranty.
+
+ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ THIS SOFTWARE.
+ </copyright>
+
+ <interface name="zwlr_input_inhibit_manager_v1" version="1">
+ <description summary="inhibits input events to other clients">
+ Clients can use this interface to prevent input events from being sent to
+ any surfaces but its own, which is useful for example in lock screen
+ software. It is assumed that access to this interface will be locked down
+ to whitelisted clients by the compositor.
+ </description>
+
+ <request name="get_inhibitor">
+ <description summary="inhibit input to other clients">
+ Activates the input inhibitor. As long as the inhibitor is active, the
+ compositor will not send input events to other clients.
+ </description>
+ <arg name="id" type="new_id" interface="zwlr_input_inhibitor_v1"/>
+ </request>
+
+ <enum name="error">
+ <entry name="already_inhibited" value="0" summary="an input inhibitor is already in use on the compositor"/>
+ </enum>
+ </interface>
+
+ <interface name="zwlr_input_inhibitor_v1" version="1">
+ <description summary="inhibits input to other clients">
+ While this resource exists, input to clients other than the owner of the
+ inhibitor resource will not receive input events. The client that owns
+ this resource will receive all input events normally. The compositor will
+ also disable all of its own input processing (such as keyboard shortcuts)
+ while the inhibitor is active.
+
+ The compositor may continue to send input events to selected clients,
+ such as an on-screen keyboard (via the input-method protocol).
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the input inhibitor object">
+ Destroy the inhibitor and allow other clients to receive input.
+ </description>
+ </request>
+ </interface>
+</protocol>
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)
{
/* 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;
/*
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) {
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);
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 */
/* 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;
}
}
}
}
}
+ 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,
#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"
}
}
+static void seat_clear_touch_points(struct seat *seat,
+ struct wl_client *active_client){
+ 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 != active_client) {
+ wlr_seat_touch_point_clear_focus(seat->seat,
+ now.tv_nsec / 1000, point->touch_id);
+ }
+ }
+}
+
+
+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))
+ {
+ wlr_log(WLR_INFO, "defocus layer");
+ 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) {
+ wlr_log(WLR_INFO, "defocus surface");
+ 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_log(WLR_INFO, "defocus ptr");
+ wlr_seat_pointer_clear_focus(seat->seat);
+ }
+ seat_clear_touch_points(seat, active_client);
+}
+
+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 roots_output *output;
+ wl_list_for_each(output, &seat->input->server->desktop->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)
{
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);