|
@@ -450,6 +450,8 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
|
|
|
physics_2d_server->init();
|
|
|
|
|
|
input = memnew( InputDefault );
|
|
|
+
|
|
|
+ window_has_focus = true; // Set focus to true at init
|
|
|
#ifdef JOYDEV_ENABLED
|
|
|
joypad = memnew( JoypadLinux(input));
|
|
|
#endif
|
|
@@ -518,17 +520,21 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) {
|
|
|
if (p_mode==mouse_mode)
|
|
|
return;
|
|
|
|
|
|
- if (mouse_mode==MOUSE_MODE_CAPTURED)
|
|
|
+ if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED)
|
|
|
XUngrabPointer(x11_display, CurrentTime);
|
|
|
- if (mouse_mode!=MOUSE_MODE_VISIBLE && p_mode==MOUSE_MODE_VISIBLE)
|
|
|
- XUndefineCursor(x11_display,x11_window);
|
|
|
- if (p_mode!=MOUSE_MODE_VISIBLE && mouse_mode==MOUSE_MODE_VISIBLE) {
|
|
|
- XDefineCursor(x11_display,x11_window,null_cursor);
|
|
|
+
|
|
|
+ // The only modes that show a cursor are VISIBLE and CONFINED
|
|
|
+ bool showCursor = (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED);
|
|
|
+
|
|
|
+ if (showCursor) {
|
|
|
+ XUndefineCursor(x11_display,x11_window); // show cursor
|
|
|
+ } else {
|
|
|
+ XDefineCursor(x11_display,x11_window,null_cursor); // hide cursor
|
|
|
}
|
|
|
|
|
|
mouse_mode=p_mode;
|
|
|
|
|
|
- if (mouse_mode==MOUSE_MODE_CAPTURED) {
|
|
|
+ if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED) {
|
|
|
|
|
|
while(true) {
|
|
|
//flush pending motion events
|
|
@@ -1254,6 +1260,10 @@ void OS_X11::process_xevents() {
|
|
|
|
|
|
do_mouse_warp=false;
|
|
|
|
|
|
+
|
|
|
+ // Is the current mouse mode one where it needs to be grabbed.
|
|
|
+ bool mouse_mode_grab = mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED;
|
|
|
+
|
|
|
while (XPending(x11_display) > 0) {
|
|
|
XEvent event;
|
|
|
XNextEvent(x11_display, &event);
|
|
@@ -1272,35 +1282,45 @@ void OS_X11::process_xevents() {
|
|
|
minimized = (visibility->state == VisibilityFullyObscured);
|
|
|
} break;
|
|
|
case LeaveNotify: {
|
|
|
-
|
|
|
- if (main_loop && mouse_mode!=MOUSE_MODE_CAPTURED)
|
|
|
+ if (main_loop && !mouse_mode_grab)
|
|
|
main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT);
|
|
|
if (input)
|
|
|
input->set_mouse_in_window(false);
|
|
|
|
|
|
} break;
|
|
|
case EnterNotify: {
|
|
|
-
|
|
|
- if (main_loop && mouse_mode!=MOUSE_MODE_CAPTURED)
|
|
|
+ if (main_loop && !mouse_mode_grab)
|
|
|
main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
|
|
|
if (input)
|
|
|
input->set_mouse_in_window(true);
|
|
|
} break;
|
|
|
case FocusIn:
|
|
|
minimized = false;
|
|
|
+ window_has_focus = true;
|
|
|
main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
|
|
|
- if (mouse_mode==MOUSE_MODE_CAPTURED) {
|
|
|
+ if (mouse_mode_grab) {
|
|
|
+ // Show and update the cursor if confined and the window regained focus.
|
|
|
+ if (mouse_mode==MOUSE_MODE_CONFINED)
|
|
|
+ XUndefineCursor(x11_display, x11_window);
|
|
|
+ else if (mouse_mode==MOUSE_MODE_CAPTURED) // or re-hide it in captured mode
|
|
|
+ XDefineCursor(x11_display, x11_window, null_cursor);
|
|
|
+
|
|
|
XGrabPointer(
|
|
|
- x11_display, x11_window, True,
|
|
|
+ x11_display, x11_window, True,
|
|
|
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
|
|
|
GrabModeAsync, GrabModeAsync, x11_window, None, CurrentTime);
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
case FocusOut:
|
|
|
+ window_has_focus = false;
|
|
|
main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
|
|
|
- if (mouse_mode==MOUSE_MODE_CAPTURED) {
|
|
|
+ if (mouse_mode_grab) {
|
|
|
//dear X11, I try, I really try, but you never work, you do whathever you want.
|
|
|
+ if (mouse_mode==MOUSE_MODE_CAPTURED) {
|
|
|
+ // Show the cursor if we're in captured mode so it doesn't look weird.
|
|
|
+ XUndefineCursor(x11_display, x11_window);
|
|
|
+ }
|
|
|
XUngrabPointer(x11_display, CurrentTime);
|
|
|
}
|
|
|
break;
|
|
@@ -1320,7 +1340,7 @@ void OS_X11::process_xevents() {
|
|
|
|
|
|
/* exit in case of a mouse button press */
|
|
|
last_timestamp=event.xbutton.time;
|
|
|
- if (mouse_mode==MOUSE_MODE_CAPTURED) {
|
|
|
+ if (mouse_mode == MOUSE_MODE_CAPTURED) {
|
|
|
event.xbutton.x=last_mouse_pos.x;
|
|
|
event.xbutton.y=last_mouse_pos.y;
|
|
|
}
|
|
@@ -1343,7 +1363,6 @@ void OS_X11::process_xevents() {
|
|
|
|
|
|
mouse_event.mouse_button.pressed=(event.type==ButtonPress);
|
|
|
|
|
|
-
|
|
|
if (event.type==ButtonPress && event.xbutton.button==1) {
|
|
|
|
|
|
uint64_t diff = get_ticks_usec()/1000 - last_click_ms;
|
|
@@ -1377,7 +1396,6 @@ void OS_X11::process_xevents() {
|
|
|
// PLEASE DO ME A FAVOR AND DIE DROWNED IN A FECAL
|
|
|
// MOUNTAIN BECAUSE THAT'S WHERE YOU BELONG.
|
|
|
|
|
|
-
|
|
|
while(true) {
|
|
|
if (mouse_mode==MOUSE_MODE_CAPTURED && event.xmotion.x==current_videomode.width/2 && event.xmotion.y==current_videomode.height/2) {
|
|
|
//this is likely the warp event since it was warped here
|
|
@@ -1419,7 +1437,7 @@ void OS_X11::process_xevents() {
|
|
|
Point2i new_center = pos;
|
|
|
pos = last_mouse_pos + ( pos - center );
|
|
|
center=new_center;
|
|
|
- do_mouse_warp=true;
|
|
|
+ do_mouse_warp=window_has_focus; // warp the cursor if we're focused in
|
|
|
#else
|
|
|
//Dear X11, thanks for making my life miserable
|
|
|
|
|
@@ -1462,8 +1480,11 @@ void OS_X11::process_xevents() {
|
|
|
last_mouse_pos=pos;
|
|
|
|
|
|
// printf("rel: %d,%d\n", rel.x, rel.y );
|
|
|
-
|
|
|
- input->parse_input_event( motion_event);
|
|
|
+ // Don't propagate the motion event unless we have focus
|
|
|
+ // this is so that the relative motion doesn't get messed up
|
|
|
+ // after we regain focus.
|
|
|
+ if (window_has_focus || !mouse_mode_grab)
|
|
|
+ input->parse_input_event( motion_event);
|
|
|
|
|
|
} break;
|
|
|
case KeyPress:
|