Merge lp:~agateau/unity-2d/use-gtk-rendering into lp:unity-2d/3.0

Proposed by Aurélien Gâteau
Status: Superseded
Proposed branch: lp:~agateau/unity-2d/use-gtk-rendering
Merge into: lp:unity-2d/3.0
Prerequisite: lp:~agateau/unity-2d/unity-core
Diff against target: 1345 lines (+523/-434)
16 files modified
CMakeLists.txt (+1/-0)
libunity-2d-private/src/CMakeLists.txt (+4/-0)
libunity-2d-private/src/unity2dapplication.cpp (+49/-1)
libunity-2d-private/src/unity2dapplication.h (+3/-0)
panel/applets/CMakeLists.txt (+4/-0)
panel/applets/appname/appnameapplet.cpp (+2/-47)
panel/applets/appname/croppedlabel.cpp (+140/-0)
panel/applets/appname/croppedlabel.h (+45/-0)
panel/applets/common/cairoutils.cpp (+42/-0)
panel/applets/common/cairoutils.h (+47/-0)
panel/applets/common/fakecairo.h (+0/-125)
panel/applets/common/indicatorentrywidget.cpp (+135/-157)
panel/applets/common/indicatorentrywidget.h (+10/-1)
panel/applets/common/panelstyle.cpp (+30/-91)
panel/applets/common/panelstyle.h (+7/-10)
panel/applets/homebutton/homebutton.cpp (+4/-2)
To merge this branch: bzr merge lp:~agateau/unity-2d/use-gtk-rendering
Reviewer Review Type Date Requested Status
Florian Boucault Pending
Review via email: mp+69113@code.launchpad.net

This proposal has been superseded by a proposal from 2011-07-27.

Commit message

[panel] Use GTK3 primitives to draw labels and panel menubar item background

Description of the change

This branch uses GTK3 primitives to draw labels and active menubar item background instead of the Cairo code which was copied from unity-3d.

To post a comment you must log in.
695. By Aurélien Gâteau

Sync with unity-core

696. By Aurélien Gâteau

Sync with unity-core

697. By Aurélien Gâteau

[platform] Move all font handling from PanelStyle to Unity2dApplication

698. By Aurélien Gâteau

[panel] Fix home button active background

Do not use bfb_bg_active.png: it only works with Ambiance theme

699. By Aurélien Gâteau

Sync with unity-core

Unmerged revisions

699. By Aurélien Gâteau

Sync with unity-core

698. By Aurélien Gâteau

[panel] Fix home button active background

Do not use bfb_bg_active.png: it only works with Ambiance theme

697. By Aurélien Gâteau

[platform] Move all font handling from PanelStyle to Unity2dApplication

696. By Aurélien Gâteau

Sync with unity-core

695. By Aurélien Gâteau

Sync with unity-core

694. By Aurélien Gâteau

Synced with unity-core branch

693. By Aurélien Gâteau

#define => static const char*

692. By Aurélien Gâteau

[panel] Cleanup, simplify, comment text drawing code

691. By Aurélien Gâteau

[panel] Crude port of Unity label drawing code

690. By Aurélien Gâteau

