]> git.sesse.net Git - vlc/blob - modules/gui/skins2/win32/win32_factory.cpp
* modules/gui/skins2/*: a few portability fixes.
[vlc] / modules / gui / skins2 / win32 / win32_factory.cpp
1 /*****************************************************************************
2  * win32_factory.cpp
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id$
6  *
7  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
8  *          Olivier Teulière <ipkiss@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 #ifdef WIN32_SKINS
26
27 #include "win32_factory.hpp"
28 #include "win32_graphics.hpp"
29 #include "win32_timer.hpp"
30 #include "win32_window.hpp"
31 #include "win32_tooltip.hpp"
32 #include "win32_loop.hpp"
33 #include "../src/theme.hpp"
34
35
36 LRESULT CALLBACK Win32Proc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
37 {
38     // Get pointer to thread info: should only work with the parent window
39     intf_thread_t *p_intf = (intf_thread_t *)GetWindowLongPtr( hwnd,
40         GWLP_USERDATA );
41
42     // If doesn't exist, treat windows message normally
43     if( p_intf == NULL || p_intf->p_sys->p_osFactory == NULL )
44     {
45         return DefWindowProc( hwnd, uMsg, wParam, lParam );
46     }
47
48     // Here we know we are getting a message for the parent window, since it is
49     // the only one to store p_intf...
50     // Yes, it is a kludge :)
51
52 //Win32Factory *pFactory = (Win32Factory*)Win32Factory::instance( p_intf );
53 //msg_Err( p_intf, "Parent window %p %p %u %i\n", pFactory->m_hParentWindow, hwnd, uMsg, wParam );
54     // If Window is parent window
55     // XXX: this test isn't needed, see the kludge above...
56 //    if( hwnd == pFactory->m_hParentWindow )
57     {
58         if( uMsg == WM_SYSCOMMAND )
59         {
60             // If closing parent window
61             if( wParam == SC_CLOSE )
62             {
63                 Win32Loop *pLoop = (Win32Loop*)Win32Loop::instance( p_intf );
64                 pLoop->exit();
65                 return 0;
66             }
67             else
68             {
69                 msg_Err( p_intf, "WM_SYSCOMMAND %i", wParam );
70             }
71 //            if( (Event *)wParam != NULL )
72 //                ( (Event *)wParam )->SendEvent();
73 //            return 0;
74         }
75     }
76
77     // If hwnd does not match any window or message not processed
78     return DefWindowProc( hwnd, uMsg, wParam, lParam );
79 }
80
81
82 Win32Factory::Win32Factory( intf_thread_t *pIntf ):
83     OSFactory( pIntf ), TransparentBlt( NULL ), AlphaBlend( NULL ),
84     SetLayeredWindowAttributes( NULL ), m_hParentWindow( NULL ),
85     m_dirSep( "\\" )
86 {
87     // see init()
88 }
89
90
91 bool Win32Factory::init()
92 {
93     // Get instance handle
94     m_hInst = GetModuleHandle( NULL );
95     if( m_hInst == NULL )
96     {
97         msg_Err( getIntf(), "Cannot get module handle" );
98     }
99
100     // Create window class
101     WNDCLASS skinWindowClass;
102     skinWindowClass.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
103     skinWindowClass.lpfnWndProc = (WNDPROC) Win32Proc;
104     skinWindowClass.lpszClassName = _T("SkinWindowClass");
105     skinWindowClass.lpszMenuName = NULL;
106     skinWindowClass.cbClsExtra = 0;
107     skinWindowClass.cbWndExtra = 0;
108     skinWindowClass.hbrBackground = NULL;
109     skinWindowClass.hCursor = LoadCursor( NULL , IDC_ARROW );
110     skinWindowClass.hIcon = LoadIcon( m_hInst, _T("VLC_ICON") );
111     skinWindowClass.hInstance = m_hInst;
112
113     // Register class and check it
114     if( !RegisterClass( &skinWindowClass ) )
115     {
116         WNDCLASS wndclass;
117
118         // Check why it failed. If it's because the class already exists
119         // then fine, otherwise return with an error.
120         if( !GetClassInfo( m_hInst, _T("SkinWindowClass"), &wndclass ) )
121         {
122             msg_Err( getIntf(), "Cannot register window class" );
123             return false;
124         }
125     }
126
127     // Create Window
128     m_hParentWindow = CreateWindowEx( WS_EX_APPWINDOW, _T("SkinWindowClass"),
129         _T("VLC media player"), WS_SYSMENU|WS_POPUP,
130         -200, -200, 0, 0, 0, 0, m_hInst, 0 );
131     if( m_hParentWindow == NULL )
132     {
133         msg_Err( getIntf(), "Cannot create parent window" );
134         return false;
135     }
136
137     // We do it this way otherwise CreateWindowEx will fail
138     // if WS_EX_LAYERED is not supported
139     SetWindowLongPtr( m_hParentWindow, GWL_EXSTYLE,
140                       GetWindowLong( m_hParentWindow, GWL_EXSTYLE ) |
141                       WS_EX_LAYERED );
142
143     // Store with it a pointer to the interface thread
144     SetWindowLongPtr( m_hParentWindow, GWLP_USERDATA, (LONG_PTR)getIntf() );
145     ShowWindow( m_hParentWindow, SW_SHOW );
146
147     // Initialize the OLE library (for drag & drop)
148     OleInitialize( NULL );
149
150     // We dynamically load msimg32.dll to get a pointer to TransparentBlt()
151     m_hMsimg32 = LoadLibrary( _T("msimg32.dll") );
152     if( !m_hMsimg32 ||
153         !( TransparentBlt =
154             (BOOL (WINAPI*)(HDC, int, int, int, int,
155                             HDC, int, int, int, int, unsigned int))
156             GetProcAddress( m_hMsimg32, _T("TransparentBlt") ) ) )
157     {
158         TransparentBlt = NULL;
159         msg_Dbg( getIntf(), "Couldn't find TransparentBlt(), "
160                  "falling back to BitBlt()" );
161     }
162     if( !m_hMsimg32 ||
163         !( AlphaBlend =
164             (BOOL (WINAPI*)( HDC, int, int, int, int, HDC, int, int,
165                               int, int, BLENDFUNCTION ))
166             GetProcAddress( m_hMsimg32, _T("AlphaBlend") ) ) )
167     {
168         AlphaBlend = NULL;
169         msg_Dbg( getIntf(), "Couldn't find AlphaBlend()" );
170     }
171
172     // Idem for user32.dll and SetLayeredWindowAttributes()
173     m_hUser32 = LoadLibrary( _T("user32.dll") );
174     if( !m_hUser32 ||
175         !( SetLayeredWindowAttributes =
176             (BOOL (WINAPI *)(HWND, COLORREF, BYTE, DWORD))
177             GetProcAddress( m_hUser32, _T("SetLayeredWindowAttributes") ) ) )
178     {
179         SetLayeredWindowAttributes = NULL;
180         msg_Dbg( getIntf(), "Couldn't find SetLayeredWindowAttributes()" );
181     }
182
183     // Initialize the resource path
184     m_resourcePath.push_back( (string)getIntf()->p_vlc->psz_homedir +
185                                "\\" + CONFIG_DIR + "\\skins" );
186     m_resourcePath.push_back( (string)getIntf()->p_libvlc->psz_vlcpath +
187                               "\\skins" );
188     m_resourcePath.push_back( (string)getIntf()->p_libvlc->psz_vlcpath +
189                               "\\skins2" );
190     m_resourcePath.push_back( (string)getIntf()->p_libvlc->psz_vlcpath +
191                               "\\share\\skins" );
192     m_resourcePath.push_back( (string)getIntf()->p_libvlc->psz_vlcpath +
193                               "\\share\\skins2" );
194
195     // All went well
196     return true;
197 }
198
199
200 Win32Factory::~Win32Factory()
201 {
202     // Uninitialize the OLE library
203     OleUninitialize();
204
205     if( m_hParentWindow ) DestroyWindow( m_hParentWindow );
206
207     // Unload msimg32.dll and user32.dll
208     if( m_hMsimg32 )
209         FreeLibrary( m_hMsimg32 );
210     if( m_hUser32 )
211         FreeLibrary( m_hUser32 );
212 }
213
214
215 OSGraphics *Win32Factory::createOSGraphics( int width, int height )
216 {
217     return new Win32Graphics( getIntf(), width, height );
218 }
219
220
221 OSLoop *Win32Factory::getOSLoop()
222 {
223     return Win32Loop::instance( getIntf() );
224 }
225
226
227 void Win32Factory::destroyOSLoop()
228 {
229     Win32Loop::destroy( getIntf() );
230 }
231
232 void Win32Factory::minimize()
233 {
234     /* Make sure no tooltip is visible first */
235     getIntf()->p_sys->p_theme->getWindowManager().hideTooltip();
236
237     ShowWindow( m_hParentWindow, SW_MINIMIZE );
238 }
239
240 OSTimer *Win32Factory::createOSTimer( const Callback &rCallback )
241 {
242     return new Win32Timer( getIntf(), rCallback, m_hParentWindow );
243 }
244
245
246 OSWindow *Win32Factory::createOSWindow( GenericWindow &rWindow, bool dragDrop,
247                                         bool playOnDrop, OSWindow *pParent )
248 {
249     return new Win32Window( getIntf(), rWindow, m_hInst, m_hParentWindow,
250                             dragDrop, playOnDrop, (Win32Window*)pParent );
251 }
252
253
254 OSTooltip *Win32Factory::createOSTooltip()
255 {
256     return new Win32Tooltip( getIntf(), m_hInst, m_hParentWindow );
257 }
258
259
260 int Win32Factory::getScreenWidth() const
261 {
262     return GetSystemMetrics(SM_CXSCREEN);
263
264 }
265
266
267 int Win32Factory::getScreenHeight() const
268 {
269     return GetSystemMetrics(SM_CYSCREEN);
270 }
271
272
273 Rect Win32Factory::getWorkArea() const
274 {
275     RECT r;
276     SystemParametersInfo( SPI_GETWORKAREA, 0, &r, 0 );
277     // Fill a Rect object
278     Rect rect( r.left, r.top, r.right, r.bottom );
279     return rect;
280 }
281
282
283 void Win32Factory::getMousePos( int &rXPos, int &rYPos ) const
284 {
285     POINT mousePos;
286     GetCursorPos( &mousePos );
287     rXPos = mousePos.x;
288     rYPos = mousePos.y;
289 }
290
291
292 void Win32Factory::changeCursor( CursorType_t type ) const
293 {
294     LPCTSTR id;
295     switch( type )
296     {
297         case kDefaultArrow:
298             id = IDC_ARROW;
299             break;
300         case kResizeNWSE:
301             id = IDC_SIZENWSE;
302             break;
303         case kResizeNS:
304             id = IDC_SIZENS;
305             break;
306         case kResizeWE:
307             id = IDC_SIZEWE;
308             break;
309         case kResizeNESW:
310             id = IDC_SIZENESW;
311             break;
312         default:
313             id = IDC_ARROW;
314             break;
315     }
316
317     HCURSOR hCurs = LoadCursor( NULL, id );
318     SetCursor( hCurs );
319 }
320
321
322 void Win32Factory::rmDir( const string &rPath )
323 {
324     WIN32_FIND_DATA find;
325     string file;
326     string findFiles = rPath + "\\*";
327     HANDLE handle    = FindFirstFile( findFiles.c_str(), &find );
328
329     while( handle != INVALID_HANDLE_VALUE )
330     {
331         // If file is neither "." nor ".."
332         if( strcmp( find.cFileName, "." ) && strcmp( find.cFileName, ".." ) )
333         {
334             // Set file name
335             file = rPath + "\\" + (string)find.cFileName;
336
337             // If file is a directory, delete it recursively
338             if( find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
339             {
340                 rmDir( file );
341             }
342             // Else, it is a file so simply delete it
343             else
344             {
345                 DeleteFile( file.c_str() );
346             }
347         }
348
349         // If no more file in directory, exit while
350         if( !FindNextFile( handle, &find ) )
351             break;
352     }
353
354     // Now directory is empty so can be removed
355     FindClose( handle );
356     RemoveDirectory( rPath.c_str() );
357 }
358
359 #endif