summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Soriano <csoriano@gnome.org>2016-06-28 14:54:05 +0200
committerCarlos Soriano <csoriano@gnome.org>2016-06-28 17:48:48 +0200
commit909cafe88b7d428896feaa94dc5dc18a3833f447 (patch)
treee6901bd0a48b6d839ab44d9c9cebb3eef4d857cc
parentfc25f7ecd682bb65404f1a21259269c0a473c31c (diff)
downloadnautilus-wip/csoriano/icons-on-primary.tar.gz
nautilus-desktop: Place icons only in primary monitorwip/csoriano/icons-on-primary
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.
-rw-r--r--nautilus-desktop/nautilus-desktop-canvas-view.c97
-rw-r--r--nautilus-desktop/nautilus-desktop-window.c227
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 1bb505253..830dc26f9 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 7c3abecb6..81392d658 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