Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/backends/meta-idle-monitor-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ typedef struct
guint64 timeout_msec;
int idle_source_id;
GSource *timeout_source;
gboolean ignore_inhibitors;
} MetaIdleMonitorWatch;

struct _MetaIdleMonitor
Expand All @@ -56,4 +57,11 @@ struct _MetaIdleMonitorClass

void meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor);

guint meta_idle_monitor_add_idle_watch_full (MetaIdleMonitor *monitor,
guint64 interval_msec,
gboolean ignore_inhibitors,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify);

#endif /* META_IDLE_MONITOR_PRIVATE_H */
35 changes: 33 additions & 2 deletions src/backends/meta-idle-monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ update_inhibited_watch (gpointer key,
if (!watch->timeout_source)
return;

if (monitor->inhibited)
if (monitor->inhibited && !watch->ignore_inhibitors)
{
g_source_set_ready_time (watch->timeout_source, -1);
}
Expand Down Expand Up @@ -337,6 +337,7 @@ make_watch (MetaIdleMonitor *monitor,
watch->user_data = user_data;
watch->notify = notify;
watch->timeout_msec = timeout_msec;
watch->ignore_inhibitors = FALSE;

if (timeout_msec != 0)
{
Expand Down Expand Up @@ -498,7 +499,7 @@ meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor)
}
else
{
if (monitor->inhibited)
if (monitor->inhibited && !watch->ignore_inhibitors)
{
g_source_set_ready_time (watch->timeout_source, -1);
}
Expand All @@ -513,3 +514,33 @@ meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor)

g_list_free (watch_ids);
}

