summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/imageformats/gif/qgifhandler.cpp7
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuloader.mm33
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp16
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h4
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp7
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp27
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp89
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp16
11 files changed, 63 insertions, 143 deletions
diff --git a/src/plugins/imageformats/gif/qgifhandler.cpp b/src/plugins/imageformats/gif/qgifhandler.cpp
index e0f7f44701..ebe5964664 100644
--- a/src/plugins/imageformats/gif/qgifhandler.cpp
+++ b/src/plugins/imageformats/gif/qgifhandler.cpp
@@ -354,7 +354,8 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
(*image) = QImage(swidth, sheight, format);
bpl = image->bytesPerLine();
bits = image->bits();
- memset(bits, 0, image->sizeInBytes());
+ if (bits)
+ memset(bits, 0, image->sizeInBytes());
}
// Check if the previous attempt to create the image failed. If it
@@ -415,6 +416,10 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
backingstore = QImage(qMax(backingstore.width(), w),
qMax(backingstore.height(), h),
QImage::Format_RGB32);
+ if (backingstore.isNull()) {
+ state = Error;
+ return -1;
+ }
memset(backingstore.bits(), 0, backingstore.sizeInBytes());
}
const int dest_bpl = backingstore.bytesPerLine();
diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.mm b/src/plugins/platforms/cocoa/qcocoamenuloader.mm
index 345b370826..5610c36ea1 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuloader.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuloader.mm
@@ -213,26 +213,23 @@
Q_ASSERT(mainMenu);
#endif
// Grab the app menu out of the current menu.
- const int numItems = mainMenu.numberOfItems;
- NSMenuItem *oldAppMenuItem = nil;
- for (int i = 0; i < numItems; ++i) {
- NSMenuItem *item = [mainMenu itemAtIndex:i];
- if (item.submenu == appMenu) {
- oldAppMenuItem = item;
- [oldAppMenuItem retain];
- [mainMenu removeItemAtIndex:i];
- break;
+ auto unparentAppMenu = ^bool (NSMenu *supermenu) {
+ auto index = [supermenu indexOfItemWithSubmenu:appMenu];
+ if (index != -1) {
+ [supermenu removeItemAtIndex:index];
+ return true;
}
- }
+ return false;
+ };
- if (oldAppMenuItem) {
- oldAppMenuItem.submenu = nil;
- [oldAppMenuItem release];
- NSMenuItem *appMenuItem = [[NSMenuItem alloc] initWithTitle:@"Apple"
- action:nil keyEquivalent:@""];
- appMenuItem.submenu = appMenu;
- [menu insertItem:appMenuItem atIndex:0];
- }
+ if (!mainMenu || !unparentAppMenu(mainMenu))
+ if (appMenu.supermenu)
+ unparentAppMenu(appMenu.supermenu);
+
+ NSMenuItem *appMenuItem = [[NSMenuItem alloc] initWithTitle:@"Apple"
+ action:nil keyEquivalent:@""];
+ appMenuItem.submenu = appMenu;
+ [menu insertItem:appMenuItem atIndex:0];
}
- (NSMenu *)menu
diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp
index 1443e5e920..825602e7dc 100644
--- a/src/plugins/platforms/windows/qwindowscursor.cpp
+++ b/src/plugins/platforms/windows/qwindowscursor.cpp
@@ -550,6 +550,7 @@ CursorHandlePtr QWindowsCursor::standardWindowCursor(Qt::CursorShape shape)
}
HCURSOR QWindowsCursor::m_overriddenCursor = nullptr;
+HCURSOR QWindowsCursor::m_overrideCursor = nullptr;
/*!
\brief Return cached pixmap cursor or create new one.
@@ -622,11 +623,20 @@ void QWindowsCursor::changeCursor(QCursor *cursorIn, QWindow *window)
}
}
+// QTBUG-69637: Override cursors can get reset externally when moving across
+// window borders. Enforce the cursor again (to be called from enter event).
+void QWindowsCursor::enforceOverrideCursor()
+{
+ if (hasOverrideCursor() && m_overrideCursor != GetCursor())
+ SetCursor(m_overrideCursor);
+}
+
void QWindowsCursor::setOverrideCursor(const QCursor &cursor)
{
const CursorHandlePtr wcursor = cursorHandle(cursor);
- if (wcursor->handle()) {
- const HCURSOR previousCursor = SetCursor(wcursor->handle());
+ if (const auto overrideCursor = wcursor->handle()) {
+ m_overrideCursor = overrideCursor;
+ const HCURSOR previousCursor = SetCursor(overrideCursor);
if (m_overriddenCursor == nullptr)
m_overriddenCursor = previousCursor;
} else {
@@ -639,7 +649,7 @@ void QWindowsCursor::clearOverrideCursor()
{
if (m_overriddenCursor) {
SetCursor(m_overriddenCursor);
- m_overriddenCursor = nullptr;
+ m_overriddenCursor = m_overrideCursor = nullptr;
}
}
diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
index 715533e0af..1816732594 100644
--- a/src/plugins/platforms/windows/qwindowscursor.h
+++ b/src/plugins/platforms/windows/qwindowscursor.h
@@ -107,7 +107,8 @@ public:
void changeCursor(QCursor * widgetCursor, QWindow * widget) override;
void setOverrideCursor(const QCursor &cursor) override;
void clearOverrideCursor() override;
- bool hasOverrideCursor() const { return m_overriddenCursor != nullptr; }
+ static void enforceOverrideCursor();
+ static bool hasOverrideCursor() { return m_overriddenCursor != nullptr; }
QPoint pos() const override;
void setPos(const QPoint &pos) override;
@@ -143,6 +144,7 @@ private:
mutable QPixmap m_ignoreDragCursor;
static HCURSOR m_overriddenCursor;
+ static HCURSOR m_overrideCursor;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 17fc120b42..45788fec15 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -2108,6 +2108,8 @@ bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow *
HWND desktopHWND = GetDesktopWindow();
platformWindow->m_data.embedded = !parentWindow && parentHWND && (parentHWND != desktopHWND);
}
+ if (qWindow->flags().testFlag(Qt::WindowStaysOnBottomHint))
+ windowPos->hwndInsertAfter = HWND_BOTTOM;
}
if (!qWindow->isTopLevel()) // Implement hasHeightForWidth().
return false;
@@ -2454,8 +2456,11 @@ static inline bool applyNewCursor(const QWindow *w)
void QWindowsWindow::applyCursor()
{
- if (static_cast<const QWindowsCursor *>(screen()->cursor())->hasOverrideCursor())
+ if (QWindowsCursor::hasOverrideCursor()) {
+ if (isTopLevel())
+ QWindowsCursor::enforceOverrideCursor();
return;
+ }
#ifndef QT_NO_CURSOR
if (m_cursor->isNull()) { // Recurse up to parent with non-null cursor. Set default for toplevel.
if (const QWindow *p = window()->parent()) {
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
index 0ae60ad220..85a931e015 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
@@ -68,21 +68,18 @@ QWindowsUiaAccessibility::~QWindowsUiaAccessibility()
// Handles UI Automation window messages.
bool QWindowsUiaAccessibility::handleWmGetObject(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult)
{
- if (lParam == LPARAM(UiaRootObjectId)) {
-
- // Start handling accessibility internally
- QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true);
-
- // Ignoring all requests while starting up / shutting down
- if (QCoreApplication::startingUp() || QCoreApplication::closingDown())
- return false;
-
- if (QWindow *window = QWindowsContext::instance()->findWindow(hwnd)) {
- if (QAccessibleInterface *accessible = window->accessibleRoot()) {
- QWindowsUiaMainProvider *provider = QWindowsUiaMainProvider::providerForAccessible(accessible);
- *lResult = QWindowsUiaWrapper::instance()->returnRawElementProvider(hwnd, wParam, lParam, provider);
- return true;
- }
+ // Start handling accessibility internally
+ QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true);
+
+ // Ignoring all requests while starting up / shutting down
+ if (QCoreApplication::startingUp() || QCoreApplication::closingDown())
+ return false;
+
+ if (QWindow *window = QWindowsContext::instance()->findWindow(hwnd)) {
+ if (QAccessibleInterface *accessible = window->accessibleRoot()) {
+ QWindowsUiaMainProvider *provider = QWindowsUiaMainProvider::providerForAccessible(accessible);
+ *lResult = QWindowsUiaWrapper::instance()->returnRawElementProvider(hwnd, wParam, lParam, provider);
+ return true;
}
}
return false;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
index 96f557efd3..11397fb9ec 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
@@ -149,7 +149,7 @@ long roleToControlTypeId(QAccessible::Role role)
{QAccessible::Caret, UIA_CustomControlTypeId},
{QAccessible::AlertMessage, UIA_CustomControlTypeId},
{QAccessible::Window, UIA_WindowControlTypeId},
- {QAccessible::Client, UIA_CustomControlTypeId},
+ {QAccessible::Client, UIA_GroupControlTypeId},
{QAccessible::PopupMenu, UIA_MenuControlTypeId},
{QAccessible::MenuItem, UIA_MenuItemControlTypeId},
{QAccessible::ToolTip, UIA_ToolTipControlTypeId},
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 327811a7d2..c14f3f3703 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -1693,10 +1693,8 @@ bool QXcbConnection::compressEvent(xcb_generic_event_t *event, int currentIndex,
continue;
if (isXIType(next, m_xiOpCode, XCB_INPUT_TOUCH_UPDATE)) {
auto *touchUpdateNextEvent = reinterpret_cast<xcb_input_touch_update_event_t *>(next);
- if (id == touchUpdateNextEvent->detail % INT_MAX &&
- touchUpdateNextEvent->deviceid == touchUpdateEvent->deviceid) {
+ if (id == touchUpdateNextEvent->detail % INT_MAX)
return true;
- }
}
}
return false;
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index c24bcf91f3..0b31e9c3e7 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -569,7 +569,6 @@ private:
bool m_xi2Enabled = false;
#if QT_CONFIG(xcb_xinput)
- QVector<int> m_floatingSlaveDevices;
int m_xi2Minor = -1;
void initializeXInput2();
void xi2SetupDevice(void *info, bool removeExisting = true);
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 01b1b37bb8..a327d8dea7 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -113,7 +113,7 @@ void QXcbConnection::xi2SelectDeviceEvents(xcb_window_t window)
}
qt_xcb_input_event_mask_t mask;
- mask.header.deviceid = XCB_INPUT_DEVICE_ALL;
+ mask.header.deviceid = XCB_INPUT_DEVICE_ALL_MASTER;
mask.header.mask_len = 1;
mask.mask = bitMask;
xcb_void_cookie_t cookie =
@@ -309,7 +309,6 @@ void QXcbConnection::xi2SetupDevices()
m_scrollingDevices.clear();
m_touchDevices.clear();
m_xiMasterPointerIds.clear();
- m_floatingSlaveDevices.clear();
auto reply = Q_XCB_REPLY(xcb_input_xi_query_device, m_connection, XCB_INPUT_DEVICE_ALL);
if (!reply) {
@@ -320,10 +319,6 @@ void QXcbConnection::xi2SetupDevices()
auto it = xcb_input_xi_query_device_infos_iterator(reply.get());
for (; it.rem; xcb_input_xi_device_info_next(&it)) {
xcb_input_xi_device_info_t *deviceInfo = it.data;
- if (deviceInfo->type == XCB_INPUT_DEVICE_TYPE_FLOATING_SLAVE) {
- m_floatingSlaveDevices.append(deviceInfo->deviceid);
- continue;
- }
if (deviceInfo->type == XCB_INPUT_DEVICE_TYPE_MASTER_POINTER) {
m_xiMasterPointerIds.append(deviceInfo->deviceid);
continue;
@@ -547,72 +542,6 @@ static inline qreal fixed1616ToReal(xcb_input_fp1616_t val)
}
#endif // QT_CONFIG(tabletevent)
-namespace {
-
-/*! \internal
-
- Qt listens for XIAllDevices to avoid losing mouse events. This function
- ensures that we don't process the same event twice: from a slave device and
- then again from a master device.
-
- In a normal use case (e.g. mouse press and release inside a window), we will
- drop events from master devices as duplicates. Other advantage of processing
- events from slave devices is that they don't share button state. All buttons
- on a master device share the state.
-
- Examples of special cases:
-
- - During system move/resize, window manager (_NET_WM_MOVERESIZE) grabs the
- master pointer, in this case we process the matching release from the slave
- device. A master device event is not sent by the server, hence no duplicate
- event to drop. If we listened for XIAllMasterDevices instead, we would never
- see a release event in this case.
-
- - If we dismiss a context menu by clicking somewhere outside a Qt application,
- we will process the mouse press from the master pointer as that is the
- device we are grabbing. We are not grabbing slave devices (grabbing on the
- slave device is buggy according to 19d289ab1b5bde3e136765e5432b5c7d004df3a4).
- And since the event occurs outside our window, the slave device event is
- not sent to us by the server, hence no duplicate event to drop.
-*/
-bool isDuplicateEvent(xcb_ge_event_t *event)
-{
- struct qXIEvent {
- bool isValid = false;
- uint16_t sourceid;
- uint8_t event_type;
- uint32_t detail;
- int32_t root_x;
- int32_t root_y;
- };
- static qXIEvent lastSeenEvent;
-
- bool isDuplicate = false;
- auto xiDeviceEvent = reinterpret_cast<qt_xcb_input_device_event_t *>(event);
- if (lastSeenEvent.isValid) {
- isDuplicate = lastSeenEvent.sourceid == xiDeviceEvent->sourceid &&
- lastSeenEvent.event_type == xiDeviceEvent->event_type &&
- lastSeenEvent.detail == xiDeviceEvent->detail &&
- lastSeenEvent.root_x == xiDeviceEvent->root_x &&
- lastSeenEvent.root_y == xiDeviceEvent->root_y;
- } else {
- lastSeenEvent.isValid = true;
- }
- lastSeenEvent.sourceid = xiDeviceEvent->sourceid;
- lastSeenEvent.event_type = xiDeviceEvent->event_type;
- lastSeenEvent.detail = xiDeviceEvent->detail;
- lastSeenEvent.root_x = xiDeviceEvent->root_x;
- lastSeenEvent.root_y = xiDeviceEvent->root_y;
-
- if (isDuplicate)
- // This sanity check ensures that special cases like QTBUG-59277 keep working.
- lastSeenEvent.isValid = false; // An event can be a duplicate only once.
-
- return isDuplicate;
-}
-
-} // namespace
-
void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
{
auto *xiEvent = reinterpret_cast<qt_xcb_input_device_event_t *>(event);
@@ -621,31 +550,15 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
xcb_input_enter_event_t *xiEnterEvent = nullptr;
QXcbWindowEventListener *eventListener = 0;
- bool isTouchEvent = true;
switch (xiEvent->event_type) {
case XCB_INPUT_BUTTON_PRESS:
case XCB_INPUT_BUTTON_RELEASE:
case XCB_INPUT_MOTION:
- isTouchEvent = false;
- if (!xi2MouseEventsDisabled() && isDuplicateEvent(event))
- return;
case XCB_INPUT_TOUCH_BEGIN:
case XCB_INPUT_TOUCH_UPDATE:
case XCB_INPUT_TOUCH_END:
{
xiDeviceEvent = xiEvent;
-
- if (m_floatingSlaveDevices.contains(xiDeviceEvent->sourceid))
- return; // Not interested in floating slave device events, only in attached slaves.
-
- bool isSlaveEvent = xiDeviceEvent->deviceid == xiDeviceEvent->sourceid;
- if (!xi2MouseEventsDisabled() && isTouchEvent && isSlaveEvent) {
- // For touch events we want events only from master devices, at least
- // currently there is no apparent reason why we would need to consider
- // events from slave devices.
- return;
- }
-
eventListener = windowEventListenerFromId(xiDeviceEvent->event);
sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id instead of the master
break;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index ed37c6b1f8..d42d95f890 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -2569,12 +2569,13 @@ bool QXcbWindow::startSystemMove(const QPoint &pos)
bool QXcbWindow::startSystemMoveResize(const QPoint &pos, int corner)
{
-#if QT_CONFIG(xcb_xinput)
+ return false; // ### FIXME QTBUG-69716
const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE);
if (!connection()->wmSupport()->isSupportedByWM(moveResize))
return false;
const QPoint globalPos = QHighDpi::toNativePixels(window()->mapToGlobal(pos), window()->screen());
+#if QT_CONFIG(xcb_xinput)
// ### FIXME QTBUG-53389
bool startedByTouch = connection()->startSystemMoveResizeForTouchBegin(m_window, globalPos, corner);
if (startedByTouch) {
@@ -2584,11 +2585,9 @@ bool QXcbWindow::startSystemMoveResize(const QPoint &pos, int corner)
return false;
}
// KWin, Openbox, AwesomeWM have been tested to work with _NET_WM_MOVERESIZE.
- } else { // Started by mouse press.
- if (!connection()->hasXInput2() || connection()->xi2MouseEventsDisabled()) {
- // Without XI2 we can't get button press/move/release events.
- return false;
- }
+ } else
+#endif
+ { // Started by mouse press.
if (connection()->isUnity())
return false; // _NET_WM_MOVERESIZE on this WM is bouncy (WM bug?).
@@ -2596,11 +2595,6 @@ bool QXcbWindow::startSystemMoveResize(const QPoint &pos, int corner)
}
return true;
-#else
- Q_UNUSED(pos);
- Q_UNUSED(corner);
- return false;
-#endif // xcb_xinput
}
void QXcbWindow::doStartSystemMoveResize(const QPoint &globalPos, int corner)