Merge lp:~3v1n0/unity/indicators-p into lp:unity
- indicators-p
- Merge into trunk
Status: | Merged | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | Marco Trevisan (Treviño) | ||||||||||||||||
Approved revision: | no longer in the source branch. | ||||||||||||||||
Merged at revision: | 2132 | ||||||||||||||||
Proposed branch: | lp:~3v1n0/unity/indicators-p | ||||||||||||||||
Merge into: | lp:unity | ||||||||||||||||
Diff against target: |
2730 lines (+1212/-342) 31 files modified
CMakeLists.txt (+1/-1) UnityCore/AppmenuIndicator.cpp (+37/-0) UnityCore/AppmenuIndicator.h (+45/-0) UnityCore/CMakeLists.txt (+2/-0) UnityCore/DBusIndicators.cpp (+87/-38) UnityCore/DBusIndicators.h (+5/-2) UnityCore/Indicator.cpp (+31/-11) UnityCore/Indicator.h (+11/-7) UnityCore/IndicatorEntry.cpp (+29/-24) UnityCore/IndicatorEntry.h (+12/-7) UnityCore/Indicators.cpp (+28/-7) UnityCore/Indicators.h (+31/-10) plugins/unityshell/src/PanelIndicatorEntryView.cpp (+21/-7) plugins/unityshell/src/PanelIndicatorEntryView.h (+1/-0) plugins/unityshell/src/PanelIndicatorsView.cpp (+1/-1) plugins/unityshell/src/PanelIndicatorsView.h (+1/-1) plugins/unityshell/src/PanelView.cpp (+6/-5) plugins/unityshell/src/PanelView.h (+3/-3) services/CMakeLists.txt (+1/-1) services/panel-indicator-entry-accessible.c (+2/-1) services/panel-main.c (+33/-10) services/panel-marshal.list (+1/-0) services/panel-root-accessible.c (+5/-5) services/panel-service.c (+410/-165) services/panel-service.h (+11/-4) tests/CMakeLists.txt (+15/-2) tests/test_indicator.cpp (+207/-0) tests/test_indicator_appmenu.cpp (+66/-0) tests/test_indicator_entry.cpp (+99/-22) tests/unit/TestMain.cpp (+4/-4) tests/unit/TestPanelService.cpp (+6/-4) |
||||||||||||||||
To merge this branch: | bzr merge lp:~3v1n0/unity/indicators-p | ||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Thomi Richards (community) | Approve | ||
Tim Penhey (community) | Approve | ||
Andrea Azzarone (community) | Approve | ||
Michal Hruby (community) | Approve | ||
Review via email: mp+96862@code.launchpad.net |
Commit message
Updated unity-panel-service and libunity-core against the libindicator API changes
Description of the change
Updated unity-panel-service and libunity-core against the libindicator API changes
Supporting the new libindicator API into unity-panel-service and exposing them in the higher level wrapper library for future usage.
Doing this, I've performed some cleanup of the code, and in particular I've:
- Introduced the new AppmenuIndicator class to handle the appmenu indicator
(typing it differently allows us to remove the type-checking based only on the
indicator name, this is something we should keep at lower level).
- Fixed an issue in Indicator class, that didn't disconnect from signals of the removed
entries
- Removed the IsUnused / MarkUnused methods from IndicatorEntry, since they were
already deprecated since last cycle and actually useless. The visible() method can
now be used to perform a similar check.
- Removed the sscanf based matching from the panel-service.
On the unity-panel-service side I've also fixed two issues:
- When the menus are open now they are moved to the right position if their
entry has been moved (this happens when scrolling on the language selector).
- It is now synced with the compiz gsetting key used to define which keybinding
must be used to open the menus (so now, changing that value applies to both
opening and closing the indicators, not only to the open action).
On the Tests side, I've re-enabled and updated the panel-service unit-test, that now is working again, plus I've added new tests for the Indicator and AppmenuIndicator classes and updated the tests for IndicatorEntry against the new API.
Some more tests are covered on the lp:~3v1n0/unity/indicators-tests dependent branch.
Thomi Richards (thomir-deactivatedaccount) wrote : | # |
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
> 202 + // We have to do this because on certain systems X won't have time
> to
> 203 + // respond to our request for XUngrabPointer and this will cause the
> 204 + // menu not to show
> 205 + auto data = new ShowEntryData();
>
> Can we use a smart pointer for this please? Once you use a smart pointer you
> won't need this:
>
> 279 + delete data;
Mh, I didn't used these, not to change too much the pre-existent code.
> ...and there's a larger design issue around how we create Indicator instances.
> This code:
>
> 671 - Indicator::Ptr indicator(new Indicator(name));
> 672 + Indicator* indptr;
> 673 +
> 674 + if (name == "libappmenu.so")
> 675 + indptr = new AppmenuIndicato
> 676 + else
> 677 + indptr = new Indicator(name);
> 678 +
> 679 + Indicator::Ptr indicator(indptr);
>
> Makes me uneasy - especially this bit:
>
> 685 +
> 686 + if (indicator-
> 687 + {
> 688 + AppmenuIndicator *appmenu =
> dynamic_
> 689 +
> 690 + if (appmenu)
> 691 + appmenu-
> &Indicators:
> 692 + }
> 693 +
>
> Why are we using a boolean member variable to encode class type? Maybe I'm
> missing something, but why not just do this:
>
> AppmenuIndicator *appmenu = dynamic_
Using that bool check is faster than doing an unneeded dymamic_cast (actually we could even use just a static_cast there). And currently we only have two kinds of indicators that we must care of, standard indicators and appmenu indicators. Maybe we could use a GetType or something...
> if (appmenu)
> appmenu-
> &Indicators:
>
> ..or even better, hook up the signal for all indicators, and have child
> classes that don't need the signal simply not use it.
Mh, I don't like too much the idea of adding a signal that is not related to all the indicators to the Indicator class. Also because that class will be filled with some other stuff soon, and I don't want to repeat them in the base class...
> This is wrong:
>
> 818 + return proxy_-
>
> The method returns a std::string, so you don't need the ".c_str" on the end.
True. The mistake was already there, but I didn't notice it. Thanks.
> These:
>
> 1127 +#define COMPIZ_OPTIONS_PATH
> "/apps/
> 1128 +#define MENU_TOGGLE_
> COMPIZ_
>
> Don't need to be #defines - nor do the three #defines right above them.
Mh... In a C scope they don't look so bad... Also I should repeat some strings without them.
> In panel-service.c, I'm 99% sure there's a memory leak on line 829, where we
> do this:
>
> gchar *entry_id = get_indicator_
> g_hash_table_insert (self->
>
> entry_id needs to be freed.
Not really: http://
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
> > This is wrong:
> >
> > 818 + return proxy_-
> >
> > The method returns a std::string, so you don't need the ".c_str" on the end.
>
> True. The mistake was already there, but I didn't notice it. Thanks.
Ah, actually I already fixed in another branch... I put the fix here too.
Andrea Azzarone (azzar1) wrote : | # |
671 - Indicator::Ptr indicator(new Indicator(name));
672 + Indicator* indptr;
673 +
674 + if (name == "libappmenu.so")
675 + indptr = new AppmenuIndicato
676 + else
677 + indptr = new Indicator(name);
678 +
679 + Indicator::Ptr indicator(indptr);
It's a kind of object factory, for me it's ok.
685 +
686 + if (indicator-
687 + {
688 + AppmenuIndicator *appmenu = dynamic_
689 +
690 + if (appmenu)
691 + appmenu-
692 + }
693 +
If you can remove this please do... :) Otherwise it's ok for me.
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
> 685 +
> 686 + if (indicator-
> 687 + {
> 688 + AppmenuIndicator *appmenu =
> dynamic_
> 689 +
> 690 + if (appmenu)
> 691 + appmenu-
> &Indicators:
> 692 + }
> 693 +
>
> If you can remove this please do... :) Otherwise it's ok for me.
Yes, done. It was possible to get that before as well, but I didn't like to connect to the appmenu specific signal before than the others :)
Michal Hruby (mhr3) wrote : | # |
183 data->proxy = proxy_;
Makes me sad that it doesn't use the dbus proxy class from unity core.
194 + g_idle_add_full (G_PRIORITY_
Moreover this is pretty dangerous, it should at least grab a ref on the proxy. Alternatively such timeouts should be removed in the destructor.
1114 +#include <fcntl.h>
I hope this isn't needed?
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
> 183 data->proxy = proxy_;
>
> Makes me sad that it doesn't use the dbus proxy class from unity core.
Yes, you're right.
Unfortunately that code was written before it was available I guess, so I just didn't rewrite the whole thing.
I see if that's quickly feasible ;)
> 194 + g_idle_add_full (G_PRIORITY_
> data, NULL);
>
> Moreover this is pretty dangerous, it should at least grab a ref on the proxy.
> Alternatively such timeouts should be removed in the destructor.
Sure, again... I just followed the old school! :)
> 1114 +#include <fcntl.h>
>
> I hope this isn't needed?
Yes, no more needed. /me cleaning it.
Michal Hruby (mhr3) wrote : | # |
> DBusIndicators: use glib::Object to handle the dbus proxy, so we have ref-counting for free
So much nicer, thx!
Andrea Azzarone (azzar1) : | # |
Tim Penhey (thumper) wrote : | # |
Gah... I was wanting to work out how to remove the IsAppmenu bit, but since the cure is worse than the symptoms, I'm prepared to accept it.
Thomi Richards (thomir-deactivatedaccount) : | # |
Unity Merger (unity-merger) wrote : | # |
Attempt to merge into lp:unity failed due to conflicts:
text conflict in CMakeLists.txt
text conflict in plugins/
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2012-03-13 11:57:33 +0000 |
3 | +++ CMakeLists.txt 2012-03-20 10:02:20 +0000 |
4 | @@ -122,7 +122,7 @@ |
5 | # |
6 | # Compiz Plugins |
7 | # |
8 | -set (UNITY_PLUGIN_DEPS "compiz;nux-2.0>=2.0.0;libbamf3;dee-1.0;gio-2.0;gio-unix-2.0;dbusmenu-glib-0.4;x11;libstartup-notification-1.0;gthread-2.0;indicator3-0.4;atk;unity-misc>=0.4.0;gconf-2.0;libutouch-geis;gtk+-3.0>=3.1;sigc++-2.0;json-glib-1.0;libnotify;gnome-desktop-3.0;gdu;xfixes") |
9 | +set (UNITY_PLUGIN_DEPS "compiz;nux-2.0>=2.0.0;libbamf3;dee-1.0;gio-2.0;gio-unix-2.0;dbusmenu-glib-0.4;x11;libstartup-notification-1.0;gthread-2.0;indicator3-0.4>=0.4.90;atk;unity-misc>=0.4.0;gconf-2.0;libutouch-geis;gtk+-3.0>=3.1;sigc++-2.0;json-glib-1.0;libnotify;gnome-desktop-3.0;gdu;xfixes") |
10 | |
11 | add_subdirectory(plugins/unityshell) |
12 | add_subdirectory(plugins/gtkloader) |
13 | |
14 | === added file 'UnityCore/AppmenuIndicator.cpp' |
15 | --- UnityCore/AppmenuIndicator.cpp 1970-01-01 00:00:00 +0000 |
16 | +++ UnityCore/AppmenuIndicator.cpp 2012-03-20 10:02:20 +0000 |
17 | @@ -0,0 +1,37 @@ |
18 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
19 | +/* |
20 | + * Copyright (C) 2012 Canonical Ltd |
21 | + * |
22 | + * This program is free software: you can redistribute it and/or modify |
23 | + * it under the terms of the GNU General Public License version 3 as |
24 | + * published by the Free Software Foundation. |
25 | + * |
26 | + * This program is distributed in the hope that it will be useful, |
27 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
28 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
29 | + * GNU General Public License for more details. |
30 | + * |
31 | + * You should have received a copy of the GNU General Public License |
32 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
33 | + * |
34 | + * Authored by: Marco Trevisan (Treviño) <3v1n0@ubuntu.com> |
35 | + */ |
36 | + |
37 | +#include "AppmenuIndicator.h" |
38 | + |
39 | +namespace unity |
40 | +{ |
41 | +namespace indicator |
42 | +{ |
43 | + |
44 | +AppmenuIndicator::AppmenuIndicator(std::string const& name) |
45 | + : Indicator(name) |
46 | +{} |
47 | + |
48 | +void AppmenuIndicator::ShowAppmenu(unsigned int xid, int x, int y, unsigned int timestamp) const |
49 | +{ |
50 | + on_show_appmenu.emit(xid, x, y, timestamp); |
51 | +} |
52 | + |
53 | +} // namespace indicator |
54 | +} // namespace unity |
55 | |
56 | === added file 'UnityCore/AppmenuIndicator.h' |
57 | --- UnityCore/AppmenuIndicator.h 1970-01-01 00:00:00 +0000 |
58 | +++ UnityCore/AppmenuIndicator.h 2012-03-20 10:02:20 +0000 |
59 | @@ -0,0 +1,45 @@ |
60 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
61 | +/* |
62 | + * Copyright (C) 2012 Canonical Ltd |
63 | + * |
64 | + * This program is free software: you can redistribute it and/or modify |
65 | + * it under the terms of the GNU General Public License version 3 as |
66 | + * published by the Free Software Foundation. |
67 | + * |
68 | + * This program is distributed in the hope that it will be useful, |
69 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
70 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
71 | + * GNU General Public License for more details. |
72 | + * |
73 | + * You should have received a copy of the GNU General Public License |
74 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
75 | + * |
76 | + * Authored by: Marco Trevisan (Treviño) <3v1n0@ubuntu.com> |
77 | + */ |
78 | + |
79 | +#ifndef UNITY_APPMENU_INDICATOR_H |
80 | +#define UNITY_APPMENU_INDICATOR_H |
81 | + |
82 | +#include "Indicator.h" |
83 | + |
84 | +namespace unity |
85 | +{ |
86 | +namespace indicator |
87 | +{ |
88 | + |
89 | +class AppmenuIndicator : public Indicator |
90 | +{ |
91 | +public: |
92 | + AppmenuIndicator(std::string const& name); |
93 | + |
94 | + virtual bool IsAppmenu() const { return true; } |
95 | + |
96 | + void ShowAppmenu(unsigned int xid, int x, int y, unsigned int timestamp) const; |
97 | + |
98 | + sigc::signal<void, unsigned int, int, int, unsigned int> on_show_appmenu; |
99 | +}; |
100 | + |
101 | +} |
102 | +} |
103 | + |
104 | +#endif // UNITY_APPMENU_INDICATOR_H |
105 | |
106 | === modified file 'UnityCore/CMakeLists.txt' |
107 | --- UnityCore/CMakeLists.txt 2012-02-07 07:42:12 +0000 |
108 | +++ UnityCore/CMakeLists.txt 2012-03-20 10:02:20 +0000 |
109 | @@ -8,6 +8,7 @@ |
110 | # |
111 | set (CORE_HEADERS |
112 | ApplicationPreview.h |
113 | + AppmenuIndicator.h |
114 | Categories.h |
115 | Category.h |
116 | CheckOptionFilter.h |
117 | @@ -44,6 +45,7 @@ |
118 | |
119 | set (CORE_SOURCES |
120 | ApplicationPreview.cpp |
121 | + AppmenuIndicator.cpp |
122 | Categories.cpp |
123 | Category.cpp |
124 | CheckOptionFilter.cpp |
125 | |
126 | === modified file 'UnityCore/DBusIndicators.cpp' |
127 | --- UnityCore/DBusIndicators.cpp 2012-02-09 10:33:04 +0000 |
128 | +++ UnityCore/DBusIndicators.cpp 2012-03-20 10:02:20 +0000 |
129 | @@ -79,12 +79,13 @@ |
130 | |
131 | struct ShowEntryData |
132 | { |
133 | - GDBusProxy* proxy; |
134 | + glib::Object<GDBusProxy> proxy; |
135 | std::string entry_id; |
136 | + guint xid; |
137 | int x; |
138 | int y; |
139 | + guint button; |
140 | guint timestamp; |
141 | - guint32 button; |
142 | }; |
143 | |
144 | bool run_local_panel_service(); |
145 | @@ -95,6 +96,7 @@ |
146 | void on_sync_ready_cb(GObject* source, GAsyncResult* res, gpointer data); |
147 | |
148 | bool send_show_entry(ShowEntryData* data); |
149 | +bool send_show_appmenu(ShowEntryData* data); |
150 | |
151 | } // anonymous namespace |
152 | |
153 | @@ -105,7 +107,6 @@ |
154 | { |
155 | public: |
156 | Impl(DBusIndicators* owner); |
157 | - ~Impl(); |
158 | |
159 | void OnRemoteProxyReady(GDBusProxy* proxy); |
160 | void Reconnect(); |
161 | @@ -121,17 +122,20 @@ |
162 | GVariant* parameters); |
163 | |
164 | virtual void OnEntryScroll(std::string const& entry_id, int delta); |
165 | - virtual void OnEntryShowMenu(std::string const& entry_id, |
166 | - int x, int y, int timestamp, int button); |
167 | + virtual void OnEntryShowMenu(std::string const& entry_id, unsigned int xid, |
168 | + int x, int y, unsigned int button, |
169 | + unsigned int timestamp); |
170 | virtual void OnEntrySecondaryActivate(std::string const& entry_id, |
171 | unsigned int timestamp); |
172 | + virtual void OnShowAppMenu(unsigned int xid, int x, int y, |
173 | + unsigned int timestamp); |
174 | |
175 | std::string name() const; |
176 | std::string owner_name() const; |
177 | bool using_local_service() const; |
178 | |
179 | DBusIndicators* owner_; |
180 | - GDBusProxy* proxy_; |
181 | + glib::Object<GDBusProxy> proxy_; |
182 | typedef std::vector<SyncDataPtr> PendingSyncs; |
183 | PendingSyncs pending_syncs_; |
184 | |
185 | @@ -143,19 +147,10 @@ |
186 | // Public Methods |
187 | DBusIndicators::Impl::Impl(DBusIndicators* owner) |
188 | : owner_(owner) |
189 | - , proxy_(NULL) |
190 | { |
191 | Reconnect(); |
192 | } |
193 | |
194 | -DBusIndicators::Impl::~Impl() |
195 | -{ |
196 | - if (G_IS_OBJECT(proxy_)) |
197 | - { |
198 | - g_object_unref(proxy_); |
199 | - } |
200 | -} |
201 | - |
202 | void DBusIndicators::Impl::Reconnect() |
203 | { |
204 | g_spawn_command_line_sync("killall -9 unity-panel-service", |
205 | @@ -212,22 +207,43 @@ |
206 | |
207 | |
208 | void DBusIndicators::Impl::OnEntryShowMenu(std::string const& entry_id, |
209 | - int x, int y, int timestamp, int button) |
210 | + unsigned int xid, int x, int y, |
211 | + unsigned int button, |
212 | + unsigned int timestamp) |
213 | { |
214 | - owner_->on_entry_show_menu.emit(entry_id, x, y, timestamp, button); |
215 | + owner_->on_entry_show_menu.emit(entry_id, xid, x, y, button, timestamp); |
216 | |
217 | // We have to do this because on certain systems X won't have time to |
218 | // respond to our request for XUngrabPointer and this will cause the |
219 | // menu not to show |
220 | - ShowEntryData* data = new ShowEntryData(); |
221 | + auto data = new ShowEntryData(); |
222 | data->proxy = proxy_; |
223 | data->entry_id = entry_id; |
224 | + data->xid = xid; |
225 | data->x = x; |
226 | data->y = y; |
227 | - data->timestamp = timestamp; |
228 | data->button = button; |
229 | - |
230 | - g_idle_add_full (G_PRIORITY_DEFAULT, (GSourceFunc)send_show_entry, data, NULL); |
231 | + data->timestamp = timestamp; |
232 | + |
233 | + g_idle_add_full (G_PRIORITY_DEFAULT, (GSourceFunc) send_show_entry, data, NULL); |
234 | +} |
235 | + |
236 | +void DBusIndicators::Impl::OnShowAppMenu(unsigned int xid, int x, int y, |
237 | + unsigned int timestamp) |
238 | +{ |
239 | + owner_->on_show_appmenu.emit(xid, x, y, timestamp); |
240 | + |
241 | + // We have to do this because on certain systems X won't have time to |
242 | + // respond to our request for XUngrabPointer and this will cause the |
243 | + // menu not to show |
244 | + auto data = new ShowEntryData(); |
245 | + data->proxy = proxy_; |
246 | + data->xid = xid; |
247 | + data->x = x; |
248 | + data->y = y; |
249 | + data->timestamp = timestamp; |
250 | + |
251 | + g_idle_add_full (G_PRIORITY_DEFAULT, (GSourceFunc) send_show_appmenu, data, NULL); |
252 | } |
253 | |
254 | void DBusIndicators::Impl::OnEntrySecondaryActivate(std::string const& entry_id, |
255 | @@ -457,10 +473,13 @@ |
256 | std::string signal_name(signal_name_); |
257 | if (signal_name == "EntryActivated") |
258 | { |
259 | - const char* entry_name = g_variant_get_string(g_variant_get_child_value(parameters, 0), NULL); |
260 | + glib::String entry_name; |
261 | + nux::Rect geo; |
262 | + g_variant_get(parameters, "(s(iiuu))", &entry_name, &geo.x, &geo.y, &geo.width, &geo.height); |
263 | + |
264 | if (entry_name) |
265 | { |
266 | - owner_->ActivateEntry(entry_name); |
267 | + owner_->ActivateEntry(entry_name.Str(), geo); |
268 | } |
269 | } |
270 | else if (signal_name == "EntryActivateRequest") |
271 | @@ -499,8 +518,7 @@ |
272 | |
273 | DBusIndicators::DBusIndicators() |
274 | : pimpl(new Impl(this)) |
275 | -{ |
276 | -} |
277 | +{} |
278 | |
279 | DBusIndicators::~DBusIndicators() |
280 | { |
281 | @@ -519,9 +537,10 @@ |
282 | } |
283 | |
284 | void DBusIndicators::OnEntryShowMenu(std::string const& entry_id, |
285 | - int x, int y, int timestamp, int button) |
286 | + unsigned int xid, int x, int y, |
287 | + unsigned int button, unsigned int timestamp) |
288 | { |
289 | - pimpl->OnEntryShowMenu(entry_id, x, y, timestamp, button); |
290 | + pimpl->OnEntryShowMenu(entry_id, xid, x, y, button, timestamp); |
291 | } |
292 | |
293 | void DBusIndicators::OnEntrySecondaryActivate(std::string const& entry_id, |
294 | @@ -530,6 +549,12 @@ |
295 | pimpl->OnEntrySecondaryActivate(entry_id, timestamp); |
296 | } |
297 | |
298 | +void DBusIndicators::OnShowAppMenu(unsigned int xid, int x, int y, |
299 | + unsigned int timestamp) |
300 | +{ |
301 | + pimpl->OnShowAppMenu(xid, x, y, timestamp); |
302 | +} |
303 | + |
304 | std::string DBusIndicators::name() const |
305 | { |
306 | return pimpl->name(); |
307 | @@ -651,21 +676,45 @@ |
308 | bool send_show_entry(ShowEntryData* data) |
309 | { |
310 | g_return_val_if_fail(data != NULL, FALSE); |
311 | - g_return_val_if_fail(G_IS_DBUS_PROXY(data->proxy), FALSE); |
312 | + g_return_val_if_fail(G_IS_DBUS_PROXY(data->proxy.RawPtr()), FALSE); |
313 | |
314 | g_dbus_proxy_call(data->proxy, |
315 | "ShowEntry", |
316 | - g_variant_new("(suiii)", |
317 | + g_variant_new("(suiiuu)", |
318 | data->entry_id.c_str(), |
319 | - 0, |
320 | - data->x, |
321 | - data->y, |
322 | - data->button), |
323 | - G_DBUS_CALL_FLAGS_NONE, |
324 | - -1, |
325 | - NULL, |
326 | - NULL, |
327 | - NULL); |
328 | + data->xid, |
329 | + data->x, |
330 | + data->y, |
331 | + data->button, |
332 | + data->timestamp), |
333 | + G_DBUS_CALL_FLAGS_NONE, |
334 | + -1, |
335 | + NULL, |
336 | + NULL, |
337 | + NULL); |
338 | + |
339 | + delete data; |
340 | + return FALSE; |
341 | +} |
342 | + |
343 | +bool send_show_appmenu(ShowEntryData* data) |
344 | +{ |
345 | + g_return_val_if_fail(data != NULL, FALSE); |
346 | + g_return_val_if_fail(G_IS_DBUS_PROXY(data->proxy.RawPtr()), FALSE); |
347 | + |
348 | + g_dbus_proxy_call(data->proxy, |
349 | + "ShowAppMenu", |
350 | + g_variant_new("(uiiu)", |
351 | + data->xid, |
352 | + data->x, |
353 | + data->y, |
354 | + data->timestamp), |
355 | + G_DBUS_CALL_FLAGS_NONE, |
356 | + -1, |
357 | + NULL, |
358 | + NULL, |
359 | + NULL); |
360 | + |
361 | delete data; |
362 | return FALSE; |
363 | } |
364 | |
365 | === modified file 'UnityCore/DBusIndicators.h' |
366 | --- UnityCore/DBusIndicators.h 2011-07-29 07:15:54 +0000 |
367 | +++ UnityCore/DBusIndicators.h 2012-03-20 10:02:20 +0000 |
368 | @@ -42,10 +42,13 @@ |
369 | EntryLocationMap const& locations); |
370 | |
371 | virtual void OnEntryScroll(std::string const& entry_id, int delta); |
372 | - virtual void OnEntryShowMenu(std::string const& entry_id, |
373 | - int x, int y, int timestamp, int button); |
374 | + virtual void OnEntryShowMenu(std::string const& entry_id, unsigned int xid, |
375 | + int x, int y, unsigned int button, |
376 | + unsigned int timestamp); |
377 | virtual void OnEntrySecondaryActivate(std::string const& entry_id, |
378 | unsigned int timestamp); |
379 | + virtual void OnShowAppMenu(unsigned int xid, int x, int y, |
380 | + unsigned int timestamp); |
381 | |
382 | std::string name() const; |
383 | std::string owner_name() const; |
384 | |
385 | === modified file 'UnityCore/Indicator.cpp' |
386 | --- UnityCore/Indicator.cpp 2011-09-06 00:19:51 +0000 |
387 | +++ UnityCore/Indicator.cpp 2012-03-20 10:02:20 +0000 |
388 | @@ -35,11 +35,18 @@ |
389 | |
390 | Indicator::~Indicator() |
391 | { |
392 | - for (auto entry : entries_) { |
393 | - on_entry_removed(entry->id()); |
394 | - } |
395 | + for (auto entry : entries_) |
396 | + on_entry_removed.emit(entry->id()); |
397 | |
398 | entries_.clear(); |
399 | + |
400 | + for (auto it : entries_connections_) |
401 | + { |
402 | + for (auto conn : it.second) |
403 | + conn.disconnect(); |
404 | + |
405 | + it.second.clear(); |
406 | + } |
407 | } |
408 | |
409 | std::string const& Indicator::name() const |
410 | @@ -72,7 +79,12 @@ |
411 | } |
412 | |
413 | for (auto entry : to_rm) { |
414 | - on_entry_removed(entry->id()); |
415 | + for (auto conn : entries_connections_[entry]) |
416 | + conn.disconnect(); |
417 | + |
418 | + entries_connections_[entry].clear(); |
419 | + |
420 | + on_entry_removed.emit(entry->id()); |
421 | entries_.remove(entry); |
422 | } |
423 | |
424 | @@ -82,10 +94,19 @@ |
425 | continue; |
426 | |
427 | // Just add the new entry, and connect it up. |
428 | - new_entry->on_show_menu.connect(sigc::mem_fun(this, &Indicator::OnEntryShowMenu)); |
429 | - new_entry->on_secondary_activate.connect(sigc::mem_fun(this, &Indicator::OnEntrySecondaryActivate)); |
430 | - new_entry->on_scroll.connect(sigc::mem_fun(this, &Indicator::OnEntryScroll)); |
431 | + sigc::connection conn; |
432 | + std::vector<sigc::connection>& new_entry_connections = entries_connections_[new_entry]; |
433 | + |
434 | + conn = new_entry->on_show_menu.connect(sigc::mem_fun(this, &Indicator::OnEntryShowMenu)); |
435 | + new_entry_connections.push_back(conn); |
436 | + |
437 | + conn = new_entry->on_secondary_activate.connect(sigc::mem_fun(this, &Indicator::OnEntrySecondaryActivate)); |
438 | + new_entry_connections.push_back(conn); |
439 | + |
440 | + conn = new_entry->on_scroll.connect(sigc::mem_fun(this, &Indicator::OnEntryScroll)); |
441 | entries_.push_back(new_entry); |
442 | + new_entry_connections.push_back(conn); |
443 | + |
444 | on_entry_added.emit(new_entry); |
445 | } |
446 | } |
447 | @@ -99,11 +120,10 @@ |
448 | return Entry::Ptr(); |
449 | } |
450 | |
451 | -void Indicator::OnEntryShowMenu(std::string const& entry_id, |
452 | - int x, int y, |
453 | - int timestamp, int button) |
454 | +void Indicator::OnEntryShowMenu(std::string const& entry_id, unsigned int xid, |
455 | + int x, int y, unsigned int button, unsigned int timestamp) |
456 | { |
457 | - on_show_menu.emit(entry_id, x, y, timestamp, button); |
458 | + on_show_menu.emit(entry_id, xid, x, y, button, timestamp); |
459 | } |
460 | |
461 | void Indicator::OnEntrySecondaryActivate(std::string const& entry_id, |
462 | |
463 | === modified file 'UnityCore/Indicator.h' |
464 | --- UnityCore/Indicator.h 2011-09-06 00:19:51 +0000 |
465 | +++ UnityCore/Indicator.h 2012-03-20 10:02:20 +0000 |
466 | @@ -23,6 +23,7 @@ |
467 | |
468 | #include <vector> |
469 | #include <boost/utility.hpp> |
470 | +#include <sigc++/connection.h> |
471 | |
472 | #include "IndicatorEntry.h" |
473 | |
474 | @@ -39,28 +40,31 @@ |
475 | typedef std::list<Entry::Ptr> Entries; |
476 | |
477 | Indicator(std::string const& name); |
478 | - ~Indicator(); |
479 | + virtual ~Indicator(); |
480 | |
481 | std::string const& name() const; |
482 | |
483 | + virtual bool IsAppmenu() const { return false; } |
484 | + |
485 | void Sync(Entries const& new_entries); |
486 | Entry::Ptr GetEntry(std::string const& entry_id) const; |
487 | Entries GetEntries() const; |
488 | |
489 | - void OnEntryShowMenu(std::string const& entry_id, int x, int y, int timestamp, int button); |
490 | - void OnEntrySecondaryActivate(std::string const& entry_id, unsigned int timestamp); |
491 | - void OnEntryScroll(std::string const& entry_id, int delta); |
492 | - |
493 | // Signals |
494 | sigc::signal<void, Entry::Ptr const&> on_entry_added; |
495 | sigc::signal<void, std::string const&> on_entry_removed; |
496 | - sigc::signal<void, std::string const&, int, int, int, int> on_show_menu; |
497 | + sigc::signal<void, std::string const&, unsigned int, int, int, unsigned int, unsigned int> on_show_menu; |
498 | sigc::signal<void, std::string const&, unsigned int> on_secondary_activate; |
499 | sigc::signal<void, std::string const&, int> on_scroll; |
500 | |
501 | -private: |
502 | +protected: |
503 | + void OnEntryShowMenu(std::string const& entry_id, unsigned int xid, int x, int y, unsigned int button, unsigned int timestamp); |
504 | + void OnEntrySecondaryActivate(std::string const& entry_id, unsigned int timestamp); |
505 | + void OnEntryScroll(std::string const& entry_id, int delta); |
506 | + |
507 | Entries entries_; |
508 | std::string name_; |
509 | + std::map<Entry::Ptr, std::vector<sigc::connection>> entries_connections_; |
510 | |
511 | friend std::ostream& operator<<(std::ostream& out, Indicator const& i); |
512 | }; |
513 | |
514 | === modified file 'UnityCore/IndicatorEntry.cpp' |
515 | --- UnityCore/IndicatorEntry.cpp 2011-08-09 12:21:18 +0000 |
516 | +++ UnityCore/IndicatorEntry.cpp 2012-03-20 10:02:20 +0000 |
517 | @@ -27,8 +27,6 @@ |
518 | namespace indicator |
519 | { |
520 | |
521 | -std::string const Entry::UNUSED_ID("|"); |
522 | - |
523 | Entry::Entry(std::string const& id, |
524 | std::string const &name_hint, |
525 | std::string const& label, |
526 | @@ -104,6 +102,12 @@ |
527 | return priority_; |
528 | } |
529 | |
530 | +bool Entry::visible() const |
531 | +{ |
532 | + return ((label_visible_ && !label_.empty()) || |
533 | + (image_type_ != 0 && image_visible_ && !image_data_.empty())); |
534 | +} |
535 | + |
536 | void Entry::set_active(bool active) |
537 | { |
538 | if (active_ == active) |
539 | @@ -114,6 +118,16 @@ |
540 | updated.emit(); |
541 | } |
542 | |
543 | +void Entry::set_geometry(nux::Rect const& geometry) |
544 | +{ |
545 | + if (geometry_ == geometry) |
546 | + return; |
547 | + |
548 | + geometry_ = geometry; |
549 | + geometry_changed.emit(geometry); |
550 | + updated.emit(); |
551 | +} |
552 | + |
553 | void Entry::setLabel(std::string const& label, bool sensitive, bool visible) |
554 | { |
555 | if (label_ == label && sensitive == label_sensitive_ && visible == label_visible_) |
556 | @@ -154,6 +168,11 @@ |
557 | return active_; |
558 | } |
559 | |
560 | +nux::Rect const& Entry::geometry() const |
561 | +{ |
562 | + return geometry_; |
563 | +} |
564 | + |
565 | Entry& Entry::operator=(Entry const& rhs) |
566 | { |
567 | id_ = rhs.id_; |
568 | @@ -186,28 +205,14 @@ |
569 | updated.emit(); |
570 | } |
571 | |
572 | -void Entry::MarkUnused() |
573 | -{ |
574 | - id_ = UNUSED_ID; |
575 | - name_hint_ = ""; |
576 | - label_ = ""; |
577 | - label_sensitive_ = false; |
578 | - label_visible_ = false; |
579 | - image_type_ = 0; |
580 | - image_data_ = ""; |
581 | - image_sensitive_ = false; |
582 | - image_visible_ = false; |
583 | - updated.emit(); |
584 | -} |
585 | - |
586 | -bool Entry::IsUnused() const |
587 | -{ |
588 | - return id_ == UNUSED_ID; |
589 | -} |
590 | - |
591 | -void Entry::ShowMenu(int x, int y, int timestamp, int button) |
592 | -{ |
593 | - on_show_menu.emit(id_, x, y, timestamp, button); |
594 | +void Entry::ShowMenu(int x, int y, unsigned int button, unsigned int timestamp) |
595 | +{ |
596 | + ShowMenu(0, x, y, button, timestamp); |
597 | +} |
598 | + |
599 | +void Entry::ShowMenu(unsigned int xid, int x, int y, unsigned int button, unsigned int timestamp) |
600 | +{ |
601 | + on_show_menu.emit(id_, xid, x, y, button, timestamp); |
602 | } |
603 | |
604 | void Entry::SecondaryActivate(unsigned int timestamp) |
605 | |
606 | === modified file 'UnityCore/IndicatorEntry.h' |
607 | --- UnityCore/IndicatorEntry.h 2011-08-09 12:21:18 +0000 |
608 | +++ UnityCore/IndicatorEntry.h 2012-03-20 10:02:20 +0000 |
609 | @@ -28,7 +28,7 @@ |
610 | #include <sigc++/signal.h> |
611 | #include <boost/shared_ptr.hpp> |
612 | |
613 | -#include "NuxCore/Rect.h" |
614 | +#include <NuxCore/Rect.h> |
615 | |
616 | namespace unity |
617 | { |
618 | @@ -43,7 +43,6 @@ |
619 | { |
620 | public: |
621 | typedef boost::shared_ptr<Entry> Ptr; |
622 | - static std::string const UNUSED_ID; |
623 | |
624 | Entry(std::string const& id, |
625 | std::string const& name_hint, |
626 | @@ -72,8 +71,13 @@ |
627 | void set_active(bool active); |
628 | bool active() const; |
629 | |
630 | + void set_geometry(nux::Rect const& geometry); |
631 | + nux::Rect const& geometry() const; |
632 | + |
633 | int priority() const; |
634 | |
635 | + bool visible() const; |
636 | + |
637 | /** |
638 | * Whether this entry should be shown to the user. |
639 | * Example uses: Application menubar items are only shown when the user |
640 | @@ -82,10 +86,8 @@ |
641 | bool show_now() const; |
642 | void set_show_now(bool show_now); |
643 | |
644 | - void MarkUnused(); |
645 | - bool IsUnused() const; |
646 | - |
647 | - void ShowMenu(int x, int y, int timestamp, int button); |
648 | + void ShowMenu(int x, int y, unsigned int button, unsigned int timestamp); |
649 | + void ShowMenu(unsigned int xid, int x, int y, unsigned int button, unsigned int timestamp); |
650 | void SecondaryActivate(unsigned int timestamp); |
651 | void Scroll(int delta); |
652 | |
653 | @@ -96,9 +98,10 @@ |
654 | // Signals |
655 | sigc::signal<void> updated; |
656 | sigc::signal<void, bool> active_changed; |
657 | + sigc::signal<void, nux::Rect const&> geometry_changed; |
658 | sigc::signal<void, bool> show_now_changed; |
659 | |
660 | - sigc::signal<void, std::string const&, int, int, int, int> on_show_menu; |
661 | + sigc::signal<void, std::string const&, unsigned int, int, int, unsigned int, unsigned int> on_show_menu; |
662 | sigc::signal<void, std::string const&, unsigned int> on_secondary_activate; |
663 | sigc::signal<void, std::string const&, int> on_scroll; |
664 | |
665 | @@ -118,6 +121,8 @@ |
666 | |
667 | bool show_now_; |
668 | bool active_; |
669 | + |
670 | + nux::Rect geometry_; |
671 | }; |
672 | |
673 | std::ostream& operator<<(std::ostream& out, Entry const& e); |
674 | |
675 | === modified file 'UnityCore/Indicators.cpp' |
676 | --- UnityCore/Indicators.cpp 2011-09-05 13:21:08 +0000 |
677 | +++ UnityCore/Indicators.cpp 2012-03-20 10:02:20 +0000 |
678 | @@ -17,8 +17,9 @@ |
679 | * Authored by: Neil Jagdish Patel <neil.patel@canonical.com> |
680 | * Tim Penhey <tim.penhey@canonical.com> |
681 | */ |
682 | + |
683 | #include "Indicators.h" |
684 | - |
685 | +#include "AppmenuIndicator.h" |
686 | |
687 | namespace unity |
688 | { |
689 | @@ -35,7 +36,7 @@ |
690 | : owner_(owner) |
691 | {} |
692 | |
693 | - void ActivateEntry(std::string const& entry_id); |
694 | + void ActivateEntry(std::string const& entry_id, nux::Rect const& geometry); |
695 | void SetEntryShowNow(std::string const& entry_id, bool show_now); |
696 | |
697 | IndicatorsList GetIndicators() const; |
698 | @@ -65,10 +66,10 @@ |
699 | delete pimpl; |
700 | } |
701 | |
702 | -void Indicators::ActivateEntry(std::string const& entry_id) |
703 | +void Indicators::ActivateEntry(std::string const& entry_id, nux::Rect const& geometry) |
704 | { |
705 | - pimpl->ActivateEntry(entry_id); |
706 | - on_entry_activated.emit(entry_id); |
707 | + pimpl->ActivateEntry(entry_id, geometry); |
708 | + on_entry_activated.emit(entry_id, geometry); |
709 | } |
710 | |
711 | void Indicators::SetEntryShowNow(std::string const& entry_id, bool show_now) |
712 | @@ -96,13 +97,19 @@ |
713 | return pimpl->RemoveIndicator(name); |
714 | } |
715 | |
716 | -void Indicators::Impl::ActivateEntry(std::string const& entry_id) |
717 | +void Indicators::Impl::ActivateEntry(std::string const& entry_id, nux::Rect const& geometry) |
718 | { |
719 | if (active_entry_) |
720 | + { |
721 | + active_entry_->set_geometry(nux::Rect()); |
722 | active_entry_->set_active(false); |
723 | + } |
724 | + |
725 | active_entry_ = GetEntry(entry_id); |
726 | + |
727 | if (active_entry_) |
728 | { |
729 | + active_entry_->set_geometry(geometry); |
730 | active_entry_->set_active(true); |
731 | } |
732 | } |
733 | @@ -131,12 +138,26 @@ |
734 | |
735 | Indicator::Ptr Indicators::Impl::AddIndicator(std::string const& name) |
736 | { |
737 | - Indicator::Ptr indicator(new Indicator(name)); |
738 | + Indicator* indptr; |
739 | + |
740 | + if (name == "libappmenu.so") |
741 | + { |
742 | + AppmenuIndicator *appmenu = new AppmenuIndicator(name); |
743 | + appmenu->on_show_appmenu.connect(sigc::mem_fun(owner_, &Indicators::OnShowAppMenu)); |
744 | + indptr = appmenu; |
745 | + } |
746 | + else |
747 | + { |
748 | + indptr = new Indicator(name); |
749 | + } |
750 | + |
751 | + Indicator::Ptr indicator(indptr); |
752 | |
753 | // The owner Indicators class is interested in the other events. |
754 | indicator->on_show_menu.connect(sigc::mem_fun(owner_, &Indicators::OnEntryShowMenu)); |
755 | indicator->on_secondary_activate.connect(sigc::mem_fun(owner_, &Indicators::OnEntrySecondaryActivate)); |
756 | indicator->on_scroll.connect(sigc::mem_fun(owner_, &Indicators::OnEntryScroll)); |
757 | + |
758 | indicators_[name] = indicator; |
759 | owner_->on_object_added.emit(indicator); |
760 | |
761 | |
762 | === modified file 'UnityCore/Indicators.h' |
763 | --- UnityCore/Indicators.h 2011-09-05 13:21:08 +0000 |
764 | +++ UnityCore/Indicators.h 2012-03-20 10:02:20 +0000 |
765 | @@ -1,6 +1,6 @@ |
766 | // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
767 | /* |
768 | - * Copyright (C) 2010 Canonical Ltd |
769 | + * Copyright (C) 2010-2012 Canonical Ltd |
770 | * |
771 | * This program is free software: you can redistribute it and/or modify |
772 | * it under the terms of the GNU General Public License version 3 as |
773 | @@ -43,7 +43,7 @@ |
774 | /** |
775 | * internal |
776 | */ |
777 | - void ActivateEntry(std::string const& entry_id); |
778 | + void ActivateEntry(std::string const& entry_id, nux::Rect const& geometry); |
779 | |
780 | /** |
781 | * internal |
782 | @@ -58,11 +58,22 @@ |
783 | /** |
784 | * internal |
785 | */ |
786 | - virtual void OnEntryShowMenu(std::string const& entry_id, |
787 | - int x, int y, int timestamp, int button) = 0; |
788 | + virtual void OnEntryShowMenu(std::string const& entry_id, unsigned int xid, |
789 | + int x, int y, unsigned int button, |
790 | + unsigned int timestamp) = 0; |
791 | + |
792 | + /** |
793 | + * internal |
794 | + */ |
795 | virtual void OnEntrySecondaryActivate(std::string const& entry_id, |
796 | unsigned int timestamp) = 0; |
797 | |
798 | + /** |
799 | + * internal |
800 | + */ |
801 | + virtual void OnShowAppMenu(unsigned int xid, int x, int y, |
802 | + unsigned int timestamp) = 0; |
803 | + |
804 | // Signals |
805 | sigc::signal<void, Indicator::Ptr const&> on_object_added; |
806 | sigc::signal<void, Indicator::Ptr const&> on_object_removed; |
807 | @@ -79,7 +90,7 @@ |
808 | * An entry just got activated. View needs to repaint it. |
809 | * @param entry_id entry id |
810 | */ |
811 | - sigc::signal<void, std::string const&> on_entry_activated; |
812 | + sigc::signal<void, std::string const&, nux::Rect const&> on_entry_activated; |
813 | |
814 | /** |
815 | * internal |
816 | @@ -89,12 +100,22 @@ |
817 | /** |
818 | * The service is about to show a menu. |
819 | * @param entry_id entry id |
820 | - * @param x x coordinate |
821 | - * @param y y coordinate |
822 | - * @param timestamp current time |
823 | + * @param xid window xid |
824 | + * @param x coordinate |
825 | + * @param y coordinate |
826 | * @param button pressed button |
827 | - */ |
828 | - sigc::signal<void, std::string const&, int, int, int, int> on_entry_show_menu; |
829 | + * @param timestamp current time |
830 | + */ |
831 | + sigc::signal<void, std::string const&, unsigned int, int, int, unsigned int, unsigned int> on_entry_show_menu; |
832 | + |
833 | + /** |
834 | + * The service is about to show an appmenu. |
835 | + * @param xid window xid |
836 | + * @param x coordinate |
837 | + * @param y coordinate |
838 | + * @param timestamp current time |
839 | + */ |
840 | + sigc::signal<void, unsigned int, int, int, unsigned int> on_show_appmenu; |
841 | |
842 | protected: |
843 | Indicator::Ptr GetIndicator(std::string const& name); |
844 | |
845 | === modified file 'plugins/unityshell/src/PanelIndicatorEntryView.cpp' |
846 | --- plugins/unityshell/src/PanelIndicatorEntryView.cpp 2012-03-16 01:48:22 +0000 |
847 | +++ plugins/unityshell/src/PanelIndicatorEntryView.cpp 2012-03-20 10:02:20 +0000 |
848 | @@ -110,8 +110,8 @@ |
849 | { |
850 | proxy_->ShowMenu(GetAbsoluteX(), |
851 | GetAbsoluteY() + PANEL_HEIGHT, |
852 | - time(NULL), |
853 | - button); |
854 | + button, |
855 | + time(NULL)); |
856 | } |
857 | |
858 | void PanelIndicatorEntryView::OnMouseDown(int x, int y, long button_flags, long key_flags) |
859 | @@ -193,6 +193,14 @@ |
860 | // 3. Paint something |
861 | void PanelIndicatorEntryView::Refresh() |
862 | { |
863 | + if (!IsVisible()) |
864 | + { |
865 | + SetVisible(false); |
866 | + return; |
867 | + } |
868 | + |
869 | + SetVisible(true); |
870 | + |
871 | PangoLayout* layout = NULL; |
872 | PangoFontDescription* desc = NULL; |
873 | PangoAttrList* attrs = NULL; |
874 | @@ -472,10 +480,7 @@ |
875 | |
876 | std::string PanelIndicatorEntryView::GetName() const |
877 | { |
878 | - if (proxy_->IsUnused()) |
879 | - return ""; |
880 | - else |
881 | - return proxy_->id(); |
882 | + return proxy_->id(); |
883 | } |
884 | |
885 | void PanelIndicatorEntryView::AddProperties(GVariantBuilder* builder) |
886 | @@ -498,7 +503,7 @@ |
887 | |
888 | void PanelIndicatorEntryView::GetGeometryForSync(indicator::EntryLocationMap& locations) |
889 | { |
890 | - if (proxy_->IsUnused()) |
891 | + if (!IsVisible()) |
892 | return; |
893 | |
894 | locations[proxy_->id()] = GetAbsoluteGeometry(); |
895 | @@ -546,6 +551,15 @@ |
896 | return (disabled_ || !proxy_.get() || !IsSensitive()); |
897 | } |
898 | |
899 | +bool PanelIndicatorEntryView::IsVisible() |
900 | +{ |
901 | + if (proxy_.get()) |
902 | + { |
903 | + return proxy_->visible(); |
904 | + } |
905 | + return false; |
906 | +} |
907 | + |
908 | void PanelIndicatorEntryView::OnFontChanged(GObject* gobject, GParamSpec* pspec, |
909 | gpointer data) |
910 | { |
911 | |
912 | === modified file 'plugins/unityshell/src/PanelIndicatorEntryView.h' |
913 | --- plugins/unityshell/src/PanelIndicatorEntryView.h 2012-02-07 23:19:01 +0000 |
914 | +++ plugins/unityshell/src/PanelIndicatorEntryView.h 2012-03-20 10:02:20 +0000 |
915 | @@ -60,6 +60,7 @@ |
916 | bool IsEntryValid() const; |
917 | bool IsSensitive() const; |
918 | bool IsActive() const; |
919 | + bool IsVisible(); |
920 | int GetEntryPriority() const; |
921 | |
922 | void DashShown(); |
923 | |
924 | === modified file 'plugins/unityshell/src/PanelIndicatorsView.cpp' |
925 | --- plugins/unityshell/src/PanelIndicatorsView.cpp 2012-02-04 05:28:23 +0000 |
926 | +++ plugins/unityshell/src/PanelIndicatorsView.cpp 2012-03-20 10:02:20 +0000 |
927 | @@ -180,7 +180,7 @@ |
928 | { |
929 | PanelIndicatorEntryView* view = entry.second; |
930 | |
931 | - if (!target && view->GetAbsoluteGeometry().IsPointInside(x, y)) |
932 | + if (!target && view->IsVisible() && view->GetAbsoluteGeometry().IsPointInside(x, y)) |
933 | { |
934 | view->Activate(0); |
935 | target = view; |
936 | |
937 | === modified file 'plugins/unityshell/src/PanelIndicatorsView.h' |
938 | --- plugins/unityshell/src/PanelIndicatorsView.h 2012-02-04 05:28:23 +0000 |
939 | +++ plugins/unityshell/src/PanelIndicatorsView.h 2012-03-20 10:02:20 +0000 |
940 | @@ -83,7 +83,7 @@ |
941 | Entries entries_; |
942 | |
943 | std::string GetName() const; |
944 | - void AddProperties(GVariantBuilder* builder); |
945 | + void AddProperties(GVariantBuilder* builder); |
946 | |
947 | private: |
948 | typedef std::vector<indicator::Indicator::Ptr> Indicators; |
949 | |
950 | === modified file 'plugins/unityshell/src/PanelView.cpp' |
951 | --- plugins/unityshell/src/PanelView.cpp 2012-03-13 02:52:00 +0000 |
952 | +++ plugins/unityshell/src/PanelView.cpp 2012-03-20 10:02:20 +0000 |
953 | @@ -483,7 +483,7 @@ |
954 | { |
955 | // Appmenu is treated differently as it needs to expand |
956 | // We could do this in a more special way, but who has the time for special? |
957 | - if (proxy->name().find("appmenu") != std::string::npos) |
958 | + if (proxy->IsAppmenu()) |
959 | { |
960 | _menu_view->AddIndicator(proxy); |
961 | } |
962 | @@ -500,7 +500,7 @@ |
963 | |
964 | void PanelView::OnObjectRemoved(indicator::Indicator::Ptr const& proxy) |
965 | { |
966 | - if (proxy->name().find("appmenu") != std::string::npos) |
967 | + if (proxy->IsAppmenu()) |
968 | { |
969 | _menu_view->RemoveIndicator(proxy); |
970 | } |
971 | @@ -569,7 +569,7 @@ |
972 | return TRUE; |
973 | } |
974 | |
975 | -void PanelView::OnEntryActivated(std::string const& entry_id) |
976 | +void PanelView::OnEntryActivated(std::string const& entry_id, nux::Rect const& geo) |
977 | { |
978 | bool active = (entry_id.size() > 0); |
979 | if (active && !_track_menu_pointer_id) |
980 | @@ -605,8 +605,9 @@ |
981 | _needs_geo_sync = true; |
982 | } |
983 | |
984 | -void PanelView::OnEntryShowMenu(std::string const& entry_id, |
985 | - int x, int y, int timestamp, int button) |
986 | +void PanelView::OnEntryShowMenu(std::string const& entry_id, unsigned int xid, |
987 | + int x, int y, unsigned int button, |
988 | + unsigned int timestamp) |
989 | { |
990 | Display* d = nux::GetGraphicsDisplay()->GetX11Display(); |
991 | XUngrabPointer(d, CurrentTime); |
992 | |
993 | === modified file 'plugins/unityshell/src/PanelView.h' |
994 | --- plugins/unityshell/src/PanelView.h 2012-02-04 05:28:23 +0000 |
995 | +++ plugins/unityshell/src/PanelView.h 2012-03-20 10:02:20 +0000 |
996 | @@ -57,10 +57,10 @@ |
997 | void OnIndicatorViewUpdated(PanelIndicatorEntryView* view); |
998 | void OnMenuPointerMoved(int x, int y); |
999 | void OnEntryActivateRequest(std::string const& entry_id); |
1000 | - void OnEntryActivated(std::string const& entry_id); |
1001 | + void OnEntryActivated(std::string const& entry_id, nux::Rect const& geo); |
1002 | void OnSynced(); |
1003 | - void OnEntryShowMenu(std::string const& entry_id, |
1004 | - int x, int y, int timestamp, int button); |
1005 | + void OnEntryShowMenu(std::string const& entry_id, unsigned int xid, int x, int y, |
1006 | + unsigned int button, unsigned int timestamp); |
1007 | |
1008 | void SetPrimary(bool primary); |
1009 | bool GetPrimary(); |
1010 | |
1011 | === modified file 'services/CMakeLists.txt' |
1012 | --- services/CMakeLists.txt 2012-02-04 05:28:23 +0000 |
1013 | +++ services/CMakeLists.txt 2012-03-20 10:02:20 +0000 |
1014 | @@ -2,7 +2,7 @@ |
1015 | # Panel Service |
1016 | # |
1017 | find_package(PkgConfig) |
1018 | -pkg_check_modules(SERVICE_DEPS REQUIRED gtk+-3.0>=3.3 gobject-2.0 gio-2.0 gthread-2.0 indicator3-0.4 x11 gconf-2.0) |
1019 | +pkg_check_modules(SERVICE_DEPS REQUIRED gtk+-3.0>=3.3 gobject-2.0 gio-2.0 gthread-2.0 indicator3-0.4>=0.4.90 x11 gconf-2.0) |
1020 | |
1021 | execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} indicator3-0.4 --variable indicatordir OUTPUT_VARIABLE _indicatordir OUTPUT_STRIP_TRAILING_WHITESPACE) |
1022 | execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} indicator3-0.4 --variable iconsdir OUTPUT_VARIABLE _iconsdir OUTPUT_STRIP_TRAILING_WHITESPACE) |
1023 | |
1024 | === modified file 'services/panel-indicator-entry-accessible.c' |
1025 | --- services/panel-indicator-entry-accessible.c 2011-11-11 10:44:50 +0000 |
1026 | +++ services/panel-indicator-entry-accessible.c 2012-03-20 10:02:20 +0000 |
1027 | @@ -46,7 +46,8 @@ |
1028 | #define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_INDICATOR_ENTRY_ACCESSIBLE, PanelIndicatorEntryAccessiblePrivate)) |
1029 | |
1030 | static void |
1031 | -on_entry_activated_cb (PanelService *service, const gchar *entry_id, gpointer user_data) |
1032 | +on_entry_activated_cb (PanelService *service, const gchar *entry_id, |
1033 | + gint x, gint y, guint w, guint h, gpointer user_data) |
1034 | { |
1035 | gchar *s; |
1036 | gboolean adding = FALSE; |
1037 | |
1038 | === modified file 'services/panel-main.c' |
1039 | --- services/panel-main.c 2012-01-12 16:47:05 +0000 |
1040 | +++ services/panel-main.c 2012-03-20 10:02:20 +0000 |
1041 | @@ -58,13 +58,21 @@ |
1042 | " <method name='SyncGeometries'>" |
1043 | " <arg type='a(ssiiii)' name='geometries' direction='in'/>" |
1044 | " </method>" |
1045 | - "" |
1046 | + "" |
1047 | " <method name='ShowEntry'>" |
1048 | " <arg type='s' name='entry_id' direction='in'/>" |
1049 | - " <arg type='u' name='timestamp' direction='in'/>" |
1050 | - " <arg type='i' name='x' direction='in'/>" |
1051 | - " <arg type='i' name='y' direction='in'/>" |
1052 | - " <arg type='i' name='button' direction='in'/>" |
1053 | + " <arg type='u' name='xid' direction='in'/>" |
1054 | + " <arg type='i' name='x' direction='in'/>" |
1055 | + " <arg type='i' name='y' direction='in'/>" |
1056 | + " <arg type='u' name='button' direction='in'/>" |
1057 | + " <arg type='u' name='timestamp' direction='in'/>" |
1058 | + " </method>" |
1059 | + "" |
1060 | + " <method name='ShowAppMenu'>" |
1061 | + " <arg type='u' name='xid' direction='in'/>" |
1062 | + " <arg type='i' name='x' direction='in'/>" |
1063 | + " <arg type='i' name='y' direction='in'/>" |
1064 | + " <arg type='u' name='timestamp' direction='in'/>" |
1065 | " </method>" |
1066 | "" |
1067 | " <method name='SecondaryActivateEntry'>" |
1068 | @@ -79,6 +87,7 @@ |
1069 | "" |
1070 | " <signal name='EntryActivated'>" |
1071 | " <arg type='s' name='entry_id' />" |
1072 | + " <arg type='(iiuu)' name='entry_geometry' />" |
1073 | " </signal>" |
1074 | "" |
1075 | " <signal name='ReSync'>" |
1076 | @@ -174,18 +183,31 @@ |
1077 | } |
1078 | else if (g_strcmp0 (method_name, "ShowEntry") == 0) |
1079 | { |
1080 | + guint32 xid; |
1081 | gchar *entry_id; |
1082 | - guint32 timestamp; |
1083 | gint32 x; |
1084 | gint32 y; |
1085 | - gint32 button; |
1086 | - g_variant_get (parameters, "(suiii)", &entry_id, ×tamp, &x, &y, &button, NULL); |
1087 | + guint32 button; |
1088 | + guint32 timestamp; |
1089 | + g_variant_get (parameters, "(suiiuu)", &entry_id, &xid, &x, &y, &button, ×tamp, NULL); |
1090 | |
1091 | - panel_service_show_entry (service, entry_id, timestamp, x, y, button); |
1092 | + panel_service_show_entry (service, entry_id, xid, x, y, button, timestamp); |
1093 | |
1094 | g_dbus_method_invocation_return_value (invocation, NULL); |
1095 | g_free (entry_id); |
1096 | } |
1097 | + else if (g_strcmp0 (method_name, "ShowAppMenu") == 0) |
1098 | + { |
1099 | + guint32 xid; |
1100 | + gint32 x; |
1101 | + gint32 y; |
1102 | + guint32 timestamp; |
1103 | + g_variant_get (parameters, "(uiiu)", &xid, &x, &y, ×tamp, NULL); |
1104 | + |
1105 | + panel_service_show_app_menu (service, xid, x, y, timestamp); |
1106 | + |
1107 | + g_dbus_method_invocation_return_value (invocation, NULL); |
1108 | + } |
1109 | else if (g_strcmp0 (method_name, "SecondaryActivateEntry") == 0) |
1110 | { |
1111 | gchar *entry_id; |
1112 | @@ -229,6 +251,7 @@ |
1113 | static void |
1114 | on_service_entry_activated (PanelService *service, |
1115 | const gchar *entry_id, |
1116 | + gint x, gint y, guint w, guint h, |
1117 | GDBusConnection *connection) |
1118 | { |
1119 | GError *error = NULL; |
1120 | @@ -237,7 +260,7 @@ |
1121 | S_PATH, |
1122 | S_IFACE, |
1123 | "EntryActivated", |
1124 | - g_variant_new ("(s)", entry_id), |
1125 | + g_variant_new ("(s(iiuu))", entry_id, x, y, w, h), |
1126 | &error); |
1127 | |
1128 | if (error) |
1129 | |
1130 | === modified file 'services/panel-marshal.list' |
1131 | --- services/panel-marshal.list 2011-03-17 14:16:13 +0000 |
1132 | +++ services/panel-marshal.list 2012-03-20 10:02:20 +0000 |
1133 | @@ -1,2 +1,3 @@ |
1134 | NONE:OBJECT,POINTER,INT,INT,INT,INT |
1135 | VOID:STRING,BOOLEAN |
1136 | +VOID:STRING,INT,INT,UINT,UINT |
1137 | |
1138 | === modified file 'services/panel-root-accessible.c' |
1139 | --- services/panel-root-accessible.c 2011-11-11 10:44:50 +0000 |
1140 | +++ services/panel-root-accessible.c 2012-03-20 10:02:20 +0000 |
1141 | @@ -134,16 +134,16 @@ |
1142 | if (INDICATOR_IS_OBJECT (indicator)) |
1143 | { |
1144 | AtkObject *child; |
1145 | - gpointer *data; |
1146 | + gpointer *weak_data; |
1147 | |
1148 | child = panel_indicator_accessible_new (indicator); |
1149 | /* FIXME: use proper signals once we support dynamic adding/removing |
1150 | * of indicators */ |
1151 | - data = g_new0 (gpointer, 2); |
1152 | - data[0] = root; |
1153 | - data[1] = child; |
1154 | + weak_data = g_new0 (gpointer, 2); |
1155 | + weak_data[0] = root; |
1156 | + weak_data[1] = child; |
1157 | g_object_weak_ref (G_OBJECT (indicator), |
1158 | - (GWeakNotify) on_indicator_removed, data); |
1159 | + (GWeakNotify) on_indicator_removed, weak_data); |
1160 | |
1161 | atk_object_set_parent (child, accessible); |
1162 | root->priv->a11y_children = g_slist_append (root->priv->a11y_children, child); |
1163 | |
1164 | === modified file 'services/panel-service.c' |
1165 | --- services/panel-service.c 2012-02-22 13:59:25 +0000 |
1166 | +++ services/panel-service.c 2012-03-20 10:02:20 +0000 |
1167 | @@ -1,6 +1,6 @@ |
1168 | // -*- Mode: C; indent-tabs-mode: nil; tab-width: 2 -*- |
1169 | /* |
1170 | - * Copyright (C) 2010 Canonical Ltd |
1171 | + * Copyright (C) 2010-2012 Canonical Ltd |
1172 | * |
1173 | * This program is free software: you can redistribute it and/or modify |
1174 | * it under the terms of the GNU General Public License version 3 as |
1175 | @@ -27,8 +27,10 @@ |
1176 | #include "panel-service.h" |
1177 | |
1178 | #include <stdlib.h> |
1179 | +#include <string.h> |
1180 | #include <gtk/gtk.h> |
1181 | #include <gdk/gdkx.h> |
1182 | +#include <gconf/gconf-client.h> |
1183 | |
1184 | #include <X11/extensions/XInput2.h> |
1185 | #include <X11/XKBlib.h> |
1186 | @@ -44,12 +46,15 @@ |
1187 | #define N_TIMEOUT_SLOTS 50 |
1188 | #define MAX_INDICATOR_ENTRIES 50 |
1189 | |
1190 | +#define COMPIZ_OPTIONS_PATH "/apps/compiz-1/plugins/unityshell/screen0/options" |
1191 | +#define MENU_TOGGLE_KEYBINDING_PATH COMPIZ_OPTIONS_PATH"/panel_first_menu" |
1192 | + |
1193 | static PanelService *static_service = NULL; |
1194 | |
1195 | struct _PanelServicePrivate |
1196 | { |
1197 | GSList *indicators; |
1198 | - GHashTable *entry2indicator_hash; |
1199 | + GHashTable *id2entry_hash; |
1200 | GHashTable *panel2entries_hash; |
1201 | |
1202 | guint initial_sync_id; |
1203 | @@ -69,6 +74,10 @@ |
1204 | gint last_bottom; |
1205 | guint32 last_menu_button; |
1206 | |
1207 | + KeyCode toggle_key; |
1208 | + guint32 toggle_modifiers; |
1209 | + guint32 key_monitor_id; |
1210 | + |
1211 | IndicatorObjectEntry *pressed_entry; |
1212 | gboolean use_event; |
1213 | }; |
1214 | @@ -121,7 +130,6 @@ |
1215 | static void sort_indicators (PanelService *self); |
1216 | |
1217 | static void notify_object (IndicatorObject *object); |
1218 | -static IndicatorObjectEntry *get_entry_at (PanelService *self, gint x, gint y); |
1219 | |
1220 | static GdkFilterReturn event_filter (GdkXEvent *ev, |
1221 | GdkEvent *gev, |
1222 | @@ -137,24 +145,27 @@ |
1223 | PanelServicePrivate *priv = PANEL_SERVICE (object)->priv; |
1224 | gint i; |
1225 | |
1226 | - g_hash_table_destroy (priv->entry2indicator_hash); |
1227 | + g_hash_table_destroy (priv->id2entry_hash); |
1228 | g_hash_table_destroy (priv->panel2entries_hash); |
1229 | |
1230 | gdk_window_remove_filter (NULL, (GdkFilterFunc)event_filter, object); |
1231 | |
1232 | - if (G_IS_OBJECT (priv->menubar)) |
1233 | + if (GTK_IS_WIDGET (priv->menubar) && |
1234 | + gtk_widget_get_realized (GTK_WIDGET (priv->menubar))) |
1235 | { |
1236 | g_object_unref (priv->menubar); |
1237 | priv->menubar = NULL; |
1238 | } |
1239 | |
1240 | - if (G_IS_OBJECT (priv->offscreen_window)) |
1241 | + if (GTK_IS_WIDGET (priv->offscreen_window) && |
1242 | + gtk_widget_get_realized (GTK_WIDGET (priv->offscreen_window))) |
1243 | { |
1244 | g_object_unref (priv->offscreen_window); |
1245 | priv->offscreen_window = NULL; |
1246 | } |
1247 | |
1248 | - if (G_IS_OBJECT (priv->last_menu)) |
1249 | + if (GTK_IS_WIDGET (priv->last_menu) && |
1250 | + gtk_widget_get_realized (GTK_WIDGET (priv->last_menu))) |
1251 | { |
1252 | g_object_unref (priv->last_menu); |
1253 | priv->last_menu = NULL; |
1254 | @@ -175,15 +186,28 @@ |
1255 | } |
1256 | } |
1257 | |
1258 | + if (priv->key_monitor_id) |
1259 | + { |
1260 | + gconf_client_notify_remove (gconf_client_get_default(), priv->key_monitor_id); |
1261 | + priv->key_monitor_id = 0; |
1262 | + } |
1263 | + |
1264 | G_OBJECT_CLASS (panel_service_parent_class)->dispose (object); |
1265 | } |
1266 | |
1267 | static void |
1268 | +panel_service_class_finalize (GObject *object) |
1269 | +{ |
1270 | + static_service = NULL; |
1271 | +} |
1272 | + |
1273 | +static void |
1274 | panel_service_class_init (PanelServiceClass *klass) |
1275 | { |
1276 | GObjectClass *obj_class = G_OBJECT_CLASS (klass); |
1277 | |
1278 | obj_class->dispose = panel_service_class_dispose; |
1279 | + obj_class->finalize = panel_service_class_finalize; |
1280 | |
1281 | /* Signals */ |
1282 | _service_signals[ENTRY_ACTIVATED] = |
1283 | @@ -192,8 +216,9 @@ |
1284 | G_SIGNAL_RUN_LAST, |
1285 | 0, |
1286 | NULL, NULL, |
1287 | - g_cclosure_marshal_VOID__STRING, |
1288 | - G_TYPE_NONE, 1, G_TYPE_STRING); |
1289 | + panel_marshal_VOID__STRING_INT_INT_UINT_UINT, |
1290 | + G_TYPE_NONE, 5, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT, |
1291 | + G_TYPE_UINT, G_TYPE_UINT); |
1292 | |
1293 | _service_signals[RE_SYNC] = |
1294 | g_signal_new ("re-sync", |
1295 | @@ -212,6 +237,7 @@ |
1296 | NULL, NULL, |
1297 | g_cclosure_marshal_VOID__STRING, |
1298 | G_TYPE_NONE, 1, G_TYPE_STRING); |
1299 | + |
1300 | _service_signals[GEOMETRIES_CHANGED] = |
1301 | g_signal_new ("geometries-changed", |
1302 | G_OBJECT_CLASS_TYPE (obj_class), |
1303 | @@ -245,6 +271,82 @@ |
1304 | g_type_class_add_private (obj_class, sizeof (PanelServicePrivate)); |
1305 | } |
1306 | |
1307 | +static IndicatorObjectEntry * |
1308 | +get_entry_at (PanelService *self, gint x, gint y) |
1309 | +{ |
1310 | + GHashTableIter panel_iter, entries_iter; |
1311 | + gpointer key, value, k, v; |
1312 | + |
1313 | + g_hash_table_iter_init (&panel_iter, self->priv->panel2entries_hash); |
1314 | + while (g_hash_table_iter_next (&panel_iter, &key, &value)) |
1315 | + { |
1316 | + GHashTable *entry2geometry_hash = value; |
1317 | + g_hash_table_iter_init (&entries_iter, entry2geometry_hash); |
1318 | + |
1319 | + while (g_hash_table_iter_next (&entries_iter, &k, &v)) |
1320 | + { |
1321 | + IndicatorObjectEntry *entry = k; |
1322 | + GdkRectangle *geo = v; |
1323 | + |
1324 | + if (x >= geo->x && x <= (geo->x + geo->width) && |
1325 | + y >= geo->y && y <= (geo->y + geo->height)) |
1326 | + { |
1327 | + return entry; |
1328 | + } |
1329 | + } |
1330 | + } |
1331 | + |
1332 | + return NULL; |
1333 | +} |
1334 | + |
1335 | +static IndicatorObject * |
1336 | +get_entry_parent_indicator (IndicatorObjectEntry *entry) |
1337 | +{ |
1338 | + if (!entry || !INDICATOR_IS_OBJECT (entry->parent_object)) |
1339 | + return NULL; |
1340 | + |
1341 | + return INDICATOR_OBJECT (entry->parent_object); |
1342 | +} |
1343 | + |
1344 | +static gchar * |
1345 | +get_indicator_entry_id_by_entry (IndicatorObjectEntry *entry) |
1346 | +{ |
1347 | + gchar *entry_id = NULL; |
1348 | + |
1349 | + if (entry) |
1350 | + entry_id = g_strdup_printf ("%p", entry); |
1351 | + |
1352 | + return entry_id; |
1353 | +} |
1354 | + |
1355 | +static IndicatorObjectEntry * |
1356 | +get_indicator_entry_by_id (PanelService *self, const gchar *entry_id) |
1357 | +{ |
1358 | + IndicatorObjectEntry *entry; |
1359 | + |
1360 | + entry = g_hash_table_lookup (self->priv->id2entry_hash, entry_id); |
1361 | + |
1362 | + if (entry) |
1363 | + { |
1364 | + if (g_slist_find (self->priv->indicators, entry->parent_object)) |
1365 | + { |
1366 | + if (!INDICATOR_IS_OBJECT (entry->parent_object)) |
1367 | + entry = NULL; |
1368 | + } |
1369 | + else |
1370 | + { |
1371 | + entry = NULL; |
1372 | + } |
1373 | + |
1374 | + if (!entry) |
1375 | + { |
1376 | + g_warning("The entry id '%s' you're trying to lookup is not a valid IndicatorObjectEntry!", entry_id); |
1377 | + } |
1378 | + } |
1379 | + |
1380 | + return entry; |
1381 | +} |
1382 | + |
1383 | static GdkFilterReturn |
1384 | event_filter (GdkXEvent *ev, GdkEvent *gev, PanelService *self) |
1385 | { |
1386 | @@ -269,9 +371,9 @@ |
1387 | if (!event) |
1388 | return ret; |
1389 | |
1390 | - if (event->evtype == XI_KeyRelease) |
1391 | + if (event->evtype == XI_KeyPress) |
1392 | { |
1393 | - if (XkbKeycodeToKeysym(event->display, event->detail, 0, 0) == GDK_KEY_F10) |
1394 | + if (event->mods.base == priv->toggle_modifiers && event->detail == priv->toggle_key) |
1395 | { |
1396 | if (GTK_IS_MENU (priv->last_menu)) |
1397 | gtk_menu_popdown (GTK_MENU (priv->last_menu)); |
1398 | @@ -293,16 +395,16 @@ |
1399 | gboolean event_is_a_click = FALSE; |
1400 | entry = get_entry_at (self, event->root_x, event->root_y); |
1401 | |
1402 | - if (XIMaskIsSet (event->buttons.mask, 1) || XIMaskIsSet (event->buttons.mask, 3)) |
1403 | + if (event->detail == 1 || event->detail == 3) |
1404 | { |
1405 | /* Consider only right and left clicks over the indicators entries */ |
1406 | event_is_a_click = TRUE; |
1407 | } |
1408 | - else if (XIMaskIsSet (event->buttons.mask, 2) && entry) |
1409 | + else if (entry && event->detail == 2) |
1410 | { |
1411 | /* Middle clicks over an appmenu entry are considered just like |
1412 | * all other clicks */ |
1413 | - IndicatorObject *obj = g_hash_table_lookup (priv->entry2indicator_hash, entry); |
1414 | + IndicatorObject *obj = get_entry_parent_indicator (entry); |
1415 | |
1416 | if (g_strcmp0 (g_object_get_data (G_OBJECT (obj), "id"), "libappmenu.so") == 0) |
1417 | { |
1418 | @@ -330,25 +432,23 @@ |
1419 | /* If we were navigating over indicators using the keyboard |
1420 | * and now we click over the indicator under the mouse, we |
1421 | * must force it to show back again, not make it close */ |
1422 | - gchar *entry_id = g_strdup_printf ("%p", entry); |
1423 | + gchar *entry_id = get_indicator_entry_id_by_entry (entry); |
1424 | g_signal_emit (self, _service_signals[ENTRY_ACTIVATE_REQUEST], 0, entry_id); |
1425 | g_free (entry_id); |
1426 | } |
1427 | } |
1428 | } |
1429 | } |
1430 | - else if ((XIMaskIsSet (event->buttons.mask, 2) || |
1431 | - XIMaskIsSet (event->buttons.mask, 4) || |
1432 | - XIMaskIsSet (event->buttons.mask, 5)) && entry) |
1433 | + else if (entry && (event->detail == 2 || event->detail == 4 || event->detail == 5)) |
1434 | { |
1435 | /* If we're scrolling or middle-clicking over an indicator |
1436 | * (which is not an appmenu entry) then we need to send the |
1437 | * event to the indicator itself, and avoid it to close */ |
1438 | - gchar *entry_id = g_strdup_printf ("%p", entry); |
1439 | + gchar *entry_id = get_indicator_entry_id_by_entry (entry); |
1440 | |
1441 | - if (XIMaskIsSet (event->buttons.mask, 4) || XIMaskIsSet (event->buttons.mask, 5)) |
1442 | + if (event->detail == 4 || event->detail == 5) |
1443 | { |
1444 | - gint32 delta = XIMaskIsSet (event->buttons.mask, 4) ? 120 : -120; |
1445 | + gint32 delta = (event->detail == 4) ? 120 : -120; |
1446 | panel_service_scroll_entry (self, entry_id, delta); |
1447 | } |
1448 | else if (entry == priv->pressed_entry) |
1449 | @@ -365,60 +465,6 @@ |
1450 | return ret; |
1451 | } |
1452 | |
1453 | -static IndicatorObjectEntry * |
1454 | -get_entry_at (PanelService *self, gint x, gint y) |
1455 | -{ |
1456 | - GHashTableIter panel_iter, entries_iter; |
1457 | - gpointer key, value, k, v; |
1458 | - |
1459 | - g_hash_table_iter_init (&panel_iter, self->priv->panel2entries_hash); |
1460 | - while (g_hash_table_iter_next (&panel_iter, &key, &value)) |
1461 | - { |
1462 | - GHashTable *entry2geometry_hash = value; |
1463 | - g_hash_table_iter_init (&entries_iter, entry2geometry_hash); |
1464 | - |
1465 | - while (g_hash_table_iter_next (&entries_iter, &k, &v)) |
1466 | - { |
1467 | - IndicatorObjectEntry *entry = k; |
1468 | - GdkRectangle *geo = v; |
1469 | - |
1470 | - if (x >= geo->x && x <= (geo->x + geo->width) && |
1471 | - y >= geo->y && y <= (geo->y + geo->height)) |
1472 | - { |
1473 | - return entry; |
1474 | - } |
1475 | - } |
1476 | - } |
1477 | - |
1478 | - return NULL; |
1479 | -} |
1480 | - |
1481 | -static void |
1482 | -panel_service_get_indicator_entry_by_id (PanelService *self, |
1483 | - const gchar *entry_id, |
1484 | - IndicatorObjectEntry **entry, |
1485 | - IndicatorObject **object) |
1486 | -{ |
1487 | - IndicatorObject *indicator; |
1488 | - IndicatorObjectEntry *probably_entry; |
1489 | - PanelServicePrivate *priv = self->priv; |
1490 | - |
1491 | - /* FIXME: eeek, why do we even do this? */ |
1492 | - if (sscanf (entry_id, "%p", &probably_entry) == 1) |
1493 | - { |
1494 | - /* check that there really is such IndicatorObjectEntry */ |
1495 | - indicator = g_hash_table_lookup (priv->entry2indicator_hash, |
1496 | - probably_entry); |
1497 | - if (object) *object = indicator; |
1498 | - if (entry) *entry = indicator != NULL ? probably_entry : NULL; |
1499 | - } |
1500 | - else |
1501 | - { |
1502 | - if (object) *object = NULL; |
1503 | - if (entry) *entry = NULL; |
1504 | - } |
1505 | -} |
1506 | - |
1507 | static gboolean |
1508 | initial_resync (PanelService *self) |
1509 | { |
1510 | @@ -431,6 +477,73 @@ |
1511 | } |
1512 | |
1513 | static void |
1514 | +panel_service_update_menu_keybinding (PanelService *self) |
1515 | +{ |
1516 | + GConfClient *client = gconf_client_get_default (); |
1517 | + gchar *binding = gconf_client_get_string (client, MENU_TOGGLE_KEYBINDING_PATH, NULL); |
1518 | + |
1519 | + KeyCode keycode = 0; |
1520 | + KeySym keysym = NoSymbol; |
1521 | + guint32 modifiers = 0; |
1522 | + |
1523 | + gchar *keystart = (binding) ? strrchr(binding, '>') : NULL; |
1524 | + |
1525 | + if (!keystart) |
1526 | + keystart = binding; |
1527 | + |
1528 | + while (keystart && !g_ascii_isalnum (*keystart)) |
1529 | + keystart++; |
1530 | + |
1531 | + gchar *keyend = keystart; |
1532 | + |
1533 | + while (keyend && g_ascii_isalnum (*keyend)) |
1534 | + keyend++; |
1535 | + |
1536 | + if (keystart != keyend) |
1537 | + { |
1538 | + gchar *keystr = g_strndup (keystart, keyend-keystart); |
1539 | + keysym = XStringToKeysym (keystr); |
1540 | + } |
1541 | + |
1542 | + if (keysym != NoSymbol) |
1543 | + { |
1544 | + Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); |
1545 | + keycode = XKeysymToKeycode(dpy, keysym); |
1546 | + |
1547 | + if (g_strrstr (binding, "<Shift>")) |
1548 | + { |
1549 | + modifiers |= GDK_SHIFT_MASK; |
1550 | + } |
1551 | + if (g_strrstr (binding, "<Control>")) |
1552 | + { |
1553 | + modifiers |= GDK_CONTROL_MASK; |
1554 | + } |
1555 | + if (g_strrstr (binding, "<Alt>") || g_strrstr (binding, "<Mod1>")) |
1556 | + { |
1557 | + modifiers |= GDK_MOD1_MASK; |
1558 | + } |
1559 | + if (g_strrstr (binding, "<Super>")) |
1560 | + { |
1561 | + modifiers |= GDK_SUPER_MASK; |
1562 | + } |
1563 | + } |
1564 | + |
1565 | + self->priv->toggle_key = keycode; |
1566 | + self->priv->toggle_modifiers = modifiers; |
1567 | + |
1568 | + g_free (binding); |
1569 | +} |
1570 | + |
1571 | +void |
1572 | +on_keybinding_changed (GConfClient* client, guint id, GConfEntry* entry, gpointer data) |
1573 | +{ |
1574 | + PanelService *self = data; |
1575 | + g_return_if_fail (PANEL_IS_SERVICE (data)); |
1576 | + |
1577 | + panel_service_update_menu_keybinding (self); |
1578 | +} |
1579 | + |
1580 | +static void |
1581 | panel_service_init (PanelService *self) |
1582 | { |
1583 | PanelServicePrivate *priv; |
1584 | @@ -442,7 +555,7 @@ |
1585 | |
1586 | gdk_window_add_filter (NULL, (GdkFilterFunc)event_filter, self); |
1587 | |
1588 | - priv->entry2indicator_hash = g_hash_table_new (g_direct_hash, g_direct_equal); |
1589 | + priv->id2entry_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); |
1590 | priv->panel2entries_hash = g_hash_table_new_full (g_str_hash, g_str_equal, |
1591 | g_free, |
1592 | (GDestroyNotify) g_hash_table_destroy); |
1593 | @@ -452,6 +565,14 @@ |
1594 | sort_indicators (self); |
1595 | suppress_signals = FALSE; |
1596 | |
1597 | + panel_service_update_menu_keybinding (self); |
1598 | + |
1599 | + GConfClient *client = gconf_client_get_default (); |
1600 | + gconf_client_add_dir (client, COMPIZ_OPTIONS_PATH, GCONF_CLIENT_PRELOAD_NONE, NULL); |
1601 | + priv->key_monitor_id = gconf_client_notify_add (client, MENU_TOGGLE_KEYBINDING_PATH, |
1602 | + on_keybinding_changed, self, |
1603 | + NULL, NULL); |
1604 | + |
1605 | priv->initial_sync_id = g_idle_add ((GSourceFunc)initial_resync, self); |
1606 | } |
1607 | |
1608 | @@ -481,17 +602,23 @@ |
1609 | { |
1610 | for (l = entries; l; l = l->next) |
1611 | { |
1612 | - g_hash_table_remove (self->priv->entry2indicator_hash, l->data); |
1613 | - |
1614 | + IndicatorObjectEntry *entry; |
1615 | + gchar *entry_id; |
1616 | GHashTableIter iter; |
1617 | gpointer key, value; |
1618 | + |
1619 | + entry = l->data; |
1620 | + entry_id = get_indicator_entry_id_by_entry (entry); |
1621 | + g_hash_table_remove (self->priv->id2entry_hash, entry_id); |
1622 | + g_free (entry_id); |
1623 | + |
1624 | g_hash_table_iter_init (&iter, self->priv->panel2entries_hash); |
1625 | while (g_hash_table_iter_next (&iter, &key, &value)) |
1626 | { |
1627 | GHashTable *entry2geometry_hash = value; |
1628 | |
1629 | if (g_hash_table_size (entry2geometry_hash) > 1) |
1630 | - g_hash_table_remove (entry2geometry_hash, l->data); |
1631 | + g_hash_table_remove (entry2geometry_hash, entry); |
1632 | else |
1633 | g_hash_table_iter_remove (&iter); |
1634 | } |
1635 | @@ -586,7 +713,7 @@ |
1636 | gpointer timeout = g_object_get_data (G_OBJECT (indicator), "remove-timeout"); |
1637 | |
1638 | if (timeout) |
1639 | - g_source_remove (GPOINTER_TO_UINT (timeout)); |
1640 | + g_source_remove (GPOINTER_TO_UINT (timeout)); |
1641 | |
1642 | g_object_set_data (G_OBJECT (indicator), "remove", GINT_TO_POINTER (TRUE)); |
1643 | notify_object (indicator); |
1644 | @@ -695,13 +822,11 @@ |
1645 | IndicatorObjectEntry *entry, |
1646 | PanelService *self) |
1647 | { |
1648 | - PanelServicePrivate *priv; |
1649 | - |
1650 | g_return_if_fail (PANEL_IS_SERVICE (self)); |
1651 | g_return_if_fail (entry != NULL); |
1652 | - priv = self->priv; |
1653 | |
1654 | - g_hash_table_insert (priv->entry2indicator_hash, entry, object); |
1655 | + gchar *entry_id = get_indicator_entry_id_by_entry (entry); |
1656 | + g_hash_table_insert (self->priv->id2entry_hash, entry_id, entry); |
1657 | |
1658 | if (GTK_IS_LABEL (entry->label)) |
1659 | { |
1660 | @@ -748,18 +873,18 @@ |
1661 | IndicatorObjectEntry *entry, |
1662 | PanelService *self) |
1663 | { |
1664 | - PanelServicePrivate *priv; |
1665 | g_return_if_fail (PANEL_IS_SERVICE (self)); |
1666 | g_return_if_fail (entry != NULL); |
1667 | |
1668 | - priv = self->priv; |
1669 | - |
1670 | - g_hash_table_remove (priv->entry2indicator_hash, entry); |
1671 | - /* Don't remove here the value from priv->panel2entries_hash, this should |
1672 | - * be done in during the sync, to avoid false positive. |
1673 | + /* Don't remove here the value from panel2entries_hash, this should be |
1674 | + * done during the geometries sync, to avoid false positive. |
1675 | * FIXME this in libappmenu.so to avoid to send an "entry-removed" signal |
1676 | * when switching the focus from a window to one of its dialog children */ |
1677 | |
1678 | + gchar *entry_id = get_indicator_entry_id_by_entry (entry); |
1679 | + g_hash_table_remove (self->priv->id2entry_hash, entry_id); |
1680 | + g_free (entry_id); |
1681 | + |
1682 | notify_object (object); |
1683 | } |
1684 | |
1685 | @@ -786,10 +911,8 @@ |
1686 | return; |
1687 | } |
1688 | |
1689 | - entry_id = g_strdup_printf ("%p", entry); |
1690 | - |
1691 | + entry_id = get_indicator_entry_id_by_entry (entry); |
1692 | g_signal_emit (self, _service_signals[ENTRY_ACTIVATE_REQUEST], 0, entry_id); |
1693 | - |
1694 | g_free (entry_id); |
1695 | } |
1696 | |
1697 | @@ -808,10 +931,8 @@ |
1698 | return; |
1699 | } |
1700 | |
1701 | - entry_id = g_strdup_printf ("%p", entry); |
1702 | - |
1703 | + entry_id = get_indicator_entry_id_by_entry (entry); |
1704 | g_signal_emit (self, _service_signals[ENTRY_SHOW_NOW_CHANGED], 0, entry_id, show_now_changed); |
1705 | - |
1706 | g_free (entry_id); |
1707 | } |
1708 | |
1709 | @@ -829,7 +950,7 @@ |
1710 | gchar *name; |
1711 | GList *entries, *entry; |
1712 | |
1713 | - indicator_object_set_environment(object, (const GStrv)indicator_environment); |
1714 | + indicator_object_set_environment(object, (GStrv)indicator_environment); |
1715 | |
1716 | if (_name != NULL) |
1717 | name = g_strdup (_name); |
1718 | @@ -1079,7 +1200,7 @@ |
1719 | { |
1720 | gint prio = -1; |
1721 | IndicatorObjectEntry *entry = e->data; |
1722 | - gchar *id = g_strdup_printf ("%p", entry); |
1723 | + gchar *id = get_indicator_entry_id_by_entry (entry); |
1724 | |
1725 | if (entry->name_hint) |
1726 | { |
1727 | @@ -1095,13 +1216,14 @@ |
1728 | indicator_entry_to_variant (entry, id, indicator_id, b, prio); |
1729 | g_free (id); |
1730 | } |
1731 | + |
1732 | + g_list_free (entries); |
1733 | } |
1734 | else |
1735 | { |
1736 | /* Add a null entry to indicate that there is an indicator here, it's just empty */ |
1737 | indicator_entry_null_to_variant (indicator_id, b); |
1738 | } |
1739 | - g_list_free (entries); |
1740 | } |
1741 | |
1742 | static void |
1743 | @@ -1147,7 +1269,7 @@ |
1744 | priv->use_event = FALSE; |
1745 | priv->pressed_entry = NULL; |
1746 | |
1747 | - g_signal_emit (self, _service_signals[ENTRY_ACTIVATED], 0, ""); |
1748 | + g_signal_emit (self, _service_signals[ENTRY_ACTIVATED], 0, "", 0, 0, 0, 0); |
1749 | } |
1750 | |
1751 | /* |
1752 | @@ -1226,15 +1348,29 @@ |
1753 | { |
1754 | IndicatorObject *object; |
1755 | IndicatorObjectEntry *entry; |
1756 | + gboolean valid_entry = TRUE; |
1757 | PanelServicePrivate *priv = self->priv; |
1758 | |
1759 | - panel_service_get_indicator_entry_by_id (self, entry_id, &entry, &object); |
1760 | + entry = get_indicator_entry_by_id (self, entry_id); |
1761 | + |
1762 | + /* If the entry we read is not valid, maybe it has already been removed |
1763 | + * or unparented, so we need to make sure that the related key on the |
1764 | + * entry2geometry_hash is correctly removed and the value is free'd */ |
1765 | + if (!entry) |
1766 | + { |
1767 | + IndicatorObjectEntry *invalid_entry; |
1768 | + if (sscanf (entry_id, "%p", &invalid_entry) == 1) |
1769 | + { |
1770 | + entry = invalid_entry; |
1771 | + valid_entry = FALSE; |
1772 | + } |
1773 | + } |
1774 | |
1775 | if (entry) |
1776 | { |
1777 | GHashTable *entry2geometry_hash = g_hash_table_lookup (priv->panel2entries_hash, panel_id); |
1778 | |
1779 | - if (width < 0 || height < 0) |
1780 | + if (width < 0 || height < 0 || !valid_entry) |
1781 | { |
1782 | if (entry2geometry_hash) |
1783 | { |
1784 | @@ -1247,63 +1383,110 @@ |
1785 | g_hash_table_remove (priv->panel2entries_hash, panel_id); |
1786 | } |
1787 | } |
1788 | + |
1789 | + /* If the entry has been removed let's make sure that its menu is closed */ |
1790 | + if (valid_entry && GTK_IS_MENU (priv->last_menu) && priv->last_menu == entry->menu) |
1791 | + { |
1792 | + gtk_menu_popdown (entry->menu); |
1793 | + } |
1794 | } |
1795 | else |
1796 | { |
1797 | GdkRectangle *geo = NULL; |
1798 | |
1799 | if (entry2geometry_hash == NULL) |
1800 | - { |
1801 | - //FIXME - this leaks memory but i'm not 100% on the logic, |
1802 | - // using g_free as the keys destructor function causes all |
1803 | - // kinds of problems |
1804 | - entry2geometry_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, |
1805 | - NULL, g_free); |
1806 | - g_hash_table_insert (priv->panel2entries_hash, g_strdup (panel_id), |
1807 | - entry2geometry_hash); |
1808 | - } |
1809 | + { |
1810 | + entry2geometry_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, |
1811 | + NULL, g_free); |
1812 | + g_hash_table_insert (priv->panel2entries_hash, g_strdup (panel_id), |
1813 | + entry2geometry_hash); |
1814 | + } |
1815 | else |
1816 | - { |
1817 | - geo = g_hash_table_lookup (entry2geometry_hash, entry); |
1818 | - } |
1819 | + { |
1820 | + geo = g_hash_table_lookup (entry2geometry_hash, entry); |
1821 | + } |
1822 | |
1823 | if (geo == NULL) |
1824 | { |
1825 | - geo = g_new (GdkRectangle, 1); |
1826 | + geo = g_new0 (GdkRectangle, 1); |
1827 | g_hash_table_insert (entry2geometry_hash, entry, geo); |
1828 | } |
1829 | |
1830 | + /* If the current entry geometry has changed, we need to move the menu |
1831 | + * accordingly to the change we recorded! */ |
1832 | + if (GTK_IS_MENU (priv->last_menu) && priv->last_menu == entry->menu) |
1833 | + { |
1834 | + GtkWidget *top_widget = gtk_widget_get_toplevel (GTK_WIDGET (priv->last_menu)); |
1835 | + |
1836 | + if (GTK_IS_WINDOW (top_widget)) |
1837 | + { |
1838 | + GtkWindow *top_win = GTK_WINDOW (top_widget); |
1839 | + gint old_x, old_y; |
1840 | + |
1841 | + gtk_window_get_position (top_win, &old_x, &old_y); |
1842 | + gtk_window_move (top_win, old_x - (geo->x - x), old_y - (geo->y - y)); |
1843 | + } |
1844 | + } |
1845 | + |
1846 | geo->x = x; |
1847 | geo->y = y; |
1848 | geo->width = width; |
1849 | geo->height = height; |
1850 | } |
1851 | |
1852 | - g_signal_emit (self, _service_signals[GEOMETRIES_CHANGED], 0, object, entry, x, y, width, height); |
1853 | + if (valid_entry) |
1854 | + { |
1855 | + object = get_entry_parent_indicator (entry); |
1856 | + g_signal_emit (self, _service_signals[GEOMETRIES_CHANGED], 0, object, entry, x, y, width, height); |
1857 | + } |
1858 | } |
1859 | } |
1860 | |
1861 | static gboolean |
1862 | -should_skip_menu (IndicatorObjectEntry *entry) |
1863 | +panel_service_entry_is_visible (PanelService *self, IndicatorObjectEntry *entry) |
1864 | { |
1865 | - gboolean label_ok = FALSE; |
1866 | - gboolean image_ok = FALSE; |
1867 | - |
1868 | - g_return_val_if_fail (entry != NULL, TRUE); |
1869 | + GHashTableIter panel_iter; |
1870 | + gpointer key, value; |
1871 | + gboolean found_geo; |
1872 | + |
1873 | + g_return_val_if_fail (PANEL_IS_SERVICE (self), FALSE); |
1874 | + g_return_val_if_fail (entry != NULL, FALSE); |
1875 | + |
1876 | + found_geo = FALSE; |
1877 | + g_hash_table_iter_init (&panel_iter, self->priv->panel2entries_hash); |
1878 | + |
1879 | + while (g_hash_table_iter_next (&panel_iter, &key, &value) && !found_geo) |
1880 | + { |
1881 | + GHashTable *entry2geometry_hash = value; |
1882 | + |
1883 | + if (g_hash_table_lookup (entry2geometry_hash, entry)) |
1884 | + { |
1885 | + found_geo = TRUE; |
1886 | + } |
1887 | + } |
1888 | + |
1889 | + if (!found_geo) |
1890 | + return FALSE; |
1891 | |
1892 | if (GTK_IS_LABEL (entry->label)) |
1893 | { |
1894 | - label_ok = gtk_widget_get_visible (GTK_WIDGET (entry->label)) |
1895 | - && gtk_widget_is_sensitive (GTK_WIDGET (entry->label)); |
1896 | + if (gtk_widget_get_visible (GTK_WIDGET (entry->label)) && |
1897 | + gtk_widget_is_sensitive (GTK_WIDGET (entry->label))) |
1898 | + { |
1899 | + return TRUE; |
1900 | + } |
1901 | } |
1902 | |
1903 | if (GTK_IS_IMAGE (entry->image)) |
1904 | { |
1905 | - image_ok = gtk_widget_get_visible (GTK_WIDGET (entry->image)) |
1906 | - && gtk_widget_is_sensitive (GTK_WIDGET (entry->image)); |
1907 | + if (gtk_widget_get_visible (GTK_WIDGET (entry->image)) && |
1908 | + gtk_widget_is_sensitive (GTK_WIDGET (entry->image))) |
1909 | + { |
1910 | + return TRUE; |
1911 | + } |
1912 | } |
1913 | |
1914 | - return !label_ok && !image_ok; |
1915 | + return TRUE; |
1916 | } |
1917 | |
1918 | static int |
1919 | @@ -1341,7 +1524,7 @@ |
1920 | gint prio = -1; |
1921 | new_entry = ll->data; |
1922 | |
1923 | - if (should_skip_menu (new_entry)) |
1924 | + if (!panel_service_entry_is_visible (self, new_entry)) |
1925 | continue; |
1926 | |
1927 | if (new_entry->name_hint) |
1928 | @@ -1388,7 +1571,7 @@ |
1929 | |
1930 | if (new_entry) |
1931 | { |
1932 | - id = g_strdup_printf ("%p", new_entry); |
1933 | + id = get_indicator_entry_id_by_entry (new_entry); |
1934 | g_signal_emit (self, _service_signals[ENTRY_ACTIVATE_REQUEST], 0, id); |
1935 | g_free (id); |
1936 | } |
1937 | @@ -1433,7 +1616,7 @@ |
1938 | } |
1939 | |
1940 | /* Find the next/prev indicator */ |
1941 | - object = g_hash_table_lookup (priv->entry2indicator_hash, priv->last_entry); |
1942 | + object = get_entry_parent_indicator(priv->last_entry); |
1943 | if (object == NULL) |
1944 | { |
1945 | g_warning ("Unable to find IndicatorObject for entry"); |
1946 | @@ -1450,23 +1633,25 @@ |
1947 | gtk_widget_destroy (menu); |
1948 | } |
1949 | |
1950 | -void |
1951 | -panel_service_show_entry (PanelService *self, |
1952 | - const gchar *entry_id, |
1953 | - guint32 timestamp, |
1954 | - gint32 x, |
1955 | - gint32 y, |
1956 | - gint32 button) |
1957 | +static void |
1958 | +panel_service_show_entry_common (PanelService *self, |
1959 | + IndicatorObject *object, |
1960 | + IndicatorObjectEntry *entry, |
1961 | + guint32 xid, |
1962 | + gint32 x, |
1963 | + gint32 y, |
1964 | + guint32 button, |
1965 | + guint32 timestamp) |
1966 | { |
1967 | - IndicatorObject *object; |
1968 | - IndicatorObjectEntry *entry; |
1969 | - GtkWidget *last_menu; |
1970 | - PanelServicePrivate *priv = self->priv; |
1971 | - |
1972 | - panel_service_get_indicator_entry_by_id (self, entry_id, &entry, &object); |
1973 | - |
1974 | + PanelServicePrivate *priv; |
1975 | + GtkWidget *last_menu; |
1976 | + |
1977 | + g_return_if_fail (PANEL_IS_SERVICE (self)); |
1978 | + g_return_if_fail (INDICATOR_IS_OBJECT (object)); |
1979 | g_return_if_fail (entry); |
1980 | |
1981 | + priv = self->priv; |
1982 | + |
1983 | if (priv->last_entry == entry) |
1984 | return; |
1985 | |
1986 | @@ -1489,7 +1674,14 @@ |
1987 | |
1988 | if (entry != NULL) |
1989 | { |
1990 | - g_signal_emit (self, _service_signals[ENTRY_ACTIVATED], 0, entry_id); |
1991 | + if (xid > 0) |
1992 | + { |
1993 | + indicator_object_entry_activate_window (object, entry, xid, CurrentTime); |
1994 | + } |
1995 | + else |
1996 | + { |
1997 | + indicator_object_entry_activate (object, entry, CurrentTime); |
1998 | + } |
1999 | |
2000 | if (GTK_IS_MENU (entry->menu)) |
2001 | { |
2002 | @@ -1526,29 +1718,33 @@ |
2003 | priv->last_menu_move_id = g_signal_connect_after (priv->last_menu, "move-current", |
2004 | G_CALLBACK (on_active_menu_move_current), self); |
2005 | |
2006 | - indicator_object_entry_activate (object, entry, CurrentTime); |
2007 | - |
2008 | gtk_menu_popup (priv->last_menu, NULL, NULL, positon_menu, self, 0, CurrentTime); |
2009 | GdkWindow *gdkwin = gtk_widget_get_window (GTK_WIDGET (priv->last_menu)); |
2010 | + |
2011 | if (gdkwin != NULL) |
2012 | - { |
2013 | - gint left=0, top=0, width=0, height=0; |
2014 | - |
2015 | - gdk_window_get_geometry (gdkwin, NULL, NULL, &width, &height); |
2016 | - gdk_window_get_origin (gdkwin, &left, &top); |
2017 | - |
2018 | - priv->last_left = left; |
2019 | - priv->last_right = left + width -1; |
2020 | - priv->last_top = top; |
2021 | - priv->last_bottom = top + height -1; |
2022 | - } |
2023 | + { |
2024 | + gint left=0, top=0, width=0, height=0; |
2025 | + |
2026 | + gdk_window_get_geometry (gdkwin, NULL, NULL, &width, &height); |
2027 | + gdk_window_get_origin (gdkwin, &left, &top); |
2028 | + |
2029 | + gchar *entry_id = get_indicator_entry_id_by_entry (entry); |
2030 | + g_signal_emit (self, _service_signals[ENTRY_ACTIVATED], 0, entry_id, |
2031 | + left, top, width, height); |
2032 | + g_free (entry_id); |
2033 | + |
2034 | + priv->last_left = left; |
2035 | + priv->last_right = left + width -1; |
2036 | + priv->last_top = top; |
2037 | + priv->last_bottom = top + height -1; |
2038 | + } |
2039 | else |
2040 | - { |
2041 | - priv->last_left = 0; |
2042 | - priv->last_right = 0; |
2043 | - priv->last_top = 0; |
2044 | - priv->last_bottom = 0; |
2045 | - } |
2046 | + { |
2047 | + priv->last_left = 0; |
2048 | + priv->last_right = 0; |
2049 | + priv->last_top = 0; |
2050 | + priv->last_bottom = 0; |
2051 | + } |
2052 | } |
2053 | |
2054 | /* We popdown the old one last so we don't accidently send key focus back to the |
2055 | @@ -1560,6 +1756,53 @@ |
2056 | } |
2057 | |
2058 | void |
2059 | +panel_service_show_entry (PanelService *self, |
2060 | + const gchar *entry_id, |
2061 | + guint32 xid, |
2062 | + gint32 x, |
2063 | + gint32 y, |
2064 | + guint32 button, |
2065 | + guint32 timestamp) |
2066 | +{ |
2067 | + IndicatorObject *object; |
2068 | + IndicatorObjectEntry *entry; |
2069 | + |
2070 | + g_return_if_fail (PANEL_IS_SERVICE (self)); |
2071 | + |
2072 | + entry = get_indicator_entry_by_id (self, entry_id); |
2073 | + object = get_entry_parent_indicator (entry); |
2074 | + |
2075 | + panel_service_show_entry_common (self, object, entry, xid, x, y, button, timestamp); |
2076 | +} |
2077 | + |
2078 | +void |
2079 | +panel_service_show_app_menu (PanelService *self, |
2080 | + guint32 xid, |
2081 | + gint32 x, |
2082 | + gint32 y, |
2083 | + guint32 timestamp) |
2084 | +{ |
2085 | + IndicatorObject *object; |
2086 | + IndicatorObjectEntry *entry; |
2087 | + GList *entries; |
2088 | + |
2089 | + g_return_if_fail (PANEL_IS_SERVICE (self)); |
2090 | + |
2091 | + object = panel_service_get_indicator (self, "libappmenu.so"); |
2092 | + g_return_if_fail (INDICATOR_IS_OBJECT (object)); |
2093 | + |
2094 | + entries = indicator_object_get_entries (object); |
2095 | + |
2096 | + if (entries) |
2097 | + { |
2098 | + entry = entries->data; |
2099 | + g_list_free (entries); |
2100 | + |
2101 | + panel_service_show_entry_common (self, object, entry, xid, x, y, 1, timestamp); |
2102 | + } |
2103 | +} |
2104 | + |
2105 | +void |
2106 | panel_service_secondary_activate_entry (PanelService *self, |
2107 | const gchar *entry_id, |
2108 | guint32 timestamp) |
2109 | @@ -1567,9 +1810,10 @@ |
2110 | IndicatorObject *object; |
2111 | IndicatorObjectEntry *entry; |
2112 | |
2113 | - panel_service_get_indicator_entry_by_id (self, entry_id, &entry, &object); |
2114 | + entry = get_indicator_entry_by_id (self, entry_id); |
2115 | g_return_if_fail (entry); |
2116 | |
2117 | + object = get_entry_parent_indicator (entry); |
2118 | g_signal_emit_by_name(object, INDICATOR_OBJECT_SIGNAL_SECONDARY_ACTIVATE, entry, |
2119 | timestamp); |
2120 | } |
2121 | @@ -1582,11 +1826,12 @@ |
2122 | IndicatorObject *object; |
2123 | IndicatorObjectEntry *entry; |
2124 | |
2125 | - panel_service_get_indicator_entry_by_id (self, entry_id, &entry, &object); |
2126 | + entry = get_indicator_entry_by_id (self, entry_id); |
2127 | g_return_if_fail (entry); |
2128 | |
2129 | GdkScrollDirection direction = delta < 0 ? GDK_SCROLL_DOWN : GDK_SCROLL_UP; |
2130 | |
2131 | + object = get_entry_parent_indicator (entry); |
2132 | g_signal_emit_by_name(object, INDICATOR_OBJECT_SIGNAL_ENTRY_SCROLLED, entry, |
2133 | abs(delta/120), direction); |
2134 | } |
2135 | |
2136 | === modified file 'services/panel-service.h' |
2137 | --- services/panel-service.h 2011-09-04 12:11:22 +0000 |
2138 | +++ services/panel-service.h 2012-03-20 10:02:20 +0000 |
2139 | @@ -95,10 +95,17 @@ |
2140 | |
2141 | void panel_service_show_entry (PanelService *self, |
2142 | const gchar *entry_id, |
2143 | - guint32 timestamp, |
2144 | - gint32 x, |
2145 | - gint32 y, |
2146 | - gint32 button); |
2147 | + guint32 xid, |
2148 | + gint32 x, |
2149 | + gint32 y, |
2150 | + guint32 button, |
2151 | + guint32 timestamp); |
2152 | + |
2153 | +void panel_service_show_app_menu (PanelService *self, |
2154 | + guint32 xid, |
2155 | + gint32 x, |
2156 | + gint32 y, |
2157 | + guint32 timestamp); |
2158 | |
2159 | void panel_service_secondary_activate_entry (PanelService *self, |
2160 | const gchar *entry_id, |
2161 | |
2162 | === modified file 'tests/CMakeLists.txt' |
2163 | --- tests/CMakeLists.txt 2012-03-13 01:59:15 +0000 |
2164 | +++ tests/CMakeLists.txt 2012-03-20 10:02:20 +0000 |
2165 | @@ -45,9 +45,18 @@ |
2166 | # We can't have convenience libs so we need to rebuild with what we need |
2167 | # Please keep actual test files alphabetically at top and then files |
2168 | # from ../${UNITY_SRC} or ../../services in alphabetically after that |
2169 | +find_program(GLIB_GENMARSHAL glib-genmarshal) |
2170 | +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/panel-marshal.c |
2171 | + COMMAND ${GLIB_GENMARSHAL} ARGS ../services/panel-marshal.list --body --prefix=panel_marshal > ${CMAKE_CURRENT_BINARY_DIR}/panel-marshal.c |
2172 | + COMMAND ${GLIB_GENMARSHAL} ARGS ../services/panel-marshal.list --header --prefix=panel_marshal > ${CMAKE_CURRENT_BINARY_DIR}/panel-marshal.h |
2173 | + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} |
2174 | + DEPENDS ../services/panel-marshal.list |
2175 | + COMMENT "Generating marshallers for panel-service") |
2176 | + |
2177 | add_executable (test-unit |
2178 | + unit/TestMain.cpp |
2179 | unit/TestQuicklistMenuitems.cpp |
2180 | - unit/TestMain.cpp |
2181 | + unit/TestPanelService.cpp |
2182 | unit/TestUBus.cpp |
2183 | unit/TestStaticCairoText.cpp |
2184 | ${UNITY_SRC}/CairoBaseWindow.cpp |
2185 | @@ -59,6 +68,8 @@ |
2186 | ${UNITY_SRC}/QuicklistMenuItemSeparator.cpp |
2187 | ${UNITY_SRC}/QuicklistView.cpp |
2188 | ${UNITY_SRC}/StaticCairoText.cpp |
2189 | + ../services/panel-service.c |
2190 | + ${CMAKE_CURRENT_BINARY_DIR}/panel-marshal.c |
2191 | ${UNITY_SRC}/ubus-server.cpp |
2192 | ) |
2193 | add_dependencies (test-unit unity-core-${UNITY_API_VERSION}) |
2194 | @@ -114,6 +125,9 @@ |
2195 | test_glib_signals_utils.h |
2196 | test_glib_variant.cpp |
2197 | ${CMAKE_CURRENT_BINARY_DIR}/test_glib_signals_utils_marshal.cpp |
2198 | + test_indicator.cpp |
2199 | + test_indicator_appmenu.cpp |
2200 | + test_indicator_entry.cpp |
2201 | test_favorite_store_gsettings.cpp |
2202 | test_favorite_store_private.cpp |
2203 | test_home_lens.cpp |
2204 | @@ -180,7 +194,6 @@ |
2205 | test_filter.cpp |
2206 | test_gdbus_proxy.cpp |
2207 | test_hud.cpp |
2208 | - test_indicator_entry.cpp |
2209 | test_lens.cpp |
2210 | test_main_dbus.cpp |
2211 | test_model.cpp |
2212 | |
2213 | === added file 'tests/test_indicator.cpp' |
2214 | --- tests/test_indicator.cpp 1970-01-01 00:00:00 +0000 |
2215 | +++ tests/test_indicator.cpp 2012-03-20 10:02:20 +0000 |
2216 | @@ -0,0 +1,207 @@ |
2217 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
2218 | +/* |
2219 | + * Copyright (C) 2012 Canonical Ltd |
2220 | + * |
2221 | + * This program is free software: you can redistribute it and/or modify |
2222 | + * it under the terms of the GNU General Public License version 3 as |
2223 | + * published by the Free Software Foundation. |
2224 | + * |
2225 | + * This program is distributed in the hope that it will be useful, |
2226 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2227 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2228 | + * GNU General Public License for more details. |
2229 | + * |
2230 | + * You should have received a copy of the GNU General Public License |
2231 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2232 | + * |
2233 | + * Authored by: Marco Trevisan (Treviño) <3v1n0@ubuntu.com> |
2234 | + */ |
2235 | + |
2236 | +#include <UnityCore/Indicator.h> |
2237 | + |
2238 | +#include <gtest/gtest.h> |
2239 | + |
2240 | +using namespace std; |
2241 | +using namespace unity; |
2242 | +using namespace indicator; |
2243 | + |
2244 | +namespace |
2245 | +{ |
2246 | + |
2247 | +TEST(TestIndicator, Construction) |
2248 | +{ |
2249 | + Indicator indicator("indicator-test"); |
2250 | + |
2251 | + EXPECT_EQ(indicator.name(), "indicator-test"); |
2252 | + EXPECT_FALSE(indicator.IsAppmenu()); |
2253 | + EXPECT_EQ(indicator.GetEntry("test-entry"), nullptr); |
2254 | + EXPECT_TRUE(indicator.GetEntries().empty()); |
2255 | +} |
2256 | + |
2257 | +TEST(TestIndicator, Syncing) |
2258 | +{ |
2259 | + Indicator::Entries sync_data; |
2260 | + Entry* entry; |
2261 | + |
2262 | + Indicator indicator("indicator-test"); |
2263 | + |
2264 | + // Connecting to signals |
2265 | + Indicator::Entries added; |
2266 | + indicator.on_entry_added.connect([&added] (Entry::Ptr const& e) { |
2267 | + added.push_back(e); |
2268 | + }); |
2269 | + |
2270 | + std::vector<std::string> removed; |
2271 | + sigc::connection removed_connection = indicator.on_entry_removed.connect([&removed] |
2272 | + (std::string const& en_id) { |
2273 | + removed.push_back(en_id); |
2274 | + }); |
2275 | + |
2276 | + entry = new Entry("test-entry-1", "name-hint", "label", true, true, 0, "icon", |
2277 | + true, true, -1); |
2278 | + Entry::Ptr entry1(entry); |
2279 | + sync_data.push_back(entry1); |
2280 | + |
2281 | + entry = new Entry("test-entry-2", "name-hint", "label", true, true, 0, "icon", |
2282 | + true, true, -1); |
2283 | + Entry::Ptr entry2(entry); |
2284 | + sync_data.push_back(entry2); |
2285 | + |
2286 | + entry = new Entry("test-entry-3", "name-hint", "label", true, true, 0, "icon", |
2287 | + true, true, -1); |
2288 | + Entry::Ptr entry3(entry); |
2289 | + sync_data.push_back(entry3); |
2290 | + |
2291 | + // Sync the indicator, adding 3 entries |
2292 | + indicator.Sync(sync_data); |
2293 | + EXPECT_EQ(indicator.GetEntries().size(), 3); |
2294 | + EXPECT_EQ(indicator.GetEntry("test-entry-2"), entry2); |
2295 | + EXPECT_EQ(added.size(), 3); |
2296 | + EXPECT_EQ(added.front()->id(), "test-entry-1"); |
2297 | + EXPECT_EQ(added.back()->id(), "test-entry-3"); |
2298 | + EXPECT_EQ(removed.size(), 0); |
2299 | + |
2300 | + added.clear(); |
2301 | + removed.clear(); |
2302 | + |
2303 | + // Sync the indicator removing an entry |
2304 | + sync_data.remove(entry2); |
2305 | + EXPECT_EQ(sync_data.size(), 2); |
2306 | + |
2307 | + indicator.Sync(sync_data); |
2308 | + EXPECT_EQ(indicator.GetEntries().size(), 2); |
2309 | + EXPECT_EQ(indicator.GetEntry("test-entry-2"), nullptr); |
2310 | + EXPECT_EQ(added.size(), 0); |
2311 | + EXPECT_EQ(removed.size(), 1); |
2312 | + EXPECT_EQ(removed.front(), entry2->id()); |
2313 | + |
2314 | + // Sync the indicator removing an entry and adding a new one |
2315 | + entry = new Entry("test-entry-4", "name-hint", "label", true, true, 0, "icon", |
2316 | + true, true, -1); |
2317 | + Entry::Ptr entry4(entry); |
2318 | + sync_data.push_back(entry4); |
2319 | + sync_data.remove(entry3); |
2320 | + EXPECT_EQ(sync_data.size(), 2); |
2321 | + |
2322 | + added.clear(); |
2323 | + removed.clear(); |
2324 | + |
2325 | + indicator.Sync(sync_data); |
2326 | + EXPECT_EQ(indicator.GetEntries().size(), 2); |
2327 | + EXPECT_EQ(added.size(), 1); |
2328 | + EXPECT_EQ(added.front(), entry4); |
2329 | + EXPECT_EQ(removed.size(), 1); |
2330 | + EXPECT_EQ(removed.front(), entry3->id()); |
2331 | + |
2332 | + // Remove all the indicators |
2333 | + added.clear(); |
2334 | + removed.clear(); |
2335 | + |
2336 | + sync_data.clear(); |
2337 | + indicator.Sync(sync_data); |
2338 | + EXPECT_EQ(indicator.GetEntries().size(), 0); |
2339 | + EXPECT_EQ(added.size(), 0); |
2340 | + EXPECT_EQ(removed.size(), 2); |
2341 | + |
2342 | + removed_connection.disconnect(); |
2343 | +} |
2344 | + |
2345 | +TEST(TestIndicator, ChildrenSignals) |
2346 | +{ |
2347 | + Indicator::Entries sync_data; |
2348 | + Entry* entry; |
2349 | + |
2350 | + Indicator indicator("indicator-test"); |
2351 | + |
2352 | + entry = new Entry("test-entry-1", "name-hint", "label", true, true, 0, "icon", |
2353 | + true, true, -1); |
2354 | + Entry::Ptr entry1(entry); |
2355 | + sync_data.push_back(entry1); |
2356 | + |
2357 | + indicator.Sync(sync_data); |
2358 | + |
2359 | + std::string show_entry; |
2360 | + int show_x, show_y; |
2361 | + unsigned int show_xid, show_button, show_timestamp; |
2362 | + |
2363 | + // Connecting to signals |
2364 | + indicator.on_show_menu.connect([&] (std::string const& eid, unsigned int xid, |
2365 | + int x, int y, unsigned int button, |
2366 | + unsigned int timestamp) { |
2367 | + show_entry = eid; |
2368 | + show_xid = xid; |
2369 | + show_x = x; |
2370 | + show_y = y; |
2371 | + show_button = button; |
2372 | + show_timestamp = timestamp; |
2373 | + }); |
2374 | + |
2375 | + entry1->ShowMenu(123456789, 50, 100, 2, 1328058770); |
2376 | + EXPECT_EQ(show_entry, "test-entry-1"); |
2377 | + EXPECT_EQ(show_xid, 123456789); |
2378 | + EXPECT_EQ(show_x, 50); |
2379 | + EXPECT_EQ(show_y, 100); |
2380 | + EXPECT_EQ(show_button, 2); |
2381 | + EXPECT_EQ(show_timestamp, 1328058770); |
2382 | + |
2383 | + // Check if a removed entry still emits a signal to the old indicator |
2384 | + show_entry = "invalid-entry"; |
2385 | + sync_data.remove(entry1); |
2386 | + indicator.Sync(sync_data); |
2387 | + |
2388 | + entry1->ShowMenu(123456789, 50, 100, 2, 1328058770); |
2389 | + EXPECT_EQ(show_entry, "invalid-entry"); |
2390 | + |
2391 | + // Checking secondary activate signal |
2392 | + entry = new Entry("test-entry-2", "name-hint", "label", true, true, 0, "icon", |
2393 | + true, true, -1); |
2394 | + sync_data.push_back(Entry::Ptr(entry)); |
2395 | + indicator.Sync(sync_data); |
2396 | + |
2397 | + std::string secondary_activated; |
2398 | + unsigned int secondary_timestamp; |
2399 | + indicator.on_secondary_activate.connect([&] (std::string const& eid, |
2400 | + unsigned int timestamp) { |
2401 | + secondary_activated = eid; |
2402 | + secondary_timestamp = timestamp; |
2403 | + }); |
2404 | + |
2405 | + entry->SecondaryActivate(1328060717); |
2406 | + EXPECT_EQ(secondary_activated, "test-entry-2"); |
2407 | + EXPECT_EQ(secondary_timestamp, 1328060717); |
2408 | + |
2409 | + // Checking scroll signal |
2410 | + std::string scrolled_entry; |
2411 | + int scrolled_delta; |
2412 | + |
2413 | + indicator.on_scroll.connect([&] (std::string const& eid, int delta) { |
2414 | + scrolled_entry = eid; |
2415 | + scrolled_delta = delta; |
2416 | + }); |
2417 | + |
2418 | + entry->Scroll(-5); |
2419 | + EXPECT_EQ(scrolled_entry, "test-entry-2"); |
2420 | + EXPECT_EQ(scrolled_delta, -5); |
2421 | +} |
2422 | + |
2423 | +} |
2424 | |
2425 | === added file 'tests/test_indicator_appmenu.cpp' |
2426 | --- tests/test_indicator_appmenu.cpp 1970-01-01 00:00:00 +0000 |
2427 | +++ tests/test_indicator_appmenu.cpp 2012-03-20 10:02:20 +0000 |
2428 | @@ -0,0 +1,66 @@ |
2429 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
2430 | +/* |
2431 | + * Copyright (C) 2012 Canonical Ltd |
2432 | + * |
2433 | + * This program is free software: you can redistribute it and/or modify |
2434 | + * it under the terms of the GNU General Public License version 3 as |
2435 | + * published by the Free Software Foundation. |
2436 | + * |
2437 | + * This program is distributed in the hope that it will be useful, |
2438 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2439 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2440 | + * GNU General Public License for more details. |
2441 | + * |
2442 | + * You should have received a copy of the GNU General Public License |
2443 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2444 | + * |
2445 | + * Authored by: Marco Trevisan (Treviño) <3v1n0@ubuntu.com> |
2446 | + */ |
2447 | + |
2448 | +#include <UnityCore/AppmenuIndicator.h> |
2449 | + |
2450 | +#include <gtest/gtest.h> |
2451 | + |
2452 | +using namespace std; |
2453 | +using namespace unity; |
2454 | +using namespace indicator; |
2455 | + |
2456 | +namespace |
2457 | +{ |
2458 | + |
2459 | +TEST(TestAppmenuIndicator, Construction) |
2460 | +{ |
2461 | + AppmenuIndicator indicator("indicator-appmenu"); |
2462 | + |
2463 | + EXPECT_EQ(indicator.name(), "indicator-appmenu"); |
2464 | + EXPECT_TRUE(indicator.IsAppmenu()); |
2465 | +} |
2466 | + |
2467 | +TEST(TestAppmenuIndicator, ShowAppmenu) |
2468 | +{ |
2469 | + AppmenuIndicator indicator("indicator-appmenu"); |
2470 | + |
2471 | + bool signal_emitted = false; |
2472 | + int show_x, show_y; |
2473 | + unsigned int show_xid, show_timestamp; |
2474 | + |
2475 | + // Connecting to signals |
2476 | + indicator.on_show_appmenu.connect([&] (unsigned int xid, int x, int y, |
2477 | + unsigned int timestamp) { |
2478 | + signal_emitted = true; |
2479 | + show_xid = xid; |
2480 | + show_x = x; |
2481 | + show_y = y; |
2482 | + show_timestamp = timestamp; |
2483 | + }); |
2484 | + |
2485 | + indicator.ShowAppmenu(123456789, 50, 100, 1328308554); |
2486 | + EXPECT_TRUE(signal_emitted); |
2487 | + |
2488 | + EXPECT_EQ(show_xid, 123456789); |
2489 | + EXPECT_EQ(show_x, 50); |
2490 | + EXPECT_EQ(show_y, 100); |
2491 | + EXPECT_EQ(show_timestamp, 1328308554); |
2492 | +} |
2493 | + |
2494 | +} |
2495 | |
2496 | === modified file 'tests/test_indicator_entry.cpp' |
2497 | --- tests/test_indicator_entry.cpp 2011-09-08 14:41:57 +0000 |
2498 | +++ tests/test_indicator_entry.cpp 2012-03-20 10:02:20 +0000 |
2499 | @@ -24,7 +24,7 @@ |
2500 | EXPECT_TRUE(entry.image_visible()); |
2501 | EXPECT_FALSE(entry.active()); |
2502 | EXPECT_FALSE(entry.show_now()); |
2503 | - EXPECT_FALSE(entry.IsUnused()); |
2504 | + EXPECT_TRUE(entry.visible()); |
2505 | EXPECT_EQ(entry.image_type(), 1); |
2506 | EXPECT_EQ(entry.image_data(), "some icon"); |
2507 | EXPECT_EQ(entry.priority(), -1); |
2508 | @@ -77,21 +77,6 @@ |
2509 | EXPECT_EQ(entry.priority(), 5); |
2510 | } |
2511 | |
2512 | -TEST(TestIndicatorEntry, TestUnused) |
2513 | -{ |
2514 | - |
2515 | - indicator::Entry entry("id", "name_hint", "label", true, true, |
2516 | - 0, "some icon", false, true, -1); |
2517 | - |
2518 | - Counter counter; |
2519 | - entry.updated.connect(sigc::mem_fun(counter, &Counter::increment)); |
2520 | - |
2521 | - entry.MarkUnused(); |
2522 | - EXPECT_TRUE(entry.IsUnused()); |
2523 | - // Setting unused emits updated. |
2524 | - EXPECT_EQ(counter.count, 1); |
2525 | -} |
2526 | - |
2527 | TEST(TestIndicatorEntry, TestShowNowEvents) |
2528 | { |
2529 | |
2530 | @@ -174,16 +159,18 @@ |
2531 | |
2532 | struct ShowMenuRecorder |
2533 | { |
2534 | - void OnShowMenu(std::string const& a, int b, int c, int d, int e) |
2535 | + void OnShowMenu(std::string const& a, unsigned int b, int c, int d, unsigned int e, unsigned int f) |
2536 | { |
2537 | name = a; |
2538 | - x = b; |
2539 | - y = c; |
2540 | - timestamp = d; |
2541 | + xid = b; |
2542 | + x = c; |
2543 | + y = d; |
2544 | button = e; |
2545 | + timestamp = f; |
2546 | } |
2547 | std::string name; |
2548 | - int x, y, timestamp, button; |
2549 | + unsigned int xid, timestamp, button; |
2550 | + int x, y; |
2551 | }; |
2552 | |
2553 | TEST(TestIndicatorEntry, TestOnShowMenu) |
2554 | @@ -195,13 +182,103 @@ |
2555 | ShowMenuRecorder recorder; |
2556 | entry.on_show_menu.connect(sigc::mem_fun(recorder, &ShowMenuRecorder::OnShowMenu)); |
2557 | |
2558 | - entry.ShowMenu(10, 20, 12345, 1); |
2559 | + entry.ShowMenu(10, 20, 1, 12345); |
2560 | EXPECT_EQ(recorder.name, "id"); |
2561 | + EXPECT_EQ(recorder.xid, 0); |
2562 | EXPECT_EQ(recorder.x, 10); |
2563 | EXPECT_EQ(recorder.y, 20); |
2564 | EXPECT_EQ(recorder.timestamp, 12345); |
2565 | EXPECT_EQ(recorder.button, 1); |
2566 | } |
2567 | |
2568 | +TEST(TestIndicatorEntry, TestOnShowMenuXid) |
2569 | +{ |
2570 | + |
2571 | + indicator::Entry entry("xid", "name_hint", "label", true, true, |
2572 | + 0, "some icon", false, true, -1); |
2573 | + |
2574 | + ShowMenuRecorder recorder; |
2575 | + entry.on_show_menu.connect(sigc::mem_fun(recorder, &ShowMenuRecorder::OnShowMenu)); |
2576 | + |
2577 | + entry.ShowMenu(88492615, 15, 25, 2, 123456); |
2578 | + EXPECT_EQ(recorder.name, "xid"); |
2579 | + EXPECT_EQ(recorder.xid, 88492615); |
2580 | + EXPECT_EQ(recorder.x, 15); |
2581 | + EXPECT_EQ(recorder.y, 25); |
2582 | + EXPECT_EQ(recorder.timestamp, 123456); |
2583 | + EXPECT_EQ(recorder.button, 2); |
2584 | +} |
2585 | + |
2586 | +TEST(TestIndicatorEntry, TestVisibility) |
2587 | +{ |
2588 | + |
2589 | + indicator::Entry entry("id", "name_hint", "label", true, true, |
2590 | + 0, "some icon", false, false, -1); |
2591 | + |
2592 | + EXPECT_TRUE(entry.visible()); |
2593 | + |
2594 | + entry.setLabel("", true, true); |
2595 | + EXPECT_FALSE(entry.visible()); |
2596 | + |
2597 | + entry.setLabel("valid-label", true, true); |
2598 | + EXPECT_TRUE(entry.visible()); |
2599 | + |
2600 | + entry.setLabel("invalid-label", true, false); |
2601 | + EXPECT_FALSE(entry.visible()); |
2602 | + |
2603 | + entry.setImage(1, "valid-image", true, true); |
2604 | + EXPECT_TRUE(entry.visible()); |
2605 | + |
2606 | + entry.setImage(1, "", true, true); |
2607 | + EXPECT_FALSE(entry.visible()); |
2608 | + |
2609 | + entry.setImage(1, "valid-image", true, true); |
2610 | + EXPECT_TRUE(entry.visible()); |
2611 | + |
2612 | + entry.setImage(0, "invalid-image-type", true, true); |
2613 | + EXPECT_FALSE(entry.visible()); |
2614 | + |
2615 | + entry.setLabel("valid-label", true, true); |
2616 | + EXPECT_TRUE(entry.visible()); |
2617 | + |
2618 | + entry.setLabel("invalid-label", true, false); |
2619 | + EXPECT_FALSE(entry.visible()); |
2620 | + |
2621 | + entry.setImage(1, "invalid-image", true, false); |
2622 | + EXPECT_FALSE(entry.visible()); |
2623 | + |
2624 | + entry.setLabel("valid-label", true, true); |
2625 | + entry.setImage(1, "valid-image", true, true); |
2626 | + EXPECT_TRUE(entry.visible()); |
2627 | +} |
2628 | + |
2629 | +TEST(TestIndicatorEntry, TestGeometry) |
2630 | +{ |
2631 | + |
2632 | + indicator::Entry entry("id", "name_hint", "label", true, true, |
2633 | + 0, "some icon", false, true, -1); |
2634 | + |
2635 | + Counter counter; |
2636 | + entry.updated.connect(sigc::mem_fun(counter, &Counter::increment)); |
2637 | + bool geo_changed = false; |
2638 | + nux::Rect new_geo; |
2639 | + |
2640 | + entry.geometry_changed.connect([&] (nux::Rect const& geo) { |
2641 | + geo_changed = true; |
2642 | + new_geo = geo; |
2643 | + }); |
2644 | + |
2645 | + // Setting to the same value doesn't emit any events. |
2646 | + entry.set_geometry(nux::Rect()); |
2647 | + EXPECT_EQ(entry.geometry(), nux::Rect()); |
2648 | + EXPECT_EQ(counter.count, 0); |
2649 | + |
2650 | + // Setting to a different value does emit the events. |
2651 | + entry.set_geometry(nux::Rect(1, 2, 3, 4)); |
2652 | + EXPECT_EQ(entry.geometry(), nux::Rect(1, 2, 3, 4)); |
2653 | + EXPECT_TRUE(geo_changed); |
2654 | + EXPECT_EQ(new_geo, nux::Rect(1, 2, 3, 4)); |
2655 | + EXPECT_EQ(counter.count, 1); |
2656 | +} |
2657 | |
2658 | } |
2659 | |
2660 | === modified file 'tests/unit/TestMain.cpp' |
2661 | --- tests/unit/TestMain.cpp 2012-01-09 16:49:50 +0000 |
2662 | +++ tests/unit/TestMain.cpp 2012-03-20 10:02:20 +0000 |
2663 | @@ -25,9 +25,9 @@ |
2664 | #include "Nux/Nux.h" |
2665 | #include "Nux/WindowThread.h" |
2666 | |
2667 | -//void TestPanelServiceCreateSuite (void); |
2668 | -void TestUBusCreateSuite(void); |
2669 | -void TestQuicklistMenuitemsCreateSuite(void); |
2670 | +void TestPanelServiceCreateSuite(); |
2671 | +void TestUBusCreateSuite(); |
2672 | +void TestQuicklistMenuitemsCreateSuite(); |
2673 | void TestStaticCairoTextCreateSuite(); |
2674 | |
2675 | nux::WindowThread* |
2676 | @@ -70,7 +70,7 @@ |
2677 | g_test_init(&argc, &argv, NULL); |
2678 | |
2679 | //Keep alphabetical please |
2680 | - //TestPanelServiceCreateSuite (); |
2681 | + TestPanelServiceCreateSuite(); |
2682 | TestQuicklistMenuitemsCreateSuite(); |
2683 | TestStaticCairoTextCreateSuite(); |
2684 | TestUBusCreateSuite(); |
2685 | |
2686 | === modified file 'tests/unit/TestPanelService.cpp' |
2687 | --- tests/unit/TestPanelService.cpp 2011-08-09 12:21:18 +0000 |
2688 | +++ tests/unit/TestPanelService.cpp 2012-03-20 10:02:20 +0000 |
2689 | @@ -177,6 +177,7 @@ |
2690 | GVariantIter* iter; |
2691 | gchar* indicator_id; |
2692 | gchar* entry_id; |
2693 | + gchar* entry_name_hint; |
2694 | gchar* label; |
2695 | gboolean label_sensitive; |
2696 | gboolean label_visible; |
2697 | @@ -185,10 +186,11 @@ |
2698 | gboolean image_sensitive; |
2699 | gboolean image_visible; |
2700 | |
2701 | - g_variant_get(result, "(a(sssbbusbb))", &iter); |
2702 | - while (g_variant_iter_loop(iter, "(sssbbusbb)", |
2703 | + g_variant_get(result, "(a(ssssbbusbbi))", &iter); |
2704 | + while (g_variant_iter_loop(iter, "(ssssbbusbbi)", |
2705 | &indicator_id, |
2706 | &entry_id, |
2707 | + &entry_name_hint, |
2708 | &label, |
2709 | &label_sensitive, |
2710 | &label_visible, |
2711 | @@ -215,8 +217,8 @@ |
2712 | guint ret = 0; |
2713 | GVariantIter* iter; |
2714 | gchar* indicator_id; |
2715 | - gchar* name_hint; |
2716 | gchar* entry_id; |
2717 | + gchar* entry_name_hint; |
2718 | gchar* label; |
2719 | gboolean label_sensitive; |
2720 | gboolean label_visible; |
2721 | @@ -229,8 +231,8 @@ |
2722 | g_variant_get(result, "(a(ssssbbusbbi))", &iter); |
2723 | while (g_variant_iter_loop(iter, "(ssssbbusbbi)", |
2724 | &indicator_id, |
2725 | - &name_hint, |
2726 | &entry_id, |
2727 | + &entry_name_hint, |
2728 | &label, |
2729 | &label_sensitive, |
2730 | &label_visible, |
Hi,
202 + // We have to do this because on certain systems X won't have time to
203 + // respond to our request for XUngrabPointer and this will cause the
204 + // menu not to show
205 + auto data = new ShowEntryData();
Can we use a smart pointer for this please? Once you use a smart pointer you won't need this:
279 + delete data;
...and there's a larger design issue around how we create Indicator instances. This code:
671 - Indicator::Ptr indicator(new Indicator(name)); r(name) ;
672 + Indicator* indptr;
673 +
674 + if (name == "libappmenu.so")
675 + indptr = new AppmenuIndicato
676 + else
677 + indptr = new Indicator(name);
678 +
679 + Indicator::Ptr indicator(indptr);
Makes me uneasy - especially this bit:
685 + >IsAppmenu( )) cast<AppmenuInd icator* >(indicator. get()); >on_show_ appmenu. connect( sigc::mem_ fun(owner_ , &Indicators: :OnShowAppMenu) );
686 + if (indicator-
687 + {
688 + AppmenuIndicator *appmenu = dynamic_
689 +
690 + if (appmenu)
691 + appmenu-
692 + }
693 +
Why are we using a boolean member variable to encode class type? Maybe I'm missing something, but why not just do this:
AppmenuIndicator *appmenu = dynamic_ cast<AppmenuInd icator* >(indicator. get());
if (appmenu) >on_show_ appmenu. connect( sigc::mem_ fun(owner_ , &Indicators: :OnShowAppMenu) );
appmenu-
..or even better, hook up the signal for all indicators, and have child classes that don't need the signal simply not use it.
This is wrong:
818 + return proxy_- >id().c_ str();
The method returns a std::string, so you don't need the ".c_str" on the end.
These:
1127 +#define COMPIZ_OPTIONS_PATH "/apps/ compiz- 1/plugins/ unityshell/ screen0/ options" KEYBINDING_ PATH COMPIZ_ OPTIONS_ PATH"/panel_ first_menu"
1128 +#define MENU_TOGGLE_
Don't need to be #defines - nor do the three #defines right above them.
In panel-service.c, I'm 99% sure there's a memory leak on line 829, where we do this:
gchar *entry_id = get_indicator_ entry_id_ by_entry (entry); table_insert (self-> priv->id2entry_ hash, entry_id, entry);
g_hash_
entry_id needs to be freed.
The points above need to be fixed. You should also get someone else to look at this (someone who understands the panel code).
Cheers,