diff options
author | Carlos Soriano <csoriano@gnome.org> | 2016-06-28 14:54:05 +0200 |
---|---|---|
committer | Carlos Soriano <csoriano@gnome.org> | 2016-06-28 17:48:48 +0200 |
commit | 909cafe88b7d428896feaa94dc5dc18a3833f447 (patch) | |
tree | e6901bd0a48b6d839ab44d9c9cebb3eef4d857cc | |
parent | fc25f7ecd682bb65404f1a21259269c0a473c31c (diff) | |
download | nautilus-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.c | 97 | ||||
-rw-r--r-- | 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 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 |