diff options
Diffstat (limited to 'video/out/w32_common.c')
-rw-r--r-- | video/out/w32_common.c | 451 |
1 files changed, 230 insertions, 221 deletions
diff --git a/video/out/w32_common.c b/video/out/w32_common.c index b93a4fd..feeae81 100644 --- a/video/out/w32_common.c +++ b/video/out/w32_common.c @@ -62,8 +62,12 @@ typedef enum MONITOR_DPI_TYPE { } MONITOR_DPI_TYPE; #endif +#define rect_w(r) ((r).right - (r).left) +#define rect_h(r) ((r).bottom - (r).top) + struct w32_api { HRESULT (WINAPI *pGetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); + BOOL (WINAPI *pImmDisableIME)(DWORD); }; struct vo_w32_state { @@ -84,15 +88,8 @@ struct vo_w32_state { HWINEVENTHOOK parent_evt_hook; HMONITOR monitor; // Handle of the current screen - struct mp_rect screenrc; // Size and virtual position of the current screen char *color_profile; // Path of the current screen's color profile - // last non-fullscreen extends (updated only on fullscreen or on initialization) - int prev_width; - int prev_height; - int prev_x; - int prev_y; - // Has the window seen a WM_DESTROY? If so, don't call DestroyWindow again. bool destroyed; @@ -102,11 +99,10 @@ struct vo_w32_state { bool current_fs; bool toggle_fs; // whether the current fullscreen state needs to be switched - // currently known window state - int window_x; - int window_y; - int dw; - int dh; + 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; // video size uint32_t o_dwidth; @@ -130,6 +126,9 @@ struct vo_w32_state { // UTF-16 decoding state for WM_CHAR and VK_PACKET int high_surrogate; + // Whether to fit the window on screen on next window state updating + bool fit_on_screen; + ITaskbarList2 *taskbar_list; ITaskbarList3 *taskbar_list3; UINT tbtnCreatedMsg; @@ -140,6 +139,7 @@ struct vo_w32_state { // updates on move/resize/displaychange double display_fps; + bool moving; bool snapped; int snap_dx; int snap_dy; @@ -182,16 +182,16 @@ static LRESULT borderless_nchittest(struct vo_w32_state *w32, int x, int y) if (mouse.y < frame_size) { if (mouse.x < diagonal_width) return HTTOPLEFT; - if (mouse.x >= w32->dw - diagonal_width) + if (mouse.x >= rect_w(w32->windowrc) - diagonal_width) return HTTOPRIGHT; return HTTOP; } // Hit-test bottom border - if (mouse.y >= w32->dh - frame_size) { + if (mouse.y >= rect_h(w32->windowrc) - frame_size) { if (mouse.x < diagonal_width) return HTBOTTOMLEFT; - if (mouse.x >= w32->dw - diagonal_width) + if (mouse.x >= rect_w(w32->windowrc) - diagonal_width) return HTBOTTOMRIGHT; return HTBOTTOM; } @@ -199,7 +199,7 @@ static LRESULT borderless_nchittest(struct vo_w32_state *w32, int x, int y) // Hit-test side borders if (mouse.x < frame_size) return HTLEFT; - if (mouse.x >= w32->dw - frame_size) + if (mouse.x >= rect_w(w32->windowrc) - frame_size) return HTRIGHT; return HTCLIENT; } @@ -607,6 +607,9 @@ static void update_playback_state(struct vo_w32_state *w32) static bool snap_to_screen_edges(struct vo_w32_state *w32, RECT *rc) { + if (w32->parent || w32->current_fs || IsMaximized(w32->window)) + return false; + if (!w32->opts->snap_window) { w32->snapped = false; return false; @@ -616,16 +619,24 @@ static bool snap_to_screen_edges(struct vo_w32_state *w32, RECT *rc) POINT cursor; if (!GetWindowRect(w32->window, &rect) || !GetCursorPos(&cursor)) return false; - // Check for aero snapping - if ((rc->right - rc->left != rect.right - rect.left) || - (rc->bottom - rc->top != rect.bottom - rect.top)) + // Check if window is going to be aero-snapped + if (rect_w(*rc) != rect_w(rect) || rect_h(*rc) != rect_h(rect)) + return false; + + // Check if window has already been aero-snapped + WINDOWPLACEMENT wp = {0}; + wp.length = sizeof(wp); + if (!GetWindowPlacement(w32->window, &wp)) + return false; + RECT wr = wp.rcNormalPosition; + 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 - RECT wr = mi.rcWork; + wr = mi.rcWork; // Check for invisible borders and adjust the work area size RECT frame = {0}; @@ -706,15 +717,10 @@ static void update_screen_rect(struct vo_w32_state *w32) // Handle --fs-screen=all if (w32->current_fs && screen == -2) { - struct mp_rect rc = { - GetSystemMetrics(SM_XVIRTUALSCREEN), - GetSystemMetrics(SM_YVIRTUALSCREEN), - GetSystemMetrics(SM_CXVIRTUALSCREEN), - GetSystemMetrics(SM_CYVIRTUALSCREEN), - }; - rc.x1 += rc.x0; - rc.y1 += rc.y0; - w32->screenrc = rc; + 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; } @@ -734,10 +740,7 @@ static void update_screen_rect(struct vo_w32_state *w32) MONITORINFO mi = { .cbSize = sizeof(mi) }; GetMonitorInfoW(mon, &mi); - w32->screenrc = (struct mp_rect){ - mi.rcMonitor.left, mi.rcMonitor.top, - mi.rcMonitor.right, mi.rcMonitor.bottom, - }; + w32->screenrc = mi.rcMonitor; } static DWORD update_style(struct vo_w32_state *w32, DWORD style) @@ -754,139 +757,148 @@ static DWORD update_style(struct vo_w32_state *w32, DWORD style) return style; } -// Update the window title, position, size, and border style. -static void reinit_window_state(struct vo_w32_state *w32) +static void update_window_style(struct vo_w32_state *w32) { - HWND layer = HWND_NOTOPMOST; - RECT r; - if (w32->parent) return; - bool new_fs = w32->toggle_fs ? !w32->current_fs : w32->opts->fullscreen; - bool toggle_fs = w32->current_fs != new_fs; - w32->current_fs = new_fs; - w32->toggle_fs = false; + // SetWindowLongPtr can trigger a WM_SIZE event, so window rect + // has to be saved now and restored after setting the new style. + const RECT wr = w32->windowrc; + const DWORD style = GetWindowLongPtrW(w32->window, GWL_STYLE); + SetWindowLongPtrW(w32->window, GWL_STYLE, update_style(w32, style)); + w32->windowrc = wr; +} - if (w32->taskbar_list) { - ITaskbarList2_MarkFullscreenWindow(w32->taskbar_list, - w32->window, w32->current_fs); +// Adjust rc size and position if its size is larger than rc2. +// returns true if the rectangle was modified. +static bool fit_rect(RECT *rc, RECT *rc2) +{ + // Calculate old size and maximum new size + int o_w = rect_w(*rc), o_h = rect_h(*rc); + int n_w = rect_w(*rc2), n_h = rect_h(*rc2); + if (o_w <= n_w && o_h <= n_h) + return false; + + // Apply letterboxing + const float o_asp = o_w / (float)MPMAX(o_h, 1); + const float n_asp = n_w / (float)MPMAX(n_h, 1); + if (o_asp > n_asp) { + n_h = n_w / o_asp; + } else { + n_w = n_h * o_asp; } - DWORD style = update_style(w32, GetWindowLongPtrW(w32->window, GWL_STYLE)); + // Calculate new position and save the rect + const int x = rc->left + o_w / 2 - n_w / 2; + const int y = rc->top + o_h / 2 - n_h / 2; + SetRect(rc, x, y, x + n_w, y + n_h); + return true; +} - if (w32->opts->ontop) - layer = HWND_TOPMOST; +// Adjust window size and position if its size is larger than the screen size. +static void fit_window_on_screen(struct vo_w32_state *w32) +{ + if (w32->parent || w32->current_fs || IsMaximized(w32->window)) + return; - // xxx not sure if this can trigger any unwanted messages (WM_MOVE/WM_SIZE) - update_screen_rect(w32); + RECT screen = w32->screenrc; + if (w32->opts->border && w32->opts->fit_border) + subtract_window_borders(w32->window, &screen); - int screen_w = w32->screenrc.x1 - w32->screenrc.x0; - int screen_h = w32->screenrc.y1 - w32->screenrc.y0; + if (fit_rect(&w32->windowrc, &screen)) { + MP_VERBOSE(w32, "adjusted window bounds: %d:%d:%d:%d\n", + (int)w32->windowrc.left, (int)w32->windowrc.top, + (int)rect_w(w32->windowrc), (int)rect_h(w32->windowrc)); + } +} - if (w32->current_fs) { - // Save window position and size when switching to fullscreen. - if (toggle_fs) { - w32->prev_width = w32->dw; - w32->prev_height = w32->dh; - w32->prev_x = w32->window_x; - w32->prev_y = w32->window_y; - MP_VERBOSE(w32, "save window bounds: %d:%d:%d:%d\n", - w32->prev_x, w32->prev_y, w32->prev_width, w32->prev_height); - } +// Calculate new fullscreen state and change window size and position. +// returns true if fullscreen state was changed. +static bool update_fullscreen_state(struct vo_w32_state *w32) +{ + if (w32->parent) + return false; - w32->window_x = w32->screenrc.x0; - w32->window_y = w32->screenrc.y0; - w32->dw = screen_w; - w32->dh = screen_h; - } else { - if (toggle_fs) { - // Restore window position and size when switching from fullscreen. - MP_VERBOSE(w32, "restore window bounds: %d:%d:%d:%d\n", - w32->prev_x, w32->prev_y, w32->prev_width, w32->prev_height); - w32->dw = w32->prev_width; - w32->dh = w32->prev_height; - w32->window_x = w32->prev_x; - w32->window_y = w32->prev_y; - } + bool new_fs = w32->opts->fullscreen; + if (w32->toggle_fs) { + new_fs = !w32->current_fs; + w32->toggle_fs = false; } - r.left = w32->window_x; - r.right = r.left + w32->dw; - r.top = w32->window_y; - r.bottom = r.top + w32->dh; - - SetWindowLongPtrW(w32->window, GWL_STYLE, style); - - RECT cr = r; - add_window_borders(w32->window, &r); - // Check on client area size instead of window size on --fit-border=no - long o_w; - long o_h; - if( w32->opts->fit_border ) { - o_w = r.right - r.left; - o_h = r.bottom - r.top; - } else { - o_w = cr.right - cr.left; - o_h = cr.bottom - cr.top; - } + bool toggle_fs = w32->current_fs != new_fs; + w32->current_fs = new_fs; - if ( !w32->current_fs && ( o_w > screen_w || o_h > screen_h ) ) - { - MP_VERBOSE(w32, "requested window size larger than the screen\n"); - // Use the aspect of the client area, not the full window size. - // Basically, try to compute the maximum window size. - long n_w; - long n_h; - if( w32->opts->fit_border ) { - n_w = screen_w - (r.right - cr.right) - (cr.left - r.left); - n_h = screen_h - (r.bottom - cr.bottom) - (cr.top - r.top); - } else { - n_w = screen_w; - n_h = screen_h; - } - // Letterbox - double asp = (cr.right - cr.left) / (double)(cr.bottom - cr.top); - double s_asp = n_w / (double)n_h; - if (asp > s_asp) { - n_h = n_w / asp; + update_screen_rect(w32); + + if (toggle_fs) { + RECT rc; + char msg[50]; + if (w32->current_fs) { + // Save window rect when switching to fullscreen. + rc = w32->prev_windowrc = w32->windowrc; + sprintf(msg, "save window bounds"); } else { - n_w = n_h * asp; + // Restore window rect when switching from fullscreen. + rc = w32->windowrc = w32->prev_windowrc; + sprintf(msg, "restore window bounds"); } - // Save new size - w32->dw = n_w; - w32->dh = n_h; - // Get old window center - long o_cx = r.left + (r.right - r.left) / 2; - long o_cy = r.top + (r.bottom - r.top) / 2; - // Add window borders to the new window size - r = (RECT){.right = n_w, .bottom = n_h}; - add_window_borders(w32->window, &r); - // Get top and left border size for client area position calculation - long b_top = -r.top; - long b_left = -r.left; - // Center the final window around the old window center - n_w = r.right - r.left; - n_h = r.bottom - r.top; - r.left = o_cx - n_w / 2; - r.top = o_cy - n_h / 2; - r.right = r.left + n_w; - r.bottom = r.top + n_h; - // Save new client area position - w32->window_x = r.left + b_left; - w32->window_y = r.top + b_top; + MP_VERBOSE(w32, "%s: %d:%d:%d:%d\n", msg, + (int)rc.left, (int)rc.top, (int)rect_w(rc), (int)rect_h(rc)); } + if (w32->current_fs) + w32->windowrc = w32->screenrc; + MP_VERBOSE(w32, "reset window bounds: %d:%d:%d:%d\n", - (int) r.left, (int) r.top, (int)(r.right - r.left), - (int)(r.bottom - r.top)); + (int)w32->windowrc.left, (int)w32->windowrc.top, + (int)rect_w(w32->windowrc), (int)rect_h(w32->windowrc)); + return toggle_fs; +} + +static void update_window_state(struct vo_w32_state *w32) +{ + if (w32->parent) + return; + + RECT wr = w32->windowrc; + add_window_borders(w32->window, &wr); - SetWindowPos(w32->window, layer, r.left, r.top, r.right - r.left, - r.bottom - r.top, SWP_FRAMECHANGED | SWP_SHOWWINDOW); + SetWindowPos(w32->window, w32->opts->ontop ? HWND_TOPMOST : HWND_NOTOPMOST, + wr.left, wr.top, rect_w(wr), rect_h(wr), + SWP_FRAMECHANGED | SWP_SHOWWINDOW); + + // Notify the taskbar about the fullscreen state only after the window + // is visible, to make sure the taskbar item has already been created + if (w32->taskbar_list) { + ITaskbarList2_MarkFullscreenWindow(w32->taskbar_list, + w32->window, w32->current_fs); + } signal_events(w32, VO_EVENT_RESIZE); } +static void reinit_window_state(struct vo_w32_state *w32) +{ + if (w32->parent) + return; + + // The order matters: fs state should be updated prior to changing styles + bool toggle_fs = update_fullscreen_state(w32); + update_window_style(w32); + + // Assume that the window has already been fit on screen before switching fs + if (!toggle_fs || w32->fit_on_screen) { + fit_window_on_screen(w32); + // The fullscreen state might still be active, so set the flag + // to fit on screen next time the window leaves the fullscreen. + w32->fit_on_screen = w32->current_fs; + } + + // Show and activate the window after all window state parameters were set + update_window_state(w32); +} + static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { @@ -917,25 +929,26 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, signal_events(w32, VO_EVENT_EXPOSE); break; case WM_MOVE: { - POINT p = {0}; - ClientToScreen(w32->window, &p); - w32->window_x = p.x; - w32->window_y = p.y; + const int x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam); + OffsetRect(&w32->windowrc, x - w32->windowrc.left, + y - w32->windowrc.top); // Window may intersect with new monitors (see VOCTRL_GET_DISPLAY_NAMES) signal_events(w32, VO_EVENT_WIN_STATE); update_display_info(w32); // if we moved between monitors - MP_DBG(w32, "move window: %d:%d\n", w32->window_x, w32->window_y); + MP_DBG(w32, "move window: %d:%d\n", x, y); break; } case WM_MOVING: { + w32->moving = true; RECT *rc = (RECT*)lParam; if (snap_to_screen_edges(w32, rc)) return TRUE; break; } case WM_ENTERSIZEMOVE: + w32->moving = true; if (w32->snapped) { // Save the cursor offset from the window borders, // so the player window can be unsnapped later @@ -947,13 +960,19 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, } } break; + case WM_EXITSIZEMOVE: + w32->moving = false; + break; case WM_SIZE: { - RECT r; - if (GetClientRect(w32->window, &r) && r.right > 0 && r.bottom > 0) { - w32->dw = r.right; - w32->dh = r.bottom; + if (w32->moving) + w32->snapped = false; + + const int w = LOWORD(lParam), h = HIWORD(lParam); + if (w > 0 && h > 0) { + w32->windowrc.right = w32->windowrc.left + w; + w32->windowrc.bottom = w32->windowrc.top + h; signal_events(w32, VO_EVENT_RESIZE); - MP_VERBOSE(w32, "resize window: %d:%d\n", w32->dw, w32->dh); + MP_VERBOSE(w32, "resize window: %d:%d\n", w, h); } // Window may have been minimized or restored @@ -971,7 +990,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, // (subtracting the window borders) RECT r = *rc; subtract_window_borders(w32->window, &r); - int c_w = r.right - r.left, c_h = r.bottom - r.top; + int c_w = rect_w(r), c_h = rect_h(r); float aspect = w32->o_dwidth / (float) MPMAX(w32->o_dheight, 1); int d_w = c_h * aspect - c_w; int d_h = c_w / aspect - c_h; @@ -988,8 +1007,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, update_display_info(w32); break; case WM_CLOSE: - // Don't actually allow it to destroy the window, or whatever else it - // is that will make us lose WM_USER wakeups. + // Don't destroy the window yet to not lose wakeup events. mp_input_put_key(w32->input_ctx, MP_KEY_CLOSE_WIN); return 0; case WM_NCDESTROY: // Sometimes only WM_NCDESTROY is received in --wid mode @@ -1260,56 +1278,51 @@ static void run_message_loop(struct vo_w32_state *w32) static void gui_thread_reconfig(void *ptr) { struct vo_w32_state *w32 = ptr; - struct vo *vo = w32->vo; struct vo_win_geometry geo; - vo_calc_window_geometry(vo, &w32->screenrc, &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); - bool reset_size = w32->o_dwidth != vo->dwidth || w32->o_dheight != vo->dheight; - bool pos_init = false; + bool reset_size = w32->o_dwidth != vo->dwidth || + w32->o_dheight != vo->dheight; w32->o_dwidth = vo->dwidth; w32->o_dheight = vo->dheight; - // the desired size is ignored in wid mode, it always matches the window size. - if (!w32->parent) { - if (w32->window_bounds_initialized) { - // restore vo_dwidth/vo_dheight, which are reset against our will - // in vo_config() - RECT r; - GetClientRect(w32->window, &r); - vo->dwidth = r.right; - vo->dheight = r.bottom; - } else { - w32->window_bounds_initialized = true; - reset_size = true; - pos_init = true; - w32->window_x = w32->prev_x = geo.win.x0; - w32->window_y = w32->prev_y = geo.win.y0; - } + if (!w32->parent && !w32->window_bounds_initialized) { + SetRect(&w32->windowrc, geo.win.x0, geo.win.y0, + geo.win.x0 + vo->dwidth, geo.win.y0 + vo->dheight); + w32->prev_windowrc = w32->windowrc; + w32->window_bounds_initialized = true; + w32->fit_on_screen = true; + goto finish; + } - if (reset_size) { - w32->prev_width = vo->dwidth = w32->o_dwidth; - w32->prev_height = vo->dheight = w32->o_dheight; - } - } else { + // The rect which size is going to be modified. + RECT *rc = &w32->windowrc; + + // 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; vo->dheight = r.bottom; + } else { + if (w32->current_fs) + rc = &w32->prev_windowrc; + w32->fit_on_screen = true; } - // Recenter window around old position on new video size - // excluding the case when initial position handled by win_state. - if (!pos_init) { - w32->window_x += w32->dw / 2 - vo->dwidth / 2; - w32->window_y += w32->dh / 2 - vo->dheight / 2; - } - w32->dw = vo->dwidth; - w32->dh = vo->dheight; + // Save new window size and position. + const int x = rc->left + rect_w(*rc) / 2 - vo->dwidth / 2; + const int y = rc->top + rect_h(*rc) / 2 - vo->dheight / 2; + SetRect(rc, x, y, x + vo->dwidth, y + vo->dheight); +finish: reinit_window_state(w32); } @@ -1320,25 +1333,18 @@ void vo_w32_config(struct vo *vo) mp_dispatch_run(w32->dispatch, gui_thread_reconfig, w32); } -static void thread_disable_ime(void) -{ - // Disables the IME for windows on this thread. imm32.dll must be loaded - // dynamically to account for machines without East Asian language support. - HMODULE imm32 = LoadLibraryW(L"imm32.dll"); - if (!imm32) - return; - BOOL (WINAPI *pImmDisableIME)(DWORD) = (BOOL (WINAPI*)(DWORD)) - GetProcAddress(imm32, "ImmDisableIME"); - if (pImmDisableIME) - pImmDisableIME(0); - FreeLibrary(imm32); -} - static void w32_api_load(struct vo_w32_state *w32) { HMODULE shcore_dll = LoadLibraryW(L"shcore.dll"); + // Available since Win8.1 w32->api.pGetDpiForMonitor = !shcore_dll ? NULL : (void *)GetProcAddress(shcore_dll, "GetDpiForMonitor"); + + // imm32.dll must be loaded dynamically + // to account for machines without East Asian language support + HMODULE imm32_dll = LoadLibraryW(L"imm32.dll"); + w32->api.pImmDisableIME = !imm32_dll ? NULL : + (void *)GetProcAddress(imm32_dll, "ImmDisableIME"); } static void *gui_thread(void *ptr) @@ -1350,7 +1356,10 @@ static void *gui_thread(void *ptr) mpthread_set_name("win32 window"); w32_api_load(w32); - thread_disable_ime(); + + // Disables the IME for windows on this thread + if (w32->api.pImmDisableIME) + w32->api.pImmDisableIME(0); if (w32->opts->WinID >= 0) w32->parent = (HWND)(intptr_t)(w32->opts->WinID); @@ -1423,6 +1432,9 @@ static void *gui_thread(void *ptr) EnableWindow(w32->window, 0); w32->cursor_visible = true; + w32->moving = false; + w32->snapped = false; + w32->snap_dx = w32->snap_dy = 0; update_screen_rect(w32); @@ -1544,10 +1556,11 @@ static int gui_thread_control(struct vo_w32_state *w32, int request, void *arg) reinit_window_state(w32); return VO_TRUE; case VOCTRL_ONTOP: - reinit_window_state(w32); + update_window_state(w32); return VO_TRUE; case VOCTRL_BORDER: - reinit_window_state(w32); + update_window_style(w32); + update_window_state(w32); return VO_TRUE; case VOCTRL_GET_FULLSCREEN: *(bool *)arg = w32->current_fs; @@ -1558,8 +1571,9 @@ static int gui_thread_control(struct vo_w32_state *w32, int request, void *arg) if (!w32->window_bounds_initialized) return VO_FALSE; - s[0] = w32->current_fs ? w32->prev_width : w32->dw; - s[1] = w32->current_fs ? w32->prev_height : w32->dh; + RECT *rc = w32->current_fs ? &w32->prev_windowrc : &w32->windowrc; + s[0] = rect_w(*rc); + s[1] = rect_h(*rc); return VO_TRUE; } case VOCTRL_SET_UNFS_WINDOW_SIZE: { @@ -1567,18 +1581,13 @@ static int gui_thread_control(struct vo_w32_state *w32, int request, void *arg) if (!w32->window_bounds_initialized) return VO_FALSE; - if (w32->current_fs) { - w32->prev_x += w32->prev_width / 2 - s[0] / 2; - w32->prev_y += w32->prev_height / 2 - s[1] / 2; - w32->prev_width = s[0]; - w32->prev_height = s[1]; - } else { - w32->window_x += w32->dw / 2 - s[0] / 2; - w32->window_y += w32->dh / 2 - s[1] / 2; - w32->dw = s[0]; - w32->dh = s[1]; - } + RECT *rc = w32->current_fs ? &w32->prev_windowrc : &w32->windowrc; + const int x = rc->left + rect_w(*rc) / 2 - s[0] / 2; + const int y = rc->top + rect_h(*rc) / 2 - s[1] / 2; + SetRect(rc, x, y, x + s[0], y + s[1]); + + w32->fit_on_screen = true; reinit_window_state(w32); return VO_TRUE; } @@ -1648,8 +1657,8 @@ static void do_control(void *ptr) *events |= atomic_fetch_and(&w32->event_flags, 0); // Safe access, since caller (owner of vo) is blocked. if (*events & VO_EVENT_RESIZE) { - w32->vo->dwidth = w32->dw; - w32->vo->dheight = w32->dh; + w32->vo->dwidth = rect_w(w32->windowrc); + w32->vo->dheight = rect_h(w32->windowrc); } } @@ -1660,8 +1669,8 @@ int vo_w32_control(struct vo *vo, int *events, int request, void *arg) *events |= atomic_fetch_and(&w32->event_flags, 0); if (*events & VO_EVENT_RESIZE) { mp_dispatch_lock(w32->dispatch); - vo->dwidth = w32->dw; - vo->dheight = w32->dh; + vo->dwidth = rect_w(w32->windowrc); + vo->dheight = rect_h(w32->windowrc); mp_dispatch_unlock(w32->dispatch); } return VO_TRUE; |