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