summaryrefslogtreecommitdiffstats
path: root/video/out/w32_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/w32_common.c')
-rw-r--r--video/out/w32_common.c117
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;
}