diff --git a/core/input/input.cpp b/core/input/input.cpp index 4413c426cf0..b705968b87e 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -77,6 +77,10 @@ Input *Input::singleton = nullptr; void (*Input::set_mouse_mode_func)(Input::MouseMode) = nullptr; Input::MouseMode (*Input::get_mouse_mode_func)() = nullptr; +void (*Input::set_mouse_mode_override_func)(Input::MouseMode) = nullptr; +Input::MouseMode (*Input::get_mouse_mode_override_func)() = nullptr; +void (*Input::set_mouse_mode_override_enabled_func)(bool) = nullptr; +bool (*Input::is_mouse_mode_override_enabled_func)() = nullptr; void (*Input::warp_mouse_func)(const Vector2 &p_position) = nullptr; Input::CursorShape (*Input::get_current_cursor_shape_func)() = nullptr; void (*Input::set_custom_mouse_cursor_func)(const Ref &, Input::CursorShape, const Vector2 &) = nullptr; @@ -86,51 +90,29 @@ Input *Input::get_singleton() { } void Input::set_mouse_mode(MouseMode p_mode) { - ERR_FAIL_INDEX((int)p_mode, 5); - - if (p_mode == mouse_mode) { - return; - } - - // Allow to be set even if overridden, to see if the platform allows the mode. + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); set_mouse_mode_func(p_mode); - mouse_mode = get_mouse_mode_func(); - - if (mouse_mode_override_enabled) { - set_mouse_mode_func(mouse_mode_override); - } } Input::MouseMode Input::get_mouse_mode() const { - return mouse_mode; -} - -void Input::set_mouse_mode_override_enabled(bool p_enabled) { - if (p_enabled == mouse_mode_override_enabled) { - return; - } - - mouse_mode_override_enabled = p_enabled; - - if (p_enabled) { - set_mouse_mode_func(mouse_mode_override); - mouse_mode_override = get_mouse_mode_func(); - } else { - set_mouse_mode_func(mouse_mode); - } + return get_mouse_mode_func(); } void Input::set_mouse_mode_override(MouseMode p_mode) { - ERR_FAIL_INDEX((int)p_mode, 5); + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + set_mouse_mode_override_func(p_mode); +} - if (p_mode == mouse_mode_override) { - return; - } +Input::MouseMode Input::get_mouse_mode_override() const { + return get_mouse_mode_override_func(); +} - if (mouse_mode_override_enabled) { - set_mouse_mode_func(p_mode); - mouse_mode_override = get_mouse_mode_func(); - } +void Input::set_mouse_mode_override_enabled(bool p_override_enabled) { + set_mouse_mode_override_enabled_func(p_override_enabled); +} + +bool Input::is_mouse_mode_override_enabled() { + return is_mouse_mode_override_enabled_func(); } void Input::_bind_methods() { @@ -199,6 +181,7 @@ void Input::_bind_methods() { BIND_ENUM_CONSTANT(MOUSE_MODE_CAPTURED); BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED); BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED_HIDDEN); + BIND_ENUM_CONSTANT(MOUSE_MODE_MAX); BIND_ENUM_CONSTANT(CURSOR_ARROW); BIND_ENUM_CONSTANT(CURSOR_IBEAM); diff --git a/core/input/input.h b/core/input/input.h index 6893c4b997b..bbe185de3cb 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -47,12 +47,14 @@ class Input : public Object { static constexpr uint64_t MAX_EVENT = 32; public: + // Keep synced with "DisplayServer::MouseMode" enum. enum MouseMode { MOUSE_MODE_VISIBLE, MOUSE_MODE_HIDDEN, MOUSE_MODE_CAPTURED, MOUSE_MODE_CONFINED, MOUSE_MODE_CONFINED_HIDDEN, + MOUSE_MODE_MAX, }; #undef CursorShape @@ -105,10 +107,6 @@ private: bool legacy_just_pressed_behavior = false; bool disable_input = false; - MouseMode mouse_mode = MOUSE_MODE_VISIBLE; - bool mouse_mode_override_enabled = false; - MouseMode mouse_mode_override = MOUSE_MODE_VISIBLE; - struct ActionState { uint64_t pressed_physics_frame = UINT64_MAX; uint64_t pressed_process_frame = UINT64_MAX; @@ -268,6 +266,10 @@ private: static void (*set_mouse_mode_func)(MouseMode); static MouseMode (*get_mouse_mode_func)(); + static void (*set_mouse_mode_override_func)(MouseMode); + static MouseMode (*get_mouse_mode_override_func)(); + static void (*set_mouse_mode_override_enabled_func)(bool); + static bool (*is_mouse_mode_override_enabled_func)(); static void (*warp_mouse_func)(const Vector2 &p_position); static CursorShape (*get_current_cursor_shape_func)(); @@ -286,8 +288,10 @@ protected: public: void set_mouse_mode(MouseMode p_mode); MouseMode get_mouse_mode() const; - void set_mouse_mode_override_enabled(bool p_enabled); void set_mouse_mode_override(MouseMode p_mode); + MouseMode get_mouse_mode_override() const; + void set_mouse_mode_override_enabled(bool p_override_enabled); + bool is_mouse_mode_override_enabled(); #ifdef TOOLS_ENABLED void get_argument_options(const StringName &p_function, int p_idx, List *r_options) const override; diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index 8c9855fa918..6089f85bc77 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -1968,6 +1968,9 @@ Confines the mouse cursor to the game window, and make it hidden. + + Max value of the [enum MouseMode]. + Represents the screen containing the mouse pointer. [b]Note:[/b] On Linux (Wayland), this constant always represents the screen at index [code]0[/code]. diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index 2e12015e5f9..e0d8be91577 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -464,6 +464,9 @@ Confines the mouse cursor to the game window, and make it hidden. + + Max value of the [enum MouseMode]. + Arrow cursor. Standard, default pointing cursor. diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index 06973f289c5..f8d960f2b70 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -771,33 +771,68 @@ void DisplayServerAndroid::process_gyroscope(const Vector3 &p_gyroscope) { Input::get_singleton()->set_gyroscope(p_gyroscope); } -void DisplayServerAndroid::mouse_set_mode(MouseMode p_mode) { +void DisplayServerAndroid::_mouse_update_mode() { + MouseMode wanted_mouse_mode = mouse_mode_override_enabled + ? mouse_mode_override + : mouse_mode_base; + if (!OS_Android::get_singleton()->get_godot_java()->get_godot_view()->can_update_pointer_icon() || !OS_Android::get_singleton()->get_godot_java()->get_godot_view()->can_capture_pointer()) { return; } - if (mouse_mode == p_mode) { + if (mouse_mode == wanted_mouse_mode) { return; } - if (p_mode == MouseMode::MOUSE_MODE_HIDDEN) { + if (wanted_mouse_mode == MouseMode::MOUSE_MODE_HIDDEN) { OS_Android::get_singleton()->get_godot_java()->get_godot_view()->set_pointer_icon(CURSOR_TYPE_NULL); } else { cursor_set_shape(cursor_shape); } - if (p_mode == MouseMode::MOUSE_MODE_CAPTURED) { + if (wanted_mouse_mode == MouseMode::MOUSE_MODE_CAPTURED) { OS_Android::get_singleton()->get_godot_java()->get_godot_view()->request_pointer_capture(); } else { OS_Android::get_singleton()->get_godot_java()->get_godot_view()->release_pointer_capture(); } - mouse_mode = p_mode; + mouse_mode = wanted_mouse_mode; +} + +void DisplayServerAndroid::mouse_set_mode(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_base) { + return; + } + mouse_mode_base = p_mode; + _mouse_update_mode(); } DisplayServer::MouseMode DisplayServerAndroid::mouse_get_mode() const { return mouse_mode; } +void DisplayServerAndroid::mouse_set_mode_override(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_override) { + return; + } + mouse_mode_override = p_mode; + _mouse_update_mode(); +} + +DisplayServer::MouseMode DisplayServerAndroid::mouse_get_mode_override() const { + return mouse_mode_override; +} + +void DisplayServerAndroid::mouse_set_mode_override_enabled(bool p_override_enabled) { + mouse_mode_override_enabled = p_override_enabled; + _mouse_update_mode(); +} + +bool DisplayServerAndroid::mouse_is_mode_override_enabled() const { + return mouse_mode_override_enabled; +} + Point2i DisplayServerAndroid::mouse_get_position() const { return Input::get_singleton()->get_mouse_position(); } diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h index 0d2caa07b7c..587d8731a10 100644 --- a/platform/android/display_server_android.h +++ b/platform/android/display_server_android.h @@ -66,6 +66,10 @@ class DisplayServerAndroid : public DisplayServer { }; const int CURSOR_TYPE_NULL = 0; MouseMode mouse_mode = MouseMode::MOUSE_MODE_VISIBLE; + MouseMode mouse_mode_base = MouseMode::MOUSE_MODE_VISIBLE; + MouseMode mouse_mode_override = MouseMode::MOUSE_MODE_VISIBLE; + bool mouse_mode_override_enabled = false; + void _mouse_update_mode(); bool keep_screen_on; bool swap_buffers_flag; @@ -228,6 +232,10 @@ public: virtual void mouse_set_mode(MouseMode p_mode) override; virtual MouseMode mouse_get_mode() const override; + virtual void mouse_set_mode_override(MouseMode p_mode) override; + virtual MouseMode mouse_get_mode_override() const override; + virtual void mouse_set_mode_override_enabled(bool p_override_enabled) override; + virtual bool mouse_is_mode_override_enabled() const override; static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, Error &r_error); static Vector get_rendering_drivers_func(); diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp index 532eaa6bcf4..19123875b2c 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.cpp +++ b/platform/linuxbsd/wayland/display_server_wayland.cpp @@ -325,20 +325,24 @@ void DisplayServerWayland::beep() const { wayland_thread.beep(); } -void DisplayServerWayland::mouse_set_mode(MouseMode p_mode) { - if (p_mode == mouse_mode) { +void DisplayServerWayland::_mouse_update_mode() { + MouseMode wanted_mouse_mode = mouse_mode_override_enabled + ? mouse_mode_override + : mouse_mode_base; + + if (wanted_mouse_mode == mouse_mode) { return; } MutexLock mutex_lock(wayland_thread.mutex); - bool show_cursor = (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED); + bool show_cursor = (wanted_mouse_mode == MOUSE_MODE_VISIBLE || wanted_mouse_mode == MOUSE_MODE_CONFINED); wayland_thread.cursor_set_visible(show_cursor); WaylandThread::PointerConstraint constraint = WaylandThread::PointerConstraint::NONE; - switch (p_mode) { + switch (wanted_mouse_mode) { case DisplayServer::MOUSE_MODE_CAPTURED: { constraint = WaylandThread::PointerConstraint::LOCKED; } break; @@ -354,13 +358,47 @@ void DisplayServerWayland::mouse_set_mode(MouseMode p_mode) { wayland_thread.pointer_set_constraint(constraint); - mouse_mode = p_mode; + mouse_mode = wanted_mouse_mode; +} + +void DisplayServerWayland::mouse_set_mode(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_base) { + return; + } + mouse_mode_base = p_mode; + _mouse_update_mode(); } DisplayServerWayland::MouseMode DisplayServerWayland::mouse_get_mode() const { return mouse_mode; } +void DisplayServerWayland::mouse_set_mode_override(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_override) { + return; + } + mouse_mode_override = p_mode; + _mouse_update_mode(); +} + +DisplayServerWayland::MouseMode DisplayServerWayland::mouse_get_mode_override() const { + return mouse_mode_override; +} + +void DisplayServerWayland::mouse_set_mode_override_enabled(bool p_override_enabled) { + if (p_override_enabled == mouse_mode_override_enabled) { + return; + } + mouse_mode_override_enabled = p_override_enabled; + _mouse_update_mode(); +} + +bool DisplayServerWayland::mouse_is_mode_override_enabled() const { + return mouse_mode_override_enabled; +} + // NOTE: This is hacked together (and not guaranteed to work in the first place) // as for some reason the there's no proper way to ask the compositor to warp // the pointer, although, at the time of writing, there's a proposal for a diff --git a/platform/linuxbsd/wayland/display_server_wayland.h b/platform/linuxbsd/wayland/display_server_wayland.h index 8c3bac9c7e3..97a07194a6a 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.h +++ b/platform/linuxbsd/wayland/display_server_wayland.h @@ -113,6 +113,10 @@ class DisplayServerWayland : public DisplayServer { CursorShape cursor_shape = CURSOR_ARROW; DisplayServer::MouseMode mouse_mode = DisplayServer::MOUSE_MODE_VISIBLE; + DisplayServer::MouseMode mouse_mode_base = MOUSE_MODE_VISIBLE; + DisplayServer::MouseMode mouse_mode_override = MOUSE_MODE_VISIBLE; + bool mouse_mode_override_enabled = false; + void _mouse_update_mode(); HashMap custom_cursors; @@ -191,6 +195,10 @@ public: virtual void mouse_set_mode(MouseMode p_mode) override; virtual MouseMode mouse_get_mode() const override; + virtual void mouse_set_mode_override(MouseMode p_mode) override; + virtual MouseMode mouse_get_mode_override() const override; + virtual void mouse_set_mode_override_enabled(bool p_override_enabled) override; + virtual bool mouse_is_mode_override_enabled() const override; virtual void warp_mouse(const Point2i &p_to) override; virtual Point2i mouse_get_position() const override; diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index b1945eb47a2..9dbf4dda597 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -417,10 +417,14 @@ void DisplayServerX11::beep() const { XBell(x11_display, 0); } -void DisplayServerX11::mouse_set_mode(MouseMode p_mode) { +void DisplayServerX11::_mouse_update_mode() { _THREAD_SAFE_METHOD_ - if (p_mode == mouse_mode) { + MouseMode wanted_mouse_mode = mouse_mode_override_enabled + ? mouse_mode_override + : mouse_mode_base; + + if (wanted_mouse_mode == mouse_mode) { return; } @@ -429,7 +433,7 @@ void DisplayServerX11::mouse_set_mode(MouseMode p_mode) { } // The only modes that show a cursor are VISIBLE and CONFINED - bool show_cursor = (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED); + bool show_cursor = (wanted_mouse_mode == MOUSE_MODE_VISIBLE || wanted_mouse_mode == MOUSE_MODE_CONFINED); bool previously_shown = (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED); if (show_cursor && !previously_shown) { @@ -450,7 +454,7 @@ void DisplayServerX11::mouse_set_mode(MouseMode p_mode) { XDefineCursor(x11_display, E.value.x11_window, null_cursor); // hide cursor } } - mouse_mode = p_mode; + mouse_mode = wanted_mouse_mode; if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { //flush pending motion events @@ -484,10 +488,44 @@ void DisplayServerX11::mouse_set_mode(MouseMode p_mode) { XFlush(x11_display); } +void DisplayServerX11::mouse_set_mode(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_base) { + return; + } + mouse_mode_base = p_mode; + _mouse_update_mode(); +} + DisplayServerX11::MouseMode DisplayServerX11::mouse_get_mode() const { return mouse_mode; } +void DisplayServerX11::mouse_set_mode_override(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_override) { + return; + } + mouse_mode_override = p_mode; + _mouse_update_mode(); +} + +DisplayServerX11::MouseMode DisplayServerX11::mouse_get_mode_override() const { + return mouse_mode_override; +} + +void DisplayServerX11::mouse_set_mode_override_enabled(bool p_override_enabled) { + if (p_override_enabled == mouse_mode_override_enabled) { + return; + } + mouse_mode_override_enabled = p_override_enabled; + _mouse_update_mode(); +} + +bool DisplayServerX11::mouse_is_mode_override_enabled() const { + return mouse_mode_override_enabled; +} + void DisplayServerX11::warp_mouse(const Point2i &p_position) { _THREAD_SAFE_METHOD_ diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h index e0a84db4b62..166b2cb57b5 100644 --- a/platform/linuxbsd/x11/display_server_x11.h +++ b/platform/linuxbsd/x11/display_server_x11.h @@ -297,6 +297,11 @@ class DisplayServerX11 : public DisplayServer { void _flush_mouse_motion(); MouseMode mouse_mode = MOUSE_MODE_VISIBLE; + MouseMode mouse_mode_base = MOUSE_MODE_VISIBLE; + MouseMode mouse_mode_override = MOUSE_MODE_VISIBLE; + bool mouse_mode_override_enabled = false; + void _mouse_update_mode(); + Point2i center; void _handle_key_event(WindowID p_window, XKeyEvent *p_event, LocalVector &p_events, uint32_t &p_event_index, bool p_echo = false); @@ -424,6 +429,10 @@ public: virtual void mouse_set_mode(MouseMode p_mode) override; virtual MouseMode mouse_get_mode() const override; + virtual void mouse_set_mode_override(MouseMode p_mode) override; + virtual MouseMode mouse_get_mode_override() const override; + virtual void mouse_set_mode_override_enabled(bool p_override_enabled) override; + virtual bool mouse_is_mode_override_enabled() const override; virtual void warp_mouse(const Point2i &p_position) override; virtual Point2i mouse_get_position() const override; diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index 32ab1fc478d..eb536f9894c 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -169,6 +169,10 @@ private: CGEventSourceRef event_source; MouseMode mouse_mode = MOUSE_MODE_VISIBLE; + MouseMode mouse_mode_base = MOUSE_MODE_VISIBLE; + MouseMode mouse_mode_override = MOUSE_MODE_VISIBLE; + bool mouse_mode_override_enabled = false; + void _mouse_update_mode(); bool drop_events = false; bool in_dispatch_input_event = false; @@ -306,6 +310,10 @@ public: virtual void mouse_set_mode(MouseMode p_mode) override; virtual MouseMode mouse_get_mode() const override; + virtual void mouse_set_mode_override(MouseMode p_mode) override; + virtual MouseMode mouse_get_mode_override() const override; + virtual void mouse_set_mode_override_enabled(bool p_override_enabled) override; + virtual bool mouse_is_mode_override_enabled() const override; bool update_mouse_wrap(WindowData &p_wd, NSPoint &r_delta, NSPoint &r_mpos, NSTimeInterval p_timestamp); virtual void warp_mouse(const Point2i &p_position) override; diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index 174e28310ef..dd351bcad79 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -1264,10 +1264,14 @@ Error DisplayServerMacOS::dialog_input_text(String p_title, String p_description return OK; } -void DisplayServerMacOS::mouse_set_mode(MouseMode p_mode) { +void DisplayServerMacOS::_mouse_update_mode() { _THREAD_SAFE_METHOD_ - if (p_mode == mouse_mode) { + MouseMode wanted_mouse_mode = mouse_mode_override_enabled + ? mouse_mode_override + : mouse_mode_base; + + if (wanted_mouse_mode == mouse_mode) { return; } @@ -1277,7 +1281,7 @@ void DisplayServerMacOS::mouse_set_mode(MouseMode p_mode) { } WindowData &wd = windows[window_id]; - bool show_cursor = (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED); + bool show_cursor = (wanted_mouse_mode == MOUSE_MODE_VISIBLE || wanted_mouse_mode == MOUSE_MODE_CONFINED); bool previously_shown = (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED); if (show_cursor && !previously_shown) { @@ -1285,7 +1289,7 @@ void DisplayServerMacOS::mouse_set_mode(MouseMode p_mode) { mouse_enter_window(window_id); } - if (p_mode == MOUSE_MODE_CAPTURED) { + if (wanted_mouse_mode == MOUSE_MODE_CAPTURED) { // Apple Docs state that the display parameter is not used. // "This parameter is not used. By default, you may pass kCGDirectMainDisplay." // https://developer.apple.com/library/mac/documentation/graphicsimaging/reference/Quartz_Services_Ref/Reference/reference.html @@ -1299,17 +1303,17 @@ void DisplayServerMacOS::mouse_set_mode(MouseMode p_mode) { NSPoint pointOnScreen = [[wd.window_view window] convertRectToScreen:pointInWindowRect].origin; CGPoint lMouseWarpPos = { pointOnScreen.x, CGDisplayBounds(CGMainDisplayID()).size.height - pointOnScreen.y }; CGWarpMouseCursorPosition(lMouseWarpPos); - } else if (p_mode == MOUSE_MODE_HIDDEN) { + } else if (wanted_mouse_mode == MOUSE_MODE_HIDDEN) { if (previously_shown) { CGDisplayHideCursor(kCGDirectMainDisplay); } [wd.window_object setMovable:YES]; CGAssociateMouseAndMouseCursorPosition(true); - } else if (p_mode == MOUSE_MODE_CONFINED) { + } else if (wanted_mouse_mode == MOUSE_MODE_CONFINED) { CGDisplayShowCursor(kCGDirectMainDisplay); [wd.window_object setMovable:NO]; CGAssociateMouseAndMouseCursorPosition(false); - } else if (p_mode == MOUSE_MODE_CONFINED_HIDDEN) { + } else if (wanted_mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { if (previously_shown) { CGDisplayHideCursor(kCGDirectMainDisplay); } @@ -1324,17 +1328,51 @@ void DisplayServerMacOS::mouse_set_mode(MouseMode p_mode) { last_warp = [[NSProcessInfo processInfo] systemUptime]; ignore_warp = true; warp_events.clear(); - mouse_mode = p_mode; + mouse_mode = wanted_mouse_mode; if (show_cursor) { cursor_update_shape(); } } +void DisplayServerMacOS::mouse_set_mode(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_base) { + return; + } + mouse_mode_base = p_mode; + _mouse_update_mode(); +} + DisplayServer::MouseMode DisplayServerMacOS::mouse_get_mode() const { return mouse_mode; } +void DisplayServerMacOS::mouse_set_mode_override(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_override) { + return; + } + mouse_mode_override = p_mode; + _mouse_update_mode(); +} + +DisplayServer::MouseMode DisplayServerMacOS::mouse_get_mode_override() const { + return mouse_mode_override; +} + +void DisplayServerMacOS::mouse_set_mode_override_enabled(bool p_override_enabled) { + if (p_override_enabled == mouse_mode_override_enabled) { + return; + } + mouse_mode_override_enabled = p_override_enabled; + _mouse_update_mode(); +} + +bool DisplayServerMacOS::mouse_is_mode_override_enabled() const { + return mouse_mode_override_enabled; +} + bool DisplayServerMacOS::update_mouse_wrap(WindowData &p_wd, NSPoint &r_delta, NSPoint &r_mpos, NSTimeInterval p_timestamp) { _THREAD_SAFE_METHOD_ diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp index 8b4a733a088..89cc6339d28 100644 --- a/platform/web/display_server_web.cpp +++ b/platform/web/display_server_web.cpp @@ -550,26 +550,39 @@ void DisplayServerWeb::cursor_set_custom_image(const Ref &p_cursor, Cu } // Mouse mode -void DisplayServerWeb::mouse_set_mode(MouseMode p_mode) { - ERR_FAIL_COND_MSG(p_mode == MOUSE_MODE_CONFINED || p_mode == MOUSE_MODE_CONFINED_HIDDEN, "MOUSE_MODE_CONFINED is not supported for the Web platform."); - if (p_mode == mouse_get_mode()) { +void DisplayServerWeb::_mouse_update_mode() { + MouseMode wanted_mouse_mode = mouse_mode_override_enabled + ? mouse_mode_override + : mouse_mode_base; + + ERR_FAIL_COND_MSG(wanted_mouse_mode == MOUSE_MODE_CONFINED || wanted_mouse_mode == MOUSE_MODE_CONFINED_HIDDEN, "MOUSE_MODE_CONFINED is not supported for the Web platform."); + if (wanted_mouse_mode == mouse_get_mode()) { return; } - if (p_mode == MOUSE_MODE_VISIBLE) { + if (wanted_mouse_mode == MOUSE_MODE_VISIBLE) { godot_js_display_cursor_set_visible(1); godot_js_display_cursor_lock_set(0); - } else if (p_mode == MOUSE_MODE_HIDDEN) { + } else if (wanted_mouse_mode == MOUSE_MODE_HIDDEN) { godot_js_display_cursor_set_visible(0); godot_js_display_cursor_lock_set(0); - } else if (p_mode == MOUSE_MODE_CAPTURED) { + } else if (wanted_mouse_mode == MOUSE_MODE_CAPTURED) { godot_js_display_cursor_set_visible(1); godot_js_display_cursor_lock_set(1); } } +void DisplayServerWeb::mouse_set_mode(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_base) { + return; + } + mouse_mode_base = p_mode; + _mouse_update_mode(); +} + DisplayServer::MouseMode DisplayServerWeb::mouse_get_mode() const { if (godot_js_display_cursor_is_hidden()) { return MOUSE_MODE_HIDDEN; @@ -581,6 +594,31 @@ DisplayServer::MouseMode DisplayServerWeb::mouse_get_mode() const { return MOUSE_MODE_VISIBLE; } +void DisplayServerWeb::mouse_set_mode_override(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_override) { + return; + } + mouse_mode_override = p_mode; + _mouse_update_mode(); +} + +DisplayServer::MouseMode DisplayServerWeb::mouse_get_mode_override() const { + return mouse_mode_override; +} + +void DisplayServerWeb::mouse_set_mode_override_enabled(bool p_override_enabled) { + if (p_override_enabled == mouse_mode_override_enabled) { + return; + } + mouse_mode_override_enabled = p_override_enabled; + _mouse_update_mode(); +} + +bool DisplayServerWeb::mouse_is_mode_override_enabled() const { + return mouse_mode_override_enabled; +} + Point2i DisplayServerWeb::mouse_get_position() const { return Input::get_singleton()->get_mouse_position(); } diff --git a/platform/web/display_server_web.h b/platform/web/display_server_web.h index de0eb93238c..2d0d13c19a3 100644 --- a/platform/web/display_server_web.h +++ b/platform/web/display_server_web.h @@ -106,6 +106,11 @@ private: bool tts = false; NativeMenu *native_menu = nullptr; + MouseMode mouse_mode_base = MOUSE_MODE_VISIBLE; + MouseMode mouse_mode_override = MOUSE_MODE_VISIBLE; + bool mouse_mode_override_enabled = false; + void _mouse_update_mode(); + // utilities static void dom2godot_mod(Ref ev, int p_mod, Key p_keycode); static const char *godot2dom_cursor(DisplayServer::CursorShape p_shape); @@ -184,6 +189,11 @@ public: // mouse virtual void mouse_set_mode(MouseMode p_mode) override; virtual MouseMode mouse_get_mode() const override; + virtual void mouse_set_mode_override(MouseMode p_mode) override; + virtual MouseMode mouse_get_mode_override() const override; + virtual void mouse_set_mode_override_enabled(bool p_override_enabled) override; + virtual bool mouse_is_mode_override_enabled() const override; + virtual Point2i mouse_get_position() const override; // ime diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 1d3a6f0ca4f..ab91b2398d9 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -796,23 +796,61 @@ void DisplayServerWindows::beep() const { MessageBeep(MB_OK); } -void DisplayServerWindows::mouse_set_mode(MouseMode p_mode) { +void DisplayServerWindows::_mouse_update_mode() { _THREAD_SAFE_METHOD_ - if (mouse_mode == p_mode) { + MouseMode wanted_mouse_mode = mouse_mode_override_enabled + ? mouse_mode_override + : mouse_mode_base; + + if (mouse_mode == wanted_mouse_mode) { // Already in the same mode; do nothing. return; } - mouse_mode = p_mode; + mouse_mode = wanted_mouse_mode; - _set_mouse_mode_impl(p_mode); + _set_mouse_mode_impl(wanted_mouse_mode); +} + +void DisplayServerWindows::mouse_set_mode(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_base) { + return; + } + mouse_mode_base = p_mode; + _mouse_update_mode(); } DisplayServer::MouseMode DisplayServerWindows::mouse_get_mode() const { return mouse_mode; } +void DisplayServerWindows::mouse_set_mode_override(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_override) { + return; + } + mouse_mode_override = p_mode; + _mouse_update_mode(); +} + +DisplayServer::MouseMode DisplayServerWindows::mouse_get_mode_override() const { + return mouse_mode_override; +} + +void DisplayServerWindows::mouse_set_mode_override_enabled(bool p_override_enabled) { + if (p_override_enabled == mouse_mode_override_enabled) { + return; + } + mouse_mode_override_enabled = p_override_enabled; + _mouse_update_mode(); +} + +bool DisplayServerWindows::mouse_is_mode_override_enabled() const { + return mouse_mode_override_enabled; +} + void DisplayServerWindows::warp_mouse(const Point2i &p_position) { _THREAD_SAFE_METHOD_ diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index b85394366e8..71de7a73769 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -620,6 +620,10 @@ class DisplayServerWindows : public DisplayServer { void _get_window_style(bool p_main_window, bool p_initialized, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_minimized, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, bool p_embed_child, DWORD &r_style, DWORD &r_style_ex); MouseMode mouse_mode; + MouseMode mouse_mode_base = MOUSE_MODE_VISIBLE; + MouseMode mouse_mode_override = MOUSE_MODE_VISIBLE; + bool mouse_mode_override_enabled = false; + void _mouse_update_mode(); int restore_mouse_trails = 0; bool use_raw_input = false; @@ -715,6 +719,10 @@ public: virtual void mouse_set_mode(MouseMode p_mode) override; virtual MouseMode mouse_get_mode() const override; + virtual void mouse_set_mode_override(MouseMode p_mode) override; + virtual MouseMode mouse_get_mode_override() const override; + virtual void mouse_set_mode_override_enabled(bool p_override_enabled) override; + virtual bool mouse_is_mode_override_enabled() const override; virtual void warp_mouse(const Point2i &p_position) override; virtual Point2i mouse_get_position() const override; diff --git a/servers/display_server.cpp b/servers/display_server.cpp index dc3402bdf88..bf3d428420a 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -501,6 +501,22 @@ DisplayServer::MouseMode DisplayServer::mouse_get_mode() const { return MOUSE_MODE_VISIBLE; } +void DisplayServer::mouse_set_mode_override(MouseMode p_mode) { + WARN_PRINT("Mouse is not supported by this display server."); +} + +DisplayServer::MouseMode DisplayServer::mouse_get_mode_override() const { + return MOUSE_MODE_VISIBLE; +} + +void DisplayServer::mouse_set_mode_override_enabled(bool p_override_enabled) { + WARN_PRINT("Mouse is not supported by this display server."); +} + +bool DisplayServer::mouse_is_mode_override_enabled() const { + return false; +} + void DisplayServer::warp_mouse(const Point2i &p_position) { } @@ -1098,6 +1114,7 @@ void DisplayServer::_bind_methods() { BIND_ENUM_CONSTANT(MOUSE_MODE_CAPTURED); BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED); BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED_HIDDEN); + BIND_ENUM_CONSTANT(MOUSE_MODE_MAX); BIND_CONSTANT(SCREEN_WITH_MOUSE_FOCUS); BIND_CONSTANT(SCREEN_WITH_KEYBOARD_FOCUS); @@ -1266,6 +1283,22 @@ Input::MouseMode DisplayServer::_input_get_mouse_mode() { return Input::MouseMode(singleton->mouse_get_mode()); } +void DisplayServer::_input_set_mouse_mode_override(Input::MouseMode p_mode) { + singleton->mouse_set_mode_override(MouseMode(p_mode)); +} + +Input::MouseMode DisplayServer::_input_get_mouse_mode_override() { + return Input::MouseMode(singleton->mouse_get_mode_override()); +} + +void DisplayServer::_input_set_mouse_mode_override_enabled(bool p_enabled) { + singleton->mouse_set_mode_override_enabled(p_enabled); +} + +bool DisplayServer::_input_is_mouse_mode_override_enabled() { + return singleton->mouse_is_mode_override_enabled(); +} + void DisplayServer::_input_warp(const Vector2 &p_to_pos) { singleton->warp_mouse(p_to_pos); } @@ -1347,6 +1380,10 @@ DisplayServer::DisplayServer() { singleton = this; Input::set_mouse_mode_func = _input_set_mouse_mode; Input::get_mouse_mode_func = _input_get_mouse_mode; + Input::set_mouse_mode_override_func = _input_set_mouse_mode_override; + Input::get_mouse_mode_override_func = _input_get_mouse_mode_override; + Input::set_mouse_mode_override_enabled_func = _input_set_mouse_mode_override_enabled; + Input::is_mouse_mode_override_enabled_func = _input_is_mouse_mode_override_enabled; Input::warp_mouse_func = _input_warp; Input::get_current_cursor_shape_func = _input_get_current_cursor_shape; Input::set_custom_mouse_cursor_func = _input_set_custom_mouse_cursor_func; diff --git a/servers/display_server.h b/servers/display_server.h index 562c2bf5abe..30bb533a5d3 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -98,6 +98,10 @@ public: private: static void _input_set_mouse_mode(Input::MouseMode p_mode); static Input::MouseMode _input_get_mouse_mode(); + static void _input_set_mouse_mode_override(Input::MouseMode p_mode); + static Input::MouseMode _input_get_mouse_mode_override(); + static void _input_set_mouse_mode_override_enabled(bool p_enabled); + static bool _input_is_mouse_mode_override_enabled(); static void _input_warp(const Vector2 &p_to_pos); static Input::CursorShape _input_get_current_cursor_shape(); static void _input_set_custom_mouse_cursor_func(const Ref &, Input::CursorShape, const Vector2 &p_hotspot); @@ -275,15 +279,20 @@ public: static void set_early_window_clear_color_override(bool p_enabled, Color p_color = Color(0, 0, 0, 0)); enum MouseMode { - MOUSE_MODE_VISIBLE, - MOUSE_MODE_HIDDEN, - MOUSE_MODE_CAPTURED, - MOUSE_MODE_CONFINED, - MOUSE_MODE_CONFINED_HIDDEN, + MOUSE_MODE_VISIBLE = Input::MOUSE_MODE_VISIBLE, + MOUSE_MODE_HIDDEN = Input::MOUSE_MODE_HIDDEN, + MOUSE_MODE_CAPTURED = Input::MOUSE_MODE_CAPTURED, + MOUSE_MODE_CONFINED = Input::MOUSE_MODE_CONFINED, + MOUSE_MODE_CONFINED_HIDDEN = Input::MOUSE_MODE_CONFINED_HIDDEN, + MOUSE_MODE_MAX = Input::MOUSE_MODE_MAX, }; virtual void mouse_set_mode(MouseMode p_mode); virtual MouseMode mouse_get_mode() const; + virtual void mouse_set_mode_override(MouseMode p_mode); + virtual MouseMode mouse_get_mode_override() const; + virtual void mouse_set_mode_override_enabled(bool p_override_enabled); + virtual bool mouse_is_mode_override_enabled() const; virtual void warp_mouse(const Point2i &p_position); virtual Point2i mouse_get_position() const; diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h index 12c174ae2b0..7bd8cbf0752 100644 --- a/servers/display_server_headless.h +++ b/servers/display_server_headless.h @@ -170,6 +170,8 @@ public: void tts_stop() override {} void mouse_set_mode(MouseMode p_mode) override {} + void mouse_set_mode_override(MouseMode p_mode) override {} + void mouse_set_mode_override_enabled(bool p_override_enabled) override {} Point2i mouse_get_position() const override { return Point2i(); } void clipboard_set(const String &p_text) override {} void clipboard_set_primary(const String &p_text) override {}