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

Proposed by Marco Trevisan (Treviño) on 2012-02-13
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 2012-02-13 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.
lp:~3v1n0/unity/lim-panel updated on 2012-02-13
1970. By Marco Trevisan (Treviño) on 2012-02-13

Merging with trunk

1971. By Marco Trevisan (Treviño) on 2012-02-13

unityshell: always draw the destkop shadow when integrated menus are enabled.

1972. By Marco Trevisan (Treviño) on 2012-02-13

WindowButtons: don't leak memory when allocating the textures.

We need to use the ObjectPtr's Adopt facility here.

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".

lp:~3v1n0/unity/lim-panel updated on 2012-02-13
1973. By Marco Trevisan (Treviño) on 2012-02-13

PanelMenuView: remove the right layout padding

Otherwise there would be a small area at the right of the menus that won't be grabbable.

1974. By Marco Trevisan (Treviño) on 2012-02-13

UnityCore, Variant: added wrappers for long long types as well.

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...

lp:~3v1n0/unity/lim-panel updated on 2012-02-18
1975. By Marco Trevisan (Treviño) on 2012-02-13

PanelIndicatorEntryView: allow to define the spacing per each view.

1976. By Marco Trevisan (Treviño) on 2012-02-13

PanelIndicatorAppmenuView: reduced the spacing to 2px

1977. By Marco Trevisan (Treviño) on 2012-02-13

PanelIndicatorAppmenuView: including the has_menu property to the introspect.

1978. By Marco Trevisan (Treviño) on 2012-02-13

PanelMenuView: make sure that the window buttons are middle-aligned on the panel.

1979. By Marco Trevisan (Treviño) on 2012-02-13

PanelIndicatorAppmenuView: Consider the entry with when drawing the flair

When an entry is smaller than the opened menu, we have to draw a smaller flair.

Also using cairo_translate to correctly draw without being dependent on the source geometry.

1980. By Marco Trevisan (Treviño) on 2012-02-13

unityshell, resources: added the LIM flair assets from design

1981. By Marco Trevisan (Treviño) on 2012-02-13

PanelIndicatorEntryView: add support for left/right padding protected parameters

1982. By Marco Trevisan (Treviño) on 2012-02-13

PanelIndicatorAppmenuView: setting the right padding value to 7 pixels

The value has been computed using design mokups

1983. By Marco Trevisan (Treviño) on 2012-02-13

PanelMenuView: fix the items padding values according to the design specs

Making the panel pixel-perfect as well! ;)

1984. By Marco Trevisan (Treviño) on 2012-02-13

PanelMenuView: avoid to get an invalid maximized window

1985. By Marco Trevisan (Treviño) on 2012-02-16

Merging with LIM fixes from lp:~3v1n0/unity/lim

1986. By Marco Trevisan (Treviño) on 2012-02-16

PanelIndicatorEntryView: fixed compiler warning

1987. By Marco Trevisan (Treviño) on 2012-02-17

PanelStyle: implement unfocused/disabled state on GetWindowButtonForTheme

1988. By Marco Trevisan (Treviño) on 2012-02-17

PanelStyle: make GetFallbackWindowButton public

It was GetWindowButtonForTheme before.

1989. By Marco Trevisan (Treviño) on 2012-02-17

PanelStyle: add myself as author.

1990. By Marco Trevisan (Treviño) on 2012-02-17

PanelTitlebarGrabAreaView: ignore the grabs if during the timeout we got a small movement

Adding movement tolerance to the grab, if we have a grab of just few pixels
during the first timeout duration, let's just ignore them.

As design wanted.

1991. By Marco Trevisan (Treviño) on 2012-02-17

PanelIndicatorAppmenuView: use the Cimi's cairo flair instead of the asset

Thanks

1992. By Marco Trevisan (Treviño) on 2012-02-18

WindowManager: add some utility functions to handle window geometries

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.

1993. By Marco Trevisan (Treviño) on 2012-02-18

PanelMenuView: Make the grabbing of a maximized window from the panel better.

 - The window is be restored as soon as the mouse pointer drags content outside
   the panel area.
 - Once a window is restored it is not placed outside the desktop area,
   unless it fits into it, also it is never below the launcher (when visible).
   In the case that the window is bigger than the available space,
   the top and left borders should be always visible anyway.
 - The just restored window, is grabbed on a point of the top decoration
   that is proportional to the x-offset grabbed on the panel, so if you start
   dragging at the left of the panel, the window is handled by the top-left
   corner, if you start dragging on the right of the panel, the window is
   proportionally handled on the right; this applies only with LIM enabled.
   When LIMs are disabled, we just prefer the decoration middle point.

Added also misc improvements to the PanelMenuView code.

1994. By Marco Trevisan (Treviño) on 2012-02-18

Panel*.h classes, move introspection methods in protect field.

1995. By Marco Trevisan (Treviño) on 2012-02-18

Unione con il tronco... [cit. Jason]

1996. By Marco Trevisan (Treviño) on 2012-02-18

PanelStyle: fallback-buttons, handle the case of an unfocused close button

1997. By Marco Trevisan (Treviño) on 2012-02-18

PanelMenuView: update the layout padding on sytle changes, according to buttons size

1998. By Marco Trevisan (Treviño) on 2012-02-18

PanelStyle: fallback buttons, make them smaller, except for HighContrast themes

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.

lp:~3v1n0/unity/lim-panel updated on 2012-02-20
1999. By Marco Trevisan (Treviño) on 2012-02-20

PanelMenuView: restore a grabbed window, handling it in a position relative to the panel size

So this is shared between integrated and global modes.

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! ;)

lp:~3v1n0/unity/lim-panel updated on 2012-04-18
2000. By Marco Trevisan (Treviño) on 2012-02-20

WindowButtons: improved a lot the code, using more the WindowButtons container

2001. By Marco Trevisan (Treviño) on 2012-02-21

WindowButtons: add one more button for restore state, and swap it with the maximize one

Also handle internally the maximization / restore of the dash.

2002. By Marco Trevisan (Treviño) on 2012-02-22

PanelMenuView: make the WindowButtons handle their operation, just update their xid

2003. By Marco Trevisan (Treviño) on 2012-02-22

WindowManager: add getter to check if a window is minimizable.

2004. By Marco Trevisan (Treviño) on 2012-02-22

WindowButtons: if the managed window is not minimizable, disable the minimize button

2005. By Marco Trevisan (Treviño) on 2012-02-22

WindowButton: no need to add an extra _enabled variable, ViewEnabled can be enough

We need the nux branch lp:~3v1n0/nux/view-enable-logic-fix to be merged
as well.

2006. By Marco Trevisan (Treviño) on 2012-02-22

PanelIndicators: don't activate them if unfocused or invisible on mouse-over

2007. By Marco Trevisan (Treviño) on 2012-02-22

PanelIndicatorEntryView: sync geometries also for unfocused items.

It could gives wrong results when opening an unfocused menu.

2008. By Marco Trevisan (Treviño) on 2012-02-22

PanelView: cleanup the API

2009. By Marco Trevisan (Treviño) on 2012-02-22

PanelView: no need to resync on remote synced signal, entries will notify the panel

2010. By Marco Trevisan (Treviño) on 2012-02-22

PanelView: move to UBusWrapper

2011. By Marco Trevisan (Treviño) on 2012-02-22

PanelView: some more cleanup

2012. By Marco Trevisan (Treviño) on 2012-02-22

PanelMenuView: no need to register interest for dash status, let's use the parent

2013. By Marco Trevisan (Treviño) on 2012-02-22

PanelMenuView: use geometry in DrawText

2014. By Marco Trevisan (Treviño) on 2012-02-22

PanelView -> PanelIndicatorAppmenu: don't always open menus on keyboard shortcuts

We need to check that the current appmenu is actually focused.

2015. By Marco Trevisan (Treviño) on 2012-02-22

Merging with trunk

2016. By Marco Trevisan (Treviño) on 2012-02-22

PanelMenuView: removing unneeded includes

2017. By Marco Trevisan (Treviño) on 2012-02-22

PanelIndicatorEntryView: don't try to draw an invalid flair, and re-draw it

Flair wasn't drawn anymore... Fixing it, and possible glitches.

2018. By Marco Trevisan (Treviño) on 2012-02-23

PanelView: add monitor getter.

2019. By Marco Trevisan (Treviño) on 2012-02-23

Merging trunk

2020. By Marco Trevisan (Treviño) on 2012-02-23

PanelView: always set the monitor.

2021. By Marco Trevisan (Treviño) on 2012-02-23

unityshell: Alt+F10 should be triggeted on ButtonPress.

2022. By Marco Trevisan (Treviño) on 2012-02-23

PanelIndicatorsView: don't activate an unfocused entry on keyboard Alt+F10

