Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/window/menubarwindow.cxx
Line
Count
Source
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 "menubarwindow.hxx"
21
#include "menuitemlist.hxx"
22
#include "menufloatingwindow.hxx"
23
24
#include <vcl/dockingarea.hxx>
25
#include <vcl/settings.hxx>
26
#include <vcl/taskpanelist.hxx>
27
#include <sal/log.hxx>
28
29
#include <salframe.hxx>
30
#include <salmenu.hxx>
31
#include <svdata.hxx>
32
#include <strings.hrc>
33
#include <bitmaps.hlst>
34
#include <window.h>
35
#include "bufferdevice.hxx"
36
#include <menubarvalue.hxx>
37
38
// document closing button
39
0
#define IID_DOCUMENTCLOSE 1
40
41
DecoToolBox::DecoToolBox( vcl::Window* pParent ) :
42
0
    ToolBox( pParent, 0 ),
43
0
    lastSize(-1)
44
0
{
45
0
    calcMinSize();
46
0
}
Unexecuted instantiation: DecoToolBox::DecoToolBox(vcl::Window*)
Unexecuted instantiation: DecoToolBox::DecoToolBox(vcl::Window*)
47
48
void DecoToolBox::DataChanged( const DataChangedEvent& rDCEvt )
49
0
{
50
0
    Window::DataChanged( rDCEvt );
51
52
0
    if ( rDCEvt.GetFlags() & AllSettingsFlags::STYLE )
53
0
    {
54
0
        calcMinSize();
55
0
        SetBackground();
56
0
        SetImages( 0, true);
57
0
    }
58
0
}
59
60
void DecoToolBox::calcMinSize()
61
0
{
62
0
    ScopedVclPtrInstance<ToolBox> aTbx( GetParent() );
63
0
    if( GetItemCount() == 0 )
64
0
    {
65
0
        aTbx->InsertItem(ToolBoxItemId(IID_DOCUMENTCLOSE), Image(StockImage::Yes, SV_RESID_BITMAP_CLOSEDOC));
66
0
    }
67
0
    else
68
0
    {
69
0
        ImplToolItems::size_type nItems = GetItemCount();
70
0
        for( ImplToolItems::size_type i = 0; i < nItems; i++ )
71
0
        {
72
0
            ToolBoxItemId nId = GetItemId( i );
73
0
            aTbx->InsertItem( nId, GetItemImage( nId ) );
74
0
        }
75
0
    }
76
0
    maMinSize = aTbx->CalcWindowSizePixel();
77
78
0
    aTbx.disposeAndClear();
79
0
}
80
81
void DecoToolBox::SetImages( tools::Long nMaxHeight, bool bForce )
82
0
{
83
0
    tools::Long border = getMinSize().Height() - maImage.GetSizePixel().Height();
84
85
0
    if( !nMaxHeight && lastSize != -1 )
86
0
        nMaxHeight = lastSize + border; // don't change anything if called with 0
87
88
0
    if( nMaxHeight < getMinSize().Height() )
89
0
        nMaxHeight = getMinSize().Height();
90
91
0
    if( (lastSize == nMaxHeight - border) && !bForce )
92
0
        return;
93
94
0
    lastSize = nMaxHeight - border;
95
96
0
    Bitmap    aBmpDst( maImage.GetBitmap() );
97
0
    Bitmap    aBmpSrc( aBmpDst );
98
99
0
    aBmpDst.Erase( Color( ColorAlpha, 0, 255, 255, 255 ) );
100
0
    aBmpDst.Scale( Size( lastSize, lastSize ) );
101
102
0
    tools::Rectangle aSrcRect( Point(0,0), maImage.GetSizePixel() );
103
0
    tools::Rectangle aDestRect( Point((lastSize - maImage.GetSizePixel().Width())/2,
104
0
                            (lastSize - maImage.GetSizePixel().Height())/2 ),
105
0
                        maImage.GetSizePixel() );
106
107
0
    aBmpDst.CopyPixel( aDestRect, aSrcRect, aBmpSrc );
108
0
    SetItemImage( ToolBoxItemId(IID_DOCUMENTCLOSE), Image( aBmpDst ) );
109
110
0
}
111
112
MenuBarWindow::MenuBarWindow( vcl::Window* pParent ) :
113
0
    Window( pParent, 0 ),
114
0
    m_aCloseBtn(VclPtr<DecoToolBox>::Create(this)),
115
0
    m_aFloatBtn(VclPtr<PushButton>::Create(this, WB_NOPOINTERFOCUS | WB_SMALLSTYLE | WB_RECTSTYLE)),
116
0
    m_aHideBtn(VclPtr<PushButton>::Create(this, WB_NOPOINTERFOCUS | WB_SMALLSTYLE | WB_RECTSTYLE))
117
0
{
118
0
    SetType(WindowType::MENUBARWINDOW);
119
0
    m_pMenu = nullptr;
120
0
    m_pActivePopup = nullptr;
121
0
    m_nHighlightedItem = ITEMPOS_INVALID;
122
0
    m_nRolloveredItem = ITEMPOS_INVALID;
123
0
    mbAutoPopup = true;
124
0
    m_bIgnoreFirstMove = true;
125
0
    SetMBWHideAccel(ImplGetSVData()->maNWFData.mbAutoAccel);
126
0
    SetMBWMenuKey(false);
127
128
0
    m_aCloseBtn->maImage = Image(StockImage::Yes, SV_RESID_BITMAP_CLOSEDOC);
129
130
0
    m_aCloseBtn->SetBackground();
131
0
    m_aCloseBtn->SetPaintTransparent(true);
132
0
    m_aCloseBtn->SetParentClipMode(ParentClipMode::NoClip);
133
134
0
    m_aCloseBtn->InsertItem(ToolBoxItemId(IID_DOCUMENTCLOSE), m_aCloseBtn->maImage);
135
0
    m_aCloseBtn->SetSelectHdl(LINK(this, MenuBarWindow, CloseHdl));
136
0
    m_aCloseBtn->AddEventListener(LINK(this, MenuBarWindow, ToolboxEventHdl));
137
0
    m_aCloseBtn->SetQuickHelpText(ToolBoxItemId(IID_DOCUMENTCLOSE), VclResId(SV_HELPTEXT_CLOSEDOCUMENT));
138
139
0
    m_aFloatBtn->SetSymbol( SymbolType::FLOAT );
140
0
    m_aFloatBtn->SetQuickHelpText(VclResId(SV_HELPTEXT_RESTORE));
141
142
0
    m_aHideBtn->SetSymbol( SymbolType::HIDE );
143
0
    m_aHideBtn->SetQuickHelpText(VclResId(SV_HELPTEXT_MINIMIZE));
144
145
0
    ImplInitStyleSettings();
146
147
0
    AddEventListener(LINK(this, MenuBarWindow, ShowHideListener));
148
0
}
Unexecuted instantiation: MenuBarWindow::MenuBarWindow(vcl::Window*)
Unexecuted instantiation: MenuBarWindow::MenuBarWindow(vcl::Window*)
149
150
MenuBarWindow::~MenuBarWindow()
151
0
{
152
0
    disposeOnce();
153
0
}
154
155
void MenuBarWindow::dispose()
156
0
{
157
0
    m_aCloseBtn->RemoveEventListener(LINK(this, MenuBarWindow, ToolboxEventHdl));
158
0
    RemoveEventListener(LINK(this, MenuBarWindow, ShowHideListener));
159
160
0
    mpParentPopup.disposeAndClear();
161
0
    m_aHideBtn.disposeAndClear();
162
0
    m_aFloatBtn.disposeAndClear();
163
0
    m_aCloseBtn.disposeAndClear();
164
0
    m_pMenu.reset();
165
0
    m_pActivePopup.reset();
166
0
    m_xSaveFocusId.reset();
167
168
0
    Window::dispose();
169
0
}
170
171
void MenuBarWindow::SetMenu( MenuBar* pMen )
172
0
{
173
0
    m_pMenu = pMen;
174
0
    KillActivePopup();
175
0
    m_nHighlightedItem = ITEMPOS_INVALID;
176
0
    if (pMen)
177
0
    {
178
0
        m_aCloseBtn->ShowItem(ToolBoxItemId(IID_DOCUMENTCLOSE), pMen->HasCloseButton());
179
0
        m_aCloseBtn->Show(pMen->HasCloseButton() || !m_aAddButtons.empty());
180
0
        m_aFloatBtn->Show(pMen->HasFloatButton());
181
0
        m_aHideBtn->Show(pMen->HasHideButton());
182
0
    }
183
0
    Invalidate();
184
185
    // show and connect native menubar
186
0
    if( m_pMenu && m_pMenu->ImplGetSalMenu() )
187
0
    {
188
0
        if( m_pMenu->ImplGetSalMenu()->VisibleMenuBar() )
189
0
            ImplGetFrame()->SetMenu( m_pMenu->ImplGetSalMenu() );
190
191
0
        m_pMenu->ImplGetSalMenu()->SetFrame( ImplGetFrame() );
192
0
        m_pMenu->ImplGetSalMenu()->ShowMenuBar(true);
193
0
    }
194
0
}
195
196
void MenuBarWindow::SetHeight(tools::Long nHeight)
197
0
{
198
0
    setPosSizePixel(0, 0, 0, nHeight, PosSizeFlags::Height);
199
0
}
200
201
void MenuBarWindow::ShowButtons( bool bClose, bool bFloat, bool bHide )
202
0
{
203
0
    m_aCloseBtn->ShowItem(ToolBoxItemId(IID_DOCUMENTCLOSE), bClose);
204
0
    m_aCloseBtn->Show(bClose || !m_aAddButtons.empty());
205
0
    if (m_pMenu->mpSalMenu)
206
0
        m_pMenu->mpSalMenu->ShowCloseButton(bClose);
207
0
    m_aFloatBtn->Show( bFloat );
208
0
    m_aHideBtn->Show( bHide );
209
0
    Resize();
210
0
}
211
212
Size const & MenuBarWindow::MinCloseButtonSize() const
213
0
{
214
0
    return m_aCloseBtn->getMinSize();
215
0
}
216
217
IMPL_LINK_NOARG(MenuBarWindow, CloseHdl, ToolBox *, void)
218
0
{
219
0
    if( ! m_pMenu )
220
0
        return;
221
222
0
    if( m_aCloseBtn->GetCurItemId() == ToolBoxItemId(IID_DOCUMENTCLOSE) )
223
0
    {
224
        // #i106052# call close hdl asynchronously to ease handler implementation
225
        // this avoids still being in the handler while the DecoToolBox already
226
        // gets destroyed
227
0
        Application::PostUserEvent(m_pMenu->GetCloseButtonClickHdl());
228
0
    }
229
0
    else
230
0
    {
231
0
        std::map<sal_uInt16,AddButtonEntry>::iterator it = m_aAddButtons.find(sal_uInt16(m_aCloseBtn->GetCurItemId()));
232
0
        if( it != m_aAddButtons.end() )
233
0
        {
234
0
            MenuBarButtonCallbackArg aArg;
235
0
            aArg.nId = it->first;
236
0
            aArg.bHighlight = (sal_uInt16(m_aCloseBtn->GetHighlightItemId()) == it->first);
237
0
            it->second.m_aSelectLink.Call( aArg );
238
0
        }
239
0
    }
240
0
}
241
242
IMPL_LINK( MenuBarWindow, ToolboxEventHdl, VclWindowEvent&, rEvent, void )
243
0
{
244
0
    if( ! m_pMenu )
245
0
        return;
246
247
0
    MenuBarButtonCallbackArg aArg;
248
0
    aArg.nId = 0xffff;
249
0
    aArg.bHighlight = (rEvent.GetId() == VclEventId::ToolboxHighlight);
250
0
    if( rEvent.GetId() == VclEventId::ToolboxHighlight )
251
0
        aArg.nId =sal_uInt16(m_aCloseBtn->GetHighlightItemId());
252
0
    else if( rEvent.GetId() == VclEventId::ToolboxHighlightOff )
253
0
    {
254
0
        auto nPos = static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rEvent.GetData()));
255
0
        aArg.nId = sal_uInt16(m_aCloseBtn->GetItemId(nPos));
256
0
    }
257
0
    std::map< sal_uInt16, AddButtonEntry >::iterator it = m_aAddButtons.find( aArg.nId );
258
0
    if( it != m_aAddButtons.end() )
259
0
    {
260
0
        it->second.m_aHighlightLink.Call( aArg );
261
0
    }
