Merge lp:~unity-team/unity/fix-lp1309778-trusty into lp:unity/7.2

Proposed by Christopher Townsend on 2015-07-15
Status: Needs review
Proposed branch: lp:~unity-team/unity/fix-lp1309778-trusty
Merge into: lp:unity/7.2
Prerequisite: lp:~unity-team/unity/fix-lp1351591-trusty
Diff against target: 5329 lines (+1369/-784)
71 files modified
UnityCore/AppmenuIndicator.cpp (+52/-12)
UnityCore/AppmenuIndicator.h (+4/-3)
UnityCore/CMakeLists.txt (+1/-0)
UnityCore/DBusIndicators.cpp (+52/-40)
UnityCore/GLibDBusServer.cpp (+3/-2)
UnityCore/GLibSource.h (+2/-2)
UnityCore/Indicator.cpp (+15/-30)
UnityCore/Indicator.h (+3/-4)
UnityCore/IndicatorEntry.cpp (+15/-5)
UnityCore/IndicatorEntry.h (+4/-1)
UnityCore/Indicators.cpp (+2/-1)
UnityCore/pch/unitycore_pch.hh (+1/-0)
com.canonical.Unity.gschema.xml (+6/-0)
dash/DashView.h (+1/-1)
dash/ScopeView.h (+2/-1)
debian/control (+1/-1)
decorations/DecoratedWindow.cpp (+13/-9)
decorations/DecorationsManager.cpp (+12/-15)
decorations/DecorationsMenuDropdown.cpp (+4/-3)
decorations/DecorationsMenuEntry.cpp (+12/-2)
decorations/DecorationsMenuEntry.h (+2/-1)
decorations/DecorationsMenuLayout.cpp (+25/-3)
decorations/DecorationsPriv.h (+3/-1)
decorations/DecorationsSlidingLayout.cpp (+1/-1)
decorations/DecorationsWidgets.cpp (+4/-9)
launcher/LauncherEntryRemoteModel.h (+2/-2)
launcher/XdndStartStopNotifierImp.h (+1/-1)
lockscreen/LockScreenPanel.cpp (+1/-1)
panel/PanelIndicatorEntryDropdownView.cpp (+6/-1)
panel/PanelIndicatorEntryDropdownView.h (+1/-0)
panel/PanelIndicatorEntryView.cpp (+7/-5)
panel/PanelIndicatorEntryView.h (+2/-3)
panel/PanelIndicatorsView.cpp (+43/-13)
panel/PanelIndicatorsView.h (+6/-4)
panel/PanelMenuView.cpp (+140/-112)
panel/PanelMenuView.h (+8/-4)
panel/PanelView.cpp (+3/-3)
plugins/unityshell/src/unityshell.cpp (+34/-44)
plugins/unityshell/src/unityshell.h (+2/-1)
services/panel-main.c (+20/-20)
services/panel-service-private.h (+22/-3)
services/panel-service.c (+148/-60)
services/panel-service.h (+0/-8)
shortcuts/ShortcutModel.h (+3/-3)
tests/autopilot/unity/emulators/panel.py (+4/-0)
tests/autopilot/unity/tests/__init__.py (+12/-13)
tests/autopilot/unity/tests/test_dash.py (+2/-2)
tests/autopilot/unity/tests/test_hud.py (+2/-2)
tests/autopilot/unity/tests/test_panel.py (+258/-211)
tests/autopilot/unity/tests/test_wm_keybindings.py (+1/-6)
tests/mock-application.h (+2/-2)
tests/test_dbus_indicators.cpp (+3/-4)
tests/test_indicator.cpp (+18/-21)
tests/test_indicator_appmenu.cpp (+182/-21)
tests/test_indicator_entry.cpp (+17/-14)
tests/test_indicators.cpp (+11/-11)
tests/test_panel_menu_view.cpp (+19/-3)
tests/test_panel_service.cpp (+6/-2)
tests/test_service_panel.cpp (+18/-15)
unity-shared/IconLoader.cpp (+2/-2)
unity-shared/MenuManager.cpp (+63/-8)
unity-shared/NuxObjectPtrHash.h (+36/-0)
unity-shared/PlacesVScrollBar.cpp (+1/-1)
unity-shared/PluginAdapter.cpp (+11/-2)
unity-shared/PluginAdapter.h (+2/-2)
unity-shared/PreviewStyle.cpp (+1/-1)
unity-shared/StandaloneWindowManager.cpp (+1/-0)
unity-shared/UBusWrapper.cpp (+3/-4)
unity-shared/UBusWrapper.h (+2/-2)
unity-shared/UnitySettings.cpp (+2/-0)
unity-shared/UnitySettings.h (+1/-0)
To merge this branch: bzr merge lp:~unity-team/unity/fix-lp1309778-trusty
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve on 2015-07-15
Unity Team 2015-07-15 Pending
Review via email: mp+264837@code.launchpad.net

Commit message

Decorations, Panel: add menus for unfocused windows as well

Now the indicator-appmenu exports the menus for all the windows, then it's up to us to filter them based on their parent window and show on relevant place.

To post a comment you must log in.

Unmerged revisions

3833. By Christopher Townsend on 2015-07-15

Merge lp:unity/7.2.

3832. By Marco Trevisan (Treviño) on 2015-05-28

Decorations, Panel: add menus for unfocused windows as well

