diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 295167eea2b0..05b7fa08cabc 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -3023,6 +3023,10 @@ void Node3DEditorViewport::_notification(int p_what) { update_preview_node = false; } break; + case NOTIFICATION_WM_WINDOW_FOCUS_OUT: { + set_freelook_active(false); + } break; + case NOTIFICATION_ENTER_TREE: { surface->connect(SceneStringName(draw), callable_mp(this, &Node3DEditorViewport::_draw)); surface->connect(SceneStringName(gui_input), callable_mp(this, &Node3DEditorViewport::_sinput)); diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index 767ea927c1b9..34b6d0219a5b 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -502,7 +502,34 @@ Point2i DisplayServerX11::mouse_get_position() const { } BitField DisplayServerX11::mouse_get_button_state() const { - return last_button_state; + int number_of_screens = XScreenCount(x11_display); + for (int i = 0; i < number_of_screens; i++) { + Window root, child; + int root_x, root_y, win_x, win_y; + unsigned int mask; + if (XQueryPointer(x11_display, XRootWindow(x11_display, i), &root, &child, &root_x, &root_y, &win_x, &win_y, &mask)) { + BitField last_button_state = 0; + + if (mask & Button1Mask) { + last_button_state.set_flag(MouseButtonMask::LEFT); + } + if (mask & Button2Mask) { + last_button_state.set_flag(MouseButtonMask::MIDDLE); + } + if (mask & Button3Mask) { + last_button_state.set_flag(MouseButtonMask::RIGHT); + } + if (mask & Button4Mask) { + last_button_state.set_flag(MouseButtonMask::MB_XBUTTON1); + } + if (mask & Button5Mask) { + last_button_state.set_flag(MouseButtonMask::MB_XBUTTON2); + } + + return last_button_state; + } + } + return 0; } void DisplayServerX11::clipboard_set(const String &p_text) { @@ -3351,18 +3378,6 @@ void DisplayServerX11::_get_key_modifier_state(unsigned int p_x11_state, Refset_meta_pressed((p_x11_state & Mod4Mask)); } -BitField DisplayServerX11::_get_mouse_button_state(MouseButton p_x11_button, int p_x11_type) { - MouseButtonMask mask = mouse_button_to_mask(p_x11_button); - - if (p_x11_type == ButtonPress) { - last_button_state.set_flag(mask); - } else { - last_button_state.clear_flag(mask); - } - - return last_button_state; -} - void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, LocalVector &p_events, uint32_t &p_event_index, bool p_echo) { WindowData &wd = windows[p_window]; // X11 functions don't know what const is @@ -4750,12 +4765,20 @@ void DisplayServerX11::process_events() { } else if (mb->get_button_index() == MouseButton::MIDDLE) { mb->set_button_index(MouseButton::RIGHT); } - mb->set_button_mask(_get_mouse_button_state(mb->get_button_index(), event.xbutton.type)); mb->set_position(Vector2(event.xbutton.x, event.xbutton.y)); mb->set_global_position(mb->get_position()); mb->set_pressed((event.type == ButtonPress)); + if (mb->is_pressed() && mb->get_button_index() >= MouseButton::WHEEL_UP && mb->get_button_index() <= MouseButton::WHEEL_RIGHT) { + MouseButtonMask mask = mouse_button_to_mask(mb->get_button_index()); + BitField scroll_mask = mouse_get_button_state(); + scroll_mask.set_flag(mask); + mb->set_button_mask(scroll_mask); + } else { + mb->set_button_mask(mouse_get_button_state()); + } + const WindowData &wd = windows[window_id]; if (event.type == ButtonPress) { diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h index 7c69df3df0d0..f0b181198696 100644 --- a/platform/linuxbsd/x11/display_server_x11.h +++ b/platform/linuxbsd/x11/display_server_x11.h @@ -263,7 +263,6 @@ class DisplayServerX11 : public DisplayServer { Point2i last_click_pos = Point2i(-100, -100); uint64_t last_click_ms = 0; MouseButton last_click_button_index = MouseButton::NONE; - BitField last_button_state; bool app_focused = false; uint64_t time_since_no_focus = 0; @@ -292,7 +291,6 @@ class DisplayServerX11 : public DisplayServer { Rect2i _screen_get_rect(int p_screen) const; - BitField _get_mouse_button_state(MouseButton p_x11_button, int p_x11_type); void _get_key_modifier_state(unsigned int p_x11_state, Ref state); void _flush_mouse_motion(); diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index 608c34edc6f3..b4741dc08f49 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -164,7 +164,6 @@ private: CGEventSourceRef event_source; MouseMode mouse_mode = MOUSE_MODE_VISIBLE; - BitField last_button_state; bool drop_events = false; bool in_dispatch_input_event = false; @@ -302,7 +301,6 @@ public: 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; virtual Point2i mouse_get_position() const override; - void mouse_set_button_state(BitField p_state); virtual BitField mouse_get_button_state() const override; virtual void clipboard_set(const String &p_text) override; diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index 0ccce1ad6a66..50313cfe67af 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -1421,11 +1421,25 @@ Point2i DisplayServerMacOS::mouse_get_position() const { return Vector2i(); } -void DisplayServerMacOS::mouse_set_button_state(BitField p_state) { - last_button_state = p_state; -} - BitField DisplayServerMacOS::mouse_get_button_state() const { + BitField last_button_state = 0; + + NSUInteger buttons = [NSEvent pressedMouseButtons]; + if (buttons & (1 << 0)) { + last_button_state.set_flag(MouseButtonMask::LEFT); + } + if (buttons & (1 << 1)) { + last_button_state.set_flag(MouseButtonMask::RIGHT); + } + if (buttons & (1 << 2)) { + last_button_state.set_flag(MouseButtonMask::MIDDLE); + } + if (buttons & (1 << 3)) { + last_button_state.set_flag(MouseButtonMask::MB_XBUTTON1); + } + if (buttons & (1 << 4)) { + last_button_state.set_flag(MouseButtonMask::MB_XBUTTON2); + } return last_button_state; } diff --git a/platform/macos/godot_content_view.mm b/platform/macos/godot_content_view.mm index 7dcb1ac9dbda..77f3a28ae70b 100644 --- a/platform/macos/godot_content_view.mm +++ b/platform/macos/godot_content_view.mm @@ -370,16 +370,6 @@ } DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); - BitField last_button_state = ds->mouse_get_button_state(); - - MouseButtonMask mask = mouse_button_to_mask(index); - - if (pressed) { - last_button_state.set_flag(mask); - } else { - last_button_state.clear_flag(mask); - } - ds->mouse_set_button_state(last_button_state); Ref mb; mb.instantiate(); @@ -394,7 +384,7 @@ mb->set_pressed(pressed); mb->set_position(wd.mouse_pos); mb->set_global_position(wd.mouse_pos); - mb->set_button_mask(last_button_state); + mb->set_button_mask(ds->mouse_get_button_state()); if (!outofstream && index == MouseButton::LEFT && pressed) { mb->set_double_click([event clickCount] == 2); } @@ -745,7 +735,6 @@ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); MouseButtonMask mask = mouse_button_to_mask(button); - BitField last_button_state = ds->mouse_get_button_state(); Ref sc; sc.instantiate(); @@ -757,9 +746,9 @@ sc->set_pressed(true); sc->set_position(wd.mouse_pos); sc->set_global_position(wd.mouse_pos); - last_button_state.set_flag(mask); - sc->set_button_mask(last_button_state); - ds->mouse_set_button_state(last_button_state); + BitField scroll_mask = ds->mouse_get_button_state(); + scroll_mask.set_flag(mask); + sc->set_button_mask(scroll_mask); Input::get_singleton()->parse_input_event(sc); @@ -770,9 +759,8 @@ sc->set_pressed(false); sc->set_position(wd.mouse_pos); sc->set_global_position(wd.mouse_pos); - last_button_state.clear_flag(mask); - sc->set_button_mask(last_button_state); - ds->mouse_set_button_state(last_button_state); + scroll_mask.clear_flag(mask); + sc->set_button_mask(scroll_mask); Input::get_singleton()->parse_input_event(sc); } diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 4c52d883775c..c114adff84f3 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -660,6 +660,24 @@ Point2i DisplayServerWindows::mouse_get_position() const { } BitField DisplayServerWindows::mouse_get_button_state() const { + BitField last_button_state = 0; + + if (GetAsyncKeyState(VK_LBUTTON) & (1 << 15)) { + last_button_state.set_flag(MouseButtonMask::LEFT); + } + if (GetAsyncKeyState(VK_RBUTTON) & (1 << 15)) { + last_button_state.set_flag(MouseButtonMask::RIGHT); + } + if (GetAsyncKeyState(VK_MBUTTON) & (1 << 15)) { + last_button_state.set_flag(MouseButtonMask::MIDDLE); + } + if (GetAsyncKeyState(VK_XBUTTON1) & (1 << 15)) { + last_button_state.set_flag(MouseButtonMask::MB_XBUTTON1); + } + if (GetAsyncKeyState(VK_XBUTTON2) & (1 << 15)) { + last_button_state.set_flag(MouseButtonMask::MB_XBUTTON2); + } + return last_button_state; } @@ -3999,7 +4017,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA mm->set_pressure((raw->data.mouse.ulButtons & RI_MOUSE_LEFT_BUTTON_DOWN) ? 1.0f : 0.0f); - mm->set_button_mask(last_button_state); + mm->set_button_mask(mouse_get_button_state()); Point2i c(windows[window_id].width / 2, windows[window_id].height / 2); @@ -4103,7 +4121,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA mm->set_tilt(windows[window_id].last_tilt); mm->set_pen_inverted(windows[window_id].last_pen_inverted); - mm->set_button_mask(last_button_state); + mm->set_button_mask(mouse_get_button_state()); mm->set_position(Vector2(coords.x, coords.y)); mm->set_global_position(Vector2(coords.x, coords.y)); @@ -4248,7 +4266,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA mm->set_alt_pressed(mods.has_flag(WinKeyModifierMask::ALT)); mm->set_meta_pressed(mods.has_flag(WinKeyModifierMask::META)); - mm->set_button_mask(last_button_state); + mm->set_button_mask(mouse_get_button_state()); POINT coords; // Client coords. coords.x = GET_X_LPARAM(lParam); @@ -4378,7 +4396,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA mm->set_tilt(windows[window_id].last_tilt); mm->set_pen_inverted(windows[window_id].last_pen_inverted); - mm->set_button_mask(last_button_state); + mm->set_button_mask(mouse_get_button_state()); mm->set_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); mm->set_global_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); @@ -4552,12 +4570,14 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA mb->set_alt_pressed(mods.has_flag(WinKeyModifierMask::ALT)); mb->set_meta_pressed(mods.has_flag(WinKeyModifierMask::META)); - if (mb->is_pressed()) { - last_button_state.set_flag(mouse_button_to_mask(mb->get_button_index())); + if (mb->is_pressed() && mb->get_button_index() >= MouseButton::WHEEL_UP && mb->get_button_index() <= MouseButton::WHEEL_RIGHT) { + MouseButtonMask mask = mouse_button_to_mask(mb->get_button_index()); + BitField scroll_mask = mouse_get_button_state(); + scroll_mask.set_flag(mask); + mb->set_button_mask(scroll_mask); } else { - last_button_state.clear_flag(mouse_button_to_mask(mb->get_button_index())); + mb->set_button_mask(mouse_get_button_state()); } - mb->set_button_mask(last_button_state); mb->set_position(Vector2(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); @@ -4571,7 +4591,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA SetCapture(hWnd); } } else { - if (--pressrc <= 0 || last_button_state.is_empty()) { + if (--pressrc <= 0 || mouse_get_button_state().is_empty()) { if (mouse_mode != MOUSE_MODE_CAPTURED) { ReleaseCapture(); } @@ -4596,8 +4616,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA // Send release for mouse wheel. Ref mbd = mb->duplicate(); mbd->set_window_id(window_id); - last_button_state.clear_flag(mouse_button_to_mask(mbd->get_button_index())); - mbd->set_button_mask(last_button_state); + mbd->set_button_mask(mouse_get_button_state()); mbd->set_pressed(false); Input::get_singleton()->parse_input_event(mbd); } diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 7ef64d2ce3b9..0f649b76d780 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -478,7 +478,7 @@ class DisplayServerWindows : public DisplayServer { MouseMode mouse_mode; int restore_mouse_trails = 0; - BitField last_button_state; + bool use_raw_input = false; bool drop_events = false; bool in_dispatch_input_event = false;