summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2015-09-25 14:02:04 +0200
committerLiang Qi <liang.qi@theqtcompany.com>2015-09-25 14:02:04 +0200
commita1ad9a74ebb3c556c5f70f7e03be68b09598ac53 (patch)
tree615a96db418219a57a745a5899e39a9ac90744ec /src/plugins/platforms/windows
parent6d78b7a0c46ea04f4bb771d960e2f7dff1362341 (diff)
parent462f355e4fb16cc7a1838fa2dda0f763eee58c84 (diff)
Merge remote-tracking branch 'origin/5.6' into dev
Conflicts: src/corelib/io/io.pri src/corelib/io/qdatastream.cpp src/corelib/io/qdatastream.h src/network/socket/qabstractsocket.cpp src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h src/widgets/styles/qgtkstyle.cpp tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/qmimedatabase-cache.pro tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/qmimedatabase-xml.pro tests/auto/dbus/qdbusconnection/qdbusconnection.pro tests/auto/dbus/qdbuspendingcall/tst_qdbuspendingcall.cpp tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp Change-Id: I347549a024eb5bfa986699e0a11f96cc55c797a7
Diffstat (limited to 'src/plugins/platforms/windows')
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp31
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.cpp43
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.cpp16
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.h1
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp55
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.cpp114
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.h8
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp19
-rw-r--r--src/plugins/platforms/windows/qwindowsole.cpp17
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp12
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h2
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.cpp18
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp16
17 files changed, 246 insertions, 129 deletions
diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp
index 925427ac30..97459a4d97 100644
--- a/src/plugins/platforms/windows/qwindowsclipboard.cpp
+++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp
@@ -109,8 +109,11 @@ static QDebug operator<<(QDebug d, const QMimeData *mimeData)
IDataObject *QWindowsClipboardRetrievalMimeData::retrieveDataObject() const
{
IDataObject * pDataObj = 0;
- if (OleGetClipboard(&pDataObj) == S_OK)
+ if (OleGetClipboard(&pDataObj) == S_OK) {
+ if (QWindowsContext::verbose > 1)
+ qCDebug(lcQpaMime) << __FUNCTION__ << pDataObj;
return pDataObj;
+ }
return 0;
}
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 717adcc47f..4ec34c05bd 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -33,6 +33,7 @@
****************************************************************************/
#include "qwindowscontext.h"
+#include "qwindowsintegration.h"
#include "qwindowswindow.h"
#include "qwindowskeymapper.h"
#include "qwindowsguieventdispatcher.h"
@@ -907,16 +908,30 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
return true;
}
}
+ if (et & QtWindows::InputMethodEventFlag) {
+ QWindowsInputContext *windowsInputContext =
+ qobject_cast<QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext());
+ // Disable IME assuming this is a special implementation hooking into keyboard input.
+ // "Real" IME implementations should use a native event filter intercepting IME events.
+ if (!windowsInputContext) {
+ QWindowsInputContext::setWindowsImeEnabled(platformWindow, false);
+ return false;
+ }
+ switch (et) {
+ case QtWindows::InputMethodStartCompositionEvent:
+ return windowsInputContext->startComposition(hwnd);
+ case QtWindows::InputMethodCompositionEvent:
+ return windowsInputContext->composition(hwnd, lParam);
+ case QtWindows::InputMethodEndCompositionEvent:
+ return windowsInputContext->endComposition(hwnd);
+ case QtWindows::InputMethodRequest:
+ return windowsInputContext->handleIME_Request(wParam, lParam, result);
+ default:
+ break;
+ }
+ } // InputMethodEventFlag
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::GestureEvent:
#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER)
return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateGestureEvent(platformWindow->window(), hwnd, et, msg, result);
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index 06c9985cac..e4ec3f3cf8 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
@@ -350,16 +350,16 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester:
{
const HDC dc = QWindowsContext::instance()->displayContext();
if (!dc){
- qWarning("%s: No Display", Q_FUNC_INFO);
+ qWarning("%s: No Display", __FUNCTION__);
return 0;
}
if (!libEGL.init()) {
- qWarning("%s: Failed to load and resolve libEGL functions", Q_FUNC_INFO);
+ qWarning("%s: Failed to load and resolve libEGL functions", __FUNCTION__);
return 0;
}
if (!libGLESv2.init()) {
- qWarning("%s: Failed to load and resolve libGLESv2 functions", Q_FUNC_INFO);
+ qWarning("%s: Failed to load and resolve libGLESv2 functions", __FUNCTION__);
return 0;
}
@@ -396,15 +396,15 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester:
if (display == EGL_NO_DISPLAY)
display = libEGL.eglGetDisplay((EGLNativeDisplayType)dc);
if (!display) {
- qWarning("%s: Could not obtain EGL display", Q_FUNC_INFO);
+ qWarning("%s: Could not obtain EGL display", __FUNCTION__);
return 0;
}
if (!major && !libEGL.eglInitialize(display, &major, &minor)) {
int err = libEGL.eglGetError();
- qWarning("%s: Could not initialize EGL display: error 0x%x\n", Q_FUNC_INFO, err);
+ qWarning("%s: Could not initialize EGL display: error 0x%x", __FUNCTION__, err);
if (err == 0x3001)
- qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", Q_FUNC_INFO);
+ qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", __FUNCTION__);
return 0;
}
@@ -430,7 +430,7 @@ void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *na
(EGLNativeWindowType) nativeWindow, 0);
if (surface == EGL_NO_SURFACE) {
*err = libEGL.eglGetError();
- qWarning("%s: Could not create the EGL window surface: 0x%x\n", Q_FUNC_INFO, *err);
+ qWarning("%s: Could not create the EGL window surface: 0x%x", __FUNCTION__, *err);
}
return surface;
@@ -533,7 +533,12 @@ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext,
}
if (m_eglContext == EGL_NO_CONTEXT) {
- qWarning("QWindowsEGLContext: eglError: %x, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
+ int err = QWindowsEGLStaticContext::libEGL.eglGetError();
+ qWarning("QWindowsEGLContext: Failed to create context, eglError: %x, this: %p", err, this);
+ // ANGLE gives bad alloc when it fails to reset a previously lost D3D device.
+ // A common cause for this is disabling the graphics adapter used by the app.
+ if (err == EGL_BAD_ALLOC)
+ qWarning("QWindowsEGLContext: Graphics device lost. (Did the adapter get disabled?)");
return;
}
@@ -594,6 +599,12 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
if (err == EGL_CONTEXT_LOST) {
m_eglContext = EGL_NO_CONTEXT;
qCDebug(lcQpaGl) << "Got EGL context lost in createWindowSurface() for context" << this;
+ } else if (err == EGL_BAD_ACCESS) {
+ // With ANGLE this means no (D3D) device and can happen when disabling/changing graphics adapters.
+ qCDebug(lcQpaGl) << "Bad access (missing device?) in createWindowSurface() for context" << this;
+ // Simulate context loss as the context is useless.
+ QWindowsEGLStaticContext::libEGL.eglDestroyContext(m_eglDisplay, m_eglContext);
+ m_eglContext = EGL_NO_CONTEXT;
}
return false;
}
@@ -623,7 +634,7 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
// Drop the surface. Will recreate on the next makeCurrent.
window->invalidateSurface();
} else {
- qWarning("QWindowsEGLContext::makeCurrent: eglError: %x, this: %p \n", err, this);
+ qWarning("%s: Failed to make surface current. eglError: %x, this: %p", __FUNCTION__, err, this);
}
}
@@ -635,7 +646,8 @@ void QWindowsEGLContext::doneCurrent()
QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
bool ok = QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (!ok)
- qWarning("QWindowsEGLContext::doneCurrent: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
+ qWarning("%s: Failed to make no context/surface current. eglError: %d, this: %p", __FUNCTION__,
+ QWindowsEGLStaticContext::libEGL.eglGetError(), this);
}
void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface)
@@ -653,8 +665,15 @@ void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface)
}
bool ok = QWindowsEGLStaticContext::libEGL.eglSwapBuffers(m_eglDisplay, eglSurface);
- if (!ok)
- qWarning("QWindowsEGLContext::swapBuffers: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
+ if (!ok) {
+ err = QWindowsEGLStaticContext::libEGL.eglGetError();
+ if (err == EGL_CONTEXT_LOST) {
+ m_eglContext = EGL_NO_CONTEXT;
+ qCDebug(lcQpaGl) << "Got EGL context lost in eglSwapBuffers()";
+ } else {
+ qWarning("%s: Failed to swap buffers. eglError: %d, this: %p", __FUNCTION__, err, this);
+ }
+ }
}
QFunctionPointer QWindowsEGLContext::getProcAddress(const QByteArray &procName)
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp
index 16b9118e81..3685197430 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp
@@ -181,9 +181,8 @@ void QWindowsFontEngine::getCMap()
bool symb = false;
if (ttf) {
cmapTable = getSfntTable(qbswap<quint32>(MAKE_TAG('c', 'm', 'a', 'p')));
- int size = 0;
cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()),
- cmapTable.size(), &symb, &size);
+ cmapTable.size(), &symb, &cmapSize);
}
if (!cmap) {
ttf = false;
@@ -218,16 +217,16 @@ int QWindowsFontEngine::getGlyphIndexes(const QChar *str, int numChars, QGlyphLa
QStringIterator it(str, str + numChars);
while (it.hasNext()) {
const uint uc = it.next();
- glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
+ glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
if(!glyphs->glyphs[glyph_pos] && uc < 0x100)
- glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000);
+ glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
++glyph_pos;
}
} else if (ttf) {
QStringIterator it(str, str + numChars);
while (it.hasNext()) {
const uint uc = it.next();
- glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc);
+ glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
++glyph_pos;
}
} else {
@@ -275,6 +274,7 @@ QWindowsFontEngine::QWindowsFontEngine(const QString &name,
hasOutline(0),
lw(0),
cmap(0),
+ cmapSize(0),
lbearing(SHRT_MIN),
rbearing(SHRT_MIN),
x_height(-1),
@@ -346,11 +346,11 @@ glyph_t QWindowsFontEngine::glyphIndex(uint ucs4) const
#if !defined(Q_OS_WINCE)
if (symbol) {
- glyph = getTrueTypeGlyphIndex(cmap, ucs4);
+ glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4);
if (glyph == 0 && ucs4 < 0x100)
- glyph = getTrueTypeGlyphIndex(cmap, ucs4 + 0xf000);
+ glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4 + 0xf000);
} else if (ttf) {
- glyph = getTrueTypeGlyphIndex(cmap, ucs4);
+ glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4);
#else
if (tm.tmFirstChar > 60000) {
glyph = ucs4;
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h
index 6df69c34db..409b44264e 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.h
+++ b/src/plugins/platforms/windows/qwindowsfontengine.h
@@ -146,6 +146,7 @@ private:
TEXTMETRIC tm;
int lw;
const unsigned char *cmap;
+ int cmapSize;
QByteArray cmapTable;
mutable qreal lbearing;
mutable qreal rbearing;
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index 485b876fc7..e016b84bba 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -199,32 +199,44 @@ void QWindowsInputContext::reset()
doneContext();
}
-void QWindowsInputContext::setFocusObject(QObject *object)
+void QWindowsInputContext::setFocusObject(QObject *)
{
// ### fixme: On Windows 8.1, it has been observed that the Input context
// remains active when this happens resulting in a lock-up. Consecutive
// key events still have VK_PROCESSKEY set and are thus ignored.
if (m_compositionContext.isComposing)
- imeNotifyCancelComposition(m_compositionContext.hwnd);
+ reset();
+ updateEnabled();
+}
+void QWindowsInputContext::updateEnabled()
+{
+ if (!QGuiApplication::focusObject())
+ return;
const QWindow *window = QGuiApplication::focusWindow();
- if (object && window && window->handle()) {
+ if (window && window->handle()) {
QWindowsWindow *platformWindow = QWindowsWindow::baseWindowOf(window);
- if (inputMethodAccepted()) {
- // Re-enable IME by associating default context saved on first disabling.
- if (platformWindow->testFlag(QWindowsWindow::InputMethodDisabled)) {
- ImmAssociateContext(platformWindow->handle(), QWindowsInputContext::m_defaultContext);
- platformWindow->clearFlag(QWindowsWindow::InputMethodDisabled);
- }
- } else {
- // Disable IME by associating 0 context. Store context first time.
- if (!platformWindow->testFlag(QWindowsWindow::InputMethodDisabled)) {
- const HIMC oldImC = ImmAssociateContext(platformWindow->handle(), 0);
- platformWindow->setFlag(QWindowsWindow::InputMethodDisabled);
- if (!QWindowsInputContext::m_defaultContext && oldImC)
- QWindowsInputContext::m_defaultContext = oldImC;
- }
- }
+ const bool accepted = inputMethodAccepted();
+ if (QWindowsContext::verbose > 1)
+ qCDebug(lcQpaInputMethods) << __FUNCTION__ << window << "accepted=" << accepted;
+ QWindowsInputContext::setWindowsImeEnabled(platformWindow, accepted);
+ }
+}
+
+void QWindowsInputContext::setWindowsImeEnabled(QWindowsWindow *platformWindow, bool enabled)
+{
+ if (!platformWindow || platformWindow->testFlag(QWindowsWindow::InputMethodDisabled) == !enabled)
+ return;
+ if (enabled) {
+ // Re-enable Windows IME by associating default context saved on first disabling.
+ ImmAssociateContext(platformWindow->handle(), QWindowsInputContext::m_defaultContext);
+ platformWindow->clearFlag(QWindowsWindow::InputMethodDisabled);
+ } else {
+ // Disable Windows IME by associating 0 context. Store context first time.
+ const HIMC oldImC = ImmAssociateContext(platformWindow->handle(), 0);
+ platformWindow->setFlag(QWindowsWindow::InputMethodDisabled);
+ if (!QWindowsInputContext::m_defaultContext && oldImC)
+ QWindowsInputContext::m_defaultContext = oldImC;
}
}
@@ -234,6 +246,8 @@ void QWindowsInputContext::setFocusObject(QObject *object)
void QWindowsInputContext::update(Qt::InputMethodQueries queries)
{
+ if (queries & Qt::ImEnabled)
+ updateEnabled();
QPlatformInputContext::update(queries);
}
@@ -295,11 +309,6 @@ void QWindowsInputContext::invokeAction(QInputMethod::Action action, int cursorP
ImmReleaseContext(m_compositionContext.hwnd, himc);
}
-QWindowsInputContext *QWindowsInputContext::instance()
-{
- return static_cast<QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext());
-}
-
static inline QString getCompositionString(HIMC himc, DWORD dwIndex)
{
enum { bufferSize = 256 };
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h
index 83a39989f6..eb4e3a3faa 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.h
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.h
@@ -42,6 +42,7 @@
QT_BEGIN_NAMESPACE
class QInputMethodEvent;
+class QWindowsWindow;
class QWindowsInputContext : public QPlatformInputContext
{
@@ -62,14 +63,14 @@ public:
explicit QWindowsInputContext();
~QWindowsInputContext();
+ static void setWindowsImeEnabled(QWindowsWindow *platformWindow, bool enabled);
+
bool hasCapability(Capability capability) const Q_DECL_OVERRIDE;
void reset() Q_DECL_OVERRIDE;
void update(Qt::InputMethodQueries) Q_DECL_OVERRIDE;
void invokeAction(QInputMethod::Action, int cursorPosition) Q_DECL_OVERRIDE;
void setFocusObject(QObject *object) Q_DECL_OVERRIDE;
- static QWindowsInputContext *instance();
-
bool startComposition(HWND hwnd);
bool composition(HWND hwnd, LPARAM lParam);
bool endComposition(HWND hwnd);
@@ -87,6 +88,7 @@ private:
void doneContext();
void startContextComposition();
void endContextComposition();
+ void updateEnabled();
const DWORD m_WM_MSIME_MOUSE;
static HIMC m_defaultContext;
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 081a800913..402ab9ad71 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -266,10 +266,9 @@ QWindowsIntegration::~QWindowsIntegration()
void QWindowsIntegration::initialize()
{
- if (QPlatformInputContext *pluginContext = QPlatformInputContextFactory::create())
- d->m_inputContext.reset(pluginContext);
- else
- d->m_inputContext.reset(new QWindowsInputContext);
+ QString icStr = QPlatformInputContextFactory::requested();
+ icStr.isNull() ? d->m_inputContext.reset(new QWindowsInputContext)
+ : d->m_inputContext.reset(QPlatformInputContextFactory::create(icStr));
}
bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 3636bb7893..f8e2ded228 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -33,6 +33,7 @@
#include "qwindowskeymapper.h"
#include "qwindowscontext.h"
+#include "qwindowsintegration.h"
#include "qwindowswindow.h"
#include "qwindowsguieventdispatcher.h"
#include "qwindowsinputcontext.h"
@@ -1074,7 +1075,9 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms
// results, if we map this virtual key-code directly (for eg '?' US layouts). So try
// to find the correct key using the current message parameters & keyboard state.
if (uch.isNull() && msgType == WM_IME_KEYDOWN) {
- if (!QWindowsInputContext::instance()->isComposing())
+ const QWindowsInputContext *windowsInputContext =
+ qobject_cast<const QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext());
+ if (!(windowsInputContext && windowsInputContext->isComposing()))
vk_key = ImmGetVirtualKey((HWND)window->winId());
BYTE keyState[256];
wchar_t newKey[3] = {0};
diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp
index f86ab9fee3..375a7f11db 100644
--- a/src/plugins/platforms/windows/qwindowsmime.cpp
+++ b/src/plugins/platforms/windows/qwindowsmime.cpp
@@ -299,8 +299,6 @@ static bool qt_read_dibv5(QDataStream &s, QImage &image)
return true;
}
-//#define QMIME_DEBUG
-
// helpers for using global memory
static int getCf(const FORMATETC &formatetc)
@@ -380,6 +378,73 @@ static bool canGetData(int cf, IDataObject * pDataObj)
return true;
}
+#ifndef QT_NO_DEBUG_OUTPUT
+QDebug operator<<(QDebug d, const FORMATETC &tc)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << "FORMATETC(cfFormat=" << tc.cfFormat << ' ';
+ switch (tc.cfFormat) {
+ case CF_TEXT:
+ d << "CF_TEXT";
+ break;
+ case CF_BITMAP:
+ d << "CF_BITMAP";
+ break;
+ case CF_TIFF:
+ d << "CF_TIFF";
+ break;
+ case CF_OEMTEXT:
+ d << "CF_OEMTEXT";
+ break;
+ case CF_DIB:
+ d << "CF_DIB";
+ break;
+ case CF_DIBV5:
+ d << "CF_DIBV5";
+ break;
+ case CF_UNICODETEXT:
+ d << "CF_UNICODETEXT";
+ break;
+#ifndef Q_OS_WINCE
+ case CF_ENHMETAFILE:
+ d << "CF_ENHMETAFILE";
+ break;
+#endif // !Q_OS_WINCE
+ default:
+ d << QWindowsMimeConverter::clipboardFormatName(tc.cfFormat);
+ break;
+ }
+ d << ", dwAspect=" << tc.dwAspect << ", lindex=" << tc.lindex
+ << ", tymed=" << tc.tymed << ", ptd=" << tc.ptd << ')';
+ return d;
+}
+
+QDebug operator<<(QDebug d, IDataObject *dataObj)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d.noquote();
+ d << "IDataObject(";
+ if (dataObj) { // Output formats contained in IDataObject.
+ IEnumFORMATETC *enumFormatEtc;
+ if (SUCCEEDED(dataObj->EnumFormatEtc(DATADIR_GET, &enumFormatEtc)) && enumFormatEtc) {
+ FORMATETC formatEtc[1];
+ ULONG fetched;
+ if (SUCCEEDED(enumFormatEtc->Reset())) {
+ while (SUCCEEDED(enumFormatEtc->Next(1, formatEtc, &fetched)) && fetched)
+ d << formatEtc[0] << ',';
+ enumFormatEtc->Release();
+ }
+ }
+ } else {
+ d << '0';
+ }
+ d << ')';
+ return d;
+}
+#endif // !QT_NO_DEBUG_OUTPUT
+
/*!
\class QWindowsMime
\brief The QWindowsMime class maps open-standard MIME to Window Clipboard formats.
@@ -894,11 +959,7 @@ QVariant QWindowsMimeHtml::convertToMime(const QString &mime, IDataObject *pData
QVariant result;
if (canConvertToMime(mime, pDataObj)) {
QByteArray html = getData(CF_HTML, pDataObj);
-#ifdef QMIME_DEBUG
- qDebug("QWindowsMimeHtml::convertToMime");
- qDebug("raw :");
- qDebug(html);
-#endif
+ qCDebug(lcQpaMime) << __FUNCTION__ << "raw:" << html;
int start = html.indexOf("StartHTML:");
int end = html.indexOf("EndHTML:");
@@ -990,13 +1051,14 @@ QVector<FORMATETC> QWindowsMimeImage::formatsForMime(const QString &mimeType, co
{
QVector<FORMATETC> formatetcs;
if (mimeData->hasImage() && mimeType == QLatin1String("application/x-qt-image")) {
- //add DIBV5 if image has alpha channel
+ //add DIBV5 if image has alpha channel. Do not add CF_PNG here as it will confuse MS Office (QTBUG47656).
QImage image = qvariant_cast<QImage>(mimeData->imageData());
if (!image.isNull() && image.hasAlphaChannel())
formatetcs += setCf(CF_DIBV5);
formatetcs += setCf(CF_DIB);
- formatetcs += setCf(CF_PNG); // QTBUG-86848, Paste into GIMP queries for PNG.
}
+ if (!formatetcs.isEmpty())
+ qCDebug(lcQpaMime) << __FUNCTION__ << mimeType << formatetcs;
return formatetcs;
}
@@ -1024,11 +1086,7 @@ bool QWindowsMimeImage::canConvertFromMime(const FORMATETC &formatetc, const QMi
const QImage image = qvariant_cast<QImage>(mimeData->imageData());
if (image.isNull())
return false;
- // QTBUG-11463, deny CF_DIB support for images with alpha to prevent loss of
- // transparency in conversion.
- return cf == CF_DIBV5
- || (cf == CF_DIB && !image.hasAlphaChannel())
- || cf == int(CF_PNG);
+ return cf == CF_DIBV5 || (cf == CF_DIB) || cf == int(CF_PNG);
}
bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const
@@ -1221,9 +1279,7 @@ QVariant QBuiltInMimes::convertToMime(const QString &mimeType, IDataObject *pDat
if (canConvertToMime(mimeType, pDataObj)) {
QByteArray data = getData(inFormats.key(mimeType), pDataObj);
if (!data.isEmpty()) {
-#ifdef QMIME_DEBUG
- qDebug("QBuiltInMimes::convertToMime()");
-#endif
+ qCDebug(lcQpaMime) << __FUNCTION__;
if (mimeType == QLatin1String("text/html") && preferredType == QVariant::String) {
// text/html is in wide chars on windows (compatible with Mozilla)
val = QString::fromWCharArray((const wchar_t *)data.data());
@@ -1331,6 +1387,8 @@ QVector<FORMATETC> QLastResortMimes::formatsForMime(const QString &mimeType, con
that->formats.insert(cf, mimeType);
formatetcs += setCf(cf);
}
+ if (!formatetcs.isEmpty())
+ qCDebug(lcQpaMime) << __FUNCTION__ << mimeType << formatetcs;
return formatetcs;
}
static const char x_qt_windows_mime[] = "application/x-qt-windows-mime;value=\"";
@@ -1405,11 +1463,8 @@ QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const
if (!format.isEmpty())
return format;
- wchar_t buffer[256];
- int len = GetClipboardFormatName(getCf(formatetc), buffer, 256);
-
- if (len) {
- QString clipFormat = QString::fromWCharArray(buffer, len);
+ const QString clipFormat = QWindowsMimeConverter::clipboardFormatName(getCf(formatetc));
+ if (!clipFormat.isEmpty()) {
#ifndef QT_NO_DRAGANDDROP
if (QInternalMimeData::canReadData(clipFormat))
format = clipFormat;
@@ -1475,15 +1530,12 @@ QStringList QWindowsMimeConverter::allMimesForFormats(IDataObject *pDataObj) con
if (hr == NOERROR) {
FORMATETC fmtetc;
while (S_OK == fmtenum->Next(1, &fmtetc, 0)) {
-#if defined(QMIME_DEBUG)
- wchar_t buf[256] = {0};
- GetClipboardFormatName(fmtetc.cfFormat, buf, 255);
- qDebug("CF = %d : %s", fmtetc.cfFormat, qPrintable(QString::fromWCharArray(buf)));
-#endif
for (int i= m_mimes.size() - 1; i >= 0; --i) {
QString format = m_mimes.at(i)->mimeForFormat(fmtetc);
if (!format.isEmpty() && !formats.contains(format)) {
formats += format;
+ if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled())
+ qCDebug(lcQpaMime) << __FUNCTION__ << fmtetc << format;
}
}
// as documented in MSDN to avoid possible memleak
@@ -1499,6 +1551,7 @@ QStringList QWindowsMimeConverter::allMimesForFormats(IDataObject *pDataObj) con
QWindowsMime * QWindowsMimeConverter::converterFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
{
ensureInitialized();
+ qCDebug(lcQpaMime) << __FUNCTION__ << formatetc;
for (int i = m_mimes.size()-1; i >= 0; --i) {
if (m_mimes.at(i)->canConvertFromMime(formatetc, mimeData))
return m_mimes.at(i);
@@ -1533,6 +1586,13 @@ void QWindowsMimeConverter::ensureInitialized() const
}
}
+QString QWindowsMimeConverter::clipboardFormatName(int cf)
+{
+ wchar_t buf[256] = {0};
+ return GetClipboardFormatName(cf, buf, 255)
+ ? QString::fromWCharArray(buf) : QString();
+}
+
QVariant QWindowsMimeConverter::convertToMime(const QStringList &mimeTypes,
IDataObject *pDataObj,
QVariant::Type preferredType,
diff --git a/src/plugins/platforms/windows/qwindowsmime.h b/src/plugins/platforms/windows/qwindowsmime.h
index 952410e14b..17fddef1bc 100644
--- a/src/plugins/platforms/windows/qwindowsmime.h
+++ b/src/plugins/platforms/windows/qwindowsmime.h
@@ -42,6 +42,7 @@
QT_BEGIN_NAMESPACE
+class QDebug;
class QMimeData;
class QWindowsMime
@@ -83,6 +84,8 @@ public:
void registerMime(QWindowsMime *mime);
void unregisterMime(QWindowsMime *mime) { m_mimes.removeOne(mime); }
+ static QString clipboardFormatName(int cf);
+
private:
void ensureInitialized() const;
@@ -90,6 +93,11 @@ private:
mutable int m_internalMimeCount;
};
+#ifndef QT_NO_DEBUG_OUTPUT
+QDebug operator<<(QDebug, const FORMATETC &);
+QDebug operator<<(QDebug d, IDataObject *);
+#endif
+
QT_END_NAMESPACE
#endif // QWINDOWSMIME_H
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
index 200eb11855..90cb6fe195 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
@@ -368,7 +368,10 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
QWindowsKeyMapper::queryKeyboardModifiers(),
source);
m_previousCaptureWindow = hasCapture ? window : 0;
- return true;
+ // QTBUG-48117, force synchronous handling for the extra buttons so that WM_APPCOMMAND
+ // is sent for unhandled WM_XBUTTONDOWN.
+ return (msg.message != WM_XBUTTONUP && msg.message != WM_XBUTTONDOWN && msg.message != WM_XBUTTONDBLCLK)
+ || QWindowSystemInterface::flushWindowSystemEvents();
}
static bool isValidWheelReceiver(QWindow *candidate)
@@ -474,7 +477,12 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND,
typedef QList<QWindowSystemInterface::TouchPoint> QTouchPointList;
Q_ASSERT(m_touchDevice);
- const QRect screenGeometry = window->screen()->geometry();
+ const QScreen *screen = window->screen();
+ if (!screen)
+ screen = QGuiApplication::primaryScreen();
+ if (!screen)
+ return true;
+ const QRect screenGeometry = screen->geometry();
const int winTouchPointCount = msg.wParam;
QScopedArrayPointer<TOUCHINPUT> winTouchInputs(new TOUCHINPUT[winTouchPointCount]);
@@ -566,7 +574,12 @@ bool QWindowsMouseHandler::translateGestureEvent(QWindow *window, HWND hwnd,
if (gi.dwID != GID_DIRECTMANIPULATION)
return true;
static QPoint lastTouchPos;
- const QRect screenGeometry = window->screen()->geometry();
+ const QScreen *screen = window->screen();
+ if (!screen)
+ screen = QGuiApplication::primaryScreen();
+ if (!screen)
+ return true;
+ const QRect screenGeometry = screen->geometry();
QWindowSystemInterface::TouchPoint touchPoint;
static QWindowSystemInterface::TouchPoint touchPoint2;
touchPoint.id = 0;//gi.dwInstanceID;
diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp
index 6f5a521af8..e480c1ebcf 100644
--- a/src/plugins/platforms/windows/qwindowsole.cpp
+++ b/src/plugins/platforms/windows/qwindowsole.cpp
@@ -132,12 +132,6 @@ QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)
{
HRESULT hr = ResultFromScode(DATA_E_FORMATETC);
- if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled()) {
- wchar_t buf[256] = {0};
- GetClipboardFormatName(pformatetc->cfFormat, buf, 255);
- qCDebug(lcQpaMime) <<__FUNCTION__ << "CF = " << pformatetc->cfFormat << QString::fromWCharArray(buf);
- }
-
if (data) {
const QWindowsMimeConverter &mc = QWindowsContext::instance()->mimeConverter();
if (QWindowsMime *converter = mc.converterFromMime(*pformatetc, data))
@@ -145,11 +139,8 @@ QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)
hr = ResultFromScode(S_OK);
}
- if (QWindowsContext::verbose > 1) {
- wchar_t buf[256] = {0};
- GetClipboardFormatName(pformatetc->cfFormat, buf, 255);
- qCDebug(lcQpaMime) <<__FUNCTION__ << "CF = " << pformatetc->cfFormat << " returns 0x" << int(hr) << dec;
- }
+ if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled())
+ qCDebug(lcQpaMime) <<__FUNCTION__ << *pformatetc << "returns" << hex << showbase << quint64(hr);
return hr;
}
@@ -211,7 +202,7 @@ STDMETHODIMP
QWindowsOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc)
{
if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaMime) << __FUNCTION__;
+ qCDebug(lcQpaMime) << __FUNCTION__ << "dwDirection=" << dwDirection;
if (!data)
return ResultFromScode(DATA_E_FORMATETC);
@@ -274,7 +265,7 @@ QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs)
m_dwRefs(1), m_nIndex(0), m_isNull(false)
{
if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaMime) << __FUNCTION__;
+ qCDebug(lcQpaMime) << __FUNCTION__ << fmtetcs;
m_lpfmtetcs.reserve(fmtetcs.count());
for (int idx = 0; idx < fmtetcs.count(); ++idx) {
LPFORMATETC destetc = new FORMATETC();
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 391735a035..e6abfb2403 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -276,18 +276,6 @@ QWindow *QWindowsScreen::windowAt(const QPoint &screenPoint, unsigned flags)
return result;
}
-QWindowsScreen *QWindowsScreen::screenOf(const QWindow *w)
-{
- if (w)
- if (const QScreen *s = w->screen())
- if (QPlatformScreen *pscr = s->handle())
- return static_cast<QWindowsScreen *>(pscr);
- if (const QScreen *ps = QGuiApplication::primaryScreen())
- if (QPlatformScreen *ppscr = ps->handle())
- return static_cast<QWindowsScreen *>(ppscr);
- return 0;
-}
-
qreal QWindowsScreen::pixelDensity() const
{
const qreal physicalDpi = m_data.geometry.width() / m_data.physicalSizeMM.width() * qreal(25.4);
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 67e7ff644b..bc8fbf553b 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -79,8 +79,6 @@ public:
explicit QWindowsScreen(const QWindowsScreenData &data);
- static QWindowsScreen *screenOf(const QWindow *w = 0);
-
QRect geometry() const Q_DECL_OVERRIDE { return m_data.geometry; }
QRect availableGeometry() const Q_DECL_OVERRIDE { return m_data.availableGeometry; }
int depth() const Q_DECL_OVERRIDE { return m_data.depth; }
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
index 05bddec530..3951401273 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
@@ -54,7 +54,7 @@
#include <QtCore/private/qsystemlibrary_p.h>
// Note: The definition of the PACKET structure in pktdef.h depends on this define.
-#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_Z)
+#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_Z | PK_TIME)
#include <pktdef.h>
QT_BEGIN_NAMESPACE
@@ -342,17 +342,18 @@ QWindowsTabletDeviceData QWindowsTabletSupport::tabletInit(const quint64 uniqueI
bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, LPARAM lParam)
{
+ PACKET proximityBuffer[1]; // we are only interested in the first packet in this case
+ const int totalPacks = QWindowsTabletSupport::m_winTab32DLL.wTPacketsGet(m_context, 1, proximityBuffer);
+ if (!totalPacks)
+ return false;
if (!LOWORD(lParam)) {
qCDebug(lcQpaTablet) << "leave proximity for device #" << m_currentDevice;
- QWindowSystemInterface::handleTabletLeaveProximityEvent(m_devices.at(m_currentDevice).currentDevice,
+ QWindowSystemInterface::handleTabletLeaveProximityEvent(proximityBuffer[0].pkTime,
+ m_devices.at(m_currentDevice).currentDevice,
m_devices.at(m_currentDevice).currentPointerType,
m_devices.at(m_currentDevice).uniqueId);
return true;
}
- PACKET proximityBuffer[1]; // we are only interested in the first packet in this case
- const int totalPacks = QWindowsTabletSupport::m_winTab32DLL.wTPacketsGet(m_context, 1, proximityBuffer);
- if (!totalPacks)
- return false;
const UINT currentCursor = proximityBuffer[0].pkCursor;
UINT physicalCursorId;
QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_CURSORS + currentCursor, CSR_PHYSID, &physicalCursorId);
@@ -370,7 +371,8 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L
m_devices[m_currentDevice].currentPointerType = pointerType(currentCursor);
qCDebug(lcQpaTablet) << "enter proximity for device #"
<< m_currentDevice << m_devices.at(m_currentDevice);
- QWindowSystemInterface::handleTabletEnterProximityEvent(m_devices.at(m_currentDevice).currentDevice,
+ QWindowSystemInterface::handleTabletEnterProximityEvent(proximityBuffer[0].pkTime,
+ m_devices.at(m_currentDevice).currentDevice,
m_devices.at(m_currentDevice).currentPointerType,
m_devices.at(m_currentDevice).uniqueId);
return true;
@@ -473,7 +475,7 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
<< tiltY << "tanP:" << tangentialPressure << "rotation:" << rotation;
}
- QWindowSystemInterface::handleTabletEvent(target, QPointF(localPos), globalPosF,
+ QWindowSystemInterface::handleTabletEvent(target, packet.pkTime, QPointF(localPos), globalPosF,
currentDevice, currentPointer,
static_cast<Qt::MouseButtons>(packet.pkButtons),
pressureNew, tiltX, tiltY,
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 1b5d7b87bc..abfddcfed6 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1045,8 +1045,8 @@ void QWindowsWindow::setDropSiteEnabled(bool dropEnabled)
RegisterDragDrop(m_data.hwnd, m_dropTarget);
CoLockObjectExternal(m_dropTarget, true, true);
} else {
- m_dropTarget->Release();
CoLockObjectExternal(m_dropTarget, false, true);
+ m_dropTarget->Release();
RevokeDragDrop(m_data.hwnd);
m_dropTarget = 0;
}
@@ -1637,8 +1637,12 @@ void QWindowsWindow::setWindowState(Qt::WindowState state)
bool QWindowsWindow::isFullScreen_sys() const
{
const QWindow *w = window();
- return w->isTopLevel()
- && geometry_sys() == QHighDpi::toNativePixels(w->screen()->geometry(), w);
+ if (!w->isTopLevel())
+ return false;
+ const QScreen *screen = w->screen();
+ if (!screen)
+ screen = QGuiApplication::primaryScreen();
+ return screen && geometry_sys() == QHighDpi::toNativePixels(screen->geometry(), w);
}
/*!
@@ -1708,7 +1712,9 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
// Use geometry of QWindow::screen() within creation or the virtual screen the
// window is in (QTBUG-31166, QTBUG-30724).
const QScreen *screen = window()->screen();
- const QRect r = QHighDpi::toNativePixels(screen->geometry(), window());
+ if (!screen)
+ screen = QGuiApplication::primaryScreen();
+ const QRect r = screen ? QHighDpi::toNativePixels(screen->geometry(), window()) : m_savedFrameGeometry;
const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
setFlag(SynchronousGeometryChangeEvent);
@@ -1825,7 +1831,7 @@ bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow *
const QRect suggestedFrameGeometry(windowPos->x, windowPos->y,
windowPos->cx, windowPos->cy);
const QRect suggestedGeometry = suggestedFrameGeometry - margins;
- const QRectF correctedGeometryF = qWindow->handle()->windowClosestAcceptableGeometry(suggestedGeometry);
+ const QRectF correctedGeometryF = QPlatformWindow::closestAcceptableGeometry(qWindow, suggestedGeometry);
if (!correctedGeometryF.isValid())
return false;
const QRect correctedFrameGeometry = correctedGeometryF.toRect() + margins;