--- a/jdk/src/solaris/native/sun/awt/awt_wm.c Mon Dec 12 08:12:38 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2869 +0,0 @@
-/*
- * Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifdef HEADLESS
- #error This file should not be included in headless library
-#endif
-
-/*
- * Some SCIENCE stuff happens, and it is CONFUSING
- */
-
-#include "awt_p.h"
-
-#include <X11/Xproto.h>
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#include <Xm/MwmUtil.h>
-
-/* JNI headers */
-#include "java_awt_Frame.h" /* for frame state constants */
-
-#include "awt_wm.h"
-#include "awt_util.h" /* for X11 error handling macros */
-
-/*
- * NB: 64 bit awareness.
- *
- * Since this code reads/writes window properties heavily, one thing
- * should be noted well. Xlib uses C type 'long' for properties of
- * format 32. Fortunately, typedef for Atom is 'long' as well, so
- * passing property data as or casting returned property data to
- * arrays of atoms is safe.
- */
-
-
-/*
- * Atoms used to communicate with window manager(s).
- * Naming convention:
- * o for atom "FOO" the variable is "XA_FOO"
- * o for atom "_BAR" the variable is "_XA_BAR"
- * Don't forget to add initialization to awt_wm_initAtoms below.
- */
-
-/*
- * Before WM rototill JDK used to check for running WM by just testing
- * if certain atom is interned or not. We'd better not confuse older
- * JDK by interning these atoms. Use awt_wm_atomInterned() to intern
- * them lazily.
- *
- * ENLIGHTENMENT_COMMS
- * _ICEWM_WINOPTHINT
- * _SAWMILL_TIMESTAMP
- * _DT_SM_WINDOW_INFO
- * _MOTIF_WM_INFO
- * _SUN_WM_PROTOCOLS
- */
-
-/* Good old ICCCM */
-static Atom XA_WM_STATE;
-
-/* New "netwm" spec from www.freedesktop.org */
-static Atom XA_UTF8_STRING; /* like STRING but encoding is UTF-8 */
-static Atom _XA_NET_SUPPORTING_WM_CHECK;
-static Atom _XA_NET_SUPPORTED; /* list of protocols (property of root) */
-static Atom _XA_NET_WM_NAME; /* window property */
-static Atom _XA_NET_WM_STATE; /* both window property and request */
-
-/*
- * _NET_WM_STATE is a list of atoms.
- * NB: Standard spelling is "HORZ" (yes, without an 'I'), but KDE2
- * uses misspelled "HORIZ" (see KDE bug #20229). This was fixed in
- * KDE 2.2. Under earlier versions of KDE2 horizontal and full
- * maximization doesn't work .
- */
-static Atom _XA_NET_WM_STATE_MAXIMIZED_HORZ;
-static Atom _XA_NET_WM_STATE_MAXIMIZED_VERT;
-static Atom _XA_NET_WM_STATE_SHADED;
-static Atom _XA_NET_WM_STATE_ABOVE;
-static Atom _XA_NET_WM_STATE_BELOW;
-static Atom _XA_NET_WM_STATE_HIDDEN;
-
-/* Currently we only care about max_v and max_h in _NET_WM_STATE */
-#define AWT_NET_N_KNOWN_STATES 2
-
-/* Gnome WM spec (superseded by "netwm" above, but still in use) */
-static Atom _XA_WIN_SUPPORTING_WM_CHECK;
-static Atom _XA_WIN_PROTOCOLS;
-static Atom _XA_WIN_STATE;
-static Atom _XA_WIN_LAYER;
-
-/* Enlightenment */
-static Atom _XA_E_FRAME_SIZE;
-
-/* KWin (KDE2) */
-static Atom _XA_KDE_NET_WM_FRAME_STRUT;
-
-/* KWM (KDE 1.x) OBSOLETE??? */
-static Atom XA_KWM_WIN_ICONIFIED;
-static Atom XA_KWM_WIN_MAXIMIZED;
-
-/* OpenLook */
-static Atom _XA_OL_DECOR_DEL;
-static Atom _XA_OL_DECOR_HEADER;
-static Atom _XA_OL_DECOR_RESIZE;
-static Atom _XA_OL_DECOR_PIN;
-static Atom _XA_OL_DECOR_CLOSE;
-
-/* For _NET_WM_STATE ClientMessage requests */
-#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
-#define _NET_WM_STATE_ADD 1 /* add/set property */
-#define _NET_WM_STATE_TOGGLE 2 /* toggle property */
-
-/* _WIN_STATE bits */
-#define WIN_STATE_STICKY (1<<0) /* everyone knows sticky */
-#define WIN_STATE_MINIMIZED (1<<1) /* Reserved - definition is unclear */
-#define WIN_STATE_MAXIMIZED_VERT (1<<2) /* window in maximized V state */
-#define WIN_STATE_MAXIMIZED_HORIZ (1<<3) /* window in maximized H state */
-#define WIN_STATE_HIDDEN (1<<4) /* not on taskbar but window visible*/
-#define WIN_STATE_SHADED (1<<5) /* shaded (MacOS / Afterstep style) */
-#define WIN_LAYER_ONTOP 6
-#define WIN_LAYER_NORMAL 4
-
-#define URGENCY_HINT (1<<8)
-#define LAYER_ALWAYS_ON_TOP 1
-#define LAYER_NORMAL 0
-
-
-/*
- * Intern a bunch of atoms we are going use.
- */
-static void
-awt_wm_initAtoms(void)
-{
- /* Minimize X traffic by creating atoms en mass... This requires
- slightly more code but reduces number of server requests. */
- struct atominit {
- Atom *atomptr;
- const char *name;
- };
-
- /* Just add new atoms to this list */
- static struct atominit atom_list[] = {
- { &XA_WM_STATE, "WM_STATE" },
-
- { &XA_UTF8_STRING, "UTF8_STRING" },
-
- { &_XA_NET_SUPPORTING_WM_CHECK, "_NET_SUPPORTING_WM_CHECK" },
- { &_XA_NET_SUPPORTED, "_NET_SUPPORTED" },
- { &_XA_NET_WM_STATE, "_NET_WM_STATE" },
- { &_XA_NET_WM_STATE_MAXIMIZED_VERT, "_NET_WM_STATE_MAXIMIZED_VERT" },
- { &_XA_NET_WM_STATE_MAXIMIZED_HORZ, "_NET_WM_STATE_MAXIMIZED_HORZ" },
- { &_XA_NET_WM_STATE_SHADED, "_NET_WM_STATE_SHADED" },
- { &_XA_NET_WM_STATE_ABOVE, "_NET_WM_STATE_ABOVE" },
- { &_XA_NET_WM_STATE_BELOW, "_NET_WM_STATE_BELOW" },
- { &_XA_NET_WM_STATE_HIDDEN, "_NET_WM_STATE_HIDDEN" },
- { &_XA_NET_WM_NAME, "_NET_WM_NAME" },
-
- { &_XA_WIN_SUPPORTING_WM_CHECK, "_WIN_SUPPORTING_WM_CHECK" },
- { &_XA_WIN_PROTOCOLS, "_WIN_PROTOCOLS" },
- { &_XA_WIN_STATE, "_WIN_STATE" },
- { &_XA_WIN_LAYER, "_WIN_LAYER" },
-
- { &_XA_KDE_NET_WM_FRAME_STRUT, "_KDE_NET_WM_FRAME_STRUT" },
-
- { &_XA_E_FRAME_SIZE, "_E_FRAME_SIZE" },
-
- { &XA_KWM_WIN_ICONIFIED, "KWM_WIN_ICONIFIED" },
- { &XA_KWM_WIN_MAXIMIZED, "KWM_WIN_MAXIMIZED" },
-
- { &_XA_OL_DECOR_DEL, "_OL_DECOR_DEL" },
- { &_XA_OL_DECOR_HEADER, "_OL_DECOR_HEADER" },
- { &_XA_OL_DECOR_RESIZE, "_OL_DECOR_RESIZE" },
- { &_XA_OL_DECOR_PIN, "_OL_DECOR_PIN" },
- { &_XA_OL_DECOR_CLOSE, "_OL_DECOR_CLOSE" }
- };
-#define ATOM_LIST_LENGTH (sizeof(atom_list)/sizeof(atom_list[0]))
-
- const char *names[ATOM_LIST_LENGTH];
- Atom atoms[ATOM_LIST_LENGTH];
- Status status;
- size_t i;
-
- /* Fill the array of atom names */
- for (i = 0; i < ATOM_LIST_LENGTH; ++i) {
- names[i] = atom_list[i].name;
- }
-
- DTRACE_PRINT("WM: initializing atoms ... ");
- status = XInternAtoms(awt_display, (char**)names, ATOM_LIST_LENGTH,
- False, atoms);
- if (status == 0) {
- DTRACE_PRINTLN("failed");
- return;
- }
-
- /* Store returned atoms into corresponding global variables */
- DTRACE_PRINTLN("ok");
- for (i = 0; i < ATOM_LIST_LENGTH; ++i) {
- *atom_list[i].atomptr = atoms[i];
- }
-#undef ATOM_LIST_LENGTH
-}
-
-
-/*
- * When checking for various WMs don't intern certain atoms we use to
- * distinguish those WMs. Rather check if the atom is interned first.
- * If it's not, further tests are not necessary anyway.
- * This also saves older JDK a great deal of confusion (4487993).
- */
-static Boolean
-awt_wm_atomInterned(Atom *pa, const char *name)
-{
- DASSERT(pa != NULL);
- if (*pa == None) {
- DASSERT(name != NULL);
- *pa = XInternAtom(awt_display, name, True);
- if (*pa == None) {
- DTRACE_PRINTLN1("\"%s\" is not interned", name);
- return False;
- } else {
- return True;
- }
- } else {
- return True;
- }
-}
-
-
-
-/*****************************************************************************\
- *
- * DTRACE utils for various states ...
- *
-\*****************************************************************************/
-
-
-static void
-awt_wm_dtraceWMState(uint32_t wm_state)
-{
-#ifdef DEBUG
- DTRACE_PRINT("WM_STATE = ");
- switch (wm_state) {
- case WithdrawnState:
- DTRACE_PRINTLN("Withdrawn");
- break;
- case NormalState:
- DTRACE_PRINTLN("Normal");
- break;
- case IconicState:
- DTRACE_PRINTLN("Iconic");
- break;
- default:
- DTRACE_PRINTLN1("unknown state %d", wm_state);
- break;
- }
-#endif /* DEBUG */
-}
-
-static void
-awt_wm_dtraceStateNet(Atom *net_wm_state, unsigned long nitems)
-{
-#ifdef DEBUG
- unsigned long i;
-
- DTRACE_PRINT("_NET_WM_STATE = {");
- for (i = 0; i < nitems; ++i) {
- char *name, *print_name;
- name = XGetAtomName(awt_display, net_wm_state[i]);
- if (name == NULL) {
- print_name = "???";
- } else if (strncmp(name, "_NET_WM_STATE", 13) == 0) {
- print_name = name + 13; /* skip common prefix to reduce noice */
- } else {
- print_name = name;
- }
- DTRACE_PRINT1(" %s", print_name);
- if (name) {
- XFree(name);
- }
- }
- DTRACE_PRINTLN(" }");
-#endif
-}
-
-
-static void
-awt_wm_dtraceStateWin(uint32_t win_state)
-{
-#ifdef DEBUG
- DTRACE_PRINT("_WIN_STATE = {");
- if (win_state & WIN_STATE_STICKY) {
- DTRACE_PRINT(" STICKY");
- }
- if (win_state & WIN_STATE_MINIMIZED) {
- DTRACE_PRINT(" MINIMIZED");
- }
- if (win_state & WIN_STATE_MAXIMIZED_VERT) {
- DTRACE_PRINT(" MAXIMIZED_VERT");
- }
- if (win_state & WIN_STATE_MAXIMIZED_HORIZ) {
- DTRACE_PRINT(" MAXIMIZED_HORIZ");
- }
- if (win_state & WIN_STATE_HIDDEN) {
- DTRACE_PRINT(" HIDDEN");
- }
- if (win_state & WIN_STATE_SHADED) {
- DTRACE_PRINT(" SHADED");
- }
- DTRACE_PRINTLN(" }");
-#endif
-}
-
-
-static void
-awt_wm_dtraceStateJava(jint java_state)
-{
-#ifdef DEBUG
- DTRACE_PRINT("java state = ");
- if (java_state == java_awt_Frame_NORMAL) {
- DTRACE_PRINTLN("NORMAL");
- }
- else {
- DTRACE_PRINT("{");
- if (java_state & java_awt_Frame_ICONIFIED) {
- DTRACE_PRINT(" ICONIFIED");
- }
- if ((java_state & java_awt_Frame_MAXIMIZED_BOTH)
- == java_awt_Frame_MAXIMIZED_BOTH)
- {
- DTRACE_PRINT(" MAXIMIZED_BOTH");
- }
- else if (java_state & java_awt_Frame_MAXIMIZED_HORIZ) {
- DTRACE_PRINT(" MAXIMIZED_HORIZ");
- }
- else if (java_state & java_awt_Frame_MAXIMIZED_VERT) {
- DTRACE_PRINT(" MAXIMIZED_VERT");
- }
- DTRACE_PRINTLN(" }");
- }
-#endif /* DEBUG */
-}
-
-
-
-/*****************************************************************************\
- *
- * Utility functions ...
- *
-\*****************************************************************************/
-
-/*
- * Instead of validating window id, we simply call XGetWindowProperty,
- * but temporary install this function as the error handler to ignore
- * BadWindow error.
- */
-int /* but ingored */
-xerror_ignore_bad_window(Display *dpy, XErrorEvent *err)
-{
- XERROR_SAVE(err);
- if (err->error_code == BadWindow) {
- DTRACE_PRINTLN("IGNORING BadWindow");
- return 0; /* ok to fail */
- }
- else {
- return (*xerror_saved_handler)(dpy, err);
- }
-}
-
-
-/*
- * Convenience wrapper for XGetWindowProperty for XA_ATOM properties.
- * E.g. WM_PROTOCOLS, _NET_WM_STATE, _OL_DECOR_DEL.
- * It's up to caller to XFree returned value.
- * Number of items returned is stored to nitems_ptr (if non-null).
- */
-static Atom *
-awt_getAtomListProperty(Window w, Atom property, unsigned long *nitems_ptr)
-{
- /* Request status */
- int status;
-
- /* Returns of XGetWindowProperty */
- Atom actual_type;
- int actual_format;
- unsigned long nitems_stub;
- unsigned long bytes_after;
- Atom *list;
-
- if (nitems_ptr == NULL) {
- /* Caller is not interested in the number of items,
- provide a stub for XGetWindowProperty */
- nitems_ptr = &nitems_stub;
- }
-
- status = XGetWindowProperty(awt_display, w,
- property, 0, 0xFFFF, False, XA_ATOM,
- &actual_type, &actual_format, nitems_ptr, &bytes_after,
- (unsigned char **)&list);
-
- if (status != Success || list == NULL) {
- *nitems_ptr = 0;
- return NULL;
- }
-
- if (actual_type != XA_ATOM || actual_format != 32) {
- XFree(list);
- *nitems_ptr = 0;
- return NULL;
- }
-
- if (*nitems_ptr == 0) {
- XFree(list);
- return NULL;
- }
-
- return list;
-}
-
-
-/*
- * Auxiliary function that returns the value of 'property' of type
- * 'property_type' on window 'w'. Format of the property must be 8.
- * Terminating zero added by XGetWindowProperty is preserved.
- * It's up to caller to XFree the result.
- */
-static unsigned char *
-awt_getProperty8(Window w, Atom property, Atom property_type)
-{
- /* Request status */
- int status;
-
- /* Returns of XGetWindowProperty */
- Atom actual_type;
- int actual_format;
- unsigned long nitems;
- unsigned long bytes_after;
- unsigned char *string;
-
- /* BadWindow is ok and will be blocked by our special handler */
- WITH_XERROR_HANDLER(xerror_ignore_bad_window);
- {
- status = XGetWindowProperty(awt_display, w,
- property, 0, 0xFFFF, False, property_type,
- &actual_type, &actual_format, &nitems, &bytes_after,
- &string);
- }
- RESTORE_XERROR_HANDLER;
-
- if (status != Success || string == NULL) {
- return NULL;
- }
-
- if (actual_type != property_type || actual_format != 8) {
- XFree(string);
- return NULL;
- }
-
- /* XGetWindowProperty kindly supplies terminating zero */
- return string;
-}
-
-
-/*
- * Auxiliary function that returns the value of 'property' of type
- * 'property_type' on window 'w'. Format of the property must be 32.
- */
-static int32_t
-awt_getProperty32(Window w, Atom property, Atom property_type)
-{
- /* Property value*/
- int32_t value;
-
- /* Request status */
- int status;
-
- /* Returns of XGetWindowProperty */
- Atom actual_type;
- int actual_format;
- unsigned long nitems;
- unsigned long bytes_after;
- long *data; /* NB: 64 bit: Format 32 props are 'long' */
-
- /* BadWindow is ok and will be blocked by our special handler */
- WITH_XERROR_HANDLER(xerror_ignore_bad_window);
- {
- status = XGetWindowProperty(awt_display, w,
- property, 0, 1, False, property_type,
- &actual_type, &actual_format, &nitems, &bytes_after,
- (unsigned char **)&data);
- }
- RESTORE_XERROR_HANDLER;
-
- if (status != Success || data == NULL) {
- return 0;
- }
-
- if (actual_type != property_type || actual_format != 32) {
- XFree(data); /* NULL data already catched above */
- return 0;
- }
-
- value = (int32_t)*data;
- XFree(data);
-
- return value;
-}
-
-
-
-/*****************************************************************************\
- *
- * Detecting WM ...
- *
-\*****************************************************************************/
-
-
-
-/*
- * Check for anchor_prop(anchor_type) on root, take the value as the
- * window id and check if that window exists and has anchor_prop(anchor_type)
- * with the same value (i.e. pointing back to self).
- *
- * Returns the anchor window, as some WM may put interesting stuff in
- * its properties (e.g. sawfish).
- */
-static Window
-awt_wm_checkAnchor(Atom anchor_prop, Atom anchor_type)
-{
- Window root_xref;
- Window self_xref;
-
- root_xref = (Window)awt_getProperty32(DefaultRootWindow(awt_display),
- anchor_prop, anchor_type);
- if (root_xref == None) {
- DTRACE_PRINTLN("no");
- return None;
- }
-
- DTRACE_PRINT1("0x%x ... ", (unsigned int)root_xref);
- self_xref = (Window)awt_getProperty32(root_xref,
- anchor_prop, anchor_type);
- if (self_xref != root_xref) {
- DTRACE_PRINTLN("stale");
- return None;
- }
-
- DTRACE_PRINTLN("ok");
- return self_xref;
-}
-
-
-/*
- * New WM spec: KDE 2.0.1, sawfish 0.3x, ...
- * <http://www.freedesktop.org/standards/wm-spec.html>
- */
-static Window
-awt_wm_isNetSupporting(void)
-{
- static Boolean checked = False;
- static Window isNetSupporting = None;
-
- if (checked) {
- return isNetSupporting;
- }
-
- DTRACE_PRINT("WM: checking for _NET_SUPPORTING ... ");
- isNetSupporting = awt_wm_checkAnchor(_XA_NET_SUPPORTING_WM_CHECK,
- XA_WINDOW);
- checked = True;
- return isNetSupporting;
-}
-
-
-/*
- * Old Gnome WM spec: WindowMaker, Enlightenment, IceWM ...
- * <http://developer.gnome.org/doc/standards/wm/book1.html>
- */
-static Window
-awt_wm_isWinSupporting(void)
-{
- static Boolean checked = False;
- static Window isWinSupporting = None;
-
- if (checked) {
- return isWinSupporting;
- }
-
- DTRACE_PRINT("WM: checking for _WIN_SUPPORTING ... ");
- isWinSupporting = awt_wm_checkAnchor(_XA_WIN_SUPPORTING_WM_CHECK,
- XA_CARDINAL);
- checked = True;
- return isWinSupporting;
-}
-
-
-/*
- * Check that that the list of protocols specified by WM in property
- * named LIST_NAME on the root window contains protocol PROTO.
- */
-static Boolean
-awt_wm_checkProtocol(Atom list_name, Atom proto)
-{
- Atom *protocols;
- unsigned long nproto;
- Boolean found;
- unsigned long i;
-
- protocols = awt_getAtomListProperty(DefaultRootWindow(awt_display),
- list_name, &nproto);
- if (protocols == NULL) {
- return False;
- }
-
- found = False;
- for (i = 0; i < nproto; ++i) {
- if (protocols[i] == proto) {
- found = True;
- break;
- }
- }
-
- if (protocols != NULL) {
- XFree(protocols);
- }
- return found;
-}
-
-static Boolean
-awt_wm_doStateProtocolNet(void)
-{
- static Boolean checked = False;
- static Boolean supported = False;
-
- if (checked) {
- return supported;
- }
-
- if (awt_wm_isNetSupporting()) {
- DTRACE_PRINT("WM: checking for _NET_WM_STATE in _NET_SUPPORTED ... ");
- supported = awt_wm_checkProtocol(_XA_NET_SUPPORTED, _XA_NET_WM_STATE);
- DTRACE_PRINTLN1("%s", supported ? "yes" : "no");
- }
-
- checked = True;
- return supported;
-}
-
-static Boolean
-awt_wm_doStateProtocolWin(void)
-{
- static Boolean checked = False;
- static Boolean supported = False;
-
- if (checked) {
- return supported;
- }
-
- if (awt_wm_isWinSupporting()) {
- DTRACE_PRINT("WM: checking for _WIN_STATE in _WIN_PROTOCOLS ... ");
- supported = awt_wm_checkProtocol(_XA_WIN_PROTOCOLS, _XA_WIN_STATE);
- DTRACE_PRINTLN1("%s", supported ? "yes" : "no");
- }
- checked = True;
- return supported;
-}
-
-
-
-/*
- * Helper function for awt_wm_isEnlightenment.
- * Enlightenment uses STRING property for its comms window id. Gaaa!
- * The property is ENLIGHTENMENT_COMMS, STRING/8 and the string format
- * is "WINID %8x". Gee, I haven't been using scanf for *ages*... :-)
- */
-static Window
-awt_getECommsWindowIDProperty(Window w)
-{
- static Atom XA_ENLIGHTENMENT_COMMS = None;
-
- /* Property value*/
- Window value;
-
- /* Request status */
- int status;
-
- /* Returns of XGetWindowProperty */
- Atom actual_type;
- int actual_format;
- unsigned long nitems;
- unsigned long bytes_after;
- unsigned char *data;
-
- if (!awt_wm_atomInterned(&XA_ENLIGHTENMENT_COMMS, "ENLIGHTENMENT_COMMS")) {
- return False;
- }
-
- /* BadWindow is ok and will be blocked by our special handler */
- WITH_XERROR_HANDLER(xerror_ignore_bad_window);
- {
- status = XGetWindowProperty(awt_display, w,
- XA_ENLIGHTENMENT_COMMS, 0, 14, False, XA_STRING,
- &actual_type, &actual_format, &nitems, &bytes_after,
- &data);
- }
- RESTORE_XERROR_HANDLER;
-
- if (status != Success || data == NULL) {
- DTRACE_PRINTLN("no ENLIGHTENMENT_COMMS");
- return None;
- }
-
- if (actual_type != XA_STRING || actual_format != 8
- || nitems != 14 || bytes_after != 0)
- {
- DTRACE_PRINTLN("malformed ENLIGHTENMENT_COMMS");
- XFree(data); /* NULL data already catched above */
- return None;
- }
-
- value = None;
- sscanf((char *)data, "WINID %8lx", &value); /* NB: 64 bit: XID is long */
- XFree(data);
-
- return value;
-}
-
-
-/*
- * Is Enlightenment WM running? Congruent to awt_wm_checkAnchor, but
- * uses STRING property peculiar to Enlightenment.
- */
-static Boolean
-awt_wm_isEnlightenment(void)
-{
- Window root_xref;
- Window self_xref;
-
- DTRACE_PRINT("WM: checking for Enlightenment ... ");
- root_xref = awt_getECommsWindowIDProperty(DefaultRootWindow(awt_display));
- if (root_xref == None) {
- return False;
- }
-
- DTRACE_PRINT1("0x%x ... ", root_xref);
- self_xref = awt_getECommsWindowIDProperty(root_xref);
- if (self_xref != root_xref) {
- return False;
- }
-
- DTRACE_PRINTLN("ok");
- return True;
-}
-
-
-/*
- * Is CDE running?
- *
- * XXX: This is hairy... CDE is MWM as well. It seems we simply test
- * for default setup and will be bitten if user changes things...
- *
- * Check for _DT_SM_WINDOW_INFO(_DT_SM_WINDOW_INFO) on root. Take the
- * second element of the property and check for presence of
- * _DT_SM_STATE_INFO(_DT_SM_STATE_INFO) on that window.
- *
- * XXX: Any header that defines this structures???
- */
-static Boolean
-awt_wm_isCDE(void)
-{
- static Atom _XA_DT_SM_WINDOW_INFO = None;
- static Atom _XA_DT_SM_STATE_INFO = None;
-
- /* Property value*/
- Window wmwin;
-
- /* Request status */
- int status;
-
- /* Returns of XGetWindowProperty */
- Atom actual_type;
- int actual_format;
- unsigned long nitems;
- unsigned long bytes_after;
- long *data; /* NB: 64 bit: Format 32 props are 'long' */
-
- DTRACE_PRINT("WM: checking for CDE ... ");
-
- if (!awt_wm_atomInterned(&_XA_DT_SM_WINDOW_INFO, "_DT_SM_WINDOW_INFO")) {
- return False;
- }
-
- status = XGetWindowProperty(awt_display, DefaultRootWindow(awt_display),
- _XA_DT_SM_WINDOW_INFO, 0, 2, False, _XA_DT_SM_WINDOW_INFO,
- &actual_type, &actual_format, &nitems, &bytes_after,
- (unsigned char **)&data);
-
- if (status != Success || data == NULL) {
- DTRACE_PRINTLN("no _DT_SM_WINDOW_INFO on root");
- return False;
- }
-
- if (actual_type != _XA_DT_SM_WINDOW_INFO || actual_format != 32
- || nitems != 2 || bytes_after != 0)
- {
- DTRACE_PRINTLN("malformed _DT_SM_WINDOW_INFO on root");
- XFree(data); /* NULL data already catched above */
- return False;
- }
-
- wmwin = (Window)data[1];
- XFree(data);
-
- /* Now check that this window has _DT_SM_STATE_INFO (ignore contents) */
-
- if (!awt_wm_atomInterned(&_XA_DT_SM_STATE_INFO, "_DT_SM_STATE_INFO")) {
- return False;
- }
-
- /* BadWindow is ok and will be blocked by our special handler */
- WITH_XERROR_HANDLER(xerror_ignore_bad_window);
- {
- status = XGetWindowProperty(awt_display, wmwin,
- _XA_DT_SM_STATE_INFO, 0, 1, False, _XA_DT_SM_STATE_INFO,
- &actual_type, &actual_format, &nitems, &bytes_after,
- (unsigned char **)&data);
- }
- RESTORE_XERROR_HANDLER;
-
- if (status != Success || data == NULL) {
- DTRACE_PRINTLN("no _DT_SM_STATE_INFO");
- return False;
- }
-
- if (actual_type != _XA_DT_SM_STATE_INFO || actual_format != 32) {
- DTRACE_PRINTLN("malformed _DT_SM_STATE_INFO");
- XFree(data); /* NULL data already catched above */
- return False;
- }
-
- DTRACE_PRINTLN("yes");
- XFree(data);
- return True;
-}
-
-/*
- * Is MWM running? (Note that CDE will test positive as well).
- *
- * Check for _MOTIF_WM_INFO(_MOTIF_WM_INFO) on root. Take the
- * second element of the property and check for presence of
- * _DT_SM_STATE_INFO(_DT_SM_STATE_INFO) on that window.
- */
-static Boolean
-awt_wm_isMotif(void)
-{
- /*
- * Grr. Motif just had to be different, ain't it!? Everyone use
- * "XA" for things of type Atom, but motif folks chose to define
- * _XA_MOTIF_* to be atom *names*. How pathetic...
- */
-#undef _XA_MOTIF_WM_INFO
- static Atom _XA_MOTIF_WM_INFO = None;
- static Atom _XA_DT_WORKSPACE_CURRENT = None;
-
- /* Property value */
- Window wmwin;
- Atom *curws;
-
- /* Request status */
- int status;
-
- /* Returns of XGetWindowProperty */
- Atom actual_type;
- int actual_format;
- unsigned long nitems;
- unsigned long bytes_after;
- long *data; /* NB: 64 bit: Format 32 props are 'long' */
-
- DTRACE_PRINT("WM: checking for MWM ... ");
-
- if (!awt_wm_atomInterned(&_XA_MOTIF_WM_INFO, "_MOTIF_WM_INFO")
- || !awt_wm_atomInterned(&_XA_DT_WORKSPACE_CURRENT, "_DT_WORKSPACE_CURRENT"))
- {
- return False;
- }
-
-
- status = XGetWindowProperty(awt_display, DefaultRootWindow(awt_display),
- _XA_MOTIF_WM_INFO, 0, PROP_MOTIF_WM_INFO_ELEMENTS, False,
- _XA_MOTIF_WM_INFO, &actual_type,
- &actual_format, &nitems, &bytes_after,
- (unsigned char **)&data);
-
- if (status != Success || data == NULL) {
- DTRACE_PRINTLN("no _MOTIF_WM_INFO on root");
- return False;
- }
-
- if (actual_type != _XA_MOTIF_WM_INFO || actual_format != 32
- || nitems != PROP_MOTIF_WM_INFO_ELEMENTS || bytes_after != 0)
- {
- DTRACE_PRINTLN("malformed _MOTIF_WM_INFO on root");
- XFree(data); /* NULL data already catched above */
- return False;
- }
-
- /* NB: 64 bit: Cannot cast data to MotifWmInfo */
- wmwin = (Window)data[1];
- XFree(data);
-
- /* Now check that this window has _DT_WORKSPACE_CURRENT */
- curws = awt_getAtomListProperty(wmwin, _XA_DT_WORKSPACE_CURRENT, NULL);
- if (curws == NULL) {
- DTRACE_PRINTLN("no _DT_WORKSPACE_CURRENT");
- return False;
- }
-
- DTRACE_PRINTLN("yes");
- XFree(curws);
- return True;
-}
-
-
-static Boolean
-awt_wm_isNetWMName(char *name)
-{
- Window anchor;
- unsigned char *net_wm_name;
- Boolean matched;
-
- anchor = awt_wm_isNetSupporting();
- if (anchor == None) {
- return False;
- }
-
- DTRACE_PRINT1("WM: checking for %s by _NET_WM_NAME ... ", name);
-
- /*
- * Check both UTF8_STRING and STRING. We only call this function
- * with ASCII names and UTF8 preserves ASCII bit-wise. wm-spec
- * mandates UTF8_STRING for _NET_WM_NAME but at least sawfish-1.0
- * still uses STRING. (mmm, moving targets...).
- */
- net_wm_name = awt_getProperty8(anchor, _XA_NET_WM_NAME, XA_UTF8_STRING);
- if (net_wm_name == NULL) {
- net_wm_name = awt_getProperty8(anchor, _XA_NET_WM_NAME, XA_STRING);
- }
-
- if (net_wm_name == NULL) {
- DTRACE_PRINTLN("no (missing _NET_WM_NAME)");
- return False;
- }
-
- matched = (strcmp((char *)net_wm_name, name) == 0);
- if (matched) {
- DTRACE_PRINTLN("yes");
- } else {
- DTRACE_PRINTLN1("no (_NET_WM_NAME = \"%s\")", net_wm_name);
- }
- XFree(net_wm_name);
- return matched;
-}
-
-/*
- * Is Sawfish running?
- */
-static Boolean
-awt_wm_isSawfish(void)
-{
- return awt_wm_isNetWMName("Sawfish");
-}
-
-/*
- * Is KDE2 (KWin) running?
- */
-static Boolean
-awt_wm_isKDE2(void)
-{
- return awt_wm_isNetWMName("KWin");
-}
-
-
-/*
- * Is Metacity running?
- */
-static Boolean
-awt_wm_isMetacity(void)
-{
- return awt_wm_isNetWMName("Metacity");
-}
-
-
-/*
- * Temporary error handler that ensures that we know if
- * XChangeProperty succeeded or not.
- */
-static int /* but ignored */
-xerror_verify_change_property(Display *dpy, XErrorEvent *err)
-{
- XERROR_SAVE(err);
- if (err->request_code == X_ChangeProperty) {
- return 0;
- }
- else {
- return (*xerror_saved_handler)(dpy, err);
- }
-}
-
-
-/*
- * Prepare IceWM check.
- *
- * The only way to detect IceWM, seems to be by setting
- * _ICEWM_WINOPTHINT(_ICEWM_WINOPTHINT/8) on root and checking if it
- * was immediately deleted by IceWM.
- *
- * But messing with PropertyNotify here is way too much trouble, so
- * approximate the check by setting the property in this function and
- * checking if it still exists later on.
- *
- * Gaa, dirty dances...
- */
-static Boolean
-awt_wm_prepareIsIceWM(void)
-{
- static Atom _XA_ICEWM_WINOPTHINT = None;
-
- /*
- * Choose something innocuous: "AWT_ICEWM_TEST allWorkspaces 0".
- * IceWM expects "class\0option\0arg\0" with zero bytes as delimiters.
- */
- static unsigned char opt[] = {
- 'A','W','T','_','I','C','E','W','M','_','T','E','S','T','\0',
- 'a','l','l','W','o','r','k','s','p','a','c','e','s','\0',
- '0','\0'
- };
-
- DTRACE_PRINT("WM: scheduling check for IceWM ... ");
-
- if (!awt_wm_atomInterned(&_XA_ICEWM_WINOPTHINT, "_ICEWM_WINOPTHINT")) {
- return False;
- }
-
- WITH_XERROR_HANDLER(xerror_verify_change_property);
- {
- XChangeProperty(awt_display, DefaultRootWindow(awt_display),
- _XA_ICEWM_WINOPTHINT, _XA_ICEWM_WINOPTHINT, 8,
- PropModeReplace, opt, sizeof(opt));
- }
- RESTORE_XERROR_HANDLER;
-
- if (xerror_code != Success) {
- DTRACE_PRINTLN1("can't set _ICEWM_WINOPTHINT, error = %d",
- xerror_code);
- return False;
- }
- else {
- DTRACE_PRINTLN("scheduled");
- return True;
- }
-}
-
-/*
- * Is IceWM running?
- *
- * Note well: Only call this if awt_wm_prepareIsIceWM succeeded, or a
- * false positive will be reported.
- */
-static Boolean
-awt_wm_isIceWM(void)
-{
- static Atom _XA_ICEWM_WINOPTHINT = None;
-
- /* Request status */
- int status;
-
- /* Returns of XGetWindowProperty */
- Atom actual_type;
- int actual_format;
- unsigned long nitems;
- unsigned long bytes_after;
- unsigned char *data;
-
- DTRACE_PRINT("WM: checking for IceWM ... ");
-
- if (!awt_wm_atomInterned(&_XA_ICEWM_WINOPTHINT, "_ICEWM_WINOPTHINT")) {
- return False;
- }
-
- XGetWindowProperty(awt_display, DefaultRootWindow(awt_display),
- _XA_ICEWM_WINOPTHINT, 0, 0xFFFF, True, /* NB: deleting! */
- _XA_ICEWM_WINOPTHINT, &actual_type,
- &actual_format, &nitems, &bytes_after,
- &data);
-
- if (data != NULL) {
- XFree(data);
- }
-
- if (actual_type == None) {
- DTRACE_PRINTLN("yes");
- return True;
- }
- else {
- DTRACE_PRINTLN("no");
- return False;
- }
-}
-
-/*
- * Is OpenLook WM running?
- *
- * This one is pretty lame, but the only property peculiar to OLWM is
- * _SUN_WM_PROTOCOLS(ATOM[]). Fortunately, olwm deletes it on exit.
- */
-static Boolean
-awt_wm_isOpenLook(void)
-{
- static Atom _XA_SUN_WM_PROTOCOLS = None;
- Atom *list;
-
- DTRACE_PRINT("WM: checking for OpenLook WM ... ");
-
- if (!awt_wm_atomInterned(&_XA_SUN_WM_PROTOCOLS, "_SUN_WM_PROTOCOLS")) {
- return False;
- }
-
- list = awt_getAtomListProperty(DefaultRootWindow(awt_display),
- _XA_SUN_WM_PROTOCOLS, NULL);
- if (list == NULL) {
- DTRACE_PRINTLN("no _SUN_WM_PROTOCOLS on root");
- return False;
- }
-
- DTRACE_PRINTLN("yes");
- XFree(list);
- return True;
-}
-
-
-
-static Boolean winmgr_running = False;
-
-/*
- * Temporary error handler that checks if selecting for
- * SubstructureRedirect failed.
- */
-static int /* but ignored */
-xerror_detect_wm(Display *dpy, XErrorEvent *err)
-{
- XERROR_SAVE(err);
- if (err->request_code == X_ChangeWindowAttributes
- && err->error_code == BadAccess)
- {
- DTRACE_PRINTLN("some WM is running (hmm, we'll see)");
- winmgr_running = True;
- return 0;
- }
- else {
- return (*xerror_saved_handler)(dpy, err);
- }
-}
-
-
-/*
- * Make an educated guess about running window manager.
- * XXX: ideally, we should detect wm restart.
- */
-enum wmgr_t
-awt_wm_getRunningWM(void)
-{
- /*
- * Ideally, we should support cases when a different WM is started
- * during a Java app lifetime.
- */
- static enum wmgr_t awt_wmgr = UNDETERMINED_WM;
-
- XSetWindowAttributes substruct;
- const char *vendor_string;
- Boolean doIsIceWM;
-
- if (awt_wmgr != UNDETERMINED_WM) {
- return awt_wmgr;
- }
-
- /*
- * Quick checks for specific servers.
- */
- vendor_string = ServerVendor(awt_display);
- if (strstr(vendor_string, "eXcursion") != NULL) {
- /*
- * Use NO_WM since in all other aspects eXcursion is like not
- * having a window manager running. I.e. it does not reparent
- * top level shells.
- */
- DTRACE_PRINTLN("WM: eXcursion detected - treating as NO_WM");
- awt_wmgr = NO_WM;
- return awt_wmgr;
- }
-
- /*
- * If *any* window manager is running?
- *
- * Try selecting for SubstructureRedirect, that only one client
- * can select for, and if the request fails, than some other WM is
- * already running.
- */
- winmgr_running = 0;
- substruct.event_mask = SubstructureRedirectMask;
-
- DTRACE_PRINT("WM: trying SubstructureRedirect ... ");
- WITH_XERROR_HANDLER(xerror_detect_wm);
- {
- XChangeWindowAttributes(awt_display, DefaultRootWindow(awt_display),
- CWEventMask, &substruct);
- }
- RESTORE_XERROR_HANDLER;
-
- /*
- * If no WM is running than our selection for SubstructureRedirect
- * succeeded and needs to be undone (hey we are *not* a WM ;-).
- */
- if (!winmgr_running) {
- DTRACE_PRINTLN("no WM is running");
- awt_wmgr = NO_WM;
- substruct.event_mask = 0;
- XChangeWindowAttributes(awt_display, DefaultRootWindow(awt_display),
- CWEventMask, &substruct);
- return NO_WM;
- }
-
- /* actual check for IceWM to follow below */
- doIsIceWM = awt_wm_prepareIsIceWM(); /* and let IceWM to act */
-
- if (awt_wm_isNetSupporting()) {
- awt_wm_doStateProtocolNet();
- }
- if (awt_wm_isWinSupporting()) {
- awt_wm_doStateProtocolWin();
- }
-
- /*
- * Ok, some WM is out there. Check which one by testing for
- * "distinguishing" atoms.
- */
- if (doIsIceWM && awt_wm_isIceWM()) {
- awt_wmgr = ICE_WM;
- }
- else if (awt_wm_isEnlightenment()) {
- awt_wmgr = ENLIGHTEN_WM;
- }
- else if (awt_wm_isMetacity()) {
- awt_wmgr = METACITY_WM;
- }
- else if (awt_wm_isSawfish()) {
- awt_wmgr = SAWFISH_WM;
- }
- else if (awt_wm_isKDE2()) {
- awt_wmgr = KDE2_WM;
- }
- /*
- * We don't check for legacy WM when we already know that WM
- * supports WIN or _NET wm spec.
- */
- else if (awt_wm_isNetSupporting()) {
- DTRACE_PRINTLN("WM: other WM (supports _NET)");
- awt_wmgr = OTHER_WM;
- }
- else if (awt_wm_isWinSupporting()) {
- DTRACE_PRINTLN("WM: other WM (supports _WIN)");
- awt_wmgr = OTHER_WM;
- }
- /*
- * Check for legacy WMs.
- */
- else if (awt_wm_isCDE()) { /* XXX: must come before isMotif */
- awt_wmgr = CDE_WM;
- }
- else if (awt_wm_isMotif()) {
- awt_wmgr = MOTIF_WM;
- }
- else if (awt_wm_isOpenLook()) {
- awt_wmgr = OPENLOOK_WM;
- }
- else {
- DTRACE_PRINTLN("WM: some other legacy WM");
- awt_wmgr = OTHER_WM;
- }
-
- return awt_wmgr;
-}
-
-
-/*
- * Some buggy WMs ignore window gravity when processing
- * ConfigureRequest and position window as if the gravity is Static.
- * We work around this in MWindowPeer.pReshape().
- */
-Boolean
-awt_wm_configureGravityBuggy(void)
-{
- static int env_not_checked = 1;
- static int env_buggy = 0;
-
- if (env_not_checked) {
- DTRACE_PRINT("WM: checking for _JAVA_AWT_WM_STATIC_GRAVITY in environment ... ");
- if (getenv("_JAVA_AWT_WM_STATIC_GRAVITY") != NULL) {
- DTRACE_PRINTLN("set");
- env_buggy = 1;
- } else {
- DTRACE_PRINTLN("no");
- }
- env_not_checked = 0;
- }
-
- if (env_buggy) {
- return True;
- }
-
- switch (awt_wm_getRunningWM()) {
- case ICE_WM:
- /*
- * See bug #228981 at IceWM's SourceForge pages.
- * Latest stable version 1.0.8-6 still has this problem.
- */
- return True;
-
- case ENLIGHTEN_WM:
- /* At least E16 is buggy. */
- return True;
-
- default:
- return False;
- }
-}
-
-/**
- * Check if state is supported.
- * Note that a compound state is always reported as not supported.
- * Note also that MAXIMIZED_BOTH is considered not a compound state.
- * Therefore, a compound state is just ICONIFIED | anything else.
- *
- */
-Boolean
-awt_wm_supportsExtendedState(jint state)
-{
- switch (state) {
- case java_awt_Frame_MAXIMIZED_VERT:
- case java_awt_Frame_MAXIMIZED_HORIZ:
- /*
- * WMs that talk NET/WIN protocol, but do not support
- * unidirectional maximization.
- */
- if (awt_wm_getRunningWM() == METACITY_WM) {
- /* "This is a deliberate policy decision." -hp */
- return JNI_FALSE;
- }
- /* FALLTROUGH */
- case java_awt_Frame_MAXIMIZED_BOTH:
- return (awt_wm_doStateProtocolNet() || awt_wm_doStateProtocolWin());
- default:
- return JNI_FALSE;
- }
-}
-
-
-
-
-/*****************************************************************************\
- *
- * Size and decoration hints ...
- *
-\*****************************************************************************/
-
-
-/*
- * Remove size hints specified by the mask.
- * XXX: Why do we need this in the first place???
- */
-void
-awt_wm_removeSizeHints(Widget shell, long mask)
-{
- Display *dpy = XtDisplay(shell);
- Window shell_win = XtWindow(shell);
- XSizeHints *hints = XAllocSizeHints();
- long ignore = 0;
-
- if (hints == NULL) {
- DTRACE_PRINTLN("WM: removeSizeHints FAILED to allocate XSizeHints");
- return;
- }
-
- /* sanitize the mask, only do these hints */
- mask &= (PMaxSize|PMinSize|USPosition|PPosition);
-
- XGetWMNormalHints(dpy, shell_win, hints, &ignore);
- if ((hints->flags & mask) == 0) {
- XFree(hints);
- return;
- }
-
-#ifdef DEBUG
- DTRACE_PRINT("WM: removing hints");
-
- if (mask & PMaxSize) {
- DTRACE_PRINT(" Max = ");
- if (hints->flags & PMaxSize) {
- DTRACE_PRINT2("%d x %d;", hints->max_width, hints->max_height);
- } else {
- DTRACE_PRINT("none;");
- }
- }
-
- if (mask & PMinSize) {
- DTRACE_PRINT(" Min = ");
- if (hints->flags & PMinSize) {
- DTRACE_PRINT2("%d x %d;", hints->min_width, hints->min_height);
- } else {
- DTRACE_PRINT("none;");
- }
- }
-
- DTRACE_PRINTLN("");
-#endif
-
- hints->flags &= ~mask;
- XSetWMNormalHints(dpy, shell_win, hints);
- XFree(hints);
-}
-
-/*
- *
- *
- */
-static void
-awt_wm_proclaimUrgency(struct FrameData *wdata)
-{
- Display *dpy = XtDisplay(wdata->winData.shell);
- Window shell_win = XtWindow(wdata->winData.shell);
-
- XWMHints *hints = XGetWMHints(dpy, shell_win);
- if( hints == NULL ) {
- /* For now just */ return;
- }
- if ((hints->flags & URGENCY_HINT) != 0) {
- /* it's here already */
- XFree(hints);
- return;
- }
- hints->flags |= URGENCY_HINT;
- XSetWMHints(dpy, shell_win, hints);
- XFree(hints);
-}
-
-/*
- * If MWM_DECOR_ALL bit is set, then the rest of the bit-mask is taken
- * to be subtracted from the decorations. Normalize decoration spec
- * so that we can map motif decor to something else bit-by-bit in the
- * rest of the code.
- */
-static int
-awt_wm_normalizeMotifDecor(int decorations)
-{
- int d;
-
- if (!(decorations & MWM_DECOR_ALL))
- return decorations; /* already normalized */
-
- d = MWM_DECOR_BORDER |MWM_DECOR_RESIZEH | MWM_DECOR_TITLE
- | MWM_DECOR_MENU | MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE;
- d &= ~decorations;
- return d;
-}
-
-
-/*
- * Infer OL properties from MWM decorations.
- * Use _OL_DECOR_DEL(ATOM[]) to remove unwanted ones.
- */
-static void
-awt_wm_setOLDecor(struct FrameData *wdata, Boolean resizable, int decorations)
-{
- Window shell_win = XtWindow(wdata->winData.shell);
- Atom decorDel[3];
- int nitems;
-
- if (shell_win == None) {
- DTRACE_PRINTLN("WM: setOLDecor - no window, returning");
- return;
- }
-
- decorations = awt_wm_normalizeMotifDecor(decorations);
- DTRACE_PRINT("WM: _OL_DECOR_DEL = {");
-
- nitems = 0;
- if (!(decorations & MWM_DECOR_TITLE)) {
- DTRACE_PRINT(" _OL_DECOR_HEADER");
- decorDel[nitems++] = _XA_OL_DECOR_HEADER;
- }
- if (!(decorations & (MWM_DECOR_RESIZEH | MWM_DECOR_MAXIMIZE))) {
- DTRACE_PRINT(" _OL_DECOR_RESIZE");
- decorDel[nitems++] = _XA_OL_DECOR_RESIZE;
- }
- if (!(decorations & (MWM_DECOR_MENU | MWM_DECOR_MAXIMIZE
- | MWM_DECOR_MINIMIZE)))
- {
- DTRACE_PRINT(" _OL_DECOR_CLOSE");
- decorDel[nitems++] = _XA_OL_DECOR_CLOSE;
- }
- DTRACE_PRINT(" }");
-
- if (nitems == 0) {
- DTRACE_PRINTLN(" ... removing");
- XDeleteProperty(awt_display, shell_win, _XA_OL_DECOR_DEL);
- }
- else {
- DTRACE_PRINTLN(" ... setting");
- XChangeProperty(awt_display, shell_win,
- _XA_OL_DECOR_DEL, XA_ATOM, 32,
- PropModeReplace, (unsigned char *)decorDel, nitems);
- }
-}
-
-/*
- * Set MWM decorations. Infer MWM functions from decorations.
- */
-static void
-awt_wm_setMotifDecor(struct FrameData *wdata, Boolean resizable, int decorations)
-{
- int functions;
-
- /* Apparently some WMs don't implement MWM_*_ALL semantic correctly */
- if ((decorations & MWM_DECOR_ALL) && (decorations != MWM_DECOR_ALL)) {
- decorations = awt_wm_normalizeMotifDecor(decorations);
- DTRACE_PRINTLN1("WM: setMotifDecor normalize exclusions, decor = 0x%X",
- decorations);
- }
-
- DTRACE_PRINT("WM: setMotifDecor functions = {");
- functions = 0;
-
- if (decorations & MWM_DECOR_ALL) {
- DTRACE_PRINT(" ALL");
- functions |= MWM_FUNC_ALL;
- }
- else {
- /*
- * Functions we always want to be enabled as mwm(1) and
- * descendants not only hide disabled functions away from
- * user, but also ignore corresponding requests from the
- * program itself (e.g. 4442047).
- */
- DTRACE_PRINT(" CLOSE MOVE MINIMIZE");
- functions |= (MWM_FUNC_CLOSE | MWM_FUNC_MOVE | MWM_FUNC_MINIMIZE);
-
- if (resizable) {
- DTRACE_PRINT(" RESIZE MAXIMIZE");
- functions |= MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE;
- }
- }
-
- DTRACE_PRINTLN(" }");
-
- XtVaSetValues(wdata->winData.shell,
- XmNmwmDecorations, decorations,
- XmNmwmFunctions, functions,
- NULL);
-}
-
-
-/*
- * Under some window managers if shell is already mapped, we MUST
- * unmap and later remap in order to effect the changes we make in the
- * window manager decorations.
- *
- * N.B. This unmapping / remapping of the shell exposes a bug in
- * X/Motif or the Motif Window Manager. When you attempt to map a
- * widget which is positioned (partially) off-screen, the window is
- * relocated to be entirely on screen. Good idea. But if both the x
- * and the y coordinates are less than the origin (0,0), the first
- * (re)map will move the window to the origin, and any subsequent
- * (re)map will relocate the window at some other point on the screen.
- * I have written a short Motif test program to discover this bug.
- * This should occur infrequently and it does not cause any real
- * problem. So for now we'll let it be.
- */
-static Boolean
-awt_wm_needRemap()
-{
- switch (awt_wm_getRunningWM()) {
-#if 0 /* XXX */
- case OPENLOOK_WM:
- case MOTIF_WM:
- case CDE_WM:
- case ICE_WM:
- case ENLIGHTEN_WM:
- return True;
-#endif
- default:
- return True;
- }
-}
-
-/*
- * Set decoration hints on the shell to wdata->decor adjusted
- * appropriately if not resizable.
- */
-void
-awt_wm_setShellDecor(struct FrameData *wdata, Boolean resizable)
-{
- int decorations = wdata->decor;
-
- DTRACE_PRINTLN3("WM: setShellDecor(0x%x/0x%x, %s)",
- wdata->winData.shell, XtWindow(wdata->winData.shell),
- resizable ? "resizable" : "not resizable");
-
- if (!resizable) {
- if (decorations & MWM_DECOR_ALL) {
- decorations |= (MWM_DECOR_RESIZEH | MWM_DECOR_MAXIMIZE);
- }
- else {
- decorations &= ~(MWM_DECOR_RESIZEH | MWM_DECOR_MAXIMIZE);
- }
- }
-
- DTRACE_PRINTLN1("WM: decorations = 0x%X", decorations);
- awt_wm_setMotifDecor(wdata, resizable, decorations);
- awt_wm_setOLDecor(wdata, resizable, decorations);
-
- /* Some WMs need remap to redecorate the window */
- if (wdata->isShowing && awt_wm_needRemap()) {
- /*
- * Do the re/mapping at the Xlib level. Since we essentially
- * work around a WM bug we don't want this hack to be exposed
- * to Intrinsics (i.e. don't mess with grabs, callbacks etc).
- */
- Display *dpy = XtDisplay(wdata->winData.shell);
- Window shell_win = XtWindow(wdata->winData.shell);
-
- DTRACE_PRINT("WM: setShellDecor REMAPPING ... ");
- XUnmapWindow(dpy, shell_win);
- XSync(dpy, False); /* give WM a chance to catch up */
- XMapWindow(dpy, shell_win);
- DTRACE_PRINTLN("done");
- }
-}
-
-
-/*
- * Make specified shell resizable.
- */
-void
-awt_wm_setShellResizable(struct FrameData *wdata)
-{
- DTRACE_PRINTLN2("WM: setShellResizable(0x%x/0x%x)",
- wdata->winData.shell, XtWindow(wdata->winData.shell));
-
- XtVaSetValues(wdata->winData.shell,
- XmNallowShellResize, True,
- XmNminWidth, XtUnspecifiedShellInt,
- XmNminHeight, XtUnspecifiedShellInt,
- XmNmaxWidth, XtUnspecifiedShellInt,
- XmNmaxHeight, XtUnspecifiedShellInt,
- NULL);
-
- /* REMINDER: will need to revisit when setExtendedStateBounds is added */
- awt_wm_removeSizeHints(wdata->winData.shell, PMinSize|PMaxSize);
-
- /* Restore decorations */
- awt_wm_setShellDecor(wdata, True);
-}
-
-
-/*
- * Make specified shell non-resizable.
- * If justChangeSize is false, update decorations as well.
- */
-void
-awt_wm_setShellNotResizable(struct FrameData *wdata,
- int32_t width, int32_t height,
- Boolean justChangeSize)
-{
- DTRACE_PRINTLN5("WM: setShellNotResizable(0x%x/0x%x, %d, %d, %s)",
- wdata->winData.shell, XtWindow(wdata->winData.shell),
- width, height,
- justChangeSize ? "size only" : "redecorate");
-
- /* Fix min/max size hints at the specified values */
- if ((width > 0) && (height > 0)) {
- XtVaSetValues(wdata->winData.shell,
- XmNwidth, (XtArgVal)width,
- XmNheight, (XtArgVal)height,
- XmNminWidth, (XtArgVal)width,
- XmNminHeight, (XtArgVal)height,
- XmNmaxWidth, (XtArgVal)width,
- XmNmaxHeight, (XtArgVal)height,
- NULL);
- }
-
- if (!justChangeSize) { /* update decorations */
- awt_wm_setShellDecor(wdata, False);
- }
-}
-
-
-/*
- * Helper function for awt_wm_getInsetsFromProp.
- * Read property of type CARDINAL[4] = { left, right, top, bottom }
- */
-static Boolean
-awt_wm_readInsetsArray(Window shell_win, Atom insets_property,
- int32_t *top, int32_t *left, int32_t *bottom, int32_t *right)
-{
- /* Request status */
- int status;
-
- /* Returns of XGetWindowProperty */
- Atom actual_type;
- int actual_format;
- unsigned long nitems;
- unsigned long bytes_after;
- long *insets = NULL; /* NB: 64 bit: Format 32 props are 'long' */
-
- status = XGetWindowProperty (awt_display, shell_win,
- insets_property, 0, 4, False, XA_CARDINAL,
- &actual_type, &actual_format, &nitems, &bytes_after,
- (unsigned char **)&insets);
-
- if (status != Success || insets == NULL) {
- DTRACE_PRINTLN("failed");
- return False;
- }
-
- if (actual_type != XA_CARDINAL || actual_format != 32) {
- DTRACE_PRINTLN("type/format mismatch");
- XFree(insets);
- return False;
- }
-
- *left = (int32_t)insets[0];
- *right = (int32_t)insets[1];
- *top = (int32_t)insets[2];
- *bottom = (int32_t)insets[3];
- XFree(insets);
-
- /* Order is that of java.awt.Insets.toString */
- DTRACE_PRINTLN4("[top=%d,left=%d,bottom=%d,right=%d]",
- *top, *left, *bottom, *right);
- return True;
-}
-
-/*
- * If WM implements the insets property - fill insets with values
- * specified in that property.
- */
-Boolean
-awt_wm_getInsetsFromProp(Window shell_win,
- int32_t *top, int32_t *left, int32_t *bottom, int32_t *right)
-{
- switch (awt_wm_getRunningWM()) {
-
- case ENLIGHTEN_WM:
- DTRACE_PRINT("WM: reading _E_FRAME_SIZE ... ");
- return awt_wm_readInsetsArray(shell_win, _XA_E_FRAME_SIZE,
- top, left, bottom, right);
-
-#if 0
- /*
- * uwe: disabled for now, as KDE seems to supply bogus values
- * when we maximize iconified frame. Need to verify with KDE2.1.
- * NB: Also note, that "external" handles (e.g. in laptop decor)
- * are also included in the frame strut, which is probably not
- * what we want.
- */
- case KDE2_WM:
- DTRACE_PRINT("WM: reading _KDE_NET_WM_FRAME_STRUT ... ");
- return awt_wm_readInsetsArray(shell_win, _XA_KDE_NET_WM_FRAME_STRUT,
- top, left, bottom, right);
-#endif
-
- default:
- return False;
- }
-}
-
-/*
- * XmNiconic and Map/UnmapNotify (that XmNiconic relies on) are
- * unreliable, since mapping changes can happen for a virtual desktop
- * switch or MacOS style shading that became quite popular under X as
- * well. Yes, it probably should not be this way, as it violates
- * ICCCM, but reality is that quite a lot of window managers abuse
- * mapping state.
- */
-int
-awt_wm_getWMState(Window shell_win)
-{
- /* Request status */
- int status;
-
- /* Returns of XGetWindowProperty */
- Atom actual_type;
- int actual_format;
- unsigned long nitems;
- unsigned long bytes_after;
- long *data; /* NB: 64 bit: Format 32 props are 'long' */
-
- int wm_state;
-
- status = XGetWindowProperty(awt_display, shell_win,
- XA_WM_STATE, 0, 1, False, XA_WM_STATE,
- &actual_type, &actual_format, &nitems, &bytes_after,
- (unsigned char **)&data);
-
- if (status != Success || data == NULL) {
- return WithdrawnState;
- }
-
- if (actual_type != XA_WM_STATE) {
- DTRACE_PRINTLN1("WM: WM_STATE(0x%x) - wrong type", shell_win);
- XFree(data);
- return WithdrawnState;
- }
-
- wm_state = (int)*data;
- XFree(data);
- return wm_state;
-}
-
-
-
-/*****************************************************************************\
- *
- * Reading state from properties WM puts on our window ...
- *
-\*****************************************************************************/
-
-/*
- * New "NET" WM spec: _NET_WM_STATE/Atom[]
- */
-static jint
-awt_wm_getStateNet(Window shell_win)
-{
- Atom *net_wm_state;
- jint java_state;
- unsigned long nitems;
- unsigned long i;
-
- net_wm_state = awt_getAtomListProperty(shell_win, _XA_NET_WM_STATE, &nitems);
- if (nitems == 0) {
- DTRACE_PRINTLN("WM: _NET_WM_STATE = { }");
- if (net_wm_state) {
- XFree(net_wm_state);
- }
- return java_awt_Frame_NORMAL;
- }
-#ifdef DEBUG
- DTRACE_PRINT("WM: ");
- awt_wm_dtraceStateNet(net_wm_state, nitems);
-#endif
-
- java_state = java_awt_Frame_NORMAL;
- for (i = 0; i < nitems; ++i) {
- if (net_wm_state[i] == _XA_NET_WM_STATE_MAXIMIZED_VERT) {
- java_state |= java_awt_Frame_MAXIMIZED_VERT;
- }
- else if (net_wm_state[i] == _XA_NET_WM_STATE_MAXIMIZED_HORZ) {
- java_state |= java_awt_Frame_MAXIMIZED_HORIZ;
- }
- }
- XFree(net_wm_state);
- return java_state;
-}
-
-Boolean
-awt_wm_isStateNetHidden(Window shell_win)
-{
- Atom *net_wm_state;
- Boolean result = False;
- unsigned long nitems;
- unsigned long i;
-
- net_wm_state = awt_getAtomListProperty(shell_win, _XA_NET_WM_STATE, &nitems);
- if (nitems == 0) {
- DTRACE_PRINTLN("WM: _NET_WM_STATE = { }");
- if (net_wm_state) {
- XFree(net_wm_state);
- }
- return False;
- }
-#ifdef DEBUG
- DTRACE_PRINT("WM: ");
- awt_wm_dtraceStateNet(net_wm_state, nitems);
-#endif
-
- for (i = 0; i < nitems; ++i) {
- if (net_wm_state[i] == _XA_NET_WM_STATE_HIDDEN) {
- result = True;
- }
- }
- XFree(net_wm_state);
- return result;
-}
-
-/*
- * Similar code to getStateNet, to get layer state.
- */
-static int
-awt_wm_getLayerNet(Window shell_win)
-{
- Atom *net_wm_state;
- int java_state;
- unsigned long nitems;
- unsigned long i;
-
- net_wm_state = awt_getAtomListProperty(shell_win, _XA_NET_WM_STATE, &nitems);
- if (nitems == 0) {
- DTRACE_PRINTLN("WM: _NET_WM_STATE = { }");
- if (net_wm_state) {
- XFree(net_wm_state);
- }
- return LAYER_NORMAL;
- }
-#ifdef DEBUG
- DTRACE_PRINT("WM: ");
- awt_wm_dtraceStateNet(net_wm_state, nitems);
-#endif
-
- java_state = LAYER_NORMAL;
- for (i = 0; i < nitems; ++i) {
- if (net_wm_state[i] == _XA_NET_WM_STATE_ABOVE) {
- java_state = LAYER_ALWAYS_ON_TOP;
- }
- }
- XFree(net_wm_state);
- return java_state;
-}
-
-/*
- * Old Gnome spec: _WIN_STATE/CARDINAL
- */
-static jint
-awt_wm_getStateWin(Window shell_win)
-{
- long win_state;
- jint java_state;
-
- win_state = awt_getProperty32(shell_win, _XA_WIN_STATE, XA_CARDINAL);
-#ifdef DEBUG
- DTRACE_PRINT("WM: ");
- awt_wm_dtraceStateWin(win_state);
-#endif
-
- java_state = java_awt_Frame_NORMAL;
- if (win_state & WIN_STATE_MAXIMIZED_VERT) {
- java_state |= java_awt_Frame_MAXIMIZED_VERT;
- }
- if (win_state & WIN_STATE_MAXIMIZED_HORIZ) {
- java_state |= java_awt_Frame_MAXIMIZED_HORIZ;
- }
- return java_state;
-}
-
-/*
- * Code similar to getStateWin, to get layer state.
- */
-static int
-awt_wm_getLayerWin(Window shell_win)
-{
- long win_state;
- jint java_state;
-
- win_state = awt_getProperty32(shell_win, _XA_WIN_LAYER, XA_CARDINAL);
-#ifdef DEBUG
- DTRACE_PRINT("WM: ");
- awt_wm_dtraceStateWin(win_state);
-#endif
-
- java_state = LAYER_NORMAL;
- if (win_state == WIN_LAYER_ONTOP) {
- java_state = LAYER_ALWAYS_ON_TOP;
- }
- return java_state;
-}
-
-
-static jint
-awt_wm_getExtendedState(Window shell_win)
-{
- if (awt_wm_doStateProtocolNet()) {
- return awt_wm_getStateNet(shell_win);
- }
- else if (awt_wm_doStateProtocolWin()) {
- return awt_wm_getStateWin(shell_win);
- }
- else {
- return java_awt_Frame_NORMAL;
- }
-}
-
-jint
-awt_wm_getState(struct FrameData *wdata)
-{
- Window shell_win = XtWindow(wdata->winData.shell);
- jint java_state;
-
- DTRACE_PRINTLN2("WM: getState(0x%x/0x%x)",
- wdata->winData.shell, shell_win);
-
- if (shell_win == None) {
- DTRACE_PRINTLN("WM: no window, use wdata");
- java_state = wdata->state;
- }
- else {
- int wm_state = awt_wm_getWMState(shell_win);
- if (wm_state == WithdrawnState) {
- DTRACE_PRINTLN("WM: window withdrawn, use wdata");
- java_state = wdata->state;
- }
- else {
-#ifdef DEBUG
- DTRACE_PRINT("WM: ");
- awt_wm_dtraceWMState(wm_state);
-#endif
- if (wm_state == IconicState) {
- java_state = java_awt_Frame_ICONIFIED;
- } else {
- java_state = java_awt_Frame_NORMAL;
- }
- java_state |= awt_wm_getExtendedState(shell_win);
- }
- }
-
-#ifdef DEBUG
- DTRACE_PRINT("WM: ");
- awt_wm_dtraceStateJava(java_state);
-#endif
-
- return java_state;
-}
-
-
-
-/*****************************************************************************\
- *
- * Notice window state change when WM changes a property on the window ...
- *
-\*****************************************************************************/
-
-
-/*
- * Check if property change is a window state protocol message.
- * If it is - return True and return the new state in *pstate.
- */
-Boolean
-awt_wm_isStateChange(struct FrameData *wdata, XPropertyEvent *e, jint *pstate)
-{
- Window shell_win = XtWindow(wdata->winData.shell);
- Boolean is_state_change = False;
- int wm_state;
-
- if (!wdata->isShowing) {
- return False;
- }
-
- wm_state = awt_wm_getWMState(shell_win);
- if (wm_state == WithdrawnState) {
- return False;
- }
-
- if (e->atom == XA_WM_STATE) {
- is_state_change = True;
- }
- else if (e->atom == _XA_NET_WM_STATE) {
- is_state_change = awt_wm_doStateProtocolNet();
- }
- else if (e->atom == _XA_WIN_STATE) {
- is_state_change = awt_wm_doStateProtocolWin();
- }
-
- if (is_state_change) {
-#ifdef DEBUG
- Widget shell = wdata->winData.shell;
- char *name = XGetAtomName(XtDisplay(shell), e->atom);
- DTRACE_PRINTLN4("WM: PropertyNotify(0x%x/0x%x) %s %s",
- shell, XtWindow(shell),
- name != NULL ? name : "???",
- e->state == PropertyNewValue ? "changed" : "deleted");
- if (name != NULL) {
- XFree(name);
- }
- DTRACE_PRINT("WM: ");
- awt_wm_dtraceWMState(wm_state);
-#endif
- if (wm_state == IconicState) {
- *pstate = java_awt_Frame_ICONIFIED;
- } else {
- *pstate = java_awt_Frame_NORMAL;
- }
- *pstate |= awt_wm_getExtendedState(shell_win);
-
-#ifdef DEBUG
- DTRACE_PRINT("WM: ");
- awt_wm_dtraceStateJava(*pstate);
-#endif
- }
-
- return is_state_change;
-}
-
-
-
-
-/*****************************************************************************\
- *
- * Setting/changing window state ...
- *
-\*****************************************************************************/
-
-/*
- * Request a state transition from a _NET supporting WM by sending
- * _NET_WM_STATE ClientMessage to root window.
- */
-static void
-awt_wm_requestStateNet(struct FrameData *wdata, jint state)
-{
- Widget shell = wdata->winData.shell;
- Window shell_win = XtWindow(shell);
- XClientMessageEvent req;
- jint old_net_state;
- jint max_changed;
-
- /* must use awt_wm_setInitialStateNet for withdrawn windows */
- DASSERT(wdata->isShowing);
-
- /*
- * We have to use toggle for maximization because of transitions
- * from maximization in one direction only to maximization in the
- * other direction only.
- */
- old_net_state = awt_wm_getStateNet(shell_win);
- max_changed = (state ^ old_net_state) & java_awt_Frame_MAXIMIZED_BOTH;
-
- switch (max_changed) {
- case 0:
- DTRACE_PRINTLN("WM: requestStateNet - maximization unchanged");
- return;
-
- case java_awt_Frame_MAXIMIZED_HORIZ:
- DTRACE_PRINTLN("WM: requestStateNet - toggling MAX_HORZ");
- req.data.l[1] = _XA_NET_WM_STATE_MAXIMIZED_HORZ;
- req.data.l[2] = 0;
- break;
-
- case java_awt_Frame_MAXIMIZED_VERT:
- DTRACE_PRINTLN("WM: requestStateNet - toggling MAX_VERT");
- req.data.l[1] = _XA_NET_WM_STATE_MAXIMIZED_VERT;
- req.data.l[2] = 0;
- break;
-
- default: /* both */
- DTRACE_PRINTLN("WM: requestStateNet - toggling HORZ + VERT");
- req.data.l[1] = _XA_NET_WM_STATE_MAXIMIZED_HORZ;
- req.data.l[2] = _XA_NET_WM_STATE_MAXIMIZED_VERT;
- break;
- }
-
- req.type = ClientMessage;
- req.window = XtWindow(shell);
- req.message_type = _XA_NET_WM_STATE;
- req.format = 32;
- req.data.l[0] = _NET_WM_STATE_TOGGLE;
-
- XSendEvent(XtDisplay(shell), RootWindowOfScreen(XtScreen(shell)), False,
- (SubstructureRedirectMask | SubstructureNotifyMask),
- (XEvent *)&req);
-}
-
-
-/*
- * Request state transition from a Gnome WM (_WIN protocol) by sending
- * _WIN_STATE ClientMessage to root window.
- */
-static void
-awt_wm_requestStateWin(struct FrameData *wdata, jint state)
-{
- Widget shell = wdata->winData.shell;
- XClientMessageEvent req;
- long win_state; /* typeof(XClientMessageEvent.data.l) */
-
- /* must use awt_wm_setInitialStateWin for withdrawn windows */
- DASSERT(wdata->isShowing);
-
- win_state = 0;
- if (state & java_awt_Frame_MAXIMIZED_VERT) {
- win_state |= WIN_STATE_MAXIMIZED_VERT;
- }
- if (state & java_awt_Frame_MAXIMIZED_HORIZ) {
- win_state |= WIN_STATE_MAXIMIZED_HORIZ;
- }
-
- req.type = ClientMessage;
- req.window = XtWindow(shell);
- req.message_type = _XA_WIN_STATE;
- req.format = 32;
- req.data.l[0] = (WIN_STATE_MAXIMIZED_HORIZ | WIN_STATE_MAXIMIZED_VERT);
- req.data.l[1] = win_state;
-
- XSendEvent(XtDisplay(shell), RootWindowOfScreen(XtScreen(shell)), False,
- (SubstructureRedirectMask | SubstructureNotifyMask),
- (XEvent *)&req);
-}
-
-
-/*
- * Specify initial state for _NET supporting WM by setting
- * _NET_WM_STATE property on the window to the desired state before
- * mapping it.
- */
-static void
-awt_wm_setInitialStateNet(struct FrameData *wdata, jint state)
-{
- Widget shell = wdata->winData.shell;
- Window shell_win = XtWindow(shell);
- Display *dpy = XtDisplay(shell);
-
- Atom *old_state;
- unsigned long nitems;
-
- /* must use awt_wm_requestStateNet for managed windows */
- DASSERT(!wdata->isShowing);
-
- /* Be careful to not wipe out state bits we don't understand */
- old_state = awt_getAtomListProperty(shell_win, _XA_NET_WM_STATE, &nitems);
-
- if (nitems == 0) {
- /*
- * Empty or absent _NET_WM_STATE - set a new one if necessary.
- */
- Atom net_wm_state[AWT_NET_N_KNOWN_STATES];
-
- if (old_state != NULL) {
- XFree(old_state);
- }
-
- if (state & java_awt_Frame_MAXIMIZED_VERT) {
- net_wm_state[nitems++] = _XA_NET_WM_STATE_MAXIMIZED_VERT;
- }
- if (state & java_awt_Frame_MAXIMIZED_HORIZ) {
- net_wm_state[nitems++] = _XA_NET_WM_STATE_MAXIMIZED_HORZ;
- }
- DASSERT(nitems <= AWT_NET_N_KNOWN_STATES);
-
- if (nitems == 0) {
- DTRACE_PRINTLN("WM: initial _NET_WM_STATE not necessary");
- return;
- }
-
-#ifdef DEBUG
- DTRACE_PRINT("WM: setting initial ");
- awt_wm_dtraceStateNet(net_wm_state, nitems);
-#endif
- XChangeProperty(dpy, shell_win,
- _XA_NET_WM_STATE, XA_ATOM, 32, PropModeReplace,
- (unsigned char *)net_wm_state, nitems);
- }
- else {
- /*
- * Tweak existing _NET_WM_STATE, preserving bits we don't use.
- */
- jint want= state /* which flags we want */
- & (java_awt_Frame_MAXIMIZED_HORIZ | java_awt_Frame_MAXIMIZED_VERT);
-
- jint has = 0; /* which flags the window already has */
- int mode; /* property mode: replace/append */
-
- Atom *new_state; /* new _net_wm_state value */
- int new_nitems;
- unsigned long i;
-
-#ifdef DEBUG
- DTRACE_PRINT("WM: already has ");
- awt_wm_dtraceStateNet(old_state, nitems);
-#endif
-
- for (i = 0; i < nitems; ++i) {
- if (old_state[i] == _XA_NET_WM_STATE_MAXIMIZED_HORZ) {
- has |= java_awt_Frame_MAXIMIZED_HORIZ;
- }
- else if (old_state[i] == _XA_NET_WM_STATE_MAXIMIZED_VERT) {
- has |= java_awt_Frame_MAXIMIZED_VERT;
- }
- }
-
- if ((has ^ want) == 0) {
- DTRACE_PRINTLN("WM: no changes to _NET_WM_STATE necessary");
- XFree(old_state);
- return;
- }
-
- new_nitems = 0;
- if (has == 0) { /* only adding flags */
- new_state = calloc(AWT_NET_N_KNOWN_STATES, sizeof(Atom));
- mode = PropModeAppend;
- }
- else {
- new_state = calloc(nitems + AWT_NET_N_KNOWN_STATES, sizeof(Atom));
- mode = PropModeReplace;
- }
-
- if (has != 0) { /* copy existing flags */
- DTRACE_PRINT("WM: ");
- for (i = 0; i < nitems; ++i) {
- if (old_state[i] == _XA_NET_WM_STATE_MAXIMIZED_HORZ) {
- if (want & java_awt_Frame_MAXIMIZED_HORIZ) {
- DTRACE_PRINT(" keep _HORZ");
- } else {
- DTRACE_PRINT(" drop _HORZ");
- continue;
- }
- }
- else if (old_state[i] == _XA_NET_WM_STATE_MAXIMIZED_VERT) {
- if (want & java_awt_Frame_MAXIMIZED_VERT) {
- DTRACE_PRINT(" keep _VERT");
- } else {
- DTRACE_PRINT(" drop _VERT");
- continue;
- }
- }
- new_state[new_nitems++] = old_state[i];
- }
- }
-
- /* Add missing flags */
- if ((want & java_awt_Frame_MAXIMIZED_HORIZ)
- && !(has & java_awt_Frame_MAXIMIZED_HORIZ))
- {
- DTRACE_PRINT(" add _HORZ");
- new_state[new_nitems] = _XA_NET_WM_STATE_MAXIMIZED_HORZ;
- ++new_nitems;
- }
- if ((want & java_awt_Frame_MAXIMIZED_VERT)
- && !(has & java_awt_Frame_MAXIMIZED_VERT))
- {
- DTRACE_PRINT(" add _VERT");
- new_state[new_nitems] = _XA_NET_WM_STATE_MAXIMIZED_VERT;
- ++new_nitems;
- }
-
- DTRACE_PRINTLN(mode == PropModeReplace ?
- " ... replacing" : " ... appending");
- XChangeProperty(dpy, shell_win,
- _XA_NET_WM_STATE, XA_ATOM, 32, mode,
- (unsigned char *)new_state, new_nitems);
- XFree(old_state);
- XFree(new_state);
- }
-}
-
-
-/*
- * Specify initial state for a Gnome WM (_WIN protocol) by setting
- * WIN_STATE property on the window to the desired state before
- * mapping it.
- */
-static void
-awt_wm_setInitialStateWin(struct FrameData *wdata, jint state)
-{
- Display *dpy = XtDisplay(wdata->winData.shell);
- Window shell_win = XtWindow(wdata->winData.shell);
- long win_state, old_win_state;
-
- /* must use awt_wm_requestStateWin for managed windows */
- DASSERT(!wdata->isShowing);
-
- /* Be careful to not wipe out state bits we don't understand */
- win_state = awt_getProperty32(shell_win, _XA_WIN_STATE, XA_CARDINAL);
- old_win_state = win_state;
-#ifdef DEBUG
- if (win_state != 0) {
- DTRACE_PRINT("WM: already has ");
- awt_wm_dtraceStateWin(win_state);
- }
-#endif
-
- /*
- * In their stupid quest of reinventing every wheel, Gnome WM spec
- * have its own "minimized" hint (instead of using initial state
- * and WM_STATE hints). This is bogus, but, apparently, some WMs
- * pay attention.
- */
- if (state & java_awt_Frame_ICONIFIED) {
- win_state |= WIN_STATE_MINIMIZED;
- } else {
- win_state &= ~WIN_STATE_MINIMIZED;
- }
-
- if (state & java_awt_Frame_MAXIMIZED_VERT) {
- win_state |= WIN_STATE_MAXIMIZED_VERT;
- } else {
- win_state &= ~WIN_STATE_MAXIMIZED_VERT;
- }
-
- if (state & java_awt_Frame_MAXIMIZED_HORIZ) {
- win_state |= WIN_STATE_MAXIMIZED_HORIZ;
- } else {
- win_state &= ~WIN_STATE_MAXIMIZED_HORIZ;
- }
-
- if (old_win_state ^ win_state) {
-#ifdef DEBUG
- DTRACE_PRINT("WM: setting initial ");
- awt_wm_dtraceStateWin(win_state);
-#endif
- XChangeProperty(dpy, shell_win,
- _XA_WIN_STATE, XA_CARDINAL, 32, PropModeReplace,
- (unsigned char *)&win_state, 1);
- }
-#ifdef DEBUG
- else {
- DTRACE_PRINTLN("WM: no changes to _WIN_STATE necessary");
- }
-#endif
-}
-
-/*
- * Request a layer change from a _NET supporting WM by sending
- * _NET_WM_STATE ClientMessage to root window.
- */
-static void
-awt_wm_requestLayerNet(struct FrameData *wdata, int state)
-{
- Widget shell = wdata->winData.shell;
- Window shell_win = XtWindow(shell);
- XClientMessageEvent req;
- int currentLayer;
- long cmd;
-
- /* must use awt_wm_setInitialLayerNet for withdrawn windows */
- DASSERT(wdata->isShowing);
-
- currentLayer = awt_wm_getLayerNet(shell_win);
- if(state == currentLayer) {
- return;
- }
- cmd = currentLayer == LAYER_ALWAYS_ON_TOP && state == LAYER_NORMAL ?
- _NET_WM_STATE_REMOVE :
- currentLayer == LAYER_NORMAL && state == LAYER_ALWAYS_ON_TOP ?
- _NET_WM_STATE_ADD :
- _NET_WM_STATE_ADD;
- req.type = ClientMessage;
- req.window = XtWindow(shell);
- req.message_type = _XA_NET_WM_STATE;
- req.format = 32;
- req.data.l[0] = cmd;
- req.data.l[1] = _XA_NET_WM_STATE_ABOVE;
- req.data.l[2] = 0L;
-
- XSendEvent(XtDisplay(shell), RootWindowOfScreen(XtScreen(shell)), False,
- (SubstructureRedirectMask | SubstructureNotifyMask),
- (XEvent *)&req);
-}
-
-/*
- * Request a layer change from a Gnome WM (_WIN protocol) by sending
- * _WIN_LAYER ClientMessage to root window.
- */
-static void
-awt_wm_requestLayerWin(struct FrameData *wdata, int state)
-{
- Widget shell = wdata->winData.shell;
- XClientMessageEvent req;
- Display *dpy = XtDisplay(shell);
-
- /* must use awt_wm_setInitialLayerWin for withdrawn windows */
- DASSERT(wdata->isShowing);
-
- req.type = ClientMessage;
- req.window = XtWindow(shell);
- req.message_type = _XA_WIN_LAYER;
- req.format = 32;
- req.data.l[0] = state == LAYER_NORMAL ? WIN_LAYER_NORMAL : WIN_LAYER_ONTOP;
- req.data.l[1] = 0L;
- req.data.l[2] = 0L;
-
- XSendEvent(XtDisplay(shell), RootWindowOfScreen(XtScreen(shell)), False,
- /*(SubstructureRedirectMask |*/
- SubstructureNotifyMask,
- (XEvent *)&req);
-}
-/*
- * Specify initial layer for _NET supporting WM by setting
- * _NET_WM_STATE property on the window to the desired state before
- * mapping it.
- * NB: looks like it doesn't have any effect.
- */
-static void
-awt_wm_setInitialLayerNet(struct FrameData *wdata, int state)
-{
- Widget shell = wdata->winData.shell;
- Window shell_win = XtWindow(shell);
- Display *dpy = XtDisplay(shell);
-
- Atom *old_state;
- unsigned long nitems;
- Atom new_state = _XA_NET_WM_STATE_ABOVE;
-
- /* must use awt_wm_requestLayerNet for managed windows */
- DASSERT(!wdata->isShowing);
-
- /* Be careful to not wipe out state bits we don't understand */
- old_state = awt_getAtomListProperty(shell_win, _XA_NET_WM_STATE, &nitems);
-
- if (nitems == 0 && state != LAYER_ALWAYS_ON_TOP) {
- if (old_state != NULL) {
- XFree(old_state);
- }
- return;
- }else if( nitems == 0 && state == LAYER_ALWAYS_ON_TOP) {
- unsigned long data[2];
- /* create new state */
- if (old_state != NULL) {
- XFree(old_state);
- }
- nitems = 1;
- data[0] = new_state;
- data[1] = 0;
- XChangeProperty(dpy, shell_win,
- _XA_NET_WM_STATE, XA_ATOM, 32, PropModeReplace,
- (unsigned char *)data, nitems);
- XSync(dpy, False);
- }else { /* nitems > 0 */
- unsigned long i;
- Boolean bShift = False;
- int mode;
- for(i = 0; i < nitems; i++) {
- if( bShift ) {
- old_state[i-1] = old_state[i];
- }else if( old_state[i] == _XA_NET_WM_STATE_ABOVE ) {
- if(state == LAYER_ALWAYS_ON_TOP) {
- /* no change necessary */
- XFree(old_state);
- return;
- }else{
- /* wipe off this atom */
- bShift = True;
- }
- }
- }
-
- if( bShift ) {
- /* atom was found and removed: change property */
- mode = PropModeReplace;
- nitems--;
- }else if( state != LAYER_ALWAYS_ON_TOP ) {
- /* atom was not found and not needed */
- XFree( old_state);
- return;
- }else {
- /* must add new atom */
- mode = PropModeAppend;
- nitems = 1;
- }
-
- XChangeProperty(dpy, shell_win,
- _XA_NET_WM_STATE, XA_ATOM, 32, mode,
- mode == PropModeAppend ?
- (unsigned char *)(&new_state) :
- (unsigned char *)old_state, nitems);
- XFree(old_state);
- XSync(dpy, False);
- }
-}
-
-/*
- * Specify initial layer for a Gnome WM (_WIN protocol) by setting
- * WIN_LAYER property on the window to the desired state before
- * mapping it.
- */
-static void
-awt_wm_setInitialLayerWin(struct FrameData *wdata, int state)
-{
- Display *dpy = XtDisplay(wdata->winData.shell);
- Window shell_win = XtWindow(wdata->winData.shell);
- long win_state, old_win_state;
- int currentLayer;
-
- /* must use awt_wm_requestLayerWin for managed windows */
- DASSERT(!wdata->isShowing);
-
- currentLayer = awt_wm_getLayerWin(shell_win);
- if( currentLayer == state ) {
- /* no change necessary */
- return;
- }
- if( state == LAYER_ALWAYS_ON_TOP ) {
- win_state = WIN_LAYER_ONTOP;
- }else {
- win_state = WIN_LAYER_NORMAL;
- }
-
- XChangeProperty(dpy, shell_win,
- _XA_WIN_LAYER, XA_CARDINAL, 32, PropModeReplace,
- (unsigned char *)&win_state, 1);
-}
-
-void
-awt_wm_setExtendedState(struct FrameData *wdata, jint state)
-{
- Display *dpy = XtDisplay(wdata->winData.shell);
- Window shell_win = XtWindow(wdata->winData.shell);
-
-#ifdef DEBUG
- DTRACE_PRINT2("WM: setExtendedState(0x%x/0x%x) ",
- wdata->winData.shell, shell_win);
- awt_wm_dtraceStateJava(state);
-#endif
-
- if (wdata->isShowing) {
- /*
- * If the window is managed by WM, we should send
- * ClientMessage requests.
- */
- if (awt_wm_doStateProtocolNet()) {
- awt_wm_requestStateNet(wdata, state);
- }
- else if (awt_wm_doStateProtocolWin()) {
- awt_wm_requestStateWin(wdata, state);
- }
- XSync(dpy, False);
- }
- else {
- /*
- * If the window is withdrawn we should set necessary
- * properties directly to the window before mapping it.
- */
- if (awt_wm_doStateProtocolNet()) {
- awt_wm_setInitialStateNet(wdata, state);
- }
- else if (awt_wm_doStateProtocolWin()) {
- awt_wm_setInitialStateWin(wdata, state);
- }
-#if 1
- /*
- * Purge KWM bits.
- * Not really tested with KWM, only with WindowMaker.
- */
- XDeleteProperty(dpy, shell_win, XA_KWM_WIN_ICONIFIED);
- XDeleteProperty(dpy, shell_win, XA_KWM_WIN_MAXIMIZED);
-#endif /* 1 */
- }
-}
-
-static Boolean
-awt_wm_supportsLayersNet() {
- Boolean supported = awt_wm_doStateProtocolNet();
-
- /*
- In fact, WM may report this not supported but do support.
- */
- supported &= awt_wm_checkProtocol(_XA_NET_SUPPORTED, _XA_NET_WM_STATE_ABOVE);
- return supported;
-}
-
-static Boolean
-awt_wm_supportsLayersWin() {
- Boolean supported = awt_wm_doStateProtocolWin();
- /*
- * In fact, WM may report this supported but do not support.
- */
- supported &= awt_wm_checkProtocol(_XA_WIN_PROTOCOLS, _XA_WIN_LAYER);
- return supported;
-}
-
-void
-awt_wm_updateAlwaysOnTop(struct FrameData *wdata, jboolean bLayerState) {
- Display *dpy = XtDisplay(wdata->winData.shell);
- Window shell_win = XtWindow(wdata->winData.shell);
- int layerState = bLayerState ? LAYER_ALWAYS_ON_TOP : LAYER_NORMAL;
-
- if (wdata->isShowing) {
- /**
- We don't believe anyone, and now send both ClientMessage requests.
- And eg Metacity under RH 6.1 required both to work.
- **/
- awt_wm_requestLayerNet(wdata, layerState);
- awt_wm_requestLayerWin(wdata, layerState);
- } else {
- /**
- We don't believe anyone, and now set both atoms.
- And eg Metacity under RH 6.1 required both to work.
- **/
- awt_wm_setInitialLayerNet(wdata, layerState);
- awt_wm_setInitialLayerWin(wdata, layerState);
- }
- XSync(dpy, False);
-}
-
-/*
- * Work around for 4775545. _NET version.
- */
-static void
-awt_wm_unshadeKludgeNet(struct FrameData *wdata)
-{
- Display *dpy = XtDisplay(wdata->winData.shell);
- Window shell_win = XtWindow(wdata->winData.shell);
- Atom *net_wm_state;
- Boolean shaded;
- unsigned long nitems;
- unsigned long i;
-
- net_wm_state = awt_getAtomListProperty(shell_win,
- _XA_NET_WM_STATE, &nitems);
- if (nitems == 0) {
- DTRACE_PRINTLN("WM: _NET_WM_STATE = { }");
- if (net_wm_state) {
- XFree(net_wm_state);
- }
- return;
- }
-#ifdef DEBUG
- DTRACE_PRINT("WM: ");
- awt_wm_dtraceStateNet(net_wm_state, nitems);
-#endif
-
- shaded = False;
- for (i = 0; i < nitems; ++i) {
- if (net_wm_state[i] == _XA_NET_WM_STATE_SHADED) {
- shaded = True;
- break;
- }
- }
-
- if (!shaded) {
- DTRACE_PRINTLN("WM: not _SHADED, no workaround necessary");
- return;
- }
-
- DTRACE_PRINTLN("WM: removing _SHADED");
- ++i; /* skip _SHADED */
- while (i < nitems) { /* copy the rest */
- net_wm_state[i-1] = net_wm_state[i];
- ++i;
- }
- --nitems; /* _SHADED has been removed */
-
-#ifdef DEBUG
- DTRACE_PRINT("WM: ");
- awt_wm_dtraceStateNet(net_wm_state, nitems);
-#endif
-
- WITH_XERROR_HANDLER(xerror_verify_change_property);
- {
- XChangeProperty(dpy, shell_win,
- _XA_NET_WM_STATE, XA_ATOM, 32, PropModeReplace,
- (unsigned char *)net_wm_state, nitems);
- }
- RESTORE_XERROR_HANDLER;
-
- if (xerror_code != Success) {
- DTRACE_PRINTLN1("WM: XChangeProperty failed, error = %d",
- xerror_code);
- }
-
- XFree(net_wm_state);
-}
-
-
-/*
- * Work around for 4775545. _WIN version.
- */
-static void
-awt_wm_unshadeKludgeWin(struct FrameData *wdata)
-{
- Display *dpy = XtDisplay(wdata->winData.shell);
- Window shell_win = XtWindow(wdata->winData.shell);
- long win_state;
-
- win_state = awt_getProperty32(shell_win, _XA_WIN_STATE, XA_CARDINAL);
-#ifdef DEBUG
- DTRACE_PRINT("WM: ");
- awt_wm_dtraceStateWin(win_state);
-#endif
-
- if ((win_state & WIN_STATE_SHADED) == 0) {
- DTRACE_PRINTLN("WM: not _SHADED, no workaround necessary");
- return;
- }
-
- win_state &= ~WIN_STATE_SHADED;
- XChangeProperty(dpy, shell_win,
- _XA_WIN_STATE, XA_CARDINAL, 32, PropModeReplace,
- (unsigned char *)&win_state, 1);
-}
-
-
-/*
- * Work around for 4775545.
- *
- * If WM exits while the top-level is shaded, the shaded hint remains
- * on the top-level properties. When WM restarts and sees the shaded
- * window it can reparent it into a "pre-shaded" decoration frame
- * (Metacity does), and our insets logic will go crazy, b/c it will
- * see a huge nagative bottom inset. There's no clean solution for
- * this, so let's just be weasels and drop the shaded hint if we
- * detect that WM exited. NB: we are in for a race condition with WM
- * restart here. NB2: e.g. WindowMaker saves the state in a private
- * property that this code knows nothing about, so this workaround is
- * not effective; other WMs might play similar tricks.
- */
-void
-awt_wm_unshadeKludge(struct FrameData *wdata)
-{
- DTRACE_PRINTLN("WM: unshade kludge");
- DASSERT(wdata->isShowing);
-
- if (awt_wm_doStateProtocolNet()) {
- awt_wm_unshadeKludgeNet(wdata);
- }
- else if (awt_wm_doStateProtocolWin()) {
- awt_wm_unshadeKludgeWin(wdata);
- }
-#ifdef DEBUG
- else {
- DTRACE_PRINTLN("WM: not a _NET or _WIN supporting WM");
- }
-#endif
-
- XSync(XtDisplay(wdata->winData.shell), False);
-}
-
-
-void
-awt_wm_init(void)
-{
- static Boolean inited = False;
- if (inited) {
- return;
- }
-
- awt_wm_initAtoms();
- awt_wm_getRunningWM();
- inited = True;
-}
-
-Boolean awt_wm_supportsAlwaysOnTop() {
- return awt_wm_supportsLayersNet() || awt_wm_supportsLayersWin();
-}