Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/window/event.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 <vcl/event.hxx>
21
#include <vcl/window.hxx>
22
#include <vcl/dockwin.hxx>
23
#include <vcl/layout.hxx>
24
#include <sal/log.hxx>
25
26
#include <window.h>
27
#include <svdata.hxx>
28
#include <salframe.hxx>
29
#include <config_features.h>
30
#include <comphelper/scopeguard.hxx>
31
32
#include "impldockingwrapper.hxx"
33
34
namespace vcl {
35
36
void Window::DataChanged( const DataChangedEvent& )
37
2
{
38
2
}
39
40
void Window::NotifyAllChildren( DataChangedEvent& rDCEvt )
41
0
{
42
0
    CompatDataChanged( rDCEvt );
43
44
0
    vcl::Window* pChild = mpWindowImpl->mpFirstChild;
45
0
    while ( pChild )
46
0
    {
47
0
        pChild->NotifyAllChildren( rDCEvt );
48
0
        pChild = pChild->mpWindowImpl->mpNext;
49
0
    }
50
0
}
51
52
bool Window::PreNotify( NotifyEvent& rNEvt )
53
0
{
54
0
    bool bDone = false;
55
0
    if ( mpWindowImpl->mpParent && !ImplIsOverlapWindow() )
56
0
        bDone = mpWindowImpl->mpParent->CompatPreNotify( rNEvt );
57
58
0
    if ( !bDone )
59
0
    {
60
0
        if( rNEvt.GetType() == NotifyEventType::GETFOCUS )
61
0
        {
62
0
            bool bCompoundFocusChanged = false;
63
0
            if ( mpWindowImpl->mbCompoundControl && !mpWindowImpl->mbCompoundControlHasFocus && HasChildPathFocus() )
64
0
            {
65
0
                mpWindowImpl->mbCompoundControlHasFocus = true;
66
0
                bCompoundFocusChanged = true;
67
0
            }
68
69
0
            if ( bCompoundFocusChanged || ( rNEvt.GetWindow() == this ) )
70
0
                CallEventListeners( VclEventId::WindowGetFocus );
71
0
        }
72
0
        else if( rNEvt.GetType() == NotifyEventType::LOSEFOCUS )
73
0
        {
74
0
            bool bCompoundFocusChanged = false;
75
0
            if ( mpWindowImpl->mbCompoundControl && mpWindowImpl->mbCompoundControlHasFocus && !HasChildPathFocus() )
76
0
            {
77
0
                mpWindowImpl->mbCompoundControlHasFocus = false ;
78
0
                bCompoundFocusChanged = true;
79
0
            }
80
81
0
            if ( bCompoundFocusChanged || ( rNEvt.GetWindow() == this ) )
82
0
                CallEventListeners( VclEventId::WindowLoseFocus );
83
0
        }
84
85
        // #82968# mouse and key events will be notified after processing ( in ImplNotifyKeyMouseCommandEventListeners() )!
86
        //    see also ImplHandleMouseEvent(), ImplHandleKey()
87
88
0
    }
89
90
0
    return bDone;
91
0
}
92
93
namespace
94
{
95
    bool parentNotDialogControl(Window* pWindow)
96
0
    {
97
0
        vcl::Window* pParent = getNonLayoutParent(pWindow);
98
0
        if (!pParent)
99
0
            return true;
100
0
        return ((pParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) != WB_DIALOGCONTROL);
101
0
    }
102
}
103
104
bool Window::EventNotify( NotifyEvent& rNEvt )
105
0
{
106
0
    bool bRet = false;
107
108
0
    if (isDisposed())
109
0
        return false;
110
111
    // check for docking window
112
    // but do nothing if window is docked and locked
113
0
    ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
114
0
    if ((GetStyle() & WB_DOCKABLE) &&
115
0
            pWrapper && ( pWrapper->IsFloatingMode() || !pWrapper->IsLocked() ))
116
0
    {
117
0
        const bool bDockingSupportCrippled = !StyleSettings::GetDockingFloatsSupported();
118
119
0
        if ( rNEvt.GetType() == NotifyEventType::MOUSEBUTTONDOWN )
120
0
        {
121
0
            const MouseEvent* pMEvt = rNEvt.GetMouseEvent();
122
0
            bool bHit = pWrapper->GetDragArea().Contains( pMEvt->GetPosPixel() );
123
0
            if ( pMEvt->IsLeft() )
124
0
            {
125
0
                if (!bDockingSupportCrippled && pMEvt->IsMod1() && (pMEvt->GetClicks() == 2))
126
0
                {
127
                    // ctrl double click toggles floating mode
128
0
                    pWrapper->SetFloatingMode( !pWrapper->IsFloatingMode() );
129
0
                    return true;
130
0
                }
131
0
                else if ( pMEvt->GetClicks() == 1 && bHit)
132
0
                {
133
                    // allow start docking during mouse move
134
0
                    pWrapper->ImplEnableStartDocking();
135
0
                    return true;
136
0
                }
137
0
            }
138
0
        }
139
0
        else if ( rNEvt.GetType() == NotifyEventType::MOUSEMOVE )
140
0
        {
141
0
            const MouseEvent* pMEvt = rNEvt.GetMouseEvent();
142
0
            bool bHit = pWrapper->GetDragArea().Contains( pMEvt->GetPosPixel() );
143
0
            if ( pMEvt->IsLeft() )
144
0
            {
145
                // check if a single click initiated this sequence ( ImplStartDockingEnabled() )
146
                // check if window is docked and
147
0
                if( pWrapper->ImplStartDockingEnabled() && !pWrapper->IsFloatingMode() &&
148
0
                    !pWrapper->IsDocking() && bHit )
149
0
                {
150
0
                    Point   aPos = pMEvt->GetPosPixel();
151
0
                    vcl::Window* pWindow = rNEvt.GetWindow();
152
0
                    if ( pWindow != this )
153
0
                    {
154
0
                        aPos = pWindow->OutputToScreenPixel( aPos );
155
0
                        aPos = ScreenToOutputPixel( aPos );
156
0
                    }
157
0
                    pWrapper->ImplStartDocking( aPos );
158
0
                }
159
0
                return true;
160
0
            }
161
0
        }
162
0
        else if( rNEvt.GetType() == NotifyEventType::KEYINPUT )
163
0
        {
164
0
            const vcl::KeyCode& rKey = rNEvt.GetKeyEvent()->GetKeyCode();
165
0
            if (rKey.GetCode() == KEY_F10 && rKey.GetModifier() &&
166
0
                rKey.IsShift() && rKey.IsMod1() && !bDockingSupportCrippled)
167
0
            {
168
0
                pWrapper->SetFloatingMode( !pWrapper->IsFloatingMode() );
169
                /* At this point the floating toolbar frame does not have the
170
                 * input focus since these frames don't get the focus per default
171
                 * To enable keyboard handling of this toolbar set the input focus
172
                 * to the frame. This needs to be done with ToTop since GrabFocus
173
                 * would not notice any change since "this" already has the focus.
174
                 */
175
0
                if( pWrapper->IsFloatingMode() )
176
0
                    ToTop( ToTopFlags::GrabFocusOnly );
177
0
                return true;
178
0
            }
179
0
        }
180
0
    }
181
182
    // manage the dialogs
183
0
    if ( (GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) == WB_DIALOGCONTROL )
184
0
    {
185
        // if the parent also has dialog control activated, the parent takes over control
186
0
        if ( (rNEvt.GetType() == NotifyEventType::KEYINPUT) || (rNEvt.GetType() == NotifyEventType::KEYUP) )
187
0
        {
188
            // ScGridWindow has WB_DIALOGCONTROL set, so pressing tab in ScCheckListMenuControl won't
189
            // get processed here by the toplevel DockingWindow of ScCheckListMenuControl by
190
            // just checking if parentNotDialogControl is true
191
0
            bool bTopLevelFloatingWindow = (pWrapper && pWrapper->IsFloatingMode());
192
0
            if (ImplIsOverlapWindow() || parentNotDialogControl(this) || bTopLevelFloatingWindow)
193
0
            {
194
0
                bRet = ImplDlgCtrl( *rNEvt.GetKeyEvent(), rNEvt.GetType() == NotifyEventType::KEYINPUT );
195
0
            }
196
0
        }
197
0
        else if ( (rNEvt.GetType() == NotifyEventType::GETFOCUS) || (rNEvt.GetType() == NotifyEventType::LOSEFOCUS) )
198
0
        {
199
0
            ImplDlgCtrlFocusChanged( rNEvt.GetWindow(), rNEvt.GetType() == NotifyEventType::GETFOCUS );
200
0
            if ( (rNEvt.GetWindow() == this) && (rNEvt.GetType() == NotifyEventType::GETFOCUS) &&
201
0
                 !(GetStyle() & WB_TABSTOP) && !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) )
202
0
            {
203
0
                vcl::Window* pFirstChild = ImplGetDlgWindow( 0, GetDlgWindowType::First );
204
0
                if ( pFirstChild )
205
0
                    pFirstChild->ImplControlFocus();
206
0
            }
207
0
        }
208
0
    }
209
210
0
    if ( !bRet )
211
0
    {
212
0
        if ( mpWindowImpl->mpParent && !ImplIsOverlapWindow() )
213
0
            bRet = mpWindowImpl->mpParent->CompatNotify( rNEvt );
214
0
    }
215
216
0
    return bRet;
217
0
}
218
219
void Window::CallEventListeners( VclEventId nEvent, void* pData )
220
195k
{
221
195k
    VclWindowEvent aEvent( this, nEvent, pData );
222
223
195k
    VclPtr<vcl::Window> xWindow = this;
224
225
195k
    Application::ImplCallEventListeners( aEvent );
226
227
    // if we have ObjectDying, then the bIsDisposed flag has already been set,
228
    // but we still need to let listeners know.
229
195k
    const bool bIgnoreDisposed = nEvent == VclEventId::ObjectDying;
230
231
195k
    if ( !bIgnoreDisposed && xWindow->isDisposed() )
232
12.1k
        return;
233
234
    // If maEventListeners is empty, the XVCLWindow has not yet been initialized.
235
    // Calling GetComponentInterface will do that.
236
183k
    if (mpWindowImpl->maEventListeners.empty() && pData)
237
4.14k
        xWindow->GetComponentInterface();
238
239
183k
    if (!mpWindowImpl->maEventListeners.empty())
240
28.6k
    {
241
        // Copy the list, because this can be destroyed when calling a Link...
242
28.6k
        std::vector<Link<VclWindowEvent&,void>> aCopy( mpWindowImpl->maEventListeners );
243
        // we use an iterating counter/flag and a set of deleted Link's to avoid O(n^2) behaviour
244
28.6k
        mpWindowImpl->mnEventListenersIteratingCount++;
245
28.6k
        auto& rWindowImpl = *mpWindowImpl;
246
28.6k
        comphelper::ScopeGuard aGuard(
247
28.6k
            [&rWindowImpl, &xWindow, &bIgnoreDisposed]()
248
28.6k
            {
249
28.6k
                if (bIgnoreDisposed || !xWindow->isDisposed())
250
28.6k
                {
251
28.6k
                    rWindowImpl.mnEventListenersIteratingCount--;
252
28.6k
                    if (rWindowImpl.mnEventListenersIteratingCount == 0)
253
28.6k
                        rWindowImpl.maEventListenersDeleted.clear();
254
28.6k
                }
255
28.6k
            }
256
28.6k
        );
257
28.6k
        for ( const Link<VclWindowEvent&,void>& rLink : aCopy )
258
32.6k
        {
259
32.6k
            if (!bIgnoreDisposed && xWindow->isDisposed()) break;
260
            // check this hasn't been removed in some re-enterancy scenario fdo#47368
261
32.6k
            if( rWindowImpl.maEventListenersDeleted.find(rLink) == rWindowImpl.maEventListenersDeleted.end() )
262
32.6k
                rLink.Call( aEvent );
263
32.6k
        }
264
28.6k
    }
265
266
815k
    while ( xWindow )
267
632k
    {
268
269
632k
        if ( !bIgnoreDisposed && xWindow->isDisposed() )
270
0
            return;
271
272
632k
        if (!xWindow->mpWindowImpl)
273
0
            break;
274
275
632k
        auto& rWindowImpl = *xWindow->mpWindowImpl;
276
632k
        if (!rWindowImpl.maChildEventListeners.empty())
277
138k
        {
278
            // Copy the list, because this can be destroyed when calling a Link...
279
138k
            std::vector<Link<VclWindowEvent&,void>> aCopy( rWindowImpl.maChildEventListeners );
280
            // we use an iterating counter/flag and a set of deleted Link's to avoid O(n^2) behaviour
281
138k
            rWindowImpl.mnChildEventListenersIteratingCount++;
282
138k
            comphelper::ScopeGuard aGuard(
283
138k
                [&rWindowImpl, &xWindow, &bIgnoreDisposed]()
284
138k
                {
285
138k
                    if (bIgnoreDisposed || !xWindow->isDisposed())
286
138k
                    {
287
138k
                        rWindowImpl.mnChildEventListenersIteratingCount--;
288
138k
                        if (rWindowImpl.mnChildEventListenersIteratingCount == 0)
289
138k
                            rWindowImpl.maChildEventListenersDeleted.clear();
290
138k
                    }
291
138k
                }
292
138k
            );
293
138k
            for ( const Link<VclWindowEvent&,void>& rLink : aCopy )
294
138k
            {
295
138k
                if (!bIgnoreDisposed && xWindow->isDisposed())
296
0
                    return;
297
                // Check this hasn't been removed in some re-enterancy scenario fdo#47368.
298
138k
                if( rWindowImpl.maChildEventListenersDeleted.find(rLink) == rWindowImpl.maChildEventListenersDeleted.end() )
299
138k
                    rLink.Call( aEvent );
300
138k
            }
301
138k
        }
302
303
632k
        if ( !bIgnoreDisposed && xWindow->isDisposed() )
304
0
            return;
305
306
632k
        xWindow = xWindow->GetParent();
307
632k
    }
308
183k
}
309
310
void Window::AddEventListener( const Link<VclWindowEvent&,void>& rEventListener )
311
81.8k
{
312
81.8k
    mpWindowImpl->maEventListeners.push_back( rEventListener );
313
81.8k
}
314
315
void Window::RemoveEventListener( const Link<VclWindowEvent&,void>& rEventListener )
316
93.9k
{
317
93.9k
    if (mpWindowImpl)
318
93.9k
    {
319
93.9k
        auto& rListeners = mpWindowImpl->maEventListeners;
320
93.9k
        std::erase(rListeners, rEventListener);
321
93.9k
        if (mpWindowImpl->mnEventListenersIteratingCount)
322
0
            mpWindowImpl->maEventListenersDeleted.insert(rEventListener);
323
93.9k
    }
324
93.9k
}
325
326
void Window::AddChildEventListener( const Link<VclWindowEvent&,void>& rEventListener )
327
8.17k
{
328
8.17k
    mpWindowImpl->maChildEventListeners.push_back( rEventListener );
329
8.17k
}
330
331
void Window::RemoveChildEventListener( const Link<VclWindowEvent&,void>& rEventListener )
332
8.16k
{
333
8.16k
    if (mpWindowImpl)
334
8.16k
    {
335
8.16k
        auto& rListeners = mpWindowImpl->maChildEventListeners;
336
8.16k
        std::erase(rListeners, rEventListener);
337
8.16k
        if (mpWindowImpl->mnChildEventListenersIteratingCount)
338
0
            mpWindowImpl->maChildEventListenersDeleted.insert(rEventListener);
339
8.16k
    }
340
8.16k
}
341
342
ImplSVEvent * Window::PostUserEvent( const Link<void*,void>& rLink, void* pCaller, bool bReferenceLink )
343
0
{
344
0
    std::unique_ptr<ImplSVEvent> pSVEvent(new ImplSVEvent);
345
0
    pSVEvent->mpData    = pCaller;
346
0
    pSVEvent->maLink    = rLink;
347
0
    pSVEvent->mpWindow  = this;
348
0
    pSVEvent->mbCall    = true;
349
0
    if (bReferenceLink)
350
0
    {
351
0
        pSVEvent->mpInstanceRef = static_cast<vcl::Window *>(rLink.GetInstance());
352
0
    }
353
354
0
    auto pTmpEvent = pSVEvent.get();
355
0
    if (!mpWindowImpl->mpFrame->PostEvent( std::move(pSVEvent) ))
356
0
        return nullptr;
357
0
    return pTmpEvent;
358
0
}
359
360
void Window::RemoveUserEvent( ImplSVEvent * nUserEvent )
361
0
{
362
0
    SAL_WARN_IF( nUserEvent->mpWindow.get() != this, "vcl",
363
0
                "Window::RemoveUserEvent(): Event doesn't send to this window or is already removed" );
364
0
    SAL_WARN_IF( !nUserEvent->mbCall, "vcl",
365
0
                "Window::RemoveUserEvent(): Event is already removed" );
366
367
0
    if ( nUserEvent->mpWindow )
368
0
    {
369
0
        nUserEvent->mpWindow = nullptr;
370
0
    }
371
372
0
    nUserEvent->mbCall = false;
373
0
}
374
375
376
static MouseEvent ImplTranslateMouseEvent( const MouseEvent& rE, vcl::Window const * pSource, vcl::Window const * pDest )
377
0
{
378
    // the mouse event occurred in a different window, we need to translate the coordinates of
379
    // the mouse cursor within that (source) window to the coordinates the mouse cursor would
380
    // be in the destination window
381
0
    Point aPos = pSource->OutputToScreenPixel( rE.GetPosPixel() );
382
0
    return MouseEvent( pDest->ScreenToOutputPixel( aPos ), rE.GetClicks(), rE.GetMode(), rE.GetButtons(), rE.GetModifier() );
383
0
}
384
385
void Window::ImplNotifyKeyMouseCommandEventListeners( NotifyEvent& rNEvt )
386
0
{
387
0
    if( rNEvt.GetType() == NotifyEventType::COMMAND )
388
0
    {
389
0
        const CommandEvent* pCEvt = rNEvt.GetCommandEvent();
390
0
        if ( pCEvt->GetCommand() != CommandEventId::ContextMenu )
391
            // non context menu events are not to be notified up the chain
392
            // so we return immediately
393
0
            return;
394
395
0
        if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
396
0
        {
397
            // not interested: The event listeners are already called in ::Command,
398
            // and calling them here a second time doesn't make sense
399
0
            if ( rNEvt.GetWindow() != this )
400
0
            {
401
0
                CommandEvent aCommandEvent;
402
403
0
                if ( !pCEvt->IsMouseEvent() )
404
0
                {
405
0
                    aCommandEvent = *pCEvt;
406
0
                }
407
0
                else
408
0
                {
409
                    // the mouse event occurred in a different window, we need to translate the coordinates of
410
                    // the mouse cursor within that window to the coordinates the mouse cursor would be in the
411
                    // current window
412
0
                    vcl::Window* pSource = rNEvt.GetWindow();
413
0
                    Point aPos = pSource->OutputToScreenPixel( pCEvt->GetMousePosPixel() );
414
0
                    aCommandEvent = CommandEvent( ScreenToOutputPixel( aPos ), pCEvt->GetCommand(), pCEvt->IsMouseEvent(), pCEvt->GetEventData() );
415
0
                }
416
417
0
                CallEventListeners( VclEventId::WindowCommand, &aCommandEvent );
418
0
            }
419
0
        }
420
0
    }
421
422
    // #82968# notify event listeners for mouse and key events separately and
423
    // not in PreNotify ( as for focus listeners )
424
    // this allows for processing those events internally first and pass it to
425
    // the toolkit later
426
427
0
    VclPtr<vcl::Window> xWindow = this;
428
429
0
    if( rNEvt.GetType() == NotifyEventType::MOUSEMOVE )
430
0
    {
431
0
        if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
432
0
        {
433
0
            if ( rNEvt.GetWindow() == this )
434
0
                CallEventListeners( VclEventId::WindowMouseMove, const_cast<MouseEvent *>(rNEvt.GetMouseEvent()) );
435
0
            else
436
0
            {
437
0
                MouseEvent aMouseEvent = ImplTranslateMouseEvent( *rNEvt.GetMouseEvent(), rNEvt.GetWindow(), this );
438
0
                CallEventListeners( VclEventId::WindowMouseMove, &aMouseEvent );
439
0
            }
440
0
        }
441
0
    }
442
0
    else if( rNEvt.GetType() == NotifyEventType::MOUSEBUTTONUP )
443
0
    {
444
0
        if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
445
0
        {
446
0
            if ( rNEvt.GetWindow() == this )
447
0
                CallEventListeners( VclEventId::WindowMouseButtonUp, const_cast<MouseEvent *>(rNEvt.GetMouseEvent()) );
448
0
            else
449
0
            {
450
0
                MouseEvent aMouseEvent = ImplTranslateMouseEvent( *rNEvt.GetMouseEvent(), rNEvt.GetWindow(), this );
451
0
                CallEventListeners( VclEventId::WindowMouseButtonUp, &aMouseEvent );
452
0
            }
453
0
        }
454
0
    }
455
0
    else if( rNEvt.GetType() == NotifyEventType::MOUSEBUTTONDOWN )
456
0
    {
457
0
        if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
458
0
        {
459
0
            if ( rNEvt.GetWindow() == this )
460
0
                CallEventListeners( VclEventId::WindowMouseButtonDown, const_cast<MouseEvent *>(rNEvt.GetMouseEvent()) );
461
0
            else
462
0
            {
463
0
                MouseEvent aMouseEvent = ImplTranslateMouseEvent( *rNEvt.GetMouseEvent(), rNEvt.GetWindow(), this );
464
0
                CallEventListeners( VclEventId::WindowMouseButtonDown, &aMouseEvent );
465
0
            }
466
0
        }
467
0
    }
468
0
    else if( rNEvt.GetType() == NotifyEventType::KEYINPUT )
469
0
    {
470
0
        if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
471
0
            CallEventListeners( VclEventId::WindowKeyInput, const_cast<KeyEvent *>(rNEvt.GetKeyEvent()) );
472
0
    }
473
0
    else if( rNEvt.GetType() == NotifyEventType::KEYUP )
474
0
    {
475
0
        if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
476
0
            CallEventListeners( VclEventId::WindowKeyUp, const_cast<KeyEvent *>(rNEvt.GetKeyEvent()) );
477
0
    }
478
479
0
    if ( xWindow->isDisposed() )
480
0
        return;
481
482
    // #106721# check if we're part of a compound control and notify
483
0
    vcl::Window *pParent = ImplGetParent();
484
0
    while( pParent )
485
0
    {
486
0
        if( pParent->IsCompoundControl() )
487
0
        {
488
0
            pParent->ImplNotifyKeyMouseCommandEventListeners( rNEvt );
489
0
            break;
490
0
        }
491
0
        pParent = pParent->ImplGetParent();
492
0
    }
493
0
}
494
495
void Window::ImplCallInitShow()
496
0
{
497
0
    mpWindowImpl->mbReallyShown   = true;
498
0
    mpWindowImpl->mbInInitShow    = true;
499
0
    CompatStateChanged( StateChangedType::InitShow );
500
0
    mpWindowImpl->mbInInitShow    = false;
501
502
0
    vcl::Window* pWindow = mpWindowImpl->mpFirstOverlap;
503
0
    while ( pWindow )
504
0
    {
505
0
        if ( pWindow->mpWindowImpl->mbVisible )
506
0
            pWindow->ImplCallInitShow();
507
0
        pWindow = pWindow->mpWindowImpl->mpNext;
508
0
    }
509
510
0
    pWindow = mpWindowImpl->mpFirstChild;
511
0
    while ( pWindow )
512
0
    {
513
0
        if ( pWindow->mpWindowImpl->mbVisible )
514
0
            pWindow->ImplCallInitShow();
515
0
        pWindow = pWindow->mpWindowImpl->mpNext;
516
0
    }
517
0
}
518
519
520
void Window::ImplCallResize()
521
20.3k
{
522
20.3k
    mpWindowImpl->mbCallResize = false;
523
524
    // Normally we avoid blanking on re-size unless people might notice:
525
20.3k
    if( GetBackground().IsGradient() )
526
0
        Invalidate();
527
528
20.3k
    Resize();
529
530
    // #88419# Most classes don't call the base class in Resize() and Move(),
531
    // => Call ImpleResize/Move instead of Resize/Move directly...
532
20.3k
    CallEventListeners( VclEventId::WindowResize );
533
20.3k
}
534
535
void Window::ImplCallMove()
536
24.4k
{
537
24.4k
    mpWindowImpl->mbCallMove = false;
538
539
24.4k
    if( mpWindowImpl->mbFrame )
540
0
    {
541
        // update frame position
542
0
        SalFrame *pParentFrame = nullptr;
543
0
        vcl::Window *pParent = ImplGetParent();
544
0
        while( pParent )
545
0
        {
546
0
            if( pParent->mpWindowImpl &&
547
0
                pParent->mpWindowImpl->mpFrame != mpWindowImpl->mpFrame )
548
0
            {
549
0
                pParentFrame = pParent->mpWindowImpl->mpFrame;
550
0
                break;
551
0
            }
552
0
            pParent = pParent->GetParent();
553
0
        }
554
555
0
        SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
556
0
        mpWindowImpl->maPos = Point(g.x(), g.y());
557
0
        if( pParentFrame )
558
0
        {
559
0
            g = pParentFrame->GetGeometry();
560
0
            mpWindowImpl->maPos -= Point(g.x(), g.y());
561
0
        }
562
        // the client window and all its subclients have the same position as the borderframe
563
        // this is important for floating toolbars where the borderwindow is a floating window
564
        // which has another borderwindow (ie the system floating window)
565
0
        vcl::Window *pClientWin = mpWindowImpl->mpClientWindow;
566
0
        while( pClientWin )
567
0
        {
568
0
            pClientWin->mpWindowImpl->maPos = mpWindowImpl->maPos;
569
0
            pClientWin = pClientWin->mpWindowImpl->mpClientWindow;
570
0
        }
571
0
    }
572
573
24.4k
    Move();
574
575
24.4k
    CallEventListeners( VclEventId::WindowMove );
576
24.4k
}
577
578
void Window::ImplCallFocusChangeActivate( vcl::Window* pNewOverlapWindow,
579
                                          vcl::Window* pOldOverlapWindow )
580
0
{
581
0
    ImplSVData* pSVData = ImplGetSVData();
582
0
    vcl::Window*     pNewRealWindow;
583
0
    vcl::Window*     pOldRealWindow;
584
0
    bool bCallActivate = true;
585
0
    bool bCallDeactivate = true;
586
587
0
    if (!pOldOverlapWindow)
588
0
    {
589
0
        return;
590
0
    }
591
592
0
    pOldRealWindow = pOldOverlapWindow->ImplGetWindow();
593
0
    if (!pNewOverlapWindow)
594
0
    {
595
0
        return;
596
0
    }
597
598
0
    pNewRealWindow = pNewOverlapWindow->ImplGetWindow();
599
0
    if ( (pOldRealWindow->GetType() != WindowType::FLOATINGWINDOW) ||
600
0
         pOldRealWindow->GetActivateMode() != ActivateModeFlags::NONE )
601
0
    {
602
0
        if ( (pNewRealWindow->GetType() == WindowType::FLOATINGWINDOW) &&
603
0
             pNewRealWindow->GetActivateMode() == ActivateModeFlags::NONE)
604
0
        {
605
0
            pSVData->mpWinData->mpLastDeacWin = pOldOverlapWindow;
606
0
            bCallDeactivate = false;
607
0
        }
608
0
    }
609
0
    else if ( (pNewRealWindow->GetType() != WindowType::FLOATINGWINDOW) ||
610
0
              pNewRealWindow->GetActivateMode() != ActivateModeFlags::NONE )
611
0
    {
612
0
        if (pSVData->mpWinData->mpLastDeacWin)
613
0
        {
614
0
            if (pSVData->mpWinData->mpLastDeacWin.get() == pNewOverlapWindow)
615
0
                bCallActivate = false;
616
0
            else
617
0
            {
618
0
                vcl::Window* pLastRealWindow = pSVData->mpWinData->mpLastDeacWin->ImplGetWindow();
619
0
                pSVData->mpWinData->mpLastDeacWin->mpWindowImpl->mbActive = false;
620
0
                pSVData->mpWinData->mpLastDeacWin->Deactivate();
621
0
                if (pLastRealWindow != pSVData->mpWinData->mpLastDeacWin.get())
622
0
                {
623
0
                    pLastRealWindow->mpWindowImpl->mbActive = true;
624
0
                    pLastRealWindow->Activate();
625
0
                }
626
0
            }
627
0
            pSVData->mpWinData->mpLastDeacWin = nullptr;
628
0
        }
629
0
    }
630
631
0
    if ( bCallDeactivate )
632
0
    {
633
0
        if( pOldOverlapWindow->mpWindowImpl->mbActive )
634
0
        {
635
0
            pOldOverlapWindow->mpWindowImpl->mbActive = false;
636
0
            pOldOverlapWindow->Deactivate();
637
0
        }
638
0
        if ( pOldRealWindow != pOldOverlapWindow )
639
0
        {
640
0
            if( pOldRealWindow->mpWindowImpl->mbActive )
641
0
            {
642
0
                pOldRealWindow->mpWindowImpl->mbActive = false;
643
0
                pOldRealWindow->Deactivate();
644
0
            }
645
0
        }
646
0
    }
647
0
    if ( !bCallActivate || pNewOverlapWindow->mpWindowImpl->mbActive )
648
0
        return;
649
650
0
    pNewOverlapWindow->mpWindowImpl->mbActive = true;
651
0
    pNewOverlapWindow->Activate();
652
653
0
    if ( pNewRealWindow != pNewOverlapWindow )
654
0
    {
655
0
        if( ! pNewRealWindow->mpWindowImpl->mbActive )
656
0
        {
657
0
            pNewRealWindow->mpWindowImpl->mbActive = true;
658
0
            pNewRealWindow->Activate();
659
0
        }
660
0
    }
661
0
}
662
663
} /* namespace vcl */
664
665
666
NotifyEvent::NotifyEvent( NotifyEventType nEventType, vcl::Window* pWindow,
667
                          const void* pEvent )
668
0
{
669
0
    mpWindow    = pWindow;
670
0
    mpData      = const_cast<void*>(pEvent);
671
0
    mnEventType  = nEventType;
672
0
}
673
674
0
NotifyEvent::~NotifyEvent() = default;
675
676
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */