]> git.pld-linux.org Git - packages/icedtea8.git/blob - icedtea6-system_tray.patch
4a0cb0071aa07934f4841542ebaf26df901ebe68
[packages/icedtea8.git] / icedtea6-system_tray.patch
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      }
This page took 0.080247 seconds and 2 git commands to generate.