Merge lp:~unity-team/unity/7.2.2 into lp:unity/7.2

Proposed by Christopher Townsend
Status: Merged
Approved by: Stephen M. Webb
Approved revision: no longer in the source branch.
Merged at revision: 3798
Proposed branch: lp:~unity-team/unity/7.2.2
Merge into: lp:unity/7.2
Diff against target: 3472 lines (+1152/-478)
54 files modified
UnityCore/GnomeSessionManager.cpp (+32/-0)
UnityCore/GnomeSessionManagerImpl.h (+4/-0)
UnityCore/SessionManager.h (+4/-0)
dash/DashController.cpp (+3/-1)
debian/changelog (+59/-0)
hud/HudController.cpp (+1/-0)
launcher/AbstractLauncherIcon.h (+3/-2)
launcher/ApplicationLauncherIcon.cpp (+20/-19)
launcher/ApplicationLauncherIcon.h (+0/-1)
launcher/Launcher.cpp (+26/-10)
launcher/LauncherIcon.cpp (+7/-3)
launcher/LauncherIcon.h (+2/-1)
launcher/SwitcherView.cpp (+54/-31)
launcher/SwitcherView.h (+3/-4)
launcher/TrashLauncherIcon.cpp (+1/-0)
launcher/VolumeLauncherIcon.cpp (+1/-0)
lockscreen/LockScreenAbstractShield.h (+0/-1)
lockscreen/LockScreenController.cpp (+2/-3)
lockscreen/LockScreenShield.cpp (+0/-6)
lockscreen/LockScreenShield.h (+0/-1)
lockscreen/UserPromptView.cpp (+8/-99)
lockscreen/UserPromptView.h (+1/-13)
panel/PanelIndicatorEntryView.cpp (+7/-0)
plugins/unityshell/src/GesturalWindowSwitcher.cpp (+3/-0)
plugins/unityshell/src/GesturalWindowSwitcher.h (+1/-0)
plugins/unityshell/src/unityshell.cpp (+57/-50)
plugins/unityshell/src/unityshell.h (+2/-0)
po/POTFILES.in (+1/-0)
po/unity.pot (+70/-3)
shortcuts/ShortcutController.cpp (+4/-6)
shortcuts/ShortcutView.cpp (+113/-48)
shortcuts/ShortcutView.h (+9/-3)
shutdown/SessionButton.cpp (+30/-5)
shutdown/SessionButton.h (+5/-0)
shutdown/SessionController.cpp (+2/-0)
shutdown/SessionView.cpp (+68/-27)
shutdown/SessionView.h (+5/-0)
tests/test-gestures/LockScreenControllerMock.h (+43/-0)
tests/test-gestures/sed_script_switcher (+2/-0)
tests/test-gestures/unityshell_mock.h (+8/-1)
tests/test_lockscreen_controller.cpp (+0/-1)
tests/test_switcher_view.cpp (+1/-2)
tests/test_unity_window_view.cpp (+9/-9)
unity-shared/EMConverter.cpp (+2/-2)
unity-shared/IMTextEntry.cpp (+7/-0)
unity-shared/IMTextEntry.h (+2/-0)
unity-shared/PluginAdapter.cpp (+43/-10)
unity-shared/RawPixel.cpp (+1/-1)
unity-shared/TextInput.cpp (+178/-4)
unity-shared/TextInput.h (+19/-4)
unity-shared/UnityWindowStyle.cpp (+135/-62)
unity-shared/UnityWindowStyle.h (+35/-20)
unity-shared/UnityWindowView.cpp (+53/-25)
unity-shared/UnityWindowView.h (+6/-0)
To merge this branch: bzr merge lp:~unity-team/unity/7.2.2
Reviewer Review Type Date Requested Status
Marco Trevisan (Treviño) Approve
Review via email: mp+225184@code.launchpad.net

Commit message

Prepare for upstream micro-release 7.2.2 that includes fixes for the following bugs:
Bug #607796: Launcher, Window management - Dragging and holding a selection over an entry in the Launcher should spread out windows belonging to that application
Bug #727902: Launcher icon highlighting should not switch off as soon the cursor moves after the app spread appears.
Bug #741869: Unity/compiz intercepts Super and Alt keypresses from grabbed windows like VMs.
Bug #754580: Cannot move tabs between multiple Firefox or Chromium windows while using Unity unless windows are both unmaximized, unminimized, and visible.
Bug #839728: Launcher - dragging a item on top of a launcher tile that is a valid drop receptacle in the Launcher should cause that launcher tile to glow
Bug #924840: Keyboard shortcuts overlay text too long
Bug #1281058: [UIFe] The system shutdowns when multiple accounts are open
Bug #1283775: Launcher: icon pips are not always updated properly
Bug #1304882: [Regression] Launcher doesn't reappear fully after hiding from DND
Bug #1305586: Lock screen is unusable when some windows have a keyboard/mouse grab
Bug #1307738: Lockscreen caps lock icon drawn under text entry, should be a white icon.
Bug #1308288: Lockscreen warning icon has no tooltip
Bug #1308323: Shutdown/reboot/login/logout dialogs not scaled after toggling UI scale Edit
Bug #1308911: Clipboard contents are accessible within lockscreen
Bug #1309739: Unity launcher icon edge illumination is offset
Bug #1310200: Indicators disappear at the panel (clementine, dropbox, skype etc)
Bug #1313280: Fullscreen window set to "Always on Top" in single-monitor will hide the lockscreen
Bug #1316005: Panel shadow appears over full screen applications w/ locally integrated menus enabled
Bug #1317348: Switcher (Alt-Tab) does not respect monitor-defined scaling factor
Bug #1317356: Shortcut hint does not respect monitor scaling factor
Bug #1317869: Keyboard shortcuts overlay does not show up when workspaces are enabled at 1366x768
Bug #1320438: Unity launcher auto hide fails on screen unlock using "Super+L"
Bug #1321043: [regression] lock screen bypass with touchpad

Description of the change

Prepare for upstream micro-release 7.2.2.

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

Looks fine to me, all the relevant fixes are in and the delta with trunk is now reduced ;)

