Skip to content

Commit

Permalink
Partly revert "(wlroots a289f81) drop KDE idle protocol support" and …
Browse files Browse the repository at this point in the history
…change it to the idle notify v1 protocola
  • Loading branch information
arjanoosting authored and jwijenbergh committed Jun 9, 2024
1 parent 465126f commit b7cb03a
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Qtile x.xx.x, released xxxx-xx-xx:
- Add `background` parameter to `Screen` to paint a solid colour background
- Add ability to use key codes to bind keys. Will benefit users who change keyboard layouts but
wish to retain same bindings, irrespective of layout.
- Wayland: Add support for idle-notify-v1 protocol needed by swayidle.

* bugfixes
- Fix `Plasma` layout with `ScreenSplit` by implementing `get_windows`
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ def __dir__(self):
"wlroots.wlr_types",
"wlroots.wlr_types.cursor",
"wlroots.wlr_types.foreign_toplevel_management_v1",
"wlroots.wlr_types.idle",
"wlroots.wlr_types.idle_inhibit_v1",
"wlroots.wlr_types.idle_notify_v1",
"wlroots.wlr_types.keyboard",
"wlroots.wlr_types.layer_shell_v1",
"wlroots.wlr_types.output_management_v1",
Expand Down
43 changes: 43 additions & 0 deletions libqtile/backend/wayland/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
xdg_decoration_v1,
)
from wlroots.wlr_types.cursor import Cursor, WarpMode
from wlroots.wlr_types.idle_inhibit_v1 import IdleInhibitorManagerV1, IdleInhibitorV1
from wlroots.wlr_types.idle_notify_v1 import IdleNotifierV1
from wlroots.wlr_types.keyboard import Keyboard
from wlroots.wlr_types.layer_shell_v1 import LayerShellV1, LayerSurfaceV1
from wlroots.wlr_types.output_management_v1 import (
Expand Down Expand Up @@ -330,6 +332,9 @@ def __init__(self) -> None:
self.add_listener(
output_power_manager.set_mode_event, self._on_output_power_manager_set_mode
)
self.idle = IdleNotifierV1(self.display)
idle_ihibitor_manager = IdleInhibitorManagerV1(self.display)
self.add_listener(idle_ihibitor_manager.new_inhibitor_event, self._on_new_idle_inhibitor)
PrimarySelectionV1DeviceManager(self.display)
virtual_keyboard_manager_v1 = vkeyboard.VirtualKeyboardManagerV1(self.display)
self.add_listener(
Expand Down Expand Up @@ -688,6 +693,7 @@ def _on_cursor_frame(self, _listener: Listener, _data: Any) -> None:

def _on_cursor_button(self, _listener: Listener, event: pointer.PointerButtonEvent) -> None:
assert self.qtile is not None
self.idle.notify_activity(self.seat)
found = None
pressed = event.button_state == input_device.ButtonState.PRESSED
if pressed:
Expand Down Expand Up @@ -726,6 +732,7 @@ def _implicit_grab_motion(self, time: int) -> None:

def _on_cursor_motion(self, _listener: Listener, event: pointer.PointerMotionEvent) -> None:
assert self.qtile is not None
self.idle.notify_activity(self.seat)

dx = event.delta_x
dy = event.delta_y
Expand Down Expand Up @@ -758,6 +765,7 @@ def _on_cursor_motion_absolute(
self, _listener: Listener, event: pointer.PointerMotionAbsoluteEvent
) -> None:
assert self.qtile is not None
self.idle.notify_activity(self.seat)

x, y = self.cursor.absolute_to_layout_coords(event.pointer.base, event.x, event.y)
self.cursor.move(x - self.cursor.x, y - self.cursor.y)
Expand All @@ -771,6 +779,7 @@ def _on_cursor_pinch_begin(
_listener: Listener,
event: pointer.PointerPinchBeginEvent,
) -> None:
self.idle.notify_activity(self.seat)
self._gestures.send_pinch_begin(self.seat, event.time_msec, event.fingers)

def _on_cursor_pinch_update(
Expand All @@ -787,13 +796,15 @@ def _on_cursor_pinch_end(
_listener: Listener,
event: pointer.PointerPinchEndEvent,
) -> None:
self.idle.notify_activity(self.seat)
self._gestures.send_pinch_end(self.seat, event.time_msec, event.cancelled)

def _on_cursor_swipe_begin(
self,
_listener: Listener,
event: pointer.PointerSwipeBeginEvent,
) -> None:
self.idle.notify_activity(self.seat)
self._gestures.send_swipe_begin(self.seat, event.time_msec, event.fingers)

def _on_cursor_swipe_update(
Expand All @@ -808,20 +819,23 @@ def _on_cursor_swipe_end(
_listener: Listener,
event: pointer.PointerSwipeEndEvent,
) -> None:
self.idle.notify_activity(self.seat)
self._gestures.send_swipe_end(self.seat, event.time_msec, event.cancelled)

def _on_cursor_hold_begin(
self,
_listener: Listener,
event: pointer.PointerHoldBeginEvent,
) -> None:
self.idle.notify_activity(self.seat)
self._gestures.send_hold_begin(self.seat, event.time_msec, event.fingers)

def _on_cursor_hold_end(
self,
_listener: Listener,
event: pointer.PointerHoldEndEvent,
) -> None:
self.idle.notify_activity(self.seat)
self._gestures.send_hold_end(self.seat, event.time_msec, event.cancelled)

def _on_new_pointer_constraint(
Expand All @@ -847,6 +861,20 @@ def _on_new_virtual_pointer(
device = self._add_new_pointer(new_pointer_event.new_pointer.pointer.base)
logger.info("New virtual pointer: %s %s", *device.get_info())

def _on_new_idle_inhibitor(
self, _listener: Listener, idle_inhibitor: IdleInhibitorV1
) -> None:
logger.debug("Signal: idle_inhibitor new_inhibitor")

for win in self.qtile.windows_map.values():
if isinstance(win, (window.Window, window.Static)):
win.surface.for_each_surface(win.add_idle_inhibitor, idle_inhibitor)
if idle_inhibitor.data:
# We break if the .data attribute was set, because that tells us
# that `win.add_idle_inhibitor` identified this inhibitor as
# belonging to that window.
break

def _on_input_inhibitor_activate(self, _listener: Listener, _data: Any) -> None:
logger.debug("Signal: input_inhibitor activate")
assert self.qtile is not None
Expand Down Expand Up @@ -1454,6 +1482,21 @@ def _under_pointer(self) -> tuple[window.WindowType, Surface | None, float, floa
logger.warning("Couldn't determine what was under the pointer. Please report.")
return None

def check_idle_inhibitor(self) -> None:
"""
Checks if any window that is currently mapped has idle inhibitor
and if so inhibits idle
"""
assert self.qtile is not None

for win in self.qtile.windows_map.values():
if not isinstance(win, window.Internal) and win.is_idle_inhibited:
# TODO: do we also need to check that the window is mapped?
self.idle.set_inhibited(True)
return

self.idle.set_inhibited(False)

def get_screen_info(self) -> list[ScreenRect]:
"""Get the output information"""
return [output.get_screen_info() for output in self.get_enabled_outputs()]
Expand Down
2 changes: 2 additions & 0 deletions libqtile/backend/wayland/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ def _on_modifier(self, _listener: Listener, _data: Any) -> None:
def _on_key(self, _listener: Listener, event: KeyboardKeyEvent) -> None:
self.qtile = self.core.qtile

self.core.idle.notify_activity(self.seat)

if event.state == KEY_PRESSED and not self.core.exclusive_client:
# translate libinput keycode -> xkbcommon
keycode = event.keycode + 8
Expand Down
59 changes: 59 additions & 0 deletions libqtile/backend/wayland/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from wlroots import PtrHasData
from wlroots.util.box import Box
from wlroots.wlr_types import Buffer
from wlroots.wlr_types.idle_inhibit_v1 import IdleInhibitorV1
from wlroots.wlr_types.pointer_constraints_v1 import (
PointerConstraintV1,
PointerConstraintV1StateField,
Expand All @@ -53,6 +54,8 @@
if typing.TYPE_CHECKING:
from typing import Any

from wlroots.wlr_types import Surface

from libqtile.backend.wayland.core import Core
from libqtile.command.base import CommandObject, ItemT
from libqtile.core.manager import Qtile
Expand Down Expand Up @@ -112,6 +115,7 @@ def __init__(self, core: Core, qtile: Qtile, surface: S):
self.y = 0
self._opacity: float = 1.0
self._wm_class: str | None = None
self._idle_inhibitors_count: int = 0
self._urgent = False

# Create a scene-graph tree for this window and its borders
Expand Down Expand Up @@ -229,6 +233,15 @@ def _on_foreign_request_close(self, _listener: Listener, _data: Any) -> None:
logger.debug("Signal: foreign_toplevel_management request_close")
self.kill()

def _on_inhibitor_destroy(self, listener: Listener, surface: Surface) -> None:
# We don't have reference to the inhibitor, but it doesn't really
# matter we only need to keep count of how many inhibitors there are
self._idle_inhibitors_count -= 1
listener.remove()
if self._idle_inhibitors_count == 0:
self.core.check_idle_inhibitor()
# TODO: do we also need to check idle inhibitors when unmapping?

def hide(self) -> None:
self.container.node.set_enabled(enabled=False)
seat = self.core.seat
Expand Down Expand Up @@ -587,6 +600,24 @@ def info(self) -> dict:
def match(self, match: config._Match) -> bool:
return match.compare(self)

def add_idle_inhibitor(
self,
surface: Surface,
_x: int,
_y: int,
inhibitor: IdleInhibitorV1,
) -> None:
if surface == inhibitor.surface:
self._idle_inhibitors_count += 1
inhibitor.data = self
self.add_listener(inhibitor.destroy_event, self._on_inhibitor_destroy)
if self._idle_inhibitors_count == 1:
self.core.check_idle_inhibitor()

@property
def is_idle_inhibited(self) -> bool:
return self._idle_inhibitors_count > 0

def _items(self, name: str) -> ItemT:
if name == "group":
return True, []
Expand Down Expand Up @@ -763,6 +794,7 @@ def __init__(
qtile: Qtile,
surface: S,
wid: int,
idle_inhibitor_count: int = 0,
):
base.Static.__init__(self)
self.core = core
Expand All @@ -778,6 +810,7 @@ def __init__(
self.bordercolor: list[ffi.CData] = [_rgb((0, 0, 0, 1))]
self.opacity: float = 1.0
self._wm_class: str | None = None
self._idle_inhibitors_count = idle_inhibitor_count
self.ftm_handle: ftm.ForeignToplevelHandleV1 | None = None
self.data_handle = ffi.new_handle(self)
surface.data = self.data_handle
Expand Down Expand Up @@ -842,6 +875,32 @@ def _on_foreign_request_close(self, _listener: Listener, _data: Any) -> None:
logger.debug("Signal: foreign_toplevel_management static request_close")
self.kill()

def _on_inhibitor_destroy(self, listener: Listener, surface: Surface) -> None:
# We don't have reference to the inhibitor, but it doesn't really
# matter we only need to keep count of how many inhibitors there are
self._idle_inhibitors_count -= 1
listener.remove()
if self._idle_inhibitors_count == 0:
self.core.check_idle_inhibitor()

def add_idle_inhibitor(
self,
surface: Surface,
_x: int,
_y: int,
inhibitor: IdleInhibitorV1,
) -> None:
if surface == inhibitor.surface:
self._idle_inhibitors_count += 1
inhibitor.data = self
self.add_listener(inhibitor.destroy_event, self._on_inhibitor_destroy)
if self._idle_inhibitors_count == 1:
self.core.check_idle_inhibitor()

@property
def is_idle_inhibited(self) -> bool:
return self._idle_inhibitors_count > 0

def belongs_to_client(self, other: Client) -> bool:
return other == Client.from_resource(self.surface.surface._ptr.resource)

Expand Down
6 changes: 5 additions & 1 deletion libqtile/backend/wayland/xdgwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ def _to_static(
self.core,
self.qtile,
self,
self._idle_inhibitors_count,
)


Expand All @@ -324,9 +325,12 @@ def __init__(
core: Core,
qtile: Qtile,
win: XdgWindow,
idle_inhibitor_count: int,
):
surface = win.surface
Static.__init__(self, core, qtile, surface, win.wid)
Static.__init__(
self, core, qtile, surface, win.wid, idle_inhibitor_count=idle_inhibitor_count
)

if surface.toplevel.title:
self.name = surface.toplevel.title
Expand Down
9 changes: 7 additions & 2 deletions libqtile/backend/wayland/xwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,9 @@ def static(
def _to_static(
self, x: int | None, y: int | None, width: int | None, height: int | None
) -> XStatic:
return XStatic(self.core, self.qtile, self, x, y, width, height)
return XStatic(
self.core, self.qtile, self, self._idle_inhibitors_count, x, y, width, height
)


class ConfigWindow:
Expand All @@ -401,13 +403,16 @@ def __init__(
core: Core,
qtile: Qtile,
win: XWindow,
idle_inhibitor_count: int,
x: int | None,
y: int | None,
width: int | None,
height: int | None,
):
surface = win.surface
Static.__init__(self, core, qtile, surface, win.wid)
Static.__init__(
self, core, qtile, surface, win.wid, idle_inhibitor_count=idle_inhibitor_count
)
self._wm_class = surface.wm_class

self._conf_x = x
Expand Down

0 comments on commit b7cb03a

Please sign in to comment.