2021-07-16 17:12:20 -05:00

432 lines
13 KiB
Java

/*
* This file is modified by Ivan Maidanski <ivmai@ivmaisoft.com>
* Project name: JCGO-SUNAWT (http://www.ivmaisoft.com/jcgo/)
*/
/*
* @(#)MWindowPeer.java 1.49 03/01/23
*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package sun.awt.motif;
import java.util.Vector;
import java.awt.*;
import java.awt.peer.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.ImageObserver;
import sun.awt.image.ImageRepresentation;
import sun.awt.motif.X11InputMethod;
import sun.awt.motif.MInputMethodControl;
import sun.awt.im.*;
import sun.awt.DisplayChangedListener;
import sun.awt.SunToolkit;
class MWindowPeer extends MPanelPeer implements WindowPeer,
DisplayChangedListener {
Insets insets = new Insets( 0, 0, 0, 0 );
MWindowAttributes winAttr;
static Vector allWindows = new Vector();
int iconWidth = -1;
int iconHeight = -1;
native void pCreate(MComponentPeer parent, String targetClassName);
native void pShow();
native void pShowModal(boolean isModal);
native void pHide();
native void pReshape(int x, int y, int width, int height);
native void pDispose();
native void pSetTitle(String title);
public native void setState(int state);
public native int getState();
public native void setResizable(boolean resizable);
native void addTextComponentNative(MComponentPeer tc);
native void removeTextComponentNative();
native void pSetIMMOption(String option);
native void pSetMenuBar(MMenuBarPeer mbpeer);
native void setSaveUnder(boolean state);
private static native void initIDs();
static {
initIDs();
}
// this function is privileged! do not change it to public!
private static int getInset(final String name, final int def) {
Integer tmp = (Integer) java.security.AccessController.doPrivileged(
new sun.security.action.GetIntegerAction(name, def));
return tmp.intValue();
}
MWindowPeer() {
insets = new Insets(0,0,0,0);
winAttr = new MWindowAttributes();
}
MWindowPeer(Window target) {
this();
init(target);
allWindows.addElement(this);
}
void create(MComponentPeer parent) {
pCreate(parent, target.getClass().getName());
}
void init( Window target ) {
if ( winAttr.nativeDecor == true ) {
insets.top = getInset("awt.frame.topInset", -1);
insets.left = getInset("awt.frame.leftInset", -1);
insets.bottom = getInset("awt.frame.bottomInset", -1);
insets.right = getInset("awt.frame.rightInset", -1);
}
Rectangle rectangle = target.getBounds();
sysX = rectangle.x;
sysY = rectangle.y;
sysW = rectangle.width;
sysH = rectangle.height;
super.init(target);
InputMethodManager imm = InputMethodManager.getInstance();
String menuString = imm.getTriggerMenuString();
if (menuString != null)
{
pSetIMMOption(menuString);
}
pSetTitle(winAttr.title);
/*
* For Windows and undecorated Frames and Dialogs this just
* disables/enables resizing functions in the system menu.
*/
setResizable(winAttr.isResizable);
setSaveUnder(true);
Font f = target.getFont();
if (f == null) {
f = defaultFont;
target.setFont(f);
setFont(f);
}
Color c = target.getBackground();
if (c == null) {
target.setBackground(SystemColor.window);
setBackground(SystemColor.window);
}
c = target.getForeground();
if (c == null) {
target.setForeground(SystemColor.windowText);
setForeground(SystemColor.windowText);
}
}
protected void disposeImpl() {
allWindows.removeElement(this);
super.disposeImpl();
}
public native void toBack();
public void toFront() {
if (target.isVisible()) {
pShow();
}
}
public Insets getInsets() {
return insets;
}
public void handleQuit() {
postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_CLOSING));
}
// XXX: nasty WM, foul play. spank WM author.
public void handleDestroy() {
final Window target = (Window)this.target;
SunToolkit.executeOnEventHandlerThread(target,
new Runnable() {
public void run() {
// This seems like the only reasonable thing we
// could do in this situation as the native window
// is already dead.
target.dispose();
}
});
}
// 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));
}
/**
* Called to inform the Window that its size has changed and it
* should layout its children.
*/
// NOTE: This method may be called by privileged threads.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
public void handleResize(int width, int height) {
sysW = width;
sysH = height;
// REMIND: Is this secure? Can client code subclass input method?
if (!tcList.isEmpty() &&
!imList.isEmpty()){
int i;
for (i = 0; i < imList.size(); i++){
((X11InputMethod)imList.elementAt(i)).configureStatus();
}
}
postEvent(new ComponentEvent(target, ComponentEvent.COMPONENT_RESIZED));
}
/**
* DEPRECATED: Replaced by getInsets().
*/
public Insets insets() {
return getInsets();
}
public void handleMoved(int x, int y) {
sysX = x;
sysY = y;
postEvent(new ComponentEvent(target, ComponentEvent.COMPONENT_MOVED));
}
private native AWTEvent wrapInSequenced(AWTEvent event);
// NOTE: This method may be called by privileged threads.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
public void handleWindowFocusIn() {
WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS);
/* wrap in Sequenced, then post*/
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) {
WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_LOST_FOCUS,
oppositeWindow);
/* wrap in Sequenced, then post*/
postEvent(wrapInSequenced((AWTEvent) we));
}
// relocation of Imm stuff
private Vector imList = new Vector();
private Vector tcList = new Vector();
// NOTE: This method is called by privileged threads.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
void notifyIMMOptionChange(){
// REMIND: IS THIS SECURE? CAN USER CODE SUBCLASS INPUTMETHODMGR?
InputMethodManager.getInstance().notifyChangeRequest(target);
}
public void addInputMethod(X11InputMethod im) {
if (!imList.contains(im))
imList.addElement(im);
}
public void removeInputMethod(X11InputMethod im) {
if (imList.contains(im))
imList.removeElement(im);
}
public void addTextComponent(MComponentPeer tc) {
if (tcList.contains(tc))
return;
if (tcList.isEmpty()){
addTextComponentNative(tc);
if (!imList.isEmpty()) {
for (int i = 0; i < imList.size(); i++) {
((X11InputMethod)imList.elementAt(i)).reconfigureXIC((MInputMethodControl)this);
}
}
MToolkit.executeOnEventHandlerThread(target, new Runnable() {
public void run() {
synchronized(target.getTreeLock()) {
target.doLayout();
}
}
});
}
tcList.addElement(tc);
}
public void removeTextComponent(MComponentPeer tc) {
if (!tcList.contains(tc))
return;
tcList.removeElement(tc);
if (tcList.isEmpty()){
removeTextComponentNative();
if (!imList.isEmpty()) {
for (int i = 0; i < imList.size(); i++) {
((X11InputMethod)imList.elementAt(i)).reconfigureXIC((MInputMethodControl)this);
}
}
target.doLayout();
}
}
public MComponentPeer getTextComponent() {
if (!tcList.isEmpty()) {
return (MComponentPeer)tcList.firstElement();
} else {
return null;
}
}
boolean hasDecorations(int decor) {
if (!winAttr.nativeDecor) {
return false;
}
else {
int myDecor = winAttr.decorations;
boolean hasBits = ((myDecor & decor) == decor);
if ((myDecor & MWindowAttributes.AWT_DECOR_ALL) != 0)
return !hasBits;
else
return hasBits;
}
}
/* Returns the native paint should be posted after setting new size
*/
public boolean checkNativePaintOnSetBounds(int width, int height) {
// Fix for 4418155. Window does not repaint
// automticaly if shrinking. Should not wait for Expose
return (width > oldWidth) || (height > oldHeight);
}
/* --- DisplayChangedListener Stuff --- */
native void resetTargetGC(Component target);
/* Xinerama
* called to update our GC when dragged onto another screen
*/
public void draggedToNewScreen(int screenNum) {
final int finalScreenNum = screenNum;
SunToolkit.executeOnEventHandlerThread((Component)target, new Runnable()
{
public void run() {
displayChanged(finalScreenNum);
}
});
}
/* Xinerama
* called to update our GC when dragged onto another screen
*/
public void displayChanged(int screenNum) {
// update our GC
resetLocalGC(screenNum); /* upcall to MCanvasPeer */
resetTargetGC(target); /* call Window.resetGC() via native */
//propagate to children
super.displayChanged(screenNum); /* upcall to MPanelPeer */
}
private volatile int sysX;
private volatile int sysY;
private volatile int sysW;
private volatile int sysH;
private final boolean hasWarningWindow() {
return ((Window)target).getWarningString() != null;
}
boolean isTargetUndecorated() {
return true;
}
public void setBounds(int x, int y, int width, int height) {
Rectangle rectangle = constrainBounds(x, y, width, height);
super.setBounds(rectangle.x, rectangle.y, rectangle.width,
rectangle.height);
}
Rectangle constrainBounds(int i, int j, int k, int l) {
if (!hasWarningWindow())
return new Rectangle(i, j, k, l);
int i1 = i;
int j1 = j;
int k1 = k;
int l1 = l;
GraphicsConfiguration graphicsconfiguration =
((Window)target).getGraphicsConfiguration();
Rectangle rectangle = graphicsconfiguration.getBounds();
Insets insets1 =
((Window)target).getToolkit().getScreenInsets(graphicsconfiguration);
int i2 = rectangle.width - insets1.left - insets1.right;
int j2 = rectangle.height - insets1.top - insets1.bottom;
if (!target.isVisible() || isTargetUndecorated()) {
int k2 = rectangle.x + insets1.left;
int i3 = rectangle.y + insets1.top;
if (k1 > i2)
k1 = i2;
if (l1 > j2)
l1 = j2;
if (i1 < k2) {
i1 = k2;
} else if (i1 + k1 > k2 + i2) {
i1 = (k2 + i2) - k1;
}
if (j1 < i3) {
j1 = i3;
} else if (j1 + l1 > i3 + j2) {
j1 = (i3 + j2) - l1;
}
} else {
int l2 = Math.max(i2, sysW);
int j3 = Math.max(j2, sysH);
if (k1 > l2)
k1 = l2;
if (l1 > j3)
l1 = j3;
}
return new Rectangle(i1, j1, k1, l1);
}
}