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