[gnome-flashback] shell: add osd window
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-flashback] shell: add osd window
- Date: Sat, 28 Mar 2015 01:34:41 +0000 (UTC)
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]