4 #include "osdep/keycodes.h"
5 #include "input/input.h"
6 #include "input/mouse.h"
10 #include "w32_common.h"
12 extern void mplayer_put_key(int code
);
14 #ifndef MONITOR_DEFAULTTOPRIMARY
15 #define MONITOR_DEFAULTTOPRIMARY 1
18 static const char* classname
= "MPlayer - Media player for Win32";
22 // last non-fullscreen extends
31 static HINSTANCE hInstance
;
33 static int cursor
= 1;
34 static int event_flags
;
37 static HMONITOR (WINAPI
* myMonitorFromWindow
)(HWND
, DWORD
);
38 static BOOL (WINAPI
* myGetMonitorInfo
)(HMONITOR
, LPMONITORINFO
);
39 static BOOL (WINAPI
* myEnumDisplayMonitors
)(HDC
, LPCRECT
, MONITORENUMPROC
, LPARAM
);
41 static LRESULT CALLBACK
WndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
) {
46 event_flags
|= VO_EVENT_EXPOSE
;
51 ClientToScreen(vo_window
, &p
);
56 event_flags
|= VO_EVENT_RESIZE
;
57 GetClientRect(vo_window
, &r
);
59 vo_dheight
= r
.bottom
;
62 mplayer_put_key(KEY_CLOSE_WIN
);
68 mp_msg(MSGT_VO
, MSGL_V
, "vo: win32: killing screensaver\n");
74 case VK_LEFT
: mplayer_put_key(KEY_LEFT
); break;
75 case VK_UP
: mplayer_put_key(KEY_UP
); break;
76 case VK_RIGHT
: mplayer_put_key(KEY_RIGHT
); break;
77 case VK_DOWN
: mplayer_put_key(KEY_DOWN
); break;
78 case VK_TAB
: mplayer_put_key(KEY_TAB
); break;
79 case VK_CONTROL
: mplayer_put_key(KEY_CTRL
); break;
80 case VK_DELETE
: mplayer_put_key(KEY_DELETE
); break;
81 case VK_INSERT
: mplayer_put_key(KEY_INSERT
); break;
82 case VK_HOME
: mplayer_put_key(KEY_HOME
); break;
83 case VK_END
: mplayer_put_key(KEY_END
); break;
84 case VK_PRIOR
: mplayer_put_key(KEY_PAGE_UP
); break;
85 case VK_NEXT
: mplayer_put_key(KEY_PAGE_DOWN
); break;
86 case VK_ESCAPE
: mplayer_put_key(KEY_ESC
); break;
90 mplayer_put_key(wParam
);
93 if (!vo_nomouse_input
&& (vo_fs
|| (wParam
& MK_CONTROL
))) {
94 mplayer_put_key(MOUSE_BTN0
);
99 SendMessage(hWnd
, WM_NCLBUTTONDOWN
, HTCAPTION
, 0);
104 if (!vo_nomouse_input
)
105 mplayer_put_key(MOUSE_BTN1
);
108 if (!vo_nomouse_input
)
109 mplayer_put_key(MOUSE_BTN2
);
112 if (!vo_nomouse_input
) {
113 int x
= GET_WHEEL_DELTA_WPARAM(wParam
);
115 mplayer_put_key(MOUSE_BTN3
);
117 mplayer_put_key(MOUSE_BTN4
);
122 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
125 int vo_w32_check_events(void) {
128 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
)) {
129 TranslateMessage(&msg
);
130 DispatchMessage(&msg
);
136 static BOOL CALLBACK
mon_enum(HMONITOR hmon
, HDC hdc
, LPRECT r
, LPARAM p
) {
137 // this defaults to the last screen if specified number does not exist
138 xinerama_x
= r
->left
;
140 vo_screenwidth
= r
->right
- r
->left
;
141 vo_screenheight
= r
->bottom
- r
->top
;
142 if (mon_cnt
== xinerama_screen
)
148 void update_xinerama_info(void) {
149 xinerama_x
= xinerama_y
= 0;
150 if (xinerama_screen
< -1) {
152 xinerama_x
= GetSystemMetrics(SM_XVIRTUALSCREEN
);
153 xinerama_y
= GetSystemMetrics(SM_YVIRTUALSCREEN
);
154 tmp
= GetSystemMetrics(SM_CXVIRTUALSCREEN
);
155 if (tmp
) vo_screenwidth
= tmp
;
156 tmp
= GetSystemMetrics(SM_CYVIRTUALSCREEN
);
157 if (tmp
) vo_screenheight
= tmp
;
158 } else if (xinerama_screen
== -1 && myMonitorFromWindow
&& myGetMonitorInfo
) {
160 HMONITOR m
= myMonitorFromWindow(vo_window
, MONITOR_DEFAULTTOPRIMARY
);
161 mi
.cbSize
= sizeof(mi
);
162 myGetMonitorInfo(m
, &mi
);
163 xinerama_x
= mi
.rcMonitor
.left
;
164 xinerama_y
= mi
.rcMonitor
.top
;
165 vo_screenwidth
= mi
.rcMonitor
.right
- mi
.rcMonitor
.left
;
166 vo_screenheight
= mi
.rcMonitor
.bottom
- mi
.rcMonitor
.top
;
167 } else if (xinerama_screen
> 0 && myEnumDisplayMonitors
) {
169 myEnumDisplayMonitors(NULL
, NULL
, mon_enum
, 0);
171 aspect_save_screenres(vo_screenwidth
, vo_screenheight
);
174 static void updateScreenProperties() {
176 dm
.dmSize
= sizeof dm
;
177 dm
.dmDriverExtra
= 0;
178 dm
.dmFields
= DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
179 if (!EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS
, &dm
)) {
180 mp_msg(MSGT_VO
, MSGL_ERR
, "vo: win32: unable to enumerate display settings!\n");
184 vo_screenwidth
= dm
.dmPelsWidth
;
185 vo_screenheight
= dm
.dmPelsHeight
;
186 vo_depthonscreen
= dm
.dmBitsPerPel
;
187 update_xinerama_info();
190 static void changeMode(void) {
192 dm
.dmSize
= sizeof dm
;
193 dm
.dmDriverExtra
= 0;
195 dm
.dmFields
= DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
196 dm
.dmBitsPerPel
= vo_depthonscreen
;
197 dm
.dmPelsWidth
= vo_screenwidth
;
198 dm
.dmPelsHeight
= vo_screenheight
;
202 int bestScore
= INT_MAX
;
204 for (i
= 0; EnumDisplaySettings(0, i
, &dm
); ++i
) {
205 int score
= (dm
.dmPelsWidth
- o_dwidth
) * (dm
.dmPelsHeight
- o_dheight
);
206 if (dm
.dmBitsPerPel
!= vo_depthonscreen
) continue;
207 if (dm
.dmPelsWidth
< o_dwidth
) continue;
208 if (dm
.dmPelsHeight
< o_dheight
) continue;
210 if (score
< bestScore
) {
217 EnumDisplaySettings(0, bestMode
, &dm
);
219 ChangeDisplaySettings(&dm
, CDS_FULLSCREEN
);
223 static void resetMode(void) {
225 ChangeDisplaySettings(0, 0);
228 static int createRenderingContext(void) {
229 HWND layer
= HWND_NOTOPMOST
;
230 PIXELFORMATDESCRIPTOR pfd
;
233 int style
= (vo_border
&& !vo_fs
) ?
234 (WS_OVERLAPPEDWINDOW
| WS_SIZEBOX
) : WS_POPUP
;
236 if (vo_fs
|| vo_ontop
) layer
= HWND_TOPMOST
;
250 updateScreenProperties();
251 ShowWindow(vo_window
, SW_HIDE
);
252 SetWindowLong(vo_window
, GWL_STYLE
, style
);
254 prev_width
= vo_dwidth
;
255 prev_height
= vo_dheight
;
258 vo_dwidth
= vo_screenwidth
;
259 vo_dheight
= vo_screenheight
;
263 vo_dwidth
= prev_width
;
264 vo_dheight
= prev_height
;
269 r
.right
= r
.left
+ vo_dwidth
;
271 r
.bottom
= r
.top
+ vo_dheight
;
272 AdjustWindowRect(&r
, style
, 0);
273 SetWindowPos(vo_window
, layer
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
, SWP_SHOWWINDOW
);
275 memset(&pfd
, 0, sizeof pfd
);
276 pfd
.nSize
= sizeof pfd
;
278 pfd
.dwFlags
= PFD_DRAW_TO_WINDOW
| PFD_SUPPORT_OPENGL
| PFD_DOUBLEBUFFER
;
279 pfd
.iPixelType
= PFD_TYPE_RGBA
;
281 pfd
.iLayerType
= PFD_MAIN_PLANE
;
282 pf
= ChoosePixelFormat(vo_hdc
, &pfd
);
284 mp_msg(MSGT_VO
, MSGL_ERR
, "vo: win32: unable to select a valid pixel format!\n");
288 SetPixelFormat(vo_hdc
, pf
, &pfd
);
290 mp_msg(MSGT_VO
, MSGL_V
, "vo: win32: running at %dx%d with depth %d\n", vo_screenwidth
, vo_screenheight
, vo_depthonscreen
);
295 int vo_w32_config(uint32_t width
, uint32_t height
, uint32_t flags
) {
296 // store original size for videomode switching
301 prev_height
= height
;
305 vo_fs
= flags
& VOFLAG_FULLSCREEN
;
306 vo_vm
= flags
& VOFLAG_MODESWITCHING
;
307 return createRenderingContext();
311 HICON mplayerIcon
= 0;
312 char exedir
[MAX_PATH
];
318 hInstance
= GetModuleHandle(0);
320 if (GetModuleFileName(0, exedir
, MAX_PATH
))
321 mplayerIcon
= ExtractIcon(hInstance
, exedir
, 0);
323 mplayerIcon
= LoadIcon(0, IDI_APPLICATION
);
326 WNDCLASSEX wcex
= { sizeof wcex
, CS_OWNDC
, WndProc
, 0, 0, hInstance
, mplayerIcon
, LoadCursor(0, IDC_ARROW
), (HBRUSH
)GetStockObject(BLACK_BRUSH
), 0, classname
, mplayerIcon
};
328 if (!RegisterClassEx(&wcex
)) {
329 mp_msg(MSGT_VO
, MSGL_ERR
, "vo: win32: unable to register window class!\n");
337 vo_window
= CreateWindowEx(0, classname
, classname
,
338 vo_border
? (WS_OVERLAPPEDWINDOW
| WS_SIZEBOX
) : WS_POPUP
,
339 CW_USEDEFAULT
, 0, 100, 100, 0, 0, hInstance
, 0);
341 mp_msg(MSGT_VO
, MSGL_ERR
, "vo: win32: unable to create window!\n");
346 vo_hdc
= GetDC(vo_window
);
348 myMonitorFromWindow
= NULL
;
349 myGetMonitorInfo
= NULL
;
350 myEnumDisplayMonitors
= NULL
;
351 user32
= GetModuleHandle("user32.dll");
353 myMonitorFromWindow
= GetProcAddress(user32
, "MonitorFromWindow");
354 myGetMonitorInfo
= GetProcAddress(user32
, "GetMonitorInfoA");
355 myEnumDisplayMonitors
= GetProcAddress(user32
, "EnumDisplayMonitors");
357 updateScreenProperties();
362 void vo_w32_fullscreen(void) {
365 createRenderingContext();
368 void vo_w32_border() {
369 vo_border
= !vo_border
;
370 createRenderingContext();
373 void vo_w32_ontop( void )
375 vo_ontop
= !vo_ontop
;
377 HWND layer
= HWND_NOTOPMOST
;
378 if (vo_ontop
) layer
= HWND_TOPMOST
;
379 SetWindowPos(vo_window
, layer
, (vo_screenwidth
- vo_dwidth
) / 2, (vo_screenheight
- vo_dheight
) / 2, vo_dwidth
, vo_dheight
, SWP_SHOWWINDOW
);
383 void vo_w32_uninit() {
384 mp_msg(MSGT_VO
, MSGL_V
, "vo: win32: uninit\n");
387 vo_depthonscreen
= 0;
389 DestroyWindow(vo_window
);
391 UnregisterClass(classname
, 0);