1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2003 the VideoLAN team
7 * Authors: Cyril Deguet <asmax@via.ecp.fr>
8 * Olivier Teulière <ipkiss@via.ecp.fr>
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
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_popup.hpp"
33 #include "win32_loop.hpp"
34 #include "../src/theme.hpp"
35 #include "../src/window_manager.hpp"
36 #include "../src/generic_window.hpp"
37 #include "../commands/cmd_dialogs.hpp"
38 #include "../commands/cmd_minimize.hpp"
40 // Custom message for the notifications of the system tray
41 #define MY_WM_TRAYACTION (WM_APP + 1)
44 LRESULT CALLBACK Win32Proc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
46 // Get pointer to thread info: should only work with the parent window
47 intf_thread_t *p_intf = (intf_thread_t *)GetWindowLongPtr( hwnd,
50 // If doesn't exist, treat windows message normally
51 if( p_intf == NULL || p_intf->p_sys->p_osFactory == NULL )
53 return DefWindowProc( hwnd, uMsg, wParam, lParam );
56 Win32Factory *pFactory = (Win32Factory*)Win32Factory::instance( p_intf );
58 if( hwnd == pFactory->getParentWindow() )
60 if( uMsg == WM_SYSCOMMAND )
62 // If closing parent window
63 if( wParam == SC_CLOSE )
65 libvlc_Quit( p_intf->p_libvlc );
68 else if( wParam == SC_MINIMIZE )
73 else if( wParam == SC_RESTORE )
80 msg_Dbg( p_intf, "WM_SYSCOMMAND %i", wParam );
83 // Handle systray notifications
84 else if( uMsg == MY_WM_TRAYACTION )
86 if( (UINT)lParam == WM_LBUTTONDOWN )
88 p_intf->p_sys->p_theme->getWindowManager().raiseAll();
89 CmdDlgHidePopupMenu aCmdPopup( p_intf );
92 else if( (UINT)lParam == WM_RBUTTONDOWN )
94 CmdDlgShowPopupMenu aCmdPopup( p_intf );
97 else if( (UINT)lParam == WM_LBUTTONDBLCLK )
99 CmdRestore aCmdRestore( p_intf );
100 aCmdRestore.execute();
105 // If hwnd does not match any window or message not processed
106 return DefWindowProc( hwnd, uMsg, wParam, lParam );
110 Win32Factory::Win32Factory( intf_thread_t *pIntf ):
111 OSFactory( pIntf ), TransparentBlt( NULL ), AlphaBlend( NULL ),
112 SetLayeredWindowAttributes( NULL ), m_hParentWindow( NULL ),
119 bool Win32Factory::init()
121 // Get instance handle
122 m_hInst = GetModuleHandle( NULL );
123 if( m_hInst == NULL )
125 msg_Err( getIntf(), "Cannot get module handle" );
128 // Create window class
129 WNDCLASS skinWindowClass;
130 skinWindowClass.style = CS_DBLCLKS;
131 skinWindowClass.lpfnWndProc = (WNDPROC) Win32Proc;
132 skinWindowClass.lpszClassName = _T("SkinWindowClass");
133 skinWindowClass.lpszMenuName = NULL;
134 skinWindowClass.cbClsExtra = 0;
135 skinWindowClass.cbWndExtra = 0;
136 skinWindowClass.hbrBackground = NULL;
137 skinWindowClass.hCursor = LoadCursor( NULL, IDC_ARROW );
138 skinWindowClass.hIcon = LoadIcon( m_hInst, _T("VLC_ICON") );
139 skinWindowClass.hInstance = m_hInst;
141 // Register class and check it
142 if( !RegisterClass( &skinWindowClass ) )
146 // Check why it failed. If it's because the class already exists
147 // then fine, otherwise return with an error.
148 if( !GetClassInfo( m_hInst, _T("SkinWindowClass"), &wndclass ) )
150 msg_Err( getIntf(), "cannot register window class" );
156 m_hParentWindow = CreateWindowEx( WS_EX_TOOLWINDOW, _T("SkinWindowClass"),
157 _T("VLC media player"), WS_POPUP | WS_SYSMENU | WS_MINIMIZEBOX,
158 -200, -200, 0, 0, 0, 0, m_hInst, 0 );
159 if( m_hParentWindow == NULL )
161 msg_Err( getIntf(), "cannot create parent window" );
165 // Store with it a pointer to the interface thread
166 SetWindowLongPtr( m_hParentWindow, GWLP_USERDATA, (LONG_PTR)getIntf() );
168 // We do it this way otherwise CreateWindowEx will fail
169 // if WS_EX_LAYERED is not supported
170 SetWindowLongPtr( m_hParentWindow, GWL_EXSTYLE,
171 GetWindowLongPtr( m_hParentWindow, GWL_EXSTYLE ) |
174 ShowWindow( m_hParentWindow, SW_SHOW );
176 // Initialize the systray icon
177 m_trayIcon.cbSize = sizeof( NOTIFYICONDATA );
178 m_trayIcon.hWnd = m_hParentWindow;
180 m_trayIcon.uFlags = NIF_ICON|NIF_TIP|NIF_MESSAGE;
181 m_trayIcon.uCallbackMessage = MY_WM_TRAYACTION;
182 m_trayIcon.hIcon = LoadIcon( m_hInst, _T("VLC_ICON") );
183 strcpy( m_trayIcon.szTip, "VLC media player" );
185 // Show the systray icon if needed
186 if( var_InheritBool( getIntf(), "skins2-systray" ) )
191 // Show the task in the task bar if needed
192 if( var_InheritBool( getIntf(), "skins2-taskbar" ) )
197 // Initialize the OLE library (for drag & drop)
198 OleInitialize( NULL );
200 // We dynamically load msimg32.dll to get a pointer to TransparentBlt()
201 m_hMsimg32 = LoadLibrary( _T("msimg32.dll") );
204 (BOOL (WINAPI*)(HDC, int, int, int, int,
205 HDC, int, int, int, int, unsigned int))
206 GetProcAddress( m_hMsimg32, _T("TransparentBlt") ) ) )
208 TransparentBlt = NULL;
209 msg_Dbg( getIntf(), "couldn't find TransparentBlt(), "
210 "falling back to BitBlt()" );
214 (BOOL (WINAPI*)( HDC, int, int, int, int, HDC, int, int,
215 int, int, BLENDFUNCTION ))
216 GetProcAddress( m_hMsimg32, _T("AlphaBlend") ) ) )
219 msg_Dbg( getIntf(), "couldn't find AlphaBlend()" );
222 // Idem for user32.dll and SetLayeredWindowAttributes()
223 m_hUser32 = LoadLibrary( _T("user32.dll") );
225 !( SetLayeredWindowAttributes =
226 (BOOL (WINAPI *)(HWND, COLORREF, BYTE, DWORD))
227 GetProcAddress( m_hUser32, _T("SetLayeredWindowAttributes") ) ) )
229 SetLayeredWindowAttributes = NULL;
230 msg_Dbg( getIntf(), "couldn't find SetLayeredWindowAttributes()" );
233 // Initialize the resource path
234 char *datadir = config_GetUserDir( VLC_DATA_DIR );
235 m_resourcePath.push_back( (string)datadir + "\\skins" );
237 datadir = config_GetDataDir( getIntf() );
238 m_resourcePath.push_back( (string)datadir + "\\skins" );
239 m_resourcePath.push_back( (string)datadir + "\\skins2" );
240 m_resourcePath.push_back( (string)datadir + "\\share\\skins" );
241 m_resourcePath.push_back( (string)datadir + "\\share\\skins2" );
249 Win32Factory::~Win32Factory()
251 // Uninitialize the OLE library
254 // Remove the systray icon
257 if( m_hParentWindow ) DestroyWindow( m_hParentWindow );
259 // Unload msimg32.dll and user32.dll
261 FreeLibrary( m_hMsimg32 );
263 FreeLibrary( m_hUser32 );
267 OSGraphics *Win32Factory::createOSGraphics( int width, int height )
269 return new Win32Graphics( getIntf(), width, height );
273 OSLoop *Win32Factory::getOSLoop()
275 return Win32Loop::instance( getIntf() );
279 void Win32Factory::destroyOSLoop()
281 Win32Loop::destroy( getIntf() );
284 void Win32Factory::minimize()
286 /* Make sure no tooltip is visible first */
287 getIntf()->p_sys->p_theme->getWindowManager().hideTooltip();
289 ShowWindow( m_hParentWindow, SW_MINIMIZE );
292 void Win32Factory::restore()
294 ShowWindow( m_hParentWindow, SW_RESTORE );
297 void Win32Factory::addInTray()
299 Shell_NotifyIcon( NIM_ADD, &m_trayIcon );
302 void Win32Factory::removeFromTray()
304 Shell_NotifyIcon( NIM_DELETE, &m_trayIcon );
307 void Win32Factory::addInTaskBar()
309 ShowWindow( m_hParentWindow, SW_HIDE );
310 SetWindowLongPtr( m_hParentWindow, GWL_EXSTYLE,
311 WS_EX_LAYERED|WS_EX_APPWINDOW );
312 ShowWindow( m_hParentWindow, SW_SHOW );
315 void Win32Factory::removeFromTaskBar()
317 ShowWindow( m_hParentWindow, SW_HIDE );
318 SetWindowLongPtr( m_hParentWindow, GWL_EXSTYLE,
319 WS_EX_LAYERED|WS_EX_TOOLWINDOW );
320 ShowWindow( m_hParentWindow, SW_SHOW );
323 OSTimer *Win32Factory::createOSTimer( CmdGeneric &rCmd )
325 return new Win32Timer( getIntf(), rCmd, m_hParentWindow );
329 OSWindow *Win32Factory::createOSWindow( GenericWindow &rWindow, bool dragDrop,
330 bool playOnDrop, OSWindow *pParent,
331 GenericWindow::WindowType_t type )
333 return new Win32Window( getIntf(), rWindow, m_hInst, m_hParentWindow,
334 dragDrop, playOnDrop, (Win32Window*)pParent, type );
338 OSTooltip *Win32Factory::createOSTooltip()
340 return new Win32Tooltip( getIntf(), m_hInst, m_hParentWindow );
344 OSPopup *Win32Factory::createOSPopup()
346 // XXX FIXME: this way of getting the handle really sucks!
347 // In fact, the clean way would be to have in Builder::addPopup() a call
348 // to pPopup->associateToWindow() (to be written)... but the problem is
349 // that there is no way to access the OS-dependent window handle from a
350 // GenericWindow (we cannot even access the OSWindow).
351 if( m_windowMap.begin() == m_windowMap.end() )
353 msg_Err( getIntf(), "no window has been created before the popup!" );
357 return new Win32Popup( getIntf(), m_windowMap.begin()->first );
361 int Win32Factory::getScreenWidth() const
363 return GetSystemMetrics(SM_CXSCREEN);
368 int Win32Factory::getScreenHeight() const
370 return GetSystemMetrics(SM_CYSCREEN);
374 SkinsRect Win32Factory::getWorkArea() const
377 SystemParametersInfo( SPI_GETWORKAREA, 0, &r, 0 );
378 // Fill a Rect object
379 return SkinsRect( r.left, r.top, r.right, r.bottom );
383 void Win32Factory::getMousePos( int &rXPos, int &rYPos ) const
386 GetCursorPos( &mousePos );
392 void Win32Factory::changeCursor( CursorType_t type ) const
398 case kDefaultArrow: id = IDC_ARROW; break;
399 case kResizeNWSE: id = IDC_SIZENWSE; break;
400 case kResizeNS: id = IDC_SIZENS; break;
401 case kResizeWE: id = IDC_SIZEWE; break;
402 case kResizeNESW: id = IDC_SIZENESW; break;
405 HCURSOR hCurs = LoadCursor( NULL, id );
410 void Win32Factory::rmDir( const string &rPath )
412 WIN32_FIND_DATA find;
414 string findFiles = rPath + "\\*";
415 HANDLE handle = FindFirstFile( findFiles.c_str(), &find );
417 while( handle != INVALID_HANDLE_VALUE )
419 // If file is neither "." nor ".."
420 if( strcmp( find.cFileName, "." ) && strcmp( find.cFileName, ".." ) )
423 file = rPath + "\\" + (string)find.cFileName;
425 // If file is a directory, delete it recursively
426 if( find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
430 // Else, it is a file so simply delete it
433 DeleteFile( file.c_str() );
437 // If no more file in directory, exit while
438 if( !FindNextFile( handle, &find ) )
442 // Now directory is empty so can be removed
444 RemoveDirectory( rPath.c_str() );