xref: /trunk/main/vcl/unx/gtk/a11y/atkutil.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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     );
146 
147     void attachRecursive(
148         const uno::Reference< accessibility::XAccessible >& xAccessible,
149         const uno::Reference< accessibility::XAccessibleContext >& xContext
150     );
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     );
157 
158     void detachRecursive(
159         const uno::Reference< accessibility::XAccessible >& xAccessible
160     );
161 
162     void detachRecursive(
163         const uno::Reference< accessibility::XAccessible >& xAccessible,
164         const uno::Reference< accessibility::XAccessibleContext >& xContext
165     );
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     );
172 
173     static uno::Reference< accessibility::XAccessible > getAccessible(const lang::EventObject& aEvent );
174 
175     // XEventListener
176     virtual void disposing( const lang::EventObject& Source );
177 
178     // XAccessibleEventListener
179     virtual void notifyEvent( const accessibility::AccessibleEventObject& aEvent );
180 };
181 
182 /*****************************************************************************/
183 
disposing(const lang::EventObject & aEvent)184 void DocumentFocusListener::disposing( const lang::EventObject& aEvent )
185 {
186 //    fprintf(stderr, "In DocumentFocusListener::disposing (%p)\n", this);
187 //    fprintf(stderr, "m_aRefList has %d entries\n", m_aRefList.size());
188 
189     // Unref the object here, but do not remove as listener since the object
190     // might no longer be in a state that safely allows this.
191     if( aEvent.Source.is() )
192         m_aRefList.erase(aEvent.Source);
193 
194 //    fprintf(stderr, "m_aRefList has %d entries\n", m_aRefList.size());
195 
196 }
197 
198 /*****************************************************************************/
199 
notifyEvent(const accessibility::AccessibleEventObject & aEvent)200 void DocumentFocusListener::notifyEvent( const accessibility::AccessibleEventObject& aEvent )
201 {
202     try {
203         switch( aEvent.EventId )
204         {
205             case accessibility::AccessibleEventId::STATE_CHANGED:
206             {
207                 sal_Int16 nState = accessibility::AccessibleStateType::INVALID;
208                 aEvent.NewValue >>= nState;
209 
210                 if( accessibility::AccessibleStateType::FOCUSED == nState )
211                     atk_wrapper_focus_tracker_notify_when_idle( getAccessible(aEvent) );
212             }
213             break;
214 
215             case accessibility::AccessibleEventId::CHILD:
216             {
217                 uno::Reference< accessibility::XAccessible > xChild;
218                 if( (aEvent.OldValue >>= xChild) && xChild.is() )
219                     detachRecursive(xChild);
220 
221                 if( (aEvent.NewValue >>= xChild) && xChild.is() )
222                     attachRecursive(xChild);
223             }
224             break;
225 
226             case accessibility::AccessibleEventId::INVALIDATE_ALL_CHILDREN:
227 /*        {
228             uno::Reference< accessibility::XAccessible > xAccessible( getAccessible(aEvent) );
229             detachRecursive(xAccessible);
230             attachRecursive(xAccessible);
231           }
232 */
233             g_warning( "Invalidate all children called\n" );
234             break;
235 
236             default:
237                 break;
238         }
239     }
240     catch( const lang::IndexOutOfBoundsException& e )
241     {
242         g_warning("Focused object has invalid index in parent");
243     }
244 }
245 
246 /*****************************************************************************/
247 
getAccessible(const lang::EventObject & aEvent)248 uno::Reference< accessibility::XAccessible > DocumentFocusListener::getAccessible(const lang::EventObject& aEvent )
249 {
250     uno::Reference< accessibility::XAccessible > xAccessible(aEvent.Source, uno::UNO_QUERY);
251 
252     if( xAccessible.is() )
253         return xAccessible;
254 
255     uno::Reference< accessibility::XAccessibleContext > xContext(aEvent.Source, uno::UNO_QUERY);
256 
257     if( xContext.is() )
258     {
259         uno::Reference< accessibility::XAccessible > xParent( xContext->getAccessibleParent() );
260         if( xParent.is() )
261         {
262             uno::Reference< accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
263             if( xParentContext.is() )
264             {
265                 return xParentContext->getAccessibleChild( xContext->getAccessibleIndexInParent() );
266             }
267         }
268     }
269 
270     return uno::Reference< accessibility::XAccessible >();
271 }
272 
273 /*****************************************************************************/
274 
attachRecursive(const uno::Reference<accessibility::XAccessible> & xAccessible)275 void DocumentFocusListener::attachRecursive(
276     const uno::Reference< accessibility::XAccessible >& xAccessible
277 )
278 {
279     uno::Reference< accessibility::XAccessibleContext > xContext =
280         xAccessible->getAccessibleContext();
281 
282     if( xContext.is() )
283         attachRecursive(xAccessible, xContext);
284 }
285 
286 /*****************************************************************************/
287 
attachRecursive(const uno::Reference<accessibility::XAccessible> & xAccessible,const uno::Reference<accessibility::XAccessibleContext> & xContext)288 void DocumentFocusListener::attachRecursive(
289     const uno::Reference< accessibility::XAccessible >& xAccessible,
290     const uno::Reference< accessibility::XAccessibleContext >& xContext
291 )
292 {
293     uno::Reference< accessibility::XAccessibleStateSet > xStateSet =
294         xContext->getAccessibleStateSet();
295 
296     if( xStateSet.is() )
297         attachRecursive(xAccessible, xContext, xStateSet);
298 }
299 
300 /*****************************************************************************/
301 
attachRecursive(const uno::Reference<accessibility::XAccessible> & xAccessible,const uno::Reference<accessibility::XAccessibleContext> & xContext,const uno::Reference<accessibility::XAccessibleStateSet> & xStateSet)302 void DocumentFocusListener::attachRecursive(
303     const uno::Reference< accessibility::XAccessible >& xAccessible,
304     const uno::Reference< accessibility::XAccessibleContext >& xContext,
305     const uno::Reference< accessibility::XAccessibleStateSet >& xStateSet
306 )
307 {
308     if( xStateSet->contains(accessibility::AccessibleStateType::FOCUSED ) )
309         atk_wrapper_focus_tracker_notify_when_idle( xAccessible );
310 
311     uno::Reference< accessibility::XAccessibleEventBroadcaster > xBroadcaster =
312         uno::Reference< accessibility::XAccessibleEventBroadcaster >(xContext, uno::UNO_QUERY);
313 
314     // If not already done, add the broadcaster to the list and attach as listener.
315     if( xBroadcaster.is() && m_aRefList.insert(xBroadcaster).second )
316     {
317         xBroadcaster->addEventListener(static_cast< accessibility::XAccessibleEventListener *>(this));
318 
319         if( ! xStateSet->contains(accessibility::AccessibleStateType::MANAGES_DESCENDANTS ) )
320         {
321             sal_Int32 n, nmax = xContext->getAccessibleChildCount();
322             for( n = 0; n < nmax; n++ )
323             {
324                 uno::Reference< accessibility::XAccessible > xChild( xContext->getAccessibleChild( n ) );
325 
326                 if( xChild.is() )
327                     attachRecursive(xChild);
328             }
329         }
330     }
331 }
332 
333 /*****************************************************************************/
334 
detachRecursive(const uno::Reference<accessibility::XAccessible> & xAccessible)335 void DocumentFocusListener::detachRecursive(
336     const uno::Reference< accessibility::XAccessible >& xAccessible
337 )
338 {
339     uno::Reference< accessibility::XAccessibleContext > xContext =
340         xAccessible->getAccessibleContext();
341 
342     if( xContext.is() )
343         detachRecursive(xAccessible, xContext);
344 }
345 
346 /*****************************************************************************/
347 
detachRecursive(const uno::Reference<accessibility::XAccessible> & xAccessible,const uno::Reference<accessibility::XAccessibleContext> & xContext)348 void DocumentFocusListener::detachRecursive(
349     const uno::Reference< accessibility::XAccessible >& xAccessible,
350     const uno::Reference< accessibility::XAccessibleContext >& xContext
351 )
352 {
353     uno::Reference< accessibility::XAccessibleStateSet > xStateSet =
354         xContext->getAccessibleStateSet();
355 
356     if( xStateSet.is() )
357         detachRecursive(xAccessible, xContext, xStateSet);
358 }
359 
360 /*****************************************************************************/
361 
detachRecursive(const uno::Reference<accessibility::XAccessible> &,const uno::Reference<accessibility::XAccessibleContext> & xContext,const uno::Reference<accessibility::XAccessibleStateSet> & xStateSet)362 void DocumentFocusListener::detachRecursive(
363     const uno::Reference< accessibility::XAccessible >&,
364     const uno::Reference< accessibility::XAccessibleContext >& xContext,
365     const uno::Reference< accessibility::XAccessibleStateSet >& xStateSet
366 )
367 {
368     uno::Reference< accessibility::XAccessibleEventBroadcaster > xBroadcaster =
369         uno::Reference< accessibility::XAccessibleEventBroadcaster >(xContext, uno::UNO_QUERY);
370 
371     if( xBroadcaster.is() && 0 < m_aRefList.erase(xBroadcaster) )
372     {
373         xBroadcaster->removeEventListener(static_cast< accessibility::XAccessibleEventListener *>(this));
374 
375         if( ! xStateSet->contains(accessibility::AccessibleStateType::MANAGES_DESCENDANTS ) )
376         {
377             sal_Int32 n, nmax = xContext->getAccessibleChildCount();
378             for( n = 0; n < nmax; n++ )
379             {
380                 uno::Reference< accessibility::XAccessible > xChild( xContext->getAccessibleChild( n ) );
381 
382                 if( xChild.is() )
383                     detachRecursive(xChild);
384             }
385         }
386     }
387 }
388 
389 /*****************************************************************************/
390 
391 /*
392  * page tabs in gtk are widgets, so we need to simulate focus events for those
393  */
394 
handle_tabpage_activated(Window * pWindow)395 static void handle_tabpage_activated(Window *pWindow)
396 {
397     uno::Reference< accessibility::XAccessible > xAccessible =
398         pWindow->GetAccessible();
399 
400     if( ! xAccessible.is() )
401         return;
402 
403     uno::Reference< accessibility::XAccessibleSelection > xSelection(
404         xAccessible->getAccessibleContext(), uno::UNO_QUERY);
405 
406     if( xSelection.is() )
407         atk_wrapper_focus_tracker_notify_when_idle( xSelection->getSelectedAccessibleChild(0) );
408 }
409 
410 /*****************************************************************************/
411 
412 /*
413  * toolbar items in gtk are widgets, so we need to simulate focus events for those
414  */
415 
notify_toolbox_item_focus(ToolBox * pToolBox)416 static void notify_toolbox_item_focus(ToolBox *pToolBox)
417 {
418     uno::Reference< accessibility::XAccessible > xAccessible =
419         pToolBox->GetAccessible();
420 
421     if( ! xAccessible.is() )
422         return;
423 
424     uno::Reference< accessibility::XAccessibleContext > xContext =
425         xAccessible->getAccessibleContext();
426 
427     if( ! xContext.is() )
428         return;
429 
430     sal_Int32 nPos = pToolBox->GetItemPos( pToolBox->GetHighlightItemId() );
431     if( nPos != TOOLBOX_ITEM_NOTFOUND )
432         atk_wrapper_focus_tracker_notify_when_idle( xContext->getAccessibleChild( nPos ) );
433 }
434 
handle_toolbox_highlight(Window * pWindow)435 static void handle_toolbox_highlight(Window *pWindow)
436 {
437     ToolBox *pToolBox = static_cast <ToolBox *> (pWindow);
438 
439     // Make sure either the toolbox or its parent toolbox has the focus
440     if ( ! pToolBox->HasFocus() )
441     {
442         ToolBox* pToolBoxParent = dynamic_cast< ToolBox* >( pToolBox->GetParent() );
443         if ( ! pToolBoxParent || ! pToolBoxParent->HasFocus() )
444             return;
445     }
446 
447     notify_toolbox_item_focus(pToolBox);
448 }
449 
handle_toolbox_highlightoff(Window * pWindow)450 static void handle_toolbox_highlightoff(Window *pWindow)
451 {
452     ToolBox *pToolBox = static_cast <ToolBox *> (pWindow);
453     ToolBox* pToolBoxParent = dynamic_cast< ToolBox* >( pToolBox->GetParent() );
454 
455     // Notify when leaving sub toolboxes
456     if( pToolBoxParent && pToolBoxParent->HasFocus() )
457         notify_toolbox_item_focus( pToolBoxParent );
458 }
459 
460 /*****************************************************************************/
461 
create_wrapper_for_child(const uno::Reference<accessibility::XAccessibleContext> & xContext,sal_Int32 index)462 static void create_wrapper_for_child(
463     const uno::Reference< accessibility::XAccessibleContext >& xContext,
464     sal_Int32 index)
465 {
466     if( xContext.is() )
467     {
468         uno::Reference< accessibility::XAccessible > xChild(xContext->getAccessibleChild(index));
469         if( xChild.is() )
470         {
471             // create the wrapper object - it will survive the unref unless it is a transient object
472             g_object_unref( atk_object_wrapper_ref( xChild ) );
473         }
474     }
475 }
476 
477 /*****************************************************************************/
478 
handle_toolbox_buttonchange(VclWindowEvent const * pEvent)479 static void handle_toolbox_buttonchange(VclWindowEvent const *pEvent)
480 {
481     Window* pWindow = pEvent->GetWindow();
482     sal_Int32 index = (sal_Int32)(sal_IntPtr) pEvent->GetData();
483 
484     if( pWindow && pWindow->IsReallyVisible() )
485     {
486         uno::Reference< accessibility::XAccessible > xAccessible(pWindow->GetAccessible());
487         if( xAccessible.is() )
488         {
489             create_wrapper_for_child(xAccessible->getAccessibleContext(), index);
490         }
491     }
492 }
493 
494 /*****************************************************************************/
495 
496 /* currently not needed anymore...
497 static void create_wrapper_for_children(Window *pWindow)
498 {
499     if( pWindow && pWindow->IsReallyVisible() )
500     {
501         uno::Reference< accessibility::XAccessible > xAccessible(pWindow->GetAccessible());
502         if( xAccessible.is() )
503         {
504             uno::Reference< accessibility::XAccessibleContext > xContext(xAccessible->getAccessibleContext());
505             if( xContext.is() )
506             {
507                 sal_Int32 nChildren = xContext->getAccessibleChildCount();
508                 for( sal_Int32 i = 0; i < nChildren; ++i )
509                     create_wrapper_for_child(xContext, i);
510             }
511         }
512     }
513 }
514 */
515 
516 /*****************************************************************************/
517 
518 static std::set< Window * > g_aWindowList;
519 
handle_get_focus(::VclWindowEvent const * pEvent)520 static void handle_get_focus(::VclWindowEvent const * pEvent)
521 {
522     static rtl::Reference< DocumentFocusListener > aDocumentFocusListener =
523         new DocumentFocusListener();
524 
525     Window *pWindow = pEvent->GetWindow();
526 
527     // The menu bar is handled through VCLEVENT_MENU_HIGHLIGHTED
528     if( ! pWindow || !pWindow->IsReallyVisible() || pWindow->GetType() == WINDOW_MENUBARWINDOW )
529         return;
530 
531     // ToolBoxes are handled through VCLEVENT_TOOLBOX_HIGHLIGHT
532     if( pWindow->GetType() == WINDOW_TOOLBOX )
533         return;
534 
535     if( pWindow->GetType() == WINDOW_TABCONTROL )
536     {
537         handle_tabpage_activated( pWindow );
538         return;
539     }
540 
541     uno::Reference< accessibility::XAccessible > xAccessible =
542         pWindow->GetAccessible();
543 
544     if( ! xAccessible.is() )
545         return;
546 
547     uno::Reference< accessibility::XAccessibleContext > xContext =
548         xAccessible->getAccessibleContext();
549 
550     if( ! xContext.is() )
551         return;
552 
553     uno::Reference< accessibility::XAccessibleStateSet > xStateSet =
554         xContext->getAccessibleStateSet();
555 
556     if( ! xStateSet.is() )
557         return;
558 
559 /* the UNO ToolBox wrapper does not (yet?) support XAccessibleSelection, so we
560  * need to add listeners to the children instead of re-using the tabpage stuff
561  */
562     if( xStateSet->contains(accessibility::AccessibleStateType::FOCUSED) &&
563         ( pWindow->GetType() != WINDOW_TREELISTBOX ) )
564     {
565         atk_wrapper_focus_tracker_notify_when_idle( xAccessible );
566     }
567     else
568     {
569         if( g_aWindowList.find(pWindow) == g_aWindowList.end() )
570         {
571             g_aWindowList.insert(pWindow);
572             try
573             {
574                 aDocumentFocusListener->attachRecursive(xAccessible, xContext, xStateSet);
575             }
576             catch( const uno::Exception &e )
577             {
578                 g_warning( "Exception caught processing focus events" );
579             }
580         }
581 #ifdef ENABLE_TRACING
582         else
583             fprintf(stderr, "Window %p already in the list\n", pWindow );
584 #endif
585     }
586 }
587 
588 /*****************************************************************************/
589 
handle_menu_highlighted(::VclMenuEvent const * pEvent)590 static void handle_menu_highlighted(::VclMenuEvent const * pEvent)
591 {
592     try
593     {
594         Menu* pMenu = pEvent->GetMenu();
595         sal_uInt16 nPos = pEvent->GetItemPos();
596 
597         if( pMenu &&  nPos != 0xFFFF)
598         {
599             uno::Reference< accessibility::XAccessible > xAccessible ( pMenu->GetAccessible() );
600 
601             if( xAccessible.is() )
602             {
603                 uno::Reference< accessibility::XAccessibleContext > xContext ( xAccessible->getAccessibleContext() );
604 
605                 if( xContext.is() )
606                     atk_wrapper_focus_tracker_notify_when_idle( xContext->getAccessibleChild( nPos ) );
607             }
608         }
609     }
610     catch( const uno::Exception& e )
611     {
612         g_warning( "Exception caught processing menu highlight events" );
613     }
614 }
615 
616 /*****************************************************************************/
617 
WindowEventHandler(void *,::VclSimpleEvent const * pEvent)618 long WindowEventHandler(void *, ::VclSimpleEvent const * pEvent)
619 {
620     switch (pEvent->GetId())
621     {
622     case VCLEVENT_WINDOW_SHOW:
623 //        fprintf(stderr, "got VCLEVENT_WINDOW_SHOW for %p\n",
624 //            static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
625         break;
626     case VCLEVENT_WINDOW_HIDE:
627 //        fprintf(stderr, "got VCLEVENT_WINDOW_HIDE for %p\n",
628 //            static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
629         break;
630     case VCLEVENT_WINDOW_CLOSE:
631 //        fprintf(stderr, "got VCLEVENT_WINDOW_CLOSE for %p\n",
632 //            static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
633         break;
634     case VCLEVENT_WINDOW_GETFOCUS:
635         handle_get_focus(static_cast< ::VclWindowEvent const * >(pEvent));
636         break;
637     case VCLEVENT_WINDOW_LOSEFOCUS:
638 //        fprintf(stderr, "got VCLEVENT_WINDOW_LOSEFOCUS for %p\n",
639 //            static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
640         break;
641     case VCLEVENT_WINDOW_MINIMIZE:
642 //        fprintf(stderr, "got VCLEVENT_WINDOW_MINIMIZE for %p\n",
643 //            static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
644         break;
645     case VCLEVENT_WINDOW_NORMALIZE:
646 //        fprintf(stderr, "got VCLEVENT_WINDOW_NORMALIZE for %p\n",
647 //            static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
648         break;
649     case VCLEVENT_WINDOW_KEYINPUT:
650     case VCLEVENT_WINDOW_KEYUP:
651     case VCLEVENT_WINDOW_COMMAND:
652     case VCLEVENT_WINDOW_MOUSEMOVE:
653         break;
654  /*
655         fprintf(stderr, "got VCLEVENT_WINDOW_COMMAND (%d) for %p\n",
656             static_cast< ::CommandEvent const * > (
657                 static_cast< ::VclWindowEvent const * >(pEvent)->GetData())->GetCommand(),
658             static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
659  */
660     case VCLEVENT_MENU_HIGHLIGHT:
661         if (const VclMenuEvent* pMenuEvent = dynamic_cast<const VclMenuEvent*>(pEvent))
662         {
663             handle_menu_highlighted(pMenuEvent);
664         }
665         else if (const VclAccessibleEvent* pAccEvent = dynamic_cast<const VclAccessibleEvent*>(pEvent))
666         {
667             uno::Reference< accessibility::XAccessible > xAccessible = pAccEvent->GetAccessible();
668             if (xAccessible.is())
669                 atk_wrapper_focus_tracker_notify_when_idle(xAccessible);
670         }
671         break;
672 
673     case VCLEVENT_TOOLBOX_HIGHLIGHT:
674         handle_toolbox_highlight(static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
675         break;
676 
677     case VCLEVENT_TOOLBOX_BUTTONSTATECHANGED:
678         handle_toolbox_buttonchange(static_cast< ::VclWindowEvent const * >(pEvent));
679         break;
680 
681     case VCLEVENT_OBJECT_DYING:
682         g_aWindowList.erase( static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow() );
683         // fallthrough intentional !
684     case VCLEVENT_TOOLBOX_HIGHLIGHTOFF:
685         handle_toolbox_highlightoff(static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
686         break;
687 
688     case VCLEVENT_TABPAGE_ACTIVATE:
689         handle_tabpage_activated(static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
690         break;
691 
692     case VCLEVENT_COMBOBOX_SETTEXT:
693         // MT 2010/02: This looks quite strange to me. Stumbled over this when fixing #i104290#.
694         // This kicked in when leaving the combobox in the toolbar, after that the events worked.
695         // 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.
696         // Fix for #i104290# was done in toolkit/source/awt/vclxaccessiblecomponent, FOCUSED state for compound controls in general.
697         // create_wrapper_for_children(static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow());
698         break;
699 
700     default:
701 //        OSL_TRACE("got event %d \n", pEvent->GetId());
702         break;
703     }
704     return 0;
705 }
706 
707 static Link g_aEventListenerLink( NULL, (PSTUB) WindowEventHandler );
708 
709 /*****************************************************************************/
710 
711 extern "C" {
712 
713 static G_CONST_RETURN gchar *
ooo_atk_util_get_toolkit_name(void)714 ooo_atk_util_get_toolkit_name (void)
715 {
716     return "VCL";
717 }
718 
719 /*****************************************************************************/
720 
721 static G_CONST_RETURN gchar *
ooo_atk_util_get_toolkit_version(void)722 ooo_atk_util_get_toolkit_version (void)
723 {
724     /*
725      * Version is passed in as a -D flag when this file is
726      * compiled.
727      */
728 
729     return VERSION;
730 }
731 
732 /*****************************************************************************/
733 
734 /*
735  * GObject inheritance
736  */
737 
738 static void
ooo_atk_util_class_init(AtkUtilClass *)739 ooo_atk_util_class_init (AtkUtilClass *)
740 {
741     AtkUtilClass *atk_class;
742     gpointer data;
743 
744     data = g_type_class_peek (ATK_TYPE_UTIL);
745     atk_class = ATK_UTIL_CLASS (data);
746 
747     atk_class->get_toolkit_name = ooo_atk_util_get_toolkit_name;
748     atk_class->get_toolkit_version = ooo_atk_util_get_toolkit_version;
749 
750     Application::AddEventListener( g_aEventListenerLink );
751 }
752 
753 } // extern "C"
754 
755 /*****************************************************************************/
756 
757 GType
ooo_atk_util_get_type(void)758 ooo_atk_util_get_type (void)
759 {
760     static GType type = 0;
761 
762     if (!type)
763     {
764         GType parent_type = g_type_from_name( "GailUtil" );
765 
766         if( ! parent_type )
767         {
768             g_warning( "Unknown type: GailUtil" );
769             parent_type = ATK_TYPE_UTIL;
770         }
771 
772         GTypeQuery type_query;
773         g_type_query( parent_type, &type_query );
774 
775         static const GTypeInfo typeInfo =
776         {
777             (guint16) type_query.class_size,
778             (GBaseInitFunc) NULL,
779             (GBaseFinalizeFunc) NULL,
780             (GClassInitFunc) ooo_atk_util_class_init,
781             (GClassFinalizeFunc) NULL,
782             NULL,
783             (guint16) type_query.instance_size,
784             0,
785             (GInstanceInitFunc) NULL,
786             NULL
787         } ;
788 
789         type = g_type_register_static (parent_type, "OOoUtil", &typeInfo, (GTypeFlags)0) ;
790   }
791 
792   return type;
793 }
794