2009-02-08 04:27:30 +01:00
|
|
|
/*
|
|
|
|
* This file is part of MPlayer.
|
|
|
|
*
|
|
|
|
* MPlayer is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* MPlayer is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*/
|
|
|
|
|
2007-03-04 14:20:51 +01:00
|
|
|
#include <stdio.h>
|
2003-09-19 16:33:51 +02:00
|
|
|
#include <limits.h>
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
#include <assert.h>
|
2003-09-19 16:33:51 +02:00
|
|
|
#include <windows.h>
|
2007-03-04 14:20:51 +01:00
|
|
|
#include <windowsx.h>
|
2014-01-06 05:21:54 +01:00
|
|
|
#include <ole2.h>
|
2003-09-19 16:33:51 +02:00
|
|
|
|
2013-12-17 02:02:25 +01:00
|
|
|
#include "options/options.h"
|
2013-12-17 01:23:09 +01:00
|
|
|
#include "input/keycodes.h"
|
|
|
|
#include "input/input.h"
|
2014-01-06 05:21:54 +01:00
|
|
|
#include "input/event.h"
|
2013-12-17 02:39:45 +01:00
|
|
|
#include "common/msg.h"
|
|
|
|
#include "common/common.h"
|
2012-11-09 01:06:43 +01:00
|
|
|
#include "vo.h"
|
2014-05-06 23:01:19 +02:00
|
|
|
#include "win_state.h"
|
2003-09-19 16:33:51 +02:00
|
|
|
#include "w32_common.h"
|
2011-12-07 01:36:19 +01:00
|
|
|
#include "osdep/io.h"
|
2014-01-19 14:20:02 +01:00
|
|
|
#include "osdep/w32_keyboard.h"
|
2011-12-07 01:36:19 +01:00
|
|
|
#include "talloc.h"
|
2003-09-19 16:33:51 +02:00
|
|
|
|
2013-03-23 20:38:22 +01:00
|
|
|
#define WIN_ID_TO_HWND(x) ((HWND)(intptr_t)(x))
|
2012-02-27 19:15:13 +01:00
|
|
|
|
2012-10-11 02:04:08 +02:00
|
|
|
static const wchar_t classname[] = L"mpv";
|
2003-09-19 16:33:51 +02:00
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
struct vo_w32_state {
|
|
|
|
struct mp_log *log;
|
|
|
|
struct vo *vo;
|
|
|
|
struct mp_vo_opts *opts;
|
|
|
|
struct input_ctx *input_ctx;
|
|
|
|
|
|
|
|
HWND window;
|
|
|
|
|
|
|
|
// Size and virtual position of the current screen.
|
|
|
|
struct mp_rect screenrc;
|
|
|
|
|
|
|
|
// last non-fullscreen extends (updated only on fullscreen or on initialization)
|
|
|
|
int prev_width;
|
|
|
|
int prev_height;
|
|
|
|
int prev_x;
|
|
|
|
int prev_y;
|
|
|
|
|
|
|
|
// whether the window position and size were intialized
|
|
|
|
bool window_bounds_initialized;
|
|
|
|
|
|
|
|
bool current_fs;
|
|
|
|
|
|
|
|
// currently known window state
|
|
|
|
int window_x;
|
|
|
|
int window_y;
|
|
|
|
int dw;
|
|
|
|
int dh;
|
|
|
|
|
|
|
|
// video size
|
|
|
|
uint32_t o_dwidth;
|
|
|
|
uint32_t o_dheight;
|
|
|
|
|
|
|
|
bool disable_screensaver;
|
|
|
|
bool cursor_visible;
|
|
|
|
int event_flags;
|
|
|
|
int mon_cnt;
|
|
|
|
int mon_id;
|
|
|
|
|
|
|
|
BOOL tracking;
|
|
|
|
TRACKMOUSEEVENT trackEvent;
|
|
|
|
|
|
|
|
int mouse_x;
|
|
|
|
int mouse_y;
|
|
|
|
|
|
|
|
// UTF-16 decoding state for WM_CHAR and VK_PACKET
|
|
|
|
int high_surrogate;
|
|
|
|
};
|
|
|
|
|
2014-01-06 05:21:54 +01:00
|
|
|
typedef struct tagDropTarget {
|
|
|
|
IDropTarget iface;
|
|
|
|
ULONG refCnt;
|
|
|
|
DWORD lastEffect;
|
|
|
|
IDataObject* dataObj;
|
2014-07-26 20:27:03 +02:00
|
|
|
struct vo_w32_state *w32;
|
2014-01-06 05:21:54 +01:00
|
|
|
} DropTarget;
|
|
|
|
|
|
|
|
static FORMATETC fmtetc_file = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
|
|
|
static FORMATETC fmtetc_url = { 0, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
|
|
|
|
|
|
|
static void DropTarget_Destroy(DropTarget* This)
|
|
|
|
{
|
|
|
|
if (This->dataObj != NULL) {
|
|
|
|
This->dataObj->lpVtbl->Release(This->dataObj);
|
|
|
|
This->dataObj->lpVtbl = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
talloc_free(This);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE DropTarget_QueryInterface(IDropTarget* This,
|
|
|
|
REFIID riid,
|
|
|
|
void** ppvObject)
|
|
|
|
{
|
|
|
|
if (!IsEqualGUID(riid, &IID_IUnknown) ||
|
|
|
|
!IsEqualGUID(riid, &IID_IDataObject)) {
|
|
|
|
*ppvObject = NULL;
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*ppvObject = This;
|
|
|
|
This->lpVtbl->AddRef(This);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG STDMETHODCALLTYPE DropTarget_AddRef(IDropTarget* This)
|
|
|
|
{
|
|
|
|
DropTarget* t = (DropTarget*)This;
|
|
|
|
return ++(t->refCnt);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG STDMETHODCALLTYPE DropTarget_Release(IDropTarget* This)
|
|
|
|
{
|
|
|
|
DropTarget* t = (DropTarget*)This;
|
|
|
|
ULONG cRef = --(t->refCnt);
|
|
|
|
|
|
|
|
if (cRef == 0) {
|
|
|
|
DropTarget_Destroy(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cRef;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE DropTarget_DragEnter(IDropTarget* This,
|
|
|
|
IDataObject* pDataObj,
|
|
|
|
DWORD grfKeyState,
|
|
|
|
POINTL pt,
|
|
|
|
DWORD* pdwEffect)
|
|
|
|
{
|
|
|
|
DropTarget* t = (DropTarget*)This;
|
|
|
|
|
|
|
|
pDataObj->lpVtbl->AddRef(pDataObj);
|
|
|
|
if (pDataObj->lpVtbl->QueryGetData(pDataObj, &fmtetc_file) != S_OK &&
|
|
|
|
pDataObj->lpVtbl->QueryGetData(pDataObj, &fmtetc_url) != S_OK) {
|
|
|
|
|
|
|
|
*pdwEffect = DROPEFFECT_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (t->dataObj != NULL) {
|
|
|
|
t->dataObj->lpVtbl->Release(t->dataObj);
|
|
|
|
}
|
|
|
|
|
|
|
|
t->dataObj = pDataObj;
|
|
|
|
t->lastEffect = *pdwEffect;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE DropTarget_DragOver(IDropTarget* This,
|
|
|
|
DWORD grfKeyState,
|
|
|
|
POINTL pt,
|
|
|
|
DWORD* pdwEffect)
|
|
|
|
{
|
|
|
|
DropTarget* t = (DropTarget*)This;
|
|
|
|
|
|
|
|
*pdwEffect = t->lastEffect;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE DropTarget_DragLeave(IDropTarget* This)
|
|
|
|
{
|
|
|
|
DropTarget* t = (DropTarget*)This;
|
|
|
|
|
|
|
|
if (t->dataObj != NULL) {
|
|
|
|
t->dataObj->lpVtbl->Release(t->dataObj);
|
|
|
|
t->dataObj = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT STDMETHODCALLTYPE DropTarget_Drop(IDropTarget* This,
|
|
|
|
IDataObject* pDataObj,
|
|
|
|
DWORD grfKeyState, POINTL pt,
|
|
|
|
DWORD* pdwEffect)
|
|
|
|
{
|
|
|
|
DropTarget* t = (DropTarget*)This;
|
|
|
|
|
|
|
|
STGMEDIUM medium;
|
|
|
|
|
|
|
|
if (t->dataObj != NULL) {
|
|
|
|
t->dataObj->lpVtbl->Release(t->dataObj);
|
|
|
|
t->dataObj = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pDataObj->lpVtbl->AddRef(pDataObj);
|
|
|
|
|
|
|
|
if (pDataObj->lpVtbl->GetData(pDataObj, &fmtetc_file, &medium) == S_OK) {
|
|
|
|
if (GlobalLock(medium.hGlobal) != NULL) {
|
|
|
|
HDROP hDrop = (HDROP)medium.hGlobal;
|
|
|
|
|
|
|
|
UINT numFiles = DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0);
|
|
|
|
char** files = talloc_zero_array(NULL, char*, numFiles);
|
|
|
|
|
|
|
|
UINT nrecvd_files = 0;
|
|
|
|
for (UINT i = 0; i < numFiles; i++) {
|
|
|
|
UINT len = DragQueryFileW(hDrop, i, NULL, 0);
|
|
|
|
wchar_t* buf = talloc_array(NULL, wchar_t, len + 1);
|
|
|
|
|
|
|
|
if (DragQueryFileW(hDrop, i, buf, len + 1) == len) {
|
|
|
|
char* fname = mp_to_utf8(files, buf);
|
|
|
|
files[nrecvd_files++] = fname;
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
MP_VERBOSE(t->w32, "received dropped file: %s\n",
|
2014-01-06 05:21:54 +01:00
|
|
|
fname);
|
|
|
|
} else {
|
2014-07-26 20:27:03 +02:00
|
|
|
MP_ERR(t->w32, "error getting dropped file name\n");
|
2014-01-06 05:21:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
talloc_free(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
GlobalUnlock(medium.hGlobal);
|
2014-07-26 20:27:03 +02:00
|
|
|
mp_event_drop_files(t->w32->input_ctx, nrecvd_files, files);
|
2014-01-06 05:21:54 +01:00
|
|
|
|
|
|
|
talloc_free(files);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseStgMedium(&medium);
|
|
|
|
} else if (pDataObj->lpVtbl->GetData(pDataObj,
|
|
|
|
&fmtetc_url, &medium) == S_OK) {
|
|
|
|
// get the URL encoded in US-ASCII
|
|
|
|
char* url = (char*)GlobalLock(medium.hGlobal);
|
|
|
|
if (url != NULL) {
|
2014-07-26 20:27:03 +02:00
|
|
|
if (mp_event_drop_mime_data(t->w32->input_ctx, "text/uri-list",
|
2014-01-06 05:21:54 +01:00
|
|
|
bstr0(url)) > 0) {
|
2014-07-26 20:27:03 +02:00
|
|
|
MP_VERBOSE(t->w32, "received dropped URL: %s\n", url);
|
2014-01-06 05:21:54 +01:00
|
|
|
} else {
|
2014-07-26 20:27:03 +02:00
|
|
|
MP_ERR(t->w32, "error getting dropped URL\n");
|
2014-01-06 05:21:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
GlobalUnlock(medium.hGlobal);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseStgMedium(&medium);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
t->lastEffect = DROPEFFECT_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pDataObj->lpVtbl->Release(pDataObj);
|
|
|
|
*pdwEffect = t->lastEffect;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
static void DropTarget_Init(DropTarget* This, struct vo_w32_state *w32)
|
2014-01-06 05:21:54 +01:00
|
|
|
{
|
|
|
|
IDropTargetVtbl* vtbl = talloc(This, IDropTargetVtbl);
|
|
|
|
*vtbl = (IDropTargetVtbl){
|
|
|
|
DropTarget_QueryInterface, DropTarget_AddRef, DropTarget_Release,
|
|
|
|
DropTarget_DragEnter, DropTarget_DragOver, DropTarget_DragLeave,
|
|
|
|
DropTarget_Drop
|
|
|
|
};
|
|
|
|
|
|
|
|
This->iface.lpVtbl = vtbl;
|
|
|
|
This->refCnt = 0;
|
|
|
|
This->lastEffect = 0;
|
|
|
|
This->dataObj = NULL;
|
2014-07-26 20:27:03 +02:00
|
|
|
This->w32 = w32;
|
2014-01-06 05:21:54 +01:00
|
|
|
}
|
|
|
|
|
2012-04-14 13:39:53 +02:00
|
|
|
static void add_window_borders(HWND hwnd, RECT *rc)
|
2011-10-28 15:19:51 +02:00
|
|
|
{
|
2012-04-14 13:39:53 +02:00
|
|
|
AdjustWindowRect(rc, GetWindowLong(hwnd, GWL_STYLE), 0);
|
2011-10-28 15:19:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// basically a reverse AdjustWindowRect (win32 doesn't appear to have this)
|
2012-04-14 13:39:53 +02:00
|
|
|
static void subtract_window_borders(HWND hwnd, RECT *rc)
|
2011-10-28 15:19:51 +02:00
|
|
|
{
|
|
|
|
RECT b = { 0, 0, 0, 0 };
|
2012-04-14 13:39:53 +02:00
|
|
|
add_window_borders(hwnd, &b);
|
2011-10-28 15:19:51 +02:00
|
|
|
rc->left -= b.left;
|
|
|
|
rc->top -= b.top;
|
|
|
|
rc->right -= b.right;
|
|
|
|
rc->bottom -= b.bottom;
|
|
|
|
}
|
|
|
|
|
|
|
|
// turn a WMSZ_* input value in v into the border that should be resized
|
|
|
|
// returns: 0=left, 1=top, 2=right, 3=bottom, -1=undefined
|
2014-01-06 12:26:42 +01:00
|
|
|
static int get_resize_border(int v)
|
|
|
|
{
|
2011-10-28 15:19:51 +02:00
|
|
|
switch (v) {
|
|
|
|
case WMSZ_LEFT: return 3;
|
|
|
|
case WMSZ_TOP: return 2;
|
|
|
|
case WMSZ_RIGHT: return 3;
|
|
|
|
case WMSZ_BOTTOM: return 2;
|
|
|
|
case WMSZ_TOPLEFT: return 1;
|
|
|
|
case WMSZ_TOPRIGHT: return 1;
|
|
|
|
case WMSZ_BOTTOMLEFT: return 3;
|
|
|
|
case WMSZ_BOTTOMRIGHT: return 3;
|
|
|
|
default: return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
static bool key_state(int vk)
|
2012-04-14 13:27:34 +02:00
|
|
|
{
|
|
|
|
return GetKeyState(vk) & 0x8000;
|
|
|
|
}
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
static int mod_state(struct vo_w32_state *w32)
|
2012-04-06 23:14:21 +02:00
|
|
|
{
|
|
|
|
int res = 0;
|
2014-04-17 17:25:45 +02:00
|
|
|
|
|
|
|
// AltGr is represented as LCONTROL+RMENU on Windows
|
2014-07-26 20:27:03 +02:00
|
|
|
bool alt_gr = mp_input_use_alt_gr(w32->input_ctx) &&
|
|
|
|
key_state(VK_RMENU) && key_state(VK_LCONTROL);
|
2014-04-17 17:25:45 +02:00
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
if (key_state(VK_RCONTROL) || (key_state(VK_LCONTROL) && !alt_gr))
|
2013-02-12 01:34:04 +01:00
|
|
|
res |= MP_KEY_MODIFIER_CTRL;
|
2014-07-26 20:27:03 +02:00
|
|
|
if (key_state(VK_SHIFT))
|
2013-02-12 01:34:04 +01:00
|
|
|
res |= MP_KEY_MODIFIER_SHIFT;
|
2014-07-26 20:27:03 +02:00
|
|
|
if (key_state(VK_LMENU) || (key_state(VK_RMENU) && !alt_gr))
|
2013-02-12 01:34:04 +01:00
|
|
|
res |= MP_KEY_MODIFIER_ALT;
|
2012-04-06 23:14:21 +02:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2014-04-17 17:25:45 +02:00
|
|
|
static int decode_surrogate_pair(wchar_t lead, wchar_t trail)
|
|
|
|
{
|
|
|
|
return 0x10000 + ((lead & 0x3ff) << 10) | (trail & 0x3ff);
|
|
|
|
}
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
static int decode_utf16(struct vo_w32_state *w32, wchar_t c)
|
2014-04-17 17:25:45 +02:00
|
|
|
{
|
|
|
|
// Decode UTF-16, keeping state in w32->high_surrogate
|
|
|
|
if (IS_HIGH_SURROGATE(c)) {
|
|
|
|
w32->high_surrogate = c;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (IS_LOW_SURROGATE(c)) {
|
|
|
|
if (!w32->high_surrogate) {
|
2014-07-26 20:27:03 +02:00
|
|
|
MP_ERR(w32, "Invalid UTF-16 input\n");
|
2014-04-17 17:25:45 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int codepoint = decode_surrogate_pair(w32->high_surrogate, c);
|
|
|
|
w32->high_surrogate = 0;
|
|
|
|
return codepoint;
|
|
|
|
}
|
|
|
|
if (w32->high_surrogate != 0) {
|
|
|
|
w32->high_surrogate = 0;
|
2014-07-26 20:27:03 +02:00
|
|
|
MP_ERR(w32, "Invalid UTF-16 input\n");
|
2014-04-17 17:25:45 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void clear_keyboard_buffer(void)
|
|
|
|
{
|
|
|
|
static const UINT vkey = VK_DECIMAL;
|
|
|
|
static const BYTE keys[256] = { 0 };
|
|
|
|
UINT scancode = MapVirtualKey(vkey, MAPVK_VK_TO_VSC);
|
|
|
|
wchar_t buf[10];
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
// Use the method suggested by Michael Kaplan to clear any pending dead
|
|
|
|
// keys from the current keyboard layout. See:
|
|
|
|
// https://web.archive.org/web/20101004154432/http://blogs.msdn.com/b/michkap/archive/2006/04/06/569632.aspx
|
|
|
|
// https://web.archive.org/web/20100820152419/http://blogs.msdn.com/b/michkap/archive/2007/10/27/5717859.aspx
|
|
|
|
do {
|
|
|
|
ret = ToUnicode(vkey, scancode, keys, buf, MP_ARRAY_SIZE(buf), 0);
|
|
|
|
} while (ret < 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int to_unicode(UINT vkey, UINT scancode, const BYTE keys[256])
|
|
|
|
{
|
|
|
|
// This wraps ToUnicode to be stateless and to return only one character
|
|
|
|
|
|
|
|
// Make the buffer 10 code units long to be safe, same as here:
|
|
|
|
// https://web.archive.org/web/20101013215215/http://blogs.msdn.com/b/michkap/archive/2006/03/24/559169.aspx
|
|
|
|
wchar_t buf[10] = { 0 };
|
|
|
|
|
|
|
|
// Dead keys aren't useful for key shortcuts, so clear the keyboard state
|
|
|
|
clear_keyboard_buffer();
|
|
|
|
|
|
|
|
int len = ToUnicode(vkey, scancode, keys, buf, MP_ARRAY_SIZE(buf), 0);
|
|
|
|
|
|
|
|
// Return the last complete UTF-16 code point. A negative return value
|
|
|
|
// indicates a dead key, however there should still be a non-combining
|
|
|
|
// version of the key in the buffer.
|
|
|
|
if (len < 0)
|
|
|
|
len = -len;
|
|
|
|
if (len >= 2 && IS_SURROGATE_PAIR(buf[len - 2], buf[len - 1]))
|
|
|
|
return decode_surrogate_pair(buf[len - 2], buf[len - 1]);
|
|
|
|
if (len >= 1)
|
|
|
|
return buf[len - 1];
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
static int decode_key(struct vo_w32_state *w32, UINT vkey, UINT scancode)
|
2014-04-17 17:25:45 +02:00
|
|
|
{
|
|
|
|
BYTE keys[256];
|
|
|
|
GetKeyboardState(keys);
|
|
|
|
|
|
|
|
// If mp_input_use_alt_gr is false, detect and remove AltGr so normal
|
|
|
|
// characters are generated. Note that AltGr is represented as
|
|
|
|
// LCONTROL+RMENU on Windows.
|
|
|
|
if ((keys[VK_RMENU] & 0x80) && (keys[VK_LCONTROL] & 0x80) &&
|
2014-07-26 20:27:03 +02:00
|
|
|
!mp_input_use_alt_gr(w32->input_ctx))
|
2014-04-17 17:25:45 +02:00
|
|
|
{
|
|
|
|
keys[VK_RMENU] = keys[VK_LCONTROL] = 0;
|
|
|
|
keys[VK_MENU] = keys[VK_LMENU];
|
|
|
|
keys[VK_CONTROL] = keys[VK_RCONTROL];
|
|
|
|
}
|
|
|
|
|
|
|
|
int c = to_unicode(vkey, scancode, keys);
|
|
|
|
|
|
|
|
// Some shift states prevent ToUnicode from working or cause it to produce
|
|
|
|
// control characters. If this is detected, remove modifiers until it
|
|
|
|
// starts producing normal characters.
|
|
|
|
if (c < 0x20 && (keys[VK_MENU] & 0x80)) {
|
|
|
|
keys[VK_LMENU] = keys[VK_RMENU] = keys[VK_MENU] = 0;
|
|
|
|
c = to_unicode(vkey, scancode, keys);
|
|
|
|
}
|
|
|
|
if (c < 0x20 && (keys[VK_CONTROL] & 0x80)) {
|
|
|
|
keys[VK_LCONTROL] = keys[VK_RCONTROL] = keys[VK_CONTROL] = 0;
|
|
|
|
c = to_unicode(vkey, scancode, keys);
|
|
|
|
}
|
|
|
|
if (c < 0x20)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Decode lone UTF-16 surrogates (VK_PACKET can generate these)
|
|
|
|
if (c < 0x10000)
|
2014-07-26 20:27:03 +02:00
|
|
|
return decode_utf16(w32, c);
|
2014-04-17 17:25:45 +02:00
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
static void handle_key_down(struct vo_w32_state *w32, UINT vkey, UINT scancode)
|
2014-04-17 17:25:45 +02:00
|
|
|
{
|
|
|
|
// Ignore key repeat
|
|
|
|
if (scancode & KF_REPEAT)
|
|
|
|
return;
|
|
|
|
|
|
|
|
int mpkey = mp_w32_vkey_to_mpkey(vkey, scancode & KF_EXTENDED);
|
|
|
|
if (!mpkey) {
|
2014-07-26 20:27:03 +02:00
|
|
|
mpkey = decode_key(w32, vkey, scancode & (0xff | KF_EXTENDED));
|
2014-04-17 17:25:45 +02:00
|
|
|
if (!mpkey)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
mp_input_put_key(w32->input_ctx, mpkey | mod_state(w32) | MP_KEY_STATE_DOWN);
|
2014-04-17 17:25:45 +02:00
|
|
|
}
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
static void handle_key_up(struct vo_w32_state *w32, UINT vkey, UINT scancode)
|
2014-04-17 17:25:45 +02:00
|
|
|
{
|
|
|
|
switch (vkey) {
|
|
|
|
case VK_MENU:
|
|
|
|
case VK_CONTROL:
|
|
|
|
case VK_SHIFT:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// Releasing all keys on key-up is simpler and ensures no keys can be
|
|
|
|
// get "stuck." This matches the behaviour of other VOs.
|
2014-07-26 20:27:03 +02:00
|
|
|
mp_input_put_key(w32->input_ctx, MP_INPUT_RELEASE_ALL);
|
2014-04-17 17:25:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
static bool handle_char(struct vo_w32_state *w32, wchar_t wc)
|
2014-04-17 17:25:45 +02:00
|
|
|
{
|
2014-07-26 20:27:03 +02:00
|
|
|
int c = decode_utf16(w32, wc);
|
2014-04-17 17:25:45 +02:00
|
|
|
|
|
|
|
if (c == 0)
|
|
|
|
return true;
|
|
|
|
if (c < 0x20)
|
|
|
|
return false;
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
mp_input_put_key(w32->input_ctx, c | mod_state(w32));
|
2014-04-17 17:25:45 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-04-14 13:39:53 +02:00
|
|
|
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
|
|
|
if (message == WM_NCCREATE) {
|
|
|
|
CREATESTRUCT *cs = (void*)lParam;
|
|
|
|
SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)cs->lpCreateParams);
|
|
|
|
}
|
2014-07-26 20:27:03 +02:00
|
|
|
struct vo_w32_state *w32 = (void*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
|
2012-04-14 13:39:53 +02:00
|
|
|
// message before WM_NCCREATE, pray to Raymond Chen that it's not important
|
2014-07-26 20:27:03 +02:00
|
|
|
if (!w32)
|
2012-04-14 13:39:53 +02:00
|
|
|
return DefWindowProcW(hWnd, message, wParam, lParam);
|
2013-06-20 23:39:53 +02:00
|
|
|
int mouse_button = 0;
|
2012-04-14 13:39:53 +02:00
|
|
|
|
2003-09-19 16:33:51 +02:00
|
|
|
switch (message) {
|
2014-01-06 15:35:27 +01:00
|
|
|
case WM_ERASEBKGND: // no need to erase background seperately
|
|
|
|
return 1;
|
|
|
|
case WM_PAINT:
|
|
|
|
w32->event_flags |= VO_EVENT_EXPOSE;
|
|
|
|
break;
|
|
|
|
case WM_MOVE: {
|
|
|
|
POINT p = {0};
|
|
|
|
ClientToScreen(w32->window, &p);
|
|
|
|
w32->window_x = p.x;
|
|
|
|
w32->window_y = p.y;
|
2014-07-26 20:27:03 +02:00
|
|
|
MP_VERBOSE(w32, "move window: %d:%d\n", w32->window_x, w32->window_y);
|
2014-01-06 15:35:27 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case WM_SIZE: {
|
|
|
|
w32->event_flags |= VO_EVENT_RESIZE;
|
|
|
|
RECT r;
|
|
|
|
GetClientRect(w32->window, &r);
|
2014-07-26 20:27:03 +02:00
|
|
|
w32->dw = r.right;
|
|
|
|
w32->dh = r.bottom;
|
|
|
|
w32->vo->dwidth = w32->dw;
|
|
|
|
w32->vo->dheight = w32->dh;
|
|
|
|
MP_VERBOSE(w32, "resize window: %d:%d\n", w32->dw, w32->dh);
|
2014-01-06 15:35:27 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case WM_SIZING:
|
2014-07-26 20:27:03 +02:00
|
|
|
if (w32->opts->keepaspect && !w32->opts->fullscreen &&
|
|
|
|
w32->opts->WinID < 0)
|
2014-01-06 15:35:27 +01:00
|
|
|
{
|
|
|
|
RECT *rc = (RECT*)lParam;
|
|
|
|
// get client area of the windows if it had the rect rc
|
|
|
|
// (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;
|
|
|
|
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;
|
|
|
|
int d_corners[4] = { d_w, d_h, -d_w, -d_h };
|
|
|
|
int corners[4] = { rc->left, rc->top, rc->right, rc->bottom };
|
|
|
|
int corner = get_resize_border(wParam);
|
|
|
|
if (corner >= 0)
|
|
|
|
corners[corner] -= d_corners[corner];
|
|
|
|
*rc = (RECT) { corners[0], corners[1], corners[2], corners[3] };
|
|
|
|
return TRUE;
|
2012-04-06 23:14:21 +02:00
|
|
|
}
|
2014-01-06 15:35:27 +01:00
|
|
|
break;
|
|
|
|
case WM_CLOSE:
|
2014-07-26 20:27:03 +02:00
|
|
|
mp_input_put_key(w32->input_ctx, MP_KEY_CLOSE_WIN);
|
2014-01-06 15:35:27 +01:00
|
|
|
break;
|
|
|
|
case WM_SYSCOMMAND:
|
|
|
|
switch (wParam) {
|
|
|
|
case SC_SCREENSAVE:
|
|
|
|
case SC_MONITORPOWER:
|
|
|
|
if (w32->disable_screensaver) {
|
2014-07-26 20:27:03 +02:00
|
|
|
MP_VERBOSE(w32, "killing screensaver\n");
|
2012-04-06 23:14:21 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2012-04-07 14:47:06 +02:00
|
|
|
break;
|
2012-04-06 23:14:21 +02:00
|
|
|
}
|
2014-01-06 15:35:27 +01:00
|
|
|
break;
|
2014-01-14 12:27:42 +01:00
|
|
|
case WM_SYSKEYDOWN:
|
2014-04-17 17:25:45 +02:00
|
|
|
case WM_KEYDOWN:
|
2014-07-26 20:27:03 +02:00
|
|
|
handle_key_down(w32, wParam, HIWORD(lParam));
|
2014-04-17 17:25:45 +02:00
|
|
|
if (wParam == VK_F10)
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
case WM_SYSKEYUP:
|
|
|
|
case WM_KEYUP:
|
2014-07-26 20:27:03 +02:00
|
|
|
handle_key_up(w32, wParam, HIWORD(lParam));
|
2014-01-06 15:35:27 +01:00
|
|
|
if (wParam == VK_F10)
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
case WM_CHAR:
|
2014-04-17 17:25:45 +02:00
|
|
|
case WM_SYSCHAR:
|
2014-07-26 20:27:03 +02:00
|
|
|
if (handle_char(w32, wParam))
|
2014-01-06 15:35:27 +01:00
|
|
|
return 0;
|
|
|
|
break;
|
2014-04-17 17:25:45 +02:00
|
|
|
case WM_KILLFOCUS:
|
2014-07-26 20:27:03 +02:00
|
|
|
mp_input_put_key(w32->input_ctx, MP_INPUT_RELEASE_ALL);
|
2014-04-17 17:25:45 +02:00
|
|
|
break;
|
2014-01-06 15:35:27 +01:00
|
|
|
case WM_SETCURSOR:
|
|
|
|
if (LOWORD(lParam) == HTCLIENT && !w32->cursor_visible) {
|
|
|
|
SetCursor(NULL);
|
|
|
|
return TRUE;
|
2013-06-20 23:39:53 +02:00
|
|
|
}
|
2014-01-06 15:35:27 +01:00
|
|
|
break;
|
|
|
|
case WM_MOUSELEAVE:
|
|
|
|
w32->tracking = FALSE;
|
2014-07-26 20:27:03 +02:00
|
|
|
mp_input_put_key(w32->input_ctx, MP_KEY_MOUSE_LEAVE);
|
2014-01-06 15:35:27 +01:00
|
|
|
break;
|
|
|
|
case WM_MOUSEMOVE: {
|
|
|
|
if (!w32->tracking)
|
|
|
|
w32->tracking = TrackMouseEvent(&w32->trackEvent);
|
|
|
|
// Windows can send spurious mouse events, which would make the mpv
|
|
|
|
// core unhide the mouse cursor on completely unrelated events. See:
|
|
|
|
// https://blogs.msdn.com/b/oldnewthing/archive/2003/10/01/55108.aspx
|
|
|
|
int x = GET_X_LPARAM(lParam);
|
|
|
|
int y = GET_Y_LPARAM(lParam);
|
|
|
|
if (x != w32->mouse_x || y != w32->mouse_y) {
|
|
|
|
w32->mouse_x = x;
|
|
|
|
w32->mouse_y = y;
|
2014-07-26 20:27:03 +02:00
|
|
|
vo_mouse_movement(w32->vo, x, y);
|
2014-01-06 15:35:27 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
mouse_button = MP_MOUSE_BTN0 | MP_KEY_STATE_DOWN;
|
|
|
|
break;
|
|
|
|
case WM_LBUTTONUP:
|
|
|
|
mouse_button = MP_MOUSE_BTN0 | MP_KEY_STATE_UP;
|
|
|
|
break;
|
|
|
|
case WM_MBUTTONDOWN:
|
|
|
|
mouse_button = MP_MOUSE_BTN1 | MP_KEY_STATE_DOWN;
|
|
|
|
break;
|
|
|
|
case WM_MBUTTONUP:
|
|
|
|
mouse_button = MP_MOUSE_BTN1 | MP_KEY_STATE_UP;
|
|
|
|
break;
|
|
|
|
case WM_RBUTTONDOWN:
|
|
|
|
mouse_button = MP_MOUSE_BTN2 | MP_KEY_STATE_DOWN;
|
|
|
|
break;
|
|
|
|
case WM_RBUTTONUP:
|
|
|
|
mouse_button = MP_MOUSE_BTN2 | MP_KEY_STATE_UP;
|
|
|
|
break;
|
|
|
|
case WM_MOUSEWHEEL: {
|
|
|
|
int x = GET_WHEEL_DELTA_WPARAM(wParam);
|
|
|
|
mouse_button = x > 0 ? MP_MOUSE_BTN3 : MP_MOUSE_BTN4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case WM_XBUTTONDOWN:
|
|
|
|
mouse_button = HIWORD(wParam) == 1 ? MP_MOUSE_BTN5 : MP_MOUSE_BTN6;
|
|
|
|
mouse_button |= MP_KEY_STATE_DOWN;
|
|
|
|
break;
|
|
|
|
case WM_XBUTTONUP:
|
|
|
|
mouse_button = HIWORD(wParam) == 1 ? MP_MOUSE_BTN5 : MP_MOUSE_BTN6;
|
|
|
|
mouse_button |= MP_KEY_STATE_UP;
|
|
|
|
break;
|
2013-06-20 23:39:53 +02:00
|
|
|
}
|
|
|
|
|
2013-12-19 20:56:42 +01:00
|
|
|
if (mouse_button) {
|
2014-07-26 20:27:03 +02:00
|
|
|
mouse_button |= mod_state(w32);
|
|
|
|
mp_input_put_key(w32->input_ctx, mouse_button);
|
2013-12-19 20:56:42 +01:00
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
if (w32->opts->enable_mouse_movements) {
|
2013-12-19 20:56:42 +01:00
|
|
|
int x = GET_X_LPARAM(lParam);
|
|
|
|
int y = GET_Y_LPARAM(lParam);
|
|
|
|
|
|
|
|
if (mouse_button == (MP_MOUSE_BTN0 | MP_KEY_STATE_DOWN) &&
|
2014-07-26 20:27:03 +02:00
|
|
|
!w32->opts->fullscreen &&
|
|
|
|
!mp_input_test_dragging(w32->input_ctx, x, y))
|
2013-12-19 20:56:42 +01:00
|
|
|
{
|
|
|
|
// Window dragging hack
|
|
|
|
ReleaseCapture();
|
|
|
|
SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
|
2014-07-26 20:27:03 +02:00
|
|
|
mp_input_put_key(w32->input_ctx, MP_MOUSE_BTN0 |
|
|
|
|
MP_KEY_STATE_UP);
|
2013-12-19 20:56:42 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2014-02-20 15:21:17 +01:00
|
|
|
|
|
|
|
if (mouse_button & MP_KEY_STATE_DOWN)
|
|
|
|
SetCapture(w32->window);
|
|
|
|
else
|
|
|
|
ReleaseCapture();
|
2003-09-19 16:33:51 +02:00
|
|
|
}
|
2009-07-07 01:26:13 +02:00
|
|
|
|
2012-04-06 23:42:02 +02:00
|
|
|
return DefWindowProcW(hWnd, message, wParam, lParam);
|
2003-09-19 16:33:51 +02:00
|
|
|
}
|
|
|
|
|
2014-04-17 17:25:45 +02:00
|
|
|
static bool is_key_message(UINT msg)
|
2014-01-14 12:27:42 +01:00
|
|
|
{
|
2014-04-17 17:25:45 +02:00
|
|
|
return msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN ||
|
|
|
|
msg == WM_KEYUP || msg == WM_SYSKEYUP;
|
2014-01-14 12:27:42 +01:00
|
|
|
}
|
|
|
|
|
2008-11-18 13:23:23 +01:00
|
|
|
/**
|
|
|
|
* \brief Dispatch incoming window events and handle them.
|
|
|
|
*
|
|
|
|
* This function should be placed inside libvo's function "check_events".
|
|
|
|
*
|
|
|
|
* \return int with these flags possibly set, take care to handle in the right order
|
|
|
|
* if it matters in your driver:
|
|
|
|
*
|
|
|
|
* VO_EVENT_RESIZE = The window was resized. If necessary reinit your
|
|
|
|
* driver render context accordingly.
|
|
|
|
* VO_EVENT_EXPOSE = The window was exposed. Call e.g. flip_frame() to redraw
|
|
|
|
* the window if the movie is paused.
|
|
|
|
*/
|
2014-07-26 20:27:03 +02:00
|
|
|
static int vo_w32_check_events(struct vo_w32_state *w32)
|
2012-04-14 13:39:53 +02:00
|
|
|
{
|
2003-09-19 16:33:51 +02:00
|
|
|
MSG msg;
|
2012-04-14 13:39:53 +02:00
|
|
|
w32->event_flags = 0;
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2012-04-06 23:42:02 +02:00
|
|
|
while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE)) {
|
2014-04-17 17:25:45 +02:00
|
|
|
// Only send IME messages to TranslateMessage
|
|
|
|
if (is_key_message(msg.message) && msg.wParam == VK_PROCESSKEY)
|
2014-01-14 12:27:42 +01:00
|
|
|
TranslateMessage(&msg);
|
2012-04-06 23:42:02 +02:00
|
|
|
DispatchMessageW(&msg);
|
2003-09-19 16:33:51 +02:00
|
|
|
}
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
if (w32->opts->WinID >= 0) {
|
2010-05-19 19:53:47 +02:00
|
|
|
BOOL res;
|
2007-03-04 11:30:55 +01:00
|
|
|
RECT r;
|
2011-06-19 12:36:15 +02:00
|
|
|
POINT p;
|
2012-04-14 13:39:53 +02:00
|
|
|
res = GetClientRect(w32->window, &r);
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
if (res && (r.right != w32->dw || r.bottom != w32->dh)) {
|
|
|
|
w32->dw = r.right; w32->dh = r.bottom;
|
|
|
|
w32->vo->dwidth = w32->dw; w32->vo->dheight = w32->dh;
|
2012-04-14 13:39:53 +02:00
|
|
|
w32->event_flags |= VO_EVENT_RESIZE;
|
2008-12-03 11:54:01 +01:00
|
|
|
}
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2011-06-19 12:36:15 +02:00
|
|
|
p.x = 0; p.y = 0;
|
2012-04-14 13:39:53 +02:00
|
|
|
ClientToScreen(w32->window, &p);
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2012-04-14 13:39:53 +02:00
|
|
|
if (p.x != w32->window_x || p.y != w32->window_y) {
|
|
|
|
w32->window_x = p.x; w32->window_y = p.y;
|
2011-06-19 12:36:15 +02:00
|
|
|
}
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
res = GetClientRect(WIN_ID_TO_HWND(w32->opts->WinID), &r);
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
if (res && (r.right != w32->dw || r.bottom != w32->dh))
|
2012-04-14 13:39:53 +02:00
|
|
|
MoveWindow(w32->window, 0, 0, r.right, r.bottom, FALSE);
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
if (!IsWindow(WIN_ID_TO_HWND(w32->opts->WinID))) {
|
2010-05-19 19:53:47 +02:00
|
|
|
// Window has probably been closed, e.g. due to program crash
|
2014-07-26 20:27:03 +02:00
|
|
|
mp_input_put_key(w32->input_ctx, MP_KEY_CLOSE_WIN);
|
2014-01-06 12:26:42 +01:00
|
|
|
}
|
2007-03-04 11:30:55 +01:00
|
|
|
}
|
2009-07-07 01:26:13 +02:00
|
|
|
|
2012-04-14 13:39:53 +02:00
|
|
|
return w32->event_flags;
|
2003-09-19 16:33:51 +02:00
|
|
|
}
|
|
|
|
|
2012-04-14 13:39:53 +02:00
|
|
|
static BOOL CALLBACK mon_enum(HMONITOR hmon, HDC hdc, LPRECT r, LPARAM p)
|
|
|
|
{
|
2014-07-26 20:27:03 +02:00
|
|
|
struct vo_w32_state *w32 = (void *)p;
|
2006-04-16 15:38:28 +02:00
|
|
|
// this defaults to the last screen if specified number does not exist
|
2014-05-06 23:01:19 +02:00
|
|
|
w32->screenrc = (struct mp_rect){r->left, r->top, r->right, r->bottom};
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2013-02-17 16:35:44 +01:00
|
|
|
if (w32->mon_cnt == w32->mon_id)
|
2006-04-16 15:38:28 +02:00
|
|
|
return FALSE;
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2012-04-14 13:39:53 +02:00
|
|
|
w32->mon_cnt++;
|
2006-04-16 15:38:28 +02:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
static void w32_update_xinerama_info(struct vo_w32_state *w32)
|
2012-04-14 13:39:53 +02:00
|
|
|
{
|
2014-07-26 20:27:03 +02:00
|
|
|
struct mp_vo_opts *opts = w32->opts;
|
2013-07-18 14:05:39 +02:00
|
|
|
int screen = opts->fullscreen ? opts->fsscreen_id : opts->screen_id;
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2013-07-18 14:05:39 +02:00
|
|
|
if (opts->fullscreen && screen == -2) {
|
2014-05-06 23:01:19 +02:00
|
|
|
struct mp_rect rc = {
|
|
|
|
GetSystemMetrics(SM_XVIRTUALSCREEN),
|
|
|
|
GetSystemMetrics(SM_YVIRTUALSCREEN),
|
|
|
|
GetSystemMetrics(SM_CXVIRTUALSCREEN),
|
|
|
|
GetSystemMetrics(SM_CYVIRTUALSCREEN),
|
|
|
|
};
|
|
|
|
if (!rc.x1 || !rc.y1) {
|
2014-05-09 21:49:19 +02:00
|
|
|
rc.x0 = rc.y0 = 0;
|
|
|
|
rc.x1 = w32->screenrc.x1;
|
|
|
|
rc.y1 = w32->screenrc.y1;
|
2014-05-06 23:01:19 +02:00
|
|
|
}
|
|
|
|
rc.x1 += rc.x0;
|
|
|
|
rc.y1 += rc.y0;
|
|
|
|
w32->screenrc = rc;
|
2013-02-17 16:35:44 +01:00
|
|
|
} else if (screen == -1) {
|
2006-04-16 15:38:28 +02:00
|
|
|
MONITORINFO mi;
|
2012-04-14 13:39:53 +02:00
|
|
|
HMONITOR m = MonitorFromWindow(w32->window, MONITOR_DEFAULTTOPRIMARY);
|
2006-04-16 15:38:28 +02:00
|
|
|
mi.cbSize = sizeof(mi);
|
2012-04-06 23:42:02 +02:00
|
|
|
GetMonitorInfoW(m, &mi);
|
2014-05-06 23:01:19 +02:00
|
|
|
w32->screenrc = (struct mp_rect){
|
|
|
|
mi.rcMonitor.left, mi.rcMonitor.top,
|
|
|
|
mi.rcMonitor.right, mi.rcMonitor.bottom,
|
|
|
|
};
|
2013-02-17 16:35:44 +01:00
|
|
|
} else if (screen >= 0) {
|
2012-04-14 13:39:53 +02:00
|
|
|
w32->mon_cnt = 0;
|
2013-02-17 16:35:44 +01:00
|
|
|
w32->mon_id = screen;
|
2014-07-26 20:27:03 +02:00
|
|
|
EnumDisplayMonitors(NULL, NULL, mon_enum, (LONG_PTR)w32);
|
2006-04-16 15:38:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
static void updateScreenProperties(struct vo_w32_state *w32)
|
2012-04-14 13:39:53 +02:00
|
|
|
{
|
2005-02-21 15:44:39 +01:00
|
|
|
DEVMODE dm;
|
|
|
|
dm.dmSize = sizeof dm;
|
|
|
|
dm.dmDriverExtra = 0;
|
|
|
|
dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2005-02-21 15:44:39 +01:00
|
|
|
if (!EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &dm)) {
|
2014-07-26 20:27:03 +02:00
|
|
|
MP_ERR(w32, "unable to enumerate display settings!\n");
|
2007-03-04 11:39:02 +01:00
|
|
|
return;
|
2005-02-21 15:44:39 +01:00
|
|
|
}
|
|
|
|
|
2014-05-06 23:01:19 +02:00
|
|
|
w32->screenrc = (struct mp_rect){0, 0, dm.dmPelsWidth, dm.dmPelsHeight};
|
2014-07-26 20:27:03 +02:00
|
|
|
w32_update_xinerama_info(w32);
|
2005-02-21 15:44:39 +01:00
|
|
|
}
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
static DWORD update_style(struct vo_w32_state *w32, DWORD style)
|
2012-04-14 13:39:53 +02:00
|
|
|
{
|
|
|
|
const DWORD NO_FRAME = WS_POPUP;
|
|
|
|
const DWORD FRAME = WS_OVERLAPPEDWINDOW | WS_SIZEBOX;
|
|
|
|
style &= ~(NO_FRAME | FRAME);
|
2014-07-26 20:27:03 +02:00
|
|
|
style |= (w32->opts->border && !w32->opts->fullscreen) ? FRAME : NO_FRAME;
|
2012-04-14 13:39:53 +02:00
|
|
|
return style;
|
|
|
|
}
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
// Update the window title, position, size, and border style.
|
|
|
|
static int reinit_window_state(struct vo_w32_state *w32)
|
2012-04-14 13:39:53 +02:00
|
|
|
{
|
2003-11-30 17:36:10 +01:00
|
|
|
HWND layer = HWND_NOTOPMOST;
|
2005-11-17 21:49:46 +01:00
|
|
|
RECT r;
|
2003-09-19 16:33:51 +02:00
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
if (w32->opts->WinID >= 0)
|
2010-11-09 23:11:08 +01:00
|
|
|
return 1;
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
bool toggle_fs = w32->current_fs != w32->opts->fullscreen;
|
|
|
|
w32->current_fs = w32->opts->fullscreen;
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
DWORD style = update_style(w32, GetWindowLong(w32->window, GWL_STYLE));
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
if (w32->opts->ontop)
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
layer = HWND_TOPMOST;
|
|
|
|
|
|
|
|
// xxx not sure if this can trigger any unwanted messages (WM_MOVE/WM_SIZE)
|
2014-07-26 20:27:03 +02:00
|
|
|
updateScreenProperties(w32);
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
if (w32->opts->fullscreen) {
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
// Save window position and size when switching to fullscreen.
|
|
|
|
if (toggle_fs) {
|
2014-07-26 20:27:03 +02:00
|
|
|
w32->prev_width = w32->dw;
|
|
|
|
w32->prev_height = w32->dh;
|
2012-04-14 13:39:53 +02:00
|
|
|
w32->prev_x = w32->window_x;
|
|
|
|
w32->prev_y = w32->window_y;
|
2014-07-26 20:27:03 +02:00
|
|
|
MP_VERBOSE(w32, "save window bounds: %d:%d:%d:%d\n",
|
2012-04-14 13:39:53 +02:00
|
|
|
w32->prev_x, w32->prev_y, w32->prev_width, w32->prev_height);
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
}
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2014-05-06 23:01:19 +02:00
|
|
|
w32->window_x = w32->screenrc.x0;
|
|
|
|
w32->window_y = w32->screenrc.y0;
|
2014-07-26 20:27:03 +02:00
|
|
|
w32->dw = w32->screenrc.x1 - w32->screenrc.x0;
|
|
|
|
w32->dh = w32->screenrc.y1 - w32->screenrc.y0;
|
2014-01-06 14:12:08 +01:00
|
|
|
style &= ~WS_OVERLAPPEDWINDOW;
|
2006-04-12 16:11:26 +02:00
|
|
|
} else {
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
if (toggle_fs) {
|
|
|
|
// Restore window position and size when switching from fullscreen.
|
2014-07-26 20:27:03 +02:00
|
|
|
MP_VERBOSE(w32, "restore window bounds: %d:%d:%d:%d\n",
|
2012-04-14 13:39:53 +02:00
|
|
|
w32->prev_x, w32->prev_y, w32->prev_width, w32->prev_height);
|
2014-07-26 20:27:03 +02:00
|
|
|
w32->dw = w32->prev_width;
|
|
|
|
w32->dh = w32->prev_height;
|
2012-04-14 13:39:53 +02:00
|
|
|
w32->window_x = w32->prev_x;
|
|
|
|
w32->window_y = w32->prev_y;
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
}
|
2006-04-12 16:11:26 +02:00
|
|
|
}
|
2014-07-26 20:27:03 +02:00
|
|
|
w32->vo->dwidth = w32->dw;
|
|
|
|
w32->vo->dheight = w32->dh;
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
|
2012-04-14 13:39:53 +02:00
|
|
|
r.left = w32->window_x;
|
2014-07-26 20:27:03 +02:00
|
|
|
r.right = r.left + w32->dw;
|
2012-04-14 13:39:53 +02:00
|
|
|
r.top = w32->window_y;
|
2014-07-26 20:27:03 +02:00
|
|
|
r.bottom = r.top + w32->dh;
|
2011-11-18 00:59:48 +01:00
|
|
|
|
2012-04-14 13:39:53 +02:00
|
|
|
SetWindowLong(w32->window, GWL_STYLE, style);
|
|
|
|
add_window_borders(w32->window, &r);
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
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));
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
|
2012-04-14 13:39:53 +02:00
|
|
|
SetWindowPos(w32->window, layer, r.left, r.top, r.right - r.left,
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
r.bottom - r.top, SWP_FRAMECHANGED);
|
|
|
|
// For some reason, moving SWP_SHOWWINDOW to a second call works better
|
|
|
|
// with wine: returning from fullscreen doesn't cause a bogus resize to
|
|
|
|
// screen size.
|
|
|
|
// It's not needed on Windows XP or wine with a virtual desktop.
|
|
|
|
// It doesn't seem to have any negative effects.
|
2012-04-14 13:39:53 +02:00
|
|
|
SetWindowPos(w32->window, NULL, 0, 0, 0, 0,
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
|
|
|
|
|
2003-09-19 16:33:51 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2008-11-18 13:23:23 +01:00
|
|
|
/**
|
|
|
|
* \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
|
|
|
|
*/
|
2014-05-06 23:01:19 +02:00
|
|
|
int vo_w32_config(struct vo *vo, uint32_t flags)
|
2012-04-14 13:39:53 +02:00
|
|
|
{
|
|
|
|
struct vo_w32_state *w32 = vo->w32;
|
2010-11-10 23:10:30 +01:00
|
|
|
PIXELFORMATDESCRIPTOR pfd;
|
|
|
|
int pf;
|
2012-11-10 16:20:03 +01:00
|
|
|
HDC vo_hdc = GetDC(w32->window);
|
2010-11-10 23:10:30 +01:00
|
|
|
|
|
|
|
memset(&pfd, 0, sizeof pfd);
|
|
|
|
pfd.nSize = sizeof pfd;
|
|
|
|
pfd.nVersion = 1;
|
|
|
|
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2010-11-10 23:48:41 +01:00
|
|
|
if (flags & VOFLAG_STEREO)
|
|
|
|
pfd.dwFlags |= PFD_STEREO;
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2010-11-10 23:10:30 +01:00
|
|
|
pfd.iPixelType = PFD_TYPE_RGBA;
|
|
|
|
pfd.cColorBits = 24;
|
|
|
|
pfd.iLayerType = PFD_MAIN_PLANE;
|
|
|
|
pf = ChoosePixelFormat(vo_hdc, &pfd);
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2010-11-10 23:10:30 +01:00
|
|
|
if (!pf) {
|
2014-07-26 20:27:03 +02:00
|
|
|
MP_ERR(w32, "unable to select a valid pixel format!\n");
|
2012-11-10 16:20:03 +01:00
|
|
|
ReleaseDC(w32->window, vo_hdc);
|
2010-11-10 23:10:30 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
SetPixelFormat(vo_hdc, pf, &pfd);
|
2012-11-10 16:20:03 +01:00
|
|
|
ReleaseDC(w32->window, vo_hdc);
|
2010-11-10 23:10:30 +01:00
|
|
|
|
2010-02-04 23:46:45 +01:00
|
|
|
// we already have a fully initialized window, so nothing needs to be done
|
|
|
|
if (flags & VOFLAG_HIDDEN)
|
2010-05-19 19:55:39 +02:00
|
|
|
return 1;
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
|
2014-05-06 23:01:19 +02:00
|
|
|
struct vo_win_geometry geo;
|
|
|
|
vo_calc_window_geometry(vo, &w32->screenrc, &geo);
|
|
|
|
vo_apply_window_geometry(vo, &geo);
|
2014-07-26 20:27:03 +02:00
|
|
|
w32->dw = vo->dwidth;
|
|
|
|
w32->dh = vo->dheight;
|
2014-05-06 23:01:19 +02:00
|
|
|
|
|
|
|
bool reset_size = w32->o_dwidth != vo->dwidth || w32->o_dheight != vo->dheight;
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
|
2014-05-06 23:01:19 +02:00
|
|
|
w32->o_dwidth = vo->dwidth;
|
|
|
|
w32->o_dheight = vo->dheight;
|
2006-04-12 16:11:26 +02:00
|
|
|
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
// the desired size is ignored in wid mode, it always matches the window size.
|
2014-07-26 20:27:03 +02:00
|
|
|
if (w32->opts->WinID < 0) {
|
2012-04-14 13:39:53 +02:00
|
|
|
if (w32->window_bounds_initialized) {
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
// restore vo_dwidth/vo_dheight, which are reset against our will
|
|
|
|
// in vo_config()
|
|
|
|
RECT r;
|
2012-04-14 13:39:53 +02:00
|
|
|
GetClientRect(w32->window, &r);
|
|
|
|
vo->dwidth = r.right;
|
|
|
|
vo->dheight = r.bottom;
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
} else {
|
2012-04-14 13:39:53 +02:00
|
|
|
w32->window_bounds_initialized = true;
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
reset_size = true;
|
2014-05-06 23:01:19 +02:00
|
|
|
w32->window_x = w32->prev_x = geo.win.x0;
|
|
|
|
w32->window_y = w32->prev_y = geo.win.y0;
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
}
|
2014-01-06 12:26:42 +01:00
|
|
|
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
if (reset_size) {
|
2014-05-06 23:01:19 +02:00
|
|
|
w32->prev_width = vo->dwidth = w32->o_dwidth;
|
|
|
|
w32->prev_height = vo->dheight = w32->o_dheight;
|
win32: fix window creation and size handling
This commit fixes various issues with the way the window position and
size is setup. Most importantly, it fixes some bugs with restoring from
fullscreen state.
Rename create_rendering_context() to reinit_window_state(). This function
doesn't create anything, it just sets the window bounds and styles.
Do not use vo_dx/dy for the window position, as video_out.c overwrites it
with each vo_config() call. Use private variables window_x/y instead.
A big cause for issues was that reinit_window_state() accidentally cleared
the WS_VISIBLE style. I suspect that the API call to temporarily hide the
window was a hack to deal with this. Another bug was that the window style
was changed without calling SetWindowPos with SWP_FRAMECHANGED (as the
MSDN documentation says).
Properly initialize window position and size on vo_config following the
same rules as the x11 backend:
- Never change the window position. The window position should be kept, as
the user might move the window, and resetting the window position e.g.
during ordered chapter playback is not desired.
- Never change the window size, unless the size of the video changes.
These rules don't apply to fullscreen. When switching from fullscreen to
windowed mode, the backend should restore the previous windowed size and
position. When the VO was reconfigured during playback (vo_config() etc.),
the saved window position and size should be changed according to the
rules above, even if the window was in fullscreen mode during
reconfiguring.
Note that these rules might be perceived as awkward by some users: if you
play multiple files with different resolutions, the window won't be
centered when playing the files after the first. This is not a bug.
2011-10-22 02:11:14 +02:00
|
|
|
}
|
2013-03-19 23:36:43 +01:00
|
|
|
} else {
|
|
|
|
RECT r;
|
|
|
|
GetClientRect(w32->window, &r);
|
|
|
|
vo->dwidth = r.right;
|
|
|
|
vo->dheight = r.bottom;
|
2008-12-03 11:38:50 +01:00
|
|
|
}
|
2006-04-12 16:11:26 +02:00
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
return reinit_window_state(w32);
|
2006-04-12 16:11:26 +02:00
|
|
|
}
|
|
|
|
|
2008-11-18 13:23:23 +01:00
|
|
|
/**
|
|
|
|
* \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.
|
|
|
|
*
|
|
|
|
* \return 1 = Success, 0 = Failure
|
|
|
|
*/
|
2012-04-14 13:39:53 +02:00
|
|
|
int vo_w32_init(struct vo *vo)
|
|
|
|
{
|
2013-06-15 18:57:38 +02:00
|
|
|
assert(!vo->w32);
|
2003-09-19 16:33:51 +02:00
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
struct vo_w32_state *w32 = talloc_ptrtype(vo, w32);
|
2013-06-15 18:57:38 +02:00
|
|
|
vo->w32 = w32;
|
2014-07-26 20:27:03 +02:00
|
|
|
*w32 = (struct vo_w32_state){
|
|
|
|
.log = mp_log_new(w32, vo->log, "win32"),
|
|
|
|
.vo = vo,
|
|
|
|
.opts = vo->opts,
|
|
|
|
.input_ctx = vo->input_ctx,
|
|
|
|
};
|
2009-07-07 01:26:13 +02:00
|
|
|
|
2012-04-14 13:39:53 +02:00
|
|
|
HINSTANCE hInstance = GetModuleHandleW(NULL);
|
|
|
|
|
|
|
|
WNDCLASSEXW wcex = {
|
|
|
|
.cbSize = sizeof wcex,
|
2013-12-19 20:56:42 +01:00
|
|
|
.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW,
|
2012-04-14 13:39:53 +02:00
|
|
|
.lpfnWndProc = WndProc,
|
|
|
|
.hInstance = hInstance,
|
2014-02-16 11:32:58 +01:00
|
|
|
.hIcon = LoadIconW(hInstance, L"IDI_ICON1"),
|
2013-07-14 14:57:39 +02:00
|
|
|
.hCursor = LoadCursor(NULL, IDC_ARROW),
|
2012-04-14 13:39:53 +02:00
|
|
|
.lpszClassName = classname,
|
|
|
|
};
|
2003-09-19 16:33:51 +02:00
|
|
|
|
2012-04-06 23:42:02 +02:00
|
|
|
if (!RegisterClassExW(&wcex)) {
|
2014-07-26 20:27:03 +02:00
|
|
|
MP_ERR(w32, "unable to register window class!\n");
|
2007-03-04 11:39:02 +01:00
|
|
|
return 0;
|
2003-09-19 16:33:51 +02:00
|
|
|
}
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
if (w32->opts->WinID >= 0) {
|
2008-02-09 15:14:35 +01:00
|
|
|
RECT r;
|
2014-07-26 20:27:03 +02:00
|
|
|
GetClientRect(WIN_ID_TO_HWND(w32->opts->WinID), &r);
|
2012-04-14 13:39:53 +02:00
|
|
|
w32->window = CreateWindowExW(WS_EX_NOPARENTNOTIFY, classname,
|
|
|
|
classname,
|
|
|
|
WS_CHILD | WS_VISIBLE,
|
2014-07-26 20:27:03 +02:00
|
|
|
0, 0, r.right, r.bottom,
|
|
|
|
WIN_ID_TO_HWND(w32->opts->WinID),
|
|
|
|
0, hInstance, w32);
|
2012-04-14 13:39:53 +02:00
|
|
|
} else {
|
|
|
|
w32->window = CreateWindowExW(0, classname,
|
|
|
|
classname,
|
2014-07-26 20:27:03 +02:00
|
|
|
update_style(w32, 0),
|
2012-04-14 13:39:53 +02:00
|
|
|
CW_USEDEFAULT, 0, 100, 100,
|
2014-07-26 20:27:03 +02:00
|
|
|
0, 0, hInstance, w32);
|
2012-04-14 13:39:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!w32->window) {
|
2014-07-26 20:27:03 +02:00
|
|
|
MP_ERR(w32, "unable to create window!\n");
|
2007-03-04 11:39:02 +01:00
|
|
|
return 0;
|
2003-09-19 16:33:51 +02:00
|
|
|
}
|
|
|
|
|
2014-01-06 05:21:54 +01:00
|
|
|
if (OleInitialize(NULL) == S_OK) {
|
|
|
|
fmtetc_url.cfFormat = (CLIPFORMAT)RegisterClipboardFormat(TEXT("UniformResourceLocator"));
|
|
|
|
DropTarget* dropTarget = talloc(NULL, DropTarget);
|
2014-07-26 20:27:03 +02:00
|
|
|
DropTarget_Init(dropTarget, w32);
|
2014-01-06 05:21:54 +01:00
|
|
|
RegisterDragDrop(w32->window, &dropTarget->iface);
|
|
|
|
}
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2013-07-25 19:47:49 +02:00
|
|
|
w32->tracking = FALSE;
|
|
|
|
w32->trackEvent = (TRACKMOUSEEVENT){
|
|
|
|
.cbSize = sizeof(TRACKMOUSEEVENT),
|
|
|
|
.dwFlags = TME_LEAVE,
|
|
|
|
.hwndTrack = w32->window,
|
|
|
|
};
|
2013-07-25 19:19:12 +02:00
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
if (w32->opts->WinID >= 0)
|
2012-04-14 13:39:53 +02:00
|
|
|
EnableWindow(w32->window, 0);
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2013-07-14 14:57:39 +02:00
|
|
|
w32->cursor_visible = true;
|
2012-04-14 13:39:53 +02:00
|
|
|
|
2012-12-19 12:58:52 +01:00
|
|
|
// we don't have proper event handling
|
|
|
|
vo->wakeup_period = 0.02;
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
updateScreenProperties(w32);
|
2003-09-19 16:33:51 +02:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
static bool vo_w32_is_cursor_in_client(struct vo_w32_state *w32)
|
2013-07-14 14:57:39 +02:00
|
|
|
{
|
|
|
|
DWORD pos = GetMessagePos();
|
2014-07-26 20:27:03 +02:00
|
|
|
return SendMessage(w32->window, WM_NCHITTEST, 0, pos) == HTCLIENT;
|
2013-07-14 14:57:39 +02:00
|
|
|
}
|
|
|
|
|
2013-05-15 18:17:18 +02:00
|
|
|
int vo_w32_control(struct vo *vo, int *events, int request, void *arg)
|
|
|
|
{
|
2013-06-14 00:36:43 +02:00
|
|
|
struct vo_w32_state *w32 = vo->w32;
|
2013-05-15 18:17:18 +02:00
|
|
|
switch (request) {
|
2014-01-06 15:35:27 +01:00
|
|
|
case VOCTRL_CHECK_EVENTS:
|
2014-07-26 20:27:03 +02:00
|
|
|
*events |= vo_w32_check_events(w32);
|
2014-01-06 15:35:27 +01:00
|
|
|
return VO_TRUE;
|
|
|
|
case VOCTRL_FULLSCREEN:
|
2014-07-26 20:27:03 +02:00
|
|
|
if (w32->opts->fullscreen != w32->current_fs)
|
|
|
|
reinit_window_state(w32);
|
2014-01-06 15:35:27 +01:00
|
|
|
*events |= VO_EVENT_RESIZE;
|
|
|
|
return VO_TRUE;
|
|
|
|
case VOCTRL_ONTOP:
|
2014-07-26 20:27:03 +02:00
|
|
|
w32->opts->ontop = !w32->opts->ontop;
|
|
|
|
reinit_window_state(w32);
|
2014-01-06 15:35:27 +01:00
|
|
|
return VO_TRUE;
|
|
|
|
case VOCTRL_BORDER:
|
2014-07-26 20:27:03 +02:00
|
|
|
w32->opts->border = !w32->opts->border;
|
|
|
|
reinit_window_state(vo->w32);
|
2014-01-06 15:35:27 +01:00
|
|
|
*events |= VO_EVENT_RESIZE;
|
|
|
|
return VO_TRUE;
|
|
|
|
case VOCTRL_GET_WINDOW_SIZE: {
|
|
|
|
int *s = arg;
|
|
|
|
|
|
|
|
if (!w32->window_bounds_initialized)
|
|
|
|
return VO_FALSE;
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
s[0] = w32->current_fs ? w32->prev_width : w32->dw;
|
|
|
|
s[1] = w32->current_fs ? w32->prev_height : w32->dh;
|
2014-01-06 15:35:27 +01:00
|
|
|
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 {
|
2014-07-26 20:27:03 +02:00
|
|
|
w32->dw = s[0];
|
|
|
|
w32->dh = s[1];
|
2013-11-02 17:50:09 +01:00
|
|
|
}
|
2013-07-14 14:57:39 +02:00
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
reinit_window_state(w32);
|
2014-01-06 15:35:27 +01:00
|
|
|
*events |= VO_EVENT_RESIZE;
|
|
|
|
return VO_TRUE;
|
|
|
|
}
|
|
|
|
case VOCTRL_SET_CURSOR_VISIBILITY:
|
|
|
|
w32->cursor_visible = *(bool *)arg;
|
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
if (vo_w32_is_cursor_in_client(w32)) {
|
2014-01-06 15:35:27 +01:00
|
|
|
if (w32->cursor_visible)
|
|
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
|
|
else
|
|
|
|
SetCursor(NULL);
|
2013-05-17 00:10:46 +02:00
|
|
|
}
|
2014-01-06 15:35:27 +01:00
|
|
|
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;
|
|
|
|
}
|
2013-05-15 18:17:18 +02:00
|
|
|
}
|
|
|
|
return VO_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
2008-11-18 13:23:23 +01:00
|
|
|
/**
|
|
|
|
* \brief Uninitialize w32_common framework.
|
|
|
|
*
|
|
|
|
* Should be called last in video driver's uninit function. First release
|
2008-11-21 20:32:19 +01:00
|
|
|
* anything built on top of the created window e.g. rendering context inside
|
2008-11-18 13:23:23 +01:00
|
|
|
* and call vo_w32_uninit at the end.
|
|
|
|
*/
|
2012-04-14 13:39:53 +02:00
|
|
|
void vo_w32_uninit(struct vo *vo)
|
|
|
|
{
|
|
|
|
struct vo_w32_state *w32 = vo->w32;
|
2012-04-24 00:41:12 +02:00
|
|
|
if (!w32)
|
|
|
|
return;
|
2014-01-06 12:26:42 +01:00
|
|
|
|
2014-07-26 20:27:03 +02:00
|
|
|
MP_VERBOSE(w32, "uninit\n");
|
|
|
|
|
2014-01-06 05:21:54 +01:00
|
|
|
RevokeDragDrop(w32->window);
|
|
|
|
OleUninitialize();
|
2013-06-27 04:27:34 +02:00
|
|
|
SetThreadExecutionState(ES_CONTINUOUS);
|
2012-04-14 13:39:53 +02:00
|
|
|
DestroyWindow(w32->window);
|
2012-04-06 23:42:02 +02:00
|
|
|
UnregisterClassW(classname, 0);
|
2012-04-14 13:39:53 +02:00
|
|
|
talloc_free(w32);
|
|
|
|
vo->w32 = NULL;
|
2003-09-19 16:33:51 +02:00
|
|
|
}
|
2014-07-26 20:27:03 +02:00
|
|
|
|
|
|
|
HWND vo_w32_hwnd(struct vo *vo)
|
|
|
|
{
|
|
|
|
struct vo_w32_state *w32 = vo->w32;
|
|
|
|
return w32->window;
|
|
|
|
}
|