Patch to movehandle widget to make window snap to corners and edge centers

Jasper Huijsmans jasper at moongroup.com
Sat Mar 8 20:30:20 CET 2003


On 07 Mar 2003 20:52:22 +0100
Olivier Fourdan <fourdan at xfce.org> wrote:

> Hi Jasper,
> 
> I guess you can forget about struts awareness, but Xinerama would be
> definitly usefull.
> 

So, how about this. I haven't actually tested this with Xinerama, so it
would be helpful if somebody could do that for me.

Index: xfce_movehandler.c
===================================================================
RCS file:
/cvsroot/xfce/xfce-devel/libxfcegui4/libxfcegui4/xfce_movehandler.c,v
retrieving revision 1.5
diff -u -r1.5 xfce_movehandler.c
--- xfce_movehandler.c	18 Oct 2002 13:00:52 -0000	1.5
+++ xfce_movehandler.c	8 Mar 2003 18:52:39 -0000
@@ -24,9 +24,12 @@
 #include <stdlib.h>
 
 #include <gdk/gdk.h>
+#include <gdk/gdkx.h>
 #include <gdk/gdkcursor.h>
 #include <gtk/gtkwindow.h>
 #include "xfce_movehandler.h"
+#include "xinerama.h"
+#include "debug.h"
 
 #define DECOR_WIDTH  6
 #define DECOR_HEIGHT 6
@@ -286,6 +289,65 @@
     }
 }
 
+static void update_snap_coordinates(XfceMovehandler *movehandler)
+{
+    GtkWidget *win;
+    int x, y;
+    Display *dpy;
+    int scr;
+    
+    win = movehandler->gtk_window;
+    
+    /* TODO: for gtk 2.2 we could use gtk_widget_get_display() et al.
*/
+    dpy = gdk_display;
+    scr = DefaultScreen(dpy); 
+    
+    x = win->allocation.x + win->allocation.width / 2;
+    y = win->allocation.y + win->allocation.height / 2;
+    
+    movehandler->screen_x = MyDisplayX(x, y);
+    movehandler->screen_maxx = MyDisplayMaxX(dpy, scr, x, y);
+    movehandler->screen_y = MyDisplayY(x, y);
+    movehandler->screen_maxy = MyDisplayMaxY(dpy, scr, x, y);
+    
+    /* Snap coordinates: 4 corners + 4 edge centers */
+    /* top left */
+    movehandler->snapx[0] = movehandler->screen_x;
+    movehandler->snapy[0] = movehandler->screen_y;
+
+    /* top right */
+    movehandler->snapx[1] = movehandler->screen_maxx -
win->allocation.width;
+    movehandler->snapy[1] = movehandler->screen_y;
+    
+    /* bottom left */
+    movehandler->snapx[2] = movehandler->screen_x;
+    movehandler->snapy[2] = movehandler->screen_maxy -
win->allocation.height;
+
+    /* bottom right */
+    movehandler->snapx[3] = movehandler->snapx[1];
+    movehandler->snapy[3] = movehandler->snapy[2];
+    
+    /* top center */
+    movehandler->snapx[4] = 
+	(movehandler->screen_maxy - movehandler->screen_y) / 2 
+	- win->allocation.width / 2;
+    movehandler->snapy[4] = movehandler->screen_y;
+
+    /* bottom center */
+    movehandler->snapx[5] = movehandler->snapx[4];
+    movehandler->snapy[5] = movehandler->snapy[2];
+
+    /* left center */
+    movehandler->snapx[6] = movehandler->screen_x;
+    movehandler->snapy[6] = 
+	(movehandler->screen_maxy - movehandler->screen_y)/ 2 
+	- win->allocation.height / 2;
+
+    /* right center */
+    movehandler->snapx[7] = movehandler->snapx[1];
+    movehandler->snapy[7] = movehandler->snapy[6];
+}
+
 static gint xfce_movehandler_button_changed (GtkWidget *widget,
GdkEventButton *event)
 {
     XfceMovehandler *movehandler;
@@ -320,6 +382,8 @@
             movehandler->deskoff_x = desk_x - root_x;
             movehandler->deskoff_y = desk_y - root_y;
 
+	    update_snap_coordinates(movehandler);
+	    
             movehandler->in_drag = TRUE;
             fleur = gdk_cursor_new (GDK_FLEUR);
             if (gdk_pointer_grab (widget->window, FALSE,
(GDK_BUTTON1_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK |
GDK_BUTTON_RELEASE_MASK), NULL, fleur, GDK_CURRENT_TIME) != 0)
@@ -344,6 +408,54 @@
     return event_handled;
 }
 
+#define SNAP_DISTANCE 20
+
+static void snap_to_corners(XfceMovehandler *movehandler, int *x, int
*y)
+{
+    int i, center_x, center_y;
+    int *snapx, *snapy;
+    GtkWidget *win;
+    
+    win = movehandler->gtk_window;
+    
+    center_x = win->allocation.x + win->allocation.width / 2;
+    center_y = win->allocation.y + win->allocation.height / 2;
+    
+#if defined(HAVE_LIBXINERAMA) || defined(EMULATE_XINERAMA)
+    if (center_x < movehandler->screen_x ||
+	center_x > movehandler->screen_maxx ||
+	center_y < movehandler->screen_y ||
+	center_y > movehandler->screen_maxy)
+    {
+	update_snap_coordinates(movehandler);
+    }
+#endif
+
+    snapx = movehandler->snapx;
+    snapy = movehandler->snapy;
+    
+    /* snap to corners or edge centers (8 snap positions) */
+    for (i = 0; i < 8; i++)
+    {
+	int minx, maxx, miny, maxy;
+
+	minx = snapx[i] - SNAP_DISTANCE;
+	maxx = snapx[i] + SNAP_DISTANCE;
+	miny = snapy[i] - SNAP_DISTANCE;
+	maxy = snapy[i] + SNAP_DISTANCE;
+
+	if (*x > minx && *x < maxx && *y > miny && *y < maxy)
+	{
+	    *x = snapx[i];
+	    *y = snapy[i];
+
+	    DBG("snap: (x,y) = (%d,%d)\n", *x, *y);
+
+	    break;
+	}
+    }
+}
+
 static gint xfce_movehandler_motion (GtkWidget *widget, GdkEventMotion
*event)
 {
     XfceMovehandler *movehandler;
@@ -367,6 +479,8 @@
     new_x += movehandler->float_allocation.x + movehandler->deskoff_x;
     new_y += movehandler->float_allocation.y + movehandler->deskoff_y;
 
+    snap_to_corners(movehandler, &new_x, &new_y);
+    
     gdk_window_move (movehandler->float_window, new_x, new_y);
     gdk_window_raise (movehandler->float_window);
 
Index: xfce_movehandler.h
===================================================================
RCS file:
/cvsroot/xfce/xfce-devel/libxfcegui4/libxfcegui4/xfce_movehandler.h,v
retrieving revision 1.4
diff -u -r1.4 xfce_movehandler.h
--- xfce_movehandler.h	8 Oct 2002 19:56:37 -0000	1.4
+++ xfce_movehandler.h	8 Mar 2003 18:52:39 -0000
@@ -51,6 +51,9 @@
         GdkBitmap *dark_bmap;
         GdkBitmap *mid_bmap;
         GdkBitmap *light_bmap;
+
+	gint screen_x, screen_maxx, screen_y, screen_maxy;
+	gint snapx[8], snapy[8];
     };
 
     struct _XfceMovehandlerClass



More information about the Xfce4-dev mailing list