diff --git a/kick.c b/kick.c index ba3af37..236ff0b 100644 --- a/kick.c +++ b/kick.c @@ -83,14 +83,17 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include +#include #include #include #include @@ -104,8 +107,12 @@ #include #include #include +#include #include +#include +#include #include +#include #include #include #include @@ -344,6 +351,38 @@ struct kick_server { nothing to wire up: every output commit that carries a rendered buffer becomes a copyable frame. */ struct wlr_screencopy_manager_v1 *screencopy_mgr; + /* Tearing (wp-tearing-control-v1) + fractional-scale (wp-fractional-scale): + both are advertised for client convenience. kick drives a vsynced scene + and fixed 1.0 scale, so nothing is honoured: the hint object is only + logged (DEBUG), and fractional scale has nothing to notify. */ + struct wlr_tearing_control_manager_v1 *tearing_mgr; + struct wl_listener tearing_new_object; + struct wlr_fractional_scale_manager_v1 *fractional_scale_mgr; + /* Output power management (zwlr_output_power_management_v1): a client + (e.g. wlopm) blanks or unblanks a specific output. kick's seatless + headless/standalone output maps to the single server output. */ + struct wlr_output_power_manager_v1 *output_power_mgr; + struct wl_listener output_power_set_mode; + /* Keyboard shortcuts inhibit (zwp_keyboard_shortcuts_inhibit_v1): lets a + fullscreen game/VM grab the compositor's keyboard shortcuts. While the + focused surface's inhibitor is active, the grab chords in + process_key_event are swallowed (see process_key_event). */ + struct wlr_keyboard_shortcuts_inhibit_manager_v1 *kb_inhibit_mgr; + struct wl_listener kb_inhibit_new_inhibitor; + struct wl_listener kb_inhibit_destroy; + /* Virtual keyboard/pointer (zwp_virtual_keyboard_v1 / + zwp_virtual_pointer_v1): synthesised input from clients like wtype, fed + into the seat just like real devices. */ + struct wlr_virtual_keyboard_manager_v1 *virtual_kb_mgr; + struct wl_listener virtual_kb_new; + struct wlr_virtual_keyboard_v1 *virtual_keyboard; + struct wlr_virtual_pointer_manager_v1 *virtual_ptr_mgr; + struct wl_listener virtual_ptr_new; + /* Xdg-activation (xdg-activation-v1): lets a launcher focus a window by + token instead of requiring user input at exactly the right time. On a + request_activate we switch to the tab owning that surface. */ + struct wlr_xdg_activation_v1 *xdg_activation; + struct wl_listener xdg_activation_request; /* Pointer constraints + relative pointer (zwp_pointer_constraints_v1 / zwp_relative_pointer_v1). Only the focused surface's constraint is active; its region lives in the surface's local space, so the surface's @@ -5803,6 +5842,22 @@ static void handle_idle_new_inhibitor(struct wl_listener *listener, void *data) wlr_idle_notifier_v1_set_inhibited(server.idle_notifier, server.idle_inhibited); } +/* ===================== Tearing + fractional-scale ===================== + Both are pass-through wlroots managers that exist only to be advertised: + - wp-tearing-control-v1 lets a surface request unthrottled presentation. + kick drives a fully vsynced scene (no page-flip bypass), so the hint is + only logged (DEBUG); nothing skips vsync. + - wp-fractional-scale-v1 lets clients learn a non-integer scale. kick's + output runs at scale 1.0 and never changes it at runtime, so there is + nothing to notify via wlr_fractional_scale_v1_notify_scale. */ +static void handle_tearing_new_object(struct wl_listener *listener, + void *data) { + (void)listener; + struct wlr_tearing_control_v1 *tc = data; + kick_log(KICK_LOG_DEBUG, "[tearing] surface %p hint=%d\n", + (void *)tc->surface, (int)tc->current); +} + /* ===================== Foreign toplevel management ===================== Taskbars/switchers (waybar taskbar, disorder, etc.) enumerate kick's windows through wlr-foreign-toplevel-management-v1 and @@ -9830,6 +9885,16 @@ int main(int argc, char *argv[]) { runs the whole capture flow itself off the output commit path. */ server.screencopy_mgr = wlr_screencopy_manager_v1_create(server.wl_display); + /* Tearing-control + fractional-scale: advertised for client convenience + (games, HiDPI surfaces). Nothing is honoured beyond the DEBUG log on + a new tearing object. */ + server.tearing_mgr = wlr_tearing_control_manager_v1_create(server.wl_display, 1); + server.tearing_new_object.notify = handle_tearing_new_object; + wl_signal_add(&server.tearing_mgr->events.new_object, + &server.tearing_new_object); + server.fractional_scale_mgr = + wlr_fractional_scale_manager_v1_create(server.wl_display, 1); + /* The output layout exists in both modes so xdg-output can advertise logical output geometry to clients; nested mode simply has one output (the host window) in the layout. */ diff --git a/meson.build b/meson.build index 1bf97af..46b13f8 100644 --- a/meson.build +++ b/meson.build @@ -149,6 +149,24 @@ protocols = { 'wlr-protocols/wlr-screencopy-unstable-v1.xml', 'wlr-screencopy-unstable-v1', ], + # Tearing control (a surface asks for unthrottled presentation) and + # fractional scale (a surface learns a non-integer output scale). Both + # are staging protocols; kick only advertises them. + 'tearing-control': [ + wl_protocols_dir / 'staging/tearing-control/tearing-control-v1.xml', + 'tearing-control-v1', + ], + 'fractional-scale': [ + wl_protocols_dir / 'staging/fractional-scale/fractional-scale-v1.xml', + 'fractional-scale-v1', + ], + # Output power management (a client blanks/unblanks an output). Bundled + # locally like the other wlr-protocols XMLs (copied from the pinned + # wlroots subproject). + 'wlr-output-power-management-unstable-v1': [ + 'wlr-protocols/wlr-output-power-management-unstable-v1.xml', + 'wlr-output-power-management-unstable-v1', + ], 'cursor-shape': [ wl_protocols_dir / 'staging/cursor-shape/cursor-shape-v1.xml', 'cursor-shape-v1', @@ -223,6 +241,22 @@ foreach protocol, p : protocols output: base + '-protocol.h', command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@']) endif + if protocol == 'tearing-control' + # Serves wlr_tearing_control_v1.h's quoted + # #include "tearing-control-v1-protocol.h". + protocol_headers += custom_target(protocol + ' server header', + input: xml, + output: base + '-protocol.h', + command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@']) + endif + if protocol == 'wlr-output-power-management-unstable-v1' + # Serves wlr_output_power_management_v1.h's quoted + # #include "wlr-output-power-management-unstable-v1-protocol.h". + protocol_headers += custom_target(protocol + ' server header', + input: xml, + output: base + '-protocol.h', + command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@']) + endif endforeach executable('kick', diff --git a/tests/test_smoke.py b/tests/test_smoke.py index 6a2359b..53810d5 100644 --- a/tests/test_smoke.py +++ b/tests/test_smoke.py @@ -3365,3 +3365,26 @@ def test_standalone_headless_screencopy_frame(tmp_path): finally: s.close() + +def test_standalone_headless_tearing_and_fractional_globals(tmp_path): + """The compositor advertises wp_tearing_control_manager_v1 (games request + unthrottled presentation) and wp_fractional_scale_manager_v1 (clients + learn a non-integer scale). kick drives a vsynced scene at scale 1.0, + so both are pass-through: advertised but nothing honoured.""" + out = tmp_path / "globals.txt" + s = _spawn_standalone({}, "%s --globals-out '%s' '#112233'" % (WL, out)) + try: + deadline = time.monotonic() + 15.0 + while time.monotonic() < deadline: + if out.exists(): + break + time.sleep(0.1) + assert out.exists(), "wltest --globals-out never wrote its file" + names = {line.split()[0] for line in out.read_text().splitlines()} + for want in ("wp_tearing_control_manager_v1", + "wp_fractional_scale_manager_v1"): + assert want in names, \ + f"missing global {want}; advertised: {sorted(names)}" + finally: + s.close() + diff --git a/wlr-protocols/wlr-output-power-management-unstable-v1.xml b/wlr-protocols/wlr-output-power-management-unstable-v1.xml new file mode 100644 index 0000000..a977839 --- /dev/null +++ b/wlr-protocols/wlr-output-power-management-unstable-v1.xml @@ -0,0 +1,128 @@ + + + + Copyright © 2019 Purism SPC + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + This protocol allows clients to control power management modes + of outputs that are currently part of the compositor space. The + intent is to allow special clients like desktop shells to power + down outputs when the system is idle. + + To modify outputs not currently part of the compositor space see + wlr-output-management. + + Warning! The protocol described in this file is experimental and + backward incompatible changes may be made. Backward compatible changes + may be added together with the corresponding interface version bump. + Backward incompatible changes are done by bumping the version number in + the protocol and interface names and resetting the interface version. + Once the protocol is to be declared stable, the 'z' prefix and the + version number in the protocol and interface names are removed and the + interface version number is reset. + + + + + This interface is a manager that allows creating per-output power + management mode controls. + + + + + Create a output power management mode control that can be used to + adjust the power management mode for a given output. + + + + + + + + All objects created by the manager will still remain valid, until their + appropriate destroy request has been called. + + + + + + + This object offers requests to set the power management mode of + an output. + + + + + + + + + + + + + + Set an output's power save mode to the given mode. The mode change + is effective immediately. If the output does not support the given + mode a failed event is sent. + + + + + + + Report the power management mode change of an output. + + The mode event is sent after an output changed its power + management mode. The reason can be a client using set_mode or the + compositor deciding to change an output's mode. + This event is also sent immediately when the object is created + so the client is informed about the current power management mode. + + + + + + + This event indicates that the output power management mode control + is no longer valid. This can happen for a number of reasons, + including: + - The output doesn't support power management + - Another client already has exclusive power management mode control + for this output + - The output disappeared + + Upon receiving this event, the client should destroy this object. + + + + + + Destroys the output power management mode control object. + + + +