2023. By Marco Trevisan (Treviño) on 2012-02-24

Merging with lp:~3v1n0/unity/lim

2024. By Marco Trevisan (Treviño) on 2012-02-24

PanelView: fix the evil red panel

It happened with bluish backgrounds... Damned double/float conversion! ;)

2025. By Marco Trevisan (Treviño) on 2012-02-24

PanelIndicatorAppmenuView: add a workaround to disable the menus only on few cases

Right now it's better to stop the false-negatives more than the false-positives

2026. By Marco Trevisan (Treviño) on 2012-02-25

PanelService: merging with lp:~3v1n0/lim fixes

2027. By Marco Trevisan (Treviño) on 2012-02-25

PanelView: On opacity toggle redraw the panel on expo changes

Fixes bug #940683

2028. By Marco Trevisan (Treviño) on 2012-02-25

PanelTitlebarGrabAreaView: increase the mouse-down timeout to 150ms

2029. By Marco Trevisan (Treviño) on 2012-02-25

PanelTitlebarGrabAreaView: return gboolean FALSE instead of bool false on timeout

2030. By Marco Trevisan (Treviño) on 2012-02-25

WindowButtons: put win-buttons into the unity namespace.

2031. By Marco Trevisan (Treviño) on 2012-02-25

WindowButton: add UpdateSize function to define the maximum button size

2032. By Marco Trevisan (Treviño) on 2012-02-25

WindowButtons: make the buttons more Fitt's law conformant.

2033. By Marco Trevisan (Treviño) on 2012-02-25

WindowButtons: manually manage the clicks on the buttons to be more Fitts conformant

The window buttons are now put into the layout to manage their position
automatically, but we redirect the mouse events over them
to be more conformant to the Fitt's law.

2034. By Marco Trevisan (Treviño) on 2012-02-25

Merging trunk

2035. By Marco Trevisan (Treviño) on 2012-02-25

Merging with lp:~3v1n0/unity/lim

2036. By Marco Trevisan (Treviño) on 2012-02-25

Pushing back removed changes

2037. By Marco Trevisan (Treviño) on 2012-02-26

PanelTray: main code cleanup, hopefully fix crashes

2038. By Marco Trevisan (Treviño) on 2012-02-26

PanelTray: update whitelist value on runtime.

2039. By Marco Trevisan (Treviño) on 2012-02-29

Merging with trunk

2040. By Marco Trevisan (Treviño) on 2012-03-01

PanelIndicatorEntryView: improve the drawing of collapsed menus

Consider the right_marging as well.

2041. By Marco Trevisan (Treviño) on 2012-03-01

PanelIndicatorsView: make each menu entry to use the most space it really can

When setting the maximium width for the entries, we shouold care of the
current sizes. So basically, if an entry doesn't need to be resized,
we can just take its width and remove it from the maximum space we have,
then the space that the other entries can use, is computed using the
remaining space.

This improves a lot the entries collapsing, and make sure that we always
use all the horizontal space that we have.

2042. By Marco Trevisan (Treviño) on 2012-03-02

Panel: add more debug introspection informations

2043. By Marco Trevisan (Treviño) on 2012-03-02

PanelMenuView: use PanelIndicatorsView as base for introspection data

2044. By Marco Trevisan (Treviño) on 2012-03-02

PanelIndicatorAppmenuView: use area visibility as well.

Disable the appmenu when not in use.

2045. By Marco Trevisan (Treviño) on 2012-03-02

PanelMenuView: reduce the risk of getting an empty panel

2046. By Marco Trevisan (Treviño) on 2012-03-02

PanelIndicatorAppmenuView: set invisible by default.

2047. By Marco Trevisan (Treviño) on 2012-03-02

PanelMenuView: improve debugging strings

2048. By Marco Trevisan (Treviño) on 2012-03-02

PanelMenuView: take care of the workarea x when dragging down a window.

Fixes the restored position in a multimonitor setup.

2049. By Marco Trevisan (Treviño) on 2012-03-02

PanelView: don't allow to open menus in an inactive PanelMenuView

2050. By Marco Trevisan (Treviño) on 2012-03-02

Merging with trunk

2051. By Marco Trevisan (Treviño) on 2012-03-06

Merging with trunk

2052. By Marco Trevisan (Treviño) on 2012-03-08

LauncherController: send UBus messages when the launcher selection has changed

2053. By Marco Trevisan (Treviño) on 2012-03-08

PanelMenuView: show the selected icon name on the panel during key navigation

