[gnome-settings-daemon/reusable-osd-window: 1/5] Start an on-screen-display window (OSD)
- From: Federico Mena Quintero <federico src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-settings-daemon/reusable-osd-window: 1/5] Start an on-screen-display window (OSD)
- Date: Wed, 23 Dec 2009 00:04:35 +0000 (UTC)
commit f27de43c929c978efde88f38439ba630fc16bb91
Author: Federico Mena Quintero <federico novell com>
Date: Tue Dec 22 12:59:58 2009 -0600
Start an on-screen-display window (OSD)
This is the code from GsdMediaKeysWindow without the parts specific to media-keys;
the basic GsdOsdWindow will just know how to draw and composite itself, but it will
have no actual contents.
The idea is to have subclasses in the media-keys plugin and in the RANDR plugin;
those can add their own contents to the window.
Signed-off-by: Federico Mena Quintero <federico novell com>
plugins/common/gsd-osd-window.c | 343 +++++++++++++++++++++++++++++++++++++++
plugins/common/gsd-osd-window.h | 75 +++++++++
2 files changed, 418 insertions(+), 0 deletions(-)
---
diff --git a/plugins/common/gsd-osd-window.c b/plugins/common/gsd-osd-window.c
new file mode 100644
index 0000000..19bc459
--- /dev/null
+++ b/plugins/common/gsd-osd-window.c
@@ -0,0 +1,343 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * On-screen-display (OSD) window for gnome-settings-daemon's plugins
+ *
+ * Copyright (C) 2006-2007 William Jon McCann <mccann jhu edu>
+ * Copyright (C) 2009 Novell, Inc
+ *
+ * Authors:
+ * William Jon McCann <mccann jhu edu>
+ * Federico Mena-Quintero <federico novell com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2, 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 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gsd-osd-window.h"
+
+#define DIALOG_TIMEOUT 2000 /* dialog timeout in ms */
+#define DIALOG_FADE_TIMEOUT 1500 /* timeout before fade starts */
+#define FADE_TIMEOUT 10 /* timeout in ms between each frame of the fade */
+
+#define BG_ALPHA 0.75
+#define FG_ALPHA 1.00
+
+#define GSD_OSD_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_OSD_WINDOW, GsdOsdWindowPrivate))
+
+struct GsdOsdWindowPrivate
+{
+ guint is_composited : 1;
+ double fade_out_alpha;
+};
+
+G_DEFINE_TYPE (GsdOsdWindow, gsd_osd_window, GTK_TYPE_WINDOW)
+
+static void
+rounded_rectangle (cairo_t* cr,
+ gdouble aspect,
+ gdouble x,
+ gdouble y,
+ gdouble corner_radius,
+ gdouble width,
+ gdouble height)
+{
+ gdouble radius = corner_radius / aspect;
+
+ cairo_move_to (cr, x + radius, y);
+
+ cairo_line_to (cr,
+ x + width - radius,
+ y);
+ cairo_arc (cr,
+ x + width - radius,
+ y + radius,
+ radius,
+ -90.0f * G_PI / 180.0f,
+ 0.0f * G_PI / 180.0f);
+ cairo_line_to (cr,
+ x + width,
+ y + height - radius);
+ cairo_arc (cr,
+ x + width - radius,
+ y + height - radius,
+ radius,
+ 0.0f * G_PI / 180.0f,
+ 90.0f * G_PI / 180.0f);
+ cairo_line_to (cr,
+ x + radius,
+ y + height);
+ cairo_arc (cr,
+ x + radius,
+ y + height - radius,
+ radius,
+ 90.0f * G_PI / 180.0f,
+ 180.0f * G_PI / 180.0f);
+ cairo_line_to (cr,
+ x,
+ y + radius);
+ cairo_arc (cr,
+ x + radius,
+ y + radius,
+ radius,
+ 180.0f * G_PI / 180.0f,
+ 270.0f * G_PI / 180.0f);
+ cairo_close_path (cr);
+}
+
+static gboolean
+on_expose_event (GtkWidget *widget,
+ GdkEventExpose *event,
+ GsdOsdWindow *window)
+{
+ cairo_t *context;
+ cairo_t *cr;
+ cairo_surface_t *surface;
+ int width;
+ int height;
+ GtkStyle *style;
+ GdkColor color;
+ double r, g, b;
+
+ context = gdk_cairo_create (gtk_widget_get_window (widget));
+
+ style = gtk_widget_get_style (widget);
+ 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 */
+ rounded_rectangle (cr, 1.0, 0.5, 0.5, height / 10, width-1, height-1);
+ color_reverse (&style->bg[GTK_STATE_NORMAL], &color);
+ 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, BG_ALPHA);
+ cairo_fill_preserve (cr);
+
+ color_reverse (&style->text_aa[GTK_STATE_NORMAL], &color);
+ 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, BG_ALPHA / 2);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke (cr);
+
+#if 0
+ /* draw action */
+ draw_action (window, cr);
+#endif
+
+ 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, window->priv->fade_out_alpha);
+
+ done:
+ if (surface != NULL) {
+ cairo_surface_destroy (surface);
+ }
+ cairo_destroy (context);
+
+ return FALSE;
+}
+
+static void
+gsd_osd_window_real_show (GtkWidget *widget)
+{
+ GsdOsdWindow *window;
+
+ if (GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->show) {
+ GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->show (widget);
+ }
+
+ window = GSD_OSD_WINDOW (widget);
+ remove_hide_timeout (window);
+ add_hide_timeout (window);
+}
+
+static void
+gsd_osd_window_real_hide (GtkWidget *widget)
+{
+ GsdOsdWindow *window;
+
+ if (GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->hide) {
+ GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->hide (widget);
+ }
+
+ window = GSD_OSD_WINDOW (widget);
+ remove_hide_timeout (window);
+}
+
+static void
+gsd_osd_window_real_realize (GtkWidget *widget)
+{
+ GdkColormap *colormap;
+ GtkAllocation allocation;
+ 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 (gsd_osd_window_parent_class)->realize) {
+ GTK_WIDGET_CLASS (gsd_osd_window_parent_class)->realize (widget);
+ }
+
+ gtk_widget_get_allocation (widget, &allocation);
+ mask = gdk_pixmap_new (gtk_widget_get_window (widget),
+ allocation.width,
+ allocation.height,
+ 1);
+ cr = gdk_cairo_create (mask);
+
+ cairo_set_source_rgba (cr, 1., 1., 1., 0.);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr);
+
+ /* make the whole window ignore events */
+ gdk_window_input_shape_combine_mask (gtk_widget_get_window (widget), mask, 0, 0);
+ g_object_unref (mask);
+ cairo_destroy (cr);
+}
+
+static void
+gsd_osd_window_class_init (GsdOsdWindowClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ widget_class->show = gsd_osd_window_real_show;
+ widget_class->hide = gsd_osd_window_real_hide;
+ widget_class->realize = gsd_osd_window_real_realize;
+
+ g_type_class_add_private (klass, sizeof (GsdOsdWindowPrivate));
+}
+
+
+/* gsd_osd_window_is_valid:
+ * @window: a #GsdOsdWindow
+ *
+ * Return value: TRUE if the @window's idea of being composited matches whether
+ * its current screen is actually composited.
+ */
+gboolean
+gsd_osd_window_is_valid (GsdOsdWindow *window)
+{
+ GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (window));
+ return gdk_screen_is_composited (screen) == window->priv->is_composited;
+}
+
+static void
+gsd_osd_window_init (GsdOsdWindow *window)
+{
+ GdkScreen *screen;
+
+ window->priv = GSD_OSD_WINDOW_GET_PRIVATE (window);
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (window));
+
+ window->priv->is_composited = gdk_screen_is_composited (screen);
+
+ if (window->priv->is_composited) {
+ gdouble scalew, scaleh, scale;
+ gint size;
+
+ gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
+ gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
+
+ /* assume 130x130 on a 640x480 display and scale from there */
+ 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_window_set_default_size (GTK_WINDOW (window), size, size);
+ g_signal_connect (window, "expose-event", G_CALLBACK (on_expose_event), window);
+
+ window->priv->fade_out_alpha = 1.0;
+ } else {
+ GtkBuilder *builder;
+ const gchar *objects[] = {"acme_frame", NULL};
+ GtkWidget *frame;
+
+ builder = gtk_builder_new ();
+ gtk_builder_add_objects_from_file (builder,
+ GTKBUILDERDIR "/acme.ui",
+ (char **) objects,
+ NULL);
+
+ frame = GTK_WIDGET (gtk_builder_get_object (builder,
+ "acme_frame"));
+
+ if (frame != NULL) {
+ gtk_container_add (GTK_CONTAINER (window), frame);
+ gtk_widget_show_all (frame);
+ }
+
+ /* The builder needs to stay alive until the window
+ takes ownership of the frame (and its children) */
+ g_object_unref (builder);
+ }
+}
+
+GtkWidget *
+gsd_osd_window_new (void)
+{
+ GObject *object;
+
+ object = g_object_new (GSD_TYPE_OSD_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/plugins/common/gsd-osd-window.h b/plugins/common/gsd-osd-window.h
new file mode 100644
index 0000000..ba82cbc
--- /dev/null
+++ b/plugins/common/gsd-osd-window.h
@@ -0,0 +1,75 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8; tab-width: 8 -*-
+ *
+ * On-screen-display (OSD) window for gnome-settings-daemon's plugins
+ *
+ * Copyright (C) 2006 William Jon McCann <mccann jhu edu>
+ * Copyright (C) 2009 Novell, Inc
+ *
+ * Authors:
+ * William Jon McCann <mccann jhu edu>
+ * Federico Mena-Quintero <federico novell com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2, 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 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+/* GsdOsdWindow is an "on-screen-display" window (OSD). It is the cute,
+ * semi-transparent, curved popup that appears when you press a hotkey global to
+ * the desktop, such as to change the volume, switch your monitor's parameters,
+ * etc.
+ *
+ * You can create a GsdOsdWindow and use it as a normal GtkWindow. It will
+ * automatically center itself, figure out if it needs to be composited, etc.
+ * Just pack your widgets in it, sit back, and enjoy the ride.
+ */
+
+#ifndef GSD_OSD_WINDOW_H
+#define GSD_OSD_WINDOW_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GSD_TYPE_OSD_WINDOW (gsd_osd_window_get_type ())
+#define GSD_OSD_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_OSD_WINDOW, GsdOsdWindow))
+#define GSD_OSD_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_OSD_WINDOW, GsdOsdWindowClass))
+#define GSD_IS_OSD_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_OSD_WINDOW))
+#define GSD_IS_OSD_WINDOW_CLASS(klass) (G_TYPE_INSTANCE_GET_CLASS ((klass), GSD_TYPE_OSD_WINDOW))
+
+typedef struct GsdOsdWindow GsdOsdWindow;
+typedef struct GsdOsdWindowClass GsdOsdWindowClass;
+typedef struct GsdOsdWindowPrivate GsdOsdWindowPrivate;
+
+struct GsdOsdWindow {
+ GtkWindow parent;
+
+ GsdOsdWindowPrivate *priv;
+};
+
+struct GsdOsdWindowClass {
+ GtkWindowClass parent_class;
+};
+
+GType gsd_osd_window_get_type (void);
+
+GtkWidget * gsd_osd_window_new (void);
+gboolean gsd_osd_window_is_valid (GsdOsdWindow *window);
+
+G_END_DECLS
+
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]