top_window.cpp
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:15k
源码类别:

midi

开发平台:

Unix_Linux

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