1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26
27 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
28 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
29 #include <com/sun/star/accessibility/XAccessibleSelection.hpp>
30 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
31 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
32 // --> OD 2009-04-14 #i93269#
33 #include <com/sun/star/accessibility/XAccessibleText.hpp>
34 // <--
35 #include <cppuhelper/implbase1.hxx>
36 #include <vos/mutex.hxx>
37 #include <rtl/ref.hxx>
38
39 #include <vcl/svapp.hxx>
40 #include <vcl/window.hxx>
41 #include <vcl/menu.hxx>
42 #include <vcl/toolbox.hxx>
43
44 #include "atkwrapper.hxx"
45 #include "atkutil.hxx"
46
47 #include <gtk/gtk.h>
48
49 #include <set>
50
51 // #define ENABLE_TRACING
52
53 #ifdef ENABLE_TRACING
54 #include <stdio.h>
55 #endif
56
57 using namespace ::com::sun::star;
58
59 static uno::WeakReference< accessibility::XAccessible > xNextFocusObject;
60 static guint focus_notify_handler = 0;
61
62 /*****************************************************************************/
63
64 extern "C" {
65
66 static gint
atk_wrapper_focus_idle_handler(gpointer data)67 atk_wrapper_focus_idle_handler (gpointer data)
68 {
69 vos::OGuard aGuard( Application::GetSolarMutex() );
70
71 focus_notify_handler = 0;
72
73 uno::Reference< accessibility::XAccessible > xAccessible = xNextFocusObject;
74 if( xAccessible.get() == reinterpret_cast < accessibility::XAccessible * > (data) )
75 {
76 AtkObject *atk_obj = xAccessible.is() ? atk_object_wrapper_ref( xAccessible ) : NULL;
77 // Gail does not notify focus changes to NULL, so do we ..
78 if( atk_obj )
79 {
80 #ifdef ENABLE_TRACING
81 fprintf(stderr, "notifying focus event for %p\n", atk_obj);
82 #endif
83 atk_focus_tracker_notify(atk_obj);
84 // --> OD 2009-04-14 #i93269#
85 // emit text_caret_moved event for <XAccessibleText> object,
86 // if cursor is inside the <XAccessibleText> object.
87 // also emit state-changed:focused event under the same condition.
88 {
89 AtkObjectWrapper* wrapper_obj = ATK_OBJECT_WRAPPER (atk_obj);
90 if( wrapper_obj && !wrapper_obj->mpText && wrapper_obj->mpContext )
91 {
92 uno::Any any = wrapper_obj->mpContext->queryInterface( accessibility::XAccessibleText::static_type(NULL) );
93 if ( typelib_TypeClass_INTERFACE == any.pType->eTypeClass &&
94 any.pReserved != 0 )
95 {
96 wrapper_obj->mpText = reinterpret_cast< accessibility::XAccessibleText * > (any.pReserved);
97 if ( wrapper_obj->mpText != 0 )
98 {
99 wrapper_obj->mpText->acquire();
100 gint caretPos = wrapper_obj->mpText->getCaretPosition();
101
102 if ( caretPos != -1 )
103 {
104 atk_object_notify_state_change( atk_obj, ATK_STATE_FOCUSED, TRUE );
105 g_signal_emit_by_name( atk_obj, "text_caret_moved", caretPos );
106 }
107 }
108 }
109 }
110 }
111 // <--
112 g_object_unref(atk_obj);
113 }
114 }
115
116 return FALSE;
117 }
118
119 } // extern "C"
120
121 /*****************************************************************************/
122
123 static void
atk_wrapper_focus_tracker_notify_when_idle(const uno::Reference<accessibility::XAccessible> & xAccessible)124 atk_wrapper_focus_tracker_notify_when_idle( const uno::Reference< accessibility::XAccessible > &xAccessible )
125 {
126 if( focus_notify_handler )
127 g_source_remove(focus_notify_handler);
128
129 xNextFocusObject = xAccessible;
130
131 focus_notify_handler = g_idle_add (atk_wrapper_focus_idle_handler, xAccessible.get());
132 }
133
134 /*****************************************************************************/
135
136 class DocumentFocusListener :
137 public ::cppu::WeakImplHelper1< accessibility::XAccessibleEventListener >
138 {
139
140 std::set< uno::Reference< uno::XInterface > > m_aRefList;
141
142 public:
143 void attachRecursive(
144 const uno::Reference< accessibility::XAccessible >& xAccessible
145 ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException);
146
147 void attachRecursive(
148 const uno::Reference< accessibility::XAccessible >& xAccessible,
149 const uno::Reference< accessibility::XAccessibleContext >& xContext
150 ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException);
151
152 void attachRecursive(
153 const uno::Reference< accessibility::XAccessible >& xAccessible,
154 const uno::Reference< accessibility::XAccessibleContext >& xContext,
155 const uno::Reference< accessibility::XAccessibleStateSet >& xStateSet
156 ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException);
157
158 void detachRecursive(
159 const uno::Reference< accessibility::XAccessible >& xAccessible
160 ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException);
161
162 void detachRecursive(
163 const uno::Reference< accessibility::XAccessible >& xAccessible,
164 const uno::Reference< accessibility::XAccessibleContext >& xContext
165 ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException);
166
167 void detachRecursive(
168 const uno::Reference< accessibility::XAccessible >& xAccessible,
169 const uno::Reference< accessibility::XAccessibleContext >& xContext,
170 const uno::Reference< accessibility::XAccessibleStateSet >& xStateSet
171 ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException);
172
173 static uno::Reference< accessibility::XAccessible > getAccessible(const lang::EventObject& aEvent )
174 throw (lang::IndexOutOfBoundsException, uno::RuntimeException);
175
176 // XEventListener
177 virtual void disposing( const lang::EventObject& Source ) throw (uno::RuntimeException);
178
179 // XAccessibleEventListener
180 virtual void notifyEvent( const accessibility::AccessibleEventObject& aEvent ) throw( uno::RuntimeException );
181 };
182
183 /*****************************************************************************/
184
disposing(const lang::EventObject & aEvent)185 void DocumentFocusListener::disposing( const lang::EventObject& aEvent )
186 throw (uno::RuntimeException)
187 {
188 // fprintf(stderr, "In DocumentFocusListener::disposing (%p)\n", this);
189 // fprintf(stderr, "m_aRefList has %d entries\n", m_aRefList.size());
190
191 // Unref the object here, but do not remove as listener since the object
192 // might no longer be in a state that safely allows this.
193 if( aEvent.Source.is() )
194 m_aRefList.erase(aEvent.Source);
195
196 // fprintf(stderr, "m_aRefList has %d entries\n", m_aRefList.size());
197
198 }
199
200 /*****************************************************************************/
201
notifyEvent(const accessibility::AccessibleEventObject & aEvent)202 void DocumentFocusListener::notifyEvent( const accessibility::AccessibleEventObject& aEvent )
203 throw( uno::RuntimeException )
204 {
205 try {
206 switch( aEvent.EventId )
207 {
208 case accessibility::AccessibleEventId::STATE_CHANGED:
209 {
210 sal_Int16 nState = accessibility::AccessibleStateType::INVALID;
211 aEvent.NewValue >>= nState;
212
213 if( accessibility::AccessibleStateType::FOCUSED == nState )
214 atk_wrapper_focus_tracker_notify_when_idle( getAccessible(aEvent) );
215 }
216 break;
217
218 case accessibility::AccessibleEventId::CHILD:
219 {
220 uno::Reference< accessibility::XAccessible > xChild;
221 if( (aEvent.OldValue >>= xChild) && xChild.is() )
222 detachRecursive(xChild);
223
224 if( (aEvent.NewValue >>= xChild) && xChild.is() )
225 attachRecursive(xChild);
226 }
227 break;
228
229 case accessibility::AccessibleEventId::INVALIDATE_ALL_CHILDREN:
230 /* {
231 uno::Reference< accessibility::XAccessible > xAccessible( getAccessible(aEvent) );
232 detachRecursive(xAccessible);
233 attachRecursive(xAccessible);
234 }
235 */
236 g_warning( "Invalidate all children called\n" );
237 break;
238
239 default:
240 break;
241 }
242 }
243 catch( const lang::IndexOutOfBoundsException& e )
244 {
245 g_warning("Focused object has invalid index in parent");
246 }
247 }
248
249 /*****************************************************************************/
250
getAccessible(const lang::EventObject & aEvent)251 uno::Reference< accessibility::XAccessible > DocumentFocusListener::getAccessible(const lang::EventObject& aEvent )
252 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
253 {
254 uno::Reference< accessibility::XAccessible > xAccessible(aEvent.Source, uno::UNO_QUERY);
255
256 if( xAccessible.is() )
257 return xAccessible;
258
259 uno::Reference< accessibility::XAccessibleContext > xContext(aEvent.Source, uno::UNO_QUERY);
260
261 if( xContext.is() )
262 {
263 uno::Reference< accessibility::XAccessible > xParent( xContext->getAccessibleParent() );
264 if( xParent.is() )
265 {
266 uno::Reference< accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
267 if( xParentContext.is() )
268 {
269 return xParentContext->getAccessibleChild( xContext->getAccessibleIndexInParent() );
270 }
271 }
272 }
273
274 return uno::Reference< accessibility::XAccessible >();
275 }
276
277 /*****************************************************************************/
278
attachRecursive(const uno::Reference<accessibility::XAccessible> & xAccessible)279 void DocumentFocusListener::attachRecursive(
280 const uno::Reference< accessibility::XAccessible >& xAccessible
281 ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
282 {
283 uno::Reference< accessibility::XAccessibleContext > xContext =
284 xAccessible->getAccessibleContext();
285
286 if( xContext.is() )
287 attachRecursive(xAccessible, xContext);
288 }
289
290 /*****************************************************************************/
291
attachRecursive(const uno::Reference<accessibility::XAccessible> & xAccessible,const uno::Reference<accessibility::XAccessibleContext> & xContext)292 void DocumentFocusListener::attachRecursive(
293 const uno::Reference< accessibility::XAccessible >& xAccessible,
294 const uno::Reference< accessibility::XAccessibleContext >& xContext
295 ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
296 {
297 uno::Reference< accessibility::XAccessibleStateSet > xStateSet =
298 xContext->getAccessibleStateSet();
299
300 if( xStateSet.is() )
301 attachRecursive(xAccessible, xContext, xStateSet);
302 }
303
304 /*****************************************************************************/
305
attachRecursive(const uno::Reference<accessibility::XAccessible> & xAccessible,const uno::Reference<accessibility::XAccessibleContext> & xContext,const uno::Reference<accessibility::XAccessibleStateSet> & xStateSet)306 void DocumentFocusListener::attachRecursive(
307 const uno::Reference< accessibility::XAccessible >& xAccessible,
308 const uno::Reference< accessibility::XAccessibleContext >& xContext,
309 const uno::Reference< accessibility::XAccessibleStateSet >& xStateSet
310 ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
311 {
312 if( xStateSet->contains(accessibility::AccessibleStateType::FOCUSED ) )
313 atk_wrapper_focus_tracker_notify_when_idle( xAccessible );
314
315 uno::Reference< accessibility::XAccessibleEventBroadcaster > xBroadcaster =
316 uno::Reference< accessibility::XAccessibleEventBroadcaster >(xContext, uno::UNO_QUERY);
317
318 // If not already done, add the broadcaster to the list and attach as listener.
319 if( xBroadcaster.is() && m_aRefList.insert(xBroadcaster).second )
320 {
321 xBroadcaster->addEventListener(static_cast< accessibility::XAccessibleEventListener *>(this));
322
323 if( ! xStateSet->contains(accessibility::AccessibleStateType::MANAGES_DESCENDANTS ) )
324 {
325 sal_Int32 n, nmax = xContext->getAccessibleChildCount();
326 for( n = 0; n < nmax; n++ )
327 {
328 uno::Reference< accessibility::XAccessible > xChild( xContext->getAccessibleChild( n ) );
329
330 if( xChild.is() )
331 attachRecursive(xChild);
332 }
333 }
334 }
335 }
336
337 /*****************************************************************************/
338
detachRecursive(const uno::Reference<accessibility::XAccessible> & xAccessible)339 void DocumentFocusListener::detachRecursive(
340 const uno::Reference< accessibility::XAccessible >& xAccessible
341 ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
342 {
343 uno::Reference< accessibility::XAccessibleContext > xContext =
344 xAccessible->getAccessibleContext();
345
346 if( xContext.is() )
347 detachRecursive(xAccessible, xContext);
348 }
349
350 /*****************************************************************************/
351
detachRecursive(const uno::Reference<accessibility::XAccessible> & xAccessible,const uno::Reference<accessibility::XAccessibleContext> & xContext)352 void DocumentFocusListener::detachRecursive(
353 const uno::Reference< accessibility::XAccessible >& xAccessible,
354 const uno::Reference< accessibility::XAccessibleContext >& xContext
355 ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
356 {
357 uno::Reference< accessibility::XAccessibleStateSet > xStateSet =
358 xContext->getAccessibleStateSet();
359
360 if( xStateSet.is() )
361 detachRecursive(xAccessible, xContext, xStateSet);
362 }
363
364 /*****************************************************************************/
365
detachRecursive(const uno::Reference<accessibility::XAccessible> &,const uno::Reference<accessibility::XAccessibleContext> & xContext,const uno::Reference<accessibility::XAccessibleStateSet> & xStateSet)366 void DocumentFocusListener::detachRecursive(
367 const uno::Reference< accessibility::XAccessible >&,
368 const uno::Reference< accessibility::XAccessibleContext >& xContext,
369 const uno::Reference< accessibility::XAccessibleStateSet >& xStateSet
370 ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
371 {
372 uno::Reference< accessibility::XAccessibleEventBroadcaster > xBroadcaster =
373 uno::Reference< accessibility::XAccessibleEventBroadcaster >(xContext, uno::UNO_QUERY);
374
375 if( xBroadcaster.is() && 0 < m_aRefList.erase(xBroadcaster) )
376 {
377 xBroadcaster->removeEventListener(static_cast< accessibility::XAccessibleEventListener *>(this));
378
379 if( ! xStateSet->contains(accessibility::AccessibleStateType::MANAGES_DESCENDANTS ) )
380 {
381 sal_Int32 n, nmax = xContext->getAccessibleChildCount();
382 for( n = 0; n < nmax; n++ )
383 {
384 uno::Reference< accessibility::XAccessible > xChild( xContext->getAccessibleChild( n ) );
385
386 if( xChild.is() )
387 detachRecursive(xChild);
388 }
389 }
390 }
391 }
392
393 /*****************************************************************************/
394
395 /*
396 * page tabs in gtk are widgets, so we need to simulate focus events for those
397 */
398
handle_tabpage_activated(Window * pWindow)399 static void handle_tabpage_activated(Window *pWindow)
400 {
401 uno::Reference< accessibility::XAccessible > xAccessible =
402 pWindow->GetAccessible();
403
404 if( ! xAccessible.is() )
405 return;
406
407 uno::Reference< accessibility::XAccessibleSelection > xSelection(
408 xAccessible->getAccessibleContext(), uno::UNO_QUERY);
409
410 if( xSelection.is() )
411 atk_wrapper_focus_tracker_notify_when_idle( xSelection->getSelectedAccessibleChild(0) );
412 }
413
414 /*****************************************************************************/
415
416 /*
417 * toolbar items in gtk are widgets, so we need to simulate focus events for those
418 */
419
notify_toolbox_item_focus(ToolBox * pToolBox)420 static void notify_toolbox_item_focus(ToolBox *pToolBox)
421 {
422 uno::Reference< accessibility::XAccessible > xAccessible =
423 pToolBox->GetAccessible();
424
425 if( ! xAccessible.is() )
426 return;
427
428 uno::Reference< accessibility::XAccessibleContext > xContext =
429 xAccessible->getAccessibleContext();
430
431 if( ! xContext.is() )
432 return;
433
434 sal_Int32 nPos = pToolBox->GetItemPos( pToolBox->GetHighlightItemId() );
435 if( nPos != TOOLBOX_ITEM_NOTFOUND )
436 atk_wrapper_focus_tracker_notify_when_idle( xContext->getAccessibleChild( nPos ) );
437 }
438
handle_toolbox_highlight(Window * pWindow)439 static void handle_toolbox_highlight(Window *pWindow)
440 {
441 ToolBox *pToolBox = static_cast <ToolBox *> (pWindow);
442
443 // Make sure either the toolbox or its parent toolbox has the focus
444 if ( ! pToolBox->HasFocus() )
445 {
446 ToolBox* pToolBoxParent = dynamic_cast< ToolBox* >( pToolBox->GetParent() );
447 if ( ! pToolBoxParent || ! pToolBoxParent->HasFocus() )
448 return;
449 }
450
451 notify_toolbox_item_focus(pToolBox);
452 }
453
handle_toolbox_highlightoff(Window * pWindow)454 static void handle_toolbox_highlightoff(Window *pWindow)
455 {
456 ToolBox *pToolBox = static_cast <ToolBox *> (pWindow);
457 ToolBox* pToolBoxParent = dynamic_cast< ToolBox* >( pToolBox->GetParent() );
458
459 // Notify when leaving sub toolboxes
460 if( pToolBoxParent && pToolBoxParent->HasFocus() )
461 notify_toolbox_item_focus( pToolBoxParent );
462 }
463
464 /*****************************************************************************/
465
create_wrapper_for_child(const uno::Reference<accessibility::XAccessibleContext> & xContext,sal_Int32 index)466 static void create_wrapper_for_child(
467 const uno::Reference< accessibility::XAccessibleContext >& xContext,
468 sal_Int32 index)
469 {
470 if( xContext.is() )
471 {
472 uno::Reference< accessibility::XAccessible > xChild(xContext->getAccessibleChild(index));
473 if( xChild.is() )
474 {
475 // create the wrapper object - it will survive the unref unless it is a transient object
476 g_object_unref( atk_object_wrapper_ref( xChild ) );
477 }
478 }
479 }
480
481 /*****************************************************************************/
482
handle_toolbox_buttonchange(VclWindowEvent const * pEvent)483 static void handle_toolbox_buttonchange(VclWindowEvent const *pEvent)
484 {
485 Window* pWindow = pEvent->GetWindow();
486 sal_Int32 index = (sal_Int32)(sal_IntPtr) pEvent->GetData();
487
488 if( pWindow && pWindow->IsReallyVisible() )
489 {
490 uno::Reference< accessibility::XAccessible > xAccessible(pWindow->GetAccessible());
491 if( xAccessible.is() )
492 {
493 create_wrapper_for_child(xAccessible->getAccessibleContext(), index);
494 }
495 }
496 }
497
498 /*****************************************************************************/
499
500 /* currently not needed anymore...
501 static void create_wrapper_for_children(Window *pWindow)
502 {
503 if( pWindow && pWindow->IsReallyVisible() )
504 {
505 uno::Reference< accessibility::XAccessible > xAccessible(pWindow->GetAccessible());
506 if( xAccessible.is() )
507 {
508 uno::Reference< accessibility::XAccessibleContext > xContext(xAccessible->getAccessibleContext());
509 if( xContext.is() )
510 {
511 sal_Int32 nChildren = xContext->getAccessibleChildCount();
512 for( sal_Int32 i = 0; i < nChildren; ++i )
513 create_wrapper_for_child(xContext, i);
514 }
515 }
516 }
517 }
518 */
519
520 /*****************************************************************************/
521
522 static std::set< Window * > g_aWindowList;
523
handle_get_focus(::VclWindowEvent const * pEvent)524 static void handle_get_focus(::VclWindowEvent const * pEvent)
525 {
526 static rtl::Reference< DocumentFocusListener > aDocumentFocusListener =
527 new DocumentFocusListener();
528
529 Window *pWindow = pEvent->GetWindow();
530
531 // The menu bar is handled through VCLEVENT_MENU_HIGHLIGHTED
532 if( ! pWindow || !pWindow->IsReallyVisible() || pWindow->GetType() == WINDOW_MENUBARWINDOW )
533 return;
534
535 // ToolBoxes are handled through VCLEVENT_TOOLBOX_HIGHLIGHT
536 if( pWindow->GetType() == WINDOW_TOOLBOX )
537 return;
538
539 if( pWindow->GetType() == WINDOW_TABCONTROL )
540 {
541 handle_tabpage_activated( pWindow );
542 return;
543 }
544
545 uno::Reference< accessibility::XAccessible > xAccessible =
546 pWindow->GetAccessible();
547
548 if( ! xAccessible.is() )
549 return;
550
551 uno::Reference< accessibility::XAccessibleContext > xContext =
552 xAccessible->getAccessibleContext();
553
554 if( ! xContext.is() )
555 return;
556
557 uno::Reference< accessibility::XAccessibleStateSet > xStateSet =
558 xContext->getAccessibleStateSet();
559
560 if( ! xStateSet.is() )
561 return;
562
563 /* the UNO ToolBox wrapper does not (yet?) support XAccessibleSelection, so we
564 * need to add listeners to the children instead of re-using the tabpage stuff
565 */
566 if( xStateSet->contains(accessibility::AccessibleStateType::FOCUSED) &&
567 ( pWindow->GetType() != WINDOW_TREELISTBOX ) )
568 {
569 atk_wrapper_focus_tracker_notify_when_idle( xAccessible );
570 }
571 else
572 {
573 if( g_aWindowList.find(pWindow) == g_aWindowList.end() )
574 {
575 g_aWindowList.insert(pWindow);
576 try
577 {
578 aDocumentFocusListener->attachRecursive(xAccessible, xContext, xStateSet);
579 }
580 catch( const uno::Exception &e )
581 {
582 g_warning( "Exception caught processing focus events" );
583 }
584 }
585 #ifdef ENABLE_TRACING
586 else
587 fprintf(stderr, "Window %p already in the list\n", pWindow );
588 #endif
589 }
590 }
591
592 /*****************************************************************************/
593
handle_menu_highlighted(::VclMenuEvent const * pEvent)594 static void handle_menu_highlighted(::VclMenuEvent const * pEvent)
595 {
596 try
597 {
598 Menu* pMenu = pEvent->GetMenu();
599 sal_uInt16 nPos = pEvent->GetItemPos();
600
601 if( pMenu && nPos != 0xFFFF)
602 {
603 uno::Reference< accessibility::XAccessible > xAccessible ( pMenu->GetAccessible() );
604
605 if( xAccessible.is() )
606 {
607 uno::Reference< accessibility::XAccessibleContext > xContext ( xAccessible->getAccessibleContext() );
608
609 if( xContext.is() )
610 atk_wrapper_focus_tracker_notify_when_idle( xContext->getAccessibleChild( nPos ) );
611 }
612 }
613 }
614 catch( const uno::Exception& e )
615 {
616 g_warning( "Exception caught processing menu highlight events" );
617 }
618 }
619
620 /*****************************************************************************/
621
WindowEventHandler(void *,::VclSimpleEvent const * pEvent)622 long WindowEventHandler(void *, ::VclSimpleEvent const * pEvent)
623 {
624 switch (pEvent->GetId())
625 {
626 case VCLEVENT_WINDOW_SHOW:
627 // fprintf(stderr, "got VCLEVENT_WINDOW_SHOW for %p\n",
628 // static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
629 break;
630 case VCLEVENT_WINDOW_HIDE:
631 // fprintf(stderr, "got VCLEVENT_WINDOW_HIDE for %p\n",
632 // static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
633 break;
634 case VCLEVENT_WINDOW_CLOSE:
635 // fprintf(stderr, "got VCLEVENT_WINDOW_CLOSE for %p\n",
636 // static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
637 break;
638 case VCLEVENT_WINDOW_GETFOCUS:
639 handle_get_focus(static_cast< ::VclWindowEvent const * >(pEvent));
640 break;
641 case VCLEVENT_WINDOW_LOSEFOCUS:
642 // fprintf(stderr, "got VCLEVENT_WINDOW_LOSEFOCUS for %p\n",
643 // static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
644 break;
645 case VCLEVENT_WINDOW_MINIMIZE:
646 // fprintf(stderr, "got VCLEVENT_WINDOW_MINIMIZE for %p\n",
647 // static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
648 break;
649 case VCLEVENT_WINDOW_NORMALIZE:
650 // fprintf(stderr, "got VCLEVENT_WINDOW_NORMALIZE for %p\n",
651 // static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
652 break;
653 case VCLEVENT_WINDOW_KEYINPUT:
654 case VCLEVENT_WINDOW_KEYUP:
655 case VCLEVENT_WINDOW_COMMAND:
656 case VCLEVENT_WINDOW_MOUSEMOVE:
657 break;
658 /*
659 fprintf(stderr, "got VCLEVENT_WINDOW_COMMAND (%d) for %p\n",
660 static_cast< ::CommandEvent const * > (
661 static_cast< ::VclWindowEvent const * >(pEvent)->GetData())->GetCommand(),
662 static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
663 */
664 case VCLEVENT_MENU_HIGHLIGHT:
665 if (const VclMenuEvent* pMenuEvent = dynamic_cast<const VclMenuEvent*>(pEvent))
666 {
667 handle_menu_highlighted(pMenuEvent);
668 }
669 else if (const VclAccessibleEvent* pAccEvent = dynamic_cast<const VclAccessibleEvent*>(pEvent))
670 {
671 uno::Reference< accessibility::XAccessible > xAccessible = pAccEvent->GetAccessible();
672 if (xAccessible.is())
673 atk_wrapper_focus_tracker_notify_when_idle(xAccessible);
674 }
675 break;
676
677 case VCLEVENT_TOOLBOX_HIGHLIGHT:
678 handle_toolbox_highlight(static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
679 break;
680
681 case VCLEVENT_TOOLBOX_BUTTONSTATECHANGED:
682 handle_toolbox_buttonchange(static_cast< ::VclWindowEvent const * >(pEvent));
683 break;
684
685 case VCLEVENT_OBJECT_DYING:
686 g_aWindowList.erase( static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow() );
687 // fallthrough intentional !
688 case VCLEVENT_TOOLBOX_HIGHLIGHTOFF:
689 handle_toolbox_highlightoff(static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
690 break;
691
692 case VCLEVENT_TABPAGE_ACTIVATE:
693 handle_tabpage_activated(static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
694 break;
695
696 case VCLEVENT_COMBOBOX_SETTEXT:
697 // MT 2010/02: This looks quite strange to me. Stumbled over this when fixing #i104290#.
698 // This kicked in when leaving the combobox in the toolbar, after that the events worked.
699 // I guess this was a try to work around missing combobox events, which didn't do the full job, and shouldn't be necessary anymore.
700 // Fix for #i104290# was done in toolkit/source/awt/vclxaccessiblecomponent, FOCUSED state for compound controls in general.
701 // create_wrapper_for_children(static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
702 break;
703
704 default:
705 // OSL_TRACE("got event %d \n", pEvent->GetId());
706 break;
707 }
708 return 0;
709 }
710
711 static Link g_aEventListenerLink( NULL, (PSTUB) WindowEventHandler );
712
713 /*****************************************************************************/
714
715 extern "C" {
716
717 static G_CONST_RETURN gchar *
ooo_atk_util_get_toolkit_name(void)718 ooo_atk_util_get_toolkit_name (void)
719 {
720 return "VCL";
721 }
722
723 /*****************************************************************************/
724
725 static G_CONST_RETURN gchar *
ooo_atk_util_get_toolkit_version(void)726 ooo_atk_util_get_toolkit_version (void)
727 {
728 /*
729 * Version is passed in as a -D flag when this file is
730 * compiled.
731 */
732
733 return VERSION;
734 }
735
736 /*****************************************************************************/
737
738 /*
739 * GObject inheritance
740 */
741
742 static void
ooo_atk_util_class_init(AtkUtilClass *)743 ooo_atk_util_class_init (AtkUtilClass *)
744 {
745 AtkUtilClass *atk_class;
746 gpointer data;
747
748 data = g_type_class_peek (ATK_TYPE_UTIL);
749 atk_class = ATK_UTIL_CLASS (data);
750
751 atk_class->get_toolkit_name = ooo_atk_util_get_toolkit_name;
752 atk_class->get_toolkit_version = ooo_atk_util_get_toolkit_version;
753
754 Application::AddEventListener( g_aEventListenerLink );
755 }
756
757 } // extern "C"
758
759 /*****************************************************************************/
760
761 GType
ooo_atk_util_get_type(void)762 ooo_atk_util_get_type (void)
763 {
764 static GType type = 0;
765
766 if (!type)
767 {
768 GType parent_type = g_type_from_name( "GailUtil" );
769
770 if( ! parent_type )
771 {
772 g_warning( "Unknown type: GailUtil" );
773 parent_type = ATK_TYPE_UTIL;
774 }
775
776 GTypeQuery type_query;
777 g_type_query( parent_type, &type_query );
778
779 static const GTypeInfo typeInfo =
780 {
781 type_query.class_size,
782 (GBaseInitFunc) NULL,
783 (GBaseFinalizeFunc) NULL,
784 (GClassInitFunc) ooo_atk_util_class_init,
785 (GClassFinalizeFunc) NULL,
786 NULL,
787 type_query.instance_size,
788 0,
789 (GInstanceInitFunc) NULL,
790 NULL
791 } ;
792
793 type = g_type_register_static (parent_type, "OOoUtil", &typeInfo, (GTypeFlags)0) ;
794 }
795
796 return type;
797 }
798
799
800