Changeset View
Changeset View
Standalone View
Standalone View
input.cpp
Show All 30 Lines | |||||
31 | #include "pointer_input.h" | 31 | #include "pointer_input.h" | ||
32 | #include "tablet_input.h" | 32 | #include "tablet_input.h" | ||
33 | #include "touch_hide_cursor_spy.h" | 33 | #include "touch_hide_cursor_spy.h" | ||
34 | #include "touch_input.h" | 34 | #include "touch_input.h" | ||
35 | #include "x11client.h" | 35 | #include "x11client.h" | ||
36 | #ifdef KWIN_BUILD_TABBOX | 36 | #ifdef KWIN_BUILD_TABBOX | ||
37 | #include "tabbox/tabbox.h" | 37 | #include "tabbox/tabbox.h" | ||
38 | #endif | 38 | #endif | ||
39 | #include "unmanaged.h" | 39 | #include "internal_client.h" | ||
40 | #include "screenedge.h" | | |||
41 | #include "screens.h" | | |||
42 | #include "workspace.h" | | |||
43 | #include "libinput/connection.h" | 40 | #include "libinput/connection.h" | ||
44 | #include "libinput/device.h" | 41 | #include "libinput/device.h" | ||
45 | #include "platform.h" | 42 | #include "platform.h" | ||
46 | #include "popup_input_filter.h" | 43 | #include "popup_input_filter.h" | ||
47 | #include "xdgshellclient.h" | 44 | #include "screenedge.h" | ||
45 | #include "screens.h" | ||||
46 | #include "unmanaged.h" | ||||
48 | #include "wayland_server.h" | 47 | #include "wayland_server.h" | ||
48 | #include "workspace.h" | ||||
49 | #include "xdgshellclient.h" | ||||
49 | #include "xwl/xwayland_interface.h" | 50 | #include "xwl/xwayland_interface.h" | ||
50 | #include "internal_client.h" | 51 | #include <KDecoration2/Decoration> | ||
52 | #include <KGlobalAccel> | ||||
51 | #include <KWayland/Server/display.h> | 53 | #include <KWayland/Server/display.h> | ||
52 | #include <KWayland/Server/fakeinput_interface.h> | 54 | #include <KWayland/Server/fakeinput_interface.h> | ||
53 | #include <KWayland/Server/seat_interface.h> | | |||
54 | #include <KWayland/Server/relativepointer_interface.h> | 55 | #include <KWayland/Server/relativepointer_interface.h> | ||
56 | #include <KWayland/Server/seat_interface.h> | ||||
57 | #include <KWayland/Server/surface_interface.h> | ||||
58 | #include <KWayland/Server/tablet_interface.h> | ||||
55 | #include <decorations/decoratedclient.h> | 59 | #include <decorations/decoratedclient.h> | ||
56 | #include <KDecoration2/Decoration> | | |||
57 | #include <KGlobalAccel> | | |||
58 | 60 | | |||
59 | //screenlocker | 61 | //screenlocker | ||
60 | #include <KScreenLocker/KsldApp> | 62 | #include <KScreenLocker/KsldApp> | ||
61 | // Qt | 63 | // Qt | ||
62 | #include <QKeyEvent> | 64 | #include <QKeyEvent> | ||
63 | 65 | | |||
64 | #include <xkbcommon/xkbcommon.h> | 66 | #include <xkbcommon/xkbcommon.h> | ||
65 | 67 | | |||
▲ Show 20 Lines • Show All 106 Lines • ▼ Show 20 Line(s) | |||||
172 | } | 174 | } | ||
173 | 175 | | |||
174 | bool InputEventFilter::switchEvent(SwitchEvent *event) | 176 | bool InputEventFilter::switchEvent(SwitchEvent *event) | ||
175 | { | 177 | { | ||
176 | Q_UNUSED(event) | 178 | Q_UNUSED(event) | ||
177 | return false; | 179 | return false; | ||
178 | } | 180 | } | ||
179 | 181 | | |||
180 | bool InputEventFilter::tabletToolEvent(QTabletEvent *event) | 182 | bool InputEventFilter::tabletToolEvent(TabletEvent *event) | ||
181 | { | 183 | { | ||
182 | Q_UNUSED(event) | 184 | Q_UNUSED(event) | ||
183 | return false; | 185 | return false; | ||
184 | } | 186 | } | ||
185 | 187 | | |||
186 | bool InputEventFilter::tabletToolButtonEvent(const QSet<uint> &pressedButtons) | 188 | bool InputEventFilter::tabletToolButtonEvent(const QSet<uint> &pressedButtons) | ||
187 | { | 189 | { | ||
188 | Q_UNUSED(pressedButtons) | 190 | Q_UNUSED(pressedButtons) | ||
▲ Show 20 Lines • Show All 1326 Lines • ▼ Show 20 Line(s) | 1514 | bool swipeGestureCancelled(quint32 time) override { | |||
1515 | } | 1517 | } | ||
1516 | auto seat = waylandServer()->seat(); | 1518 | auto seat = waylandServer()->seat(); | ||
1517 | seat->setTimestamp(time); | 1519 | seat->setTimestamp(time); | ||
1518 | seat->cancelPointerSwipeGesture(); | 1520 | seat->cancelPointerSwipeGesture(); | ||
1519 | return true; | 1521 | return true; | ||
1520 | } | 1522 | } | ||
1521 | }; | 1523 | }; | ||
1522 | 1524 | | |||
1525 | static KWayland::Server::SeatInterface *findSeat() | ||||
1526 | { | ||||
1527 | auto server = waylandServer(); | ||||
1528 | if (!server) { | ||||
1529 | return nullptr; | ||||
1530 | } | ||||
1531 | return server->seat(); | ||||
1532 | } | ||||
1533 | | ||||
1523 | /** | 1534 | /** | ||
1524 | * Useful when there's no proper tablet support on the clients | 1535 | * Useful when there's no proper tablet support on the clients | ||
1525 | */ | 1536 | */ | ||
1526 | class FakeTabletInputFilter : public InputEventFilter | 1537 | class TabletInputFilter : public QObject, public InputEventFilter | ||
1527 | { | 1538 | { | ||
1528 | public: | 1539 | public: | ||
1529 | FakeTabletInputFilter() | 1540 | TabletInputFilter() | ||
1530 | { | 1541 | { | ||
1531 | } | 1542 | } | ||
1532 | 1543 | | |||
1533 | bool tabletToolEvent(QTabletEvent *event) override | 1544 | static KWayland::Server::TabletSeatInterface *findTabletSeat() | ||
1545 | { | ||||
1546 | auto server = waylandServer(); | ||||
1547 | if (!server) { | ||||
1548 | return nullptr; | ||||
1549 | } | ||||
1550 | KWayland::Server::TabletManagerInterface *manager = server->tabletManager(); | ||||
zzag: No `auto`.
https://community.kde.org/Policies/Library_Code_Policy#auto_Keyword | |||||
1551 | return manager->seat(findSeat()); | ||||
1552 | } | ||||
1553 | | ||||
1554 | void integrateDevice(LibInput::Device *device) | ||||
zzag: Naming nitpick: maybe `addDevice`? | |||||
1555 | { | ||||
1556 | if (device->isTabletTool()) { | ||||
1557 | KWayland::Server::TabletSeatInterface *tabletSeat = findTabletSeat(); | ||||
1558 | struct udev_device *const udev_device = libinput_device_get_udev_device(device->device()); | ||||
1559 | const char *devnode = udev_device_get_devnode(udev_device); | ||||
zzag: Use explicit type
```lang=cpp
const char *devnode = udev_device_get_devnode(udev_device);
``` | |||||
1560 | tabletSeat->addTablet(device->vendor(), device->product(), device->sysName(), device->name(), {QString::fromUtf8(devnode)}); | ||||
1561 | } | ||||
1562 | } | ||||
1563 | void removeDevice(const QString &sysname) | ||||
1564 | { | ||||
1565 | KWayland::Server::TabletSeatInterface *tabletSeat = findTabletSeat(); | ||||
1566 | tabletSeat->removeTablet(sysname); | ||||
1567 | } | ||||
1568 | | ||||
1569 | bool tabletToolEvent(TabletEvent *event) override | ||||
1570 | { | ||||
1571 | if (!workspace()) { | ||||
1572 | return false; | ||||
1573 | } | ||||
1574 | | ||||
1575 | KWayland::Server::TabletSeatInterface *tabletSeat = findTabletSeat(); | ||||
1576 | auto tool = tabletSeat->toolByHardwareId(event->serialId()); | ||||
davidedmundson: I think this should be event->uniqueId() | |||||
We are using the same value as the second argument of addTablet() (se below). If we change here the serialId, we'd have to change it there too and we'd have the same behaviour. apol: We are using the same value as the second argument of `addTablet()` (se below). If we change… | |||||
1577 | if (!tool) { | ||||
1578 | using namespace KWayland::Server; | ||||
1579 | | ||||
1580 | const QVector<InputRedirection::Capability> capabilities = event->capabilities(); | ||||
1581 | const auto f = [](InputRedirection::Capability cap) { | ||||
1582 | switch (cap) { | ||||
1583 | case InputRedirection::Tilt: | ||||
1584 | return TabletToolInterface::Tilt; | ||||
1585 | case InputRedirection::Pressure: | ||||
1586 | return TabletToolInterface::Pressure; | ||||
1587 | case InputRedirection::Distance: | ||||
1588 | return TabletToolInterface::Distance; | ||||
1589 | case InputRedirection::Rotation: | ||||
1590 | return TabletToolInterface::Rotation; | ||||
1591 | case InputRedirection::Slider: | ||||
1592 | return TabletToolInterface::Slider; | ||||
1593 | case InputRedirection::Wheel: | ||||
1594 | return TabletToolInterface::Wheel; | ||||
1595 | } | ||||
1596 | return TabletToolInterface::Wheel; | ||||
1597 | }; | ||||
1598 | QVector<TabletToolInterface::Capability> ifaceCapabilities; | ||||
1599 | ifaceCapabilities.resize(capabilities.size()); | ||||
1600 | std::transform(capabilities.constBegin(), capabilities.constEnd(), ifaceCapabilities.begin(), f); | ||||
1601 | | ||||
1602 | TabletToolInterface::Type toolType = TabletToolInterface::Type::Pen; | ||||
1603 | switch (event->toolType()) { | ||||
1604 | case InputRedirection::Pen: | ||||
1605 | toolType = TabletToolInterface::Type::Pen; | ||||
1606 | break; | ||||
1607 | case InputRedirection::Eraser: | ||||
1608 | toolType = TabletToolInterface::Type::Eraser; | ||||
1609 | break; | ||||
1610 | case InputRedirection::Brush: | ||||
1611 | toolType = TabletToolInterface::Type::Brush; | ||||
zzag: Align pointers to right. | |||||
1612 | break; | ||||
1613 | case InputRedirection::Pencil: | ||||
1614 | toolType = TabletToolInterface::Type::Pencil; | ||||
1615 | break; | ||||
1616 | case InputRedirection::Airbrush: | ||||
No short names. Toplevel *toplevel = input()->findToplevel(event->globalPos()); if (!toplevel || !toplevel->surface()) { return false; } zzag: No short names.
```lang=cpp
Toplevel *toplevel = input()->findToplevel(event… | |||||
1617 | toolType = TabletToolInterface::Type::Airbrush; | ||||
1618 | break; | ||||
zzag: Align pointers to right. | |||||
1619 | case InputRedirection::Finger: | ||||
1620 | toolType = TabletToolInterface::Type::Finger; | ||||
1621 | break; | ||||
1622 | case InputRedirection::Mouse: | ||||
zzag: Add missing braces. | |||||
1623 | toolType = TabletToolInterface::Type::Mouse; | ||||
1624 | break; | ||||
1625 | case InputRedirection::Lens: | ||||
1626 | toolType = TabletToolInterface::Type::Lens; | ||||
1627 | break; | ||||
1628 | case InputRedirection::Totem: | ||||
1629 | toolType = TabletToolInterface::Type::Totem; | ||||
1630 | break; | ||||
1631 | } | ||||
1632 | tool = tabletSeat->addTool(toolType, event->serialId(), event->uniqueId(), ifaceCapabilities); | ||||
1633 | } | ||||
1634 | | ||||
1635 | KWayland::Server::TabletInterface *tablet = tabletSeat->tabletByName(event->tabletSysName()); | ||||
1636 | | ||||
1637 | Toplevel *toplevel = input()->findToplevel(event->globalPos()); | ||||
1638 | if (!toplevel || !toplevel->surface()) { | ||||
1639 | return false; | ||||
1640 | } | ||||
1641 | | ||||
Double check with vlad, but I think we want toplevel->bufferGeometry().topLeft() as input is relative to the buffer not the frame davidedmundson: Double check with vlad, but I think we want
toplevel->bufferGeometry().topLeft()
as input is… | |||||
Yes, x and y in the motion event must be in the surface-local coordinates, i.e. relative to the upper left corner of the main surface. zzag: Yes, x and y in the motion event must be in the surface-local coordinates, i.e. relative to the… | |||||
btw, maybe it might be worth to introduce a method to map points from the global screen coordinates to surface-local coordinates, e.g. QPoint Toplevel::mapToLocal(const QPoint &point) const { return point - bufferGeometry().topLeft(); } QPointF Toplevel::mapToLocal(const QPointF &point) const { return point - QPointF(bufferGeometry().topLeft()); } zzag: btw, maybe it might be worth to introduce a method to map points from the global screen… | |||||
1642 | KWayland::Server::SurfaceInterface *surface = toplevel->surface(); | ||||
1643 | tool->setCurrentSurface(surface); | ||||
1644 | | ||||
1645 | if (!tool->isClientSupported() || !tablet->isSurfaceSupported(surface)) { | ||||
1646 | return emulateTabletEvent(event); | ||||
1647 | } | ||||
1648 | | ||||
1649 | switch (event->type()) { | ||||
1650 | case QEvent::TabletMove: | ||||
1651 | tool->sendMotion(event->globalPosF() - toplevel->pos()); | ||||
1652 | break; | ||||
1653 | case QEvent::TabletEnterProximity: | ||||
1654 | tool->sendProximityIn(tablet); | ||||
1655 | break; | ||||
1656 | case QEvent::TabletLeaveProximity: | ||||
1657 | tool->sendProximityOut(); | ||||
1658 | break; | ||||
1659 | case QEvent::TabletPress: | ||||
1660 | tool->sendDown(); | ||||
1661 | break; | ||||
1662 | case QEvent::TabletRelease: | ||||
1663 | tool->sendUp(); | ||||
1664 | break; | ||||
1665 | default: | ||||
1666 | qCWarning(KWIN_CORE) << "Unexpected tablet event type" << event; | ||||
1667 | break; | ||||
1668 | } | ||||
1669 | const quint32 MAX_VAL = 65535; | ||||
1670 | tool->sendPressure(MAX_VAL * event->pressure()); | ||||
1671 | tool->sendFrame(event->timestamp()); | ||||
1672 | waylandServer()->simulateUserActivity(); | ||||
1673 | return true; | ||||
1674 | } | ||||
1675 | | ||||
1676 | bool emulateTabletEvent(TabletEvent *event) | ||||
1534 | { | 1677 | { | ||
1535 | if (!workspace()) { | 1678 | if (!workspace()) { | ||
1536 | return false; | 1679 | return false; | ||
1537 | } | 1680 | } | ||
1538 | 1681 | | |||
1539 | switch (event->type()) { | 1682 | switch (event->type()) { | ||
1540 | case QEvent::TabletMove: | 1683 | case QEvent::TabletMove: | ||
1541 | case QEvent::TabletEnterProximity: | 1684 | case QEvent::TabletEnterProximity: | ||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Line(s) | 1735 | if (t) { | |||
1594 | if (t->surface() != seat->dragSurface()) { | 1737 | if (t->surface() != seat->dragSurface()) { | ||
1595 | if (AbstractClient *c = qobject_cast<AbstractClient*>(t)) { | 1738 | if (AbstractClient *c = qobject_cast<AbstractClient*>(t)) { | ||
1596 | workspace()->activateClient(c); | 1739 | workspace()->activateClient(c); | ||
1597 | } | 1740 | } | ||
1598 | seat->setDragTarget(t->surface(), t->inputTransformation()); | 1741 | seat->setDragTarget(t->surface(), t->inputTransformation()); | ||
1599 | } | 1742 | } | ||
1600 | } else { | 1743 | } else { | ||
1601 | // no window at that place, if we have a surface we need to reset | 1744 | // no window at that place, if we have a surface we need to reset | ||
1602 | seat->setDragTarget(nullptr); | 1745 | seat->setDragTarget(nullptr); | ||
zzag: No short names.
```lang=cpp
Toplevel *toplevel = ...
``` | |||||
1603 | } | 1746 | } | ||
1604 | break; | 1747 | break; | ||
zzag: Should have braces. | |||||
1605 | } | 1748 | } | ||
1606 | case QEvent::MouseButtonPress: | 1749 | case QEvent::MouseButtonPress: | ||
1607 | seat->pointerButtonPressed(nativeButton); | 1750 | seat->pointerButtonPressed(nativeButton); | ||
1608 | break; | 1751 | break; | ||
1609 | case QEvent::MouseButtonRelease: | 1752 | case QEvent::MouseButtonRelease: | ||
1610 | seat->pointerButtonReleased(nativeButton); | 1753 | seat->pointerButtonReleased(nativeButton); | ||
1611 | break; | 1754 | break; | ||
1612 | default: | 1755 | default: | ||
▲ Show 20 Lines • Show All 303 Lines • ▼ Show 20 Line(s) | 2058 | #endif | |||
1916 | if (hasGlobalShortcutSupport) { | 2059 | if (hasGlobalShortcutSupport) { | ||
1917 | installInputEventFilter(new GlobalShortcutFilter); | 2060 | installInputEventFilter(new GlobalShortcutFilter); | ||
1918 | } | 2061 | } | ||
1919 | installInputEventFilter(new DecorationEventFilter); | 2062 | installInputEventFilter(new DecorationEventFilter); | ||
1920 | installInputEventFilter(new InternalWindowEventFilter); | 2063 | installInputEventFilter(new InternalWindowEventFilter); | ||
1921 | if (waylandServer()) { | 2064 | if (waylandServer()) { | ||
1922 | installInputEventFilter(new WindowActionInputFilter); | 2065 | installInputEventFilter(new WindowActionInputFilter); | ||
1923 | installInputEventFilter(new ForwardInputFilter); | 2066 | installInputEventFilter(new ForwardInputFilter); | ||
1924 | installInputEventFilter(new FakeTabletInputFilter); | 2067 | | ||
2068 | m_tabletSupport = new TabletInputFilter; | ||||
2069 | for (LibInput::Device *dev : m_libInput->devices()) { | ||||
2070 | m_tabletSupport->integrateDevice(dev); | ||||
Please put a single space between for and the opening parenthesis, add missing braces and use explicit type. zzag: Please put a single space between `for` and the opening parenthesis, add missing braces and use… | |||||
2071 | } | ||||
2072 | connect(m_libInput, &LibInput::Connection::deviceAdded, m_tabletSupport, &TabletInputFilter::integrateDevice); | ||||
2073 | connect(m_libInput, &LibInput::Connection::deviceRemovedSysName, m_tabletSupport, &TabletInputFilter::removeDevice); | ||||
2074 | installInputEventFilter(m_tabletSupport); | ||||
1925 | } | 2075 | } | ||
1926 | } | 2076 | } | ||
1927 | 2077 | | |||
1928 | void InputRedirection::reconfigure() | 2078 | void InputRedirection::reconfigure() | ||
1929 | { | 2079 | { | ||
1930 | if (Application::usesLibinput()) { | 2080 | if (Application::usesLibinput()) { | ||
1931 | auto inputConfig = kwinApp()->inputConfig(); | 2081 | auto inputConfig = kwinApp()->inputConfig(); | ||
1932 | inputConfig->reparseConfiguration(); | 2082 | inputConfig->reparseConfiguration(); | ||
1933 | const auto config = inputConfig->group(QStringLiteral("Keyboard")); | 2083 | const auto config = inputConfig->group(QStringLiteral("Keyboard")); | ||
1934 | const int delay = config.readEntry("RepeatDelay", 660); | 2084 | const int delay = config.readEntry("RepeatDelay", 660); | ||
1935 | const int rate = config.readEntry("RepeatRate", 25); | 2085 | const int rate = config.readEntry("RepeatRate", 25); | ||
1936 | const bool enabled = config.readEntry("KeyboardRepeating", 0) == 0; | 2086 | const bool enabled = config.readEntry("KeyboardRepeating", 0) == 0; | ||
1937 | 2087 | | |||
1938 | waylandServer()->seat()->setKeyRepeatInfo(enabled ? rate : 0, delay); | 2088 | waylandServer()->seat()->setKeyRepeatInfo(enabled ? rate : 0, delay); | ||
1939 | } | 2089 | } | ||
1940 | } | 2090 | } | ||
1941 | 2091 | | |||
1942 | static KWayland::Server::SeatInterface *findSeat() | | |||
1943 | { | | |||
1944 | auto server = waylandServer(); | | |||
1945 | if (!server) { | | |||
1946 | return nullptr; | | |||
1947 | } | | |||
1948 | return server->seat(); | | |||
1949 | } | | |||
1950 | | ||||
1951 | void InputRedirection::setupLibInput() | 2092 | void InputRedirection::setupLibInput() | ||
1952 | { | 2093 | { | ||
1953 | if (!Application::usesLibinput()) { | 2094 | if (!Application::usesLibinput()) { | ||
1954 | return; | 2095 | return; | ||
1955 | } | 2096 | } | ||
1956 | if (m_libInput) { | 2097 | if (m_libInput) { | ||
1957 | return; | 2098 | return; | ||
1958 | } | 2099 | } | ||
▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Line(s) | 2102 | if (conn) { | |||
2071 | connect(LogindIntegration::self(), &LogindIntegration::sessionActiveChanged, m_libInput, | 2212 | connect(LogindIntegration::self(), &LogindIntegration::sessionActiveChanged, m_libInput, | ||
2072 | [this] (bool active) { | 2213 | [this] (bool active) { | ||
2073 | if (!active) { | 2214 | if (!active) { | ||
2074 | m_libInput->deactivate(); | 2215 | m_libInput->deactivate(); | ||
2075 | } | 2216 | } | ||
2076 | } | 2217 | } | ||
2077 | ); | 2218 | ); | ||
2078 | } | 2219 | } | ||
2220 | | ||||
2079 | setupTouchpadShortcuts(); | 2221 | setupTouchpadShortcuts(); | ||
2080 | } | 2222 | } | ||
2081 | 2223 | | |||
2082 | void InputRedirection::setupTouchpadShortcuts() | 2224 | void InputRedirection::setupTouchpadShortcuts() | ||
2083 | { | 2225 | { | ||
2084 | if (!m_libInput) { | 2226 | if (!m_libInput) { | ||
2085 | return; | 2227 | return; | ||
2086 | } | 2228 | } | ||
▲ Show 20 Lines • Show All 453 Lines • Show Last 20 Lines |
No auto.
https://community.kde.org/Policies/Library_Code_Policy#auto_Keyword