diff --git a/core/os/input.cpp b/core/os/input.cpp index ccc576f8797..4fdbd034b77 100644 --- a/core/os/input.cpp +++ b/core/os/input.cpp @@ -45,7 +45,7 @@ Input *Input::get_singleton() { } void Input::set_mouse_mode(MouseMode p_mode) { - ERR_FAIL_INDEX((int)p_mode, 4); + ERR_FAIL_INDEX((int)p_mode, 5); OS::get_singleton()->set_mouse_mode((OS::MouseMode)p_mode); } @@ -113,6 +113,7 @@ void Input::_bind_methods() { BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN); BIND_ENUM_CONSTANT(MOUSE_MODE_CAPTURED); BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED); + BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED_HIDDEN); BIND_ENUM_CONSTANT(CURSOR_ARROW); BIND_ENUM_CONSTANT(CURSOR_IBEAM); diff --git a/core/os/input.h b/core/os/input.h index e17fc1640df..1dfd52b9666 100644 --- a/core/os/input.h +++ b/core/os/input.h @@ -48,7 +48,8 @@ public: MOUSE_MODE_VISIBLE, MOUSE_MODE_HIDDEN, MOUSE_MODE_CAPTURED, - MOUSE_MODE_CONFINED + MOUSE_MODE_CONFINED, + MOUSE_MODE_CONFINED_HIDDEN, }; #undef CursorShape diff --git a/core/os/os.h b/core/os/os.h index 97e31cee741..a728e6b7e11 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -191,7 +191,8 @@ public: MOUSE_MODE_VISIBLE, MOUSE_MODE_HIDDEN, MOUSE_MODE_CAPTURED, - MOUSE_MODE_CONFINED + MOUSE_MODE_CONFINED, + MOUSE_MODE_CONFINED_HIDDEN, }; virtual void set_mouse_mode(MouseMode p_mode); diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index a4f2b688895..f30d9c1c633 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -426,7 +426,10 @@ [b]Note:[/b] If you want to process the mouse's movement in this mode, you need to use [member InputEventMouseMotion.relative]. - Makes the mouse cursor visible but confines it to the game window. + Confines the mouse cursor to the game window, and make it visible. + + + Confines the mouse cursor to the game window, and make it hidden. Arrow cursor. Standard, default pointing cursor. diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index fe2c66424f5..0728722de58 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -533,9 +533,10 @@ void OS_JavaScript::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_s } void OS_JavaScript::set_mouse_mode(OS::MouseMode p_mode) { - ERR_FAIL_COND_MSG(p_mode == MOUSE_MODE_CONFINED, "MOUSE_MODE_CONFINED is not supported for the HTML5 platform."); - if (p_mode == get_mouse_mode()) + ERR_FAIL_COND_MSG(p_mode == MOUSE_MODE_CONFINED || p_mode == MOUSE_MODE_CONFINED_HIDDEN, "MOUSE_MODE_CONFINED is not supported for the HTML5 platform."); + if (p_mode == get_mouse_mode()) { return; + } if (p_mode == MOUSE_MODE_VISIBLE) { godot_js_display_cursor_set_visible(1); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index cee62e062e4..e203a341a76 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -761,7 +761,7 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) { return; } - if (OS_OSX::singleton->mouse_mode == OS::MOUSE_MODE_CONFINED) { + if (OS_OSX::singleton->mouse_mode == OS::MOUSE_MODE_CONFINED || OS_OSX::singleton->mouse_mode == OS::MOUSE_MODE_CONFINED_HIDDEN) { // Discard late events if (([event timestamp]) < OS_OSX::singleton->last_warp) { return; @@ -2229,7 +2229,7 @@ void OS_OSX::warp_mouse_position(const Point2 &p_to) { CGEventSourceSetLocalEventsSuppressionInterval(lEventRef, 0.0); CGAssociateMouseAndMouseCursorPosition(false); CGWarpMouseCursorPosition(lMouseWarpPos); - if (mouse_mode != MOUSE_MODE_CONFINED) { + if (mouse_mode != MOUSE_MODE_CONFINED && mouse_mode != MOUSE_MODE_CONFINED_HIDDEN) { CGAssociateMouseAndMouseCursorPosition(true); } } @@ -3509,7 +3509,12 @@ void OS_OSX::set_mouse_mode(MouseMode p_mode) { } else if (p_mode == MOUSE_MODE_CONFINED) { CGDisplayShowCursor(kCGDirectMainDisplay); CGAssociateMouseAndMouseCursorPosition(false); - } else { + } else if (p_mode == MOUSE_MODE_CONFINED_HIDDEN) { + if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { + CGDisplayHideCursor(kCGDirectMainDisplay); + } + CGAssociateMouseAndMouseCursorPosition(false); + } else { // MOUSE_MODE_VISIBLE CGDisplayShowCursor(kCGDirectMainDisplay); CGAssociateMouseAndMouseCursorPosition(true); } diff --git a/platform/uwp/app.cpp b/platform/uwp/app.cpp index a00ef77eb21..7f93e9763d5 100644 --- a/platform/uwp/app.cpp +++ b/platform/uwp/app.cpp @@ -342,8 +342,9 @@ void App::OnPointerMoved(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Co os->input_event(screen_drag); } else { // In case the mouse grabbed, MouseMoved will handle this - if (os->get_mouse_mode() == OS::MouseMode::MOUSE_MODE_CAPTURED) + if (os->get_mouse_mode() == OS::MouseMode::MOUSE_MODE_CAPTURED) { return; + } Ref mouse_motion; mouse_motion.instance(); @@ -360,8 +361,9 @@ void App::OnPointerMoved(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Co void App::OnMouseMoved(MouseDevice ^ mouse_device, MouseEventArgs ^ args) { // In case the mouse isn't grabbed, PointerMoved will handle this - if (os->get_mouse_mode() != OS::MouseMode::MOUSE_MODE_CAPTURED) + if (os->get_mouse_mode() != OS::MouseMode::MOUSE_MODE_CAPTURED) { return; + } Windows::Foundation::Point pos; pos.X = last_mouse_pos.X + args->MouseDelta.X; diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 813c7c1ee23..a1a14c7f319 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -435,14 +435,12 @@ void OS_UWP::ManagedType::on_gyroscope_reading_changed(Gyrometer ^ sender, Gyrom void OS_UWP::set_mouse_mode(MouseMode p_mode) { if (p_mode == MouseMode::MOUSE_MODE_CAPTURED) { CoreWindow::GetForCurrentThread()->SetPointerCapture(); - } else { CoreWindow::GetForCurrentThread()->ReleasePointerCapture(); } - if (p_mode == MouseMode::MOUSE_MODE_CAPTURED || p_mode == MouseMode::MOUSE_MODE_HIDDEN) { + if (p_mode == MouseMode::MOUSE_MODE_HIDDEN || p_mode == MouseMode::MOUSE_MODE_CAPTURED || p_mode == MouseMode::MOUSE_MODE_CONFINED_HIDDEN) { CoreWindow::GetForCurrentThread()->PointerCursor = nullptr; - } else { CoreWindow::GetForCurrentThread()->PointerCursor = ref new CoreCursor(CoreCursorType::Arrow, 0); } diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 0002529f4ca..aac901c97ba 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -532,8 +532,9 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ScreenToClient(hWnd, &coords); // Don't calculate relative mouse movement if we don't have focus in CAPTURED mode. - if (!window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED) + if (!window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED) { break; + } Ref mm; mm.instance(); @@ -663,8 +664,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) + if (!window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED) { break; + } Ref mm; mm.instance(); @@ -765,8 +767,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) + if (!window_has_focus && mouse_mode == MOUSE_MODE_CAPTURED) { break; + } Ref mm; mm.instance(); @@ -1146,7 +1149,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } break; case WM_SETCURSOR: { if (LOWORD(lParam) == HTCLIENT) { - if (window_has_focus && (mouse_mode == MOUSE_MODE_HIDDEN || mouse_mode == MOUSE_MODE_CAPTURED)) { + if (window_has_focus && (mouse_mode == MOUSE_MODE_HIDDEN || mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN)) { //Hide the cursor if (hCursor == NULL) { hCursor = SetCursor(NULL); @@ -1853,7 +1856,8 @@ void OS_Windows::set_mouse_mode(MouseMode p_mode) { } void OS_Windows::_set_mouse_mode_impl(MouseMode p_mode) { - if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED) { + if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED || p_mode == MOUSE_MODE_CONFINED_HIDDEN) { + // Mouse is grabbed (captured or confined). RECT clipRect; GetClientRect(hWnd, &clipRect); ClientToScreen(hWnd, (POINT *)&clipRect.left); @@ -1867,11 +1871,12 @@ void OS_Windows::_set_mouse_mode_impl(MouseMode p_mode) { SetCapture(hWnd); } } else { + // Mouse is free to move around (not captured or confined). ReleaseCapture(); ClipCursor(NULL); } - if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_HIDDEN) { + if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_HIDDEN || p_mode == MOUSE_MODE_CONFINED_HIDDEN) { if (hCursor == NULL) { hCursor = SetCursor(NULL); } else { @@ -2101,7 +2106,7 @@ void OS_Windows::set_window_position(const Point2 &p_position) { MoveWindow(hWnd, p_position.x, p_position.y, r.right - r.left, r.bottom - r.top, TRUE); // Don't let the mouse leave the window when moved - if (mouse_mode == MOUSE_MODE_CONFINED) { + if (mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { RECT rect; GetClientRect(hWnd, &rect); ClientToScreen(hWnd, (POINT *)&rect.left); @@ -2182,7 +2187,7 @@ void OS_Windows::set_window_size(const Size2 p_size) { MoveWindow(hWnd, rect.left, rect.top, w, h, TRUE); // Don't let the mouse leave the window when resizing to a smaller resolution - if (mouse_mode == MOUSE_MODE_CONFINED) { + if (mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { RECT crect; GetClientRect(hWnd, &crect); ClientToScreen(hWnd, (POINT *)&crect.left); diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index f123ebcfe25..edf958de133 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -972,7 +972,7 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) { return; } - if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED) { + if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { XUngrabPointer(x11_display, CurrentTime); } @@ -987,7 +987,7 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) { mouse_mode = p_mode; - if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED) { + if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { //flush pending motion events flush_mouse_motion(); @@ -2573,7 +2573,7 @@ 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; + bool mouse_mode_grab = mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN; xi.pressure = 0; xi.tilt = Vector2(); @@ -2808,7 +2808,7 @@ void OS_X11::process_xevents() { // 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 + } else if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { // or re-hide it in captured mode XDefineCursor(x11_display, x11_window, null_cursor); }