diff options
-rw-r--r-- | data/org.mate.power-manager.gschema.xml.in | 20 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/gpm-common.c | 46 | ||||
-rw-r--r-- | src/gpm-common.h | 11 | ||||
-rw-r--r-- | src/gpm-idle.c | 1 | ||||
-rw-r--r-- | src/gpm-kbd-backlight.c | 734 | ||||
-rw-r--r-- | src/gpm-kbd-backlight.h | 79 | ||||
-rw-r--r-- | src/gpm-manager.c | 12 |
8 files changed, 905 insertions, 0 deletions
diff --git a/data/org.mate.power-manager.gschema.xml.in b/data/org.mate.power-manager.gschema.xml.in index 99ee820..dcd2cd4 100644 --- a/data/org.mate.power-manager.gschema.xml.in +++ b/data/org.mate.power-manager.gschema.xml.in @@ -61,6 +61,26 @@ <_summary>Reduce the backlight brightness when on battery power</_summary> <_description>If the screen should be reduced in brightness when the computer is on battery power.</_description> </key> + <key name="kbd-backlight-battery-reduce" type="b"> + <default>true</default> + <summary>Reduce the keyboard backlight when on battery power</summary> + <description>If the keyboard backlight brightness should be reduced when the computer is on battery power</description> + </key> + <key name="kbd-brightness-on-ac" type="i"> + <default>100</default> + <summary>Keyboard backlight brightness when on AC power.</summary> + <description>Percent brightness to set keyboard backlight at when on AC power. Legal values are between 0 and 100.</description> + </key> + <key name="kbd-brightness-dim-by-on-battery" type="i"> + <default>50</default> + <summary>Percent to reduce keyboard backlight by when on battery power.</summary> + <description>The percentage to reduce the keyboard backlight by when on battery power. For example, if set to '60', the backlight will be cut by 40% on battery power. Legal values are between 0 and 100.</description> + </key> + <key name="kbd-brightness-dim-by-on-idle" type="i"> + <default>75</default> + <summary>Percent to reduce keyboard backlight by when idle.</summary> + <description>The percentage to reduce the keyboard backlight by when idle. For example, if set to '60', the backlight will be cut by 40% when idle. Legal values are between 0 and 100.</description> + </key> <key name="idle-brightness" type="i"> <default>30</default> <_summary>The brightness of the screen when idle</_summary> diff --git a/src/Makefile.am b/src/Makefile.am index 2fdf9d0..6393bbd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -158,6 +158,8 @@ mate_power_manager_SOURCES = \ gpm-control.c \ gpm-button.h \ gpm-button.c \ + gpm-kbd-backlight.h \ + gpm-kbd-backlight.c \ gpm-main.c \ gpm-manager.h \ gpm-manager.c \ diff --git a/src/gpm-common.c b/src/gpm-common.c index 861837a..e7d1d66 100644 --- a/src/gpm-common.c +++ b/src/gpm-common.c @@ -79,6 +79,52 @@ gpm_get_timestring (guint time_secs) } /** + * gpm_discrete_from_percent: + * @percentage: The percentage to convert + * @levels: The number of discrete levels + * + * We have to be carefull when converting from %->discrete as precision is very + * important if we want the highest value. + * + * Return value: The discrete value for this percentage. + **/ +guint +gpm_discrete_from_percent (guint percentage, guint levels) +{ + /* check we are in range */ + if (percentage > 100) + return levels; + if (levels == 0) { + g_warning ("levels is 0!"); + return 0; + } + return (guint) ((((gfloat) percentage * (gfloat) (levels - 1)) / 100.0f) + 0.5f); +} + +/** + * gpm_discrete_to_percent: + * @hw: The discrete level + * @levels: The number of discrete levels + * + * We have to be carefull when converting from discrete->%. + * + * Return value: The percentage for this discrete value. + **/ +guint +gpm_discrete_to_percent (guint discrete, guint levels) +{ + /* check we are in range */ + if (discrete > levels) + return 100; + if (levels == 0) { + g_warning ("levels is 0!"); + return 0; + } + return (guint) (((gfloat) discrete * (100.0f / (gfloat) (levels - 1))) + 0.5f); +} + + +/** * gpm_help_display: * @link_id: Subsection of mate-power-manager help section **/ diff --git a/src/gpm-common.h b/src/gpm-common.h index 48bb89d..ca4762c 100644 --- a/src/gpm-common.h +++ b/src/gpm-common.h @@ -31,6 +31,7 @@ G_BEGIN_DECLS #define GPM_DBUS_INTERFACE_BACKLIGHT "org.mate.PowerManager.Backlight" #define GPM_DBUS_PATH "/org/mate/PowerManager" #define GPM_DBUS_PATH_BACKLIGHT "/org/mate/PowerManager/Backlight" +#define GPM_DBUS_PATH_KBD_BACKLIGHT "/org/mate/PowerManager/KbdBacklight" /* common descriptions of this program */ #define GPM_NAME _("Power Manager") @@ -59,6 +60,12 @@ G_BEGIN_DECLS #define GPM_SETTINGS_BRIGHTNESS_AC "brightness-ac" #define GPM_SETTINGS_BRIGHTNESS_DIM_BATT "brightness-dim-battery" +/* keyboard backlight */ +#define GPM_SETTINGS_KBD_BACKLIGHT_BATT_REDUCE "kbd-backlight-battery-reduce" +#define GPM_SETTINGS_KBD_BRIGHTNESS_ON_AC "kbd-brightness-on-ac" +#define GPM_SETTINGS_KBD_BRIGHTNESS_DIM_BY_ON_BATT "kbd-brightness-dim-by-on-battery" +#define GPM_SETTINGS_KBD_BRIGHTNESS_DIM_BY_ON_IDLE "kbd-brightness-dim-by-on-idle" + /* buttons */ #define GPM_SETTINGS_BUTTON_LID_AC "button-lid-ac" #define GPM_SETTINGS_BUTTON_LID_BATT "button-lid-battery" @@ -149,6 +156,10 @@ typedef enum { } GpmActionPolicy; gchar *gpm_get_timestring (guint time); +guint gpm_discrete_from_percent (guint percentage, + guint levels); +guint gpm_discrete_to_percent (guint discrete, + guint levels); void gpm_help_display (const gchar *link_id); #ifdef EGG_TEST void gpm_common_test (gpointer data); diff --git a/src/gpm-idle.c b/src/gpm-idle.c index 0a7c33c..97e9072 100644 --- a/src/gpm-idle.c +++ b/src/gpm-idle.c @@ -352,6 +352,7 @@ static void gpm_idle_session_idle_changed_cb (GpmSession *session, gboolean is_idle, GpmIdle *idle) { egg_debug ("Received mate session idle changed: %i", is_idle); + idle->priv->x_idle = TRUE; gpm_idle_evaluate (idle); } diff --git a/src/gpm-kbd-backlight.c b/src/gpm-kbd-backlight.c new file mode 100644 index 0000000..4ed3fcf --- /dev/null +++ b/src/gpm-kbd-backlight.c @@ -0,0 +1,734 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2010 Alex Launi <alex launi canonical com> + * + * 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. + */ + +#include <gio/gio.h> +#include <glib.h> +#include <libupower-glib/upower.h> + +#include "gpm-button.h" +#include "gpm-common.h" +#include "gpm-control.h" +#include "gpm-idle.h" +#include "gpm-kbd-backlight.h" + +static const gchar *kbd_backlight_introspection = "" +"<?xml version=\"1.0\" encoding=\"UTF-8\"?>""<node name=\"/\">" + "<interface name=\"org.mate.PowerManager.Backlight\">" + "<method name=\"GetBrightness\">" + "<arg type=\"u\" name=\"percentage_brightness\" direction=\"out\"/>" + "</method>" + "<method name=\"SetBrightness\">" + "<arg type=\"u\" name=\"percentage_brightness\" direction=\"in\"/>" + "</method>" + "<signal name=\"BrightnessChanged\">" + "<arg type=\"u\" name=\"percentage_brightness\" direction=\"out\"/>" + "</signal>" + "</interface>" +"</node>"; + +#define GPM_KBD_BACKLIGHT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPM_TYPE_KBD_BACKLIGHT, GpmKbdBacklightPrivate)) + +struct GpmKbdBacklightPrivate +{ + UpClient *client; + GpmButton *button; + GSettings *settings; + GSettings *settings_gsd; + GpmControl *control; + GpmIdle *idle; + gboolean can_dim; + gboolean system_is_idle; + GTimer *idle_timer; + guint idle_dim_timeout; + guint master_percentage; + guint brightness; + guint max_brightness; + guint brightness_percent; + GDBusProxy *upower_proxy; + GDBusConnection *bus_connection; + guint bus_object_id; +}; + +enum { + BRIGHTNESS_CHANGED, + LAST_SIGNAL +}; + +static guint signals [LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE (GpmKbdBacklight, gpm_kbd_backlight, G_TYPE_OBJECT) + +/** + * gpm_kbd_backlight_error_quark: + * Return value: Our personal error quark. + **/ +GQuark +gpm_kbd_backlight_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("gpm_kbd_backlight_error"); + return quark; +} + +/** + * gpm_kbd_backlight_get_brightness: + * @backlight: + * @brightness: + * @error: + * + * Return value: + */ +gboolean +gpm_kbd_backlight_get_brightness (GpmKbdBacklight *backlight, + guint *brightness, + GError **error) +{ + g_return_val_if_fail (backlight != NULL, FALSE); + g_return_val_if_fail (GPM_IS_KBD_BACKLIGHT (backlight), FALSE); + g_return_val_if_fail (brightness != NULL, FALSE); + + if (backlight->priv->can_dim == FALSE) { + g_set_error_literal (error, gpm_kbd_backlight_error_quark (), + GPM_KBD_BACKLIGHT_ERROR_HARDWARE_NOT_PRESENT, + "Dim capable hardware not present"); + return FALSE; + } + + *brightness = backlight->priv->brightness_percent; + return TRUE; +} + +static gboolean +gpm_kbd_backlight_set (GpmKbdBacklight *backlight, + guint percentage) +{ + gint scale; + guint goal; + + g_return_val_if_fail (GPM_IS_KBD_BACKLIGHT (backlight), FALSE); + /* if we're setting the same we are, don't bother */ + //g_return_val_if_fail (backlight->priv->brightness_percent != percentage, FALSE); + + goal = gpm_discrete_from_percent (percentage, backlight->priv->max_brightness); + scale = percentage > backlight->priv->brightness_percent ? 1 : -1; + + /* step loop down by 1 for a dimming effect */ + while (backlight->priv->brightness != goal) { + backlight->priv->brightness += scale; + backlight->priv->brightness_percent = gpm_discrete_to_percent (backlight->priv->brightness, backlight->priv->max_brightness); + + g_dbus_proxy_call (backlight->priv->upower_proxy, + "SetBrightness", + g_variant_new ("(i)", (gint) backlight->priv->brightness), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + NULL, + NULL); + } + + return TRUE; +} + +/** + * gpm_kbd_backlight_brightness_up: + **/ +static gboolean +gpm_kbd_backlight_brightness_up (GpmKbdBacklight *backlight) +{ + guint new; + + new = MIN (backlight->priv->brightness_percent + GPM_KBD_BACKLIGHT_STEP, 100u); + return gpm_kbd_backlight_set (backlight, new); +} + +/** + * gpm_kbd_backlight_brightness_down: + **/ +static gboolean +gpm_kbd_backlight_brightness_down (GpmKbdBacklight *backlight) +{ + guint new; + + // we can possibly go below 0 here, so by converting to a gint we avoid underflow errors. + new = MAX ((gint) backlight->priv->brightness_percent - GPM_KBD_BACKLIGHT_STEP, 0); + return gpm_kbd_backlight_set (backlight, new); +} + +/** + * gpm_kbd_backlight_set_brightness: + * @backlight: + * @percentage: + * @error: + * + * Return value: + **/ +gboolean +gpm_kbd_backlight_set_brightness (GpmKbdBacklight *backlight, + guint percentage, + GError **error) +{ + gboolean ret; + + g_return_val_if_fail (backlight != NULL, FALSE); + g_return_val_if_fail (GPM_IS_KBD_BACKLIGHT (backlight), FALSE); + + if (backlight->priv->can_dim == FALSE) { + g_set_error_literal (error, gpm_kbd_backlight_error_quark (), + GPM_KBD_BACKLIGHT_ERROR_HARDWARE_NOT_PRESENT, + "Dim capable hardware not present"); + return FALSE; + } + + backlight->priv->master_percentage = percentage; + + ret = gpm_kbd_backlight_set (backlight, percentage); + if (!ret) { + g_set_error_literal (error, gpm_kbd_backlight_error_quark (), + GPM_KBD_BACKLIGHT_ERROR_GENERAL, + "Cannot set keyboard backlight brightness"); + } + + return ret; +} + +static void +gpm_kbd_backlight_on_brightness_changed (GpmKbdBacklight *backlight, + guint value) +{ + backlight->priv->brightness = value; + backlight->priv->brightness_percent = gpm_discrete_to_percent (value, backlight->priv->max_brightness); + backlight->priv->master_percentage = backlight->priv->brightness_percent; + g_signal_emit (backlight, signals [BRIGHTNESS_CHANGED], 0, backlight->priv->brightness_percent); +} + +/** + * gpm_kbd_backlight_on_dbus_signal: + **/ +static void +gpm_kbd_backlight_on_dbus_signal (GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + guint value; + GpmKbdBacklight *backlight = GPM_KBD_BACKLIGHT (user_data); + + if (g_strcmp0 (signal_name, "BrightnessChanged") == 0) { + g_variant_get (parameters, "(i)", &value); + gpm_kbd_backlight_on_brightness_changed (backlight, value); + return; + } + + g_assert_not_reached (); +} + +/** + * gpm_kbd_backlight_dbus_method_call: + * @connection: + * @object_path: + * @interface_name: + * @method_name: + * @parameters: + * @invocation: + * @user_data: + **/ +static void +gpm_kbd_backlight_dbus_method_call (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + guint value; + gboolean ret; + GError *error = NULL; + GpmKbdBacklight *backlight = GPM_KBD_BACKLIGHT (user_data); + + if (g_strcmp0 (method_name, "GetBrightness") == 0) { + ret = gpm_kbd_backlight_get_brightness (backlight, &value, &error); + if (!ret) { + g_dbus_method_invocation_return_gerror (invocation, error); + g_error_free (error); + } else { + g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", value)); + } + return; + } + + if (g_strcmp0 (method_name, "SetBrightness") == 0) { + g_variant_get (parameters, "(u)", &value); + ret = gpm_kbd_backlight_set_brightness (backlight, value, &error); + if (!ret) { + g_dbus_method_invocation_return_gerror (invocation, error); + g_error_free (error); + } else { + g_dbus_method_invocation_return_value (invocation, NULL); + } + return; + } + + g_assert_not_reached (); +} + + +/** + * gpm_kbd_backlight_dbus_property_get: + * @sender: + * @object_path: + * @interface_name: + * @property_name: + * @error: + * @user_data: + * + * Return value: + **/ +static GVariant * +gpm_kbd_backlight_dbus_property_get (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GError **error, + gpointer user_data) +{ + /* Do nothing, we have no props */ + return NULL; +} + +/** + * gpm_kbd_backlight_dbus_property_set: + * @connection: + * @sender: + * @object_path: + * @interface_name: + * @property_name: + * + * Return value: + **/ +static gboolean +gpm_kbd_backlight_dbus_property_set (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GVariant *value, + GError **error, + gpointer user_data) +{ + /* do nothing, no properties defined */ + return FALSE; +} + +/** + * gpm_kbd_backlight_register_dbus: + * @backlight: + * @connection: + * @error: + **/ +void +gpm_kbd_backlight_register_dbus (GpmKbdBacklight *backlight, + GDBusConnection *connection, + GError **error) +{ + GDBusNodeInfo *node_info; + GDBusInterfaceInfo *interface_info; + GDBusInterfaceVTable interface_vtable = { + gpm_kbd_backlight_dbus_method_call, + gpm_kbd_backlight_dbus_property_get, + gpm_kbd_backlight_dbus_property_set + }; + + node_info = g_dbus_node_info_new_for_xml (kbd_backlight_introspection, NULL); + interface_info = g_dbus_node_info_lookup_interface (node_info, GPM_DBUS_INTERFACE_BACKLIGHT); + + backlight->priv->bus_connection = g_object_ref (connection); + backlight->priv->bus_object_id = + g_dbus_connection_register_object (connection, + GPM_DBUS_PATH_KBD_BACKLIGHT, + interface_info, + &interface_vtable, + backlight, + NULL, + error); + g_dbus_node_info_unref (node_info); +} + +static gboolean +gpm_kbd_backlight_evaluate_power_source_and_set (GpmKbdBacklight *backlight) +{ + gfloat brightness; + gfloat scale; + gboolean on_battery; + gboolean battery_reduce; + guint value; + gboolean ret; + + brightness = backlight->priv->master_percentage; + + g_object_get (backlight->priv->client, + "on-battery", + &on_battery, + NULL); + + battery_reduce = g_settings_get_boolean (backlight->priv->settings, GPM_SETTINGS_KBD_BACKLIGHT_BATT_REDUCE); + + if (on_battery && battery_reduce) { + value = g_settings_get_int (backlight->priv->settings, GPM_SETTINGS_KBD_BRIGHTNESS_DIM_BY_ON_BATT); + + if (value > 100) { + g_warning ("Cannot scale brightness down by more than 100%%. Scaling by 50%%"); + value = 50; + } + + scale = (100 - value) / 100.0f; + brightness *= scale; + + value = (guint) brightness; + + } else { + value = g_settings_get_int (backlight->priv->settings, GPM_SETTINGS_KBD_BRIGHTNESS_ON_AC); + } + + ret = gpm_kbd_backlight_set (backlight, value); + return ret; +} + +/** + * gpm_kbd_backlight_control_resume_cb: + * @control: The control class instance + * @backlight: This backlight class instance + * + * Just make sure that the backlight is back on + **/ +static void +gpm_kbd_backlight_control_resume_cb (GpmControl *control, + GpmControlAction action, + GpmKbdBacklight *backlight) +{ + gboolean ret; + + ret = gpm_kbd_backlight_evaluate_power_source_and_set (backlight); + if (!ret) + g_warning ("Failed to turn kbd brightness back on after resuming"); +} + +/** + * gpm_kbd_backlight_client_changed_cb: + * @client: The up_client class instance + * @backlight: This class instance + * + * Does the actions when the ac power source is inserted/removed. + **/ +static void +gpm_kbd_backlight_client_changed_cb (UpClient *client, + GpmKbdBacklight *backlight) +{ + gpm_kbd_backlight_evaluate_power_source_and_set (backlight); +} + +/** + * gpm_kbd_backlight_button_pressed_cb: + * @power: The power class instance + * @type: The button type, but here we only care about keyboard brightness buttons + * @backlight: This class instance + **/ +static void +gpm_kbd_backlight_button_pressed_cb (GpmButton *button, + const gchar *type, + GpmKbdBacklight *backlight) +{ + static guint saved_brightness; + + saved_brightness = backlight->priv->master_percentage; + + if (g_strcmp0 (type, GPM_BUTTON_KBD_BRIGHT_UP) == 0) { + gpm_kbd_backlight_brightness_up (backlight); + + } else if (g_strcmp0 (type, GPM_BUTTON_KBD_BRIGHT_DOWN) == 0) { + gpm_kbd_backlight_brightness_down (backlight); + + } else if (g_strcmp0 (type, GPM_BUTTON_KBD_BRIGHT_TOGGLE) == 0) { + if (backlight->priv->master_percentage == 0) { + /* backlight is off turn it back on */ + gpm_kbd_backlight_set (backlight, saved_brightness); + } else { + /* backlight is on, turn it off and save current value */ + saved_brightness = backlight->priv->master_percentage; + gpm_kbd_backlight_set (backlight, 0); + } + } +} + +/** + * gpm_kbd_backlight_idle_changed_cb: + * @idle: The idle class instance + * @mode: The idle mode, e.g. GPM_IDLE_MODE_BLANK + * @backlight: This class instance + * + * This callback is called when mate-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 +gpm_kbd_backlight_idle_changed_cb (GpmIdle *idle, + GpmIdleMode mode, + GpmKbdBacklight *backlight) +{ + gfloat brightness; + gfloat scale; + guint value; + gboolean lid_closed; + gboolean on_battery; + gboolean enable_action; + + lid_closed = gpm_button_is_lid_closed (backlight->priv->button); + + if (lid_closed) + return; + + g_object_get (backlight->priv->client, + "on-battery", + &on_battery, + NULL); + + enable_action = on_battery + ? g_settings_get_boolean (backlight->priv->settings_gsd, GPM_SETTINGS_IDLE_DIM_BATT) + : g_settings_get_boolean (backlight->priv->settings_gsd, GPM_SETTINGS_IDLE_DIM_AC); + + if (!enable_action) + return; + + if (mode == GPM_IDLE_MODE_NORMAL) { + backlight->priv->master_percentage = 100; + gpm_kbd_backlight_evaluate_power_source_and_set (backlight); + } else if (mode == GPM_IDLE_MODE_DIM) { + brightness = backlight->priv->master_percentage; + value = g_settings_get_int (backlight->priv->settings, GPM_SETTINGS_KBD_BRIGHTNESS_DIM_BY_ON_IDLE); + + if (value > 100) { + g_warning ("Cannot scale brightness down by more than 100%%. Scaling by 50%%"); + value = 50; + } + + scale = (100 - value) / 100.0f; + brightness *= scale; + + value = (guint) brightness; + gpm_kbd_backlight_set (backlight, value); + } else if (mode == GPM_IDLE_MODE_BLANK) { + gpm_kbd_backlight_set (backlight, 0u); + } +} + +/** + * gpm_kbd_backlight_finalize: + * @object: + **/ +static void +gpm_kbd_backlight_finalize (GObject *object) +{ + GpmKbdBacklight *backlight; + + g_return_if_fail (object != NULL); + g_return_if_fail (GPM_IS_KBD_BACKLIGHT (object)); + + backlight = GPM_KBD_BACKLIGHT (object); + + if (backlight->priv->upower_proxy != NULL) { + g_object_unref (backlight->priv->upower_proxy); + } + if (backlight->priv->bus_connection != NULL) { + g_dbus_connection_unregister_object (backlight->priv->bus_connection, + backlight->priv->bus_object_id); + g_object_unref (backlight->priv->bus_connection); + } + + g_timer_destroy (backlight->priv->idle_timer); + + g_object_unref (backlight->priv->control); + g_object_unref (backlight->priv->settings); + g_object_unref (backlight->priv->settings_gsd); + g_object_unref (backlight->priv->client); + g_object_unref (backlight->priv->button); + g_object_unref (backlight->priv->idle); + + g_return_if_fail (backlight->priv != NULL); + G_OBJECT_CLASS (gpm_kbd_backlight_parent_class)->finalize (object); +} + +/** + * gpm_kbd_backlight_class_init: + * @klass: + **/ +static void +gpm_kbd_backlight_class_init (GpmKbdBacklightClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->finalize = gpm_kbd_backlight_finalize; + + signals [BRIGHTNESS_CHANGED] = + g_signal_new ("brightness-changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GpmKbdBacklightClass, brightness_changed), + NULL, + NULL, + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, + 1, + G_TYPE_UINT); + + g_type_class_add_private (klass, sizeof (GpmKbdBacklightPrivate)); +} + +/** + * gpm_kbd_backlight_init: + * @backlight: This KbdBacklight class instance + * + * Initializes the KbdBacklight class. + **/ +static void +gpm_kbd_backlight_init (GpmKbdBacklight *backlight) +{ + GVariant *u_brightness; + GVariant *u_max_brightness; + GError *error = NULL; + + backlight->priv = GPM_KBD_BACKLIGHT_GET_PRIVATE (backlight); + + backlight->priv->upower_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + "org.freedesktop.UPower", + "/org/freedesktop/UPower/KbdBacklight", + "org.freedesktop.UPower.KbdBacklight", + NULL, + &error); + if (backlight->priv->upower_proxy == NULL) { + g_printerr ("Could not connect to UPower system bus: %s", error->message); + g_error_free (error); + goto err; + } + + g_signal_connect (backlight->priv->upower_proxy, + "g-signal", + G_CALLBACK (gpm_kbd_backlight_on_dbus_signal), + backlight); + + u_brightness = g_dbus_proxy_call_sync (backlight->priv->upower_proxy, + "GetBrightness", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (u_brightness == NULL) { + g_warning ("Failed to get brightness: %s", error->message); + g_error_free (error); + goto err; + } + + error = NULL; + u_max_brightness = g_dbus_proxy_call_sync (backlight->priv->upower_proxy, + "GetMaxBrightness", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (u_max_brightness == NULL) { + g_warning ("Failed to get max brightness: %s", error->message); + g_error_free (error); + g_variant_unref (u_brightness); + goto err; + } + + g_variant_get (u_brightness, "(i)", &backlight->priv->brightness); + g_variant_get (u_max_brightness, "(i)", &backlight->priv->max_brightness); + + backlight->priv->brightness_percent = gpm_discrete_to_percent (backlight->priv->brightness, + backlight->priv->max_brightness); + + g_variant_unref (u_brightness); + g_variant_unref (u_max_brightness); + goto noerr; + +err: + backlight->priv->brightness = 0; + backlight->priv->brightness_percent = 100; + backlight->priv->max_brightness = 0; + +noerr: + /* Initialize the master to full power. It will get scaled if needed */ + backlight->priv->master_percentage = 100u; + + backlight->priv->idle_timer = g_timer_new (); + backlight->priv->can_dim = backlight->priv->max_brightness > 1; + + /* Use upower for ac changed signal */ + backlight->priv->client = up_client_new (); + g_signal_connect (backlight->priv->client, "changed", + G_CALLBACK (gpm_kbd_backlight_client_changed_cb), backlight); + + backlight->priv->settings = g_settings_new (GPM_SETTINGS_SCHEMA); + //backlight->priv->settings_gsd = g_settings_new (GSD_SETTINGS_SCHEMA); + + /* watch for kbd brightness up and down button presses */ + backlight->priv->button = gpm_button_new (); + g_signal_connect (backlight->priv->button, "button-pressed", + G_CALLBACK (gpm_kbd_backlight_button_pressed_cb), backlight); + + backlight->priv->idle = gpm_idle_new (); + g_signal_connect (backlight->priv->idle, "idle-changed", + G_CALLBACK (gpm_kbd_backlight_idle_changed_cb), backlight); + + /* since gpm is just starting we can pretty safely assume that we're not idle */ + backlight->priv->system_is_idle = FALSE; + backlight->priv->idle_dim_timeout = g_settings_get_int (backlight->priv->settings_gsd, GPM_SETTINGS_IDLE_DIM_TIME); + gpm_idle_set_timeout_dim (backlight->priv->idle, backlight->priv->idle_dim_timeout); + + /* make sure we turn the keyboard backlight back on after resuming */ + backlight->priv->control = gpm_control_new (); + g_signal_connect (backlight->priv->control, "resume", + G_CALLBACK (gpm_kbd_backlight_control_resume_cb), backlight); + + /* set initial values for whether we're on AC or battery*/ + gpm_kbd_backlight_evaluate_power_source_and_set (backlight); +} + +/** + * gpm_kbd_backlight_new: + * Return value: A new GpmKbdBacklight class instance. + **/ +GpmKbdBacklight * +gpm_kbd_backlight_new (void) +{ + GpmKbdBacklight *backlight = g_object_new (GPM_TYPE_KBD_BACKLIGHT, NULL); + return backlight; +} + diff --git a/src/gpm-kbd-backlight.h b/src/gpm-kbd-backlight.h new file mode 100644 index 0000000..78975b5 --- /dev/null +++ b/src/gpm-kbd-backlight.h @@ -0,0 +1,79 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2010 Alex Launi <alex launi canonical com> + * + * 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_KBD_BACKLIGHT_H +#define __GPM_KBD_BACKLIGHT_H + +#include <gio/gio.h> +#include <glib.h> +#include <glib-object.h> + +G_BEGIN_DECLS + +#define GPM_TYPE_KBD_BACKLIGHT (gpm_kbd_backlight_get_type ()) +#define GPM_KBD_BACKLIGHT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GPM_TYPE_KBD_BACKLIGHT, GpmKbdBacklight)) +#define GPM_KBD_BACKLIGHT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GPM_TYPE_KBD_BACKLIGHT, GpmKbdBacklightClass)) +#define GPM_IS_KBD_BACKLIGHT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GPM_TYPE_KBD_BACKLIGHT)) +#define GPM_IS_KBD_BACKLIGHT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GPM_TYPE_KBD_BACKLIGHT)) +#define GPM_KBD_BACKLIGHT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GPM_TYPE_KBD_BACKLIGHT, GpmKbdBacklightClass)) + +#define GPM_KBD_BACKLIGHT_DIM_INTERVAL 5 /* ms */ +#define GPM_KBD_BACKLIGHT_STEP 10 /* change by 10% each step */ + +typedef struct GpmKbdBacklightPrivate GpmKbdBacklightPrivate; + +typedef struct +{ + GObject parent; + GpmKbdBacklightPrivate *priv; +} GpmKbdBacklight; + +typedef struct +{ + GObjectClass parent_class; + void (* brightness_changed) (GpmKbdBacklight *backlight, + gint brightness); +} GpmKbdBacklightClass; + +typedef enum +{ + GPM_KBD_BACKLIGHT_ERROR_GENERAL, + GPM_KBD_BACKLIGHT_ERROR_DATA_NOT_AVAILABLE, + GPM_KBD_BACKLIGHT_ERROR_HARDWARE_NOT_PRESENT +} GpmKbdBacklightError; + +GType gpm_kbd_backlight_get_type (void); +GQuark gpm_kbd_backlight_error_quark (void); +GpmKbdBacklight *gpm_kbd_backlight_new (void); +gboolean gpm_kbd_backlight_get_brightness (GpmKbdBacklight *backlight, + guint *brightness, + GError **error); +gboolean gpm_kbd_backlight_set_brightness (GpmKbdBacklight *backlight, + guint brightness, + GError **error); +void gpm_kbd_backlight_register_dbus (GpmKbdBacklight *backlight, + GDBusConnection *connection, + GError **error); + +G_END_DECLS + +#endif /* __GPM_KBD_BACKLIGHT_H */ + diff --git a/src/gpm-manager.c b/src/gpm-manager.c index 68ff788..9ee8781 100644 --- a/src/gpm-manager.c +++ b/src/gpm-manager.c @@ -53,6 +53,7 @@ #include "gpm-manager.h" #include "gpm-screensaver.h" #include "gpm-backlight.h" +#include "gpm-kbd-backlight.h" #include "gpm-session.h" #include "gpm-stock-icons.h" #include "gpm-tray-icon.h" @@ -84,6 +85,7 @@ struct GpmManagerPrivate GpmTrayIcon *tray_icon; GpmEngine *engine; GpmBacklight *backlight; + GpmKbdBacklight *kbd_backlight; EggConsoleKit *console; guint32 screensaver_ac_throttle_id; guint32 screensaver_dpms_throttle_id; @@ -1848,10 +1850,12 @@ gpm_manager_init (GpmManager *manager) gboolean check_type_cpu; gint timeout; DBusGConnection *connection; + GDBusConnection *g_connection; GError *error = NULL; manager->priv = GPM_MANAGER_GET_PRIVATE (manager); connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); + g_connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); /* init to unthrottled */ manager->priv->screensaver_ac_throttle_id = 0; @@ -1904,6 +1908,13 @@ gpm_manager_init (GpmManager *manager) G_OBJECT (manager->priv->backlight)); } + manager->priv->kbd_backlight = gpm_kbd_backlight_new (); + if (manager->priv->kbd_backlight != NULL) { + gpm_kbd_backlight_register_dbus (manager->priv->kbd_backlight, + g_connection, + NULL); + } + manager->priv->idle = gpm_idle_new (); g_signal_connect (manager->priv->idle, "idle-changed", G_CALLBACK (gpm_manager_idle_changed_cb), manager); @@ -1998,6 +2009,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->kbd_backlight); g_object_unref (manager->priv->console); g_object_unref (manager->priv->client); g_object_unref (manager->priv->status_icon); |