1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include <qapplication.h>
43 #include <qwidget.h>
44 #include <qpainter.h>
45 #include <qdrawutil.h>
46 #include "qdecorationwindows_qws.h"
47 
48 QT_BEGIN_NAMESPACE
49 
50 #if !defined(QT_NO_QWS_DECORATION_WINDOWS) || defined(QT_PLUGIN)
51 
52 #ifndef QT_NO_IMAGEFORMAT_XPM
53 
54 /* XPM */
55 static const char * const win_close_xpm[] = {
56 "16 16 4 1",
57 "  s None  c None",
58 ". c #000000",
59 "X c #FFFFFF",
60 "Y c #707070",
61 "                ",
62 "                ",
63 "                ",
64 "   Y.      .Y   ",
65 "    ..    ..    ",
66 "     ..  ..     ",
67 "      .YY.      ",
68 "      Y..Y      ",
69 "      .YY.      ",
70 "     ..  ..     ",
71 "    ..    ..    ",
72 "   Y.      .Y   ",
73 "                ",
74 "                ",
75 "                ",
76 "                "};
77 
78 static const char * const win_help_xpm[] = {
79 "16 16 3 1",
80 "       s None  c None",
81 ".      c #ffffff",
82 "X      c #000000",
83 "                ",
84 "                ",
85 "                ",
86 "     XXXXXX     ",
87 "    XX    XX    ",
88 "    XX    XX    ",
89 "          XX    ",
90 "         XX     ",
91 "       XX       ",
92 "       XX       ",
93 "                ",
94 "       XX       ",
95 "       XX       ",
96 "                ",
97 "                ",
98 "                "};
99 
100 static const char * const win_maximize_xpm[] = {
101 "16 16 4 1",
102 "  s None  c None",
103 ". c #000000",
104 "X c #FFFFFF",
105 "Y c #707070",
106 "                ",
107 "                ",
108 "                ",
109 "   ..........   ",
110 "   ..........   ",
111 "   .        .   ",
112 "   .        .   ",
113 "   .        .   ",
114 "   .        .   ",
115 "   .        .   ",
116 "   .        .   ",
117 "   ..........   ",
118 "                ",
119 "                ",
120 "                ",
121 "                "};
122 
123 static const char * const win_minimize_xpm[] = {
124 "16 16 4 1",
125 "  s None  c None",
126 ". c #000000",
127 "X c #FFFFFF",
128 "Y c #707070",
129 "                ",
130 "                ",
131 "                ",
132 "                ",
133 "                ",
134 "                ",
135 "                ",
136 "                ",
137 "                ",
138 "                ",
139 "    ........    ",
140 "    ........    ",
141 "                ",
142 "                ",
143 "                ",
144 "                "};
145 
146 static const char * const win_normalize_xpm[] = {
147 "16 16 4 1",
148 "  s None  c None",
149 ". c #000000",
150 "X c #FFFFFF",
151 "Y c #707070",
152 "                ",
153 "                ",
154 "     .........  ",
155 "     .........  ",
156 "     .       .  ",
157 "     .       .  ",
158 "  .........  .  ",
159 "  .........  .  ",
160 "  .       .  .  ",
161 "  .       ....  ",
162 "  .       .     ",
163 "  .       .     ",
164 "  .........     ",
165 "                ",
166 "                ",
167 "                "};
168 
169 #endif // QT_NO_IMAGEFORMAT_XPM
170 
171 
QDecorationWindows()172 QDecorationWindows::QDecorationWindows()
173     : QDecorationDefault()
174 {
175     menu_width = 16;
176     help_width = 18;
177     minimize_width = 18;
178     maximize_width = 18;
179     close_width = 18;
180 }
181 
~QDecorationWindows()182 QDecorationWindows::~QDecorationWindows()
183 {
184 }
185 
xpmForRegion(int reg)186 const char **QDecorationWindows::xpmForRegion(int reg)
187 {
188 #ifdef QT_NO_IMAGEFORMAT_XPM
189     Q_UNUSED(reg);
190 #else
191     switch(reg)
192     {
193     case Close:
194         return (const char **)win_close_xpm;
195     case Help:
196         return (const char **)win_help_xpm;
197     case Minimize:
198         return (const char **)win_minimize_xpm;
199     case Maximize:
200         return (const char **)win_maximize_xpm;
201     case Normalize:
202         return (const char **)win_normalize_xpm;
203     default:
204         return QDecorationDefault::xpmForRegion(reg);
205     }
206 #endif
207     return 0;
208 }
209 
region(const QWidget * widget,const QRect & rect,int type)210 QRegion QDecorationWindows::region(const QWidget *widget, const QRect &rect, int type)
211 {
212     Qt::WindowFlags flags = widget->windowFlags();
213     bool hasTitle = flags & Qt::WindowTitleHint;
214     bool hasSysMenu = flags & Qt::WindowSystemMenuHint;
215     bool hasContextHelp = flags & Qt::WindowContextHelpButtonHint;
216     bool hasMinimize = flags & Qt::WindowMinimizeButtonHint;
217     bool hasMaximize = flags & Qt::WindowMaximizeButtonHint;
218     const QFontMetrics fontMetrics = QApplication::fontMetrics();
219     int titleHeight = hasTitle ? qMax(20, fontMetrics.height()) : 0;
220     int state = widget->windowState();
221     bool isMinimized = state & Qt::WindowMinimized;
222     bool isMaximized = state & Qt::WindowMaximized;
223 
224     QRegion region;
225     switch (type) {
226         case Menu: {
227                 if (hasSysMenu) {
228                     region = QRect(rect.left() + 2, rect.top() - titleHeight,
229                                    menu_width, titleHeight);
230                 }
231             }
232             break;
233 
234         case Title: {
235                 QRect r(rect.left()
236                         + (hasSysMenu ? menu_width + 4: 0),
237                         rect.top() - titleHeight,
238                         rect.width()
239                         - (hasSysMenu ? menu_width : 0)
240                         - close_width
241                         - (hasMaximize ? maximize_width : 0)
242                         - (hasMinimize ? minimize_width : 0)
243                         - (hasContextHelp ? help_width : 0)
244                         - 3,
245                         titleHeight);
246                 if (r.width() > 0)
247                     region = r;
248             }
249             break;
250         case Help: {
251                 if (hasContextHelp) {
252                     QRect r(rect.right()
253                             - close_width
254                             - (hasMaximize ? maximize_width : 0)
255                             - (hasMinimize ? minimize_width : 0)
256                             - help_width - 3, rect.top() - titleHeight,
257                             help_width, titleHeight);
258                     if (r.left() > rect.left() + titleHeight)
259                         region = r;
260                 }
261             }
262             break;
263 
264         case Minimize: {
265                 if (hasMinimize && !isMinimized) {
266                     QRect r(rect.right() - close_width
267                             - (hasMaximize ? maximize_width : 0)
268                             - minimize_width - 3, rect.top() - titleHeight,
269                             minimize_width, titleHeight);
270                     if (r.left() > rect.left() + titleHeight)
271                         region = r;
272                 }
273             }
274             break;
275 
276         case Maximize: {
277                 if (hasMaximize && !isMaximized) {
278                     QRect r(rect.right() - close_width - maximize_width - 3,
279                             rect.top() - titleHeight, maximize_width, titleHeight);
280                     if (r.left() > rect.left() + titleHeight)
281                         region = r;
282                 }
283             }
284             break;
285 
286         case Normalize: {
287                 if (hasMinimize && isMinimized) {
288                     QRect r(rect.right() - close_width
289                             - (hasMaximize ? maximize_width : 0)
290                             - minimize_width - 3, rect.top() - titleHeight,
291                             minimize_width, titleHeight);
292                     if (r.left() > rect.left() + titleHeight)
293                         region = r;
294                 } else if (hasMaximize && isMaximized) {
295                     QRect r(rect.right() - close_width - maximize_width - 3,
296                             rect.top() - titleHeight, maximize_width, titleHeight);
297                     if (r.left() > rect.left() + titleHeight)
298                         region = r;
299                 }
300             }
301             break;
302 
303         case Close: {
304                 QRect r(rect.right() - close_width - 1, rect.top() - titleHeight,
305                         close_width, titleHeight);
306                 if (r.left() > rect.left() + titleHeight)
307                     region = r;
308             }
309             break;
310 
311         default:
312             region = QDecorationDefault::region(widget, rect, type);
313             break;
314     }
315 
316     return region;
317 }
318 
paint(QPainter * painter,const QWidget * widget,int decorationRegion,DecorationState state)319 bool QDecorationWindows::paint(QPainter *painter, const QWidget *widget, int decorationRegion,
320                                DecorationState state)
321 {
322     if (decorationRegion == None)
323         return false;
324 
325     const QRect titleRect = QDecoration::region(widget, Title).boundingRect();
326     const QPalette pal = QApplication::palette();
327     QRegion oldClipRegion = painter->clipRegion();
328 
329     bool paintAll = (decorationRegion == int(All));
330     if ((paintAll || decorationRegion & Title && titleRect.width() > 0) && state == Normal
331         && (widget->windowFlags() & Qt::WindowTitleHint) ) {
332         painter->setClipRegion(oldClipRegion);
333         QColor fromBrush, toBrush;
334         QPen   titlePen;
335 
336         if (widget == qApp->activeWindow() || qApp->activeWindow() == qApp->activePopupWidget()) {
337             fromBrush = pal.color(QPalette::Highlight);
338             titlePen  = pal.color(QPalette::HighlightedText);
339         } else {
340             fromBrush = pal.color(QPalette::Window);
341             titlePen  = pal.color(QPalette::Text);
342         }
343         toBrush = fromBrush.lighter(300);
344 
345         painter->setPen(Qt::NoPen);
346         QPoint p1(titleRect.x(), titleRect.y() + titleRect.height()/2);
347         QPoint p2(titleRect.right(), titleRect.y() + titleRect.height()/2);
348         QLinearGradient lg(p1, p2);
349         lg.setColorAt(0, fromBrush);
350         lg.setColorAt(1, toBrush);
351         painter->fillRect(titleRect, lg);
352 
353         painter->setPen(titlePen);
354         painter->drawText(titleRect, Qt::AlignVCenter, windowTitleFor(widget));
355         decorationRegion ^= Title;
356     }
357 
358     return QDecorationDefault::paint(painter, widget, decorationRegion, state);
359 }
360 
paintButton(QPainter * painter,const QWidget * widget,int buttonRegion,DecorationState state,const QPalette & pal)361 void QDecorationWindows::paintButton(QPainter *painter, const QWidget *widget, int buttonRegion,
362                                      DecorationState state, const QPalette &pal)
363 {
364     QBrush fromBrush, toBrush;
365     QPen   titlePen;
366 
367     if (widget == qApp->activeWindow() || qApp->activeWindow() == qApp->activePopupWidget()) {
368         fromBrush = pal.brush(QPalette::Highlight);
369         titlePen  = pal.color(QPalette::HighlightedText);
370     } else {
371         fromBrush = pal.brush(QPalette::Window);
372         titlePen  = pal.color(QPalette::Text);
373     }
374     toBrush = fromBrush.color().lighter(300);
375 
376     QRect brect(QDecoration::region(widget, buttonRegion).boundingRect());
377     if (buttonRegion != Close && buttonRegion != Menu)
378         painter->fillRect(brect, toBrush);
379     else
380         painter->fillRect(brect.x() - 2, brect.y(), brect.width() + 4, brect.height(),
381                           buttonRegion == Menu ? fromBrush : toBrush);
382 
383     int xoff = 1;
384     int yoff = 2;
385     const QPixmap pm = pixmapFor(widget, buttonRegion, xoff, yoff);
386     if (buttonRegion != Menu) {
387         if (state & Normal) {
388             qDrawWinPanel(painter, brect.x(), brect.y() + 2, brect.width(),
389                           brect.height() - 4, pal, false, &pal.brush(QPalette::Window));
390         } else if (state & Pressed) {
391             qDrawWinPanel(painter, brect.x(), brect.y() + 2, brect.width(),
392                           brect.height() - 4, pal, true, &pal.brush(QPalette::Window));
393             ++xoff;
394             ++yoff;
395         }
396     } else {
397         xoff = 0;
398         yoff = 2;
399     }
400 
401     if (!pm.isNull())
402         painter->drawPixmap(brect.x() + xoff, brect.y() + yoff, pm);
403 }
404 
405 #endif // QT_NO_QWS_DECORATION_WINDOWS || QT_PLUGIN
406 
407 QT_END_NAMESPACE
408