Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 1197 | ||||
Proposed branch: | lp:~ricotz/plank/dbus | ||||
Merge into: | lp:plank | ||||
Diff against target: |
906 lines (+747/-4) 12 files modified
.bzrignore (+4/-0) Makefile.am (+1/-0) configure.ac (+1/-0) docs/Makefile.am (+3/-0) examples/Makefile.am (+48/-0) examples/RemoteClient.vala (+65/-0) lib/DBus/Client.vala (+307/-0) lib/DBus/Interfaces.vala (+73/-0) lib/DBusManager.vala (+220/-0) lib/DockController.vala (+10/-4) lib/Makefile.am (+3/-0) lib/libplank.symbols (+12/-0) |
||||
To merge this branch: | bzr merge lp:~ricotz/plank/dbus | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Docky Core | Pending | ||
Review via email: mp+249177@code.launchpad.net |
Commit message
Description of the change
Provide Client class which discovers and connect to a running dock which provides certain inferfaces to control and manipulate it.
Provide a simple example using the Client class.
- 1182. By Rico Tzschichholz
-
items: Add boolean return-value to public DockContainer/
-Provider methods This will indicate the success or failure of the corresponding operation.
- 1183. By Rico Tzschichholz
-
items: Avoid removal-delay when unpinning an application
Remove an AppDockItem if it doesn't represent a running application and
doesn't have visible remote-info coming via LauncherEntry. - 1184. By Rico Tzschichholz
-
po: Update translations
- 1185. By Rico Tzschichholz
-
items: It is an ApplicationDock
Item, no need to use "as" - 1186. By Rico Tzschichholz
-
renderer: Draw final internal dock-buffer on window-context at (0,0)
- 1187. By Rico Tzschichholz
-
build: Make "distcheck" work independent from originally passed confflags
- 1188. By Rico Tzschichholz
-
dockwindow: Drop hack for menu-position with gtk+ 3.15+
Reverts r1158
- 1189. By Rico Tzschichholz
-
hidemanager: Add window-dodge hide-mode
- 1190. By Rico Tzschichholz
-
po: Update translations
- 1191. By Rico Tzschichholz
-
item: Rename protected arraylist-fields *_items to *_elements
- 1192. By Rico Tzschichholz
-
dockcontainer: Rename property Elements to VisibleElements
- 1193. By Rico Tzschichholz
-
controller: Rename property Items to VisibleItems
- 1194. By Rico Tzschichholz
-
controller: Add Items property
Which actually returns a list of all items regardless their visibility.
- 1195. By Rico Tzschichholz
-
controller: Call update_items while replacing default_provider
- 1196. By Rico Tzschichholz
-
Update symbols
- 1197. By Rico Tzschichholz
-
Add DBusManager to provide some useful remotely accessible actions
Provide "net.launchpad.
plank.Items" interface with "Add", "Remove",
"GetCount", "GetPersistentApplications" and "GetTransientAp plications"
methods.
Preview Diff
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2014-06-02 14:18:48 +0000 |
3 | +++ .bzrignore 2015-03-16 17:58:40 +0000 |
4 | @@ -33,6 +33,9 @@ |
5 | docs/c-doc |
6 | docs/vala-doc |
7 | docs/web-doc |
8 | +examples/remote-client |
9 | +examples/*.c |
10 | +examples/*.stamp |
11 | lib/abi* |
12 | lib/*-abi |
13 | lib/*.c |
14 | @@ -41,6 +44,7 @@ |
15 | lib/*.vapi |
16 | lib/*.pc |
17 | lib/*.stamp |
18 | +lib/DBus/*.c |
19 | lib/Drawing/*.c |
20 | lib/Factories/*.c |
21 | lib/Services/*.c |
22 | |
23 | === modified file 'Makefile.am' |
24 | --- Makefile.am 2015-03-11 16:25:25 +0000 |
25 | +++ Makefile.am 2015-03-16 17:58:40 +0000 |
26 | @@ -9,6 +9,7 @@ |
27 | vapi \ |
28 | src \ |
29 | tests \ |
30 | + examples \ |
31 | $(NULL) |
32 | |
33 | if HAVE_VALADOC |
34 | |
35 | === modified file 'configure.ac' |
36 | --- configure.ac 2015-01-25 19:35:00 +0000 |
37 | +++ configure.ac 2015-03-16 17:58:40 +0000 |
38 | @@ -356,6 +356,7 @@ |
39 | docs/Makefile |
40 | po/Makefile.in |
41 | tests/Makefile |
42 | +examples/Makefile |
43 | vapi/Makefile |
44 | ]) |
45 | |
46 | |
47 | === modified file 'docs/Makefile.am' |
48 | --- docs/Makefile.am 2015-03-11 16:25:25 +0000 |
49 | +++ docs/Makefile.am 2015-03-16 17:58:40 +0000 |
50 | @@ -17,6 +17,7 @@ |
51 | $(NULL) |
52 | |
53 | plank_doc_files = \ |
54 | + $(top_srcdir)/lib/DBusManager.vala \ |
55 | $(top_srcdir)/lib/DockController.vala \ |
56 | $(top_srcdir)/lib/DockPreferences.vala \ |
57 | $(top_srcdir)/lib/DockRenderer.vala \ |
58 | @@ -24,6 +25,8 @@ |
59 | $(top_srcdir)/lib/HideManager.vala \ |
60 | $(top_srcdir)/lib/PositionManager.vala \ |
61 | $(top_builddir)/lib/Version.vala \ |
62 | + $(top_srcdir)/lib/DBus/Client.vala \ |
63 | + $(top_srcdir)/lib/DBus/Interfaces.vala \ |
64 | $(top_srcdir)/lib/Drawing/AnimatedRenderer.vala \ |
65 | $(top_srcdir)/lib/Drawing/Color.vala \ |
66 | $(top_srcdir)/lib/Drawing/DrawingService.vala \ |
67 | |
68 | === added directory 'examples' |
69 | === added file 'examples/Makefile.am' |
70 | --- examples/Makefile.am 1970-01-01 00:00:00 +0000 |
71 | +++ examples/Makefile.am 2015-03-16 17:58:40 +0000 |
72 | @@ -0,0 +1,48 @@ |
73 | +include $(top_srcdir)/Makefile.common |
74 | + |
75 | +remote_client_VALAFLAGS = \ |
76 | + $(PLANK_CORE_VALAFLAGS) \ |
77 | + $(top_builddir)/lib/plank.vapi \ |
78 | + --vapidir $(top_srcdir)/vapi \ |
79 | + -C \ |
80 | + $(NULL) |
81 | + |
82 | +BUILT_SOURCES = remote_client_vala.stamp |
83 | + |
84 | +noinst_PROGRAMS = remote-client |
85 | + |
86 | +remote_client_CFLAGS = \ |
87 | + $(PLANK_CORE_CFLAGS) \ |
88 | + -include config.h \ |
89 | + -w \ |
90 | + -I$(top_builddir)/lib \ |
91 | + $(NULL) |
92 | + |
93 | +remote_client_LDADD = \ |
94 | + $(PLANK_CORE_LIBS) \ |
95 | + $(top_builddir)/lib/libplank.la \ |
96 | + $(NULL) |
97 | + |
98 | +remote_client_VALASOURCES = \ |
99 | + RemoteClient.vala \ |
100 | + $(NULL) |
101 | + |
102 | +nodist_remote_client_SOURCES = \ |
103 | + remote_client_vala.stamp \ |
104 | + $(remote_client_VALASOURCES:.vala=.c) \ |
105 | + $(NULL) |
106 | + |
107 | +remote_client_vala.stamp: $(remote_client_VALASOURCES) $(top_builddir)/lib/plank.vapi Makefile |
108 | + $(AM_V_VALA)$(VALAC) \ |
109 | + $(remote_client_VALAFLAGS) \ |
110 | + $(filter %.vala %.c,$^) |
111 | + $(AM_V_at)touch $@ |
112 | + |
113 | +CLEANFILES = \ |
114 | + $(nodist_remote_client_SOURCES) \ |
115 | + $(NULL) |
116 | + |
117 | +EXTRA_DIST = \ |
118 | + $(remote_client_VALASOURCES) \ |
119 | + $(NULL) |
120 | + |
121 | |
122 | === added file 'examples/RemoteClient.vala' |
123 | --- examples/RemoteClient.vala 1970-01-01 00:00:00 +0000 |
124 | +++ examples/RemoteClient.vala 2015-03-16 17:58:40 +0000 |
125 | @@ -0,0 +1,65 @@ |
126 | +// |
127 | +// Copyright (C) 2015 Rico Tzschichholz |
128 | +// |
129 | +// This program is free software: you can redistribute it and/or modify |
130 | +// it under the terms of the GNU General Public License as published by |
131 | +// the Free Software Foundation, either version 3 of the License, or |
132 | +// (at your option) any later version. |
133 | +// |
134 | +// This program is distributed in the hope that it will be useful, |
135 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
136 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
137 | +// GNU General Public License for more details. |
138 | +// |
139 | +// You should have received a copy of the GNU General Public License |
140 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
141 | +// |
142 | + |
143 | +using Plank.DBus; |
144 | +using Plank.Services; |
145 | + |
146 | +namespace Plank.Examples |
147 | +{ |
148 | + public class RemoteClient : GLib.Application |
149 | + { |
150 | + construct |
151 | + { |
152 | + application_id = "net.launchpad.plank.remote-client"; |
153 | + flags = ApplicationFlags.FLAGS_NONE; |
154 | + |
155 | + Logger.initialize ("remote-client"); |
156 | + Logger.DisplayLevel = LogLevel.DEBUG; |
157 | + } |
158 | + |
159 | + public override void activate () |
160 | + { |
161 | + hold (); |
162 | + |
163 | + var client = Client.get_instance (); |
164 | + client.proxy_changed.connect (handle_proxy_changed); |
165 | + } |
166 | + |
167 | + void handle_proxy_changed (Client client) |
168 | + { |
169 | + if (!client.is_connected) |
170 | + return; |
171 | + |
172 | + print ("List all persistent applications:\n"); |
173 | + foreach (unowned string s in client.get_persistent_applications ()) |
174 | + print (" + %s\n", s); |
175 | + |
176 | + print ("List all transient applications:\n"); |
177 | + foreach (unowned string s in client.get_transient_applications ()) |
178 | + print (" + %s\n", s); |
179 | + |
180 | + print ("\n"); |
181 | + } |
182 | + |
183 | + public static int main (string[] args) |
184 | + { |
185 | + var application = new RemoteClient (); |
186 | + return application.run (args); |
187 | + } |
188 | + |
189 | + } |
190 | +} |
191 | |
192 | === added directory 'lib/DBus' |
193 | === added file 'lib/DBus/Client.vala' |
194 | --- lib/DBus/Client.vala 1970-01-01 00:00:00 +0000 |
195 | +++ lib/DBus/Client.vala 2015-03-16 17:58:40 +0000 |
196 | @@ -0,0 +1,307 @@ |
197 | +// |
198 | +// Copyright (C) 2015 Rico Tzschichholz |
199 | +// |
200 | +// This program is free software: you can redistribute it and/or modify |
201 | +// it under the terms of the GNU General Public License as published by |
202 | +// the Free Software Foundation, either version 3 of the License, or |
203 | +// (at your option) any later version. |
204 | +// |
205 | +// This program is distributed in the hope that it will be useful, |
206 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
207 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
208 | +// GNU General Public License for more details. |
209 | +// |
210 | +// You should have received a copy of the GNU General Public License |
211 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
212 | +// |
213 | + |
214 | +namespace Plank.DBus |
215 | +{ |
216 | + /** |
217 | + * Connects to a running instance of plank via DBus and |
218 | + * provides remote interface to a currently runnning dock. |
219 | + */ |
220 | + public class Client : GLib.Object |
221 | + { |
222 | + static Client? instance; |
223 | + |
224 | + /** |
225 | + * Get the singleton instance of {@link Plank.DBus.Client} |
226 | + */ |
227 | + public static unowned Client get_instance () |
228 | + { |
229 | + if (instance == null) |
230 | + instance = new Client (); |
231 | + |
232 | + return instance; |
233 | + } |
234 | + |
235 | + /** |
236 | + * If the proxy interfaces for the dock are ready to be used |
237 | + * or were changed on runtime this signal will be emitted. |
238 | + */ |
239 | + public signal void proxy_changed (); |
240 | + |
241 | + /** |
242 | + * Whether the client is in an operatable state and connected to |
243 | + * a running dock |
244 | + */ |
245 | + public bool is_connected { |
246 | + get { |
247 | + return (items_proxy != null); |
248 | + } |
249 | + } |
250 | + |
251 | + DBusConnection? connection = null; |
252 | + string? client_object_path; |
253 | + |
254 | + string? dock_bus_owner; |
255 | + string? dock_bus_name; |
256 | + string? dock_object_path; |
257 | + |
258 | + uint dbus_dock_ping_id = 0; |
259 | + uint dbus_name_owner_changed_signal_id = 0; |
260 | + |
261 | + ItemsIface? items_proxy = null; |
262 | + int items_count = int.MIN; |
263 | + string[]? persistent_apps_list = null; |
264 | + string[]? transient_apps_list = null; |
265 | + |
266 | + Client () |
267 | + { |
268 | + Object (); |
269 | + } |
270 | + |
271 | + construct |
272 | + { |
273 | + unowned Application? application = GLib.Application.get_default (); |
274 | + unowned string? object_path = null; |
275 | + |
276 | + if (application != null) { |
277 | + connection = application.get_dbus_connection (); |
278 | + object_path = application.get_dbus_object_path (); |
279 | + } |
280 | + |
281 | + if (connection == null || object_path == null) { |
282 | + critical ("Initializing client failed"); |
283 | + return; |
284 | + } |
285 | + |
286 | + try { |
287 | + // Listen for "Ping" signals coming from docks |
288 | + dbus_dock_ping_id = connection.signal_subscribe (null, Plank.DBus.DOCK_INTERFACE_NAME, |
289 | + Plank.DBus.PING_NAME, null, null, DBusSignalFlags.NONE, handle_dock_ping); |
290 | + } catch (IOError e) { |
291 | + warning ("Could not subscribe for dock signal (%s)", e.message); |
292 | + } |
293 | + |
294 | + dbus_name_owner_changed_signal_id = connection.signal_subscribe ("org.freedesktop.DBus", "org.freedesktop.DBus", |
295 | + "NameOwnerChanged", "/org/freedesktop/DBus", null, DBusSignalFlags.NONE, handle_name_owner_changed); |
296 | + |
297 | + client_object_path = object_path; |
298 | + |
299 | + try { |
300 | + // Broadcast to inform running docks |
301 | + connection.emit_signal (null, client_object_path, Plank.DBus.CLIENT_INTERFACE_NAME, Plank.DBus.PING_NAME, null); |
302 | + } catch (Error e) { |
303 | + warning ("Could not ping running docks (%s)", e.message); |
304 | + } |
305 | + } |
306 | + |
307 | + ~Client () |
308 | + { |
309 | + if (connection != null) { |
310 | + if (dbus_dock_ping_id > 0) |
311 | + connection.signal_unsubscribe (dbus_dock_ping_id); |
312 | + if (dbus_name_owner_changed_signal_id > 0) |
313 | + connection.signal_unsubscribe (dbus_name_owner_changed_signal_id); |
314 | + } |
315 | + } |
316 | + |
317 | + void handle_dock_ping (DBusConnection connection, string sender_name, string object_path, |
318 | + string interface_name, string signal_name, Variant parameters) |
319 | + { |
320 | + if (dock_bus_name == null && dock_bus_name != sender_name) |
321 | + connect_proxies (connection, sender_name, object_path); |
322 | + } |
323 | + |
324 | + void handle_name_owner_changed (DBusConnection connection, string sender_name, string object_path, |
325 | + string interface_name, string signal_name, Variant parameters) |
326 | + { |
327 | + string name, before, after; |
328 | + parameters.get ("(sss)", out name, out before, out after); |
329 | + |
330 | + if (dock_bus_owner != null && dock_bus_owner == after) |
331 | + return; |
332 | + |
333 | + if (name != null && name != "" && name != dock_bus_name) |
334 | + return; |
335 | + |
336 | + if (after == null || after == "") { |
337 | + disconnect_proxies (); |
338 | + return; |
339 | + } |
340 | + |
341 | + connect_proxies (connection, name, object_path); |
342 | + } |
343 | + |
344 | + void connect_proxies (DBusConnection connection, string sender_name, string object_path) |
345 | + { |
346 | + debug ("Connecting and create proxies for '%s' (%s)", sender_name, object_path); |
347 | + |
348 | + try { |
349 | + items_proxy = connection.get_proxy_sync<Plank.DBus.ItemsIface> (sender_name, object_path, DBusProxyFlags.NONE); |
350 | + items_proxy.changed.connect (invalidate_items_cache); |
351 | + dock_bus_owner = ((DBusProxy) items_proxy).get_name_owner (); |
352 | + dock_bus_name = sender_name; |
353 | + dock_object_path = object_path; |
354 | + } catch (Error e) { |
355 | + dock_bus_owner = null; |
356 | + dock_bus_name = null; |
357 | + dock_object_path = null; |
358 | + |
359 | + items_proxy = null; |
360 | + critical ("Failed to create items proxy for '%s' (%s)", sender_name, object_path); |
361 | + } |
362 | + |
363 | + proxy_changed (); |
364 | + } |
365 | + |
366 | + void disconnect_proxies () |
367 | + { |
368 | + debug ("Disconnecting from '%s' (%s)", dock_bus_name, dock_object_path); |
369 | + |
370 | + dock_bus_owner = null; |
371 | + dock_bus_name = null; |
372 | + dock_object_path = null; |
373 | + |
374 | + items_proxy.changed.disconnect (invalidate_items_cache); |
375 | + items_proxy = null; |
376 | + } |
377 | + |
378 | + |
379 | + void invalidate_items_cache () |
380 | + { |
381 | + items_count = int.MIN; |
382 | + persistent_apps_list = null; |
383 | + transient_apps_list = null; |
384 | + } |
385 | + |
386 | + /** |
387 | + * Add a new item for the given uri to the dock |
388 | + * |
389 | + * @param uri an URI |
390 | + * @return whether it was successfully added |
391 | + */ |
392 | + public bool add_item (string uri) |
393 | + { |
394 | + if (items_proxy == null) { |
395 | + warning ("No proxy connected"); |
396 | + return false; |
397 | + } |
398 | + |
399 | + try { |
400 | + return items_proxy.add (uri); |
401 | + } catch (IOError e) { |
402 | + warning (e.message); |
403 | + return false; |
404 | + } |
405 | + } |
406 | + |
407 | + /** |
408 | + * Remove an existing item for the given uri from the dock |
409 | + * |
410 | + * @param uri an URI |
411 | + * @return whether it was successfully removed |
412 | + */ |
413 | + public bool remove_item (string uri) |
414 | + { |
415 | + if (items_proxy == null) { |
416 | + warning ("No proxy connected"); |
417 | + return false; |
418 | + } |
419 | + |
420 | + try { |
421 | + return items_proxy.remove (uri); |
422 | + } catch (IOError e) { |
423 | + warning (e.message); |
424 | + return false; |
425 | + } |
426 | + } |
427 | + |
428 | + /** |
429 | + * Returns the number of currently visible items on the dock |
430 | + * |
431 | + * @return the item-count |
432 | + */ |
433 | + public int get_items_count () |
434 | + { |
435 | + if (items_proxy == null) { |
436 | + warning ("No proxy connected"); |
437 | + return -1; |
438 | + } |
439 | + |
440 | + try { |
441 | + if (items_count == int.MIN) |
442 | + items_count = items_proxy.get_count (); |
443 | + } catch (IOError e) { |
444 | + warning (e.message); |
445 | + return -1; |
446 | + } |
447 | + |
448 | + return items_count; |
449 | + } |
450 | + |
451 | + /** |
452 | + * Returns an array of uris of the persistent applications on the dock |
453 | + * |
454 | + * @return the array of uris |
455 | + */ |
456 | + public unowned string[]? get_persistent_applications () |
457 | + { |
458 | + if (items_proxy == null) { |
459 | + warning ("No proxy connected"); |
460 | + return null; |
461 | + } |
462 | + |
463 | + if (persistent_apps_list != null) |
464 | + return persistent_apps_list; |
465 | + |
466 | + try { |
467 | + if (persistent_apps_list == null) |
468 | + persistent_apps_list = items_proxy.get_persistent_applications (); |
469 | + return persistent_apps_list; |
470 | + } catch (IOError e) { |
471 | + warning (e.message); |
472 | + } |
473 | + |
474 | + return null; |
475 | + } |
476 | + |
477 | + /** |
478 | + * Returns an array of uris of the transient applications on the dock |
479 | + * |
480 | + * @return the array of uris |
481 | + */ |
482 | + public unowned string[]? get_transient_applications () |
483 | + { |
484 | + if (items_proxy == null) { |
485 | + warning ("No proxy connected"); |
486 | + return null; |
487 | + } |
488 | + |
489 | + if (transient_apps_list != null) |
490 | + return transient_apps_list; |
491 | + |
492 | + try { |
493 | + if (transient_apps_list == null) |
494 | + transient_apps_list = items_proxy.get_transient_applications (); |
495 | + return transient_apps_list; |
496 | + } catch (IOError e) { |
497 | + warning (e.message); |
498 | + } |
499 | + |
500 | + return null; |
501 | + } |
502 | + } |
503 | +} |
504 | |
505 | === added file 'lib/DBus/Interfaces.vala' |
506 | --- lib/DBus/Interfaces.vala 1970-01-01 00:00:00 +0000 |
507 | +++ lib/DBus/Interfaces.vala 2015-03-16 17:58:40 +0000 |
508 | @@ -0,0 +1,73 @@ |
509 | +// |
510 | +// Copyright (C) 2015 Rico Tzschichholz |
511 | +// |
512 | +// This program is free software: you can redistribute it and/or modify |
513 | +// it under the terms of the GNU General Public License as published by |
514 | +// the Free Software Foundation, either version 3 of the License, or |
515 | +// (at your option) any later version. |
516 | +// |
517 | +// This program is distributed in the hope that it will be useful, |
518 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
519 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
520 | +// GNU General Public License for more details. |
521 | +// |
522 | +// You should have received a copy of the GNU General Public License |
523 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
524 | +// |
525 | + |
526 | +namespace Plank.DBus |
527 | +{ |
528 | + const string PING_NAME = "Ping"; |
529 | + |
530 | + const string DOCK_INTERFACE_NAME = "net.launchpad.plank"; |
531 | + const string CLIENT_INTERFACE_NAME = "net.launchpad.plank.Client"; |
532 | + |
533 | + /** |
534 | + * Provide an interface to manage items of the dock |
535 | + */ |
536 | + [DBus (name = "net.launchpad.plank.Items")] |
537 | + interface ItemsIface : GLib.Object |
538 | + { |
539 | + /** |
540 | + * Emmited when items are changed |
541 | + */ |
542 | + public signal void changed (); |
543 | + |
544 | + /** |
545 | + * Add a new item for the given uri to the dock |
546 | + * |
547 | + * @param uri an URI |
548 | + * @return whether it was successfully added |
549 | + */ |
550 | + public abstract bool add (string uri) throws GLib.IOError; |
551 | + |
552 | + /** |
553 | + * Remove an existing item for the given uri from the dock |
554 | + * |
555 | + * @param uri an URI |
556 | + * @return whether it was successfully removed |
557 | + */ |
558 | + public abstract bool remove (string uri) throws GLib.IOError; |
559 | + |
560 | + /** |
561 | + * Returns the number of currently visible items on the dock |
562 | + * |
563 | + * @return the item-count |
564 | + */ |
565 | + public abstract int get_count () throws GLib.IOError; |
566 | + |
567 | + /** |
568 | + * Returns an array of uris of the persistent applications on the dock |
569 | + * |
570 | + * @return the array of uris |
571 | + */ |
572 | + public abstract string[] get_persistent_applications () throws GLib.IOError; |
573 | + |
574 | + /** |
575 | + * Returns an array of uris of the transient applications on the dock |
576 | + * |
577 | + * @return the array of uris |
578 | + */ |
579 | + public abstract string[] get_transient_applications () throws GLib.IOError; |
580 | + } |
581 | +} |
582 | |
583 | === added file 'lib/DBusManager.vala' |
584 | --- lib/DBusManager.vala 1970-01-01 00:00:00 +0000 |
585 | +++ lib/DBusManager.vala 2015-03-16 17:58:40 +0000 |
586 | @@ -0,0 +1,220 @@ |
587 | +// |
588 | +// Copyright (C) 2015 Rico Tzschichholz |
589 | +// |
590 | +// This program is free software: you can redistribute it and/or modify |
591 | +// it under the terms of the GNU General Public License as published by |
592 | +// the Free Software Foundation, either version 3 of the License, or |
593 | +// (at your option) any later version. |
594 | +// |
595 | +// This program is distributed in the hope that it will be useful, |
596 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
597 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
598 | +// GNU General Public License for more details. |
599 | +// |
600 | +// You should have received a copy of the GNU General Public License |
601 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
602 | +// |
603 | + |
604 | +using Plank.Factories; |
605 | +using Plank.Items; |
606 | +using Plank.Services; |
607 | + |
608 | +namespace Plank |
609 | +{ |
610 | + /** |
611 | + * Provide an interface to manage items of the dock |
612 | + */ |
613 | + class DBusItems : GLib.Object, Plank.DBus.ItemsIface |
614 | + { |
615 | + DockController controller; |
616 | + uint changed_timer = 0; |
617 | + |
618 | + public DBusItems (DockController _controller) |
619 | + { |
620 | + controller = _controller; |
621 | + controller.items_changed.connect (handle_items_changed); |
622 | + } |
623 | + |
624 | + ~DBusItems () |
625 | + { |
626 | + controller.items_changed.disconnect (handle_items_changed); |
627 | + |
628 | + if (changed_timer > 0) { |
629 | + GLib.Source.remove (changed_timer); |
630 | + changed_timer = 0; |
631 | + } |
632 | + } |
633 | + |
634 | + void handle_items_changed () |
635 | + { |
636 | + if (changed_timer > 0) |
637 | + return; |
638 | + |
639 | + // Fire updates with a reasonable rate |
640 | + changed_timer = Timeout.add (500, () => { |
641 | + changed_timer = 0; |
642 | + changed (); |
643 | + return false; |
644 | + }); |
645 | + } |
646 | + |
647 | + public bool add (string uri) |
648 | + { |
649 | + debug ("Try to remotely add '%s'", uri); |
650 | + |
651 | + unowned ApplicationDockItemProvider? provider = controller.default_provider; |
652 | + if (provider == null) |
653 | + return false; |
654 | + |
655 | + unowned DockItem? item = provider.item_for_uri (uri); |
656 | + if (item != null && item is TransientDockItem) { |
657 | + ((TransientDockItem) item).pin_launcher (); |
658 | + return true; |
659 | + } |
660 | + |
661 | + return provider.add_item_with_uri (uri); |
662 | + } |
663 | + |
664 | + public bool remove (string uri) |
665 | + { |
666 | + debug ("Try to remotely remove '%s'", uri); |
667 | + |
668 | + unowned ApplicationDockItemProvider? provider = controller.default_provider; |
669 | + if (provider == null) |
670 | + return false; |
671 | + |
672 | + unowned DockItem? item = provider.item_for_uri (uri); |
673 | + if (item == null) |
674 | + return false; |
675 | + |
676 | + if (item is ApplicationDockItem) { |
677 | + if (!(item is TransientDockItem)) |
678 | + ((ApplicationDockItem) item).pin_launcher (); |
679 | + return true; |
680 | + } |
681 | + |
682 | + return provider.remove_item (item); |
683 | + } |
684 | + |
685 | + public int get_count () |
686 | + { |
687 | + return controller.VisibleItems.size; |
688 | + } |
689 | + |
690 | + public string[] get_persistent_applications () |
691 | + { |
692 | + Logger.verbose ("Remotely list persistent items"); |
693 | + |
694 | + var items = controller.Items; |
695 | + |
696 | + string[] result = {}; |
697 | + unowned string launcher; |
698 | + foreach (unowned DockItem item in items) { |
699 | + if (item is ApplicationDockItem && !(item is TransientDockItem)) { |
700 | + launcher = item.Launcher; |
701 | + if (launcher != null && launcher != "") |
702 | + result += launcher; |
703 | + } |
704 | + } |
705 | + |
706 | + return result; |
707 | + } |
708 | + |
709 | + public string[] get_transient_applications () |
710 | + { |
711 | + Logger.verbose ("Remotely list transient items"); |
712 | + |
713 | + var items = controller.Items; |
714 | + |
715 | + string[] result = {}; |
716 | + unowned string launcher; |
717 | + foreach (unowned DockItem item in items) { |
718 | + if (item is TransientDockItem) { |
719 | + launcher = item.Launcher; |
720 | + if (launcher != null && launcher != "") |
721 | + result += launcher; |
722 | + } |
723 | + } |
724 | + |
725 | + return result; |
726 | + } |
727 | + } |
728 | + |
729 | + /** |
730 | + * Handles all the exported DBus functions of the dock |
731 | + */ |
732 | + public class DBusManager : GLib.Object |
733 | + { |
734 | + public DockController controller { private get; construct; } |
735 | + |
736 | + string? dock_object_path; |
737 | + |
738 | + uint dbus_items_id = 0; |
739 | + uint dbus_client_ping_id = 0; |
740 | + |
741 | + public DBusManager (DockController controller) |
742 | + { |
743 | + Object (controller: controller); |
744 | + } |
745 | + |
746 | + construct |
747 | + { |
748 | + unowned Application application = Application.get_default (); |
749 | + unowned DBusConnection connection = application.get_dbus_connection (); |
750 | + unowned string? object_path = application.get_dbus_object_path (); |
751 | + |
752 | + if (connection == null || object_path == null) { |
753 | + critical ("Not able to register our interfaces"); |
754 | + return; |
755 | + } |
756 | + |
757 | + // Listen for "Ping" signals coming from clients |
758 | + try { |
759 | + dbus_client_ping_id = connection.signal_subscribe (null, Plank.DBus.CLIENT_INTERFACE_NAME, |
760 | + Plank.DBus.PING_NAME, null, null, DBusSignalFlags.NONE, handle_client_ping); |
761 | + } catch (IOError e) { |
762 | + warning ("Could not subscribe for client signal (%s)", e.message); |
763 | + } |
764 | + |
765 | + try { |
766 | + var dbus_items = new DBusItems (controller); |
767 | + dbus_items_id = connection.register_object<Plank.DBus.ItemsIface> (object_path, dbus_items); |
768 | + } catch (IOError e) { |
769 | + warning ("Could not register service (%s)", e.message); |
770 | + } |
771 | + |
772 | + dock_object_path = object_path; |
773 | + |
774 | + try { |
775 | + // Broadcast to inform running clients |
776 | + connection.emit_signal (null, dock_object_path, Plank.DBus.DOCK_INTERFACE_NAME, Plank.DBus.PING_NAME, null); |
777 | + } catch (Error e) { |
778 | + warning ("Could not ping running clients (%s)", e.message); |
779 | + } |
780 | + } |
781 | + |
782 | + ~DBusManager () |
783 | + { |
784 | + unowned Application application = Application.get_default (); |
785 | + unowned DBusConnection connection = application.get_dbus_connection (); |
786 | + |
787 | + if (connection != null) { |
788 | + if (dbus_items_id > 0) |
789 | + connection.unregister_object (dbus_items_id); |
790 | + if (dbus_client_ping_id > 0) |
791 | + connection.signal_unsubscribe (dbus_client_ping_id); |
792 | + } |
793 | + } |
794 | + |
795 | + void handle_client_ping (DBusConnection connection, string sender_name, string object_path, |
796 | + string interface_name, string signal_name, Variant parameters) |
797 | + { |
798 | + try { |
799 | + // Broadcast to inform running clients |
800 | + connection.emit_signal (null, dock_object_path, Plank.DBus.DOCK_INTERFACE_NAME, Plank.DBus.PING_NAME, null); |
801 | + } catch (Error e) { |
802 | + warning ("Could not ping running clients (%s)", e.message); |
803 | + } |
804 | + } |
805 | + } |
806 | +} |
807 | |
808 | === modified file 'lib/DockController.vala' |
809 | --- lib/DockController.vala 2015-03-16 17:44:57 +0000 |
810 | +++ lib/DockController.vala 2015-03-16 17:58:40 +0000 |
811 | @@ -42,7 +42,9 @@ |
812 | public DockRenderer renderer { get; protected set; } |
813 | public DockWindow window { get; protected set; } |
814 | |
815 | - ApplicationDockItemProvider? default_provider; |
816 | + public ApplicationDockItemProvider? default_provider { get; private set; } |
817 | + |
818 | + DBusManager dbus_manager; |
819 | Gee.ArrayList<unowned DockItem> visible_items; |
820 | Gee.ArrayList<unowned DockItem> items; |
821 | |
822 | @@ -90,6 +92,8 @@ |
823 | |
824 | prefs.notify["PinnedOnly"].connect (update_default_provider); |
825 | |
826 | + dbus_manager = new DBusManager (this); |
827 | + |
828 | position_manager = new PositionManager (this); |
829 | drag_manager = new DragManager (this); |
830 | hide_manager = new HideManager (this); |
831 | @@ -135,12 +139,12 @@ |
832 | return; |
833 | |
834 | Logger.verbose ("DockController.add_default_provider ()"); |
835 | - default_provider = get_default_provider (); |
836 | + default_provider = create_default_provider (); |
837 | |
838 | add_item (default_provider); |
839 | } |
840 | |
841 | - ApplicationDockItemProvider get_default_provider () |
842 | + ApplicationDockItemProvider create_default_provider () |
843 | { |
844 | ApplicationDockItemProvider provider; |
845 | |
846 | @@ -169,7 +173,7 @@ |
847 | return; |
848 | |
849 | var old_default_provider = default_provider; |
850 | - default_provider = get_default_provider (); |
851 | + default_provider = create_default_provider (); |
852 | default_provider.prepare (); |
853 | replace_item (default_provider, old_default_provider); |
854 | |
855 | @@ -275,6 +279,8 @@ |
856 | position_manager.update_regions (); |
857 | } |
858 | window.update_icon_regions (); |
859 | + |
860 | + items_changed (added, removed); |
861 | } |
862 | |
863 | void handle_item_positions_changed (DockContainer provider, Gee.List<unowned DockElement> moved_items) |
864 | |
865 | === modified file 'lib/Makefile.am' |
866 | --- lib/Makefile.am 2015-01-22 10:24:51 +0000 |
867 | +++ lib/Makefile.am 2015-03-16 17:58:40 +0000 |
868 | @@ -61,12 +61,15 @@ |
869 | $(NULL) |
870 | |
871 | libplank_la_VALASOURCES = \ |
872 | + DBusManager.vala \ |
873 | DockController.vala \ |
874 | DockPreferences.vala \ |
875 | DockRenderer.vala \ |
876 | DragManager.vala \ |
877 | HideManager.vala \ |
878 | PositionManager.vala \ |
879 | + DBus/Client.vala \ |
880 | + DBus/Interfaces.vala \ |
881 | Drawing/AnimatedRenderer.vala \ |
882 | Drawing/Color.vala \ |
883 | Drawing/DrawingService.vala \ |
884 | |
885 | === modified file 'lib/libplank.symbols' |
886 | --- lib/libplank.symbols 2015-03-16 17:47:28 +0000 |
887 | +++ lib/libplank.symbols 2015-03-16 17:58:40 +0000 |
888 | @@ -1,6 +1,18 @@ |
889 | +plank_dbus_client_add_item |
890 | +plank_dbus_client_get_instance |
891 | +plank_dbus_client_get_is_connected |
892 | +plank_dbus_client_get_items_count |
893 | +plank_dbus_client_get_persistent_applications |
894 | +plank_dbus_client_get_transient_applications |
895 | +plank_dbus_client_get_type |
896 | +plank_dbus_client_remove_item |
897 | +plank_dbus_manager_construct |
898 | +plank_dbus_manager_get_type |
899 | +plank_dbus_manager_new |
900 | plank_dock_controller_add_default_provider |
901 | plank_dock_controller_construct |
902 | plank_dock_controller_get_config_folder |
903 | +plank_dock_controller_get_default_provider |
904 | plank_dock_controller_get_drag_manager |
905 | plank_dock_controller_get_hide_manager |
906 | plank_dock_controller_get_Items |