cmd: Fix a couple of issues with redirections.
[wine.git] / dlls / quartz / window.c
blob02c6a826bb22e549720ea6d3e73121ae3b1f8a66
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 (!window->pPin->peer)
198 return VFW_E_NOT_CONNECTED;
200 if (!SetWindowTextW(window->hwnd, caption))
201 return E_FAIL;
203 return S_OK;
206 HRESULT WINAPI BaseControlWindowImpl_get_Caption(IVideoWindow *iface, BSTR *caption)
208 struct video_window *window = impl_from_IVideoWindow(iface);
209 WCHAR *str;
210 int len;
212 TRACE("window %p, caption %p.\n", window, caption);
214 *caption = NULL;
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);
222 heap_free(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))
233 return E_INVALIDARG;
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);
240 return S_OK;
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);
250 return S_OK;
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))
260 return E_FAIL;
261 return S_OK;
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);
271 return S_OK;
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;
285 return S_OK;
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;
296 return S_OK;
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);
306 return S_OK;
309 HRESULT WINAPI BaseControlWindowImpl_get_WindowState(IVideoWindow *iface, LONG *state)
311 struct video_window *window = impl_from_IVideoWindow(iface);
312 DWORD style;
314 TRACE("window %p, state %p.\n", window, state);
316 style = GetWindowLongPtrW(window->hwnd, GWL_STYLE);
317 if (!(style & WS_VISIBLE))
318 *state = SW_HIDE;
319 else if (style & WS_MINIMIZE)
320 *state = SW_MINIMIZE;
321 else if (style & WS_MAXIMIZE)
322 *state = SW_MAXIMIZE;
323 else
324 *state = SW_SHOW;
326 return S_OK;
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);
335 return S_OK;
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);
344 return S_OK;
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);
357 return S_OK;
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);
366 if (!visible)
367 return E_POINTER;
369 *visible = IsWindowVisible(window->hwnd) ? OATRUE : OAFALSE;
370 return S_OK;
373 HRESULT WINAPI BaseControlWindowImpl_put_Left(IVideoWindow *iface, LONG left)
375 struct video_window *window = impl_from_IVideoWindow(iface);
376 RECT rect;
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))
383 return E_FAIL;
385 return S_OK;
388 HRESULT WINAPI BaseControlWindowImpl_get_Left(IVideoWindow *iface, LONG *left)
390 struct video_window *window = impl_from_IVideoWindow(iface);
391 RECT rect;
393 TRACE("window %p, left %p.\n", window, left);
395 GetWindowRect(window->hwnd, &rect);
396 *left = rect.left;
397 return S_OK;
400 HRESULT WINAPI BaseControlWindowImpl_put_Width(IVideoWindow *iface, LONG width)
402 struct video_window *window = impl_from_IVideoWindow(iface);
403 RECT rect;
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))
410 return E_FAIL;
412 return S_OK;
415 HRESULT WINAPI BaseControlWindowImpl_get_Width(IVideoWindow *iface, LONG *width)
417 struct video_window *window = impl_from_IVideoWindow(iface);
418 RECT rect;
420 TRACE("window %p, width %p.\n", window, width);
422 GetWindowRect(window->hwnd, &rect);
423 *width = rect.right - rect.left;
424 return S_OK;
427 HRESULT WINAPI BaseControlWindowImpl_put_Top(IVideoWindow *iface, LONG top)
429 struct video_window *window = impl_from_IVideoWindow(iface);
430 RECT rect;
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))
437 return E_FAIL;
439 return S_OK;
442 HRESULT WINAPI BaseControlWindowImpl_get_Top(IVideoWindow *iface, LONG *top)
444 struct video_window *window = impl_from_IVideoWindow(iface);
445 RECT rect;
447 TRACE("window %p, top %p.\n", window, top);
449 GetWindowRect(window->hwnd, &rect);
450 *top = rect.top;
451 return S_OK;
454 HRESULT WINAPI BaseControlWindowImpl_put_Height(IVideoWindow *iface, LONG height)
456 struct video_window *window = impl_from_IVideoWindow(iface);
457 RECT rect;
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))
464 return E_FAIL;
466 return S_OK;
469 HRESULT WINAPI BaseControlWindowImpl_get_Height(IVideoWindow *iface, LONG *height)
471 struct video_window *window = impl_from_IVideoWindow(iface);
472 RECT rect;
474 TRACE("window %p, height %p.\n", window, height);
476 GetWindowRect(window->hwnd, &rect);
477 *height = rect.bottom - rect.top;
478 return S_OK;
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;
495 if (owner)
496 SetWindowLongPtrW(hwnd, GWL_STYLE, GetWindowLongPtrW(hwnd, GWL_STYLE) | WS_CHILD);
497 else
498 SetWindowLongPtrW(hwnd, GWL_STYLE, GetWindowLongPtrW(hwnd, GWL_STYLE) & ~WS_CHILD);
499 SetParent(hwnd, (HWND)owner);
501 return S_OK;
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;
512 return S_OK;
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;
526 return S_OK;
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;
537 return S_OK;
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);
546 return S_OK;
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);
555 return S_OK;
558 HRESULT WINAPI BaseControlWindowImpl_get_FullScreenMode(IVideoWindow *iface, LONG *FullScreenMode)
560 TRACE("(%p)->(%p)\n", iface, FullScreenMode);
562 return E_NOTIMPL;
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);
571 return E_NOTIMPL;
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)
582 return E_INVALIDARG;
584 if (!window->pPin->peer)
585 return VFW_E_NOT_CONNECTED;
587 if (!focus)
588 flags |= SWP_NOACTIVATE;
589 SetWindowPos(window->hwnd, HWND_TOP, 0, 0, 0, 0, flags);
591 return S_OK;
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))
605 return E_FAIL;
606 return S_OK;
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);
613 RECT rect;
615 TRACE("window %p, left %p, top %p, width %p, height %p.\n", window, left, top, width, height);
617 GetWindowRect(window->hwnd, &rect);
618 *left = rect.left;
619 *top = rect.top;
620 *width = rect.right - rect.left;
621 *height = rect.bottom - rect.top;
622 return S_OK;
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. */
635 switch (message)
637 case WM_ACTIVATEAPP:
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);
645 break;
648 return S_OK;
651 HRESULT WINAPI BaseControlWindowImpl_GetMinIdealImageSize(IVideoWindow *iface, LONG *width, LONG *height)
653 struct video_window *window = impl_from_IVideoWindow(iface);
654 RECT rect;
656 TRACE("window %p, width %p, height %p.\n", window, width, height);
658 window->ops->get_default_rect(window, &rect);
659 *width = rect.right - rect.left;
660 *height = rect.bottom - rect.top;
661 return S_OK;
664 HRESULT WINAPI BaseControlWindowImpl_GetMaxIdealImageSize(IVideoWindow *iface, LONG *width, LONG *height)
666 struct video_window *window = impl_from_IVideoWindow(iface);
667 RECT rect;
669 TRACE("window %p, width %p, height %p.\n", window, width, height);
671 window->ops->get_default_rect(window, &rect);
672 *width = rect.right - rect.left;
673 *height = rect.bottom - rect.top;
674 return S_OK;
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);
683 return S_OK;
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);
692 return S_OK;
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);
701 return S_OK;
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);
730 *count = 1;
731 return S_OK;
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)
744 ITypeInfo *typeinfo;
745 HRESULT hr;
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);
755 return hr;
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)
761 ITypeInfo *typeinfo;
762 HRESULT hr;
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);
772 return hr;
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;
787 else
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);
795 if (!reftime)
796 return E_POINTER;
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;
803 return S_OK;
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);
812 if (!rate)
813 return E_POINTER;
814 if (!window->pPin->peer)
815 return VFW_E_NOT_CONNECTED;
817 *rate = get_video_format(window)->dwBitRate;
818 return S_OK;
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);
827 if (!rate)
828 return E_POINTER;
829 if (!window->pPin->peer)
830 return VFW_E_NOT_CONNECTED;
832 *rate = get_video_format(window)->dwBitErrorRate;
833 return S_OK;
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);
842 if (!width)
843 return E_POINTER;
845 *width = get_bitmap_header(window)->biWidth;
847 return S_OK;
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);
856 if (!height)
857 return E_POINTER;
859 *height = abs(get_bitmap_header(window)->biHeight);
861 return S_OK;
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)
871 return E_INVALIDARG;
873 OffsetRect(&window->src, left - window->src.left, 0);
874 return S_OK;
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);
883 if (!left)
884 return E_POINTER;
886 *left = window->src.left;
887 return S_OK;
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)
897 return E_INVALIDARG;
899 window->src.right = window->src.left + width;
900 return S_OK;
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);
909 if (!width)
910 return E_POINTER;
912 *width = window->src.right - window->src.left;
913 return S_OK;
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)
923 return E_INVALIDARG;
925 OffsetRect(&window->src, 0, top - window->src.top);
926 return S_OK;
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);
935 if (!top)
936 return E_POINTER;
938 *top = window->src.top;
939 return S_OK;
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)
949 return E_INVALIDARG;
951 window->src.bottom = window->src.top + height;
952 return S_OK;
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);
961 if (!height)
962 return E_POINTER;
964 *height = window->src.bottom - window->src.top;
965 return S_OK;
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);
976 return S_OK;
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);
985 if (!left)
986 return E_POINTER;
988 *left = window->dst.left;
989 return S_OK;
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);
998 if (width <= 0)
999 return E_INVALIDARG;
1001 window->default_dst = FALSE;
1002 window->dst.right = window->dst.left + width;
1003 return S_OK;
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);
1012 if (!width)
1013 return E_POINTER;
1015 *width = window->dst.right - window->dst.left;
1016 return S_OK;
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);
1027 return S_OK;
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);
1036 if (!top)
1037 return E_POINTER;
1039 *top = window->dst.top;
1040 return S_OK;
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);
1049 if (height <= 0)
1050 return E_INVALIDARG;
1052 window->default_dst = FALSE;
1053 window->dst.bottom = window->dst.top + height;
1054 return S_OK;
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);
1063 if (!height)
1064 return E_POINTER;
1066 *height = window->dst.bottom - window->dst.top;
1067 return S_OK;
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);
1084 return S_OK;
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)
1095 return E_POINTER;
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;
1101 return S_OK;
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);
1112 return S_OK;
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);
1127 return S_OK;
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)
1138 return E_POINTER;
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;
1144 return S_OK;
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);
1155 return S_OK;
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)
1166 return E_POINTER;
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;
1173 return S_OK;
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)
1185 return E_POINTER;
1187 *ret_count = 0;
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)
1198 return E_POINTER;
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)
1213 return S_OK;
1214 return S_FALSE;
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,
1229 basic_video_AddRef,
1230 basic_video_Release,
1231 basic_video_GetTypeInfoCount,
1232 basic_video_GetTypeInfo,
1233 basic_video_GetIDsOfNames,
1234 basic_video_Invoke,
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));
1279 window->ops = ops;
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;
1285 window->pPin = pin;
1288 void video_window_cleanup(struct video_window *window)
1290 if (window->hwnd)
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;