0001: /*
0002: * Copyright 2003-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:
0026: package sun.awt.X11;
0027:
0028: import java.awt.*;
0029: import sun.awt.*;
0030: import java.util.logging.*;
0031: import java.util.*;
0032:
0033: public class XBaseWindow implements XConstants, XUtilConstants {
0034: private static final Logger log = Logger
0035: .getLogger("sun.awt.X11.XBaseWindow");
0036: private static final Logger insLog = Logger
0037: .getLogger("sun.awt.X11.insets.XBaseWindow");
0038: private static final Logger eventLog = Logger
0039: .getLogger("sun.awt.X11.event.XBaseWindow");
0040: private static final Logger focusLog = Logger
0041: .getLogger("sun.awt.X11.focus.XBaseWindow");
0042: private static final Logger grabLog = Logger
0043: .getLogger("sun.awt.X11.grab.XBaseWindow");
0044:
0045: public static final String PARENT_WINDOW = "parent window", // parent window, Long
0046: BOUNDS = "bounds", // bounds of the window, Rectangle
0047: OVERRIDE_REDIRECT = "overrideRedirect", // override_redirect setting, Boolean
0048: EVENT_MASK = "event mask", // event mask, Integer
0049: VALUE_MASK = "value mask", // value mask, Long
0050: BORDER_PIXEL = "border pixel", // border pixel value, Integer
0051: COLORMAP = "color map", // color map, Long
0052: DEPTH = "visual depth", // depth, Integer
0053: VISUAL_CLASS = "visual class", // visual class, Integer
0054: VISUAL = "visual", // visual, Long
0055: EMBEDDED = "embedded", // is embedded?, Boolean
0056: DELAYED = "delayed", // is creation delayed?, Boolean
0057: PARENT = "parent", // parent peer
0058: BACKGROUND_PIXMAP = "pixmap", // background pixmap
0059: VISIBLE = "visible", // whether it is visible by default
0060: SAVE_UNDER = "save under", // save content under this window
0061: BACKING_STORE = "backing store", // enables double buffering
0062: BIT_GRAVITY = "bit gravity"; // copy old content on geometry change
0063: private XCreateWindowParams delayedParams;
0064:
0065: Set<Long> children = new HashSet<Long>();
0066: long window;
0067: boolean visible;
0068: boolean mapped;
0069: boolean embedded;
0070: Rectangle maxBounds;
0071: volatile XBaseWindow parentWindow;
0072:
0073: private boolean disposed;
0074:
0075: private long screen;
0076: private XSizeHints hints;
0077: private XWMHints wmHints;
0078:
0079: final static int MIN_SIZE = 1;
0080: final static int DEF_LOCATION = 1;
0081:
0082: private static XAtom wm_client_leader;
0083:
0084: static enum InitialiseState {
0085: INITIALISING, NOT_INITIALISED, INITIALISED, FAILED_INITIALISATION
0086: };
0087:
0088: private InitialiseState initialising;
0089:
0090: int x;
0091: int y;
0092: int width;
0093: int height;
0094:
0095: void awtLock() {
0096: XToolkit.awtLock();
0097: }
0098:
0099: void awtUnlock() {
0100: XToolkit.awtUnlock();
0101: }
0102:
0103: void awtLockNotifyAll() {
0104: XToolkit.awtLockNotifyAll();
0105: }
0106:
0107: void awtLockWait() throws InterruptedException {
0108: XToolkit.awtLockWait();
0109: }
0110:
0111: // To prevent errors from overriding obsolete methods
0112: protected final void init(long parentWindow, Rectangle bounds) {
0113: }
0114:
0115: protected final void preInit() {
0116: }
0117:
0118: protected final void postInit() {
0119: }
0120:
0121: // internal lock for synchronizing state changes and paint calls, initialized in preInit.
0122: // the order with other locks: AWTLock -> stateLock
0123: static class StateLock extends Object {
0124: }
0125:
0126: protected StateLock state_lock;
0127:
0128: /**
0129: * Called for delayed inits during construction
0130: */
0131: void instantPreInit(XCreateWindowParams params) {
0132: state_lock = new StateLock();
0133: initialising = InitialiseState.NOT_INITIALISED;
0134: }
0135:
0136: /**
0137: * Called before window creation, descendants should override to initialize the data,
0138: * initialize params.
0139: */
0140: void preInit(XCreateWindowParams params) {
0141: state_lock = new StateLock();
0142: initialising = InitialiseState.NOT_INITIALISED;
0143: embedded = Boolean.TRUE.equals(params.get(EMBEDDED));
0144: visible = Boolean.TRUE.equals(params.get(VISIBLE));
0145:
0146: Object parent = params.get(PARENT);
0147: if (parent instanceof XBaseWindow) {
0148: parentWindow = (XBaseWindow) parent;
0149: } else {
0150: Long parentWindowID = (Long) params.get(PARENT_WINDOW);
0151: if (parentWindowID != null) {
0152: parentWindow = XToolkit.windowToXWindow(parentWindowID);
0153: }
0154: }
0155:
0156: Long eventMask = (Long) params.get(EVENT_MASK);
0157: if (eventMask != null) {
0158: long mask = eventMask.longValue();
0159: mask |= SubstructureNotifyMask;
0160: params.put(EVENT_MASK, mask);
0161: }
0162:
0163: screen = -1;
0164: }
0165:
0166: /**
0167: * Called after window creation, descendants should override to initialize Window
0168: * with class-specific values and perform post-initialization actions.
0169: */
0170: void postInit(XCreateWindowParams params) {
0171: if (log.isLoggable(Level.FINE))
0172: log.fine("WM name is " + getWMName());
0173: updateWMName();
0174:
0175: // Set WM_CLIENT_LEADER property
0176: initClientLeader();
0177: }
0178:
0179: /**
0180: * Creates window using parameters <code>params</code>
0181: * If params contain flag DELAYED doesn't do anything.
0182: * Note: Descendants can call this method to create the window
0183: * at the time different to instance construction.
0184: */
0185: protected final void init(XCreateWindowParams params) {
0186: awtLock();
0187: initialising = InitialiseState.INITIALISING;
0188: awtUnlock();
0189:
0190: try {
0191: if (!Boolean.TRUE.equals(params.get(DELAYED))) {
0192: preInit(params);
0193: create(params);
0194: postInit(params);
0195: } else {
0196: instantPreInit(params);
0197: delayedParams = params;
0198: }
0199: awtLock();
0200: initialising = InitialiseState.INITIALISED;
0201: awtLockNotifyAll();
0202: awtUnlock();
0203: } catch (RuntimeException re) {
0204: awtLock();
0205: initialising = InitialiseState.FAILED_INITIALISATION;
0206: awtLockNotifyAll();
0207: awtUnlock();
0208: throw re;
0209: } catch (Throwable t) {
0210: log.log(Level.WARNING,
0211: "Exception during peer initialization", t);
0212: awtLock();
0213: initialising = InitialiseState.FAILED_INITIALISATION;
0214: awtLockNotifyAll();
0215: awtUnlock();
0216: }
0217: }
0218:
0219: public boolean checkInitialised() {
0220: awtLock();
0221: try {
0222: switch (initialising) {
0223: case INITIALISED:
0224: return true;
0225: case INITIALISING:
0226: try {
0227: while (initialising != InitialiseState.INITIALISED) {
0228: awtLockWait();
0229: }
0230: } catch (InterruptedException ie) {
0231: return false;
0232: }
0233: return true;
0234: case NOT_INITIALISED:
0235: case FAILED_INITIALISATION:
0236: return false;
0237: default:
0238: return false;
0239: }
0240: } finally {
0241: awtUnlock();
0242: }
0243: }
0244:
0245: /*
0246: * Creates an invisible InputOnly window without an associated Component.
0247: */
0248: XBaseWindow() {
0249: this (new XCreateWindowParams());
0250: }
0251:
0252: /**
0253: * Creates normal child window
0254: */
0255: XBaseWindow(long parentWindow, Rectangle bounds) {
0256: this (new XCreateWindowParams(new Object[] { BOUNDS, bounds,
0257: PARENT_WINDOW, Long.valueOf(parentWindow) }));
0258: }
0259:
0260: /**
0261: * Creates top-level window
0262: */
0263: XBaseWindow(Rectangle bounds) {
0264: this (new XCreateWindowParams(new Object[] { BOUNDS, bounds }));
0265: }
0266:
0267: public XBaseWindow(XCreateWindowParams params) {
0268: init(params);
0269: }
0270:
0271: /* This create is used by the XEmbeddedFramePeer since it has to create the window
0272: as a child of the netscape window. This netscape window is passed in as wid */
0273: XBaseWindow(long parentWindow) {
0274: this (new XCreateWindowParams(new Object[] { PARENT_WINDOW,
0275: Long.valueOf(parentWindow), EMBEDDED, Boolean.TRUE }));
0276: }
0277:
0278: /**
0279: * Verifies that all required parameters are set. If not, sets them to default values.
0280: * Verifies values of critical parameters, adjust their values when needed.
0281: * @throws IllegalArgumentException if params is null
0282: */
0283: protected void checkParams(XCreateWindowParams params) {
0284: if (params == null) {
0285: throw new IllegalArgumentException(
0286: "Window creation parameters are null");
0287: }
0288: params.putIfNull(PARENT_WINDOW, Long.valueOf(XToolkit
0289: .getDefaultRootWindow()));
0290: params.putIfNull(BOUNDS, new Rectangle(DEF_LOCATION,
0291: DEF_LOCATION, MIN_SIZE, MIN_SIZE));
0292: params.putIfNull(DEPTH, Integer
0293: .valueOf((int) XlibWrapper.CopyFromParent));
0294: params.putIfNull(VISUAL, Long
0295: .valueOf(XlibWrapper.CopyFromParent));
0296: params.putIfNull(VISUAL_CLASS, Integer
0297: .valueOf((int) XlibWrapper.InputOnly));
0298: params.putIfNull(VALUE_MASK, Long
0299: .valueOf(XlibWrapper.CWEventMask));
0300: Rectangle bounds = (Rectangle) params.get(BOUNDS);
0301: bounds.width = Math.max(MIN_SIZE, bounds.width);
0302: bounds.height = Math.max(MIN_SIZE, bounds.height);
0303:
0304: Long eventMaskObj = (Long) params.get(EVENT_MASK);
0305: long eventMask = eventMaskObj != null ? eventMaskObj
0306: .longValue() : 0;
0307: // We use our own synthetic grab see XAwtState.getGrabWindow()
0308: // (see X vol. 1, 8.3.3.2)
0309: eventMask |= PropertyChangeMask | OwnerGrabButtonMask;
0310: params.put(EVENT_MASK, Long.valueOf(eventMask));
0311: }
0312:
0313: /**
0314: * Creates window with parameters specified by <code>params</code>
0315: * @see #init
0316: */
0317: private final void create(XCreateWindowParams params) {
0318: XToolkit.awtLock();
0319: try {
0320: XSetWindowAttributes xattr = new XSetWindowAttributes();
0321: try {
0322: checkParams(params);
0323:
0324: long value_mask = ((Long) params.get(VALUE_MASK))
0325: .longValue();
0326:
0327: Long eventMask = (Long) params.get(EVENT_MASK);
0328: xattr.set_event_mask(eventMask.longValue());
0329: value_mask |= XlibWrapper.CWEventMask;
0330:
0331: Long border_pixel = (Long) params.get(BORDER_PIXEL);
0332: if (border_pixel != null) {
0333: xattr.set_border_pixel(border_pixel.longValue());
0334: value_mask |= XlibWrapper.CWBorderPixel;
0335: }
0336:
0337: Long colormap = (Long) params.get(COLORMAP);
0338: if (colormap != null) {
0339: xattr.set_colormap(colormap.longValue());
0340: value_mask |= XlibWrapper.CWColormap;
0341: }
0342: Long background_pixmap = (Long) params
0343: .get(BACKGROUND_PIXMAP);
0344: if (background_pixmap != null) {
0345: xattr.set_background_pixmap(background_pixmap
0346: .longValue());
0347: value_mask |= XlibWrapper.CWBackPixmap;
0348: }
0349:
0350: Long parentWindow = (Long) params.get(PARENT_WINDOW);
0351: Rectangle bounds = (Rectangle) params.get(BOUNDS);
0352: Integer depth = (Integer) params.get(DEPTH);
0353: Integer visual_class = (Integer) params
0354: .get(VISUAL_CLASS);
0355: Long visual = (Long) params.get(VISUAL);
0356: Boolean overrideRedirect = (Boolean) params
0357: .get(OVERRIDE_REDIRECT);
0358: if (overrideRedirect != null) {
0359: xattr.set_override_redirect(overrideRedirect
0360: .booleanValue());
0361: value_mask |= XlibWrapper.CWOverrideRedirect;
0362: }
0363:
0364: Boolean saveUnder = (Boolean) params.get(SAVE_UNDER);
0365: if (saveUnder != null) {
0366: xattr.set_save_under(saveUnder.booleanValue());
0367: value_mask |= XlibWrapper.CWSaveUnder;
0368: }
0369:
0370: Integer backingStore = (Integer) params
0371: .get(BACKING_STORE);
0372: if (backingStore != null) {
0373: xattr.set_backing_store(backingStore.intValue());
0374: value_mask |= XlibWrapper.CWBackingStore;
0375: }
0376:
0377: Integer bitGravity = (Integer) params.get(BIT_GRAVITY);
0378: if (bitGravity != null) {
0379: xattr.set_bit_gravity(bitGravity.intValue());
0380: value_mask |= XlibWrapper.CWBitGravity;
0381: }
0382:
0383: if (log.isLoggable(Level.FINE)) {
0384: log.fine("Creating window for " + this
0385: + " with the following attributes: \n"
0386: + params);
0387: }
0388: window = XlibWrapper.XCreateWindow(XToolkit
0389: .getDisplay(), parentWindow.longValue(),
0390: bounds.x, bounds.y, // location
0391: bounds.width, bounds.height, // size
0392: 0, // border
0393: depth.intValue(), // depth
0394: visual_class.intValue(), // class
0395: visual.longValue(), // visual
0396: value_mask, // value mask
0397: xattr.pData); // attributes
0398:
0399: if (window == 0) {
0400: throw new IllegalStateException(
0401: "Couldn't create window because of wrong parameters. Run with NOISY_AWT to see details");
0402: }
0403: XToolkit.addToWinMap(window, this );
0404: } finally {
0405: xattr.dispose();
0406: }
0407: } finally {
0408: XToolkit.awtUnlock();
0409: }
0410: }
0411:
0412: public XCreateWindowParams getDelayedParams() {
0413: return delayedParams;
0414: }
0415:
0416: protected String getWMName() {
0417: return XToolkit.getCorrectXIDString(getClass().getName());
0418: }
0419:
0420: protected void initClientLeader() {
0421: XToolkit.awtLock();
0422: try {
0423: if (wm_client_leader == null) {
0424: wm_client_leader = XAtom.get("WM_CLIENT_LEADER");
0425: }
0426: wm_client_leader.setWindowProperty(this ,
0427: getXAWTRootWindow());
0428: } finally {
0429: XToolkit.awtUnlock();
0430: }
0431: }
0432:
0433: static XRootWindow getXAWTRootWindow() {
0434: return XRootWindow.getInstance();
0435: }
0436:
0437: void destroy() {
0438: XToolkit.awtLock();
0439: try {
0440: if (hints != null) {
0441: XlibWrapper.XFree(hints.pData);
0442: hints = null;
0443: }
0444: XToolkit.removeFromWinMap(getWindow(), this );
0445: XlibWrapper.XDestroyWindow(XToolkit.getDisplay(),
0446: getWindow());
0447: if (XPropertyCache.isCachingSupported()) {
0448: XPropertyCache.clearCache(window);
0449: }
0450: window = -1;
0451: if (!isDisposed()) {
0452: setDisposed(true);
0453: }
0454:
0455: XAwtState.getGrabWindow(); // Magic - getGrabWindow clear state if grabbing window is disposed of.
0456: } finally {
0457: XToolkit.awtUnlock();
0458: }
0459: }
0460:
0461: void flush() {
0462: XToolkit.awtLock();
0463: try {
0464: XlibWrapper.XFlush(XToolkit.getDisplay());
0465: } finally {
0466: XToolkit.awtUnlock();
0467: }
0468: }
0469:
0470: /**
0471: * Helper function to set W
0472: */
0473: public final void setWMHints(XWMHints hints) {
0474: XToolkit.awtLock();
0475: try {
0476: XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(),
0477: hints.pData);
0478: } finally {
0479: XToolkit.awtUnlock();
0480: }
0481: }
0482:
0483: public XWMHints getWMHints() {
0484: if (wmHints == null) {
0485: wmHints = new XWMHints(XlibWrapper.XAllocWMHints());
0486: // XlibWrapper.XGetWMHints(XToolkit.getDisplay(),
0487: // getWindow(),
0488: // wmHints.pData);
0489: }
0490: return wmHints;
0491: }
0492:
0493: /*
0494: * Call this method under AWTLock.
0495: * The lock should be acquired untill all operations with XSizeHints are completed.
0496: */
0497: public XSizeHints getHints() {
0498: if (hints == null) {
0499: long p_hints = XlibWrapper.XAllocSizeHints();
0500: hints = new XSizeHints(p_hints);
0501: // XlibWrapper.XGetWMNormalHints(XToolkit.getDisplay(), getWindow(), p_hints, XlibWrapper.larg1);
0502: // TODO: Shouldn't we listen for WM updates on this property?
0503: }
0504: return hints;
0505: }
0506:
0507: public void setSizeHints(long flags, int x, int y, int width,
0508: int height) {
0509: if (insLog.isLoggable(Level.FINER))
0510: insLog.finer("Setting hints, flags "
0511: + XlibWrapper.hintsToString(flags));
0512: XToolkit.awtLock();
0513: try {
0514: XSizeHints hints = getHints();
0515: // Note: if PPosition is not set in flags this means that
0516: // we want to reset PPosition in hints. This is necessary
0517: // for locationByPlatform functionality
0518: if ((flags & XlibWrapper.PPosition) != 0) {
0519: hints.set_x(x);
0520: hints.set_y(y);
0521: }
0522: if ((flags & XlibWrapper.PSize) != 0) {
0523: hints.set_width(width);
0524: hints.set_height(height);
0525: } else if ((hints.get_flags() & XlibWrapper.PSize) != 0) {
0526: flags |= XlibWrapper.PSize;
0527: }
0528: if ((flags & XlibWrapper.PMinSize) != 0) {
0529: hints.set_min_width(width);
0530: hints.set_min_height(height);
0531: } else if ((hints.get_flags() & XlibWrapper.PMinSize) != 0) {
0532: flags |= XlibWrapper.PMinSize;
0533: //Fix for 4320050: Minimum size for java.awt.Frame is not being enforced.
0534: //We don't need to reset minimum size if it's already set
0535: }
0536: if ((flags & XlibWrapper.PMaxSize) != 0) {
0537: if (maxBounds != null) {
0538: if (maxBounds.width != Integer.MAX_VALUE) {
0539: hints.set_max_width(maxBounds.width);
0540: } else {
0541: hints.set_max_width(XToolkit
0542: .getDefaultScreenWidth());
0543: }
0544: if (maxBounds.height != Integer.MAX_VALUE) {
0545: hints.set_max_height(maxBounds.height);
0546: } else {
0547: hints.set_max_height(XToolkit
0548: .getDefaultScreenHeight());
0549: }
0550: } else {
0551: hints.set_max_width(width);
0552: hints.set_max_height(height);
0553: }
0554: } else if ((hints.get_flags() & XlibWrapper.PMaxSize) != 0) {
0555: flags |= XlibWrapper.PMaxSize;
0556: if (maxBounds != null) {
0557: if (maxBounds.width != Integer.MAX_VALUE) {
0558: hints.set_max_width(maxBounds.width);
0559: } else {
0560: hints.set_max_width(XToolkit
0561: .getDefaultScreenWidth());
0562: }
0563: if (maxBounds.height != Integer.MAX_VALUE) {
0564: hints.set_max_height(maxBounds.height);
0565: } else {
0566: hints.set_max_height(XToolkit
0567: .getDefaultScreenHeight());
0568: }
0569: } else {
0570: // Leave intact
0571: }
0572: }
0573: flags |= XlibWrapper.PWinGravity;
0574: hints.set_flags(flags);
0575: hints.set_win_gravity((int) XlibWrapper.NorthWestGravity);
0576: if (insLog.isLoggable(Level.FINER))
0577: insLog.finer("Setting hints, resulted flags "
0578: + XlibWrapper.hintsToString(flags)
0579: + ", values " + hints);
0580: XlibWrapper.XSetWMNormalHints(XToolkit.getDisplay(),
0581: getWindow(), hints.pData);
0582: } finally {
0583: XToolkit.awtUnlock();
0584: }
0585: }
0586:
0587: public boolean isMinSizeSet() {
0588: XSizeHints hints = getHints();
0589: long flags = hints.get_flags();
0590: return ((flags & XlibWrapper.PMinSize) == XlibWrapper.PMinSize);
0591: }
0592:
0593: /**
0594: * This lock object can be used to protect instance data from concurrent access
0595: * by two threads. If both state lock and AWT lock are taken, AWT Lock should be taken first.
0596: */
0597: Object getStateLock() {
0598: return state_lock;
0599: }
0600:
0601: public long getWindow() {
0602: return window;
0603: }
0604:
0605: public long getContentWindow() {
0606: return window;
0607: }
0608:
0609: public XBaseWindow getContentXWindow() {
0610: return XToolkit.windowToXWindow(getContentWindow());
0611: }
0612:
0613: public Rectangle getBounds() {
0614: return new Rectangle(x, y, width, height);
0615: }
0616:
0617: public Dimension getSize() {
0618: return new Dimension(width, height);
0619: }
0620:
0621: public void toFront() {
0622: XToolkit.awtLock();
0623: try {
0624: XlibWrapper
0625: .XRaiseWindow(XToolkit.getDisplay(), getWindow());
0626: } finally {
0627: XToolkit.awtUnlock();
0628: }
0629: }
0630:
0631: public void xRequestFocus(long time) {
0632: XToolkit.awtLock();
0633: try {
0634: if (focusLog.isLoggable(Level.FINER))
0635: focusLog.finer("XSetInputFocus on "
0636: + Long.toHexString(getWindow()) + " with time "
0637: + time);
0638: XlibWrapper.XSetInputFocus2(XToolkit.getDisplay(),
0639: getWindow(), time);
0640: } finally {
0641: XToolkit.awtUnlock();
0642: }
0643: }
0644:
0645: public void xRequestFocus() {
0646: XToolkit.awtLock();
0647: try {
0648: if (focusLog.isLoggable(Level.FINER))
0649: focusLog.finer("XSetInputFocus on "
0650: + Long.toHexString(getWindow()));
0651: XlibWrapper.XSetInputFocus(XToolkit.getDisplay(),
0652: getWindow());
0653: } finally {
0654: XToolkit.awtUnlock();
0655: }
0656: }
0657:
0658: public static long xGetInputFocus() {
0659: XToolkit.awtLock();
0660: try {
0661: return XlibWrapper.XGetInputFocus(XToolkit.getDisplay());
0662: } finally {
0663: XToolkit.awtUnlock();
0664: }
0665: }
0666:
0667: public void xSetVisible(boolean visible) {
0668: if (log.isLoggable(Level.FINE))
0669: log.fine("Setting visible on " + this + " to " + visible);
0670: XToolkit.awtLock();
0671: try {
0672: this .visible = visible;
0673: if (visible) {
0674: XlibWrapper.XMapWindow(XToolkit.getDisplay(),
0675: getWindow());
0676: } else {
0677: XlibWrapper.XUnmapWindow(XToolkit.getDisplay(),
0678: getWindow());
0679: }
0680: XlibWrapper.XFlush(XToolkit.getDisplay());
0681: } finally {
0682: XToolkit.awtUnlock();
0683: }
0684: }
0685:
0686: boolean isMapped() {
0687: return mapped;
0688: }
0689:
0690: void updateWMName() {
0691: String name = getWMName();
0692: XToolkit.awtLock();
0693: try {
0694: if (name == null) {
0695: name = " ";
0696: }
0697: XAtom nameAtom = XAtom.get(XAtom.XA_WM_NAME);
0698: nameAtom.setProperty(getWindow(), name);
0699: XAtom netNameAtom = XAtom.get("_NET_WM_NAME");
0700: netNameAtom.setPropertyUTF8(getWindow(), name);
0701: } finally {
0702: XToolkit.awtUnlock();
0703: }
0704: }
0705:
0706: void setWMClass(String[] cl) {
0707: if (cl.length != 2) {
0708: throw new IllegalArgumentException(
0709: "WM_CLASS_NAME consists of exactly two strings");
0710: }
0711: XToolkit.awtLock();
0712: try {
0713: XAtom xa = XAtom.get(XAtom.XA_WM_CLASS);
0714: xa.setProperty8(getWindow(), cl[0] + '\0' + cl[1]);
0715: } finally {
0716: XToolkit.awtUnlock();
0717: }
0718: }
0719:
0720: boolean isVisible() {
0721: return visible;
0722: }
0723:
0724: static long getScreenOfWindow(long window) {
0725: XToolkit.awtLock();
0726: try {
0727: return XlibWrapper.getScreenOfWindow(XToolkit.getDisplay(),
0728: window);
0729: } finally {
0730: XToolkit.awtUnlock();
0731: }
0732: }
0733:
0734: long getScreenNumber() {
0735: XToolkit.awtLock();
0736: try {
0737: return XlibWrapper.XScreenNumberOfScreen(getScreen());
0738: } finally {
0739: XToolkit.awtUnlock();
0740: }
0741: }
0742:
0743: long getScreen() {
0744: if (screen == -1) { // Not initialized
0745: screen = getScreenOfWindow(window);
0746: }
0747: return screen;
0748: }
0749:
0750: public void xSetBounds(Rectangle bounds) {
0751: xSetBounds(bounds.x, bounds.y, bounds.width, bounds.height);
0752: }
0753:
0754: public void xSetBounds(int x, int y, int width, int height) {
0755: if (getWindow() == 0) {
0756: insLog.warning("Attempt to resize uncreated window");
0757: throw new IllegalStateException(
0758: "Attempt to resize uncreated window");
0759: }
0760: insLog.fine("Setting bounds on " + this + " to (" + x + ", "
0761: + y + "), " + width + "x" + height);
0762: if (width <= 0) {
0763: width = 1;
0764: }
0765: if (height <= 0) {
0766: height = 1;
0767: }
0768: XToolkit.awtLock();
0769: try {
0770: XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(),
0771: getWindow(), x, y, width, height);
0772: } finally {
0773: XToolkit.awtUnlock();
0774: }
0775: }
0776:
0777: /**
0778: * Translate coordinates from one window into another. Optimized
0779: * for XAWT - uses cached data when possible. Preferable over
0780: * pure XTranslateCoordinates.
0781: * @return coordinates relative to dst, or null if error happened
0782: */
0783: static Point toOtherWindow(long src, long dst, int x, int y) {
0784: Point rpt = new Point(0, 0);
0785:
0786: // Check if both windows belong to XAWT - then no X calls are necessary
0787:
0788: XBaseWindow srcPeer = XToolkit.windowToXWindow(src);
0789: XBaseWindow dstPeer = XToolkit.windowToXWindow(dst);
0790:
0791: if (srcPeer != null && dstPeer != null) {
0792: // (x, y) is relative to src
0793: rpt.x = x + srcPeer.getAbsoluteX() - dstPeer.getAbsoluteX();
0794: rpt.y = y + srcPeer.getAbsoluteY() - dstPeer.getAbsoluteY();
0795: } else if (dstPeer != null
0796: && XlibUtil.isRoot(src, dstPeer.getScreenNumber())) {
0797: // from root into peer
0798: rpt.x = x - dstPeer.getAbsoluteX();
0799: rpt.y = y - dstPeer.getAbsoluteY();
0800: } else if (srcPeer != null
0801: && XlibUtil.isRoot(dst, srcPeer.getScreenNumber())) {
0802: // from peer into root
0803: rpt.x = x + srcPeer.getAbsoluteX();
0804: rpt.y = y + srcPeer.getAbsoluteY();
0805: } else {
0806: rpt = XlibUtil.translateCoordinates(src, dst, new Point(x,
0807: y));
0808: }
0809: return rpt;
0810: }
0811:
0812: /*
0813: * Convert to global coordinates.
0814: */
0815: Rectangle toGlobal(Rectangle rec) {
0816: Point p = toGlobal(rec.getLocation());
0817: Rectangle newRec = new Rectangle(rec);
0818: if (p != null) {
0819: newRec.setLocation(p);
0820: }
0821: return newRec;
0822: }
0823:
0824: Point toGlobal(Point pt) {
0825: Point p = toGlobal(pt.x, pt.y);
0826: if (p != null) {
0827: return p;
0828: } else {
0829: return new Point(pt);
0830: }
0831: }
0832:
0833: Point toGlobal(int x, int y) {
0834: long root;
0835: XToolkit.awtLock();
0836: try {
0837: root = XlibWrapper.RootWindow(XToolkit.getDisplay(),
0838: getScreenNumber());
0839: } finally {
0840: XToolkit.awtUnlock();
0841: }
0842: Point p = toOtherWindow(getContentWindow(), root, x, y);
0843: if (p != null) {
0844: return p;
0845: } else {
0846: return new Point(x, y);
0847: }
0848: }
0849:
0850: /*
0851: * Convert to local coordinates.
0852: */
0853: Point toLocal(Point pt) {
0854: Point p = toLocal(pt.x, pt.y);
0855: if (p != null) {
0856: return p;
0857: } else {
0858: return new Point(pt);
0859: }
0860: }
0861:
0862: Point toLocal(int x, int y) {
0863: long root;
0864: XToolkit.awtLock();
0865: try {
0866: root = XlibWrapper.RootWindow(XToolkit.getDisplay(),
0867: getScreenNumber());
0868: } finally {
0869: XToolkit.awtUnlock();
0870: }
0871: Point p = toOtherWindow(root, getContentWindow(), x, y);
0872: if (p != null) {
0873: return p;
0874: } else {
0875: return new Point(x, y);
0876: }
0877: }
0878:
0879: /**
0880: * We should always grab both keyboard and pointer to control event flow
0881: * on popups. This also simplifies synthetic grab implementation.
0882: * The active grab overrides activated automatic grab.
0883: */
0884: public boolean grabInput() {
0885: grabLog.log(Level.FINE, "Grab input on {0}",
0886: new Object[] { this });
0887:
0888: XToolkit.awtLock();
0889: try {
0890: if (XAwtState.getGrabWindow() == this
0891: && XAwtState.isManualGrab()) {
0892: grabLog.fine(" Already Grabbed");
0893: return true;
0894: }
0895: //6273031: PIT. Choice drop down does not close once it is right clicked to show a popup menu
0896: //remember previous window having grab and if it's not null ungrab it.
0897: XBaseWindow prevGrabWindow = XAwtState.getGrabWindow();
0898: final int eventMask = (int) (ButtonPressMask
0899: | ButtonReleaseMask | EnterWindowMask
0900: | LeaveWindowMask | PointerMotionMask | ButtonMotionMask);
0901: final int ownerEvents = 1;
0902:
0903: int ptrGrab = XlibWrapper.XGrabPointer(XToolkit
0904: .getDisplay(), getContentWindow(), ownerEvents,
0905: eventMask, GrabModeAsync, GrabModeAsync, None, (XWM
0906: .isMotif() ? XToolkit.arrowCursor : None),
0907: CurrentTime);
0908: // Check grab results to be consistent with X server grab
0909: if (ptrGrab != GrabSuccess) {
0910: XlibWrapper.XUngrabPointer(XToolkit.getDisplay(),
0911: CurrentTime);
0912: XAwtState.setGrabWindow(null);
0913: grabLog.fine(" Grab Failure - mouse");
0914: return false;
0915: }
0916:
0917: int keyGrab = XlibWrapper.XGrabKeyboard(XToolkit
0918: .getDisplay(), getContentWindow(), ownerEvents,
0919: GrabModeAsync, GrabModeAsync, CurrentTime);
0920: if (keyGrab != GrabSuccess) {
0921: XlibWrapper.XUngrabPointer(XToolkit.getDisplay(),
0922: CurrentTime);
0923: XlibWrapper.XUngrabKeyboard(XToolkit.getDisplay(),
0924: CurrentTime);
0925: XAwtState.setGrabWindow(null);
0926: grabLog.fine(" Grab Failure - keyboard");
0927: return false;
0928: }
0929: if (prevGrabWindow != null) {
0930: prevGrabWindow.ungrabInputImpl();
0931: }
0932: XAwtState.setGrabWindow(this );
0933: grabLog.fine(" Grab - success");
0934: return true;
0935: } finally {
0936: XToolkit.awtUnlock();
0937: }
0938: }
0939:
0940: static void ungrabInput() {
0941: XToolkit.awtLock();
0942: try {
0943: XBaseWindow grabWindow = XAwtState.getGrabWindow();
0944: grabLog.log(Level.FINE, "UnGrab input on {0}",
0945: new Object[] { grabWindow });
0946: if (grabWindow != null) {
0947: grabWindow.ungrabInputImpl();
0948: XlibWrapper.XUngrabPointer(XToolkit.getDisplay(),
0949: CurrentTime);
0950: XlibWrapper.XUngrabKeyboard(XToolkit.getDisplay(),
0951: CurrentTime);
0952: XAwtState.setGrabWindow(null);
0953: // we need to call XFlush() here to force ungrab
0954: // see 6384219 for details
0955: XlibWrapper.XFlush(XToolkit.getDisplay());
0956: }
0957: } finally {
0958: XToolkit.awtUnlock();
0959: }
0960: }
0961:
0962: // called from ungrabInput, used in popup windows to hide theirselfs in ungrabbing
0963: void ungrabInputImpl() {
0964: }
0965:
0966: static void checkSecurity() {
0967: if (XToolkit.isSecurityWarningEnabled()
0968: && XToolkit.isToolkitThread()) {
0969: StackTraceElement stack[] = (new Throwable())
0970: .getStackTrace();
0971: log
0972: .warning(stack[1]
0973: + ": Security violation: calling user code on toolkit thread");
0974: }
0975: }
0976:
0977: public Set<Long> getChildren() {
0978: synchronized (getStateLock()) {
0979: return new HashSet<Long>(children);
0980: }
0981: }
0982:
0983: // -------------- Event handling ----------------
0984: public void handleMapNotifyEvent(XEvent xev) {
0985: mapped = true;
0986: }
0987:
0988: public void handleUnmapNotifyEvent(XEvent xev) {
0989: mapped = false;
0990: }
0991:
0992: public void handleReparentNotifyEvent(XEvent xev) {
0993: if (eventLog.isLoggable(Level.FINER)) {
0994: XReparentEvent msg = xev.get_xreparent();
0995: eventLog.finer(msg.toString());
0996: }
0997: }
0998:
0999: public void handlePropertyNotify(XEvent xev) {
1000: XPropertyEvent msg = xev.get_xproperty();
1001: if (XPropertyCache.isCachingSupported()) {
1002: XPropertyCache
1003: .clearCache(window, XAtom.get(msg.get_atom()));
1004: }
1005: if (eventLog.isLoggable(Level.FINER)) {
1006: eventLog.log(Level.FINER, "{0}", new Object[] { msg });
1007: }
1008: }
1009:
1010: public void handleDestroyNotify(XEvent xev) {
1011: XAnyEvent xany = xev.get_xany();
1012: if (xany.get_window() == getWindow()) {
1013: XToolkit.removeFromWinMap(getWindow(), this );
1014: if (XPropertyCache.isCachingSupported()) {
1015: XPropertyCache.clearCache(getWindow());
1016: }
1017: }
1018: if (xany.get_window() != getWindow()) {
1019: synchronized (getStateLock()) {
1020: children.remove(xany.get_window());
1021: }
1022: }
1023: }
1024:
1025: public void handleCreateNotify(XEvent xev) {
1026: XAnyEvent xany = xev.get_xany();
1027: if (xany.get_window() != getWindow()) {
1028: synchronized (getStateLock()) {
1029: children.add(xany.get_window());
1030: }
1031: }
1032: }
1033:
1034: public void handleClientMessage(XEvent xev) {
1035: if (eventLog.isLoggable(Level.FINER)) {
1036: XClientMessageEvent msg = xev.get_xclient();
1037: eventLog.finer(msg.toString());
1038: }
1039: }
1040:
1041: public void handleVisibilityEvent(XEvent xev) {
1042: }
1043:
1044: public void handleKeyPress(XEvent xev) {
1045: }
1046:
1047: public void handleKeyRelease(XEvent xev) {
1048: }
1049:
1050: public void handleExposeEvent(XEvent xev) {
1051: }
1052:
1053: /**
1054: * Activate automatic grab on first ButtonPress,
1055: * deactivate on full mouse release
1056: */
1057: public void handleButtonPressRelease(XEvent xev) {
1058: XButtonEvent xbe = xev.get_xbutton();
1059: final int buttonState = xbe.get_state()
1060: & (Button1Mask | Button2Mask | Button3Mask
1061: | Button4Mask | Button5Mask);
1062: switch (xev.get_type()) {
1063: case ButtonPress:
1064: if (buttonState == 0) {
1065: XAwtState.setAutoGrabWindow(this );
1066: }
1067: break;
1068: case ButtonRelease:
1069: if (isFullRelease(buttonState, xbe.get_button())) {
1070: XAwtState.setAutoGrabWindow(null);
1071: }
1072: break;
1073: }
1074: }
1075:
1076: public void handleMotionNotify(XEvent xev) {
1077: }
1078:
1079: public void handleXCrossingEvent(XEvent xev) {
1080: }
1081:
1082: public void handleConfigureNotifyEvent(XEvent xev) {
1083: XConfigureEvent xe = xev.get_xconfigure();
1084: insLog.log(Level.FINER, "Configure, {0}", new Object[] { xe });
1085: x = xe.get_x();
1086: y = xe.get_y();
1087: width = xe.get_width();
1088: height = xe.get_height();
1089: }
1090:
1091: /**
1092: * Checks ButtonRelease released all Mouse buttons
1093: */
1094: static boolean isFullRelease(int buttonState, int button) {
1095: switch (button) {
1096: case Button1:
1097: return buttonState == Button1Mask;
1098: case Button2:
1099: return buttonState == Button2Mask;
1100: case Button3:
1101: return buttonState == Button3Mask;
1102: case Button4:
1103: return buttonState == Button4Mask;
1104: case Button5:
1105: return buttonState == Button5Mask;
1106: }
1107: return buttonState == 0;
1108: }
1109:
1110: static boolean isGrabbedEvent(XEvent ev, XBaseWindow target) {
1111: switch (ev.get_type()) {
1112: case ButtonPress:
1113: case ButtonRelease:
1114: case MotionNotify:
1115: case KeyPress:
1116: case KeyRelease:
1117: return true;
1118: case LeaveNotify:
1119: case EnterNotify:
1120: // We shouldn't dispatch this events to the grabbed components (see 6317481)
1121: // But this logic is important if the grabbed component is top-level (see realSync)
1122: return (target instanceof XWindowPeer);
1123: default:
1124: return false;
1125: }
1126: }
1127:
1128: /**
1129: * Dispatches event to the grab Window or event source window depending
1130: * on whether the grab is active and on the event type
1131: */
1132: static void dispatchToWindow(XEvent ev) {
1133: XBaseWindow target = XAwtState.getGrabWindow();
1134: if (target == null || !isGrabbedEvent(ev, target)) {
1135: target = XToolkit.windowToXWindow(ev.get_xany()
1136: .get_window());
1137: }
1138: if (target != null && target.checkInitialised()) {
1139: target.dispatchEvent(ev);
1140: }
1141: }
1142:
1143: public void dispatchEvent(XEvent xev) {
1144: if (eventLog.isLoggable(Level.FINEST))
1145: eventLog.finest(xev.toString());
1146: int type = xev.get_type();
1147:
1148: if (isDisposed()) {
1149: return;
1150: }
1151:
1152: switch (type) {
1153: case VisibilityNotify:
1154: handleVisibilityEvent(xev);
1155: break;
1156: case ClientMessage:
1157: handleClientMessage(xev);
1158: break;
1159: case Expose:
1160: case GraphicsExpose:
1161: handleExposeEvent(xev);
1162: break;
1163: case ButtonPress:
1164: case ButtonRelease:
1165: handleButtonPressRelease(xev);
1166: break;
1167:
1168: case MotionNotify:
1169: handleMotionNotify(xev);
1170: break;
1171: case KeyPress:
1172: handleKeyPress(xev);
1173: break;
1174: case KeyRelease:
1175: handleKeyRelease(xev);
1176: break;
1177: case EnterNotify:
1178: case LeaveNotify:
1179: handleXCrossingEvent(xev);
1180: break;
1181: case ConfigureNotify:
1182: handleConfigureNotifyEvent(xev);
1183: break;
1184: case MapNotify:
1185: handleMapNotifyEvent(xev);
1186: break;
1187: case UnmapNotify:
1188: handleUnmapNotifyEvent(xev);
1189: break;
1190: case ReparentNotify:
1191: handleReparentNotifyEvent(xev);
1192: break;
1193: case PropertyNotify:
1194: handlePropertyNotify(xev);
1195: break;
1196: case DestroyNotify:
1197: handleDestroyNotify(xev);
1198: break;
1199: case CreateNotify:
1200: handleCreateNotify(xev);
1201: break;
1202: }
1203: }
1204:
1205: protected boolean isEventDisabled(XEvent e) {
1206: return false;
1207: }
1208:
1209: int getX() {
1210: return x;
1211: }
1212:
1213: int getY() {
1214: return y;
1215: }
1216:
1217: int getWidth() {
1218: return width;
1219: }
1220:
1221: int getHeight() {
1222: return height;
1223: }
1224:
1225: void setDisposed(boolean d) {
1226: disposed = d;
1227: }
1228:
1229: boolean isDisposed() {
1230: return disposed;
1231: }
1232:
1233: public int getAbsoluteX() {
1234: XBaseWindow pw = getParentWindow();
1235: if (pw != null) {
1236: return pw.getAbsoluteX() + getX();
1237: } else {
1238: // Overridden for top-levels as their (x,y) is Java (x, y), not native location
1239: return getX();
1240: }
1241: }
1242:
1243: public int getAbsoluteY() {
1244: XBaseWindow pw = getParentWindow();
1245: if (pw != null) {
1246: return pw.getAbsoluteY() + getY();
1247: } else {
1248: return getY();
1249: }
1250: }
1251:
1252: public XBaseWindow getParentWindow() {
1253: return parentWindow;
1254: }
1255:
1256: public XWindowPeer getToplevelXWindow() {
1257: XBaseWindow bw = this ;
1258: while (bw != null && !(bw instanceof XWindowPeer)) {
1259: bw = bw.getParentWindow();
1260: }
1261: return (XWindowPeer) bw;
1262: }
1263:
1264: public String toString() {
1265: return super .toString() + "(" + Long.toString(getWindow(), 16)
1266: + ")";
1267: }
1268:
1269: /**
1270: * Returns whether the given point is inside of the window. Coordinates are local.
1271: */
1272: public boolean contains(int x, int y) {
1273: return x >= 0 && y >= 0 && x < getWidth() && y < getHeight();
1274: }
1275:
1276: /**
1277: * Returns whether the given point is inside of the window. Coordinates are global.
1278: */
1279: public boolean containsGlobal(int x, int y) {
1280: return x >= getAbsoluteX() && y >= getAbsoluteY()
1281: && x < (getAbsoluteX() + getWidth())
1282: && y < (getAbsoluteY() + getHeight());
1283: }
1284:
1285: }
|