1 /* 2 * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27 package sun.awt.X11; 28 29 import java.awt.*; 30 import java.util.logging.Level; 31 import java.util.logging.Logger; 32 33 class XWINProtocol extends XProtocol implements XStateProtocol, XLayerProtocol { 34 final static Logger log = Logger.getLogger("sun.awt.X11.XWINProtocol"); 35 36 /* Gnome WM spec */ 37 XAtom XA_WIN_SUPPORTING_WM_CHECK = XAtom.get("_WIN_SUPPORTING_WM_CHECK"); 38 XAtom XA_WIN_PROTOCOLS = XAtom.get("_WIN_PROTOCOLS"); 39 XAtom XA_WIN_STATE = XAtom.get("_WIN_STATE"); 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 (window.isShowing()) { 47 /* 48 * Request state transition from a Gnome WM (_WIN protocol) by sending 49 * _WIN_STATE ClientMessage to root window. 50 */ 51 long win_state = 0; 52 53 if ( (state & Frame.MAXIMIZED_VERT) != 0) { 54 win_state |= WIN_STATE_MAXIMIZED_VERT; 55 } 56 if ( (state & Frame.MAXIMIZED_HORIZ) != 0) { 57 win_state |= WIN_STATE_MAXIMIZED_HORIZ; 58 } 59 60 XClientMessageEvent req = new XClientMessageEvent(); 61 req.set_type(XlibWrapper.ClientMessage); 62 req.set_window(window.getWindow()); 63 req.set_message_type(XA_WIN_STATE.getAtom()); 64 req.set_format(32); 65 req.set_data(0, (WIN_STATE_MAXIMIZED_HORIZ | WIN_STATE_MAXIMIZED_VERT)); 66 req.set_data(1, win_state); 67 if (log.isLoggable(Level.FINE)) { 68 log.fine("Sending WIN_STATE to root to change the state to " + win_state); 69 } 70 try { 71 XToolkit.awtLock(); 72 XlibWrapper.XSendEvent(XToolkit.getDisplay(), 73 XlibWrapper.RootWindow(XToolkit.getDisplay(), 74 window.getScreenNumber()), 75 false, 76 XlibWrapper.SubstructureRedirectMask | XlibWrapper.SubstructureNotifyMask, 77 req.pData); 78 } 79 finally { 80 XToolkit.awtUnlock(); 81 } 82 req.dispose(); 83 } else { 84 /* 85 * Specify initial state for a Gnome WM (_WIN protocol) by setting 86 * WIN_STATE property on the window to the desired state before 87 * mapping it. 88 */ 89 /* Be careful to not wipe out state bits we don't understand */ 90 long win_state = XA_WIN_STATE.getCard32Property(window); 91 long old_win_state = win_state; 92 93 /* 94 * In their stupid quest of reinventing every wheel, Gnome WM spec 95 * have its own "minimized" hint (instead of using initial state 96 * and WM_STATE hints). This is bogus, but, apparently, some WMs 97 * pay attention. 98 */ 99 if ((state & Frame.ICONIFIED) != 0) { 100 win_state |= WIN_STATE_MINIMIZED; 101 } else { 102 win_state &= ~WIN_STATE_MINIMIZED; 103 } 104 105 if ((state & Frame.MAXIMIZED_VERT) != 0) { 106 win_state |= WIN_STATE_MAXIMIZED_VERT; 107 } else { 108 win_state &= ~WIN_STATE_MAXIMIZED_VERT; 109 } 110 111 if ((state & Frame.MAXIMIZED_HORIZ) != 0) { 112 win_state |= WIN_STATE_MAXIMIZED_HORIZ; 113 } else { 114 win_state &= ~WIN_STATE_MAXIMIZED_HORIZ; 115 } 116 if ((old_win_state ^ win_state) != 0) { 117 if (log.isLoggable(Level.FINE)) { 118 log.fine("Setting WIN_STATE on " + window + " to change the state to " + win_state); 119 } 120 XA_WIN_STATE.setCard32Property(window, win_state); 121 } 122 } 123 } 124 125 public int getState(XWindowPeer window) { 126 long win_state = XA_WIN_STATE.getCard32Property(window); 127 int java_state = Frame.NORMAL; 128 if ((win_state & WIN_STATE_MAXIMIZED_VERT) != 0) { 129 java_state |= Frame.MAXIMIZED_VERT; 130 } 131 if ((win_state & WIN_STATE_MAXIMIZED_HORIZ) != 0) { 132 java_state |= Frame.MAXIMIZED_HORIZ; 133 } 134 return java_state; 135 } 136 137 public boolean isStateChange(XPropertyEvent e) { 138 return doStateProtocol() && e.get_atom() == XA_WIN_STATE.getAtom(); 139 } 140 141 public void unshadeKludge(XWindowPeer window) { 142 long win_state = XA_WIN_STATE.getCard32Property(window); 143 if ((win_state & WIN_STATE_SHADED) == 0) { 144 return; 145 } 146 win_state &= ~WIN_STATE_SHADED; 147 XA_WIN_STATE.setCard32Property(window, win_state); 148 } 149 150 public boolean supportsLayer(int layer) { 151 return ((layer == LAYER_ALWAYS_ON_TOP) || (layer == LAYER_NORMAL)) && doLayerProtocol(); 152 } 153 154 public void setLayer(XWindowPeer window, int layer) { 155 if (window.isShowing()) { 156 XClientMessageEvent req = new XClientMessageEvent(); 157 req.set_type(XlibWrapper.ClientMessage); 158 req.set_window(window.getWindow()); 159 req.set_message_type(XA_WIN_LAYER.getAtom()); 160 req.set_format(32); 161 req.set_data(0, layer == LAYER_NORMAL ? WIN_LAYER_NORMAL : WIN_LAYER_ONTOP); 162 req.set_data(1, 0); 163 req.set_data(2, 0); 164 if (log.isLoggable(Level.FINE)) { 165 log.fine("Setting layer " + layer + " by root message : " + req); 166 } 167 XToolkit.awtLock(); 168 try { 169 XlibWrapper.XSendEvent(XToolkit.getDisplay(), 170 XlibWrapper.RootWindow(XToolkit.getDisplay(), 171 window.getScreenNumber()), 172 false, 173 /*XlibWrapper.SubstructureRedirectMask | */XlibWrapper.SubstructureNotifyMask, 174 req.pData); 175 } 176 finally { 177 XToolkit.awtUnlock(); 178 } 179 req.dispose(); 180 } else { 181 if (log.isLoggable(Level.FINE)) { 182 log.fine("Setting layer property to " + layer); 183 } 184 XA_WIN_LAYER.setCard32Property(window, layer == LAYER_NORMAL ? WIN_LAYER_NORMAL : WIN_LAYER_ONTOP); 185 } 186 } 187 188 XAtom XA_WIN_LAYER = XAtom.get("_WIN_LAYER"); 189 190 /* _WIN_STATE bits */ 191 final static int WIN_STATE_STICKY =(1<<0); /* everyone knows sticky */ 192 final static int WIN_STATE_MINIMIZED =(1<<1); /* Reserved - definition is unclear */ 193 final static int WIN_STATE_MAXIMIZED_VERT =(1<<2); /* window in maximized V state */ 194 final static int WIN_STATE_MAXIMIZED_HORIZ =(1<<3); /* window in maximized H state */ 195 final static int WIN_STATE_HIDDEN =(1<<4); /* not on taskbar but window visible*/ 196 final static int WIN_STATE_SHADED =(1<<5); /* shaded (MacOS / Afterstep style) */ 197 /* _WIN_LAYER values */ 198 final static int WIN_LAYER_ONTOP = 6; 199 final static int WIN_LAYER_NORMAL = 4; 200 201 long WinWindow = 0; 202 boolean supportChecked = false; 203 void detect() { 204 if (supportChecked) { 205 return; 206 } 207 WinWindow = checkAnchor(XA_WIN_SUPPORTING_WM_CHECK, XAtom.XA_CARDINAL); 208 supportChecked = true; 209 if (log.isLoggable(Level.FINE)) { 210 log.fine("### " + this + " is active: " + (WinWindow != 0)); 211 } 212 } 213 214 boolean active() { 215 detect(); 216 return WinWindow != 0; 217 } 218 boolean doStateProtocol() { 219 boolean res = active() && checkProtocol(XA_WIN_PROTOCOLS, XA_WIN_STATE); 220 if (log.isLoggable(Level.FINE)) { 221 log.fine("### " + this + " supports state: " + res); 222 } 223 return res; 224 } 225 226 boolean doLayerProtocol() { 227 boolean res = active() && checkProtocol(XA_WIN_PROTOCOLS, XA_WIN_LAYER); 228 if (log.isLoggable(Level.FINE)) { 229 log.fine("### " + this + " supports layer: " + res); 230 } 231 return res; 232 } 233 }