1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <config_feature_desktop.h>
24 #include <UIKit/UIKit.h>
28 #include <com/sun/star/frame/theGlobalEventBroadcaster.hpp>
29 #include <comphelper/lok.hxx>
30 #include <comphelper/scopeguard.hxx>
31 #include <comphelper/processfactory.hxx>
32 #include <officecfg/Office/Common.hxx>
33 #include <osl/diagnose.h>
39 #include <rtl/bootstrap.hxx>
40 #include <rtl/strbuf.hxx>
41 #include <sal/log.hxx>
43 #include <vcl/abstdlg.hxx>
44 #include <vcl/accel.hxx>
45 #include <vcl/builder.hxx>
46 #include <vcl/layout.hxx>
47 #include <vcl/svapp.hxx>
48 #include <vcl/event.hxx>
49 #include <vcl/waitobj.hxx>
50 #include <vcl/wrkwin.hxx>
51 #include <vcl/toolkit/button.hxx>
52 #include <vcl/mnemonic.hxx>
53 #include <vcl/toolkit/dialog.hxx>
54 #include <vcl/dialoghelper.hxx>
55 #include <vcl/settings.hxx>
56 #include <vcl/virdev.hxx>
57 #include <vcl/weld.hxx>
58 #include <vcl/uitest/uiobject.hxx>
59 #include <vcl/uitest/logger.hxx>
60 #include <vcl/IDialogRenderable.hxx>
61 #include <messagedialog.hxx>
62 #include <salframe.hxx>
67 static OString
ImplGetDialogText( Dialog
* pDialog
)
69 OStringBuffer
aErrorStr(OUStringToOString(
70 pDialog
->GetText(), RTL_TEXTENCODING_UTF8
));
73 if (MessageDialog
* pMessDialog
= dynamic_cast<MessageDialog
*>(pDialog
))
75 sMessage
= pMessDialog
->get_primary_text();
78 if (!sMessage
.isEmpty())
80 aErrorStr
.append(", ");
81 aErrorStr
.append(OUStringToOString(
82 sMessage
, RTL_TEXTENCODING_UTF8
));
84 return aErrorStr
.makeStringAndClear();
87 static bool ImplIsMnemonicCtrl( vcl::Window
* pWindow
)
89 if( ! pWindow
->GetSettings().GetStyleSettings().GetAutoMnemonic() )
92 if ( (pWindow
->GetType() == WindowType::RADIOBUTTON
) ||
93 (pWindow
->GetType() == WindowType::CHECKBOX
) ||
94 (pWindow
->GetType() == WindowType::TRISTATEBOX
) ||
95 (pWindow
->GetType() == WindowType::PUSHBUTTON
) )
98 if ( pWindow
->GetType() == WindowType::FIXEDTEXT
)
100 FixedText
*pText
= static_cast<FixedText
*>(pWindow
);
101 if (pText
->get_mnemonic_widget())
103 //This is the legacy pre-layout logic which we retain
104 //until we can be sure we can remove it
105 if (pWindow
->GetStyle() & WB_NOLABEL
)
107 vcl::Window
* pNextWindow
= pWindow
->GetWindow( GetWindowType::Next
);
110 pNextWindow
= pNextWindow
->GetWindow( GetWindowType::Client
);
111 return !(!(pNextWindow
->GetStyle() & WB_TABSTOP
) ||
112 (pNextWindow
->GetType() == WindowType::FIXEDTEXT
) ||
113 (pNextWindow
->GetType() == WindowType::GROUPBOX
) ||
114 (pNextWindow
->GetType() == WindowType::RADIOBUTTON
) ||
115 (pNextWindow
->GetType() == WindowType::CHECKBOX
) ||
116 (pNextWindow
->GetType() == WindowType::TRISTATEBOX
) ||
117 (pNextWindow
->GetType() == WindowType::PUSHBUTTON
));
123 // Called by native error dialog popup implementations
124 void ImplHideSplash()
126 ImplSVData
* pSVData
= ImplGetSVData();
127 if( pSVData
->mpIntroWindow
)
128 pSVData
->mpIntroWindow
->Hide();
131 vcl::Window
* nextLogicalChildOfParent(const vcl::Window
*pTopLevel
, const vcl::Window
*pChild
)
133 const vcl::Window
*pLastChild
= pChild
;
135 if (pChild
->GetType() == WindowType::SCROLLWINDOW
)
136 pChild
= static_cast<const VclScrolledWindow
*>(pChild
)->get_child();
137 else if (isContainerWindow(*pChild
))
138 pChild
= pChild
->GetWindow(GetWindowType::FirstChild
);
140 pChild
= pChild
->GetWindow(GetWindowType::Next
);
144 vcl::Window
*pParent
= pLastChild
->GetParent();
147 if (pParent
== pTopLevel
)
149 pLastChild
= pParent
;
150 pChild
= pParent
->GetWindow(GetWindowType::Next
);
153 if (isContainerWindow(*pChild
))
154 pChild
= nextLogicalChildOfParent(pTopLevel
, pChild
);
156 return const_cast<vcl::Window
*>(pChild
);
159 vcl::Window
* prevLogicalChildOfParent(const vcl::Window
*pTopLevel
, const vcl::Window
*pChild
)
161 const vcl::Window
*pLastChild
= pChild
;
163 if (pChild
->GetType() == WindowType::SCROLLWINDOW
)
164 pChild
= static_cast<const VclScrolledWindow
*>(pChild
)->get_child();
165 else if (isContainerWindow(*pChild
))
166 pChild
= pChild
->GetWindow(GetWindowType::LastChild
);
168 pChild
= pChild
->GetWindow(GetWindowType::Prev
);
172 vcl::Window
*pParent
= pLastChild
->GetParent();
175 if (pParent
== pTopLevel
)
177 pLastChild
= pParent
;
178 pChild
= pParent
->GetWindow(GetWindowType::Prev
);
181 if (isContainerWindow(*pChild
))
182 pChild
= prevLogicalChildOfParent(pTopLevel
, pChild
);
184 return const_cast<vcl::Window
*>(pChild
);
187 vcl::Window
* firstLogicalChildOfParent(const vcl::Window
*pTopLevel
)
189 const vcl::Window
*pChild
= pTopLevel
->GetWindow(GetWindowType::FirstChild
);
190 if (pChild
&& isContainerWindow(*pChild
))
191 pChild
= nextLogicalChildOfParent(pTopLevel
, pChild
);
192 return const_cast<vcl::Window
*>(pChild
);
195 vcl::Window
* lastLogicalChildOfParent(const vcl::Window
*pTopLevel
)
197 const vcl::Window
*pChild
= pTopLevel
->GetWindow(GetWindowType::LastChild
);
198 if (pChild
&& isContainerWindow(*pChild
))
199 pChild
= prevLogicalChildOfParent(pTopLevel
, pChild
);
200 return const_cast<vcl::Window
*>(pChild
);
203 void Accelerator::GenerateAutoMnemonicsOnHierarchy(const vcl::Window
* pWindow
)
205 MnemonicGenerator aMnemonicGenerator
;
206 vcl::Window
* pGetChild
;
209 // register the assigned mnemonics
210 pGetChild
= pWindow
->GetWindow( GetWindowType::FirstChild
);
213 pChild
= pGetChild
->ImplGetWindow();
214 aMnemonicGenerator
.RegisterMnemonic( pChild
->GetText() );
215 pGetChild
= nextLogicalChildOfParent(pWindow
, pGetChild
);
218 // take the Controls of the dialog into account for TabPages
219 if ( pWindow
->GetType() == WindowType::TABPAGE
)
221 vcl::Window
* pParent
= pWindow
->GetParent();
222 if (pParent
&& pParent
->GetType() == WindowType::TABCONTROL
)
223 pParent
= pParent
->GetParent();
225 if (pParent
&& (pParent
->GetStyle() & (WB_DIALOGCONTROL
| WB_NODIALOGCONTROL
)) == WB_DIALOGCONTROL
)
227 pGetChild
= pParent
->GetWindow( GetWindowType::FirstChild
);
230 pChild
= pGetChild
->ImplGetWindow();
231 aMnemonicGenerator
.RegisterMnemonic( pChild
->GetText() );
232 pGetChild
= nextLogicalChildOfParent(pWindow
, pGetChild
);
237 // assign mnemonics to Controls which have none
238 pGetChild
= pWindow
->GetWindow( GetWindowType::FirstChild
);
241 pChild
= pGetChild
->ImplGetWindow();
242 if ( ImplIsMnemonicCtrl( pChild
) )
244 OUString aText
= pChild
->GetText();
245 OUString aNewText
= aMnemonicGenerator
.CreateMnemonic( aText
);
246 if ( aText
!= aNewText
)
247 pChild
->SetText( aNewText
);
250 pGetChild
= nextLogicalChildOfParent(pWindow
, pGetChild
);
254 static VclButtonBox
* getActionArea(Dialog
const *pDialog
)
256 VclButtonBox
*pButtonBox
= nullptr;
257 if (pDialog
->isLayoutEnabled())
259 vcl::Window
*pBox
= pDialog
->GetWindow(GetWindowType::FirstChild
);
260 vcl::Window
*pChild
= pBox
->GetWindow(GetWindowType::LastChild
);
263 pButtonBox
= dynamic_cast<VclButtonBox
*>(pChild
);
266 pChild
= pChild
->GetWindow(GetWindowType::Prev
);
272 static vcl::Window
* getActionAreaButtonList(Dialog
const *pDialog
)
274 VclButtonBox
* pButtonBox
= getActionArea(pDialog
);
276 return pButtonBox
->GetWindow(GetWindowType::FirstChild
);
277 return pDialog
->GetWindow(GetWindowType::FirstChild
);
280 static PushButton
* ImplGetDefaultButton( Dialog
const * pDialog
)
282 vcl::Window
* pChild
= getActionAreaButtonList(pDialog
);
285 if ( pChild
->ImplIsPushButton() )
287 PushButton
* pPushButton
= static_cast<PushButton
*>(pChild
);
288 if ( pPushButton
->ImplIsDefButton() )
292 pChild
= pChild
->GetWindow( GetWindowType::Next
);
298 static PushButton
* ImplGetOKButton( Dialog
const * pDialog
)
300 vcl::Window
* pChild
= getActionAreaButtonList(pDialog
);
303 if ( pChild
->GetType() == WindowType::OKBUTTON
)
304 return static_cast<PushButton
*>(pChild
);
306 pChild
= pChild
->GetWindow( GetWindowType::Next
);
312 static PushButton
* ImplGetCancelButton( Dialog
const * pDialog
)
314 vcl::Window
* pChild
= getActionAreaButtonList(pDialog
);
318 if ( pChild
->GetType() == WindowType::CANCELBUTTON
)
319 return static_cast<PushButton
*>(pChild
);
321 pChild
= pChild
->GetWindow( GetWindowType::Next
);
327 static void ImplMouseAutoPos( Dialog
* pDialog
)
329 MouseSettingsOptions nMouseOptions
= pDialog
->GetSettings().GetMouseSettings().GetOptions();
330 if ( nMouseOptions
& MouseSettingsOptions::AutoCenterPos
)
332 Size aSize
= pDialog
->GetOutputSizePixel();
333 pDialog
->SetPointerPosPixel( Point( aSize
.Width()/2, aSize
.Height()/2 ) );
335 else if ( nMouseOptions
& MouseSettingsOptions::AutoDefBtnPos
)
337 vcl::Window
* pWindow
= ImplGetDefaultButton( pDialog
);
339 pWindow
= ImplGetOKButton( pDialog
);
341 pWindow
= ImplGetCancelButton( pDialog
);
344 Size aSize
= pWindow
->GetOutputSizePixel();
345 pWindow
->SetPointerPosPixel( Point( aSize
.Width()/2, aSize
.Height()/2 ) );
351 std::vector
<VclPtr
<PushButton
>> maOwnedButtons
;
352 std::map
<VclPtr
<vcl::Window
>, short> maResponses
;
353 tools::Long mnResult
;
355 VclAbstractDialog::AsyncContext maEndCtx
;
356 Link
<const CommandEvent
&, bool> m_aPopupMenuHdl
;
357 Link
<void*, vcl::ILibreOfficeKitNotifier
*> m_aInstallLOKNotifierHdl
;
359 DialogImpl() : mnResult( -1 ), mbStartedModal( false ) {}
362 short get_response(vcl::Window
*pWindow
) const
364 auto aFind
= maResponses
.find(pWindow
);
365 if (aFind
!= maResponses
.end())
366 return aFind
->second
;
373 for (VclPtr
<PushButton
> & pOwnedButton
: maOwnedButtons
)
374 pOwnedButton
.disposeAndClear();
378 void Dialog::disposeOwnedButtons()
380 for (VclPtr
<PushButton
> & pOwnedButton
: mpDialogImpl
->maOwnedButtons
)
381 pOwnedButton
.disposeAndClear();
384 void Dialog::ImplInitDialogData()
386 mpWindowImpl
->mbDialog
= true;
388 mbInSyncExecute
= false;
391 mpContentArea
.clear();
392 mpActionArea
.clear();
393 mnMousePositioned
= 0;
394 mpDialogImpl
.reset(new DialogImpl
);
397 vcl::Window
* Dialog::GetDefaultParent(WinBits nStyle
)
399 vcl::Window
* pParent
= Application::GetDefDialogParent();
400 if (!pParent
&& !(nStyle
& WB_SYSTEMWINDOW
))
401 pParent
= ImplGetSVData()->maFrameData
.mpAppWin
;
403 // If Parent is disabled, then we search for a modal dialog
405 if (pParent
&& (!pParent
->IsInputEnabled() || pParent
->IsInModalMode()))
407 ImplSVData
* pSVData
= ImplGetSVData();
408 auto& rExecuteDialogs
= pSVData
->mpWinData
->mpExecuteDialogs
;
409 auto it
= std::find_if(rExecuteDialogs
.rbegin(), rExecuteDialogs
.rend(),
410 [&pParent
](VclPtr
<Dialog
>& rDialogPtr
) {
411 return pParent
->ImplGetFirstOverlapWindow()->IsWindowOrChild(rDialogPtr
, true) &&
412 rDialogPtr
->IsReallyVisible() && rDialogPtr
->IsEnabled() &&
413 rDialogPtr
->IsInputEnabled() && !rDialogPtr
->IsInModalMode(); });
414 if (it
!= rExecuteDialogs
.rend())
421 VclPtr
<vcl::Window
> Dialog::AddBorderWindow(vcl::Window
* pParent
, WinBits nStyle
)
423 VclPtrInstance
<ImplBorderWindow
> pBorderWin( pParent
, nStyle
, BorderWindowStyle::Frame
);
424 ImplInit( pBorderWin
, nStyle
& ~WB_BORDER
, nullptr );
425 pBorderWin
->mpWindowImpl
->mpClientWindow
= this;
426 pBorderWin
->GetBorder( mpWindowImpl
->mnLeftBorder
, mpWindowImpl
->mnTopBorder
, mpWindowImpl
->mnRightBorder
, mpWindowImpl
->mnBottomBorder
);
427 mpWindowImpl
->mpBorderWindow
= pBorderWin
;
428 mpWindowImpl
->mpRealParent
= pParent
;
433 void Dialog::ImplInitDialog( vcl::Window
* pParent
, WinBits nStyle
, InitFlag eFlag
)
435 SystemWindowFlags nSysWinMode
= Application::GetSystemWindowMode();
437 if ( !(nStyle
& WB_NODIALOGCONTROL
) )
438 nStyle
|= WB_DIALOGCONTROL
;
439 nStyle
|= WB_ROLLABLE
;
441 // Now, all Dialogs are per default system windows !!!
442 nStyle
|= WB_SYSTEMWINDOW
;
444 if (InitFlag::NoParent
== eFlag
)
448 else if (!pParent
) // parent is NULL: get the default Dialog parent
450 pParent
= Dialog::GetDefaultParent(nStyle
);
453 if ( !pParent
|| (nStyle
& WB_SYSTEMWINDOW
) ||
454 (pParent
->mpWindowImpl
->mpFrameData
->mbNeedSysWindow
&& !(nSysWinMode
& SystemWindowFlags::NOAUTOMODE
)) ||
455 (nSysWinMode
& SystemWindowFlags::DIALOG
) )
457 // create window with a small border ?
458 if ((nStyle
& WB_ALLOWMENUBAR
) || ((nStyle
& (WB_BORDER
| WB_NOBORDER
| WB_MOVEABLE
| WB_SIZEABLE
| WB_CLOSEABLE
)) == WB_BORDER
))
460 AddBorderWindow(pParent
, nStyle
);
464 mpWindowImpl
->mbFrame
= true;
465 mpWindowImpl
->mbOverlapWin
= true;
466 ImplInit( pParent
, (nStyle
& (WB_MOVEABLE
| WB_SIZEABLE
| WB_ROLLABLE
| WB_STANDALONE
)) | WB_CLOSEABLE
, nullptr );
467 // Now set all style bits
468 mpWindowImpl
->mnStyle
= nStyle
;
473 VclPtrInstance
<ImplBorderWindow
> pBorderWin( pParent
, nStyle
, BorderWindowStyle::Overlap
);
474 ImplInit( pBorderWin
, nStyle
& ~WB_BORDER
, nullptr );
475 pBorderWin
->mpWindowImpl
->mpClientWindow
= this;
476 pBorderWin
->GetBorder( mpWindowImpl
->mnLeftBorder
, mpWindowImpl
->mnTopBorder
, mpWindowImpl
->mnRightBorder
, mpWindowImpl
->mnBottomBorder
);
477 mpWindowImpl
->mpBorderWindow
= pBorderWin
;
478 mpWindowImpl
->mpRealParent
= pParent
;
481 SetActivateMode( ActivateModeFlags::GrabFocus
);
486 void Dialog::ApplySettings(vcl::RenderContext
& rRenderContext
)
488 if (IsControlBackground())
491 SetBackground(GetControlBackground());
493 else if (rRenderContext
.IsNativeControlSupported(ControlType::WindowBackground
, ControlPart::BackgroundDialog
))
496 mpWindowImpl
->mnNativeBackground
= ControlPart::BackgroundDialog
;
497 EnableChildTransparentMode();
501 // fallback to settings color
502 rRenderContext
.SetBackground(GetSettings().GetStyleSettings().GetDialogColor());
506 void Dialog::ImplInitSettings()
509 if (IsControlBackground())
510 SetBackground(GetControlBackground());
512 else if( IsNativeControlSupported(ControlType::WindowBackground
, ControlPart::BackgroundDialog
))
514 mpWindowImpl
->mnNativeBackground
= ControlPart::BackgroundDialog
;
515 EnableChildTransparentMode();
517 // fallback to settings color
519 SetBackground(GetSettings().GetStyleSettings().GetDialogColor());
522 void Dialog::ImplLOKNotifier(vcl::Window
* pParent
)
524 if (comphelper::LibreOfficeKit::isActive() && pParent
)
526 if (VclPtr
<vcl::Window
> pWin
= pParent
->GetParentWithLOKNotifier())
528 SetLOKNotifier(pWin
->GetLOKNotifier());
533 Dialog::Dialog( WindowType nType
)
534 : SystemWindow( nType
)
535 , mnInitFlag(InitFlag::Default
)
537 ImplInitDialogData();
540 void VclBuilderContainer::disposeBuilder()
543 m_pUIBuilder
->disposeBuilder();
546 OUString
AllSettings::GetUIRootDir()
548 OUString
sShareLayer("$BRAND_BASE_DIR/$BRAND_SHARE_SUBDIR/config/soffice.cfg/");
549 rtl::Bootstrap::expandMacros(sShareLayer
);
553 //we can't change sizeable after the fact, so need to defer until we know and then
554 //do the init. Find the real parent stashed in mpDialogParent.
555 void Dialog::doDeferredInit(WinBits nBits
)
557 VclPtr
<vcl::Window
> pParent
= mpDialogParent
;
558 mpDialogParent
= nullptr;
559 ImplInitDialog(pParent
, nBits
| WB_BORDER
, mnInitFlag
);
560 mbIsDeferredInit
= false;
563 Dialog::Dialog(vcl::Window
* pParent
, const OUString
& rID
, const OUString
& rUIXMLDescription
)
564 : SystemWindow(WindowType::DIALOG
)
565 , mnInitFlag(InitFlag::Default
)
567 ImplLOKNotifier(pParent
);
568 ImplInitDialogData();
569 loadUI(pParent
, OUStringToOString(rID
, RTL_TEXTENCODING_UTF8
), rUIXMLDescription
);
572 Dialog::Dialog(vcl::Window
* pParent
, WinBits nStyle
, InitFlag eFlag
)
573 : SystemWindow(WindowType::DIALOG
)
576 ImplLOKNotifier(pParent
);
577 ImplInitDialogData();
578 ImplInitDialog( pParent
, nStyle
, eFlag
);
581 void Dialog::set_action_area(VclButtonBox
* pBox
)
583 mpActionArea
.set(pBox
);
586 const DialogStyle
& rDialogStyle
=
587 GetSettings().GetStyleSettings().GetDialogStyle();
588 pBox
->set_border_width(rDialogStyle
.action_area_border
);
592 void Dialog::set_content_area(VclBox
* pBox
)
594 mpContentArea
.set(pBox
);
597 void Dialog::settingOptimalLayoutSize(Window
*pBox
)
599 const DialogStyle
& rDialogStyle
=
600 GetSettings().GetStyleSettings().GetDialogStyle();
601 VclBox
* pBox2
= static_cast<VclBox
*>(pBox
);
602 pBox2
->set_border_width(rDialogStyle
.content_area_border
);
610 void Dialog::dispose()
612 mpDialogImpl
.reset();
614 mpActionArea
.clear();
615 mpContentArea
.clear();
617 css::uno::Reference
< css::uno::XComponentContext
> xContext(
618 comphelper::getProcessComponentContext() );
619 css::uno::Reference
<css::frame::XGlobalEventBroadcaster
> xEventBroadcaster(css::frame::theGlobalEventBroadcaster::get(xContext
), css::uno::UNO_SET_THROW
);
620 css::document::DocumentEvent aObject
;
621 aObject
.EventName
= "DialogClosed";
622 xEventBroadcaster
->documentEventOccured(aObject
);
623 UITestLogger::getInstance().log("Close Dialog");
625 if (comphelper::LibreOfficeKit::isActive())
627 if(const vcl::ILibreOfficeKitNotifier
* pNotifier
= GetLOKNotifier())
629 pNotifier
->notifyWindow(GetLOKWindowId(), "close");
630 ReleaseLOKNotifier();
634 SystemWindow::dispose();
637 IMPL_LINK_NOARG(Dialog
, ImplAsyncCloseHdl
, void*, void)
642 bool Dialog::EventNotify( NotifyEvent
& rNEvt
)
644 // first call the base class due to Tab control
645 bool bRet
= SystemWindow::EventNotify( rNEvt
);
648 if ( rNEvt
.GetType() == MouseNotifyEvent::KEYINPUT
)
650 const KeyEvent
* pKEvt
= rNEvt
.GetKeyEvent();
651 vcl::KeyCode aKeyCode
= pKEvt
->GetKeyCode();
652 sal_uInt16 nKeyCode
= aKeyCode
.GetCode();
654 if ( (nKeyCode
== KEY_ESCAPE
) &&
655 ((GetStyle() & WB_CLOSEABLE
) || ImplGetCancelButton( this ) || ImplGetOKButton( this )) )
657 // #i89505# for the benefit of slightly mentally challenged implementations
658 // like e.g. SfxModelessDialog which destroy themselves inside Close()
659 // post this Close asynchronous so we can leave our key handler before
661 PostUserEvent( LINK( this, Dialog
, ImplAsyncCloseHdl
), nullptr, true);
665 else if ( rNEvt
.GetType() == MouseNotifyEvent::GETFOCUS
)
667 // make sure the dialog is still modal
668 // changing focus between application frames may
669 // have re-enabled input for our parent
670 if( mbInExecute
&& mbModalMode
)
672 ImplSetModalInputMode( false );
673 ImplSetModalInputMode( true );
675 // #93022# def-button might have changed after show
676 if( !mnMousePositioned
)
678 mnMousePositioned
= 1;
679 ImplMouseAutoPos( this );
689 //What we really want here is something that gives the available width and
690 //height of a users screen, taking away the space taken up the OS
691 //taskbar, menus, etc.
692 Size
bestmaxFrameSizeForScreenSize(const Size
&rScreenSize
)
695 tools::Long w
= rScreenSize
.Width();
703 tools::Long h
= rScreenSize
.Height();
709 return Size(std::max
<tools::Long
>(w
, 640 - 15),
710 std::max
<tools::Long
>(h
, 480 - 50));
712 // Don't bother with ancient magic numbers of unclear relevance on non-desktop apps anyway. It
713 // seems that at least currently in the iOS app, this function is called just once per dialog,
714 // with a rScreenSize parameter of 1x1 (!). This would lead to always returning 625x430 which is
715 // a bit random and needlessly small on an iPad at least. We want something that closely will
716 // just fit on the display in either orientation.
718 // We ignore the rScreenSize as it will be the dummy 1x1 from iosinst.cxx (see "Totally wrong of course").
721 const int n
= std::min
<CGFloat
>([[UIScreen mainScreen
] bounds
].size
.width
, [[UIScreen mainScreen
] bounds
].size
.height
);
722 return Size(n
-10, n
-10);
726 void Dialog::SetPopupMenuHdl(const Link
<const CommandEvent
&, bool>& rLink
)
728 mpDialogImpl
->m_aPopupMenuHdl
= rLink
;
731 void Dialog::SetInstallLOKNotifierHdl(const Link
<void*, vcl::ILibreOfficeKitNotifier
*>& rLink
)
733 mpDialogImpl
->m_aInstallLOKNotifierHdl
= rLink
;
736 void Dialog::StateChanged( StateChangedType nType
)
738 if (nType
== StateChangedType::InitShow
)
742 const bool bKitActive
= comphelper::LibreOfficeKit::isActive();
745 std::vector
<vcl::LOKPayloadItem
> aItems
;
746 aItems
.emplace_back("type", "dialog");
747 aItems
.emplace_back("size", GetSizePixel().toString());
748 if (!GetText().isEmpty())
749 aItems
.emplace_back("title", GetText().toUtf8());
751 if (const vcl::ILibreOfficeKitNotifier
* pNotifier
= GetLOKNotifier())
753 pNotifier
->notifyWindow(GetLOKWindowId(), "created", aItems
);
754 pNotifier
->notifyWindow(GetLOKWindowId(), "created", aItems
);
758 vcl::ILibreOfficeKitNotifier
* pViewShell
= mpDialogImpl
->m_aInstallLOKNotifierHdl
.Call(nullptr);
761 SetLOKNotifier(pViewShell
);
762 pViewShell
->notifyWindow(GetLOKWindowId(), "created", aItems
);
767 if ( !HasChildPathFocus() || HasFocus() )
768 GrabFocusToFirstControl();
769 if ( !(GetStyle() & WB_CLOSEABLE
) )
771 if ( ImplGetCancelButton( this ) || ImplGetOKButton( this ) )
773 if ( ImplGetBorderWindow() )
774 static_cast<ImplBorderWindow
*>(ImplGetBorderWindow())->SetCloseButton();
778 ImplMouseAutoPos( this );
780 else if (nType
== StateChangedType::Text
)
782 if (const vcl::ILibreOfficeKitNotifier
* pNotifier
= GetLOKNotifier())
784 std::vector
<vcl::LOKPayloadItem
> aPayload
;
785 aPayload
.emplace_back("title", GetText().toUtf8());
786 pNotifier
->notifyWindow(GetLOKWindowId(), "title_changed", aPayload
);
790 SystemWindow::StateChanged( nType
);
792 if (nType
== StateChangedType::ControlBackground
)
798 if (!mbModalMode
&& nType
== StateChangedType::Visible
)
800 if (const vcl::ILibreOfficeKitNotifier
* pNotifier
= GetLOKNotifier())
802 std::vector
<vcl::LOKPayloadItem
> aPayload
;
803 aPayload
.emplace_back("title", GetText().toUtf8());
804 pNotifier
->notifyWindow(GetLOKWindowId(), IsVisible()? OUString("show"): OUString("hide"), aPayload
);
809 void Dialog::DataChanged( const DataChangedEvent
& rDCEvt
)
811 SystemWindow::DataChanged( rDCEvt
);
813 if ( (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) &&
814 (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
823 VclPtr
<vcl::Window
> xWindow
= this;
824 CallEventListeners( VclEventId::WindowClose
);
825 if ( xWindow
->IsDisposed() )
828 if ( mpWindowImpl
->mxWindowPeer
.is() && IsCreatedWithToolkit() && !IsInExecute() )
831 // If there's a cancel button with a custom handler, then always give it a chance to
832 // handle Dialog::Close
833 PushButton
* pCustomCancelButton
;
834 PushButton
* pCancelButton
= dynamic_cast<PushButton
*>(get_widget_for_response(RET_CANCEL
));
835 if (!mbInClose
&& pCancelButton
&& pCancelButton
->GetClickHdl().IsSet())
836 pCustomCancelButton
= pCancelButton
;
838 pCustomCancelButton
= nullptr;
842 if (pCustomCancelButton
)
844 pCustomCancelButton
->Click();
845 if (xWindow
->IsDisposed())
851 if ( !(GetStyle() & WB_CLOSEABLE
) )
854 PushButton
* pButton
= ImplGetCancelButton( this );
859 pButton
= ImplGetOKButton( this );
865 if ( xWindow
->IsDisposed() )
870 if (IsInExecute() || mpDialogImpl
->maEndCtx
.isSet())
879 return SystemWindow::Close();
883 bool Dialog::ImplStartExecute()
885 setDeferredProperties();
887 if (IsInExecute() || mpDialogImpl
->maEndCtx
.isSet())
890 SAL_WARN( "vcl", "Dialog::StartExecuteModal() is called in Dialog::StartExecuteModal(): "
891 << ImplGetDialogText(this) );
896 ImplSVData
* pSVData
= ImplGetSVData();
898 const bool bKitActive
= comphelper::LibreOfficeKit::isActive();
900 const bool bModal
= GetType() != WindowType::MODELESSDIALOG
;
904 if (bKitActive
&& !GetLOKNotifier())
905 SetLOKNotifier(mpDialogImpl
->m_aInstallLOKNotifierHdl
.Call(nullptr));
907 switch ( Application::GetDialogCancelMode() )
909 case DialogCancelMode::Off
:
911 case DialogCancelMode::Silent
:
912 if (bModal
&& GetLOKNotifier())
914 // check if there's already some dialog being ::Execute()d
915 const bool bDialogExecuting
= std::any_of(pSVData
->mpWinData
->mpExecuteDialogs
.begin(),
916 pSVData
->mpWinData
->mpExecuteDialogs
.end(),
917 [](const Dialog
* pDialog
) {
918 return pDialog
->IsInSyncExecute();
920 if (!(bDialogExecuting
&& IsInSyncExecute()))
923 SAL_WARN("lok.dialog", "Dialog \"" << ImplGetDialogText(this) << "\" is being synchronously executed over an existing synchronously executing dialog.");
928 "Dialog \"" << ImplGetDialogText(this)
929 << "\"cancelled in silent mode");
931 default: // default cannot happen
932 case DialogCancelMode::Fatal
:
937 vcl::Window
* pParent
= GetParent();
940 pParent
= pParent
->ImplGetFirstOverlapWindow();
941 SAL_WARN_IF( !pParent
->IsReallyVisible(), "vcl",
942 "Dialog::StartExecuteModal() - Parent not visible" );
943 SAL_WARN_IF( !pParent
->IsInputEnabled(), "vcl",
944 "Dialog::StartExecuteModal() - Parent input disabled, use another parent to ensure modality!" );
945 SAL_WARN_IF( pParent
->IsInModalMode(), "vcl",
946 "Dialog::StartExecuteModal() - Parent already modally disabled, use another parent to ensure modality!" );
950 // link all dialogs which are being executed
951 pSVData
->mpWinData
->mpExecuteDialogs
.push_back(this);
953 // stop capturing, in order to have control over the dialog
954 if (pSVData
->mpWinData
->mpTrackWin
)
955 pSVData
->mpWinData
->mpTrackWin
->EndTracking(TrackingEventFlags::Cancel
);
956 if (pSVData
->mpWinData
->mpCaptureWin
)
957 pSVData
->mpWinData
->mpCaptureWin
->ReleaseMouse();
962 // no real modality in LibreOfficeKit
963 if (!bKitActive
&& bModal
)
964 SetModalInputMode(true);
966 // FIXME: no layouting, workaround some clipping issues
967 ImplAdjustNWFSizes();
969 css::uno::Reference
< css::uno::XComponentContext
> xContext(
970 comphelper::getProcessComponentContext());
971 bool bForceFocusAndToFront(officecfg::Office::Common::View::NewDocumentHandling::ForceFocusAndToFront::get(xContext
));
972 ShowFlags showFlags
= bForceFocusAndToFront
? ShowFlags::ForegroundTask
: ShowFlags::NONE
;
973 Show(true, showFlags
);
976 pSVData
->maAppData
.mnModalMode
++;
978 css::uno::Reference
<css::frame::XGlobalEventBroadcaster
> xEventBroadcaster(
979 css::frame::theGlobalEventBroadcaster::get(xContext
), css::uno::UNO_SET_THROW
);
980 css::document::DocumentEvent aObject
;
981 aObject
.EventName
= "DialogExecute";
982 xEventBroadcaster
->documentEventOccured(aObject
);
984 UITestLogger::getInstance().log("Open Modal " + get_id());
986 UITestLogger::getInstance().log("Open Modeless " + get_id());
988 if (comphelper::LibreOfficeKit::isActive())
990 if (const vcl::ILibreOfficeKitNotifier
* pNotifier
= GetLOKNotifier())
992 // Dialog boxes don't get the Resize call and they
993 // can have invalid size at 'created' message above.
994 // If there is no difference, the client should detect it and ignore us,
995 // otherwise, this should make sure that the window has the correct size.
996 std::vector
<vcl::LOKPayloadItem
> aItems
;
997 aItems
.emplace_back("size", GetSizePixel().toString());
998 pNotifier
->notifyWindow(GetLOKWindowId(), "size_changed", aItems
);
1005 void Dialog::ImplEndExecuteModal()
1007 ImplSVData
* pSVData
= ImplGetSVData();
1008 pSVData
->maAppData
.mnModalMode
--;
1011 short Dialog::Execute()
1013 // Once the Android app is based on same idea as the iOS one currently
1014 // being developed, no conditional should be needed here. Until then,
1016 #if HAVE_FEATURE_DESKTOP || defined IOS
1017 VclPtr
<vcl::Window
> xWindow
= this;
1019 mbInSyncExecute
= true;
1020 comphelper::ScopeGuard
aGuard([&]() {
1021 mbInSyncExecute
= false;
1024 if ( !ImplStartExecute() )
1027 // Yield util EndDialog is called or dialog gets destroyed
1028 // (the latter should not happen, but better safe than sorry
1029 while ( !xWindow
->IsDisposed() && mbInExecute
)
1030 Application::Yield();
1032 ImplEndExecuteModal();
1034 assert (!mpDialogParent
|| !mpDialogParent
->IsDisposed());
1036 if ( !xWindow
->IsDisposed() )
1040 OSL_FAIL( "Dialog::Execute() - Dialog destroyed in Execute()" );
1043 tools::Long nRet
= mpDialogImpl
->mnResult
;
1044 mpDialogImpl
->mnResult
= -1;
1046 return static_cast<short>(nRet
);
1054 bool Dialog::StartExecuteAsync( VclAbstractDialog::AsyncContext
&rCtx
)
1056 const bool bModal
= GetType() != WindowType::MODELESSDIALOG
;
1057 if (!ImplStartExecute())
1059 rCtx
.mxOwner
.disposeAndClear();
1060 rCtx
.mxOwnerDialogController
.reset();
1061 rCtx
.mxOwnerSelf
.reset();
1065 mpDialogImpl
->maEndCtx
= rCtx
;
1066 mpDialogImpl
->mbStartedModal
= bModal
;
1071 void Dialog::RemoveFromDlgList()
1073 ImplSVData
* pSVData
= ImplGetSVData();
1074 auto& rExecuteDialogs
= pSVData
->mpWinData
->mpExecuteDialogs
;
1076 // remove dialog from the list of dialogs which are being executed
1077 rExecuteDialogs
.erase(std::remove_if(rExecuteDialogs
.begin(), rExecuteDialogs
.end(), [this](VclPtr
<Dialog
>& dialog
){ return dialog
.get() == this; }), rExecuteDialogs
.end());
1080 void Dialog::EndDialog( tools::Long nResult
)
1082 if (!mbInExecute
|| IsDisposed())
1085 const bool bModal
= GetType() != WindowType::MODELESSDIALOG
;
1089 if (comphelper::LibreOfficeKit::isActive())
1091 if(const vcl::ILibreOfficeKitNotifier
* pNotifier
= GetLOKNotifier())
1093 pNotifier
->notifyWindow(GetLOKWindowId(), "close");
1094 ReleaseLOKNotifier();
1100 SetModalInputMode(false);
1102 RemoveFromDlgList();
1104 // set focus to previous modal dialog if it is modal for
1105 // the same frame parent (or NULL)
1106 ImplSVData
* pSVData
= ImplGetSVData();
1107 if (!pSVData
->mpWinData
->mpExecuteDialogs
.empty())
1109 VclPtr
<Dialog
> pPrevious
= pSVData
->mpWinData
->mpExecuteDialogs
.back();
1111 vcl::Window
* pFrameParent
= ImplGetFrameWindow()->ImplGetParent();
1112 vcl::Window
* pPrevFrameParent
= pPrevious
->ImplGetFrameWindow()? pPrevious
->ImplGetFrameWindow()->ImplGetParent(): nullptr;
1113 if( ( !pFrameParent
&& !pPrevFrameParent
) ||
1114 ( pFrameParent
&& pPrevFrameParent
&& pFrameParent
->ImplGetFrame() == pPrevFrameParent
->ImplGetFrame() )
1117 pPrevious
->GrabFocus();
1122 mpDialogImpl
->mnResult
= nResult
;
1124 if ( mpDialogImpl
->mbStartedModal
)
1125 ImplEndExecuteModal();
1127 if ( mpDialogImpl
&& mpDialogImpl
->maEndCtx
.isSet() )
1129 auto fn
= std::move(mpDialogImpl
->maEndCtx
.maEndDialogFn
);
1130 // std::move leaves maEndDialogFn in a valid state with unspecified
1131 // value. For the SwSyncBtnDlg case gcc and msvc left maEndDialogFn
1132 // unset, but clang left maEndDialogFn at its original value, keeping
1133 // an extra reference to the DialogController in its lambda giving
1134 // an inconsistent lifecycle for the dialog. Force it to be unset.
1135 mpDialogImpl
->maEndCtx
.maEndDialogFn
= nullptr;
1139 if ( mpDialogImpl
&& mpDialogImpl
->mbStartedModal
)
1141 mpDialogImpl
->mbStartedModal
= false;
1142 mpDialogImpl
->mnResult
= -1;
1144 mbInExecute
= false;
1148 // Destroy ourselves (if we have a context with VclPtr owner)
1149 std::shared_ptr
<weld::DialogController
> xOwnerDialogController
= std::move(mpDialogImpl
->maEndCtx
.mxOwnerDialogController
);
1150 std::shared_ptr
<weld::Dialog
> xOwnerSelf
= std::move(mpDialogImpl
->maEndCtx
.mxOwnerSelf
);
1151 mpDialogImpl
->maEndCtx
.mxOwner
.disposeAndClear();
1152 xOwnerDialogController
.reset();
1159 void EndAllDialogs( vcl::Window
const * pParent
)
1161 ImplSVData
* pSVData
= ImplGetSVData();
1162 auto& rExecuteDialogs
= pSVData
->mpWinData
->mpExecuteDialogs
;
1164 for (auto it
= rExecuteDialogs
.rbegin(); it
!= rExecuteDialogs
.rend(); ++it
)
1166 if (!pParent
|| pParent
->IsWindowOrChild(*it
, true))
1169 (*it
)->PostUserEvent(Link
<void*, void>());
1174 void EnableDialogInput(vcl::Window
* pWindow
)
1176 if (Dialog
* pDialog
= dynamic_cast<Dialog
*>(pWindow
))
1178 pDialog
->EnableInput();
1182 bool CloseDialog(vcl::Window
* pWindow
)
1184 if (Dialog
* pDialog
= dynamic_cast<Dialog
*>(pWindow
))
1193 void Dialog::SetModalInputMode( bool bModal
)
1195 if ( bModal
== mbModalMode
)
1198 ImplGetFrame()->SetModal(bModal
);
1202 SalFrame
* pFrame
= GetParent()->ImplGetFrame();
1203 pFrame
->NotifyModalHierarchy(bModal
);
1206 ImplSetModalInputMode(bModal
);
1209 void Dialog::ImplSetModalInputMode( bool bModal
)
1211 if ( bModal
== mbModalMode
)
1214 // previously Execute()'d dialog - the one below the top-most one
1215 VclPtr
<Dialog
> pPrevious
;
1216 ImplSVData
* pSVData
= ImplGetSVData();
1217 auto& rExecuteDialogs
= pSVData
->mpWinData
->mpExecuteDialogs
;
1218 if (rExecuteDialogs
.size() > 1)
1219 pPrevious
= rExecuteDialogs
[rExecuteDialogs
.size() - 2];
1221 mbModalMode
= bModal
;
1224 // Disable the prev Modal Dialog, because our dialog must close at first,
1225 // before the other dialog can be closed (because the other dialog
1226 // is on stack since our dialog returns)
1227 if (pPrevious
&& !pPrevious
->IsWindowOrChild(this, true))
1228 pPrevious
->EnableInput(false, this);
1230 // determine next overlap dialog parent
1231 vcl::Window
* pParent
= GetParent();
1234 // #103716# dialogs should always be modal to the whole frame window
1235 // #115933# disable the whole frame hierarchy, useful if our parent
1236 // is a modeless dialog
1237 mpDialogParent
= pParent
->mpWindowImpl
->mpFrameWindow
;
1238 mpDialogParent
->IncModalCount();
1243 if ( mpDialogParent
)
1245 // #115933# re-enable the whole frame hierarchy again (see above)
1246 // note that code in getfocus assures that we do not accidentally enable
1247 // windows that were disabled before
1248 mpDialogParent
->DecModalCount();
1251 // Enable the prev Modal Dialog
1252 if (pPrevious
&& !pPrevious
->IsWindowOrChild(this, true))
1254 pPrevious
->EnableInput(true, this);
1256 // ensure continued modality of prev dialog
1257 // do not change modality counter
1259 // #i119994# need find the last modal dialog before reactive it
1260 if (pPrevious
->IsModalInputMode() || !pPrevious
->IsWindowOrChild(this, true))
1262 pPrevious
->ImplSetModalInputMode(false);
1263 pPrevious
->ImplSetModalInputMode(true);
1269 void Dialog::GrabFocusToFirstControl()
1271 vcl::Window
* pFocusControl
;
1273 // find focus control, even if the dialog has focus
1275 pFocusControl
= nullptr;
1278 // prefer a child window which had focus before
1279 pFocusControl
= ImplGetFirstOverlapWindow()->mpWindowImpl
->mpLastFocusWindow
;
1280 // find the control out of the dialog control
1281 if ( pFocusControl
)
1282 pFocusControl
= ImplFindDlgCtrlWindow( pFocusControl
);
1284 // no control had the focus before or the control is not
1285 // part of the tab-control, now give focus to the
1286 // first control in the tab-control
1287 if ( !pFocusControl
||
1288 !(pFocusControl
->GetStyle() & WB_TABSTOP
) ||
1289 !isVisibleInLayout(pFocusControl
) ||
1290 !isEnabledInLayout(pFocusControl
) || !pFocusControl
->IsInputEnabled() )
1292 pFocusControl
= ImplGetDlgWindow( 0, GetDlgWindowType::First
);
1294 if ( pFocusControl
)
1295 pFocusControl
->ImplControlFocus( GetFocusFlags::Init
);
1298 void Dialog::GetDrawWindowBorder( sal_Int32
& rLeftBorder
, sal_Int32
& rTopBorder
, sal_Int32
& rRightBorder
, sal_Int32
& rBottomBorder
) const
1300 ScopedVclPtrInstance
<ImplBorderWindow
> aImplWin( static_cast<vcl::Window
*>(const_cast<Dialog
*>(this)), WB_BORDER
|WB_STDWORK
, BorderWindowStyle::Overlap
);
1301 aImplWin
->GetBorder( rLeftBorder
, rTopBorder
, rRightBorder
, rBottomBorder
);
1304 void Dialog::Draw( OutputDevice
* pDev
, const Point
& rPos
, DrawFlags
)
1306 Point aPos
= pDev
->LogicToPixel( rPos
);
1307 Size aSize
= GetSizePixel();
1309 Wallpaper aWallpaper
= GetBackground();
1310 if ( !aWallpaper
.IsBitmap() )
1315 pDev
->SetLineColor();
1317 if ( aWallpaper
.IsBitmap() )
1318 pDev
->DrawBitmapEx( aPos
, aSize
, aWallpaper
.GetBitmap() );
1321 pDev
->SetFillColor( aWallpaper
.GetColor() );
1322 pDev
->DrawRect( tools::Rectangle( aPos
, aSize
) );
1325 if (!( GetStyle() & WB_NOBORDER
))
1327 ScopedVclPtrInstance
< ImplBorderWindow
> aImplWin( this, WB_BORDER
|WB_STDWORK
, BorderWindowStyle::Overlap
);
1328 aImplWin
->SetText( GetText() );
1329 aImplWin
->setPosSizePixel( aPos
.X(), aPos
.Y(), aSize
.Width(), aSize
.Height() );
1330 aImplWin
->SetDisplayActive( true );
1331 aImplWin
->InitView();
1333 aImplWin
->Draw( pDev
, aPos
);
1339 void Dialog::queue_resize(StateChangedType eReason
)
1343 SystemWindow::queue_resize(eReason
);
1346 void Dialog::Resize()
1348 SystemWindow::Resize();
1350 if (comphelper::LibreOfficeKit::isDialogPainting())
1353 if (const vcl::ILibreOfficeKitNotifier
* pNotifier
= GetLOKNotifier())
1355 std::vector
<vcl::LOKPayloadItem
> aItems
;
1356 aItems
.emplace_back("size", GetSizePixel().toString());
1357 pNotifier
->notifyWindow(GetLOKWindowId(), "size_changed", aItems
);
1361 bool Dialog::set_property(const OString
&rKey
, const OUString
&rValue
)
1363 if (rKey
== "border-width")
1364 set_border_width(rValue
.toInt32());
1366 return SystemWindow::set_property(rKey
, rValue
);
1370 FactoryFunction
Dialog::GetUITestFactory() const
1372 return DialogUIObject::create
;
1375 IMPL_LINK(Dialog
, ResponseHdl
, Button
*, pButton
, void)
1377 auto aFind
= mpDialogImpl
->maResponses
.find(pButton
);
1378 if (aFind
== mpDialogImpl
->maResponses
.end())
1380 short nResponse
= aFind
->second
;
1381 if (nResponse
== RET_HELP
)
1383 vcl::Window
* pFocusWin
= Application::GetFocusWindow();
1385 pFocusWin
= pButton
;
1386 HelpEvent
aEvt(pFocusWin
->GetPointerPosPixel(), HelpEventMode::CONTEXT
);
1387 pFocusWin
->RequestHelp(aEvt
);
1390 EndDialog(nResponse
);
1393 void Dialog::add_button(PushButton
* pButton
, int response
, bool bTransferOwnership
)
1395 if (bTransferOwnership
)
1396 mpDialogImpl
->maOwnedButtons
.push_back(pButton
);
1397 mpDialogImpl
->maResponses
[pButton
] = response
;
1398 switch (pButton
->GetType())
1400 case WindowType::PUSHBUTTON
:
1402 if (!pButton
->GetClickHdl().IsSet())
1403 pButton
->SetClickHdl(LINK(this, Dialog
, ResponseHdl
));
1406 //insist that the response ids match the default actions for those
1407 //widgets, and leave their default handlers in place
1408 case WindowType::OKBUTTON
:
1409 assert(mpDialogImpl
->get_response(pButton
) == RET_OK
);
1411 case WindowType::CANCELBUTTON
:
1412 assert(mpDialogImpl
->get_response(pButton
) == RET_CANCEL
|| mpDialogImpl
->get_response(pButton
) == RET_CLOSE
);
1414 case WindowType::HELPBUTTON
:
1415 assert(mpDialogImpl
->get_response(pButton
) == RET_HELP
);
1418 SAL_WARN("vcl.layout", "The type of widget " <<
1419 pButton
->GetHelpId() << " is currently not handled");
1424 vcl::Window
* Dialog::get_widget_for_response(int response
)
1426 //copy explicit responses
1427 std::map
<VclPtr
<vcl::Window
>, short> aResponses(mpDialogImpl
->maResponses
);
1431 //add implicit responses
1432 for (vcl::Window
* pChild
= mpActionArea
->GetWindow(GetWindowType::FirstChild
); pChild
;
1433 pChild
= pChild
->GetWindow(GetWindowType::Next
))
1435 if (aResponses
.find(pChild
) != aResponses
.end())
1437 switch (pChild
->GetType())
1439 case WindowType::OKBUTTON
:
1440 aResponses
[pChild
] = RET_OK
;
1442 case WindowType::CANCELBUTTON
:
1443 aResponses
[pChild
] = RET_CANCEL
;
1445 case WindowType::HELPBUTTON
:
1446 aResponses
[pChild
] = RET_HELP
;
1454 for (const auto& a
: aResponses
)
1456 if (a
.second
== response
)
1463 int Dialog::get_default_response() const
1465 //copy explicit responses
1466 std::map
<VclPtr
<vcl::Window
>, short> aResponses(mpDialogImpl
->maResponses
);
1470 //add implicit responses
1471 for (vcl::Window
* pChild
= mpActionArea
->GetWindow(GetWindowType::FirstChild
); pChild
;
1472 pChild
= pChild
->GetWindow(GetWindowType::Next
))
1474 if (aResponses
.find(pChild
) != aResponses
.end())
1476 switch (pChild
->GetType())
1478 case WindowType::OKBUTTON
:
1479 aResponses
[pChild
] = RET_OK
;
1481 case WindowType::CANCELBUTTON
:
1482 aResponses
[pChild
] = RET_CANCEL
;
1484 case WindowType::HELPBUTTON
:
1485 aResponses
[pChild
] = RET_HELP
;
1493 for (const auto& a
: aResponses
)
1495 if (a
.first
->GetStyle() & WB_DEFBUTTON
)
1503 void Dialog::set_default_response(int response
)
1505 //copy explicit responses
1506 std::map
<VclPtr
<vcl::Window
>, short> aResponses(mpDialogImpl
->maResponses
);
1510 //add implicit responses
1511 for (vcl::Window
* pChild
= mpActionArea
->GetWindow(GetWindowType::FirstChild
); pChild
;
1512 pChild
= pChild
->GetWindow(GetWindowType::Next
))
1514 if (aResponses
.find(pChild
) != aResponses
.end())
1516 switch (pChild
->GetType())
1518 case WindowType::OKBUTTON
:
1519 aResponses
[pChild
] = RET_OK
;
1521 case WindowType::CANCELBUTTON
:
1522 aResponses
[pChild
] = RET_CANCEL
;
1524 case WindowType::HELPBUTTON
:
1525 aResponses
[pChild
] = RET_HELP
;
1533 for (auto& a
: aResponses
)
1535 if (a
.second
== response
)
1537 a
.first
->SetStyle(a
.first
->GetStyle() | WB_DEFBUTTON
);
1538 a
.first
->GrabFocus();
1542 a
.first
->SetStyle(a
.first
->GetStyle() & ~WB_DEFBUTTON
);
1547 VclBuilderContainer::VclBuilderContainer()
1551 VclBuilderContainer::~VclBuilderContainer()
1555 void Dialog::Activate()
1557 if (GetType() == WindowType::MODELESSDIALOG
)
1559 css::uno::Reference
< css::uno::XComponentContext
> xContext(
1560 comphelper::getProcessComponentContext() );
1561 css::uno::Reference
<css::frame::XGlobalEventBroadcaster
> xEventBroadcaster(css::frame::theGlobalEventBroadcaster::get(xContext
), css::uno::UNO_SET_THROW
);
1562 css::document::DocumentEvent aObject
;
1563 aObject
.EventName
= "ModelessDialogVisible";
1564 xEventBroadcaster
->documentEventOccured(aObject
);
1566 SystemWindow::Activate();
1569 void Dialog::Command(const CommandEvent
& rCEvt
)
1571 if (mpDialogImpl
&& mpDialogImpl
->m_aPopupMenuHdl
.Call(rCEvt
))
1573 SystemWindow::Command(rCEvt
);
1576 void TopLevelWindowLocker::incBusy(const weld::Widget
* pIgnore
)
1578 // lock any toplevel windows from being closed until busy is over
1579 std::vector
<VclPtr
<vcl::Window
>> aTopLevels
;
1580 vcl::Window
*pTopWin
= Application::GetFirstTopLevelWindow();
1583 vcl::Window
* pCandidate
= pTopWin
;
1584 if (pCandidate
->GetType() == WindowType::BORDERWINDOW
)
1585 pCandidate
= pCandidate
->GetWindow(GetWindowType::FirstChild
);
1586 // tdf#125266 ignore HelpTextWindows
1588 pCandidate
->GetType() != WindowType::HELPTEXTWINDOW
&&
1589 pCandidate
->GetType() != WindowType::FLOATINGWINDOW
&&
1590 pCandidate
->GetFrameWeld() != pIgnore
)
1592 aTopLevels
.push_back(pCandidate
);
1594 pTopWin
= Application::GetNextTopLevelWindow(pTopWin
);
1596 for (auto& a
: aTopLevels
)
1599 a
->ImplGetFrame()->NotifyModalHierarchy(true);
1601 m_aBusyStack
.push(aTopLevels
);
1604 void TopLevelWindowLocker::decBusy()
1606 // unlock locked toplevel windows from being closed now busy is over
1607 for (auto& a
: m_aBusyStack
.top())
1609 if (a
->IsDisposed())
1612 a
->ImplGetFrame()->NotifyModalHierarchy(false);
1617 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */