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/qxcbkeyboard.cpp112
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp8
-rw-r--r--src/plugins/platforms/xcb/qxcbxsettings.cpp4
4 files changed, 84 insertions, 44 deletions
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index 5fbc23c049..2529fb8a83 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -583,7 +583,7 @@ static const Qt::KeyboardModifiers ModsTbl[] = {
Qt::AltModifier | Qt::ShiftModifier, // 5
Qt::AltModifier | Qt::ControlModifier, // 6
Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7
- Qt::NoModifier // Fall-back to raw Key_*
+ Qt::NoModifier // Fall-back to raw Key_*, for non-latin1 kb layouts
};
Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const
@@ -602,8 +602,9 @@ Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const
return ret;
}
-void QXcbKeyboard::readXKBConfig(struct xkb_rule_names *xkb_names)
+void QXcbKeyboard::readXKBConfig()
{
+ clearXKBConfig();
xcb_generic_error_t *error;
xcb_get_property_cookie_t cookie;
xcb_get_property_reply_t *config_reply;
@@ -634,15 +635,30 @@ void QXcbKeyboard::readXKBConfig(struct xkb_rule_names *xkb_names)
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]);
+ 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::clearXKBConfig()
+{
+ if (xkb_names.rules)
+ delete[] xkb_names.rules;
+ if (xkb_names.model)
+ delete[] xkb_names.model;
+ if (xkb_names.layout)
+ delete[] xkb_names.layout;
+ if (xkb_names.variant)
+ delete[] xkb_names.variant;
+ if (xkb_names.options)
+ delete[] xkb_names.options;
+ memset(&xkb_names, 0, sizeof(xkb_names));
+}
+
void QXcbKeyboard::updateKeymap()
{
m_config = true;
@@ -654,22 +670,13 @@ void QXcbKeyboard::updateKeymap()
return;
}
}
-
- struct xkb_rule_names xkb_names = {0, 0, 0, 0, 0};
-
- readXKBConfig(&xkb_names);
+ readXKBConfig();
// 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;
@@ -724,14 +731,14 @@ void QXcbKeyboard::updateXKBState(xcb_xkb_state_notify_event_t *state)
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);
+ const xkb_state_component 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)");
@@ -745,17 +752,22 @@ 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,
+ const quint32 modsDepressed = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_DEPRESSED);
+ const quint32 modsLatched = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED);
+ const quint32 modsLocked = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED);
+ const quint32 xkbMask = xkbModMask(state);
+
+ const quint32 latched = modsLatched & xkbMask;
+ const quint32 locked = modsLocked & xkbMask;
+ quint32 depressed = modsDepressed & xkbMask;
+ // set modifiers in depressed if they don't appear in any of the final masks
+ depressed |= ~(depressed | latched | locked) & xkbMask;
+
+ const xkb_state_component newState
+ = xkb_state_update_mask(xkb_state,
+ depressed,
+ latched,
+ locked,
0,
0,
(state >> 13) & 3); // bits 13 and 14 report the state keyboard group
@@ -838,7 +850,7 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(xkb_keymap, "Control");
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
for (uint i = 1; i < sizeof(ModsTbl) / sizeof(*ModsTbl) ; ++i) {
@@ -854,8 +866,23 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
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);
+ 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
+ continue;
+ } else {
+ 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)
@@ -870,8 +897,11 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
result += (qtKey + mods);
}
}
+ if (kb_state)
+ xkb_state_unref(kb_state);
+ if (fallback_keymap)
+ xkb_keymap_unref(fallback_keymap);
- xkb_state_unref(kb_state);
return result;
}
@@ -941,6 +971,7 @@ QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection)
, core_device_id(0)
#endif
{
+ memset(&xkb_names, 0, sizeof(xkb_names));
updateKeymap();
#ifndef QT_NO_XKB
if (connection->hasXKB()) {
@@ -982,6 +1013,7 @@ QXcbKeyboard::~QXcbKeyboard()
#ifdef QT_NO_XKB
xcb_key_symbols_free(m_key_symbols);
#endif
+ clearXKBConfig();
}
#ifndef QT_NO_XKB
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h
index 770a7eabea..0256602782 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.h
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.h
@@ -91,7 +91,8 @@ protected:
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);
+ void readXKBConfig();
+ void clearXKBConfig();
#ifdef QT_NO_XKB
void updateModifiers();
@@ -107,6 +108,7 @@ private:
struct xkb_context *xkb_context;
struct xkb_keymap *xkb_keymap;
struct xkb_state *xkb_state;
+ struct xkb_rule_names xkb_names;
struct _mod_masks {
uint alt;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index c95c4d95ba..35b95b84a1 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -1302,6 +1302,9 @@ QRect QXcbWindow::windowToWmGeometry(QRect r) const
r.translate(m_frameMargins.left(), m_frameMargins.top());
} else if (!frameInclusive && m_gravity == XCB_GRAVITY_NORTH_WEST) {
r.translate(-m_frameMargins.left(), -m_frameMargins.top());
+ } else if (!frameInclusive && m_gravity == XCB_GRAVITY_CENTER) {
+ r.translate(-(m_frameMargins.left() - m_frameMargins.right())/2,
+ -(m_frameMargins.top() - m_frameMargins.bottom())/2);
}
return r;
}
@@ -1643,7 +1646,8 @@ void QXcbWindow::handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event)
void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event)
{
- if (window() != QGuiApplication::focusWindow()) {
+ const bool isWheel = event->detail >= 4 && event->detail <= 7;
+ if (!isWheel && window() != QGuiApplication::focusWindow()) {
QWindow *w = static_cast<QWindowPrivate *>(QObjectPrivate::get(window()))->eventReceiver();
if (!(w->flags() & Qt::WindowDoesNotAcceptFocus))
w->requestActivate();
@@ -1665,7 +1669,7 @@ void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event)
Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
- if (event->detail >= 4 && event->detail <= 7) {
+ if (isWheel) {
// Logic borrowed from qapplication_x11.cpp
int delta = 120 * ((event->detail == 4 || event->detail == 6) ? 1 : -1);
bool hor = (((event->detail == 4 || event->detail == 5)
diff --git a/src/plugins/platforms/xcb/qxcbxsettings.cpp b/src/plugins/platforms/xcb/qxcbxsettings.cpp
index c106bd00f8..1423c6262d 100644
--- a/src/plugins/platforms/xcb/qxcbxsettings.cpp
+++ b/src/plugins/platforms/xcb/qxcbxsettings.cpp
@@ -221,6 +221,7 @@ QXcbXSettings::QXcbXSettings(QXcbScreen *screen)
xcb_intern_atom_reply_t *atom_reply = xcb_intern_atom_reply(screen->xcb_connection(),atom_cookie,&error);
if (error) {
qWarning() << Q_FUNC_INFO << "Failed to find XSETTINGS_S atom";
+ free(error);
return;
}
xcb_atom_t selection_owner_atom = atom_reply->atom;
@@ -233,14 +234,15 @@ QXcbXSettings::QXcbXSettings(QXcbScreen *screen)
xcb_get_selection_owner_reply(screen->xcb_connection(), selection_cookie, &error);
if (error) {
qWarning() << Q_FUNC_INFO << "Failed to get selection owner for XSETTINGS_S atom";
+ free(error);
return;
}
d_ptr->x_settings_window = selection_result->owner;
+ free(selection_result);
if (!d_ptr->x_settings_window) {
return;
}
- free(selection_result);
const uint32_t event = XCB_CW_EVENT_MASK;
const uint32_t event_mask[] = { XCB_EVENT_MASK_STRUCTURE_NOTIFY|XCB_EVENT_MASK_PROPERTY_CHANGE };