[gpm] Keyboard backlight support



Hi,

Attached is a patch to add keyboard backlight support via UPower. This
add gpm-backlight-kbd which is basically a copy & paste of
gpm-backlight which allows us to have the same policy as is currently
used for screen backlight and instead uses the recently added UPower
KbdBacklight interface.

At this stage I have made the patch against the 2.32.0 version (aka
0761a35880a5816f884f2ddad8989bee961c985f) (not git HEAD since I can't
compile it easily with the latest dependencies on my Ubuntu machine)
so it would need some small work to adapt to changes in HEAD.

Any comments etc would be muchly appreciated.

Cheers
Alex
From 5f4f713e8c1ec6bb9b091c15dfb95c5e42cd86a9 Mon Sep 17 00:00:00 2001
From: Alex Murray <murray alex gmail com>
Date: Sun, 17 Oct 2010 09:01:29 +1030
Subject: [PATCH] Initial keyboard backlight support

Added GpmBacklightKbd based off existing GpmBacklight to control any keyboard
backlight via the org.freedesktop.UPower.KbdBacklight interface. This emulates
most of the policy for GpmBacklight, so we ensure that for instance the
keyboard backlight is proportional to the display backlight when on battery
power etc.
---
 src/Makefile.am         |    2 +
 src/gpm-backlight-kbd.c |  699 +++++++++++++++++++++++++++++++++++++++++++++++
 src/gpm-backlight-kbd.h |   57 ++++
 src/gpm-manager.c       |    4 +
 4 files changed, 762 insertions(+), 0 deletions(-)
 create mode 100644 src/gpm-backlight-kbd.c
 create mode 100644 src/gpm-backlight-kbd.h

diff --git a/src/Makefile.am b/src/Makefile.am
index c04c4ae..2c798ab 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -146,6 +146,8 @@ gnome_power_manager_SOURCES =				\
 	gpm-phone.c					\
 	gpm-backlight.h					\
 	gpm-backlight.c					\
+	gpm-backlight-kbd.h				\
+	gpm-backlight-kbd.c				\
 	gpm-prefs-server.h				\
 	gpm-prefs-server.c				\
 	gpm-idle.h					\
