summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am56
-rw-r--r--src/egg-idletime.c538
-rw-r--r--src/gpm-brightness.c253
-rw-r--r--src/gpm-button.c68
-rw-r--r--src/gpm-dpms.c371
-rw-r--r--src/gpm-manager.c15
-rw-r--r--src/gpm-tray-icon.c79
-rw-r--r--src/gpm-tray-icon.h2
-rw-r--r--src/meson.build45
-rw-r--r--src/msd-osd-window.c14
-rw-r--r--src/wlr-output-power-management-unstable-v1.xml128
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>