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
=== modified file 'panel/app/CMakeLists.txt'
--- panel/app/CMakeLists.txt 2011-02-02 16:57:00 +0000
+++ panel/app/CMakeLists.txt 2011-04-04 16:49:30 +0000
@@ -1,5 +1,6 @@
1set(panel_SRCS1set(panel_SRCS
2 main.cpp2 main.cpp
3 panelmanager.cpp
3 unity2dstyle.cpp4 unity2dstyle.cpp
4 )5 )
56
67
=== modified file 'panel/app/main.cpp'
--- panel/app/main.cpp 2011-03-22 10:31:28 +0000
+++ panel/app/main.cpp 2011-04-04 16:49:30 +0000
@@ -21,18 +21,11 @@
2121
22// Local22// Local
23#include <config.h>23#include <config.h>
2424#include <panelmanager.h>
25// Applets
26#include <appindicator/appindicatorapplet.h>
27#include <appname/appnameapplet.h>
28#include <homebutton/homebuttonapplet.h>
29#include <indicator/indicatorapplet.h>
30#include <legacytray/legacytrayapplet.h>
3125
32// Unity26// Unity
33#include <gnomesessionclient.h>27#include <gnomesessionclient.h>
34#include <unity2ddebug.h>28#include <unity2ddebug.h>
35#include <unity2dpanel.h>
36#include <unity2dapplication.h>29#include <unity2dapplication.h>
37#include <unity2dstyle.h>30#include <unity2dstyle.h>
38#include <unity2dtr.h>31#include <unity2dtr.h>
@@ -41,9 +34,6 @@
41#include <QAbstractFileEngineHandler>34#include <QAbstractFileEngineHandler>
42#include <QApplication>35#include <QApplication>
43#include <QFSFileEngine>36#include <QFSFileEngine>
44#include <QLabel>
45
46using namespace Unity2d;
4737
48class ThemeEngineHandler : public QAbstractFileEngineHandler38class ThemeEngineHandler : public QAbstractFileEngineHandler
49{39{
@@ -59,32 +49,6 @@
59 }49 }
60};50};
6151
62QPalette getPalette()
63{
64 QPalette palette;
65
66 /* Should use the panel's background provided by Unity but it turns
67 out not to be good. It would look like:
68
69 QBrush bg(QPixmap("theme:/panel_background.png"));
70 */
71 QBrush bg(QPixmap(unity2dDirectory() + "/panel/artwork/background.png"));
72 palette.setBrush(QPalette::Window, bg);
73 palette.setBrush(QPalette::Button, bg);
74 palette.setColor(QPalette::WindowText, Qt::white);
75 palette.setColor(QPalette::ButtonText, Qt::white);
76 return palette;
77}
78
79QLabel* createSeparator()
80{
81 QLabel* label = new QLabel;
82 QPixmap pix(unity2dDirectory() + "/panel/artwork/divider.png");
83 label->setPixmap(pix);
84 label->setFixedSize(pix.size());
85 return label;
86}
87
88int main(int argc, char** argv)52int main(int argc, char** argv)
89{53{
90 ThemeEngineHandler handler;54 ThemeEngineHandler handler;
@@ -109,16 +73,7 @@
109 /* Configure translations */73 /* Configure translations */
110 Unity2dTr::init("unity-2d", INSTALL_PREFIX "/share/locale");74 Unity2dTr::init("unity-2d", INSTALL_PREFIX "/share/locale");
11175
112 Unity2dPanel panel;76 PanelManager panels;
113 panel.setEdge(Unity2dPanel::TopEdge);
114 panel.setPalette(getPalette());
115 panel.setFixedHeight(24);
11677
117 panel.addWidget(new HomeButtonApplet);
118 panel.addWidget(createSeparator());
119 panel.addWidget(new AppNameApplet);
120 panel.addWidget(new LegacyTrayApplet);
121 panel.addWidget(new IndicatorApplet);
122 panel.show();
123 return app.exec();78 return app.exec();
124}79}
12580
=== added file 'panel/app/panelmanager.cpp'
--- panel/app/panelmanager.cpp 1970-01-01 00:00:00 +0000
+++ panel/app/panelmanager.cpp 2011-04-04 16:49:30 +0000
@@ -0,0 +1,135 @@
1/*
2 * This file is part of unity-2d
3 *
4 * Copyright 2010 Canonical Ltd.
5 *
6 * Authors:
7 * - Olivier Tilloy <olivier.tilloy@canonical.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 3.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
20 */
21
22// Self
23#include "panelmanager.h"
24
25// Local
26#include <config.h>
27
28// Applets
29#include <appindicator/appindicatorapplet.h>
30#include <appname/appnameapplet.h>
31#include <homebutton/homebuttonapplet.h>
32#include <indicator/indicatorapplet.h>
33#include <legacytray/legacytrayapplet.h>
34
35// Unity
36#include <unity2dpanel.h>
37
38// Qt
39#include <QApplication>
40#include <QDesktopWidget>
41#include <QLabel>
42
43using namespace Unity2d;
44
45static QPalette getPalette()
46{
47 QPalette palette;
48
49 /* Should use the panel's background provided by Unity but it turns
50 out not to be good. It would look like:
51
52 QBrush bg(QPixmap("theme:/panel_background.png"));
53 */
54 QBrush bg(QPixmap(unity2dDirectory() + "/panel/artwork/background.png"));
55 palette.setBrush(QPalette::Window, bg);
56 palette.setBrush(QPalette::Button, bg);
57 palette.setColor(QPalette::WindowText, Qt::white);
58 palette.setColor(QPalette::ButtonText, Qt::white);
59 return palette;
60}
61
62static QLabel* createSeparator()
63{
64 QLabel* label = new QLabel;
65 QPixmap pix(unity2dDirectory() + "/panel/artwork/divider.png");
66 label->setPixmap(pix);
67 label->setFixedSize(pix.size());
68 return label;
69}
70
71static Unity2dPanel* instantiatePanel(int screen)
72{
73 Unity2dPanel* panel = new Unity2dPanel;
74 panel->setEdge(Unity2dPanel::TopEdge);
75 panel->setPalette(getPalette());
76 panel->setFixedHeight(24);
77
78 int primary = QApplication::desktop()->primaryScreen();
79 if (screen == primary) {
80 panel->addWidget(new HomeButtonApplet);
81 panel->addWidget(createSeparator());
82 }
83 panel->addWidget(new AppNameApplet);
84 if (screen == primary) {
85 /* It doesn’t make sense to have more than one instance of the systray,
86 XEmbed’ed windows can be displayed only once anyway. */
87 panel->addWidget(new LegacyTrayApplet);
88 }
89 panel->addWidget(new IndicatorApplet);
90 return panel;
91}
92
93PanelManager::PanelManager(QObject* parent)
94 : QObject(parent)
95{
96 QDesktopWidget* desktop = QApplication::desktop();
97 for(int i = 0; i < desktop->screenCount(); ++i) {
98 Unity2dPanel* panel = instantiatePanel(i);
99 m_panels.append(panel);
100 panel->show();
101 panel->move(desktop->screenGeometry(i).topLeft());
102 }
103 connect(desktop, SIGNAL(screenCountChanged(int)), SLOT(onScreenCountChanged(int)));
104}
105
106PanelManager::~PanelManager()
107{
108 qDeleteAll(m_panels);
109}
110
111void
112PanelManager::onScreenCountChanged(int newCount)
113{
114 QDesktopWidget* desktop = QApplication::desktop();
115 int size = m_panels.size();
116 /* Update the position of existing panels, and instantiate new panels. */
117 for (int i = 0; i < newCount; ++i) {
118 Unity2dPanel* panel;
119 if (i < size) {
120 panel = m_panels[i];
121 } else {
122 panel = instantiatePanel(i);
123 m_panels.append(panel);
124 }
125 panel->show();
126 panel->move(desktop->screenGeometry(i).topLeft());
127 }
128 /* Remove extra panels if any. */
129 while (m_panels.size() > newCount) {
130 delete m_panels.takeLast();
131 }
132}
133
134#include "panelmanager.moc"
135
0136
=== added file 'panel/app/panelmanager.h'
--- panel/app/panelmanager.h 1970-01-01 00:00:00 +0000
+++ panel/app/panelmanager.h 2011-04-04 16:49:30 +0000
@@ -0,0 +1,48 @@
1/*
2 * This file is part of unity-2d
3 *
4 * Copyright 2010 Canonical Ltd.
5 *
6 * Authors:
7 * - Olivier Tilloy <olivier.tilloy@canonical.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 3.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
20 */
21
22#ifndef PanelManager_H
23#define PanelManager_H
24
25// Qt
26#include <QObject>
27#include <QList>
28
29class Unity2dPanel;
30
31class PanelManager : public QObject
32{
33Q_OBJECT
34
35public:
36 PanelManager(QObject* parent = 0);
37 ~PanelManager();
38
39private:
40 Q_DISABLE_COPY(PanelManager)
41 QList<Unity2dPanel*> m_panels;
42
43private Q_SLOTS:
44 void onScreenCountChanged(int newCount);
45};
46
47#endif // PanelManager_H
48
049
=== modified file 'panel/applets/appname/appnameapplet.cpp'
--- panel/applets/appname/appnameapplet.cpp 2011-03-14 11:23:53 +0000
+++ panel/applets/appname/appnameapplet.cpp 2011-04-04 16:49:30 +0000
@@ -41,6 +41,8 @@
41#include <QLabel>41#include <QLabel>
42#include <QMenuBar>42#include <QMenuBar>
43#include <QPainter>43#include <QPainter>
44#include <QApplication>
45#include <QDesktopWidget>
4446
45static const char* METACITY_DIR = "/usr/share/themes/Ambiance/metacity-1";47static const char* METACITY_DIR = "/usr/share/themes/Ambiance/metacity-1";
4648
@@ -217,12 +219,13 @@
217219
218 bool isMaximized = d->m_windowHelper->isMaximized();220 bool isMaximized = d->m_windowHelper->isMaximized();
219 bool isUserVisibleApp = app ? app->user_visible() : false;221 bool isUserVisibleApp = app ? app->user_visible() : false;
220 bool showMenu = (!d->m_menuBarWidget->isEmpty() && isUserVisibleApp)222 bool isOnSameScreen = d->m_windowHelper->isMostlyOnScreen(QApplication::desktop()->screenNumber(this));
223 bool showMenu = (!d->m_menuBarWidget->isEmpty() && isUserVisibleApp && isOnSameScreen)
221 && (window()->geometry().contains(QCursor::pos())224 && (window()->geometry().contains(QCursor::pos())
222 || KeyboardModifiersMonitor::instance()->keyboardModifiers() == Qt::AltModifier225 || KeyboardModifiersMonitor::instance()->keyboardModifiers() == Qt::AltModifier
223 || d->m_menuBarWidget->isOpened()226 || d->m_menuBarWidget->isOpened()
224 );227 );
225 bool showLabel = !(isMaximized && showMenu) && isUserVisibleApp;228 bool showLabel = !(isMaximized && showMenu) && isUserVisibleApp && isOnSameScreen;
226229
227 d->m_windowButtonWidget->setVisible(isMaximized);230 d->m_windowButtonWidget->setVisible(isMaximized);
228231
229232
=== modified file 'panel/applets/appname/menubarwidget.cpp'
--- panel/applets/appname/menubarwidget.cpp 2011-01-15 01:41:03 +0000
+++ panel/applets/appname/menubarwidget.cpp 2011-04-04 16:49:30 +0000
@@ -74,7 +74,7 @@
7474
75void MenuBarWidget::setupRegistrar()75void MenuBarWidget::setupRegistrar()
76{76{
77 m_registrar = new Registrar(this);77 m_registrar = Registrar::instance();
78 if (!m_registrar->connectToBus()) {78 if (!m_registrar->connectToBus()) {
79 UQ_WARNING << "could not connect registrar to DBus";79 UQ_WARNING << "could not connect registrar to DBus";
80 }80 }
8181
=== modified file 'panel/applets/appname/registrar.cpp'
--- panel/applets/appname/registrar.cpp 2011-02-10 01:10:19 +0000
+++ panel/applets/appname/registrar.cpp 2011-04-04 16:49:30 +0000
@@ -51,8 +51,8 @@
51 return argument;51 return argument;
52}52}
5353
54Registrar::Registrar(QObject* parent)54Registrar::Registrar()
55: QObject(parent)55: QObject()
56, mServiceWatcher(new QDBusServiceWatcher(this))56, mServiceWatcher(new QDBusServiceWatcher(this))
57{57{
58 qDBusRegisterMetaType<MenuInfo>();58 qDBusRegisterMetaType<MenuInfo>();
@@ -67,6 +67,12 @@
67 QDBusConnection::sessionBus().unregisterService(mService);67 QDBusConnection::sessionBus().unregisterService(mService);
68}68}
6969
70Registrar* Registrar::instance()
71{
72 static Registrar singleton;
73 return &singleton;
74}
75
70bool Registrar::connectToBus(const QString& _service, const QString& _path)76bool Registrar::connectToBus(const QString& _service, const QString& _path)
71{77{
72 mService = _service.isEmpty() ? DBUS_SERVICE : _service;78 mService = _service.isEmpty() ? DBUS_SERVICE : _service;
7379
=== modified file 'panel/applets/appname/registrar.h'
--- panel/applets/appname/registrar.h 2011-01-15 01:41:03 +0000
+++ panel/applets/appname/registrar.h 2011-04-04 16:49:30 +0000
@@ -53,8 +53,8 @@
53 Q_OBJECT53 Q_OBJECT
5454
55public:55public:
56 Registrar(QObject*);56 /* The registrar is a singleton shared between all instances of MenuBarWidget. */
57 ~Registrar();57 static Registrar* instance();
5858
59 bool connectToBus(const QString& service = QString(), const QString& objectPath = QString());59 bool connectToBus(const QString& service = QString(), const QString& objectPath = QString());
6060
@@ -72,6 +72,10 @@
72 void slotServiceUnregistered(const QString& service);72 void slotServiceUnregistered(const QString& service);
7373
74private:74private:
75 Registrar();
76 Q_DISABLE_COPY(Registrar)
77 ~Registrar();
78
75 QDBusServiceWatcher* mServiceWatcher;79 QDBusServiceWatcher* mServiceWatcher;
76 typedef QHash<WId, MenuInfo> MenuInfoDb;80 typedef QHash<WId, MenuInfo> MenuInfoDb;
77 MenuInfoDb mDb;81 MenuInfoDb mDb;
7882
=== modified file 'panel/applets/appname/windowhelper.cpp'
--- panel/applets/appname/windowhelper.cpp 2011-02-07 15:15:55 +0000
+++ panel/applets/appname/windowhelper.cpp 2011-04-04 16:49:30 +0000
@@ -40,6 +40,8 @@
4040
41// Qt41// Qt
42#include <QDateTime>42#include <QDateTime>
43#include <QApplication>
44#include <QDesktopWidget>
4345
44struct WindowHelperPrivate46struct WindowHelperPrivate
45{47{
@@ -111,6 +113,29 @@
111 return wnck_window_is_maximized(d->m_window);113 return wnck_window_is_maximized(d->m_window);
112}114}
113115
116bool WindowHelper::isMostlyOnScreen(int screen) const
117{
118 if (!d->m_window) {
119 return false;
120 }
121 int x, y, width, height;
122 wnck_window_get_geometry(d->m_window, &x, &y, &width, &height);
123 const QRect windowGeometry(x, y, width, height);
124 QDesktopWidget* desktop = QApplication::desktop();
125 const QRect screenGeometry = desktop->screenGeometry(screen);
126 QRect onScreen = screenGeometry.intersected(windowGeometry);
127 int intersected = onScreen.width() * onScreen.height();
128 for (int i = 0; i < desktop->screenCount(); ++i) {
129 if (i != screen) {
130 onScreen = desktop->screenGeometry(i).intersected(windowGeometry);
131 if (onScreen.width() * onScreen.height() > intersected) {
132 return false;
133 }
134 }
135 }
136 return true;
137}
138
114void WindowHelper::close()139void WindowHelper::close()
115{140{
116 guint32 timestamp = QDateTime::currentDateTime().toTime_t();141 guint32 timestamp = QDateTime::currentDateTime().toTime_t();
117142
=== modified file 'panel/applets/appname/windowhelper.h'
--- panel/applets/appname/windowhelper.h 2011-02-07 15:10:08 +0000
+++ panel/applets/appname/windowhelper.h 2011-04-04 16:49:30 +0000
@@ -38,6 +38,7 @@
38 void setXid(uint);38 void setXid(uint);
3939
40 bool isMaximized() const;40 bool isMaximized() const;
41 bool isMostlyOnScreen(int screen) const;
4142
42public Q_SLOTS:43public Q_SLOTS:
43 void close();44 void close();

Subscribers

People subscribed via source and target branches