Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Virtual input #251

Merged
merged 1 commit into from
Jan 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions cage.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
#include <wlr/types/wlr_single_pixel_buffer_v1.h>
#include <wlr/types/wlr_subcompositor.h>
#include <wlr/types/wlr_viewporter.h>
#include <wlr/types/wlr_virtual_keyboard_v1.h>
#include <wlr/types/wlr_virtual_pointer_v1.h>
#if CAGE_HAS_XWAYLAND
#include <wlr/types/wlr_xcursor_manager.h>
#endif
Expand Down Expand Up @@ -270,6 +272,8 @@ main(int argc, char *argv[])
struct wlr_single_pixel_buffer_manager_v1 *single_pixel_buffer = NULL;
struct wlr_xdg_output_manager_v1 *output_manager = NULL;
struct wlr_gamma_control_manager_v1 *gamma_control_manager = NULL;
struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard = NULL;
struct wlr_virtual_pointer_manager_v1 *virtual_pointer = NULL;
struct wlr_viewporter *viewporter = NULL;
struct wlr_presentation *presentation = NULL;
struct wlr_xdg_shell *xdg_shell = NULL;
Expand Down Expand Up @@ -482,6 +486,22 @@ main(int argc, char *argv[])
goto end;
}

virtual_keyboard = wlr_virtual_keyboard_manager_v1_create(server.wl_display);
if (!virtual_keyboard) {
wlr_log(WLR_ERROR, "Unable to create the virtual keyboard manager");
ret = 1;
goto end;
}
wl_signal_add(&virtual_keyboard->events.new_virtual_keyboard, &server.new_virtual_keyboard);

virtual_pointer = wlr_virtual_pointer_manager_v1_create(server.wl_display);
if (!virtual_pointer) {
wlr_log(WLR_ERROR, "Unable to create the virtual pointer manager");
ret = 1;
goto end;
}
wl_signal_add(&virtual_pointer->events.new_virtual_pointer, &server.new_virtual_pointer);

#if CAGE_HAS_XWAYLAND
xwayland = wlr_xwayland_create(server.wl_display, compositor, true);
if (!xwayland) {
Expand Down
74 changes: 63 additions & 11 deletions seat.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@
* See the LICENSE file accompanying this file.
*/

#define _POSIX_C_SOURCE 200809L

#include "config.h"

#include <assert.h>
#include <linux/input-event-codes.h>
#include <stdlib.h>
#include <string.h>
#include <wayland-server-core.h>
#include <wlr/backend.h>
#include <wlr/backend/multi.h>
Expand All @@ -22,6 +25,8 @@
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_seat.h>
#include <wlr/types/wlr_touch.h>
#include <wlr/types/wlr_virtual_keyboard_v1.h>
#include <wlr/types/wlr_virtual_pointer_v1.h>
#include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/util/log.h>
#if CAGE_HAS_XWAYLAND
Expand Down Expand Up @@ -216,6 +221,27 @@ handle_new_pointer(struct cg_seat *seat, struct wlr_pointer *wlr_pointer)
map_input_device_to_output(seat, &wlr_pointer->base, wlr_pointer->output_name);
}

static void
handle_virtual_pointer(struct wl_listener *listener, void *data)
{
struct cg_server *server = wl_container_of(listener, server, new_virtual_pointer);
struct cg_seat *seat = server->seat;
struct wlr_virtual_pointer_v1_new_pointer_event *event = data;
struct wlr_virtual_pointer_v1 *pointer = event->new_pointer;
struct wlr_pointer *wlr_pointer = &pointer->pointer;

/* We'll want to map the device back to an output later, this is a bit
* sub-optimal (we could just keep the suggested_output), but just copy
* its name so we do like other devices
*/
if (event->suggested_output != NULL) {
wlr_pointer->output_name = strdup(event->suggested_output->name);
}
/* TODO: event->suggested_seat should be checked if we handle multiple seats */
handle_new_pointer(seat, wlr_pointer);
update_capabilities(seat);
}

static void
handle_modifier_event(struct wlr_keyboard *keyboard, struct cg_seat *seat)
{
Expand Down Expand Up @@ -295,14 +321,21 @@ handle_keyboard_group_modifiers(struct wl_listener *listener, void *data)
}

