[gnome-applets/wip/segeiger/type-changed: 4/4] windowpicker: handle to monitor-geometry changed signal



commit 654aa7a8486d711dd7a05a1bd23aad2a174a8cc0
Author: Sebastian Geiger <sbastig gmx net>
Date:   Mon Feb 8 01:34:24 2016 +0100

    windowpicker: handle to monitor-geometry changed signal
    
    Works but still needs some cleanup.

 windowpicker/src/task-item.c |   64 +++++++++++++++-
 windowpicker/src/task-item.h |    3 +
 windowpicker/src/task-list.c |  171 ++++++++++++++++++++++++++++++++++++------
 windowpicker/src/task-list.h |   14 +++-
 4 files changed, 224 insertions(+), 28 deletions(-)
---
diff --git a/windowpicker/src/task-item.c b/windowpicker/src/task-item.c
index d781486..70c8115 100644
--- a/windowpicker/src/task-item.c
+++ b/windowpicker/src/task-item.c
@@ -43,11 +43,13 @@ struct _TaskItemPrivate {
     GTimeVal     urgent_time;
     guint        blink_timer;
     gboolean     mouse_over;
+    gint         monitor;
     WpApplet    *windowPickerApplet;
 };
 
 enum {
     TASK_ITEM_CLOSED_SIGNAL,
+    TASK_ITEM_MONITOR_CHANGED,
     LAST_SIGNAL
 };
 
@@ -482,10 +484,52 @@ on_window_type_changed (WnckWindow *window,
         type == WNCK_WINDOW_SPLASHSCREEN ||
         type == WNCK_WINDOW_MENU)
       {
-          task_item_close (item, window);
+          task_item_close (item);
       }
 }
 
