Merge lp:~azzar1/unity/shortcut-hint into lp:unity

Proposed by Andrea Azzarone
Status: Merged
Approved by: Andrea Azzarone
Approved revision: no longer in the source branch.
Merged at revision: 1833
Proposed branch: lp:~azzar1/unity/shortcut-hint
Merge into: lp:unity
Diff against target: 2326 lines (+2055/-7)
25 files modified
plugins/unityshell/src/AbstractSeparator.cpp (+68/-0)
plugins/unityshell/src/AbstractSeparator.h (+49/-0)
plugins/unityshell/src/AbstractShortcutHint.h (+102/-0)
plugins/unityshell/src/BackgroundEffectHelper.cpp (+1/-1)
plugins/unityshell/src/LineSeparator.cpp (+73/-0)
plugins/unityshell/src/LineSeparator.h (+44/-0)
plugins/unityshell/src/MockShortcutHint.h (+72/-0)
plugins/unityshell/src/ShortcutController.cpp (+194/-0)
plugins/unityshell/src/ShortcutController.h (+87/-0)
plugins/unityshell/src/ShortcutHint.cpp (+137/-0)
plugins/unityshell/src/ShortcutHint.h (+53/-0)
plugins/unityshell/src/ShortcutHintPrivate.cpp (+79/-0)
plugins/unityshell/src/ShortcutHintPrivate.h (+39/-0)
plugins/unityshell/src/ShortcutModel.cpp (+60/-0)
plugins/unityshell/src/ShortcutModel.h (+64/-0)
plugins/unityshell/src/ShortcutView.cpp (+424/-0)
plugins/unityshell/src/ShortcutView.h (+93/-0)
plugins/unityshell/src/unityshell.cpp (+99/-1)
plugins/unityshell/src/unityshell.h (+9/-1)
plugins/unityshell/unityshell.xml.in (+6/-0)
standalone-clients/CMakeLists.txt (+26/-3)
standalone-clients/TestShortcut.cpp (+109/-0)
tests/CMakeLists.txt (+9/-1)
tests/test_shortcut_model.cpp (+84/-0)
tests/test_shortcut_private.cpp (+74/-0)
To merge this branch: bzr merge lp:~azzar1/unity/shortcut-hint
Reviewer Review Type Date Requested Status
Marco Trevisan (Treviño) Approve
John Lea (community) design Approve
Tim Penhey (community) Approve
Review via email: mp+85575@code.launchpad.net

This proposal supersedes a proposal from 2011-12-07.

Description of the change

Display a shortcut hints overlay during the super key pressing.

It includes two unit tests and a standalone test.

Mockup: https://launchpadlibrarian.net/85352653/Super_key_shutcuts_overlay.png
Branch: http://ubuntuone.com/7cqBbWAbvXTRCT4ySFj7z4

Visual diff: http://ubuntuone.com/014zDKCoxaQYmtm8mS5pp8

Keep in mind that something is different because the shortcuts values are not hardcoded.

To post a comment you must log in.
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote : Posted in a previous version of this proposal

I've just looked at few things but it seem good, however remember to unregister the ubus controller (i.e as done in lp:~vanvugt/unity/fix-887465-trunk ) in ~Controller and to use g_markup_escape_text ;).

Revision history for this message
Andrea Azzarone (azzar1) wrote : Posted in a previous version of this proposal

Marco you should not review a WIP :P

> I've just looked at few things but it seem good, however remember to unregister the ubus controller (i.e as done in lp:~vanvugt/unity/fix-887465-trunk )

Thanks for tip.

> and to use g_markup_escape_text ;).

We no longer need it ;)

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote : Posted in a previous version of this proposal

That was not a review, just a comment! :)

Revision history for this message
Jeremy Bícha (jbicha) wrote : Posted in a previous version of this proposal

Hi, I hope you don't mind me giving feedback on the wording choices since it's still WIP...

Please use Trash instead of Rubbish Bin; the en_GB translation can change it back to Rubbish Bin.

The verb should consistently add the trailing "s" or not. In other words, "open" or "opens". For the Ubuntu system help, we left off the "s" but it could just as easily go the other way.

I'd like to see the keyboard keys always capitalized; I think some are stored as lowercase in metacity or whatever, but for display you should be able to upper-case them. ("Super + s" should be "Super + S").

How about "arrow keys" instead of "cursor keys"?

I believe menu bar is slightly preferred over top bar.

Revision history for this message
Andrea Azzarone (azzar1) wrote : Posted in a previous version of this proposal
Revision history for this message
Marco Biscaro (marcobiscaro2112) wrote : Posted in a previous version of this proposal

Another comment :) there is a typo here:

+ hints_.push_back(new shortcut::Hint(_("Switching"), "", "", _("Moves the foucs."), shortcut::HARDCODED_OPTION, _("Cursor Left & Right")));

Revision history for this message
Tim Penhey (thumper) wrote : Posted in a previous version of this proposal

another comment, since this isn't yet a review :-)

properties should be lower case.

Revision history for this message
Tim Penhey (thumper) wrote :

Hi Andy,

Can you add links for the design mockup, and a picture of what is
rendered with this branch?

Cheers,
Tim

Revision history for this message
Tim Penhey (thumper) wrote :

Purely visual review:

The mockup lines are not white, but either transparent white or
transparent grey. The headings of each group are also not white.

The lines in the mockup are 1px thin grey with distinct ends. The view
has thicker lines that are brighter that taper at the ends.

The white-space above the "Windows" header is greater than the rest.

Some of the key-bindings are lower case, why is that?

Why are we missing some of the key bindings, like moving the focused
window to other workspaces?

Tim

review: Needs Information
Revision history for this message
Andrea Azzarone (azzar1) wrote :

> Purely visual review:
>
> The mockup lines are not white, but either transparent white or
> transparent grey. The headings of each group are also not white.
>
> The lines in the mockup are 1px thin grey with distinct ends. The view
> has thicker lines that are brighter that taper at the ends.
>

I'll look to it.

>
> The white-space above the "Windows" header is greater than the rest.
>

Yeah, because i've commented a couple of key bindings because they are not yet implemented.

>
> Some of the key-bindings are lower case, why is that?
>

Because Compiz CompOption gives me something like that: <Super>f... I've writed a very simple function to change it in "Super + f". I think the best solution is to capitalize each word of the shortcut.

> Why are we missing some of the key bindings, like moving the focused
> window to other workspaces?

As said, some options are not yet implmented. For example, regarding "Move focused window to different workspace" I can't find it in CCSM.

Revision history for this message
John Lea (johnlea) wrote :

Looking great! ;-) However there are a few minor issues that need to be fixed before this lands.

The feedback below is based on comparing the implementation screenshot posted with the following designs:
- https://launchpadlibrarian.net/85352653/Super_key_shutcuts_overlay.png (the design itself)
- https://launchpadlibrarian.net/86861725/keyboard_shortcuts_sizes.png (the grid the design is build on)

Items in need of fixing:

1. The divider lines should by 10% opacity (while remaining 100% white)

2. The divider should start flush with text, and end flush with grid (see grid design above)

3. The divider lines should have flat ends

4. The spacing of the title "Keyboard Shortcuts" is slightly out, should have slightly more space above than below (see design)

5. The spacing of the section titles is slightly out, should have slightly more space above each title than below (see design)

6. The shortcuts need updating to exactly match those specified in the following document https://docs.google.com/a/canonical.com/document/d/1jqeKtIJwqLtl58Wk_fqjr9Rrgxn9zsouCYOo-cZsLSE/edit?authkey=CLGG9NkJ&hl=en_GB

Once these are fixed we are good to go, thx!

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

> > Why are we missing some of the key bindings, like moving the focused
> > window to other workspaces?
>
> As said, some options are not yet implmented. For example, regarding "Move
> focused window to different workspace" I can't find it in CCSM.

It's under desktop wall -> bindings -> Move with window within wall

Plus, I put here for reference as well, the bottom edge has some issues here:
 - http://ubuntuone.com/5bB2px39meddmAtL4bomM2

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

> 6. The shortcuts need updating to exactly match those specified in the
> following document https://docs.google.com/a/canonical.com/document/d
> /1jqeKtIJwqLtl58Wk_fqjr9Rrgxn9zsouCYOo-cZsLSE/edit?authkey=CLGG9NkJ&hl=en_GB

About the Alt+` shortcut... As it depends to the keyboard layout (i.e. in the Italian we have Alt+\ in fact), I guess that it should be localized...

Revision history for this message
Andrea Azzarone (azzar1) wrote :

> Looking great! ;-) However there are a few minor issues that need to be fixed
> before this lands.
>
> The feedback below is based on comparing the implementation screenshot posted
> with the following designs:
> - https://launchpadlibrarian.net/85352653/Super_key_shutcuts_overlay.png (the
> design itself)
> - https://launchpadlibrarian.net/86861725/keyboard_shortcuts_sizes.png (the
> grid the design is build on)
>
> Items in need of fixing:
>
> 1. The divider lines should by 10% opacity (while remaining 100% white)
>

Done.

> 2. The divider should start flush with text, and end flush with grid (see grid
> design above)

Done.

>
> 3. The divider lines should have flat ends

Done.

>
> 4. The spacing of the title "Keyboard Shortcuts" is slightly out, should have
> slightly more space above than below (see design)
>

Done.

> 5. The spacing of the section titles is slightly out, should have slightly
> more space above each title than below (see design)

Done.

>
> 6. The shortcuts need updating to exactly match those specified in the
> following document https://docs.google.com/a/canonical.com/document/d
> /1jqeKtIJwqLtl58Wk_fqjr9Rrgxn9zsouCYOo-cZsLSE/edit?authkey=CLGG9NkJ&hl=en_GB
>
> Once these are fixed we are good to go, thx!

I'll do it tomorrow.

Revision history for this message
Andrea Azzarone (azzar1) wrote :

Ok ready for the review. I've fixed something in the layout but I don't know if I've fixed the Marco's problem. Marco can you test it please? If you still have the same problem, can you check your DPI?

Revision history for this message
Tim Penhey (thumper) wrote :

A general pass over the code and it seems OK, but nothing in UnityCore.

review: Approve
Revision history for this message
John Lea (johnlea) wrote :

awesome, everything perfect, great to see a attached .png with the visual design matched up against the implementation.

thanks!

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

I've just checked again this branch, but I still get that visual issue that I've already mentioned :(

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

I'm working on a branch dependent on this (lp:~3v1n0/unity/unity-dialog), working to fix the issue I got.

So, approving.

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

Attempt to merge into lp:unity failed due to conflicts:

text conflict in standalone-clients/CMakeLists.txt

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'plugins/unityshell/src/AbstractSeparator.cpp'
2--- plugins/unityshell/src/AbstractSeparator.cpp 1970-01-01 00:00:00 +0000
3+++ plugins/unityshell/src/AbstractSeparator.cpp 2012-01-13 15:39:27 +0000
4@@ -0,0 +1,68 @@
5+/*
6+ * Copyright (C) 2011 Canonical Ltd
7+ *
8+ * This program is free software: you can redistribute it and/or modify
9+ * it under the terms of the GNU General Public License version 3 as
10+ * published by the Free Software Foundation.
11+ *
12+ * This program is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ * GNU General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU General Public License
18+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
19+ *
20+ * Authored by: Jay Taoko <jaytaoko@inalogic.com>
21+ *
22+ */
23+
24+#include "AbstractSeparator.h"
25+
26+#include "Nux/Nux.h"
27+
28+namespace unity
29+{
30+
31+AbstractSeparator::AbstractSeparator(NUX_FILE_LINE_DECL)
32+ : nux::View(NUX_FILE_LINE_PARAM)
33+ , color_(nux::color::White)
34+ , alpha0_(0.0f)
35+ , alpha1_(0.10f)
36+ , border_size_(0)
37+{
38+}
39+
40+// Maybe it's better to use default arguments?
41+AbstractSeparator::AbstractSeparator(nux::Color const& color, float alpha0,
42+ float alpha1, int border, NUX_FILE_LINE_DECL)
43+ : nux::View(NUX_FILE_LINE_PARAM)
44+ , color_(color)
45+ , alpha0_(alpha0)
46+ , alpha1_(alpha1)
47+ , border_size_(border)
48+{
49+}
50+
51+AbstractSeparator::~AbstractSeparator()
52+{
53+
54+}
55+
56+void AbstractSeparator::SetColor(nux::Color const &color)
57+{
58+ color_ = color;
59+}
60+
61+void AbstractSeparator::SetAlpha(float alpha0, float alpha1)
62+{
63+ alpha0_ = alpha0;
64+ alpha1_ = alpha1;
65+}
66+
67+void AbstractSeparator::SetBorderSize(int border)
68+{
69+ border_size_ = border;
70+}
71+
72+} // namespace unity
73
74=== added file 'plugins/unityshell/src/AbstractSeparator.h'
75--- plugins/unityshell/src/AbstractSeparator.h 1970-01-01 00:00:00 +0000
76+++ plugins/unityshell/src/AbstractSeparator.h 2012-01-13 15:39:27 +0000
77@@ -0,0 +1,49 @@
78+/*
79+ * Copyright (C) 2011 Canonical Ltd
80+ *
81+ * This program is free software: you can redistribute it and/or modify
82+ * it under the terms of the GNU General Public License version 3 as
83+ * published by the Free Software Foundation.
84+ *
85+ * This program is distributed in the hope that it will be useful,
86+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
87+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
88+ * GNU General Public License for more details.
89+ *
90+ * You should have received a copy of the GNU General Public License
91+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
92+ *
93+ * Authored by: Jay Taoko <jaytaoko@inalogic.com>
94+ *
95+ */
96+
97+#ifndef UNITYSHELL_ABSTRACTSEPARATOR_H
98+#define UNITYSHELL_ABSTRACTSEPARATOR_H
99+
100+#include <Nux/Nux.h>
101+#include <Nux/View.h>
102+
103+namespace unity
104+{
105+
106+class AbstractSeparator: public nux::View
107+{
108+public:
109+ AbstractSeparator(NUX_FILE_LINE_PROTO);
110+ AbstractSeparator(nux::Color const& color, float alpha0, float alpha1, int vorder, NUX_FILE_LINE_PROTO);
111+ ~AbstractSeparator();
112+
113+ void SetColor(nux::Color const& color);
114+ void SetAlpha(float alpha0, float alpha1);
115+ void SetBorderSize(int border);
116+
117+protected:
118+ nux::Color color_;
119+ float alpha0_;
120+ float alpha1_;
121+ int border_size_;
122+};
123+
124+} // namespace unity
125+
126+#endif // UNITYSHELL_ABSTRACTSEPARATOR_H
127
128=== added file 'plugins/unityshell/src/AbstractShortcutHint.h'
129--- plugins/unityshell/src/AbstractShortcutHint.h 1970-01-01 00:00:00 +0000
130+++ plugins/unityshell/src/AbstractShortcutHint.h 2012-01-13 15:39:27 +0000
131@@ -0,0 +1,102 @@
132+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
133+/*
134+ * Copyright (C) 2011 Canonical Ltd
135+ *
136+ * This program is free software: you can redistribute it and/or modify
137+ * it under the terms of the GNU General Public License version 3 as
138+ * published by the Free Software Foundation.
139+ *
140+ * This program is distributed in the hope that it will be useful,
141+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
142+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
143+ * GNU General Public License for more details.
144+ *
145+ * You should have received a copy of the GNU General Public License
146+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
147+ *
148+ * Authored by: Andrea Azzarone <azzaronea@gmail.com>
149+ */
150+
151+#ifndef UNITYSHELL_ABSTRACT_SHORTCUT_ICON_H
152+#define UNITYSHELL_ABSTRACT_SHORTCUT_ICON_H
153+
154+#include <string>
155+
156+#include <Nux/Nux.h>
157+#include <NuxCore/Property.h>
158+
159+namespace unity
160+{
161+namespace shortcut
162+{
163+
164+enum OptionType
165+{
166+ COMPIZ_KEY_OPTION = 0,
167+ COMPIZ_MOUSE_OPTION,
168+ HARDCODED_OPTION
169+ /* GSETTINGS_OPTION,
170+ * GCONF_OPTION */
171+};
172+
173+class AbstractHint
174+{
175+public:
176+ // Ctor
177+ AbstractHint(std::string const& category,
178+ std::string const& prefix,
179+ std::string const& postfix,
180+ std::string const& description,
181+ OptionType const type,
182+ std::string const& arg1,
183+ std::string const& arg2 = "",
184+ std::string const& arg3 = "")
185+ : category(category)
186+ , prefix(prefix)
187+ , postfix(postfix)
188+ , description(description)
189+ , type(type)
190+ , arg1(arg1)
191+ , arg2(arg2)
192+ , arg3(arg3)
193+ {
194+ }
195+
196+ // Copy ctor
197+ AbstractHint(unity::shortcut::AbstractHint const& obj)
198+ : category(obj.category())
199+ , prefix(obj.prefix())
200+ , postfix(obj.postfix())
201+ , description(obj.description())
202+ , type(obj.type())
203+ , arg1(obj.arg1())
204+ , arg2(obj.arg2())
205+ , arg3(obj.arg3())
206+ , value(obj.value())
207+ , shortkey(obj.shortkey())
208+ {
209+ }
210+
211+ // Dtor
212+ virtual ~AbstractHint(){};
213+
214+ // Public Methods
215+ virtual bool Fill() = 0;
216+
217+ // Properties
218+ nux::Property<std::string> category;
219+ nux::Property<std::string> prefix;
220+ nux::Property<std::string> postfix;
221+ nux::Property<std::string> description;
222+ nux::Property<OptionType> type;
223+ nux::Property<std::string> arg1;
224+ nux::Property<std::string> arg2;
225+ nux::Property<std::string> arg3;
226+ nux::Property<std::string> value;
227+ nux::Property<std::string> shortkey;
228+};
229+
230+} // namespace shortcut
231+} // namespace unity
232+
233+#endif // UNITYSHELL_ABSTRACT_SHORTCUT_ICON_H
234
235=== modified file 'plugins/unityshell/src/BackgroundEffectHelper.cpp'
236--- plugins/unityshell/src/BackgroundEffectHelper.cpp 2012-01-05 02:47:09 +0000
237+++ plugins/unityshell/src/BackgroundEffectHelper.cpp 2012-01-13 15:39:27 +0000
238@@ -72,7 +72,7 @@
239 {
240 for (BackgroundEffectHelper * bg_effect_helper : registered_list_)
241 {
242- if (bg_effect_helper->cache_dirty || !bg_effect_helper->owner)
243+ if (bg_effect_helper->cache_dirty || !bg_effect_helper->owner || !bg_effect_helper->enabled)
244 continue;
245
246 if (!geo.Intersect (bg_effect_helper->blur_geometry_).IsNull())
247
248=== added file 'plugins/unityshell/src/LineSeparator.cpp'
249--- plugins/unityshell/src/LineSeparator.cpp 1970-01-01 00:00:00 +0000
250+++ plugins/unityshell/src/LineSeparator.cpp 2012-01-13 15:39:27 +0000
251@@ -0,0 +1,73 @@
252+/*
253+ * Copyright (C) 2011 Canonical Ltd
254+ *
255+ * This program is free software: you can redistribute it and/or modify
256+ * it under the terms of the GNU General Public License version 3 as
257+ * published by the Free Software Foundation.
258+ *
259+ * This program is distributed in the hope that it will be useful,
260+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
261+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
262+ * GNU General Public License for more details.
263+ *
264+ * You should have received a copy of the GNU General Public License
265+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
266+ *
267+ * Authored by: Jay Taoko <jaytaoko@inalogic.com>
268+ *
269+ */
270+
271+#include "LineSeparator.h"
272+
273+#include "Nux/Nux.h"
274+
275+namespace unity
276+{
277+
278+HSeparator::HSeparator()
279+{
280+ SetMinimumHeight(1);
281+ SetMaximumHeight(1);
282+}
283+
284+HSeparator::HSeparator(nux::Color const& color, float alpha0, float alpha1, int border)
285+ : AbstractSeparator(color, alpha0, alpha1, border)
286+{
287+ SetMinimumHeight(1);
288+ SetMaximumHeight(1);
289+}
290+
291+HSeparator::~HSeparator()
292+{
293+}
294+
295+void HSeparator::Draw(nux::GraphicsEngine &GfxContext, bool force_draw)
296+{
297+ nux::Geometry base = GetGeometry();
298+ base.OffsetPosition(3, 0);
299+ base.OffsetSize(-6, 0);
300+ int y0 = base.y + base.GetHeight() / 2;
301+
302+ nux::GetGraphicsDisplay()->GetGraphicsEngine()->GetRenderStates().SetBlend(TRUE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
303+
304+ if (base.GetWidth() - 2 * border_size_ > 0)
305+ {
306+ nux::Color color0 = color_;
307+ nux::Color color1 = color_;
308+ color0.alpha = alpha0_;
309+ color1.alpha = alpha1_;
310+ nux::GetPainter().Draw2DLine(GfxContext, base.x, y0, base.x + border_size_, y0, color0, color1);
311+ nux::GetPainter().Draw2DLine(GfxContext, base.x + border_size_, y0, base.x + base.GetWidth() - border_size_, y0, color1, color1);
312+ nux::GetPainter().Draw2DLine(GfxContext, base.x + base.GetWidth() - border_size_, y0, base.x + base.GetWidth(), y0, color1, color0);
313+ }
314+ else
315+ {
316+ nux::Color color1 = color_;
317+ color1.alpha = alpha1_;
318+ nux::GetPainter().Draw2DLine(GfxContext, base.x, y0, base.x + base.GetWidth(), y0, color1, color1);
319+ }
320+
321+ nux::GetGraphicsDisplay()->GetGraphicsEngine()->GetRenderStates().SetBlend(FALSE);
322+}
323+
324+} // namespace unity
325
326=== added file 'plugins/unityshell/src/LineSeparator.h'
327--- plugins/unityshell/src/LineSeparator.h 1970-01-01 00:00:00 +0000
328+++ plugins/unityshell/src/LineSeparator.h 2012-01-13 15:39:27 +0000
329@@ -0,0 +1,44 @@
330+/*
331+ * Copyright (C) 2011 Canonical Ltd
332+ *
333+ * This program is free software: you can redistribute it and/or modify
334+ * it under the terms of the GNU General Public License version 3 as
335+ * published by the Free Software Foundation.
336+ *
337+ * This program is distributed in the hope that it will be useful,
338+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
339+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
340+ * GNU General Public License for more details.
341+ *
342+ * You should have received a copy of the GNU General Public License
343+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
344+ *
345+ * Authored by: Jay Taoko <jaytaoko@inalogic.com>
346+ *
347+ */
348+
349+#ifndef UNITYSHELL_HSEPARATOR_H
350+#define UNITYSHELL_HSEPARATOR_H
351+
352+#include "AbstractSeparator.h"
353+
354+namespace unity
355+{
356+
357+class HSeparator: public AbstractSeparator
358+{
359+public:
360+ HSeparator();
361+ HSeparator(nux::Color const& color, float alpha0, float alpha1, int border);
362+
363+ ~HSeparator();
364+
365+protected:
366+ virtual void Draw(nux::GraphicsEngine& GfxContext, bool force_draw);
367+ virtual void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw) {};
368+
369+};
370+
371+} // namespace unity
372+
373+#endif // UNITYSHELL_HSEPARATOR_H
374
375=== added file 'plugins/unityshell/src/MockShortcutHint.h'
376--- plugins/unityshell/src/MockShortcutHint.h 1970-01-01 00:00:00 +0000
377+++ plugins/unityshell/src/MockShortcutHint.h 2012-01-13 15:39:27 +0000
378@@ -0,0 +1,72 @@
379+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
380+/*
381+ * Copyright (C) 2011 Canonical Ltd
382+ *
383+ * This program is free software: you can redistribute it and/or modify
384+ * it under the terms of the GNU General Public License version 3 as
385+ * published by the Free Software Foundation.
386+ *
387+ * This program is distributed in the hope that it will be useful,
388+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
389+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
390+ * GNU General Public License for more details.
391+ *
392+ * You should have received a copy of the GNU General Public License
393+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
394+ *
395+ * Authored by: Andrea Azzarone <azzaronea@gmail.com>
396+ */
397+
398+#ifndef UNITYSHELL_MOCK_SHORTCUT_HINT_H
399+#define UNITYSHELL_MOCK_SHORTCUT_HINT_H
400+
401+#include "AbstractShortcutHint.h"
402+
403+namespace unity
404+{
405+namespace shortcut
406+{
407+
408+class MockHint : public AbstractHint
409+{
410+public:
411+ // Ctor and dtor
412+ MockHint(std::string const& category,
413+ std::string const& prefix,
414+ std::string const& postfix,
415+ std::string const& description,
416+ OptionType const type,
417+ std::string const& arg1,
418+ std::string const& arg2 = "",
419+ std::string const& arg3 = "")
420+ : AbstractHint(category, prefix, postfix, description, type, arg1, arg2, arg3)
421+ {
422+ }
423+
424+ ~MockHint() {};
425+
426+ // Methods...
427+ bool Fill()
428+ {
429+ switch (type())
430+ {
431+ case COMPIZ_MOUSE_OPTION:
432+ case COMPIZ_KEY_OPTION:
433+ value = arg1() + "-" + arg2();
434+ shortkey = prefix() + value() + postfix();
435+ return true;
436+
437+ case HARDCODED_OPTION:
438+ value = arg1();
439+ shortkey = prefix() + value() + postfix();
440+ return true;
441+ }
442+
443+ return false;
444+ }
445+};
446+
447+} // shortcut hint
448+} // namespace unity
449+
450+#endif // UNITYSHELL_MOCK_SHORTCUT_HINT_H
451
452=== added file 'plugins/unityshell/src/ShortcutController.cpp'
453--- plugins/unityshell/src/ShortcutController.cpp 1970-01-01 00:00:00 +0000
454+++ plugins/unityshell/src/ShortcutController.cpp 2012-01-13 15:39:27 +0000
455@@ -0,0 +1,194 @@
456+/*
457+ * Copyright (C) 2011 Canonical Ltd
458+ *
459+ * This program is free software: you can redistribute it and/or modify
460+ * it under the terms of the GNU General Public License version 3 as
461+ * published by the Free Software Foundation.
462+ *
463+ * This program is distributed in the hope that it will be useful,
464+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
465+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
466+ * GNU General Public License for more details.
467+ *
468+ * You should have received a copy of the GNU General Public License
469+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
470+ *
471+ * Authored by: Andrea Azzarone <azzaronea@gmail.com>
472+ */
473+
474+#include "ShortcutController.h"
475+
476+#include "UBusMessages.h"
477+#include "ubus-server.h"
478+#include "WindowManager.h"
479+
480+namespace unity
481+{
482+namespace shortcut
483+{
484+namespace
485+{
486+const unsigned int SUPER_TAP_DURATION = 650;
487+} // anonymouse namespace;
488+
489+Controller::Controller(std::list<AbstractHint*>& hints)
490+ : view_window_(0)
491+ , visible_(false)
492+ , show_timer_(0)
493+ , fade_in_animator_(new Animator(100))
494+ , fade_out_animator_(new Animator(100))
495+
496+{
497+ bg_color_ = nux::Color(0.0, 0.0, 0.0, 0.5);
498+
499+ UBusServer *ubus = ubus_server_get_default();
500+ bg_update_handle_ = ubus_server_register_interest(ubus, UBUS_BACKGROUND_COLOR_CHANGED,
501+ (UBusCallback)&Controller::OnBackgroundUpdate,
502+ this);
503+
504+ model_.reset(new Model(hints));
505+
506+ model_->Fill();
507+ ConstructView();
508+
509+ fade_in_animator_->animation_updated.connect(sigc::mem_fun(this, &Controller::OnFadeInUpdated));
510+ fade_in_animator_->animation_ended.connect(sigc::mem_fun(this, &Controller::OnFadeInEnded));
511+ fade_out_animator_->animation_updated.connect(sigc::mem_fun(this, &Controller::OnFadeOutUpdated));
512+ fade_out_animator_->animation_ended.connect(sigc::mem_fun(this, &Controller::OnFadeOutEnded));
513+}
514+
515+Controller::~Controller()
516+{
517+ ubus_server_unregister_interest(ubus_server_get_default(), bg_update_handle_);
518+
519+ if (fade_in_animator_)
520+ delete fade_in_animator_;
521+
522+ if (fade_out_animator_)
523+ delete fade_out_animator_;
524+
525+ if (view_window_)
526+ view_window_->UnReference();
527+
528+ view_.Release();
529+}
530+
531+
532+void Controller::OnFadeInUpdated(double opacity)
533+{
534+ view_window_->SetOpacity(opacity);
535+}
536+
537+void Controller::OnFadeInEnded()
538+{
539+ view_window_->SetOpacity(1.0);
540+}
541+
542+void Controller::OnFadeOutUpdated(double progress)
543+{
544+ double opacity = CLAMP(1.0f - progress, 0.0f, 1.0f);
545+ view_window_->SetOpacity(opacity);
546+}
547+
548+void Controller::OnFadeOutEnded()
549+{
550+ view_window_->SetOpacity(0.0);
551+}
552+
553+
554+void Controller::OnBackgroundUpdate(GVariant* data, Controller* self)
555+{
556+ gdouble red, green, blue, alpha;
557+ g_variant_get(data, "(dddd)", &red, &green, &blue, &alpha);
558+ self->bg_color_ = nux::Color(red, green, blue, alpha);
559+
560+ if (self->view_)
561+ self->view_->background_color = self->bg_color_;
562+}
563+
564+void Controller::Show()
565+{
566+ if (show_timer_)
567+ g_source_remove (show_timer_);
568+ show_timer_ = g_timeout_add(SUPER_TAP_DURATION, &Controller::OnShowTimer, this);
569+
570+ model_->Fill();
571+ visible_ = true;
572+}
573+
574+gboolean Controller::OnShowTimer(gpointer data)
575+{
576+ Controller* self = static_cast<Controller*>(data);
577+
578+ ubus_server_send_message(ubus_server_get_default(),
579+ UBUS_PLACE_VIEW_CLOSE_REQUEST,
580+ NULL);
581+
582+ if (self->visible_)
583+ {
584+ self->view_->SetupBackground(true);
585+ self->fade_out_animator_->Stop();
586+ self->fade_in_animator_->Start(self->view_window_->GetOpacity());
587+ }
588+
589+ self->show_timer_ = 0;
590+ return FALSE;
591+}
592+
593+void Controller::ConstructView()
594+{
595+ view_ = View::Ptr(new View());
596+ view_->SetModel(model_);
597+ view_->background_color = bg_color_;
598+
599+ if (!view_window_)
600+ {
601+ main_layout_ = new nux::HLayout(NUX_TRACKER_LOCATION);
602+ main_layout_->SetVerticalExternalMargin(0);
603+ main_layout_->SetHorizontalExternalMargin(0);
604+
605+ view_window_ = new nux::BaseWindow("ShortcutHint");
606+ view_window_->SinkReference();
607+ view_window_->SetLayout(main_layout_);
608+ view_window_->SetBackgroundColor(nux::Color(0x00000000));
609+ }
610+
611+ main_layout_->AddView(view_.GetPointer(), 1);
612+
613+ view_->SetupBackground(false);
614+ view_window_->SetOpacity(0.0);
615+ view_window_->ShowWindow(true);
616+}
617+
618+void Controller::SetWorkspace(nux::Geometry const& geo)
619+{
620+ workarea_ = geo;
621+ view_window_->SetGeometry(workarea_);
622+}
623+
624+void Controller::Hide()
625+{
626+ if (!visible_)
627+ return;
628+
629+ visible_ = false;
630+
631+ if (view_window_)
632+ {
633+ view_->SetupBackground(false);
634+ fade_in_animator_->Stop();
635+ fade_out_animator_->Start(1.0 - view_window_->GetOpacity());
636+ }
637+
638+ if (show_timer_)
639+ g_source_remove(show_timer_);
640+ show_timer_ = 0;
641+}
642+
643+bool Controller::Visible()
644+{
645+ return visible_;
646+}
647+
648+} // namespace shortcut
649+} // namespace unity
650
651=== added file 'plugins/unityshell/src/ShortcutController.h'
652--- plugins/unityshell/src/ShortcutController.h 1970-01-01 00:00:00 +0000
653+++ plugins/unityshell/src/ShortcutController.h 2012-01-13 15:39:27 +0000
654@@ -0,0 +1,87 @@
655+/*
656+ * Copyright (C) 2011 Canonical Ltd
657+ *
658+ * This program is free software: you can redistribute it and/or modify
659+ * it under the terms of the GNU General Public License version 3 as
660+ * published by the Free Software Foundation.
661+ *
662+ * This program is distributed in the hope that it will be useful,
663+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
664+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
665+ * GNU General Public License for more details.
666+ *
667+ * You should have received a copy of the GNU General Public License
668+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
669+ *
670+ * Authored by: Andrea Azzarone <azzaronea@gmail.com>
671+ */
672+
673+#ifndef UNITYSHELL_SHORTCUTCONTROLLER_H
674+#define UNITYSHELL_SHORTCUTCONTROLLER_H
675+
676+#include <boost/shared_ptr.hpp>
677+
678+#include <Nux/Nux.h>
679+#include <Nux/BaseWindow.h>
680+#include <Nux/HLayout.h>
681+#include <NuxCore/Color.h>
682+
683+#include "Animator.h"
684+#include "ShortcutModel.h"
685+#include "ShortcutView.h"
686+
687+namespace unity
688+{
689+namespace shortcut
690+{
691+
692+class Controller
693+{
694+public:
695+ typedef std::shared_ptr<Controller> Ptr;
696+
697+ // Ctor and dtor
698+ Controller(std::list<AbstractHint*>& hints);
699+ ~Controller();
700+
701+ // Public Methods
702+ void Show();
703+ void Hide();
704+
705+ bool Visible();
706+
707+ void SetWorkspace(nux::Geometry const& geo);
708+
709+private:
710+ // Private Methods
711+ void ConstructView();
712+ static void OnBackgroundUpdate(GVariant* data, Controller* self);
713+ void OnFadeInUpdated(double opacity);
714+ void OnFadeInEnded();
715+ void OnFadeOutUpdated(double opacity);
716+ void OnFadeOutEnded();
717+
718+ static gboolean OnShowTimer(gpointer data);
719+
720+ // Private Members
721+ View::Ptr view_;
722+ Model::Ptr model_;
723+
724+ nux::Geometry workarea_;
725+ nux::BaseWindow* view_window_;
726+ nux::HLayout* main_layout_;
727+
728+ bool visible_;
729+ nux::Color bg_color_;
730+ guint show_timer_;
731+ guint bg_update_handle_;
732+
733+ Animator* fade_in_animator_;
734+ Animator* fade_out_animator_;
735+};
736+
737+} // namespace shortcut
738+} // namespace unity
739+
740+#endif //UNITYSHELL_SHORTCUTHINTCONTROLLER_H
741+
742
743=== added file 'plugins/unityshell/src/ShortcutHint.cpp'
744--- plugins/unityshell/src/ShortcutHint.cpp 1970-01-01 00:00:00 +0000
745+++ plugins/unityshell/src/ShortcutHint.cpp 2012-01-13 15:39:27 +0000
746@@ -0,0 +1,137 @@
747+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
748+/*
749+ * Copyright (C) 2011 Canonical Ltd
750+ *
751+ * This program is free software: you can redistribute it and/or modify
752+ * it under the terms of the GNU General Public License version 3 as
753+ * published by the Free Software Foundation.
754+ *
755+ * This program is distributed in the hope that it will be useful,
756+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
757+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
758+ * GNU General Public License for more details.
759+ *
760+ * You should have received a copy of the GNU General Public License
761+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
762+ *
763+ * Authored by: Andrea Azzarone <azzaronea@gmail.com>
764+ */
765+
766+#include "ShortcutHint.h"
767+
768+#include <core/core.h> // Compiz...
769+#include <NuxCore/Logger.h>
770+
771+#include "ShortcutHintPrivate.h"
772+
773+namespace unity
774+{
775+namespace shortcut
776+{
777+namespace
778+{
779+ nux::logging::Logger logger("unity.shortcut");
780+} // anonymouse namespace
781+
782+// Ctor
783+Hint::Hint(std::string const& category,
784+ std::string const& prefix,
785+ std::string const& postfix,
786+ std::string const& description,
787+ OptionType const type,
788+ std::string const& arg1,
789+ std::string const& arg2,
790+ std::string const& arg3)
791+ : AbstractHint(category, prefix, postfix, description, type, arg1, arg2, arg3)
792+{
793+}
794+
795+// Dtor
796+Hint::~Hint()
797+{
798+}
799+
800+/*
801+ * Gets and fills the shortcut value.
802+ * Returns true if everything was OK, returns false otherwise.
803+ * Use member property Value to get it.
804+ */
805+bool Hint::Fill()
806+{
807+ switch(type())
808+ {
809+ case COMPIZ_MOUSE_OPTION:
810+ {
811+ // Arg1 = Plugin name
812+ // Arg2 = key Option name
813+ CompPlugin* p = CompPlugin::find(arg1().c_str());
814+
815+ if (!p)
816+ return false;
817+
818+ foreach (CompOption &opt, p->vTable->getOptions())
819+ {
820+ if (opt.name() == arg2())
821+ {
822+ std::string temp = impl::FixMouseShortcut(impl::FixShortcutFormat(opt.value().action().buttonToString()));
823+ temp = impl::ProperCase(temp);
824+
825+ if (value() != temp)
826+ {
827+ value = temp;
828+ shortkey = prefix() + value() + postfix();
829+ }
830+
831+ return true;
832+ }
833+ }
834+
835+ break;
836+ }
837+ break;
838+
839+ case COMPIZ_KEY_OPTION:
840+ {
841+ // Arg1 = Plugin name
842+ // Arg2 = key Option name
843+ CompPlugin* p = CompPlugin::find(arg1().c_str());
844+
845+ if (!p)
846+ return false;
847+
848+ foreach (CompOption &opt, p->vTable->getOptions())
849+ {
850+ if (opt.name() == arg2())
851+ {
852+ std::string temp = impl::FixShortcutFormat(opt.value().action().keyToString());
853+ temp = impl::ProperCase(temp);
854+
855+ if (value() != temp)
856+ {
857+ value = temp;
858+ shortkey = prefix() + value() + postfix();
859+ }
860+
861+ return true;
862+ }
863+ }
864+
865+ break;
866+ }
867+ case HARDCODED_OPTION:
868+ if (value != arg1())
869+ {
870+ value = arg1();
871+ shortkey = prefix() + value() + postfix();
872+ }
873+ return true;
874+
875+ default:
876+ LOG_WARNING(logger) << "Unable to find the option type" << type();
877+ }
878+
879+ return false;
880+}
881+
882+} // namespace shortcut
883+} // namespace unity
884
885=== added file 'plugins/unityshell/src/ShortcutHint.h'
886--- plugins/unityshell/src/ShortcutHint.h 1970-01-01 00:00:00 +0000
887+++ plugins/unityshell/src/ShortcutHint.h 2012-01-13 15:39:27 +0000
888@@ -0,0 +1,53 @@
889+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
890+/*
891+ * Copyright (C) 2011 Canonical Ltd
892+ *
893+ * This program is free software: you can redistribute it and/or modify
894+ * it under the terms of the GNU General Public License version 3 as
895+ * published by the Free Software Foundation.
896+ *
897+ * This program is distributed in the hope that it will be useful,
898+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
899+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
900+ * GNU General Public License for more details.
901+ *
902+ * You should have received a copy of the GNU General Public License
903+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
904+ *
905+ * Authored by: Andrea Azzarone <azzaronea@gmail.com>
906+ */
907+
908+#ifndef UNITYSHELL_SHORTCUTHINT_H
909+#define UNITYSHELL_SHORTCUTHINT_H
910+
911+#include "AbstractShortcutHint.h"
912+
913+namespace unity
914+{
915+namespace shortcut
916+{
917+
918+class Hint : public AbstractHint
919+{
920+public:
921+ // Ctor
922+ Hint(std::string const& category,
923+ std::string const& prefix,
924+ std::string const& postfix,
925+ std::string const& description,
926+ OptionType const type,
927+ std::string const& arg1,
928+ std::string const& arg2 = "",
929+ std::string const& arg3 = "");
930+
931+ // Dtor
932+ ~Hint();
933+
934+ // Public methods
935+ bool Fill();
936+};
937+
938+} // namespace shortcut
939+} // namespace unity
940+
941+ #endif // UNITYSHELL_SHORTCUTHINT_H
942
943=== added file 'plugins/unityshell/src/ShortcutHintPrivate.cpp'
944--- plugins/unityshell/src/ShortcutHintPrivate.cpp 1970-01-01 00:00:00 +0000
945+++ plugins/unityshell/src/ShortcutHintPrivate.cpp 2012-01-13 15:39:27 +0000
946@@ -0,0 +1,79 @@
947+/*
948+ * Copyright (C) 2011 Canonical Ltd
949+ *
950+ * This program is free software: you can redistribute it and/or modify
951+ * it under the terms of the GNU General Public License version 3 as
952+ * published by the Free Software Foundation.
953+ *
954+ * This program is distributed in the hope that it will be useful,
955+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
956+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
957+ * GNU General Public License for more details.
958+ *
959+ * You should have received a copy of the GNU General Public License
960+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
961+ *
962+ * Authored by: Andrea Azzarone <azzaronea@gmail.com>
963+ */
964+
965+#include "ShortcutHintPrivate.h"
966+
967+#include <boost/algorithm/string/replace.hpp>
968+
969+namespace unity
970+{
971+namespace shortcut
972+{
973+namespace impl
974+{
975+
976+std::string FixShortcutFormat(std::string const& scut)
977+{
978+ std::string ret(scut.begin(), scut.end() - 1);
979+
980+ boost::replace_all(ret, "<", "");
981+ boost::replace_all(ret, ">", " + ");
982+
983+ if (scut[scut.size()-1] != '>')
984+ ret += scut[scut.size()-1];
985+
986+ return ret;
987+}
988+
989+std::string FixMouseShortcut(std::string const& scut)
990+{
991+ std::string ret(scut);
992+
993+ boost::replace_all(ret, "Button1", "Left Mouse");
994+ boost::replace_all(ret, "Button2", "Middle Mouse");
995+ boost::replace_all(ret, "Button3", "Right Mouse");
996+
997+ return ret;
998+}
999+
1000+std::string ProperCase(std::string const& str)
1001+{
1002+ std::string ret = str;
1003+
1004+ bool cap_next = true;
1005+
1006+ for (unsigned int i = 0; i < ret.length(); ++i)
1007+ {
1008+ if (cap_next and isalpha(ret[i]))
1009+ {
1010+ ret[i]=toupper(ret[i]);
1011+ cap_next = false;
1012+ }
1013+ else
1014+ {
1015+ cap_next = ispunct(ret[i]) || isspace(ret[i]);
1016+ }
1017+ }
1018+
1019+ return ret;
1020+}
1021+
1022+} // namespace impl
1023+} // namespace shortcut
1024+} // namespace unity
1025+
1026
1027=== added file 'plugins/unityshell/src/ShortcutHintPrivate.h'
1028--- plugins/unityshell/src/ShortcutHintPrivate.h 1970-01-01 00:00:00 +0000
1029+++ plugins/unityshell/src/ShortcutHintPrivate.h 2012-01-13 15:39:27 +0000
1030@@ -0,0 +1,39 @@
1031+/*
1032+ * Copyright (C) 2011 Canonical Ltd
1033+ *
1034+ * This program is free software: you can redistribute it and/or modify
1035+ * it under the terms of the GNU General Public License version 3 as
1036+ * published by the Free Software Foundation.
1037+ *
1038+ * This program is distributed in the hope that it will be useful,
1039+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1040+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1041+ * GNU General Public License for more details.
1042+ *
1043+ * You should have received a copy of the GNU General Public License
1044+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1045+ *
1046+ * Authored by: Andrea Azzarone <azzaronea@gmail.com>
1047+ */
1048+
1049+#ifndef UNITYSHELL_SHORTCUT_HINT_PRIVATE_H
1050+#define UNITYSHELL_SHORTCUT_HINT_PRIVATE_H
1051+
1052+#include <string>
1053+
1054+namespace unity
1055+{
1056+namespace shortcut
1057+{
1058+namespace impl
1059+{
1060+
1061+std::string FixShortcutFormat(std::string const& scut);
1062+std::string FixMouseShortcut(std::string const& scut);
1063+std::string ProperCase(std::string const& str);
1064+
1065+} // namespace impl
1066+} // namespace shortcut
1067+} // namespace unity
1068+
1069+#endif // UNITYSHELL_SHORTCUT_HINT_PRIVATE_H
1070
1071=== added file 'plugins/unityshell/src/ShortcutModel.cpp'
1072--- plugins/unityshell/src/ShortcutModel.cpp 1970-01-01 00:00:00 +0000
1073+++ plugins/unityshell/src/ShortcutModel.cpp 2012-01-13 15:39:27 +0000
1074@@ -0,0 +1,60 @@
1075+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
1076+/*
1077+ * Copyright (C) 2011 Canonical Ltd
1078+ *
1079+ * This program is free software: you can redistribute it and/or modify
1080+ * it under the terms of the GNU General Public License version 3 as
1081+ * published by the Free Software Foundation.
1082+ *
1083+ * This program is distributed in the hope that it will be useful,
1084+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1085+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1086+ * GNU General Public License for more details.
1087+ *
1088+ * You should have received a copy of the GNU General Public License
1089+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1090+ *
1091+ * Authored by: Andrea Azzarone <azzaronea@gmail.com>
1092+ */
1093+
1094+#include "ShortcutModel.h"
1095+
1096+namespace unity
1097+{
1098+namespace shortcut
1099+{
1100+
1101+// Ctor
1102+Model::Model(std::list<AbstractHint*>& hints)
1103+{
1104+ for (auto hint : hints)
1105+ AddHint(hint);
1106+}
1107+
1108+// Dtor
1109+Model::~Model()
1110+{
1111+}
1112+
1113+
1114+void Model::AddHint(AbstractHint* hint)
1115+{
1116+ if (!hint)
1117+ return;
1118+
1119+ if (hints_.find(hint->category()) == hints_.end())
1120+ categories_.push_back(hint->category());
1121+
1122+ hints_[hint->category()].push_back(hint);
1123+}
1124+
1125+
1126+void Model::Fill()
1127+{
1128+ for (auto category : categories_)
1129+ for (auto item : hints_[category])
1130+ item->Fill();
1131+}
1132+
1133+} // namespace shortcut
1134+} // namespace unity
1135
1136=== added file 'plugins/unityshell/src/ShortcutModel.h'
1137--- plugins/unityshell/src/ShortcutModel.h 1970-01-01 00:00:00 +0000
1138+++ plugins/unityshell/src/ShortcutModel.h 2012-01-13 15:39:27 +0000
1139@@ -0,0 +1,64 @@
1140+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
1141+/*
1142+ * Copyright (C) 2011 Canonical Ltd
1143+ *
1144+ * This program is free software: you can redistribute it and/or modify
1145+ * it under the terms of the GNU General Public License version 3 as
1146+ * published by the Free Software Foundation.
1147+ *
1148+ * This program is distributed in the hope that it will be useful,
1149+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1150+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1151+ * GNU General Public License for more details.
1152+ *
1153+ * You should have received a copy of the GNU General Public License
1154+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1155+ *
1156+ * Authored by: Andrea Azzarone <azzaronea@gmail.com>
1157+ */
1158+
1159+#ifndef UNITYSHELL_SHORTCUSMODEL_H
1160+#define UNITYSHELL_SHORTCUSMODEL_H
1161+
1162+#include <boost/noncopyable.hpp>
1163+#include <map>
1164+#include <memory>
1165+#include <list>
1166+#include <string>
1167+#include <vector>
1168+
1169+#include "AbstractShortcutHint.h"
1170+
1171+namespace unity
1172+{
1173+namespace shortcut
1174+{
1175+
1176+class Model : boost::noncopyable
1177+{
1178+public:
1179+ typedef std::shared_ptr<Model> Ptr;
1180+
1181+ // Ctor and dtor
1182+ Model(std::list<AbstractHint*>& hints);
1183+ ~Model();
1184+
1185+ // Accessors
1186+ std::vector<std::string>& categories() { return categories_; }
1187+ std::map<std::string, std::list<AbstractHint*>>& hints() { return hints_; }
1188+
1189+ void Fill();
1190+
1191+private:
1192+ // Private functions
1193+ void AddHint(AbstractHint* hint);
1194+
1195+ // Private members
1196+ std::vector<std::string> categories_;
1197+ std::map<std::string, std::list<AbstractHint*>> hints_;
1198+};
1199+
1200+} // shortcut
1201+} // unity
1202+
1203+#endif // UNITYSHELL_SHORTCUTS_H
1204
1205=== added file 'plugins/unityshell/src/ShortcutView.cpp'
1206--- plugins/unityshell/src/ShortcutView.cpp 1970-01-01 00:00:00 +0000
1207+++ plugins/unityshell/src/ShortcutView.cpp 2012-01-13 15:39:27 +0000
1208@@ -0,0 +1,424 @@
1209+/*
1210+ * Copyright (C) 2011 Canonical Ltd
1211+ *
1212+ * This program is free software: you can redistribute it and/or modify
1213+ * it under the terms of the GNU General Public License version 3 as
1214+ * published by the Free Software Foundation.
1215+ *
1216+ * This program is distributed in the hope that it will be useful,
1217+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1218+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1219+ * GNU General Public License for more details.
1220+ *
1221+ * You should have received a copy of the GNU General Public License
1222+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1223+ *
1224+ * Authored by: Andrea Azzarone <azzaronea@gmail.com>
1225+ * Jay Taoko <jay.taoko@canonical.com>
1226+ */
1227+
1228+#include "ShortcutView.h"
1229+
1230+#include <glib/gi18n-lib.h>
1231+#include <boost/algorithm/string.hpp>
1232+#include <UnityCore/GLibWrapper.h>
1233+
1234+#include "LineSeparator.h"
1235+#include "StaticCairoText.h"
1236+
1237+namespace unity
1238+{
1239+namespace shortcut
1240+{
1241+namespace
1242+{
1243+ int SECTION_NAME_FONT_SIZE = 17/1.33;
1244+ int SHORTKEY_ENTRY_FONT_SIZE = 13/1.33;
1245+ int INTER_SPACE_SHORTKEY_DESCRIPTION = 10;
1246+ int SHORTKEY_COLUMN_WIDTH = 150;
1247+ int DESCRIPTION_COLUMN_WIDTH = 265;
1248+ int LINE_SPACING = 5;
1249+} // namespace anonymouse
1250+
1251+NUX_IMPLEMENT_OBJECT_TYPE(View);
1252+
1253+View::View(NUX_FILE_LINE_DECL)
1254+ : nux::View(NUX_FILE_LINE_PARAM)
1255+{
1256+ layout_ = new nux::VLayout();
1257+ layout_->SetPadding(50, 38);
1258+ layout_->SetSpaceBetweenChildren(20);
1259+ SetLayout(layout_);
1260+
1261+ background_top_ = nux::CreateTexture2DFromFile(PKGDATADIR"/switcher_top.png", -1, true);
1262+ background_left_ = nux::CreateTexture2DFromFile(PKGDATADIR"/switcher_left.png", -1, true);
1263+ background_corner_ = nux::CreateTexture2DFromFile(PKGDATADIR"/switcher_corner.png", -1, true);
1264+ rounding_texture_ = nux::CreateTexture2DFromFile(PKGDATADIR"/switcher_round_rect.png", -1, true);
1265+
1266+ std::string header = "<b>";
1267+ header += _("Keyboard Shortcuts");
1268+ header += "</b>";
1269+
1270+ nux::StaticText* header_view = new nux::StaticText(header.c_str(), NUX_TRACKER_LOCATION);
1271+ header_view->SetTextPointSize(20/1.33);
1272+ header_view->SetFontName("Ubuntu");
1273+ layout_->AddView(header_view, 1 , nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
1274+
1275+ layout_->AddView(new HSeparator(), 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
1276+
1277+ columns_layout_ = new nux::HLayout();
1278+ columns_layout_->SetSpaceBetweenChildren(30);
1279+ layout_->AddLayout(columns_layout_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
1280+
1281+ // Column 1...
1282+ columns_.push_back(new nux::VLayout());
1283+ columns_layout_->AddLayout(columns_[0], 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
1284+
1285+ // Column 2...
1286+ columns_.push_back(new nux::VLayout());
1287+ columns_layout_->AddLayout(columns_[1], 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
1288+
1289+ bg_effect_helper_.owner = this;
1290+}
1291+
1292+View::~View()
1293+{
1294+ if (background_top_ != NULL)
1295+ background_top_->UnReference();
1296+
1297+ if (background_left_ != NULL)
1298+ background_left_->UnReference();
1299+
1300+ if (background_corner_ != NULL)
1301+ background_corner_->UnReference();
1302+
1303+ if (rounding_texture_ != NULL)
1304+ rounding_texture_->UnReference();
1305+}
1306+
1307+void View::SetModel(Model::Ptr model)
1308+{
1309+ model_ = model;
1310+
1311+ // Fills the columns...
1312+ RenderColumns();
1313+}
1314+
1315+Model::Ptr View::GetModel()
1316+{
1317+ return model_;
1318+}
1319+
1320+void View::SetupBackground(bool enabled)
1321+{
1322+ bg_effect_helper_.enabled = enabled;
1323+}
1324+
1325+nux::LinearLayout* View::CreateSectionLayout(const char* section_name)
1326+{
1327+ nux::VLayout* layout = new nux::VLayout(NUX_TRACKER_LOCATION);
1328+
1329+ std::string name = "<b>";
1330+ name += std::string(section_name);
1331+ name += "</b>";
1332+
1333+
1334+ nux::StaticText* section_name_view = new nux::StaticText(name.c_str(), NUX_TRACKER_LOCATION);
1335+ section_name_view->SetTextPointSize(SECTION_NAME_FONT_SIZE);
1336+ section_name_view->SetFontName("Ubuntu");
1337+ layout->AddView(new nux::SpaceLayout(10, 10, 10, 10), 0, nux::MINOR_POSITION_START, nux::MINOR_SIZE_MATCHCONTENT);
1338+ layout->AddView(section_name_view, 0, nux::MINOR_POSITION_START, nux::MINOR_SIZE_MATCHCONTENT);
1339+ layout->AddView(new nux::SpaceLayout(15, 15, 15, 15), 0, nux::MINOR_POSITION_START, nux::MINOR_SIZE_MATCHCONTENT);
1340+
1341+ return layout;
1342+}
1343+
1344+nux::LinearLayout* View::CreateShortKeyEntryLayout(AbstractHint* hint)
1345+{
1346+ nux::HLayout* layout = new nux::HLayout("EntryLayout", NUX_TRACKER_LOCATION);
1347+ nux::HLayout* shortkey_layout = new nux::HLayout(NUX_TRACKER_LOCATION);
1348+ nux::HLayout* description_layout = new nux::HLayout(NUX_TRACKER_LOCATION);
1349+
1350+ glib::String shortkey(g_markup_escape_text(hint->shortkey().c_str(), -1));
1351+
1352+ std::string skey = "<b>";
1353+ skey += shortkey.Str();
1354+ skey += "</b>";
1355+
1356+ nux::StaticText* shortkey_view = new nux::StaticText(skey, NUX_TRACKER_LOCATION);
1357+ shortkey_view->SetTextAlignment(nux::StaticText::ALIGN_LEFT);
1358+ shortkey_view->SetFontName("Ubuntu");
1359+ shortkey_view->SetTextPointSize(SHORTKEY_ENTRY_FONT_SIZE);
1360+ shortkey_view->SetMinimumWidth(SHORTKEY_COLUMN_WIDTH);
1361+ shortkey_view->SetMaximumWidth(SHORTKEY_COLUMN_WIDTH);
1362+
1363+ glib::String es_desc(g_markup_escape_text(hint->description().c_str(), -1));
1364+
1365+ nux::StaticText* description_view = new nux::StaticText(es_desc.Value(), NUX_TRACKER_LOCATION);
1366+ description_view->SetTextAlignment(nux::StaticText::ALIGN_LEFT);
1367+ shortkey_view->SetFontName("Ubuntu");
1368+ description_view->SetTextPointSize(SHORTKEY_ENTRY_FONT_SIZE);
1369+ description_view->SetMinimumWidth(DESCRIPTION_COLUMN_WIDTH);
1370+ description_view->SetMaximumWidth(DESCRIPTION_COLUMN_WIDTH);
1371+
1372+ shortkey_layout->AddView(shortkey_view, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_MATCHCONTENT);
1373+ shortkey_layout->SetContentDistribution(nux::MAJOR_POSITION_START);
1374+ shortkey_layout->SetMinimumWidth(SHORTKEY_COLUMN_WIDTH);
1375+ shortkey_layout->SetMaximumWidth(SHORTKEY_COLUMN_WIDTH);
1376+
1377+ description_layout->AddView(description_view, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_MATCHCONTENT);
1378+ description_layout->SetContentDistribution(nux::MAJOR_POSITION_START);
1379+ description_layout->SetMinimumWidth(DESCRIPTION_COLUMN_WIDTH);
1380+ description_layout->SetMaximumWidth(DESCRIPTION_COLUMN_WIDTH);
1381+
1382+ layout->AddLayout(shortkey_layout, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_MATCHCONTENT);
1383+ layout->AddLayout(description_layout, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_MATCHCONTENT);
1384+ layout->SetSpaceBetweenChildren(INTER_SPACE_SHORTKEY_DESCRIPTION);
1385+ description_layout->SetContentDistribution(nux::MAJOR_POSITION_START);
1386+
1387+ auto on_shortkey_changed = [](std::string const& new_shortkey, nux::StaticText* view) {
1388+ std::string skey = "<b>";
1389+ skey += new_shortkey;
1390+ skey += "</b>";
1391+
1392+ view->SetText(skey);
1393+ };
1394+
1395+ hint->shortkey.changed.connect(sigc::bind(sigc::slot<void, std::string const&, nux::StaticText*>(on_shortkey_changed), shortkey_view));
1396+
1397+ return layout;
1398+}
1399+
1400+nux::LinearLayout* View::CreateIntermediateLayout()
1401+{
1402+ nux::VLayout* layout = new nux::VLayout(NUX_TRACKER_LOCATION);
1403+ layout->SetSpaceBetweenChildren(LINE_SPACING);
1404+
1405+ return layout;
1406+}
1407+
1408+void View::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
1409+{
1410+ return;
1411+}
1412+
1413+void View::DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw)
1414+{
1415+ nux::Geometry base = GetGeometry();
1416+ GfxContext.PushClippingRectangle(base);
1417+
1418+ // clear region
1419+ gPainter.PaintBackground(GfxContext, base);
1420+
1421+ nux::Geometry background_geo;
1422+
1423+ background_geo.width = base.width;
1424+ background_geo.height = base.height;
1425+ background_geo.x = (base.width - background_geo.width)/2;
1426+ background_geo.y = (base.height - background_geo.height)/2;
1427+
1428+ // magic constant comes from texture contents (distance to cleared area)
1429+ const int internal_offset = 20;
1430+ nux::Geometry internal_clip(background_geo.x + internal_offset,
1431+ background_geo.y + internal_offset,
1432+ background_geo.width - internal_offset * 2,
1433+ background_geo.height - internal_offset * 2);
1434+ GfxContext.PushClippingRectangle(internal_clip);
1435+
1436+ nux::Geometry geo_absolute = GetAbsoluteGeometry();
1437+ if (BackgroundEffectHelper::blur_type != BLUR_NONE)
1438+ {
1439+ nux::Geometry blur_geo(geo_absolute.x, geo_absolute.y, base.width, base.height);
1440+ auto blur_texture = bg_effect_helper_.GetBlurRegion(blur_geo);
1441+
1442+ if (blur_texture.IsValid())
1443+ {
1444+ nux::TexCoordXForm texxform_blur_bg;
1445+ texxform_blur_bg.flip_v_coord = true;
1446+ texxform_blur_bg.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
1447+ texxform_blur_bg.uoffset = ((float) base.x) / geo_absolute.width;
1448+ texxform_blur_bg.voffset = ((float) base.y) / geo_absolute.height;
1449+
1450+ nux::ROPConfig rop;
1451+ rop.Blend = false;
1452+ rop.SrcBlend = GL_ONE;
1453+ rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
1454+
1455+ gPainter.PushDrawTextureLayer(GfxContext, base,
1456+ blur_texture,
1457+ texxform_blur_bg,
1458+ nux::color::White,
1459+ true,
1460+ rop);
1461+ }
1462+ }
1463+
1464+ nux::ROPConfig rop;
1465+ rop.Blend = true;
1466+ rop.SrcBlend = GL_ONE;
1467+ rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
1468+ gPainter.PushDrawColorLayer(GfxContext, internal_clip, background_color, false, rop);
1469+
1470+ // Make round corners
1471+ rop.Blend = true;
1472+ rop.SrcBlend = GL_ZERO;
1473+ rop.DstBlend = GL_SRC_ALPHA;
1474+ gPainter.PaintShapeCornerROP(GfxContext,
1475+ internal_clip,
1476+ nux::color::White,
1477+ nux::eSHAPE_CORNER_ROUND4,
1478+ nux::eCornerTopLeft | nux::eCornerTopRight |
1479+ nux::eCornerBottomLeft | nux::eCornerBottomRight,
1480+ true,
1481+ rop);
1482+
1483+ GfxContext.GetRenderStates().SetPremultipliedBlend(nux::SRC_OVER);
1484+
1485+ GfxContext.PopClippingRectangle();
1486+ GfxContext.PopClippingRectangle();
1487+
1488+ DrawBackground(GfxContext, background_geo);
1489+
1490+
1491+ layout_->ProcessDraw(GfxContext, force_draw);
1492+}
1493+
1494+
1495+void View::DrawBackground(nux::GraphicsEngine& GfxContext, nux::Geometry const& geo)
1496+{
1497+ int border = 30;
1498+
1499+ GfxContext.GetRenderStates().SetBlend(TRUE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1500+
1501+ nux::TexCoordXForm texxform;
1502+ texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
1503+ texxform.SetWrap(nux::TEXWRAP_REPEAT, nux::TEXWRAP_REPEAT);
1504+
1505+ // Draw TOP-LEFT CORNER
1506+ texxform.u0 = 0;
1507+ texxform.v0 = 0;
1508+ texxform.u1 = border;
1509+ texxform.v1 = border;
1510+ GfxContext.QRP_1Tex(geo.x, geo.y,
1511+ border, border, background_corner_->GetDeviceTexture(), texxform, nux::color::White);
1512+
1513+ // Draw TOP-RIGHT CORNER
1514+ texxform.u0 = 0;
1515+ texxform.v0 = 0;
1516+ texxform.u1 = border;
1517+ texxform.v1 = border;
1518+ texxform.flip_u_coord = true;
1519+ texxform.flip_v_coord = false;
1520+ GfxContext.QRP_1Tex(geo.x + geo.width - border, geo.y,
1521+ border, border, background_corner_->GetDeviceTexture(), texxform, nux::color::White);
1522+
1523+ // Draw BOTTOM-LEFT CORNER
1524+ texxform.u0 = 0;
1525+ texxform.v0 = 0;
1526+ texxform.u1 = border;
1527+ texxform.v1 = border;
1528+ texxform.flip_u_coord = false;
1529+ texxform.flip_v_coord = true;
1530+ GfxContext.QRP_1Tex(geo.x, geo.y + geo.height - border,
1531+ border, border, background_corner_->GetDeviceTexture(), texxform, nux::color::White);
1532+
1533+ // Draw BOTTOM-RIGHT CORNER
1534+ texxform.u0 = 0;
1535+ texxform.v0 = 0;
1536+ texxform.u1 = border;
1537+ texxform.v1 = border;
1538+ texxform.flip_u_coord = true;
1539+ texxform.flip_v_coord = true;
1540+ GfxContext.QRP_1Tex(geo.x + geo.width - border, geo.y + geo.height - border,
1541+ border, border, background_corner_->GetDeviceTexture(), texxform, nux::color::White);
1542+
1543+ int top_width = background_top_->GetWidth();
1544+ int top_height = background_top_->GetHeight();
1545+
1546+ // Draw TOP BORDER
1547+ texxform.u0 = 0;
1548+ texxform.v0 = 0;
1549+ texxform.u1 = top_width;
1550+ texxform.v1 = top_height;
1551+ texxform.flip_u_coord = false;
1552+ texxform.flip_v_coord = false;
1553+ GfxContext.QRP_1Tex(geo.x + border, geo.y, geo.width - border - border, border, background_top_->GetDeviceTexture(), texxform, nux::color::White);
1554+
1555+ // Draw BOTTOM BORDER
1556+ texxform.u0 = 0;
1557+ texxform.v0 = 0;
1558+ texxform.u1 = top_width;
1559+ texxform.v1 = top_height;
1560+ texxform.flip_u_coord = false;
1561+ texxform.flip_v_coord = true;
1562+ GfxContext.QRP_1Tex(geo.x + border, geo.y + geo.height - border, geo.width - border - border, border, background_top_->GetDeviceTexture(), texxform, nux::color::White);
1563+
1564+
1565+ int left_width = background_left_->GetWidth();
1566+ int left_height = background_left_->GetHeight();
1567+
1568+ // Draw LEFT BORDER
1569+ texxform.u0 = 0;
1570+ texxform.v0 = 0;
1571+ texxform.u1 = left_width;
1572+ texxform.v1 = left_height;
1573+ texxform.flip_u_coord = false;
1574+ texxform.flip_v_coord = false;
1575+ GfxContext.QRP_1Tex(geo.x, geo.y + border, border, geo.height - border - border, background_left_->GetDeviceTexture(), texxform, nux::color::White);
1576+
1577+ // Draw RIGHT BORDER
1578+ texxform.u0 = 0;
1579+ texxform.v0 = 0;
1580+ texxform.u1 = left_width;
1581+ texxform.v1 = left_height;
1582+ texxform.flip_u_coord = true;
1583+ texxform.flip_v_coord = false;
1584+ GfxContext.QRP_1Tex(geo.x + geo.width - border, geo.y + border, border, geo.height - border - border, background_left_->GetDeviceTexture(), texxform, nux::color::White);
1585+
1586+ GfxContext.GetRenderStates().SetBlend(FALSE);
1587+}
1588+
1589+void View::RenderColumns()
1590+{
1591+ int i = 0;
1592+ int column = 0;
1593+
1594+ for (auto category : model_->categories())
1595+ {
1596+ // Three sections in the fist column...
1597+ if (i > 2)
1598+ column = 1;
1599+
1600+ nux::LinearLayout* section_layout = CreateSectionLayout(category.c_str());
1601+ nux::LinearLayout* intermediate_layout = CreateIntermediateLayout();
1602+ intermediate_layout->SetContentDistribution(nux::MAJOR_POSITION_START);
1603+
1604+ for (auto hint : model_->hints()[category])
1605+ {
1606+ //std::string str_value = hint->prefix() + hint->value() + hint->postfix();
1607+ //boost::replace_all(str_value, "&", "&amp;");
1608+ //boost::replace_all(str_value, "<", "&lt;");
1609+ //boost::replace_all(str_value, ">", "&gt;");
1610+
1611+ intermediate_layout->AddLayout(CreateShortKeyEntryLayout(hint), 0, nux::MINOR_POSITION_START, nux::MINOR_SIZE_FULL);
1612+ }
1613+
1614+ section_layout->AddLayout(intermediate_layout, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
1615+
1616+ if (i == 0 or i==1 or i==3 or i==4)
1617+ {
1618+ // Add space before the line
1619+ section_layout->AddView(new nux::SpaceLayout(23, 23, 23, 23), 0, nux::MINOR_POSITION_START, nux::MINOR_SIZE_MATCHCONTENT);
1620+ section_layout->AddView(new HSeparator(), 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
1621+ // Add space after the line
1622+ section_layout->AddView(new nux::SpaceLayout(20, 20, 20, 20), 0, nux::MINOR_POSITION_START, nux::MINOR_SIZE_MATCHCONTENT);
1623+ }
1624+
1625+ columns_[column]->AddView(section_layout, 1, nux::MINOR_POSITION_START, nux::MINOR_SIZE_FULL);
1626+
1627+ i++;
1628+ }
1629+}
1630+
1631+} // namespace shortcut
1632+} // namespace unity
1633
1634=== added file 'plugins/unityshell/src/ShortcutView.h'
1635--- plugins/unityshell/src/ShortcutView.h 1970-01-01 00:00:00 +0000
1636+++ plugins/unityshell/src/ShortcutView.h 2012-01-13 15:39:27 +0000
1637@@ -0,0 +1,93 @@
1638+/*
1639+ * Copyright (C) 2011 Canonical Ltd
1640+ *
1641+ * This program is free software: you can redistribute it and/or modify
1642+ * it under the terms of the GNU General Public License version 3 as
1643+ * published by the Free Software Foundation.
1644+ *
1645+ * This program is distributed in the hope that it will be useful,
1646+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1647+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1648+ * GNU General Public License for more details.
1649+ *
1650+ * You should have received a copy of the GNU General Public License
1651+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1652+ *
1653+ * Authored by: Andrea Azzarone <azzaronea@gmail.com>
1654+ */
1655+
1656+#ifndef UNITYSHELL_SHORTCUTVIEW_H
1657+#define UNITYSHELL_SHORTCUTVIEW_H
1658+
1659+#include <Nux/Nux.h>
1660+#include <Nux/GridHLayout.h>
1661+#include <Nux/HLayout.h>
1662+#include <NuxCore/ObjectPtr.h>
1663+#include <NuxCore/Property.h>
1664+#include <Nux/StaticText.h>
1665+#include <Nux/View.h>
1666+#include <Nux/VLayout.h>
1667+
1668+#include "BackgroundEffectHelper.h"
1669+#include "ShortcutModel.h"
1670+
1671+namespace unity
1672+{
1673+namespace shortcut
1674+{
1675+
1676+class View : public nux::View
1677+{
1678+ NUX_DECLARE_OBJECT_TYPE(View, nux::View);
1679+public:
1680+ typedef nux::ObjectPtr<View> Ptr;
1681+
1682+ // Ctor and dtor
1683+ View(NUX_FILE_LINE_PROTO);
1684+ ~View();
1685+
1686+ // Public methods
1687+ void SetModel(Model::Ptr model);
1688+ Model::Ptr GetModel();
1689+
1690+ void SetupBackground(bool enabled);
1691+
1692+ // Properties
1693+ nux::Property<nux::Color> background_color;
1694+
1695+protected:
1696+ // Protected methods
1697+ void Draw(nux::GraphicsEngine& GfxContext, bool force_draw);
1698+ void DrawContent(nux::GraphicsEngine& GfxContext, bool force_draw);
1699+
1700+private:
1701+ // Private methods
1702+ nux::LinearLayout* CreateSectionLayout(const char* section_name);
1703+ nux::LinearLayout* CreateShortKeyEntryLayout(AbstractHint* hint);
1704+ nux::LinearLayout* CreateIntermediateLayout();
1705+
1706+ void DrawBackground(nux::GraphicsEngine& GfxContext, nux::Geometry const& geo);
1707+ void RenderColumns();
1708+
1709+ // Private members
1710+ Model::Ptr model_;
1711+
1712+ nux::BaseTexture* background_top_;
1713+ nux::BaseTexture* background_left_;
1714+ nux::BaseTexture* background_corner_;
1715+ nux::BaseTexture* rounding_texture_;
1716+
1717+ nux::VLayout* layout_;
1718+ nux::HLayout* columns_layout_;
1719+ std::vector<nux::VLayout*> columns_;
1720+
1721+ BackgroundEffectHelper bg_effect_helper_;
1722+
1723+};
1724+
1725+} // namespace shortcut
1726+
1727+} // namespace unity
1728+
1729+#endif // UNITYSHELL_SHORTCUTVIEW_H
1730+
1731
1732=== modified file 'plugins/unityshell/src/unityshell.cpp'
1733--- plugins/unityshell/src/unityshell.cpp 2012-01-09 16:49:50 +0000
1734+++ plugins/unityshell/src/unityshell.cpp 2012-01-13 15:39:27 +0000
1735@@ -97,6 +97,7 @@
1736 , screen(screen)
1737 , cScreen(CompositeScreen::get(screen))
1738 , gScreen(GLScreen::get(screen))
1739+ , enable_shortcut_overlay_(true)
1740 , gestureEngine(nullptr)
1741 , wt(nullptr)
1742 , panelWindow(nullptr)
1743@@ -258,7 +259,8 @@
1744 optionSetIconSizeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
1745 optionSetAutohideAnimationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
1746 optionSetDashBlurExperimentalNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
1747- optionSetDevicesOptionNotify(boost::bind (&UnityScreen::optionChanged, this, _1, _2));
1748+ optionSetDevicesOptionNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
1749+ optionSetShortcutOverlayNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
1750 optionSetShowDesktopIconNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
1751 optionSetShowLauncherInitiate(boost::bind(&UnityScreen::showLauncherKeyInitiate, this, _1, _2, _3));
1752 optionSetShowLauncherTerminate(boost::bind(&UnityScreen::showLauncherKeyTerminate, this, _1, _2, _3));
1753@@ -1120,6 +1122,7 @@
1754 // thing that could possibly make sense here.
1755 key_string[result] = 0;
1756 if (super_keypressed_) {
1757+ shortcut_controller_->Hide();
1758 skip_other_plugins = launcher.CheckSuperShortcutPressed(screen->dpy(), key_sym, event->xkey.keycode, event->xkey.state, key_string);
1759 if (!skip_other_plugins) {
1760 skip_other_plugins = dash_controller_->CheckShortcutActivation(key_string);
1761@@ -1234,6 +1237,33 @@
1762 super_keypressed_ = true;
1763 launcher_controller_->launcher().StartKeyShowLauncher();
1764 EnsureSuperKeybindings ();
1765+
1766+ if (enable_shortcut_overlay_ and !shortcut_controller_->Visible())
1767+ {
1768+ static nux::Geometry last_geo;
1769+ UScreen* uscreen = UScreen::GetDefault();
1770+ int primary_monitor = uscreen->GetPrimaryMonitor();
1771+ auto monitor_geo = uscreen->GetMonitorGeometry(primary_monitor);
1772+
1773+ int width = 970;
1774+ int height = 680;
1775+ int launcher_width = optionGetIconSize() + 18;
1776+ int panel_height = 24;
1777+ int x = monitor_geo.x + launcher_width + (monitor_geo.width - launcher_width- width) / 2;
1778+ int y = monitor_geo.y + panel_height + (monitor_geo.height - panel_height - height) / 2;
1779+
1780+ nux::Geometry geo (x, y, width, height);
1781+
1782+ if (last_geo != geo)
1783+ {
1784+ shortcut_controller_->SetWorkspace(geo);
1785+ last_geo = geo;
1786+ }
1787+
1788+ if (last_geo.x > monitor_geo.x and last_geo.y > monitor_geo.y)
1789+ shortcut_controller_->Show();
1790+ }
1791+
1792 return false;
1793 }
1794
1795@@ -1243,6 +1273,7 @@
1796 {
1797 super_keypressed_ = false;
1798 launcher_controller_->launcher().EndKeyShowLauncher();
1799+ shortcut_controller_->Hide();
1800 return false;
1801 }
1802
1803@@ -2176,6 +2207,9 @@
1804 screen->enterShowDesktopModeSetEnabled (this, optionGetShowMinimizedWindows ());
1805 screen->leaveShowDesktopModeSetEnabled (this, optionGetShowMinimizedWindows ());
1806 break;
1807+ case UnityshellOptions::ShortcutOverlay:
1808+ enable_shortcut_overlay_ = optionGetShortcutOverlay();
1809+ break;
1810 case UnityshellOptions::ShowDesktopIcon:
1811 launcher_controller_->SetShowDesktopIcon(optionGetShowDesktopIcon());
1812 break;
1813@@ -2304,6 +2338,10 @@
1814 /* Setup Places */
1815 dash_controller_.reset(new dash::Controller());
1816 dash_controller_->on_realize.connect(sigc::mem_fun(this, &UnityScreen::OnDashRealized));
1817+
1818+ // Setup Shortcut Hint
1819+ InitHints();
1820+ shortcut_controller_.reset(new shortcut::Controller(hints_));
1821
1822 AddChild(dash_controller_.get());
1823
1824@@ -2316,6 +2354,66 @@
1825 OnLauncherHiddenChanged();
1826 }
1827
1828+void UnityScreen::InitHints()
1829+{
1830+ // TODO move category text into a vector...
1831+
1832+ // Launcher...
1833+ std::string const launcher = _("Launcher");
1834+
1835+ hints_.push_back(new shortcut::Hint(launcher, "", _(" (Press)"), _("Open Launcher, displays shortcuts."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher" ));
1836+ hints_.push_back(new shortcut::Hint(launcher, "", "", _("Open Launcher keyboard navigation mode."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "keyboard_focus"));
1837+ hints_.push_back(new shortcut::Hint(launcher, "", "", _("Switch applications via Launcher."), shortcut::HARDCODED_OPTION, "Super + Tab"));
1838+ hints_.push_back(new shortcut::Hint(launcher, "", _(" + 1 to 9"), _("Same as clicking on a Launcher icon."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
1839+ hints_.push_back(new shortcut::Hint(launcher, "", _(" + Shift + 1 to 9"), _("Open new window of the app."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
1840+ hints_.push_back(new shortcut::Hint(launcher, "", " + T", _("Open the Rubbish Bin."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
1841+
1842+ // Dash...
1843+ std::string const dash = _("Dash");
1844+
1845+ hints_.push_back(new shortcut::Hint(dash, "", _(" (Tap)"), _("Open the Dash Home."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
1846+ hints_.push_back(new shortcut::Hint(dash, "", " + A", _("Open the Dash App Lens."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
1847+ hints_.push_back(new shortcut::Hint(dash, "", " + F", _("Open the Dash Files Lens."), shortcut::COMPIZ_KEY_OPTION,"unityshell", "show_launcher"));
1848+ hints_.push_back(new shortcut::Hint(dash, "", " + M", _("Open the Dash Music Lens."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
1849+ hints_.push_back(new shortcut::Hint(dash, "", "", _("Switches between Lenses."), shortcut::HARDCODED_OPTION, "Ctrl + Tab"));
1850+ hints_.push_back(new shortcut::Hint(dash, "", "", _("Moves the focus."), shortcut::HARDCODED_OPTION, _("Cursor Keys")));
1851+ hints_.push_back(new shortcut::Hint(dash, "", "", _("Open currently focused item."), shortcut::HARDCODED_OPTION, _("Enter & Return")));
1852+ hints_.push_back(new shortcut::Hint(dash, "", "", _("'Run Command' mode."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "execute_command"));
1853+
1854+ // Top Bar
1855+ std::string const topbar = _("Top Bar");
1856+
1857+ hints_.push_back(new shortcut::Hint(topbar, "", "", _("Reveals application menu."), shortcut::HARDCODED_OPTION, "Alt"));
1858+ hints_.push_back(new shortcut::Hint(topbar, "", "", _("Opens the indicator menu."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "panel_first_menu"));
1859+ hints_.push_back(new shortcut::Hint(topbar, "", "", _("Moves focus between indicators."), shortcut::HARDCODED_OPTION, _("Cursor Left or Right")));
1860+
1861+ // Switching
1862+ std::string const switching = _("Switching");
1863+
1864+ hints_.push_back(new shortcut::Hint(switching, "", "", _("Switch between applications."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "alt_tab_forward"));
1865+ hints_.push_back(new shortcut::Hint(switching, "", "", _("Switch windows of current application."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "alt_tab_next_window"));
1866+ hints_.push_back(new shortcut::Hint(switching, "", "", _("Moves the focus."), shortcut::HARDCODED_OPTION, _("Cursor Left or Right")));
1867+
1868+ // Workspaces
1869+ std::string const workspaces = _("Workspaces");
1870+ hints_.push_back(new shortcut::Hint(workspaces, "", "", _("Spread workspaces."), shortcut::COMPIZ_KEY_OPTION, "expo", "expo_key"));
1871+ hints_.push_back(new shortcut::Hint(workspaces, "", "", _("Switch workspaces."), shortcut::HARDCODED_OPTION, _("Super + Cursor Keys")));
1872+ hints_.push_back(new shortcut::Hint(workspaces, "", " or Right", _("Move focused window to different workspace."), shortcut::HARDCODED_OPTION, _("Super + Alt + Cursor Keys")));
1873+
1874+ // Windows
1875+ std::string const windows = _("Windows");
1876+ hints_.push_back(new shortcut::Hint(windows, "", "", _("Spreads all windows in the current workspace."), shortcut::COMPIZ_KEY_OPTION, "scale", "initiate_all_key"));
1877+ hints_.push_back(new shortcut::Hint(windows, "", "", _("Minimises all windows."), shortcut::COMPIZ_KEY_OPTION, "core", "show_desktop_key"));
1878+ hints_.push_back(new shortcut::Hint(windows, "", "", _("Maximises the current window."), shortcut::COMPIZ_KEY_OPTION, "core", "maximize_window_key"));
1879+ hints_.push_back(new shortcut::Hint(windows, "", "", _("Restores or minimises current window."), shortcut::COMPIZ_KEY_OPTION, "core", "unmaximize_window_key"));
1880+ hints_.push_back(new shortcut::Hint(windows, "", " or Right", _("Semi-maximises current window."), shortcut::COMPIZ_KEY_OPTION, "grid", "put_left_key"));
1881+ hints_.push_back(new shortcut::Hint(windows, "", "", _("Closes current window."), shortcut::COMPIZ_KEY_OPTION, "core", "close_window_key"));
1882+ hints_.push_back(new shortcut::Hint(windows, "", "", _("Opens window accessibility menu."), shortcut::HARDCODED_OPTION, "Alt + Space"));
1883+ hints_.push_back(new shortcut::Hint(windows, "", "", _("Places window in corresponding positions."), shortcut::HARDCODED_OPTION, "Ctrl + Alt + Num"));
1884+ hints_.push_back(new shortcut::Hint(windows, "", " Drag", _("Move window."), shortcut::COMPIZ_MOUSE_OPTION, "move", "initiate_button"));
1885+ hints_.push_back(new shortcut::Hint(windows, "", " Drag", _("Resize window."), shortcut::COMPIZ_MOUSE_OPTION, "resize", "initiate_button"));
1886+}
1887+
1888 /* Window init */
1889 UnityWindow::UnityWindow(CompWindow* window)
1890 : BaseSwitchWindow (dynamic_cast<BaseSwitchScreen *> (UnityScreen::get (screen)), window)
1891
1892=== modified file 'plugins/unityshell/src/unityshell.h'
1893--- plugins/unityshell/src/unityshell.h 2012-01-06 04:53:09 +0000
1894+++ plugins/unityshell/src/unityshell.h 2012-01-13 15:39:27 +0000
1895@@ -39,6 +39,8 @@
1896 #include "DashSettings.h"
1897 #include "DashStyle.h"
1898 #include "FontSettings.h"
1899+#include "ShortcutController.h"
1900+#include "ShortcutHint.h"
1901 #include "LauncherController.h"
1902 #include "PanelController.h"
1903 #include "PanelStyle.h"
1904@@ -242,6 +244,8 @@
1905 static void OnQuicklistEndKeyNav(GVariant* data, void* value);
1906 static void OnLauncherStartKeyNav(GVariant* data, void* value);
1907 static void OnLauncherEndKeyNav(GVariant* data, void* value);
1908+
1909+ void InitHints();
1910
1911 dash::Settings dash_settings_;
1912 dash::Style dash_style_;
1913@@ -253,6 +257,10 @@
1914 panel::Controller::Ptr panel_controller_;
1915 switcher::Controller::Ptr switcher_controller_;
1916
1917+ shortcut::Controller::Ptr shortcut_controller_;
1918+ std::list<shortcut::AbstractHint*> hints_;
1919+ bool enable_shortcut_overlay_;
1920+
1921 GestureEngine* gestureEngine;
1922 nux::WindowThread* wt;
1923 nux::BaseWindow* panelWindow;
1924@@ -266,7 +274,7 @@
1925 guint32 _redraw_handle;
1926 gint _edge_pointerY;
1927 guint _ubus_handles[3];
1928-
1929+
1930 typedef std::shared_ptr<CompAction> CompActionPtr;
1931 typedef std::vector<CompActionPtr> ShortcutActions;
1932 ShortcutActions _shortcut_actions;
1933
1934=== modified file 'plugins/unityshell/unityshell.xml.in'
1935--- plugins/unityshell/unityshell.xml.in 2011-12-08 21:16:50 +0000
1936+++ plugins/unityshell/unityshell.xml.in 2012-01-13 15:39:27 +0000
1937@@ -341,6 +341,12 @@
1938 <_name>Always</_name>
1939 </desc>
1940 </option>
1941+
1942+ <option name="shortcut_overlay" type="bool">
1943+ <_short>Enable Shortcut Hints Overlay</_short>
1944+ <_long>Enable Shortcut Hints Overlay</_long>
1945+ <default>true</default>
1946+ </option>
1947
1948 <option name="show_desktop_icon" type="bool">
1949 <_short>Show "Desktop Icon" in the launcher</_short>
1950
1951=== modified file 'standalone-clients/CMakeLists.txt'
1952--- standalone-clients/CMakeLists.txt 2012-01-06 13:10:01 +0000
1953+++ standalone-clients/CMakeLists.txt 2012-01-13 15:39:27 +0000
1954@@ -452,8 +452,32 @@
1955 )
1956 add_dependencies (bg-hash unity-core-${UNITY_API_VERSION})
1957
1958+add_executable (test-shortcut
1959+ TestShortcut.cpp
1960+ ${UNITY_SRC}/AbstractSeparator.cpp
1961+ ${UNITY_SRC}/AbstractSeparator.h
1962+ ${UNITY_SRC}/AbstractShortcutHint.h
1963+ ${UNITY_SRC}/Animator.cpp
1964+ ${UNITY_SRC}/Animator.h
1965+ ${UNITY_SRC}/BackgroundEffectHelper.cpp
1966+ ${UNITY_SRC}/BackgroundEffectHelper.h
1967+ ${UNITY_SRC}/LineSeparator.cpp
1968+ ${UNITY_SRC}/LineSeparator.h
1969+ ${UNITY_SRC}/MockShortcutHint.h
1970+ ${UNITY_SRC}/ShortcutController.cpp
1971+ ${UNITY_SRC}/ShortcutController.h
1972+ ${UNITY_SRC}/ShortcutModel.cpp
1973+ ${UNITY_SRC}/ShortcutModel.h
1974+ ${UNITY_SRC}/ShortcutView.cpp
1975+ ${UNITY_SRC}/ShortcutView.h
1976+ ${UNITY_SRC}/StaticCairoText.cpp
1977+ ${UNITY_SRC}/StaticCairoText.h
1978+ ${UNITY_SRC}/UBusMessages.h
1979+ ${UNITY_SRC}/ubus-server.cpp
1980+ ${UNITY_SRC}/ubus-server.h
1981+ )
1982+
1983 find_package (OpenGL)
1984-
1985 include_directories (${OPENGL_gl_INCDIRS})
1986 add_library (glfuncloader SHARED
1987 ${CMAKE_CURRENT_SOURCE_DIR}/GLFuncLoader.cpp)
1988@@ -467,9 +491,8 @@
1989 target_link_libraries (screen-effect-fbo glfuncloader ${OPENGL_gl_LIBRARY})
1990 add_dependencies (screen-effect-fbo ${UNITY_API_VERSION})
1991
1992-
1993 # Custom target to make all the other targets here, add your test to this list
1994-add_custom_target(standalone-clients DEPENDS dash panel launcher switcher keyutil quicklist quicklist-visuals filters filter-bar preview-applicaiton preview-generic preview-music result-view dash-style bg-hash)
1995+add_custom_target(standalone-clients DEPENDS dash panel launcher switcher keyutil quicklist quicklist-visuals filters filter-bar preview-applicaiton preview-generic preview-music result-view dash-style bg-hash shortcut-view)
1996
1997
1998
1999
2000=== added file 'standalone-clients/TestShortcut.cpp'
2001--- standalone-clients/TestShortcut.cpp 1970-01-01 00:00:00 +0000
2002+++ standalone-clients/TestShortcut.cpp 2012-01-13 15:39:27 +0000
2003@@ -0,0 +1,109 @@
2004+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2005+/*
2006+ * Copyright (C) 2011 Canonical Ltd
2007+ *
2008+ * This program is free software: you can redistribute it and/or modify
2009+ * it under the terms of the GNU General Public License version 3 as
2010+ * published by the Free Software Foundation.
2011+ *
2012+ * This program is distributed in the hope that it will be useful,
2013+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2014+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2015+ * GNU General Public License for more details.
2016+ *
2017+ * You should have received a copy of the GNU General Public License
2018+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2019+ *
2020+ * Authored by: Andrea Azzarone <azzaronea@gmail.com>
2021+ */
2022+
2023+#include <dbus/dbus-glib.h>
2024+#include <glib/gi18n-lib.h>
2025+#include <gtk/gtk.h>
2026+#include <Nux/Nux.h>
2027+#include <Nux/WindowThread.h>
2028+
2029+#include "BackgroundEffectHelper.h"
2030+#include "MockShortcutHint.h"
2031+#include "ShortcutController.h"
2032+
2033+using namespace unity;
2034+
2035+static shortcut::Controller::Ptr controller;
2036+
2037+void ThreadWidgetInit(nux::NThread* thread, void* InitData)
2038+{
2039+ std::list<shortcut::AbstractHint*> hints;
2040+
2041+ // Launcher...
2042+ hints.push_back(new shortcut::MockHint(_("Launcher"), "", _(" (Press)"), _("Open Launcher, displays shortcuts."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher" ));
2043+ hints.push_back(new shortcut::MockHint(_("Launcher"), "", "", _("Open Launcher keyboard navigation mode."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "keyboard_focus"));
2044+ // FIXME: Implement it...
2045+ hints.push_back(new shortcut::MockHint(_("Launcher"), "", "", _("Switch application via Launcher."), shortcut::HARDCODED_OPTION, "Super + Tab"));
2046+ hints.push_back(new shortcut::MockHint(_("Launcher"), "", _(" + 1 to 9"), _("Same as clicking on a Launcher icon."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
2047+ hints.push_back(new shortcut::MockHint(_("Launcher"), "", _(" + Shift + 1 to 9"), _("Open a new window of the app."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
2048+ hints.push_back(new shortcut::MockHint(_("Launcher"), "", " + T", _("Open the Rubbish Bin."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
2049+
2050+ // Dash...
2051+ hints.push_back(new shortcut::MockHint(_("Dash"), "", _(" (Tap)"), _("Open the Dash Home."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
2052+ // These are not really hardcoded...
2053+ hints.push_back(new shortcut::MockHint(_("Dash"), "", " + A", _("Open the Dash App Lens."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
2054+ hints.push_back(new shortcut::MockHint(_("Dash"), "", " + F", _("Open the Dash Files Lens."), shortcut::COMPIZ_KEY_OPTION,"unityshell", "show_launcher"));
2055+ hints.push_back(new shortcut::MockHint(_("Dash"), "", " + M", _("Open the Dash Music Lens."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "show_launcher"));
2056+ hints.push_back(new shortcut::MockHint(_("Dash"), "", "", _("Switches between Lenses."), shortcut::HARDCODED_OPTION, "Ctrl + Tab"));
2057+ hints.push_back(new shortcut::MockHint(_("Dash"), "", "", _("Moves the focus."), shortcut::HARDCODED_OPTION, _("Cursor Keys")));
2058+ hints.push_back(new shortcut::MockHint(_("Dash"), "", "", _("Open currently focused item."), shortcut::HARDCODED_OPTION, _("Enter / Return")));
2059+ hints.push_back(new shortcut::MockHint(_("Dash"), "", "", _("'Run Command' mode."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "execute_command"));
2060+
2061+ // Top Bar
2062+ // Is it really hard coded?
2063+ hints.push_back(new shortcut::MockHint(_("Top Bar"), "", "", _("Reveals application menu."), shortcut::HARDCODED_OPTION, "Alt"));
2064+ hints.push_back(new shortcut::MockHint(_("Top Bar"), "", "", _("Opens the indicator menu."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "panel_first_menu"));
2065+ hints.push_back(new shortcut::MockHint(_("Top Bar"), "", "", _("Moves focus between indicators."), shortcut::HARDCODED_OPTION, _("Cursor Left & Right")));
2066+
2067+ // Switching
2068+ hints.push_back(new shortcut::MockHint(_("Switching"), "", "", _("Switch between applications."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "alt_tab_forward"));
2069+ hints.push_back(new shortcut::MockHint(_("Switching"), "", "", _("Switch windows of current application."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "alt_tab_next_window"));
2070+ hints.push_back(new shortcut::MockHint(_("Switching"), "", "", _("Close window switch, return to app switch."), shortcut::COMPIZ_KEY_OPTION, "unityshell", "alt_tab_detail_stop"));
2071+ hints.push_back(new shortcut::MockHint(_("Switching"), "", "", _("Moves the foucs."), shortcut::HARDCODED_OPTION, _("Cursor Left & Right")));
2072+
2073+ // Workspaces
2074+ hints.push_back(new shortcut::MockHint(_("Workspaces"), "", "", _("Spread workspaces."), shortcut::COMPIZ_KEY_OPTION, "expo", "expo_key"));
2075+ hints.push_back(new shortcut::MockHint(_("Workspaces"), "", "", _("Switch workspaces."), shortcut::HARDCODED_OPTION, _("Cursor Keys")));
2076+ //hints.push_back(new shortcut::MockHint(_("Workspaces"), "", "", _("Move focused window to other workspace."), ...)
2077+
2078+ // Windows
2079+ hints.push_back(new shortcut::MockHint(_("Windows"), "", "", _("Spreads all windows in current workspace."), shortcut::COMPIZ_KEY_OPTION, "scale", "initiate_output_key"));
2080+ hints.push_back(new shortcut::MockHint(_("Windows"), "", "", _("Minimises all windows."), shortcut::COMPIZ_KEY_OPTION, "core", "show_desktop_key"));
2081+ // I don't know if it is really hardcoded, but I can't find where this option is stored.
2082+ hints.push_back(new shortcut::MockHint(_("Windows"), "", "", _("Open window accessibility menu."), shortcut::HARDCODED_OPTION, "Alt+Space"));
2083+ hints.push_back(new shortcut::MockHint(_("Windows"), "", "", _("Maximises current window."), shortcut::COMPIZ_KEY_OPTION, "core", "maximize_window_key"));
2084+ hints.push_back(new shortcut::MockHint(_("Windows"), "", "", _("Un-maximises current window."), shortcut::COMPIZ_KEY_OPTION, "core", "unmaximize_window_key"));
2085+ hints.push_back(new shortcut::MockHint(_("Windows"), "", "", _("Minimises current window."), shortcut::COMPIZ_KEY_OPTION, "core", "minimize_window_key"));
2086+ hints.push_back(new shortcut::MockHint(_("Windows"), "", "", _("Resizes current window."), shortcut::COMPIZ_KEY_OPTION, "resize", "initiate_key"));
2087+ hints.push_back(new shortcut::MockHint(_("Windows"), "", "", _("Closes current window."), shortcut::COMPIZ_KEY_OPTION, "core", "close_window_key"));
2088+ hints.push_back(new shortcut::MockHint(_("Windows"), "", "", _("Places window in corresponding positions."), shortcut::HARDCODED_OPTION, "Ctrl + Alt + Num"));
2089+ hints.push_back(new shortcut::MockHint(_("Windows"), "", "", _("Move window."), shortcut::COMPIZ_KEY_OPTION, "move", "initiate_key"));
2090+
2091+ controller.reset(new shortcut::Controller(hints));
2092+ controller->SetWorkspace(nux::Geometry(25, 17, 1200 - 50, 720 - 35));
2093+ controller->Show();
2094+}
2095+
2096+int main(int argc, char** argv)
2097+{
2098+ g_type_init();
2099+ //g_thread_init(NULL);
2100+ gtk_init(&argc, &argv);
2101+
2102+ dbus_g_thread_init();
2103+
2104+ nux::NuxInitialize(0);
2105+
2106+ BackgroundEffectHelper::blur_type = BLUR_NONE;
2107+ nux::WindowThread* wt = nux::CreateGUIThread(TEXT("Unity Shortcut Hint Overlay"), 1200, 720, 0, &ThreadWidgetInit, 0);
2108+
2109+ wt->Run(NULL);
2110+ delete wt;
2111+ return 0;
2112+}
2113
2114=== modified file 'tests/CMakeLists.txt'
2115--- tests/CMakeLists.txt 2011-12-22 06:27:26 +0000
2116+++ tests/CMakeLists.txt 2012-01-13 15:39:27 +0000
2117@@ -70,7 +70,6 @@
2118 ${UNITY_SRC}/
2119 )
2120 add_dependencies (test-unit unity-core-${UNITY_API_VERSION})
2121-
2122 add_subdirectory (test-input-remover)
2123 add_subdirectory (test-minimize-window-handler)
2124 add_subdirectory (test-get-transients)
2125@@ -107,6 +106,7 @@
2126 test_service_model.h)
2127 add_dependencies (test-gtest-service unity-core-${UNITY_API_VERSION})
2128
2129+
2130 # The actual test executable (xless) - do not put anything that requires X in here
2131 add_executable(test-gtest-xless
2132 test_animator.cpp
2133@@ -118,10 +118,13 @@
2134 test_glib_signals_utils.h
2135 ${CMAKE_CURRENT_BINARY_DIR}/test_glib_signals_utils_marshal.cpp
2136 test_favorite_store_gsettings.cpp
2137+ test_shortcut_model.cpp
2138+ test_shortcut_private.cpp
2139 test_introspection.cpp
2140 test_main_xless.cpp
2141 test_grabhandle.cpp
2142 ${UNITY_SRC}/AbstractLauncherIcon.h
2143+ ${UNITY_SRC}/AbstractShortcutHint.h
2144 ${UNITY_SRC}/Animator.cpp
2145 ${UNITY_SRC}/Animator.h
2146 ${UNITY_SRC}/DebugDBusInterface.h
2147@@ -133,6 +136,11 @@
2148 ${UNITY_SRC}/FavoriteStoreGSettings.cpp
2149 ${UNITY_SRC}/FavoriteStoreGSettings.h
2150 ${UNITY_SRC}/MockLauncherIcon.h
2151+ ${UNITY_SRC}/MockShortcutHint.h
2152+ ${UNITY_SRC}/ShortcutModel.cpp
2153+ ${UNITY_SRC}/ShortcutModel.h
2154+ ${UNITY_SRC}/ShortcutHintPrivate.cpp
2155+ ${UNITY_SRC}/ShortcutHintPrivate.h
2156 ${UNITY_SRC}/SwitcherModel.cpp
2157 ${UNITY_SRC}/SwitcherModel.h
2158 ${UNITY_SRC}/Introspectable.cpp
2159
2160=== added file 'tests/test_shortcut_model.cpp'
2161--- tests/test_shortcut_model.cpp 1970-01-01 00:00:00 +0000
2162+++ tests/test_shortcut_model.cpp 2012-01-13 15:39:27 +0000
2163@@ -0,0 +1,84 @@
2164+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2165+/*
2166+ * Copyright (C) 2011 Canonical Ltd
2167+ *
2168+ * This program is free software: you can redistribute it and/or modify
2169+ * it under the terms of the GNU General Public License version 3 as
2170+ * published by the Free Software Foundation.
2171+ *
2172+ * This program is distributed in the hope that it will be useful,
2173+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2174+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2175+ * GNU General Public License for more details.
2176+ *
2177+ * You should have received a copy of the GNU General Public License
2178+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2179+ *
2180+ * Authored by: Andrea Azzarone <azzaronea@gmail.com>
2181+ */
2182+
2183+#include <gtest/gtest.h>
2184+
2185+#include "MockShortcutHint.h"
2186+#include "ShortcutModel.h"
2187+
2188+using namespace unity::shortcut;
2189+
2190+namespace {
2191+
2192+TEST(TestShortcutModel, TestConstruction)
2193+{
2194+ std::list<AbstractHint*> hints;
2195+
2196+ hints.push_back(new MockHint("Launcher", "", "", "Description 1", COMPIZ_KEY_OPTION, "Plugin 1", "key_option_1"));
2197+ hints.push_back(new MockHint("Launcher", "", "", "Description 2", HARDCODED_OPTION, "Value 2"));
2198+ hints.push_back(new MockHint("Dash", "Prefix", "Postfix", "Description 3", COMPIZ_KEY_OPTION, "Plugin 3", "key_option_3"));
2199+ hints.push_back(new MockHint("Top Bar", "Prefix", "Postfix", "Description 4", HARDCODED_OPTION, "Value4"));
2200+
2201+ Model model(hints);
2202+
2203+ EXPECT_EQ(model.categories().size(), 3);
2204+ EXPECT_EQ(model.hints()["Launcher"].size(), 2);
2205+ EXPECT_EQ(model.hints()["Dash"].size(), 1);
2206+ EXPECT_EQ(model.hints()["Top Bar"].size(), 1);
2207+ EXPECT_EQ(model.hints()["Unity"].size(), 0);
2208+}
2209+
2210+TEST(TestShortcutModel, TestFill)
2211+{
2212+ std::list<AbstractHint*> hints;
2213+
2214+ hints.push_back(new MockHint("Launcher", "", "", "Description 1", COMPIZ_KEY_OPTION, "Plugin 1", "key_option_1"));
2215+ hints.push_back(new MockHint("Launcher", "", "", "Description 2", HARDCODED_OPTION, "Value 2"));
2216+ hints.push_back(new MockHint("Dash", "Prefix", "Postfix", "Description 3", COMPIZ_KEY_OPTION, "Plugin 3", "key_option_3"));
2217+ hints.push_back(new MockHint("Top Bar", "Prefix", "Postfix", "Description 4", HARDCODED_OPTION, "Value 4"));
2218+
2219+ Model model(hints);
2220+
2221+ model.Fill();
2222+
2223+ // We cannot test CompOption here... :/
2224+ EXPECT_EQ(model.hints()["Launcher"].front()->value(), "Plugin 1-key_option_1");
2225+ EXPECT_EQ(model.hints()["Launcher"].back()->value(), "Value 2");
2226+ EXPECT_EQ(model.hints()["Dash"].front()->value(),"Plugin 3-key_option_3");
2227+ EXPECT_EQ(model.hints()["Top Bar"].front()->value(), "Value 4");
2228+}
2229+
2230+TEST(TestShortcutModel, TestProperty)
2231+{
2232+ std::list<AbstractHint*> hints;
2233+
2234+ hints.push_back(new MockHint("Launcher", "Prefix1", "Postfix1", "Description1", COMPIZ_KEY_OPTION, "Plugin1", "key_option1"));
2235+
2236+ Model model(hints);
2237+
2238+ EXPECT_EQ(model.hints()["Launcher"].front()->category(), "Launcher");
2239+ EXPECT_EQ(model.hints()["Launcher"].front()->prefix(), "Prefix1");
2240+ EXPECT_EQ(model.hints()["Launcher"].front()->postfix(), "Postfix1");
2241+ EXPECT_EQ(model.hints()["Launcher"].front()->description(), "Description1");
2242+ EXPECT_EQ(model.hints()["Launcher"].front()->type(), COMPIZ_KEY_OPTION);
2243+ EXPECT_EQ(model.hints()["Launcher"].front()->arg1(), "Plugin1");
2244+ EXPECT_EQ(model.hints()["Launcher"].front()->arg2(), "key_option1");
2245+}
2246+
2247+} // anonymouse namespace
2248
2249=== added file 'tests/test_shortcut_private.cpp'
2250--- tests/test_shortcut_private.cpp 1970-01-01 00:00:00 +0000
2251+++ tests/test_shortcut_private.cpp 2012-01-13 15:39:27 +0000
2252@@ -0,0 +1,74 @@
2253+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2254+/*
2255+ * Copyright (C) 2011 Canonical Ltd
2256+ *
2257+ * This program is free software: you can redistribute it and/or modify
2258+ * it under the terms of the GNU General Public License version 3 as
2259+ * published by the Free Software Foundation.
2260+ *
2261+ * This program is distributed in the hope that it will be useful,
2262+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2263+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2264+ * GNU General Public License for more details.
2265+ *
2266+ * You should have received a copy of the GNU General Public License
2267+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2268+ *
2269+ * Authored by: Andrea Azzarone <azzaronea@gmail.com>
2270+ */
2271+
2272+#include <gtest/gtest.h>
2273+
2274+#include "ShortcutHintPrivate.h"
2275+
2276+using namespace unity::shortcut::impl;
2277+
2278+namespace {
2279+
2280+TEST(TestShortcutHintPrivate, TestFixShortcutFormatCorrect)
2281+{
2282+ EXPECT_EQ(FixShortcutFormat("Super"), "Super");
2283+ EXPECT_EQ(FixShortcutFormat("Super + A"), "Super + A");
2284+}
2285+
2286+
2287+TEST(TestShortcutHintPrivate, TestFixShortcutFormatLT)
2288+{
2289+ EXPECT_EQ(FixShortcutFormat("<Super"), "Super");
2290+ EXPECT_EQ(FixShortcutFormat("<Super + <Alt"), "Super + Alt");
2291+}
2292+
2293+TEST(TestShortcutHintPrivate, TestFixShortcutFormatGT)
2294+{
2295+ EXPECT_EQ(FixShortcutFormat("Super>"), "Super");
2296+ EXPECT_EQ(FixShortcutFormat("Super>A"), "Super + A");
2297+ EXPECT_EQ(FixShortcutFormat("Super>Alt>A"), "Super + Alt + A");
2298+}
2299+
2300+TEST(TestShortcutHintPrivate, TestFixShortcutComplete)
2301+{
2302+ EXPECT_EQ(FixShortcutFormat("Super"), "Super");
2303+ EXPECT_EQ(FixShortcutFormat("Super + A"), "Super + A");
2304+ EXPECT_EQ(FixShortcutFormat("<Super>"), "Super");
2305+ EXPECT_EQ(FixShortcutFormat("<Super>A"), "Super + A");
2306+ EXPECT_EQ(FixShortcutFormat("<Super><Alt>A"), "Super + Alt + A");
2307+}
2308+
2309+TEST(TestShortcutHintPrivate, TestProperCase)
2310+{
2311+ EXPECT_EQ(ProperCase("super"), "Super");
2312+ EXPECT_EQ(ProperCase("sUper"), "SUper");
2313+ EXPECT_EQ(ProperCase("super + a"), "Super + A");
2314+ EXPECT_EQ(ProperCase("super+a"), "Super+A");
2315+ EXPECT_EQ(ProperCase("<super><alt>a"), "<Super><Alt>A");
2316+}
2317+
2318+TEST(TestShortcutHintPrivate, TestFixMouseShortcut)
2319+{
2320+ EXPECT_EQ(FixMouseShortcut("Super<Button1>"), "Super<Left Mouse>");
2321+ EXPECT_EQ(FixMouseShortcut("Super<Button2>"), "Super<Middle Mouse>");
2322+ EXPECT_EQ(FixMouseShortcut("Super<Button3>"), "Super<Right Mouse>");
2323+
2324+}
2325+
2326+} // anonymouse namespace