[gnome-settings-daemon/reusable-osd-window: 1/5] Start an on-screen-display window (OSD)



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]