aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar pavelxdd <pavel.otchertsov@gmail.com>2017-12-22 19:19:28 +0300
committerGravatar Jan Ekström <jeebjp@gmail.com>2018-11-18 00:56:34 +0200
commitedbe25f38a2d5867dec066288cb61adf6191f327 (patch)
treebe873b69b8b9f4695f2986e6fe7cd630770b9723
parentf1ba1ef77f9536910caac8fff2c3793491d23459 (diff)
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.
-rw-r--r--video/out/w32_common.c155
1 files changed, 81 insertions, 74 deletions
diff --git a/video/out/w32_common.c b/video/out/w32_common.c
index de81b35dca..92b6650c09 100644
--- a/video/out/w32_common.c
+++ b/video/out/w32_common.c
@@ -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;