package sun.awt.windows;
import java.awt.AWTEvent;
import java.awt.AWTEventMulticaster;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.SystemColor;
import java.awt.Window;
import java.awt.event.FocusEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.geom.AffineTransform;
import java.awt.image.DataBufferInt;
import java.awt.peer.WindowPeer;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.LinkedList;
import java.util.List;
import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.DisplayChangedListener;
import sun.awt.SunToolkit;
import sun.awt.Win32GraphicsConfig;
import sun.awt.Win32GraphicsDevice;
import sun.awt.Win32GraphicsEnvironment;
import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.pipe.Region;
import sun.util.logging.PlatformLogger;
public class WWindowPeer extends WPanelPeer implements WindowPeer,
DisplayChangedListener
{
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.windows.WWindowPeer");
private static final PlatformLogger screenLog = PlatformLogger.getLogger("sun.awt.windows.screen.WWindowPeer");
private WWindowPeer modalBlocker = null;
private boolean isOpaque;
private TranslucentWindowPainter painter;
private static final StringBuffer ACTIVE_WINDOWS_KEY =
new StringBuffer("active_windows_list");
private static PropertyChangeListener activeWindowListener =
new ActiveWindowListener();
private static final PropertyChangeListener guiDisposedListener =
new GuiDisposedListener();
private WindowListener windowListener;
private float scaleX;
private float scaleY;
private static native void initIDs();
static {
initIDs();
}
@Override
@SuppressWarnings("unchecked")
protected void disposeImpl() {
AppContext appContext = SunToolkit.targetToAppContext(target);
synchronized (appContext) {
List<WWindowPeer> l = (List<WWindowPeer>)appContext.get(ACTIVE_WINDOWS_KEY);
if (l != null) {
l.remove(this);
}
}
GraphicsConfiguration gc = getGraphicsConfiguration();
((Win32GraphicsDevice)gc.getDevice()).removeDisplayChangedListener(this);
synchronized (getStateLock()) {
TranslucentWindowPainter currentPainter = painter;
if (currentPainter != null) {
currentPainter.flush();
}
}
super.disposeImpl();
}
@Override
public void toFront() {
updateFocusableWindowState();
_toFront();
}
private native void _toFront();
@Override
public native void toBack();
private native void setAlwaysOnTopNative(boolean value);
public void setAlwaysOnTop(boolean value) {
if ((value && ((Window)target).isVisible()) || !value) {
setAlwaysOnTopNative(value);
}
}
@Override
public void updateAlwaysOnTopState() {
setAlwaysOnTop(((Window)target).isAlwaysOnTop());
}
@Override
public void updateFocusableWindowState() {
setFocusableWindow(((Window)target).isFocusableWindow());
}
native void setFocusableWindow(boolean value);
public void setTitle(String title) {
if (title == null) {
title = "";
}
_setTitle(title);
}
private native void _setTitle(String title);
public void setResizable(boolean resizable) {
_setResizable(resizable);
}
private native void _setResizable(boolean resizable);
WWindowPeer(Window target) {
super(target);
}
@Override
void initialize() {
super.initialize();
updateInsets(insets_);
if (!((Window) target).isFontSet()) {
((Window) target).setFont(defaultFont);
setFont(defaultFont);
}
if (!((Window) target).isForegroundSet()) {
((Window) target).setForeground(SystemColor.windowText);
}
if (!((Window) target).isBackgroundSet()) {
((Window) target).setBackground(SystemColor.window);
}
GraphicsConfiguration gc = getGraphicsConfiguration();
Win32GraphicsDevice gd = (Win32GraphicsDevice) gc.getDevice();
gd.addDisplayChangedListener(this);
scaleX = gd.getDefaultScaleX();
scaleY = gd.getDefaultScaleY();
initActiveWindowsTracking((Window)target);
updateIconImages();
Shape shape = ((Window)target).getShape();
if (shape != null) {
applyShape(Region.getInstance(shape, null));
}
float opacity = ((Window)target).getOpacity();
if (opacity < 1.0f) {
setOpacity(opacity);
}
synchronized (getStateLock()) {
this.isOpaque = true;
setOpaque(((Window)target).isOpaque());
}
}
native void createAwtWindow(WComponentPeer parent);
private volatile Window.Type windowType = Window.Type.NORMAL;
void preCreate(WComponentPeer parent) {
windowType = ((Window)target).getType();
}
@Override
void create(WComponentPeer parent) {
preCreate(parent);
createAwtWindow(parent);
}
@Override
final WComponentPeer getNativeParent() {
final Container owner = ((Window) target).getOwner();
return (WComponentPeer) WToolkit.targetToPeer(owner);
}
protected void realShow() {
super.show();
}
@Override
public void show() {
updateFocusableWindowState();
boolean alwaysOnTop = ((Window)target).isAlwaysOnTop();
updateGC();
realShow();
updateMinimumSize();
if (((Window)target).isAlwaysOnTopSupported() && alwaysOnTop) {
setAlwaysOnTop(alwaysOnTop);
}
synchronized (getStateLock()) {
if (!isOpaque) {
updateWindow(true);
}
}
WComponentPeer owner = getNativeParent();
if (owner != null && owner.isLightweightFramePeer()) {
Rectangle b = getBounds();
handleExpose(0, 0, b.width, b.height);
}
}
native void updateInsets(Insets i);
static native int getSysMinWidth();
static native int getSysMinHeight();
static native int getSysIconWidth();
static native int getSysIconHeight();
static native int getSysSmIconWidth();
static native int getSysSmIconHeight();
native void setIconImagesData(int[] iconRaster, int w, int h,
int[] smallIconRaster, int smw, int smh);
synchronized native void reshapeFrame(int x, int y, int width, int height);
native Dimension getNativeWindowSize();
public Dimension getScaledWindowSize() {
return getNativeWindowSize();
}
public boolean requestWindowFocus(FocusEvent.Cause cause) {
if (!focusAllowedFor()) {
return false;
}
return requestWindowFocus(cause == FocusEvent.Cause.MOUSE_EVENT);
}
private native boolean requestWindowFocus(boolean isMouseEventCause);
public boolean focusAllowedFor() {
Window window = (Window)this.target;
if (!window.isVisible() ||
!window.isEnabled() ||
!window.isFocusableWindow())
{
return false;
}
if (isModalBlocked()) {
return false;
}
return true;
}
@Override
void hide() {
WindowListener listener = windowListener;
if (listener != null) {
listener.windowClosing(new WindowEvent((Window)target, WindowEvent.WINDOW_CLOSING));
}
super.hide();
}
@Override
void preprocessPostEvent(AWTEvent event) {
if (event instanceof WindowEvent) {
WindowListener listener = windowListener;
if (listener != null) {
switch(event.getID()) {
case WindowEvent.WINDOW_CLOSING:
listener.windowClosing((WindowEvent)event);
break;
case WindowEvent.WINDOW_ICONIFIED:
listener.windowIconified((WindowEvent)event);
break;
}
}
}
}
synchronized void addWindowListener(WindowListener l) {
windowListener = AWTEventMulticaster.add(windowListener, l);
}
synchronized void removeWindowListener(WindowListener l) {
windowListener = AWTEventMulticaster.remove(windowListener, l);
}
@Override
public void updateMinimumSize() {
Dimension minimumSize = null;
if (((Component)target).isMinimumSizeSet()) {
minimumSize = ((Component)target).getMinimumSize();
}
if (minimumSize != null) {
int msw = getSysMinWidth();
int msh = getSysMinHeight();
int w = (minimumSize.width >= msw) ? minimumSize.width : msw;
int h = (minimumSize.height >= msh) ? minimumSize.height : msh;
setMinSize(w, h);
} else {
setMinSize(0, 0);
}
}
@Override
public void updateIconImages() {
java.util.List<Image> imageList = ((Window)target).getIconImages();
if (imageList == null || imageList.size() == 0) {
setIconImagesData(null, 0, 0, null, 0, 0);
} else {
int w = getSysIconWidth();
int h = getSysIconHeight();
int smw = getSysSmIconWidth();
int smh = getSysSmIconHeight();
AffineTransform tx = getGraphicsConfiguration().getDefaultTransform();
w = Region.clipScale(w, tx.getScaleX());
h = Region.clipScale(h, tx.getScaleY());
smw = Region.clipScale(smw, tx.getScaleX());
smh = Region.clipScale(smh, tx.getScaleY());
DataBufferInt iconData = SunToolkit.getScaledIconData(imageList,
w, h);
DataBufferInt iconSmData = SunToolkit.getScaledIconData(imageList,
smw, smh);
if (iconData != null && iconSmData != null) {
setIconImagesData(iconData.getData(), w, h,
iconSmData.getData(), smw, smh);
} else {
setIconImagesData(null, 0, 0, null, 0, 0);
}
}
}
native void setMinSize(int width, int height);
public boolean isModalBlocked() {
return modalBlocker != null;
}
@Override
public void setModalBlocked(Dialog dialog, boolean blocked) {
synchronized (((Component)getTarget()).getTreeLock())
{
WWindowPeer blockerPeer = AWTAccessor.getComponentAccessor()
.getPeer(dialog);
if (blocked)
{
modalBlocker = blockerPeer;
if (blockerPeer instanceof WFileDialogPeer) {
((WFileDialogPeer)blockerPeer).blockWindow(this);
} else if (blockerPeer instanceof WPrintDialogPeer) {
((WPrintDialogPeer)blockerPeer).blockWindow(this);
} else {
modalDisable(dialog, blockerPeer.getHWnd());
}
} else {
modalBlocker = null;
if (blockerPeer instanceof WFileDialogPeer) {
((WFileDialogPeer)blockerPeer).unblockWindow(this);
} else if (blockerPeer instanceof WPrintDialogPeer) {
((WPrintDialogPeer)blockerPeer).unblockWindow(this);
} else {
modalEnable(dialog);
}
}
}
}
native void modalDisable(Dialog blocker, long blockerHWnd);
native void modalEnable(Dialog blocker);
@SuppressWarnings("unchecked")
public static long[] getActiveWindowHandles(Component target) {
AppContext appContext = SunToolkit.targetToAppContext(target);
if (appContext == null) return null;
synchronized (appContext) {
List<WWindowPeer> l = (List<WWindowPeer>)appContext.get(ACTIVE_WINDOWS_KEY);
if (l == null) {
return null;
}
long[] result = new long[l.size()];
for (int j = 0; j < l.size(); j++) {
result[j] = l.get(j).getHWnd();
}
return result;
}
}
void draggedToNewScreen() {
displayChanged();
}
public void updateGC() {
int scrn = getScreenImOn();
if (screenLog.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("Screen number: " + scrn);
}
Win32GraphicsDevice oldDev = winGraphicsConfig.getDevice();
Win32GraphicsDevice newDev;
GraphicsDevice[] devs = GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getScreenDevices();
if (scrn >= devs.length) {
newDev = (Win32GraphicsDevice)GraphicsEnvironment
.getLocalGraphicsEnvironment().getDefaultScreenDevice();
} else {
newDev = (Win32GraphicsDevice)devs[scrn];
}
winGraphicsConfig = (Win32GraphicsConfig)newDev
.getDefaultConfiguration();
if (screenLog.isLoggable(PlatformLogger.Level.FINE)) {
if (winGraphicsConfig == null) {
screenLog.fine("Assertion (winGraphicsConfig != null) failed");
}
}
if (oldDev != newDev) {
oldDev.removeDisplayChangedListener(this);
newDev.addDisplayChangedListener(this);
}
AWTAccessor.getComponentAccessor().
setGraphicsConfiguration((Component)target, winGraphicsConfig);
checkDPIChange(oldDev, newDev);
}
private void checkDPIChange(Win32GraphicsDevice oldDev,
Win32GraphicsDevice newDev) {
float newScaleX = newDev.getDefaultScaleX();
float newScaleY = newDev.getDefaultScaleY();
if (scaleX != newScaleX || scaleY != newScaleY) {
windowDPIChange(oldDev.getScreen(), scaleX, scaleY,
newDev.getScreen(), newScaleX, newScaleY);
scaleX = newScaleX;
scaleY = newScaleY;
}
}
@Override
public void displayChanged() {
SunToolkit.executeOnEventHandlerThread(target, this::updateGC);
}
@Override
public void paletteChanged() {
}
private native int getScreenImOn();
public final native void setFullScreenExclusiveModeState(boolean state);
public void grab() {
nativeGrab();
}
public void ungrab() {
nativeUngrab();
}
private native void nativeGrab();
private native void nativeUngrab();
private boolean hasWarningWindow() {
return ((Window)target).getWarningString() != null;
}
boolean isTargetUndecorated() {
return true;
}
private volatile int sysX = 0;
private volatile int sysY = 0;
private volatile int sysW = 0;
private volatile int sysH = 0;
@Override
public native void repositionSecurityWarning();
@Override
public void setBounds(int x, int y, int width, int height, int op) {
sysX = x;
sysY = y;
sysW = width;
sysH = height;
int cx = x + width / 2;
int cy = y + height / 2;
GraphicsConfiguration current = getGraphicsConfiguration();
GraphicsConfiguration other = SunGraphicsEnvironment
.getGraphicsConfigurationAtPoint(current, cx, cy);
if (!current.equals(other)) {
AffineTransform tx = other.getDefaultTransform();
double otherScaleX = tx.getScaleX();
double otherScaleY = tx.getScaleY();
initScales();
if (scaleX != otherScaleX || scaleY != otherScaleY) {
x = (int) Math.floor(x * otherScaleX / scaleX);
y = (int) Math.floor(y * otherScaleY / scaleY);
}
}
super.setBounds(x, y, width, height, op);
}
private void initScales() {
if (scaleX >= 1 && scaleY >= 1) {
return;
}
GraphicsConfiguration gc = getGraphicsConfiguration();
if (gc instanceof Win32GraphicsConfig) {
Win32GraphicsDevice gd = ((Win32GraphicsConfig) gc).getDevice();
scaleX = gd.getDefaultScaleX();
scaleY = gd.getDefaultScaleY();
} else {
AffineTransform tx = gc.getDefaultTransform();
scaleX = (float) tx.getScaleX();
scaleY = (float) tx.getScaleY();
}
}
@Override
public void print(Graphics g) {
Shape shape = ((Window)target).getShape();
if (shape != null) {
g.setClip(shape);
}
super.print(g);
}
private void replaceSurfaceDataRecursively(Component c) {
if (c instanceof Container) {
for (Component child : ((Container)c).getComponents()) {
replaceSurfaceDataRecursively(child);
}
}
final Object cp = AWTAccessor.getComponentAccessor().getPeer(c);
if (cp instanceof WComponentPeer) {
((WComponentPeer)cp).replaceSurfaceDataLater();
}
}
public final Graphics getTranslucentGraphics() {
synchronized (getStateLock()) {
return isOpaque ? null : painter.getGraphics(false);
}
}
@Override
public void setBackground(Color c) {
super.setBackground(c);
synchronized (getStateLock()) {
if (!isOpaque && ((Window)target).isVisible()) {
updateWindow(true);
}
}
}
private native void setOpacity(int iOpacity);
private float opacity = 1.0f;
@Override
public void setOpacity(float opacity) {
if (!((SunToolkit)((Window)target).getToolkit()).
isWindowOpacitySupported())
{
return;
}
if (opacity < 0.0f || opacity > 1.0f) {
throw new IllegalArgumentException(
"The value of opacity should be in the range [0.0f .. 1.0f].");
}
if (((this.opacity == 1.0f && opacity < 1.0f) ||
(this.opacity < 1.0f && opacity == 1.0f)) &&
!Win32GraphicsEnvironment.isVistaOS())
{
replaceSurfaceDataRecursively((Component)getTarget());
}
this.opacity = opacity;
final int maxOpacity = 0xff;
int iOpacity = (int)(opacity * maxOpacity);
if (iOpacity < 0) {
iOpacity = 0;
}
if (iOpacity > maxOpacity) {
iOpacity = maxOpacity;
}
setOpacity(iOpacity);
synchronized (getStateLock()) {
if (!isOpaque && ((Window)target).isVisible()) {
updateWindow(true);
}
}
}
private native void setOpaqueImpl(boolean isOpaque);
@Override
public void setOpaque(boolean isOpaque) {
synchronized (getStateLock()) {
if (this.isOpaque == isOpaque) {
return;
}
}
Window target = (Window)getTarget();
if (!isOpaque) {
SunToolkit sunToolkit = (SunToolkit)target.getToolkit();
if (!sunToolkit.isWindowTranslucencySupported() ||
!sunToolkit.isTranslucencyCapable(target.getGraphicsConfiguration()))
{
return;
}
}
boolean isVistaOS = Win32GraphicsEnvironment.isVistaOS();
if (this.isOpaque != isOpaque && !isVistaOS) {
replaceSurfaceDataRecursively(target);
}
synchronized (getStateLock()) {
this.isOpaque = isOpaque;
setOpaqueImpl(isOpaque);
if (isOpaque) {
TranslucentWindowPainter currentPainter = painter;
if (currentPainter != null) {
currentPainter.flush();
painter = null;
}
} else {
painter = TranslucentWindowPainter.createInstance(this);
}
}
if (isVistaOS) {
Shape shape = target.getShape();
if (shape != null) {
target.setShape(shape);
}
}
if (target.isVisible()) {
updateWindow(true);
}
}
native void updateWindowImpl(int[] data, int width, int height);
@Override
public void updateWindow() {
updateWindow(false);
}
private void updateWindow(boolean repaint) {
Window w = (Window)target;
synchronized (getStateLock()) {
if (isOpaque || !w.isVisible() ||
(w.getWidth() <= 0) || (w.getHeight() <= 0))
{
return;
}
TranslucentWindowPainter currentPainter = painter;
if (currentPainter != null) {
currentPainter.updateWindow(repaint);
} else if (log.isLoggable(PlatformLogger.Level.FINER)) {
log.finer("Translucent window painter is null in updateWindow");
}
}
}
native void windowDPIChange(int prevScreen, float prevScaleX, float prevScaleY,
int newScreen, float newScaleX, float newScaleY);
@SuppressWarnings("unchecked")
private static void initActiveWindowsTracking(Window w) {
AppContext appContext = AppContext.getAppContext();
synchronized (appContext) {
List<WWindowPeer> l = (List<WWindowPeer>)appContext.get(ACTIVE_WINDOWS_KEY);
if (l == null) {
l = new LinkedList<WWindowPeer>();
appContext.put(ACTIVE_WINDOWS_KEY, l);
appContext.addPropertyChangeListener(AppContext.GUI_DISPOSED, guiDisposedListener);
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
kfm.addPropertyChangeListener("activeWindow", activeWindowListener);
}
}
}
private static class GuiDisposedListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent e) {
boolean isDisposed = (Boolean)e.getNewValue();
if (isDisposed != true) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine(" Assertion (newValue != true) failed for AppContext.GUI_DISPOSED ");
}
}
AppContext appContext = AppContext.getAppContext();
synchronized (appContext) {
appContext.remove(ACTIVE_WINDOWS_KEY);
appContext.removePropertyChangeListener(AppContext.GUI_DISPOSED, this);
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
kfm.removePropertyChangeListener("activeWindow", activeWindowListener);
}
}
}
@SuppressWarnings("unchecked")
private static class ActiveWindowListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent e) {
Window w = (Window)e.getNewValue();
if (w == null) {
return;
}
AppContext appContext = SunToolkit.targetToAppContext(w);
synchronized (appContext) {
WWindowPeer wp = AWTAccessor.getComponentAccessor().getPeer(w);
List<WWindowPeer> l = (List<WWindowPeer>)appContext.get(ACTIVE_WINDOWS_KEY);
if (l != null) {
l.remove(wp);
l.add(wp);
}
}
}
}
}