mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-17 03:13:11 +00:00
685 lines
25 KiB
Java
685 lines
25 KiB
Java
/*
|
|
* Copyright (c) 2002, 2015, 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.Color;
|
|
import java.awt.Dimension;
|
|
import java.awt.Font;
|
|
import java.awt.FontMetrics;
|
|
import java.awt.Frame;
|
|
import java.awt.Graphics;
|
|
import java.awt.Insets;
|
|
import java.awt.MenuBar;
|
|
import java.awt.Rectangle;
|
|
import java.awt.peer.FramePeer;
|
|
import sun.util.logging.PlatformLogger;
|
|
import sun.awt.AWTAccessor;
|
|
|
|
class XFramePeer extends XDecoratedPeer implements FramePeer {
|
|
private static PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XFramePeer");
|
|
private static PlatformLogger stateLog = PlatformLogger.getLogger("sun.awt.X11.states");
|
|
private static PlatformLogger insLog = PlatformLogger.getLogger("sun.awt.X11.insets.XFramePeer");
|
|
|
|
XMenuBarPeer menubarPeer;
|
|
MenuBar menubar;
|
|
int state;
|
|
private Boolean undecorated;
|
|
|
|
private static final int MENUBAR_HEIGHT_IF_NO_MENUBAR = 0;
|
|
private int lastAppliedMenubarHeight = MENUBAR_HEIGHT_IF_NO_MENUBAR;
|
|
|
|
XFramePeer(Frame target) {
|
|
super(target);
|
|
}
|
|
|
|
XFramePeer(XCreateWindowParams params) {
|
|
super(params);
|
|
}
|
|
|
|
void preInit(XCreateWindowParams params) {
|
|
super.preInit(params);
|
|
Frame target = (Frame)(this.target);
|
|
// set the window attributes for this Frame
|
|
winAttr.initialState = target.getExtendedState();
|
|
state = 0;
|
|
undecorated = Boolean.valueOf(target.isUndecorated());
|
|
winAttr.nativeDecor = !target.isUndecorated();
|
|
if (winAttr.nativeDecor) {
|
|
winAttr.decorations = XWindowAttributesData.AWT_DECOR_ALL;
|
|
} else {
|
|
winAttr.decorations = XWindowAttributesData.AWT_DECOR_NONE;
|
|
}
|
|
winAttr.functions = MWMConstants.MWM_FUNC_ALL;
|
|
winAttr.isResizable = true; // target.isResizable();
|
|
winAttr.title = target.getTitle();
|
|
winAttr.initialResizability = target.isResizable();
|
|
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
|
log.fine("Frame''s initial attributes: decor {0}, resizable {1}, undecorated {2}, initial state {3}",
|
|
Integer.valueOf(winAttr.decorations), Boolean.valueOf(winAttr.initialResizability),
|
|
Boolean.valueOf(!winAttr.nativeDecor), Integer.valueOf(winAttr.initialState));
|
|
}
|
|
}
|
|
|
|
void postInit(XCreateWindowParams params) {
|
|
super.postInit(params);
|
|
setupState(true);
|
|
}
|
|
|
|
@Override
|
|
boolean isTargetUndecorated() {
|
|
if (undecorated != null) {
|
|
return undecorated.booleanValue();
|
|
} else {
|
|
return ((Frame)target).isUndecorated();
|
|
}
|
|
}
|
|
|
|
void setupState(boolean onInit) {
|
|
if (onInit) {
|
|
state = winAttr.initialState;
|
|
}
|
|
if ((state & Frame.ICONIFIED) != 0) {
|
|
setInitialState(XUtilConstants.IconicState);
|
|
} else {
|
|
setInitialState(XUtilConstants.NormalState);
|
|
}
|
|
setExtendedState(state);
|
|
}
|
|
|
|
@SuppressWarnings("deprecation")
|
|
public void setMenuBar(MenuBar mb) {
|
|
// state_lock should always be the second after awt_lock
|
|
XToolkit.awtLock();
|
|
try {
|
|
synchronized(getStateLock()) {
|
|
if (mb == menubar) return;
|
|
if (mb == null) {
|
|
if (menubar != null) {
|
|
menubarPeer.xSetVisible(false);
|
|
menubar = null;
|
|
menubarPeer.dispose();
|
|
menubarPeer = null;
|
|
}
|
|
} else {
|
|
menubar = mb;
|
|
menubarPeer = AWTAccessor.getMenuComponentAccessor()
|
|
.getPeer(mb);
|
|
if (menubarPeer != null) {
|
|
menubarPeer.init((Frame)target);
|
|
}
|
|
}
|
|
}
|
|
} finally {
|
|
XToolkit.awtUnlock();
|
|
}
|
|
|
|
reshapeMenubarPeer();
|
|
}
|
|
|
|
XMenuBarPeer getMenubarPeer() {
|
|
return menubarPeer;
|
|
}
|
|
|
|
int getMenuBarHeight() {
|
|
if (menubarPeer != null) {
|
|
return menubarPeer.getDesiredHeight();
|
|
} else {
|
|
return MENUBAR_HEIGHT_IF_NO_MENUBAR;
|
|
}
|
|
}
|
|
|
|
void updateChildrenSizes() {
|
|
super.updateChildrenSizes();
|
|
int height = getMenuBarHeight();
|
|
|
|
// XWindow.reshape calls XBaseWindow.xSetBounds, which acquires
|
|
// the AWT lock, so we have to acquire the AWT lock here
|
|
// before getStateLock() to avoid a deadlock with the Toolkit thread
|
|
// when this method is called on the EDT.
|
|
XToolkit.awtLock();
|
|
try {
|
|
synchronized(getStateLock()) {
|
|
int width = dimensions.getClientSize().width;
|
|
if (menubarPeer != null) {
|
|
menubarPeer.reshape(0, 0, width, height);
|
|
}
|
|
}
|
|
} finally {
|
|
XToolkit.awtUnlock();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* In addition to reshaping menubarPeer (by using 'updateChildrenSizes')
|
|
* this method also performs some frame reaction on this (i.e. layouts
|
|
* other frame children, if required)
|
|
*/
|
|
final void reshapeMenubarPeer() {
|
|
XToolkit.executeOnEventHandlerThread(
|
|
target,
|
|
new Runnable() {
|
|
public void run() {
|
|
updateChildrenSizes();
|
|
boolean heightChanged = false;
|
|
|
|
int height = getMenuBarHeight();
|
|
// Neither 'XToolkit.awtLock()' nor 'getStateLock()'
|
|
// is acquired under this call, and it looks to run
|
|
// thread-safely. I currently see no reason to move
|
|
// it under following 'synchronized' clause.
|
|
|
|
synchronized(getStateLock()) {
|
|
if (height != lastAppliedMenubarHeight) {
|
|
lastAppliedMenubarHeight = height;
|
|
heightChanged = true;
|
|
}
|
|
}
|
|
if (heightChanged) {
|
|
// To make frame contents be re-layout (copied from
|
|
// 'XDecoratedPeer.revalidate()'). These are not
|
|
// 'synchronized', because can recursively call client
|
|
// methods, which are not supposed to be called with locks
|
|
// acquired.
|
|
target.invalidate();
|
|
target.validate();
|
|
}
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
public void setMaximizedBounds(Rectangle b) {
|
|
if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
|
|
insLog.fine("Setting maximized bounds to " + b);
|
|
}
|
|
if (b == null) return;
|
|
maxBounds = new Rectangle(b);
|
|
XToolkit.awtLock();
|
|
try {
|
|
XSizeHints hints = getHints();
|
|
hints.set_flags(hints.get_flags() | (int)XUtilConstants.PMaxSize);
|
|
if (b.width != Integer.MAX_VALUE) {
|
|
hints.set_max_width(b.width);
|
|
} else {
|
|
hints.set_max_width((int)XlibWrapper.DisplayWidth(XToolkit.getDisplay(), XlibWrapper.DefaultScreen(XToolkit.getDisplay())));
|
|
}
|
|
if (b.height != Integer.MAX_VALUE) {
|
|
hints.set_max_height(b.height);
|
|
} else {
|
|
hints.set_max_height((int)XlibWrapper.DisplayHeight(XToolkit.getDisplay(), XlibWrapper.DefaultScreen(XToolkit.getDisplay())));
|
|
}
|
|
if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
|
|
insLog.finer("Setting hints, flags " + XlibWrapper.hintsToString(hints.get_flags()));
|
|
}
|
|
XlibWrapper.XSetWMNormalHints(XToolkit.getDisplay(), window, hints.pData);
|
|
} finally {
|
|
XToolkit.awtUnlock();
|
|
}
|
|
}
|
|
|
|
public int getState() {
|
|
synchronized(getStateLock()) {
|
|
return state;
|
|
}
|
|
}
|
|
|
|
public void setState(int newState) {
|
|
synchronized(getStateLock()) {
|
|
if (!isShowing()) {
|
|
stateLog.finer("Frame is not showing");
|
|
state = newState;
|
|
return;
|
|
}
|
|
}
|
|
changeState(newState);
|
|
}
|
|
|
|
void changeState(int newState) {
|
|
int changed = state ^ newState;
|
|
int changeIconic = changed & Frame.ICONIFIED;
|
|
boolean iconic = (newState & Frame.ICONIFIED) != 0;
|
|
if (stateLog.isLoggable(PlatformLogger.Level.FINER)) {
|
|
stateLog.finer("Changing state, old state {0}, new state {1}(iconic {2})",
|
|
Integer.valueOf(state), Integer.valueOf(newState), Boolean.valueOf(iconic));
|
|
}
|
|
if (changeIconic != 0 && iconic) {
|
|
if (stateLog.isLoggable(PlatformLogger.Level.FINER)) {
|
|
stateLog.finer("Iconifying shell " + getShell() + ", this " + this + ", screen " + getScreenNumber());
|
|
}
|
|
XToolkit.awtLock();
|
|
try {
|
|
int res = XlibWrapper.XIconifyWindow(XToolkit.getDisplay(), getShell(), getScreenNumber());
|
|
if (stateLog.isLoggable(PlatformLogger.Level.FINER)) {
|
|
stateLog.finer("XIconifyWindow returned " + res);
|
|
}
|
|
}
|
|
finally {
|
|
XToolkit.awtUnlock();
|
|
}
|
|
}
|
|
if ((changed & ~Frame.ICONIFIED) != 0) {
|
|
setExtendedState(newState);
|
|
}
|
|
if (changeIconic != 0 && !iconic) {
|
|
if (stateLog.isLoggable(PlatformLogger.Level.FINER)) {
|
|
stateLog.finer("DeIconifying " + this);
|
|
}
|
|
|
|
XNETProtocol net_protocol = XWM.getWM().getNETProtocol();
|
|
if (net_protocol != null) {
|
|
net_protocol.setActiveWindow(getWindow());
|
|
}
|
|
xSetVisible(true);
|
|
}
|
|
}
|
|
|
|
void setExtendedState(int newState) {
|
|
XWM.getWM().setExtendedState(this, newState);
|
|
}
|
|
|
|
public void handlePropertyNotify(XEvent xev) {
|
|
super.handlePropertyNotify(xev);
|
|
XPropertyEvent ev = xev.get_xproperty();
|
|
|
|
if (log.isLoggable(PlatformLogger.Level.FINER)) {
|
|
log.finer("Property change {0}", ev);
|
|
}
|
|
/*
|
|
* Let's see if this is a window state protocol message, and
|
|
* if it is - decode a new state in terms of java constants.
|
|
*/
|
|
if (!XWM.getWM().isStateChange(this, ev)) {
|
|
stateLog.finer("either not a state atom or state has not been changed");
|
|
return;
|
|
}
|
|
|
|
final int newState = XWM.getWM().getState(this);
|
|
int changed = state ^ newState;
|
|
if (changed == 0) {
|
|
if (stateLog.isLoggable(PlatformLogger.Level.FINER)) {
|
|
stateLog.finer("State is the same: " + state);
|
|
}
|
|
return;
|
|
}
|
|
|
|
int old_state = state;
|
|
state = newState;
|
|
|
|
// sync target with peer
|
|
AWTAccessor.getFrameAccessor().setExtendedState((Frame)target, state);
|
|
|
|
if ((changed & Frame.ICONIFIED) != 0) {
|
|
if ((state & Frame.ICONIFIED) != 0) {
|
|
stateLog.finer("Iconified");
|
|
handleIconify();
|
|
} else {
|
|
stateLog.finer("DeIconified");
|
|
content.purgeIconifiedExposeEvents();
|
|
handleDeiconify();
|
|
}
|
|
}
|
|
handleStateChange(old_state, state);
|
|
|
|
// RepaintManager does not repaint iconified windows. Window needs to be
|
|
// repainted explicitly, when it is deiconified.
|
|
if (((changed & Frame.ICONIFIED) != 0) &&
|
|
((state & Frame.ICONIFIED) == 0)) {
|
|
repaint();
|
|
}
|
|
}
|
|
|
|
// NOTE: This method may be called by privileged threads.
|
|
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
|
|
public void handleStateChange(int oldState, int newState) {
|
|
super.handleStateChange(oldState, newState);
|
|
for (ToplevelStateListener topLevelListenerTmp : toplevelStateListeners) {
|
|
topLevelListenerTmp.stateChangedJava(oldState, newState);
|
|
}
|
|
}
|
|
|
|
public void setVisible(boolean vis) {
|
|
if (vis) {
|
|
setupState(false);
|
|
} else {
|
|
if ((state & Frame.MAXIMIZED_BOTH) != 0) {
|
|
XWM.getWM().setExtendedState(this, state & ~Frame.MAXIMIZED_BOTH);
|
|
}
|
|
}
|
|
super.setVisible(vis);
|
|
if (vis && maxBounds != null) {
|
|
setMaximizedBounds(maxBounds);
|
|
}
|
|
}
|
|
|
|
void setInitialState(int wm_state) {
|
|
XToolkit.awtLock();
|
|
try {
|
|
XWMHints hints = getWMHints();
|
|
hints.set_flags((int)XUtilConstants.StateHint | hints.get_flags());
|
|
hints.set_initial_state(wm_state);
|
|
if (stateLog.isLoggable(PlatformLogger.Level.FINE)) {
|
|
stateLog.fine("Setting initial WM state on " + this + " to " + wm_state);
|
|
}
|
|
XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData);
|
|
}
|
|
finally {
|
|
XToolkit.awtUnlock();
|
|
}
|
|
}
|
|
|
|
public void dispose() {
|
|
if (menubarPeer != null) {
|
|
menubarPeer.dispose();
|
|
}
|
|
super.dispose();
|
|
}
|
|
|
|
boolean isMaximized() {
|
|
return (state & (Frame.MAXIMIZED_VERT | Frame.MAXIMIZED_HORIZ)) != 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
static final int CROSSHAIR_INSET = 5;
|
|
|
|
static final int BUTTON_Y = CROSSHAIR_INSET + 1;
|
|
static final int BUTTON_W = 17;
|
|
static final int BUTTON_H = 17;
|
|
|
|
static final int SYS_MENU_X = CROSSHAIR_INSET + 1;
|
|
static final int SYS_MENU_CONTAINED_X = SYS_MENU_X + 5;
|
|
static final int SYS_MENU_CONTAINED_Y = BUTTON_Y + 7;
|
|
static final int SYS_MENU_CONTAINED_W = 8;
|
|
static final int SYS_MENU_CONTAINED_H = 3;
|
|
|
|
static final int MAXIMIZE_X_DIFF = CROSSHAIR_INSET + BUTTON_W;
|
|
static final int MAXIMIZE_CONTAINED_X_DIFF = MAXIMIZE_X_DIFF - 5;
|
|
static final int MAXIMIZE_CONTAINED_Y = BUTTON_Y + 5;
|
|
static final int MAXIMIZE_CONTAINED_W = 8;
|
|
static final int MAXIMIZE_CONTAINED_H = 8;
|
|
|
|
static final int MINIMIZE_X_DIFF = MAXIMIZE_X_DIFF + BUTTON_W;
|
|
static final int MINIMIZE_CONTAINED_X_DIFF = MINIMIZE_X_DIFF - 7;
|
|
static final int MINIMIZE_CONTAINED_Y = BUTTON_Y + 7;
|
|
static final int MINIMIZE_CONTAINED_W = 3;
|
|
static final int MINIMIZE_CONTAINED_H = 3;
|
|
|
|
static final int TITLE_X = SYS_MENU_X + BUTTON_W;
|
|
static final int TITLE_W_DIFF = BUTTON_W * 3 + CROSSHAIR_INSET * 2 - 1;
|
|
static final int TITLE_MID_Y = BUTTON_Y + (BUTTON_H / 2);
|
|
|
|
static final int MENUBAR_X = CROSSHAIR_INSET + 1;
|
|
static final int MENUBAR_Y = BUTTON_Y + BUTTON_H;
|
|
|
|
static final int HORIZ_RESIZE_INSET = CROSSHAIR_INSET + BUTTON_H;
|
|
static final int VERT_RESIZE_INSET = CROSSHAIR_INSET + BUTTON_W;
|
|
|
|
|
|
/*
|
|
* Print the native component by rendering the Motif look ourselves.
|
|
* We also explicitly print the MenuBar since a MenuBar isn't a subclass
|
|
* of Component (and thus it has no "print" method which gets called by
|
|
* default).
|
|
*/
|
|
public void print(Graphics g) {
|
|
super.print(g);
|
|
|
|
Frame f = (Frame)target;
|
|
Insets finsets = f.getInsets();
|
|
Dimension fsize = f.getSize();
|
|
|
|
Color bg = f.getBackground();
|
|
Color fg = f.getForeground();
|
|
Color highlight = bg.brighter();
|
|
Color shadow = bg.darker();
|
|
|
|
// Well, we could query for the currently running window manager
|
|
// and base the look on that, or we could just always do dtwm.
|
|
// aim, tball, and levenson all agree we'll just do dtwm.
|
|
|
|
if (hasDecorations(XWindowAttributesData.AWT_DECOR_BORDER)) {
|
|
|
|
// top outer -- because we'll most likely be drawing on white paper,
|
|
// for aesthetic reasons, don't make any part of the outer border
|
|
// pure white
|
|
if (highlight.equals(Color.white)) {
|
|
g.setColor(new Color(230, 230, 230));
|
|
}
|
|
else {
|
|
g.setColor(highlight);
|
|
}
|
|
g.drawLine(0, 0, fsize.width, 0);
|
|
g.drawLine(0, 1, fsize.width - 1, 1);
|
|
|
|
// left outer
|
|
// if (highlight.equals(Color.white)) {
|
|
// g.setColor(new Color(230, 230, 230));
|
|
// }
|
|
// else {
|
|
// g.setColor(highlight);
|
|
// }
|
|
g.drawLine(0, 0, 0, fsize.height);
|
|
g.drawLine(1, 0, 1, fsize.height - 1);
|
|
|
|
// bottom cross-hair
|
|
g.setColor(highlight);
|
|
g.drawLine(CROSSHAIR_INSET + 1, fsize.height - CROSSHAIR_INSET,
|
|
fsize.width - CROSSHAIR_INSET,
|
|
fsize.height - CROSSHAIR_INSET);
|
|
|
|
// right cross-hair
|
|
// g.setColor(highlight);
|
|
g.drawLine(fsize.width - CROSSHAIR_INSET, CROSSHAIR_INSET + 1,
|
|
fsize.width - CROSSHAIR_INSET,
|
|
fsize.height - CROSSHAIR_INSET);
|
|
|
|
// bottom outer
|
|
g.setColor(shadow);
|
|
g.drawLine(1, fsize.height, fsize.width, fsize.height);
|
|
g.drawLine(2, fsize.height - 1, fsize.width, fsize.height - 1);
|
|
|
|
// right outer
|
|
// g.setColor(shadow);
|
|
g.drawLine(fsize.width, 1, fsize.width, fsize.height);
|
|
g.drawLine(fsize.width - 1, 2, fsize.width - 1, fsize.height);
|
|
|
|
// top cross-hair
|
|
// g.setColor(shadow);
|
|
g.drawLine(CROSSHAIR_INSET, CROSSHAIR_INSET,
|
|
fsize.width - CROSSHAIR_INSET, CROSSHAIR_INSET);
|
|
|
|
// left cross-hair
|
|
// g.setColor(shadow);
|
|
g.drawLine(CROSSHAIR_INSET, CROSSHAIR_INSET, CROSSHAIR_INSET,
|
|
fsize.height - CROSSHAIR_INSET);
|
|
}
|
|
|
|
if (hasDecorations(XWindowAttributesData.AWT_DECOR_TITLE)) {
|
|
|
|
if (hasDecorations(XWindowAttributesData.AWT_DECOR_MENU)) {
|
|
|
|
// system menu
|
|
g.setColor(bg);
|
|
g.fill3DRect(SYS_MENU_X, BUTTON_Y, BUTTON_W, BUTTON_H, true);
|
|
g.fill3DRect(SYS_MENU_CONTAINED_X, SYS_MENU_CONTAINED_Y,
|
|
SYS_MENU_CONTAINED_W, SYS_MENU_CONTAINED_H, true);
|
|
}
|
|
|
|
// title bar
|
|
// g.setColor(bg);
|
|
g.fill3DRect(TITLE_X, BUTTON_Y, fsize.width - TITLE_W_DIFF, BUTTON_H,
|
|
true);
|
|
|
|
if (hasDecorations(XWindowAttributesData.AWT_DECOR_MINIMIZE)) {
|
|
|
|
// minimize button
|
|
// g.setColor(bg);
|
|
g.fill3DRect(fsize.width - MINIMIZE_X_DIFF, BUTTON_Y, BUTTON_W,
|
|
BUTTON_H, true);
|
|
g.fill3DRect(fsize.width - MINIMIZE_CONTAINED_X_DIFF,
|
|
MINIMIZE_CONTAINED_Y, MINIMIZE_CONTAINED_W,
|
|
MINIMIZE_CONTAINED_H, true);
|
|
}
|
|
|
|
if (hasDecorations(XWindowAttributesData.AWT_DECOR_MAXIMIZE)) {
|
|
|
|
// maximize button
|
|
// g.setColor(bg);
|
|
g.fill3DRect(fsize.width - MAXIMIZE_X_DIFF, BUTTON_Y, BUTTON_W,
|
|
BUTTON_H, true);
|
|
g.fill3DRect(fsize.width - MAXIMIZE_CONTAINED_X_DIFF,
|
|
MAXIMIZE_CONTAINED_Y, MAXIMIZE_CONTAINED_W,
|
|
MAXIMIZE_CONTAINED_H, true);
|
|
}
|
|
|
|
// title bar text
|
|
g.setColor(fg);
|
|
Font sysfont = new Font(Font.SANS_SERIF, Font.PLAIN, 10);
|
|
g.setFont(sysfont);
|
|
FontMetrics sysfm = g.getFontMetrics();
|
|
String ftitle = f.getTitle();
|
|
g.drawString(ftitle,
|
|
((TITLE_X + TITLE_X + fsize.width - TITLE_W_DIFF) / 2) -
|
|
(sysfm.stringWidth(ftitle) / 2),
|
|
TITLE_MID_Y + sysfm.getMaxDescent());
|
|
}
|
|
|
|
if (f.isResizable() &&
|
|
hasDecorations(XWindowAttributesData.AWT_DECOR_RESIZEH)) {
|
|
|
|
// add resize cross hairs
|
|
|
|
// upper-left horiz (shadow)
|
|
g.setColor(shadow);
|
|
g.drawLine(1, HORIZ_RESIZE_INSET, CROSSHAIR_INSET,
|
|
HORIZ_RESIZE_INSET);
|
|
// upper-left vert (shadow)
|
|
// g.setColor(shadow);
|
|
g.drawLine(VERT_RESIZE_INSET, 1, VERT_RESIZE_INSET, CROSSHAIR_INSET);
|
|
// upper-right horiz (shadow)
|
|
// g.setColor(shadow);
|
|
g.drawLine(fsize.width - CROSSHAIR_INSET + 1, HORIZ_RESIZE_INSET,
|
|
fsize.width, HORIZ_RESIZE_INSET);
|
|
// upper-right vert (shadow)
|
|
// g.setColor(shadow);
|
|
g.drawLine(fsize.width - VERT_RESIZE_INSET - 1, 2,
|
|
fsize.width - VERT_RESIZE_INSET - 1, CROSSHAIR_INSET + 1);
|
|
// lower-left horiz (shadow)
|
|
// g.setColor(shadow);
|
|
g.drawLine(1, fsize.height - HORIZ_RESIZE_INSET - 1,
|
|
CROSSHAIR_INSET, fsize.height - HORIZ_RESIZE_INSET - 1);
|
|
// lower-left vert (shadow)
|
|
// g.setColor(shadow);
|
|
g.drawLine(VERT_RESIZE_INSET, fsize.height - CROSSHAIR_INSET + 1,
|
|
VERT_RESIZE_INSET, fsize.height);
|
|
// lower-right horiz (shadow)
|
|
// g.setColor(shadow);
|
|
g.drawLine(fsize.width - CROSSHAIR_INSET + 1,
|
|
fsize.height - HORIZ_RESIZE_INSET - 1, fsize.width,
|
|
fsize.height - HORIZ_RESIZE_INSET - 1);
|
|
// lower-right vert (shadow)
|
|
// g.setColor(shadow);
|
|
g.drawLine(fsize.width - VERT_RESIZE_INSET - 1,
|
|
fsize.height - CROSSHAIR_INSET + 1,
|
|
fsize.width - VERT_RESIZE_INSET - 1, fsize.height);
|
|
|
|
// upper-left horiz (highlight)
|
|
g.setColor(highlight);
|
|
g.drawLine(2, HORIZ_RESIZE_INSET + 1, CROSSHAIR_INSET,
|
|
HORIZ_RESIZE_INSET + 1);
|
|
// upper-left vert (highlight)
|
|
// g.setColor(highlight);
|
|
g.drawLine(VERT_RESIZE_INSET + 1, 2, VERT_RESIZE_INSET + 1,
|
|
CROSSHAIR_INSET);
|
|
// upper-right horiz (highlight)
|
|
// g.setColor(highlight);
|
|
g.drawLine(fsize.width - CROSSHAIR_INSET + 1,
|
|
HORIZ_RESIZE_INSET + 1, fsize.width - 1,
|
|
HORIZ_RESIZE_INSET + 1);
|
|
// upper-right vert (highlight)
|
|
// g.setColor(highlight);
|
|
g.drawLine(fsize.width - VERT_RESIZE_INSET, 2,
|
|
fsize.width - VERT_RESIZE_INSET, CROSSHAIR_INSET);
|
|
// lower-left horiz (highlight)
|
|
// g.setColor(highlight);
|
|
g.drawLine(2, fsize.height - HORIZ_RESIZE_INSET, CROSSHAIR_INSET,
|
|
fsize.height - HORIZ_RESIZE_INSET);
|
|
// lower-left vert (highlight)
|
|
// g.setColor(highlight);
|
|
g.drawLine(VERT_RESIZE_INSET + 1,
|
|
fsize.height - CROSSHAIR_INSET + 1,
|
|
VERT_RESIZE_INSET + 1, fsize.height - 1);
|
|
// lower-right horiz (highlight)
|
|
// g.setColor(highlight);
|
|
g.drawLine(fsize.width - CROSSHAIR_INSET + 1,
|
|
fsize.height - HORIZ_RESIZE_INSET, fsize.width - 1,
|
|
fsize.height - HORIZ_RESIZE_INSET);
|
|
// lower-right vert (highlight)
|
|
// g.setColor(highlight);
|
|
g.drawLine(fsize.width - VERT_RESIZE_INSET,
|
|
fsize.height - CROSSHAIR_INSET + 1,
|
|
fsize.width - VERT_RESIZE_INSET, fsize.height - 1);
|
|
}
|
|
|
|
XMenuBarPeer peer = menubarPeer;
|
|
if (peer != null) {
|
|
Insets insets = getInsets();
|
|
Graphics ng = g.create();
|
|
int menubarX = 0;
|
|
int menubarY = 0;
|
|
if (hasDecorations(XWindowAttributesData.AWT_DECOR_BORDER)) {
|
|
menubarX += CROSSHAIR_INSET + 1;
|
|
menubarY += CROSSHAIR_INSET + 1;
|
|
}
|
|
if (hasDecorations(XWindowAttributesData.AWT_DECOR_TITLE)) {
|
|
menubarY += BUTTON_H;
|
|
}
|
|
try {
|
|
ng.translate(menubarX, menubarY);
|
|
peer.print(ng);
|
|
} finally {
|
|
ng.dispose();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void setBoundsPrivate(int x, int y, int width, int height) {
|
|
setBounds(x, y, width, height, SET_BOUNDS);
|
|
}
|
|
|
|
public Rectangle getBoundsPrivate() {
|
|
return getBounds();
|
|
}
|
|
|
|
public void emulateActivation(boolean doActivate) {
|
|
if (doActivate) {
|
|
handleWindowFocusIn(0);
|
|
} else {
|
|
handleWindowFocusOut(null, 0);
|
|
}
|
|
}
|
|
}
|