[gnome-flashback] shell: add osd window



commit be70b7268c32c054de1883637265e1c413d0acf0
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Sat Mar 28 03:33:51 2015 +0200

    shell: add osd window

 configure.ac                                    |    2 +-
 gnome-flashback/libshell/Makefile.am            |    2 +
 gnome-flashback/libshell/flashback-osd-window.c |  300 +++++++++++++++++++++++
 gnome-flashback/libshell/flashback-osd-window.h |   43 ++++
 gnome-flashback/libshell/flashback-osd.c        |  116 +++++++++-
 5 files changed, 460 insertions(+), 3 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index b5dca72..9352029 100644
--- a/configure.ac
+++ b/configure.ac
@@ -61,7 +61,7 @@ PKG_CHECK_MODULES(SCREENSHOT, gtk+-3.0 >= $GTK_REQUIRED)
 AC_SUBST(SCREENSHOT_CFLAGS)
 AC_SUBST(SCREENSHOT_LIBS)
 
-PKG_CHECK_MODULES(SHELL, gtk+-3.0 >= $GTK_REQUIRED x11)
+PKG_CHECK_MODULES(SHELL, gtk+-3.0 >= $GTK_REQUIRED glib-2.0 >= $GLIB_REQUIRED x11)
 AC_SUBST(SHELL_CFLAGS)
 AC_SUBST(SHELL_LIBS)
 
diff --git a/gnome-flashback/libshell/Makefile.am b/gnome-flashback/libshell/Makefile.am
index 74449d4..ffce25e 100644
--- a/gnome-flashback/libshell/Makefile.am
+++ b/gnome-flashback/libshell/Makefile.am
@@ -14,6 +14,8 @@ libshell_la_SOURCES = \
        flashback-monitor-labeler.h \
        flashback-osd.c \
        flashback-osd.h \
+       flashback-osd-window.c \
+       flashback-osd-window.h \
        flashback-shell.c \
        flashback-shell.h
 
diff --git a/gnome-flashback/libshell/flashback-osd-window.c b/gnome-flashback/libshell/flashback-osd-window.c
new file mode 100644
index 0000000..f47cd07
--- /dev/null
+++ b/gnome-flashback/libshell/flashback-osd-window.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2015 Alberts Muktupāvels
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <math.h>
+#include <gdk/gdk.h>
+#include "flashback-osd-window.h"
+
+#define HIDE_TIMEOUT 1500
+#define FADE_TIMEOUT 10
+
+struct _FlashbackOsdWindow
+{
+  GtkWindow    parent;
+
+  GdkRectangle monitor;
+
+  guint        hide_timeout_id;
+  guint        fade_timeout_id;
+
+  gdouble      fade_out_alpha;
+};
+
+G_DEFINE_TYPE (FlashbackOsdWindow, flashback_osd_window, GTK_TYPE_WINDOW)
+
+static cairo_surface_t *
+flashback_osd_window_draw_real (FlashbackOsdWindow *window,
+                                cairo_t            *cr1,
+                                gint                width,
+                                gint                height)
+{
+  cairo_surface_t *surface;
+  cairo_t *cr2;
+  GtkStyleContext *context;
+
+  surface = cairo_surface_create_similar (cairo_get_target (cr1),
+                                          CAIRO_CONTENT_COLOR_ALPHA,
+                                          width, height);
+
+  if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
+    {
+      if (surface)
+        cairo_surface_destroy (surface);
+      return NULL;
+    }
+
+  cr2 = cairo_create (surface);
+
+  if (cairo_status (cr2) != CAIRO_STATUS_SUCCESS)
+    {
+      cairo_surface_destroy (surface);
+      return NULL;
+    }
+
+  context = gtk_widget_get_style_context (GTK_WIDGET (window));
+  gtk_render_background (context, cr2, 0, 0, width, height);
+  gtk_render_frame (context, cr2, 0, 0, width, height);
+
+  cairo_destroy (cr2);
+
+  return surface;
+}
+
+static gboolean
+flashback_osd_window_draw (GtkWidget *widget,
+                           cairo_t   *cr)
+{
+  FlashbackOsdWindow *window;
+  gint width;
+  gint height;
+  cairo_surface_t *surface;
+
+  window = FLASHBACK_OSD_WINDOW (widget);
+
+  gtk_window_get_size (GTK_WINDOW (widget), &width, &height);
+
+  surface = flashback_osd_window_draw_real (window, cr, width, height);
+
+  if (surface == NULL)
+    return TRUE;
+
+  cairo_rectangle (cr, 0, 0, width, height);
+  cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
+  cairo_fill (cr);
+
+  cairo_set_source_surface (cr, surface, 0, 0);
+  cairo_paint_with_alpha (cr, window->fade_out_alpha);
+
+  cairo_surface_destroy (surface);
+
+  return GTK_WIDGET_CLASS (flashback_osd_window_parent_class)->draw (widget, cr);
+}
+
+static gboolean
+fade_timeout_cb (gpointer user_data)
+{
+  FlashbackOsdWindow *window;
+
+  window = FLASHBACK_OSD_WINDOW (user_data);
+
+  if (window->fade_out_alpha <= 0.0)
+    {
+      flashback_osd_window_hide (window);
+
+      return FALSE;
+    }
+
+  window->fade_out_alpha -= 0.10;
+
+  gtk_widget_queue_draw (GTK_WIDGET (window));
+
+  return TRUE;
+}
+
+static gboolean
+hide_timeout_cb (gpointer user_data)
+{
+  FlashbackOsdWindow *window;
+
+  window = FLASHBACK_OSD_WINDOW (user_data);
+
+  window->fade_timeout_id = g_timeout_add (FADE_TIMEOUT,
+                                           (GSourceFunc) fade_timeout_cb,
+                                           window);
+
+  window->hide_timeout_id = 0;
+
+  return FALSE;
+}
+
+static void
+add_hide_timeout (FlashbackOsdWindow *window)
+{
+  window->hide_timeout_id = g_timeout_add (HIDE_TIMEOUT,
+                                           (GSourceFunc) hide_timeout_cb,
+                                           window);
+}
+
+static void
+remove_hide_timeout (FlashbackOsdWindow *window)
+{
+  if (window->hide_timeout_id > 0)
+    {
+      g_source_remove (window->hide_timeout_id);
+      window->hide_timeout_id = 0;
+    }
+
+  if (window->fade_timeout_id > 0)
+    {
+      g_source_remove (window->fade_timeout_id);
+      window->fade_timeout_id = 0;
+      window->fade_out_alpha = 1.0;
+    }
+}
+
+static void
+flashback_osd_window_finalize (GObject *object)
+{
+  FlashbackOsdWindow *window;
+
+  window = FLASHBACK_OSD_WINDOW (object);
+
+  remove_hide_timeout (window);
+
+  G_OBJECT_CLASS (flashback_osd_window_parent_class)->finalize (object);
+}
+
+static void
+flashback_osd_window_realize (GtkWidget *widget)
+{
+  GdkScreen *screen;
+  GdkVisual *visual;
+  cairo_region_t *region;
+
+  screen = gtk_widget_get_screen (widget);
+  visual = gdk_screen_get_rgba_visual (screen);
+
+  if (visual == NULL)
+    visual = gdk_screen_get_system_visual (screen);
+
+  gtk_widget_set_visual (widget, visual);
+
+  GTK_WIDGET_CLASS (flashback_osd_window_parent_class)->realize (widget);
+
+  region = cairo_region_create ();
+  gtk_widget_input_shape_combine_region (widget, region);
+  cairo_region_destroy (region);
+}
+
+static void
+flashback_osd_window_class_init (FlashbackOsdWindowClass *window_class)
+{
+  GObjectClass *object_class;
+  GtkWidgetClass *widget_class;
+
+  object_class = G_OBJECT_CLASS (window_class);
+  widget_class = GTK_WIDGET_CLASS (window_class);
+
+  object_class->finalize = flashback_osd_window_finalize;
+
+  widget_class->draw = flashback_osd_window_draw;
+  widget_class->realize = flashback_osd_window_realize;
+}
+
+static void
+flashback_osd_window_init (FlashbackOsdWindow *window)
+{
+  window->fade_out_alpha = 1.0;
+}
+
+FlashbackOsdWindow *
+flashback_osd_window_new (gint monitor)
+{
+  FlashbackOsdWindow *window;
+  GdkScreen *screen;
+  gint width;
+  gint height;
+  gint size;
+
+  screen = gdk_screen_get_default ();
+  window = g_object_new (FLASHBACK_TYPE_OSD_WINDOW,
+                         "type", GTK_WINDOW_POPUP,
+                         "type-hint", GDK_WINDOW_TYPE_HINT_NOTIFICATION,
+                         "app-paintable", TRUE,
+                         "decorated", FALSE,
+                         "skip-taskbar-hint", TRUE,
+                         "skip-pager-hint", TRUE,
+                         "focus-on-map", FALSE,
+                         NULL);
+
+  gdk_screen_get_monitor_workarea (screen, monitor, &window->monitor);
+
+  width = window->monitor.width;
+  height = window->monitor.height;
+  size = 110 * MAX (1, MIN (width / 640.0, height / 480.0));
+
+  gtk_window_resize (GTK_WINDOW (window), size, size);
+
+  return window;
+}
+
+void
+flashback_osd_window_set_icon (FlashbackOsdWindow *window,
+                               GIcon              *icon)
+{
+}
+
+void
+flashback_osd_window_set_label (FlashbackOsdWindow *window,
+                                const gchar        *label)
+{
+}
+
+void
+flashback_osd_window_set_level (FlashbackOsdWindow *window,
+                                gint                level)
+{
+}
+
+void
+flashback_osd_window_show (FlashbackOsdWindow *window)
+{
+  gint width;
+  gint height;
+  GdkRectangle rect;
+  gint x;
+  gint y;
+
+  gtk_window_get_size (GTK_WINDOW (window), &width, &height);
+
+  rect = window->monitor;
+  x = ((rect.width - width) / 2) + rect.x;
+  y = ((rect.height - height) / 4 * 3) + rect.y;
+
+  gtk_window_move (GTK_WINDOW (window), x, y);
+  gtk_widget_show (GTK_WIDGET (window));
+  remove_hide_timeout (window);
+  add_hide_timeout (window);
+}
+
+void
+flashback_osd_window_hide (FlashbackOsdWindow *window)
+{
+  gtk_widget_hide (GTK_WIDGET (window));
+  remove_hide_timeout (window);
+}
diff --git a/gnome-flashback/libshell/flashback-osd-window.h b/gnome-flashback/libshell/flashback-osd-window.h
new file mode 100644
index 0000000..6d1687a
--- /dev/null
+++ b/gnome-flashback/libshell/flashback-osd-window.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2015 Alberts Muktupāvels
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef FLASHBACK_OSD_WINDOW_H
+#define FLASHBACK_OSD_WINDOW_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define FLASHBACK_TYPE_OSD_WINDOW flashback_osd_window_get_type ()
+G_DECLARE_FINAL_TYPE (FlashbackOsdWindow, flashback_osd_window,
+                      FLASHBACK, OSD_WINDOW, GtkWindow)
+
+FlashbackOsdWindow *flashback_osd_window_new       (gint                monitor);
+
+void                flashback_osd_window_set_icon  (FlashbackOsdWindow *window,
+                                                    GIcon              *icon);
+void                flashback_osd_window_set_label (FlashbackOsdWindow *window,
+                                                    const gchar        *label);
+void                flashback_osd_window_set_level (FlashbackOsdWindow *window,
+                                                    gint                level);
+
+void                flashback_osd_window_show      (FlashbackOsdWindow *window);
+void                flashback_osd_window_hide      (FlashbackOsdWindow *window);
+
+G_END_DECLS
+
+#endif
diff --git a/gnome-flashback/libshell/flashback-osd.c b/gnome-flashback/libshell/flashback-osd.c
index bb2aedc..eec9e18 100644
--- a/gnome-flashback/libshell/flashback-osd.c
+++ b/gnome-flashback/libshell/flashback-osd.c
@@ -17,22 +17,79 @@
 
 #include <config.h>
 #include "flashback-osd.h"
