summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/xcb')
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp20
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h7
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp49
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp190
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.h5
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp7
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp15
-rw-r--r--src/plugins/platforms/xcb/qxcbwmsupport.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbxsettings.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbxsettings.h1
-rw-r--r--src/plugins/platforms/xcb/xcb-plugin.pro2
16 files changed, 226 insertions, 88 deletions
diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/qglxintegration.h
index 84910c4172..5777980093 100644
--- a/src/plugins/platforms/xcb/qglxintegration.h
+++ b/src/plugins/platforms/xcb/qglxintegration.h
@@ -75,7 +75,6 @@ private:
void init(QXcbScreen *screen, QPlatformOpenGLContext *share);
void init(QXcbScreen *screen, QPlatformOpenGLContext *share, const QVariant &nativeHandle);
- QXcbScreen *m_screen;
Display *m_display;
GLXFBConfig m_config;
GLXContext m_context;
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index 45856f3e6c..8b3893ec2f 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -276,7 +276,7 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c)
m_timestamp[QClipboard::Clipboard] = XCB_CURRENT_TIME;
m_timestamp[QClipboard::Selection] = XCB_CURRENT_TIME;
- m_screen = connection()->screens().at(connection()->primaryScreen());
+ m_screen = connection()->primaryScreen();
int x = 0, y = 0, w = 3, h = 3;
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 835c414d85..5510c3b1b4 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -244,7 +244,7 @@ void QXcbConnection::updateScreens()
// the first or an exact match. An exact match isn't
// always available if primary->output is XCB_NONE
// or currently disconnected output.
- if (m_primaryScreen == xcbScreenNumber) {
+ if (m_primaryScreenNumber == xcbScreenNumber) {
if (!primaryScreen || (primary && outputs[i] == primary->output)) {
primaryScreen = screen;
siblings.prepend(siblings.takeLast());
@@ -306,7 +306,7 @@ void QXcbConnection::updateScreens()
QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName)
: m_connection(0)
, m_canGrabServer(canGrabServer)
- , m_primaryScreen(0)
+ , m_primaryScreenNumber(0)
, m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY"))
, m_nativeInterface(nativeInterface)
, xfixes_first_event(0)
@@ -331,7 +331,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
#ifdef XCB_USE_XLIB
dpy = XOpenDisplay(m_displayName.constData());
if (dpy) {
- m_primaryScreen = DefaultScreen(dpy);
+ m_primaryScreenNumber = DefaultScreen(dpy);
m_connection = XGetXCBConnection(dpy);
XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
XSetErrorHandler(nullErrorHandler);
@@ -339,7 +339,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
m_xlib_display = dpy;
}
#else
- m_connection = xcb_connect(m_displayName.constData(), &m_primaryScreen);
+ m_connection = xcb_connect(m_displayName.constData(), &m_primaryScreenNumber);
#endif //XCB_USE_XLIB
if (!m_connection || xcb_connection_has_error(m_connection))
@@ -449,6 +449,16 @@ QXcbConnection::~QXcbConnection()
delete m_keyboard;
}
+QXcbScreen *QXcbConnection::primaryScreen() const
+{
+ if (!m_screens.isEmpty()) {
+ Q_ASSERT(m_screens.first()->screenNumber() == primaryScreenNumber());
+ return m_screens.first();
+ }
+
+ return Q_NULLPTR;
+}
+
void QXcbConnection::addWindowEventListener(xcb_window_t id, QXcbWindowEventListener *eventListener)
{
m_mapper.insert(id, eventListener);
@@ -1219,7 +1229,7 @@ xcb_timestamp_t QXcbConnection::getTimestamp()
xcb_window_t QXcbConnection::rootWindow()
{
- return screens().at(primaryScreen())->root();
+ return primaryScreen()->root();
}
void QXcbConnection::processXcbEvents()
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 4a16e116c6..7286b6b89b 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -324,6 +324,7 @@ private:
class QXcbWindowEventListener
{
public:
+ virtual ~QXcbWindowEventListener() {}
virtual bool handleGenericEvent(xcb_generic_event_t *, long *) { return false; }
virtual void handleExposeEvent(const xcb_expose_event_t *) {}
@@ -369,7 +370,8 @@ public:
QXcbConnection *connection() const { return const_cast<QXcbConnection *>(this); }
const QList<QXcbScreen *> &screens() const { return m_screens; }
- int primaryScreen() const { return m_primaryScreen; }
+ int primaryScreenNumber() const { return m_primaryScreenNumber; }
+ QXcbScreen *primaryScreen() const;
inline xcb_atom_t atom(QXcbAtom::Atom atom) const { return m_allAtoms[atom]; }
QXcbAtom::Atom qatom(xcb_atom_t atom) const;
@@ -469,6 +471,7 @@ public:
QXcbEventReader *eventReader() const { return m_reader; }
+ bool canGrab() const { return m_canGrabServer; }
protected:
bool event(QEvent *e) Q_DECL_OVERRIDE;
@@ -550,7 +553,7 @@ private:
bool m_canGrabServer;
QList<QXcbScreen *> m_screens;
- int m_primaryScreen;
+ int m_primaryScreenNumber;
xcb_atom_t m_allAtoms[QXcbAtom::NAtoms];
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index 53437f24ae..7037e102e2 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -311,7 +311,7 @@ void QXcbDrag::move(const QMouseEvent *me)
return;
const QList<QXcbScreen *> &screens = connection()->screens();
- QXcbScreen *screen = screens.at(connection()->primaryScreen());
+ QXcbScreen *screen = connection()->primaryScreen();
for (int i = 0; i < screens.size(); ++i) {
if (screens.at(i)->geometry().contains(globalPos)) {
screen = screens.at(i);
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index d3533b8e44..3818494d99 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -92,11 +92,11 @@
QT_BEGIN_NAMESPACE
-#if defined(QT_DEBUG) && defined(Q_OS_LINUX)
// Find out if our parent process is gdb by looking at the 'exe' symlink under /proc,.
// or, for older Linuxes, read out 'cmdline'.
static bool runningUnderDebugger()
{
+#if defined(QT_DEBUG) && defined(Q_OS_LINUX)
const QString parentProc = QLatin1String("/proc/") + QString::number(getppid());
const QFileInfo parentProcExe(parentProc + QLatin1String("/exe"));
if (parentProcExe.isSymLink())
@@ -113,12 +113,15 @@ static bool runningUnderDebugger()
s += c;
}
return s == "gdb";
-}
+#else
+ return false;
#endif
+}
QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char **argv)
: m_services(new QGenericUnixServices)
, m_instanceName(0)
+ , m_canGrab(true)
{
qRegisterMetaType<QXcbWindow*>();
#ifdef XCB_USE_XLIB
@@ -126,16 +129,10 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char
#endif
m_nativeInterface.reset(new QXcbNativeInterface);
- bool canGrab = true;
- #if defined(QT_DEBUG) && defined(Q_OS_LINUX)
- canGrab = !runningUnderDebugger();
- #endif
- static bool canNotGrabEnv = qgetenv("QT_XCB_NO_GRAB_SERVER").length();
- if (canNotGrabEnv)
- canGrab = false;
-
// Parse arguments
const char *displayName = 0;
+ bool noGrabArg = false;
+ bool doGrabArg = false;
if (argc) {
int j = 1;
for (int i = 1; i < argc; i++) {
@@ -146,13 +143,35 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char
displayName = argv[++i];
else if (arg == "-name" && i < argc - 1)
m_instanceName = argv[++i];
+ else if (arg == "-nograb")
+ noGrabArg = true;
+ else if (arg == "-dograb")
+ doGrabArg = true;
else
argv[j++] = argv[i];
}
argc = j;
} // argc
- m_connections << new QXcbConnection(m_nativeInterface.data(), canGrab, displayName);
+ bool underDebugger = runningUnderDebugger();
+ if (noGrabArg && doGrabArg && underDebugger) {
+ qWarning() << "Both -nograb and -dograb command line arguments specified. Please pick one. -nograb takes prcedence";
+ doGrabArg = false;
+ }
+
+#if defined(QT_DEBUG)
+ if (!noGrabArg && !doGrabArg && underDebugger) {
+ qDebug("Qt: gdb: -nograb added to command-line options.\n"
+ "\t Use the -dograb option to enforce grabbing.");
+ }
+#endif
+ m_canGrab = (!underDebugger && noGrabArg) || (underDebugger && doGrabArg);
+
+ static bool canNotGrabEnv = qEnvironmentVariableIsSet("QT_XCB_NO_GRAB_SERVER");
+ if (canNotGrabEnv)
+ m_canGrab = false;
+
+ m_connections << new QXcbConnection(m_nativeInterface.data(), m_canGrab, displayName);
for (int i = 0; i < parameters.size() - 1; i += 2) {
#ifdef Q_XCB_DEBUG
@@ -408,19 +427,19 @@ QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
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::FontSmoothingGamma:
+ // Match Qt 4.8 text rendering, and rendering of other X11 toolkits.
+ return qreal(1.0);
case QPlatformIntegration::StartDragDistance: {
// The default (in QPlatformTheme::defaultThemeHint) is 10 pixels, but
// on a high-resolution screen it makes sense to increase it.
- const QList<QXcbScreen *> &screens = defaultConnection()->screens();
qreal dpi = 100.0;
- if (screens.length() > 0) {
- const QXcbScreen *screen = screens.at(defaultConnection()->primaryScreen());
+ if (const QXcbScreen *screen = defaultConnection()->primaryScreen()) {
if (screen->logicalDpi().first > dpi)
dpi = screen->logicalDpi().first;
if (screen->logicalDpi().second > dpi)
diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h
index ffb068ecb3..db6ad541ea 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.h
+++ b/src/plugins/platforms/xcb/qxcbintegration.h
@@ -117,6 +117,7 @@ private:
mutable QByteArray m_wmClass;
const char *m_instanceName;
+ bool m_canGrab;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index dae3a79628..260fb46309 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -721,7 +721,7 @@ void QXcbKeyboard::updateKeymap()
if (xkb_keymap) {
new_state = xkb_state_new(xkb_keymap);
} else {
- printKeymapError("Failed to compile a keymap!");
+ printKeymapError("Qt: Failed to compile a keymap!");
m_config = false;
return;
}
@@ -737,6 +737,8 @@ void QXcbKeyboard::updateKeymap()
xkb_state = new_state;
if (!connection()->hasXKB())
updateXKBMods();
+
+ checkForLatinLayout();
}
#ifndef QT_NO_XKB
@@ -824,37 +826,137 @@ void QXcbKeyboard::updateXKBMods()
xkb_mods.mod5 = xkb_keymap_mod_get_index(xkb_keymap, "Mod5");
}
+static bool isLatin(xkb_keysym_t sym)
+{
+ return ((sym >= 'a' && sym <= 'z') || (sym >= 'A' && sym <= 'Z'));
+}
+
+void QXcbKeyboard::checkForLatinLayout()
+{
+ m_hasLatinLayout = false;
+ const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts(xkb_keymap);
+ const xcb_keycode_t minKeycode = connection()->setup()->min_keycode;
+ const xcb_keycode_t maxKeycode = connection()->setup()->max_keycode;
+ struct xkb_state *kb_state = xkb_state_new(xkb_keymap);
+ for (xkb_layout_index_t layout = 0; layout < layoutCount; ++layout) {
+ xkb_state_update_mask(kb_state, 0, 0, 0, 0, 0, layout);
+ for (xcb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
+ xkb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, code);
+ // if layout can produce any of these latin letters (chosen
+ // arbitrarily) then it must be a latin key based layout
+ if (sym == XK_q || sym == XK_a || sym == XK_e) {
+ m_hasLatinLayout = true;
+ xkb_state_unref(kb_state);
+ return;
+ }
+ }
+ }
+ xkb_state_unref(kb_state);
+}
+
+xkb_keysym_t QXcbKeyboard::lookupLatinKeysym(xkb_keycode_t keycode) const
+{
+ xkb_layout_index_t layout;
+ xkb_keysym_t sym = XKB_KEY_NoSymbol;
+ const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts_for_key(xkb_keymap, keycode);
+ const xkb_layout_index_t currentLayout = xkb_state_key_get_layout(xkb_state, keycode);
+ // Look at user layouts in the order in which they are defined in system
+ // settings to find a latin keysym.
+ for (layout = 0; layout < layoutCount; ++layout) {
+ if (layout == currentLayout)
+ continue;
+ const xkb_keysym_t *syms;
+ xkb_level_index_t level = xkb_state_key_get_level(xkb_state, keycode, layout);
+ if (xkb_keymap_key_get_syms_by_level(xkb_keymap, keycode, layout, level, &syms) != 1)
+ continue;
+ if (isLatin(syms[0])) {
+ sym = syms[0];
+ break;
+ }
+ }
+ // If user layouts don't contain any layout that results in a latin key, we query a
+ // key from "US" layout, this allows for latin-key-based shorcuts to work even when
+ // users have only one (non-latin) layout set.
+ xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED);
+ xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED);
+ if (sym == XKB_KEY_NoSymbol && !m_hasLatinLayout) {
+ if (!latin_keymap) {
+ const struct xkb_rule_names names = { xkb_names.rules, xkb_names.model, "us", 0, 0 };
+ latin_keymap = xkb_keymap_new_from_names(xkb_context, &names, (xkb_keymap_compile_flags)0);
+ static bool printFailure = true;
+ if (!latin_keymap && printFailure) {
+ // print message about failure to compile US keymap only once,
+ // no need to do this on every key press.
+ printFailure = false;
+ printKeymapError("Qt: Failed to compile US keymap, shortcut handling with "
+ "non-Latin keyboard layouts may not be fully functional!");
+ }
+ }
+ if (latin_keymap) {
+ struct xkb_state *latin_state = xkb_state_new(latin_keymap);
+ if (latin_state) {
+ xkb_state_update_mask(latin_state, 0, latchedMods, lockedMods, 0, 0, 0);
+ sym = xkb_state_key_get_one_sym(latin_state, keycode);
+ xkb_state_unref(latin_state);
+ } else {
+ qWarning("QXcbKeyboard: failed to create a state for US keymap!");
+ }
+ }
+ }
+ if (sym == XKB_KEY_NoSymbol)
+ return sym;
+ // Check for uniqueness, consider the following setup:
+ // setxkbmap -layout us,ru,us -variant dvorak,, -option 'grp:ctrl_alt_toggle' (set 'ru' as active).
+ // In this setup, the user would expect to trigger a ctrl+q shortcut by pressing ctrl+<physical x key>,
+ // because "US dvorak" is higher up in the layout settings list. This check verifies that an obtained
+ // 'sym' can not be acquired by any other layout higher up in the user's layout list. If it can be acquired
+ // then the obtained key is not unique. This prevents ctrl+<physical q key> from generating a ctrl+q
+ // shortcut in the above described setup. We don't want ctrl+<physical x key> and ctrl+<physical q key> to
+ // generate the same shortcut event in this case.
+ const xcb_keycode_t minKeycode = connection()->setup()->min_keycode;
+ const xcb_keycode_t maxKeycode = connection()->setup()->max_keycode;
+ struct xkb_state *kb_state = xkb_state_new(xkb_keymap);
+ for (xkb_layout_index_t prevLayout = 0; prevLayout < layout; ++prevLayout) {
+ xkb_state_update_mask(kb_state, 0, latchedMods, lockedMods, 0, 0, prevLayout);
+ for (xcb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
+ xkb_keysym_t prevSym = xkb_state_key_get_one_sym(kb_state, code);
+ if (prevSym == sym) {
+ sym = XKB_KEY_NoSymbol;
+ break;
+ }
+ }
+ }
+ xkb_state_unref(kb_state);
+ return sym;
+}
+
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);
+ struct xkb_state *kb_state = xkb_state_new(xkb_keymap);
if (!kb_state) {
- qWarning("QXcbKeyboard: failed to compile xkb keymap");
+ 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_mask_t latchedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED);
xkb_mod_mask_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_state_update_mask(kb_state, 0, latchedMods, lockedMods, 0, 0, lockedLayout);
- xkb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, event->nativeScanCode());
+ quint32 keycode = event->nativeScanCode();
+ xkb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, keycode);
if (sym == XKB_KEY_NoSymbol) {
xkb_state_unref(kb_state);
return QList<int>();
}
QList<int> result;
- int baseQtKey = keysymToQtKey(sym, modifiers, lookupString(kb_state, event->nativeScanCode()));
+ int baseQtKey = keysymToQtKey(sym, modifiers, lookupString(kb_state, keycode));
result += (baseQtKey + modifiers); // The base key is _always_ valid, of course
xkb_mod_index_t shiftMod = xkb_keymap_mod_get_index(xkb_keymap, "Shift");
@@ -866,48 +968,33 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
Q_ASSERT(controlMod < 32);
xkb_mod_mask_t depressed;
- struct xkb_keymap *fallback_keymap = 0;
int qtKey = 0;
- //obtain a list of possible shortcuts for the given key event
+ // 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
if (i == 8) {
- // Add a fall back key for layouts with non Latin-1 characters
- if (baseQtKey > 255) {
- struct xkb_rule_names names = { xkb_names.rules, xkb_names.model, "us", 0, 0 };
- fallback_keymap = xkb_keymap_new_from_names(xkb_context, &names, (xkb_keymap_compile_flags)0);
- if (!fallback_keymap)
- continue;
- xkb_state_unref(kb_state);
- kb_state = xkb_state_new(fallback_keymap);
- if (!kb_state)
- continue;
- } else
+ if (isLatin(baseQtKey))
continue;
+ // add a latin key as a fall back key
+ sym = lookupLatinKeysym(keycode);
} else {
- xkb_state_update_mask(kb_state, depressed, latchedMods, lockedMods,
- baseLayout, latchedLayout, lockedLayout);
+ depressed = 0;
+ if (neededMods & Qt::AltModifier)
+ depressed |= (1 << altMod);
+ if (neededMods & Qt::ShiftModifier)
+ depressed |= (1 << shiftMod);
+ if (neededMods & Qt::ControlModifier)
+ depressed |= (1 << controlMod);
+ xkb_state_update_mask(kb_state, depressed, latchedMods, lockedMods, 0, 0, lockedLayout);
+ sym = xkb_state_key_get_one_sym(kb_state, keycode);
}
- 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, lookupString(kb_state, event->nativeScanCode()));
-
- if (qtKey == baseQtKey || qtKey == 0)
+ qtKey = keysymToQtKey(sym, mods, lookupString(kb_state, keycode));
+ if (!qtKey || qtKey == baseQtKey)
continue;
// catch only more specific shortcuts, i.e. Ctrl+Shift+= also generates Ctrl++ and +,
@@ -926,8 +1013,6 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
}
}
xkb_state_unref(kb_state);
- xkb_keymap_unref(fallback_keymap);
-
return result;
}
@@ -1002,6 +1087,8 @@ QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection)
, xkb_context(0)
, xkb_keymap(0)
, xkb_state(0)
+ , latin_keymap(0)
+ , m_hasLatinLayout(false)
{
memset(&xkb_names, 0, sizeof(xkb_names));
#ifndef QT_NO_XKB
@@ -1029,6 +1116,7 @@ QXcbKeyboard::~QXcbKeyboard()
xkb_state_unref(xkb_state);
xkb_keymap_unref(xkb_keymap);
xkb_context_unref(xkb_context);
+ xkb_keymap_unref(latin_keymap);
if (!connection()->hasXKB())
xcb_key_symbols_free(m_key_symbols);
clearXKBConfig();
@@ -1324,7 +1412,6 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
if (type == QEvent::KeyPress)
targetWindow->updateNetWmUserTime(time);
- // 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);
QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext();
@@ -1348,15 +1435,22 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
return;
}
- Qt::KeyboardModifiers modifiers = translateModifiers(state);
-
QString string = lookupString(xkb_state, code);
int count = string.size();
string.truncate(count);
- int qtcode = keysymToQtKey(sym, modifiers, string);
- bool isAutoRepeat = false;
+ // Ιf control modifier is set we should prefer latin character, this is
+ // used for standard shortcuts in checks like "key == QKeySequence::Copy",
+ // users can still see the actual X11 keysym with QKeyEvent::nativeVirtualKey
+ Qt::KeyboardModifiers modifiers = translateModifiers(state);
+ xcb_keysym_t translatedSym = XKB_KEY_NoSymbol;
+ if (modifiers & Qt::ControlModifier && !isLatin(sym))
+ translatedSym = lookupLatinKeysym(code);
+ if (translatedSym == XKB_KEY_NoSymbol)
+ translatedSym = sym;
+ int qtcode = keysymToQtKey(translatedSym, modifiers, string);
+ bool isAutoRepeat = false;
if (type == QEvent::KeyPress) {
if (m_autorepeat_code == code) {
isAutoRepeat = true;
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h
index e71165d824..9f1cf165cb 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.h
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.h
@@ -91,6 +91,9 @@ protected:
void updateVModMapping();
void updateVModToRModMapping();
+ xkb_keysym_t lookupLatinKeysym(xkb_keycode_t keycode) const;
+ void checkForLatinLayout();
+
private:
bool m_config;
xcb_keycode_t m_autorepeat_code;
@@ -99,6 +102,7 @@ private:
struct xkb_keymap *xkb_keymap;
struct xkb_state *xkb_state;
struct xkb_rule_names xkb_names;
+ mutable struct xkb_keymap *latin_keymap;
struct _mod_masks {
uint alt;
@@ -128,6 +132,7 @@ private:
_mod_masks vmod_masks;
int core_device_id;
#endif
+ bool m_hasLatinLayout;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index 0d75a7f032..3058b29f2d 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -367,7 +367,7 @@ void *QXcbNativeInterface::x11Screen()
QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration());
QXcbConnection *defaultConnection = integration->defaultConnection();
if (defaultConnection)
- return reinterpret_cast<void *>(defaultConnection->primaryScreen());
+ return reinterpret_cast<void *>(defaultConnection->primaryScreenNumber());
return 0;
}
diff --git a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
index 9ec4ea80ec..40a50f61ab 100644
--- a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
+++ b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
@@ -59,7 +59,7 @@ QXcbSystemTrayTracker *QXcbSystemTrayTracker::create(QXcbConnection *connection)
const xcb_atom_t trayAtom = connection->atom(QXcbAtom::_NET_SYSTEM_TRAY_OPCODE);
if (!trayAtom)
return 0;
- const QByteArray netSysTray = QByteArrayLiteral("_NET_SYSTEM_TRAY_S") + QByteArray::number(connection->primaryScreen());
+ const QByteArray netSysTray = QByteArrayLiteral("_NET_SYSTEM_TRAY_S") + QByteArray::number(connection->primaryScreenNumber());
const xcb_atom_t selection = connection->internAtom(netSysTray.constData());
if (!selection)
return 0;
@@ -145,11 +145,8 @@ QRect QXcbSystemTrayTracker::systemTrayWindowGlobalGeometry(xcb_window_t window)
inline void QXcbSystemTrayTracker::emitSystemTrayWindowChanged()
{
- const int screen = m_connection->primaryScreen();
- if (screen >= 0 && screen < m_connection->screens().size()) {
- const QPlatformScreen *ps = m_connection->screens().at(screen);
+ if (const QPlatformScreen *ps = m_connection->primaryScreen())
emit systemTrayWindowChanged(ps->screen());
- }
}
// Client messages with the "MANAGER" atom on the root window indicate creation of a new tray.
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 0c2e9d047c..85af8ee1d2 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -2170,6 +2170,9 @@ void QXcbWindow::updateSyncRequestCounter()
bool QXcbWindow::setKeyboardGrabEnabled(bool grab)
{
+ if (grab && !connection()->canGrab())
+ return false;
+
if (!grab) {
xcb_ungrab_keyboard(xcb_connection(), XCB_TIME_CURRENT_TIME);
return true;
@@ -2185,6 +2188,9 @@ bool QXcbWindow::setKeyboardGrabEnabled(bool grab)
bool QXcbWindow::setMouseGrabEnabled(bool grab)
{
+ if (grab && !connection()->canGrab())
+ return false;
+
if (!grab) {
xcb_ungrab_pointer(xcb_connection(), XCB_TIME_CURRENT_TIME);
return true;
@@ -2380,13 +2386,10 @@ void QXcbWindow::setAlertState(bool enabled)
{
if (m_alertState == enabled)
return;
- const NetWmStates oldState = netWmStates();
+
m_alertState = enabled;
- if (enabled) {
- setNetWmStates(oldState | NetWmStateDemandsAttention);
- } else {
- setNetWmStates(oldState & ~NetWmStateDemandsAttention);
- }
+
+ changeNetWmState(enabled, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION));
}
bool QXcbWindow::needsSync() const
diff --git a/src/plugins/platforms/xcb/qxcbwmsupport.cpp b/src/plugins/platforms/xcb/qxcbwmsupport.cpp
index 0458be32f6..1be9ab3e05 100644
--- a/src/plugins/platforms/xcb/qxcbwmsupport.cpp
+++ b/src/plugins/platforms/xcb/qxcbwmsupport.cpp
@@ -56,7 +56,7 @@ void QXcbWMSupport::updateNetWMAtoms()
{
net_wm_atoms.clear();
- xcb_window_t root = connection()->screens().at(connection()->primaryScreen())->root();
+ xcb_window_t root = connection()->primaryScreen()->root();
int offset = 0;
int remaining = 0;
do {
@@ -90,7 +90,7 @@ void QXcbWMSupport::updateVirtualRoots()
if (!isSupportedByWM(atom(QXcbAtom::_NET_VIRTUAL_ROOTS)))
return;
- xcb_window_t root = connection()->screens().at(connection()->primaryScreen())->root();
+ xcb_window_t root = connection()->primaryScreen()->root();
int offset = 0;
int remaining = 0;
do {
diff --git a/src/plugins/platforms/xcb/qxcbxsettings.cpp b/src/plugins/platforms/xcb/qxcbxsettings.cpp
index 6f2e60c9be..13d42832db 100644
--- a/src/plugins/platforms/xcb/qxcbxsettings.cpp
+++ b/src/plugins/platforms/xcb/qxcbxsettings.cpp
@@ -262,6 +262,12 @@ QXcbXSettings::QXcbXSettings(QXcbScreen *screen)
d_ptr->initialized = true;
}
+QXcbXSettings::~QXcbXSettings()
+{
+ delete d_ptr;
+ d_ptr = 0;
+}
+
bool QXcbXSettings::initialized() const
{
Q_D(const QXcbXSettings);
diff --git a/src/plugins/platforms/xcb/qxcbxsettings.h b/src/plugins/platforms/xcb/qxcbxsettings.h
index 717fe559c9..3496cedf36 100644
--- a/src/plugins/platforms/xcb/qxcbxsettings.h
+++ b/src/plugins/platforms/xcb/qxcbxsettings.h
@@ -45,6 +45,7 @@ class QXcbXSettings : public QXcbWindowEventListener
Q_DECLARE_PRIVATE(QXcbXSettings)
public:
QXcbXSettings(QXcbScreen *screen);
+ ~QXcbXSettings();
bool initialized() const;
QVariant setting(const QByteArray &property) const;
diff --git a/src/plugins/platforms/xcb/xcb-plugin.pro b/src/plugins/platforms/xcb/xcb-plugin.pro
index 9aaafadcad..f14fcde73f 100644
--- a/src/plugins/platforms/xcb/xcb-plugin.pro
+++ b/src/plugins/platforms/xcb/xcb-plugin.pro
@@ -60,7 +60,7 @@ contains(QT_CONFIG, xcb-xlib) {
# to support custom cursors with depth > 1
contains(QT_CONFIG, xcb-render) {
DEFINES += XCB_USE_RENDER
- LIBS += -lxcb-render -lxcb-render-util -lXrender
+ LIBS += -lxcb-render -lxcb-render-util
}
# build with session management support