001: /*
002: * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.awt.X11;
027:
028: import java.awt.*;
029: import java.util.logging.Level;
030: import java.util.logging.Logger;
031:
032: class XWINProtocol extends XProtocol implements XStateProtocol,
033: XLayerProtocol {
034: final static Logger log = Logger
035: .getLogger("sun.awt.X11.XWINProtocol");
036:
037: /* Gnome WM spec */
038: XAtom XA_WIN_SUPPORTING_WM_CHECK = XAtom
039: .get("_WIN_SUPPORTING_WM_CHECK");
040: XAtom XA_WIN_PROTOCOLS = XAtom.get("_WIN_PROTOCOLS");
041: XAtom XA_WIN_STATE = XAtom.get("_WIN_STATE");
042:
043: public boolean supportsState(int state) {
044: return doStateProtocol(); // TODO - check for Frame constants
045: }
046:
047: public void setState(XWindowPeer window, int state) {
048: if (window.isShowing()) {
049: /*
050: * Request state transition from a Gnome WM (_WIN protocol) by sending
051: * _WIN_STATE ClientMessage to root window.
052: */
053: long win_state = 0;
054:
055: if ((state & Frame.MAXIMIZED_VERT) != 0) {
056: win_state |= WIN_STATE_MAXIMIZED_VERT;
057: }
058: if ((state & Frame.MAXIMIZED_HORIZ) != 0) {
059: win_state |= WIN_STATE_MAXIMIZED_HORIZ;
060: }
061:
062: XClientMessageEvent req = new XClientMessageEvent();
063: req.set_type(XlibWrapper.ClientMessage);
064: req.set_window(window.getWindow());
065: req.set_message_type(XA_WIN_STATE.getAtom());
066: req.set_format(32);
067: req
068: .set_data(
069: 0,
070: (WIN_STATE_MAXIMIZED_HORIZ | WIN_STATE_MAXIMIZED_VERT));
071: req.set_data(1, win_state);
072: if (log.isLoggable(Level.FINE))
073: log
074: .fine("Sending WIN_STATE to root to change the state to "
075: + win_state);
076: try {
077: XToolkit.awtLock();
078: XlibWrapper.XSendEvent(XToolkit.getDisplay(),
079: XlibWrapper.RootWindow(XToolkit.getDisplay(),
080: window.getScreenNumber()), false,
081: XlibWrapper.SubstructureRedirectMask
082: | XlibWrapper.SubstructureNotifyMask,
083: req.pData);
084: } finally {
085: XToolkit.awtUnlock();
086: }
087: req.dispose();
088: } else {
089: /*
090: * Specify initial state for a Gnome WM (_WIN protocol) by setting
091: * WIN_STATE property on the window to the desired state before
092: * mapping it.
093: */
094: /* Be careful to not wipe out state bits we don't understand */
095: long win_state = XA_WIN_STATE.getCard32Property(window);
096: long old_win_state = win_state;
097:
098: /*
099: * In their stupid quest of reinventing every wheel, Gnome WM spec
100: * have its own "minimized" hint (instead of using initial state
101: * and WM_STATE hints). This is bogus, but, apparently, some WMs
102: * pay attention.
103: */
104: if ((state & Frame.ICONIFIED) != 0) {
105: win_state |= WIN_STATE_MINIMIZED;
106: } else {
107: win_state &= ~WIN_STATE_MINIMIZED;
108: }
109:
110: if ((state & Frame.MAXIMIZED_VERT) != 0) {
111: win_state |= WIN_STATE_MAXIMIZED_VERT;
112: } else {
113: win_state &= ~WIN_STATE_MAXIMIZED_VERT;
114: }
115:
116: if ((state & Frame.MAXIMIZED_HORIZ) != 0) {
117: win_state |= WIN_STATE_MAXIMIZED_HORIZ;
118: } else {
119: win_state &= ~WIN_STATE_MAXIMIZED_HORIZ;
120: }
121: if ((old_win_state ^ win_state) != 0) {
122: if (log.isLoggable(Level.FINE))
123: log.fine("Setting WIN_STATE on " + window
124: + " to change the state to " + win_state);
125: XA_WIN_STATE.setCard32Property(window, win_state);
126: }
127: }
128: }
129:
130: public int getState(XWindowPeer window) {
131: long win_state = XA_WIN_STATE.getCard32Property(window);
132: int java_state = Frame.NORMAL;
133: if ((win_state & WIN_STATE_MAXIMIZED_VERT) != 0) {
134: java_state |= Frame.MAXIMIZED_VERT;
135: }
136: if ((win_state & WIN_STATE_MAXIMIZED_HORIZ) != 0) {
137: java_state |= Frame.MAXIMIZED_HORIZ;
138: }
139: return java_state;
140: }
141:
142: public boolean isStateChange(XPropertyEvent e) {
143: return doStateProtocol()
144: && e.get_atom() == XA_WIN_STATE.getAtom();
145: }
146:
147: public void unshadeKludge(XWindowPeer window) {
148: long win_state = XA_WIN_STATE.getCard32Property(window);
149: if ((win_state & WIN_STATE_SHADED) == 0) {
150: return;
151: }
152: win_state &= ~WIN_STATE_SHADED;
153: XA_WIN_STATE.setCard32Property(window, win_state);
154: }
155:
156: public boolean supportsLayer(int layer) {
157: return ((layer == LAYER_ALWAYS_ON_TOP) || (layer == LAYER_NORMAL))
158: && doLayerProtocol();
159: }
160:
161: public void setLayer(XWindowPeer window, int layer) {
162: if (window.isShowing()) {
163: XClientMessageEvent req = new XClientMessageEvent();
164: req.set_type(XlibWrapper.ClientMessage);
165: req.set_window(window.getWindow());
166: req.set_message_type(XA_WIN_LAYER.getAtom());
167: req.set_format(32);
168: req.set_data(0, layer == LAYER_NORMAL ? WIN_LAYER_NORMAL
169: : WIN_LAYER_ONTOP);
170: req.set_data(1, 0);
171: req.set_data(2, 0);
172: if (log.isLoggable(Level.FINE))
173: log.fine("Setting layer " + layer
174: + " by root message : " + req);
175: XToolkit.awtLock();
176: try {
177: XlibWrapper
178: .XSendEvent(
179: XToolkit.getDisplay(),
180: XlibWrapper.RootWindow(XToolkit
181: .getDisplay(), window
182: .getScreenNumber()),
183: false,
184: /*XlibWrapper.SubstructureRedirectMask | */XlibWrapper.SubstructureNotifyMask,
185: req.pData);
186: } finally {
187: XToolkit.awtUnlock();
188: }
189: req.dispose();
190: } else {
191: if (log.isLoggable(Level.FINE))
192: log.fine("Setting layer property to " + layer);
193: XA_WIN_LAYER.setCard32Property(window,
194: layer == LAYER_NORMAL ? WIN_LAYER_NORMAL
195: : WIN_LAYER_ONTOP);
196: }
197: }
198:
199: XAtom XA_WIN_LAYER = XAtom.get("_WIN_LAYER");
200:
201: /* _WIN_STATE bits */
202: final static int WIN_STATE_STICKY = (1 << 0); /* everyone knows sticky */
203: final static int WIN_STATE_MINIMIZED = (1 << 1); /* Reserved - definition is unclear */
204: final static int WIN_STATE_MAXIMIZED_VERT = (1 << 2); /* window in maximized V state */
205: final static int WIN_STATE_MAXIMIZED_HORIZ = (1 << 3); /* window in maximized H state */
206: final static int WIN_STATE_HIDDEN = (1 << 4); /* not on taskbar but window visible*/
207: final static int WIN_STATE_SHADED = (1 << 5); /* shaded (MacOS / Afterstep style) */
208: /* _WIN_LAYER values */
209: final static int WIN_LAYER_ONTOP = 6;
210: final static int WIN_LAYER_NORMAL = 4;
211:
212: long WinWindow = 0;
213: boolean supportChecked = false;
214:
215: void detect() {
216: if (supportChecked) {
217: return;
218: }
219: WinWindow = checkAnchor(XA_WIN_SUPPORTING_WM_CHECK,
220: XAtom.XA_CARDINAL);
221: supportChecked = true;
222: if (log.isLoggable(Level.FINE))
223: log.fine("### " + this + " is active: " + (WinWindow != 0));
224: }
225:
226: boolean active() {
227: detect();
228: return WinWindow != 0;
229: }
230:
231: boolean doStateProtocol() {
232: boolean res = active()
233: && checkProtocol(XA_WIN_PROTOCOLS, XA_WIN_STATE);
234: if (log.isLoggable(Level.FINE))
235: log.fine("### " + this + " supports state: " + res);
236: return res;
237: }
238:
239: boolean doLayerProtocol() {
240: boolean res = active()
241: && checkProtocol(XA_WIN_PROTOCOLS, XA_WIN_LAYER);
242: if (log.isLoggable(Level.FINE))
243: log.fine("### " + this + " supports layer: " + res);
244: return res;
245: }
246: }
|