|
Java example source code file (XWM.java)
The XWM.java Java example source code
/*
* Copyright (c) 2003, 2013, 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.
*/
/**
* Ported from awt_wm.c, SCCS v1.11, author Valeriy Ushakov
* Author: Denis Mikhalkin
*/
package sun.awt.X11;
import sun.awt.IconInfo;
import sun.misc.Unsafe;
import java.awt.Insets;
import java.awt.Frame;
import java.awt.Rectangle;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import sun.util.logging.PlatformLogger;
/**
* Class incapsulating knowledge about window managers in general
* Descendants should provide some information about specific window manager.
*/
final class XWM
{
private final static PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XWM");
private final static PlatformLogger insLog = PlatformLogger.getLogger("sun.awt.X11.insets.XWM");
private final static PlatformLogger stateLog = PlatformLogger.getLogger("sun.awt.X11.states.XWM");
static final XAtom XA_MWM_HINTS = new XAtom();
private static Unsafe unsafe = XlibWrapper.unsafe;
/* Good old ICCCM */
static XAtom XA_WM_STATE = new XAtom();
XAtom XA_UTF8_STRING = XAtom.get("UTF8_STRING"); /* like STRING but encoding is UTF-8 */
/* Currently we only care about max_v and max_h in _NET_WM_STATE */
final static int AWT_NET_N_KNOWN_STATES=2;
/* Enlightenment */
final static XAtom XA_E_FRAME_SIZE = new XAtom();
/* KWin (KDE2) */
final static XAtom XA_KDE_NET_WM_FRAME_STRUT = new XAtom();
/* KWM (KDE 1.x) OBSOLETE??? */
final static XAtom XA_KWM_WIN_ICONIFIED = new XAtom();
final static XAtom XA_KWM_WIN_MAXIMIZED = new XAtom();
/* OpenLook */
final static XAtom XA_OL_DECOR_DEL = new XAtom();
final static XAtom XA_OL_DECOR_HEADER = new XAtom();
final static XAtom XA_OL_DECOR_RESIZE = new XAtom();
final static XAtom XA_OL_DECOR_PIN = new XAtom();
final static XAtom XA_OL_DECOR_CLOSE = new XAtom();
/* EWMH */
final static XAtom XA_NET_FRAME_EXTENTS = new XAtom();
final static XAtom XA_NET_REQUEST_FRAME_EXTENTS = new XAtom();
final static int
UNDETERMINED_WM = 1,
NO_WM = 2,
OTHER_WM = 3,
OPENLOOK_WM = 4,
MOTIF_WM = 5,
CDE_WM = 6,
ENLIGHTEN_WM = 7,
KDE2_WM = 8,
SAWFISH_WM = 9,
ICE_WM = 10,
METACITY_WM = 11,
COMPIZ_WM = 12,
LG3D_WM = 13,
CWM_WM = 14,
MUTTER_WM = 15;
public String toString() {
switch (WMID) {
case NO_WM:
return "NO WM";
case OTHER_WM:
return "Other WM";
case OPENLOOK_WM:
return "OPENLOOK";
case MOTIF_WM:
return "MWM";
case CDE_WM:
return "DTWM";
case ENLIGHTEN_WM:
return "Enlightenment";
case KDE2_WM:
return "KWM2";
case SAWFISH_WM:
return "Sawfish";
case ICE_WM:
return "IceWM";
case METACITY_WM:
return "Metacity";
case COMPIZ_WM:
return "Compiz";
case LG3D_WM:
return "LookingGlass";
case CWM_WM:
return "CWM";
case MUTTER_WM:
return "Mutter";
case UNDETERMINED_WM:
default:
return "Undetermined WM";
}
}
int WMID;
static final Insets zeroInsets = new Insets(0, 0, 0, 0);
static final Insets defaultInsets = new Insets(25, 5, 5, 5);
XWM(int WMID) {
this.WMID = WMID;
initializeProtocols();
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("Window manager: " + toString());
}
}
int getID() {
return WMID;
}
static Insets normalize(Insets insets) {
if (insets.top > 64 || insets.top < 0) {
insets.top = 28;
}
if (insets.left > 32 || insets.left < 0) {
insets.left = 6;
}
if (insets.right > 32 || insets.right < 0) {
insets.right = 6;
}
if (insets.bottom > 32 || insets.bottom < 0) {
insets.bottom = 6;
}
return insets;
}
static XNETProtocol g_net_protocol = null;
static XWINProtocol g_win_protocol = null;
static boolean isNetWMName(String name) {
if (g_net_protocol != null) {
return g_net_protocol.isWMName(name);
} else {
return false;
}
}
static void initAtoms() {
final Object[][] atomInitList ={
{ XA_WM_STATE, "WM_STATE" },
{ 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" },
{ XA_MWM_HINTS, "_MOTIF_WM_HINTS" },
{ XA_NET_FRAME_EXTENTS, "_NET_FRAME_EXTENTS" },
{ XA_NET_REQUEST_FRAME_EXTENTS, "_NET_REQUEST_FRAME_EXTENTS" },
};
String[] names = new String[atomInitList.length];
for (int index = 0; index < names.length; index++) {
names[index] = (String)atomInitList[index][1];
}
int atomSize = XAtom.getAtomSize();
long atoms = unsafe.allocateMemory(names.length*atomSize);
XToolkit.awtLock();
try {
int status = XlibWrapper.XInternAtoms(XToolkit.getDisplay(), names, false, atoms);
if (status == 0) {
return;
}
for (int atom = 0, atomPtr = 0; atom < names.length; atom++, atomPtr += atomSize) {
((XAtom)(atomInitList[atom][0])).setValues(XToolkit.getDisplay(), names[atom], XAtom.getAtom(atoms + atomPtr));
}
} finally {
XToolkit.awtUnlock();
unsafe.freeMemory(atoms);
}
}
/*
* MUST BE CALLED UNDER AWTLOCK.
*
* If *any* window manager is running?
*
* According to ICCCM 2.0 section 4.3.
* WM will acquire ownership of a selection named WM_Sn, where n is
* the screen number.
*
* No selection owner, but, perhaps it is not ICCCM compliant WM
* (e.g. CDE/Sawfish).
* Try selecting for SubstructureRedirect, that only one client
* can select for, and if the request fails, than some other WM is
* already running.
*
* We also treat eXcursion as NO_WM.
*/
private static boolean isNoWM() {
/*
* Quick checks for specific servers.
*/
String vendor_string = XlibWrapper.ServerVendor(XToolkit.getDisplay());
if (vendor_string.indexOf("eXcursion") != -1) {
/*
* 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.
*/
if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
insLog.finer("eXcursion means NO_WM");
}
return true;
}
XSetWindowAttributes substruct = new XSetWindowAttributes();
try {
/*
* Let's check an owner of WM_Sn selection for the default screen.
*/
final long default_screen_number =
XlibWrapper.DefaultScreen(XToolkit.getDisplay());
final String selection_name = "WM_S" + default_screen_number;
long selection_owner =
XlibWrapper.XGetSelectionOwner(XToolkit.getDisplay(),
XAtom.get(selection_name).getAtom());
if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
insLog.finer("selection owner of " + selection_name
+ " is " + selection_owner);
}
if (selection_owner != XConstants.None) {
return false;
}
winmgr_running = false;
substruct.set_event_mask(XConstants.SubstructureRedirectMask);
XErrorHandlerUtil.WITH_XERROR_HANDLER(detectWMHandler);
XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),
XToolkit.getDefaultRootWindow(),
XConstants.CWEventMask,
substruct.pData);
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
/*
* If no WM is running then our selection for SubstructureRedirect
* succeeded and needs to be undone (hey we are *not* a WM ;-).
*/
if (!winmgr_running) {
substruct.set_event_mask(0);
XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),
XToolkit.getDefaultRootWindow(),
XConstants.CWEventMask,
substruct.pData);
if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
insLog.finer("It looks like there is no WM thus NO_WM");
}
}
return !winmgr_running;
} finally {
substruct.dispose();
}
}
static XAtom XA_ENLIGHTENMENT_COMMS = new XAtom("ENLIGHTENMENT_COMMS", false);
/*
* Helper function for 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 long getECommsWindowIDProperty(long window) {
if (!XA_ENLIGHTENMENT_COMMS.isInterned()) {
return 0;
}
WindowPropertyGetter getter =
new WindowPropertyGetter(window, XA_ENLIGHTENMENT_COMMS, 0, 14, false,
XAtom.XA_STRING);
try {
int status = getter.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
if (status != XConstants.Success || getter.getData() == 0) {
return 0;
}
if (getter.getActualType() != XAtom.XA_STRING
|| getter.getActualFormat() != 8
|| getter.getNumberOfItems() != 14 || getter.getBytesAfter() != 0)
{
return 0;
}
// Convert data to String, ASCII
byte[] bytes = XlibWrapper.getStringBytes(getter.getData());
String id = new String(bytes);
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("ENLIGHTENMENT_COMMS is " + id);
}
// Parse WINID
Pattern winIdPat = Pattern.compile("WINID\\s+(\\p{XDigit}{0,8})");
try {
Matcher match = winIdPat.matcher(id);
if (match.matches()) {
if (log.isLoggable(PlatformLogger.Level.FINEST)) {
log.finest("Match group count: " + match.groupCount());
}
String longId = match.group(1);
if (log.isLoggable(PlatformLogger.Level.FINEST)) {
log.finest("Match group 1 " + longId);
}
long winid = Long.parseLong(longId, 16);
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("Enlightenment communication window " + winid);
}
return winid;
} else {
log.finer("ENLIGHTENMENT_COMMS has wrong format");
return 0;
}
} catch (Exception e) {
if (log.isLoggable(PlatformLogger.Level.FINER)) {
e.printStackTrace();
}
return 0;
}
} finally {
getter.dispose();
}
}
/*
* Is Enlightenment WM running? Congruent to awt_wm_checkAnchor, but
* uses STRING property peculiar to Enlightenment.
*/
static boolean isEnlightenment() {
long root_xref = getECommsWindowIDProperty(XToolkit.getDefaultRootWindow());
if (root_xref == 0) {
return false;
}
long self_xref = getECommsWindowIDProperty(root_xref);
if (self_xref != root_xref) {
return false;
}
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 final XAtom XA_DT_SM_WINDOW_INFO = new XAtom("_DT_SM_WINDOW_INFO", false);
static final XAtom XA_DT_SM_STATE_INFO = new XAtom("_DT_SM_STATE_INFO", false);
static boolean isCDE() {
if (!XA_DT_SM_WINDOW_INFO.isInterned()) {
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("{0} is not interned", XA_DT_SM_WINDOW_INFO);
}
return false;
}
WindowPropertyGetter getter =
new WindowPropertyGetter(XToolkit.getDefaultRootWindow(),
XA_DT_SM_WINDOW_INFO, 0, 2,
false, XA_DT_SM_WINDOW_INFO);
try {
int status = getter.execute();
if (status != XConstants.Success || getter.getData() == 0) {
log.finer("Getting of _DT_SM_WINDOW_INFO is not successfull");
return false;
}
if (getter.getActualType() != XA_DT_SM_WINDOW_INFO.getAtom()
|| getter.getActualFormat() != 32
|| getter.getNumberOfItems() != 2 || getter.getBytesAfter() != 0)
{
log.finer("Wrong format of _DT_SM_WINDOW_INFO");
return false;
}
long wmwin = Native.getWindow(getter.getData(), 1); //unsafe.getInt(getter.getData()+4);
if (wmwin == 0) {
log.fine("WARNING: DT_SM_WINDOW_INFO exists but returns zero windows");
return false;
}
/* Now check that this window has _DT_SM_STATE_INFO (ignore contents) */
if (!XA_DT_SM_STATE_INFO.isInterned()) {
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("{0} is not interned", XA_DT_SM_STATE_INFO);
}
return false;
}
WindowPropertyGetter getter2 =
new WindowPropertyGetter(wmwin, XA_DT_SM_STATE_INFO, 0, 1,
false, XA_DT_SM_STATE_INFO);
try {
status = getter2.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
if (status != XConstants.Success || getter2.getData() == 0) {
log.finer("Getting of _DT_SM_STATE_INFO is not successfull");
return false;
}
if (getter2.getActualType() != XA_DT_SM_STATE_INFO.getAtom()
|| getter2.getActualFormat() != 32)
{
log.finer("Wrong format of _DT_SM_STATE_INFO");
return false;
}
return true;
} finally {
getter2.dispose();
}
} finally {
getter.dispose();
}
}
/*
* 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 final XAtom XA_MOTIF_WM_INFO = new XAtom("_MOTIF_WM_INFO", false);
static final XAtom XA_DT_WORKSPACE_CURRENT = new XAtom("_DT_WORKSPACE_CURRENT", false);
static boolean isMotif() {
if (!(XA_MOTIF_WM_INFO.isInterned()/* && XA_DT_WORKSPACE_CURRENT.isInterned()*/) ) {
return false;
}
WindowPropertyGetter getter =
new WindowPropertyGetter(XToolkit.getDefaultRootWindow(),
XA_MOTIF_WM_INFO, 0,
MWMConstants.PROP_MOTIF_WM_INFO_ELEMENTS,
false, XA_MOTIF_WM_INFO);
try {
int status = getter.execute();
if (status != XConstants.Success || getter.getData() == 0) {
return false;
}
if (getter.getActualType() != XA_MOTIF_WM_INFO.getAtom()
|| getter.getActualFormat() != 32
|| getter.getNumberOfItems() != MWMConstants.PROP_MOTIF_WM_INFO_ELEMENTS
|| getter.getBytesAfter() != 0)
{
return false;
}
long wmwin = Native.getLong(getter.getData(), 1);
if (wmwin != 0) {
if (XA_DT_WORKSPACE_CURRENT.isInterned()) {
/* Now check that this window has _DT_WORKSPACE_CURRENT */
XAtom[] curws = XA_DT_WORKSPACE_CURRENT.getAtomListProperty(wmwin);
if (curws.length == 0) {
return false;
}
return true;
} else {
// No DT_WORKSPACE, however in our tests MWM sometimes can be without desktop -
// and that is still MWM. So simply check for the validity of this window
// (through WM_STATE property).
WindowPropertyGetter state_getter =
new WindowPropertyGetter(wmwin,
XA_WM_STATE,
0, 1, false,
XA_WM_STATE);
try {
if (state_getter.execute() == XConstants.Success &&
state_getter.getData() != 0 &&
state_getter.getActualType() == XA_WM_STATE.getAtom())
{
return true;
}
} finally {
state_getter.dispose();
}
}
}
} finally {
getter.dispose();
}
return false;
}
/*
* Is Sawfish running?
*/
static boolean isSawfish() {
return isNetWMName("Sawfish");
}
/*
* Is KDE2 (KWin) running?
*/
static boolean isKDE2() {
return isNetWMName("KWin");
}
static boolean isCompiz() {
return isNetWMName("compiz");
}
static boolean isLookingGlass() {
return isNetWMName("LG3D");
}
static boolean isCWM() {
return isNetWMName("CWM");
}
/*
* Is Metacity running?
*/
static boolean isMetacity() {
return isNetWMName("Metacity");
// || (
// XA_NET_SUPPORTING_WM_CHECK.
// getIntProperty(XToolkit.getDefaultRootWindow(), XA_NET_SUPPORTING_WM_CHECK.
// getIntProperty(XToolkit.getDefaultRootWindow(), XAtom.XA_CARDINAL)) == 0);
}
static boolean isMutter() {
return isNetWMName("Mutter") || isNetWMName("GNOME Shell");
}
static boolean isNonReparentingWM() {
return (XWM.getWMID() == XWM.COMPIZ_WM || XWM.getWMID() == XWM.LG3D_WM || XWM.getWMID() == XWM.CWM_WM);
}
/*
* 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 final XAtom XA_ICEWM_WINOPTHINT = new XAtom("_ICEWM_WINOPTHINT", false);
static final 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'
};
static boolean prepareIsIceWM() {
/*
* Choose something innocuous: "AWT_ICEWM_TEST allWorkspaces 0".
* IceWM expects "class\0option\0arg\0" with zero bytes as delimiters.
*/
if (!XA_ICEWM_WINOPTHINT.isInterned()) {
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("{0} is not interned", XA_ICEWM_WINOPTHINT);
}
return false;
}
XToolkit.awtLock();
try {
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
XlibWrapper.XChangePropertyS(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(),
XA_ICEWM_WINOPTHINT.getAtom(),
XA_ICEWM_WINOPTHINT.getAtom(),
8, XConstants.PropModeReplace,
new String(opt));
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
if ((XErrorHandlerUtil.saved_error != null) &&
(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
log.finer("Erorr getting XA_ICEWM_WINOPTHINT property");
return false;
}
log.finer("Prepared for IceWM detection");
return true;
} finally {
XToolkit.awtUnlock();
}
}
/*
* Is IceWM running?
*
* Note well: Only call this if awt_wm_prepareIsIceWM succeeded, or a
* false positive will be reported.
*/
static boolean isIceWM() {
if (!XA_ICEWM_WINOPTHINT.isInterned()) {
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("{0} is not interned", XA_ICEWM_WINOPTHINT);
}
return false;
}
WindowPropertyGetter getter =
new WindowPropertyGetter(XToolkit.getDefaultRootWindow(),
XA_ICEWM_WINOPTHINT, 0, 0xFFFF,
true, XA_ICEWM_WINOPTHINT);
try {
int status = getter.execute();
boolean res = (status == XConstants.Success && getter.getActualType() != 0);
if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("Status getting XA_ICEWM_WINOPTHINT: " + !res);
}
return !res || isNetWMName("IceWM");
} finally {
getter.dispose();
}
}
/*
* 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 final XAtom XA_SUN_WM_PROTOCOLS = new XAtom("_SUN_WM_PROTOCOLS", false);
static boolean isOpenLook() {
if (!XA_SUN_WM_PROTOCOLS.isInterned()) {
return false;
}
XAtom[] list = XA_SUN_WM_PROTOCOLS.getAtomListProperty(XToolkit.getDefaultRootWindow());
return (list.length != 0);
}
/*
* Temporary error handler that checks if selecting for
* SubstructureRedirect failed.
*/
private static boolean winmgr_running = false;
private static XErrorHandler detectWMHandler = new XErrorHandler.XBaseErrorHandler() {
@Override
public int handleError(long display, XErrorEvent err) {
if ((err.get_request_code() == XProtocolConstants.X_ChangeWindowAttributes) &&
(err.get_error_code() == XConstants.BadAccess))
{
winmgr_running = true;
return 0;
}
return super.handleError(display, err);
}
};
/*
* Make an educated guess about running window manager.
* XXX: ideally, we should detect wm restart.
*/
static int awt_wmgr = XWM.UNDETERMINED_WM;
static XWM wm;
static XWM getWM() {
if (wm == null) {
wm = new XWM(awt_wmgr = getWMID()/*XWM.OTHER_WM*/);
}
return wm;
}
static int getWMID() {
if (insLog.isLoggable(PlatformLogger.Level.FINEST)) {
insLog.finest("awt_wmgr = " + awt_wmgr);
}
/*
* Ideally, we should support cases when a different WM is started
* during a Java app lifetime.
*/
if (awt_wmgr != XWM.UNDETERMINED_WM) {
return awt_wmgr;
}
XSetWindowAttributes substruct = new XSetWindowAttributes();
XToolkit.awtLock();
try {
if (isNoWM()) {
awt_wmgr = XWM.NO_WM;
return awt_wmgr;
}
// Initialize _NET protocol - used to detect Window Manager.
// Later, WM will initialize its own version of protocol
XNETProtocol l_net_protocol = g_net_protocol = new XNETProtocol();
l_net_protocol.detect();
if (log.isLoggable(PlatformLogger.Level.FINE) && l_net_protocol.active()) {
log.fine("_NET_WM_NAME is " + l_net_protocol.getWMName());
}
XWINProtocol win = g_win_protocol = new XWINProtocol();
win.detect();
/* actual check for IceWM to follow below */
boolean doIsIceWM = prepareIsIceWM(); /* and let IceWM to act */
/*
* Ok, some WM is out there. Check which one by testing for
* "distinguishing" atoms.
*/
if (isEnlightenment()) {
awt_wmgr = XWM.ENLIGHTEN_WM;
} else if (isMetacity()) {
awt_wmgr = XWM.METACITY_WM;
} else if (isMutter()) {
awt_wmgr = XWM.MUTTER_WM;
} else if (isSawfish()) {
awt_wmgr = XWM.SAWFISH_WM;
} else if (isKDE2()) {
awt_wmgr =XWM.KDE2_WM;
} else if (isCompiz()) {
awt_wmgr = XWM.COMPIZ_WM;
} else if (isLookingGlass()) {
awt_wmgr = LG3D_WM;
} else if (isCWM()) {
awt_wmgr = CWM_WM;
} else if (doIsIceWM && isIceWM()) {
awt_wmgr = XWM.ICE_WM;
}
/*
* We don't check for legacy WM when we already know that WM
* supports WIN or _NET wm spec.
*/
else if (l_net_protocol.active()) {
awt_wmgr = XWM.OTHER_WM;
} else if (win.active()) {
awt_wmgr = XWM.OTHER_WM;
}
/*
* Check for legacy WMs.
*/
else if (isCDE()) { /* XXX: must come before isMotif */
awt_wmgr = XWM.CDE_WM;
} else if (isMotif()) {
awt_wmgr = XWM.MOTIF_WM;
} else if (isOpenLook()) {
awt_wmgr = XWM.OPENLOOK_WM;
} else {
awt_wmgr = XWM.OTHER_WM;
}
return awt_wmgr;
} finally {
XToolkit.awtUnlock();
substruct.dispose();
}
}
/*****************************************************************************\
*
* Size and decoration hints ...
*
\*****************************************************************************/
/*
* Remove size hints specified by the mask.
* XXX: Why do we need this in the first place???
*/
static void removeSizeHints(XDecoratedPeer window, long mask) {
mask &= XUtilConstants.PMaxSize | XUtilConstants.PMinSize;
XToolkit.awtLock();
try {
XSizeHints hints = window.getHints();
if ((hints.get_flags() & mask) == 0) {
return;
}
hints.set_flags(hints.get_flags() & ~mask);
if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
insLog.finer("Setting hints, flags " + XlibWrapper.hintsToString(hints.get_flags()));
}
XlibWrapper.XSetWMNormalHints(XToolkit.getDisplay(),
window.getWindow(),
hints.pData);
} finally {
XToolkit.awtUnlock();
}
}
/*
* 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 normalizeMotifDecor(int decorations) {
if ((decorations & MWMConstants.MWM_DECOR_ALL) == 0) {
return decorations;
}
int d = MWMConstants.MWM_DECOR_BORDER | MWMConstants.MWM_DECOR_RESIZEH
| MWMConstants.MWM_DECOR_TITLE
| MWMConstants.MWM_DECOR_MENU | MWMConstants.MWM_DECOR_MINIMIZE
| MWMConstants.MWM_DECOR_MAXIMIZE;
d &= ~decorations;
return d;
}
/*
* If MWM_FUNC_ALL bit is set, then the rest of the bit-mask is taken
* to be subtracted from the functions. Normalize function spec
* so that we can map motif func to something else bit-by-bit in the
* rest of the code.
*/
static int normalizeMotifFunc(int functions) {
if ((functions & MWMConstants.MWM_FUNC_ALL) == 0) {
return functions;
}
int f = MWMConstants.MWM_FUNC_RESIZE |
MWMConstants.MWM_FUNC_MOVE |
MWMConstants.MWM_FUNC_MAXIMIZE |
MWMConstants.MWM_FUNC_MINIMIZE |
MWMConstants.MWM_FUNC_CLOSE;
f &= ~functions;
return f;
}
/*
* Infer OL properties from MWM decorations.
* Use _OL_DECOR_DEL(ATOM[]) to remove unwanted ones.
*/
static void setOLDecor(XWindow window, boolean resizable, int decorations) {
if (window == null) {
return;
}
XAtomList decorDel = new XAtomList();
decorations = normalizeMotifDecor(decorations);
if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
insLog.finer("Setting OL_DECOR to " + Integer.toBinaryString(decorations));
}
if ((decorations & MWMConstants.MWM_DECOR_TITLE) == 0) {
decorDel.add(XA_OL_DECOR_HEADER);
}
if ((decorations & (MWMConstants.MWM_DECOR_RESIZEH | MWMConstants.MWM_DECOR_MAXIMIZE)) == 0) {
decorDel.add(XA_OL_DECOR_RESIZE);
}
if ((decorations & (MWMConstants.MWM_DECOR_MENU |
MWMConstants.MWM_DECOR_MAXIMIZE |
MWMConstants.MWM_DECOR_MINIMIZE)) == 0)
{
decorDel.add(XA_OL_DECOR_CLOSE);
}
if (decorDel.size() == 0) {
insLog.finer("Deleting OL_DECOR");
XA_OL_DECOR_DEL.DeleteProperty(window);
} else {
if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
insLog.finer("Setting OL_DECOR to " + decorDel);
}
XA_OL_DECOR_DEL.setAtomListProperty(window, decorDel);
}
}
/*
* Set MWM decorations. Set MWM functions depending on resizability.
*/
static void setMotifDecor(XWindow window, boolean resizable, int decorations, int functions) {
/* Apparently some WMs don't implement MWM_*_ALL semantic correctly */
if ((decorations & MWMConstants.MWM_DECOR_ALL) != 0
&& (decorations != MWMConstants.MWM_DECOR_ALL))
{
decorations = normalizeMotifDecor(decorations);
}
if ((functions & MWMConstants.MWM_FUNC_ALL) != 0
&& (functions != MWMConstants.MWM_FUNC_ALL))
{
functions = normalizeMotifFunc(functions);
}
PropMwmHints hints = window.getMWMHints();
hints.set_flags(hints.get_flags() |
MWMConstants.MWM_HINTS_FUNCTIONS |
MWMConstants.MWM_HINTS_DECORATIONS);
hints.set_functions(functions);
hints.set_decorations(decorations);
if (stateLog.isLoggable(PlatformLogger.Level.FINER)) {
stateLog.finer("Setting MWM_HINTS to " + hints);
}
window.setMWMHints(hints);
}
/*
* 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 needRemap(XDecoratedPeer window) {
// Don't remap EmbeddedFrame,
// e.g. for TrayIcon it causes problems.
return !window.isEmbedded();
}
/*
* Set decoration hints on the shell to wdata->decor adjusted
* appropriately if not resizable.
*/
static void setShellDecor(XDecoratedPeer window) {
int decorations = window.getDecorations();
int functions = window.getFunctions();
boolean resizable = window.isResizable();
if (!resizable) {
if ((decorations & MWMConstants.MWM_DECOR_ALL) != 0) {
decorations |= MWMConstants.MWM_DECOR_RESIZEH | MWMConstants.MWM_DECOR_MAXIMIZE;
} else {
decorations &= ~(MWMConstants.MWM_DECOR_RESIZEH | MWMConstants.MWM_DECOR_MAXIMIZE);
}
}
setMotifDecor(window, resizable, decorations, functions);
setOLDecor(window, resizable, decorations);
/* Some WMs need remap to redecorate the window */
if (window.isShowing() && needRemap(window)) {
/*
* 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).
*/
window.xSetVisible(false);
XToolkit.XSync();
window.xSetVisible(true);
}
}
/*
* Make specified shell resizable.
*/
static void setShellResizable(XDecoratedPeer window) {
if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
insLog.fine("Setting shell resizable " + window);
}
XToolkit.awtLock();
try {
Rectangle shellBounds = window.getShellBounds();
shellBounds.translate(-window.currentInsets.left, -window.currentInsets.top);
window.updateSizeHints(window.getDimensions());
requestWMExtents(window.getWindow());
XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), window.getShell(),
shellBounds.x, shellBounds.y, shellBounds.width, shellBounds.height);
/* REMINDER: will need to revisit when setExtendedStateBounds is added */
//Fix for 4320050: Minimum size for java.awt.Frame is not being enforced.
//We need to update frame's minimum size, not to reset it
removeSizeHints(window, XUtilConstants.PMaxSize);
window.updateMinimumSize();
/* Restore decorations */
setShellDecor(window);
} finally {
XToolkit.awtUnlock();
}
}
/*
* Make specified shell non-resizable.
* If justChangeSize is false, update decorations as well.
* @param shellBounds bounds of the shell window
*/
static void setShellNotResizable(XDecoratedPeer window, WindowDimensions newDimensions, Rectangle shellBounds,
boolean justChangeSize)
{
if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
insLog.fine("Setting non-resizable shell " + window + ", dimensions " + newDimensions +
", shellBounds " + shellBounds +", just change size: " + justChangeSize);
}
XToolkit.awtLock();
try {
/* Fix min/max size hints at the specified values */
if (!shellBounds.isEmpty()) {
window.updateSizeHints(newDimensions);
requestWMExtents(window.getWindow());
XToolkit.XSync();
XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), window.getShell(),
shellBounds.x, shellBounds.y, shellBounds.width, shellBounds.height);
}
if (!justChangeSize) { /* update decorations */
setShellDecor(window);
}
} finally {
XToolkit.awtUnlock();
}
}
/*****************************************************************************\
* Protocols support
*/
private HashMap<Class>, Collection>> protocolsMap = new HashMap
Other Java examples (source code examples)Here is a short list of links related to this Java XWM.java source code file: |
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.