|
Java example source code file (XWindowPeer.java)
This example Java source code file (XWindowPeer.java) is included in the alvinalexander.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn
Java by Example" TM.
Learn more about this Java project at its project page.
The XWindowPeer.java Java example source code
/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.X11;
import java.awt.*;
import java.awt.event.ComponentEvent;
import java.awt.event.FocusEvent;
import java.awt.event.WindowEvent;
import java.awt.peer.ComponentPeer;
import java.awt.peer.WindowPeer;
import java.io.UnsupportedEncodingException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicBoolean;
import sun.util.logging.PlatformLogger;
import sun.awt.AWTAccessor;
import sun.awt.DisplayChangedListener;
import sun.awt.SunToolkit;
import sun.awt.X11GraphicsDevice;
import sun.awt.X11GraphicsEnvironment;
import sun.awt.IconInfo;
import sun.java2d.pipe.Region;
class XWindowPeer extends XPanelPeer implements WindowPeer,
DisplayChangedListener {
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XWindowPeer");
private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.X11.focus.XWindowPeer");
private static final PlatformLogger insLog = PlatformLogger.getLogger("sun.awt.X11.insets.XWindowPeer");
private static final PlatformLogger grabLog = PlatformLogger.getLogger("sun.awt.X11.grab.XWindowPeer");
private static final PlatformLogger iconLog = PlatformLogger.getLogger("sun.awt.X11.icon.XWindowPeer");
// should be synchronized on awtLock
private static Set<XWindowPeer> windows = new HashSet();
private boolean cachedFocusableWindow;
XWarningWindow warningWindow;
private boolean alwaysOnTop;
private boolean locationByPlatform;
Dialog modalBlocker;
boolean delayedModalBlocking = false;
Dimension targetMinimumSize = null;
private XWindowPeer ownerPeer;
// used for modal blocking to keep existing z-order
protected XWindowPeer prevTransientFor, nextTransientFor;
// value of WM_TRANSIENT_FOR hint set on this window
private XWindowPeer curRealTransientFor;
private boolean grab = false; // Whether to do a grab during showing
private boolean isMapped = false; // Is this window mapped or not
private boolean mustControlStackPosition = false; // Am override-redirect not on top
private XEventDispatcher rootPropertyEventDispatcher = null;
private static final AtomicBoolean isStartupNotificationRemoved = new AtomicBoolean();
/*
* Focus related flags
*/
private boolean isUnhiding = false; // Is the window unhiding.
private boolean isBeforeFirstMapNotify = false; // Is the window (being shown) between
// setVisible(true) & handleMapNotify().
/**
* The type of the window.
*
* The type is supposed to be immutable while the peer object exists.
* The value gets initialized in the preInit() method.
*/
private Window.Type windowType = Window.Type.NORMAL;
public final Window.Type getWindowType() {
return windowType;
}
// It need to be accessed from XFramePeer.
protected Vector <ToplevelStateListener> toplevelStateListeners = new Vector();
XWindowPeer(XCreateWindowParams params) {
super(params.putIfNull(PARENT_WINDOW, Long.valueOf(0)));
}
XWindowPeer(Window target) {
super(new XCreateWindowParams(new Object[] {
TARGET, target,
PARENT_WINDOW, Long.valueOf(0)}));
}
/*
* This constant defines icon size recommended for using.
* Apparently, we should use XGetIconSizes which should
* return icon sizes would be most appreciated by the WM.
* However, XGetIconSizes always returns 0 for some reason.
* So the constant has been introduced.
*/
private static final int PREFERRED_SIZE_FOR_ICON = 128;
/*
* Sometimes XChangeProperty(_NET_WM_ICON) doesn't work if
* image buffer is too large. This constant holds maximum
* length of buffer which can be used with _NET_WM_ICON hint.
* It holds int's value.
*/
private static final int MAXIMUM_BUFFER_LENGTH_NET_WM_ICON = (2<<15) - 1;
void preInit(XCreateWindowParams params) {
target = (Component)params.get(TARGET);
windowType = ((Window)target).getType();
params.put(REPARENTED,
Boolean.valueOf(isOverrideRedirect() || isSimpleWindow()));
super.preInit(params);
params.putIfNull(BIT_GRAVITY, Integer.valueOf(XConstants.NorthWestGravity));
long eventMask = 0;
if (params.containsKey(EVENT_MASK)) {
eventMask = ((Long)params.get(EVENT_MASK));
}
eventMask |= XConstants.VisibilityChangeMask;
params.put(EVENT_MASK, eventMask);
XA_NET_WM_STATE = XAtom.get("_NET_WM_STATE");
params.put(OVERRIDE_REDIRECT, Boolean.valueOf(isOverrideRedirect()));
SunToolkit.awtLock();
try {
windows.add(this);
} finally {
SunToolkit.awtUnlock();
}
cachedFocusableWindow = isFocusableWindow();
Font f = target.getFont();
if (f == null) {
f = XWindow.getDefaultFont();
target.setFont(f);
// we should not call setFont because it will call a repaint
// which the peer may not be ready to do yet.
}
Color c = target.getBackground();
if (c == null) {
Color background = SystemColor.window;
target.setBackground(background);
// we should not call setBackGround because it will call a repaint
// which the peer may not be ready to do yet.
}
c = target.getForeground();
if (c == null) {
target.setForeground(SystemColor.windowText);
// we should not call setForeGround because it will call a repaint
// which the peer may not be ready to do yet.
}
alwaysOnTop = ((Window)target).isAlwaysOnTop() && ((Window)target).isAlwaysOnTopSupported();
GraphicsConfiguration gc = getGraphicsConfiguration();
((X11GraphicsDevice)gc.getDevice()).addDisplayChangedListener(this);
}
protected String getWMName() {
String name = target.getName();
if (name == null || name.trim().equals("")) {
name = " ";
}
return name;
}
private static native String getLocalHostname();
private static native int getJvmPID();
void postInit(XCreateWindowParams params) {
super.postInit(params);
// Init WM_PROTOCOLS atom
initWMProtocols();
// Set _NET_WM_PID and WM_CLIENT_MACHINE using this JVM
XAtom.get("WM_CLIENT_MACHINE").setProperty(getWindow(), getLocalHostname());
XAtom.get("_NET_WM_PID").setCard32Property(getWindow(), getJvmPID());
// Set WM_TRANSIENT_FOR and group_leader
Window t_window = (Window)target;
Window owner = t_window.getOwner();
if (owner != null) {
ownerPeer = (XWindowPeer)owner.getPeer();
if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
focusLog.finer("Owner is " + owner);
focusLog.finer("Owner peer is " + ownerPeer);
focusLog.finer("Owner X window " + Long.toHexString(ownerPeer.getWindow()));
focusLog.finer("Owner content X window " + Long.toHexString(ownerPeer.getContentWindow()));
}
// as owner window may be an embedded window, we must get a toplevel window
// to set as TRANSIENT_FOR hint
long ownerWindow = ownerPeer.getWindow();
if (ownerWindow != 0) {
XToolkit.awtLock();
try {
// Set WM_TRANSIENT_FOR
if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
focusLog.fine("Setting transient on " + Long.toHexString(getWindow())
+ " for " + Long.toHexString(ownerWindow));
}
setToplevelTransientFor(this, ownerPeer, false, true);
// Set group leader
XWMHints hints = getWMHints();
hints.set_flags(hints.get_flags() | (int)XUtilConstants.WindowGroupHint);
hints.set_window_group(ownerWindow);
XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData);
}
finally {
XToolkit.awtUnlock();
}
}
}
if (owner != null || isSimpleWindow()) {
XNETProtocol protocol = XWM.getWM().getNETProtocol();
if (protocol != null && protocol.active()) {
XToolkit.awtLock();
try {
XAtomList net_wm_state = getNETWMState();
net_wm_state.add(protocol.XA_NET_WM_STATE_SKIP_TASKBAR);
setNETWMState(net_wm_state);
} finally {
XToolkit.awtUnlock();
}
}
}
// Init warning window(for applets)
if (((Window)target).getWarningString() != null) {
// accessSystemTray permission allows to display TrayIcon, TrayIcon tooltip
// and TrayIcon balloon windows without a warning window.
if (!AWTAccessor.getWindowAccessor().isTrayIconWindow((Window)target)) {
warningWindow = new XWarningWindow((Window)target, getWindow(), this);
}
}
setSaveUnder(true);
updateIconImages();
updateShape();
updateOpacity();
// no need in updateOpaque() as it is no-op
}
public void updateIconImages() {
Window target = (Window)this.target;
java.util.List<Image> iconImages = ((Window)target).getIconImages();
XWindowPeer ownerPeer = getOwnerPeer();
winAttr.icons = new ArrayList<IconInfo>();
if (iconImages.size() != 0) {
//read icon images from target
winAttr.iconsInherited = false;
for (Iterator<Image> i = iconImages.iterator(); i.hasNext(); ) {
Image image = i.next();
if (image == null) {
if (log.isLoggable(PlatformLogger.Level.FINEST)) {
log.finest("XWindowPeer.updateIconImages: Skipping the image passed into Java because it's null.");
}
continue;
}
IconInfo iconInfo;
try {
iconInfo = new IconInfo(image);
} catch (Exception e){
if (log.isLoggable(PlatformLogger.Level.FINEST)) {
log.finest("XWindowPeer.updateIconImages: Perhaps the image passed into Java is broken. Skipping this icon.");
}
continue;
}
if (iconInfo.isValid()) {
winAttr.icons.add(iconInfo);
}
}
}
// Fix for CR#6425089
winAttr.icons = normalizeIconImages(winAttr.icons);
if (winAttr.icons.size() == 0) {
//target.icons is empty or all icon images are broken
if (ownerPeer != null) {
//icon is inherited from parent
winAttr.iconsInherited = true;
winAttr.icons = ownerPeer.getIconInfo();
} else {
//default icon is used
winAttr.iconsInherited = false;
winAttr.icons = getDefaultIconInfo();
}
}
recursivelySetIcon(winAttr.icons);
}
/*
* Sometimes XChangeProperty(_NET_WM_ICON) doesn't work if
* image buffer is too large. This function help us accommodate
* initial list of the icon images to certainly-acceptable.
* It does scale some of these icons to appropriate size
* if it's necessary.
*/
static java.util.List<IconInfo> normalizeIconImages(java.util.List icons) {
java.util.List<IconInfo> result = new ArrayList();
int totalLength = 0;
boolean haveLargeIcon = false;
for (IconInfo icon : icons) {
int width = icon.getWidth();
int height = icon.getHeight();
int length = icon.getRawLength();
if (width > PREFERRED_SIZE_FOR_ICON || height > PREFERRED_SIZE_FOR_ICON) {
if (haveLargeIcon) {
continue;
}
int scaledWidth = width;
int scaledHeight = height;
while (scaledWidth > PREFERRED_SIZE_FOR_ICON ||
scaledHeight > PREFERRED_SIZE_FOR_ICON) {
scaledWidth = scaledWidth / 2;
scaledHeight = scaledHeight / 2;
}
icon.setScaledSize(scaledWidth, scaledHeight);
length = icon.getRawLength();
}
if (totalLength + length <= MAXIMUM_BUFFER_LENGTH_NET_WM_ICON) {
totalLength += length;
result.add(icon);
if (width > PREFERRED_SIZE_FOR_ICON || height > PREFERRED_SIZE_FOR_ICON) {
haveLargeIcon = true;
}
}
}
if (iconLog.isLoggable(PlatformLogger.Level.FINEST)) {
iconLog.finest(">>> Length_ of buffer of icons data: " + totalLength +
", maximum length: " + MAXIMUM_BUFFER_LENGTH_NET_WM_ICON);
}
return result;
}
/*
* Dumps each icon from the list
*/
static void dumpIcons(java.util.List<IconInfo> icons) {
if (iconLog.isLoggable(PlatformLogger.Level.FINEST)) {
iconLog.finest(">>> Sizes of icon images:");
for (Iterator<IconInfo> i = icons.iterator(); i.hasNext(); ) {
iconLog.finest(" {0}", i.next());
}
}
}
public void recursivelySetIcon(java.util.List<IconInfo> icons) {
dumpIcons(winAttr.icons);
setIconHints(icons);
Window target = (Window)this.target;
Window[] children = target.getOwnedWindows();
int cnt = children.length;
for (int i = 0; i < cnt; i++) {
ComponentPeer childPeer = children[i].getPeer();
if (childPeer != null && childPeer instanceof XWindowPeer) {
if (((XWindowPeer)childPeer).winAttr.iconsInherited) {
((XWindowPeer)childPeer).winAttr.icons = icons;
((XWindowPeer)childPeer).recursivelySetIcon(icons);
}
}
}
}
java.util.List<IconInfo> getIconInfo() {
return winAttr.icons;
}
void setIconHints(java.util.List<IconInfo> icons) {
//This does nothing for XWindowPeer,
//It's overriden in XDecoratedPeer
}
private static ArrayList<IconInfo> defaultIconInfo;
protected synchronized static java.util.List<IconInfo> getDefaultIconInfo() {
if (defaultIconInfo == null) {
defaultIconInfo = new ArrayList<IconInfo>();
if (XlibWrapper.dataModel == 32) {
defaultIconInfo.add(new IconInfo(sun.awt.AWTIcon32_java_icon16_png.java_icon16_png));
defaultIconInfo.add(new IconInfo(sun.awt.AWTIcon32_java_icon24_png.java_icon24_png));
defaultIconInfo.add(new IconInfo(sun.awt.AWTIcon32_java_icon32_png.java_icon32_png));
defaultIconInfo.add(new IconInfo(sun.awt.AWTIcon32_java_icon48_png.java_icon48_png));
} else {
defaultIconInfo.add(new IconInfo(sun.awt.AWTIcon64_java_icon16_png.java_icon16_png));
defaultIconInfo.add(new IconInfo(sun.awt.AWTIcon64_java_icon24_png.java_icon24_png));
defaultIconInfo.add(new IconInfo(sun.awt.AWTIcon64_java_icon32_png.java_icon32_png));
defaultIconInfo.add(new IconInfo(sun.awt.AWTIcon64_java_icon48_png.java_icon48_png));
}
}
return defaultIconInfo;
}
private void updateShape() {
// Shape shape = ((Window)target).getShape();
Shape shape = AWTAccessor.getWindowAccessor().getShape((Window)target);
if (shape != null) {
applyShape(Region.getInstance(shape, null));
}
}
private void updateOpacity() {
// float opacity = ((Window)target).getOpacity();
float opacity = AWTAccessor.getWindowAccessor().getOpacity((Window)target);
if (opacity < 1.0f) {
setOpacity(opacity);
}
}
public void updateMinimumSize() {
//This function only saves minimumSize value in XWindowPeer
//Setting WMSizeHints is implemented in XDecoratedPeer
targetMinimumSize = (((Component)target).isMinimumSizeSet()) ?
((Component)target).getMinimumSize() : null;
}
public Dimension getTargetMinimumSize() {
return (targetMinimumSize == null) ? null : new Dimension(targetMinimumSize);
}
public XWindowPeer getOwnerPeer() {
return ownerPeer;
}
//Fix for 6318144: PIT:Setting Min Size bigger than current size enlarges
//the window but fails to revalidate, Sol-CDE
//This bug is regression for
//5025858: Resizing a decorated frame triggers componentResized event twice.
//Since events are not posted from Component.setBounds we need to send them here.
//Note that this function is overriden in XDecoratedPeer so event
//posting is not changing for decorated peers
public void setBounds(int x, int y, int width, int height, int op) {
XToolkit.awtLock();
try {
Rectangle oldBounds = getBounds();
super.setBounds(x, y, width, height, op);
Rectangle bounds = getBounds();
XSizeHints hints = getHints();
setSizeHints(hints.get_flags() | XUtilConstants.PPosition | XUtilConstants.PSize,
bounds.x, bounds.y, bounds.width, bounds.height);
XWM.setMotifDecor(this, false, 0, 0);
boolean isResized = !bounds.getSize().equals(oldBounds.getSize());
boolean isMoved = !bounds.getLocation().equals(oldBounds.getLocation());
if (isMoved || isResized) {
repositionSecurityWarning();
}
if (isResized) {
postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_RESIZED));
}
if (isMoved) {
postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_MOVED));
}
} finally {
XToolkit.awtUnlock();
}
}
void updateFocusability() {
updateFocusableWindowState();
XToolkit.awtLock();
try {
XWMHints hints = getWMHints();
hints.set_flags(hints.get_flags() | (int)XUtilConstants.InputHint);
hints.set_input(false/*isNativelyNonFocusableWindow() ? (0):(1)*/);
XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData);
}
finally {
XToolkit.awtUnlock();
}
}
public Insets getInsets() {
return new Insets(0, 0, 0, 0);
}
// NOTE: This method may be called by privileged threads.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
public void handleIconify() {
postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_ICONIFIED));
}
// NOTE: This method may be called by privileged threads.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
public void handleDeiconify() {
postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_DEICONIFIED));
}
// NOTE: This method may be called by privileged threads.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
public void handleStateChange(int oldState, int newState) {
postEvent(new WindowEvent((Window)target,
WindowEvent.WINDOW_STATE_CHANGED,
oldState, newState));
}
/**
* DEPRECATED: Replaced by getInsets().
*/
public Insets insets() {
return getInsets();
}
boolean isAutoRequestFocus() {
if (XToolkit.isToolkitThread()) {
return AWTAccessor.getWindowAccessor().isAutoRequestFocus((Window)target);
} else {
return ((Window)target).isAutoRequestFocus();
}
}
/*
* Retrives real native focused window and converts it into Java peer.
*/
static XWindowPeer getNativeFocusedWindowPeer() {
XBaseWindow baseWindow = XToolkit.windowToXWindow(xGetInputFocus());
return (baseWindow instanceof XWindowPeer) ? (XWindowPeer)baseWindow :
(baseWindow instanceof XFocusProxyWindow) ?
((XFocusProxyWindow)baseWindow).getOwner() : null;
}
/*
* Retrives real native focused window and converts it into Java window.
*/
static Window getNativeFocusedWindow() {
XWindowPeer peer = getNativeFocusedWindowPeer();
return peer != null ? (Window)peer.target : null;
}
boolean isFocusableWindow() {
if (XToolkit.isToolkitThread() || SunToolkit.isAWTLockHeldByCurrentThread())
{
return cachedFocusableWindow;
} else {
return ((Window)target).isFocusableWindow();
}
}
/* WARNING: don't call client code in this method! */
boolean isFocusedWindowModalBlocker() {
return false;
}
long getFocusTargetWindow() {
return getContentWindow();
}
/**
* Returns whether or not this window peer has native X window
* configured as non-focusable window. It might happen if:
* - Java window is non-focusable
* - Java window is simple Window(not Frame or Dialog)
*/
boolean isNativelyNonFocusableWindow() {
if (XToolkit.isToolkitThread() || SunToolkit.isAWTLockHeldByCurrentThread())
{
return isSimpleWindow() || !cachedFocusableWindow;
} else {
return isSimpleWindow() || !(((Window)target).isFocusableWindow());
}
}
public void handleWindowFocusIn_Dispatch() {
if (EventQueue.isDispatchThread()) {
XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow((Window) target);
WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS);
SunToolkit.setSystemGenerated(we);
target.dispatchEvent(we);
}
}
public void handleWindowFocusInSync(long serial) {
WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS);
XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow((Window) target);
sendEvent(we);
}
// NOTE: This method may be called by privileged threads.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
public void handleWindowFocusIn(long serial) {
WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS);
/* wrap in Sequenced, then post*/
XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow((Window) target);
postEvent(wrapInSequenced((AWTEvent) we));
}
// NOTE: This method may be called by privileged threads.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
public void handleWindowFocusOut(Window oppositeWindow, long serial) {
WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_LOST_FOCUS, oppositeWindow);
XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow(null);
XKeyboardFocusManagerPeer.getInstance().setCurrentFocusOwner(null);
/* wrap in Sequenced, then post*/
postEvent(wrapInSequenced((AWTEvent) we));
}
public void handleWindowFocusOutSync(Window oppositeWindow, long serial) {
WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_LOST_FOCUS, oppositeWindow);
XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow(null);
XKeyboardFocusManagerPeer.getInstance().setCurrentFocusOwner(null);
sendEvent(we);
}
/* --- DisplayChangedListener Stuff --- */
/* Xinerama
* called to check if we've been moved onto a different screen
* Based on checkNewXineramaScreen() in awt_GraphicsEnv.c
*/
public void checkIfOnNewScreen(Rectangle newBounds) {
if (!XToolkit.localEnv.runningXinerama()) {
return;
}
if (log.isLoggable(PlatformLogger.Level.FINEST)) {
log.finest("XWindowPeer: Check if we've been moved to a new screen since we're running in Xinerama mode");
}
int area = newBounds.width * newBounds.height;
int intAmt, vertAmt, horizAmt;
int largestAmt = 0;
int curScreenNum = ((X11GraphicsDevice)getGraphicsConfiguration().getDevice()).getScreen();
int newScreenNum = 0;
GraphicsDevice gds[] = XToolkit.localEnv.getScreenDevices();
GraphicsConfiguration newGC = null;
Rectangle screenBounds;
for (int i = 0; i < gds.length; i++) {
screenBounds = gds[i].getDefaultConfiguration().getBounds();
if (newBounds.intersects(screenBounds)) {
horizAmt = Math.min(newBounds.x + newBounds.width,
screenBounds.x + screenBounds.width) -
Math.max(newBounds.x, screenBounds.x);
vertAmt = Math.min(newBounds.y + newBounds.height,
screenBounds.y + screenBounds.height)-
Math.max(newBounds.y, screenBounds.y);
intAmt = horizAmt * vertAmt;
if (intAmt == area) {
// Completely on this screen - done!
newScreenNum = i;
newGC = gds[i].getDefaultConfiguration();
break;
}
if (intAmt > largestAmt) {
largestAmt = intAmt;
newScreenNum = i;
newGC = gds[i].getDefaultConfiguration();
}
}
}
if (newScreenNum != curScreenNum) {
if (log.isLoggable(PlatformLogger.Level.FINEST)) {
log.finest("XWindowPeer: Moved to a new screen");
}
executeDisplayChangedOnEDT(newGC);
}
}
/**
* Helper method that executes the displayChanged(screen) method on
* the event dispatch thread. This method is used in the Xinerama case
* and after display mode change events.
*/
private void executeDisplayChangedOnEDT(final GraphicsConfiguration gc) {
Runnable dc = new Runnable() {
public void run() {
AWTAccessor.getComponentAccessor().
setGraphicsConfiguration((Component)target, gc);
}
};
SunToolkit.executeOnEventHandlerThread((Component)target, dc);
}
/**
* From the DisplayChangedListener interface; called from
* X11GraphicsDevice when the display mode has been changed.
*/
public void displayChanged() {
executeDisplayChangedOnEDT(getGraphicsConfiguration());
}
/**
* From the DisplayChangedListener interface; top-levels do not need
* to react to this event.
*/
public void paletteChanged() {
}
private Point queryXLocation()
{
return XlibUtil.translateCoordinates(
getContentWindow(),
XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber()),
new Point(0, 0));
}
protected Point getNewLocation(XConfigureEvent xe, int leftInset, int topInset) {
// Bounds of the window
Rectangle targetBounds = AWTAccessor.getComponentAccessor().getBounds((Component)target);
int runningWM = XWM.getWMID();
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() - leftInset, xe.get_y() - topInset);
} else {
// ICCCM 4.1.5 states that a real ConfigureNotify will be sent when
// a window is resized but the client can not tell if the window was
// moved or not. The client should consider the position as unkown
// and use TranslateCoordinates to find the actual position.
//
// TODO this should be the default for every case.
switch (runningWM) {
case XWM.CDE_WM:
case XWM.MOTIF_WM:
case XWM.METACITY_WM:
case XWM.MUTTER_WM:
case XWM.SAWFISH_WM:
{
Point xlocation = queryXLocation();
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("New X location: {0}", xlocation);
}
if (xlocation != null) {
newLocation = xlocation;
}
break;
}
default:
break;
}
}
return newLocation;
}
/*
* Overridden to check if we need to update our GraphicsDevice/Config
* Added for 4934052.
*/
@Override
public void handleConfigureNotifyEvent(XEvent xev) {
XConfigureEvent xe = xev.get_xconfigure();
/*
* Correct window location which could be wrong in some cases.
* See getNewLocation() for the details.
*/
Point newLocation = getNewLocation(xe, 0, 0);
xe.set_x(newLocation.x);
xe.set_y(newLocation.y);
checkIfOnNewScreen(new Rectangle(xe.get_x(),
xe.get_y(),
xe.get_width(),
xe.get_height()));
// Don't call super until we've handled a screen change. Otherwise
// there could be a race condition in which a ComponentListener could
// see the old screen.
super.handleConfigureNotifyEvent(xev);
repositionSecurityWarning();
}
final void requestXFocus(long time) {
requestXFocus(time, true);
}
final void requestXFocus() {
requestXFocus(0, false);
}
/**
* Requests focus to this top-level. Descendants should override to provide
* implementations based on a class of top-level.
*/
protected void requestXFocus(long time, boolean timeProvided) {
// Since in XAWT focus is synthetic and all basic Windows are
// override_redirect all we can do is check whether our parent
// is active. If it is - we can freely synthesize focus transfer.
// Luckily, this logic is already implemented in requestWindowFocus.
if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
focusLog.fine("Requesting window focus");
}
requestWindowFocus(time, timeProvided);
}
public final boolean focusAllowedFor() {
if (isNativelyNonFocusableWindow()) {
return false;
}
/*
Window target = (Window)this.target;
if (!target.isVisible() ||
!target.isEnabled() ||
!target.isFocusable())
{
return false;
}
*/
if (isModalBlocked()) {
return false;
}
return true;
}
public void handleFocusEvent(XEvent xev) {
XFocusChangeEvent xfe = xev.get_xfocus();
FocusEvent fe;
if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
focusLog.fine("{0}", xfe);
}
if (isEventDisabled(xev)) {
return;
}
if (xev.get_type() == XConstants.FocusIn)
{
// If this window is non-focusable don't post any java focus event
if (focusAllowedFor()) {
if (xfe.get_mode() == XConstants.NotifyNormal // Normal notify
|| xfe.get_mode() == XConstants.NotifyWhileGrabbed) // Alt-Tab notify
{
handleWindowFocusIn(xfe.get_serial());
}
}
}
else
{
if (xfe.get_mode() == XConstants.NotifyNormal // Normal notify
|| xfe.get_mode() == XConstants.NotifyWhileGrabbed) // Alt-Tab notify
{
// If this window is non-focusable don't post any java focus event
if (!isNativelyNonFocusableWindow()) {
XWindowPeer oppositeXWindow = getNativeFocusedWindowPeer();
Object oppositeTarget = (oppositeXWindow!=null)? oppositeXWindow.getTarget() : null;
Window oppositeWindow = null;
if (oppositeTarget instanceof Window) {
oppositeWindow = (Window) oppositeTarget;
}
// Check if opposite window is non-focusable. In that case we don't want to
// post any event.
if (oppositeXWindow != null && oppositeXWindow.isNativelyNonFocusableWindow()) {
return;
}
if (this == oppositeXWindow) {
oppositeWindow = null;
} else if (oppositeXWindow instanceof XDecoratedPeer) {
if (((XDecoratedPeer) oppositeXWindow).actualFocusedWindow != null) {
oppositeXWindow = ((XDecoratedPeer) oppositeXWindow).actualFocusedWindow;
oppositeTarget = oppositeXWindow.getTarget();
if (oppositeTarget instanceof Window
&& oppositeXWindow.isVisible()
&& oppositeXWindow.isNativelyNonFocusableWindow())
{
oppositeWindow = ((Window) oppositeTarget);
}
}
}
handleWindowFocusOut(oppositeWindow, xfe.get_serial());
}
}
}
}
void setSaveUnder(boolean state) {}
public void toFront() {
if (isOverrideRedirect() && mustControlStackPosition) {
mustControlStackPosition = false;
removeRootPropertyEventDispatcher();
}
if (isVisible()) {
super.toFront();
if (isFocusableWindow() && isAutoRequestFocus() &&
!isModalBlocked() && !isWithdrawn())
{
requestInitialFocus();
}
} else {
setVisible(true);
}
}
public void toBack() {
XToolkit.awtLock();
try {
if(!isOverrideRedirect()) {
XlibWrapper.XLowerWindow(XToolkit.getDisplay(), getWindow());
}else{
lowerOverrideRedirect();
}
}
finally {
XToolkit.awtUnlock();
}
}
private void lowerOverrideRedirect() {
//
// make new hash of toplevels of all windows from 'windows' hash.
// FIXME: do not call them "toplevel" as it is misleading.
//
HashSet toplevels = new HashSet();
long topl = 0, mytopl = 0;
for (XWindowPeer xp : windows) {
topl = getToplevelWindow( xp.getWindow() );
if( xp.equals( this ) ) {
mytopl = topl;
}
if( topl > 0 )
toplevels.add( Long.valueOf( topl ) );
}
//
// find in the root's tree:
// (1) my toplevel, (2) lowest java toplevel, (3) desktop
// We must enforce (3), (1), (2) order, upward;
// note that nautilus on the next restacking will do (1),(3),(2).
//
long laux, wDesktop = -1, wBottom = -1;
int iMy = -1, iDesktop = -1, iBottom = -1;
int i = 0;
XQueryTree xqt = new XQueryTree(XToolkit.getDefaultRootWindow());
try {
if( xqt.execute() > 0 ) {
int nchildren = xqt.get_nchildren();
long children = xqt.get_children();
for(i = 0; i < nchildren; i++) {
laux = Native.getWindow(children, i);
if( laux == mytopl ) {
iMy = i;
}else if( isDesktopWindow( laux ) ) {
// we need topmost desktop of them all.
iDesktop = i;
wDesktop = laux;
}else if(iBottom < 0 &&
toplevels.contains( Long.valueOf(laux) ) &&
laux != mytopl) {
iBottom = i;
wBottom = laux;
}
}
}
if( (iMy < iBottom || iBottom < 0 )&& iDesktop < iMy)
return; // no action necessary
long to_restack = Native.allocateLongArray(2);
Native.putLong(to_restack, 0, wBottom);
Native.putLong(to_restack, 1, mytopl);
XlibWrapper.XRestackWindows(XToolkit.getDisplay(), to_restack, 2);
XlibWrapper.unsafe.freeMemory(to_restack);
if( !mustControlStackPosition ) {
mustControlStackPosition = true;
// add root window property listener:
// somebody (eg nautilus desktop) may obscure us
addRootPropertyEventDispatcher();
}
} finally {
xqt.dispose();
}
}
/**
Get XID of closest to root window in a given window hierarchy.
FIXME: do not call it "toplevel" as it is misleading.
On error return 0.
*/
private long getToplevelWindow( long w ) {
long wi = w, ret, root;
do {
ret = wi;
XQueryTree qt = new XQueryTree(wi);
try {
if (qt.execute() == 0) {
return 0;
}
root = qt.get_root();
wi = qt.get_parent();
} finally {
qt.dispose();
}
} while (wi != root);
return ret;
}
private static boolean isDesktopWindow( long wi ) {
return XWM.getWM().isDesktopWindow( wi );
}
private void updateAlwaysOnTop() {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("Promoting always-on-top state {0}", Boolean.valueOf(alwaysOnTop));
}
XWM.getWM().setLayer(this,
alwaysOnTop ?
XLayerProtocol.LAYER_ALWAYS_ON_TOP :
XLayerProtocol.LAYER_NORMAL);
}
public void updateAlwaysOnTopState() {
this.alwaysOnTop = ((Window) this.target).isAlwaysOnTop();
updateAlwaysOnTop();
}
boolean isLocationByPlatform() {
return locationByPlatform;
}
private void promoteDefaultPosition() {
this.locationByPlatform = ((Window)target).isLocationByPlatform();
if (locationByPlatform) {
XToolkit.awtLock();
try {
Rectangle bounds = getBounds();
XSizeHints hints = getHints();
setSizeHints(hints.get_flags() & ~(XUtilConstants.USPosition | XUtilConstants.PPosition),
bounds.x, bounds.y, bounds.width, bounds.height);
} finally {
XToolkit.awtUnlock();
}
}
}
public void setVisible(boolean vis) {
if (!isVisible() && vis) {
isBeforeFirstMapNotify = true;
winAttr.initialFocus = isAutoRequestFocus();
if (!winAttr.initialFocus) {
/*
* It's easier and safer to temporary suppress WM_TAKE_FOCUS
* protocol itself than to ignore WM_TAKE_FOCUS client message.
* Because we will have to make the difference between
* the message come after showing and the message come after
* activation. Also, on Metacity, for some reason, we have _two_
* WM_TAKE_FOCUS client messages when showing a frame/dialog.
*/
suppressWmTakeFocus(true);
}
}
updateFocusability();
promoteDefaultPosition();
if (!vis && warningWindow != null) {
warningWindow.setSecurityWarningVisible(false, false);
}
super.setVisible(vis);
if (!vis && !isWithdrawn()) {
// ICCCM, 4.1.4. Changing Window State:
// "Iconic -> Withdrawn - The client should unmap the window and follow it
// with a synthetic UnmapNotify event as described later in this section."
// The same is true for Normal -> Withdrawn
XToolkit.awtLock();
try {
XUnmapEvent unmap = new XUnmapEvent();
unmap.set_window(window);
unmap.set_event(XToolkit.getDefaultRootWindow());
unmap.set_type((int)XConstants.UnmapNotify);
unmap.set_from_configure(false);
XlibWrapper.XSendEvent(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(),
false, XConstants.SubstructureNotifyMask | XConstants.SubstructureRedirectMask,
unmap.pData);
unmap.dispose();
}
finally {
XToolkit.awtUnlock();
}
}
// method called somewhere in parent does not generate configure-notify
// event for override-redirect.
// Ergo, no reshape and bugs like 5085647 in case setBounds was
// called before setVisible.
if (isOverrideRedirect() && vis) {
updateChildrenSizes();
}
repositionSecurityWarning();
}
protected void suppressWmTakeFocus(boolean doSuppress) {
}
final boolean isSimpleWindow() {
return !(target instanceof Frame || target instanceof Dialog);
}
boolean hasWarningWindow() {
return ((Window)target).getWarningString() != null;
}
// The height of menu bar window
int getMenuBarHeight() {
return 0;
}
// Called when shell changes its size and requires children windows
// to update their sizes appropriately
void updateChildrenSizes() {
}
public void repositionSecurityWarning() {
// NOTE: On KWin if the window/border snapping option is enabled,
// the Java window may be swinging while it's being moved.
// This doesn't make the application unusable though looks quite ugly.
// Probobly we need to find some hint to assign to our Security
// Warning window in order to exclude it from the snapping option.
// We are not currently aware of existance of such a property.
if (warningWindow != null) {
// We can't use the coordinates stored in the XBaseWindow since
// they are zeros for decorated frames.
AWTAccessor.ComponentAccessor compAccessor = AWTAccessor.getComponentAccessor();
int x = compAccessor.getX(target);
int y = compAccessor.getY(target);
int width = compAccessor.getWidth(target);
int height = compAccessor.getHeight(target);
warningWindow.reposition(x, y, width, height);
}
}
@Override
protected void setMouseAbove(boolean above) {
super.setMouseAbove(above);
updateSecurityWarningVisibility();
}
@Override
public void setFullScreenExclusiveModeState(boolean state) {
super.setFullScreenExclusiveModeState(state);
updateSecurityWarningVisibility();
}
public void updateSecurityWarningVisibility() {
if (warningWindow == null) {
return;
}
if (!isVisible()) {
return; // The warning window should already be hidden.
}
boolean show = false;
if (!isFullScreenExclusiveMode()) {
int state = getWMState();
// getWMState() always returns 0 (Withdrawn) for simple windows. Hence
// we ignore the state for such windows.
if (isVisible() && (state == XUtilConstants.NormalState || isSimpleWindow())) {
if (XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow() ==
getTarget())
{
show = true;
}
if (isMouseAbove() || warningWindow.isMouseAbove())
{
show = true;
}
}
}
warningWindow.setSecurityWarningVisible(show, true);
}
boolean isOverrideRedirect() {
return XWM.getWMID() == XWM.OPENLOOK_WM ||
Window.Type.POPUP.equals(getWindowType());
}
final boolean isOLWMDecorBug() {
return XWM.getWMID() == XWM.OPENLOOK_WM &&
winAttr.nativeDecor == false;
}
public void dispose() {
if (isGrabbed()) {
if (grabLog.isLoggable(PlatformLogger.Level.FINE)) {
grabLog.fine("Generating UngrabEvent on {0} because of the window disposal", this);
}
postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource()));
}
SunToolkit.awtLock();
try {
windows.remove(this);
} finally {
SunToolkit.awtUnlock();
}
if (warningWindow != null) {
warningWindow.destroy();
}
removeRootPropertyEventDispatcher();
mustControlStackPosition = false;
super.dispose();
/*
* Fix for 6457980.
* When disposing an owned Window we should implicitly
* return focus to its decorated owner because it won't
* receive WM_TAKE_FOCUS.
*/
if (isSimpleWindow()) {
if (target == XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow()) {
Window owner = getDecoratedOwner((Window)target);
((XWindowPeer)AWTAccessor.getComponentAccessor().getPeer(owner)).requestWindowFocus();
}
}
}
boolean isResizable() {
return winAttr.isResizable;
}
public void handleVisibilityEvent(XEvent xev) {
super.handleVisibilityEvent(xev);
XVisibilityEvent ve = xev.get_xvisibility();
winAttr.visibilityState = ve.get_state();
// if (ve.get_state() == XlibWrapper.VisibilityUnobscured) {
// // raiseInputMethodWindow
// }
repositionSecurityWarning();
}
void handleRootPropertyNotify(XEvent xev) {
XPropertyEvent ev = xev.get_xproperty();
if( mustControlStackPosition &&
ev.get_atom() == XAtom.get("_NET_CLIENT_LIST_STACKING").getAtom()){
// Restore stack order unhadled/spoiled by WM or some app (nautilus).
// As of now, don't use any generic machinery: just
// do toBack() again.
if(isOverrideRedirect()) {
toBack();
}
}
}
private void removeStartupNotification() {
if (isStartupNotificationRemoved.getAndSet(true)) {
return;
}
final String desktopStartupId = AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return XToolkit.getEnv("DESKTOP_STARTUP_ID");
}
});
if (desktopStartupId == null) {
return;
}
final StringBuilder messageBuilder = new StringBuilder("remove: ID=");
messageBuilder.append('"');
for (int i = 0; i < desktopStartupId.length(); i++) {
if (desktopStartupId.charAt(i) == '"' || desktopStartupId.charAt(i) == '\\') {
messageBuilder.append('\\');
}
messageBuilder.append(desktopStartupId.charAt(i));
}
messageBuilder.append('"');
messageBuilder.append('\0');
final byte[] message;
try {
message = messageBuilder.toString().getBytes("UTF-8");
} catch (UnsupportedEncodingException cannotHappen) {
return;
}
XClientMessageEvent req = null;
XToolkit.awtLock();
try {
final XAtom netStartupInfoBeginAtom = XAtom.get("_NET_STARTUP_INFO_BEGIN");
final XAtom netStartupInfoAtom = XAtom.get("_NET_STARTUP_INFO");
req = new XClientMessageEvent();
req.set_type(XConstants.ClientMessage);
req.set_window(getWindow());
req.set_message_type(netStartupInfoBeginAtom.getAtom());
req.set_format(8);
for (int pos = 0; pos < message.length; pos += 20) {
final int msglen = Math.min(message.length - pos, 20);
int i = 0;
for (; i < msglen; i++) {
XlibWrapper.unsafe.putByte(req.get_data() + i, message[pos + i]);
}
for (; i < 20; i++) {
XlibWrapper.unsafe.putByte(req.get_data() + i, (byte)0);
}
XlibWrapper.XSendEvent(XToolkit.getDisplay(),
XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber()),
false,
XConstants.PropertyChangeMask,
req.pData);
req.set_message_type(netStartupInfoAtom.getAtom());
}
} finally {
XToolkit.awtUnlock();
if (req != null) {
req.dispose();
}
}
}
public void handleMapNotifyEvent(XEvent xev) {
removeStartupNotification();
// See 6480534.
isUnhiding |= isWMStateNetHidden();
super.handleMapNotifyEvent(xev);
if (!winAttr.initialFocus) {
suppressWmTakeFocus(false); // restore the protocol.
/*
* For some reason, on Metacity, a frame/dialog being shown
* without WM_TAKE_FOCUS protocol doesn't get moved to the front.
* So, we do it evidently.
*/
XToolkit.awtLock();
try {
XlibWrapper.XRaiseWindow(XToolkit.getDisplay(), getWindow());
} finally {
XToolkit.awtUnlock();
}
}
if (shouldFocusOnMapNotify()) {
focusLog.fine("Automatically request focus on window");
requestInitialFocus();
}
isUnhiding = false;
isBeforeFirstMapNotify = false;
updateAlwaysOnTop();
synchronized (getStateLock()) {
if (!isMapped) {
isMapped = true;
}
}
}
public void handleUnmapNotifyEvent(XEvent xev) {
super.handleUnmapNotifyEvent(xev);
// On Metacity UnmapNotify comes before PropertyNotify (for _NET_WM_STATE_HIDDEN).
// So we also check for the property later in MapNotify. See 6480534.
isUnhiding |= isWMStateNetHidden();
synchronized (getStateLock()) {
if (isMapped) {
isMapped = false;
}
}
}
private boolean shouldFocusOnMapNotify() {
boolean res = false;
if (isBeforeFirstMapNotify) {
res = (winAttr.initialFocus || // Window.autoRequestFocus
isFocusedWindowModalBlocker());
} else {
res = isUnhiding; // Unhiding
}
res = res &&
isFocusableWindow() && // General focusability
!isModalBlocked(); // Modality
return res;
}
protected boolean isWMStateNetHidden() {
XNETProtocol protocol = XWM.getWM().getNETProtocol();
return (protocol != null && protocol.isWMStateNetHidden(this));
}
protected void requestInitialFocus() {
requestXFocus();
}
public void addToplevelStateListener(ToplevelStateListener l){
toplevelStateListeners.add(l);
}
public void removeToplevelStateListener(ToplevelStateListener l){
toplevelStateListeners.remove(l);
}
/**
* Override this methods to get notifications when top-level window state changes. The state is
* meant in terms of ICCCM: WithdrawnState, IconicState, NormalState
*/
@Override
protected void stateChanged(long time, int oldState, int newState) {
// Fix for 6401700, 6412803
// If this window is modal blocked, it is put into the transient_for
// chain using prevTransientFor and nextTransientFor hints. However,
// the real WM_TRANSIENT_FOR hint shouldn't be set for windows in
// different WM states (except for owner-window relationship), so
// if the window changes its state, its real WM_TRANSIENT_FOR hint
// should be updated accordingly.
updateTransientFor();
for (ToplevelStateListener topLevelListenerTmp : toplevelStateListeners) {
topLevelListenerTmp.stateChangedICCCM(oldState, newState);
}
updateSecurityWarningVisibility();
}
boolean isWithdrawn() {
return getWMState() == XUtilConstants.WithdrawnState;
}
boolean hasDecorations(int decor) {
if (!winAttr.nativeDecor) {
return false;
}
else {
int myDecor = winAttr.decorations;
boolean hasBits = ((myDecor & decor) == decor);
if ((myDecor & XWindowAttributesData.AWT_DECOR_ALL) != 0)
return !hasBits;
else
return hasBits;
}
}
void setReparented(boolean newValue) {
super.setReparented(newValue);
XToolkit.awtLock();
try {
if (isReparented() && delayedModalBlocking) {
addToTransientFors((XDialogPeer) AWTAccessor.getComponentAccessor().getPeer(modalBlocker));
delayedModalBlocking = false;
}
} finally {
XToolkit.awtUnlock();
}
}
/*
* Returns a Vector of all Java top-level windows,
* sorted by their current Z-order
*/
static Vector<XWindowPeer> collectJavaToplevels() {
Vector<XWindowPeer> javaToplevels = new Vector();
Vector<Long> v = new Vector();
X11GraphicsEnvironment ge =
(X11GraphicsEnvironment)GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gds = ge.getScreenDevices();
if (!ge.runningXinerama() && (gds.length > 1)) {
for (GraphicsDevice gd : gds) {
int screen = ((X11GraphicsDevice)gd).getScreen();
long rootWindow = XlibWrapper.RootWindow(XToolkit.getDisplay(), screen);
v.add(rootWindow);
}
} else {
v.add(XToolkit.getDefaultRootWindow());
}
final int windowsCount = windows.size();
while ((v.size() > 0) && (javaToplevels.size() < windowsCount)) {
long win = v.remove(0);
XQueryTree qt = new XQueryTree(win);
try {
if (qt.execute() != 0) {
int nchildren = qt.get_nchildren();
long children = qt.get_children();
// XQueryTree returns window children ordered by z-order
for (int i = 0; i < nchildren; i++) {
long child = Native.getWindow(children, i);
XBaseWindow childWindow = XToolkit.windowToXWindow(child);
// filter out Java non-toplevels
if ((childWindow != null) && !(childWindow instanceof XWindowPeer)) {
continue;
} else {
v.add(child);
}
if (childWindow instanceof XWindowPeer) {
XWindowPeer np = (XWindowPeer)childWindow;
javaToplevels.add(np);
// XQueryTree returns windows sorted by their z-order. However,
// if WM has not handled transient for hint for a child window,
// it may appear in javaToplevels before its owner. Move such
// children after their owners.
int k = 0;
XWindowPeer toCheck = javaToplevels.get(k);
while (toCheck != np) {
XWindowPeer toCheckOwnerPeer = toCheck.getOwnerPeer();
if (toCheckOwnerPeer == np) {
javaToplevels.remove(k);
javaToplevels.add(toCheck);
} else {
k++;
}
toCheck = javaToplevels.get(k);
}
}
}
}
} finally {
qt.dispose();
}
}
return javaToplevels;
}
public void setModalBlocked(Dialog d, boolean blocked) {
setModalBlocked(d, blocked, null);
}
public void setModalBlocked(Dialog d, boolean blocked,
Vector<XWindowPeer> javaToplevels)
{
XToolkit.awtLock();
try {
// State lock should always be after awtLock
synchronized(getStateLock()) {
XDialogPeer blockerPeer = (XDialogPeer) AWTAccessor.getComponentAccessor().getPeer(d);
if (blocked) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("{0} is blocked by {1}", this, blockerPeer);
}
modalBlocker = d;
if (isReparented() || XWM.isNonReparentingWM()) {
addToTransientFors(blockerPeer, javaToplevels);
} else {
delayedModalBlocking = true;
}
} else {
if (d != modalBlocker) {
throw new IllegalStateException("Trying to unblock window blocked by another dialog");
}
modalBlocker = null;
if (isReparented() || XWM.isNonReparentingWM()) {
removeFromTransientFors();
} else {
delayedModalBlocking = false;
}
}
updateTransientFor();
}
} finally {
XToolkit.awtUnlock();
}
}
/*
* Sets the TRANSIENT_FOR hint to the given top-level window. This
* method is used when a window is modal blocked/unblocked or
* changed its state from/to NormalState to/from other states.
* If window or transientForWindow are embedded frames, the containing
* top-level windows are used.
*
* @param window specifies the top-level window that the hint
* is to be set to
* @param transientForWindow the top-level window
* @param updateChain specifies if next/prevTransientFor fields are
* to be updated
* @param allStates if set to <code>true then TRANSIENT_FOR hint
* is set regardless of the state of window and transientForWindow,
* otherwise it is set only if both are in the same state
*/
static void setToplevelTransientFor(XWindowPeer window, XWindowPeer transientForWindow,
boolean updateChain, boolean allStates)
{
if ((window == null) || (transientForWindow == null)) {
return;
}
if (updateChain) {
window.prevTransientFor = transientForWindow;
transientForWindow.nextTransientFor = window;
}
if (window.curRealTransientFor == transientForWindow) {
return;
}
if (!allStates && (window.getWMState() != transientForWindow.getWMState())) {
return;
}
if (window.getScreenNumber() != transientForWindow.getScreenNumber()) {
return;
}
long bpw = window.getWindow();
while (!XlibUtil.isToplevelWindow(bpw) && !XlibUtil.isXAWTToplevelWindow(bpw)) {
bpw = XlibUtil.getParentWindow(bpw);
}
long tpw = transientForWindow.getWindow();
while (!XlibUtil.isToplevelWindow(tpw) && !XlibUtil.isXAWTToplevelWindow(tpw)) {
tpw = XlibUtil.getParentWindow(tpw);
}
XlibWrapper.XSetTransientFor(XToolkit.getDisplay(), bpw, tpw);
window.curRealTransientFor = transientForWindow;
}
/*
* This method does nothing if this window is not blocked by any modal dialog.
* For modal blocked windows this method looks up for the nearest
* prevTransiendFor window that is in the same state (Normal/Iconified/Withdrawn)
* as this one and makes this window transient for it. The same operation is
* performed for nextTransientFor window.
* Values of prevTransientFor and nextTransientFor fields are not changed.
*/
void updateTransientFor() {
int state = getWMState();
XWindowPeer p = prevTransientFor;
while ((p != null) && ((p.getWMState() != state) || (p.getScreenNumber() != getScreenNumber()))) {
p = p.prevTransientFor;
}
if (p != null) {
setToplevelTransientFor(this, p, false, false);
} else {
restoreTransientFor(this);
}
XWindowPeer n = nextTransientFor;
while ((n != null) && ((n.getWMState() != state) || (n.getScreenNumber() != getScreenNumber()))) {
n = n.nextTransientFor;
}
if (n != null) {
setToplevelTransientFor(n, this, false, false);
}
}
/*
* Removes the TRANSIENT_FOR hint from the given top-level window.
* If window or transientForWindow are embedded frames, the containing
* top-level windows are used.
*
* @param window specifies the top-level window that the hint
* is to be removed from
*/
private static void removeTransientForHint(XWindowPeer window) {
XAtom XA_WM_TRANSIENT_FOR = XAtom.get(XAtom.XA_WM_TRANSIENT_FOR);
long bpw = window.getWindow();
while (!XlibUtil.isToplevelWindow(bpw) && !XlibUtil.isXAWTToplevelWindow(bpw)) {
bpw = XlibUtil.getParentWindow(bpw);
}
XlibWrapper.XDeleteProperty(XToolkit.getDisplay(), bpw, XA_WM_TRANSIENT_FOR.getAtom());
window.curRealTransientFor = null;
}
/*
* When a modal dialog is shown, all its blocked windows are lined up into
* a chain in such a way that each window is a transient_for window for
* the next one. That allows us to keep the modal dialog above all its
* blocked windows (even if there are some another modal dialogs between
* them).
* This method adds this top-level window to the chain of the given modal
* dialog. To keep the current relative z-order, we should use the
* XQueryTree to find the place to insert this window to. As each window
* can be blocked by only one modal dialog (such checks are performed in
* shared code), both this and blockerPeer are on the top of their chains
* (chains may be empty).
* If this window is a modal dialog and has its own chain, these chains are
* merged according to the current z-order (XQueryTree is used again).
* Below are some simple examples (z-order is from left to right, -- is
* modal blocking).
*
* Example 0:
* T (current chain of this, no windows are blocked by this)
* W1---B (current chain of blockerPeer, W2 is blocked by blockerPeer)
* Result is:
* W1-T-B (merged chain, all the windows are blocked by blockerPeer)
*
* Example 1:
* W1-T (current chain of this, W1 is blocked by this)
* W2-B (current chain of blockerPeer, W2 is blocked by blockerPeer)
* Result is:
* W1-T-W2-B (merged chain, all the windows are blocked by blockerPeer)
*
* Example 2:
* W1----T (current chain of this, W1 is blocked by this)
* W2---B (current chain of blockerPeer, W2 is blocked by blockerPeer)
* Result is:
* W1-W2-T-B (merged chain, all the windows are blocked by blockerPeer)
*
* This method should be called under the AWT lock.
*
* @see #removeFromTransientFors
* @see #setModalBlocked
*/
private void addToTransientFors(XDialogPeer blockerPeer) {
addToTransientFors(blockerPeer, null);
}
private void addToTransientFors(XDialogPeer blockerPeer, Vector<XWindowPeer> javaToplevels)
{
// blockerPeer chain iterator
XWindowPeer blockerChain = blockerPeer;
while (blockerChain.prevTransientFor != null) {
blockerChain = blockerChain.prevTransientFor;
}
// this window chain iterator
// each window can be blocked no more than once, so this window
// is on top of its chain
XWindowPeer thisChain = this;
while (thisChain.prevTransientFor != null) {
thisChain = thisChain.prevTransientFor;
}
// if there are no windows blocked by modalBlocker, simply add this window
// and its chain to blocker's chain
if (blockerChain == blockerPeer) {
setToplevelTransientFor(blockerPeer, this, true, false);
} else {
// Collect all the Java top-levels, if required
if (javaToplevels == null) {
javaToplevels = collectJavaToplevels();
}
// merged chain tail
XWindowPeer mergedChain = null;
for (XWindowPeer w : javaToplevels) {
XWindowPeer prevMergedChain = mergedChain;
if (w == thisChain) {
if (thisChain == this) {
if (prevMergedChain != null) {
setToplevelTransientFor(this, prevMergedChain, true, false);
}
setToplevelTransientFor(blockerChain, this, true, false);
break;
} else {
mergedChain = thisChain;
thisChain = thisChain.nextTransientFor;
}
} else if (w == blockerChain) {
mergedChain = blockerChain;
blockerChain = blockerChain.nextTransientFor;
} else {
continue;
}
if (prevMergedChain == null) {
mergedChain.prevTransientFor = null;
} else {
setToplevelTransientFor(mergedChain, prevMergedChain, true, false);
mergedChain.updateTransientFor();
}
if (blockerChain == blockerPeer) {
setToplevelTransientFor(thisChain, mergedChain, true, false);
setToplevelTransientFor(blockerChain, this, true, false);
break;
}
}
}
XToolkit.XSync();
}
static void restoreTransientFor(XWindowPeer window) {
XWindowPeer ownerPeer = window.getOwnerPeer();
if (ownerPeer != null) {
setToplevelTransientFor(window, ownerPeer, false, true);
} else {
removeTransientForHint(window);
}
}
/*
* When a window is modally unblocked, it should be removed from its blocker
* chain, see {@link #addToTransientFor addToTransientFors} method for the
* chain definition.
* The problem is that we cannot simply restore window's original
* TRANSIENT_FOR hint (if any) and link prevTransientFor and
* nextTransientFor together as the whole chain could be created as a merge
* of two other chains in addToTransientFors. In that case, if this window is
* a modal dialog, it would lost all its own chain, if we simply exclude it
* from the chain.
* The correct behaviour of this method should be to split the chain, this
* window is currently in, into two chains. First chain is this window own
* chain (i. e. all the windows blocked by this one, directly or indirectly),
* if any, and the rest windows from the current chain.
*
* Example:
* Original state:
* W1-B1 (window W1 is blocked by B1)
* W2-B2 (window W2 is blocked by B2)
* B3 is shown and blocks B1 and B2:
* W1-W2-B1-B2-B3 (a single chain after B1.addToTransientFors() and B2.addToTransientFors())
* If we then unblock B1, the state should be:
* W1-B1 (window W1 is blocked by B1)
* W2-B2-B3 (window W2 is blocked by B2 and B2 is blocked by B3)
*
* This method should be called under the AWT lock.
*
* @see #addToTransientFors
* @see #setModalBlocked
*/
private void removeFromTransientFors() {
// the head of the chain of this window
XWindowPeer thisChain = this;
// the head of the current chain
// nextTransientFor is always not null as this window is in the chain
XWindowPeer otherChain = nextTransientFor;
// the set of blockers in this chain: if this dialog blocks some other
// modal dialogs, their blocked windows should stay in this dialog's chain
Set<XWindowPeer> thisChainBlockers = new HashSet();
thisChainBlockers.add(this);
// current chain iterator in the order from next to prev
XWindowPeer chainToSplit = prevTransientFor;
while (chainToSplit != null) {
XWindowPeer blocker = (XWindowPeer) AWTAccessor.getComponentAccessor().getPeer(chainToSplit.modalBlocker);
if (thisChainBlockers.contains(blocker)) {
// add to this dialog's chain
setToplevelTransientFor(thisChain, chainToSplit, true, false);
thisChain = chainToSplit;
thisChainBlockers.add(chainToSplit);
} else {
// leave in the current chain
setToplevelTransientFor(otherChain, chainToSplit, true, false);
otherChain = chainToSplit;
}
chainToSplit = chainToSplit.prevTransientFor;
}
restoreTransientFor(thisChain);
thisChain.prevTransientFor = null;
restoreTransientFor(otherChain);
otherChain.prevTransientFor = null;
nextTransientFor = null;
XToolkit.XSync();
}
boolean isModalBlocked() {
return modalBlocker != null;
}
static Window getDecoratedOwner(Window window) {
while ((null != window) && !(window instanceof Frame || window instanceof Dialog)) {
window = (Window) AWTAccessor.getComponentAccessor().getParent(window);
}
return window;
}
public boolean requestWindowFocus(XWindowPeer actualFocusedWindow) {
setActualFocusedWindow(actualFocusedWindow);
return requestWindowFocus();
}
public boolean requestWindowFocus() {
return requestWindowFocus(0, false);
}
public boolean requestWindowFocus(long time, boolean timeProvided) {
focusLog.fine("Request for window focus");
// If this is Frame or Dialog we can't assure focus request success - but we still can try
// If this is Window and its owner Frame is active we can be sure request succedded.
Window ownerWindow = XWindowPeer.getDecoratedOwner((Window)target);
Window focusedWindow = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow();
Window activeWindow = XWindowPeer.getDecoratedOwner(focusedWindow);
if (isWMStateNetHidden()) {
focusLog.fine("The window is unmapped, so rejecting the request");
return false;
}
if (activeWindow == ownerWindow) {
focusLog.fine("Parent window is active - generating focus for this window");
handleWindowFocusInSync(-1);
return true;
}
focusLog.fine("Parent window is not active");
XDecoratedPeer wpeer = (XDecoratedPeer)AWTAccessor.getComponentAccessor().getPeer(ownerWindow);
if (wpeer != null && wpeer.requestWindowFocus(this, time, timeProvided)) {
focusLog.fine("Parent window accepted focus request - generating focus for this window");
return true;
}
focusLog.fine("Denied - parent window is not active and didn't accept focus request");
return false;
}
// This method is to be overriden in XDecoratedPeer.
void setActualFocusedWindow(XWindowPeer actualFocusedWindow) {
}
/**
* Applies the current window type.
*/
private void applyWindowType() {
XNETProtocol protocol = XWM.getWM().getNETProtocol();
if (protocol == null) {
return;
}
XAtom typeAtom = null;
switch (getWindowType())
{
case NORMAL:
typeAtom = (ownerPeer == null) ?
protocol.XA_NET_WM_WINDOW_TYPE_NORMAL :
protocol.XA_NET_WM_WINDOW_TYPE_DIALOG;
break;
case UTILITY:
typeAtom = protocol.XA_NET_WM_WINDOW_TYPE_UTILITY;
break;
case POPUP:
typeAtom = protocol.XA_NET_WM_WINDOW_TYPE_POPUP_MENU;
break;
}
if (typeAtom != null) {
XAtomList wtype = new XAtomList();
wtype.add(typeAtom);
protocol.XA_NET_WM_WINDOW_TYPE.
setAtomListProperty(getWindow(), wtype);
} else {
protocol.XA_NET_WM_WINDOW_TYPE.
DeleteProperty(getWindow());
}
}
@Override
public void xSetVisible(boolean visible) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("Setting visible on " + this + " to " + visible);
}
XToolkit.awtLock();
try {
this.visible = visible;
if (visible) {
applyWindowType();
XlibWrapper.XMapRaised(XToolkit.getDisplay(), getWindow());
} else {
XlibWrapper.XUnmapWindow(XToolkit.getDisplay(), getWindow());
}
XlibWrapper.XFlush(XToolkit.getDisplay());
}
finally {
XToolkit.awtUnlock();
}
}
// should be synchronized on awtLock
private int dropTargetCount = 0;
public void addDropTarget() {
XToolkit.awtLock();
try {
if (dropTargetCount == 0) {
long window = getWindow();
if (window != 0) {
XDropTargetRegistry.getRegistry().registerDropSite(window);
}
}
dropTargetCount++;
} finally {
XToolkit.awtUnlock();
}
}
public void removeDropTarget() {
XToolkit.awtLock();
try {
dropTargetCount--;
if (dropTargetCount == 0) {
long window = getWindow();
if (window != 0) {
XDropTargetRegistry.getRegistry().unregisterDropSite(window);
}
}
} finally {
XToolkit.awtUnlock();
}
}
void addRootPropertyEventDispatcher() {
if( rootPropertyEventDispatcher == null ) {
rootPropertyEventDispatcher = new XEventDispatcher() {
public void dispatchEvent(XEvent ev) {
if( ev.get_type() == XConstants.PropertyNotify ) {
handleRootPropertyNotify( ev );
}
}
};
XlibWrapper.XSelectInput( XToolkit.getDisplay(),
XToolkit.getDefaultRootWindow(),
XConstants.PropertyChangeMask);
XToolkit.addEventDispatcher(XToolkit.getDefaultRootWindow(),
rootPropertyEventDispatcher);
}
}
void removeRootPropertyEventDispatcher() {
if( rootPropertyEventDispatcher != null ) {
XToolkit.removeEventDispatcher(XToolkit.getDefaultRootWindow(),
rootPropertyEventDispatcher);
rootPropertyEventDispatcher = null;
}
}
public void updateFocusableWindowState() {
cachedFocusableWindow = isFocusableWindow();
}
XAtom XA_NET_WM_STATE;
XAtomList net_wm_state;
public XAtomList getNETWMState() {
if (net_wm_state == null) {
net_wm_state = XA_NET_WM_STATE.getAtomListPropertyList(this);
}
return net_wm_state;
}
public void setNETWMState(XAtomList state) {
net_wm_state = state;
if (state != null) {
XA_NET_WM_STATE.setAtomListProperty(this, state);
}
}
public PropMwmHints getMWMHints() {
if (mwm_hints == null) {
mwm_hints = new PropMwmHints();
if (!XWM.XA_MWM_HINTS.getAtomData(getWindow(), mwm_hints.pData, MWMConstants.PROP_MWM_HINTS_ELEMENTS)) {
mwm_hints.zero();
}
}
return mwm_hints;
}
public void setMWMHints(PropMwmHints hints) {
mwm_hints = hints;
if (hints != null) {
XWM.XA_MWM_HINTS.setAtomData(getWindow(), mwm_hints.pData, MWMConstants.PROP_MWM_HINTS_ELEMENTS);
}
}
protected void updateDropTarget() {
XToolkit.awtLock();
try {
if (dropTargetCount > 0) {
long window = getWindow();
if (window != 0) {
XDropTargetRegistry.getRegistry().unregisterDropSite(window);
XDropTargetRegistry.getRegistry().registerDropSite(window);
}
}
} finally {
XToolkit.awtUnlock();
}
}
public void setGrab(boolean grab) {
this.grab = grab;
if (grab) {
pressTarget = this;
grabInput();
} else {
ungrabInput();
}
}
public boolean isGrabbed() {
return grab && XAwtState.getGrabWindow() == this;
}
public void handleXCrossingEvent(XEvent xev) {
XCrossingEvent xce = xev.get_xcrossing();
if (grabLog.isLoggable(PlatformLogger.Level.FINE)) {
grabLog.fine("{0}, when grabbed {1}, contains {2}",
xce, isGrabbed(), containsGlobal(xce.get_x_root(), xce.get_y_root()));
}
if (isGrabbed()) {
// When window is grabbed, all events are dispatched to
// it. Retarget them to the corresponding windows (notice
// that XBaseWindow.dispatchEvent does the opposite
// translation)
// Note that we need to retarget XCrossingEvents to content window
// since it generates MOUSE_ENTERED/MOUSE_EXITED for frame and dialog.
// (fix for 6390326)
XBaseWindow target = XToolkit.windowToXWindow(xce.get_window());
if (grabLog.isLoggable(PlatformLogger.Level.FINER)) {
grabLog.finer(" - Grab event target {0}", target);
}
if (target != null && target != this) {
target.dispatchEvent(xev);
return;
}
}
super.handleXCrossingEvent(xev);
}
public void handleMotionNotify(XEvent xev) {
XMotionEvent xme = xev.get_xmotion();
if (grabLog.isLoggable(PlatformLogger.Level.FINER)) {
grabLog.finer("{0}, when grabbed {1}, contains {2}",
xme, isGrabbed(), containsGlobal(xme.get_x_root(), xme.get_y_root()));
}
if (isGrabbed()) {
boolean dragging = false;
final int buttonsNumber = XToolkit.getNumberOfButtonsForMask();
for (int i = 0; i < buttonsNumber; i++){
// here is the bug in WM: extra buttons doesn't have state!=0 as they should.
if ((i != 4) && (i != 5)){
dragging = dragging || ((xme.get_state() & XlibUtil.getButtonMask(i + 1)) != 0);
}
}
// When window is grabbed, all events are dispatched to
// it. Retarget them to the corresponding windows (notice
// that XBaseWindow.dispatchEvent does the opposite
// translation)
XBaseWindow target = XToolkit.windowToXWindow(xme.get_window());
if (dragging && pressTarget != target) {
// for some reasons if we grab input MotionNotify for drag is reported with target
// to underlying window, not to window on which we have initiated drag
// so we need to retarget them. Here I use simplified logic which retarget all
// such events to source of mouse press (or the grabber). It helps with fix for 6390326.
// So, I do not want to implement complicated logic for better retargeting.
target = pressTarget.isVisible() ? pressTarget : this;
xme.set_window(target.getWindow());
Point localCoord = target.toLocal(xme.get_x_root(), xme.get_y_root());
xme.set_x(localCoord.x);
xme.set_y(localCoord.y);
}
if (grabLog.isLoggable(PlatformLogger.Level.FINER)) {
grabLog.finer(" - Grab event target {0}", target);
}
if (target != null) {
if (target != getContentXWindow() && target != this) {
target.dispatchEvent(xev);
return;
}
}
// note that we need to pass dragging events to the grabber (6390326)
// see comment above for more inforamtion.
if (!containsGlobal(xme.get_x_root(), xme.get_y_root()) && !dragging) {
// Outside of Java
return;
}
}
super.handleMotionNotify(xev);
}
// we use it to retarget mouse drag and mouse release during grab.
private XBaseWindow pressTarget = this;
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;
}
if (grabLog.isLoggable(PlatformLogger.Level.FINE)) {
grabLog.fine("{0}, when grabbed {1}, contains {2} ({3}, {4}, {5}x{6})",
xbe, isGrabbed(), containsGlobal(xbe.get_x_root(), xbe.get_y_root()), getAbsoluteX(), getAbsoluteY(), getWidth(), getHeight());
}
if (isGrabbed()) {
// When window is grabbed, all events are dispatched to
// it. Retarget them to the corresponding windows (notice
// that XBaseWindow.dispatchEvent does the opposite
// translation)
XBaseWindow target = XToolkit.windowToXWindow(xbe.get_window());
try {
if (grabLog.isLoggable(PlatformLogger.Level.FINER)) {
grabLog.finer(" - Grab event target {0} (press target {1})", target, pressTarget);
}
if (xbe.get_type() == XConstants.ButtonPress
&& xbe.get_button() == XConstants.buttons[0])
{
// need to keep it to retarget mouse release
pressTarget = target;
} else if (xbe.get_type() == XConstants.ButtonRelease
&& xbe.get_button() == XConstants.buttons[0]
&& pressTarget != target)
{
// during grab we do receive mouse release on different component (not on the source
// of mouse press). So we need to retarget it.
// see 6390326 for more information.
target = pressTarget.isVisible() ? pressTarget : this;
xbe.set_window(target.getWindow());
Point localCoord = target.toLocal(xbe.get_x_root(), xbe.get_y_root());
xbe.set_x(localCoord.x);
xbe.set_y(localCoord.y);
pressTarget = this;
}
if (target != null && target != getContentXWindow() && target != this) {
target.dispatchEvent(xev);
return;
}
} finally {
if (target != null) {
// Target is either us or our content window -
// check that event is inside. 'Us' in case of
// shell will mean that this will also filter out press on title
if ((target == this || target == getContentXWindow()) && !containsGlobal(xbe.get_x_root(), xbe.get_y_root())) {
// Outside this toplevel hierarchy
// According to the specification of UngrabEvent, post it
// when press occurs outside of the window and not on its owned windows
if (xbe.get_type() == XConstants.ButtonPress) {
if (grabLog.isLoggable(PlatformLogger.Level.FINE)) {
grabLog.fine("Generating UngrabEvent on {0} because not inside of shell", this);
}
postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource()));
return;
}
}
// First, get the toplevel
XWindowPeer toplevel = target.getToplevelXWindow();
if (toplevel != null) {
Window w = (Window)toplevel.target;
while (w != null && toplevel != this && !(toplevel instanceof XDialogPeer)) {
w = (Window) AWTAccessor.getComponentAccessor().getParent(w);
if (w != null) {
toplevel = (XWindowPeer) AWTAccessor.getComponentAccessor().getPeer(w);
}
}
if (w == null || (w != this.target && w instanceof Dialog)) {
// toplevel == null - outside of
// hierarchy, toplevel is Dialog - should
// send ungrab (but shouldn't for Window)
if (grabLog.isLoggable(PlatformLogger.Level.FINE)) {
grabLog.fine("Generating UngrabEvent on {0} because hierarchy ended", this);
}
postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource()));
}
} else {
// toplevel is null - outside of hierarchy
if (grabLog.isLoggable(PlatformLogger.Level.FINE)) {
grabLog.fine("Generating UngrabEvent on {0} because toplevel is null", this);
}
postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource()));
return;
}
} else {
// target doesn't map to XAWT window - outside of hierarchy
if (grabLog.isLoggable(PlatformLogger.Level.FINE)) {
grabLog.fine("Generating UngrabEvent on because target is null {0}", this);
}
postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource()));
return;
}
}
}
super.handleButtonPressRelease(xev);
}
public void print(Graphics g) {
// We assume we print the whole frame,
// so we expect no clip was set previously
Shape shape = AWTAccessor.getWindowAccessor().getShape((Window)target);
if (shape != null) {
g.setClip(shape);
}
super.print(g);
}
@Override
public void setOpacity(float opacity) {
final long maxOpacity = 0xffffffffl;
long iOpacity = (long)(opacity * maxOpacity);
if (iOpacity < 0) {
iOpacity = 0;
}
if (iOpacity > maxOpacity) {
iOpacity = maxOpacity;
}
XAtom netWmWindowOpacityAtom = XAtom.get("_NET_WM_WINDOW_OPACITY");
if (iOpacity == maxOpacity) {
netWmWindowOpacityAtom.DeleteProperty(getWindow());
} else {
netWmWindowOpacityAtom.setCard32Property(getWindow(), iOpacity);
}
}
@Override
public void setOpaque(boolean isOpaque) {
// no-op
}
@Override
public void updateWindow() {
// no-op
}
}
Other Java examples (source code examples)
Here is a short list of links related to this Java XWindowPeer.java source code file:
|