+gint get_window_monitor (WnckWindow *window)
+{
+    gint x, y, w, h;
+    gint window_monitor;
+    GdkScreen *gdk_screen;
+
+    wnck_window_get_geometry (window, &x, &y, &w, &h);
+
+    gdk_screen = gdk_screen_get_default ();
+    window_monitor = gdk_screen_get_monitor_at_point (gdk_screen,
+                                                      x + w / 2,
+                                                      y + h / 2);
+    return window_monitor;
+}
+
+static void
+on_window_geometry_changed (WnckWindow *window,
+                            TaskItem   *item)
+{
+    gint old_monitor;
+    gint window_monitor;
+    gboolean handled;
+
+    //g_signal_handlers_block_by_func (window, on_window_geometry_changed, item);
+
+    window_monitor = get_window_monitor (window);
+
+    old_monitor = item->priv->monitor;
+    if (old_monitor != window_monitor)
+      {
+        item->priv->monitor = window_monitor;
+        g_message ("old_monitor=%d, window_monitor=%d, emitting signal", old_monitor,
+                   window_monitor);
+
+        g_signal_emit (item, task_item_signals[TASK_ITEM_MONITOR_CHANGED], 0,
+                       old_monitor, &handled);
+      }
+
+    //g_signal_handlers_unblock_by_func (window, on_window_geometry_changed,
+    //                                   item);
+}
+
 static void on_screen_active_window_changed (
     WnckScreen    *screen,
     WnckWindow    *old_window,
@@ -810,6 +854,14 @@ static void task_item_class_init (TaskItemClass *klass) {
         G_STRUCT_OFFSET (TaskItemClass, itemclosed),
         NULL, NULL,
         g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
+    task_item_signals [TASK_ITEM_MONITOR_CHANGED] =
+        g_signal_new ("monitor-changed",
+                      TASK_TYPE_ITEM,
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (TaskItemClass, monitor_changed),
+                      g_signal_accumulator_true_handled, NULL, NULL,
+                      G_TYPE_BOOLEAN, 1, G_TYPE_INT);
 }
 
 static void task_item_init (TaskItem *item) {
@@ -838,6 +890,9 @@ GtkWidget *task_item_new (WpApplet* windowPickerApplet, WnckWindow *window) {
     screen = wnck_window_get_screen (window);
     priv->screen = screen;
     priv->windowPickerApplet = windowPickerApplet;
+    priv->monitor = get_window_monitor (window);
+
+    g_message ("item=%p on monitor=%d", item, priv->monitor);
 
     /** Drag and Drop code
      * This item can be both the target and the source of a drag and drop
@@ -899,6 +954,8 @@ GtkWidget *task_item_new (WpApplet* windowPickerApplet, WnckWindow *window) {
         G_CALLBACK (on_window_icon_changed), item);
     g_signal_connect (window, "type-changed",
         G_CALLBACK (on_window_type_changed), item);
+    g_signal_connect (window, "geometry-changed",
+        G_CALLBACK (on_window_geometry_changed), item);
     g_signal_connect(item, "draw",
         G_CALLBACK(task_item_draw), windowPickerApplet);
     g_signal_connect (item, "button-release-event",
@@ -917,3 +974,8 @@ GtkWidget *task_item_new (WpApplet* windowPickerApplet, WnckWindow *window) {
     task_item_setup_atk (taskItem);
     return item;
 }
+
+gint task_item_get_monitor (TaskItem *item)
+{
+    return item->priv->monitor;
+}
diff --git a/windowpicker/src/task-item.h b/windowpicker/src/task-item.h
index dcb9a0e..0ea6b10 100644
--- a/windowpicker/src/task-item.h
+++ b/windowpicker/src/task-item.h
@@ -46,9 +46,12 @@ struct _TaskItem {
 struct _TaskItemClass {
     GtkEventBoxClass   parent_class;
     void (* itemclosed) (TaskItem *item);
+    void (* monitor_changed) (TaskItem *item);
 };
 
 GType task_item_get_type (void) G_GNUC_CONST;
 GtkWidget * task_item_new (WpApplet *windowPickerApplet, WnckWindow *window);
 
+gint        task_item_get_monitor (TaskItem *item);
+
 #endif /* _TASK_ITEM_H_ */
diff --git a/windowpicker/src/task-list.c b/windowpicker/src/task-list.c
index 672de37..6c91ed6 100644
--- a/windowpicker/src/task-list.c
+++ b/windowpicker/src/task-list.c
@@ -29,9 +29,67 @@ struct _TaskListPrivate {
     WpApplet *windowPickerApplet;
 };
 
-static GSList *task_lists;
+struct _TaskListClassPrivate {
+    GSList *task_lists;
+};
+
+G_DEFINE_TYPE_WITH_CODE (TaskList, task_list, GTK_TYPE_BOX,
+                         G_ADD_PRIVATE (TaskList);
+                         g_type_add_class_private (g_define_type_id,
+                                                   sizeof (TaskListClassPrivate)))
+
+static guint
+get_num_task_lists (TaskList *task_list)
+{
+    TaskListClassPrivate *class_private = TASK_LIST_GET_CLASS_PRIVATE (task_list);
+
+    return g_slist_length (class_private->task_lists);
+}
+
+static void
+add_task_list (TaskList *task_list)
+{
+    TaskListClassPrivate *class_private = TASK_LIST_GET_CLASS_PRIVATE (task_list);
+
+    class_private->task_lists = g_slist_append (class_private->task_lists,
+                                                task_list);
+}
+
+static void
+remove_task_list (TaskList *task_list)
+{
+    TaskListClassPrivate *class_private = TASK_LIST_GET_CLASS_PRIVATE (task_list);
+
+    class_private->task_lists = g_slist_remove (class_private->task_lists,
+                                                task_list);
+}
+
+static TaskList *
+get_task_list_for_monitor (TaskList *task_list,
+                           guint monitor)
+{
+    GSList *list;
+    gint list_monitor;
+
+    TaskListClassPrivate *class_private =
+        TASK_LIST_GET_CLASS_PRIVATE (task_list);
+
+    list = class_private->task_lists;
+
+    while (list != NULL)
+    {
+        task_list = list->data;
+        list_monitor = task_list_get_monitor (task_list);
+
+        if (list_monitor == monitor)
+            return task_list;
+
+        list = list->next;
+    }
+
+    return class_private->task_lists->data;
+}
 
-G_DEFINE_TYPE_WITH_PRIVATE (TaskList, task_list, GTK_TYPE_BOX);
 
 static void on_task_item_closed (
     TaskItem *item,
@@ -44,30 +102,76 @@ static void on_task_item_closed (
     gtk_widget_destroy (GTK_WIDGET (item));
 }
 
+static gint
+window_get_monitor (WnckWindow *window)
+{
+    GdkScreen *gdk_screen;
+    gint x, y, w, h;
+
+    gdk_screen = gdk_screen_get_default ();
+
+    wnck_window_get_geometry (window, &x, &y, &w, &h);
+
+    return gdk_screen_get_monitor_at_point (gdk_screen,
+                                            x + w / 2,
+                                            y + h / 2);
+}
+
+static void
+on_task_item_monitor_changed_cb (TaskItem *item,
+                                 gint      old_monitor,
+                                 TaskList *current_list)
+{
+    gint monitor;
+    gint list_monitor;
+    TaskList *list;
+
+    monitor = task_item_get_monitor (item);
+    list_monitor = task_list_get_monitor (current_list);
+
+    if (monitor != list_monitor)
+    {
+
+        list = TASK_LIST (get_task_list_for_monitor (current_list,
+                                                     monitor));
+
+        g_object_ref (item);
+        gtk_container_remove (GTK_CONTAINER (current_list), GTK_WIDGET (item));
+
+        gtk_widget_queue_resize (GTK_WIDGET (current_list));
+
+        g_signal_handlers_disconnect_by_func (item,
+                                              on_task_item_monitor_changed_cb,
+                                              current_list);
+
+        gtk_container_add (GTK_CONTAINER (list), GTK_WIDGET (item));
+
+        g_signal_connect (TASK_ITEM (item), "monitor-changed",
+                          G_CALLBACK (on_task_item_monitor_changed_cb),
+                          list);
+
+        g_object_unref (item);
+
+        gtk_widget_queue_resize (GTK_WIDGET (list));
+        gtk_widget_queue_draw (GTK_WIDGET (list));
+    }
+}
+
 static void create_task_item (TaskList   *taskList,
                               WnckWindow *window)
 {
     GtkWidget *item;
-    GdkScreen *gdk_screen;
-    GdkWindow *gdk_window;
     gint list_monitor;
     gint window_monitor;
-    gint x;
-    gint y;
-    gint w;
-    gint h;
+    guint num;
 
-    if (g_slist_length (task_lists) > 1) {
-        gdk_window = gtk_widget_get_window (GTK_WIDGET (taskList));
-        gdk_screen = gtk_widget_get_screen (GTK_WIDGET (taskList));
-        list_monitor = gdk_screen_get_monitor_at_window (gdk_screen,
-                                                         gdk_window);
+    num = get_num_task_lists (taskList);
 
-        wnck_window_get_geometry (window, &x, &y, &w, &h);
+    g_message ("number of task_lists=%d", num);
 
-        window_monitor = gdk_screen_get_monitor_at_point (gdk_screen,
-                                                          x + w / 2,
-                                                          y + h / 2);
+    if (num > 1) {
+        list_monitor = task_list_get_monitor (taskList);
+        window_monitor = window_get_monitor (window);
 
         if (list_monitor != window_monitor)
             return;
@@ -76,12 +180,16 @@ static void create_task_item (TaskList   *taskList,
     item = task_item_new (taskList->priv->windowPickerApplet,
                                      window);
 
-    if (item)
-      {
-        gtk_container_add (GTK_CONTAINER (taskList), item);
+    if (item) {
+        gtk_container_add (GTK_CONTAINER(taskList), item);
+
         g_signal_connect (TASK_ITEM (item), "task-item-closed",
                           G_CALLBACK (on_task_item_closed), taskList);
-      }
+
+        g_signal_connect (TASK_ITEM (item), "monitor-changed",
+                          G_CALLBACK (on_task_item_monitor_changed_cb),
+                          taskList);
+    }
 }
 
 static void type_changed (WnckWindow *window,
@@ -153,7 +261,11 @@ task_list_dispose (GObject *object)
 static void
 task_list_finalize (GObject *object)
 {
-    task_lists = g_slist_remove (task_lists, object);
+    TaskList *taskList;
+
+    taskList = TASK_LIST (object);
+
+    remove_task_list (taskList);
 
     G_OBJECT_CLASS (task_list_parent_class)->finalize (object);
 }
@@ -193,7 +305,7 @@ GtkWidget *task_list_new (WpApplet *windowPickerApplet) {
                                        NULL
     );
 
-    task_lists = g_slist_append (task_lists, taskList);
+    add_task_list (taskList);
 
     taskList->priv->windowPickerApplet = windowPickerApplet;
 
@@ -209,3 +321,16 @@ GtkWidget *task_list_new (WpApplet *windowPickerApplet) {
     }
     return (GtkWidget *) taskList;
 }
+
+gint
+task_list_get_monitor (TaskList *list)
+{
+    GdkScreen *gdk_screen;
+    GdkWindow *gdk_window;
+
+    gdk_window = gtk_widget_get_window (GTK_WIDGET (list));
+    gdk_screen = gtk_widget_get_screen (GTK_WIDGET (list));
+
+    return gdk_screen_get_monitor_at_window (gdk_screen,
+                                             gdk_window);
+}
diff --git a/windowpicker/src/task-list.h b/windowpicker/src/task-list.h
index 3fb4631..ae52620 100644
--- a/windowpicker/src/task-list.h
+++ b/windowpicker/src/task-list.h
@@ -42,9 +42,14 @@
 #define TASK_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\
     TASK_TYPE_LIST, TaskListClass))
 
-typedef struct _TaskList        TaskList;
-typedef struct _TaskListClass   TaskListClass;
-typedef struct _TaskListPrivate TaskListPrivate;
+#define TASK_LIST_GET_CLASS_PRIVATE(obj) (G_TYPE_CLASS_GET_PRIVATE ( \
+    TASK_LIST_GET_CLASS ((obj)), \
+    TASK_TYPE_LIST, TaskListClassPrivate))
+
+typedef struct _TaskList             TaskList;
+typedef struct _TaskListClass        TaskListClass;
+typedef struct _TaskListPrivate      TaskListPrivate;
+typedef struct _TaskListClassPrivate TaskListClassPrivate;
 
 struct _TaskList {
     GtkBox           parent;
@@ -52,11 +57,12 @@ struct _TaskList {
 };
 
 struct _TaskListClass {
-    GtkBoxClass parent_class;
+    GtkBoxClass           parent_class;
 };
 
 GType task_list_get_type (void) G_GNUC_CONST;
 GtkWidget * task_list_new (WpApplet* windowPickerApplet);
 gboolean    task_list_get_desktop_visible (TaskList *list);
+gint        task_list_get_monitor         (TaskList *list);
 
 #endif /* _TASK_LIST_H_ */


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