1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-24 15:52:25 +00:00

w32_common: support minimized and maximized properties

Add support for setting window-minimized and window-maximized in
Windows. The minimized and maximized state can be set independently.
When the window is minimized, the value of window-maximized will
determine whether the window is restored to the maximized state or not.

Changing state is done with ShowWindow(), which has commands that change
the window state and activate it (eg. SW_RESTORE) and commands that
change the window state without activating it (eg. SW_SHOWNOACTIVATE.)
It would be nice if we could use commands that don't activate the
window, so scripts could change the window state in the backrgound
without bringing it to the foreground, but there are some problems with
that. There is no command to maximize a window without activating it, so
SW_MAXIMIZE is used instead.  Also, restoring a window from minimize
without activating it seems buggy. On my Windows 10 1909 PC, it always
moves the window to the back of the z-order. SW_RESTORE is used instead
of SW_SHOWNOACTIVATE because of this.

This also changes the way the window is initially shown. Previously, the
window was made visible as a consequence of the SWP_SHOWWINDOW flag in
the first call to SetWindowPos. In order to set the initial minimized or
maximized state of the window, the window is shown with the ShowWindow
function instead, where the ShowWindow command is determined by whether
the window should be initially maximized or minimized.

Even when showing the window normally, we should still call ShowWindow
with the SW_SHOW command instead of using SetWindowPos, since the first
call a process makes to ShowWindow(SW_SHOW) has special behaviour
where it uses the show command in the process' STARTUPINFO instead of
the command passed to the function, which should fix #5724.

Note: While changes to window-minimized while in fullscreen mode should
work as expected, changing window-maximized while in fullscreen does not
work and won't result in the window changing state, even after leaving
fullscreen. For this to work correctly, the fullscreen logic needs to be
changed to apply the new maximized state on leaving fullscreen.

Fixes: #5724
Fixes: #7351
This commit is contained in:
James Ross-Gowan 2019-12-28 02:12:44 +11:00 committed by Jan Ekström
parent 48880d827d
commit 80423e5b55

View File

@ -867,6 +867,57 @@ static bool update_fullscreen_state(struct vo_w32_state *w32)
return toggle_fs;
}
static void update_minimized_state(struct vo_w32_state *w32)
{
if (w32->parent)
return;
if (!!IsMinimized(w32->window) != w32->opts->window_minimized) {
if (w32->opts->window_minimized) {
ShowWindow(w32->window, SW_SHOWMINNOACTIVE);
} else {
ShowWindow(w32->window, SW_RESTORE);
}
}
}
static void update_maximized_state(struct vo_w32_state *w32)
{
if (w32->parent)
return;
// Don't change the maximized state in fullscreen for now. In future, this
// should be made to apply the maximized state on leaving fullscreen.
if (w32->current_fs)
return;
WINDOWPLACEMENT wp = { .length = sizeof wp };
GetWindowPlacement(w32->window, &wp);
if (wp.showCmd == SW_SHOWMINIMIZED) {
// When the window is minimized, setting this property just changes
// whether it will be maximized when it's restored
if (w32->opts->window_maximized) {
wp.flags |= WPF_RESTORETOMAXIMIZED;
} else {
wp.flags &= ~WPF_RESTORETOMAXIMIZED;
}
SetWindowPlacement(w32->window, &wp);
} else if ((wp.showCmd == SW_SHOWMAXIMIZED) != w32->opts->window_maximized) {
if (w32->opts->window_maximized) {
ShowWindow(w32->window, SW_SHOWMAXIMIZED);
} else {
ShowWindow(w32->window, SW_SHOWNOACTIVATE);
}
}
}
static bool is_visible(HWND window)
{
// Unlike IsWindowVisible, this doesn't check the window's parents
return GetWindowLongPtrW(window, GWL_STYLE) & WS_VISIBLE;
}
static void update_window_state(struct vo_w32_state *w32)
{
if (w32->parent)
@ -877,7 +928,19 @@ static void update_window_state(struct vo_w32_state *w32)
SetWindowPos(w32->window, w32->opts->ontop ? HWND_TOPMOST : HWND_NOTOPMOST,
wr.left, wr.top, rect_w(wr), rect_h(wr),
SWP_FRAMECHANGED | SWP_SHOWWINDOW);
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
// Show the window if it's not yet visible
if (!is_visible(w32->window)) {
if (w32->opts->window_minimized) {
ShowWindow(w32->window, SW_SHOWMINIMIZED);
update_maximized_state(w32); // Set the WPF_RESTORETOMAXIMIZED flag
} else if (w32->opts->window_maximized) {
ShowWindow(w32->window, SW_SHOWMAXIMIZED);
} else {
ShowWindow(w32->window, SW_SHOW);
}
}
// Notify the taskbar about the fullscreen state only after the window
// is visible, to make sure the taskbar item has already been created
@ -990,10 +1053,28 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
MP_VERBOSE(w32, "resize window: %d:%d\n", w, h);
}
// Window may have been minimized or restored
w32->opts->window_minimized = IsIconic(w32->window);
// Window may have been minimized, maximized or restored
if (is_visible(w32->window)) {
WINDOWPLACEMENT wp = { .length = sizeof wp };
GetWindowPlacement(w32->window, &wp);
bool is_minimized = wp.showCmd == SW_SHOWMINIMIZED;
if (w32->opts->window_minimized != is_minimized) {
w32->opts->window_minimized = is_minimized;
m_config_cache_write_opt(w32->opts_cache,
&w32->opts->window_minimized);
}
bool is_maximized = wp.showCmd == SW_SHOWMAXIMIZED ||
(wp.showCmd == SW_SHOWMINIMIZED &&
(wp.flags & WPF_RESTORETOMAXIMIZED));
if (w32->opts->window_maximized != is_maximized) {
w32->opts->window_maximized = is_maximized;
m_config_cache_write_opt(w32->opts_cache,
&w32->opts->window_maximized);
}
}
signal_events(w32, VO_EVENT_WIN_STATE);
update_display_info(w32);
@ -1584,6 +1665,10 @@ static int gui_thread_control(struct vo_w32_state *w32, int request, void *arg)
} else if (changed_option == &vo_opts->border) {
update_window_style(w32);
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);
}
}