]>
Commit | Line | Data |
---|---|---|
0676719a JK |
1 | diff -durN -x '*~' -x '*.orig' -x '*.rej' openjdk.orig/jdk/src/share/classes/java/awt/SystemTray.java openjdk/jdk/src/share/classes/java/awt/SystemTray.java |
2 | --- openjdk.orig/jdk/src/share/classes/java/awt/SystemTray.java 2010-02-17 04:14:21.000000000 +0100 | |
3 | +++ openjdk/jdk/src/share/classes/java/awt/SystemTray.java 2010-11-27 19:29:43.661160073 +0100 | |
4 | @@ -125,6 +125,8 @@ | |
5 | ||
6 | transient private SystemTrayPeer peer; | |
7 | ||
8 | + private static final TrayIcon[] EMPTY_TRAY_ARRAY = new TrayIcon[0]; | |
9 | + | |
10 | /** | |
11 | * Private <code>SystemTray</code> constructor. | |
12 | * | |
13 | @@ -164,16 +166,14 @@ | |
14 | if (GraphicsEnvironment.isHeadless()) { | |
15 | throw new HeadlessException(); | |
16 | } | |
17 | + | |
18 | + initializeSystemTrayIfNeeded(); | |
19 | + | |
20 | if (!isSupported()) { | |
21 | throw new UnsupportedOperationException( | |
22 | "The system tray is not supported on the current platform."); | |
23 | } | |
24 | ||
25 | - synchronized (SystemTray.class) { | |
26 | - if (systemTray == null) { | |
27 | - systemTray = new SystemTray(); | |
28 | - } | |
29 | - } | |
30 | return systemTray; | |
31 | } | |
32 | ||
33 | @@ -203,15 +203,18 @@ | |
34 | * functionality is supported for the current platform | |
35 | */ | |
36 | public static boolean isSupported() { | |
37 | - if (Toolkit.getDefaultToolkit() instanceof SunToolkit) { | |
38 | - | |
39 | - return ((SunToolkit)Toolkit.getDefaultToolkit()).isTraySupported(); | |
40 | - | |
41 | - } else if (Toolkit.getDefaultToolkit() instanceof HeadlessToolkit) { | |
42 | - | |
43 | - return ((HeadlessToolkit)Toolkit.getDefaultToolkit()).isTraySupported(); | |
44 | + Toolkit toolkit = Toolkit.getDefaultToolkit(); | |
45 | + if (toolkit instanceof SunToolkit) { | |
46 | + // connecting tray to native resource | |
47 | + initializeSystemTrayIfNeeded(); | |
48 | + return ((SunToolkit)toolkit).isTraySupported(); | |
49 | + } else if (toolkit instanceof HeadlessToolkit) { | |
50 | + // skip initialization as the init routine | |
51 | + // throws HeadlessException | |
52 | + return ((HeadlessToolkit)toolkit).isTraySupported(); | |
53 | + } else { | |
54 | + return false; | |
55 | } | |
56 | - return false; | |
57 | } | |
58 | ||
59 | /** | |
60 | @@ -323,7 +326,7 @@ | |
61 | if (icons != null) { | |
62 | return (TrayIcon[])icons.toArray(new TrayIcon[icons.size()]); | |
63 | } | |
64 | - return new TrayIcon[0]; | |
65 | + return EMPTY_TRAY_ARRAY; | |
66 | } | |
67 | ||
68 | /** | |
69 | @@ -343,19 +346,32 @@ | |
70 | } | |
71 | ||
72 | /** | |
73 | - * Adds a {@code PropertyChangeListener} to the listener list for a | |
74 | - * specific property. Currently supported property: | |
75 | - * <ul> | |
76 | - * <li>{@code trayIcons}<p> | |
77 | - * <p> | |
78 | - * This {@code SystemTray}'s array of {@code TrayIcon}s. | |
79 | - * The array is accessed via {@link SystemTray#getTrayIcons}.<br> | |
80 | - * This property is changed when a {@code TrayIcon} is added to | |
81 | - * (or removed from) the {@code SystemTray}.<br> For example, this property | |
82 | - * is changed when the native {@code SystemTray} becomes unavailable on the | |
83 | - * desktop<br> and the {@code TrayIcon}s are automatically removed.</li> | |
84 | - * </ul> | |
85 | - * <p> | |
86 | + * Adds a {@code PropertyChangeListener} to the list of listeners for the | |
87 | + * specific property. The following properties are currently supported: | |
88 | + * <p> </p> | |
89 | + * <table border=1 summary="SystemTray properties"> | |
90 | + * <tr> | |
91 | + * <th>Property</th> | |
92 | + * <th>Description</th> | |
93 | + * </tr> | |
94 | + * <tr> | |
95 | + * <td>{@code trayIcons}</td> | |
96 | + * <td>The {@code SystemTray}'s array of {@code TrayIcon} objects. | |
97 | + * The array is accessed via the {@link #getTrayIcons} method.<br> | |
98 | + * This property is changed when a tray icon is added to (or removed | |
99 | + * from) the system tray.<br> For example, this property is changed | |
100 | + * when the system tray becomes unavailable on the desktop<br> | |
101 | + * and the tray icons are automatically removed.</td> | |
102 | + * </tr> | |
103 | + * <tr> | |
104 | + * <td>{@code systemTray}</td> | |
105 | + * <td>This property contains {@code SystemTray} instance when the system tray | |
106 | + * is available or <code>null</code> otherwise.<br> This property is changed | |
107 | + * when the system tray becomes available or unavailable on the desktop.<br> | |
108 | + * The property is accessed by the {@link #getSystemTray} method.</td> | |
109 | + * </tr> | |
110 | + * </table> | |
111 | + * <p> </p> | |
112 | * The {@code listener} listens to property changes only in this context. | |
113 | * <p> | |
114 | * If {@code listener} is {@code null}, no exception is thrown | |
115 | @@ -462,7 +478,12 @@ | |
116 | ||
117 | synchronized void addNotify() { | |
118 | if (peer == null) { | |
119 | - peer = ((SunToolkit)Toolkit.getDefaultToolkit()).createSystemTray(this); | |
120 | + Toolkit toolkit = Toolkit.getDefaultToolkit(); | |
121 | + if (toolkit instanceof SunToolkit) { | |
122 | + peer = ((SunToolkit)Toolkit.getDefaultToolkit()).createSystemTray(this); | |
123 | + } else if (toolkit instanceof HeadlessToolkit) { | |
124 | + peer = ((HeadlessToolkit)Toolkit.getDefaultToolkit()).createSystemTray(this); | |
125 | + } | |
126 | } | |
127 | } | |
128 | ||
129 | @@ -472,4 +493,12 @@ | |
130 | security.checkPermission(SecurityConstants.ACCESS_SYSTEM_TRAY_PERMISSION); | |
131 | } | |
132 | } | |
133 | + | |
134 | + private static void initializeSystemTrayIfNeeded() { | |
135 | + synchronized (SystemTray.class) { | |
136 | + if (systemTray == null) { | |
137 | + systemTray = new SystemTray(); | |
138 | + } | |
139 | + } | |
140 | + } | |
141 | } | |
142 | diff -durN -x '*~' -x '*.orig' -x '*.rej' openjdk.orig/jdk/src/solaris/classes/sun/awt/X11/XMSelection.java openjdk/jdk/src/solaris/classes/sun/awt/X11/XMSelection.java | |
143 | --- openjdk.orig/jdk/src/solaris/classes/sun/awt/X11/XMSelection.java 2010-02-17 04:14:46.000000000 +0100 | |
144 | +++ openjdk/jdk/src/solaris/classes/sun/awt/X11/XMSelection.java 2010-11-27 19:29:43.661160073 +0100 | |
145 | @@ -254,7 +254,7 @@ | |
146 | } | |
147 | ||
148 | public synchronized void removeSelectionListener(XMSelectionListener listener) { | |
149 | - if (listeners == null) { | |
150 | + if (listeners != null) { | |
151 | listeners.remove(listener); | |
152 | } | |
153 | } | |
154 | diff -durN -x '*~' -x '*.orig' -x '*.rej' openjdk.orig/jdk/src/solaris/classes/sun/awt/X11/XSystemTrayPeer.java openjdk/jdk/src/solaris/classes/sun/awt/X11/XSystemTrayPeer.java | |
155 | --- openjdk.orig/jdk/src/solaris/classes/sun/awt/X11/XSystemTrayPeer.java 2010-02-17 04:14:46.000000000 +0100 | |
156 | +++ openjdk/jdk/src/solaris/classes/sun/awt/X11/XSystemTrayPeer.java 2010-11-27 19:29:43.661160073 +0100 | |
157 | @@ -27,47 +27,94 @@ | |
158 | ||
159 | import java.awt.*; | |
160 | import java.awt.peer.SystemTrayPeer; | |
161 | +import java.lang.reflect.Method; | |
162 | +import java.lang.reflect.InvocationTargetException; | |
163 | +import java.util.logging.Logger; | |
164 | +import sun.awt.SunToolkit; | |
165 | +import sun.awt.AppContext; | |
166 | + | |
167 | +public class XSystemTrayPeer implements SystemTrayPeer, XMSelectionListener { | |
168 | + private static final Logger log = Logger.getLogger("sun.awt.X11.XSystemTrayPeer"); | |
169 | ||
170 | -public class XSystemTrayPeer implements SystemTrayPeer { | |
171 | SystemTray target; | |
172 | - long tray_owner; | |
173 | static XSystemTrayPeer peerInstance; // there is only one SystemTray peer per application | |
174 | ||
175 | - final static XAtom _NET_SYSTEM_TRAY = XAtom.get("_NET_SYSTEM_TRAY_S0"); | |
176 | - final static XAtom _XEMBED_INFO = XAtom.get("_XEMBED_INFO"); | |
177 | - final static XAtom _NET_SYSTEM_TRAY_OPCODE = XAtom.get("_NET_SYSTEM_TRAY_OPCODE"); | |
178 | - final static XAtom _NET_WM_ICON = XAtom.get("_NET_WM_ICON"); | |
179 | - final static long SYSTEM_TRAY_REQUEST_DOCK = 0; | |
180 | + private volatile boolean available; | |
181 | + private final XMSelection selection = new XMSelection("_NET_SYSTEM_TRAY"); | |
182 | + | |
183 | + private static final Method firePropertyChangeMethod = | |
184 | + XToolkit.getMethod(SystemTray.class, "firePropertyChange", new Class[] {String.class, Object.class, Object.class}); | |
185 | + private static final Method addNotifyMethod = XToolkit.getMethod(TrayIcon.class, "addNotify", null); | |
186 | + private static final Method removeNotifyMethod = XToolkit.getMethod(TrayIcon.class, "removeNotify", null); | |
187 | + | |
188 | + private static final int SCREEN = 0; | |
189 | + private static final String SYSTEM_TRAY_PROPERTY_NAME = "systemTray"; | |
190 | + private static final XAtom _NET_SYSTEM_TRAY = XAtom.get("_NET_SYSTEM_TRAY_S" + SCREEN); | |
191 | + private static final XAtom _XEMBED_INFO = XAtom.get("_XEMBED_INFO"); | |
192 | + private static final XAtom _NET_SYSTEM_TRAY_OPCODE = XAtom.get("_NET_SYSTEM_TRAY_OPCODE"); | |
193 | + private static final XAtom _NET_WM_ICON = XAtom.get("_NET_WM_ICON"); | |
194 | + private static final long SYSTEM_TRAY_REQUEST_DOCK = 0; | |
195 | ||
196 | XSystemTrayPeer(SystemTray target) { | |
197 | this.target = target; | |
198 | peerInstance = this; | |
199 | ||
200 | - XToolkit.awtLock(); | |
201 | - try { | |
202 | - tray_owner = XlibWrapper.XGetSelectionOwner(XToolkit.getDisplay(), _NET_SYSTEM_TRAY.getAtom()); | |
203 | - } finally { | |
204 | - XToolkit.awtUnlock(); | |
205 | + selection.addSelectionListener(this); | |
206 | + | |
207 | + long selection_owner = selection.getOwner(SCREEN); | |
208 | + available = (selection_owner != XConstants.None); | |
209 | + | |
210 | + log.fine(" check if system tray is available. selection owner: " + selection_owner); | |
211 | + } | |
212 | + | |
213 | + public void ownerChanged(int screen, XMSelection sel, long newOwner, long data, long timestamp) { | |
214 | + if (screen != SCREEN) { | |
215 | + return; | |
216 | + } | |
217 | + if (!available) { | |
218 | + available = true; | |
219 | + firePropertyChange(SYSTEM_TRAY_PROPERTY_NAME, null, target); | |
220 | + } else { | |
221 | + removeTrayPeers(); | |
222 | } | |
223 | + createTrayPeers(); | |
224 | + } | |
225 | + | |
226 | + public void ownerDeath(int screen, XMSelection sel, long deadOwner) { | |
227 | + if (screen != SCREEN) { | |
228 | + return; | |
229 | + } | |
230 | + if (available) { | |
231 | + available = false; | |
232 | + firePropertyChange(SYSTEM_TRAY_PROPERTY_NAME, target, null); | |
233 | + removeTrayPeers(); | |
234 | + } | |
235 | + } | |
236 | + | |
237 | + public void selectionChanged(int screen, XMSelection sel, long owner, XPropertyEvent event) { | |
238 | } | |
239 | ||
240 | public Dimension getTrayIconSize() { | |
241 | return new Dimension(XTrayIconPeer.TRAY_ICON_HEIGHT, XTrayIconPeer.TRAY_ICON_WIDTH); | |
242 | } | |
243 | ||
244 | + boolean isAvailable() { | |
245 | + return available; | |
246 | + } | |
247 | + | |
248 | + void dispose() { | |
249 | + selection.removeSelectionListener(this); | |
250 | + } | |
251 | + | |
252 | // *********************************************************************** | |
253 | // *********************************************************************** | |
254 | ||
255 | void addTrayIcon(XTrayIconPeer tiPeer) throws AWTException { | |
256 | - tray_owner = 0; | |
257 | - XToolkit.awtLock(); | |
258 | - try { | |
259 | - tray_owner = XlibWrapper.XGetSelectionOwner(XToolkit.getDisplay(), _NET_SYSTEM_TRAY.getAtom()); | |
260 | - } finally { | |
261 | - XToolkit.awtUnlock(); | |
262 | - } | |
263 | + long selection_owner = selection.getOwner(SCREEN); | |
264 | ||
265 | - if (tray_owner == 0) { | |
266 | + log.fine(" send SYSTEM_TRAY_REQUEST_DOCK message to owner: " + selection_owner); | |
267 | + | |
268 | + if (selection_owner == XConstants.None) { | |
269 | throw new AWTException("TrayIcon couldn't be displayed."); | |
270 | } | |
271 | ||
272 | @@ -77,7 +124,7 @@ | |
273 | ||
274 | _XEMBED_INFO.setAtomData(tray_window, data_ptr, data.length); | |
275 | ||
276 | - sendMessage(tray_owner, SYSTEM_TRAY_REQUEST_DOCK, tray_window, 0, 0); | |
277 | + sendMessage(selection_owner, SYSTEM_TRAY_REQUEST_DOCK, tray_window, 0, 0); | |
278 | } | |
279 | ||
280 | void sendMessage(long win, long msg, long data1, long data2, long data3) { | |
281 | @@ -109,4 +156,51 @@ | |
282 | static XSystemTrayPeer getPeerInstance() { | |
283 | return peerInstance; | |
284 | } | |
285 | + | |
286 | + private void firePropertyChange(final String propertyName, final Object oldValue, final Object newValue) { | |
287 | + Runnable runnable = new Runnable() { | |
288 | + public void run() { | |
289 | + Object[] args = new Object[] {propertyName, oldValue, newValue}; | |
290 | + invokeMethod(firePropertyChangeMethod, target, args); | |
291 | + } | |
292 | + }; | |
293 | + invokeOnEachAppContext(runnable); | |
294 | + } | |
295 | + | |
296 | + private void createTrayPeers() { | |
297 | + invokeOnEachTrayIcon(addNotifyMethod); | |
298 | + } | |
299 | + | |
300 | + private void removeTrayPeers() { | |
301 | + invokeOnEachTrayIcon(removeNotifyMethod); | |
302 | + } | |
303 | + | |
304 | + private void invokeOnEachTrayIcon(final Method method) { | |
305 | + Runnable runnable = new Runnable() { | |
306 | + public void run() { | |
307 | + TrayIcon[] icons = target.getTrayIcons(); | |
308 | + for (TrayIcon ti : icons) { | |
309 | + invokeMethod(method, ti, (Object[]) null); | |
310 | + } | |
311 | + } | |
312 | + }; | |
313 | + invokeOnEachAppContext(runnable); | |
314 | + } | |
315 | + | |
316 | + private void invokeMethod(Method method, Object obj, Object[] args) { | |
317 | + try{ | |
318 | + method.invoke(obj, args); | |
319 | + } catch (InvocationTargetException e){ | |
320 | + e.printStackTrace(); | |
321 | + } catch (IllegalAccessException e) { | |
322 | + e.printStackTrace(); | |
323 | + } | |
324 | + } | |
325 | + | |
326 | + private void invokeOnEachAppContext(Runnable runnable) { | |
327 | + for (AppContext appContext : AppContext.getAppContexts()) { | |
328 | + SunToolkit.invokeLaterOnAppContext(appContext, runnable); | |
329 | + } | |
330 | + } | |
331 | + | |
332 | } | |
333 | diff -durN -x '*~' -x '*.orig' -x '*.rej' openjdk.orig/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java openjdk/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java | |
334 | --- openjdk.orig/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java 2010-11-27 18:09:50.051823664 +0100 | |
335 | +++ openjdk/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java 2010-11-27 19:30:50.372032878 +0100 | |
336 | @@ -300,6 +300,14 @@ | |
337 | } | |
338 | } | |
339 | }); | |
340 | + Runtime.getRuntime().addShutdownHook(new Thread() { | |
341 | + public void run() { | |
342 | + XSystemTrayPeer peer = XSystemTrayPeer.getPeerInstance(); | |
343 | + if (peer != null) { | |
344 | + peer.dispose(); | |
345 | + } | |
346 | + } | |
347 | + }); | |
348 | } | |
349 | ||
350 | static String getCorrectXIDString(String val) { | |
351 | @@ -1066,10 +1074,9 @@ | |
352 | } | |
353 | ||
354 | public boolean isTraySupported() { | |
355 | - int wm = XWM.getWMID(); | |
356 | - if (wm == XWM.METACITY_WM || wm == XWM.KDE2_WM) | |
357 | - { | |
358 | - return true; | |
359 | + XSystemTrayPeer peer = XSystemTrayPeer.getPeerInstance(); | |
360 | + if (peer != null) { | |
361 | + return peer.isAvailable(); | |
362 | } | |
363 | return false; | |
364 | } |