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 "qdecoration_qws.h"
43
44 #include "qapplication.h"
45 #include "qdrawutil.h"
46 #include "qpainter.h"
47 #include "qregion.h"
48 #include "qwhatsthis.h"
49
50 #include "qmenu.h"
51 #include "private/qwidget_p.h"
52 #include "qwsmanager_qws.h"
53
54 QT_BEGIN_NAMESPACE
55
56 /*!
57 \class QDecoration
58 \ingroup qws
59
60 \brief The QDecoration class is a base class for window
61 decorations in Qt for Embedded Linux
62
63 Note that this class is non-portable and only available in
64 \l{Qt for Embedded Linux}.
65
66 \l{Qt for Embedded Linux} provides window management of top level windows
67 and several ready made decorations (i.e., \c Default, \c Styled
68 and \c Windows). Custom decorations can be implemented by
69 subclassing the QDecoration class and creating a decoration plugin
70 (derived from QDecorationPlugin). The default
71 implementation of the QDecorationFactory class will automatically
72 detect the plugin, and load the decoration into the application at
73 run-time using Qt's \l {How to Create Qt Plugins}{plugin
74 system}. To actually apply a decoration, use the
75 QApplication::qwsSetDecoration() function.
76
77 When creating a custom decoration, implement the paint() function
78 to paint the border and title decoration, and the region()
79 function to return the regions the decoration
80 occupies. Reimplement the regionClicked() and
81 regionDoubleClicked() functions to respond to mouse clicks (the
82 default implementations responds to (single) clicks on items in a
83 widget's system menu and double clicks on a widget's title).
84
85 QDecoration provides the DecorationRegion enum that describes the
86 various regions of the window decoration, and the regionAt()
87 function to determine the region containing a given point. The
88 QDecoration class also provides the DecorationState enum
89 describing the state of a given region, e.g. whether it is active
90 or not.
91
92 In addition, it is possible to build the system menu for a given
93 top level widget using the buildSysMenu() function; whenever an
94 action in this menu is triggered, the menuTriggered() function is
95 called automatically.
96
97 Finally, the QDecoration class provides a couple of static
98 functions, startMove() and startResize(), which start a move or
99 resize action by making the appropriate decoration region active
100 and grabbing the mouse input.
101
102 \sa QDecorationFactory, QDecorationPlugin, {Qt for Embedded Linux
103 Architecture}
104 */
105
106 /*!
107 \fn QDecoration::QDecoration()
108
109 Constructs a decoration object.
110 */
111
112 /*!
113 \fn QDecoration::~QDecoration()
114
115 Destroys this decoration object.
116 */
117
118 /*!
119 \enum QDecoration::DecorationRegion
120
121 This enum describes the various regions of the window decoration.
122
123 \value All The entire region used by the window decoration.
124
125 \value Top The top border used to vertically resize the window.
126 \value Bottom The bottom border used to vertically resize the window.
127 \value Left The left border used to horizontally resize the window.
128 \value Right The right border used to horizontally resize the window.
129 \value TopLeft The top-left corner of the window used to resize the
130 window both horizontally and vertically.
131 \value TopRight The top-right corner of the window used to resize the
132 window both horizontally and vertically.
133 \value BottomLeft The bottom-left corner of the window used to resize the
134 window both horizontally and vertically.
135 \value BottomRight The bottom-right corner of the window used to resize the
136 window both horizontally and vertically.
137 \value Borders All the regions used to describe the window's borders.
138
139 \value Title The region containing the window title, used
140 to move the window by dragging with the mouse cursor.
141 \value Close The region occupied by the close button. Clicking in this
142 region closes the window.
143 \value Minimize The region occupied by the minimize button. Clicking in
144 this region minimizes the window.
145 \value Maximize The region occupied by the maximize button. Clicking in
146 this region maximizes the window.
147 \value Normalize The region occupied by a button used to restore a window's
148 normal size. Clicking in this region restores a maximized
149 window to its previous size. The region used for this
150 button is often also the Maximize region.
151 \value Menu The region occupied by the window's menu button. Clicking
152 in this region opens the window operations (system) menu.
153 \value Help The region occupied by the window's help button. Clicking
154 in this region causes the context-sensitive help function
155 to be enabled.
156 \value Resize The region used to resize the window.
157 \value Move The region used to move the window.
158 \value None No region.
159
160 \sa region(), regionAt(), DecorationState
161 */
162
163 /*!
164 \enum QDecoration::DecorationState
165
166 This enum describes the various states of a decoration region.
167
168 \value Normal The region is active
169 \value Disabled The region is inactive.
170 \value Hover The cursor is hovering over the region.
171 \value Pressed The region is pressed.
172
173 \sa paint(), DecorationRegion
174 */
175
176 /*!
177 \fn QRegion QDecoration::region(const QWidget *widget, const QRect & rectangle, int decorationRegion)
178
179 Implement this function to return the region specified by \a
180 decorationRegion for the given top level \a widget.
181
182 The \a rectangle parameter specifies the rectangle the decoration
183 is wrapped around. The \a decorationRegion is a bitmask of the
184 values described by the DecorationRegion enum.
185
186 \sa regionAt(), paint()
187 */
188
189 /*!
190 \fn QRegion QDecoration::region(const QWidget *widget, int decorationRegion)
191 \overload
192 */
193
194 /*!
195 \fn bool QDecoration::paint(QPainter *painter, const QWidget *widget, int decorationRegion,
196 DecorationState state)
197
198 Implement this function to paint the border and title decoration
199 for the specified top level \a widget using the given \a painter
200 and decoration \a state. The specified \a decorationRegion is a
201 bitmask of the values described by the DecorationRegion enum.
202
203 Note that \l{Qt for Embedded Linux} expects this function to return true if
204 any of the widget's decorations are repainted; otherwise it should
205 return false.
206
207 \sa region()
208 */
209
210 /*!
211 \fn int QDecoration::regionAt(const QWidget *widget, const QPoint &point)
212
213 Returns the type of the first region of the specified top level \a
214 widget containing the given \a point.
215
216 The return value is one of the DecorationRegion enum's values. Use
217 the region() function to retrieve the actual region. If none of
218 the widget's regions contain the point, this function returns \l
219 None.
220
221 \sa region()
222 */
regionAt(const QWidget * w,const QPoint & point)223 int QDecoration::regionAt(const QWidget *w, const QPoint &point)
224 {
225 int regions[] = {
226 TopLeft, Top, TopRight, Left, Right, BottomLeft, Bottom, BottomRight, // Borders first
227 Menu, Title, Help, Minimize, Normalize, Maximize, Close, // then buttons
228 None
229 };
230
231 // char *regions_str[] = {
232 // "TopLeft", "Top", "TopRight", "Left", "Right", "BottomLeft", "Bottom", "BottomRight",
233 // "Menu", "Title", "Help", "Minimize", "Normalize", "Maximize", "Close",
234 // "None"
235 // };
236
237 // First check to see if within all regions at all
238 QRegion reg = region(w, w->geometry(), All);
239 if (!reg.contains(point)) {
240 return None;
241 }
242
243 int i = 0;
244 while (regions[i]) {
245 reg = region(w, w->geometry(), regions[i]);
246 if (reg.contains(point)) {
247 // qDebug("In region %s", regions_str[i]);
248 return regions[i];
249 }
250 ++i;
251 }
252 return None;
253 }
254
255 #ifndef QT_NO_MENU
256 /*!
257 Builds the system menu for the given top level \a widget, adding
258 \gui Restore, \gui Move, \gui Size, \gui Minimize, \gui Maximize
259 and \gui Close actions to the given \a menu.
260
261 \sa menuTriggered()
262 */
buildSysMenu(QWidget * widget,QMenu * menu)263 void QDecoration::buildSysMenu(QWidget *widget, QMenu *menu)
264 {
265 QDecorationAction *act = new QDecorationAction(QLatin1String("Restore"),
266 menu, Maximize);
267 act->setEnabled(widget->windowState() & Qt::WindowMaximized);
268 menu->addAction(act);
269 act = new QDecorationAction(QLatin1String("Move"), menu, Move);
270 act->setEnabled(!(widget->windowState() & Qt::WindowMaximized));
271 menu->addAction(act);
272 menu->addAction(new QDecorationAction(QLatin1String("Size"), menu, Resize));
273 act = new QDecorationAction(QLatin1String("Minimize"), menu, Minimize);
274 menu->addAction(act);
275 act = new QDecorationAction(QLatin1String("Maximize"), menu, Maximize);
276 act->setDisabled(widget->windowState() & Qt::WindowMaximized);
277 menu->addAction(act);
278 menu->addSeparator();
279 menu->addAction(new QDecorationAction(QLatin1String("Close"), menu, Close));
280 }
281
282 /*!
283 This function is called whenever an action in a top level widget's
284 menu is triggered, and simply calls the regionClicked() function
285 passing the \a widget and \a action parameters as arguments.
286
287 \sa buildSysMenu()
288 */
menuTriggered(QWidget * widget,QAction * action)289 void QDecoration::menuTriggered(QWidget *widget, QAction *action)
290 {
291 QDecorationAction *decAction = static_cast<QDecorationAction *>(action);
292 regionClicked(widget, decAction->reg);
293 }
294 #endif // QT_NO_MENU
295
296 /*!
297 \fn void QDecoration::regionClicked(QWidget *widget, int region)
298
299 Handles the event that the specified \a region in the given top
300 level \a widget is activated by a single click (the \a region
301 parameter is described using the DecorationRegion enum).
302
303 This function is called whenever a region in a top level widget is
304 clicked; the default implementation responds to clicks on items in
305 the system menu, performing the requested actions.
306
307 \sa regionDoubleClicked(), region()
308 */
regionClicked(QWidget * widget,int reg)309 void QDecoration::regionClicked(QWidget *widget, int reg)
310 {
311 switch(reg) {
312 case Move:
313 startMove(widget);
314 break;
315 case Resize:
316 startResize(widget);
317 break;
318 case Help:
319 #ifndef QT_NO_WHATSTHIS
320 if (QWhatsThis::inWhatsThisMode())
321 QWhatsThis::leaveWhatsThisMode();
322 else
323 QWhatsThis::enterWhatsThisMode();
324 #endif
325 break;
326 case Close:
327 widget->close();
328 break;
329 case Normalize:
330 widget->showNormal();
331 break;
332 case Maximize:
333 if (widget->windowState() & Qt::WindowMaximized)
334 widget->showNormal();
335 else
336 widget->showMaximized();
337 break;
338 }
339 }
340
341 /*!
342 \fn void QDecoration::regionDoubleClicked(QWidget *widget, int region)
343
344 Handles the event that the specified \a region in the given top
345 level \a widget is activated by a double click (the region
346 parameter is described using the DecorationRegion enum).
347
348 This function is called whenever a region in a top level widget is
349 double clicked; the default implementation responds to a double
350 click on the widget's title, toggling its size between the maximum
351 and its normal size.
352
353 \sa regionClicked(), region()
354 */
regionDoubleClicked(QWidget * widget,int reg)355 void QDecoration::regionDoubleClicked(QWidget *widget, int reg)
356 {
357 switch(reg)
358 {
359 case Title: {
360 if (widget->windowState() & Qt::WindowMaximized)
361 widget->showNormal();
362 else
363 widget->showMaximized();
364 break;
365 }
366 }
367 }
368
369 /*!
370 Starts to move the given top level \a widget by making its \l
371 Title region active and grabbing the mouse input.
372
373 \sa startResize()
374 */
startMove(QWidget * widget)375 void QDecoration::startMove(QWidget *widget)
376 {
377 #ifdef QT_NO_QWS_MANAGER
378 Q_UNUSED(widget);
379 #else
380 QWSManager *manager = widget->d_func()->topData()->qwsManager;
381 if (manager)
382 manager->startMove();
383 #endif
384 }
385
386 /*!
387 Starts to resize the given top level \a widget by making its \l
388 BottomRight region active and grabbing the mouse input.
389
390 \sa startMove()
391 */
startResize(QWidget * widget)392 void QDecoration::startResize(QWidget *widget)
393 {
394 #ifdef QT_NO_QWS_MANAGER
395 Q_UNUSED(widget);
396 #else
397 QWSManager *manager = widget->d_func()->topData()->qwsManager;
398 if (manager)
399 manager->startResize();
400 #endif
401 }
402
403
404 QT_END_NAMESPACE
405