Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Winink] Check pointer button states. #94063

Merged
merged 1 commit into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 124 additions & 1 deletion platform/windows/display_server_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4161,6 +4161,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
mm->set_relative_screen_position(mm->get_relative());
old_x = mm->get_position().x;
old_y = mm->get_position().y;

if (windows[window_id].window_focused || window_get_active_popup() == window_id) {
Input::get_singleton()->parse_input_event(mm);
}
Expand All @@ -4187,13 +4188,118 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
break;
}

pointer_button[GET_POINTERID_WPARAM(wParam)] = MouseButton::NONE;
windows[window_id].block_mm = true;
return 0;
} break;
case WM_POINTERLEAVE: {
pointer_button[GET_POINTERID_WPARAM(wParam)] = MouseButton::NONE;
windows[window_id].block_mm = false;
return 0;
} break;
case WM_POINTERDOWN:
case WM_POINTERUP: {
if (mouse_mode == MOUSE_MODE_CAPTURED && use_raw_input) {
break;
}

if ((tablet_get_current_driver() != "winink") || !winink_available) {
break;
}

Ref<InputEventMouseButton> mb;
mb.instantiate();
mb->set_window_id(window_id);

BitField<MouseButtonMask> last_button_state = 0;
if (IS_POINTER_FIRSTBUTTON_WPARAM(wParam)) {
last_button_state.set_flag(MouseButtonMask::LEFT);
mb->set_button_index(MouseButton::LEFT);
}
if (IS_POINTER_SECONDBUTTON_WPARAM(wParam)) {
last_button_state.set_flag(MouseButtonMask::RIGHT);
mb->set_button_index(MouseButton::RIGHT);
}
if (IS_POINTER_THIRDBUTTON_WPARAM(wParam)) {
last_button_state.set_flag(MouseButtonMask::MIDDLE);
mb->set_button_index(MouseButton::MIDDLE);
}
if (IS_POINTER_FOURTHBUTTON_WPARAM(wParam)) {
last_button_state.set_flag(MouseButtonMask::MB_XBUTTON1);
mb->set_button_index(MouseButton::MB_XBUTTON1);
}
if (IS_POINTER_FIFTHBUTTON_WPARAM(wParam)) {
last_button_state.set_flag(MouseButtonMask::MB_XBUTTON2);
mb->set_button_index(MouseButton::MB_XBUTTON2);
}
mb->set_button_mask(last_button_state);

const BitField<WinKeyModifierMask> &mods = _get_mods();
mb->set_ctrl_pressed(mods.has_flag(WinKeyModifierMask::CTRL));
mb->set_shift_pressed(mods.has_flag(WinKeyModifierMask::SHIFT));
mb->set_alt_pressed(mods.has_flag(WinKeyModifierMask::ALT));
mb->set_meta_pressed(mods.has_flag(WinKeyModifierMask::META));

POINT coords; // Client coords.
coords.x = GET_X_LPARAM(lParam);
coords.y = GET_Y_LPARAM(lParam);

// Note: Handle popup closing here, since mouse event is not emulated and hook will not be called.
uint64_t delta = OS::get_singleton()->get_ticks_msec() - time_since_popup;
if (delta > 250) {
Point2i pos = Point2i(coords.x, coords.y) - _get_screens_origin();
List<WindowID>::Element *C = nullptr;
List<WindowID>::Element *E = popup_list.back();
// Find top popup to close.
while (E) {
// Popup window area.
Rect2i win_rect = Rect2i(window_get_position_with_decorations(E->get()), window_get_size_with_decorations(E->get()));
// Area of the parent window, which responsible for opening sub-menu.
Rect2i safe_rect = window_get_popup_safe_rect(E->get());
if (win_rect.has_point(pos)) {
break;
} else if (safe_rect != Rect2i() && safe_rect.has_point(pos)) {
break;
} else {
C = E;
E = E->prev();
}
}
if (C) {
_send_window_event(windows[C->get()], DisplayServerWindows::WINDOW_EVENT_CLOSE_REQUEST);
}
}

int64_t pen_id = GET_POINTERID_WPARAM(wParam);
if (uMsg == WM_POINTERDOWN) {
mb->set_pressed(true);
if (pointer_down_time.has(pen_id) && (pointer_prev_button[pen_id] == mb->get_button_index()) && (ABS(coords.y - pointer_last_pos[pen_id].y) < GetSystemMetrics(SM_CYDOUBLECLK)) && GetMessageTime() - pointer_down_time[pen_id] < (LONG)GetDoubleClickTime()) {
mb->set_double_click(true);
pointer_down_time[pen_id] = 0;
} else {
pointer_down_time[pen_id] = GetMessageTime();
pointer_prev_button[pen_id] = mb->get_button_index();
pointer_last_pos[pen_id] = Vector2(coords.x, coords.y);
}
pointer_button[pen_id] = mb->get_button_index();
} else {
if (!pointer_button.has(pen_id)) {
return 0;
}
mb->set_pressed(false);
mb->set_button_index(pointer_button[pen_id]);
pointer_button[pen_id] = MouseButton::NONE;
}

ScreenToClient(windows[window_id].hWnd, &coords);

mb->set_position(Vector2(coords.x, coords.y));
mb->set_global_position(Vector2(coords.x, coords.y));

Input::get_singleton()->parse_input_event(mb);

return 0;
} break;
case WM_POINTERUPDATE: {
if (mouse_mode == MOUSE_MODE_CAPTURED && use_raw_input) {
break;
Expand Down Expand Up @@ -4271,7 +4377,23 @@ 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(mouse_get_button_state());
BitField<MouseButtonMask> last_button_state = 0;
if (IS_POINTER_FIRSTBUTTON_WPARAM(wParam)) {
last_button_state.set_flag(MouseButtonMask::LEFT);
}
if (IS_POINTER_SECONDBUTTON_WPARAM(wParam)) {
last_button_state.set_flag(MouseButtonMask::RIGHT);
}
if (IS_POINTER_THIRDBUTTON_WPARAM(wParam)) {
last_button_state.set_flag(MouseButtonMask::MIDDLE);
}
if (IS_POINTER_FOURTHBUTTON_WPARAM(wParam)) {
last_button_state.set_flag(MouseButtonMask::MB_XBUTTON1);
}
if (IS_POINTER_FIFTHBUTTON_WPARAM(wParam)) {
last_button_state.set_flag(MouseButtonMask::MB_XBUTTON2);
}
mm->set_button_mask(last_button_state);

POINT coords; // Client coords.
coords.x = GET_X_LPARAM(lParam);
Expand Down Expand Up @@ -4442,6 +4564,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
mm->set_position(mm->get_position() - window_get_position(receiving_window_id) + window_get_position(window_id));
mm->set_global_position(mm->get_position());
}

Input::get_singleton()->parse_input_event(mm);

} break;
Expand Down
57 changes: 57 additions & 0 deletions platform/windows/display_server_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,50 @@ typedef UINT32 PEN_MASK;
#define POINTER_MESSAGE_FLAG_FIRSTBUTTON 0x00000010
#endif

