diff options
Diffstat (limited to 'video/out/w32_common.c')
-rw-r--r-- | video/out/w32_common.c | 117 |
1 files changed, 97 insertions, 20 deletions
diff --git a/video/out/w32_common.c b/video/out/w32_common.c index 6d89355a70..dc796b0ccd 100644 --- a/video/out/w32_common.c +++ b/video/out/w32_common.c @@ -210,7 +210,7 @@ static inline int get_system_metrics(struct vo_w32_state *w32, int metric) static void adjust_window_rect(struct vo_w32_state *w32, HWND hwnd, RECT *rc) { - if (!w32->opts->border) + if (!w32->opts->border && !IsMaximized(w32->window)) return; if (w32->api.pAdjustWindowRectExForDpi) { @@ -244,7 +244,7 @@ static bool check_windows10_build(DWORD build) // Get adjusted title bar height, only relevant for --title-bar=no static int get_title_bar_height(struct vo_w32_state *w32) { - assert(!w32->opts->title_bar && w32->opts->border); + assert(w32->opts->border ? !w32->opts->title_bar : IsMaximized(w32->window)); UINT visible_border = 0; // Only available on Windows 11, check in case it's backported and breaks // WM_NCCALCSIZE exception for Windows 10. @@ -568,19 +568,29 @@ static void begin_dragging(struct vo_w32_state *w32) mp_input_put_key(w32->input_ctx, MP_INPUT_RELEASE_ALL); } -static bool handle_mouse_down(struct vo_w32_state *w32, int btn, int x, int y) +// If native touch is enabled and the mouse event is emulated, ignore it. +// See: <https://learn.microsoft.com/en-us/windows/win32/tablet/ +// system-events-and-mouse-messages#distinguishing-pen-input-from-mouse-and-touch> +static bool should_ignore_mouse_event(const struct vo_w32_state *w32) { + return w32->opts->native_touch && ((GetMessageExtraInfo() & 0xFFFFFF00) == 0xFF515700); +} + +static void handle_mouse_down(struct vo_w32_state *w32, int btn, int x, int y) +{ + if (should_ignore_mouse_event(w32)) + return; btn |= mod_state(w32); mp_input_put_key(w32->input_ctx, btn | MP_KEY_STATE_DOWN); SetCapture(w32->window); - return false; } static void handle_mouse_up(struct vo_w32_state *w32, int btn) { + if (should_ignore_mouse_event(w32)) + return; btn |= mod_state(w32); mp_input_put_key(w32->input_ctx, btn | MP_KEY_STATE_UP); - ReleaseCapture(); } @@ -757,8 +767,15 @@ static void update_playback_state(struct vo_w32_state *w32) return; } + ULONGLONG completed = pstate->position; + ULONGLONG total = UINT8_MAX; + if (!pstate->position) { + completed = 1; + total = MAXULONGLONG; + } + ITaskbarList3_SetProgressValue(w32->taskbar_list3, w32->window, - pstate->percent_pos, 100); + completed, total); ITaskbarList3_SetProgressState(w32->taskbar_list3, w32->window, pstate->paused ? TBPF_PAUSED : TBPF_NORMAL); @@ -947,7 +964,7 @@ static DWORD update_style(struct vo_w32_state *w32, DWORD style) if (w32->current_fs) { style |= FULLSCREEN; } else { - style |= w32->opts->border ? FRAME : NO_FRAME; + style |= (w32->opts->border || w32->opts->window_maximized) ? FRAME : NO_FRAME; if (!w32->opts->title_bar && is_high_contrast()) style &= ~WS_CAPTION; } @@ -1111,6 +1128,8 @@ static void update_maximized_state(struct vo_w32_state *w32, bool leaving_fullsc if (w32->parent) return; + update_window_style(w32); + // Apply the maximized state on leaving fullscreen. if (w32->current_fs && !leaving_fullscreen) return; @@ -1315,6 +1334,19 @@ static void update_cursor_passthrough(const struct vo_w32_state *w32) } } +static void update_native_touch(const struct vo_w32_state *w32) +{ + if (w32->parent) + return; + + if (w32->opts->native_touch) { + RegisterTouchWindow(w32->window, 0); + } else { + UnregisterTouchWindow(w32->window); + mp_input_put_key(w32->input_ctx, MP_TOUCH_RELEASE_ALL); + } +} + static void set_ime_conversion_mode(const struct vo_w32_state *w32, DWORD mode) { if (w32->parent) @@ -1444,6 +1476,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, (wp.flags & WPF_RESTORETOMAXIMIZED)); if (w32->opts->window_maximized != is_maximized) { w32->opts->window_maximized = is_maximized; + update_window_style(w32); m_config_cache_write_opt(w32->opts_cache, &w32->opts->window_maximized); } @@ -1509,7 +1542,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, } break; } - case WM_SYSCOMMAND: + case WM_SYSCOMMAND: { switch (wParam & 0xFFF0) { case SC_SCREENSAVE: case SC_MONITORPOWER: @@ -1527,7 +1560,18 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, } break; } + // All custom items must use ids of less than 0xF000. The context menu items are + // also larger than WM_USER, which excludes SCF_ISSECURE. + if (wParam > WM_USER && wParam < 0xF000) { + const char *cmd = mp_win32_menu_get_cmd(w32->menu_ctx, LOWORD(wParam)); + if (cmd) { + mp_cmd_t *cmdt = mp_input_parse_cmd(w32->input_ctx, bstr0(cmd), ""); + mp_input_queue_cmd(w32->input_ctx, cmdt); + return 0; + } + } break; + } case WM_NCACTIVATE: // Cosmetic to remove blinking window border when initializing window if (!w32->opts->border) @@ -1615,14 +1659,14 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, if (x != w32->mouse_x || y != w32->mouse_y) { w32->mouse_x = x; w32->mouse_y = y; - mp_input_set_mouse_pos(w32->input_ctx, x, y); + if (!should_ignore_mouse_event(w32)) + mp_input_set_mouse_pos(w32->input_ctx, x, y); } break; } case WM_LBUTTONDOWN: - if (handle_mouse_down(w32, MP_MBTN_LEFT, GET_X_LPARAM(lParam), - GET_Y_LPARAM(lParam))) - return 0; + handle_mouse_down(w32, MP_MBTN_LEFT, GET_X_LPARAM(lParam), + GET_Y_LPARAM(lParam)); break; case WM_LBUTTONUP: handle_mouse_up(w32, MP_MBTN_LEFT); @@ -1667,12 +1711,13 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, update_window_state(w32); break; case WM_NCCALCSIZE: - if (!w32->opts->border) + if (!w32->opts->border && !IsMaximized(w32->window)) return 0; + // Apparently removing WS_CAPTION disables some window animation, instead // just reduce non-client size to remove title bar. - if (wParam && lParam && w32->opts->border && !w32->opts->title_bar && - !w32->current_fs && !w32->parent && + if (wParam && lParam && !w32->current_fs && !w32->parent && + (w32->opts->border ? !w32->opts->title_bar : IsMaximized(w32->window)) && (GetWindowLongPtrW(w32->window, GWL_STYLE) & WS_CAPTION)) { // Remove all NC area on Windows 10 due to inability to control the @@ -1683,7 +1728,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, adjust_window_rect(w32, w32->window, &r); NCCALCSIZE_PARAMS *p = (LPNCCALCSIZE_PARAMS)lParam; p->rgrc[0].top += r.top + get_title_bar_height(w32); - } + } break; case WM_IME_STARTCOMPOSITION: { HIMC imc = ImmGetContext(w32->window); @@ -1707,12 +1752,33 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, if (wParam == WM_CREATE) { // Default to alphanumeric input when the IME is first initialized. set_ime_conversion_mode(w32, IME_CMODE_ALPHANUMERIC); + KillTimer(w32->window, (UINT_PTR)WM_CREATE); return 0; } break; case WM_SHOWMENU: mp_win32_menu_show(w32->menu_ctx, w32->window); break; + case WM_TOUCH: { + UINT count = LOWORD(wParam); + TOUCHINPUT *inputs = talloc_array_ptrtype(NULL, inputs, count); + if (GetTouchInputInfo((HTOUCHINPUT)lParam, count, inputs, sizeof(TOUCHINPUT))) { + for (UINT i = 0; i < count; i++) { + TOUCHINPUT *ti = &inputs[i]; + POINT pt = {TOUCH_COORD_TO_PIXEL(ti->x), TOUCH_COORD_TO_PIXEL(ti->y)}; + ScreenToClient(w32->window, &pt); + if (ti->dwFlags & TOUCHEVENTF_DOWN) + mp_input_add_touch_point(w32->input_ctx, ti->dwID, pt.x, pt.y); + if (ti->dwFlags & TOUCHEVENTF_MOVE) + mp_input_update_touch_point(w32->input_ctx, ti->dwID, pt.x, pt.y); + if (ti->dwFlags & TOUCHEVENTF_UP) + mp_input_remove_touch_point(w32->input_ctx, ti->dwID); + } + } + CloseTouchInputHandle((HTOUCHINPUT)lParam); + talloc_free(inputs); + return 0; + } } if (message == w32->tbtn_created_msg) { @@ -1988,6 +2054,7 @@ static MP_THREAD_VOID gui_thread(void *ptr) goto done; } + w32->menu_ctx = mp_win32_menu_init(w32->window); update_dark_mode(w32); update_corners_pref(w32); if (w32->opts->window_affinity) @@ -1996,6 +2063,8 @@ static MP_THREAD_VOID gui_thread(void *ptr) update_backdrop(w32); if (w32->opts->cursor_passthrough) update_cursor_passthrough(w32); + if (w32->opts->native_touch) + update_native_touch(w32); if (SUCCEEDED(OleInitialize(NULL))) { ole_ok = true; @@ -2061,6 +2130,8 @@ done: MP_VERBOSE(w32, "uninit\n"); remove_parent_hook(w32); + if (w32->menu_ctx) + mp_win32_menu_uninit(w32->menu_ctx); if (w32->window && !w32->destroyed) DestroyWindow(w32->window); if (w32->taskbar_list) @@ -2086,7 +2157,6 @@ bool vo_w32_init(struct vo *vo) .dispatch = mp_dispatch_create(w32), }; w32->opts = w32->opts_cache->opts; - w32->menu_ctx = mp_win32_menu_init(); vo->w32 = w32; if (mp_thread_create(&w32->thread, gui_thread, w32)) @@ -2182,17 +2252,25 @@ static int gui_thread_control(struct vo_w32_state *w32, int request, void *arg) } else if (changed_option == &vo_opts->cursor_passthrough) { update_cursor_passthrough(w32); } else if (changed_option == &vo_opts->border || - changed_option == &vo_opts->title_bar || - changed_option == &vo_opts->show_in_taskbar) + changed_option == &vo_opts->title_bar) { update_window_style(w32); update_window_state(w32); + } else if (changed_option == &vo_opts->show_in_taskbar) { + // This hide and show is apparently required according to the documentation: + // https://learn.microsoft.com/en-us/windows/win32/shell/taskbar#managing-taskbar-buttons + ShowWindow(w32->window, SW_HIDE); + update_window_style(w32); + ShowWindow(w32->window, SW_SHOW); + update_window_state(w32); } else if (changed_option == &vo_opts->window_minimized) { update_minimized_state(w32); } else if (changed_option == &vo_opts->window_maximized) { update_maximized_state(w32, false); } else if (changed_option == &vo_opts->window_corners) { update_corners_pref(w32); + } else if (changed_option == &vo_opts->native_touch) { + update_native_touch(w32); } else if (changed_option == &vo_opts->geometry || changed_option == &vo_opts->autofit || changed_option == &vo_opts->autofit_smaller || changed_option == &vo_opts->autofit_larger) { @@ -2369,7 +2447,6 @@ void vo_w32_uninit(struct vo *vo) AvRevertMmThreadCharacteristics(w32->avrt_handle); - mp_win32_menu_uninit(w32->menu_ctx); talloc_free(w32); vo->w32 = NULL; } |