0001: /*
0002: * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
0003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004: *
0005: * This code is free software; you can redistribute it and/or modify it
0006: * under the terms of the GNU General Public License version 2 only, as
0007: * published by the Free Software Foundation. Sun designates this
0008: * particular file as subject to the "Classpath" exception as provided
0009: * by Sun in the LICENSE file that accompanied this code.
0010: *
0011: * This code is distributed in the hope that it will be useful, but WITHOUT
0012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014: * version 2 for more details (a copy is included in the LICENSE file that
0015: * accompanied this code).
0016: *
0017: * You should have received a copy of the GNU General Public License version
0018: * 2 along with this work; if not, write to the Free Software Foundation,
0019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020: *
0021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022: * CA 95054 USA or visit www.sun.com if you need additional information or
0023: * have any questions.
0024: */
0025: package sun.awt.X11;
0026:
0027: import java.awt.*;
0028:
0029: import java.awt.event.ComponentEvent;
0030: import java.awt.event.FocusEvent;
0031: import java.awt.event.WindowEvent;
0032:
0033: import java.awt.peer.ComponentPeer;
0034: import java.awt.peer.WindowPeer;
0035:
0036: import java.util.ArrayList;
0037: import java.util.HashSet;
0038: import java.util.Iterator;
0039: import java.util.Set;
0040: import java.util.Vector;
0041:
0042: import java.util.logging.Level;
0043: import java.util.logging.Logger;
0044:
0045: import sun.awt.ComponentAccessor;
0046: import sun.awt.WindowAccessor;
0047: import sun.awt.DisplayChangedListener;
0048: import sun.awt.SunToolkit;
0049: import sun.awt.X11GraphicsDevice;
0050: import sun.awt.X11GraphicsEnvironment;
0051:
0052: class XWindowPeer extends XPanelPeer implements WindowPeer,
0053: DisplayChangedListener, MWMConstants {
0054:
0055: private static final Logger log = Logger
0056: .getLogger("sun.awt.X11.XWindowPeer");
0057: private static final Logger focusLog = Logger
0058: .getLogger("sun.awt.X11.focus.XWindowPeer");
0059: private static final Logger insLog = Logger
0060: .getLogger("sun.awt.X11.insets.XWindowPeer");
0061: private static final Logger grabLog = Logger
0062: .getLogger("sun.awt.X11.grab.XWindowPeer");
0063: private static final Logger iconLog = Logger
0064: .getLogger("sun.awt.X11.icon.XWindowPeer");
0065:
0066: // should be synchronized on awtLock
0067: private static Set<XWindowPeer> windows = new HashSet<XWindowPeer>();
0068:
0069: static XAtom wm_protocols;
0070: static XAtom wm_delete_window;
0071: static XAtom wm_take_focus;
0072:
0073: Insets insets = new Insets(0, 0, 0, 0);
0074: XWindowAttributesData winAttr;
0075: private boolean cachedFocusableWindow;
0076: XWarningWindow warningWindow;
0077:
0078: private boolean alwaysOnTop;
0079: PropMwmHints mwm_hints;
0080: private boolean locationByPlatform;
0081:
0082: Dialog modalBlocker;
0083: boolean delayedModalBlocking = false;
0084: Dimension targetMinimumSize = null;
0085:
0086: private XWindowPeer ownerPeer;
0087:
0088: // used for modal blocking to keep existing z-order
0089: protected XWindowPeer prevTransientFor, nextTransientFor;
0090: // value of WM_TRANSIENT_FOR hint set on this window
0091: private XWindowPeer curRealTransientFor;
0092:
0093: private boolean grab = false; // Whether to do a grab during showing
0094:
0095: private boolean isMapped = false; // Is this window mapped or not
0096: private boolean stateChanged; // Indicates whether the value on savedState is valid
0097: private int savedState; // Holds last known state of the top-level window
0098: private boolean mustControlStackPosition = false; // Am override-redirect not on top
0099: private XEventDispatcher rootPropertyEventDispatcher = null;
0100:
0101: /*
0102: * Focus related flags
0103: */
0104: private boolean isUnhiding = false; // Is the window unhiding.
0105: private boolean isBeforeFirstMapNotify = false; // Is the window (being shown) between
0106: // setVisible(true) & handleMapNotify().
0107:
0108: // It need to be accessed from XFramePeer.
0109: protected Vector<ToplevelStateListener> toplevelStateListeners = new Vector<ToplevelStateListener>();
0110:
0111: XWindowPeer(XCreateWindowParams params) {
0112: super (params.putIfNull(PARENT_WINDOW, Long.valueOf(0)));
0113: }
0114:
0115: XWindowPeer(Window target) {
0116: super (new XCreateWindowParams(new Object[] { TARGET, target,
0117: PARENT_WINDOW, Long.valueOf(0) }));
0118: }
0119:
0120: // fallback default font object
0121: static Font defaultFont;
0122:
0123: /*
0124: * This constant defines icon size recommended for using.
0125: * Apparently, we should use XGetIconSizes which should
0126: * return icon sizes would be most appreciated by the WM.
0127: * However, XGetIconSizes always returns 0 for some reason.
0128: * So the constant has been introduced.
0129: */
0130: private static final int PREFERRED_SIZE_FOR_ICON = 128;
0131:
0132: /*
0133: * Sometimes XChangeProperty(_NET_WM_ICON) doesn't work if
0134: * image buffer is too large. This constant holds maximum
0135: * length of buffer which can be used with _NET_WM_ICON hint.
0136: * It holds int's value.
0137: */
0138: private static final int MAXIMUM_BUFFER_LENGTH_NET_WM_ICON = (2 << 15) - 1;
0139:
0140: void preInit(XCreateWindowParams params) {
0141: params.put(REPARENTED, Boolean.valueOf(isOverrideRedirect()
0142: || isSimpleWindow()));
0143: super .preInit(params);
0144: params
0145: .putIfNull(BIT_GRAVITY, Integer
0146: .valueOf(NorthWestGravity));
0147:
0148: savedState = WithdrawnState;
0149: XA_NET_WM_STATE = XAtom.get("_NET_WM_STATE");
0150:
0151: winAttr = new XWindowAttributesData();
0152: insets = new Insets(0, 0, 0, 0);
0153:
0154: params.put(OVERRIDE_REDIRECT, Boolean
0155: .valueOf(isOverrideRedirect()));
0156:
0157: SunToolkit.awtLock();
0158: try {
0159: windows.add(this );
0160: if (wm_protocols == null) {
0161: wm_protocols = XAtom.get("WM_PROTOCOLS");
0162: wm_delete_window = XAtom.get("WM_DELETE_WINDOW");
0163: wm_take_focus = XAtom.get("WM_TAKE_FOCUS");
0164: }
0165: } finally {
0166: SunToolkit.awtUnlock();
0167: }
0168: cachedFocusableWindow = isFocusableWindow();
0169:
0170: Font f = target.getFont();
0171: if (f == null) {
0172: if (defaultFont == null) {
0173: defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12);
0174: }
0175: f = defaultFont;
0176: target.setFont(f);
0177: // we should not call setFont because it will call a repaint
0178: // which the peer may not be ready to do yet.
0179: }
0180: Color c = target.getBackground();
0181: if (c == null) {
0182: Color background = SystemColor.window;
0183: target.setBackground(background);
0184: // we should not call setBackGround because it will call a repaint
0185: // which the peer may not be ready to do yet.
0186: }
0187: c = target.getForeground();
0188: if (c == null) {
0189: target.setForeground(SystemColor.windowText);
0190: // we should not call setForeGround because it will call a repaint
0191: // which the peer may not be ready to do yet.
0192: }
0193:
0194: alwaysOnTop = ((Window) target).isAlwaysOnTop()
0195: && ((Window) target).isAlwaysOnTopSupported();
0196:
0197: GraphicsConfiguration gc = getGraphicsConfiguration();
0198: ((X11GraphicsDevice) gc.getDevice())
0199: .addDisplayChangedListener(this );
0200: }
0201:
0202: private void initWMProtocols() {
0203: wm_protocols.setAtomListProperty(this , getWMProtocols());
0204: }
0205:
0206: /**
0207: * Returns list of protocols which should be installed on this window.
0208: * Descendants can override this method to add class-specific protocols
0209: */
0210: protected XAtomList getWMProtocols() {
0211: // No protocols on simple window
0212: return new XAtomList();
0213: }
0214:
0215: protected String getWMName() {
0216: String name = target.getName();
0217: if (name == null || name.trim().equals("")) {
0218: name = " ";
0219: }
0220: return name;
0221: }
0222:
0223: void postInit(XCreateWindowParams params) {
0224: super .postInit(params);
0225:
0226: // Init WM_PROTOCOLS atom
0227: initWMProtocols();
0228:
0229: // Set WM_TRANSIENT_FOR and group_leader
0230: Window t_window = (Window) target;
0231: Window owner = t_window.getOwner();
0232: if (owner != null) {
0233: ownerPeer = (XWindowPeer) owner.getPeer();
0234: if (focusLog.isLoggable(Level.FINER)) {
0235: focusLog.fine("Owner is " + owner);
0236: focusLog.fine("Owner peer is " + ownerPeer);
0237: focusLog.fine("Owner X window "
0238: + Long.toHexString(ownerPeer.getWindow()));
0239: focusLog.fine("Owner content X window "
0240: + Long
0241: .toHexString(ownerPeer
0242: .getContentWindow()));
0243: }
0244: // as owner window may be an embedded window, we must get a toplevel window
0245: // to set as TRANSIENT_FOR hint
0246: long ownerWindow = ownerPeer.getWindow();
0247: if (ownerWindow != 0) {
0248: XToolkit.awtLock();
0249: try {
0250: // Set WM_TRANSIENT_FOR
0251: if (focusLog.isLoggable(Level.FINE))
0252: focusLog.fine("Setting transient on "
0253: + Long.toHexString(getWindow())
0254: + " for "
0255: + Long.toHexString(ownerWindow));
0256: setToplevelTransientFor(this , ownerPeer, false,
0257: true);
0258:
0259: // Set group leader
0260: XWMHints hints = getWMHints();
0261: hints.set_flags(hints.get_flags()
0262: | (int) XlibWrapper.WindowGroupHint);
0263: hints.set_window_group(ownerWindow);
0264: XlibWrapper.XSetWMHints(XToolkit.getDisplay(),
0265: getWindow(), hints.pData);
0266: } finally {
0267: XToolkit.awtUnlock();
0268: }
0269: }
0270: }
0271:
0272: // Init warning window(for applets)
0273: if (((Window) target).getWarningString() != null) {
0274: // accessSystemTray permission allows to display TrayIcon, TrayIcon tooltip
0275: // and TrayIcon balloon windows without a warning window.
0276: if (!WindowAccessor.isTrayIconWindow((Window) target)) {
0277: warningWindow = new XWarningWindow((Window) target,
0278: getWindow());
0279: }
0280: }
0281:
0282: setSaveUnder(true);
0283:
0284: XWM.requestWMExtents(getWindow());
0285: updateIconImages();
0286: }
0287:
0288: public void updateIconImages() {
0289: Window target = (Window) this .target;
0290: java.util.List<Image> iconImages = ((Window) target)
0291: .getIconImages();
0292: XWindowPeer ownerPeer = getOwnerPeer();
0293: winAttr.icons = new ArrayList<XIconInfo>();
0294: if (iconImages.size() != 0) {
0295: //read icon images from target
0296: winAttr.iconsInherited = false;
0297: for (Iterator<Image> i = iconImages.iterator(); i.hasNext();) {
0298: Image image = i.next();
0299: if (image == null) {
0300: if (log.isLoggable(Level.FINEST)) {
0301: log
0302: .finest("XWindowPeer.updateIconImages: Skipping the image passed into Java because it's null.");
0303: }
0304: continue;
0305: }
0306: XIconInfo iconInfo;
0307: try {
0308: iconInfo = new XIconInfo(image);
0309: } catch (Exception e) {
0310: if (log.isLoggable(Level.FINEST)) {
0311: log
0312: .finest("XWindowPeer.updateIconImages: Perhaps the image passed into Java is broken. Skipping this icon.");
0313: }
0314: continue;
0315: }
0316: if (iconInfo.isValid()) {
0317: winAttr.icons.add(iconInfo);
0318: }
0319: }
0320: }
0321:
0322: // Fix for CR#6425089
0323: winAttr.icons = normalizeIconImages(winAttr.icons);
0324:
0325: if (winAttr.icons.size() == 0) {
0326: //target.icons is empty or all icon images are broken
0327: if (ownerPeer != null) {
0328: //icon is inherited from parent
0329: winAttr.iconsInherited = true;
0330: winAttr.icons = ownerPeer.getIconInfo();
0331: } else {
0332: //default icon is used
0333: winAttr.iconsInherited = false;
0334: winAttr.icons = getDefaultIconInfo();
0335: }
0336: }
0337: recursivelySetIcon(winAttr.icons);
0338: }
0339:
0340: /*
0341: * Sometimes XChangeProperty(_NET_WM_ICON) doesn't work if
0342: * image buffer is too large. This function help us accommodate
0343: * initial list of the icon images to certainly-acceptable.
0344: * It does scale some of these icons to appropriate size
0345: * if it's necessary.
0346: */
0347: static java.util.List<XIconInfo> normalizeIconImages(
0348: java.util.List<XIconInfo> icons) {
0349: java.util.List<XIconInfo> result = new ArrayList<XIconInfo>();
0350: int totalLength = 0;
0351: boolean haveLargeIcon = false;
0352:
0353: for (XIconInfo icon : icons) {
0354: int width = icon.getWidth();
0355: int height = icon.getHeight();
0356: int length = icon.getRawLength();
0357:
0358: if (width > PREFERRED_SIZE_FOR_ICON
0359: || height > PREFERRED_SIZE_FOR_ICON) {
0360: if (haveLargeIcon) {
0361: continue;
0362: }
0363: int scaledWidth = width;
0364: int scaledHeight = height;
0365: while (scaledWidth > PREFERRED_SIZE_FOR_ICON
0366: || scaledHeight > PREFERRED_SIZE_FOR_ICON) {
0367: scaledWidth = scaledWidth / 2;
0368: scaledHeight = scaledHeight / 2;
0369: }
0370:
0371: icon.setScaledSize(scaledWidth, scaledHeight);
0372: length = icon.getRawLength();
0373: }
0374:
0375: if (totalLength + length <= MAXIMUM_BUFFER_LENGTH_NET_WM_ICON) {
0376: totalLength += length;
0377: result.add(icon);
0378: if (width > PREFERRED_SIZE_FOR_ICON
0379: || height > PREFERRED_SIZE_FOR_ICON) {
0380: haveLargeIcon = true;
0381: }
0382: }
0383: }
0384:
0385: if (iconLog.isLoggable(Level.FINEST)) {
0386: iconLog.log(Level.FINEST,
0387: ">>> Length_ of buffer of icons data: "
0388: + totalLength + ", maximum length: "
0389: + MAXIMUM_BUFFER_LENGTH_NET_WM_ICON);
0390: }
0391:
0392: return result;
0393: }
0394:
0395: /*
0396: * Dumps each icon from the list
0397: */
0398: static void dumpIcons(java.util.List<XIconInfo> icons) {
0399: if (iconLog.isLoggable(Level.FINEST)) {
0400: iconLog.log(Level.FINEST, ">>> Sizes of icon images:");
0401: for (Iterator<XIconInfo> i = icons.iterator(); i.hasNext();) {
0402: iconLog.log(Level.FINEST, " {0}", i.next());
0403: }
0404: }
0405: }
0406:
0407: public void recursivelySetIcon(java.util.List<XIconInfo> icons) {
0408: dumpIcons(winAttr.icons);
0409: setIconHints(icons);
0410: Window target = (Window) this .target;
0411: Window[] children = target.getOwnedWindows();
0412: int cnt = children.length;
0413: for (int i = 0; i < cnt; i++) {
0414: ComponentPeer childPeer = children[i].getPeer();
0415: if (childPeer != null && childPeer instanceof XWindowPeer) {
0416: if (((XWindowPeer) childPeer).winAttr.iconsInherited) {
0417: ((XWindowPeer) childPeer).winAttr.icons = icons;
0418: ((XWindowPeer) childPeer).recursivelySetIcon(icons);
0419: }
0420: }
0421: }
0422: }
0423:
0424: java.util.List<XIconInfo> getIconInfo() {
0425: return winAttr.icons;
0426: }
0427:
0428: void setIconHints(java.util.List<XIconInfo> icons) {
0429: //This does nothing for XWindowPeer,
0430: //It's overriden in XDecoratedPeer
0431: }
0432:
0433: private static ArrayList<XIconInfo> defaultIconInfo;
0434:
0435: protected synchronized static java.util.List<XIconInfo> getDefaultIconInfo() {
0436: if (defaultIconInfo == null) {
0437: defaultIconInfo = new ArrayList<XIconInfo>();
0438: if (XlibWrapper.dataModel == 32) {
0439: defaultIconInfo.add(new XIconInfo(
0440: XAWTIcon32_java_icon16_png.java_icon16_png));
0441: defaultIconInfo.add(new XIconInfo(
0442: XAWTIcon32_java_icon24_png.java_icon24_png));
0443: defaultIconInfo.add(new XIconInfo(
0444: XAWTIcon32_java_icon32_png.java_icon32_png));
0445: defaultIconInfo.add(new XIconInfo(
0446: XAWTIcon32_java_icon48_png.java_icon48_png));
0447: } else {
0448: defaultIconInfo.add(new XIconInfo(
0449: XAWTIcon64_java_icon16_png.java_icon16_png));
0450: defaultIconInfo.add(new XIconInfo(
0451: XAWTIcon64_java_icon24_png.java_icon24_png));
0452: defaultIconInfo.add(new XIconInfo(
0453: XAWTIcon64_java_icon32_png.java_icon32_png));
0454: defaultIconInfo.add(new XIconInfo(
0455: XAWTIcon64_java_icon48_png.java_icon48_png));
0456: }
0457: }
0458: return defaultIconInfo;
0459: }
0460:
0461: public void updateMinimumSize() {
0462: //This function only saves minimumSize value in XWindowPeer
0463: //Setting WMSizeHints is implemented in XDecoratedPeer
0464: targetMinimumSize = (((Component) target).isMinimumSizeSet()) ? ((Component) target)
0465: .getMinimumSize()
0466: : null;
0467: }
0468:
0469: public Dimension getTargetMinimumSize() {
0470: return (targetMinimumSize == null) ? null : new Dimension(
0471: targetMinimumSize);
0472: }
0473:
0474: public XWindowPeer getOwnerPeer() {
0475: return ownerPeer;
0476: }
0477:
0478: //Fix for 6318144: PIT:Setting Min Size bigger than current size enlarges
0479: //the window but fails to revalidate, Sol-CDE
0480: //This bug is regression for
0481: //5025858: Resizing a decorated frame triggers componentResized event twice.
0482: //Since events are not posted from Component.setBounds we need to send them here.
0483: //Note that this function is overriden in XDecoratedPeer so event
0484: //posting is not changing for decorated peers
0485: public void setBounds(int x, int y, int width, int height, int op) {
0486: XToolkit.awtLock();
0487: try {
0488: Rectangle oldBounds = getBounds();
0489: super .setBounds(x, y, width, height, op);
0490: Rectangle bounds = getBounds();
0491:
0492: XSizeHints hints = getHints();
0493: setSizeHints(hints.get_flags() | XlibWrapper.PPosition
0494: | XlibWrapper.PSize, bounds.x, bounds.y,
0495: bounds.width, bounds.height);
0496: XWM.setMotifDecor(this , false, 0, 0);
0497:
0498: XNETProtocol protocol = XWM.getWM().getNETProtocol();
0499: if (protocol != null && protocol.active()) {
0500: XAtomList net_wm_state = getNETWMState();
0501: net_wm_state.add(protocol.XA_NET_WM_STATE_SKIP_TASKBAR);
0502: setNETWMState(net_wm_state);
0503: }
0504:
0505: if (!bounds.getSize().equals(oldBounds.getSize())) {
0506: postEventToEventQueue(new ComponentEvent(
0507: getEventSource(),
0508: ComponentEvent.COMPONENT_RESIZED));
0509: }
0510: if (!bounds.getLocation().equals(oldBounds.getLocation())) {
0511: postEventToEventQueue(new ComponentEvent(
0512: getEventSource(),
0513: ComponentEvent.COMPONENT_MOVED));
0514: }
0515: } finally {
0516: XToolkit.awtUnlock();
0517: }
0518: }
0519:
0520: void updateFocusability() {
0521: updateFocusableWindowState();
0522: XToolkit.awtLock();
0523: try {
0524: XWMHints hints = getWMHints();
0525: hints.set_flags(hints.get_flags()
0526: | (int) XlibWrapper.InputHint);
0527: hints
0528: .set_input(false/*isNativelyNonFocusableWindow() ? (0):(1)*/);
0529: XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(),
0530: hints.pData);
0531: } finally {
0532: XToolkit.awtUnlock();
0533: }
0534: }
0535:
0536: public Insets getInsets() {
0537: Insets in = (Insets) (insets.clone());
0538: in.top += getWarningWindowHeight();
0539: return in;
0540: }
0541:
0542: // NOTE: This method may be called by privileged threads.
0543: // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
0544: public void handleIconify() {
0545: postEvent(new WindowEvent((Window) target,
0546: WindowEvent.WINDOW_ICONIFIED));
0547: }
0548:
0549: // NOTE: This method may be called by privileged threads.
0550: // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
0551: public void handleDeiconify() {
0552: postEvent(new WindowEvent((Window) target,
0553: WindowEvent.WINDOW_DEICONIFIED));
0554: }
0555:
0556: // NOTE: This method may be called by privileged threads.
0557: // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
0558: public void handleStateChange(int oldState, int newState) {
0559: postEvent(new WindowEvent((Window) target,
0560: WindowEvent.WINDOW_STATE_CHANGED, oldState, newState));
0561: }
0562:
0563: /**
0564: * DEPRECATED: Replaced by getInsets().
0565: */
0566: public Insets insets() {
0567: return getInsets();
0568: }
0569:
0570: boolean isAutoRequestFocus() {
0571: if (XToolkit.isToolkitThread()) {
0572: return WindowAccessor.isAutoRequestFocus((Window) target);
0573: } else {
0574: return ((Window) target).isAutoRequestFocus();
0575: }
0576: }
0577:
0578: /*
0579: * Converts native focused X window id into Java peer.
0580: */
0581: static XWindowPeer getNativeFocusedWindowPeer() {
0582: XBaseWindow baseWindow = XToolkit
0583: .windowToXWindow(xGetInputFocus());
0584: return (baseWindow instanceof XWindowPeer) ? (XWindowPeer) baseWindow
0585: : (baseWindow instanceof XFocusProxyWindow) ? ((XFocusProxyWindow) baseWindow)
0586: .getOwner()
0587: : null;
0588: }
0589:
0590: boolean isFocusableWindow() {
0591: if (XToolkit.isToolkitThread()
0592: || SunToolkit.isAWTLockHeldByCurrentThread()) {
0593: return cachedFocusableWindow;
0594: } else {
0595: return ((Window) target).isFocusableWindow();
0596: }
0597: }
0598:
0599: /* WARNING: don't call client code in this method! */
0600: boolean isFocusedWindowModalBlocker() {
0601: return false;
0602: }
0603:
0604: long getFocusTargetWindow() {
0605: return getContentWindow();
0606: }
0607:
0608: /**
0609: * Returns whether or not this window peer has native X window
0610: * configured as non-focusable window. It might happen if:
0611: * - Java window is non-focusable
0612: * - Java window is simple Window(not Frame or Dialog)
0613: */
0614: boolean isNativelyNonFocusableWindow() {
0615: if (XToolkit.isToolkitThread()
0616: || SunToolkit.isAWTLockHeldByCurrentThread()) {
0617: return isSimpleWindow() || !cachedFocusableWindow;
0618: } else {
0619: return isSimpleWindow()
0620: || !(((Window) target).isFocusableWindow());
0621: }
0622: }
0623:
0624: public void handleWindowFocusIn_Dispatch() {
0625: if (EventQueue.isDispatchThread()) {
0626: XKeyboardFocusManagerPeer
0627: .setCurrentNativeFocusedWindow((Window) target);
0628: target.dispatchEvent(new WindowEvent((Window) target,
0629: WindowEvent.WINDOW_GAINED_FOCUS));
0630: }
0631: }
0632:
0633: public void handleWindowFocusInSync(long serial) {
0634: WindowEvent we = new WindowEvent((Window) target,
0635: WindowEvent.WINDOW_GAINED_FOCUS);
0636: XKeyboardFocusManagerPeer
0637: .setCurrentNativeFocusedWindow((Window) target);
0638: sendEvent(we);
0639: }
0640:
0641: // NOTE: This method may be called by privileged threads.
0642: // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
0643: public void handleWindowFocusIn(long serial) {
0644: WindowEvent we = new WindowEvent((Window) target,
0645: WindowEvent.WINDOW_GAINED_FOCUS);
0646: /* wrap in Sequenced, then post*/
0647: XKeyboardFocusManagerPeer
0648: .setCurrentNativeFocusedWindow((Window) target);
0649: postEvent(wrapInSequenced((AWTEvent) we));
0650: }
0651:
0652: // NOTE: This method may be called by privileged threads.
0653: // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
0654: public void handleWindowFocusOut(Window oppositeWindow, long serial) {
0655: WindowEvent we = new WindowEvent((Window) target,
0656: WindowEvent.WINDOW_LOST_FOCUS, oppositeWindow);
0657: XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow(null);
0658: XKeyboardFocusManagerPeer.setCurrentNativeFocusOwner(null);
0659: /* wrap in Sequenced, then post*/
0660: postEvent(wrapInSequenced((AWTEvent) we));
0661: }
0662:
0663: public void handleWindowFocusOutSync(Window oppositeWindow,
0664: long serial) {
0665: WindowEvent we = new WindowEvent((Window) target,
0666: WindowEvent.WINDOW_LOST_FOCUS, oppositeWindow);
0667: XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow(null);
0668: XKeyboardFocusManagerPeer.setCurrentNativeFocusOwner(null);
0669: sendEvent(we);
0670: }
0671:
0672: /* --- DisplayChangedListener Stuff --- */
0673:
0674: /* Xinerama
0675: * called to check if we've been moved onto a different screen
0676: * Based on checkNewXineramaScreen() in awt_GraphicsEnv.c
0677: */
0678: public void checkIfOnNewScreen(Rectangle newBounds) {
0679: if (!XToolkit.localEnv.runningXinerama()) {
0680: return;
0681: }
0682:
0683: if (log.isLoggable(Level.FINEST)) {
0684: log
0685: .finest("XWindowPeer: Check if we've been moved to a new screen since we're running in Xinerama mode");
0686: }
0687:
0688: int area = newBounds.width * newBounds.height;
0689: int intAmt, vertAmt, horizAmt;
0690: int largestAmt = 0;
0691: int curScreenNum = ((X11GraphicsDevice) getGraphicsConfiguration()
0692: .getDevice()).getScreen();
0693: int newScreenNum = 0;
0694: GraphicsDevice gds[] = XToolkit.localEnv.getScreenDevices();
0695: Rectangle screenBounds;
0696:
0697: for (int i = 0; i < gds.length; i++) {
0698: screenBounds = gds[i].getDefaultConfiguration().getBounds();
0699: if (newBounds.intersects(screenBounds)) {
0700: horizAmt = Math.min(newBounds.x + newBounds.width,
0701: screenBounds.x + screenBounds.width)
0702: - Math.max(newBounds.x, screenBounds.x);
0703: vertAmt = Math.min(newBounds.y + newBounds.height,
0704: screenBounds.y + screenBounds.height)
0705: - Math.max(newBounds.y, screenBounds.y);
0706: intAmt = horizAmt * vertAmt;
0707: if (intAmt == area) {
0708: // Completely on this screen - done!
0709: newScreenNum = i;
0710: break;
0711: }
0712: if (intAmt > largestAmt) {
0713: largestAmt = intAmt;
0714: newScreenNum = i;
0715: }
0716: }
0717: }
0718: if (newScreenNum != curScreenNum) {
0719: if (log.isLoggable(Level.FINEST)) {
0720: log.finest("XWindowPeer: Moved to a new screen");
0721: }
0722: draggedToNewScreen(newScreenNum);
0723: }
0724: }
0725:
0726: /* Xinerama
0727: * called to update our GC when dragged onto another screen
0728: */
0729: public void draggedToNewScreen(int screenNum) {
0730: executeDisplayChangedOnEDT(screenNum);
0731: }
0732:
0733: /**
0734: * Helper method that executes the displayChanged(screen) method on
0735: * the event dispatch thread. This method is used in the Xinerama case
0736: * and after display mode change events.
0737: */
0738: private void executeDisplayChangedOnEDT(final int screenNum) {
0739: Runnable dc = new Runnable() {
0740: public void run() {
0741: // Updates this window's GC and notifies all the children.
0742: // See XPanelPeer/XCanvasPeer.displayChanged(int) for details.
0743: displayChanged(screenNum);
0744: }
0745: };
0746: SunToolkit.executeOnEventHandlerThread((Component) target, dc);
0747: }
0748:
0749: /**
0750: * From the DisplayChangedListener interface; called from
0751: * X11GraphicsDevice when the display mode has been changed.
0752: */
0753: public void displayChanged() {
0754: GraphicsConfiguration gc = getGraphicsConfiguration();
0755: int curScreenNum = ((X11GraphicsDevice) gc.getDevice())
0756: .getScreen();
0757: executeDisplayChangedOnEDT(curScreenNum);
0758: }
0759:
0760: /**
0761: * From the DisplayChangedListener interface; top-levels do not need
0762: * to react to this event.
0763: */
0764: public void paletteChanged() {
0765: }
0766:
0767: /*
0768: * Overridden to check if we need to update our GraphicsDevice/Config
0769: * Added for 4934052.
0770: */
0771: public void handleConfigureNotifyEvent(XEvent xev) {
0772: // TODO: We create an XConfigureEvent every time we override
0773: // handleConfigureNotify() - too many!
0774: XConfigureEvent xe = xev.get_xconfigure();
0775: checkIfOnNewScreen(new Rectangle(xe.get_x(), xe.get_y(), xe
0776: .get_width(), xe.get_height()));
0777:
0778: // Don't call super until we've handled a screen change. Otherwise
0779: // there could be a race condition in which a ComponentListener could
0780: // see the old screen.
0781: super .handleConfigureNotifyEvent(xev);
0782: // for 5085647: no applet warning window visible
0783: updateChildrenSizes();
0784: }
0785:
0786: final void requestXFocus(long time) {
0787: requestXFocus(time, true);
0788: }
0789:
0790: final void requestXFocus() {
0791: requestXFocus(0, false);
0792: }
0793:
0794: /**
0795: * Requests focus to this top-level. Descendants should override to provide
0796: * implementations based on a class of top-level.
0797: */
0798: protected void requestXFocus(long time, boolean timeProvided) {
0799: // Since in XAWT focus is synthetic and all basic Windows are
0800: // override_redirect all we can do is check whether our parent
0801: // is active. If it is - we can freely synthesize focus transfer.
0802: // Luckily, this logic is already implemented in requestWindowFocus.
0803: if (focusLog.isLoggable(Level.FINE))
0804: focusLog.fine("Requesting window focus");
0805: requestWindowFocus(time, timeProvided);
0806: }
0807:
0808: public final boolean focusAllowedFor() {
0809: if (isNativelyNonFocusableWindow()) {
0810: return false;
0811: }
0812: /*
0813: Window target = (Window)this.target;
0814: if (!target.isVisible() ||
0815: !target.isEnabled() ||
0816: !target.isFocusable())
0817: {
0818: return false;
0819: }
0820: */
0821: if (isModalBlocked()) {
0822: return false;
0823: }
0824: return true;
0825: }
0826:
0827: public void handleFocusEvent(XEvent xev) {
0828: XFocusChangeEvent xfe = xev.get_xfocus();
0829: FocusEvent fe;
0830: focusLog.log(Level.FINE, "{0}", new Object[] { xfe });
0831: if (isEventDisabled(xev)) {
0832: return;
0833: }
0834: if (xev.get_type() == XlibWrapper.FocusIn) {
0835: // If this window is non-focusable don't post any java focus event
0836: if (focusAllowedFor()) {
0837: if (xfe.get_mode() == XlibWrapper.NotifyNormal // Normal notify
0838: || xfe.get_mode() == XlibWrapper.NotifyWhileGrabbed) // Alt-Tab notify
0839: {
0840: handleWindowFocusIn(xfe.get_serial());
0841: }
0842: }
0843: } else {
0844: if (xfe.get_mode() == XlibWrapper.NotifyNormal // Normal notify
0845: || xfe.get_mode() == XlibWrapper.NotifyWhileGrabbed) // Alt-Tab notify
0846: {
0847: // If this window is non-focusable don't post any java focus event
0848: if (!isNativelyNonFocusableWindow()) {
0849: XWindowPeer oppositeXWindow = getNativeFocusedWindowPeer();
0850: Object oppositeTarget = (oppositeXWindow != null) ? oppositeXWindow
0851: .getTarget()
0852: : null;
0853: Window oppositeWindow = null;
0854: if (oppositeTarget instanceof Window) {
0855: oppositeWindow = (Window) oppositeTarget;
0856: }
0857: // Check if opposite window is non-focusable. In that case we don't want to
0858: // post any event.
0859: if (oppositeXWindow != null
0860: && oppositeXWindow
0861: .isNativelyNonFocusableWindow()) {
0862: return;
0863: }
0864: if (this == oppositeXWindow) {
0865: oppositeWindow = null;
0866: } else if (oppositeXWindow instanceof XDecoratedPeer) {
0867: if (((XDecoratedPeer) oppositeXWindow).actualFocusedWindow != null) {
0868: oppositeXWindow = ((XDecoratedPeer) oppositeXWindow).actualFocusedWindow;
0869: oppositeTarget = oppositeXWindow
0870: .getTarget();
0871: if (oppositeTarget instanceof Window
0872: && oppositeXWindow.isVisible()
0873: && oppositeXWindow
0874: .isNativelyNonFocusableWindow()) {
0875: oppositeWindow = ((Window) oppositeTarget);
0876: }
0877: }
0878: }
0879: handleWindowFocusOut(oppositeWindow, xfe
0880: .get_serial());
0881: }
0882: }
0883: }
0884: }
0885:
0886: void setSaveUnder(boolean state) {
0887: }
0888:
0889: public void toFront() {
0890: if (isOverrideRedirect() && mustControlStackPosition) {
0891: mustControlStackPosition = false;
0892: removeRootPropertyEventDispatcher();
0893: }
0894: if (isVisible()) {
0895: super .toFront();
0896: if (isFocusableWindow() && isAutoRequestFocus()
0897: && !isModalBlocked() && !isWithdrawn()) {
0898: requestInitialFocus();
0899: }
0900: } else {
0901: setVisible(true);
0902: }
0903: }
0904:
0905: public void toBack() {
0906: XToolkit.awtLock();
0907: try {
0908: if (!isOverrideRedirect()) {
0909: XlibWrapper.XLowerWindow(XToolkit.getDisplay(),
0910: getWindow());
0911: } else {
0912: lowerOverrideRedirect();
0913: }
0914: } finally {
0915: XToolkit.awtUnlock();
0916: }
0917: }
0918:
0919: private void lowerOverrideRedirect() {
0920: //
0921: // make new hash of toplevels of all windows from 'windows' hash.
0922: // FIXME: do not call them "toplevel" as it is misleading.
0923: //
0924: HashSet toplevels = new HashSet();
0925: long topl = 0, mytopl = 0;
0926:
0927: for (XWindowPeer xp : windows) {
0928: topl = getToplevelWindow(xp.getWindow());
0929: if (xp.equals(this )) {
0930: mytopl = topl;
0931: }
0932: if (topl > 0)
0933: toplevels.add(Long.valueOf(topl));
0934: }
0935:
0936: //
0937: // find in the root's tree:
0938: // (1) my toplevel, (2) lowest java toplevel, (3) desktop
0939: // We must enforce (3), (1), (2) order, upward;
0940: // note that nautilus on the next restacking will do (1),(3),(2).
0941: //
0942: long laux, wDesktop = -1, wBottom = -1;
0943: int iMy = -1, iDesktop = -1, iBottom = -1;
0944: int i = 0;
0945: XQueryTree xqt = new XQueryTree(XToolkit.getDefaultRootWindow());
0946: try {
0947: if (xqt.execute() > 0) {
0948: int nchildren = xqt.get_nchildren();
0949: long children = xqt.get_children();
0950: for (i = 0; i < nchildren; i++) {
0951: laux = Native.getWindow(children, i);
0952: if (laux == mytopl) {
0953: iMy = i;
0954: } else if (isDesktopWindow(laux)) {
0955: // we need topmost desktop of them all.
0956: iDesktop = i;
0957: wDesktop = laux;
0958: } else if (iBottom < 0
0959: && toplevels.contains(Long.valueOf(laux))
0960: && laux != mytopl) {
0961: iBottom = i;
0962: wBottom = laux;
0963: }
0964: }
0965: }
0966:
0967: if ((iMy < iBottom || iBottom < 0) && iDesktop < iMy)
0968: return; // no action necessary
0969:
0970: long to_restack = Native.allocateLongArray(2);
0971: Native.putLong(to_restack, 0, wBottom);
0972: Native.putLong(to_restack, 1, mytopl);
0973: XlibWrapper.XRestackWindows(XToolkit.getDisplay(),
0974: to_restack, 2);
0975: XlibWrapper.unsafe.freeMemory(to_restack);
0976:
0977: if (!mustControlStackPosition) {
0978: mustControlStackPosition = true;
0979: // add root window property listener:
0980: // somebody (eg nautilus desktop) may obscure us
0981: addRootPropertyEventDispatcher();
0982: }
0983: } finally {
0984: xqt.dispose();
0985: }
0986: }
0987:
0988: /**
0989: Get XID of closest to root window in a given window hierarchy.
0990: FIXME: do not call it "toplevel" as it is misleading.
0991: On error return 0.
0992: */
0993: private long getToplevelWindow(long w) {
0994: long wi = w, ret, root;
0995: do {
0996: ret = wi;
0997: XQueryTree qt = new XQueryTree(wi);
0998: try {
0999: if (qt.execute() == 0) {
1000: return 0;
1001: }
1002: root = qt.get_root();
1003: wi = qt.get_parent();
1004: } finally {
1005: qt.dispose();
1006: }
1007:
1008: } while (wi != root);
1009:
1010: return ret;
1011: }
1012:
1013: private boolean isDesktopWindow(long wi) {
1014: return XWM.getWM().isDesktopWindow(wi);
1015: }
1016:
1017: private void updateAlwaysOnTop() {
1018: log.log(Level.FINE, "Promoting always-on-top state {0}",
1019: Boolean.valueOf(alwaysOnTop));
1020: XWM.getWM().setLayer(
1021: this ,
1022: alwaysOnTop ? XLayerProtocol.LAYER_ALWAYS_ON_TOP
1023: : XLayerProtocol.LAYER_NORMAL);
1024: }
1025:
1026: public void setAlwaysOnTop(boolean alwaysOnTop) {
1027: this .alwaysOnTop = alwaysOnTop;
1028: updateAlwaysOnTop();
1029: }
1030:
1031: boolean isLocationByPlatform() {
1032: return locationByPlatform;
1033: }
1034:
1035: private void promoteDefaultPosition() {
1036: this .locationByPlatform = ((Window) target)
1037: .isLocationByPlatform();
1038: if (locationByPlatform) {
1039: XToolkit.awtLock();
1040: try {
1041: Rectangle bounds = getBounds();
1042: XSizeHints hints = getHints();
1043: setSizeHints(hints.get_flags()
1044: & ~(USPosition | PPosition), bounds.x,
1045: bounds.y, bounds.width, bounds.height);
1046: } finally {
1047: XToolkit.awtUnlock();
1048: }
1049: }
1050: }
1051:
1052: public void setVisible(boolean vis) {
1053: if (!isVisible() && vis) {
1054: isBeforeFirstMapNotify = true;
1055: winAttr.initialFocus = isAutoRequestFocus();
1056: if (!winAttr.initialFocus) {
1057: /*
1058: * It's easier and safer to temporary suppress WM_TAKE_FOCUS
1059: * protocol itself than to ignore WM_TAKE_FOCUS client message.
1060: * Because we will have to make the difference between
1061: * the message come after showing and the message come after
1062: * activation. Also, on Metacity, for some reason, we have _two_
1063: * WM_TAKE_FOCUS client messages when showing a frame/dialog.
1064: */
1065: suppressWmTakeFocus(true);
1066: }
1067: }
1068: updateFocusability();
1069: promoteDefaultPosition();
1070: super .setVisible(vis);
1071: if (!vis && !isWithdrawn()) {
1072: // ICCCM, 4.1.4. Changing Window State:
1073: // "Iconic -> Withdrawn - The client should unmap the window and follow it
1074: // with a synthetic UnmapNotify event as described later in this section."
1075: // The same is true for Normal -> Withdrawn
1076: XToolkit.awtLock();
1077: try {
1078: XUnmapEvent unmap = new XUnmapEvent();
1079: unmap.set_window(window);
1080: unmap.set_event(XToolkit.getDefaultRootWindow());
1081: unmap.set_type((int) XlibWrapper.UnmapNotify);
1082: unmap.set_from_configure(false);
1083: XlibWrapper.XSendEvent(XToolkit.getDisplay(), XToolkit
1084: .getDefaultRootWindow(), false,
1085: XlibWrapper.SubstructureNotifyMask
1086: | XlibWrapper.SubstructureRedirectMask,
1087: unmap.pData);
1088: unmap.dispose();
1089: } finally {
1090: XToolkit.awtUnlock();
1091: }
1092: }
1093: // method called somewhere in parent does not generate configure-notify
1094: // event for override-redirect.
1095: // Ergo, no reshape and bugs like 5085647 in case setBounds was
1096: // called before setVisible.
1097: if (isOverrideRedirect() && vis) {
1098: updateChildrenSizes();
1099: }
1100: }
1101:
1102: protected void suppressWmTakeFocus(boolean doSuppress) {
1103: }
1104:
1105: final boolean isSimpleWindow() {
1106: return !(target instanceof Frame || target instanceof Dialog);
1107: }
1108:
1109: boolean hasWarningWindow() {
1110: return warningWindow != null;
1111: }
1112:
1113: // The height of menu bar window
1114: int getMenuBarHeight() {
1115: return 0;
1116: }
1117:
1118: // The height of area used to display Applet's warning about securit
1119: int getWarningWindowHeight() {
1120: if (warningWindow != null) {
1121: return warningWindow.getHeight();
1122: } else {
1123: return 0;
1124: }
1125: }
1126:
1127: // Called when shell changes its size and requires children windows
1128: // to update their sizes appropriately
1129: void updateChildrenSizes() {
1130: if (warningWindow != null) {
1131: warningWindow.reshape(0, getMenuBarHeight(),
1132: getSize().width, warningWindow.getHeight());
1133: }
1134: }
1135:
1136: boolean isOverrideRedirect() {
1137: return (XWM.getWMID() == XWM.OPENLOOK_WM ? true : false)
1138: || XTrayIconPeer.isTrayIconStuffWindow((Window) target);
1139: }
1140:
1141: final boolean isOLWMDecorBug() {
1142: return XWM.getWMID() == XWM.OPENLOOK_WM
1143: && winAttr.nativeDecor == false;
1144: }
1145:
1146: public void dispose() {
1147: SunToolkit.awtLock();
1148: try {
1149: windows.remove(this );
1150: } finally {
1151: SunToolkit.awtUnlock();
1152: }
1153: if (warningWindow != null) {
1154: warningWindow.destroy();
1155: }
1156: removeRootPropertyEventDispatcher();
1157: mustControlStackPosition = false;
1158: super .dispose();
1159:
1160: /*
1161: * Fix for 6457980.
1162: * When disposing an owned Window we should implicitly
1163: * return focus to its decorated owner because it won't
1164: * receive WM_TAKE_FOCUS.
1165: */
1166: if (isSimpleWindow()) {
1167: if (target == XKeyboardFocusManagerPeer
1168: .getCurrentNativeFocusedWindow()) {
1169: Window owner = getDecoratedOwner((Window) target);
1170: ((XWindowPeer) ComponentAccessor.getPeer(owner))
1171: .requestWindowFocus();
1172: }
1173: }
1174: }
1175:
1176: boolean isResizable() {
1177: return winAttr.isResizable;
1178: }
1179:
1180: public void handleVisibilityEvent(XEvent xev) {
1181: super .handleVisibilityEvent(xev);
1182: XVisibilityEvent ve = xev.get_xvisibility();
1183: winAttr.visibilityState = ve.get_state();
1184: // if (ve.get_state() == XlibWrapper.VisibilityUnobscured) {
1185: // // raiseInputMethodWindow
1186: // }
1187: }
1188:
1189: public void handlePropertyNotify(XEvent xev) {
1190: super .handlePropertyNotify(xev);
1191: XPropertyEvent ev = xev.get_xproperty();
1192: if (ev.get_atom() == XWM.XA_WM_STATE.getAtom()) {
1193: // State has changed, invalidate saved value
1194: stateChanged = true;
1195: stateChanged(ev.get_time(), savedState, getWMState());
1196: } else if (ev.get_atom() == XWM.XA_KDE_NET_WM_FRAME_STRUT
1197: .getAtom()
1198: || ev.get_atom() == XWM.XA_NET_FRAME_EXTENTS.getAtom()) {
1199: getWMSetInsets(XAtom.get(ev.get_atom()));
1200: }
1201: }
1202:
1203: void handleRootPropertyNotify(XEvent xev) {
1204: XPropertyEvent ev = xev.get_xproperty();
1205: if (mustControlStackPosition
1206: && ev.get_atom() == XAtom.get(
1207: "_NET_CLIENT_LIST_STACKING").getAtom()) {
1208: // Restore stack order unhadled/spoiled by WM or some app (nautilus).
1209: // As of now, don't use any generic machinery: just
1210: // do toBack() again.
1211: if (isOverrideRedirect()) {
1212: toBack();
1213: }
1214: }
1215: }
1216:
1217: public void handleMapNotifyEvent(XEvent xev) {
1218: // See 6480534.
1219: isUnhiding |= isWMStateNetHidden();
1220:
1221: super .handleMapNotifyEvent(xev);
1222: if (!winAttr.initialFocus) {
1223: suppressWmTakeFocus(false); // restore the protocol.
1224: /*
1225: * For some reason, on Metacity, a frame/dialog being shown
1226: * without WM_TAKE_FOCUS protocol doesn't get moved to the front.
1227: * So, we do it evidently.
1228: */
1229: XToolkit.awtLock();
1230: try {
1231: XlibWrapper.XRaiseWindow(XToolkit.getDisplay(),
1232: getWindow());
1233: } finally {
1234: XToolkit.awtUnlock();
1235: }
1236: }
1237: if (shouldFocusOnMapNotify()) {
1238: focusLog.fine("Automatically request focus on window");
1239: requestInitialFocus();
1240: }
1241: isUnhiding = false;
1242: isBeforeFirstMapNotify = false;
1243: updateAlwaysOnTop();
1244:
1245: synchronized (getStateLock()) {
1246: if (!isMapped) {
1247: isMapped = true;
1248: }
1249: }
1250: }
1251:
1252: public void handleUnmapNotifyEvent(XEvent xev) {
1253: super .handleUnmapNotifyEvent(xev);
1254:
1255: // On Metacity UnmapNotify comes before PropertyNotify (for _NET_WM_STATE_HIDDEN).
1256: // So we also check for the property later in MapNotify. See 6480534.
1257: isUnhiding |= isWMStateNetHidden();
1258:
1259: synchronized (getStateLock()) {
1260: if (isMapped) {
1261: isMapped = false;
1262: }
1263: }
1264: }
1265:
1266: private boolean shouldFocusOnMapNotify() {
1267: boolean res = false;
1268:
1269: if (isBeforeFirstMapNotify) {
1270: res = (winAttr.initialFocus || // Window.autoRequestFocus
1271: isFocusedWindowModalBlocker());
1272: } else {
1273: res = isUnhiding; // Unhiding
1274: }
1275: res = res && isFocusableWindow() && // General focusability
1276: !isModalBlocked(); // Modality
1277:
1278: return res;
1279: }
1280:
1281: private boolean isWMStateNetHidden() {
1282: XNETProtocol protocol = XWM.getWM().getNETProtocol();
1283: return (protocol != null && protocol.isWMStateNetHidden(this ));
1284: }
1285:
1286: protected void requestInitialFocus() {
1287: requestXFocus();
1288: }
1289:
1290: public void addToplevelStateListener(ToplevelStateListener l) {
1291: toplevelStateListeners.add(l);
1292: }
1293:
1294: public void removeToplevelStateListener(ToplevelStateListener l) {
1295: toplevelStateListeners.remove(l);
1296: }
1297:
1298: /**
1299: * Override this methods to get notifications when top-level window state changes. The state is
1300: * meant in terms of ICCCM: WithdrawnState, IconicState, NormalState
1301: */
1302: protected void stateChanged(long time, int oldState, int newState) {
1303: // Fix for 6401700, 6412803
1304: // If this window is modal blocked, it is put into the transient_for
1305: // chain using prevTransientFor and nextTransientFor hints. However,
1306: // the real WM_TRANSIENT_FOR hint shouldn't be set for windows in
1307: // different WM states (except for owner-window relationship), so
1308: // if the window changes its state, its real WM_TRANSIENT_FOR hint
1309: // should be updated accordingly.
1310: updateTransientFor();
1311:
1312: for (ToplevelStateListener topLevelListenerTmp : toplevelStateListeners) {
1313: topLevelListenerTmp.stateChangedICCCM(oldState, newState);
1314: }
1315: }
1316:
1317: /*
1318: * XmNiconic and Map/UnmapNotify (that XmNiconic relies on) are
1319: * unreliable, since mapping changes can happen for a virtual desktop
1320: * switch or MacOS style shading that became quite popular under X as
1321: * well. Yes, it probably should not be this way, as it violates
1322: * ICCCM, but reality is that quite a lot of window managers abuse
1323: * mapping state.
1324: */
1325: int getWMState() {
1326: if (stateChanged) {
1327: stateChanged = false;
1328: WindowPropertyGetter getter = new WindowPropertyGetter(
1329: window, XWM.XA_WM_STATE, 0, 1, false,
1330: XWM.XA_WM_STATE);
1331: try {
1332: int status = getter.execute();
1333: if (status != XlibWrapper.Success
1334: || getter.getData() == 0) {
1335: return savedState = XlibWrapper.WithdrawnState;
1336: }
1337:
1338: if (getter.getActualType() != XWM.XA_WM_STATE.getAtom()
1339: && getter.getActualFormat() != 32) {
1340: return savedState = XlibWrapper.WithdrawnState;
1341: }
1342: savedState = (int) Native.getCard32(getter.getData());
1343: } finally {
1344: getter.dispose();
1345: }
1346: }
1347: return savedState;
1348: }
1349:
1350: boolean isWithdrawn() {
1351: return getWMState() == XlibWrapper.WithdrawnState;
1352: }
1353:
1354: boolean hasDecorations(int decor) {
1355: if (!winAttr.nativeDecor) {
1356: return false;
1357: } else {
1358: int myDecor = winAttr.decorations;
1359: boolean hasBits = ((myDecor & decor) == decor);
1360: if ((myDecor & XWindowAttributesData.AWT_DECOR_ALL) != 0)
1361: return !hasBits;
1362: else
1363: return hasBits;
1364: }
1365: }
1366:
1367: void setReparented(boolean newValue) {
1368: super .setReparented(newValue);
1369: XToolkit.awtLock();
1370: try {
1371: if (isReparented() && delayedModalBlocking) {
1372: addToTransientFors((XDialogPeer) ComponentAccessor
1373: .getPeer(modalBlocker));
1374: delayedModalBlocking = false;
1375: }
1376: } finally {
1377: XToolkit.awtUnlock();
1378: }
1379: }
1380:
1381: /*
1382: * Returns a Vector of all Java top-level windows,
1383: * sorted by their current Z-order
1384: */
1385: static Vector<XWindowPeer> collectJavaToplevels() {
1386: Vector<XWindowPeer> javaToplevels = new Vector<XWindowPeer>();
1387: Vector<Long> v = new Vector<Long>();
1388: X11GraphicsEnvironment ge = (X11GraphicsEnvironment) GraphicsEnvironment
1389: .getLocalGraphicsEnvironment();
1390: GraphicsDevice[] gds = ge.getScreenDevices();
1391: if (!ge.runningXinerama() && (gds.length > 1)) {
1392: for (GraphicsDevice gd : gds) {
1393: int screen = ((X11GraphicsDevice) gd).getScreen();
1394: long rootWindow = XlibWrapper.RootWindow(XToolkit
1395: .getDisplay(), screen);
1396: v.add(rootWindow);
1397: }
1398: } else {
1399: v.add(XToolkit.getDefaultRootWindow());
1400: }
1401: final int windowsCount = windows.size();
1402: while ((v.size() > 0) && (javaToplevels.size() < windowsCount)) {
1403: long win = v.remove(0);
1404: XQueryTree qt = new XQueryTree(win);
1405: try {
1406: if (qt.execute() != 0) {
1407: int nchildren = qt.get_nchildren();
1408: long children = qt.get_children();
1409: // XQueryTree returns window children ordered by z-order
1410: for (int i = 0; i < nchildren; i++) {
1411: long child = Native.getWindow(children, i);
1412: XBaseWindow childWindow = XToolkit
1413: .windowToXWindow(child);
1414: // filter out Java non-toplevels
1415: if ((childWindow != null)
1416: && !(childWindow instanceof XWindowPeer)) {
1417: continue;
1418: } else {
1419: v.add(child);
1420: }
1421: if (childWindow instanceof XWindowPeer) {
1422: XWindowPeer np = (XWindowPeer) childWindow;
1423: javaToplevels.add(np);
1424: // XQueryTree returns windows sorted by their z-order. However,
1425: // if WM has not handled transient for hint for a child window,
1426: // it may appear in javaToplevels before its owner. Move such
1427: // children after their owners.
1428: int k = 0;
1429: XWindowPeer toCheck = javaToplevels.get(k);
1430: while (toCheck != np) {
1431: XWindowPeer toCheckOwnerPeer = toCheck
1432: .getOwnerPeer();
1433: if (toCheckOwnerPeer == np) {
1434: javaToplevels.remove(k);
1435: javaToplevels.add(toCheck);
1436: } else {
1437: k++;
1438: }
1439: toCheck = javaToplevels.get(k);
1440: }
1441: }
1442: }
1443: }
1444: } finally {
1445: qt.dispose();
1446: }
1447: }
1448: return javaToplevels;
1449: }
1450:
1451: public void setModalBlocked(Dialog d, boolean blocked) {
1452: setModalBlocked(d, blocked, null);
1453: }
1454:
1455: public void setModalBlocked(Dialog d, boolean blocked,
1456: Vector<XWindowPeer> javaToplevels) {
1457: XToolkit.awtLock();
1458: try {
1459: // State lock should always be after awtLock
1460: synchronized (getStateLock()) {
1461: XDialogPeer blockerPeer = (XDialogPeer) ComponentAccessor
1462: .getPeer(d);
1463: if (blocked) {
1464: log.log(Level.FINE, "{0} is blocked by {1}",
1465: new Object[] { this , blockerPeer });
1466: modalBlocker = d;
1467:
1468: if (isReparented() || XWM.isNonReparentingWM()) {
1469: addToTransientFors(blockerPeer, javaToplevels);
1470: } else {
1471: delayedModalBlocking = true;
1472: }
1473: } else {
1474: if (d != modalBlocker) {
1475: throw new IllegalStateException(
1476: "Trying to unblock window blocked by another dialog");
1477: }
1478: modalBlocker = null;
1479:
1480: if (isReparented() || XWM.isNonReparentingWM()) {
1481: removeFromTransientFors();
1482: } else {
1483: delayedModalBlocking = false;
1484: }
1485: }
1486:
1487: updateTransientFor();
1488: }
1489: } finally {
1490: XToolkit.awtUnlock();
1491: }
1492: }
1493:
1494: /*
1495: * Sets the TRANSIENT_FOR hint to the given top-level window. This
1496: * method is used when a window is modal blocked/unblocked or
1497: * changed its state from/to NormalState to/from other states.
1498: * If window or transientForWindow are embedded frames, the containing
1499: * top-level windows are used.
1500: *
1501: * @param window specifies the top-level window that the hint
1502: * is to be set to
1503: * @param transientForWindow the top-level window
1504: * @param updateChain specifies if next/prevTransientFor fields are
1505: * to be updated
1506: * @param allStates if set to <code>true</code> then TRANSIENT_FOR hint
1507: * is set regardless of the state of window and transientForWindow,
1508: * otherwise it is set only if both are in the same state
1509: */
1510: static void setToplevelTransientFor(XWindowPeer window,
1511: XWindowPeer transientForWindow, boolean updateChain,
1512: boolean allStates) {
1513: if ((window == null) || (transientForWindow == null)) {
1514: return;
1515: }
1516: if (updateChain) {
1517: window.prevTransientFor = transientForWindow;
1518: transientForWindow.nextTransientFor = window;
1519: }
1520: if (window.curRealTransientFor == transientForWindow) {
1521: return;
1522: }
1523: if (!allStates
1524: && (window.getWMState() != transientForWindow
1525: .getWMState())) {
1526: return;
1527: }
1528: if (window.getScreenNumber() != transientForWindow
1529: .getScreenNumber()) {
1530: return;
1531: }
1532: long bpw = window.getWindow();
1533: while (!XlibUtil.isToplevelWindow(bpw)
1534: && !XlibUtil.isXAWTToplevelWindow(bpw)) {
1535: bpw = XlibUtil.getParentWindow(bpw);
1536: }
1537: long tpw = transientForWindow.getWindow();
1538: while (!XlibUtil.isToplevelWindow(tpw)
1539: && !XlibUtil.isXAWTToplevelWindow(tpw)) {
1540: tpw = XlibUtil.getParentWindow(tpw);
1541: }
1542: XlibWrapper.XSetTransientFor(XToolkit.getDisplay(), bpw, tpw);
1543: window.curRealTransientFor = transientForWindow;
1544: }
1545:
1546: /*
1547: * This method does nothing if this window is not blocked by any modal dialog.
1548: * For modal blocked windows this method looks up for the nearest
1549: * prevTransiendFor window that is in the same state (Normal/Iconified/Withdrawn)
1550: * as this one and makes this window transient for it. The same operation is
1551: * performed for nextTransientFor window.
1552: * Values of prevTransientFor and nextTransientFor fields are not changed.
1553: */
1554: void updateTransientFor() {
1555: int state = getWMState();
1556: XWindowPeer p = prevTransientFor;
1557: while ((p != null)
1558: && ((p.getWMState() != state) || (p.getScreenNumber() != getScreenNumber()))) {
1559: p = p.prevTransientFor;
1560: }
1561: if (p != null) {
1562: setToplevelTransientFor(this , p, false, false);
1563: } else {
1564: restoreTransientFor(this );
1565: }
1566: XWindowPeer n = nextTransientFor;
1567: while ((n != null)
1568: && ((n.getWMState() != state) || (n.getScreenNumber() != getScreenNumber()))) {
1569: n = n.nextTransientFor;
1570: }
1571: if (n != null) {
1572: setToplevelTransientFor(n, this , false, false);
1573: }
1574: }
1575:
1576: /*
1577: * Removes the TRANSIENT_FOR hint from the given top-level window.
1578: * If window or transientForWindow are embedded frames, the containing
1579: * top-level windows are used.
1580: *
1581: * @param window specifies the top-level window that the hint
1582: * is to be removed from
1583: */
1584: private static void removeTransientForHint(XWindowPeer window) {
1585: XAtom XA_WM_TRANSIENT_FOR = XAtom
1586: .get(XAtom.XA_WM_TRANSIENT_FOR);
1587: long bpw = window.getWindow();
1588: while (!XlibUtil.isToplevelWindow(bpw)
1589: && !XlibUtil.isXAWTToplevelWindow(bpw)) {
1590: bpw = XlibUtil.getParentWindow(bpw);
1591: }
1592: XlibWrapper.XDeleteProperty(XToolkit.getDisplay(), bpw,
1593: XA_WM_TRANSIENT_FOR.getAtom());
1594: window.curRealTransientFor = null;
1595: }
1596:
1597: /*
1598: * When a modal dialog is shown, all its blocked windows are lined up into
1599: * a chain in such a way that each window is a transient_for window for
1600: * the next one. That allows us to keep the modal dialog above all its
1601: * blocked windows (even if there are some another modal dialogs between
1602: * them).
1603: * This method adds this top-level window to the chain of the given modal
1604: * dialog. To keep the current relative z-order, we should use the
1605: * XQueryTree to find the place to insert this window to. As each window
1606: * can be blocked by only one modal dialog (such checks are performed in
1607: * shared code), both this and blockerPeer are on the top of their chains
1608: * (chains may be empty).
1609: * If this window is a modal dialog and has its own chain, these chains are
1610: * merged according to the current z-order (XQueryTree is used again).
1611: * Below are some simple examples (z-order is from left to right, -- is
1612: * modal blocking).
1613: *
1614: * Example 0:
1615: * T (current chain of this, no windows are blocked by this)
1616: * W1---B (current chain of blockerPeer, W2 is blocked by blockerPeer)
1617: * Result is:
1618: * W1-T-B (merged chain, all the windows are blocked by blockerPeer)
1619: *
1620: * Example 1:
1621: * W1-T (current chain of this, W1 is blocked by this)
1622: * W2-B (current chain of blockerPeer, W2 is blocked by blockerPeer)
1623: * Result is:
1624: * W1-T-W2-B (merged chain, all the windows are blocked by blockerPeer)
1625: *
1626: * Example 2:
1627: * W1----T (current chain of this, W1 is blocked by this)
1628: * W2---B (current chain of blockerPeer, W2 is blocked by blockerPeer)
1629: * Result is:
1630: * W1-W2-T-B (merged chain, all the windows are blocked by blockerPeer)
1631: *
1632: * This method should be called under the AWT lock.
1633: *
1634: * @see #removeFromTransientFors
1635: * @see #setModalBlocked
1636: */
1637: private void addToTransientFors(XDialogPeer blockerPeer) {
1638: addToTransientFors(blockerPeer, null);
1639: }
1640:
1641: private void addToTransientFors(XDialogPeer blockerPeer,
1642: Vector<XWindowPeer> javaToplevels) {
1643: // blockerPeer chain iterator
1644: XWindowPeer blockerChain = blockerPeer;
1645: while (blockerChain.prevTransientFor != null) {
1646: blockerChain = blockerChain.prevTransientFor;
1647: }
1648: // this window chain iterator
1649: // each window can be blocked no more than once, so this window
1650: // is on top of its chain
1651: XWindowPeer this Chain = this ;
1652: while (this Chain.prevTransientFor != null) {
1653: this Chain = this Chain.prevTransientFor;
1654: }
1655: // if there are no windows blocked by modalBlocker, simply add this window
1656: // and its chain to blocker's chain
1657: if (blockerChain == blockerPeer) {
1658: setToplevelTransientFor(blockerPeer, this , true, false);
1659: } else {
1660: // Collect all the Java top-levels, if required
1661: if (javaToplevels == null) {
1662: javaToplevels = collectJavaToplevels();
1663: }
1664: // merged chain tail
1665: XWindowPeer mergedChain = null;
1666: for (XWindowPeer w : javaToplevels) {
1667: XWindowPeer prevMergedChain = mergedChain;
1668: if (w == this Chain) {
1669: if (this Chain == this ) {
1670: if (prevMergedChain != null) {
1671: setToplevelTransientFor(this ,
1672: prevMergedChain, true, false);
1673: }
1674: setToplevelTransientFor(blockerChain, this ,
1675: true, false);
1676: break;
1677: } else {
1678: mergedChain = this Chain;
1679: this Chain = this Chain.nextTransientFor;
1680: }
1681: } else if (w == blockerChain) {
1682: mergedChain = blockerChain;
1683: blockerChain = blockerChain.nextTransientFor;
1684: } else {
1685: continue;
1686: }
1687: if (prevMergedChain == null) {
1688: mergedChain.prevTransientFor = null;
1689: } else {
1690: setToplevelTransientFor(mergedChain,
1691: prevMergedChain, true, false);
1692: mergedChain.updateTransientFor();
1693: }
1694: if (blockerChain == blockerPeer) {
1695: setToplevelTransientFor(this Chain, mergedChain,
1696: true, false);
1697: setToplevelTransientFor(blockerChain, this , true,
1698: false);
1699: break;
1700: }
1701: }
1702: }
1703:
1704: XToolkit.XSync();
1705: }
1706:
1707: static void restoreTransientFor(XWindowPeer window) {
1708: XWindowPeer ownerPeer = window.getOwnerPeer();
1709: if (ownerPeer != null) {
1710: setToplevelTransientFor(window, ownerPeer, false, true);
1711: } else {
1712: removeTransientForHint(window);
1713: }
1714: }
1715:
1716: /*
1717: * When a window is modally unblocked, it should be removed from its blocker
1718: * chain, see {@link #addToTransientFor addToTransientFors} method for the
1719: * chain definition.
1720: * The problem is that we cannot simply restore window's original
1721: * TRANSIENT_FOR hint (if any) and link prevTransientFor and
1722: * nextTransientFor together as the whole chain could be created as a merge
1723: * of two other chains in addToTransientFors. In that case, if this window is
1724: * a modal dialog, it would lost all its own chain, if we simply exclude it
1725: * from the chain.
1726: * The correct behaviour of this method should be to split the chain, this
1727: * window is currently in, into two chains. First chain is this window own
1728: * chain (i. e. all the windows blocked by this one, directly or indirectly),
1729: * if any, and the rest windows from the current chain.
1730: *
1731: * Example:
1732: * Original state:
1733: * W1-B1 (window W1 is blocked by B1)
1734: * W2-B2 (window W2 is blocked by B2)
1735: * B3 is shown and blocks B1 and B2:
1736: * W1-W2-B1-B2-B3 (a single chain after B1.addToTransientFors() and B2.addToTransientFors())
1737: * If we then unblock B1, the state should be:
1738: * W1-B1 (window W1 is blocked by B1)
1739: * W2-B2-B3 (window W2 is blocked by B2 and B2 is blocked by B3)
1740: *
1741: * This method should be called under the AWT lock.
1742: *
1743: * @see #addToTransientFors
1744: * @see #setModalBlocked
1745: */
1746: private void removeFromTransientFors() {
1747: // the head of the chain of this window
1748: XWindowPeer this Chain = this ;
1749: // the head of the current chain
1750: // nextTransientFor is always not null as this window is in the chain
1751: XWindowPeer otherChain = nextTransientFor;
1752: // the set of blockers in this chain: if this dialog blocks some other
1753: // modal dialogs, their blocked windows should stay in this dialog's chain
1754: Set<XWindowPeer> this ChainBlockers = new HashSet<XWindowPeer>();
1755: this ChainBlockers.add(this );
1756: // current chain iterator in the order from next to prev
1757: XWindowPeer chainToSplit = prevTransientFor;
1758: while (chainToSplit != null) {
1759: XWindowPeer blocker = (XWindowPeer) ComponentAccessor
1760: .getPeer(chainToSplit.modalBlocker);
1761: if (this ChainBlockers.contains(blocker)) {
1762: // add to this dialog's chain
1763: setToplevelTransientFor(this Chain, chainToSplit, true,
1764: false);
1765: this Chain = chainToSplit;
1766: this ChainBlockers.add(chainToSplit);
1767: } else {
1768: // leave in the current chain
1769: setToplevelTransientFor(otherChain, chainToSplit, true,
1770: false);
1771: otherChain = chainToSplit;
1772: }
1773: chainToSplit = chainToSplit.prevTransientFor;
1774: }
1775: restoreTransientFor(this Chain);
1776: this Chain.prevTransientFor = null;
1777: restoreTransientFor(otherChain);
1778: otherChain.prevTransientFor = null;
1779: nextTransientFor = null;
1780:
1781: XToolkit.XSync();
1782: }
1783:
1784: boolean isModalBlocked() {
1785: return modalBlocker != null;
1786: }
1787:
1788: static Window getDecoratedOwner(Window window) {
1789: while ((null != window)
1790: && !(window instanceof Frame || window instanceof Dialog)) {
1791: window = (Window) ComponentAccessor
1792: .getParent_NoClientCode(window);
1793: }
1794: return window;
1795: }
1796:
1797: public boolean requestWindowFocus() {
1798: return requestWindowFocus(0, false);
1799: }
1800:
1801: public boolean requestWindowFocus(long time, boolean timeProvided) {
1802: focusLog.fine("Request for window focus");
1803: // If this is Frame or Dialog we can't assure focus request success - but we still can try
1804: // If this is Window and its owner Frame is active we can be sure request succedded.
1805: Window win = (Window) target;
1806: Window owner = XWindowPeer.getDecoratedOwner(win);
1807:
1808: final Window activeWindow = XWindowPeer
1809: .getDecoratedOwner(XKeyboardFocusManagerPeer
1810: .getCurrentNativeFocusedWindow());
1811: if (activeWindow == owner) {
1812: focusLog
1813: .fine("Parent window is active - generating focus for this window");
1814: handleWindowFocusInSync(-1);
1815: return true;
1816: } else {
1817: focusLog.fine("Parent window is not active");
1818: }
1819: ComponentPeer peer = ComponentAccessor.getPeer(owner);
1820: if (peer instanceof XDecoratedPeer) {
1821: XDecoratedPeer wpeer = (XDecoratedPeer) peer;
1822: if (wpeer.requestWindowFocus(this , time, timeProvided)) {
1823: focusLog
1824: .fine("Parent window accepted focus request - generating focus for this window");
1825: return true;
1826: }
1827: }
1828: focusLog
1829: .fine("Denied - parent window is not active and didn't accept focus request");
1830: return false;
1831: }
1832:
1833: // This method is to be overriden in XDecoratedPeer.
1834: void setActualFocusedWindow(XWindowPeer actualFocusedWindow) {
1835: }
1836:
1837: public void xSetVisible(boolean visible) {
1838: if (log.isLoggable(Level.FINE))
1839: log.fine("Setting visible on " + this + " to " + visible);
1840: XToolkit.awtLock();
1841: try {
1842: this .visible = visible;
1843: if (visible) {
1844: XlibWrapper.XMapRaised(XToolkit.getDisplay(),
1845: getWindow());
1846: } else {
1847: XlibWrapper.XUnmapWindow(XToolkit.getDisplay(),
1848: getWindow());
1849: }
1850: XlibWrapper.XFlush(XToolkit.getDisplay());
1851: } finally {
1852: XToolkit.awtUnlock();
1853: }
1854: }
1855:
1856: private int dropTargetCount = 0;
1857:
1858: public synchronized void addDropTarget() {
1859: if (dropTargetCount == 0) {
1860: long window = getWindow();
1861: if (window != 0) {
1862: XDropTargetRegistry.getRegistry().registerDropSite(
1863: window);
1864: }
1865: }
1866: dropTargetCount++;
1867: }
1868:
1869: public synchronized void removeDropTarget() {
1870: dropTargetCount--;
1871: if (dropTargetCount == 0) {
1872: long window = getWindow();
1873: if (window != 0) {
1874: XDropTargetRegistry.getRegistry().unregisterDropSite(
1875: window);
1876: }
1877: }
1878: }
1879:
1880: void addRootPropertyEventDispatcher() {
1881: if (rootPropertyEventDispatcher == null) {
1882: rootPropertyEventDispatcher = new XEventDispatcher() {
1883: public void dispatchEvent(XEvent ev) {
1884: if (ev.get_type() == PropertyNotify) {
1885: handleRootPropertyNotify(ev);
1886: }
1887: }
1888: };
1889: XlibWrapper.XSelectInput(XToolkit.getDisplay(), XToolkit
1890: .getDefaultRootWindow(),
1891: XlibWrapper.PropertyChangeMask);
1892: XToolkit.addEventDispatcher(
1893: XToolkit.getDefaultRootWindow(),
1894: rootPropertyEventDispatcher);
1895: }
1896: }
1897:
1898: void removeRootPropertyEventDispatcher() {
1899: if (rootPropertyEventDispatcher != null) {
1900: XToolkit.removeEventDispatcher(XToolkit
1901: .getDefaultRootWindow(),
1902: rootPropertyEventDispatcher);
1903: rootPropertyEventDispatcher = null;
1904: }
1905: }
1906:
1907: public void updateFocusableWindowState() {
1908: cachedFocusableWindow = isFocusableWindow();
1909: }
1910:
1911: XAtom XA_NET_WM_STATE;
1912: XAtomList net_wm_state;
1913:
1914: public XAtomList getNETWMState() {
1915: if (net_wm_state == null) {
1916: net_wm_state = XA_NET_WM_STATE
1917: .getAtomListPropertyList(this );
1918: }
1919: return net_wm_state;
1920: }
1921:
1922: public void setNETWMState(XAtomList state) {
1923: net_wm_state = state;
1924: if (state != null) {
1925: XA_NET_WM_STATE.setAtomListProperty(this , state);
1926: }
1927: }
1928:
1929: public PropMwmHints getMWMHints() {
1930: if (mwm_hints == null) {
1931: mwm_hints = new PropMwmHints();
1932: if (!XWM.XA_MWM_HINTS.getAtomData(getWindow(),
1933: mwm_hints.pData, PROP_MWM_HINTS_ELEMENTS)) {
1934: mwm_hints.zero();
1935: }
1936: }
1937: return mwm_hints;
1938: }
1939:
1940: public void setMWMHints(PropMwmHints hints) {
1941: mwm_hints = hints;
1942: if (hints != null) {
1943: XWM.XA_MWM_HINTS.setAtomData(getWindow(), mwm_hints.pData,
1944: PROP_MWM_HINTS_ELEMENTS);
1945: }
1946: }
1947:
1948: private Insets wm_set_insets;
1949:
1950: public Insets getWMSetInsets(XAtom changedAtom) {
1951: if (isEmbedded()) {
1952: return null;
1953: }
1954:
1955: if (wm_set_insets != null) {
1956: return wm_set_insets;
1957: }
1958:
1959: if (changedAtom == null) {
1960: wm_set_insets = XWM.getInsetsFromExtents(getWindow());
1961: } else {
1962: wm_set_insets = XWM.getInsetsFromProp(getWindow(),
1963: changedAtom);
1964: }
1965:
1966: insLog.log(Level.FINER, "FRAME_EXTENTS: {0}",
1967: new Object[] { wm_set_insets });
1968:
1969: if (wm_set_insets != null) {
1970: handleWMSetInsets(wm_set_insets);
1971: }
1972: return wm_set_insets;
1973: }
1974:
1975: protected void handleWMSetInsets(Insets newInsets) {
1976: wm_set_insets = (Insets) newInsets.clone();
1977: }
1978:
1979: public void resetWMSetInsets() {
1980: wm_set_insets = null;
1981: }
1982:
1983: protected synchronized void updateDropTarget() {
1984: if (dropTargetCount > 0) {
1985: long window = getWindow();
1986: if (window != 0) {
1987: XDropTargetRegistry.getRegistry().unregisterDropSite(
1988: window);
1989: XDropTargetRegistry.getRegistry().registerDropSite(
1990: window);
1991: }
1992: }
1993: }
1994:
1995: public void setGrab(boolean grab) {
1996: this .grab = grab;
1997: if (grab) {
1998: pressTarget = this ;
1999: grabInput();
2000: } else {
2001: ungrabInput();
2002: }
2003: }
2004:
2005: public boolean isGrabbed() {
2006: return grab && XAwtState.getGrabWindow() == this ;
2007: }
2008:
2009: public void handleXCrossingEvent(XEvent xev) {
2010: XCrossingEvent xce = xev.get_xcrossing();
2011: if (grabLog.isLoggable(Level.FINE)) {
2012: grabLog.log(Level.FINE,
2013: "{0}, when grabbed {1}, contains {2}",
2014: new Object[] {
2015: xce,
2016: isGrabbed(),
2017: containsGlobal(xce.get_x_root(), xce
2018: .get_y_root()) });
2019: }
2020: if (isGrabbed()) {
2021: // When window is grabbed, all events are dispatched to
2022: // it. Retarget them to the corresponding windows (notice
2023: // that XBaseWindow.dispatchEvent does the opposite
2024: // translation)
2025: // Note that we need to retarget XCrossingEvents to content window
2026: // since it generates MOUSE_ENTERED/MOUSE_EXITED for frame and dialog.
2027: // (fix for 6390326)
2028: XBaseWindow target = XToolkit.windowToXWindow(xce
2029: .get_window());
2030: grabLog.log(Level.FINER, " - Grab event target {0}",
2031: new Object[] { target });
2032: if (target != null && target != this ) {
2033: target.dispatchEvent(xev);
2034: return;
2035: }
2036: }
2037: super .handleXCrossingEvent(xev);
2038: }
2039:
2040: public void handleMotionNotify(XEvent xev) {
2041: XMotionEvent xme = xev.get_xmotion();
2042: if (grabLog.isLoggable(Level.FINE)) {
2043: grabLog.log(Level.FINER,
2044: "{0}, when grabbed {1}, contains {2}",
2045: new Object[] {
2046: xme,
2047: isGrabbed(),
2048: containsGlobal(xme.get_x_root(), xme
2049: .get_y_root()) });
2050: }
2051: if (isGrabbed()) {
2052: boolean dragging = (xme.get_state() & (Button1Mask
2053: | Button2Mask | Button3Mask)) != 0;
2054: // When window is grabbed, all events are dispatched to
2055: // it. Retarget them to the corresponding windows (notice
2056: // that XBaseWindow.dispatchEvent does the opposite
2057: // translation)
2058: XBaseWindow target = XToolkit.windowToXWindow(xme
2059: .get_window());
2060: if (dragging && pressTarget != target) {
2061: // for some reasons if we grab input MotionNotify for drag is reported with target
2062: // to underlying window, not to window on which we have initiated drag
2063: // so we need to retarget them. Here I use simplified logic which retarget all
2064: // such events to source of mouse press (or the grabber). It helps with fix for 6390326.
2065: // So, I do not want to implement complicated logic for better retargeting.
2066: target = pressTarget.isVisible() ? pressTarget : this ;
2067: xme.set_window(target.getWindow());
2068: xme.set_x(xme.get_x_root() - target.getX());
2069: xme.set_y(xme.get_y_root() - target.getY());
2070: }
2071: grabLog.log(Level.FINER, " - Grab event target {0}",
2072: new Object[] { target });
2073: if (target != null) {
2074: if (target != getContentXWindow() && target != this ) {
2075: target.dispatchEvent(xev);
2076: return;
2077: }
2078: }
2079:
2080: // note that we need to pass dragging events to the grabber (6390326)
2081: // see comment above for more inforamtion.
2082: if (!containsGlobal(xme.get_x_root(), xme.get_y_root())
2083: && !dragging) {
2084: // Outside of Java
2085: return;
2086: }
2087: }
2088: super .handleMotionNotify(xev);
2089: }
2090:
2091: // we use it to retarget mouse drag and mouse release during grab.
2092: private XBaseWindow pressTarget = this ;
2093:
2094: public void handleButtonPressRelease(XEvent xev) {
2095: XButtonEvent xbe = xev.get_xbutton();
2096: if (grabLog.isLoggable(Level.FINE)) {
2097: grabLog
2098: .log(
2099: Level.FINE,
2100: "{0}, when grabbed {1}, contains {2} ({3}, {4}, {5}x{6})",
2101: new Object[] {
2102: xbe,
2103: isGrabbed(),
2104: containsGlobal(xbe.get_x_root(),
2105: xbe.get_y_root()),
2106: getAbsoluteX(), getAbsoluteY(),
2107: getWidth(), getHeight() });
2108: }
2109: if (isGrabbed()) {
2110: // When window is grabbed, all events are dispatched to
2111: // it. Retarget them to the corresponding windows (notice
2112: // that XBaseWindow.dispatchEvent does the opposite
2113: // translation)
2114: XBaseWindow target = XToolkit.windowToXWindow(xbe
2115: .get_window());
2116: try {
2117: grabLog
2118: .log(
2119: Level.FINER,
2120: " - Grab event target {0} (press target {1})",
2121: new Object[] { target, pressTarget });
2122: if (xbe.get_type() == XConstants.ButtonPress
2123: && xbe.get_button() == XlibWrapper.Button1) {
2124: // need to keep it to retarget mouse release
2125: pressTarget = target;
2126: } else if (xbe.get_type() == XConstants.ButtonRelease
2127: && xbe.get_button() == XlibWrapper.Button1
2128: && pressTarget != target) {
2129: // during grab we do receive mouse release on different component (not on the source
2130: // of mouse press). So we need to retarget it.
2131: // see 6390326 for more information.
2132: target = pressTarget.isVisible() ? pressTarget
2133: : this ;
2134: xbe.set_window(target.getWindow());
2135: xbe.set_x(xbe.get_x_root() - target.getX());
2136: xbe.set_y(xbe.get_y_root() - target.getY());
2137: pressTarget = this ;
2138: }
2139: if (target != null && target != getContentXWindow()
2140: && target != this ) {
2141: target.dispatchEvent(xev);
2142: return;
2143: }
2144: } finally {
2145: if (target != null) {
2146: // Target is either us or our content window -
2147: // check that event is inside. 'Us' in case of
2148: // shell will mean that this will also filter out press on title
2149: if ((target == this || target == getContentXWindow())
2150: && !containsGlobal(xbe.get_x_root(), xbe
2151: .get_y_root())) {
2152: // Outside this toplevel hierarchy
2153: // According to the specification of UngrabEvent, post it
2154: // when press occurs outside of the window and not on its owned windows
2155: grabLog
2156: .log(
2157: Level.FINE,
2158: "Generating UngrabEvent on {0} because not inside of shell",
2159: this );
2160: postEventToEventQueue(new sun.awt.UngrabEvent(
2161: getEventSource()));
2162: return;
2163: }
2164: // First, get the toplevel
2165: XWindowPeer toplevel = target.getToplevelXWindow();
2166: if (toplevel != null) {
2167: Window w = (Window) toplevel.target;
2168: while (w != null && toplevel != this
2169: && !(toplevel instanceof XDialogPeer)) {
2170: w = (Window) ComponentAccessor
2171: .getParent_NoClientCode(w);
2172: if (w != null) {
2173: toplevel = (XWindowPeer) ComponentAccessor
2174: .getPeer(w);
2175: }
2176: }
2177: if (w == null
2178: || (w != this .target && w instanceof Dialog)) {
2179: // toplevel == null - outside of
2180: // hierarchy, toplevel is Dialog - should
2181: // send ungrab (but shouldn't for Window)
2182: grabLog
2183: .log(
2184: Level.FINE,
2185: "Generating UngrabEvent on {0} because hierarchy ended",
2186: this );
2187: postEventToEventQueue(new sun.awt.UngrabEvent(
2188: getEventSource()));
2189: }
2190: } else {
2191: // toplevel is null - outside of hierarchy
2192: grabLog
2193: .log(
2194: Level.FINE,
2195: "Generating UngrabEvent on {0} because toplevel is null",
2196: this );
2197: postEventToEventQueue(new sun.awt.UngrabEvent(
2198: getEventSource()));
2199: return;
2200: }
2201: } else {
2202: // target doesn't map to XAWT window - outside of hierarchy
2203: grabLog
2204: .log(
2205: Level.FINE,
2206: "Generating UngrabEvent on because target is null {0}",
2207: this );
2208: postEventToEventQueue(new sun.awt.UngrabEvent(
2209: getEventSource()));
2210: return;
2211: }
2212: }
2213: }
2214: super.handleButtonPressRelease(xev);
2215: }
2216: }
|