d3d9/tests: Accept AMD GPU sysmem sample failure in test_mipmap_upload.
[wine.git] / dlls / quartz / window.c
blob2064be7e320d8923ff34512f4106ffed4a980363
1 /*
2 * Common implementation of IVideoWindow
4 * Copyright 2012 Aric Stewart, CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "quartz_private.h"
23 #define WM_QUARTZ_DESTROY (WM_USER + WM_DESTROY)
25 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
27 static const WCHAR class_name[] = L"wine_quartz_window";
29 static inline struct video_window *impl_from_IVideoWindow(IVideoWindow *iface)
31 return CONTAINING_RECORD(iface, struct video_window, IVideoWindow_iface);
34 static LRESULT CALLBACK WndProcW(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
36 struct video_window *window = (struct video_window *)GetWindowLongPtrW(hwnd, 0);
38 if (!window)
39 return DefWindowProcW(hwnd, message, wparam, lparam);
41 switch (message)
43 case WM_KEYDOWN:
44 case WM_KEYUP:
45 case WM_LBUTTONDBLCLK:
46 case WM_LBUTTONDOWN:
47 case WM_LBUTTONUP:
48 case WM_MBUTTONDBLCLK:
49 case WM_MBUTTONDOWN:
50 case WM_MBUTTONUP:
51 case WM_MOUSEACTIVATE:
52 case WM_MOUSEMOVE:
53 case WM_NCLBUTTONDBLCLK:
54 case WM_NCLBUTTONDOWN:
55 case WM_NCLBUTTONUP:
56 case WM_NCMBUTTONDBLCLK:
57 case WM_NCMBUTTONDOWN:
58 case WM_NCMBUTTONUP:
59 case WM_NCMOUSEMOVE:
60 case WM_NCRBUTTONDBLCLK:
61 case WM_NCRBUTTONDOWN:
62 case WM_NCRBUTTONUP:
63 case WM_RBUTTONDBLCLK:
64 case WM_RBUTTONDOWN:
65 case WM_RBUTTONUP:
66 if (window->hwndDrain)
68 PostMessageW(window->hwndDrain, message, wparam, lparam);
69 return 0;
71 break;
72 case WM_SIZE:
73 if (window->default_dst)
74 GetClientRect(window->hwnd, &window->dst);
75 break;
76 case WM_QUARTZ_DESTROY:
77 DestroyWindow(hwnd);
78 return 0;
79 case WM_CLOSE:
81 IFilterGraph *graph = window->pFilter->graph;
82 IMediaEventSink *event_sink;
83 IVideoWindow_put_Visible(&window->IVideoWindow_iface, OAFALSE);
84 if (graph && SUCCEEDED(IFilterGraph_QueryInterface(graph,
85 &IID_IMediaEventSink,
86 (void **)&event_sink)))
88 IMediaEventSink_Notify(event_sink, EC_USERABORT, 0, 0);
89 IMediaEventSink_Release(event_sink);
91 return 0;
95 return DefWindowProcW(hwnd, message, wparam, lparam);
98 HRESULT video_window_create_window(struct video_window *window)
100 WNDCLASSW winclass = {0};
102 winclass.lpfnWndProc = WndProcW;
103 winclass.cbWndExtra = sizeof(window);
104 winclass.lpszClassName = class_name;
105 if (!RegisterClassW(&winclass) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
107 ERR("Failed to register class, error %lu.\n", GetLastError());
108 return E_FAIL;
111 if (!(window->hwnd = CreateWindowExW(0, class_name, L"ActiveMovie Window",
112 WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
113 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
114 NULL, NULL, NULL, NULL)))
116 ERR("Unable to create window\n");
117 return E_FAIL;
120 SetWindowLongPtrW(window->hwnd, 0, (LONG_PTR)window);
122 return S_OK;
125 HRESULT WINAPI BaseControlWindowImpl_QueryInterface(IVideoWindow *iface, REFIID iid, void **out)
127 struct video_window *window = impl_from_IVideoWindow(iface);
128 return IUnknown_QueryInterface(window->pFilter->outer_unk, iid, out);
131 ULONG WINAPI BaseControlWindowImpl_AddRef(IVideoWindow *iface)
133 struct video_window *window = impl_from_IVideoWindow(iface);
134 return IUnknown_AddRef(window->pFilter->outer_unk);
137 ULONG WINAPI BaseControlWindowImpl_Release(IVideoWindow *iface)
139 struct video_window *window = impl_from_IVideoWindow(iface);
140 return IUnknown_Release(window->pFilter->outer_unk);
143 HRESULT WINAPI BaseControlWindowImpl_GetTypeInfoCount(IVideoWindow *iface, UINT *count)
145 TRACE("iface %p, count %p.\n", iface, count);
146 *count = 1;
147 return S_OK;
150 HRESULT WINAPI BaseControlWindowImpl_GetTypeInfo(IVideoWindow *iface, UINT index,
151 LCID lcid, ITypeInfo **typeinfo)
153 TRACE("iface %p, index %u, lcid %#lx, typeinfo %p.\n", iface, index, lcid, typeinfo);
154 return strmbase_get_typeinfo(IVideoWindow_tid, typeinfo);
157 HRESULT WINAPI BaseControlWindowImpl_GetIDsOfNames(IVideoWindow *iface, REFIID iid,
158 LPOLESTR *names, UINT count, LCID lcid, DISPID *ids)
160 ITypeInfo *typeinfo;
161 HRESULT hr;
163 TRACE("iface %p, iid %s, names %p, count %u, lcid %#lx, ids %p.\n",
164 iface, debugstr_guid(iid), names, count, lcid, ids);
166 if (SUCCEEDED(hr = strmbase_get_typeinfo(IVideoWindow_tid, &typeinfo)))
168 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, ids);
169 ITypeInfo_Release(typeinfo);
171 return hr;
174 HRESULT WINAPI BaseControlWindowImpl_Invoke(IVideoWindow *iface, DISPID id, REFIID iid, LCID lcid,
175 WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *error_arg)
177 ITypeInfo *typeinfo;
178 HRESULT hr;
180 TRACE("iface %p, id %ld, iid %s, lcid %#lx, flags %#x, params %p, result %p, excepinfo %p, error_arg %p.\n",
181 iface, id, debugstr_guid(iid), lcid, flags, params, result, excepinfo, error_arg);
183 if (SUCCEEDED(hr = strmbase_get_typeinfo(IVideoWindow_tid, &typeinfo)))
185 hr = ITypeInfo_Invoke(typeinfo, iface, id, flags, params, result, excepinfo, error_arg);
186 ITypeInfo_Release(typeinfo);
188 return hr;
191 HRESULT WINAPI BaseControlWindowImpl_put_Caption(IVideoWindow *iface, BSTR caption)
193 struct video_window *window = impl_from_IVideoWindow(iface);
195 TRACE("window %p, caption %s.\n", window, debugstr_w(caption));
197 if (!SetWindowTextW(window->hwnd, caption))
198 return E_FAIL;
200 return S_OK;
203 HRESULT WINAPI BaseControlWindowImpl_get_Caption(IVideoWindow *iface, BSTR *caption)
205 struct video_window *window = impl_from_IVideoWindow(iface);
206 WCHAR *str;
207 int len;
209 TRACE("window %p, caption %p.\n", window, caption);
211 *caption = NULL;
213 len = GetWindowTextLengthW(window->hwnd) + 1;
214 if (!(str = heap_alloc(len * sizeof(WCHAR))))
215 return E_OUTOFMEMORY;
217 GetWindowTextW(window->hwnd, str, len);
218 *caption = SysAllocString(str);
219 heap_free(str);
220 return *caption ? S_OK : E_OUTOFMEMORY;
223 HRESULT WINAPI BaseControlWindowImpl_put_WindowStyle(IVideoWindow *iface, LONG style)
225 struct video_window *window = impl_from_IVideoWindow(iface);
227 TRACE("window %p, style %#lx.\n", window, style);
229 if (style & (WS_DISABLED|WS_HSCROLL|WS_MAXIMIZE|WS_MINIMIZE|WS_VSCROLL))
230 return E_INVALIDARG;
232 SetWindowLongW(window->hwnd, GWL_STYLE, style);
233 SetWindowPos(window->hwnd, 0, 0, 0, 0, 0,
234 SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
235 return S_OK;
238 HRESULT WINAPI BaseControlWindowImpl_get_WindowStyle(IVideoWindow *iface, LONG *style)
240 struct video_window *window = impl_from_IVideoWindow(iface);
242 TRACE("window %p, style %p.\n", window, style);
244 *style = GetWindowLongW(window->hwnd, GWL_STYLE);
245 return S_OK;
248 HRESULT WINAPI BaseControlWindowImpl_put_WindowStyleEx(IVideoWindow *iface, LONG style)
250 struct video_window *window = impl_from_IVideoWindow(iface);
252 TRACE("window %p, style %#lx.\n", window, style);
254 if (!SetWindowLongW(window->hwnd, GWL_EXSTYLE, style))
255 return E_FAIL;
256 return S_OK;
259 HRESULT WINAPI BaseControlWindowImpl_get_WindowStyleEx(IVideoWindow *iface, LONG *style)
261 struct video_window *window = impl_from_IVideoWindow(iface);
263 TRACE("window %p, style %p.\n", window, style);
265 *style = GetWindowLongW(window->hwnd, GWL_EXSTYLE);
266 return S_OK;
269 HRESULT WINAPI BaseControlWindowImpl_put_AutoShow(IVideoWindow *iface, LONG AutoShow)
271 struct video_window *This = impl_from_IVideoWindow(iface);
273 TRACE("window %p, AutoShow %ld.\n", This, AutoShow);
275 This->AutoShow = AutoShow;
277 return S_OK;
280 HRESULT WINAPI BaseControlWindowImpl_get_AutoShow(IVideoWindow *iface, LONG *AutoShow)
282 struct video_window *This = impl_from_IVideoWindow(iface);
284 TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow);
286 *AutoShow = This->AutoShow;
288 return S_OK;
291 HRESULT WINAPI BaseControlWindowImpl_put_WindowState(IVideoWindow *iface, LONG state)
293 struct video_window *window = impl_from_IVideoWindow(iface);
295 TRACE("window %p, state %ld.\n", window, state);
297 ShowWindow(window->hwnd, state);
298 return S_OK;
301 HRESULT WINAPI BaseControlWindowImpl_get_WindowState(IVideoWindow *iface, LONG *state)
303 struct video_window *window = impl_from_IVideoWindow(iface);
304 DWORD style;
306 TRACE("window %p, state %p.\n", window, state);
308 style = GetWindowLongPtrW(window->hwnd, GWL_STYLE);
309 if (!(style & WS_VISIBLE))
310 *state = SW_HIDE;
311 else if (style & WS_MINIMIZE)
312 *state = SW_MINIMIZE;
313 else if (style & WS_MAXIMIZE)
314 *state = SW_MAXIMIZE;
315 else
316 *state = SW_SHOW;
318 return S_OK;
321 HRESULT WINAPI BaseControlWindowImpl_put_BackgroundPalette(IVideoWindow *iface, LONG BackgroundPalette)
323 struct video_window *This = impl_from_IVideoWindow(iface);
325 FIXME("window %p, palette %ld, stub!\n", This, BackgroundPalette);
327 return S_OK;
330 HRESULT WINAPI BaseControlWindowImpl_get_BackgroundPalette(IVideoWindow *iface, LONG *pBackgroundPalette)
332 struct video_window *This = impl_from_IVideoWindow(iface);
334 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBackgroundPalette);
336 return S_OK;
339 HRESULT WINAPI BaseControlWindowImpl_put_Visible(IVideoWindow *iface, LONG visible)
341 struct video_window *window = impl_from_IVideoWindow(iface);
343 TRACE("window %p, visible %ld.\n", window, visible);
345 ShowWindow(window->hwnd, visible ? SW_SHOW : SW_HIDE);
346 return S_OK;
349 HRESULT WINAPI BaseControlWindowImpl_get_Visible(IVideoWindow *iface, LONG *visible)
351 struct video_window *window = impl_from_IVideoWindow(iface);
353 TRACE("window %p, visible %p.\n", window, visible);
355 if (!visible)
356 return E_POINTER;
358 *visible = IsWindowVisible(window->hwnd) ? OATRUE : OAFALSE;
359 return S_OK;
362 HRESULT WINAPI BaseControlWindowImpl_put_Left(IVideoWindow *iface, LONG left)
364 struct video_window *window = impl_from_IVideoWindow(iface);
365 RECT rect;
367 TRACE("window %p, left %ld.\n", window, left);
369 GetWindowRect(window->hwnd, &rect);
370 if (!SetWindowPos(window->hwnd, NULL, left, rect.top, 0, 0,
371 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE))
372 return E_FAIL;
374 return S_OK;
377 HRESULT WINAPI BaseControlWindowImpl_get_Left(IVideoWindow *iface, LONG *left)
379 struct video_window *window = impl_from_IVideoWindow(iface);
380 RECT rect;
382 TRACE("window %p, left %p.\n", window, left);
384 GetWindowRect(window->hwnd, &rect);
385 *left = rect.left;
386 return S_OK;
389 HRESULT WINAPI BaseControlWindowImpl_put_Width(IVideoWindow *iface, LONG width)
391 struct video_window *window = impl_from_IVideoWindow(iface);
392 RECT rect;
394 TRACE("window %p, width %ld.\n", window, width);
396 GetWindowRect(window->hwnd, &rect);
397 if (!SetWindowPos(window->hwnd, NULL, 0, 0, width, rect.bottom - rect.top,
398 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE))
399 return E_FAIL;
401 return S_OK;
404 HRESULT WINAPI BaseControlWindowImpl_get_Width(IVideoWindow *iface, LONG *width)
406 struct video_window *window = impl_from_IVideoWindow(iface);
407 RECT rect;
409 TRACE("window %p, width %p.\n", window, width);
411 GetWindowRect(window->hwnd, &rect);
412 *width = rect.right - rect.left;
413 return S_OK;
416 HRESULT WINAPI BaseControlWindowImpl_put_Top(IVideoWindow *iface, LONG top)
418 struct video_window *window = impl_from_IVideoWindow(iface);
419 RECT rect;
421 TRACE("window %p, top %ld.\n", window, top);
423 GetWindowRect(window->hwnd, &rect);
424 if (!SetWindowPos(window->hwnd, NULL, rect.left, top, 0, 0,
425 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE))
426 return E_FAIL;
428 return S_OK;
431 HRESULT WINAPI BaseControlWindowImpl_get_Top(IVideoWindow *iface, LONG *top)
433 struct video_window *window = impl_from_IVideoWindow(iface);
434 RECT rect;
436 TRACE("window %p, top %p.\n", window, top);
438 GetWindowRect(window->hwnd, &rect);
439 *top = rect.top;
440 return S_OK;
443 HRESULT WINAPI BaseControlWindowImpl_put_Height(IVideoWindow *iface, LONG height)
445 struct video_window *window = impl_from_IVideoWindow(iface);
446 RECT rect;
448 TRACE("window %p, height %ld.\n", window, height);
450 GetWindowRect(window->hwnd, &rect);
451 if (!SetWindowPos(window->hwnd, NULL, 0, 0, rect.right - rect.left,
452 height, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE))
453 return E_FAIL;
455 return S_OK;
458 HRESULT WINAPI BaseControlWindowImpl_get_Height(IVideoWindow *iface, LONG *height)
460 struct video_window *window = impl_from_IVideoWindow(iface);
461 RECT rect;
463 TRACE("window %p, height %p.\n", window, height);
465 GetWindowRect(window->hwnd, &rect);
466 *height = rect.bottom - rect.top;
467 return S_OK;
470 HRESULT WINAPI BaseControlWindowImpl_put_Owner(IVideoWindow *iface, OAHWND owner)
472 struct video_window *window = impl_from_IVideoWindow(iface);
473 HWND hwnd = window->hwnd;
475 TRACE("window %p, owner %#Ix.\n", window, owner);
477 /* Make sure we are marked as WS_CHILD before reparenting ourselves, so that
478 * we do not steal focus. LEGO Island depends on this. */
480 window->hwndOwner = (HWND)owner;
481 if (owner)
482 SetWindowLongPtrW(hwnd, GWL_STYLE, GetWindowLongPtrW(hwnd, GWL_STYLE) | WS_CHILD);
483 else
484 SetWindowLongPtrW(hwnd, GWL_STYLE, GetWindowLongPtrW(hwnd, GWL_STYLE) & ~WS_CHILD);
485 SetParent(hwnd, (HWND)owner);
487 return S_OK;
490 HRESULT WINAPI BaseControlWindowImpl_get_Owner(IVideoWindow *iface, OAHWND *Owner)
492 struct video_window *This = impl_from_IVideoWindow(iface);
494 TRACE("(%p/%p)->(%p)\n", This, iface, Owner);
496 *(HWND*)Owner = This->hwndOwner;
498 return S_OK;
501 HRESULT WINAPI BaseControlWindowImpl_put_MessageDrain(IVideoWindow *iface, OAHWND Drain)
503 struct video_window *This = impl_from_IVideoWindow(iface);
505 TRACE("window %p, drain %#Ix.\n", This, Drain);
507 This->hwndDrain = (HWND)Drain;
509 return S_OK;
512 HRESULT WINAPI BaseControlWindowImpl_get_MessageDrain(IVideoWindow *iface, OAHWND *Drain)
514 struct video_window *This = impl_from_IVideoWindow(iface);
516 TRACE("(%p/%p)->(%p)\n", This, iface, Drain);
518 *Drain = (OAHWND)This->hwndDrain;
520 return S_OK;
523 HRESULT WINAPI BaseControlWindowImpl_get_BorderColor(IVideoWindow *iface, LONG *Color)
525 struct video_window *This = impl_from_IVideoWindow(iface);
527 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, Color);
529 return S_OK;
532 HRESULT WINAPI BaseControlWindowImpl_put_BorderColor(IVideoWindow *iface, LONG Color)
534 struct video_window *This = impl_from_IVideoWindow(iface);
536 TRACE("window %p, colour %#lx.\n", This, Color);
538 return S_OK;
541 HRESULT WINAPI BaseControlWindowImpl_get_FullScreenMode(IVideoWindow *iface, LONG *FullScreenMode)
543 TRACE("(%p)->(%p)\n", iface, FullScreenMode);
545 return E_NOTIMPL;
548 HRESULT WINAPI BaseControlWindowImpl_put_FullScreenMode(IVideoWindow *iface, LONG fullscreen)
550 struct video_window *window = impl_from_IVideoWindow(iface);
552 TRACE("window %p, fullscreen %ld.\n", window, fullscreen);
554 return E_NOTIMPL;
557 HRESULT WINAPI BaseControlWindowImpl_SetWindowForeground(IVideoWindow *iface, LONG focus)
559 struct video_window *window = impl_from_IVideoWindow(iface);
560 UINT flags = SWP_NOMOVE | SWP_NOSIZE;
562 TRACE("window %p, focus %ld.\n", window, focus);
564 if (focus != OAFALSE && focus != OATRUE)
565 return E_INVALIDARG;
567 if (!window->pPin->peer)
568 return VFW_E_NOT_CONNECTED;
570 if (!focus)
571 flags |= SWP_NOACTIVATE;
572 SetWindowPos(window->hwnd, HWND_TOP, 0, 0, 0, 0, flags);
574 return S_OK;
577 HRESULT WINAPI BaseControlWindowImpl_SetWindowPosition(IVideoWindow *iface,
578 LONG left, LONG top, LONG width, LONG height)
580 struct video_window *window = impl_from_IVideoWindow(iface);
582 TRACE("window %p, left %ld, top %ld, width %ld, height %ld.\n", window, left, top, width, height);
584 if (!SetWindowPos(window->hwnd, NULL, left, top, width, height, SWP_NOACTIVATE | SWP_NOZORDER))
585 return E_FAIL;
586 return S_OK;
589 HRESULT WINAPI BaseControlWindowImpl_GetWindowPosition(IVideoWindow *iface,
590 LONG *left, LONG *top, LONG *width, LONG *height)
592 struct video_window *window = impl_from_IVideoWindow(iface);
593 RECT rect;
595 TRACE("window %p, left %p, top %p, width %p, height %p.\n", window, left, top, width, height);
597 GetWindowRect(window->hwnd, &rect);
598 *left = rect.left;
599 *top = rect.top;
600 *width = rect.right - rect.left;
601 *height = rect.bottom - rect.top;
602 return S_OK;
605 HRESULT WINAPI BaseControlWindowImpl_NotifyOwnerMessage(IVideoWindow *iface,
606 OAHWND hwnd, LONG message, LONG_PTR wparam, LONG_PTR lparam)
608 struct video_window *window = impl_from_IVideoWindow(iface);
610 TRACE("window %p, hwnd %#Ix, message %#lx, wparam %#Ix, lparam %#Ix.\n",
611 window, hwnd, message, wparam, lparam);
613 /* That these messages are forwarded, and no others, is stated by the
614 * DirectX documentation, and supported by manual testing. */
615 switch (message)
617 case WM_ACTIVATEAPP:
618 case WM_DEVMODECHANGE:
619 case WM_DISPLAYCHANGE:
620 case WM_PALETTECHANGED:
621 case WM_PALETTEISCHANGING:
622 case WM_QUERYNEWPALETTE:
623 case WM_SYSCOLORCHANGE:
624 SendMessageW(window->hwnd, message, wparam, lparam);
625 break;
628 return S_OK;
631 HRESULT WINAPI BaseControlWindowImpl_GetMinIdealImageSize(IVideoWindow *iface, LONG *width, LONG *height)
633 struct video_window *window = impl_from_IVideoWindow(iface);
634 RECT rect;
636 TRACE("window %p, width %p, height %p.\n", window, width, height);
638 rect = window->ops->get_default_rect(window);
639 *width = rect.right - rect.left;
640 *height = rect.bottom - rect.top;
641 return S_OK;
644 HRESULT WINAPI BaseControlWindowImpl_GetMaxIdealImageSize(IVideoWindow *iface, LONG *width, LONG *height)
646 struct video_window *window = impl_from_IVideoWindow(iface);
647 RECT rect;
649 TRACE("window %p, width %p, height %p.\n", window, width, height);
651 rect = window->ops->get_default_rect(window);
652 *width = rect.right - rect.left;
653 *height = rect.bottom - rect.top;
654 return S_OK;
657 HRESULT WINAPI BaseControlWindowImpl_GetRestorePosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop, LONG *pWidth, LONG *pHeight)
659 struct video_window *This = impl_from_IVideoWindow(iface);
661 FIXME("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight);
663 return S_OK;
666 HRESULT WINAPI BaseControlWindowImpl_HideCursor(IVideoWindow *iface, LONG hide)
668 struct video_window *window = impl_from_IVideoWindow(iface);
670 FIXME("window %p, hide %ld, stub!\n", window, hide);
672 return S_OK;
675 HRESULT WINAPI BaseControlWindowImpl_IsCursorHidden(IVideoWindow *iface, LONG *CursorHidden)
677 struct video_window *This = impl_from_IVideoWindow(iface);
679 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, CursorHidden);
681 return S_OK;
684 static inline struct video_window *impl_from_IBasicVideo(IBasicVideo *iface)
686 return CONTAINING_RECORD(iface, struct video_window, IBasicVideo_iface);
689 static HRESULT WINAPI basic_video_QueryInterface(IBasicVideo *iface, REFIID iid, void **out)
691 struct video_window *window = impl_from_IBasicVideo(iface);
692 return IUnknown_QueryInterface(window->pFilter->outer_unk, iid, out);
695 static ULONG WINAPI basic_video_AddRef(IBasicVideo *iface)
697 struct video_window *window = impl_from_IBasicVideo(iface);
698 return IUnknown_AddRef(window->pFilter->outer_unk);
701 static ULONG WINAPI basic_video_Release(IBasicVideo *iface)
703 struct video_window *window = impl_from_IBasicVideo(iface);
704 return IUnknown_Release(window->pFilter->outer_unk);
707 static HRESULT WINAPI basic_video_GetTypeInfoCount(IBasicVideo *iface, UINT *count)
709 TRACE("iface %p, count %p.\n", iface, count);
710 *count = 1;
711 return S_OK;
714 static HRESULT WINAPI basic_video_GetTypeInfo(IBasicVideo *iface, UINT index,
715 LCID lcid, ITypeInfo **typeinfo)
717 TRACE("iface %p, index %u, lcid %#lx, typeinfo %p.\n", iface, index, lcid, typeinfo);
718 return strmbase_get_typeinfo(IBasicVideo_tid, typeinfo);
721 static HRESULT WINAPI basic_video_GetIDsOfNames(IBasicVideo *iface, REFIID iid,
722 LPOLESTR *names, UINT count, LCID lcid, DISPID *ids)
724 ITypeInfo *typeinfo;
725 HRESULT hr;
727 TRACE("iface %p, iid %s, names %p, count %u, lcid %#lx, ids %p.\n",
728 iface, debugstr_guid(iid), names, count, lcid, ids);
730 if (SUCCEEDED(hr = strmbase_get_typeinfo(IBasicVideo_tid, &typeinfo)))
732 hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, ids);
733 ITypeInfo_Release(typeinfo);
735 return hr;
738 static HRESULT WINAPI basic_video_Invoke(IBasicVideo *iface, DISPID id, REFIID iid, LCID lcid,
739 WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *error_arg)
741 ITypeInfo *typeinfo;
742 HRESULT hr;
744 TRACE("iface %p, id %ld, iid %s, lcid %#lx, flags %#x, params %p, result %p, excepinfo %p, error_arg %p.\n",
745 iface, id, debugstr_guid(iid), lcid, flags, params, result, excepinfo, error_arg);
747 if (SUCCEEDED(hr = strmbase_get_typeinfo(IBasicVideo_tid, &typeinfo)))
749 hr = ITypeInfo_Invoke(typeinfo, iface, id, flags, params, result, excepinfo, error_arg);
750 ITypeInfo_Release(typeinfo);
752 return hr;
755 static const VIDEOINFOHEADER *get_video_format(struct video_window *window)
757 /* Members of VIDEOINFOHEADER up to bmiHeader are identical to those of
758 * VIDEOINFOHEADER2. */
759 return (const VIDEOINFOHEADER *)window->pPin->mt.pbFormat;
762 static const BITMAPINFOHEADER *get_bitmap_header(struct video_window *window)
764 const AM_MEDIA_TYPE *mt = &window->pPin->mt;
765 if (IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo))
766 return &((VIDEOINFOHEADER *)mt->pbFormat)->bmiHeader;
767 else
768 return &((VIDEOINFOHEADER2 *)mt->pbFormat)->bmiHeader;
771 static HRESULT WINAPI basic_video_get_AvgTimePerFrame(IBasicVideo *iface, REFTIME *reftime)
773 struct video_window *window = impl_from_IBasicVideo(iface);
775 if (!reftime)
776 return E_POINTER;
777 if (!window->pPin->peer)
778 return VFW_E_NOT_CONNECTED;
780 TRACE("window %p, reftime %p.\n", window, reftime);
782 *reftime = (double)get_video_format(window)->AvgTimePerFrame / 1e7;
783 return S_OK;
786 static HRESULT WINAPI basic_video_get_BitRate(IBasicVideo *iface, LONG *rate)
788 struct video_window *window = impl_from_IBasicVideo(iface);
790 TRACE("window %p, rate %p.\n", window, rate);
792 if (!rate)
793 return E_POINTER;
794 if (!window->pPin->peer)
795 return VFW_E_NOT_CONNECTED;
797 *rate = get_video_format(window)->dwBitRate;
798 return S_OK;
801 static HRESULT WINAPI basic_video_get_BitErrorRate(IBasicVideo *iface, LONG *rate)
803 struct video_window *window = impl_from_IBasicVideo(iface);
805 TRACE("window %p, rate %p.\n", window, rate);
807 if (!rate)
808 return E_POINTER;
809 if (!window->pPin->peer)
810 return VFW_E_NOT_CONNECTED;
812 *rate = get_video_format(window)->dwBitErrorRate;
813 return S_OK;
816 static HRESULT WINAPI basic_video_get_VideoWidth(IBasicVideo *iface, LONG *width)
818 struct video_window *window = impl_from_IBasicVideo(iface);
820 TRACE("window %p, width %p.\n", window, width);
822 if (!width)
823 return E_POINTER;
825 *width = get_bitmap_header(window)->biWidth;
827 return S_OK;
830 static HRESULT WINAPI basic_video_get_VideoHeight(IBasicVideo *iface, LONG *height)
832 struct video_window *window = impl_from_IBasicVideo(iface);
834 TRACE("window %p, height %p.\n", window, height);
836 if (!height)
837 return E_POINTER;
839 *height = abs(get_bitmap_header(window)->biHeight);
841 return S_OK;
844 static HRESULT WINAPI basic_video_put_SourceLeft(IBasicVideo *iface, LONG left)
846 struct video_window *window = impl_from_IBasicVideo(iface);
848 TRACE("window %p, left %ld.\n", window, left);
850 if (left < 0 || window->src.right + left - window->src.left > get_bitmap_header(window)->biWidth)
851 return E_INVALIDARG;
853 OffsetRect(&window->src, left - window->src.left, 0);
854 return S_OK;
857 static HRESULT WINAPI basic_video_get_SourceLeft(IBasicVideo *iface, LONG *left)
859 struct video_window *window = impl_from_IBasicVideo(iface);
861 TRACE("window %p, left %p.\n", window, left);
863 if (!left)
864 return E_POINTER;
866 *left = window->src.left;
867 return S_OK;
870 static HRESULT WINAPI basic_video_put_SourceWidth(IBasicVideo *iface, LONG width)
872 struct video_window *window = impl_from_IBasicVideo(iface);
874 TRACE("window %p, width %ld.\n", window, width);
876 if (width <= 0 || window->src.left + width > get_bitmap_header(window)->biWidth)
877 return E_INVALIDARG;
879 window->src.right = window->src.left + width;
880 return S_OK;
883 static HRESULT WINAPI basic_video_get_SourceWidth(IBasicVideo *iface, LONG *width)
885 struct video_window *window = impl_from_IBasicVideo(iface);
887 TRACE("window %p, width %p.\n", window, width);
889 if (!width)
890 return E_POINTER;
892 *width = window->src.right - window->src.left;
893 return S_OK;
896 static HRESULT WINAPI basic_video_put_SourceTop(IBasicVideo *iface, LONG top)
898 struct video_window *window = impl_from_IBasicVideo(iface);
900 TRACE("window %p, top %ld.\n", window, top);
902 if (top < 0 || window->src.bottom + top - window->src.top > get_bitmap_header(window)->biHeight)
903 return E_INVALIDARG;
905 OffsetRect(&window->src, 0, top - window->src.top);
906 return S_OK;
909 static HRESULT WINAPI basic_video_get_SourceTop(IBasicVideo *iface, LONG *top)
911 struct video_window *window = impl_from_IBasicVideo(iface);
913 TRACE("window %p, top %p.\n", window, top);
915 if (!top)
916 return E_POINTER;
918 *top = window->src.top;
919 return S_OK;
922 static HRESULT WINAPI basic_video_put_SourceHeight(IBasicVideo *iface, LONG height)
924 struct video_window *window = impl_from_IBasicVideo(iface);
926 TRACE("window %p, height %ld.\n", window, height);
928 if (height <= 0 || window->src.top + height > get_bitmap_header(window)->biHeight)
929 return E_INVALIDARG;
931 window->src.bottom = window->src.top + height;
932 return S_OK;
935 static HRESULT WINAPI basic_video_get_SourceHeight(IBasicVideo *iface, LONG *height)
937 struct video_window *window = impl_from_IBasicVideo(iface);
939 TRACE("window %p, height %p\n", window, height);
941 if (!height)
942 return E_POINTER;
944 *height = window->src.bottom - window->src.top;
945 return S_OK;
948 static HRESULT WINAPI basic_video_put_DestinationLeft(IBasicVideo *iface, LONG left)
950 struct video_window *window = impl_from_IBasicVideo(iface);
952 TRACE("window %p, left %ld.\n", window, left);
954 window->default_dst = FALSE;
955 OffsetRect(&window->dst, left - window->dst.left, 0);
956 return S_OK;
959 static HRESULT WINAPI basic_video_get_DestinationLeft(IBasicVideo *iface, LONG *left)
961 struct video_window *window = impl_from_IBasicVideo(iface);
963 TRACE("window %p, left %p.\n", window, left);
965 if (!left)
966 return E_POINTER;
968 *left = window->dst.left;
969 return S_OK;
972 static HRESULT WINAPI basic_video_put_DestinationWidth(IBasicVideo *iface, LONG width)
974 struct video_window *window = impl_from_IBasicVideo(iface);
976 TRACE("window %p, width %ld.\n", window, width);
978 if (width <= 0)
979 return E_INVALIDARG;
981 window->default_dst = FALSE;
982 window->dst.right = window->dst.left + width;
983 return S_OK;
986 static HRESULT WINAPI basic_video_get_DestinationWidth(IBasicVideo *iface, LONG *width)
988 struct video_window *window = impl_from_IBasicVideo(iface);
990 TRACE("window %p, width %p.\n", window, width);
992 if (!width)
993 return E_POINTER;
995 *width = window->dst.right - window->dst.left;
996 return S_OK;
999 static HRESULT WINAPI basic_video_put_DestinationTop(IBasicVideo *iface, LONG top)
1001 struct video_window *window = impl_from_IBasicVideo(iface);
1003 TRACE("window %p, top %ld.\n", window, top);
1005 window->default_dst = FALSE;
1006 OffsetRect(&window->dst, 0, top - window->dst.top);
1007 return S_OK;
1010 static HRESULT WINAPI basic_video_get_DestinationTop(IBasicVideo *iface, LONG *top)
1012 struct video_window *window = impl_from_IBasicVideo(iface);
1014 TRACE("window %p, top %p.\n", window, top);
1016 if (!top)
1017 return E_POINTER;
1019 *top = window->dst.top;
1020 return S_OK;
1023 static HRESULT WINAPI basic_video_put_DestinationHeight(IBasicVideo *iface, LONG height)
1025 struct video_window *window = impl_from_IBasicVideo(iface);
1027 TRACE("window %p, height %ld.\n", window, height);
1029 if (height <= 0)
1030 return E_INVALIDARG;
1032 window->default_dst = FALSE;
1033 window->dst.bottom = window->dst.top + height;
1034 return S_OK;
1037 static HRESULT WINAPI basic_video_get_DestinationHeight(IBasicVideo *iface, LONG *height)
1039 struct video_window *window = impl_from_IBasicVideo(iface);
1041 TRACE("window %p, height %p.\n", window, height);
1043 if (!height)
1044 return E_POINTER;
1046 *height = window->dst.bottom - window->dst.top;
1047 return S_OK;
1050 static HRESULT WINAPI basic_video_SetSourcePosition(IBasicVideo *iface,
1051 LONG left, LONG top, LONG width, LONG height)
1053 struct video_window *window = impl_from_IBasicVideo(iface);
1054 const BITMAPINFOHEADER *bitmap_header = get_bitmap_header(window);
1056 TRACE("window %p, left %ld, top %ld, width %ld, height %ld.\n", window, left, top, width, height);
1058 if (left < 0 || left + width > bitmap_header->biWidth || width <= 0)
1059 return E_INVALIDARG;
1060 if (top < 0 || top + height > bitmap_header->biHeight || height <= 0)
1061 return E_INVALIDARG;
1063 SetRect(&window->src, left, top, left + width, top + height);
1064 return S_OK;
1067 static HRESULT WINAPI basic_video_GetSourcePosition(IBasicVideo *iface,
1068 LONG *left, LONG *top, LONG *width, LONG *height)
1070 struct video_window *window = impl_from_IBasicVideo(iface);
1072 TRACE("window %p, left %p, top %p, width %p, height %p.\n", window, left, top, width, height);
1074 if (!left || !top || !width || !height)
1075 return E_POINTER;
1077 *left = window->src.left;
1078 *top = window->src.top;
1079 *width = window->src.right - window->src.left;
1080 *height = window->src.bottom - window->src.top;
1081 return S_OK;
1084 static HRESULT WINAPI basic_video_SetDefaultSourcePosition(IBasicVideo *iface)
1086 struct video_window *window = impl_from_IBasicVideo(iface);
1087 const BITMAPINFOHEADER *bitmap_header = get_bitmap_header(window);
1089 TRACE("window %p.\n", window);
1091 SetRect(&window->src, 0, 0, bitmap_header->biWidth, bitmap_header->biHeight);
1092 return S_OK;
1095 static HRESULT WINAPI basic_video_SetDestinationPosition(IBasicVideo *iface,
1096 LONG left, LONG top, LONG width, LONG height)
1098 struct video_window *window = impl_from_IBasicVideo(iface);
1100 TRACE("window %p, left %ld, top %ld, width %ld, height %ld.\n", window, left, top, width, height);
1102 if (width <= 0 || height <= 0)
1103 return E_INVALIDARG;
1105 window->default_dst = FALSE;
1106 SetRect(&window->dst, left, top, left + width, top + height);
1107 return S_OK;
1110 static HRESULT WINAPI basic_video_GetDestinationPosition(IBasicVideo *iface,
1111 LONG *left, LONG *top, LONG *width, LONG *height)
1113 struct video_window *window = impl_from_IBasicVideo(iface);
1115 TRACE("window %p, left %p, top %p, width %p, height %p.\n", window, left, top, width, height);
1117 if (!left || !top || !width || !height)
1118 return E_POINTER;
1120 *left = window->dst.left;
1121 *top = window->dst.top;
1122 *width = window->dst.right - window->dst.left;
1123 *height = window->dst.bottom - window->dst.top;
1124 return S_OK;
1127 static HRESULT WINAPI basic_video_SetDefaultDestinationPosition(IBasicVideo *iface)
1129 struct video_window *window = impl_from_IBasicVideo(iface);
1131 TRACE("window %p.\n", window);
1133 window->default_dst = TRUE;
1134 GetClientRect(window->hwnd, &window->dst);
1135 return S_OK;
1138 static HRESULT WINAPI basic_video_GetVideoSize(IBasicVideo *iface, LONG *width, LONG *height)
1140 struct video_window *window = impl_from_IBasicVideo(iface);
1141 const BITMAPINFOHEADER *bitmap_header = get_bitmap_header(window);
1143 TRACE("window %p, width %p, height %p.\n", window, width, height);
1145 if (!width || !height)
1146 return E_POINTER;
1148 *width = bitmap_header->biWidth;
1149 *height = bitmap_header->biHeight;
1150 return S_OK;
1153 static HRESULT WINAPI basic_video_GetVideoPaletteEntries(IBasicVideo *iface,
1154 LONG start, LONG count, LONG *ret_count, LONG *palette)
1156 struct video_window *window = impl_from_IBasicVideo(iface);
1158 FIXME("window %p, start %ld, count %ld, ret_count %p, palette %p, stub!\n",
1159 window, start, count, ret_count, palette);
1161 if (!ret_count || !palette)
1162 return E_POINTER;
1164 *ret_count = 0;
1165 return VFW_E_NO_PALETTE_AVAILABLE;
1168 static HRESULT WINAPI basic_video_GetCurrentImage(IBasicVideo *iface, LONG *size, LONG *image)
1170 struct video_window *window = impl_from_IBasicVideo(iface);
1172 TRACE("window %p, size %p, image %p.\n", window, size, image);
1174 if (!size || !image)
1175 return E_POINTER;
1177 return window->ops->get_current_image(window, size, image);
1180 static HRESULT WINAPI basic_video_IsUsingDefaultSource(IBasicVideo *iface)
1182 struct video_window *window = impl_from_IBasicVideo(iface);
1183 const BITMAPINFOHEADER *bitmap_header = get_bitmap_header(window);
1185 TRACE("window %p.\n", window);
1187 if (!window->src.left && !window->src.top
1188 && window->src.right == bitmap_header->biWidth
1189 && window->src.bottom == bitmap_header->biHeight)
1190 return S_OK;
1191 return S_FALSE;
1194 static HRESULT WINAPI basic_video_IsUsingDefaultDestination(IBasicVideo *iface)
1196 struct video_window *window = impl_from_IBasicVideo(iface);
1198 TRACE("window %p.\n", window);
1200 return window->default_dst ? S_OK : S_FALSE;
1203 static const IBasicVideoVtbl basic_video_vtbl =
1205 basic_video_QueryInterface,
1206 basic_video_AddRef,
1207 basic_video_Release,
1208 basic_video_GetTypeInfoCount,
1209 basic_video_GetTypeInfo,
1210 basic_video_GetIDsOfNames,
1211 basic_video_Invoke,
1212 basic_video_get_AvgTimePerFrame,
1213 basic_video_get_BitRate,
1214 basic_video_get_BitErrorRate,
1215 basic_video_get_VideoWidth,
1216 basic_video_get_VideoHeight,
1217 basic_video_put_SourceLeft,
1218 basic_video_get_SourceLeft,
1219 basic_video_put_SourceWidth,
1220 basic_video_get_SourceWidth,
1221 basic_video_put_SourceTop,
1222 basic_video_get_SourceTop,
1223 basic_video_put_SourceHeight,
1224 basic_video_get_SourceHeight,
1225 basic_video_put_DestinationLeft,
1226 basic_video_get_DestinationLeft,
1227 basic_video_put_DestinationWidth,
1228 basic_video_get_DestinationWidth,
1229 basic_video_put_DestinationTop,
1230 basic_video_get_DestinationTop,
1231 basic_video_put_DestinationHeight,
1232 basic_video_get_DestinationHeight,
1233 basic_video_SetSourcePosition,
1234 basic_video_GetSourcePosition,
1235 basic_video_SetDefaultSourcePosition,
1236 basic_video_SetDestinationPosition,
1237 basic_video_GetDestinationPosition,
1238 basic_video_SetDefaultDestinationPosition,
1239 basic_video_GetVideoSize,
1240 basic_video_GetVideoPaletteEntries,
1241 basic_video_GetCurrentImage,
1242 basic_video_IsUsingDefaultSource,
1243 basic_video_IsUsingDefaultDestination
1246 void video_window_unregister_class(void)
1248 if (!UnregisterClassW(class_name, NULL) && GetLastError() != ERROR_CLASS_DOES_NOT_EXIST)
1249 ERR("Failed to unregister class, error %lu.\n", GetLastError());
1252 void video_window_init(struct video_window *window, const IVideoWindowVtbl *vtbl,
1253 struct strmbase_filter *owner, struct strmbase_pin *pin, const struct video_window_ops *ops)
1255 memset(window, 0, sizeof(*window));
1256 window->ops = ops;
1257 window->IVideoWindow_iface.lpVtbl = vtbl;
1258 window->IBasicVideo_iface.lpVtbl = &basic_video_vtbl;
1259 window->default_dst = TRUE;
1260 window->AutoShow = OATRUE;
1261 window->pFilter = owner;
1262 window->pPin = pin;
1265 void video_window_cleanup(struct video_window *window)
1267 if (window->hwnd)
1269 /* Media Player Classic deadlocks if WM_PARENTNOTIFY is sent, so clear
1270 * the child style first. Just like Windows, we don't actually unparent
1271 * the window, to prevent extra focus events from being generated since
1272 * it would become top-level for a brief period before being destroyed. */
1273 SetWindowLongW(window->hwnd, GWL_STYLE, GetWindowLongW(window->hwnd, GWL_STYLE) & ~WS_CHILD);
1275 SendMessageW(window->hwnd, WM_QUARTZ_DESTROY, 0, 0);
1276 window->hwnd = NULL;