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