Merge lp:~osomon/unity-2d/one-panel-per-screen into lp:unity-2d/3.0

Proposed by Olivier Tilloy
Status: Merged
Approved by: Aurélien Gâteau
Approved revision: 505
Merged at revision: 508
Proposed branch: lp:~osomon/unity-2d/one-panel-per-screen
Merge into: lp:unity-2d/3.0
Diff against target: 439 lines (+232/-54)
10 files modified
panel/app/CMakeLists.txt (+1/-0)
panel/app/main.cpp (+2/-47)
panel/app/panelmanager.cpp (+135/-0)
panel/app/panelmanager.h (+48/-0)
panel/applets/appname/appnameapplet.cpp (+5/-2)
panel/applets/appname/menubarwidget.cpp (+1/-1)
panel/applets/appname/registrar.cpp (+8/-2)
panel/applets/appname/registrar.h (+6/-2)
panel/applets/appname/windowhelper.cpp (+25/-0)
panel/applets/appname/windowhelper.h (+1/-0)
To merge this branch: bzr merge lp:~osomon/unity-2d/one-panel-per-screen
Reviewer Review Type Date Requested Status
Aurélien Gâteau (community) Approve
Review via email: mp+56162@code.launchpad.net

Commit message

[panel] Display one panel per screen.
Only the panel on the primary screen contains the home button applet ("circle of friends" that invokes the dash) and the systray.
All panels contain an instance of the applet that displays the active window’s application title and menu bar, as well as the application and system indicators.

Description of the change

Notes to the reviewer:

 - I developed and tested on Maverick, so thorough functional testing on Natty is expected, in particular dynamically adding/removing screens while unity-2d-panel is running.

 - On Maverick, I noticed one tiny problem with the "me" system indicator: when there are several screens, only the instance on the primary screen has an icon and a label, other instances seem empty. However their menus are there and functional, the problem is only with the menu title. I suspect a bug in the indicator itself, but I’m not sure. It may have been fixed in Natty as well, feedback is welcome.

To post a comment you must log in.
Revision history for this message
Aurélien Gâteau (agateau) wrote :

No time to test tonight, but the way you implemented it looks good. Here are a few remarks to keep things moving:

- Please rename PanelsManager to PanelManager

- Can you make the helper functions in panelmanagers static? this makes it more explicit they are not meant to be used from outside (they were not when they were in main.cpp because I assumed it was clear no code from main.cpp would ever be called from somewhere else)

- Adjust the registrar singleton method to something like this:

Registrar* Registrar::instance()
{
    static Registrar singleton;
    return &singleton;
}

It's almost the same, except memory checkers such as valgrind won't complain about not released memory.

- You don't need to mark Registrar constructor explicit. This is only useful for one-parameter constructors.

I may add a few other requests tomorrow morning, but I have to go now.

review: Needs Fixing
502. By Olivier Tilloy

Renamed PanelsManager to PanelManager.

503. By Olivier Tilloy

Made some helper functions static.

504. By Olivier Tilloy

Cosmetics to make the code more valgrind-proof.

505. By Olivier Tilloy

Removed unneeded explicitness.

Revision history for this message
Aurélien Gâteau (agateau) wrote :

