1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ***********************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sfx2.hxx"
30 
31 #include "sfx2/userinputinterception.hxx"
32 
33 /** === begin UNO includes === **/
34 #include <com/sun/star/awt/MouseButton.hpp>
35 #include <com/sun/star/awt/KeyModifier.hpp>
36 /** === end UNO includes === **/
37 
38 #include <cppuhelper/interfacecontainer.hxx>
39 #include <cppuhelper/weak.hxx>
40 #include <vcl/event.hxx>
41 #include <vcl/window.hxx>
42 
43 //........................................................................
44 namespace sfx2
45 {
46 //........................................................................
47 
48 	/** === begin UNO using === **/
49 	using ::com::sun::star::uno::Reference;
50 	using ::com::sun::star::uno::XInterface;
51 	using ::com::sun::star::uno::UNO_QUERY;
52 	using ::com::sun::star::uno::UNO_QUERY_THROW;
53 	using ::com::sun::star::uno::UNO_SET_THROW;
54 	using ::com::sun::star::uno::Exception;
55 	using ::com::sun::star::uno::RuntimeException;
56 	using ::com::sun::star::uno::Any;
57 	using ::com::sun::star::uno::makeAny;
58 	using ::com::sun::star::awt::MouseEvent;
59 	using ::com::sun::star::awt::KeyEvent;
60 	using ::com::sun::star::awt::InputEvent;
61     using ::com::sun::star::awt::XKeyHandler;
62     using ::com::sun::star::awt::XMouseClickHandler;
63     using ::com::sun::star::lang::DisposedException;
64 	/** === end UNO using === **/
65     namespace MouseButton = ::com::sun::star::awt::MouseButton;
66     namespace KeyModifier = ::com::sun::star::awt::KeyModifier;
67 
68     struct UserInputInterception_Data
69     {
70     public:
71         ::cppu::OWeakObject&                m_rControllerImpl;
72         ::cppu::OInterfaceContainerHelper   m_aKeyHandlers;
73         ::cppu::OInterfaceContainerHelper   m_aMouseClickHandlers;
74 
75     public:
76         UserInputInterception_Data( ::cppu::OWeakObject& _rControllerImpl, ::osl::Mutex& _rMutex )
77             :m_rControllerImpl( _rControllerImpl )
78             ,m_aKeyHandlers( _rMutex )
79             ,m_aMouseClickHandlers( _rMutex )
80         {
81         }
82     };
83 
84     namespace
85     {
86         template< class VLCEVENT >
87         void lcl_initModifiers( InputEvent& _rEvent, const VLCEVENT& _rVclEvent )
88         {
89 	        _rEvent.Modifiers = 0;
90 
91             if ( _rVclEvent.IsShift() )
92 		        _rEvent.Modifiers |= KeyModifier::SHIFT;
93 	        if ( _rVclEvent.IsMod1() )
94 		        _rEvent.Modifiers |= KeyModifier::MOD1;
95 	        if ( _rVclEvent.IsMod2() )
96 		        _rEvent.Modifiers |= KeyModifier::MOD2;
97                 if ( _rVclEvent.IsMod3() )
98                         _rEvent.Modifiers |= KeyModifier::MOD3;
99         }
100 
101         void lcl_initKeyEvent( KeyEvent& rEvent, const ::KeyEvent& rEvt )
102         {
103             lcl_initModifiers( rEvent, rEvt.GetKeyCode() );
104 
105 	        rEvent.KeyCode = rEvt.GetKeyCode().GetCode();
106 	        rEvent.KeyChar = rEvt.GetCharCode();
107 	        rEvent.KeyFunc = sal::static_int_cast< sal_Int16 >( rEvt.GetKeyCode().GetFunction());
108         }
109 
110         void lcl_initMouseEvent( MouseEvent& rEvent, const ::MouseEvent& rEvt )
111         {
112             lcl_initModifiers( rEvent, rEvt );
113 
114 	        rEvent.Buttons = 0;
115 	        if ( rEvt.IsLeft() )
116 		        rEvent.Buttons |= MouseButton::LEFT;
117 	        if ( rEvt.IsRight() )
118 		        rEvent.Buttons |= MouseButton::RIGHT;
119 	        if ( rEvt.IsMiddle() )
120 		        rEvent.Buttons |= MouseButton::MIDDLE;
121 
122 	        rEvent.X = rEvt.GetPosPixel().X();
123 	        rEvent.Y = rEvt.GetPosPixel().Y();
124 	        rEvent.ClickCount = rEvt.GetClicks();
125 	        rEvent.PopupTrigger = sal_False;
126         }
127 
128     }
129 
130 	//====================================================================
131 	//= UserInputInterception
132 	//====================================================================
133 	//--------------------------------------------------------------------
134     UserInputInterception::UserInputInterception( ::cppu::OWeakObject& _rControllerImpl, ::osl::Mutex& _rMutex )
135         :m_pData( new UserInputInterception_Data( _rControllerImpl, _rMutex ) )
136     {
137     }
138 
139     //--------------------------------------------------------------------
140     UserInputInterception::~UserInputInterception()
141     {
142     }
143 
144     //--------------------------------------------------------------------
145     void UserInputInterception::addKeyHandler( const Reference< XKeyHandler >& _rxHandler ) throw (RuntimeException)
146     {
147         if ( _rxHandler.is() )
148 	        m_pData->m_aKeyHandlers.addInterface( _rxHandler );
149     }
150 
151     //--------------------------------------------------------------------
152     void UserInputInterception::removeKeyHandler( const Reference< XKeyHandler >& _rxHandler ) throw (RuntimeException)
153     {
154         m_pData->m_aKeyHandlers.removeInterface( _rxHandler );
155     }
156 
157     //--------------------------------------------------------------------
158     void UserInputInterception::addMouseClickHandler( const Reference< XMouseClickHandler >& _rxHandler ) throw (RuntimeException)
159     {
160         if ( _rxHandler.is() )
161 	        m_pData->m_aMouseClickHandlers.addInterface( _rxHandler );
162     }
163 
164     //--------------------------------------------------------------------
165     void UserInputInterception::removeMouseClickHandler( const Reference< XMouseClickHandler >& _rxHandler ) throw (RuntimeException)
166     {
167         m_pData->m_aMouseClickHandlers.removeInterface( _rxHandler );
168     }
169 
170     //--------------------------------------------------------------------
171     bool UserInputInterception::hasKeyHandlers() const
172     {
173         return m_pData->m_aKeyHandlers.getLength() > 0;
174     }
175 
176     //--------------------------------------------------------------------
177     bool UserInputInterception::hasMouseClickListeners() const
178     {
179         return m_pData->m_aMouseClickHandlers.getLength() > 0;
180     }
181 
182     //--------------------------------------------------------------------
183     bool UserInputInterception::handleNotifyEvent( const NotifyEvent& _rEvent )
184     {
185         Reference < XInterface > xHoldAlive( m_pData->m_rControllerImpl );
186 
187         sal_uInt16 nType = _rEvent.GetType();
188         bool bHandled = false;
189 
190 		switch ( nType )
191         {
192             case EVENT_KEYINPUT:
193             case EVENT_KEYUP:
194             {
195                 KeyEvent aEvent;
196                 lcl_initKeyEvent( aEvent, *_rEvent.GetKeyEvent() );
197                 if ( _rEvent.GetWindow() )
198                     aEvent.Source = _rEvent.GetWindow()->GetComponentInterface();
199 
200                 ::cppu::OInterfaceIteratorHelper aIterator( m_pData->m_aKeyHandlers );
201                 while ( aIterator.hasMoreElements() )
202                 {
203                     Reference< XKeyHandler > xHandler( static_cast< XKeyHandler* >( aIterator.next() ) );
204                     if ( !xHandler.is() )
205                         continue;
206 
207                     try
208                     {
209                         if ( nType == EVENT_KEYINPUT )
210                             bHandled = xHandler->keyPressed( aEvent );
211                         else
212                             bHandled = xHandler->keyReleased( aEvent );
213                     }
214                     catch( const DisposedException& e )
215                     {
216                         if ( e.Context == xHandler )
217                             aIterator.remove();
218                     }
219                     catch( const RuntimeException& )
220                     {
221                         throw;
222                     }
223                     catch( const Exception& )
224                     {
225                     }
226                 }
227             }
228             break;
229 
230             case EVENT_MOUSEBUTTONDOWN:
231             case EVENT_MOUSEBUTTONUP:
232             {
233                 MouseEvent aEvent;
234                 lcl_initMouseEvent( aEvent, *_rEvent.GetMouseEvent() );
235                 if ( _rEvent.GetWindow() )
236                     aEvent.Source = _rEvent.GetWindow()->GetComponentInterface();
237 
238                 ::cppu::OInterfaceIteratorHelper aIterator( m_pData->m_aMouseClickHandlers );
239                 while ( aIterator.hasMoreElements() )
240                 {
241                     Reference< XMouseClickHandler > xHandler( static_cast< XMouseClickHandler* >( aIterator.next() ) );
242                     if ( !xHandler.is() )
243                         continue;
244 
245                     try
246                     {
247                         if ( nType == EVENT_MOUSEBUTTONDOWN )
248                             bHandled = xHandler->mousePressed( aEvent );
249                         else
250                             bHandled = xHandler->mouseReleased( aEvent );
251                     }
252                     catch( const DisposedException& e )
253                     {
254                         if ( e.Context == xHandler )
255                             aIterator.remove();
256                     }
257                     catch( const RuntimeException& )
258                     {
259                         throw;
260                     }
261                     catch( const Exception& )
262                     {
263                     }
264                 }
265             }
266             break;
267 
268             default:
269                 OSL_ENSURE( false, "UserInputInterception::handleNotifyEvent: illegal event type!" );
270                 break;
271         }
272 
273         return bHandled;
274     }
275 
276 //........................................................................
277 } // namespace sfx2
278 //........................................................................
279