/** * \brief Toogle window ontop attribute. * * Should be called on VOCTRL_ONTOP event. */ void vo_w32_ontop(struct vo *vo) { vo->opts->ontop = !vo->opts->ontop; reinit_window_state(vo); }
/** * \brief Toogle window border attribute. * * Should be called on VOCTRL_BORDER event. */ void vo_w32_border(struct vo *vo) { vo->opts->border = !vo->opts->border; reinit_window_state(vo); }
/** * \brief Initialize w32_common framework. * * The first function that should be called from the w32_common framework. * It handles window creation on the screen with proper title and attributes. * It also initializes the framework's internal variables. The function should * be called after your own preinit initialization and you shouldn't do any * window management on your own. * * Global libvo variables changed: * vo_w32_window * vo_screenwidth * vo_screenheight * * \return 1 = Success, 0 = Failure */ int vo_w32_init(struct vo *vo) { struct vo_w32_state *w32 = vo->w32; if (w32 && w32->window) return 1; if (!w32) w32 = vo->w32 = talloc_zero(vo, struct vo_w32_state); HINSTANCE hInstance = GetModuleHandleW(NULL); HICON mplayerIcon = LoadIconW(hInstance, L"IDI_ICON1"); WNDCLASSEXW wcex = { .cbSize = sizeof wcex, .style = CS_OWNDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, .lpfnWndProc = WndProc, .hInstance = hInstance, .hIcon = mplayerIcon, .hCursor = LoadCursor(0, IDC_ARROW), .lpszClassName = classname, .hIconSm = mplayerIcon, }; if (!RegisterClassExW(&wcex)) { mp_msg(MSGT_VO, MSGL_ERR, "vo: win32: unable to register window class!\n"); return 0; } if (vo->opts->WinID >= 0) { RECT r; GetClientRect(WIN_ID_TO_HWND(vo->opts->WinID), &r); vo->dwidth = r.right; vo->dheight = r.bottom; w32->window = CreateWindowExW(WS_EX_NOPARENTNOTIFY, classname, classname, WS_CHILD | WS_VISIBLE, 0, 0, vo->dwidth, vo->dheight, WIN_ID_TO_HWND(vo->opts->WinID), 0, hInstance, vo); } else { w32->window = CreateWindowExW(0, classname, classname, update_style(vo, 0), CW_USEDEFAULT, 0, 100, 100, 0, 0, hInstance, vo); } if (!w32->window) { mp_msg(MSGT_VO, MSGL_ERR, "vo: win32: unable to create window!\n"); return 0; } if (vo->opts->WinID >= 0) EnableWindow(w32->window, 0); // we don't have proper event handling vo->wakeup_period = 0.02; updateScreenProperties(vo); mp_msg(MSGT_VO, MSGL_V, "vo: win32: running at %dx%d\n", vo->opts->screenwidth, vo->opts->screenheight); return 1; } /** * \brief Toogle fullscreen / windowed mode. * * Should be called on VOCTRL_FULLSCREEN event. The window is * always resized during this call, so the rendering context * should be reinitialized with the new dimensions. * It is unspecified if vo_check_events will create a resize * event in addition or not. */ void vo_w32_fullscreen(struct vo *vo) { vo->opts->fs = !vo->opts->fs; reinit_window_state(vo); }
/** * \brief Configure and show window on the screen. * * This function should be called in libvo's "config" callback. * It configures a window and shows it on the screen. * * \return 1 - Success, 0 - Failure */ int vo_w32_config(struct vo *vo, uint32_t width, uint32_t height, uint32_t flags) { struct vo_w32_state *w32 = vo->w32; PIXELFORMATDESCRIPTOR pfd; int pf; HDC vo_hdc = GetDC(w32->window); memset(&pfd, 0, sizeof pfd); pfd.nSize = sizeof pfd; pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; if (flags & VOFLAG_STEREO) pfd.dwFlags |= PFD_STEREO; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 24; pfd.iLayerType = PFD_MAIN_PLANE; pf = ChoosePixelFormat(vo_hdc, &pfd); if (!pf) { mp_msg(MSGT_VO, MSGL_ERR, "vo: win32: unable to select a valid pixel format!\n"); ReleaseDC(w32->window, vo_hdc); return 0; } SetPixelFormat(vo_hdc, pf, &pfd); ReleaseDC(w32->window, vo_hdc); // we already have a fully initialized window, so nothing needs to be done if (flags & VOFLAG_HIDDEN) return 1; bool reset_size = !(w32->o_dwidth == width && w32->o_dheight == height); w32->o_dwidth = width; w32->o_dheight = height; // the desired size is ignored in wid mode, it always matches the window size. if (vo->opts->WinID < 0) { 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 { // first vo_config call; vo_config() will always set vo_dx/dy so // that the window is centered on the screen, and this is the only // time we actually want to use vo_dy/dy (this is not sane, and // vo.h should provide a function to query the initial // window position instead) w32->window_bounds_initialized = true; reset_size = true; w32->window_x = w32->prev_x = vo->dx; w32->window_y = w32->prev_y = vo->dy; } if (reset_size) { w32->prev_width = vo->dwidth = width; w32->prev_height = vo->dheight = height; } } else { RECT r; GetClientRect(w32->window, &r); vo->dwidth = r.right; vo->dheight = r.bottom; } vo->opts->fs = flags & VOFLAG_FULLSCREEN; return reinit_window_state(vo); }
int vo_w32_control(struct vo *vo, int *events, int request, void *arg) { struct vo_w32_state *w32 = vo->w32; switch (request) { case VOCTRL_CHECK_EVENTS: *events |= vo_w32_check_events(vo); return VO_TRUE; case VOCTRL_FULLSCREEN: vo_w32_fullscreen(vo); *events |= VO_EVENT_RESIZE; return VO_TRUE; case VOCTRL_ONTOP: vo_w32_ontop(vo); return VO_TRUE; case VOCTRL_BORDER: vo_w32_border(vo); *events |= VO_EVENT_RESIZE; return VO_TRUE; case VOCTRL_UPDATE_SCREENINFO: w32_update_xinerama_info(vo); return VO_TRUE; case VOCTRL_GET_WINDOW_SIZE: { int *s = arg; if (!w32->window_bounds_initialized) return VO_FALSE; s[0] = w32->current_fs ? w32->prev_width : vo->dwidth; s[1] = w32->current_fs ? w32->prev_height : vo->dheight; return VO_TRUE; } case VOCTRL_SET_WINDOW_SIZE: { int *s = arg; if (!w32->window_bounds_initialized) return VO_FALSE; if (w32->current_fs) { w32->prev_width = s[0]; w32->prev_height = s[1]; } else { vo->dwidth = s[0]; vo->dheight = s[1]; } reinit_window_state(vo); *events |= VO_EVENT_RESIZE; return VO_TRUE; } case VOCTRL_SET_CURSOR_VISIBILITY: w32->cursor_visible = *(bool *)arg; if (vo_w32_is_cursor_in_client(vo)) { if (w32->cursor_visible) SetCursor(LoadCursor(NULL, IDC_ARROW)); else SetCursor(NULL); } return VO_TRUE; case VOCTRL_KILL_SCREENSAVER: w32->disable_screensaver = true; SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED); return VO_TRUE; case VOCTRL_RESTORE_SCREENSAVER: w32->disable_screensaver = false; SetThreadExecutionState(ES_CONTINUOUS); return VO_TRUE; case VOCTRL_UPDATE_WINDOW_TITLE: { wchar_t *title = mp_from_utf8(NULL, (char *)arg); SetWindowTextW(w32->window, title); talloc_free(title); return VO_TRUE; } } return VO_NOTIMPL; }
/** * \brief Initialize w32_common framework. * * The first function that should be called from the w32_common framework. * It handles window creation on the screen with proper title and attributes. * It also initializes the framework's internal variables. The function should * be called after your own preinit initialization and you shouldn't do any * window management on your own. * * Global libvo variables changed: * vo_w32_window * vo_screenwidth * vo_screenheight * * \return 1 = Success, 0 = Failure */ int vo_w32_init(struct vo *vo) { assert(!vo->w32); struct vo_w32_state *w32 = talloc_zero(vo, struct vo_w32_state); vo->w32 = w32; HINSTANCE hInstance = GetModuleHandleW(NULL); HICON mplayerIcon = LoadIconW(hInstance, L"IDI_ICON1"); WNDCLASSEXW wcex = { .cbSize = sizeof wcex, .style = CS_OWNDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, .lpfnWndProc = WndProc, .hInstance = hInstance, .hIcon = mplayerIcon, .hCursor = LoadCursor(NULL, IDC_ARROW), .lpszClassName = classname, .hIconSm = mplayerIcon, }; if (!RegisterClassExW(&wcex)) { MP_ERR(vo, "win32: unable to register window class!\n"); return 0; } if (vo->opts->WinID >= 0) { RECT r; GetClientRect(WIN_ID_TO_HWND(vo->opts->WinID), &r); vo->dwidth = r.right; vo->dheight = r.bottom; w32->window = CreateWindowExW(WS_EX_NOPARENTNOTIFY, classname, classname, WS_CHILD | WS_VISIBLE, 0, 0, vo->dwidth, vo->dheight, WIN_ID_TO_HWND(vo->opts->WinID), 0, hInstance, vo); } else { w32->window = CreateWindowExW(0, classname, classname, update_style(vo, 0), CW_USEDEFAULT, 0, 100, 100, 0, 0, hInstance, vo); } if (!w32->window) { MP_ERR(vo, "win32: unable to create window!\n"); return 0; } w32->tracking = FALSE; w32->trackEvent = (TRACKMOUSEEVENT){ .cbSize = sizeof(TRACKMOUSEEVENT), .dwFlags = TME_LEAVE, .hwndTrack = w32->window, }; if (vo->opts->WinID >= 0) EnableWindow(w32->window, 0); w32->cursor_visible = true; // we don't have proper event handling vo->wakeup_period = 0.02; updateScreenProperties(vo); MP_VERBOSE(vo, "win32: running at %dx%d\n", vo->opts->screenwidth, vo->opts->screenheight); return 1; } /** * \brief Toogle fullscreen / windowed mode. * * Should be called on VOCTRL_FULLSCREEN event. The window is * always resized during this call, so the rendering context * should be reinitialized with the new dimensions. * It is unspecified if vo_check_events will create a resize * event in addition or not. */ static void vo_w32_fullscreen(struct vo *vo) { if (vo->opts->fullscreen != vo->w32->current_fs) reinit_window_state(vo); } /** * \brief Toogle window border attribute. * * Should be called on VOCTRL_BORDER event. */ static void vo_w32_border(struct vo *vo) { vo->opts->border = !vo->opts->border; reinit_window_state(vo); } /** * \brief Toogle window ontop attribute. * * Should be called on VOCTRL_ONTOP event. */ static void vo_w32_ontop(struct vo *vo) { vo->opts->ontop = !vo->opts->ontop; reinit_window_state(vo); }