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