[panel] Move qtgconf test up so that it can be used in panel

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2011-07-27 15:41:41 +0000
+++ CMakeLists.txt 2011-07-27 15:41:41 +0000
@@ -29,6 +29,7 @@
29pkg_check_modules(GTK REQUIRED gtk+-3.0)29pkg_check_modules(GTK REQUIRED gtk+-3.0)
30pkg_check_modules(GIO REQUIRED gio-2.0)30pkg_check_modules(GIO REQUIRED gio-2.0)
31pkg_check_modules(WNCK REQUIRED libwnck-3.0)31pkg_check_modules(WNCK REQUIRED libwnck-3.0)
32pkg_check_modules(QTGCONF REQUIRED libqtgconf)
3233
3334
34# GSettings schemas35# GSettings schemas
3536
=== modified file 'libunity-2d-private/src/CMakeLists.txt'
--- libunity-2d-private/src/CMakeLists.txt 2011-07-27 15:41:41 +0000
+++ libunity-2d-private/src/CMakeLists.txt 2011-07-27 15:41:41 +0000
@@ -31,6 +31,8 @@
31 ${CMAKE_CURRENT_BINARY_DIR}31 ${CMAKE_CURRENT_BINARY_DIR}
32 ${CMAKE_CURRENT_SOURCE_DIR}32 ${CMAKE_CURRENT_SOURCE_DIR}
33 ${GLIB_INCLUDE_DIRS}33 ${GLIB_INCLUDE_DIRS}
34 ${GTK_INCLUDE_DIRS}
35 ${PANGO_INCLUDE_DIRS}
34 ${WNCK_INCLUDE_DIRS}36 ${WNCK_INCLUDE_DIRS}
35 )37 )
3638
@@ -48,6 +50,8 @@
48 ${QT_QTOPENGL_LIBRARIES}50 ${QT_QTOPENGL_LIBRARIES}
49 ${X11_LIBRARIES}51 ${X11_LIBRARIES}
50 ${GLIB_LDFLAGS}52 ${GLIB_LDFLAGS}
53 ${GTK_LDFLAGS}
54 ${PANGO_LDFLAGS}
51 ${WNCK_LDFLAGS}55 ${WNCK_LDFLAGS}
52 )56 )
5357
5458
=== modified file 'libunity-2d-private/src/unity2dapplication.cpp'
--- libunity-2d-private/src/unity2dapplication.cpp 2011-07-27 15:41:41 +0000
+++ libunity-2d-private/src/unity2dapplication.cpp 2011-07-27 15:41:41 +0000
@@ -25,14 +25,59 @@
2525
26// libunity-2d26// libunity-2d
27#include <debug_p.h>27#include <debug_p.h>
28#include <gconnector.h>
29#include <gscopedpointer.h>
28#include <unity2ddebug.h>30#include <unity2ddebug.h>
2931
30// Qt32// Qt
33#include <QFont>
31#include <QWindowsStyle>34#include <QWindowsStyle>
3235
33// GTK36// GTK
34#include <gtk/gtk.h>37#include <gtk/gtk.h>
3538#include <pango/pango.h>
39
40///////////////////////////////
41class PlatformFontTracker
42{
43public:
44 PlatformFontTracker()
45 {
46 m_gConnector.connect(gtk_settings_get_default(), "notify::gtk-font-name",
47 G_CALLBACK(PlatformFontTracker::onFontChanged), this);
48
49 updateFont();
50 }
51
52private:
53 void updateFont()
54 {
55 gchar* fontName = 0;
56 g_object_get(gtk_settings_get_default(), "gtk-font-name", &fontName, NULL);
57 GScopedPointer<PangoFontDescription, pango_font_description_free> fontDescription(
58 pango_font_description_from_string(fontName)
59 );
60 g_free(fontName);
61
62 int size = pango_font_description_get_size(fontDescription.data());
63
64 QFont font = QFont(
65 pango_font_description_get_family(fontDescription.data()),
66 size / PANGO_SCALE
67 );
68
69 QApplication::setFont(font);
70 }
71
72 static void onFontChanged(GObject*, GParamSpec*, PlatformFontTracker* obj)
73 {
74 obj->updateFont();
75 }
76
77 GConnector m_gConnector;
78};
79
80///////////////////////////////
36AbstractX11EventFilter::~AbstractX11EventFilter()81AbstractX11EventFilter::~AbstractX11EventFilter()
37{82{
38 Unity2dApplication* application = Unity2dApplication::instance();83 Unity2dApplication* application = Unity2dApplication::instance();
@@ -41,6 +86,7 @@
41 }86 }
42}87}
4388
89///////////////////////////////
44static bool arrayContains(char** begin, char** end, const char* string)90static bool arrayContains(char** begin, char** end, const char* string)
45{91{
46 for (char** ptr = begin; ptr != end; ++ptr) {92 for (char** ptr = begin; ptr != end; ++ptr) {
@@ -83,6 +129,7 @@
83129
84Unity2dApplication::Unity2dApplication(int& argc, char** argv)130Unity2dApplication::Unity2dApplication(int& argc, char** argv)
85: QApplication(argc, argv)131: QApplication(argc, argv)
132, m_platformFontTracker(new PlatformFontTracker)
86{133{
87 /* Allow developers to run Unity 2D uninstalled by telling dconf-qt134 /* Allow developers to run Unity 2D uninstalled by telling dconf-qt
88 where to look for Unity 2D's schemas.135 where to look for Unity 2D's schemas.
@@ -96,6 +143,7 @@
96Unity2dApplication::~Unity2dApplication()143Unity2dApplication::~Unity2dApplication()
97{144{
98 qDeleteAll(m_x11EventFilters);145 qDeleteAll(m_x11EventFilters);
146 delete m_platformFontTracker;
99}147}
100148
101Unity2dApplication* Unity2dApplication::instance()149Unity2dApplication* Unity2dApplication::instance()
102150
=== modified file 'libunity-2d-private/src/unity2dapplication.h'
--- libunity-2d-private/src/unity2dapplication.h 2011-07-18 13:47:29 +0000
+++ libunity-2d-private/src/unity2dapplication.h 2011-07-27 15:41:41 +0000
@@ -27,6 +27,8 @@
2727
28class Unity2dApplication;28class Unity2dApplication;
2929
30class PlatformFontTracker;
31
30class AbstractX11EventFilter32class AbstractX11EventFilter
31{33{
32public:34public:
@@ -65,6 +67,7 @@
6567
66private:68private:
67 QList<AbstractX11EventFilter*> m_x11EventFilters;69 QList<AbstractX11EventFilter*> m_x11EventFilters;
70 PlatformFontTracker* m_platformFontTracker;
68};71};
6972
70#endif // UNITY2DAPPLICATION_H73#endif // UNITY2DAPPLICATION_H
7174
=== modified file 'panel/applets/CMakeLists.txt'
--- panel/applets/CMakeLists.txt 2011-07-27 15:41:41 +0000
+++ panel/applets/CMakeLists.txt 2011-07-27 15:41:41 +0000
@@ -12,12 +12,14 @@
12 appindicator/appindicatorapplet.cpp12 appindicator/appindicatorapplet.cpp
13 appindicator/sniitem.cpp13 appindicator/sniitem.cpp
14 appname/appnameapplet.cpp14 appname/appnameapplet.cpp
15 appname/croppedlabel.cpp
15 appname/menubarwidget.cpp16 appname/menubarwidget.cpp
16 appname/windowhelper.cpp17 appname/windowhelper.cpp
17 common/applet.cpp18 common/applet.cpp
18 common/indicatorentrywidget.cpp19 common/indicatorentrywidget.cpp
19 common/indicatorsmanager.cpp20 common/indicatorsmanager.cpp
20 common/indicatorwidget.cpp21 common/indicatorwidget.cpp
22 common/cairoutils.cpp
21 common/panelstyle.cpp23 common/panelstyle.cpp
22 homebutton/homebuttonapplet.cpp24 homebutton/homebuttonapplet.cpp
23 homebutton/homebutton.cpp25 homebutton/homebutton.cpp
@@ -41,6 +43,7 @@
41 ${CMAKE_CURRENT_SOURCE_DIR}/indicator43 ${CMAKE_CURRENT_SOURCE_DIR}/indicator
42 ${CMAKE_CURRENT_SOURCE_DIR}/unitycore44 ${CMAKE_CURRENT_SOURCE_DIR}/unitycore
43 ${QTBAMF_INCLUDE_DIRS}45 ${QTBAMF_INCLUDE_DIRS}
46 ${QTGCONF_INCLUDE_DIRS}
44 ${DBUSMENUQT_INCLUDE_DIRS}47 ${DBUSMENUQT_INCLUDE_DIRS}
45 ${GTK_INCLUDE_DIRS}48 ${GTK_INCLUDE_DIRS}
46 ${WNCK_INCLUDE_DIRS}49 ${WNCK_INCLUDE_DIRS}
@@ -58,6 +61,7 @@
58 ${QT_QTCORE_LIBRARIES}61 ${QT_QTCORE_LIBRARIES}
59 ${DBUSMENUQT_LDFLAGS}62 ${DBUSMENUQT_LDFLAGS}
60 ${QTBAMF_LDFLAGS}63 ${QTBAMF_LDFLAGS}
64 ${QTGCONF_LDFLAGS}
61 ${GTK_LDFLAGS}65 ${GTK_LDFLAGS}
62 ${WNCK_LDFLAGS}66 ${WNCK_LDFLAGS}
63 ${X11_LIBRARIES}67 ${X11_LIBRARIES}
6468
=== modified file 'panel/applets/appname/appnameapplet.cpp'
--- panel/applets/appname/appnameapplet.cpp 2011-07-27 15:41:41 +0000
+++ panel/applets/appname/appnameapplet.cpp 2011-07-27 15:41:41 +0000
@@ -23,6 +23,7 @@
23#include "appnameapplet.h"23#include "appnameapplet.h"
2424
25// Local25// Local
26#include "croppedlabel.h"
26#include "menubarwidget.h"27#include "menubarwidget.h"
27#include "windowhelper.h"28#include "windowhelper.h"
2829
@@ -49,9 +50,7 @@
4950
50static const int WINDOW_BUTTONS_RIGHT_MARGIN = 4;51static const int WINDOW_BUTTONS_RIGHT_MARGIN = 4;
5152
52static const int APPNAME_LABEL_LEFT_MARGIN = 12;53static const int APPNAME_LABEL_LEFT_MARGIN = 6;
53
54static const int FADEOUT_WIDTH = 16;
5554
56namespace Unity2d55namespace Unity2d
57{56{
@@ -106,50 +105,6 @@
106 }105 }
107};106};
108107
109/**
110 * This label makes sure minimumSizeHint() is not set. This ensures the applet
111 * does not get wider if a window title is very long
112 */
113class CroppedLabel : public QLabel
114{
115public:
116 CroppedLabel(QWidget* parent = 0)
117 : QLabel(parent)
118 {}
119
120 QSize minimumSizeHint() const
121 {
122 return QWidget::minimumSizeHint();
123 }
124
125protected:
126 void paintEvent(QPaintEvent* event)
127 {
128 QImage image(width(), height(), QImage::Format_ARGB32_Premultiplied);
129 {
130 QPainter painter(&image);
131 painter.initFrom(this);
132 painter.setCompositionMode(QPainter::CompositionMode_Source);
133 painter.fillRect(rect(), Qt::transparent);
134
135 painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
136 painter.drawText(contentsRect(), Qt::AlignLeft | Qt::AlignVCenter, text());
137
138 if (QLabel::minimumSizeHint().width() > contentsRect().width()) {
139 // Text does not fit, fade the end
140 painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
141 QRect gradientRect(width() - FADEOUT_WIDTH, 0, FADEOUT_WIDTH, height());
142 QLinearGradient gradient(gradientRect.topLeft(), gradientRect.topRight());
143 gradient.setColorAt(0, Qt::white);
144 gradient.setColorAt(1, Qt::transparent);
145 painter.fillRect(gradientRect, gradient);
146 }
147 }
148 QPainter painter(this);
149 painter.drawImage(0, 0, image);
150 }
151};
152
153struct AppNameAppletPrivate108struct AppNameAppletPrivate
154{109{
155 AppNameApplet* q;110 AppNameApplet* q;
156111
=== added file 'panel/applets/appname/croppedlabel.cpp'
--- panel/applets/appname/croppedlabel.cpp 1970-01-01 00:00:00 +0000
+++ panel/applets/appname/croppedlabel.cpp 2011-07-27 15:41:41 +0000
@@ -0,0 +1,140 @@
1/*
2 * This file is part of unity-2d
3 *
4 * Copyright 2011 Canonical Ltd.
5 *
6 * Authors:
7 * - Aurélien Gâteau <aurelien.gateau@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// Self
22#include "croppedlabel.h"
23
24// Local
25#include <cairoutils.h>
26#include <panelstyle.h>
27
28// unity-2d
29#include <debug_p.h>
30
31// libqtgconf
32#include <gconfitem-qml-wrapper.h>
33
34// Qt
35#include <QImage>
36#include <QPainter>
37
38// GTK
39#include <gtk/gtk.h>
40
41static const int FADEOUT_WIDTH = 30;
42
43static const char* WINDOW_TITLE_FONT_KEY = "/apps/metacity/general/titlebar_font";
44
45CroppedLabel::CroppedLabel(QWidget* parent)
46: QLabel(parent)
47{
48}
49
50QSize CroppedLabel::minimumSizeHint() const
51{
52 return QWidget::minimumSizeHint();
53}
54
55static void paintFadeoutGradient(QImage* image)
56{
57 QPainter painter(image);
58 painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
59 QRect gradientRect(image->width() - FADEOUT_WIDTH, 0, FADEOUT_WIDTH, image->height());
60 QLinearGradient gradient(gradientRect.topLeft(), gradientRect.topRight());
61 gradient.setColorAt(0, Qt::white);
62 gradient.setColorAt(1, Qt::transparent);
63 painter.fillRect(gradientRect, gradient);
64}
65
66static QString getWindowTitleFontName()
67{
68 GConfItemQmlWrapper client;
69 client.setKey(WINDOW_TITLE_FONT_KEY);
70 return client.getValue().toString();
71}
72
73void CroppedLabel::paintEvent(QPaintEvent* event)
74{
75 // Create an image filled with background brush (to avoid subpixel hinting
76 // artefacts around text)
77 QImage image(width(), height(), QImage::Format_ARGB32_Premultiplied);
78 {
79 QPainter painter(&image);
80 painter.initFrom(this);
81 painter.eraseRect(rect());
82 }
83
84 // Create a pango layout
85 GObjectScopedPointer<PangoContext> pangoContext(gdk_pango_context_get());
86 GObjectScopedPointer<PangoLayout> layout(pango_layout_new(pangoContext.data()));
87
88 // Set font
89 QByteArray fontName = getWindowTitleFontName().toUtf8();
90 PangoFontDescription* desc = pango_font_description_from_string(fontName.data());
91 pango_layout_set_font_description(layout.data(), desc);
92 pango_font_description_free(desc);
93
94 // Set text
95 QByteArray utf8Text = text().toUtf8();
96 pango_layout_set_text (layout.data(), utf8Text.data(), -1);
97
98 // Get text size
99 int textWidth = 0;
100 int textHeight = 0;
101 pango_layout_get_pixel_size(layout.data(), &textWidth, &textHeight);
102
103 // Draw text
104 CairoUtils::SurfacePointer surface(CairoUtils::createSurfaceForQImage(&image));
105 CairoUtils::Pointer cr(cairo_create(surface.data()));
106
107 PanelStyle* style = PanelStyle::instance();
108 GtkStyleContext* style_context = style->styleContext();
109
110 gtk_style_context_save(style_context);
111
112 GtkWidgetPath* widget_path = gtk_widget_path_new();
113 gtk_widget_path_append_type(widget_path, GTK_TYPE_MENU_BAR);
114 gtk_widget_path_append_type(widget_path, GTK_TYPE_MENU_ITEM);
115 gtk_widget_path_iter_set_name(widget_path, -1 , "UnityPanelWidget");
116
117 gtk_style_context_set_path(style_context, widget_path);
118 gtk_style_context_add_class(style_context, GTK_STYLE_CLASS_MENUBAR);
119 gtk_style_context_add_class(style_context, GTK_STYLE_CLASS_MENUITEM);
120
121 gtk_render_layout(style_context, cr.data(),
122 contentsRect().left(),
123 contentsRect().top() + (height() - textHeight) / 2,
124 layout.data());
125
126 gtk_widget_path_free(widget_path);
127
128 gtk_style_context_restore(style_context);
129
130 // Fade if necessary
131 if (textWidth > contentsRect().width()) {
132 paintFadeoutGradient(&image);
133 }
134
135 // Paint on our widget
136 QPainter painter(this);
137 painter.drawImage(0, 0, image);
138}
139
140#include "croppedlabel.moc"
0141
=== added file 'panel/applets/appname/croppedlabel.h'
--- panel/applets/appname/croppedlabel.h 1970-01-01 00:00:00 +0000
+++ panel/applets/appname/croppedlabel.h 2011-07-27 15:41:41 +0000
@@ -0,0 +1,45 @@
1/*
2 * This file is part of unity-2d
3 *
4 * Copyright 2011 Canonical Ltd.
5 *
6 * Authors:
7 * - Aurélien Gâteau <aurelien.gateau@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#ifndef CROPPEDLABEL_H
22#define CROPPEDLABEL_H
23
24// Local
25
26// Qt
27#include <QLabel>
28
29/**
30 * This label makes sure minimumSizeHint() is not set. This ensures the applet
31 * does not get wider if a window title is very long
32 */
33class CroppedLabel : public QLabel
34{
35 Q_OBJECT
36public:
37 CroppedLabel(QWidget* parent = 0);
38
39 QSize minimumSizeHint() const;
40
41protected:
42 void paintEvent(QPaintEvent*);
43};
44
45#endif /* CROPPEDLABEL_H */
046
=== added file 'panel/applets/common/cairoutils.cpp'
--- panel/applets/common/cairoutils.cpp 1970-01-01 00:00:00 +0000
+++ panel/applets/common/cairoutils.cpp 2011-07-27 15:41:41 +0000
@@ -0,0 +1,42 @@
1/*
2 * This file is part of unity-2d
3 *
4 * Copyright 2011 Canonical Ltd.
5 *
6 * Authors:
7 * - Aurélien Gâteau <aurelien.gateau@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// Self
22#include "cairoutils.h"
23
24// Local
25
26// Qt
27#include <QImage>
28
29namespace CairoUtils {
30
31cairo_surface_t* createSurfaceForQImage(QImage* image)
32{
33 return cairo_image_surface_create_for_data(
34 image->bits(),
35 CAIRO_FORMAT_ARGB32,
36 image->width(),
37 image->height(),
38 image->bytesPerLine()
39 );
40}
41
42} // namespace
043
=== added file 'panel/applets/common/cairoutils.h'
--- panel/applets/common/cairoutils.h 1970-01-01 00:00:00 +0000
+++ panel/applets/common/cairoutils.h 2011-07-27 15:41:41 +0000
@@ -0,0 +1,47 @@
1/*
2 * This file is part of unity-2d
3 *
4 * Copyright 2011 Canonical Ltd.
5 *
6 * Authors:
7 * - Aurélien Gâteau <aurelien.gateau@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#ifndef CAIROUTILS_H
22#define CAIROUTILS_H
23
24// Local
25#include <gscopedpointer.h>
26
27// Qt
28
29// Cairo
30#include <cairo.h>
31
32class QImage;
33
34namespace CairoUtils {
35
36typedef GScopedPointer<cairo_surface_t, cairo_surface_destroy> SurfacePointer;
37typedef GScopedPointer<cairo_t, cairo_destroy> Pointer;
38
39/**
40 * Creates a Cairo surface for a QImage.
41 * QImage format must be Format_ARGB32_Premultiplied.
42 */
43cairo_surface_t* createSurfaceForQImage(QImage*);
44
45} // namespace
46
47#endif /* CAIROUTILS_H */
048
=== removed file 'panel/applets/common/fakecairo.h'
--- panel/applets/common/fakecairo.h 2011-07-27 15:41:41 +0000
+++ panel/applets/common/fakecairo.h 1970-01-01 00:00:00 +0000
@@ -1,125 +0,0 @@
1/*
2 * This file is part of unity-2d
3 *
4 * Copyright 2011 Canonical Ltd.
5 *
6 * Authors:
7 * - Aurélien Gâteau <aurelien.gateau@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#ifndef FAKECAIRO_H
22#define FAKECAIRO_H
23
24// NuxCore
25#include <NuxCore/Color.h>
26
27// Qt
28#include <QPainter>
29#include <QPainterPath>
30
31/*
32 * This module attempts to fake Cairo calls using QPainter, making it easier to
33 * port Cairo paint operations to Qt
34 */
35struct fcairo_t
36{
37 fcairo_t(QPainter* _painter)
38 : painter(_painter)
39 {
40 painter->save();
41 }
42
43 ~fcairo_t()
44 {
45 painter->restore();
46 }
47
48 QPainter* painter;
49 QPainterPath path;
50};
51
52inline void fcairo_arc(fcairo_t& cr, qreal xc, qreal yc, qreal radius, qreal angle1, qreal angle2)
53{
54 QRectF rect(xc - radius, yc - radius, radius * 2, radius * 2);
55
56 while (angle2 < angle1) {
57 angle2 += 2 * M_PI;
58 }
59
60 qreal start = (2. - angle1 / M_PI) * 180;
61 qreal stop = (2. - angle2 / M_PI) * 180;
62 cr.path.arcTo(rect, start, stop - start);
63}
64
65inline void fcairo_move_to(fcairo_t& cr, qreal x, qreal y)
66{
67 cr.path.moveTo(x, y);
68}
69
70inline void fcairo_line_to(fcairo_t& cr, qreal x, qreal y)
71{
72 cr.path.lineTo(x, y);
73}
74
75inline void fcairo_fill_preserve(fcairo_t& cr)
76{
77 cr.painter->fillPath(cr.path, cr.painter->brush());
78}
79
80inline void fcairo_stroke(fcairo_t& cr)
81{
82 QPen pen(cr.painter->brush().color(), 1);
83 cr.painter->strokePath(cr.path, pen);
84 cr.path = QPainterPath();
85}
86
87typedef QGradient fcairo_pattern_t;
88
89inline fcairo_pattern_t* fcairo_pattern_create_linear (qreal x1, qreal y1, qreal x2, qreal y2)
90{
91 return new QLinearGradient(x1, y1, x2, y2);
92}
93
94inline void fcairo_pattern_destroy(fcairo_pattern_t* pattern)
95{
96 delete pattern;
97}
98
99inline void fcairo_pattern_add_color_stop_rgba(fcairo_pattern_t* pattern, qreal offset, qreal r, qreal g, qreal b, qreal a)
100{
101 pattern->setColorAt(offset, QColor::fromRgbF(r, g, b, a));
102}
103
104inline void fcairo_set_source(fcairo_t& cr, fcairo_pattern_t* pattern)
105{
106 cr.painter->setPen(Qt::NoPen);
107 cr.painter->setBrush(*pattern);
108}
109
110inline void fcairo_set_source_rgb(fcairo_t& cr, qreal r, qreal g, qreal b)
111{
112 cr.painter->setBrush(QColor::fromRgbF(r, g, b));
113}
114
115inline nux::color::Color nuxColorFromQColor(const QColor& qColor)
116{
117 nux::color::Color color;
118 color.red = qColor.redF();
119 color.green = qColor.greenF();
120 color.blue = qColor.blueF();
121 color.alpha = qColor.alphaF();
122 return color;
123}
124
125#endif /* FAKECAIRO_H */
1260
=== modified file 'panel/applets/common/indicatorentrywidget.cpp'
--- panel/applets/common/indicatorentrywidget.cpp 2011-07-27 15:41:41 +0000
+++ panel/applets/common/indicatorentrywidget.cpp 2011-07-27 15:41:41 +0000
@@ -22,8 +22,9 @@
22#include "indicatorentrywidget.h"22#include "indicatorentrywidget.h"
2323
24// Local24// Local
25#include <cairoutils.h>
25#include <debug_p.h>26#include <debug_p.h>
26#include <fakecairo.h>27#include <gscopedpointer.h>
27#include <panelstyle.h>28#include <panelstyle.h>
2829
29// Qt30// Qt
@@ -42,56 +43,25 @@
4243
43using namespace unity::indicator;44using namespace unity::indicator;
4445
45// Copied from libdbusmenu-qt
46static QString swapMnemonicChar(const QString &in, const char src, const char dst)
47{
48 QString out;
49 bool mnemonicFound = false;
50
51 for (int pos = 0; pos < in.length(); ) {
52 QChar ch = in[pos];
53 if (ch == src) {
54 if (pos == in.length() - 1) {
55 // 'src' at the end of string, skip it
56 ++pos;
57 } else {
58 if (in[pos + 1] == src) {
59 // A real 'src'
60 out += src;
61 pos += 2;
62 } else if (!mnemonicFound) {
63 // We found the mnemonic
64 mnemonicFound = true;
65 out += dst;
66 ++pos;
67 } else {
68 // We already have a mnemonic, just skip the char
69 ++pos;
70 }
71 }
72 } else if (ch == dst) {
73 // Escape 'dst'
74 out += dst;
75 out += dst;
76 ++pos;
77 } else {
78 out += ch;
79 ++pos;
80 }
81 }
82
83 return out;
84}
85
86IndicatorEntryWidget::IndicatorEntryWidget(const Entry::Ptr& entry)46IndicatorEntryWidget::IndicatorEntryWidget(const Entry::Ptr& entry)
87: m_entry(entry)47: m_entry(entry)
88, m_padding(PADDING)48, m_padding(PADDING)
89, m_hasIcon(false)49, m_hasIcon(false)
90, m_hasLabel(false)50, m_hasLabel(false)
51, m_gtkWidgetPath(gtk_widget_path_new())
91{52{
53 gtk_widget_path_append_type(m_gtkWidgetPath, GTK_TYPE_WINDOW);
54 gtk_widget_path_iter_set_name(m_gtkWidgetPath, -1 , "UnityPanelWidget");
55 gtk_widget_path_append_type(m_gtkWidgetPath, GTK_TYPE_MENU_BAR);
56 gtk_widget_path_append_type(m_gtkWidgetPath, GTK_TYPE_MENU_ITEM);
57
92 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);58 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
93 m_entry->updated.connect(sigc::mem_fun(this, &IndicatorEntryWidget::updatePix));59 m_entry->updated.connect(sigc::mem_fun(this, &IndicatorEntryWidget::updatePix));
94 updatePix();60}
61
62IndicatorEntryWidget::~IndicatorEntryWidget()
63{
64 gtk_widget_path_free(m_gtkWidgetPath);
95}65}
9666
97QSize IndicatorEntryWidget::minimumSizeHint() const67QSize IndicatorEntryWidget::minimumSizeHint() const
@@ -104,105 +74,47 @@
104 return m_pix.size();74 return m_pix.size();
105}75}
10676
77void IndicatorEntryWidget::resizeEvent(QResizeEvent* event)
78{
79 QWidget::resizeEvent(event);
80 updatePix();
81}
82
107void IndicatorEntryWidget::paintEvent(QPaintEvent*)83void IndicatorEntryWidget::paintEvent(QPaintEvent*)
108{84{
109 if (!m_pix.isNull()) {85 if (!m_pix.isNull()) {
110 QPainter painter(this);86 QPainter painter(this);
111 if (m_entry->active()) {
112 paintActiveBackground(&painter);
113 }
114 painter.drawPixmap(0, 0, m_pix);87 painter.drawPixmap(0, 0, m_pix);
115 }88 }
116}89}
11790
11891
119void IndicatorEntryWidget::paintActiveBackground(QPainter* painter)92void IndicatorEntryWidget::paintActiveBackground(QImage* image)
120{93{
121 // This code should be kept in sync with the draw_menu_bg() function from94 // This code should be kept in sync with corresponding unityshell code from
122 // plugins/unityshell/src/PanelIndicatorObjectEntryView.cpp95 // plugins/unityshell/src/PanelIndicatorObjectEntryView.cpp
123 int radius = 4;96
124 double x = 0;97 // Get a surface and a context
125 double y = 0;98 CairoUtils::SurfacePointer surface(CairoUtils::createSurfaceForQImage(image));
126 double xos = 0.5;99 CairoUtils::Pointer cr(cairo_create(surface.data()));
127 double yos = 0.5;100
128 /* FIXME */101 // Init style
129 double mpi = 3.14159265358979323846;102 GtkStyleContext* styleContext = PanelStyle::instance()->styleContext();
130103
131 PanelStyle* style = PanelStyle::instance();104 gtk_style_context_save(styleContext);
132 nux::color::Color bgtop = nuxColorFromQColor(style->backgroundTopColor());105
133 nux::color::Color bgbot = nuxColorFromQColor(style->backgroundBottomColor());106 gtk_style_context_set_path(styleContext, m_gtkWidgetPath);
134 nux::color::Color line = nuxColorFromQColor(style->lineColor());107 gtk_style_context_add_class(styleContext, GTK_STYLE_CLASS_MENUBAR);
135108 gtk_style_context_add_class(styleContext, GTK_STYLE_CLASS_MENUITEM);
136 painter->setRenderHint(QPainter::Antialiasing);109 gtk_style_context_set_state(styleContext, GTK_STATE_FLAG_PRELIGHT);
137110
138 fcairo_t cr(painter);111 // Draw
139112 // FIXME(Cimi) probably some padding is needed here.
140 fcairo_move_to (cr, x+xos+radius, y+yos);113 gtk_render_background(styleContext, cr.data(), 0, 0, width(), height());
141 fcairo_arc (cr, x+xos+width()-xos*2-radius, y+yos+radius, radius, mpi*1.5, mpi*2);114 gtk_render_frame(styleContext, cr.data(), 0, 0, width(), height());
142 fcairo_line_to (cr, x+xos+width()-xos*2, y+yos+height()-yos*2+2);115
143 fcairo_line_to (cr, x+xos, y+yos+height()-yos*2+2);116 // Clean up
144 fcairo_arc (cr, x+xos+radius, y+yos+radius, radius, mpi, mpi*1.5);117 gtk_style_context_restore(styleContext);
145
146 fcairo_pattern_t * pat = fcairo_pattern_create_linear (x+xos, y, x+xos, y+height()-yos*2+2);
147 fcairo_pattern_add_color_stop_rgba (pat, 0.0,
148 bgtop.red,
149 bgtop.green,
150 bgtop.blue,
151 1.0f - bgbot.red);
152 fcairo_pattern_add_color_stop_rgba (pat, 1.0,
153 bgbot.red,
154 bgbot.green,
155 bgbot.blue,
156 1.0f - bgtop.red);
157 fcairo_set_source (cr, pat);
158 fcairo_fill_preserve (cr);
159 fcairo_pattern_destroy (pat);
160
161 /*
162 pat = fcairo_pattern_create_linear (x+xos, y, x+xos, y+height()-yos*2+2);
163 fcairo_pattern_add_color_stop_rgba (pat, 0.0,
164 line.red,
165 line.green,
166 line.blue,
167 1.0f);
168 fcairo_pattern_add_color_stop_rgba (pat, 1.0,
169 line.red,
170 line.green,
171 line.blue,
172 1.0f);
173 fcairo_set_source (cr, pat);
174 */
175 fcairo_set_source_rgb (cr, line.red, line.green, line.blue);
176 fcairo_stroke (cr);
177 //fcairo_pattern_destroy (pat);
178
179 xos++;
180 yos++;
181
182 /* enlarging the area to not draw the lightborder at bottom, ugly trick :P */
183 fcairo_move_to (cr, x+radius+xos, y+yos);
184 fcairo_arc (cr, x+xos+width()-xos*2-radius, y+yos+radius, radius, mpi*1.5, mpi*2);
185 fcairo_line_to (cr, x+xos+width()-xos*2, y+yos+height()-yos*2+3);
186 fcairo_line_to (cr, x+xos, y+yos+height()-yos*2+3);
187 fcairo_arc (cr, x+xos+radius, y+yos+radius, radius, mpi, mpi*1.5);
188
189 /*
190 pat = fcairo_pattern_create_linear (x+xos, y, x+xos, y+height()-yos*2+3);
191 fcairo_pattern_add_color_stop_rgba (pat, 0.0,
192 bgbot.red,
193 bgbot.green,
194 bgbot.blue,
195 1.0f);
196 fcairo_pattern_add_color_stop_rgba (pat, 1.0,
197 bgbot.red,
198 bgbot.green,
199 bgbot.blue,
200 1.0f);
201 fcairo_set_source (cr, pat);
202 */
203 fcairo_set_source_rgb (cr, bgbot.red, bgbot.green, bgbot.blue);
204 fcairo_stroke (cr);
205 //fcairo_pattern_destroy (pat);
206}118}
207119
208void IndicatorEntryWidget::updatePix()120void IndicatorEntryWidget::updatePix()
@@ -213,6 +125,8 @@
213 int iconX = m_padding;125 int iconX = m_padding;
214 int labelX = 0;126 int labelX = 0;
215127
128 GObjectScopedPointer<PangoLayout> pangoLayout;
129
216 // Compute width, labelX and update m_has{Icon,Label}130 // Compute width, labelX and update m_has{Icon,Label}
217 QPixmap iconPix;131 QPixmap iconPix;
218 if (m_entry->image_visible()) {132 if (m_entry->image_visible()) {
@@ -225,17 +139,18 @@
225 width += iconPix.width();139 width += iconPix.width();
226 }140 }
227141
228 QString label = QString::fromUtf8(m_entry->label().c_str());142 m_hasLabel = !m_entry->label().empty() && m_entry->label_visible();
229 label = swapMnemonicChar(label, '_', '&');
230 m_hasLabel = !label.isEmpty() && m_entry->label_visible();
231 if (m_hasLabel) {143 if (m_hasLabel) {
232 if (m_hasIcon) {144 if (m_hasIcon) {
233 width += SPACING;145 width += SPACING;
234 }146 }
235 labelX = width;147 labelX = width;
236 QString visibleLabel = label;148 pangoLayout.reset(createPangoLayout());
237 visibleLabel.remove('&');149 int labelWidth;
238 width += fontMetrics().width(visibleLabel);150 int labelHeight;
151 pango_layout_get_pixel_size(pangoLayout.data(), &labelWidth, &labelHeight);
152
153 width += labelWidth;
239 }154 }
240155
241 width += m_padding;156 width += m_padding;
@@ -245,38 +160,27 @@
245 if (!m_hasIcon && !m_hasLabel) {160 if (!m_hasIcon && !m_hasLabel) {
246 m_pix = QPixmap();161 m_pix = QPixmap();
247 } else {162 } else {
248 m_pix = QPixmap(width, 24);163 QImage img(width, height(), QImage::Format_ARGB32_Premultiplied);
249 m_pix.fill(Qt::transparent);164 QPainter painter(&img);
250 QPainter painter(&m_pix);
251 painter.initFrom(this);165 painter.initFrom(this);
166 painter.eraseRect(img.rect());
167 if (m_entry->active()) {
168 paintActiveBackground(&img);
169 }
252 if (m_hasIcon) {170 if (m_hasIcon) {
253 bool disabled = !m_entry->image_sensitive();171 bool disabled = !m_entry->image_sensitive();
254 if (disabled) {172 if (disabled) {
255 painter.setOpacity(0.5);173 painter.setOpacity(0.5);
256 }174 }
257 painter.drawPixmap(iconX, 0, iconPix);175 painter.drawPixmap(iconX, (height() - iconPix.height()) / 2, iconPix);
258 if (disabled) {176 if (disabled) {
259 painter.setOpacity(1);177 painter.setOpacity(1);
260 }178 }
261 }179 }
262 if (m_hasLabel) {180 if (m_hasLabel) {
263 PanelStyle* style = PanelStyle::instance();181 paintLabel(&img, pangoLayout.data(), labelX);
264
265 int flags = Qt::AlignLeft | Qt::AlignVCenter;
266 flags |= m_entry->show_now() ? Qt::TextShowMnemonic : Qt::TextHideMnemonic;
267
268 // Shadow
269 QColor color = style->textShadowColor();
270 color.setAlphaF(1. - color.redF());
271 painter.setPen(color);
272 painter.drawText(labelX, 1, width - labelX, m_pix.height(), flags, label);
273
274 // Text
275 color = style->textColor();
276 color.setAlphaF(m_entry->label_sensitive() ? 1. : .5);
277 painter.setPen(color);
278 painter.drawText(labelX, 0, width - labelX, m_pix.height(), flags, label);
279 }182 }
183 m_pix = QPixmap::fromImage(img);
280 }184 }
281185
282 // Notify others we changed, but only trigger a layout update if necessary186 // Notify others we changed, but only trigger a layout update if necessary
@@ -294,6 +198,80 @@
294 }198 }
295}199}
296200
201PangoLayout* IndicatorEntryWidget::createPangoLayout()
202{
203 // Parse
204 PangoAttrList* attrs = NULL;
205 if (m_entry->show_now()) {
206 if (!pango_parse_markup(m_entry->label().c_str(),
207 -1,
208 '_',
209 &attrs,
210 NULL,
211 NULL,
212 NULL))
213 {
214 UQ_WARNING << "pango_parse_markup failed";
215 }
216 }
217
218 // Create layout
219 GObjectScopedPointer<PangoContext> pangoContext(gdk_pango_context_get());
220 PangoLayout* layout = pango_layout_new(pangoContext.data());
221
222 if (attrs) {
223 pango_layout_set_attributes(layout, attrs);
224 pango_attr_list_unref(attrs);
225 }
226
227 // Set font
228 char* font_description = NULL;
229 GtkSettings *settings = gtk_settings_get_default();
230 g_object_get(settings,
231 "gtk-font-name", &font_description,
232 NULL);
233 PangoFontDescription* desc = pango_font_description_from_string(font_description);
234 pango_font_description_set_weight(desc, PANGO_WEIGHT_NORMAL);
235 pango_layout_set_font_description(layout, desc);
236 pango_font_description_free(desc);
237 g_free(font_description);
238
239 // Set text
240 QString label = QString::fromUtf8(m_entry->label().c_str());
241 label.replace('_', QString());
242 QByteArray utf8Label = label.toUtf8();
243 pango_layout_set_text(layout, utf8Label.data(), -1);
244
245 return layout;
246}
247
248void IndicatorEntryWidget::paintLabel(QImage* image, PangoLayout* layout, int labelX)
249{
250 // This code should be kept in sync with corresponding unityshell code from
251 // plugins/unityshell/src/PanelIndicatorObjectEntryView.cpp
252 int labelWidth, labelHeight;
253 pango_layout_get_pixel_size(layout, &labelWidth, &labelHeight);
254 CairoUtils::SurfacePointer surface(CairoUtils::createSurfaceForQImage(image));
255 CairoUtils::Pointer cr(cairo_create(surface.data()));
256 pango_cairo_update_layout(cr.data(), layout);
257
258 PanelStyle* style = PanelStyle::instance();
259 GtkStyleContext* styleContext = style->styleContext();
260
261 gtk_style_context_save(styleContext);
262
263 gtk_style_context_set_path(styleContext, m_gtkWidgetPath);
264 gtk_style_context_add_class(styleContext, GTK_STYLE_CLASS_MENUBAR);
265 gtk_style_context_add_class(styleContext, GTK_STYLE_CLASS_MENUITEM);
266
267 if (m_entry->active()) {
268 gtk_style_context_set_state(styleContext, GTK_STATE_FLAG_PRELIGHT);
269 }
270
271 gtk_render_layout(styleContext, cr.data(), labelX, (image->height() - labelHeight) / 2, layout);
272 gtk_style_context_restore(styleContext);
273}
274
297QPixmap IndicatorEntryWidget::decodeIcon()275QPixmap IndicatorEntryWidget::decodeIcon()
298{276{
299 QPixmap pix;277 QPixmap pix;
300278
=== modified file 'panel/applets/common/indicatorentrywidget.h'
--- panel/applets/common/indicatorentrywidget.h 2011-07-27 15:41:41 +0000
+++ panel/applets/common/indicatorentrywidget.h 2011-07-27 15:41:41 +0000
@@ -29,6 +29,9 @@
29// Qt29// Qt
30#include <QWidget>30#include <QWidget>
3131
32struct _GtkWidgetPath;
33struct _PangoLayout;
34
32class QPainter;35class QPainter;
3336
34class IndicatorEntryWidget : public QWidget, public sigc::trackable37class IndicatorEntryWidget : public QWidget, public sigc::trackable
@@ -36,6 +39,7 @@
36Q_OBJECT39Q_OBJECT
37public:40public:
38 IndicatorEntryWidget(const unity::indicator::Entry::Ptr& entry);41 IndicatorEntryWidget(const unity::indicator::Entry::Ptr& entry);
42 ~IndicatorEntryWidget();
3943
40 QSize minimumSizeHint() const;44 QSize minimumSizeHint() const;
41 QSize sizeHint() const;45 QSize sizeHint() const;
@@ -61,6 +65,7 @@
61 void isEmptyChanged();65 void isEmptyChanged();
6266
63protected:67protected:
68 void resizeEvent(QResizeEvent*);
64 void paintEvent(QPaintEvent*);69 void paintEvent(QPaintEvent*);
65 void mousePressEvent(QMouseEvent*);70 void mousePressEvent(QMouseEvent*);
66 void mouseReleaseEvent(QMouseEvent*);71 void mouseReleaseEvent(QMouseEvent*);
@@ -73,9 +78,13 @@
73 int m_padding;78 int m_padding;
74 bool m_hasIcon;79 bool m_hasIcon;
75 bool m_hasLabel;80 bool m_hasLabel;
81 struct _GtkWidgetPath* m_gtkWidgetPath;
76 void updatePix();82 void updatePix();
77 QPixmap decodeIcon();83 QPixmap decodeIcon();
78 void paintActiveBackground(QPainter*);84 void paintActiveBackground(QImage*);
85
86 struct _PangoLayout* createPangoLayout();
87 void paintLabel(QImage*, struct _PangoLayout*, int labelX);
79};88};
8089
81#endif /* INDICATORENTRYWIDGET_H */90#endif /* INDICATORENTRYWIDGET_H */
8291
=== modified file 'panel/applets/common/panelstyle.cpp'
--- panel/applets/common/panelstyle.cpp 2011-07-27 15:41:41 +0000
+++ panel/applets/common/panelstyle.cpp 2011-07-27 15:41:41 +0000
@@ -22,92 +22,54 @@
22#include "panelstyle.h"22#include "panelstyle.h"
2323
24// libunity-2d24// libunity-2d
25#include <cairoutils.h>
25#include <debug_p.h>26#include <debug_p.h>
26#include <gconnector.h>27#include <gconnector.h>
27#include <gscopedpointer.h>28#include <gscopedpointer.h>
2829
29// Qt30// Qt
30#include <QApplication>31#include <QApplication>
31#include <QColor>
32#include <QFont>
33#include <QPalette>32#include <QPalette>
3433
35// GTK34// GTK
36#include <gtk/gtk.h>35#include <gtk/gtk.h>
37#include <pango/pango.h>
38
39typedef void (*ColorGetter)(GtkStyleContext*, GtkStateFlags, GdkRGBA*);
40
41inline QColor colorFromContext(ColorGetter getter, GtkStyleContext* context, GtkStateFlags state)
42{
43 GdkRGBA color;
44 getter(context, state, &color);
45 return QColor::fromRgbF(color.red, color.green, color.blue, color.alpha);
46}
4736
48class PanelStylePrivate37class PanelStylePrivate
49{38{
50public:39public:
51 PanelStyle* q;40 PanelStyle* q;
52 GtkWidget* m_offScreenWindow;41 GObjectScopedPointer<GtkStyleContext> m_styleContext;
53 GConnector m_gConnector;42 GConnector m_gConnector;
5443
55 QColor m_textColor;
56 QColor m_backgroundTopColor;
57 QColor m_backgroundBottomColor;
58 QColor m_textShadowColor;
59 QColor m_lineColor;
60 QFont m_font;
61
62 static void onThemeChanged(GObject*, GParamSpec*, gpointer data)44 static void onThemeChanged(GObject*, GParamSpec*, gpointer data)
63 {45 {
64 PanelStylePrivate* priv = reinterpret_cast<PanelStylePrivate*>(data);46 PanelStylePrivate* priv = reinterpret_cast<PanelStylePrivate*>(data);
65 priv->updatePalette();47 priv->updatePalette();
66 }48 }
6749
68 static void onFontChanged(GObject*, GParamSpec*, gpointer data)
69 {
70 PanelStylePrivate* priv = reinterpret_cast<PanelStylePrivate*>(data);
71 priv->updateFont();
72 }
73
74 void updatePalette()50 void updatePalette()
75 {51 {
76 GtkStyleContext* context = gtk_widget_get_style_context(m_offScreenWindow);52 GtkStyleContext* context = m_styleContext.data();
77 UQ_RETURN_IF_FAIL(context);53 gtk_style_context_invalidate(context);
7854
79 m_textColor = colorFromContext(gtk_style_context_get_color, context, GTK_STATE_FLAG_NORMAL);55 // Without this line, it seems the GtkStyleContext is not correctly
80 m_textShadowColor = colorFromContext(gtk_style_context_get_color, context, GTK_STATE_FLAG_SELECTED);56 // initialized and we get some uninitialized pixels in the background
81 m_lineColor = colorFromContext(gtk_style_context_get_background_color, context, GTK_STATE_FLAG_NORMAL).darker(130);57 // brush.
82 m_backgroundTopColor = colorFromContext(gtk_style_context_get_background_color, context, GTK_STATE_FLAG_ACTIVE);58 gtk_style_context_get(context, GTK_STATE_FLAG_NORMAL, NULL);
83 m_backgroundBottomColor = colorFromContext(gtk_style_context_get_background_color, context, GTK_STATE_FLAG_NORMAL);
8459
85 QPalette pal;60 QPalette pal;
86 pal.setColor(QPalette::Window, m_backgroundTopColor);61 pal.setBrush(QPalette::Window, generateBackgroundBrush());
87 pal.setColor(QPalette::Button, m_backgroundTopColor);
88 pal.setColor(QPalette::Text, m_textColor);
89 pal.setColor(QPalette::WindowText, m_textColor);
90 pal.setColor(QPalette::ButtonText, m_textColor);
91 QApplication::setPalette(pal);62 QApplication::setPalette(pal);
92 }63 }
9364
94 void updateFont()65 QBrush generateBackgroundBrush()
95 {66 {
96 gchar* fontName = 0;67 QImage image(100, 24, QImage::Format_ARGB32_Premultiplied); // FIXME: Hardcoded
97 g_object_get(gtk_settings_get_default(), "gtk-font-name", &fontName, NULL);68 image.fill(Qt::transparent);
98 GScopedPointer<PangoFontDescription, pango_font_description_free> fontDescription(69 CairoUtils::SurfacePointer surface(CairoUtils::createSurfaceForQImage(&image));
99 pango_font_description_from_string(fontName)70 CairoUtils::Pointer cr(cairo_create(surface.data()));
100 );71 gtk_render_background(m_styleContext.data(), cr.data(), 0, 0, image.width(), image.height());
101 g_free(fontName);72 return QBrush(image);
102
103 int size = pango_font_description_get_size(fontDescription.data());
104
105 m_font = QFont(
106 pango_font_description_get_family(fontDescription.data()),
107 size / PANGO_SCALE
108 );
109
110 QApplication::setFont(m_font);
111 }73 }
112};74};
11375
@@ -115,24 +77,26 @@
115: d(new PanelStylePrivate)77: d(new PanelStylePrivate)
116{78{
117 d->q = this;79 d->q = this;
118 d->m_offScreenWindow = gtk_offscreen_window_new();80 d->m_styleContext.reset(gtk_style_context_new());
119 gtk_widget_set_name(d->m_offScreenWindow, "UnityPanelWidget");81
120 gtk_widget_set_size_request(d->m_offScreenWindow, 100, 24);82 GtkWidgetPath* widgetPath = gtk_widget_path_new ();
121 gtk_style_context_add_class(gtk_widget_get_style_context(d->m_offScreenWindow), "menubar");83 gtk_widget_path_append_type(widgetPath, GTK_TYPE_WINDOW);
122 gtk_widget_show_all(d->m_offScreenWindow);84 gtk_widget_path_iter_set_name(widgetPath, -1 , "UnityPanelWidget");
85
86 gtk_style_context_set_path(d->m_styleContext.data(), widgetPath);
87 gtk_style_context_add_class(d->m_styleContext.data(), "gnome-panel-menu-bar");
88 gtk_style_context_add_class(d->m_styleContext.data(), "unity-panel");
89
90 gtk_widget_path_free (widgetPath);
12391
124 d->m_gConnector.connect(gtk_settings_get_default(), "notify::gtk-theme-name",92 d->m_gConnector.connect(gtk_settings_get_default(), "notify::gtk-theme-name",
125 G_CALLBACK(PanelStylePrivate::onThemeChanged), d);93 G_CALLBACK(PanelStylePrivate::onThemeChanged), d);
126 d->m_gConnector.connect(gtk_settings_get_default(), "notify::gtk-font-name",
127 G_CALLBACK(PanelStylePrivate::onFontChanged), d);
12894
129 d->updatePalette();95 d->updatePalette();
130 d->updateFont();
131}96}
13297
133PanelStyle::~PanelStyle()98PanelStyle::~PanelStyle()
134{99{
135 gtk_widget_destroy(d->m_offScreenWindow);
136 delete d;100 delete d;
137}101}
138102
@@ -142,34 +106,9 @@
142 return &style;106 return &style;
143}107}
144108
145QColor PanelStyle::textColor() const109GtkStyleContext* PanelStyle::styleContext() const
146{110{
147 return d->m_textColor;111 return d->m_styleContext.data();
148}
149
150QColor PanelStyle::backgroundTopColor() const
151{
152 return d->m_backgroundTopColor;
153}
154
155QColor PanelStyle::backgroundBottomColor() const
156{
157 return d->m_backgroundBottomColor;
158}
159
160QColor PanelStyle::textShadowColor() const
161{
162 return d->m_textShadowColor;
163}
164
165QColor PanelStyle::lineColor() const
166{
167 return d->m_lineColor;
168}
169
170QFont PanelStyle::font() const
171{
172 return d->m_font;
173}112}
174113
175#include "panelstyle.moc"114#include "panelstyle.moc"
176115
=== modified file 'panel/applets/common/panelstyle.h'
--- panel/applets/common/panelstyle.h 2011-07-27 15:41:41 +0000
+++ panel/applets/common/panelstyle.h 2011-07-27 15:41:41 +0000
@@ -26,12 +26,15 @@
26// Qt26// Qt
27#include <QObject>27#include <QObject>
2828
29class QColor;29struct _GtkStyleContext;
30class QFont;
3130
32class PanelStylePrivate;31class PanelStylePrivate;
33/**32/**
34 * Provides easy access to panel colors33 * Provides easy access to panel style context and track platform theme to
34 * ensure we have the correct background brush.
35 *
36 * FIXME: This class does not have a very clear focus and has side-effects
37 * (background brush handling). It should be refactored.
35 */38 */
36class PanelStyle : public QObject39class PanelStyle : public QObject
37{40{
@@ -42,13 +45,7 @@
4245
43 static PanelStyle* instance();46 static PanelStyle* instance();
4447
45 QColor textColor() const;48 struct _GtkStyleContext* styleContext() const;
46 QColor backgroundTopColor() const;
47 QColor backgroundBottomColor() const;
48 QColor textShadowColor() const;
49 QColor lineColor() const;
50
51 QFont font() const;
5249
53private:50private:
54 friend class PanelStylePrivate;51 friend class PanelStylePrivate;
5552
=== modified file 'panel/applets/homebutton/homebutton.cpp'
--- panel/applets/homebutton/homebutton.cpp 2011-05-26 16:41:04 +0000
+++ panel/applets/homebutton/homebutton.cpp 2011-07-27 15:41:41 +0000
@@ -40,8 +40,10 @@
40 setStyleSheet(40 setStyleSheet(
41 "QToolButton { border: none; margin: 0; padding: 0; width: 61 }"41 "QToolButton { border: none; margin: 0; padding: 0; width: 61 }"
42 "QToolButton:checked, QToolButton:pressed {"42 "QToolButton:checked, QToolButton:pressed {"
43 // Use border-image here, not background-image, because bfb_bg_active.png is 56px wide43 " padding-top: 1px;"
44 " border-image: url(theme:/bfb_bg_active.png);"44 " padding-left: 1px;"
45 " padding-right: -1px;"
46 " padding-bottom: -1px;"
45 "}"47 "}"
46 );48 );
47}49}

Subscribers

People subscribed via source and target branches