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