mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-02-05 04:06:11 -05:00
Merge branch 'ext-virtual-keyboard-v1' into 'master'
Implement ext-virtual-keyboard-v1 See merge request wlroots/wlroots!4682
This commit is contained in:
commit
23046763ba
7 changed files with 523 additions and 1 deletions
45
include/wlr/types/wlr_ext_virtual_keyboard_v1.h
Normal file
45
include/wlr/types/wlr_ext_virtual_keyboard_v1.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* This an unstable interface of wlroots. No guarantees are made regarding the
|
||||
* future consistency of this API.
|
||||
*/
|
||||
#ifndef WLR_USE_UNSTABLE
|
||||
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
|
||||
#endif
|
||||
|
||||
#ifndef WLR_TYPES_EXT_VIRTUAL_KEYBOARD_V1_H
|
||||
#define WLR_TYPES_EXT_VIRTUAL_KEYBOARD_V1_H
|
||||
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/types/wlr_keyboard.h>
|
||||
|
||||
struct wlr_ext_virtual_keyboard_manager_v1 {
|
||||
struct wl_global *global;
|
||||
struct wl_list keyboards; // wlr_ext_virtual_keyboard_v1.link
|
||||
|
||||
struct {
|
||||
struct wl_signal new_keyboard; // struct wlr_ext_virtual_keyboard_v1
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
// private state
|
||||
struct wl_listener display_destroy;
|
||||
|
||||
};
|
||||
|
||||
struct wlr_ext_virtual_keyboard_v1 {
|
||||
struct wlr_keyboard keyboard;
|
||||
struct wl_resource *resource;
|
||||
struct wlr_ext_virtual_keyboard_manager_v1 *manager;
|
||||
struct wlr_seat *seat;
|
||||
bool has_keymap;
|
||||
|
||||
struct wl_list link; // wlr_ext_virtual_keyboard_manager_v1.ext_virtual_keyboards
|
||||
};
|
||||
|
||||
struct wlr_ext_virtual_keyboard_manager_v1* wlr_ext_virtual_keyboard_manager_v1_create(
|
||||
struct wl_display *display, uint32_t version);
|
||||
|
||||
struct wlr_ext_virtual_keyboard_v1 *wlr_ext_virtual_keyboard_v1_try_from_wlr_input_device(
|
||||
struct wlr_input_device *wlr_dev);
|
||||
|
||||
#endif
|
||||
186
protocol/ext-virtual-keyboard-v1.xml
Normal file
186
protocol/ext-virtual-keyboard-v1.xml
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="ext_virtual_keyboard_v1">
|
||||
<copyright>
|
||||
Copyright © 2008-2011 Kristian Høgsberg
|
||||
Copyright © 2010-2013 Intel Corporation
|
||||
Copyright © 2012-2013 Collabora, Ltd.
|
||||
Copyright © 2018 Purism SPC
|
||||
Copyright © 2023 Simon Ser
|
||||
|
||||
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>
|
||||
|
||||
<description summary="virtual keyboard protocol">
|
||||
This protocol allows privileged clients to create a virtual keyboard device
|
||||
and emit synthetic input events. It is intended to be used by remote
|
||||
desktop applications and on-screen keyboards.
|
||||
|
||||
The compositor may choose to restrict this protocol to a special client
|
||||
launched by the compositor itself or expose it to all privileged clients,
|
||||
this is compositor policy.
|
||||
|
||||
The key words "must", "must not", "required", "shall", "shall not", "should",
|
||||
"should not", "recommended", "may", and "optional" in this document are to
|
||||
be interpreted as described in IETF RFC 2119.
|
||||
|
||||
Warning! The protocol described in this file is currently in the testing
|
||||
phase. Backward compatible changes may be added together with the
|
||||
corresponding interface version bump. Backward incompatible changes can
|
||||
only be done by creating a new major version of the extension.
|
||||
</description>
|
||||
|
||||
<interface name="ext_virtual_keyboard_manager_v1" version="1">
|
||||
<description summary="virtual keyboard manager">
|
||||
A virtual keyboard manager allows an application to create virtual
|
||||
keyboards.
|
||||
</description>
|
||||
|
||||
<request name="create_virtual_keyboard">
|
||||
<description summary="create a new virtual keyboard">
|
||||
Create a new virtual keyboard.
|
||||
|
||||
If the seat is null, the compositor will pick one. If the seat is
|
||||
non-null, the compositor must attach the virtual keyboard to that seat
|
||||
or immediately send the finished event on the newly created virtual
|
||||
keyboard object.
|
||||
</description>
|
||||
<arg name="seat" type="object" interface="wl_seat" allow-null="true"/>
|
||||
<arg name="id" type="new_id" interface="ext_virtual_keyboard_v1"
|
||||
summary="the newly created virtual keyboard"/>
|
||||
</request>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the virtual keyboard manager">
|
||||
Destroy the virtual keyboard manager.
|
||||
|
||||
Existing ext_virtual_keyboard_v1 objects remain valid.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="ext_virtual_keyboard_v1" version="1">
|
||||
<description summary="virtual keyboard">
|
||||
The virtual keyboard interface allows a client to send synthetic keyboard
|
||||
input events.
|
||||
|
||||
The virtual keyboard has exclusive control over its modifier state. The
|
||||
compositor must ensure that the correct modifier state is applied before
|
||||
passing on events from the virtual keyboard to wl_keyboard.
|
||||
</description>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="invalid_keymap" value="1" summary="keymap format invalid"/>
|
||||
<entry name="invalid_key_state" value="2" summary="key state invalid"/>
|
||||
<entry name="missing_keymap" value="3" summary="missing keymap"/>
|
||||
</enum>
|
||||
|
||||
<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.
|
||||
|
||||
The FD must be mapped with MAP_PRIVATE by the recipient, as MAP_SHARED
|
||||
may fail.
|
||||
|
||||
The underlying keymap data must remain available as long as the object
|
||||
hasn't been destroyed.
|
||||
|
||||
If the keymap format is invalid, the invalid_keymap protocol error is
|
||||
raised. The only valid format is xkb_v1.
|
||||
|
||||
The compositor must take care to notify clients of the correct keymap
|
||||
before it sends other wl_keyboard events, i.e. set the keymap
|
||||
corresponding to the event source.
|
||||
</description>
|
||||
<arg name="format" type="uint" enum="wl_keyboard.keymap_format"
|
||||
summary="keymap format (must be xkb_v1)"/>
|
||||
<arg name="fd" type="fd" summary="keymap file descriptor"/>
|
||||
<arg name="size" type="uint" summary="keymap size, in bytes"/>
|
||||
</request>
|
||||
|
||||
<request name="key">
|
||||
<description summary="key event">
|
||||
Notify that a key was pressed or released.
|
||||
|
||||
The time argument is a timestamp with millisecond granularity in the
|
||||
CLOCK_MONOTONIC domain.
|
||||
|
||||
If the state is invalid, the invalid_key_state protocol error is raised.
|
||||
If no keymap has been set, the missing_keymap protocol error is raised.
|
||||
|
||||
Valid values for state are released, pressed and repeated from
|
||||
wl_keyboard.key_state. All other values are invalid.
|
||||
</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" enum="wl_keyboard.key_state"
|
||||
summary="physical state of the key"/>
|
||||
</request>
|
||||
|
||||
<request name="modifiers">
|
||||
<description summary="modifier and group state">
|
||||
Notify that the modifier and/or group state has changed.
|
||||
|
||||
If no keymap has been set, the missing_keymap protocol error is raised.
|
||||
</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="repeat_info">
|
||||
<description summary="set repeat info">
|
||||
Sets the repeat info for associated wl_keyboard objects.
|
||||
|
||||
This request should be passed by the compositor to clients via the
|
||||
wl_keyboard.repeat_info event.
|
||||
</description>
|
||||
<arg name="rate" type="int"
|
||||
summary="the rate of repeating keys in characters per second"/>
|
||||
<arg name="delay" type="int"
|
||||
summary="delay in milliseconds since key down until repeating starts"/>
|
||||
</request>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the virtual keyboard">
|
||||
Destroy the virtual keyboard.
|
||||
|
||||
The compositor should release any pressed keys.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<event name="finished">
|
||||
<description summary="the virtual keyboard should be destroyed">
|
||||
The compositor has decided that the virtual keyboard should be
|
||||
destroyed as it will no longer be used by the compositor. Exactly when
|
||||
this event is sent is compositor policy, but it must never be sent more
|
||||
than once for a given virtual keyboard object.
|
||||
|
||||
This might be sent because the user has decided to stop the virtual
|
||||
input device, or the compositor has decided to deny the client request
|
||||
for some other reason.
|
||||
|
||||
Upon receiving this event, the client should send a destroy request.
|
||||
</description>
|
||||
</event>
|
||||
</interface>
|
||||
</protocol>
|
||||
|
|
@ -77,6 +77,7 @@ protocols = {
|
|||
'wlr-output-power-management-unstable-v1': 'wlr-output-power-management-unstable-v1.xml',
|
||||
'wlr-screencopy-unstable-v1': 'wlr-screencopy-unstable-v1.xml',
|
||||
'wlr-virtual-pointer-unstable-v1': 'wlr-virtual-pointer-unstable-v1.xml',
|
||||
'ext-virtual-keyboard-v1': 'ext-virtual-keyboard-v1.xml',
|
||||
}
|
||||
|
||||
protocols_code = {}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ wlr_files += files(
|
|||
'wlr_ext_workspace_v1.c',
|
||||
'wlr_fixes.c',
|
||||
'wlr_foreign_toplevel_management_v1.c',
|
||||
'wlr_ext_virtual_keyboard_v1.c',
|
||||
'wlr_fractional_scale_v1.c',
|
||||
'wlr_gamma_control_v1.c',
|
||||
'wlr_idle_inhibit_v1.c',
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
#include "types/wlr_seat.h"
|
||||
#include "util/global.h"
|
||||
|
||||
#define SEAT_VERSION 9
|
||||
#define SEAT_VERSION 10
|
||||
|
||||
static void seat_handle_get_pointer(struct wl_client *client,
|
||||
struct wl_resource *seat_resource, uint32_t id) {
|
||||
|
|
|
|||
|
|
@ -78,6 +78,12 @@ void wlr_seat_keyboard_send_key(struct wlr_seat *wlr_seat, uint32_t time,
|
|||
continue;
|
||||
}
|
||||
|
||||
int version = wl_resource_get_version(resource);
|
||||
if (state == WL_KEYBOARD_KEY_STATE_REPEATED &&
|
||||
version < WL_KEYBOARD_KEY_STATE_REPEATED_SINCE_VERSION) {
|
||||
continue;
|
||||
}
|
||||
|
||||
wl_keyboard_send_key(resource, serial, time, key, state);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
283
types/wlr_ext_virtual_keyboard_v1.c
Normal file
283
types/wlr_ext_virtual_keyboard_v1.c
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <wlr/interfaces/wlr_keyboard.h>
|
||||
#include <wlr/types/wlr_seat.h>
|
||||
#include <wlr/types/wlr_ext_virtual_keyboard_v1.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include "ext-virtual-keyboard-v1-protocol.h"
|
||||
|
||||
static const struct wlr_keyboard_impl keyboard_impl = {
|
||||
.name = "ext-virtual-keyboard-v1",
|
||||
};
|
||||
|
||||
static const struct ext_virtual_keyboard_v1_interface ext_virtual_keyboard_impl;
|
||||
|
||||
static struct wlr_ext_virtual_keyboard_v1 *ext_virtual_keyboard_from_resource(
|
||||
struct wl_resource *resource) {
|
||||
assert(wl_resource_instance_of(resource,
|
||||
&ext_virtual_keyboard_v1_interface, &ext_virtual_keyboard_impl));
|
||||
return wl_resource_get_user_data(resource);
|
||||
}
|
||||
|
||||
struct wlr_ext_virtual_keyboard_v1 *wlr_ext_virtual_keyboard_v1_try_from_wlr_input_device(
|
||||
struct wlr_input_device *wlr_dev) {
|
||||
if (wlr_dev->type != WLR_INPUT_DEVICE_KEYBOARD) {
|
||||
return NULL;
|
||||
}
|
||||
struct wlr_keyboard *wlr_keyboard = wlr_keyboard_from_input_device(wlr_dev);
|
||||
if (wlr_keyboard->impl != &keyboard_impl) {
|
||||
return NULL;
|
||||
}
|
||||
return wl_container_of(wlr_keyboard,
|
||||
(struct wlr_ext_virtual_keyboard_v1 *)NULL, keyboard);
|
||||
}
|
||||
|
||||
static void ext_virtual_keyboard_keymap(struct wl_client *client,
|
||||
struct wl_resource *resource, uint32_t format, int32_t fd,
|
||||
uint32_t size) {
|
||||
struct wlr_ext_virtual_keyboard_v1 *keyboard =
|
||||
ext_virtual_keyboard_from_resource(resource);
|
||||
if (keyboard == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
|
||||
wl_resource_post_error(resource,
|
||||
EXT_VIRTUAL_KEYBOARD_V1_ERROR_INVALID_KEYMAP,
|
||||
"Unsupported keymap format");
|
||||
return;
|
||||
}
|
||||
|
||||
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
if (!context) {
|
||||
wl_client_post_no_memory(client);
|
||||
goto context_fail;
|
||||
}
|
||||
void *data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (data == MAP_FAILED) {
|
||||
wl_resource_post_error(resource,
|
||||
EXT_VIRTUAL_KEYBOARD_V1_ERROR_INVALID_KEYMAP,
|
||||
"Failed to map file descriptor to memory");
|
||||
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) {
|
||||
wl_resource_post_error(resource,
|
||||
EXT_VIRTUAL_KEYBOARD_V1_ERROR_INVALID_KEYMAP,
|
||||
"Failed to parse keymap");
|
||||
goto keymap_fail;
|
||||
}
|
||||
wlr_keyboard_set_keymap(&keyboard->keyboard, keymap);
|
||||
|
||||
bool had_keymap = keyboard->has_keymap;
|
||||
keyboard->has_keymap = true;
|
||||
|
||||
if (!had_keymap) {
|
||||
wl_signal_emit_mutable(&keyboard->manager->events.new_keyboard,
|
||||
keyboard);
|
||||
}
|
||||
|
||||
xkb_keymap_unref(keymap);
|
||||
keymap_fail:
|
||||
fd_fail:
|
||||
xkb_context_unref(context);
|
||||
context_fail:
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static bool is_key_state_valid(enum wl_keyboard_key_state state) {
|
||||
switch (state) {
|
||||
case WL_KEYBOARD_KEY_STATE_PRESSED:
|
||||
case WL_KEYBOARD_KEY_STATE_RELEASED:
|
||||
case WL_KEYBOARD_KEY_STATE_REPEATED:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ext_virtual_keyboard_key(struct wl_client *client,
|
||||
struct wl_resource *resource, uint32_t time, uint32_t key,
|
||||
uint32_t state) {
|
||||
struct wlr_ext_virtual_keyboard_v1 *keyboard =
|
||||
ext_virtual_keyboard_from_resource(resource);
|
||||
if (keyboard == NULL) {
|
||||
return;
|
||||
}
|
||||
if (!is_key_state_valid(state)) {
|
||||
wl_resource_post_error(resource,
|
||||
EXT_VIRTUAL_KEYBOARD_V1_ERROR_INVALID_KEY_STATE,
|
||||
"Invalid key state");
|
||||
return;
|
||||
}
|
||||
if (!keyboard->has_keymap) {
|
||||
wl_resource_post_error(resource,
|
||||
EXT_VIRTUAL_KEYBOARD_V1_ERROR_MISSING_KEYMAP,
|
||||
"Cannot send a keypress before defining a keymap");
|
||||
return;
|
||||
}
|
||||
struct wlr_keyboard_key_event event = {
|
||||
.time_msec = time,
|
||||
.keycode = key,
|
||||
.update_state = false,
|
||||
.state = state,
|
||||
};
|
||||
wlr_keyboard_notify_key(&keyboard->keyboard, &event);
|
||||
}
|
||||
|
||||
static void ext_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_ext_virtual_keyboard_v1 *keyboard =
|
||||
ext_virtual_keyboard_from_resource(resource);
|
||||
if (keyboard == NULL) {
|
||||
return;
|
||||
}
|
||||
if (!keyboard->has_keymap) {
|
||||
wl_resource_post_error(resource,
|
||||
EXT_VIRTUAL_KEYBOARD_V1_ERROR_MISSING_KEYMAP,
|
||||
"Cannot send a modifier state before defining a keymap");
|
||||
return;
|
||||
}
|
||||
wlr_keyboard_notify_modifiers(&keyboard->keyboard,
|
||||
mods_depressed, mods_latched, mods_locked, group);
|
||||
}
|
||||
|
||||
static void ext_virtual_keyboard_repeat_info(struct wl_client *client,
|
||||
struct wl_resource *resource, int32_t rate, int32_t delay) {
|
||||
struct wlr_ext_virtual_keyboard_v1 *keyboard =
|
||||
ext_virtual_keyboard_from_resource(resource);
|
||||
if (keyboard == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_keyboard_set_repeat_info(&keyboard->keyboard, rate, delay);
|
||||
}
|
||||
|
||||
static void ext_virtual_keyboard_destroy_resource(struct wl_resource *resource) {
|
||||
struct wlr_ext_virtual_keyboard_v1 *keyboard =
|
||||
ext_virtual_keyboard_from_resource(resource);
|
||||
if (keyboard == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_keyboard_finish(&keyboard->keyboard);
|
||||
wl_list_remove(&keyboard->link);
|
||||
free(keyboard);
|
||||
}
|
||||
|
||||
static void ext_virtual_keyboard_destroy(struct wl_client *client,
|
||||
struct wl_resource *resource) {
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static const struct ext_virtual_keyboard_v1_interface ext_virtual_keyboard_impl = {
|
||||
.keymap = ext_virtual_keyboard_keymap,
|
||||
.key = ext_virtual_keyboard_key,
|
||||
.modifiers = ext_virtual_keyboard_modifiers,
|
||||
.repeat_info = ext_virtual_keyboard_repeat_info,
|
||||
.destroy = ext_virtual_keyboard_destroy,
|
||||
};
|
||||
|
||||
static const struct ext_virtual_keyboard_manager_v1_interface manager_impl;
|
||||
|
||||
static struct wlr_ext_virtual_keyboard_manager_v1 *manager_from_resource(
|
||||
struct wl_resource *resource) {
|
||||
assert(wl_resource_instance_of(resource,
|
||||
&ext_virtual_keyboard_manager_v1_interface, &manager_impl));
|
||||
return wl_resource_get_user_data(resource);
|
||||
}
|
||||
|
||||
static void ext_virtual_keyboard_manager_create_ext_virtual_keyboard(
|
||||
struct wl_client *client, struct wl_resource *resource,
|
||||
struct wl_resource *seat, uint32_t id) {
|
||||
struct wlr_ext_virtual_keyboard_manager_v1 *manager =
|
||||
manager_from_resource(resource);
|
||||
struct wlr_seat_client *seat_client = wlr_seat_client_from_resource(seat);
|
||||
|
||||
struct wl_resource *keyboard_resource = wl_resource_create(client,
|
||||
&ext_virtual_keyboard_v1_interface, wl_resource_get_version(resource),
|
||||
id);
|
||||
if (!keyboard_resource) {
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
}
|
||||
wl_resource_set_implementation(keyboard_resource, &ext_virtual_keyboard_impl,
|
||||
NULL, ext_virtual_keyboard_destroy_resource);
|
||||
if (seat_client == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_ext_virtual_keyboard_v1 *ext_virtual_keyboard = calloc(1, sizeof(*ext_virtual_keyboard));
|
||||
if (!ext_virtual_keyboard) {
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_keyboard_init(&ext_virtual_keyboard->keyboard, &keyboard_impl,
|
||||
"wlr_ext_virtual_keyboard_v1");
|
||||
|
||||
ext_virtual_keyboard->resource = keyboard_resource;
|
||||
ext_virtual_keyboard->manager = manager;
|
||||
ext_virtual_keyboard->seat = seat_client->seat;
|
||||
wl_resource_set_user_data(keyboard_resource, ext_virtual_keyboard);
|
||||
|
||||
wl_list_insert(&manager->keyboards, &ext_virtual_keyboard->link);
|
||||
}
|
||||
|
||||
static const struct ext_virtual_keyboard_manager_v1_interface manager_impl = {
|
||||
.create_virtual_keyboard = ext_virtual_keyboard_manager_create_ext_virtual_keyboard,
|
||||
};
|
||||
|
||||
static void ext_virtual_keyboard_manager_bind(struct wl_client *client, void *data,
|
||||
uint32_t version, uint32_t id) {
|
||||
struct wlr_ext_virtual_keyboard_manager_v1 *manager = data;
|
||||
|
||||
struct wl_resource *resource = wl_resource_create(client,
|
||||
&ext_virtual_keyboard_manager_v1_interface, version, id);
|
||||
if (!resource) {
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
}
|
||||
|
||||
wl_resource_set_implementation(resource, &manager_impl, manager, NULL);
|
||||
}
|
||||
|
||||
static void handle_display_destroy(struct wl_listener *listener, void *data) {
|
||||
struct wlr_ext_virtual_keyboard_manager_v1 *manager =
|
||||
wl_container_of(listener, manager, display_destroy);
|
||||
wl_signal_emit_mutable(&manager->events.destroy, manager);
|
||||
wl_list_remove(&manager->display_destroy.link);
|
||||
wl_global_destroy(manager->global);
|
||||
free(manager);
|
||||
}
|
||||
|
||||
struct wlr_ext_virtual_keyboard_manager_v1 *wlr_ext_virtual_keyboard_manager_v1_create(
|
||||
struct wl_display *display, uint32_t version) {
|
||||
struct wlr_ext_virtual_keyboard_manager_v1 *manager = calloc(1, sizeof(*manager));
|
||||
if (!manager) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
manager->global = wl_global_create(display,
|
||||
&ext_virtual_keyboard_manager_v1_interface, version, manager,
|
||||
ext_virtual_keyboard_manager_bind);
|
||||
if (!manager->global) {
|
||||
free(manager);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
manager->display_destroy.notify = handle_display_destroy;
|
||||
wl_display_add_destroy_listener(display, &manager->display_destroy);
|
||||
|
||||
wl_list_init(&manager->keyboards);
|
||||
|
||||
wl_signal_init(&manager->events.new_keyboard);
|
||||
wl_signal_init(&manager->events.destroy);
|
||||
|
||||
return manager;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue