parent
a94c56a828
commit
5334ee8bfd
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef ROOTSTON_VIRTUAL_KEYBOARD_H
|
||||||
|
#define ROOTSTON_VIRTUAL_KEYBOARD_H
|
||||||
|
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
|
||||||
|
void handle_virtual_keyboard(struct wl_listener *listener, void *data);
|
||||||
|
#endif
|
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef WLR_TYPES_WLR_VIRTUAL_KEYBOARD_V1_H
|
||||||
|
#define WLR_TYPES_WLR_VIRTUAL_KEYBOARD_V1_H
|
||||||
|
|
||||||
|
#include <wayland-server.h>
|
||||||
|
#include <wlr/interfaces/wlr_input_device.h>
|
||||||
|
#include <wlr/interfaces/wlr_keyboard.h>
|
||||||
|
|
||||||
|
struct wlr_virtual_keyboard_manager_v1 {
|
||||||
|
struct wl_global *global;
|
||||||
|
struct wl_list resources; // struct wl_resource*
|
||||||
|
struct wl_list virtual_keyboards; // struct wlr_virtual_keyboard_v1*
|
||||||
|
|
||||||
|
struct wl_listener display_destroy;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct wl_signal new_virtual_keyboard; // struct wlr_virtual_keyboard_v1*
|
||||||
|
} events;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_virtual_keyboard_v1 {
|
||||||
|
struct wl_resource *resource;
|
||||||
|
struct wlr_input_device input_device;
|
||||||
|
struct wlr_seat *seat;
|
||||||
|
|
||||||
|
struct wl_list link;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct wl_signal destroy; // struct wlr_virtual_keyboard_v1*
|
||||||
|
} events;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_virtual_keyboard_manager_v1* wlr_virtual_keyboard_manager_v1_create(
|
||||||
|
struct wl_display *display);
|
||||||
|
void wlr_virtual_keyboard_manager_v1_destroy(
|
||||||
|
struct wlr_virtual_keyboard_manager_v1 *manager);
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,113 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<protocol name="virtual_keyboard_unstable_v1">
|
||||||
|
<copyright>
|
||||||
|
Copyright © 2008-2011 Kristian Høgsberg
|
||||||
|
Copyright © 2010-2013 Intel Corporation
|
||||||
|
Copyright © 2012-2013 Collabora, Ltd.
|
||||||
|
Copyright © 2018 Purism SPC
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice (including the next
|
||||||
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<interface name="zwp_virtual_keyboard_v1" version="1">
|
||||||
|
<description summary="virtual keyboard">
|
||||||
|
The virtual keyboard provides an application with requests which emulate
|
||||||
|
the behaviour of a physical keyboard.
|
||||||
|
|
||||||
|
This interface can be used by clients on its own to provide raw input
|
||||||
|
events, or it can accompany the input method protocol.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="keymap">
|
||||||
|
<description summary="keyboard mapping">
|
||||||
|
Provide a file descriptor to the compositor which can be
|
||||||
|
memory-mapped to provide a keyboard mapping description.
|
||||||
|
|
||||||
|
Format carries a value from the keymap_format enumeration.
|
||||||
|
</description>
|
||||||
|
<arg name="format" type="uint" summary="keymap format"/>
|
||||||
|
<arg name="fd" type="fd" summary="keymap file descriptor"/>
|
||||||
|
<arg name="size" type="uint" summary="keymap size, in bytes"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<enum name="error">
|
||||||
|
<entry name="no_keymap" value="0" summary="No keymap was set"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<request name="key">
|
||||||
|
<description summary="key event">
|
||||||
|
A key was pressed or released.
|
||||||
|
The time argument is a timestamp with millisecond granularity, with an
|
||||||
|
undefined base. All requests regarding a single object must share the
|
||||||
|
same clock.
|
||||||
|
|
||||||
|
Keymap must be set before issuing this request.
|
||||||
|
|
||||||
|
State carries a value from the key_state enumeration.
|
||||||
|
</description>
|
||||||
|
<arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
|
||||||
|
<arg name="key" type="uint" summary="key that produced the event"/>
|
||||||
|
<arg name="state" type="uint" summary="physical state of the key"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="modifiers">
|
||||||
|
<description summary="modifier and group state">
|
||||||
|
Notifies the compositor that the modifier and/or group state has
|
||||||
|
changed, and it should update state.
|
||||||
|
|
||||||
|
The client should use wl_keyboard.modifiers event to synchronize its
|
||||||
|
internal state with seat state.
|
||||||
|
|
||||||
|
Keymap must be set before issuing this request.
|
||||||
|
</description>
|
||||||
|
<arg name="mods_depressed" type="uint" summary="depressed modifiers"/>
|
||||||
|
<arg name="mods_latched" type="uint" summary="latched modifiers"/>
|
||||||
|
<arg name="mods_locked" type="uint" summary="locked modifiers"/>
|
||||||
|
<arg name="group" type="uint" summary="keyboard layout"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor" since="1">
|
||||||
|
<description summary="destroy the virtual keyboard keyboard object"/>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="zwp_virtual_keyboard_manager_v1" version="1">
|
||||||
|
<description summary="virtual keyboard manager">
|
||||||
|
A virtual keyboard manager allows an application to provide keyboard
|
||||||
|
input events as if they came from a physical keyboard.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<enum name="error">
|
||||||
|
<entry name="unauthorized" value="0" summary="client not authorized to use the interface"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<request name="create_virtual_keyboard">
|
||||||
|
<description summary="Create a new virtual keyboard">
|
||||||
|
Creates a new virtual keyboard associated to a seat.
|
||||||
|
|
||||||
|
If the compositor enables a keyboard to perform arbitrary actions, it
|
||||||
|
should present an error when an untrusted client requests a new
|
||||||
|
keyboard.
|
||||||
|
</description>
|
||||||
|
<arg name="seat" type="object" interface="wl_seat"/>
|
||||||
|
<arg name="id" type="new_id" interface="zwp_virtual_keyboard_v1"/>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
</protocol>
|
@ -0,0 +1,21 @@
|
|||||||
|
#define _POSIX_C_SOURCE 199309L
|
||||||
|
|
||||||
|
#include <wlr/util/log.h>
|
||||||
|
#include <wlr/types/wlr_virtual_keyboard_v1.h>
|
||||||
|
#include "rootston/virtual_keyboard.h"
|
||||||
|
#include "rootston/seat.h"
|
||||||
|
|
||||||
|
void handle_virtual_keyboard(struct wl_listener *listener, void *data) {
|
||||||
|
struct roots_desktop *desktop =
|
||||||
|
wl_container_of(listener, desktop, virtual_keyboard_new);
|
||||||
|
struct wlr_virtual_keyboard_v1 *keyboard = data;
|
||||||
|
|
||||||
|
struct roots_seat *seat = input_seat_from_wlr_seat(desktop->server->input,
|
||||||
|
keyboard->seat);
|
||||||
|
if (!seat) {
|
||||||
|
wlr_log(L_ERROR, "could not find roots seat");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
roots_seat_add_device(seat, &keyboard->input_device);
|
||||||
|
}
|
@ -0,0 +1,236 @@
|
|||||||
|
#define _POSIX_C_SOURCE 1
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <wlr/types/wlr_seat.h>
|
||||||
|
#include <wlr/types/wlr_virtual_keyboard_v1.h>
|
||||||
|
#include <wlr/util/log.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#include "util/signal.h"
|
||||||
|
#include "virtual-keyboard-unstable-v1-protocol.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void keyboard_led_update(struct wlr_keyboard *wlr_kb, uint32_t leds) {
|
||||||
|
// unsupported by virtual keyboard protocol
|
||||||
|
}
|
||||||
|
|
||||||
|
static void keyboard_destroy(struct wlr_keyboard *wlr_kb) {
|
||||||
|
// safe to ignore - keyboard will be destroyed only iff associated virtual
|
||||||
|
// keyboard is torn down, no need to tear down the keyboard separately
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wlr_keyboard_impl keyboard_impl = {
|
||||||
|
.destroy = keyboard_destroy,
|
||||||
|
.led_update = keyboard_led_update
|
||||||
|
};
|
||||||
|
|
||||||
|
static void input_device_destroy(struct wlr_input_device *dev) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wlr_input_device_impl input_device_impl = {
|
||||||
|
.destroy = input_device_destroy
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct zwp_virtual_keyboard_v1_interface virtual_keyboard_impl;
|
||||||
|
|
||||||
|
static struct wlr_virtual_keyboard_v1 *virtual_keyboard_from_resource(
|
||||||
|
struct wl_resource *resource) {
|
||||||
|
assert(wl_resource_instance_of(resource,
|
||||||
|
&zwp_virtual_keyboard_v1_interface, &virtual_keyboard_impl));
|
||||||
|
return wl_resource_get_user_data(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtual_keyboard_keymap(struct wl_client *client,
|
||||||
|
struct wl_resource *resource, uint32_t format, int32_t fd,
|
||||||
|
uint32_t size) {
|
||||||
|
struct wlr_virtual_keyboard_v1 *keyboard =
|
||||||
|
virtual_keyboard_from_resource(resource);
|
||||||
|
|
||||||
|
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
|
if (!context) {
|
||||||
|
goto context_fail;
|
||||||
|
}
|
||||||
|
void *data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
|
if (!data) {
|
||||||
|
goto fd_fail;
|
||||||
|
}
|
||||||
|
struct xkb_keymap *keymap = xkb_keymap_new_from_string(context, data,
|
||||||
|
XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
munmap(data, size);
|
||||||
|
if (!keymap) {
|
||||||
|
goto keymap_fail;
|
||||||
|
}
|
||||||
|
wlr_keyboard_set_keymap(keyboard->input_device.keyboard, keymap);
|
||||||
|
xkb_keymap_unref(keymap);
|
||||||
|
xkb_context_unref(context);
|
||||||
|
return;
|
||||||
|
keymap_fail:
|
||||||
|
fd_fail:
|
||||||
|
xkb_context_unref(context);
|
||||||
|
context_fail:
|
||||||
|
wl_client_post_no_memory(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtual_keyboard_key(struct wl_client *client,
|
||||||
|
struct wl_resource *resource, uint32_t time, uint32_t key,
|
||||||
|
uint32_t state) {
|
||||||
|
struct wlr_virtual_keyboard_v1 *keyboard =
|
||||||
|
virtual_keyboard_from_resource(resource);
|
||||||
|
struct wlr_event_keyboard_key event = {
|
||||||
|
.time_msec = time,
|
||||||
|
.keycode = key,
|
||||||
|
.update_state = false,
|
||||||
|
.state = state,
|
||||||
|
};
|
||||||
|
wlr_keyboard_notify_key(keyboard->input_device.keyboard, &event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtual_keyboard_modifiers(struct wl_client *client,
|
||||||
|
struct wl_resource *resource, uint32_t mods_depressed,
|
||||||
|
uint32_t mods_latched, uint32_t mods_locked, uint32_t group) {
|
||||||
|
struct wlr_virtual_keyboard_v1 *keyboard =
|
||||||
|
virtual_keyboard_from_resource(resource);
|
||||||
|
wlr_keyboard_notify_modifiers(keyboard->input_device.keyboard,
|
||||||
|
mods_depressed, mods_latched, mods_locked, group);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtual_keyboard_destroy_resource(struct wl_resource *resource) {
|
||||||
|
struct wlr_virtual_keyboard_v1 *keyboard =
|
||||||
|
virtual_keyboard_from_resource(resource);
|
||||||
|
wlr_signal_emit_safe(&keyboard->events.destroy, keyboard);
|
||||||
|
wl_list_remove(&keyboard->link);
|
||||||
|
wlr_keyboard_destroy(keyboard->input_device.keyboard);
|
||||||
|
free(keyboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtual_keyboard_destroy(struct wl_client *client,
|
||||||
|
struct wl_resource *resource) {
|
||||||
|
wl_resource_destroy(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct zwp_virtual_keyboard_v1_interface virtual_keyboard_impl = {
|
||||||
|
.keymap = virtual_keyboard_keymap,
|
||||||
|
.key = virtual_keyboard_key,
|
||||||
|
.modifiers = virtual_keyboard_modifiers,
|
||||||
|
.destroy = virtual_keyboard_destroy,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct zwp_virtual_keyboard_manager_v1_interface manager_impl;
|
||||||
|
|
||||||
|
static struct wlr_virtual_keyboard_manager_v1 *manager_from_resource(
|
||||||
|
struct wl_resource *resource) {
|
||||||
|
assert(wl_resource_instance_of(resource,
|
||||||
|
&zwp_virtual_keyboard_manager_v1_interface, &manager_impl));
|
||||||
|
return wl_resource_get_user_data(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtual_keyboard_manager_create_virtual_keyboard(
|
||||||
|
struct wl_client *client, struct wl_resource *resource,
|
||||||
|
struct wl_resource *seat, uint32_t id) {
|
||||||
|
struct wlr_virtual_keyboard_manager_v1 *manager =
|
||||||
|
manager_from_resource(resource);
|
||||||
|
|
||||||
|
struct wlr_virtual_keyboard_v1 *virtual_keyboard = calloc(1,
|
||||||
|
sizeof(struct wlr_virtual_keyboard_v1));
|
||||||
|
if (!virtual_keyboard) {
|
||||||
|
wl_client_post_no_memory(client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_keyboard* keyboard = calloc(1, sizeof(struct wlr_keyboard));
|
||||||
|
if (!keyboard) {
|
||||||
|
wlr_log(L_ERROR, "Cannot allocate wlr_keyboard");
|
||||||
|
free(virtual_keyboard);
|
||||||
|
wl_client_post_no_memory(client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wlr_keyboard_init(keyboard, &keyboard_impl);
|
||||||
|
|
||||||
|
struct wl_resource *keyboard_resource = wl_resource_create(client,
|
||||||
|
&zwp_virtual_keyboard_v1_interface, wl_resource_get_version(resource),
|
||||||
|
id);
|
||||||
|
if (!keyboard_resource) {
|
||||||
|
free(keyboard);
|
||||||
|
free(virtual_keyboard);
|
||||||
|
wl_client_post_no_memory(client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_resource_set_implementation(keyboard_resource, &virtual_keyboard_impl,
|
||||||
|
virtual_keyboard, virtual_keyboard_destroy_resource);
|
||||||
|
|
||||||
|
wlr_input_device_init(&virtual_keyboard->input_device,
|
||||||
|
WLR_INPUT_DEVICE_KEYBOARD, &input_device_impl, "virtual keyboard",
|
||||||
|
0x0, 0x0);
|
||||||
|
|
||||||
|
struct wlr_seat_client *seat_client = wlr_seat_client_from_resource(seat);
|
||||||
|
|
||||||
|
virtual_keyboard->input_device.keyboard = keyboard;
|
||||||
|
virtual_keyboard->resource = keyboard_resource;
|
||||||
|
virtual_keyboard->seat = seat_client->seat;
|
||||||
|
wl_signal_init(&virtual_keyboard->events.destroy);
|
||||||
|
|
||||||
|
wl_list_insert(&manager->virtual_keyboards, &virtual_keyboard->link);
|
||||||
|
|
||||||
|
wlr_signal_emit_safe(&manager->events.new_virtual_keyboard,
|
||||||
|
virtual_keyboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct zwp_virtual_keyboard_manager_v1_interface manager_impl = {
|
||||||
|
.create_virtual_keyboard = virtual_keyboard_manager_create_virtual_keyboard,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void handle_manager_unbind(struct wl_resource *resource) {
|
||||||
|
wl_list_remove(wl_resource_get_link(resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virtual_keyboard_manager_bind(struct wl_client *client, void *data,
|
||||||
|
uint32_t version, uint32_t id) {
|
||||||
|
struct wlr_virtual_keyboard_manager_v1 *manager = data;
|
||||||
|
|
||||||
|
struct wl_resource *resource = wl_resource_create(client,
|
||||||
|
&zwp_virtual_keyboard_manager_v1_interface, version, id);
|
||||||
|
|
||||||
|
if (!resource) {
|
||||||
|
wl_client_post_no_memory(client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_resource_set_implementation(resource, &manager_impl, manager,
|
||||||
|
handle_manager_unbind);
|
||||||
|
wl_list_insert(&manager->resources, wl_resource_get_link(resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_display_destroy(struct wl_listener *listener, void *data) {
|
||||||
|
struct wlr_virtual_keyboard_manager_v1 *manager =
|
||||||
|
wl_container_of(listener, manager, display_destroy);
|
||||||
|
wlr_virtual_keyboard_manager_v1_destroy(manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_virtual_keyboard_manager_v1*
|
||||||
|
wlr_virtual_keyboard_manager_v1_create(
|
||||||
|
struct wl_display *display) {
|
||||||
|
struct wlr_virtual_keyboard_manager_v1 *manager = calloc(1,
|
||||||
|
sizeof(struct wlr_virtual_keyboard_manager_v1));
|
||||||
|
if (!manager) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
manager->display_destroy.notify = handle_display_destroy;
|
||||||
|
wl_display_add_destroy_listener(display, &manager->display_destroy);
|
||||||
|
|
||||||
|
wl_list_init(&manager->resources);
|
||||||
|
wl_list_init(&manager->virtual_keyboards);
|
||||||
|
|
||||||
|
wl_signal_init(&manager->events.new_virtual_keyboard);
|
||||||
|
manager->global = wl_global_create(display,
|
||||||
|
&zwp_virtual_keyboard_manager_v1_interface, 1, manager,
|
||||||
|
virtual_keyboard_manager_bind);
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_virtual_keyboard_manager_v1_destroy(
|
||||||
|
struct wlr_virtual_keyboard_manager_v1 *manager) {
|
||||||
|
wl_global_destroy(manager->global);
|
||||||
|
free(manager);
|
||||||
|
}
|
Loading…
Reference in new issue