bool QXcbGlxIntegration::handleXcbEvent(xcb_generic_event_t *event, uint responseType) { bool handled = false; // Check if a custom XEvent constructor was registered in xlib for this event type, and call it discarding the constructed XEvent if any. // XESetWireToEvent might be used by libraries to intercept messages from the X server e.g. the OpenGL lib waiting for DRI2 events. Display *xdisplay = static_cast<Display *>(m_connection->xlib_display()); XLockDisplay(xdisplay); bool locked = true; Bool (*proc)(Display*, XEvent*, xEvent*) = XESetWireToEvent(xdisplay, responseType, 0); if (proc) { XESetWireToEvent(xdisplay, responseType, proc); XEvent dummy; event->sequence = LastKnownRequestProcessed(xdisplay); if (proc(xdisplay, &dummy, (xEvent*)event)) { #ifdef XCB_HAS_XCB_GLX // DRI2 clients don't receive GLXBufferSwapComplete events on the wire. // Instead the GLX event is synthesized from the DRI2BufferSwapComplete event // by DRI2WireToEvent(). For an application to be able to see the event // we have to convert it to an xcb_glx_buffer_swap_complete_event_t and // pass it to the native event filter. const uint swap_complete = m_glx_first_event + XCB_GLX_BUFFER_SWAP_COMPLETE; QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance(); if (dispatcher && uint(dummy.type) == swap_complete && responseType != swap_complete) { QGLXBufferSwapComplete *xev = reinterpret_cast<QGLXBufferSwapComplete *>(&dummy); xcb_glx_buffer_swap_complete_event_t ev; memset(&ev, 0, sizeof(xcb_glx_buffer_swap_complete_event_t)); ev.response_type = xev->type; ev.sequence = xev->serial; ev.event_type = xev->event_type; ev.drawable = xev->drawable; ev.ust_hi = xev->ust >> 32; ev.ust_lo = xev->ust & 0xffffffff; ev.msc_hi = xev->msc >> 32; ev.msc_lo = xev->msc & 0xffffffff; ev.sbc = xev->sbc & 0xffffffff; // Unlock the display before calling the native event filter XUnlockDisplay(xdisplay); locked = false; QByteArray genericEventFilterType = m_connection->nativeInterface()->genericEventFilterType(); long result = 0; handled = dispatcher->filterNativeEvent(genericEventFilterType, &ev, &result); } #endif } }
bool QWindowsContext::windowsProc(HWND hwnd, UINT message, QtWindows::WindowsEventType et, WPARAM wParam, LPARAM lParam, LRESULT *result) { *result = 0; MSG msg; msg.hwnd = hwnd; // re-create MSG structure msg.message = message; // time and pt fields ignored msg.wParam = wParam; msg.lParam = lParam; msg.pt.x = msg.pt.y = 0; if (et != QtWindows::CursorEvent && (et & (QtWindows::MouseEventFlag | QtWindows::NonClientEventFlag))) { msg.pt.x = GET_X_LPARAM(lParam); msg.pt.y = GET_Y_LPARAM(lParam); // For non-client-area messages, these are screen coordinates (as expected // in the MSG structure), otherwise they are client coordinates. if (!(et & QtWindows::NonClientEventFlag)) { ClientToScreen(msg.hwnd, &msg.pt); } } else { #ifndef Q_OS_WINCE GetCursorPos(&msg.pt); #endif } // Run the native event filters. long filterResult = 0; QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance(); if (dispatcher && dispatcher->filterNativeEvent(d->m_eventType, &msg, &filterResult)) { *result = LRESULT(filterResult); return true; } QWindowsWindow *platformWindow = findPlatformWindow(hwnd); if (platformWindow) { filterResult = 0; if (QWindowSystemInterface::handleNativeEvent(platformWindow->window(), d->m_eventType, &msg, &filterResult)) { *result = LRESULT(filterResult); return true; } } switch (et) { case QtWindows::InputMethodStartCompositionEvent: return QWindowsInputContext::instance()->startComposition(hwnd); case QtWindows::InputMethodCompositionEvent: return QWindowsInputContext::instance()->composition(hwnd, lParam); case QtWindows::InputMethodEndCompositionEvent: return QWindowsInputContext::instance()->endComposition(hwnd); case QtWindows::InputMethodRequest: return QWindowsInputContext::instance()->handleIME_Request(wParam, lParam, result); case QtWindows::InputMethodOpenCandidateWindowEvent: case QtWindows::InputMethodCloseCandidateWindowEvent: // TODO: Release/regrab mouse if a popup has mouse grab. return false; case QtWindows::DestroyEvent: if (platformWindow && !platformWindow->testFlag(QWindowsWindow::WithinDestroy)) { qWarning() << "External WM_DESTROY received for " << platformWindow->window() << ", parent: " << platformWindow->window()->parent() << ", transient parent: " << platformWindow->window()->transientParent(); } return false; case QtWindows::ClipboardEvent: return false; case QtWindows::UnknownEvent: return false; case QtWindows::AccessibleObjectFromWindowRequest: #ifndef QT_NO_ACCESSIBILITY return QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(hwnd, wParam, lParam, result); #else return false; #endif case QtWindows::DisplayChangedEvent: return d->m_screenManager.handleDisplayChange(wParam, lParam); case QtWindows::SettingChangedEvent: return d->m_screenManager.handleScreenChanges(); default: break; } // Before CreateWindowEx() returns, some events are sent, // for example WM_GETMINMAXINFO asking for size constraints for top levels. // Pass on to current creation context if (!platformWindow && !d->m_creationContext.isNull()) { switch (et) { #ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO case QtWindows::QuerySizeHints: d->m_creationContext->applyToMinMaxInfo(reinterpret_cast<MINMAXINFO *>(lParam)); return true; #endif case QtWindows::ResizeEvent: d->m_creationContext->obtainedGeometry.setSize(QSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); return true; case QtWindows::MoveEvent: d->m_creationContext->obtainedGeometry.moveTo(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); return true; case QtWindows::CalculateSize: return QWindowsGeometryHint::handleCalculateSize(d->m_creationContext->customMargins, msg, result); case QtWindows::GeometryChangingEvent: return QWindowsWindow::handleGeometryChangingMessage(&msg, d->m_creationContext->window, d->m_creationContext->margins + d->m_creationContext->customMargins); default: break; } } if (platformWindow) { // Suppress events sent during DestroyWindow() for native children. if (platformWindow->testFlag(QWindowsWindow::WithinDestroy)) return false; if (QWindowsContext::verbose > 1) qCDebug(lcQpaEvents) << "Event window: " << platformWindow->window(); } else { qWarning("%s: No Qt Window found for event 0x%x (%s), hwnd=0x%p.", __FUNCTION__, message, QWindowsGuiEventDispatcher::windowsMessageName(message), hwnd); return false; } switch (et) { case QtWindows::KeyDownEvent: case QtWindows::KeyEvent: case QtWindows::InputMethodKeyEvent: case QtWindows::InputMethodKeyDownEvent: case QtWindows::KeyboardLayoutChangeEvent: case QtWindows::AppCommandEvent: #if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) return platformSessionManager()->isInteractionBlocked() ? true : d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result); #else return d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result); #endif case QtWindows::MoveEvent: platformWindow->handleMoved(); return true; case QtWindows::ResizeEvent: platformWindow->handleResized((int)wParam); return true; #ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO case QtWindows::QuerySizeHints: platformWindow->getSizeHints(reinterpret_cast<MINMAXINFO *>(lParam)); return true;// maybe available on some SDKs revisit WM_NCCALCSIZE case QtWindows::CalculateSize: return QWindowsGeometryHint::handleCalculateSize(platformWindow->customMargins(), msg, result); case QtWindows::NonClientHitTest: return platformWindow->handleNonClientHitTest(QPoint(msg.pt.x, msg.pt.y), result); case QtWindows::GeometryChangingEvent: return platformWindow->QWindowsWindow::handleGeometryChanging(&msg); #endif // !Q_OS_WINCE case QtWindows::ExposeEvent: return platformWindow->handleWmPaint(hwnd, message, wParam, lParam); case QtWindows::NonClientMouseEvent: if (platformWindow->frameStrutEventsEnabled()) #if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); #else return d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); #endif break; /* the mouse tracking on windows already handles the reset of the cursor * and does not like somebody else handling it. * on WINCE its necessary to handle this event to get the correct cursor */ #ifdef Q_OS_WINCE case QtWindows::CursorEvent: { QWindowsWindow::baseWindowOf(platformWindow->window())->applyCursor(); return true; } #endif case QtWindows::MouseWheelEvent: case QtWindows::MouseEvent: case QtWindows::LeaveEvent: #if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); #else return d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); #endif case QtWindows::TouchEvent: #if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result); #else return d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result); #endif case QtWindows::FocusInEvent: // see QWindowsWindow::requestActivateWindow(). case QtWindows::FocusOutEvent: handleFocusEvent(et, platformWindow); return true; case QtWindows::ShowEventOnParentRestoring: // QTBUG-40696, prevent Windows from re-showing hidden transient children (dialogs). if (!platformWindow->window()->isVisible()) { *result = 0; return true; } break; case QtWindows::HideEvent: platformWindow->handleHidden(); return false;// Indicate transient children should be hidden by windows (SW_PARENTCLOSING) case QtWindows::CloseEvent: QWindowSystemInterface::handleCloseEvent(platformWindow->window()); return true; case QtWindows::ThemeChanged: { // Switch from Aero to Classic changes margins. const Qt::WindowFlags flags = platformWindow->window()->flags(); if ((flags & Qt::WindowType_Mask) != Qt::Desktop && !(flags & Qt::FramelessWindowHint)) platformWindow->setFlag(QWindowsWindow::FrameDirty); if (QWindowsTheme *theme = QWindowsTheme::instance()) theme->windowsThemeChanged(platformWindow->window()); return true; } case QtWindows::CompositionSettingsChanged: platformWindow->handleCompositionSettingsChanged(); return true; #ifndef Q_OS_WINCE case QtWindows::ActivateWindowEvent: if (platformWindow->window()->flags() & Qt::WindowDoesNotAcceptFocus) { *result = LRESULT(MA_NOACTIVATE); return true; } #ifndef QT_NO_TABLETEVENT if (!d->m_tabletSupport.isNull()) d->m_tabletSupport->notifyActivate(); #endif // !QT_NO_TABLETEVENT if (platformWindow->testFlag(QWindowsWindow::BlockedByModal)) if (const QWindow *modalWindow = QGuiApplication::modalWindow()) QWindowsWindow::baseWindowOf(modalWindow)->alertWindow(); break; case QtWindows::MouseActivateWindowEvent: if (platformWindow->window()->flags() & Qt::WindowDoesNotAcceptFocus) { *result = LRESULT(MA_NOACTIVATE); return true; } break; #endif #ifndef QT_NO_CONTEXTMENU case QtWindows::ContextMenu: return handleContextMenuEvent(platformWindow->window(), msg); #endif case QtWindows::WhatsThisEvent: { #ifndef QT_NO_WHATSTHIS QWindowSystemInterface::handleEnterWhatsThisEvent(); return true; #endif } break; #if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) case QtWindows::QueryEndSessionApplicationEvent: { QWindowsSessionManager *sessionManager = platformSessionManager(); if (sessionManager->isActive()) { // bogus message from windows *result = sessionManager->wasCanceled() ? 0 : 1; return true; } sessionManager->setActive(true); sessionManager->blocksInteraction(); sessionManager->clearCancellation(); QGuiApplicationPrivate *qGuiAppPriv = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp)); qGuiAppPriv->commitData(); if (lParam & ENDSESSION_LOGOFF) fflush(NULL); *result = sessionManager->wasCanceled() ? 0 : 1; return true; } case QtWindows::EndSessionApplicationEvent: { QWindowsSessionManager *sessionManager = platformSessionManager(); sessionManager->setActive(false); sessionManager->allowsInteraction(); bool endsession = (bool) wParam; // we receive the message for each toplevel window included internal hidden ones, // but the aboutToQuit signal should be emitted only once. QGuiApplicationPrivate *qGuiAppPriv = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp)); if (endsession && !qGuiAppPriv->aboutToQuitEmitted) { qGuiAppPriv->aboutToQuitEmitted = true; int index = QGuiApplication::staticMetaObject.indexOfSignal("aboutToQuit()"); qApp->qt_metacall(QMetaObject::InvokeMetaMethod, index,0); // since the process will be killed immediately quit() has no real effect QGuiApplication::quit(); } return true; } #endif // !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) default: break; } return false; }
bool QWindowsContext::windowsProc(HWND hwnd, UINT message, QtWindows::WindowsEventType et, WPARAM wParam, LPARAM lParam, LRESULT *result) { *result = 0; MSG msg; msg.hwnd = hwnd; // re-create MSG structure msg.message = message; // time and pt fields ignored msg.wParam = wParam; msg.lParam = lParam; msg.pt.x = GET_X_LPARAM(lParam); msg.pt.y = GET_Y_LPARAM(lParam); // Run the native event filters. long filterResult = 0; QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance(); if (dispatcher && dispatcher->filterNativeEvent(d->m_eventType, &msg, &filterResult)) { *result = LRESULT(filterResult); return true; } QWindowsWindow *platformWindow = findPlatformWindow(hwnd); if (platformWindow) { filterResult = 0; if (QWindowSystemInterface::handleNativeEvent(platformWindow->window(), d->m_eventType, &msg, &filterResult)) { *result = LRESULT(filterResult); return true; } } switch (et) { case QtWindows::InputMethodStartCompositionEvent: return QWindowsInputContext::instance()->startComposition(hwnd); case QtWindows::InputMethodCompositionEvent: return QWindowsInputContext::instance()->composition(hwnd, lParam); case QtWindows::InputMethodEndCompositionEvent: return QWindowsInputContext::instance()->endComposition(hwnd); case QtWindows::InputMethodRequest: return QWindowsInputContext::instance()->handleIME_Request(wParam, lParam, result); case QtWindows::InputMethodOpenCandidateWindowEvent: case QtWindows::InputMethodCloseCandidateWindowEvent: // TODO: Release/regrab mouse if a popup has mouse grab. return false; case QtWindows::ClipboardEvent: case QtWindows::DestroyEvent: case QtWindows::UnknownEvent: return false; case QtWindows::AccessibleObjectFromWindowRequest: #ifndef QT_NO_ACCESSIBILITY return QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(hwnd, wParam, lParam, result); #else return false; #endif case QtWindows::DisplayChangedEvent: return d->m_screenManager.handleDisplayChange(wParam, lParam); case QtWindows::SettingChangedEvent: return d->m_screenManager.handleScreenChanges(); default: break; } // Before CreateWindowEx() returns, some events are sent, // for example WM_GETMINMAXINFO asking for size constraints for top levels. // Pass on to current creation context if (!platformWindow && !d->m_creationContext.isNull()) { switch (et) { #ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO case QtWindows::QuerySizeHints: d->m_creationContext->applyToMinMaxInfo(reinterpret_cast<MINMAXINFO *>(lParam)); return true; #endif case QtWindows::ResizeEvent: d->m_creationContext->obtainedGeometry.setSize(QSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); return true; case QtWindows::MoveEvent: d->m_creationContext->obtainedGeometry.moveTo(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); return true; case QtWindows::CalculateSize: return false; default: break; } } if (platformWindow) { // Suppress events sent during DestroyWindow() for native children. if (platformWindow->testFlag(QWindowsWindow::WithinDestroy)) return false; if (QWindowsContext::verboseEvents > 1) qDebug().nospace() << "Event window: " << platformWindow->window(); } else { qWarning("%s: No Qt Window found for event 0x%x (%s), hwnd=0x%p.", __FUNCTION__, message, QWindowsGuiEventDispatcher::windowsMessageName(message), hwnd); return false; } switch (et) { case QtWindows::KeyDownEvent: case QtWindows::KeyEvent: case QtWindows::InputMethodKeyEvent: case QtWindows::InputMethodKeyDownEvent: return d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result); case QtWindows::MoveEvent: platformWindow->handleMoved(); return true; case QtWindows::ResizeEvent: platformWindow->handleResized((int)wParam); return true; #ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO case QtWindows::QuerySizeHints: platformWindow->getSizeHints(reinterpret_cast<MINMAXINFO *>(lParam)); return true;// maybe available on some SDKs revisit WM_NCCALCSIZE case QtWindows::CalculateSize: // NCCALCSIZE_PARAMS structure if wParam==TRUE if (wParam && QWindowsContext::verboseWindows) { const NCCALCSIZE_PARAMS *ncp = reinterpret_cast<NCCALCSIZE_PARAMS *>(lParam); qDebug() << platformWindow->window() << *ncp; } break; #endif case QtWindows::ExposeEvent: return platformWindow->handleWmPaint(hwnd, message, wParam, lParam); case QtWindows::NonClientMouseEvent: if (platformWindow->frameStrutEventsEnabled()) return d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); break; /* the mouse tracking on windows already handles the reset of the cursor * and does not like somebody else handling it. * on WINCE its necessary to handle this event to get the correct cursor */ #ifdef Q_OS_WINCE case QtWindows::CursorEvent: { QWindowsWindow::baseWindowOf(platformWindow->window())->applyCursor(); return true; } #endif case QtWindows::MouseWheelEvent: case QtWindows::MouseEvent: case QtWindows::LeaveEvent: return d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); case QtWindows::TouchEvent: return d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result); case QtWindows::FocusInEvent: // see QWindowsWindow::requestActivateWindow(). case QtWindows::FocusOutEvent: handleFocusEvent(et, platformWindow); return true; case QtWindows::ShowEvent: platformWindow->handleShown(); return true; case QtWindows::HideEvent: platformWindow->handleHidden(); return true; case QtWindows::CloseEvent: QWindowSystemInterface::handleCloseEvent(platformWindow->window()); return true; case QtWindows::ThemeChanged: // ### fixme: Compress these events? if (QWindowsTheme *theme = QWindowsTheme::instance()) theme->windowsThemeChanged(platformWindow->window()); return true; #ifndef Q_OS_WINCE case QtWindows::ActivateWindowEvent: if (platformWindow->testFlag(QWindowsWindow::BlockedByModal)) if (const QWindow *modalWindow = QGuiApplication::modalWindow()) QWindowsWindow::baseWindowOf(modalWindow)->alertWindow(); break; #endif #ifndef QT_NO_CONTEXTMENU case QtWindows::ContextMenu: handleContextMenuEvent(platformWindow->window(), msg); return true; #endif default: break; } return false; }
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) { if (message == WM_NCCREATE) return true; MSG msg; msg.hwnd = hwnd; msg.message = message; msg.wParam = wp; msg.lParam = lp; QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance(); long result; if (!dispatcher) { if (message == WM_TIMER) KillTimer(hwnd, wp); return 0; } else if (dispatcher->filterNativeEvent(QByteArrayLiteral("windows_dispatcher_MSG"), &msg, &result)) { return result; } #ifdef GWLP_USERDATA QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLongPtr(hwnd, GWLP_USERDATA); #else QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLong(hwnd, GWL_USERDATA); #endif QEventDispatcherWin32Private *d = 0; if (q != 0) d = q->d_func(); if (message == WM_QT_SOCKETNOTIFIER) { // socket notifier message int type = -1; switch (WSAGETSELECTEVENT(lp)) { case FD_READ: case FD_ACCEPT: type = 0; break; case FD_WRITE: case FD_CONNECT: type = 1; break; case FD_OOB: type = 2; break; case FD_CLOSE: type = 3; break; } if (type >= 0) { Q_ASSERT(d != 0); QSNDict *sn_vec[4] = { &d->sn_read, &d->sn_write, &d->sn_except, &d->sn_read }; QSNDict *dict = sn_vec[type]; QSockNot *sn = dict ? dict->value(wp) : 0; if (sn) { if (type < 3) { QEvent event(QEvent::SockAct); QCoreApplication::sendEvent(sn->obj, &event); } else { QEvent event(QEvent::SockClose); QCoreApplication::sendEvent(sn->obj, &event); } } } return 0; } else if (message == WM_QT_SENDPOSTEDEVENTS // we also use a Windows timer to send posted events when the message queue is full || (message == WM_TIMER && d->sendPostedEventsWindowsTimerId != 0 && wp == (uint)d->sendPostedEventsWindowsTimerId)) { const int localSerialNumber = d->serialNumber.load(); if (localSerialNumber != d->lastSerialNumber) { d->lastSerialNumber = localSerialNumber; q->sendPostedEvents(); } return 0; } else if (message == WM_TIMER) { Q_ASSERT(d != 0); d->sendTimerEvent(wp); return 0; } return DefWindowProc(hwnd, message, wp, lp); }