...
This commit is contained in:
parent
71d3333d4d
commit
93b7bd2c81
@ -1290,6 +1290,10 @@ 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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
349
src/place.c
349
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
14
src/window.c
14
src/window.c
@ -1408,12 +1408,16 @@ meta_window_get_position (MetaWindow *window,
|
||||
{
|
||||
if (window->frame)
|
||||
{
|
||||
if (x)
|
||||
*x = window->frame->rect.x + window->frame->child_x;
|
||||
if (y)
|
||||
*y = window->frame->rect.y + window->frame->child_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x)
|
||||
*x = window->rect.x;
|
||||
if (y)
|
||||
*y = window->rect.y;
|
||||
}
|
||||
}
|
||||
@ -1489,6 +1493,16 @@ meta_window_get_gravity_position (MetaWindow *window,
|
||||
*root_y = y;
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user