Added focus tracking in X11 and Windows classes, added new confined mouse mode (#7162)
This commit is contained in:
parent
4c28f35b2c
commit
1005a56e5a
@ -38,7 +38,7 @@ Input *Input::get_singleton() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Input::set_mouse_mode(MouseMode p_mode) {
|
void Input::set_mouse_mode(MouseMode p_mode) {
|
||||||
ERR_FAIL_INDEX(p_mode,3);
|
ERR_FAIL_INDEX(p_mode,4);
|
||||||
OS::get_singleton()->set_mouse_mode((OS::MouseMode)p_mode);
|
OS::get_singleton()->set_mouse_mode((OS::MouseMode)p_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,6 +87,7 @@ void Input::_bind_methods() {
|
|||||||
BIND_CONSTANT( MOUSE_MODE_VISIBLE );
|
BIND_CONSTANT( MOUSE_MODE_VISIBLE );
|
||||||
BIND_CONSTANT( MOUSE_MODE_HIDDEN );
|
BIND_CONSTANT( MOUSE_MODE_HIDDEN );
|
||||||
BIND_CONSTANT( MOUSE_MODE_CAPTURED );
|
BIND_CONSTANT( MOUSE_MODE_CAPTURED );
|
||||||
|
BIND_CONSTANT( MOUSE_MODE_CONFINED );
|
||||||
|
|
||||||
ADD_SIGNAL( MethodInfo("joy_connection_changed", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "connected")) );
|
ADD_SIGNAL( MethodInfo("joy_connection_changed", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "connected")) );
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,8 @@ public:
|
|||||||
enum MouseMode {
|
enum MouseMode {
|
||||||
MOUSE_MODE_VISIBLE,
|
MOUSE_MODE_VISIBLE,
|
||||||
MOUSE_MODE_HIDDEN,
|
MOUSE_MODE_HIDDEN,
|
||||||
MOUSE_MODE_CAPTURED
|
MOUSE_MODE_CAPTURED,
|
||||||
|
MOUSE_MODE_CONFINED
|
||||||
};
|
};
|
||||||
|
|
||||||
void set_mouse_mode(MouseMode p_mode);
|
void set_mouse_mode(MouseMode p_mode);
|
||||||
|
@ -131,7 +131,8 @@ public:
|
|||||||
enum MouseMode {
|
enum MouseMode {
|
||||||
MOUSE_MODE_VISIBLE,
|
MOUSE_MODE_VISIBLE,
|
||||||
MOUSE_MODE_HIDDEN,
|
MOUSE_MODE_HIDDEN,
|
||||||
MOUSE_MODE_CAPTURED
|
MOUSE_MODE_CAPTURED,
|
||||||
|
MOUSE_MODE_CONFINED
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void set_mouse_mode(MouseMode p_mode);
|
virtual void set_mouse_mode(MouseMode p_mode);
|
||||||
|
@ -254,6 +254,25 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
|||||||
|
|
||||||
switch (uMsg) // Check For Windows Messages
|
switch (uMsg) // Check For Windows Messages
|
||||||
{
|
{
|
||||||
|
case WM_SETFOCUS:
|
||||||
|
{
|
||||||
|
window_has_focus = true;
|
||||||
|
// Re-capture cursor if we're in one of the capture modes
|
||||||
|
if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED) {
|
||||||
|
SetCapture(hWnd);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_KILLFOCUS:
|
||||||
|
{
|
||||||
|
window_has_focus = false;
|
||||||
|
|
||||||
|
// Release capture if we're in one of the capture modes
|
||||||
|
if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED) {
|
||||||
|
ReleaseCapture();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case WM_ACTIVATE: // Watch For Window Activate Message
|
case WM_ACTIVATE: // Watch For Window Activate Message
|
||||||
{
|
{
|
||||||
minimized = HIWORD(wParam) != 0;
|
minimized = HIWORD(wParam) != 0;
|
||||||
@ -266,19 +285,17 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
|||||||
alt_mem=false;
|
alt_mem=false;
|
||||||
control_mem=false;
|
control_mem=false;
|
||||||
shift_mem=false;
|
shift_mem=false;
|
||||||
if (mouse_mode==MOUSE_MODE_CAPTURED) {
|
if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED) {
|
||||||
RECT clipRect;
|
RECT clipRect;
|
||||||
GetClientRect(hWnd, &clipRect);
|
GetClientRect(hWnd, &clipRect);
|
||||||
ClientToScreen(hWnd, (POINT*) &clipRect.left);
|
ClientToScreen(hWnd, (POINT*) &clipRect.left);
|
||||||
ClientToScreen(hWnd, (POINT*) &clipRect.right);
|
ClientToScreen(hWnd, (POINT*) &clipRect.right);
|
||||||
ClipCursor(&clipRect);
|
ClipCursor(&clipRect);
|
||||||
SetCapture(hWnd);
|
SetCapture(hWnd);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
|
main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
|
||||||
alt_mem=false;
|
alt_mem=false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return 0; // Return To The Message Loop
|
return 0; // Return To The Message Loop
|
||||||
@ -345,6 +362,9 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't calculate relative mouse movement if we don't have focus in CAPTURED mode.
|
||||||
|
if (!window_has_focus && mouse_mode==MOUSE_MODE_CAPTURED)
|
||||||
|
break;
|
||||||
/*
|
/*
|
||||||
LPARAM extra = GetMessageExtraInfo();
|
LPARAM extra = GetMessageExtraInfo();
|
||||||
if (IsPenEvent(extra)) {
|
if (IsPenEvent(extra)) {
|
||||||
@ -410,7 +430,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
|||||||
mm.relative_y=mm.y-old_y;
|
mm.relative_y=mm.y-old_y;
|
||||||
old_x=mm.x;
|
old_x=mm.x;
|
||||||
old_y=mm.y;
|
old_y=mm.y;
|
||||||
if (main_loop)
|
if (window_has_focus && main_loop)
|
||||||
input->parse_input_event(event);
|
input->parse_input_event(event);
|
||||||
|
|
||||||
|
|
||||||
@ -714,9 +734,8 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
|||||||
joypad->probe_joypads();
|
joypad->probe_joypads();
|
||||||
} break;
|
} break;
|
||||||
case WM_SETCURSOR: {
|
case WM_SETCURSOR: {
|
||||||
|
|
||||||
if(LOWORD(lParam) == HTCLIENT) {
|
if(LOWORD(lParam) == HTCLIENT) {
|
||||||
if(mouse_mode == MOUSE_MODE_HIDDEN || mouse_mode == MOUSE_MODE_CAPTURED) {
|
if(window_has_focus && (mouse_mode == MOUSE_MODE_HIDDEN || mouse_mode == MOUSE_MODE_CAPTURED)) {
|
||||||
//Hide the cursor
|
//Hide the cursor
|
||||||
if(hCursor == NULL)
|
if(hCursor == NULL)
|
||||||
hCursor = SetCursor(NULL);
|
hCursor = SetCursor(NULL);
|
||||||
@ -948,7 +967,7 @@ void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_
|
|||||||
|
|
||||||
main_loop=NULL;
|
main_loop=NULL;
|
||||||
outside=true;
|
outside=true;
|
||||||
|
window_has_focus=true;
|
||||||
WNDCLASSEXW wc;
|
WNDCLASSEXW wc;
|
||||||
|
|
||||||
video_mode=p_desired;
|
video_mode=p_desired;
|
||||||
@ -1326,16 +1345,16 @@ void OS_Windows::set_mouse_mode(MouseMode p_mode) {
|
|||||||
if (mouse_mode==p_mode)
|
if (mouse_mode==p_mode)
|
||||||
return;
|
return;
|
||||||
mouse_mode=p_mode;
|
mouse_mode=p_mode;
|
||||||
if (p_mode==MOUSE_MODE_CAPTURED) {
|
if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED) {
|
||||||
RECT clipRect;
|
RECT clipRect;
|
||||||
GetClientRect(hWnd, &clipRect);
|
GetClientRect(hWnd, &clipRect);
|
||||||
ClientToScreen(hWnd, (POINT*) &clipRect.left);
|
ClientToScreen(hWnd, (POINT*) &clipRect.left);
|
||||||
ClientToScreen(hWnd, (POINT*) &clipRect.right);
|
ClientToScreen(hWnd, (POINT*) &clipRect.right);
|
||||||
ClipCursor(&clipRect);
|
ClipCursor(&clipRect);
|
||||||
SetCapture(hWnd);
|
|
||||||
center=Point2i(video_mode.width/2,video_mode.height/2);
|
center=Point2i(video_mode.width/2,video_mode.height/2);
|
||||||
POINT pos = { (int) center.x, (int) center.y };
|
POINT pos = { (int) center.x, (int) center.y };
|
||||||
ClientToScreen(hWnd, &pos);
|
ClientToScreen(hWnd, &pos);
|
||||||
|
if (mouse_mode==MOUSE_MODE_CAPTURED)
|
||||||
SetCursorPos(pos.x, pos.y);
|
SetCursorPos(pos.x, pos.y);
|
||||||
} else {
|
} else {
|
||||||
ReleaseCapture();
|
ReleaseCapture();
|
||||||
|
@ -118,6 +118,7 @@ class OS_Windows : public OS {
|
|||||||
bool control_mem;
|
bool control_mem;
|
||||||
bool meta_mem;
|
bool meta_mem;
|
||||||
bool force_quit;
|
bool force_quit;
|
||||||
|
bool window_has_focus;
|
||||||
uint32_t last_button_state;
|
uint32_t last_button_state;
|
||||||
|
|
||||||
CursorShape cursor_shape;
|
CursorShape cursor_shape;
|
||||||
|
@ -450,6 +450,8 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
|
|||||||
physics_2d_server->init();
|
physics_2d_server->init();
|
||||||
|
|
||||||
input = memnew( InputDefault );
|
input = memnew( InputDefault );
|
||||||
|
|
||||||
|
window_has_focus = true; // Set focus to true at init
|
||||||
#ifdef JOYDEV_ENABLED
|
#ifdef JOYDEV_ENABLED
|
||||||
joypad = memnew( JoypadLinux(input));
|
joypad = memnew( JoypadLinux(input));
|
||||||
#endif
|
#endif
|
||||||
@ -518,17 +520,21 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) {
|
|||||||
if (p_mode==mouse_mode)
|
if (p_mode==mouse_mode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mouse_mode==MOUSE_MODE_CAPTURED)
|
if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode==MOUSE_MODE_CONFINED)
|
||||||
XUngrabPointer(x11_display, CurrentTime);
|
XUngrabPointer(x11_display, CurrentTime);
|
||||||
if (mouse_mode!=MOUSE_MODE_VISIBLE && p_mode==MOUSE_MODE_VISIBLE)
|
|
||||||
XUndefineCursor(x11_display,x11_window);
|
// The only modes that show a cursor are VISIBLE and CONFINED
|
||||||
if (p_mode!=MOUSE_MODE_VISIBLE && mouse_mode==MOUSE_MODE_VISIBLE) {
|
bool showCursor = (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED);
|
||||||
XDefineCursor(x11_display,x11_window,null_cursor);
|
|
||||||
|
if (showCursor) {
|
||||||
|
XUndefineCursor(x11_display,x11_window); // show cursor
|
||||||
|
} else {
|
||||||
|
XDefineCursor(x11_display,x11_window,null_cursor); // hide cursor
|
||||||
}
|
}
|
||||||
|
|
||||||
mouse_mode=p_mode;
|
mouse_mode=p_mode;
|
||||||
|
|
||||||
if (mouse_mode==MOUSE_MODE_CAPTURED) {
|
if (mouse_mode==MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED) {
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
//flush pending motion events
|
//flush pending motion events
|
||||||
@ -1254,6 +1260,10 @@ void OS_X11::process_xevents() {
|
|||||||
|
|
||||||
do_mouse_warp=false;
|
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) {
|
while (XPending(x11_display) > 0) {
|
||||||
XEvent event;
|
XEvent event;
|
||||||
XNextEvent(x11_display, &event);
|
XNextEvent(x11_display, &event);
|
||||||
@ -1272,24 +1282,29 @@ void OS_X11::process_xevents() {
|
|||||||
minimized = (visibility->state == VisibilityFullyObscured);
|
minimized = (visibility->state == VisibilityFullyObscured);
|
||||||
} break;
|
} break;
|
||||||
case LeaveNotify: {
|
case LeaveNotify: {
|
||||||
|
if (main_loop && !mouse_mode_grab)
|
||||||
if (main_loop && mouse_mode!=MOUSE_MODE_CAPTURED)
|
|
||||||
main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT);
|
main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT);
|
||||||
if (input)
|
if (input)
|
||||||
input->set_mouse_in_window(false);
|
input->set_mouse_in_window(false);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case EnterNotify: {
|
case EnterNotify: {
|
||||||
|
if (main_loop && !mouse_mode_grab)
|
||||||
if (main_loop && mouse_mode!=MOUSE_MODE_CAPTURED)
|
|
||||||
main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
|
main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
|
||||||
if (input)
|
if (input)
|
||||||
input->set_mouse_in_window(true);
|
input->set_mouse_in_window(true);
|
||||||
} break;
|
} break;
|
||||||
case FocusIn:
|
case FocusIn:
|
||||||
minimized = false;
|
minimized = false;
|
||||||
|
window_has_focus = true;
|
||||||
main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
|
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(
|
XGrabPointer(
|
||||||
x11_display, x11_window, True,
|
x11_display, x11_window, True,
|
||||||
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
|
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
|
||||||
@ -1298,9 +1313,14 @@ void OS_X11::process_xevents() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case FocusOut:
|
case FocusOut:
|
||||||
|
window_has_focus = false;
|
||||||
main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
|
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.
|
//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);
|
XUngrabPointer(x11_display, CurrentTime);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1343,7 +1363,6 @@ void OS_X11::process_xevents() {
|
|||||||
|
|
||||||
mouse_event.mouse_button.pressed=(event.type==ButtonPress);
|
mouse_event.mouse_button.pressed=(event.type==ButtonPress);
|
||||||
|
|
||||||
|
|
||||||
if (event.type==ButtonPress && event.xbutton.button==1) {
|
if (event.type==ButtonPress && event.xbutton.button==1) {
|
||||||
|
|
||||||
uint64_t diff = get_ticks_usec()/1000 - last_click_ms;
|
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
|
// PLEASE DO ME A FAVOR AND DIE DROWNED IN A FECAL
|
||||||
// MOUNTAIN BECAUSE THAT'S WHERE YOU BELONG.
|
// MOUNTAIN BECAUSE THAT'S WHERE YOU BELONG.
|
||||||
|
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
if (mouse_mode==MOUSE_MODE_CAPTURED && event.xmotion.x==current_videomode.width/2 && event.xmotion.y==current_videomode.height/2) {
|
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
|
//this is likely the warp event since it was warped here
|
||||||
@ -1419,7 +1437,7 @@ void OS_X11::process_xevents() {
|
|||||||
Point2i new_center = pos;
|
Point2i new_center = pos;
|
||||||
pos = last_mouse_pos + ( pos - center );
|
pos = last_mouse_pos + ( pos - center );
|
||||||
center=new_center;
|
center=new_center;
|
||||||
do_mouse_warp=true;
|
do_mouse_warp=window_has_focus; // warp the cursor if we're focused in
|
||||||
#else
|
#else
|
||||||
//Dear X11, thanks for making my life miserable
|
//Dear X11, thanks for making my life miserable
|
||||||
|
|
||||||
@ -1462,7 +1480,10 @@ void OS_X11::process_xevents() {
|
|||||||
last_mouse_pos=pos;
|
last_mouse_pos=pos;
|
||||||
|
|
||||||
// printf("rel: %d,%d\n", rel.x, rel.y );
|
// printf("rel: %d,%d\n", rel.x, rel.y );
|
||||||
|
// 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);
|
input->parse_input_event( motion_event);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
@ -134,7 +134,7 @@ class OS_X11 : public OS_Unix {
|
|||||||
|
|
||||||
bool force_quit;
|
bool force_quit;
|
||||||
bool minimized;
|
bool minimized;
|
||||||
|
bool window_has_focus;
|
||||||
bool do_mouse_warp;
|
bool do_mouse_warp;
|
||||||
|
|
||||||
const char *cursor_theme;
|
const char *cursor_theme;
|
||||||
|
Loading…
Reference in New Issue
Block a user