| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- -- SPDX-License-Identifier: MIT
- --
- -- This is an example libinput plugin
- --
- -- This plugin controls a mouse/pointer from a tablet device. This
- -- effectively hides stylus interactions and sends pointer events
- -- instead. In other words: mouse emulation for tablets, implemented
- -- by (remote) controlling a mouse device. This allows using a
- -- tablet stylus as a mouse replacement without tablet limitations
- -- from compositors or clients. Note that axis usually needed for
- -- drawing (like pressure, tilt or distance) are no longer emitted
- -- when this plugin is active and a mouse is connected. When no
- -- mouse is connected, this plugin doesn't change tablet events,
- -- thus the stylus works like a normal stylus.
- -- UNCOMMENT THIS LINE TO ACTIVATE THE PLUGIN
- -- libinput:register({1})
- -- globals
- pointer_device = nil
- tablet_device = nil
- maximum_x = nil
- maximum_y = nil
- function adjust_for_aspect_ratio(y)
- -- adjust y to match monitor 21:9 aspect ratio
- local adj_maximum_y = maximum_x * 1440 / 3440
- return math.floor(math.min(y * maximum_y / adj_maximum_y, maximum_y + 1))
- end
- function on_tablet_frame(device, frame, time_in_microseconds)
- -- emit tablet frame when there is no pointer device
- if not pointer_device then return nil end
- -- map tablet frame to pointer frame
- local events = {}
- for _, v in ipairs(frame) do
- if v.usage == evdev.ABS_MISC then
- -- save a few cycles on Wacom tablets by discarding a
- -- proximity in / out frame early, non-Wacom tablets should
- -- use BTN_TOOL_PEN/RUBBER/... instead
- return {}
- elseif v.usage == evdev.ABS_X then
- table.insert(events, { usage = evdev.ABS_X, value = v.value })
- elseif v.usage == evdev.ABS_Y then
- -- uncomment the next two lines and comment the original line
- -- for configuring aspect correction, see
- -- adjust_for_aspect_ratio() for details and configuration
- -- local adj_value = adjust_for_aspect_ratio(v.value)
- -- table.insert(events, { usage = evdev.ABS_Y, value = adj_value })
- table.insert(events, { usage = evdev.ABS_Y, value = v.value })
- elseif v.usage == evdev.BTN_TOUCH then
- table.insert(events, { usage = evdev.BTN_LEFT, value = v.value })
- elseif v.usage == evdev.BTN_STYLUS then
- table.insert(events, { usage = evdev.BTN_RIGHT, value = v.value })
- elseif v.usage == evdev.BTN_STYLUS2 then
- table.insert(events, { usage = evdev.BTN_MIDDLE, value = v.value })
- end
- end
- -- emit pointer frame, if any
- if #events > 0 then pointer_device:append_frame(events) end
- -- discard tablet frame
- return {}
- end
- function on_tablet_removed(device)
- libinput:log_info("Remove tablet device")
- tablet_device = nil
- end
- function on_pointer_removed(device)
- libinput:log_info("Remove pointer device")
- pointer_device = nil
- end
- function setup()
- if not pointer_device or not tablet_device then return end
- libinput:log_info("Controlling '" .. pointer_device:name() .. "' with '" .. tablet_device:name() .. "'")
- -- fetch absinfos from tablet
- local absinfo_x = {}
- local absinfo_y = {}
- for a, b in pairs(tablet_device:absinfos()) do
- if a == evdev.ABS_X then absinfo_x = b end
- if a == evdev.ABS_Y then absinfo_y = b end
- end
- -- copy max values for aspect ratio correction later on
- maximum_x = absinfo_x.maximum
- maximum_y = absinfo_y.maximum
- -- copy absinfos to pointer device
- pointer_device:set_absinfo(evdev.ABS_X, absinfo_x)
- pointer_device:set_absinfo(evdev.ABS_Y, absinfo_y)
- -- setup listeners
- pointer_device:connect("device-removed", on_pointer_removed)
- tablet_device:connect("device-removed", on_tablet_removed)
- tablet_device:connect("evdev-frame", on_tablet_frame)
- end
- function on_new_device(device)
- local udev = device:udev_properties()
- if udev["ID_INPUT_TABLET"] and not udev["ID_INPUT_TABLET_PAD"] then
- libinput:log_info("Found tablet device")
- tablet_device = device
- setup()
- end
- if udev["ID_INPUT_MOUSE"] then
- libinput:log_info("Found pointer device")
- pointer_device = device
- setup()
- end
- end
- -- setup listener
- libinput:connect("new-evdev-device", on_new_device)
|