top_window.cpp
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:13k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * top_window.cpp
  3.  *****************************************************************************
  4.  * Copyright (C) 2003 VideoLAN
  5.  * $Id: top_window.cpp 8524 2004-08-25 21:32:15Z ipkiss $
  6.  *
  7.  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
  8.  *          Olivier Teuli鑢e <ipkiss@via.ecp.fr>
  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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. #include "top_window.hpp"
  25. #include "generic_layout.hpp"
  26. #include "os_graphics.hpp"
  27. #include "os_window.hpp"
  28. #include "os_factory.hpp"
  29. #include "theme.hpp"
  30. #include "var_manager.hpp"
  31. #include "../commands/cmd_on_top.hpp"
  32. #include "../commands/cmd_dialogs.hpp"
  33. #include "../controls/ctrl_generic.hpp"
  34. #include "../events/evt_enter.hpp"
  35. #include "../events/evt_focus.hpp"
  36. #include "../events/evt_leave.hpp"
  37. #include "../events/evt_motion.hpp"
  38. #include "../events/evt_mouse.hpp"
  39. #include "../events/evt_key.hpp"
  40. #include "../events/evt_special.hpp"
  41. #include "../events/evt_scroll.hpp"
  42. #include "../utils/position.hpp"
  43. #include "../utils/ustring.hpp"
  44. #include <vlc_keys.h>
  45. TopWindow::TopWindow( intf_thread_t *pIntf, int left, int top,
  46.                       WindowManager &rWindowManager,
  47.                       bool dragDrop, bool playOnDrop ):
  48.     GenericWindow( pIntf, left, top, dragDrop, playOnDrop,
  49.                    NULL),
  50.     m_rWindowManager( rWindowManager ), m_pActiveLayout( NULL ),
  51.     m_pLastHitControl( NULL ), m_pCapturingControl( NULL ),
  52.     m_pFocusControl( NULL ), m_currModifier( 0 )
  53. {
  54.     // Register as a moving window
  55.     m_rWindowManager.registerWindow( *this );
  56. }
  57. TopWindow::~TopWindow()
  58. {
  59.     // Unregister from the window manager
  60.     m_rWindowManager.unregisterWindow( *this );
  61. }
  62. void TopWindow::processEvent( EvtFocus &rEvtFocus )
  63. {
  64. //    fprintf(stderr, rEvtFocus.getAsString().c_str()) ;
  65. }
  66. void TopWindow::processEvent( EvtMotion &rEvtMotion )
  67. {
  68.     // New control hit by the mouse
  69.     CtrlGeneric *pNewHitControl =
  70.         findHitControl( rEvtMotion.getXPos() - getLeft(),
  71.                         rEvtMotion.getYPos() - getTop() );
  72.     setLastHit( pNewHitControl );
  73.     /// Update the help text
  74.     VarManager *pVarManager = VarManager::instance( getIntf() );
  75.     if( pNewHitControl )
  76.     {
  77.         pVarManager->getHelpText().set( pNewHitControl->getHelpText() );
  78.     }
  79.     // Send a motion event to the hit control, or to the control
  80.     // that captured the mouse, if any
  81.     CtrlGeneric *pActiveControl = pNewHitControl;
  82.     if( m_pCapturingControl )
  83.     {
  84.         pActiveControl = m_pCapturingControl;
  85.     }
  86.     if( pActiveControl )
  87.     {
  88.         // Compute the coordinates relative to the window
  89.         int xPos = rEvtMotion.getXPos() - getLeft();
  90.         int yPos = rEvtMotion.getYPos() - getTop();
  91.         // Send a motion event
  92.         EvtMotion evt( getIntf(), xPos, yPos );
  93.         pActiveControl->handleEvent( evt );
  94.     }
  95. }
  96. void TopWindow::processEvent( EvtLeave &rEvtLeave )
  97. {
  98.     // No more hit control
  99.     setLastHit( NULL );
  100.     if( !m_pCapturingControl )
  101.     {
  102.         m_rWindowManager.hideTooltip();
  103.     }
  104. }
  105. void TopWindow::processEvent( EvtMouse &rEvtMouse )
  106. {
  107.     // Get the control hit by the mouse
  108.     CtrlGeneric *pNewHitControl = findHitControl( rEvtMouse.getXPos(),
  109.                                                   rEvtMouse.getYPos() );
  110.     setLastHit( pNewHitControl );
  111.     // Change the focused control
  112.     if( rEvtMouse.getAction() == EvtMouse::kDown )
  113.     {
  114.         // Raise the window
  115.         m_rWindowManager.raise( *this );
  116.         if( pNewHitControl && pNewHitControl->isFocusable() )
  117.         {
  118.             // If a new control gains the focus, the previous one loses it
  119.             if( m_pFocusControl && m_pFocusControl != pNewHitControl )
  120.             {
  121.                 EvtFocus evt( getIntf(), false );
  122.                 m_pFocusControl->handleEvent( evt );
  123.             }
  124.             if( pNewHitControl != m_pFocusControl )
  125.             {
  126.                 m_pFocusControl = pNewHitControl;
  127.                 EvtFocus evt( getIntf(), false );
  128.                 pNewHitControl->handleEvent( evt );
  129.             }
  130.         }
  131.         else if( m_pFocusControl )
  132.         {
  133.             // The previous control loses the focus
  134.             EvtFocus evt( getIntf(), false );
  135.             m_pFocusControl->handleEvent( evt );
  136.             m_pFocusControl = NULL;
  137.         }
  138.     }
  139.     // Send a mouse event to the hit control, or to the control
  140.     // that captured the mouse, if any
  141.     CtrlGeneric *pActiveControl = pNewHitControl;
  142.     if( m_pCapturingControl )
  143.     {
  144.         pActiveControl = m_pCapturingControl;
  145.     }
  146.     if( pActiveControl )
  147.     {
  148.         pActiveControl->handleEvent( rEvtMouse );
  149.     }
  150. }
  151. void TopWindow::processEvent( EvtKey &rEvtKey )
  152. {
  153.     // Forward the event to the focused control, if any
  154.     if( m_pFocusControl )
  155.     {
  156.         m_pFocusControl->handleEvent( rEvtKey );
  157.         return;
  158.     }
  159.     // Only do the action when the key is down
  160.     if( rEvtKey.getAsString().find( "key:down") != string::npos )
  161.     {
  162.         //XXX not to be hardcoded!
  163.         // Ctrl-S = Change skin
  164.         if( (rEvtKey.getMod() & EvtInput::kModCtrl) &&
  165.             rEvtKey.getKey() == 's' )
  166.         {
  167.             CmdDlgChangeSkin cmd( getIntf() );
  168.             cmd.execute();
  169.             return;
  170.         }
  171.         //XXX not to be hardcoded!
  172.         // Ctrl-T = Toggle on top
  173.         if( (rEvtKey.getMod() & EvtInput::kModCtrl) &&
  174.             rEvtKey.getKey() == 't' )
  175.         {
  176.             CmdOnTop cmd( getIntf() );
  177.             cmd.execute();
  178.             return;
  179.         }
  180.         vlc_value_t val;
  181.         // Set the key
  182.         val.i_int = rEvtKey.getKey();
  183.         // Set the modifiers
  184.         if( rEvtKey.getMod() & EvtInput::kModAlt )
  185.         {
  186.             val.i_int |= KEY_MODIFIER_ALT;
  187.         }
  188.         if( rEvtKey.getMod() & EvtInput::kModCtrl )
  189.         {
  190.             val.i_int |= KEY_MODIFIER_CTRL;
  191.         }
  192.         if( rEvtKey.getMod() & EvtInput::kModShift )
  193.         {
  194.             val.i_int |= KEY_MODIFIER_SHIFT;
  195.         }
  196.         var_Set( getIntf()->p_vlc, "key-pressed", val );
  197.     }
  198.     // Always store the modifier, which can be needed for scroll events
  199.     m_currModifier = rEvtKey.getMod();
  200. }
  201. void TopWindow::processEvent( EvtScroll &rEvtScroll )
  202. {
  203.     // Raise the windows
  204.     raise();
  205.     // Get the control hit by the mouse
  206.     CtrlGeneric *pNewHitControl = findHitControl( rEvtScroll.getXPos(),
  207.                                                   rEvtScroll.getYPos());
  208.     setLastHit( pNewHitControl );
  209.     // Send a mouse event to the hit control, or to the control
  210.     // that captured the mouse, if any
  211.     CtrlGeneric *pActiveControl = pNewHitControl;
  212.     if( m_pCapturingControl )
  213.     {
  214.         pActiveControl = m_pCapturingControl;
  215.     }
  216.     if( pActiveControl )
  217.     {
  218.         pActiveControl->handleEvent( rEvtScroll );
  219.     }
  220.     else
  221.     {
  222.         // Treat the scroll event as a hotkey
  223.         vlc_value_t val;
  224.         if( rEvtScroll.getDirection() == EvtScroll::kUp )
  225.         {
  226.             val.i_int = KEY_MOUSEWHEELUP;
  227.         }
  228.         else
  229.         {
  230.             val.i_int = KEY_MOUSEWHEELDOWN;
  231.         }
  232.         // Add the modifiers
  233.         val.i_int |= m_currModifier;
  234.         var_Set( getIntf()->p_vlc, "key-pressed", val );
  235.     }
  236. }
  237. void TopWindow::forwardEvent( EvtGeneric &rEvt, CtrlGeneric &rCtrl )
  238. {
  239.     // XXX: We should do some checks here
  240.     rCtrl.handleEvent( rEvt );
  241. }
  242. void TopWindow::refresh( int left, int top, int width, int height )
  243. {
  244.     if( m_pActiveLayout )
  245.     {
  246.         m_pActiveLayout->getImage()->copyToWindow( *getOSWindow(), left, top,
  247.                                                    width, height, left, top );
  248.     }
  249. }
  250. void TopWindow::setActiveLayout( GenericLayout *pLayout )
  251. {
  252.     pLayout->setWindow( this );
  253.     m_pActiveLayout = pLayout;
  254.     // Get the size of the layout and resize the window
  255.     resize( pLayout->getWidth(), pLayout->getHeight() );
  256.     updateShape();
  257.     pLayout->refreshAll();
  258. }
  259. const GenericLayout& TopWindow::getActiveLayout() const
  260. {
  261.     return *m_pActiveLayout;
  262. }
  263. void TopWindow::innerShow()
  264. {
  265.     // First, refresh the layout and update the shape of the window
  266.     if( m_pActiveLayout )
  267.     {
  268.         updateShape();
  269.         m_pActiveLayout->refreshAll();
  270.     }
  271.     // Show the window
  272.     GenericWindow::innerShow();
  273. }
  274.  
  275. void TopWindow::updateShape()
  276. {
  277.     // Set the shape of the window
  278.     if( m_pActiveLayout )
  279.     {
  280.         OSGraphics *pImage = m_pActiveLayout->getImage();
  281.         if( pImage )
  282.         {
  283.             pImage->applyMaskToWindow( *getOSWindow() );
  284.         }
  285.     }
  286. }
  287. void TopWindow::onControlCapture( const CtrlGeneric &rCtrl )
  288. {
  289.     // Set the capturing control
  290.     m_pCapturingControl = (CtrlGeneric*) &rCtrl;
  291. }
  292. void TopWindow::onControlRelease( const CtrlGeneric &rCtrl )
  293. {
  294.     // Release the capturing control
  295.     if( m_pCapturingControl == &rCtrl )
  296.     {
  297.         m_pCapturingControl = NULL;
  298.     }
  299.     else
  300.     {
  301.         msg_Dbg( getIntf(), "Control had not captured the mouse" );
  302.     }
  303.     // Send an enter event to the control under the mouse, if it doesn't
  304.     // have received it yet
  305.     if( m_pLastHitControl && m_pLastHitControl != &rCtrl )
  306.     {
  307.         EvtEnter evt( getIntf() );
  308.         m_pLastHitControl->handleEvent( evt );
  309.         // Show the tooltip
  310.         m_rWindowManager.hideTooltip();
  311.         UString tipText = m_pLastHitControl->getTooltipText();
  312.         if( tipText.length() > 0 )
  313.         {
  314.             // Set the tooltip text variable
  315.             VarManager *pVarManager = VarManager::instance( getIntf() );
  316.             pVarManager->getTooltipText().set( tipText );
  317.             m_rWindowManager.showTooltip();
  318.         }
  319.     }
  320. }
  321. void TopWindow::onTooltipChange( const CtrlGeneric &rCtrl )
  322. {
  323.     // Check that the control is the active one
  324.     if( m_pLastHitControl && m_pLastHitControl == &rCtrl )
  325.     {
  326.         // Set the tooltip text variable
  327.         VarManager *pVarManager = VarManager::instance( getIntf() );
  328.         pVarManager->getTooltipText().set( rCtrl.getTooltipText() );
  329.     }
  330. }
  331. CtrlGeneric *TopWindow::findHitControl( int xPos, int yPos )
  332. {
  333.     if( m_pActiveLayout == NULL )
  334.     {
  335.         return NULL;
  336.     }
  337.     // Get the controls in the active layout
  338.     const list<LayeredControl> &ctrlList = m_pActiveLayout->getControlList();
  339.     list<LayeredControl>::const_reverse_iterator iter;
  340.     // New control hit by the mouse
  341.     CtrlGeneric *pNewHitControl = NULL;
  342.     // Loop on the control list to find the uppest hit control
  343.     for( iter = ctrlList.rbegin(); iter != ctrlList.rend(); iter++ )
  344.     {
  345.         // Get the position of the control in the layout
  346.         const Position *pos = (*iter).m_pControl->getPosition();
  347.         if( pos != NULL )
  348.         {
  349.             // Compute the coordinates of the mouse relative to the control
  350.             int xRel = xPos - pos->getLeft();
  351.             int yRel = yPos - pos->getTop();
  352.             CtrlGeneric *pCtrl = (*iter).m_pControl;
  353.             // Control hit ?
  354.             if( pCtrl->isVisible() && pCtrl->mouseOver( xRel, yRel ) )
  355.             {
  356.                 pNewHitControl = (*iter).m_pControl;
  357.                 break;
  358.             }
  359.         }
  360.         else
  361.         {
  362.             msg_Dbg( getIntf(), "Control at NULL position" );
  363.         }
  364.     }
  365.     // If the hit control has just been entered, send it an enter event
  366.     if( pNewHitControl && (pNewHitControl != m_pLastHitControl) )
  367.     {
  368.         // Don't send the event if another control captured the mouse
  369.         if( !m_pCapturingControl || (m_pCapturingControl == pNewHitControl ) )
  370.         {
  371.             EvtEnter evt( getIntf() );
  372.             pNewHitControl->handleEvent( evt );
  373.             if( !m_pCapturingControl )
  374.             {
  375.                 // Show the tooltip
  376.                 m_rWindowManager.hideTooltip();
  377.                 UString tipText = pNewHitControl->getTooltipText();
  378.                 if( tipText.length() > 0 )
  379.                 {
  380.                     // Set the tooltip text variable
  381.                     VarManager *pVarManager = VarManager::instance( getIntf() );
  382.                     pVarManager->getTooltipText().set( tipText );
  383.                     m_rWindowManager.showTooltip();
  384.                 }
  385.             }
  386.         }
  387.     }
  388.     return pNewHitControl;
  389. }
  390. void TopWindow::setLastHit( CtrlGeneric *pNewHitControl )
  391. {
  392.     // Send a leave event to the left control
  393.     if( m_pLastHitControl && (pNewHitControl != m_pLastHitControl) )
  394.     {
  395.         // Don't send the event if another control captured the mouse
  396.         if( !m_pCapturingControl || (m_pCapturingControl == m_pLastHitControl))
  397.         {
  398.             EvtLeave evt( getIntf() );
  399.             m_pLastHitControl->handleEvent( evt );
  400.         }
  401.     }
  402.     m_pLastHitControl = pNewHitControl;
  403. }