Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/window/mouse.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
21
#include <config_feature_desktop.h>
22
#include <config_vclplug.h>
23
24
#include <tools/time.hxx>
25
26
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
27
28
#include <vcl/ITiledRenderable.hxx>
29
#include <vcl/dndlistenercontainer.hxx>
30
#include <vcl/svapp.hxx>
31
#include <vcl/window.hxx>
32
#include <vcl/cursor.hxx>
33
#include <vcl/sysdata.hxx>
34
#include <vcl/event.hxx>
35
36
#include <sal/types.h>
37
38
#include <window.h>
39
#include <svdata.hxx>
40
#include <salobj.hxx>
41
#include <salgdi.hxx>
42
#include <salframe.hxx>
43
#include <salinst.hxx>
44
45
#include <dndeventdispatcher.hxx>
46
47
#include <com/sun/star/datatransfer/dnd/XDragSource.hpp>
48
#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
49
#include <com/sun/star/uno/XComponentContext.hpp>
50
51
#include <comphelper/processfactory.hxx>
52
53
using namespace ::com::sun::star::uno;
54
55
namespace vcl {
56
57
WindowHitTest Window::ImplHitTest( const Point& rFramePos )
58
0
{
59
0
    Point aFramePos( rFramePos );
60
0
    if( GetOutDev()->ImplIsAntiparallel() )
61
0
    {
62
0
        const OutputDevice *pOutDev = GetOutDev();
63
0
        pOutDev->ReMirror( aFramePos );
64
0
    }
65
0
    if ( !GetOutputRectPixel().Contains( aFramePos ) )
66
0
        return WindowHitTest::NONE;
67
0
    if ( mpWindowImpl->mbWinRegion )
68
0
    {
69
0
        Point aTempPos = aFramePos;
70
0
        aTempPos.AdjustX( -GetOutDev()->mnOutOffX );
71
0
        aTempPos.AdjustY( -GetOutDev()->mnOutOffY );
72
0
        if ( !mpWindowImpl->maWinRegion.Contains( aTempPos ) )
73
0
            return WindowHitTest::NONE;
74
0
    }
75
76
0
    WindowHitTest nHitTest = WindowHitTest::Inside;
77
0
    if ( mpWindowImpl->mbMouseTransparent )
78
0
        nHitTest |= WindowHitTest::Transparent;
79
0
    return nHitTest;
80
0
}
81
82
bool Window::ImplTestMousePointerSet()
83
13.0k
{
84
    // as soon as mouse is captured, switch mouse-pointer
85
13.0k
    if ( IsMouseCaptured() )
86
0
        return true;
87
88
    // if the mouse is over the window, switch it
89
13.0k
    tools::Rectangle aClientRect( Point( 0, 0 ), GetOutputSizePixel() );
90
13.0k
    return aClientRect.Contains( GetPointerPosPixel() );
91
13.0k
}
92
93
PointerStyle Window::ImplGetMousePointer() const
94
0
{
95
0
    PointerStyle    ePointerStyle;
96
0
    bool            bWait = false;
97
98
0
    if ( IsEnabled() && IsInputEnabled() && ! IsInModalMode() )
99
0
        ePointerStyle = GetPointer();
100
0
    else
101
0
        ePointerStyle = PointerStyle::Arrow;
102
103
0
    const vcl::Window* pWindow = this;
104
0
    do
105
0
    {
106
        // when the pointer is not visible stop the search, as
107
        // this status should not be overwritten
108
0
        if ( pWindow->mpWindowImpl->mbNoPtrVisible )
109
0
            return PointerStyle::Null;
110
111
0
        if ( !bWait )
112
0
        {
113
0
            if ( pWindow->mpWindowImpl->mnWaitCount )
114
0
            {
115
0
                ePointerStyle = PointerStyle::Wait;
116
0
                bWait = true;
117
0
            }
118
0
            else
119
0
            {
120
0
                if ( pWindow->mpWindowImpl->mbChildPtrOverwrite )
121
0
                    ePointerStyle = pWindow->GetPointer();
122
0
            }
123
0
        }
124
125
0
        if ( pWindow->ImplIsOverlapWindow() )
126
0
            break;
127
128
0
        pWindow = pWindow->ImplGetParent();
129
0
    }
130
0
    while ( pWindow );
131
132
0
    return ePointerStyle;
133
0
}
134
135
void Window::ImplCallMouseMove( sal_uInt16 nMouseCode, bool bModChanged )
136
0
{
137
0
    if ( !(mpWindowImpl->mpFrameData->mbMouseIn && mpWindowImpl->mpFrameWindow->mpWindowImpl->mbReallyVisible) )
138
0
        return;
139
140
0
    sal_uInt64 nTime   = tools::Time::GetSystemTicks();
141
0
    tools::Long    nX      = mpWindowImpl->mpFrameData->mnLastMouseX;
142
0
    tools::Long    nY      = mpWindowImpl->mpFrameData->mnLastMouseY;
143
0
    sal_uInt16  nCode   = nMouseCode;
144
0
    MouseEventModifiers nMode = mpWindowImpl->mpFrameData->mnMouseMode;
145
0
    bool    bLeave;
146
    // check for MouseLeave
147
0
    bLeave = ((nX < 0) || (nY < 0) ||
148
0
              (nX >= mpWindowImpl->mpFrameWindow->GetOutDev()->mnOutWidth) ||
149
0
              (nY >= mpWindowImpl->mpFrameWindow->GetOutDev()->mnOutHeight)) &&
150
0
             !ImplGetSVData()->mpWinData->mpCaptureWin;
151
0
    nMode |= MouseEventModifiers::SYNTHETIC;
152
0
    if ( bModChanged )
153
0
        nMode |= MouseEventModifiers::MODIFIERCHANGED;
154
0
    ImplHandleMouseEvent( mpWindowImpl->mpFrameWindow, NotifyEventType::MOUSEMOVE, bLeave, nX, nY, nTime, nCode, nMode );
155
0
}
156
157
void Window::ImplGenerateMouseMove()
158
0
{
159
0
    if ( mpWindowImpl && mpWindowImpl->mpFrameData &&
160
0
         !mpWindowImpl->mpFrameData->mnMouseMoveId )
161
0
        mpWindowImpl->mpFrameData->mnMouseMoveId = Application::PostUserEvent( LINK( mpWindowImpl->mpFrameWindow, Window, ImplGenerateMouseMoveHdl ), nullptr, true );
162
0
}
163
164
IMPL_LINK_NOARG(Window, ImplGenerateMouseMoveHdl, void*, void)
165
0
{
166
0
    mpWindowImpl->mpFrameData->mnMouseMoveId = nullptr;
167
0
    vcl::Window* pCaptureWin = ImplGetSVData()->mpWinData->mpCaptureWin;
168
0
    if( ! pCaptureWin ||
169
0
        (pCaptureWin->mpWindowImpl && pCaptureWin->mpWindowImpl->mpFrame == mpWindowImpl->mpFrame)
170
0
    )
171
0
    {
172
0
        ImplCallMouseMove( mpWindowImpl->mpFrameData->mnMouseCode );
173
0
    }
174
0
}
175
176
void Window::ImplInvertFocus( const tools::Rectangle& rRect )
177
0
{
178
0
    InvertTracking( rRect, ShowTrackFlags::Small | ShowTrackFlags::TrackWindow );
179
0
}
180
181
static bool IsWindowFocused(const WindowImpl& rWinImpl)
182
0
{
183
0
    if (rWinImpl.mpSysObj)
184
0
        return true;
185
186
0
    if (rWinImpl.mpFrameData->mbHasFocus)
187
0
        return true;
188
189
0
    if (rWinImpl.mbFakeFocusSet)
190
0
        return true;
191
192
0
    return false;
193
0
}
194
195
void Window::ImplGrabFocus( GetFocusFlags nFlags )
196
0
{
197
    // #143570# no focus for destructing windows
198
0
    if( !mpWindowImpl || mpWindowImpl->mbInDispose )
199
0
        return;
200
201
    // some event listeners do really bad stuff
202
    // => prepare for the worst
203
0
    VclPtr<vcl::Window> xWindow( this );
204
205
    // Currently the client window should always get the focus
206
    // Should the border window at some point be focusable
207
    // we need to change all GrabFocus() instances in VCL,
208
    // e.g. in ToTop()
209
210
0
    if ( mpWindowImpl->mpClientWindow )
211
0
    {
212
        // For a lack of design we need a little hack here to
213
        // ensure that dialogs on close pass the focus back to
214
        // the correct window
215
0
        if ( mpWindowImpl->mpLastFocusWindow && (mpWindowImpl->mpLastFocusWindow.get() != this) &&
216
0
             !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) &&
217
0
             mpWindowImpl->mpLastFocusWindow->IsEnabled() &&
218
0
             mpWindowImpl->mpLastFocusWindow->IsInputEnabled() &&
219
0
             ! mpWindowImpl->mpLastFocusWindow->IsInModalMode()
220
0
             )
221
0
            mpWindowImpl->mpLastFocusWindow->GrabFocus();
222
0
        else
223
0
            mpWindowImpl->mpClientWindow->GrabFocus();
224
0
        return;
225
0
    }
226
0
    else if ( mpWindowImpl->mbFrame )
227
0
    {
228
        // For a lack of design we need a little hack here to
229
        // ensure that dialogs on close pass the focus back to
230
        // the correct window
231
0
        if ( mpWindowImpl->mpLastFocusWindow && (mpWindowImpl->mpLastFocusWindow.get() != this) &&
232
0
             !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) &&
233
0
             mpWindowImpl->mpLastFocusWindow->IsEnabled() &&
234
0
             mpWindowImpl->mpLastFocusWindow->IsInputEnabled() &&
235
0
             ! mpWindowImpl->mpLastFocusWindow->IsInModalMode()
236
0
             )
237
0
        {
238
0
            mpWindowImpl->mpLastFocusWindow->GrabFocus();
239
0
            return;
240
0
        }
241
0
    }
242
243
    // If the Window is disabled, then we don't change the focus
244
0
    if ( !IsEnabled() || !IsInputEnabled() || IsInModalMode() )
245
0
        return;
246
247
    // we only need to set the focus if it is not already set
248
    // note: if some other frame is waiting for an asynchronous focus event
249
    // we also have to post an asynchronous focus event for this frame
250
    // which is done using ToTop
251
0
    ImplSVData* pSVData = ImplGetSVData();
252
253
0
    bool bAsyncFocusWaiting = false;
254
0
    vcl::Window *pFrame = pSVData->maFrameData.mpFirstFrame;
255
0
    while( pFrame && pFrame->mpWindowImpl && pFrame->mpWindowImpl->mpFrameData )
256
0
    {
257
0
        if( pFrame != mpWindowImpl->mpFrameWindow.get() && pFrame->mpWindowImpl->mpFrameData->mnFocusId )
258
0
        {
259
0
            bAsyncFocusWaiting = true;
260
0
            break;
261
0
        }
262
0
        pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame;
263
0
    }
264
265
0
    bool bHasFocus = IsWindowFocused(*mpWindowImpl);
266
267
0
    bool bMustNotGrabFocus = false;
268
    // #100242#, check parent hierarchy if some floater prohibits grab focus
269
270
0
    vcl::Window *pParent = this;
271
0
    while( pParent )
272
0
    {
273
0
        if ((pParent->GetStyle() & WB_SYSTEMFLOATWIN) && !(pParent->GetStyle() & WB_MOVEABLE))
274
0
        {
275
0
            bMustNotGrabFocus = true;
276
0
            break;
277
0
        }
278
0
        if (!pParent->mpWindowImpl)
279
0
            break;
280
0
        pParent = pParent->mpWindowImpl->mpParent;
281
0
    }
282
283
0
    if ( !(( pSVData->mpWinData->mpFocusWin.get() != this &&
284
0
             !mpWindowImpl->mbInDispose ) ||
285
0
           ( bAsyncFocusWaiting && !bHasFocus && !bMustNotGrabFocus )) )
286
0
        return;
287
288
    // EndExtTextInput if it is not the same window
289
0
    if (pSVData->mpWinData->mpExtTextInputWin
290
0
        && (pSVData->mpWinData->mpExtTextInputWin.get() != this))
291
0
        pSVData->mpWinData->mpExtTextInputWin->EndExtTextInput();
292
293
    // mark this windows as the last FocusWindow
294
0
    vcl::Window* pOverlapWindow = ImplGetFirstOverlapWindow();
295
0
    if (pOverlapWindow->mpWindowImpl)
296
0
        pOverlapWindow->mpWindowImpl->mpLastFocusWindow = this;
297
0
    mpWindowImpl->mpFrameData->mpFocusWin = this;
298
299
0
    if( !bHasFocus )
300
0
    {
301
        // menu windows never get the system focus
302
        // the application will keep the focus
303
0
        if( bMustNotGrabFocus )
304
0
            return;
305
0
        else
306
0
        {
307
            // here we already switch focus as ToTop()
308
            // should not give focus to another window
309
0
            mpWindowImpl->mpFrame->ToTop( SalFrameToTop::GrabFocus | SalFrameToTop::GrabFocusOnly );
310
0
            return;
311
0
        }
312
0
    }
313
314
0
    VclPtr<vcl::Window> pOldFocusWindow = pSVData->mpWinData->mpFocusWin;
315
316
0
    pSVData->mpWinData->mpFocusWin = this;
317
318
0
    if ( pOldFocusWindow && pOldFocusWindow->mpWindowImpl )
319
0
    {
320
        // Cursor hidden
321
0
        if ( pOldFocusWindow->mpWindowImpl->mpCursor )
322
0
            pOldFocusWindow->mpWindowImpl->mpCursor->ImplHide();
323
0
    }
324
325
    // !!!!! due to old SV-Office Activate/Deactivate handling
326
    // !!!!! first as before
327
0
    if ( pOldFocusWindow )
328
0
    {
329
        // remember Focus
330
0
        vcl::Window* pOldOverlapWindow = pOldFocusWindow->ImplGetFirstOverlapWindow();
331
0
        vcl::Window* pNewOverlapWindow = ImplGetFirstOverlapWindow();
332
0
        if ( pOldOverlapWindow != pNewOverlapWindow )
333
0
            ImplCallFocusChangeActivate( pNewOverlapWindow, pOldOverlapWindow );
334
0
    }
335
0
    else
336
0
    {
337
0
        vcl::Window* pNewOverlapWindow = ImplGetFirstOverlapWindow();
338
0
        if ( pNewOverlapWindow && pNewOverlapWindow->mpWindowImpl )
339
0
        {
340
0
            vcl::Window* pNewRealWindow = pNewOverlapWindow->ImplGetWindow();
341
0
            pNewOverlapWindow->mpWindowImpl->mbActive = true;
342
0
            pNewOverlapWindow->Activate();
343
0
            if ( pNewRealWindow != pNewOverlapWindow  && pNewRealWindow && pNewRealWindow->mpWindowImpl )
344
0
            {
345
0
                pNewRealWindow->mpWindowImpl->mbActive = true;
346
0
                pNewRealWindow->Activate();
347
0
            }
348
0
        }
349
0
    }
350
351
    // call Get- and LoseFocus
352
0
    if ( pOldFocusWindow && ! pOldFocusWindow->isDisposed() )
353
0
    {
354
0
        NotifyEvent aNEvt( NotifyEventType::LOSEFOCUS, pOldFocusWindow );
355
0
        if ( !ImplCallPreNotify( aNEvt ) )
356
0
            pOldFocusWindow->CompatLoseFocus();
357
0
        pOldFocusWindow->ImplCallDeactivateListeners( this );
358
0
    }
359
360
0
    if (pSVData->mpWinData->mpFocusWin.get() == this)
361
0
    {
362
0
        if ( mpWindowImpl->mpSysObj )
363
0
        {
364
0
            mpWindowImpl->mpFrameData->mpFocusWin = this;
365
0
            if ( !mpWindowImpl->mpFrameData->mbInSysObjFocusHdl )
366
0
                mpWindowImpl->mpSysObj->GrabFocus();
367
0
        }
368
369
0
        if (pSVData->mpWinData->mpFocusWin.get() == this)
370
0
        {
371
0
            if ( mpWindowImpl->mpCursor )
372
0
                mpWindowImpl->mpCursor->ImplShow();
373
0
            mpWindowImpl->mbInFocusHdl = true;
374
0
            mpWindowImpl->mnGetFocusFlags = nFlags;
375
            // if we're changing focus due to closing a popup floating window
376
            // notify the new focus window so it can restore the inner focus
377
            // eg, toolboxes can select their recent active item
378
0
            if( pOldFocusWindow &&
379
0
                ! pOldFocusWindow->isDisposed() &&
380
0
                ( pOldFocusWindow->GetDialogControlFlags() & DialogControlFlags::FloatWinPopupModeEndCancel ) )
381
0
                mpWindowImpl->mnGetFocusFlags |= GetFocusFlags::FloatWinPopupModeEndCancel;
382
0
            NotifyEvent aNEvt( NotifyEventType::GETFOCUS, this );
383
0
            if ( !ImplCallPreNotify( aNEvt ) && !xWindow->isDisposed() )
384
0
                CompatGetFocus();
385
0
            if( !xWindow->isDisposed() )
386
0
            {
387
0
                if (pOldFocusWindow && pOldFocusWindow->isDisposed())
388
0
                    pOldFocusWindow = nullptr;
389
0
                ImplCallActivateListeners(pOldFocusWindow);
390
0
            }
391
0
            if( !xWindow->isDisposed() )
392
0
            {
393
0
                mpWindowImpl->mnGetFocusFlags = GetFocusFlags::NONE;
394
0
                mpWindowImpl->mbInFocusHdl = false;
395
0
            }
396
0
        }
397
0
    }
398
399
0
    ImplNewInputContext();
400
401
0
}
402
403
void Window::ImplGrabFocusToDocument( GetFocusFlags nFlags )
404
0
{
405
0
    vcl::Window *pWin = this;
406
0
    while( pWin )
407
0
    {
408
0
        if( !pWin->GetParent() )
409
0
        {
410
0
            pWin->mpWindowImpl->mpFrame->GrabFocus();
411
0
            pWin->ImplGetFrameWindow()->GetWindow( GetWindowType::Client )->ImplGrabFocus(nFlags);
412
0
            return;
413
0
        }
414
0
        pWin = pWin->GetParent();
415
0
    }
416
0
}
417
418
void Window::MouseMove( const MouseEvent& rMEvt )
419
0
{
420
0
    NotifyEvent aNEvt( NotifyEventType::MOUSEMOVE, this, &rMEvt );
421
0
    EventNotify(aNEvt);
422
0
}
423
424
void Window::MouseButtonDown( const MouseEvent& rMEvt )
425
0
{
426
0
    NotifyEvent aNEvt( NotifyEventType::MOUSEBUTTONDOWN, this, &rMEvt );
427
0
    if (!EventNotify(aNEvt) && mpWindowImpl)
428
0
        mpWindowImpl->mbMouseButtonDown = true;
429
0
}
430
431
void Window::MouseButtonUp( const MouseEvent& rMEvt )
432
0
{
433
0
    NotifyEvent aNEvt( NotifyEventType::MOUSEBUTTONUP, this, &rMEvt );
434
0
    if (!EventNotify(aNEvt) && mpWindowImpl)
435
0
        mpWindowImpl->mbMouseButtonUp = true;
436
0
}
437
438
void Window::SetMouseTransparent( bool bTransparent )
439
0
{
440
441
0
    if ( mpWindowImpl->mpBorderWindow )
442
0
        mpWindowImpl->mpBorderWindow->SetMouseTransparent( bTransparent );
443
444
0
    if( mpWindowImpl->mpSysObj )
445
0
        mpWindowImpl->mpSysObj->SetMouseTransparent( bTransparent );
446
447
0
    mpWindowImpl->mbMouseTransparent = bTransparent;
448
0
}
449
450
void Window::LocalStartDrag()
451
0
{
452
0
    ImplGetFrameData()->mbDragging = true;
453
0
}
454
455
void Window::CaptureMouse()
456
0
{
457
0
    ImplSVData* pSVData = ImplGetSVData();
458
459
    // possibly stop tracking
460
0
    if (pSVData->mpWinData->mpTrackWin.get() != this)
461
0
    {
462
0
        if (pSVData->mpWinData->mpTrackWin)
463
0
            pSVData->mpWinData->mpTrackWin->EndTracking(TrackingEventFlags::Cancel);
464
0
    }
465
466
0
    if (pSVData->mpWinData->mpCaptureWin.get() != this)
467
0
    {
468
0
        pSVData->mpWinData->mpCaptureWin = this;
469
0
        mpWindowImpl->mpFrame->CaptureMouse( true );
470
0
    }
471
0
}
472
473
void Window::ReleaseMouse()
474
0
{
475
0
    if (IsMouseCaptured())
476
0
    {
477
0
        ImplSVData* pSVData = ImplGetSVData();
478
0
        pSVData->mpWinData->mpCaptureWin = nullptr;
479
0
        if (mpWindowImpl && mpWindowImpl->mpFrame)
480
0
            mpWindowImpl->mpFrame->CaptureMouse( false );
481
0
        ImplGenerateMouseMove();
482
0
    }
483
0
}
484
485
bool Window::IsMouseCaptured() const
486
119k
{
487
119k
    return (this == ImplGetSVData()->mpWinData->mpCaptureWin);
488
119k
}
489
490
void Window::SetPointer( PointerStyle nPointer )
491
4.26k
{
492
4.26k
    if ( mpWindowImpl->maPointer == nPointer )
493
0
        return;
494
495
4.26k
    mpWindowImpl->maPointer   = nPointer;
496
497
    // possibly immediately move pointer
498
4.26k
    if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
499
0
        mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
500
4.26k
}
501
502
void Window::EnableChildPointerOverwrite( bool bOverwrite )
503
0
{
504
505
0
    if ( mpWindowImpl->mbChildPtrOverwrite == bOverwrite )
506
0
        return;
507
508
0
    mpWindowImpl->mbChildPtrOverwrite  = bOverwrite;
509
510
    // possibly immediately move pointer
511
0
    if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
512
0
        mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
513
0
}
514
515
void Window::SetPointerPosPixel( const Point& rPos )
516
0
{
517
0
    Point aPos = OutputToScreenPixel( rPos );
518
0
    const OutputDevice *pOutDev = GetOutDev();
519
0
    if( pOutDev->HasMirroredGraphics() )
520
0
    {
521
0
        if( !IsRTLEnabled() )
522
0
        {
523
0
            pOutDev->ReMirror( aPos );
524
0
        }
525
        // mirroring is required here, SetPointerPos bypasses SalGraphics
526
0
        aPos.setX( GetOutDev()->mpGraphics->mirror2( aPos.X(), *GetOutDev() ) );
527
0
    }
528
0
    else if( GetOutDev()->ImplIsAntiparallel() )
529
0
    {
530
0
        pOutDev->ReMirror( aPos );
531
0
    }
532
0
    mpWindowImpl->mpFrame->SetPointerPos( aPos.X(), aPos.Y() );
533
0
}
534
535
void Window::SetLastMousePos(const Point& rPos)
536
0
{
537
    // Do this conversion, so when GetPointerPosPixel() calls
538
    // ScreenToOutputPixel(), we get back the original position.
539
0
    Point aPos = OutputToScreenPixel(rPos);
540
0
    mpWindowImpl->mpFrameData->mnLastMouseX = aPos.X();
541
0
    mpWindowImpl->mpFrameData->mnLastMouseY = aPos.Y();
542
0
}
543
544
Point Window::GetPointerPosPixel()
545
17.3k
{
546
547
17.3k
    Point aPos( mpWindowImpl->mpFrameData->mnLastMouseX, mpWindowImpl->mpFrameData->mnLastMouseY );
548
17.3k
    if( GetOutDev()->ImplIsAntiparallel() )
549
0
    {
550
0
        const OutputDevice *pOutDev = GetOutDev();
551
0
        pOutDev->ReMirror( aPos );
552
0
    }
553
17.3k
    return ScreenToOutputPixel( aPos );
554
17.3k
}
555
556
Point Window::GetLastPointerPosPixel()
557
0
{
558
559
0
    Point aPos( mpWindowImpl->mpFrameData->mnBeforeLastMouseX, mpWindowImpl->mpFrameData->mnBeforeLastMouseY );
560
0
    if( GetOutDev()->ImplIsAntiparallel() )
561
0
    {
562
0
        const OutputDevice *pOutDev = GetOutDev();
563
0
        pOutDev->ReMirror( aPos );
564
0
    }
565
0
    return ScreenToOutputPixel( aPos );
566
0
}
567
568
void Window::ShowPointer( bool bVisible )
569
0
{
570
571
0
    if ( mpWindowImpl->mbNoPtrVisible != !bVisible )
572
0
    {
573
0
        mpWindowImpl->mbNoPtrVisible = !bVisible;
574
575
        // possibly immediately move pointer
576
0
        if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
577
0
            mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
578
0
    }
579
0
}
580
581
Window::PointerState Window::GetPointerState()
582
0
{
583
0
    PointerState aState;
584
0
    aState.mnState = 0;
585
586
0
    if (mpWindowImpl->mpFrame)
587
0
    {
588
0
        SalFrame::SalPointerState aSalPointerState = mpWindowImpl->mpFrame->GetPointerState();
589
0
        if( GetOutDev()->ImplIsAntiparallel() )
590
0
        {
591
0
            const OutputDevice *pOutDev = GetOutDev();
592
0
            pOutDev->ReMirror( aSalPointerState.maPos );
593
0
        }
594
0
        aState.maPos = ScreenToOutputPixel( aSalPointerState.maPos );
595
0
        aState.mnState = aSalPointerState.mnState;
596
0
    }
597
0
    return aState;
598
0
}
599
600
bool Window::IsMouseOver() const
601
0
{
602
0
    return ImplGetWinData()->mbMouseOver;
603
0
}
604
605
void Window::EnterWait()
606
8.67k
{
607
608
8.67k
    mpWindowImpl->mnWaitCount++;
609
610
8.67k
    if ( mpWindowImpl->mnWaitCount == 1 )
611
4.41k
    {
612
        // possibly immediately move pointer
613
4.41k
        if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
614
0
            mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
615
4.41k
    }
616
8.67k
}
617
618
void Window::LeaveWait()
619
8.67k
{
620
8.67k
    if( !mpWindowImpl )
621
0
        return;
622
623
8.67k
    if ( mpWindowImpl->mnWaitCount )
624
8.67k
    {
625
8.67k
        mpWindowImpl->mnWaitCount--;
626
627
8.67k
        if ( !mpWindowImpl->mnWaitCount )
628
4.41k
        {
629
            // possibly immediately move pointer
630
4.41k
            if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
631
0
                mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
632
4.41k
        }
633
8.67k
    }
634
8.67k
}
635
636
bool Window::ImplStopDnd()
637
0
{
638
0
    bool bRet = false;
639
0
    if( mpWindowImpl->mpFrameData && mpWindowImpl->mpFrameData->mxDropTargetListener.is() )
640
0
    {
641
0
        bRet = true;
642
0
        mpWindowImpl->mpFrameData->mxDropTarget.clear();
643
0
        mpWindowImpl->mpFrameData->mxDragSource.clear();
644
0
        mpWindowImpl->mpFrameData->mxDropTargetListener.clear();
645
0
    }
646
647
0
    return bRet;
648
0
}
649
650
void Window::ImplStartDnd()
651
0
{
652
0
    GetDropTarget();
653
0
}
654
655
rtl::Reference<DNDListenerContainer> Window::GetDropTarget()
656
37.6k
{
657
37.6k
    if( !mpWindowImpl )
658
0
        return {};
659
660
37.6k
    if( ! mpWindowImpl->mxDNDListenerContainer.is() )
661
12.1k
    {
662
12.1k
        sal_Int8 nDefaultActions = 0;
663
664
12.1k
        if( mpWindowImpl->mpFrameData )
665
12.1k
        {
666
12.1k
            if( ! mpWindowImpl->mpFrameData->mxDropTarget.is() )
667
12.1k
            {
668
                // initialization is done in GetDragSource
669
12.1k
                GetDragSource();
670
12.1k
            }
671
672
12.1k
            if( mpWindowImpl->mpFrameData->mxDropTarget.is() )
673
0
            {
674
0
                nDefaultActions = mpWindowImpl->mpFrameData->mxDropTarget->getDefaultActions();
675
676
0
                if( ! mpWindowImpl->mpFrameData->mxDropTargetListener.is() )
677
0
                {
678
0
                    mpWindowImpl->mpFrameData->mxDropTargetListener = new DNDEventDispatcher( mpWindowImpl->mpFrameWindow );
679
680
0
                    try
681
0
                    {
682
0
                        mpWindowImpl->mpFrameData->mxDropTarget->addDropTargetListener( mpWindowImpl->mpFrameData->mxDropTargetListener );
683
684
                        // register also as drag gesture listener if directly supported by drag source
685
0
                        Reference< css::datatransfer::dnd::XDragGestureRecognizer > xDragGestureRecognizer(
686
0
                            mpWindowImpl->mpFrameData->mxDragSource, UNO_QUERY);
687
688
0
                        if( xDragGestureRecognizer.is() )
689
0
                        {
690
0
                            xDragGestureRecognizer->addDragGestureListener(mpWindowImpl->mpFrameData->mxDropTargetListener);
691
0
                        }
692
0
                        else
693
0
                            mpWindowImpl->mpFrameData->mbInternalDragGestureRecognizer = true;
694
695
0
                    }
696
0
                    catch (const RuntimeException&)
697
0
                    {
698
                        // release all instances
699
0
                        mpWindowImpl->mpFrameData->mxDropTarget.clear();
700
0
                        mpWindowImpl->mpFrameData->mxDragSource.clear();
701
0
                    }
702
0
                }
703
0
            }
704
705
12.1k
        }
706
707
12.1k
        mpWindowImpl->mxDNDListenerContainer = new DNDListenerContainer( nDefaultActions );
708
12.1k
    }
709
710
    // this object is located in the same process, so there will be no runtime exception
711
37.6k
    return mpWindowImpl->mxDNDListenerContainer;
712
37.6k
}
713
714
Reference< css::datatransfer::dnd::XDragSource > Window::GetDragSource()
715
12.1k
{
716
#if HAVE_FEATURE_DESKTOP
717
    const SystemEnvData* pEnvData = GetSystemData();
718
    if (!mpWindowImpl->mpFrameData || !pEnvData)
719
        return Reference<css::datatransfer::dnd::XDragSource>();
720
    if (mpWindowImpl->mpFrameData->mxDragSource.is())
721
        return mpWindowImpl->mpFrameData->mxDragSource;
722
723
    try
724
    {
725
        SalInstance* pInst = ImplGetSVData()->mpDefInst;
726
        mpWindowImpl->mpFrameData->mxDragSource = pInst->CreateDragSource(*pEnvData);
727
        mpWindowImpl->mpFrameData->mxDropTarget = pInst->CreateDropTarget(*pEnvData);
728
    }
729
    catch (const Exception&)
730
    {
731
        mpWindowImpl->mpFrameData->mxDropTarget.clear();
732
        mpWindowImpl->mpFrameData->mxDragSource.clear();
733
    }
734
    return mpWindowImpl->mpFrameData->mxDragSource;
735
#else
736
12.1k
    return Reference< css::datatransfer::dnd::XDragSource > ();
737
12.1k
#endif
738
12.1k
}
739
740
} /* namespace vcl */
741
742
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */