Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-3.0-or-later
2 : : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
3 : :
4 : : #define G_LOG_DOMAIN "valent-xdp-input"
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <linux/input-event-codes.h>
9 : :
10 : : #include <gio/gio.h>
11 : : #include <libportal/portal.h>
12 : : #include <valent.h>
13 : :
14 : : #ifdef HAVE_LIBEI
15 : : # include "valent-ei-input.h"
16 : : #endif /* HAVE_LIBEI */
17 : : #include "valent-xdp-utils.h"
18 : :
19 : : #include "valent-xdp-input.h"
20 : :
21 : : struct _ValentXdpInput
22 : : {
23 : : ValentInputAdapter parent_instance;
24 : :
25 : : ValentInputAdapter *delegate;
26 : : GSettings *settings;
27 : : XdpSession *session;
28 : : gboolean session_starting;
29 : : gboolean started;
30 : : };
31 : :
32 : 0 : G_DEFINE_FINAL_TYPE (ValentXdpInput, valent_xdp_input, VALENT_TYPE_INPUT_ADAPTER)
33 : :
34 : :
35 : : /*
36 : : * Portal Callbacks
37 : : */
38 : : static void
39 : 0 : on_session_closed (ValentXdpInput *self)
40 : : {
41 : 0 : g_clear_object (&self->delegate);
42 : 0 : g_clear_object (&self->session);
43 : 0 : self->started = FALSE;
44 : 0 : }
45 : :
46 : : static void
47 : 0 : on_session_started (XdpSession *session,
48 : : GAsyncResult *res,
49 : : gpointer user_data)
50 : : {
51 : 0 : ValentXdpInput *self = VALENT_XDP_INPUT (user_data);
52 : 0 : g_autofree char *session_token = NULL;
53 : 0 : g_autoptr (GError) error = NULL;
54 : :
55 : 0 : self->started = xdp_session_start_finish (session, res, &error);
56 : 0 : if (!self->started)
57 : : {
58 : 0 : g_warning ("%s(): %s", G_STRFUNC, error->message);
59 : 0 : g_clear_object (&self->session);
60 : : }
61 : :
62 : : #ifdef HAVE_LIBEI
63 : 0 : int ei_fd = xdp_session_connect_to_eis (self->session, &error);
64 : 0 : if (ei_fd > -1)
65 : : {
66 : 0 : self->delegate = g_initable_new (VALENT_TYPE_EI_INPUT, NULL, &error,
67 : : "parent", self,
68 : : "fd", ei_fd,
69 : : NULL);
70 : 0 : if (self->delegate == NULL)
71 : 0 : g_warning ("%s(): %s", G_STRFUNC, error->message);
72 : : }
73 : : else
74 : : {
75 : 0 : g_warning ("%s(): %s", G_STRFUNC, error->message);
76 : : }
77 : : #endif /* HAVE_LIBEI */
78 : :
79 : 0 : session_token = xdp_session_get_restore_token (session);
80 : 0 : g_settings_set_string (self->settings,
81 : : "session-token",
82 : : session_token ? session_token : "");
83 : 0 : self->session_starting = FALSE;
84 : 0 : }
85 : :
86 : : static void
87 : 0 : on_session_created (XdpPortal *portal,
88 : : GAsyncResult *result,
89 : : gpointer user_data)
90 : : {
91 : 0 : ValentXdpInput *self = VALENT_XDP_INPUT (user_data);
92 : 0 : g_autoptr (XdpParent) parent = NULL;
93 : 0 : g_autoptr (GError) error = NULL;
94 : :
95 : 0 : self->session = xdp_portal_create_remote_desktop_session_finish (portal,
96 : : result,
97 : : &error);
98 : :
99 : 0 : if (self->session == NULL)
100 : : {
101 : 0 : g_warning ("%s(): %s", G_STRFUNC, error->message);
102 : 0 : self->session_starting = FALSE;
103 : 0 : return;
104 : : }
105 : :
106 : 0 : g_signal_connect_object (self->session,
107 : : "closed",
108 : : G_CALLBACK (on_session_closed),
109 : : self,
110 : : G_CONNECT_SWAPPED);
111 : :
112 : 0 : parent = valent_xdp_get_parent ();
113 : 0 : xdp_session_start (self->session,
114 : : parent,
115 : : g_task_get_cancellable (G_TASK (result)),
116 : : (GAsyncReadyCallback)on_session_started,
117 : : self);
118 : : }
119 : :
120 : : static gboolean
121 : 0 : ensure_session (ValentXdpInput *self)
122 : : {
123 : 0 : g_autoptr (GCancellable) cancellable = NULL;
124 : 0 : g_autofree char *restore_token = NULL;
125 : :
126 : 0 : if (self->session_starting)
127 : : return FALSE;
128 : :
129 : 0 : if G_LIKELY (self->started)
130 : : return TRUE;
131 : :
132 : 0 : self->session_starting = TRUE;
133 : 0 : cancellable = valent_object_ref_cancellable (VALENT_OBJECT (self));
134 : 0 : restore_token = g_settings_get_string (self->settings, "session-token");
135 : 0 : if (!g_uuid_string_is_valid (restore_token))
136 : 0 : g_clear_pointer (&restore_token, g_free);
137 : :
138 : 0 : xdp_portal_create_remote_desktop_session_full (valent_xdp_get_default (),
139 : : (XDP_DEVICE_KEYBOARD |
140 : : XDP_DEVICE_POINTER),
141 : : XDP_OUTPUT_NONE,
142 : : XDP_REMOTE_DESKTOP_FLAG_NONE,
143 : : XDP_CURSOR_MODE_HIDDEN,
144 : : XDP_PERSIST_MODE_PERSISTENT,
145 : : restore_token,
146 : : cancellable,
147 : : (GAsyncReadyCallback)on_session_created,
148 : : self);
149 : :
150 : 0 : return FALSE;
151 : : }
152 : :
153 : :
154 : : /*
155 : : * ValentInputAdapter
156 : : */
157 : : static void
158 : 0 : valent_xdp_input_keyboard_keysym (ValentInputAdapter *adapter,
159 : : uint32_t keysym,
160 : : gboolean state)
161 : : {
162 : 0 : ValentXdpInput *self = VALENT_XDP_INPUT (adapter);
163 : :
164 : 0 : g_assert (VALENT_IS_INPUT_ADAPTER (adapter));
165 : 0 : g_assert (VALENT_IS_XDP_INPUT (self));
166 : :
167 : 0 : if G_UNLIKELY (!ensure_session (self))
168 : : return;
169 : :
170 : 0 : if (self->delegate != NULL)
171 : : {
172 : : #ifdef HAVE_LIBEI
173 : 0 : valent_input_adapter_keyboard_keysym (self->delegate, keysym, state);
174 : : #endif /* HAVE_LIBEI */
175 : : }
176 : : else
177 : : {
178 : : // TODO: XDP_KEY_PRESSED/XDP_KEY_RELEASED
179 : 0 : xdp_session_keyboard_key (self->session, TRUE, keysym, state);
180 : : }
181 : : }
182 : :
183 : : static unsigned int
184 : 0 : translate_to_evdev_button (unsigned int button)
185 : : {
186 : 0 : switch (button)
187 : : {
188 : : case VALENT_POINTER_PRIMARY:
189 : : return BTN_LEFT;
190 : :
191 : : case VALENT_POINTER_MIDDLE:
192 : : return BTN_MIDDLE;
193 : :
194 : : case VALENT_POINTER_SECONDARY:
195 : : return BTN_RIGHT;
196 : :
197 : 0 : default:
198 : : /* Any other buttons go after the legacy scroll buttons (4-7). */
199 : 0 : return button + (BTN_LEFT - 1) - 4;
200 : : }
201 : : }
202 : :
203 : : static void
204 : 0 : valent_xdp_input_pointer_axis (ValentInputAdapter *adapter,
205 : : double dx,
206 : : double dy)
207 : : {
208 : 0 : ValentXdpInput *self = VALENT_XDP_INPUT (adapter);
209 : :
210 : 0 : g_assert (VALENT_IS_INPUT_ADAPTER (adapter));
211 : 0 : g_assert (VALENT_IS_XDP_INPUT (self));
212 : 0 : g_assert (!G_APPROX_VALUE (dx, 0.0, 0.01) || !G_APPROX_VALUE (dy, 0.0, 0.01));
213 : :
214 : 0 : if G_UNLIKELY (!ensure_session (self))
215 : : return;
216 : :
217 : 0 : if (self->delegate != NULL)
218 : : {
219 : : #ifdef HAVE_LIBEI
220 : 0 : valent_input_adapter_pointer_axis (self->delegate, dx, dy);
221 : : #endif /* HAVE_LIBEI */
222 : : }
223 : : else
224 : : {
225 : 0 : xdp_session_pointer_axis (self->session, FALSE, dx, dy);
226 : 0 : xdp_session_pointer_axis (self->session, TRUE, 0.0, 0.0);
227 : : }
228 : : }
229 : :
230 : : static void
231 : 0 : valent_xdp_input_pointer_button (ValentInputAdapter *adapter,
232 : : unsigned int button,
233 : : gboolean pressed)
234 : : {
235 : 0 : ValentXdpInput *self = VALENT_XDP_INPUT (adapter);
236 : :
237 : 0 : g_assert (VALENT_IS_INPUT_ADAPTER (adapter));
238 : 0 : g_assert (VALENT_IS_XDP_INPUT (self));
239 : :
240 : 0 : if G_UNLIKELY (!ensure_session (self))
241 : : return;
242 : :
243 : 0 : if (self->delegate != NULL)
244 : : {
245 : : #ifdef HAVE_LIBEI
246 : 0 : valent_input_adapter_pointer_button (self->delegate, button, pressed);
247 : : #endif /* HAVE_LIBEI */
248 : : }
249 : : else
250 : : {
251 : 0 : button = translate_to_evdev_button (button);
252 : 0 : xdp_session_pointer_button (self->session, button, pressed);
253 : : }
254 : : }
255 : :
256 : : static void
257 : 0 : valent_xdp_input_pointer_motion (ValentInputAdapter *adapter,
258 : : double dx,
259 : : double dy)
260 : : {
261 : 0 : ValentXdpInput *self = VALENT_XDP_INPUT (adapter);
262 : :
263 : 0 : g_assert (VALENT_IS_INPUT_ADAPTER (adapter));
264 : 0 : g_assert (VALENT_IS_XDP_INPUT (self));
265 : :
266 : 0 : if G_UNLIKELY (!ensure_session (self))
267 : : return;
268 : :
269 : 0 : if (self->delegate != NULL)
270 : : {
271 : : #ifdef HAVE_LIBEI
272 : 0 : valent_input_adapter_pointer_motion (self->delegate, dx, dy);
273 : : #endif /* HAVE_LIBEI */
274 : : }
275 : : else
276 : : {
277 : 0 : xdp_session_pointer_motion (self->session, dx, dy);
278 : : }
279 : : }
280 : :
281 : :
282 : : /*
283 : : * ValentObject
284 : : */
285 : : static void
286 : 0 : valent_xdp_input_destroy (ValentObject *object)
287 : : {
288 : 0 : ValentXdpInput *self = VALENT_XDP_INPUT (object);
289 : :
290 : 0 : if (self->session != NULL)
291 : 0 : xdp_session_close (self->session);
292 : :
293 : 0 : if (self->delegate != NULL)
294 : 0 : g_clear_object (&self->delegate);
295 : :
296 : 0 : VALENT_OBJECT_CLASS (valent_xdp_input_parent_class)->destroy (object);
297 : 0 : }
298 : :
299 : : /*
300 : : * GObject
301 : : */
302 : : static void
303 : 0 : valent_xdp_input_finalize (GObject *object)
304 : : {
305 : 0 : ValentXdpInput *self = VALENT_XDP_INPUT (object);
306 : :
307 : 0 : g_clear_object (&self->settings);
308 : 0 : g_clear_object (&self->session);
309 : :
310 : 0 : G_OBJECT_CLASS (valent_xdp_input_parent_class)->finalize (object);
311 : 0 : }
312 : :
313 : : static void
314 : 0 : valent_xdp_input_class_init (ValentXdpInputClass *klass)
315 : : {
316 : 0 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
317 : 0 : ValentObjectClass *vobject_class = VALENT_OBJECT_CLASS (klass);
318 : 0 : ValentInputAdapterClass *adapter_class = VALENT_INPUT_ADAPTER_CLASS (klass);
319 : :
320 : 0 : object_class->finalize = valent_xdp_input_finalize;
321 : :
322 : 0 : vobject_class->destroy = valent_xdp_input_destroy;
323 : :
324 : 0 : adapter_class->keyboard_keysym = valent_xdp_input_keyboard_keysym;
325 : 0 : adapter_class->pointer_axis = valent_xdp_input_pointer_axis;
326 : 0 : adapter_class->pointer_button = valent_xdp_input_pointer_button;
327 : 0 : adapter_class->pointer_motion = valent_xdp_input_pointer_motion;
328 : : }
329 : :
330 : : static void
331 : 0 : valent_xdp_input_init (ValentXdpInput *self)
332 : : {
333 : 0 : self->settings = g_settings_new ("ca.andyholmes.Valent.Plugin.xdp");
334 : 0 : }
335 : :
|