[gnome-power-manager: 1/3] Use the same composited OSD for brightness notification. Fixes rh#512968
- From: Richard Hughes <rhughes src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnome-power-manager: 1/3] Use the same composited OSD for brightness notification. Fixes rh#512968
- Date: Thu, 23 Jul 2009 11:16:59 +0000 (UTC)
commit d2251e9373add05113623c0a812a86bdd35d9116
Author: Richard Hughes <richard hughsie com>
Date: Thu Jul 23 12:05:43 2009 +0100
Use the same composited OSD for brightness notification. Fixes rh#512968
data/gpm-feedback-widget.ui | 11 +-
src/.gitignore | 1 +
src/Makefile.am | 4 +-
src/gpm-backlight.c | 33 ++-
src/gpm-feedback-widget.c | 239 --------------
src/gpm-feedback-widget.h | 59 ----
src/gpm-manager.c | 1 -
src/gpm-popup-window.c | 721 +++++++++++++++++++++++++++++++++++++++++++
src/gpm-popup-window.h | 61 ++++
9 files changed, 809 insertions(+), 321 deletions(-)
---
diff --git a/data/gpm-feedback-widget.ui b/data/gpm-feedback-widget.ui
index 0400adf..44702c3 100644
--- a/data/gpm-feedback-widget.ui
+++ b/data/gpm-feedback-widget.ui
@@ -2,22 +2,21 @@
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy toplevel-contextual -->
- <object class="GtkWindow" id="main_window">
- <property name="type">popup</property>
+ <object class="GtkWindow" id="window_popup">
<property name="title" translatable="yes">Brightness</property>
<property name="type_hint">notification</property>
<child>
- <object class="GtkFrame" id="frame1">
+ <object class="GtkFrame" id="frame_popup">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">out</property>
<child>
- <object class="GtkVBox" id="vbox2">
+ <object class="GtkVBox" id="vbox_popup">
<property name="visible">True</property>
<property name="border_width">12</property>
<property name="spacing">6</property>
<child>
- <object class="GtkImage" id="image">
+ <object class="GtkImage" id="image_popup">
<property name="visible">True</property>
<property name="icon-size">6</property>
</object>
@@ -26,7 +25,7 @@
</packing>
</child>
<child>
- <object class="GtkProgressBar" id="progressbar">
+ <object class="GtkProgressBar" id="progressbar_popup">
<property name="visible">True</property>
<property name="pulse_step">0.10000000149</property>
</object>
diff --git a/src/.gitignore b/src/.gitignore
index 033005c..067eecf 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -1,3 +1,4 @@
+*.a
*.o
.deps
gnome-power-manager
diff --git a/src/Makefile.am b/src/Makefile.am
index 16fd1a3..14f2fe1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -160,8 +160,8 @@ gnome_power_manager_SOURCES = \
gpm-networkmanager.h \
gpm-networkmanager.c \
gpm-stock-icons.h \
- gpm-feedback-widget.h \
- gpm-feedback-widget.c \
+ gpm-popup-window.h \
+ gpm-popup-window.c \
gpm-engine.h \
gpm-engine.c \
$(NULL)
diff --git a/src/gpm-backlight.c b/src/gpm-backlight.c
index c62e780..b789c2c 100644
--- a/src/gpm-backlight.c
+++ b/src/gpm-backlight.c
@@ -48,7 +48,7 @@
#include "gpm-control.h"
#include "gpm-common.h"
#include "egg-debug.h"
-#include "gpm-feedback-widget.h"
+#include "gpm-popup-window.h"
#include "gpm-dpms.h"
#include "gpm-idle.h"
#include "gpm-marshal.h"
@@ -63,7 +63,7 @@ struct GpmBacklightPrivate
GpmBrightness *brightness;
GpmButton *button;
GConfClient *conf;
- GpmFeedback *feedback;
+ GtkWidget *popup;
GpmControl *control;
GpmDpms *dpms;
GpmIdle *idle;
@@ -161,7 +161,7 @@ gpm_backlight_set_brightness (GpmBacklight *backlight, guint percentage, GError
/* we emit a signal for the brightness applet */
if (ret && hw_changed) {
egg_debug ("emitting brightness-changed : %i", percentage);
- g_signal_emit (backlight, signals [BRIGHTNESS_CHANGED], 0, percentage);
+// g_signal_emit (backlight, signals [BRIGHTNESS_CHANGED], 0, percentage);
}
return ret;
}
@@ -260,8 +260,10 @@ gpm_backlight_brightness_evaluate_and_set (GpmBacklight *backlight, gboolean int
}
/* only show dialog if interactive */
- if (interactive)
- gpm_feedback_display_value (backlight->priv->feedback, (float) brightness);
+ if (interactive) {
+ gpm_popup_window_set_value (GPM_POPUP_WINDOW (backlight->priv->popup), (float) brightness);
+ gtk_widget_show (backlight->priv->popup);
+ }
ret = gpm_brightness_set (backlight->priv->brightness, value, &hw_changed);
/* we emit a signal for the brightness applet */
@@ -350,14 +352,15 @@ gpm_backlight_button_pressed_cb (GpmButton *button, const gchar *type, GpmBackli
/* show the new value */
if (ret) {
gpm_brightness_get (backlight->priv->brightness, &percentage);
- gpm_feedback_display_value (backlight->priv->feedback, (float) percentage/100.0f);
+ gpm_popup_window_set_value (GPM_POPUP_WINDOW (backlight->priv->popup), (gfloat) percentage/100.0f);
+ gtk_widget_show (backlight->priv->popup);
/* save the new percentage */
backlight->priv->master_percentage = percentage;
}
/* we emit a signal for the brightness applet */
if (ret && hw_changed) {
egg_debug ("emitting brightness-changed : %i", percentage);
- g_signal_emit (backlight, signals [BRIGHTNESS_CHANGED], 0, percentage);
+// g_signal_emit (backlight, signals [BRIGHTNESS_CHANGED], 0, percentage);
}
} else if (strcmp (type, GPM_BUTTON_BRIGHT_DOWN) == 0) {
/* go up down step */
@@ -366,14 +369,15 @@ gpm_backlight_button_pressed_cb (GpmButton *button, const gchar *type, GpmBackli
/* show the new value */
if (ret) {
gpm_brightness_get (backlight->priv->brightness, &percentage);
- gpm_feedback_display_value (backlight->priv->feedback, (float) percentage/100.0f);
+ gpm_popup_window_set_value (GPM_POPUP_WINDOW (backlight->priv->popup), (gfloat) percentage/100.0f);
+ gtk_widget_show (backlight->priv->popup);
/* save the new percentage */
backlight->priv->master_percentage = percentage;
}
/* we emit a signal for the brightness applet */
if (ret && hw_changed) {
egg_debug ("emitting brightness-changed : %i", percentage);
- g_signal_emit (backlight, signals [BRIGHTNESS_CHANGED], 0, percentage);
+// g_signal_emit (backlight, signals [BRIGHTNESS_CHANGED], 0, percentage);
}
} else if (strcmp (type, GPM_BUTTON_LID_OPEN) == 0) {
/* make sure we undim when we lift the lid */
@@ -573,10 +577,10 @@ gpm_backlight_finalize (GObject *object)
backlight = GPM_BACKLIGHT (object);
g_timer_destroy (backlight->priv->idle_timer);
+ gtk_widget_destroy (backlight->priv->popup);
g_object_unref (backlight->priv->dpms);
g_object_unref (backlight->priv->control);
- g_object_unref (backlight->priv->feedback);
g_object_unref (backlight->priv->conf);
g_object_unref (backlight->priv->client);
g_object_unref (backlight->priv->button);
@@ -627,7 +631,7 @@ gpm_backlight_init (GpmBacklight *backlight)
/* record our idle time */
backlight->priv->idle_timer = g_timer_new ();
- /* watch for manual brightness changes (for the feedback widget) */
+ /* watch for manual brightness changes (for the popup widget) */
backlight->priv->brightness = gpm_brightness_new ();
g_signal_connect (backlight->priv->brightness, "brightness-changed",
G_CALLBACK (brightness_changed_cb), backlight);
@@ -684,9 +688,10 @@ gpm_backlight_init (GpmBacklight *backlight)
gpm_idle_set_timeout_dim (backlight->priv->idle, backlight->priv->idle_dim_timeout);
/* use a visual widget */
- backlight->priv->feedback = gpm_feedback_new ();
- gpm_feedback_set_icon_name (backlight->priv->feedback,
- GPM_STOCK_BRIGHTNESS_LCD);
+ backlight->priv->popup = gpm_popup_window_new ();
+ gtk_window_set_position (GTK_WINDOW (backlight->priv->popup), GTK_WIN_POS_NONE);
+ gpm_popup_window_set_icon_name (GPM_POPUP_WINDOW (backlight->priv->popup),
+ GPM_STOCK_BRIGHTNESS_LCD);
/* DPMS mode poll class */
backlight->priv->dpms = gpm_dpms_new ();
diff --git a/src/gpm-manager.c b/src/gpm-manager.c
index 1e9154c..8efe88e 100644
--- a/src/gpm-manager.c
+++ b/src/gpm-manager.c
@@ -62,7 +62,6 @@
#include "gpm-engine.h"
#include "gpm-devicekit.h"
#include "gpm-disks.h"
-#include "gpm-feedback-widget.h"
#include "org.gnome.PowerManager.Backlight.h"
diff --git a/src/gpm-popup-window.c b/src/gpm-popup-window.c
new file mode 100644
index 0000000..9fd2f3f
--- /dev/null
+++ b/src/gpm-popup-window.c
@@ -0,0 +1,721 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006-2007 William Jon McCann <mccann jhu edu>
+ * Copyright (C) 2009 Richard Hughes <richard hughsie 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <math.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include "egg-debug.h"
+
+#include "gpm-popup-window.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;
+};
+
+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;
+
+ egg_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)
+ egg_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, GPM_DATA "/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);
+ egg_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;
+
+ 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);
+}
+
+/**
+ * gpm_popup_window_new:
+ **/
+GtkWidget *
+gpm_popup_window_new (void)
+{
+ GObject *object;
+ 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);
+ return GTK_WIDGET (object);
+}
diff --git a/src/gpm-popup-window.h b/src/gpm-popup-window.h
new file mode 100644
index 0000000..ad3e33e
--- /dev/null
+++ b/src/gpm-popup-window.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006 William Jon McCann <mccann jhu edu>
+ * Copyright (C) 2009 Richard Hughes <richard hughsie 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GPM_POPUP_WINDOW_H
+#define GPM_POPUP_WINDOW_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+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 (void);
+void gpm_popup_window_set_icon_name (GpmPopupWindow *popup,
+ const gchar *icon_name);
+void gpm_popup_window_set_value (GpmPopupWindow *popup,
+ gfloat value);
+
+G_END_DECLS
+
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]