Revert "Move QWindowSystemInterface out of qpa."
[profile/ivi/qtbase.git] / src / widgets / kernel / qapplication_qpa.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qapplication_p.h"
43 #include "qcolormap.h"
44 #include "qpalette.h"
45 #include "qpixmapcache.h"
46 #ifndef QT_NO_CURSOR
47 #include "private/qcursor_p.h"
48 #endif
49 #include "qscreen.h"
50
51 #include "private/qwidget_p.h"
52 #include "private/qevent_p.h"
53
54 #include <qpa/qplatformintegrationfactory_p.h>
55 #include <qdesktopwidget.h>
56 #include <qpa/qplatformcursor.h>
57 #include <qpa/qplatformtheme.h>
58
59 #include <qdebug.h>
60 #include <qpa/qwindowsysteminterface.h>
61 #include <qpa/qwindowsysteminterface_p.h>
62 #include <qpa/qplatformintegration.h>
63
64 #include "qdesktopwidget_qpa_p.h"
65 #include "qwidgetwindow_qpa_p.h"
66 #include "qtooltip.h"
67
68 #ifdef Q_OS_WIN
69 #  include <QtCore/qt_windows.h> // for qt_win_display_dc()
70 #endif
71
72 QT_BEGIN_NAMESPACE
73
74 static QString appFont;
75 static bool popupGrabOk = false;
76 static QPointer<QWidget> autoGrabber;
77 extern QWidget *qt_button_down;
78 extern QWidget *qt_popup_down;
79 extern bool qt_replay_popup_mouse_event;
80 int openPopupCount = 0;
81
82 void QApplicationPrivate::createEventDispatcher()
83 {
84     QGuiApplicationPrivate::createEventDispatcher();
85 }
86
87 bool qt_try_modal(QWidget *widget, QEvent::Type type)
88 {
89     QWidget * top = 0;
90
91     if (QApplicationPrivate::tryModalHelper(widget, &top))
92         return true;
93
94     bool block_event  = false;
95     bool paint_event = false;
96
97     switch (type) {
98 #if 0
99     case QEvent::Focus:
100         if (!static_cast<QWSFocusEvent*>(event)->simpleData.get_focus)
101             break;
102         // drop through
103 #endif
104     case QEvent::MouseButtonPress:                        // disallow mouse/key events
105     case QEvent::MouseButtonRelease:
106     case QEvent::MouseMove:
107     case QEvent::KeyPress:
108     case QEvent::KeyRelease:
109         block_event         = true;
110         break;
111     default:
112         break;
113     }
114
115     if ((block_event || paint_event) && top->parentWidget() == 0)
116         top->raise();
117
118     return !block_event;
119 }
120
121 bool QApplicationPrivate::modalState()
122 {
123     return !self->modalWindowList.isEmpty();
124 }
125
126 QWidget *qt_tlw_for_window(QWindow *wnd)
127 {
128     if (wnd)
129         foreach (QWidget *tlw, qApp->topLevelWidgets())
130             if (tlw->windowHandle() == wnd)
131                 return tlw;
132     return 0;
133 }
134
135 void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous)
136 {
137     Q_UNUSED(previous);
138     QWindow *wnd = QGuiApplicationPrivate::focus_window;
139     if (inPopupMode()) // some delayed focus event to ignore
140         return;
141     QWidget *tlw = qt_tlw_for_window(wnd);
142     QApplication::setActiveWindow(tlw);
143 }
144
145 void QApplicationPrivate::handleAutomaticMouseGrab(QWidget *widget, QMouseEvent *e)
146 {
147     // Grab the mouse automatically for current window when any button is pressed,
148     // unless there is an active mousegrabber or mouse is being grabbed for a popup.
149     if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease) {
150         if (e->buttons() == Qt::NoButton) {
151             // No buttons remain pressed, so release the grab unless grab has been acquired
152             // for some other reason in the meantime.
153             if (autoGrabber && !QWidget::mouseGrabber() && !popupGrabOk)
154                 qt_widget_private(autoGrabber)->stealMouseGrab(false);
155             autoGrabber = 0;
156         } else {
157             // Some buttons are pressed, grab mouse input for current window,
158             // unless there is already an active grab.
159             if (!autoGrabber && !QWidget::mouseGrabber() && !popupGrabOk) {
160                 autoGrabber = widget->window();
161                 qt_widget_private(autoGrabber)->stealMouseGrab(true);
162             }
163         }
164     }
165 }
166
167 static void ungrabKeyboardForPopup(QWidget *popup)
168 {
169     if (QWidget::keyboardGrabber())
170         qt_widget_private(QWidget::keyboardGrabber())->stealKeyboardGrab(true);
171     else
172         qt_widget_private(popup)->stealKeyboardGrab(false);
173 }
174
175 static void ungrabMouseForPopup(QWidget *popup)
176 {
177     if (QWidget::mouseGrabber())
178         qt_widget_private(QWidget::mouseGrabber())->stealMouseGrab(true);
179     else
180         qt_widget_private(popup)->stealMouseGrab(false);
181 }
182
183 static void grabForPopup(QWidget *popup)
184 {
185     Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
186     popupGrabOk = qt_widget_private(popup)->stealKeyboardGrab(true);
187     if (popupGrabOk) {
188         if (autoGrabber)
189             qt_widget_private(autoGrabber)->stealMouseGrab(false);
190         autoGrabber = 0;
191         popupGrabOk = qt_widget_private(popup)->stealMouseGrab(true);
192         if (!popupGrabOk) {
193             // transfer grab back to the keyboard grabber if any
194             ungrabKeyboardForPopup(popup);
195         }
196     }
197 }
198
199 void QApplicationPrivate::closePopup(QWidget *popup)
200 {
201     if (!popupWidgets)
202         return;
203     popupWidgets->removeAll(popup);
204
205      if (popup == qt_popup_down) {
206          qt_button_down = 0;
207          qt_popup_down = 0;
208      }
209
210     if (QApplicationPrivate::popupWidgets->count() == 0) { // this was the last popup
211         delete QApplicationPrivate::popupWidgets;
212         QApplicationPrivate::popupWidgets = 0;
213
214         if (popupGrabOk) {
215             popupGrabOk = false;
216
217             if (popup->geometry().contains(QPoint(QGuiApplicationPrivate::mousePressX,
218                                                   QGuiApplicationPrivate::mousePressY))
219                 || popup->testAttribute(Qt::WA_NoMouseReplay)) {
220                 // mouse release event or inside
221                 qt_replay_popup_mouse_event = false;
222             } else { // mouse press event
223                 QGuiApplicationPrivate::mousePressTime -= 10000; // avoid double click
224                 qt_replay_popup_mouse_event = true;
225             }
226
227             // transfer grab back to mouse grabber if any, otherwise release the grab
228             ungrabMouseForPopup(popup);
229
230             // transfer grab back to keyboard grabber if any, otherwise release the grab
231             ungrabKeyboardForPopup(popup);
232         }
233
234         if (active_window) {
235             if (QWidget *fw = active_window->focusWidget()) {
236                 if (fw != QApplication::focusWidget()) {
237                     fw->setFocus(Qt::PopupFocusReason);
238                 } else {
239                     QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
240                     QCoreApplication::sendEvent(fw, &e);
241                 }
242             }
243         }
244
245     } else {
246         // A popup was closed, so the previous popup gets the focus.
247         QWidget* aw = QApplicationPrivate::popupWidgets->last();
248         if (QWidget *fw = aw->focusWidget())
249             fw->setFocus(Qt::PopupFocusReason);
250
251         if (QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard
252             grabForPopup(aw);
253     }
254
255 }
256
257 void QApplicationPrivate::openPopup(QWidget *popup)
258 {
259     openPopupCount++;
260     if (!popupWidgets) // create list
261         popupWidgets = new QWidgetList;
262     popupWidgets->append(popup); // add to end of list
263
264     if (QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard
265         grabForPopup(popup);
266
267     // popups are not focus-handled by the window system (the first
268     // popup grabbed the keyboard), so we have to do that manually: A
269     // new popup gets the focus
270     if (popup->focusWidget()) {
271         popup->focusWidget()->setFocus(Qt::PopupFocusReason);
272     } else if (popupWidgets->count() == 1) { // this was the first popup
273         if (QWidget *fw = QApplication::focusWidget()) {
274             QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
275             QApplication::sendEvent(fw, &e);
276         }
277     }
278 }
279
280 void QApplicationPrivate::initializeMultitouch_sys()
281 {
282 }
283
284 void QApplicationPrivate::cleanupMultitouch_sys()
285 {
286 }
287
288 static void setPossiblePalette(const QPalette *palette, const char *className)
289 {
290     if (palette == 0)
291         return;
292     QApplicationPrivate::setPalette_helper(*palette, className, false);
293 }
294
295
296 void QApplicationPrivate::initializeWidgetPaletteHash()
297 {
298     QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme();
299     if (!platformTheme)
300         return;
301     setPossiblePalette(platformTheme->palette(QPlatformTheme::ToolButtonPalette), "QToolButton");
302     setPossiblePalette(platformTheme->palette(QPlatformTheme::ButtonPalette), "QAbstractButton");
303     setPossiblePalette(platformTheme->palette(QPlatformTheme::HeaderPalette), "QHeaderView");
304     setPossiblePalette(platformTheme->palette(QPlatformTheme::ItemViewPalette), "QAbstractItemView");
305     setPossiblePalette(platformTheme->palette(QPlatformTheme::MessageBoxLabelPelette), "QMessageBoxLabel");
306     setPossiblePalette(platformTheme->palette(QPlatformTheme::TabBarPalette), "QTabBar");
307     setPossiblePalette(platformTheme->palette(QPlatformTheme::LabelPalette), "QLabel");
308     setPossiblePalette(platformTheme->palette(QPlatformTheme::GroupBoxPalette), "QGroupBox");
309     setPossiblePalette(platformTheme->palette(QPlatformTheme::MenuPalette), "QMenu");
310     setPossiblePalette(platformTheme->palette(QPlatformTheme::MenuBarPalette), "QMenuBar");
311     setPossiblePalette(platformTheme->palette(QPlatformTheme::TextEditPalette), "QTextEdit");
312     setPossiblePalette(platformTheme->palette(QPlatformTheme::TextEditPalette), "QTextControl");
313     setPossiblePalette(platformTheme->palette(QPlatformTheme::TextLineEditPalette), "QLineEdit");
314 }
315
316 void QApplicationPrivate::initializeWidgetFontHash()
317 {
318     const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
319     if (!theme)
320         return;
321     FontHash *fontHash = qt_app_fonts_hash();
322     if (const QFont *font = theme->font(QPlatformTheme::MenuFont))
323         fontHash->insert(QByteArrayLiteral("QMenu"), *font);
324     if (const QFont *font = theme->font(QPlatformTheme::MenuBarFont))
325         fontHash->insert(QByteArrayLiteral("QMenuBar"), *font);
326     if (const QFont *font = theme->font(QPlatformTheme::MenuItemFont))
327         fontHash->insert(QByteArrayLiteral("QMenuItem"), *font);
328     if (const QFont *font = theme->font(QPlatformTheme::MessageBoxFont))
329         fontHash->insert(QByteArrayLiteral("QMessageBox"), *font);
330     if (const QFont *font = theme->font(QPlatformTheme::LabelFont))
331         fontHash->insert(QByteArrayLiteral("QLabel"), *font);
332     if (const QFont *font = theme->font(QPlatformTheme::TipLabelFont))
333         fontHash->insert(QByteArrayLiteral("QTipLabel"), *font);
334     if (const QFont *font = theme->font(QPlatformTheme::TitleBarFont))
335         fontHash->insert(QByteArrayLiteral("QTitleBar"), *font);
336     if (const QFont *font = theme->font(QPlatformTheme::StatusBarFont))
337         fontHash->insert(QByteArrayLiteral("QStatusBar"), *font);
338     if (const QFont *font = theme->font(QPlatformTheme::MdiSubWindowTitleFont))
339         fontHash->insert(QByteArrayLiteral("QMdiSubWindowTitleBar"), *font);
340     if (const QFont *font = theme->font(QPlatformTheme::DockWidgetTitleFont))
341         fontHash->insert(QByteArrayLiteral("QDockWidgetTitle"), *font);
342     if (const QFont *font = theme->font(QPlatformTheme::PushButtonFont))
343         fontHash->insert(QByteArrayLiteral("QPushButton"), *font);
344     if (const QFont *font = theme->font(QPlatformTheme::ToolButtonFont))
345         fontHash->insert(QByteArrayLiteral("QToolButton"), *font);
346     if (const QFont *font = theme->font(QPlatformTheme::ItemViewFont))
347         fontHash->insert(QByteArrayLiteral("QAbstractItemView"), *font);
348     if (const QFont *font = theme->font(QPlatformTheme::ListViewFont))
349         fontHash->insert(QByteArrayLiteral("QListViewFont"), *font);
350     if (const QFont *font = theme->font(QPlatformTheme::HeaderViewFont))
351         fontHash->insert(QByteArrayLiteral("QHeaderViewFont"), *font);
352     if (const QFont *font = theme->font(QPlatformTheme::ListBoxFont))
353         fontHash->insert(QByteArrayLiteral("QListBox"), *font);
354     if (const QFont *font = theme->font(QPlatformTheme::ComboMenuItemFont))
355         fontHash->insert(QByteArrayLiteral("QComboMenuItemFont"), *font);
356     if (const QFont *font = theme->font(QPlatformTheme::ComboLineEditFont))
357         fontHash->insert(QByteArrayLiteral("QComboLineEditFont"), *font);
358     if (const QFont *font = theme->font(QPlatformTheme::SmallFont))
359         fontHash->insert(QByteArrayLiteral("QSmallFont"), *font);
360     if (const QFont *font = theme->font(QPlatformTheme::MiniFont))
361         fontHash->insert(QByteArrayLiteral("QMiniFont"), *font);
362 }
363
364 #ifndef QT_NO_WHEELEVENT
365 void QApplication::setWheelScrollLines(int lines)
366 {
367     QApplicationPrivate::wheel_scroll_lines = lines;
368 }
369
370 int QApplication::wheelScrollLines()
371 {
372     return QApplicationPrivate::wheel_scroll_lines;
373 }
374 #endif
375
376 static inline int uiEffectToFlag(Qt::UIEffect effect)
377 {
378     switch (effect) {
379     case Qt::UI_General:
380         return QPlatformTheme::GeneralUiEffect;
381     case Qt::UI_AnimateMenu:
382         return QPlatformTheme::AnimateMenuUiEffect;
383     case Qt::UI_FadeMenu:
384         return QPlatformTheme::FadeMenuUiEffect;
385     case Qt::UI_AnimateCombo:
386         return QPlatformTheme::AnimateComboUiEffect;
387     case Qt::UI_AnimateTooltip:
388         return QPlatformTheme::AnimateTooltipUiEffect;
389     case Qt::UI_FadeTooltip:
390         return QPlatformTheme::FadeTooltipUiEffect;
391     case Qt::UI_AnimateToolBox:
392         return QPlatformTheme::AnimateToolBoxUiEffect;
393     }
394     return 0;
395 }
396
397 void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
398 {
399     int effectFlags = uiEffectToFlag(effect);
400     if (enable) {
401         if (effectFlags & QPlatformTheme::FadeMenuUiEffect)
402             effectFlags |= QPlatformTheme::AnimateMenuUiEffect;
403         if (effectFlags & QPlatformTheme::FadeTooltipUiEffect)
404             effectFlags |= QPlatformTheme::AnimateTooltipUiEffect;
405         QApplicationPrivate::enabledAnimations |= effectFlags;
406     } else {
407         QApplicationPrivate::enabledAnimations &= ~effectFlags;
408     }
409 }
410
411 bool QApplication::isEffectEnabled(Qt::UIEffect effect)
412 {
413     return QColormap::instance().depth() >= 16
414            && (QApplicationPrivate::enabledAnimations & QPlatformTheme::GeneralUiEffect)
415            && (QApplicationPrivate::enabledAnimations & uiEffectToFlag(effect));
416         return false;
417 }
418
419 QWidget *QApplication::topLevelAt(const QPoint &pos)
420 {
421     QList<QScreen *> screens = QGuiApplication::screens();
422     QList<QScreen *>::const_iterator screen = screens.constBegin();
423     QList<QScreen *>::const_iterator end = screens.constEnd();
424
425     while (screen != end) {
426         if ((*screen)->geometry().contains(pos)) {
427             QWidgetWindow *w = qobject_cast<QWidgetWindow *>((*screen)->handle()->topLevelAt(pos));
428             return w ? w->widget() : 0;
429         }
430         ++screen;
431     }
432     return 0;
433 }
434
435 void QApplication::beep()
436 {
437 }
438
439 void QApplication::alert(QWidget *, int)
440 {
441 }
442
443 void qt_init(QApplicationPrivate *priv, int type)
444 {
445     Q_UNUSED(priv);
446     Q_UNUSED(type);
447
448     QColormap::initialize();
449
450     if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette))
451         QToolTip::setPalette(*toolTipPalette);
452     QApplicationPrivate::initializeWidgetFontHash();
453 }
454
455 #ifdef Q_OS_WIN
456 // #fixme: Remove.
457 static HDC         displayDC        = 0;                // display device context
458
459 Q_WIDGETS_EXPORT HDC qt_win_display_dc()                        // get display DC
460 {
461     Q_ASSERT(qApp && qApp->thread() == QThread::currentThread());
462     if (!displayDC)
463         displayDC = GetDC(0);
464     return displayDC;
465 }
466 #endif
467
468 void qt_cleanup()
469 {
470     QPixmapCache::clear();
471     QColormap::cleanup();
472
473     QApplicationPrivate::active_window = 0; //### this should not be necessary
474 #ifdef Q_OS_WIN
475     if (displayDC) {
476         ReleaseDC(0, displayDC);
477         displayDC = 0;
478     }
479 #endif
480 }
481
482
483 QT_END_NAMESPACE