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);
39 return DefWindowProcW(hwnd
, message
, wparam
, lparam
);
45 case WM_LBUTTONDBLCLK
:
48 case WM_MBUTTONDBLCLK
:
51 case WM_MOUSEACTIVATE
:
53 case WM_NCLBUTTONDBLCLK
:
54 case WM_NCLBUTTONDOWN
:
56 case WM_NCMBUTTONDBLCLK
:
57 case WM_NCMBUTTONDOWN
:
60 case WM_NCRBUTTONDBLCLK
:
61 case WM_NCRBUTTONDOWN
:
63 case WM_RBUTTONDBLCLK
:
66 if (window
->hwndDrain
)
68 PostMessageW(window
->hwndDrain
, message
, wparam
, lparam
);
73 if (window
->default_dst
)
74 GetClientRect(window
->hwnd
, &window
->dst
);
76 case WM_QUARTZ_DESTROY
:
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
,
86 (void **)&event_sink
)))
88 IMediaEventSink_Notify(event_sink
, EC_USERABORT
, 0, 0);
89 IMediaEventSink_Release(event_sink
);
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());
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");
120 SetWindowLongPtrW(window
->hwnd
, 0, (LONG_PTR
)window
);
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
);
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
)
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
);
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
)
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
);
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 (!window
->pPin
->peer
)
198 return VFW_E_NOT_CONNECTED
;
200 if (!SetWindowTextW(window
->hwnd
, caption
))
206 HRESULT WINAPI
BaseControlWindowImpl_get_Caption(IVideoWindow
*iface
, BSTR
*caption
)
208 struct video_window
*window
= impl_from_IVideoWindow(iface
);
212 TRACE("window %p, caption %p.\n", window
, caption
);
216 len
= GetWindowTextLengthW(window
->hwnd
) + 1;
217 if (!(str
= heap_alloc(len
* sizeof(WCHAR
))))
218 return E_OUTOFMEMORY
;
220 GetWindowTextW(window
->hwnd
, str
, len
);
221 *caption
= SysAllocString(str
);
223 return *caption
? S_OK
: E_OUTOFMEMORY
;
226 HRESULT WINAPI
BaseControlWindowImpl_put_WindowStyle(IVideoWindow
*iface
, LONG style
)
228 struct video_window
*window
= impl_from_IVideoWindow(iface
);
230 TRACE("window %p, style %#lx.\n", window
, style
);
232 if (style
& (WS_DISABLED
|WS_HSCROLL
|WS_MAXIMIZE
|WS_MINIMIZE
|WS_VSCROLL
))
234 if (!window
->pPin
->peer
)
235 return VFW_E_NOT_CONNECTED
;
237 SetWindowLongW(window
->hwnd
, GWL_STYLE
, style
);
238 SetWindowPos(window
->hwnd
, 0, 0, 0, 0, 0,
239 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_FRAMECHANGED
);
243 HRESULT WINAPI
BaseControlWindowImpl_get_WindowStyle(IVideoWindow
*iface
, LONG
*style
)
245 struct video_window
*window
= impl_from_IVideoWindow(iface
);
247 TRACE("window %p, style %p.\n", window
, style
);
249 *style
= GetWindowLongW(window
->hwnd
, GWL_STYLE
);
253 HRESULT WINAPI
BaseControlWindowImpl_put_WindowStyleEx(IVideoWindow
*iface
, LONG style
)
255 struct video_window
*window
= impl_from_IVideoWindow(iface
);
257 TRACE("window %p, style %#lx.\n", window
, style
);
259 if (!SetWindowLongW(window
->hwnd
, GWL_EXSTYLE
, style
))
264 HRESULT WINAPI
BaseControlWindowImpl_get_WindowStyleEx(IVideoWindow
*iface
, LONG
*style
)
266 struct video_window
*window
= impl_from_IVideoWindow(iface
);
268 TRACE("window %p, style %p.\n", window
, style
);
270 *style
= GetWindowLongW(window
->hwnd
, GWL_EXSTYLE
);
274 HRESULT WINAPI
BaseControlWindowImpl_put_AutoShow(IVideoWindow
*iface
, LONG AutoShow
)
276 struct video_window
*window
= impl_from_IVideoWindow(iface
);
278 TRACE("window %p, AutoShow %ld.\n", window
, AutoShow
);
280 if (!window
->pPin
->peer
)
281 return VFW_E_NOT_CONNECTED
;
283 window
->AutoShow
= AutoShow
;
288 HRESULT WINAPI
BaseControlWindowImpl_get_AutoShow(IVideoWindow
*iface
, LONG
*AutoShow
)
290 struct video_window
*This
= impl_from_IVideoWindow(iface
);
292 TRACE("(%p/%p)->(%p)\n", This
, iface
, AutoShow
);
294 *AutoShow
= This
->AutoShow
;
299 HRESULT WINAPI
BaseControlWindowImpl_put_WindowState(IVideoWindow
*iface
, LONG state
)
301 struct video_window
*window
= impl_from_IVideoWindow(iface
);
303 TRACE("window %p, state %ld.\n", window
, state
);
305 ShowWindow(window
->hwnd
, state
);
309 HRESULT WINAPI
BaseControlWindowImpl_get_WindowState(IVideoWindow
*iface
, LONG
*state
)
311 struct video_window
*window
= impl_from_IVideoWindow(iface
);
314 TRACE("window %p, state %p.\n", window
, state
);
316 style
= GetWindowLongPtrW(window
->hwnd
, GWL_STYLE
);
317 if (!(style
& WS_VISIBLE
))
319 else if (style
& WS_MINIMIZE
)
320 *state
= SW_MINIMIZE
;
321 else if (style
& WS_MAXIMIZE
)
322 *state
= SW_MAXIMIZE
;
329 HRESULT WINAPI
BaseControlWindowImpl_put_BackgroundPalette(IVideoWindow
*iface
, LONG BackgroundPalette
)
331 struct video_window
*This
= impl_from_IVideoWindow(iface
);
333 FIXME("window %p, palette %ld, stub!\n", This
, BackgroundPalette
);
338 HRESULT WINAPI
BaseControlWindowImpl_get_BackgroundPalette(IVideoWindow
*iface
, LONG
*pBackgroundPalette
)
340 struct video_window
*This
= impl_from_IVideoWindow(iface
);
342 FIXME("(%p/%p)->(%p): stub !!!\n", This
, iface
, pBackgroundPalette
);
347 HRESULT WINAPI
BaseControlWindowImpl_put_Visible(IVideoWindow
*iface
, LONG visible
)
349 struct video_window
*window
= impl_from_IVideoWindow(iface
);
351 TRACE("window %p, visible %ld.\n", window
, visible
);
353 if (!window
->pPin
->peer
)
354 return VFW_E_NOT_CONNECTED
;
356 ShowWindow(window
->hwnd
, visible
? SW_SHOW
: SW_HIDE
);
360 HRESULT WINAPI
BaseControlWindowImpl_get_Visible(IVideoWindow
*iface
, LONG
*visible
)
362 struct video_window
*window
= impl_from_IVideoWindow(iface
);
364 TRACE("window %p, visible %p.\n", window
, visible
);
369 *visible
= IsWindowVisible(window
->hwnd
) ? OATRUE
: OAFALSE
;
373 HRESULT WINAPI
BaseControlWindowImpl_put_Left(IVideoWindow
*iface
, LONG left
)
375 struct video_window
*window
= impl_from_IVideoWindow(iface
);
378 TRACE("window %p, left %ld.\n", window
, left
);
380 GetWindowRect(window
->hwnd
, &rect
);
381 if (!SetWindowPos(window
->hwnd
, NULL
, left
, rect
.top
, 0, 0,
382 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_NOSIZE
))
388 HRESULT WINAPI
BaseControlWindowImpl_get_Left(IVideoWindow
*iface
, LONG
*left
)
390 struct video_window
*window
= impl_from_IVideoWindow(iface
);
393 TRACE("window %p, left %p.\n", window
, left
);
395 GetWindowRect(window
->hwnd
, &rect
);
400 HRESULT WINAPI
BaseControlWindowImpl_put_Width(IVideoWindow
*iface
, LONG width
)
402 struct video_window
*window
= impl_from_IVideoWindow(iface
);
405 TRACE("window %p, width %ld.\n", window
, width
);
407 GetWindowRect(window
->hwnd
, &rect
);
408 if (!SetWindowPos(window
->hwnd
, NULL
, 0, 0, width
, rect
.bottom
- rect
.top
,
409 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_NOMOVE
))
415 HRESULT WINAPI
BaseControlWindowImpl_get_Width(IVideoWindow
*iface
, LONG
*width
)
417 struct video_window
*window
= impl_from_IVideoWindow(iface
);
420 TRACE("window %p, width %p.\n", window
, width
);
422 GetWindowRect(window
->hwnd
, &rect
);
423 *width
= rect
.right
- rect
.left
;
427 HRESULT WINAPI
BaseControlWindowImpl_put_Top(IVideoWindow
*iface
, LONG top
)
429 struct video_window
*window
= impl_from_IVideoWindow(iface
);
432 TRACE("window %p, top %ld.\n", window
, top
);
434 GetWindowRect(window
->hwnd
, &rect
);
435 if (!SetWindowPos(window
->hwnd
, NULL
, rect
.left
, top
, 0, 0,
436 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_NOSIZE
))
442 HRESULT WINAPI
BaseControlWindowImpl_get_Top(IVideoWindow
*iface
, LONG
*top
)
444 struct video_window
*window
= impl_from_IVideoWindow(iface
);
447 TRACE("window %p, top %p.\n", window
, top
);
449 GetWindowRect(window
->hwnd
, &rect
);
454 HRESULT WINAPI
BaseControlWindowImpl_put_Height(IVideoWindow
*iface
, LONG height
)
456 struct video_window
*window
= impl_from_IVideoWindow(iface
);
459 TRACE("window %p, height %ld.\n", window
, height
);
461 GetWindowRect(window
->hwnd
, &rect
);
462 if (!SetWindowPos(window
->hwnd
, NULL
, 0, 0, rect
.right
- rect
.left
,
463 height
, SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_NOMOVE
))
469 HRESULT WINAPI
BaseControlWindowImpl_get_Height(IVideoWindow
*iface
, LONG
*height
)
471 struct video_window
*window
= impl_from_IVideoWindow(iface
);
474 TRACE("window %p, height %p.\n", window
, height
);
476 GetWindowRect(window
->hwnd
, &rect
);
477 *height
= rect
.bottom
- rect
.top
;
481 HRESULT WINAPI
BaseControlWindowImpl_put_Owner(IVideoWindow
*iface
, OAHWND owner
)
483 struct video_window
*window
= impl_from_IVideoWindow(iface
);
484 HWND hwnd
= window
->hwnd
;
486 TRACE("window %p, owner %#Ix.\n", window
, owner
);
488 if (!window
->pPin
->peer
)
489 return VFW_E_NOT_CONNECTED
;
491 /* Make sure we are marked as WS_CHILD before reparenting ourselves, so that
492 * we do not steal focus. LEGO Island depends on this. */
494 window
->hwndOwner
= (HWND
)owner
;
496 SetWindowLongPtrW(hwnd
, GWL_STYLE
, GetWindowLongPtrW(hwnd
, GWL_STYLE
) | WS_CHILD
);
498 SetWindowLongPtrW(hwnd
, GWL_STYLE
, GetWindowLongPtrW(hwnd
, GWL_STYLE
) & ~WS_CHILD
);
499 SetParent(hwnd
, (HWND
)owner
);
504 HRESULT WINAPI
BaseControlWindowImpl_get_Owner(IVideoWindow
*iface
, OAHWND
*Owner
)
506 struct video_window
*This
= impl_from_IVideoWindow(iface
);
508 TRACE("(%p/%p)->(%p)\n", This
, iface
, Owner
);
510 *(HWND
*)Owner
= This
->hwndOwner
;
515 HRESULT WINAPI
BaseControlWindowImpl_put_MessageDrain(IVideoWindow
*iface
, OAHWND Drain
)
517 struct video_window
*window
= impl_from_IVideoWindow(iface
);
519 TRACE("window %p, drain %#Ix.\n", window
, Drain
);
521 if (!window
->pPin
->peer
)
522 return VFW_E_NOT_CONNECTED
;
524 window
->hwndDrain
= (HWND
)Drain
;
529 HRESULT WINAPI
BaseControlWindowImpl_get_MessageDrain(IVideoWindow
*iface
, OAHWND
*Drain
)
531 struct video_window
*This
= impl_from_IVideoWindow(iface
);
533 TRACE("(%p/%p)->(%p)\n", This
, iface
, Drain
);
535 *Drain
= (OAHWND
)This
->hwndDrain
;
540 HRESULT WINAPI
BaseControlWindowImpl_get_BorderColor(IVideoWindow
*iface
, LONG
*Color
)
542 struct video_window
*This
= impl_from_IVideoWindow(iface
);
544 FIXME("(%p/%p)->(%p): stub !!!\n", This
, iface
, Color
);
549 HRESULT WINAPI
BaseControlWindowImpl_put_BorderColor(IVideoWindow
*iface
, LONG Color
)
551 struct video_window
*This
= impl_from_IVideoWindow(iface
);
553 TRACE("window %p, colour %#lx.\n", This
, Color
);
558 HRESULT WINAPI
BaseControlWindowImpl_get_FullScreenMode(IVideoWindow
*iface
, LONG
*FullScreenMode
)
560 TRACE("(%p)->(%p)\n", iface
, FullScreenMode
);
565 HRESULT WINAPI
BaseControlWindowImpl_put_FullScreenMode(IVideoWindow
*iface
, LONG fullscreen
)
567 struct video_window
*window
= impl_from_IVideoWindow(iface
);
569 TRACE("window %p, fullscreen %ld.\n", window
, fullscreen
);
574 HRESULT WINAPI
BaseControlWindowImpl_SetWindowForeground(IVideoWindow
*iface
, LONG focus
)
576 struct video_window
*window
= impl_from_IVideoWindow(iface
);
577 UINT flags
= SWP_NOMOVE
| SWP_NOSIZE
;
579 TRACE("window %p, focus %ld.\n", window
, focus
);
581 if (focus
!= OAFALSE
&& focus
!= OATRUE
)
584 if (!window
->pPin
->peer
)
585 return VFW_E_NOT_CONNECTED
;
588 flags
|= SWP_NOACTIVATE
;
589 SetWindowPos(window
->hwnd
, HWND_TOP
, 0, 0, 0, 0, flags
);
594 HRESULT WINAPI
BaseControlWindowImpl_SetWindowPosition(IVideoWindow
*iface
,
595 LONG left
, LONG top
, LONG width
, LONG height
)
597 struct video_window
*window
= impl_from_IVideoWindow(iface
);
599 TRACE("window %p, left %ld, top %ld, width %ld, height %ld.\n", window
, left
, top
, width
, height
);
601 if (!window
->pPin
->peer
)
602 return VFW_E_NOT_CONNECTED
;
604 if (!SetWindowPos(window
->hwnd
, NULL
, left
, top
, width
, height
, SWP_NOACTIVATE
| SWP_NOZORDER
))
609 HRESULT WINAPI
BaseControlWindowImpl_GetWindowPosition(IVideoWindow
*iface
,
610 LONG
*left
, LONG
*top
, LONG
*width
, LONG
*height
)
612 struct video_window
*window
= impl_from_IVideoWindow(iface
);
615 TRACE("window %p, left %p, top %p, width %p, height %p.\n", window
, left
, top
, width
, height
);
617 GetWindowRect(window
->hwnd
, &rect
);
620 *width
= rect
.right
- rect
.left
;
621 *height
= rect
.bottom
- rect
.top
;
625 HRESULT WINAPI
BaseControlWindowImpl_NotifyOwnerMessage(IVideoWindow
*iface
,
626 OAHWND hwnd
, LONG message
, LONG_PTR wparam
, LONG_PTR lparam
)
628 struct video_window
*window
= impl_from_IVideoWindow(iface
);
630 TRACE("window %p, hwnd %#Ix, message %#lx, wparam %#Ix, lparam %#Ix.\n",
631 window
, hwnd
, message
, wparam
, lparam
);
633 /* That these messages are forwarded, and no others, is stated by the
634 * DirectX documentation, and supported by manual testing. */
638 case WM_DEVMODECHANGE
:
639 case WM_DISPLAYCHANGE
:
640 case WM_PALETTECHANGED
:
641 case WM_PALETTEISCHANGING
:
642 case WM_QUERYNEWPALETTE
:
643 case WM_SYSCOLORCHANGE
:
644 SendMessageW(window
->hwnd
, message
, wparam
, lparam
);
651 HRESULT WINAPI
BaseControlWindowImpl_GetMinIdealImageSize(IVideoWindow
*iface
, LONG
*width
, LONG
*height
)
653 struct video_window
*window
= impl_from_IVideoWindow(iface
);
656 TRACE("window %p, width %p, height %p.\n", window
, width
, height
);
658 rect
= window
->ops
->get_default_rect(window
);
659 *width
= rect
.right
- rect
.left
;
660 *height
= rect
.bottom
- rect
.top
;
664 HRESULT WINAPI
BaseControlWindowImpl_GetMaxIdealImageSize(IVideoWindow
*iface
, LONG
*width
, LONG
*height
)
666 struct video_window
*window
= impl_from_IVideoWindow(iface
);
669 TRACE("window %p, width %p, height %p.\n", window
, width
, height
);
671 rect
= window
->ops
->get_default_rect(window
);
672 *width
= rect
.right
- rect
.left
;
673 *height
= rect
.bottom
- rect
.top
;
677 HRESULT WINAPI
BaseControlWindowImpl_GetRestorePosition(IVideoWindow
*iface
, LONG
*pLeft
, LONG
*pTop
, LONG
*pWidth
, LONG
*pHeight
)
679 struct video_window
*This
= impl_from_IVideoWindow(iface
);
681 FIXME("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This
, iface
, pLeft
, pTop
, pWidth
, pHeight
);
686 HRESULT WINAPI
BaseControlWindowImpl_HideCursor(IVideoWindow
*iface
, LONG hide
)
688 struct video_window
*window
= impl_from_IVideoWindow(iface
);
690 FIXME("window %p, hide %ld, stub!\n", window
, hide
);
695 HRESULT WINAPI
BaseControlWindowImpl_IsCursorHidden(IVideoWindow
*iface
, LONG
*CursorHidden
)
697 struct video_window
*This
= impl_from_IVideoWindow(iface
);
699 FIXME("(%p/%p)->(%p): stub !!!\n", This
, iface
, CursorHidden
);
704 static inline struct video_window
*impl_from_IBasicVideo(IBasicVideo
*iface
)
706 return CONTAINING_RECORD(iface
, struct video_window
, IBasicVideo_iface
);
709 static HRESULT WINAPI
basic_video_QueryInterface(IBasicVideo
*iface
, REFIID iid
, void **out
)
711 struct video_window
*window
= impl_from_IBasicVideo(iface
);
712 return IUnknown_QueryInterface(window
->pFilter
->outer_unk
, iid
, out
);
715 static ULONG WINAPI
basic_video_AddRef(IBasicVideo
*iface
)
717 struct video_window
*window
= impl_from_IBasicVideo(iface
);
718 return IUnknown_AddRef(window
->pFilter
->outer_unk
);
721 static ULONG WINAPI
basic_video_Release(IBasicVideo
*iface
)
723 struct video_window
*window
= impl_from_IBasicVideo(iface
);
724 return IUnknown_Release(window
->pFilter
->outer_unk
);
727 static HRESULT WINAPI
basic_video_GetTypeInfoCount(IBasicVideo
*iface
, UINT
*count
)
729 TRACE("iface %p, count %p.\n", iface
, count
);
734 static HRESULT WINAPI
basic_video_GetTypeInfo(IBasicVideo
*iface
, UINT index
,
735 LCID lcid
, ITypeInfo
**typeinfo
)
737 TRACE("iface %p, index %u, lcid %#lx, typeinfo %p.\n", iface
, index
, lcid
, typeinfo
);
738 return strmbase_get_typeinfo(IBasicVideo_tid
, typeinfo
);
741 static HRESULT WINAPI
basic_video_GetIDsOfNames(IBasicVideo
*iface
, REFIID iid
,
742 LPOLESTR
*names
, UINT count
, LCID lcid
, DISPID
*ids
)
747 TRACE("iface %p, iid %s, names %p, count %u, lcid %#lx, ids %p.\n",
748 iface
, debugstr_guid(iid
), names
, count
, lcid
, ids
);
750 if (SUCCEEDED(hr
= strmbase_get_typeinfo(IBasicVideo_tid
, &typeinfo
)))
752 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, names
, count
, ids
);
753 ITypeInfo_Release(typeinfo
);
758 static HRESULT WINAPI
basic_video_Invoke(IBasicVideo
*iface
, DISPID id
, REFIID iid
, LCID lcid
,
759 WORD flags
, DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*error_arg
)
764 TRACE("iface %p, id %ld, iid %s, lcid %#lx, flags %#x, params %p, result %p, excepinfo %p, error_arg %p.\n",
765 iface
, id
, debugstr_guid(iid
), lcid
, flags
, params
, result
, excepinfo
, error_arg
);
767 if (SUCCEEDED(hr
= strmbase_get_typeinfo(IBasicVideo_tid
, &typeinfo
)))
769 hr
= ITypeInfo_Invoke(typeinfo
, iface
, id
, flags
, params
, result
, excepinfo
, error_arg
);
770 ITypeInfo_Release(typeinfo
);
775 static const VIDEOINFOHEADER
*get_video_format(struct video_window
*window
)
777 /* Members of VIDEOINFOHEADER up to bmiHeader are identical to those of
778 * VIDEOINFOHEADER2. */
779 return (const VIDEOINFOHEADER
*)window
->pPin
->mt
.pbFormat
;
782 static const BITMAPINFOHEADER
*get_bitmap_header(struct video_window
*window
)
784 const AM_MEDIA_TYPE
*mt
= &window
->pPin
->mt
;
785 if (IsEqualGUID(&mt
->formattype
, &FORMAT_VideoInfo
))
786 return &((VIDEOINFOHEADER
*)mt
->pbFormat
)->bmiHeader
;
788 return &((VIDEOINFOHEADER2
*)mt
->pbFormat
)->bmiHeader
;
791 static HRESULT WINAPI
basic_video_get_AvgTimePerFrame(IBasicVideo
*iface
, REFTIME
*reftime
)
793 struct video_window
*window
= impl_from_IBasicVideo(iface
);
797 if (!window
->pPin
->peer
)
798 return VFW_E_NOT_CONNECTED
;
800 TRACE("window %p, reftime %p.\n", window
, reftime
);
802 *reftime
= (double)get_video_format(window
)->AvgTimePerFrame
/ 1e7
;
806 static HRESULT WINAPI
basic_video_get_BitRate(IBasicVideo
*iface
, LONG
*rate
)
808 struct video_window
*window
= impl_from_IBasicVideo(iface
);
810 TRACE("window %p, rate %p.\n", window
, rate
);
814 if (!window
->pPin
->peer
)
815 return VFW_E_NOT_CONNECTED
;
817 *rate
= get_video_format(window
)->dwBitRate
;
821 static HRESULT WINAPI
basic_video_get_BitErrorRate(IBasicVideo
*iface
, LONG
*rate
)
823 struct video_window
*window
= impl_from_IBasicVideo(iface
);
825 TRACE("window %p, rate %p.\n", window
, rate
);
829 if (!window
->pPin
->peer
)
830 return VFW_E_NOT_CONNECTED
;
832 *rate
= get_video_format(window
)->dwBitErrorRate
;
836 static HRESULT WINAPI
basic_video_get_VideoWidth(IBasicVideo
*iface
, LONG
*width
)
838 struct video_window
*window
= impl_from_IBasicVideo(iface
);
840 TRACE("window %p, width %p.\n", window
, width
);
845 *width
= get_bitmap_header(window
)->biWidth
;
850 static HRESULT WINAPI
basic_video_get_VideoHeight(IBasicVideo
*iface
, LONG
*height
)
852 struct video_window
*window
= impl_from_IBasicVideo(iface
);
854 TRACE("window %p, height %p.\n", window
, height
);
859 *height
= abs(get_bitmap_header(window
)->biHeight
);
864 static HRESULT WINAPI
basic_video_put_SourceLeft(IBasicVideo
*iface
, LONG left
)
866 struct video_window
*window
= impl_from_IBasicVideo(iface
);
868 TRACE("window %p, left %ld.\n", window
, left
);
870 if (left
< 0 || window
->src
.right
+ left
- window
->src
.left
> get_bitmap_header(window
)->biWidth
)
873 OffsetRect(&window
->src
, left
- window
->src
.left
, 0);
877 static HRESULT WINAPI
basic_video_get_SourceLeft(IBasicVideo
*iface
, LONG
*left
)
879 struct video_window
*window
= impl_from_IBasicVideo(iface
);
881 TRACE("window %p, left %p.\n", window
, left
);
886 *left
= window
->src
.left
;
890 static HRESULT WINAPI
basic_video_put_SourceWidth(IBasicVideo
*iface
, LONG width
)
892 struct video_window
*window
= impl_from_IBasicVideo(iface
);
894 TRACE("window %p, width %ld.\n", window
, width
);
896 if (width
<= 0 || window
->src
.left
+ width
> get_bitmap_header(window
)->biWidth
)
899 window
->src
.right
= window
->src
.left
+ width
;
903 static HRESULT WINAPI
basic_video_get_SourceWidth(IBasicVideo
*iface
, LONG
*width
)
905 struct video_window
*window
= impl_from_IBasicVideo(iface
);
907 TRACE("window %p, width %p.\n", window
, width
);
912 *width
= window
->src
.right
- window
->src
.left
;
916 static HRESULT WINAPI
basic_video_put_SourceTop(IBasicVideo
*iface
, LONG top
)
918 struct video_window
*window
= impl_from_IBasicVideo(iface
);
920 TRACE("window %p, top %ld.\n", window
, top
);
922 if (top
< 0 || window
->src
.bottom
+ top
- window
->src
.top
> get_bitmap_header(window
)->biHeight
)
925 OffsetRect(&window
->src
, 0, top
- window
->src
.top
);
929 static HRESULT WINAPI
basic_video_get_SourceTop(IBasicVideo
*iface
, LONG
*top
)
931 struct video_window
*window
= impl_from_IBasicVideo(iface
);
933 TRACE("window %p, top %p.\n", window
, top
);
938 *top
= window
->src
.top
;
942 static HRESULT WINAPI
basic_video_put_SourceHeight(IBasicVideo
*iface
, LONG height
)
944 struct video_window
*window
= impl_from_IBasicVideo(iface
);
946 TRACE("window %p, height %ld.\n", window
, height
);
948 if (height
<= 0 || window
->src
.top
+ height
> get_bitmap_header(window
)->biHeight
)
951 window
->src
.bottom
= window
->src
.top
+ height
;
955 static HRESULT WINAPI
basic_video_get_SourceHeight(IBasicVideo
*iface
, LONG
*height
)
957 struct video_window
*window
= impl_from_IBasicVideo(iface
);
959 TRACE("window %p, height %p\n", window
, height
);
964 *height
= window
->src
.bottom
- window
->src
.top
;
968 static HRESULT WINAPI
basic_video_put_DestinationLeft(IBasicVideo
*iface
, LONG left
)
970 struct video_window
*window
= impl_from_IBasicVideo(iface
);
972 TRACE("window %p, left %ld.\n", window
, left
);
974 window
->default_dst
= FALSE
;
975 OffsetRect(&window
->dst
, left
- window
->dst
.left
, 0);
979 static HRESULT WINAPI
basic_video_get_DestinationLeft(IBasicVideo
*iface
, LONG
*left
)
981 struct video_window
*window
= impl_from_IBasicVideo(iface
);
983 TRACE("window %p, left %p.\n", window
, left
);
988 *left
= window
->dst
.left
;
992 static HRESULT WINAPI
basic_video_put_DestinationWidth(IBasicVideo
*iface
, LONG width
)
994 struct video_window
*window
= impl_from_IBasicVideo(iface
);
996 TRACE("window %p, width %ld.\n", window
, width
);
1001 window
->default_dst
= FALSE
;
1002 window
->dst
.right
= window
->dst
.left
+ width
;
1006 static HRESULT WINAPI
basic_video_get_DestinationWidth(IBasicVideo
*iface
, LONG
*width
)
1008 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1010 TRACE("window %p, width %p.\n", window
, width
);
1015 *width
= window
->dst
.right
- window
->dst
.left
;
1019 static HRESULT WINAPI
basic_video_put_DestinationTop(IBasicVideo
*iface
, LONG top
)
1021 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1023 TRACE("window %p, top %ld.\n", window
, top
);
1025 window
->default_dst
= FALSE
;
1026 OffsetRect(&window
->dst
, 0, top
- window
->dst
.top
);
1030 static HRESULT WINAPI
basic_video_get_DestinationTop(IBasicVideo
*iface
, LONG
*top
)
1032 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1034 TRACE("window %p, top %p.\n", window
, top
);
1039 *top
= window
->dst
.top
;
1043 static HRESULT WINAPI
basic_video_put_DestinationHeight(IBasicVideo
*iface
, LONG height
)
1045 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1047 TRACE("window %p, height %ld.\n", window
, height
);
1050 return E_INVALIDARG
;
1052 window
->default_dst
= FALSE
;
1053 window
->dst
.bottom
= window
->dst
.top
+ height
;
1057 static HRESULT WINAPI
basic_video_get_DestinationHeight(IBasicVideo
*iface
, LONG
*height
)
1059 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1061 TRACE("window %p, height %p.\n", window
, height
);
1066 *height
= window
->dst
.bottom
- window
->dst
.top
;
1070 static HRESULT WINAPI
basic_video_SetSourcePosition(IBasicVideo
*iface
,
1071 LONG left
, LONG top
, LONG width
, LONG height
)
1073 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1074 const BITMAPINFOHEADER
*bitmap_header
= get_bitmap_header(window
);
1076 TRACE("window %p, left %ld, top %ld, width %ld, height %ld.\n", window
, left
, top
, width
, height
);
1078 if (left
< 0 || left
+ width
> bitmap_header
->biWidth
|| width
<= 0)
1079 return E_INVALIDARG
;
1080 if (top
< 0 || top
+ height
> bitmap_header
->biHeight
|| height
<= 0)
1081 return E_INVALIDARG
;
1083 SetRect(&window
->src
, left
, top
, left
+ width
, top
+ height
);
1087 static HRESULT WINAPI
basic_video_GetSourcePosition(IBasicVideo
*iface
,
1088 LONG
*left
, LONG
*top
, LONG
*width
, LONG
*height
)
1090 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1092 TRACE("window %p, left %p, top %p, width %p, height %p.\n", window
, left
, top
, width
, height
);
1094 if (!left
|| !top
|| !width
|| !height
)
1097 *left
= window
->src
.left
;
1098 *top
= window
->src
.top
;
1099 *width
= window
->src
.right
- window
->src
.left
;
1100 *height
= window
->src
.bottom
- window
->src
.top
;
1104 static HRESULT WINAPI
basic_video_SetDefaultSourcePosition(IBasicVideo
*iface
)
1106 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1107 const BITMAPINFOHEADER
*bitmap_header
= get_bitmap_header(window
);
1109 TRACE("window %p.\n", window
);
1111 SetRect(&window
->src
, 0, 0, bitmap_header
->biWidth
, bitmap_header
->biHeight
);
1115 static HRESULT WINAPI
basic_video_SetDestinationPosition(IBasicVideo
*iface
,
1116 LONG left
, LONG top
, LONG width
, LONG height
)
1118 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1120 TRACE("window %p, left %ld, top %ld, width %ld, height %ld.\n", window
, left
, top
, width
, height
);
1122 if (width
<= 0 || height
<= 0)
1123 return E_INVALIDARG
;
1125 window
->default_dst
= FALSE
;
1126 SetRect(&window
->dst
, left
, top
, left
+ width
, top
+ height
);
1130 static HRESULT WINAPI
basic_video_GetDestinationPosition(IBasicVideo
*iface
,
1131 LONG
*left
, LONG
*top
, LONG
*width
, LONG
*height
)
1133 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1135 TRACE("window %p, left %p, top %p, width %p, height %p.\n", window
, left
, top
, width
, height
);
1137 if (!left
|| !top
|| !width
|| !height
)
1140 *left
= window
->dst
.left
;
1141 *top
= window
->dst
.top
;
1142 *width
= window
->dst
.right
- window
->dst
.left
;
1143 *height
= window
->dst
.bottom
- window
->dst
.top
;
1147 static HRESULT WINAPI
basic_video_SetDefaultDestinationPosition(IBasicVideo
*iface
)
1149 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1151 TRACE("window %p.\n", window
);
1153 window
->default_dst
= TRUE
;
1154 GetClientRect(window
->hwnd
, &window
->dst
);
1158 static HRESULT WINAPI
basic_video_GetVideoSize(IBasicVideo
*iface
, LONG
*width
, LONG
*height
)
1160 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1161 const BITMAPINFOHEADER
*bitmap_header
;
1163 TRACE("window %p, width %p, height %p.\n", window
, width
, height
);
1165 if (!width
|| !height
)
1167 if (!window
->pPin
->peer
)
1168 return VFW_E_NOT_CONNECTED
;
1170 bitmap_header
= get_bitmap_header(window
);
1171 *width
= bitmap_header
->biWidth
;
1172 *height
= bitmap_header
->biHeight
;
1176 static HRESULT WINAPI
basic_video_GetVideoPaletteEntries(IBasicVideo
*iface
,
1177 LONG start
, LONG count
, LONG
*ret_count
, LONG
*palette
)
1179 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1181 FIXME("window %p, start %ld, count %ld, ret_count %p, palette %p, stub!\n",
1182 window
, start
, count
, ret_count
, palette
);
1184 if (!ret_count
|| !palette
)
1188 return VFW_E_NO_PALETTE_AVAILABLE
;
1191 static HRESULT WINAPI
basic_video_GetCurrentImage(IBasicVideo
*iface
, LONG
*size
, LONG
*image
)
1193 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1195 TRACE("window %p, size %p, image %p.\n", window
, size
, image
);
1197 if (!size
|| !image
)
1200 return window
->ops
->get_current_image(window
, size
, image
);
1203 static HRESULT WINAPI
basic_video_IsUsingDefaultSource(IBasicVideo
*iface
)
1205 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1206 const BITMAPINFOHEADER
*bitmap_header
= get_bitmap_header(window
);
1208 TRACE("window %p.\n", window
);
1210 if (!window
->src
.left
&& !window
->src
.top
1211 && window
->src
.right
== bitmap_header
->biWidth
1212 && window
->src
.bottom
== bitmap_header
->biHeight
)
1217 static HRESULT WINAPI
basic_video_IsUsingDefaultDestination(IBasicVideo
*iface
)
1219 struct video_window
*window
= impl_from_IBasicVideo(iface
);
1221 TRACE("window %p.\n", window
);
1223 return window
->default_dst
? S_OK
: S_FALSE
;
1226 static const IBasicVideoVtbl basic_video_vtbl
=
1228 basic_video_QueryInterface
,
1230 basic_video_Release
,
1231 basic_video_GetTypeInfoCount
,
1232 basic_video_GetTypeInfo
,
1233 basic_video_GetIDsOfNames
,
1235 basic_video_get_AvgTimePerFrame
,
1236 basic_video_get_BitRate
,
1237 basic_video_get_BitErrorRate
,
1238 basic_video_get_VideoWidth
,
1239 basic_video_get_VideoHeight
,
1240 basic_video_put_SourceLeft
,
1241 basic_video_get_SourceLeft
,
1242 basic_video_put_SourceWidth
,
1243 basic_video_get_SourceWidth
,
1244 basic_video_put_SourceTop
,
1245 basic_video_get_SourceTop
,
1246 basic_video_put_SourceHeight
,
1247 basic_video_get_SourceHeight
,
1248 basic_video_put_DestinationLeft
,
1249 basic_video_get_DestinationLeft
,
1250 basic_video_put_DestinationWidth
,
1251 basic_video_get_DestinationWidth
,
1252 basic_video_put_DestinationTop
,
1253 basic_video_get_DestinationTop
,
1254 basic_video_put_DestinationHeight
,
1255 basic_video_get_DestinationHeight
,
1256 basic_video_SetSourcePosition
,
1257 basic_video_GetSourcePosition
,
1258 basic_video_SetDefaultSourcePosition
,
1259 basic_video_SetDestinationPosition
,
1260 basic_video_GetDestinationPosition
,
1261 basic_video_SetDefaultDestinationPosition
,
1262 basic_video_GetVideoSize
,
1263 basic_video_GetVideoPaletteEntries
,
1264 basic_video_GetCurrentImage
,
1265 basic_video_IsUsingDefaultSource
,
1266 basic_video_IsUsingDefaultDestination
1269 void video_window_unregister_class(void)
1271 if (!UnregisterClassW(class_name
, NULL
) && GetLastError() != ERROR_CLASS_DOES_NOT_EXIST
)
1272 ERR("Failed to unregister class, error %lu.\n", GetLastError());
1275 void video_window_init(struct video_window
*window
, const IVideoWindowVtbl
*vtbl
,
1276 struct strmbase_filter
*owner
, struct strmbase_pin
*pin
, const struct video_window_ops
*ops
)
1278 memset(window
, 0, sizeof(*window
));
1280 window
->IVideoWindow_iface
.lpVtbl
= vtbl
;
1281 window
->IBasicVideo_iface
.lpVtbl
= &basic_video_vtbl
;
1282 window
->default_dst
= TRUE
;
1283 window
->AutoShow
= OATRUE
;
1284 window
->pFilter
= owner
;
1288 void video_window_cleanup(struct video_window
*window
)
1292 /* Media Player Classic deadlocks if WM_PARENTNOTIFY is sent, so clear
1293 * the child style first. Just like Windows, we don't actually unparent
1294 * the window, to prevent extra focus events from being generated since
1295 * it would become top-level for a brief period before being destroyed. */
1296 SetWindowLongW(window
->hwnd
, GWL_STYLE
, GetWindowLongW(window
->hwnd
, GWL_STYLE
) & ~WS_CHILD
);
1298 SendMessageW(window
->hwnd
, WM_QUARTZ_DESTROY
, 0, 0);
1299 window
->hwnd
= NULL
;