262
0
}
263
264
IMPL_LINK( MenuBarWindow, ShowHideListener, VclWindowEvent&, rEvent, void )
265
0
{
266
0
    if( ! m_pMenu )
267
0
        return;
268
269
0
    if( rEvent.GetId() == VclEventId::WindowShow )
270
0
        m_pMenu->ImplCallEventListeners( VclEventId::MenuShow, ITEMPOS_INVALID );
271
0
    else if( rEvent.GetId() == VclEventId::WindowHide )
272
0
        m_pMenu->ImplCallEventListeners( VclEventId::MenuHide, ITEMPOS_INVALID );
273
0
}
274
275
void MenuBarWindow::ImplCreatePopup( bool bPreSelectFirst )
276
0
{
277
0
    MenuItemData* pItemData = m_pMenu ? m_pMenu->GetItemList()->GetDataFromPos( m_nHighlightedItem ) : nullptr;
278
0
    if ( !pItemData )
279
0
        return;
280
281
0
    m_bIgnoreFirstMove = true;
282
0
    if ( m_pActivePopup && ( m_pActivePopup != pItemData->pSubMenu ) )
283
0
    {
284
0
        KillActivePopup();
285
0
    }
286
0
    if ( !(pItemData->bEnabled && pItemData->pSubMenu && ( m_nHighlightedItem != ITEMPOS_INVALID ) &&
287
0
         ( pItemData->pSubMenu != m_pActivePopup )) )
288
0
        return;
289
290
0
    m_pActivePopup = pItemData->pSubMenu.get();
291
0
    tools::Long nX = 0;
292
0
    MenuItemData* pData = nullptr;
293
0
    for ( sal_uLong n = 0; n < m_nHighlightedItem; n++ )
294
0
    {
295
0
        pData = m_pMenu->GetItemList()->GetDataFromPos( n );
296
0
        nX += pData->aSz.Width();
297
0
    }
298
0
    pData = m_pMenu->pItemList->GetDataFromPos( m_nHighlightedItem );
299
0
    Point aItemTopLeft( nX, 0 );
300
0
    Point aItemBottomRight( aItemTopLeft );
301
0
    aItemBottomRight.AdjustX(pData->aSz.Width() );
302
303
0
    if (pData->bHiddenOnGUI)
304
0
    {
305
0
        mpParentPopup.disposeAndClear();
306
0
        mpParentPopup = VclPtr<PopupMenu>::Create();
307
0
        m_pActivePopup = mpParentPopup.get();
308
309
0
        for (sal_uInt16 i = m_nHighlightedItem; i < m_pMenu->GetItemCount(); ++i)
310
0
        {
311
0
            sal_uInt16 nId = m_pMenu->GetItemId(i);
312
313
0
            MenuItemData* pParentItemData = m_pMenu->GetItemList()->GetData(nId);
314
0
            assert(pParentItemData);
315
0
            mpParentPopup->InsertItem(nId, pParentItemData->aText, pParentItemData->nBits, pParentItemData->sIdent);
316
0
            mpParentPopup->SetHelpId(nId, pParentItemData->aHelpId);
317
0
            mpParentPopup->SetHelpText(nId, pParentItemData->aHelpText);
318
0
            mpParentPopup->SetAccelKey(nId, pParentItemData->aAccelKey);
319
0
            mpParentPopup->SetItemCommand(nId, pParentItemData->aCommandStr);
320
0
            mpParentPopup->SetHelpCommand(nId, pParentItemData->aHelpCommandStr);
321
322
0
            PopupMenu* pPopup = m_pMenu->GetPopupMenu(nId);
323
0
            mpParentPopup->SetPopupMenu(nId, pPopup);
324
0
        }
325
0
    }
326
    // the menu bar could have height 0 in fullscreen mode:
327
    // so do not use always WindowHeight, as ItemHeight < WindowHeight.
328
0
    if ( GetSizePixel().Height() )
329
0
    {
330
        // #107747# give menuitems the height of the menubar
331
0
        aItemBottomRight.AdjustY(GetOutputSizePixel().Height()-1 );
332
0
    }
333
334
    // ImplExecute is not modal...
335
    // #99071# do not grab the focus, otherwise it will be restored to the menubar
336
    // when the frame is reactivated later
337
    //GrabFocus();
338
0
    m_pActivePopup->ImplExecute( this, tools::Rectangle( aItemTopLeft, aItemBottomRight ), FloatWinPopupFlags::Down | FloatWinPopupFlags::NoHorzPlacement, m_pMenu, bPreSelectFirst );
339
    // does not have a window, if aborted before or if there are no entries
340
0
    if ( m_pActivePopup->ImplGetFloatingWindow() )
341
0
        m_pActivePopup->ImplGetFloatingWindow()->AddPopupModeWindow( this );
342
0
    else
343
0
        m_pActivePopup = nullptr;
344
0
}
345
346
void MenuBarWindow::KillActivePopup()
347
0
{
348
0
    if ( !m_pActivePopup )
349
0
        return;
350
351
0
    FloatingWindow* pFloatWin = m_pActivePopup->ImplGetFloatingWindow();
352
0
    if (pFloatWin && pFloatWin->IsInCleanUp())
353
0
        return; // kill it later
354
355
0
    if ( m_pActivePopup->bInCallback )
356
0
        m_pActivePopup->bCanceled = true;
357
358
0
    m_pActivePopup->bInCallback = true;
359
0
    m_pActivePopup->Deactivate();
360
0
    m_pActivePopup->bInCallback = false;
361
    // check for pActivePopup, if stopped by deactivate...
362
0
    if (m_pActivePopup->GetWindow())
363
0
    {
364
0
        if (mpParentPopup)
365
0
        {
366
0
            for (sal_uInt16 i = 0; i < mpParentPopup->GetItemCount(); ++i)
367
0
            {
368
0
                sal_uInt16 nId = mpParentPopup->GetItemId(i);
369
0
                MenuItemData* pParentItemData = mpParentPopup->GetItemList()->GetData(nId);
370
0
                assert(pParentItemData);
371
0
                pParentItemData->pSubMenu = nullptr;
372
0
            }
373
0
        }
374
0
        m_pActivePopup->ImplGetFloatingWindow()->StopExecute();
375
0
        m_pActivePopup->ImplGetFloatingWindow()->doShutdown();
376
0
        m_pActivePopup->m_pWindow.disposeAndClear();
377
0
    }
378
0
    m_pActivePopup = nullptr;
379
0
}
380
381
void MenuBarWindow::PopupClosed( Menu const * pPopup )
382
0
{
383
0
    if ( pPopup == m_pActivePopup )
384
0
    {
385
0
        KillActivePopup();
386
0
        ChangeHighlightItem( ITEMPOS_INVALID, false, ImplGetFrameWindow()->ImplGetFrameData()->mbHasFocus, false );
387
0
    }
388
0
}
389
390
void MenuBarWindow::MouseButtonDown( const MouseEvent& rMEvt )
391
0
{
392
0
    mbAutoPopup = true;
393
0
    SetMBWMenuKey(false);
394
0
    sal_uInt16 nEntry = ImplFindEntry( rMEvt.GetPosPixel() );
395
0
    if ( ( nEntry != ITEMPOS_INVALID ) && !m_pActivePopup )
396
0
    {
397
0
        ChangeHighlightItem( nEntry, false );
398
0
    }
399
0
    else
400
0
    {
401
0
        KillActivePopup();
402
0
        ChangeHighlightItem( ITEMPOS_INVALID, false );
403
0
    }
404
0
}
405
406
void MenuBarWindow::MouseButtonUp( const MouseEvent& )
407
0
{
408
0
}
409
410
void MenuBarWindow::MouseMove( const MouseEvent& rMEvt )
411
0
{
412
0
    if ( rMEvt.IsSynthetic() || rMEvt.IsEnterWindow() )
413
0
        return;
414
415
0
    if ( rMEvt.IsLeaveWindow() )
416
0
    {
417
0
        if ( m_nRolloveredItem != ITEMPOS_INVALID && m_nRolloveredItem != m_nHighlightedItem )
418
0
        {
419
            // there is a spurious MouseMove generated after a menu is launched from the keyboard, hence this...
420
0
            if (m_nHighlightedItem != ITEMPOS_INVALID)
421
0
            {
422
0
                bool hide = GetMBWHideAccel();
423
0
                SetMBWHideAccel(ImplGetSVData()->maNWFData.mbAutoAccel);
424
0
                Invalidate(); //HighlightItem( nRolloveredItem, false );
425
0
                SetMBWHideAccel(hide);
426
0
            }
427
0
            else
428
0
                Invalidate(); //HighlightItem( nRolloveredItem, false );
429
0
        }
430
431
0
        m_nRolloveredItem = ITEMPOS_INVALID;
432
0
        return;
433
0
    }
434
435
0
    sal_uInt16 nEntry = ImplFindEntry( rMEvt.GetPosPixel() );
436
0
    if ( m_nHighlightedItem == ITEMPOS_INVALID )
437
0
    {
438
0
        if ( m_nRolloveredItem != nEntry  )
439
0
        {
440
0
            if ( m_nRolloveredItem != ITEMPOS_INVALID )
441
0
                Invalidate(); //HighlightItem( nRolloveredItem, false );
442
443
0
            m_nRolloveredItem = nEntry;
444
0
            Invalidate(); //HighlightItem( nRolloveredItem, true );
445
0
        }
446
0
        return;
447
0
    }
448
0
    m_nRolloveredItem = nEntry;
449
450
0
    if( m_bIgnoreFirstMove )
451
0
    {
452
0
        m_bIgnoreFirstMove = false;
453
0
        return;
454
0
    }
455
456
0
    if ( ( nEntry != ITEMPOS_INVALID )
457
0
       && ( nEntry != m_nHighlightedItem ) )
458
0
        ChangeHighlightItem( nEntry, false );
459
0
}
460
461
void MenuBarWindow::ChangeHighlightItem( sal_uInt16 n, bool bSelectEntry, bool bAllowRestoreFocus, bool bDefaultToDocument)
462
0
{
463
0
    if( ! m_pMenu )
464
0
        return;
465
466
0
    if (n == ITEMPOS_INVALID)
467
0
        SetMBWHideAccel(ImplGetSVData()->maNWFData.mbAutoAccel);
468
469
    // #57934# close active popup if applicable, as TH's background storage works.
470
0
    MenuItemData* pNextData = m_pMenu->pItemList->GetDataFromPos( n );
471
0
    if (m_pActivePopup && m_pActivePopup->GetWindow() && (!pNextData || (m_pActivePopup != pNextData->pSubMenu)))
472
0
        KillActivePopup(); // pActivePopup when applicable without pWin, if Rescheduled in  Activate()
473
474
    // activate menubar only ones per cycle...
475
0
    bool bJustActivated = false;
476
0
    if ( ( m_nHighlightedItem == ITEMPOS_INVALID ) && ( n != ITEMPOS_INVALID ) )
477
0
    {
478
0
        ImplGetSVData()->mpWinData->mbNoDeactivate = true;
479
        // #105406# avoid saving the focus when we already have the focus
480
0
        bool bNoSaveFocus = (this == ImplGetSVData()->mpWinData->mpFocusWin.get());
481
482
0
        if( m_xSaveFocusId != nullptr )
483
0
        {
484
0
            if (!ImplGetSVData()->mpWinData->mbNoSaveFocus)
485
0
            {
486
0
                 m_xSaveFocusId = nullptr;
487
0
                 if( !bNoSaveFocus )
488
0
                    m_xSaveFocusId = Window::SaveFocus(); // only save focus when initially activated
489
0
            }
490
0
            else {
491
0
                ; // do nothing: we 're activated again from taskpanelist, focus was already saved
492
0
            }
493
0
        }
494
0
        else
495
0
        {
496
0
            if( !bNoSaveFocus )
497
0
                m_xSaveFocusId = Window::SaveFocus(); // only save focus when initially activated
498
0
        }
499
0
        m_pMenu->bInCallback = true;  // set here if Activate overridden
500
0
        m_pMenu->Activate();
501
0
        m_pMenu->bInCallback = false;
502
0
        bJustActivated = true;
503
0
    }
504
0
    else if ( ( m_nHighlightedItem != ITEMPOS_INVALID ) && ( n == ITEMPOS_INVALID ) )
505
0
    {
506
0
        m_pMenu->bInCallback = true;
507
0
        m_pMenu->Deactivate();
508
0
        m_pMenu->bInCallback = false;
509
0
        ImplGetSVData()->mpWinData->mbNoDeactivate = false;
510
0
        if (!ImplGetSVData()->mpWinData->mbNoSaveFocus)
511
0
        {
512
0
            VclPtr<vcl::Window> xTempFocusId;
513
0
            if (m_xSaveFocusId && !m_xSaveFocusId->isDisposed())
514
0
                xTempFocusId = m_xSaveFocusId;
515
0
            m_xSaveFocusId = nullptr;
516
517
0
            if (bAllowRestoreFocus)
518
0
            {
519
                // tdf#115227 the popup is already killed, so temporarily set us as the
520
                // focus window, so we could avoid sending superfluous activate events
521
                // to top window listeners.
522
0
                if (xTempFocusId || bDefaultToDocument)
523
0
                    ImplGetSVData()->mpWinData->mpFocusWin = this;
524
525
                // #105406# restore focus to document if we could not save focus before
526
0
                if (!xTempFocusId && bDefaultToDocument)
527
0
                    GrabFocusToDocument();
528
0
                else
529
0
                    Window::EndSaveFocus(xTempFocusId);
530
0
            }
531
0
        }
532
0
    }
533
534
0
    if ( m_nHighlightedItem != ITEMPOS_INVALID )
535
0
    {
536
0
        if ( m_nHighlightedItem != m_nRolloveredItem )
537
0
            Invalidate(); //HighlightItem( nHighlightedItem, false );
538
539
0
        m_pMenu->ImplCallEventListeners( VclEventId::MenuDehighlight, m_nHighlightedItem );
540
0
    }
541
542
0
    m_nHighlightedItem = n;
543
0
    SAL_WARN_IF( ( m_nHighlightedItem != ITEMPOS_INVALID ) && !m_pMenu->ImplIsVisible( m_nHighlightedItem ), "vcl", "ChangeHighlightItem: Not visible!" );
544
0
    if ( m_nHighlightedItem != ITEMPOS_INVALID )
545
0
        Invalidate(); //HighlightItem( nHighlightedItem, true );
546
0
    else if ( m_nRolloveredItem != ITEMPOS_INVALID )
547
0
        Invalidate(); //HighlightItem( nRolloveredItem, true );
548
0
    m_pMenu->ImplCallHighlight(m_nHighlightedItem);
549
550
0
    if( mbAutoPopup )
551
0
        ImplCreatePopup( bSelectEntry );
552
553
    // #58935# #73659# Focus, if no popup underneath...
554
0
    if ( bJustActivated && !m_pActivePopup )
555
0
        GrabFocus();
556
0
}
557
558
static int ImplGetTopDockingAreaHeight( vcl::Window const *pWindow )
559
0
{
560
    // find docking area that is top aligned and return its height
561
    // note: dockingareas are direct children of the SystemWindow
562
0
    if( pWindow->ImplGetFrameWindow() )
563
0
    {
564
0
        vcl::Window *pWin = pWindow->ImplGetFrameWindow()->GetWindow( GetWindowType::FirstChild ); //mpWindowImpl->mpFirstChild;
565
0
        while( pWin )
566
0
        {
567
0
            if( pWin->IsSystemWindow() )
568
0
            {
569
0
                vcl::Window *pChildWin = pWin->GetWindow( GetWindowType::FirstChild ); //mpWindowImpl->mpFirstChild;
570
0
                while( pChildWin )
571
0
                {
572
0
                    DockingAreaWindow *pDockingArea = nullptr;
573
0
                    if ( pChildWin->GetType() == WindowType::DOCKINGAREA )
574
0
                        pDockingArea = static_cast< DockingAreaWindow* >( pChildWin );
575
576
0
                    if( pDockingArea && pDockingArea->GetAlign() == WindowAlign::Top &&
577
0
                        pDockingArea->IsVisible() && pDockingArea->GetOutputSizePixel().Height() != 0 )
578
0
                    {
579
0
                        return pDockingArea->GetOutputSizePixel().Height();
580
0
                    }
581
582
0
                    pChildWin = pChildWin->GetWindow( GetWindowType::Next ); //mpWindowImpl->mpNext;
583
0
                }
584
585
0
            }
586
587
0
            pWin = pWin->GetWindow( GetWindowType::Next ); //mpWindowImpl->mpNext;
588
0
        }
589
0
    }
590
0
    return 0;
591
0
}
592
593
static void ImplAddNWFSeparator(vcl::RenderContext& rRenderContext, const Size& rSize, const MenubarValue& rMenubarValue)
594
0
{
595
    // add a separator if
596
    // - we have an adjacent docking area
597
    // - and if toolbars would draw them as well (mbDockingAreaSeparateTB must not be set, see dockingarea.cxx)
598
0
    if (rMenubarValue.maTopDockingAreaHeight
599
0
      && !ImplGetSVData()->maNWFData.mbDockingAreaSeparateTB
600
0
      && !ImplGetSVData()->maNWFData.mbDockingAreaAvoidTBFrames)
601
0
    {
602
        // note: the menubar only provides the upper (dark) half of it, the rest (bright part) is drawn by the docking area
603
604
0
        rRenderContext.SetLineColor(rRenderContext.GetSettings().GetStyleSettings().GetSeparatorColor());
605
0
        tools::Rectangle aRect(Point(), rSize);
606
0
        rRenderContext.DrawLine(aRect.BottomLeft(), aRect.BottomRight());
607
0
    }
608
0
}
609
610
void MenuBarWindow::HighlightItem(vcl::RenderContext& rRenderContext, sal_uInt16 nPos)
611
0
{
612
0
    if (!m_pMenu)
613
0
        return;
614
615
0
    tools::Long nX = 0;
616
0
    size_t nCount = m_pMenu->pItemList->size();
617
618
0
    Size aOutputSize = GetOutputSizePixel();
619
0
    aOutputSize.AdjustWidth( -(m_aCloseBtn->GetSizePixel().Width()) );
620
621
0
    for (size_t n = 0; n < nCount; n++)
622
0
    {
623
0
        MenuItemData* pData = m_pMenu->pItemList->GetDataFromPos( n );
624
0
        if (n == nPos)
625
0
        {
626
0
            if (pData->eType != MenuItemType::SEPARATOR)
627
0
            {
628
                // #107747# give menuitems the height of the menubar
629
0
                tools::Rectangle aRect(Point(nX, 1), Size(pData->aSz.Width(), aOutputSize.Height() - 2));
630
0
                rRenderContext.Push(vcl::PushFlags::CLIPREGION);
631
0
                rRenderContext.IntersectClipRegion(aRect);
632
0
                bool bRollover, bHighlight;
633
0
                if (!ImplGetSVData()->maNWFData.mbRolloverMenubar)
634
0
                {
635
0
                    bHighlight = true;
636
0
                    bRollover = nPos != m_nHighlightedItem;
637
0
                }
638
0
                else
639
0
                {
640
0
                    bRollover = nPos == m_nRolloveredItem;
641
0
                    bHighlight = nPos == m_nHighlightedItem;
642
0
                }
643
0
                if (rRenderContext.IsNativeControlSupported(ControlType::Menubar, ControlPart::MenuItem) &&
644
0
                    rRenderContext.IsNativeControlSupported(ControlType::Menubar, ControlPart::Entire))
645
0
                {
646
                    // draw background (transparency)
647
0
                    MenubarValue aControlValue;
648
0
                    aControlValue.maTopDockingAreaHeight = ImplGetTopDockingAreaHeight( this );
649
650
0
                    tools::Rectangle aBgRegion(Point(), aOutputSize);
651
0
                    rRenderContext.DrawNativeControl(ControlType::Menubar, ControlPart::Entire, aBgRegion,
652
0
                                                     ControlState::ENABLED, aControlValue, OUString());
653
654
0
                    ImplAddNWFSeparator(rRenderContext, aOutputSize, aControlValue);
655
656
                    // draw selected item
657
0
                    ControlState nState = ControlState::ENABLED;
658
0
                    if (bRollover)
659
0
                        nState |= ControlState::ROLLOVER;
660
0
                    else
661
0
                        nState |= ControlState::SELECTED;
662
0
                    rRenderContext.DrawNativeControl(ControlType::Menubar, ControlPart::MenuItem,
663
0
                                                     aRect, nState, aControlValue, OUString() );
664
0
                }
665
0
                else
666
0
                {
667
0
                    if (bRollover)
668
0
                        rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetMenuBarRolloverColor());
669
0
                    else
670
0
                        rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetMenuHighlightColor());
671
0
                    rRenderContext.SetLineColor();
672
0
                    rRenderContext.DrawRect(aRect);
673
0
                }
674
0
                rRenderContext.Pop();
675
676
0
                m_pMenu->ImplPaint(rRenderContext, aOutputSize, 0, 0, pData, bHighlight, false, bRollover);
677
0
            }
678
0
            return;
679
0
        }
