/* * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package sun.awt.X11; import java.awt.*; import sun.awt.*; import java.util.logging.*; import java.util.*; public class XBaseWindow { private static final Logger log = Logger.getLogger("sun.awt.X11.XBaseWindow"); private static final Logger insLog = Logger.getLogger("sun.awt.X11.insets.XBaseWindow"); private static final Logger eventLog = Logger.getLogger("sun.awt.X11.event.XBaseWindow"); private static final Logger focusLog = Logger.getLogger("sun.awt.X11.focus.XBaseWindow"); private static final Logger grabLog = Logger.getLogger("sun.awt.X11.grab.XBaseWindow"); public static final String PARENT_WINDOW = "parent window", // parent window, Long BOUNDS = "bounds", // bounds of the window, Rectangle OVERRIDE_REDIRECT = "overrideRedirect", // override_redirect setting, Boolean EVENT_MASK = "event mask", // event mask, Integer VALUE_MASK = "value mask", // value mask, Long BORDER_PIXEL = "border pixel", // border pixel value, Integer COLORMAP = "color map", // color map, Long DEPTH = "visual depth", // depth, Integer VISUAL_CLASS = "visual class", // visual class, Integer VISUAL = "visual", // visual, Long EMBEDDED = "embedded", // is embedded?, Boolean DELAYED = "delayed", // is creation delayed?, Boolean PARENT = "parent", // parent peer BACKGROUND_PIXMAP = "pixmap", // background pixmap VISIBLE = "visible", // whether it is visible by default SAVE_UNDER = "save under", // save content under this window BACKING_STORE = "backing store", // enables double buffering BIT_GRAVITY = "bit gravity"; // copy old content on geometry change private XCreateWindowParams delayedParams; Set children = new HashSet(); long window = XConstants.None; boolean visible; boolean mapped; boolean embedded; Rectangle maxBounds; volatile XBaseWindow parentWindow; private boolean disposed; private long screen; private XSizeHints hints; private XWMHints wmHints; final static int MIN_SIZE = 1; final static int DEF_LOCATION = 1; private static XAtom wm_client_leader; static enum InitialiseState { INITIALISING, NOT_INITIALISED, INITIALISED, FAILED_INITIALISATION }; private InitialiseState initialising; int x; int y; int width; int height; void awtLock() { XToolkit.awtLock(); } void awtUnlock() { XToolkit.awtUnlock(); } void awtLockNotifyAll() { XToolkit.awtLockNotifyAll(); } void awtLockWait() throws InterruptedException { XToolkit.awtLockWait(); } // To prevent errors from overriding obsolete methods protected final void init(long parentWindow, Rectangle bounds) {} protected final void preInit() {} protected final void postInit() {} // internal lock for synchronizing state changes and paint calls, initialized in preInit. // the order with other locks: AWTLock -> stateLock static class StateLock extends Object { } protected StateLock state_lock; /** * Called for delayed inits during construction */ void instantPreInit(XCreateWindowParams params) { state_lock = new StateLock(); initialising = InitialiseState.NOT_INITIALISED; } /** * Called before window creation, descendants should override to initialize the data, * initialize params. */ void preInit(XCreateWindowParams params) { state_lock = new StateLock(); initialising = InitialiseState.NOT_INITIALISED; embedded = Boolean.TRUE.equals(params.get(EMBEDDED)); visible = Boolean.TRUE.equals(params.get(VISIBLE)); Object parent = params.get(PARENT); if (parent instanceof XBaseWindow) { parentWindow = (XBaseWindow)parent; } else { Long parentWindowID = (Long)params.get(PARENT_WINDOW); if (parentWindowID != null) { parentWindow = XToolkit.windowToXWindow(parentWindowID); } } Long eventMask = (Long)params.get(EVENT_MASK); if (eventMask != null) { long mask = eventMask.longValue(); mask |= XConstants.SubstructureNotifyMask; params.put(EVENT_MASK, mask); } screen = -1; } /** * Called after window creation, descendants should override to initialize Window * with class-specific values and perform post-initialization actions. */ void postInit(XCreateWindowParams params) { if (log.isLoggable(Level.FINE)) log.fine("WM name is " + getWMName()); updateWMName(); // Set WM_CLIENT_LEADER property initClientLeader(); } /** * Creates window using parameters params * If params contain flag DELAYED doesn't do anything. * Note: Descendants can call this method to create the window * at the time different to instance construction. */ protected final void init(XCreateWindowParams params) { awtLock(); initialising = InitialiseState.INITIALISING; awtUnlock(); try { if (!Boolean.TRUE.equals(params.get(DELAYED))) { preInit(params); create(params); postInit(params); } else { instantPreInit(params); delayedParams = params; } awtLock(); initialising = InitialiseState.INITIALISED; awtLockNotifyAll(); awtUnlock(); } catch (RuntimeException re) { awtLock(); initialising = InitialiseState.FAILED_INITIALISATION; awtLockNotifyAll(); awtUnlock(); throw re; } catch (Throwable t) { log.log(Level.WARNING, "Exception during peer initialization", t); awtLock(); initialising = InitialiseState.FAILED_INITIALISATION; awtLockNotifyAll(); awtUnlock(); } } public boolean checkInitialised() { awtLock(); try { switch (initialising) { case INITIALISED: return true; case INITIALISING: try { while (initialising != InitialiseState.INITIALISED) { awtLockWait(); } } catch (InterruptedException ie) { return false; } return true; case NOT_INITIALISED: case FAILED_INITIALISATION: return false; default: return false; } } finally { awtUnlock(); } } /* * Creates an invisible InputOnly window without an associated Component. */ XBaseWindow() { this(new XCreateWindowParams()); } /** * Creates normal child window */ XBaseWindow(long parentWindow, Rectangle bounds) { this(new XCreateWindowParams(new Object[] { BOUNDS, bounds, PARENT_WINDOW, Long.valueOf(parentWindow)})); } /** * Creates top-level window */ XBaseWindow(Rectangle bounds) { this(new XCreateWindowParams(new Object[] { BOUNDS, bounds })); } public XBaseWindow (XCreateWindowParams params) { init(params); } /* This create is used by the XEmbeddedFramePeer since it has to create the window as a child of the netscape window. This netscape window is passed in as wid */ XBaseWindow(long parentWindow) { this(new XCreateWindowParams(new Object[] { PARENT_WINDOW, Long.valueOf(parentWindow), EMBEDDED, Boolean.TRUE })); } /** * Verifies that all required parameters are set. If not, sets them to default values. * Verifies values of critical parameters, adjust their values when needed. * @throws IllegalArgumentException if params is null */ protected void checkParams(XCreateWindowParams params) { if (params == null) { throw new IllegalArgumentException("Window creation parameters are null"); } params.putIfNull(PARENT_WINDOW, Long.valueOf(XToolkit.getDefaultRootWindow())); params.putIfNull(BOUNDS, new Rectangle(DEF_LOCATION, DEF_LOCATION, MIN_SIZE, MIN_SIZE)); params.putIfNull(DEPTH, Integer.valueOf((int)XConstants.CopyFromParent)); params.putIfNull(VISUAL, Long.valueOf(XConstants.CopyFromParent)); params.putIfNull(VISUAL_CLASS, Integer.valueOf((int)XConstants.InputOnly)); params.putIfNull(VALUE_MASK, Long.valueOf(XConstants.CWEventMask)); Rectangle bounds = (Rectangle)params.get(BOUNDS); bounds.width = Math.max(MIN_SIZE, bounds.width); bounds.height = Math.max(MIN_SIZE, bounds.height); Long eventMaskObj = (Long)params.get(EVENT_MASK); long eventMask = eventMaskObj != null ? eventMaskObj.longValue() : 0; // We use our own synthetic grab see XAwtState.getGrabWindow() // (see X vol. 1, 8.3.3.2) eventMask |= XConstants.PropertyChangeMask | XConstants.OwnerGrabButtonMask; params.put(EVENT_MASK, Long.valueOf(eventMask)); } /** * Creates window with parameters specified by params * @see #init */ private final void create(XCreateWindowParams params) { XToolkit.awtLock(); try { XSetWindowAttributes xattr = new XSetWindowAttributes(); try { checkParams(params); long value_mask = ((Long)params.get(VALUE_MASK)).longValue(); Long eventMask = (Long)params.get(EVENT_MASK); xattr.set_event_mask(eventMask.longValue()); value_mask |= XConstants.CWEventMask; Long border_pixel = (Long)params.get(BORDER_PIXEL); if (border_pixel != null) { xattr.set_border_pixel(border_pixel.longValue()); value_mask |= XConstants.CWBorderPixel; } Long colormap = (Long)params.get(COLORMAP); if (colormap != null) { xattr.set_colormap(colormap.longValue()); value_mask |= XConstants.CWColormap; } Long background_pixmap = (Long)params.get(BACKGROUND_PIXMAP); if (background_pixmap != null) { xattr.set_background_pixmap(background_pixmap.longValue()); value_mask |= XConstants.CWBackPixmap; } Long parentWindow = (Long)params.get(PARENT_WINDOW); Rectangle bounds = (Rectangle)params.get(BOUNDS); this.x = bounds.x; this.y = bounds.y; this.width = bounds.width; this.height = bounds.height; Integer depth = (Integer)params.get(DEPTH); Integer visual_class = (Integer)params.get(VISUAL_CLASS); Long visual = (Long)params.get(VISUAL); Boolean overrideRedirect = (Boolean)params.get(OVERRIDE_REDIRECT); if (overrideRedirect != null) { xattr.set_override_redirect(overrideRedirect.booleanValue()); value_mask |= XConstants.CWOverrideRedirect; } Boolean saveUnder = (Boolean)params.get(SAVE_UNDER); if (saveUnder != null) { xattr.set_save_under(saveUnder.booleanValue()); value_mask |= XConstants.CWSaveUnder; } Integer backingStore = (Integer)params.get(BACKING_STORE); if (backingStore != null) { xattr.set_backing_store(backingStore.intValue()); value_mask |= XConstants.CWBackingStore; } Integer bitGravity = (Integer)params.get(BIT_GRAVITY); if (bitGravity != null) { xattr.set_bit_gravity(bitGravity.intValue()); value_mask |= XConstants.CWBitGravity; } if (log.isLoggable(Level.FINE)) { log.fine("Creating window for " + this + " with the following attributes: \n" + params); } window = XlibWrapper.XCreateWindow(XToolkit.getDisplay(), parentWindow.longValue(), bounds.x, bounds.y, // location bounds.width, bounds.height, // size 0, // border depth.intValue(), // depth visual_class.intValue(), // class visual.longValue(), // visual value_mask, // value mask xattr.pData); // attributes if (window == 0) { throw new IllegalStateException("Couldn't create window because of wrong parameters. Run with NOISY_AWT to see details"); } XToolkit.addToWinMap(window, this); } finally { xattr.dispose(); } } finally { XToolkit.awtUnlock(); } } public XCreateWindowParams getDelayedParams() { return delayedParams; } protected String getWMName() { return XToolkit.getCorrectXIDString(getClass().getName()); } protected void initClientLeader() { XToolkit.awtLock(); try { if (wm_client_leader == null) { wm_client_leader = XAtom.get("WM_CLIENT_LEADER"); } wm_client_leader.setWindowProperty(this, getXAWTRootWindow()); } finally { XToolkit.awtUnlock(); } } static XRootWindow getXAWTRootWindow() { return XRootWindow.getInstance(); } void destroy() { XToolkit.awtLock(); try { if (hints != null) { XlibWrapper.XFree(hints.pData); hints = null; } XToolkit.removeFromWinMap(getWindow(), this); XlibWrapper.XDestroyWindow(XToolkit.getDisplay(), getWindow()); if (XPropertyCache.isCachingSupported()) { XPropertyCache.clearCache(window); } window = -1; if( !isDisposed() ) { setDisposed( true ); } XAwtState.getGrabWindow(); // Magic - getGrabWindow clear state if grabbing window is disposed of. } finally { XToolkit.awtUnlock(); } } void flush() { XToolkit.awtLock(); try { XlibWrapper.XFlush(XToolkit.getDisplay()); } finally { XToolkit.awtUnlock(); } } /** * Helper function to set W */ public final void setWMHints(XWMHints hints) { XToolkit.awtLock(); try { XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData); } finally { XToolkit.awtUnlock(); } } public XWMHints getWMHints() { if (wmHints == null) { wmHints = new XWMHints(XlibWrapper.XAllocWMHints()); // XlibWrapper.XGetWMHints(XToolkit.getDisplay(), // getWindow(), // wmHints.pData); } return wmHints; } /* * Call this method under AWTLock. * The lock should be acquired untill all operations with XSizeHints are completed. */ public XSizeHints getHints() { if (hints == null) { long p_hints = XlibWrapper.XAllocSizeHints(); hints = new XSizeHints(p_hints); // XlibWrapper.XGetWMNormalHints(XToolkit.getDisplay(), getWindow(), p_hints, XlibWrapper.larg1); // TODO: Shouldn't we listen for WM updates on this property? } return hints; } public void setSizeHints(long flags, int x, int y, int width, int height) { if (insLog.isLoggable(Level.FINER)) insLog.finer("Setting hints, flags " + XlibWrapper.hintsToString(flags)); XToolkit.awtLock(); try { XSizeHints hints = getHints(); // Note: if PPosition is not set in flags this means that // we want to reset PPosition in hints. This is necessary // for locationByPlatform functionality if ((flags & XUtilConstants.PPosition) != 0) { hints.set_x(x); hints.set_y(y); } if ((flags & XUtilConstants.PSize) != 0) { hints.set_width(width); hints.set_height(height); } else if ((hints.get_flags() & XUtilConstants.PSize) != 0) { flags |= XUtilConstants.PSize; } if ((flags & XUtilConstants.PMinSize) != 0) { hints.set_min_width(width); hints.set_min_height(height); } else if ((hints.get_flags() & XUtilConstants.PMinSize) != 0) { flags |= XUtilConstants.PMinSize; //Fix for 4320050: Minimum size for java.awt.Frame is not being enforced. //We don't need to reset minimum size if it's already set } if ((flags & XUtilConstants.PMaxSize) != 0) { if (maxBounds != null) { if (maxBounds.width != Integer.MAX_VALUE) { hints.set_max_width(maxBounds.width); } else { hints.set_max_width(XToolkit.getDefaultScreenWidth()); } if (maxBounds.height != Integer.MAX_VALUE) { hints.set_max_height(maxBounds.height); } else { hints.set_max_height(XToolkit.getDefaultScreenHeight()); } } else { hints.set_max_width(width); hints.set_max_height(height); } } else if ((hints.get_flags() & XUtilConstants.PMaxSize) != 0) { flags |= XUtilConstants.PMaxSize; if (maxBounds != null) { if (maxBounds.width != Integer.MAX_VALUE) { hints.set_max_width(maxBounds.width); } else { hints.set_max_width(XToolkit.getDefaultScreenWidth()); } if (maxBounds.height != Integer.MAX_VALUE) { hints.set_max_height(maxBounds.height); } else { hints.set_max_height(XToolkit.getDefaultScreenHeight()); } } else { // Leave intact } } flags |= XUtilConstants.PWinGravity; hints.set_flags(flags); hints.set_win_gravity((int)XConstants.NorthWestGravity); if (insLog.isLoggable(Level.FINER)) insLog.finer("Setting hints, resulted flags " + XlibWrapper.hintsToString(flags) + ", values " + hints); XlibWrapper.XSetWMNormalHints(XToolkit.getDisplay(), getWindow(), hints.pData); } finally { XToolkit.awtUnlock(); } } public boolean isMinSizeSet() { XSizeHints hints = getHints(); long flags = hints.get_flags(); return ((flags & XUtilConstants.PMinSize) == XUtilConstants.PMinSize); } /** * This lock object can be used to protect instance data from concurrent access * by two threads. If both state lock and AWT lock are taken, AWT Lock should be taken first. */ Object getStateLock() { return state_lock; } public long getWindow() { return window; } public long getContentWindow() { return window; } public XBaseWindow getContentXWindow() { return XToolkit.windowToXWindow(getContentWindow()); } public Rectangle getBounds() { return new Rectangle(x, y, width, height); } public Dimension getSize() { return new Dimension(width, height); } public void toFront() { XToolkit.awtLock(); try { XlibWrapper.XRaiseWindow(XToolkit.getDisplay(), getWindow()); } finally { XToolkit.awtUnlock(); } } public void xRequestFocus(long time) { XToolkit.awtLock(); try { if (focusLog.isLoggable(Level.FINER)) focusLog.finer("XSetInputFocus on " + Long.toHexString(getWindow()) + " with time " + time); XlibWrapper.XSetInputFocus2(XToolkit.getDisplay(), getWindow(), time); } finally { XToolkit.awtUnlock(); } } public void xRequestFocus() { XToolkit.awtLock(); try { if (focusLog.isLoggable(Level.FINER)) focusLog.finer("XSetInputFocus on " + Long.toHexString(getWindow())); XlibWrapper.XSetInputFocus(XToolkit.getDisplay(), getWindow()); } finally { XToolkit.awtUnlock(); } } public static long xGetInputFocus() { XToolkit.awtLock(); try { return XlibWrapper.XGetInputFocus(XToolkit.getDisplay()); } finally { XToolkit.awtUnlock(); } } public void xSetVisible(boolean visible) { if (log.isLoggable(Level.FINE)) log.fine("Setting visible on " + this + " to " + visible); XToolkit.awtLock(); try { this.visible = visible; if (visible) { XlibWrapper.XMapWindow(XToolkit.getDisplay(), getWindow()); } else { XlibWrapper.XUnmapWindow(XToolkit.getDisplay(), getWindow()); } XlibWrapper.XFlush(XToolkit.getDisplay()); } finally { XToolkit.awtUnlock(); } } boolean isMapped() { return mapped; } void updateWMName() { String name = getWMName(); XToolkit.awtLock(); try { if (name == null) { name = " "; } XAtom nameAtom = XAtom.get(XAtom.XA_WM_NAME); nameAtom.setProperty(getWindow(), name); XAtom netNameAtom = XAtom.get("_NET_WM_NAME"); netNameAtom.setPropertyUTF8(getWindow(), name); } finally { XToolkit.awtUnlock(); } } void setWMClass(String[] cl) { if (cl.length != 2) { throw new IllegalArgumentException("WM_CLASS_NAME consists of exactly two strings"); } XToolkit.awtLock(); try { XAtom xa = XAtom.get(XAtom.XA_WM_CLASS); xa.setProperty8(getWindow(), cl[0] + '\0' + cl[1]); } finally { XToolkit.awtUnlock(); } } boolean isVisible() { return visible; } static long getScreenOfWindow(long window) { XToolkit.awtLock(); try { return XlibWrapper.getScreenOfWindow(XToolkit.getDisplay(), window); } finally { XToolkit.awtUnlock(); } } long getScreenNumber() { XToolkit.awtLock(); try { return XlibWrapper.XScreenNumberOfScreen(getScreen()); } finally { XToolkit.awtUnlock(); } } long getScreen() { if (screen == -1) { // Not initialized screen = getScreenOfWindow(window); } return screen; } public void xSetBounds(Rectangle bounds) { xSetBounds(bounds.x, bounds.y, bounds.width, bounds.height); } public void xSetBounds(int x, int y, int width, int height) { if (getWindow() == 0) { insLog.warning("Attempt to resize uncreated window"); throw new IllegalStateException("Attempt to resize uncreated window"); } insLog.fine("Setting bounds on " + this + " to (" + x + ", " + y + "), " + width + "x" + height); if (width <= 0) { width = 1; } if (height <= 0) { height = 1; } XToolkit.awtLock(); try { XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), getWindow(), x,y,width,height); } finally { XToolkit.awtUnlock(); } } /** * Translate coordinates from one window into another. Optimized * for XAWT - uses cached data when possible. Preferable over * pure XTranslateCoordinates. * @return coordinates relative to dst, or null if error happened */ static Point toOtherWindow(long src, long dst, int x, int y) { Point rpt = new Point(0, 0); // Check if both windows belong to XAWT - then no X calls are necessary XBaseWindow srcPeer = XToolkit.windowToXWindow(src); XBaseWindow dstPeer = XToolkit.windowToXWindow(dst); if (srcPeer != null && dstPeer != null) { // (x, y) is relative to src rpt.x = x + srcPeer.getAbsoluteX() - dstPeer.getAbsoluteX(); rpt.y = y + srcPeer.getAbsoluteY() - dstPeer.getAbsoluteY(); } else if (dstPeer != null && XlibUtil.isRoot(src, dstPeer.getScreenNumber())) { // from root into peer rpt.x = x - dstPeer.getAbsoluteX(); rpt.y = y - dstPeer.getAbsoluteY(); } else if (srcPeer != null && XlibUtil.isRoot(dst, srcPeer.getScreenNumber())) { // from peer into root rpt.x = x + srcPeer.getAbsoluteX(); rpt.y = y + srcPeer.getAbsoluteY(); } else { rpt = XlibUtil.translateCoordinates(src, dst, new Point(x, y)); } return rpt; } /* * Convert to global coordinates. */ Rectangle toGlobal(Rectangle rec) { Point p = toGlobal(rec.getLocation()); Rectangle newRec = new Rectangle(rec); if (p != null) { newRec.setLocation(p); } return newRec; } Point toGlobal(Point pt) { Point p = toGlobal(pt.x, pt.y); if (p != null) { return p; } else { return new Point(pt); } } Point toGlobal(int x, int y) { long root; XToolkit.awtLock(); try { root = XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber()); } finally { XToolkit.awtUnlock(); } Point p = toOtherWindow(getContentWindow(), root, x, y); if (p != null) { return p; } else { return new Point(x, y); } } /* * Convert to local coordinates. */ Point toLocal(Point pt) { Point p = toLocal(pt.x, pt.y); if (p != null) { return p; } else { return new Point(pt); } } Point toLocal(int x, int y) { long root; XToolkit.awtLock(); try { root = XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber()); } finally { XToolkit.awtUnlock(); } Point p = toOtherWindow(root, getContentWindow(), x, y); if (p != null) { return p; } else { return new Point(x, y); } } /** * We should always grab both keyboard and pointer to control event flow * on popups. This also simplifies synthetic grab implementation. * The active grab overrides activated automatic grab. */ public boolean grabInput() { grabLog.log(Level.FINE, "Grab input on {0}", new Object[] {this}); XToolkit.awtLock(); try { if (XAwtState.getGrabWindow() == this && XAwtState.isManualGrab()) { grabLog.fine(" Already Grabbed"); return true; } //6273031: PIT. Choice drop down does not close once it is right clicked to show a popup menu //remember previous window having grab and if it's not null ungrab it. XBaseWindow prevGrabWindow = XAwtState.getGrabWindow(); final int eventMask = (int) (XConstants.ButtonPressMask | XConstants.ButtonReleaseMask | XConstants.EnterWindowMask | XConstants.LeaveWindowMask | XConstants.PointerMotionMask | XConstants.ButtonMotionMask); final int ownerEvents = 1; //6714678: IDE (Netbeans, Eclipse, JDeveloper) Debugger hangs //process on Linux //The user must pass the sun.awt.disablegrab property to disable //taking grabs. This prevents hanging of the GUI when a breakpoint //is hit while a popup window taking the grab is open. if (!XToolkit.getSunAwtDisableGrab()) { int ptrGrab = XlibWrapper.XGrabPointer(XToolkit.getDisplay(), getContentWindow(), ownerEvents, eventMask, XConstants.GrabModeAsync, XConstants.GrabModeAsync, XConstants.None, (XWM.isMotif() ? XToolkit.arrowCursor : XConstants.None), XConstants.CurrentTime); // Check grab results to be consistent with X server grab if (ptrGrab != XConstants.GrabSuccess) { XlibWrapper.XUngrabPointer(XToolkit.getDisplay(), XConstants.CurrentTime); XAwtState.setGrabWindow(null); grabLog.fine(" Grab Failure - mouse"); return false; } int keyGrab = XlibWrapper.XGrabKeyboard(XToolkit.getDisplay(), getContentWindow(), ownerEvents, XConstants.GrabModeAsync, XConstants.GrabModeAsync, XConstants.CurrentTime); if (keyGrab != XConstants.GrabSuccess) { XlibWrapper.XUngrabPointer(XToolkit.getDisplay(), XConstants.CurrentTime); XlibWrapper.XUngrabKeyboard(XToolkit.getDisplay(), XConstants.CurrentTime); XAwtState.setGrabWindow(null); grabLog.fine(" Grab Failure - keyboard"); return false; } } if (prevGrabWindow != null) { prevGrabWindow.ungrabInputImpl(); } XAwtState.setGrabWindow(this); grabLog.fine(" Grab - success"); return true; } finally { XToolkit.awtUnlock(); } } static void ungrabInput() { XToolkit.awtLock(); try { XBaseWindow grabWindow = XAwtState.getGrabWindow(); grabLog.log(Level.FINE, "UnGrab input on {0}", new Object[] {grabWindow}); if (grabWindow != null) { grabWindow.ungrabInputImpl(); if (!XToolkit.getSunAwtDisableGrab()) { XlibWrapper.XUngrabPointer(XToolkit.getDisplay(), XConstants.CurrentTime); XlibWrapper.XUngrabKeyboard(XToolkit.getDisplay(), XConstants.CurrentTime); } XAwtState.setGrabWindow(null); // we need to call XFlush() here to force ungrab // see 6384219 for details XlibWrapper.XFlush(XToolkit.getDisplay()); } } finally { XToolkit.awtUnlock(); } } // called from ungrabInput, used in popup windows to hide theirselfs in ungrabbing void ungrabInputImpl() { } static void checkSecurity() { if (XToolkit.isSecurityWarningEnabled() && XToolkit.isToolkitThread()) { StackTraceElement stack[] = (new Throwable()).getStackTrace(); log.warning(stack[1] + ": Security violation: calling user code on toolkit thread"); } } public Set getChildren() { synchronized (getStateLock()) { return new HashSet(children); } } // -------------- Event handling ---------------- public void handleMapNotifyEvent(XEvent xev) { if (xev.get_xany().get_window() == getWindow()) { mapped = true; } } public void handleUnmapNotifyEvent(XEvent xev) { if (xev.get_xany().get_window() == getWindow()) { mapped = false; } } public void handleReparentNotifyEvent(XEvent xev) { if (eventLog.isLoggable(Level.FINER)) { XReparentEvent msg = xev.get_xreparent(); eventLog.finer(msg.toString()); } } public void handlePropertyNotify(XEvent xev) { XPropertyEvent msg = xev.get_xproperty(); if (XPropertyCache.isCachingSupported()) { XPropertyCache.clearCache(window, XAtom.get(msg.get_atom())); } if (eventLog.isLoggable(Level.FINER)) { eventLog.log(Level.FINER, "{0}", new Object[] {msg}); } } public void handleDestroyNotify(XEvent xev) { XAnyEvent xany = xev.get_xany(); if (xany.get_window() == getWindow()) { XToolkit.removeFromWinMap(getWindow(), this); if (XPropertyCache.isCachingSupported()) { XPropertyCache.clearCache(getWindow()); } } if (xany.get_window() != getWindow()) { synchronized (getStateLock()) { children.remove(xany.get_window()); } } } public void handleCreateNotify(XEvent xev) { XAnyEvent xany = xev.get_xany(); if (xany.get_window() != getWindow()) { synchronized (getStateLock()) { children.add(xany.get_window()); } } } public void handleClientMessage(XEvent xev) { if (eventLog.isLoggable(Level.FINER)) { XClientMessageEvent msg = xev.get_xclient(); eventLog.finer(msg.toString()); } } public void handleVisibilityEvent(XEvent xev) { } public void handleKeyPress(XEvent xev) { } public void handleKeyRelease(XEvent xev) { } public void handleExposeEvent(XEvent xev) { } /** * Activate automatic grab on first ButtonPress, * deactivate on full mouse release */ public void handleButtonPressRelease(XEvent xev) { XButtonEvent xbe = xev.get_xbutton(); /* * Ignore the buttons above 20 due to the bit limit for * InputEvent.BUTTON_DOWN_MASK. * One more bit is reserved for FIRST_HIGH_BIT. */ if (xbe.get_button() > SunToolkit.MAX_BUTTONS_SUPPORTED) { return; } int buttonState = 0; final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons(); for (int i = 0; i buttonsNumber) { return buttonState == 0; } else { return buttonState == XConstants.buttonsMask[button - 1]; } } static boolean isGrabbedEvent(XEvent ev, XBaseWindow target) { switch (ev.get_type()) { case XConstants.ButtonPress: case XConstants.ButtonRelease: case XConstants.MotionNotify: case XConstants.KeyPress: case XConstants.KeyRelease: return true; case XConstants.LeaveNotify: case XConstants.EnterNotify: // We shouldn't dispatch this events to the grabbed components (see 6317481) // But this logic is important if the grabbed component is top-level (see realSync) return (target instanceof XWindowPeer); default: return false; } } /** * Dispatches event to the grab Window or event source window depending * on whether the grab is active and on the event type */ static void dispatchToWindow(XEvent ev) { XBaseWindow target = XAwtState.getGrabWindow(); if (target == null || !isGrabbedEvent(ev, target)) { target = XToolkit.windowToXWindow(ev.get_xany().get_window()); } if (target != null && target.checkInitialised()) { target.dispatchEvent(ev); } } public void dispatchEvent(XEvent xev) { if (eventLog.isLoggable(Level.FINEST)) eventLog.finest(xev.toString()); int type = xev.get_type(); if (isDisposed()) { return; } switch (type) { case XConstants.VisibilityNotify: handleVisibilityEvent(xev); break; case XConstants.ClientMessage: handleClientMessage(xev); break; case XConstants.Expose : case XConstants.GraphicsExpose : handleExposeEvent(xev); break; case XConstants.ButtonPress: case XConstants.ButtonRelease: handleButtonPressRelease(xev); break; case XConstants.MotionNotify: handleMotionNotify(xev); break; case XConstants.KeyPress: handleKeyPress(xev); break; case XConstants.KeyRelease: handleKeyRelease(xev); break; case XConstants.EnterNotify: case XConstants.LeaveNotify: handleXCrossingEvent(xev); break; case XConstants.ConfigureNotify: handleConfigureNotifyEvent(xev); break; case XConstants.MapNotify: handleMapNotifyEvent(xev); break; case XConstants.UnmapNotify: handleUnmapNotifyEvent(xev); break; case XConstants.ReparentNotify: handleReparentNotifyEvent(xev); break; case XConstants.PropertyNotify: handlePropertyNotify(xev); break; case XConstants.DestroyNotify: handleDestroyNotify(xev); break; case XConstants.CreateNotify: handleCreateNotify(xev); break; } } protected boolean isEventDisabled(XEvent e) { return false; } int getX() { return x; } int getY() { return y; } int getWidth() { return width; } int getHeight() { return height; } void setDisposed(boolean d) { disposed = d; } boolean isDisposed() { return disposed; } public int getAbsoluteX() { XBaseWindow pw = getParentWindow(); if (pw != null) { return pw.getAbsoluteX() + getX(); } else { // Overridden for top-levels as their (x,y) is Java (x, y), not native location return getX(); } } public int getAbsoluteY() { XBaseWindow pw = getParentWindow(); if (pw != null) { return pw.getAbsoluteY() + getY(); } else { return getY(); } } public XBaseWindow getParentWindow() { return parentWindow; } public XWindowPeer getToplevelXWindow() { XBaseWindow bw = this; while (bw != null && !(bw instanceof XWindowPeer)) { bw = bw.getParentWindow(); } return (XWindowPeer)bw; } public String toString() { return super.toString() + "(" + Long.toString(getWindow(), 16) + ")"; } /** * Returns whether the given point is inside of the window. Coordinates are local. */ public boolean contains(int x, int y) { return x >= 0 && y >= 0 && x < getWidth() && y < getHeight(); } /** * Returns whether the given point is inside of the window. Coordinates are global. */ public boolean containsGlobal(int x, int y) { return x >= getAbsoluteX() && y >= getAbsoluteY() && x < (getAbsoluteX()+getWidth()) && y < (getAbsoluteY()+getHeight()); } }