--- /dev/null 2009-08-05 16:01:56.213259805 +0530 +++ dalston/gpm-popup-window.c 2009-08-05 17:42:32.000000000 +0530 @@ -0,0 +1,735 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2006-2007 William Jon McCann + * Copyright (C) 2009 Richard Hughes + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include "gpm-popup-window.h" +#include "dalston-brightness-manager.h" + +#define GPM_POPUP_WINDOW_DIALOG_TIMEOUT 2000 /* dialog timeout in ms */ +#define GPM_POPUP_WINDOW_DIALOG_FADE_TIMEOUT 1500 /* timeout before fade starts */ +#define GPM_POPUP_WINDOW_FADE_TIMEOUT 10 /* timeout in ms between each frame of the fade */ + +#define GPM_POPUP_WINDOW_BG_ALPHA 0.50 +#define GPM_POPUP_WINDOW_FG_ALPHA 1.00 + +#define GPM_POPUP_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPM_TYPE_POPUP_WINDOW, GpmPopupWindowPrivate)) + +struct GpmPopupWindowPrivate +{ + gboolean is_composited; + guint hide_timeout_id; + guint fade_timeout_id; + gdouble fade_out_alpha; + gfloat value; + gchar *icon_name; + GtkImage *image; + GtkWidget *progress; + GtkWidget *frame; + DalstonBrightnessManager *manager; +}; + +G_DEFINE_TYPE (GpmPopupWindow, gpm_popup_window, GTK_TYPE_WINDOW) + +/** + * gpm_popup_window_fade_timeout_cb: + **/ +static gboolean +gpm_popup_window_fade_timeout_cb (GpmPopupWindow *popup) +{ + if (popup->priv->fade_out_alpha <= 0.0) { + gtk_widget_hide (GTK_WIDGET (popup)); + + /* Reset it for the next time */ + popup->priv->fade_out_alpha = 1.0; + popup->priv->fade_timeout_id = 0; + + return FALSE; + } else { + GdkRectangle rect; + GtkWidget *widget = GTK_WIDGET (popup); + + popup->priv->fade_out_alpha -= 0.10; + + rect.x = 0; + rect.y = 0; + rect.width = widget->allocation.width; + rect.height = widget->allocation.height; + + gdk_window_invalidate_rect (widget->window, &rect, FALSE); + } + + return TRUE; +} + +/** + * gpm_popup_window_hide_timeout_cb: + **/ +static gboolean +gpm_popup_window_hide_timeout_cb (GpmPopupWindow *popup) +{ + if (popup->priv->is_composited) { + popup->priv->hide_timeout_id = 0; + popup->priv->fade_timeout_id = g_timeout_add (GPM_POPUP_WINDOW_FADE_TIMEOUT, + (GSourceFunc) gpm_popup_window_fade_timeout_cb, popup); + } else { + gtk_widget_hide (GTK_WIDGET (popup)); + } + + return FALSE; +} + +/** + * gpm_popup_window_remove_hide_timeout: + **/ +static void +gpm_popup_window_remove_hide_timeout (GpmPopupWindow *popup) +{ + if (popup->priv->hide_timeout_id != 0) { + g_source_remove (popup->priv->hide_timeout_id); + popup->priv->hide_timeout_id = 0; + } + + if (popup->priv->fade_timeout_id != 0) { + g_source_remove (popup->priv->fade_timeout_id); + popup->priv->fade_timeout_id = 0; + popup->priv->fade_out_alpha = 1.0; + } +} + +/** + * gpm_popup_window_add_hide_timeout: + **/ +static void +gpm_popup_window_add_hide_timeout (GpmPopupWindow *popup) +{ + guint timeout; + if (popup->priv->is_composited) { + timeout = GPM_POPUP_WINDOW_DIALOG_FADE_TIMEOUT; + } else { + timeout = GPM_POPUP_WINDOW_DIALOG_TIMEOUT; + } + popup->priv->hide_timeout_id = g_timeout_add (timeout, (GSourceFunc) gpm_popup_window_hide_timeout_cb, popup); +} + +/** + * gpm_popup_window_update_window: + **/ +static void +gpm_popup_window_update_window (GpmPopupWindow *popup) +{ + gpm_popup_window_remove_hide_timeout (popup); + gpm_popup_window_add_hide_timeout (popup); + + if (popup->priv->is_composited) + gtk_widget_queue_draw (GTK_WIDGET (popup)); +} + +/** + * gpm_popup_window_set_icon_name: + **/ +void +gpm_popup_window_set_icon_name (GpmPopupWindow *popup, const gchar *icon_name) +{ + g_return_if_fail (GPM_IS_POPUP_WINDOW (popup)); + g_free (popup->priv->icon_name); + popup->priv->icon_name = g_strdup (icon_name); + if (popup->priv->image != NULL) + gtk_image_set_from_icon_name (popup->priv->image, icon_name, GTK_ICON_SIZE_DIALOG); +} + +/** + * gpm_popup_window_set_value: + **/ +void +gpm_popup_window_set_value (GpmPopupWindow *popup, gfloat level) +{ + g_return_if_fail (GPM_IS_POPUP_WINDOW (popup)); + + if (popup->priv->value != level) { + popup->priv->value = level; + gpm_popup_window_update_window (popup); + + /* set value straight away */ + if (!popup->priv->is_composited && popup->priv->progress != NULL) + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (popup->priv->progress), popup->priv->value); + } +} + +/** + * gpm_popup_window_curved_rectangle: + **/ +static void +gpm_popup_window_curved_rectangle (cairo_t *cr, gdouble x, gdouble y, gdouble width, gdouble height, gdouble radius) +{ + gdouble xw; + gdouble yh; + + xw = x + width; + yh = y + height; + + if (!width || !height) { + goto out; + } + + if (width / 2 < radius) { + if (height / 2 < radius) { + cairo_move_to (cr, x, (y + yh) / 2); + cairo_curve_to (cr, x ,y, x, y, (x + xw) / 2, y); + cairo_curve_to (cr, xw, y, xw, y, xw, (y + yh) / 2); + cairo_curve_to (cr, xw, yh, xw, yh, (xw + x) / 2, yh); + cairo_curve_to (cr, x, yh, x, yh, x, (y + yh) / 2); + } else { + cairo_move_to (cr, x, y + radius); + cairo_curve_to (cr, x, y, x, y, (x + xw) / 2, y); + cairo_curve_to (cr, xw, y, xw, y, xw, y + radius); + cairo_line_to (cr, xw, yh - radius); + cairo_curve_to (cr, xw, yh, xw, yh, (xw + x) / 2, yh); + cairo_curve_to (cr, x, yh, x, yh, x, yh - radius); + } + } else { + if (height / 2 < radius) { + cairo_move_to (cr, x, (y + yh) / 2); + cairo_curve_to (cr, x, y, x , y, x + radius, y); + cairo_line_to (cr, xw - radius, y); + cairo_curve_to (cr, xw, y, xw, y, xw, (y + yh) / 2); + cairo_curve_to (cr, xw, yh, xw, yh, xw - radius, yh); + cairo_line_to (cr, x + radius, yh); + cairo_curve_to (cr, x, yh, x, yh, x, (y + yh) / 2); + } else { + cairo_move_to (cr, x, y + radius); + cairo_curve_to (cr, x , y, x , y, x + radius, y); + cairo_line_to (cr, xw - radius, y); + cairo_curve_to (cr, xw, y, xw, y, xw, y + radius); + cairo_line_to (cr, xw, yh - radius); + cairo_curve_to (cr, xw, yh, xw, yh, xw - radius, yh); + cairo_line_to (cr, x + radius, yh); + cairo_curve_to (cr, x, yh, x, yh, x, yh - radius); + } + } +out: + cairo_close_path (cr); +} + +/** + * gpm_popup_window_load_pixbuf: + **/ +static GdkPixbuf * +gpm_popup_window_load_pixbuf (GpmPopupWindow *popup, const gchar *icon_name, gint icon_size) +{ + GtkIconTheme *theme; + GdkPixbuf *pixbuf = NULL; + guint width; + + if (icon_name == NULL) + goto out; + + g_debug ("rendering %s to a pixbuf", icon_name); + if (popup != NULL && gtk_widget_has_screen (GTK_WIDGET (popup))) { + theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (popup))); + } else { + theme = gtk_icon_theme_get_default (); + } + + /* make sure the pixbuf is close to the requested size + * this is necessary because GTK_ICON_LOOKUP_FORCE_SVG + * seems to be broken */ + pixbuf = gtk_icon_theme_load_icon (theme, icon_name, icon_size, GTK_ICON_LOOKUP_FORCE_SVG, NULL); + if (pixbuf != NULL) { + width = gdk_pixbuf_get_width (pixbuf); + if (width < (float)icon_size * 0.75) { + g_object_unref (pixbuf); + pixbuf = NULL; + } + } +out: + return pixbuf; +} + +/** + * gpm_popup_window_render_icon: + **/ +static gboolean +gpm_popup_window_render_icon (GpmPopupWindow *popup, cairo_t *cr, gdouble x, gdouble y, gdouble width, gdouble height) +{ + GdkPixbuf *pixbuf; + + /* get pixbuf */ + pixbuf = gpm_popup_window_load_pixbuf (popup, popup->priv->icon_name, (gint) width); + if (pixbuf == NULL) + return FALSE; + + /* render */ + gdk_cairo_set_source_pixbuf (cr, pixbuf, x, y); + cairo_paint_with_alpha (cr, GPM_POPUP_WINDOW_FG_ALPHA); + + g_object_unref (pixbuf); + return TRUE; +} + +/** + * gpm_popup_window_draw_progress_bar: + **/ +static void +gpm_popup_window_draw_progress_bar (GpmPopupWindow *popup, cairo_t *cr, gdouble percentage, + gdouble x, gdouble y, gdouble width, gdouble height) +{ + gdouble xw; + GdkColor color; + gdouble r, g, b; + + xw = width * percentage; + + /* bar background */ + color = GTK_WIDGET (popup)->style->dark [GTK_STATE_NORMAL]; + r = (float)color.red / 65535.0; + g = (float)color.green / 65535.0; + b = (float)color.blue / 65535.0; + cairo_rectangle (cr, x, y, width, height); + cairo_set_source_rgba (cr, r, g, b, GPM_POPUP_WINDOW_FG_ALPHA); + cairo_fill (cr); + + /* bar border */ + color = GTK_WIDGET (popup)->style->dark [GTK_STATE_SELECTED]; + r = (float)color.red / 65535.0; + g = (float)color.green / 65535.0; + b = (float)color.blue / 65535.0; + cairo_rectangle (cr, x, y, width, height); + cairo_set_source_rgba (cr, r, g, b, GPM_POPUP_WINDOW_FG_ALPHA); + cairo_set_line_width (cr, 1); + cairo_stroke (cr); + + /* bar progress */ + color = GTK_WIDGET (popup)->style->bg [GTK_STATE_SELECTED]; + r = (float)color.red / 65535.0; + g = (float)color.green / 65535.0; + b = (float)color.blue / 65535.0; + cairo_rectangle (cr, x, y, xw, height); + cairo_set_source_rgba (cr, r, g, b, GPM_POPUP_WINDOW_FG_ALPHA); + cairo_fill (cr); +} + +/** + * gpm_popup_window_draw_action: + **/ +static void +gpm_popup_window_draw_action (GpmPopupWindow *popup, cairo_t *cr) +{ + gint window_width; + gint window_height; + gdouble icon_box_width; + gdouble icon_box_height; + gdouble icon_box_x; + gdouble icon_box_y; + gdouble value_box_x; + gdouble value_box_y; + gdouble value_box_width; + gdouble value_box_height; + gboolean ret; + + gtk_window_get_size (GTK_WINDOW (popup), &window_width, &window_height); + + icon_box_width = window_width * 0.65; + icon_box_height = window_height * 0.65; + value_box_width = icon_box_width; + value_box_height = window_height * 0.05; + + icon_box_x = (window_width - icon_box_width) / 2; + icon_box_y = (window_height - icon_box_height - value_box_height) / 2; + value_box_x = icon_box_x; + value_box_y = icon_box_height + icon_box_y; + + ret = gpm_popup_window_render_icon (popup, cr, icon_box_x, icon_box_y, icon_box_width, icon_box_height); + if (!ret) + g_warning ("failed to render"); + + /* draw progress bar */ + gpm_popup_window_draw_progress_bar (popup, cr, popup->priv->value, + value_box_x, value_box_y, + value_box_width, value_box_height); +} + +/** + * gpm_popup_window_expose_event_cb: + **/ +static gboolean +gpm_popup_window_expose_event_cb (GtkWidget *widget, GdkEventExpose *event, GpmPopupWindow *popup) +{ + cairo_t *context; + cairo_t *cr; + cairo_surface_t *surface; + gint width; + gint height; + GdkColor color; + gdouble r, g, b; + + /* ignore for non-composite windows */ + if (!popup->priv->is_composited) + goto out; + + context = gdk_cairo_create (GTK_WIDGET (popup)->window); + + cairo_set_operator (context, CAIRO_OPERATOR_SOURCE); + gtk_window_get_size (GTK_WINDOW (widget), &width, &height); + + surface = cairo_surface_create_similar (cairo_get_target (context), + CAIRO_CONTENT_COLOR_ALPHA, + width, height); + + if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS) + goto done; + + cr = cairo_create (surface); + if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) + goto done; + + cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0); + cairo_set_operator (cr, CAIRO_OPERATOR_OVER); + cairo_paint (cr); + + /* draw a box */ + gpm_popup_window_curved_rectangle (cr, 0.5, 0.5, width-1, height-1, height / 10); + color = GTK_WIDGET (popup)->style->bg [GTK_STATE_NORMAL]; + r = (float)color.red / 65535.0; + g = (float)color.green / 65535.0; + b = (float)color.blue / 65535.0; + cairo_set_source_rgba (cr, r, g, b, GPM_POPUP_WINDOW_BG_ALPHA); + cairo_fill_preserve (cr); + + color = GTK_WIDGET (popup)->style->fg [GTK_STATE_NORMAL]; + r = (float)color.red / 65535.0; + g = (float)color.green / 65535.0; + b = (float)color.blue / 65535.0; + cairo_set_source_rgba (cr, r, g, b, GPM_POPUP_WINDOW_BG_ALPHA); + cairo_set_line_width (cr, 1); + cairo_stroke (cr); + + /* draw action */ + gpm_popup_window_draw_action (popup, cr); + + cairo_destroy (cr); + + /* Make sure we have a transparent background */ + cairo_rectangle (context, 0, 0, width, height); + cairo_set_source_rgba (context, 0.0, 0.0, 0.0, 0.0); + cairo_fill (context); + + cairo_set_source_surface (context, surface, 0, 0); + cairo_paint_with_alpha (context, popup->priv->fade_out_alpha); + +done: + if (surface != NULL) + cairo_surface_destroy (surface); + cairo_destroy (context); +out: + return FALSE; +} + +/** + * gpm_popup_window_move_to_screen_base: + **/ +static void +gpm_popup_window_move_to_screen_base (GtkWidget *widget) +{ + gint orig_w, orig_h; + gint screen_w, screen_h; + gint x, y; + gint pointer_x, pointer_y; + GtkRequisition widget_req; + GdkScreen *pointer_screen = NULL; + GdkRectangle geometry; + gint monitor = 0; + GdkScreen *current_screen; + + current_screen = gdk_screen_get_default (); + gtk_window_set_screen (GTK_WINDOW (widget), current_screen); + + /* 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 (widget), &orig_w, &orig_h); + gtk_widget_size_request (widget, &widget_req); + + if (widget_req.width > orig_w) + orig_w = widget_req.width; + if (widget_req.height > orig_h) + orig_h = widget_req.height; + + gdk_display_get_pointer (gdk_screen_get_display (current_screen), + &pointer_screen, &pointer_x, &pointer_y, NULL); + /* is the pointer is on the current screen */ + if (pointer_screen == current_screen) + monitor = gdk_screen_get_monitor_at_point (current_screen, pointer_x, pointer_y); + + /* get monitor size */ + gdk_screen_get_monitor_geometry (current_screen, monitor, &geometry); + screen_w = geometry.width; + screen_h = geometry.height; + + /* put two thirds down */ + 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 (widget), x, y); +} + +/** + * gpm_popup_window_show: + **/ +static void +gpm_popup_window_show (GtkWidget *widget) +{ + GpmPopupWindow *popup; + + /* put two thirds down */ + gpm_popup_window_move_to_screen_base (widget); + + if (GTK_WIDGET_CLASS (gpm_popup_window_parent_class)->show) + GTK_WIDGET_CLASS (gpm_popup_window_parent_class)->show (widget); + + popup = GPM_POPUP_WINDOW (widget); + gpm_popup_window_remove_hide_timeout (popup); + gpm_popup_window_add_hide_timeout (popup); +} + +/** + * gpm_popup_window_hide: + **/ +static void +gpm_popup_window_hide (GtkWidget *widget) +{ + GpmPopupWindow *popup; + + if (GTK_WIDGET_CLASS (gpm_popup_window_parent_class)->hide) + GTK_WIDGET_CLASS (gpm_popup_window_parent_class)->hide (widget); + + popup = GPM_POPUP_WINDOW (widget); + gpm_popup_window_remove_hide_timeout (popup); +} + +/** + * gpm_popup_window_realize: + **/ +static void +gpm_popup_window_realize (GtkWidget *widget) +{ + GdkColormap *colormap; + GdkBitmap *mask; + cairo_t *cr; + + colormap = gdk_screen_get_rgba_colormap (gtk_widget_get_screen (widget)); + + if (colormap != NULL) + gtk_widget_set_colormap (widget, colormap); + + if (GTK_WIDGET_CLASS (gpm_popup_window_parent_class)->realize) + GTK_WIDGET_CLASS (gpm_popup_window_parent_class)->realize (widget); + + mask = gdk_pixmap_new (widget->window, + widget->allocation.width, + widget->allocation.height, 1); + cr = gdk_cairo_create (mask); + + cairo_set_source_rgba (cr, 1.0f, 1.0f, 1.0f, 0.0f); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + + /* make the whole window ignore events */ + gdk_window_input_shape_combine_mask (widget->window, mask, 0, 0); + g_object_unref (mask); + cairo_destroy (cr); +} + +/** + * gpm_popup_window_finalize: + **/ +static void +gpm_popup_window_finalize (GObject *object) +{ + GpmPopupWindow *popup; + g_return_if_fail (object != NULL); + g_return_if_fail (GPM_IS_POPUP_WINDOW (object)); + + popup = GPM_POPUP_WINDOW (object); + popup->priv = GPM_POPUP_WINDOW_GET_PRIVATE (popup); + + g_free (popup->priv->icon_name); + if (popup->priv->hide_timeout_id != 0) + g_source_remove (popup->priv->hide_timeout_id); + if (popup->priv->fade_timeout_id != 0) + g_source_remove (popup->priv->fade_timeout_id); + + G_OBJECT_CLASS (gpm_popup_window_parent_class)->finalize (object); +} + +/** + * gpm_popup_window_class_init: + **/ +static void +gpm_popup_window_class_init (GpmPopupWindowClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->finalize = gpm_popup_window_finalize; + + widget_class->show = gpm_popup_window_show; + widget_class->hide = gpm_popup_window_hide; + widget_class->realize = gpm_popup_window_realize; + + g_type_class_add_private (klass, sizeof (GpmPopupWindowPrivate)); +} + +/** + * gpm_popup_window_setup: + **/ +static void +gpm_popup_window_setup (GpmPopupWindow *popup) +{ + gdouble scalew, scaleh, scale; + gint size; + GdkScreen *screen; + GtkBuilder *builder; + gchar **objects; + + /* remove non-composited frame */ + if (popup->priv->frame != NULL) { + gtk_container_remove (GTK_CONTAINER (popup), popup->priv->frame); + popup->priv->frame = NULL; + popup->priv->image = NULL; + popup->priv->progress = NULL; + } + + if (popup->priv->is_composited) { + + gtk_window_set_decorated (GTK_WINDOW (popup), FALSE); + gtk_widget_set_app_paintable (GTK_WIDGET (popup), TRUE); + + /* assume 130xw30 on a 640x480 display and scale from there */ + screen = gtk_widget_get_screen (GTK_WIDGET (popup)); + scalew = gdk_screen_get_width (screen) / 640.0; + scaleh = gdk_screen_get_height (screen) / 480.0; + scale = MIN (scalew, scaleh); + size = 130 * MAX (1, scale); + + gtk_widget_set_size_request (GTK_WIDGET (popup), size, size); + gtk_window_set_default_size (GTK_WINDOW (popup), size, size); + + } else { + builder = gtk_builder_new (); + objects = g_strsplit ("frame_popup", ",", -1); + gtk_builder_add_objects_from_file (builder, PKG_DATA_DIR "/gpm-feedback-widget.ui", objects, NULL); + g_strfreev (objects); + + /* setup non-composited window as a fallback */ + popup->priv->image = GTK_IMAGE (gtk_builder_get_object (builder, "image_popup")); + popup->priv->progress = GTK_WIDGET (gtk_builder_get_object (builder, "progressbar_popup")); + popup->priv->frame = GTK_WIDGET (gtk_builder_get_object (builder, "frame_popup")); + if (popup->priv->frame != NULL) { + gtk_container_add (GTK_CONTAINER (popup), popup->priv->frame); + gtk_widget_show_all (popup->priv->frame); + } + + /* if we're going from composited to non-composited, set this now */ + if (popup->priv->icon_name != NULL) + gtk_image_set_from_icon_name (popup->priv->image, popup->priv->icon_name, GTK_ICON_SIZE_DIALOG); + + gtk_widget_set_app_paintable (GTK_WIDGET (popup), FALSE); + gtk_widget_set_size_request (GTK_WIDGET (popup), -1, -1); + gtk_window_set_default_size (GTK_WINDOW (popup), -1, -1); + + /* stay alive until the window takes ownership of the frame (and its children) */ + g_object_unref (builder); + gtk_widget_hide (GTK_WIDGET (popup)); + } +} + +/** + * gpm_popup_window_screen_changed_cb: + **/ +static void +gpm_popup_window_screen_changed_cb (GdkScreen *screen, GpmPopupWindow *popup) +{ + popup->priv->is_composited = gdk_screen_is_composited (screen); + g_debug ("is_composited=%i", popup->priv->is_composited); + gpm_popup_window_setup (popup); +} + +/** + * gpm_popup_window_init: + **/ +static void +gpm_popup_window_init (GpmPopupWindow *popup) +{ + GdkScreen *screen; + + popup->priv = GPM_POPUP_WINDOW_GET_PRIVATE (popup); + popup->priv->fade_out_alpha = 1.0; + popup->priv->frame = NULL; + popup->priv->icon_name = g_strdup ("gpm-brightness-lcd"); + + gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), PKG_DATA_DIR G_DIR_SEPARATOR_S "icons"); + gtk_window_set_wmclass ((GtkWindow *)popup, "GpmPopupWindow", "hardware-osd"); + screen = gtk_widget_get_screen (GTK_WIDGET (popup)); + + popup->priv->is_composited = gdk_screen_is_composited (screen); + g_signal_connect (screen, "size-changed", G_CALLBACK (gpm_popup_window_screen_changed_cb), popup); + g_signal_connect (screen, "monitors-changed", G_CALLBACK (gpm_popup_window_screen_changed_cb), popup); + g_signal_connect (screen, "composited-changed", G_CALLBACK (gpm_popup_window_screen_changed_cb), popup); + + /* needed for composite window */ + g_signal_connect (popup, "expose-event", G_CALLBACK (gpm_popup_window_expose_event_cb), popup); + + /* setup window */ + gpm_popup_window_setup (popup); +} + +void +gpm_popup_window_refresh (GpmPopupWindow *window) +{ + dalston_brightness_manager_get_brightness (window->priv->manager); +} + +/** + * gpm_popup_window_new: + **/ +GtkWidget * +gpm_popup_window_new (gpointer manager) +{ + GObject *object; + GpmPopupWindow *popup; + + object = g_object_new (GPM_TYPE_POPUP_WINDOW, + "type", GTK_WINDOW_POPUP, + "type-hint", GDK_WINDOW_TYPE_HINT_NOTIFICATION, + "skip-taskbar-hint", TRUE, + "skip-pager-hint", TRUE, + "focus-on-map", FALSE, + NULL); + + popup = (GpmPopupWindow *)object; + + popup->priv->manager = manager; + + return GTK_WIDGET (object); +} --- /dev/null 2009-08-05 16:01:56.213259805 +0530 +++ dalston/gpm-popup-window.h 2009-08-05 19:08:54.000000000 +0530 @@ -0,0 +1,61 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2006 William Jon McCann + * Copyright (C) 2009 Richard Hughes + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef GPM_POPUP_WINDOW_H +#define GPM_POPUP_WINDOW_H + +#include +#include + +G_BEGIN_DECLS + +#define GPM_TYPE_POPUP_WINDOW (gpm_popup_window_get_type ()) +#define GPM_POPUP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GPM_TYPE_POPUP_WINDOW, GpmPopupWindow)) +#define GPM_POPUP_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GPM_TYPE_POPUP_WINDOW, GpmPopupWindowClass)) +#define GPM_IS_POPUP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GPM_TYPE_POPUP_WINDOW)) +#define GPM_IS_POPUP_WINDOW_CLASS(klass) (G_TYPE_INSTANCE_GET_CLASS ((klass), GPM_TYPE_POPUP_WINDOW)) + +typedef struct GpmPopupWindow GpmPopupWindow; +typedef struct GpmPopupWindowClass GpmPopupWindowClass; +typedef struct GpmPopupWindowPrivate GpmPopupWindowPrivate; + +struct GpmPopupWindow +{ + GtkWindow parent; + GpmPopupWindowPrivate *priv; +}; + +struct GpmPopupWindowClass +{ + GtkWindowClass parent_class; +}; + +GType gpm_popup_window_get_type (void); +GtkWidget *gpm_popup_window_new (gpointer foo); +void gpm_popup_window_set_icon_name (GpmPopupWindow *popup, + const gchar *icon_name); +void gpm_popup_window_set_value (GpmPopupWindow *popup, + gfloat value); +void gpm_popup_window_refresh (GpmPopupWindow *window); +G_END_DECLS + +#endif --- /dev/null 2009-08-05 16:01:56.213259805 +0530 +++ dalston/dalston-hal-key-monitor.c 2009-08-05 19:10:23.000000000 +0530 @@ -0,0 +1,313 @@ +/* + * Dalston - power and volume applets for Moblin + * Copyright (C) 2009, Intel Corporation. + * + * Authors: Rob Bradford + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include "dalston-hal-key-monitor.h" + +#include +#include +#include + +G_DEFINE_TYPE (DalstonHalKeyMonitor, dalston_hal_key_monitor, G_TYPE_OBJECT) + +#define GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), DALSTON_TYPE_HAL_KEY_MONITOR, DalstonHalKeyMonitorPrivate)) + +typedef struct _DalstonHalKeyMonitorPrivate DalstonHalKeyMonitorPrivate; + +struct _DalstonHalKeyMonitorPrivate { + HalPowerProxy *power_proxy; + HalManager *manager; + GList *devices; + gboolean is_hal_running; + GpmPopupWindow *window; +}; + +static void +dalston_hal_key_monitor_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +dalston_hal_key_monitor_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +_cleanup_hal_key_devices (DalstonHalKeyMonitor *self) +{ + DalstonHalKeyMonitorPrivate *priv = GET_PRIVATE (self); + GList *l = NULL; + HalDevice *device = NULL; + + for (l = priv->devices; l; l = g_list_delete_link (l, l)) + { + device = (HalDevice *)l->data; + + if (device) + { + g_object_unref (device); + } + } + + priv->devices = l; +} + +static void +dalston_hal_key_monitor_dispose (GObject *object) +{ + DalstonHalKeyMonitorPrivate *priv = GET_PRIVATE (object); + + if (priv->power_proxy) + { + g_object_unref (priv->power_proxy); + priv->power_proxy = NULL; + } + + if (priv->manager) + { + g_object_unref (priv->manager); + priv->manager = NULL; + } + + /* yes, we are sure it's a DalstonButtonMonitor */ + _cleanup_hal_key_devices ((DalstonHalKeyMonitor *)object); + + G_OBJECT_CLASS (dalston_hal_key_monitor_parent_class)->dispose (object); +} + +static void +dalston_hal_key_monitor_finalize (GObject *object) +{ + G_OBJECT_CLASS (dalston_hal_key_monitor_parent_class)->finalize (object); +} + +static void +dalston_hal_key_monitor_class_init (DalstonHalKeyMonitorClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (DalstonHalKeyMonitorPrivate)); + + object_class->get_property = dalston_hal_key_monitor_get_property; + object_class->set_property = dalston_hal_key_monitor_set_property; + object_class->dispose = dalston_hal_key_monitor_dispose; + object_class->finalize = dalston_hal_key_monitor_finalize; +} + + +static void +_device_condition_cb (HalDevice *device, + const gchar *condition, + const gchar *details, + gpointer userdata) +{ + DalstonHalKeyMonitor *monitor = (DalstonHalKeyMonitor *)userdata; + DalstonHalKeyMonitorPrivate *priv = GET_PRIVATE (monitor); + gchar *type = NULL; + GError *error = NULL; + gboolean state = FALSE; + gboolean has_state = FALSE; + + printf("COND: %s\n", condition); + if (!g_str_equal (condition, "ButtonPressed")) + { + /* Not expecting another event...*/ + return; + } + + g_warning (G_STRLOC "_device_condition_cb"); + g_warning (G_STRLOC "key details: %s", details); + + if (strcmp(details, "brightness-up") == 0 || + strcmp (details, "brightness-down") == 0) { + gtk_widget_show ((GtkWidget *)priv->window); + gpm_popup_window_refresh(priv->window); + return; + } + if (!hal_device_get_string (device, + "button.type", + &type, + &error)) + { + g_warning (G_STRLOC ": Getting type failed: %s", + error->message); + g_clear_error (&error); + g_free (type); + return; + } + printf("keu %s\n", type); + g_warning (G_STRLOC "key type: %s", type); + + if (g_str_equal (type, "sleep") || g_str_equal (type, "lid")) + { + g_debug (G_STRLOC ": Got lid button signal"); + + hal_device_get_bool (device, + "button.has_state", + &has_state, + &error); + + if (error) + { + g_warning (G_STRLOC ": Error getting if button has state: %s", + error->message); + g_clear_error (&error); + } else { + if (has_state) + { + hal_device_get_bool (device, + "button.state.value", + &state, + &error); + + if (error) + { + g_warning (G_STRLOC ": Error getting button state: %s", + error->message); + g_clear_error (&error); + } else { + g_debug (G_STRLOC ": Lid button has state: %s", + state ? "on" : "off"); + + if (state) + hal_power_proxy_suspend_sync (priv->power_proxy); + } + } else { + hal_power_proxy_suspend_sync (priv->power_proxy); + } + } + } + + g_free (type); +} + +static void +_setup_hal_key_devices (DalstonHalKeyMonitor *self) +{ + DalstonHalKeyMonitorPrivate *priv = GET_PRIVATE (self); + HalDevice *device; + + device = hal_device_new (); + hal_device_set_udi (device, "/org/freedesktop/Hal/devices/platform_i8042_i8042_KBD_port_logicaldev_input"); + hal_device_watch_condition (device); + g_signal_connect (device, + "device-condition", + (GCallback)_device_condition_cb, + self); + priv->devices = g_list_append (priv->devices, device); + + device = hal_device_new (); + hal_device_set_udi (device, "/org/freedesktop/Hal/devices/computer_logicaldev_input_0"); + hal_device_watch_condition (device); + g_signal_connect (device, + "device-condition", + (GCallback)_device_condition_cb, + self); + priv->devices = g_list_append (priv->devices, device); + + +} + +static void +_hal_daemon_start (HalManager *manager, + DalstonHalKeyMonitor *self) +{ + DalstonHalKeyMonitorPrivate *priv = GET_PRIVATE (self); + + /* spurious signal ? */ + if (priv->is_hal_running) + return; + + _setup_hal_key_devices (self); + + priv->is_hal_running = TRUE; +} + +static void +_hal_daemon_stop (HalManager *manager, + DalstonHalKeyMonitor *self) +{ + DalstonHalKeyMonitorPrivate *priv = GET_PRIVATE (self); + + /* spurious signal ? */ + if (!priv->is_hal_running) + return; + + _cleanup_hal_key_devices (self); + + priv->is_hal_running = FALSE; +} + +static void +dalston_hal_key_monitor_init (DalstonHalKeyMonitor *self) +{ + DalstonHalKeyMonitorPrivate *priv = GET_PRIVATE (self); + + priv->power_proxy = hal_power_proxy_new (); + + if (!priv->power_proxy) + { + g_warning (G_STRLOC ": No power proxy; not listening for buttons."); + return; + } + + priv->manager = hal_manager_new (); + g_signal_connect (priv->manager, + "daemon-start", + G_CALLBACK (_hal_daemon_start), + self); + g_signal_connect (priv->manager, + "daemon-stop", + G_CALLBACK (_hal_daemon_stop), + self); + + priv->is_hal_running = FALSE; + if (hal_manager_is_running (priv->manager)) + { + priv->is_hal_running = TRUE; + _setup_hal_key_devices (self); + } +} + +DalstonHalKeyMonitor * +dalston_hal_key_monitor_new (GpmPopupWindow *window) +{ + DalstonHalKeyMonitor *monitor = g_object_new (DALSTON_TYPE_HAL_KEY_MONITOR, NULL); + DalstonHalKeyMonitorPrivate *priv = GET_PRIVATE (monitor); + + priv->window = window; + + return monitor; +} + + --- /dev/null 2009-08-05 16:01:56.213259805 +0530 +++ dalston/dalston-hal-key-monitor.h 2009-08-05 19:05:33.000000000 +0530 @@ -0,0 +1,63 @@ +/* + * Dalston - power and volume applets for Moblin + * Copyright (C) 2009, Intel Corporation. + * + * Authors: Rob Bradford + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + + +#ifndef _DALSTON_HAL_KEY_MONITOR +#define _DALSTON_HAL_KEY_MONITOR + +#include +#include "gpm-popup-window.h" + +G_BEGIN_DECLS + +#define DALSTON_TYPE_HAL_KEY_MONITOR dalston_hal_key_monitor_get_type() + +#define DALSTON_HAL_KEY_MONITOR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), DALSTON_TYPE_HAL_KEY_MONITOR, DalstonHalKeyMonitor)) + +#define DALSTON_HAL_KEY_MONITOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), DALSTON_TYPE_HAL_KEY_MONITOR, DalstonHalKeyMonitorClass)) + +#define DALSTON_IS_HAL_KEY_MONITOR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DALSTON_TYPE_HAL_KEY_MONITOR)) + +#define DALSTON_IS_HAL_KEY_MONITOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), DALSTON_TYPE_HAL_KEY_MONITOR)) + +#define DALSTON_HAL_KEY_MONITOR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), DALSTON_TYPE_HAL_KEY_MONITOR, DalstonHalkeyMonitorClass)) + +typedef struct { + GObject parent; +} DalstonHalKeyMonitor; + +typedef struct { + GObjectClass parent_class; +} DalstonHalKeyMonitorClass; + +GType dalston_hal_key_monitor_get_type (void); + +DalstonHalKeyMonitor *dalston_hal_key_monitor_new (GpmPopupWindow *window); + +G_END_DECLS + +#endif /* _DALSTON_HAL_KEY_MONITOR */ + --- /dev/null 2009-08-05 16:01:56.213259805 +0530 +++ data/gpm-feedback-widget.ui 2009-08-05 05:26:21.000000000 +0530 @@ -0,0 +1,43 @@ + + + + + + Brightness + notification + + + True + 0 + out + + + True + 12 + 6 + + + True + 6 + + + 0 + + + + + True + 0.10000000149 + + + False + False + 1 + + + + + + + + --- /dev/null 2009-08-05 16:01:56.213259805 +0530 +++ data/icons/gpm-brightness-lcd.svg 2009-08-05 06:14:14.000000000 +0530 @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +