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 "qcursor.h"
43 #include "qapplication.h"
44 #include "qapplication_p.h"
45 #include "qpainter.h"
46 #include "qbitmap.h"
47 #include "qimage.h"
48 #include "qhash.h"
49 #include "qstack.h"
50 #include "qlayout.h"
51 #include "qtextcodec.h"
52 #include "qinputcontext.h"
53 #include "qdesktopwidget.h"
54
55 #include "qwsdisplay_qws.h"
56 #include "private/qwsdisplay_qws_p.h"
57 #include "qscreen_qws.h"
58 #include "qwsmanager_qws.h"
59 #include <private/qwsmanager_p.h>
60 #include <private/qbackingstore_p.h>
61 #include <private/qwindowsurface_qws_p.h>
62 #include <private/qwslock_p.h>
63 #include "qpaintengine.h"
64
65 #include "qdebug.h"
66
67 #include "qwidget_p.h"
68
69 QT_BEGIN_NAMESPACE
70
71 QT_USE_NAMESPACE
72
73 extern int *qt_last_x;
74 extern int *qt_last_y;
75 extern WId qt_last_cursor;
76 extern bool qws_overrideCursor;
77 extern QWidget *qt_pressGrab;
78 extern QWidget *qt_mouseGrb;
79
80 static QWidget *keyboardGrb = 0;
81
takeLocalId()82 static int takeLocalId()
83 {
84 static int n=-1000;
85 return --n;
86 }
87
88 class QWSServer;
89 extern QWSServer *qwsServer;
90
isServerProcess()91 static inline bool isServerProcess()
92 {
93 return (qwsServer != 0);
94 }
95
96 /*****************************************************************************
97 QWidget member functions
98 *****************************************************************************/
99
create_sys(WId window,bool initializeWindow,bool)100 void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool /*destroyOldWindow*/)
101 {
102 Q_Q(QWidget);
103 Qt::WindowType type = q->windowType();
104
105 // Make sure the WindowTitleHint is on if any of the title bar hints are set
106 // Note: This might be moved to cross-platform QWidgetPrivate::adjustFlags()
107 if ( !(data.window_flags & Qt::CustomizeWindowHint) && (
108 (data.window_flags & Qt::WindowSystemMenuHint) ||
109 (data.window_flags & Qt::WindowContextHelpButtonHint) ||
110 (data.window_flags & Qt::WindowMinimizeButtonHint) ||
111 (data.window_flags & Qt::WindowMaximizeButtonHint) ||
112 (data.window_flags & Qt::WindowCloseButtonHint) ) ) {
113 data.window_flags |= Qt::WindowTitleHint;
114 }
115
116 // Decoration plugins on QWS don't support switching on the close button on its own
117 if (data.window_flags & Qt::WindowCloseButtonHint)
118 data.window_flags |= Qt::WindowSystemMenuHint;
119
120 Qt::WindowFlags flags = data.window_flags;
121
122 data.alloc_region_index = -1;
123
124 // we don't have a "Drawer" window type
125 if (type == Qt::Drawer) {
126 type = Qt::Widget;
127 flags &= ~Qt::WindowType_Mask;
128 }
129
130
131 bool topLevel = (flags & Qt::Window);
132 bool popup = (type == Qt::Popup);
133 bool dialog = (type == Qt::Dialog
134 || type == Qt::Sheet
135 || (flags & Qt::MSWindowsFixedSizeDialogHint));
136 bool desktop = (type == Qt::Desktop);
137 bool tool = (type == Qt::Tool || type == Qt::SplashScreen || type == Qt::ToolTip);
138
139
140 #ifndef QT_NO_WARNING_OUTPUT
141 static bool toolWarningShown = false;
142 if (!toolWarningShown && type == Qt::Tool && !(flags & Qt::FramelessWindowHint)) {
143 qWarning("Qt for Embedded Linux " QT_VERSION_STR " does not support tool windows with frames.\n"
144 "This behavior will change in a later release. To ensure compatibility with\n"
145 "future versions, use (Qt::Tool | Qt::FramelessWindowHint).");
146 toolWarningShown = true;
147 }
148 #endif
149
150 WId id;
151 QWSDisplay* dpy = QWidget::qwsDisplay();
152
153 if (!window) // always initialize
154 initializeWindow = true;
155
156 // use the size of the primary screen to determine the default window size
157 QList<QScreen *> screens = qt_screen->subScreens();
158 if (screens.isEmpty())
159 screens.append(qt_screen);
160 int sw = screens[0]->width();
161 int sh = screens[0]->height();
162
163 if (desktop) { // desktop widget
164 dialog = popup = false; // force these flags off
165 data.crect.setRect(0, 0, sw, sh);
166 } else if (topLevel && !q->testAttribute(Qt::WA_Resized)) {
167 int width = sw / 2;
168 int height = 4 * sh / 10;
169 if (extra) {
170 width = qMax(qMin(width, extra->maxw), extra->minw);
171 height = qMax(qMin(height, extra->maxh), extra->minh);
172 }
173 data.crect.setSize(QSize(width, height));
174 }
175
176 if (window) { // override the old window
177 id = window;
178 setWinId(window);
179 } else if (desktop) { // desktop widget
180 id = (WId)-2; // id = root window
181 #if 0
182 QWidget *otherDesktop = q->find(id); // is there another desktop?
183 if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) {
184 otherDesktop->d_func()->setWinId(0); // remove id from widget mapper
185 setWinId(id); // make sure otherDesktop is
186 otherDesktop->d_func()->setWinId(id); // found first
187 } else
188 #endif
189 {
190 setWinId(id);
191 }
192 } else {
193 id = topLevel ? dpy->takeId() : takeLocalId();
194 setWinId(id); // set widget id/handle + hd
195 }
196
197
198 bool hasFrame = true;
199 if (topLevel) {
200 if (desktop || popup || tool || q->testAttribute(Qt::WA_DontShowOnScreen))
201 hasFrame = false;
202 else
203 hasFrame = !(flags & Qt::FramelessWindowHint);
204 }
205 if (desktop) {
206 q->setAttribute(Qt::WA_WState_Visible);
207 } else if (topLevel) { // set X cursor
208 //QCursor *oc = QApplication::overrideCursor();
209 if (initializeWindow) {
210 //XXX XDefineCursor(dpy, winid, oc ? oc->handle() : cursor().handle());
211 }
212 QWidget::qwsDisplay()->nameRegion(q->internalWinId(), q->objectName(), q->windowTitle());
213 }
214
215 if (topLevel) {
216 createTLExtra();
217 QTLWExtra *topextra = extra->topextra;
218 #ifndef QT_NO_QWS_MANAGER
219 if (hasFrame) {
220 // get size of wm decoration and make the old crect the new frect
221 QRect cr = data.crect;
222 QRegion r = QApplication::qwsDecoration().region(q, cr) | cr;
223 QRect br(r.boundingRect());
224 topextra->frameStrut.setCoords(cr.x() - br.x(),
225 cr.y() - br.y(),
226 br.right() - cr.right(),
227 br.bottom() - cr.bottom());
228 if (!q->testAttribute(Qt::WA_Moved) || topextra->posFromMove)
229 data.crect.translate(topextra->frameStrut.left(), topextra->frameStrut.top());
230 if (!topData()->qwsManager) {
231 topData()->qwsManager = new QWSManager(q);
232 if((q->data->window_state & ~Qt::WindowActive) == Qt::WindowMaximized)
233 topData()->qwsManager->maximize();
234 }
235
236 } else if (topData()->qwsManager) {
237 delete topData()->qwsManager;
238 topData()->qwsManager = 0;
239 data.crect.translate(-topextra->frameStrut.left(), -topextra->frameStrut.top());
240 topextra->frameStrut.setCoords(0, 0, 0, 0);
241 }
242 #endif
243 if (!topextra->caption.isEmpty())
244 setWindowTitle_helper(topextra->caption);
245
246 //XXX If we are session managed, inform the window manager about it
247 } else {
248 if (extra && extra->topextra) { // already allocated due to reparent?
249 extra->topextra->frameStrut.setCoords(0, 0, 0, 0);
250 }
251 //updateRequestedRegion(mapToGlobal(QPoint(0,0)));
252 }
253 }
254
255
destroy(bool destroyWindow,bool destroySubWindows)256 void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
257 {
258 Q_D(QWidget);
259 d->aboutToDestroy();
260 if (!isWindow() && parentWidget())
261 parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
262
263 d->deactivateWidgetCleanup();
264 if (testAttribute(Qt::WA_WState_Created)) {
265 setAttribute(Qt::WA_WState_Created, false);
266 QObjectList childObjects = children();
267 for (int i = 0; i < childObjects.size(); ++i) {
268 QObject *obj = childObjects.at(i);
269 if (obj->isWidgetType())
270 static_cast<QWidget*>(obj)->destroy(destroySubWindows,
271 destroySubWindows);
272 }
273 releaseMouse();
274 if (qt_pressGrab == this)
275 qt_pressGrab = 0;
276
277 if (keyboardGrb == this)
278 releaseKeyboard();
279 if (testAttribute(Qt::WA_ShowModal)) // just be sure we leave modal
280 QApplicationPrivate::leaveModal(this);
281 else if ((windowType() == Qt::Popup))
282 qApp->d_func()->closePopup(this);
283 #ifndef QT_NO_IM
284 if (d->ic) {
285 delete d->ic;
286 d->ic =0;
287 } else {
288 // release previous focus information participating with
289 // preedit preservation of qic -- while we still have a winId
290 QInputContext *qic = QApplicationPrivate::inputContext;
291 if (qic)
292 qic->widgetDestroyed(this);
293 }
294 #endif //QT_NO_IM
295
296 if ((windowType() == Qt::Desktop)) {
297 } else {
298 if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) {
299 d->hide_sys();
300 }
301 if (destroyWindow && isWindow()) {
302 if (d->extra && d->extra->topextra && d->extra->topextra->backingStore)
303 d->extra->topextra->backingStore->windowSurface->setGeometry(QRect());
304 qwsDisplay()->destroyRegion(internalWinId());
305 }
306 }
307 QT_TRY {
308 d->setWinId(0);
309 } QT_CATCH (const std::bad_alloc &) {
310 // swallow - destructors must not throw
311 }
312 }
313 }
314
315
setParent_sys(QWidget * newparent,Qt::WindowFlags f)316 void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
317 {
318 Q_Q(QWidget);
319 bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
320 if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
321 q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
322 #ifndef QT_NO_CURSOR
323 QCursor oldcurs;
324 bool setcurs=q->testAttribute(Qt::WA_SetCursor);
325 if (setcurs) {
326 oldcurs = q->cursor();
327 q->unsetCursor();
328 }
329 #endif
330
331 WId old_winid = data.winid;
332 if ((q->windowType() == Qt::Desktop))
333 old_winid = 0;
334
335 if (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_WState_Created))
336 hide_sys();
337
338 setWinId(0);
339
340 if (parent != newparent) {
341 QWidget *oldparent = q->parentWidget();
342 QObjectPrivate::setParent_helper(newparent);
343 if (oldparent) {
344 // oldparent->d_func()->setChildrenAllocatedDirty();
345 // oldparent->data->paintable_region_dirty = true;
346 }
347 if (newparent) {
348 // newparent->d_func()->setChildrenAllocatedDirty();
349 // newparent->data->paintable_region_dirty = true;
350 //@@@@@@@
351 }
352 }
353 Qt::FocusPolicy fp = q->focusPolicy();
354 QSize s = q->size();
355 //QBrush bgc = background(); // save colors
356 bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
357
358 data.window_flags = f;
359 q->setAttribute(Qt::WA_WState_Created, false);
360 q->setAttribute(Qt::WA_WState_Visible, false);
361 q->setAttribute(Qt::WA_WState_Hidden, false);
362 adjustFlags(data.window_flags, q);
363 // keep compatibility with previous versions, we need to preserve the created state
364 // (but we recreate the winId for the widget being reparented, again for compatibility)
365 if (wasCreated || (!q->isWindow() && newparent->testAttribute(Qt::WA_WState_Created)))
366 createWinId();
367 if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
368 q->setAttribute(Qt::WA_WState_Hidden);
369 q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
370
371 if (q->isWindow()) {
372 QRect fs = frameStrut();
373 data.crect = QRect(fs.left(), fs.top(), s.width(), s.height());
374 if ((data.window_flags & Qt::FramelessWindowHint) && extra && extra->topextra)
375 extra->topextra->frameStrut.setCoords(0, 0, 0, 0);
376 } else {
377 data.crect = QRect(0, 0, s.width(), s.height());
378 }
379
380 q->setFocusPolicy(fp);
381 if (extra && !extra->mask.isEmpty()) {
382 QRegion r = extra->mask;
383 extra->mask = QRegion();
384 q->setMask(r);
385 }
386 if ((int)old_winid > 0) {
387 QWidget::qwsDisplay()->destroyRegion(old_winid);
388 extra->topextra->backingStore->windowSurface->setGeometry(QRect());
389 }
390 #ifndef QT_NO_CURSOR
391 if (setcurs) {
392 q->setCursor(oldcurs);
393 }
394 #endif
395 }
396
397
mapToGlobal(const QPoint & pos) const398 QPoint QWidget::mapToGlobal(const QPoint &pos) const
399 {
400 int x=pos.x(), y=pos.y();
401 const QWidget* w = this;
402 while (w) {
403 x += w->data->crect.x();
404 y += w->data->crect.y();
405 w = w->isWindow() ? 0 : w->parentWidget();
406 }
407 return QPoint(x, y);
408 }
409
mapFromGlobal(const QPoint & pos) const410 QPoint QWidget::mapFromGlobal(const QPoint &pos) const
411 {
412 int x=pos.x(), y=pos.y();
413 const QWidget* w = this;
414 while (w) {
415 x -= w->data->crect.x();
416 y -= w->data->crect.y();
417 w = w->isWindow() ? 0 : w->parentWidget();
418 }
419 return QPoint(x, y);
420 }
421
422 #if 0 // #####
423 void QWidget::setMicroFocusHint(int x, int y, int width, int height,
424 bool text, QFont *)
425 {
426 if (QRect(x, y, width, height) != microFocusHint()) {
427 d->createExtra();
428 d->extra->micro_focus_hint.setRect(x, y, width, height);
429 }
430 #ifndef QT_NO_QWS_INPUTMETHODS
431 if (text) {
432 QWidget *tlw = window();
433 int winid = tlw->internalWinId();
434 QPoint p(x, y + height);
435 QPoint gp = mapToGlobal(p);
436
437 QRect r = QRect(mapToGlobal(QPoint(0,0)),
438 size());
439
440 r.setBottom(tlw->geometry().bottom());
441
442 //qDebug("QWidget::setMicroFocusHint %d %d %d %d", r.x(),
443 // r.y(), r.width(), r.height());
444 QInputContext::setMicroFocusWidget(this);
445
446 qwsDisplay()->setIMInfo(winid, gp.x(), gp.y(), r);
447
448 //send font info, ###if necessary
449 qwsDisplay()->setInputFont(winid, font());
450 }
451 #endif
452 }
453 #endif
454
updateSystemBackground()455 void QWidgetPrivate::updateSystemBackground() {}
456
457 #ifndef QT_NO_CURSOR
setCursor_sys(const QCursor & cursor)458 void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
459 {
460 Q_UNUSED(cursor);
461 Q_Q(QWidget);
462 if (q->isVisible())
463 updateCursor();
464 }
465
unsetCursor_sys()466 void QWidgetPrivate::unsetCursor_sys()
467 {
468 Q_Q(QWidget);
469 if (q->isVisible())
470 updateCursor();
471 }
472 #endif //QT_NO_CURSOR
473
setWindowTitle_sys(const QString & caption)474 void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
475 {
476 Q_Q(QWidget);
477 QWidget::qwsDisplay()->setWindowCaption(q, caption);
478 }
479
setWindowIcon_sys(bool)480 void QWidgetPrivate::setWindowIcon_sys(bool /*forceReset*/)
481 {
482 #if 0
483 QTLWExtra* x = d->topData();
484 delete x->icon;
485 x->icon = 0;
486 QBitmap mask;
487 if (unscaledPixmap.isNull()) {
488 } else {
489 QImage unscaledIcon = unscaledPixmap.toImage();
490 QPixmap pixmap =
491 QPixmap::fromImage(unscaledIcon.scale(16, 16, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
492 x->icon = new QPixmap(pixmap);
493 mask = pixmap.mask() ? *pixmap.mask() : pixmap.createHeuristicMask();
494 }
495 #endif
496 }
497
setWindowIconText_sys(const QString & iconText)498 void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
499 {
500 Q_UNUSED(iconText);
501 }
502
grabMouse()503 void QWidget::grabMouse()
504 {
505 if (qt_mouseGrb)
506 qt_mouseGrb->releaseMouse();
507
508 qwsDisplay()->grabMouse(this,true);
509
510 qt_mouseGrb = this;
511 qt_pressGrab = 0;
512 }
513
514 #ifndef QT_NO_CURSOR
grabMouse(const QCursor & cursor)515 void QWidget::grabMouse(const QCursor &cursor)
516 {
517 if (qt_mouseGrb)
518 qt_mouseGrb->releaseMouse();
519
520 qwsDisplay()->grabMouse(this,true);
521 qwsDisplay()->selectCursor(this, cursor.handle());
522 qt_mouseGrb = this;
523 qt_pressGrab = 0;
524 }
525 #endif
526
releaseMouse()527 void QWidget::releaseMouse()
528 {
529 if (qt_mouseGrb == this) {
530 qwsDisplay()->grabMouse(this,false);
531 qt_mouseGrb = 0;
532 }
533 }
534
grabKeyboard()535 void QWidget::grabKeyboard()
536 {
537 if (keyboardGrb)
538 keyboardGrb->releaseKeyboard();
539 qwsDisplay()->grabKeyboard(this, true);
540 keyboardGrb = this;
541 }
542
releaseKeyboard()543 void QWidget::releaseKeyboard()
544 {
545 if (keyboardGrb == this) {
546 qwsDisplay()->grabKeyboard(this, false);
547 keyboardGrb = 0;
548 }
549 }
550
551
mouseGrabber()552 QWidget *QWidget::mouseGrabber()
553 {
554 if (qt_mouseGrb)
555 return qt_mouseGrb;
556 return qt_pressGrab;
557 }
558
559
keyboardGrabber()560 QWidget *QWidget::keyboardGrabber()
561 {
562 return keyboardGrb;
563 }
564
activateWindow()565 void QWidget::activateWindow()
566 {
567 QWidget *tlw = window();
568 if (tlw->isVisible()) {
569 Q_ASSERT(tlw->testAttribute(Qt::WA_WState_Created));
570 qwsDisplay()->requestFocus(tlw->internalWinId(), true);
571 }
572 }
573
show_sys()574 void QWidgetPrivate::show_sys()
575 {
576 Q_Q(QWidget);
577 q->setAttribute(Qt::WA_Mapped);
578 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
579 invalidateBuffer(q->rect());
580 return;
581 }
582
583 if (q->isWindow()) {
584
585
586 if (!q->testAttribute(Qt::WA_ShowWithoutActivating)
587 && q->windowType() != Qt::Popup
588 && q->windowType() != Qt::Tool
589 && q->windowType() != Qt::ToolTip) {
590 QWidget::qwsDisplay()->requestFocus(data.winid,true);
591 }
592
593
594 if (QWindowSurface *surface = q->windowSurface()) {
595 const QRect frameRect = q->frameGeometry();
596 if (surface->geometry() != frameRect)
597 surface->setGeometry(frameRect);
598 }
599
600 QRegion r = localRequestedRegion();
601 #ifndef QT_NO_QWS_MANAGER
602 if (extra && extra->topextra && extra->topextra->qwsManager) {
603 r.translate(data.crect.topLeft());
604 r += extra->topextra->qwsManager->region();
605 r.translate(-data.crect.topLeft());
606 }
607 #endif
608 data.fstrut_dirty = true;
609 invalidateBuffer(r);
610 bool staysontop =
611 (q->windowFlags() & Qt::WindowStaysOnTopHint)
612 || q->windowType() == Qt::Popup;
613 if (!staysontop && q->parentWidget()) { // if our parent stays on top, so must we
614 QWidget *ptl = q->parentWidget()->window();
615 if (ptl && (ptl->windowFlags() & Qt::WindowStaysOnTopHint))
616 staysontop = true;
617 }
618
619 QWSChangeAltitudeCommand::Altitude altitude;
620 altitude = staysontop ? QWSChangeAltitudeCommand::StaysOnTop : QWSChangeAltitudeCommand::Raise;
621 QWidget::qwsDisplay()->setAltitude(data.winid, altitude, true);
622 if (!q->objectName().isEmpty()) {
623 QWidget::qwsDisplay()->setWindowCaption(q, q->windowTitle());
624 }
625 }
626 #ifdef Q_BACKINGSTORE_SUBSURFACES
627 else if ( extra && extra->topextra && extra->topextra->windowSurface) {
628 QWSWindowSurface *surface;
629 surface = static_cast<QWSWindowSurface*>(q->windowSurface());
630 const QPoint p = q->mapToGlobal(QPoint());
631 surface->setGeometry(QRect(p, q->size()));
632 }
633 #endif
634
635 if (!q->window()->data->in_show) {
636 invalidateBuffer(q->rect());
637 }
638 }
639
640
hide_sys()641 void QWidgetPrivate::hide_sys()
642 {
643 Q_Q(QWidget);
644 deactivateWidgetCleanup();
645
646 if (q->isWindow()) {
647 q->releaseMouse();
648 // requestWindowRegion(QRegion());
649
650 if (extra->topextra->backingStore)
651 extra->topextra->backingStore->releaseBuffer();
652
653
654 QWidget::qwsDisplay()->requestFocus(data.winid,false);
655 } else {
656 QWidget *p = q->parentWidget();
657 if (p &&p->isVisible()) {
658 invalidateBuffer(q->rect());
659 }
660 }
661 }
662
663
664
effectiveState(Qt::WindowStates state)665 static Qt::WindowStates effectiveState(Qt::WindowStates state)
666 {
667 if (state & Qt::WindowMinimized)
668 return Qt::WindowMinimized;
669 else if (state & Qt::WindowFullScreen)
670 return Qt::WindowFullScreen;
671 else if (state & Qt::WindowMaximized)
672 return Qt::WindowMaximized;
673 return Qt::WindowNoState;
674 }
675
setMaxWindowState_helper()676 void QWidgetPrivate::setMaxWindowState_helper()
677 {
678 // in_set_window_state is usually set in setWindowState(), but this
679 // function is used in other functions as well
680 // (e.g QApplicationPrivate::setMaxWindowRect())
681 const uint old_state = data.in_set_window_state;
682 data.in_set_window_state = 1;
683
684 #ifndef QT_NO_QWS_MANAGER
685 if (extra && extra->topextra && extra->topextra->qwsManager)
686 extra->topextra->qwsManager->maximize();
687 else
688 #endif
689 {
690 Q_Q(QWidget);
691 const QDesktopWidget *desktop = QApplication::desktop();
692 const int screen = desktop->screenNumber(q);
693 const QRect maxWindowRect = desktop->availableGeometry(screen);
694 q->setGeometry(maxWindowRect);
695 }
696 data.in_set_window_state = old_state;
697 }
698
setFullScreenSize_helper()699 void QWidgetPrivate::setFullScreenSize_helper()
700 {
701 Q_Q(QWidget);
702
703 const uint old_state = data.in_set_window_state;
704 data.in_set_window_state = 1;
705
706 const QRect screen = qApp->desktop()->screenGeometry(qApp->desktop()->screenNumber(q));
707 q->move(screen.topLeft());
708 q->resize(screen.size());
709
710 data.in_set_window_state = old_state;
711 }
712
setWindowState(Qt::WindowStates newstate)713 void QWidget::setWindowState(Qt::WindowStates newstate)
714 {
715 Q_D(QWidget);
716 Qt::WindowStates oldstate = windowState();
717 if (oldstate == newstate)
718 return;
719 if (isWindow() && !testAttribute(Qt::WA_WState_Created))
720 create();
721
722 data->window_state = newstate;
723 data->in_set_window_state = 1;
724 bool needShow = false;
725 Qt::WindowStates newEffectiveState = effectiveState(newstate);
726 Qt::WindowStates oldEffectiveState = effectiveState(oldstate);
727 if (isWindow() && newEffectiveState != oldEffectiveState) {
728 d->createTLExtra();
729 if (oldEffectiveState == Qt::WindowNoState) { //normal
730 d->topData()->normalGeometry = geometry();
731 } else if (oldEffectiveState == Qt::WindowFullScreen) {
732 setParent(0, d->topData()->savedFlags);
733 needShow = true;
734 } else if (oldEffectiveState == Qt::WindowMinimized) {
735 needShow = true;
736 }
737
738 if (newEffectiveState == Qt::WindowMinimized) {
739 //### not ideal...
740 hide();
741 needShow = false;
742 } else if (newEffectiveState == Qt::WindowFullScreen) {
743 d->topData()->savedFlags = windowFlags();
744 setParent(0, Qt::FramelessWindowHint | (windowFlags() & Qt::WindowStaysOnTopHint));
745 d->setFullScreenSize_helper();
746 raise();
747 needShow = true;
748 } else if (newEffectiveState == Qt::WindowMaximized) {
749 createWinId();
750 d->setMaxWindowState_helper();
751 } else { //normal
752 QRect r = d->topData()->normalGeometry;
753 if (r.width() >= 0) {
754 d->topData()->normalGeometry = QRect(0,0,-1,-1);
755 setGeometry(r);
756 }
757 }
758 }
759 data->in_set_window_state = 0;
760
761 if (needShow)
762 show();
763
764 if (newstate & Qt::WindowActive)
765 activateWindow();
766
767 QWindowStateChangeEvent e(oldstate);
768 QApplication::sendEvent(this, &e);
769 }
770
setFocus_sys()771 void QWidgetPrivate::setFocus_sys()
772 {
773
774 }
775
raise_sys()776 void QWidgetPrivate::raise_sys()
777 {
778 Q_Q(QWidget);
779 //@@@ transaction
780 if (q->isWindow()) {
781 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
782 QWidget::qwsDisplay()->setAltitude(q->internalWinId(),
783 QWSChangeAltitudeCommand::Raise);
784 // XXX: subsurfaces?
785 #ifdef QT_NO_WINDOWGROUPHINT
786 #else
787 QObjectList childObjects = q->children();
788 if (!childObjects.isEmpty()) {
789 QWidgetList toraise;
790 for (int i = 0; i < childObjects.size(); ++i) {
791 QObject *obj = childObjects.at(i);
792 if (obj->isWidgetType()) {
793 QWidget* w = static_cast<QWidget*>(obj);
794 if (w->isWindow())
795 toraise.append(w);
796 }
797 }
798
799 for (int i = 0; i < toraise.size(); ++i) {
800 QWidget *w = toraise.at(i);
801 if (w->isVisible())
802 w->raise();
803 }
804 }
805 #endif // QT_NO_WINDOWGROUPHINT
806 }
807 }
808
lower_sys()809 void QWidgetPrivate::lower_sys()
810 {
811 Q_Q(QWidget);
812 if (q->isWindow()) {
813 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
814 QWidget::qwsDisplay()->setAltitude(data.winid,
815 QWSChangeAltitudeCommand::Lower);
816 } else if (QWidget *p = q->parentWidget()) {
817 setDirtyOpaqueRegion();
818 p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
819 }
820 }
821
stackUnder_sys(QWidget *)822 void QWidgetPrivate::stackUnder_sys(QWidget*)
823 {
824 Q_Q(QWidget);
825 if (QWidget *p = q->parentWidget()) {
826 setDirtyOpaqueRegion();
827 p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
828 }
829 }
830
moveSurface(QWindowSurface * surface,const QPoint & offset)831 void QWidgetPrivate::moveSurface(QWindowSurface *surface, const QPoint &offset)
832 {
833 QWSWindowSurface *s = static_cast<QWSWindowSurface*>(surface);
834 if (!s->move(offset))
835 s->invalidateBuffer();
836
837 QWSDisplay::instance()->moveRegion(s->winId(), offset.x(), offset.y());
838 }
839
setGeometry_sys(int x,int y,int w,int h,bool isMove)840 void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
841 {
842 Q_Q(QWidget);
843 if (extra) { // any size restrictions?
844 w = qMin(w,extra->maxw);
845 h = qMin(h,extra->maxh);
846 w = qMax(w,extra->minw);
847 h = qMax(h,extra->minh);
848 }
849
850 QPoint oldp = q->geometry().topLeft();
851 QSize olds = q->size();
852 QRect r(x, y, w, h);
853
854 bool isResize = olds != r.size();
855 isMove = oldp != r.topLeft(); //### why do we have isMove as a parameter?
856
857 // We only care about stuff that changes the geometry, or may
858 // cause the window manager to change its state
859 if (r.size() == olds && oldp == r.topLeft())
860 return;
861
862 if (!data.in_set_window_state) {
863 q->data->window_state &= ~Qt::WindowMaximized;
864 q->data->window_state &= ~Qt::WindowFullScreen;
865 if (q->isWindow())
866 topData()->normalGeometry = QRect(0, 0, -1, -1);
867 }
868 QPoint oldPos = q->pos();
869 data.crect = r;
870
871 if ((q->windowType() == Qt::Desktop))
872 return;
873
874 if (q->isVisible()) {
875
876 bool toplevelMove = false;
877 QWSWindowSurface *surface = 0;
878
879 if (q->isWindow()) {
880 //### ConfigPending not implemented, do we need it?
881 //setAttribute(Qt::WA_WState_ConfigPending);
882 const QWidgetBackingStore *bs = maybeBackingStore();
883 if (bs)
884 surface = static_cast<QWSWindowSurface*>(bs->windowSurface);
885 if (isMove && !isResize && surface) {
886 const QPoint offset(x - oldp.x(), y - oldp.y());
887 moveSurface(surface, offset);
888 toplevelMove = true; //server moves window, but we must send moveEvent, which might trigger painting
889
890 #ifdef Q_BACKINGSTORE_SUBSURFACES
891 QList<QWindowSurface*> surfaces = bs->subSurfaces;
892 for (int i = 0; i < surfaces.size(); ++i)
893 moveSurface(surfaces.at(i), offset);
894 #endif
895 } else {
896 updateFrameStrut();
897 }
898 }
899
900 if (!toplevelMove) {
901 if (q->isWindow()) {
902 if (surface)
903 surface->setGeometry(q->frameGeometry());
904 else
905 invalidateBuffer(q->rect()); //###
906
907 #ifdef Q_BACKINGSTORE_SUBSURFACES
908 // XXX: should not resize subsurfaces. Children within a layout
909 // will be resized automatically while children with a static
910 // geometry should get a new clip region instead.
911 const QRect clipRect = q->geometry();
912 QWidgetBackingStore *bs = maybeBackingStore();
913 QList<QWindowSurface*> surfaces = bs->subSurfaces;
914 for (int i = 0; i < surfaces.size(); ++i) {
915 QWSWindowSurface *s = static_cast<QWSWindowSurface*>(surfaces.at(i));
916 QRect srect = s->geometry();
917 s->setGeometry(clipRect & srect);
918 }
919 #endif
920 }
921 #ifdef Q_BACKINGSTORE_SUBSURFACES
922 // XXX: merge this case with the isWindow() case
923 else if (maybeTopData() && maybeTopData()->windowSurface) {
924 QWSWindowSurface *surface;
925 surface = static_cast<QWSWindowSurface*>(q->windowSurface());
926 if (isMove && !isResize) {
927 moveSurface(surface, QPoint(x - oldp.x(), y - oldp.y()));
928 } else {
929 const QPoint p = q->mapToGlobal(QPoint());
930 surface->setGeometry(QRect(p, QSize(w, h)));
931 }
932 }
933 #endif
934 else {
935 if (isMove && !isResize)
936 moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
937 else
938 invalidateBuffer_resizeHelper(oldPos, olds);
939 }
940 }
941
942 //### must have frame geometry correct before sending move/resize events
943 if (isMove) {
944 QMoveEvent e(q->pos(), oldPos);
945 QApplication::sendEvent(q, &e);
946 }
947 if (isResize) {
948 QResizeEvent e(r.size(), olds);
949 QApplication::sendEvent(q, &e);
950 }
951
952 } else { // not visible
953 if (isMove && q->pos() != oldPos)
954 q->setAttribute(Qt::WA_PendingMoveEvent, true);
955 if (isResize)
956 q->setAttribute(Qt::WA_PendingResizeEvent, true);
957 }
958 }
959
setConstraints_sys()960 void QWidgetPrivate::setConstraints_sys()
961 {
962 }
963
getScreen() const964 QScreen* QWidgetPrivate::getScreen() const
965 {
966 Q_Q(const QWidget);
967
968 const QList<QScreen*> subScreens = qt_screen->subScreens();
969 if (subScreens.isEmpty() || q->windowType() == Qt::Desktop)
970 return qt_screen;
971
972 const int screen = QApplication::desktop()->screenNumber(q);
973
974 return qt_screen->subScreens().at(screen < 0 ? 0 : screen);
975 }
976
scroll_sys(int dx,int dy)977 void QWidgetPrivate::scroll_sys(int dx, int dy)
978 {
979 Q_Q(QWidget);
980 scrollChildren(dx, dy);
981 scrollRect(q->rect(), dx, dy);
982 }
983
scroll_sys(int dx,int dy,const QRect & r)984 void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
985 {
986 scrollRect(r, dx, dy);
987 }
988
metric(PaintDeviceMetric m) const989 int QWidget::metric(PaintDeviceMetric m) const
990 {
991 Q_D(const QWidget);
992
993 int val;
994 if (m == PdmWidth) {
995 val = data->crect.width();
996 } else if (m == PdmWidthMM) {
997 const QScreen *screen = d->getScreen();
998 val = data->crect.width() * screen->physicalWidth() / screen->width();
999 } else if (m == PdmHeight) {
1000 val = data->crect.height();
1001 } else if (m == PdmHeightMM) {
1002 const QScreen *screen = d->getScreen();
1003 val = data->crect.height() * screen->physicalHeight() / screen->height();
1004 } else if (m == PdmDepth) {
1005 return qwsDisplay()->depth();
1006 } else if (m == PdmDpiX || m == PdmPhysicalDpiX) {
1007 if (d->extra && d->extra->customDpiX)
1008 return d->extra->customDpiX;
1009 else if (d->parent)
1010 return static_cast<QWidget *>(d->parent)->metric(m);
1011 const QScreen *screen = d->getScreen();
1012 return qRound(screen->width() / double(screen->physicalWidth() / 25.4));
1013 } else if (m == PdmDpiY || m == PdmPhysicalDpiY) {
1014 if (d->extra && d->extra->customDpiY)
1015 return d->extra->customDpiY;
1016 else if (d->parent)
1017 return static_cast<QWidget *>(d->parent)->metric(m);
1018 const QScreen *screen = d->getScreen();
1019 return qRound(screen->height() / double(screen->physicalHeight() / 25.4));
1020 } else if (m == PdmNumColors) {
1021 QScreen *screen = d->getScreen();
1022 int ret = screen->colorCount();
1023 if (!ret) {
1024 const int depth = qwsDisplay()->depth();
1025 switch (depth) {
1026 case 1:
1027 ret = 2;
1028 break;
1029 case 8:
1030 ret = 256;
1031 break;
1032 case 16:
1033 ret = 65536;
1034 break;
1035 case 24:
1036 ret = 16777216;
1037 break;
1038 case 32:
1039 ret = 2147483647;
1040 break;
1041 }
1042 }
1043 return ret;
1044 } else {
1045 val = QPaintDevice::metric(m);// XXX
1046 }
1047 return val;
1048 }
1049
createSysExtra()1050 void QWidgetPrivate::createSysExtra()
1051 {
1052 }
1053
deleteSysExtra()1054 void QWidgetPrivate::deleteSysExtra()
1055 {
1056 }
1057
createTLSysExtra()1058 void QWidgetPrivate::createTLSysExtra()
1059 {
1060 #ifndef QT_NO_QWS_MANAGER
1061 extra->topextra->qwsManager = 0;
1062 #endif
1063 }
1064
deleteTLSysExtra()1065 void QWidgetPrivate::deleteTLSysExtra()
1066 {
1067 }
1068
registerDropSite(bool on)1069 void QWidgetPrivate::registerDropSite(bool on)
1070 {
1071 Q_UNUSED(on);
1072 }
1073
localRequestedRegion() const1074 QRegion QWidgetPrivate::localRequestedRegion() const
1075 {
1076 Q_Q(const QWidget);
1077 QRegion r(q->rect());
1078 if (extra && !extra->mask.isEmpty())
1079 r &= extra->mask;
1080
1081 return r;
1082 }
1083
localAllocatedRegion() const1084 QRegion QWidgetPrivate::localAllocatedRegion() const
1085 {
1086 Q_Q(const QWidget);
1087
1088 QWidgetBackingStore *wbs = q->window()->d_func()->maybeBackingStore();
1089
1090 QWindowSurface *ws = wbs ? wbs->windowSurface : 0;
1091 if (!ws)
1092 return QRegion();
1093 QRegion r = static_cast<QWSWindowSurface*>(ws)->clipRegion();
1094 if (!q->isWindow()) {
1095 QPoint off = q->mapTo(q->window(), QPoint());
1096 r &= localRequestedRegion().translated(off);
1097 r.translate(-off);
1098 }
1099 return r;
1100 }
1101
intersects(const QRect & r) const1102 inline bool QRect::intersects(const QRect &r) const
1103 {
1104 return (qMax(x1, r.x1) <= qMin(x2, r.x2) &&
1105 qMax(y1, r.y1) <= qMin(y2, r.y2));
1106 }
1107
setMask_sys(const QRegion & region)1108 void QWidgetPrivate::setMask_sys(const QRegion ®ion)
1109 {
1110 Q_UNUSED(region);
1111 Q_Q(QWidget);
1112
1113 if (!q->isVisible() || !q->isWindow())
1114 return;
1115
1116 data.fstrut_dirty = true;
1117 invalidateBuffer(q->rect());
1118 QWindowSurface *surface = extra->topextra->backingStore->windowSurface;
1119 if (surface) {
1120 // QWSWindowSurface::setGeometry() returns without doing anything
1121 // if old geom == new geom. Therefore, we need to reset the old value.
1122 surface->QWindowSurface::setGeometry(QRect());
1123 surface->setGeometry(q->frameGeometry());
1124 }
1125 }
1126
updateFrameStrut()1127 void QWidgetPrivate::updateFrameStrut()
1128 {
1129 Q_Q(QWidget);
1130
1131 if(!q->isVisible() || (q->windowType() == Qt::Desktop)) {
1132 data.fstrut_dirty = q->isVisible();
1133 return;
1134 }
1135
1136 #ifndef QT_NO_QWS_MANAGER
1137 if (extra && extra->topextra && extra->topextra->qwsManager) {
1138 QTLWExtra *topextra = extra->topextra;
1139 const QRect oldFrameStrut = topextra->frameStrut;
1140 const QRect contents = data.crect;
1141 QRegion r = localRequestedRegion().translated(contents.topLeft());
1142 r += extra->topextra->qwsManager->region();
1143 const QRect frame = r.boundingRect();
1144
1145 topextra->frameStrut.setCoords(contents.left() - frame.left(),
1146 contents.top() - frame.top(),
1147 frame.right() - contents.right(),
1148 frame.bottom() - contents.bottom());
1149 topextra->qwsManager->repaintRegion(QDecoration::All, QDecoration::Normal);
1150 }
1151 #endif
1152 data.fstrut_dirty = false;
1153 }
1154
1155 #ifndef QT_NO_CURSOR
updateCursor() const1156 void QWidgetPrivate::updateCursor() const
1157 {
1158 Q_Q(const QWidget);
1159
1160 if (QApplication::overrideCursor())
1161 return;
1162
1163 if (qt_last_x
1164 && (!QWidget::mouseGrabber() || QWidget::mouseGrabber() == q)
1165 && qt_last_cursor != (WId)q->cursor().handle())
1166 {
1167 const QPoint pos(*qt_last_x, *qt_last_y);
1168 const QPoint offset = q->mapToGlobal(QPoint());
1169 if (!localAllocatedRegion().contains(pos - offset))
1170 return;
1171
1172 const QWidget *w = q->childAt(q->mapFromGlobal(pos));
1173 if (!w || w->cursor().handle() == q->cursor().handle())
1174 QWidget::qwsDisplay()->selectCursor(const_cast<QWidget*>(q),
1175 q->cursor().handle());
1176 }
1177 }
1178 #endif
1179
setWindowOpacity_sys(qreal level)1180 void QWidgetPrivate::setWindowOpacity_sys(qreal level)
1181 {
1182 Q_Q(QWidget);
1183 Q_UNUSED(level);
1184 createWinId();
1185 QWidget::qwsDisplay()->setOpacity(q->data->winid, topData()->opacity);
1186 }
1187
1188 //static QSingleCleanupHandler<QWSPaintEngine> qt_paintengine_cleanup_handler;
1189 //static QWSPaintEngine *qt_widget_paintengine = 0;
paintEngine() const1190 QPaintEngine *QWidget::paintEngine() const
1191 {
1192 qWarning("QWidget::paintEngine: Should no longer be called");
1193 return 0; //##### @@@
1194 // if (!qt_widget_paintengine) {
1195 // qt_widget_paintengine = new QRasterPaintEngine();
1196 // qt_paintengine_cleanup_handler.set(&qt_widget_paintengine);
1197 // }
1198 // if (qt_widget_paintengine->isActive()) {
1199 // if (d->extraPaintEngine)
1200 // return d->extraPaintEngine;
1201 // const_cast<QWidget *>(this)->d_func()->extraPaintEngine = new QRasterPaintEngine();
1202 // return d->extraPaintEngine;
1203 // }
1204 // return qt_widget_paintengine;
1205 }
1206
createDefaultWindowSurface_sys()1207 QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
1208 {
1209 Q_Q(QWidget);
1210 if (q->windowType() == Qt::Desktop)
1211 return 0;
1212 q->ensurePolished();
1213 return qt_screen->createSurface(q);
1214 }
1215
setModal_sys()1216 void QWidgetPrivate::setModal_sys()
1217 {
1218 }
1219
1220
1221 QT_END_NAMESPACE
1222