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

top_window.cpp

00001 /*****************************************************************************
00002  * top_window.cpp
00003  *****************************************************************************
00004  * Copyright (C) 2003 the VideoLAN team
00005  * $Id: top_window.cpp 12912 2005-10-22 11:57:29Z asmax $
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 #include "top_window.hpp"
00026 #include "generic_layout.hpp"
00027 #include "os_graphics.hpp"
00028 #include "os_window.hpp"
00029 #include "os_factory.hpp"
00030 #include "theme.hpp"
00031 #include "var_manager.hpp"
00032 #include "../commands/cmd_on_top.hpp"
00033 #include "../commands/cmd_dialogs.hpp"
00034 #include "../controls/ctrl_generic.hpp"
00035 #include "../events/evt_refresh.hpp"
00036 #include "../events/evt_enter.hpp"
00037 #include "../events/evt_focus.hpp"
00038 #include "../events/evt_leave.hpp"
00039 #include "../events/evt_motion.hpp"
00040 #include "../events/evt_mouse.hpp"
00041 #include "../events/evt_key.hpp"
00042 #include "../events/evt_special.hpp"
00043 #include "../events/evt_scroll.hpp"
00044 #include "../utils/position.hpp"
00045 #include "../utils/ustring.hpp"
00046 
00047 #include <vlc_keys.h>
00048 
00049 
00050 TopWindow::TopWindow( intf_thread_t *pIntf, int left, int top,
00051                       WindowManager &rWindowManager,
00052                       bool dragDrop, bool playOnDrop, bool visible ):
00053     GenericWindow( pIntf, left, top, dragDrop, playOnDrop, NULL ),
00054     m_visible( visible ), m_rWindowManager( rWindowManager ),
00055     m_pActiveLayout( NULL ), m_pLastHitControl( NULL ),
00056     m_pCapturingControl( NULL ), m_pFocusControl( NULL ), m_currModifier( 0 )
00057 {
00058     // Register as a moving window
00059     m_rWindowManager.registerWindow( *this );
00060 }
00061 
00062 
00063 TopWindow::~TopWindow()
00064 {
00065     // Unregister from the window manager
00066     m_rWindowManager.unregisterWindow( *this );
00067 }
00068 
00069 
00070 void TopWindow::processEvent( EvtRefresh &rEvtRefresh )
00071 {
00072     // We override the behaviour defined in GenericWindow, because we don't
00073     // want to draw on a video control!
00074     if( m_pActiveLayout == NULL )
00075     {
00076         GenericWindow::processEvent( rEvtRefresh );
00077     }
00078     else
00079     {
00080         m_pActiveLayout->refreshRect( rEvtRefresh.getXStart(),
00081                                       rEvtRefresh.getYStart(),
00082                                       rEvtRefresh.getWidth(),
00083                                       rEvtRefresh.getHeight() );
00084     }
00085 }
00086 
00087 
00088 void TopWindow::processEvent( EvtFocus &rEvtFocus )
00089 {
00090 //    fprintf(stderr, rEvtFocus.getAsString().c_str()) ;
00091 }
00092 
00093 
00094 void TopWindow::processEvent( EvtMotion &rEvtMotion )
00095 {
00096     // New control hit by the mouse
00097     CtrlGeneric *pNewHitControl =
00098         findHitControl( rEvtMotion.getXPos() - getLeft(),
00099                         rEvtMotion.getYPos() - getTop() );
00100 
00101     setLastHit( pNewHitControl );
00102 
00104     VarManager *pVarManager = VarManager::instance( getIntf() );
00105     if( pNewHitControl )
00106     {
00107         pVarManager->getHelpText().set( pNewHitControl->getHelpText() );
00108     }
00109 
00110     // Send a motion event to the hit control, or to the control
00111     // that captured the mouse, if any
00112     CtrlGeneric *pActiveControl = pNewHitControl;
00113     if( m_pCapturingControl )
00114     {
00115         pActiveControl = m_pCapturingControl;
00116     }
00117     if( pActiveControl )
00118     {
00119         // Compute the coordinates relative to the window
00120         int xPos = rEvtMotion.getXPos() - getLeft();
00121         int yPos = rEvtMotion.getYPos() - getTop();
00122         // Send a motion event
00123         EvtMotion evt( getIntf(), xPos, yPos );
00124         pActiveControl->handleEvent( evt );
00125     }
00126 }
00127 
00128 
00129 void TopWindow::processEvent( EvtLeave &rEvtLeave )
00130 {
00131     // No more hit control
00132     setLastHit( NULL );
00133 
00134     if( !m_pCapturingControl )
00135     {
00136         m_rWindowManager.hideTooltip();
00137     }
00138 }
00139 
00140 
00141 void TopWindow::processEvent( EvtMouse &rEvtMouse )
00142 {
00143     // Get the control hit by the mouse
00144     CtrlGeneric *pNewHitControl = findHitControl( rEvtMouse.getXPos(),
00145                                                   rEvtMouse.getYPos() );
00146     setLastHit( pNewHitControl );
00147 
00148     // Change the focused control
00149     if( rEvtMouse.getAction() == EvtMouse::kDown )
00150     {
00151         // Raise the window
00152         m_rWindowManager.raise( *this );
00153 
00154         if( pNewHitControl && pNewHitControl->isFocusable() )
00155         {
00156             // If a new control gains the focus, the previous one loses it
00157             if( m_pFocusControl && m_pFocusControl != pNewHitControl )
00158             {
00159                 EvtFocus evt( getIntf(), false );
00160                 m_pFocusControl->handleEvent( evt );
00161             }
00162             if( pNewHitControl != m_pFocusControl )
00163             {
00164                 m_pFocusControl = pNewHitControl;
00165                 EvtFocus evt( getIntf(), false );
00166                 pNewHitControl->handleEvent( evt );
00167             }
00168         }
00169         else if( m_pFocusControl )
00170         {
00171             // The previous control loses the focus
00172             EvtFocus evt( getIntf(), false );
00173             m_pFocusControl->handleEvent( evt );
00174             m_pFocusControl = NULL;
00175         }
00176     }
00177 
00178     // Send a mouse event to the hit control, or to the control
00179     // that captured the mouse, if any
00180     CtrlGeneric *pActiveControl = pNewHitControl;
00181     if( m_pCapturingControl )
00182     {
00183         pActiveControl = m_pCapturingControl;
00184     }
00185     if( pActiveControl )
00186     {
00187         pActiveControl->handleEvent( rEvtMouse );
00188     }
00189 }
00190 
00191 
00192 void TopWindow::processEvent( EvtKey &rEvtKey )
00193 {
00194     // Forward the event to the focused control, if any
00195     if( m_pFocusControl )
00196     {
00197         m_pFocusControl->handleEvent( rEvtKey );
00198         return;
00199     }
00200 
00201     // Only do the action when the key is down
00202     if( rEvtKey.getAsString().find( "key:down") != string::npos )
00203     {
00204         //XXX not to be hardcoded!
00205         // Ctrl-S = Change skin
00206         if( (rEvtKey.getMod() & EvtInput::kModCtrl) &&
00207             rEvtKey.getKey() == 's' )
00208         {
00209             CmdDlgChangeSkin cmd( getIntf() );
00210             cmd.execute();
00211             return;
00212         }
00213 
00214         //XXX not to be hardcoded!
00215         // Ctrl-T = Toggle on top
00216         if( (rEvtKey.getMod() & EvtInput::kModCtrl) &&
00217             rEvtKey.getKey() == 't' )
00218         {
00219             CmdOnTop cmd( getIntf() );
00220             cmd.execute();
00221             return;
00222         }
00223 
00224         vlc_value_t val;
00225         // Set the key
00226         val.i_int = rEvtKey.getKey();
00227         // Set the modifiers
00228         if( rEvtKey.getMod() & EvtInput::kModAlt )
00229         {
00230             val.i_int |= KEY_MODIFIER_ALT;
00231         }
00232         if( rEvtKey.getMod() & EvtInput::kModCtrl )
00233         {
00234             val.i_int |= KEY_MODIFIER_CTRL;
00235         }
00236         if( rEvtKey.getMod() & EvtInput::kModShift )
00237         {
00238             val.i_int |= KEY_MODIFIER_SHIFT;
00239         }
00240 
00241         var_Set( getIntf()->p_vlc, "key-pressed", val );
00242     }
00243 
00244     // Always store the modifier, which can be needed for scroll events
00245     m_currModifier = rEvtKey.getMod();
00246 }
00247 
00248 
00249 void TopWindow::processEvent( EvtScroll &rEvtScroll )
00250 {
00251     // Raise the windows
00252     raise();
00253 
00254     // Get the control hit by the mouse
00255     CtrlGeneric *pNewHitControl = findHitControl( rEvtScroll.getXPos(),
00256                                                   rEvtScroll.getYPos());
00257     setLastHit( pNewHitControl );
00258 
00259     // Send a mouse event to the hit control, or to the control
00260     // that captured the mouse, if any
00261     CtrlGeneric *pActiveControl = pNewHitControl;
00262 
00263     if( m_pCapturingControl )
00264     {
00265         pActiveControl = m_pCapturingControl;
00266     }
00267     if( pActiveControl )
00268     {
00269         pActiveControl->handleEvent( rEvtScroll );
00270     }
00271     else
00272     {
00273         // Treat the scroll event as a hotkey
00274         vlc_value_t val;
00275         if( rEvtScroll.getDirection() == EvtScroll::kUp )
00276         {
00277             val.i_int = KEY_MOUSEWHEELUP;
00278         }
00279         else
00280         {
00281             val.i_int = KEY_MOUSEWHEELDOWN;
00282         }
00283         // Add the modifiers
00284         val.i_int |= m_currModifier;
00285 
00286         var_Set( getIntf()->p_vlc, "key-pressed", val );
00287     }
00288 }
00289 
00290 
00291 void TopWindow::forwardEvent( EvtGeneric &rEvt, CtrlGeneric &rCtrl )
00292 {
00293     // XXX: We should do some checks here
00294     rCtrl.handleEvent( rEvt );
00295 }
00296 
00297 
00298 void TopWindow::refresh( int left, int top, int width, int height )
00299 {
00300     if( m_pActiveLayout )
00301     {
00302         m_pActiveLayout->getImage()->copyToWindow( *getOSWindow(), left, top,
00303                                                    width, height, left, top );
00304     }
00305 }
00306 
00307 
00308 void TopWindow::setActiveLayout( GenericLayout *pLayout )
00309 {
00310     pLayout->setWindow( this );
00311     m_pActiveLayout = pLayout;
00312     // Get the size of the layout and resize the window
00313     resize( pLayout->getWidth(), pLayout->getHeight() );
00314     updateShape();
00315     pLayout->refreshAll();
00316 }
00317 
00318 
00319 const GenericLayout& TopWindow::getActiveLayout() const
00320 {
00321     return *m_pActiveLayout;
00322 }
00323 
00324 
00325 void TopWindow::innerShow()
00326 {
00327     // First, refresh the layout and update the shape of the window
00328     if( m_pActiveLayout )
00329     {
00330         updateShape();
00331         m_pActiveLayout->refreshAll();
00332     }
00333     // Show the window
00334     GenericWindow::innerShow();
00335 }
00336 
00337  
00338 void TopWindow::updateShape()
00339 {
00340     // Set the shape of the window
00341     if( m_pActiveLayout )
00342     {
00343         OSGraphics *pImage = m_pActiveLayout->getImage();
00344         if( pImage )
00345         {
00346             pImage->applyMaskToWindow( *getOSWindow() );
00347         }
00348     }
00349 }
00350 
00351 
00352 void TopWindow::onControlCapture( const CtrlGeneric &rCtrl )
00353 {
00354     // Set the capturing control
00355     m_pCapturingControl = (CtrlGeneric*) &rCtrl;
00356 }
00357 
00358 
00359 void TopWindow::onControlRelease( const CtrlGeneric &rCtrl )
00360 {
00361     // Release the capturing control
00362     if( m_pCapturingControl == &rCtrl )
00363     {
00364         m_pCapturingControl = NULL;
00365     }
00366     else
00367     {
00368         msg_Dbg( getIntf(), "Control had not captured the mouse" );
00369     }
00370 
00371     // Send an enter event to the control under the mouse, if it doesn't
00372     // have received it yet
00373     if( m_pLastHitControl && m_pLastHitControl != &rCtrl )
00374     {
00375         EvtEnter evt( getIntf() );
00376         m_pLastHitControl->handleEvent( evt );
00377 
00378         // Show the tooltip
00379         m_rWindowManager.hideTooltip();
00380         UString tipText = m_pLastHitControl->getTooltipText();
00381         if( tipText.length() > 0 )
00382         {
00383             // Set the tooltip text variable
00384             VarManager *pVarManager = VarManager::instance( getIntf() );
00385             pVarManager->getTooltipText().set( tipText );
00386             m_rWindowManager.showTooltip();
00387         }
00388     }
00389 }
00390 
00391 
00392 void TopWindow::onTooltipChange( const CtrlGeneric &rCtrl )
00393 {
00394     // Check that the control is the active one
00395     if( m_pLastHitControl && m_pLastHitControl == &rCtrl )
00396     {
00397         // Set the tooltip text variable
00398         VarManager *pVarManager = VarManager::instance( getIntf() );
00399         pVarManager->getTooltipText().set( rCtrl.getTooltipText() );
00400     }
00401 }
00402 
00403 
00404 CtrlGeneric *TopWindow::findHitControl( int xPos, int yPos )
00405 {
00406     if( m_pActiveLayout == NULL )
00407     {
00408         return NULL;
00409     }
00410 
00411     // Get the controls in the active layout
00412     const list<LayeredControl> &ctrlList = m_pActiveLayout->getControlList();
00413     list<LayeredControl>::const_reverse_iterator iter;
00414 
00415     // New control hit by the mouse
00416     CtrlGeneric *pNewHitControl = NULL;
00417 
00418     // Loop on the control list to find the uppest hit control
00419     for( iter = ctrlList.rbegin(); iter != ctrlList.rend(); iter++ )
00420     {
00421         // Get the position of the control in the layout
00422         const Position *pos = (*iter).m_pControl->getPosition();
00423         if( pos != NULL )
00424         {
00425             // Compute the coordinates of the mouse relative to the control
00426             int xRel = xPos - pos->getLeft();
00427             int yRel = yPos - pos->getTop();
00428 
00429             CtrlGeneric *pCtrl = (*iter).m_pControl;
00430             // Control hit ?
00431             if( pCtrl->isVisible() && pCtrl->mouseOver( xRel, yRel ) )
00432             {
00433                 pNewHitControl = (*iter).m_pControl;
00434                 break;
00435             }
00436         }
00437         else
00438         {
00439             msg_Dbg( getIntf(), "Control at NULL position" );
00440         }
00441     }
00442 
00443     // If the hit control has just been entered, send it an enter event
00444     if( pNewHitControl && (pNewHitControl != m_pLastHitControl) )
00445     {
00446         // Don't send the event if another control captured the mouse
00447         if( !m_pCapturingControl || (m_pCapturingControl == pNewHitControl ) )
00448         {
00449             EvtEnter evt( getIntf() );
00450             pNewHitControl->handleEvent( evt );
00451 
00452             if( !m_pCapturingControl )
00453             {
00454                 // Show the tooltip
00455                 m_rWindowManager.hideTooltip();
00456                 UString tipText = pNewHitControl->getTooltipText();
00457                 if( tipText.length() > 0 )
00458                 {
00459                     // Set the tooltip text variable
00460                     VarManager *pVarManager = VarManager::instance( getIntf() );
00461                     pVarManager->getTooltipText().set( tipText );
00462                     m_rWindowManager.showTooltip();
00463                 }
00464             }
00465         }
00466     }
00467 
00468     return pNewHitControl;
00469 }
00470 
00471 
00472 
00473 void TopWindow::setLastHit( CtrlGeneric *pNewHitControl )
00474 {
00475     // Send a leave event to the left control
00476     if( m_pLastHitControl && (pNewHitControl != m_pLastHitControl) )
00477     {
00478         // Don't send the event if another control captured the mouse
00479         if( !m_pCapturingControl || (m_pCapturingControl == m_pLastHitControl))
00480         {
00481             EvtLeave evt( getIntf() );
00482             m_pLastHitControl->handleEvent( evt );
00483         }
00484     }
00485 
00486     m_pLastHitControl = pNewHitControl;
00487 }
00488 

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