/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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
#endif
/*
* Some SCIENCE stuff happens, and it is CONFUSING
*/
#include "awt_p.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.
*
* 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 */
/* New "netwm" spec from www.freedesktop.org */
/*
* _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 .
*/
/* Currently we only care about max_v and max_h in _NET_WM_STATE */
/* Gnome WM spec (superseded by "netwm" above, but still in use) */
/* Enlightenment */
/* KWin (KDE2) */
/* KWM (KDE 1.x) OBSOLETE??? */
/* OpenLook */
/* For _NET_WM_STATE ClientMessage requests */
/* _WIN_STATE bits */
#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 {
const char *name;
};
/* Just add new atoms to this 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" }
};
size_t i;
/* Fill the array of atom names */
for (i = 0; i < ATOM_LIST_LENGTH; ++i) {
}
DTRACE_PRINT("WM: initializing 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) {
}
}
/*
* 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
{
return False;
} else {
return True;
}
} else {
return True;
}
}
/*****************************************************************************\
*
* DTRACE utils for various states ...
*
\*****************************************************************************/
static void
{
#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:
break;
}
#endif /* DEBUG */
}
static void
{
#ifdef DEBUG
unsigned long i;
DTRACE_PRINT("_NET_WM_STATE = {");
for (i = 0; i < nitems; ++i) {
print_name = "???";
} else {
print_name = name;
}
if (name) {
}
}
DTRACE_PRINTLN(" }");
#endif
}
static void
{
#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
{
#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");
}
{
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 ...
*
\*****************************************************************************/
/*
* 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 *
{
/* Request status */
int status;
/* Returns of XGetWindowProperty */
int actual_format;
unsigned long nitems_stub;
unsigned long bytes_after;
if (nitems_ptr == NULL) {
/* Caller is not interested in the number of items,
provide a stub for XGetWindowProperty */
}
(unsigned char **)&list);
*nitems_ptr = 0;
return NULL;
}
*nitems_ptr = 0;
return NULL;
}
if (*nitems_ptr == 0) {
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 *
{
/* Request status */
int status;
/* Returns of XGetWindowProperty */
int actual_format;
unsigned long nitems;
unsigned long bytes_after;
unsigned char *string;
/* BadWindow is ok and will be blocked by our special handler */
"()Lsun/awt/X11/XErrorHandler$IgnoreBadWindowHandler;", JNI_FALSE,
&string));
return NULL;
}
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
{
/* Property value*/
/* Request status */
int status;
/* Returns of XGetWindowProperty */
int actual_format;
unsigned long nitems;
unsigned long bytes_after;
/* BadWindow is ok and will be blocked by our special handler */
"()Lsun/awt/X11/XErrorHandler$IgnoreBadWindowHandler;", JNI_FALSE,
(unsigned char **)&data));
return 0;
}
return 0;
}
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
{
DTRACE_PRINTLN("no");
return None;
}
DTRACE_PRINTLN("stale");
return None;
}
DTRACE_PRINTLN("ok");
return self_xref;
}
/*
* New WM spec: KDE 2.0.1, sawfish 0.3x, ...
*/
static Window
awt_wm_isNetSupporting(void)
{
if (checked) {
return isNetSupporting;
}
DTRACE_PRINT("WM: checking for _NET_SUPPORTING ... ");
return isNetSupporting;
}
/*
* Old Gnome WM spec: WindowMaker, Enlightenment, IceWM ...
*/
static Window
awt_wm_isWinSupporting(void)
{
if (checked) {
return isWinSupporting;
}
DTRACE_PRINT("WM: checking for _WIN_SUPPORTING ... ");
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
{
unsigned long nproto;
unsigned long i;
return False;
}
for (i = 0; i < nproto; ++i) {
break;
}
}
}
return found;
}
static Boolean
{
if (checked) {
return supported;
}
if (awt_wm_isNetSupporting()) {
DTRACE_PRINT("WM: checking for _NET_WM_STATE in _NET_SUPPORTED ... ");
}
return supported;
}
static Boolean
{
if (checked) {
return supported;
}
if (awt_wm_isWinSupporting()) {
DTRACE_PRINT("WM: checking for _WIN_STATE in _WIN_PROTOCOLS ... ");
}
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
{
/* Property value*/
/* Request status */
int status;
/* Returns of XGetWindowProperty */
int actual_format;
unsigned long nitems;
unsigned long bytes_after;
unsigned char *data;
return False;
}
/* BadWindow is ok and will be blocked by our special handler */
"()Lsun/awt/X11/XErrorHandler$IgnoreBadWindowHandler;", JNI_FALSE,
&data));
DTRACE_PRINTLN("no ENLIGHTENMENT_COMMS");
return None;
}
{
DTRACE_PRINTLN("malformed ENLIGHTENMENT_COMMS");
return None;
}
return value;
}
/*
* Is Enlightenment WM running? Congruent to awt_wm_checkAnchor, but
* uses STRING property peculiar to Enlightenment.
*/
static Boolean
awt_wm_isEnlightenment(void)
{
DTRACE_PRINT("WM: checking for Enlightenment ... ");
return False;
}
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)
{
/* Property value*/
/* Request status */
int status;
/* Returns of XGetWindowProperty */
int actual_format;
unsigned long nitems;
unsigned long bytes_after;
DTRACE_PRINT("WM: checking for CDE ... ");
return False;
}
(unsigned char **)&data);
DTRACE_PRINTLN("no _DT_SM_WINDOW_INFO on root");
return False;
}
{
DTRACE_PRINTLN("malformed _DT_SM_WINDOW_INFO on root");
return False;
}
/* Now check that this window has _DT_SM_STATE_INFO (ignore contents) */
return False;
}
/* BadWindow is ok and will be blocked by our special handler */
"()Lsun/awt/X11/XErrorHandler$IgnoreBadWindowHandler;", JNI_FALSE,
(unsigned char **)&data));
DTRACE_PRINTLN("no _DT_SM_STATE_INFO");
return False;
}
DTRACE_PRINTLN("malformed _DT_SM_STATE_INFO");
return False;
}
DTRACE_PRINTLN("yes");
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...
*/
/* Property value */
/* Request status */
int status;
/* Returns of XGetWindowProperty */
int actual_format;
unsigned long nitems;
unsigned long bytes_after;
DTRACE_PRINT("WM: checking for MWM ... ");
{
return False;
}
(unsigned char **)&data);
DTRACE_PRINTLN("no _MOTIF_WM_INFO on root");
return False;
}
{
DTRACE_PRINTLN("malformed _MOTIF_WM_INFO on root");
return False;
}
/* NB: 64 bit: Cannot cast data to MotifWmInfo */
/* Now check that this window has _DT_WORKSPACE_CURRENT */
DTRACE_PRINTLN("no _DT_WORKSPACE_CURRENT");
return False;
}
DTRACE_PRINTLN("yes");
return True;
}
static Boolean
{
unsigned char *net_wm_name;
return False;
}
/*
* 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...).
*/
if (net_wm_name == NULL) {
}
if (net_wm_name == NULL) {
DTRACE_PRINTLN("no (missing _NET_WM_NAME)");
return False;
}
if (matched) {
DTRACE_PRINTLN("yes");
} else {
}
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");
}
/*
* 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)
{
/*
* 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'
};
unsigned char xerror_code;
DTRACE_PRINT("WM: scheduling check for IceWM ... ");
return False;
}
"()Lsun/awt/X11/XErrorHandler$VerifyChangePropertyHandler;", JNI_FALSE,
if (xerror_code != Success) {
DTRACE_PRINTLN1("can't set _ICEWM_WINOPTHINT, error = %d",
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)
{
/* Request status */
int status;
/* Returns of XGetWindowProperty */
int actual_format;
unsigned long nitems;
unsigned long bytes_after;
unsigned char *data;
DTRACE_PRINT("WM: checking for IceWM ... ");
return False;
}
&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)
{
DTRACE_PRINT("WM: checking for OpenLook WM ... ");
return False;
}
DTRACE_PRINTLN("no _SUN_WM_PROTOCOLS on root");
return False;
}
DTRACE_PRINTLN("yes");
return True;
}
/*
* 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.
*/
const char *vendor_string;
if (awt_wmgr != UNDETERMINED_WM) {
return awt_wmgr;
}
/*
* Quick checks for specific servers.
*/
/*
* 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");
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.
*/
DTRACE_PRINT("WM: trying SubstructureRedirect ... ");
"()Lsun/awt/X11/XErrorHandler$XChangeWindowAttributesHandler;", JNI_TRUE,
CWEventMask, &substruct));
/*
* If no WM is running than our selection for SubstructureRedirect
* succeeded and needs to be undone (hey we are *not* a WM ;-).
*/
if (errorOccurredFlag == JNI_FALSE) {
DTRACE_PRINTLN("no WM is running");
substruct.event_mask = 0;
CWEventMask, &substruct);
return NO_WM;
}
/* actual check for IceWM to follow below */
if (awt_wm_isNetSupporting()) {
}
if (awt_wm_isWinSupporting()) {
}
/*
* Ok, some WM is out there. Check which one by testing for
* "distinguishing" atoms.
*/
if (doIsIceWM && awt_wm_isIceWM()) {
}
else if (awt_wm_isEnlightenment()) {
}
else if (awt_wm_isMetacity()) {
}
else if (awt_wm_isSawfish()) {
}
else if (awt_wm_isKDE2()) {
}
/*
* 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)");
}
else if (awt_wm_isWinSupporting()) {
DTRACE_PRINTLN("WM: other WM (supports _WIN)");
}
/*
* Check for legacy WMs.
*/
else if (awt_wm_isCDE()) { /* XXX: must come before isMotif */
}
else if (awt_wm_isMotif()) {
}
else if (awt_wm_isOpenLook()) {
}
else {
DTRACE_PRINTLN("WM: some other legacy 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().
*/
{
static int env_buggy = 0;
if (env_not_checked) {
DTRACE_PRINT("WM: checking for _JAVA_AWT_WM_STATIC_GRAVITY in environment ... ");
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.
*
*/
{
switch (state) {
/*
* unidirectional maximization.
*/
if (awt_wm_getRunningWM() == METACITY_WM) {
/* "This is a deliberate policy decision." -hp */
return JNI_FALSE;
}
/* FALLTROUGH */
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
{
long ignore = 0;
DTRACE_PRINTLN("WM: removeSizeHints FAILED to allocate XSizeHints");
return;
}
/* sanitize the mask, only do these hints */
return;
}
#ifdef DEBUG
DTRACE_PRINT("WM: removing hints");
DTRACE_PRINT(" Max = ");
} else {
DTRACE_PRINT("none;");
}
}
DTRACE_PRINT(" Min = ");
} else {
DTRACE_PRINT("none;");
}
}
DTRACE_PRINTLN("");
#endif
}
/*
*
*
*/
static void
{
/* For now just */ return;
}
/* it's here already */
return;
}
}
/*
* 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
{
int d;
if (!(decorations & MWM_DECOR_ALL))
return decorations; /* already normalized */
d &= ~decorations;
return d;
}
/*
* Infer OL properties from MWM decorations.
* Use _OL_DECOR_DEL(ATOM[]) to remove unwanted ones.
*/
static void
{
int nitems;
DTRACE_PRINTLN("WM: setOLDecor - no window, returning");
return;
}
DTRACE_PRINT("WM: _OL_DECOR_DEL = {");
nitems = 0;
if (!(decorations & MWM_DECOR_TITLE)) {
DTRACE_PRINT(" _OL_DECOR_HEADER");
}
DTRACE_PRINT(" _OL_DECOR_RESIZE");
}
| MWM_DECOR_MINIMIZE)))
{
DTRACE_PRINT(" _OL_DECOR_CLOSE");
}
DTRACE_PRINT(" }");
if (nitems == 0) {
DTRACE_PRINTLN(" ... removing");
}
else {
DTRACE_PRINTLN(" ... setting");
}
}
/*
* Set MWM decorations. Infer MWM functions from decorations.
*/
static void
{
int functions;
/* Apparently some WMs don't implement MWM_*_ALL semantic correctly */
DTRACE_PRINTLN1("WM: setMotifDecor normalize exclusions, decor = 0x%X",
}
DTRACE_PRINT("WM: setMotifDecor functions = {");
functions = 0;
if (decorations & MWM_DECOR_ALL) {
DTRACE_PRINT(" 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");
if (resizable) {
DTRACE_PRINT(" RESIZE MAXIMIZE");
}
}
DTRACE_PRINTLN(" }");
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
* 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
{
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
{
DTRACE_PRINTLN3("WM: setShellDecor(0x%x/0x%x, %s)",
if (!resizable) {
if (decorations & MWM_DECOR_ALL) {
}
else {
}
}
/* Some WMs need remap to redecorate the window */
/*
* 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).
*/
DTRACE_PRINT("WM: setShellDecor REMAPPING ... ");
DTRACE_PRINTLN("done");
}
}
/*
* Make specified shell resizable.
*/
void
{
DTRACE_PRINTLN2("WM: setShellResizable(0x%x/0x%x)",
NULL);
/* REMINDER: will need to revisit when setExtendedStateBounds is added */
/* Restore decorations */
}
/*
* Make specified shell non-resizable.
* If justChangeSize is false, update decorations as well.
*/
void
{
DTRACE_PRINTLN5("WM: setShellNotResizable(0x%x/0x%x, %d, %d, %s)",
NULL);
}
if (!justChangeSize) { /* update decorations */
}
}
/*
* Helper function for awt_wm_getInsetsFromProp.
* Read property of type CARDINAL[4] = { left, right, top, bottom }
*/
static Boolean
{
/* Request status */
int status;
/* Returns of XGetWindowProperty */
int actual_format;
unsigned long nitems;
unsigned long bytes_after;
(unsigned char **)&insets);
DTRACE_PRINTLN("failed");
return False;
}
DTRACE_PRINTLN("type/format mismatch");
return False;
}
/* Order is that of java.awt.Insets.toString */
DTRACE_PRINTLN4("[top=%d,left=%d,bottom=%d,right=%d]",
return True;
}
/*
* If WM implements the insets property - fill insets with values
* specified in that property.
*/
{
switch (awt_wm_getRunningWM()) {
case ENLIGHTEN_WM:
DTRACE_PRINT("WM: reading _E_FRAME_SIZE ... ");
#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 ... ");
#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
{
/* Request status */
int status;
/* Returns of XGetWindowProperty */
int actual_format;
unsigned long nitems;
unsigned long bytes_after;
int wm_state;
(unsigned char **)&data);
return WithdrawnState;
}
if (actual_type != XA_WM_STATE) {
return WithdrawnState;
}
return wm_state;
}
/*****************************************************************************\
*
* Reading state from properties WM puts on our window ...
*
\*****************************************************************************/
/*
* New "NET" WM spec: _NET_WM_STATE/Atom[]
*/
static jint
{
unsigned long nitems;
unsigned long i;
if (nitems == 0) {
DTRACE_PRINTLN("WM: _NET_WM_STATE = { }");
if (net_wm_state) {
}
return java_awt_Frame_NORMAL;
}
#ifdef DEBUG
DTRACE_PRINT("WM: ");
#endif
for (i = 0; i < nitems; ++i) {
if (net_wm_state[i] == _XA_NET_WM_STATE_MAXIMIZED_VERT) {
}
else if (net_wm_state[i] == _XA_NET_WM_STATE_MAXIMIZED_HORZ) {
}
}
return java_state;
}
{
unsigned long nitems;
unsigned long i;
if (nitems == 0) {
DTRACE_PRINTLN("WM: _NET_WM_STATE = { }");
if (net_wm_state) {
}
return False;
}
#ifdef DEBUG
DTRACE_PRINT("WM: ");
#endif
for (i = 0; i < nitems; ++i) {
if (net_wm_state[i] == _XA_NET_WM_STATE_HIDDEN) {
}
}
return result;
}
/*
* Similar code to getStateNet, to get layer state.
*/
static int
{
int java_state;
unsigned long nitems;
unsigned long i;
if (nitems == 0) {
DTRACE_PRINTLN("WM: _NET_WM_STATE = { }");
if (net_wm_state) {
}
return LAYER_NORMAL;
}
#ifdef DEBUG
DTRACE_PRINT("WM: ");
#endif
for (i = 0; i < nitems; ++i) {
if (net_wm_state[i] == _XA_NET_WM_STATE_ABOVE) {
}
}
return java_state;
}
/*
*/
static jint
{
long win_state;
#ifdef DEBUG
DTRACE_PRINT("WM: ");
#endif
if (win_state & WIN_STATE_MAXIMIZED_VERT) {
}
if (win_state & WIN_STATE_MAXIMIZED_HORIZ) {
}
return java_state;
}
/*
* Code similar to getStateWin, to get layer state.
*/
static int
{
long win_state;
#ifdef DEBUG
DTRACE_PRINT("WM: ");
#endif
if (win_state == WIN_LAYER_ONTOP) {
}
return java_state;
}
static jint
{
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;
}
}
{
DTRACE_PRINTLN2("WM: getState(0x%x/0x%x)",
DTRACE_PRINTLN("WM: no window, use wdata");
}
else {
if (wm_state == WithdrawnState) {
DTRACE_PRINTLN("WM: window withdrawn, use wdata");
}
else {
#ifdef DEBUG
DTRACE_PRINT("WM: ");
#endif
if (wm_state == IconicState) {
} else {
}
}
}
#ifdef DEBUG
DTRACE_PRINT("WM: ");
#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.
*/
{
int wm_state;
return False;
}
if (wm_state == WithdrawnState) {
return False;
}
if (e->atom == XA_WM_STATE) {
}
else if (e->atom == _XA_NET_WM_STATE) {
}
else if (e->atom == _XA_WIN_STATE) {
}
if (is_state_change) {
#ifdef DEBUG
DTRACE_PRINTLN4("WM: PropertyNotify(0x%x/0x%x) %s %s",
}
DTRACE_PRINT("WM: ");
#endif
if (wm_state == IconicState) {
} else {
}
#ifdef DEBUG
DTRACE_PRINT("WM: ");
#endif
}
return is_state_change;
}
/*****************************************************************************\
*
*
\*****************************************************************************/
/*
* Request a state transition from a _NET supporting WM by sending
* _NET_WM_STATE ClientMessage to root window.
*/
static void
{
/* must use awt_wm_setInitialStateNet for withdrawn windows */
/*
* We have to use toggle for maximization because of transitions
* from maximization in one direction only to maximization in the
* other direction only.
*/
switch (max_changed) {
case 0:
DTRACE_PRINTLN("WM: requestStateNet - maximization unchanged");
return;
DTRACE_PRINTLN("WM: requestStateNet - toggling MAX_HORZ");
break;
DTRACE_PRINTLN("WM: requestStateNet - toggling MAX_VERT");
break;
default: /* both */
DTRACE_PRINTLN("WM: requestStateNet - toggling HORZ + VERT");
break;
}
}
/*
* Request state transition from a Gnome WM (_WIN protocol) by sending
* _WIN_STATE ClientMessage to root window.
*/
static void
{
/* must use awt_wm_setInitialStateWin for withdrawn windows */
win_state = 0;
if (state & java_awt_Frame_MAXIMIZED_VERT) {
}
if (state & java_awt_Frame_MAXIMIZED_HORIZ) {
}
}
/*
* 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
{
unsigned long nitems;
/* must use awt_wm_requestStateNet for managed windows */
/* Be careful to not wipe out state bits we don't understand */
if (nitems == 0) {
/*
* Empty or absent _NET_WM_STATE - set a new one if necessary.
*/
}
if (state & java_awt_Frame_MAXIMIZED_VERT) {
}
if (state & java_awt_Frame_MAXIMIZED_HORIZ) {
}
if (nitems == 0) {
DTRACE_PRINTLN("WM: initial _NET_WM_STATE not necessary");
return;
}
#ifdef DEBUG
DTRACE_PRINT("WM: setting initial ");
#endif
(unsigned char *)net_wm_state, nitems);
}
else {
/*
* Tweak existing _NET_WM_STATE, preserving bits we don't use.
*/
int new_nitems;
unsigned long i;
#ifdef DEBUG
DTRACE_PRINT("WM: already has ");
#endif
for (i = 0; i < nitems; ++i) {
if (old_state[i] == _XA_NET_WM_STATE_MAXIMIZED_HORZ) {
}
else if (old_state[i] == _XA_NET_WM_STATE_MAXIMIZED_VERT) {
}
}
DTRACE_PRINTLN("WM: no changes to _NET_WM_STATE necessary");
return;
}
new_nitems = 0;
if (has == 0) { /* only adding flags */
}
else {
}
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;
}
}
}
}
/* Add missing flags */
if ((want & java_awt_Frame_MAXIMIZED_HORIZ)
&& !(has & java_awt_Frame_MAXIMIZED_HORIZ))
{
DTRACE_PRINT(" add _HORZ");
++new_nitems;
}
if ((want & java_awt_Frame_MAXIMIZED_VERT)
&& !(has & java_awt_Frame_MAXIMIZED_VERT))
{
DTRACE_PRINT(" add _VERT");
++new_nitems;
}
" ... replacing" : " ... appending");
(unsigned char *)new_state, new_nitems);
}
}
/*
* 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
{
/* must use awt_wm_requestStateWin for managed windows */
/* Be careful to not wipe out state bits we don't understand */
#ifdef DEBUG
if (win_state != 0) {
DTRACE_PRINT("WM: already has ");
}
#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) {
} else {
}
if (state & java_awt_Frame_MAXIMIZED_VERT) {
} else {
}
if (state & java_awt_Frame_MAXIMIZED_HORIZ) {
} else {
}
if (old_win_state ^ win_state) {
#ifdef DEBUG
DTRACE_PRINT("WM: setting initial ");
#endif
(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
{
int currentLayer;
long cmd;
/* must use awt_wm_setInitialLayerNet for withdrawn windows */
if(state == currentLayer) {
return;
}
}
/*
* Request a layer change from a Gnome WM (_WIN protocol) by sending
* _WIN_LAYER ClientMessage to root window.
*/
static void
{
/* must use awt_wm_setInitialLayerWin for withdrawn windows */
/*(SubstructureRedirectMask |*/
}
/*
* 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
{
unsigned long nitems;
/* must use awt_wm_requestLayerNet for managed windows */
/* Be careful to not wipe out state bits we don't understand */
}
return;
/* create new state */
}
nitems = 1;
data[1] = 0;
}else { /* nitems > 0 */
unsigned long i;
int mode;
for(i = 0; i < nitems; i++) {
if( bShift ) {
}else if( old_state[i] == _XA_NET_WM_STATE_ABOVE ) {
if(state == LAYER_ALWAYS_ON_TOP) {
/* no change necessary */
return;
}else{
/* wipe off this atom */
}
}
}
if( bShift ) {
/* atom was found and removed: change property */
nitems--;
}else if( state != LAYER_ALWAYS_ON_TOP ) {
/* atom was not found and not needed */
return;
}else {
/* must add new atom */
nitems = 1;
}
mode == PropModeAppend ?
(unsigned char *)(&new_state) :
}
}
/*
* 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
{
int currentLayer;
/* must use awt_wm_requestLayerWin for managed windows */
if( currentLayer == state ) {
/* no change necessary */
return;
}
if( state == LAYER_ALWAYS_ON_TOP ) {
}else {
}
(unsigned char *)&win_state, 1);
}
void
{
#ifdef DEBUG
DTRACE_PRINT2("WM: setExtendedState(0x%x/0x%x) ",
#endif
/*
* If the window is managed by WM, we should send
* ClientMessage requests.
*/
if (awt_wm_doStateProtocolNet()) {
}
else if (awt_wm_doStateProtocolWin()) {
}
}
else {
/*
* If the window is withdrawn we should set necessary
* properties directly to the window before mapping it.
*/
if (awt_wm_doStateProtocolNet()) {
}
else if (awt_wm_doStateProtocolWin()) {
}
#if 1
/*
* Purge KWM bits.
* Not really tested with KWM, only with WindowMaker.
*/
#endif /* 1 */
}
}
static Boolean
/*
In fact, WM may report this not supported but do support.
*/
return supported;
}
static Boolean
/*
* In fact, WM may report this supported but do not support.
*/
return supported;
}
void
/**
We don't believe anyone, and now send both ClientMessage requests.
And eg Metacity under RH 6.1 required both to work.
**/
} else {
/**
We don't believe anyone, and now set both atoms.
And eg Metacity under RH 6.1 required both to work.
**/
}
}
/*
* Work around for 4775545. _NET version.
*/
static void
{
unsigned long nitems;
unsigned long i;
unsigned char xerror_code;
if (nitems == 0) {
DTRACE_PRINTLN("WM: _NET_WM_STATE = { }");
if (net_wm_state) {
}
return;
}
#ifdef DEBUG
DTRACE_PRINT("WM: ");
#endif
for (i = 0; i < nitems; ++i) {
if (net_wm_state[i] == _XA_NET_WM_STATE_SHADED) {
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 */
++i;
}
--nitems; /* _SHADED has been removed */
#ifdef DEBUG
DTRACE_PRINT("WM: ");
#endif
"()Lsun/awt/X11/XErrorHandler$VerifyChangePropertyHandler;", JNI_FALSE,
(unsigned char *)net_wm_state, nitems));
if (xerror_code != Success) {
DTRACE_PRINTLN1("WM: XChangeProperty failed, error = %d",
}
}
/*
* Work around for 4775545. _WIN version.
*/
static void
{
long win_state;
#ifdef DEBUG
DTRACE_PRINT("WM: ");
#endif
if ((win_state & WIN_STATE_SHADED) == 0) {
DTRACE_PRINTLN("WM: not _SHADED, no workaround necessary");
return;
}
(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
{
DTRACE_PRINTLN("WM: unshade kludge");
if (awt_wm_doStateProtocolNet()) {
}
else if (awt_wm_doStateProtocolWin()) {
}
#ifdef DEBUG
else {
DTRACE_PRINTLN("WM: not a _NET or _WIN supporting WM");
}
#endif
}
void
awt_wm_init(void)
{
if (inited) {
return;
}
}
return awt_wm_supportsLayersNet() || awt_wm_supportsLayersWin();
}