Skip to content
This repository was archived by the owner on Jan 30, 2025. It is now read-only.

Commit

Permalink
vm_tools: sommelier: allow inhibit sleep on idle
Browse files Browse the repository at this point in the history
Implement zwp_idle_inhibit_manager_v1[1].

This is a simple pass-through implementation to the host.

At present, garcon and concierge already support this feature by implementing dbus org.freedesktop.ScreenSaver[2], but mpv refuses to use this[3].

[1]: https://wayland.app/protocols/idle-inhibit-unstable-v1
[2]: https://people.freedesktop.org/~hadess/idle-inhibition-spec/re01.html
[3]: mpv-player/mpv#9275 (comment)

BUG=None
TEST=`meson test`, `mpv -v --frames=0 <some_video_source> | grep zwp_idle_inhibit_manager_v1`, manually tested with mpv

Change-Id: I521ededd5f5c5f96165c04abc47e6aa85153ba8f
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/4864538
Reviewed-by: Nic Hollingum <[email protected]>
Tested-by: Fabian Bieler <[email protected]>
Commit-Queue: Fabian Bieler <[email protected]>
Reviewed-by: Chloe Pelling <[email protected]>
  • Loading branch information
fabianbieler authored and Chromeos LUCI committed Sep 22, 2023
1 parent 9e0e1d5 commit 89002b8
Show file tree
Hide file tree
Showing 7 changed files with 233 additions and 0 deletions.
2 changes: 2 additions & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ wayland_protocols = [
"protocol/fractional-scale-v1.xml",
"protocol/gaming-input-unstable-v2.xml",
"protocol/gtk-shell.xml",
"protocol/idle-inhibit-unstable-v1.xml",
"protocol/keyboard-extension-unstable-v1.xml",
"protocol/linux-dmabuf-unstable-v1.xml",
"protocol/linux-explicit-synchronization-unstable-v1.xml",
Expand Down Expand Up @@ -111,6 +112,7 @@ static_library("libsommelier") {
"sommelier-fractional-scale.cc",
"sommelier-global.cc",
"sommelier-gtk-shell.cc",
"sommelier-idle-inhibit-manager.cc",
"sommelier-inpututils.cc",
"sommelier-output.cc",
"sommelier-pointer-constraints.cc",
Expand Down
2 changes: 2 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ wl_protocols = [
'protocol/fractional-scale-v1.xml',
'protocol/gaming-input-unstable-v2.xml',
'protocol/gtk-shell.xml',
'protocol/idle-inhibit-unstable-v1.xml',
'protocol/keyboard-extension-unstable-v1.xml',
'protocol/linux-dmabuf-unstable-v1.xml',
'protocol/linux-explicit-synchronization-unstable-v1.xml',
Expand Down Expand Up @@ -159,6 +160,7 @@ libsommelier = static_library('sommelier',
'sommelier-fractional-scale.cc',
'sommelier-gtk-shell.cc',
'sommelier-global.cc',
'sommelier-idle-inhibit-manager.cc',
'sommelier-inpututils.cc',
'sommelier-output.cc',
'sommelier-pointer-constraints.cc',
Expand Down
83 changes: 83 additions & 0 deletions protocol/idle-inhibit-unstable-v1.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="idle_inhibit_unstable_v1">

<copyright>
Copyright © 2015 Samsung Electronics Co., Ltd

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.
</copyright>

<interface name="zwp_idle_inhibit_manager_v1" version="1">
<description summary="control behavior when display idles">
This interface permits inhibiting the idle behavior such as screen
blanking, locking, and screensaving. The client binds the idle manager
globally, then creates idle-inhibitor objects for each surface.

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.
</description>

<request name="destroy" type="destructor">
<description summary="destroy the idle inhibitor object">
Destroy the inhibit manager.
</description>
</request>

<request name="create_inhibitor">
<description summary="create a new inhibitor object">
Create a new inhibitor object associated with the given surface.
</description>
<arg name="id" type="new_id" interface="zwp_idle_inhibitor_v1"/>
<arg name="surface" type="object" interface="wl_surface"
summary="the surface that inhibits the idle behavior"/>
</request>

</interface>

<interface name="zwp_idle_inhibitor_v1" version="1">
<description summary="context object for inhibiting idle behavior">
An idle inhibitor prevents the output that the associated surface is
visible on from being set to a state where it is not visually usable due
to lack of user interaction (e.g. blanked, dimmed, locked, set to power
save, etc.) Any screensaver processes are also blocked from displaying.

If the surface is destroyed, unmapped, becomes occluded, loses
visibility, or otherwise becomes not visually relevant for the user, the
idle inhibitor will not be honored by the compositor; if the surface
subsequently regains visibility the inhibitor takes effect once again.
Likewise, the inhibitor isn't honored if the system was already idled at
the time the inhibitor was established, although if the system later
de-idles and re-idles the inhibitor will take effect.
</description>

<request name="destroy" type="destructor">
<description summary="destroy the idle inhibitor object">
Remove the inhibitor effect from the associated wl_surface.
</description>
</request>

</interface>
</protocol>
1 change: 1 addition & 0 deletions sommelier-ctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ struct sl_context {
struct sl_relative_pointer_manager* relative_pointer_manager;
struct sl_pointer_constraints* pointer_constraints;
struct sl_fractional_scale_manager* fractional_scale_manager;
struct sl_idle_inhibit_manager* idle_inhibit_manager;
struct wl_list outputs;
struct wl_list seats;
std::unique_ptr<struct wl_event_source> display_event_source;
Expand Down
120 changes: 120 additions & 0 deletions sommelier-idle-inhibit-manager.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sommelier.h" // NOLINT(build/include_directory)

#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <wayland-client.h>
#include <wayland-server-core.h>
#include <wayland-util.h>

#include "idle-inhibit-unstable-v1-client-protocol.h" // NOLINT(build/include_directory)
#include "idle-inhibit-unstable-v1-server-protocol.h" // NOLINT(build/include_directory)

struct sl_host_idle_inhibit_manager {
struct sl_context* ctx;
struct wl_resource* resource;
struct zwp_idle_inhibit_manager_v1* proxy;
};

struct sl_host_idle_inhibitor {
struct sl_context* ctx;
struct wl_resource* resource;
struct zwp_idle_inhibitor_v1* proxy;
};

static void sl_destroy_host_idle_inhibitor(struct wl_resource* resource) {
struct sl_host_idle_inhibitor* host =
static_cast<sl_host_idle_inhibitor*>(wl_resource_get_user_data(resource));

zwp_idle_inhibitor_v1_destroy(host->proxy);
wl_resource_set_user_data(resource, nullptr);
delete host;
}

static void sl_idle_inhibit_destroy(struct wl_client* client,
struct wl_resource* resource) {
wl_resource_destroy(resource);
}

static struct zwp_idle_inhibitor_v1_interface sl_idle_inhibit_implementation = {
sl_idle_inhibit_destroy,
};

static void sl_destroy_host_idle_inhibit_manager(struct wl_resource* resource) {
struct sl_host_idle_inhibit_manager* host =
static_cast<sl_host_idle_inhibit_manager*>(
wl_resource_get_user_data(resource));

zwp_idle_inhibit_manager_v1_destroy(host->proxy);
wl_resource_set_user_data(resource, nullptr);
delete host;
}

static void sl_idle_inhibit_manager_destroy(struct wl_client* client,
struct wl_resource* resource) {
wl_resource_destroy(resource);
}

static void sl_idle_inhibit_manager_create_inhibitor(
struct wl_client* client,
struct wl_resource* resource,
uint32_t id,
struct wl_resource* surface) {
struct sl_host_idle_inhibit_manager* host =
static_cast<sl_host_idle_inhibit_manager*>(
wl_resource_get_user_data(resource));
struct sl_host_surface* host_surface =
static_cast<sl_host_surface*>(wl_resource_get_user_data(surface));
struct wl_resource* idle_inhibit_resource =
wl_resource_create(client, &zwp_idle_inhibitor_v1_interface, 1, id);
struct sl_host_idle_inhibitor* idle_inhibitor_host =
new sl_host_idle_inhibitor();
idle_inhibitor_host->resource = idle_inhibit_resource;
idle_inhibitor_host->ctx = host->ctx;
idle_inhibitor_host->proxy = zwp_idle_inhibit_manager_v1_create_inhibitor(
host->proxy, host_surface->proxy);
wl_resource_set_implementation(
idle_inhibit_resource, &sl_idle_inhibit_implementation,
idle_inhibitor_host, sl_destroy_host_idle_inhibitor);
}

static struct zwp_idle_inhibit_manager_v1_interface
sl_idle_inhibit_manager_implementation = {
sl_idle_inhibit_manager_destroy,
sl_idle_inhibit_manager_create_inhibitor,
};

static void sl_bind_host_idle_inhibit_manager(struct wl_client* client,
void* data,
uint32_t version,
uint32_t id) {
struct sl_context* ctx = (struct sl_context*)data;
struct sl_idle_inhibit_manager* idle_inhibit_manager =
ctx->idle_inhibit_manager;
struct sl_host_idle_inhibit_manager* host =
new sl_host_idle_inhibit_manager();
host->ctx = ctx;
host->resource =
wl_resource_create(client, &zwp_idle_inhibit_manager_v1_interface, 1, id);
wl_resource_set_implementation(host->resource,
&sl_idle_inhibit_manager_implementation, host,
sl_destroy_host_idle_inhibit_manager);
host->proxy = static_cast<zwp_idle_inhibit_manager_v1*>(wl_registry_bind(
wl_display_get_registry(ctx->display), idle_inhibit_manager->id,
&zwp_idle_inhibit_manager_v1_interface,
wl_resource_get_version(host->resource)));
zwp_idle_inhibit_manager_v1_set_user_data(host->proxy, host);
}

struct sl_global* sl_idle_inhibit_manager_global_create(
struct sl_context* ctx) {
return sl_global_create(ctx, &zwp_idle_inhibit_manager_v1_interface, 1, ctx,
sl_bind_host_idle_inhibit_manager);
}
17 changes: 17 additions & 0 deletions sommelier.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#ifdef GAMEPAD_SUPPORT
#include "gaming-input-unstable-v2-client-protocol.h" // NOLINT(build/include_directory)
#endif
#include "idle-inhibit-unstable-v1-client-protocol.h" // NOLINT(build/include_directory)
#include "keyboard-extension-unstable-v1-client-protocol.h" // NOLINT(build/include_directory)
#include "linux-dmabuf-unstable-v1-client-protocol.h" // NOLINT(build/include_directory)
#include "linux-explicit-synchronization-unstable-v1-client-protocol.h" // NOLINT(build/include_directory)
Expand Down Expand Up @@ -791,6 +792,16 @@ void sl_registry_handler(void* data,
ctx->fractional_scale_manager = fractional_scale_manager;
fractional_scale_manager->host_fractional_scale_manager_global =
sl_fractional_scale_manager_global_create(ctx);
} else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0) {
struct sl_idle_inhibit_manager* idle_inhibit =
static_cast<sl_idle_inhibit_manager*>(
malloc(sizeof(struct sl_idle_inhibit_manager)));
assert(idle_inhibit);
idle_inhibit->ctx = ctx;
idle_inhibit->id = id;
assert(!ctx->idle_inhibit_manager);
ctx->idle_inhibit_manager = idle_inhibit;
idle_inhibit->host_global = sl_idle_inhibit_manager_global_create(ctx);
}
}

Expand Down Expand Up @@ -922,6 +933,12 @@ void sl_registry_remover(void* data,
ctx->pointer_constraints = nullptr;
return;
}
if (ctx->idle_inhibit_manager && ctx->idle_inhibit_manager->id == id) {
sl_global_destroy(ctx->idle_inhibit_manager->host_global);
free(ctx->idle_inhibit_manager);
ctx->idle_inhibit_manager = nullptr;
return;
}
wl_list_for_each(output, &ctx->outputs, link) {
if (output->id == id) {
sl_global_destroy(output->host_global);
Expand Down
8 changes: 8 additions & 0 deletions sommelier.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,12 @@ struct sl_host_gamepad {
};
#endif

struct sl_idle_inhibit_manager {
struct sl_context* ctx;
uint32_t id;
struct sl_global* host_global;
};

struct sl_host_buffer* sl_create_host_buffer(struct sl_context* ctx,
struct wl_client* client,
uint32_t id,
Expand Down Expand Up @@ -533,6 +539,8 @@ struct sl_global* sl_pointer_constraints_global_create(struct sl_context* ctx);
struct sl_global* sl_fractional_scale_manager_global_create(
struct sl_context* ctx);

struct sl_global* sl_idle_inhibit_manager_global_create(struct sl_context* ctx);

void sl_set_display_implementation(struct sl_context* ctx,
struct wl_client* client);

Expand Down

0 comments on commit 89002b8

Please sign in to comment.