summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrhp <rhp>2001-07-12 05:53:56 +0000
committerrhp <rhp>2001-07-12 05:53:56 +0000
commit93b7bd2c8157fe727eff70d642a5c9623cf28015 (patch)
tree1112ee11037a7a69bae4b7a0b7cf60a09097d667
parent71d3333d4de1b02dbfd415edd6051ce14510f15e (diff)
downloadmutter-93b7bd2c8157fe727eff70d642a5c9623cf28015.tar.gz
...
-rw-r--r--src/display.c6
-rw-r--r--src/display.h1
-rw-r--r--src/keybindings.c50
-rw-r--r--src/place.c349
-rw-r--r--src/place.h5
-rwxr-xr-xsrc/run-metacity.sh2
-rw-r--r--src/session.c4
-rw-r--r--src/window.c22
-rw-r--r--src/window.h2
9 files changed, 429 insertions, 12 deletions
diff --git a/src/display.c b/src/display.c
index 0d4d6b165..aec65d798 100644
--- a/src/display.c
+++ b/src/display.c
@@ -1290,7 +1290,11 @@ meta_display_begin_grab_op (MetaDisplay *display,
display->grab_button = button;
display->grab_root_x = root_x;
display->grab_root_y = root_y;
-
+ display->grab_initial_window_pos = window->rect;
+ meta_window_get_position (display->grab_window,
+ &display->grab_initial_window_pos.x,
+ &display->grab_initial_window_pos.y);
+
meta_verbose ("Grab op %d on window %s successful\n",
display->grab_op, display->grab_window->desc);
diff --git a/src/display.h b/src/display.h
index f2afd56ea..11718ab49 100644
--- a/src/display.h
+++ b/src/display.h
@@ -129,6 +129,7 @@ struct _MetaDisplay
gulong grab_mask;
guint grab_have_pointer : 1;
guint grab_have_keyboard : 1;
+ MetaRectangle grab_initial_window_pos;
};
gboolean meta_display_open (const char *name);
diff --git a/src/keybindings.c b/src/keybindings.c
index 759baf8d0..f91c7d0a4 100644
--- a/src/keybindings.c
+++ b/src/keybindings.c
@@ -24,6 +24,7 @@
#include "errors.h"
#include "ui.h"
#include "frame.h"
+#include "place.h"
#include <X11/keysym.h>
@@ -401,47 +402,84 @@ meta_display_process_key_event (MetaDisplay *display,
int x, y;
int incr;
gboolean smart_snap;
+ int edge;
+
+ if (event->type == KeyRelease)
+ return; /* don't care about releases */
if (window == NULL)
meta_bug ("NULL window while META_GRAB_OP_MOVING\n");
meta_window_get_position (window, &x, &y);
- smart_snap =
- (event->xkey.state & ControlMask) != 0 &&
- (event->xkey.state & ShiftMask) != 0;
+ smart_snap = (event->xkey.state & ShiftMask) != 0;
- /* FIXME replace LARGE_INCREMENT with intelligent snapping */
#define SMALL_INCREMENT 1
#define NORMAL_INCREMENT 10
-#define LARGE_INCREMENT 100
if (smart_snap)
- incr = LARGE_INCREMENT;
+ incr = 0;
else if (event->xkey.state & ControlMask)
incr = SMALL_INCREMENT;
else
incr = NORMAL_INCREMENT;
+
+ /* When moving by increments, we still snap to edges if the move
+ * to the edge is smaller than the increment. This is because
+ * Shift + arrow to snap is sort of a hidden feature. This way
+ * people using just arrows shouldn't get too frustrated.
+ */
switch (keysym)
{
case XK_Up:
+ case XK_KP_Up:
+ edge = meta_window_find_next_horizontal_edge (window, FALSE);
y -= incr;
+
+ if (smart_snap || ((edge > y) && ABS (edge - y) < incr))
+ y = edge;
+
handled = TRUE;
break;
case XK_Down:
+ case XK_KP_Down:
+ edge = meta_window_find_next_horizontal_edge (window, TRUE);
y += incr;
+
+ if (smart_snap || ((edge < y) && ABS (edge - y) < incr))
+ y = edge;
+
handled = TRUE;
break;
case XK_Left:
+ case XK_KP_Left:
+ edge = meta_window_find_next_vertical_edge (window, FALSE);
x -= incr;
+
+ if (smart_snap || ((edge > x) && ABS (edge - x) < incr))
+ x = edge;
+
handled = TRUE;
break;
case XK_Right:
+ case XK_KP_Right:
+ edge = meta_window_find_next_vertical_edge (window, TRUE);
x += incr;
+ if (smart_snap || ((edge < x) && ABS (edge - x) < incr))
+ x = edge;
handled = TRUE;
break;
+ case XK_Escape:
+ /* End move and restore to original position */
+ meta_window_move_resize (display->grab_window,
+ display->grab_initial_window_pos.x,
+ display->grab_initial_window_pos.y,
+ display->grab_initial_window_pos.width,
+ display->grab_initial_window_pos.height);
+ break;
+
default:
break;
}
diff --git a/src/place.c b/src/place.c
index c303cfb44..f2c70adbe 100644
--- a/src/place.c
+++ b/src/place.c
@@ -23,6 +23,7 @@
#include "workspace.h"
#include <gdk/gdkregion.h>
#include <math.h>
+#include <stdlib.h>
static gint
northwestcmp (gconstpointer a, gconstpointer b)
@@ -304,3 +305,351 @@ meta_window_place (MetaWindow *window,
*new_x = x;
*new_y = y;
}
+
+
+/* These are used while moving or resizing to "snap" to useful
+ * places; the return value is the x/y position of the window to
+ * be snapped to the given edge.
+ *
+ * They only use edges on the current workspace, since things
+ * would be weird otherwise.
+ */
+static GSList*
+get_windows_on_same_workspace (MetaWindow *window,
+ int *n_windows)
+{
+ GSList *windows;
+ GSList *all_windows;
+ GSList *tmp;
+ int i;
+
+ windows = NULL;
+
+ i = 0;
+ all_windows = meta_display_list_windows (window->display);
+
+ tmp = all_windows;
+ while (tmp != NULL)
+ {
+ MetaWindow *w = tmp->data;
+
+ if (!w->minimized &&
+ w != window &&
+ meta_workspace_contains_window (window->screen->active_workspace,
+ w))
+ {
+ windows = g_slist_prepend (windows, w);
+ ++i;
+ }
+
+ tmp = tmp->next;
+ }
+
+ if (n_windows)
+ *n_windows = i;
+
+ return windows;
+}
+
+static void
+window_get_edges (MetaWindow *w,
+ int *left,
+ int *right,
+ int *top,
+ int *bottom)
+{
+ int left_edge;
+ int right_edge;
+ int top_edge;
+ int bottom_edge;
+ MetaRectangle rect;
+
+ meta_window_get_outer_rect (w, &rect);
+
+ left_edge = rect.x;
+ right_edge = rect.x + rect.width;
+ top_edge = rect.y;
+ bottom_edge = rect.y + rect.height;
+
+ if (left)
+ *left = left_edge;
+ if (right)
+ *right = right_edge;
+ if (top)
+ *top = top_edge;
+ if (bottom)
+ *bottom = bottom_edge;
+}
+
+static int
+intcmp (const void* a, const void* b)
+{
+ const int *ai = a;
+ const int *bi = b;
+
+ if (*ai < *bi)
+ return -1;
+ else if (*ai > *bi)
+ return 1;
+ else
+ return 0;
+}
+
+static gboolean
+rects_overlap_vertically (const MetaRectangle *a,
+ const MetaRectangle *b)
+{
+ /* if they don't overlap, then either a is above b
+ * or b is above a
+ */
+ if ((a->y + a->height) < b->y)
+ return FALSE;
+ else if ((b->y + b->height) < a->y)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+static gboolean
+rects_overlap_horizontally (const MetaRectangle *a,
+ const MetaRectangle *b)
+{
+ if ((a->x + a->width) < b->x)
+ return FALSE;
+ else if ((b->x + b->width) < a->x)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+int
+meta_window_find_next_vertical_edge (MetaWindow *window,
+ gboolean right)
+{
+ GSList *windows;
+ GSList *tmp;
+ int left_edge, right_edge;
+ int n_windows;
+ int *edges;
+ int i;
+ int n_edges;
+ int retval;
+ MetaRectangle rect;
+
+ windows = get_windows_on_same_workspace (window, &n_windows);
+
+ i = 0;
+ n_edges = n_windows * 2 + 4; /* 4 = workspace/screen edges */
+ edges = g_new (int, n_edges);
+
+ /* workspace/screen edges */
+ edges[i] = window->screen->active_workspace->workarea.x;
+ ++i;
+ edges[i] =
+ window->screen->active_workspace->workarea.x +
+ window->screen->active_workspace->workarea.width;
+ ++i;
+ edges[i] = 0;
+ ++i;
+ edges[i] = window->screen->width;
+ ++i;
+
+ g_assert (i == 4);
+
+ meta_window_get_outer_rect (window, &rect);
+
+ /* get window edges */
+ tmp = windows;
+ while (tmp != NULL)
+ {
+ MetaWindow *w = tmp->data;
+ MetaRectangle w_rect;
+
+ meta_window_get_outer_rect (w, &w_rect);
+
+ if (rects_overlap_vertically (&rect, &w_rect))
+ {
+ window_get_edges (w, &edges[i], &edges[i+1], NULL, NULL);
+ i += 2;
+ }
+
+ tmp = tmp->next;
+ }
+ n_edges = i;
+
+ g_slist_free (windows);
+
+ /* Sort */
+ qsort (edges, n_edges, sizeof (int), intcmp);
+
+ /* Find next */
+ meta_window_get_position (window, &retval, NULL);
+
+ window_get_edges (window, &left_edge, &right_edge, NULL, NULL);
+
+ if (right)
+ {
+ i = 0;
+ while (i < n_edges)
+ {
+ if (edges[i] > right_edge)
+ {
+ /* This is the one we want, snap right
+ * edge of window to edges[i]
+ */
+ retval = edges[i];
+ if (window->frame)
+ {
+ retval -= window->frame->rect.width;
+ retval += window->frame->child_x;
+ }
+ else
+ {
+ retval -= window->rect.width;
+ }
+ break;
+ }
+
+ ++i;
+ }
+ }
+ else
+ {
+ i = n_edges;
+ do
+ {
+ --i;
+
+ if (edges[i] < left_edge)
+ {
+ /* This is the one we want */
+ retval = edges[i];
+ if (window->frame)
+ retval += window->frame->child_x;
+
+ break;
+ }
+ }
+ while (i > 0);
+ }
+
+ g_free (edges);
+
+ return retval;
+}
+
+int
+meta_window_find_next_horizontal_edge (MetaWindow *window,
+ gboolean down)
+{
+ GSList *windows;
+ GSList *tmp;
+ int top_edge, bottom_edge;
+ int n_windows;
+ int *edges;
+ int i;
+ int n_edges;
+ int retval;
+ MetaRectangle rect;
+
+ windows = get_windows_on_same_workspace (window, &n_windows);
+
+ i = 0;
+ n_edges = n_windows * 2 + 4; /* 4 = workspace/screen edges */
+ edges = g_new (int, n_edges);
+
+ /* workspace/screen edges */
+ edges[i] = window->screen->active_workspace->workarea.y;
+ ++i;
+ edges[i] =
+ window->screen->active_workspace->workarea.y +
+ window->screen->active_workspace->workarea.height;
+ ++i;
+ edges[i] = 0;
+ ++i;
+ edges[i] = window->screen->height;
+ ++i;
+
+ g_assert (i == 4);
+
+ meta_window_get_outer_rect (window, &rect);
+
+ /* get window edges */
+ tmp = windows;
+ while (tmp != NULL)
+ {
+ MetaWindow *w = tmp->data;
+ MetaRectangle w_rect;
+
+ meta_window_get_outer_rect (w, &w_rect);
+
+ if (rects_overlap_horizontally (&rect, &w_rect))
+ {
+ window_get_edges (w, NULL, NULL, &edges[i], &edges[i+1]);
+ i += 2;
+ }
+
+ tmp = tmp->next;
+ }
+ n_edges = i;
+
+ g_slist_free (windows);
+
+ /* Sort */
+ qsort (edges, n_edges, sizeof (int), intcmp);
+
+ /* Find next */
+ meta_window_get_position (window, NULL, &retval);
+
+ window_get_edges (window, NULL, NULL, &top_edge, &bottom_edge);
+
+ if (down)
+ {
+ i = 0;
+ while (i < n_edges)
+ {
+ if (edges[i] > bottom_edge)
+ {
+ /* This is the one we want, snap right
+ * edge of window to edges[i]
+ */
+ retval = edges[i];
+ if (window->frame)
+ {
+ retval -= window->frame->rect.height;
+ retval += window->frame->child_y;
+ }
+ else
+ {
+ retval -= window->rect.height;
+ }
+ break;
+ }
+
+ ++i;
+ }
+ }
+ else
+ {
+ i = n_edges;
+ do
+ {
+ --i;
+
+ if (edges[i] < top_edge)
+ {
+ /* This is the one we want */
+ retval = edges[i];
+ if (window->frame)
+ retval += window->frame->child_y;
+
+ break;
+ }
+ }
+ while (i > 0);
+ }
+
+ g_free (edges);
+
+ return retval;
+}
diff --git a/src/place.h b/src/place.h
index 6b79ecdc9..1d3274ba8 100644
--- a/src/place.h
+++ b/src/place.h
@@ -32,6 +32,11 @@ void meta_window_place (MetaWindow *window,
int *new_x,
int *new_y);
+int meta_window_find_next_vertical_edge (MetaWindow *window,
+ gboolean right);
+int meta_window_find_next_horizontal_edge (MetaWindow *window,
+ gboolean down);
+
#endif
diff --git a/src/run-metacity.sh b/src/run-metacity.sh
index 7aa123a71..b2266dc97 100755
--- a/src/run-metacity.sh
+++ b/src/run-metacity.sh
@@ -15,7 +15,7 @@ if test -z "$CLIENTS"; then
fi
if test -z "$ONLY_WM"; then
- Xnest -ac :1 -scrns $SCREENS -geometry 640x400 -bw 15 &
+ Xnest -ac :1 -scrns $SCREENS -geometry 640x480 -bw 15 &
usleep 500000
if test $CLIENTS != 0; then
diff --git a/src/session.c b/src/session.c
index 414b59881..15258516c 100644
--- a/src/session.c
+++ b/src/session.c
@@ -54,6 +54,10 @@ process_ice_messages (GIOChannel *channel,
IceConn connection = (IceConn) client_data;
IceProcessMessagesStatus status;
+ /* This blocks infinitely sometimes. I don't know what
+ * to do about it. Checking "condition" just breaks
+ * session management.
+ */
status = IceProcessMessages (connection, NULL, NULL);
if (status == IceProcessMessagesIOError)
diff --git a/src/window.c b/src/window.c
index 0c0724635..cb079b97e 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1408,13 +1408,17 @@ meta_window_get_position (MetaWindow *window,
{
if (window->frame)
{
- *x = window->frame->rect.x + window->frame->child_x;
- *y = window->frame->rect.y + window->frame->child_y;
+ if (x)
+ *x = window->frame->rect.x + window->frame->child_x;
+ if (y)
+ *y = window->frame->rect.y + window->frame->child_y;
}
else
{
- *x = window->rect.x;
- *y = window->rect.y;
+ if (x)
+ *x = window->rect.x;
+ if (y)
+ *y = window->rect.y;
}
}
@@ -1490,6 +1494,16 @@ meta_window_get_gravity_position (MetaWindow *window,
}
void
+meta_window_get_outer_rect (MetaWindow *window,
+ MetaRectangle *rect)
+{
+ if (window->frame)
+ *rect = window->frame->rect;
+ else
+ *rect = window->rect;
+}
+
+void
meta_window_delete (MetaWindow *window,
Time timestamp)
{
diff --git a/src/window.h b/src/window.h
index 192a0daf3..9bd3b8b9d 100644
--- a/src/window.h
+++ b/src/window.h
@@ -257,6 +257,8 @@ void meta_window_get_position (MetaWindow *window,
void meta_window_get_gravity_position (MetaWindow *window,
int *x,
int *y);
+void meta_window_get_outer_rect (MetaWindow *window,
+ MetaRectangle *rect);
void meta_window_delete (MetaWindow *window,
Time timestamp);
void meta_window_focus (MetaWindow *window,