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