/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #ifdef _WIN32 #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef MACOSX #include #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if HAVE_FEATURE_OPENGL #include #endif #include #include #include #include #include #include #include #include #if defined(_WIN32) #define SYSTEM_DEPENDENT_TYPE css::lang::SystemDependent::SYSTEM_WIN32 #elif defined(MACOSX) #define SYSTEM_DEPENDENT_TYPE css::lang::SystemDependent::SYSTEM_MAC #elif defined(UNX) #define SYSTEM_DEPENDENT_TYPE css::lang::SystemDependent::SYSTEM_XWINDOW #endif void MessBox::ImplInitButtons() { ButtonDialogFlags nOKFlags = ButtonDialogFlags::OK; ButtonDialogFlags nCancelFlags = ButtonDialogFlags::Cancel; ButtonDialogFlags nRetryFlags = ButtonDialogFlags::NONE; ButtonDialogFlags nYesFlags = ButtonDialogFlags::NONE; ButtonDialogFlags nNoFlags = ButtonDialogFlags::NONE; if ( mnMessBoxStyle & MessBoxStyle::OkCancel ) { if ( mnMessBoxStyle & MessBoxStyle::DefaultCancel ) nCancelFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus; else // MessBoxStyle::DefaultOk nOKFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus; AddButton( StandardButtonType::OK, RET_OK, nOKFlags ); AddButton( StandardButtonType::Cancel, RET_CANCEL, nCancelFlags ); } else if ( mnMessBoxStyle & MessBoxStyle::YesNo ) { if ( mnMessBoxStyle & MessBoxStyle::DefaultYes ) nYesFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus; else // MessBoxStyle::DefaultNo nNoFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus; nNoFlags |= ButtonDialogFlags::Cancel; AddButton( StandardButtonType::Yes, RET_YES, nYesFlags ); AddButton( StandardButtonType::No, RET_NO, nNoFlags ); } else if ( mnMessBoxStyle & MessBoxStyle::YesNoCancel ) { if ( mnMessBoxStyle & MessBoxStyle::DefaultYes ) nYesFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus; else if ( mnMessBoxStyle & MessBoxStyle::DefaultNo ) nNoFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus; else nCancelFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus; AddButton( StandardButtonType::Yes, RET_YES, nYesFlags ); AddButton( StandardButtonType::No, RET_NO, nNoFlags ); AddButton( StandardButtonType::Cancel, RET_CANCEL, nCancelFlags ); } else if ( mnMessBoxStyle & MessBoxStyle::RetryCancel ) { if ( mnMessBoxStyle & MessBoxStyle::DefaultCancel ) nCancelFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus; else // MessBoxStyle::DefaultRetry nRetryFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus; AddButton( StandardButtonType::Retry, RET_RETRY, nRetryFlags ); AddButton( StandardButtonType::Cancel, RET_CANCEL, nCancelFlags ); } else if ( mnMessBoxStyle & MessBoxStyle::AbortRetryIgnore ) { ButtonDialogFlags nAbortFlags = ButtonDialogFlags::NONE; ButtonDialogFlags nIgnoreFlags = ButtonDialogFlags::NONE; if ( mnMessBoxStyle & MessBoxStyle::DefaultCancel ) nAbortFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus; else if ( mnMessBoxStyle & MessBoxStyle::DefaultRetry ) nRetryFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus; else if ( mnMessBoxStyle & MessBoxStyle::DefaultIgnore ) nIgnoreFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus; AddButton( StandardButtonType::Abort, RET_CANCEL, nAbortFlags ); AddButton( StandardButtonType::Retry, RET_RETRY, nRetryFlags ); AddButton( StandardButtonType::Ignore, RET_IGNORE, nIgnoreFlags ); } else if ( mnMessBoxStyle & MessBoxStyle::Ok ) { nOKFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus; AddButton( StandardButtonType::OK, RET_OK, nOKFlags ); } } MessBox::MessBox(vcl::Window* pParent, MessBoxStyle nMessBoxStyle, WinBits nWinBits, const OUString& rTitle, const OUString& rMessage) : ButtonDialog( WindowType::MESSBOX ), mbHelpBtn( false ), mnMessBoxStyle( nMessBoxStyle ), maMessText( rMessage ) { ImplLOKNotifier(pParent); ImplInit(pParent, nWinBits | WB_MOVEABLE | WB_HORZ | WB_CENTER); ImplInitButtons(); if ( !rTitle.isEmpty() ) SetText( rTitle ); } MessBox::~MessBox() { disposeOnce(); } void MessBox::dispose() { mpVCLMultiLineEdit.disposeAndClear(); mpFixedImage.disposeAndClear(); ButtonDialog::dispose(); } void MessBox::ImplPosControls() { if ( !GetHelpId().isEmpty() ) { if ( !mbHelpBtn ) { AddButton( StandardButtonType::Help, RET_HELP, ButtonDialogFlags::Help, 3 ); mbHelpBtn = true; } } else { if ( mbHelpBtn ) { RemoveButton( RET_HELP ); mbHelpBtn = false; } } TextRectInfo aTextInfo; tools::Rectangle aRect( 0, 0, 30000, 30000 ); tools::Rectangle aFormatRect; Point aTextPos( IMPL_DIALOG_OFFSET, IMPL_DIALOG_OFFSET+IMPL_MSGBOX_OFFSET_EXTRA_Y ); Size aImageSize; Size aPageSize; Size aMEditSize; long nTitleWidth; long nButtonSize = ImplGetButtonSize(); long nMaxWidth = GetDesktopRectPixel().GetWidth()-8; long nMaxLineWidth; long nWidth; WinBits nWinStyle = WB_LEFT | WB_NOLABEL; DrawTextFlags nTextStyle = DrawTextFlags::MultiLine | DrawTextFlags::Top | DrawTextFlags::Left; mpVCLMultiLineEdit.disposeAndClear(); mpFixedImage.disposeAndClear(); // Clean up message text with tabs OUString aMessText(maMessText.replaceAll("\t", " ")); //If window too small, we make dialog box be wider nMaxWidth = 630 * GetDPIScaleFactor(); // MessagBox should be at least as wide as to see the title // Extra-Width for Close button, because Close button is set after this call nTitleWidth = CalcTitleWidth(); nMaxWidth -= (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_X*2); // for an image, get its size, create a suitable control and position it aImageSize = maImage.GetSizePixel(); if ( aImageSize.Width() ) { aImageSize.AdjustWidth(4 ); aImageSize.AdjustHeight(4 ); aTextPos.AdjustX(aImageSize.Width()+IMPL_SEP_MSGBOX_IMAGE ); mpFixedImage = VclPtr::Create( this ); mpFixedImage->SetPosSizePixel( Point( IMPL_DIALOG_OFFSET-2+IMPL_MSGBOX_OFFSET_EXTRA_X, IMPL_DIALOG_OFFSET-2+IMPL_MSGBOX_OFFSET_EXTRA_Y ), aImageSize ); mpFixedImage->SetImage( maImage ); mpFixedImage->Show(); nMaxWidth -= aImageSize.Width()+IMPL_SEP_MSGBOX_IMAGE; } else aTextPos.AdjustX(IMPL_MSGBOX_OFFSET_EXTRA_X ); // Determine maximum line length without wordbreak aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo ); nMaxLineWidth = aFormatRect.GetWidth(); nTextStyle |= DrawTextFlags::WordBreak; // Determine the width for text formatting if ( nMaxLineWidth > 450 ) nWidth = 450; else if ( nMaxLineWidth > 300 ) nWidth = nMaxLineWidth+5; else nWidth = 300; nWidth *= GetDPIScaleFactor(); if ( nButtonSize > nWidth ) nWidth = nButtonSize-(aTextPos.X()-IMPL_DIALOG_OFFSET); if ( nWidth > nMaxWidth ) nWidth = nMaxWidth; aRect.SetRight( nWidth ); aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo ); if ( aTextInfo.GetMaxLineWidth() > nWidth ) { nWidth = aTextInfo.GetMaxLineWidth()+8; aRect.SetRight( nWidth ); aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo ); } // get Style for VCLMultiLineEdit aMEditSize.setWidth( aTextInfo.GetMaxLineWidth()+1 ); aMEditSize.setHeight( aFormatRect.GetHeight() ); aPageSize.setWidth( aImageSize.Width() ); if ( aMEditSize.Height() < aImageSize.Height() ) { nWinStyle |= WB_VCENTER; aPageSize.setHeight( aImageSize.Height() ); aMEditSize.setHeight( aImageSize.Height() ); } else { nWinStyle |= WB_TOP; aPageSize.setHeight( aMEditSize.Height() ); } if ( aImageSize.Width() ) aPageSize.AdjustWidth(IMPL_SEP_MSGBOX_IMAGE ); aPageSize.AdjustWidth((IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_X*2) ); aPageSize.AdjustWidth(aMEditSize.Width()+1 ); aPageSize.AdjustHeight((IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_Y*2) ); if ( aPageSize.Width() < IMPL_MINSIZE_MSGBOX_WIDTH ) aPageSize.setWidth( IMPL_MINSIZE_MSGBOX_WIDTH ); if ( aPageSize.Width() < nTitleWidth ) aPageSize.setWidth( nTitleWidth ); mpVCLMultiLineEdit = VclPtr::Create( this, nWinStyle ); mpVCLMultiLineEdit->SetText( aMessText ); mpVCLMultiLineEdit->SetPosSizePixel( aTextPos, aMEditSize ); mpVCLMultiLineEdit->Show(); mpVCLMultiLineEdit->SetPaintTransparent(true); mpVCLMultiLineEdit->EnableCursor(false); SetPageSizePixel( aPageSize ); } void MessBox::StateChanged( StateChangedType nType ) { if ( nType == StateChangedType::InitShow ) { ImplPosControls(); } ButtonDialog::StateChanged( nType ); } Size MessBox::GetOptimalSize() const { // FIXME: base me on the font size ? return Size( 250, 100 ); } namespace { extern "C" typedef vcl::Window* (*FN_SvtCreateWindow)( VCLXWindow** ppNewComp, const css::awt::WindowDescriptor* pDescriptor, vcl::Window* pParent, WinBits nWinBits ); class Pause : public Idle { public: explicit Pause(sal_Int32 nPauseMilliseconds) : Idle("pause"), m_nPauseMilliseconds(nPauseMilliseconds) { SetPriority(TaskPriority::HIGHEST); Start(); } virtual void Invoke() override { SolarMutexGuard aSolarGuard; osl::Thread::wait(std::chrono::milliseconds(m_nPauseMilliseconds)); Stop(); delete this; } sal_Int32 m_nPauseMilliseconds; }; class VCLXToolkitMutexHelper { protected: ::osl::Mutex maMutex; }; class VCLXToolkit : public VCLXToolkitMutexHelper, public cppu::WeakComponentImplHelper< css::awt::XToolkitExperimental, css::awt::XToolkitRobot, css::lang::XServiceInfo > { css::uno::Reference< css::datatransfer::clipboard::XClipboard > mxClipboard; css::uno::Reference< css::datatransfer::clipboard::XClipboard > mxSelection; oslModule hSvToolsLib; FN_SvtCreateWindow fnSvtCreateWindow; ::comphelper::OInterfaceContainerHelper2 m_aTopWindowListeners; ::comphelper::OInterfaceContainerHelper2 m_aKeyHandlers; ::comphelper::OInterfaceContainerHelper2 m_aFocusListeners; ::Link m_aEventListenerLink; ::Link m_aKeyListenerLink; bool m_bEventListener; bool m_bKeyListener; DECL_LINK(eventListenerHandler, ::VclSimpleEvent&, void); DECL_LINK(keyListenerHandler, ::VclWindowEvent&, bool); void callTopWindowListeners( ::VclSimpleEvent const * pEvent, void (SAL_CALL css::awt::XTopWindowListener::* pFn)( css::lang::EventObject const &)); bool callKeyHandlers(::VclSimpleEvent const * pEvent, bool bPressed); void callFocusListeners(::VclSimpleEvent const * pEvent, bool bGained); protected: ::osl::Mutex& GetMutex() { return maMutex; } virtual void SAL_CALL disposing() override; static vcl::Window* ImplCreateWindow( VCLXWindow** ppNewComp, const css::awt::WindowDescriptor& rDescriptor, vcl::Window* pParent, WinBits nWinBits, MessBoxStyle nMessBoxStyle ); css::uno::Reference< css::awt::XWindowPeer > ImplCreateWindow( const css::awt::WindowDescriptor& Descriptor, MessBoxStyle nForceMessBoxStyle ); public: VCLXToolkit(); // css::awt::XToolkitExperimental virtual void SAL_CALL processEventsToIdle() override; virtual sal_Int64 SAL_CALL getOpenGLBufferSwapCounter() override; virtual void SAL_CALL setDeterministicScheduling(sal_Bool bDeterministicMode) override; virtual void SAL_CALL pause(sal_Int32 nMilliseconds) override; virtual void SAL_CALL startRecording() override; virtual void SAL_CALL stopRecording() override; css::uno::Sequence< OUString > SAL_CALL getRecordingAndClear() override; // css::awt::XToolkit css::uno::Reference< css::awt::XWindowPeer > SAL_CALL getDesktopWindow( ) override; css::awt::Rectangle SAL_CALL getWorkArea( ) override; css::uno::Reference< css::awt::XWindowPeer > SAL_CALL createWindow( const css::awt::WindowDescriptor& Descriptor ) override; css::uno::Sequence< css::uno::Reference< css::awt::XWindowPeer > > SAL_CALL createWindows( const css::uno::Sequence< css::awt::WindowDescriptor >& Descriptors ) override; css::uno::Reference< css::awt::XDevice > SAL_CALL createScreenCompatibleDevice( sal_Int32 Width, sal_Int32 Height ) override; css::uno::Reference< css::awt::XRegion > SAL_CALL createRegion( ) override; // css::awt::XSystemChildFactory css::uno::Reference< css::awt::XWindowPeer > SAL_CALL createSystemChild( const css::uno::Any& Parent, const css::uno::Sequence< sal_Int8 >& ProcessId, sal_Int16 SystemType ) override; // css::awt::XMessageBoxFactory virtual css::uno::Reference< css::awt::XMessageBox > SAL_CALL createMessageBox( const css::uno::Reference< css::awt::XWindowPeer >& aParent, css::awt::MessageBoxType eType, ::sal_Int32 aButtons, const OUString& aTitle, const OUString& aMessage ) override; // css::awt::XDataTransfer css::uno::Reference< css::datatransfer::dnd::XDragGestureRecognizer > SAL_CALL getDragGestureRecognizer( const css::uno::Reference< css::awt::XWindow >& window ) override; css::uno::Reference< css::datatransfer::dnd::XDragSource > SAL_CALL getDragSource( const css::uno::Reference< css::awt::XWindow >& window ) override; css::uno::Reference< css::datatransfer::dnd::XDropTarget > SAL_CALL getDropTarget( const css::uno::Reference< css::awt::XWindow >& window ) override; css::uno::Reference< css::datatransfer::clipboard::XClipboard > SAL_CALL getClipboard( const OUString& clipboardName ) override; // css::lang::XServiceInfo OUString SAL_CALL getImplementationName( ) override; sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; // css::awt::XExtendedToolkit: virtual ::sal_Int32 SAL_CALL getTopWindowCount() override; virtual css::uno::Reference< css::awt::XTopWindow > SAL_CALL getTopWindow(::sal_Int32 nIndex) override; virtual css::uno::Reference< css::awt::XTopWindow > SAL_CALL getActiveTopWindow() override; virtual void SAL_CALL addTopWindowListener( css::uno::Reference< css::awt::XTopWindowListener > const & rListener) override; virtual void SAL_CALL removeTopWindowListener( css::uno::Reference< css::awt::XTopWindowListener > const & rListener) override; virtual void SAL_CALL addKeyHandler( css::uno::Reference< css::awt::XKeyHandler > const & rHandler) override; virtual void SAL_CALL removeKeyHandler( css::uno::Reference< css::awt::XKeyHandler > const & rHandler) override; virtual void SAL_CALL addFocusListener( css::uno::Reference< css::awt::XFocusListener > const & rListener) override; virtual void SAL_CALL removeFocusListener( css::uno::Reference< css::awt::XFocusListener > const & rListener) override; virtual void SAL_CALL fireFocusGained( css::uno::Reference< css::uno::XInterface > const & source) override; virtual void SAL_CALL fireFocusLost( css::uno::Reference< css::uno::XInterface > const & source) override; // css::awt::XReschedule: virtual void SAL_CALL reschedule() override; // css:awt:XToolkitRobot virtual void SAL_CALL keyPress( const css::awt::KeyEvent & aKeyEvent ) override; virtual void SAL_CALL keyRelease( const css::awt::KeyEvent & aKeyEvent ) override; virtual void SAL_CALL mousePress( const css::awt::MouseEvent & aMouseEvent ) override; virtual void SAL_CALL mouseRelease( const css::awt::MouseEvent & aMouseEvent ) override; virtual void SAL_CALL mouseMove( const css::awt::MouseEvent & aMouseEvent ) override; }; std::pair ImplGetWinBits( sal_uInt32 nComponentAttribs, WindowType nCompType ) { WinBits nWinBits = 0; MessBoxStyle nStyle = MessBoxStyle::NONE; bool bMessBox = false; if ( ( nCompType == WindowType::INFOBOX ) || ( nCompType == WindowType::MESSBOX ) || ( nCompType == WindowType::QUERYBOX ) || ( nCompType == WindowType::WARNINGBOX ) || ( nCompType == WindowType::ERRORBOX ) ) { bMessBox = true; } bool bDecoratedWindow = false; if ( bMessBox || ( nCompType == WindowType::DIALOG ) || ( nCompType == WindowType::MODELESSDIALOG ) || ( nCompType == WindowType::MODALDIALOG ) || ( nCompType == WindowType::DOCKINGWINDOW ) || ( nCompType == WindowType::TABDIALOG ) || ( nCompType == WindowType::BUTTONDIALOG ) || ( nCompType == WindowType::SYSTEMCHILDWINDOW ) ) { bDecoratedWindow = true; } if( nComponentAttribs & css::awt::WindowAttribute::BORDER ) nWinBits |= WB_BORDER; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::NOBORDER ) nWinBits |= WB_NOBORDER; if( nComponentAttribs & css::awt::WindowAttribute::SIZEABLE ) nWinBits |= WB_SIZEABLE; if( nComponentAttribs & css::awt::WindowAttribute::MOVEABLE ) nWinBits |= WB_MOVEABLE; if( nComponentAttribs & css::awt::WindowAttribute::CLOSEABLE ) nWinBits |= WB_CLOSEABLE; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::HSCROLL ) nWinBits |= WB_HSCROLL; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::VSCROLL ) nWinBits |= WB_VSCROLL; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::LEFT ) nWinBits |= WB_LEFT; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::CENTER ) nWinBits |= WB_CENTER; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::RIGHT ) nWinBits |= WB_RIGHT; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::SPIN ) nWinBits |= WB_SPIN; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::SORT ) nWinBits |= WB_SORT; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DROPDOWN ) nWinBits |= WB_DROPDOWN; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DEFBUTTON ) nWinBits |= WB_DEFBUTTON; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::READONLY ) nWinBits |= WB_READONLY; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::CLIPCHILDREN ) nWinBits |= WB_CLIPCHILDREN; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::GROUP ) nWinBits |= WB_GROUP; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::NOLABEL ) //added for issue79712 nWinBits |= WB_NOLABEL; // These bits are not unique if ( bMessBox ) { if( nComponentAttribs & css::awt::VclWindowPeerAttribute::OK ) nStyle |= MessBoxStyle::Ok; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::OK_CANCEL ) nStyle |= MessBoxStyle::OkCancel; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::YES_NO ) nStyle |= MessBoxStyle::YesNo; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::YES_NO_CANCEL ) nStyle |= MessBoxStyle::YesNoCancel; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::RETRY_CANCEL ) nStyle |= MessBoxStyle::RetryCancel; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DEF_OK ) nStyle |= MessBoxStyle::DefaultOk; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DEF_CANCEL ) nStyle |= MessBoxStyle::DefaultCancel; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DEF_RETRY ) nStyle |= MessBoxStyle::DefaultRetry; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DEF_YES ) nStyle |= MessBoxStyle::DefaultYes; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DEF_NO ) nStyle |= MessBoxStyle::DefaultNo; } if ( nCompType == WindowType::MULTILINEEDIT || nCompType == WindowType::DIALOG || nCompType == WindowType::GROUPBOX ) { if( nComponentAttribs & css::awt::VclWindowPeerAttribute::AUTOHSCROLL ) nWinBits |= WB_AUTOHSCROLL; if( nComponentAttribs & css::awt::VclWindowPeerAttribute::AUTOVSCROLL ) nWinBits |= WB_AUTOVSCROLL; } if ( bDecoratedWindow ) { if( nComponentAttribs & css::awt::WindowAttribute::NODECORATION ) { // No decoration removes several window attributes and must // set WB_NOBORDER! nWinBits &= ~WB_BORDER; nWinBits &= ~WB_SIZEABLE; nWinBits &= ~WB_MOVEABLE; nWinBits &= ~WB_CLOSEABLE; nWinBits |= WB_NOBORDER; } } return { nWinBits, nStyle }; } struct ComponentInfo { const char* pName; WindowType nWinType; }; static ComponentInfo aComponentInfos [] = { { "buttondialog", WindowType::BUTTONDIALOG }, { "cancelbutton", WindowType::CANCELBUTTON }, { "checkbox", WindowType::CHECKBOX }, { "combobox", WindowType::COMBOBOX }, { "control", WindowType::CONTROL }, { "currencybox", WindowType::CURRENCYBOX }, { "currencyfield", WindowType::CURRENCYFIELD }, { "datebox", WindowType::DATEBOX }, { "datefield", WindowType::DATEFIELD }, { "dialog", WindowType::DIALOG }, { "dockingarea", WindowType::DOCKINGAREA }, { "dockingwindow", WindowType::DOCKINGWINDOW }, { "edit", WindowType::EDIT }, { "errorbox", WindowType::ERRORBOX }, { "fixedbitmap", WindowType::FIXEDBITMAP }, { "fixedimage", WindowType::FIXEDIMAGE }, { "fixedline", WindowType::FIXEDLINE }, { "fixedtext", WindowType::FIXEDTEXT }, { "floatingwindow", WindowType::FLOATINGWINDOW }, { "framewindow", WindowType::TOOLKIT_FRAMEWINDOW }, { "groupbox", WindowType::GROUPBOX }, { "frame", WindowType::GROUPBOX }, { "helpbutton", WindowType::HELPBUTTON }, { "imagebutton", WindowType::IMAGEBUTTON }, { "infobox", WindowType::INFOBOX }, { "listbox", WindowType::LISTBOX }, { "longcurrencybox", WindowType::LONGCURRENCYBOX }, { "longcurrencyfield", WindowType::LONGCURRENCYFIELD }, { "menubutton", WindowType::MENUBUTTON }, { "messbox", WindowType::MESSBOX }, { "metricbox", WindowType::METRICBOX }, { "metricfield", WindowType::METRICFIELD }, { "modaldialog", WindowType::MODALDIALOG }, { "modelessdialog", WindowType::MODELESSDIALOG }, { "morebutton", WindowType::MOREBUTTON }, { "multilineedit", WindowType::MULTILINEEDIT }, { "multilistbox", WindowType::MULTILISTBOX }, { "numericbox", WindowType::NUMERICBOX }, { "numericfield", WindowType::NUMERICFIELD }, { "okbutton", WindowType::OKBUTTON }, { "patternbox", WindowType::PATTERNBOX }, { "patternfield", WindowType::PATTERNFIELD }, { "pushbutton", WindowType::PUSHBUTTON }, { "querybox", WindowType::QUERYBOX }, { "radiobutton", WindowType::RADIOBUTTON }, { "scrollbar", WindowType::SCROLLBAR }, { "scrollbarbox", WindowType::SCROLLBARBOX }, { "animatedimages", WindowType::CONTROL }, { "spinbutton", WindowType::SPINBUTTON }, { "spinfield", WindowType::SPINFIELD }, { "splitter", WindowType::SPLITTER }, { "splitwindow", WindowType::SPLITWINDOW }, { "statusbar", WindowType::STATUSBAR }, { "systemchildwindow", WindowType::TOOLKIT_SYSTEMCHILDWINDOW }, { "tabcontrol", WindowType::TABCONTROL }, { "tabdialog", WindowType::TABDIALOG }, { "tabpage", WindowType::TABPAGE }, { "timebox", WindowType::TIMEBOX }, { "timefield", WindowType::TIMEFIELD }, { "toolbox", WindowType::TOOLBOX }, { "tristatebox", WindowType::TRISTATEBOX }, { "warningbox", WindowType::WARNINGBOX }, { "window", WindowType::WINDOW }, { "workwindow", WindowType::WORKWINDOW }, { "tabpagecontainer", WindowType::CONTROL }, { "tabpagemodel", WindowType::TABPAGE } }; extern "C" { static int ComponentInfoCompare( const void* pFirst, const void* pSecond) { return strcmp( static_cast(pFirst)->pName, static_cast(pSecond)->pName ); } } WindowType ImplGetComponentType( const OUString& rServiceName ) { static bool bSorted = false; if( !bSorted ) { qsort( static_cast(aComponentInfos), SAL_N_ELEMENTS( aComponentInfos ), sizeof( ComponentInfo ), ComponentInfoCompare ); bSorted = true; } ComponentInfo aSearch; OString aServiceName(OUStringToOString(rServiceName, osl_getThreadTextEncoding()).toAsciiLowerCase()); if ( !aServiceName.isEmpty() ) aSearch.pName = aServiceName.getStr(); else aSearch.pName = "window"; ComponentInfo* pInf = static_cast(bsearch( &aSearch, static_cast(aComponentInfos), SAL_N_ELEMENTS( aComponentInfos ), sizeof( ComponentInfo ), ComponentInfoCompare )); return pInf ? pInf->nWinType : WindowType::NONE; } struct MessageBoxTypeInfo { css::awt::MessageBoxType eType; const sal_Char *pName; sal_Int32 nLen; }; static const MessageBoxTypeInfo aMessageBoxTypeInfo[] = { { css::awt::MessageBoxType_MESSAGEBOX, RTL_CONSTASCII_STRINGPARAM("messbox") }, { css::awt::MessageBoxType_INFOBOX, RTL_CONSTASCII_STRINGPARAM("infobox") }, { css::awt::MessageBoxType_WARNINGBOX, RTL_CONSTASCII_STRINGPARAM("warningbox") }, { css::awt::MessageBoxType_ERRORBOX, RTL_CONSTASCII_STRINGPARAM("errorbox") }, { css::awt::MessageBoxType_QUERYBOX, RTL_CONSTASCII_STRINGPARAM("querybox") }, { css::awt::MessageBoxType::MessageBoxType_MAKE_FIXED_SIZE, nullptr, 0 } }; bool lcl_convertMessageBoxType( rtl::OUString &sType, css::awt::MessageBoxType eType ) { const MessageBoxTypeInfo *pMap = aMessageBoxTypeInfo; css::awt::MessageBoxType eVal = css::awt::MessageBoxType::MessageBoxType_MAKE_FIXED_SIZE; while ( pMap->pName ) { if ( pMap->eType == eType ) { eVal = eType; sType = rtl::OUString( pMap->pName, pMap->nLen, RTL_TEXTENCODING_ASCII_US ); break; } pMap++; } return ( eVal != css::awt::MessageBoxType::MessageBoxType_MAKE_FIXED_SIZE ); } static sal_Int32 nVCLToolkitInstanceCount = 0; static bool bInitedByVCLToolkit = false; osl::Mutex & getInitMutex() { static osl::Mutex * pM; if( !pM ) { osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); if( !pM ) { static osl::Mutex aMutex; pM = &aMutex; } } return *pM; } osl::Condition & getInitCondition() { static osl::Condition * pC = nullptr; if( !pC ) { osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); if( !pC ) { static osl::Condition aCondition; pC = &aCondition; } } return *pC; } extern "C" { static void ToolkitWorkerFunction( void* pArgs ) { osl_setThreadName("VCLXToolkit VCL main thread"); css::uno::Reference xServiceManager; try { xServiceManager = ::comphelper::getProcessServiceFactory(); } catch (const css::uno::DeploymentException&) { } if (!xServiceManager.is()) { css::uno::Reference xContext = ::cppu::defaultBootstrap_InitialComponentContext(); xServiceManager.set( xContext->getServiceManager(), css::uno::UNO_QUERY_THROW ); // set global process service factory used by unotools config helpers ::comphelper::setProcessServiceFactory( xServiceManager ); } VCLXToolkit * pTk = static_cast(pArgs); bInitedByVCLToolkit = InitVCL(); if( bInitedByVCLToolkit ) { UnoWrapper* pUnoWrapper = new UnoWrapper( pTk ); Application::SetUnoWrapper( pUnoWrapper ); } getInitCondition().set(); if( bInitedByVCLToolkit ) { { SolarMutexGuard aGuard; Application::Execute(); } try { pTk->dispose(); } catch( css::uno::Exception & ) { } DeInitVCL(); } else { // having the thread join itself is pretty stupid. // but we can't get the osl_Thread to destroy here so just leak it. } } } // constructor, which might initialize VCL VCLXToolkit::VCLXToolkit(): cppu::WeakComponentImplHelper< css::awt::XToolkitExperimental, css::awt::XToolkitRobot, css::lang::XServiceInfo>( GetMutex() ), m_aTopWindowListeners(rBHelper.rMutex), m_aKeyHandlers(rBHelper.rMutex), m_aFocusListeners(rBHelper.rMutex), m_aEventListenerLink(LINK(this, VCLXToolkit, eventListenerHandler)), m_aKeyListenerLink(LINK(this, VCLXToolkit, keyListenerHandler)), m_bEventListener(false), m_bKeyListener(false) { hSvToolsLib = nullptr; fnSvtCreateWindow = nullptr; osl::Guard< osl::Mutex > aGuard( getInitMutex() ); nVCLToolkitInstanceCount++; if( ( nVCLToolkitInstanceCount == 1 ) && ( !Application::IsInMain() ) ) { // setup execute thread CreateMainLoopThread( ToolkitWorkerFunction, this ); getInitCondition().wait(); } } void SAL_CALL VCLXToolkit::disposing() { #ifndef DISABLE_DYNLOADING if ( hSvToolsLib ) { osl_unloadModule( hSvToolsLib ); hSvToolsLib = nullptr; fnSvtCreateWindow = nullptr; } #endif { osl::Guard< osl::Mutex > aGuard( getInitMutex() ); if( --nVCLToolkitInstanceCount == 0 ) { if( bInitedByVCLToolkit ) { Application::Quit(); JoinMainLoopThread(); bInitedByVCLToolkit = false; } } } if (m_bEventListener) { ::Application::RemoveEventListener(m_aEventListenerLink); m_bEventListener = false; } if (m_bKeyListener) { ::Application::RemoveKeyListener(m_aKeyListenerLink); m_bKeyListener = false; } css::lang::EventObject aEvent( static_cast< ::cppu::OWeakObject * >(this)); m_aTopWindowListeners.disposeAndClear(aEvent); m_aKeyHandlers.disposeAndClear(aEvent); m_aFocusListeners.disposeAndClear(aEvent); } css::uno::Reference< css::awt::XWindowPeer > VCLXToolkit::getDesktopWindow( ) { css::uno::Reference< css::awt::XWindowPeer > xRef; // 07/00: AppWindow doesn't exist anymore... return xRef; } css::awt::Rectangle VCLXToolkit::getWorkArea( ) { sal_Int32 nDisplay = Application::GetDisplayBuiltInScreen(); tools::Rectangle aWorkRect = Application::GetScreenPosSizePixel( nDisplay ); css::awt::Rectangle aNotherRect; aNotherRect.X = aWorkRect.getX(); aNotherRect.Y = aWorkRect.getY(); aNotherRect.Width = aWorkRect.getWidth(); aNotherRect.Height = aWorkRect.getHeight(); return aNotherRect; } css::uno::Reference< css::awt::XWindowPeer > VCLXToolkit::createWindow( const css::awt::WindowDescriptor& rDescriptor ) { return ImplCreateWindow( rDescriptor, MessBoxStyle::NONE ); } css::uno::Reference< css::awt::XDevice > VCLXToolkit::createScreenCompatibleDevice( sal_Int32 Width, sal_Int32 Height ) { ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); css::uno::Reference< css::awt::XDevice > xRef; VCLXVirtualDevice* pVDev = new VCLXVirtualDevice; SolarMutexGuard aSolarGuard; VclPtrInstance pV; pV->SetOutputSizePixel( Size( Width, Height ) ); pVDev->SetVirtualDevice( pV ); xRef = pVDev; return xRef; } css::uno::Reference< css::awt::XRegion > VCLXToolkit::createRegion( ) { ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); css::uno::Reference< css::awt::XRegion > xRef = new VCLXRegion; return xRef; } class InfoBox : public MessBox { public: InfoBox(vcl::Window* pParent, const OUString& rMessage) : MessBox(pParent, MessBoxStyle::Ok | MessBoxStyle::DefaultOk, 0, OUString(), rMessage) { // Default Text is the display title from the application if (GetText().isEmpty()) SetText(GetStandardInfoBoxText()); SetImage(GetStandardInfoBoxImage()); } }; class ErrorBox : public MessBox { public: ErrorBox(vcl::Window* pParent, MessBoxStyle nStyle, WinBits nWinBits, const OUString& rMessage) : MessBox(pParent, nStyle, nWinBits, OUString(), rMessage) { // Default Text is the display title from the application if (GetText().isEmpty()) SetText(GetStandardErrorBoxText()); SetImage(GetStandardErrorBoxImage()); } }; class QueryBox : public MessBox { public: QueryBox(vcl::Window* pParent, MessBoxStyle nStyle, WinBits nWinBits, const OUString& rMessage) : MessBox(pParent, nStyle, nWinBits, OUString(), rMessage) { // Default Text is the display title from the application if (GetText().isEmpty()) SetText(GetStandardQueryBoxText()); SetImage(GetStandardQueryBoxImage()); } }; class WarningBox : public MessBox { public: WarningBox(vcl::Window* pParent, MessBoxStyle nStyle, WinBits nWinBits, const OUString& rMessage) : MessBox(pParent, nStyle, nWinBits, OUString(), rMessage) { // Default Text is the display title from the application if (GetText().isEmpty()) SetText(GetStandardWarningBoxText()); SetImage(GetStandardWarningBoxImage()); } }; vcl::Window* VCLXToolkit::ImplCreateWindow( VCLXWindow** ppNewComp, const css::awt::WindowDescriptor& rDescriptor, vcl::Window* pParent, WinBits nWinBits, MessBoxStyle nMessBoxStyle ) { OUString aServiceName( rDescriptor.WindowServiceName ); aServiceName = aServiceName.toAsciiLowerCase(); VclPtr pNewWindow; WindowType nType = ImplGetComponentType( aServiceName ); bool bFrameControl = false; if ( aServiceName == "frame" ) bFrameControl = true; if ( aServiceName == "tabcontrolnotabs" ) { nWinBits |= WB_NOBORDER; nType = ImplGetComponentType( "tabcontrol" ); } if ( !pParent ) { // If the component needs a parent, then return NULL, // some time later css::uno::Exception... bool bException = true; if ( ( nType == WindowType::DIALOG ) || ( nType == WindowType::MODALDIALOG ) || ( nType == WindowType::MODELESSDIALOG ) || ( nType == WindowType::MESSBOX ) || ( nType == WindowType::INFOBOX ) || ( nType == WindowType::WARNINGBOX ) || ( nType == WindowType::ERRORBOX ) || ( nType == WindowType::QUERYBOX ) ) bException = false; else if ( ( nType == WindowType::WINDOW ) || ( nType == WindowType::WORKWINDOW ) || ( nType == WindowType::TOOLKIT_FRAMEWINDOW ) ) { if ( rDescriptor.Type == css::awt::WindowClass_TOP ) bException = false; } if ( bException ) { *ppNewComp = nullptr; return nullptr; } } if ( nType != WindowType::NONE ) { SolarMutexGuard aVclGuard; switch ( nType ) { case WindowType::CANCELBUTTON: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXButton; break; case WindowType::CHECKBOX: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXCheckBox; break; case WindowType::COMBOBOX: pNewWindow = VclPtr::Create( pParent, nWinBits|WB_AUTOHSCROLL ); static_cast(pNewWindow.get())->EnableAutoSize( false ); *ppNewComp = new VCLXComboBox; break; case WindowType::CURRENCYBOX: pNewWindow = VclPtr::Create( pParent, nWinBits ); break; case WindowType::CURRENCYFIELD: pNewWindow = VclPtr::Create( pParent, nWinBits ); static_cast(pNewWindow.get())->EnableEmptyFieldValue( true ); *ppNewComp = new VCLXNumericField; static_cast(*ppNewComp)->SetFormatter( static_cast(static_cast(pNewWindow.get())) ); break; case WindowType::DATEBOX: pNewWindow = VclPtr::Create( pParent, nWinBits ); break; case WindowType::DATEFIELD: pNewWindow = VclPtr::Create( pParent, nWinBits ); static_cast(pNewWindow.get())->EnableEmptyFieldValue( true ); *ppNewComp = new VCLXDateField; static_cast(*ppNewComp)->SetFormatter( static_cast(static_cast(pNewWindow.get())) ); break; case WindowType::DOCKINGAREA: pNewWindow = VclPtr::Create( pParent ); break; case WindowType::MULTILINEEDIT: case WindowType::EDIT: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXEdit; break; case WindowType::ERRORBOX: pNewWindow = VclPtr::Create( pParent, nMessBoxStyle, nWinBits, OUString() ); *ppNewComp = new VCLXMessageBox; break; case WindowType::FIXEDBITMAP: pNewWindow = VclPtr::Create( pParent, nWinBits ); break; case WindowType::FIXEDIMAGE: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXImageControl; break; case WindowType::FIXEDLINE: pNewWindow = VclPtr::Create( pParent, nWinBits ); break; case WindowType::FIXEDTEXT: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXFixedText; break; case WindowType::FLOATINGWINDOW: pNewWindow = VclPtr::Create( pParent, nWinBits ); break; case WindowType::GROUPBOX: pNewWindow = VclPtr::Create( pParent, nWinBits ); if ( bFrameControl ) { GroupBox* pGroupBox = static_cast< GroupBox* >( pNewWindow.get() ); *ppNewComp = new VCLXFrame; // Frame control needs to receive // Mouse events pGroupBox->SetMouseTransparent( false ); } break; case WindowType::HELPBUTTON: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXButton; break; case WindowType::IMAGEBUTTON: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXButton; break; case WindowType::INFOBOX: pNewWindow = VclPtr::Create( pParent, OUString() ); *ppNewComp = new VCLXMessageBox; break; case WindowType::LISTBOX: pNewWindow = VclPtr::Create( pParent, nWinBits|WB_SIMPLEMODE|WB_AUTOHSCROLL ); static_cast(pNewWindow.get())->EnableAutoSize( false ); *ppNewComp = new VCLXListBox; break; case WindowType::LONGCURRENCYBOX: pNewWindow = VclPtr::Create( pParent, nWinBits ); break; case WindowType::LONGCURRENCYFIELD: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXCurrencyField; static_cast(*ppNewComp)->SetFormatter( static_cast(static_cast(pNewWindow.get())) ); break; case WindowType::MENUBUTTON: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXButton; break; case WindowType::MESSBOX: pNewWindow = VclPtr::Create( pParent, nMessBoxStyle, nWinBits, OUString(), OUString() ); *ppNewComp = new VCLXMessageBox; break; case WindowType::METRICBOX: pNewWindow = VclPtr::Create( pParent, nWinBits ); break; case WindowType::METRICFIELD: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXMetricField; static_cast(*ppNewComp)->SetFormatter( static_cast(static_cast(pNewWindow.get())) ); break; case WindowType::DIALOG: case WindowType::MODALDIALOG: case WindowType::MODELESSDIALOG: { // Modal/Modeless only via Show/Execute if ( (pParent == nullptr ) && ( rDescriptor.ParentIndex == -1 ) ) pNewWindow = VclPtr::Create( nullptr, nWinBits, Dialog::InitFlag::NoParent ); else pNewWindow = VclPtr::Create( pParent, nWinBits ); // #i70217# Don't always create a new component object. It's possible that VCL has called // GetComponentInterface( sal_True ) in the Dialog ctor itself (see Window::IsTopWindow() ) // which creates a component object. css::uno::Reference< css::awt::XWindowPeer > xWinPeer = pNewWindow->GetComponentInterface( false ); if ( xWinPeer.is() ) *ppNewComp = dynamic_cast< VCLXDialog* >( xWinPeer.get() ); else *ppNewComp = new VCLXDialog; } break; case WindowType::MOREBUTTON: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXButton; break; case WindowType::MULTILISTBOX: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXListBox; break; case WindowType::NUMERICBOX: pNewWindow = VclPtr::Create( pParent, nWinBits ); break; case WindowType::NUMERICFIELD: pNewWindow = VclPtr::Create( pParent, nWinBits ); static_cast(pNewWindow.get())->EnableEmptyFieldValue( true ); *ppNewComp = new VCLXNumericField; static_cast(*ppNewComp)->SetFormatter( static_cast(static_cast(pNewWindow.get())) ); break; case WindowType::OKBUTTON: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXButton; break; case WindowType::PATTERNBOX: pNewWindow = VclPtr::Create( pParent, nWinBits ); break; case WindowType::PATTERNFIELD: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXPatternField; static_cast(*ppNewComp)->SetFormatter( static_cast(static_cast(pNewWindow.get())) ); break; case WindowType::PUSHBUTTON: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXButton; break; case WindowType::QUERYBOX: pNewWindow = VclPtr::Create( pParent, nMessBoxStyle, nWinBits, OUString() ); *ppNewComp = new VCLXMessageBox; break; case WindowType::RADIOBUTTON: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXRadioButton; // by default, disable RadioCheck // Since the VCLXRadioButton really cares for its RadioCheck settings, this is important: // if we enable it, the VCLXRadioButton will use RadioButton::Check instead of RadioButton::SetState // This leads to a strange behaviour if the control is newly created: when settings the initial // state to "checked", the RadioButton::Check (called because RadioCheck=sal_True) will uncheck // _all_other_ radio buttons in the same group. However, at this moment the grouping of the controls // is not really valid: the controls are grouped after they have been created, but we're still in // the creation process, so the RadioButton::Check relies on invalid grouping information. // 07.08.2001 - #87254# - frank.schoenheit@sun.com static_cast(pNewWindow.get())->EnableRadioCheck( false ); break; case WindowType::SCROLLBAR: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXScrollBar; break; case WindowType::SCROLLBARBOX: pNewWindow = VclPtr::Create( pParent, nWinBits ); break; case WindowType::SPINBUTTON: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new ::toolkit::VCLXSpinButton; break; case WindowType::SPINFIELD: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXNumericField; break; case WindowType::SPLITTER: pNewWindow = VclPtr::Create( pParent, nWinBits ); break; case WindowType::SPLITWINDOW: pNewWindow = VclPtr::Create( pParent, nWinBits ); break; case WindowType::STATUSBAR: pNewWindow = VclPtr::Create( pParent, nWinBits ); break; case WindowType::TOOLKIT_SYSTEMCHILDWINDOW: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXSystemDependentWindow(); break; case WindowType::TABCONTROL: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXMultiPage; break; case WindowType::TABDIALOG: pNewWindow = VclPtr::Create( pParent, nWinBits ); break; case WindowType::TABPAGE: { pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXTabPage; } break; case WindowType::TIMEBOX: pNewWindow = VclPtr::Create( pParent, nWinBits ); break; case WindowType::TIMEFIELD: pNewWindow = VclPtr::Create( pParent, nWinBits ); static_cast(pNewWindow.get())->EnableEmptyFieldValue( true ); *ppNewComp = new VCLXTimeField; static_cast(*ppNewComp)->SetFormatter( static_cast(static_cast(pNewWindow.get())) ); break; case WindowType::TOOLBOX: pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXToolBox; break; case WindowType::TRISTATEBOX: pNewWindow = VclPtr::Create( pParent, nWinBits ); break; case WindowType::WARNINGBOX: pNewWindow = VclPtr::Create( pParent, nMessBoxStyle, nWinBits, OUString() ); *ppNewComp = new VCLXMessageBox; break; case WindowType::WORKWINDOW: case WindowType::WINDOW: case WindowType::TOOLKIT_FRAMEWINDOW: case WindowType::DOCKINGWINDOW: if ( rDescriptor.Type == css::awt::WindowClass_TOP ) { if (nType == WindowType::DOCKINGWINDOW ) pNewWindow = VclPtr::Create( pParent, nWinBits ); else { if ((pParent == nullptr) && rDescriptor.Parent.is()) { // try to get a system dependent window handle css::uno::Reference< css::awt::XSystemDependentWindowPeer > xSystemDepParent(rDescriptor.Parent, css::uno::UNO_QUERY); if (xSystemDepParent.is()) { sal_Int8 processID[16]; rtl_getGlobalProcessId( reinterpret_cast(processID) ); css::uno::Sequence processIdSeq(processID, 16); css::uno::Any anyHandle = xSystemDepParent->getWindowHandle(processIdSeq, SYSTEM_DEPENDENT_TYPE); // use sal_Int64 here to accommodate all int types // uno::Any shift operator whill upcast if necessary sal_Int64 nWindowHandle = 0; bool bXEmbed = false; bool bUseParentData = true; if( ! (anyHandle >>= nWindowHandle) ) { css::uno::Sequence< css::beans::NamedValue > aProps; if( anyHandle >>= aProps ) { const int nProps = aProps.getLength(); const css::beans::NamedValue* pProps = aProps.getConstArray(); for( int i = 0; i < nProps; i++ ) { if ( pProps[i].Name == "WINDOW" ) pProps[i].Value >>= nWindowHandle; else if ( pProps[i].Name == "XEMBED" ) pProps[i].Value >>= bXEmbed; } } else bUseParentData = false; } if( bUseParentData ) { SystemParentData aParentData; aParentData.nSize = sizeof( aParentData ); #if defined MACOSX aParentData.pView = reinterpret_cast(nWindowHandle); #elif defined ANDROID // Nothing #elif defined IOS // Nothing #elif defined UNX aParentData.aWindow = nWindowHandle; aParentData.bXEmbedSupport = bXEmbed; #elif defined WNT aParentData.hWnd = reinterpret_cast(nWindowHandle); #endif pNewWindow = VclPtr::Create( &aParentData ); } } } if (!pNewWindow) pNewWindow = VclPtr::Create( pParent, nWinBits ); } *ppNewComp = new VCLXTopWindow(); } else if ( rDescriptor.Type == css::awt::WindowClass_CONTAINER ) { if (nType == WindowType::DOCKINGWINDOW ) pNewWindow = VclPtr::Create( pParent, nWinBits ); else pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXContainer; } else { if (nType == WindowType::DOCKINGWINDOW ) pNewWindow = VclPtr::Create( pParent, nWinBits ); else pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXWindow; } break; case WindowType::CONTROL: if ( rDescriptor.WindowServiceName.equalsIgnoreAsciiCase( "tabpagecontainer" ) ) { pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new VCLXTabPageContainer; } else if ( aServiceName == "animatedimages" ) { pNewWindow = VclPtr::Create( pParent, nWinBits ); *ppNewComp = new ::toolkit::AnimatedImagesPeer; } break; default: OSL_ENSURE( false, "VCLXToolkit::ImplCreateWindow: unknown window type!" ); break; } } return pNewWindow; } #ifndef DISABLE_DYNLOADING extern "C" { static void thisModule() {} } #else extern "C" vcl::Window* SAL_CALL CreateWindow( VCLXWindow** ppNewComp, const css::awt::WindowDescriptor* pDescriptor, vcl::Window* pParent, WinBits nWinBits ); #endif css::uno::Reference< css::awt::XWindowPeer > VCLXToolkit::ImplCreateWindow( const css::awt::WindowDescriptor& rDescriptor, MessBoxStyle nForceMessBoxStyle ) { ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); SolarMutexGuard aSolarGuard; css::uno::Reference< css::awt::XWindowPeer > xRef; VclPtr pParent; if ( rDescriptor.Parent.is() ) { VCLXWindow* pParentComponent = VCLXWindow::GetImplementation( rDescriptor.Parent ); // #103939# Don't throw assertion, may be it's a system dependent window, used in ImplCreateWindow. // DBG_ASSERT( pParentComponent, "ParentComponent not valid" ); if ( pParentComponent ) pParent = pParentComponent->GetWindow(); } std::pair aPair = ImplGetWinBits( rDescriptor.WindowAttributes, ImplGetComponentType( rDescriptor.WindowServiceName ) ); WinBits nWinBits = aPair.first; aPair.second |= nForceMessBoxStyle; VCLXWindow* pNewComp = nullptr; vcl::Window* pNewWindow = nullptr; // Try to create the window with SvTools // (do this _before_ creating it on our own: The old mechanism (extended toolkit in SvTools) did it this way, // and we need to stay compatible) // try to load the lib if ( !fnSvtCreateWindow #ifndef DISABLE_DYNLOADING && !hSvToolsLib #endif ) { #ifndef DISABLE_DYNLOADING OUString aLibName(SVT_DLL_NAME); hSvToolsLib = osl_loadModuleRelative( &thisModule, aLibName.pData, SAL_LOADMODULE_DEFAULT ); if ( hSvToolsLib ) { OUString aFunctionName( "CreateWindow" ); fnSvtCreateWindow = reinterpret_cast(osl_getFunctionSymbol( hSvToolsLib, aFunctionName.pData )); } #else fnSvtCreateWindow = CreateWindow; #endif } // ask the SvTool creation function if ( fnSvtCreateWindow ) pNewWindow = fnSvtCreateWindow( &pNewComp, &rDescriptor, pParent, nWinBits ); // if SvTools could not provide a window, create it ourself if ( !pNewWindow ) pNewWindow = ImplCreateWindow( &pNewComp, rDescriptor, pParent, nWinBits, aPair.second ); DBG_ASSERT( pNewWindow, "createWindow: Unknown Component!" ); SAL_INFO_IF( !pNewComp, "toolkit", "createWindow: No special Interface!" ); if ( pNewWindow ) { pNewWindow->SetCreatedWithToolkit( true ); //pNewWindow->SetPosPixel( Point() ); // do not force (0,0) position, keep default pos instead if ( rDescriptor.WindowAttributes & css::awt::WindowAttribute::MINSIZE ) { pNewWindow->SetSizePixel( Size() ); } else if ( rDescriptor.WindowAttributes & css::awt::WindowAttribute::FULLSIZE ) { if ( pParent ) pNewWindow->SetSizePixel( pParent->GetOutputSizePixel() ); } else if ( !VCLUnoHelper::IsZero( rDescriptor.Bounds ) ) { tools::Rectangle aRect = VCLRectangle( rDescriptor.Bounds ); pNewWindow->SetPosSizePixel( aRect.TopLeft(), aRect.GetSize() ); } if ( !pNewComp ) { // Default-Interface xRef = pNewWindow->GetComponentInterface(); } else { xRef = pNewComp; pNewWindow->SetComponentInterface( xRef ); } DBG_ASSERT( pNewWindow->GetComponentInterface( false ) == xRef, "VCLXToolkit::createWindow: did #133706# resurge?" ); if ( rDescriptor.WindowAttributes & css::awt::WindowAttribute::SHOW ) pNewWindow->Show(); } return xRef; } css::uno::Sequence< css::uno::Reference< css::awt::XWindowPeer > > VCLXToolkit::createWindows( const css::uno::Sequence< css::awt::WindowDescriptor >& rDescriptors ) { ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); sal_uInt32 nComponents = rDescriptors.getLength(); css::uno::Sequence< css::uno::Reference< css::awt::XWindowPeer > > aSeq( nComponents ); for ( sal_uInt32 n = 0; n < nComponents; n++ ) { css::awt::WindowDescriptor aDescr = rDescriptors.getConstArray()[n]; if ( aDescr.ParentIndex == -1 ) aDescr.Parent = nullptr; else if ( ( aDescr.ParentIndex >= 0 ) && ( aDescr.ParentIndex < static_cast(n) ) ) aDescr.Parent = aSeq.getConstArray()[aDescr.ParentIndex]; aSeq.getArray()[n] = createWindow( aDescr ); } return aSeq; } // css::awt::XSystemChildFactory css::uno::Reference< css::awt::XWindowPeer > VCLXToolkit::createSystemChild( const css::uno::Any& Parent, const css::uno::Sequence< sal_Int8 >& /*ProcessId*/, sal_Int16 nSystemType ) { VclPtr pChildWindow; if ( nSystemType == SYSTEM_DEPENDENT_TYPE ) { // use sal_Int64 here to accommodate all int types // uno::Any shift operator whill upcast if necessary sal_Int64 nWindowHandle = 0; bool bXEmbed = false; bool bUseParentData = true; if( ! (Parent >>= nWindowHandle) ) { css::uno::Sequence< css::beans::NamedValue > aProps; if( Parent >>= aProps ) { const int nProps = aProps.getLength(); const css::beans::NamedValue* pProps = aProps.getConstArray(); for( int i = 0; i < nProps; i++ ) { if ( pProps[i].Name == "WINDOW" ) pProps[i].Value >>= nWindowHandle; else if ( pProps[i].Name == "XEMBED" ) pProps[i].Value >>= bXEmbed; } } else bUseParentData = false; } if( bUseParentData ) { SystemParentData aParentData; aParentData.nSize = sizeof( aParentData ); #if defined MACOSX aParentData.pView = reinterpret_cast(nWindowHandle); #elif defined ANDROID // Nothing #elif defined IOS // Nothing #elif defined UNX aParentData.aWindow = nWindowHandle; aParentData.bXEmbedSupport = bXEmbed; #elif defined WNT aParentData.hWnd = reinterpret_cast(nWindowHandle); #endif SolarMutexGuard aGuard; try { pChildWindow.reset( VclPtr::Create( &aParentData ) ); } catch ( const css::uno::RuntimeException & ) { // system child window could not be created DBG_UNHANDLED_EXCEPTION("toolkit"); pChildWindow.clear(); } } } else if (nSystemType == css::lang::SystemDependent::SYSTEM_JAVA) { SolarMutexGuard aGuard; pChildWindow.reset(VclPtr::Create(nullptr, Parent)); } css::uno::Reference< css::awt::XWindowPeer > xPeer; if ( pChildWindow ) { VCLXTopWindow* pPeer = new VCLXTopWindow; SolarMutexGuard aGuard; pPeer->SetWindow( pChildWindow ); xPeer = pPeer; } return xPeer; } // css::awt::XMessageBoxFactory css::uno::Reference< css::awt::XMessageBox > SAL_CALL VCLXToolkit::createMessageBox( const css::uno::Reference< css::awt::XWindowPeer >& aParent, css::awt::MessageBoxType eType, ::sal_Int32 aButtons, const OUString& aTitle, const OUString& aMessage ) { css::awt::WindowDescriptor aDescriptor; sal_Int32 nWindowAttributes = css::awt::WindowAttribute::BORDER|css::awt::WindowAttribute::MOVEABLE|css::awt::WindowAttribute::CLOSEABLE; // Map button definitions to window attributes if (( aButtons & 0x0000ffffL ) == css::awt::MessageBoxButtons::BUTTONS_OK ) nWindowAttributes |= css::awt::VclWindowPeerAttribute::OK; else if (( aButtons & 0x0000ffffL ) == css::awt::MessageBoxButtons::BUTTONS_OK_CANCEL ) nWindowAttributes |= css::awt::VclWindowPeerAttribute::OK_CANCEL; else if (( aButtons & 0x0000ffffL ) == css::awt::MessageBoxButtons::BUTTONS_YES_NO ) nWindowAttributes |= css::awt::VclWindowPeerAttribute::YES_NO; else if (( aButtons & 0x0000ffffL ) == css::awt::MessageBoxButtons::BUTTONS_YES_NO_CANCEL ) nWindowAttributes |= css::awt::VclWindowPeerAttribute::YES_NO_CANCEL; else if (( aButtons & 0x0000ffffL ) == css::awt::MessageBoxButtons::BUTTONS_RETRY_CANCEL ) nWindowAttributes |= css::awt::VclWindowPeerAttribute::RETRY_CANCEL; // Map default button definitions to window attributes if (sal_Int32( aButtons & 0xffff0000L ) == css::awt::MessageBoxButtons::DEFAULT_BUTTON_OK ) nWindowAttributes |= css::awt::VclWindowPeerAttribute::DEF_OK; else if (sal_Int32( aButtons & 0xffff0000L ) == css::awt::MessageBoxButtons::DEFAULT_BUTTON_CANCEL ) nWindowAttributes |= css::awt::VclWindowPeerAttribute::DEF_CANCEL; else if (sal_Int32( aButtons & 0xffff0000L ) == css::awt::MessageBoxButtons::DEFAULT_BUTTON_YES ) nWindowAttributes |= css::awt::VclWindowPeerAttribute::DEF_YES; else if (sal_Int32( aButtons & 0xffff0000L ) == css::awt::MessageBoxButtons::DEFAULT_BUTTON_NO ) nWindowAttributes |= css::awt::VclWindowPeerAttribute::DEF_NO; else if (sal_Int32( aButtons & 0xffff0000L ) == css::awt::MessageBoxButtons::DEFAULT_BUTTON_RETRY ) nWindowAttributes |= css::awt::VclWindowPeerAttribute::DEF_RETRY; // No more bits for VclWindowPeerAttribute possible. Mapping must be // done explicitly using VCL methods MessBoxStyle nAddWinBits = MessBoxStyle::NONE; if (( aButtons & 0x0000ffffL ) == css::awt::MessageBoxButtons::BUTTONS_ABORT_IGNORE_RETRY ) nAddWinBits |= MessBoxStyle::AbortRetryIgnore; if ( sal_Int32( aButtons & 0xffff0000L ) == css::awt::MessageBoxButtons::DEFAULT_BUTTON_IGNORE ) nAddWinBits |= MessBoxStyle::DefaultIgnore; rtl::OUString aType; lcl_convertMessageBoxType( aType, eType ); aDescriptor.Type = css::awt::WindowClass_MODALTOP; aDescriptor.WindowServiceName = aType; aDescriptor.ParentIndex = -1; aDescriptor.Parent = aParent; aDescriptor.WindowAttributes = nWindowAttributes; css::uno::Reference< css::awt::XMessageBox > xMsgBox( ImplCreateWindow( aDescriptor, nAddWinBits ), css::uno::UNO_QUERY ); css::uno::Reference< css::awt::XWindow > xWindow( xMsgBox, css::uno::UNO_QUERY ); if ( xMsgBox.is() && xWindow.is() ) { VclPtr pWindow = VCLUnoHelper::GetWindow( xWindow ); if ( pWindow ) { SolarMutexGuard aGuard; xMsgBox->setCaptionText( aTitle ); xMsgBox->setMessageText( aMessage ); } } return xMsgBox; } css::uno::Reference< css::datatransfer::dnd::XDragGestureRecognizer > SAL_CALL VCLXToolkit::getDragGestureRecognizer( const css::uno::Reference< css::awt::XWindow >& window ) { SolarMutexGuard g; VclPtr pWindow = VCLUnoHelper::GetWindow( window ); if( pWindow ) return pWindow->GetDragGestureRecognizer(); return css::uno::Reference< css::datatransfer::dnd::XDragGestureRecognizer >(); } css::uno::Reference< css::datatransfer::dnd::XDragSource > SAL_CALL VCLXToolkit::getDragSource( const css::uno::Reference< css::awt::XWindow >& window ) { SolarMutexGuard g; VclPtr pWindow = VCLUnoHelper::GetWindow( window ); if( pWindow ) return pWindow->GetDragSource(); return css::uno::Reference< css::datatransfer::dnd::XDragSource >(); } css::uno::Reference< css::datatransfer::dnd::XDropTarget > SAL_CALL VCLXToolkit::getDropTarget( const css::uno::Reference< css::awt::XWindow >& window ) { SolarMutexGuard g; VclPtr pWindow = VCLUnoHelper::GetWindow( window ); if( pWindow ) return pWindow->GetDropTarget(); return css::uno::Reference< css::datatransfer::dnd::XDropTarget >(); } css::uno::Reference< css::datatransfer::clipboard::XClipboard > SAL_CALL VCLXToolkit::getClipboard( const OUString& clipboardName ) { if( clipboardName.isEmpty() ) { if( !mxClipboard.is() ) { // remember clipboard here mxClipboard = css::datatransfer::clipboard::SystemClipboard::create( comphelper::getProcessComponentContext()); } return mxClipboard; } else if( clipboardName == "Selection" ) { return mxSelection; } return css::uno::Reference< css::datatransfer::clipboard::XClipboard >(); } // XServiceInfo OUString VCLXToolkit::getImplementationName() { return OUString("stardiv.Toolkit.VCLXToolkit"); } sal_Bool VCLXToolkit::supportsService( const OUString& rServiceName ) { return cppu::supportsService(this, rServiceName); } css::uno::Sequence< OUString > VCLXToolkit::getSupportedServiceNames() { return css::uno::Sequence{ "com.sun.star.awt.Toolkit", "stardiv.vcl.VclToolkit"}; } // css::awt::XExtendedToolkit: // virtual ::sal_Int32 SAL_CALL VCLXToolkit::getTopWindowCount() { return static_cast< ::sal_Int32 >(::Application::GetTopWindowCount()); // XXX numeric overflow } // virtual css::uno::Reference< css::awt::XTopWindow > SAL_CALL VCLXToolkit::getTopWindow(::sal_Int32 nIndex) { vcl::Window * p = ::Application::GetTopWindow(static_cast< long >(nIndex)); // XXX numeric overflow return css::uno::Reference< css::awt::XTopWindow >( p == nullptr ? nullptr : static_cast< css::awt::XWindow * >(p->GetWindowPeer()), css::uno::UNO_QUERY); } // virtual css::uno::Reference< css::awt::XTopWindow > SAL_CALL VCLXToolkit::getActiveTopWindow() { vcl::Window * p = ::Application::GetActiveTopWindow(); return css::uno::Reference< css::awt::XTopWindow >( p == nullptr ? nullptr : static_cast< css::awt::XWindow * >(p->GetWindowPeer()), css::uno::UNO_QUERY); } // virtual void SAL_CALL VCLXToolkit::addTopWindowListener( css::uno::Reference< css::awt::XTopWindowListener > const & rListener) { OSL_ENSURE(rListener.is(), "Null rListener"); ::osl::ClearableMutexGuard aGuard(rBHelper.rMutex); if (rBHelper.bDisposed || rBHelper.bInDispose) { aGuard.clear(); rListener->disposing( css::lang::EventObject( static_cast< ::cppu::OWeakObject * >(this))); } else if (m_aTopWindowListeners.addInterface(rListener) == 1 && !m_bEventListener) { m_bEventListener = true; ::Application::AddEventListener(m_aEventListenerLink); } } // virtual void SAL_CALL VCLXToolkit::removeTopWindowListener( css::uno::Reference< css::awt::XTopWindowListener > const & rListener) { ::osl::MutexGuard aGuard(rBHelper.rMutex); if (!(rBHelper.bDisposed || rBHelper.bInDispose) && m_aTopWindowListeners.removeInterface(rListener) == 0 && m_aFocusListeners.getLength() == 0 && m_bEventListener) { ::Application::RemoveEventListener(m_aEventListenerLink); m_bEventListener = false; } } // virtual void SAL_CALL VCLXToolkit::addKeyHandler( css::uno::Reference< css::awt::XKeyHandler > const & rHandler) { OSL_ENSURE(rHandler.is(), "Null rHandler"); ::osl::ClearableMutexGuard aGuard(rBHelper.rMutex); if (rBHelper.bDisposed || rBHelper.bInDispose) { aGuard.clear(); rHandler->disposing( css::lang::EventObject( static_cast< ::cppu::OWeakObject * >(this))); } else if (m_aKeyHandlers.addInterface(rHandler) == 1 && !m_bKeyListener) { m_bKeyListener = true; ::Application::AddKeyListener(m_aKeyListenerLink); } } // virtual void SAL_CALL VCLXToolkit::removeKeyHandler( css::uno::Reference< css::awt::XKeyHandler > const & rHandler) { ::osl::MutexGuard aGuard(rBHelper.rMutex); if (!(rBHelper.bDisposed || rBHelper.bInDispose) && m_aKeyHandlers.removeInterface(rHandler) == 0 && m_bKeyListener) { ::Application::RemoveKeyListener(m_aKeyListenerLink); m_bKeyListener = false; } } // virtual void SAL_CALL VCLXToolkit::addFocusListener( css::uno::Reference< css::awt::XFocusListener > const & rListener) { OSL_ENSURE(rListener.is(), "Null rListener"); ::osl::ClearableMutexGuard aGuard(rBHelper.rMutex); if (rBHelper.bDisposed || rBHelper.bInDispose) { aGuard.clear(); rListener->disposing( css::lang::EventObject( static_cast< ::cppu::OWeakObject * >(this))); } else if (m_aFocusListeners.addInterface(rListener) == 1 && !m_bEventListener) { m_bEventListener = true; ::Application::AddEventListener(m_aEventListenerLink); } } // virtual void SAL_CALL VCLXToolkit::removeFocusListener( css::uno::Reference< css::awt::XFocusListener > const & rListener) { ::osl::MutexGuard aGuard(rBHelper.rMutex); if (!(rBHelper.bDisposed || rBHelper.bInDispose) && m_aFocusListeners.removeInterface(rListener) == 0 && m_aTopWindowListeners.getLength() == 0 && m_bEventListener) { ::Application::RemoveEventListener(m_aEventListenerLink); m_bEventListener = false; } } // virtual void SAL_CALL VCLXToolkit::fireFocusGained( css::uno::Reference< css::uno::XInterface > const &) { } // virtual void SAL_CALL VCLXToolkit::fireFocusLost( css::uno::Reference< css::uno::XInterface > const &) { } IMPL_LINK(VCLXToolkit, eventListenerHandler, ::VclSimpleEvent&, rEvent, void) { switch (rEvent.GetId()) { case VclEventId::WindowShow: callTopWindowListeners( &rEvent, &css::awt::XTopWindowListener::windowOpened); break; case VclEventId::WindowHide: callTopWindowListeners( &rEvent, &css::awt::XTopWindowListener::windowClosed); break; case VclEventId::WindowActivate: callTopWindowListeners( &rEvent, &css::awt::XTopWindowListener::windowActivated); break; case VclEventId::WindowDeactivate: callTopWindowListeners( &rEvent, &css::awt::XTopWindowListener::windowDeactivated); break; case VclEventId::WindowClose: callTopWindowListeners( &rEvent, &css::awt::XTopWindowListener::windowClosing); break; case VclEventId::WindowGetFocus: callFocusListeners(&rEvent, true); break; case VclEventId::WindowLoseFocus: callFocusListeners(&rEvent, false); break; case VclEventId::WindowMinimize: callTopWindowListeners( &rEvent, &css::awt::XTopWindowListener::windowMinimized); break; case VclEventId::WindowNormalize: callTopWindowListeners( &rEvent, &css::awt::XTopWindowListener::windowNormalized); break; default: break; } } IMPL_LINK(VCLXToolkit, keyListenerHandler, ::VclWindowEvent&, rEvent, bool) { switch (rEvent.GetId()) { case VclEventId::WindowKeyInput: return callKeyHandlers(&rEvent, true); case VclEventId::WindowKeyUp: return callKeyHandlers(&rEvent, false); default: break; } return false; } void VCLXToolkit::callTopWindowListeners( ::VclSimpleEvent const * pEvent, void (SAL_CALL css::awt::XTopWindowListener::* pFn)( css::lang::EventObject const &)) { vcl::Window * pWindow = static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow(); if (pWindow->IsTopWindow()) { std::vector< css::uno::Reference< css::uno::XInterface > > aListeners(m_aTopWindowListeners.getElements()); if (!aListeners.empty()) { css::lang::EventObject aAwtEvent( static_cast< css::awt::XWindow * >(pWindow->GetWindowPeer())); for (css::uno::Reference & i : aListeners) { css::uno::Reference< css::awt::XTopWindowListener > xListener(i, css::uno::UNO_QUERY); try { (xListener.get()->*pFn)(aAwtEvent); } catch (const css::uno::RuntimeException &) { DBG_UNHANDLED_EXCEPTION("toolkit"); } } } } } bool VCLXToolkit::callKeyHandlers(::VclSimpleEvent const * pEvent, bool bPressed) { std::vector< css::uno::Reference< css::uno::XInterface > > aHandlers(m_aKeyHandlers.getElements()); if (!aHandlers.empty()) { vcl::Window * pWindow = static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow(); // See implementation in vclxwindow.cxx for mapping between VCL and UNO AWT event ::KeyEvent * pKeyEvent = static_cast< ::KeyEvent * >( static_cast< ::VclWindowEvent const * >(pEvent)->GetData()); css::awt::KeyEvent aAwtEvent( static_cast< css::awt::XWindow * >(pWindow->GetWindowPeer()), (pKeyEvent->GetKeyCode().IsShift() ? css::awt::KeyModifier::SHIFT : 0) | (pKeyEvent->GetKeyCode().IsMod1() ? css::awt::KeyModifier::MOD1 : 0) | (pKeyEvent->GetKeyCode().IsMod2() ? css::awt::KeyModifier::MOD2 : 0) | (pKeyEvent->GetKeyCode().IsMod3() ? css::awt::KeyModifier::MOD3 : 0), pKeyEvent->GetKeyCode().GetCode(), pKeyEvent->GetCharCode(), sal::static_int_cast< sal_Int16 >( pKeyEvent->GetKeyCode().GetFunction())); for (css::uno::Reference & i : aHandlers) { css::uno::Reference< css::awt::XKeyHandler > xHandler( i, css::uno::UNO_QUERY); try { if (bPressed ? xHandler->keyPressed(aAwtEvent) : xHandler->keyReleased(aAwtEvent)) return true; } catch (const css::uno::RuntimeException &) { DBG_UNHANDLED_EXCEPTION("toolkit"); } } } return false; } void VCLXToolkit::callFocusListeners(::VclSimpleEvent const * pEvent, bool bGained) { vcl::Window * pWindow = static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow(); if (pWindow->IsTopWindow()) { std::vector< css::uno::Reference< css::uno::XInterface > > aListeners(m_aFocusListeners.getElements()); if (!aListeners.empty()) { // Ignore the interior of compound controls when determining the // window that gets the focus next (see implementation in // vclxwindow.cxx for mapping between VCL and UNO AWT event): css::uno::Reference< css::uno::XInterface > xNext; vcl::Window * pFocus = ::Application::GetFocusWindow(); for (vcl::Window * p = pFocus; p != nullptr; p = p->GetParent()) if (!p->IsCompoundControl()) { pFocus = p; break; } if (pFocus != nullptr) xNext = pFocus->GetComponentInterface(); css::awt::FocusEvent aAwtEvent( static_cast< css::awt::XWindow * >(pWindow->GetWindowPeer()), static_cast(pWindow->GetGetFocusFlags()), xNext, false); for (css::uno::Reference & i : aListeners) { css::uno::Reference< css::awt::XFocusListener > xListener( i, css::uno::UNO_QUERY); try { bGained ? xListener->focusGained(aAwtEvent) : xListener->focusLost(aAwtEvent); } catch (const css::uno::RuntimeException &) { DBG_UNHANDLED_EXCEPTION("toolkit"); } } } } } // css::awt::XReschedule: void SAL_CALL VCLXToolkit::reschedule() { SolarMutexGuard aSolarGuard; Application::Reschedule(true); } // css::awt::XToolkitExperimental void SAL_CALL VCLXToolkit::processEventsToIdle() { SolarMutexGuard aSolarGuard; comphelper::ProfileZone aZone("processEvents"); Scheduler::ProcessEventsToIdle(); } sal_Int64 SAL_CALL VCLXToolkit::getOpenGLBufferSwapCounter() { #if HAVE_FEATURE_OPENGL return OpenGLWrapper::getBufferSwapCounter(); #else return 0; #endif } void SAL_CALL VCLXToolkit::setDeterministicScheduling(sal_Bool bDeterministicMode) { SolarMutexGuard aSolarGuard; Scheduler::SetDeterministicMode(bDeterministicMode); } void SAL_CALL VCLXToolkit::pause(sal_Int32 nMilliseconds) { new Pause(nMilliseconds); } void SAL_CALL VCLXToolkit::startRecording() { ::comphelper::ProfileRecording::startRecording(true); } void SAL_CALL VCLXToolkit::stopRecording() { ::comphelper::ProfileRecording::startRecording( false ); } css::uno::Sequence< OUString > VCLXToolkit::getRecordingAndClear() { return ::comphelper::ProfileRecording::getRecordingAndClear(); } // css:awt:XToolkitRobot void SAL_CALL VCLXToolkit::keyPress( const css::awt::KeyEvent & aKeyEvent ) { css::uno::Reference xWindow ( aKeyEvent.Source, css::uno::UNO_QUERY_THROW ); VclPtr pWindow = VCLUnoHelper::GetWindow( xWindow ); if( !pWindow ) throw css::uno::RuntimeException( "invalid event source" ); ::KeyEvent aVCLKeyEvent = VCLUnoHelper::createVCLKeyEvent( aKeyEvent ); ::Application::PostKeyEvent( VclEventId::WindowKeyInput, pWindow, &aVCLKeyEvent ); } void SAL_CALL VCLXToolkit::keyRelease( const css::awt::KeyEvent & aKeyEvent ) { css::uno::Reference xWindow ( aKeyEvent.Source, css::uno::UNO_QUERY_THROW ); VclPtr pWindow = VCLUnoHelper::GetWindow( xWindow ); if( !pWindow ) throw css::uno::RuntimeException( "invalid event source" ); ::KeyEvent aVCLKeyEvent = VCLUnoHelper::createVCLKeyEvent( aKeyEvent ); ::Application::PostKeyEvent( VclEventId::WindowKeyUp, pWindow, &aVCLKeyEvent ); } void SAL_CALL VCLXToolkit::mousePress( const css::awt::MouseEvent & aMouseEvent ) { css::uno::Reference xWindow ( aMouseEvent.Source, css::uno::UNO_QUERY_THROW ); VclPtr pWindow = VCLUnoHelper::GetWindow( xWindow ); if( !pWindow ) throw css::uno::RuntimeException( "invalid event source" ); ::MouseEvent aVCLMouseEvent = VCLUnoHelper::createVCLMouseEvent( aMouseEvent ); ::Application::PostMouseEvent( VclEventId::WindowMouseButtonDown, pWindow, &aVCLMouseEvent ); } void SAL_CALL VCLXToolkit::mouseRelease( const css::awt::MouseEvent & aMouseEvent ) { css::uno::Reference xWindow ( aMouseEvent.Source, css::uno::UNO_QUERY_THROW ); VclPtr pWindow = VCLUnoHelper::GetWindow( xWindow ); if( !pWindow ) throw css::uno::RuntimeException( "invalid event source" ); ::MouseEvent aVCLMouseEvent = VCLUnoHelper::createVCLMouseEvent( aMouseEvent ); ::Application::PostMouseEvent( VclEventId::WindowMouseButtonUp, pWindow, &aVCLMouseEvent ); } void SAL_CALL VCLXToolkit::mouseMove( const css::awt::MouseEvent & aMouseEvent ) { css::uno::Reference xWindow ( aMouseEvent.Source, css::uno::UNO_QUERY_THROW ); VclPtr pWindow = VCLUnoHelper::GetWindow( xWindow ); if( !pWindow ) throw css::uno::RuntimeException( "invalid event source" ); ::MouseEvent aVCLMouseEvent = VCLUnoHelper::createVCLMouseEvent( aMouseEvent ); ::Application::PostMouseEvent( VclEventId::WindowMouseMove, pWindow, &aVCLMouseEvent ); } } extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * stardiv_Toolkit_VCLXToolkit_get_implementation( css::uno::XComponentContext *, css::uno::Sequence const &) { return cppu::acquire(new VCLXToolkit()); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */