]> git.sesse.net Git - vlc/blob - projects/activex/oleobject.cpp
configure: Use the full path to luac to support our contrib system.
[vlc] / projects / activex / oleobject.cpp
1 /*****************************************************************************
2  * oleobject.cpp: ActiveX control for VLC
3  *****************************************************************************
4  * Copyright (C) 2005 the VideoLAN team
5  *
6  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22
23 #include "plugin.h"
24 #include "oleobject.h"
25
26 #include "utils.h"
27
28 #include <docobj.h>
29
30 using namespace std;
31
32 VLCOleObject::VLCOleObject(VLCPlugin *p_instance) :
33 _p_clientsite(NULL), _p_instance(p_instance)
34 {
35     CreateOleAdviseHolder(&_p_advise_holder);
36 };
37
38 VLCOleObject::~VLCOleObject()
39 {
40     SetClientSite(NULL);
41     Close(OLECLOSE_NOSAVE);
42     _p_advise_holder->Release();
43 };
44
45 STDMETHODIMP VLCOleObject::Advise(IAdviseSink *pAdvSink, DWORD *dwConnection)
46 {
47     return _p_advise_holder->Advise(pAdvSink, dwConnection);
48 };
49
50 STDMETHODIMP VLCOleObject::Close(DWORD dwSaveOption)
51 {
52     if( _p_instance->isRunning() )
53     {
54         _p_advise_holder->SendOnClose();
55         return _p_instance->onClose(dwSaveOption);
56     }
57     return S_OK;
58 };
59
60 STDMETHODIMP VLCOleObject::DoVerb(LONG iVerb, LPMSG lpMsg, LPOLECLIENTSITE pActiveSite,
61                                     LONG lIndex, HWND hwndParent, LPCRECT lprcPosRect)
62 {
63     switch( iVerb )
64     {
65         case OLEIVERB_PRIMARY:
66         case OLEIVERB_SHOW:
67         case OLEIVERB_OPEN:
68             // force control to be visible when activating in place
69             _p_instance->setVisible(TRUE);
70             return doInPlaceActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect, TRUE);
71
72         case OLEIVERB_INPLACEACTIVATE:
73             return doInPlaceActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect, FALSE);
74
75         case OLEIVERB_HIDE:
76             _p_instance->setVisible(FALSE);
77             return S_OK;
78
79         case OLEIVERB_UIACTIVATE:
80             // UI activate only if visible
81             if( _p_instance->isVisible() )
82                 return doInPlaceActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect, TRUE);
83             return OLEOBJ_S_CANNOT_DOVERB_NOW;
84
85         case OLEIVERB_DISCARDUNDOSTATE:
86             return S_OK;
87
88         default:
89             if( iVerb > 0 ) {
90                 _p_instance->setVisible(TRUE);
91                 doInPlaceActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect, TRUE);
92                 return OLEOBJ_S_INVALIDVERB;
93             }
94             return E_NOTIMPL;
95     }
96 };
97
98 HRESULT VLCOleObject::doInPlaceActivate(LPMSG lpMsg, LPOLECLIENTSITE pActiveSite, HWND hwndParent, LPCRECT lprcPosRect, BOOL uiActivate)
99 {
100     RECT posRect;
101     RECT clipRect;
102     LPCRECT lprcClipRect = lprcPosRect;
103
104     if( pActiveSite )
105     {
106         LPOLEINPLACESITE p_inPlaceSite;
107         IOleInPlaceSiteEx *p_inPlaceSiteEx;
108         LPOLEINPLACEFRAME p_inPlaceFrame;
109         LPOLEINPLACEUIWINDOW p_inPlaceUIWindow;
110
111         if( SUCCEEDED(pActiveSite->QueryInterface(IID_IOleInPlaceSiteEx, reinterpret_cast<void**>(&p_inPlaceSiteEx))) )
112         {
113             p_inPlaceSite = p_inPlaceSiteEx;
114             p_inPlaceSite->AddRef();
115         }
116         else if FAILED(pActiveSite->QueryInterface(IID_IOleInPlaceSite, reinterpret_cast<void**>(&p_inPlaceSite)) )
117         {
118             p_inPlaceSite = p_inPlaceSiteEx = NULL;
119         }
120
121         if( p_inPlaceSite )
122         {
123             OLEINPLACEFRAMEINFO oleFrameInfo;
124
125             oleFrameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
126             if( SUCCEEDED(p_inPlaceSite->GetWindowContext(&p_inPlaceFrame, &p_inPlaceUIWindow, &posRect, &clipRect, &oleFrameInfo)) )
127             {
128                 lprcPosRect = &posRect;
129                 lprcClipRect = &clipRect;
130             }
131
132             if( (NULL == hwndParent) && FAILED(p_inPlaceSite->GetWindow(&hwndParent)) )
133             {
134                 p_inPlaceSite->Release();
135                 if( p_inPlaceSiteEx )
136                     p_inPlaceSiteEx->Release();
137                 if( p_inPlaceFrame )
138                     p_inPlaceFrame->Release();
139                 if( p_inPlaceUIWindow )
140                     p_inPlaceUIWindow->Release();
141
142                 return OLEOBJ_S_INVALIDHWND;
143             }
144         }
145         else if( NULL == hwndParent )
146         {
147             return OLEOBJ_S_INVALIDHWND;
148         }
149         else if( NULL == lprcPosRect )
150         {
151             SetRect(&posRect, 0, 0, 0, 0);
152             lprcPosRect = &posRect;
153             lprcClipRect = &posRect;
154         }
155
156         // check if not already activated
157         if( ! _p_instance->isInPlaceActive() )
158         {
159             if( ((NULL == p_inPlaceSite) || (S_OK == p_inPlaceSite->CanInPlaceActivate()))
160              && SUCCEEDED(_p_instance->onActivateInPlace(lpMsg, hwndParent, lprcPosRect, lprcClipRect)) )
161             {
162                 if( p_inPlaceSiteEx )
163                 {
164                     BOOL needsRedraw;
165                     p_inPlaceSiteEx->OnInPlaceActivateEx(&needsRedraw, 0);
166                 }
167                 else if( p_inPlaceSite )
168                     p_inPlaceSite->OnInPlaceActivate();
169             }
170             else
171             {
172                 if( p_inPlaceSite )
173                 {
174                     p_inPlaceSite->Release();
175                     if( p_inPlaceSiteEx )
176                         p_inPlaceSiteEx->Release();
177                     if( p_inPlaceFrame )
178                         p_inPlaceFrame->Release();
179                     if( p_inPlaceUIWindow )
180                         p_inPlaceUIWindow->Release();
181                 }
182                 return OLEOBJ_S_CANNOT_DOVERB_NOW;
183             }
184         }
185
186         if( p_inPlaceSite )
187             p_inPlaceSite->OnPosRectChange(lprcPosRect);
188
189         if( uiActivate )
190         {
191             if( (NULL == p_inPlaceSiteEx) || (S_OK == p_inPlaceSiteEx->RequestUIActivate()) )
192             {
193                 if( p_inPlaceSite)
194                 {
195                     p_inPlaceSite->OnUIActivate();
196
197                     LPOLEINPLACEACTIVEOBJECT p_inPlaceActiveObject;
198                     if( SUCCEEDED(QueryInterface(IID_IOleInPlaceActiveObject, reinterpret_cast<void**>(&p_inPlaceActiveObject))) )
199                     {
200                         if( p_inPlaceFrame )
201                             p_inPlaceFrame->SetActiveObject(p_inPlaceActiveObject, NULL);
202                         if( p_inPlaceUIWindow )
203                             p_inPlaceUIWindow->SetActiveObject(p_inPlaceActiveObject, NULL);
204                         p_inPlaceActiveObject->Release();
205                     }
206                     if( p_inPlaceFrame )
207                         p_inPlaceFrame->RequestBorderSpace(NULL);
208
209                     pActiveSite->ShowObject();
210                 }
211                 _p_instance->setFocus(TRUE);
212             }
213         }
214
215         if( p_inPlaceSite )
216         {
217             p_inPlaceSite->Release();
218             if( p_inPlaceSiteEx )
219                 p_inPlaceSiteEx->Release();
220             if( p_inPlaceFrame )
221                 p_inPlaceFrame->Release();
222             if( p_inPlaceUIWindow )
223                 p_inPlaceUIWindow->Release();
224         }
225         return S_OK;
226     }
227     return OLEOBJ_S_CANNOT_DOVERB_NOW;
228 };
229
230 STDMETHODIMP VLCOleObject::EnumAdvise(IEnumSTATDATA **ppEnumAdvise)
231 {
232     return _p_advise_holder->EnumAdvise(ppEnumAdvise);
233 };
234
235 STDMETHODIMP VLCOleObject::EnumVerbs(IEnumOleVerb **ppEnumOleVerb)
236 {
237     return OleRegEnumVerbs(_p_instance->getClassID(),
238         ppEnumOleVerb);
239 };
240
241 STDMETHODIMP VLCOleObject::GetClientSite(LPOLECLIENTSITE *ppClientSite)
242 {
243     if( NULL == ppClientSite )
244         return E_POINTER;
245
246     if( NULL != _p_clientsite )
247         _p_clientsite->AddRef();
248
249     *ppClientSite = _p_clientsite;
250     return S_OK;
251 };
252
253 STDMETHODIMP VLCOleObject::GetClipboardData(DWORD dwReserved, LPDATAOBJECT *ppDataObject)
254 {
255     return _p_instance->pUnkOuter->QueryInterface(IID_IDataObject, (void **)ppDataObject);
256 };
257
258 STDMETHODIMP VLCOleObject::GetExtent(DWORD dwDrawAspect, SIZEL *pSizel)
259 {
260     if( NULL == pSizel )
261         return E_POINTER;
262
263     if( dwDrawAspect & DVASPECT_CONTENT )
264     {
265         *pSizel = _p_instance->getExtent();
266         return S_OK;
267     }
268     pSizel->cx= 0L;
269     pSizel->cy= 0L;
270     return E_NOTIMPL;
271 };
272
273 STDMETHODIMP VLCOleObject::GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus)
274 {
275     if( NULL == pdwStatus )
276         return E_POINTER;
277
278     switch( dwAspect )
279     {
280         case DVASPECT_CONTENT:
281             *pdwStatus = OLEMISC_RECOMPOSEONRESIZE
282                 | OLEMISC_CANTLINKINSIDE
283                 | OLEMISC_INSIDEOUT
284                 | OLEMISC_ACTIVATEWHENVISIBLE
285                 | OLEMISC_SETCLIENTSITEFIRST;
286             break;
287         default:
288             *pdwStatus = 0;
289     }
290
291     return S_OK;
292 };
293
294 STDMETHODIMP VLCOleObject::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER *ppMoniker)
295 {
296     if( NULL != _p_clientsite )
297         return _p_clientsite->GetMoniker(dwAssign,dwWhichMoniker, ppMoniker);
298
299     return E_UNEXPECTED;
300 };
301
302 STDMETHODIMP VLCOleObject::GetUserClassID(LPCLSID pClsid)
303 {
304     if( NULL == pClsid )
305         return E_POINTER;
306  
307     *pClsid = _p_instance->getClassID();
308     return S_OK;
309 };
310
311 STDMETHODIMP VLCOleObject::GetUserType(DWORD dwFormOfType, LPOLESTR *pszUserType)
312 {
313     return OleRegGetUserType(_p_instance->getClassID(),
314         dwFormOfType, pszUserType);
315 };
316
317 STDMETHODIMP VLCOleObject::InitFromData(LPDATAOBJECT pDataObject, BOOL fCreation, DWORD dwReserved)
318 {
319     return E_NOTIMPL;
320 };
321
322 STDMETHODIMP VLCOleObject::IsUpToDate(void)
323 {
324     return S_OK;
325 };
326
327 STDMETHODIMP VLCOleObject::SetClientSite(LPOLECLIENTSITE pClientSite)
328 {
329     if( NULL != _p_clientsite )
330         _p_clientsite->Release();
331
332     _p_clientsite = pClientSite;
333
334     if( NULL != pClientSite )
335     {
336         pClientSite->AddRef();
337         _p_instance->onAmbientChanged(pClientSite, DISPID_UNKNOWN);
338     }
339     return S_OK;
340 };
341
342 STDMETHODIMP VLCOleObject::SetColorScheme(LOGPALETTE *pLogpal)
343 {
344     return E_NOTIMPL;
345 };
346
347 STDMETHODIMP VLCOleObject::SetExtent(DWORD dwDrawAspect, SIZEL *pSizel)
348 {
349     if( NULL == pSizel )
350         return E_POINTER;
351
352     if( dwDrawAspect & DVASPECT_CONTENT )
353     {
354         _p_instance->setExtent(*pSizel);
355
356         if( _p_instance->isInPlaceActive() )
357         {
358             LPOLEINPLACESITE p_inPlaceSite;
359
360             if( SUCCEEDED(_p_clientsite->QueryInterface(IID_IOleInPlaceSite, (void**)&p_inPlaceSite)) )
361             {
362                 HWND hwnd;
363
364                 if( SUCCEEDED(p_inPlaceSite->GetWindow(&hwnd)) )
365                 {
366                     // use HIMETRIC to pixel transform
367                     RECT posRect = _p_instance->getPosRect();
368                     HDC hDC = GetDC(hwnd);
369                     posRect.right = (pSizel->cx*GetDeviceCaps(hDC, LOGPIXELSX)/2540L)+posRect.left;
370                     posRect.bottom = (pSizel->cy*GetDeviceCaps(hDC, LOGPIXELSY)/2540L)+posRect.top;
371                     DeleteDC(hDC);
372                     p_inPlaceSite->OnPosRectChange(&posRect);
373                 }
374                 p_inPlaceSite->Release();
375             }
376         }
377         return S_OK;
378     }
379     return E_NOTIMPL;
380 };
381
382 STDMETHODIMP VLCOleObject::SetHostNames(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
383 {
384     return S_OK;
385 };
386
387 STDMETHODIMP VLCOleObject::SetMoniker(DWORD dwWhichMoniker, LPMONIKER pMoniker)
388 {
389     return _p_advise_holder->SendOnRename(pMoniker);
390 };
391
392 STDMETHODIMP VLCOleObject::Unadvise(DWORD dwConnection)
393 {
394     return _p_advise_holder->Unadvise(dwConnection);
395 };
396
397 STDMETHODIMP VLCOleObject::Update(void)
398 {
399     return S_OK;
400 };
401