mouse: rework mouse_client_move

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Michael Gehring 2008-06-15 17:32:03 +02:00 committed by Julien Danjou
parent 6a96c25be2
commit 4d2dcb4476
1 changed files with 75 additions and 88 deletions

163
mouse.c
View File

@ -364,124 +364,111 @@ mouse_get_client_under_pointer()
}
/** Move the focused window with the mouse.
* \param c The client.
* \param snap The maximum distance in pixels to trigger a "snap".
* \param infobox Enable or disable the infobox.
*/
static void
mouse_client_move(client_t *c, int snap, bool infobox)
{
int ocx, ocy, newscreen;
area_t geometry;
client_t *target;
/* current mouse postion */
int mouse_x, mouse_y;
/* last mouse position */
int last_x, last_y;
/* current layout */
layout_t *layout;
/* the infobox */
simple_window_t *sw = NULL;
draw_context_t *ctx;
xcb_generic_event_t *ev = NULL;
xcb_motion_notify_event_t *ev_motion = NULL;
xcb_grab_pointer_reply_t *grab_pointer_r = NULL;
xcb_grab_pointer_cookie_t grab_pointer_c;
xcb_query_pointer_reply_t *query_pointer_r = NULL, *mquery_pointer_r = NULL;
xcb_query_pointer_cookie_t query_pointer_c;
xcb_screen_t *s;
/* the root window */
xcb_window_t root;
layout = layout_get_current(c->screen);
s = xcb_aux_get_screen(globalconf.connection, c->phys_screen);
root = xcb_aux_get_screen(globalconf.connection, c->phys_screen)->root;
/* Send pointer requests */
grab_pointer_c = xcb_grab_pointer_unchecked(globalconf.connection, false, s->root,
MOUSEMASK, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC,
s->root, globalconf.cursor[CurMove], XCB_CURRENT_TIME);
/* get current pointer position */
mouse_query_pointer(root, &last_x, &last_y);
query_pointer_c = xcb_query_pointer_unchecked(globalconf.connection, s->root);
geometry = c->geometry;
ocx = geometry.x;
ocy = geometry.y;
/* Get responses */
if(!(grab_pointer_r = xcb_grab_pointer_reply(globalconf.connection, grab_pointer_c, NULL)))
return;
/* grab pointer */
mouse_grab_pointer(root, CurMove);
c->ismax = false;
p_delete(&grab_pointer_r);
query_pointer_r = xcb_query_pointer_reply(globalconf.connection, query_pointer_c, NULL);
if(infobox && (c->isfloating || layout == layout_floating))
{
sw = mouse_infobox_new(c->phys_screen, c->border, c->geometry, &ctx);
xcb_aux_sync(globalconf.connection);
}
while(true)
/* for each motion event */
while(mouse_track_mouse_drag(&mouse_x, &mouse_y))
{
/* XMaskEvent allows to retrieve only specified events from
* the queue and requeue the other events... */
while(ev || (ev = xcb_wait_for_event(globalconf.connection)))
if(c->isfloating || layout == layout_floating)
{
switch((ev->response_type & 0x7f))
area_t geometry;
/* calc new geometry */
geometry = c->geometry;
geometry.x += (mouse_x - last_x);
geometry.y += (mouse_y - last_y);
/* snap and move */
geometry = mouse_snapclient(c, geometry, snap);
c->ismoving = true;
client_resize(c, geometry, false);
c->ismoving = false;
/* draw the infobox */
if(sw)
{
case XCB_BUTTON_RELEASE:
xcb_ungrab_pointer(globalconf.connection, XCB_CURRENT_TIME);
if(sw)
{
draw_context_delete(&ctx);
simplewindow_delete(&sw);
}
p_delete(&query_pointer_r);
p_delete(&ev);
return;
case XCB_MOTION_NOTIFY:
if(c->isfloating || layout == layout_floating)
{
ev_motion = (xcb_motion_notify_event_t *) ev;
mouse_infobox_draw(ctx, sw, c->geometry, c->border);
xcb_aux_sync(globalconf.connection);
}
geometry.x = ocx + (ev_motion->event_x - query_pointer_r->root_x);
geometry.y = ocy + (ev_motion->event_y - query_pointer_r->root_y);
/* keep track */
last_x = mouse_x;
last_y = mouse_y;
}
else
{
int newscreen;
client_t *target;
geometry = mouse_snapclient(c, geometry, snap);
c->ismoving = true;
client_resize(c, geometry, false);
c->ismoving = false;
/* client moved to another screen? */
newscreen = screen_get_bycoord(globalconf.screens_info, c->screen,
mouse_x, mouse_y);
if(newscreen != c->screen)
{
screen_client_moveto(c, newscreen, true);
globalconf.screens[c->screen].need_arrange = true;
globalconf.screens[newscreen].need_arrange = true;
layout_refresh();
}
if(sw)
mouse_infobox_draw(ctx, sw, c->geometry, c->border);
/* find client to swap with */
target = mouse_get_client_under_pointer();
xcb_aux_sync(globalconf.connection);
}
else
{
query_pointer_c = xcb_query_pointer_unchecked(globalconf.connection, s->root);
mquery_pointer_r = xcb_query_pointer_reply(globalconf.connection, query_pointer_c, NULL);
if((newscreen = screen_get_bycoord(globalconf.screens_info, c->screen,
mquery_pointer_r->root_x,
mquery_pointer_r->root_y)) != c->screen)
{
screen_client_moveto(c, newscreen, true);
globalconf.screens[c->screen].need_arrange = true;
globalconf.screens[newscreen].need_arrange = true;
layout_refresh();
}
if((target = client_getbywin(mquery_pointer_r->child))
&& target != c && !target->isfloating)
{
client_list_swap(&globalconf.clients, c, target);
globalconf.screens[c->screen].need_arrange = true;
layout_refresh();
}
p_delete(&mquery_pointer_r);
}
p_delete(&ev);
while((ev = xcb_poll_for_event(globalconf.connection))
&& (ev->response_type & 0x7f) == XCB_MOTION_NOTIFY)
p_delete(&ev);
break;
default:
xcb_handle_event(globalconf.evenths, ev);
p_delete(&ev);
break;
/* swap position */
if(target && target != c && !target->isfloating)
{
client_list_swap(&globalconf.clients, c, target);
globalconf.screens[c->screen].need_arrange = true;
layout_refresh();
}
}
}
/* ungrab pointer */
xcb_ungrab_pointer(globalconf.connection, XCB_CURRENT_TIME);
/* free the infobox */
if(sw)
{
draw_context_delete(&ctx);
simplewindow_delete(&sw);
}
xcb_aux_sync(globalconf.connection);
}