Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

x11_loop.cpp

00001 /*****************************************************************************
00002  * x11_loop.cpp
00003  *****************************************************************************
00004  * Copyright (C) 2003 the VideoLAN team
00005  * $Id: x11_loop.cpp 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Cyril Deguet     <[email protected]>
00008  *          Olivier Teulière <[email protected]>
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
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 // Maximum interval between clicks for a double-click (in microsec)
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     // Initialize the key map
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     // Main event loop
00115     while( ! m_exit )
00116     {
00117         int nPending;
00118 
00119         // Number of pending events in the queue
00120         nPending = XPending( XDISPLAY );
00121 
00122         while( ! m_exit && nPending > 0 )
00123         {
00124             // Handle the next X11 event
00125             handleX11Event();
00126 
00127             // Number of pending events in the queue
00128             nPending = XPending( XDISPLAY );
00129         }
00130 
00131         // Wait for the next timer and execute it
00132         // The sleep is interrupted if an X11 event is received
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     // Look for the next event in the queue
00153     XNextEvent( XDISPLAY, &event );
00154 
00155     if( event.xany.window == m_rDisplay.getMainWindow() )
00156     {
00157         if( event.type == MapNotify )
00158         {
00159             // When the "parent" window is mapped, show all the visible
00160             // windows, as it is not automatic, unfortunately
00161             Theme *pTheme = getIntf()->p_sys->p_theme;
00162             if( pTheme )
00163             {
00164                 pTheme->getWindowManager().synchVisibility();
00165             }
00166         }
00167         return;
00168     }
00169 
00170     // Find the window to which the event is sent
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     // Send the right event object to the window
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             // Don't trust the position in the event, it is
00207             // out of date. Get the actual current position instead
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             // Get the modifiers
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             // Check for double clicks
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                     // Scroll up
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                     // Scroll down
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             // Get the modifiers
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             // Take the first keysym = lower case character
00337             KeySym keysym = XLookupKeysym( &event.xkey, 0 );
00338 
00339             // Get VLC key code from the keysym
00340             int key = keysymToVlcKey[keysym];
00341             if( !key )
00342             {
00343                 // Normal key
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             // Get the message type
00364             string type = XGetAtomName( XDISPLAY, event.xclient.message_type );
00365 
00366             // Find the DnD object for this window
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

Generated on Tue Dec 20 10:14:44 2005 for vlc-0.8.4a by  doxygen 1.4.2