1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 package org.openoffice.accessibility;
24 
25 import com.sun.star.accessibility.AccessibleRole;
26 import com.sun.star.accessibility.XAccessible;
27 import com.sun.star.accessibility.XAccessibleContext;
28 import com.sun.star.awt.XExtendedToolkit;
29 import com.sun.star.awt.XTopWindow;
30 import com.sun.star.awt.XTopWindowListener;
31 import com.sun.star.awt.XWindow;
32 import com.sun.star.comp.loader.FactoryHelper;
33 import com.sun.star.lang.XComponent;
34 import com.sun.star.lang.XInitialization;
35 import com.sun.star.lang.XMultiServiceFactory;
36 import com.sun.star.lang.XSingleServiceFactory;
37 import com.sun.star.registry.*;
38 import com.sun.star.uno.*;
39 
40 import org.openoffice.java.accessibility.*;
41 
42 import java.lang.reflect.InvocationTargetException;
43 import java.lang.reflect.Method;
44 
45 import javax.accessibility.Accessible;
46 
47 
48 public class AccessBridge {
49     //
50     protected static java.util.Hashtable topWindowMap = new java.util.Hashtable();
51 
getTopWindowImpl(XAccessible xAccessible)52     private static java.awt.Window getTopWindowImpl(XAccessible xAccessible) {
53         // Because it can not be garantied that
54         // WindowsAccessBridgeAdapter.registerTopWindow() is called
55         // before windowOpened(), we have to make this operation
56         // atomic.
57         synchronized (topWindowMap) {
58             String oid = UnoRuntime.generateOid(xAccessible);
59             java.awt.Window w = (java.awt.Window) topWindowMap.get(oid);
60 
61             if (w == null) {
62                 w = AccessibleObjectFactory.getTopWindow(xAccessible);
63 
64                 if (w != null) {
65                     topWindowMap.put(oid, w);
66                 }
67             }
68 
69             return w;
70         }
71     }
72 
getTopWindow(XAccessible xAccessible)73     protected static java.awt.Window getTopWindow(XAccessible xAccessible) {
74         if (xAccessible != null) {
75             XAccessibleContext xAccessibleContext = xAccessible.getAccessibleContext();
76             if (xAccessibleContext != null) {
77 
78                 // Toolkit reports the VCL peer windows as toplevels. These have an
79                 // accessible parent which represents the native frame window
80                 switch(xAccessibleContext.getAccessibleRole()) {
81                     case AccessibleRole.ROOT_PANE:
82                     case AccessibleRole.POPUP_MENU:
83                         return getTopWindow(xAccessibleContext.getAccessibleParent());
84 
85                     case AccessibleRole.WINDOW:
86                     case AccessibleRole.FRAME:
87                     case AccessibleRole.DIALOG:
88                     case AccessibleRole.ALERT:
89                         return getTopWindowImpl(xAccessible);
90 
91                     default:
92                         break;
93                 }
94             }
95         }
96 
97         return null;
98     }
99 
removeTopWindow(XAccessible xAccessible)100     protected static java.awt.Window removeTopWindow(XAccessible xAccessible) {
101         if (xAccessible != null) {
102             XAccessibleContext xAccessibleContext = xAccessible.getAccessibleContext();
103             if (xAccessibleContext != null) {
104 
105                 // Toolkit reports the VCL peer windows as toplevels. These have an
106                 // accessible parent which represents the native frame window
107                 switch(xAccessibleContext.getAccessibleRole()) {
108                     case AccessibleRole.ROOT_PANE:
109                     case AccessibleRole.POPUP_MENU:
110                         return removeTopWindow(xAccessibleContext.getAccessibleParent());
111 
112                     case AccessibleRole.WINDOW:
113                     case AccessibleRole.FRAME:
114                     case AccessibleRole.DIALOG:
115                         return (java.awt.Window) topWindowMap.remove(UnoRuntime.generateOid(xAccessible));
116 
117                     default:
118                         break;
119                 }
120             }
121         }
122 
123         return null;
124     }
125 
__getServiceFactory(String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey)126     public static XSingleServiceFactory __getServiceFactory(String implName,
127         XMultiServiceFactory multiFactory, XRegistryKey regKey) {
128         XSingleServiceFactory xSingleServiceFactory = null;
129 
130         if (implName.equals(AccessBridge.class.getName())) {
131             // Initialize toolkit to register at Java <-> Windows access bridge
132             java.awt.Toolkit tk = java.awt.Toolkit.getDefaultToolkit();
133 
134             xSingleServiceFactory = FactoryHelper.getServiceFactory(_AccessBridge.class,
135                     _AccessBridge._serviceName, multiFactory, regKey);
136         }
137 
138         return xSingleServiceFactory;
139     }
140 
141     static public class _AccessBridge implements XTopWindowListener,
142         XInitialization, XComponent {
143         static final String _serviceName = "com.sun.star.accessibility.AccessBridge";
144         XComponentContext xComponentContext;
145 
_AccessBridge(XComponentContext xComponentContext)146         public _AccessBridge(XComponentContext xComponentContext) {
147             this.xComponentContext = xComponentContext;
148         }
149 
150         /*
151         * XInitialization
152         */
initialize(java.lang.Object[] arguments)153         public void initialize(java.lang.Object[] arguments) {
154             try {
155                 // FIXME: Currently there is no way to determine if key event forwarding is needed or not,
156                 // so we have to do it always ..
157                 XExtendedToolkit unoToolkit = (XExtendedToolkit) AnyConverter.toObject(new Type(
158                             XExtendedToolkit.class), arguments[0]);
159 
160                 if (unoToolkit != null) {
161                     // FIXME this should be done in VCL
162                     unoToolkit.addTopWindowListener(this);
163 
164                     String os = (String) System.getProperty("os.name");
165 
166                     // Try to initialize the WindowsAccessBridgeAdapter
167                     if (os.startsWith("Windows")) {
168                         WindowsAccessBridgeAdapter.attach(xComponentContext);
169                     } else {
170                         unoToolkit.addKeyHandler(new KeyHandler());
171                     }
172                 } else if (Build.DEBUG) {
173                     System.err.println(
174                         "argument 0 is not of type XExtendedToolkit.");
175                 }
176             } catch (com.sun.star.lang.IllegalArgumentException e) {
177                 // FIXME: output
178             }
179         }
180 
181         /*
182         * XTopWindowListener
183         */
windowOpened(com.sun.star.lang.EventObject event)184         public void windowOpened(com.sun.star.lang.EventObject event) {
185             XAccessible xAccessible = (XAccessible) UnoRuntime.queryInterface(XAccessible.class,
186                     event.Source);
187             java.awt.Window w = getTopWindow(xAccessible);
188         }
189 
windowActivated(com.sun.star.lang.EventObject event)190         public void windowActivated(com.sun.star.lang.EventObject event) {
191         }
192 
windowDeactivated(com.sun.star.lang.EventObject event)193         public void windowDeactivated(com.sun.star.lang.EventObject event) {
194         }
195 
windowMinimized(com.sun.star.lang.EventObject event)196         public void windowMinimized(com.sun.star.lang.EventObject event) {
197         }
198 
windowNormalized(com.sun.star.lang.EventObject event)199         public void windowNormalized(com.sun.star.lang.EventObject event) {
200         }
201 
windowClosing(com.sun.star.lang.EventObject event)202         public void windowClosing(com.sun.star.lang.EventObject event) {
203         }
204 
windowClosed(com.sun.star.lang.EventObject event)205         public void windowClosed(com.sun.star.lang.EventObject event) {
206             XAccessible xAccessible = (XAccessible) UnoRuntime.queryInterface(XAccessible.class,
207                     event.Source);
208 
209             java.awt.Window w = removeTopWindow(xAccessible);
210 
211             if (w != null) {
212                 w.dispose();
213             }
214         }
215 
disposing(com.sun.star.lang.EventObject event)216         public void disposing(com.sun.star.lang.EventObject event) {
217         }
218 
219         /*
220         * XComponent
221         */
222 
addEventListener(com.sun.star.lang.XEventListener listener)223         public void addEventListener(com.sun.star.lang.XEventListener listener) {
224         }
225 
removeEventListener(com.sun.star.lang.XEventListener listener)226         public void removeEventListener(com.sun.star.lang.XEventListener listener) {
227         }
228 
dispose()229         public void dispose() {
230             try {
231                 java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue().invokeAndWait(
232                     new Runnable() {
233                         public void run() {
234                         }
235                     } );
236             } catch (java.lang.InterruptedException e) {
237             } catch (java.lang.reflect.InvocationTargetException e) {
238             }
239         }
240     }
241 }
242