Coverage Report

Created: 2026-05-16 09:25

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