Looks good now. Does not support the case where top edges are not aligned but this is tracked by a separate bug report.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'panel/app/CMakeLists.txt'
2--- panel/app/CMakeLists.txt 2011-02-02 16:57:00 +0000
3+++ panel/app/CMakeLists.txt 2011-04-04 16:49:30 +0000
4@@ -1,5 +1,6 @@
5 set(panel_SRCS
6 main.cpp
7+ panelmanager.cpp
8 unity2dstyle.cpp
9 )
10
11
12=== modified file 'panel/app/main.cpp'
13--- panel/app/main.cpp 2011-03-22 10:31:28 +0000
14+++ panel/app/main.cpp 2011-04-04 16:49:30 +0000
15@@ -21,18 +21,11 @@
16
17 // Local
18 #include <config.h>
19-
20-// Applets
21-#include <appindicator/appindicatorapplet.h>
22-#include <appname/appnameapplet.h>
23-#include <homebutton/homebuttonapplet.h>
24-#include <indicator/indicatorapplet.h>
25-#include <legacytray/legacytrayapplet.h>
26+#include <panelmanager.h>
27
28 // Unity
29 #include <gnomesessionclient.h>
30 #include <unity2ddebug.h>
31-#include <unity2dpanel.h>
32 #include <unity2dapplication.h>
33 #include <unity2dstyle.h>
34 #include <unity2dtr.h>
35@@ -41,9 +34,6 @@
36 #include <QAbstractFileEngineHandler>
37 #include <QApplication>
38 #include <QFSFileEngine>
39-#include <QLabel>
40-
41-using namespace Unity2d;
42
43 class ThemeEngineHandler : public QAbstractFileEngineHandler
44 {
45@@ -59,32 +49,6 @@
46 }
47 };
48
49-QPalette getPalette()
50-{
51- QPalette palette;
52-
53- /* Should use the panel's background provided by Unity but it turns
54- out not to be good. It would look like:
55-
56- QBrush bg(QPixmap("theme:/panel_background.png"));
57- */
58- QBrush bg(QPixmap(unity2dDirectory() + "/panel/artwork/background.png"));
59- palette.setBrush(QPalette::Window, bg);
60- palette.setBrush(QPalette::Button, bg);
61- palette.setColor(QPalette::WindowText, Qt::white);
62- palette.setColor(QPalette::ButtonText, Qt::white);
63- return palette;
64-}
65-
66-QLabel* createSeparator()
67-{
68- QLabel* label = new QLabel;
69- QPixmap pix(unity2dDirectory() + "/panel/artwork/divider.png");
70- label->setPixmap(pix);
71- label->setFixedSize(pix.size());
72- return label;
73-}
74-
75 int main(int argc, char** argv)
76 {
77 ThemeEngineHandler handler;
78@@ -109,16 +73,7 @@
79 /* Configure translations */
80 Unity2dTr::init("unity-2d", INSTALL_PREFIX "/share/locale");
81
82- Unity2dPanel panel;
83- panel.setEdge(Unity2dPanel::TopEdge);
84- panel.setPalette(getPalette());
85- panel.setFixedHeight(24);
86+ PanelManager panels;
87
88- panel.addWidget(new HomeButtonApplet);
89- panel.addWidget(createSeparator());
90- panel.addWidget(new AppNameApplet);
91- panel.addWidget(new LegacyTrayApplet);
92- panel.addWidget(new IndicatorApplet);
93- panel.show();
94 return app.exec();
95 }
96
97=== added file 'panel/app/panelmanager.cpp'
98--- panel/app/panelmanager.cpp 1970-01-01 00:00:00 +0000
99+++ panel/app/panelmanager.cpp 2011-04-04 16:49:30 +0000
100@@ -0,0 +1,135 @@
101+/*
102+ * This file is part of unity-2d
103+ *
104+ * Copyright 2010 Canonical Ltd.
105+ *
106+ * Authors:
107+ * - Olivier Tilloy <olivier.tilloy@canonical.com>
108+ *
109+ * This program is free software; you can redistribute it and/or modify
110+ * it under the terms of the GNU General Public License as published by
111+ * the Free Software Foundation; version 3.
112+ *
113+ * This program is distributed in the hope that it will be useful,
114+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
115+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
116+ * GNU General Public License for more details.
117+ *
118+ * You should have received a copy of the GNU General Public License
119+ * along with this program. If not, see <http://www.gnu.org/licenses/>
120+ */
121+
122+// Self
123+#include "panelmanager.h"
124+
125+// Local
126+#include <config.h>
127+
128+// Applets
129+#include <appindicator/appindicatorapplet.h>
130+#include <appname/appnameapplet.h>
131+#include <homebutton/homebuttonapplet.h>
132+#include <indicator/indicatorapplet.h>
133+#include <legacytray/legacytrayapplet.h>
134+
135+// Unity
136+#include <unity2dpanel.h>
137+
138+// Qt
139+#include <QApplication>
140+#include <QDesktopWidget>
141+#include <QLabel>
142+
143+using namespace Unity2d;
144+
145+static QPalette getPalette()
146+{
147+ QPalette palette;
148+
149+ /* Should use the panel's background provided by Unity but it turns
150+ out not to be good. It would look like:
151+
152+ QBrush bg(QPixmap("theme:/panel_background.png"));
153+ */
154+ QBrush bg(QPixmap(unity2dDirectory() + "/panel/artwork/background.png"));
155+ palette.setBrush(QPalette::Window, bg);
156+ palette.setBrush(QPalette::Button, bg);
157+ palette.setColor(QPalette::WindowText, Qt::white);
158+ palette.setColor(QPalette::ButtonText, Qt::white);
159+ return palette;
160+}
161+
162+static QLabel* createSeparator()
163+{
164+ QLabel* label = new QLabel;
165+ QPixmap pix(unity2dDirectory() + "/panel/artwork/divider.png");
166+ label->setPixmap(pix);
167+ label->setFixedSize(pix.size());
168+ return label;
169+}
170+
171+static Unity2dPanel* instantiatePanel(int screen)
172+{
173+ Unity2dPanel* panel = new Unity2dPanel;
174+ panel->setEdge(Unity2dPanel::TopEdge);
175+ panel->setPalette(getPalette());
176+ panel->setFixedHeight(24);
177+
178+ int primary = QApplication::desktop()->primaryScreen();
179+ if (screen == primary) {
180+ panel->addWidget(new HomeButtonApplet);
181+ panel->addWidget(createSeparator());
182+ }
183+ panel->addWidget(new AppNameApplet);
184+ if (screen == primary) {
185+ /* It doesn’t make sense to have more than one instance of the systray,
186+ XEmbed’ed windows can be displayed only once anyway. */
187+ panel->addWidget(new LegacyTrayApplet);
188+ }
189+ panel->addWidget(new IndicatorApplet);
190+ return panel;
191+}
192+
193+PanelManager::PanelManager(QObject* parent)
194+ : QObject(parent)
195+{
196+ QDesktopWidget* desktop = QApplication::desktop();
197+ for(int i = 0; i < desktop->screenCount(); ++i) {
198+ Unity2dPanel* panel = instantiatePanel(i);
199+ m_panels.append(panel);
200+ panel->show();
201+ panel->move(desktop->screenGeometry(i).topLeft());
202+ }
203+ connect(desktop, SIGNAL(screenCountChanged(int)), SLOT(onScreenCountChanged(int)));
204+}
205+
206+PanelManager::~PanelManager()
207+{
208+ qDeleteAll(m_panels);
209+}
210+
211+void
212+PanelManager::onScreenCountChanged(int newCount)
213+{
214+ QDesktopWidget* desktop = QApplication::desktop();
215+ int size = m_panels.size();
216+ /* Update the position of existing panels, and instantiate new panels. */
217+ for (int i = 0; i < newCount; ++i) {
218+ Unity2dPanel* panel;
219+ if (i < size) {
220+ panel = m_panels[i];
221+ } else {
222+ panel = instantiatePanel(i);
223+ m_panels.append(panel);
224+ }
225+ panel->show();
226+ panel->move(desktop->screenGeometry(i).topLeft());
227+ }
228+ /* Remove extra panels if any. */
229+ while (m_panels.size() > newCount) {
230+ delete m_panels.takeLast();
231+ }
232+}
233+
234+#include "panelmanager.moc"
235+
236
237=== added file 'panel/app/panelmanager.h'
238--- panel/app/panelmanager.h 1970-01-01 00:00:00 +0000
239+++ panel/app/panelmanager.h 2011-04-04 16:49:30 +0000
240@@ -0,0 +1,48 @@
241+/*
242+ * This file is part of unity-2d
243+ *
244+ * Copyright 2010 Canonical Ltd.
245+ *
246+ * Authors:
247+ * - Olivier Tilloy <olivier.tilloy@canonical.com>
248+ *
249+ * This program is free software; you can redistribute it and/or modify
250+ * it under the terms of the GNU General Public License as published by
251+ * the Free Software Foundation; version 3.
252+ *
253+ * This program is distributed in the hope that it will be useful,
254+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
255+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
256+ * GNU General Public License for more details.
257+ *
258+ * You should have received a copy of the GNU General Public License
259+ * along with this program. If not, see <http://www.gnu.org/licenses/>
260+ */
261+
262+#ifndef PanelManager_H
263+#define PanelManager_H
264+
265+// Qt
266+#include <QObject>
267+#include <QList>
268+
269+class Unity2dPanel;
270+
271+class PanelManager : public QObject
272+{
273+Q_OBJECT
274+
275+public:
276+ PanelManager(QObject* parent = 0);
277+ ~PanelManager();
278+
279+private:
280+ Q_DISABLE_COPY(PanelManager)
281+ QList<Unity2dPanel*> m_panels;
282+
283+private Q_SLOTS:
284+ void onScreenCountChanged(int newCount);
285+};
286+
287+#endif // PanelManager_H
288+
289
290=== modified file 'panel/applets/appname/appnameapplet.cpp'
291--- panel/applets/appname/appnameapplet.cpp 2011-03-14 11:23:53 +0000
292+++ panel/applets/appname/appnameapplet.cpp 2011-04-04 16:49:30 +0000
293@@ -41,6 +41,8 @@
294 #include <QLabel>
295 #include <QMenuBar>
296 #include <QPainter>
297+#include <QApplication>
298+#include <QDesktopWidget>
299
300 static const char* METACITY_DIR = "/usr/share/themes/Ambiance/metacity-1";
301
302@@ -217,12 +219,13 @@
303
304 bool isMaximized = d->m_windowHelper->isMaximized();
305 bool isUserVisibleApp = app ? app->user_visible() : false;
306- bool showMenu = (!d->m_menuBarWidget->isEmpty() && isUserVisibleApp)
307+ bool isOnSameScreen = d->m_windowHelper->isMostlyOnScreen(QApplication::desktop()->screenNumber(this));
308+ bool showMenu = (!d->m_menuBarWidget->isEmpty() && isUserVisibleApp && isOnSameScreen)
309 && (window()->geometry().contains(QCursor::pos())
310 || KeyboardModifiersMonitor::instance()->keyboardModifiers() == Qt::AltModifier
311 || d->m_menuBarWidget->isOpened()
312 );
313- bool showLabel = !(isMaximized && showMenu) && isUserVisibleApp;
314+ bool showLabel = !(isMaximized && showMenu) && isUserVisibleApp && isOnSameScreen;
315
316 d->m_windowButtonWidget->setVisible(isMaximized);
317
318
319=== modified file 'panel/applets/appname/menubarwidget.cpp'
320--- panel/applets/appname/menubarwidget.cpp 2011-01-15 01:41:03 +0000
321+++ panel/applets/appname/menubarwidget.cpp 2011-04-04 16:49:30 +0000
322@@ -74,7 +74,7 @@
323
324 void MenuBarWidget::setupRegistrar()
325 {
326- m_registrar = new Registrar(this);
327+ m_registrar = Registrar::instance();
328 if (!m_registrar->connectToBus()) {
329 UQ_WARNING << "could not connect registrar to DBus";
330 }
331
332=== modified file 'panel/applets/appname/registrar.cpp'
333--- panel/applets/appname/registrar.cpp 2011-02-10 01:10:19 +0000
334+++ panel/applets/appname/registrar.cpp 2011-04-04 16:49:30 +0000
335@@ -51,8 +51,8 @@
336 return argument;
337 }
338
339-Registrar::Registrar(QObject* parent)
340-: QObject(parent)
341+Registrar::Registrar()
342+: QObject()
343 , mServiceWatcher(new QDBusServiceWatcher(this))
344 {
345 qDBusRegisterMetaType<MenuInfo>();
346@@ -67,6 +67,12 @@
347 QDBusConnection::sessionBus().unregisterService(mService);
348 }
349
350+Registrar* Registrar::instance()
351+{
352+ static Registrar singleton;
353+ return &singleton;
354+}
355+
356 bool Registrar::connectToBus(const QString& _service, const QString& _path)
357 {
358 mService = _service.isEmpty() ? DBUS_SERVICE : _service;
359
360=== modified file 'panel/applets/appname/registrar.h'
361--- panel/applets/appname/registrar.h 2011-01-15 01:41:03 +0000
362+++ panel/applets/appname/registrar.h 2011-04-04 16:49:30 +0000
363@@ -53,8 +53,8 @@
364 Q_OBJECT
365
366 public:
367- Registrar(QObject*);
368- ~Registrar();
369+ /* The registrar is a singleton shared between all instances of MenuBarWidget. */
370+ static Registrar* instance();
371
372 bool connectToBus(const QString& service = QString(), const QString& objectPath = QString());
373
374@@ -72,6 +72,10 @@
375 void slotServiceUnregistered(const QString& service);
376
377 private:
378+ Registrar();
379+ Q_DISABLE_COPY(Registrar)
380+ ~Registrar();
381+
382 QDBusServiceWatcher* mServiceWatcher;
383 typedef QHash<WId, MenuInfo> MenuInfoDb;
384 MenuInfoDb mDb;
385
386=== modified file 'panel/applets/appname/windowhelper.cpp'
387--- panel/applets/appname/windowhelper.cpp 2011-02-07 15:15:55 +0000
388+++ panel/applets/appname/windowhelper.cpp 2011-04-04 16:49:30 +0000
389@@ -40,6 +40,8 @@
390
391 // Qt
392 #include <QDateTime>
393+#include <QApplication>
394+#include <QDesktopWidget>
395
396 struct WindowHelperPrivate
397 {
398@@ -111,6 +113,29 @@
399 return wnck_window_is_maximized(d->m_window);
400 }
401
402+bool WindowHelper::isMostlyOnScreen(int screen) const
403+{
404+ if (!d->m_window) {
405+ return false;
406+ }
407+ int x, y, width, height;
408+ wnck_window_get_geometry(d->m_window, &x, &y, &width, &height);
409+ const QRect windowGeometry(x, y, width, height);
410+ QDesktopWidget* desktop = QApplication::desktop();
411+ const QRect screenGeometry = desktop->screenGeometry(screen);
412+ QRect onScreen = screenGeometry.intersected(windowGeometry);
413+ int intersected = onScreen.width() * onScreen.height();
414+ for (int i = 0; i < desktop->screenCount(); ++i) {
415+ if (i != screen) {
416+ onScreen = desktop->screenGeometry(i).intersected(windowGeometry);
417+ if (onScreen.width() * onScreen.height() > intersected) {
418+ return false;
419+ }
420+ }
421+ }
422+ return true;
423+}
424+
425 void WindowHelper::close()
426 {
427 guint32 timestamp = QDateTime::currentDateTime().toTime_t();
428
429=== modified file 'panel/applets/appname/windowhelper.h'
430--- panel/applets/appname/windowhelper.h 2011-02-07 15:10:08 +0000
431+++ panel/applets/appname/windowhelper.h 2011-04-04 16:49:30 +0000
432@@ -38,6 +38,7 @@
433 void setXid(uint);
434
435 bool isMaximized() const;
436+ bool isMostlyOnScreen(int screen) const;
437
438 public Q_SLOTS:
439 void close();

Subscribers

People subscribed via source and target branches