00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef X11_SKINS
00026
00027 #include <X11/keysym.h>
00028 #include "x11_loop.hpp"
00029 #include "x11_display.hpp"
00030 #include "x11_dragdrop.hpp"
00031 #include "x11_factory.hpp"
00032 #include "x11_timer.hpp"
00033 #include "../src/generic_window.hpp"
00034 #include "../src/theme.hpp"
00035 #include "../src/window_manager.hpp"
00036 #include "../events/evt_focus.hpp"
00037 #include "../events/evt_key.hpp"
00038 #include "../events/evt_mouse.hpp"
00039 #include "../events/evt_motion.hpp"
00040 #include "../events/evt_leave.hpp"
00041 #include "../events/evt_refresh.hpp"
00042 #include "../events/evt_scroll.hpp"
00043 #include "../commands/async_queue.hpp"
00044 #include "../utils/var_bool.hpp"
00045 #include "vlc_keys.h"
00046
00047
00048
00049 int X11Loop::m_dblClickDelay = 400000;
00050
00051
00052 X11Loop::X11Loop( intf_thread_t *pIntf, X11Display &rDisplay ):
00053 OSLoop( pIntf ), m_rDisplay( rDisplay ), m_exit( false ),
00054 m_lastClickTime( 0 ), m_lastClickPosX( 0 ), m_lastClickPosY( 0 )
00055 {
00056
00057 keysymToVlcKey[XK_F1] = KEY_F1;
00058 keysymToVlcKey[XK_F2] = KEY_F2;
00059 keysymToVlcKey[XK_F3] = KEY_F3;
00060 keysymToVlcKey[XK_F4] = KEY_F4;
00061 keysymToVlcKey[XK_F5] = KEY_F5;
00062 keysymToVlcKey[XK_F6] = KEY_F6;
00063 keysymToVlcKey[XK_F7] = KEY_F7;
00064 keysymToVlcKey[XK_F8] = KEY_F8;
00065 keysymToVlcKey[XK_F9] = KEY_F9;
00066 keysymToVlcKey[XK_F10] = KEY_F10;
00067 keysymToVlcKey[XK_F11] = KEY_F11;
00068 keysymToVlcKey[XK_F12] = KEY_F12;
00069 keysymToVlcKey[XK_Return] = KEY_ENTER;
00070 keysymToVlcKey[XK_space] = KEY_SPACE;
00071 keysymToVlcKey[XK_Escape] = KEY_ESC;
00072 keysymToVlcKey[XK_Left] = KEY_LEFT;
00073 keysymToVlcKey[XK_Right] = KEY_RIGHT;
00074 keysymToVlcKey[XK_Up] = KEY_UP;
00075 keysymToVlcKey[XK_Down] = KEY_DOWN;
00076 keysymToVlcKey[XK_Home] = KEY_HOME;
00077 keysymToVlcKey[XK_End] = KEY_END;
00078 keysymToVlcKey[XK_Prior] = KEY_PAGEUP;
00079 keysymToVlcKey[XK_Next] = KEY_PAGEDOWN;
00080 }
00081
00082
00083 X11Loop::~X11Loop()
00084 {
00085 }
00086
00087
00088 OSLoop *X11Loop::instance( intf_thread_t *pIntf, X11Display &rDisplay )
00089 {
00090 if( pIntf->p_sys->p_osLoop == NULL )
00091 {
00092 OSLoop *pOsLoop = new X11Loop( pIntf, rDisplay );
00093 pIntf->p_sys->p_osLoop = pOsLoop;
00094 }
00095 return pIntf->p_sys->p_osLoop;
00096 }
00097
00098
00099 void X11Loop::destroy( intf_thread_t *pIntf )
00100 {
00101 if( pIntf->p_sys->p_osLoop )
00102 {
00103 delete pIntf->p_sys->p_osLoop;
00104 pIntf->p_sys->p_osLoop = NULL;
00105 }
00106 }
00107
00108
00109 void X11Loop::run()
00110 {
00111 OSFactory *pOsFactory = OSFactory::instance( getIntf() );
00112 X11TimerLoop *pTimerLoop = ((X11Factory*)pOsFactory)->getTimerLoop();
00113
00114
00115 while( ! m_exit )
00116 {
00117 int nPending;
00118
00119
00120 nPending = XPending( XDISPLAY );
00121
00122 while( ! m_exit && nPending > 0 )
00123 {
00124
00125 handleX11Event();
00126
00127
00128 nPending = XPending( XDISPLAY );
00129 }
00130
00131
00132
00133 if( !m_exit )
00134 {
00135 pTimerLoop->waitNextTimer();
00136 }
00137 }
00138 }
00139
00140
00141 void X11Loop::exit()
00142 {
00143 m_exit = true;
00144 }
00145
00146
00147 void X11Loop::handleX11Event()
00148 {
00149 XEvent event;
00150 OSFactory *pOsFactory = OSFactory::instance( getIntf() );
00151
00152
00153 XNextEvent( XDISPLAY, &event );
00154
00155 if( event.xany.window == m_rDisplay.getMainWindow() )
00156 {
00157 if( event.type == MapNotify )
00158 {
00159
00160
00161 Theme *pTheme = getIntf()->p_sys->p_theme;
00162 if( pTheme )
00163 {
00164 pTheme->getWindowManager().synchVisibility();
00165 }
00166 }
00167 return;
00168 }
00169
00170
00171 GenericWindow *pWin =
00172 ((X11Factory*)pOsFactory)->m_windowMap[event.xany.window];
00173
00174 if( !pWin )
00175 {
00176 msg_Dbg( getIntf(), "No associated generic window !!" );
00177 return;
00178 }
00179
00180
00181 switch( event.type )
00182 {
00183 case Expose:
00184 {
00185 EvtRefresh evt( getIntf(), event.xexpose.x,
00186 event.xexpose.y, event.xexpose.width,
00187 event.xexpose.height );
00188 pWin->processEvent( evt );
00189 break;
00190 }
00191 case FocusIn:
00192 {
00193 EvtFocus evt( getIntf(), true );
00194 pWin->processEvent( evt );
00195 break;
00196 }
00197 case FocusOut:
00198 {
00199 EvtFocus evt( getIntf(), false );
00200 pWin->processEvent( evt );
00201 break;
00202 }
00203
00204 case MotionNotify:
00205 {
00206
00207
00208 int x, y;
00209 pOsFactory->getMousePos( x, y );
00210 EvtMotion evt( getIntf(), x, y );
00211 pWin->processEvent( evt );
00212 break;
00213 }
00214 case LeaveNotify:
00215 {
00216 EvtLeave evt( getIntf() );
00217 pWin->processEvent( evt );
00218 break;
00219 }
00220 case ButtonPress:
00221 case ButtonRelease:
00222 {
00223 EvtMouse::ActionType_t action = EvtMouse::kDown;
00224 switch( event.type )
00225 {
00226 case ButtonPress:
00227 action = EvtMouse::kDown;
00228 break;
00229 case ButtonRelease:
00230 action = EvtMouse::kUp;
00231 break;
00232 }
00233
00234
00235 int mod = EvtInput::kModNone;
00236 if( event.xbutton.state & Mod1Mask )
00237 {
00238 mod |= EvtInput::kModAlt;
00239 }
00240 if( event.xbutton.state & ControlMask )
00241 {
00242 mod |= EvtInput::kModCtrl;
00243 }
00244 if( event.xbutton.state & ShiftMask )
00245 {
00246 mod |= EvtInput::kModShift;
00247 }
00248
00249
00250 if( event.type == ButtonPress &&
00251 event.xbutton.button == 1 )
00252 {
00253 mtime_t time = mdate();
00254 int x, y;
00255 pOsFactory->getMousePos( x, y );
00256 if( time - m_lastClickTime < m_dblClickDelay &&
00257 x == m_lastClickPosX && y == m_lastClickPosY )
00258 {
00259 m_lastClickTime = 0;
00260 action = EvtMouse::kDblClick;
00261 }
00262 else
00263 {
00264 m_lastClickTime = time;
00265 m_lastClickPosX = x;
00266 m_lastClickPosY = y;
00267 }
00268 }
00269
00270 switch( event.xbutton.button )
00271 {
00272 case 1:
00273 {
00274 EvtMouse evt( getIntf(), event.xbutton.x,
00275 event.xbutton.y, EvtMouse::kLeft,
00276 action, mod );
00277 pWin->processEvent( evt );
00278 break;
00279 }
00280 case 2:
00281 {
00282 EvtMouse evt( getIntf(), event.xbutton.x,
00283 event.xbutton.y, EvtMouse::kMiddle,
00284 action, mod );
00285 pWin->processEvent( evt );
00286 break;
00287 }
00288 case 3:
00289 {
00290 EvtMouse evt( getIntf(), event.xbutton.x,
00291 event.xbutton.y, EvtMouse::kRight,
00292 action, mod );
00293 pWin->processEvent( evt );
00294 break;
00295 }
00296 case 4:
00297 {
00298
00299 EvtScroll evt( getIntf(), event.xbutton.x,
00300 event.xbutton.y, EvtScroll::kUp,
00301 mod );
00302 pWin->processEvent( evt );
00303 break;
00304 }
00305 case 5:
00306 {
00307
00308 EvtScroll evt( getIntf(), event.xbutton.x,
00309 event.xbutton.y, EvtScroll::kDown,
00310 mod );
00311 pWin->processEvent( evt );
00312 break;
00313 }
00314 }
00315 break;
00316 }
00317 case KeyPress:
00318 case KeyRelease:
00319 {
00320 EvtKey::ActionType_t action = EvtKey::kDown;
00321 int mod = EvtInput::kModNone;
00322
00323 if( event.xkey.state & Mod1Mask )
00324 {
00325 mod |= EvtInput::kModAlt;
00326 }
00327 if( event.xkey.state & ControlMask )
00328 {
00329 mod |= EvtInput::kModCtrl;
00330 }
00331 if( event.xkey.state & ShiftMask )
00332 {
00333 mod |= EvtInput::kModShift;
00334 }
00335
00336
00337 KeySym keysym = XLookupKeysym( &event.xkey, 0 );
00338
00339
00340 int key = keysymToVlcKey[keysym];
00341 if( !key )
00342 {
00343
00344 key = keysym;
00345 }
00346
00347 switch( event.type )
00348 {
00349 case KeyPress:
00350 action = EvtKey::kDown;
00351 break;
00352 case KeyRelease:
00353 action = EvtKey::kUp;
00354 break;
00355 }
00356 EvtKey evt( getIntf(), key, action, mod );
00357 pWin->processEvent( evt );
00358 break;
00359 }
00360
00361 case ClientMessage:
00362 {
00363
00364 string type = XGetAtomName( XDISPLAY, event.xclient.message_type );
00365
00366
00367 X11DragDrop *pDnd =
00368 ((X11Factory*)pOsFactory)->m_dndMap[event.xany.window];
00369 if( !pDnd )
00370 {
00371 msg_Err( getIntf(), "No associated D&D object !!" );
00372 return;
00373 }
00374
00375 if( type == "XdndEnter" )
00376 {
00377 pDnd->dndEnter( event.xclient.data.l );
00378 }
00379 else if( type == "XdndPosition" )
00380 {
00381 pDnd->dndPosition( event.xclient.data.l );
00382 }
00383 else if( type == "XdndLeave" )
00384 {
00385 pDnd->dndLeave( event.xclient.data.l );
00386 }
00387 else if( type == "XdndDrop" )
00388 {
00389 pDnd->dndDrop( event.xclient.data.l );
00390 }
00391 break;
00392 }
00393 }
00394 }
00395
00396 #endif