blob: 944654669504fbff50bd8944ba0a8887bf29ac45 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26
27package sun.awt.X11;
28
29import java.awt.*;
30import java.util.logging.Level;
31import java.util.logging.Logger;
32
33class 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)) log.fine("Sending WIN_STATE to root to change the state to " + win_state);
68 try {
69 XToolkit.awtLock();
70 XlibWrapper.XSendEvent(XToolkit.getDisplay(),
71 XlibWrapper.RootWindow(XToolkit.getDisplay(),
72 window.getScreenNumber()),
73 false,
74 XlibWrapper.SubstructureRedirectMask | XlibWrapper.SubstructureNotifyMask,
75 req.pData);
76 }
77 finally {
78 XToolkit.awtUnlock();
79 }
80 req.dispose();
81 } else {
82 /*
83 * Specify initial state for a Gnome WM (_WIN protocol) by setting
84 * WIN_STATE property on the window to the desired state before
85 * mapping it.
86 */
87 /* Be careful to not wipe out state bits we don't understand */
88 long win_state = XA_WIN_STATE.getCard32Property(window);
89 long old_win_state = win_state;
90
91 /*
92 * In their stupid quest of reinventing every wheel, Gnome WM spec
93 * have its own "minimized" hint (instead of using initial state
94 * and WM_STATE hints). This is bogus, but, apparently, some WMs
95 * pay attention.
96 */
97 if ((state & Frame.ICONIFIED) != 0) {
98 win_state |= WIN_STATE_MINIMIZED;
99 } else {
100 win_state &= ~WIN_STATE_MINIMIZED;
101 }
102
103 if ((state & Frame.MAXIMIZED_VERT) != 0) {
104 win_state |= WIN_STATE_MAXIMIZED_VERT;
105 } else {
106 win_state &= ~WIN_STATE_MAXIMIZED_VERT;
107 }
108
109 if ((state & Frame.MAXIMIZED_HORIZ) != 0) {
110 win_state |= WIN_STATE_MAXIMIZED_HORIZ;
111 } else {
112 win_state &= ~WIN_STATE_MAXIMIZED_HORIZ;
113 }
114 if ((old_win_state ^ win_state) != 0) {
115 if (log.isLoggable(Level.FINE)) log.fine("Setting WIN_STATE on " + window + " to change the state to " + win_state);
116 XA_WIN_STATE.setCard32Property(window, win_state);
117 }
118 }
119 }
120
121 public int getState(XWindowPeer window) {
122 long win_state = XA_WIN_STATE.getCard32Property(window);
123 int java_state = Frame.NORMAL;
124 if ((win_state & WIN_STATE_MAXIMIZED_VERT) != 0) {
125 java_state |= Frame.MAXIMIZED_VERT;
126 }
127 if ((win_state & WIN_STATE_MAXIMIZED_HORIZ) != 0) {
128 java_state |= Frame.MAXIMIZED_HORIZ;
129 }
130 return java_state;
131 }
132
133 public boolean isStateChange(XPropertyEvent e) {
134 return doStateProtocol() && e.get_atom() == XA_WIN_STATE.getAtom();
135 }
136
137 public void unshadeKludge(XWindowPeer window) {
138 long win_state = XA_WIN_STATE.getCard32Property(window);
139 if ((win_state & WIN_STATE_SHADED) == 0) {
140 return;
141 }
142 win_state &= ~WIN_STATE_SHADED;
143 XA_WIN_STATE.setCard32Property(window, win_state);
144 }
145
146 public boolean supportsLayer(int layer) {
147 return ((layer == LAYER_ALWAYS_ON_TOP) || (layer == LAYER_NORMAL)) && doLayerProtocol();
148 }
149
150 public void setLayer(XWindowPeer window, int layer) {
151 if (window.isShowing()) {
152 XClientMessageEvent req = new XClientMessageEvent();
153 req.set_type(XlibWrapper.ClientMessage);
154 req.set_window(window.getWindow());
155 req.set_message_type(XA_WIN_LAYER.getAtom());
156 req.set_format(32);
157 req.set_data(0, layer == LAYER_NORMAL ? WIN_LAYER_NORMAL : WIN_LAYER_ONTOP);
158 req.set_data(1, 0);
159 req.set_data(2, 0);
160 if (log.isLoggable(Level.FINE)) log.fine("Setting layer " + layer + " by root message : " + req);
161 XToolkit.awtLock();
162 try {
163 XlibWrapper.XSendEvent(XToolkit.getDisplay(),
164 XlibWrapper.RootWindow(XToolkit.getDisplay(),
165 window.getScreenNumber()),
166 false,
167 /*XlibWrapper.SubstructureRedirectMask | */XlibWrapper.SubstructureNotifyMask,
168 req.pData);
169 }
170 finally {
171 XToolkit.awtUnlock();
172 }
173 req.dispose();
174 } else {
175 if (log.isLoggable(Level.FINE)) log.fine("Setting layer property to " + layer);
176 XA_WIN_LAYER.setCard32Property(window, layer == LAYER_NORMAL ? WIN_LAYER_NORMAL : WIN_LAYER_ONTOP);
177 }
178 }
179
180 XAtom XA_WIN_LAYER = XAtom.get("_WIN_LAYER");
181
182/* _WIN_STATE bits */
183 final static int WIN_STATE_STICKY =(1<<0); /* everyone knows sticky */
184 final static int WIN_STATE_MINIMIZED =(1<<1); /* Reserved - definition is unclear */
185 final static int WIN_STATE_MAXIMIZED_VERT =(1<<2); /* window in maximized V state */
186 final static int WIN_STATE_MAXIMIZED_HORIZ =(1<<3); /* window in maximized H state */
187 final static int WIN_STATE_HIDDEN =(1<<4); /* not on taskbar but window visible*/
188 final static int WIN_STATE_SHADED =(1<<5); /* shaded (MacOS / Afterstep style) */
189/* _WIN_LAYER values */
190 final static int WIN_LAYER_ONTOP = 6;
191 final static int WIN_LAYER_NORMAL = 4;
192
193 long WinWindow = 0;
194 boolean supportChecked = false;
195 void detect() {
196 if (supportChecked) {
197 return;
198 }
199 WinWindow = checkAnchor(XA_WIN_SUPPORTING_WM_CHECK, XAtom.XA_CARDINAL);
200 supportChecked = true;
201 if (log.isLoggable(Level.FINE)) log.fine("### " + this + " is active: " + (WinWindow != 0));
202 }
203
204 boolean active() {
205 detect();
206 return WinWindow != 0;
207 }
208 boolean doStateProtocol() {
209 boolean res = active() && checkProtocol(XA_WIN_PROTOCOLS, XA_WIN_STATE);
210 if (log.isLoggable(Level.FINE)) log.fine("### " + this + " supports state: " + res);
211 return res;
212 }
213
214 boolean doLayerProtocol() {
215 boolean res = active() && checkProtocol(XA_WIN_PROTOCOLS, XA_WIN_LAYER);
216 if (log.isLoggable(Level.FINE)) log.fine("### " + this + " supports layer: " + res);
217 return res;
218 }
219}