Merge lp:~3v1n0/unity/dbus-indicators-proxy into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Marco Trevisan (Treviño)
Approved revision: no longer in the source branch.
Merged at revision: 2133
Proposed branch: lp:~3v1n0/unity/dbus-indicators-proxy
Merge into: lp:unity
Prerequisite: lp:~3v1n0/unity/indicators-p
Diff against target: 1049 lines (+260/-524)
7 files modified
UnityCore/DBusIndicators.cpp (+202/-450)
UnityCore/DBusIndicators.h (+2/-8)
UnityCore/GLibDBusProxy.cpp (+51/-55)
UnityCore/GLibDBusProxy.h (+2/-2)
UnityCore/Indicators.cpp (+2/-5)
UnityCore/Indicators.h (+1/-1)
plugins/unityshell/src/PanelView.cpp (+0/-3)
To merge this branch: bzr merge lp:~3v1n0/unity/dbus-indicators-proxy
Reviewer Review Type Date Requested Status
Michal Hruby (community) Approve
Review via email: mp+97328@code.launchpad.net

Commit message

DBusIndicators code rewritten to use glib::DBusProxy instead of raw gdbus calls

Description of the change

DBusIndicators code rewritten to use glib::DBusProxy instead of raw gdbus calls.

The code now is more simple, clean and C++ conformant. Also, now we always make sure that the panel is launched when it is not available (before this was not happening in some corner cases).

Tests are covered by lp:~3v1n0/unity/indicators-tests

To post a comment you must log in.
Revision history for this message
Michal Hruby (mhr3) wrote :

787 + bool auto_reconnect)

What are you actually trying to achieve with this? GDBusProxy automatically reconnects itself if you construct it using a known service name (as opposed to unique bus address). Therefore it seems redundant to me.

If you want to make sure that a service is alive, all you need to do is watch changes to the connected state and if it disconnects, just call any method from given interface and that will dbus-activate the service again.

review: Needs Information
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

> 787 + bool auto_reconnect)
>
> What are you actually trying to achieve with this? GDBusProxy automatically
> reconnects itself if you construct it using a known service name (as opposed
> to unique bus address). Therefore it seems redundant to me.

Yeah, I know, but it doesn't work here for the reason we discovered...

> If you want to make sure that a service is alive, all you need to do is watch
> changes to the connected state and if it disconnects, just call any method
> from given interface and that will dbus-activate the service again.

That's what I've tried to do, but it doesn't work here because glib::DBusProxy notify us about the disconnection event when actually the name has vanished, but the proxy is not disconnected yet.
Adding a timeout fixes it, but we should handle that in a better way.

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

> 787 + bool auto_reconnect)
>
> What are you actually trying to achieve with this? GDBusProxy automatically
> reconnects itself if you construct it using a known service name (as opposed
> to unique bus address). Therefore it seems redundant to me.

Ok this is now fixed into lp:~3v1n0/unity/dbus-indicators-proxy that will merge in this one as you know ;)

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

> Ok this is now fixed into lp:~3v1n0/unity/dbus-indicators-proxy that will
> merge in this one as you know ;)

Ops, I meant lp:~3v1n0/unity/dbus-proxy-name-owner-watch

Revision history for this message
Unity Merger (unity-merger) wrote :

The prerequisite lp:~3v1n0/unity/indicators-p has not yet been merged into lp:unity.

Revision history for this message
Michal Hruby (mhr3) wrote :

Overall I'm liking this a lot - mostly because of "(+234/-516)" :) I have some concerns though:

269 + RequestSyncAll();
270 +
271 + reconnect_timeout_id_ = g_timeout_add_seconds(1, [](gpointer data) -> gboolean {
272 + auto self = static_cast<DBusIndicators::Impl*>(data);
273 +
274 + if (!self->gproxy_.IsConnected())
275 + {
276 + self->RequestSyncAll();
277 + return TRUE;
278 + }
279 +
280 + self->reconnect_timeout_id_ = 0;
281 + return FALSE;
282 + }, this);

Are you sure you want to call RequestSyncAll also outside of the lambda expression? Plus you should be checking if reconnect_timeout_id == 0, before calling g_timeout_add...

146 + struct CallData
147 + {
148 + Impl* self;
149 + GVariant *parameters;
150 + };

I'm not really liking this, it's unclear who owns the variant (or rather why isn't it unreffed) - using our Variant wrapper should fix this. What's worse is that the CallData can be alive even after the Impl instance is destroyed which can lead to a crash.

review: Needs Fixing
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

> Overall I'm liking this a lot - mostly because of "(+234/-516)" :)

Ehehe ;)

> Are you sure you want to call RequestSyncAll also outside of the lambda
> expression?

Yes. Because after we get a disconnection event we can try immediately to restore the service, it that fails we retry every 1 second. This assures that if we have a valid u-p-s running or in the system as well, we use it!

> Plus you should be checking if reconnect_timeout_id == 0, before
> calling g_timeout_add...

Yes, sure.