+#include "flashback-osd-window.h"
 
 struct _FlashbackOsd
 {
-  GObject parent;
+  GObject              parent;
+
+  FlashbackOsdWindow **windows;
+  gint                 n_monitors;
 };
 
 G_DEFINE_TYPE (FlashbackOsd, flashback_osd, G_TYPE_OBJECT)
 
 static void
+monitors_changed (GdkScreen *screen,
+                  gpointer   user_data)
+{
+  FlashbackOsd *osd;
+  gint n_monitors;
+  gint i;
+
+  osd = FLASHBACK_OSD (user_data);
+  n_monitors = gdk_screen_get_n_monitors (screen);
+
+  if (osd->windows != NULL)
+    {
+      for (i = 0; i < osd->n_monitors; i++)
+        gtk_widget_destroy (GTK_WIDGET (osd->windows[i]));
+      g_free (osd->windows);
+    }
+
+  osd->windows = g_new0 (FlashbackOsdWindow *, n_monitors);
+
+  for (i = 0; i < n_monitors; i++)
+    osd->windows[i] = flashback_osd_window_new (i);
+
+  osd->n_monitors = n_monitors;
+}
+
+static void
+flashabck_osd_finalize (GObject *object)
+{
+  GdkScreen *screen;
+  FlashbackOsd *osd;
+
+  screen = gdk_screen_get_default ();
+  osd = FLASHBACK_OSD (object);
+
+  g_signal_handlers_disconnect_by_func (screen, monitors_changed, osd);
+
+  G_OBJECT_CLASS (flashback_osd_parent_class)->finalize (object);
+}
+
+static void
 flashback_osd_class_init (FlashbackOsdClass *osd_class)
 {
+  GObjectClass *object_class;
+
+  object_class = G_OBJECT_CLASS (osd_class);
+
+  object_class->finalize = flashabck_osd_finalize;
 }
 
 static void
 flashback_osd_init (FlashbackOsd *osd)
 {
+  GdkScreen *screen;
+
+  screen = gdk_screen_get_default ();
+
+  g_signal_connect (screen, "monitors-changed",
+                    G_CALLBACK (monitors_changed), osd);
+
+  monitors_changed (screen, osd);
 }
 
 FlashbackOsd *
