diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 56 | ||||
| -rw-r--r-- | src/egg-idletime.c | 538 | ||||
| -rw-r--r-- | src/gpm-brightness.c | 253 | ||||
| -rw-r--r-- | src/gpm-button.c | 68 | ||||
| -rw-r--r-- | src/gpm-dpms.c | 371 | ||||
| -rw-r--r-- | src/gpm-manager.c | 15 | ||||
| -rw-r--r-- | src/gpm-tray-icon.c | 79 | ||||
| -rw-r--r-- | src/gpm-tray-icon.h | 2 | ||||
| -rw-r--r-- | src/meson.build | 45 | ||||
| -rw-r--r-- | src/msd-osd-window.c | 14 | ||||
| -rw-r--r-- | src/wlr-output-power-management-unstable-v1.xml | 128 |
11 files changed, 1240 insertions, 329 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index da49dab..0d8ab57 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,8 +8,13 @@ EXTRA_DIST = \ org.mate.PowerManager.Backlight.xml \ org.mate.PowerManager.KbdBacklight.xml \ gpm-marshal.list \ + wlr-output-power-management-unstable-v1.xml \ $(NULL) +WAYLAND_PROTOCOLS_DATADIR = @WAYLAND_PROTOCOLS_DATADIR@ +EXT_IDLE_NOTIFY_XML = $(WAYLAND_PROTOCOLS_DATADIR)/staging/ext-idle-notify/ext-idle-notify-v1.xml +WLR_OUTPUT_POWER_XML = $(srcdir)/wlr-output-power-management-unstable-v1.xml + AM_CPPFLAGS = \ $(GLIB_CFLAGS) \ $(DBUS_CFLAGS) \ @@ -21,15 +26,16 @@ AM_CPPFLAGS = \ $(LIBNOTIFY_CFLAGS) \ $(CANBERRA_CFLAGS) \ $(GSTREAMER_CFLAGS) \ + $(APPLICATION_INDICATOR_CFLAGS) \ -DI_KNOW_THE_DEVICEKIT_POWER_API_IS_SUBJECT_TO_CHANGE \ $(UPOWER_CFLAGS) \ -DBINDIR=\"$(bindir)\" \ -DSBINDIR=\"$(sbindir)\" \ -DMATELOCALEDIR=\""$(datadir)/locale"\" \ -DDATADIR=\"$(datadir)\" \ - -DPREFIX=\""$(prefix)"\" \ - -DSYSCONFDIR=\""$(sysconfdir)"\" \ - -DLIBDIR=\""$(libdir)"\" \ + -DPREFIX=\""$(prefix)\"" \ + -DSYSCONFDIR=\""$(sysconfdir)\"" \ + -DLIBDIR=\""$(libdir)\"" \ -DVERSION="\"$(VERSION)\"" \ -DGPM_ICONS_DATA=\"$(pkgdatadir)/icons\" \ -DGTKBUILDERDIR=\"$(pkgdatadir)\" \ @@ -38,6 +44,13 @@ AM_CPPFLAGS = \ -I$(top_srcdir) \ $(DISABLE_DEPRECATED) +if HAVE_WAYLAND +AM_CPPFLAGS += \ + $(WAYLAND_CLIENT_CFLAGS) \ + -DHAVE_WAYLAND \ + $(NULL) +endif + AM_CPPFLAGS += $(NULL) bin_PROGRAMS = \ @@ -78,6 +91,13 @@ libgpmshared_a_SOURCES = \ gpm-upower.c \ gpm-upower.h +if HAVE_WAYLAND +nodist_libgpmshared_a_SOURCES = \ + ext-idle-notify-v1-protocol.c \ + wlr-output-power-management-unstable-v1-protocol.c \ + $(NULL) +endif + mate_power_backlight_helper_SOURCES = \ gpm-backlight-helper.c \ $(NULL) @@ -208,8 +228,15 @@ mate_power_manager_LDADD = \ $(LIBNOTIFY_LIBS) \ $(GPM_EXTRA_LIBS) \ $(UPOWER_LIBS) \ + $(APPLICATION_INDICATOR_LIBS) \ -lm +if HAVE_WAYLAND +mate_power_manager_LDADD += \ + $(WAYLAND_CLIENT_LIBS) \ + $(NULL) +endif + mate_power_manager_CFLAGS = \ $(WARN_CFLAGS) \ $(NULL) @@ -289,6 +316,27 @@ BUILT_SOURCES = \ gpm-marshal.h \ $(NULL) +if HAVE_WAYLAND +BUILT_SOURCES += \ + ext-idle-notify-v1-client.h \ + ext-idle-notify-v1-protocol.c \ + wlr-output-power-management-unstable-v1-client.h \ + wlr-output-power-management-unstable-v1-protocol.c \ + $(NULL) +endif + +ext-idle-notify-v1-client.h: $(EXT_IDLE_NOTIFY_XML) + $(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@ + +ext-idle-notify-v1-protocol.c: $(EXT_IDLE_NOTIFY_XML) + $(AM_V_GEN)$(WAYLAND_SCANNER) private-code < $< > $@ + +wlr-output-power-management-unstable-v1-client.h: $(WLR_OUTPUT_POWER_XML) + $(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@ + +wlr-output-power-management-unstable-v1-protocol.c: $(WLR_OUTPUT_POWER_XML) + $(AM_V_GEN)$(WAYLAND_SCANNER) private-code < $< > $@ + gpm-marshal.c: gpm-marshal.list echo "#include \"gpm-marshal.h\"" > $@ && \ @GLIB_GENMARSHAL@ $< --prefix=gpm_marshal --body >> $@ @@ -320,6 +368,8 @@ org.mate.PowerManager.KbdBacklight.h: org.mate.PowerManager.KbdBacklight.xml clean-local: rm -f *~ rm -f gpm-marshal.c gpm-marshal.h + rm -f ext-idle-notify-v1-client.h ext-idle-notify-v1-protocol.c + rm -f wlr-output-power-management-unstable-v1-client.h wlr-output-power-management-unstable-v1-protocol.c CLEANFILES = \ $(BUILT_SOURCES) \ diff --git a/src/egg-idletime.c b/src/egg-idletime.c index cbf869c..e2edb42 100644 --- a/src/egg-idletime.c +++ b/src/egg-idletime.c @@ -25,10 +25,19 @@ #endif #include <glib.h> +#include <gdk/gdk.h> + +#ifdef HAVE_X11 #include <X11/Xlib.h> #include <X11/extensions/sync.h> #include <gdk/gdkx.h> -#include <gdk/gdk.h> +#endif /* HAVE_X11 */ + +#ifdef HAVE_WAYLAND +#include <gdk/gdkwayland.h> +#include <wayland-client.h> +#include "ext-idle-notify-v1-client.h" +#endif /* HAVE_WAYLAND */ #include <stdio.h> #include <stdlib.h> @@ -37,16 +46,27 @@ #include "egg-idletime.h" static void egg_idletime_finalize (GObject *object); +gint64 egg_idletime_get_time (EggIdletime *idletime); struct EggIdletimePrivate { - gint sync_event; gboolean reset_set; - XSyncCounter idle_counter; GPtrArray *array; +#ifdef HAVE_X11 + gint sync_event; + XSyncCounter idle_counter; Display *dpy; +#endif +#ifdef HAVE_WAYLAND + struct ext_idle_notifier_v1 *idle_notifier; + struct wl_seat *seat; + GPtrArray *wayland_notifications; /* of EggIdletimeWaylandNotification* */ + gboolean wayland_is_idle; + GTimer *idle_timer; +#endif }; +#ifdef HAVE_X11 typedef struct { guint id; @@ -54,6 +74,16 @@ typedef struct XSyncAlarm xalarm; EggIdletime *idletime; } EggIdletimeAlarm; +#endif + +#ifdef HAVE_WAYLAND +typedef struct +{ + guint id; + guint timeout; + struct ext_idle_notification_v1 *notification; +} EggIdletimeWaylandNotification; +#endif enum { SIGNAL_ALARM_EXPIRED, @@ -61,17 +91,21 @@ enum { LAST_SIGNAL }; +#ifdef HAVE_X11 typedef enum { EGG_IDLETIME_ALARM_TYPE_POSITIVE, EGG_IDLETIME_ALARM_TYPE_NEGATIVE, EGG_IDLETIME_ALARM_TYPE_DISABLED } EggIdletimeAlarmType; +#endif static guint signals [LAST_SIGNAL] = { 0 }; static gpointer egg_idletime_object = NULL; G_DEFINE_TYPE_WITH_PRIVATE (EggIdletime, egg_idletime, G_TYPE_OBJECT) +#ifdef HAVE_X11 + /** * egg_idletime_xsyncvalue_to_int64: */ @@ -82,17 +116,6 @@ egg_idletime_xsyncvalue_to_int64 (XSyncValue value) } /** - * egg_idletime_get_time: - */ -gint64 -egg_idletime_get_time (EggIdletime *idletime) -{ - XSyncValue value; - XSyncQueryCounter (idletime->priv->dpy, idletime->priv->idle_counter, &value); - return egg_idletime_xsyncvalue_to_int64 (value); -} - -/** * egg_idletime_xsync_alarm_set: */ static void @@ -135,37 +158,6 @@ egg_idletime_xsync_alarm_set (EggIdletime *idletime, EggIdletimeAlarm *alarm, Eg } /** - * egg_idletime_alarm_reset_all: - */ -void -egg_idletime_alarm_reset_all (EggIdletime *idletime) -{ - guint i; - EggIdletimeAlarm *alarm; - - g_return_if_fail (EGG_IS_IDLETIME (idletime)); - - if (!idletime->priv->reset_set) - return; - - /* reset all the alarms (except the reset alarm) to their timeouts */ - for (i=1; i<idletime->priv->array->len; i++) { - alarm = g_ptr_array_index (idletime->priv->array, i); - egg_idletime_xsync_alarm_set (idletime, alarm, EGG_IDLETIME_ALARM_TYPE_POSITIVE); - } - - /* set the reset alarm to be disabled */ - alarm = g_ptr_array_index (idletime->priv->array, 0); - egg_idletime_xsync_alarm_set (idletime, alarm, EGG_IDLETIME_ALARM_TYPE_DISABLED); - - /* emit signal so say we've reset all timers */ - g_signal_emit (idletime, signals [SIGNAL_RESET], 0); - - /* we need to be reset again on the next event */ - idletime->priv->reset_set = FALSE; -} - -/** * egg_idletime_alarm_find_id: */ static EggIdletimeAlarm * @@ -290,36 +282,6 @@ egg_idletime_alarm_new (EggIdletime *idletime, guint id) } /** - * egg_idletime_alarm_set: - */ -gboolean -egg_idletime_alarm_set (EggIdletime *idletime, guint id, guint timeout) -{ - EggIdletimeAlarm *alarm; - - g_return_val_if_fail (EGG_IS_IDLETIME (idletime), FALSE); - g_return_val_if_fail (id != 0, FALSE); - g_return_val_if_fail (timeout != 0, FALSE); - - /* see if we already created an alarm with this ID */ - alarm = egg_idletime_alarm_find_id (idletime, id); - if (alarm == NULL) { - /* create a new alarm */ - alarm = egg_idletime_alarm_new (idletime, id); - - /* add to array */ - g_ptr_array_add (idletime->priv->array, alarm); - } - - /* set the timeout */ - XSyncIntToValue (&alarm->timeout, (gint)timeout); - - /* set, and start the timer */ - egg_idletime_xsync_alarm_set (idletime, alarm, EGG_IDLETIME_ALARM_TYPE_POSITIVE); - return TRUE; -} - -/** * egg_idletime_alarm_free: */ static gboolean @@ -336,24 +298,73 @@ egg_idletime_alarm_free (EggIdletime *idletime, EggIdletimeAlarm *alarm) return TRUE; } +#endif /* HAVE_X11 */ + +#ifdef HAVE_WAYLAND + /** - * egg_idletime_alarm_free: + * egg_idletime_alarm_wayland_find_id: */ -gboolean -egg_idletime_alarm_remove (EggIdletime *idletime, guint id) +static EggIdletimeWaylandNotification * +egg_idletime_alarm_wayland_find_id (EggIdletime *idletime, guint id) { - EggIdletimeAlarm *alarm; + guint i; + EggIdletimeWaylandNotification *wn; + for (i = 0; i < idletime->priv->wayland_notifications->len; i++) { + wn = g_ptr_array_index (idletime->priv->wayland_notifications, i); + if (wn->id == id) + return wn; + } + return NULL; +} - g_return_val_if_fail (EGG_IS_IDLETIME (idletime), FALSE); +/** + * egg_idletime_wayland_notification_idled_cb: + */ +static void +egg_idletime_wayland_notification_idled_cb (void *data, + struct ext_idle_notification_v1 *notification) +{ + EggIdletime *idletime = EGG_IDLETIME (data); + EggIdletimeWaylandNotification *wn; + guint i; - alarm = egg_idletime_alarm_find_id (idletime, id); - if (alarm == NULL) - return FALSE; - egg_idletime_alarm_free (idletime, alarm); - return TRUE; + for (i = 0; i < idletime->priv->wayland_notifications->len; i++) { + wn = g_ptr_array_index (idletime->priv->wayland_notifications, i); + if (wn->notification == notification) { + g_signal_emit (idletime, signals [SIGNAL_ALARM_EXPIRED], 0, wn->id); + break; + } + } + idletime->priv->wayland_is_idle = TRUE; + if (idletime->priv->idle_timer) + g_timer_start (idletime->priv->idle_timer); } /** + * egg_idletime_wayland_notification_resumed_cb: + */ +static void +egg_idletime_wayland_notification_resumed_cb (void *data, + struct ext_idle_notification_v1 *notification) +{ + EggIdletime *idletime = EGG_IDLETIME (data); + + if (idletime->priv->wayland_is_idle) { + idletime->priv->wayland_is_idle = FALSE; + g_signal_emit (idletime, signals [SIGNAL_RESET], 0); + } +} + +static const struct ext_idle_notification_v1_listener +egg_idletime_wayland_notification_listener = { + .idled = egg_idletime_wayland_notification_idled_cb, + .resumed = egg_idletime_wayland_notification_resumed_cb, +}; + +#endif /* HAVE_WAYLAND */ + +/** * egg_idletime_class_init: **/ static void @@ -379,52 +390,317 @@ egg_idletime_class_init (EggIdletimeClass *klass) } /** + * egg_idletime_get_time: + * Return value: current idle time in milliseconds + **/ +gint64 +egg_idletime_get_time (EggIdletime *idletime) +{ + g_return_val_if_fail (EGG_IS_IDLETIME (idletime), 0); + +#ifdef HAVE_X11 + if (gdk_display_get_default () != NULL && + GDK_IS_X11_DISPLAY (gdk_display_get_default ()) && + idletime->priv->idle_counter) { + XSyncValue value; + XSyncQueryCounter (idletime->priv->dpy, idletime->priv->idle_counter, &value); + return egg_idletime_xsyncvalue_to_int64 (value); + } +#endif +#ifdef HAVE_WAYLAND + if (gdk_display_get_default () != NULL && + GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ()) && + idletime->priv->wayland_is_idle && + idletime->priv->idle_timer) { + return (gint64)(g_timer_elapsed (idletime->priv->idle_timer, NULL) * 1000.0); + } +#endif + return 0; +} + +#ifdef HAVE_WAYLAND + +/** + * egg_idletime_wayland_registry_global_cb: + */ +static void +egg_idletime_wayland_registry_global_cb (void *data, struct wl_registry *registry, + uint32_t name, const char *interface, + uint32_t version) +{ + EggIdletime *idletime = EGG_IDLETIME (data); + + if (g_strcmp0 (interface, "ext_idle_notifier_v1") == 0) { + idletime->priv->idle_notifier = wl_registry_bind (registry, name, + &ext_idle_notifier_v1_interface, MIN (version, 2u)); + g_debug ("bound ext_idle_notifier_v1 (version %u)", MIN (version, 2u)); + } else if (g_strcmp0 (interface, "wl_seat") == 0) { + if (idletime->priv->seat == NULL) { + idletime->priv->seat = wl_registry_bind (registry, name, + &wl_seat_interface, MIN (version, 1u)); + } + } +} + +static void +egg_idletime_wayland_registry_global_remove_cb (void *data, struct wl_registry *registry, + uint32_t name) +{ +} + +static const struct wl_registry_listener egg_idletime_wayland_registry_listener = { + .global = egg_idletime_wayland_registry_global_cb, + .global_remove = egg_idletime_wayland_registry_global_remove_cb, +}; + +#endif /* HAVE_WAYLAND */ + +/** * egg_idletime_init: **/ static void egg_idletime_init (EggIdletime *idletime) { - int sync_error; - int ncounters; - XSyncSystemCounter *counters; - EggIdletimeAlarm *alarm; - gint i; - idletime->priv = egg_idletime_get_instance_private (idletime); + idletime->priv->reset_set = FALSE; idletime->priv->array = g_ptr_array_new (); - idletime->priv->reset_set = FALSE; - idletime->priv->idle_counter = None; - idletime->priv->sync_event = 0; - idletime->priv->dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default()); +#ifdef HAVE_WAYLAND + idletime->priv->wayland_notifications = NULL; + idletime->priv->wayland_is_idle = FALSE; + idletime->priv->idle_timer = NULL; +#endif + +#ifdef HAVE_X11 + if (gdk_display_get_default () != NULL && + GDK_IS_X11_DISPLAY (gdk_display_get_default ())) { + int sync_error; + int ncounters; + XSyncSystemCounter *counters; + EggIdletimeAlarm *alarm; + gint i; + + idletime->priv->idle_counter = None; + idletime->priv->sync_event = 0; + idletime->priv->dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default()); + + /* get the sync event */ + if (!XSyncQueryExtension (idletime->priv->dpy, &idletime->priv->sync_event, &sync_error)) { + g_warning ("No Sync extension."); + return; + } + + /* gtk_init should do XSyncInitialize for us */ + counters = XSyncListSystemCounters (idletime->priv->dpy, &ncounters); + for (i=0; i < ncounters && !idletime->priv->idle_counter; i++) { + if (strcmp(counters[i].name, "IDLETIME") == 0) + idletime->priv->idle_counter = counters[i].counter; + } + XSyncFreeSystemCounterList (counters); + + /* arh. we don't have IDLETIME support */ + if (!idletime->priv->idle_counter) { + g_warning ("No idle counter."); + return; + } - /* get the sync event */ - if (!XSyncQueryExtension (idletime->priv->dpy, &idletime->priv->sync_event, &sync_error)) { - g_warning ("No Sync extension."); + /* catch the timer alarm */ + gdk_window_add_filter (NULL, egg_idletime_event_filter_cb, idletime); + + /* create a reset alarm */ + alarm = egg_idletime_alarm_new (idletime, 0); + g_ptr_array_add (idletime->priv->array, alarm); return; } +#endif +#ifdef HAVE_WAYLAND + if (gdk_display_get_default () != NULL && + GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ())) { + struct wl_display *display; + struct wl_registry *registry; + + idletime->priv->wayland_notifications = g_ptr_array_new_with_free_func (g_free); + idletime->priv->idle_timer = g_timer_new (); + + display = gdk_wayland_display_get_wl_display (gdk_display_get_default ()); + if (display == NULL) { + g_warning ("Cannot get Wayland display"); + return; + } - /* gtk_init should do XSyncInitialize for us */ - counters = XSyncListSystemCounters (idletime->priv->dpy, &ncounters); - for (i=0; i < ncounters && !idletime->priv->idle_counter; i++) { - if (strcmp(counters[i].name, "IDLETIME") == 0) - idletime->priv->idle_counter = counters[i].counter; - } - XSyncFreeSystemCounterList (counters); + registry = wl_display_get_registry (display); + if (registry == NULL) { + g_warning ("Cannot get Wayland registry"); + return; + } + + wl_registry_add_listener (registry, &egg_idletime_wayland_registry_listener, idletime); + wl_display_roundtrip (display); - /* arh. we don't have IDLETIME support */ - if (!idletime->priv->idle_counter) { - g_warning ("No idle counter."); + if (idletime->priv->idle_notifier == NULL) { + g_debug ("Compositor does not support ext_idle_notifier_v1"); + } + if (idletime->priv->seat == NULL) { + g_warning ("No wl_seat available"); + } return; } +#endif + g_debug ("No idle tracking available for current display"); +} + +/** + * egg_idletime_alarm_set: + */ +gboolean +egg_idletime_alarm_set (EggIdletime *idletime, guint id, guint timeout) +{ + g_return_val_if_fail (EGG_IS_IDLETIME (idletime), FALSE); + g_return_val_if_fail (id != 0, FALSE); + g_return_val_if_fail (timeout != 0, FALSE); + +#ifdef HAVE_X11 + if (gdk_display_get_default () != NULL && + GDK_IS_X11_DISPLAY (gdk_display_get_default ())) { + EggIdletimeAlarm *alarm; + + /* see if we already created an alarm with this ID */ + alarm = egg_idletime_alarm_find_id (idletime, id); + if (alarm == NULL) { + /* create a new alarm */ + alarm = egg_idletime_alarm_new (idletime, id); + + /* add to array */ + g_ptr_array_add (idletime->priv->array, alarm); + } + + /* set the timeout */ + XSyncIntToValue (&alarm->timeout, (gint)timeout); + + /* set, and start the timer */ + egg_idletime_xsync_alarm_set (idletime, alarm, EGG_IDLETIME_ALARM_TYPE_POSITIVE); + return TRUE; + } +#endif +#ifdef HAVE_WAYLAND + if (gdk_display_get_default () != NULL && + GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ())) { + EggIdletimeWaylandNotification *wn; + + if (idletime->priv->idle_notifier == NULL) { + g_warning ("EggIdletime: idle_notifier not available"); + return FALSE; + } + if (idletime->priv->seat == NULL) { + g_warning ("EggIdletime: no Wayland seat available"); + return FALSE; + } + + /* see if we already created a notification with this ID */ + wn = egg_idletime_alarm_wayland_find_id (idletime, id); + if (wn != NULL) { + if (wn->notification) + ext_idle_notification_v1_destroy (wn->notification); + wn->timeout = timeout; + } else { + wn = g_new0 (EggIdletimeWaylandNotification, 1); + wn->id = id; + wn->timeout = timeout; + g_ptr_array_add (idletime->priv->wayland_notifications, wn); + } + + wn->notification = ext_idle_notifier_v1_get_input_idle_notification ( + idletime->priv->idle_notifier, timeout, idletime->priv->seat); + ext_idle_notification_v1_add_listener (wn->notification, + &egg_idletime_wayland_notification_listener, idletime); + + return TRUE; + } +#endif + return FALSE; +} + +/** + * egg_idletime_alarm_remove: + */ +gboolean +egg_idletime_alarm_remove (EggIdletime *idletime, guint id) +{ + g_return_val_if_fail (EGG_IS_IDLETIME (idletime), FALSE); - /* catch the timer alarm */ - gdk_window_add_filter (NULL, egg_idletime_event_filter_cb, idletime); +#ifdef HAVE_X11 + if (gdk_display_get_default () != NULL && + GDK_IS_X11_DISPLAY (gdk_display_get_default ())) { + EggIdletimeAlarm *alarm; - /* create a reset alarm */ - alarm = egg_idletime_alarm_new (idletime, 0); - g_ptr_array_add (idletime->priv->array, alarm); + alarm = egg_idletime_alarm_find_id (idletime, id); + if (alarm == NULL) + return FALSE; + return egg_idletime_alarm_free (idletime, alarm); + } +#endif +#ifdef HAVE_WAYLAND + if (gdk_display_get_default () != NULL && + GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ())) { + EggIdletimeWaylandNotification *wn; + + wn = egg_idletime_alarm_wayland_find_id (idletime, id); + if (wn == NULL) + return FALSE; + + if (wn->notification) + ext_idle_notification_v1_destroy (wn->notification); + g_ptr_array_remove (idletime->priv->wayland_notifications, wn); + g_free (wn); + return TRUE; + } +#endif + return FALSE; +} + +/** + * egg_idletime_alarm_reset_all: + */ +void +egg_idletime_alarm_reset_all (EggIdletime *idletime) +{ + g_return_if_fail (EGG_IS_IDLETIME (idletime)); + +#ifdef HAVE_X11 + if (gdk_display_get_default () != NULL && + GDK_IS_X11_DISPLAY (gdk_display_get_default ())) { + guint i; + EggIdletimeAlarm *alarm; + + if (!idletime->priv->reset_set) + return; + + /* reset all the alarms (except the reset alarm) to their timeouts */ + for (i=1; i<idletime->priv->array->len; i++) { + alarm = g_ptr_array_index (idletime->priv->array, i); + egg_idletime_xsync_alarm_set (idletime, alarm, EGG_IDLETIME_ALARM_TYPE_POSITIVE); + } + + /* set the reset alarm to be disabled */ + alarm = g_ptr_array_index (idletime->priv->array, 0); + egg_idletime_xsync_alarm_set (idletime, alarm, EGG_IDLETIME_ALARM_TYPE_DISABLED); + + /* emit signal so say we've reset all timers */ + g_signal_emit (idletime, signals [SIGNAL_RESET], 0); + + /* we need to be reset again on the next event */ + idletime->priv->reset_set = FALSE; + return; + } +#endif +#ifdef HAVE_WAYLAND + if (gdk_display_get_default () != NULL && + GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ())) { + g_signal_emit (idletime, signals [SIGNAL_RESET], 0); + return; + } +#endif } /** @@ -435,7 +711,6 @@ egg_idletime_finalize (GObject *object) { guint i; EggIdletime *idletime; - EggIdletimeAlarm *alarm; g_return_if_fail (object != NULL); g_return_if_fail (EGG_IS_IDLETIME (object)); @@ -443,11 +718,37 @@ egg_idletime_finalize (GObject *object) idletime = EGG_IDLETIME (object); idletime->priv = egg_idletime_get_instance_private (idletime); - /* free all counters, including reset counter */ - for (i=0; i<idletime->priv->array->len; i++) { - alarm = g_ptr_array_index (idletime->priv->array, i); - egg_idletime_alarm_free (idletime, alarm); +#ifdef HAVE_X11 + if (gdk_display_get_default () != NULL && + GDK_IS_X11_DISPLAY (gdk_display_get_default ())) { + EggIdletimeAlarm *alarm; + + /* free all counters, including reset counter */ + for (i=0; i<idletime->priv->array->len; i++) { + alarm = g_ptr_array_index (idletime->priv->array, i); + if (alarm->xalarm) + XSyncDestroyAlarm (idletime->priv->dpy, alarm->xalarm); + g_object_unref (alarm->idletime); + g_free (alarm); + } + } +#endif +#ifdef HAVE_WAYLAND + if (idletime->priv->wayland_notifications != NULL) { + EggIdletimeWaylandNotification *wn; + + for (i = 0; i < idletime->priv->wayland_notifications->len; i++) { + wn = g_ptr_array_index (idletime->priv->wayland_notifications, i); + if (wn->notification) + ext_idle_notification_v1_destroy (wn->notification); + } + g_ptr_array_free (idletime->priv->wayland_notifications, TRUE); } + if (idletime->priv->idle_notifier) + ext_idle_notifier_v1_destroy (idletime->priv->idle_notifier); + if (idletime->priv->idle_timer) + g_timer_destroy (idletime->priv->idle_timer); +#endif g_ptr_array_free (idletime->priv->array, TRUE); G_OBJECT_CLASS (egg_idletime_parent_class)->finalize (object); @@ -685,4 +986,3 @@ egg_idletime_test (gpointer data) } #endif - diff --git a/src/gpm-brightness.c b/src/gpm-brightness.c index a3a0589..7e0757c 100644 --- a/src/gpm-brightness.c +++ b/src/gpm-brightness.c @@ -29,10 +29,17 @@ #include <time.h> #include <errno.h> +#ifdef HAVE_X11 #include <X11/Xatom.h> #include <X11/Xlib.h> #include <X11/extensions/Xrandr.h> #include <gdk/gdkx.h> +#endif /* HAVE_X11 */ + +#ifdef HAVE_WAYLAND +#include <gdk/gdkwayland.h> +#endif /* HAVE_WAYLAND */ + #include <gtk/gtk.h> #include <string.h> #include <sys/time.h> @@ -55,16 +62,18 @@ struct GpmBrightnessPrivate gboolean cache_trusted; guint cache_percentage; guint last_set_hw; + gboolean has_extension; + gboolean hw_changed; + gint extension_levels; + gint extension_current; +#ifdef HAVE_X11 Atom backlight; Display *dpy; GdkWindow *root_window; guint shared_value; - gboolean has_extension; - gboolean hw_changed; /* A cache of XRRScreenResources is used as XRRGetScreenResources is expensive */ GPtrArray *resources; - gint extension_levels; - gint extension_current; +#endif }; enum { @@ -72,12 +81,14 @@ enum { LAST_SIGNAL }; +#ifdef HAVE_X11 typedef enum { ACTION_BACKLIGHT_GET, ACTION_BACKLIGHT_SET, ACTION_BACKLIGHT_INC, ACTION_BACKLIGHT_DEC } GpmXRandROp; +#endif G_DEFINE_TYPE_WITH_PRIVATE (GpmBrightness, gpm_brightness, G_TYPE_OBJECT) @@ -186,6 +197,8 @@ gpm_brightness_get_step (guint levels) return 1; } +#ifdef HAVE_X11 + /** * gpm_brightness_output_get_internal: **/ @@ -445,7 +458,6 @@ gpm_brightness_output_set (GpmBrightness *brightness, RROutput output) /* step the correct way */ if ((gint) cur < shared_value_abs) { - /* some adaptors have a large number of steps */ step = gpm_brightness_get_step (shared_value_abs - cur); g_debug ("using step of %u", step); @@ -459,7 +471,6 @@ gpm_brightness_output_set (GpmBrightness *brightness, RROutput output) g_usleep (1000 * GPM_BRIGHTNESS_DIM_INTERVAL); } } else { - /* some adaptors have a large number of steps */ step = gpm_brightness_get_step (cur - shared_value_abs); g_debug ("using step of %u", step); @@ -543,6 +554,79 @@ gpm_brightness_foreach_screen (GpmBrightness *brightness, GpmXRandROp op) return success_any; } +static void gpm_brightness_may_have_changed (GpmBrightness *brightness); + +/** + * gpm_brightness_filter_xevents: + **/ +static GdkFilterReturn +gpm_brightness_filter_xevents (GdkXEvent *xevent, GdkEvent *event, gpointer data) +{ + GpmBrightness *brightness = GPM_BRIGHTNESS (data); + if (event->type == GDK_NOTHING) + return GDK_FILTER_CONTINUE; + gpm_brightness_may_have_changed (brightness); + return GDK_FILTER_CONTINUE; +} + +static void gpm_brightness_update_cache (GpmBrightness *brightness); + +/** + * gpm_brightness_monitors_changed: + **/ +static void +gpm_brightness_monitors_changed (GdkScreen *screen, GpmBrightness *brightness) +{ + g_return_if_fail (GPM_IS_BRIGHTNESS (brightness)); + gpm_brightness_update_cache (brightness); +} + +/** + * gpm_brightness_update_cache: + **/ +static void +gpm_brightness_update_cache (GpmBrightness *brightness) +{ + guint length; + Window root; + GdkScreen *gscreen; + GdkDisplay *display; + XRRScreenResources *resource; + + g_return_if_fail (GPM_IS_BRIGHTNESS (brightness)); + + /* invalidate and remove all the previous entries */ + length = brightness->priv->resources->len; + if (length > 0) + g_ptr_array_set_size (brightness->priv->resources, 0); + + display = gdk_display_get_default (); + gscreen = gdk_display_get_default_screen (display); + + /* if we have not setup the changed on the monitor, set it here */ + if (g_object_get_data (G_OBJECT (gscreen), "gpk-set-monitors-changed") == NULL) { + g_debug ("watching ::monitors_changed on %p", gscreen); + g_object_set_data (G_OBJECT (gscreen), "gpk-set-monitors-changed", (gpointer) "true"); + g_signal_connect (G_OBJECT (gscreen), "monitors_changed", + G_CALLBACK (gpm_brightness_monitors_changed), brightness); + } + + root = RootWindow (brightness->priv->dpy, 0); + + gdk_x11_display_error_trap_push (display); + resource = XRRGetScreenResourcesCurrent (brightness->priv->dpy, root); + if (gdk_x11_display_error_trap_pop (display) || resource == NULL) { + g_warning ("failed to XRRGetScreenResourcesCurrent"); + } + + if (resource != NULL) { + g_debug ("adding resource %p", resource); + g_ptr_array_add (brightness->priv->resources, resource); + } +} + +#endif /* HAVE_X11 */ + /** * gpm_brightness_trust_cache: * @brightness: This brightness class instance @@ -591,11 +675,16 @@ gpm_brightness_set (GpmBrightness *brightness, guint percentage, gboolean *hw_ch } /* set the value we want */ +#ifdef HAVE_X11 brightness->priv->shared_value = percentage; +#endif /* reset to not-changed */ brightness->priv->hw_changed = FALSE; + +#ifdef HAVE_X11 ret = gpm_brightness_foreach_screen (brightness, ACTION_BACKLIGHT_SET); +#endif /* legacy fallback */ if (!ret) { @@ -642,8 +731,10 @@ gpm_brightness_get (GpmBrightness *brightness, guint *percentage) } /* get the brightness from hardware -- slow */ +#ifdef HAVE_X11 ret = gpm_brightness_foreach_screen (brightness, ACTION_BACKLIGHT_GET); percentage_local = brightness->priv->shared_value; +#endif /* legacy fallback */ if (!ret) { @@ -689,7 +780,10 @@ gpm_brightness_up (GpmBrightness *brightness, gboolean *hw_changed) /* reset to not-changed */ brightness->priv->hw_changed = FALSE; + +#ifdef HAVE_X11 ret = gpm_brightness_foreach_screen (brightness, ACTION_BACKLIGHT_INC); +#endif /* did the hardware have to be modified? */ if (ret && hw_changed != NULL) @@ -740,7 +834,10 @@ gpm_brightness_down (GpmBrightness *brightness, gboolean *hw_changed) /* reset to not-changed */ brightness->priv->hw_changed = FALSE; + +#ifdef HAVE_X11 ret = gpm_brightness_foreach_screen (brightness, ACTION_BACKLIGHT_DEC); +#endif /* did the hardware have to be modified? */ if (ret && hw_changed != NULL) @@ -791,75 +888,6 @@ gpm_brightness_may_have_changed (GpmBrightness *brightness) } /** - * gpm_brightness_filter_xevents: - **/ -static GdkFilterReturn -gpm_brightness_filter_xevents (GdkXEvent *xevent, GdkEvent *event, gpointer data) -{ - GpmBrightness *brightness = GPM_BRIGHTNESS (data); - if (event->type == GDK_NOTHING) - return GDK_FILTER_CONTINUE; - gpm_brightness_may_have_changed (brightness); - return GDK_FILTER_CONTINUE; -} - -static void gpm_brightness_update_cache (GpmBrightness *brightness); - -/** - * gpm_brightness_monitors_changed: - **/ -static void -gpm_brightness_monitors_changed (GdkScreen *screen, GpmBrightness *brightness) -{ - g_return_if_fail (GPM_IS_BRIGHTNESS (brightness)); - gpm_brightness_update_cache (brightness); -} - -/** - * gpm_brightness_update_cache: - **/ -static void -gpm_brightness_update_cache (GpmBrightness *brightness) -{ - guint length; - Window root; - GdkScreen *gscreen; - GdkDisplay *display; - XRRScreenResources *resource; - - g_return_if_fail (GPM_IS_BRIGHTNESS (brightness)); - - /* invalidate and remove all the previous entries */ - length = brightness->priv->resources->len; - if (length > 0) - g_ptr_array_set_size (brightness->priv->resources, 0); - - display = gdk_display_get_default (); - gscreen = gdk_display_get_default_screen (display); - - /* if we have not setup the changed on the monitor, set it here */ - if (g_object_get_data (G_OBJECT (gscreen), "gpk-set-monitors-changed") == NULL) { - g_debug ("watching ::monitors_changed on %p", gscreen); - g_object_set_data (G_OBJECT (gscreen), "gpk-set-monitors-changed", (gpointer) "true"); - g_signal_connect (G_OBJECT (gscreen), "monitors_changed", - G_CALLBACK (gpm_brightness_monitors_changed), brightness); - } - - root = RootWindow (brightness->priv->dpy, 0); - - gdk_x11_display_error_trap_push (display); - resource = XRRGetScreenResourcesCurrent (brightness->priv->dpy, root); - if (gdk_x11_display_error_trap_pop (display) || resource == NULL) { - g_warning ("failed to XRRGetScreenResourcesCurrent"); - } - - if (resource != NULL) { - g_debug ("adding resource %p", resource); - g_ptr_array_add (brightness->priv->resources, resource); - } -} - -/** * gpm_brightness_has_hw: **/ gboolean @@ -868,8 +896,10 @@ gpm_brightness_has_hw (GpmBrightness *brightness) g_return_val_if_fail (GPM_IS_BRIGHTNESS (brightness), FALSE); /* use XRandR first */ +#ifdef HAVE_X11 if (brightness->priv->has_extension) return TRUE; +#endif /* fallback to legacy access */ if (brightness->priv->extension_levels < 0) @@ -889,9 +919,11 @@ gpm_brightness_finalize (GObject *object) g_return_if_fail (object != NULL); g_return_if_fail (GPM_IS_BRIGHTNESS (object)); brightness = GPM_BRIGHTNESS (object); +#ifdef HAVE_X11 g_ptr_array_unref (brightness->priv->resources); gdk_window_remove_filter (brightness->priv->root_window, gpm_brightness_filter_xevents, brightness); +#endif G_OBJECT_CLASS (gpm_brightness_parent_class)->finalize (object); } @@ -919,11 +951,6 @@ gpm_brightness_class_init (GpmBrightnessClass *klass) static void gpm_brightness_init (GpmBrightness *brightness) { - GdkScreen *screen; - GdkDisplay *display; - int event_base; - int ignore; - brightness->priv = gpm_brightness_get_instance_private (brightness); brightness->priv->cache_trusted = FALSE; @@ -931,37 +958,50 @@ gpm_brightness_init (GpmBrightness *brightness) brightness->priv->cache_percentage = 0; brightness->priv->hw_changed = FALSE; brightness->priv->extension_levels = -1; - brightness->priv->resources = g_ptr_array_new_with_free_func ((GDestroyNotify) XRRFreeScreenResources); - /* can we do this */ - brightness->priv->has_extension = gpm_brightness_setup_display (brightness); - if (brightness->priv->has_extension == FALSE) - g_debug ("no XRANDR extension"); +#ifdef HAVE_X11 + if (gdk_display_get_default () != NULL && + GDK_IS_X11_DISPLAY (gdk_display_get_default ())) { + GdkScreen *screen; + GdkDisplay *display; + int event_base; + int ignore; - screen = gdk_screen_get_default (); - brightness->priv->root_window = gdk_screen_get_root_window (screen); - display = gdk_display_get_default (); + brightness->priv->resources = g_ptr_array_new_with_free_func ((GDestroyNotify) XRRFreeScreenResources); - /* as we a filtering by a window, we have to add an event type */ - if (!XRRQueryExtension (GDK_DISPLAY_XDISPLAY (gdk_display_get_default()), &event_base, &ignore)) { - g_warning ("can't get event_base for XRR"); - } - gdk_x11_register_standard_event_type (display, event_base, RRNotify + 1); - gdk_window_add_filter (brightness->priv->root_window, - gpm_brightness_filter_xevents, brightness); + /* can we do this */ + brightness->priv->has_extension = gpm_brightness_setup_display (brightness); + if (brightness->priv->has_extension == FALSE) + g_debug ("no XRANDR extension"); - /* don't abort on error */ - gdk_x11_display_error_trap_push (display); - XRRSelectInput (GDK_DISPLAY_XDISPLAY (gdk_display_get_default()), - GDK_WINDOW_XID (brightness->priv->root_window), - RRScreenChangeNotifyMask | - RROutputPropertyNotifyMask); /* <--- the only one we need, but see rh:345551 */ - gdk_display_flush (display); - if (gdk_x11_display_error_trap_pop (display)) - g_warning ("failed to select XRRSelectInput"); + screen = gdk_screen_get_default (); + brightness->priv->root_window = gdk_screen_get_root_window (screen); + display = gdk_display_get_default (); - /* create cache of XRRScreenResources as XRRGetScreenResources() is slow */ - gpm_brightness_update_cache (brightness); + /* as we a filtering by a window, we have to add an event type */ + if (!XRRQueryExtension (GDK_DISPLAY_XDISPLAY (gdk_display_get_default()), &event_base, &ignore)) { + g_warning ("can't get event_base for XRR"); + } + gdk_x11_register_standard_event_type (display, event_base, RRNotify + 1); + gdk_window_add_filter (brightness->priv->root_window, + gpm_brightness_filter_xevents, brightness); + + /* don't abort on error */ + gdk_x11_display_error_trap_push (display); + XRRSelectInput (GDK_DISPLAY_XDISPLAY (gdk_display_get_default()), + GDK_WINDOW_XID (brightness->priv->root_window), + RRScreenChangeNotifyMask | + RROutputPropertyNotifyMask); /* <--- the only one we need, but see rh:345551 */ + gdk_display_flush (display); + if (gdk_x11_display_error_trap_pop (display)) + g_warning ("failed to select XRRSelectInput"); + + /* create cache of XRRScreenResources as XRRGetScreenResources() is slow */ + gpm_brightness_update_cache (brightness); + return; + } +#endif + g_debug ("No XRandR brightness backend; using sysfs fallback only"); } /** @@ -980,4 +1020,3 @@ gpm_brightness_new (void) } return GPM_BRIGHTNESS (gpm_brightness_object); } - diff --git a/src/gpm-button.c b/src/gpm-button.c index 5bfe19d..9fa5ab0 100644 --- a/src/gpm-button.c +++ b/src/gpm-button.c @@ -26,10 +26,13 @@ #include <glib.h> #include <glib/gi18n.h> +#ifdef HAVE_X11 #include <X11/X.h> #include <gdk/gdkx.h> -#include <gtk/gtk.h> #include <X11/XF86keysym.h> +#endif /* HAVE_X11 */ + +#include <gtk/gtk.h> #include <libupower-glib/upower.h> #include "gpm-common.h" @@ -39,9 +42,11 @@ static void gpm_button_finalize (GObject *object); struct GpmButtonPrivate { +#ifdef HAVE_X11 GdkScreen *screen; GdkWindow *window; GHashTable *keysym_to_name_hash; +#endif gchar *last_button; GTimer *timer; gboolean lid_is_closed; @@ -86,6 +91,8 @@ gpm_button_emit_type (GpmButton *button, const gchar *type) return TRUE; } +#ifdef HAVE_X11 + /** * gpm_button_filter_x_events: **/ @@ -227,6 +234,8 @@ gpm_button_xevent_key (GpmButton *button, guint keysym, const gchar *key_name) return TRUE; } +#endif /* HAVE_X11 */ + /** * gpm_button_class_init: * @button: This class instance @@ -351,10 +360,6 @@ gpm_button_init (GpmButton *button) { button->priv = gpm_button_get_instance_private (button); - button->priv->screen = gdk_screen_get_default (); - button->priv->window = gdk_screen_get_root_window (button->priv->screen); - - button->priv->keysym_to_name_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); button->priv->last_button = NULL; button->priv->timer = g_timer_new (); @@ -362,27 +367,33 @@ gpm_button_init (GpmButton *button) button->priv->lid_is_closed = up_client_get_lid_is_closed (button->priv->client); g_signal_connect (button->priv->client, "notify", G_CALLBACK (gpm_button_client_changed_cb), button); - /* register the brightness keys */ - gpm_button_xevent_key (button, XF86XK_PowerOff, GPM_BUTTON_POWER); - - /* The kernel messes up suspend/hibernate in some places. One of - * them is the key names. Unfortunately, they refuse to see the - * errors of their way in the name of 'compatibility'. Meh - */ - gpm_button_xevent_key (button, XF86XK_Suspend, GPM_BUTTON_HIBERNATE); - gpm_button_xevent_key (button, XF86XK_Sleep, GPM_BUTTON_SUSPEND); /* should be configurable */ - gpm_button_xevent_key (button, XF86XK_Hibernate, GPM_BUTTON_HIBERNATE); - gpm_button_xevent_key (button, XF86XK_MonBrightnessUp, GPM_BUTTON_BRIGHT_UP); - gpm_button_xevent_key (button, XF86XK_MonBrightnessDown, GPM_BUTTON_BRIGHT_DOWN); - gpm_button_xevent_key (button, XF86XK_ScreenSaver, GPM_BUTTON_LOCK); - gpm_button_xevent_key (button, XF86XK_Battery, GPM_BUTTON_BATTERY); - gpm_button_xevent_key (button, XF86XK_KbdBrightnessUp, GPM_BUTTON_KBD_BRIGHT_UP); - gpm_button_xevent_key (button, XF86XK_KbdBrightnessDown, GPM_BUTTON_KBD_BRIGHT_DOWN); - gpm_button_xevent_key (button, XF86XK_KbdLightOnOff, GPM_BUTTON_KBD_BRIGHT_TOGGLE); - - /* use global filter */ - gdk_window_add_filter (button->priv->window, - gpm_button_filter_x_events, (gpointer) button); + +#ifdef HAVE_X11 + if (gdk_display_get_default () != NULL && + GDK_IS_X11_DISPLAY (gdk_display_get_default ())) { + button->priv->screen = gdk_screen_get_default (); + button->priv->window = gdk_screen_get_root_window (button->priv->screen); + button->priv->keysym_to_name_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + + gpm_button_xevent_key (button, XF86XK_PowerOff, GPM_BUTTON_POWER); + + gpm_button_xevent_key (button, XF86XK_Suspend, GPM_BUTTON_HIBERNATE); + gpm_button_xevent_key (button, XF86XK_Sleep, GPM_BUTTON_SUSPEND); + gpm_button_xevent_key (button, XF86XK_Hibernate, GPM_BUTTON_HIBERNATE); + gpm_button_xevent_key (button, XF86XK_MonBrightnessUp, GPM_BUTTON_BRIGHT_UP); + gpm_button_xevent_key (button, XF86XK_MonBrightnessDown, GPM_BUTTON_BRIGHT_DOWN); + gpm_button_xevent_key (button, XF86XK_ScreenSaver, GPM_BUTTON_LOCK); + gpm_button_xevent_key (button, XF86XK_Battery, GPM_BUTTON_BATTERY); + gpm_button_xevent_key (button, XF86XK_KbdBrightnessUp, GPM_BUTTON_KBD_BRIGHT_UP); + gpm_button_xevent_key (button, XF86XK_KbdBrightnessDown, GPM_BUTTON_KBD_BRIGHT_DOWN); + gpm_button_xevent_key (button, XF86XK_KbdLightOnOff, GPM_BUTTON_KBD_BRIGHT_TOGGLE); + + gdk_window_add_filter (button->priv->window, + gpm_button_filter_x_events, (gpointer) button); + return; + } +#endif + g_debug ("No X11 backend for button key grabbing; compositor handles keys"); } /** @@ -403,7 +414,10 @@ gpm_button_finalize (GObject *object) g_free (button->priv->last_button); g_timer_destroy (button->priv->timer); - g_hash_table_unref (button->priv->keysym_to_name_hash); +#ifdef HAVE_X11 + if (button->priv->keysym_to_name_hash) + g_hash_table_unref (button->priv->keysym_to_name_hash); +#endif G_OBJECT_CLASS (gpm_button_parent_class)->finalize (object); } diff --git a/src/gpm-dpms.c b/src/gpm-dpms.c index 5e5af30..2d0e489 100644 --- a/src/gpm-dpms.c +++ b/src/gpm-dpms.c @@ -36,10 +36,18 @@ #endif /* HAVE_UNISTD_H */ #include <gdk/gdk.h> -#include <gdk/gdkx.h> +#ifdef HAVE_X11 +#include <gdk/gdkx.h> #include <X11/Xproto.h> #include <X11/extensions/dpms.h> +#endif /* HAVE_X11 */ + +#ifdef HAVE_WAYLAND +#include <gdk/gdkwayland.h> +#include <wayland-client.h> +#include "wlr-output-power-management-unstable-v1-client.h" +#endif /* HAVE_WAYLAND */ #include "gpm-dpms.h" @@ -48,12 +56,26 @@ static void gpm_dpms_finalize (GObject *object); /* until we get a nice event-emitting DPMS extension, we have to poll... */ #define GPM_DPMS_POLL_TIME 10 +#ifdef HAVE_WAYLAND +typedef struct { + struct zwlr_output_power_v1 *power; + uint32_t name; + GpmDpmsMode mode; +} GpmDpmsWaylandOutput; +#endif + struct GpmDpmsPrivate { gboolean dpms_capable; GpmDpmsMode mode; guint timer_id; +#ifdef HAVE_X11 Display *display; +#endif +#ifdef HAVE_WAYLAND + struct zwlr_output_power_manager_v1 *power_manager; + GPtrArray *wayland_outputs; +#endif }; enum { @@ -78,6 +100,8 @@ gpm_dpms_error_quark (void) return quark; } +#ifdef HAVE_X11 + /** * gpm_dpms_x11_get_mode: **/ @@ -188,13 +212,176 @@ gpm_dpms_x11_set_mode (GpmDpms *dpms, GpmDpmsMode mode, GError **error) } /** + * gpm_dpms_clear_timeouts: + **/ +static gboolean +gpm_dpms_clear_timeouts (GpmDpms *dpms) +{ + gboolean ret = FALSE; + + /* never going to work */ + if (!dpms->priv->dpms_capable) { + g_debug ("not DPMS capable"); + goto out; + } + + g_debug ("set timeouts to zero"); + ret = DPMSSetTimeouts (dpms->priv->display, 0, 0, 0); + +out: + return ret; +} + +#endif /* HAVE_X11 */ + +#ifdef HAVE_WAYLAND + +static void +gpm_dpms_wayland_output_mode_cb (void *data, + struct zwlr_output_power_v1 *power, + uint32_t mode) +{ + GpmDpmsWaylandOutput *output = data; + GpmDpmsMode new_mode; + + switch (mode) { + case ZWLR_OUTPUT_POWER_V1_MODE_OFF: + new_mode = GPM_DPMS_MODE_OFF; + break; + case ZWLR_OUTPUT_POWER_V1_MODE_ON: + default: + new_mode = GPM_DPMS_MODE_ON; + break; + } + + if (new_mode != output->mode) { + output->mode = new_mode; + } +} + +static void +gpm_dpms_wayland_output_failed_cb (void *data, + struct zwlr_output_power_v1 *power) +{ + GpmDpmsWaylandOutput *output = data; + g_debug ("wlr-output-power failed for output %u", output->name); +} + +static const struct zwlr_output_power_v1_listener +gpm_dpms_wayland_power_listener = { + .mode = gpm_dpms_wayland_output_mode_cb, + .failed = gpm_dpms_wayland_output_failed_cb, +}; + +static GpmDpmsWaylandOutput * +gpm_dpms_wayland_output_find (GpmDpms *dpms, uint32_t name) +{ + guint i; + for (i = 0; i < dpms->priv->wayland_outputs->len; i++) { + GpmDpmsWaylandOutput *o = g_ptr_array_index (dpms->priv->wayland_outputs, i); + if (o->name == name) + return o; + } + return NULL; +} + +static void +gpm_dpms_wayland_registry_global_cb (void *data, struct wl_registry *registry, + uint32_t name, const char *interface, + uint32_t version) +{ + GpmDpms *dpms = data; + + if (g_strcmp0 (interface, "zwlr_output_power_manager_v1") == 0) { + dpms->priv->power_manager = wl_registry_bind (registry, name, + &zwlr_output_power_manager_v1_interface, 1); + g_debug ("bound zwlr_output_power_manager_v1"); + } else if (g_strcmp0 (interface, "wl_output") == 0) { + struct wl_output *output; + GpmDpmsWaylandOutput *wo; + + wo = gpm_dpms_wayland_output_find (dpms, name); + if (wo != NULL) + return; + + output = wl_registry_bind (registry, name, + &wl_output_interface, 1); + if (dpms->priv->power_manager == NULL) + return; + + wo = g_new0 (GpmDpmsWaylandOutput, 1); + wo->name = name; + wo->mode = GPM_DPMS_MODE_ON; + wo->power = zwlr_output_power_manager_v1_get_output_power ( + dpms->priv->power_manager, output); + zwlr_output_power_v1_add_listener (wo->power, + &gpm_dpms_wayland_power_listener, wo); + g_ptr_array_add (dpms->priv->wayland_outputs, wo); + g_debug ("added zwlr_output_power_v1 for output %u", name); + } +} + +static void +gpm_dpms_wayland_registry_global_remove_cb (void *data, + struct wl_registry *registry, + uint32_t name) +{ + GpmDpms *dpms = data; + GpmDpmsWaylandOutput *wo = gpm_dpms_wayland_output_find (dpms, name); + if (wo == NULL) + return; + if (wo->power) + zwlr_output_power_v1_destroy (wo->power); + g_ptr_array_remove (dpms->priv->wayland_outputs, wo); + g_free (wo); + g_debug ("removed zwlr_output_power_v1 for output %u", name); +} + +static const struct wl_registry_listener gpm_dpms_wayland_registry_listener = { + .global = gpm_dpms_wayland_registry_global_cb, + .global_remove = gpm_dpms_wayland_registry_global_remove_cb, +}; + +static gboolean +gpm_dpms_wayland_set_mode (GpmDpms *dpms, GpmDpmsMode mode, GError **error) +{ + guint i; + uint32_t wlr_mode; + + if (dpms->priv->wayland_outputs->len == 0) { + g_set_error (error, GPM_DPMS_ERROR, GPM_DPMS_ERROR_GENERAL, + "No Wayland outputs available"); + return FALSE; + } + + switch (mode) { + case GPM_DPMS_MODE_OFF: + wlr_mode = ZWLR_OUTPUT_POWER_V1_MODE_OFF; + break; + case GPM_DPMS_MODE_ON: + case GPM_DPMS_MODE_STANDBY: + case GPM_DPMS_MODE_SUSPEND: + default: + wlr_mode = ZWLR_OUTPUT_POWER_V1_MODE_ON; + break; + } + + for (i = 0; i < dpms->priv->wayland_outputs->len; i++) { + GpmDpmsWaylandOutput *wo = g_ptr_array_index (dpms->priv->wayland_outputs, i); + zwlr_output_power_v1_set_mode (wo->power, wlr_mode); + } + + return TRUE; +} + +#endif /* HAVE_WAYLAND */ + +/** * gpm_dpms_set_mode: **/ gboolean gpm_dpms_set_mode (GpmDpms *dpms, GpmDpmsMode mode, GError **error) { - gboolean ret; - g_return_val_if_fail (GPM_IS_DPMS (dpms), FALSE); if (mode == GPM_DPMS_MODE_UNKNOWN) { @@ -204,8 +391,21 @@ gpm_dpms_set_mode (GpmDpms *dpms, GpmDpmsMode mode, GError **error) return FALSE; } - ret = gpm_dpms_x11_set_mode (dpms, mode, error); - return ret; +#ifdef HAVE_X11 + if (gdk_display_get_default () != NULL && + GDK_IS_X11_DISPLAY (gdk_display_get_default ())) { + return gpm_dpms_x11_set_mode (dpms, mode, error); + } +#endif +#ifdef HAVE_WAYLAND + if (gdk_display_get_default () != NULL && + GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ())) { + return gpm_dpms_wayland_set_mode (dpms, mode, error); + } +#endif + g_set_error (error, GPM_DPMS_ERROR, GPM_DPMS_ERROR_GENERAL, + "DPMS not supported on this display"); + return FALSE; } /** @@ -214,11 +414,38 @@ gpm_dpms_set_mode (GpmDpms *dpms, GpmDpmsMode mode, GError **error) gboolean gpm_dpms_get_mode (GpmDpms *dpms, GpmDpmsMode *mode, GError **error) { - gboolean ret; + g_return_val_if_fail (GPM_IS_DPMS (dpms), FALSE); + +#ifdef HAVE_X11 + if (gdk_display_get_default () != NULL && + GDK_IS_X11_DISPLAY (gdk_display_get_default ())) { + return gpm_dpms_x11_get_mode (dpms, mode, error); + } +#endif +#ifdef HAVE_WAYLAND + if (gdk_display_get_default () != NULL && + GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ())) { + GpmDpmsMode result = GPM_DPMS_MODE_ON; + guint i; + gboolean all_off = TRUE; + + for (i = 0; i < dpms->priv->wayland_outputs->len; i++) { + GpmDpmsWaylandOutput *wo = g_ptr_array_index (dpms->priv->wayland_outputs, i); + if (wo->mode != GPM_DPMS_MODE_OFF) { + all_off = FALSE; + break; + } + } + if (all_off && dpms->priv->wayland_outputs->len > 0) + result = GPM_DPMS_MODE_OFF; + if (mode) + *mode = result; + return TRUE; + } +#endif if (mode) - *mode = GPM_DPMS_MODE_UNKNOWN; - ret = gpm_dpms_x11_get_mode (dpms, mode, error); - return ret; + *mode = GPM_DPMS_MODE_ON; + return TRUE; } /** @@ -227,47 +454,30 @@ gpm_dpms_get_mode (GpmDpms *dpms, GpmDpmsMode *mode, GError **error) static gboolean gpm_dpms_poll_mode_cb (GpmDpms *dpms) { - gboolean ret; - GpmDpmsMode mode; - GError *error = NULL; +#ifdef HAVE_X11 + if (gdk_display_get_default () != NULL && + GDK_IS_X11_DISPLAY (gdk_display_get_default ())) { + gboolean ret; + GpmDpmsMode mode; + GError *error = NULL; + + ret = gpm_dpms_x11_get_mode (dpms, &mode, &error); + if (!ret) { + g_clear_error (&error); + return TRUE; + } - /* Try again */ - ret = gpm_dpms_x11_get_mode (dpms, &mode, &error); - if (!ret) { - g_clear_error (&error); + if (mode != dpms->priv->mode) { + dpms->priv->mode = mode; + g_signal_emit (dpms, signals [MODE_CHANGED], 0, mode); + } return TRUE; } - - if (mode != dpms->priv->mode) { - dpms->priv->mode = mode; - g_signal_emit (dpms, signals [MODE_CHANGED], 0, mode); - } - +#endif return TRUE; } /** - * gpm_dpms_clear_timeouts: - **/ -static gboolean -gpm_dpms_clear_timeouts (GpmDpms *dpms) -{ - gboolean ret = FALSE; - - /* never going to work */ - if (!dpms->priv->dpms_capable) { - g_debug ("not DPMS capable"); - goto out; - } - - g_debug ("set timeouts to zero"); - ret = DPMSSetTimeouts (dpms->priv->display, 0, 0, 0); - -out: - return ret; -} - -/** * gpm_dpms_class_init: **/ static void @@ -293,14 +503,59 @@ gpm_dpms_init (GpmDpms *dpms) { dpms->priv = gpm_dpms_get_instance_private (dpms); - /* DPMSCapable() can never change for a given display */ - dpms->priv->display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default()); - dpms->priv->dpms_capable = DPMSCapable (dpms->priv->display); - dpms->priv->timer_id = g_timeout_add_seconds (GPM_DPMS_POLL_TIME, (GSourceFunc)gpm_dpms_poll_mode_cb, dpms); - g_source_set_name_by_id (dpms->priv->timer_id, "[GpmDpms] poll"); + dpms->priv->dpms_capable = FALSE; + dpms->priv->mode = GPM_DPMS_MODE_UNKNOWN; + dpms->priv->timer_id = 0; + +#ifdef HAVE_X11 + if (gdk_display_get_default () != NULL && + GDK_IS_X11_DISPLAY (gdk_display_get_default ())) { + /* DPMSCapable() can never change for a given display */ + dpms->priv->display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default()); + dpms->priv->dpms_capable = DPMSCapable (dpms->priv->display); + dpms->priv->timer_id = g_timeout_add_seconds (GPM_DPMS_POLL_TIME, (GSourceFunc)gpm_dpms_poll_mode_cb, dpms); + g_source_set_name_by_id (dpms->priv->timer_id, "[GpmDpms] poll"); + + /* ensure we clear the default timeouts (Standby: 1200s, Suspend: 1800s, Off: 2400s) */ + gpm_dpms_clear_timeouts (dpms); + return; + } +#endif +#ifdef HAVE_WAYLAND + if (gdk_display_get_default () != NULL && + GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ())) { + struct wl_display *display; + struct wl_registry *registry; + + dpms->priv->wayland_outputs = g_ptr_array_new_with_free_func (g_free); + + display = gdk_wayland_display_get_wl_display (gdk_display_get_default ()); + if (display == NULL) { + g_warning ("Cannot get Wayland display"); + return; + } + + registry = wl_display_get_registry (display); + if (registry == NULL) { + g_warning ("Cannot get Wayland registry"); + return; + } - /* ensure we clear the default timeouts (Standby: 1200s, Suspend: 1800s, Off: 2400s) */ - gpm_dpms_clear_timeouts (dpms); + wl_registry_add_listener (registry, + &gpm_dpms_wayland_registry_listener, dpms); + wl_display_roundtrip (display); + + if (dpms->priv->power_manager == NULL) { + g_debug ("Compositor does not support zwlr_output_power_manager_v1"); + } + + dpms->priv->timer_id = g_timeout_add_seconds (GPM_DPMS_POLL_TIME, + (GSourceFunc) gpm_dpms_poll_mode_cb, dpms); + g_source_set_name_by_id (dpms->priv->timer_id, "[GpmDpms] poll"); + return; + } +#endif + g_debug ("No DPMS backend available for current display"); } /** @@ -323,6 +578,21 @@ gpm_dpms_finalize (GObject *object) dpms->priv->timer_id = 0; } +#ifdef HAVE_WAYLAND + if (gdk_display_get_default () != NULL && + GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ())) { + guint i; + for (i = 0; i < dpms->priv->wayland_outputs->len; i++) { + GpmDpmsWaylandOutput *wo = g_ptr_array_index (dpms->priv->wayland_outputs, i); + if (wo->power) + zwlr_output_power_v1_destroy (wo->power); + } + g_ptr_array_free (dpms->priv->wayland_outputs, TRUE); + if (dpms->priv->power_manager) + zwlr_output_power_manager_v1_destroy (dpms->priv->power_manager); + } +#endif + G_OBJECT_CLASS (gpm_dpms_parent_class)->finalize (object); } @@ -422,4 +692,3 @@ gpm_dpms_test (gpointer data) } #endif - diff --git a/src/gpm-manager.c b/src/gpm-manager.c index 6a8cc1e..70818b9 100644 --- a/src/gpm-manager.c +++ b/src/gpm-manager.c @@ -93,7 +93,6 @@ struct GpmManagerPrivate UpClient *client; gboolean on_battery; gboolean just_resumed; - GtkStatusIcon *status_icon; NotifyNotification *notification_general; NotifyNotification *notification_warning_low; NotifyNotification *notification_discharging; @@ -475,6 +474,7 @@ gpm_manager_notify (GpmManager *manager, NotifyNotification **notification_class { gboolean ret; GError *error = NULL; + gchar *tray_icon_name; NotifyNotification *notification; GtkWidget *dialog; @@ -482,11 +482,12 @@ gpm_manager_notify (GpmManager *manager, NotifyNotification **notification_class gpm_manager_notify_close (manager, *notification_class); /* if the status icon is hidden, don't point at it */ - if (manager->priv->status_icon != NULL && - gtk_status_icon_is_embedded (manager->priv->status_icon)) - notification = notify_notification_new (title, message, gtk_status_icon_get_icon_name(manager->priv->status_icon)); + tray_icon_name = gpm_tray_icon_get_icon_name (manager->priv->tray_icon); + if (tray_icon_name != NULL) + notification = notify_notification_new (title, message, tray_icon_name); else notification = notify_notification_new (title, message, icon); + g_free (tray_icon_name); notify_notification_set_timeout (notification, timeout); notify_notification_set_urgency (notification, urgency); g_signal_connect (notification, "closed", G_CALLBACK (gpm_manager_notification_closed_cb), notification_class); @@ -1596,7 +1597,7 @@ gpm_manager_engine_charge_action_cb (GpmEngine *engine, UpDevice *device, GpmMan } else if (policy == GPM_ACTION_POLICY_SUSPEND) { /* TRANSLATORS: computer will suspend */ message = g_strdup (_("The battery is below the critical level and " - "this computer is about to suspend.<br>" + "this computer is about to suspend.\n" "<b>NOTE:</b> A small amount of power is required " "to keep your computer in a suspended state.")); @@ -1909,9 +1910,6 @@ gpm_manager_init (GpmManager *manager) g_debug ("creating new tray icon"); manager->priv->tray_icon = gpm_tray_icon_new (); - /* keep a reference for the notifications */ - manager->priv->status_icon = gpm_tray_icon_get_status_icon (manager->priv->tray_icon); - gpm_manager_sync_policy_sleep (manager); manager->priv->engine = gpm_engine_new (); @@ -1990,7 +1988,6 @@ gpm_manager_finalize (GObject *object) g_object_unref (manager->priv->kbd_backlight); g_object_unref (manager->priv->console); g_object_unref (manager->priv->client); - g_object_unref (manager->priv->status_icon); if (LOGIND_RUNNING()) { /* Let systemd take over again ... */ diff --git a/src/gpm-tray-icon.c b/src/gpm-tray-icon.c index bf27640..80dd67b 100644 --- a/src/gpm-tray-icon.c +++ b/src/gpm-tray-icon.c @@ -43,6 +43,10 @@ #include <libmate-desktop/mate-image-menu-item.h> +#ifdef HAVE_APP_INDICATOR +#include <libayatana-appindicator/app-indicator.h> +#endif + #include "gpm-upower.h" #include "gpm-engine.h" #include "gpm-common.h" @@ -55,7 +59,12 @@ struct GpmTrayIconPrivate { GSettings *settings; GpmEngine *engine; +#ifdef HAVE_APP_INDICATOR + AppIndicator *indicator; +#else GtkStatusIcon *status_icon; +#endif + gchar *current_icon; gboolean show_actions; }; @@ -79,7 +88,12 @@ static void gpm_tray_icon_show (GpmTrayIcon *icon, gboolean enabled) { g_return_if_fail (GPM_IS_TRAY_ICON (icon)); +#ifdef HAVE_APP_INDICATOR + app_indicator_set_status (icon->priv->indicator, + enabled ? APP_INDICATOR_STATUS_ACTIVE : APP_INDICATOR_STATUS_PASSIVE); +#else gtk_status_icon_set_visible (icon->priv->status_icon, enabled); +#endif } /** @@ -93,20 +107,24 @@ gpm_tray_icon_set_tooltip (GpmTrayIcon *icon, const gchar *tooltip) g_return_val_if_fail (GPM_IS_TRAY_ICON (icon), FALSE); g_return_val_if_fail (tooltip != NULL, FALSE); +#ifdef HAVE_APP_INDICATOR + app_indicator_set_title (icon->priv->indicator, tooltip); +#else gtk_status_icon_set_tooltip_text (icon->priv->status_icon, tooltip); gtk_status_icon_set_title (icon->priv->status_icon, tooltip); +#endif return TRUE; } /** - * gpm_tray_icon_get_status_icon: + * gpm_tray_icon_get_icon_name: **/ -GtkStatusIcon * -gpm_tray_icon_get_status_icon (GpmTrayIcon *icon) +gchar * +gpm_tray_icon_get_icon_name (GpmTrayIcon *icon) { g_return_val_if_fail (GPM_IS_TRAY_ICON (icon), NULL); - return g_object_ref (icon->priv->status_icon); + return g_strdup (icon->priv->current_icon); } /** @@ -123,8 +141,15 @@ gpm_tray_icon_set_icon (GpmTrayIcon *icon, const gchar *icon_name) if (icon_name != NULL) { g_debug ("Setting icon to %s", icon_name); +#ifdef HAVE_APP_INDICATOR + app_indicator_set_icon (icon->priv->indicator, icon_name); +#else gtk_status_icon_set_from_icon_name (icon->priv->status_icon, icon_name); +#endif + + g_free (icon->priv->current_icon); + icon->priv->current_icon = g_strdup (icon_name); /* make sure that we are visible */ gpm_tray_icon_show (icon, TRUE); @@ -132,6 +157,9 @@ gpm_tray_icon_set_icon (GpmTrayIcon *icon, const gchar *icon_name) /* remove icon */ g_debug ("no icon will be displayed"); + g_free (icon->priv->current_icon); + icon->priv->current_icon = NULL; + /* make sure that we are hidden */ gpm_tray_icon_show (icon, FALSE); } @@ -367,10 +395,10 @@ gpm_tray_icon_create_menu (GpmTrayIcon *icon) g_ptr_array_unref (array); /* skip for things like live-cd's and GDM */ - if (!icon->priv->show_actions) + if (!icon->priv->show_actions && dev_cnt != 0) goto skip_prefs; - /* only do the separator if we have at least one device */ + /* if no devices either, still show preferences to avoid empty menu */ if (dev_cnt != 0) { item = gtk_separator_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); @@ -409,6 +437,7 @@ skip_prefs: return menu; } +#ifndef HAVE_APP_INDICATOR /** * gpm_tray_icon_popup_cleared_cd: * @widget: The popup Gtkwidget @@ -470,6 +499,24 @@ gpm_tray_icon_activate_cb (GtkStatusIcon *status_icon, GpmTrayIcon *icon) g_debug ("icon left clicked"); gpm_tray_icon_popup_menu (icon, gtk_get_current_event_time()); } +#endif /* !HAVE_APP_INDICATOR */ + +/** + * gpm_tray_icon_rebuild_menu: + * + * Rebuild the menu and update the indicator. + **/ +static void +gpm_tray_icon_rebuild_menu (GpmTrayIcon *icon) +{ +#ifdef HAVE_APP_INDICATOR + GtkMenu *menu; + + menu = gpm_tray_icon_create_menu (icon); + gtk_widget_show_all (GTK_WIDGET (menu)); + app_indicator_set_menu (icon->priv->indicator, menu); +#endif +} /** * gpm_tray_icon_settings_changed_cb: @@ -484,6 +531,7 @@ gpm_tray_icon_settings_changed_cb (GSettings *settings, const gchar *key, GpmTra if (g_strcmp0 (key, GPM_SETTINGS_SHOW_ACTIONS) == 0) { allowed_in_menu = g_settings_get_boolean (settings, key); gpm_tray_icon_enable_actions (icon, allowed_in_menu); + gpm_tray_icon_rebuild_menu (icon); } } @@ -505,6 +553,15 @@ gpm_tray_icon_init (GpmTrayIcon *icon) g_signal_connect (icon->priv->settings, "changed", G_CALLBACK (gpm_tray_icon_settings_changed_cb), icon); +#ifdef HAVE_APP_INDICATOR + icon->priv->indicator = app_indicator_new ("mate-power-manager", + "mate-power-manager", + APP_INDICATOR_CATEGORY_HARDWARE); + g_object_ref_sink (icon->priv->indicator); + + /* start hidden; the engine decides when to show the icon */ + app_indicator_set_status (icon->priv->indicator, APP_INDICATOR_STATUS_PASSIVE); +#else icon->priv->status_icon = gtk_status_icon_new (); gpm_tray_icon_show (icon, FALSE); g_signal_connect_object (G_OBJECT (icon->priv->status_icon), @@ -515,9 +572,12 @@ gpm_tray_icon_init (GpmTrayIcon *icon) "activate", G_CALLBACK (gpm_tray_icon_activate_cb), icon, 0); +#endif allowed_in_menu = g_settings_get_boolean (icon->priv->settings, GPM_SETTINGS_SHOW_ACTIONS); gpm_tray_icon_enable_actions (icon, allowed_in_menu); + + gpm_tray_icon_rebuild_menu (icon); } /** @@ -534,8 +594,14 @@ gpm_tray_icon_finalize (GObject *object) tray_icon = GPM_TRAY_ICON (object); + g_object_unref (tray_icon->priv->settings); +#ifdef HAVE_APP_INDICATOR + g_object_unref (tray_icon->priv->indicator); +#else g_object_unref (tray_icon->priv->status_icon); +#endif g_object_unref (tray_icon->priv->engine); + g_free (tray_icon->priv->current_icon); g_return_if_fail (tray_icon->priv != NULL); G_OBJECT_CLASS (gpm_tray_icon_parent_class)->finalize (object); @@ -552,4 +618,3 @@ gpm_tray_icon_new (void) tray_icon = g_object_new (GPM_TYPE_TRAY_ICON, NULL); return GPM_TRAY_ICON (tray_icon); } - diff --git a/src/gpm-tray-icon.h b/src/gpm-tray-icon.h index b31a9a8..123ce79 100644 --- a/src/gpm-tray-icon.h +++ b/src/gpm-tray-icon.h @@ -57,7 +57,7 @@ gboolean gpm_tray_icon_set_tooltip (GpmTrayIcon *icon, const gchar *tooltip); gboolean gpm_tray_icon_set_icon (GpmTrayIcon *icon, const gchar *icon_name); -GtkStatusIcon *gpm_tray_icon_get_status_icon (GpmTrayIcon *icon); +gchar *gpm_tray_icon_get_icon_name (GpmTrayIcon *icon); G_END_DECLS diff --git a/src/meson.build b/src/meson.build index 35a0b88..ee5026f 100644 --- a/src/meson.build +++ b/src/meson.build @@ -33,6 +33,45 @@ cflags = [ '-DI_KNOW_THE_DEVICEKIT_POWER_API_IS_SUBJECT_TO_CHANGE', '-DEGG_CONSOLE="GPM_CONSOLE"' ] + +if enable_wayland + cflags += '-DHAVE_WAYLAND' + wp_dep = dependency('wayland-protocols') + wp_datadir = wp_dep.get_pkgconfig_variable('pkgdatadir') + ext_idle_notify_xml = join_paths(wp_datadir, 'staging', 'ext-idle-notify', 'ext-idle-notify-v1.xml') + ext_idle_notify_code = custom_target('ext-idle-notify-protocol', + input: ext_idle_notify_xml, + output: 'ext-idle-notify-v1-protocol.c', + command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'] + ) + ext_idle_notify_header = custom_target('ext-idle-notify-header', + input: ext_idle_notify_xml, + output: 'ext-idle-notify-v1-client.h', + command: [wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@'] + ) + + wlr_power_xml = files('wlr-output-power-management-unstable-v1.xml') + wlr_output_power_code = custom_target('wlr-output-power-protocol', + input: wlr_power_xml, + output: 'wlr-output-power-management-unstable-v1-protocol.c', + command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'] + ) + wlr_output_power_header = custom_target('wlr-output-power-header', + input: wlr_power_xml, + output: 'wlr-output-power-management-unstable-v1-client.h', + command: [wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@'] + ) + + wayland_protocol_sources = [ + ext_idle_notify_code, + ext_idle_notify_header, + wlr_output_power_code, + wlr_output_power_header, + ] + sources += wayland_protocol_sources +else + wayland_protocol_sources = [] +endif marshal_files = gnome.genmarshal('gpm-marshal', prefix : 'gpm_marshal', sources : 'gpm-marshal.list') dbus_binding_tool = find_program('dbus-binding-tool') @@ -63,8 +102,13 @@ deps = [ keyring, libsecret, notify, + appindicator, ] +if enable_wayland + deps += wayland_client +endif + libmpm_shared = static_library( 'libmpmstatic', sources: [ @@ -175,6 +219,7 @@ executable( dbus_Backlight, dbus_KbdBacklight, dbus_Manager, + wayland_protocol_sources, ], include_directories : [ include_directories('..'), diff --git a/src/msd-osd-window.c b/src/msd-osd-window.c index e6ebc0b..128fcae 100644 --- a/src/msd-osd-window.c +++ b/src/msd-osd-window.c @@ -457,11 +457,15 @@ msd_osd_window_init (MsdOsdWindow *window) style = gtk_widget_get_style_context (GTK_WIDGET (window)); gtk_style_context_add_class (style, "window-frame"); - /* assume 110x110 on a 640x480 display and scale from there */ - scalew = WidthOfScreen (gdk_x11_screen_get_xscreen (screen)) / (640.0 * window->priv->scale_factor); - scaleh = HeightOfScreen (gdk_x11_screen_get_xscreen (screen)) / (480.0 * window->priv->scale_factor); - scale = MIN (scalew, scaleh); - size = 110 * MAX (1, scale); + if (GDK_IS_X11_SCREEN (screen)) { + /* assume 110x110 on a 640x480 display and scale from there */ + scalew = WidthOfScreen (gdk_x11_screen_get_xscreen (screen)) / (640.0 * window->priv->scale_factor); + scaleh = HeightOfScreen (gdk_x11_screen_get_xscreen (screen)) / (480.0 * window->priv->scale_factor); + scale = MIN (scalew, scaleh); + size = 110 * MAX (1, scale); + } else { + size = 110; + } gtk_window_set_default_size (GTK_WINDOW (window), size, size); diff --git a/src/wlr-output-power-management-unstable-v1.xml b/src/wlr-output-power-management-unstable-v1.xml new file mode 100644 index 0000000..20dbb77 --- /dev/null +++ b/src/wlr-output-power-management-unstable-v1.xml @@ -0,0 +1,128 @@ +<?xml version="1.0" encoding="UTF-8"?> +<protocol name="wlr_output_power_management_unstable_v1"> + <copyright> + 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. + </copyright> + + <description summary="Control power management modes of outputs"> + 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. + </description> + + <interface name="zwlr_output_power_manager_v1" version="1"> + <description summary="manager to create per-output power management"> + This interface is a manager that allows creating per-output power + management mode controls. + </description> + + <request name="get_output_power"> + <description summary="get a power management for an output"> + Create an output power management mode control that can be used to + adjust the power management mode for a given output. + </description> + <arg name="id" type="new_id" interface="zwlr_output_power_v1"/> + <arg name="output" type="object" interface="wl_output"/> + </request> + + <request name="destroy" type="destructor"> + <description summary="destroy the manager"> + All objects created by the manager will still remain valid, until their + appropriate destroy request has been called. + </description> + </request> + </interface> + + <interface name="zwlr_output_power_v1" version="1"> + <description summary="adjust power management mode for an output"> + This object offers requests to set the power management mode of + an output. + </description> + + <enum name="mode"> + <entry name="off" value="0" + summary="Output is turned off."/> + <entry name="on" value="1" + summary="Output is turned on, no power saving"/> + </enum> + + <enum name="error"> + <entry name="invalid_mode" value="1" summary="nonexistent power save mode"/> + </enum> + + <request name="set_mode"> + <description summary="Set an outputs power save mode"> + 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. + </description> + <arg name="mode" type="uint" enum="mode" summary="the power save mode to set"/> + </request> + + <event name="mode"> + <description summary="Report a power management mode change"> + 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. + </description> + <arg name="mode" type="uint" enum="mode" + summary="the output's new power management mode"/> + </event> + + <event name="failed"> + <description summary="object no longer valid"> + 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. + </description> + </event> + + <request name="destroy" type="destructor"> + <description summary="destroy this power management"> + Destroys the output power management mode control object. + </description> + </request> + </interface> +</protocol> |
