[nautilus/wip/csoriano/icons-on-primary] nautilus-desktop: Place icons only in primary monitor



commit 909cafe88b7d428896feaa94dc5dc18a3833f447
Author: Carlos Soriano <csoriano gnome org>
Date:   Tue Jun 28 14:54:05 2016 +0200

    nautilus-desktop: Place icons only in primary monitor
    
    Due to the restrictions of using a big window we were making choices
    between different areas across monitors for placing icons.
    However that makes happy no one since depending on the area used the
    icons can jump or not being places on the primary monitor on certain
    multi monitor setups.
    
    For now use a single window that equals to the primary monitor to avoid
    these issues.
    For future we might want to have a single window per each monitor.

 nautilus-desktop/nautilus-desktop-canvas-view.c |   97 ++--------
 nautilus-desktop/nautilus-desktop-window.c      |  227 ++++++++++++++++++++---
 2 files changed, 214 insertions(+), 110 deletions(-)
---
diff --git a/nautilus-desktop/nautilus-desktop-canvas-view.c b/nautilus-desktop/nautilus-desktop-canvas-view.c
index 1bb5052..830dc26 100644
--- a/nautilus-desktop/nautilus-desktop-canvas-view.c
+++ b/nautilus-desktop/nautilus-desktop-canvas-view.c
@@ -59,11 +59,6 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-struct NautilusDesktopCanvasViewDetails
-{
-       GdkWindow *root_window;
-};
-
 static void     default_zoom_level_changed                        (gpointer                user_data);
 static void     real_update_context_menus                         (NautilusFilesView           *view);
 static char*    real_get_backing_uri                              (NautilusFilesView           *view);
@@ -86,31 +81,31 @@ canvas_container_set_workarea (NautilusCanvasContainer *canvas_container,
                             int                    n_items)
 {
        int left, right, top, bottom;
-       int screen_width, screen_height;
        int i;
+       GdkRectangle geometry;
 
        left = right = top = bottom = 0;
-
-       screen_width  = gdk_screen_get_width (screen);
-       screen_height = gdk_screen_get_height (screen);
+       gdk_screen_get_monitor_geometry (screen, gdk_screen_get_primary_monitor (screen), &geometry);
 
        for (i = 0; i < n_items; i += 4) {
-               int x      = workareas [i];
-               int y      = workareas [i + 1];
-               int width  = workareas [i + 2];
-               int height = workareas [i + 3];
+               GdkRectangle workarea;
 
-               if ((x + width) > screen_width || (y + height) > screen_height)
+               workarea.x = workareas[i];
+               workarea.y = workareas[i + 1];
+               workarea.width = workareas[i + 2];
+               workarea.height = workareas[i + 3];
+
+               if (!gdk_rectangle_intersect (&geometry, &workarea, &workarea))
                        continue;
 
-               left   = MAX (left, x);
-               right  = MAX (right, screen_width - width - x);
-               top    = MAX (top, y);
-               bottom = MAX (bottom, screen_height - height - y);
+               left   = MAX (left, workarea.x);
+               right  = MAX (right, (workarea.x + workarea.width) - (geometry.x + geometry.width));
+               top    = MAX (top, workarea.y);
+               bottom = MAX (bottom, (workarea.y + workarea.height) - (geometry.y + geometry.height));
        }
 
        nautilus_canvas_container_set_margins (canvas_container,
-                                            left, right, top, bottom);
+                                            0, 0, 0, 0);
 }
 
 static void
@@ -196,28 +191,6 @@ net_workarea_changed (NautilusDesktopCanvasView *canvas_view,
                g_free (workareas);
 }
 
-static GdkFilterReturn
-desktop_canvas_view_property_filter (GdkXEvent *gdk_xevent,
-                                  GdkEvent *event,
-                                  gpointer data)
-{
-       XEvent *xevent = gdk_xevent;
-       NautilusDesktopCanvasView *canvas_view;
-
-       canvas_view = NAUTILUS_DESKTOP_CANVAS_VIEW (data);
-  
-       switch (xevent->type) {
-       case PropertyNotify:
-               if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name ("_NET_WORKAREA"))
-                       net_workarea_changed (canvas_view, event->any.window);
-               break;
-       default:
-               break;
-       }
-
-       return GDK_FILTER_CONTINUE;
-}
-
 static guint
 real_get_id (NautilusFilesView *view)
 {
@@ -305,43 +278,6 @@ nautilus_desktop_canvas_view_class_init (NautilusDesktopCanvasViewClass *class)
        vclass->end_loading = nautilus_desktop_canvas_view_end_loading;
        vclass->get_backing_uri = real_get_backing_uri;
        vclass->check_empty_states = real_check_empty_states;
-
-       g_type_class_add_private (class, sizeof (NautilusDesktopCanvasViewDetails));
-}
-
-static void
-unrealized_callback (GtkWidget *widget, NautilusDesktopCanvasView *desktop_canvas_view)
-{
-       g_return_if_fail (desktop_canvas_view->details->root_window != NULL);
-
-       /* Remove the property filter */
-       gdk_window_remove_filter (desktop_canvas_view->details->root_window,
-                                 desktop_canvas_view_property_filter,
-                                 desktop_canvas_view);
-       desktop_canvas_view->details->root_window = NULL;
-}
-
-static void
-realized_callback (GtkWidget *widget, NautilusDesktopCanvasView *desktop_canvas_view)
-{
-       GdkWindow *root_window;
-       GdkScreen *screen;
-
-       g_return_if_fail (desktop_canvas_view->details->root_window == NULL);
-
-       screen = gtk_widget_get_screen (widget);
-       root_window = gdk_screen_get_root_window (screen);
-
-       desktop_canvas_view->details->root_window = root_window;
-
-       /* Read out the workarea geometry and update the icon container accordingly */
-       net_workarea_changed (desktop_canvas_view, root_window);
-
-       /* Setup the property filter */
-       gdk_window_set_events (root_window, GDK_PROPERTY_CHANGE_MASK);
-       gdk_window_add_filter (root_window,
-                              desktop_canvas_view_property_filter,
-                              desktop_canvas_view);
 }
 
 static void
