Chord: suppress middle-click primary paste on both press and release
The X11 primary-selection paste was leaking through on the middle-button release because only the press was consumed. Now the middle button is consumed inside the editor on BOTH press and release (tracked via m_swallowMiddleRelease), fully suppressing primary paste there. The chord Cut uses edit_cut, which writes to the standard KDE clipboard (Klipper), so paste is the normal Ctrl+V / palette paste. All 5 ctest suites green.
This commit is contained in:
parent
75367f85ef
commit
87f5587bd4
11
docs/PLAN.md
11
docs/PLAN.md
|
|
@ -131,10 +131,13 @@ Therefore the palette is replaced, not extended, and the replacement is built on
|
|||
### Mouse chording (Acme-style) — DONE (first increment)
|
||||
- Left+middle chord = **Cut**: with the left button held while selecting
|
||||
(button 1 anchor), a tap of the middle button (button 2) cuts the current
|
||||
selection. Driven by the same application event filter — it tracks the left
|
||||
button held inside the view and, on a middle press while held, triggers
|
||||
`edit_cut` and consumes the event. Middle-click alone (no left held) still
|
||||
does the usual primary-selection paste.
|
||||
selection via `edit_cut`, which uses the **standard KDE clipboard**
|
||||
(Klipper-backed), not the X11 primary selection.
|
||||
- **Middle-click primary paste is suppressed** inside the editor. Kate pastes
|
||||
the primary selection on the middle event; the filter consumes the middle
|
||||
button on **both press and release** (swallowing only the press let the paste
|
||||
leak through on release). So middle-click no longer pastes in the editor —
|
||||
paste is the normal `Ctrl+V` / palette paste from the KDE clipboard.
|
||||
- Right-button chords are intentionally **not** ported — the right button is the
|
||||
radial gesture. (Revisit later.)
|
||||
- The radial gesture is suppressed while the left button is held, so an RMB tap
|
||||
|
|
|
|||
|
|
@ -347,25 +347,38 @@ bool OllieView::eventFilter(QObject *obj, QEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
// Acme-style left+middle chord = Cut. Button 1 (left) held while selecting
|
||||
// is the anchor; a tap of button 2 (middle) cuts the current selection.
|
||||
// Acme-style left+middle chord = Cut, and suppression of X11 primary-
|
||||
// selection paste. Middle-button events inside the view are consumed on
|
||||
// BOTH press and release (Kate pastes the primary selection on the middle
|
||||
// event; swallowing only the press lets the paste leak through on release).
|
||||
// When the left button is held, the middle tap cuts the current selection
|
||||
// via edit_cut, which uses the standard KDE clipboard (Klipper-backed).
|
||||
// Right-button chords are intentionally not ported (RMB is the radial).
|
||||
// Middle-click alone (no left held) still does the usual primary paste.
|
||||
if (event->type() == QEvent::MouseButtonRelease) {
|
||||
if (static_cast<QMouseEvent *>(event)->button() == Qt::LeftButton) {
|
||||
auto *mev = static_cast<QMouseEvent *>(event);
|
||||
if (mev->button() == Qt::LeftButton) {
|
||||
m_leftDownInView = false;
|
||||
}
|
||||
if (mev->button() == Qt::MiddleButton && m_swallowMiddleRelease) {
|
||||
m_swallowMiddleRelease = false;
|
||||
return true; // suppress the primary paste that fires on release
|
||||
}
|
||||
} else if (event->type() == QEvent::MouseButtonPress) {
|
||||
auto *mev = static_cast<QMouseEvent *>(event);
|
||||
KTextEditor::View *v = m_mainWindow->activeView();
|
||||
auto *w = qobject_cast<QWidget *>(obj);
|
||||
const bool inView = v && w && v->isAncestorOf(w);
|
||||
|
||||
if (mev->button() == Qt::MiddleButton && m_leftDownInView && inView) {
|
||||
if (QAction *cut = findActionByName(QStringLiteral("edit_cut"))) {
|
||||
cut->trigger();
|
||||
if (mev->button() == Qt::MiddleButton && inView) {
|
||||
if (m_leftDownInView) {
|
||||
if (QAction *cut = findActionByName(QStringLiteral("edit_cut"))) {
|
||||
cut->trigger();
|
||||
}
|
||||
}
|
||||
return true; // consume: this is the chord, not a primary paste
|
||||
// Consume press (and its release) to suppress middle-click primary
|
||||
// paste entirely inside the editor.
|
||||
m_swallowMiddleRelease = true;
|
||||
return true;
|
||||
}
|
||||
if (mev->button() == Qt::LeftButton && inView) {
|
||||
m_leftDownInView = true; // anchor set; selection proceeds normally
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ private:
|
|||
QHash<int, int> m_buttonToRadial; // Qt::MouseButton (int) -> def index
|
||||
bool m_gestureActive = false; // an RMB drag gesture is in progress
|
||||
bool m_leftDownInView = false; // LMB held inside the view (Acme chord anchor)
|
||||
bool m_swallowMiddleRelease = false; // swallow the release paired with a consumed middle press
|
||||
QHash<QString, QPointer<QAction>> m_actionsById;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue