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_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"
40 // XXX: Cygwin (at least) doesn't define these macros. Too bad...
42 #define GET_X_LPARAM(a) ((int16_t)(a))
43 #define GET_Y_LPARAM(a) ((int16_t)((a)>>16))
47 Win32Loop::Win32Loop( intf_thread_t *pIntf ): OSLoop( pIntf )
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;
92 Win32Loop::~Win32Loop()
97 OSLoop *Win32Loop::instance( intf_thread_t *pIntf )
99 if( pIntf->p_sys->p_osLoop == NULL )
101 OSLoop *pOsLoop = new Win32Loop( pIntf );
102 pIntf->p_sys->p_osLoop = pOsLoop;
104 return pIntf->p_sys->p_osLoop;
108 void Win32Loop::destroy( intf_thread_t *pIntf )
110 if( pIntf->p_sys->p_osLoop )
112 delete pIntf->p_sys->p_osLoop;
113 pIntf->p_sys->p_osLoop = NULL;
118 void Win32Loop::run()
122 // Compute windows message list
123 while( GetMessage( &msg, NULL, 0, 0 ) )
125 Win32Factory *pFactory =
126 (Win32Factory*)Win32Factory::instance( getIntf() );
127 GenericWindow *pWin = pFactory->m_windowMap[msg.hwnd];
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 );
136 GenericWindow &win = *pWin;
137 switch( msg.message )
142 BeginPaint( msg.hwnd, &Infos );
143 EvtRefresh evt( getIntf(),
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 );
154 EvtMenu evt( getIntf(), LOWORD( msg.wParam ) );
155 win.processEvent( evt );
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 );
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 );
177 EvtLeave evt( getIntf() );
178 win.processEvent( evt );
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 )
188 EvtScroll evt( getIntf(), x, y, EvtScroll::kUp, mod );
189 win.processEvent( evt );
193 EvtScroll evt( getIntf(), x, y, EvtScroll::kDown, mod );
194 win.processEvent( evt );
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 );
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 );
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 );
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 );
234 case WM_LBUTTONDBLCLK:
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 );
243 case WM_RBUTTONDBLCLK:
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 );
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.
261 // Get VLC key code from the virtual key code
262 int key = virtKeyToVlcKey[msg.wParam];
265 // This appears to be a "normal" (ascii) key
266 key = tolower( MapVirtualKey( msg.wParam, 2 ) );
273 if( GetKeyState( VK_CONTROL ) & 0x8000 )
275 mod |= EvtInput::kModCtrl;
277 if( GetKeyState( VK_SHIFT ) & 0x8000 )
279 mod |= EvtInput::kModShift;
281 if( GetKeyState( VK_MENU ) & 0x8000 )
283 mod |= EvtInput::kModAlt;
287 EvtKey::ActionType_t state;
288 if( msg.message == WM_KEYDOWN ||
289 msg.message == WM_SYSKEYDOWN )
291 state = EvtKey::kDown;
298 EvtKey evt( getIntf(), key, state, mod );
299 win.processEvent( evt );
304 TranslateMessage( &msg );
305 DispatchMessage( &msg );
311 int Win32Loop::getMod( WPARAM wParam ) const
313 int mod = EvtInput::kModNone;
314 if( wParam & MK_CONTROL )
315 mod |= EvtInput::kModCtrl;
316 if( wParam & MK_SHIFT )
317 mod |= EvtInput::kModShift;
323 void Win32Loop::exit()