1 /* 2 * Copyright (c) 2003, 2008, 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 sun.util.logging.PlatformLogger; 31 32 class XWINProtocol extends XProtocol implements XStateProtocol, XLayerProtocol { 33 final static PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XWINProtocol"); 34 35 /* Gnome WM spec */ 36 XAtom XA_WIN_SUPPORTING_WM_CHECK = XAtom.get("_WIN_SUPPORTING_WM_CHECK"); 37 XAtom XA_WIN_PROTOCOLS = XAtom.get("_WIN_PROTOCOLS"); 38 XAtom XA_WIN_STATE = XAtom.get("_WIN_STATE"); 39 40 public boolean supportsState(int state) { 41 return doStateProtocol(); // TODO - check for Frame constants 42 } 43 44 public void setState(XWindowPeer window, int state) { 45 if (window.isShowing()) { 46 /* 47 * Request state transition from a Gnome WM (_WIN protocol) by sending 48 * _WIN_STATE ClientMessage to root window. 49 */ 50 long win_state = 0; 51 52 if ( (state & Frame.MAXIMIZED_VERT) != 0) { 53 win_state |= WIN_STATE_MAXIMIZED_VERT; 54 } 55 if ( (state & Frame.MAXIMIZED_HORIZ) != 0) { 56 win_state |= WIN_STATE_MAXIMIZED_HORIZ; 57 } 58 59 XClientMessageEvent req = new XClientMessageEvent(); 60 req.set_type(XConstants.ClientMessage); 61 req.set_window(window.getWindow()); 62 req.set_message_type(XA_WIN_STATE.getAtom()); 63 req.set_format(32); 64 req.set_data(0, (WIN_STATE_MAXIMIZED_HORIZ | WIN_STATE_MAXIMIZED_VERT)); 65 req.set_data(1, win_state); 66 if (log.isLoggable(PlatformLogger.FINE)) { 67 log.fine("Sending WIN_STATE to root to change the state to " + win_state); 68 } 69 try { 70 XToolkit.awtLock(); 71 XlibWrapper.XSendEvent(XToolkit.getDisplay(), 72 XlibWrapper.RootWindow(XToolkit.getDisplay(), 73 window.getScreenNumber()), 74 false, 75 XConstants.SubstructureRedirectMask | XConstants.SubstructureNotifyMask, 76 req.pData); 77 } 78 finally { 79 XToolkit.awtUnlock(); 80 } 81 req.dispose(); 82 } else { 83 /* 84 * Specify initial state for a Gnome WM (_WIN protocol) by setting 85 * WIN_STATE property on the window to the desired state before 86 * mapping it. 87 */ 88 /* Be careful to not wipe out state bits we don't understand */ 89 long win_state = XA_WIN_STATE.getCard32Property(window); 90 long old_win_state = win_state; 91 92 /* 93 * In their stupid quest of reinventing every wheel, Gnome WM spec 94 * have its own "minimized" hint (instead of using initial state 95 * and WM_STATE hints). This is bogus, but, apparently, some WMs 96 * pay attention. 97 */ 98 if ((state & Frame.ICONIFIED) != 0) { 99 win_state |= WIN_STATE_MINIMIZED; 100 } else { 101 win_state &= ~WIN_STATE_MINIMIZED; 102 } 103 104 if ((state & Frame.MAXIMIZED_VERT) != 0) { 105 win_state |= WIN_STATE_MAXIMIZED_VERT; 106 } else { 107 win_state &= ~WIN_STATE_MAXIMIZED_VERT; 108 } 109 110 if ((state & Frame.MAXIMIZED_HORIZ) != 0) { 111 win_state |= WIN_STATE_MAXIMIZED_HORIZ; 112 } else { 113 win_state &= ~WIN_STATE_MAXIMIZED_HORIZ; 114 } 115 if ((old_win_state ^ win_state) != 0) { 116 if (log.isLoggable(PlatformLogger.FINE)) { 117 log.fine("Setting WIN_STATE on " + window + " to change the state to " + win_state); 118 } 119 XA_WIN_STATE.setCard32Property(window, win_state); 120 } 121 } 122 } 123 124 public int getState(XWindowPeer window) { 125 long win_state = XA_WIN_STATE.getCard32Property(window); 126 int java_state = Frame.NORMAL; 127 if ((win_state & WIN_STATE_MAXIMIZED_VERT) != 0) { 128 java_state |= Frame.MAXIMIZED_VERT; 129 } 130 if ((win_state & WIN_STATE_MAXIMIZED_HORIZ) != 0) { 131 java_state |= Frame.MAXIMIZED_HORIZ; 132 } 133 return java_state; 134 } 135 136 public boolean isStateChange(XPropertyEvent e) { 137 return doStateProtocol() && e.get_atom() == XA_WIN_STATE.getAtom(); 138 } 139 140 public void unshadeKludge(XWindowPeer window) { 141 long win_state = XA_WIN_STATE.getCard32Property(window); 142 if ((win_state & WIN_STATE_SHADED) == 0) { 143 return; 144 } 145 win_state &= ~WIN_STATE_SHADED; 146 XA_WIN_STATE.setCard32Property(window, win_state); 147 } 148 149 public boolean supportsLayer(int layer) { 150 return ((layer == LAYER_ALWAYS_ON_TOP) || (layer == LAYER_NORMAL)) && doLayerProtocol(); 151 } 152 153 public void setLayer(XWindowPeer window, int layer) { 154 if (window.isShowing()) { 155 XClientMessageEvent req = new XClientMessageEvent(); 156 req.set_type(XConstants.ClientMessage); 157 req.set_window(window.getWindow()); 158 req.set_message_type(XA_WIN_LAYER.getAtom()); 159 req.set_format(32); 160 req.set_data(0, layer == LAYER_NORMAL ? WIN_LAYER_NORMAL : WIN_LAYER_ONTOP); 161 req.set_data(1, 0); 162 req.set_data(2, 0); 163 if (log.isLoggable(PlatformLogger.FINE)) { 164 log.fine("Setting layer " + layer + " by root message : " + req); 165 } 166 XToolkit.awtLock(); 167 try { 168 XlibWrapper.XSendEvent(XToolkit.getDisplay(), 169 XlibWrapper.RootWindow(XToolkit.getDisplay(), 170 window.getScreenNumber()), 171 false, 172 /*XConstants.SubstructureRedirectMask | */XConstants.SubstructureNotifyMask, 173 req.pData); 174 } 175 finally { 176 XToolkit.awtUnlock(); 177 } 178 req.dispose(); 179 } else { 180 if (log.isLoggable(PlatformLogger.FINE)) { 181 log.fine("Setting layer property to " + layer); 182 } 183 XA_WIN_LAYER.setCard32Property(window, layer == LAYER_NORMAL ? WIN_LAYER_NORMAL : WIN_LAYER_ONTOP); 184 } 185 } 186 187 XAtom XA_WIN_LAYER = XAtom.get("_WIN_LAYER"); 188 189 /* _WIN_STATE bits */ 190 final static int WIN_STATE_STICKY =(1<<0); /* everyone knows sticky */ 191 final static int WIN_STATE_MINIMIZED =(1<<1); /* Reserved - definition is unclear */ 192 final static int WIN_STATE_MAXIMIZED_VERT =(1<<2); /* window in maximized V state */ 193 final static int WIN_STATE_MAXIMIZED_HORIZ =(1<<3); /* window in maximized H state */ 194 final static int WIN_STATE_HIDDEN =(1<<4); /* not on taskbar but window visible*/ 195 final static int WIN_STATE_SHADED =(1<<5); /* shaded (MacOS / Afterstep style) */ 196 /* _WIN_LAYER values */ 197 final static int WIN_LAYER_ONTOP = 6; 198 final static int WIN_LAYER_NORMAL = 4; 199 200 long WinWindow = 0; 201 boolean supportChecked = false; 202 void detect() { 203 if (supportChecked) { 204 return; 205 } 206 WinWindow = checkAnchor(XA_WIN_SUPPORTING_WM_CHECK, XAtom.XA_CARDINAL); 207 supportChecked = true; 208 if (log.isLoggable(PlatformLogger.FINE)) { 209 log.fine("### " + this + " is active: " + (WinWindow != 0)); 210 } 211 } 212 213 boolean active() { 214 detect(); 215 return WinWindow != 0; 216 } 217 boolean doStateProtocol() { 218 boolean res = active() && checkProtocol(XA_WIN_PROTOCOLS, XA_WIN_STATE); 219 if (log.isLoggable(PlatformLogger.FINE)) { 220 log.fine("### " + this + " supports state: " + res); 221 } 222 return res; 223 } 224 225 boolean doLayerProtocol() { 226 boolean res = active() && checkProtocol(XA_WIN_PROTOCOLS, XA_WIN_LAYER); 227 if (log.isLoggable(PlatformLogger.FINE)) { 228 log.fine("### " + this + " supports layer: " + res); 229 } 230 return res; 231 } 232 }