summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/android/src/opengl/qeglfshooks_android.cpp7
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm16
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm12
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm1
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm10
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm53
-rw-r--r--src/plugins/platforms/cocoa/qnsview.h2
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm32
-rw-r--r--src/plugins/platforms/cocoa/qnswindowdelegate.h2
-rw-r--r--src/plugins/platforms/eglfs/eglfs.pri2
-rw-r--r--src/plugins/platforms/eglfs/qeglfshooks_stub.cpp4
-rw-r--r--src/plugins/platforms/eglfs/qeglfshooks_x11.cpp160
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.cpp4
-rw-r--r--src/plugins/platforms/eglfs/qeglfsscreen.cpp8
-rw-r--r--src/plugins/platforms/ios/qioscontext.mm3
-rw-r--r--src/plugins/platforms/ios/qioswindow.h7
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm103
-rw-r--r--src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp9
-rw-r--r--src/plugins/platforms/qnx/qnx.pro2
-rw-r--r--src/plugins/platforms/qnx/qqnxbuffer.cpp21
-rw-r--r--src/plugins/platforms/qnx/qqnxglcontext.cpp30
-rw-r--r--src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp19
-rw-r--r--src/plugins/platforms/qnx/qqnxintegration.cpp12
-rw-r--r--src/plugins/platforms/qnx/qqnxnavigatorpps.cpp3
-rw-r--r--src/plugins/platforms/qnx/qqnxrootwindow.cpp60
-rw-r--r--src/plugins/platforms/qnx/qqnxscreen.cpp10
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp53
-rw-r--r--src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp15
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.cpp81
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.cpp24
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.h1
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp41
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp164
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h26
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp14
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp115
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.h7
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp24
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp32
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp909
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.h89
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp10
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h5
-rw-r--r--src/plugins/platforms/xcb/qxcbxsettings.cpp280
-rw-r--r--src/plugins/platforms/xcb/qxcbxsettings.h71
-rw-r--r--src/plugins/platforms/xcb/xcb-plugin.pro25
-rw-r--r--src/plugins/platforms/xcb/xcb-static/xcb-static.pro3
54 files changed, 1817 insertions, 788 deletions
diff --git a/src/plugins/platforms/android/src/opengl/qeglfshooks_android.cpp b/src/plugins/platforms/android/src/opengl/qeglfshooks_android.cpp
index 005758d83d..5a35310111 100644
--- a/src/plugins/platforms/android/src/opengl/qeglfshooks_android.cpp
+++ b/src/plugins/platforms/android/src/opengl/qeglfshooks_android.cpp
@@ -62,6 +62,7 @@ public:
EGLNativeWindowType createNativeWindow(const QSize &size, const QSurfaceFormat &format);
void destroyNativeWindow(EGLNativeWindowType window);
bool hasCapability(QPlatformIntegration::Capability cap) const;
+ QEglFSCursor *createCursor(QEglFSScreen *screen) const;
};
void QEglFSAndroidHooks::platformInit()
@@ -134,6 +135,12 @@ QSurfaceFormat QEglFSAndroidHooks::surfaceFormatFor(const QSurfaceFormat &inputF
return ret;
}
+QEglFSCursor *QEglFSAndroidHooks::createCursor(QEglFSScreen *screen) const
+{
+ Q_UNUSED(screen);
+ return 0;
+}
+
static QEglFSAndroidHooks eglFSAndroidHooks;
QEglFSHooks *platformHooks = &eglFSAndroidHooks;
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
index 7320fc11e6..95fe9129d3 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
@@ -100,11 +100,23 @@ static void cleanupCocoaApplicationDelegate()
- (id)init
{
self = [super init];
- if (self)
+ if (self) {
inLaunch = true;
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(updateScreens:)
+ name:NSApplicationDidChangeScreenParametersNotification
+ object:NSApp];
+ }
return self;
}
+- (void)updateScreens:(NSNotification *)notification
+{
+ if (QCocoaIntegration *ci = dynamic_cast<QCocoaIntegration *>(QGuiApplicationPrivate::platformIntegration()))
+ ci->updateScreens();
+}
+
- (void)dealloc
{
sharedCocoaApplicationDelegate = nil;
@@ -114,6 +126,8 @@ static void cleanupCocoaApplicationDelegate()
[NSApp setDelegate:reflectionDelegate];
[reflectionDelegate release];
}
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+
[super dealloc];
}
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index d4673baaef..3dee137038 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -133,18 +133,6 @@ void QCocoaGLContext::setActiveWindow(QWindow *window)
cocoaWindow->setCurrentContext(this);
[(QNSView *) cocoaWindow->contentView() setQCocoaGLContext:this];
-
- // Enable high-dpi OpenGL for retina displays. Enabling has the side
- // effect that Cooca will start calling glViewport(0, 0, width, height),
- // overriding any glViewport calls in application code. This is usually not a
- // problem, except if the applcation wants to have a "custom" viewport.
- // (like the hellogl example)
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
- if (cocoaWindow->devicePixelRatio() > 1)
- [cocoaWindow->contentView() setWantsBestResolutionOpenGLSurface:YES];
- }
-#endif
}
void QCocoaGLContext::doneCurrent()
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index 6e690dd51e..7831888da1 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -125,6 +125,7 @@ public:
QList<int> possibleKeys(const QKeyEvent *event) const;
void updateScreens();
+ QCocoaScreen *screenAtIndex(int index) const { return mScreens.at(index); }
private:
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 50d68f8311..987520f307 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -352,6 +352,7 @@ bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) cons
case BufferQueueingOpenGL:
case WindowMasks:
case MultipleWindows:
+ case ForeignWindows:
return true;
default:
return QPlatformIntegration::hasCapability(cap);
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm
index 0a98819d16..df0ef390c9 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenu.mm
@@ -98,6 +98,16 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate);
return self;
}
+
+- (void)menu:(NSMenu*)menu willHighlightItem:(NSMenuItem*)item
+{
+ Q_UNUSED(menu);
+ if (item && [item tag]) {
+ QCocoaMenuItem *cocoaItem = reinterpret_cast<QCocoaMenuItem *>([item tag]);
+ cocoaItem->hovered();
+ }
+}
+
- (void) menuWillOpen:(NSMenu*)m
{
Q_UNUSED(m);
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 5d1600dba6..47341e2262 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -118,7 +118,7 @@ static bool isMouseEvent(NSEvent *ev)
// Windows with a transient parent (such as combobox popup windows)
// cannot become the main window:
- if (m_cocoaPlatformWindow && m_cocoaPlatformWindow->window()->transientParent())
+ if (!m_cocoaPlatformWindow || m_cocoaPlatformWindow->window()->transientParent())
canBecomeMain = NO;
return canBecomeMain;
@@ -159,7 +159,8 @@ static bool isMouseEvent(NSEvent *ev)
return NO;
// Only tool or dialog windows should become key:
- if (m_cocoaPlatformWindow->window()->type() == Qt::Tool || m_cocoaPlatformWindow->window()->type() == Qt::Dialog)
+ if (m_cocoaPlatformWindow
+ && (m_cocoaPlatformWindow->window()->type() == Qt::Tool || m_cocoaPlatformWindow->window()->type() == Qt::Dialog))
return YES;
return NO;
}
@@ -195,6 +196,8 @@ const int QCocoaWindow::NoAlertRequest = -1;
QCocoaWindow::QCocoaWindow(QWindow *tlw)
: QPlatformWindow(tlw)
+ , m_contentView(nil)
+ , m_qtView(nil)
, m_nsWindow(0)
, m_contentViewIsEmbedded(false)
, m_contentViewIsToBeEmbedded(false)
@@ -215,8 +218,23 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
#endif
QCocoaAutoReleasePool pool;
- m_qtView = [[QNSView alloc] initWithQWindow:tlw platformWindow:this];
- m_contentView = m_qtView;
+ if (tlw->type() == Qt::ForeignWindow) {
+ NSView *foreignView = (NSView *)WId(tlw->property("_q_foreignWinId").value<WId>());
+ setContentView(foreignView);
+ } else {
+ m_qtView = [[QNSView alloc] initWithQWindow:tlw platformWindow:this];
+ m_contentView = m_qtView;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+ // Enable high-dpi OpenGL for retina displays. Enabling has the side
+ // effect that Cocoa will start calling glViewport(0, 0, width, height),
+ // overriding any glViewport calls in application code. This is usually not a
+ // problem, except if the appilcation wants to have a "custom" viewport.
+ // (like the hellogl example)
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7
+ && tlw->surfaceType() == QSurface::OpenGLSurface)
+ [m_contentView setWantsBestResolutionOpenGLSurface:YES];
+#endif
+ }
setGeometry(tlw->geometry());
recreateWindow(parent());
tlw->setGeometry(geometry());
@@ -258,8 +276,7 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect)
if (m_nsWindow) {
NSRect bounds = qt_mac_flipRect(rect, window());
- [m_nsWindow setContentSize : bounds.size];
- [m_nsWindow setFrameOrigin : bounds.origin];
+ [m_nsWindow setFrame:[m_nsWindow frameRectForContentRect:bounds] display:YES animate:NO];
} else {
[m_contentView setFrame : NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())];
}
@@ -308,6 +325,8 @@ void QCocoaWindow::setVisible(bool visible)
exposeWindow();
if (m_nsWindow) {
+ QWindowSystemInterface::flushWindowSystemEvents();
+
// setWindowState might have been called while the window was hidden and
// will not change the NSWindow state in that case. Sync up here:
syncWindowState(window()->windowState());
@@ -349,11 +368,22 @@ void QCocoaWindow::setVisible(bool visible)
QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher));
cocoaEventDispatcherPrivate->endModalSession(window());
m_hasModalSession = false;
+
+ [m_nsWindow orderOut:m_nsWindow];
+ if (m_nsWindow == [NSApp keyWindow] && !cocoaEventDispatcherPrivate->currentModalSession()) {
+ // Probably because we call runModalSession: outside [NSApp run] in QCocoaEventDispatcher
+ // (e.g., when show()-ing a modal QDialog instead of exec()-ing it), it can happen that
+ // the current NSWindow is still key after being ordered out. Then, after checking we
+ // don't have any other modal session left, it's safe to make the main window key again.
+ NSWindow *mainWindow = [NSApp mainWindow];
+ if (mainWindow && [mainWindow canBecomeKeyWindow])
+ [mainWindow makeKeyWindow];
+ }
} else {
if ([m_nsWindow isSheet])
[NSApp endSheet:m_nsWindow];
+ [m_nsWindow orderOut:m_nsWindow];
}
- [m_nsWindow orderOut:m_nsWindow];
} else {
[m_contentView setHidden:YES];
}
@@ -446,8 +476,6 @@ void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
NSInteger level = this->windowLevel(flags);
[m_nsWindow setStyleMask:styleMask];
[m_nsWindow setLevel:level];
- [m_nsWindow setIgnoresMouseEvents:((flags & Qt::ToolTip) == Qt::ToolTip) ? YES : NO];
- // TODO deal with WindowTransparentForInput; setIgnoresMouseEvents is too extreme, you can't click the titlebar
setWindowShadow(flags);
}
@@ -784,8 +812,10 @@ NSWindow * QCocoaWindow::createNSWindow()
// before the window is shown and needs a proper window.).
if ((type & Qt::Popup) == Qt::Popup)
[window setHasShadow:YES];
- else
+ else {
setWindowShadow(flags);
+ [window setHidesOnDeactivate: NO];
+ }
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
@@ -987,7 +1017,8 @@ QWindow *QCocoaWindow::childWindowAt(QPoint windowPoint)
if (QWindow *childWindow = qobject_cast<QWindow *>(child)) {
if (childWindow->geometry().contains(windowPoint)) {
QCocoaWindow* platformWindow = static_cast<QCocoaWindow*>(childWindow->handle());
- targetWindow = platformWindow->childWindowAt(windowPoint - childWindow->position());
+ if (platformWindow->isExposed())
+ targetWindow = platformWindow->childWindowAt(windowPoint - childWindow->position());
}
}
}
diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h
index 67b16b4b32..85f72a4dbb 100644
--- a/src/plugins/platforms/cocoa/qnsview.h
+++ b/src/plugins/platforms/cocoa/qnsview.h
@@ -69,6 +69,8 @@ QT_END_NAMESPACE
bool m_sendUpAsRightButton;
Qt::KeyboardModifiers currentWheelModifiers;
bool m_subscribesForGlobalFrameNotifications;
+ QCocoaGLContext *m_glContext;
+ bool m_shouldSetGLContextinDrawRect;
}
- (id)init;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index c114ab20d0..42117a64a1 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -58,6 +58,7 @@
#include <private/qguiapplication_p.h>
#include "qcocoabackingstore.h"
#include "qcocoaglcontext.h"
+#include "qcocoaintegration.h"
#ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR
#include <accessibilityinspector.h>
@@ -85,6 +86,8 @@ static QTouchDevice *touchDevice = 0;
m_buttons = Qt::NoButton;
m_sendKeyEvent = false;
m_subscribesForGlobalFrameNotifications = false;
+ m_glContext = 0;
+ m_shouldSetGLContextinDrawRect = false;
currentCustomDragTypes = 0;
m_sendUpAsRightButton = false;
@@ -150,7 +153,13 @@ static QTouchDevice *touchDevice = 0;
- (void) setQCocoaGLContext:(QCocoaGLContext *)context
{
- [context->nsOpenGLContext() setView:self];
+ m_glContext = context;
+ [m_glContext->nsOpenGLContext() setView:self];
+ if (![m_glContext->nsOpenGLContext() view]) {
+ //was unable to set view
+ m_shouldSetGLContextinDrawRect = true;
+ }
+
if (!m_subscribesForGlobalFrameNotifications) {
// NSOpenGLContext expects us to repaint (or update) the view when
// it changes position on screen. Since this happens unnoticed for
@@ -268,6 +277,15 @@ static QTouchDevice *touchDevice = 0;
m_platformWindow->obscureWindow();
} else if ([notificationName isEqualToString: @"NSWindowDidOrderOnScreenAndFinishAnimatingNotification"]) {
m_platformWindow->exposeWindow();
+ } else if (notificationName == NSWindowDidChangeScreenNotification) {
+ if (m_window) {
+ QCocoaIntegration *ci = static_cast<QCocoaIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ NSUInteger screenIndex = [[NSScreen screens] indexOfObject:self.window.screen];
+ if (screenIndex != NSNotFound) {
+ QCocoaScreen *cocoaScreen = ci->screenAtIndex(screenIndex);
+ QWindowSystemInterface::handleWindowScreenChanged(m_window, cocoaScreen->screen());
+ }
+ }
} else {
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
@@ -344,6 +362,11 @@ static QTouchDevice *touchDevice = 0;
- (void) drawRect:(NSRect)dirtyRect
{
+ if (m_glContext && m_shouldSetGLContextinDrawRect) {
+ [m_glContext->nsOpenGLContext() setView:self];
+ m_shouldSetGLContextinDrawRect = false;
+ }
+
if (!m_backingStore)
return;
@@ -1304,14 +1327,17 @@ static QTouchDevice *touchDevice = 0;
QCocoaDropData mimeData([sender draggingPasteboard]);
response = QWindowSystemInterface::handleDrop(m_window, &mimeData, qt_windowPoint, qtAllowed);
}
+ if (response.isAccepted()) {
+ QCocoaDrag* nativeDrag = static_cast<QCocoaDrag *>(QGuiApplicationPrivate::platformIntegration()->drag());
+ nativeDrag->setAcceptedAction(response.acceptedAction());
+ }
return response.isAccepted();
}
- (void)draggedImage:(NSImage*) img endedAt:(NSPoint) point operation:(NSDragOperation) operation
{
Q_UNUSED(img);
- QCocoaDrag* nativeDrag = static_cast<QCocoaDrag *>(QGuiApplicationPrivate::platformIntegration()->drag());
- nativeDrag->setAcceptedAction(qt_mac_mapNSDragOperation(operation));
+ Q_UNUSED(operation);
// keep our state, and QGuiApplication state (buttons member) in-sync,
// or future mouse events will be processed incorrectly
diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.h b/src/plugins/platforms/cocoa/qnswindowdelegate.h
index a5b46a971f..9a616ba8e8 100644
--- a/src/plugins/platforms/cocoa/qnswindowdelegate.h
+++ b/src/plugins/platforms/cocoa/qnswindowdelegate.h
@@ -55,7 +55,7 @@
- (void)windowDidResize:(NSNotification *)notification;
- (void)windowDidMove:(NSNotification *)notification;
-- (void)windowWillClose:(NSNotification *)notification;
+- (void)windowWillMove:(NSNotification *)notification;
- (BOOL)windowShouldClose:(NSNotification *)notification;
@end
diff --git a/src/plugins/platforms/eglfs/eglfs.pri b/src/plugins/platforms/eglfs/eglfs.pri
index eb66e17479..44455ed3d8 100644
--- a/src/plugins/platforms/eglfs/eglfs.pri
+++ b/src/plugins/platforms/eglfs/eglfs.pri
@@ -7,7 +7,7 @@ DEFINES += MESA_EGL_NO_X11_HEADERS
#To test the hooks on x11 (xlib), comment the above define too
#EGLFS_PLATFORM_HOOKS_SOURCES += qeglfshooks_x11.cpp
-#LIBS += -lX11
+#LIBS += -lX11 -lX11-xcb -lxcb
SOURCES += $$PWD/qeglfsintegration.cpp \
$$PWD/qeglfswindow.cpp \
diff --git a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp
index 5c264834b3..91a97ff977 100644
--- a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp
+++ b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qeglfshooks.h"
+#include "qeglfscursor.h"
#include <fcntl.h>
#include <unistd.h>
@@ -249,8 +250,7 @@ bool QEglFSHooks::hasCapability(QPlatformIntegration::Capability cap) const
QEglFSCursor *QEglFSHooks::createCursor(QEglFSScreen *screen) const
{
- Q_UNUSED(screen);
- return 0;
+ return new QEglFSCursor(screen);
}
void QEglFSHooks::waitForVSync() const
diff --git a/src/plugins/platforms/eglfs/qeglfshooks_x11.cpp b/src/plugins/platforms/eglfs/qeglfshooks_x11.cpp
index f44107e830..0d8be66438 100644
--- a/src/plugins/platforms/eglfs/qeglfshooks_x11.cpp
+++ b/src/plugins/platforms/eglfs/qeglfshooks_x11.cpp
@@ -41,13 +41,36 @@
#include "qeglfshooks.h"
+#include <qpa/qwindowsysteminterface.h>
+#include <QThread>
+
#include <X11/Xlib.h>
+#include <X11/Xlib-xcb.h>
+#include <xcb/xcb.h>
QT_BEGIN_NAMESPACE
+class EventReader : public QThread
+{
+public:
+ EventReader(xcb_connection_t *connection)
+ : m_connection(connection)
+ {
+ }
+
+ void run();
+
+ xcb_connection_t *connection() { return m_connection; }
+
+private:
+ xcb_connection_t *m_connection;
+};
+
class QEglFSX11Hooks : public QEglFSHooks
{
public:
+ QEglFSX11Hooks() : m_eventReader(0) {}
+
virtual void platformInit();
virtual void platformDestroy();
virtual EGLNativeDisplayType platformDisplay() const;
@@ -55,20 +78,151 @@ public:
virtual EGLNativeWindowType createNativeWindow(const QSize &size, const QSurfaceFormat &format);
virtual void destroyNativeWindow(EGLNativeWindowType window);
virtual bool hasCapability(QPlatformIntegration::Capability cap) const;
+
+private:
+ void sendConnectionEvent(xcb_atom_t a);
+
+ EventReader *m_eventReader;
+ xcb_connection_t *m_connection;
+ xcb_window_t m_connectionEventListener;
};
static Display *display = 0;
+QAtomicInt running;
+
+static Qt::MouseButtons translateMouseButtons(int s)
+{
+ Qt::MouseButtons ret = 0;
+ if (s & XCB_BUTTON_MASK_1)
+ ret |= Qt::LeftButton;
+ if (s & XCB_BUTTON_MASK_2)
+ ret |= Qt::MidButton;
+ if (s & XCB_BUTTON_MASK_3)
+ ret |= Qt::RightButton;
+ return ret;
+}
+
+static Qt::MouseButton translateMouseButton(xcb_button_t s)
+{
+ switch (s) {
+ case 1: return Qt::LeftButton;
+ case 2: return Qt::MidButton;
+ case 3: return Qt::RightButton;
+ // Button values 4-7 were already handled as Wheel events, and won't occur here.
+ case 8: return Qt::BackButton; // Also known as Qt::ExtraButton1
+ case 9: return Qt::ForwardButton; // Also known as Qt::ExtraButton2
+ case 10: return Qt::ExtraButton3;
+ case 11: return Qt::ExtraButton4;
+ case 12: return Qt::ExtraButton5;
+ case 13: return Qt::ExtraButton6;
+ case 14: return Qt::ExtraButton7;
+ case 15: return Qt::ExtraButton8;
+ case 16: return Qt::ExtraButton9;
+ case 17: return Qt::ExtraButton10;
+ case 18: return Qt::ExtraButton11;
+ case 19: return Qt::ExtraButton12;
+ case 20: return Qt::ExtraButton13;
+ case 21: return Qt::ExtraButton14;
+ case 22: return Qt::ExtraButton15;
+ case 23: return Qt::ExtraButton16;
+ case 24: return Qt::ExtraButton17;
+ case 25: return Qt::ExtraButton18;
+ case 26: return Qt::ExtraButton19;
+ case 27: return Qt::ExtraButton20;
+ case 28: return Qt::ExtraButton21;
+ case 29: return Qt::ExtraButton22;
+ case 30: return Qt::ExtraButton23;
+ case 31: return Qt::ExtraButton24;
+ default: return Qt::NoButton;
+ }
+}
+
+void EventReader::run()
+{
+ Qt::MouseButtons buttons;
+
+ xcb_generic_event_t *event;
+ while (running.load() && (event = xcb_wait_for_event(m_connection))) {
+ uint response_type = event->response_type & ~0x80;
+ switch (response_type) {
+ case XCB_BUTTON_PRESS: {
+ xcb_button_press_event_t *press = (xcb_button_press_event_t *)event;
+ QPoint p(press->event_x, press->event_y);
+ buttons = (buttons & ~0x7) | translateMouseButtons(press->state);
+ buttons |= translateMouseButton(press->detail);
+ QWindowSystemInterface::handleMouseEvent(0, press->time, p, p, buttons);
+ break;
+ }
+ case XCB_BUTTON_RELEASE: {
+ xcb_button_release_event_t *release = (xcb_button_release_event_t *)event;
+ QPoint p(release->event_x, release->event_y);
+ buttons = (buttons & ~0x7) | translateMouseButtons(release->state);
+ buttons &= ~translateMouseButton(release->detail);
+ QWindowSystemInterface::handleMouseEvent(0, release->time, p, p, buttons);
+ break;
+ }
+ case XCB_MOTION_NOTIFY: {
+ xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t *)event;
+ QPoint p(motion->event_x, motion->event_y);
+ QWindowSystemInterface::handleMouseEvent(0, motion->time, p, p, buttons);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+void QEglFSX11Hooks::sendConnectionEvent(xcb_atom_t a)
+{
+ xcb_client_message_event_t event;
+ memset(&event, 0, sizeof(event));
+
+ event.response_type = XCB_CLIENT_MESSAGE;
+ event.format = 32;
+ event.sequence = 0;
+ event.window = m_connectionEventListener;
+ event.type = a;
+
+ xcb_send_event(m_connection, false, m_connectionEventListener, XCB_EVENT_MASK_NO_EVENT, (const char *)&event);
+ xcb_flush(m_connection);
+}
+
void QEglFSX11Hooks::platformInit()
{
display = XOpenDisplay(NULL);
if (!display)
qFatal("Could not open display");
+ XSetEventQueueOwner(display, XCBOwnsEventQueue);
+
+ running.ref();
+
+ m_connection = XGetXCBConnection(display);
+
+ xcb_screen_iterator_t it = xcb_setup_roots_iterator(xcb_get_setup(m_connection));
+
+ m_connectionEventListener = xcb_generate_id(m_connection);
+ xcb_create_window(m_connection, XCB_COPY_FROM_PARENT,
+ m_connectionEventListener, it.data->root,
+ 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
+ it.data->root_visual, 0, 0);
+
+ m_eventReader = new EventReader(m_connection);
+ m_eventReader->start();
}
void QEglFSX11Hooks::platformDestroy()
{
+ running.deref();
+
+ sendConnectionEvent(XCB_ATOM_NONE);
+
XCloseDisplay(display);
+
+ m_eventReader->wait();
+ delete m_eventReader;
+ m_eventReader = 0;
}
EGLNativeDisplayType QEglFSX11Hooks::platformDisplay() const
@@ -91,10 +245,12 @@ EGLNativeWindowType QEglFSX11Hooks::createNativeWindow(const QSize &size, const
Window root = DefaultRootWindow(display);
XSetWindowAttributes swa;
memset(&swa, 0, sizeof(swa));
- Window win = XCreateWindow(display, root, 0, 0, size.width(), size.height(), 0, CopyFromParent,
- InputOutput, CopyFromParent, CWEventMask, &swa);
+ swa.event_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ButtonMotionMask;
+ Window win = XCreateWindow(display, root, 0, 0, size.width(), size.height(), 0, CopyFromParent,
+ InputOutput, CopyFromParent, CWEventMask, &swa);
XMapWindow(display, win);
XStoreName(display, win, "EGLFS");
+
return win;
}
diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
index 615b69f7d9..cf1503b7f9 100644
--- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
@@ -53,7 +53,7 @@
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
#include <QtPlatformSupport/private/qeglpbuffer_p.h>
-#if !defined(QT_NO_EVDEV) && !defined(Q_OS_ANDROID)
+#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
#include <QtPlatformSupport/private/qevdevmousemanager_p.h>
#include <QtPlatformSupport/private/qevdevkeyboardmanager_p.h>
#include <QtPlatformSupport/private/qevdevtouch_p.h>
@@ -79,7 +79,7 @@ QEglFSIntegration::QEglFSIntegration()
{
QGuiApplicationPrivate::instance()->setEventDispatcher(mEventDispatcher);
-#if !defined(QT_NO_EVDEV) && !defined(Q_OS_ANDROID)
+#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this);
new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this);
new QEvdevTouchScreenHandlerThread(QString() /* spec */, this);
diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/qeglfsscreen.cpp
index e104bd7f2b..6cb1f88c66 100644
--- a/src/plugins/platforms/eglfs/qeglfsscreen.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsscreen.cpp
@@ -55,12 +55,8 @@ QEglFSScreen::QEglFSScreen(EGLDisplay dpy)
#endif
static int hideCursor = qgetenv("QT_QPA_EGLFS_HIDECURSOR").toInt();
- if (!hideCursor) {
- if (QEglFSCursor *customCursor = QEglFSHooks::hooks()->createCursor(this))
- m_cursor = customCursor;
- else
- m_cursor = new QEglFSCursor(this);
- }
+ if (!hideCursor)
+ m_cursor = QEglFSHooks::hooks()->createCursor(this);
}
QEglFSScreen::~QEglFSScreen()
diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm
index 807c75df54..735dd26b6d 100644
--- a/src/plugins/platforms/ios/qioscontext.mm
+++ b/src/plugins/platforms/ios/qioscontext.mm
@@ -156,6 +156,9 @@ GLuint QIOSContext::defaultFramebufferObject(QPlatformSurface *surface) const
if (framebufferObject.renderbufferWidth != platformWindow->effectiveWidth() ||
framebufferObject.renderbufferHeight != platformWindow->effectiveHeight()) {
+ [EAGLContext setCurrentContext:m_eaglContext];
+ glBindFramebuffer(GL_FRAMEBUFFER, framebufferObject.handle);
+
glBindRenderbuffer(GL_RENDERBUFFER, framebufferObject.colorRenderbuffer);
UIView *view = reinterpret_cast<UIView *>(platformWindow->winId());
CAEAGLLayer *layer = static_cast<CAEAGLLayer *>(view.layer);
diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h
index b86dbf7d46..20f0aa59b6 100644
--- a/src/plugins/platforms/ios/qioswindow.h
+++ b/src/plugins/platforms/ios/qioswindow.h
@@ -82,15 +82,8 @@ public:
WId winId() const { return WId(m_view); };
- QList<QWindowSystemInterface::TouchPoint> &touchPoints() { return m_touchPoints; }
- QHash<UITouch *, int> &activeTouches() { return m_activeTouches; }
- int &touchId() { return m_touchId; }
-
private:
UIView *m_view;
- QList<QWindowSystemInterface::TouchPoint> m_touchPoints;
- QHash<UITouch *, int> m_activeTouches;
- int m_touchId;
QRect m_requestedGeometry;
int m_windowLevel;
diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm
index b173fb786f..02ac413b3b 100644
--- a/src/plugins/platforms/ios/qioswindow.mm
+++ b/src/plugins/platforms/ios/qioswindow.mm
@@ -68,6 +68,8 @@
UIReturnKeyType returnKeyType;
BOOL secureTextEntry;
QIOSWindow *m_qioswindow;
+ QHash<UITouch *, QWindowSystemInterface::TouchPoint> m_activeTouches;
+ int m_nextTouchId;
}
@property(nonatomic) UITextAutocapitalizationType autocapitalizationType;
@@ -113,6 +115,7 @@
keyboardType = UIKeyboardTypeDefault;
returnKeyType = UIReturnKeyDone;
secureTextEntry = NO;
+ m_nextTouchId = 0;
if (isQtApplication())
self.hidden = YES;
@@ -145,45 +148,25 @@
[super layoutSubviews];
}
-/*
- Touch handling:
-
- UIKit generates [Began -> Moved -> Ended] event sequences for
- each touch point. The iOS plugin tracks each individual
- touch and assigns it an id for use by Qt. The id counter is
- incremented on each began and decrement as follows:
- 1) by one when the most recent touch ends.
- 2) to zero when all touches ends.
-
- The TouchPoint list is reused between events.
-*/
- (void)updateTouchList:(NSSet *)touches withState:(Qt::TouchPointState)state
{
- QList<QWindowSystemInterface::TouchPoint> &touchPoints = m_qioswindow->touchPoints();
- QHash<UITouch *, int> &activeTouches = m_qioswindow->activeTouches();
-
- // Mark all touch points as stationary
- for (QList<QWindowSystemInterface::TouchPoint>::iterator it = touchPoints.begin(); it != touchPoints.end(); ++it)
- it->state = Qt::TouchPointStationary;
-
- // Update changed touch points with the new state
- for (UITouch *touch in touches) {
- const int touchId = activeTouches.value(touch);
- QWindowSystemInterface::TouchPoint &touchPoint = touchPoints[touchId];
- touchPoint.state = state;
- if (state == Qt::TouchPointPressed)
- touchPoint.pressure = 1.0;
- else if (state == Qt::TouchPointReleased)
- touchPoint.pressure = 0.0;
-
- // Set position
- QRect viewGeometry = fromCGRect(self.frame);
- QPoint touchViewLocation = fromCGPoint([touch locationInView:self]);
- QPoint touchScreenLocation = touchViewLocation + viewGeometry.topLeft();
- touchPoint.area = QRectF(touchScreenLocation , QSize(0, 0));
-
- CGSize fullscreenSize = self.window.rootViewController.view.bounds.size;
- touchPoint.normalPosition = QPointF(touchScreenLocation.x() / fullscreenSize.width, touchScreenLocation.y() / fullscreenSize.height);
+ QRect applicationRect = fromCGRect(self.window.screen.applicationFrame);
+
+ foreach (UITouch *uiTouch, m_activeTouches.keys()) {
+ QWindowSystemInterface::TouchPoint &touchPoint = m_activeTouches[uiTouch];
+ if (![touches containsObject:uiTouch]) {
+ touchPoint.state = Qt::TouchPointStationary;
+ } else {
+ touchPoint.state = state;
+ touchPoint.pressure = (state == Qt::TouchPointReleased) ? 0.0 : 1.0;
+
+ // Find the touch position relative to the window. Then calculate the screen
+ // position by subtracting the position of the applicationRect (since UIWindow
+ // does not take that into account when reporting its own frame):
+ QPoint touchPos = fromCGPoint([uiTouch locationInView:nil]);
+ touchPoint.area = QRectF(touchPos - applicationRect.topLeft(), QSize(0, 0));
+ touchPoint.normalPosition = QPointF(touchPos.x() / applicationRect.width(), touchPos.y() / applicationRect.height());
+ }
}
}
@@ -191,8 +174,7 @@
{
// Send touch event synchronously
QIOSIntegration *iosIntegration = static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
- QWindowSystemInterface::handleTouchEvent(m_qioswindow->window(), timeStamp,
- iosIntegration->touchDevice(), m_qioswindow->touchPoints());
+ QWindowSystemInterface::handleTouchEvent(m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values());
QWindowSystemInterface::flushWindowSystemEvents();
}
@@ -204,19 +186,13 @@
if (window != QGuiApplication::focusWindow())
m_qioswindow->requestActivateWindow();
- // Track Cocoa touch id to Qt touch id. The UITouch pointer is constant
- // for the touch duration.
- QHash<UITouch *, int> &activeTouches = m_qioswindow->activeTouches();
- QList<QWindowSystemInterface::TouchPoint> &touchPoints = m_qioswindow->touchPoints();
- for (UITouch *touch in touches)
- activeTouches.insert(touch, m_qioswindow->touchId()++);
-
- // Create new touch points if needed.
- int newTouchPointsNeeded = m_qioswindow->touchId() - touchPoints.count();
- for (int i = 0; i < newTouchPointsNeeded; ++i) {
- QWindowSystemInterface::TouchPoint touchPoint;
- touchPoint.id = touchPoints.count(); // id is the index in the touchPoints list.
- touchPoints.append(touchPoint);
+ // UIKit generates [Began -> Moved -> Ended] event sequences for
+ // each touch point. Internally we keep a hashmap of active UITouch
+ // points to QWindowSystemInterface::TouchPoints, and assigns each TouchPoint
+ // an id for use by Qt.
+ for (UITouch *touch in touches) {
+ Q_ASSERT(!m_activeTouches.contains(touch));
+ m_activeTouches[touch].id = m_nextTouchId++;
}
[self updateTouchList:touches withState:Qt::TouchPointPressed];
@@ -234,19 +210,11 @@
[self updateTouchList:touches withState:Qt::TouchPointReleased];
[self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
- // Remove ended touch points from the active set (event processing has completed at this point)
- QHash<UITouch *, int> &activeTouches = m_qioswindow->activeTouches();
- for (UITouch *touch in touches) {
- int id = activeTouches.take(touch);
-
- // If this touch is the most recent touch we can reuse its id
- if (id == m_qioswindow->touchId() - 1)
- --m_qioswindow->touchId();
- }
-
- // Reset the touch id when there are no more active touches
- if (activeTouches.isEmpty())
- m_qioswindow->touchId() = 0;
+ // Remove ended touch points from the active set:
+ for (UITouch *touch in touches)
+ m_activeTouches.remove(touch);
+ if (m_activeTouches.isEmpty())
+ m_nextTouchId = 0;
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
@@ -254,8 +222,8 @@
Q_UNUSED(touches) // ### can a subset of the active touches be cancelled?
// Clear current touch points
- m_qioswindow->activeTouches().clear();
- m_qioswindow->touchId() = 0;
+ m_activeTouches.clear();
+ m_nextTouchId = 0;
// Send cancel touch event synchronously
QIOSIntegration *iosIntegration = static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
@@ -322,7 +290,6 @@ QT_BEGIN_NAMESPACE
QIOSWindow::QIOSWindow(QWindow *window)
: QPlatformWindow(window)
, m_view([[EAGLView alloc] initWithQIOSWindow:this])
- , m_touchId(0)
, m_requestedGeometry(QPlatformWindow::geometry())
, m_windowLevel(0)
, m_devicePixelRatio(1.0)
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
index cd987d8d02..ad5206ba41 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
+++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
@@ -369,9 +369,10 @@ bool QLinuxFbScreen::initialize(const QStringList &args)
mDepth = determineDepth(vinfo);
mBytesPerLine = finfo.line_length;
- mGeometry = determineGeometry(vinfo, userGeometry);
+ QRect geometry = determineGeometry(vinfo, userGeometry);
+ mGeometry = QRect(QPoint(0, 0), geometry.size());
mFormat = determineFormat(vinfo, mDepth);
- mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, mGeometry.size());
+ mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, geometry.size());
// mmap the framebuffer
mMmap.size = finfo.smem_len;
@@ -381,11 +382,11 @@ bool QLinuxFbScreen::initialize(const QStringList &args)
return false;
}
- mMmap.offset = mGeometry.y() * mBytesPerLine + mGeometry.x() * mDepth / 8;
+ mMmap.offset = geometry.y() * mBytesPerLine + geometry.x() * mDepth / 8;
mMmap.data = data + mMmap.offset;
QFbScreen::initializeCompositor();
- mFbScreenImage = QImage(data, mGeometry.width(), mGeometry.height(), mBytesPerLine, mFormat);
+ mFbScreenImage = QImage(mMmap.data, geometry.width(), geometry.height(), mBytesPerLine, mFormat);
mCursor = new QFbCursor(this);
mTtyFd = openTtyDevice(ttyDevice);
diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro
index 50884ace66..7c497b4434 100644
--- a/src/plugins/platforms/qnx/qnx.pro
+++ b/src/plugins/platforms/qnx/qnx.pro
@@ -1,6 +1,6 @@
TARGET = qqnx
-QT += platformsupport platformsupport-private
+QT += platformsupport-private core-private gui-private
# Uncomment this to build with support for IMF once it becomes available in the BBNDK
#CONFIG += qqnx_imf
diff --git a/src/plugins/platforms/qnx/qqnxbuffer.cpp b/src/plugins/platforms/qnx/qqnxbuffer.cpp
index c5e99a2001..abb8a07026 100644
--- a/src/plugins/platforms/qnx/qqnxbuffer.cpp
+++ b/src/plugins/platforms/qnx/qqnxbuffer.cpp
@@ -69,36 +69,31 @@ QQnxBuffer::QQnxBuffer(screen_buffer_t buffer)
errno = 0;
int size[2];
int result = screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_BUFFER_SIZE, size);
- if (result != 0) {
+ if (result != 0)
qFatal("QQNX: failed to query buffer size, errno=%d", errno);
- }
// Get stride of buffer
errno = 0;
int stride;
result = screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_STRIDE, &stride);
- if (result != 0) {
+ if (result != 0)
qFatal("QQNX: failed to query buffer stride, errno=%d", errno);
- }
// Get access to buffer's data
errno = 0;
uchar *dataPtr = 0;
result = screen_get_buffer_property_pv(buffer, SCREEN_PROPERTY_POINTER, (void **)&dataPtr);
- if (result != 0) {
+ if (result != 0)
qFatal("QQNX: failed to query buffer pointer, errno=%d", errno);
- }
- if (dataPtr == 0) {
+ if (dataPtr == 0)
qFatal("QQNX: buffer pointer is NULL, errno=%d", errno);
- }
// Get format of buffer
errno = 0;
int screenFormat;
result = screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_FORMAT, &screenFormat);
- if (result != 0) {
+ if (result != 0)
qFatal("QQNX: failed to query buffer format, errno=%d", errno);
- }
// Convert screen format to QImage format
QImage::Format imageFormat = QImage::Format_Invalid;
@@ -146,16 +141,14 @@ void QQnxBuffer::invalidateInCache()
qBufferDebug() << Q_FUNC_INFO;
// Verify native buffer exists
- if (m_buffer == 0) {
+ if (m_buffer == 0)
qFatal("QQNX: can't invalidate cache for null buffer");
- }
// Evict buffer's data from cache
errno = 0;
int result = msync(m_image.bits(), m_image.height() * m_image.bytesPerLine(), MS_INVALIDATE | MS_CACHE_ONLY);
- if (result != 0) {
+ if (result != 0)
qFatal("QQNX: failed to invalidate cache, errno=%d", errno);
- }
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxglcontext.cpp b/src/plugins/platforms/qnx/qqnxglcontext.cpp
index f77bb73614..005b6d272a 100644
--- a/src/plugins/platforms/qnx/qqnxglcontext.cpp
+++ b/src/plugins/platforms/qnx/qqnxglcontext.cpp
@@ -96,9 +96,8 @@ QQnxGLContext::QQnxGLContext(QOpenGLContext *glContext)
// Set current rendering API
EGLBoolean eglResult = eglBindAPI(EGL_OPENGL_ES_API);
- if (eglResult != EGL_TRUE) {
+ if (eglResult != EGL_TRUE)
qFatal("QQNX: failed to set EGL API, err=%d", eglGetError());
- }
// Get colour channel sizes from window format
int alphaSize = format.alphaBufferSize();
@@ -149,9 +148,8 @@ QQnxGLContext::QQnxGLContext(QOpenGLContext *glContext)
// Select EGL config based on requested window format
m_eglConfig = q_configFromGLFormat(ms_eglDisplay, format);
- if (m_eglConfig == 0) {
+ if (m_eglConfig == 0)
qFatal("QQnxGLContext: failed to find EGL config");
- }
m_eglContext = eglCreateContext(ms_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, contextAttrs());
if (m_eglContext == EGL_NO_CONTEXT) {
@@ -168,9 +166,8 @@ QQnxGLContext::~QQnxGLContext()
qGLContextDebug() << Q_FUNC_INFO;
// Cleanup EGL context if it exists
- if (m_eglContext != EGL_NO_CONTEXT) {
+ if (m_eglContext != EGL_NO_CONTEXT)
eglDestroyContext(ms_eglDisplay, m_eglContext);
- }
// Cleanup EGL surface if it exists
destroySurface();
@@ -216,9 +213,8 @@ bool QQnxGLContext::makeCurrent(QPlatformSurface *surface)
// Set current rendering API
EGLBoolean eglResult = eglBindAPI(EGL_OPENGL_ES_API);
- if (eglResult != EGL_TRUE) {
+ if (eglResult != EGL_TRUE)
qFatal("QQnxGLContext: failed to set EGL API, err=%d", eglGetError());
- }
if (m_newSurfaceRequested.testAndSetOrdered(true, false)) {
qGLContextDebug() << "New EGL surface requested";
@@ -241,15 +237,13 @@ void QQnxGLContext::doneCurrent()
// set current rendering API
EGLBoolean eglResult = eglBindAPI(EGL_OPENGL_ES_API);
- if (eglResult != EGL_TRUE) {
+ if (eglResult != EGL_TRUE)
qFatal("QQNX: failed to set EGL API, err=%d", eglGetError());
- }
// clear curent EGL context and unbind EGL surface
eglResult = eglMakeCurrent(ms_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- if (eglResult != EGL_TRUE) {
+ if (eglResult != EGL_TRUE)
qFatal("QQNX: failed to clear current EGL context, err=%d", eglGetError());
- }
}
void QQnxGLContext::swapBuffers(QPlatformSurface *surface)
@@ -259,15 +253,13 @@ void QQnxGLContext::swapBuffers(QPlatformSurface *surface)
// Set current rendering API
EGLBoolean eglResult = eglBindAPI(EGL_OPENGL_ES_API);
- if (eglResult != EGL_TRUE) {
+ if (eglResult != EGL_TRUE)
qFatal("QQNX: failed to set EGL API, err=%d", eglGetError());
- }
// Post EGL surface to window
eglResult = eglSwapBuffers(ms_eglDisplay, m_eglSurface);
- if (eglResult != EGL_TRUE) {
+ if (eglResult != EGL_TRUE)
qFatal("QQNX: failed to swap EGL buffers, err=%d", eglGetError());
- }
}
QFunctionPointer QQnxGLContext::getProcAddress(const QByteArray &procName)
@@ -276,9 +268,8 @@ QFunctionPointer QQnxGLContext::getProcAddress(const QByteArray &procName)
// Set current rendering API
EGLBoolean eglResult = eglBindAPI(EGL_OPENGL_ES_API);
- if (eglResult != EGL_TRUE) {
+ if (eglResult != EGL_TRUE)
qFatal("QQNX: failed to set EGL API, err=%d", eglGetError());
- }
// Lookup EGL extension function pointer
return static_cast<QFunctionPointer>(eglGetProcAddress(procName.constData()));
@@ -309,9 +300,8 @@ void QQnxGLContext::createSurface(QPlatformSurface *surface)
// Get a pointer to the corresponding platform window
QQnxWindow *platformWindow = dynamic_cast<QQnxWindow*>(surface);
- if (!platformWindow) {
+ if (!platformWindow)
qFatal("QQNX: unable to create EGLSurface without a QQnxWindow");
- }
// Link the window and context
platformWindow->setPlatformOpenGLContext(this);
diff --git a/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp b/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp
index 97a361158e..580553f6e2 100644
--- a/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp
+++ b/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp
@@ -606,12 +606,10 @@ static bool imfAvailable()
static bool s_imfDisabled = getenv("DISABLE_IMF") != 0;
static bool s_imfReady = false;
- if ( s_imfInitFailed || s_imfDisabled) {
+ if ( s_imfInitFailed || s_imfDisabled)
return false;
- }
- else if ( s_imfReady ) {
+ else if ( s_imfReady )
return true;
- }
if ( p_imf_client_init == 0 ) {
void *handle = dlopen("libinput_client.so.1", 0);
@@ -623,17 +621,15 @@ static bool imfAvailable()
p_ictrl_dispatch_event = (int32_t (*)(event_t *))dlsym(handle, "ictrl_dispatch_event");
p_vkb_init_selection_service = (int32_t (*)())dlsym(handle, "vkb_init_selection_service");
p_ictrl_get_num_active_sessions = (int32_t (*)())dlsym(handle, "ictrl_get_num_active_sessions");
- }
- else
- {
+ } else {
qCritical() << Q_FUNC_INFO << "libinput_client.so.1 is not present - IMF services are disabled.";
s_imfDisabled = true;
return false;
}
+
if ( p_imf_client_init && p_ictrl_open_session && p_ictrl_dispatch_event ) {
s_imfReady = true;
- }
- else {
+ } else {
p_ictrl_open_session = 0;
p_ictrl_dispatch_event = 0;
s_imfDisabled = true;
@@ -1400,11 +1396,10 @@ spannable_string_t *QQnxInputContext::onGetTextBeforeCursor(input_session_t *ic,
QString text = query.value(Qt::ImSurroundingText).toString();
m_lastCaretPos = query.value(Qt::ImCursorPosition).toInt();
- if (n < m_lastCaretPos) {
+ if (n < m_lastCaretPos)
return toSpannableString(text.mid(m_lastCaretPos - n, n));
- } else {
+ else
return toSpannableString(text.mid(0, m_lastCaretPos));
- }
}
int32_t QQnxInputContext::onPerformEditorAction(input_session_t *ic, int32_t editor_action)
diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp
index 00706f715d..a933f7d571 100644
--- a/src/plugins/platforms/qnx/qqnxintegration.cpp
+++ b/src/plugins/platforms/qnx/qqnxintegration.cpp
@@ -155,9 +155,8 @@ QQnxIntegration::QQnxIntegration(const QStringList &paramList)
// Open connection to QNX composition manager
errno = 0;
int result = screen_create_context(&m_screenContext, SCREEN_APPLICATION_CONTEXT);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnx: failed to connect to composition manager, errno=%d", errno);
- }
// Not on BlackBerry, it has specialized event dispatcher which also handles navigator events
#if !defined(Q_OS_BLACKBERRY) && defined(QQNX_PPS)
@@ -388,9 +387,8 @@ QPlatformClipboard *QQnxIntegration::clipboard() const
qIntegrationDebug() << Q_FUNC_INFO;
#if defined(QQNX_PPS)
- if (!m_clipboard) {
+ if (!m_clipboard)
m_clipboard = new QQnxClipboard;
- }
#endif
return m_clipboard;
}
@@ -463,9 +461,8 @@ void QQnxIntegration::createDisplays()
errno = 0;
int displayCount;
int result = screen_get_context_property_iv(m_screenContext, SCREEN_PROPERTY_DISPLAY_COUNT, &displayCount);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxIntegration: failed to query display count, errno=%d", errno);
- }
if (displayCount < 1) {
// Never happens, even if there's no display, libscreen returns 1
@@ -476,9 +473,8 @@ void QQnxIntegration::createDisplays()
errno = 0;
screen_display_t *displays = (screen_display_t *)alloca(sizeof(screen_display_t) * displayCount);
result = screen_get_context_property_pv(m_screenContext, SCREEN_PROPERTY_DISPLAYS, (void **)displays);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxIntegration: failed to query displays, errno=%d", errno);
- }
// If it's primary, we create a QScreen for it even if it's not attached
// since Qt will dereference QGuiApplication::primaryScreen()
diff --git a/src/plugins/platforms/qnx/qqnxnavigatorpps.cpp b/src/plugins/platforms/qnx/qqnxnavigatorpps.cpp
index 1656ab029b..c5c40f5a23 100644
--- a/src/plugins/platforms/qnx/qqnxnavigatorpps.cpp
+++ b/src/plugins/platforms/qnx/qqnxnavigatorpps.cpp
@@ -150,9 +150,8 @@ void QQnxNavigatorPps::parsePPS(const QByteArray &ppsData, QHash<QByteArray, QBy
QList<QByteArray> lines = ppsData.split('\n');
// validate pps object
- if (lines.size() == 0 || lines.at(0) != "@control") {
+ if (lines.size() == 0 || lines.at(0) != "@control")
qFatal("QQNX: unrecognized pps object, data=%s", ppsData.constData());
- }
// parse pps object attributes and extract values
for (int i = 1; i < lines.size(); i++) {
diff --git a/src/plugins/platforms/qnx/qqnxrootwindow.cpp b/src/plugins/platforms/qnx/qqnxrootwindow.cpp
index 198801a832..dddadb5ca8 100644
--- a/src/plugins/platforms/qnx/qqnxrootwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxrootwindow.cpp
@@ -68,17 +68,15 @@ QQnxRootWindow::QQnxRootWindow(const QQnxScreen *screen)
errno = 0;
int result = screen_create_window(&m_window, m_screen->nativeContext());
int val[2];
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxRootWindow: failed to create window, errno=%d", errno);
- }
// Move window to proper display
errno = 0;
screen_display_t display = m_screen->nativeDisplay();
result = screen_set_window_property_pv(m_window, SCREEN_PROPERTY_DISPLAY, (void **)&display);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxRootWindow: failed to set window display, errno=%d", errno);
- }
// Make sure window is above navigator but below keyboard if running as root
// since navigator won't automatically set our z-order in this case
@@ -86,39 +84,34 @@ QQnxRootWindow::QQnxRootWindow(const QQnxScreen *screen)
errno = 0;
val[0] = MAGIC_ZORDER_FOR_NO_NAV;
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_ZORDER, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxRootWindow: failed to set window z-order, errno=%d", errno);
- }
}
// Window won't be visible unless it has some buffers so make one dummy buffer that is 1x1
errno = 0;
val[0] = SCREEN_USAGE_NATIVE;
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_USAGE, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxRootWindow: failed to set window buffer usage, errno=%d", errno);
- }
errno = 0;
val[0] = m_screen->nativeFormat();
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_FORMAT, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxRootWindow: failed to set window pixel format, errno=%d", errno);
- }
errno = 0;
val[0] = 1;
val[1] = 1;
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_BUFFER_SIZE, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxRootWindow: failed to set window buffer size, errno=%d", errno);
- }
errno = 0;
result = screen_create_window_buffers(m_window, 1);
- if (result != 0) {
+ if (result != 0)
qFatal("QQNX: failed to create window buffer, errno=%d", errno);
- }
// Window is always the size of the display
errno = 0;
@@ -126,50 +119,44 @@ QQnxRootWindow::QQnxRootWindow(const QQnxScreen *screen)
val[0] = geometry.width();
val[1] = geometry.height();
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SIZE, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxRootWindow: failed to set window size, errno=%d", errno);
- }
// Fill the window with solid black
errno = 0;
val[0] = 0;
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_COLOR, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxRootWindow: failed to set window colour, errno=%d", errno);
- }
// Make the window opaque
errno = 0;
val[0] = SCREEN_TRANSPARENCY_NONE;
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_TRANSPARENCY, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxRootWindow: failed to set window transparency, errno=%d", errno);
- }
// Set the swap interval to 1
errno = 0;
val[0] = 1;
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SWAP_INTERVAL, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxRootWindow: failed to set window swap interval, errno=%d", errno);
- }
// Set viewport size equal to window size but move outside buffer so the fill colour is used exclusively
errno = 0;
val[0] = geometry.width();
val[1] = geometry.height();
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SOURCE_SIZE, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxRootWindow: failed to set window source size, errno=%d", errno);
- }
errno = 0;
val[0] = 1;
val[1] = 0;
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SOURCE_POSITION, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxRootWindow: failed to set window source position, errno=%d", errno);
- }
createWindowGroup();
post();
@@ -187,16 +174,14 @@ void QQnxRootWindow::post() const
errno = 0;
screen_buffer_t buffer;
int result = screen_get_window_property_pv(m_window, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)&buffer);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxRootWindow: failed to query window buffer, errno=%d", errno);
- }
errno = 0;
int dirtyRect[] = {0, 0, 1, 1};
result = screen_post_window(m_window, buffer, 1, dirtyRect, 0);
- if (result != 0) {
+ if (result != 0)
qFatal("QQNX: failed to post window buffer, errno=%d", errno);
- }
}
void QQnxRootWindow::flush() const
@@ -205,9 +190,8 @@ void QQnxRootWindow::flush() const
// Force immediate display update
errno = 0;
int result = screen_flush_context(m_screen->nativeContext(), 0);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxRootWindow: failed to flush context, errno=%d", errno);
- }
}
void QQnxRootWindow::setRotation(int rotation)
@@ -215,9 +199,8 @@ void QQnxRootWindow::setRotation(int rotation)
qRootWindowDebug() << Q_FUNC_INFO << "angle =" << rotation;
errno = 0;
int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_ROTATION, &rotation);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxRootWindow: failed to set window rotation, errno=%d", errno);
- }
}
void QQnxRootWindow::resize(const QSize &size)
@@ -225,15 +208,13 @@ void QQnxRootWindow::resize(const QSize &size)
errno = 0;
int val[] = {size.width(), size.height()};
int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SIZE, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxRootWindow: failed to set window size, errno=%d", errno);
- }
errno = 0;
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SOURCE_SIZE, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxRootWindow: failed to set window source size, errno=%d", errno);
- }
// NOTE: display will update when child windows relayout and repaint
}
@@ -246,7 +227,6 @@ void QQnxRootWindow::createWindowGroup()
// Create window group so child windows can be parented by container window
errno = 0;
int result = screen_create_window_group(m_window, m_windowGroupName.constData());
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxRootWindow: failed to create app window group, errno=%d", errno);
- }
}
diff --git a/src/plugins/platforms/qnx/qqnxscreen.cpp b/src/plugins/platforms/qnx/qqnxscreen.cpp
index 2b81559ab6..f8203b2329 100644
--- a/src/plugins/platforms/qnx/qqnxscreen.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreen.cpp
@@ -118,18 +118,17 @@ QQnxScreen::QQnxScreen(screen_context_t screenContext, screen_display_t display,
// Cache initial orientation of this display
errno = 0;
int result = screen_get_display_property_iv(m_display, SCREEN_PROPERTY_ROTATION, &m_initialRotation);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxScreen: failed to query display rotation, errno=%d", errno);
- }
+
m_currentRotation = m_initialRotation;
// Cache size of this display in pixels
errno = 0;
int val[2];
result = screen_get_display_property_iv(m_display, SCREEN_PROPERTY_SIZE, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxScreen: failed to query display size, errno=%d", errno);
- }
m_currentGeometry = m_initialGeometry = QRect(0, 0, val[0], val[1]);
@@ -165,9 +164,8 @@ static int defaultDepth()
// check if display depth was specified in environment variable;
// use default value if no valid value found
defaultDepth = qgetenv("QQNX_DISPLAY_DEPTH").toInt();
- if (defaultDepth != 16 && defaultDepth != 32) {
+ if (defaultDepth != 16 && defaultDepth != 32)
defaultDepth = 32;
- }
}
return defaultDepth;
}
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
index 57cfdc5eb6..c2d0e3e41c 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
@@ -90,9 +90,8 @@ bool QQnxScreenEventHandler::handleEvent(screen_event_t event)
errno = 0;
int qnxType;
int result = screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &qnxType);
- if (result) {
+ if (result)
qFatal("QQNX: failed to query event type, errno=%d", errno);
- }
return handleEvent(event, qnxType);
}
@@ -161,9 +160,8 @@ void QQnxScreenEventHandler::injectKeyboardEvent(int flags, int sym, int modifie
if ( qtMod & Qt::ControlModifier ) {
keyStr = QChar((int)(key & 0x3f));
} else {
- if (flags & KEY_SYM_VALID) {
+ if (flags & KEY_SYM_VALID)
keyStr = QChar(sym);
- }
}
} else if ((cap > 0x0ff && cap < UNICODE_PRIVATE_USE_AREA_FIRST) || cap > UNICODE_PRIVATE_USE_AREA_LAST) {
key = (Qt::Key)cap;
@@ -186,35 +184,30 @@ void QQnxScreenEventHandler::handleKeyboardEvent(screen_event_t event)
errno = 0;
int flags;
int result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_FLAGS, &flags);
- if (result) {
+ if (result)
qFatal("QQNX: failed to query event flags, errno=%d", errno);
- }
// get key code
errno = 0;
int sym;
result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_SYM, &sym);
- if (result) {
+ if (result)
qFatal("QQNX: failed to query event sym, errno=%d", errno);
- }
int modifiers;
result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_MODIFIERS, &modifiers);
- if (result) {
+ if (result)
qFatal("QQNX: failed to query event modifiers, errno=%d", errno);
- }
int scan;
result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_SCAN, &scan);
- if (result) {
+ if (result)
qFatal("QQNX: failed to query event modifiers, errno=%d", errno);
- }
int cap;
result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_CAP, &cap);
- if (result) {
+ if (result)
qFatal("QQNX: failed to query event cap, errno=%d", errno);
- }
injectKeyboardEvent(flags, sym, modifiers, scan, cap);
}
@@ -227,38 +220,34 @@ void QQnxScreenEventHandler::handlePointerEvent(screen_event_t event)
screen_window_t qnxWindow;
void *handle;
int result = screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, &handle);
- if (result) {
+ if (result)
qFatal("QQNX: failed to query event window, errno=%d", errno);
- }
+
qnxWindow = static_cast<screen_window_t>(handle);
// Query the button states
int buttonState = 0;
result = screen_get_event_property_iv(event, SCREEN_PROPERTY_BUTTONS, &buttonState);
- if (result) {
+ if (result)
qFatal("QQNX: failed to query event button state, errno=%d", errno);
- }
// Query the window position
int windowPos[2];
result = screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, windowPos);
- if (result) {
+ if (result)
qFatal("QQNX: failed to query event window position, errno=%d", errno);
- }
// Query the screen position
int pos[2];
result = screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, pos);
- if (result) {
+ if (result)
qFatal("QQNX: failed to query event position, errno=%d", errno);
- }
// Query the wheel delta
int wheelDelta = 0;
result = screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_WHEEL, &wheelDelta);
- if (result) {
+ if (result)
qFatal("QQNX: failed to query event wheel delta, errno=%d", errno);
- }
// Map window handle to top-level QWindow
QWindow *w = QQnxIntegration::window(qnxWindow);
@@ -343,9 +332,8 @@ void QQnxScreenEventHandler::handleTouchEvent(screen_event_t event, int qnxType)
errno = 0;
int pos[2];
int result = screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, pos);
- if (result) {
+ if (result)
qFatal("QQNX: failed to query event position, errno=%d", errno);
- }
QCursor::setPos(pos[0], pos[1]);
@@ -353,25 +341,23 @@ void QQnxScreenEventHandler::handleTouchEvent(screen_event_t event, int qnxType)
errno = 0;
int windowPos[2];
result = screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, windowPos);
- if (result) {
+ if (result)
qFatal("QQNX: failed to query event window position, errno=%d", errno);
- }
// determine which finger touched
errno = 0;
int touchId;
result = screen_get_event_property_iv(event, SCREEN_PROPERTY_TOUCH_ID, &touchId);
- if (result) {
+ if (result)
qFatal("QQNX: failed to query event touch id, errno=%d", errno);
- }
// determine which window was touched
errno = 0;
void *handle;
result = screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, &handle);
- if (result) {
+ if (result)
qFatal("QQNX: failed to query event window, errno=%d", errno);
- }
+
screen_window_t qnxWindow = static_cast<screen_window_t>(handle);
// check if finger is valid
@@ -454,9 +440,8 @@ void QQnxScreenEventHandler::handleCloseEvent(screen_event_t event)
// Map window handle to top-level QWindow
QWindow *w = QQnxIntegration::window(window);
- if (w != 0) {
+ if (w != 0)
QWindowSystemInterface::handleCloseEvent(w);
- }
}
void QQnxScreenEventHandler::handleCreateEvent(screen_event_t event)
diff --git a/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp b/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp
index e810b47c22..20fce3da70 100644
--- a/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp
+++ b/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp
@@ -209,13 +209,14 @@ void QQnxVirtualKeyboardPps::ppsDataReady()
}
if (pps_decoder_get_string(m_decoder, "msg", &value) == PPS_DECODER_OK) {
- if (strcmp(value, "show") == 0) {
+ if (strcmp(value, "show") == 0)
setVisible(true);
- } else if (strcmp(value, "hide") == 0) {
+ else if (strcmp(value, "hide") == 0)
setVisible(false);
- } else if (strcmp(value, "info") == 0)
+ else if (strcmp(value, "info") == 0)
handleKeyboardInfoMessage();
- else if (strcmp(value, "connect") == 0) { }
+ else if (strcmp(value, "connect") == 0)
+ qVirtualKeyboardDebug() << Q_FUNC_INFO << "Unhandled command 'connect'";
else
qCritical("QQnxVirtualKeyboard: Unexpected keyboard PPS msg value: %s", value ? value : "[null]");
} else if (pps_decoder_get_string(m_decoder, "res", &value) == PPS_DECODER_OK) {
@@ -223,8 +224,9 @@ void QQnxVirtualKeyboardPps::ppsDataReady()
handleKeyboardInfoMessage();
else
qCritical("QQnxVirtualKeyboard: Unexpected keyboard PPS res value: %s", value ? value : "[null]");
- } else
+ } else {
qCritical("QQnxVirtualKeyboard: Unexpected keyboard PPS message type");
+ }
}
void QQnxVirtualKeyboardPps::handleKeyboardInfoMessage()
@@ -368,9 +370,8 @@ void QQnxVirtualKeyboardPps::applyKeyboardModeOptions(KeyboardMode mode)
pps_encoder_end_object(m_encoder);
- if (::write(m_fd, pps_encoder_buffer(m_encoder), pps_encoder_length(m_encoder)) == -1) {
+ if (::write(m_fd, pps_encoder_buffer(m_encoder), pps_encoder_length(m_encoder)) == -1)
close();
- }
pps_encoder_reset(m_encoder);
}
diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp
index 2bcc11f0b0..6992d70fb1 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxwindow.cpp
@@ -87,9 +87,8 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context)
// Create child QNX window
errno = 0;
result = screen_create_window_type(&m_window, m_screenContext, SCREEN_CHILD_WINDOW);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxWindow: failed to create window, errno=%d", errno);
- }
// Set window buffer usage based on rendering API
int val;
@@ -108,32 +107,36 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context)
errno = 0;
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_USAGE, &val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxWindow: failed to set window buffer usage, errno=%d", errno);
- }
// Alpha channel is always pre-multiplied if present
errno = 0;
val = SCREEN_PRE_MULTIPLIED_ALPHA;
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_ALPHA_MODE, &val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxWindow: failed to set window alpha mode, errno=%d", errno);
- }
// Make the window opaque
errno = 0;
val = SCREEN_TRANSPARENCY_NONE;
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_TRANSPARENCY, &val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxWindow: failed to set window transparency, errno=%d", errno);
- }
// Set the window swap interval
errno = 0;
val = 1;
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SWAP_INTERVAL, &val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxWindow: failed to set window swap interval, errno=%d", errno);
+
+ if (window->flags() && Qt::WindowDoesNotAcceptFocus) {
+ errno = 0;
+ val = SCREEN_SENSITIVITY_NO_FOCUS;
+ result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SENSITIVITY, &val);
+ if (result != 0)
+ qFatal("QQnxWindow: failed to set window sensitivity, errno=%d", errno);
}
setScreen(static_cast<QQnxScreen *>(window->screen()->handle()));
@@ -219,24 +222,21 @@ QRect QQnxWindow::setGeometryHelper(const QRect &rect)
val[0] = rect.x();
val[1] = rect.y();
int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_POSITION, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxWindow: failed to set window position, errno=%d", errno);
- }
errno = 0;
val[0] = rect.width();
val[1] = rect.height();
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SIZE, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxWindow: failed to set window size, errno=%d", errno);
- }
// Set viewport size equal to window size
errno = 0;
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SOURCE_SIZE, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxWindow: failed to set window source size, errno=%d", errno);
- }
return oldGeometry;
}
@@ -257,9 +257,8 @@ void QQnxWindow::setOffset(const QPoint &offset)
val[0] = newGeometry.x();
val[1] = newGeometry.y();
int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_POSITION, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxWindow: failed to set window position, errno=%d", errno);
- }
Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
childWindow->setOffset(offset);
@@ -296,9 +295,8 @@ void QQnxWindow::updateVisibility(bool parentVisible)
errno = 0;
int val = (m_visible && parentVisible) ? 1 : 0;
int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_VISIBLE, &val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxWindow: failed to set window visibility, errno=%d", errno);
- }
Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
childWindow->updateVisibility(m_visible && parentVisible);
@@ -311,9 +309,8 @@ void QQnxWindow::setOpacity(qreal level)
errno = 0;
int val = (int)(level * 255);
int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_GLOBAL_ALPHA, &val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxWindow: failed to set window global alpha, errno=%d", errno);
- }
// TODO: How to handle children of this window? If we change all the visibilities, then
// the transparency will look wrong...
@@ -352,9 +349,8 @@ void QQnxWindow::setBufferSize(const QSize &size)
int val[2] = { nonEmptySize.width(), nonEmptySize.height() };
int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_BUFFER_SIZE, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxWindow: failed to set window buffer size, errno=%d", errno);
- }
// Create window buffers if they do not exist
if (m_bufferSize.isEmpty()) {
@@ -362,31 +358,27 @@ void QQnxWindow::setBufferSize(const QSize &size)
#if !defined(QT_NO_OPENGL)
// Get pixel format from EGL config if using OpenGL;
// otherwise inherit pixel format of window's screen
- if (m_platformOpenGLContext != 0) {
+ if (m_platformOpenGLContext != 0)
val[0] = platformWindowFormatToNativeFormat(m_platformOpenGLContext->format());
- }
#endif
errno = 0;
result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_FORMAT, val);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxWindow: failed to set window pixel format, errno=%d", errno);
- }
errno = 0;
result = screen_create_window_buffers(m_window, MAX_BUFFER_COUNT);
- if (result != 0) {
+ if (result != 0)
qWarning() << "QQnxWindow: Buffer size was" << size;
qFatal("QQnxWindow: failed to create window buffers, errno=%d", errno);
- }
// check if there are any buffers available
int bufferCount = 0;
result = screen_get_window_property_iv(m_window, SCREEN_PROPERTY_RENDER_BUFFER_COUNT, &bufferCount);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxWindow: failed to query window buffer count, errno=%d", errno);
- }
if (bufferCount != MAX_BUFFER_COUNT) {
qFatal("QQnxWindow: invalid buffer count. Expected = %d, got = %d. You might experience problems.",
@@ -416,9 +408,8 @@ QQnxBuffer &QQnxWindow::renderBuffer()
errno = 0;
screen_buffer_t buffers[MAX_BUFFER_COUNT];
const int result = screen_get_window_property_pv(m_window, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)buffers);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxWindow: failed to query window buffers, errno=%d", errno);
- }
// Wrap each buffer
for (int i = 0; i < MAX_BUFFER_COUNT; ++i) {
@@ -482,24 +473,21 @@ void QQnxWindow::post(const QRegion &dirty)
// Update the display with contents of render buffer
errno = 0;
int result = screen_post_window(m_window, currentBuffer.nativeBuffer(), 1, dirtyRect, 0);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxWindow: failed to post window buffer, errno=%d", errno);
- }
// Advance to next nender buffer
m_previousBufferIndex = m_currentBufferIndex++;
- if (m_currentBufferIndex >= MAX_BUFFER_COUNT) {
+ if (m_currentBufferIndex >= MAX_BUFFER_COUNT)
m_currentBufferIndex = 0;
- }
// Save modified region and clear scrolled region
m_previousDirty = dirty;
m_scrolled = QRegion();
// Notify screen that window posted
- if (m_screen != 0) {
+ if (m_screen != 0)
m_screen->onWindowPost(this);
- }
}
}
@@ -524,16 +512,14 @@ void QQnxWindow::setScreen(QQnxScreen *platformScreen)
errno = 0;
screen_display_t display = platformScreen->nativeDisplay();
int result = screen_set_window_property_pv(m_window, SCREEN_PROPERTY_DISPLAY, (void **)&display);
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxWindow: failed to set window display, errno=%d", errno);
- }
// Add window to display's window group
errno = 0;
result = screen_join_window_group(m_window, platformScreen->windowGroupName());
- if (result != 0) {
+ if (result != 0)
qFatal("QQnxWindow: failed to join window group, errno=%d", errno);
- }
Q_FOREACH (QQnxWindow *childWindow, m_childWindows) {
// Only subwindows and tooltips need necessarily be moved to another display with the window.
@@ -813,19 +799,16 @@ int QQnxWindow::platformWindowFormatToNativeFormat(const QSurfaceFormat &format)
qWindowDebug() << Q_FUNC_INFO;
// Extract size of colour channels from window format
int redSize = format.redBufferSize();
- if (redSize == -1) {
+ if (redSize == -1)
qFatal("QQnxWindow: red size not defined");
- }
int greenSize = format.greenBufferSize();
- if (greenSize == -1) {
+ if (greenSize == -1)
qFatal("QQnxWindow: green size not defined");
- }
int blueSize = format.blueBufferSize();
- if (blueSize == -1) {
+ if (blueSize == -1)
qFatal("QQnxWindow: blue size not defined");
- }
// select matching native format
if (redSize == 5 && greenSize == 6 && blueSize == 5) {
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp
index 5757bcad4e..792e79df19 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp
@@ -1095,7 +1095,7 @@ QWindowsNativeImage *QWindowsFontEngine::drawGDIGlyph(HFONT font, glyph_t glyph,
xform.eDx = margin;
xform.eDy = margin;
- HDC hdc = CreateCompatibleDC(QWindowsContext::instance()->displayContext());
+ const HDC hdc = m_fontEngineData->hdc;
SetGraphicsMode(hdc, GM_ADVANCED);
SetWorldTransform(hdc, &xform);
@@ -1107,8 +1107,16 @@ QWindowsNativeImage *QWindowsFontEngine::drawGDIGlyph(HFONT font, glyph_t glyph,
memset(&mat, 0, sizeof(mat));
mat.eM11.value = mat.eM22.value = 1;
- if (GetGlyphOutline(hdc, glyph, ggo_options, &tgm, 0, 0, &mat) == GDI_ERROR) {
- qWarning("QWinFontEngine: unable to query transformed glyph metrics...");
+ const DWORD result = GetGlyphOutline(hdc, glyph, ggo_options, &tgm, 0, 0, &mat);
+
+ XFORM identity = {1, 0, 0, 1, 0, 0};
+ SetWorldTransform(hdc, &identity);
+ SetGraphicsMode(hdc, GM_COMPATIBLE);
+ SelectObject(hdc, old_font);
+
+ if (result == GDI_ERROR) {
+ const int errorCode = GetLastError();
+ qErrnoWarning(errorCode, "QWinFontEngine: unable to query transformed glyph metrics (GetGlyphOutline() failed, error %d)...", errorCode);
return 0;
}
@@ -1117,10 +1125,6 @@ QWindowsNativeImage *QWindowsFontEngine::drawGDIGlyph(HFONT font, glyph_t glyph,
xform.eDx -= tgm.gmptGlyphOrigin.x;
xform.eDy += tgm.gmptGlyphOrigin.y;
-
- SetGraphicsMode(hdc, GM_COMPATIBLE);
- SelectObject(hdc, old_font);
- DeleteDC(hdc);
}
#else // else wince
unsigned int options = 0;
@@ -1412,5 +1416,11 @@ void QWindowsMultiFontEngine::loadEngine(int at)
// TODO: increase cost in QFontCache for the font engine loaded here
}
+bool QWindowsFontEngine::supportsTransformation(const QTransform &transform) const
+{
+ // Support all transformations for ttf files, and translations for raster fonts
+ return ttf || transform.type() <= QTransform::TxTranslate;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h
index 2bf6ead503..9e92a8fbff 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.h
+++ b/src/plugins/platforms/windows/qwindowsfontengine.h
@@ -123,6 +123,7 @@ public:
virtual QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform);
virtual QFontEngine *cloneWithSize(qreal pixelSize) const;
+ virtual bool supportsTransformation(const QTransform &transform) const;
#ifndef Q_CC_MINGW
virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index ae66ef8a3d..f6dda04c13 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -613,8 +613,12 @@ static HGLRC createContext(const QOpenGLStaticContext &staticContext,
const HGLRC result =
staticContext.wglCreateContextAttribsARB(hdc, shared, attributes);
- if (!result)
- qErrnoWarning("%s: wglCreateContextAttribsARB() failed.", __FUNCTION__);
+ if (!result) {
+ QString message;
+ QDebug(&message).nospace() << __FUNCTION__ << ": wglCreateContextAttribsARB() failed (GL error code: 0x"
+ << hex << glGetError() << dec << ") for format: " << format << ", shared context: " << shared;
+ qErrnoWarning("%s", qPrintable(message));
+ }
return result;
}
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
index dd16ea1c6f..fd00a07d6c 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
@@ -237,8 +237,8 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
platformWindow->setFlag(QWindowsWindow::AutoMouseCapture);
if (QWindowsContext::verboseEvents)
qDebug() << "Automatic mouse capture " << window;
- // Implement "Click to focus" for native child windows.
- if (!window->isTopLevel() && QGuiApplication::focusWindow() != window)
+ // Implement "Click to focus" for native child windows (unless it is a native widget window).
+ if (!window->isTopLevel() && !window->inherits("QWidgetWindow") && QGuiApplication::focusWindow() != window)
window->requestActivate();
} else if (platformWindow->hasMouseCapture()
&& platformWindow->testFlag(QWindowsWindow::AutoMouseCapture)
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 010197d6d8..73c78f0090 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -203,10 +203,9 @@ static inline QSize clientSize(HWND hwnd)
return qSizeOfRect(rect);
}
-// from qwidget_win.cpp
-static bool shouldShowMaximizeButton(const QWindow *w)
+// from qwidget_win.cpp, pass flags separately in case they have been "autofixed".
+static bool shouldShowMaximizeButton(const QWindow *w, Qt::WindowFlags flags)
{
- const Qt::WindowFlags flags = w->flags();
if ((flags & Qt::MSWindowsFixedSizeDialogHint) || !(flags & Qt::WindowMaximizeButtonHint))
return false;
// if the user explicitly asked for the maximize button, we try to add
@@ -333,6 +332,25 @@ QDebug operator<<(QDebug debug, const WindowCreationData &d)
return debug;
}
+// Fix top level window flags in case only the type flags are passed.
+static inline void fixTopLevelWindowFlags(Qt::WindowFlags &flags)
+{
+ switch (flags) {
+ case Qt::Window:
+ flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint
+ |Qt::WindowMaximizeButtonHint|Qt::WindowCloseButtonHint;
+ break;
+ case Qt::Dialog:
+ flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowContextHelpButtonHint | Qt::WindowCloseButtonHint;
+ break;
+ case Qt::Tool:
+ flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
+ break;
+ default:
+ break;
+ }
+}
+
void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flagsIn,
unsigned creationFlags)
{
@@ -359,10 +377,8 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
topLevel = (creationFlags & ForceTopLevel) ? true : w->isTopLevel();
}
- if (topLevel && flags == 1) {
- flags |= Qt::WindowTitleHint|Qt::WindowSystemMenuHint|Qt::WindowMinimizeButtonHint
- |Qt::WindowMaximizeButtonHint|Qt::WindowCloseButtonHint;
- }
+ if (topLevel)
+ fixTopLevelWindowFlags(flags);
type = static_cast<Qt::WindowType>(int(flags) & Qt::WindowType_Mask);
switch (type) {
@@ -433,7 +449,7 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
style |= WS_SYSMENU;
if (flags & Qt::WindowMinimizeButtonHint)
style |= WS_MINIMIZEBOX;
- if (shouldShowMaximizeButton(w))
+ if (shouldShowMaximizeButton(w, flags))
style |= WS_MAXIMIZEBOX;
if (tool)
exStyle |= WS_EX_TOOLWINDOW;
@@ -775,7 +791,7 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w,
QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) :
QPlatformWindow(aWindow),
m_data(data),
- m_flags(0),
+ m_flags(WithinCreate),
m_hdc(0),
m_windowState(Qt::WindowNoState),
m_opacity(1.0),
@@ -826,6 +842,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) :
const qreal opacity = qt_window_private(aWindow)->opacity;
if (!qFuzzyCompare(opacity, qreal(1.0)))
setOpacity(opacity);
+ clearFlag(WithinCreate);
}
QWindowsWindow::~QWindowsWindow()
@@ -1481,8 +1498,10 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
if (visible)
newStyle |= WS_VISIBLE;
setStyle(newStyle);
-
- const QRect r = effectiveScreen(window())->geometry();
+ // Use geometry of QWindow::screen() within creation or the virtual screen the
+ // window is in (QTBUG-31166, QTBUG-30724).
+ const QScreen *screen = testFlag(WithinCreate) ? window()->screen() : effectiveScreen(window());
+ const QRect r = screen->geometry();
const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
setFlag(SynchronousGeometryChangeEvent);
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 6c735ede7d..07f3976d87 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -134,7 +134,8 @@ public:
WithinDestroy = 0x1000,
TouchRegistered = 0x2000,
AlertState = 0x4000,
- Exposed = 0x08000
+ Exposed = 0x08000,
+ WithinCreate = 0x10000
};
struct WindowData
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 10a8f26614..209c7bb187 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -253,10 +253,13 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
#endif
, xfixes_first_event(0)
, xrandr_first_event(0)
+ , xkb_first_event(0)
, has_glx_extension(false)
, has_shape_extension(false)
, has_randr_extension(false)
, has_input_shape(false)
+ , has_touch_without_mouse_emulation(false)
+ , has_xkb(false)
, m_buttons(0)
, m_focusWindow(0)
{
@@ -297,6 +300,9 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
xcb_extension_t *extensions[] = {
&xcb_shm_id, &xcb_xfixes_id, &xcb_randr_id, &xcb_shape_id, &xcb_sync_id,
+#ifndef QT_NO_XKB
+ &xcb_xkb_id,
+#endif
#ifdef XCB_USE_RENDER
&xcb_render_id,
#endif
@@ -335,6 +341,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
initializeXInput2();
#endif
initializeXShape();
+ initializeXKB();
m_wmSupport.reset(new QXcbWMSupport(this));
m_keyboard = new QXcbKeyboard(this);
@@ -478,7 +485,6 @@ void printXcbEvent(const char *message, xcb_generic_event_t *event)
PRINT_XCB_EVENT(XCB_SELECTION_NOTIFY);
PRINT_XCB_EVENT(XCB_COLORMAP_NOTIFY);
PRINT_XCB_EVENT(XCB_CLIENT_MESSAGE);
- PRINT_XCB_EVENT(XCB_MAPPING_NOTIFY);
default:
qDebug("QXcbConnection: %s: unknown event - response_type: %d - sequence: %d", message, int(event->response_type & ~0x80), int(event->sequence));
}
@@ -744,6 +750,23 @@ void QXcbConnection::handleButtonRelease(xcb_generic_event_t *ev)
m_buttons &= ~translateMouseButton(event->detail);
}
+#ifndef QT_NO_XKB
+namespace {
+ typedef union {
+ /* All XKB events share these fields. */
+ struct {
+ uint8_t response_type;
+ uint8_t xkbType;
+ uint16_t sequence;
+ xcb_timestamp_t time;
+ uint8_t deviceID;
+ } any;
+ xcb_xkb_map_notify_event_t map_notify;
+ xcb_xkb_state_notify_event_t state_notify;
+ } _xkb_event;
+}
+#endif
+
void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
{
#ifdef Q_XCB_DEBUG
@@ -768,12 +791,21 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
case XCB_EXPOSE:
HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent);
case XCB_BUTTON_PRESS:
+#ifdef QT_NO_XKB
+ m_keyboard->updateXKBStateFromCore(((xcb_button_press_event_t *)event)->state);
+#endif
handleButtonPress(event);
HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent);
case XCB_BUTTON_RELEASE:
+#ifdef QT_NO_XKB
+ m_keyboard->updateXKBStateFromCore(((xcb_button_release_event_t *)event)->state);
+#endif
handleButtonRelease(event);
HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent);
case XCB_MOTION_NOTIFY:
+#ifdef QT_NO_XKB
+ m_keyboard->updateXKBStateFromCore(((xcb_motion_notify_event_t *)event)->state);
+#endif
HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent);
case XCB_CONFIGURE_NOTIFY:
HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent);
@@ -787,18 +819,29 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
case XCB_ENTER_NOTIFY:
HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent);
case XCB_LEAVE_NOTIFY:
+#ifdef QT_NO_XKB
+ m_keyboard->updateXKBStateFromCore(((xcb_leave_notify_event_t *)event)->state);
+#endif
HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent);
case XCB_FOCUS_IN:
HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent);
case XCB_FOCUS_OUT:
HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent);
case XCB_KEY_PRESS:
+#ifdef QT_NO_XKB
+ m_keyboard->updateXKBStateFromCore(((xcb_key_press_event_t *)event)->state);
+#endif
HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent);
case XCB_KEY_RELEASE:
+#ifdef QT_NO_XKB
+ m_keyboard->updateXKBStateFromCore(((xcb_key_release_event_t *)event)->state);
+#endif
HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent);
+#ifdef QT_NO_XKB
case XCB_MAPPING_NOTIFY:
m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event);
break;
+#endif
case XCB_SELECTION_REQUEST:
{
xcb_selection_request_event_t *sr = (xcb_selection_request_event_t *)event;
@@ -861,6 +904,24 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
}
}
handled = true;
+#ifndef QT_NO_XKB
+ } else if (response_type == xkb_first_event) { // https://bugs.freedesktop.org/show_bug.cgi?id=51295
+ _xkb_event *xkb_event = reinterpret_cast<_xkb_event *>(event);
+ if (xkb_event->any.deviceID == m_keyboard->coreDeviceId()) {
+ switch (xkb_event->any.xkbType) {
+ case XCB_XKB_STATE_NOTIFY:
+ m_keyboard->updateXKBState(&xkb_event->state_notify);
+ handled = true;
+ break;
+ case XCB_XKB_MAP_NOTIFY:
+ m_keyboard->handleMappingNotifyEvent(&xkb_event->map_notify);
+ handled = true;
+ break;
+ default:
+ break;
+ }
+ }
+#endif
}
}
@@ -868,7 +929,6 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
if (!handled) {
// 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 = (Display *)m_xlib_display;
XLockDisplay(xdisplay);
Bool (*proc)(Display*, XEvent*, xEvent*) = XESetWireToEvent(xdisplay, response_type, 0);
@@ -1016,32 +1076,36 @@ namespace
xcb_timestamp_t QXcbConnection::getTimestamp()
{
// send a dummy event to myself to get the timestamp from X server.
- xcb_window_t rootWindow = screens().at(primaryScreen())->root();
- xcb_change_property(xcb_connection(), XCB_PROP_MODE_APPEND, rootWindow, atom(QXcbAtom::CLIP_TEMPORARY),
+ xcb_window_t root_win = rootWindow();
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_APPEND, root_win, atom(QXcbAtom::CLIP_TEMPORARY),
XCB_ATOM_INTEGER, 32, 0, NULL);
connection()->flush();
- PropertyNotifyEvent checker(rootWindow, atom(QXcbAtom::CLIP_TEMPORARY));
+ PropertyNotifyEvent checker(root_win, atom(QXcbAtom::CLIP_TEMPORARY));
xcb_generic_event_t *event = 0;
// lets keep this inside a loop to avoid a possible race condition, where
// reader thread has not yet had the time to acquire the mutex in order
// to add the new set of events to its event queue
- while (true) {
+ while (!event) {
connection()->sync();
- if ((event = checkEvent(checker)))
- break;
+ event = checkEvent(checker);
}
xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event;
xcb_timestamp_t timestamp = pn->time;
free(event);
- xcb_delete_property(xcb_connection(), rootWindow, atom(QXcbAtom::CLIP_TEMPORARY));
+ xcb_delete_property(xcb_connection(), root_win, atom(QXcbAtom::CLIP_TEMPORARY));
return timestamp;
}
+xcb_window_t QXcbConnection::rootWindow()
+{
+ return screens().at(primaryScreen())->root();
+}
+
void QXcbConnection::processXcbEvents()
{
int connection_error = xcb_connection_has_error(xcb_connection());
@@ -1333,6 +1397,7 @@ static const char * xcb_atomnames = {
#if XCB_USE_MAEMO_WINDOW_PROPERTIES
"_MEEGOTOUCH_ORIENTATION_ANGLE\0"
#endif
+ "_XSETTINGS_SETTINGS"
};
xcb_atom_t QXcbConnection::atom(QXcbAtom::Atom atom)
@@ -1538,6 +1603,67 @@ void QXcbConnection::initializeXShape()
free(shape_query);
}
+void QXcbConnection::initializeXKB()
+{
+#ifndef QT_NO_XKB
+ const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xkb_id);
+ if (!reply || !reply->present) {
+ xkb_first_event = 0;
+ return;
+ }
+ xkb_first_event = reply->first_event;
+
+ xcb_connection_t *c = connection()->xcb_connection();
+ xcb_xkb_use_extension_cookie_t xkb_query_cookie;
+ xcb_xkb_use_extension_reply_t *xkb_query;
+
+ xkb_query_cookie = xcb_xkb_use_extension(c, XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION);
+ xkb_query = xcb_xkb_use_extension_reply(c, xkb_query_cookie, 0);
+
+ if (!xkb_query) {
+ qWarning("Qt: Failed to initialize XKB extension");
+ return;
+ } else if (!xkb_query->supported) {
+ qWarning("Qt: Unsupported XKB version (want %d %d, has %d %d)",
+ XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION,
+ xkb_query->serverMajor, xkb_query->serverMinor);
+ free(xkb_query);
+ return;
+ }
+
+ has_xkb = true;
+ free(xkb_query);
+
+ uint affectMap, map;
+ affectMap = map = XCB_XKB_MAP_PART_KEY_TYPES |
+ XCB_XKB_MAP_PART_KEY_SYMS |
+ XCB_XKB_MAP_PART_MODIFIER_MAP |
+ XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
+ XCB_XKB_MAP_PART_KEY_ACTIONS |
+ XCB_XKB_MAP_PART_KEY_BEHAVIORS |
+ XCB_XKB_MAP_PART_VIRTUAL_MODS |
+ XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP;
+
+ // Xkb events are reported to all interested clients without regard
+ // to the current keyboard input focus or grab state
+ xcb_void_cookie_t select = xcb_xkb_select_events_checked(c,
+ XCB_XKB_ID_USE_CORE_KBD,
+ XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY,
+ 0,
+ XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY,
+ affectMap,
+ map,
+ 0);
+
+ xcb_generic_error_t *error = xcb_request_check(c, select);
+ if (error) {
+ free(error);
+ qWarning() << "Qt: failed to select notify events from xcb-xkb";
+ return;
+ }
+#endif
+}
+
#if defined(XCB_USE_EGL)
bool QXcbConnection::hasEgl() const
{
@@ -1594,4 +1720,24 @@ bool QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event, int o
}
#endif // defined(XCB_USE_XINPUT2) || defined(XCB_USE_XINPUT2_MAEMO)
+QXcbConnectionGrabber::QXcbConnectionGrabber(QXcbConnection *connection)
+ :m_connection(connection)
+{
+ connection->grabServer();
+}
+
+QXcbConnectionGrabber::~QXcbConnectionGrabber()
+{
+ if (m_connection)
+ m_connection->ungrabServer();
+}
+
+void QXcbConnectionGrabber::release()
+{
+ if (m_connection) {
+ m_connection->ungrabServer();
+ m_connection = 0;
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 44c0e28dd5..883ee95e22 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -53,6 +53,14 @@
#include <QVarLengthArray>
#include <qpa/qwindowsysteminterface.h>
+// This is needed to make Qt compile together with XKB. xkb.h is using a variable
+// which is called 'explicit', this is a reserved keyword in c++ */
+#ifndef QT_NO_XKB
+#define explicit dont_use_cxx_explicit
+#include <xcb/xkb.h>
+#undef explicit
+#endif
+
#ifndef QT_NO_TABLETEVENT
#include <QTabletEvent>
#endif
@@ -261,6 +269,7 @@ namespace QXcbAtom {
#if XCB_USE_MAEMO_WINDOW_PROPERTIES
MeegoTouchOrientationAngle,
#endif
+ _XSETTINGS_SETTINGS,
NPredefinedAtoms,
@@ -355,7 +364,7 @@ public:
#endif
QXcbWMSupport *wmSupport() const { return m_wmSupport.data(); }
-
+ xcb_window_t rootWindow();
#ifdef XCB_USE_XLIB
void *xlib_display() const { return m_xlib_display; }
#endif
@@ -401,6 +410,8 @@ public:
bool hasXShape() const { return has_shape_extension; }
bool hasXRandr() const { return has_randr_extension; }
bool hasInputShape() const { return has_input_shape; }
+ bool hasTouchWithoutMouseEmulation() const { return has_touch_without_mouse_emulation; }
+ bool hasXKB() const { return has_xkb; }
bool supportsThreadedRendering() const { return m_reader->isRunning(); }
@@ -429,6 +440,7 @@ private:
void initializeXRender();
void initializeXRandr();
void initializeXShape();
+ void initializeXKB();
#ifdef XCB_USE_XINPUT2_MAEMO
void initializeXInput2Maemo();
void finalizeXInput2Maemo();
@@ -538,11 +550,14 @@ private:
uint32_t xfixes_first_event;
uint32_t xrandr_first_event;
+ uint32_t xkb_first_event;
bool has_glx_extension;
bool has_shape_extension;
bool has_randr_extension;
bool has_input_shape;
+ bool has_touch_without_mouse_emulation;
+ bool has_xkb;
Qt::MouseButtons m_buttons;
@@ -570,6 +585,15 @@ xcb_generic_event_t *QXcbConnection::checkEvent(T &checker)
return 0;
}
+class QXcbConnectionGrabber
+{
+public:
+ QXcbConnectionGrabber(QXcbConnection *connection);
+ ~QXcbConnectionGrabber();
+ void release();
+private:
+ QXcbConnection *m_connection;
+};
#ifdef Q_XCB_DEBUG
template <typename cookie_t>
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index dfd4feb254..991c82eaaa 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -92,6 +92,9 @@ void QXcbConnection::initializeXInput2()
// Tablet support: Find the stylus-related devices.
xi2SetupTabletDevices();
#endif // QT_NO_TABLETEVENT
+#ifdef XI2_TOUCH_DEBUG
+ qDebug("XInput version %d.%d is supported", xiMajor, m_xi2Minor);
+#endif
}
}
}
@@ -118,7 +121,16 @@ void QXcbConnection::xi2Select(xcb_window_t window)
mask.deviceid = XIAllMasterDevices;
mask.mask_len = sizeof(bitMask);
mask.mask = xiBitMask;
- XISelectEvents(xDisplay, window, &mask, 1);
+ Status result = XISelectEvents(xDisplay, window, &mask, 1);
+ // If we have XInput 2.2 and successfully enable touch on the master
+ // devices, then evdev touchscreens will provide touch only. In most other
+ // cases, there will be emulated mouse events, because true X11 touch
+ // support is so new that for the older drivers, mouse emulation was the
+ // only way; and it's still the fallback even with the modern evdev driver.
+ // But if neither Qt nor X11 does mouse emulation, it will not be possible
+ // to interact with mouse-oriented QWidgets; so we have to let Qt do it.
+ if (m_xi2Minor >= 2 && result == Success)
+ has_touch_without_mouse_emulation = true;
#endif
#ifndef QT_NO_TABLETEVENT
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
index 3fd2ca70e3..756c3c22dd 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.cpp
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -43,6 +43,8 @@
#include "qxcbconnection.h"
#include "qxcbwindow.h"
#include "qxcbimage.h"
+#include "qxcbxsettings.h"
+
#include <QtCore/QLibrary>
#include <QtGui/QWindow>
#include <QtGui/QBitmap>
@@ -54,9 +56,17 @@
QT_BEGIN_NAMESPACE
typedef int (*PtrXcursorLibraryLoadCursor)(void *, const char *);
+typedef char *(*PtrXcursorLibraryGetTheme)(void *);
+typedef int (*PtrXcursorLibrarySetTheme)(void *, const char *);
+typedef int (*PtrXcursorLibraryGetDefaultSize)(void *);
+
#ifdef XCB_USE_XLIB
static PtrXcursorLibraryLoadCursor ptrXcursorLibraryLoadCursor = 0;
+static PtrXcursorLibraryGetTheme ptrXcursorLibraryGetTheme = 0;
+static PtrXcursorLibrarySetTheme ptrXcursorLibrarySetTheme = 0;
+static PtrXcursorLibraryGetDefaultSize ptrXcursorLibraryGetDefaultSize = 0;
#endif
+
static xcb_font_t cursorFont = 0;
static int cursorCount = 0;
@@ -263,7 +273,7 @@ static const char * const cursorNames[] = {
};
QXcbCursor::QXcbCursor(QXcbConnection *conn, QXcbScreen *screen)
- : QXcbObject(conn), m_screen(screen)
+ : QXcbObject(conn), m_screen(screen), m_gtkCursorThemeInitialized(false)
{
if (cursorCount++)
return;
@@ -273,21 +283,38 @@ QXcbCursor::QXcbCursor(QXcbConnection *conn, QXcbScreen *screen)
xcb_open_font(xcb_connection(), cursorFont, strlen(cursorStr), cursorStr);
#ifdef XCB_USE_XLIB
- QLibrary xcursorLib(QLatin1String("Xcursor"), 1);
- bool xcursorFound = xcursorLib.load();
- if (!xcursorFound) { // try without the version number
- xcursorLib.setFileName(QLatin1String("Xcursor"));
- xcursorFound = xcursorLib.load();
+ static bool function_ptrs_not_initialized = true;
+ if (function_ptrs_not_initialized) {
+ QLibrary xcursorLib(QLatin1String("Xcursor"), 1);
+ bool xcursorFound = xcursorLib.load();
+ if (!xcursorFound) { // try without the version number
+ xcursorLib.setFileName(QLatin1String("Xcursor"));
+ xcursorFound = xcursorLib.load();
+ }
+ if (xcursorFound) {
+ ptrXcursorLibraryLoadCursor =
+ (PtrXcursorLibraryLoadCursor) xcursorLib.resolve("XcursorLibraryLoadCursor");
+ ptrXcursorLibraryGetTheme =
+ (PtrXcursorLibraryGetTheme) xcursorLib.resolve("XcursorGetTheme");
+ ptrXcursorLibrarySetTheme =
+ (PtrXcursorLibrarySetTheme) xcursorLib.resolve("XcursorSetTheme");
+ ptrXcursorLibraryGetDefaultSize =
+ (PtrXcursorLibraryGetDefaultSize) xcursorLib.resolve("XcursorGetDefaultSize");
+ }
+ function_ptrs_not_initialized = false;
}
- if (xcursorFound)
- ptrXcursorLibraryLoadCursor =
- (PtrXcursorLibraryLoadCursor) xcursorLib.resolve("XcursorLibraryLoadCursor");
+
#endif
}
QXcbCursor::~QXcbCursor()
{
xcb_connection_t *conn = xcb_connection();
+
+ if (m_gtkCursorThemeInitialized) {
+ m_screen->xSettings()->removeCallbackForHandle(this);
+ }
+
if (!--cursorCount)
xcb_close_font(conn, cursorFont);
@@ -448,6 +475,52 @@ xcb_cursor_t QXcbCursor::createNonStandardCursor(int cshape)
return cursor;
}
+#ifdef XCB_USE_XLIB
+bool updateCursorTheme(void *dpy, const QByteArray theme) {
+ if (!ptrXcursorLibraryGetTheme
+ || !ptrXcursorLibrarySetTheme)
+ return false;
+ QByteArray oldTheme = ptrXcursorLibraryGetTheme(dpy);
+ if (oldTheme == theme)
+ return false;
+
+ int setTheme = ptrXcursorLibrarySetTheme(dpy,theme.constData());
+ return setTheme;
+}
+
+ void QXcbCursor::cursorThemePropertyChanged(QXcbScreen *screen, const QByteArray &name, const QVariant &property, void *handle)
+{
+ Q_UNUSED(screen);
+ Q_UNUSED(name);
+ QXcbCursor *self = static_cast<QXcbCursor *>(handle);
+ updateCursorTheme(self->connection()->xlib_display(),property.toByteArray());
+}
+
+static xcb_cursor_t loadCursor(void *dpy, int cshape)
+{
+ xcb_cursor_t cursor = XCB_NONE;
+ if (!ptrXcursorLibraryLoadCursor || !dpy)
+ return cursor;
+ switch (cshape) {
+ case Qt::DragCopyCursor:
+ cursor = ptrXcursorLibraryLoadCursor(dpy, "dnd-copy");
+ break;
+ case Qt::DragMoveCursor:
+ cursor = ptrXcursorLibraryLoadCursor(dpy, "dnd-move");
+ break;
+ case Qt::DragLinkCursor:
+ cursor = ptrXcursorLibraryLoadCursor(dpy, "dnd-link");
+ break;
+ default:
+ break;
+ }
+ if (!cursor) {
+ cursor = ptrXcursorLibraryLoadCursor(dpy, cursorNames[cshape]);
+ }
+ return cursor;
+}
+#endif //XCB_USE_XLIB
+
xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
{
xcb_connection_t *conn = xcb_connection();
@@ -456,24 +529,18 @@ xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
// Try Xcursor first
#ifdef XCB_USE_XLIB
- if (ptrXcursorLibraryLoadCursor && cshape >= 0 && cshape < Qt::LastCursor) {
+ if (cshape >= 0 && cshape < Qt::LastCursor) {
void *dpy = connection()->xlib_display();
// special case for non-standard dnd-* cursors
- switch (cshape) {
- case Qt::DragCopyCursor:
- cursor = ptrXcursorLibraryLoadCursor(dpy, "dnd-copy");
- break;
- case Qt::DragMoveCursor:
- cursor = ptrXcursorLibraryLoadCursor(dpy, "dnd-move");
- break;
- case Qt::DragLinkCursor:
- cursor = ptrXcursorLibraryLoadCursor(dpy, "dnd-link");
- break;
- default:
- break;
+ cursor = loadCursor(dpy, cshape);
+ if (!cursor && !m_gtkCursorThemeInitialized) {
+ QByteArray gtkCursorTheme = m_screen->xSettings()->setting("Gtk/CursorThemeName").toByteArray();
+ m_screen->xSettings()->registerCallbackForProperty("Gtk/CursorThemeName",cursorThemePropertyChanged,this);
+ if (updateCursorTheme(dpy,gtkCursorTheme)) {
+ cursor = loadCursor(dpy, cshape);
+ }
+ m_gtkCursorThemeInitialized = true;
}
- if (!cursor)
- cursor = ptrXcursorLibraryLoadCursor(dpy, cursorNames[cshape]);
}
if (cursor)
return cursor;
diff --git a/src/plugins/platforms/xcb/qxcbcursor.h b/src/plugins/platforms/xcb/qxcbcursor.h
index 4bbb99e802..081300868c 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.h
+++ b/src/plugins/platforms/xcb/qxcbcursor.h
@@ -72,6 +72,13 @@ private:
QMap<int, xcb_cursor_t> m_shapeCursorMap;
QMap<qint64, xcb_cursor_t> m_bitmapCursorMap;
#endif
+#ifdef XCB_USE_XLIB
+ static void cursorThemePropertyChanged(QXcbScreen *screen,
+ const QByteArray &name,
+ const QVariant &property,
+ void *handle);
+#endif
+ bool m_gtkCursorThemeInitialized;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index dceac09be5..db736cef4e 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -140,7 +140,6 @@ QXcbDrag::QXcbDrag(QXcbConnection *c) : QXcbObject(c)
dropData = new QXcbDropData(this);
init();
- heartbeat = -1;
cleanup_timer = -1;
}
@@ -179,9 +178,6 @@ void QXcbDrag::startDrag()
init();
- heartbeat = startTimer(200);
-
-
xcb_set_selection_owner(xcb_connection(), connection()->clipboard()->owner(),
atom(QXcbAtom::XdndSelection), connection()->time());
@@ -202,10 +198,6 @@ void QXcbDrag::startDrag()
void QXcbDrag::endDrag()
{
- if (heartbeat != -1) {
- killTimer(heartbeat);
- heartbeat = -1;
- }
QBasicDrag::endDrag();
}
@@ -485,11 +477,6 @@ void QXcbDrag::drop(const QMouseEvent *event)
{
QBasicDrag::drop(event);
- if (heartbeat != -1) {
- killTimer(heartbeat);
- heartbeat = -1;
- }
-
if (!current_target)
return;
@@ -536,7 +523,6 @@ void QXcbDrag::drop(const QMouseEvent *event)
current_proxy_target = 0;
source_time = 0;
// current_embedding_widget = 0;
- // #fixme resetDndState(false);
}
Qt::DropAction QXcbDrag::toDropAction(xcb_atom_t a) const
@@ -1041,12 +1027,7 @@ void QXcbDrag::handleFinished(const xcb_client_message_event_t *event)
void QXcbDrag::timerEvent(QTimerEvent* e)
{
- if (e->timerId() == heartbeat && source_sameanswer.isNull()) {
- QPointF pos = QCursor::pos();
- QMouseEvent me(QEvent::MouseMove, pos, pos, pos, Qt::LeftButton,
- QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
- move(&me);
- } else if (e->timerId() == cleanup_timer) {
+ if (e->timerId() == cleanup_timer) {
bool stopTimer = true;
for (int i = 0; i < transactions.count(); ++i) {
const Transaction &t = transactions.at(i);
@@ -1160,7 +1141,7 @@ bool QXcbDrag::dndEnable(QXcbWindow *w, bool on)
if (desktop_proxy) // *WE* already have one.
return false;
- connection()->grabServer();
+ QXcbConnectionGrabber grabber(connection());
// As per Xdnd4, use XdndProxy
xcb_window_t proxy_id = xdndProxy(connection(), w->xcb_window());
@@ -1176,7 +1157,6 @@ bool QXcbDrag::dndEnable(QXcbWindow *w, bool on)
XCB_ATOM_WINDOW, 32, 1, &proxy_id);
}
- connection()->ungrabServer();
} else {
xdnd_widget = w;
}
diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h
index cc74d85b51..5678c2d303 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.h
+++ b/src/plugins/platforms/xcb/qxcbdrag.h
@@ -143,8 +143,6 @@ private:
xcb_window_t current_proxy_target;
QXcbScreen *current_screen;
- // timer used when target wants "continuous" move messages (eg. scroll)
- int heartbeat;
// 10 minute timer used to discard old XdndDrop transactions
enum { XdndDropTransactionTimeout = 600000 };
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index dd1466d23c..77c265fd09 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -327,6 +327,11 @@ Qt::KeyboardModifiers QXcbIntegration::queryKeyboardModifiers() const
return conn->keyboard()->translateModifiers(keybMask);
}
+QList<int> QXcbIntegration::possibleKeys(const QKeyEvent *e) const
+{
+ return m_connections.at(0)->keyboard()->possibleKeys(e);
+}
+
QStringList QXcbIntegration::themeNames() const
{
return QGenericUnixTheme::themeNames();
@@ -337,4 +342,31 @@ QPlatformTheme *QXcbIntegration::createPlatformTheme(const QString &name) const
return QGenericUnixTheme::createUnixTheme(name);
}
+QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
+{
+ switch (hint) {
+ case QPlatformIntegration::CursorFlashTime:
+ case QPlatformIntegration::KeyboardInputInterval:
+ case QPlatformIntegration::MouseDoubleClickInterval:
+ case QPlatformIntegration::StartDragDistance:
+ case QPlatformIntegration::StartDragTime:
+ case QPlatformIntegration::KeyboardAutoRepeatRate:
+ case QPlatformIntegration::PasswordMaskDelay:
+ case QPlatformIntegration::FontSmoothingGamma:
+ case QPlatformIntegration::StartDragVelocity:
+ case QPlatformIntegration::UseRtlExtensions:
+ case QPlatformIntegration::PasswordMaskCharacter:
+ // TODO using various xcb, gnome or KDE settings
+ break; // Not implemented, use defaults
+ case QPlatformIntegration::ShowIsFullScreen:
+ // X11 always has support for windows, but the
+ // window manager could prevent it (e.g. matchbox)
+ return false;
+ case QPlatformIntegration::SynthesizeMouseFromTouchEvents:
+ // We do not want Qt to synthesize mouse events if X11 already does it.
+ return m_connections.at(0)->hasTouchWithoutMouseEmulation();
+ }
+ return QPlatformIntegration::styleHint(hint);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h
index 451dc43475..7042628203 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.h
+++ b/src/plugins/platforms/xcb/qxcbintegration.h
@@ -91,9 +91,11 @@ public:
QPlatformServices *services() const;
Qt::KeyboardModifiers queryKeyboardModifiers() const;
+ QList<int> possibleKeys(const QKeyEvent *e) const;
QStringList themeNames() const;
QPlatformTheme *createPlatformTheme(const QString &name) const;
+ QVariant styleHint(StyleHint hint) const;
QXcbConnection *defaultConnection() const { return m_connections.first(); }
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index c66ed53152..155b327315 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -42,8 +42,6 @@
#include "qxcbkeyboard.h"
#include "qxcbwindow.h"
#include "qxcbscreen.h"
-#include "qxlibconvenience.h"
-#include <xcb/xcb_keysyms.h>
#include <X11/keysym.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtCore/QTextCodec>
@@ -55,6 +53,10 @@
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformcursor.h>
+#ifdef XKBCOMMON_0_2_0
+#include <xkbcommon_workaround.h>
+#endif
+
#ifndef XK_ISO_Left_Tab
#define XK_ISO_Left_Tab 0xFE20
#endif
@@ -561,288 +563,333 @@ static const unsigned int KeyTbl[] = {
0, 0
};
-static const unsigned short katakanaKeysymsToUnicode[] = {
- 0x0000, 0x3002, 0x300C, 0x300D, 0x3001, 0x30FB, 0x30F2, 0x30A1,
- 0x30A3, 0x30A5, 0x30A7, 0x30A9, 0x30E3, 0x30E5, 0x30E7, 0x30C3,
- 0x30FC, 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD,
- 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD,
- 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC,
- 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, 0x30DE,
- 0x30DF, 0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9,
- 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F3, 0x309B, 0x309C
-};
-
-static const unsigned short cyrillicKeysymsToUnicode[] = {
- 0x0000, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457,
- 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0000, 0x045e, 0x045f,
- 0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407,
- 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x0000, 0x040e, 0x040f,
- 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
- 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e,
- 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
- 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a,
- 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
- 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e,
- 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
- 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a
-};
-
-static const unsigned short greekKeysymsToUnicode[] = {
- 0x0000, 0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c,
- 0x038e, 0x03ab, 0x0000, 0x038f, 0x0000, 0x0000, 0x0385, 0x2015,
- 0x0000, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc,
- 0x03cd, 0x03cb, 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
- 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
- 0x03a0, 0x03a1, 0x03a3, 0x0000, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
- 0x03a8, 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7,
- 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
- 0x03c0, 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7,
- 0x03c8, 0x03c9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
-};
-
-static const unsigned short technicalKeysymsToUnicode[] = {
- 0x0000, 0x23B7, 0x250C, 0x2500, 0x2320, 0x2321, 0x2502, 0x23A1,
- 0x23A3, 0x23A4, 0x23A6, 0x239B, 0x239D, 0x239E, 0x23A0, 0x23A8,
- 0x23AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x2264, 0x2260, 0x2265, 0x222B,
- 0x2234, 0x221D, 0x221E, 0x0000, 0x0000, 0x2207, 0x0000, 0x0000,
- 0x223C, 0x2243, 0x0000, 0x0000, 0x0000, 0x21D4, 0x21D2, 0x2261,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x221A, 0x0000,
- 0x0000, 0x0000, 0x2282, 0x2283, 0x2229, 0x222A, 0x2227, 0x2228,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2202,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x2190, 0x2191, 0x2192, 0x2193, 0x0000
-};
-
-static const unsigned short specialKeysymsToUnicode[] = {
- 0x25C6, 0x2592, 0x2409, 0x240C, 0x240D, 0x240A, 0x0000, 0x0000,
- 0x2424, 0x240B, 0x2518, 0x2510, 0x250C, 0x2514, 0x253C, 0x23BA,
- 0x23BB, 0x2500, 0x23BC, 0x23BD, 0x251C, 0x2524, 0x2534, 0x252C,
- 0x2502, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+// Possible modifier states.
+static const Qt::KeyboardModifiers ModsTbl[] = {
+ Qt::NoModifier, // 0
+ Qt::ShiftModifier, // 1
+ Qt::ControlModifier, // 2
+ Qt::ControlModifier | Qt::ShiftModifier, // 3
+ Qt::AltModifier, // 4
+ Qt::AltModifier | Qt::ShiftModifier, // 5
+ Qt::AltModifier | Qt::ControlModifier, // 6
+ Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7
+ Qt::NoModifier // Fall-back to raw Key_*
};
-static const unsigned short publishingKeysymsToUnicode[] = {
- 0x0000, 0x2003, 0x2002, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009,
- 0x200a, 0x2014, 0x2013, 0x0000, 0x0000, 0x0000, 0x2026, 0x2025,
- 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a,
- 0x2105, 0x0000, 0x0000, 0x2012, 0x2329, 0x0000, 0x232a, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000,
- 0x0000, 0x2122, 0x2613, 0x0000, 0x25c1, 0x25b7, 0x25cb, 0x25af,
- 0x2018, 0x2019, 0x201c, 0x201d, 0x211e, 0x0000, 0x2032, 0x2033,
- 0x0000, 0x271d, 0x0000, 0x25ac, 0x25c0, 0x25b6, 0x25cf, 0x25ae,
- 0x25e6, 0x25ab, 0x25ad, 0x25b3, 0x25bd, 0x2606, 0x2022, 0x25aa,
- 0x25b2, 0x25bc, 0x261c, 0x261e, 0x2663, 0x2666, 0x2665, 0x0000,
- 0x2720, 0x2020, 0x2021, 0x2713, 0x2717, 0x266f, 0x266d, 0x2642,
- 0x2640, 0x260e, 0x2315, 0x2117, 0x2038, 0x201a, 0x201e, 0x0000
-};
-
-static const unsigned short aplKeysymsToUnicode[] = {
- 0x0000, 0x0000, 0x0000, 0x003c, 0x0000, 0x0000, 0x003e, 0x0000,
- 0x2228, 0x2227, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x00af, 0x0000, 0x22a5, 0x2229, 0x230a, 0x0000, 0x005f, 0x0000,
- 0x0000, 0x0000, 0x2218, 0x0000, 0x2395, 0x0000, 0x22a4, 0x25cb,
- 0x0000, 0x0000, 0x0000, 0x2308, 0x0000, 0x0000, 0x222a, 0x0000,
- 0x2283, 0x0000, 0x2282, 0x0000, 0x22a2, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x22a3, 0x0000, 0x0000, 0x0000
-};
-
-static const unsigned short koreanKeysymsToUnicode[] = {
- 0x0000, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
- 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
- 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
- 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x314f,
- 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0x3155, 0x3156, 0x3157,
- 0x3158, 0x3159, 0x315a, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f,
- 0x3160, 0x3161, 0x3162, 0x3163, 0x11a8, 0x11a9, 0x11aa, 0x11ab,
- 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, 0x11b3,
- 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, 0x11bb,
- 0x11bc, 0x11bd, 0x11be, 0x11bf, 0x11c0, 0x11c1, 0x11c2, 0x316d,
- 0x3171, 0x3178, 0x317f, 0x3181, 0x3184, 0x3186, 0x318d, 0x318e,
- 0x11eb, 0x11f0, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x20a9
-};
-
-static QChar keysymToUnicode(unsigned char byte3, unsigned char byte4)
-{
- switch (byte3) {
- case 0x04:
- // katakana
- if (byte4 > 0xa0 && byte4 < 0xe0)
- return QChar(katakanaKeysymsToUnicode[byte4 - 0xa0]);
- else if (byte4 == 0x7e)
- return QChar(0x203e); // Overline
- break;
- case 0x06:
- // russian, use lookup table
- if (byte4 > 0xa0)
- return QChar(cyrillicKeysymsToUnicode[byte4 - 0xa0]);
- break;
- case 0x07:
- // greek
- if (byte4 > 0xa0)
- return QChar(greekKeysymsToUnicode[byte4 - 0xa0]);
- break;
- case 0x08:
- // technical
- if (byte4 > 0xa0)
- return QChar(technicalKeysymsToUnicode[byte4 - 0xa0]);
- break;
- case 0x09:
- // special
- if (byte4 >= 0xe0)
- return QChar(specialKeysymsToUnicode[byte4 - 0xe0]);
- break;
- case 0x0a:
- // publishing
- if (byte4 > 0xa0)
- return QChar(publishingKeysymsToUnicode[byte4 - 0xa0]);
- break;
- case 0x0b:
- // APL
- if (byte4 > 0xa0)
- return QChar(aplKeysymsToUnicode[byte4 - 0xa0]);
- break;
- case 0x0e:
- // Korean
- if (byte4 > 0xa0)
- return QChar(koreanKeysymsToUnicode[byte4 - 0xa0]);
- break;
- default:
- break;
- }
- return QChar(0x0);
-}
-
-Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s)
+Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const
{
Qt::KeyboardModifiers ret = 0;
if (s & XCB_MOD_MASK_SHIFT)
ret |= Qt::ShiftModifier;
if (s & XCB_MOD_MASK_CONTROL)
ret |= Qt::ControlModifier;
- if (s & m_alt_mask)
+ if (s & rmod_masks.alt)
ret |= Qt::AltModifier;
- if (s & m_meta_mask)
+ if (s & rmod_masks.meta)
ret |= Qt::MetaModifier;
+ if (s & rmod_masks.altgr)
+ ret |= Qt::GroupSwitchModifier;
return ret;
}
-int QXcbKeyboard::translateKeySym(uint key) const
+void QXcbKeyboard::readXKBConfig(struct xkb_rule_names *xkb_names)
{
- int code = Qt::Key_unknown;
- int i = 0; // any other keys
- while (KeyTbl[i]) {
- if (key == KeyTbl[i]) {
- code = (int)KeyTbl[i+1];
- break;
+ xcb_generic_error_t *error;
+ xcb_get_property_cookie_t cookie;
+ xcb_get_property_reply_t *config_reply;
+
+ xcb_connection_t *c = xcb_connection();
+ xcb_window_t rootWindow = connection()->rootWindow();
+
+ cookie = xcb_get_property(c, 0, rootWindow,
+ atom(QXcbAtom::_XKB_RULES_NAMES), XCB_ATOM_STRING, 0, 1024);
+
+ config_reply = xcb_get_property_reply(c, cookie, &error);
+ if (!config_reply) {
+ qWarning("Qt: Couldn't interpret the _XKB_RULES_NAMES property");
+ return;
+ }
+ char *xkb_config = (char *)xcb_get_property_value(config_reply);
+ int length = xcb_get_property_value_length(config_reply);
+
+ char *names[5] = { 0, 0, 0, 0, 0 };
+ char *p = xkb_config, *end = p + length;
+ int i = 0;
+ // The result from xcb_get_property_value() is not necessarily \0-terminated,
+ // we need to make sure that too many or missing '\0' symbols are handled safely.
+ do {
+ uint len = qstrnlen(p, length);
+ names[i++] = p;
+ p += len + 1;
+ length -= len + 1;
+ } while (p < end || i < 5);
+
+ xkb_names->rules = qstrdup(names[0]);
+ xkb_names->model = qstrdup(names[1]);
+ xkb_names->layout = qstrdup(names[2]);
+ xkb_names->variant = qstrdup(names[3]);
+ xkb_names->options = qstrdup(names[4]);
+
+ free(config_reply);
+}
+
+void QXcbKeyboard::updateKeymap()
+{
+ m_config = true;
+ if (!xkb_context) {
+ xkb_context = xkb_context_new((xkb_context_flags)0);
+ if (!xkb_context) {
+ qWarning("Qt: Failed to create XKB context");
+ m_config = false;
+ return;
}
- i += 2;
}
- if (m_meta_mask) {
- // translate Super/Hyper keys to Meta if we're using them as the MetaModifier
- if (m_meta_mask == m_super_mask && (code == Qt::Key_Super_L || code == Qt::Key_Super_R)) {
- code = Qt::Key_Meta;
- } else if (m_meta_mask == m_hyper_mask && (code == Qt::Key_Hyper_L || code == Qt::Key_Hyper_R)) {
- code = Qt::Key_Meta;
+
+ struct xkb_rule_names xkb_names = {0, 0, 0, 0, 0};
+
+ readXKBConfig(&xkb_names);
+ // Compile a keymap from RMLVO (rules, models, layouts, variants and options) names
+ if (xkb_keymap)
+ xkb_keymap_unref(xkb_keymap);
+
+ xkb_keymap = xkb_keymap_new_from_names(xkb_context, &xkb_names, (xkb_keymap_compile_flags)0);
+
+ delete[] xkb_names.rules;
+ delete[] xkb_names.model;
+ delete[] xkb_names.layout;
+ delete[] xkb_names.variant;
+ delete[] xkb_names.options;
+
+ if (!xkb_keymap) {
+ qWarning("Qt: Failed to compile a keymap");
+ m_config = false;
+ return;
+ }
+ // Create a new keyboard state object for a keymap
+ struct xkb_state *new_state = xkb_state_new(xkb_keymap);
+ if (!new_state) {
+ qWarning("Qt: Failed to create a new keyboard state");
+ m_config = false;
+ return;
+ }
+
+ if (xkb_state) {
+ xkb_state_unref(xkb_state);
+ xkb_state = new_state;
+ } else {
+ xkb_state = new_state;
+#ifndef QT_NO_XKB
+ // get initial state from the X server (and keep it up-to-date at all times)
+ xcb_xkb_get_state_cookie_t state;
+ xcb_xkb_get_state_reply_t *init_state;
+
+ xcb_connection_t *c = xcb_connection();
+ state = xcb_xkb_get_state(c, XCB_XKB_ID_USE_CORE_KBD);
+ init_state = xcb_xkb_get_state_reply(c, state, 0);
+ if (!init_state) {
+ qWarning("Qt: couldn't retrieve an initial keyboard state");
+ return;
}
+ /* The xkb keyboard state is comprised of the state of all keyboard modifiers,
+ the keyboard group, and the state of the pointer buttons */
+ xkb_state_update_mask(xkb_state,
+ init_state->baseMods,
+ init_state->latchedMods,
+ init_state->lockedMods,
+ init_state->baseGroup,
+ init_state->latchedGroup,
+ init_state->lockedGroup);
+ free(init_state);
+#else
+ updateXKBMods();
+#endif
}
- return code;
}
-QString QXcbKeyboard::translateKeySym(xcb_keysym_t keysym, uint xmodifiers,
- int &code, Qt::KeyboardModifiers &modifiers,
- QByteArray &chars, int &count)
+#ifndef QT_NO_XKB
+void QXcbKeyboard::updateXKBState(xcb_xkb_state_notify_event_t *state)
{
- // all keysyms smaller than 0xff00 are actally keys that can be mapped to unicode chars
-
- QTextCodec *mapper = QTextCodec::codecForLocale();
- QChar converted;
-
- if (/*count == 0 &&*/ keysym < 0xff00) {
- unsigned char byte3 = (unsigned char)(keysym >> 8);
- int mib = -1;
- switch(byte3) {
- case 0: // Latin 1
- case 1: // Latin 2
- case 2: //latin 3
- case 3: // latin4
- mib = byte3 + 4; break;
- case 5: // arabic
- mib = 82; break;
- case 12: // Hebrew
- mib = 85; break;
- case 13: // Thai
- mib = 2259; break;
- case 4: // kana
- case 6: // cyrillic
- case 7: // greek
- case 8: // technical, no mapping here at the moment
- case 9: // Special
- case 10: // Publishing
- case 11: // APL
- case 14: // Korean, no mapping
- mib = -1; // manual conversion
- mapper= 0;
-#if !defined(QT_NO_XIM)
- converted = keysymToUnicode(byte3, keysym & 0xff);
-#endif
- case 0x20:
- // currency symbols
- if (keysym >= 0x20a0 && keysym <= 0x20ac) {
- mib = -1; // manual conversion
- mapper = 0;
- converted = (uint)keysym;
- }
- break;
- default:
- break;
+ if (!m_config)
+ return;
+
+ if (connection()->hasXKB()) {
+
+ xkb_state_component newState;
+ newState = xkb_state_update_mask(xkb_state,
+ state->baseMods,
+ state->latchedMods,
+ state->lockedMods,
+ state->baseGroup,
+ state->latchedGroup,
+ state->lockedGroup);
+
+ if ((newState & XKB_STATE_LAYOUT_EFFECTIVE) == XKB_STATE_LAYOUT_EFFECTIVE) {
+ //qWarning("TODO: Support KeyboardLayoutChange on QPA (QTBUG-27681)");
}
- if (mib != -1) {
- mapper = QTextCodec::codecForMib(mib);
- if (chars.isEmpty())
- chars.resize(1);
- chars[0] = (unsigned char) (keysym & 0xff); // get only the fourth bit for conversion later
- count = 1;
+ }
+}
+
+#else
+void QXcbKeyboard::updateXKBStateFromCore(quint16 state)
+{
+ if (!m_config)
+ return;
+
+ quint32 modsDepressed, modsLatched, modsLocked;
+ modsDepressed = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_DEPRESSED);
+ modsLatched = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED);
+ modsLocked = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED);
+
+ quint32 xkbMask = xkbModMask(state);
+ xkb_state_component newState;
+ newState = xkb_state_update_mask(xkb_state,
+ modsDepressed & xkbMask,
+ modsLatched & xkbMask,
+ modsLocked & xkbMask,
+ 0,
+ 0,
+ (state >> 13) & 3); // bits 13 and 14 report the state keyboard group
+
+ if ((newState & XKB_STATE_LAYOUT_EFFECTIVE) == XKB_STATE_LAYOUT_EFFECTIVE) {
+ //qWarning("TODO: Support KeyboardLayoutChange on QPA (QTBUG-27681)");
+ }
+}
+
+quint32 QXcbKeyboard::xkbModMask(quint16 state)
+{
+ quint32 xkb_mask = 0;
+
+ if ((state & XCB_MOD_MASK_SHIFT) && xkb_mods.shift != XKB_MOD_INVALID)
+ xkb_mask |= (1 << xkb_mods.shift);
+ if ((state & XCB_MOD_MASK_LOCK) && xkb_mods.lock != XKB_MOD_INVALID)
+ xkb_mask |= (1 << xkb_mods.lock);
+ if ((state & XCB_MOD_MASK_CONTROL) && xkb_mods.control != XKB_MOD_INVALID)
+ xkb_mask |= (1 << xkb_mods.control);
+ if ((state & XCB_MOD_MASK_1) && xkb_mods.mod1 != XKB_MOD_INVALID)
+ xkb_mask |= (1 << xkb_mods.mod1);
+ if ((state & XCB_MOD_MASK_2) && xkb_mods.mod2 != XKB_MOD_INVALID)
+ xkb_mask |= (1 << xkb_mods.mod2);
+ if ((state & XCB_MOD_MASK_3) && xkb_mods.mod3 != XKB_MOD_INVALID)
+ xkb_mask |= (1 << xkb_mods.mod3);
+ if ((state & XCB_MOD_MASK_4) && xkb_mods.mod4 != XKB_MOD_INVALID)
+ xkb_mask |= (1 << xkb_mods.mod4);
+ if ((state & XCB_MOD_MASK_5) && xkb_mods.mod5 != XKB_MOD_INVALID)
+ xkb_mask |= (1 << xkb_mods.mod5);
+
+ return xkb_mask;
+}
+
+void QXcbKeyboard::updateXKBMods()
+{
+ xkb_mods.shift = xkb_map_mod_get_index(xkb_keymap, XKB_MOD_NAME_SHIFT);
+ xkb_mods.lock = xkb_map_mod_get_index(xkb_keymap, XKB_MOD_NAME_CAPS);
+ xkb_mods.control = xkb_map_mod_get_index(xkb_keymap, XKB_MOD_NAME_CTRL);
+ xkb_mods.mod1 = xkb_map_mod_get_index(xkb_keymap, "Mod1");
+ xkb_mods.mod2 = xkb_map_mod_get_index(xkb_keymap, "Mod2");
+ xkb_mods.mod3 = xkb_map_mod_get_index(xkb_keymap, "Mod3");
+ xkb_mods.mod4 = xkb_map_mod_get_index(xkb_keymap, "Mod4");
+ xkb_mods.mod5 = xkb_map_mod_get_index(xkb_keymap, "Mod5");
+}
+#endif
+
+QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
+{
+ // turn off the modifier bits which doesn't participate in shortcuts
+ Qt::KeyboardModifiers notNeeded = Qt::MetaModifier | Qt::KeypadModifier | Qt::GroupSwitchModifier;
+ Qt::KeyboardModifiers modifiers = event->modifiers() &= ~notNeeded;
+ // create a fresh kb state and test against the relevant modifier combinations
+ // NOTE: it should be possible to query the keymap directly, once it gets
+ // supported by libxkbcommon
+ struct xkb_state * kb_state = xkb_state_new(xkb_keymap);
+ if (!kb_state) {
+ qWarning("QXcbKeyboard: failed to compile xkb keymap");
+ return QList<int>();
+ }
+ // get kb state from the master xkb_state and update the temporary kb_state
+ xkb_layout_index_t baseLayout = xkb_state_serialize_layout(xkb_state, XKB_STATE_LAYOUT_DEPRESSED);
+ xkb_layout_index_t latchedLayout = xkb_state_serialize_layout(xkb_state, XKB_STATE_LAYOUT_LATCHED);
+ xkb_layout_index_t lockedLayout = xkb_state_serialize_layout(xkb_state, XKB_STATE_LAYOUT_LOCKED);
+ xkb_mod_index_t latchedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED);
+ xkb_mod_index_t lockedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED);
+
+ xkb_state_update_mask(kb_state, 0, latchedMods, lockedMods,
+ baseLayout, latchedLayout, lockedLayout);
+
+ xkb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, event->nativeScanCode());
+ if (sym == XKB_KEY_NoSymbol)
+ return QList<int>();
+
+ QList<int> result;
+ int baseQtKey = keysymToQtKey(sym, modifiers, keysymToUnicode(sym));
+ result += (baseQtKey + modifiers); // The base key is _always_ valid, of course
+
+ xkb_mod_index_t shiftMod = xkb_keymap_mod_get_index(xkb_keymap, "Shift");
+ xkb_mod_index_t altMod = xkb_keymap_mod_get_index(xkb_keymap, "Alt");
+ xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(xkb_keymap, "Control");
+
+ xkb_mod_mask_t depressed;
+
+ int qtKey = 0;
+ //obtain a list of possible shortcuts for the given key event
+ for (uint i = 1; i < sizeof(ModsTbl) / sizeof(*ModsTbl) ; ++i) {
+ Qt::KeyboardModifiers neededMods = ModsTbl[i];
+ if ((modifiers & neededMods) == neededMods) {
+
+ depressed = 0;
+ if (neededMods & Qt::AltModifier)
+ depressed |= (1 << altMod);
+ if (neededMods & Qt::ShiftModifier)
+ depressed |= (1 << shiftMod);
+ if (neededMods & Qt::ControlModifier)
+ depressed |= (1 << controlMod);
+
+ // update a keyboard state from a set of explicit masks
+ xkb_state_update_mask(kb_state, depressed, latchedMods, lockedMods,
+ baseLayout, latchedLayout, lockedLayout);
+ sym = xkb_state_key_get_one_sym(kb_state, event->nativeScanCode());
+
+ if (sym == XKB_KEY_NoSymbol)
+ continue;
+
+ Qt::KeyboardModifiers mods = modifiers & ~neededMods;
+ qtKey = keysymToQtKey(sym, mods, keysymToUnicode(sym));
+
+ if (qtKey == baseQtKey)
+ continue;
+
+ result += (qtKey + mods);
}
- } else if (keysym >= 0x1000000 && keysym <= 0x100ffff) {
- converted = (ushort) (keysym - 0x1000000);
- mapper = 0;
}
- if (count < (int)chars.size()-1)
- chars[count] = '\0';
-
- QString text;
- if (!mapper && converted.unicode() != 0x0) {
- text = converted;
- } else if (!chars.isEmpty()) {
- // convert chars (8bit) to text (unicode).
- if (mapper)
- text = mapper->toUnicode(chars.data(), count, 0);
- if (text.isEmpty()) {
- // no mapper, or codec couldn't convert to unicode (this
- // can happen when running in the C locale or with no LANG
- // set). try converting from latin-1
- text = QString::fromLatin1(chars);
+
+ xkb_state_unref(kb_state);
+ return result;
+ }
+
+int QXcbKeyboard::keysymToQtKey(xcb_keysym_t key) const
+{
+ int code = 0;
+ int i = 0;
+ while (KeyTbl[i]) {
+ if (key == KeyTbl[i]) {
+ code = (int)KeyTbl[i+1];
+ break;
}
+ i += 2;
}
- modifiers = translateModifiers(xmodifiers);
+ return code;
+}
+int QXcbKeyboard::keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, QString text) const
+{
+ int code = 0;
+ QTextCodec *systemCodec = QTextCodec::codecForLocale();
// Commentary in X11/keysymdef says that X codes match ASCII, so it
// is safe to use the locale functions to process X codes in ISO8859-1.
- //
// This is mainly for compatibility - applications should not use the
- // Qt keycodes between 128 and 255, but should rather use the
- // QKeyEvent::text().
- //
- if (keysym < 128 || (keysym < 256 && (!mapper || mapper->mibEnum()==4))) {
+ // Qt keycodes between 128 and 255 (extended ACSII codes), but should
+ // rather use the QKeyEvent::text().
+ if (keysym < 128 || (keysym < 256 && systemCodec->mibEnum() == 4)) {
// upper-case key, if known
code = isprint((int)keysym) ? toupper((int)keysym) : 0;
} else if (keysym >= XK_F1 && keysym <= XK_F35) {
@@ -853,48 +900,207 @@ QString QXcbKeyboard::translateKeySym(xcb_keysym_t keysym, uint xmodifiers,
// numeric keypad keys
code = Qt::Key_0 + ((int)keysym - XK_KP_0);
} else {
- code = translateKeySym(keysym);
+ code = keysymToQtKey(keysym);
}
modifiers |= Qt::KeypadModifier;
- } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f && text.unicode()->unicode() != 0x7f && !(keysym >= XK_dead_grave && keysym <= XK_dead_horn)) {
+ } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f
+ && text.unicode()->unicode() != 0x7f
+ && !(keysym >= XK_dead_grave && keysym <= XK_dead_currency)) {
code = text.unicode()->toUpper().unicode();
} else {
// any other keys
- code = translateKeySym(keysym);
-
- if (code == Qt::Key_Tab && (modifiers & Qt::ShiftModifier)) {
- // map shift+tab to shift+backtab, QShortcutMap knows about it
- // and will handle it.
- code = Qt::Key_Backtab;
- text = QString();
- }
+ code = keysymToQtKey(keysym);
}
- return text;
+ return code;
}
QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection)
: QXcbObject(connection)
, m_autorepeat_code(0)
+ , xkb_context(0)
+ , xkb_keymap(0)
+ , xkb_state(0)
+#ifndef QT_NO_XKB
+ , core_device_id(0)
+#endif
{
+ updateKeymap();
+#ifndef QT_NO_XKB
+ if (connection->hasXKB()) {
+
+ updateVModMapping();
+ updateVModToRModMapping();
+
+ // get the core keyboard id
+ xcb_xkb_get_device_info_cookie_t device_id_cookie;
+ xcb_xkb_get_device_info_reply_t *device_id;
+
+ device_id_cookie = xcb_xkb_get_device_info(xcb_connection(),
+ XCB_XKB_ID_USE_CORE_KBD,
+ 0, 0, 0, 0, 0, 0);
+
+ device_id = xcb_xkb_get_device_info_reply(xcb_connection(), device_id_cookie, 0);
+ if (!device_id) {
+ qWarning("Qt: couldn't get core keyboard device info");
+ return;
+ }
+
+ core_device_id = device_id->deviceID;
+ free(device_id);
+ }
+#else
m_key_symbols = xcb_key_symbols_alloc(xcb_connection());
- setupModifiers();
+ updateModifiers();
+#endif
}
QXcbKeyboard::~QXcbKeyboard()
{
+ if (xkb_state)
+ xkb_state_unref(xkb_state);
+ if (xkb_keymap)
+ xkb_keymap_unref(xkb_keymap);
+ if (xkb_context)
+ xkb_context_unref(xkb_context);
+#ifdef QT_NO_XKB
xcb_key_symbols_free(m_key_symbols);
+#endif
+}
+
+#ifndef QT_NO_XKB
+void QXcbKeyboard::updateVModMapping()
+{
+ xcb_xkb_get_names_cookie_t names_cookie;
+ xcb_xkb_get_names_reply_t *name_reply;
+ xcb_xkb_get_names_value_list_t names_list;
+
+ memset(&vmod_masks, 0, sizeof(vmod_masks));
+
+ names_cookie = xcb_xkb_get_names(xcb_connection(),
+ XCB_XKB_ID_USE_CORE_KBD,
+ XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES);
+
+ name_reply = xcb_xkb_get_names_reply(xcb_connection(), names_cookie, 0);
+ if (!name_reply) {
+ qWarning("Qt: failed to retrieve the virtual modifier names from XKB");
+ return;
+ }
+
+ const void *buffer = xcb_xkb_get_names_value_list(name_reply);
+ xcb_xkb_get_names_value_list_unpack(buffer,
+ name_reply->nTypes,
+ name_reply->indicators,
+ name_reply->virtualMods,
+ name_reply->groupNames,
+ name_reply->nKeys,
+ name_reply->nKeyAliases,
+ name_reply->nRadioGroups,
+ name_reply->which,
+ &names_list);
+
+ int count = 0;
+ uint vmod_mask, bit;
+ char *vmod_name;
+ vmod_mask = name_reply->virtualMods;
+ // find the virtual modifiers for which names are defined.
+ for (bit = 1; vmod_mask; bit <<= 1) {
+ vmod_name = 0;
+
+ if (!(vmod_mask & bit))
+ continue;
+
+ vmod_mask &= ~bit;
+ // virtualModNames - the list of virtual modifier atoms beginning with the lowest-numbered
+ // virtual modifier for which a name is defined and proceeding to the highest.
+ QByteArray atomName = connection()->atomName(names_list.virtualModNames[count]);
+ vmod_name = atomName.data();
+ count++;
+
+ if (!vmod_name)
+ continue;
+
+ // similarly we could retrieve NumLock, Super, Hyper modifiers if needed.
+ if (qstrcmp(vmod_name, "Alt") == 0)
+ vmod_masks.alt = bit;
+ else if (qstrcmp(vmod_name, "Meta") == 0)
+ vmod_masks.meta = bit;
+ else if (qstrcmp(vmod_name, "AltGr") == 0)
+ vmod_masks.altgr = bit;
+ }
+
+ free(name_reply);
}
-void QXcbKeyboard::setupModifiers()
+void QXcbKeyboard::updateVModToRModMapping()
+{
+ xcb_xkb_get_map_cookie_t map_cookie;
+ xcb_xkb_get_map_reply_t *map_reply;
+ xcb_xkb_get_map_map_t map;
+
+ memset(&rmod_masks, 0, sizeof(rmod_masks));
+
+ map_cookie = xcb_xkb_get_map(xcb_connection(),
+ XCB_XKB_ID_USE_CORE_KBD,
+ XCB_XKB_MAP_PART_VIRTUAL_MODS,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+ map_reply = xcb_xkb_get_map_reply(xcb_connection(), map_cookie, 0);
+ if (!map_reply) {
+ qWarning("Qt: failed to retrieve the virtual modifier map from XKB");
+ return;
+ }
+
+ const void *buffer = xcb_xkb_get_map_map(map_reply);
+ xcb_xkb_get_map_map_unpack(buffer,
+ map_reply->nTypes,
+ map_reply->nKeySyms,
+ map_reply->nKeyActions,
+ map_reply->totalActions,
+ map_reply->totalKeyBehaviors,
+ map_reply->nVModMapKeys,
+ map_reply->totalKeyExplicit,
+ map_reply->totalModMapKeys,
+ map_reply->totalVModMapKeys,
+ map_reply->present,
+ &map);
+
+ uint vmod_mask, bit;
+ // the virtual modifiers mask for which a set of corresponding
+ // real modifiers is to be returned
+ vmod_mask = map_reply->virtualMods;
+ int count = 0;
+
+ for (bit = 1; vmod_mask; bit <<= 1) {
+ uint modmap;
+
+ if (!(vmod_mask & bit))
+ continue;
+
+ vmod_mask &= ~bit;
+ // real modifier bindings for the specified virtual modifiers
+ modmap = map.vmods_rtrn[count];
+ count++;
+
+ if (vmod_masks.alt == bit)
+ rmod_masks.alt = modmap;
+ else if (vmod_masks.meta == bit)
+ rmod_masks.meta = modmap;
+ else if (vmod_masks.altgr == bit)
+ rmod_masks.altgr = modmap;
+ }
+
+ free(map_reply);
+}
+#else
+void QXcbKeyboard::updateModifiers()
{
- m_alt_mask = 0;
- m_super_mask = 0;
- m_hyper_mask = 0;
- m_meta_mask = 0;
- m_mode_switch_mask = 0;
- m_num_lock_mask = 0;
- m_caps_lock_mask = 0;
+ // The core protocol does not provide a convenient way to determine the mapping
+ // of modifier bits. Clients must retrieve and search the modifier map to determine
+ // the keycodes bound to each modifier, and then retrieve and search the keyboard
+ // mapping to determine the keysyms bound to the keycodes. They must repeat this
+ // process for all modifiers whenever any part of the modifier mapping is changed.
+ memset(&rmod_masks, 0, sizeof(rmod_masks));
xcb_generic_error_t *error = 0;
xcb_connection_t *conn = xcb_connection();
@@ -902,15 +1108,14 @@ void QXcbKeyboard::setupModifiers()
xcb_get_modifier_mapping_reply_t *modMapReply =
xcb_get_modifier_mapping_reply(conn, modMapCookie, &error);
if (error) {
- qWarning("QXcbKeyboard: failed to get modifier mapping");
+ qWarning("Qt: failed to get modifier mapping");
free(error);
return;
}
// for Alt and Meta L and R are the same
static const xcb_keysym_t symbols[] = {
- XK_Alt_L, XK_Meta_L, XK_Super_L, XK_Super_R,
- XK_Hyper_L, XK_Hyper_R, XK_Num_Lock, XK_Mode_switch, XK_Caps_Lock,
+ XK_Alt_L, XK_Meta_L, XK_Mode_switch
};
static const size_t numSymbols = sizeof symbols / sizeof *symbols;
@@ -928,8 +1133,15 @@ void QXcbKeyboard::setupModifiers()
xcb_keycode_t keyCode = modMap[x + bit * w];
xcb_keycode_t *itk = modKeyCodes[i];
while (itk && *itk != XCB_NO_SYMBOL)
- if (*itk++ == keyCode)
- setMask(symbols[i], mask);
+ if (*itk++ == keyCode) {
+ uint sym = symbols[i];
+ if ((sym == XK_Alt_L || sym == XK_Alt_R))
+ rmod_masks.alt = mask;
+ if ((sym == XK_Meta_L || sym == XK_Meta_R))
+ rmod_masks.meta = mask;
+ if (sym == XK_Mode_switch)
+ rmod_masks.altgr = mask;
+ }
}
}
}
@@ -938,53 +1150,7 @@ void QXcbKeyboard::setupModifiers()
free(modKeyCodes[i]);
free(modMapReply);
}
-
-void QXcbKeyboard::setMask(uint sym, uint mask)
-{
- if (m_alt_mask == 0
- && m_meta_mask != mask
- && m_super_mask != mask
- && m_hyper_mask != mask
- && (sym == XK_Alt_L || sym == XK_Alt_R))
- m_alt_mask = mask;
-
- if (m_meta_mask == 0
- && m_alt_mask != mask
- && m_super_mask != mask
- && m_hyper_mask != mask
- && (sym == XK_Meta_L || sym == XK_Meta_R))
- m_meta_mask = mask;
-
- if (m_super_mask == 0
- && m_alt_mask != mask
- && m_meta_mask != mask
- && m_hyper_mask != mask
- && (sym == XK_Super_L || sym == XK_Super_R))
- m_super_mask = mask;
-
- if (m_hyper_mask == 0
- && m_alt_mask != mask
- && m_meta_mask != mask
- && m_super_mask != mask
- && (sym == XK_Hyper_L || sym == XK_Hyper_R))
- m_hyper_mask = mask;
-
- if (m_mode_switch_mask == 0
- && m_alt_mask != mask
- && m_meta_mask != mask
- && m_super_mask != mask
- && m_hyper_mask != mask
- && sym == XK_Mode_switch)
- m_mode_switch_mask = mask;
-
- if (m_num_lock_mask == 0 && sym == XK_Num_Lock)
- m_num_lock_mask = mask;
-
- if (m_caps_lock_mask == 0 && sym == XK_Caps_Lock)
- m_caps_lock_mask = mask;
-}
-
-// #define XCB_KEYBOARD_DEBUG
+#endif
class KeyChecker
{
@@ -1046,16 +1212,21 @@ void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycod
quint16 state, xcb_timestamp_t time)
{
Q_XCB_NOOP(connection());
-#ifdef XCB_KEYBOARD_DEBUG
- printf("key code: %d, state: %d, syms: ", code, state);
- for (int i = 0; i <= 5; ++i) {
- printf("%d ", xcb_key_symbols_get_keysym(m_key_symbols, code, i));
- }
- printf("\n");
+
+ if (!m_config)
+ return;
+ // It is crucial the order of xkb_state_key_get_one_sym &
+ // xkb_state_update_key operations is not reversed!
+ xcb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state, code);
+#ifdef QT_NO_XKB
+ enum xkb_key_direction direction;
+ if (type == QEvent::KeyPress)
+ direction = XKB_KEY_DOWN;
+ else
+ direction = XKB_KEY_UP;
+ xkb_state_update_key(xkb_state, code, direction);
#endif
- QByteArray chars;
- xcb_keysym_t sym = lookupString(window, state, code, type, &chars);
QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext();
QMetaMethod method;
@@ -1077,12 +1248,12 @@ void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycod
return;
}
- Qt::KeyboardModifiers modifiers;
- int qtcode = 0;
- int count = chars.count();
- QString string = translateKeySym(sym, state, qtcode, modifiers, chars, count);
+ Qt::KeyboardModifiers modifiers = translateModifiers(state);
+ QString string = keysymToUnicode(sym);
+ int count = string.size();
string.truncate(count);
+ int qtcode = keysymToQtKey(sym, modifiers, string);
bool isAutoRepeat = false;
if (type == QEvent::KeyPress) {
@@ -1141,35 +1312,33 @@ void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycod
}
}
-xcb_keysym_t QXcbKeyboard::lookupString(QWindow *window, uint state, xcb_keycode_t code,
- QEvent::Type type, QByteArray *chars)
+QString QXcbKeyboard::keysymToUnicode(xcb_keysym_t sym) const
{
-#ifdef XCB_USE_XLIB
- xcb_window_t xWindow = static_cast<QXcbWindow *>(window->handle())->xcb_window();
- xcb_window_t root = connection()->screens().at(0)->root();
- void *xDisplay = connection()->xlib_display();
- int xType = (type == QEvent::KeyRelease ? 3 : 2);
- return q_XLookupString(xDisplay, xWindow, root, state, code, xType, chars);
-#else
-
- // No XLookupString available. The following is really incomplete...
-
- int col = state & XCB_MOD_MASK_SHIFT ? 1 : 0;
- const int altGrOffset = 4;
- if (state & 128)
- col += altGrOffset;
- xcb_keysym_t sym = xcb_key_symbols_get_keysym(m_key_symbols, code, col);
- if (sym == XCB_NO_SYMBOL)
- sym = xcb_key_symbols_get_keysym(m_key_symbols, code, col ^ 0x1);
- if (state & XCB_MOD_MASK_LOCK && sym <= 0x7f && isprint(sym)) {
- if (isupper(sym))
- sym = tolower(sym);
+ QByteArray chars;
+ int bytes;
+ chars.resize(7);
+
+#ifdef XKBCOMMON_0_2_0
+ if (needWorkaround(sym)) {
+ quint32 codepoint;
+ if (sym == XKB_KEY_KP_Space)
+ codepoint = XKB_KEY_space & 0x7f;
else
- sym = toupper(sym);
- }
- return sym;
+ codepoint = sym & 0x7f;
+ bytes = utf32_to_utf8(codepoint, chars.data());
+ } else {
+ bytes = xkb_keysym_to_utf8(sym, chars.data(), chars.size());
+ }
+#else
+ bytes = xkb_keysym_to_utf8(sym, chars.data(), chars.size());
#endif
+
+ if (bytes == -1)
+ qWarning("QXcbKeyboard::handleKeyEvent - buffer too small");
+ chars.resize(bytes-1);
+
+ return QString::fromUtf8(chars);
}
void QXcbKeyboard::handleKeyPressEvent(QXcbWindowEventListener *eventListener, const xcb_key_press_event_t *event)
@@ -1189,10 +1358,20 @@ void QXcbKeyboard::handleKeyReleaseEvent(QXcbWindowEventListener *eventListener,
handleKeyEvent(window->window(), QEvent::KeyRelease, event->detail, event->state, event->time);
}
-void QXcbKeyboard::handleMappingNotifyEvent(const xcb_mapping_notify_event_t *event)
+void QXcbKeyboard::handleMappingNotifyEvent(const void *event)
{
- xcb_refresh_keyboard_mapping(m_key_symbols, const_cast<xcb_mapping_notify_event_t *>(event));
- setupModifiers();
+ updateKeymap();
+#ifdef QT_NO_XKB
+ void *ev = const_cast<void *>(event);
+ xcb_refresh_keyboard_mapping(m_key_symbols, static_cast<xcb_mapping_notify_event_t *>(ev));
+ updateModifiers();
+#else
+ Q_UNUSED(event)
+ if (connection()->hasXKB()) {
+ updateVModMapping();
+ updateVModToRModMapping();
+ }
+#endif
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h
index 3c71daa57f..af6677c20f 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.h
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.h
@@ -44,7 +44,11 @@
#include "qxcbobject.h"
-#include "xcb/xcb_keysyms.h"
+#ifdef QT_NO_XKB
+#include <xcb/xcb_keysyms.h>
+#endif
+
+#include <xkbcommon/xkbcommon.h>
#include <QEvent>
@@ -56,37 +60,80 @@ class QXcbKeyboard : public QXcbObject
{
public:
QXcbKeyboard(QXcbConnection *connection);
+
~QXcbKeyboard();
void handleKeyPressEvent(QXcbWindowEventListener *eventListener, const xcb_key_press_event_t *event);
void handleKeyReleaseEvent(QXcbWindowEventListener *eventListener, const xcb_key_release_event_t *event);
- void handleMappingNotifyEvent(const xcb_mapping_notify_event_t *event);
+ void handleMappingNotifyEvent(const void *event);
- Qt::KeyboardModifiers translateModifiers(int s);
+ Qt::KeyboardModifiers translateModifiers(int s) const;
-private:
+ void updateKeymap();
+ QList<int> possibleKeys(const QKeyEvent *e) const;
+
+#ifdef QT_NO_XKB
+ void updateXKBStateFromCore(quint16 state);
+ void updateXKBMods();
+ quint32 xkbModMask(quint16 state);
+#else
+ int coreDeviceId() { return core_device_id; }
+ void updateXKBState(xcb_xkb_state_notify_event_t *state);
+#endif
+
+protected:
void handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycode_t code, quint16 state, xcb_timestamp_t time);
- int translateKeySym(uint key) const;
- QString translateKeySym(xcb_keysym_t keysym, uint xmodifiers,
- int &code, Qt::KeyboardModifiers &modifiers,
- QByteArray &chars, int &count);
- void setupModifiers();
- void setMask(uint sym, uint mask);
- xcb_keysym_t lookupString(QWindow *window, uint state, xcb_keycode_t code,
- QEvent::Type type, QByteArray *chars);
-
- uint m_alt_mask;
- uint m_super_mask;
- uint m_hyper_mask;
- uint m_meta_mask;
- uint m_mode_switch_mask;
- uint m_num_lock_mask;
- uint m_caps_lock_mask;
+ QString keysymToUnicode(xcb_keysym_t sym) const;
- xcb_key_symbols_t *m_key_symbols;
+ int keysymToQtKey(xcb_keysym_t keysym) const;
+ int keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, QString text) const;
+
+ void readXKBConfig(struct xkb_rule_names *names);
+
+#ifdef QT_NO_XKB
+ void updateModifiers();
+#else
+ void updateVModMapping();
+ void updateVModToRModMapping();
+#endif
+
+private:
+ bool m_config;
xcb_keycode_t m_autorepeat_code;
+
+ struct xkb_context *xkb_context;
+ struct xkb_keymap *xkb_keymap;
+ struct xkb_state *xkb_state;
+
+ struct _mod_masks {
+ uint alt;
+ uint altgr;
+ uint meta;
+ };
+
+ _mod_masks rmod_masks;
+
+#ifdef QT_NO_XKB
+ xcb_key_symbols_t *m_key_symbols;
+
+ struct _xkb_mods {
+ xkb_mod_index_t shift;
+ xkb_mod_index_t lock;
+ xkb_mod_index_t control;
+ xkb_mod_index_t mod1;
+ xkb_mod_index_t mod2;
+ xkb_mod_index_t mod3;
+ xkb_mod_index_t mod4;
+ xkb_mod_index_t mod5;
+ };
+
+ _xkb_mods xkb_mods;
+#else
+ _mod_masks vmod_masks;
+ int core_device_id;
+#endif
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index da60cfd2bd..7d832a1c08 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -58,7 +58,9 @@
#include "qglxintegration.h"
#endif
-#ifndef XCB_USE_XLIB
+#ifdef XCB_USE_XLIB
+# include <X11/Xlib.h>
+#else
# include <stdio.h>
#endif
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index a6ead49a27..37c6c97bc4 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -44,6 +44,7 @@
#include "qxcbcursor.h"
#include "qxcbimage.h"
#include "qnamespace.h"
+#include "qxcbxsettings.h"
#include <stdio.h>
@@ -68,6 +69,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr,
, m_refreshRate(60)
, m_forcedDpi(-1)
, m_hintStyle(QFontEngine::HintStyle(-1))
+ , m_xSettings(0)
{
if (connection->hasXRandr())
xcb_randr_select_input(xcb_connection(), screen()->root, true);
@@ -580,4 +582,12 @@ void QXcbScreen::readXResources()
}
}
+QXcbXSettings *QXcbScreen::xSettings() const
+{
+ if (!m_xSettings) {
+ QXcbScreen *self = const_cast<QXcbScreen *>(this);
+ self->m_xSettings = new QXcbXSettings(self);
+ }
+ return m_xSettings;
+}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index 0382be8a29..c36492db64 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -56,6 +56,7 @@ QT_BEGIN_NAMESPACE
class QXcbConnection;
class QXcbCursor;
+class QXcbXSettings;
class QXcbScreen : public QXcbObject, public QPlatformScreen
{
@@ -102,6 +103,9 @@ public:
void readXResources();
QFontEngine::HintStyle hintStyle() const { return m_hintStyle; }
+
+ QXcbXSettings *xSettings() const;
+
private:
static bool xResource(const QByteArray &identifier,
const QByteArray &expectedIdentifier,
@@ -127,6 +131,7 @@ private:
int m_refreshRate;
int m_forcedDpi;
QFontEngine::HintStyle m_hintStyle;
+ QXcbXSettings *m_xSettings;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbxsettings.cpp b/src/plugins/platforms/xcb/qxcbxsettings.cpp
new file mode 100644
index 0000000000..7ffd3e105f
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbxsettings.cpp
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxcbxsettings.h"
+
+#include <QtCore/QByteArray>
+
+#include <X11/extensions/XIproto.h>
+
+QT_BEGIN_NAMESPACE
+/* Implementation of http://standards.freedesktop.org/xsettings-spec/xsettings-0.5.html */
+
+enum XSettingsType {
+ XSettingsTypeInteger = 0,
+ XSettingsTypeString = 1,
+ XSettingsTypeColor = 2
+};
+
+class QXcbXSettingsCallback
+{
+public:
+ QXcbXSettings::PropertyChangeFunc func;
+ void *handle;
+};
+
+class QXcbXSettingsPropertyValue
+{
+public:
+ QXcbXSettingsPropertyValue()
+ : last_change_serial(-1)
+ {}
+
+ void updateValue(QXcbScreen *screen, const QByteArray &name, const QVariant &value, int last_change_serial)
+ {
+ if (last_change_serial <= this->last_change_serial)
+ return;
+ this->value = value;
+ this->last_change_serial = last_change_serial;
+ QLinkedList<QXcbXSettingsCallback>::const_iterator it = callback_links.begin();
+ for (;it != callback_links.end();++it) {
+ it->func(screen,name,value,it->handle);
+ }
+ }
+
+ void addCallback(QXcbXSettings::PropertyChangeFunc func, void *handle)
+ {
+ QXcbXSettingsCallback callback;
+ callback.func = func;
+ callback.handle = handle;
+ callback_links.append(callback);
+ }
+
+ QVariant value;
+ int last_change_serial;
+ QLinkedList<QXcbXSettingsCallback> callback_links;
+
+};
+
+class QXcbXSettingsPrivate
+{
+public:
+ QXcbXSettingsPrivate(QXcbScreen *screen)
+ : screen(screen)
+ {
+ }
+
+ QByteArray getSettings()
+ {
+ QXcbConnectionGrabber connectionGrabber(screen->connection());
+
+ int offset = 0;
+ QByteArray settings;
+ xcb_atom_t _xsettings_atom = screen->connection()->atom(QXcbAtom::_XSETTINGS_SETTINGS);
+ while (1) {
+ xcb_get_property_cookie_t get_prop_cookie =
+ xcb_get_property_unchecked(screen->xcb_connection(),
+ false,
+ x_settings_window,
+ _xsettings_atom,
+ _xsettings_atom,
+ offset/4,
+ 8192);
+ xcb_get_property_reply_t *reply = xcb_get_property_reply(screen->xcb_connection(), get_prop_cookie, NULL);
+ bool more = false;
+ if (!reply)
+ return settings;
+
+ settings += QByteArray((const char *)xcb_get_property_value(reply), xcb_get_property_value_length(reply));
+ offset += xcb_get_property_value_length(reply);
+ more = reply->bytes_after != 0;
+
+ free(reply);
+
+ if (!more)
+ break;
+ }
+
+ return settings;
+ }
+
+ static int round_to_nearest_multiple_of_4(int value)
+ {
+ int remainder = value % 4;
+ if (!remainder)
+ return value;
+ return value + 4 - remainder;
+ }
+
+ void populateSettings(const QByteArray &xSettings)
+ {
+ if (xSettings.length() < 12)
+ return;
+ // we ignore byteorder for now
+ char byteOrder = xSettings.at(1);
+ Q_UNUSED(byteOrder);
+ uint serial = *reinterpret_cast<const uint *>(xSettings.mid(4,4).constData());
+ serial = serial;
+ uint number_of_settings = *reinterpret_cast<const uint *>(xSettings.mid(8,4).constData());
+
+ const char *data = xSettings.constData() + 12;
+ size_t offset = 0;
+ for (uint i = 0; i < number_of_settings; i++) {
+ int local_offset = 0;
+ XSettingsType type = static_cast<XSettingsType>(*reinterpret_cast<const quint8 *>(data + offset));
+ local_offset += 2;
+
+ quint16 name_len = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ local_offset += 2;
+
+ QByteArray name(data + offset + local_offset, name_len);
+ local_offset += round_to_nearest_multiple_of_4(name_len);
+
+ int last_change_serial = *reinterpret_cast<const int *>(data + offset + local_offset);
+ Q_UNUSED(last_change_serial);
+ local_offset += 4;
+
+ QVariant value;
+ if (type == XSettingsTypeString) {
+ int value_length = *reinterpret_cast<const int *>(data + offset + local_offset);
+ local_offset+=4;
+ QByteArray value_string(data + offset + local_offset, value_length);
+ value.setValue(value_string);
+ local_offset += round_to_nearest_multiple_of_4(value_length);
+ } else if (type == XSettingsTypeInteger) {
+ int value_length = *reinterpret_cast<const int *>(data + offset + local_offset);
+ local_offset += 4;
+ value.setValue(value_length);
+ } else if (type == XSettingsTypeColor) {
+ quint16 red = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ local_offset += 2;
+ quint16 green = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ local_offset += 2;
+ quint16 blue = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ local_offset += 2;
+ quint16 alpha= *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ local_offset += 2;
+ QColor color_value(red,green,blue,alpha);
+ value.setValue(color_value);
+ }
+ offset += local_offset;
+ settings[name].updateValue(screen,name,value,last_change_serial);
+ }
+
+ }
+
+ QXcbScreen *screen;
+ xcb_window_t x_settings_window;
+ int serial;
+ QMap<QByteArray, QXcbXSettingsPropertyValue> settings;
+};
+
+
+QXcbXSettings::QXcbXSettings(QXcbScreen *screen)
+ : d_ptr(new QXcbXSettingsPrivate(screen))
+{
+ QByteArray settings_atom_for_screen("_XSETTINGS_S");
+ settings_atom_for_screen.append(QByteArray::number(screen->screenNumber()));
+ xcb_intern_atom_cookie_t atom_cookie = xcb_intern_atom(screen->xcb_connection(),
+ false,
+ settings_atom_for_screen.length(),
+ settings_atom_for_screen.constData());
+ xcb_intern_atom_reply_t *atom_reply = xcb_intern_atom_reply(screen->xcb_connection(),atom_cookie,NULL);
+ xcb_atom_t selection_owner_atom = atom_reply->atom;
+ free(atom_reply);
+
+ xcb_get_selection_owner_cookie_t selection_cookie =
+ xcb_get_selection_owner(screen->xcb_connection(), selection_owner_atom);
+ xcb_get_selection_owner_reply_t *selection_result =
+ xcb_get_selection_owner_reply(screen->xcb_connection(), selection_cookie, NULL);
+
+ d_ptr->x_settings_window = selection_result->owner;
+ free(selection_result);
+
+ const uint32_t event_mask[] = { XCB_EVENT_MASK_STRUCTURE_NOTIFY|XCB_EVENT_MASK_PROPERTY_CHANGE };
+ xcb_change_window_attributes(screen->xcb_connection(),d_ptr->x_settings_window,XCB_CW_EVENT_MASK,event_mask);
+
+ d_ptr->populateSettings(d_ptr->getSettings());
+}
+
+void QXcbXSettings::handlePropertyNotifyEvent(const xcb_property_notify_event_t *event)
+{
+ Q_D(QXcbXSettings);
+ if (event->window != d->x_settings_window)
+ return;
+ d->populateSettings(d->getSettings());
+}
+
+void QXcbXSettings::registerCallbackForProperty(const QByteArray &property, QXcbXSettings::PropertyChangeFunc func, void *handle)
+{
+ Q_D(QXcbXSettings);
+ d->settings[property].addCallback(func,handle);
+}
+
+void QXcbXSettings::removeCallbackForHandle(const QByteArray &property, void *handle)
+{
+ Q_D(QXcbXSettings);
+ QXcbXSettingsPropertyValue &value = d->settings[property];
+ QLinkedList<QXcbXSettingsCallback>::iterator it = value.callback_links.begin();
+ while (it != value.callback_links.end()) {
+ if (it->handle == handle)
+ it = value.callback_links.erase(it);
+ else
+ ++it;
+ }
+}
+
+void QXcbXSettings::removeCallbackForHandle(void *handle)
+{
+ Q_D(QXcbXSettings);
+ for (QMap<QByteArray, QXcbXSettingsPropertyValue>::const_iterator it = d->settings.cbegin();
+ it != d->settings.cend(); ++it) {
+ removeCallbackForHandle(it.key(),handle);
+ }
+}
+
+QVariant QXcbXSettings::setting(const QByteArray &property) const
+{
+ Q_D(const QXcbXSettings);
+ return d->settings.value(property).value;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbxsettings.h b/src/plugins/platforms/xcb/qxcbxsettings.h
new file mode 100644
index 0000000000..16fed862bc
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbxsettings.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXCBXSETTINGS_H
+#define QXCBXSETTINGS_H
+
+#include "qxcbscreen.h"
+
+QT_BEGIN_NAMESPACE
+
+class QXcbXSettingsPrivate;
+
+class QXcbXSettings : public QXcbWindowEventListener
+{
+ Q_DECLARE_PRIVATE(QXcbXSettings)
+public:
+ QXcbXSettings(QXcbScreen *screen);
+
+ QVariant setting(const QByteArray &property) const;
+
+ typedef void (*PropertyChangeFunc)(QXcbScreen *screen, const QByteArray &name, const QVariant &property, void *handle);
+ void registerCallbackForProperty(const QByteArray &property, PropertyChangeFunc func, void *handle);
+ void removeCallbackForHandle(const QByteArray &property, void *handle);
+ void removeCallbackForHandle(void *handle);
+
+ void handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) Q_DECL_OVERRIDE;
+private:
+ QXcbXSettingsPrivate *d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QXCBXSETTINGS_H
diff --git a/src/plugins/platforms/xcb/xcb-plugin.pro b/src/plugins/platforms/xcb/xcb-plugin.pro
index 5823e97f36..82995286c4 100644
--- a/src/plugins/platforms/xcb/xcb-plugin.pro
+++ b/src/plugins/platforms/xcb/xcb-plugin.pro
@@ -6,7 +6,6 @@ load(qt_plugin)
QT += core-private gui-private platformsupport-private
-
SOURCES = \
qxcbclipboard.cpp \
qxcbconnection.cpp \
@@ -22,7 +21,7 @@ SOURCES = \
qxcbnativeinterface.cpp \
qxcbcursor.cpp \
qxcbimage.cpp \
- qxlibconvenience.cpp
+ qxcbxsettings.cpp
HEADERS = \
qxcbclipboard.h \
@@ -39,11 +38,11 @@ HEADERS = \
qxcbnativeinterface.h \
qxcbcursor.h \
qxcbimage.h \
- qxlibconvenience.h
+ qxcbxsettings.h
LIBS += -ldl
-# needed by GLX, Xcursor, XLookupString, ...
+# needed by GLX, Xcursor ...
contains(QT_CONFIG, xcb-xlib) {
DEFINES += XCB_USE_XLIB
LIBS += -lX11 -lX11-xcb
@@ -112,7 +111,23 @@ contains(QT_CONFIG, xcb-qt) {
INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/sysinclude
LIBS += -lxcb -L$$OUT_PWD/xcb-static -lxcb-static
} else {
- LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr
+ LIBS += -lxcb -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr
!contains(DEFINES, QT_NO_SHAPE):LIBS += -lxcb-shape
+ contains(DEFINES, QT_NO_XKB) {
+ LIBS += -lxcb-keysyms
+ } else {
+ LIBS += -lxcb-xkb
+ }
}
+# libxkbcommon
+contains(QT_CONFIG, xkbcommon-qt): {
+ include(../../../3rdparty/xkbcommon.pri)
+} else {
+ LIBS += $$QMAKE_LIBS_XKBCOMMON
+ QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XKBCOMMON
+ equals(QMAKE_VERSION_XKBCOMMON, "0.2.0") {
+ DEFINES += XKBCOMMON_0_2_0
+ INCLUDEPATH += ../../../3rdparty/xkbcommon/xkbcommon/
+ }
+}
diff --git a/src/plugins/platforms/xcb/xcb-static/xcb-static.pro b/src/plugins/platforms/xcb/xcb-static/xcb-static.pro
index 01667d41db..2fd5519053 100644
--- a/src/plugins/platforms/xcb/xcb-static/xcb-static.pro
+++ b/src/plugins/platforms/xcb/xcb-static/xcb-static.pro
@@ -24,7 +24,8 @@ SOURCES += \
$$LIBXCB_DIR/shm.c \
$$LIBXCB_DIR/sync.c \
$$LIBXCB_DIR/render.c \
- $$LIBXCB_DIR/shape.c
+ $$LIBXCB_DIR/shape.c \
+ $$LIBXCB_DIR/xkb.c
#
# xcb-util