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