Merge lp:~unity-2d-team/unity-2d/Shell-MultiMonitor into lp:unity-2d

Proposed by Albert Astals Cid on 2012-03-15
Status: Merged
Approved by: Michał Sawicz on 2012-03-15
Approved revision: 1035
Merged at revision: 992
Proposed branch: lp:~unity-2d-team/unity-2d/Shell-MultiMonitor
Merge into: lp:unity-2d
Diff against target: 5832 lines (+2395/-1016)
85 files modified
data/com.canonical.Unity2d.gschema.xml (+10/-0)
libunity-2d-private/src/CMakeLists.txt (+1/-0)
libunity-2d-private/src/application.cpp (+68/-36)
libunity-2d-private/src/application.h (+5/-3)
libunity-2d-private/src/applicationslist.cpp (+23/-50)
libunity-2d-private/src/applicationslist.h (+8/-3)
libunity-2d-private/src/applicationslistdbus.cpp (+9/-6)
libunity-2d-private/src/applicationslistmanager.cpp (+98/-0)
libunity-2d-private/src/applicationslistmanager.h (+49/-0)
libunity-2d-private/src/bfb.cpp (+39/-16)
libunity-2d-private/src/bfb.h (+9/-6)
libunity-2d-private/src/dashclient.cpp (+27/-0)
libunity-2d-private/src/dashclient.h (+8/-0)
libunity-2d-private/src/hudclient.cpp (+28/-0)
libunity-2d-private/src/hudclient.h (+8/-0)
libunity-2d-private/src/indicatorentrywidget.cpp (+13/-3)
libunity-2d-private/src/indicatorentrywidget.h (+2/-0)
libunity-2d-private/src/launcherdevice.cpp (+6/-0)
libunity-2d-private/src/launcherdevice.h (+1/-0)
libunity-2d-private/src/launcheritem.cpp (+4/-10)
libunity-2d-private/src/launcheritem.h (+4/-2)
libunity-2d-private/src/listaggregatormodel.cpp (+21/-0)
libunity-2d-private/src/listaggregatormodel.h (+2/-0)
libunity-2d-private/src/panelpalettemanager.cpp (+4/-2)
libunity-2d-private/src/screeninfo.cpp (+18/-4)
libunity-2d-private/src/screeninfo.h (+2/-1)
libunity-2d-private/src/strutmanager.cpp (+8/-3)
libunity-2d-private/src/trash.cpp (+6/-0)
libunity-2d-private/src/trash.h (+1/-0)
libunity-2d-private/src/unity2ddeclarativeview.cpp (+95/-114)
libunity-2d-private/src/unity2ddeclarativeview.h (+29/-15)
libunity-2d-private/src/unity2dpanel.cpp (+0/-35)
libunity-2d-private/src/unity2dpanel.h (+0/-18)
libunity-2d-private/src/windowinfo.cpp (+20/-0)
libunity-2d-private/src/windowinfo.h (+3/-1)
libunity-2d-private/src/windowslist.cpp (+2/-0)
libunity-2d-private/src/workspaces.cpp (+6/-0)
libunity-2d-private/src/workspaces.h (+1/-0)
panel/applets/appname/appnameapplet.cpp (+4/-4)
panel/applets/appname/windowhelper.cpp (+12/-9)
panel/applets/appname/windowhelper.h (+1/-1)
shell/DashLoader.qml (+36/-0)
shell/HudLoader.qml (+35/-0)
shell/Shell.qml (+110/-78)
shell/app/CMakeLists.txt (+6/-0)
shell/app/dash.xml (+9/-0)
shell/app/dashdbus.cpp (+21/-13)
shell/app/dashdbus.h (+6/-3)
shell/app/hud.xml (+9/-0)
shell/app/huddbus.cpp (+13/-7)
shell/app/huddbus.h (+6/-3)
shell/app/shell.cpp (+4/-30)
shell/app/shelldbus.cpp (+4/-4)
shell/app/shelldbus.h (+3/-3)
shell/app/shelldeclarativeview.cpp (+27/-232)
shell/app/shelldeclarativeview.h (+12/-55)
shell/app/shellmanager.cpp (+683/-0)
shell/app/shellmanager.h (+128/-0)
shell/common/Background.qml (+12/-2)
shell/common/VisibilityController.qml (+4/-4)
shell/common/visibilityBehaviors/IntelliHideBehavior.qml (+2/-2)
shell/dash/Dash.qml (+49/-38)
shell/dash/Home.qml (+3/-3)
shell/dash/LensBar.qml (+1/-1)
shell/hud/Hud.qml (+11/-5)
shell/launcher/Launcher.qml (+5/-27)
shell/launcher/LauncherItem.qml (+2/-1)
shell/launcher/LauncherList.qml (+19/-10)
shell/launcher/LauncherLoader.qml (+22/-7)
shell/launcher/ListViewDragAndDrop.qml (+6/-0)
spread/Windows.qml (+13/-2)
spread/Workspace.qml (+2/-2)
spread/Workspaces.qml (+15/-7)
spread/app/CMakeLists.txt (+2/-0)
spread/app/spread.cpp (+3/-40)
spread/app/spreadcontrol.h (+2/-6)
spread/app/spreadmanager.cpp (+224/-0)
spread/app/spreadmanager.h (+60/-0)
spread/app/spreadview.cpp (+9/-60)
spread/app/spreadview.h (+3/-9)
tests/dash/fullscreen.rb (+17/-14)
tests/manual-tests/window-manager.txt (+9/-5)
tests/multimonitor/dash-moving.rb (+129/-0)
tests/run-tests.rb (+2/-0)
tests/shell/input_shaping_common.rb (+2/-1)
To merge this branch: bzr merge lp:~unity-2d-team/unity-2d/Shell-MultiMonitor
Reviewer Review Type Date Requested Status
Michał Sawicz 2012-03-15 Approve on 2012-03-15
Review via email: mp+97581@code.launchpad.net

This proposal supersedes a proposal from 2012-03-13.

Commit message

[all] implement multimonitor support in the shell

* allow launcher-per-screen configuration
* HUD and Dash follow mouse cursor
* panel per-screen, also on non-top screens
* spread per-screen
* support the switch to a single launcher on primary monitor

Description of the change

Multimonitor support for the shell

To post a comment you must log in.
1035. By Albert Astals Cid on 2012-03-15

Minor fix for RTL dash placement in MM with screens of different size

Michał Sawicz (saviq) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/com.canonical.Unity2d.gschema.xml'
2--- data/com.canonical.Unity2d.gschema.xml 2012-02-28 15:29:24 +0000
3+++ data/com.canonical.Unity2d.gschema.xml 2012-03-15 09:01:33 +0000
4@@ -15,6 +15,11 @@
5 Unity will adapt its shape and form to the device it is running on.
6 </description>
7 </key>
8+ <key type="b" name="sticky-edges">
9+ <default>true</default>
10+ <summary>Sticky edges.</summary>
11+ <description>Whether the edges in a multi-monitor setup should be sticky or not (Edges with autohide launchers are always sticky).</description>
12+ </key>
13 </schema>
14 <schema path="/com/canonical/unity-2d/launcher/" id="com.canonical.Unity2d.Launcher" gettext-domain="unity-2d">
15 <key type="b" name="super-key-enable">
16@@ -69,6 +74,11 @@
17 Only relevant for multi-monitor setups
18 </description>
19 </key>
20+ <key type="b" name="only-one-launcher">
21+ <default>true</default>
22+ <summary>Show only one launcher.</summary>
23+ <description>Whether in a multi-monitor setup there should be just one launcher in the primary screen or one in each.</description>
24+ </key>
25 </schema>
26 <schema path="/com/canonical/unity-2d/panel/" id="com.canonical.Unity2d.Panel" gettext-domain="unity-2d">
27 <key type="as" name="applets">
28
29=== modified file 'libunity-2d-private/src/CMakeLists.txt'
30--- libunity-2d-private/src/CMakeLists.txt 2012-03-13 18:54:14 +0000
31+++ libunity-2d-private/src/CMakeLists.txt 2012-03-15 09:01:33 +0000
32@@ -45,6 +45,7 @@
33 application.cpp
34 applicationslist.cpp
35 applicationslistdbus.cpp
36+ applicationslistmanager.cpp
37 launcherdevice.cpp
38 launcherdeviceslist.cpp
39 launcherutility.cpp
40
41=== modified file 'libunity-2d-private/src/application.cpp'
42--- libunity-2d-private/src/application.cpp 2012-03-13 19:23:49 +0000
43+++ libunity-2d-private/src/application.cpp 2012-03-15 09:01:33 +0000
44@@ -69,6 +69,16 @@
45
46 const char* SHORTCUT_NICK_PROPERTY = "nick";
47
48+static int windowScreen(WnckWindow *window)
49+{
50+ // Check the window screen
51+ int x, y, width, height;
52+ wnck_window_get_geometry(window, &x, &y, &width, &height);
53+ const QRect windowRect(x, y, width, height);
54+ const QPoint pos = windowRect.center();
55+ return QApplication::desktop()->screenNumber(pos);
56+}
57+
58 Application::Application()
59 : m_application(NULL)
60 , m_desktopFileWatcher(NULL)
61@@ -78,6 +88,7 @@
62 , m_counter(0), m_counterVisible(false)
63 , m_emblem(QString()), m_emblemVisible(false)
64 , m_forceUrgent(false)
65+ , m_previousActiveScreen(-1)
66 , m_dynamicQuicklistServiceWatcher(NULL)
67 {
68 m_launching_timer.setSingleShot(true);
69@@ -93,6 +104,7 @@
70 m_geometryChangedTimer.setSingleShot(true);
71 m_geometryChangedTimer.setInterval(50);
72 connect(&m_geometryChangedTimer, SIGNAL(timeout()), this, SIGNAL(windowGeometryChanged()));
73+ connect(&m_geometryChangedTimer, SIGNAL(timeout()), this, SLOT(announceActiveScreenChangedIfNeeded()));
74 }
75
76 Application::Application(const Application& other)
77@@ -460,6 +472,15 @@
78 }
79
80 void
81+Application::announceActiveScreenChangedIfNeeded()
82+{
83+ if (m_previousActiveScreen != activeScreen()) {
84+ m_previousActiveScreen = activeScreen();
85+ Q_EMIT activeScreenChanged(m_previousActiveScreen);
86+ }
87+}
88+
89+void
90 Application::onBamfApplicationClosed(bool running)
91 {
92 if(running)
93@@ -493,7 +514,7 @@
94 }
95
96 void
97-Application::setIconGeometry(int x, int y, int width, int height, uint xid)
98+Application::setIconGeometry(int x, int y, int width, int height, int screen, uint xid)
99 {
100 if (m_application == NULL) {
101 return;
102@@ -512,12 +533,13 @@
103 return;
104 }
105
106- WnckScreen* screen = wnck_screen_get_default();
107- wnck_screen_force_update(screen);
108+ wnck_screen_force_update(wnck_screen_get_default());
109
110 for (int i = 0; i < size; ++i) {
111 WnckWindow* window = wnck_window_get(xids->at(i));
112- wnck_window_set_icon_geometry(window, x, y, width, height);
113+ if (screen == -1 || windowScreen(window) == screen) {
114+ wnck_window_set_icon_geometry(window, x, y, width, height);
115+ }
116 }
117 }
118
119@@ -528,8 +550,8 @@
120 return;
121 }
122
123- QScopedPointer<BamfUintList> xids(m_application->xids());
124- int size = xids->size();
125+ QScopedPointer<BamfWindowList> windows(m_application->windows());
126+ const int size = windows->size();
127 if (size < 1) {
128 return;
129 }
130@@ -538,10 +560,8 @@
131 wnck_screen_force_update(screen);
132
133 for (int i = 0; i < size; ++i) {
134- WnckWindow* window = wnck_window_get(xids->at(i));
135- m_gConnector.connect(G_OBJECT(window), "workspace-changed",
136- G_CALLBACK(Application::onWindowWorkspaceChanged), this);
137- m_gConnector.connect(G_OBJECT(window), "geometry-changed", G_CALLBACK(geometryChangedCB), this);
138+ BamfWindow *window = windows->at(i);
139+ onWindowAdded(window);
140 }
141 }
142
143@@ -554,6 +574,7 @@
144 m_gConnector.connect(G_OBJECT(wnck_window), "workspace-changed",
145 G_CALLBACK(Application::onWindowWorkspaceChanged), this);
146 m_gConnector.connect(G_OBJECT(wnck_window), "geometry-changed", G_CALLBACK(geometryChangedCB), this);
147+ connect(window, SIGNAL(ActiveChanged(bool)), this, SLOT(announceActiveScreenChangedIfNeeded()));
148 }
149 }
150
151@@ -682,6 +703,26 @@
152 return windowCount;
153 }
154
155+int
156+Application::activeScreen() const
157+{
158+ if (!active()) {
159+ return -1;
160+ }
161+
162+ BamfWindow *bamfWindow = BamfMatcher::get_default().active_window();
163+ if (bamfWindow == NULL) {
164+ return -1;
165+ }
166+
167+ WnckWindow *wnckWindow = wnck_window_get(bamfWindow->xid());
168+ if (wnckWindow == NULL) {
169+ return -1;
170+ }
171+
172+ return windowScreen(wnckWindow);
173+}
174+
175 void
176 Application::activate()
177 {
178@@ -991,28 +1032,15 @@
179 }
180 }
181
182-bool
183-Application::belongsToDifferentWorkspace()
184-{
185- int totalWindows = windowCount();
186- int windowsInCurrentWorkspace = windowCountOnCurrentWorkspace();
187- if (totalWindows > 0 && windowsInCurrentWorkspace == 0) {
188- return true;
189- }
190-
191- return false;
192-}
193-
194-bool
195-Application::belongsToDifferentScreen(int screen)
196+int
197+Application::windowsOnCurrentWorkspaceScreen(int screen)
198 {
199 if (!m_application) {
200- return false;
201+ return 0;
202 }
203
204- if (QApplication::desktop()->screenCount() == 1) {
205- return false;
206- }
207+ int windowCount = 0;
208+ WnckWorkspace *current = wnck_screen_get_active_workspace(wnck_screen_get_default());
209
210 QScopedPointer<BamfUintList> xids(m_application->xids());
211 for (int i = 0; i < xids->size(); i++) {
212@@ -1028,17 +1056,21 @@
213 }
214 }
215
216- // Check the window screen
217- int x, y, width, height;
218- wnck_window_get_geometry(window, &x, &y, &width, &height);
219- const QRect windowRect(x, y, width, height);
220- const QPoint pos = windowRect.center();
221- if (QApplication::desktop()->screenNumber(pos) == screen) {
222- return false;
223+ if (wnck_window_is_pinned(window)) {
224+ windowCount++;
225+ } else {
226+ WnckWorkspace *workspace = wnck_window_get_workspace(window);
227+ if (workspace == current) {
228+ if (screen == -1) {
229+ windowCount++;
230+ } else if (windowScreen(window) == screen) {
231+ windowCount++;
232+ }
233+ }
234 }
235 }
236
237- return true;
238+ return windowCount;
239 }
240
241 void
242
243=== modified file 'libunity-2d-private/src/application.h'
244--- libunity-2d-private/src/application.h 2012-03-12 12:46:39 +0000
245+++ libunity-2d-private/src/application.h 2012-03-15 09:01:33 +0000
246@@ -72,6 +72,7 @@
247
248 /* getters */
249 virtual bool active() const;
250+ virtual int activeScreen() const;
251 virtual bool running() const;
252 virtual int windowCount() const;
253 virtual bool urgent() const;
254@@ -101,12 +102,11 @@
255 Q_INVOKABLE virtual void activate();
256 Q_INVOKABLE void close();
257 Q_INVOKABLE void spread(bool showAllWorkspaces = false);
258- Q_INVOKABLE void setIconGeometry(int x, int y, int width, int height, uint xid=0);
259+ Q_INVOKABLE void setIconGeometry(int x, int y, int width, int height, int screen, uint xid=0);
260 Q_INVOKABLE virtual void launchNewInstance();
261
262 Q_INVOKABLE virtual void createMenuActions();
263- Q_INVOKABLE virtual bool belongsToDifferentWorkspace();
264- Q_INVOKABLE virtual bool belongsToDifferentScreen(int screen);
265+ Q_INVOKABLE virtual int windowsOnCurrentWorkspaceScreen(int screen);
266 Q_INVOKABLE void connectWindowSignals();
267
268 void updateOverlaysState(const QString& sender, const QMap<QString, QVariant>& properties);
269@@ -128,6 +128,7 @@
270 void updateHasVisibleWindow();
271 void updateWindowCount();
272 void updateCounterVisible();
273+ void announceActiveScreenChangedIfNeeded();
274
275 bool launch();
276 void show();
277@@ -172,6 +173,7 @@
278 QString m_emblem;
279 bool m_emblemVisible;
280 bool m_forceUrgent;
281+ int m_previousActiveScreen;
282
283 void updateBamfApplicationDependentProperties();
284 void monitorDesktopFile(const QString&);
285
286=== modified file 'libunity-2d-private/src/applicationslist.cpp'
287--- libunity-2d-private/src/applicationslist.cpp 2012-02-16 11:24:19 +0000
288+++ libunity-2d-private/src/applicationslist.cpp 2012-03-15 09:01:33 +0000
289@@ -16,8 +16,8 @@
290
291 #include "application.h"
292 #include "applicationslist.h"
293+#include "applicationslistmanager.h"
294 #include "webfavorite.h"
295-#include "applicationslistdbus.h"
296
297 #include "bamf-matcher.h"
298 #include "bamf-application.h"
299@@ -29,8 +29,6 @@
300
301 #include <QStringList>
302 #include <QDir>
303-#include <QDBusConnection>
304-#include <QDBusMessage>
305 #include <QFileInfo>
306 #include <QProcess>
307 #include <QX11Info>
308@@ -41,12 +39,6 @@
309 #include <libsn/sn.h>
310 }
311
312-
313-#define DBUS_SERVICE_UNITY "com.canonical.Unity"
314-#define DBUS_SERVICE_LAUNCHER_ENTRY "com.canonical.Unity.LauncherEntry"
315-#define DBUS_SERVICE_LAUNCHER "com.canonical.Unity.Launcher"
316-#define DBUS_OBJECT_LAUNCHER "/com/canonical/Unity/Launcher"
317-
318 /* List of executables that are too generic to be matched against a single application. */
319 static const QStringList EXECUTABLES_BLACKLIST = (QStringList() << "xdg-open");
320 static const QByteArray LATEST_SETTINGS_MIGRATION = "3.2.10";
321@@ -54,34 +46,6 @@
322 ApplicationsList::ApplicationsList(QObject *parent) :
323 QAbstractListModel(parent)
324 {
325- QDBusConnection session = QDBusConnection::sessionBus();
326- /* FIXME: libunity will send out the Update signal for LauncherEntries
327- only if it finds com.canonical.Unity on the bus, so let's just quickly
328- register ourselves as Unity here. Should be moved somewhere else more proper */
329- if (!session.registerService(DBUS_SERVICE_UNITY)) {
330- UQ_WARNING << "The name" << DBUS_SERVICE_UNITY << "is already taken on DBUS";
331- } else {
332- /* Set ourselves up to receive any Update signal coming from any
333- LauncherEntry */
334- session.connect(QString(), QString(),
335- DBUS_SERVICE_LAUNCHER_ENTRY, "Update",
336- this, SLOT(onRemoteEntryUpdated(QString,QMap<QString,QVariant>)));
337- }
338-
339- if (!session.registerService(DBUS_SERVICE_LAUNCHER)) {
340- UQ_WARNING << "The name" << DBUS_SERVICE_LAUNCHER << "is already taken on DBUS";
341- } else {
342- /* Set ourselves up to receive a method call from Software Center asking us to add
343- to favorites an application that is being installed and that the user requested
344- to be added. */
345- ApplicationsListDBUS *dbusAdapter = new ApplicationsListDBUS(this);
346- if (!session.registerObject(DBUS_OBJECT_LAUNCHER, dbusAdapter,
347- QDBusConnection::ExportAllSlots)) {
348- UQ_WARNING << "The object" << DBUS_OBJECT_LAUNCHER << "on" << DBUS_SERVICE_LAUNCHER
349- << "is already present on DBUS.";
350- }
351- }
352-
353 /* Register the display to receive startup notifications */
354 Display *xdisplay = QX11Info::display();
355 m_snDisplay = sn_display_new(xdisplay, NULL, NULL);
356@@ -108,6 +72,8 @@
357 }
358
359 load();
360+
361+ ApplicationsListManager::instance()->addList(this);
362 }
363
364 void
365@@ -151,19 +117,8 @@
366 return false;
367 }
368
369-void
370-ApplicationsList::onRemoteEntryUpdated(QString applicationURI, QMap<QString, QVariant> properties)
371+void ApplicationsList::remoteEntryUpdated(const QString& desktopFile, const QString& sender, const QString& applicationURI, const QMap<QString, QVariant>& properties)
372 {
373- UQ_RETURN_IF_FAIL(calledFromDBus());
374- QString sender = message().service();
375- QString desktopFile;
376- if (applicationURI.indexOf("application://") == 0) {
377- desktopFile = applicationURI.mid(14);
378- } else {
379- UQ_WARNING << "Ignoring update that didn't come from an application:// URI but from:" << applicationURI;
380- return;
381- }
382-
383 Q_FOREACH(Application *application, m_applications) {
384 if (QFileInfo(application->desktop_file()).fileName() == desktopFile) {
385 application->updateOverlaysState(sender, properties);
386@@ -176,6 +131,8 @@
387
388 ApplicationsList::~ApplicationsList()
389 {
390+ ApplicationsListManager::instance()->removeList(this);
391+
392 sn_monitor_context_unref(m_snContext);
393 sn_display_unref(m_snDisplay);
394
395@@ -502,7 +459,17 @@
396 }
397
398 void
399-ApplicationsList::move(int from, int to)
400+ApplicationsList::moveFinished(int from, int to)
401+{
402+ Q_FOREACH(ApplicationsList *other, ApplicationsListManager::instance()->m_lists) {
403+ if (other != this) {
404+ other->doMove(from, to);
405+ }
406+ }
407+}
408+
409+void
410+ApplicationsList::doMove(int from, int to)
411 {
412 QModelIndex parent;
413 /* When moving an item down, the destination index needs to be incremented
414@@ -511,6 +478,12 @@
415 beginMoveRows(parent, from, from, parent, to + (to > from ? 1 : 0));
416 m_applications.move(from, to);
417 endMoveRows();
418+}
419+
420+void
421+ApplicationsList::move(int from, int to)
422+{
423+ doMove(from, to);
424
425 if (m_applications[from]->sticky() || m_applications[to]->sticky()) {
426 /* Update favorites only if at least one of the applications is a favorite */
427
428=== modified file 'libunity-2d-private/src/applicationslist.h'
429--- libunity-2d-private/src/applicationslist.h 2012-02-16 11:24:19 +0000
430+++ libunity-2d-private/src/applicationslist.h 2012-03-15 09:01:33 +0000
431@@ -21,6 +21,7 @@
432 #include <QList>
433 #include <QVariant>
434 #include <QString>
435+#include <QStringList>
436 #include <QUrl>
437 #include <QObject>
438 #include <QtDeclarative/qdeclarative.h>
439@@ -37,10 +38,11 @@
440 class BamfApplication;
441 class BamfView;
442
443-class ApplicationsList : public QAbstractListModel, protected AbstractX11EventFilter, protected QDBusContext
444+class ApplicationsList : public QAbstractListModel, protected AbstractX11EventFilter
445 {
446 Q_OBJECT
447 friend class ApplicationsListDBUS;
448+ friend class ApplicationsListManager;
449
450 public:
451 ApplicationsList(QObject *parent = 0);
452@@ -54,6 +56,7 @@
453
454 public Q_SLOTS:
455 void move(int from, int to);
456+ void moveFinished(int from, int to);
457
458 Q_SIGNALS:
459 void applicationBecameUrgent(int index);
460@@ -73,6 +76,10 @@
461
462 void writeFavoritesToGConf();
463
464+ void remoteEntryUpdated(const QString& desktopFile, const QString& sender, const QString& applicationURI, const QMap<QString, QVariant>& properties);
465+
466+ void doMove(int from, int to);
467+
468 /* List of Application displayed in the launcher. */
469 QList<Application*> m_applications;
470 /* Hash of desktop file names to Application used to reduce
471@@ -102,8 +109,6 @@
472 void onApplicationLaunchingChanged(bool launching);
473 void onApplicationUrgentChanged(bool urgent);
474 void onApplicationUserVisibleChanged(bool user_visible);
475- void onRemoteEntryUpdated(QString applicationURI,
476- QMap<QString, QVariant> properties);
477 };
478
479 QML_DECLARE_TYPE(ApplicationsList)
480
481=== modified file 'libunity-2d-private/src/applicationslistdbus.cpp'
482--- libunity-2d-private/src/applicationslistdbus.cpp 2012-02-16 11:24:19 +0000
483+++ libunity-2d-private/src/applicationslistdbus.cpp 2012-03-15 09:01:33 +0000
484@@ -1,6 +1,7 @@
485 #include "application.h"
486 #include "applicationslistdbus.h"
487 #include "applicationslist.h"
488+#include "applicationslistmanager.h"
489
490 ApplicationsListDBUS::ApplicationsListDBUS(QObject *parent) :
491 QDBusAbstractAdaptor(parent)
492@@ -19,12 +20,14 @@
493 Q_UNUSED(icon_size)
494 Q_UNUSED(aptdaemon_task)
495
496- ApplicationsList* applicationsList = qobject_cast<ApplicationsList*>(parent());
497- if (applicationsList != NULL && !desktop_file.isEmpty()) {
498- applicationsList->insertFavoriteApplication(desktop_file);
499- Application *application = applicationsList->m_applicationForDesktopFile.value(desktop_file, NULL);
500- if (application != NULL) {
501- application->beginForceUrgent(1500);
502+ ApplicationsListManager* applicationsListManager = qobject_cast<ApplicationsListManager*>(parent());
503+ if (applicationsListManager != NULL && !desktop_file.isEmpty()) {
504+ Q_FOREACH(ApplicationsList *applicationsList, applicationsListManager->m_lists) {
505+ applicationsList->insertFavoriteApplication(desktop_file);
506+ Application *application = applicationsList->m_applicationForDesktopFile.value(desktop_file, NULL);
507+ if (application != NULL) {
508+ application->beginForceUrgent(1500);
509+ }
510 }
511 }
512 }
513
514=== added file 'libunity-2d-private/src/applicationslistmanager.cpp'
515--- libunity-2d-private/src/applicationslistmanager.cpp 1970-01-01 00:00:00 +0000
516+++ libunity-2d-private/src/applicationslistmanager.cpp 2012-03-15 09:01:33 +0000
517@@ -0,0 +1,98 @@
518+/*
519+ * Copyright (C) 2012 Canonical, Ltd.
520+ *
521+ * This program is free software; you can redistribute it and/or modify
522+ * it under the terms of the GNU General Public License as published by
523+ * the Free Software Foundation; version 3.
524+ *
525+ * This program is distributed in the hope that it will be useful,
526+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
527+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
528+ * GNU General Public License for more details.
529+ *
530+ * You should have received a copy of the GNU General Public License
531+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
532+ */
533+
534+#include "applicationslistmanager.h"
535+
536+// unity-2d
537+#include "applicationslist.h"
538+#include "applicationslistdbus.h"
539+#include "debug_p.h"
540+
541+// Qt
542+#include <QDBusConnection>
543+#include <QDBusMessage>
544+
545+#define DBUS_SERVICE_UNITY "com.canonical.Unity"
546+#define DBUS_SERVICE_LAUNCHER_ENTRY "com.canonical.Unity.LauncherEntry"
547+#define DBUS_SERVICE_LAUNCHER "com.canonical.Unity.Launcher"
548+#define DBUS_OBJECT_LAUNCHER "/com/canonical/Unity/Launcher"
549+
550+ApplicationsListManager::ApplicationsListManager()
551+{
552+ QDBusConnection session = QDBusConnection::sessionBus();
553+ /* FIXME: libunity will send out the Update signal for LauncherEntries
554+ only if it finds com.canonical.Unity on the bus, so let's just quickly
555+ register ourselves as Unity here. Should be moved somewhere else more proper */
556+ if (!session.registerService(DBUS_SERVICE_UNITY)) {
557+ UQ_WARNING << "The name" << DBUS_SERVICE_UNITY << "is already taken on DBUS";
558+ } else {
559+ /* Set ourselves up to receive any Update signal coming from any
560+ LauncherEntry */
561+ session.connect(QString(), QString(),
562+ DBUS_SERVICE_LAUNCHER_ENTRY, "Update",
563+ this, SLOT(onRemoteEntryUpdated(QString,QMap<QString,QVariant>)));
564+ }
565+
566+ if (!session.registerService(DBUS_SERVICE_LAUNCHER)) {
567+ UQ_WARNING << "The name" << DBUS_SERVICE_LAUNCHER << "is already taken on DBUS";
568+ } else {
569+ /* Set ourselves up to receive a method call from Software Center asking us to add
570+ to favorites an application that is being installed and that the user requested
571+ to be added. */
572+ ApplicationsListDBUS *dbusAdapter = new ApplicationsListDBUS(this);
573+ if (!session.registerObject(DBUS_OBJECT_LAUNCHER, dbusAdapter,
574+ QDBusConnection::ExportAllSlots)) {
575+ UQ_WARNING << "The object" << DBUS_OBJECT_LAUNCHER << "on" << DBUS_SERVICE_LAUNCHER
576+ << "is already present on DBUS.";
577+ }
578+ }
579+}
580+
581+ApplicationsListManager *ApplicationsListManager::instance()
582+{
583+ static ApplicationsListManager manager;
584+ return &manager;
585+}
586+
587+void ApplicationsListManager::addList(ApplicationsList *list)
588+{
589+ m_lists += list;
590+}
591+
592+void ApplicationsListManager::removeList(ApplicationsList *list)
593+{
594+ m_lists -= list;
595+}
596+
597+void
598+ApplicationsListManager::onRemoteEntryUpdated(QString applicationURI, QMap<QString, QVariant> properties)
599+{
600+ UQ_RETURN_IF_FAIL(calledFromDBus());
601+ QString sender = message().service();
602+ QString desktopFile;
603+ if (applicationURI.indexOf("application://") == 0) {
604+ desktopFile = applicationURI.mid(14);
605+ } else {
606+ UQ_WARNING << "Ignoring update that didn't come from an application:// URI but from:" << applicationURI;
607+ return;
608+ }
609+
610+ Q_FOREACH(ApplicationsList *list, m_lists) {
611+ list->remoteEntryUpdated(desktopFile, sender, applicationURI, properties);
612+ }
613+}
614+
615+#include "applicationslistmanager.moc"
616\ No newline at end of file
617
618=== added file 'libunity-2d-private/src/applicationslistmanager.h'
619--- libunity-2d-private/src/applicationslistmanager.h 1970-01-01 00:00:00 +0000
620+++ libunity-2d-private/src/applicationslistmanager.h 2012-03-15 09:01:33 +0000
621@@ -0,0 +1,49 @@
622+/*
623+ * Copyright (C) 2012 Canonical, Ltd.
624+ *
625+ * This program is free software; you can redistribute it and/or modify
626+ * it under the terms of the GNU General Public License as published by
627+ * the Free Software Foundation; version 3.
628+ *
629+ * This program is distributed in the hope that it will be useful,
630+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
631+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
632+ * GNU General Public License for more details.
633+ *
634+ * You should have received a copy of the GNU General Public License
635+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
636+ */
637+
638+#ifndef APPLICATIONSLISTMODEL_H
639+#define APPLICATIONSLISTMODEL_H
640+
641+#include <QObject>
642+#include <QDBusContext>
643+
644+#include <QSet>
645+
646+class ApplicationsList;
647+
648+class ApplicationsListManager : public QObject, protected QDBusContext
649+{
650+ Q_OBJECT
651+ friend class ApplicationsListDBUS;
652+ friend class ApplicationsList;
653+
654+public:
655+ static ApplicationsListManager *instance();
656+
657+ void addList(ApplicationsList *list);
658+ void removeList(ApplicationsList *list);
659+
660+private Q_SLOTS:
661+ void onRemoteEntryUpdated(QString applicationURI,
662+ QMap<QString, QVariant> properties);
663+
664+private:
665+ ApplicationsListManager();
666+
667+ QSet<ApplicationsList*> m_lists;
668+};
669+
670+#endif // APPLICATIONSLISTMODEL_H
671
672=== modified file 'libunity-2d-private/src/bfb.cpp'
673--- libunity-2d-private/src/bfb.cpp 2012-01-19 14:22:10 +0000
674+++ libunity-2d-private/src/bfb.cpp 2012-03-15 09:01:33 +0000
675@@ -27,7 +27,7 @@
676 // Qt
677
678 BfbItem::BfbItem()
679-: m_active(false), m_view(NULL)
680+: m_active(false), m_activeScreen(-1), m_manager(NULL)
681 {
682 }
683
684@@ -40,6 +40,15 @@
685 return m_active;
686 }
687
688+int BfbItem::activeScreen() const
689+{
690+ if (active()) {
691+ return m_activeScreen;
692+ } else {
693+ return -1;
694+ }
695+}
696+
697 bool BfbItem::running() const
698 {
699 return false;
700@@ -70,27 +79,28 @@
701 return false;
702 }
703
704-QObject* BfbItem::dashView() const
705+QObject* BfbItem::dashManager() const
706 {
707- return m_view;
708+ return m_manager;
709 }
710
711-void BfbItem::setDashView(QObject* view)
712+void BfbItem::setDashManager(QObject* manager)
713 {
714- if (m_view != NULL) {
715- disconnect(view);
716+ if (m_manager != NULL) {
717+ disconnect(m_manager);
718 }
719- m_view = view;
720- if (m_view != NULL) {
721- connect(view, SIGNAL(dashActiveChanged(bool)), this, SLOT(slotDashActiveChanged(bool)));
722+ m_manager = manager;
723+ if (m_manager != NULL) {
724+ connect(manager, SIGNAL(dashActiveChanged(bool)), this, SLOT(slotDashActiveChanged(bool)));
725+ connect(manager, SIGNAL(dashScreenChanged(int)), this, SLOT(slotDashScreenChanged(int)));
726 }
727 }
728
729 void BfbItem::activate()
730 {
731- Q_ASSERT(m_view != NULL);
732- if (m_view != NULL) {
733- QMetaObject::invokeMethod(m_view, "toggleDash");
734+ Q_ASSERT(m_manager != NULL);
735+ if (m_manager != NULL) {
736+ QMetaObject::invokeMethod(m_manager, "toggleDashRequested");
737 }
738 }
739
740@@ -103,6 +113,19 @@
741 if (m_active != active) {
742 m_active = active;
743 Q_EMIT activeChanged(m_active);
744+ if (m_active) {
745+ Q_EMIT activeScreenChanged(m_activeScreen);
746+ }
747+ }
748+}
749+
750+void BfbItem::slotDashScreenChanged(int activeScreen)
751+{
752+ if (m_activeScreen != activeScreen) {
753+ m_activeScreen = activeScreen;
754+ if (m_active) {
755+ Q_EMIT activeScreenChanged(m_activeScreen);
756+ }
757 }
758 }
759
760@@ -132,14 +155,14 @@
761 return QVariant::fromValue(m_bfbItem);
762 }
763
764-QObject* BfbModel::dashView() const
765+QObject* BfbModel::dashManager() const
766 {
767- return m_bfbItem->dashView();
768+ return m_bfbItem->dashManager();
769 }
770
771-void BfbModel::setDashView(QObject* view)
772+void BfbModel::setDashManager(QObject* manager)
773 {
774- m_bfbItem->setDashView(view);
775+ m_bfbItem->setDashManager(manager);
776 }
777
778 #include <bfb.moc>
779
780=== modified file 'libunity-2d-private/src/bfb.h'
781--- libunity-2d-private/src/bfb.h 2012-01-19 14:22:10 +0000
782+++ libunity-2d-private/src/bfb.h 2012-03-15 09:01:33 +0000
783@@ -35,6 +35,7 @@
784
785 /* getters */
786 virtual bool active() const;
787+ virtual int activeScreen() const;
788 virtual bool running() const;
789 virtual int windowCount() const;
790 virtual bool urgent() const;
791@@ -42,8 +43,8 @@
792 virtual QString icon() const;
793 virtual bool launching() const;
794
795- QObject* dashView() const;
796- void setDashView(QObject* view);
797+ QObject* dashManager() const;
798+ void setDashManager(QObject* manager);
799
800 /* methods */
801 Q_INVOKABLE virtual void activate();
802@@ -51,11 +52,13 @@
803
804 private Q_SLOTS:
805 void slotDashActiveChanged(bool active);
806+ void slotDashScreenChanged(int screen);
807
808 private:
809 Q_DISABLE_COPY(BfbItem)
810 bool m_active;
811- QObject* m_view;
812+ int m_activeScreen;
813+ QObject* m_manager;
814 };
815
816 Q_DECLARE_METATYPE(BfbItem*)
817@@ -64,7 +67,7 @@
818 class BfbModel : public QAbstractListModel
819 {
820 Q_OBJECT
821- Q_PROPERTY(QObject* dashView READ dashView WRITE setDashView)
822+ Q_PROPERTY(QObject* dashManager READ dashManager WRITE setDashManager)
823 public:
824 BfbModel(QObject* parent = 0);
825 ~BfbModel();
826@@ -72,8 +75,8 @@
827 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
828 int rowCount(const QModelIndex& parent = QModelIndex()) const;
829
830- QObject* dashView() const;
831- void setDashView(QObject* view);
832+ QObject* dashManager() const;
833+ void setDashManager(QObject* manager);
834
835 private:
836 Q_DISABLE_COPY(BfbModel)
837
838=== modified file 'libunity-2d-private/src/dashclient.cpp'
839--- libunity-2d-private/src/dashclient.cpp 2012-03-06 11:16:00 +0000
840+++ libunity-2d-private/src/dashclient.cpp 2012-03-15 09:01:33 +0000
841@@ -75,6 +75,8 @@
842 SLOT(slotActiveChanged(bool)));
843 connect(m_dashDbusIface, SIGNAL(alwaysFullScreenChanged(bool)),
844 SLOT(slotAlwaysFullScreenChanged(bool)));
845+ connect(m_dashDbusIface, SIGNAL(screenChanged(int)),
846+ SLOT(slotScreenChanged(int)));
847
848 QVariant value = m_dashDbusIface->property("active");
849 if (value.isValid()) {
850@@ -89,6 +91,13 @@
851 } else {
852 UQ_WARNING << "Fetching Dash.alwaysFullScreen property failed";
853 }
854+
855+ value = m_dashDbusIface->property("screen");
856+ if (value.isValid()) {
857+ m_screen = value.toInt();
858+ } else {
859+ UQ_WARNING << "Fetching Dash.screen property failed";
860+ }
861 }
862
863 DashClient* DashClient::instance()
864@@ -136,4 +145,22 @@
865 return m_alwaysFullScreen;
866 }
867
868+void DashClient::slotScreenChanged(int screen)
869+{
870+ if (screen != m_screen) {
871+ m_screen = screen;
872+ Q_EMIT screenChanged(screen);
873+ }
874+}
875+
876+int DashClient::screen() const
877+{
878+ return m_screen;
879+}
880+
881+bool DashClient::activeInScreen(int screen) const
882+{
883+ return active() && m_screen == screen;
884+}
885+
886 #include "dashclient.moc"
887
888=== modified file 'libunity-2d-private/src/dashclient.h'
889--- libunity-2d-private/src/dashclient.h 2012-03-06 10:06:05 +0000
890+++ libunity-2d-private/src/dashclient.h 2012-03-15 09:01:33 +0000
891@@ -37,6 +37,7 @@
892 Q_OBJECT
893 Q_PROPERTY(bool alwaysFullScreen READ alwaysFullScreen NOTIFY alwaysFullScreenChanged)
894 Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
895+ Q_PROPERTY(int screen READ screen NOTIFY screenChanged)
896
897 public:
898 static DashClient* instance();
899@@ -46,14 +47,20 @@
900
901 bool alwaysFullScreen() const;
902
903+ int screen() const;
904+
905+ bool activeInScreen(int screen) const;
906+
907 Q_SIGNALS:
908 void activeChanged(bool);
909 void alwaysFullScreenChanged();
910+ void screenChanged(int);
911
912 private Q_SLOTS:
913 void connectToDash();
914 void slotActiveChanged(bool);
915 void slotAlwaysFullScreenChanged(bool);
916+ void slotScreenChanged(int);
917
918 private:
919 DashClient(QObject* parent = 0);
920@@ -61,6 +68,7 @@
921 QDBusInterface* m_dashDbusIface;
922 bool m_active;
923 bool m_alwaysFullScreen;
924+ int m_screen;
925 };
926
927 #endif /* DASHCLIENT_H */
928
929=== modified file 'libunity-2d-private/src/hudclient.cpp'
930--- libunity-2d-private/src/hudclient.cpp 2012-03-06 11:16:00 +0000
931+++ libunity-2d-private/src/hudclient.cpp 2012-03-15 09:01:33 +0000
932@@ -72,6 +72,8 @@
933 QDBusConnection::sessionBus(), this);
934 connect(m_hudDbusIface, SIGNAL(activeChanged(bool)),
935 SLOT(slotActiveChanged(bool)));
936+ connect(m_hudDbusIface, SIGNAL(screenChanged(int)),
937+ SLOT(slotScreenChanged(int)));
938
939 QVariant value = m_hudDbusIface->property("active");
940 if (value.isValid()) {
941@@ -79,6 +81,14 @@
942 } else {
943 UQ_WARNING << "Fetching HUD.active property failed";
944 }
945+
946+ value = m_hudDbusIface->property("screen");
947+ if (value.isValid()) {
948+ m_screen = value.toInt();
949+ } else {
950+ UQ_WARNING << "Fetching Hud.screen property failed";
951+ }
952+
953 }
954
955 HUDClient* HUDClient::instance()
956@@ -113,4 +123,22 @@
957 }
958 }
959
960+void HUDClient::slotScreenChanged(int screen)
961+{
962+ if (screen != m_screen) {
963+ m_screen = screen;
964+ Q_EMIT screenChanged(screen);
965+ }
966+}
967+
968+int HUDClient::screen() const
969+{
970+ return m_screen;
971+}
972+
973+bool HUDClient::activeInScreen(int screen) const
974+{
975+ return active() && m_screen == screen;
976+}
977+
978 #include "hudclient.moc"
979
980=== modified file 'libunity-2d-private/src/hudclient.h'
981--- libunity-2d-private/src/hudclient.h 2012-03-06 10:06:05 +0000
982+++ libunity-2d-private/src/hudclient.h 2012-03-15 09:01:33 +0000
983@@ -36,6 +36,7 @@
984 {
985 Q_OBJECT
986 Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
987+ Q_PROPERTY(int screen READ screen NOTIFY screenChanged)
988
989 public:
990 static HUDClient* instance();
991@@ -43,18 +44,25 @@
992 bool active() const;
993 void setActive(bool active);
994
995+ int screen() const;
996+
997+ bool activeInScreen(int screen) const;
998+
999 Q_SIGNALS:
1000 void activeChanged(bool);
1001+ void screenChanged(int);
1002
1003 private Q_SLOTS:
1004 void connectToHud();
1005 void slotActiveChanged(bool);
1006+ void slotScreenChanged(int);
1007
1008 private:
1009 HUDClient(QObject* parent = 0);
1010
1011 QDBusInterface* m_hudDbusIface;
1012 bool m_active;
1013+ int m_screen;
1014 };
1015
1016 #endif /* HUDCLIENT_H */
1017
1018=== modified file 'libunity-2d-private/src/indicatorentrywidget.cpp'
1019--- libunity-2d-private/src/indicatorentrywidget.cpp 2012-02-12 15:10:03 +0000
1020+++ libunity-2d-private/src/indicatorentrywidget.cpp 2012-03-15 09:01:33 +0000
1021@@ -50,6 +50,7 @@
1022 , m_padding(PADDING)
1023 , m_hasIcon(false)
1024 , m_hasLabel(false)
1025+, m_activatedByThisEntry(false)
1026 , m_gtkWidgetPath(gtk_widget_path_new())
1027 {
1028 gtk_widget_path_append_type(m_gtkWidgetPath, GTK_TYPE_WINDOW);
1029@@ -59,6 +60,7 @@
1030
1031 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
1032 m_entry->updated.connect(sigc::mem_fun(this, &IndicatorEntryWidget::updatePix));
1033+ m_entry->active_changed.connect(sigc::mem_fun(this, &IndicatorEntryWidget::onActiveChanged));
1034 }
1035
1036 IndicatorEntryWidget::~IndicatorEntryWidget()
1037@@ -166,7 +168,7 @@
1038 img.fill(Qt::transparent);
1039 QPainter painter(&img);
1040 painter.initFrom(this);
1041- if (m_entry->active()) {
1042+ if (m_activatedByThisEntry) {
1043 paintActiveBackground(&img);
1044 }
1045 if (m_hasIcon) {
1046@@ -200,6 +202,13 @@
1047 }
1048 }
1049
1050+void IndicatorEntryWidget::onActiveChanged(bool active)
1051+{
1052+ if (!active) {
1053+ m_activatedByThisEntry = false;
1054+ }
1055+}
1056+
1057 PangoLayout* IndicatorEntryWidget::createPangoLayout()
1058 {
1059 // Parse
1060@@ -266,7 +275,7 @@
1061 gtk_style_context_add_class(styleContext, GTK_STYLE_CLASS_MENUBAR);
1062 gtk_style_context_add_class(styleContext, GTK_STYLE_CLASS_MENUITEM);
1063
1064- if (m_entry->active()) {
1065+ if (m_activatedByThisEntry) {
1066 gtk_style_context_set_state(styleContext, GTK_STATE_FLAG_PRELIGHT);
1067 }
1068
1069@@ -332,7 +341,7 @@
1070
1071 void IndicatorEntryWidget::showMenu(Qt::MouseButton qtButton)
1072 {
1073- if (m_entry->active()) {
1074+ if (m_activatedByThisEntry) {
1075 return;
1076 }
1077 int nuxButton = qtButton == Qt::NoButton ? 0 : 1;
1078@@ -341,6 +350,7 @@
1079 time(NULL),
1080 nuxButton
1081 );
1082+ m_activatedByThisEntry = true;
1083 }
1084
1085 void IndicatorEntryWidget::setPadding(int padding)
1086
1087=== modified file 'libunity-2d-private/src/indicatorentrywidget.h'
1088--- libunity-2d-private/src/indicatorentrywidget.h 2011-08-22 09:17:03 +0000
1089+++ libunity-2d-private/src/indicatorentrywidget.h 2012-03-15 09:01:33 +0000
1090@@ -78,8 +78,10 @@
1091 int m_padding;
1092 bool m_hasIcon;
1093 bool m_hasLabel;
1094+ bool m_activatedByThisEntry;
1095 struct _GtkWidgetPath* m_gtkWidgetPath;
1096 void updatePix();
1097+ void onActiveChanged(bool active);
1098 QPixmap decodeIcon();
1099 void paintActiveBackground(QImage*);
1100
1101
1102=== modified file 'libunity-2d-private/src/launcherdevice.cpp'
1103--- libunity-2d-private/src/launcherdevice.cpp 2012-01-13 17:29:37 +0000
1104+++ libunity-2d-private/src/launcherdevice.cpp 2012-03-15 09:01:33 +0000
1105@@ -59,6 +59,12 @@
1106 return false;
1107 }
1108
1109+int
1110+LauncherDevice::activeScreen() const
1111+{
1112+ return -1;
1113+}
1114+
1115 bool
1116 LauncherDevice::running() const
1117 {
1118
1119=== modified file 'libunity-2d-private/src/launcherdevice.h'
1120--- libunity-2d-private/src/launcherdevice.h 2011-08-02 19:01:35 +0000
1121+++ libunity-2d-private/src/launcherdevice.h 2012-03-15 09:01:33 +0000
1122@@ -39,6 +39,7 @@
1123
1124 /* getters */
1125 virtual bool active() const;
1126+ virtual int activeScreen() const;
1127 virtual bool running() const;
1128 virtual int windowCount() const;
1129 virtual bool urgent() const;
1130
1131=== modified file 'libunity-2d-private/src/launcheritem.cpp'
1132--- libunity-2d-private/src/launcheritem.cpp 2012-03-01 14:26:38 +0000
1133+++ libunity-2d-private/src/launcheritem.cpp 2012-03-15 09:01:33 +0000
1134@@ -86,16 +86,10 @@
1135 /* Default to doing nothing. */
1136 }
1137
1138-bool
1139-LauncherItem::belongsToDifferentWorkspace()
1140-{
1141- return false;
1142-}
1143-
1144-bool
1145-LauncherItem::belongsToDifferentScreen(int)
1146-{
1147- return false;
1148+int
1149+LauncherItem::windowsOnCurrentWorkspaceScreen(int screen)
1150+{
1151+ return 0;
1152 }
1153
1154 bool
1155
1156=== modified file 'libunity-2d-private/src/launcheritem.h'
1157--- libunity-2d-private/src/launcheritem.h 2012-03-01 14:26:38 +0000
1158+++ libunity-2d-private/src/launcheritem.h 2012-03-15 09:01:33 +0000
1159@@ -33,6 +33,7 @@
1160 Q_OBJECT
1161
1162 Q_PROPERTY(bool active READ active NOTIFY activeChanged)
1163+ Q_PROPERTY(int activeScreen READ activeScreen NOTIFY activeScreenChanged)
1164 Q_PROPERTY(bool running READ running NOTIFY runningChanged)
1165 Q_PROPERTY(int windowCount READ windowCount NOTIFY windowCountChanged)
1166 Q_PROPERTY(bool urgent READ urgent NOTIFY urgentChanged)
1167@@ -56,6 +57,7 @@
1168
1169 /* getters */
1170 virtual bool active() const = 0;
1171+ virtual int activeScreen() const = 0;
1172 virtual bool running() const = 0;
1173 virtual int windowCount() const = 0;
1174 virtual bool urgent() const = 0;
1175@@ -79,14 +81,14 @@
1176 Q_INVOKABLE virtual void activate() = 0;
1177 Q_INVOKABLE virtual void createMenuActions() = 0;
1178 Q_INVOKABLE virtual void launchNewInstance();
1179- Q_INVOKABLE virtual bool belongsToDifferentWorkspace();
1180- Q_INVOKABLE virtual bool belongsToDifferentScreen(int screen);
1181+ Q_INVOKABLE virtual int windowsOnCurrentWorkspaceScreen(int screen);
1182
1183 protected:
1184 LauncherContextualMenu* m_menu;
1185
1186 Q_SIGNALS:
1187 void activeChanged(bool);
1188+ void activeScreenChanged(int);
1189 void runningChanged(bool);
1190 void windowCountChanged(int);
1191 void urgentChanged(bool);
1192
1193=== modified file 'libunity-2d-private/src/listaggregatormodel.cpp'
1194--- libunity-2d-private/src/listaggregatormodel.cpp 2011-07-29 13:49:34 +0000
1195+++ libunity-2d-private/src/listaggregatormodel.cpp 2012-03-15 09:01:33 +0000
1196@@ -130,6 +130,27 @@
1197 Q_ARG(int, to - offset));
1198 }
1199
1200+void
1201+ListAggregatorModel::moveFinished(int from, int to)
1202+{
1203+ QAbstractItemModel* model = modelAtIndex(from);
1204+ if (modelAtIndex(to) != model) {
1205+ UQ_WARNING << "cannot move an item from one model to another";
1206+ return;
1207+ }
1208+
1209+ if (qobject_cast<QSortFilterProxyModel*>(model) != NULL) {
1210+ UQ_WARNING << "cannot move the items of a QSortFilterProxyModel";
1211+ return;
1212+ }
1213+
1214+ int offset = computeOffset(model);
1215+ // "moveFinished" is not a member of QAbstractItemModel, cannot be invoked directly
1216+ QMetaObject::invokeMethod(model, "moveFinished",
1217+ Q_ARG(int, from - offset),
1218+ Q_ARG(int, to - offset));
1219+}
1220+
1221 int
1222 ListAggregatorModel::computeOffset(QAbstractItemModel* model) const
1223 {
1224
1225=== modified file 'libunity-2d-private/src/listaggregatormodel.h'
1226--- libunity-2d-private/src/listaggregatormodel.h 2011-07-29 13:49:34 +0000
1227+++ libunity-2d-private/src/listaggregatormodel.h 2012-03-15 09:01:33 +0000
1228@@ -62,6 +62,8 @@
1229 The item must remain in the same model. */
1230 void move(int from, int to);
1231
1232+ void moveFinished(int from, int to);
1233+
1234 protected:
1235 QList<QAbstractItemModel*> m_models;
1236
1237
1238=== modified file 'libunity-2d-private/src/panelpalettemanager.cpp'
1239--- libunity-2d-private/src/panelpalettemanager.cpp 2012-03-13 18:54:14 +0000
1240+++ libunity-2d-private/src/panelpalettemanager.cpp 2012-03-15 09:01:33 +0000
1241@@ -42,10 +42,12 @@
1242 }
1243
1244 PanelPaletteManager::PanelPaletteManager(Unity2dPanel* panel)
1245- : m_panel(panel)
1246+ : QObject(panel), m_panel(panel)
1247 {
1248 connect(DashClient::instance(), SIGNAL(activeChanged(bool)), this, SLOT(updatePalette()));
1249 connect(HUDClient::instance(), SIGNAL(activeChanged(bool)), this, SLOT(updatePalette()));
1250+ connect(DashClient::instance(), SIGNAL(screenChanged(int)), this, SLOT(updatePalette()));
1251+ connect(HUDClient::instance(), SIGNAL(screenChanged(int)), this, SLOT(updatePalette()));
1252
1253 m_gConnector.connect(gtk_settings_get_default(), "notify::gtk-theme-name", G_CALLBACK(onThemeChanged), this);
1254 updatePalette();
1255@@ -74,7 +76,7 @@
1256 gtk_style_context_get(context, GTK_STATE_FLAG_NORMAL, NULL);
1257
1258 QPalette pal;
1259- if (DashClient::instance()->active() || HUDClient::instance()->active()) {
1260+ if (DashClient::instance()->activeInScreen(m_panel->screen()) || HUDClient::instance()->activeInScreen(m_panel->screen())) {
1261 pal.setBrush(QPalette::Window, QColor(0, 0, 0, 168));
1262 } else {
1263 pal.setBrush(QPalette::Window, generateBackgroundBrush());
1264
1265=== modified file 'libunity-2d-private/src/screeninfo.cpp'
1266--- libunity-2d-private/src/screeninfo.cpp 2012-02-01 16:28:13 +0000
1267+++ libunity-2d-private/src/screeninfo.cpp 2012-03-15 09:01:33 +0000
1268@@ -4,6 +4,7 @@
1269
1270 #include <QApplication>
1271 #include <QDesktopWidget>
1272+#include <QVariant>
1273 #include <QX11Info>
1274
1275 ScreenInfo::ScreenInfo(QObject *parent) :
1276@@ -16,6 +17,7 @@
1277 SLOT(updateGeometry(int)));
1278 connect(QApplication::desktop(), SIGNAL(workAreaResized(int)),
1279 SLOT(updateAvailableGeometry(int)));
1280+ connect(&launcher2dConfiguration(), SIGNAL(onlyOneLauncherChanged(bool)), SLOT(updatePanelsFreeGeometry()));
1281 }
1282
1283 ScreenInfo::ScreenInfo(int screen, QObject *parent) :
1284@@ -28,6 +30,7 @@
1285 SLOT(updateGeometry(int)));
1286 connect(QApplication::desktop(), SIGNAL(workAreaResized(int)),
1287 SLOT(updateAvailableGeometry(int)));
1288+ connect(&launcher2dConfiguration(), SIGNAL(onlyOneLauncherChanged(bool)), SLOT(updatePanelsFreeGeometry()));
1289 }
1290
1291 ScreenInfo::ScreenInfo(QWidget *widget, QObject *parent) :
1292@@ -41,6 +44,7 @@
1293 SLOT(updateGeometry(int)));
1294 connect(QApplication::desktop(), SIGNAL(workAreaResized(int)),
1295 SLOT(updateAvailableGeometry(int)));
1296+ connect(&launcher2dConfiguration(), SIGNAL(onlyOneLauncherChanged(bool)), SLOT(updatePanelsFreeGeometry()));
1297 }
1298
1299 ScreenInfo::ScreenInfo(Corner corner, QObject *parent) :
1300@@ -53,6 +57,7 @@
1301 SLOT(updateGeometry(int)));
1302 connect(QApplication::desktop(), SIGNAL(workAreaResized(int)),
1303 SLOT(updateAvailableGeometry(int)));
1304+ connect(&launcher2dConfiguration(), SIGNAL(onlyOneLauncherChanged(bool)), SLOT(updatePanelsFreeGeometry()));
1305 }
1306
1307 ScreenInfo::~ScreenInfo()
1308@@ -74,14 +79,16 @@
1309 QRect screenRect = QApplication::desktop()->screenGeometry(m_screen);
1310 QRect availableRect = QApplication::desktop()->availableGeometry(m_screen);
1311
1312+ const bool accountForLauncher = !launcher2dConfiguration().property("onlyOneLauncher").toBool() || m_screen == 0;
1313+
1314 QRect availableGeometry(
1315- LauncherClient::MaximumWidth,
1316+ screenRect.left() + (accountForLauncher ? LauncherClient::MaximumWidth : 0),
1317 availableRect.top(),
1318- screenRect.width() - LauncherClient::MaximumWidth,
1319+ screenRect.width() - (accountForLauncher ? LauncherClient::MaximumWidth : 0),
1320 availableRect.height()
1321 );
1322 if (QApplication::isRightToLeft()) {
1323- availableGeometry.moveLeft(0);
1324+ availableGeometry.moveLeft(screenRect.left());
1325 }
1326 return availableGeometry;
1327 }
1328@@ -113,6 +120,13 @@
1329 }
1330 }
1331
1332+void ScreenInfo::updatePanelsFreeGeometry()
1333+{
1334+ if (m_screen != 0) {
1335+ Q_EMIT panelsFreeGeometryChanged(panelsFreeGeometry());
1336+ }
1337+}
1338+
1339 void ScreenInfo::updateScreen()
1340 {
1341 int screen;
1342@@ -126,7 +140,7 @@
1343 }
1344
1345 int
1346-ScreenInfo::cornerScreen(Corner corner)
1347+ScreenInfo::cornerScreen(Corner corner) const
1348 {
1349 QDesktopWidget* desktop = QApplication::desktop();
1350 switch(corner) {
1351
1352=== modified file 'libunity-2d-private/src/screeninfo.h'
1353--- libunity-2d-private/src/screeninfo.h 2012-02-01 15:01:21 +0000
1354+++ libunity-2d-private/src/screeninfo.h 2012-03-15 09:01:33 +0000
1355@@ -60,10 +60,11 @@
1356 private Q_SLOTS:
1357 void updateGeometry(int screen);
1358 void updateAvailableGeometry(int screen);
1359+ void updatePanelsFreeGeometry();
1360
1361 private:
1362 void updateScreen();
1363- int cornerScreen(Corner corner);
1364+ int cornerScreen(Corner corner) const;
1365 int m_screen;
1366 QWidget* m_widget;
1367 Corner m_corner;
1368
1369=== modified file 'libunity-2d-private/src/strutmanager.cpp'
1370--- libunity-2d-private/src/strutmanager.cpp 2012-02-09 09:27:03 +0000
1371+++ libunity-2d-private/src/strutmanager.cpp 2012-03-15 09:01:33 +0000
1372@@ -181,17 +181,22 @@
1373 switch (m_edge) {
1374 case Unity2dPanel::LeftEdge:
1375 if (QApplication::isLeftToRight()) {
1376- struts[0] = realWidth();
1377+ struts[0] = screen.x() + realWidth();
1378 struts[4] = available.top();
1379 struts[5] = available.y() + available.height();
1380 } else {
1381- struts[1] = realWidth();
1382+ // Find the right-most X
1383+ int rightMostX = 0;
1384+ for (int i = 0; i < desktop->screenCount(); ++i) {
1385+ rightMostX = qMax(rightMostX, desktop->screenGeometry(i).right());
1386+ }
1387+ struts[1] = (rightMostX - screen.right()) + realWidth();
1388 struts[6] = available.top();
1389 struts[7] = available.y() + available.height();
1390 }
1391 break;
1392 case Unity2dPanel::TopEdge:
1393- struts[2] = realHeight();
1394+ struts[2] = screen.y() + realHeight();
1395 struts[8] = screen.left();
1396 struts[9] = screen.x() + screen.width();
1397 break;
1398
1399=== modified file 'libunity-2d-private/src/trash.cpp'
1400--- libunity-2d-private/src/trash.cpp 2011-11-24 08:45:18 +0000
1401+++ libunity-2d-private/src/trash.cpp 2012-03-15 09:01:33 +0000
1402@@ -62,6 +62,12 @@
1403 return false;
1404 }
1405
1406+int
1407+Trash::activeScreen() const
1408+{
1409+ return -1;
1410+}
1411+
1412 bool
1413 Trash::isTrashWindow(WnckWindow* window) const
1414 {
1415
1416=== modified file 'libunity-2d-private/src/trash.h'
1417--- libunity-2d-private/src/trash.h 2011-09-03 20:10:01 +0000
1418+++ libunity-2d-private/src/trash.h 2012-03-15 09:01:33 +0000
1419@@ -45,6 +45,7 @@
1420
1421 /* getters */
1422 virtual bool active() const;
1423+ virtual int activeScreen() const;
1424 virtual bool running() const;
1425 virtual int windowCount() const;
1426 virtual bool urgent() const;
1427
1428=== modified file 'libunity-2d-private/src/unity2ddeclarativeview.cpp'
1429--- libunity-2d-private/src/unity2ddeclarativeview.cpp 2012-03-12 11:56:39 +0000
1430+++ libunity-2d-private/src/unity2ddeclarativeview.cpp 2012-03-15 09:01:33 +0000
1431@@ -20,9 +20,11 @@
1432 #include <config.h>
1433
1434 #include "screeninfo.h"
1435-#include "gobjectcallback.h"
1436
1437+#include <QApplication>
1438 #include <QDebug>
1439+#include <QDeclarativeEngine>
1440+#include <QDeclarativeItem>
1441 #include <QGLWidget>
1442 #include <QVariant>
1443 #include <QX11Info>
1444@@ -32,39 +34,88 @@
1445 #include <X11/Xlib.h>
1446 #include <X11/Xatom.h>
1447
1448-#include "bamf-window.h"
1449-#include "bamf-matcher.h"
1450-
1451-// libwnck
1452-extern "C" {
1453-#include <libwnck/libwnck.h>
1454-}
1455-
1456-GOBJECT_CALLBACK1(activeWorkspaceChangedCB, "onActiveWorkspaceChanged");
1457-
1458 Unity2DDeclarativeView::Unity2DDeclarativeView(QWidget *parent) :
1459- QDeclarativeView(parent),
1460+ QGraphicsView(parent),
1461 m_screenInfo(NULL),
1462 m_useOpenGL(false),
1463 m_transparentBackground(false),
1464- m_last_focused_window(None)
1465+ m_rootItem(NULL)
1466 {
1467+ setScene(&m_scene);
1468+
1469+ setOptimizationFlags(QGraphicsView::DontSavePainterState);
1470+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1471+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1472+ setFrameStyle(NoFrame);
1473+
1474+ setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
1475+ scene()->setItemIndexMethod(QGraphicsScene::NoIndex);
1476+ viewport()->setFocusPolicy(Qt::NoFocus);
1477+ setFocusPolicy(Qt::StrongFocus);
1478+
1479+ scene()->setStickyFocus(true);
1480+
1481 if (!QFileInfo(UNITY_2D_SCHEMA_FILE).exists()) {
1482 m_useOpenGL = false;
1483 } else {
1484 m_useOpenGL = unity2dConfiguration().property("useOpengl").toBool();
1485 }
1486
1487- WnckScreen* screen = wnck_screen_get_default();
1488- g_signal_connect(G_OBJECT(screen), "active_workspace_changed", G_CALLBACK(activeWorkspaceChangedCB), this);
1489-
1490 setupViewport();
1491 }
1492
1493 Unity2DDeclarativeView::~Unity2DDeclarativeView()
1494 {
1495- WnckScreen* screen = wnck_screen_get_default();
1496- g_signal_handlers_disconnect_by_func(G_OBJECT(screen), gpointer(activeWorkspaceChangedCB), this);
1497+}
1498+
1499+QDeclarativeEngine* Unity2DDeclarativeView::engine()
1500+{
1501+ static QDeclarativeEngine* engine = new QDeclarativeEngine();
1502+ return engine;
1503+}
1504+
1505+QDeclarativeContext* Unity2DDeclarativeView::rootContext() const
1506+{
1507+ return engine()->rootContext();
1508+}
1509+
1510+QDeclarativeItem* Unity2DDeclarativeView::rootObject() const
1511+{
1512+ return m_rootItem;
1513+}
1514+
1515+void Unity2DDeclarativeView::forceActivateWindow()
1516+{
1517+ forceActivateWindow(effectiveWinId(), this);
1518+}
1519+
1520+void Unity2DDeclarativeView::setSource(const QUrl &source, const QMap<const char*, QVariant> &rootObjectProperties)
1521+{
1522+ QDeclarativeComponent* component = new QDeclarativeComponent(engine(), source, this);
1523+ QObject *instance = component->beginCreate(rootContext());
1524+ if (component->isError()) {
1525+ qDebug() << component->errors();
1526+ }
1527+ QMap<const char*, QVariant>::const_iterator it = rootObjectProperties.begin();
1528+ QMap<const char*, QVariant>::const_iterator itEnd = rootObjectProperties.end();
1529+ for ( ; it != itEnd; ++it) {
1530+ instance->setProperty(it.key(), it.value());
1531+ }
1532+ component->completeCreate();
1533+ m_rootItem = qobject_cast<QDeclarativeItem *>(instance);
1534+ connect(m_rootItem, SIGNAL(widthChanged()), SLOT(resizeToRootObject()));
1535+ connect(m_rootItem, SIGNAL(heightChanged()), SLOT(resizeToRootObject()));
1536+ resizeToRootObject();
1537+ m_scene.addItem(m_rootItem);
1538+ m_source = source;
1539+}
1540+
1541+void Unity2DDeclarativeView::resizeToRootObject()
1542+{
1543+ QSize size(m_rootItem->width(), m_rootItem->height());
1544+ resize(size);
1545+ setSceneRect(QRectF(0, 0, size.width(), size.height()));
1546+ Q_EMIT sceneResized(size);
1547 }
1548
1549 bool Unity2DDeclarativeView::useOpenGL() const
1550@@ -89,6 +140,11 @@
1551 return m_transparentBackground;
1552 }
1553
1554+QUrl Unity2DDeclarativeView::source() const
1555+{
1556+ return m_source;
1557+}
1558+
1559 void Unity2DDeclarativeView::setTransparentBackground(bool transparentBackground)
1560 {
1561 if (transparentBackground == m_transparentBackground) {
1562@@ -103,7 +159,12 @@
1563
1564 QPoint Unity2DDeclarativeView::globalPosition() const
1565 {
1566- return mapToGlobal(QPoint(0,0));
1567+ // FIXME This used to be mapToGlobal(QPoint(0,0)) that is the correct
1568+ // thing for all kind of widgets, but seems to fail sometimes if we
1569+ // call it just after a moveEvent, which is bad
1570+ // Since all our Unity2DDeclarativeView are toplevel windows we
1571+ // are workarounding it by just returning pos()
1572+ return pos();
1573 }
1574
1575 void Unity2DDeclarativeView::setupViewport()
1576@@ -163,74 +224,27 @@
1577
1578 void Unity2DDeclarativeView::showEvent(QShowEvent* event)
1579 {
1580- QDeclarativeView::showEvent(event);
1581+ QGraphicsView::showEvent(event);
1582 Q_EMIT visibleChanged(true);
1583 }
1584
1585 void Unity2DDeclarativeView::hideEvent(QHideEvent* event)
1586 {
1587- QDeclarativeView::hideEvent(event);
1588+ QGraphicsView::hideEvent(event);
1589 Q_EMIT visibleChanged(false);
1590 }
1591
1592-/* Obtaining & Discarding Keyboard Focus for Window on Demand
1593- *
1594- * In the X world, activating a window means to give it the input (keyboard)
1595- * focus. When a new window opens, X usually makes it active immediately.
1596- * Clicking on a window makes it active too.
1597- *
1598- * Qt does not have the capability to explicitly ask the window manager to
1599- * make an existing window active - setFocus() only forwards input focus to
1600- * whatever QWidget you specify.
1601- *
1602- * De-Activating a window is not possible with X (and hence with Qt). So
1603- * we work-around this by remembering which application is active prior to
1604- * stealing focus, and then Re-Activating it when we're finished. This is
1605- * not guaranteed to succeed, as previous window may have closed.
1606- *
1607- * The following methods deal with these tasks. Note that when the window
1608- * has been activated (deactivated), Qt will realise it has obtained (lost)
1609- * focus and act appropriately.
1610- */
1611-
1612-/* Ask Window Manager to activate this window and hence get keyboard focus */
1613-void Unity2DDeclarativeView::forceActivateWindow()
1614-{
1615- // Save reference to window with current keyboard focus
1616- if( m_last_focused_window == None ){
1617- saveActiveWindow();
1618- }
1619-
1620- // Show this window by giving it keyboard focus
1621- forceActivateThisWindow(this->effectiveWinId());
1622-}
1623-
1624-/* Ask Window Manager to deactivate this window - not guaranteed to succeed. */
1625-void Unity2DDeclarativeView::forceDeactivateWindow()
1626-{
1627- if( m_last_focused_window == None ){
1628- UQ_WARNING << "No previously focused window found, use mouse to select window.";
1629- return;
1630- }
1631-
1632- // What if previously focused window closed while we we had focus? Check if window
1633- // exists by seeing if it has attributes.
1634- int status;
1635- XWindowAttributes attributes;
1636- status = XGetWindowAttributes(QX11Info::display(), m_last_focused_window, &attributes);
1637- if ( status == BadWindow ){
1638- UQ_WARNING << "Previously focused window has gone, use mouse to select window.";
1639- return;
1640- }
1641-
1642- // Show this window by giving it keyboard focus
1643- forceActivateThisWindow(m_last_focused_window);
1644-
1645- m_last_focused_window = None;
1646- Q_EMIT lastFocusedWindowChanged(m_last_focused_window);
1647-}
1648-
1649-void Unity2DDeclarativeView::forceActivateThisWindow(WId window)
1650+void Unity2DDeclarativeView::keyPressEvent(QKeyEvent* event)
1651+{
1652+ QApplication::sendEvent(scene(), event);
1653+}
1654+
1655+void Unity2DDeclarativeView::keyReleaseEvent(QKeyEvent* event)
1656+{
1657+ QApplication::sendEvent(scene(), event);
1658+}
1659+
1660+void Unity2DDeclarativeView::forceActivateWindow(WId window, QWidget *w)
1661 {
1662 /* Workaround focus stealing prevention implemented by some window
1663 managers such as Compiz. This is the exact same code you will find in
1664@@ -262,35 +276,8 @@
1665 XFlush(display);
1666
1667 /* Use Qt's setFocus mechanism as a safety guard in case the above failed */
1668- setFocus();
1669-}
1670-
1671-/* Save WId of window with keyboard focus to m_last_focused_window */
1672-void Unity2DDeclarativeView::saveActiveWindow()
1673-{
1674- /* Using Bamf here, 'cause XGetFocusInputFocus returned a XId
1675- different by 1, which then could not be used with Bamf to
1676- get the application. The change does not result in any functional
1677- differences, though. */
1678- WId active_window = None;
1679- BamfWindow* bamf_active_window = BamfMatcher::get_default().active_window();
1680-
1681- /* Bamf can return a null active window - example case is just after
1682- login when no application has been yet been started. */
1683- if (bamf_active_window != NULL) {
1684- active_window = bamf_active_window->xid();
1685- }
1686-
1687- if (active_window != this->effectiveWinId() && active_window != m_last_focused_window) {
1688- m_last_focused_window = active_window;
1689- Q_EMIT lastFocusedWindowChanged(m_last_focused_window);
1690- }
1691-}
1692-
1693-void Unity2DDeclarativeView::onActiveWorkspaceChanged()
1694-{
1695- m_last_focused_window = None;
1696- Q_EMIT activeWorkspaceChanged();
1697+ if (w != NULL)
1698+ w->setFocus();
1699 }
1700
1701 ScreenInfo*
1702@@ -299,10 +286,4 @@
1703 return m_screenInfo;
1704 }
1705
1706-unsigned int
1707-Unity2DDeclarativeView::lastFocusedWindow() const
1708-{
1709- return m_last_focused_window;
1710-}
1711-
1712 #include <unity2ddeclarativeview.moc>
1713
1714=== modified file 'libunity-2d-private/src/unity2ddeclarativeview.h'
1715--- libunity-2d-private/src/unity2ddeclarativeview.h 2012-02-16 15:00:08 +0000
1716+++ libunity-2d-private/src/unity2ddeclarativeview.h 2012-03-15 09:01:33 +0000
1717@@ -17,11 +17,20 @@
1718 #ifndef UNITY2DDECLARATIVEVIEW_H
1719 #define UNITY2DDECLARATIVEVIEW_H
1720
1721-#include <QDeclarativeView>
1722+#include <QGraphicsView>
1723+
1724+#include <QMap>
1725+#include <QUrl>
1726+#include <QVariant>
1727
1728 class ScreenInfo;
1729
1730-class Unity2DDeclarativeView : public QDeclarativeView
1731+class QDeclarativeContext;
1732+class QDeclarativeEngine;
1733+class QDeclarativeItem;
1734+class QGraphicsObject;
1735+
1736+class Unity2DDeclarativeView : public QGraphicsView
1737 {
1738 Q_OBJECT
1739
1740@@ -30,7 +39,6 @@
1741 Q_PROPERTY(QPoint globalPosition READ globalPosition NOTIFY globalPositionChanged)
1742 Q_PROPERTY(ScreenInfo* screen READ screen NOTIFY screenChanged)
1743 Q_PROPERTY(bool visible READ isVisible NOTIFY visibleChanged)
1744- Q_PROPERTY(unsigned int lastFocusedWindow READ lastFocusedWindow NOTIFY lastFocusedWindowChanged)
1745
1746 public:
1747 Unity2DDeclarativeView(QWidget *parent = 0);
1748@@ -39,13 +47,20 @@
1749 // getters
1750 bool useOpenGL() const;
1751 bool transparentBackground() const;
1752+ QUrl source() const;
1753 QPoint globalPosition() const;
1754 ScreenInfo* screen() const;
1755- unsigned int lastFocusedWindow() const;
1756
1757 // setters
1758 void setUseOpenGL(bool);
1759 void setTransparentBackground(bool);
1760+ void setSource(const QUrl& source, const QMap<const char*, QVariant> &rootObjectProperties = QMap<const char*, QVariant>());
1761+
1762+ static QDeclarativeEngine *engine();
1763+ QDeclarativeContext* rootContext() const;
1764+ QDeclarativeItem* rootObject() const;
1765+
1766+ Q_INVOKABLE virtual void forceActivateWindow();
1767
1768 Q_SIGNALS:
1769 void useOpenGLChanged(bool);
1770@@ -53,31 +68,30 @@
1771 void globalPositionChanged(QPoint);
1772 void screenChanged(ScreenInfo*);
1773 void visibleChanged(bool);
1774- void activeWorkspaceChanged();
1775- void lastFocusedWindowChanged(unsigned int);
1776+ void sceneResized(QSize size);
1777
1778 protected:
1779 void setupViewport();
1780 virtual void moveEvent(QMoveEvent* event);
1781 virtual void showEvent(QShowEvent *event);
1782 virtual void hideEvent(QHideEvent* event);
1783+ virtual void keyPressEvent(QKeyEvent* event);
1784+ virtual void keyReleaseEvent(QKeyEvent* event);
1785+
1786+ static void forceActivateWindow(WId window, QWidget *w = NULL);
1787
1788 ScreenInfo* m_screenInfo;
1789
1790-protected Q_SLOTS:
1791- void forceActivateWindow();
1792- void forceDeactivateWindow();
1793-
1794 private Q_SLOTS:
1795- void onActiveWorkspaceChanged();
1796+ void resizeToRootObject();
1797
1798 private:
1799- void saveActiveWindow();
1800- void forceActivateThisWindow(WId);
1801-
1802 bool m_useOpenGL;
1803 bool m_transparentBackground;
1804- WId m_last_focused_window;
1805+ QUrl m_source;
1806+
1807+ QGraphicsScene m_scene;
1808+ QDeclarativeItem* m_rootItem;
1809 };
1810
1811 Q_DECLARE_METATYPE(Unity2DDeclarativeView*)
1812
1813=== modified file 'libunity-2d-private/src/unity2dpanel.cpp'
1814--- libunity-2d-private/src/unity2dpanel.cpp 2012-03-12 11:21:15 +0000
1815+++ libunity-2d-private/src/unity2dpanel.cpp 2012-03-15 09:01:33 +0000
1816@@ -45,8 +45,6 @@
1817 Unity2dPanel::Edge m_edge;
1818 mutable IndicatorsManager* m_indicatorsManager;
1819 QHBoxLayout* m_layout;
1820- int m_delta;
1821- bool m_manualSliding;
1822 StrutManager m_strutManager;
1823 ScreenInfo* m_screenInfo;
1824
1825@@ -60,15 +58,12 @@
1826 case Unity2dPanel::LeftEdge:
1827 if (QApplication::isLeftToRight()) {
1828 rect = QRect(screen.left(), available.top(), q->width(), available.height());
1829- rect.moveLeft(m_delta);
1830 } else {
1831 rect = QRect(screen.right() - q->width(), available.top(), q->width(), available.height());
1832- rect.moveRight(screen.right() - m_delta);
1833 }
1834 break;
1835 case Unity2dPanel::TopEdge:
1836 rect = QRect(screen.left(), screen.top(), screen.width(), q->height());
1837- rect.moveTop(m_delta);
1838 break;
1839 }
1840
1841@@ -105,8 +100,6 @@
1842 d->q = this;
1843 d->m_edge = Unity2dPanel::TopEdge;
1844 d->m_indicatorsManager = 0;
1845- d->m_delta = 0;
1846- d->m_manualSliding = false;
1847 d->m_layout = new QHBoxLayout(this);
1848 d->m_layout->setMargin(0);
1849 d->m_layout->setSpacing(0);
1850@@ -214,39 +207,11 @@
1851 d->m_strutManager.setEnabled(value);
1852 }
1853
1854-int Unity2dPanel::delta() const
1855-{
1856- return d->m_delta;
1857-}
1858-
1859-void Unity2dPanel::setDelta(int delta)
1860-{
1861- /* Clamp delta to be between 0 and minus its size */
1862- int minDelta = -panelSize();
1863- int maxDelta = 0;
1864-
1865- d->m_delta = qMax(qMin(delta, maxDelta), minDelta);
1866- d->updateGeometry();
1867-}
1868-
1869 int Unity2dPanel::panelSize() const
1870 {
1871 return (d->m_edge == Unity2dPanel::TopEdge) ? height() : width();
1872 }
1873
1874-bool Unity2dPanel::manualSliding() const
1875-{
1876- return d->m_manualSliding;
1877-}
1878-
1879-void Unity2dPanel::setManualSliding(bool manualSliding)
1880-{
1881- if (d->m_manualSliding != manualSliding) {
1882- d->m_manualSliding = manualSliding;
1883- Q_EMIT manualSlidingChanged(d->m_manualSliding);
1884- }
1885-}
1886-
1887 QString Unity2dPanel::id() const
1888 {
1889 int screen = QApplication::desktop()->screenNumber(this);
1890
1891=== modified file 'libunity-2d-private/src/unity2dpanel.h'
1892--- libunity-2d-private/src/unity2dpanel.h 2012-03-07 14:34:03 +0000
1893+++ libunity-2d-private/src/unity2dpanel.h 2012-03-15 09:01:33 +0000
1894@@ -35,17 +35,6 @@
1895 class Unity2dPanel : public QWidget
1896 {
1897 Q_OBJECT
1898- /**
1899- * The amount of pixels the panel is moved from its edge. Useful for
1900- * animations.
1901- */
1902- Q_PROPERTY(int delta READ delta WRITE setDelta)
1903- /**
1904- * Whether the delta property is being set by an external client. Setting
1905- * this property to true stops any animation of the delta property triggered
1906- by slideIn() or slideOut().
1907- */
1908- Q_PROPERTY(int manualSliding READ manualSliding WRITE setManualSliding NOTIFY manualSlidingChanged)
1909 Q_PROPERTY(bool useStrut READ useStrut WRITE setUseStrut NOTIFY useStrutChanged)
1910 Q_ENUMS(Edge)
1911
1912@@ -80,18 +69,11 @@
1913 bool useStrut() const;
1914 void setUseStrut(bool);
1915
1916- int delta() const;
1917- void setDelta(int);
1918-
1919 int panelSize() const;
1920
1921- bool manualSliding() const;
1922- void setManualSliding(bool);
1923-
1924 QString id() const;
1925
1926 Q_SIGNALS:
1927- void manualSlidingChanged(bool);
1928 void useStrutChanged(bool);
1929
1930 protected:
1931
1932=== modified file 'libunity-2d-private/src/windowinfo.cpp'
1933--- libunity-2d-private/src/windowinfo.cpp 2012-03-12 17:40:31 +0000
1934+++ libunity-2d-private/src/windowinfo.cpp 2012-03-15 09:01:33 +0000
1935@@ -23,6 +23,11 @@
1936 #include "bamf-window.h"
1937
1938 #include "windowinfo.h"
1939+
1940+#include <QApplication>
1941+#include <QDesktopWidget>
1942+#include <QRect>
1943+
1944 #include <X11/Xlib.h>
1945 #include <QX11Info>
1946
1947@@ -264,6 +269,21 @@
1948 return -1;
1949 }
1950
1951+int WindowInfo::screen() const
1952+{
1953+ if (m_wnckWindow != NULL) {
1954+ // Check the window screen
1955+ int x, y, width, height;
1956+ wnck_window_get_geometry(m_wnckWindow, &x, &y, &width, &height);
1957+
1958+ const QRect windowRect(x, y, width, height);
1959+ const QPoint pos = windowRect.center();
1960+ return QApplication::desktop()->screenNumber(pos);
1961+ }
1962+
1963+ return -1;
1964+}
1965+
1966 void WindowInfo::activate()
1967 {
1968 showWindow(m_wnckWindow);
1969
1970=== modified file 'libunity-2d-private/src/windowinfo.h'
1971--- libunity-2d-private/src/windowinfo.h 2012-03-09 13:19:00 +0000
1972+++ libunity-2d-private/src/windowinfo.h 2012-03-15 09:01:33 +0000
1973@@ -77,6 +77,7 @@
1974 QString icon() const;
1975 QString desktopFile() const;
1976 int workspace() const;
1977+ int screen() const;
1978
1979 /* setters */
1980 void setContentXid(unsigned int contentXid);
1981@@ -89,7 +90,8 @@
1982 enum RoleNames {
1983 RoleWindowInfo,
1984 RoleDesktopFile,
1985- RoleWorkspace
1986+ RoleWorkspace,
1987+ RoleScreen
1988 };
1989
1990 Q_SIGNALS:
1991
1992=== modified file 'libunity-2d-private/src/windowslist.cpp'
1993--- libunity-2d-private/src/windowslist.cpp 2012-01-02 15:31:23 +0000
1994+++ libunity-2d-private/src/windowslist.cpp 2012-03-15 09:01:33 +0000
1995@@ -63,6 +63,8 @@
1996 return QVariant::fromValue(info->desktopFile());
1997 case WindowInfo::RoleWorkspace:
1998 return QVariant::fromValue(info->workspace());
1999+ case WindowInfo::RoleScreen:
2000+ return QVariant::fromValue(info->screen());
2001 default:
2002 UQ_DEBUG << "Requested invalid role (index" << role << ")";
2003 return QVariant();
2004
2005=== modified file 'libunity-2d-private/src/workspaces.cpp'
2006--- libunity-2d-private/src/workspaces.cpp 2011-07-29 13:49:34 +0000
2007+++ libunity-2d-private/src/workspaces.cpp 2012-03-15 09:01:33 +0000
2008@@ -49,6 +49,12 @@
2009 return false;
2010 }
2011
2012+int
2013+Workspaces::activeScreen() const
2014+{
2015+ return -1;
2016+}
2017+
2018 bool
2019 Workspaces::running() const
2020 {
2021
2022=== modified file 'libunity-2d-private/src/workspaces.h'
2023--- libunity-2d-private/src/workspaces.h 2011-07-29 13:49:34 +0000
2024+++ libunity-2d-private/src/workspaces.h 2012-03-15 09:01:33 +0000
2025@@ -38,6 +38,7 @@
2026
2027 /* getters */
2028 virtual bool active() const;
2029+ virtual int activeScreen() const;
2030 virtual bool running() const;
2031 virtual int windowCount() const;
2032 virtual bool urgent() const;
2033
2034=== modified file 'panel/applets/appname/appnameapplet.cpp'
2035--- panel/applets/appname/appnameapplet.cpp 2012-03-06 17:30:05 +0000
2036+++ panel/applets/appname/appnameapplet.cpp 2012-03-15 09:01:33 +0000
2037@@ -253,7 +253,7 @@
2038
2039 void setupWindowHelper()
2040 {
2041- m_windowHelper = new WindowHelper(q);
2042+ m_windowHelper = new WindowHelper(q->panel()->screen(), q);
2043 QObject::connect(m_windowHelper, SIGNAL(stateChanged()),
2044 q, SLOT(updateWidgets()));
2045 QObject::connect(m_windowHelper, SIGNAL(nameChanged()),
2046@@ -316,7 +316,7 @@
2047
2048 bool isMaximized = d->m_windowHelper->isMaximized();
2049 bool isUserVisibleApp = app ? app->user_visible() : false;
2050- bool isOnSameScreen = d->m_windowHelper->isMostlyOnScreen(QApplication::desktop()->screenNumber(this));
2051+ bool isOnSameScreen = d->m_windowHelper->isMostlyOnScreen(panel()->screen());
2052 bool isUnderMouse = rect().contains(mapFromGlobal(QCursor::pos()));
2053 bool isOpened = isOnSameScreen &&
2054 (isUnderMouse
2055@@ -325,8 +325,8 @@
2056 );
2057 bool showMenu = isOpened && !d->m_menuBarWidget->isEmpty() && isUserVisibleApp;
2058 bool dashCanResize = !DashClient::instance()->alwaysFullScreen();
2059- bool dashIsVisible = DashClient::instance()->active();
2060- bool hudIsVisible = HUDClient::instance()->active();
2061+ bool dashIsVisible = DashClient::instance()->activeInScreen(panel()->screen());
2062+ bool hudIsVisible = HUDClient::instance()->activeInScreen(panel()->screen());
2063 bool showWindowButtons = (isOpened && isMaximized) || dashIsVisible || hudIsVisible;
2064 bool showAppLabel = !(isMaximized && showMenu) && isUserVisibleApp && isOnSameScreen;
2065 bool showDesktopLabel = !app;
2066
2067=== modified file 'panel/applets/appname/windowhelper.cpp'
2068--- panel/applets/appname/windowhelper.cpp 2012-03-05 16:38:47 +0000
2069+++ panel/applets/appname/windowhelper.cpp 2012-03-15 09:01:33 +0000
2070@@ -57,16 +57,17 @@
2071 {
2072 WnckWindow* m_window;
2073 GConnector m_connector;
2074+ int m_screen;
2075 };
2076
2077-WindowHelper::WindowHelper(QObject* parent)
2078+WindowHelper::WindowHelper(int screen, QObject* parent)
2079 : QObject(parent)
2080 , d(new WindowHelperPrivate)
2081 {
2082 d->m_window = 0;
2083+ d->m_screen = screen;
2084
2085- WnckScreen* screen = wnck_screen_get_default();
2086- wnck_screen_force_update(screen);
2087+ wnck_screen_force_update(wnck_screen_get_default());
2088
2089 update();
2090
2091@@ -84,6 +85,8 @@
2092
2093 connect(DashClient::instance(), SIGNAL(activeChanged(bool)), SLOT(update()));
2094 connect(HUDClient::instance(), SIGNAL(activeChanged(bool)), SLOT(update()));
2095+ connect(DashClient::instance(), SIGNAL(screenChanged(int)), SLOT(update()));
2096+ connect(HUDClient::instance(), SIGNAL(screenChanged(int)), SLOT(update()));
2097 // FIXME: the queued connection should not be needed, however if it's not used when
2098 // (un)maximizing the dash, the panel will deadlock for some reason.
2099 connect(&dash2dConfiguration(), SIGNAL(fullScreenChanged(bool)), SLOT(update()),
2100@@ -130,7 +133,7 @@
2101
2102 bool WindowHelper::isMaximized() const
2103 {
2104- if (DashClient::instance()->active()) {
2105+ if (DashClient::instance()->activeInScreen(d->m_screen)) {
2106 return dash2dConfiguration().property("fullScreen").toBool();
2107 } else {
2108 if (d->m_window) {
2109@@ -166,9 +169,9 @@
2110
2111 void WindowHelper::close()
2112 {
2113- if (DashClient::instance()->active()) {
2114+ if (DashClient::instance()->activeInScreen(d->m_screen)) {
2115 DashClient::instance()->setActive(false);
2116- } else if (HUDClient::instance()->active()) {
2117+ } else if (HUDClient::instance()->activeInScreen(d->m_screen)) {
2118 HUDClient::instance()->setActive(false);
2119 } else {
2120 guint32 timestamp = QDateTime::currentDateTime().toTime_t();
2121@@ -178,14 +181,14 @@
2122
2123 void WindowHelper::minimize()
2124 {
2125- if (!DashClient::instance()->active()) {
2126+ if (!DashClient::instance()->activeInScreen(d->m_screen)) {
2127 wnck_window_minimize(d->m_window);
2128 }
2129 }
2130
2131 void WindowHelper::maximize()
2132 {
2133- if (DashClient::instance()->active()) {
2134+ if (DashClient::instance()->activeInScreen(d->m_screen)) {
2135 dash2dConfiguration().setProperty("fullScreen", QVariant(true));
2136 } else {
2137 /* This currently cannot happen, because the window buttons are not
2138@@ -197,7 +200,7 @@
2139
2140 void WindowHelper::unmaximize()
2141 {
2142- if (DashClient::instance()->active()) {
2143+ if (DashClient::instance()->activeInScreen(d->m_screen)) {
2144 dash2dConfiguration().setProperty("fullScreen", QVariant(false));
2145 } else {
2146 wnck_window_unmaximize(d->m_window);
2147
2148=== modified file 'panel/applets/appname/windowhelper.h'
2149--- panel/applets/appname/windowhelper.h 2012-02-07 16:48:45 +0000
2150+++ panel/applets/appname/windowhelper.h 2012-03-15 09:01:33 +0000
2151@@ -34,7 +34,7 @@
2152 {
2153 Q_OBJECT
2154 public:
2155- WindowHelper(QObject* parent);
2156+ WindowHelper(int screen, QObject* parent);
2157 ~WindowHelper();
2158
2159 void setXid(uint);
2160
2161=== added file 'shell/DashLoader.qml'
2162--- shell/DashLoader.qml 1970-01-01 00:00:00 +0000
2163+++ shell/DashLoader.qml 2012-03-15 09:01:33 +0000
2164@@ -0,0 +1,36 @@
2165+/*
2166+ * This file is part of unity-2d
2167+ *
2168+ * Copyright 2012 Canonical Ltd.
2169+ *
2170+ * This program is free software; you can redistribute it and/or modify
2171+ * it under the terms of the GNU General Public License as published by
2172+ * the Free Software Foundation; version 3.
2173+ *
2174+ * This program is distributed in the hope that it will be useful,
2175+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2176+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2177+ * GNU General Public License for more details.
2178+ *
2179+ * You should have received a copy of the GNU General Public License
2180+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2181+ */
2182+
2183+import QtQuick 1.1
2184+import "common/utils.js" as Utils
2185+
2186+Loader {
2187+ id: dashLoader
2188+ source: "dash/Dash.qml"
2189+ anchors.top: parent != undefined ? parent.top : undefined
2190+ x: Utils.isLeftToRight() ? launcherLoader.width : (parent != undefined ? parent.width - width - launcherLoader.width : 0)
2191+ onLoaded: item.focus = true
2192+ opacity: item.active ? 1.0 : 0.0
2193+ focus: item.active
2194+
2195+ Binding {
2196+ target: dashLoader.item
2197+ property: "fullscreenWidth"
2198+ value: shell.width - launcherLoader.width
2199+ }
2200+}
2201
2202=== added file 'shell/HudLoader.qml'
2203--- shell/HudLoader.qml 1970-01-01 00:00:00 +0000
2204+++ shell/HudLoader.qml 2012-03-15 09:01:33 +0000
2205@@ -0,0 +1,35 @@
2206+/*
2207+ * This file is part of unity-2d
2208+ *
2209+ * Copyright 2012 Canonical Ltd.
2210+ *
2211+ * This program is free software; you can redistribute it and/or modify
2212+ * it under the terms of the GNU General Public License as published by
2213+ * the Free Software Foundation; version 3.
2214+ *
2215+ * This program is distributed in the hope that it will be useful,
2216+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2217+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2218+ * GNU General Public License for more details.
2219+ *
2220+ * You should have received a copy of the GNU General Public License
2221+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2222+ */
2223+
2224+import QtQuick 1.1
2225+import "common/utils.js" as Utils
2226+
2227+Loader {
2228+ id: hudLoader
2229+ property bool animating: item.animating
2230+ property bool active: item.active
2231+ onActiveChanged: item.active = active
2232+
2233+ source: "hud/Hud.qml"
2234+ anchors.top: parent != undefined ? parent.top : undefined
2235+ x: Utils.isLeftToRight() ? 0 : shell.width - width
2236+ onLoaded: item.focus = true
2237+ visible: item.active
2238+ focus: item.active
2239+ width: Math.min(shell.width, 1061)
2240+}
2241
2242=== modified file 'shell/Shell.qml'
2243--- shell/Shell.qml 2012-03-13 18:54:14 +0000
2244+++ shell/Shell.qml 2012-03-15 09:01:33 +0000
2245@@ -23,6 +23,11 @@
2246
2247 Item {
2248 id: shell
2249+
2250+ property variant declarativeView
2251+ property variant dashLoader
2252+ property variant hudLoader
2253+
2254 /* Space reserved by strutManager is taken off screen.availableGeometry but
2255 we want the shell to take all the available space, including the one we
2256 reserved ourselves via strutManager. */
2257@@ -34,12 +39,32 @@
2258
2259 Accessible.name: "shell"
2260
2261- property alias hudActive: hudLoader.active
2262-
2263 GestureHandler {
2264 id: gestureHandler
2265 }
2266
2267+ onDashLoaderChanged: {
2268+ if (shellManager.dashActive) {
2269+ if (dashLoader == undefined)
2270+ {
2271+ launcherLoader.visibilityController.endForceVisible("dash")
2272+ } else {
2273+ launcherLoader.visibilityController.beginForceVisible("dash")
2274+ }
2275+ }
2276+ }
2277+
2278+ onHudLoaderChanged: {
2279+ if (shellManager.hudActive) {
2280+ if (hudLoader == undefined)
2281+ {
2282+ launcherLoader.visibilityController.endForceHidden("hud")
2283+ } else {
2284+ launcherLoader.visibilityController.beginForceHidden("hud")
2285+ }
2286+ }
2287+ }
2288+
2289 LauncherLoader {
2290 id: launcherLoader
2291 anchors.top: parent.top
2292@@ -72,36 +97,14 @@
2293 }
2294 }
2295
2296- KeyNavigation.right: dashLoader
2297-
2298 Binding {
2299 target: launcherLoader.item
2300 property: "showMenus"
2301- value: !dashLoader.item.active && !hudLoader.item.active
2302+ value: (dashLoader == undefined || !dashLoader.item.active) && (hudLoader == undefined || !hudLoader.item.active)
2303 }
2304
2305 Behavior on x { NumberAnimation { id: launcherLoaderXAnimation; duration: 125 } }
2306
2307- Connections {
2308- target: declarativeView
2309- onDashActiveChanged: {
2310- if (declarativeView.dashActive) {
2311- if (hudLoader.item.active) hudLoader.item.active = false
2312- launcherLoader.visibilityController.beginForceVisible("dash")
2313- } else {
2314- launcherLoader.visibilityController.endForceVisible("dash")
2315- if (dashLoader.status == Loader.Ready) dashLoader.item.deactivateAllLenses()
2316- }
2317- }
2318- onGlobalPositionChanged: {
2319- var x = declarativeView.globalPosition.x + (Utils.isLeftToRight() ? 0 : shell.width)
2320- launcherLoader.item.barrierP1 = Qt.point(x, 0)
2321- launcherLoader.item.barrierP2 = Qt.point(x, declarativeView.screen.geometry.height)
2322- launcherLoader.item.barrierTriggerZoneP1 = Qt.point(x, declarativeView.globalPosition.y)
2323- launcherLoader.item.barrierTriggerZoneP2 = Qt.point(x, declarativeView.globalPosition.y + launcherLoader.height)
2324- }
2325- }
2326-
2327 SpreadMonitor {
2328 id: spread
2329 onShownChanged: if (shown) {
2330@@ -114,46 +117,37 @@
2331 }
2332 }
2333
2334-
2335- Loader {
2336- id: dashLoader
2337- source: "dash/Dash.qml"
2338- anchors.top: parent.top
2339- x: Utils.isLeftToRight() ? launcherLoader.width : shell.width - width - launcherLoader.width
2340- onLoaded: item.focus = true
2341- opacity: item.active ? 1.0 : 0.0
2342- focus: item.active
2343-
2344- Binding {
2345- target: dashLoader.item
2346- property: "fullscreenWidth"
2347- value: shell.width - launcherLoader.width
2348+ Connections {
2349+ target: shellManager
2350+
2351+ onDashActiveChanged: {
2352+ if (shellManager.dashActive) {
2353+ if (hudLoader != undefined && hudLoader.item.active) {
2354+ hudLoader.item.active = false
2355+ }
2356+ if (dashLoader != undefined) {
2357+ launcherLoader.visibilityController.beginForceVisible("dash")
2358+ }
2359+ } else {
2360+ if (dashLoader != undefined) {
2361+ launcherLoader.visibilityController.endForceVisible("dash")
2362+ if (dashLoader.status == Loader.Ready) dashLoader.item.deactivateAllLenses()
2363+ }
2364+ }
2365 }
2366- }
2367-
2368- Loader {
2369- id: hudLoader
2370- property bool animating: item.animating
2371- property bool active: item.active
2372- onActiveChanged: item.active = active
2373-
2374- source: "hud/Hud.qml"
2375- anchors.top: parent.top
2376- x: Utils.isLeftToRight() ? 0 : shell.width - width
2377- onLoaded: item.focus = true
2378- visible: item.active
2379- focus: item.active
2380- width: Math.min(shell.width, 1061)
2381- }
2382-
2383- Connections {
2384- target: hudLoader.item
2385- onActiveChanged: {
2386- if (hudLoader.item.active) {
2387- if (dashLoader.item.active) dashLoader.item.active = false
2388- launcherLoader.visibilityController.beginForceHidden("hud")
2389+
2390+ onHudActiveChanged: {
2391+ if (shellManager.hudActive) {
2392+ if (dashLoader != undefined && dashLoader.item.active) {
2393+ dashLoader.item.active = false
2394+ }
2395+ if (hudLoader != undefined) {
2396+ launcherLoader.visibilityController.beginForceHidden("hud")
2397+ }
2398 } else {
2399- launcherLoader.visibilityController.endForceHidden("hud")
2400+ if (hudLoader != undefined) {
2401+ launcherLoader.visibilityController.endForceHidden("hud")
2402+ }
2403 }
2404 }
2405 }
2406@@ -165,7 +159,7 @@
2407 launcherLoader.item.focusBFB()
2408 }
2409 onFocusChanged: {
2410- if (!declarativeView.focus && hudLoader.item.active) hudLoader.item.active = false
2411+ if (!declarativeView.focus && hudLoader!= undefined && hudLoader.item.active) hudLoader.item.active = false
2412
2413 /* FIXME: The launcher is forceVisible while it has activeFocus. However even though
2414 the documentation says that setting focus=false will make an item lose activeFocus
2415@@ -177,7 +171,16 @@
2416 }
2417 }
2418
2419- Component.onCompleted: declarativeView.show()
2420+ Component.onCompleted: {
2421+ if (declarativeView.screen.screen == 0) {
2422+ var loaderComponent = Qt.createComponent("DashLoader.qml");
2423+ dashLoader = loaderComponent.createObject(shell, {});
2424+
2425+ var loaderComponent = Qt.createComponent("HudLoader.qml");
2426+ hudLoader = loaderComponent.createObject(shell, {});
2427+ }
2428+ declarativeView.show()
2429+ }
2430
2431 Keys.onPressed: {
2432 if (event.key == Qt.Key_Escape || (event.key == Qt.Key_F4 && event.modifiers == Qt.AltModifier )) {
2433@@ -194,31 +197,37 @@
2434 }
2435
2436 InputShapeRectangle {
2437- rectangle: if (desktop.isCompositingManagerRunning) {
2438- Qt.rect(dashLoader.x, dashLoader.y, dashLoader.width, dashLoader.height)
2439- } else {
2440- Qt.rect(dashLoader.x, dashLoader.y, dashLoader.width - 7, dashLoader.height - 9)
2441+ rectangle: {
2442+ if (dashLoader != undefined) {
2443+ if (desktop.isCompositingManagerRunning) {
2444+ return Qt.rect(dashLoader.x, dashLoader.y, dashLoader.width, dashLoader.height)
2445+ } else {
2446+ return Qt.rect(dashLoader.x, dashLoader.y, dashLoader.width - 7, dashLoader.height - 9)
2447+ }
2448+ } else {
2449+ return Qt.rect(0, 0, 0, 0)
2450+ }
2451 }
2452- enabled: dashLoader.status == Loader.Ready && dashLoader.item.active
2453+ enabled: dashLoader != undefined && dashLoader.status == Loader.Ready && dashLoader.item.active
2454 mirrorHorizontally: Utils.isRightToLeft()
2455
2456 InputShapeMask {
2457 id: shape1
2458 source: "shell/common/artwork/desktop_dash_background_no_transparency.png"
2459 color: "red"
2460- position: Qt.point(dashLoader.width - 50, dashLoader.height - 49)
2461- enabled: declarativeView.dashMode == ShellDeclarativeView.DesktopMode
2462+ position: dashLoader != undefined ? Qt.point(dashLoader.width - 50, dashLoader.height - 49) : Qt.point(0, 0)
2463+ enabled: shellManager.dashMode == ShellManager.DesktopMode
2464 }
2465 }
2466
2467 InputShapeRectangle {
2468 id: hudInputShape
2469- enabled: hudLoader.status == Loader.Ready && hudLoader.item.active
2470+ enabled: hudLoader != undefined && hudLoader.status == Loader.Ready && hudLoader.item.active
2471
2472 InputShapeMask {
2473 source: "shell/common/artwork/desktop_dash_background_no_transparency.png"
2474 color: "red"
2475- position: Qt.point(hudLoader.width - 50, hudLoader.height - 49)
2476+ position: hudLoader != undefined ? Qt.point(hudLoader.width - 50, hudLoader.height - 49) : Qt.point(0, 0)
2477 }
2478 }
2479 }
2480@@ -237,13 +246,17 @@
2481 target: hudInputShape
2482 property: "rectangle"
2483 value: {
2484- if (desktop.isCompositingManagerRunning) {
2485- return Qt.rect(hudLoader.x, hudLoader.y, hudLoader.width, hudLoader.height)
2486+ if (hudLoader != undefined) {
2487+ if (desktop.isCompositingManagerRunning) {
2488+ return Qt.rect(hudLoader.x, hudLoader.y, hudLoader.width, hudLoader.height)
2489+ } else {
2490+ return Qt.rect(hudLoader.x, hudLoader.y, hudLoader.width - 7, hudLoader.height - 9)
2491+ }
2492 } else {
2493- return Qt.rect(hudLoader.x, hudLoader.y, hudLoader.width - 7, hudLoader.height - 9)
2494+ return Qt.rect(0, 0, 0, 0)
2495 }
2496 }
2497- when: !hudLoader.animating
2498+ when: hudLoader != undefined && !hudLoader.animating
2499 }
2500
2501 StrutManager {
2502@@ -254,4 +267,23 @@
2503 width: launcherLoader.width
2504 enabled: Utils.clamp(launcher2dConfiguration.hideMode, 0, 2) == 0
2505 }
2506+
2507+ PointerBarrier {
2508+ property int x: declarativeView.globalPosition.x + (Utils.isLeftToRight() ? 0 : shell.width)
2509+
2510+ id: leftBarrier
2511+ triggerDirection: Utils.isLeftToRight() ? PointerBarrier.TriggerFromRight : PointerBarrier.TriggerFromLeft
2512+ triggerZoneEnabled: !launcherLoader.visibilityController.shown
2513+ p1: Qt.point(x, declarativeView.screen.geometry.y)
2514+ p2: Qt.point(x, declarativeView.screen.geometry.y + declarativeView.screen.geometry.height)
2515+ triggerZoneP1: Qt.point(x, declarativeView.globalPosition.y)
2516+ triggerZoneP2: Qt.point(x, declarativeView.globalPosition.y + launcherLoader.height)
2517+ threshold: launcherLoader.launcherInHideMode && launcherLoader.loadLauncher ? launcher2dConfiguration.edgeStopVelocity : -1
2518+ maxVelocityMultiplier: launcher2dConfiguration.edgeResponsiveness
2519+ decayRate: launcher2dConfiguration.edgeDecayrate
2520+ triggerPressure: launcher2dConfiguration.edgeRevealPressure
2521+ breakPressure: launcher2dConfiguration.edgeOvercomePressure
2522+
2523+ onTriggered: launcherLoader.item.barrierTriggered()
2524+ }
2525 }
2526
2527=== modified file 'shell/app/CMakeLists.txt'
2528--- shell/app/CMakeLists.txt 2012-03-05 16:38:47 +0000
2529+++ shell/app/CMakeLists.txt 2012-03-15 09:01:33 +0000
2530@@ -9,6 +9,7 @@
2531 dashdbus.cpp
2532 huddbus.cpp
2533 shelldeclarativeview.cpp
2534+ shellmanager.cpp
2535 )
2536
2537 set(shell_MOC_HDRS
2538@@ -16,6 +17,7 @@
2539 dashdbus.h
2540 huddbus.h
2541 shelldeclarativeview.h
2542+ shellmanager.h
2543 )
2544
2545 qt4_wrap_cpp(shell_MOC_SRCS ${shell_MOC_HDRS})
2546@@ -33,6 +35,8 @@
2547 ${QTGCONF_INCLUDE_DIRS}
2548 ${DCONFQT_INCLUDE_DIRS}
2549 ${GTK_INCLUDE_DIRS}
2550+ ${QTBAMF_INCLUDE_DIRS}
2551+ ${WNCK_INCLUDE_DIRS}
2552 ${libunity-2d-private_SOURCE_DIR}/src
2553 )
2554
2555@@ -44,6 +48,8 @@
2556 ${QTGCONF_LDFLAGS}
2557 ${DCONFQT_LDFLAGS}
2558 ${GTK_LDFLAGS}
2559+ ${WNCK_LDFLAGS}
2560+ ${QTBAMF_LDFLAGS}
2561 ${X11_Xext_LIB}
2562 ${X11_X11_LIB}
2563 unity-2d-private
2564
2565=== modified file 'shell/app/dash.xml'
2566--- shell/app/dash.xml 2012-03-05 16:38:47 +0000
2567+++ shell/app/dash.xml 2012-03-15 09:01:33 +0000
2568@@ -27,6 +27,9 @@
2569 <property name="activeLens" type="s" access="readwrite">
2570 <dox:d>The currently active lens</dox:d>
2571 </property>
2572+ <property name="screen" type="i" access="read">
2573+ <dox:d>The screen with the dash</dox:d>
2574+ </property>
2575 <signal name="activeChanged">
2576 <dox:d>Signals when the active status of the Dash changes</dox:d>
2577 <arg name="active" type="b" direction="out">
2578@@ -45,6 +48,12 @@
2579 <dox:d>The currently active lens</dox:d>
2580 </arg>
2581 </signal>
2582+ <signal name="screenChanged">
2583+ <dox:d>Signals when the screen changes</dox:d>
2584+ <arg name="active" type="i" direction="out">
2585+ <dox:d>The screen with the dash</dox:d>
2586+ </arg>
2587+ </signal>
2588 </interface>
2589 </node>
2590
2591
2592=== modified file 'shell/app/dashdbus.cpp'
2593--- shell/app/dashdbus.cpp 2012-03-05 16:38:47 +0000
2594+++ shell/app/dashdbus.cpp 2012-03-15 09:01:33 +0000
2595@@ -21,19 +21,21 @@
2596 #include "dashadaptor.h"
2597
2598 // Local
2599-#include <shelldeclarativeview.h>
2600+#include <shellmanager.h>
2601
2602 // Qt
2603 #include <QtDBus/QDBusConnection>
2604 #include <QGraphicsObject>
2605
2606-DashDBus::DashDBus(ShellDeclarativeView* view, QObject* parent)
2607+DashDBus::DashDBus(ShellManager* manager, QObject* parent)
2608 : QObject(parent)
2609-, m_view(view)
2610+, m_manager(manager)
2611 {
2612- connect(m_view, SIGNAL(dashActiveChanged(bool)), SIGNAL(activeChanged(bool)));
2613- connect(m_view, SIGNAL(dashAlwaysFullScreenChanged(bool)), SIGNAL(alwaysFullScreenChanged(bool)));
2614- connect(m_view, SIGNAL(activeLensChanged(QString)), SIGNAL(activeLensChanged(QString)));
2615+ connect(m_manager, SIGNAL(dashActiveChanged(bool)), SIGNAL(activeChanged(bool)));
2616+ connect(m_manager, SIGNAL(dashAlwaysFullScreenChanged(bool)), SIGNAL(alwaysFullScreenChanged(bool)));
2617+ connect(m_manager, SIGNAL(dashActiveLensChanged(QString)), SIGNAL(activeLensChanged(QString)));
2618+
2619+ connect(m_manager, SIGNAL(dashScreenChanged(int)), SIGNAL(screenChanged(int)));
2620
2621 new DashAdaptor(this);
2622 }
2623@@ -41,41 +43,47 @@
2624 void
2625 DashDBus::activateHome()
2626 {
2627- Q_EMIT m_view->activateHome();
2628+ Q_EMIT m_manager->dashActivateHome();
2629 }
2630
2631 void
2632 DashDBus::activateLens(const QString& lensId)
2633 {
2634- Q_EMIT m_view->activateLens(lensId);
2635+ Q_EMIT m_manager->dashActivateLens(lensId);
2636 }
2637
2638 bool
2639 DashDBus::active() const
2640 {
2641- return m_view->dashActive();
2642+ return m_manager->dashActive();
2643 }
2644
2645 void
2646 DashDBus::setActive(bool active)
2647 {
2648- m_view->setDashActive(active);
2649+ m_manager->setDashActive(active);
2650 }
2651
2652 bool
2653 DashDBus::alwaysFullScreen() const
2654 {
2655- return m_view->dashAlwaysFullScreen();
2656+ return m_manager->dashAlwaysFullScreen();
2657 }
2658
2659 QString
2660 DashDBus::activeLens() const
2661 {
2662- return m_view->activeLens();
2663+ return m_manager->dashActiveLens();
2664 }
2665
2666 void
2667 DashDBus::setActiveLens(QString activeLens)
2668 {
2669- m_view->setActiveLens(activeLens);
2670+ m_manager->setDashActiveLens(activeLens);
2671+}
2672+
2673+int
2674+DashDBus::screen() const
2675+{
2676+ return m_manager->dashScreen();
2677 }
2678
2679=== modified file 'shell/app/dashdbus.h'
2680--- shell/app/dashdbus.h 2012-03-05 16:38:47 +0000
2681+++ shell/app/dashdbus.h 2012-03-15 09:01:33 +0000
2682@@ -23,7 +23,7 @@
2683 #include <QtCore/QObject>
2684 #include <QtDBus/QDBusContext>
2685
2686-class ShellDeclarativeView;
2687+class ShellManager;
2688
2689 /**
2690 * DBus interface for the dash.
2691@@ -37,15 +37,17 @@
2692 Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
2693 Q_PROPERTY(bool alwaysFullScreen READ alwaysFullScreen NOTIFY alwaysFullScreenChanged)
2694 Q_PROPERTY(QString activeLens READ activeLens WRITE setActiveLens NOTIFY activeLensChanged)
2695+ Q_PROPERTY(int screen READ screen NOTIFY screenChanged)
2696
2697 public:
2698- DashDBus(ShellDeclarativeView* view, QObject* parent=0);
2699+ DashDBus(ShellManager* manager, QObject* parent=0);
2700
2701 bool active() const;
2702 void setActive(bool active);
2703 bool alwaysFullScreen() const;
2704 QString activeLens() const;
2705 void setActiveLens(QString activeLens);
2706+ int screen() const;
2707
2708 public Q_SLOTS:
2709 Q_NOREPLY void activateHome();
2710@@ -55,9 +57,10 @@
2711 void activeChanged(bool);
2712 void alwaysFullScreenChanged(bool);
2713 void activeLensChanged(QString);
2714+ void screenChanged(int);
2715
2716 private:
2717- ShellDeclarativeView* m_view;
2718+ ShellManager* m_manager;
2719 };
2720
2721 #endif // DashDBus_H
2722
2723=== modified file 'shell/app/hud.xml'
2724--- shell/app/hud.xml 2012-03-05 16:38:47 +0000
2725+++ shell/app/hud.xml 2012-03-15 09:01:33 +0000
2726@@ -12,12 +12,21 @@
2727 <property name="active" type="b" access="readwrite">
2728 <dox:d>True if the HUD is active</dox:d>
2729 </property>
2730+ <property name="screen" type="i" access="read">
2731+ <dox:d>The screen with the HUD</dox:d>
2732+ </property>
2733 <signal name="activeChanged">
2734 <dox:d>Signals when the active status of the HUD changes</dox:d>
2735 <arg name="active" type="b" direction="out">
2736 <dox:d>True if the HUD is active</dox:d>
2737 </arg>
2738 </signal>
2739+ <signal name="screenChanged">
2740+ <dox:d>Signals when the screen changes</dox:d>
2741+ <arg name="active" type="i" direction="out">
2742+ <dox:d>The screen with the HUD</dox:d>
2743+ </arg>
2744+ </signal>
2745 </interface>
2746 </node>
2747
2748
2749=== modified file 'shell/app/huddbus.cpp'
2750--- shell/app/huddbus.cpp 2012-03-05 16:38:47 +0000
2751+++ shell/app/huddbus.cpp 2012-03-15 09:01:33 +0000
2752@@ -21,18 +21,18 @@
2753 #include "hudadaptor.h"
2754
2755 // Local
2756-#include <shelldeclarativeview.h>
2757+#include <shellmanager.h>
2758
2759 // Qt
2760 #include <QtDBus/QDBusConnection>
2761 #include <QGraphicsObject>
2762
2763-HUDDBus::HUDDBus(ShellDeclarativeView* view, QObject* parent)
2764+HUDDBus::HUDDBus(ShellManager* manager, QObject* parent)
2765 : QObject(parent)
2766-, m_view(view)
2767+, m_manager(manager)
2768 {
2769- /* QML's propertyChanged signals are simple, they don't pass the property value */
2770- connect(m_view->rootObject(), SIGNAL(hudActiveChanged()), SLOT(onHudActiveChanged()));
2771+ connect(m_manager, SIGNAL(hudActiveChanged()), SLOT(onHudActiveChanged()));
2772+ connect(m_manager, SIGNAL(hudScreenChanged(int)), SIGNAL(screenChanged(int)));
2773
2774 new HUDAdaptor(this);
2775 }
2776@@ -40,7 +40,7 @@
2777 bool
2778 HUDDBus::active() const
2779 {
2780- return m_view->rootObject()->property("hudActive").toBool();
2781+ return m_manager->hudActive();
2782 }
2783
2784 void
2785@@ -53,7 +53,13 @@
2786 HUDDBus::setActive(bool hudActive)
2787 {
2788 if (hudActive != active()) {
2789- m_view->rootObject()->setProperty("hudActive", hudActive);
2790+ m_manager->setHudActive(hudActive);
2791 Q_EMIT activeChanged(hudActive);
2792 }
2793 }
2794+
2795+int
2796+HUDDBus::screen() const
2797+{
2798+ return m_manager->hudScreen();
2799+}
2800
2801=== modified file 'shell/app/huddbus.h'
2802--- shell/app/huddbus.h 2012-03-05 16:38:47 +0000
2803+++ shell/app/huddbus.h 2012-03-15 09:01:33 +0000
2804@@ -23,7 +23,7 @@
2805 #include <QtCore/QObject>
2806 #include <QtDBus/QDBusContext>
2807
2808-class ShellDeclarativeView;
2809+class ShellManager;
2810
2811 /**
2812 * DBus interface for the HUD.
2813@@ -32,21 +32,24 @@
2814 {
2815 Q_OBJECT
2816 Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
2817+ Q_PROPERTY(int screen READ screen NOTIFY screenChanged)
2818
2819 public:
2820- HUDDBus(ShellDeclarativeView* view, QObject* parent=0);
2821+ HUDDBus(ShellManager* manager, QObject* parent=0);
2822
2823 bool active() const;
2824 void setActive(bool active);
2825+ int screen() const;
2826
2827 Q_SIGNALS:
2828 void activeChanged(bool);
2829+ void screenChanged(int);
2830
2831 private Q_SLOTS:
2832 void onHudActiveChanged();
2833
2834 private:
2835- ShellDeclarativeView* m_view;
2836+ ShellManager* m_manager;
2837 };
2838
2839 #endif // HudDBus_H
2840
2841=== modified file 'shell/app/shell.cpp'
2842--- shell/app/shell.cpp 2012-03-06 18:06:03 +0000
2843+++ shell/app/shell.cpp 2012-03-15 09:01:33 +0000
2844@@ -21,27 +21,16 @@
2845 // QT
2846 #include <QApplication>
2847 #include <QDebug>
2848-#include <QtDeclarative>
2849-#include <QDeclarativeEngine>
2850-#include <QDeclarativeView>
2851-#include <QDesktopWidget>
2852-#include <QDBusConnection>
2853-#include <QDBusConnectionInterface>
2854-#include <QDeclarativeContext>
2855-#include <QAbstractEventDispatcher>
2856 #include <QDir>
2857-
2858-// X11
2859-#include <X11/Xlib.h>
2860+#include <QUrl>
2861
2862 // unity-2d
2863 #include <gnomesessionclient.h>
2864 #include <unity2dapplication.h>
2865-#include <unity2ddebug.h>
2866
2867 // Local
2868 #include "config.h"
2869-#include "shelldeclarativeview.h"
2870+#include "shellmanager.h"
2871 #include "shelldbus.h"
2872
2873 int main(int argc, char *argv[])
2874@@ -69,22 +58,7 @@
2875 GnomeSessionClient client(INSTALL_PREFIX "/share/applications/unity-2d-shell.desktop");
2876 client.connectToSessionManager();
2877
2878- qmlRegisterType<ShellDeclarativeView>("Unity2d", 1, 0, "ShellDeclarativeView");
2879- ShellDeclarativeView view;
2880- view.setAccessibleName("Shell");
2881- if (arguments.contains("-opengl")) {
2882- view.setUseOpenGL(true);
2883- }
2884-
2885- application.installX11EventFilter(&view);
2886-
2887- view.engine()->addImportPath(unity2dImportPath());
2888- view.engine()->setBaseUrl(QUrl::fromLocalFile(unity2dDirectory() + "/shell/"));
2889-
2890- /* Load the QML UI, focus and show the window */
2891- view.setResizeMode(QDeclarativeView::SizeViewToRootObject);
2892- view.rootContext()->setContextProperty("declarativeView", &view);
2893- view.setSource(rootFileUrl);
2894+ ShellManager shells(rootFileUrl);
2895
2896 /* Unset DESKTOP_AUTOSTART_ID in order to avoid child processes (launched
2897 applications) to use the same client id.
2898@@ -101,7 +75,7 @@
2899 (see e.g. https://bugs.launchpad.net/bugs/684471). */
2900 QDir::setCurrent(QDir::homePath());
2901
2902- ShellDBus shellDBus(&view);
2903+ ShellDBus shellDBus(&shells);
2904 if (!shellDBus.connectToBus()) {
2905 qCritical() << "Another instance of the Shell already exists. Quitting.";
2906 return -1;
2907
2908=== modified file 'shell/app/shelldbus.cpp'
2909--- shell/app/shelldbus.cpp 2012-03-05 16:38:47 +0000
2910+++ shell/app/shelldbus.cpp 2012-03-15 09:01:33 +0000
2911@@ -32,9 +32,9 @@
2912 static const char* DASH_DBUS_OBJECT_PATH = "/Dash";
2913 static const char* HUD_DBUS_OBJECT_PATH = "/HUD";
2914
2915-ShellDBus::ShellDBus(ShellDeclarativeView* view, QObject* parent)
2916+ShellDBus::ShellDBus(ShellManager* manager, QObject* parent)
2917 : QObject(parent)
2918-, m_view(view)
2919+, m_manager(manager)
2920 {
2921 }
2922
2923@@ -51,10 +51,10 @@
2924 return false;
2925 }
2926
2927- DashDBus *dashDBus = new DashDBus(m_view, this);
2928+ DashDBus *dashDBus = new DashDBus(m_manager, this);
2929 QDBusConnection::sessionBus().registerObject(DASH_DBUS_OBJECT_PATH, dashDBus);
2930
2931- HUDDBus *hudDBus = new HUDDBus(m_view, this);
2932+ HUDDBus *hudDBus = new HUDDBus(m_manager, this);
2933 QDBusConnection::sessionBus().registerObject(HUD_DBUS_OBJECT_PATH, hudDBus);
2934
2935 return true;
2936
2937=== modified file 'shell/app/shelldbus.h'
2938--- shell/app/shelldbus.h 2012-03-06 11:09:04 +0000
2939+++ shell/app/shelldbus.h 2012-03-15 09:01:33 +0000
2940@@ -24,7 +24,7 @@
2941 #include <QtCore/QObject>
2942 #include <QtDBus/QDBusContext>
2943
2944-class ShellDeclarativeView;
2945+class ShellManager;
2946
2947 /**
2948 * DBus interface for the shell.
2949@@ -34,13 +34,13 @@
2950 Q_OBJECT
2951
2952 public:
2953- ShellDBus(ShellDeclarativeView* view, QObject* parent=0);
2954+ ShellDBus(ShellManager* manager, QObject* parent=0);
2955 ~ShellDBus();
2956
2957 bool connectToBus();
2958
2959 private:
2960- ShellDeclarativeView* m_view;
2961+ ShellManager* m_manager;
2962 };
2963
2964 #endif // ShellDBus_H
2965
2966=== modified file 'shell/app/shelldeclarativeview.cpp'
2967--- shell/app/shelldeclarativeview.cpp 2012-03-05 14:04:05 +0000
2968+++ shell/app/shelldeclarativeview.cpp 2012-03-15 09:01:33 +0000
2969@@ -17,17 +17,12 @@
2970 // Local
2971 #include <config.h>
2972 #include "shelldeclarativeview.h"
2973+#include "shellmanager.h"
2974 #include "dashdbus.h"
2975
2976 // libunity-2d-private
2977 #include <debug_p.h>
2978 #include <hotkey.h>
2979-#include <hotkeymonitor.h>
2980-#include <hotmodifier.h>
2981-#include <keyboardmodifiersmonitor.h>
2982-#include <keymonitor.h>
2983-#include <dashclient.h>
2984-#include <launcherclient.h>
2985 #include <screeninfo.h>
2986 #include <strutmanager.h>
2987
2988@@ -41,69 +36,25 @@
2989 #include <QtDBus/QDBusConnectionInterface>
2990 #include <QtDBus/QDBusInterface>
2991 #include <QX11Info>
2992-#include <QGraphicsObject>
2993+#include <QDeclarativeItem>
2994 #include <QFileInfo>
2995
2996 // X11
2997 #include <X11/Xlib.h>
2998 #include <X11/Xatom.h>
2999
3000-static const char* COMMANDS_LENS_ID = "commands.lens";
3001-
3002-static const int DASH_MIN_SCREEN_WIDTH = 1280;
3003-static const int DASH_MIN_SCREEN_HEIGHT = 1084;
3004-
3005-ShellDeclarativeView::ShellDeclarativeView()
3006+ShellDeclarativeView::ShellDeclarativeView(ShellManager *manager, const QUrl &sourceFileUrl, int screen)
3007 : Unity2DDeclarativeView()
3008- , m_mode(DesktopMode)
3009- , m_expanded(true)
3010- , m_active(false)
3011- , m_dashAlwaysFullScreen(false)
3012+ , m_sourceFileUrl(sourceFileUrl)
3013+ , m_manager(manager)
3014 {
3015 setAttribute(Qt::WA_X11NetWmWindowTypeDock, true);
3016 setTransparentBackground(QX11Info::isCompositingManagerRunning());
3017
3018- m_screenInfo = new ScreenInfo(ScreenInfo::TopLeft, this);
3019-
3020- connect(&launcher2dConfiguration(), SIGNAL(superKeyEnableChanged(bool)), SLOT(updateSuperKeyMonitoring()));
3021- updateSuperKeyMonitoring();
3022-
3023- /* Super tap shows the dash, super held shows the launcher hints */
3024- m_superHotModifier = KeyboardModifiersMonitor::instance()->getHotModifierFor(Qt::MetaModifier);
3025- connect(m_superHotModifier, SIGNAL(tapped()), SLOT(toggleDash()));
3026- connect(m_superHotModifier, SIGNAL(heldChanged(bool)), SIGNAL(superKeyHeldChanged(bool)));
3027-
3028- /* Alt tap shows the HUD */
3029- m_altHotModifier = KeyboardModifiersMonitor::instance()->getHotModifierFor(Qt::AltModifier);
3030- connect(m_altHotModifier, SIGNAL(tapped()), SIGNAL(toggleHud()));
3031-
3032- /* Alt+F1 reveal the launcher and gives the keyboard focus to the Dash Button. */
3033- Hotkey* altF1 = HotkeyMonitor::instance().getHotkeyFor(Qt::Key_F1, Qt::AltModifier);
3034- connect(altF1, SIGNAL(pressed()), SLOT(onAltF1Pressed()));
3035-
3036- /* Alt+F2 shows the dash with the commands lens activated. */
3037- Hotkey* altF2 = HotkeyMonitor::instance().getHotkeyFor(Qt::Key_F2, Qt::AltModifier);
3038- connect(altF2, SIGNAL(pressed()), SLOT(showCommandsLens()));
3039-
3040- /* Super+{n} for 0 ≤ n ≤ 9 activates the item with index (n + 9) % 10. */
3041- for (Qt::Key key = Qt::Key_0; key <= Qt::Key_9; key = (Qt::Key) (key + 1)) {
3042- Hotkey* hotkey = HotkeyMonitor::instance().getHotkeyFor(key, Qt::MetaModifier);
3043- connect(hotkey, SIGNAL(pressed()), SLOT(forwardNumericHotkey()));
3044- hotkey = HotkeyMonitor::instance().getHotkeyFor(key, Qt::MetaModifier | Qt::ShiftModifier);
3045- connect(hotkey, SIGNAL(pressed()), SLOT(forwardNumericHotkey()));
3046- }
3047+ m_screenInfo = new ScreenInfo(screen, this);
3048
3049 connect(m_screenInfo, SIGNAL(availableGeometryChanged(QRect)), SLOT(updateShellPosition()));
3050 updateShellPosition();
3051-
3052- // FIXME: we need to use a queued connection here otherwise QConf will deadlock for some reason
3053- // when we read any property from the slot (which we need to do). We need to check why this
3054- // happens and report a bug to dconf-qt to get it fixed.
3055- connect(&unity2dConfiguration(), SIGNAL(formFactorChanged(QString)),
3056- SLOT(updateDashAlwaysFullScreen()), Qt::QueuedConnection);
3057- connect(QApplication::desktop(), SIGNAL(resized(int)), SLOT(updateDashAlwaysFullScreen()));
3058-
3059- updateDashAlwaysFullScreen();
3060 }
3061
3062 void
3063@@ -147,7 +98,6 @@
3064 ShellDeclarativeView::focusOutEvent(QFocusEvent* event)
3065 {
3066 Unity2DDeclarativeView::focusOutEvent(event);
3067- setDashActive(false);
3068 Q_EMIT focusChanged();
3069 }
3070
3071@@ -177,6 +127,17 @@
3072 Unity2DDeclarativeView::resizeEvent(event);
3073 }
3074
3075+
3076+void ShellDeclarativeView::forceActivateWindow()
3077+{
3078+ m_manager->forceActivateShell(this);
3079+}
3080+
3081+void ShellDeclarativeView::forceDeactivateWindow()
3082+{
3083+ m_manager->forceDeactivateShell(this);
3084+}
3085+
3086 void
3087 ShellDeclarativeView::setWMFlags()
3088 {
3089@@ -200,181 +161,21 @@
3090 /* Note that this has to be called everytime the window is shown, as the WM
3091 will remove the flags when the window is hidden */
3092 setWMFlags();
3093-}
3094-
3095-void
3096-ShellDeclarativeView::setDashActive(bool value)
3097-{
3098- if (value != m_active) {
3099- m_active = value;
3100- Q_EMIT dashActiveChanged(m_active);
3101- }
3102-}
3103-
3104-bool
3105-ShellDeclarativeView::dashActive() const
3106-{
3107- return m_active;
3108-}
3109-
3110-bool
3111-ShellDeclarativeView::haveCustomHomeShortcuts() const
3112-{
3113- return QFileInfo(unity2dDirectory() + "/shell/dash/HomeShortcutsCustomized.qml").exists();
3114-}
3115-
3116-void
3117-ShellDeclarativeView::setDashMode(ShellDeclarativeView::DashMode mode)
3118-{
3119- if (m_mode == mode) {
3120- return;
3121- }
3122-
3123- m_mode = mode;
3124- dashModeChanged(m_mode);
3125-}
3126-
3127-ShellDeclarativeView::DashMode
3128-ShellDeclarativeView::dashMode() const
3129-{
3130- return m_mode;
3131-}
3132-
3133-void
3134-ShellDeclarativeView::setExpanded(bool value)
3135-{
3136- if (m_expanded == value) {
3137- return;
3138- }
3139-
3140- m_expanded = value;
3141- expandedChanged(m_expanded);
3142-}
3143-
3144-bool
3145-ShellDeclarativeView::expanded() const
3146-{
3147- return m_expanded;
3148-}
3149-
3150-bool ShellDeclarativeView::dashAlwaysFullScreen() const
3151-{
3152- return m_dashAlwaysFullScreen;
3153-}
3154-
3155-void
3156-ShellDeclarativeView::setActiveLens(const QString& activeLens)
3157-{
3158- if (activeLens != m_activeLens) {
3159- m_activeLens = activeLens;
3160- Q_EMIT activeLensChanged(activeLens);
3161- }
3162-}
3163-
3164-const QString&
3165-ShellDeclarativeView::activeLens() const
3166-{
3167- return m_activeLens;
3168-}
3169-
3170-void
3171-ShellDeclarativeView::toggleDash()
3172-{
3173- if (dashActive()) {
3174- setDashActive(false);
3175- forceDeactivateWindow();
3176- } else {
3177- Q_EMIT activateHome();
3178- }
3179-}
3180-
3181-void
3182-ShellDeclarativeView::showCommandsLens()
3183-{
3184- Q_EMIT activateLens(COMMANDS_LENS_ID);
3185-}
3186-
3187-void
3188-ShellDeclarativeView::onAltF1Pressed()
3189+ if (source().isEmpty()) {
3190+ QMap<const char*, QVariant> rootObjectProperties;
3191+ rootObjectProperties.insert("declarativeView", QVariant::fromValue(this));
3192+ setSource(m_sourceFileUrl, rootObjectProperties);
3193+ }
3194+}
3195+
3196+void
3197+ShellDeclarativeView::toggleLauncher()
3198 {
3199 if (!isActiveWindow()) {
3200 forceActivateWindow();
3201 Q_EMIT launcherFocusRequested();
3202 } else {
3203- if (dashActive()) {
3204- // focus the launcher instead of the dash
3205- setDashActive(false);
3206- Q_EMIT launcherFocusRequested();
3207- } else {
3208- // we assume that the launcher is focused; unfocus it by deactivating the shell window
3209- forceDeactivateWindow();
3210- }
3211- }
3212-}
3213-
3214-static QSize minimumSizeForDesktop()
3215-{
3216- return QSize(DASH_MIN_SCREEN_WIDTH, DASH_MIN_SCREEN_HEIGHT);
3217-}
3218-
3219-void ShellDeclarativeView::updateDashAlwaysFullScreen()
3220-{
3221- bool dashAlwaysFullScreen;
3222- if (unity2dConfiguration().property("formFactor").toString() != "desktop") {
3223- dashAlwaysFullScreen = true;
3224- } else {
3225- const QRect rect = m_screenInfo->geometry();
3226- const QSize minSize = minimumSizeForDesktop();
3227- dashAlwaysFullScreen = rect.width() < minSize.width() && rect.height() < minSize.height();
3228- }
3229-
3230- if (m_dashAlwaysFullScreen != dashAlwaysFullScreen) {
3231- m_dashAlwaysFullScreen = dashAlwaysFullScreen;
3232- Q_EMIT dashAlwaysFullScreenChanged(dashAlwaysFullScreen);
3233- }
3234-}
3235-
3236-void
3237-ShellDeclarativeView::updateSuperKeyMonitoring()
3238-{
3239- KeyboardModifiersMonitor *modifiersMonitor = KeyboardModifiersMonitor::instance();
3240- HotkeyMonitor& hotkeyMonitor = HotkeyMonitor::instance();
3241-
3242- QVariant value = launcher2dConfiguration().property("superKeyEnable");
3243- if (!value.isValid() || value.toBool() == true) {
3244- hotkeyMonitor.enableModifiers(Qt::MetaModifier);
3245- modifiersMonitor->enableModifiers(Qt::MetaModifier);
3246- } else {
3247- hotkeyMonitor.disableModifiers(Qt::MetaModifier);
3248- modifiersMonitor->disableModifiers(Qt::MetaModifier);
3249- }
3250-}
3251-
3252-void
3253-ShellDeclarativeView::forwardNumericHotkey()
3254-{
3255- Hotkey* hotkey = qobject_cast<Hotkey*>(sender());
3256- if (hotkey != NULL) {
3257- /* Shortcuts from 1 to 9 should activate the items with index
3258- from 1 to 9 (index 0 being the so-called "BFB" or Dash launcher).
3259- Shortcut for 0 should activate item with index 10.
3260- In other words, the indexes are activated in the same order as
3261- the keys appear on a standard keyboard. */
3262- Qt::Key key = hotkey->key();
3263- if (key >= Qt::Key_1 && key <= Qt::Key_9) {
3264- int index = key - Qt::Key_0;
3265- if (hotkey->modifiers() & Qt::ShiftModifier) {
3266- Q_EMIT newInstanceShortcutPressed(index);
3267- } else {
3268- Q_EMIT activateShortcutPressed(index);
3269- }
3270- } else if (key == Qt::Key_0) {
3271- if (hotkey->modifiers() & Qt::ShiftModifier) {
3272- Q_EMIT newInstanceShortcutPressed(10);
3273- } else {
3274- Q_EMIT activateShortcutPressed(10);
3275- }
3276- }
3277+ forceDeactivateWindow();
3278 }
3279 }
3280
3281@@ -450,9 +251,3 @@
3282 {
3283 return m_monitoredAreaContainsMouse;
3284 }
3285-
3286-bool
3287-ShellDeclarativeView::superKeyHeld() const
3288-{
3289- return m_superHotModifier->held();
3290-}
3291
3292=== modified file 'shell/app/shelldeclarativeview.h'
3293--- shell/app/shelldeclarativeview.h 2012-03-05 13:59:50 +0000
3294+++ shell/app/shelldeclarativeview.h 2012-03-15 09:01:33 +0000
3295@@ -27,21 +27,14 @@
3296 class LauncherClient;
3297 class ShellDBus;
3298 class ScreenInfo;
3299-class HotModifier;
3300+class Hotkey;
3301+class ShellManager;
3302
3303 class ShellDeclarativeView : public Unity2DDeclarativeView, public AbstractX11EventFilter
3304 {
3305 Q_OBJECT
3306- Q_ENUMS(DashMode)
3307
3308- Q_PROPERTY(bool dashActive READ dashActive WRITE setDashActive NOTIFY dashActiveChanged)
3309- Q_PROPERTY(bool expanded READ expanded WRITE setExpanded NOTIFY expandedChanged)
3310- Q_PROPERTY(DashMode dashMode READ dashMode WRITE setDashMode NOTIFY dashModeChanged)
3311- Q_PROPERTY(QString activeLens READ activeLens WRITE setActiveLens NOTIFY activeLensChanged)
3312 Q_PROPERTY(bool focus READ hasFocus NOTIFY focusChanged) // overridden to add notify
3313- Q_PROPERTY(bool dashAlwaysFullScreen READ dashAlwaysFullScreen NOTIFY dashAlwaysFullScreenChanged)
3314- Q_PROPERTY(bool superKeyHeld READ superKeyHeld NOTIFY superKeyHeldChanged)
3315- Q_PROPERTY(bool haveCustomHomeShortcuts READ haveCustomHomeShortcuts)
3316
3317 /* These two properties and mouse movement tracking on the widget are added here only because
3318 we need to detect when the mouse is inside the area occupied by the lancher. This should
3319@@ -54,60 +47,31 @@
3320 NOTIFY monitoredAreaContainsMouseChanged)
3321
3322 public:
3323- enum DashMode {
3324- DesktopMode,
3325- FullScreenMode
3326- };
3327- explicit ShellDeclarativeView();
3328+ ShellDeclarativeView(ShellManager *manager, const QUrl &sourceFileUrl, int screen);
3329
3330 /* getters */
3331- bool dashActive() const;
3332- bool haveCustomHomeShortcuts() const;
3333- DashMode dashMode() const;
3334- const QString& activeLens() const;
3335- bool expanded() const;
3336- bool superKeyHeld() const;
3337- bool dashAlwaysFullScreen() const;
3338 QRect monitoredArea() const;
3339 bool monitoredAreaContainsMouse() const;
3340
3341 /* setters */
3342- Q_SLOT void setDashActive(bool active);
3343- Q_INVOKABLE void setDashMode(DashMode);
3344- Q_INVOKABLE void setActiveLens(const QString& activeLens);
3345- Q_INVOKABLE void setExpanded(bool);
3346 void setMonitoredArea(QRect monitoredArea);
3347
3348 virtual bool x11EventFilter(XEvent* event);
3349
3350+ void toggleLauncher();
3351+
3352+ Q_INVOKABLE void forceActivateWindow();
3353+ Q_INVOKABLE void forceDeactivateWindow();
3354+
3355 Q_SIGNALS:
3356- void dashActiveChanged(bool);
3357- void dashModeChanged(DashMode);
3358- void expandedChanged(bool);
3359- void activeLensChanged(const QString&);
3360- void activateLens(const QString& lensId);
3361- void activateHome();
3362- void toggleHud();
3363 void focusChanged();
3364 void monitoredAreaChanged();
3365 void monitoredAreaContainsMouseChanged();
3366
3367- void dashAlwaysFullScreenChanged(bool dashAlwaysFullScreen);
3368- void superKeyHeldChanged(bool superKeyHeld);
3369 void activateShortcutPressed(int itemIndex);
3370 void newInstanceShortcutPressed(int itemIndex);
3371 void launcherFocusRequested();
3372
3373-private Q_SLOTS:
3374- void updateSuperKeyMonitoring();
3375- void forwardNumericHotkey();
3376-
3377- void toggleDash();
3378- void showCommandsLens();
3379- void onAltF1Pressed();
3380-
3381- void updateDashAlwaysFullScreen();
3382-
3383 protected:
3384 virtual void showEvent(QShowEvent *event);
3385 virtual void mouseMoveEvent(QMouseEvent *event);
3386@@ -123,19 +87,12 @@
3387 void setWMFlags();
3388 void updateInputShape();
3389
3390- DashMode m_mode;
3391- bool m_expanded;
3392- QString m_activeLens; /* Lens id of the active lens */
3393- bool m_active;
3394-
3395- bool m_dashAlwaysFullScreen;
3396 QRect m_monitoredArea;
3397 bool m_monitoredAreaContainsMouse;
3398-
3399- HotModifier* m_superHotModifier;
3400- HotModifier* m_altHotModifier;
3401-
3402- friend class DashDBus;
3403+ QUrl m_sourceFileUrl;
3404+ ShellManager *m_manager;
3405+
3406+ friend class ShellManager;
3407 };
3408
3409 Q_DECLARE_METATYPE(ShellDeclarativeView*)
3410
3411=== added file 'shell/app/shellmanager.cpp'
3412--- shell/app/shellmanager.cpp 1970-01-01 00:00:00 +0000
3413+++ shell/app/shellmanager.cpp 2012-03-15 09:01:33 +0000
3414@@ -0,0 +1,683 @@
3415+/*
3416+ * This file is part of unity-2d
3417+ *
3418+ * Copyright 2010 Canonical Ltd.
3419+ *
3420+ * This program is free software; you can redistribute it and/or modify
3421+ * it under the terms of the GNU General Public License as published by
3422+ * the Free Software Foundation; version 3.
3423+ *
3424+ * This program is distributed in the hope that it will be useful,
3425+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3426+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3427+ * GNU General Public License for more details.
3428+ *
3429+ * You should have received a copy of the GNU General Public License
3430+ * along with this program. If not, see <http://www.gnu.org/licenses/>
3431+ */
3432+
3433+#include "shellmanager.h"
3434+
3435+// Qt
3436+#include <QApplication>
3437+#include <QDebug>
3438+#include <QtDeclarative>
3439+#include <QDesktopWidget>
3440+#include <QX11Info>
3441+
3442+// libunity-2d-private
3443+#include <debug_p.h>
3444+#include <hotmodifier.h>
3445+#include <hotkeymonitor.h>
3446+#include <hotkey.h>
3447+#include <keyboardmodifiersmonitor.h>
3448+#include <keymonitor.h>
3449+#include <screeninfo.h>
3450+
3451+// Local
3452+#include "shelldeclarativeview.h"
3453+#include "config.h"
3454+
3455+// unity-2d
3456+#include <unity2ddebug.h>
3457+#include <gobjectcallback.h>
3458+
3459+// bamf
3460+#include "bamf-window.h"
3461+#include "bamf-matcher.h"
3462+
3463+// libwnck
3464+extern "C" {
3465+#define WNCK_I_KNOW_THIS_IS_UNSTABLE
3466+#include <libwnck/libwnck.h>
3467+}
3468+
3469+static const char* COMMANDS_LENS_ID = "commands.lens";
3470+static const int DASH_MIN_SCREEN_WIDTH = 1280;
3471+static const int DASH_MIN_SCREEN_HEIGHT = 1084;
3472+
3473+GOBJECT_CALLBACK1(activeWorkspaceChangedCB, "onActiveWorkspaceChanged");
3474+
3475+struct ShellManagerPrivate
3476+{
3477+ ShellManagerPrivate()
3478+ : q(NULL)
3479+ , m_shellWithDash(NULL)
3480+ , m_shellWithHud(NULL)
3481+ , m_hudLoader(NULL)
3482+ , m_dashAlwaysFullScreen(false)
3483+ , m_dashActive(false)
3484+ , m_dashMode(ShellManager::DesktopMode)
3485+ , m_superHotModifier(NULL)
3486+ , m_last_focused_window(None)
3487+ {}
3488+
3489+ enum ActiveShellUsage {
3490+ ActiveShellGeneralUse,
3491+ ActiveShellLauncherRelatedUse
3492+ };
3493+
3494+ ShellDeclarativeView* initShell(int screen);
3495+ void updateScreenCount(int newCount);
3496+ ShellDeclarativeView* activeShell(ActiveShellUsage usage) const;
3497+ void moveDashToShell(ShellDeclarativeView* newShell);
3498+ void moveHudToShell(ShellDeclarativeView* newShell);
3499+ void saveActiveWindow();
3500+
3501+ ShellManager *q;
3502+ QList<ShellDeclarativeView *> m_viewList;
3503+ ShellDeclarativeView * m_shellWithDash;
3504+ ShellDeclarativeView * m_shellWithHud;
3505+ QDeclarativeItem* m_hudLoader;
3506+ bool m_dashAlwaysFullScreen;
3507+ QUrl m_sourceFileUrl;
3508+ bool m_dashActive;
3509+ ShellManager::DashMode m_dashMode;
3510+ QString m_dashActiveLens; /* Lens id of the active lens */
3511+
3512+ HotModifier* m_superHotModifier;
3513+ HotModifier* m_altHotModifier;
3514+
3515+ WId m_last_focused_window;
3516+};
3517+
3518+
3519+ShellDeclarativeView *
3520+ShellManagerPrivate::initShell(int screen)
3521+{
3522+ const QStringList arguments = qApp->arguments();
3523+ ShellDeclarativeView * view = new ShellDeclarativeView(q, m_sourceFileUrl, screen);
3524+ view->setAccessibleName("Shell");
3525+ if (arguments.contains("-opengl")) {
3526+ view->setUseOpenGL(true);
3527+ }
3528+
3529+ Unity2dApplication::instance()->installX11EventFilter(view);
3530+
3531+ view->engine()->addImportPath(unity2dImportPath());
3532+ view->engine()->setBaseUrl(QUrl::fromLocalFile(unity2dDirectory() + "/shell/"));
3533+
3534+ view->rootContext()->setContextProperty("shellManager", q);
3535+
3536+ view->show();
3537+
3538+ return view;
3539+}
3540+
3541+ShellDeclarativeView *
3542+ShellManagerPrivate::activeShell(ActiveShellUsage usage) const
3543+{
3544+ bool launcherOnlyInOneScreen = launcher2dConfiguration().property("onlyOneLauncher").toBool();
3545+ if (usage == ActiveShellLauncherRelatedUse && launcherOnlyInOneScreen) {
3546+ return m_viewList.isEmpty() ? NULL : m_viewList[0];
3547+ }
3548+
3549+ int cursorScreen = QApplication::desktop()->screenNumber(QCursor::pos());
3550+ Q_FOREACH(ShellDeclarativeView * shell, m_viewList) {
3551+ if (shell->screen()->screen() == cursorScreen) {
3552+ return shell;
3553+ }
3554+ }
3555+ return 0;
3556+}
3557+
3558+void
3559+ShellManagerPrivate::updateScreenCount(int newCount)
3560+{
3561+ const int previousCount = m_viewList.size();
3562+
3563+ /* Instantiate new Shells as needed. */
3564+ for (int screen = previousCount; screen < newCount; ++screen) {
3565+ ShellDeclarativeView *shell = initShell(screen);
3566+ m_viewList.append(shell);
3567+
3568+ if (screen == 0) {
3569+ m_shellWithDash = m_viewList[0];
3570+ Q_EMIT q->dashShellChanged(m_shellWithDash);
3571+ Q_EMIT q->dashScreenChanged(q->dashScreen());
3572+
3573+ m_shellWithHud = m_viewList[0];
3574+ Q_EMIT q->hudShellChanged(m_shellWithHud);
3575+ Q_EMIT q->hudScreenChanged(q->hudScreen());
3576+
3577+ m_hudLoader = qobject_cast<QDeclarativeItem*>(m_shellWithHud->rootObject()->property("hudLoader").value<QObject *>());
3578+ if (m_hudLoader != NULL) {
3579+ QObject::connect(m_hudLoader, SIGNAL(activeChanged()), q, SIGNAL(hudActiveChanged()));
3580+ } else {
3581+ qWarning() << "Could not find the hudLoader";
3582+ }
3583+ }
3584+ }
3585+
3586+ /* Remove extra Shells if any. */
3587+ while (m_viewList.size() > newCount) {
3588+ ShellDeclarativeView *shell = m_viewList.takeLast();
3589+ if (shell == m_shellWithDash) {
3590+ if (newCount > 0) {
3591+ moveDashToShell(m_viewList[0]);
3592+ } else {
3593+ m_shellWithDash = NULL;
3594+ Q_EMIT q->dashShellChanged(NULL);
3595+ Q_EMIT q->dashScreenChanged(-1);
3596+ }
3597+ }
3598+ if (shell == m_shellWithHud) {
3599+ if (newCount > 0) {
3600+ moveHudToShell(m_viewList[0]);
3601+ } else {
3602+ m_shellWithHud = NULL;
3603+ Q_EMIT q->hudShellChanged(NULL);
3604+ Q_EMIT q->hudScreenChanged(-1);
3605+ }
3606+ }
3607+ shell->deleteLater();
3608+ }
3609+
3610+}
3611+
3612+static QList<QDeclarativeItem *> dumpFocusedItems(QObject *obj) {
3613+ QList<QDeclarativeItem *> res;
3614+ QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(obj);
3615+ if (item && item->hasFocus()) {
3616+ res << item;
3617+ }
3618+ Q_FOREACH (QObject *childObj, obj->children()) {
3619+ res += dumpFocusedItems(childObj);
3620+ }
3621+ return res;
3622+}
3623+
3624+static bool moveRootChildItemToShell(const char *itemName, ShellDeclarativeView* newShell, ShellDeclarativeView* oldShell)
3625+{
3626+ bool itemMoved = false;
3627+
3628+ if (newShell != oldShell) {
3629+ QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(oldShell->rootObject()->property(itemName).value<QObject *>());
3630+ if (item) {
3631+ const QGraphicsView::ViewportUpdateMode oldShellViewportUpdateMode = oldShell->viewportUpdateMode();
3632+ const QGraphicsView::ViewportUpdateMode newShellViewportUpdateMode = newShell->viewportUpdateMode();
3633+ oldShell->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
3634+ newShell->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
3635+
3636+ // Moving the item around makes it lose its focus values, remember them and set them later
3637+ const QList<QDeclarativeItem *> itemChildrenFocusedItems = dumpFocusedItems(item);
3638+
3639+ oldShell->rootObject()->setProperty(itemName, QVariant());
3640+ oldShell->scene()->removeItem(item);
3641+
3642+ item->setParentItem(qobject_cast<QDeclarativeItem*>(newShell->rootObject()));
3643+ newShell->rootObject()->setProperty(itemName, QVariant::fromValue<QObject*>(item));
3644+
3645+ Q_FOREACH(QDeclarativeItem *childrenItem, itemChildrenFocusedItems) {
3646+ childrenItem->setFocus(true);
3647+ }
3648+
3649+ oldShell->setViewportUpdateMode(oldShellViewportUpdateMode);
3650+ newShell->setViewportUpdateMode(newShellViewportUpdateMode);
3651+
3652+ itemMoved = true;
3653+ } else {
3654+ qWarning() << "moveRootChildItemToShell: Could not find the item" << itemName;
3655+ }
3656+ }
3657+
3658+ return itemMoved;
3659+}
3660+
3661+void ShellManagerPrivate::moveDashToShell(ShellDeclarativeView* newShell)
3662+{
3663+ if (moveRootChildItemToShell("dashLoader", newShell, m_shellWithDash)) {
3664+ m_shellWithDash = newShell;
3665+ Q_EMIT q->dashShellChanged(newShell);
3666+ Q_EMIT q->dashScreenChanged(q->dashScreen());
3667+ }
3668+}
3669+
3670+void ShellManagerPrivate::moveHudToShell(ShellDeclarativeView* newShell)
3671+{
3672+ if (moveRootChildItemToShell("hudLoader", newShell, m_shellWithHud)) {
3673+ m_shellWithHud = newShell;
3674+ Q_EMIT q->hudShellChanged(newShell);
3675+ Q_EMIT q->hudScreenChanged(q->hudScreen());
3676+ }
3677+}
3678+
3679+/* -------------------------- ShellManager -----------------------------*/
3680+
3681+ShellManager::ShellManager(const QUrl &sourceFileUrl, QObject* parent) :
3682+ QObject(parent)
3683+ ,d(new ShellManagerPrivate)
3684+{
3685+ d->q = this;
3686+ d->m_sourceFileUrl = sourceFileUrl;
3687+
3688+ qmlRegisterUncreatableType<ShellDeclarativeView>("Unity2d", 1, 0, "ShellDeclarativeView", "This can only be created from C++");
3689+ qmlRegisterUncreatableType<ShellManager>("Unity2d", 1, 0, "ShellManager", "This can only be created from C++");
3690+
3691+ QDesktopWidget* desktop = QApplication::desktop();
3692+
3693+ d->updateScreenCount(desktop->screenCount());
3694+
3695+ connect(desktop, SIGNAL(screenCountChanged(int)), SLOT(onScreenCountChanged(int)));
3696+
3697+ connect(&launcher2dConfiguration(), SIGNAL(superKeyEnableChanged(bool)), SLOT(updateSuperKeyMonitoring()));
3698+ updateSuperKeyMonitoring();
3699+
3700+ /* Super tap shows the dash, super held shows the launcher hints */
3701+ d->m_superHotModifier = KeyboardModifiersMonitor::instance()->getHotModifierFor(Qt::MetaModifier);
3702+ connect(d->m_superHotModifier, SIGNAL(tapped()), SLOT(toggleDashRequested()));
3703+ connect(d->m_superHotModifier, SIGNAL(heldChanged(bool)), SIGNAL(superKeyHeldChanged(bool)));
3704+
3705+ /* Alt tap shows the HUD */
3706+ d->m_altHotModifier = KeyboardModifiersMonitor::instance()->getHotModifierFor(Qt::AltModifier);
3707+ connect(d->m_altHotModifier, SIGNAL(tapped()), SLOT(toggleHudRequested()));
3708+
3709+ /* Alt+F1 reveals the launcher and gives the keyboard focus to the Dash Button. */
3710+ Hotkey* altF1 = HotkeyMonitor::instance().getHotkeyFor(Qt::Key_F1, Qt::AltModifier);
3711+ connect(altF1, SIGNAL(pressed()), SLOT(onAltF1Pressed()));
3712+
3713+ /* Alt+F2 shows the dash with the commands lens activated. */
3714+ Hotkey* altF2 = HotkeyMonitor::instance().getHotkeyFor(Qt::Key_F2, Qt::AltModifier);
3715+ connect(altF2, SIGNAL(pressed()), SLOT(onAltF2Pressed()));
3716+
3717+ /* Super+{n} for 0 ≤ n ≤ 9 activates the item with index (n + 9) % 10. */
3718+ for (Qt::Key key = Qt::Key_0; key <= Qt::Key_9; key = (Qt::Key) (key + 1)) {
3719+ Hotkey* hotkey = HotkeyMonitor::instance().getHotkeyFor(key, Qt::MetaModifier);
3720+ connect(hotkey, SIGNAL(pressed()), SLOT(onNumericHotkeyPressed()));
3721+ hotkey = HotkeyMonitor::instance().getHotkeyFor(key, Qt::MetaModifier | Qt::ShiftModifier);
3722+ connect(hotkey, SIGNAL(pressed()), SLOT(onNumericHotkeyPressed()));
3723+ }
3724+
3725+ // FIXME: we need to use a queued connection here otherwise QConf will deadlock for some reason
3726+ // when we read any property from the slot (which we need to do). We need to check why this
3727+ // happens and report a bug to dconf-qt to get it fixed.
3728+ connect(&unity2dConfiguration(), SIGNAL(formFactorChanged(QString)),
3729+ SLOT(updateDashAlwaysFullScreen()), Qt::QueuedConnection);
3730+ connect(this, SIGNAL(dashShellChanged(QObject *)), this, SLOT(updateDashAlwaysFullScreen()));
3731+ connect(QApplication::desktop(), SIGNAL(resized(int)), SLOT(updateDashAlwaysFullScreen()));
3732+
3733+ updateDashAlwaysFullScreen();
3734+
3735+ g_signal_connect(G_OBJECT(wnck_screen_get_default()), "active_workspace_changed", G_CALLBACK(activeWorkspaceChangedCB), this);
3736+}
3737+
3738+ShellManager::~ShellManager()
3739+{
3740+ g_signal_handlers_disconnect_by_func(G_OBJECT(wnck_screen_get_default()), gpointer(activeWorkspaceChangedCB), this);
3741+
3742+ qDeleteAll(d->m_viewList);
3743+ delete d;
3744+}
3745+
3746+void
3747+ShellManager::setDashActive(bool value)
3748+{
3749+ if (value != d->m_dashActive) {
3750+ d->m_dashActive = value;
3751+ Q_EMIT dashActiveChanged(d->m_dashActive);
3752+ }
3753+}
3754+
3755+bool
3756+ShellManager::dashActive() const
3757+{
3758+ return d->m_dashActive;
3759+}
3760+
3761+void
3762+ShellManager::setDashMode(DashMode mode)
3763+{
3764+ if (d->m_dashMode == mode) {
3765+ return;
3766+ }
3767+
3768+ d->m_dashMode = mode;
3769+ dashModeChanged(d->m_dashMode);
3770+}
3771+
3772+ShellManager::DashMode
3773+ShellManager::dashMode() const
3774+{
3775+ return d->m_dashMode;
3776+}
3777+
3778+void
3779+ShellManager::setDashActiveLens(const QString& activeLens)
3780+{
3781+ if (activeLens != d->m_dashActiveLens) {
3782+ d->m_dashActiveLens = activeLens;
3783+ Q_EMIT dashActiveLensChanged(activeLens);
3784+ }
3785+}
3786+
3787+const QString&
3788+ShellManager::dashActiveLens() const
3789+{
3790+ return d->m_dashActiveLens;
3791+}
3792+
3793+bool
3794+ShellManager::dashHaveCustomHomeShortcuts() const
3795+{
3796+ return QFileInfo(unity2dDirectory() + "/shell/dash/HomeShortcutsCustomized.qml").exists();
3797+}
3798+
3799+QObject *
3800+ShellManager::dashShell() const
3801+{
3802+ return d->m_shellWithDash;
3803+}
3804+
3805+int
3806+ShellManager::dashScreen() const
3807+{
3808+ if (d->m_shellWithDash != NULL) {
3809+ return d->m_shellWithDash->screen()->screen();
3810+ } else {
3811+ return -1;
3812+ }
3813+}
3814+
3815+bool
3816+ShellManager::dashAlwaysFullScreen() const
3817+{
3818+ return d->m_dashAlwaysFullScreen;
3819+}
3820+
3821+void
3822+ShellManager::onScreenCountChanged(int newCount)
3823+{
3824+ d->updateScreenCount(newCount);
3825+}
3826+
3827+void
3828+ShellManager::toggleDashRequested()
3829+{
3830+ ShellDeclarativeView * activeShell = d->activeShell(ShellManagerPrivate::ActiveShellLauncherRelatedUse);
3831+ if (activeShell) {
3832+ const bool differentShell = d->m_shellWithDash != activeShell;
3833+
3834+ if (dashActive() && !differentShell) {
3835+ setDashActive(false);
3836+ forceDeactivateShell(d->m_shellWithDash);
3837+ } else {
3838+ d->moveDashToShell(activeShell);
3839+ Q_EMIT dashActivateHome();
3840+ }
3841+ }
3842+}
3843+
3844+void
3845+ShellManager::toggleHudRequested()
3846+{
3847+ ShellDeclarativeView * activeShell = d->activeShell(ShellManagerPrivate::ActiveShellGeneralUse);
3848+ if (activeShell) {
3849+ const bool differentShell = d->m_shellWithHud != activeShell;
3850+
3851+ if (differentShell) {
3852+ d->moveHudToShell(activeShell);
3853+
3854+ if (!hudActive()) {
3855+ Q_EMIT toggleHud();
3856+ } else {
3857+ forceActivateShell(activeShell);
3858+ }
3859+ } else {
3860+ Q_EMIT toggleHud();
3861+ }
3862+ }
3863+}
3864+
3865+static QSize minimumSizeForDesktop()
3866+{
3867+ return QSize(DASH_MIN_SCREEN_WIDTH, DASH_MIN_SCREEN_HEIGHT);
3868+}
3869+
3870+void ShellManager::updateDashAlwaysFullScreen()
3871+{
3872+ bool dashAlwaysFullScreen;
3873+ if (unity2dConfiguration().property("formFactor").toString() != "desktop") {
3874+ dashAlwaysFullScreen = true;
3875+ } else {
3876+ const QRect rect = QApplication::desktop()->screenGeometry(d->m_shellWithDash);
3877+ const QSize minSize = minimumSizeForDesktop();
3878+ dashAlwaysFullScreen = rect.width() < minSize.width() && rect.height() < minSize.height();
3879+ }
3880+
3881+ if (d->m_dashAlwaysFullScreen != dashAlwaysFullScreen) {
3882+ d->m_dashAlwaysFullScreen = dashAlwaysFullScreen;
3883+ Q_EMIT dashAlwaysFullScreenChanged(dashAlwaysFullScreen);
3884+ }
3885+}
3886+
3887+void ShellManager::onActiveWorkspaceChanged()
3888+{
3889+ Q_EMIT activeWorkspaceChanged();
3890+ d->m_last_focused_window = None;
3891+ Q_EMIT lastFocusedWindowChanged(d->m_last_focused_window);
3892+}
3893+
3894+/* ----------------- super key handling ---------------- */
3895+
3896+void
3897+ShellManager::updateSuperKeyMonitoring()
3898+{
3899+ KeyboardModifiersMonitor *modifiersMonitor = KeyboardModifiersMonitor::instance();
3900+ HotkeyMonitor& hotkeyMonitor = HotkeyMonitor::instance();
3901+
3902+ QVariant value = launcher2dConfiguration().property("superKeyEnable");
3903+ if (!value.isValid() || value.toBool() == true) {
3904+ hotkeyMonitor.enableModifiers(Qt::MetaModifier);
3905+ modifiersMonitor->enableModifiers(Qt::MetaModifier);
3906+ } else {
3907+ hotkeyMonitor.disableModifiers(Qt::MetaModifier);
3908+ modifiersMonitor->disableModifiers(Qt::MetaModifier);
3909+ }
3910+}
3911+
3912+bool
3913+ShellManager::superKeyHeld() const
3914+{
3915+ if (d->m_superHotModifier == NULL) { // We are just initializing
3916+ return false;
3917+ }
3918+
3919+ return d->m_superHotModifier->held();
3920+}
3921+
3922+bool
3923+ShellManager::hudActive() const
3924+{
3925+ if (d->m_hudLoader == NULL) { // We are just initializing
3926+ return false;
3927+ }
3928+
3929+ return d->m_hudLoader->property("active").toBool();
3930+}
3931+
3932+void
3933+ShellManager::setHudActive(bool active)
3934+{
3935+ if (d->m_hudLoader != NULL) {
3936+ d->m_hudLoader->setProperty("active", active);
3937+ }
3938+}
3939+
3940+QObject *
3941+ShellManager::hudShell() const
3942+{
3943+ return d->m_shellWithHud;
3944+}
3945+
3946+int
3947+ShellManager::hudScreen() const
3948+{
3949+ if (d->m_shellWithHud != NULL) {
3950+ return d->m_shellWithHud->screen()->screen();
3951+ } else {
3952+ return -1;
3953+ }
3954+}
3955+
3956+/*------------------ Hotkeys Handling -----------------------*/
3957+
3958+void
3959+ShellManager::onAltF1Pressed()
3960+{
3961+ ShellDeclarativeView * activeShell = d->activeShell(ShellManagerPrivate::ActiveShellLauncherRelatedUse);
3962+ if (activeShell) {
3963+ if (dashActive()) {
3964+ // focus the launcher instead of the dash
3965+ setDashActive(false);
3966+ Q_EMIT activeShell->launcherFocusRequested();
3967+ } else {
3968+ activeShell->toggleLauncher();
3969+ }
3970+ }
3971+}
3972+
3973+void
3974+ShellManager::onAltF2Pressed()
3975+{
3976+ ShellDeclarativeView * activeShell = d->activeShell(ShellManagerPrivate::ActiveShellLauncherRelatedUse);
3977+ if (activeShell) {
3978+ d->moveDashToShell(activeShell);
3979+ Q_EMIT dashActivateLens(COMMANDS_LENS_ID);
3980+ }
3981+}
3982+
3983+void
3984+ShellManager::onNumericHotkeyPressed()
3985+{
3986+ Hotkey* hotkey = qobject_cast<Hotkey*>(sender());
3987+ if (hotkey) {
3988+ ShellDeclarativeView * activeShell = d->activeShell(ShellManagerPrivate::ActiveShellLauncherRelatedUse);
3989+ if (activeShell) {
3990+ /* Shortcuts from 1 to 9 should activate the items with index
3991+ from 1 to 9 (index 0 being the so-called "BFB" or Dash launcher).
3992+ Shortcut for 0 should activate item with index 10.
3993+ In other words, the indexes are activated in the same order as
3994+ the keys appear on a standard keyboard. */
3995+ Qt::Key key = hotkey->key();
3996+ if (key >= Qt::Key_1 && key <= Qt::Key_9) {
3997+ int index = key - Qt::Key_0;
3998+ if (hotkey->modifiers() & Qt::ShiftModifier) {
3999+ Q_EMIT activeShell->newInstanceShortcutPressed(index);
4000+ } else {
4001+ Q_EMIT activeShell->activateShortcutPressed(index);
4002+ }
4003+ } else if (key == Qt::Key_0) {
4004+ if (hotkey->modifiers() & Qt::ShiftModifier) {
4005+ Q_EMIT activeShell->newInstanceShortcutPressed(10);
4006+ } else {
4007+ Q_EMIT activeShell->activateShortcutPressed(10);
4008+ }
4009+ }
4010+ }
4011+ }
4012+}
4013+
4014+unsigned int ShellManager::lastFocusedWindow() const
4015+{
4016+ return d->m_last_focused_window;
4017+}
4018+
4019+/* Obtaining & Discarding Keyboard Focus for Window on Demand
4020+ *
4021+ * In the X world, activating a window means to give it the input (keyboard)
4022+ * focus. When a new window opens, X usually makes it active immediately.
4023+ * Clicking on a window makes it active too.
4024+ *
4025+ * Qt does not have the capability to explicitly ask the window manager to
4026+ * make an existing window active - setFocus() only forwards input focus to
4027+ * whatever QWidget you specify.
4028+ *
4029+ * De-Activating a window is not possible with X (and hence with Qt). So
4030+ * we work-around this by remembering which application is active prior to
4031+ * stealing focus, and then Re-Activating it when we're finished. This is
4032+ * not guaranteed to succeed, as previous window may have closed.
4033+ *
4034+ * The following methods deal with these tasks. Note that when the window
4035+ * has been activated (deactivated), Qt will realise it has obtained (lost)
4036+ * focus and act appropriately.
4037+ */
4038+
4039+/* Save WId of window with keyboard focus to m_last_focused_window */
4040+void ShellManagerPrivate::saveActiveWindow()
4041+{
4042+ /* Using Bamf here, 'cause XGetFocusInputFocus returned a XId
4043+ different by 1, which then could not be used with Bamf to
4044+ get the application. The change does not result in any functional
4045+ differences, though. */
4046+ const BamfWindow* bamf_active_window = BamfMatcher::get_default().active_window();
4047+
4048+ /* Bamf can return a null active window - example case is just after
4049+ login when no application has been yet been started. */
4050+ const WId active_window = bamf_active_window != NULL ? bamf_active_window->xid() : None;
4051+
4052+ bool notAShell = true;
4053+ Q_FOREACH(ShellDeclarativeView * shell, m_viewList) {
4054+ notAShell = notAShell && active_window != shell->effectiveWinId();
4055+ }
4056+
4057+ if (notAShell && active_window != m_last_focused_window) {
4058+ m_last_focused_window = active_window;
4059+ Q_EMIT q->lastFocusedWindowChanged(m_last_focused_window);
4060+ }
4061+}
4062+
4063+/* Ask Window Manager to activate this window and hence get keyboard focus */
4064+void ShellManager::forceActivateShell(ShellDeclarativeView *shell)
4065+{
4066+ // Save reference to window with current keyboard focus
4067+ if( d->m_last_focused_window == None ){
4068+ d->saveActiveWindow();
4069+ }
4070+
4071+ // Show this window by giving it keyboard focus
4072+ Unity2DDeclarativeView::forceActivateWindow(shell->effectiveWinId(), shell);
4073+}
4074+
4075+/* Ask Window Manager to deactivate this window - not guaranteed to succeed. */
4076+void ShellManager::forceDeactivateShell(ShellDeclarativeView *shell)
4077+{
4078+ if( d->m_last_focused_window == None ){
4079+ UQ_WARNING << "No previously focused window found, use mouse to select window.";
4080+ return;
4081+ }
4082+
4083+ // What if previously focused window closed while we we had focus? Check if window
4084+ // exists by seeing if it has attributes.
4085+ XWindowAttributes attributes;
4086+ const int status = XGetWindowAttributes(QX11Info::display(), d->m_last_focused_window, &attributes);
4087+ if ( status == BadWindow ){
4088+ UQ_WARNING << "Previously focused window has gone, use mouse to select window.";
4089+ return;
4090+ }
4091+
4092+ // Show this window by giving it keyboard focus
4093+ Unity2DDeclarativeView::forceActivateWindow(d->m_last_focused_window);
4094+
4095+ d->m_last_focused_window = None;
4096+ Q_EMIT lastFocusedWindowChanged(d->m_last_focused_window);
4097+}
4098
4099=== added file 'shell/app/shellmanager.h'
4100--- shell/app/shellmanager.h 1970-01-01 00:00:00 +0000
4101+++ shell/app/shellmanager.h 2012-03-15 09:01:33 +0000
4102@@ -0,0 +1,128 @@
4103+/*
4104+ * This file is part of unity-2d
4105+ *
4106+ * Copyright 2010 Canonical Ltd.
4107+ *
4108+ * This program is free software; you can redistribute it and/or modify
4109+ * it under the terms of the GNU General Public License as published by
4110+ * the Free Software Foundation; version 3.
4111+ *
4112+ * This program is distributed in the hope that it will be useful,
4113+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4114+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4115+ * GNU General Public License for more details.
4116+ *
4117+ * You should have received a copy of the GNU General Public License
4118+ * along with this program. If not, see <http://www.gnu.org/licenses/>
4119+ */
4120+#ifndef SHELLMANAGER_H
4121+#define SHELLMANAGER_H
4122+
4123+#include <QObject>
4124+struct ShellManagerPrivate;
4125+
4126+class ShellDeclarativeView;
4127+
4128+class QUrl;
4129+
4130+class ShellManager : public QObject
4131+{
4132+ Q_OBJECT
4133+
4134+ Q_ENUMS(DashMode)
4135+
4136+ Q_PROPERTY(bool dashActive READ dashActive WRITE setDashActive NOTIFY dashActiveChanged)
4137+ Q_PROPERTY(DashMode dashMode READ dashMode WRITE setDashMode NOTIFY dashModeChanged)
4138+ Q_PROPERTY(QString dashActiveLens READ dashActiveLens WRITE setDashActiveLens NOTIFY dashActiveLensChanged)
4139+ Q_PROPERTY(bool dashHaveCustomHomeShortcuts READ dashHaveCustomHomeShortcuts)
4140+ Q_PROPERTY(QObject *dashShell READ dashShell NOTIFY dashShellChanged)
4141+ Q_PROPERTY(int dashScreen READ dashScreen NOTIFY dashScreenChanged)
4142+ Q_PROPERTY(bool dashAlwaysFullScreen READ dashAlwaysFullScreen NOTIFY dashAlwaysFullScreenChanged)
4143+ Q_PROPERTY(bool superKeyHeld READ superKeyHeld NOTIFY superKeyHeldChanged)
4144+ Q_PROPERTY(bool hudActive READ hudActive WRITE setHudActive NOTIFY hudActiveChanged)
4145+ Q_PROPERTY(QObject *hudShell READ hudShell NOTIFY hudShellChanged)
4146+ Q_PROPERTY(int hudScreen READ hudScreen NOTIFY hudScreenChanged)
4147+ Q_PROPERTY(unsigned int lastFocusedWindow READ lastFocusedWindow NOTIFY lastFocusedWindowChanged)
4148+
4149+public:
4150+ enum DashMode {
4151+ DesktopMode,
4152+ FullScreenMode
4153+ };
4154+
4155+ ShellManager(const QUrl &sourceFileUrl, QObject* parent = 0);
4156+ ~ShellManager();
4157+
4158+ bool dashActive() const;
4159+ Q_SLOT void setDashActive(bool active);
4160+
4161+ DashMode dashMode() const;
4162+ Q_INVOKABLE void setDashMode(DashMode);
4163+
4164+ const QString& dashActiveLens() const;
4165+ Q_INVOKABLE void setDashActiveLens(const QString& activeLens);
4166+
4167+ bool dashHaveCustomHomeShortcuts() const;
4168+
4169+ QObject *dashShell() const;
4170+
4171+ int dashScreen() const;
4172+
4173+ bool dashAlwaysFullScreen() const;
4174+
4175+ bool superKeyHeld() const;
4176+
4177+ bool hudActive() const;
4178+ void setHudActive(bool active);
4179+
4180+ QObject *hudShell() const;
4181+
4182+ int hudScreen() const;
4183+
4184+ unsigned int lastFocusedWindow() const;
4185+
4186+ void forceActivateShell(ShellDeclarativeView *shell);
4187+ void forceDeactivateShell(ShellDeclarativeView *shell);
4188+
4189+Q_SIGNALS:
4190+ void dashActiveChanged(bool);
4191+ void dashModeChanged(DashMode);
4192+ void dashActiveLensChanged(const QString&);
4193+ void dashShellChanged(QObject *shell);
4194+ void dashScreenChanged(int screen);
4195+ void dashAlwaysFullScreenChanged(bool dashAlwaysFullScreen);
4196+ void superKeyHeldChanged(bool superKeyHeld);
4197+ void hudActiveChanged();
4198+ void hudShellChanged(QObject *shell);
4199+ void hudScreenChanged(int screen);
4200+ void lastFocusedWindowChanged(unsigned int wid);
4201+
4202+ void activeWorkspaceChanged();
4203+ void dashActivateHome();
4204+ void dashActivateLens(const QString& lensId);
4205+ void toggleHud();
4206+
4207+private Q_SLOTS:
4208+ void onScreenCountChanged(int);
4209+
4210+ void updateSuperKeyMonitoring();
4211+
4212+ void onAltF1Pressed();
4213+ void onAltF2Pressed();
4214+ void onNumericHotkeyPressed();
4215+ void toggleDashRequested();
4216+ void toggleHudRequested();
4217+
4218+ void updateDashAlwaysFullScreen();
4219+
4220+ void onActiveWorkspaceChanged();
4221+
4222+private:
4223+ Q_DISABLE_COPY(ShellManager)
4224+ ShellManagerPrivate * const d;
4225+
4226+friend class DashDBus;
4227+friend struct ShellManagerPrivate;
4228+};
4229+
4230+#endif // SHELLMANAGER_H
4231
4232=== modified file 'shell/common/Background.qml'
4233--- shell/common/Background.qml 2012-03-13 18:54:14 +0000
4234+++ shell/common/Background.qml 2012-03-15 09:01:33 +0000
4235@@ -27,6 +27,15 @@
4236 property bool fullscreen: false
4237 property int bottomBorderThickness
4238 property int rightBorderThickness
4239+ property bool activeTriggerHelper: true
4240+ property bool reallyActive: active && activeTriggerHelper
4241+ property variant view: undefined
4242+
4243+ function trigger()
4244+ {
4245+ activeTriggerHelper = false
4246+ activeTriggerHelper = true
4247+ }
4248
4249 /* Avoid redraw at rendering */
4250 effect: CacheEffect {}
4251@@ -49,7 +58,7 @@
4252
4253 /* Use an image of the root window which essentially is a
4254 capture of the entire screen */
4255- source: active ? "image://window/root" : ""
4256+ source: reallyActive ? "image://window/root" : ""
4257 cache: false
4258
4259 fillMode: Image.PreserveAspectCrop
4260@@ -57,7 +66,8 @@
4261 /* Place the screenshot of the desktop background on top of the desktop background,
4262 no matter where the DeclarativeView or the parent object are placed.
4263 */
4264- property variant origin: parent.mapFromItem(null, -declarativeView.globalPosition.x, -declarativeView.globalPosition.y)
4265+ property variant origin: parent.mapFromItem(null, background.view != undefined ? -background.view.globalPosition.x : -declarativeView.globalPosition.x,
4266+ background.view != undefined ? -background.view.globalPosition.y : -declarativeView.globalPosition.y)
4267 x: origin.x
4268 y: origin.y
4269 }
4270
4271=== modified file 'shell/common/VisibilityController.qml'
4272--- shell/common/VisibilityController.qml 2012-02-15 11:55:06 +0000
4273+++ shell/common/VisibilityController.qml 2012-03-15 09:01:33 +0000
4274@@ -45,7 +45,7 @@
4275 var stack = controller.forceVisibleStack
4276 var wasEmpty = Utils.hashEmpty(stack)
4277
4278- if (forceHidden) console.log("WARNING: beginForceVisible for id \"" + id +
4279+ if (forceHidden) console.log("DEBUG: beginForceVisible for id \"" + id +
4280 "\" called when forceHidden still true")
4281
4282 if (stack[id]) stack[id] += 1
4283@@ -64,7 +64,7 @@
4284 if (stack[id]) {
4285 stack[id] -= 1
4286 if (stack[id] === 0) delete stack[id]
4287- } else console.log("WARNING: endForceVisible for id \"" + id +
4288+ } else console.log("DEBUG: endForceVisible for id \"" + id +
4289 "\" called without matching startForceVisible")
4290
4291 controller.forceVisibleStack = stack
4292@@ -78,7 +78,7 @@
4293 var stack = controller.forceHiddenStack
4294 var wasEmpty = Utils.hashEmpty(stack)
4295
4296- if (forceVisible) console.log("WARNING: beginForceHidden for id \"" + id +
4297+ if (forceVisible) console.log("DEBUG: beginForceHidden for id \"" + id +
4298 "\" called when forceVisible still true")
4299
4300 if (stack[id]) stack[id] += 1
4301@@ -97,7 +97,7 @@
4302 if (stack[id]) {
4303 stack[id] -= 1
4304 if (stack[id] === 0) delete stack[id]
4305- } else console.log("WARNING: endForceHidden for id \"" + id +
4306+ } else console.log("DEBUG: endForceHidden for id \"" + id +
4307 "\" called without matching startForceHidden")
4308
4309 controller.forceHiddenStack = stack
4310
4311=== modified file 'shell/common/visibilityBehaviors/IntelliHideBehavior.qml'
4312--- shell/common/visibilityBehaviors/IntelliHideBehavior.qml 2012-03-05 14:06:58 +0000
4313+++ shell/common/visibilityBehaviors/IntelliHideBehavior.qml 2012-03-15 09:01:33 +0000
4314@@ -41,12 +41,12 @@
4315 monitoredArea: {
4316 if (intellihide.target) {
4317 if (Utils.isLeftToRight()) {
4318- return Qt.rect(0,
4319+ return Qt.rect(declarativeView.screen.geometry.x,
4320 intellihide.target.y,
4321 intellihide.target.width,
4322 intellihide.target.height)
4323 } else {
4324- return Qt.rect(declarativeView.screen.availableGeometry.width - intellihide.target.width,
4325+ return Qt.rect(declarativeView.screen.geometry.x + declarativeView.screen.availableGeometry.width - intellihide.target.width,
4326 intellihide.target.y,
4327 intellihide.target.width,
4328 intellihide.target.height)
4329
4330=== modified file 'shell/dash/Dash.qml'
4331--- shell/dash/Dash.qml 2012-03-13 18:54:14 +0000
4332+++ shell/dash/Dash.qml 2012-03-15 09:01:33 +0000
4333@@ -31,48 +31,60 @@
4334 LayoutMirroring.childrenInherit: true
4335
4336 property variant currentPage
4337- /* FIXME: 'active' property exactly mirrors 'declarativeView.dashActive'.
4338+ /* FIXME: 'active' property exactly mirrors 'shellManager.dashActive'.
4339 The final goal is to transition to using exclusively the QML 'active' property
4340- and drop the C++ 'declarativeView.dashActive'.
4341+ and drop the C++ 'shellManager.dashActive'.
4342 */
4343 property variant active
4344- /* The following way of mirroring the values of 'declarativeView.dashActive'
4345+ /* The following way of mirroring the values of 'shellManager.dashActive'
4346 and 'active' works now and QML does not see it as a binding loop but we
4347 cannot count on it long term.
4348 */
4349 Binding {
4350- target: declarativeView
4351+ target: shellManager
4352 property: "dashActive"
4353 value: dash.active
4354 }
4355 Binding {
4356 target: dash
4357 property: "active"
4358- value: declarativeView.dashActive
4359- }
4360-
4361- onActiveChanged: if (dash.active) declarativeView.forceActivateWindow()
4362+ value: shellManager.dashActive
4363+ }
4364+
4365+ onActiveChanged: if (dash.active) shellManager.dashShell.forceActivateWindow()
4366+
4367+ Connections {
4368+ target: shellManager
4369+ onDashShellChanged: {
4370+ if (dash.active) {
4371+ background.trigger()
4372+ shellManager.dashShell.forceActivateWindow()
4373+ }
4374+ }
4375+ }
4376
4377 property variant queuedLensId
4378
4379- Binding {
4380- target: declarativeView
4381- property: "expanded"
4382- value: (currentPage && currentPage.expanded != undefined) ? currentPage.expanded : true
4383- }
4384+ property bool expanded: (currentPage && currentPage.expanded != undefined) ? currentPage.expanded : true
4385
4386 Binding {
4387- target: declarativeView
4388+ target: shellManager
4389 property: "dashMode"
4390- value: declarativeView.dashAlwaysFullScreen || dash2dConfiguration.fullScreen ?
4391- ShellDeclarativeView.FullScreenMode : ShellDeclarativeView.DesktopMode
4392- }
4393-
4394- Connections {
4395- target: declarativeView
4396-
4397- onActivateHome: activateHome()
4398- onActivateLens: activateLens(lensId)
4399+ value: shellManager.alwaysFullScreen || dash2dConfiguration.fullScreen ?
4400+ ShellManager.FullScreenMode : ShellManager.DesktopMode
4401+ }
4402+
4403+ Connections {
4404+ target: shellManager
4405+
4406+ onDashActivateHome: activateHome()
4407+ onDashActivateLens: activateLens(lensId)
4408+ }
4409+
4410+ Connections {
4411+ target: shellManager.dashShell
4412+
4413+ onFocusChanged: if (!shellManager.dashShell.focus) active = false
4414 }
4415
4416 function activatePage(page) {
4417@@ -103,7 +115,7 @@
4418 for (var i=0; i<lenses.rowCount(); i++) {
4419 lenses.get(i).viewType = Lens.Hidden
4420 }
4421- declarativeView.activeLens = ""
4422+ shellManager.dashActiveLens = ""
4423 }
4424
4425 SpreadMonitor {
4426@@ -125,7 +137,7 @@
4427 return
4428 }
4429
4430- if (lensId == declarativeView.activeLens && dash.active) {
4431+ if (lensId == shellManager.dashActiveLens && dash.active) {
4432 /* we don't need to activate the lens, just show its UI */
4433 buildLensPage(lens)
4434 return
4435@@ -147,13 +159,13 @@
4436 }
4437
4438 buildLensPage(lens)
4439- declarativeView.activeLens = lens.id
4440+ shellManager.dashActiveLens = lens.id
4441 dash.active = true
4442 }
4443
4444 function activateHome() {
4445 if (spreadMonitor.shown) return
4446- if (declarativeView.haveCustomHomeShortcuts) {
4447+ if (shellManager.dashHaveCustomHomeShortcuts) {
4448 for (var i=0; i<lenses.rowCount(); i++) {
4449 lenses.get(i).viewType = Lens.Hidden
4450 }
4451@@ -161,7 +173,7 @@
4452 /* Take advantage of the fact that the loaded qml is local and setting
4453 the source loads it immediately making pageLoader.item valid */
4454 activatePage(pageLoader.item)
4455- declarativeView.activeLens = ""
4456+ shellManager.dashActiveLens = ""
4457 dash.active = true
4458 } else {
4459 activateLens("home.lens")
4460@@ -222,7 +234,8 @@
4461 anchors.fill: parent
4462
4463 active: dash.active
4464- fullscreen: declarativeView.dashMode != ShellDeclarativeView.DesktopMode
4465+ fullscreen: shellManager.dashMode != ShellManager.DesktopMode
4466+ view: shellManager.dashShell
4467 }
4468
4469 Item {
4470@@ -289,7 +302,7 @@
4471 KeyNavigation.left: search_entry
4472
4473 /* FilterPane is only to be displayed for lenses, not in the home page or Alt+F2 Run page */
4474- visible: declarativeView.activeLens != "home.lens" && declarativeView.activeLens != "" && declarativeView.activeLens != "commands.lens"
4475+ visible: shellManager.dashActiveLens != "home.lens" && shellManager.dashActiveLens != "" && shellManager.dashActiveLens != "commands.lens"
4476 lens: visible && currentPage != undefined ? currentPage.model : undefined
4477
4478 anchors.top: search_entry.anchors.top
4479@@ -342,33 +355,31 @@
4480 anchors.left: parent.left
4481 anchors.right: parent.right
4482 height: 44
4483- visible: declarativeView.expanded
4484+ visible: expanded
4485 }
4486 }
4487
4488 property int desktopCollapsedHeight: 115
4489 property int desktopExpandedHeight: 615
4490 property int desktopWidth: 996
4491- property int fullscreenWidth: declarativeView.screen.availableGeometry.width
4492- property int fullscreenHeight: declarativeView.screen.availableGeometry.height
4493
4494 states: [
4495 State {
4496 name: "desktop"
4497- when: declarativeView.dashMode == ShellDeclarativeView.DesktopMode
4498+ when: shellManager.dashMode == ShellManager.DesktopMode
4499 PropertyChanges {
4500 target: dash
4501 width: desktopWidth
4502- height: declarativeView.expanded ? desktopExpandedHeight : desktopCollapsedHeight
4503+ height: expanded ? desktopExpandedHeight : desktopCollapsedHeight
4504 }
4505 },
4506 State {
4507 name: "fullscreen"
4508- when: declarativeView.dashMode == ShellDeclarativeView.FullScreenMode
4509+ when: shellManager.dashMode == ShellManager.FullScreenMode
4510 PropertyChanges {
4511 target: dash
4512- width: fullscreenWidth
4513- height: fullscreenHeight
4514+ width: shellManager.dashShell != undefined ? shellManager.dashShell.screen.panelsFreeGeometry.width : 0
4515+ height: shellManager.dashShell != undefined ? shellManager.dashShell.screen.panelsFreeGeometry.height : 0
4516 }
4517 }
4518 ]
4519
4520=== modified file 'shell/dash/Home.qml'
4521--- shell/dash/Home.qml 2012-03-05 17:20:00 +0000
4522+++ shell/dash/Home.qml 2012-03-15 09:01:33 +0000
4523@@ -89,7 +89,7 @@
4524 verticalAlignment: Text.AlignVCenter
4525 }
4526
4527- opacity: (!expanded && declarativeView.dashMode == ShellDeclarativeView.DesktopMode) ? 1 : 0
4528+ opacity: (!expanded && shellManager.dashMode == ShellManager.DesktopMode) ? 1 : 0
4529 Behavior on opacity {NumberAnimation {duration: 100}}
4530
4531 onClicked: {
4532@@ -137,7 +137,7 @@
4533 id: shortcuts
4534
4535 focus: !globalSearchActive
4536- opacity: (!globalSearchActive && (shortcutsActive || declarativeView.dashMode == ShellDeclarativeView.FullScreenMode)) ? 1 : 0
4537+ opacity: (!globalSearchActive && (shortcutsActive || shellManager.dashMode == ShellManager.FullScreenMode)) ? 1 : 0
4538 anchors.horizontalCenter: parent.horizontalCenter
4539 anchors.verticalCenter: parent.verticalCenter
4540
4541@@ -173,7 +173,7 @@
4542 source: "../common/artwork/cross.png"
4543 }
4544
4545- opacity: (expanded && declarativeView.dashMode == ShellDeclarativeView.DesktopMode) ? 1 : 0
4546+ opacity: (expanded && shellManager.dashMode == ShellManager.DesktopMode) ? 1 : 0
4547 Behavior on opacity {NumberAnimation {duration: 100}}
4548
4549 onClicked: shortcutsActive = false
4550
4551=== modified file 'shell/dash/LensBar.qml'
4552--- shell/dash/LensBar.qml 2012-03-06 13:05:19 +0000
4553+++ shell/dash/LensBar.qml 2012-03-15 09:01:33 +0000
4554@@ -108,7 +108,7 @@
4555 }
4556 active: {
4557 /* we need this in order to activate the arrow when using a custom shortcuts file */
4558- if (item.id == "home.lens" && declarativeView.activeLens == "") {
4559+ if (item.id == "home.lens" && shellManager.dashActiveLens == "") {
4560 return true
4561 }
4562 return item.viewType == Lens.LensView
4563
4564=== modified file 'shell/hud/Hud.qml'
4565--- shell/hud/Hud.qml 2012-02-24 11:55:38 +0000
4566+++ shell/hud/Hud.qml 2012-03-15 09:01:33 +0000
4567@@ -45,7 +45,7 @@
4568
4569 WindowInfo {
4570 id: activeWindow
4571- contentXid: declarativeView.lastFocusedWindow
4572+ contentXid: shellManager.lastFocusedWindow
4573 }
4574
4575 SpreadMonitor {
4576@@ -55,7 +55,7 @@
4577
4578 onActiveChanged: {
4579 if (active) {
4580- declarativeView.forceActivateWindow()
4581+ shellManager.hudShell.forceActivateWindow()
4582 resultList.focus = true
4583 } else {
4584 hudModel.endSearch
4585@@ -64,9 +64,14 @@
4586 }
4587
4588 Connections {
4589- target: declarativeView
4590+ target: shellManager
4591
4592 onToggleHud: toggleHud()
4593+ onHudShellChanged: {
4594+ if (active) {
4595+ background.trigger()
4596+ }
4597+ }
4598 }
4599
4600 Keys.onPressed: {
4601@@ -75,12 +80,12 @@
4602
4603 function toggleHud() {
4604 if (spread.shown) return
4605- if (active) declarativeView.forceDeactivateWindow()
4606+ if (active) shellManager.hudShell.forceDeactivateWindow()
4607 active = !active
4608 }
4609
4610 function executeResult(resultId) {
4611- declarativeView.forceDeactivateWindow()
4612+ shellManager.hudShell.forceDeactivateWindow()
4613 hudModel.executeResult(resultId)
4614 active = false
4615 }
4616@@ -93,6 +98,7 @@
4617 anchors.fill: parent
4618
4619 active: hud.active
4620+ view: shellManager.hudShell
4621 }
4622
4623 Item {
4624
4625=== modified file 'shell/launcher/Launcher.qml'
4626--- shell/launcher/Launcher.qml 2012-03-13 18:54:14 +0000
4627+++ shell/launcher/Launcher.qml 2012-03-15 09:01:33 +0000
4628@@ -27,31 +27,9 @@
4629
4630 signal barrierTriggered
4631
4632- property bool shown
4633 property bool showMenus: true
4634
4635 property bool containsMouse: declarativeView.monitoredAreaContainsMouse
4636- property variant barrierP1
4637- property variant barrierP2
4638- property variant barrierTriggerZoneP1
4639- property variant barrierTriggerZoneP2
4640-
4641- PointerBarrier {
4642- id: barrier
4643- triggerDirection: Utils.isLeftToRight() ? PointerBarrier.TriggerFromRight : PointerBarrier.TriggerFromLeft
4644- triggerZoneEnabled: !shown
4645- p1: barrierP1
4646- p2: barrierP2
4647- triggerZoneP1: barrierTriggerZoneP1
4648- triggerZoneP2: barrierTriggerZoneP2
4649- threshold: launcher2dConfiguration.edgeStopVelocity
4650- maxVelocityMultiplier: launcher2dConfiguration.edgeResponsiveness
4651- decayRate: launcher2dConfiguration.edgeDecayrate
4652- triggerPressure: launcher2dConfiguration.edgeRevealPressure
4653- breakPressure: launcher2dConfiguration.edgeOvercomePressure
4654-
4655- onTriggered: launcher.barrierTriggered()
4656- }
4657
4658 function hideMenu() {
4659 if (main.visibleMenu !== undefined) {
4660@@ -87,8 +65,8 @@
4661 Rectangle {
4662 Accessible.name: "background"
4663 anchors.fill: parent
4664- anchors.rightMargin: Utils.isLeftToRight() && !declarativeView.dashActive ? border.width : 0
4665- anchors.leftMargin: Utils.isRightToLeft() && !declarativeView.dashActive ? border.width : 0
4666+ anchors.rightMargin: Utils.isLeftToRight() && !border.visible ? border.width : 0
4667+ anchors.leftMargin: Utils.isRightToLeft() && !border.visible ? border.width : 0
4668 color: "black"
4669 opacity: 0.66
4670 visible: desktop.isCompositingManagerRunning
4671@@ -102,7 +80,7 @@
4672 height: parent.height
4673 anchors.right: Utils.isLeftToRight() ? parent.right : undefined
4674 anchors.left: Utils.isLeftToRight() ? undefined : parent.left
4675- visible: declarativeView.dashActive
4676+ visible: shellManager.dashActive && shellManager.dashShell == declarativeView
4677 source: "artwork/border.png"
4678 fillMode: Image.Stretch
4679 }
4680@@ -114,7 +92,7 @@
4681 height: parent.height
4682 anchors.right: Utils.isLeftToRight() ? border.anchors.right : undefined
4683 anchors.left: Utils.isLeftToRight() ? undefined : border.anchors.left
4684- visible: !declarativeView.dashActive
4685+ visible: !border.visible
4686
4687 color: "white"
4688 opacity: 0.15
4689@@ -216,7 +194,7 @@
4690
4691 BfbModel {
4692 id: bfbModel
4693- dashView: declarativeView
4694+ dashManager: shellManager
4695 }
4696
4697 ApplicationsList {
4698
4699=== modified file 'shell/launcher/LauncherItem.qml'
4700--- shell/launcher/LauncherItem.qml 2012-02-15 13:26:26 +0000
4701+++ shell/launcher/LauncherItem.qml 2012-03-15 09:01:33 +0000
4702@@ -65,6 +65,7 @@
4703 property alias urgentAnimation: urgentAnimation
4704 property bool running: false
4705 property bool active: false
4706+ property bool activeOnThisScreen: false
4707 property bool urgent: false
4708 property bool launching: false
4709 property alias interactive: mouse.enabled
4710@@ -138,7 +139,7 @@
4711 mirror: Utils.isRightToLeft()
4712
4713 source: "image://blended/%1color=%2alpha=%3"
4714- .arg("launcher/artwork/launcher_arrow_rtl.png")
4715+ .arg("launcher/artwork/launcher_arrow_" + (activeOnThisScreen ? "" : "outline_" ) + "rtl.png")
4716 .arg("lightgrey")
4717 .arg(1.0)
4718
4719
4720=== modified file 'shell/launcher/LauncherList.qml'
4721--- shell/launcher/LauncherList.qml 2012-02-24 12:48:13 +0000
4722+++ shell/launcher/LauncherList.qml 2012-03-15 09:01:33 +0000
4723@@ -93,11 +93,12 @@
4724 }
4725
4726 function updatePips() {
4727- if (item.belongsToDifferentWorkspace()) {
4728+ var windowCount = item.windowsOnCurrentWorkspaceScreen(launcher2dConfiguration.onlyOneLauncher ? -1 : declarativeView.screen.screen);
4729+ if (windowCount == 0 && item.windowCount != 0) {
4730 launcherItem.pips = 1
4731 launcherItem.pipSource = "launcher/artwork/launcher_arrow_outline_ltr.png";
4732 } else {
4733- launcherItem.pips = Math.min(item.windowCount, 3)
4734+ launcherItem.pips = Math.min(windowCount, 3)
4735 launcherItem.pipSource = ("launcher/artwork/launcher_" + ((pips <= 1) ? "arrow" : "pip") + "_ltr.png")
4736 }
4737 }
4738@@ -113,9 +114,9 @@
4739 icon: item.icon != "" ? "image://icons/" + item.icon : "image://icons/unknown"
4740 running: item.running
4741 active: item.active
4742+ activeOnThisScreen: item.activeScreen == declarativeView.screen.screen
4743 urgent: item.urgent
4744 launching: item.launching
4745- pips: Math.min(item.windowCount, 3)
4746
4747 counter: item.counter
4748 counterVisible: item.counterVisible
4749@@ -125,7 +126,7 @@
4750 emblemVisible: item.emblemVisible
4751
4752 /* Launcher of index 0 is the so-called BFB or Dash launcher */
4753- shortcutVisible: declarativeView.superKeyHeld &&
4754+ shortcutVisible: shellManager.superKeyHeld &&
4755 ((item.toString().indexOf("Application") == 0 && index > 0 && index <= 10) ||
4756 item.shortcutKey != 0)
4757 shortcutText: {
4758@@ -157,7 +158,7 @@
4759 list.visibleMenu.hide()
4760 }
4761 list.visibleMenu = item.menu
4762- item.menu.show(width - 5, declarativeView.globalPosition.y + list.y - list.contentY +
4763+ item.menu.show(declarativeView.globalPosition.x + width - 5, declarativeView.globalPosition.y + list.y - list.contentY +
4764 y + height - selectionOutlineSize / 2)
4765 }
4766
4767@@ -262,9 +263,10 @@
4768
4769 function setIconGeometry() {
4770 if (running) {
4771+ var screen = launcher2dConfiguration.onlyOneLauncher ? -1 : declarativeView.screen.screen
4772 item.setIconGeometry(x + declarativeView.globalPosition.x,
4773 y + declarativeView.globalPosition.y,
4774- width, height)
4775+ width, height, screen)
4776 }
4777 }
4778
4779@@ -304,11 +306,18 @@
4780
4781 Connections {
4782 target: item
4783- onWindowAdded: item.setIconGeometry(x + declarativeView.globalPosition.x,
4784- y + declarativeView.globalPosition.y,
4785- width, height, xid)
4786+ onWindowAdded: {
4787+ var screen = launcher2dConfiguration.onlyOneLauncher ? -1 : declarativeView.screen.screen
4788+ item.setIconGeometry(x + declarativeView.globalPosition.x,
4789+ y + declarativeView.globalPosition.y,
4790+ width, height, screen, xid)
4791+ }
4792 onWindowCountChanged: updatePips()
4793 onWindowWorkspaceChanged: updatePips()
4794+ onWindowGeometryChanged: {
4795+ updatePips()
4796+ setIconGeometry()
4797+ }
4798 /* Not all items are applications. */
4799 ignoreUnknownSignals: true
4800 }
4801@@ -353,7 +362,7 @@
4802 }
4803
4804 Connections {
4805- target: declarativeView
4806+ target: shellManager
4807 onActiveWorkspaceChanged: updatePips()
4808 }
4809 Component.onCompleted: updatePips()
4810
4811=== modified file 'shell/launcher/LauncherLoader.qml'
4812--- shell/launcher/LauncherLoader.qml 2012-03-06 18:06:03 +0000
4813+++ shell/launcher/LauncherLoader.qml 2012-03-15 09:01:33 +0000
4814@@ -22,10 +22,22 @@
4815 import "../common/utils.js" as Utils
4816
4817 Loader {
4818+ property bool onlyOneLauncher: true
4819+ property bool loadLauncher: !onlyOneLauncher || declarativeView.screen.screen == 0
4820+
4821 id: launcherLoader
4822- source: "Launcher.qml"
4823+ source: loadLauncher ? "Launcher.qml" : ""
4824 property variant visibilityController: visibilityController
4825 onLoaded: item.focus = true
4826+ property bool launcherInHideMode: Utils.clamp(launcher2dConfiguration.hideMode, 0, 2) != 0
4827+
4828+ Timer {
4829+ // FIXME We need this timer because otherwise changing from
4830+ // onlyOneLauncher to !onlyOneLauncher gets us in what seems to be a dbus deadlock
4831+ id: launcher2dConfigurationWorkaround
4832+ interval: 1
4833+ onTriggered: launcherLoader.onlyOneLauncher = launcher2dConfiguration.onlyOneLauncher
4834+ }
4835
4836 VisibilityController {
4837 id: visibilityController
4838@@ -52,7 +64,7 @@
4839 Binding {
4840 target: declarativeView
4841 property: "monitoredArea"
4842- value: Qt.rect(launcherLoader.x, launcherLoader.item.y, launcherLoader.item.width, launcherLoader.item.height)
4843+ value: loadLauncher ? Qt.rect(launcherLoader.x, launcherLoader.item.y, launcherLoader.item.width, launcherLoader.item.height) : Qt.rect(0, 0, 0, 0)
4844 when: launcherBehavior.status == Loader.Ready && !launcherLoaderXAnimation.running
4845 }
4846
4847@@ -75,16 +87,19 @@
4848 }
4849
4850 Connections {
4851- target: declarativeView
4852+ target: shellManager
4853 onSuperKeyHeldChanged: {
4854 if (superKeyHeld) visibilityController.beginForceVisible()
4855 else visibilityController.endForceVisible()
4856 }
4857 }
4858
4859- Binding {
4860- target: launcherLoader.item
4861- property: "shown"
4862- value: visibilityController.shown
4863+ Connections {
4864+ target: launcher2dConfiguration
4865+ onOnlyOneLauncherChanged: {
4866+ launcher2dConfigurationWorkaround.start()
4867+ }
4868 }
4869+
4870+ Component.onCompleted: launcherLoader.onlyOneLauncher = launcher2dConfiguration.onlyOneLauncher
4871 }
4872
4873=== modified file 'shell/launcher/ListViewDragAndDrop.qml'
4874--- shell/launcher/ListViewDragAndDrop.qml 2011-11-11 10:19:14 +0000
4875+++ shell/launcher/ListViewDragAndDrop.qml 2012-03-15 09:01:33 +0000
4876@@ -35,6 +35,8 @@
4877
4878 /* list index of the tile being dragged */
4879 property int draggedTileIndex
4880+ /* first list index of the tile being dragged */
4881+ property int firstDraggedTileIndex
4882 /* id (desktop file path) of the tile being dragged */
4883 property string draggedTileId: ""
4884 /* absolute mouse coordinates in the list */
4885@@ -65,10 +67,14 @@
4886 events for other mouse areas below, which is not desired). */
4887 var coord = mapToItem(list.contentItem, mouse.x, mouse.y)
4888 draggedTileIndex = list.indexAt(coord.x, coord.y)
4889+ firstDraggedTileIndex = draggedTileIndex
4890 longPressDelay.start()
4891 }
4892 function drop() {
4893 longPressDelay.stop()
4894+ if (draggedTileId != "" && firstDraggedTileIndex != draggedTileIndex) {
4895+ items.moveFinished(firstDraggedTileIndex, draggedTileIndex)
4896+ }
4897 draggedTileId = ""
4898 parent.interactive = true
4899 }
4900
4901=== added file 'shell/launcher/artwork/launcher_arrow_outline_rtl.png'
4902Binary files shell/launcher/artwork/launcher_arrow_outline_rtl.png 1970-01-01 00:00:00 +0000 and shell/launcher/artwork/launcher_arrow_outline_rtl.png 2012-03-15 09:01:33 +0000 differ
4903=== modified file 'spread/Windows.qml'
4904--- spread/Windows.qml 2011-11-29 17:36:45 +0000
4905+++ spread/Windows.qml 2012-03-15 09:01:33 +0000
4906@@ -73,6 +73,17 @@
4907 filterRegExp: RegExp("%1".arg(switcher.applicationFilter))
4908 }
4909
4910+ /* This proxy model takes care of removing all windows that are not on
4911+ the screen of this spread. */
4912+ SortFilterProxyModel {
4913+ id: filteredByScreen
4914+ model: filteredByApplication
4915+ dynamicSortFilter: true
4916+
4917+ filterRole: WindowInfo.RoleScreen
4918+ filterRegExp: RegExp("%1".arg(declarativeView.screen.screen))
4919+ }
4920+
4921 property int columns: Math.ceil(Math.sqrt(count))
4922 property int rows: Math.ceil(count / columns)
4923 property int cellSpacing: 10
4924@@ -84,7 +95,7 @@
4925 * initialization gets somehow messed up and the "columns" and "rows"
4926 * variables are set to those of the first workspace. */
4927 Component.onCompleted: {
4928- model = filteredByApplication
4929+ model = filteredByScreen
4930 }
4931
4932 delegate:
4933@@ -130,7 +141,7 @@
4934 property bool animateFollow: false
4935 property bool followCell: true
4936
4937- isSelected: cell.activeFocus
4938+ isSelected: cell.activeFocus && spreadManager.currentSwitcher == switcher
4939
4940 onEntered: {
4941 windows.currentIndex = index
4942
4943=== modified file 'spread/Workspace.qml'
4944--- spread/Workspace.qml 2012-01-31 15:09:02 +0000
4945+++ spread/Workspace.qml 2012-03-15 09:01:33 +0000
4946@@ -54,8 +54,8 @@
4947
4948 clip: true
4949 cached: false
4950- offsetX: -declarativeView.screen.panelsFreeGeometry.x
4951- offsetY: -declarativeView.screen.panelsFreeGeometry.y
4952+ offsetX: -declarativeView.screen.panelsFreeGeometry.x + declarativeView.screen.geometry.x
4953+ offsetY: -declarativeView.screen.panelsFreeGeometry.y + declarativeView.screen.geometry.y
4954 }
4955
4956 Windows {
4957
4958=== modified file 'spread/Workspaces.qml'
4959--- spread/Workspaces.qml 2012-02-07 17:06:42 +0000
4960+++ spread/Workspaces.qml 2012-03-15 09:01:33 +0000
4961@@ -25,6 +25,10 @@
4962
4963 color: "black"
4964
4965+ signal cancelAndExitStarted ()
4966+
4967+ property variant declarativeView
4968+
4969 property int columns: desktop.workspaces.columns
4970 property int rows: desktop.workspaces.rows
4971
4972@@ -104,7 +108,7 @@
4973 z: -1
4974 width: workspaces.cellWidth
4975 height: workspaces.cellHeight
4976- visible: workspaces.currentItem.state == "unzoomed"
4977+ visible: workspaces.currentItem.state == "unzoomed" && spreadManager.currentSwitcher == switcher
4978 }
4979 highlightFollowsCurrentItem: false
4980
4981@@ -210,8 +214,7 @@
4982 function show() {
4983 allWindows.load()
4984
4985- spreadView.show()
4986- spreadView.forceActivateWindow()
4987+ declarativeView.show()
4988 workspaces.currentIndex = desktop.workspaces.current
4989 /* This is necessary otherwise we don't get keypresses until the user does a
4990 mouse over on a window */
4991@@ -228,7 +231,7 @@
4992 id: exitTransitionTimer
4993 interval: Utils.transitionDuration
4994 onTriggered: {
4995- spreadView.hide()
4996+ declarativeView.hide()
4997
4998 /* Nothing should be allowed to touch the windows anymore here, so it should
4999 be safe to unload them all to save memory.
5000@@ -263,11 +266,16 @@
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches