1 /*****************************************************************************
2  * os2_loop.cpp
3  *****************************************************************************
4  * Copyright (C) 2003, 2013 the VideoLAN team
5  *
6  * Authors: Cyril Deguet      <asmax@via.ecp.fr>
7  *          Olivier Teulière <ipkiss@via.ecp.fr>
8  *          KO Myung-Hun      <komh@chollian.net>
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 OS2_SKINS
26 
27 #include "os2_factory.hpp"
28 #include "os2_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_actions.h>
38 
39 
40 #define GET_X_MP( mp ) ( SHORT1FROMMP( mp ))
41 #define GET_Y_MP( mp ) (( rcl.yTop - 1 ) - SHORT2FROMMP( mp )) /* Invert Y */
42 
43 #ifndef WM_MOUSELEAVE
44 #define WM_MOUSELEAVE   0x41F
45 #endif
46 
OS2Loop(intf_thread_t * pIntf)47 OS2Loop::OS2Loop( 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_ENTER] = KEY_ENTER;
63     virtKeyToVlcKey[VK_NEWLINE] = KEY_ENTER;
64     virtKeyToVlcKey[VK_SPACE] = ' ';
65     virtKeyToVlcKey[VK_ESC] = KEY_ESC;
66     virtKeyToVlcKey[VK_LEFT] = KEY_LEFT;
67     virtKeyToVlcKey[VK_RIGHT] = KEY_RIGHT;
68     virtKeyToVlcKey[VK_UP] = KEY_UP;
69     virtKeyToVlcKey[VK_DOWN] = KEY_DOWN;
70     virtKeyToVlcKey[VK_INSERT] = KEY_INSERT;
71     virtKeyToVlcKey[VK_DELETE] = KEY_DELETE;
72     virtKeyToVlcKey[VK_HOME] = KEY_HOME;
73     virtKeyToVlcKey[VK_END] = KEY_END;
74     virtKeyToVlcKey[VK_PAGEUP] = KEY_PAGEUP;
75     virtKeyToVlcKey[VK_PAGEDOWN] = KEY_PAGEDOWN;
76 }
77 
78 
~OS2Loop()79 OS2Loop::~OS2Loop()
80 {
81 }
82 
83 
instance(intf_thread_t * pIntf)84 OSLoop *OS2Loop::instance( intf_thread_t *pIntf )
85 {
86     if( pIntf->p_sys->p_osLoop == NULL )
87     {
88         OSLoop *pOsLoop = new OS2Loop( pIntf );
89         pIntf->p_sys->p_osLoop = pOsLoop;
90     }
91     return pIntf->p_sys->p_osLoop;
92 }
93 
94 
destroy(intf_thread_t * pIntf)95 void OS2Loop::destroy( intf_thread_t *pIntf )
96 {
97     delete pIntf->p_sys->p_osLoop;
98     pIntf->p_sys->p_osLoop = NULL;
99 }
100 
101 
run()102 void OS2Loop::run()
103 {
104     QMSG qm;
105 
106     // Compute windows message list
107     while( WinGetMsg( 0, &qm, NULLHANDLE, 0, 0 ))
108         WinDispatchMsg( 0, &qm );
109 }
110 
111 
processEvent(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)112 MRESULT EXPENTRY OS2Loop::processEvent( HWND hwnd, ULONG msg,
113                                         MPARAM mp1, MPARAM mp2 )
114 {
115     OS2Factory *pFactory =
116         (OS2Factory*)OS2Factory::instance( getIntf() );
117     GenericWindow *pWin = pFactory->m_windowMap[hwnd];
118 
119     // To invert Y
120     RECTL rcl;
121     WinQueryWindowRect( hwnd, &rcl );
122 
123     GenericWindow &win = *pWin;
124     switch( msg )
125     {
126         case WM_PAINT:
127         {
128             HPS   hps;
129             RECTL rclPaint;
130 
131             hps = WinBeginPaint( hwnd, NULLHANDLE, &rclPaint );
132             EvtRefresh evt( getIntf(),
133                             rclPaint.xLeft,
134                             // Find top and invert it
135                             ( rcl.yTop - 1 ) - ( rclPaint.yTop - 1 ),
136                             rclPaint.xRight - rclPaint.xLeft + 1,
137                             rclPaint.yTop - rclPaint.yBottom + 1 );
138             win.processEvent( evt );
139             WinEndPaint( hps );
140             return 0;
141         }
142         case WM_COMMAND:
143         {
144             EvtMenu evt( getIntf(), SHORT1FROMMP( mp1 ));
145             win.processEvent( evt );
146             return 0;
147         }
148         case WM_MOUSEMOVE:
149         {
150             pFactory->changeCursor( pFactory->getCursorType());
151 
152             // Compute the absolute position of the mouse
153             POINTL ptl;
154             WinQueryPointerPos( HWND_DESKTOP, &ptl );
155             int x = ptl.x;
156             int y = ( pFactory->getScreenHeight() - 1 ) - ptl.y;
157             EvtMotion evt( getIntf(), x, y );
158             win.processEvent( evt );
159 
160             return MRFROMLONG( TRUE );
161         }
162         case WM_MOUSELEAVE:
163         {
164             EvtLeave evt( getIntf() );
165             win.processEvent( evt );
166             return MRFROMLONG( TRUE );
167         }
168         case WM_BUTTON1DOWN:
169         {
170             WinSetCapture( HWND_DESKTOP, hwnd );
171             EvtMouse evt( getIntf(), GET_X_MP( mp1 ),
172                           GET_Y_MP( mp1 ), EvtMouse::kLeft,
173                           EvtMouse::kDown, getMod( mp2 ) );
174             win.processEvent( evt );
175             return MRFROMLONG( TRUE );
176         }
177         case WM_BUTTON2DOWN:
178         {
179             WinSetCapture( HWND_DESKTOP, hwnd );
180             EvtMouse evt( getIntf(), GET_X_MP( mp1 ),
181                           GET_Y_MP( mp1 ), EvtMouse::kRight,
182                           EvtMouse::kDown, getMod( mp2 ) );
183             win.processEvent( evt );
184             return MRFROMLONG( TRUE );
185         }
186         case WM_BUTTON1UP:
187         {
188             WinSetCapture( HWND_DESKTOP, NULLHANDLE );
189             EvtMouse evt( getIntf(), GET_X_MP( mp1 ),
190                           GET_Y_MP( mp1 ), EvtMouse::kLeft,
191                           EvtMouse::kUp, getMod( mp2 ) );
192             win.processEvent( evt );
193             return MRFROMLONG( TRUE );
194         }
195         case WM_BUTTON2UP:
196         {
197             WinSetCapture( HWND_DESKTOP, NULLHANDLE );
198             EvtMouse evt( getIntf(), GET_X_MP( mp1 ),
199                           GET_Y_MP( mp1 ), EvtMouse::kRight,
200                           EvtMouse::kUp, getMod( mp2 ) );
201             win.processEvent( evt );
202             return MRFROMLONG( TRUE );
203         }
204         case WM_BUTTON1DBLCLK:
205         {
206             WinSetCapture( HWND_DESKTOP, NULLHANDLE );
207             EvtMouse evt( getIntf(), GET_X_MP( mp1 ),
208                           GET_Y_MP( mp1 ), EvtMouse::kLeft,
209                           EvtMouse::kDblClick, getMod( mp2 ) );
210             win.processEvent( evt );
211             return MRFROMLONG( TRUE );
212         }
213         case WM_BUTTON2DBLCLK:
214         {
215             WinSetCapture( HWND_DESKTOP, NULLHANDLE );
216             EvtMouse evt( getIntf(), GET_X_MP( mp1 ),
217                           GET_Y_MP( mp1 ), EvtMouse::kRight,
218                           EvtMouse::kDblClick, getMod( mp2 ) );
219             win.processEvent( evt );
220             return MRFROMLONG( TRUE );
221         }
222         case WM_CHAR:
223         {
224             // The key events are first processed here and not translated
225             // into WM_CHAR events because we need to know the status of
226             // the modifier keys.
227 
228             USHORT fsFlags = SHORT1FROMMP( mp1 );
229             USHORT usCh    = SHORT1FROMMP( mp2 );
230             USHORT usVk    = SHORT2FROMMP( mp2 );
231 
232             // Get VLC key code from the virtual key code
233             int key = ( fsFlags & KC_VIRTUALKEY ) ?
234                             virtKeyToVlcKey[ usVk ] : 0;
235             if( !key )
236             {
237                 // This appears to be a "normal" (ascii) key
238                 key = tolower( usCh );
239             }
240 
241             if( key )
242             {
243                 // Get the modifier
244                 int mod = 0;
245                 if( fsFlags & KC_CTRL )
246                 {
247                     mod |= EvtInput::kModCtrl;
248                 }
249                 if( fsFlags & KC_SHIFT )
250                 {
251                     mod |= EvtInput::kModShift;
252                 }
253                 if( fsFlags & KC_ALT )
254                 {
255                     mod |= EvtInput::kModAlt;
256                 }
257 
258                 // Get the state
259                 EvtKey::ActionType_t state;
260                 if( fsFlags & KC_KEYUP )
261                 {
262                     state = EvtKey::kUp;
263                 }
264                 else
265                 {
266                     state = EvtKey::kDown;
267                 }
268 
269                 EvtKey evt( getIntf(), key, state, mod );
270                 win.processEvent( evt );
271             }
272             return MRFROMLONG( TRUE );
273         }
274         default:
275             break;
276     }
277     return WinDefWindowProc( hwnd, msg, mp1, mp2 );
278 }
279 
280 
getMod(MPARAM mp) const281 int OS2Loop::getMod( MPARAM mp ) const
282 {
283     int mod = EvtInput::kModNone;
284     if( SHORT2FROMMP( mp ) & KC_CTRL )
285         mod |= EvtInput::kModCtrl;
286     if( SHORT2FROMMP( mp ) & KC_SHIFT )
287         mod |= EvtInput::kModShift;
288 
289     return mod;
290 }
291 
292 
exit()293 void OS2Loop::exit()
294 {
295     WinPostQueueMsg( HMQ_CURRENT, WM_QUIT, 0, 0 );
296 }
297 
298 #endif
299