26 27 package sun.awt.X11; 28 29 import java.awt.Frame; 30 import sun.util.logging.PlatformLogger; 31 32 final class XNETProtocol extends XProtocol implements XStateProtocol, XLayerProtocol 33 { 34 private final static PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XNETProtocol"); 35 private final static PlatformLogger iconLog = PlatformLogger.getLogger("sun.awt.X11.icon.XNETProtocol"); 36 private static PlatformLogger stateLog = PlatformLogger.getLogger("sun.awt.X11.states.XNETProtocol"); 37 38 /** 39 * XStateProtocol 40 */ 41 public boolean supportsState(int state) { 42 return doStateProtocol() ; // TODO - check for Frame constants 43 } 44 45 public void setState(XWindowPeer window, int state) { 46 if (log.isLoggable(PlatformLogger.FINE)) { 47 log.fine("Setting state of " + window + " to " + state); 48 } 49 if (window.isShowing()) { 50 requestState(window, state); 51 } else { 52 setInitialState(window, state); 53 } 54 } 55 56 private void setInitialState(XWindowPeer window, int state) { 57 XAtomList old_state = window.getNETWMState(); 58 if (log.isLoggable(PlatformLogger.FINE)) { 59 log.fine("Current state of the window {0} is {1}", window, old_state); 60 } 61 if ((state & Frame.MAXIMIZED_VERT) != 0) { 62 old_state.add(XA_NET_WM_STATE_MAXIMIZED_VERT); 63 } else { 64 old_state.remove(XA_NET_WM_STATE_MAXIMIZED_VERT); 65 } 66 if ((state & Frame.MAXIMIZED_HORIZ) != 0) { 67 old_state.add(XA_NET_WM_STATE_MAXIMIZED_HORZ); 68 } else { 69 old_state.remove(XA_NET_WM_STATE_MAXIMIZED_HORZ); 70 } 71 if (log.isLoggable(PlatformLogger.FINE)) { 72 log.fine("Setting initial state of the window {0} to {1}", window, old_state); 73 } 74 window.setNETWMState(old_state); 75 } 76 77 private void requestState(XWindowPeer window, int state) { 78 /* 79 * We have to use toggle for maximization because of transitions 80 * from maximization in one direction only to maximization in the 81 * other direction only. 82 */ 83 int old_net_state = getState(window); 84 int max_changed = (state ^ old_net_state) & (Frame.MAXIMIZED_BOTH); 85 86 XClientMessageEvent req = new XClientMessageEvent(); 87 try { 88 switch(max_changed) { 89 case 0: 90 return; 91 case Frame.MAXIMIZED_HORIZ: 92 req.set_data(1, XA_NET_WM_STATE_MAXIMIZED_HORZ.getAtom()); 93 req.set_data(2, 0); 94 break; 95 case Frame.MAXIMIZED_VERT: 96 req.set_data(1, XA_NET_WM_STATE_MAXIMIZED_VERT.getAtom()); 97 req.set_data(2, 0); 98 break; 99 case Frame.MAXIMIZED_BOTH: 100 req.set_data(1, XA_NET_WM_STATE_MAXIMIZED_HORZ.getAtom()); 101 req.set_data(2, XA_NET_WM_STATE_MAXIMIZED_VERT.getAtom()); 102 break; 103 default: 104 return; 105 } 106 if (log.isLoggable(PlatformLogger.FINE)) { 107 log.fine("Requesting state on " + window + " for " + state); 108 } 109 req.set_type((int)XConstants.ClientMessage); 110 req.set_window(window.getWindow()); 111 req.set_message_type(XA_NET_WM_STATE.getAtom()); 112 req.set_format(32); 113 req.set_data(0, _NET_WM_STATE_TOGGLE); 114 XToolkit.awtLock(); 115 try { 116 XlibWrapper.XSendEvent(XToolkit.getDisplay(), 117 XlibWrapper.RootWindow(XToolkit.getDisplay(), window.getScreenNumber()), 118 false, 119 XConstants.SubstructureRedirectMask | XConstants.SubstructureNotifyMask, 120 req.pData); 121 } 122 finally { 123 XToolkit.awtUnlock(); 124 } 125 } finally { 126 req.dispose(); 170 } 171 172 /** 173 * XLayerProtocol 174 */ 175 public boolean supportsLayer(int layer) { 176 return ((layer == LAYER_ALWAYS_ON_TOP) || (layer == LAYER_NORMAL)) && doLayerProtocol(); 177 } 178 179 public void requestState(XWindow window, XAtom state, boolean isAdd) { 180 XClientMessageEvent req = new XClientMessageEvent(); 181 try { 182 req.set_type((int)XConstants.ClientMessage); 183 req.set_window(window.getWindow()); 184 req.set_message_type(XA_NET_WM_STATE.getAtom()); 185 req.set_format(32); 186 req.set_data(0, isAdd ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE); 187 req.set_data(1, state.getAtom()); 188 // Fix for 6735584: req.data[2] must be set to 0 when only one property is changed 189 req.set_data(2, 0); 190 if (log.isLoggable(PlatformLogger.FINE)) { 191 log.fine("Setting _NET_STATE atom {0} on {1} for {2}", state, window, Boolean.valueOf(isAdd)); 192 } 193 XToolkit.awtLock(); 194 try { 195 XlibWrapper.XSendEvent(XToolkit.getDisplay(), 196 XlibWrapper.RootWindow(XToolkit.getDisplay(), window.getScreenNumber()), 197 false, 198 XConstants.SubstructureRedirectMask | XConstants.SubstructureNotifyMask, 199 req.pData); 200 } 201 finally { 202 XToolkit.awtUnlock(); 203 } 204 } finally { 205 req.dispose(); 206 } 207 } 208 209 /** 210 * Helper function to set/reset one state in NET_WM_STATE 211 * If window is showing then it uses ClientMessage, otherwise adjusts NET_WM_STATE list 212 * @param window Window which NET_WM_STATE property is being modified 213 * @param state State atom to be set/reset 214 * @param reset Indicates operation, 'set' if false, 'reset' if true 215 */ 216 private void setStateHelper(XWindowPeer window, XAtom state, boolean set) { 217 if (log.isLoggable(PlatformLogger.FINER)) { 218 log.finer("Window visibility is: withdrawn={0}, visible={1}, mapped={2} showing={3}", 219 Boolean.valueOf(window.isWithdrawn()), Boolean.valueOf(window.isVisible()), 220 Boolean.valueOf(window.isMapped()), Boolean.valueOf(window.isShowing())); 221 } 222 if (window.isShowing()) { 223 requestState(window, state, set); 224 } else { 225 XAtomList net_wm_state = window.getNETWMState(); 226 if (log.isLoggable(PlatformLogger.FINER)) { 227 log.finer("Current state on {0} is {1}", window, net_wm_state); 228 } 229 if (!set) { 230 net_wm_state.remove(state); 231 } else { 232 net_wm_state.add(state); 233 } 234 if (log.isLoggable(PlatformLogger.FINE)) { 235 log.fine("Setting states on {0} to {1}", window, net_wm_state); 236 } 237 window.setNETWMState(net_wm_state); 238 } 239 XToolkit.XSync(); 240 } 241 242 public void setLayer(XWindowPeer window, int layer) { 243 setStateHelper(window, XA_NET_WM_STATE_ABOVE, layer == LAYER_ALWAYS_ON_TOP); 244 } 245 246 /* New "netwm" spec from www.freedesktop.org */ 247 XAtom XA_UTF8_STRING = XAtom.get("UTF8_STRING"); /* like STRING but encoding is UTF-8 */ 248 XAtom XA_NET_SUPPORTING_WM_CHECK = XAtom.get("_NET_SUPPORTING_WM_CHECK"); 249 XAtom XA_NET_SUPPORTED = XAtom.get("_NET_SUPPORTED"); /* list of protocols (property of root) */ 250 XAtom XA_NET_WM_NAME = XAtom.get("_NET_WM_NAME"); /* window property */ 251 XAtom XA_NET_WM_STATE = XAtom.get("_NET_WM_STATE");/* both window property and request */ 252 253 /* 254 * _NET_WM_STATE is a list of atoms. 273 public final XAtom XA_NET_WM_WINDOW_TYPE_DIALOG = XAtom.get("_NET_WM_WINDOW_TYPE_DIALOG"); 274 public final XAtom XA_NET_WM_WINDOW_TYPE_UTILITY = XAtom.get("_NET_WM_WINDOW_TYPE_UTILITY"); 275 public final XAtom XA_NET_WM_WINDOW_TYPE_POPUP_MENU = XAtom.get("_NET_WM_WINDOW_TYPE_POPUP_MENU"); 276 277 XAtom XA_NET_WM_WINDOW_OPACITY = XAtom.get("_NET_WM_WINDOW_OPACITY"); 278 279 /* For _NET_WM_STATE ClientMessage requests */ 280 final static int _NET_WM_STATE_REMOVE =0; /* remove/unset property */ 281 final static int _NET_WM_STATE_ADD =1; /* add/set property */ 282 final static int _NET_WM_STATE_TOGGLE =2; /* toggle property */ 283 284 boolean supportChecked = false; 285 long NetWindow = 0; 286 void detect() { 287 if (supportChecked) { 288 // TODO: How about detecting WM-restart or exit? 289 return; 290 } 291 NetWindow = checkAnchor(XA_NET_SUPPORTING_WM_CHECK, XAtom.XA_WINDOW); 292 supportChecked = true; 293 if (log.isLoggable(PlatformLogger.FINE)) { 294 log.fine("### " + this + " is active: " + (NetWindow != 0)); 295 } 296 } 297 298 boolean active() { 299 detect(); 300 return NetWindow != 0; 301 } 302 303 boolean doStateProtocol() { 304 boolean res = active() && checkProtocol(XA_NET_SUPPORTED, XA_NET_WM_STATE); 305 if (stateLog.isLoggable(PlatformLogger.FINER)) { 306 stateLog.finer("doStateProtocol() returns " + res); 307 } 308 return res; 309 } 310 311 boolean doLayerProtocol() { 312 boolean res = active() && checkProtocol(XA_NET_SUPPORTED, XA_NET_WM_STATE_ABOVE); 313 return res; 314 } 315 316 boolean doModalityProtocol() { 317 boolean res = active() && checkProtocol(XA_NET_SUPPORTED, XA_NET_WM_STATE_MODAL); 318 return res; 319 } 320 321 boolean doOpacityProtocol() { 322 boolean res = active() && checkProtocol(XA_NET_SUPPORTED, XA_NET_WM_WINDOW_OPACITY); 323 return res; 324 } 325 326 boolean isWMName(String name) { 327 if (!active()) { 328 return false; 329 } 330 String net_wm_name_string = getWMName(); 331 if (net_wm_name_string == null) { 332 return false; 333 } 334 if (log.isLoggable(PlatformLogger.FINE)) { 335 log.fine("### WM_NAME = " + net_wm_name_string); 336 } 337 return net_wm_name_string.startsWith(name); 338 } 339 340 String net_wm_name_cache; 341 public String getWMName() { 342 if (!active()) { 343 return null; 344 } 345 346 if (net_wm_name_cache != null) { 347 return net_wm_name_cache; 348 } 349 350 /* 351 * Check both UTF8_STRING and STRING. We only call this function 352 * with ASCII names and UTF8 preserves ASCII bit-wise. wm-spec 353 * mandates UTF8_STRING for _NET_WM_NAME but at least sawfish-1.0 354 * still uses STRING. (mmm, moving targets...). | 26 27 package sun.awt.X11; 28 29 import java.awt.Frame; 30 import sun.util.logging.PlatformLogger; 31 32 final class XNETProtocol extends XProtocol implements XStateProtocol, XLayerProtocol 33 { 34 private final static PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XNETProtocol"); 35 private final static PlatformLogger iconLog = PlatformLogger.getLogger("sun.awt.X11.icon.XNETProtocol"); 36 private static PlatformLogger stateLog = PlatformLogger.getLogger("sun.awt.X11.states.XNETProtocol"); 37 38 /** 39 * XStateProtocol 40 */ 41 public boolean supportsState(int state) { 42 return doStateProtocol() ; // TODO - check for Frame constants 43 } 44 45 public void setState(XWindowPeer window, int state) { 46 if (log.isLoggable(PlatformLogger.Level.FINE)) { 47 log.fine("Setting state of " + window + " to " + state); 48 } 49 if (window.isShowing()) { 50 requestState(window, state); 51 } else { 52 setInitialState(window, state); 53 } 54 } 55 56 private void setInitialState(XWindowPeer window, int state) { 57 XAtomList old_state = window.getNETWMState(); 58 if (log.isLoggable(PlatformLogger.Level.FINE)) { 59 log.fine("Current state of the window {0} is {1}", window, old_state); 60 } 61 if ((state & Frame.MAXIMIZED_VERT) != 0) { 62 old_state.add(XA_NET_WM_STATE_MAXIMIZED_VERT); 63 } else { 64 old_state.remove(XA_NET_WM_STATE_MAXIMIZED_VERT); 65 } 66 if ((state & Frame.MAXIMIZED_HORIZ) != 0) { 67 old_state.add(XA_NET_WM_STATE_MAXIMIZED_HORZ); 68 } else { 69 old_state.remove(XA_NET_WM_STATE_MAXIMIZED_HORZ); 70 } 71 if (log.isLoggable(PlatformLogger.Level.FINE)) { 72 log.fine("Setting initial state of the window {0} to {1}", window, old_state); 73 } 74 window.setNETWMState(old_state); 75 } 76 77 private void requestState(XWindowPeer window, int state) { 78 /* 79 * We have to use toggle for maximization because of transitions 80 * from maximization in one direction only to maximization in the 81 * other direction only. 82 */ 83 int old_net_state = getState(window); 84 int max_changed = (state ^ old_net_state) & (Frame.MAXIMIZED_BOTH); 85 86 XClientMessageEvent req = new XClientMessageEvent(); 87 try { 88 switch(max_changed) { 89 case 0: 90 return; 91 case Frame.MAXIMIZED_HORIZ: 92 req.set_data(1, XA_NET_WM_STATE_MAXIMIZED_HORZ.getAtom()); 93 req.set_data(2, 0); 94 break; 95 case Frame.MAXIMIZED_VERT: 96 req.set_data(1, XA_NET_WM_STATE_MAXIMIZED_VERT.getAtom()); 97 req.set_data(2, 0); 98 break; 99 case Frame.MAXIMIZED_BOTH: 100 req.set_data(1, XA_NET_WM_STATE_MAXIMIZED_HORZ.getAtom()); 101 req.set_data(2, XA_NET_WM_STATE_MAXIMIZED_VERT.getAtom()); 102 break; 103 default: 104 return; 105 } 106 if (log.isLoggable(PlatformLogger.Level.FINE)) { 107 log.fine("Requesting state on " + window + " for " + state); 108 } 109 req.set_type((int)XConstants.ClientMessage); 110 req.set_window(window.getWindow()); 111 req.set_message_type(XA_NET_WM_STATE.getAtom()); 112 req.set_format(32); 113 req.set_data(0, _NET_WM_STATE_TOGGLE); 114 XToolkit.awtLock(); 115 try { 116 XlibWrapper.XSendEvent(XToolkit.getDisplay(), 117 XlibWrapper.RootWindow(XToolkit.getDisplay(), window.getScreenNumber()), 118 false, 119 XConstants.SubstructureRedirectMask | XConstants.SubstructureNotifyMask, 120 req.pData); 121 } 122 finally { 123 XToolkit.awtUnlock(); 124 } 125 } finally { 126 req.dispose(); 170 } 171 172 /** 173 * XLayerProtocol 174 */ 175 public boolean supportsLayer(int layer) { 176 return ((layer == LAYER_ALWAYS_ON_TOP) || (layer == LAYER_NORMAL)) && doLayerProtocol(); 177 } 178 179 public void requestState(XWindow window, XAtom state, boolean isAdd) { 180 XClientMessageEvent req = new XClientMessageEvent(); 181 try { 182 req.set_type((int)XConstants.ClientMessage); 183 req.set_window(window.getWindow()); 184 req.set_message_type(XA_NET_WM_STATE.getAtom()); 185 req.set_format(32); 186 req.set_data(0, isAdd ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE); 187 req.set_data(1, state.getAtom()); 188 // Fix for 6735584: req.data[2] must be set to 0 when only one property is changed 189 req.set_data(2, 0); 190 if (log.isLoggable(PlatformLogger.Level.FINE)) { 191 log.fine("Setting _NET_STATE atom {0} on {1} for {2}", state, window, Boolean.valueOf(isAdd)); 192 } 193 XToolkit.awtLock(); 194 try { 195 XlibWrapper.XSendEvent(XToolkit.getDisplay(), 196 XlibWrapper.RootWindow(XToolkit.getDisplay(), window.getScreenNumber()), 197 false, 198 XConstants.SubstructureRedirectMask | XConstants.SubstructureNotifyMask, 199 req.pData); 200 } 201 finally { 202 XToolkit.awtUnlock(); 203 } 204 } finally { 205 req.dispose(); 206 } 207 } 208 209 /** 210 * Helper function to set/reset one state in NET_WM_STATE 211 * If window is showing then it uses ClientMessage, otherwise adjusts NET_WM_STATE list 212 * @param window Window which NET_WM_STATE property is being modified 213 * @param state State atom to be set/reset 214 * @param reset Indicates operation, 'set' if false, 'reset' if true 215 */ 216 private void setStateHelper(XWindowPeer window, XAtom state, boolean set) { 217 if (log.isLoggable(PlatformLogger.Level.FINER)) { 218 log.finer("Window visibility is: withdrawn={0}, visible={1}, mapped={2} showing={3}", 219 Boolean.valueOf(window.isWithdrawn()), Boolean.valueOf(window.isVisible()), 220 Boolean.valueOf(window.isMapped()), Boolean.valueOf(window.isShowing())); 221 } 222 if (window.isShowing()) { 223 requestState(window, state, set); 224 } else { 225 XAtomList net_wm_state = window.getNETWMState(); 226 if (log.isLoggable(PlatformLogger.Level.FINER)) { 227 log.finer("Current state on {0} is {1}", window, net_wm_state); 228 } 229 if (!set) { 230 net_wm_state.remove(state); 231 } else { 232 net_wm_state.add(state); 233 } 234 if (log.isLoggable(PlatformLogger.Level.FINE)) { 235 log.fine("Setting states on {0} to {1}", window, net_wm_state); 236 } 237 window.setNETWMState(net_wm_state); 238 } 239 XToolkit.XSync(); 240 } 241 242 public void setLayer(XWindowPeer window, int layer) { 243 setStateHelper(window, XA_NET_WM_STATE_ABOVE, layer == LAYER_ALWAYS_ON_TOP); 244 } 245 246 /* New "netwm" spec from www.freedesktop.org */ 247 XAtom XA_UTF8_STRING = XAtom.get("UTF8_STRING"); /* like STRING but encoding is UTF-8 */ 248 XAtom XA_NET_SUPPORTING_WM_CHECK = XAtom.get("_NET_SUPPORTING_WM_CHECK"); 249 XAtom XA_NET_SUPPORTED = XAtom.get("_NET_SUPPORTED"); /* list of protocols (property of root) */ 250 XAtom XA_NET_WM_NAME = XAtom.get("_NET_WM_NAME"); /* window property */ 251 XAtom XA_NET_WM_STATE = XAtom.get("_NET_WM_STATE");/* both window property and request */ 252 253 /* 254 * _NET_WM_STATE is a list of atoms. 273 public final XAtom XA_NET_WM_WINDOW_TYPE_DIALOG = XAtom.get("_NET_WM_WINDOW_TYPE_DIALOG"); 274 public final XAtom XA_NET_WM_WINDOW_TYPE_UTILITY = XAtom.get("_NET_WM_WINDOW_TYPE_UTILITY"); 275 public final XAtom XA_NET_WM_WINDOW_TYPE_POPUP_MENU = XAtom.get("_NET_WM_WINDOW_TYPE_POPUP_MENU"); 276 277 XAtom XA_NET_WM_WINDOW_OPACITY = XAtom.get("_NET_WM_WINDOW_OPACITY"); 278 279 /* For _NET_WM_STATE ClientMessage requests */ 280 final static int _NET_WM_STATE_REMOVE =0; /* remove/unset property */ 281 final static int _NET_WM_STATE_ADD =1; /* add/set property */ 282 final static int _NET_WM_STATE_TOGGLE =2; /* toggle property */ 283 284 boolean supportChecked = false; 285 long NetWindow = 0; 286 void detect() { 287 if (supportChecked) { 288 // TODO: How about detecting WM-restart or exit? 289 return; 290 } 291 NetWindow = checkAnchor(XA_NET_SUPPORTING_WM_CHECK, XAtom.XA_WINDOW); 292 supportChecked = true; 293 if (log.isLoggable(PlatformLogger.Level.FINE)) { 294 log.fine("### " + this + " is active: " + (NetWindow != 0)); 295 } 296 } 297 298 boolean active() { 299 detect(); 300 return NetWindow != 0; 301 } 302 303 boolean doStateProtocol() { 304 boolean res = active() && checkProtocol(XA_NET_SUPPORTED, XA_NET_WM_STATE); 305 if (stateLog.isLoggable(PlatformLogger.Level.FINER)) { 306 stateLog.finer("doStateProtocol() returns " + res); 307 } 308 return res; 309 } 310 311 boolean doLayerProtocol() { 312 boolean res = active() && checkProtocol(XA_NET_SUPPORTED, XA_NET_WM_STATE_ABOVE); 313 return res; 314 } 315 316 boolean doModalityProtocol() { 317 boolean res = active() && checkProtocol(XA_NET_SUPPORTED, XA_NET_WM_STATE_MODAL); 318 return res; 319 } 320 321 boolean doOpacityProtocol() { 322 boolean res = active() && checkProtocol(XA_NET_SUPPORTED, XA_NET_WM_WINDOW_OPACITY); 323 return res; 324 } 325 326 boolean isWMName(String name) { 327 if (!active()) { 328 return false; 329 } 330 String net_wm_name_string = getWMName(); 331 if (net_wm_name_string == null) { 332 return false; 333 } 334 if (log.isLoggable(PlatformLogger.Level.FINE)) { 335 log.fine("### WM_NAME = " + net_wm_name_string); 336 } 337 return net_wm_name_string.startsWith(name); 338 } 339 340 String net_wm_name_cache; 341 public String getWMName() { 342 if (!active()) { 343 return null; 344 } 345 346 if (net_wm_name_cache != null) { 347 return net_wm_name_cache; 348 } 349 350 /* 351 * Check both UTF8_STRING and STRING. We only call this function 352 * with ASCII names and UTF8 preserves ASCII bit-wise. wm-spec 353 * mandates UTF8_STRING for _NET_WM_NAME but at least sawfish-1.0 354 * still uses STRING. (mmm, moving targets...). |