guint
meta_idle_monitor_add_idle_watch_full (MetaIdleMonitor *monitor,
guint64 interval_msec,
gboolean ignore_inhibitors,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatch *watch;

g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
g_return_val_if_fail (interval_msec > 0, 0);

watch = make_watch (monitor,
interval_msec,
callback,
user_data,
notify);

watch->ignore_inhibitors = ignore_inhibitors;

if (monitor->inhibited && ignore_inhibitors && watch->timeout_source)
{
g_source_set_ready_time (watch->timeout_source,
monitor->last_event_time +
watch->timeout_msec * 1000);
}
return watch->id;
}
3 changes: 3 additions & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,8 @@ if have_wayland
'wayland/meta-wayland-layer-shell.c',
'wayland/meta-wayland-layer-shell.h',
'wayland/meta-wayland.h',
'wayland/meta-wayland-idle-notify.h',
'wayland/meta-wayland-idle-notify.c',
'wayland/meta-wayland-idle-inhibit.c',
'wayland/meta-wayland-idle-inhibit.h',
'wayland/meta-wayland-inhibit-shortcuts.c',
Expand Down Expand Up @@ -858,6 +860,7 @@ if have_wayland
['xapp-shell', 'private', ],
['xwayland-keyboard-grab', 'unstable', 'v1', ],
['wayland-drm', 'private', ],
['ext-idle-notify', 'staging', 'v1', ],
]
if have_wayland_eglstream
wayland_eglstream_protocols_dir = wayland_eglstream_protocols_dep.get_variable(pkgconfig: 'pkgdatadir')
Expand Down
226 changes: 226 additions & 0 deletions src/wayland/meta-wayland-idle-notify.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
/*
* Copyright (C) 2026 Linux Mint
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/

#include "config.h"

#include "wayland/meta-wayland-idle-notify.h"

#include "backends/meta-idle-monitor-private.h"
#include "wayland/meta-wayland-private.h"
#include "wayland/meta-wayland-versions.h"

#include "ext-idle-notify-v1-server-protocol.h"

typedef struct _MetaWaylandIdleNotification
{
struct wl_resource *resource;

MetaIdleMonitor *monitor;

guint idle_watch_id;
guint active_watch_id;

guint timeout;

gboolean ignore_inhibitors;
} MetaWaylandIdleNotification;

static void idle_trigger_cb (MetaIdleMonitor *monitor,
guint id,
gpointer user_data);

static void
active_trigger_cb (MetaIdleMonitor *monitor,
guint id,
gpointer user_data)
{
MetaWaylandIdleNotification *notification = user_data;

notification->active_watch_id = 0;

ext_idle_notification_v1_send_resumed (notification->resource);

notification->idle_watch_id =
meta_idle_monitor_add_idle_watch_full (notification->monitor,
notification->timeout,
notification->ignore_inhibitors,
idle_trigger_cb,
notification,
NULL);
}

static void
idle_trigger_cb (MetaIdleMonitor *monitor,
guint id,
gpointer user_data)
{
MetaWaylandIdleNotification *notification = user_data;

meta_idle_monitor_remove_watch (notification->monitor, id);
notification->idle_watch_id = 0;

ext_idle_notification_v1_send_idled (notification->resource);

notification->active_watch_id =
meta_idle_monitor_add_user_active_watch (notification->monitor,
active_trigger_cb,
notification,
NULL);
}

static void
ext_idle_notification_destructor (struct wl_resource *resource)
{
MetaWaylandIdleNotification *notification = wl_resource_get_user_data (resource);

if (notification->idle_watch_id)
meta_idle_monitor_remove_watch (notification->monitor,
notification->idle_watch_id);

if (notification->active_watch_id)
meta_idle_monitor_remove_watch (notification->monitor,
notification->active_watch_id);

g_free (notification);
}

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

static const struct ext_idle_notification_v1_interface ext_idle_notification_v1_impl = {
ext_idle_notification_destroy,
};

static void
ext_idle_notification_create (struct wl_client *client,
struct wl_resource *manager_resource,
uint32_t id,
uint32_t timeout,
struct wl_resource *seat_resource,
gboolean ignore_inhibitors)
{
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWaylandIdleNotification *notification;
uint32_t version;
ClutterInputDevice *pointer_device = NULL;

notification = g_new0 (MetaWaylandIdleNotification, 1);
notification->timeout = timeout;
notification->ignore_inhibitors = ignore_inhibitors;

if (seat && seat->pointer)
pointer_device = seat->pointer->device;

if (pointer_device)
{
MetaBackend *backend = meta_get_backend ();
notification->monitor = meta_backend_get_idle_monitor (backend, pointer_device);
}
else
{
notification->monitor = meta_idle_monitor_get_core ();
}

version = wl_resource_get_version (manager_resource);
notification->resource = wl_resource_create (client,
&ext_idle_notification_v1_interface,
version,
id);

wl_resource_set_implementation (notification->resource,
&ext_idle_notification_v1_impl,
notification,
ext_idle_notification_destructor);

notification->idle_watch_id =
meta_idle_monitor_add_idle_watch_full (notification->monitor,
notification->timeout,
notification->ignore_inhibitors,
idle_trigger_cb,
notification,
NULL);
}

static void
ext_idle_notifier_get_idle_notification (struct wl_client *client,
struct wl_resource *resource,
uint32_t id,
uint32_t timeout,
struct wl_resource *seat)
{
ext_idle_notification_create (client, resource,
id, timeout,
seat, FALSE);
}

static void
ext_idle_notifier_get_input_idle_notification (struct wl_client *client,
struct wl_resource *resource,
uint32_t id,
uint32_t timeout,
struct wl_resource *seat)
{
ext_idle_notification_create (client, resource,
id, timeout,
seat, TRUE);
}

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

static const struct ext_idle_notifier_v1_interface ext_idle_notifier_v1_impl = {
ext_idle_notifier_destroy,
ext_idle_notifier_get_idle_notification,
ext_idle_notifier_get_input_idle_notification,
};

static void
bind_ext_idle_notifier (struct wl_client *client,
void *data,
uint32_t version,
uint32_t id)
{
struct wl_resource *resource;

resource = wl_resource_create (client,
&ext_idle_notifier_v1_interface,
version,
id);
wl_resource_set_implementation (resource,
&ext_idle_notifier_v1_impl,
NULL,
NULL);
}

void
meta_wayland_idle_notify_init (MetaWaylandCompositor *compositor)
{
if (wl_global_create (compositor->wayland_display,
&ext_idle_notifier_v1_interface,
META_EXT_IDLE_NOTIFY_V1_VERSION,
NULL,
bind_ext_idle_notifier) == NULL)
g_error ("Failed to register a global ext-idle-notify object");
}
25 changes: 25 additions & 0 deletions src/wayland/meta-wayland-idle-notify.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2026 Linux Mint
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/

#ifndef META_WAYLAND_EXT_IDLE_NOTIFY_H
#define META_WAYLAND_EXT_IDLE_NOTIFY_H

#include "wayland/meta-wayland-types.h"

void meta_wayland_idle_notify_init (MetaWaylandCompositor *compositor);

#endif
1 change: 1 addition & 0 deletions src/wayland/meta-wayland-versions.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#define META_GTK_SHELL1_VERSION 6
#define META_WL_SUBCOMPOSITOR_VERSION 1
#define META_ZWP_POINTER_GESTURES_V1_VERSION 3
#define META_EXT_IDLE_NOTIFY_V1_VERSION 1
#define META_ZWP_IDLE_INHIBIT_V1_VERSION 1
#define META_ZXDG_EXPORTER_V1_VERSION 1
#define META_ZXDG_IMPORTER_V1_VERSION 1
Expand Down
2 changes: 2 additions & 0 deletions src/wayland/meta-wayland.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "wayland/meta-wayland-drm.h"
#include "wayland/meta-wayland-egl-stream.h"
#include "wayland/meta-wayland-idle-inhibit.h"
#include "wayland/meta-wayland-idle-notify.h"
#include "wayland/meta-wayland-inhibit-shortcuts-dialog.h"
#include "wayland/meta-wayland-inhibit-shortcuts.h"
#include "wayland/meta-wayland-legacy-xdg-foreign.h"
Expand Down Expand Up @@ -478,6 +479,7 @@ meta_wayland_compositor_setup (MetaWaylandCompositor *wayland_compositor)
meta_wayland_input_method_manager_init (compositor);
meta_wayland_virtual_keyboard_manager_init (compositor);
meta_wayland_activation_init (compositor);
meta_wayland_idle_notify_init (compositor);
meta_wayland_idle_inhibit_init (compositor);
meta_wayland_init_xdg_wm_dialog (compositor);
meta_wayland_xdg_toplevel_tag_init (compositor);
Expand Down
Loading