@@ -45,5 +102,60 @@ void
 flashback_osd_show (FlashbackOsd *osd,
                     GVariant     *params)
 {
-  g_warning ("shell: show osd");
+  GVariantDict dict;
+  const gchar *icon_name;
+  const gchar *label;
+  GIcon *icon;
+  gint level;
+  gint monitor;
+  gint i;
+
+  g_variant_dict_init (&dict, params);
+
+  if (!g_variant_dict_lookup (&dict, "icon", "s", &icon_name))
+    icon_name = NULL;
+
+  if (!g_variant_dict_lookup (&dict, "label", "s", &label))
+    label = NULL;
+
+  if (!g_variant_dict_lookup (&dict, "level", "u", &level))
+    level = -1;
+
+  if (!g_variant_dict_lookup (&dict, "monitor", "u", &monitor))
+    monitor = -1;
+
+  icon = NULL;
+  if (icon_name)
+    icon = g_icon_new_for_string (icon_name, NULL);
+
+  if (monitor != -1)
+    {
+      for (i = 0; i < osd->n_monitors; i++)
+        {
+          if (i == monitor)
+            {
+              flashback_osd_window_set_icon (osd->windows[i], icon);
+              flashback_osd_window_set_label (osd->windows[i], label);
+              flashback_osd_window_set_level (osd->windows[i], level);
+              flashback_osd_window_show (osd->windows[i]);
+            }
+          else
+            {
+              flashback_osd_window_hide (osd->windows[i]);
+            }
+        }
+    }
+  else
+    {
+      for (i = 0; i < osd->n_monitors; i++)
+        {
+          flashback_osd_window_set_icon (osd->windows[i], icon);
+          flashback_osd_window_set_label (osd->windows[i], label);
+          flashback_osd_window_set_level (osd->windows[i], level);
+          flashback_osd_window_show (osd->windows[i]);
+        }
+    }
+
+  if (icon)
+    g_object_unref (icon);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]