LCOV - code coverage report
Current view: top level - vcl/source/window - menufloatingwindow.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 101 680 14.9 %
Date: 2015-06-13 12:38:46 Functions: 14 46 30.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "menufloatingwindow.hxx"
      21             : #include "menuitemlist.hxx"
      22             : 
      23             : #include <svdata.hxx>
      24             : #include <vcl/decoview.hxx>
      25             : #include <vcl/settings.hxx>
      26             : #include <window.h>
      27             : 
      28           8 : MenuFloatingWindow::MenuFloatingWindow( Menu* pMen, vcl::Window* pParent, WinBits nStyle ) :
      29           8 :     FloatingWindow( pParent, nStyle )
      30             : {
      31           8 :     mpWindowImpl->mbMenuFloatingWindow= true;
      32           8 :     pMenu               = pMen;
      33           8 :     pActivePopup        = 0;
      34           8 :     nSaveFocusId        = 0;
      35           8 :     bInExecute          = false;
      36           8 :     bScrollMenu         = false;
      37           8 :     nHighlightedItem    = ITEMPOS_INVALID;
      38           8 :     nMBDownPos          = ITEMPOS_INVALID;
      39           8 :     nPosInParent        = ITEMPOS_INVALID;
      40           8 :     nScrollerHeight     = 0;
      41           8 :     nBorder             = EXTRASPACEY;
      42           8 :     nFirstEntry         = 0;
      43           8 :     bScrollUp           = false;
      44           8 :     bScrollDown         = false;
      45           8 :     bIgnoreFirstMove    = true;
      46           8 :     bKeyInput           = false;
      47             : 
      48           8 :     EnableSaveBackground();
      49           8 :     ApplySettings(*this);
      50             : 
      51           8 :     SetPopupModeEndHdl( LINK( this, MenuFloatingWindow, PopupEnd ) );
      52             : 
      53           8 :     aHighlightChangedTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, HighlightChanged ) );
      54           8 :     aHighlightChangedTimer.SetTimeout( GetSettings().GetMouseSettings().GetMenuDelay() );
      55           8 :     aSubmenuCloseTimer.SetTimeout( GetSettings().GetMouseSettings().GetMenuDelay() );
      56           8 :     aSubmenuCloseTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, SubmenuClose ) );
      57           8 :     aScrollTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, AutoScroll ) );
      58             : 
      59           8 :     AddEventListener( LINK( this, MenuFloatingWindow, ShowHideListener ) );
      60           8 : }
      61             : 
      62          16 : void MenuFloatingWindow::doShutdown()
      63             : {
      64          16 :     if( pMenu )
      65             :     {
      66             :         // #105373# notify toolkit that highlight was removed
      67             :         // otherwise the entry will not be read when the menu is opened again
      68           8 :         if( nHighlightedItem != ITEMPOS_INVALID )
      69           0 :             pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, nHighlightedItem );
      70           8 :         if (!bKeyInput && pMenu && pMenu->pStartedFrom && !pMenu->pStartedFrom->IsMenuBar())
      71             :         {
      72             :             // #102461# remove highlight in parent
      73           0 :             size_t i, nCount = pMenu->pStartedFrom->pItemList->size();
      74           0 :             for(i = 0; i < nCount; i++)
      75             :             {
      76           0 :                 MenuItemData* pData = pMenu->pStartedFrom->pItemList->GetDataFromPos( i );
      77           0 :                 if( pData && ( pData->pSubMenu == pMenu ) )
      78           0 :                     break;
      79             :             }
      80           0 :             if( i < nCount )
      81             :             {
      82           0 :                 MenuFloatingWindow* pPWin = static_cast<MenuFloatingWindow*>(pMenu->pStartedFrom->ImplGetWindow());
      83           0 :                 if (pPWin)
      84           0 :                     pPWin->InvalidateItem(i);
      85             :             }
      86             :         }
      87             : 
      88             :         // free the reference to the accessible component
      89           8 :         SetAccessible( ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >() );
      90             : 
      91           8 :         aHighlightChangedTimer.Stop();
      92             : 
      93             :         // #95056# invalidate screen area covered by system window
      94             :         // so this can be taken into account if the commandhandler performs a scroll operation
      95           8 :         if( GetParent() )
      96             :         {
      97           8 :             Rectangle aInvRect( GetWindowExtentsRelative( GetParent() ) );
      98           8 :             GetParent()->Invalidate( aInvRect );
      99             :         }
     100           8 :         pMenu = NULL;
     101           8 :         RemoveEventListener( LINK( this, MenuFloatingWindow, ShowHideListener ) );
     102             :     }
     103          16 : }
     104             : 
     105          24 : MenuFloatingWindow::~MenuFloatingWindow()
     106             : {
     107           8 :     disposeOnce();
     108          16 : }
     109             : 
     110           8 : void MenuFloatingWindow::dispose()
     111             : {
     112           8 :     doShutdown();
     113             : 
     114           8 :     FloatingWindow::dispose();
     115           8 : }
     116             : 
     117           8 : void MenuFloatingWindow::Resize()
     118             : {
     119           8 :     InitMenuClipRegion(*this); // FIXME
     120           8 : }
     121             : 
     122          16 : void MenuFloatingWindow::ApplySettings(vcl::RenderContext& rRenderContext)
     123             : {
     124          16 :     FloatingWindow::ApplySettings(rRenderContext);
     125             : 
     126          16 :     const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
     127             : 
     128          16 :     SetPointFont(rRenderContext, rStyleSettings.GetMenuFont());
     129             : 
     130          16 :     if (rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
     131             :     {
     132           0 :         rRenderContext.SetBackground(); // background will be drawn by NWF
     133             :     }
     134             :     else
     135          16 :         rRenderContext.SetBackground(Wallpaper(rStyleSettings.GetMenuColor()));
     136             : 
     137          16 :     rRenderContext.SetTextColor(rStyleSettings.GetMenuTextColor());
     138          16 :     rRenderContext.SetTextFillColor();
     139          16 :     rRenderContext.SetLineColor();
     140          16 : }
     141             : 
     142             : /// Get a negative pixel offset for an offset menu
     143           9 : long MenuFloatingWindow::ImplGetStartY() const
     144             : {
     145           9 :     long nY = 0;
     146           9 :     if( pMenu )
     147             :     {
     148           9 :         for ( sal_uInt16 n = 0; n < nFirstEntry; n++ )
     149           0 :             nY += pMenu->GetItemList()->GetDataFromPos( n )->aSz.Height();
     150           9 :         nY -= pMenu->GetTitleHeight();
     151             :     }
     152           9 :     return -nY;
     153             : }
     154             : 
     155           0 : vcl::Region MenuFloatingWindow::ImplCalcClipRegion( bool bIncludeLogo ) const
     156             : {
     157           0 :     Size aOutSz = GetOutputSizePixel();
     158           0 :     Point aPos;
     159           0 :     Rectangle aRect( aPos, aOutSz );
     160           0 :     aRect.Top() += nScrollerHeight;
     161           0 :     aRect.Bottom() -= nScrollerHeight;
     162             : 
     163           0 :     if ( pMenu && pMenu->pLogo && !bIncludeLogo )
     164           0 :         aRect.Left() += pMenu->pLogo->aBitmap.GetSizePixel().Width();
     165             : 
     166           0 :     vcl::Region aRegion(aRect);
     167           0 :     if ( pMenu && pMenu->pLogo && bIncludeLogo && nScrollerHeight )
     168           0 :         aRegion.Union( Rectangle( Point(), Size( pMenu->pLogo->aBitmap.GetSizePixel().Width(), aOutSz.Height() ) ) );
     169             : 
     170           0 :     return aRegion;
     171             : }
     172             : 
     173           8 : void MenuFloatingWindow::InitMenuClipRegion(vcl::RenderContext& rRenderContext)
     174             : {
     175           8 :     if (IsScrollMenu())
     176             :     {
     177           0 :         rRenderContext.SetClipRegion(ImplCalcClipRegion());
     178             :     }
     179             :     else
     180             :     {
     181           8 :         rRenderContext.SetClipRegion();
     182             :     }
     183           8 : }
     184             : 
     185           0 : void MenuFloatingWindow::ImplHighlightItem( const MouseEvent& rMEvt, bool bMBDown )
     186             : {
     187           0 :     if( ! pMenu )
     188           0 :         return;
     189             : 
     190           0 :     long nY = GetInitialItemY();
     191           0 :     long nMouseY = rMEvt.GetPosPixel().Y();
     192           0 :     Size aOutSz = GetOutputSizePixel();
     193           0 :     if ( ( nMouseY >= nY ) && ( nMouseY < ( aOutSz.Height() + nY ) ) )
     194             :     {
     195           0 :         bool bHighlighted = false;
     196           0 :         size_t nCount = pMenu->pItemList->size();
     197           0 :         for ( size_t n = 0; !bHighlighted && ( n < nCount ); n++ )
     198             :         {
     199           0 :             if ( pMenu->ImplIsVisible( n ) )
     200             :             {
     201           0 :                 MenuItemData* pItemData = pMenu->pItemList->GetDataFromPos( n );
     202           0 :                 long nOldY = nY;
     203           0 :                 nY += pItemData->aSz.Height();
     204           0 :                 if ( ( nOldY <= nMouseY ) && ( nY > nMouseY ) && pMenu->ImplIsSelectable( n ) )
     205             :                 {
     206           0 :                     bool bPopupArea = true;
     207           0 :                     if ( pItemData->nBits & MenuItemBits::POPUPSELECT )
     208             :                     {
     209             :                         // only when clicked over the arrow...
     210           0 :                         Size aSz = GetOutputSizePixel();
     211           0 :                         long nFontHeight = GetTextHeight();
     212           0 :                         bPopupArea = ( rMEvt.GetPosPixel().X() >= ( aSz.Width() - nFontHeight - nFontHeight/4 ) );
     213             :                     }
     214             : 
     215           0 :                     if ( bMBDown )
     216             :                     {
     217           0 :                         if ( n != nHighlightedItem )
     218             :                         {
     219           0 :                             ChangeHighlightItem( (sal_uInt16)n, false );
     220             :                         }
     221             : 
     222           0 :                         bool bAllowNewPopup = true;
     223           0 :                         if ( pActivePopup )
     224             :                         {
     225           0 :                             MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
     226           0 :                             bAllowNewPopup = pData && ( pData->pSubMenu != pActivePopup );
     227           0 :                             if ( bAllowNewPopup )
     228           0 :                                 KillActivePopup();
     229             :                         }
     230             : 
     231           0 :                         if ( bPopupArea && bAllowNewPopup )
     232             :                         {
     233           0 :                             HighlightChanged( NULL );
     234             :                         }
     235             :                     }
     236             :                     else
     237             :                     {
     238           0 :                         if ( n != nHighlightedItem )
     239             :                         {
     240           0 :                             ChangeHighlightItem( (sal_uInt16)n, true );
     241             :                         }
     242           0 :                         else if ( pItemData->nBits & MenuItemBits::POPUPSELECT )
     243             :                         {
     244           0 :                             if ( bPopupArea && ( pActivePopup != pItemData->pSubMenu ) )
     245           0 :                                 HighlightChanged( NULL );
     246             :                         }
     247             :                     }
     248           0 :                     bHighlighted = true;
     249             :                 }
     250             :             }
     251             :         }
     252           0 :         if ( !bHighlighted )
     253           0 :             ChangeHighlightItem( ITEMPOS_INVALID, true );
     254             :     }
     255             :     else
     256             :     {
     257           0 :         ImplScroll( rMEvt.GetPosPixel() );
     258           0 :         ChangeHighlightItem( ITEMPOS_INVALID, true );
     259             :     }
     260             : }
     261             : 
     262           0 : IMPL_LINK_NOARG(MenuFloatingWindow, PopupEnd)
     263             : {
     264             :     // "this" will be deleted before the end of this method!
     265           0 :     Menu* pM = pMenu;
     266           0 :     if ( bInExecute )
     267             :     {
     268           0 :         if ( pActivePopup )
     269             :         {
     270             :             //DBG_ASSERT( !pActivePopup->ImplGetWindow(), "PopupEnd, obwohl pActivePopup MIT Window!" );
     271           0 :             KillActivePopup(); // should be ok to just remove it
     272             :             //pActivePopup->bCanceled = true;
     273             :         }
     274           0 :         bInExecute = false;
     275           0 :         pMenu->bInCallback = true;
     276           0 :         pMenu->Deactivate();
     277           0 :         pMenu->bInCallback = false;
     278             :     }
     279             :     else
     280             :     {
     281           0 :         if (pMenu && pMenu->pStartedFrom)
     282           0 :             pMenu->pStartedFrom->ClosePopup(pMenu);
     283             :     }
     284             : 
     285           0 :     if ( pM )
     286           0 :         pM->pStartedFrom = 0;
     287             : 
     288           0 :     return 0;
     289             : }
     290             : 
     291           0 : IMPL_LINK_NOARG_TYPED(MenuFloatingWindow, AutoScroll, Timer *, void)
     292             : {
     293           0 :     ImplScroll( GetPointerPosPixel() );
     294           0 : }
     295             : 
     296           0 : IMPL_LINK_TYPED( MenuFloatingWindow, HighlightChanged, Timer*, pTimer, void )
     297             : {
     298           0 :     if( ! pMenu )
     299           0 :         return;
     300             : 
     301           0 :     MenuItemData* pItemData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
     302           0 :     if ( pItemData )
     303             :     {
     304           0 :         if ( pActivePopup && ( pActivePopup != pItemData->pSubMenu ) )
     305             :         {
     306           0 :             FloatWinPopupFlags nOldFlags = GetPopupModeFlags();
     307           0 :             SetPopupModeFlags( GetPopupModeFlags() | FloatWinPopupFlags::NoAppFocusClose );
     308           0 :             KillActivePopup();
     309           0 :             SetPopupModeFlags( nOldFlags );
     310             :         }
     311           0 :         if ( pItemData->bEnabled && pItemData->pSubMenu && pItemData->pSubMenu->GetItemCount() && ( pItemData->pSubMenu != pActivePopup ) )
     312             :         {
     313           0 :             pActivePopup = static_cast<PopupMenu*>(pItemData->pSubMenu);
     314           0 :             long nY = nScrollerHeight+ImplGetStartY();
     315           0 :             MenuItemData* pData = 0;
     316           0 :             for ( sal_uLong n = 0; n < nHighlightedItem; n++ )
     317             :             {
     318           0 :                 pData = pMenu->pItemList->GetDataFromPos( n );
     319           0 :                 nY += pData->aSz.Height();
     320             :             }
     321           0 :             pData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
     322           0 :             Size MySize = GetOutputSizePixel();
     323           0 :             Point aItemTopLeft( 0, nY );
     324           0 :             Point aItemBottomRight( aItemTopLeft );
     325           0 :             aItemBottomRight.X() += MySize.Width();
     326           0 :             aItemBottomRight.Y() += pData->aSz.Height();
     327             : 
     328             :             // shift the popups a little
     329           0 :             aItemTopLeft.X() += 2;
     330           0 :             aItemBottomRight.X() -= 2;
     331           0 :             if ( nHighlightedItem )
     332           0 :                 aItemTopLeft.Y() -= 2;
     333             :             else
     334             :             {
     335             :                 sal_Int32 nL, nT, nR, nB;
     336           0 :                 GetBorder( nL, nT, nR, nB );
     337           0 :                 aItemTopLeft.Y() -= nT;
     338             :             }
     339             : 
     340             :             // pTest: crash due to Reschedule() in call of Activate()
     341             :             // Also it is prevented that submenus are displayed which
     342             :             // were for long in Activate Rescheduled and which should not be
     343             :             // displayed now.
     344           0 :             Menu* pTest = pActivePopup;
     345           0 :             FloatWinPopupFlags nOldFlags = GetPopupModeFlags();
     346           0 :             SetPopupModeFlags( GetPopupModeFlags() | FloatWinPopupFlags::NoAppFocusClose );
     347           0 :             sal_uInt16 nRet = pActivePopup->ImplExecute( this, Rectangle( aItemTopLeft, aItemBottomRight ), FloatWinPopupFlags::Right, pMenu, pTimer == nullptr );
     348           0 :             SetPopupModeFlags( nOldFlags );
     349             : 
     350             :             // nRet != 0, wenn es waerend Activate() abgeschossen wurde...
     351           0 :             if ( !nRet && ( pActivePopup == pTest ) && pActivePopup->ImplGetWindow() )
     352           0 :                 pActivePopup->ImplGetFloatingWindow()->AddPopupModeWindow( this );
     353             :         }
     354             :     }
     355             : }
     356             : 
     357           0 : IMPL_LINK_NOARG_TYPED(MenuFloatingWindow, SubmenuClose, Timer *, void)
     358             : {
     359           0 :     if( pMenu && pMenu->pStartedFrom )
     360             :     {
     361           0 :         MenuFloatingWindow* pWin = static_cast<MenuFloatingWindow*>(pMenu->pStartedFrom->GetWindow());
     362           0 :         if( pWin )
     363           0 :             pWin->KillActivePopup();
     364             :     }
     365           0 : }
     366             : 
     367          96 : IMPL_LINK( MenuFloatingWindow, ShowHideListener, VclWindowEvent*, pEvent )
     368             : {
     369          48 :     if( ! pMenu )
     370           0 :         return 0;
     371             : 
     372          48 :     if( pEvent->GetId() == VCLEVENT_WINDOW_SHOW )
     373          16 :         pMenu->ImplCallEventListeners( VCLEVENT_MENU_SHOW, ITEMPOS_INVALID );
     374          32 :     else if( pEvent->GetId() == VCLEVENT_WINDOW_HIDE )
     375          16 :         pMenu->ImplCallEventListeners( VCLEVENT_MENU_HIDE, ITEMPOS_INVALID );
     376          48 :     return 0;
     377             : }
     378             : 
     379           0 : void MenuFloatingWindow::EnableScrollMenu( bool b )
     380             : {
     381           0 :     bScrollMenu = b;
     382           0 :     nScrollerHeight = b ? (sal_uInt16) GetSettings().GetStyleSettings().GetScrollBarSize() /2 : 0;
     383           0 :     bScrollDown = true;
     384           0 :     InitMenuClipRegion(*this);
     385           0 : }
     386             : 
     387           0 : void MenuFloatingWindow::Execute()
     388             : {
     389           0 :     ImplSVData* pSVData = ImplGetSVData();
     390             : 
     391           0 :     pSVData->maAppData.mpActivePopupMenu = static_cast<PopupMenu*>(pMenu);
     392             : 
     393           0 :     bInExecute = true;
     394             : //  bCallingSelect = false;
     395             : 
     396           0 :     while ( bInExecute )
     397           0 :         Application::Yield();
     398             : 
     399           0 :     pSVData->maAppData.mpActivePopupMenu = NULL;
     400           0 : }
     401             : 
     402           8 : void MenuFloatingWindow::StopExecute( sal_uLong nFocusId )
     403             : {
     404             :     // restore focus
     405             :     // (could have been restored in Select)
     406           8 :     if ( nSaveFocusId )
     407             :     {
     408           0 :         Window::EndSaveFocus( nFocusId, false );
     409           0 :         nFocusId = nSaveFocusId;
     410           0 :         if ( nFocusId )
     411             :         {
     412           0 :             nSaveFocusId = 0;
     413           0 :             ImplGetSVData()->maWinData.mbNoDeactivate = false;
     414             :         }
     415             :     }
     416           8 :     ImplEndPopupMode( FloatWinPopupEndFlags::NONE, nFocusId );
     417             : 
     418           8 :     aHighlightChangedTimer.Stop();
     419           8 :     bInExecute = false;
     420           8 :     if ( pActivePopup )
     421             :     {
     422           0 :         KillActivePopup();
     423             :     }
     424             :     // notify parent, needed for accessibility
     425           8 :     if( pMenu && pMenu->pStartedFrom )
     426           8 :         pMenu->pStartedFrom->ImplCallEventListeners( VCLEVENT_MENU_SUBMENUDEACTIVATE, nPosInParent );
     427           8 : }
     428             : 
     429           0 : void MenuFloatingWindow::KillActivePopup( PopupMenu* pThisOnly )
     430             : {
     431           0 :     if ( pActivePopup && ( !pThisOnly || ( pThisOnly == pActivePopup ) ) )
     432             :     {
     433           0 :         if( pActivePopup->pWindow )
     434           0 :             if( static_cast<FloatingWindow *>(pActivePopup->pWindow.get())->IsInCleanUp() )
     435           0 :                 return; // kill it later
     436           0 :         if ( pActivePopup->bInCallback )
     437           0 :             pActivePopup->bCanceled = true;
     438             : 
     439             :         // For all actions pActivePopup = 0, if e.g.
     440             :         // PopupModeEndHdl the popups to destroy were called synchronous
     441           0 :         PopupMenu* pPopup = pActivePopup;
     442           0 :         pActivePopup = NULL;
     443           0 :         pPopup->bInCallback = true;
     444           0 :         pPopup->Deactivate();
     445           0 :         pPopup->bInCallback = false;
     446           0 :         if ( pPopup->ImplGetWindow() )
     447             :         {
     448           0 :             pPopup->ImplGetFloatingWindow()->StopExecute();
     449           0 :             pPopup->ImplGetFloatingWindow()->doShutdown();
     450           0 :             pPopup->pWindow->doLazyDelete();
     451           0 :             pPopup->pWindow = NULL;
     452             : 
     453           0 :             Update();
     454             :         }
     455             :     }
     456             : }
     457             : 
     458           0 : void MenuFloatingWindow::EndExecute()
     459             : {
     460           0 :     Menu* pStart = pMenu ? pMenu->ImplGetStartMenu() : NULL;
     461           0 :     sal_uLong nFocusId = 0;
     462           0 :     if (pStart)
     463           0 :         nFocusId = pStart->DeactivateMenuBar(nFocusId);
     464             : 
     465             :     // if started elsewhere, cleanup there as well
     466           0 :     MenuFloatingWindow* pCleanUpFrom = this;
     467           0 :     MenuFloatingWindow* pWin = this;
     468           0 :     while (pWin && !pWin->bInExecute &&
     469           0 :         pWin->pMenu->pStartedFrom && !pWin->pMenu->pStartedFrom->IsMenuBar())
     470             :     {
     471           0 :         pWin = static_cast<PopupMenu*>(pWin->pMenu->pStartedFrom)->ImplGetFloatingWindow();
     472             :     }
     473           0 :     if ( pWin )
     474           0 :         pCleanUpFrom = pWin;
     475             : 
     476             :     // this window will be destroyed => store date locally...
     477           0 :     Menu* pM = pMenu;
     478           0 :     sal_uInt16 nItem = nHighlightedItem;
     479             : 
     480           0 :     pCleanUpFrom->StopExecute( nFocusId );
     481             : 
     482           0 :     if ( nItem != ITEMPOS_INVALID && pM )
     483             :     {
     484           0 :         MenuItemData* pItemData = pM->GetItemList()->GetDataFromPos( nItem );
     485           0 :         if ( pItemData && !pItemData->bIsTemporary )
     486             :         {
     487           0 :             pM->nSelectedId = pItemData->nId;
     488           0 :             if ( pStart )
     489           0 :                 pStart->nSelectedId = pItemData->nId;
     490             : 
     491           0 :             pM->ImplSelect();
     492             :         }
     493             :     }
     494           0 : }
     495             : 
     496           0 : void MenuFloatingWindow::EndExecute( sal_uInt16 nId )
     497             : {
     498             :     size_t nPos;
     499           0 :     if ( pMenu && pMenu->GetItemList()->GetData( nId, nPos ) )
     500           0 :         nHighlightedItem = nPos;
     501             :     else
     502           0 :         nHighlightedItem = ITEMPOS_INVALID;
     503             : 
     504           0 :     EndExecute();
     505           0 : }
     506             : 
     507           0 : void MenuFloatingWindow::MouseButtonDown( const MouseEvent& rMEvt )
     508             : {
     509             :     // TH creates a ToTop on this window, but the active popup
     510             :     // should stay on top...
     511             :     // due to focus change this would close all menus -> don't do it (#94123)
     512             :     //if ( pActivePopup && pActivePopup->ImplGetWindow() && !pActivePopup->ImplGetFloatingWindow()->pActivePopup )
     513             :     //    pActivePopup->ImplGetFloatingWindow()->ToTop( ToTopFlags::NoGrabFocus );
     514             : 
     515           0 :     ImplHighlightItem( rMEvt, true );
     516             : 
     517           0 :     nMBDownPos = nHighlightedItem;
     518           0 : }
     519             : 
     520           0 : void MenuFloatingWindow::MouseButtonUp( const MouseEvent& rMEvt )
     521             : {
     522           0 :     MenuItemData* pData = pMenu ? pMenu->GetItemList()->GetDataFromPos( nHighlightedItem ) : NULL;
     523             :     // nMBDownPos store in local variable and reset immediately,
     524             :     // as it will be too late after EndExecute
     525           0 :     sal_uInt16 _nMBDownPos = nMBDownPos;
     526           0 :     nMBDownPos = ITEMPOS_INVALID;
     527           0 :     if ( pData && pData->bEnabled && ( pData->eType != MenuItemType::SEPARATOR ) )
     528             :     {
     529           0 :         if ( !pData->pSubMenu )
     530             :         {
     531           0 :             EndExecute();
     532             :         }
     533           0 :         else if ( ( pData->nBits & MenuItemBits::POPUPSELECT ) && ( nHighlightedItem == _nMBDownPos ) && ( rMEvt.GetClicks() == 2 ) )
     534             :         {
     535             :             // not when clicked over the arrow...
     536           0 :             Size aSz = GetOutputSizePixel();
     537           0 :             long nFontHeight = GetTextHeight();
     538           0 :             if ( rMEvt.GetPosPixel().X() < ( aSz.Width() - nFontHeight - nFontHeight/4 ) )
     539           0 :                 EndExecute();
     540             :         }
     541             :     }
     542             : 
     543           0 : }
     544             : 
     545           0 : void MenuFloatingWindow::MouseMove( const MouseEvent& rMEvt )
     546             : {
     547           0 :     if ( !IsVisible() || rMEvt.IsSynthetic() || rMEvt.IsEnterWindow() )
     548           0 :         return;
     549             : 
     550           0 :     if ( rMEvt.IsLeaveWindow() )
     551             :     {
     552             :         // #102461# do not remove highlight if a popup menu is open at this position
     553           0 :         MenuItemData* pData = pMenu ? pMenu->pItemList->GetDataFromPos( nHighlightedItem ) : NULL;
     554             :         // close popup with some delayed if we leave somewhere else
     555           0 :         if( pActivePopup && pData && pData->pSubMenu != pActivePopup )
     556           0 :             pActivePopup->ImplGetFloatingWindow()->aSubmenuCloseTimer.Start();
     557             : 
     558           0 :         if( !pActivePopup || (pData && pData->pSubMenu != pActivePopup ) )
     559           0 :             ChangeHighlightItem( ITEMPOS_INVALID, false );
     560             : 
     561           0 :         if ( IsScrollMenu() )
     562           0 :             ImplScroll( rMEvt.GetPosPixel() );
     563             :     }
     564             :     else
     565             :     {
     566           0 :         aSubmenuCloseTimer.Stop();
     567           0 :         if( bIgnoreFirstMove )
     568           0 :             bIgnoreFirstMove = false;
     569             :         else
     570           0 :             ImplHighlightItem( rMEvt, false );
     571             :     }
     572             : }
     573             : 
     574           0 : void MenuFloatingWindow::ImplScroll( bool bUp )
     575             : {
     576           0 :     KillActivePopup();
     577           0 :     Update();
     578             : 
     579           0 :     if (!pMenu)
     580           0 :         return;
     581             : 
     582           0 :     Invalidate();
     583             : 
     584           0 :     pMenu->ImplKillLayoutData();
     585             : 
     586           0 :     if ( bScrollUp && bUp )
     587             :     {
     588           0 :         nFirstEntry = pMenu->ImplGetPrevVisible( nFirstEntry );
     589             :         DBG_ASSERT( nFirstEntry != ITEMPOS_INVALID, "Scroll?!" );
     590             : 
     591           0 :         long nScrollEntryHeight = pMenu->GetItemList()->GetDataFromPos( nFirstEntry )->aSz.Height();
     592             : 
     593           0 :         if ( !bScrollDown )
     594             :         {
     595           0 :             bScrollDown = true;
     596           0 :             Invalidate();
     597             :         }
     598             : 
     599           0 :         if ( pMenu->ImplGetPrevVisible( nFirstEntry ) == ITEMPOS_INVALID )
     600             :         {
     601           0 :             bScrollUp = false;
     602           0 :             Invalidate();
     603             :         }
     604             : 
     605           0 :         Scroll( 0, nScrollEntryHeight, ImplCalcClipRegion( false ).GetBoundRect(), ScrollFlags::Clip );
     606             :     }
     607           0 :     else if ( bScrollDown && !bUp )
     608             :     {
     609           0 :         long nScrollEntryHeight = pMenu->GetItemList()->GetDataFromPos( nFirstEntry )->aSz.Height();
     610             : 
     611           0 :         nFirstEntry = pMenu->ImplGetNextVisible( nFirstEntry );
     612             :         DBG_ASSERT( nFirstEntry != ITEMPOS_INVALID, "Scroll?!" );
     613             : 
     614           0 :         if ( !bScrollUp )
     615             :         {
     616           0 :             bScrollUp = true;
     617           0 :             Invalidate();
     618             :         }
     619             : 
     620           0 :         long nHeight = GetOutputSizePixel().Height();
     621             :         sal_uInt16 nLastVisible;
     622           0 :         static_cast<PopupMenu*>(pMenu)->ImplCalcVisEntries( nHeight, nFirstEntry, &nLastVisible );
     623           0 :         if ( pMenu->ImplGetNextVisible( nLastVisible ) == ITEMPOS_INVALID )
     624             :         {
     625           0 :             bScrollDown = false;
     626           0 :             Invalidate();
     627             :         }
     628             : 
     629           0 :         Scroll( 0, -nScrollEntryHeight, ImplCalcClipRegion( false ).GetBoundRect(), ScrollFlags::Clip );
     630             :     }
     631             : 
     632           0 :     Invalidate();
     633             : }
     634             : 
     635           0 : void MenuFloatingWindow::ImplScroll( const Point& rMousePos )
     636             : {
     637           0 :     Size aOutSz = GetOutputSizePixel();
     638             : 
     639           0 :     long nY = nScrollerHeight;
     640           0 :     long nMouseY = rMousePos.Y();
     641           0 :     long nDelta = 0;
     642             : 
     643           0 :     if ( bScrollUp && ( nMouseY < nY ) )
     644             :     {
     645           0 :         ImplScroll( true );
     646           0 :         nDelta = nY - nMouseY;
     647             :     }
     648           0 :     else if ( bScrollDown && ( nMouseY > ( aOutSz.Height() - nY ) ) )
     649             :     {
     650           0 :         ImplScroll( false );
     651           0 :         nDelta = nMouseY - ( aOutSz.Height() - nY );
     652             :     }
     653             : 
     654           0 :     if ( nDelta )
     655             :     {
     656           0 :         aScrollTimer.Stop();    // if scrolled through MouseMove.
     657             :         long nTimeout;
     658           0 :         if ( nDelta < 3 )
     659           0 :             nTimeout = 200;
     660           0 :         else if ( nDelta < 5 )
     661           0 :             nTimeout = 100;
     662           0 :         else if ( nDelta < 8 )
     663           0 :             nTimeout = 70;
     664           0 :         else if ( nDelta < 12 )
     665           0 :             nTimeout = 40;
     666             :         else
     667           0 :             nTimeout = 20;
     668           0 :         aScrollTimer.SetTimeout( nTimeout );
     669           0 :         aScrollTimer.Start();
     670             :     }
     671           0 : }
     672           0 : void MenuFloatingWindow::ChangeHighlightItem( sal_uInt16 n, bool bStartPopupTimer )
     673             : {
     674             :     // #57934# ggf. immediately close the active, as TH's backgroundstorage works.
     675             :     // #65750# we prefer to refrain from the background storage of small lines.
     676             :     //         otherwise the menus are difficult to operate.
     677             :     //  MenuItemData* pNextData = pMenu->pItemList->GetDataFromPos( n );
     678             :     //  if ( pActivePopup && pNextData && ( pActivePopup != pNextData->pSubMenu ) )
     679             :     //      KillActivePopup();
     680             : 
     681           0 :     aSubmenuCloseTimer.Stop();
     682           0 :     if( ! pMenu )
     683           0 :         return;
     684             : 
     685           0 :     if ( nHighlightedItem != ITEMPOS_INVALID )
     686             :     {
     687           0 :         InvalidateItem(nHighlightedItem);
     688           0 :         pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, nHighlightedItem );
     689             :     }
     690             : 
     691           0 :     nHighlightedItem = (sal_uInt16)n;
     692             :     DBG_ASSERT( pMenu->ImplIsVisible( nHighlightedItem ) || nHighlightedItem == ITEMPOS_INVALID, "ChangeHighlightItem: Not visible!" );
     693           0 :     if( nHighlightedItem != ITEMPOS_INVALID )
     694             :     {
     695           0 :         if (pMenu->pStartedFrom && !pMenu->pStartedFrom->IsMenuBar())
     696             :         {
     697             :             // #102461# make sure parent entry is highlighted as well
     698           0 :             size_t i, nCount = pMenu->pStartedFrom->pItemList->size();
     699           0 :             for(i = 0; i < nCount; i++)
     700             :             {
     701           0 :                 MenuItemData* pData = pMenu->pStartedFrom->pItemList->GetDataFromPos( i );
     702           0 :                 if( pData && ( pData->pSubMenu == pMenu ) )
     703           0 :                     break;
     704             :             }
     705           0 :             if( i < nCount )
     706             :             {
     707           0 :                 MenuFloatingWindow* pPWin = static_cast<MenuFloatingWindow*>(pMenu->pStartedFrom->ImplGetWindow());
     708           0 :                 if( pPWin && pPWin->nHighlightedItem != i )
     709             :                 {
     710           0 :                     pPWin->InvalidateItem(i);
     711           0 :                     pPWin->nHighlightedItem = i;
     712             :                 }
     713             :             }
     714             :         }
     715           0 :         InvalidateItem(nHighlightedItem);
     716           0 :         pMenu->ImplCallHighlight( nHighlightedItem );
     717             :     }
     718             :     else
     719           0 :         pMenu->nSelectedId = 0;
     720             : 
     721           0 :     if ( bStartPopupTimer )
     722             :     {
     723             :         // #102438# Menu items are not selectable
     724             :         // If a menu item is selected by an AT-tool via the XAccessibleAction, XAccessibleValue
     725             :         // or XAccessibleSelection interface, and the parent popup menus are not executed yet,
     726             :         // the parent popup menus must be executed SYNCHRONOUSLY, before the menu item is selected.
     727           0 :         if ( GetSettings().GetMouseSettings().GetMenuDelay() )
     728           0 :             aHighlightChangedTimer.Start();
     729             :         else
     730           0 :             HighlightChanged( &aHighlightChangedTimer );
     731             :     }
     732             : }
     733             : 
     734             : /// Calculate the initial vertical pixel offset of the first item.
     735             : /// May be negative for scrolled windows.
     736           0 : long MenuFloatingWindow::GetInitialItemY(long *pStartY) const
     737             : {
     738           0 :     long nStartY = ImplGetStartY();
     739           0 :     if (pStartY)
     740           0 :         *pStartY = nStartY;
     741           0 :     return nScrollerHeight + nStartY +
     742           0 :         ImplGetSVData()->maNWFData.mnMenuFormatBorderY;
     743             : }
     744             : 
     745             : /// Emit an Invalidate just for this item's area
     746           0 : void MenuFloatingWindow::InvalidateItem(sal_uInt16 nPos)
     747             : {
     748           0 :     if (!pMenu)
     749           0 :         return;
     750             : 
     751           0 :     long nY = GetInitialItemY();
     752           0 :     size_t nCount = pMenu->pItemList->size();
     753           0 :     for (size_t n = 0; n < nCount; n++)
     754             :     {
     755           0 :         MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
     756           0 :         long nHeight = pData->aSz.Height();
     757           0 :         if (n == nPos)
     758             :         {
     759           0 :             Size aWidth( GetSizePixel() );
     760           0 :             Rectangle aRect(Point(0, nY), Size(aWidth.Width(), nHeight));
     761           0 :             Invalidate( aRect );
     762             :         }
     763           0 :         nY += nHeight;
     764             :     }
     765             : }
     766             : 
     767           0 : void MenuFloatingWindow::RenderHighlightItem(vcl::RenderContext& rRenderContext, sal_uInt16 nPos, bool bHighlight)
     768             : {
     769           0 :     if (!pMenu)
     770           0 :         return;
     771             : 
     772           0 :     Size aSz = rRenderContext.GetOutputSizePixel();
     773             : 
     774           0 :     long nX = 0;
     775             :     long nStartY;
     776           0 :     long nY = GetInitialItemY(&nStartY);
     777             : 
     778           0 :     if (pMenu->pLogo)
     779           0 :         nX = pMenu->pLogo->aBitmap.GetSizePixel().Width();
     780             : 
     781           0 :     int nOuterSpaceX = ImplGetSVData()->maNWFData.mnMenuFormatBorderX;
     782             : 
     783           0 :     size_t nCount = pMenu->pItemList->size();
     784           0 :     for (size_t n = 0; n < nCount; n++)
     785             :     {
     786           0 :         MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
     787           0 :         if (n == nPos)
     788             :         {
     789             :             DBG_ASSERT(pMenu->ImplIsVisible(n), "Highlight: Item not visible!");
     790           0 :             if (pData->eType != MenuItemType::SEPARATOR)
     791             :             {
     792           0 :                 bool bRestoreLineColor = false;
     793           0 :                 Color oldLineColor;
     794           0 :                 bool bDrawItemRect = true;
     795             : 
     796           0 :                 Rectangle aItemRect(Point(nX + nOuterSpaceX, nY), Size(aSz.Width() - 2 * nOuterSpaceX, pData->aSz.Height()));
     797           0 :                 if (pData->nBits & MenuItemBits::POPUPSELECT)
     798             :                 {
     799           0 :                     long nFontHeight = GetTextHeight();
     800           0 :                     aItemRect.Right() -= nFontHeight + nFontHeight / 4;
     801             :                 }
     802             : 
     803           0 :                 if (rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
     804             :                 {
     805           0 :                     Size aPxSize(rRenderContext.GetOutputSizePixel());
     806           0 :                     rRenderContext.Push(PushFlags::CLIPREGION);
     807           0 :                     rRenderContext.IntersectClipRegion(Rectangle(Point(nX, nY), Size(aSz.Width(), pData->aSz.Height())));
     808           0 :                     Rectangle aCtrlRect(Point(nX, 0), Size(aPxSize.Width()-nX, aPxSize.Height()));
     809           0 :                     MenupopupValue aVal(pMenu->nTextPos-GUTTERBORDER, aItemRect);
     810             :                     rRenderContext.DrawNativeControl(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL,
     811           0 :                                                      aCtrlRect, ControlState::ENABLED, aVal, OUString());
     812           0 :                     if (bHighlight &&
     813           0 :                         rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_MENU_ITEM))
     814             :                     {
     815           0 :                         bDrawItemRect = false;
     816           0 :                         if (!rRenderContext.DrawNativeControl(CTRL_MENU_POPUP, PART_MENU_ITEM, aItemRect,
     817           0 :                                                               ControlState::SELECTED | (pData->bEnabled
     818             :                                                                                             ? ControlState::ENABLED
     819           0 :                                                                                             : ControlState::NONE),
     820           0 :                                                               aVal, OUString()))
     821             :                         {
     822           0 :                             bDrawItemRect = bHighlight;
     823             :                         }
     824             :                     }
     825             :                     else
     826           0 :                         bDrawItemRect = bHighlight;
     827           0 :                     rRenderContext.Pop();
     828             :                 }
     829           0 :                 if (bDrawItemRect)
     830             :                 {
     831           0 :                     if (bHighlight)
     832             :                     {
     833           0 :                         if (pData->bEnabled)
     834           0 :                             rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetMenuHighlightColor());
     835             :                         else
     836             :                         {
     837           0 :                             rRenderContext.SetFillColor();
     838           0 :                             oldLineColor = rRenderContext.GetLineColor();
     839           0 :                             rRenderContext.SetLineColor(rRenderContext.GetSettings().GetStyleSettings().GetMenuHighlightColor());
     840           0 :                             bRestoreLineColor = true;
     841             :                         }
     842             :                     }
     843             :                     else
     844           0 :                         rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetMenuColor());
     845             : 
     846           0 :                     rRenderContext.DrawRect(aItemRect);
     847             :                 }
     848           0 :                 pMenu->ImplPaint(rRenderContext, nScrollerHeight, nStartY, pData, bHighlight);
     849           0 :                 if (bRestoreLineColor)
     850           0 :                     rRenderContext.SetLineColor(oldLineColor);
     851             :             }
     852           0 :             return;
     853             :         }
     854             : 
     855           0 :         nY += pData->aSz.Height();
     856             :     }
     857             : }
     858             : 
     859           0 : Rectangle MenuFloatingWindow::ImplGetItemRect( sal_uInt16 nPos )
     860             : {
     861           0 :     if( ! pMenu )
     862           0 :         return Rectangle();
     863             : 
     864           0 :     Rectangle aRect;
     865           0 :     Size    aSz = GetOutputSizePixel();
     866           0 :     long    nStartY = ImplGetStartY();
     867           0 :     long    nY = nScrollerHeight+nStartY;
     868           0 :     long    nX = 0;
     869             : 
     870           0 :     if ( pMenu->pLogo )
     871           0 :         nX = pMenu->pLogo->aBitmap.GetSizePixel().Width();
     872             : 
     873           0 :     size_t nCount = pMenu->pItemList->size();
     874           0 :     for ( size_t n = 0; n < nCount; n++ )
     875             :     {
     876           0 :         MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
     877           0 :         if ( n == nPos )
     878             :         {
     879             :             DBG_ASSERT( pMenu->ImplIsVisible( n ), "ImplGetItemRect: Item not visible!" );
     880           0 :             if ( pData->eType != MenuItemType::SEPARATOR )
     881             :             {
     882           0 :                 aRect = Rectangle( Point( nX, nY ), Size( aSz.Width(), pData->aSz.Height() ) );
     883           0 :                 if ( pData->nBits & MenuItemBits::POPUPSELECT )
     884             :                 {
     885           0 :                     long nFontHeight = GetTextHeight();
     886           0 :                     aRect.Right() -= nFontHeight + nFontHeight/4;
     887             :                 }
     888             :             }
     889           0 :             break;
     890             :         }
     891           0 :         nY += pData->aSz.Height();
     892             :     }
     893           0 :     return aRect;
     894             : }
     895             : 
     896           0 : void MenuFloatingWindow::ImplCursorUpDown( bool bUp, bool bHomeEnd )
     897             : {
     898           0 :     if( ! pMenu )
     899           0 :         return;
     900             : 
     901           0 :     const StyleSettings& rSettings = GetSettings().GetStyleSettings();
     902             : 
     903           0 :     sal_uInt16 n = nHighlightedItem;
     904           0 :     if ( n == ITEMPOS_INVALID )
     905             :     {
     906           0 :         if ( bUp )
     907           0 :             n = 0;
     908             :         else
     909           0 :             n = pMenu->GetItemCount()-1;
     910             :     }
     911             : 
     912           0 :     sal_uInt16 nLoop = n;
     913             : 
     914           0 :     if( bHomeEnd )
     915             :     {
     916             :         // absolute positioning
     917           0 :         if( bUp )
     918             :         {
     919           0 :             n = pMenu->GetItemCount();
     920           0 :             nLoop = n-1;
     921             :         }
     922             :         else
     923             :         {
     924           0 :             n = (sal_uInt16)-1;
     925           0 :             nLoop = n+1;
     926             :         }
     927             :     }
     928             : 
     929           0 :     do
     930             :     {
     931           0 :         if ( bUp )
     932             :         {
     933           0 :             if ( n )
     934           0 :                 n--;
     935             :             else
     936           0 :                 if ( !IsScrollMenu() || ( nHighlightedItem == ITEMPOS_INVALID ) )
     937           0 :                     n = pMenu->GetItemCount()-1;
     938             :                 else
     939           0 :                     break;
     940             :         }
     941             :         else
     942             :         {
     943           0 :             n++;
     944           0 :             if ( n >= pMenu->GetItemCount() )
     945             :             {
     946           0 :                 if ( !IsScrollMenu() || ( nHighlightedItem == ITEMPOS_INVALID ) )
     947           0 :                     n = 0;
     948             :                 else
     949           0 :                     break;
     950             :             }
     951             :         }
     952             : 
     953           0 :         MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( n );
     954           0 :         if ( ( pData->bEnabled || !rSettings.GetSkipDisabledInMenus() )
     955           0 :               && ( pData->eType != MenuItemType::SEPARATOR ) && pMenu->ImplIsVisible( n ) && pMenu->ImplIsSelectable( n ) )
     956             :         {
     957             :             // Is selection in visible area?
     958           0 :             if ( IsScrollMenu() )
     959             :             {
     960           0 :                 ChangeHighlightItem( ITEMPOS_INVALID, false );
     961             : 
     962           0 :                 while ( n < nFirstEntry )
     963           0 :                     ImplScroll( true );
     964             : 
     965           0 :                 Size aOutSz = GetOutputSizePixel();
     966             :                 sal_uInt16 nLastVisible;
     967           0 :                 static_cast<PopupMenu*>(pMenu)->ImplCalcVisEntries( aOutSz.Height(), nFirstEntry, &nLastVisible );
     968           0 :                 while ( n > nLastVisible )
     969             :                 {
     970           0 :                     ImplScroll( false );
     971           0 :                     static_cast<PopupMenu*>(pMenu)->ImplCalcVisEntries( aOutSz.Height(), nFirstEntry, &nLastVisible );
     972             :                 }
     973             :             }
     974           0 :             ChangeHighlightItem( n, false );
     975           0 :             break;
     976             :         }
     977             :     } while ( n != nLoop );
     978             : }
     979             : 
     980           0 : void MenuFloatingWindow::KeyInput( const KeyEvent& rKEvent )
     981             : {
     982           0 :     ImplDelData aDelData;
     983           0 :     ImplAddDel( &aDelData );
     984             : 
     985           0 :     sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
     986           0 :     bKeyInput = true;
     987           0 :     switch ( nCode )
     988             :     {
     989             :         case KEY_UP:
     990             :         case KEY_DOWN:
     991             :         {
     992           0 :             ImplCursorUpDown( nCode == KEY_UP );
     993             :         }
     994           0 :         break;
     995             :         case KEY_END:
     996             :         case KEY_HOME:
     997             :         {
     998           0 :             ImplCursorUpDown( nCode == KEY_END, true );
     999             :         }
    1000           0 :         break;
    1001             :         case KEY_F6:
    1002             :         case KEY_ESCAPE:
    1003             :         {
    1004             :             // Ctrl-F6 acts like ESC here, the menu bar however will then put the focus in the document
    1005           0 :             if( nCode == KEY_F6 && !rKEvent.GetKeyCode().IsMod1() )
    1006           0 :                 break;
    1007           0 :             if( pMenu )
    1008             :             {
    1009           0 :                 if ( !pMenu->pStartedFrom )
    1010             :                 {
    1011           0 :                     StopExecute();
    1012           0 :                     KillActivePopup();
    1013             :                 }
    1014           0 :                 else if (pMenu->pStartedFrom->IsMenuBar())
    1015             :                 {
    1016           0 :                     pMenu->pStartedFrom->MenuBarKeyInput(rKEvent);
    1017             :                 }
    1018             :                 else
    1019             :                 {
    1020           0 :                     StopExecute();
    1021           0 :                     PopupMenu* pPopupMenu = static_cast<PopupMenu*>(pMenu->pStartedFrom);
    1022           0 :                     MenuFloatingWindow* pFloat = pPopupMenu->ImplGetFloatingWindow();
    1023           0 :                     pFloat->GrabFocus();
    1024           0 :                     pFloat->KillActivePopup();
    1025           0 :                     pPopupMenu->ImplCallHighlight(pFloat->nHighlightedItem);
    1026             :                 }
    1027             :             }
    1028             :         }
    1029           0 :         break;
    1030             :         case KEY_LEFT:
    1031             :         {
    1032           0 :             if ( pMenu && pMenu->pStartedFrom )
    1033             :             {
    1034           0 :                 StopExecute();
    1035           0 :                 if (pMenu->pStartedFrom->IsMenuBar())
    1036             :                 {
    1037           0 :                     pMenu->pStartedFrom->MenuBarKeyInput(rKEvent);
    1038             :                 }
    1039             :                 else
    1040             :                 {
    1041           0 :                     MenuFloatingWindow* pFloat = static_cast<PopupMenu*>(pMenu->pStartedFrom)->ImplGetFloatingWindow();
    1042           0 :                     pFloat->GrabFocus();
    1043           0 :                     pFloat->KillActivePopup();
    1044           0 :                     sal_uInt16 highlightItem = pFloat->GetHighlightedItem();
    1045           0 :                     pFloat->ChangeHighlightItem(highlightItem, false);
    1046             :                 }
    1047             :             }
    1048             :         }
    1049           0 :         break;
    1050             :         case KEY_RIGHT:
    1051             :         {
    1052           0 :             if( pMenu )
    1053             :             {
    1054           0 :                 bool bDone = false;
    1055           0 :                 if ( nHighlightedItem != ITEMPOS_INVALID )
    1056             :                 {
    1057           0 :                     MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
    1058           0 :                     if ( pData && pData->pSubMenu )
    1059             :                     {
    1060           0 :                         HighlightChanged( 0 );
    1061           0 :                         bDone = true;
    1062             :                     }
    1063             :                 }
    1064           0 :                 if ( !bDone )
    1065             :                 {
    1066           0 :                     Menu* pStart = pMenu->ImplGetStartMenu();
    1067           0 :                     if (pStart && pStart->IsMenuBar())
    1068             :                     {
    1069             :                         // Forward...
    1070           0 :                         pStart->ImplGetWindow()->KeyInput( rKEvent );
    1071             :                     }
    1072             :                 }
    1073             :             }
    1074             :         }
    1075           0 :         break;
    1076             :         case KEY_RETURN:
    1077             :         {
    1078           0 :             if( pMenu )
    1079             :             {
    1080           0 :                 MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
    1081           0 :                 if ( pData && pData->bEnabled )
    1082             :                 {
    1083           0 :                     if ( pData->pSubMenu )
    1084           0 :                         HighlightChanged( 0 );
    1085             :                     else
    1086           0 :                         EndExecute();
    1087             :                 }
    1088             :                 else
    1089           0 :                     StopExecute();
    1090             :             }
    1091             :         }
    1092           0 :         break;
    1093             :         case KEY_MENU:
    1094             :         {
    1095           0 :             if( pMenu )
    1096             :             {
    1097           0 :                 Menu* pStart = pMenu->ImplGetStartMenu();
    1098           0 :                 if (pStart && pStart->IsMenuBar())
    1099             :                 {
    1100             :                     // Forward...
    1101           0 :                     pStart->ImplGetWindow()->KeyInput( rKEvent );
    1102             :                 }
    1103             :             }
    1104             :         }
    1105           0 :         break;
    1106             :         default:
    1107             :         {
    1108           0 :             sal_Unicode nCharCode = rKEvent.GetCharCode();
    1109           0 :             sal_uInt16 nPos = 0;
    1110           0 :             sal_uInt16 nDuplicates = 0;
    1111           0 :             MenuItemData* pData = (nCharCode && pMenu) ? pMenu->GetItemList()->SearchItem( nCharCode, rKEvent.GetKeyCode(), nPos, nDuplicates, nHighlightedItem ) : NULL;
    1112           0 :             if ( pData )
    1113             :             {
    1114           0 :                 if ( pData->pSubMenu || nDuplicates > 1 )
    1115             :                 {
    1116           0 :                     ChangeHighlightItem( nPos, false );
    1117           0 :                     HighlightChanged( 0 );
    1118             :                 }
    1119             :                 else
    1120             :                 {
    1121           0 :                     nHighlightedItem = nPos;
    1122           0 :                     EndExecute();
    1123             :                 }
    1124             :             }
    1125             :             else
    1126           0 :                 FloatingWindow::KeyInput( rKEvent );
    1127             :         }
    1128             :     }
    1129             :     // #105474# check if menu window was not destroyed
    1130           0 :     if ( !aDelData.IsDead() )
    1131             :     {
    1132           0 :         ImplRemoveDel( &aDelData );
    1133           0 :         bKeyInput = false;
    1134           0 :     }
    1135           0 : }
    1136             : 
    1137           8 : void MenuFloatingWindow::Paint(vcl::RenderContext& rRenderContext, const Rectangle &rPaintRect)
    1138             : {
    1139           8 :     if (!pMenu)
    1140           8 :         return;
    1141             : 
    1142           8 :     rRenderContext.Push( PushFlags::CLIPREGION );
    1143           8 :     rRenderContext.SetClipRegion(vcl::Region(rPaintRect));
    1144             : 
    1145           8 :     if (rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
    1146             :     {
    1147           0 :         rRenderContext.SetClipRegion();
    1148           0 :         long nX = pMenu->pLogo ? pMenu->pLogo->aBitmap.GetSizePixel().Width() : 0;
    1149           0 :         Size aPxSize(rRenderContext.GetOutputSizePixel());
    1150           0 :         aPxSize.Width() -= nX;
    1151           0 :         ImplControlValue aVal(pMenu->nTextPos - GUTTERBORDER);
    1152             :         rRenderContext.DrawNativeControl(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL,
    1153             :                                          Rectangle(Point(nX, 0), aPxSize),
    1154           0 :                                          ControlState::ENABLED, aVal, OUString());
    1155           0 :         InitMenuClipRegion(rRenderContext);
    1156             :     }
    1157           8 :     if (IsScrollMenu())
    1158             :     {
    1159           0 :         ImplDrawScroller(rRenderContext, true);
    1160           0 :         ImplDrawScroller(rRenderContext, false);
    1161             :     }
    1162           8 :     rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetMenuColor());
    1163           8 :     pMenu->ImplPaint(rRenderContext, nScrollerHeight, ImplGetStartY());
    1164           8 :     if (nHighlightedItem != ITEMPOS_INVALID)
    1165           0 :         RenderHighlightItem(rRenderContext, nHighlightedItem, true);
    1166             : 
    1167           8 :     rRenderContext.Pop();
    1168             : }
    1169             : 
    1170           0 : void MenuFloatingWindow::ImplDrawScroller(vcl::RenderContext& rRenderContext, bool bUp)
    1171             : {
    1172           0 :     if (!pMenu)
    1173           0 :         return;
    1174             : 
    1175           0 :     rRenderContext.SetClipRegion();
    1176             : 
    1177           0 :     Size aOutSz = rRenderContext.GetOutputSizePixel();
    1178           0 :     long nY = bUp ? 0 : (aOutSz.Height() - nScrollerHeight);
    1179           0 :     long nX = pMenu->pLogo ? pMenu->pLogo->aBitmap.GetSizePixel().Width() : 0;
    1180           0 :     Rectangle aRect(Point(nX, nY), Size(aOutSz.Width() - nX, nScrollerHeight));
    1181             : 
    1182           0 :     DecorationView aDecoView(&rRenderContext);
    1183           0 :     SymbolType eSymbol = bUp ? SymbolType::SPIN_UP : SymbolType::SPIN_DOWN;
    1184             : 
    1185           0 :     DrawSymbolFlags nStyle = DrawSymbolFlags::NONE;
    1186           0 :     if ((bUp && !bScrollUp) || (!bUp && !bScrollDown))
    1187           0 :         nStyle |= DrawSymbolFlags::Disable;
    1188             : 
    1189           0 :     aDecoView.DrawSymbol(aRect, eSymbol, rRenderContext.GetSettings().GetStyleSettings().GetButtonTextColor(), nStyle);
    1190             : 
    1191           0 :     InitMenuClipRegion(rRenderContext);
    1192             : }
    1193             : 
    1194           0 : void MenuFloatingWindow::RequestHelp( const HelpEvent& rHEvt )
    1195             : {
    1196           0 :     sal_uInt16 nId = nHighlightedItem;
    1197           0 :     Menu* pM = pMenu;
    1198           0 :     vcl::Window* pW = this;
    1199             : 
    1200             :     // #102618# Get item rect before destroying the window in EndExecute() call
    1201           0 :     Rectangle aHighlightRect( ImplGetItemRect( nHighlightedItem ) );
    1202             : 
    1203           0 :     if ( rHEvt.GetMode() & (HelpEventMode::CONTEXT | HelpEventMode::EXTENDED) )
    1204             :     {
    1205           0 :         nHighlightedItem = ITEMPOS_INVALID;
    1206           0 :         EndExecute();
    1207           0 :         pW = NULL;
    1208             :     }
    1209             : 
    1210           0 :     if( !ImplHandleHelpEvent( pW, pM, nId, rHEvt, aHighlightRect ) )
    1211           0 :         Window::RequestHelp( rHEvt );
    1212           0 : }
    1213             : 
    1214          24 : void MenuFloatingWindow::StateChanged( StateChangedType nType )
    1215             : {
    1216          24 :     FloatingWindow::StateChanged( nType );
    1217             : 
    1218          24 :     if ( ( nType == StateChangedType::ControlForeground ) || ( nType == StateChangedType::ControlBackground ) )
    1219             :     {
    1220           0 :         ApplySettings(*this);
    1221           0 :         Invalidate();
    1222             :     }
    1223          24 : }
    1224             : 
    1225           0 : void MenuFloatingWindow::DataChanged( const DataChangedEvent& rDCEvt )
    1226             : {
    1227           0 :     FloatingWindow::DataChanged( rDCEvt );
    1228             : 
    1229           0 :     if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
    1230           0 :          (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
    1231           0 :          ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
    1232           0 :           (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
    1233             :     {
    1234           0 :         ApplySettings(*this);
    1235           0 :         Invalidate();
    1236             :     }
    1237           0 : }
    1238             : 
    1239           0 : void MenuFloatingWindow::Command( const CommandEvent& rCEvt )
    1240             : {
    1241           0 :     if ( rCEvt.GetCommand() == CommandEventId::Wheel )
    1242             :     {
    1243           0 :         const CommandWheelData* pData = rCEvt.GetWheelData();
    1244           0 :         if( !pData->GetModifier() && ( pData->GetMode() == CommandWheelMode::SCROLL ) )
    1245             :         {
    1246           0 :             ImplScroll( pData->GetDelta() > 0L );
    1247           0 :             MouseMove( MouseEvent( GetPointerPosPixel(), 0 ) );
    1248             :         }
    1249             :     }
    1250           0 : }
    1251             : 
    1252           0 : css::uno::Reference<css::accessibility::XAccessible> MenuFloatingWindow::CreateAccessible()
    1253             : {
    1254           0 :     css::uno::Reference<css::accessibility::XAccessible> xAcc;
    1255             : 
    1256           0 :     if (pMenu && !pMenu->pStartedFrom)
    1257           0 :         xAcc = pMenu->GetAccessible();
    1258             : 
    1259           0 :     return xAcc;
    1260             : }
    1261             : 
    1262             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11