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 <svtools/acceleratorexecute.hxx>
22 #include <com/sun/star/frame/ModuleManager.hpp>
23 #include <com/sun/star/frame/Desktop.hpp>
24 #include <com/sun/star/ui/GlobalAcceleratorConfiguration.hpp>
25 #include <com/sun/star/ui/XUIConfigurationManager.hpp>
26 #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
27 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
28 #include <com/sun/star/awt/XTopWindow.hpp>
29 #include <com/sun/star/awt/KeyModifier.hpp>
30 #include <com/sun/star/uno/Sequence.hxx>
31 #include <com/sun/star/beans/PropertyValue.hpp>
32 #include <com/sun/star/lang/DisposedException.hpp>
33 #include <com/sun/star/util/URLTransformer.hpp>
34 #include <toolkit/helper/vclunohelper.hxx>
35 #include <comphelper/processfactory.hxx>
37 #include <vcl/window.hxx>
38 #include <vcl/svapp.hxx>
39 #include <osl/mutex.hxx>
47 class SVT_DLLPRIVATE AsyncAccelExec
51 /** creates a new instance of this class, which can be used
54 This instance can be forced to execute it's internal set request
55 asynchronous. After that it deletes itself !
57 static AsyncAccelExec
* createOnShotInstance(const css::uno::Reference
< css::frame::XDispatch
>& xDispatch
,
58 const css::util::URL
& aURL
);
64 /** @short allow creation of instances of this class
65 by using our factory only!
67 SVT_DLLPRIVATE
AsyncAccelExec(const css::uno::Reference
< css::frame::XDispatch
>& xDispatch
,
68 const css::util::URL
& aURL
);
70 DECL_DLLPRIVATE_LINK(impl_ts_asyncCallback
, void*);
73 vcl::EventPoster m_aAsyncCallback
;
74 css::uno::Reference
< css::frame::XDispatch
> m_xDispatch
;
75 css::util::URL m_aURL
;
79 AcceleratorExecute::AcceleratorExecute()
81 , m_aAsyncCallback(LINK(this, AcceleratorExecute
, impl_ts_asyncCallback
))
85 AcceleratorExecute::~AcceleratorExecute()
91 AcceleratorExecute
* AcceleratorExecute::createAcceleratorHelper()
93 AcceleratorExecute
* pNew
= new AcceleratorExecute();
98 void AcceleratorExecute::init(const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
,
99 const css::uno::Reference
< css::frame::XFrame
>& xEnv
)
101 // SAFE -> ----------------------------------
102 ::osl::ResettableMutexGuard
aLock(m_aLock
);
104 // take over the uno service manager
105 m_xContext
= rxContext
;
107 // specify our internal dispatch provider
108 // frame or desktop?! => document or global config.
109 bool bDesktopIsUsed
= false;
110 m_xDispatcher
= css::uno::Reference
< css::frame::XDispatchProvider
>(xEnv
, css::uno::UNO_QUERY
);
111 if (!m_xDispatcher
.is())
114 // <- SAFE ------------------------------
116 css::uno::Reference
< css::frame::XDispatchProvider
> xDispatcher(css::frame::Desktop::create(rxContext
), css::uno::UNO_QUERY_THROW
);
118 // SAFE -> ------------------------------
121 m_xDispatcher
= xDispatcher
;
122 bDesktopIsUsed
= true;
126 // <- SAFE ----------------------------------
128 // open all needed configuration objects
129 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> xGlobalCfg
;
130 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> xModuleCfg
;
131 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> xDocCfg
;
134 xGlobalCfg
= css::ui::GlobalAcceleratorConfiguration::create(rxContext
);
138 xModuleCfg
= AcceleratorExecute::st_openModuleConfig(rxContext
, xEnv
);
141 css::uno::Reference
< css::frame::XController
> xController
;
142 css::uno::Reference
< css::frame::XModel
> xModel
;
143 xController
= xEnv
->getController();
144 if (xController
.is())
145 xModel
= xController
->getModel();
147 xDocCfg
= AcceleratorExecute::st_openDocConfig(xModel
);
150 // SAFE -> ------------------------------
153 m_xGlobalCfg
= xGlobalCfg
;
154 m_xModuleCfg
= xModuleCfg
;
155 m_xDocCfg
= xDocCfg
;
158 // <- SAFE ----------------------------------
162 bool AcceleratorExecute::execute(const vcl::KeyCode
& aVCLKey
)
164 css::awt::KeyEvent aAWTKey
= AcceleratorExecute::st_VCLKey2AWTKey(aVCLKey
);
165 return execute(aAWTKey
);
169 bool AcceleratorExecute::execute(const css::awt::KeyEvent
& aAWTKey
)
171 OUString sCommand
= impl_ts_findCommand(aAWTKey
);
173 // No Command found? Do nothing! User is not interested on any error handling .-)
174 // or for some reason m_xContext is NULL (which would crash impl_ts_getURLParser()
175 if (sCommand
.isEmpty() || !m_xContext
.is())
180 // SAFE -> ----------------------------------
181 ::osl::ResettableMutexGuard
aLock(m_aLock
);
183 css::uno::Reference
< css::frame::XDispatchProvider
> xProvider
= m_xDispatcher
;
186 // <- SAFE ----------------------------------
188 // convert command in URL structure
189 css::uno::Reference
< css::util::XURLTransformer
> xParser
= impl_ts_getURLParser();
191 aURL
.Complete
= sCommand
;
192 xParser
->parseStrict(aURL
);
194 // ask for dispatch object
195 css::uno::Reference
< css::frame::XDispatch
> xDispatch
= xProvider
->queryDispatch(aURL
, OUString(), 0);
196 bool bRet
= xDispatch
.is();
199 // Note: Such instance can be used one times only and destroy itself afterwards .-)
200 AsyncAccelExec
* pExec
= AsyncAccelExec::createOnShotInstance(xDispatch
, aURL
);
208 css::awt::KeyEvent
AcceleratorExecute::st_VCLKey2AWTKey(const vcl::KeyCode
& aVCLKey
)
210 css::awt::KeyEvent aAWTKey
;
211 aAWTKey
.Modifiers
= 0;
212 aAWTKey
.KeyCode
= (sal_Int16
)aVCLKey
.GetCode();
214 if (aVCLKey
.IsShift())
215 aAWTKey
.Modifiers
|= css::awt::KeyModifier::SHIFT
;
216 if (aVCLKey
.IsMod1())
217 aAWTKey
.Modifiers
|= css::awt::KeyModifier::MOD1
;
218 if (aVCLKey
.IsMod2())
219 aAWTKey
.Modifiers
|= css::awt::KeyModifier::MOD2
;
220 if (aVCLKey
.IsMod3())
221 aAWTKey
.Modifiers
|= css::awt::KeyModifier::MOD3
;
226 vcl::KeyCode
AcceleratorExecute::st_AWTKey2VCLKey(const css::awt::KeyEvent
& aAWTKey
)
228 bool bShift
= ((aAWTKey
.Modifiers
& css::awt::KeyModifier::SHIFT
) == css::awt::KeyModifier::SHIFT
);
229 bool bMod1
= ((aAWTKey
.Modifiers
& css::awt::KeyModifier::MOD1
) == css::awt::KeyModifier::MOD1
);
230 bool bMod2
= ((aAWTKey
.Modifiers
& css::awt::KeyModifier::MOD2
) == css::awt::KeyModifier::MOD2
);
231 bool bMod3
= ((aAWTKey
.Modifiers
& css::awt::KeyModifier::MOD3
) == css::awt::KeyModifier::MOD3
);
232 sal_uInt16 nKey
= (sal_uInt16
)aAWTKey
.KeyCode
;
234 return vcl::KeyCode(nKey
, bShift
, bMod1
, bMod2
, bMod3
);
237 OUString
AcceleratorExecute::findCommand(const css::awt::KeyEvent
& aKey
)
239 return impl_ts_findCommand(aKey
);
242 OUString
AcceleratorExecute::impl_ts_findCommand(const css::awt::KeyEvent
& aKey
)
244 // SAFE -> ----------------------------------
245 ::osl::ResettableMutexGuard
aLock(m_aLock
);
247 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> xGlobalCfg
= m_xGlobalCfg
;
248 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> xModuleCfg
= m_xModuleCfg
;
249 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> xDocCfg
= m_xDocCfg
;
252 // <- SAFE ----------------------------------
259 sCommand
= xDocCfg
->getCommandByKeyEvent(aKey
);
260 if (!sCommand
.isEmpty())
263 catch(const css::container::NoSuchElementException
&)
269 sCommand
= xModuleCfg
->getCommandByKeyEvent(aKey
);
270 if (!sCommand
.isEmpty())
273 catch(const css::container::NoSuchElementException
&)
279 sCommand
= xGlobalCfg
->getCommandByKeyEvent(aKey
);
280 if (!sCommand
.isEmpty())
283 catch(const css::container::NoSuchElementException
&)
286 // fall back to functional key codes
287 if( aKey
.Modifiers
== 0 )
289 switch( aKey
.KeyCode
)
291 case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE
:
292 return OUString( ".uno:DelToStartOfLine" );
293 case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE
:
294 return OUString( ".uno:DelToEndOfLine" );
295 case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH
:
296 return OUString( ".uno:DelToStartOfPara" );
297 case com::sun::star::awt::Key::DELETE_TO_END_OF_PARAGRAPH
:
298 return OUString( ".uno:DelToEndOfPara" );
299 case com::sun::star::awt::Key::DELETE_WORD_BACKWARD
:
300 return OUString( ".uno:DelToStartOfWord" );
301 case com::sun::star::awt::Key::DELETE_WORD_FORWARD
:
302 return OUString( ".uno:DelToEndOfWord" );
303 case com::sun::star::awt::Key::INSERT_LINEBREAK
:
304 return OUString( ".uno:InsertLinebreak" );
305 case com::sun::star::awt::Key::INSERT_PARAGRAPH
:
306 return OUString( ".uno:InsertPara" );
307 case com::sun::star::awt::Key::MOVE_WORD_BACKWARD
:
308 return OUString( ".uno:GoToPrevWord" );
309 case com::sun::star::awt::Key::MOVE_WORD_FORWARD
:
310 return OUString( ".uno:GoToNextWord" );
311 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE
:
312 return OUString( ".uno:GoToStartOfLine" );
313 case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE
:
314 return OUString( ".uno:GoToEndOfLine" );
315 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH
:
316 return OUString( ".uno:GoToStartOfPara" );
317 case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH
:
318 return OUString( ".uno:GoToEndOfPara" );
319 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT
:
320 return OUString( ".uno:GoToStartOfDoc" );
321 case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT
:
322 return OUString( ".uno:GoToEndOfDoc" );
323 case com::sun::star::awt::Key::SELECT_BACKWARD
:
324 return OUString( ".uno:CharLeftSel" );
325 case com::sun::star::awt::Key::SELECT_FORWARD
:
326 return OUString( ".uno:CharRightSel" );
327 case com::sun::star::awt::Key::SELECT_WORD_BACKWARD
:
328 return OUString( ".uno:WordLeftSel" );
329 case com::sun::star::awt::Key::SELECT_WORD_FORWARD
:
330 return OUString( ".uno:WordRightSel" );
331 case com::sun::star::awt::Key::SELECT_WORD
:
332 return OUString( ".uno:SelectWord" );
333 case com::sun::star::awt::Key::SELECT_LINE
:
335 case com::sun::star::awt::Key::SELECT_PARAGRAPH
:
336 return OUString( ".uno:SelectText" );
337 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE
:
338 return OUString( ".uno:StartOfLineSel" );
339 case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE
:
340 return OUString( ".uno:EndOfLineSel" );
341 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH
:
342 return OUString( ".uno:StartOfParaSel" );
343 case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH
:
344 return OUString( ".uno:EndOfParaSel" );
345 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT
:
346 return OUString( ".uno:StartOfDocumentSel" );
347 case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT
:
348 return OUString( ".uno:EndOfDocumentSel" );
349 case com::sun::star::awt::Key::SELECT_ALL
:
350 return OUString( ".uno:SelectAll" );
360 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> AcceleratorExecute::st_openModuleConfig(const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
,
361 const css::uno::Reference
< css::frame::XFrame
>& xFrame
)
363 css::uno::Reference
< css::frame::XModuleManager2
> xModuleDetection(
364 css::frame::ModuleManager::create(rxContext
));
369 sModule
= xModuleDetection
->identify(xFrame
);
371 catch(const css::uno::RuntimeException
&rEx
)
372 { (void) rEx
; throw; }
373 catch(const css::uno::Exception
&)
374 { return css::uno::Reference
< css::ui::XAcceleratorConfiguration
>(); }
376 css::uno::Reference
< css::ui::XModuleUIConfigurationManagerSupplier
> xUISupplier(
377 css::ui::theModuleUIConfigurationManagerSupplier::get(rxContext
) );
379 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> xAccCfg
;
382 css::uno::Reference
< css::ui::XUIConfigurationManager
> xUIManager
= xUISupplier
->getUIConfigurationManager(sModule
);
383 xAccCfg
= xUIManager
->getShortCutManager();
385 catch(const css::container::NoSuchElementException
&)
391 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> AcceleratorExecute::st_openDocConfig(const css::uno::Reference
< css::frame::XModel
>& xModel
)
393 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> xAccCfg
;
394 css::uno::Reference
< css::ui::XUIConfigurationManagerSupplier
> xUISupplier(xModel
, css::uno::UNO_QUERY
);
395 if (xUISupplier
.is())
397 css::uno::Reference
< css::ui::XUIConfigurationManager
> xUIManager
= xUISupplier
->getUIConfigurationManager();
398 xAccCfg
= xUIManager
->getShortCutManager();
404 css::uno::Reference
< css::util::XURLTransformer
> AcceleratorExecute::impl_ts_getURLParser()
406 // SAFE -> ----------------------------------
407 ::osl::ResettableMutexGuard
aLock(m_aLock
);
409 if (m_xURLParser
.is())
411 css::uno::Reference
< css::uno::XComponentContext
> xContext
= m_xContext
;
414 // <- SAFE ----------------------------------
416 css::uno::Reference
< css::util::XURLTransformer
> xParser
= css::util::URLTransformer::create( xContext
);
418 // SAFE -> ----------------------------------
420 m_xURLParser
= xParser
;
422 // <- SAFE ----------------------------------
428 IMPL_LINK_NOARG(AcceleratorExecute
, impl_ts_asyncCallback
)
430 // replaced by AsyncAccelExec!
435 AsyncAccelExec::AsyncAccelExec(const css::uno::Reference
< css::frame::XDispatch
>& xDispatch
,
436 const css::util::URL
& aURL
)
437 : m_aAsyncCallback(LINK(this, AsyncAccelExec
, impl_ts_asyncCallback
))
438 , m_xDispatch (xDispatch
)
444 AsyncAccelExec
* AsyncAccelExec::createOnShotInstance(const css::uno::Reference
< css::frame::XDispatch
>& xDispatch
,
445 const css::util::URL
& aURL
)
447 AsyncAccelExec
* pExec
= new AsyncAccelExec(xDispatch
, aURL
);
452 void AsyncAccelExec::execAsync()
454 m_aAsyncCallback
.Post(0);
458 IMPL_LINK_NOARG(AsyncAccelExec
, impl_ts_asyncCallback
)
460 if (! m_xDispatch
.is())
465 m_xDispatch
->dispatch(m_aURL
, css::uno::Sequence
< css::beans::PropertyValue
>());
467 catch(const css::lang::DisposedException
&)
469 catch(const css::uno::RuntimeException
& )
471 catch(const css::uno::Exception
&)
481 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */