From 7c56a5b3825de2372712b9f0087df868ca1fd157 Mon Sep 17 00:00:00 2001 From: Prasanth Ullattil Date: Thu, 30 Jul 2009 13:12:56 +0200 Subject: QCheckBox on an out-of-process server wont allow key & Focus rect is not drawn correctly. Depending on the type of server, QAxClientSite::TranslateAccelerator() needs to process the message differently. For ActiveQt based in-process-servers, only normal Qt event handling is required. For ActiveQt based out-of-process-servers, the message has to be forwarded and Qt event handling needs to continue. For all other type of servers, forward the message and stop Qt event processing. Styles use the WA_KeyboardFocusChange attribute set on the window to decide on drawing the focus rect. ActiveQt handles the VK_TAB key in the QAxServerBase::TranslateAcceleratorW(), the attibute is now set when focus is changed. Task-number: 253763 Reviewed-by: Volker Hilsheimer --- src/activeqt/container/qaxwidget.cpp | 40 ++++++++++++++- src/activeqt/control/qaxserverbase.cpp | 90 ++++++++++++++++++---------------- src/activeqt/shared/qaxtypes.h | 3 ++ 3 files changed, 90 insertions(+), 43 deletions(-) diff --git a/src/activeqt/container/qaxwidget.cpp b/src/activeqt/container/qaxwidget.cpp index ae468ef..19f00db 100644 --- a/src/activeqt/container/qaxwidget.cpp +++ b/src/activeqt/container/qaxwidget.cpp @@ -118,6 +118,8 @@ public: QSize minimumSizeHint() const; int qt_metacall(QMetaObject::Call, int isignal, void **argv); + void* qt_metacast(const char *clname); + inline QAxClientSite *clientSite() const { return axhost; @@ -478,7 +480,9 @@ bool axc_FilterProc(void *m) QAxWidget *ax = 0; QAxHostWidget *host = 0; while (!host && hwnd) { - host = qobject_cast(QWidget::find(hwnd)); + QWidget *widget = QWidget::find(hwnd); + if (widget && widget->inherits("QAxHostWidget")) + host = qobject_cast(widget); hwnd = ::GetParent(hwnd); } if (host) @@ -976,10 +980,34 @@ HRESULT WINAPI QAxClientSite::TransformCoords(POINTL* /*pPtlHimetric*/, POINTF* HRESULT WINAPI QAxClientSite::TranslateAccelerator(LPMSG lpMsg, DWORD /*grfModifiers*/) { - eventTranslated = false; if (lpMsg->message == WM_KEYDOWN && !lpMsg->wParam) return S_OK; + + bool ActiveQtDetected = false; + bool fromInProcServer = false; + LONG_PTR serverType = GetWindowLongPtr(lpMsg->hwnd, GWLP_USERDATA); + if (serverType == QAX_INPROC_SERVER) { + ActiveQtDetected = true; + fromInProcServer = true; + } else if (serverType == QAX_OUTPROC_SERVER) { + ActiveQtDetected = true; + fromInProcServer = false; + } + + eventTranslated = false; + if (!ActiveQtDetected || !fromInProcServer) { + // if the request is coming from an out-of-proc server or a non ActiveQt server, + // we send the message to the host window. This will make sure this key event + // comes to Qt for processing. SendMessage(host->winId(), lpMsg->message, lpMsg->wParam, lpMsg->lParam); + if (ActiveQtDetected && !fromInProcServer) { + // ActiveQt based servers will need further processing of the event + // (eg. key for a checkbox), so we return false. + return S_FALSE; + } + } + // ActiveQt based in-processes-servers will handle the event properly, so + // we dont need to send this key event to the host. return S_OK; } @@ -1617,6 +1645,14 @@ int QAxHostWidget::qt_metacall(QMetaObject::Call call, int isignal, void **argv) return -1; } +void* QAxHostWidget::qt_metacast(const char *clname) +{ + if (!clname) return 0; + if (!qstrcmp(clname,"QAxHostWidget")) + return static_cast(const_cast< QAxHostWidget*>(this)); + return QWidget::qt_metacast(clname); +} + QSize QAxHostWidget::sizeHint() const { return axhost ? axhost->sizeHint() : QWidget::sizeHint(); diff --git a/src/activeqt/control/qaxserverbase.cpp b/src/activeqt/control/qaxserverbase.cpp index d7a8e07..e482c60 100644 --- a/src/activeqt/control/qaxserverbase.cpp +++ b/src/activeqt/control/qaxserverbase.cpp @@ -3502,24 +3502,24 @@ Q_GUI_EXPORT int qt_translateKeyCode(int); HRESULT WINAPI QAxServerBase::TranslateAcceleratorW(MSG *pMsg) { if (pMsg->message != WM_KEYDOWN || !isWidget) - return S_FALSE; + return S_FALSE; DWORD dwKeyMod = 0; if (::GetKeyState(VK_SHIFT) < 0) - dwKeyMod |= 1; // KEYMOD_SHIFT + dwKeyMod |= 1; // KEYMOD_SHIFT if (::GetKeyState(VK_CONTROL) < 0) - dwKeyMod |= 2; // KEYMOD_CONTROL + dwKeyMod |= 2; // KEYMOD_CONTROL if (::GetKeyState(VK_MENU) < 0) - dwKeyMod |= 4; // KEYMOD_ALT + dwKeyMod |= 4; // KEYMOD_ALT switch (LOWORD(pMsg->wParam)) { case VK_TAB: - if (isUIActive) { - bool shift = ::GetKeyState(VK_SHIFT) < 0; - bool giveUp = true; + if (isUIActive) { + bool shift = ::GetKeyState(VK_SHIFT) < 0; + bool giveUp = true; QWidget *curFocus = qt.widget->focusWidget(); if (curFocus) { - if (shift) { + if (shift) { if (!curFocus->isWindow()) { QWidget *nextFocus = curFocus->nextInFocusChain(); QWidget *prevFocus = 0; @@ -3537,9 +3537,10 @@ HRESULT WINAPI QAxServerBase::TranslateAcceleratorW(MSG *pMsg) if (!topLevel) { giveUp = false; ((HackWidget*)curFocus)->focusNextPrevChild(false); + curFocus->window()->setAttribute(Qt::WA_KeyboardFocusChange); } } - } else { + } else { QWidget *nextFocus = curFocus; while (1) { nextFocus = nextFocus->nextInFocusChain(); @@ -3548,63 +3549,70 @@ HRESULT WINAPI QAxServerBase::TranslateAcceleratorW(MSG *pMsg) if (nextFocus->focusPolicy() & Qt::TabFocus) { giveUp = false; ((HackWidget*)curFocus)->focusNextPrevChild(true); + curFocus->window()->setAttribute(Qt::WA_KeyboardFocusChange); break; } } - } + } + } + if (giveUp) { + HWND hwnd = ::GetParent(m_hWnd); + ::SetFocus(hwnd); + } else { + return S_OK; } - if (giveUp) { - HWND hwnd = ::GetParent(m_hWnd); - ::SetFocus(hwnd); - } else { - return S_OK; - } - } - break; + } + break; case VK_LEFT: case VK_RIGHT: case VK_UP: case VK_DOWN: - if (isUIActive) - return S_FALSE; - break; + if (isUIActive) + return S_FALSE; + break; default: - if (isUIActive && qt.widget->focusWidget()) { + if (isUIActive && qt.widget->focusWidget()) { int state = Qt::NoButton; - if (dwKeyMod & 1) - state |= Qt::ShiftModifier; - if (dwKeyMod & 2) - state |= Qt::ControlModifier; - if (dwKeyMod & 4) - state |= Qt::AltModifier; - - int key = pMsg->wParam; + if (dwKeyMod & 1) + state |= Qt::ShiftModifier; + if (dwKeyMod & 2) + state |= Qt::ControlModifier; + if (dwKeyMod & 4) + state |= Qt::AltModifier; + + int key = pMsg->wParam; if (!(key >= 'A' && key <= 'Z') && !(key >= '0' && key <= '9')) key = qt_translateKeyCode(pMsg->wParam); - QKeyEvent override(QEvent::ShortcutOverride, key, (Qt::KeyboardModifiers)state); - override.ignore(); - QApplication::sendEvent(qt.widget->focusWidget(), &override); - if (override.isAccepted()) - return S_FALSE; - } - break; + QKeyEvent override(QEvent::ShortcutOverride, key, (Qt::KeyboardModifiers)state); + override.ignore(); + QApplication::sendEvent(qt.widget->focusWidget(), &override); + if (override.isAccepted()) + return S_FALSE; + } + break; } if (!m_spClientSite) - return S_FALSE; + return S_FALSE; IOleControlSite *controlSite = 0; m_spClientSite->QueryInterface(IID_IOleControlSite, (void**)&controlSite); if (!controlSite) - return S_FALSE; - + return S_FALSE; + bool resetUserData = false; + // set server type in the user-data of the window. + LONG_PTR serverType = QAX_INPROC_SERVER; + if (qAxOutProcServer) + serverType = QAX_OUTPROC_SERVER; + LONG_PTR oldData = SetWindowLongPtr(pMsg->hwnd, GWLP_USERDATA, serverType); HRESULT hres = controlSite->TranslateAcceleratorW(pMsg, dwKeyMod); - controlSite->Release(); + // reset the user-data for the window. + SetWindowLongPtr(pMsg->hwnd, GWLP_USERDATA, oldData); return hres; } diff --git a/src/activeqt/shared/qaxtypes.h b/src/activeqt/shared/qaxtypes.h index 4f647a3..e3c7138 100644 --- a/src/activeqt/shared/qaxtypes.h +++ b/src/activeqt/shared/qaxtypes.h @@ -89,6 +89,9 @@ extern QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName extern bool QVariantToVoidStar(const QVariant &var, void *data, const QByteArray &typeName, uint type = 0); extern void clearVARIANT(VARIANT *var); +#define QAX_INPROC_SERVER (0x51540001) +#define QAX_OUTPROC_SERVER (0x51540002) + QT_END_NAMESPACE #endif // QT_NO_WIN_ACTIVEQT -- cgit v0.12