Also, avoid to generate textures with empty labels, just nullify it

2054. By Marco Trevisan (Treviño) on 2012-03-08

LauncherController: send the right ubus message depending on the key navigation type

2055. By Marco Trevisan (Treviño) on 2012-03-08

PanelMenuView: also connect to the key-switcher ubus events

2056. By Marco Trevisan (Treviño) on 2012-03-08

PanelMenuView: call the right function on launcher switcher end

2057. By Marco Trevisan (Treviño) on 2012-03-08

PanelMenuView: add GetTopWindow method to get the top valid window, even if not in focus

Added also utility functions such as GetBamfWindowForXid and IsValidWindow
to get a BamfView or to check if a window can be handled by us.

We use the GetTopWindow to get the top view when an invalid one (an unity)
window is focused.

2058. By Marco Trevisan (Treviño) on 2012-03-09

PanelMenuView: reset the _new_application if it points to an invalid application

2059. By Marco Trevisan (Treviño) on 2012-03-09

PanelMenuView: add OnApplicationClosed function, to avoid casts

Also added more controls to avoid un-hidden menus.

2060. By Marco Trevisan (Treviño) on 2012-03-09

PanelMenuView: put return types on the same line of the function name

2061. By Marco Trevisan (Treviño) on 2012-03-09

PluginAdapter: add some more spacing, to improve readability

2062. By Marco Trevisan (Treviño) on 2012-03-10

LauncherController: emit the right keynav signal

2063. By Marco Trevisan (Treviño) on 2012-03-10

unityshell: listen also the launcher switcher signals

2064. By Marco Trevisan (Treviño) on 2012-03-10

Merging with changes in lp:~3v1n0/unity/lim

2065. By Marco Trevisan (Treviño) on 2012-03-19

Merging with newer lp:~3v1n0/unity/lim

2066. By Marco Trevisan (Treviño) on 2012-03-19

PanelIndicatorAppmenuView: don't sync our geometry if not focused

This will make the unity-panel-service correctly handle
the keyboard navigation.

2067. By Marco Trevisan (Treviño) on 2012-03-20

Merging with latest trunk.

2068. By Marco Trevisan (Treviño) on 2012-03-20

PanelView: putting back some changes lost during merges

2069. By Marco Trevisan (Treviño) on 2012-03-20

PanelTray: don't crash when unplugging a monitor.

2070. By Marco Trevisan (Treviño) on 2012-03-20

PanelTray: remove the idle before destroying the window.

Let's be paranoid! ;)

2071. By Marco Trevisan (Treviño) on 2012-03-29

PanelMenuView: don't draw anything on the panel located into a monitor that doesn't control the active window

2072. By Marco Trevisan (Treviño) on 2012-03-29

PanelMenuView: when we don't control the active window, all clicks are over the grab area

2073. By Marco Trevisan (Treviño) on 2012-03-29

PanelMenuView: use nux::Rect.IsInside where possible

2074. By Marco Trevisan (Treviño) on 2012-03-29

PluginAdapter: window's can't be obscured by window in different screens.

Checking the geometry, though.

2075. By Marco Trevisan (Treviño) on 2012-03-29

PanelMenuView: use Window type for windows.

2076. By Marco Trevisan (Treviño) on 2012-03-29

Merging with trunk

2077. By Marco Trevisan (Treviño) on 2012-03-29

Panel: s/Dash/Overlay/g

2078. By Marco Trevisan (Treviño) on 2012-03-29

unityshell: typo: s/showPanelFirstMenuKeyInitiate/showPanelFirstMenuKeyTerminate/

2079. By Marco Trevisan (Treviño) on 2012-03-29

WindowButtons: don't be confused by different overlays

Now switching from Dash to Hud and back works. See bug #963118

2080. By Marco Trevisan (Treviño) on 2012-03-29

PanelView: remove useless methods

2081. By Marco Trevisan (Treviño) on 2012-03-29

PanelIndicatorsView: removed the "layout workaround", NUX likes us now!

The menu/indicators layout can safely be kept and handled as the view's
layout, this saves us by doing unwanted workarounds and to just
manage its geometry.

This also fixes an issue with multimonitor, that caused menus on
other monitors not to be clickable.

2082. By Marco Trevisan (Treviño) on 2012-03-29

Merging with the panel-rework branch, readding LIMs

2083. By Marco Trevisan (Treviño) on 2012-04-18

Merging with new trunk ;)

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);