55#include <KDecoration2/Decoration>
56#include <KGlobalAccel>
57#include <KLocalizedString>
61#if KWIN_BUILD_SCREENLOCKER
62#include <KScreenLocker/KsldApp>
66#include <QDBusConnection>
67#include <QDBusMessage>
68#include <QDBusPendingCall>
71#include <qpa/qwindowsysteminterface.h>
73#include <xkbcommon/xkbcommon.h>
79using namespace std::literals;
243 if (event->isAutoRepeat()) {
248 const int keyCode =
event->nativeScanCode();
249 switch (event->type()) {
250 case QEvent::KeyPress:
253 case QEvent::KeyRelease:
263 if (!kwinApp()->inputMethod()) {
266 if (
auto keyboardGrab = kwinApp()->inputMethod()->keyboardGrab()) {
267 if (event->isAutoRepeat()) {
271 keyboardGrab->sendKey(
waylandServer()->display()->nextSerial(), event->timestamp(), event->nativeScanCode(), newState);
284 if (event->type() == QEvent::KeyPress && !event->isAutoRepeat()) {
286 if (keysym >= XKB_KEY_XF86Switch_VT_1 && keysym <= XKB_KEY_XF86Switch_VT_12) {
287 kwinApp()->session()->switchTo(keysym - XKB_KEY_XF86Switch_VT_1 + 1);
305 if (window && window->isClient() && window->isLockScreen()) {
311 if (event->type() == QEvent::MouseMove) {
312 if (pointerSurfaceAllowed()) {
314 seat->notifyPointerMotion(event->screenPos());
316 }
else if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) {
317 if (pointerSurfaceAllowed()) {
320 const auto state =
event->type() == QEvent::MouseButtonPress
323 seat->notifyPointerButton(nativeButton, state);
334 if (pointerSurfaceAllowed()) {
335 seat->notifyPointerFrame();
345 if (pointerSurfaceAllowed()) {
350 kwinAxisSourceToKWaylandAxisSource(
wheelEvent->axisSource()),
360 if (event->isAutoRepeat()) {
367#if KWIN_BUILD_SCREENLOCKER
368 event->setAccepted(
false);
369 QCoreApplication::sendEvent(ScreenLocker::KSldApp::self(), event);
370 if (event->isAccepted()) {
379 if (!keyboardSurfaceAllowed()) {
383 switch (event->type()) {
384 case QEvent::KeyPress:
387 case QEvent::KeyRelease:
395 bool touchDown(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
401 seat->setTimestamp(time);
402 if (touchSurfaceAllowed()) {
403 seat->notifyTouchDown(
id, pos);
407 bool touchMotion(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
413 seat->setTimestamp(time);
414 if (touchSurfaceAllowed()) {
415 seat->notifyTouchMotion(
id, pos);
419 bool touchUp(qint32
id, std::chrono::microseconds time)
override
425 seat->setTimestamp(time);
426 if (touchSurfaceAllowed()) {
427 seat->notifyTouchUp(
id);
436 bool pinchGestureUpdate(qreal scale, qreal angleDelta,
const QPointF &delta, std::chrono::microseconds time)
override
488 return t->isLockScreen() || t->isInputMethod() || t->isLockScreenOverlay();
494 bool pointerSurfaceAllowed()
const
498 bool keyboardSurfaceAllowed()
const
502 bool touchSurfaceAllowed()
const
535 bool touchDown(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
542 bool touchMotion(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
549 bool touchUp(qint32
id, std::chrono::microseconds time)
override
602 switch (event->type()) {
603 case QEvent::MouseMove:
606 case QEvent::MouseButtonRelease:
607 if (event->buttons() == Qt::NoButton) {
627 if (event->type() == QEvent::KeyPress) {
637 bool touchDown(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
646 bool touchMotion(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
662 bool touchUp(qint32
id, std::chrono::microseconds time)
override
668 if (m_id ==
id || !m_set) {
684 switch (event->type()) {
685 case QEvent::TabletMove:
688 case QEvent::TabletRelease:
711 switch (event->type()) {
712 case QEvent::MouseButtonRelease:
713 if (event->buttons() == Qt::NoButton) {
714 if (event->button() == Qt::RightButton) {
717 accept(event->globalPosition());
739 if (event->type() == QEvent::KeyPress) {
741 if (event->key() == Qt::Key_Escape) {
743 }
else if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return || event->key() == Qt::Key_Space) {
744 accept(
input()->globalPointer());
746 if (
input()->supportsPointerWarping()) {
749 if (event->key() == Qt::Key_Left) {
752 if (event->key() == Qt::Key_Right) {
755 if (event->key() == Qt::Key_Up) {
758 if (event->key() == Qt::Key_Down) {
761 if (event->modifiers() & Qt::ControlModifier) {
772 bool touchDown(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
777 m_touchPoints.insert(
id, pos);
781 bool touchMotion(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
786 auto it = m_touchPoints.find(
id);
787 if (it != m_touchPoints.end()) {
793 bool touchUp(qint32
id, std::chrono::microseconds time)
override
798 auto it = m_touchPoints.find(
id);
799 if (it != m_touchPoints.end()) {
800 const auto pos = it.value();
801 m_touchPoints.erase(it);
802 if (m_touchPoints.isEmpty()) {
817 m_callback = callback;
821 void start(std::function<
void(
const QPoint &)> callback)
825 m_pointSelectionFallback = callback;
834 m_callback = std::function<void(Window *)>();
835 m_pointSelectionFallback = std::function<void(const QPoint &)>();
838 m_touchPoints.clear();
845 if (m_pointSelectionFallback) {
846 m_pointSelectionFallback(QPoint(-1, -1));
850 void accept(
const QPointF &pos)
854 m_callback(
input()->findToplevel(pos));
856 if (m_pointSelectionFallback) {
857 m_pointSelectionFallback(pos.toPoint());
862 bool m_active =
false;
863 std::function<void(
Window *)> m_callback;
864 std::function<void(
const QPoint &)> m_pointSelectionFallback;
865 QMap<quint32, QPointF> m_touchPoints;
868#if KWIN_BUILD_GLOBALSHORTCUTS
869class GlobalShortcutFilter :
public InputEventFilter
872 GlobalShortcutFilter()
874 m_powerDown.setSingleShot(
true);
875 m_powerDown.setInterval(1000);
878 bool pointerEvent(MouseEvent *event, quint32 nativeButton)
override
880 if (event->type() == QEvent::MouseButtonPress) {
881 if (
input()->shortcuts()->processPointerPressed(event->modifiers(), event->buttons())) {
887 bool wheelEvent(WheelEvent *event)
override
889 if (event->modifiers() == Qt::NoModifier) {
893 if (event->angleDelta().x() < 0) {
895 }
else if (event->angleDelta().x() > 0) {
897 }
else if (event->angleDelta().y() < 0) {
899 }
else if (event->angleDelta().y() > 0) {
902 return input()->shortcuts()->processAxis(event->modifiers(), direction);
904 bool keyEvent(KeyEvent *event)
override
906 if (event->key() == Qt::Key_PowerOff) {
907 const auto modifiers =
static_cast<KeyEvent *
>(event)->modifiersRelevantForGlobalShortcuts();
908 if (event->type() == QEvent::KeyPress && !
event->isAutoRepeat()) {
909 auto passToShortcuts = [modifiers] {
910 input()->shortcuts()->processKey(modifiers, Qt::Key_PowerDown);
912 QObject::connect(&m_powerDown, &QTimer::timeout,
input()->shortcuts(), passToShortcuts, Qt::SingleShotConnection);
915 }
else if (event->type() == QEvent::KeyRelease) {
916 const bool ret = !m_powerDown.isActive() ||
input()->shortcuts()->processKey(modifiers, event->key());
920 }
else if (event->type() == QEvent::KeyPress) {
922 return input()->shortcuts()->processKey(
static_cast<KeyEvent *
>(event)->modifiersRelevantForGlobalShortcuts(), event->key());
924 }
else if (event->type() == QEvent::KeyRelease) {
926 return input()->shortcuts()->processKeyRelease(
static_cast<KeyEvent *
>(event)->modifiersRelevantForGlobalShortcuts(), event->key());
931 bool swipeGestureBegin(
int fingerCount, std::chrono::microseconds time)
override
933 m_touchpadGestureFingerCount = fingerCount;
934 if (m_touchpadGestureFingerCount >= 3) {
935 input()->shortcuts()->processSwipeStart(DeviceType::Touchpad, fingerCount);
941 bool swipeGestureUpdate(
const QPointF &delta, std::chrono::microseconds time)
override
943 if (m_touchpadGestureFingerCount >= 3) {
944 input()->shortcuts()->processSwipeUpdate(DeviceType::Touchpad, delta);
950 bool swipeGestureCancelled(std::chrono::microseconds time)
override
952 if (m_touchpadGestureFingerCount >= 3) {
953 input()->shortcuts()->processSwipeCancel(DeviceType::Touchpad);
959 bool swipeGestureEnd(std::chrono::microseconds time)
override
961 if (m_touchpadGestureFingerCount >= 3) {
962 input()->shortcuts()->processSwipeEnd(DeviceType::Touchpad);
968 bool pinchGestureBegin(
int fingerCount, std::chrono::microseconds time)
override
970 m_touchpadGestureFingerCount = fingerCount;
971 if (m_touchpadGestureFingerCount >= 3) {
972 input()->shortcuts()->processPinchStart(fingerCount);
978 bool pinchGestureUpdate(qreal scale, qreal angleDelta,
const QPointF &delta, std::chrono::microseconds time)
override
980 if (m_touchpadGestureFingerCount >= 3) {
981 input()->shortcuts()->processPinchUpdate(scale, angleDelta, delta);
987 bool pinchGestureEnd(std::chrono::microseconds time)
override
989 if (m_touchpadGestureFingerCount >= 3) {
990 input()->shortcuts()->processPinchEnd();
996 bool pinchGestureCancelled(std::chrono::microseconds time)
override
998 if (m_touchpadGestureFingerCount >= 3) {
999 input()->shortcuts()->processPinchCancel();
1005 bool touchDown(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
1007 if (m_gestureTaken) {
1008 input()->shortcuts()->processSwipeCancel(DeviceType::Touchscreen);
1009 m_gestureCancelled =
true;
1012 m_touchPoints.insert(
id, pos);
1013 if (m_touchPoints.count() == 1) {
1014 m_lastTouchDownTime = time;
1016 if (time - m_lastTouchDownTime > 250ms) {
1017 m_gestureCancelled =
true;
1020 m_lastTouchDownTime = time;
1022 auto physicalSize = output->
orientateSize(output->physicalSize());
1023 if (!physicalSize.isValid()) {
1024 physicalSize = QSize(190, 100);
1026 float xfactor = physicalSize.width() / (float)output->geometry().width();
1027 float yfactor = physicalSize.height() / (float)output->geometry().height();
1028 bool distanceMatch = std::any_of(m_touchPoints.constBegin(), m_touchPoints.constEnd(), [pos, xfactor, yfactor](
const auto &point) {
1029 QPointF p = pos - point;
1030 return std::abs(xfactor * p.x()) + std::abs(yfactor * p.y()) < 50;
1032 if (!distanceMatch) {
1033 m_gestureCancelled =
true;
1037 if (m_touchPoints.count() >= 3 && !m_gestureCancelled) {
1038 m_gestureTaken =
true;
1039 m_syntheticCancel =
true;
1040 input()->
processFilters(std::bind(&InputEventFilter::touchCancel, std::placeholders::_1));
1041 m_syntheticCancel =
false;
1042 input()->shortcuts()->processSwipeStart(DeviceType::Touchscreen, m_touchPoints.count());
1049 bool touchMotion(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
1051 if (m_gestureTaken) {
1052 if (m_gestureCancelled) {
1056 const auto physicalSize = output->
orientateSize(output->physicalSize());
1057 const float xfactor = physicalSize.width() / (float)output->geometry().width();
1058 const float yfactor = physicalSize.height() / (float)output->geometry().height();
1060 auto &point = m_touchPoints[id];
1061 const QPointF
dist = pos - point;
1062 const QPointF delta = QPointF(xfactor *
dist.x(), yfactor *
dist.y());
1063 input()->shortcuts()->processSwipeUpdate(DeviceType::Touchscreen, 5 * delta / m_touchPoints.size());
1070 bool touchUp(qint32
id, std::chrono::microseconds time)
override
1072 m_touchPoints.remove(
id);
1073 if (m_gestureTaken) {
1074 if (!m_gestureCancelled) {
1075 input()->shortcuts()->processSwipeEnd(DeviceType::Touchscreen);
1076 m_gestureCancelled =
true;
1078 m_gestureTaken &= m_touchPoints.count() > 0;
1079 m_gestureCancelled &= m_gestureTaken;
1082 m_gestureCancelled &= m_touchPoints.count() > 0;
1089 if (m_syntheticCancel) {
1092 const bool oldGestureTaken = m_gestureTaken;
1093 m_gestureTaken =
false;
1094 m_gestureCancelled =
false;
1095 m_touchPoints.clear();
1096 return oldGestureTaken;
1099 bool touchFrame()
override
1101 return m_gestureTaken;
1105 bool m_gestureTaken =
false;
1106 bool m_gestureCancelled =
false;
1107 bool m_syntheticCancel =
false;
1108 std::chrono::microseconds m_lastTouchDownTime = std::chrono::microseconds::zero();
1109 QPointF m_lastAverageDistance;
1110 QMap<int32_t, QPointF> m_touchPoints;
1111 int m_touchpadGestureFingerCount = 0;
1120enum class MouseAction {
1124std::pair<bool, bool> performWindowMouseAction(QMouseEvent *event,
Window *window, MouseAction action = MouseAction::ModifierOnly)
1127 bool wasAction =
false;
1129 if (!
input()->pointer()->isConstrained() && !
workspace()->globalShortcutsDisabled()) {
1131 switch (event->button()) {
1132 case Qt::LeftButton:
1135 case Qt::MiddleButton:
1138 case Qt::RightButton:
1147 if (action == MouseAction::ModifierAndWindow) {
1148 command = window->getMouseCommand(event->button(), &wasAction);
1152 return std::make_pair(wasAction, !window->performMouseCommand(command, event->globalPosition()));
1154 return std::make_pair(wasAction,
false);
1157std::pair<bool, bool> performWindowWheelAction(QWheelEvent *event,
Window *window, MouseAction action = MouseAction::ModifierOnly)
1159 bool wasAction =
false;
1162 if (!
input()->pointer()->isConstrained() && !
workspace()->globalShortcutsDisabled()) {
1167 if (action == MouseAction::ModifierAndWindow) {
1168 command = window->getWheelCommand(Qt::Vertical, &wasAction);
1172 return std::make_pair(wasAction, !window->performMouseCommand(command, event->globalPosition()));
1174 return std::make_pair(wasAction,
false);
1181 bool pointerEvent(
MouseEvent *event, quint32 nativeButton)
override
1183 if (!
input()->pointer()->focus() || !
input()->pointer()->focus()->isInternal()) {
1191 const bool isAccepted = QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(internal,
1192 event->position() - internal->position(),
1193 event->globalPosition(),
1197 event->modifiers());
1202 if (!
input()->pointer()->focus() || !
input()->pointer()->focus()->isInternal()) {
1206 const QPointF localPos =
event->globalPosition() - internal->position();
1207 QWheelEvent wheelEvent(localPos, event->globalPosition(), QPoint(),
1208 event->angleDelta() * -1,
1213 QCoreApplication::sendEvent(internal, &wheelEvent);
1214 return wheelEvent.isAccepted();
1216 bool keyEvent(
KeyEvent *event)
override
1219 QWindow *found =
nullptr;
1220 for (
auto it = windows.crbegin(); it != windows.crend(); ++it) {
1221 auto internal = qobject_cast<InternalWindow *>(*it);
1225 if (QWindow *w = internal->handle()) {
1226 if (!w->isVisible()) {
1229 if (!
workspace()->geometry().contains(w->geometry())) {
1232 if (w->property(
"_q_showWithoutActivating").toBool()) {
1235 if (w->property(
"outputOnly").toBool()) {
1238 if (w->flags().testFlag(Qt::ToolTip)) {
1245 if (QGuiApplication::focusWindow() != found) {
1246#if QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
1247 QWindowSystemInterface::handleWindowActivated(found);
1249 QWindowSystemInterface::handleFocusWindowChanged(found);
1256 Qt::Key key = xkb->
toQtKey(xkb->toKeysym(event->nativeScanCode()),
1257 event->nativeScanCode(),
1258 Qt::KeyboardModifiers(),
1260 QKeyEvent internalEvent(event->type(), key,
1261 event->modifiers(), event->nativeScanCode(), event->nativeVirtualKey(),
1262 event->nativeModifiers(), event->text());
1263 internalEvent.setAccepted(
false);
1264 if (QCoreApplication::sendEvent(found, &internalEvent)) {
1272 bool touchDown(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
1275 if (seat->isTouchSequence()) {
1280 if (touch->internalPressId() != -1) {
1282 m_pressedIds.insert(
id);
1286 seat->setTimestamp(time);
1287 if (!
input()->touch()->focus() || !
input()->touch()->focus()->isInternal()) {
1290 touch->setInternalPressId(
id);
1293 m_lastGlobalTouchPos = pos;
1294 m_lastLocalTouchPos = pos - internal->position();
1296 QEnterEvent enterEvent(m_lastLocalTouchPos, m_lastLocalTouchPos, pos);
1297 QCoreApplication::sendEvent(internal, &enterEvent);
1299 QMouseEvent e(QEvent::MouseButtonPress, m_lastLocalTouchPos, pos, Qt::LeftButton, Qt::LeftButton,
input()->keyboardModifiers());
1300 e.setAccepted(
false);
1301 QCoreApplication::sendEvent(internal, &e);
1304 bool touchMotion(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
1307 if (!
input()->touch()->focus() || !
input()->touch()->focus()->isInternal()) {
1310 if (touch->internalPressId() == -1) {
1314 if (touch->internalPressId() != qint32(
id) || m_pressedIds.contains(
id)) {
1319 m_lastGlobalTouchPos = pos;
1320 m_lastLocalTouchPos = pos - QPointF(internal->x(), internal->y());
1322 QMouseEvent e(QEvent::MouseMove, m_lastLocalTouchPos, m_lastGlobalTouchPos, Qt::LeftButton, Qt::LeftButton,
input()->keyboardModifiers());
1323 QCoreApplication::instance()->sendEvent(internal, &e);
1326 bool touchUp(qint32
id, std::chrono::microseconds time)
override
1329 const bool removed = m_pressedIds.remove(
id);
1330 if (touch->internalPressId() == -1) {
1334 if (touch->internalPressId() != qint32(
id)) {
1338 if (!
input()->touch()->focus() || !
input()->touch()->focus()->isInternal()) {
1343 QMouseEvent e(QEvent::MouseButtonRelease, m_lastLocalTouchPos, m_lastGlobalTouchPos, Qt::LeftButton, Qt::MouseButtons(),
input()->keyboardModifiers());
1344 e.setAccepted(
false);
1345 QCoreApplication::sendEvent(internal, &e);
1347 QEvent leaveEvent(QEvent::Leave);
1348 QCoreApplication::sendEvent(internal, &leaveEvent);
1350 m_lastGlobalTouchPos = QPointF();
1351 m_lastLocalTouchPos = QPointF();
1357 QSet<qint32> m_pressedIds;
1358 QPointF m_lastGlobalTouchPos;
1359 QPointF m_lastLocalTouchPos;
1367 m_scrollV120 +=
event->deltaV120();
1368 m_scrollDistance +=
event->delta();
1369 if (std::abs(m_scrollV120) >= 120 || (!event->
deltaV120() && std::abs(m_scrollDistance) >= 15)) {
1370 float ret = m_scrollDistance;
1372 m_scrollDistance = 0;
1380 float m_scrollDistance = 0;
1381 int m_scrollV120 = 0;
1393 const QPointF p =
event->screenPos() - decoration->window()->pos();
1394 switch (event->type()) {
1395 case QEvent::MouseMove: {
1396 QHoverEvent e(QEvent::HoverMove, p, p);
1397 QCoreApplication::instance()->sendEvent(decoration->decoration(), &e);
1398 decoration->window()->processDecorationMove(p, event->screenPos());
1401 case QEvent::MouseButtonPress:
1402 case QEvent::MouseButtonRelease: {
1403 const auto actionResult = performWindowMouseAction(event, decoration->window());
1404 if (actionResult.first) {
1405 return actionResult.second;
1407 QMouseEvent e(event->type(), p, event->screenPos(), event->button(), event->buttons(), event->modifiers());
1408 e.setTimestamp(std::chrono::duration_cast<std::chrono::milliseconds>(event->
timestamp()).count());
1409 e.setAccepted(
false);
1410 QCoreApplication::sendEvent(decoration->decoration(), &e);
1411 if (!e.isAccepted() && event->type() == QEvent::MouseButtonPress) {
1412 decoration->window()->processDecorationButtonPress(&e);
1414 if (event->type() == QEvent::MouseButtonRelease) {
1415 decoration->window()->processDecorationButtonRelease(&e);
1430 if (event->angleDelta().y() != 0) {
1432 const auto actionResult = performWindowWheelAction(event, decoration->window());
1433 if (actionResult.first) {
1434 return actionResult.second;
1437 const QPointF localPos =
event->globalPosition() - decoration->window()->pos();
1438 const Qt::Orientation orientation = (
event->angleDelta().x() != 0) ? Qt::Horizontal : Qt::Vertical;
1439 QWheelEvent e(localPos, event->globalPosition(), QPoint(),
1440 event->angleDelta(),
1445 e.setAccepted(
false);
1446 QCoreApplication::sendEvent(decoration, &e);
1447 if (e.isAccepted()) {
1450 if ((orientation == Qt::Vertical) && decoration->window()->titlebarPositionUnderMouse()) {
1451 if (
float delta = m_accumulator.
accumulate(event)) {
1453 event->globalPosition());
1458 bool touchDown(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
1461 if (seat->isTouchSequence()) {
1464 if (
input()->touch()->decorationPressId() != -1) {
1468 seat->setTimestamp(time);
1475 m_lastGlobalTouchPos = pos;
1476 m_lastLocalTouchPos = pos - decoration->window()->pos();
1478 QHoverEvent hoverEvent(QEvent::HoverMove, m_lastLocalTouchPos, m_lastLocalTouchPos);
1479 QCoreApplication::sendEvent(decoration->decoration(), &hoverEvent);
1481 QMouseEvent e(QEvent::MouseButtonPress, m_lastLocalTouchPos, pos, Qt::LeftButton, Qt::LeftButton,
input()->keyboardModifiers());
1482 e.setAccepted(
false);
1483 QCoreApplication::sendEvent(decoration->decoration(), &e);
1484 if (!e.isAccepted()) {
1485 decoration->window()->processDecorationButtonPress(&e);
1489 bool touchMotion(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
1495 if (
input()->touch()->decorationPressId() == -1) {
1498 if (
input()->touch()->decorationPressId() != qint32(
id)) {
1502 m_lastGlobalTouchPos = pos;
1503 m_lastLocalTouchPos = pos - decoration->window()->pos();
1505 QHoverEvent e(QEvent::HoverMove, m_lastLocalTouchPos, m_lastLocalTouchPos);
1506 QCoreApplication::instance()->sendEvent(decoration->decoration(), &e);
1507 decoration->window()->processDecorationMove(m_lastLocalTouchPos, pos);
1510 bool touchUp(qint32
id, std::chrono::microseconds time)
override
1515 if (
input()->touch()->decorationPressId() ==
id) {
1516 m_lastGlobalTouchPos = QPointF();
1517 m_lastLocalTouchPos = QPointF();
1523 if (
input()->touch()->decorationPressId() == -1) {
1526 if (
input()->touch()->decorationPressId() != qint32(
id)) {
1532 QMouseEvent e(QEvent::MouseButtonRelease, m_lastLocalTouchPos, m_lastGlobalTouchPos, Qt::LeftButton, Qt::MouseButtons(),
input()->keyboardModifiers());
1533 e.setAccepted(
false);
1534 QCoreApplication::sendEvent(decoration->decoration(), &e);
1535 decoration->window()->processDecorationButtonRelease(&e);
1537 QHoverEvent leaveEvent(QEvent::HoverLeave, QPointF(), QPointF());
1538 QCoreApplication::sendEvent(decoration->decoration(), &leaveEvent);
1540 m_lastGlobalTouchPos = QPointF();
1541 m_lastLocalTouchPos = QPointF();
1551 const QPointF p =
event->globalPosF() - decoration->window()->pos();
1552 switch (event->type()) {
1553 case QEvent::TabletMove:
1554 case QEvent::TabletEnterProximity: {
1555 QHoverEvent e(QEvent::HoverMove, p, p);
1556 QCoreApplication::instance()->sendEvent(decoration->decoration(), &e);
1557 decoration->window()->processDecorationMove(p, event->globalPosF());
1560 case QEvent::TabletPress:
1561 case QEvent::TabletRelease: {
1562 const bool isPressed =
event->type() == QEvent::TabletPress;
1563 QMouseEvent e(isPressed ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease,
1565 event->globalPosF(),
1567 isPressed ? Qt::LeftButton : Qt::MouseButtons(),
1569 e.setAccepted(
false);
1570 QCoreApplication::sendEvent(decoration->decoration(), &e);
1571 if (!e.isAccepted() && isPressed) {
1572 decoration->window()->processDecorationButtonPress(&e);
1574 if (event->type() == QEvent::TabletRelease) {
1575 decoration->window()->processDecorationButtonRelease(&e);
1579 case QEvent::TabletLeaveProximity: {
1580 QHoverEvent leaveEvent(QEvent::HoverLeave, QPointF(), QPointF());
1581 QCoreApplication::sendEvent(decoration->decoration(), &leaveEvent);
1592 QPointF m_lastGlobalTouchPos;
1593 QPointF m_lastLocalTouchPos;
1597#if KWIN_BUILD_TABBOX
1598class TabBoxInputFilter :
public InputEventFilter
1601 bool pointerEvent(MouseEvent *event, quint32 button)
override
1603 if (!workspace()->tabbox() || !workspace()->tabbox()->isGrabbed()) {
1606 return workspace()->tabbox()->handleMouseEvent(event);
1608 bool keyEvent(KeyEvent *event)
override
1614 seat->setFocusedKeyboardSurface(
nullptr);
1618 passToWaylandServer(event);
1620 if (event->type() == QEvent::KeyPress) {
1621 workspace()->tabbox()->keyPress(event->modifiers() | event->key());
1622 }
else if (
static_cast<KeyEvent *
>(event)->modifiersRelevantForGlobalShortcuts() == Qt::NoModifier) {
1623 workspace()->tabbox()->modifiersReleased();
1631 bool wheelEvent(WheelEvent *event)
override
1636 return workspace()->tabbox()->handleWheelEvent(event);
1650 bool touchDown(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
1653 if (m_touchInProgress ||
waylandServer()->seat()->isTouchSequence()) {
1656 m_touchInProgress =
false;
1660 if (
workspace()->screenEdges()->gestureRecognizer()->startSwipeGesture(pos) > 0) {
1661 m_touchInProgress =
true;
1668 bool touchMotion(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
1670 if (m_touchInProgress && m_id ==
id) {
1677 bool touchUp(qint32
id, std::chrono::microseconds time)
override
1679 if (m_touchInProgress && m_id ==
id) {
1681 m_touchInProgress =
false;
1688 bool m_touchInProgress =
false;
1702 if (event->type() != QEvent::MouseButtonPress) {
1706 if (!window || !window->
isClient()) {
1709 const auto actionResult = performWindowMouseAction(event, window, MouseAction::ModifierAndWindow);
1710 if (actionResult.first) {
1711 return actionResult.second;
1717 if (event->angleDelta().y() == 0) {
1722 if (!window || !window->
isClient()) {
1725 const auto actionResult = performWindowWheelAction(event, window, MouseAction::ModifierAndWindow);
1726 if (actionResult.first) {
1727 return actionResult.second;
1731 bool touchDown(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
1734 if (seat->isTouchSequence()) {
1738 if (!window || !window->
isClient()) {
1741 bool wasAction =
false;
1750 if (event->type() != QEvent::TabletPress) {
1754 if (!window || !window->
isClient()) {
1757 bool wasAction =
false;
1785 switch (event->type()) {
1786 case QEvent::MouseMove: {
1787 seat->notifyPointerMotion(event->globalPosition());
1789 if (!e->
delta().isNull()) {
1794 case QEvent::MouseButtonPress:
1797 case QEvent::MouseButtonRelease:
1808 seat->notifyPointerFrame();
1815 auto _event =
static_cast<WheelEvent *
>(event);
1816 seat->notifyPointerAxis(_event->orientation(), _event->delta(), _event->deltaV120(),
1817 kwinAxisSourceToKWaylandAxisSource(_event->axisSource()),
1823 if (event->isAutoRepeat()) {
1833 bool touchDown(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
1836 seat->setTimestamp(time);
1837 seat->notifyTouchDown(
id, pos);
1840 bool touchMotion(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
1843 seat->setTimestamp(time);
1844 seat->notifyTouchMotion(
id, pos);
1847 bool touchUp(qint32
id, std::chrono::microseconds time)
override
1850 seat->setTimestamp(time);
1851 seat->notifyTouchUp(
id);
1867 seat->setTimestamp(time);
1868 seat->startPointerPinchGesture(fingerCount);
1871 bool pinchGestureUpdate(qreal scale, qreal angleDelta,
const QPointF &delta, std::chrono::microseconds time)
override
1874 seat->setTimestamp(time);
1875 seat->updatePointerPinchGesture(delta, scale, angleDelta);
1881 seat->setTimestamp(time);
1882 seat->endPointerPinchGesture();
1888 seat->setTimestamp(time);
1889 seat->cancelPointerPinchGesture();
1896 seat->setTimestamp(time);
1897 seat->startPointerSwipeGesture(fingerCount);
1903 seat->setTimestamp(time);
1904 seat->updatePointerSwipeGesture(delta);
1910 seat->setTimestamp(time);
1911 seat->endPointerSwipeGesture();
1917 seat->setTimestamp(time);
1918 seat->cancelPointerSwipeGesture();
1924 seat->setTimestamp(time);
1925 seat->startPointerHoldGesture(fingerCount);
1931 seat->setTimestamp(time);
1932 seat->endPointerHoldGesture();
1938 seat->setTimestamp(time);
1939 seat->cancelPointerHoldGesture();
1944static SeatInterface *findSeat()
1950 return server->seat();
1961 if (
auto surfaceCursor = std::get_if<TabletSurfaceCursorV2 *>(&cursor)) {
1963 if ((*surfaceCursor) && (*surfaceCursor)->enteredSerial()) {
1964 if (!m_surfaceSource) {
1965 m_surfaceSource = std::make_unique<SurfaceCursorSource>();
1967 m_surfaceSource->update((*surfaceCursor)->surface(), (*surfaceCursor)->hotspot());
1974 if (
auto shapeCursor = std::get_if<QByteArray>(&cursor)) {
1975 shape = *shapeCursor;
1977 shape = QByteArrayLiteral(
"cross");
1981 if (!m_shapeSource) {
1982 m_shapeSource = std::make_unique<ShapeCursorSource>();
1984 m_shapeSource->setTheme(defaultCursor.
theme());
1985 m_shapeSource->setShape(shape);
1991 std::unique_ptr<ShapeCursorSource> m_shapeSource;
1992 std::unique_ptr<SurfaceCursorSource> m_surfaceSource;
2005 integrateDevice(device);
2007 connect(
input(), &InputRedirection::deviceAdded,
this, &TabletInputFilter::integrateDevice);
2008 connect(
input(), &InputRedirection::deviceRemoved,
this, &TabletInputFilter::removeDevice);
2010 auto tabletNextOutput =
new QAction(
this);
2011 tabletNextOutput->setProperty(
"componentName", QStringLiteral(
"kwin"));
2012 tabletNextOutput->setText(i18n(
"Move the tablet to the next output"));
2013 tabletNextOutput->setObjectName(QStringLiteral(
"Move Tablet to Next Output"));
2014 KGlobalAccel::setGlobalShortcut(tabletNextOutput, QList<QKeySequence>());
2015 connect(tabletNextOutput, &QAction::triggered,
this, &TabletInputFilter::trackNextOutput);
2025 return manager->
seat(findSeat());
2030 auto device = qobject_cast<LibInput::Device *>(inputDevice);
2031 if (!device || (!device->isTabletTool() && !device->isTabletPad())) {
2037 qCCritical(KWIN_CORE) <<
"Could not find tablet seat";
2040 struct udev_device *
const udev_device = libinput_device_get_udev_device(device->device());
2041 const char *devnode = udev_device_get_syspath(udev_device);
2046 tablet = tabletSeat->
addTablet(device->vendor(), device->product(), device->sysName(), device->name(), {QString::fromUtf8(devnode)});
2047 libinput_device_group_set_user_data(deviceGroup, tablet);
2050 if (device->isTabletPad()) {
2054 const int modes = libinput_device_tablet_pad_get_num_mode_groups(device->device());
2056 auto firstGroup = libinput_device_tablet_pad_get_mode_group(device->device(), 0);
2057 tabletSeat->
addTabletPad(device->sysName(), device->name(), {QString::fromUtf8(devnode)}, buttonsCount, ringsCount, stripsCount, modes, libinput_tablet_pad_mode_group_get_mode(firstGroup), tablet);
2064 if (outputs.isEmpty()) {
2068 int tabletToolCount = 0;
2071 for (
const auto device : devices) {
2072 if (!device->isTabletTool()) {
2077 if (device->outputName().isEmpty()) {
2078 device->setOutputName(outputs.constFirst()->name());
2079 changedDevice = device;
2083 auto it = std::find_if(outputs.begin(), outputs.end(), [device](
const auto &output) {
2084 return output->name() == device->outputName();
2087 auto nextOutput = it == outputs.end() ? outputs.first() : *it;
2088 device->setOutputName(nextOutput->name());
2089 changedDevice = device;
2091 const QString message = tabletToolCount == 1 ? i18n(
"Tablet moved to %1", changedDevice->
outputName()) : i18n(
"Tablets switched outputs");
2092 OSD::show(message, QStringLiteral(
"input-tablet"), 5000);
2097 auto device = qobject_cast<LibInput::Device *>(inputDevice);
2100 libinput_device_group_set_user_data(deviceGroup,
nullptr);
2106 qCCritical(KWIN_CORE) <<
"Could not find tablet to remove" << device->sysName();
2115 case InputRedirection::Pen:
2117 case InputRedirection::Eraser:
2118 return Type::Eraser;
2119 case InputRedirection::Brush:
2121 case InputRedirection::Pencil:
2122 return Type::Pencil;
2123 case InputRedirection::Airbrush:
2124 return Type::Airbrush;
2125 case InputRedirection::Finger:
2126 return Type::Finger;
2127 case InputRedirection::Mouse:
2129 case InputRedirection::Lens:
2131 case InputRedirection::Totem:
2143 case InputRedirection::Tilt:
2144 return TabletToolV2Interface::Tilt;
2145 case InputRedirection::Pressure:
2146 return TabletToolV2Interface::Pressure;
2147 case InputRedirection::Distance:
2148 return TabletToolV2Interface::Distance;
2149 case InputRedirection::Rotation:
2150 return TabletToolV2Interface::Rotation;
2151 case InputRedirection::Slider:
2152 return TabletToolV2Interface::Slider;
2153 case InputRedirection::Wheel:
2154 return TabletToolV2Interface::Wheel;
2156 return TabletToolV2Interface::Wheel;
2158 QList<TabletToolV2Interface::Capability> ifaceCapabilities;
2165 Cursors::self()->addCursor(cursor);
2166 m_cursorByTool[tool] = cursor;
2179 qCCritical(KWIN_CORE) <<
"Could not find tablet manager";
2184 tool = createTool(event->
tabletId());
2189 auto tablet =
static_cast<TabletV2Interface *
>(
event->tabletId().m_deviceGroupData);
2192 if (!window || !window->
surface()) {
2197 tool->setCurrentSurface(surface);
2199 if (!tool->isClientSupported() || (tablet && !tablet->isSurfaceSupported(surface))) {
2200 return emulateTabletEvent(event);
2203 switch (event->type()) {
2204 case QEvent::TabletMove: {
2205 const auto pos = window->
mapToLocal(event->globalPosF());
2206 tool->sendMotion(pos);
2207 m_cursorByTool[tool]->setPos(event->globalPosF());
2210 case QEvent::TabletEnterProximity: {
2211 const QPointF pos =
event->globalPosF();
2212 m_cursorByTool[tool]->setPos(pos);
2213 tool->sendProximityIn(tablet);
2214 tool->sendMotion(window->
mapToLocal(event->globalPosF()));
2217 case QEvent::TabletLeaveProximity:
2218 tool->sendProximityOut();
2220 case QEvent::TabletPress: {
2221 const auto pos = window->
mapToLocal(event->globalPosF());
2222 tool->sendMotion(pos);
2223 m_cursorByTool[tool]->setPos(event->globalPosF());
2227 case QEvent::TabletRelease:
2231 qCWarning(KWIN_CORE) <<
"Unexpected tablet event type" << event;
2234 const quint32 MAX_VAL = 65535;
2236 if (tool->hasCapability(TabletToolV2Interface::Pressure)) {
2237 tool->sendPressure(MAX_VAL * event->pressure());
2239 if (tool->hasCapability(TabletToolV2Interface::Tilt)) {
2240 tool->sendTilt(event->xTilt(), event->yTilt());
2242 if (tool->hasCapability(TabletToolV2Interface::Rotation)) {
2243 tool->sendRotation(event->rotation());
2246 tool->sendFrame(event->timestamp());
2256 switch (event->type()) {
2257 case QEvent::TabletMove:
2258 case QEvent::TabletEnterProximity:
2261 case QEvent::TabletPress:
2263 InputRedirection::PointerButtonPressed, std::chrono::milliseconds(event->timestamp()));
2265 case QEvent::TabletRelease:
2267 InputRedirection::PointerButtonReleased, std::chrono::milliseconds(event->timestamp()));
2269 case QEvent::TabletLeaveProximity:
2272 qCWarning(KWIN_CORE) <<
"Unexpected tablet event type" << event;
2283 tool = createTool(tabletToolId);
2285 if (!tool->isClientSupported()) {
2288 tool->sendButton(button, pressed);
2295 auto seat = findTabletSeat();
2302 auto pad = tablet->pad();
2306 pad->setCurrentSurface(surface, tablet);
2312 auto pad = findAndAdoptPad(tabletPadId);
2316 pad->sendButton(time, button, pressed);
2322 auto pad = findAndAdoptPad(tabletPadId);
2326 auto ring = pad->ring(number);
2328 ring->sendAngle(angle);
2330 ring->sendSource(TabletPadRingV2Interface::SourceFinger);
2332 ring->sendFrame(std::chrono::duration_cast<std::chrono::milliseconds>(time).count());
2338 auto pad = findAndAdoptPad(tabletPadId);
2342 auto strip = pad->strip(number);
2344 strip->sendPosition(position);
2346 strip->sendSource(TabletPadStripV2Interface::SourceFinger);
2348 strip->sendFrame(std::chrono::duration_cast<std::chrono::milliseconds>(time).count());
2357 auto surface = window->
surface();
2361 auto seat = waylandServer()->
seat();
2362 auto dropTarget = seat->dropHandlerForSurface(surface);
2367 if (qobject_cast<X11Window *>(window) && kwinApp()->xwayland()) {
2368 return kwinApp()->xwayland()->xwlDropHandler();
2380 m_raiseTimer.setSingleShot(
true);
2381 m_raiseTimer.setInterval(1000);
2382 connect(&m_raiseTimer, &QTimer::timeout,
this, &DragAndDropInputFilter::raiseDragTarget);
2384 connect(
waylandServer()->seat(), &SeatInterface::dragEnded,
this, [
this] {
2385 if (!m_currentToplevelDragWindow) {
2388 m_currentToplevelDragWindow->setKeepAbove(m_wasKeepAbove);
2389 workspace()->
takeActivity(m_currentToplevelDragWindow, Workspace::ActivityFlag::ActivityFocus | Workspace::ActivityFlag::ActivityRaise);
2390 m_currentToplevelDragWindow =
nullptr;
2397 if (!seat->isDragPointer()) {
2400 if (seat->isDragTouch()) {
2404 switch (event->type()) {
2405 case QEvent::MouseMove: {
2408 if (seat->xdgTopleveldrag()) {
2409 dragToplevel(pos, seat->xdgTopleveldrag());
2412 seat->notifyPointerMotion(pos);
2414 Window *dragTarget = pickDragTarget(pos);
2416 if (dragTarget != m_dragTarget) {
2418 m_raiseTimer.start();
2420 if ((pos - m_lastPos).manhattanLength() > 10) {
2423 m_raiseTimer.start();
2426 m_dragTarget = dragTarget;
2428 if (
auto *xwl = kwinApp()->xwayland()) {
2429 const auto ret = xwl->dragMoveFilter(dragTarget);
2430 if (ret == Xwl::DragEventReply::Ignore) {
2432 }
else if (ret == Xwl::DragEventReply::Take) {
2439 if (dragTarget->
surface() != seat->dragSurface()) {
2444 seat->setDragTarget(
nullptr,
nullptr);
2445 m_dragTarget =
nullptr;
2449 case QEvent::MouseButtonPress:
2450 seat->notifyPointerButton(nativeButton, PointerButtonState::Pressed);
2452 case QEvent::MouseButtonRelease:
2454 m_dragTarget =
nullptr;
2455 seat->notifyPointerButton(nativeButton, PointerButtonState::Released);
2467 if (!seat->isDragPointer()) {
2470 if (seat->isDragTouch()) {
2474 seat->notifyPointerFrame();
2478 bool touchDown(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
2481 if (seat->isDragPointer()) {
2484 if (!seat->isDragTouch()) {
2487 if (m_touchId !=
id) {
2490 seat->setTimestamp(time);
2491 seat->notifyTouchDown(
id, pos);
2495 bool touchMotion(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
2498 if (seat->isDragPointer()) {
2501 if (!seat->isDragTouch()) {
2504 if (m_touchId < 0) {
2510 if (m_touchId !=
id) {
2514 if (seat->xdgTopleveldrag()) {
2515 dragToplevel(pos, seat->xdgTopleveldrag());
2518 seat->setTimestamp(time);
2519 seat->notifyTouchMotion(
id, pos);
2521 if (
Window *t = pickDragTarget(pos)) {
2523 if (t->surface() != seat->dragSurface()) {
2524 if ((m_dragTarget =
static_cast<Window *
>(t->isClient() ? t :
nullptr))) {
2526 m_raiseTimer.start();
2528 seat->setDragTarget(dropHandler(t), t->surface(), pos, t->inputTransformation());
2530 if ((pos - m_lastPos).manhattanLength() > 10) {
2533 m_raiseTimer.start();
2537 seat->setDragTarget(
nullptr,
nullptr);
2538 m_dragTarget =
nullptr;
2542 bool touchUp(qint32
id, std::chrono::microseconds time)
override
2545 if (!seat->isDragTouch()) {
2548 seat->setTimestamp(time);
2549 seat->notifyTouchUp(
id);
2550 if (m_touchId ==
id) {
2558 if (event->key() != Qt::Key_Escape) {
2563 if (!seat->isDrag()) {
2574 void raiseDragTarget()
2576 m_raiseTimer.stop();
2582 Window *pickDragTarget(
const QPointF &pos)
const
2585 if (stacking.isEmpty()) {
2588 auto it = stacking.end();
2592 if (
auto toplevelDrag =
waylandServer()->
seat()->xdgTopleveldrag(); toplevelDrag && toplevelDrag->toplevel() && toplevelDrag->toplevel()->surface() == window->surface()) {
2595 if (window->isDeleted()) {
2598 if (!window->isClient()) {
2601 if (!window->isOnCurrentActivity() || !window->isOnCurrentDesktop() || window->isMinimized() || window->isHidden() || window->isHiddenByShowDesktop()) {
2604 if (!window->readyForPainting()) {
2607 if (window->hitTest(pos)) {
2610 }
while (it != stacking.begin());
2614 void dragToplevel(
const QPointF &pos,
const XdgToplevelDragV1Interface *toplevelDrag)
2617 auto window = toplevelDrag->toplevel() ?
waylandServer()->
findWindow(toplevelDrag->toplevel()->surface()) :
nullptr;
2619 if (m_currentToplevelDragWindow != window) {
2620 if (m_currentToplevelDragWindow) {
2621 m_currentToplevelDragWindow->
setKeepAbove(m_wasKeepAbove);
2623 m_currentToplevelDragWindow = window;
2625 m_wasKeepAbove = window->keepAbove();
2626 window->setKeepAbove(
true);
2631 window->move(pos - toplevelDrag->offset());
2635 qint32 m_touchId = -1;
2636 QPointF m_lastPos = QPointF(-1, -1);
2637 QPointer<Window> m_dragTarget;
2638 QTimer m_raiseTimer;
2639 QPointer<Window> m_currentToplevelDragWindow =
nullptr;
2640 bool m_wasKeepAbove =
false;
2645static const QString s_touchpadComponent = QStringLiteral(
"kcm_touchpad");
2647InputRedirection::InputRedirection(QObject *parent)
2649 , m_keyboard(new KeyboardInputRedirection(this))
2650 , m_pointer(new PointerInputRedirection(this))
2651 , m_tablet(new TabletInputRedirection(this))
2652 , m_touch(new TouchInputRedirection(this))
2653#if KWIN_BUILD_GLOBALSHORTCUTS
2654 , m_shortcuts(new GlobalShortcutsManager(this))
2657 qRegisterMetaType<InputRedirection::KeyboardKeyState>();
2658 qRegisterMetaType<InputRedirection::PointerButtonState>();
2659 qRegisterMetaType<InputRedirection::PointerAxis>();
2660 setupInputBackends();
2666 m_inputBackends.clear();
2667 m_inputDevices.clear();
2674 Q_ASSERT(!m_filters.contains(filter));
2675 m_filters << filter;
2680 Q_ASSERT(!m_filters.contains(filter));
2681 m_filters.prepend(filter);
2686 m_filters.removeOne(filter);
2696 m_spies.removeOne(spy);
2701 m_inputConfigWatcher = KConfigWatcher::create(kwinApp()->inputConfig());
2702 connect(m_inputConfigWatcher.data(), &KConfigWatcher::configChanged,
2703 this, &InputRedirection::handleInputConfigChanged);
2704#if KWIN_BUILD_GLOBALSHORTCUTS
2705 m_shortcuts->init();
2709void InputRedirection::setupWorkspace()
2718 updateLeds(m_keyboard->
xkb()->
leds());
2721 setupTouchpadShortcuts();
2722 setupInputFilters();
2727void InputRedirection::updateScreens()
2729 for (
const auto &backend : m_inputBackends) {
2730 backend->updateScreens();
2736 return m_lastInputDevice;
2741 m_lastInputDevice = device;
2749 if (event->isAutoRepeat() || event->type() != QEvent::KeyPress) {
2757 if (event->type() != QEvent::MouseButtonPress) {
2781 if (event->type() != QEvent::TabletPress) {
2787 void touchDown(qint32,
const QPointF &, std::chrono::microseconds time)
override
2798 window->setLastUsageSerial(
waylandServer()->seat()->display()->serial());
2819 void touchDown(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
2823 void touchMotion(qint32
id,
const QPointF &pos, std::chrono::microseconds time)
override
2827 void touchUp(qint32
id, std::chrono::microseconds time)
override
2836 void pinchGestureUpdate(qreal scale, qreal angleDelta,
const QPointF &delta, std::chrono::microseconds time)
override
2901 void notifyActivity()
2907void InputRedirection::setupInputFilters()
2911 m_virtualTerminalFilter = std::make_unique<VirtualTerminalFilter>();
2912 installInputEventFilter(m_virtualTerminalFilter.get());
2915 m_hideCursorSpy = std::make_unique<HideCursorSpy>();
2918 m_userActivitySpy = std::make_unique<UserActivitySpy>();
2921 m_windowInteractedSpy = std::make_unique<WindowInteractedSpy>();
2924 m_lockscreenFilter = std::make_unique<LockScreenFilter>();
2925 installInputEventFilter(m_lockscreenFilter.get());
2927 if (hasGlobalShortcutSupport) {
2928 m_screenEdgeFilter = std::make_unique<ScreenEdgeInputFilter>();
2929 installInputEventFilter(m_screenEdgeFilter.get());
2932 m_dragAndDropFilter = std::make_unique<DragAndDropInputFilter>();
2933 installInputEventFilter(m_dragAndDropFilter.get());
2935 m_windowSelector = std::make_unique<WindowSelectorFilter>();
2936 installInputEventFilter(m_windowSelector.get());
2938#if KWIN_BUILD_TABBOX
2939 m_tabboxFilter = std::make_unique<TabBoxInputFilter>();
2940 installInputEventFilter(m_tabboxFilter.get());
2942#if KWIN_BUILD_GLOBALSHORTCUTS
2943 if (hasGlobalShortcutSupport) {
2944 m_globalShortcutFilter = std::make_unique<GlobalShortcutFilter>();
2945 installInputEventFilter(m_globalShortcutFilter.get());
2949 m_effectsFilter = std::make_unique<EffectsFilter>();
2950 installInputEventFilter(m_effectsFilter.get());
2952 m_interactiveMoveResizeFilter = std::make_unique<MoveResizeFilter>();
2953 installInputEventFilter(m_interactiveMoveResizeFilter.get());
2955 m_popupFilter = std::make_unique<PopupInputFilter>();
2956 installInputEventFilter(m_popupFilter.get());
2958 m_decorationFilter = std::make_unique<DecorationEventFilter>();
2959 installInputEventFilter(m_decorationFilter.get());
2961 m_windowActionFilter = std::make_unique<WindowActionInputFilter>();
2962 installInputEventFilter(m_windowActionFilter.get());
2964 m_internalWindowFilter = std::make_unique<InternalWindowEventFilter>();
2965 installInputEventFilter(m_internalWindowFilter.get());
2967 m_inputKeyboardFilter = std::make_unique<InputKeyboardFilter>();
2968 installInputEventFilter(m_inputKeyboardFilter.get());
2970 m_forwardFilter = std::make_unique<ForwardInputFilter>();
2971 installInputEventFilter(m_forwardFilter.get());
2973 m_tabletFilter = std::make_unique<TabletInputFilter>();
2974 installInputEventFilter(m_tabletFilter.get());
2977void InputRedirection::handleInputConfigChanged(
const KConfigGroup &group)
2979 if (group.name() == QLatin1String(
"Keyboard")) {
2984void InputRedirection::updateLeds(LEDs leds)
2986 if (m_leds != leds) {
2989 for (
InputDevice *device : std::as_const(m_inputDevices)) {
2990 device->setLeds(leds);
3061 m_inputDevices.append(device);
3064 updateAvailableInputDevices();
3069 m_inputDevices.removeOne(device);
3072 updateAvailableInputDevices();
3075void InputRedirection::updateAvailableInputDevices()
3077 const bool hasKeyboard = std::any_of(m_inputDevices.constBegin(), m_inputDevices.constEnd(), [](
InputDevice *device) {
3078 return device->isKeyboard();
3080 if (m_hasKeyboard != hasKeyboard) {
3081 m_hasKeyboard = hasKeyboard;
3085 const bool hasPointer = std::any_of(m_inputDevices.constBegin(), m_inputDevices.constEnd(), [](
InputDevice *device) {
3086 return device->isPointer();
3093 const bool hasTouch = std::any_of(m_inputDevices.constBegin(), m_inputDevices.constEnd(), [](
InputDevice *device) {
3094 return device->isTouch();
3102 return device->isTabletModeSwitch();
3112 bool changed =
false;
3113 m_touchpadsEnabled = !m_touchpadsEnabled;
3114 for (
InputDevice *device : std::as_const(m_inputDevices)) {
3115 if (!device->isTouchpad()) {
3118 const bool old = device->isEnabled();
3119 device->setEnabled(m_touchpadsEnabled);
3120 if (old != device->isEnabled()) {
3126 QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral(
"org.kde.plasmashell"),
3127 QStringLiteral(
"/org/kde/osdService"),
3128 QStringLiteral(
"org.kde.osdService"),
3129 QStringLiteral(
"touchpadEnabledChanged"));
3130 msg.setArguments({m_touchpadsEnabled});
3131 QDBusConnection::sessionBus().asyncCall(msg);
3137 if (!m_touchpadsEnabled) {
3144 if (m_touchpadsEnabled) {
3149void InputRedirection::addInputBackend(std::unique_ptr<InputBackend> &&inputBackend)
3154 inputBackend->setConfig(kwinApp()->inputConfig());
3155 inputBackend->initialize();
3157 m_inputBackends.push_back(std::move(inputBackend));
3160void InputRedirection::setupInputBackends()
3162 std::unique_ptr<InputBackend> inputBackend = kwinApp()->outputBackend()->createInputBackend();
3164 addInputBackend(std::move(inputBackend));
3167 addInputBackend(std::make_unique<FakeInputBackend>(
waylandServer()->display()));
3171void InputRedirection::setupTouchpadShortcuts()
3173 QAction *touchpadToggleAction =
new QAction(
this);
3174 QAction *touchpadOnAction =
new QAction(
this);
3175 QAction *touchpadOffAction =
new QAction(
this);
3177 const QString touchpadDisplayName = i18n(
"Touchpad");
3179 touchpadToggleAction->setObjectName(QStringLiteral(
"Toggle Touchpad"));
3180 touchpadToggleAction->setProperty(
"componentName", s_touchpadComponent);
3181 touchpadToggleAction->setProperty(
"componentDisplayName", touchpadDisplayName);
3182 touchpadOnAction->setObjectName(QStringLiteral(
"Enable Touchpad"));
3183 touchpadOnAction->setProperty(
"componentName", s_touchpadComponent);
3184 touchpadOnAction->setProperty(
"componentDisplayName", touchpadDisplayName);
3185 touchpadOffAction->setObjectName(QStringLiteral(
"Disable Touchpad"));
3186 touchpadOffAction->setProperty(
"componentName", s_touchpadComponent);
3187 touchpadOffAction->setProperty(
"componentDisplayName", touchpadDisplayName);
3188 KGlobalAccel::self()->setDefaultShortcut(touchpadToggleAction, QList<QKeySequence>{Qt::Key_TouchpadToggle, Qt::ControlModifier | Qt::MetaModifier | Qt::Key_Zenkaku_Hankaku});
3189 KGlobalAccel::self()->setShortcut(touchpadToggleAction, QList<QKeySequence>{Qt::Key_TouchpadToggle, Qt::ControlModifier | Qt::MetaModifier | Qt::Key_Zenkaku_Hankaku});
3190 KGlobalAccel::self()->setDefaultShortcut(touchpadOnAction, QList<QKeySequence>{Qt::Key_TouchpadOn});
3191 KGlobalAccel::self()->setShortcut(touchpadOnAction, QList<QKeySequence>{Qt::Key_TouchpadOn});
3192 KGlobalAccel::self()->setDefaultShortcut(touchpadOffAction, QList<QKeySequence>{Qt::Key_TouchpadOff});
3193 KGlobalAccel::self()->setShortcut(touchpadOffAction, QList<QKeySequence>{Qt::Key_TouchpadOff});
3201 return m_hasPointer;
3211 return m_hasTabletModeSwitch;
3221 for (
IdleDetector *idleDetector : std::as_const(m_idleDetectors)) {
3222 idleDetector->activity();
3228 Q_ASSERT(!m_idleDetectors.contains(detector));
3230 m_idleDetectors.append(detector);
3235 m_idleDetectors.removeOne(detector);
3240 return m_idleInhibitors;
3245 if (!m_idleInhibitors.contains(inhibitor)) {
3246 m_idleInhibitors.append(inhibitor);
3247 for (
IdleDetector *idleDetector : std::as_const(m_idleDetectors)) {
3248 idleDetector->setInhibited(
true);
3255 if (m_idleInhibitors.removeOne(inhibitor) && m_idleInhibitors.isEmpty()) {
3256 for (
IdleDetector *idleDetector : std::as_const(m_idleDetectors)) {
3257 idleDetector->setInhibited(
false);
3268 if (!isScreenLocked) {
3275 if (stacking.isEmpty()) {
3278 auto it = stacking.end();
3292 if (isScreenLocked) {
3300 }
while (it != stacking.begin());
3316#if KWIN_BUILD_GLOBALSHORTCUTS
3317 m_shortcuts->registerPointerShortcut(action, modifiers, pointerButtons);
3323#if KWIN_BUILD_GLOBALSHORTCUTS
3324 m_shortcuts->registerAxisShortcut(action, modifiers, axis);
3330#if KWIN_BUILD_GLOBALSHORTCUTS
3331 m_shortcuts->registerTouchpadSwipe(direction, fingerCount, action, cb);
3337#if KWIN_BUILD_GLOBALSHORTCUTS
3338 m_shortcuts->registerTouchpadPinch(direction, fingerCount, onUp, progressCallback);
3344#if KWIN_BUILD_GLOBALSHORTCUTS
3345 m_shortcuts->setKGlobalAccelInterface(interface);
3351#if KWIN_BUILD_GLOBALSHORTCUTS
3352 m_shortcuts->registerTouchscreenSwipe(direction, fingerCount, action, progressCallback);
3358#if KWIN_BUILD_GLOBALSHORTCUTS
3359 m_shortcuts->forceRegisterTouchscreenSwipe(direction, fingerCount, action, progressCallback);
3365 m_pointer->
warp(pos);
3375 return m_pointer->
pos();
3380 if (!m_windowSelector || m_windowSelector->isActive()) {
3384 m_windowSelector->start(callback);
3390 if (!m_windowSelector || m_windowSelector->isActive()) {
3391 callback(QPoint(-1, -1));
3394 m_windowSelector->start(callback);
3400 return m_windowSelector ? m_windowSelector->isActive() :
false;
3417bool InputDeviceHandler::setHover(
Window *window)
3419 if (m_hover.window ==
window) {
3422 auto old = m_hover.window;
3423 disconnect(m_hover.surfaceCreatedConnection);
3424 m_hover.surfaceCreatedConnection = QMetaObject::Connection();
3432 if (m_focus.window ==
window) {
3436 Window *oldFocus = m_focus.window;
3452 auto oldDeco = m_focus.decoration;
3459void InputDeviceHandler::updateFocus()
3463 if (m_focus.decoration) {
3465 }
else if (m_hover.window && !m_hover.window->surface() && !m_hover.window->isInternal()) {
3468 if (!m_hover.surfaceCreatedConnection) {
3478void InputDeviceHandler::updateDecoration()
3480 Decoration::DecoratedClientImpl *
decoration =
nullptr;
3481 auto hover = m_hover.window.data();
3518 return m_hover.window.data();
3523 return m_focus.window.data();
3528 return m_focus.decoration;
3535#include "moc_input.cpp"
void setSource(CursorSource *source)
bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
bool touchUp(qint32 id, std::chrono::microseconds time) override
bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
bool wheelEvent(WheelEvent *event) override
bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
bool tabletToolEvent(TabletEvent *event) override
bool wheelEvent(WheelEvent *event) override
bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
bool tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId, std::chrono::microseconds time) override
bool tabletToolEvent(TabletEvent *event) override
bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
bool tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
bool tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
bool touchUp(qint32 id, std::chrono::microseconds time) override
bool keyEvent(KeyEvent *event) override
bool tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
bool hasKeyboardGrab() const
bool isMouseInterception() const
void grabbedKeyboardEvent(QKeyEvent *e)
bool tabletPadButtonEvent(uint button, bool pressed, const KWin::TabletPadId &tabletPadId, std::chrono::microseconds time)
bool tabletToolEvent(KWin::TabletEvent *event)
bool checkInputWindowEvent(QMouseEvent *e)
bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time)
bool touchUp(qint32 id, std::chrono::microseconds time)
bool tabletPadRingEvent(int number, int position, bool isFinger, const KWin::TabletPadId &tabletPadId, std::chrono::microseconds time)
bool tabletToolButtonEvent(uint button, bool pressed, const KWin::TabletToolId &tabletToolId, std::chrono::microseconds time)
bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time)
bool tabletPadStripEvent(int number, int position, bool isFinger, const KWin::TabletPadId &tabletPadId, std::chrono::microseconds time)
void updateSwipeGesture(const QPointF &delta)
void cancelSwipeGesture()
void setInhibited(bool inhibited)
std::chrono::microseconds timestamp() const
bool swipeGestureCancelled(std::chrono::microseconds time) override
bool pinchGestureEnd(std::chrono::microseconds time) override
bool swipeGestureBegin(int fingerCount, std::chrono::microseconds time) override
bool wheelEvent(WheelEvent *event) override
bool pointerFrame() override
bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
bool swipeGestureUpdate(const QPointF &delta, std::chrono::microseconds time) override
bool pinchGestureBegin(int fingerCount, std::chrono::microseconds time) override
bool pinchGestureUpdate(qreal scale, qreal angleDelta, const QPointF &delta, std::chrono::microseconds time) override
bool holdGestureEnd(std::chrono::microseconds time) override
bool holdGestureBegin(int fingerCount, std::chrono::microseconds time) override
bool touchUp(qint32 id, std::chrono::microseconds time) override
bool swipeGestureEnd(std::chrono::microseconds time) override
bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
bool pinchGestureCancelled(std::chrono::microseconds time) override
bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
bool keyEvent(KeyEvent *event) override
QPointF deltaUnaccelerated() const
std::chrono::microseconds timestamp() const
float accumulate(WheelEvent *event)
bool tabletToolEvent(TabletEvent *event) override
bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
bool keyEvent(KeyEvent *event) override
bool wheelEvent(WheelEvent *event) override
bool touchUp(qint32 id, std::chrono::microseconds time) override
Qt::KeyboardModifier commandAllModifier() const
MouseCommand operationWindowMouseWheel(int delta) const
MouseCommand operationTitlebarMouseWheel(int delta) const
QSize orientateSize(const QSize &size) const
bool isEntered(QMouseEvent *event)
GestureRecognizer * gestureRecognizer() const
Represents a Seat on the Wayland Display.
SurfaceInterface * focusedTouchSurface() const
void setTimestamp(std::chrono::microseconds time)
SurfaceInterface * focusedPointerSurface() const
SurfaceInterface * focusedKeyboardSurface() const
void setFocusedKeyboardSurface(SurfaceInterface *surface)
SurfaceCursor(TabletToolV2Interface *tool)
Resource representing a wl_surface.
ClientConnection * client() const
const TabletToolId & tabletId() const
TabletSeatV2Interface * seat(SeatInterface *seat) const
TabletPadV2Interface * addTabletPad(const QString &sysname, const QString &name, const QStringList &paths, quint32 buttons, quint32 rings, quint32 strips, quint32 modes, quint32 currentMode, TabletV2Interface *tablet)
TabletToolV2Interface * toolByHardwareSerial(quint64 hardwareSerial, TabletToolV2Interface::Type type) const
TabletToolV2Interface * addTool(TabletToolV2Interface::Type type, quint64 hardwareSerial, quint64 hardwareId, const QList< TabletToolV2Interface::Capability > &capabilities, const QString &deviceSysName)
void removeDevice(const QString &sysname)
TabletV2Interface * addTablet(quint32 vendorId, quint32 productId, const QString &sysname, const QString &name, const QStringList &paths)
void tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
void holdGestureBegin(int fingerCount, std::chrono::microseconds time) override
void keyEvent(KeyEvent *event) override
void holdGestureCancelled(std::chrono::microseconds time) override
void touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
void touchUp(qint32 id, std::chrono::microseconds time) override
void holdGestureEnd(std::chrono::microseconds time) override
void pointerEvent(MouseEvent *event) override
void pinchGestureBegin(int fingerCount, std::chrono::microseconds time) override
void tabletToolEvent(TabletEvent *event) override
void tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
void swipeGestureCancelled(std::chrono::microseconds time) override
void touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
void swipeGestureEnd(std::chrono::microseconds time) override
void pinchGestureCancelled(std::chrono::microseconds time) override
void swipeGestureUpdate(const QPointF &delta, std::chrono::microseconds time) override
void pinchGestureUpdate(qreal scale, qreal angleDelta, const QPointF &delta, std::chrono::microseconds time) override
void pinchGestureEnd(std::chrono::microseconds time) override
void tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId, std::chrono::microseconds time) override
void wheelEvent(WheelEvent *event) override
void swipeGestureBegin(int fingerCount, std::chrono::microseconds time) override
void tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId, std::chrono::microseconds time) override
void currentChanged(KWin::VirtualDesktop *previousDesktop, KWin::VirtualDesktop *newDesktop)
bool keyEvent(KeyEvent *event) override
KXcursorTheme theme() const
bool hasGlobalShortcutSupport() const
bool isScreenLocked() const
Window * findWindow(const SurfaceInterface *surface) const
SeatInterface * seat() const
std::chrono::microseconds timestamp() const
QMatrix4x4 inputTransformation() const
QPointF mapToLocal(const QPointF &point) const
virtual bool isClient() const
bool isInteractiveMove() const
void updateInteractiveMoveResize(const QPointF ¤tGlobalCursor)
void keyPressEvent(uint key_code)
void endInteractiveMoveResize()
SurfaceInterface * surface() const
bool readyForPainting() const
bool isOnCurrentActivity() const
bool isHiddenByShowDesktop() const
Options::MouseCommand getMouseCommand(Qt::MouseButton button, bool *handled) const
Decoration::DecoratedClientImpl * decoratedClient() const
bool isInteractiveResize() const
bool isOnCurrentDesktop() const
bool isLockScreenOverlay() const
bool performMouseCommand(Options::MouseCommand, const QPointF &globalPos)
virtual bool isLockScreen() const
virtual bool isInputMethod() const
virtual bool hitTest(const QPointF &point) const
void tabletToolButtonEvent(uint, bool pressed, const TabletToolId &, std::chrono::microseconds time) override
void tabletPadButtonEvent(uint, bool pressed, const TabletPadId &, std::chrono::microseconds time) override
void keyEvent(KeyEvent *event) override
void touchDown(qint32, const QPointF &, std::chrono::microseconds time) override
void tabletToolEvent(TabletEvent *event) override
void pointerEvent(MouseEvent *event) override
bool keyEvent(KeyEvent *event) override
bool wheelEvent(WheelEvent *event) override
void start(std::function< void(const QPoint &)> callback)
bool pointerEvent(MouseEvent *event, quint32 nativeButton) override
bool touchUp(qint32 id, std::chrono::microseconds time) override
bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time) override
void start(std::function< void(Window *)> callback)
Window * activeWindow() const
ScreenEdges * screenEdges() const
void activateWindow(Window *window, bool force=false)
const QList< Window * > & stackingOrder() const
void stackingOrderChanged()
Window * moveResizeWindow()
static Workspace * self()
void updateFocusMousePosition(const QPointF &pos)
QList< Output * > outputs() const
const QList< Window * > windows() const
bool takeActivity(Window *window, ActivityFlags flags)
void windowMinimizedChanged(KWin::Window *)
Output * outputAt(const QPointF &pos) const
Qt::Key toQtKey(xkb_keysym_t keysym, uint32_t scanCode=0, Qt::KeyboardModifiers modifiers=Qt::KeyboardModifiers(), bool superAsMeta=false) const
#define KWIN_SINGLETON_FACTORY(ClassName)
KWayland::Client::Seat * seat
void touchDown(qint32 id, const QPointF &pos, quint32 time)
void touchMotion(qint32 id, const QPointF &pos, quint32 time)
void touchUp(qint32 id, quint32 time)
PointerAxisDirection
The direction in which a pointer axis is moved.
uint32_t qtMouseButtonToButton(Qt::MouseButton button)
WaylandServer * waylandServer()
SwipeDirection
Directions for swipe gestures.
InputRedirection * input()
KWIN_EXPORT QPoint flooredPoint(const QPointF &point)
std::variant< TabletSurfaceCursorV2 *, QByteArray > TabletCursorSourceV2