> 146 + struct CallData
> 147 + {
> 148 + Impl* self;
> 149 + GVariant *parameters;
> 150 + };
>
> I'm not really liking this, it's unclear who owns the variant (or rather why
> isn't it unreffed) - using our Variant wrapper should fix this.

Well, as you know the proxy handles it, so I didn't ref/unreff'ed it... But I'll move to glib::Variant.

> What's worse
> is that the CallData can be alive even after the Impl instance is destroyed
> which can lead to a crash.

This should be very unlikely using an idle, but I'll make that more safe as well.

Revision history for this message
Michal Hruby (mhr3) wrote :

Awesome, thanks!

review: Approve
Revision history for this message
Unity Merger (unity-merger) wrote :

No proposals found for merge of lp:~3v1n0/unity/indicators-p into lp:unity.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'UnityCore/DBusIndicators.cpp'
2--- UnityCore/DBusIndicators.cpp 2012-03-20 10:16:27 +0000
3+++ UnityCore/DBusIndicators.cpp 2012-03-20 10:16:27 +0000
4@@ -1,6 +1,6 @@
5 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
6 /*
7- * Copyright (C) 2010, 2011 Canonical Ltd
8+ * Copyright (C) 2010-2012 Canonical Ltd
9 *
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 3 as
12@@ -18,18 +18,11 @@
13 * Marco Trevisan (Treviño) <3v1n0@ubuntu.com>
14 */
15
16+#include "config.h"
17 #include "DBusIndicators.h"
18
19-#include <algorithm>
20-#include <iostream>
21-
22-#include <gio/gio.h>
23-
24-#include <X11/Xlib.h>
25-
26-#include "config.h"
27-#include "GLibSignal.h"
28 #include "GLibWrapper.h"
29+#include "GLibDBusProxy.h"
30 #include "Variant.h"
31
32 namespace unity
33@@ -39,87 +32,33 @@
34
35 namespace
36 {
37-// This anonymous namespace holds the DBus callback methods.
38-
39-struct SyncData
40-{
41- SyncData(DBusIndicators::Impl* self_)
42- : self(self_)
43- , cancel(g_cancellable_new())
44- {
45- }
46-
47- ~SyncData()
48- {
49- if (cancel)
50- {
51- g_cancellable_cancel(cancel);
52- g_object_unref(cancel);
53- }
54- }
55-
56- void SyncComplete()
57- {
58- if (cancel)
59- {
60- g_object_unref(cancel);
61- }
62- cancel = NULL;
63- }
64-
65- DBusIndicators::Impl* self;
66- GCancellable* cancel;
67-};
68-
69-typedef boost::shared_ptr<SyncData> SyncDataPtr;
70-
71-const char* const S_NAME = "com.canonical.Unity.Panel.Service";
72-const char* const S_PATH = "/com/canonical/Unity/Panel/Service";
73-const char* const S_IFACE = "com.canonical.Unity.Panel.Service";
74-
75-struct ShowEntryData
76-{
77- glib::Object<GDBusProxy> proxy;
78- std::string entry_id;
79- guint xid;
80- int x;
81- int y;
82- guint button;
83- guint timestamp;
84-};
85-
86-bool run_local_panel_service();
87-gboolean reconnect_to_service(gpointer data);
88-void on_proxy_ready_cb(GObject* source, GAsyncResult* res, gpointer data);
89-void request_sync(GDBusProxy* proxy, const char* method, GVariant* name,
90- SyncData* data);
91-void on_sync_ready_cb(GObject* source, GAsyncResult* res, gpointer data);
92-
93-bool send_show_entry(ShowEntryData* data);
94-bool send_show_appmenu(ShowEntryData* data);
95-
96+const std::string SERVICE_NAME("com.canonical.Unity.Panel.Service");
97+const std::string SERVICE_PATH("/com/canonical/Unity/Panel/Service");
98+const std::string SERVICE_IFACE("com.canonical.Unity.Panel.Service");
99 } // anonymous namespace
100
101
102-// Connects to the remote panel service (unity-panel-service) and translates
103-// that into something that the panel can show
104+/* Connects to the remote panel service (unity-panel-service) and translates
105+ * that into something that the panel can show */
106 class DBusIndicators::Impl
107 {
108 public:
109 Impl(DBusIndicators* owner);
110+ ~Impl();
111
112- void OnRemoteProxyReady(GDBusProxy* proxy);
113- void Reconnect();
114+ void CheckLocalService();
115 void RequestSyncAll();
116 void RequestSyncIndicator(std::string const& name);
117- void Sync(GVariant* args, SyncData* data);
118- void SyncGeometries(std::string const& name,
119- EntryLocationMap const& locations);
120- void OnProxyNameOwnerChanged(GDBusProxy* proxy, GParamSpec* pspec);
121- void OnProxySignalReceived(GDBusProxy* proxy,
122- char* sender_name,
123- char* signal_name_,
124- GVariant* parameters);
125+ void Sync(GVariant* args);
126+ void SyncGeometries(std::string const& name, EntryLocationMap const& locations);
127+
128+ void OnConnected();
129+ void OnDisconnected();
130+
131+ void OnReSync(GVariant* parameters);
132+ void OnEntryActivated(GVariant* parameters);
133+ void OnEntryActivatedRequest(GVariant* parameters);
134+ void OnEntryShowNowChanged(GVariant* parameters);
135
136 virtual void OnEntryScroll(std::string const& entry_id, int delta);
137 virtual void OnEntryShowMenu(std::string const& entry_id, unsigned int xid,
138@@ -130,16 +69,17 @@
139 virtual void OnShowAppMenu(unsigned int xid, int x, int y,
140 unsigned int timestamp);
141
142- std::string name() const;
143- std::string owner_name() const;
144- bool using_local_service() const;
145+ struct CallData
146+ {
147+ Impl* self;
148+ glib::Variant parameters;
149+ };
150
151 DBusIndicators* owner_;
152- glib::Object<GDBusProxy> proxy_;
153- typedef std::vector<SyncDataPtr> PendingSyncs;
154- PendingSyncs pending_syncs_;
155-
156- glib::SignalManager signal_manager_;
157+ guint reconnect_timeout_id_;
158+ guint show_entry_idle_id_;
159+ guint show_appmenu_idle_id_;
160+ glib::DBusProxy gproxy_;
161 std::map<std::string, EntryLocationMap> cached_locations_;
162 };
163
164@@ -147,62 +87,149 @@
165 // Public Methods
166 DBusIndicators::Impl::Impl(DBusIndicators* owner)
167 : owner_(owner)
168-{
169- Reconnect();
170-}
171-
172-void DBusIndicators::Impl::Reconnect()
173-{
174- g_spawn_command_line_sync("killall -9 unity-panel-service",
175- NULL, NULL, NULL, NULL);
176-
177+ , reconnect_timeout_id_(0)
178+ , show_entry_idle_id_(0)
179+ , show_appmenu_idle_id_(0)
180+ , gproxy_(SERVICE_NAME, SERVICE_PATH, SERVICE_IFACE,
181+ G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES)
182+{
183+ gproxy_.Connect("ReSync", sigc::mem_fun(this, &DBusIndicators::Impl::OnReSync));
184+ gproxy_.Connect("EntryActivated", sigc::mem_fun(this, &DBusIndicators::Impl::OnEntryActivated));
185+ gproxy_.Connect("EntryActivateRequest", sigc::mem_fun(this, &DBusIndicators::Impl::OnEntryActivatedRequest));
186+ gproxy_.Connect("EntryShowNowChanged", sigc::mem_fun(this, &DBusIndicators::Impl::OnEntryShowNowChanged));
187+
188+ gproxy_.connected.connect(sigc::mem_fun(this, &DBusIndicators::Impl::OnConnected));
189+ gproxy_.disconnected.connect(sigc::mem_fun(this, &DBusIndicators::Impl::OnDisconnected));
190+
191+ CheckLocalService();
192+}
193+
194+DBusIndicators::Impl::~Impl()
195+{
196+ if (reconnect_timeout_id_)
197+ g_source_remove(reconnect_timeout_id_);
198+
199+ if (show_entry_idle_id_)
200+ g_source_remove(show_entry_idle_id_);
201+
202+ if (show_appmenu_idle_id_)
203+ g_source_remove(show_appmenu_idle_id_);
204+}
205+
206+void DBusIndicators::Impl::CheckLocalService()
207+{
208 if (g_getenv("PANEL_USE_LOCAL_SERVICE"))
209 {
210- run_local_panel_service();
211- g_timeout_add_seconds(1, reconnect_to_service, this);
212- }
213- else
214- {
215- // We want to grab the Panel Service object. This is async, which is fine
216- reconnect_to_service(this);
217- }
218-}
219-
220-void DBusIndicators::Impl::OnRemoteProxyReady(GDBusProxy* proxy)
221-{
222- if (proxy_)
223- {
224- // We've been connected before; We don't need new proxy, just continue
225- // rocking with the old one.
226- g_object_unref(proxy);
227- }
228- else
229- {
230- proxy_ = proxy;
231- // Connect to interesting signals
232- signal_manager_.Add(new glib::Signal<void, GDBusProxy*, char*, char*, GVariant*>
233- (proxy_, "g-signal", sigc::mem_fun(this, &Impl::OnProxySignalReceived)));
234-
235- signal_manager_.Add(new glib::Signal<void, GDBusProxy*, GParamSpec*>
236- (proxy_, "notify::g-name-owner", sigc::mem_fun(this, &Impl::OnProxyNameOwnerChanged)));
237- }
238- RequestSyncAll();
239+ glib::Error error;
240+
241+ g_spawn_command_line_sync("killall -9 unity-panel-service",
242+ nullptr, nullptr, nullptr, nullptr);
243+
244+ // This is obviously hackish, but this part of the code is mostly hackish...
245+ // Let's attempt to run it from where we expect it to be
246+ std::string cmd = PREFIXDIR + std::string("/lib/unity/unity-panel-service");
247+ std::cerr << "\nWARNING: Couldn't load panel from installed services, "
248+ << "so trying to load panel from known location: "
249+ << cmd << "\n";
250+
251+ g_spawn_command_line_async(cmd.c_str(), &error);
252+
253+ if (error)
254+ {
255+ std::cerr << "\nWARNING: Unable to launch remote service manually: "
256+ << error.Message() << "\n";
257+ }
258+ }
259+}
260+
261+void DBusIndicators::Impl::OnConnected()
262+{
263+ RequestSyncAll();
264+}
265+
266+void DBusIndicators::Impl::OnDisconnected()
267+{
268+ for (auto indicator : owner_->GetIndicators())
269+ {
270+ owner_->RemoveIndicator(indicator->name());
271+ }
272+
273+ cached_locations_.clear();
274+
275+ CheckLocalService();
276+ RequestSyncAll();
277+
278+ if (reconnect_timeout_id_)
279+ g_source_remove(reconnect_timeout_id_);
280+
281+ reconnect_timeout_id_ = g_timeout_add_seconds(1, [](gpointer data) -> gboolean {
282+ auto self = static_cast<DBusIndicators::Impl*>(data);
283+
284+ if (!self->gproxy_.IsConnected())
285+ {
286+ self->RequestSyncAll();
287+ return TRUE;
288+ }
289+
290+ self->reconnect_timeout_id_ = 0;
291+ return FALSE;
292+ }, this);
293+}
294+
295+void DBusIndicators::Impl::OnReSync(GVariant* parameters)
296+{
297+ glib::String indicator_name;
298+ g_variant_get(parameters, "(s)", &indicator_name);
299+
300+ if (indicator_name && !indicator_name.Str().empty())
301+ {
302+ RequestSyncIndicator(indicator_name);
303+ }
304+ else
305+ {
306+ RequestSyncAll();
307+ }
308+}
309+
310+void DBusIndicators::Impl::OnEntryActivated(GVariant* parameters)
311+{
312+ glib::String entry_name;
313+ nux::Rect geo;
314+ g_variant_get(parameters, "(s(iiuu))", &entry_name, &geo.x, &geo.y, &geo.width, &geo.height);
315+
316+ if (entry_name)
317+ owner_->ActivateEntry(entry_name, geo);
318+}
319+
320+void DBusIndicators::Impl::OnEntryActivatedRequest(GVariant* parameters)
321+{
322+ glib::String entry_name;
323+ g_variant_get(parameters, "(s)", &entry_name);
324+
325+ if (entry_name)
326+ owner_->on_entry_activate_request.emit(entry_name);
327+}
328+
329+void DBusIndicators::Impl::OnEntryShowNowChanged(GVariant* parameters)
330+{
331+ glib::String entry_name;
332+ gboolean show_now;
333+ g_variant_get(parameters, "(sb)", &entry_name, &show_now);
334+
335+ if (entry_name)
336+ owner_->SetEntryShowNow(entry_name, show_now);
337 }
338
339 void DBusIndicators::Impl::RequestSyncAll()
340 {
341- SyncDataPtr data(new SyncData(this));
342- pending_syncs_.push_back(data);
343- request_sync(proxy_, "Sync", NULL, data.get());
344+ gproxy_.Call("Sync", nullptr, sigc::mem_fun(this, &DBusIndicators::Impl::Sync));
345 }
346
347 void DBusIndicators::Impl::RequestSyncIndicator(std::string const& name)
348 {
349- SyncDataPtr data(new SyncData(this));
350- pending_syncs_.push_back(data);
351- // The ownership of this variant is taken by the g_dbus_proxy_call.
352- GVariant* v_name = g_variant_new("(s)", name.c_str());
353- request_sync(proxy_, "SyncOne", v_name, data.get());
354+ GVariant* parameter = g_variant_new("(s)", name.c_str());
355+
356+ gproxy_.Call("SyncOne", parameter, sigc::mem_fun(this, &DBusIndicators::Impl::Sync));
357 }
358
359
360@@ -216,16 +243,20 @@
361 // We have to do this because on certain systems X won't have time to
362 // respond to our request for XUngrabPointer and this will cause the
363 // menu not to show
364- auto data = new ShowEntryData();
365- data->proxy = proxy_;
366- data->entry_id = entry_id;
367- data->xid = xid;
368- data->x = x;
369- data->y = y;
370- data->button = button;
371- data->timestamp = timestamp;
372-
373- g_idle_add_full (G_PRIORITY_DEFAULT, (GSourceFunc) send_show_entry, data, NULL);
374+ auto data = new CallData();
375+ data->self = this;
376+ data->parameters = g_variant_new("(suiiuu)", entry_id.c_str(), xid, x, y,
377+ button, timestamp);
378+
379+ if (show_entry_idle_id_)
380+ g_source_remove(show_entry_idle_id_);
381+
382+ show_entry_idle_id_ = g_idle_add_full (G_PRIORITY_DEFAULT, [] (gpointer data) -> gboolean {
383+ auto call_data = static_cast<CallData*>(data);
384+ call_data->self->gproxy_.Call("ShowEntry", call_data->parameters);
385+
386+ return FALSE;
387+ }, data, [] (gpointer data) { delete static_cast<CallData*>(data); });
388 }
389
390 void DBusIndicators::Impl::OnShowAppMenu(unsigned int xid, int x, int y,
391@@ -236,43 +267,43 @@
392 // We have to do this because on certain systems X won't have time to
393 // respond to our request for XUngrabPointer and this will cause the
394 // menu not to show
395- auto data = new ShowEntryData();
396- data->proxy = proxy_;
397- data->xid = xid;
398- data->x = x;
399- data->y = y;
400- data->timestamp = timestamp;
401-
402- g_idle_add_full (G_PRIORITY_DEFAULT, (GSourceFunc) send_show_appmenu, data, NULL);
403+ auto data = new CallData();
404+ data->self = this;
405+ data->parameters = g_variant_new("(uiiu)", xid, x, y, timestamp);
406+
407+ if (show_appmenu_idle_id_)
408+ g_source_remove(show_appmenu_idle_id_);
409+
410+ show_appmenu_idle_id_ = g_idle_add_full (G_PRIORITY_DEFAULT, [] (gpointer data) -> gboolean {
411+ auto call_data = static_cast<CallData*>(data);
412+ call_data->self->gproxy_.Call("ShowAppMenu", call_data->parameters);
413+
414+ return FALSE;
415+ }, data, [] (gpointer data) { delete static_cast<CallData*>(data); });
416 }
417
418 void DBusIndicators::Impl::OnEntrySecondaryActivate(std::string const& entry_id,
419 unsigned int timestamp)
420 {
421- g_dbus_proxy_call(proxy_, "SecondaryActivateEntry",
422- g_variant_new("(su)", entry_id.c_str(), timestamp),
423- G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
424+ gproxy_.Call("SecondaryActivateEntry", g_variant_new("(su)", entry_id.c_str(), timestamp));
425 }
426
427 void DBusIndicators::Impl::OnEntryScroll(std::string const& entry_id, int delta)
428 {
429- g_dbus_proxy_call(proxy_, "ScrollEntry",
430- g_variant_new("(si)", entry_id.c_str(), delta),
431- G_DBUS_CALL_FLAGS_NONE,
432- -1, NULL, NULL, NULL);
433+ gproxy_.Call("ScrollEntry", g_variant_new("(si)", entry_id.c_str(), delta));
434 }
435
436-void DBusIndicators::Impl::Sync(GVariant* args, SyncData* data)
437+void DBusIndicators::Impl::Sync(GVariant* args)
438 {
439- GVariantIter* iter = NULL;
440- gchar* name_hint = NULL;
441- gchar* indicator_id = NULL;
442- gchar* entry_id = NULL;
443- gchar* label = NULL;
444+ GVariantIter* iter = nullptr;
445+ gchar* name_hint = nullptr;
446+ gchar* indicator_id = nullptr;
447+ gchar* entry_id = nullptr;
448+ gchar* label = nullptr;
449 gboolean label_sensitive = false;
450 gboolean label_visible = false;
451 guint32 image_type = 0;
452- gchar* image_data = NULL;
453+ gchar* image_data = nullptr;
454 gboolean image_sensitive = false;
455 gboolean image_visible = false;
456 gint32 priority = -1;
457@@ -308,7 +339,7 @@
458
459 Indicator::Entries& entries = indicators[indicator];
460
461- // NULL entries (entry_id == "") are empty indicators.
462+ // Null entries (entry_id == "") are empty indicators.
463 if (entry != "")
464 {
465 Entry::Ptr e = indicator->GetEntry(entry_id);
466@@ -343,20 +374,6 @@
467 i->first->Sync(indicators[i->first]);
468 }
469
470- // Clean up the SyncData. NOTE: don't use find when passing in a raw
471- // pointer due to explicit construction of the shared pointer. Could write
472- // a predicate, but often a for loop is easier to understand.
473- data->SyncComplete();
474- for (PendingSyncs::iterator i = pending_syncs_.begin(), end = pending_syncs_.end();
475- i != end; ++i)
476- {
477- if (i->get() == data)
478- {
479- pending_syncs_.erase(i);
480- break;
481- }
482- }
483-
484 // Notify listeners we have new data
485 owner_->on_synced.emit();
486 }
487@@ -364,7 +381,7 @@
488 void DBusIndicators::Impl::SyncGeometries(std::string const& name,
489 EntryLocationMap const& locations)
490 {
491- if (!proxy_)
492+ if (!gproxy_.IsConnected())
493 return;
494
495 GVariantBuilder b;
496@@ -414,116 +431,17 @@
497 }
498
499 g_variant_builder_close(&b);
500- g_dbus_proxy_call(proxy_, "SyncGeometries",
501- g_variant_builder_end(&b),
502- G_DBUS_CALL_FLAGS_NONE,
503- -1,
504- NULL,
505- NULL,
506- NULL);
507
508+ gproxy_.Call("SyncGeometries", g_variant_builder_end(&b));
509 cached_loc = locations;
510 }
511
512-std::string DBusIndicators::Impl::name() const
513-{
514- glib::String name;
515- g_object_get(proxy_, "g-name", &name, NULL);
516- return name.Str();
517-}
518-
519-std::string DBusIndicators::Impl::owner_name() const
520-{
521- glib::String owner_name;
522- g_object_get(proxy_, "g-name-owner", &owner_name, NULL);
523- return owner_name.Str();
524-}
525-
526-bool DBusIndicators::Impl::using_local_service() const
527-{
528- return g_getenv("PANEL_USE_LOCAL_SERVICE") != NULL;
529-}
530-
531-void DBusIndicators::Impl::OnProxyNameOwnerChanged(GDBusProxy* proxy,
532- GParamSpec* pspec)
533-{
534- char* name_owner = g_dbus_proxy_get_name_owner(proxy);
535-
536- if (name_owner == NULL)
537- {
538- for (auto indicator : owner_->GetIndicators())
539- {
540- owner_->RemoveIndicator(indicator->name());
541- }
542-
543- // The panel service has stopped for some reason. Restart it if not in
544- // dev mode
545- if (!g_getenv("UNITY_DEV_MODE"))
546- Reconnect();
547- }
548-
549- g_free(name_owner);
550-}
551-
552-void DBusIndicators::Impl::OnProxySignalReceived(GDBusProxy* proxy,
553- char* sender_name,
554- char* signal_name_,
555- GVariant* parameters)
556-{
557- std::string signal_name(signal_name_);
558- if (signal_name == "EntryActivated")
559- {
560- glib::String entry_name;
561- nux::Rect geo;
562- g_variant_get(parameters, "(s(iiuu))", &entry_name, &geo.x, &geo.y, &geo.width, &geo.height);
563-
564- if (entry_name)
565- {
566- owner_->ActivateEntry(entry_name.Str(), geo);
567- }
568- }
569- else if (signal_name == "EntryActivateRequest")
570- {
571- const char* entry_name = g_variant_get_string(g_variant_get_child_value(parameters, 0), NULL);
572- if (entry_name)
573- {
574- owner_->on_entry_activate_request.emit(entry_name);
575- }
576- }
577- else if (signal_name == "ReSync")
578- {
579- const char* id = g_variant_get_string(g_variant_get_child_value(parameters, 0), NULL);
580- bool sync_one = !g_strcmp0(id, "") == 0;
581-
582- if (sync_one)
583- {
584- RequestSyncIndicator(id);
585- }
586- else
587- {
588- RequestSyncAll();
589- }
590- }
591- else if (signal_name == "EntryShowNowChanged")
592- {
593- gchar* id = NULL;
594- gboolean show_now;
595-
596- g_variant_get(parameters, "(sb)", &id, &show_now);
597- owner_->SetEntryShowNow(id, show_now);
598-
599- g_free(id);
600- }
601-}
602-
603 DBusIndicators::DBusIndicators()
604 : pimpl(new Impl(this))
605 {}
606
607 DBusIndicators::~DBusIndicators()
608-{
609- delete pimpl;
610-}
611+{}
612
613 void DBusIndicators::SyncGeometries(std::string const& name,
614 EntryLocationMap const& locations)
615@@ -555,171 +473,5 @@
616 pimpl->OnShowAppMenu(xid, x, y, timestamp);
617 }
618
619-std::string DBusIndicators::name() const
620-{
621- return pimpl->name();
622-}
623-
624-std::string DBusIndicators::owner_name() const
625-{
626- return pimpl->owner_name();
627-}
628-
629-bool DBusIndicators::using_local_service() const
630-{
631- return pimpl->using_local_service();
632-}
633-
634-
635-namespace
636-{
637-
638-// Initialise DBus for the panel service, and let us know when it is
639-// ready. The unused bool return is to fit with the GSourceFunc.
640-gboolean reconnect_to_service(gpointer data)
641-{
642- g_dbus_proxy_new_for_bus(G_BUS_TYPE_SESSION,
643- G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
644- NULL,
645- S_NAME,
646- S_PATH,
647- S_IFACE,
648- NULL,
649- on_proxy_ready_cb,
650- data);
651- return false;
652-}
653-
654-// Make sure the proxy object exists and has a name, and if so, pass
655-// that on to the DBusIndicators.
656-void on_proxy_ready_cb(GObject* source, GAsyncResult* res, gpointer data)
657-{
658- DBusIndicators::Impl* remote = reinterpret_cast<DBusIndicators::Impl*>(data);
659- GError* error = NULL;
660- GDBusProxy* proxy = g_dbus_proxy_new_for_bus_finish(res, &error);
661-
662- static bool force_tried = false;
663-
664- char* name_owner;
665- if (G_IS_DBUS_PROXY(proxy) && (name_owner = g_dbus_proxy_get_name_owner(proxy)))
666- {
667- remote->OnRemoteProxyReady(G_DBUS_PROXY(proxy));
668- g_free(name_owner);
669- return;
670- }
671- else
672- {
673- if (force_tried)
674- {
675- g_warning("WARNING: Unable to connect to the unity-panel-service %s",
676- error ? error->message : "Unknown");
677- if (error)
678- g_error_free(error);
679- }
680- else
681- {
682- force_tried = true;
683- run_local_panel_service();
684- g_timeout_add_seconds(2, reconnect_to_service, remote);
685- }
686- }
687-
688- g_object_unref(proxy);
689-}
690-
691-
692-bool run_local_panel_service()
693-{
694- GError* error = NULL;
695-
696- // This is obviously hackish, but this part of the code is mostly hackish...
697- // Let's attempt to run it from where we expect it to be
698- std::string cmd = PREFIXDIR + std::string("/lib/unity/unity-panel-service");
699- std::cerr << "\nWARNING: Couldn't load panel from installed services, "
700- << "so trying to load panel from known location: "
701- << cmd << "\n";
702-
703- g_spawn_command_line_async(cmd.c_str(), &error);
704- if (error)
705- {
706- std::cerr << "\nWARNING: Unable to launch remote service manually: "
707- << error->message << "\n";
708- g_error_free(error);
709- return false;
710- }
711- return true;
712-}
713-
714-void request_sync(GDBusProxy* proxy, const char* method, GVariant* name, SyncData* data)
715-{
716- g_dbus_proxy_call(proxy, method, name, G_DBUS_CALL_FLAGS_NONE,
717- -1, data->cancel, on_sync_ready_cb, data);
718-}
719-
720-void on_sync_ready_cb(GObject* source, GAsyncResult* res, gpointer data)
721-{
722- SyncData* sync_data = reinterpret_cast<SyncData*>(data);
723- GError* error = NULL;
724- GVariant* args = g_dbus_proxy_call_finish((GDBusProxy*)source, res, &error);
725-
726- if (args == NULL)
727- {
728- g_warning("Unable to perform Sync() on panel service: %s", error->message);
729- g_error_free(error);
730- return;
731- }
732-
733- sync_data->self->Sync(args, sync_data);
734- g_variant_unref(args);
735-}
736-
737-bool send_show_entry(ShowEntryData* data)
738-{
739- g_return_val_if_fail(data != NULL, FALSE);
740- g_return_val_if_fail(G_IS_DBUS_PROXY(data->proxy.RawPtr()), FALSE);
741-
742- g_dbus_proxy_call(data->proxy,
743- "ShowEntry",
744- g_variant_new("(suiiuu)",
745- data->entry_id.c_str(),
746- data->xid,
747- data->x,
748- data->y,
749- data->button,
750- data->timestamp),
751- G_DBUS_CALL_FLAGS_NONE,
752- -1,
753- NULL,
754- NULL,
755- NULL);
756-
757- delete data;
758- return FALSE;
759-}
760-
761-bool send_show_appmenu(ShowEntryData* data)
762-{
763- g_return_val_if_fail(data != NULL, FALSE);
764- g_return_val_if_fail(G_IS_DBUS_PROXY(data->proxy.RawPtr()), FALSE);
765-
766- g_dbus_proxy_call(data->proxy,
767- "ShowAppMenu",
768- g_variant_new("(uiiu)",
769- data->xid,
770- data->x,
771- data->y,
772- data->timestamp),
773- G_DBUS_CALL_FLAGS_NONE,
774- -1,
775- NULL,
776- NULL,
777- NULL);
778-
779- delete data;
780- return FALSE;
781-}
782-
783-} // anonymous namespace
784-
785 } // namespace indicator
786 } // namespace unity
787
788=== modified file 'UnityCore/DBusIndicators.h'
789--- UnityCore/DBusIndicators.h 2012-03-20 10:16:27 +0000
790+++ UnityCore/DBusIndicators.h 2012-03-20 10:16:27 +0000
791@@ -50,15 +50,9 @@
792 virtual void OnShowAppMenu(unsigned int xid, int x, int y,
793 unsigned int timestamp);
794
795- std::string name() const;
796- std::string owner_name() const;
797- bool using_local_service() const;
798-
799- // Due to the callback nature, the Impl class must be declared public, but
800- // it is not available to anyone except the internal implementation.
801+private:
802 class Impl;
803-private:
804- Impl* pimpl;
805+ std::unique_ptr<Impl> pimpl;
806 };
807
808 }
809
810=== modified file 'UnityCore/GLibDBusProxy.cpp'
811--- UnityCore/GLibDBusProxy.cpp 2012-02-20 09:29:55 +0000
812+++ UnityCore/GLibDBusProxy.cpp 2012-03-20 10:16:27 +0000
813@@ -39,13 +39,6 @@
814
815 using std::string;
816
817-struct CallData
818-{
819- DBusProxy::ReplyCallback callback;
820- DBusProxy::Impl* impl;
821- std::string method_name;
822-};
823-
824 class DBusProxy::Impl
825 {
826 public:
827@@ -62,8 +55,7 @@
828
829 void StartReconnectionTimeout();
830 void Connect();
831- void OnProxySignal(GDBusProxy* proxy, char* sender_name, char* signal_name,
832- GVariant* parameters);
833+
834 void Call(string const& method_name,
835 GVariant* parameters,
836 ReplyCallback callback,
837@@ -74,12 +66,20 @@
838 void Connect(string const& signal_name, ReplyCallback callback);
839 bool IsConnected();
840
841- static void OnNameAppeared(GDBusConnection* connection, const char* name,
842- const char* name_owner, gpointer impl);
843- static void OnNameVanished(GDBusConnection* connection, const char* name, gpointer impl);
844+ void OnProxyNameOwnerChanged(GDBusProxy*, GParamSpec*);
845+ void OnProxySignal(GDBusProxy* proxy, char* sender_name, char* signal_name,
846+ GVariant* parameters);
847+
848 static void OnProxyConnectCallback(GObject* source, GAsyncResult* res, gpointer impl);
849 static void OnCallCallback(GObject* source, GAsyncResult* res, gpointer call_data);
850-
851+
852+ struct CallData
853+ {
854+ DBusProxy::ReplyCallback callback;
855+ DBusProxy::Impl* impl;
856+ std::string method_name;
857+ };
858+
859 DBusProxy* owner_;
860 string name_;
861 string object_path_;
862@@ -94,6 +94,7 @@
863 bool connected_;
864
865 glib::Signal<void, GDBusProxy*, char*, char*, GVariant*> g_signal_connection_;
866+ glib::Signal<void, GDBusProxy*, GParamSpec*> name_owner_signal_;
867
868 SignalHandlers handlers_;
869 };
870@@ -115,14 +116,6 @@
871 , reconnect_timeout_id_(0)
872 , connected_(false)
873 {
874- LOG_DEBUG(logger) << "Watching name " << name_;
875- watcher_id_ = g_bus_watch_name(bus_type_,
876- name.c_str(),
877- G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
878- DBusProxy::Impl::OnNameAppeared,
879- DBusProxy::Impl::OnNameVanished,
880- this,
881- NULL);
882 StartReconnectionTimeout();
883 }
884
885@@ -135,33 +128,6 @@
886 g_source_remove(reconnect_timeout_id_);
887 }
888
889-void DBusProxy::Impl::OnNameAppeared(GDBusConnection* connection,
890- const char* name,
891- const char* name_owner,
892- gpointer impl)
893-{
894- DBusProxy::Impl* self = static_cast<DBusProxy::Impl*>(impl);
895- LOG_DEBUG(logger) << self->name_ << " appeared";
896-
897- if (self->proxy_)
898- {
899- self->connected_ = true;
900- self->owner_->connected.emit();
901- }
902-}
903-
904-void DBusProxy::Impl::OnNameVanished(GDBusConnection* connection,
905- const char* name,
906- gpointer impl)
907-{
908- DBusProxy::Impl* self = static_cast<DBusProxy::Impl*>(impl);
909-
910- LOG_DEBUG(logger) << self->name_ << " vanished";
911-
912- self->connected_ = false;
913- self->owner_->disconnected.emit();
914-}
915-
916 void DBusProxy::Impl::StartReconnectionTimeout()
917 {
918 LOG_DEBUG(logger) << "Starting reconnection timeout for " << name_;
919@@ -204,6 +170,8 @@
920 GAsyncResult* res,
921 gpointer impl)
922 {
923+ DBusProxy::Impl* self = static_cast<DBusProxy::Impl*>(impl);
924+
925 glib::Error error;
926 glib::Object<GDBusProxy> proxy(g_dbus_proxy_new_for_bus_finish(res, &error));
927
928@@ -215,14 +183,44 @@
929 return;
930 }
931
932- DBusProxy::Impl* self = static_cast<DBusProxy::Impl*>(impl);
933 LOG_DEBUG(logger) << "Sucessfully created proxy: " << self->object_path_;
934
935 self->proxy_ = proxy;
936 self->g_signal_connection_.Connect(self->proxy_, "g-signal",
937- sigc::mem_fun(self, &DBusProxy::Impl::OnProxySignal));
938- self->connected_ = true;
939- self->owner_->connected.emit();
940+ sigc::mem_fun(self, &Impl::OnProxySignal));
941+ self->name_owner_signal_.Connect(self->proxy_, "notify::g-name-owner",
942+ sigc::mem_fun(self, &Impl::OnProxyNameOwnerChanged));
943+
944+ // If a proxy cannot autostart a service, it doesn't throw an error, but
945+ // sets name_owner to NULL
946+ if (glib::String(g_dbus_proxy_get_name_owner(proxy)))
947+ {
948+ self->connected_ = true;
949+ self->owner_->connected.emit();
950+ }
951+}
952+
953+void DBusProxy::Impl::OnProxyNameOwnerChanged(GDBusProxy* proxy, GParamSpec* param)
954+{
955+ glib::String name_owner(g_dbus_proxy_get_name_owner(proxy));
956+
957+ if (name_owner)
958+ {
959+ if (!connected_)
960+ {
961+ LOG_DEBUG(logger) << name_ << " appeared";
962+
963+ connected_ = true;
964+ owner_->connected.emit();
965+ }
966+ }
967+ else if (connected_)
968+ {
969+ LOG_DEBUG(logger) << name_ << " vanished";
970+
971+ connected_ = false;
972+ owner_->disconnected.emit();
973+ }
974 }
975
976 void DBusProxy::Impl::OnProxySignal(GDBusProxy* proxy,
977@@ -308,9 +306,7 @@
978 {}
979
980 DBusProxy::~DBusProxy()
981-{
982- delete pimpl;
983-}
984+{}
985
986 void DBusProxy::Call(string const& method_name,
987 GVariant* parameters,
988
989=== modified file 'UnityCore/GLibDBusProxy.h'
990--- UnityCore/GLibDBusProxy.h 2012-02-04 05:28:23 +0000
991+++ UnityCore/GLibDBusProxy.h 2012-03-20 10:16:27 +0000
992@@ -62,9 +62,9 @@
993 static void NoReplyCallback(GVariant* v) {};
994
995 // Public due to use in some callbacks
996+private:
997 class Impl;
998-private:
999- Impl* pimpl;
1000+ std::unique_ptr<Impl> pimpl;
1001 };
1002
1003 }
1004
1005=== modified file 'UnityCore/Indicators.cpp'
1006--- UnityCore/Indicators.cpp 2012-03-20 10:16:27 +0000
1007+++ UnityCore/Indicators.cpp 2012-03-20 10:16:27 +0000
1008@@ -58,13 +58,10 @@
1009
1010 Indicators::Indicators()
1011 : pimpl(new Impl(this))
1012-{
1013-}
1014+{}
1015
1016 Indicators::~Indicators()
1017-{
1018- delete pimpl;
1019-}
1020+{}
1021
1022 void Indicators::ActivateEntry(std::string const& entry_id, nux::Rect const& geometry)
1023 {
1024
1025=== modified file 'UnityCore/Indicators.h'
1026--- UnityCore/Indicators.h 2012-03-20 10:16:27 +0000
1027+++ UnityCore/Indicators.h 2012-03-20 10:16:27 +0000
1028@@ -124,7 +124,7 @@
1029
1030 private:
1031 class Impl;
1032- Impl* pimpl;
1033+ std::unique_ptr<Impl> pimpl;
1034 };
1035
1036 }
1037
1038=== modified file 'plugins/unityshell/src/PanelView.cpp'
1039--- plugins/unityshell/src/PanelView.cpp 2012-03-20 10:16:27 +0000
1040+++ plugins/unityshell/src/PanelView.cpp 2012-03-20 10:16:27 +0000
1041@@ -215,9 +215,6 @@
1042 {
1043 variant::BuilderWrapper(builder)
1044 .add("backend", "remote")
1045- .add("service-name", _remote->name())
1046- .add("service-unique-name", _remote->owner_name())
1047- .add("using-local-service", _remote->using_local_service())
1048 .add(GetGeometry());
1049 }
1050