122 case METACITY_WM:
123 return "Metacity";
124 case COMPIZ_WM:
125 return "Compiz";
126 case LG3D_WM:
127 return "LookingGlass";
128 case UNDETERMINED_WM:
129 default:
130 return "Undetermined WM";
131 }
132 }
133
134
135 int WMID;
136 static final Insets zeroInsets = new Insets(0, 0, 0, 0);
137 static final Insets defaultInsets = new Insets(25, 5, 5, 5);
138
139 XWM(int WMID) {
140 this.WMID = WMID;
141 initializeProtocols();
142 if (log.isLoggable(Level.FINE)) log.fine("Window manager: " + toString());
143 }
144 int getID() {
145 return WMID;
146 }
147
148
149 static Insets normalize(Insets insets) {
150 if (insets.top > 64 || insets.top < 0) {
151 insets.top = 28;
152 }
153 if (insets.left > 32 || insets.left < 0) {
154 insets.left = 6;
155 }
156 if (insets.right > 32 || insets.right < 0) {
157 insets.right = 6;
158 }
159 if (insets.bottom > 32 || insets.bottom < 0) {
160 insets.bottom = 6;
161 }
162 return insets;
226 *
227 * No selection owner, but, perhaps it is not ICCCM compliant WM
228 * (e.g. CDE/Sawfish).
229 * Try selecting for SubstructureRedirect, that only one client
230 * can select for, and if the request fails, than some other WM is
231 * already running.
232 *
233 * We also treat eXcursion as NO_WM.
234 */
235 private static boolean isNoWM() {
236 /*
237 * Quick checks for specific servers.
238 */
239 String vendor_string = XlibWrapper.ServerVendor(XToolkit.getDisplay());
240 if (vendor_string.indexOf("eXcursion") != -1) {
241 /*
242 * Use NO_WM since in all other aspects eXcursion is like not
243 * having a window manager running. I.e. it does not reparent
244 * top level shells.
245 */
246 if (insLog.isLoggable(Level.FINE)) {
247 insLog.finer("eXcursion means NO_WM");
248 }
249 return true;
250 }
251
252 XSetWindowAttributes substruct = new XSetWindowAttributes();
253 try {
254 /*
255 * Let's check an owner of WM_Sn selection for the default screen.
256 */
257 final long default_screen_number =
258 XlibWrapper.DefaultScreen(XToolkit.getDisplay());
259 final String selection_name = "WM_S" + default_screen_number;
260
261 long selection_owner =
262 XlibWrapper.XGetSelectionOwner(XToolkit.getDisplay(),
263 XAtom.get(selection_name).getAtom());
264 if (insLog.isLoggable(Level.FINE)) {
265 insLog.finer("selection owner of " + selection_name
266 + " is " + selection_owner);
267 }
268
269 if (selection_owner != XConstants.None) {
270 return false;
271 }
272
273 winmgr_running = false;
274 substruct.set_event_mask(XlibWrapper.SubstructureRedirectMask);
275
276 XToolkit.WITH_XERROR_HANDLER(detectWMHandler);
277 XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),
278 XToolkit.getDefaultRootWindow(),
279 XlibWrapper.CWEventMask,
280 substruct.pData);
281 XToolkit.RESTORE_XERROR_HANDLER();
282
283 /*
284 * If no WM is running then our selection for SubstructureRedirect
285 * succeeded and needs to be undone (hey we are *not* a WM ;-).
286 */
287 if (!winmgr_running) {
288 substruct.set_event_mask(0);
289 XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),
290 XToolkit.getDefaultRootWindow(),
291 XlibWrapper.CWEventMask,
292 substruct.pData);
293 if (insLog.isLoggable(Level.FINE)) {
294 insLog.finer("It looks like there is no WM thus NO_WM");
295 }
296 }
297
298 return !winmgr_running;
299 } finally {
300 substruct.dispose();
301 }
302 }
303
304 static XAtom XA_ENLIGHTENMENT_COMMS = new XAtom("ENLIGHTENMENT_COMMS", false);
305 /*
306 * Helper function for isEnlightenment().
307 * Enlightenment uses STRING property for its comms window id. Gaaa!
308 * The property is ENLIGHTENMENT_COMMS, STRING/8 and the string format
309 * is "WINID %8x". Gee, I haven't been using scanf for *ages*... :-)
310 */
311 static long getECommsWindowIDProperty(long window) {
312
313 if (!XA_ENLIGHTENMENT_COMMS.isInterned()) {
317 WindowPropertyGetter getter =
318 new WindowPropertyGetter(window, XA_ENLIGHTENMENT_COMMS, 0, 14, false,
319 XAtom.XA_STRING);
320 try {
321 int status = getter.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
322 if (status != XlibWrapper.Success || getter.getData() == 0) {
323 return 0;
324 }
325
326 if (getter.getActualType() != XAtom.XA_STRING
327 || getter.getActualFormat() != 8
328 || getter.getNumberOfItems() != 14 || getter.getBytesAfter() != 0)
329 {
330 return 0;
331 }
332
333 // Convert data to String, ASCII
334 byte[] bytes = XlibWrapper.getStringBytes(getter.getData());
335 String id = new String(bytes);
336
337 log.finer("ENLIGHTENMENT_COMMS is " + id);
338
339 // Parse WINID
340 Pattern winIdPat = Pattern.compile("WINID\\s+(\\p{XDigit}{0,8})");
341 try {
342 Matcher match = winIdPat.matcher(id);
343 if (match.matches()) {
344 log.finest("Match group count: " + match.groupCount());
345 String longId = match.group(1);
346 log.finest("Match group 1 " + longId);
347 long winid = Long.parseLong(longId, 16);
348 log.finer("Enlightenment communication window " + winid);
349 return winid;
350 } else {
351 log.finer("ENLIGHTENMENT_COMMS has wrong format");
352 return 0;
353 }
354 } catch (Exception e) {
355 if (log.isLoggable(Level.FINER)) {
356 e.printStackTrace();
357 }
358 return 0;
359 }
360 } finally {
361 getter.dispose();
362 }
363 }
364
365 /*
366 * Is Enlightenment WM running? Congruent to awt_wm_checkAnchor, but
367 * uses STRING property peculiar to Enlightenment.
368 */
632 *
633 * Note well: Only call this if awt_wm_prepareIsIceWM succeeded, or a
634 * false positive will be reported.
635 */
636 static boolean isIceWM() {
637 if (!XA_ICEWM_WINOPTHINT.isInterned()) {
638 if (log.isLoggable(Level.FINER)) {
639 log.log(Level.FINER, "{0} is not interned",
640 new Object[] {String.valueOf(XA_ICEWM_WINOPTHINT)});
641 }
642 return false;
643 }
644
645 WindowPropertyGetter getter =
646 new WindowPropertyGetter(XToolkit.getDefaultRootWindow(),
647 XA_ICEWM_WINOPTHINT, 0, 0xFFFF,
648 true, XA_ICEWM_WINOPTHINT);
649 try {
650 int status = getter.execute();
651 boolean res = (status == XlibWrapper.Success && getter.getActualType() != 0);
652 log.finer("Status getting XA_ICEWM_WINOPTHINT: " + !res);
653 return !res || isNetWMName("IceWM");
654 } finally {
655 getter.dispose();
656 }
657 }
658
659 /*
660 * Is OpenLook WM running?
661 *
662 * This one is pretty lame, but the only property peculiar to OLWM is
663 * _SUN_WM_PROTOCOLS(ATOM[]). Fortunately, olwm deletes it on exit.
664 */
665 static final XAtom XA_SUN_WM_PROTOCOLS = new XAtom("_SUN_WM_PROTOCOLS", false);
666 static boolean isOpenLook() {
667 if (!XA_SUN_WM_PROTOCOLS.isInterned()) {
668 return false;
669 }
670
671 XAtom[] list = XA_SUN_WM_PROTOCOLS.getAtomListProperty(XToolkit.getDefaultRootWindow());
672 return (list.length != 0);
790 * Size and decoration hints ...
791 *
792 \*****************************************************************************/
793
794
795 /*
796 * Remove size hints specified by the mask.
797 * XXX: Why do we need this in the first place???
798 */
799 static void removeSizeHints(XDecoratedPeer window, long mask) {
800 mask &= PMaxSize | PMinSize;
801
802 XToolkit.awtLock();
803 try {
804 XSizeHints hints = window.getHints();
805 if ((hints.get_flags() & mask) == 0) {
806 return;
807 }
808
809 hints.set_flags(hints.get_flags() & ~mask);
810 if (insLog.isLoggable(Level.FINER)) insLog.finer("Setting hints, flags " + XlibWrapper.hintsToString(hints.get_flags()));
811 XlibWrapper.XSetWMNormalHints(XToolkit.getDisplay(),
812 window.getWindow(),
813 hints.pData);
814 } finally {
815 XToolkit.awtUnlock();
816 }
817 }
818
819 /*
820 * If MWM_DECOR_ALL bit is set, then the rest of the bit-mask is taken
821 * to be subtracted from the decorations. Normalize decoration spec
822 * so that we can map motif decor to something else bit-by-bit in the
823 * rest of the code.
824 */
825 static int normalizeMotifDecor(int decorations) {
826 if ((decorations & MWM_DECOR_ALL) == 0) {
827 return decorations;
828 }
829 int d = MWM_DECOR_BORDER | MWM_DECOR_RESIZEH
830 | MWM_DECOR_TITLE
847 int f = MWM_FUNC_RESIZE |
848 MWM_FUNC_MOVE |
849 MWM_FUNC_MAXIMIZE |
850 MWM_FUNC_MINIMIZE |
851 MWM_FUNC_CLOSE;
852 f &= ~functions;
853 return f;
854 }
855
856 /*
857 * Infer OL properties from MWM decorations.
858 * Use _OL_DECOR_DEL(ATOM[]) to remove unwanted ones.
859 */
860 static void setOLDecor(XWindow window, boolean resizable, int decorations) {
861 if (window == null) {
862 return;
863 }
864
865 XAtomList decorDel = new XAtomList();
866 decorations = normalizeMotifDecor(decorations);
867 if (insLog.isLoggable(Level.FINER)) insLog.finer("Setting OL_DECOR to " + Integer.toBinaryString(decorations));
868 if ((decorations & MWM_DECOR_TITLE) == 0) {
869 decorDel.add(XA_OL_DECOR_HEADER);
870 }
871 if ((decorations & (MWM_DECOR_RESIZEH | MWM_DECOR_MAXIMIZE)) == 0) {
872 decorDel.add(XA_OL_DECOR_RESIZE);
873 }
874 if ((decorations & (MWM_DECOR_MENU |
875 MWM_DECOR_MAXIMIZE |
876 MWM_DECOR_MINIMIZE)) == 0)
877 {
878 decorDel.add(XA_OL_DECOR_CLOSE);
879 }
880 if (decorDel.size() == 0) {
881 insLog.finer("Deleting OL_DECOR");
882 XA_OL_DECOR_DEL.DeleteProperty(window);
883 } else {
884 if (insLog.isLoggable(Level.FINER)) insLog.finer("Setting OL_DECOR to " + decorDel);
885 XA_OL_DECOR_DEL.setAtomListProperty(window, decorDel);
886 }
887 }
888
889 /*
890 * Set MWM decorations. Set MWM functions depending on resizability.
891 */
892 static void setMotifDecor(XWindow window, boolean resizable, int decorations, int functions) {
893 /* Apparently some WMs don't implement MWM_*_ALL semantic correctly */
894 if ((decorations & MWM_DECOR_ALL) != 0
895 && (decorations != MWM_DECOR_ALL))
896 {
897 decorations = normalizeMotifDecor(decorations);
898 }
899 if ((functions & MWM_FUNC_ALL) != 0
900 && (functions != MWM_FUNC_ALL))
901 {
902 functions = normalizeMotifFunc(functions);
903 }
904
905 PropMwmHints hints = window.getMWMHints();
906 hints.set_flags(hints.get_flags() | MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS);
907 hints.set_functions(functions);
908 hints.set_decorations(decorations);
909
910 if (stateLog.isLoggable(Level.FINER)) stateLog.finer("Setting MWM_HINTS to " + hints);
911 window.setMWMHints(hints);
912 }
913
914 /*
915 * Under some window managers if shell is already mapped, we MUST
916 * unmap and later remap in order to effect the changes we make in the
917 * window manager decorations.
918 *
919 * N.B. This unmapping / remapping of the shell exposes a bug in
920 * X/Motif or the Motif Window Manager. When you attempt to map a
921 * widget which is positioned (partially) off-screen, the window is
922 * relocated to be entirely on screen. Good idea. But if both the x
923 * and the y coordinates are less than the origin (0,0), the first
924 * (re)map will move the window to the origin, and any subsequent
925 * (re)map will relocate the window at some other point on the screen.
926 * I have written a short Motif test program to discover this bug.
927 * This should occur infrequently and it does not cause any real
928 * problem. So for now we'll let it be.
929 */
930 static boolean needRemap(XDecoratedPeer window) {
952 setMotifDecor(window, resizable, decorations, functions);
953 setOLDecor(window, resizable, decorations);
954
955 /* Some WMs need remap to redecorate the window */
956 if (window.isShowing() && needRemap(window)) {
957 /*
958 * Do the re/mapping at the Xlib level. Since we essentially
959 * work around a WM bug we don't want this hack to be exposed
960 * to Intrinsics (i.e. don't mess with grabs, callbacks etc).
961 */
962 window.xSetVisible(false);
963 XToolkit.XSync();
964 window.xSetVisible(true);
965 }
966 }
967
968 /*
969 * Make specified shell resizable.
970 */
971 static void setShellResizable(XDecoratedPeer window) {
972 if (insLog.isLoggable(Level.FINE)) insLog.fine("Setting shell resizable " + window);
973 XToolkit.awtLock();
974 try {
975 Rectangle shellBounds = window.getShellBounds();
976 shellBounds.translate(-window.currentInsets.left, -window.currentInsets.top);
977 window.updateSizeHints(window.getDimensions());
978 requestWMExtents(window.getWindow());
979 XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), window.getShell(),
980 shellBounds.x, shellBounds.y, shellBounds.width, shellBounds.height);
981 /* REMINDER: will need to revisit when setExtendedStateBounds is added */
982 //Fix for 4320050: Minimum size for java.awt.Frame is not being enforced.
983 //We need to update frame's minimum size, not to reset it
984 removeSizeHints(window, PMaxSize);
985 window.updateMinimumSize();
986
987 /* Restore decorations */
988 setShellDecor(window);
989 } finally {
990 XToolkit.awtUnlock();
991 }
992 }
993
994 /*
995 * Make specified shell non-resizable.
996 * If justChangeSize is false, update decorations as well.
997 * @param shellBounds bounds of the shell window
998 */
999 static void setShellNotResizable(XDecoratedPeer window, WindowDimensions newDimensions, Rectangle shellBounds,
1000 boolean justChangeSize)
1001 {
1002 if (insLog.isLoggable(Level.FINE)) insLog.fine("Setting non-resizable shell " + window + ", dimensions " + newDimensions +
1003 ", shellBounds " + shellBounds +", just change size: " + justChangeSize);
1004 XToolkit.awtLock();
1005 try {
1006 /* Fix min/max size hints at the specified values */
1007 if (!shellBounds.isEmpty()) {
1008 window.updateSizeHints(newDimensions);
1009 requestWMExtents(window.getWindow());
1010 XToolkit.XSync();
1011 XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), window.getShell(),
1012 shellBounds.x, shellBounds.y, shellBounds.width, shellBounds.height);
1013 }
1014 if (!justChangeSize) { /* update decorations */
1015 setShellDecor(window);
1016 }
1017 } finally {
1018 XToolkit.awtUnlock();
1019 }
1020 }
1021
1022 /*****************************************************************************\
1023 * Protocols support
1119 * Notice window state change when WM changes a property on the window ...
1120 *
1121 \*****************************************************************************/
1122
1123
1124 /*
1125 * Check if property change is a window state protocol message.
1126 * If it is - return the new state as Integer, otherwise return null
1127 */
1128 Integer isStateChange(XDecoratedPeer window, XPropertyEvent e) {
1129 if (!window.isShowing()) {
1130 stateLog.finer("Window is not showing");
1131 return null;
1132 }
1133
1134 int wm_state = window.getWMState();
1135 if (wm_state == XlibWrapper.WithdrawnState) {
1136 stateLog.finer("WithdrawnState");
1137 return null;
1138 } else {
1139 stateLog.finer("Window WM_STATE is " + wm_state);
1140 }
1141 boolean is_state_change = false;
1142 if (e.get_atom() == XA_WM_STATE.getAtom()) {
1143 is_state_change = true;
1144 }
1145
1146 Iterator iter = getProtocols(XStateProtocol.class).iterator();
1147 while (iter.hasNext()) {
1148 XStateProtocol proto = (XStateProtocol)iter.next();
1149 is_state_change |= proto.isStateChange(e);
1150 }
1151 int res = 0;
1152
1153 if (is_state_change) {
1154 if (wm_state == XlibWrapper.IconicState) {
1155 res = Frame.ICONIFIED;
1156 } else {
1157 res = Frame.NORMAL;
1158 }
1159 res |= getExtendedState(window);
1160 }
1286 Insets guessInsets(XDecoratedPeer window) {
1287 Insets res = (Insets)storedInsets.get(window.getClass());
1288 if (res == null) {
1289 switch (WMID) {
1290 case ENLIGHTEN_WM:
1291 res = new Insets(19, 4, 4, 4);
1292 break;
1293 case CDE_WM:
1294 res = new Insets(28, 6, 6, 6);
1295 break;
1296 case NO_WM:
1297 case LG3D_WM:
1298 res = zeroInsets;
1299 break;
1300 case MOTIF_WM:
1301 case OPENLOOK_WM:
1302 default:
1303 res = defaultInsets;
1304 }
1305 }
1306 if (insLog.isLoggable(Level.FINEST)) insLog.finest("WM guessed insets: " + res);
1307 return res;
1308 }
1309 /*
1310 * Some buggy WMs ignore window gravity when processing
1311 * ConfigureRequest and position window as if the gravity is Static.
1312 * We work around this in MWindowPeer.pReshape().
1313 *
1314 * Starting with 1.5 we have introduced an Environment variable
1315 * _JAVA_AWT_WM_STATIC_GRAVITY that can be set to indicate to Java
1316 * explicitly that the WM has this behaviour, example is FVWM.
1317 */
1318
1319 static int awtWMStaticGravity = -1;
1320 static boolean configureGravityBuggy() {
1321
1322 if (awtWMStaticGravity == -1) {
1323 awtWMStaticGravity = (XToolkit.getEnv("_JAVA_AWT_WM_STATIC_GRAVITY") != null) ? 1 : 0;
1324 }
1325
1326 if (awtWMStaticGravity == 1) {
|
122 case METACITY_WM:
123 return "Metacity";
124 case COMPIZ_WM:
125 return "Compiz";
126 case LG3D_WM:
127 return "LookingGlass";
128 case UNDETERMINED_WM:
129 default:
130 return "Undetermined WM";
131 }
132 }
133
134
135 int WMID;
136 static final Insets zeroInsets = new Insets(0, 0, 0, 0);
137 static final Insets defaultInsets = new Insets(25, 5, 5, 5);
138
139 XWM(int WMID) {
140 this.WMID = WMID;
141 initializeProtocols();
142 if (log.isLoggable(Level.FINE)) {
143 log.fine("Window manager: " + toString());
144 }
145 }
146 int getID() {
147 return WMID;
148 }
149
150
151 static Insets normalize(Insets insets) {
152 if (insets.top > 64 || insets.top < 0) {
153 insets.top = 28;
154 }
155 if (insets.left > 32 || insets.left < 0) {
156 insets.left = 6;
157 }
158 if (insets.right > 32 || insets.right < 0) {
159 insets.right = 6;
160 }
161 if (insets.bottom > 32 || insets.bottom < 0) {
162 insets.bottom = 6;
163 }
164 return insets;
228 *
229 * No selection owner, but, perhaps it is not ICCCM compliant WM
230 * (e.g. CDE/Sawfish).
231 * Try selecting for SubstructureRedirect, that only one client
232 * can select for, and if the request fails, than some other WM is
233 * already running.
234 *
235 * We also treat eXcursion as NO_WM.
236 */
237 private static boolean isNoWM() {
238 /*
239 * Quick checks for specific servers.
240 */
241 String vendor_string = XlibWrapper.ServerVendor(XToolkit.getDisplay());
242 if (vendor_string.indexOf("eXcursion") != -1) {
243 /*
244 * Use NO_WM since in all other aspects eXcursion is like not
245 * having a window manager running. I.e. it does not reparent
246 * top level shells.
247 */
248 if (insLog.isLoggable(Level.FINER)) {
249 insLog.finer("eXcursion means NO_WM");
250 }
251 return true;
252 }
253
254 XSetWindowAttributes substruct = new XSetWindowAttributes();
255 try {
256 /*
257 * Let's check an owner of WM_Sn selection for the default screen.
258 */
259 final long default_screen_number =
260 XlibWrapper.DefaultScreen(XToolkit.getDisplay());
261 final String selection_name = "WM_S" + default_screen_number;
262
263 long selection_owner =
264 XlibWrapper.XGetSelectionOwner(XToolkit.getDisplay(),
265 XAtom.get(selection_name).getAtom());
266 if (insLog.isLoggable(Level.FINER)) {
267 insLog.finer("selection owner of " + selection_name
268 + " is " + selection_owner);
269 }
270
271 if (selection_owner != XConstants.None) {
272 return false;
273 }
274
275 winmgr_running = false;
276 substruct.set_event_mask(XlibWrapper.SubstructureRedirectMask);
277
278 XToolkit.WITH_XERROR_HANDLER(detectWMHandler);
279 XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),
280 XToolkit.getDefaultRootWindow(),
281 XlibWrapper.CWEventMask,
282 substruct.pData);
283 XToolkit.RESTORE_XERROR_HANDLER();
284
285 /*
286 * If no WM is running then our selection for SubstructureRedirect
287 * succeeded and needs to be undone (hey we are *not* a WM ;-).
288 */
289 if (!winmgr_running) {
290 substruct.set_event_mask(0);
291 XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),
292 XToolkit.getDefaultRootWindow(),
293 XlibWrapper.CWEventMask,
294 substruct.pData);
295 if (insLog.isLoggable(Level.FINER)) {
296 insLog.finer("It looks like there is no WM thus NO_WM");
297 }
298 }
299
300 return !winmgr_running;
301 } finally {
302 substruct.dispose();
303 }
304 }
305
306 static XAtom XA_ENLIGHTENMENT_COMMS = new XAtom("ENLIGHTENMENT_COMMS", false);
307 /*
308 * Helper function for isEnlightenment().
309 * Enlightenment uses STRING property for its comms window id. Gaaa!
310 * The property is ENLIGHTENMENT_COMMS, STRING/8 and the string format
311 * is "WINID %8x". Gee, I haven't been using scanf for *ages*... :-)
312 */
313 static long getECommsWindowIDProperty(long window) {
314
315 if (!XA_ENLIGHTENMENT_COMMS.isInterned()) {
319 WindowPropertyGetter getter =
320 new WindowPropertyGetter(window, XA_ENLIGHTENMENT_COMMS, 0, 14, false,
321 XAtom.XA_STRING);
322 try {
323 int status = getter.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
324 if (status != XlibWrapper.Success || getter.getData() == 0) {
325 return 0;
326 }
327
328 if (getter.getActualType() != XAtom.XA_STRING
329 || getter.getActualFormat() != 8
330 || getter.getNumberOfItems() != 14 || getter.getBytesAfter() != 0)
331 {
332 return 0;
333 }
334
335 // Convert data to String, ASCII
336 byte[] bytes = XlibWrapper.getStringBytes(getter.getData());
337 String id = new String(bytes);
338
339 if (log.isLoggable(Level.FINER)) {
340 log.finer("ENLIGHTENMENT_COMMS is " + id);
341 }
342
343 // Parse WINID
344 Pattern winIdPat = Pattern.compile("WINID\\s+(\\p{XDigit}{0,8})");
345 try {
346 Matcher match = winIdPat.matcher(id);
347 if (match.matches()) {
348 if (log.isLoggable(Level.FINEST)) {
349 log.finest("Match group count: " + match.groupCount());
350 }
351 String longId = match.group(1);
352 if (log.isLoggable(Level.FINEST)) {
353 log.finest("Match group 1 " + longId);
354 }
355 long winid = Long.parseLong(longId, 16);
356 if (log.isLoggable(Level.FINER)) {
357 log.finer("Enlightenment communication window " + winid);
358 }
359 return winid;
360 } else {
361 log.finer("ENLIGHTENMENT_COMMS has wrong format");
362 return 0;
363 }
364 } catch (Exception e) {
365 if (log.isLoggable(Level.FINER)) {
366 e.printStackTrace();
367 }
368 return 0;
369 }
370 } finally {
371 getter.dispose();
372 }
373 }
374
375 /*
376 * Is Enlightenment WM running? Congruent to awt_wm_checkAnchor, but
377 * uses STRING property peculiar to Enlightenment.
378 */
642 *
643 * Note well: Only call this if awt_wm_prepareIsIceWM succeeded, or a
644 * false positive will be reported.
645 */
646 static boolean isIceWM() {
647 if (!XA_ICEWM_WINOPTHINT.isInterned()) {
648 if (log.isLoggable(Level.FINER)) {
649 log.log(Level.FINER, "{0} is not interned",
650 new Object[] {String.valueOf(XA_ICEWM_WINOPTHINT)});
651 }
652 return false;
653 }
654
655 WindowPropertyGetter getter =
656 new WindowPropertyGetter(XToolkit.getDefaultRootWindow(),
657 XA_ICEWM_WINOPTHINT, 0, 0xFFFF,
658 true, XA_ICEWM_WINOPTHINT);
659 try {
660 int status = getter.execute();
661 boolean res = (status == XlibWrapper.Success && getter.getActualType() != 0);
662 if (log.isLoggable(Level.FINER)) {
663 log.finer("Status getting XA_ICEWM_WINOPTHINT: " + !res);
664 }
665 return !res || isNetWMName("IceWM");
666 } finally {
667 getter.dispose();
668 }
669 }
670
671 /*
672 * Is OpenLook WM running?
673 *
674 * This one is pretty lame, but the only property peculiar to OLWM is
675 * _SUN_WM_PROTOCOLS(ATOM[]). Fortunately, olwm deletes it on exit.
676 */
677 static final XAtom XA_SUN_WM_PROTOCOLS = new XAtom("_SUN_WM_PROTOCOLS", false);
678 static boolean isOpenLook() {
679 if (!XA_SUN_WM_PROTOCOLS.isInterned()) {
680 return false;
681 }
682
683 XAtom[] list = XA_SUN_WM_PROTOCOLS.getAtomListProperty(XToolkit.getDefaultRootWindow());
684 return (list.length != 0);
802 * Size and decoration hints ...
803 *
804 \*****************************************************************************/
805
806
807 /*
808 * Remove size hints specified by the mask.
809 * XXX: Why do we need this in the first place???
810 */
811 static void removeSizeHints(XDecoratedPeer window, long mask) {
812 mask &= PMaxSize | PMinSize;
813
814 XToolkit.awtLock();
815 try {
816 XSizeHints hints = window.getHints();
817 if ((hints.get_flags() & mask) == 0) {
818 return;
819 }
820
821 hints.set_flags(hints.get_flags() & ~mask);
822 if (insLog.isLoggable(Level.FINER)) {
823 insLog.finer("Setting hints, flags " + XlibWrapper.hintsToString(hints.get_flags()));
824 }
825 XlibWrapper.XSetWMNormalHints(XToolkit.getDisplay(),
826 window.getWindow(),
827 hints.pData);
828 } finally {
829 XToolkit.awtUnlock();
830 }
831 }
832
833 /*
834 * If MWM_DECOR_ALL bit is set, then the rest of the bit-mask is taken
835 * to be subtracted from the decorations. Normalize decoration spec
836 * so that we can map motif decor to something else bit-by-bit in the
837 * rest of the code.
838 */
839 static int normalizeMotifDecor(int decorations) {
840 if ((decorations & MWM_DECOR_ALL) == 0) {
841 return decorations;
842 }
843 int d = MWM_DECOR_BORDER | MWM_DECOR_RESIZEH
844 | MWM_DECOR_TITLE
861 int f = MWM_FUNC_RESIZE |
862 MWM_FUNC_MOVE |
863 MWM_FUNC_MAXIMIZE |
864 MWM_FUNC_MINIMIZE |
865 MWM_FUNC_CLOSE;
866 f &= ~functions;
867 return f;
868 }
869
870 /*
871 * Infer OL properties from MWM decorations.
872 * Use _OL_DECOR_DEL(ATOM[]) to remove unwanted ones.
873 */
874 static void setOLDecor(XWindow window, boolean resizable, int decorations) {
875 if (window == null) {
876 return;
877 }
878
879 XAtomList decorDel = new XAtomList();
880 decorations = normalizeMotifDecor(decorations);
881 if (insLog.isLoggable(Level.FINER)) {
882 insLog.finer("Setting OL_DECOR to " + Integer.toBinaryString(decorations));
883 }
884 if ((decorations & MWM_DECOR_TITLE) == 0) {
885 decorDel.add(XA_OL_DECOR_HEADER);
886 }
887 if ((decorations & (MWM_DECOR_RESIZEH | MWM_DECOR_MAXIMIZE)) == 0) {
888 decorDel.add(XA_OL_DECOR_RESIZE);
889 }
890 if ((decorations & (MWM_DECOR_MENU |
891 MWM_DECOR_MAXIMIZE |
892 MWM_DECOR_MINIMIZE)) == 0)
893 {
894 decorDel.add(XA_OL_DECOR_CLOSE);
895 }
896 if (decorDel.size() == 0) {
897 insLog.finer("Deleting OL_DECOR");
898 XA_OL_DECOR_DEL.DeleteProperty(window);
899 } else {
900 if (insLog.isLoggable(Level.FINER)) {
901 insLog.finer("Setting OL_DECOR to " + decorDel);
902 }
903 XA_OL_DECOR_DEL.setAtomListProperty(window, decorDel);
904 }
905 }
906
907 /*
908 * Set MWM decorations. Set MWM functions depending on resizability.
909 */
910 static void setMotifDecor(XWindow window, boolean resizable, int decorations, int functions) {
911 /* Apparently some WMs don't implement MWM_*_ALL semantic correctly */
912 if ((decorations & MWM_DECOR_ALL) != 0
913 && (decorations != MWM_DECOR_ALL))
914 {
915 decorations = normalizeMotifDecor(decorations);
916 }
917 if ((functions & MWM_FUNC_ALL) != 0
918 && (functions != MWM_FUNC_ALL))
919 {
920 functions = normalizeMotifFunc(functions);
921 }
922
923 PropMwmHints hints = window.getMWMHints();
924 hints.set_flags(hints.get_flags() | MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS);
925 hints.set_functions(functions);
926 hints.set_decorations(decorations);
927
928 if (stateLog.isLoggable(Level.FINER)) {
929 stateLog.finer("Setting MWM_HINTS to " + hints);
930 }
931 window.setMWMHints(hints);
932 }
933
934 /*
935 * Under some window managers if shell is already mapped, we MUST
936 * unmap and later remap in order to effect the changes we make in the
937 * window manager decorations.
938 *
939 * N.B. This unmapping / remapping of the shell exposes a bug in
940 * X/Motif or the Motif Window Manager. When you attempt to map a
941 * widget which is positioned (partially) off-screen, the window is
942 * relocated to be entirely on screen. Good idea. But if both the x
943 * and the y coordinates are less than the origin (0,0), the first
944 * (re)map will move the window to the origin, and any subsequent
945 * (re)map will relocate the window at some other point on the screen.
946 * I have written a short Motif test program to discover this bug.
947 * This should occur infrequently and it does not cause any real
948 * problem. So for now we'll let it be.
949 */
950 static boolean needRemap(XDecoratedPeer window) {
972 setMotifDecor(window, resizable, decorations, functions);
973 setOLDecor(window, resizable, decorations);
974
975 /* Some WMs need remap to redecorate the window */
976 if (window.isShowing() && needRemap(window)) {
977 /*
978 * Do the re/mapping at the Xlib level. Since we essentially
979 * work around a WM bug we don't want this hack to be exposed
980 * to Intrinsics (i.e. don't mess with grabs, callbacks etc).
981 */
982 window.xSetVisible(false);
983 XToolkit.XSync();
984 window.xSetVisible(true);
985 }
986 }
987
988 /*
989 * Make specified shell resizable.
990 */
991 static void setShellResizable(XDecoratedPeer window) {
992 if (insLog.isLoggable(Level.FINE)) {
993 insLog.fine("Setting shell resizable " + window);
994 }
995 XToolkit.awtLock();
996 try {
997 Rectangle shellBounds = window.getShellBounds();
998 shellBounds.translate(-window.currentInsets.left, -window.currentInsets.top);
999 window.updateSizeHints(window.getDimensions());
1000 requestWMExtents(window.getWindow());
1001 XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), window.getShell(),
1002 shellBounds.x, shellBounds.y, shellBounds.width, shellBounds.height);
1003 /* REMINDER: will need to revisit when setExtendedStateBounds is added */
1004 //Fix for 4320050: Minimum size for java.awt.Frame is not being enforced.
1005 //We need to update frame's minimum size, not to reset it
1006 removeSizeHints(window, PMaxSize);
1007 window.updateMinimumSize();
1008
1009 /* Restore decorations */
1010 setShellDecor(window);
1011 } finally {
1012 XToolkit.awtUnlock();
1013 }
1014 }
1015
1016 /*
1017 * Make specified shell non-resizable.
1018 * If justChangeSize is false, update decorations as well.
1019 * @param shellBounds bounds of the shell window
1020 */
1021 static void setShellNotResizable(XDecoratedPeer window, WindowDimensions newDimensions, Rectangle shellBounds,
1022 boolean justChangeSize)
1023 {
1024 if (insLog.isLoggable(Level.FINE)) {
1025 insLog.fine("Setting non-resizable shell " + window + ", dimensions " + newDimensions +
1026 ", shellBounds " + shellBounds +", just change size: " + justChangeSize);
1027 }
1028 XToolkit.awtLock();
1029 try {
1030 /* Fix min/max size hints at the specified values */
1031 if (!shellBounds.isEmpty()) {
1032 window.updateSizeHints(newDimensions);
1033 requestWMExtents(window.getWindow());
1034 XToolkit.XSync();
1035 XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), window.getShell(),
1036 shellBounds.x, shellBounds.y, shellBounds.width, shellBounds.height);
1037 }
1038 if (!justChangeSize) { /* update decorations */
1039 setShellDecor(window);
1040 }
1041 } finally {
1042 XToolkit.awtUnlock();
1043 }
1044 }
1045
1046 /*****************************************************************************\
1047 * Protocols support
1143 * Notice window state change when WM changes a property on the window ...
1144 *
1145 \*****************************************************************************/
1146
1147
1148 /*
1149 * Check if property change is a window state protocol message.
1150 * If it is - return the new state as Integer, otherwise return null
1151 */
1152 Integer isStateChange(XDecoratedPeer window, XPropertyEvent e) {
1153 if (!window.isShowing()) {
1154 stateLog.finer("Window is not showing");
1155 return null;
1156 }
1157
1158 int wm_state = window.getWMState();
1159 if (wm_state == XlibWrapper.WithdrawnState) {
1160 stateLog.finer("WithdrawnState");
1161 return null;
1162 } else {
1163 if (stateLog.isLoggable(Level.FINER)) {
1164 stateLog.finer("Window WM_STATE is " + wm_state);
1165 }
1166 }
1167 boolean is_state_change = false;
1168 if (e.get_atom() == XA_WM_STATE.getAtom()) {
1169 is_state_change = true;
1170 }
1171
1172 Iterator iter = getProtocols(XStateProtocol.class).iterator();
1173 while (iter.hasNext()) {
1174 XStateProtocol proto = (XStateProtocol)iter.next();
1175 is_state_change |= proto.isStateChange(e);
1176 }
1177 int res = 0;
1178
1179 if (is_state_change) {
1180 if (wm_state == XlibWrapper.IconicState) {
1181 res = Frame.ICONIFIED;
1182 } else {
1183 res = Frame.NORMAL;
1184 }
1185 res |= getExtendedState(window);
1186 }
1312 Insets guessInsets(XDecoratedPeer window) {
1313 Insets res = (Insets)storedInsets.get(window.getClass());
1314 if (res == null) {
1315 switch (WMID) {
1316 case ENLIGHTEN_WM:
1317 res = new Insets(19, 4, 4, 4);
1318 break;
1319 case CDE_WM:
1320 res = new Insets(28, 6, 6, 6);
1321 break;
1322 case NO_WM:
1323 case LG3D_WM:
1324 res = zeroInsets;
1325 break;
1326 case MOTIF_WM:
1327 case OPENLOOK_WM:
1328 default:
1329 res = defaultInsets;
1330 }
1331 }
1332 if (insLog.isLoggable(Level.FINEST)) {
1333 insLog.finest("WM guessed insets: " + res);
1334 }
1335 return res;
1336 }
1337 /*
1338 * Some buggy WMs ignore window gravity when processing
1339 * ConfigureRequest and position window as if the gravity is Static.
1340 * We work around this in MWindowPeer.pReshape().
1341 *
1342 * Starting with 1.5 we have introduced an Environment variable
1343 * _JAVA_AWT_WM_STATIC_GRAVITY that can be set to indicate to Java
1344 * explicitly that the WM has this behaviour, example is FVWM.
1345 */
1346
1347 static int awtWMStaticGravity = -1;
1348 static boolean configureGravityBuggy() {
1349
1350 if (awtWMStaticGravity == -1) {
1351 awtWMStaticGravity = (XToolkit.getEnv("_JAVA_AWT_WM_STATIC_GRAVITY") != null) ? 1 : 0;
1352 }
1353
1354 if (awtWMStaticGravity == 1) {
|