@@ -696,11 +632,6 @@ nautilus_desktop_canvas_view_init (NautilusDesktopCanvasView *desktop_canvas_vie
        g_signal_connect_object (canvas_container, "realize",
                                 G_CALLBACK (desktop_canvas_container_realize), desktop_canvas_view, 0);
 
-       g_signal_connect_object (desktop_canvas_view, "realize",
-                                G_CALLBACK (realized_callback), desktop_canvas_view, 0);
-       g_signal_connect_object (desktop_canvas_view, "unrealize",
-                                G_CALLBACK (unrealized_callback), desktop_canvas_view, 0);
-
        g_signal_connect_swapped (nautilus_icon_view_preferences,
                                  "changed::" NAUTILUS_PREFERENCES_ICON_VIEW_DEFAULT_ZOOM_LEVEL,
                                  G_CALLBACK (default_zoom_level_changed),
diff --git a/nautilus-desktop/nautilus-desktop-window.c b/nautilus-desktop/nautilus-desktop-window.c
index 7c3abec..81392d6 100644
--- a/nautilus-desktop/nautilus-desktop-window.c
+++ b/nautilus-desktop/nautilus-desktop-window.c
@@ -45,6 +45,7 @@ struct NautilusDesktopWindowDetails {
        gboolean loaded;
 
        GtkWidget *desktop_selection;
+  GdkWindow *root_window;
 };
 
 G_DEFINE_TYPE (NautilusDesktopWindow, nautilus_desktop_window, 
@@ -166,6 +167,142 @@ nautilus_desktop_window_init_selection (NautilusDesktopWindow *window)
        window->details->desktop_selection = selection_widget;
 }
 
+static GdkRectangle*
+intersect_primary_monitor_with_workareas (NautilusDesktopWindow *window,
+                                          long                  *workareas,
+                                          int                    n_items)
+{
+       int i;
+       GdkRectangle geometry;
+       GdkRectangle *intersected_geometry;
+
+        intersected_geometry = g_new (GdkRectangle, 1);
+       gdk_screen_get_monitor_geometry (gdk_screen_get_default (),
+                                         gdk_screen_get_primary_monitor (gdk_screen_get_default ()),
+                                         &geometry);
+        intersected_geometry->x = geometry.x;
+        intersected_geometry->y = geometry.y;
+        intersected_geometry->width = geometry.width;
+        intersected_geometry->height = geometry.height;
+
+       for (i = 0; i < n_items; i += 4) {
+               GdkRectangle workarea;
+
+               workarea.x = workareas[i];
+               workarea.y = workareas[i + 1];
+               workarea.width = workareas[i + 2];
+               workarea.height = workareas[i + 3];
+
+                g_print ("owrkarea %d %d %d %d, intersected %d %d %d %d\n", workarea.x, workarea.y, 
workarea.width, workarea.height, intersected_geometry->x, intersected_geometry->y,
+                         intersected_geometry->width, intersected_geometry->height);
+               if (!gdk_rectangle_intersect (&geometry, &workarea, &workarea))
+                       continue;
+
+               intersected_geometry->x = MAX (intersected_geometry->x, workarea.x);
+               intersected_geometry->y = MAX (intersected_geometry->y, workarea.y);
+               intersected_geometry->width = MIN (intersected_geometry->width,
+                                                   workarea.x + workarea.width - intersected_geometry->x);
+               intersected_geometry->height = MIN (intersected_geometry->height,
+                                                    workarea.y + workarea.height - intersected_geometry->y);
+       }
+
+  return intersected_geometry;
+}
+
+static GdkRectangle*
+calculate_size_desktop_geometry (NautilusDesktopWindow *window)
+{
+       long *nworkareas = NULL;
+       long *workareas = NULL;
+       GdkAtom type_returned;
+       int format_returned;
+       int length_returned;
+        GdkWindow *root_window;
+        GdkRectangle *intersected_geometry = NULL;
+
+        g_print ("calculate size desktop\n");
+        root_window = gdk_screen_get_root_window (gdk_screen_get_default ());
+       /* Find the number of desktops so we know how long the
+        * workareas array is going to be (each desktop will have four
+        * elements in the workareas array describing
+        * x,y,width,height) */
+       gdk_error_trap_push ();
+       if (!gdk_property_get (root_window,
+                              gdk_atom_intern ("_NET_NUMBER_OF_DESKTOPS", FALSE),
+                              gdk_x11_xatom_to_atom (XA_CARDINAL),
+                              0, 4, FALSE,
+                              &type_returned,
+                              &format_returned,
+                              &length_returned,
+                              (guchar **) &nworkareas)) {
+               g_warning("Can not calculate _NET_NUMBER_OF_DESKTOPS");
+       }
+       if (gdk_error_trap_pop()
+           || nworkareas == NULL
+           || type_returned != gdk_x11_xatom_to_atom (XA_CARDINAL)
+           || format_returned != 32)
+               g_warning("Can not calculate _NET_NUMBER_OF_DESKTOPS");
+
+       /* Note : gdk_property_get() is broken (API documents admit
+        * this).  As a length argument, it expects the number of
+        * _bytes_ of data you require.  Internally, gdk_property_get
+        * converts that value to a count of 32 bit (4 byte) elements.
+        * However, the length returned is in bytes, but is calculated
+        * via the count of returned elements * sizeof(long).  This
+        * means on a 64 bit system, the number of bytes you have to
+        * request does not correspond to the number of bytes you get
+        * back, and is the reason for the workaround below.
+        */
+       gdk_error_trap_push ();
+       if (nworkareas == NULL || (*nworkareas < 1)
+           || !gdk_property_get (root_window,
+                                 gdk_atom_intern ("_NET_WORKAREA", FALSE),
+                                 gdk_x11_xatom_to_atom (XA_CARDINAL),
+                                 0, ((*nworkareas) * 4 * 4), FALSE,
+                                 &type_returned,
+                                 &format_returned,
+                                 &length_returned,
+                                 (guchar **) &workareas)) {
+               g_warning("Can not get _NET_WORKAREA");
+               workareas = NULL;
+       }
+
+       if (gdk_error_trap_pop ()
+           || workareas == NULL
+           || type_returned != gdk_x11_xatom_to_atom (XA_CARDINAL)
+           || ((*nworkareas) * 4 * sizeof(long)) != length_returned
+           || format_returned != 32) {
+              g_critical ("NET_WORKAREA canot be peeked");
+       } else {
+        g_print ("good good \n");
+                intersected_geometry = intersect_primary_monitor_with_workareas (window, workareas, 
*nworkareas);
+        }
+
+       if (nworkareas != NULL)
+               g_free (nworkareas);
+
+       if (workareas != NULL)
+               g_free (workareas);
+
+  return intersected_geometry;
+}
+
+static void
+net_workarea_changed (NautilusDesktopWindow *window)
+{
+  GdkRectangle *geometry;
+
+  geometry = calculate_size_desktop_geometry (window);
+  g_object_set (window,
+                "width_request", geometry->width,
+                "height_request", geometry->height,
+                NULL);
+
+  gtk_window_move (GTK_WINDOW (window), geometry->x, geometry->y);
+
+  g_free (geometry);
+}
+
 static void
 nautilus_desktop_window_constructed (GObject *obj)
 {
@@ -185,11 +322,11 @@ nautilus_desktop_window_constructed (GObject *obj)
        gtk_window_set_decorated (GTK_WINDOW (window),
                                  FALSE);
 
-       gtk_window_move (GTK_WINDOW (window), 0, 0);
-
-       g_object_set_data (G_OBJECT (window), "is_desktop_window", 
+       g_object_set_data (G_OBJECT (window), "is_desktop_window",
                           GINT_TO_POINTER (1));
 
+       net_workarea_changed (window);
+
        nautilus_desktop_window_init_selection (window);
        nautilus_desktop_window_init_actions (window);
 
@@ -218,6 +355,58 @@ nautilus_desktop_window_constructed (GObject *obj)
        }
 }
 
+static GdkFilterReturn
+root_window_property_filter (GdkXEvent *gdk_xevent,
+                                  GdkEvent *event,
+                                  gpointer data)
+{
+       XEvent *xevent = gdk_xevent;
+       NautilusDesktopWindow *window;
+
+       window = NAUTILUS_DESKTOP_WINDOW (data);
+
+       switch (xevent->type) {
+       case PropertyNotify:
+               if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name ("_NET_WORKAREA"))
+                       net_workarea_changed (window);
+               break;
+       default:
+               break;
+       }
+
+       return GDK_FILTER_CONTINUE;
+}
+
+
+static void
+unrealized_callback (GtkWidget *widget,
+                     NautilusDesktopWindow *window)
+{
+       /* Remove the property filter */
+       gdk_window_remove_filter (gdk_screen_get_root_window (gdk_screen_get_default ()),
+                                 root_window_property_filter,
+                                 window);
+}
+
+static void
+realized_callback (GtkWidget *widget, NautilusDesktopWindow *window)
+{
+       GdkWindow *root_window;
+       GdkScreen *screen;
+
+       screen = gtk_widget_get_screen (widget);
+       root_window = gdk_screen_get_root_window (screen);
+
+       /* Read out the workarea geometry and update the icon container accordingly */
+       net_workarea_changed (window);
+
+       /* Setup the property filter */
+       gdk_window_set_events (root_window, GDK_PROPERTY_CHANGE_MASK);
+       gdk_window_add_filter (root_window,
+                              root_window_property_filter,
+                              window);
+}
+
 static void
 nautilus_desktop_window_init (NautilusDesktopWindow *window)
 {
@@ -226,43 +415,27 @@ nautilus_desktop_window_init (NautilusDesktopWindow *window)
        gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (window)),
                                     "nautilus-desktop-window");
 
-}
+       g_signal_connect_object (window, "realize",
+                                G_CALLBACK (realized_callback), window, 0);
+       g_signal_connect_object (window, "unrealize",
+                                G_CALLBACK (unrealized_callback), window, 0);
 
-static void
-nautilus_desktop_window_screen_size_changed (GdkScreen             *screen,
-                                            NautilusDesktopWindow *window)
-{
-       int width_request, height_request;
-
-       width_request = gdk_screen_get_width (screen);
-       height_request = gdk_screen_get_height (screen);
-       
-       g_object_set (window,
-                     "width_request", width_request,
-                     "height_request", height_request,
-                     NULL);
 }
 
 static NautilusDesktopWindow *
 nautilus_desktop_window_new (void)
 {
-       GdkScreen *screen;
        GApplication *application;
        NautilusDesktopWindow *window;
-       int width_request, height_request;
 
        application = g_application_get_default ();
-       screen = gdk_screen_get_default ();
-       width_request = gdk_screen_get_width (screen);
-       height_request = gdk_screen_get_height (screen);
-
        window = g_object_new (NAUTILUS_TYPE_DESKTOP_WINDOW,
                               "application", application,
                               "disable-chrome", TRUE,
-                              "width_request", width_request,
-                              "height_request", height_request,
                               NULL);
 
+        net_workarea_changed (window);
+
        return window;
 }
 
@@ -361,8 +534,8 @@ realize (GtkWidget *widget)
        set_wmspec_desktop_hint (gtk_widget_get_window (widget));
 
        details->size_changed_id =
-               g_signal_connect (gtk_window_get_screen (GTK_WINDOW (window)), "size-changed",
-                                 G_CALLBACK (nautilus_desktop_window_screen_size_changed), window);
+               g_signal_connect_swapped (gtk_window_get_screen (GTK_WINDOW (window)), "size-changed",
+                                 G_CALLBACK (net_workarea_changed), window);
 }
 
 static void


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