1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 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/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 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 . 18 */ 19 20 21 #include <sfx2/userinputinterception.hxx> 22 23 #include <com/sun/star/awt/MouseButton.hpp> 24 #include <com/sun/star/awt/KeyModifier.hpp> 25 #include <com/sun/star/awt/XUserInputInterception.hpp> 26 27 #include <comphelper/interfacecontainer2.hxx> 28 #include <cppuhelper/weak.hxx> 29 #include <vcl/event.hxx> 30 #include <vcl/window.hxx> 31 #include <osl/diagnose.h> 32 33 34 namespace sfx2 35 { 36 37 38 using ::com::sun::star::uno::Reference; 39 using ::com::sun::star::uno::XInterface; 40 using ::com::sun::star::uno::Exception; 41 using ::com::sun::star::uno::RuntimeException; 42 using ::com::sun::star::awt::MouseEvent; 43 using ::com::sun::star::awt::KeyEvent; 44 using ::com::sun::star::awt::InputEvent; 45 using ::com::sun::star::awt::XKeyHandler; 46 using ::com::sun::star::awt::XMouseClickHandler; 47 using ::com::sun::star::lang::DisposedException; 48 49 namespace MouseButton = ::com::sun::star::awt::MouseButton; 50 namespace KeyModifier = ::com::sun::star::awt::KeyModifier; 51 52 struct UserInputInterception_Data 53 { 54 public: 55 ::cppu::OWeakObject& m_rControllerImpl; 56 ::comphelper::OInterfaceContainerHelper2 m_aKeyHandlers; 57 ::comphelper::OInterfaceContainerHelper2 m_aMouseClickHandlers; 58 59 public: UserInputInterception_Datasfx2::UserInputInterception_Data60 UserInputInterception_Data( ::cppu::OWeakObject& _rControllerImpl, ::osl::Mutex& _rMutex ) 61 :m_rControllerImpl( _rControllerImpl ) 62 ,m_aKeyHandlers( _rMutex ) 63 ,m_aMouseClickHandlers( _rMutex ) 64 { 65 } 66 }; 67 68 namespace 69 { 70 template< class VLCEVENT > lcl_initModifiers(InputEvent & _rEvent,const VLCEVENT & _rVclEvent)71 void lcl_initModifiers( InputEvent& _rEvent, const VLCEVENT& _rVclEvent ) 72 { 73 _rEvent.Modifiers = 0; 74 75 if ( _rVclEvent.IsShift() ) 76 _rEvent.Modifiers |= KeyModifier::SHIFT; 77 if ( _rVclEvent.IsMod1() ) 78 _rEvent.Modifiers |= KeyModifier::MOD1; 79 if ( _rVclEvent.IsMod2() ) 80 _rEvent.Modifiers |= KeyModifier::MOD2; 81 if ( _rVclEvent.IsMod3() ) 82 _rEvent.Modifiers |= KeyModifier::MOD3; 83 } 84 lcl_initKeyEvent(KeyEvent & rEvent,const::KeyEvent & rEvt)85 void lcl_initKeyEvent( KeyEvent& rEvent, const ::KeyEvent& rEvt ) 86 { 87 lcl_initModifiers( rEvent, rEvt.GetKeyCode() ); 88 89 rEvent.KeyCode = rEvt.GetKeyCode().GetCode(); 90 rEvent.KeyChar = rEvt.GetCharCode(); 91 rEvent.KeyFunc = sal::static_int_cast< sal_Int16 >( rEvt.GetKeyCode().GetFunction()); 92 } 93 lcl_initMouseEvent(MouseEvent & rEvent,const::MouseEvent & rEvt)94 void lcl_initMouseEvent( MouseEvent& rEvent, const ::MouseEvent& rEvt ) 95 { 96 lcl_initModifiers( rEvent, rEvt ); 97 98 rEvent.Buttons = 0; 99 if ( rEvt.IsLeft() ) 100 rEvent.Buttons |= MouseButton::LEFT; 101 if ( rEvt.IsRight() ) 102 rEvent.Buttons |= MouseButton::RIGHT; 103 if ( rEvt.IsMiddle() ) 104 rEvent.Buttons |= MouseButton::MIDDLE; 105 106 rEvent.X = rEvt.GetPosPixel().X(); 107 rEvent.Y = rEvt.GetPosPixel().Y(); 108 rEvent.ClickCount = rEvt.GetClicks(); 109 rEvent.PopupTrigger = false; 110 } 111 112 } 113 114 115 //= UserInputInterception 116 117 UserInputInterception(::cppu::OWeakObject & _rControllerImpl,::osl::Mutex & _rMutex)118 UserInputInterception::UserInputInterception( ::cppu::OWeakObject& _rControllerImpl, ::osl::Mutex& _rMutex ) 119 :m_pData( new UserInputInterception_Data( _rControllerImpl, _rMutex ) ) 120 { 121 } 122 123 ~UserInputInterception()124 UserInputInterception::~UserInputInterception() 125 { 126 } 127 128 addKeyHandler(const Reference<XKeyHandler> & _rxHandler)129 void UserInputInterception::addKeyHandler( const Reference< XKeyHandler >& _rxHandler ) 130 { 131 if ( _rxHandler.is() ) 132 m_pData->m_aKeyHandlers.addInterface( _rxHandler ); 133 } 134 135 removeKeyHandler(const Reference<XKeyHandler> & _rxHandler)136 void UserInputInterception::removeKeyHandler( const Reference< XKeyHandler >& _rxHandler ) 137 { 138 m_pData->m_aKeyHandlers.removeInterface( _rxHandler ); 139 } 140 141 addMouseClickHandler(const Reference<XMouseClickHandler> & _rxHandler)142 void UserInputInterception::addMouseClickHandler( const Reference< XMouseClickHandler >& _rxHandler ) 143 { 144 if ( _rxHandler.is() ) 145 m_pData->m_aMouseClickHandlers.addInterface( _rxHandler ); 146 } 147 148 removeMouseClickHandler(const Reference<XMouseClickHandler> & _rxHandler)149 void UserInputInterception::removeMouseClickHandler( const Reference< XMouseClickHandler >& _rxHandler ) 150 { 151 m_pData->m_aMouseClickHandlers.removeInterface( _rxHandler ); 152 } 153 154 hasKeyHandlers() const155 bool UserInputInterception::hasKeyHandlers() const 156 { 157 return m_pData->m_aKeyHandlers.getLength() > 0; 158 } 159 160 hasMouseClickListeners() const161 bool UserInputInterception::hasMouseClickListeners() const 162 { 163 return m_pData->m_aMouseClickHandlers.getLength() > 0; 164 } 165 166 handleNotifyEvent(const NotifyEvent & _rEvent)167 bool UserInputInterception::handleNotifyEvent( const NotifyEvent& _rEvent ) 168 { 169 Reference < XInterface > xHoldAlive( m_pData->m_rControllerImpl ); 170 171 MouseNotifyEvent nType = _rEvent.GetType(); 172 bool bHandled = false; 173 174 switch ( nType ) 175 { 176 case MouseNotifyEvent::KEYINPUT: 177 case MouseNotifyEvent::KEYUP: 178 { 179 KeyEvent aEvent; 180 lcl_initKeyEvent( aEvent, *_rEvent.GetKeyEvent() ); 181 if ( _rEvent.GetWindow() ) 182 aEvent.Source = _rEvent.GetWindow()->GetComponentInterface(); 183 184 ::comphelper::OInterfaceIteratorHelper2 aIterator( m_pData->m_aKeyHandlers ); 185 while ( aIterator.hasMoreElements() ) 186 { 187 Reference< XKeyHandler > xHandler( static_cast< XKeyHandler* >( aIterator.next() ) ); 188 if ( !xHandler.is() ) 189 continue; 190 191 try 192 { 193 if ( nType == MouseNotifyEvent::KEYINPUT ) 194 bHandled = xHandler->keyPressed( aEvent ); 195 else 196 bHandled = xHandler->keyReleased( aEvent ); 197 } 198 catch( const DisposedException& e ) 199 { 200 if ( e.Context == xHandler ) 201 aIterator.remove(); 202 } 203 catch( const RuntimeException& ) 204 { 205 throw; 206 } 207 catch( const Exception& ) 208 { 209 } 210 } 211 } 212 break; 213 214 case MouseNotifyEvent::MOUSEBUTTONDOWN: 215 case MouseNotifyEvent::MOUSEBUTTONUP: 216 { 217 MouseEvent aEvent; 218 lcl_initMouseEvent( aEvent, *_rEvent.GetMouseEvent() ); 219 if ( _rEvent.GetWindow() ) 220 aEvent.Source = _rEvent.GetWindow()->GetComponentInterface(); 221 222 ::comphelper::OInterfaceIteratorHelper2 aIterator( m_pData->m_aMouseClickHandlers ); 223 while ( aIterator.hasMoreElements() ) 224 { 225 Reference< XMouseClickHandler > xHandler( static_cast< XMouseClickHandler* >( aIterator.next() ) ); 226 if ( !xHandler.is() ) 227 continue; 228 229 try 230 { 231 if ( nType == MouseNotifyEvent::MOUSEBUTTONDOWN ) 232 bHandled = xHandler->mousePressed( aEvent ); 233 else 234 bHandled = xHandler->mouseReleased( aEvent ); 235 } 236 catch( const DisposedException& e ) 237 { 238 if ( e.Context == xHandler ) 239 aIterator.remove(); 240 } 241 catch( const RuntimeException& ) 242 { 243 throw; 244 } 245 catch( const Exception& ) 246 { 247 } 248 } 249 } 250 break; 251 252 default: 253 OSL_FAIL( "UserInputInterception::handleNotifyEvent: illegal event type!" ); 254 break; 255 } 256 257 return bHandled; 258 } 259 260 261 } // namespace sfx2 262 263 264 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 265