Merge lp:~3v1n0/unity/lim-panel into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Merged
Merge reported by: Marco Trevisan (Treviño)
Merged at revision: not available
Proposed branch: lp:~3v1n0/unity/lim-panel
Merge into: lp:unity
Prerequisite: lp:~3v1n0/unity/lim
Diff against target: 1212 lines (+729/-37)
14 files modified
UnityCore/AppmenuIndicator.cpp (+47/-5)
UnityCore/AppmenuIndicator.h (+17/-3)
plugins/unityshell/src/PanelIndicatorAppmenuView.cpp (+238/-0)
plugins/unityshell/src/PanelIndicatorAppmenuView.h (+68/-0)
plugins/unityshell/src/PanelIndicatorEntryView.cpp (+25/-6)
plugins/unityshell/src/PanelIndicatorEntryView.h (+1/-0)
plugins/unityshell/src/PanelIndicatorsView.cpp (+11/-0)
plugins/unityshell/src/PanelIndicatorsView.h (+2/-0)
plugins/unityshell/src/PanelMenuView.cpp (+240/-20)
plugins/unityshell/src/PanelMenuView.h (+9/-0)
plugins/unityshell/src/PanelStyle.cpp (+1/-0)
plugins/unityshell/src/PanelStyle.h (+1/-0)
plugins/unityshell/src/unityshell.cpp (+3/-2)
tests/test_indicator_appmenu.cpp (+66/-1)
To merge this branch: bzr merge lp:~3v1n0/unity/lim-panel
Reviewer Review Type Date Requested Status
Sam Spilsbury Pending
Review via email: mp+92710@code.launchpad.net

Description of the change

UI work for the Locally Integrated Menus support for the unity panel.

I've made some code improvements and rewrite to PanelStyle, PanelMenuView, PanelIndicatorEntryView, PanelTitlebarGrabArea and WindowButtons, plus I've added the new class PanelIndicatorAppmenuView which is a special indicator that is created when the PanelMenu is in the "integrated-mode". In that case the appmenu view is populated with the indicator entry (that won't ever change) and updated against the window status changes to match the content of the currently maximized window on top of the stack.

Using the integrated menu, the appmenu-indicator is also capable of being dragged down, middle-clicked and double-clicked exactly like the PanelTitlebarGrabArea. When clicking on it, if the mouse-up event happens after 120ms the mouse-down, we just consider that action as a grab and we start acting accordingly.

Updated 17/02:
Fixed also bug #934680, added some new features to WindowManager, some of them imported from lp:~3v1n0/unity/super-arrows-shortcuts:

GetWindowSavedGeometry: returns the window saved geometry, that it doesn't
                        consider if the window is maximized or not.
MoveResizeWindow: the name should say what it does ;)
GetWorkAreaGeometry: returns the size of the work-area for the given
                     window of for the current output (if xid = 0),
                     It considers the struts geometries.
RestoreAt: restores a window and move it at the given x, y position
           keeping the standard geometry.

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

8 +BuilderWrapper& BuilderWrapper::add(char const* name, long int value)
9 +{
10 + g_variant_builder_add(builder_, "{sv}", name, g_variant_new_int64(value));

long is 32-bit on i386, if you really need 64bit value this should be changed to "long long".

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

> 8 +BuilderWrapper& BuilderWrapper::add(char const* name, long int value)
> 9 +{
> 10 + g_variant_builder_add(builder_, "{sv}", name,
> g_variant_new_int64(value));
>
> long is 32-bit on i386, if you really need 64bit value this should be changed
> to "long long".

Right. I've added wrappers for long long too, anyway I'm keeping the variant as a gint64 also for long int, to make sure it's working also on 64bit...

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

"The diff has been truncated for viewing. "

Try to avoid doing too much rewriting in any one branch :)

466 PanelIndicatorEntryView::~PanelIndicatorEntryView()
467 {
468 - on_indicator_activate_changed_connection_.disconnect();
469 - on_indicator_updated_connection_.disconnect();
470 - on_panelstyle_changed_connection_.disconnect();
471 - g_signal_handler_disconnect(gtk_settings_get_default(), on_font_changed_connection_);
472 - if (texture_layer_)
473 - delete texture_layer_;
474 + // Nothing to do...
475 }

The empty destructor's definition can be removed (unless its virtual)

+ if (!wm->IsExpoActive() && !wm->IsScaleActive())
490 + {

This probably doesn't make sense living where it is. The Panel views should block all clicks if if the screen is grabbed by compiz period (eg, add a wrapper method in WindowManager around CompScreen::otherGrabExist (NULL);)

3181 + /* FIXME, this can be removed when window_unmapped WindowManager signal
3182 + * will emit the proper xid */
3183 + Window xid = bamf_window_get_xid(reinterpret_cast<BamfWindow*>(view));
3184 + OnWindowUnmapped(xid);

Can you explain this? It could be emitting the frame xid, and that needs to be fixed there :)

nvm found it

3391 + // FIXME: compiz doesn't give us a valid xid (is always 0 on unmap)
3392 + // we need to do this again on BamfView closed signal.

Great. I'll fix that in compiz then. (This is probably the case when the window is destroyed and the xid is changed to zero, and then the unmap signal happens)

The window management stuff looks great.

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

> "The diff has been truncated for viewing. "
>
> Try to avoid doing too much rewriting in any one branch :)

Yes, I know, but things often come in mind when doing it, and as I'm touching a lot of panel stuff, I'd prefer to keep all here.
You can just use bzr send lp:unity -o branch-changes.diff to check them locally ;)

> The empty destructor's definition can be removed (unless its virtual)
>
> + if (!wm->IsExpoActive() && !wm->IsScaleActive())
> 490 + {
>
> This probably doesn't make sense living where it is. The Panel views should
> block all clicks if if the screen is grabbed by compiz period (eg, add a
> wrapper method in WindowManager around CompScreen::otherGrabExist (NULL);)

Well, if the dash grab isn't considered by that, I could try to do it.

> 3391 + // FIXME: compiz doesn't give us a valid xid (is always 0 on unmap)
> 3392 + // we need to do this again on BamfView closed signal.
>
> Great. I'll fix that in compiz then. (This is probably the case when the
> window is destroyed and the xid is changed to zero, and then the unmap signal
> happens)

Let me know when your fix will be landed, so we can remove this.

> The window management stuff looks great.

