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-presenter-plugin"
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <glib/gi18n.h>
9 : : #include <gio/gio.h>
10 : : #include <gtk/gtk.h>
11 : : #include <json-glib/json-glib.h>
12 : : #include <valent.h>
13 : :
14 : : #include "valent-presenter-plugin.h"
15 : : #include "valent-presenter-remote.h"
16 : :
17 : :
18 : : struct _ValentPresenterPlugin
19 : : {
20 : : ValentDevicePlugin parent_instance;
21 : :
22 : : ValentInput *input;
23 : : GtkWindow *remote;
24 : : };
25 : :
26 [ + + + - ]: 44 : G_DEFINE_FINAL_TYPE (ValentPresenterPlugin, valent_presenter_plugin, VALENT_TYPE_DEVICE_PLUGIN)
27 : :
28 : :
29 : : static void
30 : 2 : valent_presenter_plugin_handle_presenter (ValentPresenterPlugin *self,
31 : : JsonNode *packet)
32 : : {
33 : 2 : double dx, dy;
34 : 2 : gboolean stop;
35 : :
36 [ + - ]: 2 : g_assert (VALENT_IS_PRESENTER_PLUGIN (self));
37 [ - + ]: 2 : g_assert (VALENT_IS_PACKET (packet));
38 : :
39 : : /* NOTE: these are gyroscope motion deltas, but they're translated to pointer
40 : : * deltas due to lack of a virtual "laser pointer". */
41 [ + - + - ]: 4 : if (valent_packet_get_double (packet, "dx", &dx) &&
42 : 2 : valent_packet_get_double (packet, "dy", &dy))
43 : : {
44 : 2 : valent_input_pointer_motion (self->input, dx * 1000, dy * 1000);
45 : 4 : return;
46 : : }
47 : :
48 : : /* NOTE: this signifies that no more gyroscope deltas are incoming, so the
49 : : * "laser pointer" can be turned off. */
50 [ # # ]: 0 : if (valent_packet_get_boolean (packet, "stop", &stop))
51 : : {
52 : : VALENT_NOTE ("The \"stop\" field is not supported");
53 : : return;
54 : : }
55 : : }
56 : :
57 : : static void
58 : 1 : valent_presenter_plugin_send_motion (ValentPresenterPlugin *self,
59 : : double dx,
60 : : double dy)
61 : : {
62 : 2 : g_autoptr (JsonBuilder) builder = NULL;
63 [ - + ]: 1 : g_autoptr (JsonNode) packet = NULL;
64 : :
65 [ + - ]: 1 : g_assert (VALENT_IS_PRESENTER_PLUGIN (self));
66 : :
67 : 1 : valent_packet_init (&builder, "kdeconnect.presenter");
68 : 1 : json_builder_set_member_name (builder, "dx");
69 : 1 : json_builder_add_double_value (builder, dx);
70 : 1 : json_builder_set_member_name (builder, "dy");
71 : 1 : json_builder_add_double_value (builder, dy);
72 : 1 : packet = valent_packet_end (&builder);
73 : :
74 [ + - ]: 1 : valent_device_plugin_queue_packet (VALENT_DEVICE_PLUGIN (self), packet);
75 : 1 : }
76 : :
77 : : static void
78 : 1 : valent_presenter_plugin_send_stop (ValentPresenterPlugin *self)
79 : : {
80 : 2 : g_autoptr (JsonBuilder) builder = NULL;
81 [ - + ]: 1 : g_autoptr (JsonNode) packet = NULL;
82 : :
83 [ + - ]: 1 : g_assert (VALENT_IS_PRESENTER_PLUGIN (self));
84 : :
85 : 1 : valent_packet_init (&builder, "kdeconnect.presenter");
86 : 1 : json_builder_set_member_name (builder, "stop");
87 : 1 : json_builder_add_boolean_value (builder, TRUE);
88 : 1 : packet = valent_packet_end (&builder);
89 : :
90 [ + - ]: 1 : valent_device_plugin_queue_packet (VALENT_DEVICE_PLUGIN (self), packet);
91 : 1 : }
92 : :
93 : : /*
94 : : * GActions
95 : : */
96 : : static void
97 : 15 : valent_presenter_plugin_toggle_actions (ValentPresenterPlugin *self,
98 : : gboolean available)
99 : : {
100 : 15 : GAction *action;
101 : :
102 [ + - ]: 15 : g_assert (VALENT_IS_PRESENTER_PLUGIN (self));
103 : :
104 : 15 : action = g_action_map_lookup_action (G_ACTION_MAP (self), "remote");
105 [ + + + - ]: 34 : g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
106 : 4 : available && gtk_is_initialized ());
107 : :
108 : 15 : action = g_action_map_lookup_action (G_ACTION_MAP (self), "pointer");
109 : 15 : g_simple_action_set_enabled (G_SIMPLE_ACTION (action), available);
110 : 15 : }
111 : :
112 : : static void
113 : 0 : presenter_remote_action (GSimpleAction *action,
114 : : GVariant *parameter,
115 : : gpointer user_data)
116 : : {
117 : 0 : ValentPresenterPlugin *self = VALENT_PRESENTER_PLUGIN (user_data);
118 : :
119 [ # # ]: 0 : g_assert (VALENT_IS_PRESENTER_PLUGIN (self));
120 [ # # ]: 0 : g_assert (gtk_is_initialized ());
121 : :
122 [ # # ]: 0 : if (self->remote == NULL)
123 : : {
124 : 0 : ValentDevice *device;
125 : :
126 : 0 : device = valent_extension_get_object (VALENT_EXTENSION (self));
127 : 0 : self->remote = g_object_new (VALENT_TYPE_PRESENTER_REMOTE,
128 : : "device", device,
129 : : NULL);
130 : 0 : g_object_add_weak_pointer (G_OBJECT (self->remote),
131 : 0 : (gpointer) &self->remote);
132 : : }
133 : :
134 : 0 : gtk_window_present (self->remote);
135 : 0 : }
136 : :
137 : : static void
138 : 2 : presenter_pointer_action (GSimpleAction *action,
139 : : GVariant *parameter,
140 : : gpointer user_data)
141 : : {
142 : 2 : ValentPresenterPlugin *self = VALENT_PRESENTER_PLUGIN (user_data);
143 : 2 : double dx = 0.0;
144 : 2 : double dy = 0.0;
145 : 2 : unsigned int mask = 0;
146 : :
147 [ + - ]: 2 : g_assert (VALENT_IS_PRESENTER_PLUGIN (self));
148 : :
149 : 2 : g_variant_get (parameter, "(ddu)", &dx, &dy, &mask);
150 : :
151 [ + + - + : 2 : if (!G_APPROX_VALUE (dx, 0.0, 0.01) || !G_APPROX_VALUE (dy, 0.0, 0.01))
+ - - + -
- - + ]
152 : 1 : valent_presenter_plugin_send_motion (self, dx, dy);
153 : :
154 [ + + ]: 2 : if (mask != 0)
155 : 1 : valent_presenter_plugin_send_stop (self);
156 : 2 : }
157 : :
158 : : static const GActionEntry actions[] = {
159 : : {"remote", presenter_remote_action, NULL, NULL, NULL},
160 : : {"pointer", presenter_pointer_action, "(ddu)", NULL, NULL}
161 : : };
162 : :
163 : : /*
164 : : * ValentDevicePlugin
165 : : */
166 : : static void
167 : 15 : valent_presenter_plugin_update_state (ValentDevicePlugin *plugin,
168 : : ValentDeviceState state)
169 : : {
170 : 15 : ValentPresenterPlugin *self = VALENT_PRESENTER_PLUGIN (plugin);
171 : :
172 : 15 : gboolean available;
173 : :
174 [ + - ]: 15 : g_assert (VALENT_IS_PRESENTER_PLUGIN (self));
175 : :
176 : 15 : available = (state & VALENT_DEVICE_STATE_CONNECTED) != 0 &&
177 : : (state & VALENT_DEVICE_STATE_PAIRED) != 0;
178 : :
179 : 15 : valent_presenter_plugin_toggle_actions (self, available);
180 : 15 : }
181 : :
182 : : static void
183 : 2 : valent_presenter_plugin_handle_packet (ValentDevicePlugin *plugin,
184 : : const char *type,
185 : : JsonNode *packet)
186 : : {
187 : 2 : ValentPresenterPlugin *self = VALENT_PRESENTER_PLUGIN (plugin);
188 : :
189 [ + - ]: 2 : g_assert (VALENT_IS_PRESENTER_PLUGIN (self));
190 [ - + ]: 2 : g_assert (type != NULL);
191 [ - + ]: 2 : g_assert (VALENT_IS_PACKET (packet));
192 : :
193 [ + - ]: 2 : if (g_str_equal (type, "kdeconnect.presenter"))
194 : 2 : valent_presenter_plugin_handle_presenter (self, packet);
195 : : else
196 : 2 : g_assert_not_reached ();
197 : 2 : }
198 : :
199 : : /*
200 : : * ValentObject
201 : : */
202 : : static void
203 : 8 : valent_presenter_plugin_destroy (ValentObject *object)
204 : : {
205 : 8 : ValentPresenterPlugin *self = VALENT_PRESENTER_PLUGIN (object);
206 : 8 : ValentDevicePlugin *plugin = VALENT_DEVICE_PLUGIN (object);
207 : :
208 : : /* Destroy the presentation remote if necessary */
209 [ - + ]: 8 : g_clear_pointer (&self->remote, gtk_window_destroy);
210 : :
211 : 8 : valent_device_plugin_set_menu_item (plugin, "device.presenter.remote", NULL);
212 : :
213 : 8 : VALENT_OBJECT_CLASS (valent_presenter_plugin_parent_class)->destroy (object);
214 : 8 : }
215 : :
216 : : /*
217 : : * GObject
218 : : */
219 : : static void
220 : 5 : valent_presenter_plugin_constructed (GObject *object)
221 : : {
222 : 5 : ValentPresenterPlugin *self = VALENT_PRESENTER_PLUGIN (object);
223 : 5 : ValentDevicePlugin *plugin = VALENT_DEVICE_PLUGIN (object);
224 : :
225 : 5 : self->input = valent_input_get_default ();
226 : 5 : g_action_map_add_action_entries (G_ACTION_MAP (plugin),
227 : : actions,
228 : : G_N_ELEMENTS (actions),
229 : : plugin);
230 : 5 : valent_device_plugin_set_menu_action (plugin,
231 : : "device.presenter.remote",
232 : 5 : _("Presentation Remote"),
233 : : "valent-presenter-plugin");
234 : :
235 : 5 : G_OBJECT_CLASS (valent_presenter_plugin_parent_class)->constructed (object);
236 : 5 : }
237 : :
238 : : static void
239 : 2 : valent_presenter_plugin_class_init (ValentPresenterPluginClass *klass)
240 : : {
241 : 2 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
242 : 2 : ValentObjectClass *vobject_class = VALENT_OBJECT_CLASS (klass);
243 : 2 : ValentDevicePluginClass *plugin_class = VALENT_DEVICE_PLUGIN_CLASS (klass);
244 : :
245 : 2 : object_class->constructed = valent_presenter_plugin_constructed;
246 : :
247 : 2 : vobject_class->destroy = valent_presenter_plugin_destroy;
248 : :
249 : 2 : plugin_class->handle_packet = valent_presenter_plugin_handle_packet;
250 : 2 : plugin_class->update_state = valent_presenter_plugin_update_state;
251 : : }
252 : :
253 : : static void
254 : 5 : valent_presenter_plugin_init (ValentPresenterPlugin *self)
255 : : {
256 : 5 : }
257 : :
|