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_p.h"
43 #include "qcolormap.h"
44 #include "qpixmapcache.h"
45 #if defined(Q_OS_BLACKBERRY)
46 #include "qeventdispatcher_blackberry_qpa_p.h"
47 #else
48 #if !defined(QT_NO_GLIB)
49 #include "qeventdispatcher_glib_qpa_p.h"
50 #endif
51 #include "qeventdispatcher_qpa_p.h"
52 #endif
53 #ifndef QT_NO_CURSOR
54 #include "private/qcursor_p.h"
55 #endif
56
57 #include "private/qwidget_p.h"
58 #include "private/qevent_p.h"
59
60 #include "qgenericpluginfactory_qpa.h"
61 #include "qplatformintegrationfactory_qpa_p.h"
62 #include <qdesktopwidget.h>
63
64 #include <qinputcontext.h>
65 #include <QPlatformCursor>
66 #include <qdebug.h>
67 #include <QWindowSystemInterface>
68 #include "qwindowsysteminterface_qpa_p.h"
69 #include <QPlatformIntegration>
70
71 #include "qdesktopwidget_qpa_p.h"
72
73 QT_BEGIN_NAMESPACE
74
75 static QString appName;
76 static QString appFont;
77
78 QWidget *qt_button_down = 0; // widget got last button-down
79
80 static bool app_do_modal = false;
81 extern QWidgetList *qt_modal_stack; // stack of modal widgets
82
83 int qt_last_x = 0;
84 int qt_last_y = 0;
85 QPointer<QWidget> qt_last_mouse_receiver = 0;
86
87 static Qt::MouseButtons buttons = Qt::NoButton;
88 static ulong mousePressTime;
89 static Qt::MouseButton mousePressButton = Qt::NoButton;
90 static int mousePressX;
91 static int mousePressY;
92 static int mouse_double_click_distance = 5;
93
processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent * e)94 void QApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e)
95 {
96 switch(e->type) {
97 case QWindowSystemInterfacePrivate::Mouse:
98 QApplicationPrivate::processMouseEvent(static_cast<QWindowSystemInterfacePrivate::MouseEvent *>(e));
99 break;
100 case QWindowSystemInterfacePrivate::Wheel:
101 QApplicationPrivate::processWheelEvent(static_cast<QWindowSystemInterfacePrivate::WheelEvent *>(e));
102 break;
103 case QWindowSystemInterfacePrivate::Key:
104 QApplicationPrivate::processKeyEvent(static_cast<QWindowSystemInterfacePrivate::KeyEvent *>(e));
105 break;
106 case QWindowSystemInterfacePrivate::Touch:
107 QApplicationPrivate::processTouchEvent(static_cast<QWindowSystemInterfacePrivate::TouchEvent *>(e));
108 break;
109 case QWindowSystemInterfacePrivate::GeometryChange:
110 QApplicationPrivate::processGeometryChangeEvent(static_cast<QWindowSystemInterfacePrivate::GeometryChangeEvent*>(e));
111 break;
112 case QWindowSystemInterfacePrivate::Enter:
113 QApplicationPrivate::processEnterEvent(static_cast<QWindowSystemInterfacePrivate::EnterEvent *>(e));
114 break;
115 case QWindowSystemInterfacePrivate::Leave:
116 QApplicationPrivate::processLeaveEvent(static_cast<QWindowSystemInterfacePrivate::LeaveEvent *>(e));
117 break;
118 case QWindowSystemInterfacePrivate::ActivatedWindow:
119 QApplicationPrivate::processActivatedEvent(static_cast<QWindowSystemInterfacePrivate::ActivatedWindowEvent *>(e));
120 break;
121 case QWindowSystemInterfacePrivate::WindowStateChanged:
122 QApplicationPrivate::processWindowStateChangedEvent(static_cast<QWindowSystemInterfacePrivate::WindowStateChangedEvent *>(e));
123 break;
124 case QWindowSystemInterfacePrivate::Close:
125 QApplicationPrivate::processCloseEvent(
126 static_cast<QWindowSystemInterfacePrivate::CloseEvent *>(e));
127 break;
128 case QWindowSystemInterfacePrivate::ScreenCountChange:
129 QApplicationPrivate::reportScreenCount(
130 static_cast<QWindowSystemInterfacePrivate::ScreenCountEvent *>(e));
131 break;
132 case QWindowSystemInterfacePrivate::ScreenGeometry:
133 QApplicationPrivate::reportGeometryChange(
134 static_cast<QWindowSystemInterfacePrivate::ScreenGeometryEvent *>(e));
135 break;
136 case QWindowSystemInterfacePrivate::ScreenAvailableGeometry:
137 QApplicationPrivate::reportAvailableGeometryChange(
138 static_cast<QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *>(e));
139 break;
140 case QWindowSystemInterfacePrivate::LocaleChange:
141 QApplicationPrivate::reportLocaleChange();
142 break;
143 case QWindowSystemInterfacePrivate::PlatformPanel:
144 QApplicationPrivate::processPlatformPanelEvent(
145 static_cast<QWindowSystemInterfacePrivate::PlatformPanelEvent *>(e));
146 break;
147 default:
148 qWarning() << "Unknown user input event type:" << e->type;
149 break;
150 }
151 }
152
processWindowStateChangedEvent(QWindowSystemInterfacePrivate::WindowStateChangedEvent * wse)153 void QApplicationPrivate::processWindowStateChangedEvent(QWindowSystemInterfacePrivate::WindowStateChangedEvent *wse)
154 {
155 if (wse->tlw.isNull())
156 return;
157
158 QWidget *tlw = wse->tlw.data();
159 if (!tlw->isWindow())
160 return;
161
162 QWindowStateChangeEvent e(tlw->windowState());
163 tlw->setWindowState(wse->newState);
164 QApplication::sendSpontaneousEvent(tlw, &e);
165 }
166
appName() const167 QString QApplicationPrivate::appName() const
168 {
169 return QT_PREPEND_NAMESPACE(appName);
170 }
171
createEventDispatcher()172 void QApplicationPrivate::createEventDispatcher()
173 {
174 Q_Q(QApplication);
175 #if defined(Q_OS_BLACKBERRY)
176 eventDispatcher = new QEventDispatcherBlackberryQPA(q);
177 #else
178 #if !defined(QT_NO_GLIB)
179 if (qgetenv("QT_NO_GLIB").isEmpty() && QEventDispatcherGlib::versionSupported())
180 eventDispatcher = new QPAEventDispatcherGlib(q);
181 else
182 #endif
183 eventDispatcher = new QEventDispatcherQPA(q);
184 #endif
185 }
186
qt_try_modal(QWidget * widget,QEvent::Type type)187 static bool qt_try_modal(QWidget *widget, QEvent::Type type)
188 {
189 QWidget * top = 0;
190
191 if (QApplicationPrivate::tryModalHelper(widget, &top))
192 return true;
193
194 bool block_event = false;
195 bool paint_event = false;
196
197 switch (type) {
198 #if 0
199 case QEvent::Focus:
200 if (!static_cast<QWSFocusEvent*>(event)->simpleData.get_focus)
201 break;
202 // drop through
203 #endif
204 case QEvent::MouseButtonPress: // disallow mouse/key events
205 case QEvent::MouseButtonRelease:
206 case QEvent::MouseMove:
207 case QEvent::KeyPress:
208 case QEvent::KeyRelease:
209 case QEvent::PlatformPanel:
210 block_event = true;
211 break;
212 default:
213 break;
214 }
215
216 if ((block_event || paint_event) && top->parentWidget() == 0)
217 top->raise();
218
219 return !block_event;
220 }
221
222
223
enterModal_sys(QWidget * widget)224 void QApplicationPrivate::enterModal_sys(QWidget *widget)
225 {
226 if (!qt_modal_stack)
227 qt_modal_stack = new QWidgetList;
228 qt_modal_stack->insert(0, widget);
229 app_do_modal = true;
230 }
231
leaveModal_sys(QWidget * widget)232 void QApplicationPrivate::leaveModal_sys(QWidget *widget )
233 {
234 if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
235 if (qt_modal_stack->isEmpty()) {
236 delete qt_modal_stack;
237 qt_modal_stack = 0;
238 }
239 }
240 app_do_modal = qt_modal_stack != 0;
241 }
242
modalState()243 bool QApplicationPrivate::modalState()
244 {
245 return app_do_modal;
246 }
247
closePopup(QWidget * popup)248 void QApplicationPrivate::closePopup(QWidget *popup)
249 {
250 Q_Q(QApplication);
251 if (!popupWidgets)
252 return;
253 popupWidgets->removeAll(popup);
254
255 //###
256 // if (popup == qt_popup_down) {
257 // qt_button_down = 0;
258 // qt_popup_down = 0;
259 // }
260
261 if (QApplicationPrivate::popupWidgets->count() == 0) { // this was the last popup
262 delete QApplicationPrivate::popupWidgets;
263 QApplicationPrivate::popupWidgets = 0;
264
265 //### replay mouse event?
266
267 //### transfer/release mouse grab
268
269 //### transfer/release keyboard grab
270
271 //give back focus
272
273 if (active_window) {
274 if (QWidget *fw = active_window->focusWidget()) {
275 if (fw != QApplication::focusWidget()) {
276 fw->setFocus(Qt::PopupFocusReason);
277 } else {
278 QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
279 q->sendEvent(fw, &e);
280 }
281 }
282 }
283
284 } else {
285 // A popup was closed, so the previous popup gets the focus.
286
287 QWidget* aw = QApplicationPrivate::popupWidgets->last();
288 if (QWidget *fw = aw->focusWidget())
289 fw->setFocus(Qt::PopupFocusReason);
290
291 //### regrab the keyboard and mouse in case 'popup' lost the grab
292
293
294 }
295
296 }
297
298 static int openPopupCount = 0;
openPopup(QWidget * popup)299 void QApplicationPrivate::openPopup(QWidget *popup)
300 {
301 openPopupCount++;
302 if (!popupWidgets) { // create list
303 popupWidgets = new QWidgetList;
304
305 /* only grab if you are the first/parent popup */
306 //#### ->grabMouse(popup,true);
307 //#### ->grabKeyboard(popup,true);
308 //### popupGrabOk = true;
309 }
310 popupWidgets->append(popup); // add to end of list
311
312 // popups are not focus-handled by the window system (the first
313 // popup grabbed the keyboard), so we have to do that manually: A
314 // new popup gets the focus
315 if (popup->focusWidget()) {
316 popup->focusWidget()->setFocus(Qt::PopupFocusReason);
317 } else if (popupWidgets->count() == 1) { // this was the first popup
318 if (QWidget *fw = QApplication::focusWidget()) {
319 QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
320 QApplication::sendEvent(fw, &e);
321 }
322 }
323 }
324
initializeMultitouch_sys()325 void QApplicationPrivate::initializeMultitouch_sys()
326 {
327 }
328
cleanupMultitouch_sys()329 void QApplicationPrivate::cleanupMultitouch_sys()
330 {
331 }
332
initializeWidgetPaletteHash()333 void QApplicationPrivate::initializeWidgetPaletteHash()
334 {
335 }
336
setCursorFlashTime(int msecs)337 void QApplication::setCursorFlashTime(int msecs)
338 {
339 QApplicationPrivate::cursor_flash_time = msecs;
340 }
341
cursorFlashTime()342 int QApplication::cursorFlashTime()
343 {
344 return QApplicationPrivate::cursor_flash_time;
345 }
346
setDoubleClickInterval(int ms)347 void QApplication::setDoubleClickInterval(int ms)
348 {
349 QApplicationPrivate::mouse_double_click_time = ms;
350 }
351
doubleClickInterval()352 int QApplication::doubleClickInterval()
353 {
354 return QApplicationPrivate::mouse_double_click_time;
355 }
356
setKeyboardInputInterval(int ms)357 void QApplication::setKeyboardInputInterval(int ms)
358 {
359 QApplicationPrivate::keyboard_input_time = ms;
360 }
361
keyboardInputInterval()362 int QApplication::keyboardInputInterval()
363 {
364 return QApplicationPrivate::keyboard_input_time;
365 }
366
367 #ifndef QT_NO_WHEELEVENT
setWheelScrollLines(int lines)368 void QApplication::setWheelScrollLines(int lines)
369 {
370 QApplicationPrivate::wheel_scroll_lines = lines;
371 }
372
wheelScrollLines()373 int QApplication::wheelScrollLines()
374 {
375 return QApplicationPrivate::wheel_scroll_lines;
376 }
377 #endif
378
setEffectEnabled(Qt::UIEffect effect,bool enable)379 void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
380 {
381 switch (effect) {
382 case Qt::UI_AnimateMenu:
383 QApplicationPrivate::animate_menu = enable;
384 break;
385 case Qt::UI_FadeMenu:
386 if (enable)
387 QApplicationPrivate::animate_menu = true;
388 QApplicationPrivate::fade_menu = enable;
389 break;
390 case Qt::UI_AnimateCombo:
391 QApplicationPrivate::animate_combo = enable;
392 break;
393 case Qt::UI_AnimateTooltip:
394 QApplicationPrivate::animate_tooltip = enable;
395 break;
396 case Qt::UI_FadeTooltip:
397 if (enable)
398 QApplicationPrivate::animate_tooltip = true;
399 QApplicationPrivate::fade_tooltip = enable;
400 break;
401 case Qt::UI_AnimateToolBox:
402 QApplicationPrivate::animate_toolbox = enable;
403 break;
404 default:
405 QApplicationPrivate::animate_ui = enable;
406 break;
407 }
408 }
409
isEffectEnabled(Qt::UIEffect effect)410 bool QApplication::isEffectEnabled(Qt::UIEffect effect)
411 {
412 if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui)
413 return false;
414
415 switch(effect) {
416 case Qt::UI_AnimateMenu:
417 return QApplicationPrivate::animate_menu;
418 case Qt::UI_FadeMenu:
419 return QApplicationPrivate::fade_menu;
420 case Qt::UI_AnimateCombo:
421 return QApplicationPrivate::animate_combo;
422 case Qt::UI_AnimateTooltip:
423 return QApplicationPrivate::animate_tooltip;
424 case Qt::UI_FadeTooltip:
425 return QApplicationPrivate::fade_tooltip;
426 case Qt::UI_AnimateToolBox:
427 return QApplicationPrivate::animate_toolbox;
428 default:
429 return QApplicationPrivate::animate_ui;
430 }
431 }
432
433 #ifndef QT_NO_CURSOR
setOverrideCursor(const QCursor & cursor)434 void QApplication::setOverrideCursor(const QCursor &cursor)
435 {
436 qApp->d_func()->cursor_list.prepend(cursor);
437 qt_qpa_set_cursor(0, false);
438 }
439
restoreOverrideCursor()440 void QApplication::restoreOverrideCursor()
441 {
442 if (qApp->d_func()->cursor_list.isEmpty())
443 return;
444 qApp->d_func()->cursor_list.removeFirst();
445 qt_qpa_set_cursor(0, false);
446 }
447
448 #endif// QT_NO_CURSOR
449
topLevelAt(const QPoint & pos)450 QWidget *QApplication::topLevelAt(const QPoint &pos)
451 {
452 QPlatformIntegration *pi = QApplicationPrivate::platformIntegration();
453
454 QList<QPlatformScreen *> screens = pi->screens();
455 QList<QPlatformScreen *>::const_iterator screen = screens.constBegin();
456 QList<QPlatformScreen *>::const_iterator end = screens.constEnd();
457
458 // The first screen in a virtual environment should know about all top levels
459 if (pi->isVirtualDesktop()) {
460 QWidget *w = (*screen)->topLevelAt(pos);
461 return w;
462 }
463
464 while (screen != end) {
465 if ((*screen)->geometry().contains(pos))
466 return (*screen)->topLevelAt(pos);
467 ++screen;
468 }
469 return 0;
470 }
471
beep()472 void QApplication::beep()
473 {
474 }
475
alert(QWidget *,int)476 void QApplication::alert(QWidget *, int)
477 {
478 }
479
480 /*!
481 \internal
482 */
platformNativeInterface()483 QPlatformNativeInterface *QApplication::platformNativeInterface()
484 {
485 QPlatformIntegration *pi = QApplicationPrivate::platformIntegration();
486 return pi ? pi->nativeInterface() : 0;
487 }
488
init_platform(const QString & name,const QString & platformPluginPath)489 static void init_platform(const QString &name, const QString &platformPluginPath)
490 {
491 QApplicationPrivate::platform_integration = QPlatformIntegrationFactory::create(name, platformPluginPath);
492 if (!QApplicationPrivate::platform_integration) {
493 QStringList keys = QPlatformIntegrationFactory::keys(platformPluginPath);
494 QString fatalMessage =
495 QString::fromLatin1("Failed to load platform plugin \"%1\". Available platforms are: \n").arg(name);
496 foreach(QString key, keys) {
497 fatalMessage.append(key + QString::fromLatin1("\n"));
498 }
499 qFatal("%s", fatalMessage.toLocal8Bit().constData());
500
501 }
502
503 }
504
505
cleanup_platform()506 static void cleanup_platform()
507 {
508 delete QApplicationPrivate::platform_integration;
509 QApplicationPrivate::platform_integration = 0;
510 }
511
init_plugins(const QList<QByteArray> pluginList)512 static void init_plugins(const QList<QByteArray> pluginList)
513 {
514 for (int i = 0; i < pluginList.count(); ++i) {
515 QByteArray pluginSpec = pluginList.at(i);
516 qDebug() << "init_plugins" << i << pluginSpec;
517 int colonPos = pluginSpec.indexOf(':');
518 QObject *plugin;
519 if (colonPos < 0)
520 plugin = QGenericPluginFactory::create(QLatin1String(pluginSpec), QString());
521 else
522 plugin = QGenericPluginFactory::create(QLatin1String(pluginSpec.mid(0, colonPos)),
523 QLatin1String(pluginSpec.mid(colonPos+1)));
524 qDebug() << " created" << plugin;
525 }
526 }
527
528 #ifndef QT_NO_QWS_INPUTMETHODS
529 class QDummyInputContext : public QInputContext
530 {
531 public:
QDummyInputContext(QObject * parent=0)532 explicit QDummyInputContext(QObject* parent = 0) : QInputContext(parent) {}
~QDummyInputContext()533 ~QDummyInputContext() {}
identifierName()534 QString identifierName() { return QString(); }
language()535 QString language() { return QString(); }
536
reset()537 void reset() {}
isComposing() const538 bool isComposing() const { return false; }
539
540 };
541 #endif // QT_NO_QWS_INPUTMETHODS
542
qt_init(QApplicationPrivate * priv,int type)543 void qt_init(QApplicationPrivate *priv, int type)
544 {
545 Q_UNUSED(type);
546
547 qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
548 char *p;
549 char **argv = priv->argv;
550 int argc = priv->argc;
551
552 if (argv && *argv) { //apparently, we allow people to pass 0 on the other platforms
553 p = strrchr(argv[0], '/');
554 appName = QString::fromLocal8Bit(p ? p + 1 : argv[0]);
555 }
556
557 QList<QByteArray> pluginList;
558 QString platformPluginPath = QLatin1String(qgetenv("QT_QPA_PLATFORM_PLUGIN_PATH"));
559 QByteArray platformName;
560 #ifdef QT_QPA_DEFAULT_PLATFORM_NAME
561 platformName = QT_QPA_DEFAULT_PLATFORM_NAME;
562 #endif
563 QByteArray platformNameEnv = qgetenv("QT_QPA_PLATFORM");
564 if (!platformNameEnv.isEmpty()) {
565 platformName = platformNameEnv;
566 }
567
568 // Get command line params
569
570 int j = argc ? 1 : 0;
571 for (int i=1; i<argc; i++) {
572 if (argv[i] && *argv[i] != '-') {
573 argv[j++] = argv[i];
574 continue;
575 }
576 QByteArray arg = argv[i];
577 if (arg == "-fn" || arg == "-font") {
578 if (++i < argc)
579 appFont = QString::fromLocal8Bit(argv[i]);
580 } else if (arg == "-platformpluginpath") {
581 if (++i < argc)
582 platformPluginPath = QLatin1String(argv[i]);
583 } else if (arg == "-platform") {
584 if (++i < argc)
585 platformName = argv[i];
586 } else if (arg == "-plugin") {
587 if (++i < argc)
588 pluginList << argv[i];
589 } else {
590 argv[j++] = argv[i];
591 }
592 }
593
594 if (j < priv->argc) {
595 priv->argv[j] = 0;
596 priv->argc = j;
597 }
598
599 #if 0
600 QByteArray pluginEnv = qgetenv("QT_QPA_PLUGINS");
601 if (!pluginEnv.isEmpty()) {
602 pluginList.append(pluginEnv.split(';'));
603 }
604 #endif
605
606 init_platform(QLatin1String(platformName), platformPluginPath);
607 init_plugins(pluginList);
608
609 QColormap::initialize();
610 QFont::initialize();
611 #ifndef QT_NO_CURSOR
612 // QCursorData::initialize();
613 #endif
614
615 qApp->setObjectName(appName);
616
617 #ifndef QT_NO_QWS_INPUTMETHODS
618 qApp->setInputContext(new QDummyInputContext(qApp));
619 #endif
620 }
621
qt_cleanup()622 void qt_cleanup()
623 {
624 cleanup_platform();
625
626 QPixmapCache::clear();
627 #ifndef QT_NO_CURSOR
628 QCursorData::cleanup();
629 #endif
630 QFont::cleanup();
631 QColormap::cleanup();
632 delete QApplicationPrivate::inputContext;
633 QApplicationPrivate::inputContext = 0;
634
635 QApplicationPrivate::active_window = 0; //### this should not be necessary
636 }
637
638
639 #ifdef QT3_SUPPORT
setMainWidget(QWidget * mainWidget)640 void QApplication::setMainWidget(QWidget *mainWidget)
641 {
642 QApplicationPrivate::main_widget = mainWidget;
643 if (QApplicationPrivate::main_widget && windowIcon().isNull()
644 && QApplicationPrivate::main_widget->testAttribute(Qt::WA_SetWindowIcon))
645 setWindowIcon(QApplicationPrivate::main_widget->windowIcon());
646 }
647 #endif
648
processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent * e)649 void QApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent *e)
650 {
651 static QWeakPointer<QWidget> implicit_mouse_grabber;
652
653 QEvent::Type type;
654 // move first
655 Qt::MouseButtons stateChange = e->buttons ^ buttons;
656 if (e->globalPos != QPoint(qt_last_x, qt_last_y) && (stateChange != Qt::NoButton)) {
657 QWindowSystemInterfacePrivate::MouseEvent * newMouseEvent =
658 new QWindowSystemInterfacePrivate::MouseEvent(e->widget.data(), e->timestamp, e->localPos, e->globalPos, e->buttons);
659 QWindowSystemInterfacePrivate::windowSystemEventQueue.prepend(newMouseEvent); // just in case the move triggers a new event loop
660 stateChange = Qt::NoButton;
661 }
662
663 QWidget * tlw = e->widget.data();
664
665 QPoint localPoint = e->localPos;
666 QPoint globalPoint = e->globalPos;
667 QWidget *mouseWindow = tlw;
668
669 Qt::MouseButton button = Qt::NoButton;
670
671
672 if (qt_last_x != globalPoint.x() || qt_last_y != globalPoint.y()) {
673 type = QEvent::MouseMove;
674 qt_last_x = globalPoint.x();
675 qt_last_y = globalPoint.y();
676 if (qAbs(globalPoint.x() - mousePressX) > mouse_double_click_distance||
677 qAbs(globalPoint.y() - mousePressY) > mouse_double_click_distance)
678 mousePressButton = Qt::NoButton;
679 }
680 else { // check to see if a new button has been pressed/released
681 for (int check = Qt::LeftButton;
682 check <= Qt::XButton2;
683 check = check << 1) {
684 if (check & stateChange) {
685 button = Qt::MouseButton(check);
686 break;
687 }
688 }
689 if (button == Qt::NoButton) {
690 // Ignore mouse events that don't change the current state
691 return;
692 }
693 buttons = e->buttons;
694 if (button & e->buttons) {
695 if ((e->timestamp - mousePressTime) < static_cast<ulong>(QApplication::doubleClickInterval()) && button == mousePressButton) {
696 type = QEvent::MouseButtonDblClick;
697 mousePressButton = Qt::NoButton;
698 }
699 else {
700 type = QEvent::MouseButtonPress;
701 mousePressTime = e->timestamp;
702 mousePressButton = button;
703 mousePressX = qt_last_x;
704 mousePressY = qt_last_y;
705 }
706 }
707 else
708 type = QEvent::MouseButtonRelease;
709 }
710
711 if (self->inPopupMode()) {
712 //popup mouse handling is magical...
713 mouseWindow = qApp->activePopupWidget();
714
715 implicit_mouse_grabber.clear();
716 //### how should popup mode and implicit mouse grab interact?
717
718 } else if (tlw && app_do_modal && !qt_try_modal(tlw, QEvent::MouseButtonRelease) ) {
719 //even if we're blocked by modality, we should deliver the mouse release event..
720 //### this code is not completely correct: multiple buttons can be pressed simultaneously
721 if (!(implicit_mouse_grabber && buttons == Qt::NoButton)) {
722 //qDebug() << "modal blocked mouse event to" << tlw;
723 return;
724 }
725 }
726
727 // find the tlw if we didn't get it from the plugin
728 if (!mouseWindow) {
729 mouseWindow = QApplication::topLevelAt(globalPoint);
730 }
731
732 if (!mouseWindow && !implicit_mouse_grabber)
733 mouseWindow = QApplication::desktop();
734
735 if (mouseWindow && mouseWindow != tlw) {
736 //we did not get a sensible localPoint from the window system, so let's calculate it
737 localPoint = mouseWindow->mapFromGlobal(globalPoint);
738 }
739
740 // which child should have it?
741 QWidget *mouseWidget = mouseWindow;
742 if (mouseWindow) {
743 QWidget *w = mouseWindow->childAt(localPoint);
744 if (w) {
745 mouseWidget = w;
746 }
747 }
748
749 //handle implicit mouse grab
750 if (type == QEvent::MouseButtonPress && !implicit_mouse_grabber) {
751 implicit_mouse_grabber = mouseWidget;
752
753 Q_ASSERT(mouseWindow);
754 mouseWindow->activateWindow(); //focus
755 } else if (implicit_mouse_grabber) {
756 mouseWidget = implicit_mouse_grabber.data();
757 mouseWindow = mouseWidget->window();
758 if (mouseWindow != tlw)
759 localPoint = mouseWindow->mapFromGlobal(globalPoint);
760 }
761
762 Q_ASSERT(mouseWidget);
763
764 //localPoint is local to mouseWindow, but it needs to be local to mouseWidget
765 localPoint = mouseWidget->mapFrom(mouseWindow, localPoint);
766
767 if (buttons == Qt::NoButton) {
768 //qDebug() << "resetting mouse grabber";
769 implicit_mouse_grabber.clear();
770 }
771
772 if (mouseWidget != qt_last_mouse_receiver) {
773 dispatchEnterLeave(mouseWidget, qt_last_mouse_receiver);
774 qt_last_mouse_receiver = mouseWidget;
775 }
776
777 // Remember, we might enter a modal event loop when sending the event,
778 // so think carefully before adding code below this point.
779
780
781 QMouseEvent ev(type, localPoint, globalPoint, button, buttons, QApplication::keyboardModifiers());
782
783 QList<QWeakPointer<QPlatformCursor> > cursors = QPlatformCursorPrivate::getInstances();
784 foreach (QWeakPointer<QPlatformCursor> cursor, cursors) {
785 if (cursor)
786 cursor.data()->pointerEvent(ev);
787 }
788
789 // qDebug() << "sending mouse event" << ev.type() << localPoint << globalPoint << ev.button() << ev.buttons() << mouseWidget << "mouse grabber" << implicit_mouse_grabber;
790
791 int oldOpenPopupCount = openPopupCount;
792 QApplication::sendSpontaneousEvent(mouseWidget, &ev);
793
794 #ifndef QT_NO_CONTEXTMENU
795 if (type == QEvent::MouseButtonPress && button == Qt::RightButton && (openPopupCount == oldOpenPopupCount)) {
796 QContextMenuEvent e(QContextMenuEvent::Mouse, localPoint, globalPoint, QApplication::keyboardModifiers());
797 QApplication::sendSpontaneousEvent(mouseWidget, &e);
798 }
799 #endif // QT_NO_CONTEXTMENU
800 }
801
processPlatformPanelEvent(QWindowSystemInterfacePrivate::PlatformPanelEvent * e)802 void QApplicationPrivate::processPlatformPanelEvent(QWindowSystemInterfacePrivate::PlatformPanelEvent *e)
803 {
804 if (!e->widget)
805 return;
806
807 if (app_do_modal && !qt_try_modal(e->widget.data(), QEvent::PlatformPanel)) {
808 // a modal window is blocking this window, don't allow events through
809 return;
810 }
811
812 QEvent ev(QEvent::PlatformPanel);
813 QApplication::sendSpontaneousEvent(e->widget.data(), &ev);
814 }
815
816 //### there's a lot of duplicated logic here -- refactoring required!
817
processWheelEvent(QWindowSystemInterfacePrivate::WheelEvent * e)818 void QApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::WheelEvent *e)
819 {
820
821 if (!e->widget)
822 return;
823
824 // QPoint localPoint = ev.pos();
825 QPoint globalPoint = e->globalPos;
826 // bool trustLocalPoint = !!tlw; //is there something the local point can be local to?
827 QWidget *mouseWidget;
828
829 qt_last_x = globalPoint.x();
830 qt_last_y = globalPoint.y();
831
832 QWidget *mouseWindow = e->widget.data();
833
834 // find the tlw if we didn't get it from the plugin
835 if (!mouseWindow) {
836 mouseWindow = QApplication::topLevelAt(globalPoint);
837 }
838
839 if (!mouseWindow)
840 return;
841
842 mouseWidget = mouseWindow;
843
844 if (app_do_modal && !qt_try_modal(mouseWindow, QEvent::Wheel) ) {
845 qDebug() << "modal blocked wheel event" << mouseWindow;
846 return;
847 }
848 QPoint p = mouseWindow->mapFromGlobal(globalPoint);
849 QWidget *w = mouseWindow->childAt(p);
850 if (w) {
851 mouseWidget = w;
852 p = mouseWidget->mapFromGlobal(globalPoint);
853 }
854
855 QWheelEvent ev(p, globalPoint, e->delta, buttons, QApplication::keyboardModifiers(),
856 e->orient);
857 QApplication::sendSpontaneousEvent(mouseWidget, &ev);
858 }
859
860
861
862 // Remember, Qt convention is: keyboard state is state *before*
863
processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent * e)864 void QApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent *e)
865 {
866 QWidget *focusW = 0;
867 if (self->inPopupMode()) {
868 QWidget *popupW = qApp->activePopupWidget();
869 focusW = popupW->focusWidget() ? popupW->focusWidget() : popupW;
870 }
871 if (!focusW)
872 focusW = QApplication::focusWidget();
873 if (!focusW) {
874 focusW = e->widget.data();
875 }
876 if (!focusW)
877 focusW = QApplication::activeWindow();
878
879 //qDebug() << "handleKeyEvent" << hex << e->key() << e->modifiers() << e->text() << "widget" << focusW;
880
881 if (!focusW)
882 return;
883 if (app_do_modal && !qt_try_modal(focusW, e->keyType))
884 return;
885
886 if (e->nativeScanCode || e->nativeVirtualKey || e->nativeModifiers) {
887 QKeyEventEx ev(e->keyType, e->key, e->modifiers, e->unicode, e->repeat, e->repeatCount,
888 e->nativeScanCode, e->nativeVirtualKey, e->nativeModifiers);
889 QApplication::sendSpontaneousEvent(focusW, &ev);
890 } else {
891 QKeyEvent ev(e->keyType, e->key, e->modifiers, e->unicode, e->repeat, e->repeatCount);
892 QApplication::sendSpontaneousEvent(focusW, &ev);
893 }
894 }
895
processEnterEvent(QWindowSystemInterfacePrivate::EnterEvent * e)896 void QApplicationPrivate::processEnterEvent(QWindowSystemInterfacePrivate::EnterEvent *e)
897 {
898 if (!e->enter)
899 return;
900
901 QApplicationPrivate::dispatchEnterLeave(e->enter.data(),0);
902 qt_last_mouse_receiver = e->enter.data();
903 }
904
processLeaveEvent(QWindowSystemInterfacePrivate::LeaveEvent * e)905 void QApplicationPrivate::processLeaveEvent(QWindowSystemInterfacePrivate::LeaveEvent *e)
906 {
907 if (!e->leave)
908 return;
909
910 QApplicationPrivate::dispatchEnterLeave(0,qt_last_mouse_receiver);
911
912 if (e->leave.data() && !e->leave.data()->isAncestorOf(qt_last_mouse_receiver)) //(???) this should not happen
913 QApplicationPrivate::dispatchEnterLeave(0, e->leave.data());
914 qt_last_mouse_receiver = 0;
915
916 }
917
processActivatedEvent(QWindowSystemInterfacePrivate::ActivatedWindowEvent * e)918 void QApplicationPrivate::processActivatedEvent(QWindowSystemInterfacePrivate::ActivatedWindowEvent *e)
919 {
920 QApplication::setActiveWindow(e->activated.data());
921 }
922
processGeometryChangeEvent(QWindowSystemInterfacePrivate::GeometryChangeEvent * e)923 void QApplicationPrivate::processGeometryChangeEvent(QWindowSystemInterfacePrivate::GeometryChangeEvent *e)
924 {
925 if (e->tlw.isNull())
926 return;
927 QWidget *tlw = e->tlw.data();
928 if (!tlw->isWindow())
929 return; //geo of native child widgets is controlled by lighthouse
930 //so we already have sent the events; besides this new rect
931 //is not mapped to parent
932
933 QRect newRect = e->newGeometry;
934 QRect cr(tlw->geometry());
935 bool isResize = cr.size() != newRect.size();
936 bool isMove = cr.topLeft() != newRect.topLeft();
937 tlw->data->crect = newRect;
938 if (isResize) {
939 QResizeEvent e(tlw->data->crect.size(), cr.size());
940 QApplication::sendSpontaneousEvent(tlw, &e);
941 tlw->update();
942 }
943
944 if (isMove) {
945 //### frame geometry
946 QMoveEvent e(tlw->data->crect.topLeft(), cr.topLeft());
947 QApplication::sendSpontaneousEvent(tlw, &e);
948 }
949 }
950
processCloseEvent(QWindowSystemInterfacePrivate::CloseEvent * e)951 void QApplicationPrivate::processCloseEvent(QWindowSystemInterfacePrivate::CloseEvent *e)
952 {
953 if (e->topLevel.isNull()) {
954 //qDebug() << "QApplicationPrivate::processCloseEvent NULL";
955 return;
956 }
957 e->topLevel.data()->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent);
958 }
959
processTouchEvent(QWindowSystemInterfacePrivate::TouchEvent * e)960 void QApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::TouchEvent *e)
961 {
962 translateRawTouchEvent(e->widget.data(), e->devType, e->points);
963 }
964
reportScreenCount(QWindowSystemInterfacePrivate::ScreenCountEvent * e)965 void QApplicationPrivate::reportScreenCount(QWindowSystemInterfacePrivate::ScreenCountEvent *e)
966 {
967 // This operation only makes sense after the QApplication constructor runs
968 if (QCoreApplication::startingUp())
969 return;
970
971 QApplication::desktop()->d_func()->updateScreenList();
972 // signal anything listening for creation or deletion of screens
973 QDesktopWidget *desktop = QApplication::desktop();
974 emit desktop->screenCountChanged(e->count);
975 }
976
reportGeometryChange(QWindowSystemInterfacePrivate::ScreenGeometryEvent * e)977 void QApplicationPrivate::reportGeometryChange(QWindowSystemInterfacePrivate::ScreenGeometryEvent *e)
978 {
979 // This operation only makes sense after the QApplication constructor runs
980 if (QCoreApplication::startingUp())
981 return;
982
983 QApplication::desktop()->d_func()->updateScreenList();
984
985 // signal anything listening for screen geometry changes
986 QDesktopWidget *desktop = QApplication::desktop();
987 emit desktop->resized(e->index);
988
989 // make sure maximized and fullscreen windows are updated
990 QWidgetList list = QApplication::topLevelWidgets();
991 for (int i = list.size() - 1; i >= 0; --i) {
992 QWidget *w = list.at(i);
993 if (w->isFullScreen())
994 w->d_func()->setFullScreenSize_helper();
995 else if (w->isMaximized())
996 w->d_func()->setMaxWindowState_helper();
997 }
998 }
999
reportAvailableGeometryChange(QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent * e)1000 void QApplicationPrivate::reportAvailableGeometryChange(
1001 QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e)
1002 {
1003 // This operation only makes sense after the QApplication constructor runs
1004 if (QCoreApplication::startingUp())
1005 return;
1006
1007 QApplication::desktop()->d_func()->updateScreenList();
1008
1009 // signal anything listening for screen geometry changes
1010 QDesktopWidget *desktop = QApplication::desktop();
1011 emit desktop->workAreaResized(e->index);
1012
1013 // make sure maximized and fullscreen windows are updated
1014 QWidgetList list = QApplication::topLevelWidgets();
1015 for (int i = list.size() - 1; i >= 0; --i) {
1016 QWidget *w = list.at(i);
1017 if (w->isFullScreen())
1018 w->d_func()->setFullScreenSize_helper();
1019 else if (w->isMaximized())
1020 w->d_func()->setMaxWindowState_helper();
1021 }
1022 }
1023
reportLocaleChange()1024 void QApplicationPrivate::reportLocaleChange()
1025 {
1026 QApplication::sendSpontaneousEvent( qApp, new QEvent( QEvent::LocaleChange ) );
1027 }
1028
1029 QT_END_NAMESPACE
1030