|
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.