mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-10-29 05:40:12 -04:00 
			
		
		
		
	virtual-keyboard: add support for the virtual-keyboard-v1 protocol
This commit is contained in:
		
							parent
							
								
									a94c56a828
								
							
						
					
					
						commit
						5334ee8bfd
					
				
					 10 changed files with 427 additions and 0 deletions
				
			
		|  | @ -14,6 +14,7 @@ | ||||||
| #include <wlr/types/wlr_output.h> | #include <wlr/types/wlr_output.h> | ||||||
| #include <wlr/types/wlr_primary_selection.h> | #include <wlr/types/wlr_primary_selection.h> | ||||||
| #include <wlr/types/wlr_screenshooter.h> | #include <wlr/types/wlr_screenshooter.h> | ||||||
|  | #include <wlr/types/wlr_virtual_keyboard_v1.h> | ||||||
| #include <wlr/types/wlr_wl_shell.h> | #include <wlr/types/wlr_wl_shell.h> | ||||||
| #include <wlr/types/wlr_xcursor_manager.h> | #include <wlr/types/wlr_xcursor_manager.h> | ||||||
| #include <wlr/types/wlr_xdg_shell_v6.h> | #include <wlr/types/wlr_xdg_shell_v6.h> | ||||||
|  | @ -51,6 +52,7 @@ struct roots_desktop { | ||||||
| 	struct wlr_input_inhibit_manager *input_inhibit; | 	struct wlr_input_inhibit_manager *input_inhibit; | ||||||
| 	struct wlr_linux_dmabuf *linux_dmabuf; | 	struct wlr_linux_dmabuf *linux_dmabuf; | ||||||
| 	struct wlr_layer_shell *layer_shell; | 	struct wlr_layer_shell *layer_shell; | ||||||
|  | 	struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard; | ||||||
| 
 | 
 | ||||||
| 	struct wl_listener new_output; | 	struct wl_listener new_output; | ||||||
| 	struct wl_listener layout_change; | 	struct wl_listener layout_change; | ||||||
|  | @ -61,6 +63,7 @@ struct roots_desktop { | ||||||
| 	struct wl_listener decoration_new; | 	struct wl_listener decoration_new; | ||||||
| 	struct wl_listener input_inhibit_activate; | 	struct wl_listener input_inhibit_activate; | ||||||
| 	struct wl_listener input_inhibit_deactivate; | 	struct wl_listener input_inhibit_deactivate; | ||||||
|  | 	struct wl_listener virtual_keyboard_new; | ||||||
| 
 | 
 | ||||||
| #ifdef WLR_HAS_XWAYLAND | #ifdef WLR_HAS_XWAYLAND | ||||||
| 	struct wlr_xwayland *xwayland; | 	struct wlr_xwayland *xwayland; | ||||||
|  |  | ||||||
							
								
								
									
										7
									
								
								include/rootston/virtual_keyboard.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								include/rootston/virtual_keyboard.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -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 | ||||||
							
								
								
									
										37
									
								
								include/wlr/types/wlr_virtual_keyboard_v1.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								include/wlr/types/wlr_virtual_keyboard_v1.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -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 | ||||||
|  | @ -38,6 +38,7 @@ protocols = [ | ||||||
| 	'idle.xml', | 	'idle.xml', | ||||||
| 	'screenshooter.xml', | 	'screenshooter.xml', | ||||||
| 	'server-decoration.xml', | 	'server-decoration.xml', | ||||||
|  | 	'virtual-keyboard-unstable-v1.xml', | ||||||
| 	'wlr-layer-shell-unstable-v1.xml', | 	'wlr-layer-shell-unstable-v1.xml', | ||||||
| 	'wlr-input-inhibitor-unstable-v1.xml', | 	'wlr-input-inhibitor-unstable-v1.xml', | ||||||
| ] | ] | ||||||
|  |  | ||||||
							
								
								
									
										113
									
								
								protocol/virtual-keyboard-unstable-v1.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								protocol/virtual-keyboard-unstable-v1.xml
									
										
									
									
									
										Normal file
									
								
							|  | @ -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> | ||||||
|  | @ -26,6 +26,7 @@ | ||||||
| #include "rootston/seat.h" | #include "rootston/seat.h" | ||||||
| #include "rootston/server.h" | #include "rootston/server.h" | ||||||
| #include "rootston/view.h" | #include "rootston/view.h" | ||||||
|  | #include "rootston/virtual_keyboard.h" | ||||||
| #include "rootston/xcursor.h" | #include "rootston/xcursor.h" | ||||||
| #include "wlr-layer-shell-unstable-v1-protocol.h" | #include "wlr-layer-shell-unstable-v1-protocol.h" | ||||||
| 
 | 
 | ||||||
|  | @ -865,6 +866,12 @@ struct roots_desktop *desktop_create(struct roots_server *server, | ||||||
| 
 | 
 | ||||||
| 	desktop->linux_dmabuf = wlr_linux_dmabuf_create(server->wl_display, | 	desktop->linux_dmabuf = wlr_linux_dmabuf_create(server->wl_display, | ||||||
| 		server->renderer); | 		server->renderer); | ||||||
|  | 
 | ||||||
|  | 	desktop->virtual_keyboard = wlr_virtual_keyboard_manager_v1_create( | ||||||
|  | 		server->wl_display); | ||||||
|  | 	wl_signal_add(&desktop->virtual_keyboard->events.new_virtual_keyboard, | ||||||
|  | 		&desktop->virtual_keyboard_new); | ||||||
|  | 	desktop->virtual_keyboard_new.notify = handle_virtual_keyboard; | ||||||
| 	return desktop; | 	return desktop; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ sources = [ | ||||||
| 	'main.c', | 	'main.c', | ||||||
| 	'output.c', | 	'output.c', | ||||||
| 	'seat.c', | 	'seat.c', | ||||||
|  | 	'virtual_keyboard.c', | ||||||
| 	'wl_shell.c', | 	'wl_shell.c', | ||||||
| 	'xdg_shell_v6.c', | 	'xdg_shell_v6.c', | ||||||
| 	'xdg_shell.c', | 	'xdg_shell.c', | ||||||
|  |  | ||||||
							
								
								
									
										21
									
								
								rootston/virtual_keyboard.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								rootston/virtual_keyboard.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -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); | ||||||
|  | } | ||||||
|  | @ -44,6 +44,7 @@ lib_wlr_types = static_library( | ||||||
| 		'wlr_tablet_pad.c', | 		'wlr_tablet_pad.c', | ||||||
| 		'wlr_tablet_tool.c', | 		'wlr_tablet_tool.c', | ||||||
| 		'wlr_touch.c', | 		'wlr_touch.c', | ||||||
|  | 		'wlr_virtual_keyboard_v1.c', | ||||||
| 		'wlr_wl_shell.c', | 		'wlr_wl_shell.c', | ||||||
| 		'wlr_xcursor_manager.c', | 		'wlr_xcursor_manager.c', | ||||||
| 		'wlr_xdg_output.c', | 		'wlr_xdg_output.c', | ||||||
|  |  | ||||||
							
								
								
									
										236
									
								
								types/wlr_virtual_keyboard_v1.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								types/wlr_virtual_keyboard_v1.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dorota Czaplejewicz
						Dorota Czaplejewicz