nss: upgrade to release 3.73
[LibreOffice.git] / svtools / source / misc / acceleratorexecute.cxx
blob0a36c491f556354317b3c7cf4f6eee20d85c67d8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <memory>
21 #include <svtools/acceleratorexecute.hxx>
23 #include <com/sun/star/frame/ModuleManager.hpp>
24 #include <com/sun/star/frame/Desktop.hpp>
25 #include <com/sun/star/ui/GlobalAcceleratorConfiguration.hpp>
26 #include <com/sun/star/ui/XUIConfigurationManager.hpp>
27 #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
28 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.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/util/URLTransformer.hpp>
33 #include <cppuhelper/implbase.hxx>
35 #include <vcl/evntpost.hxx>
36 #include <sal/log.hxx>
37 #include <vcl/lok.hxx>
38 #include <vcl/window.hxx>
39 #include <vcl/svapp.hxx>
40 #include <osl/mutex.hxx>
42 namespace svt
45 namespace {
47 class AsyncAccelExec : public cppu::WeakImplHelper<css::lang::XEventListener>
49 private:
50 css::uno::Reference<css::lang::XComponent> m_xFrame;
51 css::uno::Reference< css::frame::XDispatch > m_xDispatch;
52 css::util::URL m_aURL;
53 vcl::EventPoster m_aAsyncCallback;
54 public:
56 /** creates a new instance of this class, which can be used
57 one times only!
59 This instance can be forced to execute its internal set request
60 asynchronous. After that it deletes itself!
62 static AsyncAccelExec* createOneShotInstance(const css::uno::Reference<css::lang::XComponent>& xFrame,
63 const css::uno::Reference<css::frame::XDispatch>& xDispatch,
64 const css::util::URL& rURL);
66 void execAsync();
67 private:
69 virtual void SAL_CALL disposing(const css::lang::EventObject&) override
71 m_xFrame->removeEventListener(this);
72 m_xFrame.clear();
73 m_xDispatch.clear();
76 /** @short allow creation of instances of this class
77 by using our factory only!
79 AsyncAccelExec(const css::uno::Reference<css::lang::XComponent>& xFrame,
80 const css::uno::Reference< css::frame::XDispatch >& xDispatch,
81 const css::util::URL& rURL);
83 DECL_LINK(impl_ts_asyncCallback, LinkParamNone*, void);
88 AcceleratorExecute::AcceleratorExecute()
89 : TMutexInit()
93 AcceleratorExecute::~AcceleratorExecute()
95 // does nothing real
99 std::unique_ptr<AcceleratorExecute> AcceleratorExecute::createAcceleratorHelper()
101 return std::unique_ptr<AcceleratorExecute>(new AcceleratorExecute);
105 void AcceleratorExecute::init(const css::uno::Reference< css::uno::XComponentContext >& rxContext,
106 const css::uno::Reference< css::frame::XFrame >& xEnv )
108 // SAFE -> ----------------------------------
109 ::osl::ResettableMutexGuard aLock(m_aLock);
111 // take over the uno service manager
112 m_xContext = rxContext;
114 // specify our internal dispatch provider
115 // frame or desktop?! => document or global config.
116 bool bDesktopIsUsed = false;
117 m_xDispatcher.set(xEnv, css::uno::UNO_QUERY);
118 if (!m_xDispatcher.is())
120 aLock.clear();
121 // <- SAFE ------------------------------
123 css::uno::Reference< css::frame::XDispatchProvider > xDispatcher(css::frame::Desktop::create(rxContext), css::uno::UNO_QUERY_THROW);
125 // SAFE -> ------------------------------
126 aLock.reset();
128 m_xDispatcher = xDispatcher;
129 bDesktopIsUsed = true;
132 aLock.clear();
133 // <- SAFE ----------------------------------
135 // open all needed configuration objects
136 css::uno::Reference< css::ui::XAcceleratorConfiguration > xGlobalCfg;
137 css::uno::Reference< css::ui::XAcceleratorConfiguration > xModuleCfg;
138 css::uno::Reference< css::ui::XAcceleratorConfiguration > xDocCfg ;
140 // global cfg
141 xGlobalCfg = css::ui::GlobalAcceleratorConfiguration::create(rxContext);
142 if (!bDesktopIsUsed)
144 // module cfg
145 xModuleCfg = AcceleratorExecute::st_openModuleConfig(rxContext, xEnv);
147 // doc cfg
148 css::uno::Reference< css::frame::XController > xController;
149 css::uno::Reference< css::frame::XModel > xModel;
150 xController = xEnv->getController();
151 if (xController.is())
152 xModel = xController->getModel();
153 if (xModel.is())
154 xDocCfg = AcceleratorExecute::st_openDocConfig(xModel);
157 // SAFE -> ------------------------------
158 aLock.reset();
160 m_xGlobalCfg = xGlobalCfg;
161 m_xModuleCfg = xModuleCfg;
162 m_xDocCfg = xDocCfg ;
164 aLock.clear();
165 // <- SAFE ----------------------------------
169 bool AcceleratorExecute::execute(const vcl::KeyCode& aVCLKey)
171 css::awt::KeyEvent aAWTKey = AcceleratorExecute::st_VCLKey2AWTKey(aVCLKey);
172 return execute(aAWTKey);
176 bool AcceleratorExecute::execute(const css::awt::KeyEvent& aAWTKey)
178 OUString sCommand = impl_ts_findCommand(aAWTKey);
180 // No Command found? Do nothing! User is not interested on any error handling .-)
181 // or for some reason m_xContext is NULL (which would crash impl_ts_getURLParser()
182 if (sCommand.isEmpty() || !m_xContext.is())
184 return false;
187 // SAFE -> ----------------------------------
188 osl::ClearableMutexGuard aLock(m_aLock);
190 css::uno::Reference< css::frame::XDispatchProvider > xProvider = m_xDispatcher;
192 aLock.clear();
193 // <- SAFE ----------------------------------
195 // convert command in URL structure
196 css::uno::Reference< css::util::XURLTransformer > xParser = impl_ts_getURLParser();
197 css::util::URL aURL;
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 bool bRet = xDispatch.is();
204 if ( bRet )
206 // Note: Such instance can be used one times only and destroy itself afterwards .-)
207 css::uno::Reference<css::lang::XComponent> xFrame(xProvider, css::uno::UNO_QUERY);
208 if (vcl::lok::isUnipoll())
209 { // tdf#130382 - all synchronous really.
210 try {
211 xDispatch->dispatch (aURL, css::uno::Sequence< css::beans::PropertyValue >());
213 catch(const css::uno::Exception&ev)
215 SAL_INFO("svtools", "exception on key emission: " << ev.Message);
218 else
220 AsyncAccelExec* pExec = AsyncAccelExec::createOneShotInstance(xFrame, xDispatch, aURL);
221 pExec->execAsync();
225 return bRet;
229 css::awt::KeyEvent AcceleratorExecute::st_VCLKey2AWTKey(const vcl::KeyCode& aVCLKey)
231 css::awt::KeyEvent aAWTKey;
232 aAWTKey.Modifiers = 0;
233 aAWTKey.KeyCode = static_cast<sal_Int16>(aVCLKey.GetCode());
235 if (aVCLKey.IsShift())
236 aAWTKey.Modifiers |= css::awt::KeyModifier::SHIFT;
237 if (aVCLKey.IsMod1())
238 aAWTKey.Modifiers |= css::awt::KeyModifier::MOD1;
239 if (aVCLKey.IsMod2())
240 aAWTKey.Modifiers |= css::awt::KeyModifier::MOD2;
241 if (aVCLKey.IsMod3())
242 aAWTKey.Modifiers |= css::awt::KeyModifier::MOD3;
243 return aAWTKey;
247 vcl::KeyCode AcceleratorExecute::st_AWTKey2VCLKey(const css::awt::KeyEvent& aAWTKey)
249 bool bShift = ((aAWTKey.Modifiers & css::awt::KeyModifier::SHIFT) == css::awt::KeyModifier::SHIFT );
250 bool bMod1 = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD1 ) == css::awt::KeyModifier::MOD1 );
251 bool bMod2 = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD2 ) == css::awt::KeyModifier::MOD2 );
252 bool bMod3 = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD3 ) == css::awt::KeyModifier::MOD3 );
253 sal_uInt16 nKey = static_cast<sal_uInt16>(aAWTKey.KeyCode);
255 return vcl::KeyCode(nKey, bShift, bMod1, bMod2, bMod3);
258 OUString AcceleratorExecute::findCommand(const css::awt::KeyEvent& aKey)
260 return impl_ts_findCommand(aKey);
263 OUString AcceleratorExecute::impl_ts_findCommand(const css::awt::KeyEvent& aKey)
265 // SAFE -> ----------------------------------
266 osl::ClearableMutexGuard aLock(m_aLock);
268 css::uno::Reference< css::ui::XAcceleratorConfiguration > xGlobalCfg = m_xGlobalCfg;
269 css::uno::Reference< css::ui::XAcceleratorConfiguration > xModuleCfg = m_xModuleCfg;
270 css::uno::Reference< css::ui::XAcceleratorConfiguration > xDocCfg = m_xDocCfg ;
272 aLock.clear();
273 // <- SAFE ----------------------------------
275 OUString sCommand;
279 if (xDocCfg.is())
280 sCommand = xDocCfg->getCommandByKeyEvent(aKey);
281 if (!sCommand.isEmpty())
282 return sCommand;
284 catch(const css::container::NoSuchElementException&)
289 if (xModuleCfg.is())
290 sCommand = xModuleCfg->getCommandByKeyEvent(aKey);
291 if (!sCommand.isEmpty())
292 return sCommand;
294 catch(const css::container::NoSuchElementException&)
299 if (xGlobalCfg.is())
300 sCommand = xGlobalCfg->getCommandByKeyEvent(aKey);
301 if (!sCommand.isEmpty())
302 return sCommand;
304 catch(const css::container::NoSuchElementException&)
307 // fall back to functional key codes
308 if( aKey.Modifiers == 0 )
310 switch( aKey.KeyCode )
312 case css::awt::Key::DELETE_TO_BEGIN_OF_LINE:
313 return ".uno:DelToStartOfLine";
314 case css::awt::Key::DELETE_TO_END_OF_LINE:
315 return ".uno:DelToEndOfLine";
316 case css::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH:
317 return ".uno:DelToStartOfPara";
318 case css::awt::Key::DELETE_TO_END_OF_PARAGRAPH:
319 return ".uno:DelToEndOfPara";
320 case css::awt::Key::DELETE_WORD_BACKWARD:
321 return ".uno:DelToStartOfWord";
322 case css::awt::Key::DELETE_WORD_FORWARD:
323 return ".uno:DelToEndOfWord";
324 case css::awt::Key::INSERT_LINEBREAK:
325 return ".uno:InsertLinebreak";
326 case css::awt::Key::INSERT_PARAGRAPH:
327 return ".uno:InsertPara";
328 case css::awt::Key::MOVE_WORD_BACKWARD:
329 return ".uno:GoToPrevWord";
330 case css::awt::Key::MOVE_WORD_FORWARD:
331 return ".uno:GoToNextWord";
332 case css::awt::Key::MOVE_TO_BEGIN_OF_LINE:
333 return ".uno:GoToStartOfLine";
334 case css::awt::Key::MOVE_TO_END_OF_LINE:
335 return ".uno:GoToEndOfLine";
336 case css::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
337 return ".uno:GoToStartOfPara";
338 case css::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
339 return ".uno:GoToEndOfPara";
340 case css::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
341 return ".uno:GoToStartOfDoc";
342 case css::awt::Key::MOVE_TO_END_OF_DOCUMENT:
343 return ".uno:GoToEndOfDoc";
344 case css::awt::Key::SELECT_BACKWARD:
345 return ".uno:CharLeftSel";
346 case css::awt::Key::SELECT_FORWARD:
347 return ".uno:CharRightSel";
348 case css::awt::Key::SELECT_WORD_BACKWARD:
349 return ".uno:WordLeftSel";
350 case css::awt::Key::SELECT_WORD_FORWARD:
351 return ".uno:WordRightSel";
352 case css::awt::Key::SELECT_WORD:
353 return ".uno:SelectWord";
354 case css::awt::Key::SELECT_LINE:
355 return OUString();
356 case css::awt::Key::SELECT_PARAGRAPH:
357 return ".uno:SelectText";
358 case css::awt::Key::SELECT_TO_BEGIN_OF_LINE:
359 return ".uno:StartOfLineSel";
360 case css::awt::Key::SELECT_TO_END_OF_LINE:
361 return ".uno:EndOfLineSel";
362 case css::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
363 return ".uno:StartOfParaSel";
364 case css::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
365 return ".uno:EndOfParaSel";
366 case css::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
367 return ".uno:StartOfDocumentSel";
368 case css::awt::Key::SELECT_TO_END_OF_DOCUMENT:
369 return ".uno:EndOfDocumentSel";
370 case css::awt::Key::SELECT_ALL:
371 return ".uno:SelectAll";
372 default:
373 break;
377 return OUString();
381 css::uno::Reference< css::ui::XAcceleratorConfiguration > AcceleratorExecute::st_openModuleConfig(const css::uno::Reference< css::uno::XComponentContext >& rxContext,
382 const css::uno::Reference< css::frame::XFrame >& xFrame)
384 css::uno::Reference< css::frame::XModuleManager2 > xModuleDetection(
385 css::frame::ModuleManager::create(rxContext));
387 OUString sModule;
390 sModule = xModuleDetection->identify(xFrame);
392 catch(const css::uno::RuntimeException&)
393 { throw; }
394 catch(const css::uno::Exception&)
395 { return css::uno::Reference< css::ui::XAcceleratorConfiguration >(); }
397 css::uno::Reference< css::ui::XModuleUIConfigurationManagerSupplier > xUISupplier(
398 css::ui::theModuleUIConfigurationManagerSupplier::get(rxContext) );
400 css::uno::Reference< css::ui::XAcceleratorConfiguration > xAccCfg;
403 css::uno::Reference< css::ui::XUIConfigurationManager > xUIManager = xUISupplier->getUIConfigurationManager(sModule);
404 xAccCfg = xUIManager->getShortCutManager();
406 catch(const css::container::NoSuchElementException&)
408 return xAccCfg;
412 css::uno::Reference< css::ui::XAcceleratorConfiguration > AcceleratorExecute::st_openDocConfig(const css::uno::Reference< css::frame::XModel >& xModel)
414 css::uno::Reference< css::ui::XAcceleratorConfiguration > xAccCfg;
415 css::uno::Reference< css::ui::XUIConfigurationManagerSupplier > xUISupplier(xModel, css::uno::UNO_QUERY);
416 if (xUISupplier.is())
418 css::uno::Reference< css::ui::XUIConfigurationManager > xUIManager = xUISupplier->getUIConfigurationManager();
419 xAccCfg = xUIManager->getShortCutManager();
421 return xAccCfg;
425 css::uno::Reference< css::util::XURLTransformer > AcceleratorExecute::impl_ts_getURLParser()
427 // SAFE -> ----------------------------------
428 ::osl::ResettableMutexGuard aLock(m_aLock);
430 if (m_xURLParser.is())
431 return m_xURLParser;
432 css::uno::Reference< css::uno::XComponentContext > xContext = m_xContext;
434 aLock.clear();
435 // <- SAFE ----------------------------------
437 css::uno::Reference< css::util::XURLTransformer > xParser = css::util::URLTransformer::create( xContext );
439 // SAFE -> ----------------------------------
440 aLock.reset();
441 m_xURLParser = xParser;
442 aLock.clear();
443 // <- SAFE ----------------------------------
445 return xParser;
448 AsyncAccelExec::AsyncAccelExec(const css::uno::Reference<css::lang::XComponent>& xFrame,
449 const css::uno::Reference<css::frame::XDispatch>& xDispatch,
450 const css::util::URL& rURL)
451 : m_xFrame(xFrame)
452 , m_xDispatch(xDispatch)
453 , m_aURL(rURL)
454 , m_aAsyncCallback(LINK(this, AsyncAccelExec, impl_ts_asyncCallback))
458 AsyncAccelExec* AsyncAccelExec::createOneShotInstance(const css::uno::Reference<css::lang::XComponent> &xFrame,
459 const css::uno::Reference< css::frame::XDispatch >& xDispatch,
460 const css::util::URL& rURL)
462 AsyncAccelExec* pExec = new AsyncAccelExec(xFrame, xDispatch, rURL);
463 return pExec;
467 void AsyncAccelExec::execAsync()
469 acquire();
470 if (m_xFrame.is())
471 m_xFrame->addEventListener(this);
472 m_aAsyncCallback.Post();
475 IMPL_LINK_NOARG(AsyncAccelExec, impl_ts_asyncCallback, LinkParamNone*, void)
477 if (m_xDispatch.is())
481 if (m_xFrame.is())
482 m_xFrame->removeEventListener(this);
483 m_xDispatch->dispatch(m_aURL, css::uno::Sequence< css::beans::PropertyValue >());
485 catch(const css::uno::Exception&)
489 release();
492 } // namespace svt
494 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */