Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <unx/gtk/gtkframe.hxx>
31 : : #include <vcl/svapp.hxx>
32 : : #include <vcl/window.hxx>
33 : : #include "vcl/popupmenuwindow.hxx"
34 : :
35 : : #include "atkwindow.hxx"
36 : : #include "atkwrapper.hxx"
37 : : #include "atkregistry.hxx"
38 : :
39 : : #include <com/sun/star/accessibility/AccessibleRole.hpp>
40 : :
41 : : using namespace ::com::sun::star::accessibility;
42 : : using namespace ::com::sun::star::uno;
43 : :
44 : : extern "C" {
45 : :
46 : : static void (* window_real_initialize) (AtkObject *obj, gpointer data) = NULL;
47 : : static void (* window_real_finalize) (GObject *obj) = NULL;
48 : :
49 : : static void
50 : 0 : init_from_window( AtkObject *accessible, Window *pWindow )
51 : : {
52 : : static AtkRole aDefaultRole = ATK_ROLE_INVALID;
53 : :
54 : : // Special role for sub-menu and combo-box popups that are exposed directly
55 : : // by their parents already.
56 : 0 : if( aDefaultRole == ATK_ROLE_INVALID )
57 : 0 : aDefaultRole = atk_role_register( "redundant object" );
58 : :
59 : 0 : AtkRole role = aDefaultRole;
60 : :
61 : : // Determine the appropriate role for the GtkWindow
62 : 0 : switch( pWindow->GetAccessibleRole() )
63 : : {
64 : : case AccessibleRole::ALERT:
65 : 0 : role = ATK_ROLE_ALERT;
66 : 0 : break;
67 : :
68 : : case AccessibleRole::DIALOG:
69 : 0 : role = ATK_ROLE_DIALOG;
70 : 0 : break;
71 : :
72 : : case AccessibleRole::FRAME:
73 : 0 : role = ATK_ROLE_FRAME;
74 : 0 : break;
75 : :
76 : : /* Ignore window objects for sub-menus, combo- and list boxes,
77 : : * which are exposed as children of their parents.
78 : : */
79 : : case AccessibleRole::WINDOW:
80 : : {
81 : 0 : sal_uInt16 type = WINDOW_WINDOW;
82 : 0 : bool parentIsMenuFloatingWindow = false;
83 : :
84 : 0 : Window *pParent = pWindow->GetParent();
85 : 0 : if( pParent ) {
86 : 0 : type = pParent->GetType();
87 : 0 : parentIsMenuFloatingWindow = ( TRUE == pParent->IsMenuFloatingWindow() );
88 : : }
89 : :
90 : 0 : if( (WINDOW_LISTBOX != type) && (WINDOW_COMBOBOX != type) &&
91 : 0 : (WINDOW_MENUBARWINDOW != type) && ! parentIsMenuFloatingWindow )
92 : : {
93 : 0 : role = ATK_ROLE_WINDOW;
94 : : }
95 : : }
96 : 0 : break;
97 : :
98 : : default:
99 : : {
100 : 0 : Window *pChild = pWindow->GetChild( 0 );
101 : 0 : if( pChild )
102 : : {
103 : 0 : if( WINDOW_HELPTEXTWINDOW == pChild->GetType() )
104 : : {
105 : 0 : role = ATK_ROLE_TOOL_TIP;
106 : 0 : pChild->SetAccessibleRole( AccessibleRole::LABEL );
107 : 0 : accessible->name = g_strdup( rtl::OUStringToOString( pChild->GetText(), RTL_TEXTENCODING_UTF8 ).getStr() );
108 : : }
109 : 0 : else if ( pWindow->GetType() == WINDOW_BORDERWINDOW && pChild->GetType() == WINDOW_FLOATINGWINDOW )
110 : : {
111 : 0 : PopupMenuFloatingWindow* p = dynamic_cast<PopupMenuFloatingWindow*>(pChild);
112 : 0 : if (p && p->IsPopupMenu() && p->GetMenuStackLevel() == 0)
113 : : {
114 : : // This is a top-level menu popup. Register it.
115 : 0 : role = ATK_ROLE_POPUP_MENU;
116 : 0 : pChild->SetAccessibleRole( AccessibleRole::POPUP_MENU );
117 : 0 : accessible->name = g_strdup( rtl::OUStringToOString( pChild->GetText(), RTL_TEXTENCODING_UTF8 ).getStr() );
118 : : }
119 : : }
120 : : }
121 : 0 : break;
122 : : }
123 : : }
124 : :
125 : 0 : accessible->role = role;
126 : 0 : }
127 : :
128 : : /*****************************************************************************/
129 : :
130 : : static gint
131 : 0 : ooo_window_wrapper_clear_focus(gpointer)
132 : : {
133 : 0 : SolarMutexGuard aGuard;
134 : 0 : atk_focus_tracker_notify( NULL );
135 : 0 : return FALSE;
136 : : }
137 : :
138 : : /*****************************************************************************/
139 : :
140 : : static gboolean
141 : 0 : ooo_window_wrapper_real_focus_gtk (GtkWidget *, GdkEventFocus *)
142 : : {
143 : 0 : g_idle_add( ooo_window_wrapper_clear_focus, NULL );
144 : 0 : return FALSE;
145 : : }
146 : :
147 : 0 : static gboolean ooo_tooltip_map( GtkWidget* pToolTip, gpointer )
148 : : {
149 : 0 : AtkObject* pAccessible = gtk_widget_get_accessible( pToolTip );
150 : 0 : if( pAccessible )
151 : 0 : atk_object_notify_state_change( pAccessible, ATK_STATE_SHOWING, TRUE );
152 : 0 : return FALSE;
153 : : }
154 : :
155 : 0 : static gboolean ooo_tooltip_unmap( GtkWidget* pToolTip, gpointer )
156 : : {
157 : 0 : AtkObject* pAccessible = gtk_widget_get_accessible( pToolTip );
158 : 0 : if( pAccessible )
159 : 0 : atk_object_notify_state_change( pAccessible, ATK_STATE_SHOWING, FALSE );
160 : 0 : return FALSE;
161 : : }
162 : :
163 : : /*****************************************************************************/
164 : :
165 : : static bool
166 : 0 : isChildPopupMenu(Window* pWindow)
167 : : {
168 : 0 : Window* pChild = pWindow->GetAccessibleChildWindow(0);
169 : 0 : if (!pChild)
170 : 0 : return false;
171 : :
172 : 0 : if (WINDOW_FLOATINGWINDOW != pChild->GetType())
173 : 0 : return false;
174 : :
175 : 0 : PopupMenuFloatingWindow* p = dynamic_cast<PopupMenuFloatingWindow*>(pChild);
176 : 0 : if (!p)
177 : 0 : return false;
178 : :
179 : 0 : return p->IsPopupMenu();
180 : : }
181 : :
182 : : static void
183 : 0 : ooo_window_wrapper_real_initialize(AtkObject *obj, gpointer data)
184 : : {
185 : 0 : window_real_initialize(obj, data);
186 : :
187 : 0 : GtkSalFrame *pFrame = GtkSalFrame::getFromWindow( GTK_WINDOW( data ) );
188 : 0 : if( pFrame )
189 : : {
190 : 0 : Window *pWindow = pFrame->GetWindow();
191 : 0 : if( pWindow )
192 : : {
193 : 0 : init_from_window( obj, pWindow );
194 : :
195 : 0 : Reference< XAccessible > xAccessible( pWindow->GetAccessible(true) );
196 : :
197 : : /* We need the wrapper object for the top-level XAccessible to be
198 : : * in the wrapper registry when atk traverses the hierachy up on
199 : : * focus events
200 : : */
201 : 0 : if( WINDOW_BORDERWINDOW == pWindow->GetType() )
202 : : {
203 : 0 : if ( isChildPopupMenu(pWindow) )
204 : : {
205 : 0 : AtkObject *child = atk_object_wrapper_new( xAccessible, obj );
206 : 0 : ooo_wrapper_registry_add( xAccessible, child );
207 : : }
208 : : else
209 : : {
210 : 0 : ooo_wrapper_registry_add( xAccessible, obj );
211 : 0 : g_object_set_data( G_OBJECT(obj), "ooo:atk-wrapper-key", xAccessible.get() );
212 : : }
213 : : }
214 : : else
215 : : {
216 : 0 : AtkObject *child = atk_object_wrapper_new( xAccessible, obj );
217 : 0 : child->role = ATK_ROLE_FILLER;
218 : 0 : if( (ATK_ROLE_DIALOG == obj->role) || (ATK_ROLE_ALERT == obj->role) )
219 : 0 : child->role = ATK_ROLE_OPTION_PANE;
220 : 0 : ooo_wrapper_registry_add( xAccessible, child );
221 : 0 : }
222 : : }
223 : : }
224 : :
225 : 0 : g_signal_connect_after( GTK_WIDGET( data ), "focus-out-event",
226 : : G_CALLBACK (ooo_window_wrapper_real_focus_gtk),
227 : 0 : NULL);
228 : :
229 : 0 : if( obj->role == ATK_ROLE_TOOL_TIP )
230 : : {
231 : 0 : g_signal_connect_after( GTK_WIDGET( data ), "map-event",
232 : : G_CALLBACK (ooo_tooltip_map),
233 : 0 : NULL);
234 : 0 : g_signal_connect_after( GTK_WIDGET( data ), "unmap-event",
235 : : G_CALLBACK (ooo_tooltip_unmap),
236 : 0 : NULL);
237 : : }
238 : 0 : }
239 : :
240 : : /*****************************************************************************/
241 : :
242 : : static void
243 : 0 : ooo_window_wrapper_real_finalize (GObject *obj)
244 : : {
245 : 0 : ooo_wrapper_registry_remove( (XAccessible *) g_object_get_data( obj, "ooo:atk-wrapper-key" ));
246 : 0 : window_real_finalize( obj );
247 : 0 : }
248 : :
249 : : /*****************************************************************************/
250 : :
251 : : static void
252 : 0 : ooo_window_wrapper_class_init (AtkObjectClass *klass, gpointer)
253 : : {
254 : : AtkObjectClass *atk_class;
255 : : GObjectClass *gobject_class;
256 : : gpointer data;
257 : :
258 : : /*
259 : : * Patch the gobject vtable of GailWindow to refer to our instance of
260 : : * "initialize".
261 : : */
262 : :
263 : 0 : data = g_type_class_peek_parent( klass );
264 : 0 : atk_class = ATK_OBJECT_CLASS (data);
265 : :
266 : 0 : window_real_initialize = atk_class->initialize;
267 : 0 : atk_class->initialize = ooo_window_wrapper_real_initialize;
268 : :
269 : 0 : gobject_class = G_OBJECT_CLASS (data);
270 : :
271 : 0 : window_real_finalize = gobject_class->finalize;
272 : 0 : gobject_class->finalize = ooo_window_wrapper_real_finalize;
273 : 0 : }
274 : :
275 : : } // extern "C"
276 : :
277 : : /*****************************************************************************/
278 : :
279 : : GType
280 : 0 : ooo_window_wrapper_get_type (void)
281 : : {
282 : : static GType type = 0;
283 : :
284 : 0 : if (!type)
285 : : {
286 : 0 : GType parent_type = g_type_from_name( "GailWindow" );
287 : :
288 : 0 : if( ! parent_type )
289 : : {
290 : 0 : g_warning( "Unknown type: GailWindow" );
291 : 0 : parent_type = ATK_TYPE_OBJECT;
292 : : }
293 : :
294 : : GTypeQuery type_query;
295 : 0 : g_type_query( parent_type, &type_query );
296 : :
297 : : static const GTypeInfo typeInfo =
298 : : {
299 : : static_cast<guint16>(type_query.class_size),
300 : : (GBaseInitFunc) NULL,
301 : : (GBaseFinalizeFunc) NULL,
302 : : (GClassInitFunc) ooo_window_wrapper_class_init,
303 : : (GClassFinalizeFunc) NULL,
304 : : NULL,
305 : : static_cast<guint16>(type_query.instance_size),
306 : : 0,
307 : : (GInstanceInitFunc) NULL,
308 : : NULL
309 : 0 : } ;
310 : :
311 : 0 : type = g_type_register_static (parent_type, "OOoWindowAtkObject", &typeInfo, (GTypeFlags)0) ;
312 : : }
313 : :
314 : 0 : return type;
315 : : }
316 : :
317 : 0 : void restore_gail_window_vtable (void)
318 : : {
319 : : AtkObjectClass *atk_class;
320 : : gpointer data;
321 : :
322 : 0 : GType type = g_type_from_name( "GailWindow" );
323 : :
324 : 0 : if( type == G_TYPE_INVALID )
325 : 0 : return;
326 : :
327 : 0 : data = g_type_class_peek( type );
328 : 0 : atk_class = ATK_OBJECT_CLASS (data);
329 : :
330 : 0 : atk_class->initialize = window_real_initialize;
331 : : }
332 : :
333 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|