There's just a comment (about the new translation, but I'm not sure if we're in time for changing it).

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'UnityCore/GnomeSessionManager.cpp'
2--- UnityCore/GnomeSessionManager.cpp 2014-04-10 04:52:59 +0000
3+++ UnityCore/GnomeSessionManager.cpp 2014-07-01 15:44:27 +0000
4@@ -85,6 +85,7 @@
5 , can_hibernate_(false)
6 , pending_action_(shell::Action::NONE)
7 , shell_server_(test_mode_ ? testing::DBUS_NAME : shell::DBUS_NAME)
8+ , open_sessions_(0)
9 {
10 shell_server_.AddObjects(shell::INTROSPECTION_XML, shell::DBUS_OBJECT_PATH);
11 shell_object_ = shell_server_.GetObject(shell::DBUS_INTERFACE);
12@@ -126,6 +127,22 @@
13 });
14 }
15
16+ {
17+ dm_proxy_ = std::make_shared<glib::DBusProxy>("org.freedesktop.DisplayManager",
18+ "/org/freedesktop/DisplayManager",
19+ "org.freedesktop.DisplayManager",
20+ G_BUS_TYPE_SYSTEM);
21+
22+ dm_proxy_->Connect("SessionAdded", sigc::hide(sigc::mem_fun(this, &Impl::UpdateHaveOtherOpenSessions)));
23+ dm_proxy_->Connect("SessionRemoved", sigc::hide(sigc::mem_fun(this, &Impl::UpdateHaveOtherOpenSessions)));
24+
25+ UpdateHaveOtherOpenSessions();
26+
27+ manager_->have_other_open_sessions.SetGetterFunction([this]() {
28+ return open_sessions_ > 1;
29+ });
30+ }
31+
32 CallLogindMethod("CanHibernate", nullptr, [this] (GVariant* variant, glib::Error const& err) {
33 if (err)
34 {
35@@ -422,6 +439,21 @@
36 prompt ? manager_->prompt_lock_requested.emit() : manager_->lock_requested.emit();
37 }
38
39+void GnomeManager::Impl::UpdateHaveOtherOpenSessions()
40+{
41+ dm_proxy_->GetProperty("Sessions", [this](GVariant* variant) {
42+ GVariantIter *sessions;
43+ g_variant_get(variant, "ao", &sessions);
44+ int open_sessions = g_variant_iter_n_children(sessions);
45+
46+ if (open_sessions_ != open_sessions)
47+ {
48+ open_sessions_ = open_sessions;
49+ manager_->have_other_open_sessions.changed.emit(open_sessions_);
50+ }
51+ });
52+}
53+
54 // Public implementation
55
56 GnomeManager::GnomeManager()
57
58=== modified file 'UnityCore/GnomeSessionManagerImpl.h'
59--- UnityCore/GnomeSessionManagerImpl.h 2014-04-09 15:17:46 +0000
60+++ UnityCore/GnomeSessionManagerImpl.h 2014-07-01 15:44:27 +0000
61@@ -61,6 +61,7 @@
62 void CallLogindMethod(std::string const& method, GVariant* parameters = nullptr, glib::DBusProxy::CallFinishedCallback const& cb = nullptr);
63 void CallConsoleKitMethod(std::string const& method, GVariant* parameters = nullptr);
64 bool InteractiveMode();
65+ void UpdateHaveOtherOpenSessions();
66
67 GnomeManager* manager_;
68 bool test_mode_;
69@@ -73,6 +74,9 @@
70 glib::DBusObject::Ptr shell_object_;
71 glib::DBusProxy::Ptr login_proxy_;
72 glib::DBusProxy::Ptr presence_proxy_;
73+ glib::DBusProxy::Ptr dm_proxy_;
74+
75+ int open_sessions_;
76 };
77
78 } // namespace session
79
80=== modified file 'UnityCore/SessionManager.h'
81--- UnityCore/SessionManager.h 2014-04-10 04:47:58 +0000
82+++ UnityCore/SessionManager.h 2014-07-01 15:44:27 +0000
83@@ -23,6 +23,8 @@
84 #include <sigc++/sigc++.h>
85 #include <memory>
86
87+#include <NuxCore/Property.h>
88+
89 namespace unity
90 {
91 namespace session
92@@ -36,6 +38,8 @@
93 Manager() = default;
94 virtual ~Manager() = default;
95
96+ nux::ROProperty<bool> have_other_open_sessions;
97+
98 virtual std::string RealName() const = 0;
99 virtual std::string UserName() const = 0;
100 virtual std::string HostName() const = 0;
101
102=== modified file 'dash/DashController.cpp'
103--- dash/DashController.cpp 2014-04-25 02:42:01 +0000
104+++ dash/DashController.cpp 2014-07-01 15:44:27 +0000
105@@ -104,7 +104,9 @@
106 }
107 });
108
109- WindowManager::Default().initiate_spread.connect(sigc::mem_fun(this, &Controller::HideDash));
110+ auto& wm = WindowManager::Default();
111+ wm.initiate_spread.connect(sigc::mem_fun(this, &Controller::HideDash));
112+ wm.screen_viewport_switch_started.connect(sigc::mem_fun(this, &Controller::HideDash));
113
114 dbus_server_.AddObjects(dbus::INTROSPECTION, dbus::PATH);
115 dbus_server_.GetObjects().front()->SetMethodsCallsHandler([this] (std::string const& method, GVariant*) {
116
117=== modified file 'debian/changelog'
118--- debian/changelog 2014-06-06 14:11:21 +0000
119+++ debian/changelog 2014-07-01 15:44:27 +0000
120@@ -1,3 +1,62 @@
121+unity (7.2.1+14.04.20140513-0ubuntu3) trusty; urgency=medium
122+
123+ [ Alfred Neumayer ]
124+ * Restore the launcher position by reversing the animation and
125+ unsetting the DND_PUSHED_OFF quirk. (LP: #1304882)
126+
127+ [ Brandon Schaefer ]
128+ * TextInput: move the warning icon inside the input field, render it
129+ white (LP: #1307738)
130+ * ShutdownView: Scale up the Buttons and Text plus Borders of the
131+ UnityWindowView. (LP: #1308323)
132+ * Lockscreen warning icon needs a tooltip to say what the warning is
133+ about! (LP: #1308288)
134+
135+ [ Marco Trevisan (Treviño) ]
136+ * UnityScreen: always paint the lockscreen above, just add menu and
137+ onboard as exceptions Some code cleanup, factorizing similar code.
138+ (LP: #1313280)
139+ * ApplicationLauncherIcon: Focus and, in case, Spread the windows on
140+ DnD After 1 second that an user is over an icon, that icon should
141+ focus the relative application and Spread its windows if it has more
142+ than one opened. Correctly handle the DnD scale in launcher, and
143+ apply glow to the icon under pointer. (LP: #607796)
144+ * ShutdownView: Scale up the Buttons and Text plus Borders of the
145+ UnityWindowView. (LP: #1308323)
146+ * SwitcherView: use RawPixel's for the size values and convert them to
147+ match current scaling (LP: #1317348)
148+ * PluginAdapter: try to grab the screen to make sure that the screen
149+ is not grabbed FocusIn event with NotifyGrab mode is not always
150+ triggered by X when a window takes the grab, then we need to ensure
151+ that there's no grab by trying to get one. We only care about
152+ keyboard here, since pointer grabs don't affect us in general.
153+ (LP: #741869)
154+ * ShortcutView: use RawPixel's for the size values and convert them to
155+ match current scaling Plus dinamically allocate horizontal space,
156+ not to cut the text. (LP: #924840)
157+
158+ [ Chris Townsend ]
159+ * Fix issue where scaling the edge illumination up and down with the
160+ size of the Launcher icons would cause the illumination border to be
161+ offset and smaller than the icon. (LP: #1309739)
162+ * Fix issue where the number of Launcher icon pips are not always
163+ properly updated when a new window of an already running application
164+ is opened. (LP: #1283775)
165+ * Fix issue where the Panel shadow would get drawn over drop down
166+ windows in full screen windows. (LP: #1316005)
167+
168+ [ Andrea Azzarone ]
169+ * Clear the clipboard when locking the screen. (LP: #1308911)
170+ * Disable switcher gestures if screen is locked. Fixed a regression.
171+ (LP: #1321043)
172+ * Pass the correct options to showLauncherKeyTerminate in
173+ UnityScreen::OnLockScreen (LP: #1320438)
174+ * Fix skype indicator blinking. (LP: #1310200)
175+ * Add a warning in the session dialog if other sessions are still
176+ open. (LP: #1281058)
177+
178+ -- Chris Townsend <christopher.townsend@canonical.com> Thu, 19 Jun 2014 10:36:15 -0400
179+
180 unity (7.2.1+14.04.20140513-0ubuntu2) trusty; urgency=medium
181
182 [ Brandon Schaefer ]
183
184=== modified file 'hud/HudController.cpp'
185--- hud/HudController.cpp 2014-02-28 16:56:19 +0000
186+++ hud/HudController.cpp 2014-07-01 15:44:27 +0000
187@@ -102,6 +102,7 @@
188 WindowManager& wm = WindowManager::Default();
189 wm.screen_ungrabbed.connect(sigc::mem_fun(this, &Controller::OnScreenUngrabbed));
190 wm.initiate_spread.connect(sigc::mem_fun(this, &Controller::HideHud));
191+ wm.screen_viewport_switch_started.connect(sigc::mem_fun(this, &Controller::HideHud));
192
193 hud_service_.queries_updated.connect(sigc::mem_fun(this, &Controller::OnQueriesFinished));
194 timeline_animator_.updated.connect(sigc::mem_fun(this, &Controller::OnViewShowHideFrame));
195
196=== modified file 'launcher/AbstractLauncherIcon.h'
197--- launcher/AbstractLauncherIcon.h 2014-03-17 20:58:25 +0000
198+++ launcher/AbstractLauncherIcon.h 2014-07-01 15:44:27 +0000
199@@ -110,10 +110,11 @@
200 UNFOLDED,
201 STARTING,
202 SHIMMER,
203- CENTER_SAVED,
204+ DESAT,
205+ GLOW,
206 PROGRESS,
207- DESAT,
208 PULSE_ONCE,
209+ CENTER_SAVED,
210
211 LAST
212 };
213
214=== modified file 'launcher/ApplicationLauncherIcon.cpp'
215--- launcher/ApplicationLauncherIcon.cpp 2014-04-21 15:04:09 +0000
216+++ launcher/ApplicationLauncherIcon.cpp 2014-07-01 15:44:27 +0000
217@@ -49,9 +49,10 @@
218 // We use the "bamf-" prefix since the manager is protected, to avoid name clash
219 const std::string WINDOW_MOVE_TIMEOUT = "bamf-window-move";
220 const std::string ICON_REMOVE_TIMEOUT = "bamf-icon-remove";
221-//const std::string ICON_DND_OVER_TIMEOUT = "bamf-icon-dnd-over";
222+const std::string ICON_DND_OVER_TIMEOUT = "bamf-icon-dnd-over";
223 const std::string DEFAULT_ICON = "application-default-icon";
224 const int MAXIMUM_QUICKLIST_WIDTH = 300;
225+const int COMPIZ_SCALE_DND_SPREAD = 1 << 7;
226
227 enum MenuItemType
228 {
229@@ -723,7 +724,7 @@
230
231 void ApplicationLauncherIcon::EnsureWindowState()
232 {
233- std::bitset<monitors::MAX> monitors;
234+ std::vector<int> number_of_windows_on_monitor(monitors::MAX);
235
236 for (auto& window: app_->GetWindows())
237 {
238@@ -735,18 +736,18 @@
239 // If monitor is -1 (or negative), show on all monitors.
240 if (monitor < 0)
241 {
242- monitors.set();
243- break;
244+ for (unsigned j; j < monitors::MAX; j++)
245+ ++number_of_windows_on_monitor[j];
246 }
247 else
248 {
249- monitors[monitor] = true;
250+ ++number_of_windows_on_monitor[monitor];
251 }
252 }
253 }
254
255 for (unsigned i = 0; i < monitors::MAX; i++)
256- SetWindowVisibleOnMonitor(monitors[i], i);
257+ SetNumberOfWindowsVisibleOnMonitor(number_of_windows_on_monitor[i], i);
258
259 WindowsChanged.emit();
260 }
261@@ -1157,28 +1158,28 @@
262 return _remote_uri;
263 }
264
265-void ApplicationLauncherIcon::OnDndHovered()
266-{
267- // for now, let's not do this, it turns out to be quite buggy
268- //if (IsRunning())
269- // Spread(CompAction::StateInitEdgeDnd, true);
270-}
271-
272 void ApplicationLauncherIcon::OnDndEnter()
273 {
274- /* Disabled, since the DND code is currently disabled as well.
275- _source_manager.AddTimeout(1000, [this] {
276- OnDndHovered();
277+ auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp;
278+
279+ _source_manager.AddTimeout(1000, [this, timestamp] {
280+ WindowManager::Default().TerminateScale();
281+
282+ if (!IsRunning())
283+ return false;
284+
285+ Focus(ActionArg(ActionArg::Source::LAUNCHER, 1, timestamp));
286+
287+ if (GetWindows(WindowFilter::ON_CURRENT_DESKTOP).size() > 1)
288+ Spread(true, COMPIZ_SCALE_DND_SPREAD, false);
289+
290 return false;
291 }, ICON_DND_OVER_TIMEOUT);
292- */
293 }
294
295 void ApplicationLauncherIcon::OnDndLeave()
296 {
297- /* Disabled, since the DND code is currently disabled as well.
298 _source_manager.Remove(ICON_DND_OVER_TIMEOUT);
299- */
300 }
301
302 bool ApplicationLauncherIcon::IsFileManager()
303
304=== modified file 'launcher/ApplicationLauncherIcon.h'
305--- launcher/ApplicationLauncherIcon.h 2014-03-06 21:19:21 +0000
306+++ launcher/ApplicationLauncherIcon.h 2014-07-01 15:44:27 +0000
307@@ -83,7 +83,6 @@
308 void AddProperties(debug::IntrospectionData&);
309 void OnAcceptDrop(DndData const& dnd_data);
310 void OnDndEnter();
311- void OnDndHovered();
312 void OnDndLeave();
313 void OpenInstanceLauncherIcon(Time timestamp) override;
314 void ToggleSticky();
315
316=== modified file 'launcher/Launcher.cpp'
317--- launcher/Launcher.cpp 2014-04-14 13:46:01 +0000
318+++ launcher/Launcher.cpp 2014-07-01 15:44:27 +0000
319@@ -157,6 +157,7 @@
320 hide_machine_.should_hide_changed.connect(sigc::mem_fun(this, &Launcher::SetHidden));
321 hide_machine_.reveal_progress.changed.connect(redraw_cb);
322 hover_machine_.should_hover_changed.connect(sigc::mem_fun(this, &Launcher::SetHover));
323+ bg_effect_helper_.enabled.changed.connect(redraw_cb);
324
325 mouse_down.connect(sigc::mem_fun(this, &Launcher::RecvMouseDown));
326 mouse_up.connect(sigc::mem_fun(this, &Launcher::RecvMouseUp));
327@@ -599,7 +600,7 @@
328 else
329 urgent_progress = CLAMP(urgent_progress * 3.0f - 2.0f, 0.0f, 1.0f); // we want to go 3x faster than the urgent normal cycle
330
331- arg.glow_intensity = urgent_progress;
332+ arg.glow_intensity = icon->GetQuirkProgress(AbstractLauncherIcon::Quirk::GLOW, monitor()) + urgent_progress;
333
334 if (options()->urgent_animation() == URGENT_ANIMATION_WIGGLE)
335 {
336@@ -809,13 +810,11 @@
337 }
338 }
339
340- float drag_hide_progress = dnd_hide_animation_.GetCurrentValue();
341- if (options()->hide_mode != LAUNCHER_HIDE_NEVER && drag_hide_progress > 0.0f)
342+ if (options()->hide_mode != LAUNCHER_HIDE_NEVER)
343 {
344+ float drag_hide_progress = dnd_hide_animation_.GetCurrentValue();
345 autohide_offset -= geo.width * 0.25f * drag_hide_progress;
346-
347- if (drag_hide_progress >= 1.0f)
348- hide_machine_.SetQuirk(LauncherHideMachine::DND_PUSHED_OFF, true);
349+ hide_machine_.SetQuirk(LauncherHideMachine::DND_PUSHED_OFF, (drag_hide_progress >= 1.0f));
350 }
351
352 // Inform the painter where to paint the box
353@@ -1171,6 +1170,9 @@
354 hide_machine_.SetQuirk(LauncherHideMachine::SCALE_ACTIVE, active);
355 bg_effect_helper_.enabled = active;
356
357+ if (hide_machine_.GetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE))
358+ return;
359+
360 if (active && icon_under_mouse_)
361 icon_under_mouse_->HideTooltip();
362
363@@ -1592,6 +1594,7 @@
364 icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::CENTER_SAVED, ANIM_DURATION, monitor());
365 icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::PROGRESS, ANIM_DURATION, monitor());
366 icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::DESAT, ANIM_DURATION_SHORT_SHORT, monitor());
367+ icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::GLOW, ANIM_DURATION_SHORT, monitor());
368
369 if (options()->urgent_animation() == URGENT_ANIMATION_WIGGLE)
370 icon->SetQuirkDuration(AbstractLauncherIcon::Quirk::URGENT, (ANIM_DURATION_SHORT * WIGGLE_CYCLES), monitor());
371@@ -2523,7 +2526,10 @@
372 }
373
374 if (!steal_drag_ && dnd_hovered_icon_)
375+ {
376 dnd_hovered_icon_->SendDndLeave();
377+ dnd_hovered_icon_->SetQuirk(AbstractLauncherIcon::Quirk::GLOW, false, monitor());
378+ }
379
380 steal_drag_ = false;
381 drag_edge_touching_ = false;
382@@ -2535,7 +2541,6 @@
383 {
384 #ifdef USE_X11
385 SetStateMouseOverLauncher(false);
386-
387 DndHoveredIconReset();
388 #endif
389 }
390@@ -2581,7 +2586,10 @@
391 mouse_position_.y <= (parent_->GetGeometry().height - icon_size_.CP(cv_) - 2 * SPACE_BETWEEN_ICONS.CP(cv_)))
392 {
393 if (dnd_hovered_icon_)
394- dnd_hovered_icon_->SendDndLeave();
395+ {
396+ dnd_hovered_icon_->SendDndLeave();
397+ dnd_hovered_icon_->SetQuirk(AbstractLauncherIcon::Quirk::GLOW, false, monitor());
398+ }
399
400 animation::StartOrReverse(dnd_hide_animation_, animation::Direction::FORWARD);
401 drag_edge_touching_ = true;
402@@ -2640,6 +2648,9 @@
403 {
404 hovered_icon->SendDndEnter();
405 drag_action_ = hovered_icon->QueryAcceptDrop(dnd_data_);
406+
407+ if (drag_action_ != nux::DNDACTION_NONE)
408+ hovered_icon->SetQuirk(AbstractLauncherIcon::Quirk::GLOW, true, monitor());
409 }
410 else
411 {
412@@ -2647,7 +2658,10 @@
413 }
414
415 if (dnd_hovered_icon_)
416+ {
417 dnd_hovered_icon_->SendDndLeave();
418+ dnd_hovered_icon_->SetQuirk(AbstractLauncherIcon::Quirk::GLOW, false, monitor());
419+ }
420
421 dnd_hovered_icon_ = hovered_icon;
422 }
423@@ -2790,8 +2804,10 @@
424 }
425 }
426
427- hide_machine_.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false);
428- hide_machine_.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false);
429+
430+ hide_machine_.SetQuirk(LauncherHideMachine::MT_DRAG_OUT, drag_out_delta_x_ >= DRAG_OUT_PIXELS - 90.0f);
431+ hide_machine_.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, false);
432+ animation::SetValue(dnd_hide_animation_, animation::Direction::BACKWARD);
433 #endif
434 }
435
436
437=== modified file 'launcher/LauncherIcon.cpp'
438--- launcher/LauncherIcon.cpp 2014-03-11 09:16:10 +0000
439+++ launcher/LauncherIcon.cpp 2014-07-01 15:44:27 +0000
440@@ -80,6 +80,7 @@
441 , _shortcut(0)
442 , _allow_quicklist_to_show(true)
443 , _center(monitors::MAX)
444+ , _number_of_visible_windows(monitors::MAX)
445 , _quirks(monitors::MAX)
446 , _quirk_animations(monitors::MAX, decltype(_quirk_animations)::value_type(unsigned(Quirk::LAST)))
447 , _last_stable(monitors::MAX)
448@@ -732,12 +733,15 @@
449 return {-1, nux::Point3()};
450 }
451
452-void LauncherIcon::SetWindowVisibleOnMonitor(bool val, int monitor)
453+void LauncherIcon::SetNumberOfWindowsVisibleOnMonitor(int number_of_windows, int monitor)
454 {
455- if (_has_visible_window[monitor] == val)
456+ if (_number_of_visible_windows[monitor] == number_of_windows)
457 return;
458
459- _has_visible_window[monitor] = val;
460+ _has_visible_window[monitor] = (number_of_windows > 0);
461+
462+ _number_of_visible_windows[monitor] = number_of_windows;
463+
464 EmitNeedsRedraw(monitor);
465 }
466
467
468=== modified file 'launcher/LauncherIcon.h'
469--- launcher/LauncherIcon.h 2014-03-11 09:16:10 +0000
470+++ launcher/LauncherIcon.h 2014-07-01 15:44:27 +0000
471@@ -226,7 +226,7 @@
472
473 void SetProgress(float progress);
474
475- void SetWindowVisibleOnMonitor(bool val, int monitor);
476+ void SetNumberOfWindowsVisibleOnMonitor(int number_of_windows, int monitor);
477
478 void Present(float urgency, int length, int monitor = -1);
479
480@@ -338,6 +338,7 @@
481
482 std::vector<nux::Point3> _center;
483 std::bitset<monitors::MAX> _has_visible_window;
484+ std::vector<int> _number_of_visible_windows;
485 std::vector<std::bitset<std::size_t(Quirk::LAST)>> _quirks;
486 std::vector<std::vector<std::shared_ptr<Animation>>> _quirk_animations;
487 std::vector<nux::Point3> _last_stable;
488
489=== modified file 'launcher/SwitcherView.cpp'
490--- launcher/SwitcherView.cpp 2014-03-25 19:07:36 +0000
491+++ launcher/SwitcherView.cpp 2014-07-01 15:44:27 +0000
492@@ -37,26 +37,33 @@
493
494 namespace
495 {
496- unsigned int const VERTICAL_PADDING = 45;
497- unsigned int const SPREAD_OFFSET = 100;
498- unsigned int const EXTRA_ICON_SPACE = 10;
499+ RawPixel const VERTICAL_PADDING = 45_em;
500+ RawPixel const BORDER_SIZE = 50_em;
501+ RawPixel const FLAT_SPACING = 20_em;
502+ RawPixel const ICON_SIZE = 128_em;
503+ RawPixel const MINIMUM_SPACING = 10_em;
504+ RawPixel const TILE_SIZE = 150_em;
505+ RawPixel const SPREAD_OFFSET = 100_em;
506+ RawPixel const EXTRA_ICON_SPACE = 10_em;
507+ RawPixel const TEXT_SIZE = 15_em;
508+
509+ unsigned int const ANIMATION_LENGTH = 250;
510 unsigned int const MAX_DIRECTIONS_CHANGED = 3;
511+ double const TEXT_TILE_MULTIPLIER = 3.5;
512 }
513
514 NUX_IMPLEMENT_OBJECT_TYPE(SwitcherView);
515
516 SwitcherView::SwitcherView(ui::AbstractIconRenderer::Ptr const& renderer)
517 : render_boxes(false)
518- , border_size(50)
519- , flat_spacing(20)
520- , icon_size(128)
521- , minimum_spacing(10)
522- , tile_size(150)
523- , vertical_size(tile_size + VERTICAL_PADDING * 2)
524- , text_size(15)
525- , animation_length(250)
526- , monitor(-1)
527- , spread_size(3.5f)
528+ , border_size(BORDER_SIZE.CP(scale))
529+ , flat_spacing(FLAT_SPACING.CP(scale))
530+ , icon_size(ICON_SIZE.CP(scale))
531+ , minimum_spacing(MINIMUM_SPACING.CP(scale))
532+ , tile_size(TILE_SIZE.CP(scale))
533+ , vertical_size(tile_size + VERTICAL_PADDING.CP(scale) * 2)
534+ , text_size(TEXT_SIZE.CP(scale))
535+ , animation_length(ANIMATION_LENGTH)
536 , icon_renderer_(renderer)
537 , text_view_(new StaticCairoText(""))
538 , animation_(animation_length)
539@@ -68,13 +75,15 @@
540 icon_renderer_->monitor = monitors::MAX;
541 icon_renderer_->SetTargetSize(tile_size, icon_size, minimum_spacing);
542
543- text_view_->SetMaximumWidth(tile_size * spread_size);
544+ text_view_->SetMaximumWidth(tile_size * TEXT_TILE_MULTIPLIER);
545 text_view_->SetLines(1);
546 text_view_->SetTextColor(nux::color::White);
547 text_view_->SetFont("Ubuntu Bold 10");
548+ text_view_->SetScale(scale);
549
550- icon_size.changed.connect (sigc::mem_fun (this, &SwitcherView::OnIconSizeChanged));
551- tile_size.changed.connect (sigc::mem_fun (this, &SwitcherView::OnTileSizeChanged));
552+ icon_size.changed.connect(sigc::mem_fun(this, &SwitcherView::OnIconSizeChanged));
553+ tile_size.changed.connect(sigc::mem_fun(this, &SwitcherView::OnTileSizeChanged));
554+ scale.changed.connect(sigc::mem_fun(this, &SwitcherView::OnScaleChanged));
555
556 mouse_move.connect (sigc::mem_fun(this, &SwitcherView::RecvMouseMove));
557 mouse_down.connect (sigc::mem_fun(this, &SwitcherView::RecvMouseDown));
558@@ -112,10 +121,10 @@
559 .add("vertical-size", vertical_size)
560 .add("text-size", text_size)
561 .add("animation-length", animation_length)
562- .add("spread-size", spread_size)
563+ .add("spread-size", TEXT_TILE_MULTIPLIER)
564 .add("label", text_view_->GetText())
565 .add("last_icon_selected", last_icon_selected_)
566- .add("spread_offset", SPREAD_OFFSET)
567+ .add("spread_offset", SPREAD_OFFSET.CP(scale))
568 .add("label_visible", text_view_->IsVisible());
569 }
570
571@@ -164,15 +173,27 @@
572 text_view_->SetText(model->Selection()->tooltip_text(), true);
573 }
574
575-void SwitcherView::OnIconSizeChanged (int size)
576-{
577- icon_renderer_->SetTargetSize(tile_size, icon_size, minimum_spacing);
578-}
579-
580-void SwitcherView::OnTileSizeChanged (int size)
581-{
582- icon_renderer_->SetTargetSize(tile_size, icon_size, minimum_spacing);
583- vertical_size = tile_size + VERTICAL_PADDING * 2;
584+void SwitcherView::OnIconSizeChanged(int size)
585+{
586+ icon_renderer_->SetTargetSize(tile_size, icon_size, minimum_spacing);
587+}
588+
589+void SwitcherView::OnTileSizeChanged(int size)
590+{
591+ icon_renderer_->SetTargetSize(tile_size, icon_size, minimum_spacing);
592+ vertical_size = tile_size + VERTICAL_PADDING.CP(scale) * 2;
593+}
594+
595+void SwitcherView::OnScaleChanged(double scale)
596+{
597+ text_view_->SetScale(scale);
598+ border_size = BORDER_SIZE.CP(scale);
599+ flat_spacing = FLAT_SPACING.CP(scale);
600+ icon_size = ICON_SIZE.CP(scale);
601+ minimum_spacing = MINIMUM_SPACING.CP(scale);
602+ tile_size = TILE_SIZE.CP(scale);
603+ text_size = TEXT_SIZE.CP(scale);
604+ vertical_size = tile_size + VERTICAL_PADDING.CP(scale) * 2;
605 }
606
607 void SwitcherView::StartAnimation()
608@@ -699,7 +720,10 @@
609 background_geo.height = vertical_size;
610
611 if (text_view_->IsVisible())
612+ {
613 background_geo.height += text_size;
614+ text_view_->SetBaseY(background_geo.y + background_geo.height - VERTICAL_PADDING.CP(scale));
615+ }
616
617 if (model_)
618 {
619@@ -714,7 +738,7 @@
620 nux::Geometry const& spread_bounds = UpdateRenderTargets(progress);
621 ResizeRenderTargets(spread_bounds, progress);
622 // remove extra space consumed by spread
623- spread_padded_width = spread_bounds.width + SPREAD_OFFSET;
624+ spread_padded_width = spread_bounds.width + SPREAD_OFFSET.CP(scale);
625 max_width -= spread_padded_width - tile_size;
626
627 int expansion = std::max(0, spread_bounds.height - icon_size);
628@@ -953,7 +977,6 @@
629 if (text_view_->IsVisible())
630 {
631 nux::GetPainter().PushPaintLayerStack();
632- text_view_->SetBaseY(last_background_.y + last_background_.height - 45);
633 text_view_->Draw(GfxContext, force_draw);
634 nux::GetPainter().PopPaintLayerStack();
635 }
636@@ -961,7 +984,7 @@
637
638 int SwitcherView::IconIndexAt(int x, int y) const
639 {
640- int half_size = icon_size.Get() / 2 + EXTRA_ICON_SPACE;
641+ int half_size = icon_size.Get() / 2 + EXTRA_ICON_SPACE.CP(scale);
642 int icon_index = -1;
643
644 // Taking icon rotation into consideration will make selection more
645@@ -998,7 +1021,7 @@
646
647 for (unsigned int i = 0; i < render_targets_.size(); ++i)
648 {
649- if (render_targets_[i]->result.IsPointInside(x + SPREAD_OFFSET, y + SPREAD_OFFSET))
650+ if (render_targets_[i]->result.IsPointInside(x + SPREAD_OFFSET.CP(scale), y + SPREAD_OFFSET.CP(scale)))
651 return i;
652 }
653
654
655=== modified file 'launcher/SwitcherView.h'
656--- launcher/SwitcherView.h 2014-03-25 19:07:36 +0000
657+++ launcher/SwitcherView.h 2014-07-01 15:44:27 +0000
658@@ -65,8 +65,6 @@
659 nux::Property<int> vertical_size;
660 nux::Property<int> text_size;
661 nux::Property<int> animation_length;
662- nux::Property<int> monitor;
663- nux::Property<double> spread_size;
664
665 void SkipAnimation();
666
667@@ -135,8 +133,9 @@
668 void OnDetailSelectionChanged (bool detail);
669 void OnDetailSelectionIndexChanged (unsigned int index);
670
671- void OnIconSizeChanged (int size);
672- void OnTileSizeChanged (int size);
673+ void OnIconSizeChanged(int size);
674+ void OnTileSizeChanged(int size);
675+ void OnScaleChanged(double scale);
676
677 nux::Geometry UpdateRenderTargets(float progress);
678 void ResizeRenderTargets(nux::Geometry const& layout_geo, float progress);
679
680=== modified file 'launcher/TrashLauncherIcon.cpp'
681--- launcher/TrashLauncherIcon.cpp 2014-01-15 14:51:10 +0000
682+++ launcher/TrashLauncherIcon.cpp 2014-07-01 15:44:27 +0000
683@@ -173,6 +173,7 @@
684 }
685
686 SetQuirk(LauncherIcon::Quirk::PULSE_ONCE, true);
687+ FullyAnimateQuirkDelayed(100, LauncherIcon::Quirk::SHIMMER);
688 }
689
690 std::string TrashLauncherIcon::GetName() const
691
692=== modified file 'launcher/VolumeLauncherIcon.cpp'
693--- launcher/VolumeLauncherIcon.cpp 2014-02-13 10:14:20 +0000
694+++ launcher/VolumeLauncherIcon.cpp 2014-07-01 15:44:27 +0000
695@@ -410,6 +410,7 @@
696 auto timestamp = nux::GetGraphicsDisplay()->GetCurrentEvent().x11_timestamp;
697 pimpl_->CopyFilesToVolume(dnd_data.Uris(), timestamp);
698 SetQuirk(Quirk::PULSE_ONCE, true);
699+ FullyAnimateQuirkDelayed(100, LauncherIcon::Quirk::SHIMMER);
700 }
701
702 //
703
704=== modified file 'lockscreen/LockScreenAbstractShield.h'
705--- lockscreen/LockScreenAbstractShield.h 2014-04-17 13:08:05 +0000
706+++ lockscreen/LockScreenAbstractShield.h 2014-07-01 15:44:27 +0000
707@@ -49,7 +49,6 @@
708
709 using MockableBaseWindow::RemoveLayout;
710 virtual bool IsIndicatorOpen() const = 0;
711- virtual void CheckCapsLockPrompt() = 0;
712 virtual void ActivatePanel() = 0;
713
714 sigc::signal<void, int, int> grab_motion;
715
716=== modified file 'lockscreen/LockScreenController.cpp'
717--- lockscreen/LockScreenController.cpp 2014-05-13 17:15:11 +0000
718+++ lockscreen/LockScreenController.cpp 2014-07-01 15:44:27 +0000
719@@ -171,7 +171,6 @@
720
721 primary_shield_->primary = false;
722 primary_shield_ = shield;
723- primary_shield_->CheckCapsLockPrompt();
724 shield->primary = true;
725 nux::GetWindowCompositor().SetAlwaysOnFrontWindow(primary_shield_.GetPointer());
726 auto move_cb = sigc::mem_fun(this, &Controller::OnPrimaryShieldMotion);
727@@ -330,9 +329,9 @@
728 prompt_activation_ = prompt;
729
730 lockscreen_timeout_.reset(new glib::Timeout(30, [this] {
731- bool grabbed_by_blank = (blank_window_ && blank_window_->OwnsPointerGrab());
732+ bool grabbed_by_blank = (blank_window_ && blank_window_->OwnsKeyboardGrab());
733
734- if (WindowManager::Default().IsScreenGrabbed() && !grabbed_by_blank)
735+ if (!grabbed_by_blank && WindowManager::Default().IsScreenGrabbed())
736 {
737 HideBlankWindow();
738 LOG_DEBUG(logger) << "Failed to lock the screen: the screen is already grabbed.";
739
740=== modified file 'lockscreen/LockScreenShield.cpp'
741--- lockscreen/LockScreenShield.cpp 2014-05-13 17:15:11 +0000
742+++ lockscreen/LockScreenShield.cpp 2014-07-01 15:44:27 +0000
743@@ -86,12 +86,6 @@
744 }
745 }
746
747-void Shield::CheckCapsLockPrompt()
748-{
749- if (prompt_view_)
750- prompt_view_->CheckIfCapsLockOn();
751-}
752-
753 void Shield::ShowPrimaryView()
754 {
755 GrabPointer();
756
757=== modified file 'lockscreen/LockScreenShield.h'
758--- lockscreen/LockScreenShield.h 2014-05-13 17:15:11 +0000
759+++ lockscreen/LockScreenShield.h 2014-07-01 15:44:27 +0000
760@@ -39,7 +39,6 @@
761 Shield(session::Manager::Ptr const&, indicator::Indicators::Ptr const&, Accelerators::Ptr const&, int monitor, bool is_primary);
762
763 bool IsIndicatorOpen() const override;
764- void CheckCapsLockPrompt() override;
765 void ActivatePanel() override;
766
767 protected:
768
769=== modified file 'lockscreen/UserPromptView.cpp'
770--- lockscreen/UserPromptView.cpp 2014-04-25 21:58:08 +0000
771+++ lockscreen/UserPromptView.cpp 2014-07-01 15:44:27 +0000
772@@ -21,12 +21,10 @@
773
774 #include <boost/algorithm/string/trim.hpp>
775 #include <Nux/VLayout.h>
776-#include <X11/XKBlib.h>
777
778 #include "LockScreenSettings.h"
779 #include "unity-shared/CairoTexture.h"
780 #include "unity-shared/DashStyle.h"
781-#include "unity-shared/PreviewStyle.h"
782 #include "unity-shared/TextInput.h"
783 #include "unity-shared/StaticCairoText.h"
784 #include "unity-shared/RawPixel.h"
785@@ -40,9 +38,9 @@
786 const RawPixel PADDING = 10_em;
787 const RawPixel LAYOUT_MARGIN = 10_em;
788 const RawPixel MSG_LAYOUT_MARGIN = 15_em;
789-const RawPixel PROMPT_LAYOUT_MARGIN = 5_em;
790+const RawPixel PROMPT_LAYOUT_MARGIN = 5_em;
791
792-const int PROMPT_FONT_SIZE = 13;
793+const int PROMPT_FONT_SIZE = 13;
794
795 nux::AbstractPaintLayer* CrateBackgroundLayer(int width, int height)
796 {
797@@ -78,28 +76,6 @@
798 rop));
799 }
800
801-nux::AbstractPaintLayer* CreateWarningLayer(nux::BaseTexture* texture)
802-{
803- // Create the texture layer
804- nux::TexCoordXForm texxform;
805-
806- texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
807- texxform.SetWrap(nux::TEXWRAP_REPEAT, nux::TEXWRAP_REPEAT);
808- texxform.min_filter = nux::TEXFILTER_LINEAR;
809- texxform.mag_filter = nux::TEXFILTER_LINEAR;
810-
811- nux::ROPConfig rop;
812- rop.Blend = true;
813- rop.SrcBlend = GL_ONE;
814- rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
815-
816- return (new nux::TextureLayer(texture->GetDeviceTexture(),
817- texxform,
818- nux::color::White,
819- true,
820- rop));
821-}
822-
823 std::string SanitizeMessage(std::string const& message)
824 {
825 std::string msg = boost::algorithm::trim_copy(message);
826@@ -124,7 +100,6 @@
827 UserPromptView::UserPromptView(session::Manager::Ptr const& session_manager)
828 : nux::View(NUX_TRACKER_LOCATION)
829 , session_manager_(session_manager)
830- , caps_lock_on_(false)
831 {
832 user_authenticator_.echo_on_requested.connect([this](std::string const& message, PromiseAuthCodePtr const& promise){
833 AddPrompt(message, /* visible */ true, promise);
834@@ -146,32 +121,10 @@
835 ResetLayout();
836 });
837
838- dash::previews::Style& preview_style = dash::previews::Style::Instance();
839-
840- warning_ = preview_style.GetWarningIcon();
841 ResetLayout();
842
843 user_authenticator_.AuthenticateStart(session_manager_->UserName(),
844 sigc::mem_fun(this, &UserPromptView::AuthenticationCb));
845-
846- // When we get to HiDPI changes here, we will need to update this width
847- dash::Style& style = dash::Style::Instance();
848- spin_icon_width_ = style.GetSearchSpinIcon()->GetWidth();
849-
850- CheckIfCapsLockOn();
851-}
852-
853-void UserPromptView::CheckIfCapsLockOn()
854-{
855- Display *dpy = nux::GetGraphicsDisplay()->GetX11Display();
856- unsigned int state = 0;
857- XkbGetIndicatorState(dpy, XkbUseCoreKbd, &state);
858-
859- // Caps is on 0x1, couldn't find any #define in /usr/include/X11
860- if ((state & 0x1) == 1)
861- caps_lock_on_ = true;
862- else
863- caps_lock_on_ = false;
864 }
865
866 bool UserPromptView::InspectKeyEvent(unsigned int eventType, unsigned int key_sym, const char* character)
867@@ -179,7 +132,7 @@
868 if ((eventType == nux::NUX_KEYDOWN) && (key_sym == NUX_VK_ESCAPE))
869 {
870 if (!focus_queue_.empty())
871- focus_queue_.front()->SetText("");
872+ focus_queue_.front()->text_entry()->SetText("");
873
874 return true;
875 }
876@@ -260,15 +213,6 @@
877 nux::GetPainter().PushLayer(graphics_engine, geo, bg_layer_.get());
878 }
879
880- if (caps_lock_on_)
881- {
882- for (auto const& text_entry : focus_queue_)
883- PaintWarningIcon(graphics_engine, text_entry->GetGeometry());
884-
885- if (focus_queue_.empty())
886- PaintWarningIcon(graphics_engine, cached_focused_geo_);
887- }
888-
889 if (GetLayout())
890 GetLayout()->ProcessDraw(graphics_engine, force_draw);
891
892@@ -278,49 +222,16 @@
893 graphics_engine.PopClippingRectangle();
894 }
895
896-void UserPromptView::PaintWarningIcon(nux::GraphicsEngine& graphics_engine, nux::Geometry const& geo)
897-{
898- nux::Geometry warning_geo = {geo.x + geo.width - GetWarningIconOffset(),
899- geo.y, warning_->GetWidth(), warning_->GetHeight()};
900-
901- nux::GetPainter().PushLayer(graphics_engine, warning_geo, CreateWarningLayer(warning_));
902-}
903-
904-int UserPromptView::GetWarningIconOffset()
905-{
906- return warning_->GetWidth() + spin_icon_width_;
907-}
908-
909 nux::View* UserPromptView::focus_view()
910 {
911 if (focus_queue_.empty())
912 return nullptr;
913
914 for (auto* view : focus_queue_)
915- if (view->HasKeyboardFocus())
916+ if (view->text_entry()->HasKeyboardFocus())
917 return view;
918
919- return focus_queue_.front();
920-}
921-
922-void UserPromptView::ToggleCapsLockBool()
923-{
924- caps_lock_on_ = !caps_lock_on_;
925- QueueDraw();
926-}
927-
928-void UserPromptView::RecvKeyUp(unsigned keysym,
929- unsigned long keycode,
930- unsigned long state)
931-{
932- if (!caps_lock_on_ && keysym == NUX_VK_CAPITAL)
933- {
934- ToggleCapsLockBool();
935- }
936- else if (caps_lock_on_ && keysym == NUX_VK_CAPITAL)
937- {
938- ToggleCapsLockBool();
939- }
940+ return focus_queue_.front()->text_entry();
941 }
942
943 void UserPromptView::AddPrompt(std::string const& message, bool visible, PromiseAuthCodePtr const& promise)
944@@ -330,18 +241,16 @@
945
946 text_input->input_hint = SanitizeMessage(message);
947 text_input->hint_font_size = PROMPT_FONT_SIZE;
948+ text_input->show_caps_lock = true;
949 text_entry->SetPasswordMode(!visible);
950 text_entry->SetPasswordChar("•");
951 text_entry->SetToggleCursorVisibilityOnKeyFocus(true);
952-
953- text_entry->key_up.connect(sigc::mem_fun(this, &UserPromptView::RecvKeyUp));
954+ text_entry->clipboard_enabled = false;
955
956 text_input->SetMinimumHeight(Settings::GRID_SIZE);
957 text_input->SetMaximumHeight(Settings::GRID_SIZE);
958 prompt_layout_->AddView(text_input, 1);
959- focus_queue_.push_back(text_entry);
960-
961- CheckIfCapsLockOn();
962+ focus_queue_.push_back(text_input);
963
964 // Don't remove it, it helps with a11y.
965 if (focus_queue_.size() == 1)
966
967=== modified file 'lockscreen/UserPromptView.h'
968--- lockscreen/UserPromptView.h 2014-04-09 17:09:18 +0000
969+++ lockscreen/UserPromptView.h 2014-07-01 15:44:27 +0000
970@@ -56,8 +56,6 @@
971 void AddMessage(std::string const& message, nux::Color const& color);
972 void AuthenticationCb(bool authenticated);
973
974- void CheckIfCapsLockOn();
975-
976 protected:
977 void Draw(nux::GraphicsEngine& graphics_engine, bool force_draw) override;
978 void DrawContent(nux::GraphicsEngine& graphics_engine, bool force_draw) override;
979@@ -66,12 +64,6 @@
980 void ResetLayout();
981
982 bool InspectKeyEvent(unsigned int eventType, unsigned int key_sym, const char* character);
983- void RecvKeyUp(unsigned int, unsigned long, unsigned long);
984-
985- void PaintWarningIcon(nux::GraphicsEngine& graphics_engine, nux::Geometry const& geo);
986- void ToggleCapsLockBool();
987-
988- int GetWarningIconOffset();
989
990 session::Manager::Ptr session_manager_;
991 UserAuthenticatorPam user_authenticator_;
992@@ -81,13 +73,9 @@
993 StaticCairoText* message_;
994 StaticCairoText* error_;
995 StaticCairoText* invalid_login_;
996- std::deque<IMTextEntry*> focus_queue_;
997+ std::deque<TextInput*> focus_queue_;
998
999- nux::BaseTexture* warning_;
1000 nux::Geometry cached_focused_geo_;
1001-
1002- bool caps_lock_on_;
1003- int spin_icon_width_;
1004 };
1005
1006 }
1007
1008=== modified file 'panel/PanelIndicatorEntryView.cpp'
1009--- panel/PanelIndicatorEntryView.cpp 2014-03-31 21:08:10 +0000
1010+++ panel/PanelIndicatorEntryView.cpp 2014-07-01 15:44:27 +0000
1011@@ -229,6 +229,13 @@
1012 {
1013 glib::Object<GIcon> icon(g_icon_new_for_string(proxy_->image_data().c_str(), nullptr));
1014 info = gtk_icon_theme_lookup_by_gicon(theme, icon, size, flags);
1015+
1016+ if (!info)
1017+ {
1018+ // Maybe the icon was just added to the theme, see if a rescan helps.
1019+ gtk_icon_theme_rescan_if_needed(theme);
1020+ info = gtk_icon_theme_lookup_by_gicon(theme, icon, size, flags);
1021+ }
1022 }
1023 else
1024 {
1025
1026=== modified file 'plugins/unityshell/src/GesturalWindowSwitcher.cpp'
1027--- plugins/unityshell/src/GesturalWindowSwitcher.cpp 2013-07-01 17:07:40 +0000
1028+++ plugins/unityshell/src/GesturalWindowSwitcher.cpp 2014-07-01 15:44:27 +0000
1029@@ -115,6 +115,9 @@
1030
1031 GestureDeliveryRequest GesturalWindowSwitcherPrivate::GestureEvent(nux::GestureEvent const& event)
1032 {
1033+ if (unity_screen->lockscreen_controller()->IsLocked())
1034+ return GestureDeliveryRequest::NONE;
1035+
1036 switch (state)
1037 {
1038 case State::WaitingCompoundGesture:
1039
1040=== modified file 'plugins/unityshell/src/GesturalWindowSwitcher.h'
1041--- plugins/unityshell/src/GesturalWindowSwitcher.h 2013-01-24 16:32:35 +0000
1042+++ plugins/unityshell/src/GesturalWindowSwitcher.h 2014-07-01 15:44:27 +0000
1043@@ -77,6 +77,7 @@
1044 private:
1045 GesturalWindowSwitcherPrivate* p;
1046 };
1047+
1048 typedef std::shared_ptr<GesturalWindowSwitcher> ShPtGesturalWindowSwitcher;
1049
1050 } // namespace unity
1051
1052=== modified file 'plugins/unityshell/src/unityshell.cpp'
1053--- plugins/unityshell/src/unityshell.cpp 2014-05-02 15:05:37 +0000
1054+++ plugins/unityshell/src/unityshell.cpp 2014-07-01 15:44:27 +0000
1055@@ -101,7 +101,7 @@
1056 DECLARE_LOGGER(logger, "unity.shell.compiz");
1057 namespace
1058 {
1059-UnityScreen* uScreen = 0;
1060+UnityScreen* uScreen = nullptr;
1061
1062 void reset_glib_logging();
1063 void configure_logging();
1064@@ -168,6 +168,8 @@
1065 , _key_nav_mode_requested(false)
1066 , _last_output(nullptr)
1067 , force_draw_countdown_(0)
1068+ , firstWindowAboveShell(nullptr)
1069+ , onboard_(nullptr)
1070 , grab_index_(0)
1071 , painting_tray_ (false)
1072 , last_scroll_event_(0)
1073@@ -522,6 +524,7 @@
1074
1075 void UnityScreen::OnInitiateSpread()
1076 {
1077+ scale_just_activated_ = super_keypressed_;
1078 spread_filter_ = std::make_shared<spread::Filter>();
1079 spread_filter_->text.changed.connect([this] (std::string const& filter) {
1080 if (filter.empty())
1081@@ -940,7 +943,8 @@
1082
1083 bool UnityScreen::forcePaintOnTop()
1084 {
1085- return !allowWindowPaint ||
1086+ return !allowWindowPaint ||
1087+ lockscreen_controller_->IsLocked() ||
1088 ((switcher_controller_->Visible() ||
1089 WindowManager::Default().IsExpoActive())
1090 && !fullscreen_windows_.empty () && (!(screen->grabbed () && !screen->otherGrabExist (NULL))));
1091@@ -1185,6 +1189,20 @@
1092 return window->minimized ();
1093 }
1094
1095+bool UnityWindow::CanBypassLockScreen() const
1096+{
1097+ if (window->type() == CompWindowTypePopupMenuMask &&
1098+ uScreen->lockscreen_controller_->HasOpenMenu())
1099+ {
1100+ return true;
1101+ }
1102+
1103+ if (window == uScreen->onboard_)
1104+ return true;
1105+
1106+ return false;
1107+}
1108+
1109 void UnityWindow::DoOverrideFrameRegion(CompRegion &region)
1110 {
1111 unsigned int oldUpdateFrameRegionIndex = window->updateFrameRegionGetCurrentIndex();
1112@@ -1984,19 +2002,7 @@
1113 {
1114 PluginAdapter& adapter = PluginAdapter::Default();
1115 adapter.NotifyCompizEvent(plugin, event, option);
1116- compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow>::handleCompizEvent (plugin, event, option);
1117-
1118- if (launcher_controller_->IsOverlayOpen() && g_strcmp0(event, "start_viewport_switch") == 0)
1119- {
1120- ubus_manager_.SendMessage(UBUS_OVERLAY_CLOSE_REQUEST);
1121- }
1122-
1123- if (super_keypressed_ && g_strcmp0(plugin, "scale") == 0 &&
1124- g_strcmp0(event, "activate") == 0)
1125- {
1126- scale_just_activated_ = CompOption::getBoolOptionNamed(option, "active");
1127- }
1128-
1129+ compiz::CompizMinimizedWindowHandler<UnityScreen, UnityWindow>::handleCompizEvent(plugin, event, option);
1130 screen->handleCompizEvent(plugin, event, option);
1131 }
1132
1133@@ -2834,9 +2840,7 @@
1134 * fully covers the shell on its output. It does not include regular windows
1135 * stacked above the shell like DnD icons or Onboard etc.
1136 */
1137- if (G_UNLIKELY(is_nux_window_) &&
1138- (!uScreen->lockscreen_controller_->IsLocked() ||
1139- uScreen->lockscreen_controller_->opacity() != 1.0f))
1140+ if (G_UNLIKELY(is_nux_window_))
1141 {
1142 if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
1143 {
1144@@ -2893,9 +2897,7 @@
1145
1146 if (uScreen->lockscreen_controller_->IsLocked())
1147 {
1148- if ((window->type() != CompWindowTypePopupMenuMask ||
1149- !uScreen->lockscreen_controller_->HasOpenMenu()) &&
1150- !window->minimized() && window->resName() != "onboard")
1151+ if (!window->minimized() && !CanBypassLockScreen())
1152 {
1153 // For some reasons PAINT_WINDOW_NO_CORE_INSTANCE_MASK doesn't work here
1154 // (well, it works too much, as it applies to menus too), so we need
1155@@ -2968,6 +2970,7 @@
1156 {
1157 auto window_state = window->state();
1158 auto window_type = window->type();
1159+ bool locked = uScreen->lockscreen_controller_->IsLocked();
1160
1161 if (uScreen->doShellRepaint && !uScreen->paint_panel_under_dash_ && window_type == CompWindowTypeNormalMask)
1162 {
1163@@ -2984,12 +2987,16 @@
1164 }
1165
1166 if (uScreen->doShellRepaint &&
1167- !uScreen->forcePaintOnTop () &&
1168 window == uScreen->firstWindowAboveShell &&
1169+ !uScreen->forcePaintOnTop() &&
1170 !uScreen->fullscreenRegion.contains(window->geometry()))
1171 {
1172 uScreen->paintDisplay();
1173 }
1174+ else if (locked && CanBypassLockScreen())
1175+ {
1176+ uScreen->paintDisplay();
1177+ }
1178
1179 enum class DrawPanelShadow
1180 {
1181@@ -3019,7 +3026,7 @@
1182 }
1183 else
1184 {
1185- if (window->id() == active_window || decoration::Style::Get()->integrated_menus())
1186+ if (window->id() == active_window)
1187 {
1188 draw_panel_shadow = DrawPanelShadow::BELOW_WINDOW;
1189 uScreen->is_desktop_active_ = false;
1190@@ -3038,6 +3045,10 @@
1191 }
1192 }
1193 }
1194+ else if (decoration::Style::Get()->integrated_menus())
1195+ {
1196+ draw_panel_shadow = DrawPanelShadow::BELOW_WINDOW;
1197+ }
1198 else
1199 {
1200 if (uScreen->is_desktop_active_)
1201@@ -3052,7 +3063,7 @@
1202 }
1203 }
1204
1205- if (uScreen->lockscreen_controller_->IsLocked())
1206+ if (locked)
1207 draw_panel_shadow = DrawPanelShadow::NO;
1208
1209 if (draw_panel_shadow == DrawPanelShadow::BELOW_WINDOW)
1210@@ -3808,8 +3819,12 @@
1211 screen->removeAction(&action);
1212
1213 // We notify that super/alt have been released, to avoid to leave unity in inconsistent state
1214- showLauncherKeyTerminate(&optionGetShowLauncher(), CompAction::StateTermKey, getOptions());
1215- showMenuBarTerminate(&optionGetShowMenuBar(), CompAction::StateTermKey, getOptions());
1216+ CompOption::Vector options(8);
1217+ options[7].setName("time", CompOption::TypeInt);
1218+ options[7].value().set((int) screen->getCurrentTime());
1219+
1220+ showLauncherKeyTerminate(&optionGetShowLauncher(), CompAction::StateTermKey, options);
1221+ showMenuBarTerminate(&optionGetShowMenuBar(), CompAction::StateTermKey, options);
1222 }
1223
1224 void UnityScreen::OnScreenUnlocked()
1225@@ -3854,14 +3869,14 @@
1226
1227 void UnityScreen::RaiseOSK()
1228 {
1229- /* stack any windows named "onboard" above us */
1230- for (CompWindow *w : screen->windows ())
1231+ /* stack the onboard window above us */
1232+ if (onboard_)
1233 {
1234- if (w->resName() == "onboard")
1235+ if (nux::BaseWindow* dash = dash_controller_->window())
1236 {
1237- Window xid = dash_controller_->window()->GetInputWindowId();
1238- XSetTransientForHint (screen->dpy(), w->id(), xid);
1239- w->raise ();
1240+ Window xid = dash->GetInputWindowId();
1241+ XSetTransientForHint(screen->dpy(), onboard_->id(), xid);
1242+ onboard_->raise();
1243 }
1244 }
1245 }
1246@@ -3946,8 +3961,10 @@
1247 CompOption::Value v(launcher_width);
1248 screen->setOptionForPlugin("expo", "x_offset", v);
1249
1250- if (launcher_controller_->options()->hide_mode != LAUNCHER_HIDE_NEVER)
1251- screen->setOptionForPlugin("scale", "x_offset", v);
1252+ if (launcher_controller_->options()->hide_mode == LAUNCHER_HIDE_NEVER)
1253+ v.set(0);
1254+
1255+ screen->setOptionForPlugin("scale", "x_offset", v);
1256 };
1257
1258 for (auto const& launcher : launcher_controller_->launchers())
1259@@ -4108,23 +4125,10 @@
1260 if (window->state() & CompWindowStateFullscreenMask)
1261 uScreen->fullscreen_windows_.push_back(window);
1262
1263- /* We might be starting up so make sure that
1264- * we don't deref the dashcontroller that doesnt
1265- * exist */
1266- dash::Controller::Ptr dp = uScreen->dash_controller_;
1267-
1268- if (dp)
1269+ if (window->type() == CompWindowTypeUtilMask && window->resName() == "onboard")
1270 {
1271- nux::BaseWindow* w = dp->window ();
1272-
1273- if (w)
1274- {
1275- if (window->resName() == "onboard")
1276- {
1277- Window xid = dp->window()->GetInputWindowId();
1278- XSetTransientForHint (screen->dpy(), window->id(), xid);
1279- }
1280- }
1281+ uScreen->onboard_ = window;
1282+ uScreen->RaiseOSK();
1283 }
1284 }
1285
1286@@ -4505,6 +4509,9 @@
1287 if (window->state () & CompWindowStateFullscreenMask)
1288 uScreen->fullscreen_windows_.remove(window);
1289
1290+ if (window == uScreen->onboard_)
1291+ uScreen->onboard_ = nullptr;
1292+
1293 uScreen->fake_decorated_windows_.erase(this);
1294 PluginAdapter::Default().OnWindowClosed(window);
1295 }
1296
1297=== modified file 'plugins/unityshell/src/unityshell.h'
1298--- plugins/unityshell/src/unityshell.h 2014-04-29 15:22:38 +0000
1299+++ plugins/unityshell/src/unityshell.h 2014-07-01 15:44:27 +0000
1300@@ -393,6 +393,7 @@
1301 CompRegion nuxRegion;
1302 CompRegion fullscreenRegion;
1303 CompWindow* firstWindowAboveShell;
1304+ CompWindow* onboard_;
1305
1306 ::GLFramebufferObject *oldFbo;
1307
1308@@ -520,6 +521,7 @@
1309 bool IsInShowdesktopMode ();
1310 bool IsShaded ();
1311 bool IsMinimized ();
1312+ bool CanBypassLockScreen() const;
1313 void DoOverrideFrameRegion (CompRegion &r);
1314
1315 void DoHide ();
1316
1317=== modified file 'po/POTFILES.in'
1318--- po/POTFILES.in 2014-04-02 12:31:33 +0000
1319+++ po/POTFILES.in 2014-07-01 15:44:27 +0000
1320@@ -48,5 +48,6 @@
1321 unity-shared/DashStyle.cpp
1322 unity-shared/PreviewStyle.cpp
1323 unity-shared/SearchBar.cpp
1324+unity-shared/TextInput.cpp
1325 unity-shared/UScreen.cpp
1326 gnome/50-unity-launchers.xml.in
1327
1328=== modified file 'po/unity.pot'
1329--- po/unity.pot 2014-03-10 17:51:32 +0000
1330+++ po/unity.pot 2014-07-01 15:44:27 +0000
1331@@ -8,7 +8,7 @@
1332 msgstr ""
1333 "Project-Id-Version: PACKAGE VERSION\n"
1334 "Report-Msgid-Bugs-To: ayatana-dev@lists.launchpad.net\n"
1335-"POT-Creation-Date: 2013-04-17 16:00+0100\n"
1336+"POT-Creation-Date: 2014-07-01 11:21-0400\n"
1337 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1338 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1339 "Language-Team: LANGUAGE <LL@li.org>\n"
1340@@ -38,6 +38,26 @@
1341 msgid "Last Updated"
1342 msgstr ""
1343
1344+#. The "%s" is used in the dash preview to display the "<hint>: <value>" infos
1345+#, c-format
1346+msgid "%s:"
1347+msgstr ""
1348+
1349+msgid "Comments"
1350+msgstr ""
1351+
1352+msgid "This window is not responding"
1353+msgstr ""
1354+
1355+msgid "Do you want to force the application to exit, or wait for it to respond?"
1356+msgstr ""
1357+
1358+msgid "_Wait"
1359+msgstr ""
1360+
1361+msgid "_Force Quit"
1362+msgstr ""
1363+
1364 msgid "Type your command"
1365 msgstr ""
1366
1367@@ -50,6 +70,12 @@
1368 msgid "Quit"
1369 msgstr ""
1370
1371+msgid "Exit"
1372+msgstr ""
1373+
1374+msgid "Close"
1375+msgstr ""
1376+
1377 msgid "Search your computer and online sources"
1378 msgstr ""
1379
1380@@ -69,13 +95,16 @@
1381 msgid "Waiting to install"
1382 msgstr ""
1383
1384+msgid "Installing…"
1385+msgstr ""
1386+
1387 msgid "Drop To Add Application"
1388 msgstr ""
1389
1390 msgid "Trash"
1391 msgstr ""
1392
1393-msgid "Empty Trash..."
1394+msgid "Empty Trash…"
1395 msgstr ""
1396
1397 msgid "Open"
1398@@ -96,6 +125,15 @@
1399 msgid "Unmount"
1400 msgstr ""
1401
1402+msgid "Password"
1403+msgstr ""
1404+
1405+msgid "Username"
1406+msgstr ""
1407+
1408+msgid "Invalid password, please try again"
1409+msgstr ""
1410+
1411 msgid "Ubuntu Desktop"
1412 msgstr ""
1413
1414@@ -105,6 +143,14 @@
1415 msgid "Launcher"
1416 msgstr ""
1417
1418+#, c-format
1419+msgid "%s: running: %zu windows open"
1420+msgstr ""
1421+
1422+#, c-format
1423+msgid "%s: running"
1424+msgstr ""
1425+
1426 msgid "Quicklist"
1427 msgstr ""
1428
1429@@ -165,6 +211,9 @@
1430 msgid "Opens the Dash Music Lens."
1431 msgstr ""
1432
1433+msgid "Opens the Dash Photo Lens."
1434+msgstr ""
1435+
1436 msgid "Opens the Dash Video Lens."
1437 msgstr ""
1438
1439@@ -210,6 +259,9 @@
1440 msgid "Switches between applications."
1441 msgstr ""
1442
1443+msgid "Switches between applications from all workspaces."
1444+msgstr ""
1445+
1446 msgid "Switches windows of current applications."
1447 msgstr ""
1448
1449@@ -234,6 +286,12 @@
1450 msgid "Spreads all windows in the current workspace."
1451 msgstr ""
1452
1453+msgid "Spreads all windows."
1454+msgstr ""
1455+
1456+msgid "Spreads all windows in all the workspaces."
1457+msgstr ""
1458+
1459 msgid "Minimises all windows."
1460 msgstr ""
1461
1462@@ -258,7 +316,7 @@
1463 msgid "Places the window in corresponding position."
1464 msgstr ""
1465
1466-msgid "Ctrl + Alt + Num"
1467+msgid "Ctrl + Alt + Num (keypad)"
1468 msgstr ""
1469
1470 msgid " Drag"
1471@@ -270,6 +328,11 @@
1472 msgid "Resizes the window."
1473 msgstr ""
1474
1475+msgid ""
1476+"Other users are logged in. Restarting or shutting down will close their open applications and may cause them to lose work.\n"
1477+"\n"
1478+msgstr ""
1479+
1480 msgid "Shut Down"
1481 msgstr ""
1482
1483@@ -327,3 +390,7 @@
1484
1485 msgid "Filter results"
1486 msgstr ""
1487+
1488+#. avoid wrap lines
1489+msgid "Caps lock is on"
1490+msgstr ""
1491
1492=== added file 'resources/launcher_icon_glow_62.png'
1493Binary files resources/launcher_icon_glow_62.png 1970-01-01 00:00:00 +0000 and resources/launcher_icon_glow_62.png 2014-07-01 15:44:27 +0000 differ
1494=== renamed file 'resources/launcher_icon_glow_62.svg' => 'resources/launcher_icon_glow_62.svg.save'
1495=== modified file 'shortcuts/ShortcutController.cpp'
1496--- shortcuts/ShortcutController.cpp 2014-04-05 20:09:17 +0000
1497+++ shortcuts/ShortcutController.cpp 2014-07-01 15:44:27 +0000
1498@@ -70,14 +70,12 @@
1499 if (!view_)
1500 return;
1501
1502+ model->Fill();
1503 view_->SetModel(model);
1504
1505 if (Visible())
1506 {
1507- model->Fill();
1508- auto uscreen = UScreen::GetDefault();
1509- int monitor = uscreen->GetMonitorAtPosition(view_window_->GetX(), view_window_->GetX());
1510- auto const& offset = GetOffsetPerMonitor(monitor);
1511+ auto const& offset = GetOffsetPerMonitor(view_->monitor());
1512
1513 if (offset.x < 0 || offset.y < 0)
1514 {
1515@@ -110,8 +108,8 @@
1516 modeller_->GetCurrentModel()->Fill();
1517 EnsureView();
1518
1519- int monitor = UScreen::GetDefault()->GetMonitorWithMouse();
1520- auto const& offset = GetOffsetPerMonitor(monitor);
1521+ view_->monitor = UScreen::GetDefault()->GetMonitorWithMouse();
1522+ auto const& offset = GetOffsetPerMonitor(view_->monitor());
1523
1524 if (offset.x < 0 || offset.y < 0)
1525 return false;
1526
1527=== modified file 'shortcuts/ShortcutView.cpp'
1528--- shortcuts/ShortcutView.cpp 2013-11-16 11:44:23 +0000
1529+++ shortcuts/ShortcutView.cpp 2014-07-01 15:44:27 +0000
1530@@ -38,10 +38,16 @@
1531 const unsigned MAIN_TITLE_FONT_SIZE = 15;
1532 const unsigned SECTION_NAME_FONT_SIZE = 12;
1533 const unsigned SHORTKEY_ENTRY_FONT_SIZE = 9;
1534- const unsigned INTER_SPACE_SHORTKEY_DESCRIPTION = 10;
1535- const unsigned SHORTKEY_COLUMN_WIDTH = 150;
1536- const unsigned DESCRIPTION_COLUMN_WIDTH = 265;
1537- const unsigned LINE_SPACING = 5;
1538+ const RawPixel INTER_SPACE_SHORTKEY_DESCRIPTION = 10_em;
1539+ const RawPixel SHORTKEY_COLUMN_DEFAULT_WIDTH = 150_em;
1540+ const RawPixel SHORTKEY_COLUMN_MAX_WIDTH = 350_em;
1541+ const RawPixel DESCRIPTION_COLUMN_DEFAULT_WIDTH = 265_em;
1542+ const RawPixel DESCRIPTION_COLUMN_MAX_WIDTH = 500_em;
1543+ const RawPixel LINE_SPACING = 3_em;
1544+ const RawPixel MAIN_HORIZONTAL_PADDING = 30_em;
1545+ const RawPixel MAIN_VERTICAL_PADDING = 18_em;
1546+ const RawPixel MAIN_CHILDREN_SPACE = 20_em;
1547+ const RawPixel COLUMNS_CHILDREN_SPACE = 30_em;
1548
1549 // We need this class because SetVisible doesn't work for layouts.
1550 class SectionView : public nux::View
1551@@ -72,8 +78,8 @@
1552 : ui::UnityWindowView()
1553 {
1554 auto main_layout = new nux::VLayout();
1555- main_layout->SetPadding(30, 18);
1556- main_layout->SetSpaceBetweenChildren(20);
1557+ main_layout->SetPadding(MAIN_HORIZONTAL_PADDING.CP(scale), MAIN_VERTICAL_PADDING.CP(scale));
1558+ main_layout->SetSpaceBetweenChildren(MAIN_CHILDREN_SPACE.CP(scale));
1559 SetLayout(main_layout);
1560
1561 std::string header = "<b>"+std::string(_("Keyboard Shortcuts"))+"</b>";
1562@@ -81,13 +87,22 @@
1563 auto* header_view = new StaticCairoText(header, NUX_TRACKER_LOCATION);
1564 header_view->SetFont(FONT_NAME+" "+std::to_string(MAIN_TITLE_FONT_SIZE));
1565 header_view->SetLines(-1);
1566+ header_view->SetScale(scale);
1567 main_layout->AddView(header_view, 1 , nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
1568
1569 main_layout->AddView(new HSeparator(), 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
1570
1571 columns_layout_ = new nux::HLayout();
1572- columns_layout_->SetSpaceBetweenChildren(30);
1573+ columns_layout_->SetSpaceBetweenChildren(COLUMNS_CHILDREN_SPACE.CP(scale));
1574 main_layout->AddLayout(columns_layout_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
1575+
1576+ scale.changed.connect([this, main_layout, header_view] (double scale) {
1577+ main_layout->SetPadding(MAIN_HORIZONTAL_PADDING.CP(scale), MAIN_VERTICAL_PADDING.CP(scale));
1578+ main_layout->SetSpaceBetweenChildren(MAIN_CHILDREN_SPACE.CP(scale));
1579+ columns_layout_->SetSpaceBetweenChildren(COLUMNS_CHILDREN_SPACE.CP(scale));
1580+ header_view->SetScale(scale);
1581+ RenderColumns();
1582+ });
1583 }
1584
1585 void View::SetModel(Model::Ptr model)
1586@@ -114,14 +129,17 @@
1587 auto* section_name_view = new StaticCairoText(name, NUX_TRACKER_LOCATION);
1588 section_name_view->SetFont(FONT_NAME+" "+std::to_string(SECTION_NAME_FONT_SIZE));
1589 section_name_view->SetLines(-1);
1590- layout->AddView(new nux::SpaceLayout(10, 10, 10, 10), 0, nux::MINOR_POSITION_START, nux::MINOR_SIZE_MATCHCONTENT);
1591+ section_name_view->SetScale(scale);
1592+ const int top_space = (10_em).CP(scale);
1593+ const int bottom_space = (15_em).CP(scale);
1594+ layout->AddView(new nux::SpaceLayout(top_space, top_space, top_space, top_space), 0, nux::MINOR_POSITION_START, nux::MINOR_SIZE_MATCHCONTENT);
1595 layout->AddView(section_name_view, 0, nux::MINOR_POSITION_START, nux::MINOR_SIZE_MATCHCONTENT);
1596- layout->AddView(new nux::SpaceLayout(15, 15, 15, 15), 0, nux::MINOR_POSITION_START, nux::MINOR_SIZE_MATCHCONTENT);
1597+ layout->AddView(new nux::SpaceLayout(bottom_space, bottom_space, bottom_space, bottom_space), 0, nux::MINOR_POSITION_START, nux::MINOR_SIZE_MATCHCONTENT);
1598
1599 return layout;
1600 }
1601
1602-nux::View* View::CreateShortKeyEntryView(AbstractHint::Ptr const& hint)
1603+nux::View* View::CreateShortKeyEntryView(AbstractHint::Ptr const& hint, StaticCairoText* shortkey_view, StaticCairoText* description_view)
1604 {
1605 auto* view = new SectionView(NUX_TRACKER_LOCATION);
1606
1607@@ -131,56 +149,56 @@
1608 nux::HLayout* shortkey_layout = new nux::HLayout(NUX_TRACKER_LOCATION);
1609 nux::HLayout* description_layout = new nux::HLayout(NUX_TRACKER_LOCATION);
1610
1611- glib::String shortkey(g_markup_escape_text(hint->shortkey().c_str(), -1));
1612-
1613- std::string skey = "<b>"+shortkey.Str()+"</b>";
1614- auto* shortkey_view = new StaticCairoText(skey, NUX_TRACKER_LOCATION);
1615- shortkey_view->SetTextAlignment(StaticCairoText::AlignState::NUX_ALIGN_LEFT);
1616- shortkey_view->SetFont(FONT_NAME+" "+std::to_string(SHORTKEY_ENTRY_FONT_SIZE));
1617- shortkey_view->SetLines(-1);
1618- shortkey_view->SetMinimumWidth(SHORTKEY_COLUMN_WIDTH);
1619- shortkey_view->SetMaximumWidth(SHORTKEY_COLUMN_WIDTH);
1620-
1621- glib::String es_desc(g_markup_escape_text(hint->description().c_str(), -1));
1622-
1623- auto* description_view = new StaticCairoText(es_desc.Str(), NUX_TRACKER_LOCATION);
1624- description_view->SetTextAlignment(StaticCairoText::AlignState::NUX_ALIGN_LEFT);
1625- description_view->SetFont(FONT_NAME+" "+std::to_string(SHORTKEY_ENTRY_FONT_SIZE));
1626- description_view->SetLines(-1);
1627- description_view->SetMinimumWidth(DESCRIPTION_COLUMN_WIDTH);
1628- description_view->SetMaximumWidth(DESCRIPTION_COLUMN_WIDTH);
1629-
1630 shortkey_layout->AddView(shortkey_view, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_MATCHCONTENT);
1631 shortkey_layout->SetContentDistribution(nux::MAJOR_POSITION_START);
1632- shortkey_layout->SetMinimumWidth(SHORTKEY_COLUMN_WIDTH);
1633- shortkey_layout->SetMaximumWidth(SHORTKEY_COLUMN_WIDTH);
1634
1635 description_layout->AddView(description_view, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_MATCHCONTENT);
1636 description_layout->SetContentDistribution(nux::MAJOR_POSITION_START);
1637- description_layout->SetMinimumWidth(DESCRIPTION_COLUMN_WIDTH);
1638- description_layout->SetMaximumWidth(DESCRIPTION_COLUMN_WIDTH);
1639
1640 layout->AddLayout(shortkey_layout, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_MATCHCONTENT);
1641 layout->AddLayout(description_layout, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_MATCHCONTENT);
1642- layout->SetSpaceBetweenChildren(INTER_SPACE_SHORTKEY_DESCRIPTION);
1643+ layout->SetSpaceBetweenChildren(INTER_SPACE_SHORTKEY_DESCRIPTION.CP(scale));
1644 description_layout->SetContentDistribution(nux::MAJOR_POSITION_START);
1645
1646- view->key_changed_conn_ = hint->shortkey.changed.connect([this, view, shortkey_view] (std::string const& new_key) {
1647- bool enabled = !new_key.empty();
1648- shortkey_view->SetText(enabled ? "<b>"+new_key+"</b>" : "");
1649- view->SetVisible(enabled);
1650+ view->key_changed_conn_ = hint->shortkey.changed.connect([this, view, shortkey_view] (std::string const& key) {
1651+ std::string escaped = glib::String(g_markup_escape_text(key.c_str(), -1)).Str();
1652+
1653+ if (!escaped.empty())
1654+ escaped = "<b>"+escaped+"</b>";
1655+
1656+ shortkey_view->SetText(escaped);
1657+ shortkey_view->SetVisible(!escaped.empty());
1658+ view->SetVisible(shortkey_view->IsVisible());
1659 QueueRelayout();
1660+ QueueDraw();
1661 });
1662
1663- view->SetVisible(!shortkey.Str().empty());
1664+ view->SetVisible(shortkey_view->IsVisible());
1665
1666 return view;
1667 }
1668
1669+StaticCairoText* View::CreateShortcutTextView(std::string const& text, bool bold)
1670+{
1671+ std::string escaped = glib::String(g_markup_escape_text(text.c_str(), -1)).Str();
1672+
1673+ if (bold && !text.empty())
1674+ escaped = "<b>"+escaped+"</b>";
1675+
1676+ auto* text_view = new StaticCairoText(escaped, NUX_TRACKER_LOCATION);
1677+ text_view->SetTextAlignment(StaticCairoText::AlignState::NUX_ALIGN_LEFT);
1678+ text_view->SetFont(FONT_NAME+" "+std::to_string(SHORTKEY_ENTRY_FONT_SIZE));
1679+ text_view->SetLines(-1);
1680+ text_view->SetScale(scale);
1681+ text_view->SetVisible(!escaped.empty());
1682+
1683+ return text_view;
1684+}
1685+
1686 nux::LinearLayout* View::CreateIntermediateLayout()
1687 {
1688 nux::VLayout* layout = new nux::VLayout(NUX_TRACKER_LOCATION);
1689- layout->SetSpaceBetweenChildren(LINE_SPACING);
1690+ layout->SetSpaceBetweenChildren(LINE_SPACING.CP(scale));
1691
1692 return layout;
1693 }
1694@@ -195,9 +213,38 @@
1695 view_layout_->ProcessDraw(GfxContext, force_draw);
1696 }
1697
1698+void View::PreLayoutManagement()
1699+{
1700+ UnityWindowView::PreLayoutManagement();
1701+
1702+ for (auto const& column : shortkeys_)
1703+ {
1704+ int min_width = SHORTKEY_COLUMN_DEFAULT_WIDTH.CP(scale);
1705+
1706+ for (auto* shortkey : column)
1707+ min_width = std::min(std::max(min_width, shortkey->GetTextExtents().width), shortkey->GetMaximumWidth());
1708+
1709+ for (auto* shortkey : column)
1710+ shortkey->SetMinimumWidth(min_width);
1711+ }
1712+
1713+ for (auto const& column : descriptions_)
1714+ {
1715+ int min_width = DESCRIPTION_COLUMN_DEFAULT_WIDTH.CP(scale);
1716+
1717+ for (auto* description : column)
1718+ min_width = std::min(std::max(min_width, description->GetTextExtents().width), description->GetMaximumWidth());
1719+
1720+ for (auto* description : column)
1721+ description->SetMinimumWidth(min_width);
1722+ }
1723+}
1724+
1725 void View::RenderColumns()
1726 {
1727 columns_layout_->Clear();
1728+ shortkeys_.clear();
1729+ descriptions_.clear();
1730
1731 if (!model_)
1732 {
1733@@ -209,11 +256,21 @@
1734 int i = 0;
1735 int column_idx = 0;
1736 auto const& columns = columns_layout_->GetChildren();
1737-
1738- for (auto const& category : model_->categories())
1739+ auto const& categories = model_->categories();
1740+ const int categories_per_column = model_->categories_per_column();
1741+ const int columns_number = categories.size() / categories_per_column + 1;
1742+ const int top_space = (23_em).CP(scale);
1743+ const int bottom_space = (20_em).CP(scale);
1744+ const int max_shortkeys_width = SHORTKEY_COLUMN_MAX_WIDTH.CP(scale);
1745+ const int max_descriptions_width = DESCRIPTION_COLUMN_MAX_WIDTH.CP(scale);
1746+
1747+ shortkeys_.resize(columns_number);
1748+ descriptions_.resize(columns_number);
1749+
1750+ for (auto const& category : categories)
1751 {
1752 // Computing column index based on current index
1753- column_idx = i/model_->categories_per_column();
1754+ column_idx = i/categories_per_column;
1755
1756 nux::LinearLayout* section_layout = CreateSectionLayout(category);
1757 nux::LinearLayout* intermediate_layout = CreateIntermediateLayout();
1758@@ -221,19 +278,27 @@
1759
1760 for (auto const& hint : model_->hints().at(category))
1761 {
1762- nux::View* view = CreateShortKeyEntryView(hint);
1763+ StaticCairoText* shortkey = CreateShortcutTextView(hint->shortkey(), true);
1764+ shortkey->SetMaximumWidth(max_shortkeys_width);
1765+ shortkeys_[column_idx].push_back(shortkey);
1766+
1767+ StaticCairoText* description = CreateShortcutTextView(hint->description(), false);
1768+ description->SetMaximumWidth(max_descriptions_width);
1769+ descriptions_[column_idx].push_back(description);
1770+
1771+ nux::View* view = CreateShortKeyEntryView(hint, shortkey, description);
1772 intermediate_layout->AddView(view, 0, nux::MINOR_POSITION_START, nux::MINOR_SIZE_FULL);
1773 }
1774
1775 section_layout->AddLayout(intermediate_layout, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
1776
1777- if ((i + 1) % model_->categories_per_column() != 0 && category != model_->categories().back())
1778+ if ((i + 1) % categories_per_column != 0 && category != categories.back())
1779 {
1780 // Add a line with some padding after and before each category that is not
1781 // the last of the column.
1782- section_layout->AddView(new nux::SpaceLayout(23, 23, 23, 23), 0, nux::MINOR_POSITION_START, nux::MINOR_SIZE_MATCHCONTENT);
1783+ section_layout->AddView(new nux::SpaceLayout(top_space, top_space, top_space, top_space), 0, nux::MINOR_POSITION_START, nux::MINOR_SIZE_MATCHCONTENT);
1784 section_layout->AddView(new HSeparator(), 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
1785- section_layout->AddView(new nux::SpaceLayout(20, 20, 20, 20), 0, nux::MINOR_POSITION_START, nux::MINOR_SIZE_MATCHCONTENT);
1786+ section_layout->AddView(new nux::SpaceLayout(bottom_space, bottom_space, bottom_space, bottom_space), 0, nux::MINOR_POSITION_START, nux::MINOR_SIZE_MATCHCONTENT);
1787 }
1788
1789 nux::VLayout* column = nullptr;
1790@@ -251,7 +316,7 @@
1791
1792 column->AddView(section_layout, 1, nux::MINOR_POSITION_START, nux::MINOR_SIZE_FULL);
1793
1794- i++;
1795+ ++i;
1796 }
1797
1798 ComputeContentSize();
1799
1800=== modified file 'shortcuts/ShortcutView.h'
1801--- shortcuts/ShortcutView.h 2013-11-16 11:44:23 +0000
1802+++ shortcuts/ShortcutView.h 2014-07-01 15:44:27 +0000
1803@@ -29,6 +29,8 @@
1804
1805 namespace unity
1806 {
1807+class StaticCairoText;
1808+
1809 namespace shortcut
1810 {
1811
1812@@ -47,8 +49,9 @@
1813
1814 protected:
1815 // Protected methods
1816- void DrawOverlay(nux::GraphicsEngine& GfxContext, bool force_draw, nux::Geometry const& clip);
1817- nux::Geometry GetBackgroundGeometry();
1818+ void DrawOverlay(nux::GraphicsEngine& GfxContext, bool force_draw, nux::Geometry const& clip) override;
1819+ nux::Geometry GetBackgroundGeometry() override;
1820+ void PreLayoutManagement() override;
1821
1822 // Introspectable methods
1823 std::string GetName() const;
1824@@ -56,7 +59,8 @@
1825 private:
1826 // Private methods
1827 nux::LinearLayout* CreateSectionLayout(std::string const& section_name);
1828- nux::View* CreateShortKeyEntryView(AbstractHint::Ptr const& hint);
1829+ nux::View* CreateShortKeyEntryView(AbstractHint::Ptr const&, StaticCairoText* shortkey, StaticCairoText* description);
1830+ StaticCairoText* CreateShortcutTextView(std::string const& text, bool bold);
1831 nux::LinearLayout* CreateIntermediateLayout();
1832
1833 void RenderColumns();
1834@@ -64,6 +68,8 @@
1835 // Private members
1836 Model::Ptr model_;
1837 nux::HLayout* columns_layout_;
1838+ std::vector<std::vector<StaticCairoText*>> shortkeys_;
1839+ std::vector<std::vector<StaticCairoText*>> descriptions_;
1840
1841 friend class TestShortcutView;
1842 };
1843
1844=== modified file 'shutdown/SessionButton.cpp'
1845--- shutdown/SessionButton.cpp 2014-02-25 01:07:06 +0000
1846+++ shutdown/SessionButton.cpp 2014-07-01 15:44:27 +0000
1847@@ -30,15 +30,15 @@
1848
1849 namespace style
1850 {
1851- const std::string FONT = "Ubuntu Light 12";
1852-
1853- const unsigned BUTTON_SPACE = 9;
1854+ std::string const FONT = "Ubuntu Light 12";
1855+ RawPixel const BUTTON_SPACE = 9_em;
1856 }
1857
1858 NUX_IMPLEMENT_OBJECT_TYPE(Button);
1859
1860 Button::Button(Action action, NUX_FILE_LINE_DECL)
1861 : nux::View(NUX_FILE_LINE_PARAM)
1862+ , scale(1.0)
1863 , highlighted(false)
1864 , action([this] { return action_; })
1865 , label([this] { return label_view_->GetText(); })
1866@@ -78,14 +78,21 @@
1867 break;
1868 }
1869
1870- normal_tex_.Adopt(nux::CreateTexture2DFromFile((texture_prefix + ".png").c_str(), -1, true));
1871- highlight_tex_.Adopt(nux::CreateTexture2DFromFile((texture_prefix + "_highlight.png").c_str(), -1, true));
1872+ UpdateTextures(texture_prefix);
1873
1874 auto main_layout = new nux::VLayout();
1875 main_layout->SetContentDistribution(nux::MAJOR_POSITION_CENTER);
1876 main_layout->SetSpaceBetweenChildren(style::BUTTON_SPACE);
1877 SetLayout(main_layout);
1878
1879+ scale.changed.connect([this, main_layout, texture_prefix] (double new_scale) {
1880+ main_layout->SetSpaceBetweenChildren(style::BUTTON_SPACE.CP(new_scale));
1881+ label_view_->SetScale(new_scale);
1882+
1883+ UpdateTextures(texture_prefix);
1884+ image_view_->SetTexture(highlighted ? highlight_tex_ : normal_tex_);
1885+ });
1886+
1887 image_view_ = new IconTexture(normal_tex_);
1888 image_view_->SetInputEventSensitivity(false);
1889 main_layout->AddView(image_view_, 1, nux::MINOR_POSITION_CENTER);
1890@@ -111,6 +118,24 @@
1891 });
1892 }
1893
1894+void Button::UpdateTextures(std::string const& texture_prefix)
1895+{
1896+ RawPixel const texture_size = GetDefaultMaxTextureSize(texture_prefix);
1897+
1898+ normal_tex_.Adopt(nux::CreateTexture2DFromFile((texture_prefix + ".png").c_str(), texture_size.CP(scale), true));
1899+ highlight_tex_.Adopt(nux::CreateTexture2DFromFile((texture_prefix + "_highlight.png").c_str(), texture_size.CP(scale), true));
1900+}
1901+
1902+RawPixel Button::GetDefaultMaxTextureSize(std::string const& texture_prefix) const
1903+{
1904+ nux::Size size;
1905+ auto const& texture_name = (texture_prefix + ".png");
1906+ gdk_pixbuf_get_file_info(texture_name.c_str(), &size.width, &size.height);
1907+ RawPixel max_size = std::max(size.width, size.height);
1908+
1909+ return max_size;
1910+}
1911+
1912 void Button::Draw(nux::GraphicsEngine& ctx, bool force)
1913 {
1914 GetLayout()->ProcessDraw(ctx, force);
1915
1916=== modified file 'shutdown/SessionButton.h'
1917--- shutdown/SessionButton.h 2014-02-25 01:07:06 +0000
1918+++ shutdown/SessionButton.h 2014-07-01 15:44:27 +0000
1919@@ -26,6 +26,7 @@
1920
1921 #include "unity-shared/IconTexture.h"
1922 #include "unity-shared/Introspectable.h"
1923+#include "unity-shared/RawPixel.h"
1924 #include "unity-shared/StaticCairoText.h"
1925
1926 namespace unity
1927@@ -49,6 +50,7 @@
1928
1929 Button(Action, NUX_FILE_LINE_PROTO);
1930
1931+ nux::Property<double> scale;
1932 nux::Property<bool> highlighted;
1933 nux::ROProperty<Action> action;
1934 nux::ROProperty<std::string> label;
1935@@ -65,6 +67,9 @@
1936 private:
1937 friend class TestSessionButton;
1938
1939+ void UpdateTextures(std::string const& texture_prefix);
1940+ RawPixel GetDefaultMaxTextureSize(std::string const& texture_prefix) const;
1941+
1942 Action action_;
1943 IconTexture* image_view_;
1944 StaticCairoText* label_view_;
1945
1946=== modified file 'shutdown/SessionController.cpp'
1947--- shutdown/SessionController.cpp 2014-04-30 14:59:29 +0000
1948+++ shutdown/SessionController.cpp 2014-07-01 15:44:27 +0000
1949@@ -151,6 +151,8 @@
1950 {
1951 view_->size_changed.connect([this] (nux::Area*, int, int) {
1952 int monitor = UScreen::GetDefault()->GetMonitorWithMouse();
1953+ view_->monitor = monitor;
1954+
1955 auto const& offset = GetOffsetPerMonitor(monitor);
1956 view_window_->SetXY(offset.x, offset.y);
1957 });
1958
1959=== modified file 'shutdown/SessionView.cpp'
1960--- shutdown/SessionView.cpp 2013-11-20 21:39:40 +0000
1961+++ shutdown/SessionView.cpp 2014-07-01 15:44:27 +0000
1962@@ -20,10 +20,11 @@
1963 #include "SessionView.h"
1964 #include "SessionButton.h"
1965
1966-#include <Nux/VLayout.h>
1967 #include <UnityCore/GLibWrapper.h>
1968 #include <glib/gi18n-lib.h>
1969
1970+#include "unity-shared/RawPixel.h"
1971+
1972 namespace unity
1973 {
1974 namespace session
1975@@ -31,15 +32,15 @@
1976
1977 namespace style
1978 {
1979- const std::string FONT = "Ubuntu Light";
1980- const std::string TITLE_FONT = FONT+" 15";
1981- const std::string SUBTITLE_FONT = FONT+" 12";
1982+ std::string const FONT = "Ubuntu Light";
1983+ std::string const TITLE_FONT = FONT+" 15";
1984+ std::string const SUBTITLE_FONT = FONT+" 12";
1985
1986- const unsigned LEFT_RIGHT_PADDING = 30;
1987- const unsigned TOP_PADDING = 19;
1988- const unsigned BOTTOM_PADDING = 12;
1989- const unsigned MAIN_SPACE = 10;
1990- const unsigned BUTTONS_SPACE = 20;
1991+ RawPixel const LEFT_RIGHT_PADDING = 30_em;
1992+ RawPixel const TOP_PADDING = 19_em;
1993+ RawPixel const BOTTOM_PADDING = 12_em;
1994+ RawPixel const MAIN_SPACE = 10_em;
1995+ RawPixel const BUTTONS_SPACE = 20_em;
1996 }
1997
1998 NUX_IMPLEMENT_OBJECT_TYPE(View);
1999@@ -51,18 +52,15 @@
2000 , key_focus_area_(this)
2001 {
2002 closable = true;
2003- auto main_layout = new nux::VLayout();
2004- main_layout->SetTopAndBottomPadding(style::TOP_PADDING, style::BOTTOM_PADDING);
2005- main_layout->SetLeftAndRightPadding(style::LEFT_RIGHT_PADDING);
2006- main_layout->SetSpaceBetweenChildren(style::MAIN_SPACE);
2007- SetLayout(main_layout);
2008+ main_layout_ = new nux::VLayout();
2009+ SetLayout(main_layout_);
2010
2011 title_ = new StaticCairoText("");
2012 title_->SetFont(style::TITLE_FONT);
2013 title_->SetTextAlignment(StaticCairoText::AlignState::NUX_ALIGN_LEFT);
2014 title_->SetInputEventSensitivity(false);
2015 title_->SetVisible(false);
2016- main_layout->AddView(title_);
2017+ main_layout_->AddView(title_);
2018
2019 subtitle_ = new StaticCairoText("");
2020 subtitle_->SetFont(style::SUBTITLE_FONT);
2021@@ -70,15 +68,15 @@
2022 subtitle_->SetInputEventSensitivity(false);
2023 subtitle_->SetLines(std::numeric_limits<int>::min());
2024 subtitle_->SetLineSpacing(2);
2025- main_layout->AddView(subtitle_);
2026+ main_layout_->AddView(subtitle_);
2027
2028 buttons_layout_ = new nux::HLayout();
2029- buttons_layout_->SetSpaceBetweenChildren(style::BUTTONS_SPACE);
2030- main_layout->AddLayout(buttons_layout_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_PERCENTAGE, 0.0f);
2031+ main_layout_->AddLayout(buttons_layout_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_PERCENTAGE, 0.0f);
2032
2033 GetBoundingArea()->mouse_click.connect([this] (int, int, unsigned long, unsigned long) { request_close.emit(); });
2034
2035 have_inhibitors.changed.connect(sigc::hide(sigc::mem_fun(this, &View::UpdateText)));
2036+ manager_->have_other_open_sessions.changed.connect(sigc::hide(sigc::mem_fun(this, &View::UpdateText)));
2037
2038 mode.SetSetterFunction([this] (Mode& target, Mode new_mode) {
2039 if (new_mode == Mode::SHUTDOWN && !manager_->CanShutdown())
2040@@ -98,30 +96,61 @@
2041 Populate();
2042 });
2043
2044+ scale.changed.connect(sigc::hide(sigc::mem_fun(this, &View::UpdateViewSize)));
2045+
2046+ UpdateViewSize();
2047 UpdateText();
2048 Populate();
2049 }
2050
2051+void View::UpdateViewSize()
2052+{
2053+ main_layout_->SetTopAndBottomPadding(style::TOP_PADDING.CP(scale()), style::BOTTOM_PADDING.CP(scale()));
2054+ main_layout_->SetLeftAndRightPadding(style::LEFT_RIGHT_PADDING.CP(scale()));
2055+ main_layout_->SetSpaceBetweenChildren(style::MAIN_SPACE.CP(scale()));
2056+
2057+ title_->SetScale(scale());
2058+ subtitle_->SetScale(scale());
2059+
2060+ ReloadCloseButtonTexture();
2061+
2062+ buttons_layout_->SetSpaceBetweenChildren(style::BUTTONS_SPACE.CP(scale()));
2063+
2064+ for (auto* area : buttons_layout_->GetChildren())
2065+ {
2066+ auto* button = static_cast<Button*>(area);
2067+ button->scale = scale();
2068+ }
2069+}
2070+
2071 void View::UpdateText()
2072 {
2073- const char* message = nullptr;
2074+ std::string message;
2075+ std::string other_users_msg;
2076 auto const& real_name = manager_->RealName();
2077 auto const& name = (real_name.empty() ? manager_->UserName() : real_name);
2078
2079+ other_users_msg = _("Other users are logged in. Restarting or shutting down will close their open applications and may cause them to lose work.\n\n");
2080+
2081 if (mode() == Mode::SHUTDOWN)
2082 {
2083 title_->SetText(_("Shut Down"));
2084 title_->SetVisible(true);
2085
2086+ if (manager_->have_other_open_sessions())
2087+ {
2088+ message += other_users_msg;
2089+ }
2090+
2091 if (have_inhibitors())
2092 {
2093- message = _("Hi %s, you have open files that you might want to save " \
2094- "before shutting down. Are you sure you want to continue?");
2095+ message += _("Hi %s, you have open files that you might want to save " \
2096+ "before shutting down. Are you sure you want to continue?");
2097 }
2098 else
2099 {
2100- message = _("Goodbye, %s. Are you sure you want to close all programs " \
2101- "and shut down the computer?");
2102+ message += _("Goodbye, %s. Are you sure you want to close all programs " \
2103+ "and shut down the computer?");
2104 }
2105 }
2106 else if (mode() == Mode::LOGOUT)
2107@@ -144,27 +173,32 @@
2108 {
2109 title_->SetVisible(false);
2110
2111+ if (manager_->have_other_open_sessions())
2112+ {
2113+ message += other_users_msg;
2114+ }
2115+
2116 if (have_inhibitors())
2117 {
2118 if (buttons_layout_->GetChildren().size() > 3)
2119 {
2120 // We have enough buttons to show the message without a new line.
2121- message = _("Hi %s, you have open files you might want to save. " \
2122+ message += _("Hi %s, you have open files you might want to save. " \
2123 "Would you like to…");
2124 }
2125 else
2126 {
2127- message = _("Hi %s, you have open files you might want to save.\n" \
2128+ message += _("Hi %s, you have open files you might want to save.\n" \
2129 "Would you like to…");
2130 }
2131 }
2132 else
2133 {
2134- message = _("Goodbye, %s. Would you like to…");
2135+ message += _("Goodbye, %s. Would you like to…");
2136 }
2137 }
2138
2139- subtitle_->SetText(glib::String(g_strdup_printf(message, name.c_str())).Str());
2140+ subtitle_->SetText(glib::String(g_strdup_printf(message.c_str(), name.c_str())).Str());
2141 }
2142
2143 void View::Populate()
2144@@ -176,6 +210,7 @@
2145 if (mode() == Mode::LOGOUT)
2146 {
2147 auto* button = new Button(Button::Action::LOCK, NUX_TRACKER_LOCATION);
2148+ button->scale = scale();
2149 button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::LockScreen));
2150 AddButton(button);
2151
2152@@ -189,12 +224,14 @@
2153 if (mode() == Mode::FULL)
2154 {
2155 auto* button = new Button(Button::Action::LOCK, NUX_TRACKER_LOCATION);
2156+ button->scale = scale();
2157 button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::LockScreen));
2158 AddButton(button);
2159
2160 if (manager_->CanSuspend())
2161 {
2162 button = new Button(Button::Action::SUSPEND, NUX_TRACKER_LOCATION);
2163+ button->scale = scale();
2164 button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Suspend));
2165 AddButton(button);
2166 }
2167@@ -202,6 +239,7 @@
2168 if (manager_->CanHibernate())
2169 {
2170 button = new Button(Button::Action::HIBERNATE, NUX_TRACKER_LOCATION);
2171+ button->scale = scale();
2172 button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Hibernate));
2173 AddButton(button);
2174 }
2175@@ -210,10 +248,12 @@
2176 if (manager_->CanShutdown())
2177 {
2178 auto *button = new Button(Button::Action::REBOOT, NUX_TRACKER_LOCATION);
2179+ button->scale = scale();
2180 button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Reboot));
2181 AddButton(button);
2182
2183 button = new Button(Button::Action::SHUTDOWN, NUX_TRACKER_LOCATION);
2184+ button->scale = scale();
2185 button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Shutdown));
2186 key_focus_area_ = (mode() == Mode::SHUTDOWN) ? button : key_focus_area_;
2187 AddButton(button);
2188@@ -221,6 +261,7 @@
2189 else if (mode() == Mode::FULL)
2190 {
2191 auto* button = new Button(Button::Action::LOGOUT, NUX_TRACKER_LOCATION);
2192+ button->scale = scale();
2193 button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Logout));
2194 AddButton(button);
2195 }
2196
2197=== modified file 'shutdown/SessionView.h'
2198--- shutdown/SessionView.h 2013-11-20 21:39:40 +0000
2199+++ shutdown/SessionView.h 2014-07-01 15:44:27 +0000
2200@@ -22,9 +22,11 @@
2201
2202 #include <Nux/Nux.h>
2203 #include <Nux/View.h>
2204+#include <Nux/VLayout.h>
2205 #include <Nux/HLayout.h>
2206
2207 #include "UnityCore/SessionManager.h"
2208+#include "unity-shared/EMConverter.h"
2209 #include "unity-shared/UnityWindowView.h"
2210 #include "UnityCore/SessionManager.h"
2211
2212@@ -71,6 +73,8 @@
2213 private:
2214 friend class TestSessionView;
2215
2216+ void UpdateViewSize();
2217+
2218 void UpdateText();
2219 void Populate();
2220 void AddButton(Button*);
2221@@ -78,6 +82,7 @@
2222 Manager::Ptr manager_;
2223 StaticCairoText* title_;
2224 StaticCairoText* subtitle_;
2225+ nux::VLayout* main_layout_;
2226 nux::HLayout* buttons_layout_;
2227 nux::InputArea* key_focus_area_;
2228 };
2229
2230=== added file 'tests/test-gestures/LockScreenControllerMock.h'
2231--- tests/test-gestures/LockScreenControllerMock.h 1970-01-01 00:00:00 +0000
2232+++ tests/test-gestures/LockScreenControllerMock.h 2014-07-01 15:44:27 +0000
2233@@ -0,0 +1,43 @@
2234+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2235+/*
2236+ * Copyright (C) 2014 Canonical Ltd
2237+ *
2238+ * This program is free software: you can redistribute it and/or modify
2239+ * it under the terms of the GNU General Public License version 3 as
2240+ * published by the Free Software Foundation.
2241+ *
2242+ * This program is distributed in the hope that it will be useful,
2243+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2244+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2245+ * GNU General Public License for more details.
2246+ *
2247+ * You should have received a copy of the GNU General Public License
2248+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2249+ *
2250+ * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
2251+ */
2252+
2253+#ifndef LOCK_SCREEN_CONTROLLER_MOCK_H
2254+#define LOCK_SCREEN_CONTROLLER_MOCK_H
2255+
2256+#include <memory>
2257+
2258+namespace unity
2259+{
2260+namespace lockscreen
2261+{
2262+
2263+class ControllerMock
2264+{
2265+public:
2266+ typedef std::shared_ptr<ControllerMock> Ptr;
2267+
2268+ bool IsLocked() {
2269+ return false;
2270+ }
2271+};
2272+
2273+}
2274+}
2275+
2276+#endif
2277\ No newline at end of file
2278
2279=== modified file 'tests/test-gestures/sed_script_switcher'
2280--- tests/test-gestures/sed_script_switcher 2013-01-24 16:32:35 +0000
2281+++ tests/test-gestures/sed_script_switcher 2014-07-01 15:44:27 +0000
2282@@ -19,8 +19,10 @@
2283 s|\<Nux/Nux\.h\>|NuxMock.h|g
2284 s|\<CompTimer\>|CompTimerMock|g
2285 s|\<LauncherController\>|LauncherControllerMock|g
2286+s|\<LockScreenController\>|LockControllerMock|g
2287 s|\<SwitcherController\>|SwitcherControllerMock|g
2288 s|\<switcher\:\:Controller\>|switcher\:\:ControllerMock|g
2289+s|\<lockscreen\:\:Controller\>|lockscreen\:\:ControllerMock|g
2290 s|\<launcher\:\:Controller\>|launcher\:\:ControllerMock|g
2291 /SwitcherView\.h/d
2292 s|\<SwitcherView\>|SwitcherViewMock|g
2293
2294=== modified file 'tests/test-gestures/unityshell_mock.h'
2295--- tests/test-gestures/unityshell_mock.h 2012-08-14 13:06:03 +0000
2296+++ tests/test-gestures/unityshell_mock.h 2014-07-01 15:44:27 +0000
2297@@ -6,7 +6,7 @@
2298 #include <NuxMock.h>
2299
2300 #include "SwitcherControllerMock.h"
2301-
2302+#include "LockScreenControllerMock.h"
2303
2304 namespace unity
2305 {
2306@@ -29,6 +29,7 @@
2307 UnityScreenMock()
2308 {
2309 switcher_controller_ = std::make_shared<switcher::ControllerMock>();
2310+ lockscreen_controller_ = std::make_shared<lockscreen::ControllerMock>();
2311 Reset();
2312 }
2313
2314@@ -59,7 +60,13 @@
2315 return switcher_controller_;
2316 }
2317
2318+ lockscreen::ControllerMock::Ptr lockscreen_controller()
2319+ {
2320+ return lockscreen_controller_;
2321+ }
2322+
2323 switcher::ControllerMock::Ptr switcher_controller_;
2324+ lockscreen::ControllerMock::Ptr lockscreen_controller_;
2325 int SetUpAndShowSwitcher_count_;
2326 };
2327
2328
2329=== modified file 'tests/test_lockscreen_controller.cpp'
2330--- tests/test_lockscreen_controller.cpp 2014-04-17 13:08:05 +0000
2331+++ tests/test_lockscreen_controller.cpp 2014-07-01 15:44:27 +0000
2332@@ -56,7 +56,6 @@
2333 {}
2334
2335 MOCK_CONST_METHOD0(IsIndicatorOpen, bool());
2336- MOCK_METHOD0(CheckCapsLockPrompt, void());
2337 MOCK_METHOD0(ActivatePanel, void());
2338 };
2339
2340
2341=== modified file 'tests/test_switcher_view.cpp'
2342--- tests/test_switcher_view.cpp 2014-03-25 19:07:36 +0000
2343+++ tests/test_switcher_view.cpp 2014-07-01 15:44:27 +0000
2344@@ -117,8 +117,7 @@
2345 EXPECT_EQ(switcher.vertical_size, switcher.tile_size + VERTICAL_PADDING * 2);
2346 EXPECT_EQ(switcher.text_size, 15);
2347 EXPECT_EQ(switcher.animation_length, 250);
2348- EXPECT_EQ(switcher.monitor, -1);
2349- EXPECT_EQ(switcher.spread_size, 3.5f);
2350+ EXPECT_EQ(switcher.monitor, 0);
2351 ASSERT_NE(switcher.text_view_, nullptr);
2352 ASSERT_NE(switcher.icon_renderer_, nullptr);
2353 EXPECT_EQ(switcher.icon_renderer_->pip_style, ui::OVER_TILE);
2354
2355=== modified file 'tests/test_unity_window_view.cpp'
2356--- tests/test_unity_window_view.cpp 2014-03-21 04:40:12 +0000
2357+++ tests/test_unity_window_view.cpp 2014-07-01 15:44:27 +0000
2358@@ -82,10 +82,10 @@
2359 view.closable = true;
2360 ASSERT_NE(view.close_button_, nullptr);
2361
2362- EXPECT_EQ(view.close_button_->texture(), view.style()->GetCloseIcon());
2363+ EXPECT_EQ(view.close_button_->texture(), view.style()->GetTexture(view.scale, WindowTextureType::CLOSE_ICON));
2364 EXPECT_EQ(view.close_button_->GetParentObject(), &view);
2365
2366- int padding = view.style()->GetCloseButtonPadding();
2367+ int padding = view.style()->GetCloseButtonPadding(view.scale);
2368 EXPECT_EQ(view.close_button_->GetBaseX(), padding);
2369 EXPECT_EQ(view.close_button_->GetBaseY(), padding);
2370 }
2371@@ -96,16 +96,16 @@
2372 ASSERT_NE(view.close_button_, nullptr);
2373
2374 view.close_button_->mouse_enter.emit(0, 0, 0, 0);
2375- EXPECT_EQ(view.close_button_->texture(), view.style()->GetCloseIconHighligted());
2376+ EXPECT_EQ(view.close_button_->texture(), view.style()->GetTexture(view.scale, WindowTextureType::CLOSE_ICON_HIGHLIGHTED));
2377
2378 view.close_button_->mouse_leave.emit(0, 0, 0, 0);
2379- EXPECT_EQ(view.close_button_->texture(), view.style()->GetCloseIcon());
2380+ EXPECT_EQ(view.close_button_->texture(), view.style()->GetTexture(view.scale, WindowTextureType::CLOSE_ICON));
2381
2382 view.close_button_->mouse_down.emit(0, 0, 0, 0);
2383- EXPECT_EQ(view.close_button_->texture(), view.style()->GetCloseIconPressed());
2384+ EXPECT_EQ(view.close_button_->texture(), view.style()->GetTexture(view.scale, WindowTextureType::CLOSE_ICON_PRESSED));
2385
2386 view.close_button_->mouse_up.emit(0, 0, 0, 0);
2387- EXPECT_EQ(view.close_button_->texture(), view.style()->GetCloseIcon());
2388+ EXPECT_EQ(view.close_button_->texture(), view.style()->GetTexture(view.scale, WindowTextureType::CLOSE_ICON));
2389 }
2390
2391 TEST_F(TestUnityWindowView, CloseButtonClicksRequestsClose)
2392@@ -185,7 +185,7 @@
2393 view.SetLayout(layout);
2394 view.ComputeContentSize();
2395
2396- int offset = view.style()->GetInternalOffset();
2397+ int offset = view.style()->GetInternalOffset(view.scale);
2398 EXPECT_EQ(layout->GetBaseX(), offset);
2399 EXPECT_EQ(layout->GetBaseY(), offset);
2400 }
2401@@ -199,7 +199,7 @@
2402
2403 TEST_F(TestUnityWindowView, GetInternalBackground)
2404 {
2405- int offset = view.style()->GetInternalOffset();
2406+ int offset = view.style()->GetInternalOffset(view.scale);
2407 view.background_geo_.Set(g_random_int(), g_random_int(), g_random_int(), g_random_int());
2408 EXPECT_EQ(view.GetInternalBackground(), view.background_geo_.GetExpand(-offset, -offset));
2409 }
2410@@ -240,4 +240,4 @@
2411 }
2412
2413 } // ui
2414-} // unity
2415\ No newline at end of file
2416+} // unity
2417
2418=== modified file 'unity-shared/EMConverter.cpp'
2419--- unity-shared/EMConverter.cpp 2014-02-27 04:54:19 +0000
2420+++ unity-shared/EMConverter.cpp 2014-07-01 15:44:27 +0000
2421@@ -17,6 +17,7 @@
2422 * Authored by: Brandon Schaefer <brandon.schaefer@canonical.com>
2423 */
2424
2425+#include <cmath>
2426 #include "EMConverter.h"
2427
2428 namespace unity
2429@@ -104,8 +105,7 @@
2430
2431 double EMConverter::CP(int pixels) const
2432 {
2433- double pixels_em = PixelsToBaseEM(pixels);
2434- return EMToPixels(pixels_em);
2435+ return std::round(pixels * DPIScale());
2436 }
2437
2438 double EMConverter::DPIScale() const
2439
2440=== modified file 'unity-shared/IMTextEntry.cpp'
2441--- unity-shared/IMTextEntry.cpp 2014-03-05 03:48:27 +0000
2442+++ unity-shared/IMTextEntry.cpp 2014-07-01 15:44:27 +0000
2443@@ -27,10 +27,14 @@
2444
2445 IMTextEntry::IMTextEntry()
2446 : TextEntry("", NUX_TRACKER_LOCATION)
2447+ , clipboard_enabled(true)
2448 {}
2449
2450 void IMTextEntry::CopyClipboard()
2451 {
2452+ if (!clipboard_enabled())
2453+ return;
2454+
2455 int start, end;
2456
2457 if (GetSelectionBounds(&start, &end))
2458@@ -52,6 +56,9 @@
2459
2460 void IMTextEntry::Paste(bool primary)
2461 {
2462+ if (!clipboard_enabled())
2463+ return;
2464+
2465 GdkAtom origin = primary ? GDK_SELECTION_PRIMARY : GDK_SELECTION_CLIPBOARD;
2466 GtkClipboard* clip = gtk_clipboard_get(origin);
2467
2468
2469=== modified file 'unity-shared/IMTextEntry.h'
2470--- unity-shared/IMTextEntry.h 2014-03-05 03:48:27 +0000
2471+++ unity-shared/IMTextEntry.h 2014-07-01 15:44:27 +0000
2472@@ -33,6 +33,8 @@
2473 public:
2474 IMTextEntry();
2475
2476+ nux::Property<bool> clipboard_enabled;
2477+
2478 bool im_preedit();
2479
2480 protected:
2481
2482=== modified file 'unity-shared/PluginAdapter.cpp'
2483--- unity-shared/PluginAdapter.cpp 2014-04-30 16:08:21 +0000
2484+++ unity-shared/PluginAdapter.cpp 2014-07-01 15:44:27 +0000
2485@@ -190,15 +190,34 @@
2486 _vp_switch_started = false;
2487 screen_viewport_switch_ended.emit();
2488 }
2489- else if (IsScaleActive() && g_strcmp0(plugin, "scale") == 0 &&
2490- g_strcmp0(event, "activate") == 0)
2491+ else if (g_strcmp0(plugin, "scale") == 0 && g_strcmp0(event, "activate") == 0)
2492 {
2493- // If the scale plugin is activated again while is already grabbing the screen
2494- // it means that is switching the view (i.e. switching from a spread application
2495- // to another), so we need to notify our clients that it has really terminated
2496- // and initiated again.
2497- terminate_spread.emit();
2498- initiate_spread.emit();
2499+ bool new_state = CompOption::getBoolOptionNamed(option, "active");
2500+
2501+ if (_spread_state != new_state)
2502+ {
2503+ _spread_state = new_state;
2504+ _spread_state ? initiate_spread.emit() : terminate_spread.emit();
2505+
2506+ if (!_spread_state)
2507+ _spread_windows_state = false;
2508+ }
2509+ else if (_spread_state && new_state)
2510+ {
2511+ // If the scale plugin is activated again while is already grabbing the screen
2512+ // it means that is switching the view (i.e. switching from a spread application
2513+ // to another), so we need to notify our clients that it has really terminated
2514+ // and initiated again.
2515+
2516+ bool old_windows_state = _spread_windows_state;
2517+ _spread_state = false;
2518+ _spread_windows_state = false;
2519+ terminate_spread.emit();
2520+
2521+ _spread_state = true;
2522+ _spread_windows_state = old_windows_state;
2523+ initiate_spread.emit();
2524+ }
2525 }
2526 }
2527
2528@@ -249,7 +268,7 @@
2529
2530 /* Initiate the selected action with the arguments */
2531 if (CompAction::CallBack const& initiate_cb = primary_action_->initiate())
2532- initiate_cb(action, 0, argument);
2533+ initiate_cb(action, state, argument);
2534 }
2535
2536 void MultiActionList::InitiateAll(CompOption::Vector const& extra_args, int state) const
2537@@ -1226,7 +1245,21 @@
2538
2539 bool PluginAdapter::IsScreenGrabbed() const
2540 {
2541- return m_Screen->grabbed();
2542+ if (m_Screen->grabbed())
2543+ return true;
2544+
2545+ auto* dpy = m_Screen->dpy();
2546+ auto ret = XGrabKeyboard(dpy, m_Screen->root(), True, GrabModeAsync, GrabModeAsync, CurrentTime);
2547+
2548+ if (ret == GrabSuccess)
2549+ {
2550+ XUngrabKeyboard(dpy, CurrentTime);
2551+
2552+ if (CompWindow* w = m_Screen->findWindow(m_Screen->activeWindow()))
2553+ w->moveInputFocusTo();
2554+ }
2555+
2556+ return (ret == AlreadyGrabbed);
2557 }
2558
2559 bool PluginAdapter::IsViewPortSwitchStarted() const
2560
2561=== modified file 'unity-shared/RawPixel.cpp'
2562--- unity-shared/RawPixel.cpp 2014-02-26 00:01:21 +0000
2563+++ unity-shared/RawPixel.cpp 2014-07-01 15:44:27 +0000
2564@@ -39,7 +39,7 @@
2565
2566 int RawPixel::CP(EMConverter::Ptr const& converter) const
2567 {
2568- return std::round(converter->CP(raw_pixel_));
2569+ return converter->CP(raw_pixel_);
2570 }
2571
2572 int RawPixel::CP(double scale) const
2573
2574=== modified file 'unity-shared/TextInput.cpp'
2575--- unity-shared/TextInput.cpp 2014-03-05 03:49:50 +0000
2576+++ unity-shared/TextInput.cpp 2014-07-01 15:44:27 +0000
2577@@ -18,6 +18,15 @@
2578 */
2579
2580 #include "TextInput.h"
2581+#include "unity-shared/IconTexture.h"
2582+#include "unity-shared/DashStyle.h"
2583+#include "unity-shared/RawPixel.h"
2584+#include "unity-shared/PreviewStyle.h"
2585+
2586+#include <X11/XKBlib.h>
2587+
2588+namespace unity
2589+{
2590
2591 namespace
2592 {
2593@@ -29,6 +38,14 @@
2594
2595 const int HIGHLIGHT_HEIGHT = 24;
2596
2597+const RawPixel TOOLTIP_Y_OFFSET = 3_em;
2598+const RawPixel TOOLTIP_OFFSET = 10_em;
2599+const RawPixel DEFAULT_ICON_SIZE = 22_em;
2600+
2601+// Caps is on 0x1, couldn't find any #define in /usr/include/X11
2602+const int CAPS_STATE_ON = 0x1;
2603+
2604+std::string WARNING_ICON = "dialog-warning-symbolic";
2605 // Fonts
2606 const std::string HINT_LABEL_DEFAULT_FONT_NAME = "Ubuntu";
2607 const int HINT_LABEL_FONT_SIZE = 11;
2608@@ -38,21 +55,44 @@
2609
2610 }
2611
2612-namespace unity
2613-{
2614-
2615 nux::logging::Logger logger("unity.textinput");
2616
2617 NUX_IMPLEMENT_OBJECT_TYPE(TextInput);
2618
2619+nux::AbstractPaintLayer* CreateWarningLayer(nux::BaseTexture* texture)
2620+{
2621+ // Create the texture layer
2622+ nux::TexCoordXForm texxform;
2623+
2624+ texxform.SetTexCoordType(nux::TexCoordXForm::OFFSET_COORD);
2625+ texxform.SetWrap(nux::TEXWRAP_REPEAT, nux::TEXWRAP_REPEAT);
2626+ texxform.min_filter = nux::TEXFILTER_LINEAR;
2627+ texxform.mag_filter = nux::TEXFILTER_LINEAR;
2628+
2629+ nux::ROPConfig rop;
2630+ rop.Blend = true;
2631+
2632+ rop.SrcBlend = GL_ONE;
2633+ rop.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
2634+
2635+ return (new nux::TextureLayer(texture->GetDeviceTexture(),
2636+ texxform,
2637+ nux::color::White,
2638+ true,
2639+ rop));
2640+}
2641+
2642 TextInput::TextInput(NUX_FILE_LINE_DECL)
2643 : View(NUX_FILE_LINE_PARAM)
2644 , input_hint("")
2645 , hint_font_name(HINT_LABEL_DEFAULT_FONT_NAME)
2646 , hint_font_size(HINT_LABEL_FONT_SIZE)
2647+ , show_caps_lock(false)
2648 , bg_layer_(new nux::ColorLayer(nux::Color(0xff595853), true))
2649+ , caps_lock_on(false)
2650 , last_width_(-1)
2651 , last_height_(-1)
2652+ , mouse_over_warning_icon_(false)
2653 {
2654 layout_ = new nux::HLayout(NUX_TRACKER_LOCATION);
2655 layout_->SetLeftAndRightPadding(LEFT_INTERNAL_PADDING, TEXT_INPUT_RIGHT_BORDER);
2656@@ -74,6 +114,7 @@
2657 pango_entry_->SetFontSize(PANGO_ENTRY_FONT_SIZE);
2658 pango_entry_->cursor_moved.connect([this](int i) { QueueDraw(); });
2659 pango_entry_->mouse_down.connect(sigc::mem_fun(this, &TextInput::OnMouseButtonDown));
2660+ pango_entry_->key_up.connect(sigc::mem_fun(this, &TextInput::OnKeyUp));
2661 pango_entry_->end_key_focus.connect(sigc::mem_fun(this, &TextInput::OnEndKeyFocus));
2662 pango_entry_->text_changed.connect([this](nux::TextEntry*) {
2663 hint_->SetVisible(input_string().empty());
2664@@ -86,6 +127,25 @@
2665 layered_layout_->SetActiveLayerN(1);
2666 layout_->AddView(layered_layout_, 1, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FIX);
2667
2668+ warning_ = new IconTexture(LoadWarningIcon(DEFAULT_ICON_SIZE));
2669+ warning_->SetVisible(caps_lock_on());
2670+ layout_->AddView(warning_, 0, nux::MINOR_POSITION_CENTER, nux::MINOR_SIZE_FULL);
2671+ caps_lock_on.changed.connect([this] (bool on) {
2672+ if (show_caps_lock)
2673+ {
2674+ warning_->SetVisible(on);
2675+ QueueRelayout();
2676+ QueueDraw();
2677+ }
2678+ });
2679+
2680+ show_caps_lock.changed.connect([this] (bool changed) {
2681+ if (!warning_tooltip_.IsValid())
2682+ LoadWarningTooltip();
2683+
2684+ CheckIfCapsLockOn();
2685+ });
2686+
2687 spinner_ = new SearchBarSpinner();
2688 spinner_->SetVisible(false);
2689 spinner_->SetMinMaxSize(22, 22);
2690@@ -101,6 +161,27 @@
2691 im_preedit.SetGetterFunction(sigc::mem_fun(this, &TextInput::get_im_preedit));
2692 input_hint.changed.connect([this](std::string const& s) { OnInputHintChanged(); });
2693
2694+ warning_->mouse_enter.connect([this] (int x, int y, int button, int key_flags) {
2695+ mouse_over_warning_icon_ = true;
2696+ QueueDraw();
2697+ });
2698+
2699+ warning_->mouse_leave.connect([this] (int x, int y, int button, int key_flags) {
2700+ mouse_over_warning_icon_ = false;
2701+ QueueDraw();
2702+ });
2703+}
2704+
2705+void TextInput::CheckIfCapsLockOn()
2706+{
2707+ Display *dpy = nux::GetGraphicsDisplay()->GetX11Display();
2708+ unsigned int state = 0;
2709+ XkbGetIndicatorState(dpy, XkbUseCoreKbd, &state);
2710+
2711+ if ((state & CAPS_STATE_ON) == 1)
2712+ caps_lock_on = true;
2713+ else
2714+ caps_lock_on = false;
2715 }
2716
2717 void TextInput::SetSpinnerVisible(bool visible)
2718@@ -118,6 +199,75 @@
2719 hint_->SetFont((hint_font_name() + " " + std::to_string(hint_font_size())).c_str());
2720 }
2721
2722+nux::ObjectPtr<nux::BaseTexture> TextInput::LoadWarningIcon(int icon_size)
2723+{
2724+ auto* theme = gtk_icon_theme_get_default();
2725+ GtkIconLookupFlags flags = GTK_ICON_LOOKUP_FORCE_SIZE;
2726+ glib::Error error;
2727+ glib::Object<GdkPixbuf> pixbuf(gtk_icon_theme_load_icon(theme, WARNING_ICON.c_str(), icon_size, flags, &error));
2728+
2729+ if (pixbuf != nullptr)
2730+ {
2731+ nux::CairoGraphics cg(CAIRO_FORMAT_ARGB32, gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf));
2732+ cairo_t* cr = cg.GetInternalContext();
2733+
2734+ cairo_push_group(cr);
2735+ gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
2736+ cairo_paint_with_alpha(cr, 1.0);
2737+ std::shared_ptr<cairo_pattern_t> pat(cairo_pop_group(cr), cairo_pattern_destroy);
2738+
2739+ cairo_set_source_rgba(cr, 1.0f, 1.0f, 1.0f, 1.0f);
2740+ cairo_rectangle(cr, 0, 0, gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf));
2741+ cairo_mask(cr, pat.get());
2742+
2743+ return texture_ptr_from_cairo_graphics(cg);
2744+ }
2745+ // Use fallback icon (this one is a png, and does not scale!)
2746+ else
2747+ {
2748+ dash::previews::Style& preview_style = dash::previews::Style::Instance();
2749+ return nux::ObjectPtr<nux::BaseTexture>(preview_style.GetWarningIcon());
2750+ }
2751+}
2752+
2753+void TextInput::LoadWarningTooltip()
2754+{
2755+ glib::String font_name;
2756+ g_object_get(gtk_settings_get_default(), "gtk-font-name", &font_name, NULL);
2757+
2758+ glib::Object<GtkStyleContext> style_context(gtk_style_context_new());
2759+ std::shared_ptr<GtkWidgetPath> widget_path(gtk_widget_path_new(), gtk_widget_path_free);
2760+ gtk_widget_path_append_type(widget_path.get(), GTK_TYPE_TOOLTIP);
2761+
2762+ gtk_style_context_set_path(style_context, widget_path.get());
2763+ gtk_style_context_add_class(style_context, "tooltip");
2764+
2765+ glib::Object<PangoLayout> layout;
2766+ glib::Object<PangoContext> context(gdk_pango_context_get_for_screen(gdk_screen_get_default()));
2767+ layout = pango_layout_new(context);
2768+
2769+ std::shared_ptr<PangoFontDescription> desc(pango_font_description_from_string(font_name), pango_font_description_free);
2770+ pango_context_set_font_description(context, desc.get());
2771+ pango_context_set_language(context, gtk_get_default_language());
2772+
2773+ pango_layout_set_height(layout, -1); //avoid wrap lines
2774+ pango_layout_set_text(layout, _("Caps lock is on"), -1);
2775+
2776+ nux::Size extents;
2777+ pango_layout_get_pixel_size(layout, &extents.width, &extents.height);
2778+ extents.width += TOOLTIP_OFFSET;
2779+ extents.height += TOOLTIP_OFFSET;
2780+
2781+ nux::CairoGraphics cg(CAIRO_FORMAT_ARGB32, extents.width, extents.height);
2782+ cairo_t* cr = cg.GetInternalContext();
2783+
2784+ gtk_render_background(style_context, cr, 0, 0, extents.width, extents.height);
2785+ gtk_render_frame(style_context, cr, 0, 0, extents.width, extents.height);
2786+ gtk_render_layout(style_context, cr, TOOLTIP_OFFSET/2, TOOLTIP_OFFSET/2, layout);
2787+
2788+ warning_tooltip_ = texture_ptr_from_cairo_graphics(cg);
2789+}
2790+
2791 void TextInput::OnFontChanged(GtkSettings* settings, GParamSpec* pspec)
2792 {
2793 glib::String font_name;
2794@@ -175,7 +325,6 @@
2795 nux::GetPainter().PushLayer(GfxContext, highlight_layer_->GetGeometry(), highlight_layer_.get());
2796 }
2797
2798-
2799 if (!IsFullRedraw())
2800 {
2801 gPainter.PushLayer(GfxContext, bg_layer_->GetGeometry(), bg_layer_.get());
2802@@ -187,6 +336,9 @@
2803
2804 layout_->ProcessDraw(GfxContext, force_draw);
2805
2806+ if (caps_lock_on && mouse_over_warning_icon_)
2807+ PaintWarningTooltip(GfxContext);
2808+
2809 if (!IsFullRedraw())
2810 {
2811 gPainter.PopBackground();
2812@@ -199,6 +351,18 @@
2813 GfxContext.PopClippingRectangle();
2814 }
2815
2816+void TextInput::PaintWarningTooltip(nux::GraphicsEngine& graphics_engine)
2817+{
2818+ nux::Geometry warning_geo = warning_->GetGeometry();
2819+
2820+ nux::Geometry tooltip_geo = {warning_geo.x - (warning_tooltip_->GetWidth() + TOOLTIP_OFFSET / 2),
2821+ warning_geo.y - TOOLTIP_Y_OFFSET,
2822+ warning_tooltip_->GetWidth(),
2823+ warning_tooltip_->GetHeight()};
2824+
2825+ nux::GetPainter().PushDrawLayer(graphics_engine, tooltip_geo, CreateWarningLayer(warning_tooltip_.GetPointer()));
2826+}
2827+
2828 void TextInput::UpdateBackground(bool force)
2829 {
2830 int RADIUS = 5;
2831@@ -254,6 +418,16 @@
2832 texture2D->UnReference();
2833 }
2834
2835+void TextInput::OnKeyUp(unsigned keysym,
2836+ unsigned long keycode,
2837+ unsigned long state)
2838+{
2839+ if (!caps_lock_on && keysym == NUX_VK_CAPITAL)
2840+ caps_lock_on = true;
2841+ else if (caps_lock_on && keysym == NUX_VK_CAPITAL)
2842+ caps_lock_on = false;
2843+}
2844+
2845 void TextInput::OnMouseButtonDown(int x, int y, unsigned long button, unsigned long key)
2846 {
2847 hint_->SetVisible(false);
2848
2849=== modified file 'unity-shared/TextInput.h'
2850--- unity-shared/TextInput.h 2014-03-05 01:18:40 +0000
2851+++ unity-shared/TextInput.h 2014-07-01 15:44:27 +0000
2852@@ -62,6 +62,8 @@
2853 void SetSpinnerVisible(bool visible);
2854 void SetSpinnerState(SpinnerState spinner_state);
2855
2856+ void EnableCapsLockWarning() const;
2857+
2858 IMTextEntry* text_entry() const;
2859
2860 nux::RWProperty<std::string> input_string;
2861@@ -70,6 +72,7 @@
2862 nux::Property<int> hint_font_size;
2863 nux::ROProperty<bool> im_active;
2864 nux::ROProperty<bool> im_preedit;
2865+ nux::Property<bool> show_caps_lock;
2866
2867 private:
2868 void OnFontChanged(GtkSettings* settings, GParamSpec* pspec=NULL);
2869@@ -83,9 +86,20 @@
2870 void AddProperties(debug::IntrospectionData&);
2871 bool AcceptKeyNavFocus();
2872
2873+ bool ShouldBeHighlighted();
2874+
2875+ nux::Geometry GetWaringIconGeometry() const;
2876+ void CheckIfCapsLockOn();
2877+
2878+ nux::ObjectPtr<nux::BaseTexture> LoadWarningIcon(int icon_size);
2879+ void LoadWarningTooltip();
2880+
2881+ void PaintWarningTooltip(nux::GraphicsEngine& graphics_engine);
2882+
2883 protected:
2884 void OnInputHintChanged();
2885 void OnMouseButtonDown(int x, int y, unsigned long button_flags, unsigned long key_flags);
2886+ void OnKeyUp(unsigned keysym, unsigned long keycode, unsigned long state);
2887 void OnEndKeyFocus();
2888
2889 // getters & setters
2890@@ -100,20 +114,21 @@
2891 IMTextEntry* pango_entry_;
2892
2893 private:
2894-
2895- bool ShouldBeHighlighted();
2896-
2897 std::unique_ptr<nux::AbstractPaintLayer> bg_layer_;
2898 std::unique_ptr<nux::AbstractPaintLayer> highlight_layer_;
2899 nux::HLayout* layout_;
2900 nux::LayeredLayout* layered_layout_;
2901 SearchBarSpinner* spinner_;
2902
2903+ nux::Property<bool> caps_lock_on;
2904 int last_width_;
2905 int last_height_;
2906+ bool mouse_over_warning_icon_;
2907+
2908+ IconTexture* warning_;
2909+ nux::ObjectPtr<nux::BaseTexture> warning_tooltip_;
2910
2911 glib::SignalManager sig_manager_;
2912-
2913 };
2914
2915 }
2916
2917=== modified file 'unity-shared/UnityWindowStyle.cpp'
2918--- unity-shared/UnityWindowStyle.cpp 2013-12-11 02:24:29 +0000
2919+++ unity-shared/UnityWindowStyle.cpp 2014-07-01 15:44:27 +0000
2920@@ -16,19 +16,114 @@
2921 *
2922 * Authored by: Jason Smith <jason.smith@canonical.com>
2923 * Marco Trevisan <marco.trevisan@canonical.com>
2924+ * Brandon Schaefer <brandon.schaefer@canonical.com>
2925 */
2926
2927+#include <NuxCore/Logger.h>
2928+
2929+#include "UnitySettings.h"
2930 #include "UnityWindowStyle.h"
2931+#include "UScreen.h"
2932 #include "config.h"
2933
2934-namespace unity {
2935-namespace ui {
2936+#include <unordered_set>
2937+
2938+namespace unity
2939+{
2940+namespace ui
2941+{
2942+namespace
2943+{
2944+ const char* const SWITCHER_TOP = PKGDATADIR"/switcher_top.png";
2945+ const char* const SWITCHER_LEFT = PKGDATADIR"/switcher_left.png";
2946+ const char* const SWITCHER_CORNER = PKGDATADIR"/switcher_corner.png";
2947+
2948+ const char* const DIALOG_CLOSE = PKGDATADIR"/dialog_close.png";
2949+ const char* const DIALOG_HIGHLIGHT = PKGDATADIR"/dialog_close_highlight.png";
2950+ const char* const DIALOG_PRESS = PKGDATADIR"/dialog_close_press.png";
2951+
2952+
2953+ RawPixel const INTERNAL_OFFSET = 20_em;
2954+ RawPixel const BORDER_SIZE = 30_em;
2955+ RawPixel const CLOSE_PADDING = 3_em;
2956+}
2957+
2958+DECLARE_LOGGER(logger, "unity.ui.unity.window.style");
2959+
2960
2961 UnityWindowStyle::UnityWindowStyle()
2962 {
2963- background_top_.Adopt(nux::CreateTexture2DFromFile(PKGDATADIR"/switcher_top.png", -1, true));
2964- background_left_.Adopt(nux::CreateTexture2DFromFile(PKGDATADIR"/switcher_left.png", -1, true));
2965- background_corner_.Adopt(nux::CreateTexture2DFromFile(PKGDATADIR"/switcher_corner.png", -1, true));
2966+ unsigned monitors = UScreen::GetDefault()->GetPluggedMonitorsNumber();
2967+ auto& settings = Settings::Instance();
2968+
2969+ // Pre-load scale values per monitor
2970+ for (unsigned i = 0; i < monitors; ++i)
2971+ {
2972+ double scale = settings.Instance().em(i)->DPIScale();
2973+
2974+ if (unity_window_textures_.find(scale) == unity_window_textures_.end())
2975+ LoadAllTextureInScale(scale);
2976+ }
2977+
2978+ settings.Instance().dpi_changed.connect(sigc::mem_fun(this, &UnityWindowStyle::CleanUpUnusedTextures));
2979+ UScreen::GetDefault()->changed.connect(sigc::mem_fun(this, &UnityWindowStyle::OnMonitorChanged));
2980+}
2981+
2982+void UnityWindowStyle::LoadAllTextureInScale(double scale)
2983+{
2984+ auto& window_textures = unity_window_textures_[scale];
2985+
2986+ window_textures[unsigned(WindowTextureType::BACKGROUND_TOP)] = LoadTexture(scale, SWITCHER_TOP);
2987+ window_textures[unsigned(WindowTextureType::BACKGROUND_LEFT)] = LoadTexture(scale, SWITCHER_LEFT);
2988+ window_textures[unsigned(WindowTextureType::BACKGROUND_CORNER)] = LoadTexture(scale, SWITCHER_CORNER);
2989+
2990+ window_textures[unsigned(WindowTextureType::CLOSE_ICON)] = LoadTexture(scale, DIALOG_CLOSE);
2991+ window_textures[unsigned(WindowTextureType::CLOSE_ICON_HIGHLIGHTED)] = LoadTexture(scale, DIALOG_HIGHLIGHT);
2992+ window_textures[unsigned(WindowTextureType::CLOSE_ICON_PRESSED)] = LoadTexture(scale, DIALOG_PRESS);
2993+}
2994+
2995+nux::BaseTexture* UnityWindowStyle::LoadTexture(double scale, const char* const texture_name) const
2996+{
2997+ RawPixel max_size = GetDefaultMaxTextureSize(texture_name);
2998+ return nux::CreateTexture2DFromFile(texture_name, max_size.CP(scale), true);
2999+}
3000+
3001+RawPixel UnityWindowStyle::GetDefaultMaxTextureSize(const char* const texture_name) const
3002+{
3003+ nux::Size size;
3004+ gdk_pixbuf_get_file_info(texture_name, &size.width, &size.height);
3005+ RawPixel max_size = std::max(std::round(size.width), std::round(size.height));
3006+
3007+ return max_size;
3008+}
3009+
3010+void UnityWindowStyle::OnMonitorChanged(int primary, std::vector<nux::Geometry> const& monitors)
3011+{
3012+ CleanUpUnusedTextures();
3013+}
3014+
3015+// Get current in use scale values, if a scaled value is allocated, but
3016+// not in use clean up the scaled textures in unity_window_textures
3017+void UnityWindowStyle::CleanUpUnusedTextures()
3018+{
3019+ unsigned monitors = UScreen::GetDefault()->GetPluggedMonitorsNumber();
3020+ auto& settings = Settings::Instance();
3021+ std::unordered_set<double> used_scales;
3022+
3023+ for (unsigned i = 0; i < monitors; ++i)
3024+ used_scales.insert(settings.em(i)->DPIScale());
3025+
3026+ for (auto it = unity_window_textures_.begin(); it != unity_window_textures_.end();)
3027+ {
3028+ if (used_scales.find(it->first) == used_scales.end())
3029+ {
3030+ it = unity_window_textures_.erase(it);
3031+ }
3032+ else
3033+ {
3034+ ++it;
3035+ }
3036+ }
3037 }
3038
3039 UnityWindowStyle::Ptr const& UnityWindowStyle::Get()
3040@@ -38,60 +133,38 @@
3041 return instance;
3042 }
3043
3044-int UnityWindowStyle::GetBorderSize() const
3045-{
3046- return 30; // as measured from textures
3047-}
3048-
3049-int UnityWindowStyle::GetInternalOffset() const
3050-{
3051- return 20;
3052-}
3053-
3054-int UnityWindowStyle::GetCloseButtonPadding() const
3055-{
3056- return 3;
3057-}
3058-
3059-UnityWindowStyle::BaseTexturePtr UnityWindowStyle::GetCloseIcon()
3060-{
3061- if (!close_icon_)
3062- close_icon_.Adopt(nux::CreateTexture2DFromFile(PKGDATADIR"/dialog_close.png", -1, true));
3063-
3064- return close_icon_;
3065-}
3066-
3067-UnityWindowStyle::BaseTexturePtr UnityWindowStyle::GetCloseIconHighligted()
3068-{
3069- if (!close_icon_highlighted_)
3070- close_icon_highlighted_.Adopt(nux::CreateTexture2DFromFile(PKGDATADIR"/dialog_close_highlight.png", -1, true));
3071-
3072- return close_icon_highlighted_;
3073-}
3074-
3075-UnityWindowStyle::BaseTexturePtr UnityWindowStyle::GetCloseIconPressed()
3076-{
3077- if (!close_icon_pressed_)
3078- close_icon_pressed_.Adopt(nux::CreateTexture2DFromFile(PKGDATADIR"/dialog_close_press.png", -1, true));
3079-
3080- return close_icon_pressed_;
3081-}
3082-
3083-UnityWindowStyle::BaseTexturePtr UnityWindowStyle::GetBackgroundTop() const
3084-{
3085- return background_top_;
3086-}
3087-
3088-UnityWindowStyle::BaseTexturePtr UnityWindowStyle::GetBackgroundLeft() const
3089-{
3090- return background_left_;
3091-}
3092-
3093-UnityWindowStyle::BaseTexturePtr UnityWindowStyle::GetBackgroundCorner() const
3094-{
3095- return background_corner_;
3096-}
3097-
3098-
3099-}
3100-}
3101+int UnityWindowStyle::GetBorderSize(double scale) const
3102+{
3103+ return BORDER_SIZE.CP(scale); // as measured from textures
3104+}
3105+
3106+int UnityWindowStyle::GetInternalOffset(double scale) const
3107+{
3108+ return INTERNAL_OFFSET.CP(scale);
3109+}
3110+
3111+int UnityWindowStyle::GetCloseButtonPadding(double scale) const
3112+{
3113+ return CLOSE_PADDING.CP(scale);
3114+}
3115+
3116+UnityWindowStyle::BaseTexturePtr UnityWindowStyle::GetTexture(double scale, WindowTextureType const& type)
3117+{
3118+ auto it = unity_window_textures_.find(scale);
3119+ if (it == unity_window_textures_.end())
3120+ {
3121+ LoadAllTextureInScale(scale);
3122+
3123+ it = unity_window_textures_.find(scale);
3124+ if (it == unity_window_textures_.end())
3125+ {
3126+ LOG_ERROR(logger) << "Failed to create unity window style textures, for scale size: " << scale;
3127+ return BaseTexturePtr(nullptr);
3128+ }
3129+ }
3130+
3131+ return it->second[unsigned(type)];
3132+}
3133+
3134+} // namespace ui
3135+} // namespace unity
3136
3137=== modified file 'unity-shared/UnityWindowStyle.h'
3138--- unity-shared/UnityWindowStyle.h 2013-12-11 02:24:29 +0000
3139+++ unity-shared/UnityWindowStyle.h 2014-07-01 15:44:27 +0000
3140@@ -16,6 +16,7 @@
3141 *
3142 * Authored by: Jason Smith <jason.smith@canonical.com>
3143 * Marco Trevisan <marco.trevisan@canonical.com>
3144+ * Brandon Schaefer <brandon.schaefer@canonical.com>
3145 */
3146
3147 #ifndef UNITYWINDOWSTYLE_H
3148@@ -24,8 +25,23 @@
3149 #include <sigc++/sigc++.h>
3150 #include <Nux/Nux.h>
3151
3152-namespace unity {
3153-namespace ui {
3154+#include "RawPixel.h"
3155+
3156+namespace unity
3157+{
3158+namespace ui
3159+{
3160+
3161+enum class WindowTextureType : unsigned
3162+{
3163+ BACKGROUND_TOP,
3164+ BACKGROUND_LEFT,
3165+ BACKGROUND_CORNER,
3166+ CLOSE_ICON,
3167+ CLOSE_ICON_HIGHLIGHTED,
3168+ CLOSE_ICON_PRESSED,
3169+ Size
3170+};
3171
3172 class UnityWindowStyle
3173 {
3174@@ -35,29 +51,28 @@
3175
3176 static UnityWindowStyle::Ptr const& Get();
3177
3178- BaseTexturePtr GetCloseIcon();
3179- BaseTexturePtr GetCloseIconHighligted();
3180- BaseTexturePtr GetCloseIconPressed();
3181- int GetCloseButtonPadding() const;
3182-
3183- BaseTexturePtr GetBackgroundTop() const;
3184- BaseTexturePtr GetBackgroundLeft() const;
3185- BaseTexturePtr GetBackgroundCorner() const;
3186- int GetBorderSize() const;
3187- int GetInternalOffset() const;
3188+ BaseTexturePtr GetTexture(double scale, WindowTextureType const& type);
3189+ int GetCloseButtonPadding(double scale) const;
3190+ int GetBorderSize(double scale) const;
3191+ int GetInternalOffset(double scale) const;
3192
3193 private:
3194 UnityWindowStyle();
3195
3196- BaseTexturePtr background_top_;
3197- BaseTexturePtr background_left_;
3198- BaseTexturePtr background_corner_;
3199- BaseTexturePtr close_icon_;
3200- BaseTexturePtr close_icon_highlighted_;
3201- BaseTexturePtr close_icon_pressed_;
3202+ void ReloadIcons();
3203+ void LoadAllTextureInScale(double scale);
3204+ nux::BaseTexture* LoadTexture(double scale, const char* const texture_name) const;
3205+ RawPixel GetDefaultMaxTextureSize(const char* const texture_name) const;
3206+
3207+ void OnMonitorChanged(int primary, std::vector<nux::Geometry> const& monitors);
3208+ void CleanUpUnusedTextures();
3209+
3210+ typedef std::array<BaseTexturePtr, size_t(WindowTextureType::Size)> UnityWindowTextures;
3211+ std::unordered_map<double, UnityWindowTextures> unity_window_textures_;
3212+
3213 };
3214
3215-}
3216-}
3217+} // namespace ui
3218+} // namespace unity
3219
3220 #endif
3221
3222=== modified file 'unity-shared/UnityWindowView.cpp'
3223--- unity-shared/UnityWindowView.cpp 2014-02-05 12:19:45 +0000
3224+++ unity-shared/UnityWindowView.cpp 2014-07-01 15:44:27 +0000
3225@@ -32,6 +32,8 @@
3226 : View(NUX_FILE_LINE_PARAM)
3227 , style(UnityWindowStyle::Get())
3228 , closable(false)
3229+ , monitor(0)
3230+ , scale(Settings::Instance().em()->DPIScale())
3231 , internal_layout_(nullptr)
3232 , bg_helper_(this)
3233 {
3234@@ -47,6 +49,8 @@
3235
3236 live_background = false;
3237
3238+ monitor.changed.connect(sigc::hide(sigc::mem_fun(this, &UnityWindowView::OnDPIChanged)));
3239+ Settings::Instance().dpi_changed.connect(sigc::mem_fun(this, &UnityWindowView::OnDPIChanged));
3240 closable.changed.connect(sigc::mem_fun(this, &UnityWindowView::OnClosableChanged));
3241 background_color.changed.connect(sigc::hide(sigc::mem_fun(this, &View::QueueDraw)));
3242 }
3243@@ -60,6 +64,17 @@
3244 bounding_area_->UnParentObject();
3245 }
3246
3247+void UnityWindowView::OnDPIChanged()
3248+{
3249+ scale = Settings::Instance().em(monitor())->DPIScale();
3250+
3251+ if (internal_layout_)
3252+ {
3253+ int offset = style()->GetInternalOffset(scale);
3254+ view_layout_->SetPadding(offset, offset);
3255+ }
3256+}
3257+
3258 void UnityWindowView::SetBackgroundHelperGeometryGetter(BackgroundEffectHelper::GeometryGetterFunc const& func)
3259 {
3260 bg_helper_.SetGeometryGetter(func);
3261@@ -109,6 +124,11 @@
3262 return View::FindKeyFocusArea(etype, key_code, modifiers);
3263 }
3264
3265+void UnityWindowView::ReloadCloseButtonTexture()
3266+{
3267+ OnClosableChanged(closable);
3268+}
3269+
3270 void UnityWindowView::OnClosableChanged(bool closable)
3271 {
3272 if (!closable)
3273@@ -117,34 +137,38 @@
3274 return;
3275 }
3276
3277- auto const& texture = style()->GetCloseIcon();
3278- int padding = style()->GetCloseButtonPadding();
3279+ auto const& texture = style()->GetTexture(scale, WindowTextureType::CLOSE_ICON);
3280+ int padding = style()->GetCloseButtonPadding(scale);
3281+
3282 close_button_ = new IconTexture(texture);
3283 close_button_->SetBaseXY(padding, padding);
3284 close_button_->SetParentObject(this);
3285
3286 close_button_->mouse_enter.connect([this](int, int, unsigned long, unsigned long) {
3287 if (close_button_->IsMouseOwner())
3288- close_button_->SetTexture(style()->GetCloseIconPressed());
3289+ close_button_->SetTexture(style()->GetTexture(scale, WindowTextureType::CLOSE_ICON_PRESSED));
3290 else
3291- close_button_->SetTexture(style()->GetCloseIconHighligted());
3292+ close_button_->SetTexture(style()->GetTexture(scale, WindowTextureType::CLOSE_ICON_HIGHLIGHTED));
3293 });
3294
3295 close_button_->mouse_leave.connect([this](int, int, unsigned long, unsigned long) {
3296- close_button_->SetTexture(style()->GetCloseIcon());
3297+ close_button_->SetTexture(style()->GetTexture(scale, WindowTextureType::CLOSE_ICON));
3298 });
3299
3300 close_button_->mouse_down.connect([this](int, int, unsigned long, unsigned long) {
3301- close_button_->SetTexture(style()->GetCloseIconPressed());
3302+ close_button_->SetTexture(style()->GetTexture(scale, WindowTextureType::CLOSE_ICON_PRESSED));
3303 });
3304
3305 close_button_->mouse_up.connect([this](int, int, unsigned long, unsigned long) {
3306 bool inside = close_button_->IsMouseInside();
3307- close_button_->SetTexture(inside ? style()->GetCloseIconHighligted() : style()->GetCloseIcon());
3308+ if (inside)
3309+ close_button_->SetTexture(style()->GetTexture(scale, WindowTextureType::CLOSE_ICON_HIGHLIGHTED));
3310+ else
3311+ close_button_->SetTexture(style()->GetTexture(scale, WindowTextureType::CLOSE_ICON));
3312 });
3313
3314 close_button_->mouse_click.connect([this](int, int, unsigned long, unsigned long) {
3315- close_button_->SetTexture(style()->GetCloseIcon());
3316+ close_button_->SetTexture(style()->GetTexture(scale, WindowTextureType::CLOSE_ICON));
3317 request_close.emit();
3318 });
3319
3320@@ -155,7 +179,7 @@
3321 {
3322 if (layout && layout->IsLayout())
3323 {
3324- int offset = style()->GetInternalOffset();
3325+ int offset = style()->GetInternalOffset(scale);
3326
3327 // We wrap the internal layout adding some padding, so that inherited classes
3328 // can ignore the offsets we define here.
3329@@ -180,7 +204,8 @@
3330
3331 nux::Geometry UnityWindowView::GetInternalBackground()
3332 {
3333- int offset = style()->GetInternalOffset();
3334+ int offset = style()->GetInternalOffset(scale);
3335+
3336 return GetBackgroundGeometry().GetExpand(-offset, -offset);
3337 }
3338
3339@@ -330,7 +355,9 @@
3340
3341 void UnityWindowView::DrawBackground(nux::GraphicsEngine& GfxContext, nux::Geometry const& geo)
3342 {
3343- int border = style()->GetBorderSize();
3344+ int border = style()->GetBorderSize(scale);
3345+
3346+ auto background_corner_textrue = style()->GetTexture(scale, WindowTextureType::BACKGROUND_CORNER)->GetDeviceTexture();
3347
3348 GfxContext.GetRenderStates().SetBlend(true, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
3349
3350@@ -344,7 +371,7 @@
3351 texxform.u1 = border;
3352 texxform.v1 = border;
3353 GfxContext.QRP_1Tex (geo.x, geo.y,
3354- border, border, style()->GetBackgroundCorner()->GetDeviceTexture(), texxform, nux::color::White);
3355+ border, border, background_corner_textrue, texxform, nux::color::White);
3356
3357 // Draw TOP-RIGHT CORNER
3358 texxform.u0 = 0;
3359@@ -354,7 +381,7 @@
3360 texxform.flip_u_coord = true;
3361 texxform.flip_v_coord = false;
3362 GfxContext.QRP_1Tex (geo.x + geo.width - border, geo.y,
3363- border, border, style()->GetBackgroundCorner()->GetDeviceTexture(), texxform, nux::color::White);
3364+ border, border, background_corner_textrue, texxform, nux::color::White);
3365
3366 // Draw BOTTOM-LEFT CORNER
3367 texxform.u0 = 0;
3368@@ -364,7 +391,7 @@
3369 texxform.flip_u_coord = false;
3370 texxform.flip_v_coord = true;
3371 GfxContext.QRP_1Tex (geo.x, geo.y + geo.height - border,
3372- border, border, style()->GetBackgroundCorner()->GetDeviceTexture(), texxform, nux::color::White);
3373+ border, border, background_corner_textrue, texxform, nux::color::White);
3374
3375 // Draw BOTTOM-RIGHT CORNER
3376 texxform.u0 = 0;
3377@@ -374,10 +401,11 @@
3378 texxform.flip_u_coord = true;
3379 texxform.flip_v_coord = true;
3380 GfxContext.QRP_1Tex (geo.x + geo.width - border, geo.y + geo.height - border,
3381- border, border, style()->GetBackgroundCorner()->GetDeviceTexture(), texxform, nux::color::White);
3382+ border, border, background_corner_textrue, texxform, nux::color::White);
3383
3384- int top_width = style()->GetBackgroundTop()->GetWidth();
3385- int top_height = style()->GetBackgroundTop()->GetHeight();
3386+ auto background_top = style()->GetTexture(scale, WindowTextureType::BACKGROUND_TOP);
3387+ int top_width = background_top->GetWidth();
3388+ int top_height = background_top->GetHeight();
3389
3390 // Draw TOP BORDER
3391 texxform.u0 = 0;
3392@@ -386,7 +414,7 @@
3393 texxform.v1 = top_height;
3394 texxform.flip_u_coord = false;
3395 texxform.flip_v_coord = false;
3396- GfxContext.QRP_1Tex (geo.x + border, geo.y, geo.width - border - border, border, style()->GetBackgroundTop()->GetDeviceTexture(), texxform, nux::color::White);
3397+ GfxContext.QRP_1Tex (geo.x + border, geo.y, geo.width - border - border, border, background_top->GetDeviceTexture(), texxform, nux::color::White);
3398
3399 // Draw BOTTOM BORDER
3400 texxform.u0 = 0;
3401@@ -395,11 +423,11 @@
3402 texxform.v1 = top_height;
3403 texxform.flip_u_coord = false;
3404 texxform.flip_v_coord = true;
3405- GfxContext.QRP_1Tex (geo.x + border, geo.y + geo.height - border, geo.width - border - border, border, style()->GetBackgroundTop()->GetDeviceTexture(), texxform, nux::color::White);
3406-
3407-
3408- int left_width = style()->GetBackgroundLeft()->GetWidth();
3409- int left_height = style()->GetBackgroundLeft()->GetHeight();
3410+ GfxContext.QRP_1Tex (geo.x + border, geo.y + geo.height - border, geo.width - border - border, border, background_top->GetDeviceTexture(), texxform, nux::color::White);
3411+
3412+ auto background_left = style()->GetTexture(scale, WindowTextureType::BACKGROUND_LEFT);
3413+ int left_width = background_left->GetWidth();
3414+ int left_height = background_left->GetHeight();
3415
3416 // Draw LEFT BORDER
3417 texxform.u0 = 0;
3418@@ -408,7 +436,7 @@
3419 texxform.v1 = left_height;
3420 texxform.flip_u_coord = false;
3421 texxform.flip_v_coord = false;
3422- GfxContext.QRP_1Tex (geo.x, geo.y + border, border, geo.height - border - border, style()->GetBackgroundLeft()->GetDeviceTexture(), texxform, nux::color::White);
3423+ GfxContext.QRP_1Tex (geo.x, geo.y + border, border, geo.height - border - border, background_left->GetDeviceTexture(), texxform, nux::color::White);
3424
3425 // Draw RIGHT BORDER
3426 texxform.u0 = 0;
3427@@ -417,7 +445,7 @@
3428 texxform.v1 = left_height;
3429 texxform.flip_u_coord = true;
3430 texxform.flip_v_coord = false;
3431- GfxContext.QRP_1Tex (geo.x + geo.width - border, geo.y + border, border, geo.height - border - border, style()->GetBackgroundLeft()->GetDeviceTexture(), texxform, nux::color::White);
3432+ GfxContext.QRP_1Tex (geo.x + geo.width - border, geo.y + border, border, geo.height - border - border, background_left->GetDeviceTexture(), texxform, nux::color::White);
3433
3434 GfxContext.GetRenderStates().SetBlend(false);
3435 }
3436
3437=== modified file 'unity-shared/UnityWindowView.h'
3438--- unity-shared/UnityWindowView.h 2013-11-21 16:06:58 +0000
3439+++ unity-shared/UnityWindowView.h 2014-07-01 15:44:27 +0000
3440@@ -23,6 +23,7 @@
3441
3442 #include "unity-shared/BackgroundEffectHelper.h"
3443 #include "unity-shared/IconTexture.h"
3444+
3445 #include "Introspectable.h"
3446 #include "UnityWindowStyle.h"
3447 #include <sigc++/sigc++.h>
3448@@ -41,6 +42,8 @@
3449 nux::Property<nux::Color> background_color;
3450 nux::Property<UnityWindowStyle::Ptr> style;
3451 nux::Property<bool> closable;
3452+ nux::Property<int> monitor;
3453+ nux::Property<double> scale;
3454
3455 UnityWindowView(NUX_FILE_LINE_PROTO);
3456 virtual ~UnityWindowView();
3457@@ -64,6 +67,8 @@
3458 virtual nux::Geometry GetBlurredBackgroundGeometry();
3459 void SetBackgroundHelperGeometryGetter(BackgroundEffectHelper::GeometryGetterFunc const&);
3460
3461+ void ReloadCloseButtonTexture();
3462+
3463 // Introspectable methods
3464 std::string GetName() const;
3465 void AddProperties(debug::IntrospectionData&);
3466@@ -71,6 +76,7 @@
3467 private:
3468 friend class TestUnityWindowView;
3469
3470+ void OnDPIChanged();
3471 void OnClosableChanged(bool closable);
3472 void DrawBackground(nux::GraphicsEngine& GfxContext, nux::Geometry const& geo);
3473

Subscribers

People subscribed via source and target branches

to all changes:
to status/vote changes: