File: | home/maarten/src/libreoffice/core/include/rtl/ref.hxx |
Warning: | line 113, column 13 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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_features.h> | ||||||
22 | #include <config_feature_desktop.h> | ||||||
23 | |||||||
24 | #include <tools/time.hxx> | ||||||
25 | |||||||
26 | #include <LibreOfficeKit/LibreOfficeKitEnums.h> | ||||||
27 | |||||||
28 | #include <vcl/ITiledRenderable.hxx> | ||||||
29 | #include <vcl/svapp.hxx> | ||||||
30 | #include <vcl/window.hxx> | ||||||
31 | #include <vcl/cursor.hxx> | ||||||
32 | #include <vcl/sysdata.hxx> | ||||||
33 | #include <vcl/event.hxx> | ||||||
34 | |||||||
35 | #include <sal/types.h> | ||||||
36 | |||||||
37 | #include <window.h> | ||||||
38 | #include <svdata.hxx> | ||||||
39 | #include <salobj.hxx> | ||||||
40 | #include <salgdi.hxx> | ||||||
41 | #include <salframe.hxx> | ||||||
42 | |||||||
43 | #include <dndlistenercontainer.hxx> | ||||||
44 | #include <dndeventdispatcher.hxx> | ||||||
45 | |||||||
46 | #include <com/sun/star/datatransfer/dnd/XDragSource.hpp> | ||||||
47 | #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp> | ||||||
48 | #include <com/sun/star/uno/XComponentContext.hpp> | ||||||
49 | |||||||
50 | #include <comphelper/processfactory.hxx> | ||||||
51 | |||||||
52 | using namespace ::com::sun::star::uno; | ||||||
53 | |||||||
54 | namespace vcl { | ||||||
55 | |||||||
56 | WindowHitTest Window::ImplHitTest( const Point& rFramePos ) | ||||||
57 | { | ||||||
58 | Point aFramePos( rFramePos ); | ||||||
59 | if( ImplIsAntiparallel() ) | ||||||
60 | { | ||||||
61 | const OutputDevice *pOutDev = GetOutDev(); | ||||||
62 | pOutDev->ReMirror( aFramePos ); | ||||||
63 | } | ||||||
64 | tools::Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) ); | ||||||
65 | if ( !aRect.IsInside( aFramePos ) ) | ||||||
66 | return WindowHitTest::NONE; | ||||||
67 | if ( mpWindowImpl->mbWinRegion ) | ||||||
68 | { | ||||||
69 | Point aTempPos = aFramePos; | ||||||
70 | aTempPos.AdjustX( -mnOutOffX ); | ||||||
71 | aTempPos.AdjustY( -mnOutOffY ); | ||||||
72 | if ( !mpWindowImpl->maWinRegion.IsInside( aTempPos ) ) | ||||||
73 | return WindowHitTest::NONE; | ||||||
74 | } | ||||||
75 | |||||||
76 | WindowHitTest nHitTest = WindowHitTest::Inside; | ||||||
77 | if ( mpWindowImpl->mbMouseTransparent ) | ||||||
78 | nHitTest |= WindowHitTest::Transparent; | ||||||
79 | return nHitTest; | ||||||
80 | } | ||||||
81 | |||||||
82 | bool Window::ImplTestMousePointerSet() | ||||||
83 | { | ||||||
84 | // as soon as mouse is captured, switch mouse-pointer | ||||||
85 | if ( IsMouseCaptured() ) | ||||||
86 | return true; | ||||||
87 | |||||||
88 | // if the mouse is over the window, switch it | ||||||
89 | tools::Rectangle aClientRect( Point( 0, 0 ), GetOutputSizePixel() ); | ||||||
90 | return aClientRect.IsInside( GetPointerPosPixel() ); | ||||||
91 | } | ||||||
92 | |||||||
93 | PointerStyle Window::ImplGetMousePointer() const | ||||||
94 | { | ||||||
95 | PointerStyle ePointerStyle; | ||||||
96 | bool bWait = false; | ||||||
97 | |||||||
98 | if ( IsEnabled() && IsInputEnabled() && ! IsInModalMode() ) | ||||||
99 | ePointerStyle = GetPointer(); | ||||||
100 | else | ||||||
101 | ePointerStyle = PointerStyle::Arrow; | ||||||
102 | |||||||
103 | const vcl::Window* pWindow = this; | ||||||
104 | do | ||||||
105 | { | ||||||
106 | // when the pointer is not visible stop the search, as | ||||||
107 | // this status should not be overwritten | ||||||
108 | if ( pWindow->mpWindowImpl->mbNoPtrVisible ) | ||||||
109 | return PointerStyle::Null; | ||||||
110 | |||||||
111 | if ( !bWait ) | ||||||
112 | { | ||||||
113 | if ( pWindow->mpWindowImpl->mnWaitCount ) | ||||||
114 | { | ||||||
115 | ePointerStyle = PointerStyle::Wait; | ||||||
116 | bWait = true; | ||||||
117 | } | ||||||
118 | else | ||||||
119 | { | ||||||
120 | if ( pWindow->mpWindowImpl->mbChildPtrOverwrite ) | ||||||
121 | ePointerStyle = pWindow->GetPointer(); | ||||||
122 | } | ||||||
123 | } | ||||||
124 | |||||||
125 | if ( pWindow->ImplIsOverlapWindow() ) | ||||||
126 | break; | ||||||
127 | |||||||
128 | pWindow = pWindow->ImplGetParent(); | ||||||
129 | } | ||||||
130 | while ( pWindow ); | ||||||
131 | |||||||
132 | return ePointerStyle; | ||||||
133 | } | ||||||
134 | |||||||
135 | void Window::ImplCallMouseMove( sal_uInt16 nMouseCode, bool bModChanged ) | ||||||
136 | { | ||||||
137 | if ( !(mpWindowImpl->mpFrameData->mbMouseIn && mpWindowImpl->mpFrameWindow->mpWindowImpl->mbReallyVisible) ) | ||||||
138 | return; | ||||||
139 | |||||||
140 | sal_uInt64 nTime = tools::Time::GetSystemTicks(); | ||||||
141 | long nX = mpWindowImpl->mpFrameData->mnLastMouseX; | ||||||
142 | long nY = mpWindowImpl->mpFrameData->mnLastMouseY; | ||||||
143 | sal_uInt16 nCode = nMouseCode; | ||||||
144 | MouseEventModifiers nMode = mpWindowImpl->mpFrameData->mnMouseMode; | ||||||
145 | bool bLeave; | ||||||
146 | // check for MouseLeave | ||||||
147 | bLeave = ((nX < 0) || (nY < 0) || | ||||||
148 | (nX >= mpWindowImpl->mpFrameWindow->mnOutWidth) || | ||||||
149 | (nY >= mpWindowImpl->mpFrameWindow->mnOutHeight)) && | ||||||
150 | !ImplGetSVData()->mpWinData->mpCaptureWin; | ||||||
151 | nMode |= MouseEventModifiers::SYNTHETIC; | ||||||
152 | if ( bModChanged ) | ||||||
153 | nMode |= MouseEventModifiers::MODIFIERCHANGED; | ||||||
154 | ImplHandleMouseEvent( mpWindowImpl->mpFrameWindow, MouseNotifyEvent::MOUSEMOVE, bLeave, nX, nY, nTime, nCode, nMode ); | ||||||
155 | } | ||||||
156 | |||||||
157 | void Window::ImplGenerateMouseMove() | ||||||
158 | { | ||||||
159 | if ( mpWindowImpl && mpWindowImpl->mpFrameData && | ||||||
160 | !mpWindowImpl->mpFrameData->mnMouseMoveId ) | ||||||
161 | mpWindowImpl->mpFrameData->mnMouseMoveId = Application::PostUserEvent( LINK( mpWindowImpl->mpFrameWindow, Window, ImplGenerateMouseMoveHdl )::tools::detail::makeLink( ::tools::detail::castTo<Window * >(mpWindowImpl->mpFrameWindow), &Window::LinkStubImplGenerateMouseMoveHdl ), nullptr, true ); | ||||||
162 | } | ||||||
163 | |||||||
164 | IMPL_LINK_NOARG(Window, ImplGenerateMouseMoveHdl, void*, void)void Window::LinkStubImplGenerateMouseMoveHdl(void * instance , void* data) { return static_cast<Window *>(instance)-> ImplGenerateMouseMoveHdl(data); } void Window::ImplGenerateMouseMoveHdl (__attribute__ ((unused)) void*) | ||||||
165 | { | ||||||
166 | mpWindowImpl->mpFrameData->mnMouseMoveId = nullptr; | ||||||
167 | vcl::Window* pCaptureWin = ImplGetSVData()->mpWinData->mpCaptureWin; | ||||||
168 | if( ! pCaptureWin || | ||||||
169 | (pCaptureWin->mpWindowImpl && pCaptureWin->mpWindowImpl->mpFrame == mpWindowImpl->mpFrame) | ||||||
170 | ) | ||||||
171 | { | ||||||
172 | ImplCallMouseMove( mpWindowImpl->mpFrameData->mnMouseCode ); | ||||||
173 | } | ||||||
174 | } | ||||||
175 | |||||||
176 | void Window::ImplInvertFocus( const tools::Rectangle& rRect ) | ||||||
177 | { | ||||||
178 | InvertTracking( rRect, ShowTrackFlags::Small | ShowTrackFlags::TrackWindow ); | ||||||
179 | } | ||||||
180 | |||||||
181 | static bool IsWindowFocused(const WindowImpl& rWinImpl) | ||||||
182 | { | ||||||
183 | if (rWinImpl.mpSysObj) | ||||||
184 | return true; | ||||||
185 | |||||||
186 | if (rWinImpl.mpFrameData->mbHasFocus) | ||||||
187 | return true; | ||||||
188 | |||||||
189 | if (rWinImpl.mbFakeFocusSet) | ||||||
190 | return true; | ||||||
191 | |||||||
192 | return false; | ||||||
193 | } | ||||||
194 | |||||||
195 | void Window::ImplGrabFocus( GetFocusFlags nFlags ) | ||||||
196 | { | ||||||
197 | // #143570# no focus for destructing windows | ||||||
198 | if( !mpWindowImpl || mpWindowImpl->mbInDispose ) | ||||||
199 | return; | ||||||
200 | |||||||
201 | // some event listeners do really bad stuff | ||||||
202 | // => prepare for the worst | ||||||
203 | 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 | if ( mpWindowImpl->mpClientWindow ) | ||||||
211 | { | ||||||
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 | if ( mpWindowImpl->mpLastFocusWindow && (mpWindowImpl->mpLastFocusWindow.get() != this) && | ||||||
216 | !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) && | ||||||
217 | mpWindowImpl->mpLastFocusWindow->IsEnabled() && | ||||||
218 | mpWindowImpl->mpLastFocusWindow->IsInputEnabled() && | ||||||
219 | ! mpWindowImpl->mpLastFocusWindow->IsInModalMode() | ||||||
220 | ) | ||||||
221 | mpWindowImpl->mpLastFocusWindow->GrabFocus(); | ||||||
222 | else | ||||||
223 | mpWindowImpl->mpClientWindow->GrabFocus(); | ||||||
224 | return; | ||||||
225 | } | ||||||
226 | else if ( mpWindowImpl->mbFrame ) | ||||||
227 | { | ||||||
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 | if ( mpWindowImpl->mpLastFocusWindow && (mpWindowImpl->mpLastFocusWindow.get() != this) && | ||||||
232 | !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) && | ||||||
233 | mpWindowImpl->mpLastFocusWindow->IsEnabled() && | ||||||
234 | mpWindowImpl->mpLastFocusWindow->IsInputEnabled() && | ||||||
235 | ! mpWindowImpl->mpLastFocusWindow->IsInModalMode() | ||||||
236 | ) | ||||||
237 | { | ||||||
238 | mpWindowImpl->mpLastFocusWindow->GrabFocus(); | ||||||
239 | return; | ||||||
240 | } | ||||||
241 | } | ||||||
242 | |||||||
243 | // If the Window is disabled, then we don't change the focus | ||||||
244 | if ( !IsEnabled() || !IsInputEnabled() || IsInModalMode() ) | ||||||
245 | 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 | ImplSVData* pSVData = ImplGetSVData(); | ||||||
252 | |||||||
253 | bool bAsyncFocusWaiting = false; | ||||||
254 | vcl::Window *pFrame = pSVData->maFrameData.mpFirstFrame; | ||||||
255 | while( pFrame ) | ||||||
256 | { | ||||||
257 | if( pFrame != mpWindowImpl->mpFrameWindow.get() && pFrame->mpWindowImpl->mpFrameData->mnFocusId ) | ||||||
258 | { | ||||||
259 | bAsyncFocusWaiting = true; | ||||||
260 | break; | ||||||
261 | } | ||||||
262 | pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame; | ||||||
263 | } | ||||||
264 | |||||||
265 | bool bHasFocus = IsWindowFocused(*mpWindowImpl); | ||||||
266 | |||||||
267 | bool bMustNotGrabFocus = false; | ||||||
268 | // #100242#, check parent hierarchy if some floater prohibits grab focus | ||||||
269 | |||||||
270 | vcl::Window *pParent = this; | ||||||
271 | while( pParent ) | ||||||
272 | { | ||||||
273 | if ((pParent->GetStyle() & WB_SYSTEMFLOATWIN) && !(pParent->GetStyle() & WB_MOVEABLE)) | ||||||
274 | { | ||||||
275 | bMustNotGrabFocus = true; | ||||||
276 | break; | ||||||
277 | } | ||||||
278 | pParent = pParent->mpWindowImpl->mpParent; | ||||||
279 | } | ||||||
280 | |||||||
281 | if ( !(( pSVData->mpWinData->mpFocusWin.get() != this && | ||||||
282 | !mpWindowImpl->mbInDispose ) || | ||||||
283 | ( bAsyncFocusWaiting && !bHasFocus && !bMustNotGrabFocus )) ) | ||||||
284 | return; | ||||||
285 | |||||||
286 | // EndExtTextInput if it is not the same window | ||||||
287 | if (pSVData->mpWinData->mpExtTextInputWin | ||||||
288 | && (pSVData->mpWinData->mpExtTextInputWin.get() != this)) | ||||||
289 | pSVData->mpWinData->mpExtTextInputWin->EndExtTextInput(); | ||||||
290 | |||||||
291 | // mark this windows as the last FocusWindow | ||||||
292 | vcl::Window* pOverlapWindow = ImplGetFirstOverlapWindow(); | ||||||
293 | pOverlapWindow->mpWindowImpl->mpLastFocusWindow = this; | ||||||
294 | mpWindowImpl->mpFrameData->mpFocusWin = this; | ||||||
295 | |||||||
296 | if( !bHasFocus
| ||||||
297 | { | ||||||
298 | // menu windows never get the system focus | ||||||
299 | // the application will keep the focus | ||||||
300 | if( bMustNotGrabFocus ) | ||||||
301 | return; | ||||||
302 | else | ||||||
303 | { | ||||||
304 | // here we already switch focus as ToTop() | ||||||
305 | // should not give focus to another window | ||||||
306 | mpWindowImpl->mpFrame->ToTop( SalFrameToTop::GrabFocus | SalFrameToTop::GrabFocusOnly ); | ||||||
307 | return; | ||||||
308 | } | ||||||
309 | } | ||||||
310 | |||||||
311 | VclPtr<vcl::Window> pOldFocusWindow = pSVData->mpWinData->mpFocusWin; | ||||||
312 | |||||||
313 | pSVData->mpWinData->mpFocusWin = this; | ||||||
314 | |||||||
315 | if ( pOldFocusWindow && pOldFocusWindow->mpWindowImpl ) | ||||||
316 | { | ||||||
317 | // Cursor hidden | ||||||
318 | if ( pOldFocusWindow->mpWindowImpl->mpCursor ) | ||||||
319 | pOldFocusWindow->mpWindowImpl->mpCursor->ImplHide(); | ||||||
320 | } | ||||||
321 | |||||||
322 | // !!!!! due to old SV-Office Activate/Deactivate handling | ||||||
323 | // !!!!! first as before | ||||||
324 | if ( pOldFocusWindow ) | ||||||
325 | { | ||||||
326 | // remember Focus | ||||||
327 | vcl::Window* pOldOverlapWindow = pOldFocusWindow->ImplGetFirstOverlapWindow(); | ||||||
328 | vcl::Window* pNewOverlapWindow = ImplGetFirstOverlapWindow(); | ||||||
329 | if ( pOldOverlapWindow != pNewOverlapWindow ) | ||||||
330 | ImplCallFocusChangeActivate( pNewOverlapWindow, pOldOverlapWindow ); | ||||||
331 | } | ||||||
332 | else | ||||||
333 | { | ||||||
334 | vcl::Window* pNewOverlapWindow = ImplGetFirstOverlapWindow(); | ||||||
335 | vcl::Window* pNewRealWindow = pNewOverlapWindow->ImplGetWindow(); | ||||||
336 | pNewOverlapWindow->mpWindowImpl->mbActive = true; | ||||||
337 | pNewOverlapWindow->Activate(); | ||||||
338 | if ( pNewRealWindow != pNewOverlapWindow ) | ||||||
339 | { | ||||||
340 | pNewRealWindow->mpWindowImpl->mbActive = true; | ||||||
341 | pNewRealWindow->Activate(); | ||||||
342 | } | ||||||
343 | } | ||||||
344 | |||||||
345 | // call Get- and LoseFocus | ||||||
346 | if ( pOldFocusWindow && ! pOldFocusWindow->IsDisposed() ) | ||||||
347 | { | ||||||
348 | NotifyEvent aNEvt( MouseNotifyEvent::LOSEFOCUS, pOldFocusWindow ); | ||||||
349 | if ( !ImplCallPreNotify( aNEvt ) ) | ||||||
350 | pOldFocusWindow->CompatLoseFocus(); | ||||||
351 | pOldFocusWindow->ImplCallDeactivateListeners( this ); | ||||||
352 | } | ||||||
353 | |||||||
354 | if (pSVData->mpWinData->mpFocusWin.get() == this) | ||||||
355 | { | ||||||
356 | if ( mpWindowImpl->mpSysObj ) | ||||||
357 | { | ||||||
358 | mpWindowImpl->mpFrameData->mpFocusWin = this; | ||||||
359 | if ( !mpWindowImpl->mpFrameData->mbInSysObjFocusHdl ) | ||||||
360 | mpWindowImpl->mpSysObj->GrabFocus(); | ||||||
361 | } | ||||||
362 | |||||||
363 | if (pSVData->mpWinData->mpFocusWin.get() == this) | ||||||
364 | { | ||||||
365 | if ( mpWindowImpl->mpCursor ) | ||||||
366 | mpWindowImpl->mpCursor->ImplShow(); | ||||||
367 | mpWindowImpl->mbInFocusHdl = true; | ||||||
368 | mpWindowImpl->mnGetFocusFlags = nFlags; | ||||||
369 | // if we're changing focus due to closing a popup floating window | ||||||
370 | // notify the new focus window so it can restore the inner focus | ||||||
371 | // eg, toolboxes can select their recent active item | ||||||
372 | if( pOldFocusWindow && | ||||||
373 | ! pOldFocusWindow->IsDisposed() && | ||||||
374 | ( pOldFocusWindow->GetDialogControlFlags() & DialogControlFlags::FloatWinPopupModeEndCancel ) ) | ||||||
375 | mpWindowImpl->mnGetFocusFlags |= GetFocusFlags::FloatWinPopupModeEndCancel; | ||||||
376 | NotifyEvent aNEvt( MouseNotifyEvent::GETFOCUS, this ); | ||||||
377 | if ( !ImplCallPreNotify( aNEvt ) && !xWindow->IsDisposed() ) | ||||||
378 | CompatGetFocus(); | ||||||
379 | if( !xWindow->IsDisposed() ) | ||||||
380 | ImplCallActivateListeners( (pOldFocusWindow && ! pOldFocusWindow->IsDisposed()) ? pOldFocusWindow : nullptr ); | ||||||
381 | if( !xWindow->IsDisposed() ) | ||||||
382 | { | ||||||
383 | mpWindowImpl->mnGetFocusFlags = GetFocusFlags::NONE; | ||||||
384 | mpWindowImpl->mbInFocusHdl = false; | ||||||
385 | } | ||||||
386 | } | ||||||
387 | } | ||||||
388 | |||||||
389 | ImplNewInputContext(); | ||||||
390 | |||||||
391 | } | ||||||
392 | |||||||
393 | void Window::ImplGrabFocusToDocument( GetFocusFlags nFlags ) | ||||||
394 | { | ||||||
395 | vcl::Window *pWin = this; | ||||||
396 | while( pWin ) | ||||||
| |||||||
397 | { | ||||||
398 | if( !pWin->GetParent() ) | ||||||
399 | { | ||||||
400 | pWin->mpWindowImpl->mpFrame->GrabFocus(); | ||||||
401 | pWin->ImplGetFrameWindow()->GetWindow( GetWindowType::Client )->ImplGrabFocus(nFlags); | ||||||
402 | return; | ||||||
403 | } | ||||||
404 | pWin = pWin->GetParent(); | ||||||
405 | } | ||||||
406 | } | ||||||
407 | |||||||
408 | void Window::MouseMove( const MouseEvent& rMEvt ) | ||||||
409 | { | ||||||
410 | NotifyEvent aNEvt( MouseNotifyEvent::MOUSEMOVE, this, &rMEvt ); | ||||||
411 | EventNotify(aNEvt); | ||||||
412 | } | ||||||
413 | |||||||
414 | void Window::MouseButtonDown( const MouseEvent& rMEvt ) | ||||||
415 | { | ||||||
416 | NotifyEvent aNEvt( MouseNotifyEvent::MOUSEBUTTONDOWN, this, &rMEvt ); | ||||||
417 | if (!EventNotify(aNEvt)) | ||||||
418 | mpWindowImpl->mbMouseButtonDown = true; | ||||||
419 | } | ||||||
420 | |||||||
421 | void Window::MouseButtonUp( const MouseEvent& rMEvt ) | ||||||
422 | { | ||||||
423 | NotifyEvent aNEvt( MouseNotifyEvent::MOUSEBUTTONUP, this, &rMEvt ); | ||||||
424 | if (!EventNotify(aNEvt)) | ||||||
425 | mpWindowImpl->mbMouseButtonUp = true; | ||||||
426 | } | ||||||
427 | |||||||
428 | void Window::SetMouseTransparent( bool bTransparent ) | ||||||
429 | { | ||||||
430 | |||||||
431 | if ( mpWindowImpl->mpBorderWindow ) | ||||||
432 | mpWindowImpl->mpBorderWindow->SetMouseTransparent( bTransparent ); | ||||||
433 | |||||||
434 | if( mpWindowImpl->mpSysObj ) | ||||||
435 | mpWindowImpl->mpSysObj->SetMouseTransparent( bTransparent ); | ||||||
436 | |||||||
437 | mpWindowImpl->mbMouseTransparent = bTransparent; | ||||||
438 | } | ||||||
439 | |||||||
440 | void Window::CaptureMouse() | ||||||
441 | { | ||||||
442 | ImplSVData* pSVData = ImplGetSVData(); | ||||||
443 | |||||||
444 | // possibly stop tracking | ||||||
445 | if (pSVData->mpWinData->mpTrackWin.get() != this) | ||||||
446 | { | ||||||
447 | if (pSVData->mpWinData->mpTrackWin) | ||||||
448 | pSVData->mpWinData->mpTrackWin->EndTracking(TrackingEventFlags::Cancel); | ||||||
449 | } | ||||||
450 | |||||||
451 | if (pSVData->mpWinData->mpCaptureWin.get() != this) | ||||||
452 | { | ||||||
453 | pSVData->mpWinData->mpCaptureWin = this; | ||||||
454 | mpWindowImpl->mpFrame->CaptureMouse( true ); | ||||||
455 | } | ||||||
456 | } | ||||||
457 | |||||||
458 | void Window::ReleaseMouse() | ||||||
459 | { | ||||||
460 | if (IsMouseCaptured()) | ||||||
461 | { | ||||||
462 | ImplSVData* pSVData = ImplGetSVData(); | ||||||
463 | pSVData->mpWinData->mpCaptureWin = nullptr; | ||||||
464 | mpWindowImpl->mpFrame->CaptureMouse( false ); | ||||||
465 | ImplGenerateMouseMove(); | ||||||
466 | } | ||||||
467 | } | ||||||
468 | |||||||
469 | bool Window::IsMouseCaptured() const | ||||||
470 | { | ||||||
471 | return (this == ImplGetSVData()->mpWinData->mpCaptureWin); | ||||||
472 | } | ||||||
473 | |||||||
474 | void Window::SetPointer( PointerStyle nPointer ) | ||||||
475 | { | ||||||
476 | if ( mpWindowImpl->maPointer == nPointer ) | ||||||
477 | return; | ||||||
478 | |||||||
479 | mpWindowImpl->maPointer = nPointer; | ||||||
480 | |||||||
481 | // possibly immediately move pointer | ||||||
482 | if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() ) | ||||||
483 | mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() ); | ||||||
484 | |||||||
485 | VclPtr<vcl::Window> pWin = GetParentWithLOKNotifier(); | ||||||
486 | if (!pWin) | ||||||
487 | return; | ||||||
488 | |||||||
489 | PointerStyle aPointer = GetPointer(); | ||||||
490 | // We don't map all possible pointers hence we need a default | ||||||
491 | OString aPointerString = "default"; | ||||||
492 | auto aIt = vcl::gaLOKPointerMap.find(aPointer); | ||||||
493 | if (aIt != vcl::gaLOKPointerMap.end()) | ||||||
494 | { | ||||||
495 | aPointerString = aIt->second; | ||||||
496 | } | ||||||
497 | |||||||
498 | // issue mouse pointer events only for document windows | ||||||
499 | // Doc windows' immediate parent SfxFrameViewWindow_Impl is the one with | ||||||
500 | // parent notifier set during initialization | ||||||
501 | if (GetParent()->ImplGetWindowImpl()->mbLOKParentNotifier && | ||||||
502 | GetParent()->ImplGetWindowImpl()->mnLOKWindowId == 0) | ||||||
503 | { | ||||||
504 | pWin->GetLOKNotifier()->libreOfficeKitViewCallback(LOK_CALLBACK_MOUSE_POINTER, aPointerString.getStr()); | ||||||
505 | } | ||||||
506 | } | ||||||
507 | |||||||
508 | void Window::EnableChildPointerOverwrite( bool bOverwrite ) | ||||||
509 | { | ||||||
510 | |||||||
511 | if ( mpWindowImpl->mbChildPtrOverwrite == bOverwrite ) | ||||||
512 | return; | ||||||
513 | |||||||
514 | mpWindowImpl->mbChildPtrOverwrite = bOverwrite; | ||||||
515 | |||||||
516 | // possibly immediately move pointer | ||||||
517 | if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() ) | ||||||
518 | mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() ); | ||||||
519 | } | ||||||
520 | |||||||
521 | void Window::SetPointerPosPixel( const Point& rPos ) | ||||||
522 | { | ||||||
523 | Point aPos = ImplOutputToFrame( rPos ); | ||||||
524 | const OutputDevice *pOutDev = GetOutDev(); | ||||||
525 | if( pOutDev->HasMirroredGraphics() ) | ||||||
526 | { | ||||||
527 | if( !IsRTLEnabled() ) | ||||||
528 | { | ||||||
529 | pOutDev->ReMirror( aPos ); | ||||||
530 | } | ||||||
531 | // mirroring is required here, SetPointerPos bypasses SalGraphics | ||||||
532 | aPos.setX( mpGraphics->mirror2( aPos.X(), this ) ); | ||||||
533 | } | ||||||
534 | else if( ImplIsAntiparallel() ) | ||||||
535 | { | ||||||
536 | pOutDev->ReMirror( aPos ); | ||||||
537 | } | ||||||
538 | mpWindowImpl->mpFrame->SetPointerPos( aPos.X(), aPos.Y() ); | ||||||
539 | } | ||||||
540 | |||||||
541 | void Window::SetLastMousePos(const Point& rPos) | ||||||
542 | { | ||||||
543 | // Do this conversion, so when GetPointerPosPixel() calls | ||||||
544 | // ImplFrameToOutput(), we get back the original position. | ||||||
545 | Point aPos = ImplOutputToFrame(rPos); | ||||||
546 | mpWindowImpl->mpFrameData->mnLastMouseX = aPos.X(); | ||||||
547 | mpWindowImpl->mpFrameData->mnLastMouseY = aPos.Y(); | ||||||
548 | } | ||||||
549 | |||||||
550 | Point Window::GetPointerPosPixel() | ||||||
551 | { | ||||||
552 | |||||||
553 | Point aPos( mpWindowImpl->mpFrameData->mnLastMouseX, mpWindowImpl->mpFrameData->mnLastMouseY ); | ||||||
554 | if( ImplIsAntiparallel() ) | ||||||
555 | { | ||||||
556 | const OutputDevice *pOutDev = GetOutDev(); | ||||||
557 | pOutDev->ReMirror( aPos ); | ||||||
558 | } | ||||||
559 | return ImplFrameToOutput( aPos ); | ||||||
560 | } | ||||||
561 | |||||||
562 | Point Window::GetLastPointerPosPixel() | ||||||
563 | { | ||||||
564 | |||||||
565 | Point aPos( mpWindowImpl->mpFrameData->mnBeforeLastMouseX, mpWindowImpl->mpFrameData->mnBeforeLastMouseY ); | ||||||
566 | if( ImplIsAntiparallel() ) | ||||||
567 | { | ||||||
568 | const OutputDevice *pOutDev = GetOutDev(); | ||||||
569 | pOutDev->ReMirror( aPos ); | ||||||
570 | } | ||||||
571 | return ImplFrameToOutput( aPos ); | ||||||
572 | } | ||||||
573 | |||||||
574 | void Window::ShowPointer( bool bVisible ) | ||||||
575 | { | ||||||
576 | |||||||
577 | if ( mpWindowImpl->mbNoPtrVisible != !bVisible ) | ||||||
578 | { | ||||||
579 | mpWindowImpl->mbNoPtrVisible = !bVisible; | ||||||
580 | |||||||
581 | // possibly immediately move pointer | ||||||
582 | if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() ) | ||||||
583 | mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() ); | ||||||
584 | } | ||||||
585 | } | ||||||
586 | |||||||
587 | Window::PointerState Window::GetPointerState() | ||||||
588 | { | ||||||
589 | PointerState aState; | ||||||
590 | aState.mnState = 0; | ||||||
591 | |||||||
592 | if (mpWindowImpl->mpFrame) | ||||||
593 | { | ||||||
594 | SalFrame::SalPointerState aSalPointerState = mpWindowImpl->mpFrame->GetPointerState(); | ||||||
595 | if( ImplIsAntiparallel() ) | ||||||
596 | { | ||||||
597 | const OutputDevice *pOutDev = GetOutDev(); | ||||||
598 | pOutDev->ReMirror( aSalPointerState.maPos ); | ||||||
599 | } | ||||||
600 | aState.maPos = ImplFrameToOutput( aSalPointerState.maPos ); | ||||||
601 | aState.mnState = aSalPointerState.mnState; | ||||||
602 | } | ||||||
603 | return aState; | ||||||
604 | } | ||||||
605 | |||||||
606 | bool Window::IsMouseOver() const | ||||||
607 | { | ||||||
608 | return ImplGetWinData()->mbMouseOver; | ||||||
609 | } | ||||||
610 | |||||||
611 | void Window::EnterWait() | ||||||
612 | { | ||||||
613 | |||||||
614 | mpWindowImpl->mnWaitCount++; | ||||||
615 | |||||||
616 | if ( mpWindowImpl->mnWaitCount == 1 ) | ||||||
617 | { | ||||||
618 | // possibly immediately move pointer | ||||||
619 | if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() ) | ||||||
620 | mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() ); | ||||||
621 | } | ||||||
622 | } | ||||||
623 | |||||||
624 | void Window::LeaveWait() | ||||||
625 | { | ||||||
626 | |||||||
627 | if ( mpWindowImpl->mnWaitCount ) | ||||||
628 | { | ||||||
629 | mpWindowImpl->mnWaitCount--; | ||||||
630 | |||||||
631 | if ( !mpWindowImpl->mnWaitCount ) | ||||||
632 | { | ||||||
633 | // possibly immediately move pointer | ||||||
634 | if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() ) | ||||||
635 | mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() ); | ||||||
636 | } | ||||||
637 | } | ||||||
638 | } | ||||||
639 | |||||||
640 | bool Window::ImplStopDnd() | ||||||
641 | { | ||||||
642 | bool bRet = false; | ||||||
643 | if( mpWindowImpl->mpFrameData && mpWindowImpl->mpFrameData->mxDropTargetListener.is() ) | ||||||
644 | { | ||||||
645 | bRet = true; | ||||||
646 | mpWindowImpl->mpFrameData->mxDropTarget.clear(); | ||||||
647 | mpWindowImpl->mpFrameData->mxDragSource.clear(); | ||||||
648 | mpWindowImpl->mpFrameData->mxDropTargetListener.clear(); | ||||||
649 | } | ||||||
650 | |||||||
651 | return bRet; | ||||||
652 | } | ||||||
653 | |||||||
654 | void Window::ImplStartDnd() | ||||||
655 | { | ||||||
656 | GetDropTarget(); | ||||||
657 | } | ||||||
658 | |||||||
659 | Reference< css::datatransfer::dnd::XDropTarget > Window::GetDropTarget() | ||||||
660 | { | ||||||
661 | if( !mpWindowImpl ) | ||||||
662 | return Reference< css::datatransfer::dnd::XDropTarget >(); | ||||||
663 | |||||||
664 | if( ! mpWindowImpl->mxDNDListenerContainer.is() ) | ||||||
665 | { | ||||||
666 | sal_Int8 nDefaultActions = 0; | ||||||
667 | |||||||
668 | if( mpWindowImpl->mpFrameData ) | ||||||
669 | { | ||||||
670 | if( ! mpWindowImpl->mpFrameData->mxDropTarget.is() ) | ||||||
671 | { | ||||||
672 | // initialization is done in GetDragSource | ||||||
673 | GetDragSource(); | ||||||
674 | } | ||||||
675 | |||||||
676 | if( mpWindowImpl->mpFrameData->mxDropTarget.is() ) | ||||||
677 | { | ||||||
678 | nDefaultActions = mpWindowImpl->mpFrameData->mxDropTarget->getDefaultActions(); | ||||||
679 | |||||||
680 | if( ! mpWindowImpl->mpFrameData->mxDropTargetListener.is() ) | ||||||
681 | { | ||||||
682 | mpWindowImpl->mpFrameData->mxDropTargetListener = new DNDEventDispatcher( mpWindowImpl->mpFrameWindow ); | ||||||
683 | |||||||
684 | try | ||||||
685 | { | ||||||
686 | mpWindowImpl->mpFrameData->mxDropTarget->addDropTargetListener( mpWindowImpl->mpFrameData->mxDropTargetListener ); | ||||||
687 | |||||||
688 | // register also as drag gesture listener if directly supported by drag source | ||||||
689 | Reference< css::datatransfer::dnd::XDragGestureRecognizer > xDragGestureRecognizer( | ||||||
690 | mpWindowImpl->mpFrameData->mxDragSource, UNO_QUERY); | ||||||
691 | |||||||
692 | if( xDragGestureRecognizer.is() ) | ||||||
693 | { | ||||||
694 | xDragGestureRecognizer->addDragGestureListener( | ||||||
695 | Reference< css::datatransfer::dnd::XDragGestureListener > (mpWindowImpl->mpFrameData->mxDropTargetListener, UNO_QUERY)); | ||||||
696 | } | ||||||
697 | else | ||||||
698 | mpWindowImpl->mpFrameData->mbInternalDragGestureRecognizer = true; | ||||||
699 | |||||||
700 | } | ||||||
701 | catch (const RuntimeException&) | ||||||
702 | { | ||||||
703 | // release all instances | ||||||
704 | mpWindowImpl->mpFrameData->mxDropTarget.clear(); | ||||||
705 | mpWindowImpl->mpFrameData->mxDragSource.clear(); | ||||||
706 | } | ||||||
707 | } | ||||||
708 | } | ||||||
709 | |||||||
710 | } | ||||||
711 | |||||||
712 | mpWindowImpl->mxDNDListenerContainer = static_cast < css::datatransfer::dnd::XDropTarget * > ( new DNDListenerContainer( nDefaultActions ) ); | ||||||
713 | } | ||||||
714 | |||||||
715 | // this object is located in the same process, so there will be no runtime exception | ||||||
716 | return Reference< css::datatransfer::dnd::XDropTarget > ( mpWindowImpl->mxDNDListenerContainer, UNO_QUERY ); | ||||||
717 | } | ||||||
718 | |||||||
719 | Reference< css::datatransfer::dnd::XDragSource > Window::GetDragSource() | ||||||
720 | { | ||||||
721 | |||||||
722 | #if HAVE_FEATURE_DESKTOP1 | ||||||
723 | |||||||
724 | if( mpWindowImpl->mpFrameData ) | ||||||
725 | { | ||||||
726 | if( ! mpWindowImpl->mpFrameData->mxDragSource.is() ) | ||||||
727 | { | ||||||
728 | try | ||||||
729 | { | ||||||
730 | Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() ); | ||||||
731 | const SystemEnvData * pEnvData = GetSystemData(); | ||||||
732 | |||||||
733 | if( pEnvData ) | ||||||
734 | { | ||||||
735 | Sequence< Any > aDragSourceAL( 2 ), aDropTargetAL( 2 ); | ||||||
736 | OUString aDragSourceSN, aDropTargetSN; | ||||||
737 | #if defined(_WIN32) | ||||||
738 | aDragSourceSN = "com.sun.star.datatransfer.dnd.OleDragSource"; | ||||||
739 | aDropTargetSN = "com.sun.star.datatransfer.dnd.OleDropTarget"; | ||||||
740 | aDragSourceAL[ 1 ] <<= static_cast<sal_uInt64>( reinterpret_cast<sal_IntPtr>(pEnvData->hWnd) ); | ||||||
741 | aDropTargetAL[ 0 ] <<= static_cast<sal_uInt64>( reinterpret_cast<sal_IntPtr>(pEnvData->hWnd) ); | ||||||
742 | #elif defined MACOSX | ||||||
743 | /* FIXME: macOS specific dnd interface does not exist! * | ||||||
744 | * Using Windows based dnd as a temporary solution */ | ||||||
745 | aDragSourceSN = "com.sun.star.datatransfer.dnd.OleDragSource"; | ||||||
746 | aDropTargetSN = "com.sun.star.datatransfer.dnd.OleDropTarget"; | ||||||
747 | aDragSourceAL[ 1 ] <<= static_cast<sal_uInt64>( reinterpret_cast<sal_IntPtr>(pEnvData->mpNSView) ); | ||||||
748 | aDropTargetAL[ 0 ] <<= static_cast<sal_uInt64>( reinterpret_cast<sal_IntPtr>(pEnvData->mpNSView) ); | ||||||
749 | #elif HAVE_FEATURE_X111 | ||||||
750 | aDragSourceSN = "com.sun.star.datatransfer.dnd.X11DragSource"; | ||||||
751 | aDropTargetSN = "com.sun.star.datatransfer.dnd.X11DropTarget"; | ||||||
752 | |||||||
753 | aDragSourceAL[ 0 ] <<= Application::GetDisplayConnection(); | ||||||
754 | aDragSourceAL[ 1 ] <<= pEnvData->aShellWindow; | ||||||
755 | aDropTargetAL[ 0 ] <<= Application::GetDisplayConnection(); | ||||||
756 | aDropTargetAL[ 1 ] <<= pEnvData->aShellWindow; | ||||||
757 | #endif | ||||||
758 | if( !aDragSourceSN.isEmpty() ) | ||||||
759 | mpWindowImpl->mpFrameData->mxDragSource.set( | ||||||
760 | xContext->getServiceManager()->createInstanceWithArgumentsAndContext( aDragSourceSN, aDragSourceAL, xContext ), | ||||||
761 | UNO_QUERY ); | ||||||
762 | |||||||
763 | if( !aDropTargetSN.isEmpty() ) | ||||||
764 | mpWindowImpl->mpFrameData->mxDropTarget.set( | ||||||
765 | xContext->getServiceManager()->createInstanceWithArgumentsAndContext( aDropTargetSN, aDropTargetAL, xContext ), | ||||||
766 | UNO_QUERY ); | ||||||
767 | } | ||||||
768 | } | ||||||
769 | |||||||
770 | // createInstance can throw any exception | ||||||
771 | catch (const Exception&) | ||||||
772 | { | ||||||
773 | // release all instances | ||||||
774 | mpWindowImpl->mpFrameData->mxDropTarget.clear(); | ||||||
775 | mpWindowImpl->mpFrameData->mxDragSource.clear(); | ||||||
776 | } | ||||||
777 | } | ||||||
778 | |||||||
779 | return mpWindowImpl->mpFrameData->mxDragSource; | ||||||
780 | } | ||||||
781 | #endif | ||||||
782 | return Reference< css::datatransfer::dnd::XDragSource > (); | ||||||
783 | } | ||||||
784 | |||||||
785 | Reference< css::datatransfer::dnd::XDragGestureRecognizer > Window::GetDragGestureRecognizer() | ||||||
786 | { | ||||||
787 | return Reference< css::datatransfer::dnd::XDragGestureRecognizer > ( GetDropTarget(), UNO_QUERY ); | ||||||
788 | } | ||||||
789 | |||||||
790 | } /* namespace vcl */ | ||||||
791 | |||||||
792 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_RTL_REF_HXX | ||||||||||||
21 | #define INCLUDED_RTL_REF_HXX | ||||||||||||
22 | |||||||||||||
23 | #include "sal/config.h" | ||||||||||||
24 | |||||||||||||
25 | #include <cassert> | ||||||||||||
26 | #include <cstddef> | ||||||||||||
27 | #include <functional> | ||||||||||||
28 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||||||||
29 | #include <type_traits> | ||||||||||||
30 | #endif | ||||||||||||
31 | |||||||||||||
32 | #include "sal/types.h" | ||||||||||||
33 | |||||||||||||
34 | namespace rtl | ||||||||||||
35 | { | ||||||||||||
36 | |||||||||||||
37 | /** Template reference class for reference type. | ||||||||||||
38 | */ | ||||||||||||
39 | template <class reference_type> | ||||||||||||
40 | class Reference | ||||||||||||
41 | { | ||||||||||||
42 | /** The <b>reference_type</b> body pointer. | ||||||||||||
43 | */ | ||||||||||||
44 | reference_type * m_pBody; | ||||||||||||
45 | |||||||||||||
46 | |||||||||||||
47 | public: | ||||||||||||
48 | /** Constructor... | ||||||||||||
49 | */ | ||||||||||||
50 | Reference() | ||||||||||||
51 | : m_pBody (NULL__null) | ||||||||||||
52 | {} | ||||||||||||
53 | |||||||||||||
54 | |||||||||||||
55 | /** Constructor... | ||||||||||||
56 | */ | ||||||||||||
57 | Reference (reference_type * pBody, __sal_NoAcquire) | ||||||||||||
58 | : m_pBody (pBody) | ||||||||||||
59 | { | ||||||||||||
60 | } | ||||||||||||
61 | |||||||||||||
62 | /** Constructor... | ||||||||||||
63 | */ | ||||||||||||
64 | Reference (reference_type * pBody) | ||||||||||||
65 | : m_pBody (pBody) | ||||||||||||
66 | { | ||||||||||||
67 | if (m_pBody) | ||||||||||||
68 | m_pBody->acquire(); | ||||||||||||
69 | } | ||||||||||||
70 | |||||||||||||
71 | /** Copy constructor... | ||||||||||||
72 | */ | ||||||||||||
73 | Reference (const Reference<reference_type> & handle) | ||||||||||||
74 | : m_pBody (handle.m_pBody) | ||||||||||||
75 | { | ||||||||||||
76 | if (m_pBody) | ||||||||||||
77 | m_pBody->acquire(); | ||||||||||||
78 | } | ||||||||||||
79 | |||||||||||||
80 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||||||||
81 | /** Move constructor... | ||||||||||||
82 | */ | ||||||||||||
83 | Reference (Reference<reference_type> && handle) noexcept | ||||||||||||
84 | : m_pBody (handle.m_pBody) | ||||||||||||
85 | { | ||||||||||||
86 | handle.m_pBody = nullptr; | ||||||||||||
87 | } | ||||||||||||
88 | #endif | ||||||||||||
89 | |||||||||||||
90 | #if defined LIBO_INTERNAL_ONLY1 | ||||||||||||
91 | /** Up-casting conversion constructor: Copies interface reference. | ||||||||||||
92 | |||||||||||||
93 | Does not work for up-casts to ambiguous bases. | ||||||||||||
94 | |||||||||||||
95 | @param rRef another reference | ||||||||||||
96 | */ | ||||||||||||
97 | template< class derived_type > | ||||||||||||
98 | inline Reference( | ||||||||||||
99 | const Reference< derived_type > & rRef, | ||||||||||||
100 | std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 ) | ||||||||||||
101 | : m_pBody (rRef.get()) | ||||||||||||
102 | { | ||||||||||||
103 | if (m_pBody) | ||||||||||||
104 | m_pBody->acquire(); | ||||||||||||
105 | } | ||||||||||||
106 | #endif | ||||||||||||
107 | |||||||||||||
108 | /** Destructor... | ||||||||||||
109 | */ | ||||||||||||
110 | ~Reference() COVERITY_NOEXCEPT_FALSE | ||||||||||||
111 | { | ||||||||||||
112 | if (m_pBody
| ||||||||||||
113 | m_pBody->release(); | ||||||||||||
| |||||||||||||
114 | } | ||||||||||||
115 | |||||||||||||
116 | /** Set... | ||||||||||||
117 | Similar to assignment. | ||||||||||||
118 | */ | ||||||||||||
119 | Reference<reference_type> & | ||||||||||||
120 | SAL_CALL set (reference_type * pBody) | ||||||||||||
121 | { | ||||||||||||
122 | if (pBody) | ||||||||||||
123 | pBody->acquire(); | ||||||||||||
124 | reference_type * const pOld = m_pBody; | ||||||||||||
125 | m_pBody = pBody; | ||||||||||||
126 | if (pOld) | ||||||||||||
127 | pOld->release(); | ||||||||||||
128 | return *this; | ||||||||||||
129 | } | ||||||||||||
130 | |||||||||||||
131 | /** Assignment. | ||||||||||||
132 | Unbinds this instance from its body (if bound) and | ||||||||||||
133 | bind it to the body represented by the handle. | ||||||||||||
134 | */ | ||||||||||||
135 | Reference<reference_type> & | ||||||||||||
136 | SAL_CALL operator= (const Reference<reference_type> & handle) | ||||||||||||
137 | { | ||||||||||||
138 | return set( handle.m_pBody ); | ||||||||||||
139 | } | ||||||||||||
140 | |||||||||||||
141 | #ifdef LIBO_INTERNAL_ONLY1 | ||||||||||||
142 | /** Assignment. | ||||||||||||
143 | * Unbinds this instance from its body (if bound), | ||||||||||||
144 | * bind it to the body represented by the handle, and | ||||||||||||
145 | * set the body represented by the handle to nullptr. | ||||||||||||
146 | */ | ||||||||||||
147 | Reference<reference_type> & | ||||||||||||
148 | operator= (Reference<reference_type> && handle) | ||||||||||||
149 | { | ||||||||||||
150 | // self-movement guts ourself | ||||||||||||
151 | if (m_pBody) | ||||||||||||
152 | m_pBody->release(); | ||||||||||||
153 | m_pBody = handle.m_pBody; | ||||||||||||
154 | handle.m_pBody = nullptr; | ||||||||||||
155 | return *this; | ||||||||||||
156 | } | ||||||||||||
157 | #endif | ||||||||||||
158 | |||||||||||||
159 | /** Assignment... | ||||||||||||
160 | */ | ||||||||||||
161 | Reference<reference_type> & | ||||||||||||
162 | SAL_CALL operator= (reference_type * pBody) | ||||||||||||
163 | { | ||||||||||||
164 | return set( pBody ); | ||||||||||||
165 | } | ||||||||||||
166 | |||||||||||||
167 | /** Unbind the body from this handle. | ||||||||||||
168 | Note that for a handle representing a large body, | ||||||||||||
169 | "handle.clear().set(new body());" _might_ | ||||||||||||
170 | perform a little bit better than "handle.set(new body());", | ||||||||||||
171 | since in the second case two large objects exist in memory | ||||||||||||
172 | (the old body and the new body). | ||||||||||||
173 | */ | ||||||||||||
174 | Reference<reference_type> & SAL_CALL clear() | ||||||||||||
175 | { | ||||||||||||
176 | if (m_pBody) | ||||||||||||
177 | { | ||||||||||||
178 | reference_type * const pOld = m_pBody; | ||||||||||||
179 | m_pBody = NULL__null; | ||||||||||||
180 | pOld->release(); | ||||||||||||
181 | } | ||||||||||||
182 | return *this; | ||||||||||||
183 | } | ||||||||||||
184 | |||||||||||||
185 | |||||||||||||
186 | /** Get the body. Can be used instead of operator->(). | ||||||||||||
187 | I.e. handle->someBodyOp() and handle.get()->someBodyOp() | ||||||||||||
188 | are the same. | ||||||||||||
189 | */ | ||||||||||||
190 | reference_type * SAL_CALL get() const | ||||||||||||
191 | { | ||||||||||||
192 | return m_pBody; | ||||||||||||
193 | } | ||||||||||||
194 | |||||||||||||
195 | |||||||||||||
196 | /** Probably most common used: handle->someBodyOp(). | ||||||||||||
197 | */ | ||||||||||||
198 | reference_type * SAL_CALL operator->() const | ||||||||||||
199 | { | ||||||||||||
200 | assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail ("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx" , 200, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
201 | return m_pBody; | ||||||||||||
202 | } | ||||||||||||
203 | |||||||||||||
204 | |||||||||||||
205 | /** Allows (*handle).someBodyOp(). | ||||||||||||
206 | */ | ||||||||||||
207 | reference_type & SAL_CALL operator*() const | ||||||||||||
208 | { | ||||||||||||
209 | assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail ("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx" , 209, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
210 | return *m_pBody; | ||||||||||||
211 | } | ||||||||||||
212 | |||||||||||||
213 | |||||||||||||
214 | /** Returns True if the handle does point to a valid body. | ||||||||||||
215 | */ | ||||||||||||
216 | bool SAL_CALL is() const | ||||||||||||
217 | { | ||||||||||||
218 | return (m_pBody != NULL__null); | ||||||||||||
219 | } | ||||||||||||
220 | |||||||||||||
221 | #if defined LIBO_INTERNAL_ONLY1 | ||||||||||||
222 | /** Returns True if the handle does point to a valid body. | ||||||||||||
223 | */ | ||||||||||||
224 | explicit operator bool() const | ||||||||||||
225 | { | ||||||||||||
226 | return is(); | ||||||||||||
227 | } | ||||||||||||
228 | #endif | ||||||||||||
229 | |||||||||||||
230 | /** Returns True if this points to pBody. | ||||||||||||
231 | */ | ||||||||||||
232 | bool SAL_CALL operator== (const reference_type * pBody) const | ||||||||||||
233 | { | ||||||||||||
234 | return (m_pBody == pBody); | ||||||||||||
235 | } | ||||||||||||
236 | |||||||||||||
237 | |||||||||||||
238 | /** Returns True if handle points to the same body. | ||||||||||||
239 | */ | ||||||||||||
240 | bool | ||||||||||||
241 | SAL_CALL operator== (const Reference<reference_type> & handle) const | ||||||||||||
242 | { | ||||||||||||
243 | return (m_pBody == handle.m_pBody); | ||||||||||||
244 | } | ||||||||||||
245 | |||||||||||||
246 | |||||||||||||
247 | /** Needed to place References into STL collection. | ||||||||||||
248 | */ | ||||||||||||
249 | bool | ||||||||||||
250 | SAL_CALL operator!= (const Reference<reference_type> & handle) const | ||||||||||||
251 | { | ||||||||||||
252 | return (m_pBody != handle.m_pBody); | ||||||||||||
253 | } | ||||||||||||
254 | |||||||||||||
255 | |||||||||||||
256 | /** Needed to place References into STL collection. | ||||||||||||
257 | */ | ||||||||||||
258 | bool | ||||||||||||
259 | SAL_CALL operator< (const Reference<reference_type> & handle) const | ||||||||||||
260 | { | ||||||||||||
261 | return (m_pBody < handle.m_pBody); | ||||||||||||
262 | } | ||||||||||||
263 | |||||||||||||
264 | |||||||||||||
265 | /** Needed to place References into STL collection. | ||||||||||||
266 | */ | ||||||||||||
267 | bool | ||||||||||||
268 | SAL_CALL operator> (const Reference<reference_type> & handle) const | ||||||||||||
269 | { | ||||||||||||
270 | return (m_pBody > handle.m_pBody); | ||||||||||||
271 | } | ||||||||||||
272 | }; | ||||||||||||
273 | |||||||||||||
274 | } // namespace rtl | ||||||||||||
275 | |||||||||||||
276 | #if defined LIBO_INTERNAL_ONLY1 | ||||||||||||
277 | namespace std | ||||||||||||
278 | { | ||||||||||||
279 | |||||||||||||
280 | /// @cond INTERNAL | ||||||||||||
281 | /** | ||||||||||||
282 | Make rtl::Reference hashable by default for use in STL containers. | ||||||||||||
283 | |||||||||||||
284 | @since LibreOffice 6.3 | ||||||||||||
285 | */ | ||||||||||||
286 | template<typename T> | ||||||||||||
287 | struct hash<::rtl::Reference<T>> | ||||||||||||
288 | { | ||||||||||||
289 | std::size_t operator()(::rtl::Reference<T> const & s) const | ||||||||||||
290 | { return std::size_t(s.get()); } | ||||||||||||
291 | }; | ||||||||||||
292 | /// @endcond | ||||||||||||
293 | |||||||||||||
294 | } | ||||||||||||
295 | |||||||||||||
296 | #endif | ||||||||||||
297 | |||||||||||||
298 | #endif /* ! INCLUDED_RTL_REF_HXX */ | ||||||||||||
299 | |||||||||||||
300 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_VCL_Reference_HXX |
20 | #define INCLUDED_VCL_Reference_HXX |
21 | |
22 | #include <vcl/dllapi.h> |
23 | #include <osl/interlck.h> |
24 | |
25 | class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase |
26 | { |
27 | mutable oslInterlockedCount mnRefCnt; |
28 | |
29 | template<typename T> friend class VclPtr; |
30 | |
31 | public: |
32 | void acquire() const |
33 | { |
34 | osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1); |
35 | } |
36 | |
37 | void release() const |
38 | { |
39 | if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0) |
40 | delete this; |
41 | } |
42 | #ifdef DBG_UTIL |
43 | #ifndef _WIN32 |
44 | sal_Int32 getRefCount() const { return mnRefCnt; } |
45 | #endif |
46 | #endif |
47 | |
48 | |
49 | private: |
50 | VclReferenceBase(const VclReferenceBase&) = delete; |
51 | VclReferenceBase& operator=(const VclReferenceBase&) = delete; |
52 | |
53 | bool mbDisposed : 1; |
54 | |
55 | protected: |
56 | VclReferenceBase(); |
57 | protected: |
58 | virtual ~VclReferenceBase(); |
59 | |
60 | protected: |
61 | virtual void dispose(); |
62 | |
63 | public: |
64 | void disposeOnce(); |
65 | bool isDisposed() const { return mbDisposed; } |
66 | |
67 | }; |
68 | #endif |