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