680
681
0
        nX += pData->aSz.Width();
682
0
    }
683
0
}
684
685
tools::Rectangle MenuBarWindow::ImplGetItemRect( sal_uInt16 nPos ) const
686
0
{
687
0
    tools::Rectangle aRect;
688
0
    if( m_pMenu )
689
0
    {
690
0
        tools::Long nX = 0;
691
0
        size_t nCount = m_pMenu->pItemList->size();
692
0
        for ( size_t n = 0; n < nCount; n++ )
693
0
        {
694
0
            MenuItemData* pData = m_pMenu->pItemList->GetDataFromPos( n );
695
0
            if ( n == nPos )
696
0
            {
697
0
                if ( pData->eType != MenuItemType::SEPARATOR )
698
                    // #107747# give menuitems the height of the menubar
699
0
                    aRect = tools::Rectangle( Point( nX, 1 ), Size( pData->aSz.Width(), GetOutputSizePixel().Height()-2 ) );
700
0
                break;
701
0
            }
702
703
0
            nX += pData->aSz.Width();
704
0
        }
705
0
    }
706
0
    return aRect;
707
0
}
708
709
void MenuBarWindow::KeyInput( const KeyEvent& rKEvent )
710
0
{
711
0
    if ( !HandleKeyEvent( rKEvent ) )
712
0
        Window::KeyInput( rKEvent );
713
0
}
714
715
bool MenuBarWindow::HandleKeyEvent( const KeyEvent& rKEvent, bool bFromMenu )
716
0
{
717
0
    if (!m_pMenu)
718
0
        return false;
719
720
0
    if (m_pMenu->bInCallback)
721
0
        return true;    // swallow
722
723
0
    bool bDone = false;
724
0
    sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
725
726
0
    if( GetParent() )
727
0
    {
728
0
        if( GetParent()->GetWindow( GetWindowType::Client )->IsSystemWindow() )
729
0
        {
730
0
            SystemWindow *pSysWin = static_cast<SystemWindow*>(GetParent()->GetWindow( GetWindowType::Client ));
731
0
            if( pSysWin->GetTaskPaneList() )
732
0
                if( pSysWin->GetTaskPaneList()->HandleKeyEvent( rKEvent ) )
733
0
                    return true;
734
0
        }
735
0
    }
736
737
    // no key events if native menus
738
0
    if (m_pMenu->ImplGetSalMenu() && m_pMenu->ImplGetSalMenu()->VisibleMenuBar())
739
0
    {
740
0
        return false;
741
0
    }
742
743
0
    if ( nCode == KEY_MENU && !rKEvent.GetKeyCode().IsShift() ) // only F10, not Shift-F10
744
0
    {
745
0
        mbAutoPopup = false;
746
0
        if ( m_nHighlightedItem == ITEMPOS_INVALID )
747
0
        {
748
0
            ChangeHighlightItem( 0, false );
749
0
            GrabFocus();
750
0
        }
751
0
        else
752
0
        {
753
0
            ChangeHighlightItem( ITEMPOS_INVALID, false );
754
0
            m_xSaveFocusId = nullptr;
755
0
        }
756
0
        bDone = true;
757
0
    }
758
0
    else if ( bFromMenu )
759
0
    {
760
0
        if ( ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) ||
761
0
            ( nCode == KEY_HOME ) || ( nCode == KEY_END ) )
762
0
        {
763
0
            sal_uInt16 n = m_nHighlightedItem;
764
0
            if ( n == ITEMPOS_INVALID )
765
0
            {
766
0
                if ( nCode == KEY_LEFT)
767
0
                    n = 0;
768
0
                else
769
0
                    n = m_pMenu->GetItemCount()-1;
770
0
            }
771
772
0
            sal_uInt16 nLoop = n;
773
774
0
            if (nCode == KEY_HOME)
775
0
            {
776
0
                n = ITEMPOS_INVALID;
777
0
                nLoop = 0;
778
0
            }
779
0
            else if (nCode == KEY_END)
780
0
            {
781
0
                n = m_pMenu->GetItemCount();
782
0
                nLoop = n-1;
783
0
            }
784
785
0
            do
786
0
            {
787
0
                if ( nCode == KEY_LEFT || nCode == KEY_END )
788
0
                {
789
0
                    if ( n )
790
0
                        n--;
791
0
                    else
792
0
                        n = m_pMenu->GetItemCount()-1;
793
0
                }
794
0
                if ( nCode == KEY_RIGHT || nCode == KEY_HOME )
795
0
                {
796
0
                    n = (n == ITEMPOS_INVALID) ? 0 : n + 1;
797
0
                    if ( n >= m_pMenu->GetItemCount() )
798
0
                        n = 0;
799
0
                }
800
801
0
                MenuItemData* pData = m_pMenu->GetItemList()->GetDataFromPos( n );
802
0
                if (pData->eType != MenuItemType::SEPARATOR &&
803
0
                    m_pMenu->ImplIsVisible(n) &&
804
0
                    !m_pMenu->ImplCurrentlyHiddenOnGUI(n))
805
0
                {
806
0
                    ChangeHighlightItem( n, true );
807
0
                    break;
808
0
                }
809
0
            } while ( n != nLoop );
810
0
            bDone = true;
811
0
        }
812
0
        else if ( nCode == KEY_RETURN )
813
0
        {
814
0
            if( m_pActivePopup ) KillActivePopup();
815
0
            else
816
0
                if ( !mbAutoPopup )
817
0
                {
818
0
                    ImplCreatePopup( true );
819
0
                    mbAutoPopup = true;
820
0
                }
821
0
            bDone = true;
822
0
        }
823
0
        else if ( ( nCode == KEY_UP ) || ( nCode == KEY_DOWN ) )
824
0
        {
825
0
            if ( !mbAutoPopup )
826
0
            {
827
0
                ImplCreatePopup( true );
828
0
                mbAutoPopup = true;
829
0
            }
830
0
            bDone = true;
831
0
        }
832
0
        else if ( nCode == KEY_ESCAPE || ( nCode == KEY_F6 && rKEvent.GetKeyCode().IsMod1() ) )
833
0
        {
834
0
            if( m_pActivePopup )
835
0
            {
836
                // hide the menu and remove the focus...
837
0
                mbAutoPopup = false;
838
0
                KillActivePopup();
839
0
            }
840
841
0
            ChangeHighlightItem( ITEMPOS_INVALID, false );
842
843
0
            if( nCode == KEY_F6 && rKEvent.GetKeyCode().IsMod1() )
844
0
            {
845
                // put focus into document
846
0
                GrabFocusToDocument();
847
0
            }
848
849
0
            bDone = true;
850
0
        }
851
0
    }
852
853
0
    if ( !bDone && ( bFromMenu || rKEvent.GetKeyCode().IsMod2() ) )
854
0
    {
855
0
        sal_Unicode nCharCode = rKEvent.GetCharCode();
856
0
        if ( nCharCode )
857
0
        {
858
0
            size_t nEntry, nDuplicates;
859
0
            MenuItemData* pData = m_pMenu->GetItemList()->SearchItem( nCharCode, rKEvent.GetKeyCode(), nEntry, nDuplicates, m_nHighlightedItem );
860
0
            if ( pData && (nEntry != ITEMPOS_INVALID) )
861
0
            {
862
0
                mbAutoPopup = true;
863
0
                ChangeHighlightItem( nEntry, true );
864
0
                bDone = true;
865
0
            }
866
0
        }
867
0
    }
868
869
0
    return bDone;
870
0
}
871
872
void MenuBarWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
873
0
{
874
0
    if (!m_pMenu)
875
0
        return;
876
877
0
    const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
878
879
0
    Size aOutputSize = GetOutputSizePixel();
880
881
    // no VCL paint if native menus
882
0
    if (m_pMenu->ImplGetSalMenu() && m_pMenu->ImplGetSalMenu()->VisibleMenuBar())
883
0
        return;
884
885
    // Make sure that all actual rendering happens in one go to avoid flicker.
886
0
    vcl::BufferDevice pBuffer(this, rRenderContext);
887
888
0
    if (rRenderContext.IsNativeControlSupported(ControlType::Menubar, ControlPart::Entire))
889
0
    {
890
0
        MenubarValue aMenubarValue;
891
0
        aMenubarValue.maTopDockingAreaHeight = ImplGetTopDockingAreaHeight(this);
892
893
0
        tools::Rectangle aCtrlRegion( Point(), aOutputSize );
894
895
0
        pBuffer->DrawNativeControl(ControlType::Menubar, ControlPart::Entire, aCtrlRegion,
896
0
                                   ControlState::ENABLED, aMenubarValue, OUString());
897
898
0
        ImplAddNWFSeparator(*pBuffer, aOutputSize, aMenubarValue);
899
0
    }
900
901
    // shrink the area of the buttons
902
0
    aOutputSize.AdjustWidth( -(m_aCloseBtn->GetSizePixel().Width()) );
903
904
0
    pBuffer->SetFillColor(rStyleSettings.GetMenuColor());
905
0
    m_pMenu->ImplPaint(*pBuffer, aOutputSize, 0);
906
907
0
    if (m_nHighlightedItem != ITEMPOS_INVALID && m_pMenu && !m_pMenu->GetItemList()->GetDataFromPos(m_nHighlightedItem)->bHiddenOnGUI)
908
0
        HighlightItem(*pBuffer, m_nHighlightedItem);
909
0
    else if (m_nRolloveredItem != ITEMPOS_INVALID)
910
0
        HighlightItem(*pBuffer, m_nRolloveredItem);
911
912
    // in high contrast mode draw a separating line on the lower edge
913
0
    if (!rRenderContext.IsNativeControlSupported( ControlType::Menubar, ControlPart::Entire) &&
914
0
        rStyleSettings.GetHighContrastMode())
915
0
    {
916
0
        auto popIt = pBuffer->ScopedPush(vcl::PushFlags::LINECOLOR | vcl::PushFlags::MAPMODE);
917
0
        pBuffer->SetLineColor(COL_WHITE);
918
0
        pBuffer->SetMapMode(MapMode(MapUnit::MapPixel));
919
0
        Size aSize = GetSizePixel();
920
0
        pBuffer->DrawLine(Point(0, aSize.Height() - 1),
921
0
                          Point(aSize.Width() - 1, aSize.Height() - 1));
922
0
    }
923
0
}
924
925
void MenuBarWindow::Resize()
926
0
{
927
0
    Size aOutSz = GetOutputSizePixel();
928
0
    tools::Long n      = aOutSz.Height()-4;
929
0
    tools::Long nX     = aOutSz.Width()-3;
930
0
    tools::Long nY     = 2;
931
932
0
    if ( m_aCloseBtn->IsVisible() )
933
0
    {
934
0
        m_aCloseBtn->Hide();
935
0
        m_aCloseBtn->SetImages(n);
936
0
        Size aTbxSize( m_aCloseBtn->CalcWindowSizePixel() );
937
0
        nX -= aTbxSize.Width();
938
0
        tools::Long nTbxY = (aOutSz.Height() - aTbxSize.Height())/2;
939
0
        m_aCloseBtn->setPosSizePixel(nX, nTbxY, aTbxSize.Width(), aTbxSize.Height());
940
0
        nX -= 3;
941
0
        m_aCloseBtn->Show();
942
0
    }
943
0
    if ( m_aFloatBtn->IsVisible() )
944
0
    {
945
0
        nX -= n;
946
0
        m_aFloatBtn->setPosSizePixel( nX, nY, n, n );
947
0
    }
948
0
    if ( m_aHideBtn->IsVisible() )
949
0
    {
950
0
        nX -= n;
951
0
        m_aHideBtn->setPosSizePixel( nX, nY, n, n );
952
0
    }
953
954
0
    m_aFloatBtn->SetSymbol( SymbolType::FLOAT );
955
0
    m_aHideBtn->SetSymbol( SymbolType::HIDE );
956
957
0
    Invalidate();
958
0
}
959
960
sal_uInt16 MenuBarWindow::ImplFindEntry( const Point& rMousePos ) const
961
0
{
962
0
    if( m_pMenu )
963
0
    {
964
0
        tools::Long nX = 0;
965
0
        size_t nCount = m_pMenu->pItemList->size();
966
0
        for ( size_t n = 0; n < nCount; n++ )
967
0
        {
968
0
            MenuItemData* pData = m_pMenu->pItemList->GetDataFromPos( n );
969
0
            if ( m_pMenu->ImplIsVisible( n ) )
970
0
            {
971
0
                nX += pData->aSz.Width();
972
0
                if ( nX > rMousePos.X() )
973
0
                    return static_cast<sal_uInt16>(n);
974
0
            }
975
0
        }
976
0
    }
977
0
    return ITEMPOS_INVALID;
978
0
}
979
980
void MenuBarWindow::RequestHelp( const HelpEvent& rHEvt )
981
0
{
982
0
    sal_uInt16 nId = m_nHighlightedItem;
983
0
    if ( rHEvt.GetMode() & HelpEventMode::CONTEXT )
984
0
        ChangeHighlightItem( ITEMPOS_INVALID, true );
985
986
0
    tools::Rectangle aHighlightRect( ImplGetItemRect( m_nHighlightedItem ) );
987
0
    if( !ImplHandleHelpEvent( this, m_pMenu, nId, rHEvt, aHighlightRect ) )
988
0
        Window::RequestHelp( rHEvt );
989
0
}
990
991
void MenuBarWindow::StateChanged( StateChangedType nType )
992
0
{
993
0
    Window::StateChanged( nType );
994
995
0
    if (nType == StateChangedType::ControlForeground ||
996
0
        nType == StateChangedType::ControlBackground)
997
0
    {
998
0
        ApplySettings(*GetOutDev());
999
0
        Invalidate();
1000
0
    }
1001
0
    else if (nType == StateChangedType::Enable)
1002
0
    {
1003
0
        Invalidate();
1004
0
    }
1005
0
    else if(m_pMenu)
1006
0
    {
1007
0
        m_pMenu->ImplKillLayoutData();
1008
0
    }
1009
0
}
1010
1011
void MenuBarWindow::LayoutChanged()
1012
0
{
1013
0
    if (!m_pMenu)
1014
0
        return;
1015
1016
0
    ApplySettings(*GetOutDev());
1017
1018
    // if the font was changed.
1019
0
    tools::Long nHeight = m_pMenu->ImplCalcSize(this).Height();
1020
1021
    // depending on the native implementation or the displayable flag
1022
    // the menubar windows is suppressed (ie, height=0)
1023
0
    if (!m_pMenu->IsDisplayable() ||
1024
0
        (m_pMenu->ImplGetSalMenu() && m_pMenu->ImplGetSalMenu()->VisibleMenuBar()))
1025
0
    {
1026
0
        nHeight = 0;
1027
0
    }
1028
0
    setPosSizePixel(0, 0, 0, nHeight, PosSizeFlags::Height);
1029
0
    GetParent()->Resize();
1030
0
    Invalidate();
1031
0
    Resize();
1032
1033
0
    m_pMenu->ImplKillLayoutData();
1034
0
}
1035
1036
void MenuBarWindow::ApplySettings(vcl::RenderContext& rRenderContext)
1037
0
{
1038
0
    Window::ApplySettings(rRenderContext);
1039
0
    const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1040
1041
0
    SetPointFont(rRenderContext, rStyleSettings.GetMenuFont());
1042
1043
0
    if (rRenderContext.IsNativeControlSupported(ControlType::Menubar, ControlPart::Entire))
1044
0
    {
1045
0
        rRenderContext.SetBackground(); // background will be drawn by NWF
1046
0
    }
1047
0
    else
1048
0
    {
1049
0
        Wallpaper aWallpaper;
1050
0
        aWallpaper.SetStyle(WallpaperStyle::ApplicationGradient);
1051
0
        rRenderContext.SetBackground(aWallpaper);
1052
0
        SetPaintTransparent(false);
1053
0
        SetParentClipMode();
1054
0
    }
1055
1056
0
    rRenderContext.SetTextColor(rStyleSettings.GetMenuBarTextColor());
1057
0
    rRenderContext.SetTextFillColor();
1058
0
    rRenderContext.SetLineColor();
1059
0
}
1060
1061
void MenuBarWindow::ImplInitStyleSettings()
1062
0
{
1063
0
    if (!(IsNativeControlSupported(ControlType::Menubar, ControlPart::MenuItem) &&
1064
0
        IsNativeControlSupported(ControlType::Menubar, ControlPart::Entire)))
1065
0
        return;
1066
1067
0
    AllSettings aSettings(GetSettings());
1068
0
    ImplGetFrame()->UpdateSettings(aSettings); // to update persona
1069
0
    StyleSettings aStyle(aSettings.GetStyleSettings());
1070
0
    Color aHighlightTextColor = ImplGetSVData()->maNWFData.maMenuBarHighlightTextColor;
1071
0
    if (aHighlightTextColor != COL_TRANSPARENT)
1072
0
    {
1073
0
        aStyle.SetMenuHighlightTextColor(aHighlightTextColor);
1074
0
    }
1075
0
    aSettings.SetStyleSettings(aStyle);
1076
0
    GetOutDev()->SetSettings(aSettings);
1077
0
}
1078
1079
void MenuBarWindow::DataChanged( const DataChangedEvent& rDCEvt )
1080
0
{
1081
0
    Window::DataChanged( rDCEvt );
1082
1083
0
    if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
1084
0
         (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
1085
0
         ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1086
0
          (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
1087
0
    {
1088
0
        ApplySettings(*GetOutDev());
1089
0
        ImplInitStyleSettings();
1090
0
        LayoutChanged();
1091
0
    }
1092
0
}
1093
1094
void MenuBarWindow::LoseFocus()
1095
0
{
1096
0
    if ( !HasChildPathFocus( true ) )
1097
0
        ChangeHighlightItem( ITEMPOS_INVALID, false, false );
1098
0
}
1099
1100
void MenuBarWindow::GetFocus()
1101
0
{
1102
0
    SalMenu *pNativeMenu = m_pMenu ? m_pMenu->ImplGetSalMenu() : nullptr;
1103
0
    if (pNativeMenu && pNativeMenu->TakeFocus())
1104
0
        return;
1105
1106
0
    if ( m_nHighlightedItem == ITEMPOS_INVALID )
1107
0
    {
1108
0
        mbAutoPopup = false;    // do not open menu when activated by focus handling like taskpane cycling
1109
0
        ChangeHighlightItem( 0, false );
1110
0
    }
1111
0
}
1112
1113
rtl::Reference<comphelper::OAccessible> MenuBarWindow::CreateAccessible()
1114
0
{
1115
0
    if (m_pMenu)
1116
0
        return m_pMenu->GetAccessible();
1117
1118
0
    return {};
1119
0
}
1120
1121
sal_uInt16 MenuBarWindow::AddMenuBarButton( const Image& i_rImage, const Link<MenuBarButtonCallbackArg&,bool>& i_rLink, const OUString& i_rToolTip )
1122
0
{
1123
    // find first free button id
1124
0
    sal_uInt16 nId = IID_DOCUMENTCLOSE;
1125
0
    std::map< sal_uInt16, AddButtonEntry >::const_iterator it;
1126
0
    do
1127
0
    {
1128
0
        nId++;
1129
0
        it = m_aAddButtons.find( nId );
1130
0
    } while( it != m_aAddButtons.end() && nId < 128 );
1131
0
    SAL_WARN_IF( nId >= 128, "vcl", "too many addbuttons in menubar" );
1132
0
    AddButtonEntry& rNewEntry = m_aAddButtons[nId];
1133
0
    rNewEntry.m_aSelectLink = i_rLink;
1134
0
    m_aCloseBtn->InsertItem(ToolBoxItemId(nId), i_rImage, ToolBoxItemBits::NONE, 0);
1135
0
    m_aCloseBtn->calcMinSize();
1136
0
    ShowButtons(m_aCloseBtn->IsItemVisible(ToolBoxItemId(IID_DOCUMENTCLOSE)), m_aFloatBtn->IsVisible(), m_aHideBtn->IsVisible());
1137
0
    LayoutChanged();
1138
1139
0
    if( m_pMenu->mpSalMenu )
1140
0
        m_pMenu->mpSalMenu->AddMenuBarButton( SalMenuButtonItem( nId, i_rImage, i_rToolTip ) );
1141
1142
0
    return nId;
1143
0
}
1144
1145
void MenuBarWindow::SetMenuBarButtonHighlightHdl( sal_uInt16 nId, const Link<MenuBarButtonCallbackArg&,bool>& rLink )
1146
0
{
1147
0
    std::map< sal_uInt16, AddButtonEntry >::iterator it = m_aAddButtons.find( nId );
1148
0
    if( it != m_aAddButtons.end() )
1149
0
        it->second.m_aHighlightLink = rLink;
1150
0
}
1151
1152
tools::Rectangle MenuBarWindow::GetMenuBarButtonRectPixel( sal_uInt16 nId )
1153
0
{
1154
0
    tools::Rectangle aRect;
1155
0
    if( m_aAddButtons.find( nId ) != m_aAddButtons.end() )
1156
0
    {
1157
0
        if( m_pMenu->mpSalMenu )
1158
0
        {
1159
0
            aRect = m_pMenu->mpSalMenu->GetMenuBarButtonRectPixel( nId, ImplGetWindowImpl()->mpFrame );
1160
0
            if( aRect == tools::Rectangle( Point( -1, -1 ), Size( 1, 1 ) ) )
1161
0
            {
1162
                // system menu button is somewhere but location cannot be determined
1163
0
                return tools::Rectangle();
1164
0
            }
1165
0
        }
1166
1167
0
        if( aRect.IsEmpty() )
1168
0
        {
1169
0
            aRect = m_aCloseBtn->GetItemRect(ToolBoxItemId(nId));
1170
0
            Point aOffset = m_aCloseBtn->OutputToScreenPixel(Point());
1171
0
            aRect.Move( aOffset.X(), aOffset.Y() );
1172
0
        }
1173
0
    }
1174
0
    return aRect;
1175
0
}
1176
1177
void MenuBarWindow::RemoveMenuBarButton( sal_uInt16 nId )
1178
0
{
1179
0
    ToolBox::ImplToolItems::size_type nPos = m_aCloseBtn->GetItemPos(ToolBoxItemId(nId));
1180
0
    m_aCloseBtn->RemoveItem(nPos);
1181
0
    m_aAddButtons.erase( nId );
1182
0
    m_aCloseBtn->calcMinSize();
1183
0
    LayoutChanged();
1184
1185
0
    if( m_pMenu->mpSalMenu )
1186
0
        m_pMenu->mpSalMenu->RemoveMenuBarButton( nId );
1187
0
}
1188
1189
bool MenuBarWindow::HandleMenuButtonEvent( sal_uInt16 i_nButtonId )
1190
0
{
1191
0
    std::map< sal_uInt16, AddButtonEntry >::iterator it = m_aAddButtons.find( i_nButtonId );
1192
0
    if( it != m_aAddButtons.end() )
1193
0
    {
1194
0
        MenuBarButtonCallbackArg aArg;
1195
0
        aArg.nId = it->first;
1196
0
        aArg.bHighlight = true;
1197
0
        return it->second.m_aSelectLink.Call( aArg );
1198
0
    }
1199
0
    return false;
1200
0
}
1201
1202
bool MenuBarWindow::CanGetFocus() const
1203
0
{
1204
    /* #i83908# do not use the menubar if it is native or invisible
1205
       this relies on MenuBar::ImplCreate setting the height of the menubar
1206
       to 0 in this case
1207
    */
1208
0
    SalMenu *pNativeMenu = m_pMenu ? m_pMenu->ImplGetSalMenu() : nullptr;
1209
0
    if (pNativeMenu && pNativeMenu->VisibleMenuBar())
1210
0
        return pNativeMenu->CanGetFocus();
1211
0
    return GetSizePixel().Height() > 0;
1212
0
}
1213
1214
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */