]> git.sesse.net Git - vlc/blob - modules/gui/skins2/win32/win32_loop.cpp
Add support for keyboard multimedia keys on win32. This is of course untested.
[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     virtKeyToVlcKey[VK_BROWSER_BACK] = KEY_BROWSER_BACK;
76     virtKeyToVlcKey[VK_BROWSER_FORWARD] = KEY_BROWSER_FORWARD;
77     virtKeyToVlcKey[VK_BROWSER_REFRESH] = KEY_BROWSER_REFRESH;
78     virtKeyToVlcKey[VK_BROWSER_STOP] = KEY_BROWSER_STOP;
79     virtKeyToVlcKey[VK_BROWSER_SEARCH] = KEY_BROWSER_SEARCH;
80     virtKeyToVlcKey[VK_BROWSER_FAVORITES] = KEY_BROWSER_FAVORITES;
81     virtKeyToVlcKey[VK_BROWSER_HOME] = KEY_BROWSER_HOME;
82     virtKeyToVlcKey[VK_VOLUME_MUTE] = KEY_VOLUME_MUTE;
83     virtKeyToVlcKey[VK_VOLUME_DOWN] = KEY_VOLUME_DOWN;
84     virtKeyToVlcKey[VK_VOLUME_UP] = KEY_VOLUME_UP;
85     virtKeyToVlcKey[VK_MEDIA_NEXT_TRACK] = KEY_MEDIA_NEXT_TRACK;
86     virtKeyToVlcKey[VK_MEDIA_PREV_TRACK] = KEY_MEDIA_PREV_TRACK;
87     virtKeyToVlcKey[VK_MEDIA_STOP] = KEY_MEDIA_STOP;
88     virtKeyToVlcKey[VK_MEDIA_PLAY_PAUSE] = KEY_MEDIA_PLAY_PAUSE;
89 }
90
91
92 Win32Loop::~Win32Loop()
93 {
94 }
95
96
97 OSLoop *Win32Loop::instance( intf_thread_t *pIntf )
98 {
99     if( pIntf->p_sys->p_osLoop == NULL )
100     {
101         OSLoop *pOsLoop = new Win32Loop( pIntf );
102         pIntf->p_sys->p_osLoop = pOsLoop;
103     }
104     return pIntf->p_sys->p_osLoop;
105 }
106
107
108 void Win32Loop::destroy( intf_thread_t *pIntf )
109 {
110     if( pIntf->p_sys->p_osLoop )
111     {
112         delete pIntf->p_sys->p_osLoop;
113         pIntf->p_sys->p_osLoop = NULL;
114     }
115 }
116
117
118 void Win32Loop::run()
119 {
120     MSG msg;
121
122     // Compute windows message list
123     while( GetMessage( &msg, NULL, 0, 0 ) )
124     {
125         Win32Factory *pFactory =
126             (Win32Factory*)Win32Factory::instance( getIntf() );
127         GenericWindow *pWin = pFactory->m_windowMap[msg.hwnd];
128         if( pWin == NULL )
129         {
130             // We are probably getting a message for a tooltip (which has no
131             // associated GenericWindow), for a timer, or for the parent window
132             DispatchMessage( &msg );
133             continue;
134         }
135
136         GenericWindow &win = *pWin;
137         switch( msg.message )
138         {
139             case WM_PAINT:
140             {
141                 PAINTSTRUCT Infos;
142                 BeginPaint( msg.hwnd, &Infos );
143                 EvtRefresh evt( getIntf(),
144                                 Infos.rcPaint.left,
145                                 Infos.rcPaint.top,
146                                 Infos.rcPaint.right - Infos.rcPaint.left + 1,
147                                 Infos.rcPaint.bottom - Infos.rcPaint.top + 1 );
148                 EndPaint( msg.hwnd, &Infos );
149                 win.processEvent( evt );
150                 break;
151             }
152             case WM_COMMAND:
153             {
154                 EvtMenu evt( getIntf(), LOWORD( msg.wParam ) );
155                 win.processEvent( evt );
156                 break;
157             }
158             case WM_MOUSEMOVE:
159             {
160                 // Needed to generate WM_MOUSELEAVE events
161                 TRACKMOUSEEVENT TrackEvent;
162                 TrackEvent.cbSize      = sizeof( TRACKMOUSEEVENT );
163                 TrackEvent.dwFlags     = TME_LEAVE;
164                 TrackEvent.hwndTrack   = msg.hwnd;
165                 TrackEvent.dwHoverTime = 1;
166                 TrackMouseEvent( &TrackEvent );
167
168                 // Compute the absolute position of the mouse
169                 int x = GET_X_LPARAM( msg.lParam ) + win.getLeft();
170                 int y = GET_Y_LPARAM( msg.lParam ) + win.getTop();
171                 EvtMotion evt( getIntf(), x, y );
172                 win.processEvent( evt );
173                 break;
174             }
175             case WM_MOUSELEAVE:
176             {
177                 EvtLeave evt( getIntf() );
178                 win.processEvent( evt );
179                 break;
180             }
181             case WM_MOUSEWHEEL:
182             {
183                 int x = GET_X_LPARAM( msg.lParam ) - win.getLeft();
184                 int y = GET_Y_LPARAM( msg.lParam ) - win.getTop();
185                 int mod = getMod( msg.wParam );
186                 if( GET_WHEEL_DELTA_WPARAM( msg.wParam ) > 0 )
187                 {
188                     EvtScroll evt( getIntf(), x, y, EvtScroll::kUp, mod );
189                     win.processEvent( evt );
190                 }
191                 else
192                 {
193                     EvtScroll evt( getIntf(), x, y, EvtScroll::kDown, mod );
194                     win.processEvent( evt );
195                 }
196                 break;
197             }
198             case WM_LBUTTONDOWN:
199             {
200                 SetCapture( msg.hwnd );
201                 EvtMouse evt( getIntf(), GET_X_LPARAM( msg.lParam ),
202                               GET_Y_LPARAM( msg.lParam ), EvtMouse::kLeft,
203                               EvtMouse::kDown, getMod( msg.wParam ) );
204                 win.processEvent( evt );
205                 break;
206             }
207             case WM_RBUTTONDOWN:
208             {
209                 SetCapture( msg.hwnd );
210                 EvtMouse evt( getIntf(), GET_X_LPARAM( msg.lParam ),
211                               GET_Y_LPARAM( msg.lParam ), EvtMouse::kRight,
212                               EvtMouse::kDown, getMod( msg.wParam ) );
213                 win.processEvent( evt );
214                 break;
215             }
216             case WM_LBUTTONUP:
217             {
218                 ReleaseCapture();
219                 EvtMouse evt( getIntf(), GET_X_LPARAM( msg.lParam ),
220                               GET_Y_LPARAM( msg.lParam ), EvtMouse::kLeft,
221                               EvtMouse::kUp, getMod( msg.wParam ) );
222                 win.processEvent( evt );
223                 break;
224             }
225             case WM_RBUTTONUP:
226             {
227                 ReleaseCapture();
228                 EvtMouse evt( getIntf(), GET_X_LPARAM( msg.lParam ),
229                               GET_Y_LPARAM( msg.lParam ), EvtMouse::kRight,
230                               EvtMouse::kUp, getMod( msg.wParam ) );
231                 win.processEvent( evt );
232                 break;
233             }
234             case WM_LBUTTONDBLCLK:
235             {
236                 ReleaseCapture();
237                 EvtMouse evt( getIntf(), GET_X_LPARAM( msg.lParam ),
238                               GET_Y_LPARAM( msg.lParam ), EvtMouse::kLeft,
239                               EvtMouse::kDblClick, getMod( msg.wParam ) );
240                 win.processEvent( evt );
241                 break;
242             }
243             case WM_RBUTTONDBLCLK:
244             {
245                 ReleaseCapture();
246                 EvtMouse evt( getIntf(), GET_X_LPARAM( msg.lParam ),
247                               GET_Y_LPARAM( msg.lParam ), EvtMouse::kRight,
248                               EvtMouse::kDblClick, getMod( msg.wParam ) );
249                 win.processEvent( evt );
250                 break;
251             }
252             case WM_KEYDOWN:
253             case WM_SYSKEYDOWN:
254             case WM_KEYUP:
255             case WM_SYSKEYUP:
256             {
257                 // The key events are first processed here and not translated
258                 // into WM_CHAR events because we need to know the status of
259                 // the modifier keys.
260
261                 // Get VLC key code from the virtual key code
262                 int key = virtKeyToVlcKey[msg.wParam];
263                 if( !key )
264                 {
265                     // This appears to be a "normal" (ascii) key
266                     key = tolower( MapVirtualKey( msg.wParam, 2 ) );
267                 }
268
269                 if( key )
270                 {
271                     // Get the modifier
272                     int mod = 0;
273                     if( GetKeyState( VK_CONTROL ) & 0x8000 )
274                     {
275                         mod |= EvtInput::kModCtrl;
276                     }
277                     if( GetKeyState( VK_SHIFT ) & 0x8000 )
278                     {
279                         mod |= EvtInput::kModShift;
280                     }
281                     if( GetKeyState( VK_MENU ) & 0x8000 )
282                     {
283                         mod |= EvtInput::kModAlt;
284                     }
285
286                     // Get the state
287                     EvtKey::ActionType_t state;
288                     if( msg.message == WM_KEYDOWN ||
289                         msg.message == WM_SYSKEYDOWN )
290                     {
291                         state = EvtKey::kDown;
292                     }
293                     else
294                     {
295                         state = EvtKey::kUp;
296                     }
297
298                     EvtKey evt( getIntf(), key, state, mod );
299                     win.processEvent( evt );
300                 }
301                 break;
302             }
303             default:
304                 TranslateMessage( &msg );
305                 DispatchMessage( &msg );
306         }
307     }
308 }
309
310
311 int Win32Loop::getMod( WPARAM wParam ) const
312 {
313     int mod = EvtInput::kModNone;
314     if( wParam & MK_CONTROL )
315         mod |= EvtInput::kModCtrl;
316     if( wParam & MK_SHIFT )
317         mod |= EvtInput::kModShift;
318
319     return mod;
320 }
321
322
323 void Win32Loop::exit()
324 {
325     PostQuitMessage(0);
326 }
327
328 #endif