mouse: rework mouse_client_move
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
6a96c25be2
commit
4d2dcb4476
123
mouse.c
123
mouse.c
|
@ -364,124 +364,111 @@ mouse_get_client_under_pointer()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Move the focused window with the mouse.
|
/** 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
|
static void
|
||||||
mouse_client_move(client_t *c, int snap, bool infobox)
|
mouse_client_move(client_t *c, int snap, bool infobox)
|
||||||
{
|
{
|
||||||
int ocx, ocy, newscreen;
|
/* current mouse postion */
|
||||||
area_t geometry;
|
int mouse_x, mouse_y;
|
||||||
client_t *target;
|
/* last mouse position */
|
||||||
|
int last_x, last_y;
|
||||||
|
/* current layout */
|
||||||
layout_t *layout;
|
layout_t *layout;
|
||||||
|
/* the infobox */
|
||||||
simple_window_t *sw = NULL;
|
simple_window_t *sw = NULL;
|
||||||
draw_context_t *ctx;
|
draw_context_t *ctx;
|
||||||
xcb_generic_event_t *ev = NULL;
|
/* the root window */
|
||||||
xcb_motion_notify_event_t *ev_motion = NULL;
|
xcb_window_t root;
|
||||||
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;
|
|
||||||
|
|
||||||
layout = layout_get_current(c->screen);
|
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 */
|
/* get current pointer position */
|
||||||
grab_pointer_c = xcb_grab_pointer_unchecked(globalconf.connection, false, s->root,
|
mouse_query_pointer(root, &last_x, &last_y);
|
||||||
MOUSEMASK, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC,
|
|
||||||
s->root, globalconf.cursor[CurMove], XCB_CURRENT_TIME);
|
|
||||||
|
|
||||||
query_pointer_c = xcb_query_pointer_unchecked(globalconf.connection, s->root);
|
/* grab pointer */
|
||||||
|
mouse_grab_pointer(root, CurMove);
|
||||||
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;
|
|
||||||
|
|
||||||
c->ismax = false;
|
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))
|
if(infobox && (c->isfloating || layout == layout_floating))
|
||||||
{
|
{
|
||||||
sw = mouse_infobox_new(c->phys_screen, c->border, c->geometry, &ctx);
|
sw = mouse_infobox_new(c->phys_screen, c->border, c->geometry, &ctx);
|
||||||
xcb_aux_sync(globalconf.connection);
|
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)))
|
|
||||||
{
|
|
||||||
switch((ev->response_type & 0x7f))
|
|
||||||
{
|
|
||||||
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)
|
if(c->isfloating || layout == layout_floating)
|
||||||
{
|
{
|
||||||
ev_motion = (xcb_motion_notify_event_t *) ev;
|
area_t geometry;
|
||||||
|
|
||||||
geometry.x = ocx + (ev_motion->event_x - query_pointer_r->root_x);
|
/* calc new geometry */
|
||||||
geometry.y = ocy + (ev_motion->event_y - query_pointer_r->root_y);
|
geometry = c->geometry;
|
||||||
|
geometry.x += (mouse_x - last_x);
|
||||||
|
geometry.y += (mouse_y - last_y);
|
||||||
|
|
||||||
|
/* snap and move */
|
||||||
geometry = mouse_snapclient(c, geometry, snap);
|
geometry = mouse_snapclient(c, geometry, snap);
|
||||||
c->ismoving = true;
|
c->ismoving = true;
|
||||||
client_resize(c, geometry, false);
|
client_resize(c, geometry, false);
|
||||||
c->ismoving = false;
|
c->ismoving = false;
|
||||||
|
|
||||||
|
/* draw the infobox */
|
||||||
if(sw)
|
if(sw)
|
||||||
|
{
|
||||||
mouse_infobox_draw(ctx, sw, c->geometry, c->border);
|
mouse_infobox_draw(ctx, sw, c->geometry, c->border);
|
||||||
|
|
||||||
xcb_aux_sync(globalconf.connection);
|
xcb_aux_sync(globalconf.connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* keep track */
|
||||||
|
last_x = mouse_x;
|
||||||
|
last_y = mouse_y;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
query_pointer_c = xcb_query_pointer_unchecked(globalconf.connection, s->root);
|
int newscreen;
|
||||||
mquery_pointer_r = xcb_query_pointer_reply(globalconf.connection, query_pointer_c, NULL);
|
client_t *target;
|
||||||
if((newscreen = screen_get_bycoord(globalconf.screens_info, c->screen,
|
|
||||||
mquery_pointer_r->root_x,
|
/* client moved to another screen? */
|
||||||
mquery_pointer_r->root_y)) != c->screen)
|
newscreen = screen_get_bycoord(globalconf.screens_info, c->screen,
|
||||||
|
mouse_x, mouse_y);
|
||||||
|
if(newscreen != c->screen)
|
||||||
{
|
{
|
||||||
screen_client_moveto(c, newscreen, true);
|
screen_client_moveto(c, newscreen, true);
|
||||||
globalconf.screens[c->screen].need_arrange = true;
|
globalconf.screens[c->screen].need_arrange = true;
|
||||||
globalconf.screens[newscreen].need_arrange = true;
|
globalconf.screens[newscreen].need_arrange = true;
|
||||||
layout_refresh();
|
layout_refresh();
|
||||||
}
|
}
|
||||||
if((target = client_getbywin(mquery_pointer_r->child))
|
|
||||||
&& target != c && !target->isfloating)
|
/* find client to swap with */
|
||||||
|
target = mouse_get_client_under_pointer();
|
||||||
|
|
||||||
|
/* swap position */
|
||||||
|
if(target && target != c && !target->isfloating)
|
||||||
{
|
{
|
||||||
client_list_swap(&globalconf.clients, c, target);
|
client_list_swap(&globalconf.clients, c, target);
|
||||||
globalconf.screens[c->screen].need_arrange = true;
|
globalconf.screens[c->screen].need_arrange = true;
|
||||||
layout_refresh();
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue