Qt 4.8
qwsmanager_qws.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qwsmanager_qws.h"
43 
44 #ifndef QT_NO_QWS_MANAGER
45 
46 #include "qdrawutil.h"
47 #include "qapplication.h"
48 #include "qstyle.h"
49 #include "qwidget.h"
50 #include "qmenu.h"
51 #include "qpainter.h"
52 #include "private/qpainter_p.h"
53 #include "qregion.h"
54 #include "qevent.h"
55 #include "qcursor.h"
56 #include "qwsdisplay_qws.h"
57 #include "qdesktopwidget.h"
58 
59 #include <private/qapplication_p.h>
60 #include <private/qwidget_p.h>
61 #include <private/qbackingstore_p.h>
62 #include <private/qwindowsurface_qws_p.h>
63 #include "qdecorationfactory_qws.h"
64 
65 #include "qlayout.h"
66 
67 #include "qwsmanager_p.h"
68 
69 #include <qdebug.h>
70 
72 
73 QWidget *QWSManagerPrivate::active = 0;
74 QPoint QWSManagerPrivate::mousePos;
75 
76 
77 QWSManagerPrivate::QWSManagerPrivate()
78  : QObjectPrivate(), activeRegion(QDecoration::None), managed(0), popup(0),
79  previousRegionType(0), previousRegionRepainted(false), entireDecorationNeedsRepaint(false)
80 {
81  cached_region.regionType = 0;
82 }
83 
84 QRegion &QWSManager::cachedRegion()
85 {
86  return d_func()->cached_region.region;
87 }
88 
98 QWSManager::QWSManager(QWidget *w)
99  : QObject(*new QWSManagerPrivate, (QObject*)0)
100 {
101  d_func()->managed = w;
102 
103 }
104 
105 QWSManager::~QWSManager()
106 {
107  Q_D(QWSManager);
108 #ifndef QT_NO_MENU
109  if (d->popup)
110  delete d->popup;
111 #endif
112  if (d->managed == QWSManagerPrivate::active)
113  QWSManagerPrivate::active = 0;
114 }
115 
117 {
118  Q_D(QWSManager);
119  return d->managed;
120 }
121 
122 QWidget *QWSManager::grabbedMouse()
123 {
124  return QWSManagerPrivate::active;
125 }
126 
127 QRegion QWSManager::region()
128 {
129  Q_D(QWSManager);
130  return QApplication::qwsDecoration().region(d->managed, d->managed->geometry());
131 }
132 
133 bool QWSManager::event(QEvent *e)
134 {
135  if (QObject::event(e))
136  return true;
137 
138  switch (e->type()) {
139  case QEvent::MouseMove:
140  mouseMoveEvent((QMouseEvent*)e);
141  break;
142 
144  mousePressEvent((QMouseEvent*)e);
145  break;
146 
148  mouseReleaseEvent((QMouseEvent*)e);
149  break;
150 
152  mouseDoubleClickEvent((QMouseEvent*)e);
153  break;
154 
155  case QEvent::Paint:
156  paintEvent((QPaintEvent*)e);
157  break;
158 
159  default:
160  return false;
161  break;
162  }
163 
164  return true;
165 }
166 
167 void QWSManager::mousePressEvent(QMouseEvent *e)
168 {
169  Q_D(QWSManager);
170  d->mousePos = e->globalPos();
171  d->activeRegion = QApplication::qwsDecoration().regionAt(d->managed, d->mousePos);
172  if(d->cached_region.regionType)
173  d->previousRegionRepainted |= repaintRegion(d->cached_region.regionType, QDecoration::Pressed);
174 
175  if (d->activeRegion == QDecoration::Menu) {
177  ? d->managed->geometry().topLeft()
178  : d->managed->geometry().topRight());
179  menu(pos);
180  }
181  if (d->activeRegion != QDecoration::None &&
182  d->activeRegion != QDecoration::Menu) {
183  d->active = d->managed;
184  d->managed->grabMouse();
185  }
186  if (d->activeRegion != QDecoration::None &&
187  d->activeRegion != QDecoration::Close &&
188  d->activeRegion != QDecoration::Minimize &&
189  d->activeRegion != QDecoration::Menu) {
190  d->managed->raise();
191  }
192 
193  if (e->button() == Qt::RightButton) {
194  menu(e->globalPos());
195  }
196 }
197 
198 void QWSManager::mouseReleaseEvent(QMouseEvent *e)
199 {
200  Q_D(QWSManager);
201  d->managed->releaseMouse();
202  if (d->cached_region.regionType && d->previousRegionRepainted && QApplication::mouseButtons() == 0) {
203  bool doesHover = repaintRegion(d->cached_region.regionType, QDecoration::Hover);
204  if (!doesHover) {
205  repaintRegion(d->cached_region.regionType, QDecoration::Normal);
206  d->previousRegionRepainted = false;
207  }
208  }
209 
210  if (e->button() == Qt::LeftButton) {
211  //handleMove();
212  int itm = QApplication::qwsDecoration().regionAt(d->managed, e->globalPos());
213  int activatedItem = d->activeRegion;
214  d->activeRegion = QDecoration::None;
215  d->active = 0;
216  if (activatedItem == itm)
217  QApplication::qwsDecoration().regionClicked(d->managed, itm);
218  } else if (d->activeRegion == QDecoration::None) {
219  d->active = 0;
220  }
221 }
222 
223 void QWSManager::mouseDoubleClickEvent(QMouseEvent *e)
224 {
225  Q_D(QWSManager);
226  if (e->button() == Qt::LeftButton)
227  QApplication::qwsDecoration().regionDoubleClicked(d->managed,
228  QApplication::qwsDecoration().regionAt(d->managed, e->globalPos()));
229 }
230 
231 static inline Qt::CursorShape regionToShape(int region)
232 {
233  if (region == QDecoration::None)
234  return Qt::ArrowCursor;
235 
236  static const struct {
237  int region;
238  Qt::CursorShape shape;
239  } r2s[] = {
244  { QDecoration::Right, Qt::SizeHorCursor},
245  { QDecoration::BottomLeft, Qt::SizeBDiagCursor},
246  { QDecoration::Bottom, Qt::SizeVerCursor},
247  { QDecoration::BottomRight, Qt::SizeFDiagCursor},
249  };
250 
251  int i = 0;
252  while (region != r2s[i].region && r2s[i].region)
253  ++i;
254  return r2s[i].shape;
255 }
256 
257 void QWSManager::mouseMoveEvent(QMouseEvent *e)
258 {
259  Q_D(QWSManager);
260  if (d->newCachedRegion(e->globalPos())) {
261  if(d->previousRegionType && d->previousRegionRepainted)
262  repaintRegion(d->previousRegionType, QDecoration::Normal);
263  if(d->cached_region.regionType) {
264  d->previousRegionRepainted = repaintRegion(d->cached_region.regionType, QDecoration::Hover);
265  }
266  }
267 
268 
269 #ifndef QT_NO_CURSOR
270  if (d->managed->minimumSize() != d->managed->maximumSize()) {
272  qwsd->selectCursor(d->managed, regionToShape(d->cachedRegionAt()));
273  }
274 #endif //QT_NO_CURSOR
275 
276  if (d->activeRegion)
277  handleMove(e->globalPos());
278 }
279 
280 void QWSManager::handleMove(QPoint g)
281 {
282  Q_D(QWSManager);
283 
284  // don't allow dragging to where the user probably cannot click!
286  const QRect maxWindowRect = ap->maxWindowRect(qt_screen);
287  if (maxWindowRect.isValid()) {
288  if (g.x() < maxWindowRect.x())
289  g.setX(maxWindowRect.x());
290  if (g.y() < maxWindowRect.y())
291  g.setY(maxWindowRect.y());
292  if (g.x() > maxWindowRect.right())
293  g.setX(maxWindowRect.right());
294  if (g.y() > maxWindowRect.bottom())
295  g.setY(maxWindowRect.bottom());
296  }
297 
298  if (g == d->mousePos)
299  return;
300 
301  if ( d->managed->isMaximized() )
302  return;
303 
304  int x = d->managed->geometry().x();
305  int y = d->managed->geometry().y();
306  int w = d->managed->width();
307  int h = d->managed->height();
308 
309  QRect geom(d->managed->geometry());
310 
311  QPoint delta = g - d->mousePos;
312  d->mousePos = g;
313 
314  if (d->activeRegion == QDecoration::Title) {
315  geom = QRect(x + delta.x(), y + delta.y(), w, h);
316  } else {
317  bool keepTop = true;
318  bool keepLeft = true;
319  switch (d->activeRegion) {
320  case QDecoration::Top:
321  geom.setTop(geom.top() + delta.y());
322  keepTop = false;
323  break;
324  case QDecoration::Bottom:
325  geom.setBottom(geom.bottom() + delta.y());
326  keepTop = true;
327  break;
328  case QDecoration::Left:
329  geom.setLeft(geom.left() + delta.x());
330  keepLeft = false;
331  break;
332  case QDecoration::Right:
333  geom.setRight(geom.right() + delta.x());
334  keepLeft = true;
335  break;
337  geom.setTopRight(geom.topRight() + delta);
338  keepLeft = true;
339  keepTop = false;
340  break;
342  geom.setTopLeft(geom.topLeft() + delta);
343  keepLeft = false;
344  keepTop = false;
345  break;
347  geom.setBottomLeft(geom.bottomLeft() + delta);
348  keepLeft = false;
349  keepTop = true;
350  break;
352  geom.setBottomRight(geom.bottomRight() + delta);
353  keepLeft = true;
354  keepTop = true;
355  break;
356  default:
357  return;
358  }
359 
360  QSize newSize = QLayout::closestAcceptableSize(d->managed, geom.size());
361 
362  int dx = newSize.width() - geom.width();
363  int dy = newSize.height() - geom.height();
364 
365  if (keepTop) {
366  geom.setBottom(geom.bottom() + dy);
367  d->mousePos.ry() += dy;
368  } else {
369  geom.setTop(geom.top() - dy);
370  d->mousePos.ry() -= dy;
371  }
372  if (keepLeft) {
373  geom.setRight(geom.right() + dx);
374  d->mousePos.rx() += dx;
375  } else {
376  geom.setLeft(geom.left() - dx);
377  d->mousePos.rx() -= dx;
378  }
379  }
380  if (geom != d->managed->geometry()) {
382  d->managed->setGeometry(geom);
383  }
384 }
385 
386 void QWSManager::paintEvent(QPaintEvent *)
387 {
388  Q_D(QWSManager);
389  d->dirtyRegion(QDecoration::All, QDecoration::Normal);
390 }
391 
392 void QWSManagerPrivate::dirtyRegion(int decorationRegion,
394  const QRegion &clip)
395 {
396  QTLWExtra *topextra = managed->d_func()->extra->topextra;
397  QWidgetBackingStore *bs = topextra->backingStore.data();
398  const bool pendingUpdateRequest = bs->isDirty();
399 
400  if (decorationRegion == QDecoration::All) {
401  if (clip.isEmpty())
402  entireDecorationNeedsRepaint = true;
403  dirtyRegions.clear();
404  dirtyStates.clear();
405  }
406  int i = dirtyRegions.indexOf(decorationRegion);
407  if (i >= 0) {
408  dirtyRegions.removeAt(i);
409  dirtyStates.removeAt(i);
410  }
411 
412  dirtyRegions.append(decorationRegion);
413  dirtyStates.append(state);
414  if (!entireDecorationNeedsRepaint)
415  dirtyClip += clip;
416 
417  if (!pendingUpdateRequest)
419 }
420 
421 void QWSManagerPrivate::clearDirtyRegions()
422 {
423  dirtyRegions.clear();
424  dirtyStates.clear();
425  dirtyClip = QRegion();
426  entireDecorationNeedsRepaint = false;
427 }
428 
429 bool QWSManager::repaintRegion(int decorationRegion, QDecoration::DecorationState state)
430 {
431  Q_D(QWSManager);
432 
433  d->dirtyRegion(decorationRegion, state);
434  return true;
435 }
436 
437 void QWSManager::menu(const QPoint &pos)
438 {
439 #ifdef QT_NO_MENU
440  Q_UNUSED(pos);
441 #else
442  Q_D(QWSManager);
443  if (d->popup)
444  delete d->popup;
445 
446  // Basic window operation menu
447  d->popup = new QMenu();
448  QApplication::qwsDecoration().buildSysMenu(d->managed, d->popup);
449  connect(d->popup, SIGNAL(triggered(QAction*)), SLOT(menuTriggered(QAction*)));
450 
451  d->popup->popup(pos);
452  d->activeRegion = QDecoration::None;
453 #endif // QT_NO_MENU
454 }
455 
456 void QWSManager::menuTriggered(QAction *action)
457 {
458 #ifdef QT_NO_MENU
459  Q_UNUSED(action);
460 #else
461  Q_D(QWSManager);
462  QApplication::qwsDecoration().menuTriggered(d->managed, action);
463  d->popup->deleteLater();
464  d->popup = 0;
465 #endif
466 }
467 
468 void QWSManager::startMove()
469 {
470  Q_D(QWSManager);
471  d->mousePos = QCursor::pos();
472  d->activeRegion = QDecoration::Title;
473  d->active = d->managed;
474  d->managed->grabMouse();
475 }
476 
477 void QWSManager::startResize()
478 {
479  Q_D(QWSManager);
480  d->activeRegion = QDecoration::BottomRight;
481  d->active = d->managed;
482  d->managed->grabMouse();
483 }
484 
485 void QWSManager::maximize()
486 {
487  Q_D(QWSManager);
488  // find out how much space the decoration needs
489  const int screen = QApplication::desktop()->screenNumber(d->managed);
490  const QRect desk = QApplication::desktop()->availableGeometry(screen);
491  QRect dummy(0, 0, 1, 1);
492  QRect nr;
493  QRegion r = QApplication::qwsDecoration().region(d->managed, dummy);
494  if (r.isEmpty()) {
495  nr = desk;
496  } else {
497  r += dummy; // make sure we get the full window region in case of 0 width borders
498  QRect rect = r.boundingRect();
499  nr = QRect(desk.x()-rect.x(), desk.y()-rect.y(),
500  desk.width() - (rect.width()==1 ? 0 : rect.width()-1), // ==1 -> dummy
501  desk.height() - (rect.height()==1 ? 0 : rect.height()-1));
502  }
503  d->managed->setGeometry(nr);
504 }
505 
506 bool QWSManagerPrivate::newCachedRegion(const QPoint &pos)
507 {
508  // Check if anything has changed that would affect the region caching
509  if (managed->windowFlags() == cached_region.windowFlags
510  && managed->geometry() == cached_region.windowGeometry
511  && cached_region.region.contains(pos))
512  return false;
513 
514  // Update the cached region
515  int reg = QApplication::qwsDecoration().regionAt(managed, pos);
516  if (QWidget::mouseGrabber())
517  reg = QDecoration::None;
518 
519  previousRegionType = cached_region.regionType;
520  cached_region.regionType = reg;
521  cached_region.region = QApplication::qwsDecoration().region(managed, managed->geometry(),
522  reg);
523  // Make room for borders around the widget, even if the decoration doesn't have a frame.
524  if (reg && !(reg & int(QDecoration::Borders))) {
525  cached_region.region -= QApplication::qwsDecoration().region(managed, managed->geometry(), QDecoration::Borders);
526  }
527  cached_region.windowFlags = managed->windowFlags();
528  cached_region.windowGeometry = managed->geometry();
529 // QRect rec = cached_region.region.boundingRect();
530 // qDebug("Updated cached region: 0x%04x (%d, %d) (%d, %d, %d, %d)",
531 // reg, pos.x(), pos.y(), rec.x(), rec.y(), rec.right(), rec.bottom());
532  return true;
533 }
534 
536 
537 #endif //QT_NO_QWS_MANAGER
Q_GUI_EXPORT QScreen * qt_screen
Definition: qscreen_qws.cpp:69
double d
Definition: qnumeric_p.h:62
static Qt::LayoutDirection layoutDirection()
The QWSDisplay class provides a display for QWS; it is an internal class.
QRect maxWindowRect(const QScreen *screen) const
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
EventRef event
QPointer< QWidget > widget
void selectCursor(QWidget *w, unsigned int id)
static QWSDisplay * qwsDisplay()
static void postEvent(QObject *receiver, QEvent *event)
Adds the event event, with the object receiver as the receiver of the event, to an event queue and re...
#define SLOT(a)
Definition: qobjectdefs.h:226
bool isDirty() const
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
static QApplicationPrivate * instance()
QRect boundingRect() const
Returns the bounding rectangle of this region.
Definition: qregion.cpp:4363
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
int bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:249
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
virtual bool event(QEvent *)
This virtual function receives events to an object and should return true if the event e was recogniz...
Definition: qobject.cpp:1200
#define Q_D(Class)
Definition: qglobal.h:2482
static QSize closestAcceptableSize(const QWidget *w, const QSize &s)
Returns a size that satisfies all size constraints on widget, including heightForWidth() and that is ...
Definition: qlayout.cpp:1586
The QDecoration class is a base class for window decorations in Qt for Embedded Linux.
#define SIGNAL(a)
Definition: qobjectdefs.h:227
int width() const
Returns the width.
Definition: qsize.h:126
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static QWidget * mouseGrabber()
Returns the widget that is currently grabbing the mouse input.
bool isEmpty() const
Returns true if the region is empty; otherwise returns false.
Definition: qregion.cpp:4098
static void sendPostedEvents()
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
Qt::MouseButton button() const
Returns the button that caused the event.
Definition: qevent.h:101
#define None
The QMouseEvent class contains parameters that describe a mouse event.
Definition: qevent.h:85
static QDesktopWidget * desktop()
Returns the desktop widget (also called the root window).
void setY(int y)
Sets the y coordinate of this point to the given y coordinate.
Definition: qpoint.h:137
int right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:246
The QMenu class provides a menu widget for use in menu bars, context menus, and other popup menus...
Definition: qmenu.h:72
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
CursorShape
Definition: qnamespace.h:1262
QWidgetBackingStore * data()
Definition: qwidget_p.h:132
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
int height() const
Returns the height.
Definition: qsize.h:129
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
DecorationState
This enum describes the various states of a decoration region.
int y() const
Returns the y coordinate of this point.
Definition: qpoint.h:131
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
int screenNumber(const QWidget *widget=0) const
static Qt::MouseButtons mouseButtons()
Returns the current state of the buttons on the mouse.
int x() const
Returns the x coordinate of this point.
Definition: qpoint.h:128
const QRect availableGeometry(int screen=-1) const
QWidgetBackingStoreTracker backingStore
Definition: qwidget_p.h:166
bool isValid() const
Returns true if the rectangle is valid, otherwise returns false.
Definition: qrect.h:237
The QPaintEvent class contains event parameters for paint events.
Definition: qevent.h:298
The QEvent class is the base class of all event classes.
Definition: qcoreevent.h:56
Type type() const
Returns the event type.
Definition: qcoreevent.h:303
const QPoint & globalPos() const
Returns the global position of the mouse cursor at the time of the event.
Definition: qevent.h:96
void setX(int x)
Sets the x coordinate of this point to the given x coordinate.
Definition: qpoint.h:134
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
The QAction class provides an abstract user interface action that can be inserted into widgets...
Definition: qaction.h:64
static QPoint pos()
Returns the position of the cursor (hot spot) in global screen coordinates.
Definition: qcursor_mac.mm:310