src/solaris/classes/sun/awt/X11/XDecoratedPeer.java
Print this page
*** 1,7 ****
/*
! * Copyright 2002-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
--- 1,7 ----
/*
! * Copyright 2002-2009 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
*** 31,58 ****
import java.awt.event.WindowEvent;
import java.util.logging.Level;
import java.util.logging.Logger;
import sun.awt.ComponentAccessor;
import sun.awt.SunToolkit;
abstract class XDecoratedPeer extends XWindowPeer {
private static final Logger log = Logger.getLogger("sun.awt.X11.XDecoratedPeer");
private static final Logger insLog = Logger.getLogger("sun.awt.X11.insets.XDecoratedPeer");
private static final Logger focusLog = Logger.getLogger("sun.awt.X11.focus.XDecoratedPeer");
private static final Logger iconLog = Logger.getLogger("sun.awt.X11.icon.XDecoratedPeer");
- // Set to true when we get the first ConfigureNotify after being
- // reparented - indicates that WM has adopted the top-level.
- boolean configure_seen;
- boolean insets_corrected;
-
XIconWindow iconWindow;
! WindowDimensions dimensions;
XContentWindow content;
- Insets currentInsets;
XFocusProxyWindow focusProxy;
XDecoratedPeer(Window target) {
super(target);
}
--- 31,63 ----
import java.awt.event.WindowEvent;
import java.util.logging.Level;
import java.util.logging.Logger;
+ import sun.awt.AWTAccessor;
import sun.awt.ComponentAccessor;
import sun.awt.SunToolkit;
abstract class XDecoratedPeer extends XWindowPeer {
private static final Logger log = Logger.getLogger("sun.awt.X11.XDecoratedPeer");
private static final Logger insLog = Logger.getLogger("sun.awt.X11.insets.XDecoratedPeer");
private static final Logger focusLog = Logger.getLogger("sun.awt.X11.focus.XDecoratedPeer");
private static final Logger iconLog = Logger.getLogger("sun.awt.X11.icon.XDecoratedPeer");
XIconWindow iconWindow;
!
! /**
! * The dimensions of the window.
! *
! * The entity encapsulates information about the bounds and the insets of
! * the window. The value is initialized in the preInit() method with the
! * bounds of the window as known on the shared level. Further updates
! * should be performed with the reportReshape() method only.
! */
! protected WindowDimensions dimensions;
!
XContentWindow content;
XFocusProxyWindow focusProxy;
XDecoratedPeer(Window target) {
super(target);
}
*** 71,85 ****
void preInit(XCreateWindowParams params) {
super.preInit(params);
winAttr.initialFocus = true;
- currentInsets = new Insets(0,0,0,0);
- applyGuessedInsets();
-
Rectangle bounds = (Rectangle)params.get(BOUNDS);
! dimensions = new WindowDimensions(bounds, getRealInsets(), false);
params.put(BOUNDS, dimensions.getClientRect());
insLog.log(Level.FINE, "Initial dimensions {0}", new Object[] { dimensions });
// Deny default processing of these events on the shell - proxy will take care of
// them instead
--- 76,87 ----
void preInit(XCreateWindowParams params) {
super.preInit(params);
winAttr.initialFocus = true;
Rectangle bounds = (Rectangle)params.get(BOUNDS);
! dimensions = new WindowDimensions(bounds, getNativeInsets(), false);
params.put(BOUNDS, dimensions.getClientRect());
insLog.log(Level.FINE, "Initial dimensions {0}", new Object[] { dimensions });
// Deny default processing of these events on the shell - proxy will take care of
// them instead
*** 91,101 ****
super.postInit(params);
// The lines that follow need to be in a postInit, so they
// happen after the X window is created.
initResizability();
updateSizeHints(dimensions);
- XWM.requestWMExtents(getWindow());
content = XContentWindow.createContent(this);
if (warningWindow != null) {
warningWindow.toFront();
--- 93,102 ----
*** 114,131 ****
}
}
public void updateMinimumSize() {
super.updateMinimumSize();
! updateMinSizeHints();
}
! private void updateMinSizeHints() {
if (isResizable()) {
Dimension minimumSize = getTargetMinimumSize();
if (minimumSize != null) {
- Insets insets = getRealInsets();
int minWidth = minimumSize.width - insets.left - insets.right;
int minHeight = minimumSize.height - insets.top - insets.bottom;
if (minWidth < 0) minWidth = 0;
if (minHeight < 0) minHeight = 0;
setSizeHints(XUtilConstants.PMinSize | (isLocationByPlatform()?0:(XUtilConstants.PPosition | XUtilConstants.USPosition)),
--- 115,131 ----
}
}
public void updateMinimumSize() {
super.updateMinimumSize();
! updateMinSizeHints(getNativeInsets());
}
! private void updateMinSizeHints(Insets insets) {
if (isResizable()) {
Dimension minimumSize = getTargetMinimumSize();
if (minimumSize != null) {
int minWidth = minimumSize.width - insets.left - insets.right;
int minHeight = minimumSize.height - insets.top - insets.bottom;
if (minWidth < 0) minWidth = 0;
if (minHeight < 0) minHeight = 0;
setSizeHints(XUtilConstants.PMinSize | (isLocationByPlatform()?0:(XUtilConstants.PPosition | XUtilConstants.USPosition)),
*** 229,465 ****
/***************************************************************************************
* I N S E T S C O D E
**************************************************************************************/
- protected boolean isInitialReshape() {
- return false;
- }
! private static Insets difference(Insets i1, Insets i2) {
! return new Insets(i1.top-i2.top, i1.left - i2.left, i1.bottom-i2.bottom, i1.right-i2.right);
! }
! private static boolean isNull(Insets i) {
! return (i == null) || ((i.left | i.top | i.right | i.bottom) == 0);
}
!
! private static Insets copy(Insets i) {
! return new Insets(i.top, i.left, i.bottom, i.right);
}
!
! // insets which we get from WM (e.g from _NET_FRAME_EXTENTS)
! private Insets wm_set_insets;
!
! private Insets getWMSetInsets(XAtom changedAtom) {
! if (isEmbedded()) {
! return null;
}
!
! if (wm_set_insets != null) {
! return wm_set_insets;
}
-
- if (changedAtom == null) {
- wm_set_insets = XWM.getInsetsFromExtents(getWindow());
- } else {
- wm_set_insets = XWM.getInsetsFromProp(getWindow(), changedAtom);
}
! insLog.log(Level.FINER, "FRAME_EXTENTS: {0}", new Object[]{wm_set_insets});
! if (wm_set_insets != null) {
! wm_set_insets = copy(wm_set_insets);
}
! return wm_set_insets;
}
! private void resetWMSetInsets() {
! wm_set_insets = null;
}
! public void handlePropertyNotify(XEvent xev) {
! super.handlePropertyNotify(xev);
!
! XPropertyEvent ev = xev.get_xproperty();
! if (ev.get_atom() == XWM.XA_KDE_NET_WM_FRAME_STRUT.getAtom()
! || ev.get_atom() == XWM.XA_NET_FRAME_EXTENTS.getAtom())
! {
! getWMSetInsets(XAtom.get(ev.get_atom()));
}
}
! long reparent_serial = 0;
!
! public void handleReparentNotifyEvent(XEvent xev) {
! XReparentEvent xe = xev.get_xreparent();
! if (insLog.isLoggable(Level.FINE)) insLog.fine(xe.toString());
! reparent_serial = xe.get_serial();
XToolkit.awtLock();
try {
! long root = XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber());
!
! if (isEmbedded()) {
! setReparented(true);
! insets_corrected = true;
! return;
}
- Component t = (Component)target;
- if (getDecorations() == XWindowAttributesData.AWT_DECOR_NONE) {
- setReparented(true);
- insets_corrected = true;
- reshape(dimensions, SET_SIZE, false);
- } else if (xe.get_parent() == root) {
- configure_seen = false;
- insets_corrected = false;
! /*
! * We can be repareted to root for two reasons:
! * . setVisible(false)
! * . WM exited
*/
! if (isVisible()) { /* WM exited */
! /* Work around 4775545 */
! XWM.getWM().unshadeKludge(this);
! insLog.fine("- WM exited");
! } else {
! insLog.fine(" - reparent due to hide");
}
! } else { /* reparented to WM frame, figure out our insets */
! setReparented(true);
! insets_corrected = false;
!
! // Check if we have insets provided by the WM
! Insets correctWM = getWMSetInsets(null);
! if (correctWM != null) {
! insLog.log(Level.FINER, "wm-provided insets {0}", new Object[]{correctWM});
! // If these insets are equal to our current insets - no actions are necessary
! Insets dimInsets = dimensions.getInsets();
! if (correctWM.equals(dimInsets)) {
! insLog.finer("Insets are the same as estimated - no additional reshapes necessary");
! no_reparent_artifacts = true;
! insets_corrected = true;
! applyGuessedInsets();
return;
}
- } else {
- correctWM = XWM.getWM().getInsets(this, xe.get_window(), xe.get_parent());
! if (correctWM != null) {
! insLog.log(Level.FINER, "correctWM {0}", new Object[] {correctWM});
! } else {
! insLog.log(Level.FINER, "correctWM insets are not available, waiting for configureNotify");
}
}
! if (correctWM != null) {
! handleCorrectInsets(correctWM);
}
}
- } finally {
- XToolkit.awtUnlock();
}
}
! protected void handleCorrectInsets(Insets correctWM) {
! XToolkit.awtLock();
! try {
! /*
! * Ok, now see if we need adjust window size because
! * initial insets were wrong (most likely they were).
*/
! Insets correction = difference(correctWM, currentInsets);
! insLog.log(Level.FINEST, "Corrention {0}", new Object[] {correction});
! if (!isNull(correction)) {
! currentInsets = copy(correctWM);
! applyGuessedInsets();
!
! //Fix for 6318109: PIT: Min Size is not honored properly when a
! //smaller size is specified in setSize(), XToolkit
! //update minimum size hints
! updateMinSizeHints();
}
- if (insLog.isLoggable(Level.FINER)) insLog.finer("Dimensions before reparent: " + dimensions);
! dimensions.setInsets(getRealInsets());
! insets_corrected = true;
! if (isMaximized()) {
! return;
}
! /*
! * If this window has been sized by a pack() we need
! * to keep the interior geometry intact. Since pack()
! * computed width and height with wrong insets, we
! * must adjust the target dimensions appropriately.
! */
! if ((getHints().get_flags() & (XUtilConstants.USPosition | XUtilConstants.PPosition)) != 0) {
! reshape(dimensions, SET_BOUNDS, false);
! } else {
! reshape(dimensions, SET_SIZE, false);
}
- } finally {
- XToolkit.awtUnlock();
}
}
! public void handleMoved(WindowDimensions dims) {
! Point loc = dims.getLocation();
! ComponentAccessor.setX((Component)target, loc.x);
! ComponentAccessor.setY((Component)target, loc.y);
! postEvent(new ComponentEvent(target, ComponentEvent.COMPONENT_MOVED));
}
! protected Insets guessInsets() {
! if (isEmbedded() || isTargetUndecorated()) {
! return new Insets(0, 0, 0, 0);
! } else {
! if (!isNull(currentInsets)) {
! /* insets were set on wdata by System Properties */
! return copy(currentInsets);
! } else {
! Insets res = getWMSetInsets(null);
! if (res == null) {
! res = XWM.getWM().guessInsets(this);
}
! return res;
}
}
}
! private void applyGuessedInsets() {
! Insets guessed = guessInsets();
! currentInsets = copy(guessed);
}
public void revalidate() {
XToolkit.executeOnEventHandlerThread(target, new Runnable() {
public void run() {
target.invalidate();
target.validate();
}
});
}
- Insets getRealInsets() {
- if (isNull(currentInsets)) {
- applyGuessedInsets();
- }
- return currentInsets;
- }
-
- public Insets getInsets() {
- Insets in = copy(getRealInsets());
- in.top += getMenuBarHeight();
- if (insLog.isLoggable(Level.FINEST)) {
- insLog.log(Level.FINEST, "Get insets returns {0}", new Object[] {in});
- }
- return in;
- }
-
boolean gravityBug() {
return XWM.configureGravityBuggy();
}
// The height of area used to display current active input method
--- 229,517 ----
/***************************************************************************************
* I N S E T S C O D E
**************************************************************************************/
! /**
! * Current native insets of the window on the desktop.
! * When it's noticed the insets might have been changed (like when we
! * receive a ReparentNotify), the value must be reset to null by the
! * setNativeInsets(null) call.
! *
! * Synchronization: the awtLock is used. This should have been the state
! * lock instead, but the retrieveNativeInsets() uses the awtLock, and the
! * later must be always taken before the state lock.
! *
! * The field MUST NOT be used directly. Use get/setNativeInsets() instead.
! */
! private Insets nativeInsets = null;
! /**
! * Gets the current native insets.
! * This method may only return null if the fallBackToDefault is false.
! */
! private Insets getNativeInsets(boolean retrieve, boolean fallBackToDefault) {
! if (isTargetUndecorated() || isEmbedded() || !XWM.isRunning())
! {
! return (Insets)ZERO_INSETS.clone();
}
! if (getWindow() == XConstants.None) {
! return getDefaultInsets();
}
! XToolkit.awtLock();
! try {
! if (nativeInsets == null && retrieve) {
! retrieveNativeInsets();
}
! return nativeInsets == null ?
! (fallBackToDefault ? getDefaultInsets() : null) :
! (Insets)nativeInsets.clone();
! } finally {
! XToolkit.awtUnlock();
}
}
! /**
! * Gets the current native insets.
! */
! public Insets getNativeInsets() {
! return getNativeInsets(true, true);
! }
! @Override
! public Insets getInsets() {
! Insets insets = getNativeInsets();
! insets.top += getMenuBarHeight();
! if (insLog.isLoggable(Level.FINEST)) {
! insLog.log(Level.FINEST, "Get insets returns {0}",
! new Object[] {insets});
}
! return insets;
}
! /**
! * Returns the insets that the window probably will get.
! */
! private Insets getDefaultInsets() {
! Insets insets = XWM.getWM().getDefaultInsets();
! return (Insets)(insets == null ? DEFAULT_INSETS : insets).clone();
}
! /**
! * Get rid of insane insets.
! * The operation is performed in place - the given object gets modified.
! */
! private static Insets sanitize(Insets insets) {
! //XXX: Perhaps using the marginal values instead of the default would
! // make more sense?
! if (insets.top > 64 || insets.top < 0) {
! insets.top = DEFAULT_INSETS.top;
}
+ if (insets.left > 32 || insets.left < 0) {
+ insets.left = DEFAULT_INSETS.left;
+ }
+ if (insets.right > 32 || insets.right < 0) {
+ insets.right = DEFAULT_INSETS.right;
+ }
+ if (insets.bottom > 32 || insets.bottom < 0) {
+ insets.bottom = DEFAULT_INSETS.bottom;
+ }
+ return insets;
}
! private void setNativeInsets(Insets insets) {
XToolkit.awtLock();
try {
! nativeInsets = insets == null ? null :
! sanitize((Insets)insets.clone());
! } finally {
! XToolkit.awtUnlock();
! }
}
! public static final Insets DEFAULT_INSETS = new Insets(25, 5, 5, 5);
! public static final Insets ZERO_INSETS = new Insets(0, 0, 0, 0);
!
! /**
! * Retrieve the current insets of the window.
! *
! * This method must only be called by the getNativeInsets() method. DO NOT
! * call this method directly. If the insets need to be updated, nullify
! * them using the setNativeInsets(null) method.
*/
! private void retrieveNativeInsets() {
! long window = getWindow();
!
! if (XWM.requestWMExtents(window)) {
! XWM.waitForExtentsUpdateEvent();
}
!
! // Some WMs may provide the extents via a property, but do not require
! // a request to update them. Hence try getting them unconditionally.
! // We could use the XEvent returned by the waitForExtentsUpdateEvent()
! // above, though that doesn't seem to make much sense.
! Insets insets = XWM.getInsetsFromExtents(window);
! if (insets != null) {
! setNativeInsets(insets);
return;
}
! // The window manager is unable to report any extents, so we need to
! // calculate them ourselves.
! Rectangle winRect = XlibUtil.getWindowGeometry(
! window, XlibWrapper.larg1);
! if (winRect == null) {
! // Some error occured
! return;
}
+ // The root window must be got immediately after the previous
+ // getWindowGeometry() call.
+ long root = Native.getWindow(XlibWrapper.larg1);
+
+ long parent = getNativeParent();
+ if (parent == XConstants.None || parent == root) {
+ // Non-reparenting WM. Assume the insets are zero.
+ setNativeInsets(ZERO_INSETS);
+ return;
}
! Rectangle parentRect = XlibUtil.getWindowGeometry(parent);
! if (parentRect == null) {
! // Some error again
! return;
}
+
+ long grand_parent = XlibUtil.getParentWindow(parent);
+ if (grand_parent == XConstants.None || grand_parent == root ||
+ (winRect.x != 0 || winRect.y != 0 ||
+ winRect.width != parentRect.width ||
+ winRect.height != parentRect.height))
+ {
+ // Single-reparenting WM
+ // Either there's no a valid grand-parent, or the direct parent
+ // has greater bounds than the window itself.
+ setNativeInsets(calculateInsets(winRect, parentRect));
+ } else {
+ // Double-reparenting WM
+ // There's a valid grand-parent. The bounds of the direct
+ // parent are equal to the bounds of the window itself.
+ Rectangle grandParentRect = XlibUtil.getWindowGeometry(
+ grand_parent);
+ if (grandParentRect == null) {
+ // One more error condition. This time we fall back to the
+ // single-reparenting case, though this will produce
+ // ZERO_INSETS actually...
+ setNativeInsets(calculateInsets(winRect, parentRect));
+ } else {
+ setNativeInsets(calculateInsets(parentRect, grandParentRect));
}
}
}
! /**
! * Calculates the insets for the given interior and exterior rectangles.
! * Only positive insets are allowed. If the interior rectangle is bigger
! * than the exterior one, the negative inset values will be ignored,
! * and zero value used instead.
*/
! private static Insets calculateInsets(Rectangle interior, Rectangle exterior) {
! return new Insets(
! Math.max(interior.y, 0),
! Math.max(interior.x, 0),
! Math.max(exterior.height - interior.height - interior.y, 0),
! Math.max(exterior.width - interior.width - interior.x, 0));
}
! /**
! * Applies the new insets.
! */
! private void setInsets(Insets insets) {
! setNativeInsets(insets);
! WindowDimensions dims = new WindowDimensions(dimensions);
! dims.setInsets(insets);
! reportOrAdjust(dims, false);
}
! @Override
! public void handlePropertyNotify(XEvent xev) {
! super.handlePropertyNotify(xev);
!
! XPropertyEvent ev = xev.get_xproperty();
! if (XWM.isExtentsPropertyAtom(ev.get_atom())) {
! Insets insets = XWM.getInsetsFromProp(getWindow(),
! XAtom.get(ev.get_atom()));
! if (insLog.isLoggable(Level.FINE)) {
! insLog.fine("" + insets);
! }
! if (insets != null) {
! setInsets(insets);
}
}
}
! // The serial of the last received ReparentNotify event
! private long reparentNotifySerial = 0;
!
! // The number of processed ConfigureNotify events with the same serial
! // as reparentNotifySerial.
! private int numOfConfigureNotifyJustAfterReparentNotify = 0;
!
! @Override
! public void handleReparentNotifyEvent(XEvent xev) {
! super.handleReparentNotifyEvent(xev);
!
! XReparentEvent xe = xev.get_xreparent();
! if (insLog.isLoggable(Level.FINE)) {
! insLog.fine(xe.toString());
}
+ if (xe.get_window() != getWindow()) {
+ return;
+ }
! if (!isParented()) {
! if (isVisible()) {
! // Either the WM or the embedder exited
! XWM.getWM().unshadeKludge(this);
! if (!isEmbedded()) {
! XWM.reset();
}
! setInsets(null);
! } //else: The window just got hidden
! } else {
! // We just got parented: prepare stuff to recalculate the insets,
! // and to readjust the bounds if needed
! reparentNotifySerial = xe.get_serial();
! numOfConfigureNotifyJustAfterReparentNotify = 0;
!
! setNativeInsets(null);
! needToAdjustBounds();
}
}
+
+ protected boolean isInitialReshape() {
+ return false;
}
! public void handleMoved(Point loc) {
! ComponentAccessor.setX((Component)target, loc.x);
! ComponentAccessor.setY((Component)target, loc.y);
! postEvent(new ComponentEvent(target, ComponentEvent.COMPONENT_MOVED));
}
+
public void revalidate() {
XToolkit.executeOnEventHandlerThread(target, new Runnable() {
public void run() {
target.invalidate();
target.validate();
}
});
}
boolean gravityBug() {
return XWM.configureGravityBuggy();
}
// The height of area used to display current active input method
*** 477,542 ****
updateSizeHints(dimensions);
}
// Coordinates are that of the target
// Called only on Toolkit thread
! public void reshape(WindowDimensions newDimensions, int op,
! boolean userReshape)
{
if (insLog.isLoggable(Level.FINE)) {
! insLog.fine("Reshaping " + this + " to " + newDimensions + " op " + op + " user reshape " + userReshape);
! }
! if (userReshape) {
! // We handle only userReshape == true cases. It means that
! // if the window manager or any other part of the windowing
! // system sets inappropriate size for this window, we can
! // do nothing but accept it.
! Rectangle newBounds = newDimensions.getBounds();
! Insets insets = newDimensions.getInsets();
! // Inherit isClientSizeSet from newDimensions
! if (newDimensions.isClientSizeSet()) {
! newBounds = new Rectangle(newBounds.x, newBounds.y,
! newBounds.width - insets.left - insets.right,
! newBounds.height - insets.top - insets.bottom);
! }
! newDimensions = new WindowDimensions(newBounds, insets, newDimensions.isClientSizeSet());
}
XToolkit.awtLock();
try {
! if (!isReparented() || !isVisible()) {
! insLog.log(Level.FINE, "- not reparented({0}) or not visible({1}), default reshape",
! new Object[] {Boolean.valueOf(isReparented()), Boolean.valueOf(visible)});
!
! // Fix for 6323293.
! // This actually is needed to preserve compatibility with previous releases -
! // some of licensees are expecting componentMoved event on invisible one while
! // its location changes.
Point oldLocation = getLocation();
! Point newLocation = new Point(ComponentAccessor.getX((Component)target),
! ComponentAccessor.getY((Component)target));
! if (!newLocation.equals(oldLocation)) {
! handleMoved(newDimensions);
}
! dimensions = new WindowDimensions(newDimensions);
! updateSizeHints(dimensions);
! Rectangle client = dimensions.getClientRect();
! checkShellRect(client);
! setShellBounds(client);
! if (content != null &&
! !content.getSize().equals(newDimensions.getSize()))
{
! reconfigureContentWindow(newDimensions);
}
return;
}
! int wm = XWM.getWMID();
! updateChildrenSizes();
! applyGuessedInsets();
Rectangle shellRect = newDimensions.getClientRect();
if (gravityBug()) {
Insets in = newDimensions.getInsets();
--- 529,627 ----
updateSizeHints(dimensions);
}
// Coordinates are that of the target
// Called only on Toolkit thread
! private void reshape(WindowDimensions newDimensions, int op)
{
if (insLog.isLoggable(Level.FINE)) {
! insLog.fine("Reshaping " + this + " to " + newDimensions +
! "; op " + operationToString(op));
}
XToolkit.awtLock();
try {
! if (!isVisible()) {
! Rectangle client = newDimensions.getClientRect();
! checkShellRect(client);
! setShellBounds(client);
!
! reportReshape(newDimensions);
! } else {
! requestReshape(newDimensions, op);
! }
! } finally {
! XToolkit.awtUnlock();
! }
! }
!
! /**
! * Sets window dimensions and propagates the changes to the target sending
! * corresponding events if needed.
! *
! * MUST be invoked under the AWTLock.
! */
! private void reportReshape(WindowDimensions newDims) {
! if (insLog.isLoggable(Level.FINE)) {
! insLog.fine("" + newDims);
! }
!
! final Insets insets = newDims.getInsets();
! if (!insets.equals(dimensions.getInsets())) {
! // Recalculate the minimum size of the client area
! updateMinSizeHints(insets);
! }
!
! // If the client area size changes, we need to revalidate the target.
! // This may happen in the XContentWindow.setContentBounds(). If this
! // does not happen there, we need to dispatch the operation here.
! final boolean needRevalidate =
! !dimensions.getClientSize().equals(newDims.getClientSize());
!
! checkIfOnNewScreen(newDims.getBounds());
!
Point oldLocation = getLocation();
+ dimensions = newDims;
+ if (!getLocation().equals(oldLocation)) {
+ handleMoved(getLocation());
+ }
! if (!reconfigureContentWindow(dimensions) && needRevalidate) {
! revalidate();
! }
! updateChildrenSizes();
! repositionSecurityWarning();
}
! private void reportOrAdjust(WindowDimensions newDims,
! boolean handlingConfigureNotify)
{
! if (dimensions.equals(newDims) && !areBoundsAdjusting()) {
! // If nothing has changed and we're already adjusted, return
! if (insLog.isLoggable(Level.FINE)) {
! insLog.fine("Ignored: nothing changed: " + newDims);
! }
! return;
}
+ if (adjustBounds(newDims, handlingConfigureNotify)) {
+ // We expect another ConfigureNotify
return;
}
! reportReshape(newDims);
! }
!
! /**
! * Requests the system to reshape the window.
! *
! * MUST be invoked under the AWTLock.
! */
! private void requestReshape(WindowDimensions newDimensions, int op) {
! if (insLog.isLoggable(Level.FINE)) {
! insLog.fine("Request reshape: " + newDimensions + "; op: " +
! operationToString(op));
! }
Rectangle shellRect = newDimensions.getClientRect();
if (gravityBug()) {
Insets in = newDimensions.getInsets();
*** 566,590 ****
XWM.setShellNotResizable(this, newDimensions, shellRect, true);
if (op == SET_BOUNDS) {
setShellPosition(shellRect);
}
}
-
- reconfigureContentWindow(newDimensions);
- } finally {
- XToolkit.awtUnlock();
- }
}
/**
! * @param x, y, width, heith - dimensions of the window with insets
*/
! private void reshape(int x, int y, int width, int height, int operation,
! boolean userReshape)
! {
! Rectangle newRec;
! boolean setClient = false;
WindowDimensions dims = new WindowDimensions(dimensions);
switch (operation & (~NO_EMBEDDED_CHECK)) {
case SET_LOCATION:
// Set location always sets bounds location. However, until the window is mapped we
// should use client coordinates
--- 651,669 ----
XWM.setShellNotResizable(this, newDimensions, shellRect, true);
if (op == SET_BOUNDS) {
setShellPosition(shellRect);
}
}
}
+ // This method gets overriden in XFramePeer & XDialogPeer.
+ abstract boolean isTargetUndecorated();
+
/**
! * @see java.awt.peer.ComponentPeer#setBounds
*/
! public void setBounds(int x, int y, int width, int height, int operation) {
WindowDimensions dims = new WindowDimensions(dimensions);
switch (operation & (~NO_EMBEDDED_CHECK)) {
case SET_LOCATION:
// Set location always sets bounds location. However, until the window is mapped we
// should use client coordinates
*** 595,770 ****
// should use client coordinates
dims.setSize(width, height);
break;
case SET_CLIENT_SIZE: {
// Sets client rect size. Width and height contain insets.
! Insets in = currentInsets;
width -= in.left+in.right;
height -= in.top+in.bottom;
dims.setClientSize(width, height);
break;
}
case SET_BOUNDS:
default:
dims.setLocation(x, y);
dims.setSize(width, height);
break;
}
! if (insLog.isLoggable(Level.FINE)) insLog.log(Level.FINE, "For the operation {0} new dimensions are {1}",
! new Object[] {operationToString(operation), dims});
!
! reshape(dims, operation, userReshape);
}
- // This method gets overriden in XFramePeer & XDialogPeer.
- abstract boolean isTargetUndecorated();
-
/**
! * @see java.awt.peer.ComponentPeer#setBounds
*/
! public void setBounds(int x, int y, int width, int height, int op) {
! // TODO: Rewrite with WindowDimensions
! reshape(x, y, width, height, op, true);
! validateSurface();
! }
!
! // Coordinates are that of the shell
! void reconfigureContentWindow(WindowDimensions dims) {
if (content == null) {
insLog.fine("WARNING: Content window is null");
! return;
}
! content.setContentBounds(dims);
}
! boolean no_reparent_artifacts = false;
! public void handleConfigureNotifyEvent(XEvent xev) {
! assert (SunToolkit.isAWTLockHeldByCurrentThread());
! XConfigureEvent xe = xev.get_xconfigure();
! insLog.log(Level.FINE, "Configure notify {0}", new Object[] {xe});
! // XXX: should really only consider synthetic events, but
! if (isReparented()) {
! configure_seen = true;
}
-
- if (!isMaximized()
- && (xe.get_serial() == reparent_serial || xe.get_window() != getShell())
- && !no_reparent_artifacts)
- {
- insLog.fine("- reparent artifact, skipping");
- return;
}
- no_reparent_artifacts = false;
/**
! * When there is a WM we receive some CN before being visible and after.
! * We should skip all CN which are before being visible, because we assume
! * the gravity is in action while it is not yet.
! *
! * When there is no WM we receive CN only _before_ being visible.
! * We should process these CNs.
*/
! if (!isVisible() && XWM.getWMID() != XWM.NO_WM) {
! insLog.fine(" - not visible, skipping");
! return;
}
! /*
! * Some window managers configure before we are reparented and
! * the send event flag is set! ugh... (Enlighetenment for one,
! * possibly MWM as well). If we haven't been reparented yet
! * this is just the WM shuffling us into position. Ignore
! * it!!!! or we wind up in a bogus location.
*/
! int runningWM = XWM.getWMID();
! if (insLog.isLoggable(Level.FINE)) {
! insLog.log(Level.FINE, "reparented={0}, visible={1}, WM={2}, decorations={3}",
! new Object[] {isReparented(), isVisible(), runningWM, getDecorations()});
}
! if (!isReparented() && isVisible() && runningWM != XWM.NO_WM
! && !XWM.isNonReparentingWM()
! && getDecorations() != XWindowAttributesData.AWT_DECOR_NONE) {
! insLog.fine("- visible but not reparented, skipping");
! return;
}
! //Last chance to correct insets
! if (!insets_corrected && getDecorations() != XWindowAttributesData.AWT_DECOR_NONE) {
! long parent = XlibUtil.getParentWindow(window);
! Insets correctWM = (parent != -1) ? XWM.getWM().getInsets(this, window, parent) : null;
! if (insLog.isLoggable(Level.FINER)) {
! if (correctWM != null) {
! insLog.finer("Configure notify - insets : " + correctWM);
! } else {
! insLog.finer("Configure notify - insets are still not available");
}
}
- if (correctWM != null) {
- handleCorrectInsets(correctWM);
- } else {
- //Only one attempt to correct insets is made (to lower risk)
- //if insets are still not available we simply set the flag
- insets_corrected = true;
}
}
! updateChildrenSizes();
! // Bounds of the window
! Rectangle targetBounds = new Rectangle(ComponentAccessor.getX((Component)target),
! ComponentAccessor.getY((Component)target),
! ComponentAccessor.getWidth((Component)target),
! ComponentAccessor.getHeight((Component)target));
!
! Point newLocation = targetBounds.getLocation();
! if (xe.get_send_event() || runningWM == XWM.NO_WM || XWM.isNonReparentingWM()) {
! // Location, Client size + insets
! newLocation = new Point(xe.get_x() - currentInsets.left, xe.get_y() - currentInsets.top);
! } else {
! // CDE/MWM/Metacity/Sawfish bug: if shell is resized using
! // top or left border, we don't receive synthetic
! // ConfigureNotify, only the one from X with zero
! // coordinates. This is the workaround to get real
! // location, 6261336
! switch (XWM.getWMID()) {
! case XWM.CDE_WM:
! case XWM.MOTIF_WM:
! case XWM.METACITY_WM:
! case XWM.SAWFISH_WM:
{
! Point xlocation = queryXLocation();
! if (log.isLoggable(Level.FINE)) log.log(Level.FINE, "New X location: {0}", new Object[]{xlocation});
! if (xlocation != null) {
! newLocation = xlocation;
}
! break;
}
- default:
- break;
}
}
! WindowDimensions newDimensions =
! new WindowDimensions(newLocation,
! new Dimension(xe.get_width(), xe.get_height()),
! copy(currentInsets),
! true);
! insLog.log(Level.FINER, "Insets are {0}, new dimensions {1}",
! new Object[] {currentInsets, newDimensions});
! checkIfOnNewScreen(newDimensions.getBounds());
! Point oldLocation = getLocation();
! dimensions = newDimensions;
! if (!newLocation.equals(oldLocation)) {
! handleMoved(newDimensions);
}
- reconfigureContentWindow(newDimensions);
- updateChildrenSizes();
! repositionSecurityWarning();
}
private void checkShellRectSize(Rectangle shellRect) {
if (shellRect.width < 0) {
shellRect.width = 1;
--- 674,963 ----
// should use client coordinates
dims.setSize(width, height);
break;
case SET_CLIENT_SIZE: {
// Sets client rect size. Width and height contain insets.
! // Also update the insets to the latest known value to decrease
! // (or even eliminate) the bounds adjustment after showing
! // the window.
! Insets in = getNativeInsets();
width -= in.left+in.right;
height -= in.top+in.bottom;
dims.setClientSize(width, height);
+ dims.setInsets(in);
break;
}
case SET_BOUNDS:
default:
dims.setLocation(x, y);
dims.setSize(width, height);
break;
}
! reshape(dims, operation);
! validateSurface();
}
/**
! * Sets the content window bounds.
! *
! * @return whether a COMPONENT_RESIZED has been sent
*/
! boolean reconfigureContentWindow(WindowDimensions dims) {
if (content == null) {
insLog.fine("WARNING: Content window is null");
! return false;
}
! return content.setContentBounds(dims);
}
! /**
! * Indicates if the adjustBounds() needs to be invoked.
! * Synchronization: state lock.
! */
! private boolean areBoundsAdjusted = false;
! /**
! * Forces the system to re-adjust the bounds of the window after it has
! * been finally adopted by the windowing system.
! */
! private void needToAdjustBounds() {
! synchronized (getStateLock()) {
! areBoundsAdjusted = false;
}
}
/**
! * Indicates if the window bounds has not yet been finally configured by
! * the X server/window manager.
*/
! public boolean areBoundsAdjusting() {
! synchronized (getStateLock()) {
! return !areBoundsAdjusted;
! }
}
! // XXX: Perhaps the following two might be replaced with Window.isSizeSet,
! // isLocationSet? Just like we have Window.isPacked...
! /**
! * Indicates if the size hints of the window specify a position requested
! * by the user's code.
*/
! private boolean isUserSpecifiedPositionSet() {
! return (getHints().get_flags() &
! (XUtilConstants.USPosition | XUtilConstants.PPosition)) != 0;
}
!
! /**
! * Indicates if the size hints of the window specify a position requested
! * by the user's code.
! */
! private boolean isUserSpecifiedSizeSet() {
! return (getHints().get_flags() &
! (XUtilConstants.USSize | XUtilConstants.PSize)) != 0;
}
!
! /**
! * Adjust the bounds of the window.
! *
! * @return true if an adjustment has taken place. false if the new bounds
! * are OK.
! */
! private boolean adjustBounds(WindowDimensions newDims,
! boolean handlingConfigureNotify)
! {
! synchronized (getStateLock()) {
! if (areBoundsAdjusted) {
! return false;
}
+ // We have to adjust bounds upon showing once.
+ // We also may adjust them several times before showing - e.g.
+ // when we receive the PropertyNotify event with the extents.
+ if (handlingConfigureNotify && isVisible()) {
+ insLog.log(Level.FINE, "Final adjustment");
+ areBoundsAdjusted = true;
}
}
+
+ if (isMaximized()) {
+ return false;
}
! int operation = 0;
! boolean isPacked = AWTAccessor.getWindowAccessor().
! isPacked((Window)target);
! if (!newDims.getClientSize().equals(dimensions.getClientSize())
! && isPacked)
{
! // The client area size calculated via pack() needs to be preserved
! operation = SET_SIZE;
! } else
! if (!newDims.getSize().equals(dimensions.getSize())
! && isUserSpecifiedSizeSet())
! {
! // The size set via setSize()/setBounds() needs to be preserved
! operation = SET_SIZE;
}
!
! if (isUserSpecifiedPositionSet() &&
! !newDims.getLocation().equals(dimensions.getLocation()))
! {
! // The user also requested a specific position
! if (operation == 0) {
! operation = SET_LOCATION;
! } else {
! operation = SET_BOUNDS;
}
}
+
+ if (operation == 0) {
+ insLog.fine("No adjustment needed");
+ return false;
}
! WindowDimensions dims = new WindowDimensions(
! dimensions.getLocation(),
! isPacked ? dimensions.getClientSize() : dimensions.getSize(),
! newDims.getInsets(),
! isPacked);
! if (insLog.isLoggable(Level.FINE)) {
! insLog.fine("Request: " + dims + "; operation=" +
! operationToString(operation));
! }
! requestReshape(dims, operation);
! return true;
! }
!
! @Override
! public void handleConfigureNotifyEvent(XEvent xev) {
! // Note: we don't call super because the XWindowPeer immediately calls
! // the checkIfOnNewScreen() assuming the bounds are correct. This
! // is not always correct for decorated peers.
! XConfigureEvent xe = xev.get_xconfigure();
! // Due to the SubstructureNotifyMask we should process only those
! // events that belong to us.
! if (xe.get_window() != getWindow()) {
! return;
}
! if (insLog.isLoggable(Level.FINE)) {
! insLog.fine("" + xe);
! insLog.fine("XWM.isRunning: " + XWM.isRunning());
! }
!
! // If there's a WM we have to ignore some events
! if (XWM.isRunning()) {
! // Ignore any events until after we become visible
! if (!isVisible()) {
! insLog.fine("Ignored: Not visible yet");
! needToAdjustBounds();
! return;
! }
!
! // We have not yet been parented by the WM
! if (mayBeReparented() && !isTargetUndecorated()) {
! insLog.fine("Ignored: Not parented yet");
! needToAdjustBounds();
! return;
! }
!
! // Just after reparenting we can receive a synthetic and/or real
! // event(s). Since sometimes we need to adjust the bounds of the
! // frame, we need to process only one of the events. Justification:
! // 1. Both events carry the same information: one from the X
! // server, the other from the WM.
! // 2. The adjustment operation is performed only once upon
! // processing the first ConfigureNotify event that is not
! // ignored.
! // 3. If the first event causes the adjustment to happen, the
! // second event will be considered as a normal, not ignored
! // event that may generate Java events and set incorrect
! // (not-yet-adjusted) bounds to the frame.
! // So generally, if the adjustment is needed, the first
! // ConfigureNotify that we should really process is the one caused
! // by the adjustment operation. So we process only the first
! // ConfigureNotify event having the same serial that the preceeding
! // ReparentNotify.
! //
! // There's one exception however: we do not ignore the events for
! // maximized frames. The real ConfigureNotify that we would like to
! // act upon usually is the third one (it carries the correct
! // maximized bounds). However, it has the same serial (which is
! // obvious), and what's worse - we can't reliably determine if the
! // window manager/X server send us exactly two events before that,
! // or maybe one of them might be not sent at all - and in this case
! // we would need to process the second event, not the third. So we
! // just process everything for a maximized frame. This does produce
! // absolutely meaningless bounds dancing (with events sent to the
! // user space), but at least this is backward-compatible and quite
! // reliable. Should we find a way to detect and process only the
! // very last of ConfigureNotify events sent with the same serial,
! // we would like to use this approach instead of the current
! // processing of the very first event only.
! if (xe.get_serial() == reparentNotifySerial && !isMaximized())
! {
! if (++numOfConfigureNotifyJustAfterReparentNotify > 1) {
! insLog.fine("Ignored: serial matches the ReparentNotify");
! return;
! }
! }
! }
!
! // At this point we can calculate some reliable insets
! Insets insets = getNativeInsets();
!
! // Note that in some cases this kind of event may be caused by the
! // changed insets (like if the theme changes, or something). However
! // it's difficult if at all possible to identify this situation, and
! // not confuse it with a regular reconfiguration w/o introducing some
! // serious performance degradation. So we only support changing the
! // insets:
! // a. when a reparenting WM exits/gets replaced.
! // b. when the window gets hidden/shown.
! // c. if the WM is smart enough to send the PropertyNotify
! // events with the updated extents.
!
! // x, y, width, height hold the coordinates of the whole frame
! // including the decorations.
! int x;
! int y;
!
! if (xe.get_send_event() || !isParented()) {
! // If the event is synthetic or we're not parented, the coordinates
! // are relative to the root window.
! x = xe.get_x() - insets.left;
! y = xe.get_y() - insets.top;
! } else {
! // The event is real and we're parented - the coordinates are
! // relative to the parent
! Point loc = null;
! if (XWM.isNoSyntheticConfigureNotifyOnLeftTopResize()) {
! // there's a bug in the WM, so ask the X server
! loc = queryXLocation();
! }
! if (loc == null) {
! // consider the current location unchanged
! // TODO: this may not be true... perhaps querying X in all cases is worthwhile?
! // after all: we already do this for Metacity which is quite common,
! // so we should not worry much about the performance.
! loc = getLocation();
! }
!
! x = loc.x;
! y = loc.y;
! }
!
! int width = xe.get_width() + insets.left + insets.right;
! int height = xe.get_height() + insets.top + insets.bottom;
!
! // Now apply the new bounds
! WindowDimensions d = new WindowDimensions(
! new Rectangle(x, y, width, height), insets, false);
! reportOrAdjust(d, true);
}
private void checkShellRectSize(Rectangle shellRect) {
if (shellRect.width < 0) {
shellRect.width = 1;
*** 830,858 ****
setResizable(winAttr.initialResizability);
}
public void setResizable(boolean resizable) {
int fs = winAttr.functions;
if (!isResizable() && resizable) {
! currentInsets = new Insets(0, 0, 0, 0);
! resetWMSetInsets();
! if (!isEmbedded()) {
! setReparented(false);
! }
winAttr.isResizable = resizable;
if ((fs & MWMConstants.MWM_FUNC_ALL) != 0) {
fs &= ~(MWMConstants.MWM_FUNC_RESIZE | MWMConstants.MWM_FUNC_MAXIMIZE);
} else {
fs |= (MWMConstants.MWM_FUNC_RESIZE | MWMConstants.MWM_FUNC_MAXIMIZE);
}
winAttr.functions = fs;
XWM.setShellResizable(this);
} else if (isResizable() && !resizable) {
! currentInsets = new Insets(0, 0, 0, 0);
! resetWMSetInsets();
! if (!isEmbedded()) {
! setReparented(false);
! }
winAttr.isResizable = resizable;
if ((fs & MWMConstants.MWM_FUNC_ALL) != 0) {
fs |= (MWMConstants.MWM_FUNC_RESIZE | MWMConstants.MWM_FUNC_MAXIMIZE);
} else {
fs &= ~(MWMConstants.MWM_FUNC_RESIZE | MWMConstants.MWM_FUNC_MAXIMIZE);
--- 1023,1043 ----
setResizable(winAttr.initialResizability);
}
public void setResizable(boolean resizable) {
int fs = winAttr.functions;
if (!isResizable() && resizable) {
! setNativeInsets(null);
winAttr.isResizable = resizable;
if ((fs & MWMConstants.MWM_FUNC_ALL) != 0) {
fs &= ~(MWMConstants.MWM_FUNC_RESIZE | MWMConstants.MWM_FUNC_MAXIMIZE);
} else {
fs |= (MWMConstants.MWM_FUNC_RESIZE | MWMConstants.MWM_FUNC_MAXIMIZE);
}
winAttr.functions = fs;
XWM.setShellResizable(this);
} else if (isResizable() && !resizable) {
! setNativeInsets(null);
winAttr.isResizable = resizable;
if ((fs & MWMConstants.MWM_FUNC_ALL) != 0) {
fs |= (MWMConstants.MWM_FUNC_RESIZE | MWMConstants.MWM_FUNC_MAXIMIZE);
} else {
fs &= ~(MWMConstants.MWM_FUNC_RESIZE | MWMConstants.MWM_FUNC_MAXIMIZE);
*** 909,925 ****
}
public Point getLocationOnScreen() {
XToolkit.awtLock();
try {
! if (configure_seen) {
return toGlobal(0,0);
} else {
Point location = target.getLocation();
! if (insLog.isLoggable(Level.FINE))
insLog.log(Level.FINE, "getLocationOnScreen {0} not reparented: {1} ",
new Object[] {this, location});
return location;
}
} finally {
XToolkit.awtUnlock();
}
--- 1094,1111 ----
}
public Point getLocationOnScreen() {
XToolkit.awtLock();
try {
! if (!areBoundsAdjusting()) {
return toGlobal(0,0);
} else {
Point location = target.getLocation();
! if (insLog.isLoggable(Level.FINE)) {
insLog.log(Level.FINE, "getLocationOnScreen {0} not reparented: {1} ",
new Object[] {this, location});
+ }
return location;
}
} finally {
XToolkit.awtUnlock();
}
*** 1055,1065 ****
final void dumpContent() {
dumpWindow("Content", getContentWindow());
}
final void dumpParent() {
long parent = XlibUtil.getParentWindow(getShell());
! if (parent != 0)
{
dumpWindow("Parent", parent);
}
else
{
--- 1241,1251 ----
final void dumpContent() {
dumpWindow("Content", getContentWindow());
}
final void dumpParent() {
long parent = XlibUtil.getParentWindow(getShell());
! if (parent != XConstants.None)
{
dumpWindow("Parent", parent);
}
else
{
*** 1098,1108 ****
boolean isMaximized() {
return false;
}
boolean isOverrideRedirect() {
- // return false;
return ((XToolkit)Toolkit.getDefaultToolkit()).isOverrideRedirect((Window)target);
}
public boolean requestWindowFocus(long time, boolean timeProvided) {
focusLog.fine("Request for decorated window focus");
--- 1284,1293 ----