Cool! ;)

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 2012-03-29 12:06:35 +0000
3+++ UnityCore/AppmenuIndicator.cpp 2012-04-18 08:58:24 +0000
4@@ -24,13 +24,55 @@
5 namespace indicator
6 {
7
8+namespace
9+{
10+const std::string SETTING_NAME("com.canonical.indicator.appmenu");
11+const std::string SETTING_KEY("menu-mode");
12+}
13+
14 AppmenuIndicator::AppmenuIndicator(std::string const& name)
15 : Indicator(name)
16-{}
17-
18-void AppmenuIndicator::ShowAppmenu(unsigned int xid, int x, int y, unsigned int timestamp) const
19-{
20- on_show_appmenu.emit(xid, x, y, timestamp);
21+ , gsettings_(g_settings_new(SETTING_NAME.c_str()))
22+ , integrated_(false)
23+{
24+ setting_changed_.Connect(gsettings_, "changed::menu-mode", [&] (GSettings*, gchar*) {
25+ CheckSettingValue();
26+ });
27+
28+ CheckSettingValue();
29+}
30+
31+bool AppmenuIndicator::ShowAppmenu(unsigned int xid, int x, int y, unsigned int timestamp) const
32+{
33+ if (integrated_)
34+ {
35+ on_show_appmenu.emit(xid, x, y, timestamp);
36+ return true;
37+ }
38+
39+ return false;
40+}
41+
42+bool AppmenuIndicator::IsIntegrated() const
43+{
44+ return integrated_;
45+}
46+
47+void AppmenuIndicator::CheckSettingValue()
48+{
49+ glib::String menu_mode(g_settings_get_string(gsettings_, SETTING_KEY.c_str()));
50+ bool integrated_menus = false;
51+
52+ if (menu_mode.Str() == "locally-integrated")
53+ {
54+ integrated_menus = true;
55+ }
56+
57+ if (integrated_menus != integrated_)
58+ {
59+ integrated_ = integrated_menus;
60+ integrated_changed.emit(integrated_);
61+ }
62 }
63
64 } // namespace indicator
65
66=== modified file 'UnityCore/AppmenuIndicator.h'
67--- UnityCore/AppmenuIndicator.h 2012-03-29 12:06:35 +0000
68+++ UnityCore/AppmenuIndicator.h 2012-04-18 08:58:24 +0000
69@@ -21,6 +21,10 @@
70 #define UNITY_APPMENU_INDICATOR_H
71
72 #include "Indicator.h"
73+#include "GLibWrapper.h"
74+#include "GLibSignal.h"
75+
76+#include <gio/gio.h>
77
78 namespace unity
79 {
80@@ -33,12 +37,22 @@
81 AppmenuIndicator(std::string const& name);
82
83 virtual bool IsAppmenu() const { return true; }
84-
85- void ShowAppmenu(unsigned int xid, int x, int y, unsigned int timestamp) const;
86-
87+ bool IsIntegrated() const;
88+
89+ bool ShowAppmenu(unsigned int xid, int x, int y, unsigned int timestamp) const;
90+
91+ sigc::signal<void, bool> integrated_changed;
92 sigc::signal<void, unsigned int, int, int, unsigned int> on_show_appmenu;
93+
94+private:
95+ void CheckSettingValue();
96+
97+ glib::Object<GSettings> gsettings_;
98+ glib::Signal<void, GSettings*, gchar*> setting_changed_;
99+ bool integrated_;
100 };
101
102+
103 }
104 }
105
106
107=== added file 'plugins/unityshell/src/PanelIndicatorAppmenuView.cpp'
108--- plugins/unityshell/src/PanelIndicatorAppmenuView.cpp 1970-01-01 00:00:00 +0000
109+++ plugins/unityshell/src/PanelIndicatorAppmenuView.cpp 2012-04-18 08:58:24 +0000
110@@ -0,0 +1,238 @@
111+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
112+/*
113+ * Copyright (C) 2012 Canonical Ltd
114+ *
115+ * This program is free software: you can redistribute it and/or modify
116+ * it under the terms of the GNU General Public License version 3 as
117+ * published by the Free Software Foundation.
118+ *
119+ * This program is distributed in the hope that it will be useful,
120+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
121+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
122+ * GNU General Public License for more details.
123+ *
124+ * You should have received a copy of the GNU General Public License
125+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
126+ *
127+ * Authored by: Marco Trevisan (Treviño) <3v1n0@ubuntu.com>
128+ */
129+
130+#include <UnityCore/Variant.h>
131+#include <UnityCore/GLibWrapper.h>
132+#include <libbamf/libbamf.h>
133+
134+#include "PanelIndicatorAppmenuView.h"
135+#include "WindowManager.h"
136+#include "PanelStyle.h"
137+
138+namespace unity
139+{
140+namespace
141+{
142+ const std::string MENU_ATOM = "_UBUNTU_APPMENU_UNIQUE_NAME";
143+}
144+
145+using namespace indicator;
146+
147+PanelIndicatorAppmenuView::PanelIndicatorAppmenuView(Entry::Ptr const& proxy)
148+ : PanelIndicatorEntryView(proxy, 0, APPMENU)
149+ , xid_(0)
150+ , has_menu_(false)
151+{
152+ spacing_ = 2;
153+ right_padding_ = 7;
154+ SetVisible(false);
155+}
156+
157+void PanelIndicatorAppmenuView::GetGeometryForSync(EntryLocationMap& locations)
158+{
159+ if (!IsFocused())
160+ return;
161+
162+ PanelIndicatorEntryView::GetGeometryForSync(locations);
163+}
164+
165+void PanelIndicatorAppmenuView::Activate(int button)
166+{
167+ /* If the button is 0, the entry is activated using a keyboard shortcut,
168+ * so we need to check the fucus status of the entry */
169+ if (button != 0 || (button == 0 && IsFocused()))
170+ {
171+ SetActiveState(true, 1);
172+ }
173+}
174+
175+void PanelIndicatorAppmenuView::ShowMenu(int button)
176+{
177+ if (xid_ && has_menu_)
178+ {
179+ WindowManager::Default()->Raise(xid_);
180+ WindowManager::Default()->Activate(xid_);
181+
182+ proxy_->ShowMenu(xid_,
183+ GetAbsoluteX(),
184+ GetAbsoluteY() + panel::Style::Instance().panel_height,
185+ button,
186+ time(nullptr));
187+ }
188+}
189+
190+std::string PanelIndicatorAppmenuView::GetLabel()
191+{
192+ glib::String escaped(g_markup_escape_text(label_.c_str(), -1));
193+
194+ std::ostringstream bold_label;
195+ bold_label << "<b>" << escaped.Str() << "</b>";
196+
197+ return bold_label.str();
198+}
199+
200+bool PanelIndicatorAppmenuView::IsLabelSensitive() const
201+{
202+ return (!label_.empty() && has_menu_);
203+}
204+
205+bool PanelIndicatorAppmenuView::IsLabelVisible() const
206+{
207+ return !label_.empty();
208+}
209+
210+bool PanelIndicatorAppmenuView::IsIconSensitive() const
211+{
212+ return has_menu_;
213+}
214+
215+bool PanelIndicatorAppmenuView::IsIconVisible() const
216+{
217+ return has_menu_;
218+}
219+
220+void PanelIndicatorAppmenuView::SetLabel(std::string const& label)
221+{
222+ if (label_ != label)
223+ {
224+ label_ = label;
225+ SetVisible(!label_.empty());
226+ Refresh();
227+ }
228+}
229+
230+void PanelIndicatorAppmenuView::SetControlledWindow(Window xid)
231+{
232+ if (xid_ != xid)
233+ {
234+ xid_ = xid;
235+ SetVisible(xid_ != 0);
236+ CheckWindowMenu();
237+ }
238+}
239+
240+bool PanelIndicatorAppmenuView::CheckWindowMenu()
241+{
242+ /* FIXME this is a temporary workaround */
243+ has_menu_ = true;
244+ glib::Object<BamfMatcher> matcher(bamf_matcher_get_default());
245+ BamfWindow *win = bamf_matcher_get_active_window(matcher);
246+
247+ if (BAMF_IS_WINDOW(win))
248+ {
249+ if (xid_ == bamf_window_get_xid(win))
250+ {
251+ has_menu_ = proxy_->image_sensitive();
252+ }
253+ }
254+
255+ /* FIXME re-enable this when all the clients will support the APPMENU atom.
256+ has_menu_ = false;
257+
258+ if (!xid_)
259+ return false;
260+
261+ glib::Object<BamfMatcher> matcher(bamf_matcher_get_default());
262+
263+ GList* windows = bamf_matcher_get_windows(matcher);
264+
265+ for (GList* l = windows; l; l = l->next)
266+ {
267+ if (BAMF_IS_WINDOW(l->data))
268+ {
269+ auto window = static_cast<BamfWindow*>(l->data);
270+
271+ if (bamf_window_get_xid(window) == xid_)
272+ {
273+ glib::String property(bamf_window_get_utf8_prop(window, MENU_ATOM.c_str()));
274+ has_menu_ = bool(property);
275+ break;
276+ }
277+ }
278+ }
279+
280+ g_list_free(windows);*/
281+
282+ return has_menu_;
283+}
284+
285+void PanelIndicatorAppmenuView::DrawEntryPrelight(cairo_t* cr, unsigned int width, unsigned int height)
286+{
287+ nux::Rect const& geo = proxy_->geometry();
288+
289+ if (geo == nux::Geometry())
290+ return;
291+
292+ GtkStyleContext* style_context = panel::Style::Instance().GetStyleContext();
293+ int flair_width = std::min(geo.width, GetMinimumWidth());
294+
295+ cairo_translate (cr, geo.x - GetAbsoluteX(), geo.y - height);
296+
297+ gtk_style_context_save(style_context);
298+
299+ GtkWidgetPath* widget_path = gtk_widget_path_new();
300+ gtk_widget_path_iter_set_name(widget_path, -1 , "UnityPanelWidget");
301+ gtk_widget_path_append_type(widget_path, GTK_TYPE_MENU_BAR);
302+ gtk_widget_path_append_type(widget_path, GTK_TYPE_MENU_ITEM);
303+
304+ gtk_style_context_set_path(style_context, widget_path);
305+ gtk_style_context_add_class(style_context, GTK_STYLE_CLASS_MENUBAR);
306+ gtk_style_context_add_class(style_context, GTK_STYLE_CLASS_MENUITEM);
307+ gtk_style_context_set_state(style_context, GTK_STATE_FLAG_PRELIGHT);
308+
309+ cairo_save(cr);
310+ cairo_push_group(cr);
311+
312+ gtk_render_background(style_context, cr, 0, 0, flair_width, height);
313+ gtk_render_frame(style_context, cr, 0, 0, flair_width, height);
314+
315+ cairo_pattern_t* pat = cairo_pop_group(cr);
316+ cairo_pattern_t* mask = cairo_pattern_create_linear(0, 0, 0, height);
317+ cairo_pattern_add_color_stop_rgba(mask, 0.0f, 0, 0, 0, 0.0f);
318+ cairo_pattern_add_color_stop_rgba(mask, 0.6f, 0, 0, 0, 0.0f);
319+ cairo_pattern_add_color_stop_rgba(mask, 1.0f, 0, 0, 0, 1.0f);
320+
321+ cairo_rectangle(cr, 0, 0, flair_width, height);
322+ cairo_set_source(cr, pat);
323+ cairo_mask(cr, mask);
324+
325+ cairo_pattern_destroy(pat);
326+ cairo_pattern_destroy(mask);
327+ cairo_restore(cr);
328+
329+ gtk_widget_path_free(widget_path);
330+
331+ gtk_style_context_restore(style_context);
332+}
333+
334+std::string PanelIndicatorAppmenuView::GetName() const
335+{
336+ return "Appmenu";
337+}
338+
339+void PanelIndicatorAppmenuView::AddProperties(GVariantBuilder* builder)
340+{
341+ PanelIndicatorEntryView::AddProperties(builder);
342+
343+ variant::BuilderWrapper(builder)
344+ .add("controlled-window", xid_)
345+ .add("has_menu", has_menu_);
346+}
347+
348+} // NAMESPACE
349
350=== added file 'plugins/unityshell/src/PanelIndicatorAppmenuView.h'
351--- plugins/unityshell/src/PanelIndicatorAppmenuView.h 1970-01-01 00:00:00 +0000
352+++ plugins/unityshell/src/PanelIndicatorAppmenuView.h 2012-04-18 08:58:24 +0000
353@@ -0,0 +1,68 @@
354+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
355+/*
356+ * Copyright (C) 2012 Canonical Ltd
357+ *
358+ * This program is free software: you can redistribute it and/or modify
359+ * it under the terms of the GNU General Public License version 3 as
360+ * published by the Free Software Foundation.
361+ *
362+ * This program is distributed in the hope that it will be useful,
363+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
364+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
365+ * GNU General Public License for more details.
366+ *
367+ * You should have received a copy of the GNU General Public License
368+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
369+ *
370+ * Authored by: Marco Trevisan (Treviño) <3v1n0@ubuntu.com>
371+ */
372+
373+#ifndef PANEL_INDICATOR_APPMENU_VIEW_H
374+#define PANEL_INDICATOR_APPMENU_VIEW_H
375+
376+#include <Nux/Nux.h>
377+#include <Nux/BaseWindow.h>
378+
379+#include "PanelIndicatorEntryView.h"
380+
381+namespace unity
382+{
383+using indicator::Entry;
384+
385+class PanelIndicatorAppmenuView : public PanelIndicatorEntryView
386+{
387+public:
388+ PanelIndicatorAppmenuView(Entry::Ptr const& proxy);
389+
390+ std::string GetLabel();
391+ void SetLabel(std::string const& label);
392+ bool IsLabelVisible() const;
393+ bool IsLabelSensitive() const;
394+
395+ bool IsIconVisible() const;
396+ bool IsIconSensitive() const;
397+
398+ void GetGeometryForSync(indicator::EntryLocationMap& locations);
399+
400+ void SetControlledWindow(Window xid);
401+
402+ void Activate(int button = 1);
403+
404+protected:
405+ std::string GetName() const;
406+ void AddProperties(GVariantBuilder* builder);
407+
408+ void ShowMenu(int button);
409+ void DrawEntryPrelight(cairo_t* cr, unsigned int w, unsigned int h);
410+
411+private:
412+ bool CheckWindowMenu();
413+
414+ Window xid_;
415+ bool has_menu_;
416+ std::string label_;
417+};
418+
419+}
420+
421+#endif // PANEL_INDICATOR_APPMENU_VIEW_H
422
423=== modified file 'plugins/unityshell/src/PanelIndicatorEntryView.cpp'
424--- plugins/unityshell/src/PanelIndicatorEntryView.cpp 2012-04-10 01:30:04 +0000
425+++ plugins/unityshell/src/PanelIndicatorEntryView.cpp 2012-04-18 08:58:24 +0000
426@@ -72,7 +72,7 @@
427
428 InputArea::SetAcceptMouseWheelEvent(true);
429
430- if (type_ != MENU)
431+ if (type_ != MENU && type_ != APPMENU)
432 InputArea::mouse_wheel.connect(sigc::mem_fun(this, &PanelIndicatorEntryView::OnMouseWheel));
433
434 panel::Style::Instance().changed.connect(sigc::mem_fun(this, &PanelIndicatorEntryView::Refresh));
435@@ -275,7 +275,7 @@
436 {
437 gtk_style_context_set_state(style_context, GTK_STATE_FLAG_BACKDROP);
438 }
439- else if (IsActive())
440+ else if (IsActive() && type_ != APPMENU)
441 {
442 gtk_style_context_set_state(style_context, GTK_STATE_FLAG_PRELIGHT);
443 }
444@@ -344,7 +344,7 @@
445 {
446 gtk_style_context_set_state(style_context, GTK_STATE_FLAG_BACKDROP);
447 }
448- else if (IsActive())
449+ else if (IsActive() && type_ != APPMENU)
450 {
451 gtk_style_context_set_state(style_context, GTK_STATE_FLAG_PRELIGHT);
452 }
453@@ -358,7 +358,10 @@
454 {
455 cairo_pattern_t* linpat;
456 int out_pixels = text_width - text_space;
457- const int fading_pixels = 15;
458+ int fading_pixels = 20;
459+
460+ if (type_ == APPMENU)
461+ fading_pixels = 35;
462
463 int fading_width = out_pixels < fading_pixels ? out_pixels : fading_pixels;
464
465@@ -448,6 +451,15 @@
466 PangoFontDescription* desc = nullptr;
467 PanelItem panel_item = (type_ == MENU) ? PanelItem::MENU : PanelItem::INDICATOR;
468
469+ if (type_ == MENU)
470+ {
471+ panel_item = PanelItem::INDICATOR;
472+ }
473+ else if (type_ == APPMENU)
474+ {
475+ panel_item = PanelItem::TITLE;
476+ }
477+
478 Style& panel_style = Style::Instance();
479 std::string const& font_description = panel_style.GetFontDescription(panel_item);
480 int dpi = panel_style.GetTextDPI();
481@@ -475,8 +487,15 @@
482
483 pango_layout_set_font_description(layout, desc);
484
485- boost::erase_all(label, "_");
486- pango_layout_set_text(layout, label.c_str(), -1);
487+ if (type_ == APPMENU)
488+ {
489+ pango_layout_set_markup(layout, label.c_str(), -1);
490+ }
491+ else
492+ {
493+ boost::erase_all(label, "_");
494+ pango_layout_set_text(layout, label.c_str(), -1);
495+ }
496
497 cxt = pango_layout_get_context(layout);
498 pango_cairo_context_set_font_options(cxt, gdk_screen_get_font_options(screen));
499
500=== modified file 'plugins/unityshell/src/PanelIndicatorEntryView.h'
501--- plugins/unityshell/src/PanelIndicatorEntryView.h 2012-04-10 00:30:33 +0000
502+++ plugins/unityshell/src/PanelIndicatorEntryView.h 2012-04-18 08:58:24 +0000
503@@ -43,6 +43,7 @@
504 enum IndicatorEntryType {
505 INDICATOR,
506 MENU,
507+ APPMENU,
508 OTHER
509 };
510
511
512=== modified file 'plugins/unityshell/src/PanelIndicatorsView.cpp'
513--- plugins/unityshell/src/PanelIndicatorsView.cpp 2012-04-03 16:01:38 +0000
514+++ plugins/unityshell/src/PanelIndicatorsView.cpp 2012-04-18 08:58:24 +0000
515@@ -111,6 +111,17 @@
516 return indicators_;
517 }
518
519+bool
520+PanelIndicatorsView::IsAppmenu()
521+{
522+ if (indicators_.size() == 1 && indicators_[0]->IsAppmenu())
523+ {
524+ return true;
525+ }
526+
527+ return false;
528+}
529+
530 void
531 PanelIndicatorsView::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
532 {
533
534=== modified file 'plugins/unityshell/src/PanelIndicatorsView.h'
535--- plugins/unityshell/src/PanelIndicatorsView.h 2012-04-02 10:25:16 +0000
536+++ plugins/unityshell/src/PanelIndicatorsView.h 2012-04-18 08:58:24 +0000
537@@ -66,6 +66,8 @@
538 void SetOpacity(double opacity);
539 double GetOpacity();
540
541+ bool IsAppmenu();
542+
543 void SetMaximumEntriesWidth(int max_width);
544 void GetGeometryForSync(indicator::EntryLocationMap& locations);
545
546
547=== modified file 'plugins/unityshell/src/PanelMenuView.cpp'
548--- plugins/unityshell/src/PanelMenuView.cpp 2012-04-16 12:12:05 +0000
549+++ plugins/unityshell/src/PanelMenuView.cpp 2012-04-18 08:58:24 +0000
550@@ -29,6 +29,7 @@
551 #include "UScreen.h"
552
553 #include <UnityCore/Variant.h>
554+#include <UnityCore/AppmenuIndicator.h>
555
556 #include <glib/gi18n-lib.h>
557
558@@ -51,9 +52,11 @@
559
560 PanelMenuView::PanelMenuView()
561 : _matcher(bamf_matcher_get_default()),
562+ _is_integrated(false),
563 _is_inside(false),
564 _is_grabbed(false),
565 _is_maximized(false),
566+ _integrated_menu(nullptr),
567 _last_active_view(nullptr),
568 _new_application(nullptr),
569 _overlay_showing(false),
570@@ -181,6 +184,7 @@
571 _fade_out_animator.animation_updated.clear();
572 _fade_out_animator.animation_ended.clear();
573 _style_changed_connection.disconnect();
574+ _mode_changed_connection.disconnect();
575
576 if (_active_moved_id)
577 g_source_remove(_active_moved_id);
578@@ -207,6 +211,40 @@
579 QueueDraw();
580 }
581
582+void PanelMenuView::SetIntegrated(bool integrated)
583+{
584+ if (_is_integrated == integrated)
585+ return;
586+
587+ _is_integrated = integrated;
588+ panel::Style::Instance().integrated_menus = _is_integrated;
589+
590+ if (!_is_integrated)
591+ {
592+ auto mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord();
593+ _is_inside = GetAbsoluteGeometry().IsInside(mouse);
594+
595+ _window_buttons->SetFocusedState(true);
596+ _window_buttons->SetControlledWindow(_is_maximized ? _active_xid : 0);
597+
598+ _integrated_menu = nullptr;
599+ }
600+ else
601+ {
602+ Window maximized = GetMaximizedWindow();
603+ _window_buttons->SetFocusedState(maximized == _active_xid);
604+ _window_buttons->SetControlledWindow(maximized);
605+ }
606+
607+ Refresh(true);
608+ FullRedraw();
609+}
610+
611+bool PanelMenuView::IsIntegrated() const
612+{
613+ return _is_integrated;
614+}
615+
616 void PanelMenuView::AddIndicator(indicator::Indicator::Ptr const& indicator)
617 {
618 if (!GetIndicators().empty())
619@@ -216,6 +254,27 @@
620 }
621
622 PanelIndicatorsView::AddIndicator(indicator);
623+
624+ if (indicator->IsAppmenu())
625+ {
626+ auto appmenuindicator = dynamic_cast<indicator::AppmenuIndicator*>(indicator.get());
627+
628+ if (appmenuindicator)
629+ {
630+ SetIntegrated(appmenuindicator->IsIntegrated());
631+
632+ _mode_changed_connection =
633+ appmenuindicator->integrated_changed.connect(sigc::mem_fun(this, &PanelMenuView::SetIntegrated));
634+ }
635+ }
636+}
637+
638+void PanelMenuView::RemoveIndicator(indicator::Indicator::Ptr const& indicator)
639+{
640+ PanelIndicatorsView::RemoveIndicator(indicator);
641+
642+ if (indicator->IsAppmenu())
643+ _mode_changed_connection.disconnect();
644 }
645
646 void PanelMenuView::SetMenuShowTimings(int fadein, int fadeout, int discovery,
647@@ -271,7 +330,7 @@
648 return _titlebar_grab_area;
649 }
650
651- if (_is_maximized)
652+ if (_is_maximized || (_is_integrated && GetMaximizedWindow()))
653 {
654 if (_window_buttons)
655 {
656@@ -284,6 +343,18 @@
657 {
658 found_area = _titlebar_grab_area->FindAreaUnderMouse(mouse_position, event_type);
659 NUX_RETURN_VALUE_IF_NOTNULL(found_area, found_area);
660+
661+ /* When the integrated menus are enabled, that area must act both like an
662+ * indicator-entry view and like a panel-grab-area, so not to re-implement
663+ * what we have done into PanelTitleGrabAreaView inside PanelIndicatorAppmenuView
664+ * we can just redirect the input events directed to the integrated menus
665+ * to the grab_area, then we just have to use few tricks when we get the
666+ * signals back from the grab-area to check where they really were */
667+ if (_is_integrated && _integrated_menu)
668+ {
669+ if (_integrated_menu->GetAbsoluteGeometry().IsInside(mouse_position))
670+ return _titlebar_grab_area;
671+ }
672 }
673
674 return PanelIndicatorsView::FindAreaUnderMouse(mouse_position, event_type);
675@@ -338,6 +409,16 @@
676 auto wm = WindowManager::Default();
677 bool screen_grabbed = (wm->IsExpoActive() || wm->IsScaleActive());
678
679+ if (_is_integrated && _integrated_menu)
680+ {
681+ if (!_overlay_showing && !screen_grabbed)
682+ {
683+ return (GetMaximizedWindow() != 0);
684+ }
685+
686+ return false;
687+ }
688+
689 if (_we_control_active && !_overlay_showing && !screen_grabbed &&
690 !_switcher_showing && !_launcher_keynav)
691 {
692@@ -358,6 +439,16 @@
693 if (_overlay_showing)
694 return true;
695
696+ if (_is_integrated)
697+ {
698+ if (!screen_grabbed)
699+ {
700+ return (GetMaximizedWindow() != 0);
701+ }
702+
703+ return false;
704+ }
705+
706 if (_we_control_active && _is_maximized && !screen_grabbed &&
707 !_launcher_keynav && !_switcher_showing)
708 {
709@@ -528,7 +619,8 @@
710 {
711 double title_opacity = 0.0f;
712
713- if (_we_control_active && _window_buttons->GetOpacity() == 0.0 &&
714+ if ((_we_control_active || (_is_integrated && !draw_menus)) &&
715+ _window_buttons->GetOpacity() == 0.0 &&
716 (!has_menu || (has_menu && GetOpacity() == 0.0)))
717 {
718 title_opacity = 1.0f;
719@@ -610,7 +702,7 @@
720
721 _fade_in_animator.Stop();
722
723- if (!_new_app_menu_shown)
724+ if (_is_integrated || !_new_app_menu_shown)
725 {
726 _fade_out_animator.Start(1.0f - GetOpacity());
727 }
728@@ -711,6 +803,36 @@
729 return label;
730 }
731
732+std::string PanelMenuView::GetMaximizedViewName(bool use_appname) const
733+{
734+ Window maximized = GetMaximizedWindow();
735+ BamfWindow* window = nullptr;
736+ std::string label;
737+
738+ window = GetBamfWindowForXid(maximized);
739+
740+ if (BAMF_IS_WINDOW(window) && IsWindowUnderOurControl(maximized))
741+ {
742+ BamfView* view = reinterpret_cast<BamfView*>(window);
743+ label = glib::String(bamf_view_get_name(view)).Str();
744+
745+ if (use_appname || label.empty())
746+ {
747+ BamfApplication* app = bamf_matcher_get_application_for_window(_matcher, window);
748+
749+ if (BAMF_IS_APPLICATION(app))
750+ view = reinterpret_cast<BamfView*>(app);
751+
752+ label = glib::String(bamf_view_get_name(view)).Str();
753+ }
754+ }
755+
756+ if (label.empty() && _is_integrated && !DrawMenus() && _integrated_menu)
757+ label = _desktop_name;
758+
759+ return label;
760+}
761+
762 void PanelMenuView::DrawTitle(cairo_t *cr_real, nux::Geometry const& geo, std::string const& label) const
763 {
764 using namespace panel;
765@@ -829,13 +951,34 @@
766 {
767 new_title = "";
768 }
769+ else if (_is_integrated)
770+ {
771+ Window maximized = GetMaximizedWindow();
772+ new_title = GetMaximizedViewName();
773+
774+ _window_buttons->SetControlledWindow(maximized);
775+ _window_buttons->SetFocusedState(_active_xid == maximized);
776+
777+ if (_integrated_menu)
778+ {
779+ _integrated_menu->SetControlledWindow(maximized);
780+
781+ if (DrawMenus())
782+ {
783+ _integrated_menu->SetLabel(new_title);
784+ _integrated_menu->SetFocusedState(_active_xid == maximized);
785+
786+ return;
787+ }
788+ }
789+ }
790 else if (!_switcher_showing && !_launcher_keynav)
791 {
792 new_title = GetActiveViewName();
793 _window_buttons->SetControlledWindow(_active_xid);
794 }
795
796- if (!_switcher_showing && !_launcher_keynav)
797+ if ((!_switcher_showing && !_launcher_keynav) || _is_integrated)
798 {
799 if (_panel_title != new_title)
800 {
801@@ -894,9 +1037,23 @@
802 {
803 PanelIndicatorEntryView* view;
804
805- view = new PanelIndicatorEntryView(entry, MENU_ENTRIES_PADDING, IndicatorEntryType::MENU);
806- view->mouse_enter.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseEnter));
807- view->mouse_leave.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseLeave));
808+ if (!_is_integrated)
809+ {
810+ view = new PanelIndicatorEntryView(entry, MENU_ENTRIES_PADDING, IndicatorEntryType::MENU);
811+ view->mouse_enter.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseEnter));
812+ view->mouse_leave.connect(sigc::mem_fun(this, &PanelMenuView::OnPanelViewMouseLeave));
813+ }
814+ else
815+ {
816+ if (_integrated_menu)
817+ {
818+ LOG_ERROR(logger) << "Another integrated menu has already been defined, this shouldn't happen!";
819+ }
820+
821+ _integrated_menu = new PanelIndicatorAppmenuView(entry);
822+ view = _integrated_menu;
823+ Refresh();
824+ }
825
826 entry->show_now_changed.connect(sigc::mem_fun(this, &PanelMenuView::UpdateShowNow));
827 view->active_changed.connect(sigc::mem_fun(this, &PanelMenuView::OnActiveChanged));
828@@ -904,13 +1061,24 @@
829 AddEntryView(view, IndicatorEntryPosition::END);
830 }
831
832+void PanelMenuView::OnEntryRemoved(std::string const& entry_id)
833+{
834+ if (_integrated_menu && _integrated_menu->GetEntryID() == entry_id)
835+ _integrated_menu = nullptr;
836+
837+ RemoveEntry(entry_id);
838+}
839+
840 void PanelMenuView::NotifyAllMenusClosed()
841 {
842 _last_active_view = nullptr;
843
844- auto mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord();
845- _is_inside = GetAbsoluteGeometry().IsInside(mouse);
846- FullRedraw();
847+ if (!_is_integrated)
848+ {
849+ auto mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord();
850+ _is_inside = GetAbsoluteGeometry().IsInside(mouse);
851+ FullRedraw();
852+ }
853 }
854
855 void PanelMenuView::OnNameChanged(BamfView* bamf_view, gchar* new_name, gchar* old_name)
856@@ -1009,7 +1177,7 @@
857 BamfApplication* old_app,
858 BamfApplication* new_app)
859 {
860- if (BAMF_IS_APPLICATION(new_app))
861+ if (BAMF_IS_APPLICATION(new_app) && !_is_integrated)
862 {
863 if (std::find(_new_apps.begin(), _new_apps.end(), new_app) != _new_apps.end())
864 {
865@@ -1097,7 +1265,10 @@
866 _view_name_changed_signal.Connect(new_view, "name-changed",
867 sigc::mem_fun(this, &PanelMenuView::OnNameChanged));
868
869- _window_buttons->SetControlledWindow(_is_maximized ? _active_xid : 0);
870+ if (!_is_integrated)
871+ {
872+ _window_buttons->SetControlledWindow(_is_maximized ? _active_xid : 0);
873+ }
874 }
875
876 Refresh();
877@@ -1213,9 +1384,12 @@
878
879 if (is_active)
880 {
881- // We need to update the _is_inside state in the case of maximization by grab
882- auto mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord();
883- _is_inside = GetAbsoluteGeometry().IsInside(mouse);
884+ if (!_is_integrated)
885+ {
886+ // We need to update the _is_inside state in the case of maximization by grab
887+ auto mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord();
888+ _is_inside = GetAbsoluteGeometry().IsInside(mouse);
889+ }
890
891 _is_maximized = true;
892 updated = true;
893@@ -1229,7 +1403,7 @@
894
895 _maximized_set.insert(xid);
896
897- if (updated)
898+ if (updated || _is_integrated)
899 {
900 Refresh();
901 FullRedraw();
902@@ -1410,6 +1584,23 @@
903 {
904 WindowManager::Default()->Activate(maximized);
905 }
906+
907+ /* If the user clicked over the integrated_menu we need to adjust
908+ * the coordinates we got, because they're relative to the grab area,
909+ * but due to the workaround we used, the point clicked could be
910+ * also in the integrated-menu geometry, so we can easiliy set them
911+ * correctly to check where we are and to eventually activate the
912+ * integrated menu */
913+ if (_is_integrated && _integrated_menu)
914+ {
915+ x += _titlebar_grab_area->GetAbsoluteX();
916+ y += _titlebar_grab_area->GetAbsoluteY();
917+
918+ if (_integrated_menu->GetAbsoluteGeometry().IsPointInside(x, y))
919+ {
920+ _integrated_menu->Activate();
921+ }
922+ }
923 }
924
925 void PanelMenuView::OnMaximizedRestore(int x, int y)
926@@ -1468,6 +1659,17 @@
927 x += _titlebar_grab_area->GetAbsoluteX();
928 y += _titlebar_grab_area->GetAbsoluteY();
929
930+ /* If the user clicked over the integrated_menu we need to adjust
931+ * the coordinates again, because they are still relative to the grab area */
932+ if (_is_integrated && _integrated_menu)
933+ {
934+ if (_integrated_menu->GetAbsoluteGeometry().IsPointInside(x, y))
935+ {
936+ x += _integrated_menu->GetAbsoluteX();
937+ y += _integrated_menu->GetAbsoluteY();
938+ }
939+ }
940+
941 Window maximized = GetMaximizedWindow();
942
943 /* When the drag goes out from the Panel, start the real movement.
944@@ -1543,6 +1745,7 @@
945 PanelIndicatorsView::AddProperties(builder);
946
947 variant::BuilderWrapper(builder)
948+ .add("integrated", _is_integrated)
949 .add("mouse_inside", _is_inside)
950 .add("grabbed", _is_grabbed)
951 .add("active_win_maximized", _is_maximized)
952@@ -1574,7 +1777,7 @@
953
954 _switcher_showing = switcher_shown;
955
956- if (!_switcher_showing)
957+ if (!_switcher_showing && !_is_integrated)
958 {
959 auto mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord();
960 _is_inside = GetAbsoluteGeometry().IsInside(mouse);
961@@ -1619,8 +1822,11 @@
962
963 _launcher_keynav = false;
964
965- auto mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord();
966- _is_inside = GetAbsoluteGeometry().IsInside(mouse);
967+ if (!_is_integrated)
968+ {
969+ auto mouse = nux::GetGraphicsDisplay()->GetMouseScreenCoord();
970+ _is_inside = GetAbsoluteGeometry().IsInside(mouse);
971+ }
972
973 Refresh();
974 QueueDraw();
975@@ -1670,6 +1876,9 @@
976 * If the status is false, we just check that the menus entries are hidden
977 * and we remove any eventual delayed request */
978
979+ if (_is_integrated)
980+ return;
981+
982 if (!status && _show_now_activated)
983 {
984 _show_now_activated = false;
985@@ -1726,7 +1935,18 @@
986 }
987
988 Window maximized = GetMaximizedWindow();
989- Window buttons_win = (maximized == _active_xid) ? maximized : 0;
990+ Window buttons_win = 0;
991+
992+ if (_is_integrated)
993+ {
994+ buttons_win = maximized;
995+ _window_buttons->SetFocusedState(maximized == _active_xid);
996+ }
997+ else
998+ {
999+ buttons_win = (maximized == _active_xid) ? maximized : 0;
1000+ _window_buttons->SetControlledWindow(buttons_win);
1001+ }
1002
1003 _window_buttons->SetMonitor(_monitor);
1004 _window_buttons->SetControlledWindow(buttons_win);
1005
1006=== modified file 'plugins/unityshell/src/PanelMenuView.h'
1007--- plugins/unityshell/src/PanelMenuView.h 2012-04-09 13:13:16 +0000
1008+++ plugins/unityshell/src/PanelMenuView.h 2012-04-18 08:58:24 +0000
1009@@ -28,6 +28,7 @@
1010 #include "PanelIndicatorsView.h"
1011 #include "StaticCairoText.h"
1012 #include "WindowButtons.h"
1013+#include "PanelIndicatorAppmenuView.h"
1014 #include "PanelTitlebarGrabAreaView.h"
1015 #include "PluginAdapter.h"
1016 #include "Animator.h"
1017@@ -47,14 +48,17 @@
1018
1019 void SetMousePosition(int x, int y);
1020 void SetMonitor(int monitor);
1021+ void SetIntegrated(bool integrated);
1022
1023 Window GetTopWindow() const;
1024 Window GetMaximizedWindow() const;
1025 bool GetControlsActive() const;
1026+ bool IsIntegrated() const;
1027
1028 void NotifyAllMenusClosed();
1029
1030 virtual void AddIndicator(indicator::Indicator::Ptr const& indicator);
1031+ virtual void RemoveIndicator(indicator::Indicator::Ptr const& indicator);
1032
1033 virtual void OverlayShown();
1034 virtual void OverlayHidden();
1035@@ -69,6 +73,7 @@
1036 virtual nux::Area* FindAreaUnderMouse(const nux::Point& mouse_position,
1037 nux::NuxEventType event_type);
1038 virtual void OnEntryAdded(indicator::Entry::Ptr const& entry);
1039+ virtual void OnEntryRemoved(std::string const& entry_id);
1040
1041 private:
1042 void OnActiveChanged(PanelIndicatorEntryView* view, bool is_active);
1043@@ -110,6 +115,7 @@
1044
1045 BamfWindow* GetBamfWindowForXid(Window xid) const;
1046
1047+ std::string GetMaximizedViewName(bool use_appname = false) const;
1048 std::string GetActiveViewName(bool use_appname = false) const;
1049
1050 void OnSwitcherShown(GVariant* data);
1051@@ -141,10 +147,12 @@
1052 nux::ObjectPtr<nux::BaseTexture> _title_texture;
1053 nux::ObjectPtr<nux::IOpenGLBaseTexture> _gradient_texture;
1054
1055+ bool _is_integrated;
1056 bool _is_inside;
1057 bool _is_grabbed;
1058 bool _is_maximized;
1059
1060+ PanelIndicatorAppmenuView* _integrated_menu;
1061 PanelIndicatorEntryView* _last_active_view;
1062 WindowButtons* _window_buttons;
1063 PanelTitlebarGrabArea* _titlebar_grab_area;
1064@@ -178,6 +186,7 @@
1065 glib::Signal<void, BamfMatcher*, BamfApplication*, BamfApplication*> _active_app_changed_signal;
1066 glib::Signal<void, BamfView*, gchar*, gchar*> _view_name_changed_signal;
1067 sigc::connection _style_changed_connection;
1068+ sigc::connection _mode_changed_connection;
1069
1070 UBusManager _ubus_manager;
1071
1072
1073=== modified file 'plugins/unityshell/src/PanelStyle.cpp'
1074--- plugins/unityshell/src/PanelStyle.cpp 2012-04-02 09:34:58 +0000
1075+++ plugins/unityshell/src/PanelStyle.cpp 2012-04-18 08:58:24 +0000
1076@@ -61,6 +61,7 @@
1077
1078 Style::Style()
1079 : panel_height(24)
1080+ , integrated_menus(false)
1081 , _style_context(gtk_style_context_new())
1082 {
1083 if (style_instance)
1084
1085=== modified file 'plugins/unityshell/src/PanelStyle.h'
1086--- plugins/unityshell/src/PanelStyle.h 2012-03-30 13:01:12 +0000
1087+++ plugins/unityshell/src/PanelStyle.h 2012-04-18 08:58:24 +0000
1088@@ -77,6 +77,7 @@
1089 int GetTextDPI();
1090
1091 nux::Property<int> panel_height;
1092+ nux::Property<bool> integrated_menus;
1093
1094 sigc::signal<void> changed;
1095
1096
1097=== modified file 'plugins/unityshell/src/unityshell.cpp'
1098--- plugins/unityshell/src/unityshell.cpp 2012-04-15 10:44:39 +0000
1099+++ plugins/unityshell/src/unityshell.cpp 2012-04-18 08:58:24 +0000
1100@@ -2259,14 +2259,15 @@
1101 uScreen->setPanelShadowMatrix(matrix);
1102
1103 Window active_window = screen->activeWindow();
1104- if (window->id() == active_window && window->type() != CompWindowTypeDesktopMask)
1105+ bool integrated_menus = panel::Style::Instance().integrated_menus;
1106+ if (window->id() == active_window && window->type() != CompWindowTypeDesktopMask && !integrated_menus)
1107 {
1108 uScreen->paintPanelShadow(matrix);
1109 }
1110
1111 bool ret = gWindow->glDraw(matrix, attrib, region, mask);
1112
1113- if ((active_window == 0 || active_window == window->id()) &&
1114+ if ((active_window == 0 || active_window == window->id() || integrated_menus) &&
1115 (window->type() == CompWindowTypeDesktopMask))
1116 {
1117 uScreen->paintPanelShadow(matrix);
1118
1119=== modified file 'tests/test_indicator_appmenu.cpp'
1120--- tests/test_indicator_appmenu.cpp 2012-03-29 12:06:35 +0000
1121+++ tests/test_indicator_appmenu.cpp 2012-04-18 08:58:24 +0000
1122@@ -30,16 +30,74 @@
1123
1124 TEST(TestAppmenuIndicator, Construction)
1125 {
1126+ g_setenv("GSETTINGS_BACKEND", "memory", true);
1127+
1128 AppmenuIndicator indicator("indicator-appmenu");
1129
1130 EXPECT_EQ(indicator.name(), "indicator-appmenu");
1131 EXPECT_TRUE(indicator.IsAppmenu());
1132+ EXPECT_FALSE(indicator.IsIntegrated());
1133+}
1134+
1135+TEST(TestAppmenuIndicator, ConstructionIntegrated)
1136+{
1137+ g_setenv("GSETTINGS_BACKEND", "memory", true);
1138+
1139+ glib::Object<GSettings> gsettings(g_settings_new("com.canonical.indicator.appmenu"));
1140+ g_settings_set_string(gsettings, "menu-mode", "locally-integrated");
1141+
1142+ AppmenuIndicator indicator("indicator-appmenu-integrated");
1143+
1144+ EXPECT_EQ(indicator.name(), "indicator-appmenu-integrated");
1145+ EXPECT_TRUE(indicator.IsAppmenu());
1146+ EXPECT_TRUE(indicator.IsIntegrated());
1147+}
1148+
1149+TEST(TestAppmenuIndicator, IntegratedValue)
1150+{
1151+ g_setenv("GSETTINGS_BACKEND", "memory", true);
1152+
1153+ glib::Object<GSettings> gsettings(g_settings_new("com.canonical.indicator.appmenu"));
1154+ g_settings_set_string(gsettings, "menu-mode", "global");
1155+
1156+ AppmenuIndicator indicator("indicator-appmenu");
1157+ EXPECT_FALSE(indicator.IsIntegrated());
1158+
1159+ bool integrated_changed = false;
1160+ bool integrated_value = false;
1161+ indicator.integrated_changed.connect([&] (bool new_value) {
1162+ integrated_changed = true;
1163+ integrated_value = new_value;
1164+ });
1165+
1166+ g_settings_set_string(gsettings, "menu-mode", "locally-integrated");
1167+ EXPECT_TRUE(integrated_changed);
1168+ EXPECT_TRUE(integrated_value);
1169+ EXPECT_TRUE(indicator.IsIntegrated());
1170+
1171+ integrated_changed = false;
1172+ g_settings_set_string(gsettings, "menu-mode", "locally-integrated");
1173+ EXPECT_FALSE(integrated_changed);
1174+ EXPECT_TRUE(integrated_value);
1175+ EXPECT_TRUE(indicator.IsIntegrated());
1176+
1177+ integrated_changed = false;
1178+ g_settings_set_string(gsettings, "menu-mode", "global");
1179+ EXPECT_TRUE(integrated_changed);
1180+ EXPECT_FALSE(integrated_value);
1181+ EXPECT_FALSE(indicator.IsIntegrated());
1182 }
1183
1184 TEST(TestAppmenuIndicator, ShowAppmenu)
1185 {
1186+ g_setenv("GSETTINGS_BACKEND", "memory", true);
1187+
1188+ glib::Object<GSettings> gsettings(g_settings_new("com.canonical.indicator.appmenu"));
1189+ g_settings_set_string(gsettings, "menu-mode", "global");
1190+
1191 AppmenuIndicator indicator("indicator-appmenu");
1192
1193+ bool ret;
1194 bool signal_emitted = false;
1195 int show_x, show_y;
1196 unsigned int show_xid, show_timestamp;
1197@@ -54,7 +112,14 @@
1198 show_timestamp = timestamp;
1199 });
1200
1201- indicator.ShowAppmenu(123456789, 50, 100, 1328308554);
1202+ ret = indicator.ShowAppmenu(123456789, 50, 100, 1328063758);
1203+ EXPECT_FALSE(ret);
1204+ EXPECT_FALSE(signal_emitted);
1205+
1206+ g_settings_set_string(gsettings, "menu-mode", "locally-integrated");
1207+
1208+ ret = indicator.ShowAppmenu(123456789, 50, 100, 1328308554);
1209+ EXPECT_TRUE(ret);
1210 EXPECT_TRUE(signal_emitted);
1211
1212 EXPECT_EQ(show_xid, 123456789);