diff --git a/src/gpm-backlight-kbd.c b/src/gpm-backlight-kbd.c
new file mode 100644
index 0000000..9fae79e
--- /dev/null
+++ b/src/gpm-backlight-kbd.c
@@ -0,0 +1,699 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Alex Murray <murray alex gmail com>
+ * Copyright (C) 2005-2009 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2005 William Jon McCann <mccann jhu edu>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <errno.h>
+
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <math.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#include <glib/gi18n.h>
+#include <dbus/dbus-glib.h>
+#include <gconf/gconf-client.h>
+#include <libupower-glib/upower.h>
+
+#include "gpm-button.h"
+#include "gpm-backlight-kbd.h"
+#include "gpm-control.h"
+#include "gpm-common.h"
+#include "egg-debug.h"
+#include "gsd-media-keys-window.h"
+#include "gpm-dpms.h"
+#include "gpm-idle.h"
+#include "gpm-marshal.h"
+#include "gpm-stock-icons.h"
+#include "gpm-prefs-server.h"
+#include "egg-console-kit.h"
+
+#define GPM_BACKLIGHT_KBD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPM_TYPE_BACKLIGHT_KBD, GpmBacklightKbdPrivate))
+
+struct GpmBacklightKbdPrivate
+{
+	UpClient		*client;
+	DBusGProxy		*proxy;
+	GpmButton		*button;
+	GConfClient		*conf;
+	GtkWidget		*popup;
+	GpmControl		*control;
+	GpmDpms			*dpms;
+	GpmIdle			*idle;
+	EggConsoleKit		*consolekit;
+	gboolean		 system_is_idle;
+	GTimer			*idle_timer;
+	guint			 idle_dim_timeout;
+	gint			 master_percentage;
+	gint			 max_brightness;
+	gboolean		 off;
+};
+
+G_DEFINE_TYPE (GpmBacklightKbd, gpm_backlight_kbd, G_TYPE_OBJECT)
+
+#define BACKLIGHT_KBD_SERVICE     "org.freedesktop.UPower"
+#define BACKLIGHT_KBD_PATH        "/org/freedesktop/UPower/KbdBacklight"
+#define BACKLIGHT_KBD_INTERFACE   "org.freedesktop.UPower.KbdBacklight"
+
+/**
+ * gpm_backlight_kbd_dialog_init:
+ *
+ * Initialises the popup, and makes sure that it matches the compositing of the screen.
+ **/
+static void
+gpm_backlight_kbd_dialog_init (GpmBacklightKbd *backlight_kbd)
+{
+	if (backlight_kbd->priv->popup != NULL
+	    && !gsd_media_keys_window_is_valid (GSD_MEDIA_KEYS_WINDOW (backlight_kbd->priv->popup))) {
+		gtk_widget_destroy (backlight_kbd->priv->popup);
+		backlight_kbd->priv->popup = NULL;
+	}
+
+	if (backlight_kbd->priv->popup == NULL) {
+		backlight_kbd->priv->popup= gsd_media_keys_window_new ();
+		gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (backlight_kbd->priv->popup),
+							 "gpm-brightness-kbd",
+							 TRUE);
+		gtk_window_set_position (GTK_WINDOW (backlight_kbd->priv->popup), GTK_WIN_POS_NONE);
+	}
+}
+
+/**
+ * gpm_backlight_kbd_dialog_show:
+ *
+ * Show the brightness popup, and place it nicely on the screen.
+ **/
+static void
+gpm_backlight_kbd_dialog_show (GpmBacklightKbd *backlight_kbd)
+{
+	int            orig_w;
+	int            orig_h;
+	int            screen_w;
+	int            screen_h;
+	int            x;
+	int            y;
+	int            pointer_x;
+	int            pointer_y;
+	GtkRequisition win_req;
+	GdkScreen     *pointer_screen;
+	GdkRectangle   geometry;
+	int            monitor;
+
+	/*
+	 * get the window size
+	 * if the window hasn't been mapped, it doesn't necessarily
+	 * know its true size, yet, so we need to jump through hoops
+	 */
+	gtk_window_get_default_size (GTK_WINDOW (backlight_kbd->priv->popup), &orig_w, &orig_h);
+	gtk_widget_size_request (backlight_kbd->priv->popup, &win_req);
+
+	if (win_req.width > orig_w) {
+		orig_w = win_req.width;
+	}
+	if (win_req.height > orig_h) {
+		orig_h = win_req.height;
+	}
+
+	pointer_screen = NULL;
+	gdk_display_get_pointer (gtk_widget_get_display (backlight_kbd->priv->popup),
+				 &pointer_screen,
+				 &pointer_x,
+				 &pointer_y,
+				 NULL);
+	monitor = gdk_screen_get_monitor_at_point (pointer_screen,
+						   pointer_x,
+						   pointer_y);
+
+	gdk_screen_get_monitor_geometry (pointer_screen,
+					 monitor,
+					 &geometry);
+
+	screen_w = geometry.width;
+	screen_h = geometry.height;
+
+	x = ((screen_w - orig_w) / 2) + geometry.x;
+	y = geometry.y + (screen_h / 2) + (screen_h / 2 - orig_h) / 2;
+
+	gtk_window_move (GTK_WINDOW (backlight_kbd->priv->popup), x, y);
+
+	gtk_widget_show (backlight_kbd->priv->popup);
+
+	gdk_display_sync (gtk_widget_get_display (backlight_kbd->priv->popup));
+}
+
+/**
+ * gpm_backlight_kbd_brightness_evaluate_and_set:
+ **/
+static gboolean
+gpm_backlight_kbd_brightness_evaluate_and_set (GpmBacklightKbd *backlight_kbd, gboolean interactive)
+{
+	gfloat brightness;
+	gfloat scale;
+	gboolean ret;
+	gboolean on_battery;
+	gboolean do_laptop_lcd;
+	gboolean enable_action;
+	gboolean battery_reduce;
+	GError *error = NULL;
+	gint value;
+	gint old_value;
+
+	if (backlight_kbd->priv->proxy == NULL) {
+		egg_warning ("no kbd backlight hardware");
+		return FALSE;
+	}
+
+	do_laptop_lcd = gconf_client_get_bool (backlight_kbd->priv->conf, GPM_CONF_BACKLIGHT_ENABLE, NULL);
+	if (do_laptop_lcd == FALSE) {
+		egg_warning ("policy is no dimming");
+		return FALSE;
+	}
+
+	/* get the last set brightness */
+	brightness = backlight_kbd->priv->master_percentage / 100.0f;
+	egg_debug ("1. main brightness %f", brightness);
+
+	/* get battery status */
+	g_object_get (backlight_kbd->priv->client,
+		      "on-battery", &on_battery,
+		      NULL);
+
+	/* reduce if on battery power if we should */
+	battery_reduce = gconf_client_get_bool (backlight_kbd->priv->conf, GPM_CONF_BACKLIGHT_BATTERY_REDUCE, NULL);
+	if (on_battery && battery_reduce) {
+		value = gconf_client_get_int (backlight_kbd->priv->conf, GPM_CONF_BACKLIGHT_BRIGHTNESS_DIM_BATT, NULL);
+		if (value > 100) {
+			egg_warning ("cannot use battery brightness value %i, correcting to 50", value);
+			value = 50;
+		}
+		scale = (100 - value) / 100.0f;
+		brightness *= scale;
+	} else {
+		scale = 1.0f;
+	}
+	egg_debug ("2. battery scale %f, brightness %f", scale, brightness);
+
+	/* reduce if system is momentarily idle */
+	if (!on_battery)
+		enable_action = gconf_client_get_bool (backlight_kbd->priv->conf, GPM_CONF_BACKLIGHT_IDLE_DIM_AC, NULL);
+	else
+		enable_action = gconf_client_get_bool (backlight_kbd->priv->conf, GPM_CONF_BACKLIGHT_IDLE_DIM_BATT, NULL);
+	if (enable_action && backlight_kbd->priv->system_is_idle) {
+		value = gconf_client_get_int (backlight_kbd->priv->conf, GPM_CONF_BACKLIGHT_IDLE_BRIGHTNESS, NULL);
+		if (value > 100) {
+			egg_warning ("cannot use idle brightness value %i, correcting to 50", value);
+			value = 50;
+		}
+		scale = value / 100.0f;
+		brightness *= scale;
+	} else {
+		scale = 1.0f;
+	}
+	egg_debug ("3. idle scale %f, brightness %f", scale, brightness);
+
+	/* convert to percentage */
+	value = (gint) ((brightness * 100.0f) + 0.5);
+
+	/* normalize to max brightness */
+	value = value * backlight_kbd->priv->max_brightness / 100;
+
+	if (backlight_kbd->priv->off)
+		value = 0;
+
+	/* only do stuff if the brightness is different */
+	ret = dbus_g_proxy_call (backlight_kbd->priv->proxy,
+				 "GetBrightness", &error,
+				 G_TYPE_INVALID,
+				 G_TYPE_INT, &old_value,
+				 G_TYPE_INVALID);
+	if (error) {
+		egg_debug ("ERROR: %s", error->message);
+		g_error_free (error);
+	}
+	if (!ret) {
+		egg_warning ("GetBrightness failed!");
+		return FALSE;
+	}
+	if (old_value == value) {
+		egg_debug ("values are the same, no action");
+		return FALSE;
+	}
+
+	/* only show dialog if interactive */
+	if (interactive) {
+		gpm_backlight_kbd_dialog_init (backlight_kbd);
+		gsd_media_keys_window_set_volume_level (GSD_MEDIA_KEYS_WINDOW (backlight_kbd->priv->popup),
+							round (brightness));
+		gpm_backlight_kbd_dialog_show (backlight_kbd);
+	}
+
+	egg_debug ("Setting brightness to %d", value);
+	return dbus_g_proxy_call (backlight_kbd->priv->proxy,
+				  "SetBrightness", NULL,
+				  G_TYPE_INT, value,
+				  G_TYPE_INVALID, G_TYPE_INVALID);
+	return TRUE;
+}
+
+/**
+ * gpm_conf_gconf_key_changed_cb:
+ *
+ * We might have to do things when the gconf keys change; do them here.
+ **/
+static void
+gpm_conf_gconf_key_changed_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, GpmBacklightKbd *backlight_kbd)
+{
+	GConfValue *value;
+	gboolean on_battery;
+
+	value = gconf_entry_get_value (entry);
+	if (value == NULL)
+		return;
+
+	/* get battery status */
+	g_object_get (backlight_kbd->priv->client,
+		      "on-battery", &on_battery,
+		      NULL);
+
+	if (!on_battery && strcmp (entry->key, GPM_CONF_BACKLIGHT_BRIGHTNESS_AC) == 0) {
+		backlight_kbd->priv->master_percentage = gconf_value_get_int (value);
+		gpm_backlight_kbd_brightness_evaluate_and_set (backlight_kbd, FALSE);
+
+	} else if (on_battery && strcmp (entry->key, GPM_CONF_BACKLIGHT_BRIGHTNESS_DIM_BATT) == 0) {
+		gpm_backlight_kbd_brightness_evaluate_and_set (backlight_kbd, FALSE);
+
+	} else if (strcmp (entry->key, GPM_CONF_BACKLIGHT_IDLE_DIM_AC) == 0 ||
+		   strcmp (entry->key, GPM_CONF_BACKLIGHT_ENABLE) == 0 ||
+		   strcmp (entry->key, GPM_CONF_TIMEOUT_SLEEP_DISPLAY_BATT) == 0 ||
+		   strcmp (entry->key, GPM_CONF_BACKLIGHT_BATTERY_REDUCE) == 0 ||
+		   strcmp (entry->key, GPM_CONF_BACKLIGHT_IDLE_BRIGHTNESS) == 0) {
+		gpm_backlight_kbd_brightness_evaluate_and_set (backlight_kbd, FALSE);
+
+	} else if (strcmp (entry->key, GPM_CONF_BACKLIGHT_IDLE_DIM_TIME) == 0) {
+		backlight_kbd->priv->idle_dim_timeout = gconf_value_get_int (value);
+		gpm_idle_set_timeout_dim (backlight_kbd->priv->idle, backlight_kbd->priv->idle_dim_timeout);
+	} else {
+		egg_debug ("unknown key %s", entry->key);
+	}
+}
+
+/**
+ * gpm_backlight_kbd_client_changed_cb:
+ * @client: The up_client class instance
+ * @backlight_kbd: This class instance
+ *
+ * Does the actions when the ac power source is inserted/removed.
+ **/
+static void
+gpm_backlight_kbd_client_changed_cb (UpClient *client, GpmBacklightKbd *backlight_kbd)
+{
+	gpm_backlight_kbd_brightness_evaluate_and_set (backlight_kbd, FALSE);
+}
+
+/**
+ * gpm_backlight_kbd_button_pressed_cb:
+ * @power: The power class instance
+ * @type: The button type, e.g. "power"
+ * @state: The state, where TRUE is depressed or closed
+ * @brightness: This class instance
+ **/
+static void
+gpm_backlight_kbd_button_pressed_cb (GpmButton *button, const gchar *type, GpmBacklightKbd *backlight_kbd)
+{
+	GError *error = NULL;
+	gboolean ret = FALSE;
+	gint percentage = -1, brightness;
+	egg_debug ("Button press event type=%s", type);
+
+	if (strcmp (type, GPM_BUTTON_KBD_BRIGHT_UP) == 0) {
+		percentage = MIN(100, backlight_kbd->priv->master_percentage + 10);
+		brightness = percentage * backlight_kbd->priv->max_brightness / 100;
+		egg_debug ("Setting brightness to %d", brightness);
+		ret = dbus_g_proxy_call (backlight_kbd->priv->proxy,
+					 "SetBrightness", &error,
+					 G_TYPE_INT, brightness,
+					 G_TYPE_INVALID, G_TYPE_INVALID);
+	} else if (strcmp (type, GPM_BUTTON_KBD_BRIGHT_DOWN) == 0) {
+		percentage = MAX(0, backlight_kbd->priv->master_percentage - 10);
+		brightness = percentage * backlight_kbd->priv->max_brightness / 100;
+		egg_debug ("Setting brightness to %d", brightness);
+		ret = dbus_g_proxy_call (backlight_kbd->priv->proxy,
+					 "SetBrightness", &error,
+					 G_TYPE_INT, brightness,
+					 G_TYPE_INVALID, G_TYPE_INVALID);
+	}
+	if (ret) {
+		gpm_backlight_kbd_dialog_init (backlight_kbd);
+		gsd_media_keys_window_set_volume_level (GSD_MEDIA_KEYS_WINDOW (backlight_kbd->priv->popup),
+							percentage);
+		gpm_backlight_kbd_dialog_show (backlight_kbd);
+		/* save the new percentage */
+		backlight_kbd->priv->master_percentage = percentage;
+	} else if (percentage >= 0) {
+		egg_warning ("failed to set brightness to %d: %s", brightness, error->message);
+		g_error_free (error);
+	}
+}
+
+/**
+ * gpm_backlight_kbd_notify_system_idle_changed:
+ **/
+static gboolean
+gpm_backlight_kbd_notify_system_idle_changed (GpmBacklightKbd *backlight_kbd, gboolean is_idle)
+{
+	gdouble elapsed;
+
+	/* no point continuing */
+	if (backlight_kbd->priv->system_is_idle == is_idle) {
+		egg_debug ("state not changed");
+		return FALSE;
+	}
+
+	/* get elapsed time and reset timer */
+	elapsed = g_timer_elapsed (backlight_kbd->priv->idle_timer, NULL);
+	g_timer_reset (backlight_kbd->priv->idle_timer);
+
+	if (is_idle == FALSE) {
+		egg_debug ("we have just been idle for %lfs", elapsed);
+
+		/* The user immediatly undimmed the screen!
+		 * We should double the timeout to avoid this happening again */
+		if (elapsed < 10) {
+			/* double the event time */
+			backlight_kbd->priv->idle_dim_timeout *= 2.0;
+			egg_debug ("increasing idle dim time to %is", backlight_kbd->priv->idle_dim_timeout);
+			gpm_idle_set_timeout_dim (backlight_kbd->priv->idle, backlight_kbd->priv->idle_dim_timeout);
+		}
+
+		/* We reset the dimming after 2 minutes of idle,
+		 * as the user will have changed tasks */
+		if (elapsed > 2*60) {
+			/* reset back to our default dimming */
+			backlight_kbd->priv->idle_dim_timeout =
+				gconf_client_get_int (backlight_kbd->priv->conf,
+						      GPM_CONF_BACKLIGHT_IDLE_DIM_TIME, NULL);
+			egg_debug ("resetting idle dim time to %is", backlight_kbd->priv->idle_dim_timeout);
+			gpm_idle_set_timeout_dim (backlight_kbd->priv->idle, backlight_kbd->priv->idle_dim_timeout);
+		}
+	} else {
+		egg_debug ("we were active for %lfs", elapsed);
+	}
+
+	egg_debug ("changing powersave idle status to %i", is_idle);
+	backlight_kbd->priv->system_is_idle = is_idle;
+	return TRUE;
+}
+
+/**
+ * idle_changed_cb:
+ * @idle: The idle class instance
+ * @mode: The idle mode, e.g. GPM_IDLE_MODE_BLANK
+ * @manager: This class instance
+ *
+ * This callback is called when gnome-screensaver detects that the idle state
+ * has changed. GPM_IDLE_MODE_BLANK is when the session has become inactive,
+ * and GPM_IDLE_MODE_SLEEP is where the session has become inactive, AND the
+ * session timeout has elapsed for the idle action.
+ **/
+static void
+idle_changed_cb (GpmIdle *idle, GpmIdleMode mode, GpmBacklightKbd *backlight_kbd)
+{
+	/* don't dim or undim the screen when the lid is closed */
+	if (gpm_button_is_lid_closed (backlight_kbd->priv->button))
+		return;
+
+	/* don't dim or undim the screen unless we are on the active console */
+	if (!egg_console_kit_is_active (backlight_kbd->priv->consolekit)) {
+		egg_debug ("ignoring as not on active console");
+		return;
+	}
+
+	if (mode == GPM_IDLE_MODE_NORMAL) {
+		/* sync brightness */
+		gpm_backlight_kbd_notify_system_idle_changed (backlight_kbd, FALSE);
+		gpm_backlight_kbd_brightness_evaluate_and_set (backlight_kbd, FALSE);
+	} else if (mode == GPM_IDLE_MODE_DIM) {
+		/* sync brightness */
+		gpm_backlight_kbd_notify_system_idle_changed (backlight_kbd, TRUE);
+		gpm_backlight_kbd_brightness_evaluate_and_set (backlight_kbd, FALSE);
+	} else if (mode == GPM_IDLE_MODE_BLANK) {
+		/* sync brightness */
+		gpm_backlight_kbd_notify_system_idle_changed (backlight_kbd, TRUE);
+		gpm_backlight_kbd_brightness_evaluate_and_set (backlight_kbd, FALSE);
+	}
+}
+
+/**
+ * control_resume_cb:
+ * @control: The control class instance
+ * @power: This power class instance
+ *
+ * We have to update the caches on resume
+ */
+static void
+control_resume_cb (GpmControl *control, GpmControlAction action, GpmBacklightKbd *backlight_kbd)
+{
+	gboolean ret;
+	gint brightness;
+	GError *error = NULL;
+
+	/* ensure backlight is on */
+	brightness = backlight_kbd->priv->master_percentage * backlight_kbd->priv->max_brightness / 100;
+	egg_debug ("setting brightness to %d", brightness);
+	ret = dbus_g_proxy_call (backlight_kbd->priv->proxy,
+				 "SetBrightness", &error,
+				 G_TYPE_INT, brightness,
+				 G_TYPE_INVALID, G_TYPE_INVALID);
+	if (!ret) {
+		egg_warning ("failed to turn on kbd backlight: %s", error->message);
+		g_error_free (error);
+	}
+}
+
+/**
+ * dpms_mode_changed_cb:
+ * @dpms: The dpms class instance
+ * @mode: The dpms mode
+ * @backlight_kbd: The keyboard backlight instance
+ *
+ * We want to stay in sync with screen dpms
+ */
+static void
+dpms_mode_changed_cb (GpmDpms *dpms, GpmDpmsMode mode, GpmBacklightKbd *backlight_kbd)
+{
+	backlight_kbd->priv->off = (mode != GPM_DPMS_MODE_ON);
+	gpm_backlight_kbd_brightness_evaluate_and_set (backlight_kbd, FALSE);
+}
+/**
+ * gpm_backlight_kbd_finalize:
+ **/
+static void
+gpm_backlight_kbd_finalize (GObject *object)
+{
+	GpmBacklightKbd *backlight_kbd;
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (GPM_IS_BACKLIGHT_KBD (object));
+	backlight_kbd = GPM_BACKLIGHT_KBD (object);
+
+	g_timer_destroy (backlight_kbd->priv->idle_timer);
+	gtk_widget_destroy (backlight_kbd->priv->popup);
+
+	g_object_unref (backlight_kbd->priv->dpms);
+	g_object_unref (backlight_kbd->priv->control);
+	g_object_unref (backlight_kbd->priv->conf);
+	g_object_unref (backlight_kbd->priv->client);
+	g_object_unref (backlight_kbd->priv->button);
+	g_object_unref (backlight_kbd->priv->idle);
+	g_object_unref (backlight_kbd->priv->proxy);
+	g_object_unref (backlight_kbd->priv->consolekit);
+
+	g_return_if_fail (backlight_kbd->priv != NULL);
+	G_OBJECT_CLASS (gpm_backlight_kbd_parent_class)->finalize (object);
+}
+
+/**
+ * gpm_backlight_kbd_class_init:
+ **/
+static void
+gpm_backlight_kbd_class_init (GpmBacklightKbdClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize	   = gpm_backlight_kbd_finalize;
+
+	g_type_class_add_private (klass, sizeof (GpmBacklightKbdPrivate));
+}
+
+/**
+ * gpm_backlight_kbd_init:
+ * @brightness: This brightness class instance
+ *
+ * initialises the brightness class. NOTE: We expect laptop_panel objects
+ * to *NOT* be removed or added during the session.
+ * We only control the first laptop_panel object if there are more than one.
+ **/
+static void
+gpm_backlight_kbd_init (GpmBacklightKbd *backlight_kbd)
+{
+	DBusGConnection *connection;
+	GError *error = NULL;
+	gboolean ret;
+	gint brightness;
+
+	backlight_kbd->priv = GPM_BACKLIGHT_KBD_GET_PRIVATE (backlight_kbd);
+
+	/* record our idle time */
+	backlight_kbd->priv->idle_timer = g_timer_new ();
+
+	/* we use up_client for the ac-adapter-changed signal */
+	backlight_kbd->priv->client = up_client_new ();
+	g_signal_connect (backlight_kbd->priv->client, "changed",
+			  G_CALLBACK (gpm_backlight_kbd_client_changed_cb), backlight_kbd);
+
+	/* watch for dim value changes */
+	backlight_kbd->priv->conf = gconf_client_get_default ();
+
+	/* watch gnome-power-manager keys */
+	gconf_client_add_dir (backlight_kbd->priv->conf, GPM_CONF_DIR, GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
+	gconf_client_notify_add (backlight_kbd->priv->conf, GPM_CONF_DIR,
+				 (GConfClientNotifyFunc) gpm_conf_gconf_key_changed_cb,
+				 backlight_kbd, NULL, NULL);
+
+	/* set the main brightness, this is designed to be updated if the user changes the
+	 * brightness so we can undim to the 'correct' value */
+	backlight_kbd->priv->master_percentage = gconf_client_get_int (backlight_kbd->priv->conf, GPM_CONF_BACKLIGHT_BRIGHTNESS_AC, NULL);
+
+	/* watch for brightness up and down buttons and also check lid state */
+	backlight_kbd->priv->button = gpm_button_new ();
+	g_signal_connect (backlight_kbd->priv->button, "button-pressed",
+			  G_CALLBACK (gpm_backlight_kbd_button_pressed_cb), backlight_kbd);
+
+	/* watch for idle mode changes */
+	backlight_kbd->priv->idle = gpm_idle_new ();
+	g_signal_connect (backlight_kbd->priv->idle, "idle-changed",
+			  G_CALLBACK (idle_changed_cb), backlight_kbd);
+
+	/* assumption */
+	backlight_kbd->priv->system_is_idle = FALSE;
+	backlight_kbd->priv->idle_dim_timeout = gconf_client_get_int (backlight_kbd->priv->conf, GPM_CONF_BACKLIGHT_IDLE_DIM_TIME, NULL);
+	gpm_idle_set_timeout_dim (backlight_kbd->priv->idle, backlight_kbd->priv->idle_dim_timeout);
+
+	/* use a visual widget */
+	backlight_kbd->priv->popup = gsd_media_keys_window_new ();
+	gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (backlight_kbd->priv->popup),
+						 "gpm-brightness-lcd",
+						 TRUE);
+	gtk_window_set_position (GTK_WINDOW (backlight_kbd->priv->popup), GTK_WIN_POS_NONE);
+
+	/* DPMS mode poll class */
+	backlight_kbd->priv->dpms = gpm_dpms_new ();
+	g_signal_connect (backlight_kbd->priv->dpms, "mode-changed",
+			  G_CALLBACK (dpms_mode_changed_cb), backlight_kbd);
+
+	/* we refresh backlight on resume */
+	backlight_kbd->priv->control = gpm_control_new ();
+	g_signal_connect (backlight_kbd->priv->control, "resume",
+			  G_CALLBACK (control_resume_cb), backlight_kbd);
+
+	/* Don't do dimming on inactive console */
+	backlight_kbd->priv->consolekit = egg_console_kit_new ();
+
+	connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
+	backlight_kbd->priv->proxy = dbus_g_proxy_new_for_name (connection,
+								BACKLIGHT_KBD_SERVICE,
+								BACKLIGHT_KBD_PATH,
+								BACKLIGHT_KBD_INTERFACE);
+
+	if (!backlight_kbd->priv->proxy) {
+		egg_warning ("Failed to get proxy to kbdbacklight interface");
+		return;
+	}
+
+	ret = dbus_g_proxy_call (backlight_kbd->priv->proxy,
+				 "GetBrightness", &error,
+				 G_TYPE_INVALID,
+				 G_TYPE_INT, &brightness,
+				 G_TYPE_INVALID);
+	if (error) {
+		egg_debug ("ERROR: %s", error->message);
+		g_error_free (error);
+	}
+	if (!ret) {
+		egg_warning ("GetBrightness failed!");
+		return;
+	}
+
+	ret = dbus_g_proxy_call (backlight_kbd->priv->proxy,
+				 "GetMaxBrightness", &error,
+				 G_TYPE_INVALID,
+				 G_TYPE_INT, &backlight_kbd->priv->max_brightness,
+				 G_TYPE_INVALID);
+	if (error) {
+		egg_debug ("ERROR: %s", error->message);
+		g_error_free (error);
+	}
+	if (!ret) {
+		egg_warning ("GetMaxBrightness failed!");
+		return;
+	}
+
+	brightness = (backlight_kbd->priv->max_brightness *
+		      backlight_kbd->priv->master_percentage / 100);
+	egg_debug ("Setting brightness to %d", brightness);
+	/* set initial brightness to max */
+	ret = dbus_g_proxy_call (backlight_kbd->priv->proxy,
+				 "SetBrightness", &error,
+				 G_TYPE_INT, brightness,
+				 G_TYPE_INVALID, G_TYPE_INVALID);
+	if (error) {
+		egg_debug ("ERROR: %s", error->message);
+		g_error_free (error);
+	}
+	if (!ret) {
+		egg_warning ("SetBrightness failed!");
+	}
+
+	/* sync at startup */
+	gpm_backlight_kbd_brightness_evaluate_and_set (backlight_kbd, FALSE);
+
+}
+
+
+/**
+ * gpm_backlight_kbd_new:
+ * Return value: A new brightness class instance.
+ **/
+GpmBacklightKbd *
+gpm_backlight_kbd_new (void)
+{
+	GpmBacklightKbd *backlight_kbd = g_object_new (GPM_TYPE_BACKLIGHT_KBD, NULL);
+	return backlight_kbd;
+}
+
diff --git a/src/gpm-backlight-kbd.h b/src/gpm-backlight-kbd.h
new file mode 100644
index 0000000..500a5ea
--- /dev/null
+++ b/src/gpm-backlight-kbd.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Alex Murray <murray alex gmail com>
+ * Copyright (C) 2005-2007 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2004-2005 William Jon McCann <mccann jhu edu>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __GPM_BACKLIGHT_KBD_H
+#define __GPM_BACKLIGHT_KBD_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GPM_TYPE_BACKLIGHT_KBD		(gpm_backlight_kbd_get_type ())
+#define GPM_BACKLIGHT_KBD(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), GPM_TYPE_BACKLIGHT_KBD, GpmBacklightKbd))
+#define GPM_BACKLIGHT_KBD_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), GPM_TYPE_BACKLIGHT_KBD, GpmBacklightKbdClass))
+#define GPM_IS_BACKLIGHT_KBD(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), GPM_TYPE_BACKLIGHT_KBD))
+#define GPM_IS_BACKLIGHT_KBD_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), GPM_TYPE_BACKLIGHT_KBD))
+#define GPM_BACKLIGHT_KBD_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), GPM_TYPE_BACKLIGHT_KBD, GpmBacklightKbdClass))
+
+typedef struct GpmBacklightKbdPrivate GpmBacklightKbdPrivate;
+
+typedef struct
+{
+	GObject		         parent;
+	GpmBacklightKbdPrivate *priv;
+} GpmBacklightKbd;
+
+typedef struct
+{
+	GObjectClass	parent_class;
+} GpmBacklightKbdClass;
+
+GType		 gpm_backlight_kbd_get_type			(void);
+GpmBacklightKbd	*gpm_backlight_kbd_new			(void);
+
+G_END_DECLS
+
+#endif /* __GPM_BACKLIGHT_KBD_H */
+
diff --git a/src/gpm-manager.c b/src/gpm-manager.c
index ae441cc..af04728 100644
--- a/src/gpm-manager.c
+++ b/src/gpm-manager.c
@@ -54,6 +54,7 @@
 #include "gpm-manager.h"
 #include "gpm-screensaver.h"
 #include "gpm-backlight.h"
