[gnome-flashback] shell: implement monitor labels
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-flashback] shell: implement monitor labels
- Date: Mon, 30 Mar 2015 20:08:49 +0000 (UTC)
commit bcae1ac18c6b5734df046832ea376fd1b31f203b
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Mon Mar 30 16:51:23 2015 +0300
shell: implement monitor labels
configure.ac | 2 +-
gnome-flashback/Adwaita.css | 6 +
gnome-flashback/HighContrast.css | 6 +
gnome-flashback/libshell/Makefile.am | 3 +
gnome-flashback/libshell/flashback-label-window.c | 280 ++++++++++++++++++++
gnome-flashback/libshell/flashback-label-window.h | 37 +++
.../libshell/flashback-monitor-labeler.c | 245 +++++++++++++++++-
.../libshell/flashback-monitor-labeler.h | 3 +
gnome-flashback/libshell/flashback-shell.c | 5 +-
9 files changed, 582 insertions(+), 5 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 9352029..69d0d98 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 glib-2.0 >= $GLIB_REQUIRED x11)
+PKG_CHECK_MODULES(SHELL, gtk+-3.0 >= $GTK_REQUIRED glib-2.0 >= $GLIB_REQUIRED gnome-desktop-3.0 >=
$LIBGNOME_DESKTOP_REQUIRED x11)
AC_SUBST(SHELL_CFLAGS)
AC_SUBST(SHELL_LIBS)
diff --git a/gnome-flashback/Adwaita.css b/gnome-flashback/Adwaita.css
index 362ec9a..64bcd59 100644
--- a/gnome-flashback/Adwaita.css
+++ b/gnome-flashback/Adwaita.css
@@ -2,3 +2,9 @@ FlashbackOsdWindow
{
border-radius: 20px;
}
+
+FlashbackLabelWindow
+{
+ border-radius: 20px;
+ font-size: 40px;
+}
diff --git a/gnome-flashback/HighContrast.css b/gnome-flashback/HighContrast.css
index 362ec9a..64bcd59 100644
--- a/gnome-flashback/HighContrast.css
+++ b/gnome-flashback/HighContrast.css
@@ -2,3 +2,9 @@ FlashbackOsdWindow
{
border-radius: 20px;
}
+
+FlashbackLabelWindow
+{
+ border-radius: 20px;
+ font-size: 40px;
+}
diff --git a/gnome-flashback/libshell/Makefile.am b/gnome-flashback/libshell/Makefile.am
index ffce25e..3743cc7 100644
--- a/gnome-flashback/libshell/Makefile.am
+++ b/gnome-flashback/libshell/Makefile.am
@@ -3,6 +3,7 @@ noinst_LTLIBRARIES = \
AM_CPPFLAGS = \
$(SHELL_CFLAGS) \
+ -I$(top_builddir)/gnome-flashback \
-I$(top_builddir)/gnome-flashback/libshell
libshell_la_SOURCES = \
@@ -10,6 +11,8 @@ libshell_la_SOURCES = \
flashback-dbus-shell.h \
flashback-key-bindings.c \
flashback-key-bindings.h \
+ flashback-label-window.c \
+ flashback-label-window.h \
flashback-monitor-labeler.c \
flashback-monitor-labeler.h \
flashback-osd.c \
diff --git a/gnome-flashback/libshell/flashback-label-window.c
b/gnome-flashback/libshell/flashback-label-window.c
new file mode 100644
index 0000000..e00136a
--- /dev/null
+++ b/gnome-flashback/libshell/flashback-label-window.c
@@ -0,0 +1,280 @@
+/*
+ * 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-label-window.h"
+
+#define HIDE_TIMEOUT 1500
+#define FADE_TIMEOUT 10
+
+struct _FlashbackLabelWindow
+{
+ GtkWindow parent;
+
+ GdkRectangle monitor;
+
+ guint hide_timeout_id;
+ guint fade_timeout_id;
+
+ gdouble fade_out_alpha;
+
+ GtkWidget *label;
+};
+
+G_DEFINE_TYPE (FlashbackLabelWindow, flashback_label_window, GTK_TYPE_WINDOW)
+
+static cairo_surface_t *
+flashback_label_window_draw_real (FlashbackLabelWindow *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_label_window_draw (GtkWidget *widget,
+ cairo_t *cr)
+{
+ FlashbackLabelWindow *window;
+ gint width;
+ gint height;
+ cairo_surface_t *surface;
+
+ window = FLASHBACK_LABEL_WINDOW (widget);
+
+ gtk_window_get_size (GTK_WINDOW (widget), &width, &height);
+
+ surface = flashback_label_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_label_window_parent_class)->draw (widget, cr);
+}
+
+static gboolean
+fade_timeout_cb (gpointer user_data)
+{
+ FlashbackLabelWindow *window;
+
+ window = FLASHBACK_LABEL_WINDOW (user_data);
+
+ if (window->fade_out_alpha <= 0.0)
+ {
+ window->fade_timeout_id = 0;
+ gtk_widget_destroy (GTK_WIDGET (window));
+
+ return FALSE;
+ }
+
+ window->fade_out_alpha -= 0.10;
+
+ gtk_widget_queue_draw (GTK_WIDGET (window));
+
+ return TRUE;
+}
+
+static void
+remove_fade_timeout (FlashbackLabelWindow *window)
+{
+ 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_label_window_finalize (GObject *object)
+{
+ FlashbackLabelWindow *window;
+
+ window = FLASHBACK_LABEL_WINDOW (object);
+
+ remove_fade_timeout (window);
+
+ G_OBJECT_CLASS (flashback_label_window_parent_class)->finalize (object);
+}
+
+static void
+flashback_label_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_label_window_parent_class)->realize (widget);
+
+ region = cairo_region_create ();
+ gtk_widget_input_shape_combine_region (widget, region);
+ cairo_region_destroy (region);
+}
+
+static void
+flashback_label_window_class_init (FlashbackLabelWindowClass *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_label_window_finalize;
+
+ widget_class->draw = flashback_label_window_draw;
+ widget_class->realize = flashback_label_window_realize;
+}
+
+static void
+flashback_label_window_init (FlashbackLabelWindow *window)
+{
+ GtkWidget *box;
+
+ window->fade_out_alpha = 1.0;
+
+ box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
+ gtk_container_set_border_width (GTK_CONTAINER (window), 20);
+ gtk_container_add (GTK_CONTAINER (window), box);
+ gtk_widget_show (box);
+
+ window->label = gtk_label_new ("");
+ gtk_widget_set_halign (window->label, GTK_ALIGN_CENTER);
+ gtk_widget_set_valign (window->label, GTK_ALIGN_CENTER);
+ gtk_box_pack_start (GTK_BOX (box), window->label, TRUE, FALSE, 0);
+ gtk_widget_show (window->label);
+}
+
+FlashbackLabelWindow *
+flashback_label_window_new (gint monitor,
+ const gchar *label)
+{
+ FlashbackLabelWindow *window;
+ GdkScreen *screen;
+ gint width;
+ gint height;
+ gint size;
+
+ screen = gdk_screen_get_default ();
+ window = g_object_new (FLASHBACK_TYPE_LABEL_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 = 60 * MAX (1, MIN (width / 640.0, height / 480.0));
+
+ gtk_window_resize (GTK_WINDOW (window), size, size);
+
+ gtk_label_set_text (GTK_LABEL (window->label), label);
+
+ return window;
+}
+
+void
+flashback_label_window_show (FlashbackLabelWindow *window)
+{
+ gint width;
+ gint height;
+ GdkRectangle rect;
+ GtkTextDirection dir;
+ gint x;
+ gint y;
+
+ gtk_window_get_size (GTK_WINDOW (window), &width, &height);
+
+ rect = window->monitor;
+ dir = gtk_widget_get_direction (GTK_WIDGET (window));
+
+ if (dir == GTK_TEXT_DIR_NONE)
+ dir = gtk_widget_get_default_direction ();
+
+ if (dir == GTK_TEXT_DIR_RTL)
+ x = rect.x + (rect.width - width - 20);
+ else
+ x = rect.x + 20;
+ y = rect.y + 20;
+
+ gtk_window_move (GTK_WINDOW (window), x, y);
+ gtk_widget_show (GTK_WIDGET (window));
+ remove_fade_timeout (window);
+}
+
+void
+flashback_label_window_hide (FlashbackLabelWindow *window)
+{
+ window->fade_timeout_id = g_timeout_add (FADE_TIMEOUT,
+ (GSourceFunc) fade_timeout_cb,
+ window);
+}
diff --git a/gnome-flashback/libshell/flashback-label-window.h
b/gnome-flashback/libshell/flashback-label-window.h
new file mode 100644
index 0000000..e336bf0
--- /dev/null
+++ b/gnome-flashback/libshell/flashback-label-window.h
@@ -0,0 +1,37 @@
+/*
+ * 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_LABEL_WINDOW_H
+#define FLASHBACK_LABEL_WINDOW_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define FLASHBACK_TYPE_LABEL_WINDOW flashback_label_window_get_type ()
+G_DECLARE_FINAL_TYPE (FlashbackLabelWindow, flashback_label_window,
+ FLASHBACK, LABEL_WINDOW, GtkWindow)
+
+FlashbackLabelWindow *flashback_label_window_new (gint monitor,
+ const gchar *label);
+
+void flashback_label_window_show (FlashbackLabelWindow *window);
+void flashback_label_window_hide (FlashbackLabelWindow *window);
+
+G_END_DECLS
+
+#endif
diff --git a/gnome-flashback/libshell/flashback-monitor-labeler.c
b/gnome-flashback/libshell/flashback-monitor-labeler.c
index 14902aa..f8e547b 100644
--- a/gnome-flashback/libshell/flashback-monitor-labeler.c
+++ b/gnome-flashback/libshell/flashback-monitor-labeler.c
@@ -16,18 +16,155 @@
*/
#include <config.h>
+#include <gio/gio.h>
+#include <libdisplay-config/flashback-monitor-manager.h>
#include "flashback-monitor-labeler.h"
+#include "flashback-label-window.h"
struct _FlashbackMonitorLabeler
{
- GObject parent;
+ GObject parent;
+
+ guint watch_id;
+ gchar *client;
+
+ guint hide_id;
+
+ FlashbackLabelWindow **windows;
+ gint n_windows;
};
+typedef struct
+{
+ FlashbackMonitorLabeler *labeler;
+ gchar *sender;
+} CallbackData;
+
G_DEFINE_TYPE (FlashbackMonitorLabeler, flashback_monitor_labeler, G_TYPE_OBJECT)
static void
+real_hide (FlashbackMonitorLabeler *labeler)
+{
+ gint i;
+
+ if (labeler->windows != NULL)
+ {
+ for (i = 0; i < labeler->n_windows; i++)
+ flashback_label_window_hide (labeler->windows[i]);
+ g_free (labeler->windows);
+ labeler->windows = NULL;
+ }
+}
+
+static void
+name_vanished_handler (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ FlashbackMonitorLabeler *labeler;
+
+ labeler = FLASHBACK_MONITOR_LABELER (user_data);
+
+ real_hide (labeler);
+}
+
+static gboolean
+track_client (FlashbackMonitorLabeler *labeler,
+ const gchar *client)
+{
+ if (labeler->client != NULL)
+ return g_strcmp0 (labeler->client, client) == 0;
+
+ labeler->client = g_strdup (client);
+ labeler->watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
+ client,
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ NULL,
+ (GBusNameVanishedCallback) name_vanished_handler,
+ labeler,
+ NULL);
+
+ return TRUE;
+}
+
+static gboolean
+untrack_client (FlashbackMonitorLabeler *labeler,
+ const gchar *client)
+{
+ if (labeler->client == NULL || g_strcmp0 (labeler->client, client) != 0)
+ return FALSE;
+
+ if (labeler->watch_id > 0)
+ {
+ g_bus_unwatch_name (labeler->watch_id);
+ labeler->watch_id = 0;
+ }
+
+ g_free (labeler->client);
+ labeler->client = NULL;
+
+ return TRUE;
+}
+
+static void
+free_callback_data (CallbackData *data)
+{
+ g_object_unref (data->labeler);
+ g_free (data->sender);
+ g_free (data);
+}
+
+static gboolean
+hide_cb (gpointer user_data)
+{
+ CallbackData *data;
+
+ data = (CallbackData *) user_data;
+
+ data->labeler->hide_id = 0;
+
+ if (!untrack_client (data->labeler, data->sender))
+ return FALSE;
+
+ real_hide (data->labeler);
+
+ return FALSE;
+}
+
+static void
+flashback_monitor_labeler_finalize (GObject *object)
+{
+ FlashbackMonitorLabeler *labeler;
+
+ labeler = FLASHBACK_MONITOR_LABELER (object);
+
+ if (labeler->watch_id > 0)
+ {
+ g_bus_unwatch_name (labeler->watch_id);
+ labeler->watch_id = 0;
+ }
+
+ if (labeler->hide_id > 0)
+ {
+ g_source_remove (labeler->hide_id);
+ labeler->hide_id = 0;
+ }
+
+ real_hide (labeler);
+
+ g_free (labeler->client);
+
+ G_OBJECT_CLASS (flashback_monitor_labeler_parent_class)->finalize (object);
+}
+
+static void
flashback_monitor_labeler_class_init (FlashbackMonitorLabelerClass *labeler_class)
{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (labeler_class);
+
+ object_class->finalize = flashback_monitor_labeler_finalize;
}
static void
@@ -43,15 +180,117 @@ flashback_monitor_labeler_new (void)
void
flashback_monitor_labeler_show (FlashbackMonitorLabeler *labeler,
+ FlashbackMonitorManager *manager,
const gchar *sender,
GVariant *params)
{
- g_warning ("shell: show monitor labels");
+ GVariantIter iter;
+ guint id;
+ gint number;
+ GVariant *v;
+ GHashTable *monitors;
+ GList *keys;
+ GList *key;
+ gint i;
+
+ if (labeler->hide_id > 0)
+ {
+ g_source_remove (labeler->hide_id);
+ labeler->hide_id = 0;
+ }
+
+ if (!track_client (labeler, sender))
+ return;
+
+ if (labeler->windows != NULL)
+ return;
+
+ /*if (labeler->windows != NULL)
+ {
+ for (i = 0; i < labeler->n_windows; i++)
+ gtk_widget_destroy (GTK_WIDGET (labeler->windows[i]));
+ g_free (labeler->windows);
+ labeler->windows = NULL;
+ }*/
+
+ g_variant_iter_init (&iter, params);
+
+ monitors = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ while (g_variant_iter_next (&iter, "{uv}", &id, &v))
+ {
+ gint monitor;
+
+ g_variant_get (v, "i", &number);
+
+ monitor = flashback_monitor_manager_get_monitor_for_output (manager, id);
+
+ if (monitor != -1)
+ {
+ GSList *list;
+ gboolean insert;
+
+ list = (GSList *) g_hash_table_lookup (monitors, GINT_TO_POINTER (monitor));
+ insert = (list == NULL);
+
+ list = g_slist_append (list, GINT_TO_POINTER (number));
+
+ if (insert)
+ g_hash_table_insert (monitors, GINT_TO_POINTER (monitor), list);
+ }
+
+ g_variant_unref (v);
+ }
+
+ keys = g_hash_table_get_keys (monitors);
+
+ labeler->n_windows = g_hash_table_size (monitors);
+ labeler->windows = g_new0 (FlashbackLabelWindow *, labeler->n_windows);
+ i = 0;
+
+ for (key = keys; key; key = key->next)
+ {
+ GSList *labels;
+ GSList *label;
+ GString *string;
+ gchar *real_label;
+
+ labels = (GSList *) g_hash_table_lookup (monitors, key->data);
+ string = g_string_new ("");
+
+ for (label = labels; label; label = label->next)
+ g_string_append_printf (string, "%d ", GPOINTER_TO_INT (label->data));
+ g_string_set_size (string, string->len - 1);
+
+ g_slist_free (labels);
+
+ real_label = g_string_free (string, FALSE);
+ labeler->windows[i] = flashback_label_window_new (GPOINTER_TO_INT (key->data),
+ real_label);
+ g_free (real_label);
+
+ flashback_label_window_show (labeler->windows[i]);
+
+ i++;
+ }
+
+ g_list_free (keys);
+ g_hash_table_destroy (monitors);
}
void
flashback_monitor_labeler_hide (FlashbackMonitorLabeler *labeler,
const gchar *sender)
{
- g_warning ("shell: hide monitor labels");
+ CallbackData *data;
+
+ data = (CallbackData *) g_new0 (CallbackData *, 1);
+ data->labeler = g_object_ref (labeler);
+ data->sender = g_strdup (sender);
+
+ labeler->hide_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
+ 100,
+ (GSourceFunc) hide_cb,
+ data,
+ (GDestroyNotify) free_callback_data);
}
diff --git a/gnome-flashback/libshell/flashback-monitor-labeler.h
b/gnome-flashback/libshell/flashback-monitor-labeler.h
index b8bb613..de5f454 100644
--- a/gnome-flashback/libshell/flashback-monitor-labeler.h
+++ b/gnome-flashback/libshell/flashback-monitor-labeler.h
@@ -22,6 +22,8 @@
G_BEGIN_DECLS
+typedef struct _FlashbackMonitorManager FlashbackMonitorManager;
+
#define FLASHBACK_TYPE_MONITOR_LABELER flashback_monitor_labeler_get_type ()
G_DECLARE_FINAL_TYPE (FlashbackMonitorLabeler, flashback_monitor_labeler,
FLASHBACK, MONITOR_LABELER, GObject)
@@ -29,6 +31,7 @@ G_DECLARE_FINAL_TYPE (FlashbackMonitorLabeler, flashback_monitor_labeler,
FlashbackMonitorLabeler *flashback_monitor_labeler_new (void);
void flashback_monitor_labeler_show (FlashbackMonitorLabeler *labeler,
+ FlashbackMonitorManager *manager,
const gchar *sender,
GVariant *params);
void flashback_monitor_labeler_hide (FlashbackMonitorLabeler *labeler,
diff --git a/gnome-flashback/libshell/flashback-shell.c b/gnome-flashback/libshell/flashback-shell.c
index ef30891..790b8d9 100644
--- a/gnome-flashback/libshell/flashback-shell.c
+++ b/gnome-flashback/libshell/flashback-shell.c
@@ -205,7 +205,10 @@ handle_show_monitor_labels (FlashbackDBusShell *dbus_shell,
shell = FLASHBACK_SHELL (user_data);
sender = g_dbus_method_invocation_get_sender (invocation);
- flashback_monitor_labeler_show (shell->labeler, sender, params);
+ g_assert (shell->manager != NULL);
+
+ flashback_monitor_labeler_show (shell->labeler, shell->manager,
+ sender, params);
flashback_dbus_shell_complete_show_monitor_labels (dbus_shell, invocation);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]