]> git.sesse.net Git - vlc/blob - modules/gui/skins2/win32/win32_loop.cpp
dd1b84d498b725ce2144eb13776961fd2c7fb37f
[vlc] / modules / gui / skins2 / win32 / win32_loop.cpp
1 /*****************************************************************************
2  * win32_loop.cpp
3  *****************************************************************************
4  * Copyright (C) 2003 the VideoLAN team
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #ifdef WIN32_SKINS
26
27 #include "win32_factory.hpp"
28 #include "win32_loop.hpp"
29 #include "../src/generic_window.hpp"
30 #include "../events/evt_key.hpp"
31 #include "../events/evt_leave.hpp"
32 #include "../events/evt_menu.hpp"
33 #include "../events/evt_motion.hpp"
34 #include "../events/evt_mouse.hpp"
35 #include "../events/evt_refresh.hpp"
36 #include "../events/evt_scroll.hpp"
37 #include "vlc_keys.h"
38
39
40 // XXX: Cygwin (at least) doesn't define these macros. Too bad...
41 #ifndef GET_X_LPARAM
42     #define GET_X_LPARAM(a) ((int16_t)(a))
43     #define GET_Y_LPARAM(a) ((int16_t)((a)>>16))
44 #endif
45
46
47 Win32Loop::Win32Loop( intf_thread_t *pIntf ): OSLoop( pIntf )
48 {
49     // Initialize the map
50     virtKeyToVlcKey[VK_F1] = KEY_F1;
51     virtKeyToVlcKey[VK_F2] = KEY_F2;
52     virtKeyToVlcKey[VK_F3] = KEY_F3;
53     virtKeyToVlcKey[VK_F4] = KEY_F4;
54     virtKeyToVlcKey[VK_F5] = KEY_F5;
55     virtKeyToVlcKey[VK_F6] = KEY_F6;
56     virtKeyToVlcKey[VK_F7] = KEY_F7;
57     virtKeyToVlcKey[VK_F8] = KEY_F8;
58     virtKeyToVlcKey[VK_F9] = KEY_F9;
59     virtKeyToVlcKey[VK_F10] = KEY_F10;
60     virtKeyToVlcKey[VK_F11] = KEY_F11;
61     virtKeyToVlcKey[VK_F12] = KEY_F12;
62     virtKeyToVlcKey[VK_RETURN] = KEY_ENTER;
63     virtKeyToVlcKey[VK_SPACE] = KEY_SPACE;
64     virtKeyToVlcKey[VK_ESCAPE] = KEY_ESC;
65     virtKeyToVlcKey[VK_LEFT] = KEY_LEFT;
66     virtKeyToVlcKey[VK_RIGHT] = KEY_RIGHT;
67     virtKeyToVlcKey[VK_UP] = KEY_UP;
68     virtKeyToVlcKey[VK_DOWN] = KEY_DOWN;
69     virtKeyToVlcKey[VK_INSERT] = KEY_INSERT;
70     virtKeyToVlcKey[VK_DELETE] = KEY_DELETE;
71     virtKeyToVlcKey[VK_HOME] = KEY_HOME;
72     virtKeyToVlcKey[VK_END] = KEY_END;
73     virtKeyToVlcKey[VK_PRIOR] = KEY_PAGEUP;
74     virtKeyToVlcKey[VK_NEXT] = KEY_PAGEDOWN;
75 }
76
77
78 Win32Loop::~Win32Loop()
79 {
80 }
81
82
83 OSLoop *Win32Loop::instance( intf_thread_t *pIntf )
84 {
85     if( pIntf->p_sys->p_osLoop == NULL )
86     {
87         OSLoop *pOsLoop = new Win32Loop( pIntf );
88         pIntf->p_sys->p_osLoop = pOsLoop;
89     }
90     return pIntf->p_sys->p_osLoop;
91 }
92
93
94 void Win32Loop::destroy( intf_thread_t *pIntf )
95 {
96     if( pIntf->p_sys->p_osLoop )
97     {
98         delete pIntf->p_sys->p_osLoop;
99         pIntf->p_sys->p_osLoop = NULL;
100     }
101 }
102
103
104 void Win32Loop::run()
105 {
106     MSG msg;
107
108     // Compute windows message list
109     while( GetMessage( &msg, NULL, 0, 0 ) )
110     {
111         Win32Factory *pFactory =
112             (Win32Factory*)Win32Factory::instance( getIntf() );
113         GenericWindow *pWin = pFactory->m_windowMap[msg.hwnd];
114         if( pWin == NULL )
115         {
116             // We are probably getting a message for a tooltip (which has no
117             // associated GenericWindow), for a timer, or for the parent window
118             DispatchMessage( &msg );
119             continue;
120         }
121
122         GenericWindow &win = *pWin;
123         switch( msg.message )
124         {
125             case WM_PAINT:
126             {
127                 PAINTSTRUCT Infos;
128                 BeginPaint( msg.hwnd, &Infos );
129                 EvtRefresh evt( getIntf(),
130                                 Infos.rcPaint.left,
131                                 Infos.rcPaint.top,
132                                 Infos.rcPaint.right - Infos.rcPaint.left + 1,
133                                 Infos.rcPaint.bottom - Infos.rcPaint.top + 1 );
134                 EndPaint( msg.hwnd, &Infos );
135                 win.processEvent( evt );
136                 break;
137             }
138             case WM_COMMAND:
139             {
140                 EvtMenu evt( getIntf(), LOWORD( msg.wParam ) );
141                 win.processEvent( evt );
142                 break;
143             }
144             case WM_MOUSEMOVE:
145             {
146                 // Needed to generate WM_MOUSELEAVE events
147                 TRACKMOUSEEVENT TrackEvent;
148                 TrackEvent.cbSize      = sizeof( TRACKMOUSEEVENT );
149                 TrackEvent.dwFlags     = TME_LEAVE;
150                 TrackEvent.hwndTrack   = msg.hwnd;
151                 TrackEvent.dwHoverTime = 1;
152                 TrackMouseEvent( &TrackEvent );
153
154                 // Compute the absolute position of the mouse
155                 int x = GET_X_LPARAM( msg.lParam ) + win.getLeft();
156                 int y = GET_Y_LPARAM( msg.lParam ) + win.getTop();
157                 EvtMotion evt( getIntf(), x, y );
158                 win.processEvent( evt );
159                 break;
160             }
161             case WM_MOUSELEAVE:
162             {
163                 EvtLeave evt( getIntf() );
164                 win.processEvent( evt );
165                 break;
166             }
167             case WM_MOUSEWHEEL:
168             {
169                 int x = GET_X_LPARAM( msg.lParam ) - win.getLeft();
170                 int y = GET_Y_LPARAM( msg.lParam ) - win.getTop();
171                 int mod = getMod( msg.wParam );
172                 if( GET_WHEEL_DELTA_WPARAM( msg.wParam ) > 0 )
173                 {
174                     EvtScroll evt( getIntf(), x, y, EvtScroll::kUp, mod );
175                     win.processEvent( evt );
176                 }
177                 else
178                 {
179                     EvtScroll evt( getIntf(), x, y, EvtScroll::kDown, mod );
180                     win.processEvent( evt );
181                 }
182                 break;
183             }
184             case WM_LBUTTONDOWN:
185             {
186                 SetCapture( msg.hwnd );
187                 EvtMouse evt( getIntf(), GET_X_LPARAM( msg.lParam ),
188                               GET_Y_LPARAM( msg.lParam ), EvtMouse::kLeft,
189                               EvtMouse::kDown, getMod( msg.wParam ) );
190                 win.processEvent( evt );
191                 break;
192             }
193             case WM_RBUTTONDOWN:
194             {
195                 SetCapture( msg.hwnd );
196                 EvtMouse evt( getIntf(), GET_X_LPARAM( msg.lParam ),
197                               GET_Y_LPARAM( msg.lParam ), EvtMouse::kRight,
198                               EvtMouse::kDown, getMod( msg.wParam ) );
199                 win.processEvent( evt );
200                 break;
201             }
202             case WM_LBUTTONUP:
203             {
204                 ReleaseCapture();
205                 EvtMouse evt( getIntf(), GET_X_LPARAM( msg.lParam ),
206                               GET_Y_LPARAM( msg.lParam ), EvtMouse::kLeft,
207                               EvtMouse::kUp, getMod( msg.wParam ) );
208                 win.processEvent( evt );
209                 break;
210             }
211             case WM_RBUTTONUP:
212             {
213                 ReleaseCapture();
214                 EvtMouse evt( getIntf(), GET_X_LPARAM( msg.lParam ),
215                               GET_Y_LPARAM( msg.lParam ), EvtMouse::kRight,
216                               EvtMouse::kUp, getMod( msg.wParam ) );
217                 win.processEvent( evt );
218                 break;
219             }
220             case WM_LBUTTONDBLCLK:
221             {
222                 ReleaseCapture();
223                 EvtMouse evt( getIntf(), GET_X_LPARAM( msg.lParam ),
224                               GET_Y_LPARAM( msg.lParam ), EvtMouse::kLeft,
225                               EvtMouse::kDblClick, getMod( msg.wParam ) );
226                 win.processEvent( evt );
227                 break;
228             }
229             case WM_RBUTTONDBLCLK:
230             {
231                 ReleaseCapture();
232                 EvtMouse evt( getIntf(), GET_X_LPARAM( msg.lParam ),
233                               GET_Y_LPARAM( msg.lParam ), EvtMouse::kRight,
234                               EvtMouse::kDblClick, getMod( msg.wParam ) );
235                 win.processEvent( evt );
236                 break;
237             }
238             case WM_KEYDOWN:
239             case WM_SYSKEYDOWN:
240             case WM_KEYUP:
241             case WM_SYSKEYUP:
242             {
243                 // The key events are first processed here and not translated
244                 // into WM_CHAR events because we need to know the status of
245                 // the modifier keys.
246
247                 // Get VLC key code from the virtual key code
248                 int key = virtKeyToVlcKey[msg.wParam];
249                 if( !key )
250                 {
251                     // This appears to be a "normal" (ascii) key
252                     key = tolower( MapVirtualKey( msg.wParam, 2 ) );
253                 }
254
255                 if( key )
256                 {
257                     // Get the modifier
258                     int mod = 0;
259                     if( GetKeyState( VK_CONTROL ) & 0x8000 )
260                     {
261                         mod |= EvtInput::kModCtrl;
262                     }
263                     if( GetKeyState( VK_SHIFT ) & 0x8000 )
264                     {
265                         mod |= EvtInput::kModShift;
266                     }
267                     if( GetKeyState( VK_MENU ) & 0x8000 )
268                     {
269                         mod |= EvtInput::kModAlt;
270                     }
271
272                     // Get the state
273                     EvtKey::ActionType_t state;
274                     if( msg.message == WM_KEYDOWN ||
275                         msg.message == WM_SYSKEYDOWN )
276                     {
277                         state = EvtKey::kDown;
278                     }
279                     else
280                     {
281                         state = EvtKey::kUp;
282                     }
283
284                     EvtKey evt( getIntf(), key, state, mod );
285                     win.processEvent( evt );
286                 }
287                 break;
288             }
289             default:
290                 TranslateMessage( &msg );
291                 DispatchMessage( &msg );
292         }
293     }
294 }
295
296
297 int Win32Loop::getMod( WPARAM wParam ) const
298 {
299     int mod = EvtInput::kModNone;
300     if( wParam & MK_CONTROL )
301         mod |= EvtInput::kModCtrl;
302     if( wParam & MK_SHIFT )
303         mod |= EvtInput::kModShift;
304
305     return mod;
306 }
307
308
309 void Win32Loop::exit()
310 {
311     PostQuitMessage(0);
312 }
313
314 #endif