static void
cg_keyboard_group_add(struct wlr_keyboard *keyboard, struct cg_seat *seat)
{
struct cg_keyboard_group *group;
wl_list_for_each (group, &seat->keyboard_groups, link) {
struct wlr_keyboard_group *wlr_group = group->wlr_group;
if (wlr_keyboard_group_add_keyboard(wlr_group, keyboard)) {
wlr_log(WLR_DEBUG, "Added new keyboard to existing group");
return;
cg_keyboard_group_add(struct wlr_keyboard *keyboard, struct cg_seat *seat, bool virtual)
{
/* We apparently should not group virtual keyboards,
* so create a new group with it
*/
if (!virtual) {
struct cg_keyboard_group *group;
wl_list_for_each (group, &seat->keyboard_groups, link) {
if (group->is_virtual)
continue;
struct wlr_keyboard_group *wlr_group = group->wlr_group;
if (wlr_keyboard_group_add_keyboard(wlr_group, keyboard)) {
wlr_log(WLR_DEBUG, "Added new keyboard to existing group");
return;
}
}
}

Expand All @@ -314,6 +347,7 @@ cg_keyboard_group_add(struct wlr_keyboard *keyboard, struct cg_seat *seat)
return;
}
cg_group->seat = seat;
cg_group->is_virtual = virtual;
cg_group->wlr_group = wlr_keyboard_group_create();
if (cg_group->wlr_group == NULL) {
wlr_log(WLR_ERROR, "Failed to create wlr keyboard group.");
Expand Down Expand Up @@ -346,7 +380,7 @@ cg_keyboard_group_add(struct wlr_keyboard *keyboard, struct cg_seat *seat)
}

static void
handle_new_keyboard(struct cg_seat *seat, struct wlr_keyboard *keyboard)
handle_new_keyboard(struct cg_seat *seat, struct wlr_keyboard *keyboard, bool virtual)
{
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!context) {
Expand All @@ -367,11 +401,26 @@ handle_new_keyboard(struct cg_seat *seat, struct wlr_keyboard *keyboard)
xkb_context_unref(context);
wlr_keyboard_set_repeat_info(keyboard, 25, 600);

cg_keyboard_group_add(keyboard, seat);
cg_keyboard_group_add(keyboard, seat, virtual);

wlr_seat_set_keyboard(seat->seat, keyboard);
}

static void
handle_virtual_keyboard(struct wl_listener *listener, void *data)
{
struct cg_server *server = wl_container_of(listener, server, new_virtual_keyboard);
struct cg_seat *seat = server->seat;
struct wlr_virtual_keyboard_v1 *keyboard = data;
struct wlr_keyboard *wlr_keyboard = &keyboard->keyboard;

/* TODO: If multiple seats are supported, check keyboard->seat
* to select the appropriate one */

handle_new_keyboard(seat, wlr_keyboard, true);
update_capabilities(seat);
}

static void
handle_new_input(struct wl_listener *listener, void *data)
{
Expand All @@ -380,7 +429,7 @@ handle_new_input(struct wl_listener *listener, void *data)

switch (device->type) {
case WLR_INPUT_DEVICE_KEYBOARD:
handle_new_keyboard(seat, wlr_keyboard_from_input_device(device));
handle_new_keyboard(seat, wlr_keyboard_from_input_device(device), false);
break;
case WLR_INPUT_DEVICE_POINTER:
handle_new_pointer(seat, wlr_pointer_from_input_device(device));
Expand Down Expand Up @@ -797,6 +846,9 @@ seat_create(struct cg_server *server, struct wlr_backend *backend)
seat->new_input.notify = handle_new_input;
wl_signal_add(&backend->events.new_input, &seat->new_input);

server->new_virtual_keyboard.notify = handle_virtual_keyboard;
server->new_virtual_pointer.notify = handle_virtual_pointer;

wl_list_init(&seat->drag_icons);
seat->request_start_drag.notify = handle_request_start_drag;
wl_signal_add(&seat->seat->events.request_start_drag, &seat->request_start_drag);
Expand Down
1 change: 1 addition & 0 deletions seat.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ struct cg_keyboard_group {
struct wl_listener key;
struct wl_listener modifiers;
struct wl_list link; // cg_seat::keyboard_groups
bool is_virtual;
};

struct cg_pointer {
Expand Down
7 changes: 3 additions & 4 deletions server.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@
#include <wlr/xwayland.h>
#endif

#include "output.h"
#include "seat.h"
#include "view.h"

enum cg_multi_output_mode {
CAGE_MULTI_OUTPUT_MODE_EXTEND,
CAGE_MULTI_OUTPUT_MODE_LAST,
Expand Down Expand Up @@ -44,6 +40,9 @@ struct cg_server {

struct wl_listener xdg_toplevel_decoration;
struct wl_listener new_xdg_shell_surface;

struct wl_listener new_virtual_keyboard;
struct wl_listener new_virtual_pointer;
#if CAGE_HAS_XWAYLAND
struct wl_listener new_xwayland_surface;
#endif
Expand Down