mirror of https://github.com/mpv-player/mpv
x11: implement window dragging by grabbing
We don't check whether the WM supports _NET_WM_MOVERESIZE_MOVE, but if it doesn't, nothing bad happens. There might be a race condition when pressing a button, and then moving the mouse and releasing the button at the same time; then the WM might get the message to initiate moving the window after the mouse button has been released, in which case the result will probably be annoying. This could possibly be fixed by sending _NET_WM_MOVERESIZE_CANCEL on button release, but on the other hand, we probably won't receive a button release event in this situation, so ignore this problem. The dragging is initiated only when moving the mouse pointer after a click in order to reduce annoying behavior when the user is e.g. doubleclicking. Closes #608.
This commit is contained in:
parent
4751fe408b
commit
19f101db68
|
@ -405,6 +405,7 @@ static void init_atoms(struct vo_x11_state *x11)
|
|||
XA_INIT(_NET_WM_NAME);
|
||||
XA_INIT(_NET_WM_ICON_NAME);
|
||||
XA_INIT(_NET_WM_ICON);
|
||||
XA_INIT(_NET_WM_MOVERESIZE);
|
||||
XA_INIT(_WIN_PROTOCOLS);
|
||||
XA_INIT(_WIN_LAYER);
|
||||
XA_INIT(_WIN_HINTS);
|
||||
|
@ -940,20 +941,51 @@ int vo_x11_check_events(struct vo *vo)
|
|||
{
|
||||
if (x11->no_autorepeat)
|
||||
mp_input_put_key(vo->input_ctx, MP_INPUT_RELEASE_ALL);
|
||||
x11->win_drag_button1_down = false;
|
||||
break;
|
||||
}
|
||||
case MotionNotify:
|
||||
vo_mouse_movement(vo, Event.xmotion.x, Event.xmotion.y);
|
||||
if (x11->win_drag_button1_down && !x11->fs &&
|
||||
!mp_input_test_dragging(vo->input_ctx, Event.xmotion.x,
|
||||
Event.xmotion.y))
|
||||
{
|
||||
XUngrabPointer(x11->display, CurrentTime);
|
||||
x11->win_drag_button1_down = false;
|
||||
|
||||
XEvent xev;
|
||||
xev.xclient.type = ClientMessage;
|
||||
xev.xclient.serial = 0;
|
||||
xev.xclient.send_event = True;
|
||||
xev.xclient.message_type = x11->XA_NET_WM_MOVERESIZE;
|
||||
xev.xclient.window = x11->window;
|
||||
xev.xclient.format = 32;
|
||||
xev.xclient.data.l[0] = Event.xmotion.x_root;
|
||||
xev.xclient.data.l[1] = Event.xmotion.y_root;
|
||||
xev.xclient.data.l[2] = 8; // _NET_WM_MOVERESIZE_MOVE
|
||||
xev.xclient.data.l[3] = 1; // button 1
|
||||
xev.xclient.data.l[4] = 1; // source indication: normal
|
||||
|
||||
XSendEvent(x11->display, x11->rootwin, False,
|
||||
SubstructureRedirectMask | SubstructureNotifyMask,
|
||||
&xev);
|
||||
} else {
|
||||
vo_mouse_movement(vo, Event.xmotion.x, Event.xmotion.y);
|
||||
}
|
||||
break;
|
||||
case LeaveNotify:
|
||||
x11->win_drag_button1_down = false;
|
||||
mp_input_put_key(vo->input_ctx, MP_KEY_MOUSE_LEAVE);
|
||||
break;
|
||||
case ButtonPress:
|
||||
if (Event.xbutton.button == 1)
|
||||
x11->win_drag_button1_down = true;
|
||||
mp_input_put_key(vo->input_ctx,
|
||||
(MP_MOUSE_BTN0 + Event.xbutton.button - 1) |
|
||||
get_mods(Event.xbutton.state) | MP_KEY_STATE_DOWN);
|
||||
break;
|
||||
case ButtonRelease:
|
||||
if (Event.xbutton.button == 1)
|
||||
x11->win_drag_button1_down = false;
|
||||
mp_input_put_key(vo->input_ctx,
|
||||
(MP_MOUSE_BTN0 + Event.xbutton.button - 1) |
|
||||
get_mods(Event.xbutton.state) | MP_KEY_STATE_UP);
|
||||
|
|
|
@ -107,6 +107,9 @@ struct vo_x11_state {
|
|||
Atom dnd_requested_format;
|
||||
Window dnd_src_window;
|
||||
|
||||
/* dragging the window */
|
||||
bool win_drag_button1_down;
|
||||
|
||||
Atom XA_NET_SUPPORTED;
|
||||
Atom XA_NET_WM_STATE;
|
||||
Atom XA_NET_WM_STATE_FULLSCREEN;
|
||||
|
@ -117,6 +120,7 @@ struct vo_x11_state {
|
|||
Atom XA_NET_WM_NAME;
|
||||
Atom XA_NET_WM_ICON_NAME;
|
||||
Atom XA_NET_WM_ICON;
|
||||
Atom XA_NET_WM_MOVERESIZE;
|
||||
Atom XA_WIN_PROTOCOLS;
|
||||
Atom XA_WIN_LAYER;
|
||||
Atom XA_WIN_HINTS;
|
||||
|
|
Loading…
Reference in New Issue