+#include "gpm-backlight-kbd.h"
 #include "gpm-session.h"
 #include "gpm-stock-icons.h"
 #include "gpm-prefs-server.h"
@@ -87,6 +88,7 @@ struct GpmManagerPrivate
 	GpmTrayIcon		*tray_icon;
 	GpmEngine		*engine;
 	GpmBacklight		*backlight;
+	GpmBacklightKbd		*backlight_kbd;
 	EggConsoleKit		*console;
 	guint32			 screensaver_ac_throttle_id;
 	guint32			 screensaver_dpms_throttle_id;
@@ -1993,6 +1995,7 @@ gpm_manager_init (GpmManager *manager)
 		dbus_g_connection_register_g_object (connection, GPM_DBUS_PATH_BACKLIGHT,
 						     G_OBJECT (manager->priv->backlight));
 	}
+	manager->priv->backlight_kbd = gpm_backlight_kbd_new ();
 
 	manager->priv->idle = gpm_idle_new ();
 	g_signal_connect (manager->priv->idle, "idle-changed",
@@ -2089,6 +2092,7 @@ gpm_manager_finalize (GObject *object)
 	g_object_unref (manager->priv->control);
 	g_object_unref (manager->priv->button);
 	g_object_unref (manager->priv->backlight);
+	g_object_unref (manager->priv->backlight_kbd);
 	g_object_unref (manager->priv->console);
 	g_object_unref (manager->priv->client);
 	g_object_unref (manager->priv->status_icon);
-- 
1.7.1



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]