support changing tabbox mode
Allow to change from general window cruising to application specific cruising w/ releasing the Alt key BUG: 316544 FIXED-IN: 5.5 REVIEW: 125392
This commit is contained in:
parent
121d59ee28
commit
cb1005120a
2 changed files with 80 additions and 117 deletions
|
@ -1309,8 +1309,8 @@ void TabBox::oneStepThroughDesktopList(bool forward)
|
|||
*/
|
||||
void TabBox::keyPress(int keyQt)
|
||||
{
|
||||
bool forward = false;
|
||||
bool backward = false;
|
||||
enum Direction { Backward = -1, Steady = 0, Forward = 1 };
|
||||
Direction direction(Steady);
|
||||
|
||||
auto contains = [](const QKeySequence &shortcut, int key) -> bool {
|
||||
for (int i = 0; i < shortcut.count(); ++i) {
|
||||
|
@ -1320,136 +1320,98 @@ void TabBox::keyPress(int keyQt)
|
|||
}
|
||||
return false;
|
||||
};
|
||||
auto testBacktab = [&forward,&backward,keyQt,contains](const QKeySequence &forwardShortcut, const QKeySequence &backwardShortcut) {
|
||||
if (forward || backward || !(keyQt & Qt::ShiftModifier)) {
|
||||
return;
|
||||
}
|
||||
// a shortcut containing Shift+Tab will not fire as it is registered as Alt+Backtab
|
||||
// the keyQt we get does not contain the backtab, so we need to convert it
|
||||
// extract the modifiers, tests whether the key is tab and create a new test shortcut
|
||||
// containing the extracted modifiers and backtab instead of tab
|
||||
Qt::KeyboardModifiers mods = Qt::ShiftModifier;
|
||||
auto testMod = [&mods,keyQt](Qt::KeyboardModifier modifier) {
|
||||
if (keyQt & modifier) {
|
||||
mods |= modifier;
|
||||
}
|
||||
};
|
||||
// unfortunately we have to test each of the modifiers and cannot just and with ~NoModifier
|
||||
// we don't need the shift test as we already know that shift is hold
|
||||
testMod(Qt::ControlModifier);
|
||||
testMod(Qt::AltModifier);
|
||||
testMod(Qt::MetaModifier);
|
||||
testMod(Qt::KeypadModifier);
|
||||
testMod(Qt::GroupSwitchModifier);
|
||||
// Do not AND with Key_Tab! Key_Tab is 0x01000001 which would also return true for
|
||||
// Qt::Key_Backspace which is 0x01000003 and a whole bunch of other keys!
|
||||
|
||||
// tests whether a shortcut matches and handles pitfalls on ShiftKey invocation
|
||||
auto directionFor = [keyQt, contains](const QKeySequence &forward, const QKeySequence &backward) -> Direction {
|
||||
if (contains(forward, keyQt))
|
||||
return Forward;
|
||||
if (contains(backward, keyQt))
|
||||
return Backward;
|
||||
if (!(keyQt & Qt::ShiftModifier))
|
||||
return Steady;
|
||||
|
||||
// Before testing the unshifted key (Ctrl+A vs. Ctrl+Shift+a etc.), see whether this is +Shift+Tab
|
||||
// and check that against +Shift+Backtab (as well)
|
||||
Qt::KeyboardModifiers mods = Qt::ShiftModifier|Qt::ControlModifier|Qt::AltModifier|Qt::MetaModifier|Qt::KeypadModifier|Qt::GroupSwitchModifier;
|
||||
mods &= keyQt;
|
||||
if ((keyQt & ~mods) == Qt::Key_Tab) {
|
||||
forward = contains(forwardShortcut, mods | Qt::Key_Backtab);
|
||||
backward = contains(backwardShortcut, mods | Qt::Key_Backtab);
|
||||
if (contains(forward, mods | Qt::Key_Backtab))
|
||||
return Forward;
|
||||
if (contains(backward, mods | Qt::Key_Backtab))
|
||||
return Backward;
|
||||
}
|
||||
|
||||
// if the shortcuts do not match, try matching again after filtering the shift key from keyQt
|
||||
// it is needed to handle correctly the ALT+~ shorcut for example as it is coded as ALT+SHIFT+~ in keyQt
|
||||
if (contains(forward, keyQt & ~Qt::ShiftModifier))
|
||||
return Forward;
|
||||
if (contains(backward, keyQt & ~Qt::ShiftModifier))
|
||||
return Backward;
|
||||
|
||||
return Steady;
|
||||
};
|
||||
|
||||
if (m_tabGrab) {
|
||||
QKeySequence forwardShortcut;
|
||||
QKeySequence backwardShortcut;
|
||||
switch (mode()) {
|
||||
case TabBoxWindowsMode:
|
||||
forwardShortcut = m_cutWalkThroughWindows;
|
||||
backwardShortcut = m_cutWalkThroughWindowsReverse;
|
||||
static const int ModeCount = 4;
|
||||
static const TabBoxMode modes[ModeCount] = {
|
||||
TabBoxWindowsMode, TabBoxWindowsAlternativeMode,
|
||||
TabBoxCurrentAppWindowsMode, TabBoxCurrentAppWindowsAlternativeMode
|
||||
};
|
||||
static const QKeySequence cuts[2*ModeCount] = {
|
||||
// forward
|
||||
m_cutWalkThroughWindows, m_cutWalkThroughWindowsAlternative,
|
||||
m_cutWalkThroughCurrentAppWindows, m_cutWalkThroughCurrentAppWindowsAlternative,
|
||||
// backward
|
||||
m_cutWalkThroughWindowsReverse, m_cutWalkThroughWindowsAlternativeReverse,
|
||||
m_cutWalkThroughCurrentAppWindowsReverse, m_cutWalkThroughCurrentAppWindowsAlternativeReverse
|
||||
};
|
||||
bool testedCurrent = false; // in case of collision, prefer to stay in the current mode
|
||||
int i = 0, j = 0;
|
||||
while (true) {
|
||||
if (!testedCurrent && modes[i] != mode()) {
|
||||
++j;
|
||||
i = (i+1) % ModeCount;
|
||||
continue;
|
||||
}
|
||||
if (testedCurrent && modes[i] == mode()) {
|
||||
break;
|
||||
case TabBoxWindowsAlternativeMode:
|
||||
forwardShortcut = m_cutWalkThroughWindowsAlternative;
|
||||
backwardShortcut = m_cutWalkThroughWindowsAlternativeReverse;
|
||||
}
|
||||
testedCurrent = true;
|
||||
direction = directionFor(cuts[i], cuts[i+ModeCount]);
|
||||
if (direction != Steady) {
|
||||
if (modes[i] != mode()) {
|
||||
accept(false);
|
||||
setMode(modes[i]);
|
||||
auto replayWithChangedTabboxMode = [this, direction]() {
|
||||
reset();
|
||||
nextPrev(direction == Forward);
|
||||
};
|
||||
QTimer::singleShot(50, this, replayWithChangedTabboxMode);
|
||||
}
|
||||
break;
|
||||
case TabBoxCurrentAppWindowsMode:
|
||||
forwardShortcut = m_cutWalkThroughCurrentAppWindows;
|
||||
backwardShortcut = m_cutWalkThroughCurrentAppWindowsReverse;
|
||||
break;
|
||||
case TabBoxCurrentAppWindowsAlternativeMode:
|
||||
forwardShortcut = m_cutWalkThroughCurrentAppWindowsAlternative;
|
||||
backwardShortcut = m_cutWalkThroughCurrentAppWindowsAlternativeReverse;
|
||||
break;
|
||||
default:
|
||||
} else if (++j > ModeCount) { // guarding counter for invalid modes
|
||||
qCDebug(KWIN_TABBOX) << "Invalid TabBoxMode";
|
||||
return;
|
||||
}
|
||||
forward = contains(forwardShortcut, keyQt);
|
||||
backward = contains(backwardShortcut, keyQt);
|
||||
testBacktab(forwardShortcut, backwardShortcut);
|
||||
if ((keyQt & Qt::ShiftModifier) && !(forward || backward)) {
|
||||
// if the shortcuts do not match, try matching again after filtering the shift key from keyQt
|
||||
// it is needed to handle correctly the ALT+~ shorcut for example as it is coded as ALT+SHIFT+~ in keyQt
|
||||
keyQt &= ~Qt::ShiftModifier;
|
||||
forward = contains(forwardShortcut, keyQt);
|
||||
backward = contains(backwardShortcut, keyQt);
|
||||
if (!(forward || backward)) {
|
||||
// the tabkey is however overly special and withdrawing the shift state will not turn backtab into tab
|
||||
// yet kglobalaccel fires for both. since we ensure this is in a Shift condition, try the other key
|
||||
// TODO: Check requirement regarding Qt5
|
||||
|
||||
// NOTICE: it is very important to restore the Shift modifier, since otherwise we can't distiguish
|
||||
// between the regular alt+tab / alt+shift+tab anymore!!
|
||||
if ((keyQt & Qt::Key_Backtab) == Qt::Key_Backtab) {// regular case
|
||||
keyQt &= ~Qt::Key_Backtab;
|
||||
keyQt |= (Qt::Key_Tab|Qt::ShiftModifier);
|
||||
} else if ((keyQt & Qt::Key_Tab) == Qt::Key_Tab) { // just to be very sure ... :-(
|
||||
keyQt &= ~Qt::Key_Tab;
|
||||
keyQt |= (Qt::Key_Backtab|Qt::ShiftModifier);
|
||||
}
|
||||
forward = contains(forwardShortcut, keyQt);
|
||||
backward = contains(backwardShortcut, keyQt);
|
||||
}
|
||||
i = (i+1) % ModeCount;
|
||||
}
|
||||
if (forward || backward) {
|
||||
qCDebug(KWIN_TABBOX) << "== " << forwardShortcut.toString()
|
||||
<< " or " << backwardShortcut.toString();
|
||||
KDEWalkThroughWindows(forward);
|
||||
if (direction != Steady) {
|
||||
qCDebug(KWIN_TABBOX) << "== " << cuts[i].toString() << " or " << cuts[i+ModeCount].toString();
|
||||
KDEWalkThroughWindows(direction == Forward);
|
||||
}
|
||||
} else if (m_desktopGrab) {
|
||||
forward = contains(m_cutWalkThroughDesktops, keyQt) ||
|
||||
contains(m_cutWalkThroughDesktopList, keyQt);
|
||||
backward = contains(m_cutWalkThroughDesktopsReverse, keyQt) ||
|
||||
contains(m_cutWalkThroughDesktopListReverse, keyQt);
|
||||
testBacktab(m_cutWalkThroughDesktops, m_cutWalkThroughDesktopsReverse);
|
||||
testBacktab(m_cutWalkThroughDesktopList, m_cutWalkThroughDesktopListReverse);
|
||||
if ((keyQt & Qt::ShiftModifier) && !(forward || backward)) {
|
||||
// if the shortcuts do not match, try matching again after filtering the shift key from keyQt
|
||||
// it is needed to handle correctly the ALT+~ shorcut for example as it is coded as ALT+SHIFT+~ in keyQt
|
||||
keyQt &= ~Qt::ShiftModifier;
|
||||
forward = contains(m_cutWalkThroughDesktops, keyQt) ||
|
||||
contains(m_cutWalkThroughDesktopList, keyQt);
|
||||
backward = contains(m_cutWalkThroughDesktopsReverse, keyQt) ||
|
||||
contains(m_cutWalkThroughDesktopListReverse, keyQt);
|
||||
if (!(forward || backward)) {
|
||||
// the tabkey is however overly special and withdrawing the shift state will not turn backtab into tab
|
||||
// yet kglobalaccel fires for both. since we ensure this is in a Shift condition, try the other key
|
||||
// TODO: Check requirement regarding Qt5
|
||||
|
||||
// NOTICE: it is very important to restore the Shift modifier, since otherwise we can't distiguish
|
||||
// between the regular alt+tab / alt+shift+tab anymore!!
|
||||
if ((keyQt & Qt::Key_Backtab) == Qt::Key_Backtab) {// regular case
|
||||
keyQt &= ~Qt::Key_Backtab;
|
||||
keyQt |= (Qt::Key_Tab|Qt::ShiftModifier);
|
||||
} else if ((keyQt & Qt::Key_Tab) == Qt::Key_Tab) { // just to be very sure ... :-(
|
||||
keyQt &= ~Qt::Key_Tab;
|
||||
keyQt |= (Qt::Key_Backtab|Qt::ShiftModifier);
|
||||
}
|
||||
forward = contains(m_cutWalkThroughDesktops, keyQt) ||
|
||||
contains(m_cutWalkThroughDesktopList, keyQt);
|
||||
backward = contains(m_cutWalkThroughDesktopsReverse, keyQt) ||
|
||||
contains(m_cutWalkThroughDesktopListReverse, keyQt);
|
||||
}
|
||||
}
|
||||
if (forward || backward)
|
||||
walkThroughDesktops(forward);
|
||||
direction = directionFor(m_cutWalkThroughDesktops, m_cutWalkThroughDesktopsReverse);
|
||||
if (direction == Steady)
|
||||
direction = directionFor(m_cutWalkThroughDesktopList, m_cutWalkThroughDesktopListReverse);
|
||||
if (direction != Steady)
|
||||
walkThroughDesktops(direction == Forward);
|
||||
}
|
||||
|
||||
if (m_desktopGrab || m_tabGrab) {
|
||||
if (((keyQt & ~Qt::KeyboardModifierMask) == Qt::Key_Escape)
|
||||
&& !(forward || backward)) {
|
||||
if (((keyQt & ~Qt::KeyboardModifierMask) == Qt::Key_Escape) && direction == Steady) {
|
||||
// if Escape is part of the shortcut, don't cancel
|
||||
close(true);
|
||||
} else if (!(forward || backward)) {
|
||||
} else if (direction == Steady) {
|
||||
QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, keyQt & ~Qt::KeyboardModifierMask, Qt::NoModifier);
|
||||
grabbedKeyEvent(event);
|
||||
}
|
||||
|
@ -1467,10 +1429,11 @@ void TabBox::close(bool abort)
|
|||
m_noModifierGrab = false;
|
||||
}
|
||||
|
||||
void TabBox::accept()
|
||||
void TabBox::accept(bool closeTabBox)
|
||||
{
|
||||
AbstractClient *c = currentClient();
|
||||
close();
|
||||
if (closeTabBox)
|
||||
close();
|
||||
if (c) {
|
||||
Workspace::self()->activateClient(c);
|
||||
shadeActivate(c);
|
||||
|
|
|
@ -187,7 +187,7 @@ public:
|
|||
public Q_SLOTS:
|
||||
void show();
|
||||
void close(bool abort = false);
|
||||
void accept();
|
||||
void accept(bool closeTabBox = true);
|
||||
void slotWalkThroughDesktops();
|
||||
void slotWalkBackThroughDesktops();
|
||||
void slotWalkThroughDesktopList();
|
||||
|
|
Loading…
Reference in a new issue