#ifndef POINTER_MESSAGE_FLAG_SECONDBUTTON
#define POINTER_MESSAGE_FLAG_SECONDBUTTON 0x00000020
#endif

#ifndef POINTER_MESSAGE_FLAG_THIRDBUTTON
#define POINTER_MESSAGE_FLAG_THIRDBUTTON 0x00000040
#endif

#ifndef POINTER_MESSAGE_FLAG_FOURTHBUTTON
#define POINTER_MESSAGE_FLAG_FOURTHBUTTON 0x00000080
#endif

#ifndef POINTER_MESSAGE_FLAG_FIFTHBUTTON
#define POINTER_MESSAGE_FLAG_FIFTHBUTTON 0x00000100
#endif

#ifndef IS_POINTER_FLAG_SET_WPARAM
#define IS_POINTER_FLAG_SET_WPARAM(wParam, flag) (((DWORD)HIWORD(wParam) & (flag)) == (flag))
#endif

#ifndef IS_POINTER_FIRSTBUTTON_WPARAM
#define IS_POINTER_FIRSTBUTTON_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_FIRSTBUTTON)
#endif

#ifndef IS_POINTER_SECONDBUTTON_WPARAM
#define IS_POINTER_SECONDBUTTON_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_SECONDBUTTON)
#endif

#ifndef IS_POINTER_THIRDBUTTON_WPARAM
#define IS_POINTER_THIRDBUTTON_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_THIRDBUTTON)
#endif

#ifndef IS_POINTER_FOURTHBUTTON_WPARAM
#define IS_POINTER_FOURTHBUTTON_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_FOURTHBUTTON)
#endif

#ifndef IS_POINTER_FIFTHBUTTON_WPARAM
#define IS_POINTER_FIFTHBUTTON_WPARAM(wParam) IS_POINTER_FLAG_SET_WPARAM(wParam, POINTER_MESSAGE_FLAG_FIFTHBUTTON)
#endif

#ifndef GET_POINTERID_WPARAM
#define GET_POINTERID_WPARAM(wParam) (LOWORD(wParam))
#endif

#if WINVER < 0x0602
enum tagPOINTER_INPUT_TYPE {
PT_POINTER = 0x00000001,
Expand Down Expand Up @@ -274,6 +318,14 @@ typedef struct tagPOINTER_PEN_INFO {
#define WM_POINTERLEAVE 0x024A
#endif

#ifndef WM_POINTERDOWN
#define WM_POINTERDOWN 0x0246
#endif

#ifndef WM_POINTERUP
#define WM_POINTERUP 0x0247
#endif

typedef BOOL(WINAPI *GetPointerTypePtr)(uint32_t p_id, POINTER_INPUT_TYPE *p_type);
typedef BOOL(WINAPI *GetPointerPenInfoPtr)(uint32_t p_id, POINTER_PEN_INFO *p_pen_info);
typedef BOOL(WINAPI *LogicalToPhysicalPointForPerMonitorDPIPtr)(HWND hwnd, LPPOINT lpPoint);
Expand Down Expand Up @@ -479,6 +531,11 @@ class DisplayServerWindows : public DisplayServer {
IndicatorID indicator_id_counter = 0;
HashMap<IndicatorID, IndicatorData> indicators;

HashMap<int64_t, MouseButton> pointer_prev_button;
HashMap<int64_t, MouseButton> pointer_button;
HashMap<int64_t, LONG> pointer_down_time;
HashMap<int64_t, Vector2> pointer_last_pos;

void _send_window_event(const WindowData &wd, WindowEvent p_event);
void _get_window_style(bool p_main_window, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, DWORD &r_style, DWORD &r_style_ex);

Expand Down
Loading