mirror of https://github.com/mpv-player/mpv
w32_common: use the screen working area when resizing the window
This makes the default fit on screen, autofit and window-scale changing behavior to use the screen working area, instead of the whole screen area. As a result mpv window doesn't cover the taskbar now when opening videos with size larger than the screen size. The actual behavior now is the same as expected behavior for usecases 1-4 from #4363. This commit also removes the screenrc from w32 struct. The screen rect can now be retrieved via `get_screen_area` function, which was renamed from `update_screen_rect`. On a multi-monitor system, if the user moved the window between monitors, this function will return the current screen area under the window, and not the screen area from monitor specified by `--screen` option. The `--screen` option sets the initial monitor the mpv window is displayed on.
This commit is contained in:
parent
f1ba1ef77f
commit
edbe25f38a
|
@ -101,9 +101,7 @@ struct vo_w32_state {
|
|||
bool toggle_fs; // whether the current fullscreen state needs to be switched
|
||||
|
||||
RECT windowrc; // currently known window rect
|
||||
RECT screenrc; // current screen rect
|
||||
// last non-fullscreen rect, updated only on fullscreen or on initialization
|
||||
RECT prev_windowrc;
|
||||
RECT prev_windowrc; // last non-fullscreen window rect
|
||||
|
||||
// video size
|
||||
uint32_t o_dwidth;
|
||||
|
@ -606,6 +604,80 @@ static void update_playback_state(struct vo_w32_state *w32)
|
|||
TBPF_NORMAL);
|
||||
}
|
||||
|
||||
struct get_monitor_data {
|
||||
int i;
|
||||
int target;
|
||||
HMONITOR mon;
|
||||
};
|
||||
|
||||
static BOOL CALLBACK get_monitor_proc(HMONITOR mon, HDC dc, LPRECT r, LPARAM p)
|
||||
{
|
||||
struct get_monitor_data *data = (struct get_monitor_data*)p;
|
||||
|
||||
if (data->i == data->target) {
|
||||
data->mon = mon;
|
||||
return FALSE;
|
||||
}
|
||||
data->i++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static HMONITOR get_monitor(int id)
|
||||
{
|
||||
struct get_monitor_data data = { .target = id };
|
||||
EnumDisplayMonitors(NULL, NULL, get_monitor_proc, (LPARAM)&data);
|
||||
return data.mon;
|
||||
}
|
||||
|
||||
static HMONITOR get_default_monitor(struct vo_w32_state *w32)
|
||||
{
|
||||
const int id = w32->current_fs ? w32->opts->fsscreen_id :
|
||||
w32->opts->screen_id;
|
||||
|
||||
// Handle --fs-screen=<all|default> and --screen=default
|
||||
if (id < 0)
|
||||
return MonitorFromWindow(w32->window, MONITOR_DEFAULTTOPRIMARY);
|
||||
|
||||
HMONITOR mon = get_monitor(id);
|
||||
if (mon)
|
||||
return mon;
|
||||
MP_VERBOSE(w32, "Screen %d does not exist, falling back to primary\n", id);
|
||||
return MonitorFromPoint((POINT){0, 0}, MONITOR_DEFAULTTOPRIMARY);
|
||||
}
|
||||
|
||||
static MONITORINFO get_monitor_info(struct vo_w32_state *w32)
|
||||
{
|
||||
HMONITOR mon;
|
||||
if (IsWindowVisible(w32->window) && !w32->current_fs) {
|
||||
mon = MonitorFromWindow(w32->window, MONITOR_DEFAULTTOPRIMARY);
|
||||
} else {
|
||||
// The window is not visible during initialization, so get the
|
||||
// monitor by --screen or --fs-screen id, or fallback to primary.
|
||||
mon = get_default_monitor(w32);
|
||||
}
|
||||
MONITORINFO mi = { .cbSize = sizeof(mi) };
|
||||
GetMonitorInfoW(mon, &mi);
|
||||
return mi;
|
||||
}
|
||||
|
||||
static RECT get_screen_area(struct vo_w32_state *w32)
|
||||
{
|
||||
// Handle --fs-screen=all
|
||||
if (w32->current_fs && w32->opts->fsscreen_id == -2) {
|
||||
const int x = GetSystemMetrics(SM_XVIRTUALSCREEN);
|
||||
const int y = GetSystemMetrics(SM_YVIRTUALSCREEN);
|
||||
return (RECT) { x, y, x + GetSystemMetrics(SM_CXVIRTUALSCREEN),
|
||||
y + GetSystemMetrics(SM_CYVIRTUALSCREEN) };
|
||||
}
|
||||
return get_monitor_info(w32).rcMonitor;
|
||||
}
|
||||
|
||||
static RECT get_working_area(struct vo_w32_state *w32)
|
||||
{
|
||||
return w32->current_fs ? get_screen_area(w32) :
|
||||
get_monitor_info(w32).rcWork;
|
||||
}
|
||||
|
||||
static bool snap_to_screen_edges(struct vo_w32_state *w32, RECT *rc)
|
||||
{
|
||||
if (w32->parent || w32->current_fs || IsMaximized(w32->window))
|
||||
|
@ -633,11 +705,8 @@ static bool snap_to_screen_edges(struct vo_w32_state *w32, RECT *rc)
|
|||
if (rect_w(*rc) != rect_w(wr) || rect_h(*rc) != rect_h(wr))
|
||||
return false;
|
||||
|
||||
MONITORINFO mi = { .cbSize = sizeof(mi) };
|
||||
if (!GetMonitorInfoW(w32->monitor, &mi))
|
||||
return false;
|
||||
// Get the work area to let the window snap to taskbar
|
||||
wr = mi.rcWork;
|
||||
wr = get_working_area(w32);
|
||||
|
||||
// Check for invisible borders and adjust the work area size
|
||||
RECT frame = {0};
|
||||
|
@ -686,64 +755,6 @@ static bool snap_to_screen_edges(struct vo_w32_state *w32, RECT *rc)
|
|||
return true;
|
||||
}
|
||||
|
||||
struct get_monitor_data {
|
||||
int i;
|
||||
int target;
|
||||
HMONITOR mon;
|
||||
};
|
||||
|
||||
static BOOL CALLBACK get_monitor_proc(HMONITOR mon, HDC dc, LPRECT r, LPARAM p)
|
||||
{
|
||||
struct get_monitor_data *data = (struct get_monitor_data*)p;
|
||||
|
||||
if (data->i == data->target) {
|
||||
data->mon = mon;
|
||||
return FALSE;
|
||||
}
|
||||
data->i++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static HMONITOR get_monitor(int id)
|
||||
{
|
||||
struct get_monitor_data data = { .target = id };
|
||||
EnumDisplayMonitors(NULL, NULL, get_monitor_proc, (LPARAM)&data);
|
||||
return data.mon;
|
||||
}
|
||||
|
||||
static void update_screen_rect(struct vo_w32_state *w32)
|
||||
{
|
||||
struct mp_vo_opts *opts = w32->opts;
|
||||
int screen = w32->current_fs ? opts->fsscreen_id : opts->screen_id;
|
||||
|
||||
// Handle --fs-screen=all
|
||||
if (w32->current_fs && screen == -2) {
|
||||
const int x = GetSystemMetrics(SM_XVIRTUALSCREEN);
|
||||
const int y = GetSystemMetrics(SM_YVIRTUALSCREEN);
|
||||
SetRect(&w32->screenrc, x, y, x + GetSystemMetrics(SM_CXVIRTUALSCREEN),
|
||||
y + GetSystemMetrics(SM_CYVIRTUALSCREEN));
|
||||
return;
|
||||
}
|
||||
|
||||
// When not using --fs-screen=all, mpv belongs to a specific HMONITOR
|
||||
HMONITOR mon;
|
||||
if (screen == -1) {
|
||||
// Handle --fs-screen=current and --screen=default
|
||||
mon = MonitorFromWindow(w32->window, MONITOR_DEFAULTTOPRIMARY);
|
||||
} else {
|
||||
mon = get_monitor(screen);
|
||||
if (!mon) {
|
||||
MP_INFO(w32, "Screen %d does not exist, falling back to primary\n",
|
||||
screen);
|
||||
mon = MonitorFromPoint((POINT){0, 0}, MONITOR_DEFAULTTOPRIMARY);
|
||||
}
|
||||
}
|
||||
|
||||
MONITORINFO mi = { .cbSize = sizeof(mi) };
|
||||
GetMonitorInfoW(mon, &mi);
|
||||
w32->screenrc = mi.rcMonitor;
|
||||
}
|
||||
|
||||
static DWORD update_style(struct vo_w32_state *w32, DWORD style)
|
||||
{
|
||||
const DWORD NO_FRAME = WS_OVERLAPPED | WS_MINIMIZEBOX;
|
||||
|
@ -803,7 +814,7 @@ static void fit_window_on_screen(struct vo_w32_state *w32)
|
|||
if (w32->parent || w32->current_fs || IsMaximized(w32->window))
|
||||
return;
|
||||
|
||||
RECT screen = w32->screenrc;
|
||||
RECT screen = get_working_area(w32);
|
||||
if (w32->opts->border && w32->opts->fit_border)
|
||||
subtract_window_borders(w32->window, &screen);
|
||||
|
||||
|
@ -830,8 +841,6 @@ static bool update_fullscreen_state(struct vo_w32_state *w32)
|
|||
bool toggle_fs = w32->current_fs != new_fs;
|
||||
w32->current_fs = new_fs;
|
||||
|
||||
update_screen_rect(w32);
|
||||
|
||||
if (toggle_fs) {
|
||||
RECT rc;
|
||||
char msg[50];
|
||||
|
@ -849,7 +858,7 @@ static bool update_fullscreen_state(struct vo_w32_state *w32)
|
|||
}
|
||||
|
||||
if (w32->current_fs)
|
||||
w32->windowrc = w32->screenrc;
|
||||
w32->windowrc = get_screen_area(w32);
|
||||
|
||||
MP_VERBOSE(w32, "reset window bounds: %d:%d:%d:%d\n",
|
||||
(int)w32->windowrc.left, (int)w32->windowrc.top,
|
||||
|
@ -1285,9 +1294,10 @@ static void gui_thread_reconfig(void *ptr)
|
|||
struct vo_w32_state *w32 = ptr;
|
||||
struct vo *vo = w32->vo;
|
||||
|
||||
RECT r = get_working_area(w32);
|
||||
struct mp_rect screen = { r.left, r.top, r.right, r.bottom };
|
||||
struct vo_win_geometry geo;
|
||||
struct mp_rect screen = { w32->screenrc.left, w32->screenrc.top,
|
||||
w32->screenrc.right, w32->screenrc.bottom };
|
||||
|
||||
vo_calc_window_geometry(vo, &screen, &geo);
|
||||
vo_apply_window_geometry(vo, &geo);
|
||||
|
||||
|
@ -1311,7 +1321,6 @@ static void gui_thread_reconfig(void *ptr)
|
|||
|
||||
// The desired size always matches the window size in wid mode.
|
||||
if (!reset_size || w32->parent) {
|
||||
RECT r;
|
||||
GetClientRect(w32->window, &r);
|
||||
// Restore vo_dwidth and vo_dheight, which were reset in vo_config()
|
||||
vo->dwidth = r.right;
|
||||
|
@ -1441,8 +1450,6 @@ static void *gui_thread(void *ptr)
|
|||
w32->snapped = false;
|
||||
w32->snap_dx = w32->snap_dy = 0;
|
||||
|
||||
update_screen_rect(w32);
|
||||
|
||||
mp_dispatch_set_wakeup_fn(w32->dispatch, wakeup_gui_thread, w32);
|
||||
|
||||
res = 1;
|
||||
|
|
Loading…
Reference in New Issue