Merge branch 'Plasma/5.8'
commit
9eede1c66b
|
@ -50,6 +50,7 @@ private Q_SLOTS:
|
|||
void testConsumedShift();
|
||||
void testRepeatedTrigger();
|
||||
void testUserActionsMenu();
|
||||
void testMetaShiftW();
|
||||
};
|
||||
|
||||
void GlobalShortcutsTest::initTestCase()
|
||||
|
@ -168,5 +169,31 @@ void GlobalShortcutsTest::testUserActionsMenu()
|
|||
kwinApp()->platform()->keyboardKeyReleased(KEY_LEFTALT, timestamp++);
|
||||
}
|
||||
|
||||
void GlobalShortcutsTest::testMetaShiftW()
|
||||
{
|
||||
// BUG 370341
|
||||
QScopedPointer<QAction> action(new QAction(nullptr));
|
||||
action->setProperty("componentName", QStringLiteral(KWIN_NAME));
|
||||
action->setObjectName(QStringLiteral("globalshortcuts-test-meta-shift-w"));
|
||||
QSignalSpy triggeredSpy(action.data(), &QAction::triggered);
|
||||
QVERIFY(triggeredSpy.isValid());
|
||||
KGlobalAccel::self()->setShortcut(action.data(), QList<QKeySequence>{Qt::META + Qt::SHIFT + Qt::Key_W}, KGlobalAccel::NoAutoloading);
|
||||
input()->registerShortcut(Qt::META + Qt::SHIFT + Qt::Key_W, action.data());
|
||||
|
||||
// press meta+shift+w
|
||||
quint32 timestamp = 0;
|
||||
kwinApp()->platform()->keyboardKeyPressed(KEY_LEFTMETA, timestamp++);
|
||||
QCOMPARE(input()->keyboardModifiers(), Qt::MetaModifier);
|
||||
kwinApp()->platform()->keyboardKeyPressed(KEY_LEFTSHIFT, timestamp++);
|
||||
QCOMPARE(input()->keyboardModifiers(), Qt::ShiftModifier | Qt::MetaModifier);
|
||||
kwinApp()->platform()->keyboardKeyPressed(KEY_W, timestamp++);
|
||||
QTRY_COMPARE(triggeredSpy.count(), 1);
|
||||
kwinApp()->platform()->keyboardKeyReleased(KEY_W, timestamp++);
|
||||
|
||||
// release meta+shift
|
||||
kwinApp()->platform()->keyboardKeyReleased(KEY_LEFTSHIFT, timestamp++);
|
||||
kwinApp()->platform()->keyboardKeyReleased(KEY_LEFTMETA, timestamp++);
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(GlobalShortcutsTest)
|
||||
#include "globalshortcuts_test.moc"
|
||||
|
|
|
@ -1246,7 +1246,9 @@ void InputRedirection::setupLibInput()
|
|||
}
|
||||
|
||||
conn->setInputConfig(m_inputConfig);
|
||||
conn->updateLEDs(m_keyboard->xkb()->leds());
|
||||
conn->setup();
|
||||
connect(m_keyboard, &KeyboardInputRedirection::ledsChanged, conn, &LibInput::Connection::updateLEDs);
|
||||
connect(conn, &LibInput::Connection::eventsRead, this,
|
||||
[this] {
|
||||
m_libInput->processEvents();
|
||||
|
|
|
@ -160,6 +160,19 @@ RulesWidget::RulesWidget(QWidget* parent)
|
|||
|
||||
KColorSchemeManager *schemes = new KColorSchemeManager(this);
|
||||
decocolor->setModel(schemes->model());
|
||||
|
||||
// hide autogrouping as it's currently not supported
|
||||
// BUG 370301
|
||||
line_11->hide();
|
||||
enable_autogroup->hide();
|
||||
autogroup->hide();
|
||||
rule_autogroup->hide();
|
||||
enable_autogroupid->hide();
|
||||
autogroupid->hide();
|
||||
rule_autogroupid->hide();
|
||||
enable_autogroupfg->hide();
|
||||
autogroupfg->hide();
|
||||
rule_autogroupfg->hide();
|
||||
}
|
||||
|
||||
#undef SETUP
|
||||
|
|
|
@ -90,10 +90,15 @@ Xkb::Xkb(InputRedirection *input)
|
|||
, m_controlModifier(0)
|
||||
, m_altModifier(0)
|
||||
, m_metaModifier(0)
|
||||
, m_numLock(0)
|
||||
, m_capsLock(0)
|
||||
, m_scrollLock(0)
|
||||
, m_modifiers(Qt::NoModifier)
|
||||
, m_consumedModifiers(Qt::NoModifier)
|
||||
, m_keysym(XKB_KEY_NoSymbol)
|
||||
, m_leds()
|
||||
{
|
||||
qRegisterMetaType<KWin::Xkb::LEDs>();
|
||||
if (!m_context) {
|
||||
qCDebug(KWIN_XKB) << "Could not create xkb context";
|
||||
} else {
|
||||
|
@ -219,6 +224,11 @@ void Xkb::updateKeymap(xkb_keymap *keymap)
|
|||
m_controlModifier = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_CTRL);
|
||||
m_altModifier = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_ALT);
|
||||
m_metaModifier = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_LOGO);
|
||||
|
||||
m_numLock = xkb_keymap_led_get_index(m_keymap, XKB_LED_NAME_NUM);
|
||||
m_capsLock = xkb_keymap_led_get_index(m_keymap, XKB_LED_NAME_CAPS);
|
||||
m_scrollLock = xkb_keymap_led_get_index(m_keymap, XKB_LED_NAME_SCROLL);
|
||||
|
||||
m_currentLayout = xkb_state_serialize_layout(m_state, XKB_STATE_LAYOUT_EFFECTIVE);
|
||||
|
||||
createKeymapFile();
|
||||
|
@ -346,6 +356,23 @@ void Xkb::updateModifiers()
|
|||
mods |= Qt::MetaModifier;
|
||||
}
|
||||
m_modifiers = mods;
|
||||
|
||||
// update LEDs
|
||||
LEDs leds;
|
||||
if (xkb_state_led_index_is_active(m_state, m_numLock) == 1) {
|
||||
leds = leds | LED::NumLock;
|
||||
}
|
||||
if (xkb_state_led_index_is_active(m_state, m_capsLock) == 1) {
|
||||
leds = leds | LED::CapsLock;
|
||||
}
|
||||
if (xkb_state_led_index_is_active(m_state, m_scrollLock) == 1) {
|
||||
leds = leds | LED::ScrollLock;
|
||||
}
|
||||
if (m_leds != leds) {
|
||||
m_leds = leds;
|
||||
emit m_input->keyboard()->ledsChanged(m_leds);
|
||||
}
|
||||
|
||||
const xkb_layout_index_t layout = xkb_state_serialize_layout(m_state, XKB_STATE_LAYOUT_EFFECTIVE);
|
||||
if (layout != m_currentLayout) {
|
||||
m_currentLayout = layout;
|
||||
|
@ -422,7 +449,18 @@ Qt::KeyboardModifiers Xkb::modifiersRelevantForGlobalShortcuts() const
|
|||
return mods;
|
||||
}
|
||||
|
||||
return mods & ~m_consumedModifiers;
|
||||
Qt::KeyboardModifiers consumedMods = m_consumedModifiers;
|
||||
if ((mods & Qt::ShiftModifier) && (consumedMods == Qt::ShiftModifier)) {
|
||||
// test whether current keysym is a letter
|
||||
// in that case the shift should be removed from the consumed modifiers again
|
||||
// otherwise it would not be possible to trigger e.g. Shift+W as a shortcut
|
||||
// see BUG: 370341
|
||||
if (QChar(toQtKey(m_keysym)).isLetter()) {
|
||||
consumedMods = Qt::KeyboardModifiers();
|
||||
}
|
||||
}
|
||||
|
||||
return mods & ~consumedMods;
|
||||
}
|
||||
|
||||
xkb_keysym_t Xkb::toKeysym(uint32_t key)
|
||||
|
@ -446,7 +484,7 @@ QString Xkb::toString(xkb_keysym_t keysym)
|
|||
return QString::fromUtf8(byteArray.constData());
|
||||
}
|
||||
|
||||
Qt::Key Xkb::toQtKey(xkb_keysym_t keysym)
|
||||
Qt::Key Xkb::toQtKey(xkb_keysym_t keysym) const
|
||||
{
|
||||
int key = Qt::Key_unknown;
|
||||
KKeyServer::symXToKeyQt(keysym, &key);
|
||||
|
|
|
@ -36,6 +36,7 @@ struct xkb_state;
|
|||
struct xkb_compose_table;
|
||||
struct xkb_compose_state;
|
||||
typedef uint32_t xkb_mod_index_t;
|
||||
typedef uint32_t xkb_led_index_t;
|
||||
typedef uint32_t xkb_keysym_t;
|
||||
|
||||
namespace KWin
|
||||
|
@ -64,13 +65,23 @@ public:
|
|||
return m_keysym;
|
||||
}
|
||||
QString toString(xkb_keysym_t keysym);
|
||||
Qt::Key toQtKey(xkb_keysym_t keysym);
|
||||
Qt::Key toQtKey(xkb_keysym_t keysym) const;
|
||||
Qt::KeyboardModifiers modifiers() const;
|
||||
Qt::KeyboardModifiers modifiersRelevantForGlobalShortcuts() const;
|
||||
bool shouldKeyRepeat(quint32 key) const;
|
||||
|
||||
void switchToNextLayout();
|
||||
|
||||
enum class LED {
|
||||
NumLock = 1 << 0,
|
||||
CapsLock = 1 << 1,
|
||||
ScrollLock = 1 << 2
|
||||
};
|
||||
Q_DECLARE_FLAGS(LEDs, LED)
|
||||
LEDs leds() const {
|
||||
return m_leds;
|
||||
}
|
||||
|
||||
private:
|
||||
xkb_keymap *loadKeymapFromConfig();
|
||||
xkb_keymap *loadDefaultKeymap();
|
||||
|
@ -87,6 +98,9 @@ private:
|
|||
xkb_mod_index_t m_controlModifier;
|
||||
xkb_mod_index_t m_altModifier;
|
||||
xkb_mod_index_t m_metaModifier;
|
||||
xkb_led_index_t m_numLock;
|
||||
xkb_led_index_t m_capsLock;
|
||||
xkb_led_index_t m_scrollLock;
|
||||
Qt::KeyboardModifiers m_modifiers;
|
||||
Qt::KeyboardModifiers m_consumedModifiers;
|
||||
xkb_keysym_t m_keysym;
|
||||
|
@ -100,6 +114,7 @@ private:
|
|||
xkb_compose_table *table = nullptr;
|
||||
xkb_compose_state *state = nullptr;
|
||||
} m_compose;
|
||||
LEDs m_leds;
|
||||
};
|
||||
|
||||
class KeyboardInputRedirection : public QObject
|
||||
|
@ -133,6 +148,9 @@ public:
|
|||
return m_xkb->modifiers();
|
||||
}
|
||||
|
||||
Q_SIGNALS:
|
||||
void ledsChanged(KWin::Xkb::LEDs);
|
||||
|
||||
private Q_SLOTS:
|
||||
void reconfigure();
|
||||
|
||||
|
@ -156,4 +174,7 @@ Qt::KeyboardModifiers Xkb::modifiers() const
|
|||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(KWin::Xkb::LED)
|
||||
Q_DECLARE_METATYPE(KWin::Xkb::LEDs)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -47,6 +47,21 @@ QThread *Connection::s_thread = nullptr;
|
|||
|
||||
static Context *s_context = nullptr;
|
||||
|
||||
static quint32 toLibinputLEDS(Xkb::LEDs leds)
|
||||
{
|
||||
quint32 libinputLeds = 0;
|
||||
if (leds.testFlag(Xkb::LED::NumLock)) {
|
||||
libinputLeds = libinputLeds | LIBINPUT_LED_NUM_LOCK;
|
||||
}
|
||||
if (leds.testFlag(Xkb::LED::CapsLock)) {
|
||||
libinputLeds = libinputLeds | LIBINPUT_LED_CAPS_LOCK;
|
||||
}
|
||||
if (leds.testFlag(Xkb::LED::ScrollLock)) {
|
||||
libinputLeds = libinputLeds | LIBINPUT_LED_SCROLL_LOCK;
|
||||
}
|
||||
return libinputLeds;
|
||||
}
|
||||
|
||||
Connection::Connection(QObject *parent)
|
||||
: Connection(nullptr, parent)
|
||||
{
|
||||
|
@ -95,6 +110,7 @@ Connection::Connection(Context *input, QObject *parent)
|
|||
, m_input(input)
|
||||
, m_notifier(nullptr)
|
||||
, m_mutex(QMutex::Recursive)
|
||||
, m_leds()
|
||||
{
|
||||
Q_ASSERT(m_input);
|
||||
|
||||
|
@ -246,6 +262,10 @@ void Connection::processEvents()
|
|||
}
|
||||
}
|
||||
applyDeviceConfig(device);
|
||||
|
||||
// enable possible leds
|
||||
libinput_device_led_update(device->device(), static_cast<libinput_led>(toLibinputLEDS(m_leds)));
|
||||
|
||||
emit deviceAdded(device);
|
||||
break;
|
||||
}
|
||||
|
@ -517,5 +537,18 @@ void Connection::toggleTouchpads()
|
|||
}
|
||||
}
|
||||
|
||||
void Connection::updateLEDs(Xkb::LEDs leds)
|
||||
{
|
||||
if (m_leds == leds) {
|
||||
return;
|
||||
}
|
||||
m_leds = leds;
|
||||
// update on devices
|
||||
const libinput_led l = static_cast<libinput_led>(toLibinputLEDS(leds));
|
||||
for (auto it = m_devices.constBegin(), end = m_devices.constEnd(); it != end; ++it) {
|
||||
libinput_device_led_update((*it)->device(), l);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#define KWIN_LIBINPUT_CONNECTION_H
|
||||
|
||||
#include "../input.h"
|
||||
#include "../keyboard_input.h"
|
||||
#include <kwinglobals.h>
|
||||
|
||||
#include <QObject>
|
||||
|
@ -82,6 +83,8 @@ public:
|
|||
return m_devices;
|
||||
}
|
||||
|
||||
void updateLEDs(KWin::Xkb::LEDs leds);
|
||||
|
||||
Q_SIGNALS:
|
||||
void keyChanged(quint32 key, KWin::InputRedirection::KeyboardKeyState, quint32 time, KWin::LibInput::Device *device);
|
||||
void pointerButtonChanged(quint32 button, KWin::InputRedirection::PointerButtonState state, quint32 time, KWin::LibInput::Device *device);
|
||||
|
@ -135,6 +138,7 @@ private:
|
|||
QVector<Device*> m_devices;
|
||||
KSharedConfigPtr m_config;
|
||||
bool m_touchpadsEnabled = true;
|
||||
Xkb::LEDs m_leds;
|
||||
|
||||
KWIN_SINGLETON(Connection)
|
||||
static QThread *s_thread;
|
||||
|
|
|
@ -92,6 +92,7 @@ public:
|
|||
*/
|
||||
bool isShown;
|
||||
TabBoxClient *lastRaisedClient, *lastRaisedClientSucc;
|
||||
int wheelAngleDelta = 0;
|
||||
|
||||
private:
|
||||
QObject *createSwitcherItem(bool desktopMode);
|
||||
|
@ -336,6 +337,10 @@ void TabBoxHandlerPrivate::show()
|
|||
// everything is prepared, so let's make the whole thing visible
|
||||
item->setVisible(true);
|
||||
}
|
||||
if (QWindow *w = window()) {
|
||||
wheelAngleDelta = 0;
|
||||
w->installEventFilter(q);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -607,6 +612,33 @@ QModelIndex TabBoxHandler::first() const
|
|||
return model->index(0, 0);
|
||||
}
|
||||
|
||||
bool TabBoxHandler::eventFilter(QObject *watched, QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::Wheel && watched == d->window()) {
|
||||
QWheelEvent *event = static_cast<QWheelEvent*>(e);
|
||||
// On x11 the delta for vertical scrolling might also be on X for whatever reason
|
||||
const int delta = qAbs(event->angleDelta().x()) > qAbs(event->angleDelta().y()) ? event->angleDelta().x() : event->angleDelta().y();
|
||||
d->wheelAngleDelta += delta;
|
||||
while (d->wheelAngleDelta <= -120) {
|
||||
d->wheelAngleDelta += 120;
|
||||
const QModelIndex index = nextPrev(true);
|
||||
if (index.isValid()) {
|
||||
setCurrentIndex(index);
|
||||
}
|
||||
}
|
||||
while (d->wheelAngleDelta >= 120) {
|
||||
d->wheelAngleDelta -= 120;
|
||||
const QModelIndex index = nextPrev(false);
|
||||
if (index.isValid()) {
|
||||
setCurrentIndex(index);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// pass on
|
||||
return QObject::eventFilter(watched, e);
|
||||
}
|
||||
|
||||
TabBoxHandler* tabBox = nullptr;
|
||||
|
||||
TabBoxClient::TabBoxClient()
|
||||
|
|
|
@ -334,6 +334,8 @@ public:
|
|||
*/
|
||||
QModelIndex first() const;
|
||||
|
||||
bool eventFilter(QObject *watcher, QEvent *event) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* This signal is fired when the TabBoxConfig changes
|
||||
|
|
Loading…
Reference in New Issue