Now the indicator-appmenu exports the menus for all the windows,
then it's up to us to filter them based on their parent window and
show on relevant place.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'UnityCore/AppmenuIndicator.cpp'
2--- UnityCore/AppmenuIndicator.cpp 2015-03-12 00:57:05 +0000
3+++ UnityCore/AppmenuIndicator.cpp 2015-07-15 14:19:40 +0000
4@@ -17,41 +17,81 @@
5 * Authored by: Marco Trevisan (Treviño) <3v1n0@ubuntu.com>
6 */
7
8-#include "GLibSource.h"
9+#include <unordered_set>
10+
11 #include "AppmenuIndicator.h"
12+#include "ConnectionManager.h"
13
14 namespace unity
15 {
16 namespace indicator
17 {
18+namespace
19+{
20+const Indicator::Entries empty_entries_;
21+}
22
23 struct AppmenuIndicator::Impl
24 {
25 Impl(AppmenuIndicator* parent)
26 {
27- // When the active window has changed we might need to emit an updated signal
28- parent->active_window.changed.connect([this, parent] (unsigned long) {
29- update_wait_.reset(new glib::Timeout(250, [parent] {
30- parent->updated.emit();
31- return false;
32- }));
33- });
34-
35- parent->updated.connect([this] { update_wait_.reset(); });
36+ connections_.Add(parent->on_entry_added.connect([this] (Entry::Ptr const& entry) {
37+ window_entries_[entry->parent_window()].push_back(entry);
38+ }));
39+
40+ connections_.Add(parent->on_entry_removed.connect([this] (Entry::Ptr const& entry) {
41+ auto it = window_entries_.find(entry->parent_window());
42+
43+ if (it != window_entries_.end())
44+ {
45+ auto& entries = it->second;
46+ entries.erase(std::remove(entries.begin(), entries.end(), entry), entries.end());
47+
48+ if (entries.empty())
49+ window_entries_.erase(it);
50+ }
51+ }));
52 }
53
54- glib::Source::UniquePtr update_wait_;
55+ connection::Manager connections_;
56+ std::unordered_map<uint32_t, Indicator::Entries> window_entries_;
57 };
58
59 AppmenuIndicator::AppmenuIndicator(std::string const& name)
60 : Indicator(name)
61- , active_window(0)
62 , impl_(new AppmenuIndicator::Impl(this))
63 {}
64
65 AppmenuIndicator::~AppmenuIndicator()
66 {}
67
68+void AppmenuIndicator::Sync(Indicator::Entries const& entries)
69+{
70+ std::unordered_set<uint32_t> changed_windows;
71+ connection::Wrapper added_conn(on_entry_added.connect([this, &changed_windows] (Entry::Ptr const& entry) {
72+ changed_windows.insert(entry->parent_window());
73+ }));
74+
75+ connection::Wrapper rm_conn(on_entry_removed.connect([this, &changed_windows] (Entry::Ptr const& entry) {
76+ changed_windows.insert(entry->parent_window());
77+ }));
78+
79+ Indicator::Sync(entries);
80+
81+ for (uint32_t win : changed_windows)
82+ updated_win.emit(win);
83+}
84+
85+Indicator::Entries const& AppmenuIndicator::GetEntriesForWindow(uint32_t parent_window) const
86+{
87+ auto it = impl_->window_entries_.find(parent_window);
88+
89+ if (it != impl_->window_entries_.end())
90+ return it->second;
91+
92+ return empty_entries_;
93+}
94+
95 void AppmenuIndicator::ShowAppmenu(unsigned int xid, int x, int y) const
96 {
97 on_show_appmenu.emit(xid, x, y);
98
99=== modified file 'UnityCore/AppmenuIndicator.h'
100--- UnityCore/AppmenuIndicator.h 2015-03-12 00:57:05 +0000
101+++ UnityCore/AppmenuIndicator.h 2015-07-15 14:19:40 +0000
102@@ -36,12 +36,13 @@
103 AppmenuIndicator(std::string const& name);
104 ~AppmenuIndicator();
105
106- nux::Property<unsigned> active_window;
107-
108- virtual bool IsAppmenu() const { return true; }
109+ bool IsAppmenu() const override { return true; }
110+ void Sync(Entries const&) override;
111+ Entries const& GetEntriesForWindow(uint32_t parent_window) const;
112
113 void ShowAppmenu(unsigned xid, int x, int y) const;
114
115+ sigc::signal<void, uint32_t> updated_win;
116 sigc::signal<void, unsigned, int, int> on_show_appmenu;
117
118 private:
119
120=== modified file 'UnityCore/CMakeLists.txt'
121--- UnityCore/CMakeLists.txt 2014-02-05 11:38:22 +0000
122+++ UnityCore/CMakeLists.txt 2015-07-15 14:19:40 +0000
123@@ -117,6 +117,7 @@
124 #
125 include_directories(${CORE_DEPS_INCLUDE_DIRS})
126 include_directories(${CMAKE_BINARY_DIR})
127+include_directories(..)
128
129 set (LIBS ${CORE_DEPS_LDFLAGS} ${PRIVATE_CORE_DEPS_LDFLAGS})
130
131
132=== modified file 'UnityCore/DBusIndicators.cpp'
133--- UnityCore/DBusIndicators.cpp 2014-12-09 15:41:53 +0000
134+++ UnityCore/DBusIndicators.cpp 2015-07-15 14:19:40 +0000
135@@ -27,19 +27,29 @@
136 #include "GLibSource.h"
137 #include "Variant.h"
138 #include "DBusIndicators.h"
139+#include "services/panel-service-private.h"
140
141 namespace unity
142 {
143 namespace indicator
144 {
145+
146+namespace
147+{
148 DECLARE_LOGGER(logger, "unity.indicator.dbus");
149
150-namespace
151+inline bool verify_variant_type(GVariant* value, const gchar* type)
152 {
153-const std::string SERVICE_NAME_DESKTOP("com.canonical.Unity.Panel.Service.Desktop");
154-const std::string SERVICE_NAME_LOCKSCREEN("com.canonical.Unity.Panel.Service.LockScreen");
155-const std::string SERVICE_PATH("/com/canonical/Unity/Panel/Service");
156-const std::string SERVICE_IFACE("com.canonical.Unity.Panel.Service");
157+ if (!g_variant_is_of_type (value, G_VARIANT_TYPE(type)))
158+ {
159+ LOG_ERROR(logger) << "Got invalid variant type: '"
160+ << g_variant_get_type_string(value) << "' ('"
161+ << type << "' was expected)";
162+ return false;
163+ }
164+
165+ return true;
166+}
167 } // anonymous namespace
168
169
170@@ -78,15 +88,15 @@
171 glib::Source::UniquePtr show_entry_idle_;
172 glib::Source::UniquePtr show_appmenu_idle_;
173 std::vector<std::string> icon_paths_;
174- std::map<std::string, EntryLocationMap> cached_locations_;
175+ std::unordered_map<std::string, EntryLocationMap> cached_locations_;
176 };
177
178
179 // Public Methods
180 DBusIndicators::Impl::Impl(std::string const& dbus_name, DBusIndicators* owner)
181 : owner_(owner)
182- , gproxy_(dbus_name, SERVICE_PATH, SERVICE_IFACE,
183- G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES)
184+ , gproxy_(dbus_name, UPS_PATH, UPS_IFACE, G_BUS_TYPE_SESSION,
185+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES)
186 {
187 gproxy_.Connect("ReSync", sigc::mem_fun(this, &DBusIndicators::Impl::OnReSync));
188 gproxy_.Connect("IconPathsChanged", sigc::mem_fun(this, &DBusIndicators::Impl::OnIconsPathChanged));
189@@ -208,6 +218,9 @@
190
191 void DBusIndicators::Impl::OnEntryActivated(GVariant* parameters)
192 {
193+ if (!verify_variant_type(parameters, "(ss(iiuu))"))
194+ return;
195+
196 glib::String panel;
197 glib::String entry_id;
198 nux::Rect geo;
199@@ -219,6 +232,9 @@
200
201 void DBusIndicators::Impl::OnEntryActivatedRequest(GVariant* parameters)
202 {
203+ if (!verify_variant_type(parameters, "(s)"))
204+ return;
205+
206 glib::String entry_name;
207 g_variant_get(parameters, "(s)", &entry_name);
208
209@@ -228,6 +244,9 @@
210
211 void DBusIndicators::Impl::OnEntryShowNowChanged(GVariant* parameters)
212 {
213+ if (!verify_variant_type(parameters, "(sb)"))
214+ return;
215+
216 glib::String entry_name;
217 gboolean show_now;
218 g_variant_get(parameters, "(sb)", &entry_name, &show_now);
219@@ -325,9 +344,10 @@
220 return;
221
222 GVariantIter* iter = nullptr;
223- gchar* name_hint = nullptr;
224 gchar* indicator_id = nullptr;
225 gchar* entry_id = nullptr;
226+ gchar* name_hint = nullptr;
227+ guint32 parent_window = 0;
228 gchar* label = nullptr;
229 gboolean label_sensitive = false;
230 gboolean label_visible = false;
231@@ -337,15 +357,17 @@
232 gboolean image_visible = false;
233 gint32 priority = -1;
234
235- std::map<Indicator::Ptr, Indicator::Entries> indicators;
236- int wanted_idx = 0;
237- bool any_different_idx = false;
238-
239- g_variant_get(args, "(a(ssssbbusbbi))", &iter);
240- while (g_variant_iter_loop(iter, "(ssssbbusbbi)",
241+ if (!verify_variant_type(args, "(" ENTRY_ARRAY_SIGNATURE ")"))
242+ return;
243+
244+ std::unordered_map<Indicator::Ptr, Indicator::Entries> indicators;
245+
246+ g_variant_get(args, "(" ENTRY_ARRAY_SIGNATURE ")", &iter);
247+ while (g_variant_iter_loop(iter, ENTRY_SIGNATURE,
248 &indicator_id,
249 &entry_id,
250 &name_hint,
251+ &parent_window,
252 &label,
253 &label_sensitive,
254 &label_visible,
255@@ -369,27 +391,20 @@
256 // Empty entries are empty indicators.
257 if (!entry.empty())
258 {
259- Entry::Ptr e;
260- if (!any_different_idx)
261- {
262- // Indicators can only add or remove entries, so if
263- // there is a index change we can't reuse the existing ones
264- // after that index
265- if (indicator->EntryIndex(entry_id) == wanted_idx)
266- {
267- e = indicator->GetEntry(entry_id);
268- }
269- else
270- {
271- any_different_idx = true;
272- }
273- }
274+ Entry::Ptr e = indicator->GetEntry(entry_id);
275+ int old_priority = e ? e->priority() : -1;
276+
277+ // Indicators can only add or remove entries, so if
278+ // there is a priority change we can't reuse the existing ones
279+ if (old_priority != priority)
280+ e.reset();
281
282 if (!e)
283 {
284- e = std::make_shared<Entry>(entry, name_hint, label, label_sensitive,
285- label_visible, image_type, image_data,
286- image_sensitive, image_visible, priority);
287+ e = std::make_shared<Entry>(entry, name_hint, parent_window,
288+ label, label_sensitive, label_visible,
289+ image_type, image_data, image_sensitive, image_visible,
290+ priority);
291 }
292 else
293 {
294@@ -399,15 +414,12 @@
295 }
296
297 entries.push_back(e);
298- ++wanted_idx;
299 }
300 }
301 g_variant_iter_free(iter);
302
303- for (auto i = indicators.begin(), end = indicators.end(); i != end; ++i)
304- {
305- i->first->Sync(indicators[i->first]);
306- }
307+ for (auto const& i : indicators)
308+ i.first->Sync(i.second);
309 }
310
311 void DBusIndicators::Impl::SyncGeometries(std::string const& name,
312@@ -463,7 +475,7 @@
313 }
314
315 DBusIndicators::DBusIndicators()
316- : pimpl(new Impl(SERVICE_NAME_DESKTOP, this))
317+ : pimpl(new Impl(UPS_NAME_DESKTOP, this))
318 {}
319
320 DBusIndicators::DBusIndicators(std::string const& dbus_name)
321@@ -471,7 +483,7 @@
322 {}
323
324 LockScreenDBusIndicators::LockScreenDBusIndicators()
325- : DBusIndicators(SERVICE_NAME_LOCKSCREEN)
326+ : DBusIndicators(UPS_NAME_LOCKSCREEN)
327 {}
328
329 DBusIndicators::~DBusIndicators()
330
331=== modified file 'UnityCore/GLibDBusServer.cpp'
332--- UnityCore/GLibDBusServer.cpp 2014-04-09 13:19:33 +0000
333+++ UnityCore/GLibDBusServer.cpp 2015-07-15 14:19:40 +0000
334@@ -17,6 +17,7 @@
335 * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
336 */
337
338+#include <unordered_map>
339 #include <NuxCore/Logger.h>
340
341 #include "GLibDBusServer.h"
342@@ -406,8 +407,8 @@
343
344 GDBusInterfaceVTable interface_vtable_;
345 std::shared_ptr<GDBusInterfaceInfo> interface_info_;
346- std::map<guint, std::string> registrations_;
347- std::map<std::string, glib::Object<GDBusConnection>> connection_by_path_;
348+ std::unordered_map<guint, std::string> registrations_;
349+ std::unordered_map<std::string, glib::Object<GDBusConnection>> connection_by_path_;
350 };
351
352 DBusObject::DBusObject(std::string const& introspection_xml, std::string const& interface_name)
353
354=== modified file 'UnityCore/GLibSource.h'
355--- UnityCore/GLibSource.h 2013-10-10 09:47:24 +0000
356+++ UnityCore/GLibSource.h 2015-07-15 14:19:40 +0000
357@@ -24,7 +24,7 @@
358 #include <sigc++/sigc++.h>
359 #include <glib.h>
360 #include <memory>
361-#include <map>
362+#include <unordered_map>
363
364 namespace unity
365 {
366@@ -223,7 +223,7 @@
367 Source::Ptr GetSource(unsigned int id) const;
368
369 protected: // For testing purposes
370- typedef std::map<std::string, Source::Ptr> SourcesMap;
371+ typedef std::unordered_map<std::string, Source::Ptr> SourcesMap;
372 SourcesMap sources_;
373
374 private:
375
376=== modified file 'UnityCore/Indicator.cpp'
377--- UnityCore/Indicator.cpp 2014-01-27 17:31:30 +0000
378+++ UnityCore/Indicator.cpp 2015-07-15 14:19:40 +0000
379@@ -36,7 +36,7 @@
380 Indicator::~Indicator()
381 {
382 for (auto const& entry : entries_)
383- on_entry_removed.emit(entry->id());
384+ on_entry_removed.emit(entry);
385 }
386
387 std::string const& Indicator::name() const
388@@ -51,23 +51,23 @@
389
390 void Indicator::Sync(Indicator::Entries const& new_entries)
391 {
392- bool added = false;
393- Entries to_rm;
394+ bool changed = false;
395
396- if (!entries_.empty())
397+ for (auto it = entries_.begin(); it != entries_.end();)
398 {
399- for (auto const& entry : entries_)
400+ auto entry = *it;
401+
402+ if (std::find(new_entries.begin(), new_entries.end(), entry) == new_entries.end())
403 {
404- if (std::find(new_entries.begin(), new_entries.end(), entry) == new_entries.end())
405- to_rm.push_back(entry);
406+ auto entry_id = entry->id();
407+ entries_connections_.erase(entry);
408+ it = entries_.erase(it);
409+ on_entry_removed.emit(entry);
410+ changed = true;
411+ continue;
412 }
413- }
414
415- for (auto const& entry : to_rm)
416- {
417- entries_connections_.erase(entry);
418- on_entry_removed.emit(entry->id());
419- entries_.remove(entry);
420+ ++it;
421 }
422
423 for (auto const& new_entry : new_entries)
424@@ -93,10 +93,10 @@
425 entries_.push_back(new_entry);
426 on_entry_added.emit(new_entry);
427
428- added = true;
429+ changed = true;
430 }
431
432- if (!to_rm.empty() || added)
433+ if (changed)
434 updated.emit();
435 }
436
437@@ -109,21 +109,6 @@
438 return Entry::Ptr();
439 }
440
441-int Indicator::EntryIndex(std::string const& entry_id) const
442-{
443- int i = 0;
444- for (auto const& entry : entries_)
445- {
446- if (entry->id() == entry_id)
447- {
448- return i;
449- }
450- ++i;
451- }
452-
453- return -1;
454-}
455-
456 std::ostream& operator<<(std::ostream& out, Indicator const& i)
457 {
458 out << "<Indicator " << i.name() << std::endl;
459
460=== modified file 'UnityCore/Indicator.h'
461--- UnityCore/Indicator.h 2014-02-05 17:16:41 +0000
462+++ UnityCore/Indicator.h 2015-07-15 14:19:40 +0000
463@@ -38,7 +38,7 @@
464 {
465 public:
466 typedef std::shared_ptr<Indicator> Ptr;
467- typedef std::list<Entry::Ptr> Entries;
468+ typedef std::vector<Entry::Ptr> Entries;
469
470 Indicator(std::string const& name);
471 virtual ~Indicator();
472@@ -47,15 +47,14 @@
473
474 virtual bool IsAppmenu() const { return false; }
475
476- void Sync(Entries const& new_entries);
477+ virtual void Sync(Entries const&);
478 Entry::Ptr GetEntry(std::string const& entry_id) const;
479- int EntryIndex(std::string const& entry_id) const;
480 Entries const& GetEntries() const;
481
482 // Signals
483 sigc::signal<void> updated;
484 sigc::signal<void, Entry::Ptr const&> on_entry_added;
485- sigc::signal<void, std::string const&> on_entry_removed;
486+ sigc::signal<void, Entry::Ptr const&> on_entry_removed;
487 sigc::signal<void, std::string const&, unsigned, int, int, unsigned> on_show_menu;
488 sigc::signal<void, std::string const&> on_secondary_activate;
489 sigc::signal<void, std::string const&, int> on_scroll;
490
491=== modified file 'UnityCore/IndicatorEntry.cpp'
492--- UnityCore/IndicatorEntry.cpp 2014-02-07 23:54:15 +0000
493+++ UnityCore/IndicatorEntry.cpp 2015-07-15 14:19:40 +0000
494@@ -30,6 +30,7 @@
495
496 Entry::Entry(std::string const& id,
497 std::string const& name_hint,
498+ uint32_t parent_window,
499 std::string const& label,
500 bool label_sensitive,
501 bool label_visible,
502@@ -40,6 +41,7 @@
503 int priority)
504 : id_(id)
505 , name_hint_(name_hint)
506+ , parent_window_(parent_window)
507 , label_(label)
508 , label_visible_(label_visible)
509 , label_sensitive_(label_sensitive)
510@@ -52,9 +54,10 @@
511 , active_(false)
512 {}
513
514-Entry::Entry(std::string const& id, std::string const& name_hint)
515+Entry::Entry(std::string const& id, std::string const& name_hint, uint32_t parent_window)
516 : id_(id)
517 , name_hint_(name_hint)
518+ , parent_window_(parent_window)
519 , label_visible_(false)
520 , label_sensitive_(false)
521 , image_type_(0)
522@@ -65,14 +68,19 @@
523 , active_(false)
524 {}
525
526+std::string const& Entry::id() const
527+{
528+ return id_;
529+}
530+
531 std::string const& Entry::name_hint() const
532 {
533 return name_hint_;
534 }
535
536-std::string const& Entry::id() const
537+uint32_t Entry::parent_window() const
538 {
539- return id_;
540+ return parent_window_;
541 }
542
543 std::string const& Entry::label() const
544@@ -199,6 +207,7 @@
545
546 id_ = rhs.id_;
547 name_hint_ = rhs.name_hint_;
548+ parent_window_ = rhs.parent_window_;
549 label_ = rhs.label_;
550 label_sensitive_ = rhs.label_sensitive_;
551 label_visible_ = rhs.label_visible_;
552@@ -258,7 +267,7 @@
553
554 void Entry::ShowMenu(int x, int y, unsigned button)
555 {
556- ShowMenu(0, x, y, button);
557+ ShowMenu(parent_window_, x, y, button);
558 }
559
560 void Entry::ShowMenu(unsigned int xid, int x, int y, unsigned button)
561@@ -278,7 +287,8 @@
562
563 std::ostream& operator<<(std::ostream& out, Entry const& e)
564 {
565- out << "<indicator::Entry " << e.id() << " hint: '" << e.name_hint() << "' "
566+ out << "<indicator::Entry " << e.id() << " hint: '" << e.name_hint() << "'"
567+ << " parent window: " << e.parent_window()
568 << std::boolalpha
569 << " \"" << e.label() << "\" ("
570 << e.label_sensitive() << ", " << e.label_visible() << ") image ("
571
572=== modified file 'UnityCore/IndicatorEntry.h'
573--- UnityCore/IndicatorEntry.h 2014-02-05 17:16:41 +0000
574+++ UnityCore/IndicatorEntry.h 2015-07-15 14:19:40 +0000
575@@ -44,9 +44,10 @@
576 public:
577 typedef std::shared_ptr<Entry> Ptr;
578
579- Entry(std::string const& id, std::string const& name_hint = "");
580+ Entry(std::string const& id, std::string const& name_hint = "", uint32_t parent_window = 0);
581 Entry(std::string const& id,
582 std::string const& name_hint,
583+ uint32_t parent_window,
584 std::string const& label,
585 bool label_sensitive,
586 bool label_visible,
587@@ -61,6 +62,7 @@
588
589 std::string const& id() const;
590 std::string const& name_hint() const;
591+ uint32_t parent_window() const;
592
593 void set_image(int type, std::string const& data, bool sensitive, bool visible);
594 bool image_visible() const;
595@@ -114,6 +116,7 @@
596 private:
597 std::string id_;
598 std::string name_hint_;
599+ uint32_t parent_window_;
600
601 std::string label_;
602 bool label_visible_;
603
604=== modified file 'UnityCore/Indicators.cpp'
605--- UnityCore/Indicators.cpp 2014-02-11 03:11:47 +0000
606+++ UnityCore/Indicators.cpp 2015-07-15 14:19:40 +0000
607@@ -20,6 +20,7 @@
608
609 #include "Indicators.h"
610 #include "AppmenuIndicator.h"
611+#include "services/panel-service-private.h"
612
613 namespace unity
614 {
615@@ -143,7 +144,7 @@
616 if (indicator)
617 return indicator;
618
619- if (name == "libappmenu.so")
620+ if (name == APPMENU_INDICATOR_NAME)
621 {
622 auto appmenu = std::make_shared<AppmenuIndicator>(name);
623 appmenu->on_show_appmenu.connect(sigc::mem_fun(owner_, &Indicators::OnShowAppMenu));
624
625=== modified file 'UnityCore/pch/unitycore_pch.hh'
626--- UnityCore/pch/unitycore_pch.hh 2014-01-28 15:39:57 +0000
627+++ UnityCore/pch/unitycore_pch.hh 2015-07-15 14:19:40 +0000
628@@ -29,6 +29,7 @@
629 #include <map>
630 #include <memory>
631 #include <unordered_map>
632+#include <functional>
633
634 #include <boost/utility.hpp>
635 #include <dee.h>
636
637=== modified file 'com.canonical.Unity.gschema.xml'
638--- com.canonical.Unity.gschema.xml 2015-03-12 00:57:05 +0000
639+++ com.canonical.Unity.gschema.xml 2015-07-15 14:19:40 +0000
640@@ -158,5 +158,11 @@
641 a window by double-clicking on its menus if the second click happens before the
642 specified value of ms is elapsed</description>
643 </key>
644+ <key type="b" name="unfocused-windows-popup">
645+ <default>true</default>
646+ <summary>Whether to pop-up a menu when clicking over unfocused windows entries</summary>
647+ <description>By disabling this setting you can make unity to only focus a window
648+ when clicking over unfocused menu entries</description>
649+ </key>
650 </schema>
651 </schemalist>
652
653=== modified file 'dash/DashView.h'
654--- dash/DashView.h 2014-07-24 13:49:53 +0000
655+++ dash/DashView.h 2015-07-15 14:19:40 +0000
656@@ -56,7 +56,7 @@
657 class DashView : public nux::View, public unity::debug::Introspectable
658 {
659 NUX_DECLARE_OBJECT_TYPE(DashView, nux::View);
660- typedef std::map<std::string, nux::ObjectPtr<ScopeView>> ScopeViews;
661+ typedef std::unordered_map<std::string, nux::ObjectPtr<ScopeView>> ScopeViews;
662
663 public:
664 DashView(Scopes::Ptr const& scopes, ApplicationStarter::Ptr const& application_starter);
665
666=== modified file 'dash/ScopeView.h'
667--- dash/ScopeView.h 2014-08-06 14:09:30 +0000
668+++ dash/ScopeView.h 2015-07-15 14:19:40 +0000
669@@ -35,6 +35,7 @@
670 #include "unity-shared/Introspectable.h"
671 #include "PlacesGroup.h"
672 #include "ResultViewGrid.h"
673+#include "unity-shared/NuxObjectPtrHash.h"
674 #include "unity-shared/UBusWrapper.h"
675
676 namespace unity
677@@ -48,7 +49,7 @@
678 {
679 NUX_DECLARE_OBJECT_TYPE(ScopeView, nux::View);
680 typedef std::vector<PlacesGroup::Ptr> CategoryGroups;
681- typedef std::map<PlacesGroup::Ptr, unsigned int> ResultCounts;
682+ typedef std::unordered_map<PlacesGroup::Ptr, unsigned int> ResultCounts;
683
684 public:
685 ScopeView(Scope::Ptr const& scope, nux::Area* show_filters);
686
687=== modified file 'debian/control'
688--- debian/control 2015-03-11 18:11:24 +0000
689+++ debian/control 2015-07-15 14:19:40 +0000
690@@ -80,7 +80,7 @@
691 Provides: indicator-renderer
692 Recommends: unity-control-center,
693 ${unity-default-masterscopes}
694- indicator-appmenu,
695+ indicator-appmenu (>= 15.02.0),
696 indicator-application,
697 indicator-sound,
698 indicator-bluetooth,
699
700=== modified file 'decorations/DecoratedWindow.cpp'
701--- decorations/DecoratedWindow.cpp 2015-03-12 00:57:05 +0000
702+++ decorations/DecoratedWindow.cpp 2015-07-15 14:19:40 +0000
703@@ -52,17 +52,13 @@
704 , deco_elements_(cu::DecorationElement::NONE)
705 , last_mwm_decor_(win_->mwmDecor())
706 , last_actions_(win_->actions())
707+ , panel_id_(MENUS_PANEL_NAME + std::to_string(win_->id()))
708 , cv_(Settings::Instance().em())
709 {
710 active.changed.connect([this] (bool active) {
711 bg_textures_.clear();
712 if (top_layout_)
713- {
714 top_layout_->focused = active;
715-
716- if (!active)
717- UnsetAppMenu();
718- }
719 RedrawDecorations();
720 });
721
722@@ -703,7 +699,7 @@
723
724 void Window::Impl::SetupAppMenu()
725 {
726- if (!active() || !top_layout_)
727+ if (!top_layout_)
728 return;
729
730 auto const& menu_manager = manager_->impl_->menu_manager_;
731@@ -718,8 +714,11 @@
732
733 auto menus = std::make_shared<MenuLayout>(menu_manager, win_);
734 menus->Setup();
735+
736+ if (menus->Items().empty())
737+ return;
738+
739 menus_ = menus;
740-
741 auto const& grab_edge = grab_edge_.lock();
742 sliding_layout->SetInputItem(menus);
743 sliding_layout->fadein = menu_manager->fadein();
744@@ -761,13 +760,18 @@
745 sliding_layout->mouse_owner = grab_edge_->mouse_owner();
746 }
747
748+inline std::string const& Window::Impl::GetMenusPanelID() const
749+{
750+ return panel_id_;
751+}
752+
753 void Window::Impl::UnsetAppMenu()
754 {
755 if (!menus_)
756 return;
757
758 auto const& indicators = manager_->impl_->menu_manager_->Indicators();
759- indicators->SyncGeometries(MENUS_PANEL_NAME, indicator::EntryLocationMap());
760+ indicators->SyncGeometries(GetMenusPanelID(), indicator::EntryLocationMap());
761 sliding_layout_->SetInputItem(nullptr);
762 grab_mouse_changed_->disconnect();
763 }
764@@ -780,7 +784,7 @@
765 auto const& indicators = manager_->impl_->menu_manager_->Indicators();
766 indicator::EntryLocationMap map;
767 menus_->ChildrenGeometries(map);
768- indicators->SyncGeometries(MENUS_PANEL_NAME, map);
769+ indicators->SyncGeometries(GetMenusPanelID(), map);
770 }
771
772 bool Window::Impl::ActivateMenu(std::string const& entry_id)
773
774=== modified file 'decorations/DecorationsManager.cpp'
775--- decorations/DecorationsManager.cpp 2015-03-12 00:57:05 +0000
776+++ decorations/DecorationsManager.cpp 2015-07-15 14:19:40 +0000
777@@ -144,27 +144,24 @@
778 return;
779 }
780
781- appmenu->active_window = screen->activeWindow();
782-
783- auto setup_active_window = [this] {
784- if (Window::Ptr const& active_win = active_deco_win_.lock())
785- active_win->impl_->SetupAppMenu();
786- };
787+ for (auto const& win : windows_)
788+ win.second->impl_->SetupAppMenu();
789
790 menu_connections_.Remove(appmenu_connection_);
791- appmenu_connection_ = menu_connections_.Add(appmenu->updated.connect(setup_active_window));
792- setup_active_window();
793+ appmenu_connection_ = menu_connections_.Add(appmenu->updated_win.connect([this] (uint32_t xid) {
794+ if (Window::Ptr const& win = GetWindowByXid(xid))
795+ win->impl_->SetupAppMenu();
796+ }));
797 }
798
799 void Manager::Impl::UnsetAppMenu()
800 {
801 menu_connections_.Remove(appmenu_connection_);
802- auto const& active_win = active_deco_win_.lock();
803
804- if (active_win)
805+ for (auto const& win : windows_)
806 {
807- active_win->impl_->UnsetAppMenu();
808- active_win->impl_->Damage();
809+ win.second->impl_->UnsetAppMenu();
810+ win.second->impl_->Damage();
811 }
812 }
813
814@@ -268,9 +265,6 @@
815
816 if (new_active)
817 new_active->impl_->active = true;
818-
819- if (indicator::AppmenuIndicator::Ptr const& appmenu = menu_manager_->AppMenu())
820- appmenu->active_window = active_xid;
821 }
822 else if (event->xproperty.atom == Atoms::mwmHints ||
823 event->xproperty.atom == Atoms::wmAllowedActions)
824@@ -311,6 +305,9 @@
825
826 bool Manager::Impl::HandleFrameEvent(XEvent* event)
827 {
828+ if (WindowManager::Default().IsScaleActive())
829+ return false;
830+
831 auto const& win = GetWindowByFrame(event->xany.window);
832
833 // ButtonRelease events might happen also outside the frame window, in this
834
835=== modified file 'decorations/DecorationsMenuDropdown.cpp'
836--- decorations/DecorationsMenuDropdown.cpp 2014-02-24 23:53:50 +0000
837+++ decorations/DecorationsMenuDropdown.cpp 2015-07-15 14:19:40 +0000
838@@ -33,7 +33,7 @@
839 using namespace indicator;
840
841 MenuDropdown::MenuDropdown(Indicators::Ptr const& indicators, CompWindow* win)
842- : MenuEntry(std::make_shared<Entry>("LIM-dropdown"), win)
843+ : MenuEntry(std::make_shared<Entry>("LIM"+std::to_string(win->id())+"-dropdown"), win)
844 , indicators_(indicators)
845 {
846 natural_.width = ICON_SIZE;
847@@ -53,7 +53,7 @@
848 for (auto const& child : children_)
849 entries.push_back(child->GetEntry());
850
851- indicators_->ShowEntriesDropdown(entries, active_, 0, geo.x(), geo.y2());
852+ indicators_->ShowEntriesDropdown(entries, active_, grab_.Window()->id(), geo.x(), geo.y2());
853 }
854
855 bool MenuDropdown::ActivateChild(MenuEntry::Ptr const& child)
856@@ -118,7 +118,8 @@
857
858 void MenuDropdown::RenderTexture()
859 {
860- WidgetState state = active() ? WidgetState::PRELIGHT : WidgetState::NORMAL;
861+ WidgetState normal_state = focused() ? WidgetState::NORMAL : WidgetState::BACKDROP;
862+ WidgetState state = active() ? WidgetState::PRELIGHT : normal_state;
863 cu::CairoContext icon_ctx(GetNaturalWidth(), GetNaturalHeight(), scale());
864
865 if (state == WidgetState::PRELIGHT)
866
867=== modified file 'decorations/DecorationsMenuEntry.cpp'
868--- decorations/DecorationsMenuEntry.cpp 2014-03-31 18:36:33 +0000
869+++ decorations/DecorationsMenuEntry.cpp 2015-07-15 14:19:40 +0000
870@@ -37,11 +37,13 @@
871 , in_dropdown(false)
872 , entry_(entry)
873 , grab_(win, true)
874+ , show_menu_enabled_(true)
875 {
876 entry_->updated.connect(sigc::mem_fun(this, &MenuEntry::EntryUpdated));
877 horizontal_padding.changed.connect(sigc::hide(sigc::mem_fun(this, &MenuEntry::RenderTexture)));
878 vertical_padding.changed.connect(sigc::hide(sigc::mem_fun(this, &MenuEntry::RenderTexture)));
879 scale.changed.connect(sigc::hide(sigc::mem_fun(this, &MenuEntry::RenderTexture)));
880+ focused.changed.connect(sigc::hide(sigc::mem_fun(this, &MenuEntry::RenderTexture)));
881 in_dropdown.changed.connect([this] (bool in) { visible = entry_->visible() && !in; });
882 EntryUpdated();
883 }
884@@ -63,7 +65,7 @@
885
886 void MenuEntry::RenderTexture()
887 {
888- WidgetState state = WidgetState::NORMAL;
889+ WidgetState state = focused() ? WidgetState::NORMAL : WidgetState::BACKDROP;
890
891 if (show_now())
892 state = WidgetState::PRESSED;
893@@ -120,10 +122,17 @@
894 {
895 button_up_timer_.reset();
896 grab_.ButtonDownEvent(p, button, timestamp);
897+ show_menu_enabled_ = (focused() || Settings::Instance().lim_unfocused_popup());
898 }
899
900 void MenuEntry::ButtonUpEvent(CompPoint const& p, unsigned button, Time timestamp)
901 {
902+ if (!show_menu_enabled_)
903+ {
904+ grab_.ButtonUpEvent(p, button, timestamp);
905+ return;
906+ }
907+
908 if (button == 1 && !grab_.IsGrabbed())
909 {
910 unsigned double_click_wait = Settings::Instance().lim_double_click_wait();
911@@ -143,7 +152,8 @@
912
913 if (button == 2 || button == 3)
914 {
915- ShowMenu(button);
916+ if (Style::Get()->WindowManagerAction(WMEvent(button)) == WMAction::NONE)
917+ ShowMenu(button);
918 }
919
920 grab_.ButtonUpEvent(p, button, timestamp);
921
922=== modified file 'decorations/DecorationsMenuEntry.h'
923--- decorations/DecorationsMenuEntry.h 2014-02-27 07:10:31 +0000
924+++ decorations/DecorationsMenuEntry.h 2015-07-15 14:19:40 +0000
925@@ -63,10 +63,11 @@
926
927 protected:
928 indicator::Entry::Ptr entry_;
929+ GrabEdge grab_;
930
931 private:
932+ bool show_menu_enabled_;
933 glib::Source::UniquePtr button_up_timer_;
934- GrabEdge grab_;
935 };
936
937 } // decoration namespace
938
939=== modified file 'decorations/DecorationsMenuLayout.cpp'
940--- decorations/DecorationsMenuLayout.cpp 2014-02-26 00:14:46 +0000
941+++ decorations/DecorationsMenuLayout.cpp 2015-07-15 14:19:40 +0000
942@@ -35,7 +35,9 @@
943 , win_(win)
944 , last_pointer_(-1, -1)
945 , dropdown_(std::make_shared<MenuDropdown>(menu_manager_->Indicators(), win))
946-{}
947+{
948+ visible = false;
949+}
950
951 void MenuLayout::Setup()
952 {
953@@ -56,7 +58,7 @@
954 dropdown_->active.changed.connect(active_cb);
955 dropdown_->show_now.changed.connect(show_now_cb);
956
957- for (auto const& entry : menu_manager_->AppMenu()->GetEntries())
958+ for (auto const& entry : menu_manager_->AppMenu()->GetEntriesForWindow(win_->id()))
959 {
960 auto menu = std::make_shared<MenuEntry>(entry, win_);
961 menu->mouse_owner.changed.connect(ownership_cb);
962@@ -65,7 +67,24 @@
963 menu->focused = focused();
964 menu->scale = scale();
965 menu->SetParent(shared_from_this());
966- items_.push_back(menu);
967+
968+ if (items_.empty() || entry->priority() < 0)
969+ {
970+ items_.push_back(menu);
971+ }
972+ else
973+ {
974+ auto pos = items_.rbegin();
975+
976+ for (; pos != items_.rend(); ++pos)
977+ {
978+ auto menu = std::static_pointer_cast<MenuEntry>(*pos);
979+ if (entry->priority() >= menu->GetEntry()->priority())
980+ break;
981+ }
982+
983+ items_.insert(pos.base(), menu);
984+ }
985 }
986
987 if (!items_.empty())
988@@ -195,12 +214,14 @@
989 int accumolated_width = dropdown_width + left_padding + right_padding - inner_padding;
990 int max_width = max_.width;
991 std::list<MenuEntry::Ptr> to_hide;
992+ bool is_visible = visible();
993
994 for (auto const& item : items_)
995 {
996 if (!item->visible() || item == dropdown_)
997 continue;
998
999+ is_visible = true;
1000 accumolated_width += item->GetNaturalWidth() + inner_padding;
1001
1002 if (accumolated_width > max_width)
1003@@ -235,6 +256,7 @@
1004 dropdown_->Push(hidden);
1005 }
1006
1007+ visible = is_visible;
1008 Layout::DoRelayout();
1009 }
1010
1011
1012=== modified file 'decorations/DecorationsPriv.h'
1013--- decorations/DecorationsPriv.h 2014-12-16 19:35:06 +0000
1014+++ decorations/DecorationsPriv.h 2015-07-15 14:19:40 +0000
1015@@ -111,6 +111,7 @@
1016 bool ShouldBeDecorated() const;
1017 GLTexture* ShadowTexture() const;
1018 unsigned ShadowRadius() const;
1019+ std::string const& GetMenusPanelID() const;
1020
1021 void ComputeShadowQuads();
1022 void UpdateDecorationTextures();
1023@@ -143,6 +144,7 @@
1024 connection::Wrapper dpi_changed_;
1025 connection::Wrapper grab_mouse_changed_;
1026 std::string last_title_;
1027+ std::string panel_id_;
1028 std::vector<cu::SimpleTextureQuad> bg_textures_;
1029 std::shared_ptr<ForceQuitDialog> force_quit_;
1030 InputMixer::Ptr input_mixer_;
1031@@ -194,7 +196,7 @@
1032
1033 uweak_ptr<decoration::Window> active_deco_win_;
1034 uweak_ptr<InputMixer> last_mouse_owner_;
1035- std::map<CompWindow*, decoration::Window::Ptr> windows_;
1036+ std::unordered_map<CompWindow*, decoration::Window::Ptr> windows_;
1037 std::unordered_map<::Window, std::weak_ptr<decoration::Window>> framed_windows_;
1038
1039 menu::Manager::Ptr menu_manager_;
1040
1041=== modified file 'decorations/DecorationsSlidingLayout.cpp'
1042--- decorations/DecorationsSlidingLayout.cpp 2015-03-12 00:57:05 +0000
1043+++ decorations/DecorationsSlidingLayout.cpp 2015-07-15 14:19:40 +0000
1044@@ -137,7 +137,7 @@
1045 auto& main_item_ = items_[ItemRole::MAIN];
1046 auto& input_item_ = items_[ItemRole::INPUT];
1047
1048- if (!input_item_)
1049+ if (!input_item_ || !input_item_->visible())
1050 {
1051 if (main_item_)
1052 main_item_->Draw(ctx, transformation, attrib, clip, mask);
1053
1054=== modified file 'decorations/DecorationsWidgets.cpp'
1055--- decorations/DecorationsWidgets.cpp 2014-12-08 22:38:02 +0000
1056+++ decorations/DecorationsWidgets.cpp 2015-07-15 14:19:40 +0000
1057@@ -192,15 +192,10 @@
1058
1059 BasicContainer::Ptr Item::GetTopParent() const
1060 {
1061- BasicContainer::Ptr parent = GetParent();
1062-
1063- while (parent)
1064- {
1065- if (!parent->parent_)
1066- return parent;
1067-
1068- parent = parent->GetParent();
1069- }
1070+ BasicContainer::Ptr parent = parent_;
1071+
1072+ while (parent && parent->parent_)
1073+ parent = parent->parent_;
1074
1075 return parent;
1076 }
1077
1078=== modified file 'launcher/LauncherEntryRemoteModel.h'
1079--- launcher/LauncherEntryRemoteModel.h 2012-05-07 19:52:54 +0000
1080+++ launcher/LauncherEntryRemoteModel.h 2015-07-15 14:19:40 +0000
1081@@ -22,7 +22,7 @@
1082
1083 #include <gio/gio.h>
1084 #include <sigc++/sigc++.h>
1085-#include <map>
1086+#include <unordered_map>
1087
1088 #include "LauncherEntryRemote.h"
1089
1090@@ -68,7 +68,7 @@
1091 glib::Object<GDBusConnection> _conn;
1092 unsigned int _launcher_entry_dbus_signal_id;
1093 unsigned int _dbus_name_owner_changed_signal_id;
1094- std::map<std::string, LauncherEntryRemote::Ptr> _entries_by_uri;
1095+ std::unordered_map<std::string, LauncherEntryRemote::Ptr> _entries_by_uri;
1096 };
1097
1098 } // namespace
1099
1100=== modified file 'launcher/XdndStartStopNotifierImp.h'
1101--- launcher/XdndStartStopNotifierImp.h 2012-11-15 16:05:35 +0000
1102+++ launcher/XdndStartStopNotifierImp.h 2015-07-15 14:19:40 +0000
1103@@ -27,7 +27,7 @@
1104
1105 namespace unity {
1106
1107-class XdndStartStopNotifierImp : public XdndStartStopNotifier {
1108+class XdndStartStopNotifierImp : public XdndStartStopNotifier, public sigc::trackable {
1109 public:
1110 XdndStartStopNotifierImp();
1111
1112
1113=== modified file 'lockscreen/LockScreenPanel.cpp'
1114--- lockscreen/LockScreenPanel.cpp 2014-12-15 19:12:07 +0000
1115+++ lockscreen/LockScreenPanel.cpp 2015-07-15 14:19:40 +0000
1116@@ -118,7 +118,7 @@
1117 if (entry->active())
1118 {
1119 active = true;
1120- indicators_view_->ActivateEntry(entry->id());
1121+ indicators_view_->ActivateEntry(entry);
1122 OnEntryActivated(GetPanelName(), entry->id(), entry->geometry());
1123 break;
1124 }
1125
1126=== modified file 'panel/PanelIndicatorEntryDropdownView.cpp'
1127--- panel/PanelIndicatorEntryDropdownView.cpp 2014-02-25 00:28:58 +0000
1128+++ panel/PanelIndicatorEntryDropdownView.cpp 2015-07-15 14:19:40 +0000
1129@@ -98,6 +98,11 @@
1130 return child;
1131 }
1132
1133+void PanelIndicatorEntryDropdownView::Clear()
1134+{
1135+ children_.clear();
1136+}
1137+
1138 std::deque<PanelIndicatorEntryView::Ptr> const& PanelIndicatorEntryDropdownView::Children() const
1139 {
1140 return children_;
1141@@ -144,7 +149,7 @@
1142 entries.push_back(entry->GetEntry());
1143
1144 auto const& geo = GetAbsoluteGeometry();
1145- indicators_->ShowEntriesDropdown(entries, active_entry_, 0, geo.x, geo.y + geo.height);
1146+ indicators_->ShowEntriesDropdown(entries, active_entry_, entries[0]->parent_window(), geo.x, geo.y + geo.height);
1147 }
1148
1149 bool PanelIndicatorEntryDropdownView::ActivateChild(PanelIndicatorEntryView::Ptr const& child)
1150
1151=== modified file 'panel/PanelIndicatorEntryDropdownView.h'
1152--- panel/PanelIndicatorEntryDropdownView.h 2014-02-07 23:29:46 +0000
1153+++ panel/PanelIndicatorEntryDropdownView.h 2015-07-15 14:19:40 +0000
1154@@ -39,6 +39,7 @@
1155 void Insert(PanelIndicatorEntryView::Ptr const&);
1156 void Remove(PanelIndicatorEntryView::Ptr const&);
1157 PanelIndicatorEntryView::Ptr Pop();
1158+ void Clear();
1159
1160 PanelIndicatorEntryView::Ptr Top() const;
1161 std::deque<PanelIndicatorEntryView::Ptr> const& Children() const;
1162
1163=== modified file 'panel/PanelIndicatorEntryView.cpp'
1164--- panel/PanelIndicatorEntryView.cpp 2014-12-08 19:50:13 +0000
1165+++ panel/PanelIndicatorEntryView.cpp 2015-07-15 14:19:40 +0000
1166@@ -59,6 +59,7 @@
1167 , cv_(unity::Settings::Instance().em(monitor_))
1168 {
1169 proxy_->active_changed.connect(sigc::mem_fun(this, &PanelIndicatorEntryView::OnActiveChanged));
1170+ proxy_->show_now_changed.connect(sigc::mem_fun(&show_now_changed, &sigc::signal<void, bool>::emit));
1171 proxy_->updated.connect(sigc::mem_fun(this, &PanelIndicatorEntryView::Refresh));
1172
1173 InputArea::mouse_down.connect(sigc::mem_fun(this, &PanelIndicatorEntryView::OnMouseDown));
1174@@ -84,11 +85,6 @@
1175 Refresh();
1176 }
1177
1178-PanelIndicatorEntryView::~PanelIndicatorEntryView()
1179-{
1180- // Nothing to do...
1181-}
1182-
1183 void PanelIndicatorEntryView::OnActiveChanged(bool is_active)
1184 {
1185 active_changed.emit(this, is_active);
1186@@ -114,10 +110,16 @@
1187 });
1188
1189 wm.TerminateExpo();
1190+ return;
1191 }
1192
1193 if (wm.IsScaleActive())
1194+ {
1195+ if (type_ == MENU)
1196+ return;
1197+
1198 wm.TerminateScale();
1199+ }
1200
1201 auto const& abs_geo = GetAbsoluteGeometry();
1202 proxy_->ShowMenu(abs_geo.x, abs_geo.y + abs_geo.height, button);
1203
1204=== modified file 'panel/PanelIndicatorEntryView.h'
1205--- panel/PanelIndicatorEntryView.h 2014-03-31 21:08:10 +0000
1206+++ panel/PanelIndicatorEntryView.h 2015-07-15 14:19:40 +0000
1207@@ -53,10 +53,8 @@
1208 PanelIndicatorEntryView(indicator::Entry::Ptr const& proxy, int padding = 5,
1209 IndicatorEntryType type = INDICATOR);
1210
1211- virtual ~PanelIndicatorEntryView();
1212-
1213 IndicatorEntryType GetType() const;
1214- indicator::Entry::Ptr GetEntry() const { return proxy_; }
1215+ indicator::Entry::Ptr const& GetEntry() const { return proxy_; }
1216 std::string GetEntryID() const;
1217 int GetEntryPriority() const;
1218
1219@@ -93,6 +91,7 @@
1220
1221 sigc::signal<void, PanelIndicatorEntryView*, bool> active_changed;
1222 sigc::signal<void, PanelIndicatorEntryView*> refreshed;
1223+ sigc::signal<void, bool> show_now_changed;
1224
1225 protected:
1226 std::string GetName() const;
1227
1228=== modified file 'panel/PanelIndicatorsView.cpp'
1229--- panel/PanelIndicatorsView.cpp 2014-03-06 09:26:03 +0000
1230+++ panel/PanelIndicatorsView.cpp 2015-07-15 14:19:40 +0000
1231@@ -71,7 +71,7 @@
1232 indicators_.push_back(indicator);
1233
1234 for (auto const& entry : indicator->GetEntries())
1235- AddEntry(entry);
1236+ OnEntryAdded(entry);
1237
1238 auto& conn_manager = indicators_connections_[indicator];
1239 conn_manager.Add(indicator->on_entry_added.connect(sigc::mem_fun(this, &PanelIndicatorsView::OnEntryAdded)));
1240@@ -83,7 +83,7 @@
1241 indicators_connections_.erase(indicator);
1242
1243 for (auto const& entry : indicator->GetEntries())
1244- RemoveEntry(entry->id());
1245+ RemoveEntry(entry);
1246
1247 for (auto i = indicators_.begin(); i != indicators_.end(); ++i)
1248 {
1249@@ -158,13 +158,13 @@
1250 }
1251 }
1252
1253-PanelIndicatorEntryView* PanelIndicatorsView::ActivateEntry(std::string const& entry_id, int button)
1254+PanelIndicatorEntryView* PanelIndicatorsView::ActivateEntry(indicator::Entry::Ptr const& entry, int button)
1255 {
1256- auto entry = entries_.find(entry_id);
1257+ auto it = entries_.find(entry);
1258
1259- if (entry != entries_.end())
1260+ if (it != entries_.end())
1261 {
1262- PanelIndicatorEntryView* view = entry->second;
1263+ PanelIndicatorEntryView* view = it->second;
1264
1265 if (view->IsSensitive() && view->IsVisible())
1266 {
1267@@ -181,6 +181,17 @@
1268 return nullptr;
1269 }
1270
1271+PanelIndicatorEntryView* PanelIndicatorsView::ActivateEntry(std::string const& entry_id, int button)
1272+{
1273+ for (auto const& it : entries_)
1274+ {
1275+ if (it.first->id() == entry_id)
1276+ return ActivateEntry(it.first, button);
1277+ }
1278+
1279+ return nullptr;
1280+}
1281+
1282 bool PanelIndicatorsView::ActivateIfSensitive()
1283 {
1284 for (auto* area : layout_->GetChildren())
1285@@ -222,7 +233,7 @@
1286 if (!view->IsVisible())
1287 continue;
1288
1289- if (!target && view->IsFocused() &&
1290+ if (!target &&
1291 view->IsSensitive() &&
1292 view->GetAbsoluteGeometry().IsPointInside(x, y))
1293 {
1294@@ -267,9 +278,8 @@
1295 if (!view)
1296 return;
1297
1298- auto const& entry_id = view->GetEntryID();
1299 bool added_to_dropdown = false;
1300- bool known_entry = (entries_.find(entry_id) != entries_.end());
1301+ bool known_entry = (entries_.find(view->GetEntry()) != entries_.end());
1302 view->SetOpacity(opacity());
1303
1304 if (!known_entry && dropdown_ && !dropdown_->Empty())
1305@@ -317,7 +327,7 @@
1306 {
1307 view->SetMonitor(monitor_);
1308 view->refreshed.connect(sigc::mem_fun(this, &PanelIndicatorsView::OnEntryRefreshed));
1309- entries_.insert({entry_id, view});
1310+ entries_.insert({view->GetEntry(), view});
1311 on_indicator_updated.emit();
1312 entry_added.emit(view);
1313 }
1314@@ -346,6 +356,23 @@
1315 on_indicator_updated.emit();
1316 }
1317
1318+void PanelIndicatorsView::ClearEntries()
1319+{
1320+ for (auto it = entries_.begin(); it != entries_.end();)
1321+ {
1322+ auto* entry = it->second;
1323+ ++it;
1324+
1325+ if (entry != dropdown_.GetPointer())
1326+ RemoveEntryView(entry);
1327+ }
1328+
1329+ on_indicator_updated.emit();
1330+
1331+ QueueRelayout();
1332+ QueueDraw();
1333+}
1334+
1335 void PanelIndicatorsView::RemoveEntryView(PanelIndicatorEntryView* view)
1336 {
1337 if (!view)
1338@@ -357,7 +384,7 @@
1339 dropdown_->Remove(PanelIndicatorEntryView::Ptr(view));
1340
1341 RemoveChild(view);
1342- entries_.erase(view->GetEntryID());
1343+ entries_.erase(view->GetEntry());
1344 layout_->RemoveChildObject(view);
1345 on_indicator_updated.emit();
1346
1347@@ -365,9 +392,12 @@
1348 QueueDraw();
1349 }
1350
1351-void PanelIndicatorsView::RemoveEntry(std::string const& entry_id)
1352+void PanelIndicatorsView::RemoveEntry(indicator::Entry::Ptr const& entry)
1353 {
1354- RemoveEntryView(entries_[entry_id]);
1355+ auto it = entries_.find(entry);
1356+
1357+ if (it != entries_.end())
1358+ RemoveEntryView(it->second);
1359 }
1360
1361 void PanelIndicatorsView::OverlayShown()
1362
1363=== modified file 'panel/PanelIndicatorsView.h'
1364--- panel/PanelIndicatorsView.h 2014-03-06 09:26:03 +0000
1365+++ panel/PanelIndicatorsView.h 2015-07-15 14:19:40 +0000
1366@@ -55,9 +55,10 @@
1367 int padding = 5,
1368 IndicatorEntryPosition pos = AUTO,
1369 IndicatorEntryType type = IndicatorEntryType::INDICATOR);
1370- void RemoveEntry(std::string const& entry_id);
1371+ void RemoveEntry(indicator::Entry::Ptr const&);
1372
1373 PanelIndicatorEntryView* ActivateEntryAt(int x, int y, int button = 1);
1374+ PanelIndicatorEntryView* ActivateEntry(indicator::Entry::Ptr const&, int button = 1);
1375 PanelIndicatorEntryView* ActivateEntry(std::string const& entry_id, int button = 1);
1376 bool ActivateIfSensitive();
1377
1378@@ -84,18 +85,19 @@
1379 typedef std::vector<indicator::Indicator::Ptr> Indicators;
1380 Indicators const& GetIndicators() const;
1381
1382+ void ClearEntries();
1383+
1384 virtual void Draw(nux::GraphicsEngine& GfxContext, bool force_draw);
1385 virtual void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw);
1386
1387- virtual void OnEntryAdded(indicator::Entry::Ptr const& entry);
1388+ virtual void OnEntryAdded(indicator::Entry::Ptr const&);
1389 virtual void OnEntryRefreshed(PanelIndicatorEntryView* view);
1390
1391 void AddEntryView(PanelIndicatorEntryView* view, IndicatorEntryPosition pos = AUTO);
1392 void RemoveEntryView(PanelIndicatorEntryView* view);
1393
1394 nux::HLayout* layout_;
1395- typedef std::map<std::string, PanelIndicatorEntryView*> Entries;
1396- Entries entries_;
1397+ std::unordered_map<indicator::Entry::Ptr, PanelIndicatorEntryView*> entries_;
1398
1399 int monitor_;
1400 bool overlay_showing_;
1401
1402=== modified file 'panel/PanelMenuView.cpp'
1403--- panel/PanelMenuView.cpp 2015-03-12 00:57:05 +0000
1404+++ panel/PanelMenuView.cpp 2015-07-15 14:19:40 +0000
1405@@ -27,6 +27,7 @@
1406 #include "unity-shared/CairoTexture.h"
1407 #include "unity-shared/DecorationStyle.h"
1408 #include "unity-shared/PanelStyle.h"
1409+#include "unity-shared/RawPixel.h"
1410 #include "unity-shared/UnitySettings.h"
1411 #include "unity-shared/UBusMessages.h"
1412 #include "unity-shared/UScreen.h"
1413@@ -43,15 +44,14 @@
1414
1415 namespace
1416 {
1417- const int MAIN_LEFT_PADDING = 4;
1418- const int TITLE_PADDING = 2;
1419- const int MENUBAR_PADDING = 4;
1420+ const RawPixel MAIN_LEFT_PADDING = 4_em;
1421+ const RawPixel TITLE_PADDING = 2_em;
1422+ const RawPixel MENUBAR_PADDING = 4_em;
1423 const int MENU_ENTRIES_PADDING = 6;
1424
1425 const std::string NEW_APP_HIDE_TIMEOUT = "new-app-hide-timeout";
1426 const std::string NEW_APP_SHOW_TIMEOUT = "new-app-show-timeout";
1427 const std::string WINDOW_MOVED_TIMEOUT = "window-moved-timeout";
1428- const std::string WINDOW_ACTIVATED_TIMEOUT = "window-activated-timeout";
1429 const std::string UPDATE_SHOW_NOW_TIMEOUT = "update-show-now-timeout";
1430 const std::string INTEGRATED_MENUS_DOUBLE_CLICK_TIMEOUT = "integrated-menus-double-click-timeout";
1431
1432@@ -83,7 +83,10 @@
1433 }
1434
1435 PanelMenuView::PanelMenuView(menu::Manager::Ptr const& menus)
1436- : menu_manager_(menus)
1437+ : active_window(0)
1438+ , maximized_window(0)
1439+ , focused(true)
1440+ , menu_manager_(menus)
1441 , matcher_(bamf_matcher_get_default())
1442 , is_inside_(false)
1443 , is_grabbed_(false)
1444@@ -100,16 +103,15 @@
1445 , ignore_menu_visibility_(false)
1446 , integrated_menus_(menu_manager_->integrated_menus())
1447 , always_show_menus_(menu_manager_->always_show_menus())
1448- , active_xid_(0)
1449 , desktop_name_(get_current_desktop())
1450 {
1451 BamfWindow* active_win = bamf_matcher_get_active_window(matcher_);
1452 if (BAMF_IS_WINDOW(active_win))
1453- active_xid_ = bamf_window_get_xid(active_win);
1454+ active_window = bamf_window_get_xid(active_win);
1455
1456- SetupPanelMenuViewSignals();
1457 SetupWindowButtons();
1458 SetupTitlebarGrabArea();
1459+ SetupPanelMenuViewSignals();
1460 SetupWindowManagerSignals();
1461 SetupUBusManagerInterests();
1462
1463@@ -128,8 +130,10 @@
1464 void PanelMenuView::OnStyleChanged()
1465 {
1466 int height = panel::Style::Instance().PanelHeight(monitor_);
1467+ double scale = Settings::Instance().em(monitor_)->DPIScale();
1468 window_buttons_->SetMinimumHeight(height);
1469 window_buttons_->SetMaximumHeight(height);
1470+ window_buttons_->SetLeftAndRightPadding(MAIN_LEFT_PADDING.CP(scale), MENUBAR_PADDING.CP(scale));
1471 window_buttons_->UpdateDPIChanged();
1472
1473 layout_->SetLeftAndRightPadding(window_buttons_->GetContentWidth(), 0);
1474@@ -157,6 +161,20 @@
1475
1476 menu_manager_->integrated_menus.changed.connect(sigc::mem_fun(this, &PanelMenuView::OnLIMChanged));
1477 menu_manager_->always_show_menus.changed.connect(sigc::mem_fun(this, &PanelMenuView::OnAlwaysShowMenusChanged));
1478+
1479+ auto update_target_cb = sigc::hide(sigc::mem_fun(this, &PanelMenuView::UpdateTargetWindowItems));
1480+ maximized_window.changed.connect(update_target_cb);
1481+ active_window.changed.connect(update_target_cb);
1482+
1483+ focused.changed.connect([this] (bool focused) {
1484+ Refresh(true);
1485+ window_buttons_->focused = focused;
1486+
1487+ for (auto const& entry : entries_)
1488+ entry.second->SetFocusedState(focused);
1489+
1490+ FullRedraw();
1491+ });
1492 }
1493
1494 void PanelMenuView::SetupWindowButtons()
1495@@ -164,7 +182,7 @@
1496 window_buttons_ = new WindowButtons();
1497 window_buttons_->SetParentObject(this);
1498 window_buttons_->monitor = monitor_;
1499- window_buttons_->controlled_window = active_xid_;
1500+ window_buttons_->controlled_window = active_window();
1501 window_buttons_->opacity = 0.0f;
1502 window_buttons_->SetLeftAndRightPadding(MAIN_LEFT_PADDING, MENUBAR_PADDING);
1503 window_buttons_->SetMaximumHeight(panel::Style::Instance().PanelHeight(monitor_));
1504@@ -252,6 +270,27 @@
1505 PanelIndicatorsView::AddIndicator(indicator);
1506 }
1507
1508+void PanelMenuView::UpdateTargetWindowItems()
1509+{
1510+ Window old_target = window_buttons_->controlled_window;
1511+ Window target_window = integrated_menus_ ? maximized_window() : active_window();
1512+
1513+ if (old_target != target_window)
1514+ {
1515+ window_buttons_->controlled_window = target_window;
1516+ ClearEntries();
1517+
1518+ if (indicator::AppmenuIndicator::Ptr appmenu = menu_manager_->AppMenu())
1519+ {
1520+ for (auto const& entry : appmenu->GetEntriesForWindow(target_window))
1521+ OnEntryAdded(entry);
1522+ }
1523+ }
1524+
1525+ if (integrated_menus_)
1526+ focused = (target_window == active_window());
1527+}
1528+
1529 void PanelMenuView::FullRedraw()
1530 {
1531 QueueDraw();
1532@@ -266,9 +305,11 @@
1533 if (!integrated_menus_)
1534 {
1535 CheckMouseInside();
1536- window_buttons_->focused = true;
1537+ focused = true;
1538 }
1539
1540+ UpdateTargetWindowItems();
1541+
1542 Refresh(true);
1543 FullRedraw();
1544 }
1545@@ -302,7 +343,7 @@
1546 return titlebar_grab_area_.GetPointer();
1547 }
1548
1549- if (is_maximized_ || spread_showing_ || (integrated_menus_ && GetMaximizedWindow() != 0))
1550+ if (is_maximized_ || spread_showing_ || (integrated_menus_ && maximized_window() != 0))
1551 {
1552 found_area = window_buttons_->FindAreaUnderMouse(mouse_position, event_type);
1553 NUX_RETURN_VALUE_IF_NOTNULL(found_area, found_area);
1554@@ -313,7 +354,7 @@
1555 found_area = titlebar_grab_area_->FindAreaUnderMouse(mouse_position, event_type);
1556 NUX_RETURN_VALUE_IF_NOTNULL(found_area, found_area);
1557
1558- if (integrated_menus_ && GetMaximizedWindow() != 0)
1559+ if (integrated_menus_ && maximized_window() != 0)
1560 {
1561 /* When the integrated menus are enabled, that area must act both like an
1562 * indicator-entry view and like a panel-grab-area, so not to re-implement
1563@@ -382,10 +423,7 @@
1564
1565 bool PanelMenuView::ShouldDrawMenus() const
1566 {
1567- if (integrated_menus_ && !is_maximized_)
1568- return false;
1569-
1570- if (we_control_active_ && !switcher_showing_ && !launcher_keynav_ && !ignore_menu_visibility_ && !entries_.empty())
1571+ if ((we_control_active_ || integrated_menus_) && !switcher_showing_ && !launcher_keynav_ && !ignore_menu_visibility_ && HasVisibleMenus())
1572 {
1573 WindowManager& wm = WindowManager::Default();
1574
1575@@ -410,7 +448,7 @@
1576 if (integrated_menus_)
1577 {
1578 if (!WindowManager::Default().IsExpoActive())
1579- return (GetMaximizedWindow() != 0);
1580+ return (maximized_window() != 0);
1581
1582 return false;
1583 }
1584@@ -796,7 +834,7 @@
1585
1586 std::string PanelMenuView::GetMaximizedViewName(bool use_appname) const
1587 {
1588- Window maximized = GetMaximizedWindow();
1589+ Window maximized = maximized_window();
1590 BamfWindow* window = nullptr;
1591 std::string label;
1592
1593@@ -830,18 +868,18 @@
1594 auto const& style = decoration::Style::Get();
1595 auto text_size = style->TitleNaturalSize(label);
1596 auto state = WidgetState::NORMAL;
1597- float dpi_scale = Settings::Instance().em(monitor_)->DPIScale();
1598+ double dpi_scale = Settings::Instance().em(monitor_)->DPIScale();
1599
1600 if (integrated_menus_ && !is_desktop_focused_ && !WindowManager::Default().IsExpoActive())
1601 {
1602 title_geo_.x = geo.x + window_buttons_->GetBaseWidth() + (style->TitleIndent() * dpi_scale);
1603
1604- if (!window_buttons_->focused())
1605+ if (!focused())
1606 state = WidgetState::BACKDROP;
1607 }
1608 else
1609 {
1610- title_geo_.x = geo.x + (MAIN_LEFT_PADDING + TITLE_PADDING) * dpi_scale;
1611+ title_geo_.x = geo.x + MAIN_LEFT_PADDING.CP(dpi_scale) + TITLE_PADDING.CP(dpi_scale);
1612 }
1613
1614 title_geo_.y = geo.y + (geo.height - (text_size.height * dpi_scale)) / 2;
1615@@ -904,20 +942,9 @@
1616 if (geo.width > monitor_geo_.width)
1617 return false;
1618
1619- if (integrated_menus_)
1620- {
1621- Window maximized = GetMaximizedWindow();
1622- window_buttons_->controlled_window = maximized;
1623- window_buttons_->focused = (active_xid_ == maximized);
1624- }
1625- else
1626- {
1627- window_buttons_->controlled_window = active_xid_;
1628- }
1629-
1630 std::string const& new_title = GetCurrentTitle();
1631
1632- if (new_title == panel_title_ && !force && last_geo_ == geo && title_texture_)
1633+ if (!force && new_title == panel_title_ && last_geo_ == geo && title_texture_)
1634 {
1635 // No need to redraw the title, let's save some CPU time!
1636 return false;
1637@@ -956,18 +983,20 @@
1638
1639 void PanelMenuView::OnEntryAdded(indicator::Entry::Ptr const& entry)
1640 {
1641- PanelIndicatorEntryView* view;
1642+ auto parent_window = entry->parent_window();
1643+ Window target = integrated_menus_ ? maximized_window() : active_window();
1644
1645- view = new PanelIndicatorEntryView(entry, MENU_ENTRIES_PADDING, IndicatorEntryType::MENU);
1646- entry->show_now_changed.connect(sigc::mem_fun(this, &PanelMenuView::UpdateShowNow));
1647- AddEntryView(view);
1648+ if (!parent_window || parent_window == target)
1649+ AddEntryView(new PanelIndicatorEntryView(entry, MENU_ENTRIES_PADDING, IndicatorEntryType::MENU));
1650 }
1651
1652 void PanelMenuView::OnEntryViewAdded(PanelIndicatorEntryView* view)
1653 {
1654+ view->SetFocusedState(focused());
1655 view->mouse_enter.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseEnter));
1656 view->mouse_leave.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseLeave));
1657 view->active_changed.connect(sigc::mem_fun(this, &PanelMenuView::OnActiveChanged));
1658+ view->show_now_changed.connect(sigc::mem_fun(this, &PanelMenuView::UpdateShowNow));
1659 }
1660
1661 void PanelMenuView::NotifyAllMenusClosed()
1662@@ -1116,58 +1145,41 @@
1663 show_now_activated_ = false;
1664 is_maximized_ = false;
1665 is_desktop_focused_ = false;
1666- active_xid_ = 0;
1667- bool force_refresh = false;
1668+ Window active_xid = 0;
1669
1670 sources_.Remove(WINDOW_MOVED_TIMEOUT);
1671
1672 if (BAMF_IS_WINDOW(new_view))
1673 {
1674 BamfWindow* window = reinterpret_cast<BamfWindow*>(new_view);
1675- active_xid_ = bamf_window_get_xid(window);
1676+ active_xid = bamf_window_get_xid(window);
1677 is_maximized_ = (bamf_window_maximized(window) == BAMF_WINDOW_MAXIMIZED);
1678
1679 if (bamf_window_get_window_type(window) == BAMF_WINDOW_DESKTOP)
1680 {
1681- is_desktop_focused_ = !GetMaximizedWindow();
1682+ is_desktop_focused_ = !maximized_window();
1683 we_control_active_ = true;
1684 }
1685 else
1686 {
1687- we_control_active_ = IsWindowUnderOurControl(active_xid_);
1688+ we_control_active_ = IsWindowUnderOurControl(active_xid);
1689 }
1690
1691 if (is_maximized_)
1692 {
1693- maximized_wins_.erase(std::remove(maximized_wins_.begin(), maximized_wins_.end(), active_xid_), maximized_wins_.end());
1694- maximized_wins_.push_front(active_xid_);
1695+ maximized_wins_.erase(std::remove(maximized_wins_.begin(), maximized_wins_.end(), active_xid), maximized_wins_.end());
1696+ maximized_wins_.push_front(active_xid);
1697+ UpdateMaximizedWindow();
1698 }
1699
1700 // register callback for new view
1701 view_name_changed_signal_.Connect(new_view, "name-changed",
1702 sigc::mem_fun(this, &PanelMenuView::OnNameChanged));
1703-
1704- if (integrated_menus_)
1705- force_refresh = is_maximized_;
1706- }
1707-
1708- if (!force_refresh && BAMF_IS_WINDOW(old_view) && integrated_menus_)
1709- force_refresh = (bamf_window_maximized(reinterpret_cast<BamfWindow*>(old_view)) == BAMF_WINDOW_MAXIMIZED);
1710-
1711- if (ShouldDrawMenus())
1712- {
1713- // Wait 100ms before showing the menus again if we've just switched view
1714- // this is done because the menus are updated by the indicator with some
1715- // delay, and we don't want to see the previous menus and then the new ones
1716- ignore_menu_visibility_ = true;
1717- sources_.AddTimeout(100, [this] {
1718- ignore_menu_visibility_ = false;
1719- QueueDraw();
1720- return false;
1721- }, WINDOW_ACTIVATED_TIMEOUT);
1722- }
1723-
1724- if (Refresh(force_refresh))
1725+ }
1726+
1727+ active_window = active_xid;
1728+
1729+ if (Refresh())
1730 FullRedraw();
1731 }
1732
1733@@ -1198,8 +1210,9 @@
1734 void PanelMenuView::OnWindowMinimized(Window xid)
1735 {
1736 maximized_wins_.erase(std::remove(maximized_wins_.begin(), maximized_wins_.end(), xid), maximized_wins_.end());
1737+ UpdateMaximizedWindow();
1738
1739- if (xid == active_xid_)
1740+ if (xid == active_window())
1741 {
1742 if (Refresh())
1743 QueueDraw();
1744@@ -1213,10 +1226,13 @@
1745
1746 void PanelMenuView::OnWindowUnminimized(Window xid)
1747 {
1748- if (xid == active_xid_)
1749+ if (xid == active_window())
1750 {
1751 if (WindowManager::Default().IsWindowMaximized(xid))
1752+ {
1753 maximized_wins_.push_front(xid);
1754+ UpdateMaximizedWindow();
1755+ }
1756
1757 if (Refresh())
1758 QueueDraw();
1759@@ -1224,7 +1240,10 @@
1760 else
1761 {
1762 if (WindowManager::Default().IsWindowMaximized(xid))
1763+ {
1764 maximized_wins_.push_back(xid);
1765+ UpdateMaximizedWindow();
1766+ }
1767
1768 if (integrated_menus_ && IsWindowUnderOurControl(xid))
1769 {
1770@@ -1239,8 +1258,9 @@
1771 // FIXME: compiz doesn't give us a valid xid (is always 0 on unmap)
1772 // we need to do this again on BamfView closed signal.
1773 maximized_wins_.erase(std::remove(maximized_wins_.begin(), maximized_wins_.end(), xid), maximized_wins_.end());
1774+ UpdateMaximizedWindow();
1775
1776- if (xid == active_xid_)
1777+ if (xid == active_window())
1778 {
1779 if (Refresh())
1780 QueueDraw();
1781@@ -1256,9 +1276,10 @@
1782 {
1783 if (WindowManager::Default().IsWindowMaximized(xid))
1784 {
1785- if (xid == active_xid_)
1786+ if (xid == active_window())
1787 {
1788 maximized_wins_.push_front(xid);
1789+ UpdateMaximizedWindow();
1790
1791 if (Refresh())
1792 QueueDraw();
1793@@ -1266,15 +1287,17 @@
1794 else
1795 {
1796 maximized_wins_.push_back(xid);
1797+ UpdateMaximizedWindow();
1798 }
1799 }
1800 }
1801
1802 void PanelMenuView::OnWindowMaximized(Window xid)
1803 {
1804- if (xid == active_xid_)
1805+ if (xid == active_window())
1806 {
1807 maximized_wins_.push_front(xid);
1808+ UpdateMaximizedWindow();
1809
1810 // We need to update the is_inside_ state in the case of maximization by grab
1811 CheckMouseInside();
1812@@ -1286,6 +1309,7 @@
1813 else
1814 {
1815 maximized_wins_.push_back(xid);
1816+ UpdateMaximizedWindow();
1817
1818 if (integrated_menus_ && IsWindowUnderOurControl(xid))
1819 {
1820@@ -1298,8 +1322,9 @@
1821 void PanelMenuView::OnWindowRestored(Window xid)
1822 {
1823 maximized_wins_.erase(std::remove(maximized_wins_.begin(), maximized_wins_.end(), xid), maximized_wins_.end());
1824+ UpdateMaximizedWindow();
1825
1826- if (active_xid_ == xid)
1827+ if (active_window() == xid)
1828 {
1829 is_maximized_ = false;
1830 is_grabbed_ = false;
1831@@ -1316,13 +1341,13 @@
1832
1833 bool PanelMenuView::UpdateActiveWindowPosition()
1834 {
1835- bool we_control_window = IsWindowUnderOurControl(active_xid_);
1836+ bool we_control_window = IsWindowUnderOurControl(active_window);
1837
1838 if (we_control_window != we_control_active_)
1839 {
1840 we_control_active_ = we_control_window;
1841
1842- if (!entries_.empty())
1843+ if (HasVisibleMenus())
1844 on_indicator_updated.emit();
1845
1846 if (Refresh())
1847@@ -1334,21 +1359,17 @@
1848
1849 void PanelMenuView::OnWindowMoved(Window xid)
1850 {
1851- if (active_xid_ == xid)
1852+ if (!integrated_menus_ && active_window() == xid && UScreen::GetDefault()->GetMonitors().size() > 1)
1853 {
1854 /* When moving the active window, if the current panel is controlling
1855 * the active window, then we postpone the timeout function every movement
1856 * that we have, setting a longer timeout.
1857- * Otherwise, if the moved window is not controlled by the current panel
1858+ * Otherwise, if the movedPanelMenuView::OnWindowMovedPanelMenuView::OnWindowMoved window is not controlled by the current panel
1859 * every few millisecond we check the new window position */
1860
1861 unsigned int timeout_length = 250;
1862
1863- if (we_control_active_)
1864- {
1865- sources_.Remove(WINDOW_MOVED_TIMEOUT);
1866- }
1867- else
1868+ if (!we_control_active_)
1869 {
1870 if (sources_.GetSource(WINDOW_MOVED_TIMEOUT))
1871 return;
1872@@ -1359,6 +1380,9 @@
1873 auto cb_func = sigc::mem_fun(this, &PanelMenuView::UpdateActiveWindowPosition);
1874 sources_.AddTimeout(timeout_length, cb_func, WINDOW_MOVED_TIMEOUT);
1875 }
1876+
1877+ if (std::find(maximized_wins_.begin(), maximized_wins_.end(), xid) != maximized_wins_.end())
1878+ UpdateMaximizedWindow();
1879 }
1880
1881 bool PanelMenuView::IsWindowUnderOurControl(Window xid) const
1882@@ -1391,7 +1415,7 @@
1883 return false;
1884 }
1885
1886-Window PanelMenuView::GetMaximizedWindow() const
1887+void PanelMenuView::UpdateMaximizedWindow()
1888 {
1889 Window window_xid = 0;
1890
1891@@ -1406,7 +1430,7 @@
1892 }
1893 }
1894
1895- return window_xid;
1896+ maximized_window = window_xid;
1897 }
1898
1899 Window PanelMenuView::GetTopWindow() const
1900@@ -1466,11 +1490,14 @@
1901 if (!layout_->GetAbsoluteGeometry().IsInside(click))
1902 return;
1903
1904- unsigned double_click_wait = Settings::Instance().lim_double_click_wait();
1905-
1906- if (double_click_wait > 0)
1907+ auto& settings = Settings::Instance();
1908+
1909+ if (!focused && !settings.lim_unfocused_popup())
1910+ return;
1911+
1912+ if (settings.lim_double_click_wait() > 0)
1913 {
1914- sources_.AddTimeout(double_click_wait, [this, click] {
1915+ sources_.AddTimeout(settings.lim_double_click_wait(), [this, click] {
1916 ActivateEntryAt(click.x, click.y);
1917 return false;
1918 }, INTEGRATED_MENUS_DOUBLE_CLICK_TIMEOUT);
1919@@ -1489,15 +1516,18 @@
1920
1921 void PanelMenuView::OnMaximizedActivate(int x, int y)
1922 {
1923- Window maximized = GetMaximizedWindow();
1924+ Window maximized = maximized_window();
1925
1926 if (maximized != 0)
1927 {
1928- if (maximized != active_xid_)
1929+ if (maximized != active_window())
1930 {
1931- WindowManager::Default().Activate(maximized);
1932+ auto& wm = WindowManager::Default();
1933+ wm.Raise(maximized);
1934+ wm.Activate(maximized);
1935 }
1936- else if (integrated_menus_)
1937+
1938+ if (integrated_menus_)
1939 {
1940 // Adjusting the click coordinates to be absolute.
1941 auto const& grab_geo = titlebar_grab_area_->GetAbsoluteGeometry();
1942@@ -1509,7 +1539,7 @@
1943
1944 void PanelMenuView::MaximizedWindowWMAction(int x, int y, unsigned button)
1945 {
1946- Window maximized = GetMaximizedWindow();
1947+ Window maximized = maximized_window();
1948
1949 if (!maximized)
1950 return;
1951@@ -1590,7 +1620,7 @@
1952 * This is a workaround to avoid that the grid plugin would be fired
1953 * showing the window shape preview effect. See bug #838923 */
1954
1955- Window maximized = GetMaximizedWindow();
1956+ Window maximized = maximized_window();
1957
1958 if (maximized != 0)
1959 {
1960@@ -1611,7 +1641,7 @@
1961 x += titlebar_grab_area_->GetAbsoluteX();
1962 y += titlebar_grab_area_->GetAbsoluteY();
1963
1964- Window maximized = GetMaximizedWindow();
1965+ Window maximized = maximized_window();
1966
1967 /* When the drag goes out from the Panel, start the real movement.
1968 *
1969@@ -1686,6 +1716,8 @@
1970 PanelIndicatorsView::AddProperties(introspection);
1971
1972 introspection
1973+ .add("focused", focused())
1974+ .add("integrated_menus", integrated_menus_)
1975 .add("mouse_inside", is_inside_)
1976 .add("always_show_menus", always_show_menus_)
1977 .add("grabbed", is_grabbed_)
1978@@ -1694,7 +1726,8 @@
1979 .add("panel_title", panel_title_)
1980 .add("desktop_active", (panel_title_ == desktop_name_))
1981 .add("monitor", monitor_)
1982- .add("active_window", active_xid_)
1983+ .add("active_window", active_window())
1984+ .add("maximized_window", maximized_window())
1985 .add("draw_menus", ShouldDrawMenus())
1986 .add("draw_window_buttons", ShouldDrawButtons())
1987 .add("controls_active_window", we_control_active_)
1988@@ -1833,32 +1866,19 @@
1989 auto xid = bamf_window_get_xid(window);
1990
1991 if (bamf_view_is_active(view))
1992- active_xid_ = xid;
1993+ active_window = xid;
1994
1995 if (bamf_window_maximized(window) == BAMF_WINDOW_MAXIMIZED)
1996 {
1997- if (xid == active_xid_)
1998+ if (xid == active_window())
1999 maximized_wins_.push_front(xid);
2000 else
2001 maximized_wins_.push_back(xid);
2002 }
2003 }
2004
2005- Window maximized = GetMaximizedWindow();
2006- Window buttons_win = 0;
2007-
2008- if (integrated_menus_)
2009- {
2010- buttons_win = maximized;
2011- window_buttons_->focused = (maximized == active_xid_);
2012- }
2013- else
2014- {
2015- buttons_win = (maximized == active_xid_) ? maximized : 0;
2016- }
2017-
2018 window_buttons_->monitor = monitor_;
2019- window_buttons_->controlled_window = buttons_win;
2020+ UpdateMaximizedWindow();
2021
2022 OnStyleChanged();
2023 g_list_free(windows);
2024@@ -1866,7 +1886,15 @@
2025
2026 bool PanelMenuView::HasMenus() const
2027 {
2028- if (entries_.empty())
2029+ if (!HasVisibleMenus())
2030+ return false;
2031+
2032+ return integrated_menus_ || we_control_active_;
2033+}
2034+
2035+bool PanelMenuView::HasKeyActivableMenus() const
2036+{
2037+ if (!HasVisibleMenus())
2038 return false;
2039
2040 return integrated_menus_ ? is_maximized_ : we_control_active_;
2041
2042=== modified file 'panel/PanelMenuView.h'
2043--- panel/PanelMenuView.h 2015-03-12 00:57:05 +0000
2044+++ panel/PanelMenuView.h 2015-07-15 14:19:40 +0000
2045@@ -44,13 +44,17 @@
2046 PanelMenuView(menu::Manager::Ptr const&);
2047 ~PanelMenuView();
2048
2049+ nux::Property<Window> active_window;
2050+ nux::Property<Window> maximized_window;
2051+ nux::Property<bool> focused;
2052+
2053 void SetMousePosition(int x, int y);
2054 void SetMonitor(int monitor) override;
2055
2056 Window GetTopWindow() const;
2057- Window GetMaximizedWindow() const;
2058 bool GetControlsActive() const;
2059 bool HasMenus() const;
2060+ bool HasKeyActivableMenus() const;
2061
2062 void NotifyAllMenusClosed();
2063
2064@@ -120,9 +124,9 @@
2065 bool Refresh(bool force = false);
2066
2067 void UpdateTitleTexture(nux::Geometry const&, std::string const& label);
2068-
2069 void UpdateLastGeometry(nux::Geometry const& geo);
2070 void UpdateTitleGradientTexture();
2071+ void UpdateMaximizedWindow();
2072
2073 void OnPanelViewMouseEnter(int x, int y, unsigned long mouse_button_state, unsigned long special_keys_state);
2074 void OnPanelViewMouseLeave(int x, int y, unsigned long mouse_button_state, unsigned long special_keys_state);
2075@@ -134,6 +138,7 @@
2076 void OnLauncherKeyNavEnded(GVariant* data);
2077 void OnLauncherSelectionChanged(GVariant* data);
2078
2079+ void UpdateTargetWindowItems();
2080 void UpdateShowNow(bool ignore);
2081 bool CheckMouseInside();
2082
2083@@ -158,7 +163,7 @@
2084
2085 void ActivateIntegratedMenus(nux::Point const&);
2086
2087- menu::Manager::Ptr const& menu_manager_;
2088+ menu::Manager::Ptr menu_manager_;
2089 glib::Object<BamfMatcher> matcher_;
2090
2091 nux::TextureLayer* title_layer_;
2092@@ -190,7 +195,6 @@
2093 bool integrated_menus_;
2094 bool always_show_menus_;
2095
2096- Window active_xid_;
2097 nux::Geometry monitor_geo_;
2098 const std::string desktop_name_;
2099
2100
2101=== modified file 'panel/PanelView.cpp'
2102--- panel/PanelView.cpp 2014-03-06 16:26:34 +0000
2103+++ panel/PanelView.cpp 2015-07-15 14:19:40 +0000
2104@@ -519,7 +519,7 @@
2105
2106 if (opacity_maximized_toggle_)
2107 {
2108- Window maximized_win = menu_view_->GetMaximizedWindow();
2109+ Window maximized_win = menu_view_->maximized_window();
2110
2111 if (wm.IsExpoActive() || (maximized_win != 0 && !wm.IsWindowObscured(maximized_win)))
2112 opacity = 1.0f;
2113@@ -676,7 +676,7 @@
2114 if (!IsActive())
2115 return false;
2116
2117- if ((menu_view_->HasMenus() && menu_view_->ActivateIfSensitive()) ||
2118+ if ((menu_view_->HasKeyActivableMenus() && menu_view_->ActivateIfSensitive()) ||
2119 indicators_->ActivateIfSensitive())
2120 {
2121 // Since this only happens on keyboard events, we need to prevent that the
2122@@ -693,7 +693,7 @@
2123 if (!IsActive())
2124 return false;
2125
2126- if ((menu_view_->HasMenus() && menu_view_->ActivateEntry(entry_id, 0)) ||
2127+ if ((menu_view_->HasKeyActivableMenus() && menu_view_->ActivateEntry(entry_id, 0)) ||
2128 indicators_->ActivateEntry(entry_id, 0))
2129 {
2130 // Since this only happens on keyboard events, we need to prevent that the
2131
2132=== modified file 'plugins/unityshell/src/unityshell.cpp'
2133--- plugins/unityshell/src/unityshell.cpp 2015-06-03 12:46:12 +0000
2134+++ plugins/unityshell/src/unityshell.cpp 2015-07-15 14:19:40 +0000
2135@@ -156,6 +156,7 @@
2136 , cScreen(CompositeScreen::get(screen))
2137 , gScreen(GLScreen::get(screen))
2138 , sScreen(ScaleScreen::get(screen))
2139+ , WM(PluginAdapter::Initialize(screen))
2140 , menus_(std::make_shared<menu::Manager>(std::make_shared<indicator::DBusIndicators>(), std::make_shared<key::GnomeGrabber>()))
2141 , deco_manager_(std::make_shared<decoration::Manager>(menus_))
2142 , debugger_(this)
2143@@ -278,9 +279,6 @@
2144 ScaleScreenInterface::setHandler(sScreen);
2145 screen->updateSupportedWmHints();
2146
2147- PluginAdapter::Initialize(screen);
2148- AddChild(&WindowManager::Default());
2149-
2150 StartupNotifyService::Default()->SetSnDisplay(screen->snDisplay(), screen->screenNum());
2151
2152 nux::NuxInitialize(0);
2153@@ -441,13 +439,13 @@
2154 sigc::mem_fun(this, &UnityScreen::OnMinimizeDurationChanged)
2155 );
2156
2157- WindowManager& wm = WindowManager::Default();
2158- wm.initiate_spread.connect(sigc::mem_fun(this, &UnityScreen::OnInitiateSpread));
2159- wm.terminate_spread.connect(sigc::mem_fun(this, &UnityScreen::OnTerminateSpread));
2160- wm.initiate_expo.connect(sigc::mem_fun(this, &UnityScreen::DamagePanelShadow));
2161- wm.terminate_expo.connect(sigc::mem_fun(this, &UnityScreen::DamagePanelShadow));
2162+ WM.initiate_spread.connect(sigc::mem_fun(this, &UnityScreen::OnInitiateSpread));
2163+ WM.terminate_spread.connect(sigc::mem_fun(this, &UnityScreen::OnTerminateSpread));
2164+ WM.initiate_expo.connect(sigc::mem_fun(this, &UnityScreen::DamagePanelShadow));
2165+ WM.terminate_expo.connect(sigc::mem_fun(this, &UnityScreen::DamagePanelShadow));
2166
2167- AddChild(&screen_introspection_);
2168+ Introspectable::AddChild(&WM);
2169+ Introspectable::AddChild(&screen_introspection_);
2170
2171 /* Create blur backup texture */
2172 auto gpu_device = nux::GetGraphicsDisplay()->GetGpuDevice();
2173@@ -686,7 +684,7 @@
2174 if (sources_.GetSource(local::RELAYOUT_TIMEOUT))
2175 return;
2176
2177- if (WindowManager::Default().IsExpoActive())
2178+ if (WM.IsExpoActive())
2179 return;
2180
2181 CompOutput* output = _last_output;
2182@@ -947,7 +945,7 @@
2183 nux::TexCoordXForm texxform;
2184 texxform.SetWrap(nux::TEXWRAP_REPEAT, nux::TEXWRAP_CLAMP);
2185
2186- int monitor = WindowManager::Default().MonitorGeometryIn(NuxGeometryFromCompRect(output_dev));
2187+ int monitor = WM.MonitorGeometryIn(NuxGeometryFromCompRect(output_dev));
2188 auto const& texture = panel_style_.GetBackground(monitor)->GetDeviceTexture();
2189 graphics_engine->QRP_GLSL_1Tex(0, 0, output_dev.width(), texture->GetHeight(), texture, texxform, nux::color::White);
2190 }
2191@@ -960,7 +958,7 @@
2192 hud_controller_->IsVisible() ||
2193 session_controller_->Visible() ||
2194 ((switcher_controller_->Visible() ||
2195- WindowManager::Default().IsExpoActive())
2196+ WM.IsExpoActive())
2197 && !fullscreen_windows_.empty () && (!(screen->grabbed () && !screen->otherGrabExist (NULL))));
2198 }
2199
2200@@ -2218,7 +2216,7 @@
2201 CompAction::State state,
2202 CompOption::Vector& options)
2203 {
2204- WindowManager::Default().ShowDesktop();
2205+ WM.ShowDesktop();
2206 return true;
2207 }
2208
2209@@ -2322,7 +2320,7 @@
2210 CompAction::State state,
2211 CompOption::Vector& options)
2212 {
2213- if (WindowManager::Default().IsWallActive())
2214+ if (WM.IsWallActive())
2215 return false;
2216 else if (switcher_controller_->Visible())
2217 switcher_controller_->Next();
2218@@ -2520,11 +2518,9 @@
2219 }
2220 else
2221 {
2222- auto& wm = WindowManager::Default();
2223-
2224- if (wm.IsScreenGrabbed())
2225+ if (WM.IsScreenGrabbed())
2226 {
2227- hud_ungrab_slot_ = wm.screen_ungrabbed.connect([this] { ShowHud(); });
2228+ hud_ungrab_slot_ = WM.screen_ungrabbed.connect([this] { ShowHud(); });
2229
2230 // Let's wait ungrab event for maximum a couple of seconds...
2231 sources_.AddTimeoutSeconds(2, [this] {
2232@@ -2663,7 +2659,7 @@
2233 KeySym keysym = XkbKeycodeToKeysym(screen->dpy(), keybind.keycode(), 0, 0);
2234 unsigned modifiers = CompizModifiersToNux(keybind.modifiers());
2235
2236- WindowManager::Default().close_window_key = std::make_pair(modifiers, keysym);
2237+ WM.close_window_key = std::make_pair(modifiers, keysym);
2238 }
2239
2240 void UnityScreen::UpdateActivateIndicatorsKey()
2241@@ -2672,7 +2668,7 @@
2242 KeySym keysym = XkbKeycodeToKeysym(screen->dpy(), keybind.keycode(), 0, 0);
2243 unsigned modifiers = CompizModifiersToNux(keybind.modifiers());
2244
2245- WindowManager::Default().activate_indicators_key = std::make_pair(modifiers, keysym);
2246+ WM.activate_indicators_key = std::make_pair(modifiers, keysym);
2247 }
2248
2249 bool UnityScreen::initPluginActions()
2250@@ -2925,7 +2921,7 @@
2251 }
2252 }
2253
2254- if (WindowManager::Default().IsScaleActive() &&
2255+ if (uScreen->WM.IsScaleActive() &&
2256 uScreen->sScreen->getSelectedWindow() == window->id())
2257 {
2258 nux::Geometry const& scaled_geo = GetScaledGeometry();
2259@@ -3030,9 +3026,8 @@
2260 !(window_state & CompWindowStateFullscreenMask) &&
2261 !(window_type & CompWindowTypeFullscreenMask))
2262 {
2263- WindowManager& wm = WindowManager::Default();
2264 auto const& output = uScreen->screen->currentOutputDev();
2265- int monitor = wm.MonitorGeometryIn(NuxGeometryFromCompRect(output));
2266+ int monitor = uScreen->WM.MonitorGeometryIn(NuxGeometryFromCompRect(output));
2267
2268 if (window->y() - window->border().top < output.y() + uScreen->panel_style_.PanelHeight(monitor))
2269 {
2270@@ -3670,8 +3665,7 @@
2271 {
2272 if (strcmp(name, "hsize") == 0 || strcmp(name, "vsize") == 0)
2273 {
2274- WindowManager& wm = WindowManager::Default();
2275- wm.viewport_layout_changed.emit(screen->vpSize().width(), screen->vpSize().height());
2276+ WM.viewport_layout_changed.emit(screen->vpSize().width(), screen->vpSize().height());
2277 }
2278 else if (strcmp(name, "close_window_key") == 0)
2279 {
2280@@ -3787,13 +3781,11 @@
2281 if (QuicklistManager::Default()->Current())
2282 QuicklistManager::Default()->Current()->Hide();
2283
2284- auto& wm = WindowManager::Default();
2285-
2286- if (wm.IsScaleActive())
2287- wm.TerminateScale();
2288-
2289- if (wm.IsExpoActive())
2290- wm.TerminateExpo();
2291+ if (WM.IsScaleActive())
2292+ WM.TerminateScale();
2293+
2294+ if (WM.IsExpoActive())
2295+ WM.TerminateExpo();
2296
2297 RaiseOSK();
2298 }
2299@@ -3892,24 +3884,24 @@
2300 auto edge_barriers = std::make_shared<ui::EdgeBarrierController>();
2301
2302 launcher_controller_ = std::make_shared<launcher::Controller>(xdnd_manager, edge_barriers);
2303- AddChild(launcher_controller_.get());
2304+ Introspectable::AddChild(launcher_controller_.get());
2305
2306 switcher_controller_ = std::make_shared<switcher::Controller>();
2307 switcher_controller_->detail.changed.connect(sigc::mem_fun(this, &UnityScreen::OnSwitcherDetailChanged));
2308- AddChild(switcher_controller_.get());
2309+ Introspectable::AddChild(switcher_controller_.get());
2310
2311 LOG_INFO(logger) << "initLauncher-Launcher " << timer.ElapsedSeconds() << "s";
2312
2313 /* Setup panel */
2314 timer.Reset();
2315 panel_controller_ = std::make_shared<panel::Controller>(menus_, edge_barriers);
2316- AddChild(panel_controller_.get());
2317+ Introspectable::AddChild(panel_controller_.get());
2318 LOG_INFO(logger) << "initLauncher-Panel " << timer.ElapsedSeconds() << "s";
2319
2320 /* Setup Places */
2321 dash_controller_ = std::make_shared<dash::Controller>();
2322 dash_controller_->on_realize.connect(sigc::mem_fun(this, &UnityScreen::OnDashRealized));
2323- AddChild(dash_controller_.get());
2324+ Introspectable::AddChild(dash_controller_.get());
2325
2326 /* Setup Hud */
2327 hud_controller_ = std::make_shared<hud::Controller>();
2328@@ -3918,14 +3910,14 @@
2329 hud_controller_->multiple_launchers = (optionGetNumLaunchers() == 0);
2330 hud_controller_->icon_size = launcher_controller_->options()->icon_size();
2331 hud_controller_->tile_size = launcher_controller_->options()->tile_size();
2332- AddChild(hud_controller_.get());
2333+ Introspectable::AddChild(hud_controller_.get());
2334 LOG_INFO(logger) << "initLauncher-hud " << timer.ElapsedSeconds() << "s";
2335
2336 // Setup Shortcut Hint
2337 auto base_window_raiser = std::make_shared<shortcut::BaseWindowRaiserImp>();
2338 auto shortcuts_modeller = std::make_shared<shortcut::CompizModeller>();
2339 shortcut_controller_ = std::make_shared<shortcut::Controller>(base_window_raiser, shortcuts_modeller);
2340- AddChild(shortcut_controller_.get());
2341+ Introspectable::AddChild(shortcut_controller_.get());
2342 ShowFirstRunHints();
2343
2344 // Setup Session Controller
2345@@ -3936,7 +3928,7 @@
2346 manager->unlocked.connect(sigc::mem_fun(this, &UnityScreen::OnScreenUnlocked));
2347 session_dbus_manager_ = std::make_shared<session::DBusManager>(manager);
2348 session_controller_ = std::make_shared<session::Controller>(manager);
2349- AddChild(session_controller_.get());
2350+ Introspectable::AddChild(session_controller_.get());
2351
2352 // Setup Lockscreen Controller
2353 screensaver_dbus_manager_ = std::make_shared<lockscreen::DBusManager>(manager);
2354@@ -4122,7 +4114,7 @@
2355 window->minimizedSetEnabled (this, false);
2356 }
2357
2358- /* Keep this after the optionGetShowMinimizedWindows branch */
2359+ /* Keep this after the optionGetShowMIntrospectable.hinimizedWindows branch */
2360
2361 if (window->state() & CompWindowStateFullscreenMask)
2362 uScreen->fullscreen_windows_.push_back(window);
2363@@ -4139,8 +4131,8 @@
2364 {
2365 Window xid = window->id();
2366 auto const& swins = uScreen->sScreen->getWindows();
2367+ WindowManager& wm = uScreen->WM;
2368 bool scaled = std::find(swins.begin(), swins.end(), ScaleWindow::get(window)) != swins.end();
2369- WindowManager& wm = WindowManager::Default();
2370
2371 introspection
2372 .add(scaled ? GetScaledGeometry() : wm.GetWindowGeometry(xid))
2373@@ -4376,9 +4368,7 @@
2374
2375 nux::Geometry UnityWindow::GetScaledGeometry()
2376 {
2377- WindowManager& wm = WindowManager::Default();
2378-
2379- if (!wm.IsScaleActive())
2380+ if (!uScreen->WM.IsScaleActive())
2381 return nux::Geometry();
2382
2383 ScaleWindow* scale_win = ScaleWindow::get(window);
2384
2385=== modified file 'plugins/unityshell/src/unityshell.h'
2386--- plugins/unityshell/src/unityshell.h 2015-06-03 12:46:12 +0000
2387+++ plugins/unityshell/src/unityshell.h 2015-07-15 14:19:40 +0000
2388@@ -333,6 +333,7 @@
2389
2390 /* The window thread should be the last thing removed, as c++ does it in reverse order */
2391 std::unique_ptr<nux::WindowThread> wt;
2392+ WindowManager& WM;
2393
2394 menu::Manager::Ptr menus_;
2395 std::shared_ptr<decoration::Manager> deco_manager_;
2396@@ -368,7 +369,7 @@
2397 typedef std::vector<CompActionPtr> ShortcutActions;
2398 ShortcutActions _shortcut_actions;
2399 std::map<CancelActionTarget, CompActionPtr> _escape_actions;
2400- std::map<int, unsigned int> windows_for_monitor_;
2401+ std::unordered_map<int, unsigned int> windows_for_monitor_;
2402
2403 /* keyboard-nav mode */
2404 CompWindow* newFocusedWindow;
2405
2406=== modified file 'services/panel-main.c'
2407--- services/panel-main.c 2014-12-09 15:41:53 +0000
2408+++ services/panel-main.c 2015-07-15 14:19:40 +0000
2409@@ -26,20 +26,21 @@
2410 #include "config.h"
2411 #include "panel-a11y.h"
2412 #include "panel-service.h"
2413+#include "panel-service-private.h"
2414
2415 static GDBusNodeInfo *introspection_data = NULL;
2416
2417 static const gchar introspection_xml[] =
2418 "<node>"
2419- " <interface name='com.canonical.Unity.Panel.Service'>"
2420+ " <interface name='"UPS_IFACE"'>"
2421 ""
2422 " <method name='Sync'>"
2423- " <arg type='a(ssssbbusbbi)' name='state' direction='out'/>"
2424+ " <arg type='"ENTRY_ARRAY_SIGNATURE"' name='state' direction='out'/>"
2425 " </method>"
2426 ""
2427 " <method name='SyncOne'>"
2428 " <arg type='s' name='indicator_id' direction='in'/>"
2429- " <arg type='a(ssssbbusbbi)' name='state' direction='out'/>"
2430+ " <arg type='"ENTRY_ARRAY_SIGNATURE"' name='state' direction='out'/>"
2431 " </method>"
2432 ""
2433 " <method name='SyncGeometries'>"
2434@@ -109,10 +110,6 @@
2435 " </interface>"
2436 "</node>";
2437
2438-#define S_NAME_DESKTOP "com.canonical.Unity.Panel.Service.Desktop"
2439-#define S_NAME_LOCKSCREEN "com.canonical.Unity.Panel.Service.LockScreen"
2440-#define S_PATH "/com/canonical/Unity/Panel/Service"
2441-#define S_IFACE "com.canonical.Unity.Panel.Service"
2442
2443 /* Forwards */
2444 static void
2445@@ -270,8 +267,8 @@
2446 GError *error = NULL;
2447 g_dbus_connection_emit_signal (connection,
2448 NULL,
2449- S_PATH,
2450- S_IFACE,
2451+ UPS_PATH,
2452+ UPS_IFACE,
2453 "ReSync",
2454 g_variant_new ("(s)", indicator_id),
2455 &error);
2456@@ -292,10 +289,13 @@
2457 GError *error = NULL;
2458 g_dbus_connection_emit_signal (connection,
2459 NULL,
2460- S_PATH,
2461- S_IFACE,
2462+ UPS_PATH,
2463+ UPS_IFACE,
2464 "EntryActivated",
2465- g_variant_new ("(ss(iiuu))", panel_id, entry_id, x, y, w, h),
2466+ g_variant_new ("(ss(iiuu))",
2467+ panel_id ? panel_id : "",
2468+ entry_id ? entry_id : "",
2469+ x, y, w, h),
2470 &error);
2471
2472 if (error)
2473@@ -315,8 +315,8 @@
2474
2475 g_dbus_connection_emit_signal (connection,
2476 NULL,
2477- S_PATH,
2478- S_IFACE,
2479+ UPS_PATH,
2480+ UPS_IFACE,
2481 "EntryActivateRequest",
2482 g_variant_new ("(s)", entry_id),
2483 &error);
2484@@ -337,8 +337,8 @@
2485 GError *error = NULL;
2486 g_dbus_connection_emit_signal (connection,
2487 NULL,
2488- S_PATH,
2489- S_IFACE,
2490+ UPS_PATH,
2491+ UPS_IFACE,
2492 "EntryShowNowChanged",
2493 g_variant_new ("(sb)", entry_id, show_now_state),
2494 &error);
2495@@ -356,8 +356,8 @@
2496 GError *error = NULL;
2497 g_dbus_connection_emit_signal (connection,
2498 NULL,
2499- S_PATH,
2500- S_IFACE,
2501+ UPS_PATH,
2502+ UPS_IFACE,
2503 "IconPathsChanged",
2504 NULL,
2505 &error);
2506@@ -378,7 +378,7 @@
2507 guint reg_id;
2508
2509 reg_id = g_dbus_connection_register_object (connection,
2510- S_PATH,
2511+ UPS_PATH,
2512 introspection_data->interfaces[0],
2513 &interface_vtable,
2514 service,
2515@@ -489,7 +489,7 @@
2516 service = panel_service_get_default ();
2517
2518 owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
2519- !lockscreen_mode ? S_NAME_DESKTOP : S_NAME_LOCKSCREEN,
2520+ !lockscreen_mode ? UPS_NAME_DESKTOP : UPS_NAME_LOCKSCREEN,
2521 G_BUS_NAME_OWNER_FLAGS_NONE,
2522 on_bus_acquired,
2523 on_name_acquired,
2524
2525=== modified file 'services/panel-service-private.h'
2526--- services/panel-service-private.h 2013-10-03 15:15:35 +0000
2527+++ services/panel-service-private.h 2015-07-15 14:19:40 +0000
2528@@ -21,9 +21,27 @@
2529
2530 #include <X11/Xlib.h>
2531 #include <X11/keysym.h>
2532+#include <glib.h>
2533
2534 G_BEGIN_DECLS
2535
2536+#ifdef __cplusplus
2537+extern "C" {
2538+#endif
2539+
2540+#define UPS_NAME_DESKTOP "com.canonical.Unity.Panel.Service.Desktop"
2541+#define UPS_NAME_LOCKSCREEN "com.canonical.Unity.Panel.Service.LockScreen"
2542+#define UPS_PATH "/com/canonical/Unity/Panel/Service"
2543+#define UPS_IFACE "com.canonical.Unity.Panel.Service"
2544+
2545+#define APPMENU_INDICATOR_NAME "libappmenu.so"
2546+
2547+#define ENTRY_SIGNATURE "(sssusbbusbbi)"
2548+#define ENTRY_ARRAY_SIGNATURE "a" ENTRY_SIGNATURE ""
2549+
2550+#define AltMask Mod1Mask
2551+#define SuperMask Mod4Mask
2552+
2553 typedef struct _KeyBinding
2554 {
2555 KeySym key;
2556@@ -31,11 +49,12 @@
2557 guint32 modifiers;
2558 } KeyBinding;
2559
2560-#define AltMask Mod1Mask
2561-#define SuperMask Mod4Mask
2562-
2563 void parse_string_keybinding (const char *, KeyBinding *);
2564
2565+#ifdef __cplusplus
2566+}
2567+#endif
2568+
2569 G_END_DECLS
2570
2571 #endif /* _PANEL_SERVICE_PRIVATE_H_ */
2572
2573=== modified file 'services/panel-service.c'
2574--- services/panel-service.c 2015-07-15 14:19:40 +0000
2575+++ services/panel-service.c 2015-07-15 14:19:40 +0000
2576@@ -42,7 +42,7 @@
2577
2578 #define NOTIFY_TIMEOUT 80
2579 #define N_TIMEOUT_SLOTS 50
2580-#define MAX_INDICATOR_ENTRIES 100
2581+#define MAX_INDICATOR_ENTRIES 500
2582
2583 #define NUX_VERTICAL_SCROLL_DELTA 120
2584 #define NUX_HORIZONTAL_SCROLL_DELTA (NUX_VERTICAL_SCROLL_DELTA ^ 2)
2585@@ -60,10 +60,13 @@
2586 {
2587 GSList *indicators;
2588 GSList *dropdown_entries;
2589+ GSList *removed_entries;
2590 GHashTable *id2entry_hash;
2591 GHashTable *panel2entries_hash;
2592+ IndicatorObject *appmenu_indicator;
2593
2594- gint32 timeouts[N_TIMEOUT_SLOTS];
2595+ guint timeouts[N_TIMEOUT_SLOTS];
2596+ guint remove_idle;
2597
2598 IndicatorObjectEntry *last_entry;
2599 IndicatorObjectEntry *last_dropdown_entry;
2600@@ -103,14 +106,14 @@
2601
2602 enum
2603 {
2604- SYNC_WAITING = -1,
2605+ SYNC_WAITING = G_MAXUINT,
2606 SYNC_NEUTRAL = 0,
2607 };
2608
2609 static guint32 _service_signals[LAST_SIGNAL] = { 0 };
2610
2611 static const gchar * indicator_order[][2] = {
2612- {"libappmenu.so", NULL}, /* indicator-appmenu" */
2613+ {APPMENU_INDICATOR_NAME, NULL}, /* indicator-appmenu" */
2614 {"libapplication.so", NULL}, /* indicator-application" */
2615 {"floating-indicators", NULL}, /* position-less NG indicators */
2616 {"libprintersmenu.so", NULL}, /* indicator-printers */
2617@@ -135,6 +138,8 @@
2618 static void notify_object (IndicatorObject *object);
2619 static void update_keybinding (GSettings *, const gchar *, gpointer);
2620 static void emit_upstart_event (const gchar *);
2621+static gchar * get_indicator_entry_id_by_entry (IndicatorObjectEntry *entry);
2622+static IndicatorObjectEntry * get_indicator_entry_by_id (PanelService *self, const gchar *entry_id);
2623 static GdkFilterReturn event_filter (GdkXEvent *, GdkEvent *, PanelService *);
2624
2625 /*
2626@@ -163,7 +168,7 @@
2627
2628 for (i = 0; i < N_TIMEOUT_SLOTS; i++)
2629 {
2630- if (priv->timeouts[i] > 0)
2631+ if (priv->timeouts[i] > 0 && priv->timeouts[i] != SYNC_WAITING)
2632 {
2633 g_source_remove (priv->timeouts[i]);
2634 priv->timeouts[i] = 0;
2635@@ -264,9 +269,10 @@
2636 }
2637
2638 static gboolean
2639-is_point_in_rect (gint x, gint y, GdkRectangle* rect)
2640+rect_contains_point (GdkRectangle* rect, gint x, gint y)
2641 {
2642- g_return_val_if_fail (rect, FALSE);
2643+ if (!rect)
2644+ return FALSE;
2645
2646 return (x >= rect->x && x <= (rect->x + rect->width) &&
2647 y >= rect->y && y <= (rect->y + rect->height));
2648@@ -289,7 +295,7 @@
2649 IndicatorObjectEntry *entry = k;
2650 GdkRectangle *geo = v;
2651
2652- if (is_point_in_rect (x, y, geo))
2653+ if (rect_contains_point (geo, x, y))
2654 {
2655 return entry;
2656 }
2657@@ -320,8 +326,7 @@
2658 IndicatorObjectEntry *entry = key;
2659 GdkRectangle *geo = value;
2660
2661- if (x >= geo->x && x <= (geo->x + geo->width) &&
2662- y >= geo->y && y <= (geo->y + geo->height))
2663+ if (rect_contains_point (geo, x, y))
2664 {
2665 return entry;
2666 }
2667@@ -331,7 +336,7 @@
2668 }
2669
2670 static const gchar*
2671-get_panel_at (PanelService *self, gint x, gint y)
2672+get_panel_for_parent_at (PanelService *self, guint parent, gint x, gint y)
2673 {
2674 GHashTableIter panel_iter, entries_iter;
2675 gpointer key, value, k, v;
2676@@ -345,12 +350,20 @@
2677
2678 while (g_hash_table_iter_next (&entries_iter, &k, &v))
2679 {
2680+ IndicatorObjectEntry *entry = k;
2681 GdkRectangle *geo = v;
2682
2683- if (x >= geo->x && x <= (geo->x + geo->width) &&
2684- y >= geo->y && y <= (geo->y + geo->height))
2685+ /* The entry might be invalid at this point (as it could have been
2686+ * removed, but still not synced), so it's better to double check */
2687+ if (g_slist_find (self->priv->removed_entries, entry))
2688+ continue;
2689+
2690+ if (!parent || entry->parent_window == parent)
2691 {
2692- return panel_id;
2693+ if (rect_contains_point (geo, x, y))
2694+ {
2695+ return panel_id;
2696+ }
2697 }
2698 }
2699 }
2700@@ -413,7 +426,7 @@
2701 /* Unity might register some "fake" dropdown entries that it might use to
2702 * to present long menu bars (right now only for appmenu indicator) */
2703 entry = g_new0 (IndicatorObjectEntry, 1);
2704- entry->parent_object = panel_service_get_indicator (self, "libappmenu.so");
2705+ entry->parent_object = self->priv->appmenu_indicator;
2706 entry->name_hint = g_strdup (entry_id);
2707 self->priv->dropdown_entries = g_slist_append (self->priv->dropdown_entries, entry);
2708 g_hash_table_insert (self->priv->id2entry_hash, (gpointer)entry->name_hint, entry);
2709@@ -423,6 +436,21 @@
2710 }
2711
2712 static void
2713+ensure_entry_menu_is_closed (PanelService *self,
2714+ const gchar *panel_id,
2715+ IndicatorObjectEntry *entry)
2716+{
2717+ PanelServicePrivate *priv = self->priv;
2718+
2719+ /* If the entry has been removed let's make sure that its menu is closed */
2720+ if (GTK_IS_MENU (priv->last_menu) && priv->last_menu == entry->menu)
2721+ {
2722+ if (!priv->last_panel || !panel_id || g_strcmp0 (priv->last_panel, panel_id) == 0)
2723+ gtk_menu_popdown (entry->menu);
2724+ }
2725+}
2726+
2727+static void
2728 reinject_key_event_to_root_window (XIDeviceEvent *ev)
2729 {
2730 XKeyEvent kev;
2731@@ -542,9 +570,7 @@
2732 {
2733 /* Middle clicks over an appmenu entry are considered just like
2734 * all other clicks */
2735- IndicatorObject *obj = get_entry_parent_indicator (entry);
2736-
2737- if (g_strcmp0 (g_object_get_data (G_OBJECT (obj), "id"), "libappmenu.so") == 0)
2738+ if (get_entry_parent_indicator (entry) == priv->appmenu_indicator)
2739 {
2740 event_is_a_click = TRUE;
2741 }
2742@@ -609,7 +635,7 @@
2743 initial_resync (PanelService *self)
2744 {
2745 g_signal_emit (self, _service_signals[RE_SYNC], 0, "");
2746- return FALSE;
2747+ return G_SOURCE_REMOVE;
2748 }
2749
2750 static gboolean
2751@@ -618,7 +644,7 @@
2752 if (!lockscreen_mode)
2753 emit_upstart_event ("indicator-services-start");
2754
2755- return FALSE;
2756+ return G_SOURCE_REMOVE;
2757 }
2758
2759 static void
2760@@ -782,10 +808,10 @@
2761 if (self->priv->indicators == NULL)
2762 {
2763 g_signal_emit (self, _service_signals[INDICATORS_CLEARED], 0);
2764- return FALSE;
2765+ return G_SOURCE_REMOVE;
2766 }
2767
2768- return TRUE;
2769+ return G_SOURCE_CONTINUE;
2770 }
2771
2772 static void
2773@@ -863,6 +889,9 @@
2774 g_object_ref_sink (G_OBJECT (indicator));
2775 }
2776
2777+ if (self->priv->appmenu_indicator == indicator)
2778+ self->priv->appmenu_indicator = NULL;
2779+
2780 g_object_unref (G_OBJECT (indicator));
2781 }
2782
2783@@ -1077,7 +1106,7 @@
2784 g_signal_emit (self, _service_signals[RE_SYNC],
2785 0, g_object_get_data (G_OBJECT (object), "id"));
2786
2787- return FALSE;
2788+ return G_SOURCE_REMOVE;
2789 }
2790
2791 static void
2792@@ -1136,6 +1165,7 @@
2793 g_return_if_fail (PANEL_IS_SERVICE (self));
2794 g_return_if_fail (entry != NULL);
2795
2796+ self->priv->removed_entries = g_slist_remove (self->priv->removed_entries, entry);
2797 gchar *entry_id = get_indicator_entry_id_by_entry (entry);
2798 g_hash_table_insert (self->priv->id2entry_hash, entry_id, entry);
2799
2800@@ -1175,6 +1205,42 @@
2801 notify_object (object);
2802 }
2803
2804+static gboolean
2805+on_removed_idle (PanelService *self)
2806+{
2807+ GHashTableIter iter;
2808+ GHashTable *entry2geometry_hash;
2809+ IndicatorObjectEntry *entry;
2810+ gpointer value;
2811+ GSList *l;
2812+
2813+ for (l = self->priv->removed_entries; l; l = l->next)
2814+ {
2815+ entry = l->data;
2816+ ensure_entry_menu_is_closed (self, NULL, entry);
2817+
2818+ g_hash_table_iter_init (&iter, self->priv->panel2entries_hash);
2819+ while (g_hash_table_iter_next (&iter, NULL, &value))
2820+ {
2821+ if ((entry2geometry_hash = value))
2822+ {
2823+ g_hash_table_remove (entry2geometry_hash, entry);
2824+
2825+ if (g_hash_table_size (entry2geometry_hash) == 0)
2826+ {
2827+ g_hash_table_iter_remove (&iter);
2828+ }
2829+ }
2830+ }
2831+
2832+ }
2833+
2834+ g_slist_free (self->priv->removed_entries);
2835+ self->priv->removed_entries = NULL;
2836+
2837+ return G_SOURCE_REMOVE;
2838+}
2839+
2840 static void
2841 on_entry_removed (IndicatorObject *object,
2842 IndicatorObjectEntry *entry,
2843@@ -1183,11 +1249,6 @@
2844 g_return_if_fail (PANEL_IS_SERVICE (self));
2845 g_return_if_fail (entry != NULL);
2846
2847- /* Don't remove here the value from panel2entries_hash, this should be
2848- * done during the geometries sync, to avoid false positive.
2849- * FIXME this in libappmenu.so to avoid to send an "entry-removed" signal
2850- * when switching the focus from a window to one of its dialog children */
2851-
2852 gchar *entry_id = get_indicator_entry_id_by_entry (entry);
2853 g_hash_table_remove (self->priv->id2entry_hash, entry_id);
2854 g_free (entry_id);
2855@@ -1202,6 +1263,13 @@
2856 g_signal_handlers_disconnect_by_data (entry->image, object);
2857 }
2858
2859+ self->priv->removed_entries = g_slist_append (self->priv->removed_entries, entry);
2860+
2861+ if (self->priv->remove_idle)
2862+ g_source_remove (self->priv->remove_idle);
2863+
2864+ self->priv->remove_idle = g_idle_add ((GSourceFunc) on_removed_idle, self);
2865+
2866 notify_object (object);
2867 }
2868
2869@@ -1259,6 +1327,7 @@
2870 "unity",
2871 "unity-3d",
2872 "unity-panel-service",
2873+ "unity-all-menus",
2874 NULL
2875 };
2876
2877@@ -1278,6 +1347,9 @@
2878
2879 priv->indicators = g_slist_append (priv->indicators, object);
2880
2881+ if (!priv->appmenu_indicator && g_strcmp0 (name, APPMENU_INDICATOR_NAME) == 0)
2882+ priv->appmenu_indicator = object;
2883+
2884 g_object_set_data_full (G_OBJECT (object), "id", g_strdup (name), g_free);
2885
2886 g_signal_connect (object, INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED,
2887@@ -1539,10 +1611,11 @@
2888 guint32 image_type = 0;
2889 gchar *image_data = gtk_image_to_data (entry->image, &image_type);
2890
2891- g_variant_builder_add (b, "(ssssbbusbbi)",
2892+ g_variant_builder_add (b, ENTRY_SIGNATURE,
2893 indicator_id,
2894 id,
2895 entry->name_hint ? entry->name_hint : "",
2896+ entry->parent_window,
2897 is_label ? gtk_label_get_label (entry->label) : "",
2898 is_label ? gtk_widget_get_sensitive (GTK_WIDGET (entry->label)) : FALSE,
2899 is_label ? gtk_widget_get_visible (GTK_WIDGET (entry->label)) : FALSE,
2900@@ -1559,14 +1632,15 @@
2901 indicator_entry_null_to_variant (const gchar *indicator_id,
2902 GVariantBuilder *b)
2903 {
2904- g_variant_builder_add (b, "(ssssbbusbbi)",
2905+ g_variant_builder_add (b, ENTRY_SIGNATURE,
2906 indicator_id,
2907 "",
2908 "",
2909+ 0,
2910 "",
2911 FALSE,
2912 FALSE,
2913- (guint32) 0,
2914+ 0,
2915 "",
2916 FALSE,
2917 FALSE,
2918@@ -1574,15 +1648,20 @@
2919 }
2920
2921 static void
2922-indicator_object_full_to_variant (IndicatorObject *object, const gchar *indicator_id, GVariantBuilder *b)
2923+indicator_object_full_to_variant (PanelService *self, IndicatorObject *object,
2924+ const gchar *indicator_id, GVariantBuilder *b)
2925 {
2926 GList *entries, *e;
2927+ GHashTable *index_hash = NULL;
2928 gint parent_prio = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (object), "priority"));
2929 entries = indicator_object_get_entries (object);
2930- gint index = 0;
2931+ guint index = 0;
2932
2933 if (entries)
2934 {
2935+ if (object == self->priv->appmenu_indicator)
2936+ index_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
2937+
2938 for (e = entries; e; e = e->next)
2939 {
2940 gint prio = -1;
2941@@ -1596,14 +1675,29 @@
2942
2943 if (prio < 0)
2944 {
2945+ if (index_hash)
2946+ {
2947+ index = GPOINTER_TO_UINT (g_hash_table_lookup (index_hash,
2948+ GUINT_TO_POINTER (entry->parent_window)));
2949+ }
2950+
2951 prio = parent_prio + index;
2952 index++;
2953+
2954+ if (index_hash)
2955+ {
2956+ g_hash_table_insert (index_hash, GUINT_TO_POINTER (entry->parent_window),
2957+ GUINT_TO_POINTER (index));
2958+ }
2959 }
2960
2961 indicator_entry_to_variant (entry, id, indicator_id, b, prio);
2962 g_free (id);
2963 }
2964
2965+ if (index_hash)
2966+ g_hash_table_destroy (index_hash);
2967+
2968 g_list_free (entries);
2969 }
2970 else
2971@@ -1614,15 +1708,15 @@
2972 }
2973
2974 static void
2975-indicator_object_to_variant (IndicatorObject *object, const gchar *indicator_id, GVariantBuilder *b)
2976+indicator_object_to_variant (PanelService *self, IndicatorObject *object,
2977+ const gchar *indicator_id, GVariantBuilder *b)
2978 {
2979 if (!GPOINTER_TO_INT (g_object_get_data (G_OBJECT (object), "remove")))
2980 {
2981- indicator_object_full_to_variant (object, indicator_id, b);
2982+ indicator_object_full_to_variant (self, object, indicator_id, b);
2983 }
2984 else
2985 {
2986- PanelService *self = panel_service_get_default ();
2987 indicator_entry_null_to_variant (indicator_id, b);
2988 panel_service_actually_remove_indicator (self, object);
2989 }
2990@@ -1650,7 +1744,7 @@
2991 rect.height *= scale;
2992 }
2993
2994- if (is_point_in_rect (x, y, &rect))
2995+ if (rect_contains_point (&rect, x, y))
2996 {
2997 return i;
2998 }
2999@@ -1722,8 +1816,8 @@
3000 GSList *i;
3001 gint position;
3002
3003- g_variant_builder_init (&b, G_VARIANT_TYPE ("(a(ssssbbusbbi))"));
3004- g_variant_builder_open (&b, G_VARIANT_TYPE ("a(ssssbbusbbi)"));
3005+ g_variant_builder_init (&b, G_VARIANT_TYPE ("("ENTRY_ARRAY_SIGNATURE")"));
3006+ g_variant_builder_open (&b, G_VARIANT_TYPE (ENTRY_ARRAY_SIGNATURE));
3007
3008 for (i = self->priv->indicators; i;)
3009 {
3010@@ -1733,7 +1827,7 @@
3011
3012 const gchar *indicator_id = g_object_get_data (G_OBJECT (indicator), "id");
3013 position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (indicator), "position"));
3014- indicator_object_to_variant (indicator, indicator_id, &b);
3015+ indicator_object_to_variant (self, indicator, indicator_id, &b);
3016
3017 /* Set the sync back to neutral */
3018 self->priv->timeouts[position] = SYNC_NEUTRAL;
3019@@ -1749,8 +1843,8 @@
3020 GVariantBuilder b;
3021 GSList *i;
3022
3023- g_variant_builder_init (&b, G_VARIANT_TYPE ("(a(ssssbbusbbi))"));
3024- g_variant_builder_open (&b, G_VARIANT_TYPE ("a(ssssbbusbbi)"));
3025+ g_variant_builder_init (&b, G_VARIANT_TYPE ("("ENTRY_ARRAY_SIGNATURE")"));
3026+ g_variant_builder_open (&b, G_VARIANT_TYPE (ENTRY_ARRAY_SIGNATURE));
3027
3028 for (i = self->priv->indicators; i; i = i->next)
3029 {
3030@@ -1758,7 +1852,7 @@
3031 g_object_get_data (G_OBJECT (i->data), "id")) == 0)
3032 {
3033 gint position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (i->data), "position"));
3034- indicator_object_to_variant (i->data, indicator_id, &b);
3035+ indicator_object_to_variant (self, i->data, indicator_id, &b);
3036
3037 /* Set the sync back to neutral */
3038 self->priv->timeouts[position] = SYNC_NEUTRAL;
3039@@ -1782,6 +1876,7 @@
3040 {
3041 IndicatorObject *object;
3042 IndicatorObjectEntry *entry;
3043+ GHashTable *entry2geometry_hash;
3044 gboolean valid_entry = TRUE;
3045 PanelServicePrivate *priv = self->priv;
3046
3047@@ -1802,24 +1897,18 @@
3048
3049 if (entry)
3050 {
3051- GHashTable *entry2geometry_hash = g_hash_table_lookup (priv->panel2entries_hash, panel_id);
3052+ entry2geometry_hash = g_hash_table_lookup (priv->panel2entries_hash, panel_id);
3053
3054 if (width < 0 || height < 0 || !valid_entry)
3055 {
3056- /* If the entry has been removed let's make sure that its menu is closed */
3057- if (valid_entry && GTK_IS_MENU (priv->last_menu) && priv->last_menu == entry->menu)
3058- {
3059- if (!priv->last_panel || g_strcmp0 (priv->last_panel, panel_id) == 0)
3060- gtk_menu_popdown (entry->menu);
3061- }
3062+ if (valid_entry)
3063+ ensure_entry_menu_is_closed (self, panel_id, entry);
3064
3065 if (entry2geometry_hash)
3066 {
3067- if (g_hash_table_size (entry2geometry_hash) > 1)
3068- {
3069- g_hash_table_remove (entry2geometry_hash, entry);
3070- }
3071- else
3072+ g_hash_table_remove (entry2geometry_hash, entry);
3073+
3074+ if (g_hash_table_size (entry2geometry_hash) == 0)
3075 {
3076 g_hash_table_remove (priv->panel2entries_hash, panel_id);
3077 }
3078@@ -2188,7 +2277,7 @@
3079 priv->last_x = x;
3080 priv->last_y = y;
3081 priv->last_menu_button = button;
3082- priv->last_panel = get_panel_at (self, x, y);
3083+ priv->last_panel = get_panel_for_parent_at (self, xid, x, y);
3084
3085 g_signal_connect (priv->last_menu, "hide", G_CALLBACK (on_active_menu_hidden), self);
3086 g_signal_connect_after (priv->last_menu, "move-current",
3087@@ -2394,10 +2483,9 @@
3088 GList *entries;
3089
3090 g_return_if_fail (PANEL_IS_SERVICE (self));
3091-
3092- object = panel_service_get_indicator (self, "libappmenu.so");
3093- g_return_if_fail (INDICATOR_IS_OBJECT (object));
3094-
3095+ g_return_if_fail (INDICATOR_IS_OBJECT (self->priv->appmenu_indicator));
3096+
3097+ object = self->priv->appmenu_indicator;
3098 entries = indicator_object_get_entries (object);
3099
3100 if (entries)
3101
3102=== modified file 'services/panel-service.h'
3103--- services/panel-service.h 2014-12-09 15:41:53 +0000
3104+++ services/panel-service.h 2015-07-15 14:19:40 +0000
3105@@ -56,14 +56,6 @@
3106 struct _PanelServiceClass
3107 {
3108 GObjectClass parent_class;
3109-
3110- /*< private >*/
3111- void (*_view_padding1) (void);
3112- void (*_view_padding2) (void);
3113- void (*_view_padding3) (void);
3114- void (*_view_padding4) (void);
3115- void (*_view_padding5) (void);
3116- void (*_view_padding6) (void);
3117 };
3118
3119 GType panel_service_get_type (void) G_GNUC_CONST;
3120
3121=== modified file 'shortcuts/ShortcutModel.h'
3122--- shortcuts/ShortcutModel.h 2013-01-19 00:25:07 +0000
3123+++ shortcuts/ShortcutModel.h 2015-07-15 14:19:40 +0000
3124@@ -21,7 +21,7 @@
3125 #define UNITYSHELL_SHORTCUS_MODEL_H
3126
3127 #include <boost/noncopyable.hpp>
3128-#include <map>
3129+#include <unordered_map>
3130 #include <memory>
3131 #include <list>
3132 #include <string>
3133@@ -43,7 +43,7 @@
3134
3135 nux::Property<int> categories_per_column;
3136 std::vector<std::string> const& categories() const { return categories_; }
3137- std::map<std::string, std::list<AbstractHint::Ptr>> const& hints() const { return hints_; }
3138+ std::unordered_map<std::string, std::list<AbstractHint::Ptr>> const& hints() const { return hints_; }
3139
3140 void Fill();
3141
3142@@ -51,7 +51,7 @@
3143 void AddHint(AbstractHint::Ptr const& hint);
3144
3145 std::vector<std::string> categories_;
3146- std::map<std::string, std::list<AbstractHint::Ptr>> hints_;
3147+ std::unordered_map<std::string, std::list<AbstractHint::Ptr>> hints_;
3148 };
3149
3150 }
3151
3152=== modified file 'tests/autopilot/unity/emulators/panel.py'
3153--- tests/autopilot/unity/emulators/panel.py 2013-05-10 05:16:07 +0000
3154+++ tests/autopilot/unity/emulators/panel.py 2015-07-15 14:19:40 +0000
3155@@ -159,6 +159,10 @@
3156 return self.menus.panel_title
3157
3158 @property
3159+ def focused(self):
3160+ return self.menus.focused
3161+
3162+ @property
3163 def desktop_is_active(self):
3164 return self.menus.desktop_active
3165
3166
3167=== modified file 'tests/autopilot/unity/tests/__init__.py'
3168--- tests/autopilot/unity/tests/__init__.py 2014-02-12 20:43:54 +0000
3169+++ tests/autopilot/unity/tests/__init__.py 2015-07-15 14:19:40 +0000
3170@@ -48,7 +48,7 @@
3171 from Xlib import display
3172 from Xlib import Xutil
3173
3174-from gi.repository import Gio
3175+from gi.repository import GLib, Gio
3176
3177 log = getLogger(__name__)
3178
3179@@ -256,20 +256,19 @@
3180 atom_type = display.Display().intern_atom('CARDINAL')
3181 return bamf_window.x_win.get_property(atom, atom_type, 0, 1024).value[0]
3182
3183- def call_gsettings_cmd(self, command, schema, *args):
3184+ def call_gsettings_cmd(self, command, schema, key, value=None):
3185 """Set a desktop wide gsettings option
3186-
3187- Using the gsettings command because there is a bug with importing
3188- from gobject introspection and pygtk2 simultaneously, and the Xlib
3189- keyboard layout bits are very unwieldy. This seems like the best
3190- solution, even a little bit brutish.
3191 """
3192- cmd = ['gsettings', command, schema] + list(args)
3193- # strip to remove the trailing \n.
3194- ret = check_output(cmd).strip()
3195- time.sleep(5)
3196- reset_display()
3197- return ret
3198+ settings = Gio.Settings.new(schema)
3199+
3200+ if command == "get":
3201+ return settings.get_value(key).print_(type_annotate=False)
3202+ elif command == "set":
3203+ settings.set_value(key, GLib.Variant.parse(type=None, text=value))
3204+ settings.apply()
3205+ reset_display()
3206+ elif command == "reset":
3207+ settings.reset(key)
3208
3209 def set_unity_option(self, option_name, option_value):
3210 """Set an option in the unity compiz plugin options.
3211
3212=== modified file 'tests/autopilot/unity/tests/test_dash.py'
3213--- tests/autopilot/unity/tests/test_dash.py 2014-02-28 19:53:07 +0000
3214+++ tests/autopilot/unity/tests/test_dash.py 2015-07-15 14:19:40 +0000
3215@@ -164,7 +164,7 @@
3216
3217 self.assertProperty(char_win, is_active=True)
3218
3219- def test_dash_does_not_open_when_fullscreen_window(self):
3220+ def test_dash_opens_when_fullscreen_window(self):
3221 """ The Dash must not open if a window is fullscreen. """
3222 gedit = self.process_manager.start_app("Text Editor")
3223 self.keyboard.press_and_release('F11')
3224@@ -175,7 +175,7 @@
3225 self.keybinding("dash/reveal")
3226 self.addCleanup(self.unity.dash.ensure_hidden)
3227
3228- self.assertThat(self.unity.dash.visible, Eventually(Equals(False)))
3229+ self.assertThat(self.unity.dash.visible, Eventually(Equals(True)))
3230
3231
3232 class DashRevealWithSpreadTests(DashTestCase):
3233
3234=== modified file 'tests/autopilot/unity/tests/test_hud.py'
3235--- tests/autopilot/unity/tests/test_hud.py 2014-02-28 19:53:07 +0000
3236+++ tests/autopilot/unity/tests/test_hud.py 2015-07-15 14:19:40 +0000
3237@@ -512,7 +512,7 @@
3238 self.keyboard.type("e")
3239 self.assertThat(self.unity.hud.view.selected_button, Eventually(Equals(1)))
3240
3241- def test_hud_does_not_open_when_fullscreen_window(self):
3242+ def test_hud_opens_when_fullscreen_window(self):
3243 """ The Hud must not open if a window is fullscreen. """
3244 gedit = self.process_manager.start_app("Text Editor")
3245 self.keyboard.press_and_release('F11')
3246@@ -523,7 +523,7 @@
3247 self.keybinding("hud/reveal")
3248 self.addCleanup(self.unity.hud.ensure_hidden)
3249
3250- self.assertThat(self.unity.hud.visible, Eventually(Equals(False)))
3251+ self.assertThat(self.unity.hud.visible, Eventually(Equals(True)))
3252
3253
3254 class HudLauncherInteractionsTests(HudTestsBase):
3255
3256=== modified file 'tests/autopilot/unity/tests/test_panel.py'
3257--- tests/autopilot/unity/tests/test_panel.py 2014-03-04 15:30:06 +0000
3258+++ tests/autopilot/unity/tests/test_panel.py 2015-07-15 14:19:40 +0000
3259@@ -12,6 +12,7 @@
3260 #from autopilot.emulators.bamf import BamfWindow
3261 from autopilot.process import Window
3262 from autopilot.matchers import Eventually
3263+from autopilot.testcase import multiply_scenarios
3264 import logging
3265 import os
3266 from testtools.matchers import Equals, GreaterThan, NotEquals
3267@@ -25,6 +26,13 @@
3268
3269 logger = logging.getLogger(__name__)
3270
3271+def _make_scenarios():
3272+ return multiply_scenarios(_make_monitor_scenarios(),
3273+ _make_menu_modes_scenarios())
3274+
3275+def _make_menu_modes_scenarios():
3276+ return [ ('Locally Integrated Menus', {'lim': True}),
3277+ ('Global Menus', {'lim': False}) ]
3278
3279 def _make_monitor_scenarios():
3280 num_monitors = Display.create().get_num_screens()
3281@@ -38,17 +46,41 @@
3282
3283 return scenarios
3284
3285-
3286 class PanelTestsBase(UnityTestCase):
3287
3288 panel_monitor = 0
3289+ lim = False
3290
3291 def setUp(self):
3292 super(PanelTestsBase, self).setUp()
3293 self.panel = self.unity.panels.get_panel_for_monitor(self.panel_monitor)
3294+
3295+ old_lim = self.call_gsettings_cmd('get', 'com.canonical.Unity', 'integrated-menus')
3296+ self.call_gsettings_cmd('set', 'com.canonical.Unity', 'integrated-menus', str(self.lim).lower())
3297+ self.addCleanup(self.call_gsettings_cmd, 'set', 'com.canonical.Unity', 'integrated-menus', old_lim)
3298+
3299+ old_showmenus = self.call_gsettings_cmd('get', 'com.canonical.Unity', 'always-show-menus')
3300+ self.call_gsettings_cmd('set', 'com.canonical.Unity', 'always-show-menus', 'false')
3301+ self.addCleanup(self.call_gsettings_cmd, 'set', 'com.canonical.Unity', 'always-show-menus', old_showmenus)
3302+
3303 self.panel.move_mouse_below_the_panel()
3304 self.addCleanup(self.panel.move_mouse_below_the_panel)
3305
3306+ self.assertThat(self.panel.menus.integrated_menus, Eventually(Equals(self.lim)))
3307+ if not self.lim:
3308+ self.assertThat(self.panel.focused, Eventually(Equals(True)))
3309+
3310+ def ensure_window_state(self, win, maximized=False):
3311+ if maximized and not win.is_maximized:
3312+ self.keybinding("window/maximize")
3313+ self.addCleanup(self.keybinding, "window/restore")
3314+ elif not maximized and win.is_maximized:
3315+ self.keybinding("window/restore")
3316+ self.addCleanup(self.keybinding, "window/maximize")
3317+
3318+ sleep(.25)
3319+ self.assertProperty(win, is_maximized=maximized)
3320+
3321 def open_new_application_window(self, app_name, maximized=False, move_to_monitor=True):
3322 """Opens a new instance of the requested application, ensuring that only
3323 one window is opened.
3324@@ -68,17 +100,8 @@
3325 if move_to_monitor:
3326 self.move_window_to_panel_monitor(app_win)
3327
3328- if maximized and not app_win.is_maximized:
3329- self.keybinding("window/maximize")
3330- self.addCleanup(self.keybinding, "window/restore")
3331- elif not maximized and app_win.is_maximized:
3332- self.keybinding("window/restore")
3333- self.addCleanup(self.keybinding, "window/maximize")
3334-
3335 app_win.set_focus()
3336- sleep(.25)
3337-
3338- self.assertThat(app_win.is_maximized, Equals(maximized))
3339+ self.ensure_window_state(app_win, maximized)
3340
3341 return app_win
3342
3343@@ -137,9 +160,10 @@
3344
3345 def sleep_menu_settle_period(self):
3346 """Sleep long enough for the menus to fade in and fade out again."""
3347- sleep(self.panel.menus.fadein_duration / 1000.0)
3348- sleep(self.panel.menus.discovery_duration)
3349- sleep(self.panel.menus.fadeout_duration / 1000.0)
3350+ if not self.lim:
3351+ sleep(self.panel.menus.fadein_duration / 1000.0)
3352+ sleep(self.panel.menus.discovery_duration)
3353+ sleep(self.panel.menus.fadeout_duration / 1000.0)
3354
3355 # Unable to exit SDM without any active apps, need a placeholder.
3356 # See bug LP:1079460
3357@@ -152,7 +176,7 @@
3358
3359 class PanelTitleTests(PanelTestsBase):
3360
3361- scenarios = _make_monitor_scenarios()
3362+ scenarios = _make_scenarios()
3363
3364 def setUp(self):
3365 super(PanelTitleTests, self).setUp()
3366@@ -174,13 +198,15 @@
3367 """Panel must display application name for a non-maximised application."""
3368 calc_win = self.open_new_application_window("Calculator", maximized=False)
3369
3370- self.assertThat(self.panel.title, Eventually(Equals(calc_win.application.name)))
3371+ expected = calc_win.application.name if not self.lim else ''
3372+ self.assertThat(self.panel.title, Eventually(Equals(expected)))
3373
3374 def test_panel_title_with_maximized_application(self):
3375 """Panel must display application name for a maximised application."""
3376 text_win = self.open_new_application_window("Text Editor", maximized=True)
3377
3378 self.assertThat(self.panel.title, Eventually(Equals(text_win.title)))
3379+ self.assertThat(self.panel.focused, Eventually(Equals(True)))
3380
3381 def test_panel_title_with_maximized_window_restored_child(self):
3382 """Tests the title shown in the panel when opening the restored child of
3383@@ -194,14 +220,18 @@
3384
3385 self.assertThat(lambda: len(text_win.application.get_windows()),
3386 Eventually(Equals(2)))
3387- self.assertThat(self.panel.title, Equals(text_win.application.name))
3388+ expected = text_win.application.name if not self.lim else text_win.title
3389+ self.assertThat(self.panel.title, Equals(expected))
3390+ self.assertThat(self.panel.focused, Eventually(Equals(not self.lim)))
3391
3392 def test_panel_shows_app_title_with_maximised_app(self):
3393 """Tests app titles are shown in the panel with a non-focused maximized application."""
3394- self.open_new_application_window("Text Editor", maximized=True)
3395+ text_win = self.open_new_application_window("Text Editor", maximized=True)
3396 calc_win = self.open_new_application_window("Calculator", maximized=False)
3397
3398- self.assertThat(self.panel.title, Eventually(Equals(calc_win.application.name)))
3399+ expected = calc_win.application.name if not self.lim else text_win.title
3400+ self.assertThat(self.panel.title, Eventually(Equals(expected)))
3401+ self.assertThat(self.panel.focused, Eventually(Equals(not self.lim)))
3402
3403 def test_panel_title_updates_when_switching_to_maximized_app(self):
3404 """Switching to a maximised app from a restored one must update the panel title."""
3405@@ -242,13 +272,14 @@
3406
3407 class PanelWindowButtonsTests(PanelTestsBase):
3408
3409- scenarios = _make_monitor_scenarios()
3410+ scenarios = _make_scenarios()
3411
3412 def setUp(self):
3413 super(PanelWindowButtonsTests, self).setUp()
3414 # Locked Launchers on all monitors
3415 self.set_unity_option('num_launchers', 0)
3416 self.set_unity_option('launcher_hide_mode', 0)
3417+ self.always_visible = self.lim
3418
3419 def test_window_buttons_dont_show_on_empty_desktop(self):
3420 """Tests that the window buttons are not shown on clean desktop."""
3421@@ -279,13 +310,14 @@
3422
3423 self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(False)))
3424
3425- def test_window_buttons_dont_show_for_maximized_window_on_mouse_out(self):
3426- """Window buttons must not show for a maximized window when the mouse is
3427- outside the panel.
3428+ def test_window_buttons_show_for_maximized_window_on_mouse_out(self):
3429+ """Window buttons might show for a maximized window when the mouse is
3430+ outside the panel, depending on LIM setting.
3431 """
3432 self.open_new_application_window("Text Editor", maximized=True)
3433
3434- self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(False)))
3435+ self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(self.always_visible)))
3436+ self.assertThat(self.panel.window_buttons.focused, Eventually(Equals(True)))
3437
3438 def test_window_buttons_show_for_maximized_window_on_mouse_in(self):
3439 """Window buttons must show when a maximized window is focused and the
3440@@ -296,8 +328,30 @@
3441 self.panel.move_mouse_over_window_buttons()
3442
3443 self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(True)))
3444+ self.assertThat(self.panel.window_buttons.focused, Eventually(Equals(True)))
3445 self.assertWinButtonsInOverlayMode(False)
3446
3447+ def test_window_buttons_show_for_maximized_unfocused_window_with_mouse_in_panel(self):
3448+ """Window buttons might show for an unfocused maximized window when the
3449+ mouse is over the panel, depending on LIM setting.
3450+ """
3451+ self.open_new_application_window("Text Editor", maximized=True)
3452+ self.open_new_application_window("Calculator")
3453+ self.panel.move_mouse_over_window_buttons()
3454+
3455+ self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(self.always_visible)))
3456+ self.assertThat(self.panel.window_buttons.focused, Eventually(Equals(not self.lim)))
3457+
3458+ def test_window_buttons_show_for_maximized_unfocused_window_on_mouse_out(self):
3459+ """Window buttons might show for an unfocused maximized window when the
3460+ mouse is outside the panel, depending on LIM setting.
3461+ """
3462+ self.open_new_application_window("Text Editor", maximized=True)
3463+ self.open_new_application_window("Calculator")
3464+
3465+ self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(self.always_visible)))
3466+ self.assertThat(self.panel.window_buttons.focused, Eventually(Equals(not self.lim)))
3467+
3468 def test_window_buttons_show_with_dash(self):
3469 """Window buttons must be shown when the dash is open."""
3470 self.unity.dash.ensure_visible()
3471@@ -340,122 +394,6 @@
3472 else:
3473 self.assertThat(self.unity.hud.view.overlay_window_buttons_shown[monitor], Equals(False))
3474
3475- def test_window_buttons_update_visual_state(self):
3476- """Window button must update its state in response to mouse events."""
3477- self.open_new_application_window("Text Editor", maximized=True, move_to_monitor=True)
3478- self.panel.move_mouse_over_window_buttons()
3479- button = self.panel.window_buttons.unmaximize
3480-
3481- self.assertThat(button.visual_state, Eventually(Equals("normal")))
3482-
3483- button.mouse_move_to()
3484- self.assertThat(button.visual_state, Eventually(Equals("prelight")))
3485-
3486- self.mouse.press()
3487- self.addCleanup(self.mouse.release)
3488- self.assertThat(button.visual_state, Eventually(Equals("pressed")))
3489-
3490- def test_window_buttons_cancel(self):
3491- """Window buttons must ignore clicks when the mouse released outside
3492- their area.
3493- """
3494- win = self.open_new_application_window("Text Editor", maximized=True, move_to_monitor=True)
3495- self.panel.move_mouse_over_window_buttons()
3496-
3497- button = self.panel.window_buttons.unmaximize
3498- button.mouse_move_to()
3499- self.mouse.press()
3500- self.assertThat(button.visual_state, Eventually(Equals("pressed")))
3501- self.panel.move_mouse_below_the_panel()
3502- self.mouse.release()
3503-
3504- self.assertThat(win.is_maximized, Equals(True))
3505-
3506- def test_window_buttons_close_button_works_for_window(self):
3507- """Close window button must actually closes a window."""
3508- text_win = self.open_new_application_window("Text Editor",
3509- maximized=True,
3510- move_to_monitor=True)
3511- win_xid = text_win.x_id
3512-
3513- self.panel.window_buttons.close.mouse_click()
3514- self.assertNoWindowOpenWithXid(win_xid)
3515-
3516- def test_window_buttons_close_follows_fitts_law(self):
3517- """Tests that the 'Close' button is activated when clicking at 0,0.
3518-
3519- See bug #839690
3520- """
3521- text_win = self.open_new_application_window("Text Editor",
3522- maximized=True,
3523- move_to_monitor=True)
3524- win_xid = text_win.x_id
3525-
3526- self.panel.move_mouse_over_window_buttons()
3527- screen_x, screen_y = self.display.get_screen_geometry(self.panel_monitor)[:2]
3528- self.mouse.move(screen_x, screen_y)
3529- self.mouse.click()
3530-
3531- self.assertNoWindowOpenWithXid(win_xid)
3532-
3533- def test_window_buttons_minimize_button_works_for_window(self):
3534- """Tests that the window button 'Minimize' actually minimizes a window."""
3535- text_win = self.open_new_application_window("Text Editor",
3536- maximized=True,
3537- move_to_monitor=True)
3538-
3539- self.panel.window_buttons.minimize.mouse_click()
3540-
3541- self.assertProperty(text_win, is_hidden=True)
3542-
3543- def test_window_buttons_minimize_follows_fitts_law(self):
3544- """Tests that the 'Minimize' button is conform to Fitts's Law.
3545-
3546- See bug #839690
3547- """
3548- text_win = self.open_new_application_window("Text Editor",
3549- maximized=True,
3550- move_to_monitor=True)
3551-
3552- self.panel.move_mouse_over_window_buttons()
3553- button = self.panel.window_buttons.minimize
3554- target_x = button.x + button.width / 2
3555- target_y = self.display.get_screen_geometry(self.panel_monitor)[1]
3556- self.mouse.move(target_x, target_y)
3557- self.mouse.click()
3558-
3559- self.assertProperty(text_win, is_hidden=True)
3560-
3561- def test_window_buttons_unmaximize_button_works_for_window(self):
3562- """Tests that the window button 'Unmaximize' actually unmaximizes a window."""
3563- text_win = self.open_new_application_window("Text Editor",
3564- maximized=True,
3565- move_to_monitor=True)
3566-
3567- self.panel.window_buttons.unmaximize.mouse_click()
3568-
3569- self.assertProperties(text_win, is_maximized=False, is_focused=True)
3570- self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(False)))
3571-
3572- def test_window_buttons_unmaximize_follows_fitts_law(self):
3573- """Tests that the 'Unmaximize' button is conform to Fitts's Law.
3574-
3575- See bug #839690
3576- """
3577- text_win = self.open_new_application_window("Text Editor",
3578- maximized=True,
3579- move_to_monitor=True)
3580-
3581- button = self.panel.window_buttons.unmaximize
3582- button.mouse_move_to()
3583- target_x = button.x + button.width / 2
3584- target_y = self.display.get_screen_geometry(self.panel_monitor)[1]
3585- self.mouse.move(target_x, target_y)
3586- sleep(1)
3587- self.mouse.click()
3588-
3589- self.assertProperty(text_win, is_maximized=False)
3590-
3591 def test_window_buttons_close_button_works_for_hud(self):
3592 """Tests that the window 'Close' actually closes the HUD."""
3593 self.unity.hud.ensure_visible()
3594@@ -604,9 +542,7 @@
3595
3596 def test_minimize_button_disabled_for_non_minimizable_windows(self):
3597 """Minimize button must be disabled for windows that don't support minimization."""
3598- text_win = self.open_new_application_window("Text Editor",
3599- maximized=False,
3600- move_to_monitor=True)
3601+ text_win = self.open_new_application_window("Text Editor", maximized=True)
3602
3603 self.keyboard.press_and_release("Ctrl+S")
3604 self.addCleanup(self.keyboard.press_and_release, "Escape")
3605@@ -626,28 +562,24 @@
3606 """Window buttons must be shown when mouse is over panel area with an
3607 indicator open.
3608 """
3609- self.open_new_application_window("Text Editor",
3610- maximized=True,
3611- move_to_monitor=True)
3612+ self.open_new_application_window("Text Editor", maximized=True)
3613
3614 indicator = self.panel.indicators.get_indicator_by_name_hint("indicator-session")
3615 self.mouse_open_indicator(indicator)
3616- self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(False)))
3617+ self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(self.always_visible)))
3618
3619 self.panel.move_mouse_below_the_panel()
3620- self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(False)))
3621+ self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(self.always_visible)))
3622
3623 self.panel.move_mouse_over_grab_area()
3624 self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(True)))
3625
3626 def test_window_buttons_show_when_holding_show_menu_key(self):
3627 """Window buttons must show when we press the show-menu keybinding."""
3628- self.open_new_application_window("Text Editor",
3629- maximized=True,
3630- move_to_monitor=True)
3631+ self.open_new_application_window("Text Editor", maximized=True)
3632
3633 self.sleep_menu_settle_period()
3634- self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(False)))
3635+ self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(self.always_visible)))
3636
3637 self.keybinding_hold("panel/show_menus")
3638 self.addCleanup(self.keybinding_release, "panel/show_menus")
3639@@ -657,7 +589,7 @@
3640 # Sleep a bit to avoid a race with the Hud showing
3641 sleep(0.5)
3642 self.keybinding_release("panel/show_menus")
3643- self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(False)))
3644+ self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(self.always_visible)))
3645
3646 def test_window_buttons_cant_accept_keynav_focus(self):
3647 """On a mouse down event over the window buttons
3648@@ -673,57 +605,149 @@
3649
3650 self.assertThat(self.unity.hud.search_string, Eventually(Equals("HelloWorld")))
3651
3652- def test_double_click_unmaximize_window(self):
3653- """Double clicking the grab area must unmaximize a maximized window."""
3654- gedit_win = self.open_new_application_window("Text Editor", maximized=True)
3655-
3656- self.panel.move_mouse_over_grab_area()
3657- self.mouse.click()
3658- self.mouse.click()
3659-
3660- self.assertThat(self.panel.title, Eventually(Equals(gedit_win.application.name)))
3661+
3662+class PanelWindowButtonsActionsTests(PanelTestsBase):
3663+ """Test WindowButtons actions on windows, focused or not depending on LIM"""
3664+ restored_on_top = False
3665+ scenarios = multiply_scenarios(_make_monitor_scenarios(),
3666+ (_make_menu_modes_scenarios() +
3667+ [('Locally Integrated Menus with restored on Top',
3668+ {'lim': True, 'restored_on_top': True})]))
3669+
3670+ def setUp(self):
3671+ super(PanelWindowButtonsActionsTests, self).setUp()
3672+ self.text_win = self.open_new_application_window("Text Editor", maximized=True)
3673+
3674+ if self.restored_on_top:
3675+ self.open_new_application_window("Calculator")
3676+
3677+ def test_window_buttons_update_visual_state(self):
3678+ """Window button must update its state in response to mouse events."""
3679+ self.panel.move_mouse_over_window_buttons()
3680+ button = self.panel.window_buttons.unmaximize
3681+
3682+ self.assertThat(self.panel.window_buttons.focused, Eventually(Equals(not self.restored_on_top)))
3683+ self.assertThat(button.visual_state, Eventually(Equals("normal")))
3684+
3685+ button.mouse_move_to()
3686+ self.assertThat(button.visual_state, Eventually(Equals("prelight")))
3687+
3688+ self.mouse.press()
3689+ self.addCleanup(self.mouse.release)
3690+ self.assertThat(button.visual_state, Eventually(Equals("pressed")))
3691+
3692+ def test_window_buttons_cancel(self):
3693+ """Window buttons must ignore clicks when the mouse released outside
3694+ their area.
3695+ """
3696+ self.panel.move_mouse_over_window_buttons()
3697+
3698+ button = self.panel.window_buttons.unmaximize
3699+ button.mouse_move_to()
3700+ self.mouse.press()
3701+ self.assertThat(button.visual_state, Eventually(Equals("pressed")))
3702+ self.panel.move_mouse_below_the_panel()
3703+ self.mouse.release()
3704+
3705+ self.assertThat(self.text_win.is_maximized, Equals(True))
3706+
3707+ def test_window_buttons_close_button_works_for_window(self):
3708+ """Close window button must actually closes a window."""
3709+ win_xid = self.text_win.x_id
3710+
3711+ self.panel.window_buttons.close.mouse_click()
3712+ self.assertNoWindowOpenWithXid(win_xid)
3713+
3714+ def test_window_buttons_close_follows_fitts_law(self):
3715+ """Tests that the 'Close' button is activated when clicking at 0,0.
3716+
3717+ See bug #839690
3718+ """
3719+ win_xid = self.text_win.x_id
3720+
3721+ self.panel.move_mouse_over_window_buttons()
3722+ screen_x, screen_y = self.display.get_screen_geometry(self.panel_monitor)[:2]
3723+ self.mouse.move(screen_x, screen_y)
3724+ self.mouse.click()
3725+
3726+ self.assertNoWindowOpenWithXid(win_xid)
3727+
3728+ def test_window_buttons_minimize_button_works_for_window(self):
3729+ """Tests that the window button 'Minimize' actually minimizes a window."""
3730+ self.panel.window_buttons.minimize.mouse_click()
3731+ self.assertProperty(self.text_win, is_hidden=True)
3732+
3733+ def test_window_buttons_minimize_follows_fitts_law(self):
3734+ """Tests that the 'Minimize' button is conform to Fitts's Law.
3735+
3736+ See bug #839690
3737+ """
3738+ self.panel.move_mouse_over_window_buttons()
3739+ button = self.panel.window_buttons.minimize
3740+ target_x = button.x + button.width / 2
3741+ target_y = self.display.get_screen_geometry(self.panel_monitor)[1]
3742+ self.mouse.move(target_x, target_y)
3743+ self.mouse.click()
3744+
3745+ self.assertProperty(self.text_win, is_hidden=True)
3746+
3747+ def test_window_buttons_unmaximize_button_works_for_window(self):
3748+ """Tests that the window button 'Unmaximize' actually unmaximizes a window."""
3749+ self.panel.window_buttons.unmaximize.mouse_click()
3750+
3751+ self.assertProperties(self.text_win, is_maximized=False, is_focused=True)
3752+ self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(False)))
3753+
3754+ def test_window_buttons_unmaximize_follows_fitts_law(self):
3755+ """Tests that the 'Unmaximize' button is conform to Fitts's Law.
3756+
3757+ See bug #839690
3758+ """
3759+ button = self.panel.window_buttons.unmaximize
3760+ button.mouse_move_to()
3761+ target_x = button.x + button.width / 2
3762+ target_y = self.display.get_screen_geometry(self.panel_monitor)[1]
3763+ self.mouse.move(target_x, target_y)
3764+ sleep(1)
3765+ self.mouse.click()
3766+
3767+ self.assertProperty(self.text_win, is_maximized=False)
3768
3769
3770 class PanelHoverTests(PanelTestsBase):
3771 """Tests with the mouse pointer hovering the panel area."""
3772
3773- scenarios = _make_monitor_scenarios()
3774+ scenarios = _make_scenarios()
3775
3776 def test_only_menus_show_for_restored_window_on_mouse_in_window_btn_area(self):
3777 """Restored windows should only show menus when the mouse is in the window
3778 button area.
3779 """
3780- self.open_new_application_window("Calculator",
3781- maximized=False,
3782- move_to_monitor=True)
3783+ self.open_new_application_window("Calculator")
3784 self.sleep_menu_settle_period()
3785
3786 self.panel.move_mouse_over_window_buttons()
3787
3788- self.assertThat(self.panel.menus_shown, Eventually(Equals(True)))
3789+ self.assertThat(self.panel.menus_shown, Eventually(Equals(not self.lim)))
3790 self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(False)))
3791
3792 def test_only_menus_show_for_restored_window_on_mouse_in_menu_area(self):
3793 """Restored windows should only show menus when the mouse is in the window
3794 menu area.
3795 """
3796- self.open_new_application_window("Calculator",
3797- maximized=False,
3798- move_to_monitor=True)
3799+ self.open_new_application_window("Calculator")
3800 self.sleep_menu_settle_period()
3801
3802 self.panel.move_mouse_over_menus()
3803
3804- self.assertThat(self.panel.menus_shown, Eventually(Equals(True)))
3805+ self.assertThat(self.panel.menus_shown, Eventually(Equals(not self.lim)))
3806 self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(False)))
3807
3808 def test_only_menus_show_for_restored_window_on_mouse_in_grab_area(self):
3809 """Restored windows should only show menus when the mouse is in the panel
3810 grab area.
3811 """
3812- self.open_new_application_window("Calculator",
3813- maximized=False,
3814- move_to_monitor=True)
3815+ self.open_new_application_window("Calculator")
3816 self.sleep_menu_settle_period()
3817
3818 if self.panel.grab_area.width <= 0:
3819@@ -731,14 +755,12 @@
3820
3821 self.panel.move_mouse_over_grab_area()
3822
3823- self.assertThat(self.panel.menus_shown, Eventually(Equals(True)))
3824+ self.assertThat(self.panel.menus_shown, Eventually(Equals(not self.lim)))
3825 self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(False)))
3826
3827 def test_hovering_over_indicators_does_not_show_app_menus(self):
3828 """Hovering the mouse over the indicators must not show app menus."""
3829- self.open_new_application_window("Calculator",
3830- maximized=False,
3831- move_to_monitor=True)
3832+ self.open_new_application_window("Text Editor", maximized=True)
3833 self.sleep_menu_settle_period()
3834
3835 self.panel.move_mouse_over_menus()
3836@@ -754,9 +776,7 @@
3837 """Menus and window buttons must be shown when the mouse is in the window
3838 button area for a maximised application.
3839 """
3840- self.open_new_application_window("Text Editor",
3841- maximized=True,
3842- move_to_monitor=True)
3843+ self.open_new_application_window("Text Editor", maximized=True)
3844 self.sleep_menu_settle_period()
3845
3846 self.panel.move_mouse_over_window_buttons()
3847@@ -768,9 +788,7 @@
3848 """Menus and window buttons must be shown when the mouse is in the menu
3849 area for a maximised application.
3850 """
3851- self.open_new_application_window("Text Editor",
3852- maximized=True,
3853- move_to_monitor=True)
3854+ self.open_new_application_window("Text Editor", maximized=True)
3855 self.sleep_menu_settle_period()
3856
3857 self.panel.move_mouse_over_menus()
3858@@ -785,9 +803,7 @@
3859 if self.panel.grab_area.width <= 0:
3860 self.skipTest("Grab area is too small to run this test!")
3861
3862- self.open_new_application_window("Text Editor",
3863- maximized=True,
3864- move_to_monitor=True)
3865+ self.open_new_application_window("Text Editor", maximized=True)
3866 self.sleep_menu_settle_period()
3867
3868 self.panel.move_mouse_over_grab_area()
3869@@ -799,9 +815,7 @@
3870 """Hovering the mouse over the indicators must hide the menus and window
3871 buttons.
3872 """
3873- self.open_new_application_window("Text Editor",
3874- maximized=True,
3875- move_to_monitor=True)
3876+ self.open_new_application_window("Text Editor", maximized=True)
3877 self.sleep_menu_settle_period()
3878
3879 self.panel.move_mouse_over_menus()
3880@@ -811,14 +825,14 @@
3881
3882 self.panel.move_mouse_over_indicators()
3883
3884- self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(False)))
3885+ self.assertThat(self.panel.window_buttons_shown, Eventually(Equals(self.lim)))
3886 self.assertThat(self.panel.menus_shown, Eventually(Equals(False)))
3887
3888 def test_hovering_indicators_open_menus(self):
3889 """Opening an indicator entry, and then hovering on other entries must
3890 open them.
3891 """
3892- self.open_new_application_window("Text Editor")
3893+ self.open_new_application_window("Text Editor", maximized=self.lim)
3894 entries = self.panel.get_indicator_entries(include_hidden_menus=True)
3895
3896 self.assertThat(len(entries), GreaterThan(0))
3897@@ -832,7 +846,7 @@
3898
3899 class PanelMenuTests(PanelTestsBase):
3900
3901- scenarios = _make_monitor_scenarios()
3902+ scenarios = _make_scenarios()
3903
3904 def start_test_app_with_menus(self):
3905 window_spec = {
3906@@ -846,7 +860,12 @@
3907 {"Title": "&Quit"}
3908 ]
3909 }
3910- self.launch_test_window(window_spec)
3911+ test_win = self.launch_test_window(window_spec)
3912+ test_win.set_focus()
3913+ self.move_window_to_panel_monitor(test_win)
3914+ self.ensure_window_state(test_win, maximized=self.lim)
3915+
3916+ return test_win
3917
3918 def test_menus_are_added_on_new_application(self):
3919 """Tests that menus are added when a new application is opened."""
3920@@ -872,10 +891,13 @@
3921 "Current panel entries are: %r" % self.panel.menus.get_entries())
3922
3923 self.panel.move_mouse_over_grab_area()
3924- self.assertThat(self.panel.title, Eventually(Equals(test_win.application.name)))
3925+ expected = test_win.application.name if not self.lim else ""
3926+ self.assertThat(self.panel.title, Eventually(Equals(expected)))
3927
3928 def test_menus_shows_when_new_application_is_opened(self):
3929 """When starting a new application, menus must first show, then hide."""
3930+ if self.lim:
3931+ self.skipTest("Menu discovery is disabled when LIM are enabled.")
3932
3933 # This test requires the window to be opened on the monitor that is being tested and
3934 # we cannot guarantee which monitor the window will open up on.
3935@@ -890,6 +912,9 @@
3936
3937 def test_menus_dont_show_if_a_new_application_window_is_opened(self):
3938 """This tests the menu discovery feature on new window for a know application."""
3939+ if self.lim:
3940+ self.skipTest("Menu discovery is disabled when LIM are enabled.")
3941+
3942 self.open_new_application_window("Character Map")
3943 self.sleep_menu_settle_period()
3944
3945@@ -917,7 +942,7 @@
3946
3947 self.panel.move_mouse_over_menus()
3948
3949- self.assertThat(self.panel.menus_shown, Eventually(Equals(True)))
3950+ self.assertThat(self.panel.menus_shown, Eventually(Equals(not self.lim)))
3951
3952 def test_menus_dont_show_for_maximized_window_on_mouse_out(self):
3953 """Maximized window menus must not show when the mouse is outside the
3954@@ -947,7 +972,7 @@
3955
3956 def test_menus_dont_show_with_hud(self):
3957 """Tests that menus are not showing when opening the HUD."""
3958- self.open_new_application_window("Text Editor", maximized=True)
3959+ self.open_new_application_window("Character Map", maximized=True)
3960 self.unity.hud.ensure_visible()
3961 self.addCleanup(self.unity.hud.ensure_hidden)
3962
3963@@ -957,11 +982,13 @@
3964 class PanelIndicatorEntryTests(PanelTestsBase):
3965 """Tests for the indicator entries, including both menu and indicators."""
3966
3967- scenarios = _make_monitor_scenarios()
3968+ scenarios = _make_scenarios()
3969
3970 def open_app_and_get_menu_entry(self):
3971 """Open the test app and wait for the menu entry to appear."""
3972- self.open_new_application_window("Calculator")
3973+ self.open_new_application_window("Remmina" if self.lim else "Calculator",
3974+ maximized=self.lim)
3975+
3976 refresh_fn = lambda: len(self.panel.menus.get_entries())
3977 self.assertThat(refresh_fn, Eventually(GreaterThan(0)))
3978 menu_entry = self.panel.menus.get_entries()[0]
3979@@ -1033,7 +1060,7 @@
3980
3981 class PanelKeyNavigationTests(PanelTestsBase):
3982
3983- scenarios = _make_monitor_scenarios()
3984+ scenarios = _make_scenarios()
3985
3986 def get_active_indicator(self):
3987 """Get the active indicator in a safe manner.
3988@@ -1048,17 +1075,17 @@
3989 """Pressing the open-menus keybinding must open the first indicator."""
3990 self.open_new_application_window("Calculator")
3991 refresh_fn = lambda: len(self.panel.menus.get_entries())
3992- self.assertThat(refresh_fn, Eventually(GreaterThan(0)))
3993+ self.assertThat(refresh_fn, Eventually(Equals(0) if self.lim else GreaterThan(0)))
3994 self.addCleanup(self.keyboard.press_and_release, "Escape")
3995 self.keybinding("panel/open_first_menu")
3996
3997 open_indicator = self.get_active_indicator()
3998- expected_indicator = self.panel.get_indicator_entries(include_hidden_menus=True)[0]
3999+ expected_indicator = self.panel.get_indicator_entries(include_hidden_menus=not self.lim)[0]
4000 self.assertThat(open_indicator.entry_id, Eventually(Equals(expected_indicator.entry_id)))
4001
4002 def test_panel_hold_show_menu_works(self):
4003 """Holding the show menu key must reveal the menu with mnemonics."""
4004- self.open_new_application_window("Text Editor")
4005+ self.open_new_application_window("Text Editor", maximized=self.lim)
4006 refresh_fn = lambda: len(self.panel.menus.get_entries())
4007 self.assertThat(refresh_fn, Eventually(GreaterThan(0)))
4008 self.addCleanup(self.keyboard.press_and_release, "Escape")
4009@@ -1073,7 +1100,7 @@
4010
4011 def test_panel_menu_accelerators_work(self):
4012 """Pressing a valid menu accelerator must open the correct menu item."""
4013- self.open_new_application_window("Text Editor")
4014+ self.open_new_application_window("Text Editor", maximized=self.lim)
4015 refresh_fn = lambda: len(self.panel.menus.get_entries())
4016 self.assertThat(refresh_fn, Eventually(GreaterThan(0)))
4017 self.addCleanup(self.keyboard.press_and_release, "Escape")
4018@@ -1087,7 +1114,7 @@
4019 calc_win = self.open_new_application_window("Calculator")
4020 self.assertProperty(calc_win, is_focused=True)
4021
4022- available_indicators = self.panel.get_indicator_entries(include_hidden_menus=True)
4023+ available_indicators = self.panel.get_indicator_entries(include_hidden_menus=not self.lim)
4024
4025 self.keybinding("panel/open_first_menu")
4026 self.addCleanup(self.keyboard.press_and_release, "Escape")
4027@@ -1102,7 +1129,7 @@
4028 calc_win = self.open_new_application_window("Calculator")
4029 self.assertProperty(calc_win, is_focused=True)
4030
4031- available_indicators = self.panel.get_indicator_entries(include_hidden_menus=True)
4032+ available_indicators = self.panel.get_indicator_entries(include_hidden_menus=not self.lim)
4033
4034 self.keybinding("panel/open_first_menu")
4035 self.addCleanup(self.keyboard.press_and_release, "Escape")
4036@@ -1118,14 +1145,12 @@
4037 opened with the keyboard.
4038 """
4039 self.open_new_application_window("Calculator")
4040- available_indicators = self.panel.get_indicator_entries(include_hidden_menus=True)
4041+ available_indicators = self.panel.get_indicator_entries(include_hidden_menus=not self.lim)
4042
4043 self.keybinding("panel/open_first_menu")
4044 self.addCleanup(self.keyboard.press_and_release, "Escape")
4045
4046 available_indicators[2].mouse_move_to()
4047- self.addCleanup(self.panel.move_mouse_below_the_panel)
4048-
4049 self.assertThat(available_indicators[2].active, Eventually(Equals(True)))
4050
4051 self.keybinding("panel/prev_indicator")
4052@@ -1135,11 +1160,10 @@
4053 class PanelGrabAreaTests(PanelTestsBase):
4054 """Panel grab area tests."""
4055
4056- scenarios = _make_monitor_scenarios()
4057+ scenarios = _make_scenarios()
4058
4059 def move_mouse_over_grab_area(self):
4060 self.panel.move_mouse_over_grab_area()
4061- self.addCleanup(self.panel.move_mouse_below_the_panel)
4062 sleep(.1)
4063
4064 def test_unmaximize_from_grab_area_works(self):
4065@@ -1192,6 +1216,29 @@
4066 self.assertThat(self.unity.hud.search_string, Eventually(Equals("HelloWorld")))
4067
4068
4069+class PanelLimTests(PanelTestsBase):
4070+
4071+ scenarios = _make_monitor_scenarios()
4072+
4073+ def setUp(self):
4074+ self.lim = True
4075+ super(PanelLimTests, self).setUp()
4076+
4077+ def test_title_focus_on_maximized_state_changes(self):
4078+ text_win = self.open_new_application_window("Text Editor", maximized=True)
4079+ self.assertThat(self.panel.focused, Eventually(Equals(True)))
4080+ self.assertThat(self.panel.title, Eventually(Equals(text_win.title)))
4081+
4082+ self.open_new_application_window("Calculator")
4083+ self.assertThat(self.panel.focused, Eventually(Equals(False)))
4084+ self.assertThat(self.panel.title, Eventually(Equals(text_win.title)))
4085+
4086+ text_win.set_focus()
4087+ self.assertProperty(text_win, is_focused=True)
4088+ self.assertThat(self.panel.focused, Eventually(Equals(True)))
4089+ self.assertThat(self.panel.title, Eventually(Equals(text_win.title)))
4090+
4091+
4092 class PanelCrossMonitorsTests(PanelTestsBase):
4093 """Multimonitor panel tests."""
4094
4095
4096=== modified file 'tests/autopilot/unity/tests/test_wm_keybindings.py'
4097--- tests/autopilot/unity/tests/test_wm_keybindings.py 2013-12-04 19:42:43 +0000
4098+++ tests/autopilot/unity/tests/test_wm_keybindings.py 2015-07-15 14:19:40 +0000
4099@@ -21,27 +21,24 @@
4100
4101 def open_panel_menu(self):
4102 panel = self.unity.panels.get_panel_for_monitor(0)
4103- self.assertThat(lambda: len(panel.menus.get_entries()), Eventually(GreaterThan(0)))
4104+ self.assertThat(lambda: len(panel.get_indicator_entries()), Eventually(GreaterThan(0)))
4105 self.addCleanup(self.keyboard.press_and_release, "Escape")
4106 self.keybinding("panel/open_first_menu")
4107 self.assertThat(self.unity.panels.get_active_indicator, Eventually(NotEquals(None)))
4108
4109 def test_dash_shows_on_menus_opened(self):
4110- self.process_manager.start_app_window("Calculator")
4111 self.open_panel_menu()
4112 self.addCleanup(self.unity.dash.ensure_hidden)
4113 self.unity.dash.ensure_visible()
4114 self.assertThat(self.unity.panels.get_active_indicator, Eventually(Equals(None)))
4115
4116 def test_hud_shows_on_menus_opened(self):
4117- self.process_manager.start_app_window("Calculator")
4118 self.open_panel_menu()
4119 self.addCleanup(self.unity.hud.ensure_hidden)
4120 self.unity.hud.ensure_visible()
4121 self.assertThat(self.unity.panels.get_active_indicator, Eventually(Equals(None)))
4122
4123 def test_switcher_shows_on_menus_opened(self):
4124- self.process_manager.start_app_window("Calculator")
4125 self.open_panel_menu()
4126 self.addCleanup(self.unity.switcher.terminate)
4127 self.unity.switcher.initiate()
4128@@ -49,7 +46,6 @@
4129 self.assertThat(self.unity.panels.get_active_indicator, Eventually(Equals(None)))
4130
4131 def test_shortcut_hints_shows_on_menus_opened(self):
4132- self.process_manager.start_app_window("Calculator")
4133 self.open_panel_menu()
4134 self.addCleanup(self.unity.shortcut_hint.ensure_hidden)
4135 self.unity.shortcut_hint.show()
4136@@ -57,7 +53,6 @@
4137 self.assertThat(self.unity.panels.get_active_indicator, Eventually(Equals(None)))
4138
4139 def test_spread_shows_on_menus_opened(self):
4140- self.process_manager.start_app_window("Calculator")
4141 self.open_panel_menu()
4142 self.addCleanup(self.unity.window_manager.terminate_spread)
4143 self.unity.window_manager.initiate_spread()
4144
4145=== modified file 'tests/mock-application.h'
4146--- tests/mock-application.h 2014-03-21 04:40:12 +0000
4147+++ tests/mock-application.h 2015-07-15 14:19:40 +0000
4148@@ -20,7 +20,7 @@
4149 #ifndef TESTS_MOCK_APPLICATION_H
4150 #define TESTS_MOCK_APPLICATION_H
4151
4152-#include <map>
4153+#include <unordered_map>
4154 #include <gmock/gmock.h>
4155 #include <gio/gdesktopappinfo.h>
4156 #include <UnityCore/GLibWrapper.h>
4157@@ -360,7 +360,7 @@
4158 }
4159
4160 private:
4161- typedef std::map<std::string, unity::ApplicationPtr> AppMap;
4162+ typedef std::unordered_map<std::string, unity::ApplicationPtr> AppMap;
4163 AppMap app_map_;
4164 };
4165
4166
4167=== modified file 'tests/test_dbus_indicators.cpp'
4168--- tests/test_dbus_indicators.cpp 2013-03-25 18:22:32 +0000
4169+++ tests/test_dbus_indicators.cpp 2015-07-15 14:19:40 +0000
4170@@ -5,6 +5,7 @@
4171 #include <UnityCore/GLibWrapper.h>
4172 #include <UnityCore/DBusIndicators.h>
4173
4174+#include "panel-service-private.h"
4175 #include "test_utils.h"
4176
4177 using namespace unity;
4178@@ -50,10 +51,8 @@
4179
4180 GVariant* CallPanelMethod(std::string const& name) const
4181 {
4182- return g_dbus_connection_call_sync(session,
4183- "com.canonical.Unity.Test",
4184- "/com/canonical/Unity/Panel/Service",
4185- "com.canonical.Unity.Panel.Service",
4186+ return g_dbus_connection_call_sync(session, "com.canonical.Unity.Test",
4187+ UPS_PATH, UPS_IFACE,
4188 name.c_str(),
4189 NULL,
4190 NULL,
4191
4192=== modified file 'tests/test_indicator.cpp'
4193--- tests/test_indicator.cpp 2014-01-27 17:31:30 +0000
4194+++ tests/test_indicator.cpp 2015-07-15 14:19:40 +0000
4195@@ -44,7 +44,7 @@
4196
4197 MOCK_CONST_METHOD0(Updated, void());
4198 MOCK_CONST_METHOD1(EntryAdded, void(Entry::Ptr const&));
4199- MOCK_CONST_METHOD1(EntryRemoved, void(std::string const&));
4200+ MOCK_CONST_METHOD1(EntryRemoved, void(Entry::Ptr const&));
4201 MOCK_CONST_METHOD5(ShowMenu, void(std::string const&, unsigned, int, int, unsigned));
4202 MOCK_CONST_METHOD1(SecondaryActivate, void(std::string const&));
4203 MOCK_CONST_METHOD2(Scroll, void(std::string const&, int));
4204@@ -57,7 +57,6 @@
4205 EXPECT_EQ(indicator.name(), "indicator-test");
4206 EXPECT_FALSE(indicator.IsAppmenu());
4207 EXPECT_EQ(indicator.GetEntry("test-entry"), nullptr);
4208- EXPECT_EQ(indicator.EntryIndex("test-entry"), -1);
4209 EXPECT_TRUE(indicator.GetEntries().empty());
4210 }
4211
4212@@ -69,17 +68,17 @@
4213 Indicator indicator("indicator-test");
4214 SigReceiver::Nice sig_receiver(indicator);
4215
4216- entry = new Entry("test-entry-1", "name-hint", "label", true, true, 0, "icon",
4217+ entry = new Entry("test-entry-1", "name-hint", 0, "label", true, true, 0, "icon",
4218 true, true, -1);
4219 Entry::Ptr entry1(entry);
4220 sync_data.push_back(entry1);
4221
4222- entry = new Entry("test-entry-2", "name-hint", "label", true, true, 0, "icon",
4223+ entry = new Entry("test-entry-2", "name-hint", 0, "label", true, true, 0, "icon",
4224 true, true, -1);
4225 Entry::Ptr entry2(entry);
4226 sync_data.push_back(entry2);
4227
4228- entry = new Entry("test-entry-3", "name-hint", "label", true, true, 0, "icon",
4229+ entry = new Entry("test-entry-3", "name-hint", 0, "label", true, true, 0, "icon",
4230 true, true, -1);
4231 Entry::Ptr entry3(entry);
4232 sync_data.push_back(entry3);
4233@@ -97,31 +96,29 @@
4234 indicator.Sync(sync_data);
4235 EXPECT_EQ(indicator.GetEntries().size(), 3);
4236 EXPECT_EQ(indicator.GetEntry("test-entry-2"), entry2);
4237- EXPECT_EQ(indicator.EntryIndex("test-entry-2"), 1);
4238 // Mock::VerifyAndClearExpectations(&sig_receiver);
4239
4240 // Sync the indicator removing an entry
4241- sync_data.remove(entry2);
4242+ sync_data.erase(std::remove(sync_data.begin(), sync_data.end(), entry2), sync_data.end());
4243 EXPECT_EQ(sync_data.size(), 2);
4244 EXPECT_CALL(sig_receiver, Updated());
4245 EXPECT_CALL(sig_receiver, EntryAdded(_)).Times(0);
4246- EXPECT_CALL(sig_receiver, EntryRemoved(entry2->id()));
4247+ EXPECT_CALL(sig_receiver, EntryRemoved(entry2));
4248
4249 indicator.Sync(sync_data);
4250 EXPECT_EQ(indicator.GetEntries().size(), 2);
4251 EXPECT_EQ(indicator.GetEntry("test-entry-2"), nullptr);
4252- EXPECT_EQ(indicator.EntryIndex("test-entry-2"), -1);
4253
4254 // Sync the indicator removing an entry and adding a new one
4255- entry = new Entry("test-entry-4", "name-hint", "label", true, true, 0, "icon",
4256+ entry = new Entry("test-entry-4", "name-hint", 0, "label", true, true, 0, "icon",
4257 true, true, -1);
4258 Entry::Ptr entry4(entry);
4259 sync_data.push_back(entry4);
4260- sync_data.remove(entry3);
4261+ sync_data.erase(std::remove(sync_data.begin(), sync_data.end(), entry3), sync_data.end());
4262 EXPECT_EQ(sync_data.size(), 2);
4263
4264 EXPECT_CALL(sig_receiver, EntryAdded(entry4));
4265- EXPECT_CALL(sig_receiver, EntryRemoved(entry3->id()));
4266+ EXPECT_CALL(sig_receiver, EntryRemoved(entry3));
4267 EXPECT_CALL(sig_receiver, Updated());
4268 indicator.Sync(sync_data);
4269 EXPECT_EQ(indicator.GetEntries().size(), 2);
4270@@ -129,8 +126,8 @@
4271 // Remove all the indicators
4272
4273 EXPECT_CALL(sig_receiver, EntryAdded(_)).Times(0);
4274- EXPECT_CALL(sig_receiver, EntryRemoved(entry1->id()));
4275- EXPECT_CALL(sig_receiver, EntryRemoved(entry4->id()));
4276+ EXPECT_CALL(sig_receiver, EntryRemoved(entry1));
4277+ EXPECT_CALL(sig_receiver, EntryRemoved(entry4));
4278 EXPECT_CALL(sig_receiver, Updated());
4279
4280 sync_data.clear();
4281@@ -144,13 +141,13 @@
4282 SigReceiver::Nice sig_receiver(indicator);
4283 Indicator::Entries sync_data;
4284
4285- auto entry1 = std::make_shared<Entry>("test-entry-1", "name-hint", "label", true, true, 0, "icon", true, true, -1);
4286+ auto entry1 = std::make_shared<Entry>("test-entry-1", "name-hint", 0, "label", true, true, 0, "icon", true, true, -1);
4287 sync_data.push_back(entry1);
4288
4289- auto entry2 = std::make_shared<Entry>("test-entry-2", "name-hint", "label", true, true, 0, "icon", true, true, -1);
4290+ auto entry2 = std::make_shared<Entry>("test-entry-2", "name-hint", 0, "label", true, true, 0, "icon", true, true, -1);
4291 sync_data.push_back(entry2);
4292
4293- auto entry3 = std::make_shared<Entry>("test-entry-3", "name-hint", "label", true, true, 0, "icon", true, true, -1);
4294+ auto entry3 = std::make_shared<Entry>("test-entry-3", "name-hint", 0, "label", true, true, 0, "icon", true, true, -1);
4295 sync_data.push_back(entry3);
4296
4297 EXPECT_CALL(sig_receiver, Updated());
4298@@ -162,7 +159,7 @@
4299 EXPECT_CALL(sig_receiver, Updated()).Times(0);
4300 indicator.Sync(sync_data);
4301
4302- sync_data.remove(entry3);
4303+ sync_data.erase(std::remove(sync_data.begin(), sync_data.end(), entry3), sync_data.end());
4304 EXPECT_CALL(sig_receiver, Updated());
4305 indicator.Sync(sync_data);
4306
4307@@ -176,7 +173,7 @@
4308 Indicator indicator("indicator-test");
4309 SigReceiver::Nice sig_receiver(indicator);
4310
4311- auto entry = std::make_shared<Entry>("test-entry-1", "name-hint", "label", true, true, 0, "icon", true, true, -1);
4312+ auto entry = std::make_shared<Entry>("test-entry-1", "name-hint", 0, "label", true, true, 0, "icon", true, true, -1);
4313 indicator.Sync({entry});
4314
4315 EXPECT_CALL(sig_receiver, ShowMenu(entry->id(), 123456789, 50, 100, 2));
4316@@ -194,7 +191,7 @@
4317 Indicator indicator("indicator-test");
4318 SigReceiver::Nice sig_receiver(indicator);
4319
4320- auto entry = std::make_shared<Entry>("test-entry-2", "name-hint", "label", true, true, 0, "icon", true, true, -1);
4321+ auto entry = std::make_shared<Entry>("test-entry-2", "name-hint", 0, "label", true, true, 0, "icon", true, true, -1);
4322 indicator.Sync({entry});
4323
4324 EXPECT_CALL(sig_receiver, SecondaryActivate(entry->id()));
4325@@ -206,7 +203,7 @@
4326 Indicator indicator("indicator-test");
4327 SigReceiver::Nice sig_receiver(indicator);
4328
4329- auto entry = std::make_shared<Entry>("test-entry-2", "name-hint", "label", true, true, 0, "icon", true, true, -1);
4330+ auto entry = std::make_shared<Entry>("test-entry-2", "name-hint", 0, "label", true, true, 0, "icon", true, true, -1);
4331 indicator.Sync({entry});
4332
4333 EXPECT_CALL(sig_receiver, Scroll(entry->id(), -5));
4334
4335=== modified file 'tests/test_indicator_appmenu.cpp'
4336--- tests/test_indicator_appmenu.cpp 2012-12-04 00:33:18 +0000
4337+++ tests/test_indicator_appmenu.cpp 2015-07-15 14:19:40 +0000
4338@@ -1,6 +1,6 @@
4339 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
4340 /*
4341- * Copyright (C) 2012 Canonical Ltd
4342+ * Copyright (C) 2012-2015 Canonical Ltd
4343 *
4344 * This program is free software: you can redistribute it and/or modify
4345 * it under the terms of the GNU General Public License version 3 as
4346@@ -18,15 +18,41 @@
4347 */
4348
4349 #include <UnityCore/AppmenuIndicator.h>
4350-
4351-#include <gtest/gtest.h>
4352+#include <gmock/gmock.h>
4353
4354 using namespace std;
4355 using namespace unity;
4356 using namespace indicator;
4357+using namespace testing;
4358
4359 namespace
4360 {
4361+struct SigReceiver : sigc::trackable
4362+{
4363+ typedef NiceMock<SigReceiver> Nice;
4364+
4365+ SigReceiver(AppmenuIndicator const& const_indicator)
4366+ {
4367+ auto& indicator = const_cast<AppmenuIndicator&>(const_indicator);
4368+ indicator.updated.connect(sigc::mem_fun(this, &SigReceiver::Updated));
4369+ indicator.updated_win.connect(sigc::mem_fun(this, &SigReceiver::UpdatedWin));
4370+ indicator.on_entry_added.connect(sigc::mem_fun(this, &SigReceiver::EntryAdded));
4371+ indicator.on_entry_removed.connect(sigc::mem_fun(this, &SigReceiver::EntryRemoved));
4372+ indicator.on_show_menu.connect(sigc::mem_fun(this, &SigReceiver::ShowMenu));
4373+ indicator.on_show_appmenu.connect(sigc::mem_fun(this, &SigReceiver::ShowAppmenu));
4374+ indicator.on_secondary_activate.connect(sigc::mem_fun(this, &SigReceiver::SecondaryActivate));
4375+ indicator.on_scroll.connect(sigc::mem_fun(this, &SigReceiver::Scroll));
4376+ }
4377+
4378+ MOCK_CONST_METHOD0(Updated, void());
4379+ MOCK_CONST_METHOD1(UpdatedWin, void(uint32_t));
4380+ MOCK_CONST_METHOD1(EntryAdded, void(Entry::Ptr const&));
4381+ MOCK_CONST_METHOD1(EntryRemoved, void(Entry::Ptr const&));
4382+ MOCK_CONST_METHOD5(ShowMenu, void(std::string const&, unsigned, int, int, unsigned));
4383+ MOCK_CONST_METHOD3(ShowAppmenu, void(unsigned, int, int));
4384+ MOCK_CONST_METHOD1(SecondaryActivate, void(std::string const&));
4385+ MOCK_CONST_METHOD2(Scroll, void(std::string const&, int));
4386+};
4387
4388 TEST(TestAppmenuIndicator, Construction)
4389 {
4390@@ -39,25 +65,160 @@
4391 TEST(TestAppmenuIndicator, ShowAppmenu)
4392 {
4393 AppmenuIndicator indicator("indicator-appmenu");
4394-
4395- bool signal_emitted = false;
4396- int show_x, show_y;
4397- unsigned show_xid;
4398-
4399- // Connecting to signals
4400- indicator.on_show_appmenu.connect([&] (unsigned int xid, int x, int y) {
4401- signal_emitted = true;
4402- show_xid = xid;
4403- show_x = x;
4404- show_y = y;
4405- });
4406-
4407+ SigReceiver::Nice sig_receiver(indicator);
4408+
4409+ EXPECT_CALL(sig_receiver, ShowAppmenu(123456789, 50, 100));
4410 indicator.ShowAppmenu(123456789, 50, 100);
4411- EXPECT_TRUE(signal_emitted);
4412-
4413- EXPECT_EQ(show_xid, 123456789);
4414- EXPECT_EQ(show_x, 50);
4415- EXPECT_EQ(show_y, 100);
4416+}
4417+
4418+TEST(TestAppmenuIndicator, Syncing)
4419+{
4420+ Indicator::Entries sync_data;
4421+
4422+ AppmenuIndicator indicator("indicator-appmenu");
4423+ SigReceiver::Nice sig_receiver(indicator);
4424+ const uint32_t parent_window1 = 12345;
4425+ const uint32_t parent_window2 = 54321;
4426+
4427+ auto entry1 = std::make_shared<Entry>("test-entry-1", "name-hint", parent_window1, "label", true, true, 0, "icon", true, true, -1);
4428+ sync_data.push_back(entry1);
4429+
4430+ auto entry2 = std::make_shared<Entry>("test-entry-2", "name-hint", parent_window1, "label", true, true, 0, "icon", true, true, -1);
4431+ sync_data.push_back(entry2);
4432+
4433+ auto entry3 = std::make_shared<Entry>("test-entry-3", "name-hint", parent_window2, "label", true, true, 0, "icon", true, true, -1);
4434+ sync_data.push_back(entry3);
4435+
4436+ // Sync the indicator, adding 3 entries
4437+ {
4438+ testing::InSequence s;
4439+ EXPECT_CALL(sig_receiver, EntryAdded(entry1));
4440+ EXPECT_CALL(sig_receiver, EntryAdded(entry2));
4441+ EXPECT_CALL(sig_receiver, EntryAdded(entry3));
4442+ EXPECT_CALL(sig_receiver, EntryRemoved(_)).Times(0);
4443+ EXPECT_CALL(sig_receiver, Updated());
4444+ }
4445+
4446+ EXPECT_CALL(sig_receiver, UpdatedWin(parent_window1));
4447+ EXPECT_CALL(sig_receiver, UpdatedWin(parent_window2));
4448+
4449+ indicator.Sync(sync_data);
4450+ EXPECT_EQ(indicator.GetEntriesForWindow(parent_window1), Indicator::Entries({entry1, entry2}));
4451+ EXPECT_EQ(indicator.GetEntriesForWindow(parent_window2), Indicator::Entries({entry3}));
4452+
4453+ // Sync the indicator removing an entry
4454+ sync_data.erase(std::remove(sync_data.begin(), sync_data.end(), entry2), sync_data.end());
4455+ ASSERT_EQ(sync_data.size(), 2);
4456+ EXPECT_CALL(sig_receiver, Updated());
4457+ EXPECT_CALL(sig_receiver, UpdatedWin(parent_window1));
4458+ EXPECT_CALL(sig_receiver, UpdatedWin(parent_window2)).Times(0);
4459+ EXPECT_CALL(sig_receiver, EntryAdded(_)).Times(0);
4460+ EXPECT_CALL(sig_receiver, EntryRemoved(entry2));
4461+
4462+ indicator.Sync(sync_data);
4463+ EXPECT_EQ(indicator.GetEntries().size(), 2);
4464+ EXPECT_EQ(indicator.GetEntry("test-entry-2"), nullptr);
4465+ EXPECT_EQ(indicator.GetEntriesForWindow(parent_window1), Indicator::Entries({entry1}));
4466+
4467+ // Sync the indicator removing an entry and adding a new one
4468+ auto entry4 = std::make_shared<Entry>("test-entry-4", "name-hint", parent_window2, "label", true, true, 0, "icon", true, true, -1);
4469+ sync_data.push_back(entry4);
4470+ sync_data.erase(std::remove(sync_data.begin(), sync_data.end(), entry3), sync_data.end());
4471+ EXPECT_EQ(sync_data.size(), 2);
4472+
4473+ EXPECT_CALL(sig_receiver, EntryAdded(entry4));
4474+ EXPECT_CALL(sig_receiver, EntryRemoved(entry3));
4475+ EXPECT_CALL(sig_receiver, Updated());
4476+ EXPECT_CALL(sig_receiver, UpdatedWin(parent_window1)).Times(0);
4477+ EXPECT_CALL(sig_receiver, UpdatedWin(parent_window2));
4478+ indicator.Sync(sync_data);
4479+ EXPECT_EQ(indicator.GetEntriesForWindow(parent_window1), Indicator::Entries({entry1}));
4480+ EXPECT_EQ(indicator.GetEntriesForWindow(parent_window2), Indicator::Entries({entry4}));
4481+
4482+ // Remove all the indicators
4483+ EXPECT_CALL(sig_receiver, EntryAdded(_)).Times(0);
4484+ EXPECT_CALL(sig_receiver, EntryRemoved(entry1));
4485+ EXPECT_CALL(sig_receiver, EntryRemoved(entry4));
4486+ EXPECT_CALL(sig_receiver, Updated());
4487+ EXPECT_CALL(sig_receiver, UpdatedWin(parent_window1));
4488+ EXPECT_CALL(sig_receiver, UpdatedWin(parent_window2));
4489+
4490+ sync_data.clear();
4491+ indicator.Sync(sync_data);
4492+
4493+ EXPECT_TRUE(indicator.GetEntriesForWindow(parent_window1).empty());
4494+ EXPECT_TRUE(indicator.GetEntriesForWindow(parent_window2).empty());
4495+}
4496+
4497+TEST(TestAppmenuIndicator, Updated)
4498+{
4499+ AppmenuIndicator indicator("indicator-test");
4500+ SigReceiver::Nice sig_receiver(indicator);
4501+ Indicator::Entries sync_data;
4502+ const uint32_t parent_window1 = 12345;
4503+ const uint32_t parent_window2 = 54321;
4504+
4505+ auto entry1 = std::make_shared<Entry>("test-entry-1", "name-hint", parent_window1, "label", true, true, 0, "icon", true, true, -1);
4506+ sync_data.push_back(entry1);
4507+
4508+ auto entry2 = std::make_shared<Entry>("test-entry-2", "name-hint", parent_window2, "label", true, true, 0, "icon", true, true, -1);
4509+ sync_data.push_back(entry2);
4510+
4511+ auto entry3 = std::make_shared<Entry>("test-entry-3", "name-hint", parent_window1, "label", true, true, 0, "icon", true, true, -1);
4512+ sync_data.push_back(entry3);
4513+
4514+ EXPECT_CALL(sig_receiver, Updated());
4515+
4516+ // Sync the indicator, adding 3 entries
4517+ indicator.Sync(sync_data);
4518+
4519+ // Readding the same entries, nothing is emitted
4520+ EXPECT_CALL(sig_receiver, Updated()).Times(0);
4521+ indicator.Sync(sync_data);
4522+
4523+ sync_data.erase(std::remove(sync_data.begin(), sync_data.end(), entry3), sync_data.end());
4524+ EXPECT_CALL(sig_receiver, Updated());
4525+ indicator.Sync(sync_data);
4526+
4527+ sync_data.push_back(entry3);
4528+ EXPECT_CALL(sig_receiver, Updated());
4529+ indicator.Sync(sync_data);
4530+}
4531+
4532+TEST(TestAppmenuIndicator, UpdatedWin)
4533+{
4534+ AppmenuIndicator indicator("indicator-test");
4535+ SigReceiver::Nice sig_receiver(indicator);
4536+ Indicator::Entries sync_data;
4537+ const uint32_t parent_window1 = 12345;
4538+ const uint32_t parent_window2 = 54321;
4539+
4540+ auto entry1 = std::make_shared<Entry>("test-entry-1", "name-hint", parent_window1, "label", true, true, 0, "icon", true, true, -1);
4541+ sync_data.push_back(entry1);
4542+
4543+ auto entry2 = std::make_shared<Entry>("test-entry-2", "name-hint", parent_window2, "label", true, true, 0, "icon", true, true, -1);
4544+ sync_data.push_back(entry2);
4545+
4546+ auto entry3 = std::make_shared<Entry>("test-entry-3", "name-hint", parent_window1, "label", true, true, 0, "icon", true, true, -1);
4547+ sync_data.push_back(entry3);
4548+
4549+ EXPECT_CALL(sig_receiver, UpdatedWin(parent_window1));
4550+ EXPECT_CALL(sig_receiver, UpdatedWin(parent_window2));
4551+
4552+ // Sync the indicator, adding 3 entries
4553+ indicator.Sync(sync_data);
4554+
4555+ // Readding the same entries, nothing is emitted
4556+ EXPECT_CALL(sig_receiver, UpdatedWin(_)).Times(0);
4557+ indicator.Sync(sync_data);
4558+
4559+ sync_data.erase(std::remove(sync_data.begin(), sync_data.end(), entry3), sync_data.end());
4560+ EXPECT_CALL(sig_receiver, UpdatedWin(entry3->parent_window()));
4561+ indicator.Sync(sync_data);
4562+
4563+ sync_data.push_back(entry3);
4564+ EXPECT_CALL(sig_receiver, UpdatedWin(entry3->parent_window()));
4565+ indicator.Sync(sync_data);
4566 }
4567
4568 }
4569
4570=== modified file 'tests/test_indicator_entry.cpp'
4571--- tests/test_indicator_entry.cpp 2014-02-07 23:54:15 +0000
4572+++ tests/test_indicator_entry.cpp 2015-07-15 14:19:40 +0000
4573@@ -36,11 +36,12 @@
4574 TEST(TestIndicatorEntry, TestConstruction)
4575 {
4576
4577- Entry entry("id", "name_hint", "label", true, true, 1, "some icon", false, true, -1);
4578+ Entry entry("id", "name_hint", 12345, "label", true, true, 1, "some icon", false, true, -1);
4579
4580 EXPECT_EQ(entry.id(), "id");
4581+ EXPECT_EQ(entry.name_hint(), "name_hint");
4582+ EXPECT_EQ(entry.parent_window(), 12345);
4583 EXPECT_EQ(entry.label(), "label");
4584- EXPECT_EQ(entry.name_hint(), "name_hint");
4585 EXPECT_TRUE(entry.label_sensitive());
4586 EXPECT_TRUE(entry.label_visible());
4587 EXPECT_FALSE(entry.image_sensitive());
4588@@ -55,10 +56,11 @@
4589
4590 TEST(TestIndicatorEntry, TestConstructionEmpty)
4591 {
4592- Entry entry("id", "name_hint");
4593+ Entry entry("id", "name_hint", 12345);
4594
4595 EXPECT_EQ(entry.id(), "id");
4596 EXPECT_EQ(entry.name_hint(), "name_hint");
4597+ EXPECT_EQ(entry.parent_window(), 12345);
4598 EXPECT_TRUE(entry.label().empty());
4599 EXPECT_FALSE(entry.label_sensitive());
4600 EXPECT_FALSE(entry.label_visible());
4601@@ -74,8 +76,8 @@
4602
4603 TEST(TestIndicatorEntry, TestAssignment)
4604 {
4605- Entry entry("id", "name_hint", "label", true, true, 0, "some icon", false, true, 10);
4606- Entry other_entry("other_id", "other_name_hint", "other_label", false, false, 2, "other icon", true, false, 5);
4607+ Entry entry("id", "name_hint", 12345, "label", true, true, 0, "some icon", false, true, 10);
4608+ Entry other_entry("other_id", "other_name_hint", 54321, "other_label", false, false, 2, "other icon", true, false, 5);
4609
4610 SigReceiver sig_receiver(entry);
4611 EXPECT_CALL(sig_receiver, Updated());
4612@@ -83,6 +85,7 @@
4613
4614 EXPECT_EQ(entry.id(), "other_id");
4615 EXPECT_EQ(entry.name_hint(), "other_name_hint");
4616+ EXPECT_EQ(entry.parent_window(), 54321);
4617 EXPECT_EQ(entry.label(), "other_label");
4618 EXPECT_FALSE(entry.label_sensitive());
4619 EXPECT_FALSE(entry.label_visible());
4620@@ -95,8 +98,8 @@
4621
4622 TEST(TestIndicatorEntry, TestShowNowEvents)
4623 {
4624- Entry entry("id", "name_hint", "label", true, true,
4625- 0, "some icon", false, true, -1);
4626+ Entry entry("id", "name_hint", 0, "label", true, true,
4627+ 0, "some icon", false, true, -1);
4628 SigReceiver sig_receiver(entry);
4629
4630 // Setting show_now to the same value doesn't emit any events.
4631@@ -116,7 +119,7 @@
4632
4633 TEST(TestIndicatorEntry, TestActiveEvents)
4634 {
4635- Entry entry("id", "name_hint", "label", true, true, 0, "some icon", false, true, -1);
4636+ Entry entry("id", "name_hint", 0, "label", true, true, 0, "some icon", false, true, -1);
4637
4638 SigReceiver sig_receiver(entry);
4639
4640@@ -137,7 +140,7 @@
4641
4642 TEST(TestIndicatorEntry, TestOnScroll)
4643 {
4644- Entry entry("id", "name_hint", "label", true, true, 0, "some icon", false, true, -1);
4645+ Entry entry("id", "name_hint", 0, "label", true, true, 0, "some icon", false, true, -1);
4646 SigReceiver sig_receiver(entry);
4647
4648 EXPECT_CALL(sig_receiver, OnScroll("id", 10));
4649@@ -149,16 +152,16 @@
4650
4651 TEST(TestIndicatorEntry, TestOnShowMenu)
4652 {
4653- Entry entry("id", "name_hint", "label", true, true, 0, "some icon", false, true, -1);
4654+ Entry entry("id", "name_hint", 123, "label", true, true, 0, "some icon", false, true, -1);
4655 SigReceiver sig_receiver(entry);
4656
4657- EXPECT_CALL(sig_receiver, OnShowMenu("id", 0, 10, 20, 1));
4658+ EXPECT_CALL(sig_receiver, OnShowMenu("id", 123, 10, 20, 1));
4659 entry.ShowMenu(10, 20, 1);
4660 }
4661
4662 TEST(TestIndicatorEntry, TestOnShowMenuXid)
4663 {
4664- Entry entry("xid", "name_hint", "label", true, true, 0, "some icon", false, true, -1);
4665+ Entry entry("xid", "name_hint", 0, "label", true, true, 0, "some icon", false, true, -1);
4666 SigReceiver sig_receiver(entry);
4667
4668 EXPECT_CALL(sig_receiver, OnShowMenu("xid", 88492615, 15, 25, 2));
4669@@ -167,7 +170,7 @@
4670
4671 TEST(TestIndicatorEntry, TestVisibility)
4672 {
4673- Entry entry("id", "name_hint", "label", true, true, 0, "some icon", false, false, -1);
4674+ Entry entry("id", "name_hint", 0, "label", true, true, 0, "some icon", false, false, -1);
4675
4676 EXPECT_TRUE(entry.visible());
4677
4678@@ -208,7 +211,7 @@
4679
4680 TEST(TestIndicatorEntry, TestGeometry)
4681 {
4682- Entry entry("id", "name_hint", "label", true, true, 0, "some icon", false, true, -1);
4683+ Entry entry("id", "name_hint", 0, "label", true, true, 0, "some icon", false, true, -1);
4684 SigReceiver sig_receiver(entry);
4685
4686 // Setting to the same value doesn't emit any events.
4687
4688=== modified file 'tests/test_indicators.cpp'
4689--- tests/test_indicators.cpp 2014-02-11 03:11:47 +0000
4690+++ tests/test_indicators.cpp 2015-07-15 14:19:40 +0000
4691@@ -62,15 +62,15 @@
4692
4693 Indicator::Ptr test_indicator_1 = indicators.AddIndicator("indicator-test-1");
4694
4695- entry = new Entry("indicator-test-1|entry-1", "name-hint-1", "label", true, true,
4696- 0, "icon", true, true, -1);
4697- sync_data.push_back(Entry::Ptr(entry));
4698-
4699- entry = new Entry("indicator-test-1|entry-2", "name-hint-2", "label", true, true,
4700- 0, "icon", true, true, -1);
4701- sync_data.push_back(Entry::Ptr(entry));
4702-
4703- entry = new Entry("indicator-test-1|entry-3", "name-hint-3", "label", true, true,
4704+ entry = new Entry("indicator-test-1|entry-1", "name-hint-1", 0, "label", true, true,
4705+ 0, "icon", true, true, -1);
4706+ sync_data.push_back(Entry::Ptr(entry));
4707+
4708+ entry = new Entry("indicator-test-1|entry-2", "name-hint-2", 0, "label", true, true,
4709+ 0, "icon", true, true, -1);
4710+ sync_data.push_back(Entry::Ptr(entry));
4711+
4712+ entry = new Entry("indicator-test-1|entry-3", "name-hint-3", 0, "label", true, true,
4713 0, "icon", true, true, -1);
4714 sync_data.push_back(Entry::Ptr(entry));
4715
4716@@ -83,11 +83,11 @@
4717 Indicator::Ptr test_indicator_2 = indicators.AddIndicator("indicator-test-2");
4718 sync_data.clear();
4719
4720- entry = new Entry("indicator-test-2|entry-1", "name-hint-1", "label", true, true,
4721+ entry = new Entry("indicator-test-2|entry-1", "name-hint-1", 0, "label", true, true,
4722 0, "icon", true, true, -1);
4723 sync_data.push_back(Entry::Ptr(entry));
4724
4725- entry = new Entry("indicator-test-2|entry-2", "name-hint-2", "label", true, true,
4726+ entry = new Entry("indicator-test-2|entry-2", "name-hint-2", 0, "label", true, true,
4727 0, "icon", true, true, -1);
4728 sync_data.push_back(Entry::Ptr(entry));
4729
4730
4731=== modified file 'tests/test_panel_menu_view.cpp'
4732--- tests/test_panel_menu_view.cpp 2014-03-21 04:40:12 +0000
4733+++ tests/test_panel_menu_view.cpp 2015-07-15 14:19:40 +0000
4734@@ -36,11 +36,22 @@
4735
4736 struct TestPanelMenuView : public testing::Test
4737 {
4738+ TestPanelMenuView()
4739+ : menu_manager(std::make_shared<menu::MockManager>())
4740+ , menu_view(menu_manager)
4741+ {}
4742+
4743 struct MockPanelMenuView : public PanelMenuView
4744 {
4745- MockPanelMenuView()
4746- : PanelMenuView(std::make_shared<menu::MockManager>())
4747- {}
4748+ MockPanelMenuView(menu::Manager::Ptr const& menu_manager)
4749+ : PanelMenuView(menu_manager)
4750+ {
4751+ view_opened_signal_.Disconnect();
4752+ active_win_changed_signal_.Disconnect();
4753+ active_app_changed_signal_.Disconnect();
4754+ view_closed_signal_.Disconnect();
4755+ maximized_wins_.clear();
4756+ }
4757
4758 MOCK_METHOD0(QueueDraw, void());
4759 MOCK_CONST_METHOD1(GetActiveViewName, std::string(bool));
4760@@ -53,6 +64,7 @@
4761 using PanelMenuView::titlebar_grab_area_;
4762 using PanelMenuView::we_control_active_;
4763 using PanelMenuView::spread_showing_;
4764+ using PanelMenuView::maximized_wins_;
4765 };
4766
4767 nux::ObjectPtr<nux::BaseWindow> AddPanelToWindow(int monitor)
4768@@ -69,6 +81,7 @@
4769 panel_win->ComputeContentSize();
4770
4771 menu_view.SetMonitor(monitor);
4772+ menu_view.maximized_wins_.clear();
4773
4774 return panel_win;
4775 }
4776@@ -79,6 +92,7 @@
4777 MockUScreen uscreen;
4778 panel::Style panelStyle;
4779 testwrapper::StandaloneWM WM;
4780+ menu::MockManager::Ptr menu_manager;
4781 testing::NiceMock<MockPanelMenuView> menu_view;
4782 };
4783
4784@@ -91,6 +105,7 @@
4785
4786 TEST_F(TestPanelMenuView, Escaping)
4787 {
4788+ menu_manager->integrated_menus = false;
4789 ON_CALL(menu_view, GetActiveViewName(testing::_)).WillByDefault(Return("<>'"));
4790 auto escapedText = "Panel d'Inici";
4791 ASSERT_TRUE(menu_view.GetCurrentTitle().empty());
4792@@ -136,6 +151,7 @@
4793 TEST_P(ProgressTester, RestoreOnGrabInBiggerWorkArea)
4794 {
4795 uscreen.SetupFakeMultiMonitor();
4796+ connection::Manager conn;
4797 unsigned monitor = uscreen.GetMonitors().size() - 1;
4798 auto const& monitor_geo = uscreen.GetMonitorGeometry(monitor);
4799 WM->SetWorkareaGeometry(monitor_geo);
4800
4801=== modified file 'tests/test_panel_service.cpp'
4802--- tests/test_panel_service.cpp 2013-10-03 15:16:06 +0000
4803+++ tests/test_panel_service.cpp 2015-07-15 14:19:40 +0000
4804@@ -32,8 +32,8 @@
4805 {
4806 typedef std::tuple<glib::Object<GtkLabel>, glib::Object<GtkImage>> EntryObjects;
4807
4808-const std::string SYNC_ENTRY_VARIANT_FORMAT = "(ssssbbusbbi)";
4809-const std::string SYNC_ENTRIES_VARIANT_FORMAT = "(a"+SYNC_ENTRY_VARIANT_FORMAT+")";
4810+const std::string SYNC_ENTRY_VARIANT_FORMAT = ENTRY_SIGNATURE;
4811+const std::string SYNC_ENTRIES_VARIANT_FORMAT = "(" ENTRY_ARRAY_SIGNATURE ")";
4812
4813 struct TestPanelService : Test
4814 {
4815@@ -46,6 +46,7 @@
4816 std::string indicator_id;
4817 std::string entry_id;
4818 std::string entry_name_hint;
4819+ uint32_t parent_window;
4820 std::string label;
4821 bool label_sensitive;
4822 bool label_visible;
4823@@ -63,6 +64,7 @@
4824 gchar* indicator_id;
4825 gchar* entry_id;
4826 gchar* entry_name_hint;
4827+ guint32 parent_window;
4828 gchar* label;
4829 gboolean label_sensitive;
4830 gboolean label_visible;
4831@@ -77,6 +79,7 @@
4832 &indicator_id,
4833 &entry_id,
4834 &entry_name_hint,
4835+ &parent_window,
4836 &label,
4837 &label_sensitive,
4838 &label_visible,
4839@@ -89,6 +92,7 @@
4840 results.push_back({ glib::gchar_to_string(indicator_id),
4841 glib::gchar_to_string(entry_id),
4842 glib::gchar_to_string(entry_name_hint),
4843+ parent_window,
4844 glib::gchar_to_string(label),
4845 label_sensitive != FALSE,
4846 label_visible != FALSE,
4847
4848=== modified file 'tests/test_service_panel.cpp'
4849--- tests/test_service_panel.cpp 2013-03-02 22:44:29 +0000
4850+++ tests/test_service_panel.cpp 2015-07-15 14:19:40 +0000
4851@@ -1,4 +1,5 @@
4852 #include "test_service_panel.h"
4853+#include "panel-service-private.h"
4854
4855 namespace unity
4856 {
4857@@ -9,11 +10,11 @@
4858 static const char * panel_interface =
4859 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
4860 "<node name=\"/\">\n"
4861-" <interface name=\"com.canonical.Unity.Panel.Service\">\n"
4862+" <interface name=\"" UPS_IFACE "\">\n"
4863 "\n"
4864 "<!-- Begin of real methods/signals -->\n"
4865 " <method name='Sync'>"
4866-" <arg type='a(ssssbbusbbi)' name='state' direction='out'/>"
4867+" <arg type='" ENTRY_ARRAY_SIGNATURE "' name='state' direction='out'/>"
4868 " </method>"
4869 "\n"
4870 " <signal name='ReSync'>"
4871@@ -32,12 +33,13 @@
4872 "</node>\n"
4873 ;
4874
4875-void add_entry_id(GVariantBuilder *b)
4876+void add_entry_id(GVariantBuilder *b, gint priority)
4877 {
4878- g_variant_builder_add (b, "(ssssbbusbbi)",
4879+ g_variant_builder_add (b, ENTRY_SIGNATURE,
4880 "test_indicator_id",
4881 "test_entry_id",
4882 "test_entry_name_hint",
4883+ 0, /* parent window */
4884 "test_entry_label",
4885 TRUE, /* label sensitive */
4886 TRUE, /* label visible */
4887@@ -45,15 +47,16 @@
4888 "", /* image_data */
4889 TRUE, /* image sensitive */
4890 TRUE, /* image visible */
4891- 1 /* priority */);
4892+ priority);
4893 }
4894
4895-void add_entry_id_2(GVariantBuilder *b)
4896+void add_entry_id_2(GVariantBuilder *b, gint priority)
4897 {
4898- g_variant_builder_add (b, "(ssssbbusbbi)",
4899+ g_variant_builder_add (b, ENTRY_SIGNATURE,
4900 "test_indicator_id",
4901 "test_entry_id2",
4902 "test_entry_name_hint2",
4903+ 12345, /* parent window */
4904 "test_entry_label2",
4905 TRUE, /* label sensitive */
4906 TRUE, /* label visible */
4907@@ -61,7 +64,7 @@
4908 "", /* image_data */
4909 TRUE, /* image sensitive */
4910 TRUE, /* image visible */
4911- 1 /* priority */);
4912+ priority);
4913 }
4914 }
4915
4916@@ -73,7 +76,7 @@
4917 auto object = glib::DBusObjectBuilder::GetObjectsForIntrospection(panel_interface).front();
4918 object->SetMethodsCallsHandler(sigc::mem_fun(this, &Panel::OnMethodCall));
4919
4920- server_.AddObject(object, "/com/canonical/Unity/Panel/Service");
4921+ server_.AddObject(object, UPS_PATH);
4922 }
4923
4924 GVariant* Panel::OnMethodCall(std::string const& method, GVariant *parameters)
4925@@ -82,18 +85,18 @@
4926 {
4927 GVariantBuilder b;
4928
4929- g_variant_builder_init (&b, G_VARIANT_TYPE ("(a(ssssbbusbbi))"));
4930- g_variant_builder_open (&b, G_VARIANT_TYPE ("a(ssssbbusbbi)"));
4931+ g_variant_builder_init (&b, G_VARIANT_TYPE ("(" ENTRY_ARRAY_SIGNATURE ")"));
4932+ g_variant_builder_open (&b, G_VARIANT_TYPE (ENTRY_ARRAY_SIGNATURE));
4933
4934 if (sync_return_mode_ == 0)
4935 {
4936- add_entry_id(&b);
4937- add_entry_id_2(&b);
4938+ add_entry_id(&b, 1);
4939+ add_entry_id_2(&b, 2);
4940 }
4941 else if (sync_return_mode_ == 1)
4942 {
4943- add_entry_id_2(&b);
4944- add_entry_id(&b);
4945+ add_entry_id_2(&b, 1);
4946+ add_entry_id(&b, 2);
4947 }
4948
4949 if (sync_return_mode_ == 1)
4950
4951=== modified file 'unity-shared/IconLoader.cpp'
4952--- unity-shared/IconLoader.cpp 2014-03-21 01:49:22 +0000
4953+++ unity-shared/IconLoader.cpp 2015-07-15 14:19:40 +0000
4954@@ -799,7 +799,7 @@
4955 bool CoalesceTasksCb();
4956
4957 private:
4958- std::map<std::string, glib::Object<GdkPixbuf>> cache_;
4959+ std::unordered_map<std::string, glib::Object<GdkPixbuf>> cache_;
4960 /* FIXME: the reference counting of IconLoaderTasks with shared pointers
4961 * is currently somewhat broken, and the queued_tasks_ member is what keeps
4962 * it from crashing randomly.
4963@@ -807,7 +807,7 @@
4964 * tasks, but when they are being completed in a worker thread, the thread
4965 * should own them as well (yet it doesn't), this could cause trouble
4966 * in the future... You've been warned! */
4967- std::map<std::string, IconLoaderTask::Ptr> queued_tasks_;
4968+ std::unordered_map<std::string, IconLoaderTask::Ptr> queued_tasks_;
4969 std::queue<IconLoaderTask::Ptr> tasks_;
4970 std::unordered_map<Handle, IconLoaderTask::Ptr> task_map_;
4971 std::vector<IconLoaderTask*> finished_tasks_;
4972
4973=== modified file 'unity-shared/MenuManager.cpp'
4974--- unity-shared/MenuManager.cpp 2015-03-12 00:57:05 +0000
4975+++ unity-shared/MenuManager.cpp 2015-07-15 14:19:40 +0000
4976@@ -26,6 +26,7 @@
4977 #include <unordered_map>
4978
4979 #include "MenuManager.h"
4980+#include "WindowManager.h"
4981
4982 namespace unity
4983 {
4984@@ -48,16 +49,20 @@
4985 : parent_(parent)
4986 , indicators_(indicators)
4987 , key_grabber_(grabber)
4988+ , show_now_window_(0)
4989 , settings_(g_settings_new(SETTINGS_NAME.c_str()))
4990 {
4991 for (auto const& indicator : indicators_->GetIndicators())
4992 AddIndicator(indicator);
4993
4994+ GrabMnemonicsForActiveWindow();
4995+
4996 parent_->show_menus.changed.connect(sigc::mem_fun(this, &Impl::ShowMenus));
4997 indicators_->on_object_added.connect(sigc::mem_fun(this, &Impl::AddIndicator));
4998 indicators_->on_object_removed.connect(sigc::mem_fun(this, &Impl::RemoveIndicator));
4999 indicators_->on_entry_activate_request.connect(sigc::mem_fun(this, &Impl::ActivateRequest));
5000 indicators_->icon_paths_changed.connect(sigc::mem_fun(this, &Impl::IconPathsChanged));
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to status/vote changes: