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/ModuleUIConfigurationManagerSupplier.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>
46 //-----------------------------------------------
47 class SVT_DLLPRIVATE AsyncAccelExec
50 //---------------------------------------
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
);
63 //---------------------------------------
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
;
78 //-----------------------------------------------
79 AcceleratorExecute::AcceleratorExecute()
81 , m_aAsyncCallback(LINK(this, AcceleratorExecute
, impl_ts_asyncCallback
))
85 //-----------------------------------------------
86 AcceleratorExecute::AcceleratorExecute(const AcceleratorExecute
&)
88 , m_aAsyncCallback(LINK(this, AcceleratorExecute
, impl_ts_asyncCallback
))
90 // copy construction sint supported in real ...
91 // but we need this ctor to init our async callback ...
94 //-----------------------------------------------
95 AcceleratorExecute::~AcceleratorExecute()
100 //-----------------------------------------------
101 AcceleratorExecute
* AcceleratorExecute::createAcceleratorHelper()
103 AcceleratorExecute
* pNew
= new AcceleratorExecute();
107 //-----------------------------------------------
108 void AcceleratorExecute::init(const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
,
109 const css::uno::Reference
< css::frame::XFrame
>& xEnv
)
111 // SAFE -> ----------------------------------
112 ::osl::ResettableMutexGuard
aLock(m_aLock
);
114 // take over the uno service manager
115 m_xContext
= rxContext
;
117 // specify our internal dispatch provider
118 // frame or desktop?! => document or global config.
119 sal_Bool bDesktopIsUsed
= sal_False
;
120 m_xDispatcher
= css::uno::Reference
< css::frame::XDispatchProvider
>(xEnv
, css::uno::UNO_QUERY
);
121 if (!m_xDispatcher
.is())
124 // <- SAFE ------------------------------
126 css::uno::Reference
< css::frame::XDispatchProvider
> xDispatcher(css::frame::Desktop::create(rxContext
), css::uno::UNO_QUERY_THROW
);
128 // SAFE -> ------------------------------
131 m_xDispatcher
= xDispatcher
;
132 bDesktopIsUsed
= sal_True
;
136 // <- SAFE ----------------------------------
138 // open all needed configuration objects
139 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> xGlobalCfg
;
140 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> xModuleCfg
;
141 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> xDocCfg
;
144 xGlobalCfg
= css::ui::GlobalAcceleratorConfiguration::create(rxContext
);
148 xModuleCfg
= AcceleratorExecute::st_openModuleConfig(rxContext
, xEnv
);
151 css::uno::Reference
< css::frame::XController
> xController
;
152 css::uno::Reference
< css::frame::XModel
> xModel
;
153 xController
= xEnv
->getController();
154 if (xController
.is())
155 xModel
= xController
->getModel();
157 xDocCfg
= AcceleratorExecute::st_openDocConfig(xModel
);
160 // SAFE -> ------------------------------
163 m_xGlobalCfg
= xGlobalCfg
;
164 m_xModuleCfg
= xModuleCfg
;
165 m_xDocCfg
= xDocCfg
;
168 // <- SAFE ----------------------------------
171 //-----------------------------------------------
172 sal_Bool
AcceleratorExecute::execute(const KeyCode
& aVCLKey
)
174 css::awt::KeyEvent aAWTKey
= AcceleratorExecute::st_VCLKey2AWTKey(aVCLKey
);
175 return execute(aAWTKey
);
178 //-----------------------------------------------
179 sal_Bool
AcceleratorExecute::execute(const css::awt::KeyEvent
& aAWTKey
)
181 OUString sCommand
= impl_ts_findCommand(aAWTKey
);
183 // No Command found? Do nothing! User isnt interested on any error handling .-)
184 if (sCommand
.isEmpty())
187 // SAFE -> ----------------------------------
188 ::osl::ResettableMutexGuard
aLock(m_aLock
);
190 css::uno::Reference
< css::frame::XDispatchProvider
> xProvider
= m_xDispatcher
;
193 // <- SAFE ----------------------------------
195 // convert command in URL structure
196 css::uno::Reference
< css::util::XURLTransformer
> xParser
= impl_ts_getURLParser();
198 aURL
.Complete
= sCommand
;
199 xParser
->parseStrict(aURL
);
201 // ask for dispatch object
202 css::uno::Reference
< css::frame::XDispatch
> xDispatch
= xProvider
->queryDispatch(aURL
, OUString(), 0);
203 sal_Bool bRet
= xDispatch
.is();
206 // Note: Such instance can be used one times only and destroy itself afterwards .-)
207 AsyncAccelExec
* pExec
= AsyncAccelExec::createOnShotInstance(xDispatch
, aURL
);
214 //-----------------------------------------------
215 css::awt::KeyEvent
AcceleratorExecute::st_VCLKey2AWTKey(const KeyCode
& aVCLKey
)
217 css::awt::KeyEvent aAWTKey
;
218 aAWTKey
.Modifiers
= 0;
219 aAWTKey
.KeyCode
= (sal_Int16
)aVCLKey
.GetCode();
221 if (aVCLKey
.IsShift())
222 aAWTKey
.Modifiers
|= css::awt::KeyModifier::SHIFT
;
223 if (aVCLKey
.IsMod1())
224 aAWTKey
.Modifiers
|= css::awt::KeyModifier::MOD1
;
225 if (aVCLKey
.IsMod2())
226 aAWTKey
.Modifiers
|= css::awt::KeyModifier::MOD2
;
227 if (aVCLKey
.IsMod3())
228 aAWTKey
.Modifiers
|= css::awt::KeyModifier::MOD3
;
232 //-----------------------------------------------
233 KeyCode
AcceleratorExecute::st_AWTKey2VCLKey(const css::awt::KeyEvent
& aAWTKey
)
235 sal_Bool bShift
= ((aAWTKey
.Modifiers
& css::awt::KeyModifier::SHIFT
) == css::awt::KeyModifier::SHIFT
);
236 sal_Bool bMod1
= ((aAWTKey
.Modifiers
& css::awt::KeyModifier::MOD1
) == css::awt::KeyModifier::MOD1
);
237 sal_Bool bMod2
= ((aAWTKey
.Modifiers
& css::awt::KeyModifier::MOD2
) == css::awt::KeyModifier::MOD2
);
238 sal_Bool bMod3
= ((aAWTKey
.Modifiers
& css::awt::KeyModifier::MOD3
) == css::awt::KeyModifier::MOD3
);
239 sal_uInt16 nKey
= (sal_uInt16
)aAWTKey
.KeyCode
;
241 return KeyCode(nKey
, bShift
, bMod1
, bMod2
, bMod3
);
243 //-----------------------------------------------
244 OUString
AcceleratorExecute::findCommand(const css::awt::KeyEvent
& aKey
)
246 return impl_ts_findCommand(aKey
);
248 //-----------------------------------------------
249 OUString
AcceleratorExecute::impl_ts_findCommand(const css::awt::KeyEvent
& aKey
)
251 // SAFE -> ----------------------------------
252 ::osl::ResettableMutexGuard
aLock(m_aLock
);
254 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> xGlobalCfg
= m_xGlobalCfg
;
255 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> xModuleCfg
= m_xModuleCfg
;
256 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> xDocCfg
= m_xDocCfg
;
259 // <- SAFE ----------------------------------
266 sCommand
= xDocCfg
->getCommandByKeyEvent(aKey
);
267 if (!sCommand
.isEmpty())
270 catch(const css::container::NoSuchElementException
&)
276 sCommand
= xModuleCfg
->getCommandByKeyEvent(aKey
);
277 if (!sCommand
.isEmpty())
280 catch(const css::container::NoSuchElementException
&)
286 sCommand
= xGlobalCfg
->getCommandByKeyEvent(aKey
);
287 if (!sCommand
.isEmpty())
290 catch(const css::container::NoSuchElementException
&)
293 // fall back to functional key codes
294 if( aKey
.Modifiers
== 0 )
296 switch( aKey
.KeyCode
)
298 case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE
:
299 return OUString( ".uno:DelToStartOfLine" );
300 case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE
:
301 return OUString( ".uno:DelToEndOfLine" );
302 case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH
:
303 return OUString( ".uno:DelToStartOfPara" );
304 case com::sun::star::awt::Key::DELETE_TO_END_OF_PARAGRAPH
:
305 return OUString( ".uno:DelToEndOfPara" );
306 case com::sun::star::awt::Key::DELETE_WORD_BACKWARD
:
307 return OUString( ".uno:DelToStartOfWord" );
308 case com::sun::star::awt::Key::DELETE_WORD_FORWARD
:
309 return OUString( ".uno:DelToEndOfWord" );
310 case com::sun::star::awt::Key::INSERT_LINEBREAK
:
311 return OUString( ".uno:InsertLinebreak" );
312 case com::sun::star::awt::Key::INSERT_PARAGRAPH
:
313 return OUString( ".uno:InsertPara" );
314 case com::sun::star::awt::Key::MOVE_WORD_BACKWARD
:
315 return OUString( ".uno:GoToPrevWord" );
316 case com::sun::star::awt::Key::MOVE_WORD_FORWARD
:
317 return OUString( ".uno:GoToNextWord" );
318 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE
:
319 return OUString( ".uno:GoToStartOfLine" );
320 case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE
:
321 return OUString( ".uno:GoToEndOfLine" );
322 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH
:
323 return OUString( ".uno:GoToStartOfPara" );
324 case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH
:
325 return OUString( ".uno:GoToEndOfPara" );
326 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT
:
327 return OUString( ".uno:GoToStartOfDoc" );
328 case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT
:
329 return OUString( ".uno:GoToEndOfDoc" );
330 case com::sun::star::awt::Key::SELECT_BACKWARD
:
331 return OUString( ".uno:CharLeftSel" );
332 case com::sun::star::awt::Key::SELECT_FORWARD
:
333 return OUString( ".uno:CharRightSel" );
334 case com::sun::star::awt::Key::SELECT_WORD_BACKWARD
:
335 return OUString( ".uno:WordLeftSel" );
336 case com::sun::star::awt::Key::SELECT_WORD_FORWARD
:
337 return OUString( ".uno:WordRightSel" );
338 case com::sun::star::awt::Key::SELECT_WORD
:
339 return OUString( ".uno:SelectWord" );
340 case com::sun::star::awt::Key::SELECT_LINE
:
342 case com::sun::star::awt::Key::SELECT_PARAGRAPH
:
343 return OUString( ".uno:SelectText" );
344 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE
:
345 return OUString( ".uno:StartOfLineSel" );
346 case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE
:
347 return OUString( ".uno:EndOfLineSel" );
348 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH
:
349 return OUString( ".uno:StartOfParaSel" );
350 case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH
:
351 return OUString( ".uno:EndOfParaSel" );
352 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT
:
353 return OUString( ".uno:StartOfDocumentSel" );
354 case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT
:
355 return OUString( ".uno:EndOfDocumentSel" );
356 case com::sun::star::awt::Key::SELECT_ALL
:
357 return OUString( ".uno:SelectAll" );
366 //-----------------------------------------------
367 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> AcceleratorExecute::st_openModuleConfig(const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
,
368 const css::uno::Reference
< css::frame::XFrame
>& xFrame
)
370 css::uno::Reference
< css::frame::XModuleManager2
> xModuleDetection(
371 css::frame::ModuleManager::create(rxContext
));
376 sModule
= xModuleDetection
->identify(xFrame
);
378 catch(const css::uno::RuntimeException
&rEx
)
379 { (void) rEx
; throw; }
380 catch(const css::uno::Exception
&)
381 { return css::uno::Reference
< css::ui::XAcceleratorConfiguration
>(); }
383 css::uno::Reference
< css::ui::XModuleUIConfigurationManagerSupplier
> xUISupplier(
384 css::ui::ModuleUIConfigurationManagerSupplier::create(rxContext
) );
386 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> xAccCfg
;
389 css::uno::Reference
< css::ui::XUIConfigurationManager
> xUIManager
= xUISupplier
->getUIConfigurationManager(sModule
);
390 xAccCfg
= css::uno::Reference
< css::ui::XAcceleratorConfiguration
>(xUIManager
->getShortCutManager(), css::uno::UNO_QUERY_THROW
);
392 catch(const css::container::NoSuchElementException
&)
397 //-----------------------------------------------
398 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> AcceleratorExecute::st_openDocConfig(const css::uno::Reference
< css::frame::XModel
>& xModel
)
400 css::uno::Reference
< css::ui::XAcceleratorConfiguration
> xAccCfg
;
401 css::uno::Reference
< css::ui::XUIConfigurationManagerSupplier
> xUISupplier(xModel
, css::uno::UNO_QUERY
);
402 if (xUISupplier
.is())
404 css::uno::Reference
< css::ui::XUIConfigurationManager
> xUIManager
= xUISupplier
->getUIConfigurationManager();
405 xAccCfg
.set(xUIManager
->getShortCutManager(), css::uno::UNO_QUERY_THROW
);
410 //-----------------------------------------------
411 css::uno::Reference
< css::util::XURLTransformer
> AcceleratorExecute::impl_ts_getURLParser()
413 // SAFE -> ----------------------------------
414 ::osl::ResettableMutexGuard
aLock(m_aLock
);
416 if (m_xURLParser
.is())
418 css::uno::Reference
< css::uno::XComponentContext
> xContext
= m_xContext
;
421 // <- SAFE ----------------------------------
423 css::uno::Reference
< css::util::XURLTransformer
> xParser
= css::util::URLTransformer::create( xContext
);
425 // SAFE -> ----------------------------------
427 m_xURLParser
= xParser
;
429 // <- SAFE ----------------------------------
434 //-----------------------------------------------
435 IMPL_LINK_NOARG(AcceleratorExecute
, impl_ts_asyncCallback
)
437 // replaced by AsyncAccelExec!
441 //-----------------------------------------------
442 AsyncAccelExec::AsyncAccelExec(const css::uno::Reference
< css::frame::XDispatch
>& xDispatch
,
443 const css::util::URL
& aURL
)
444 : m_aAsyncCallback(LINK(this, AsyncAccelExec
, impl_ts_asyncCallback
))
445 , m_xDispatch (xDispatch
)
450 //-----------------------------------------------
451 AsyncAccelExec
* AsyncAccelExec::createOnShotInstance(const css::uno::Reference
< css::frame::XDispatch
>& xDispatch
,
452 const css::util::URL
& aURL
)
454 AsyncAccelExec
* pExec
= new AsyncAccelExec(xDispatch
, aURL
);
458 //-----------------------------------------------
459 void AsyncAccelExec::execAsync()
461 m_aAsyncCallback
.Post(0);
464 //-----------------------------------------------
465 IMPL_LINK(AsyncAccelExec
, impl_ts_asyncCallback
, void*,)
467 if (! m_xDispatch
.is())
472 m_xDispatch
->dispatch(m_aURL
, css::uno::Sequence
< css::beans::PropertyValue
>());
474 catch(const css::lang::DisposedException
&)
476 catch(const css::uno::RuntimeException
& )
478 catch(const css::uno::Exception
&)
488 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */