J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. |
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 4 | * |
| 5 | * This code is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License version 2 only, as |
| 7 | * published by the Free Software Foundation. Sun designates this |
| 8 | * particular file as subject to the "Classpath" exception as provided |
| 9 | * by Sun in the LICENSE file that accompanied this code. |
| 10 | * |
| 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 14 | * version 2 for more details (a copy is included in the LICENSE file that |
| 15 | * accompanied this code). |
| 16 | * |
| 17 | * You should have received a copy of the GNU General Public License version |
| 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
| 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| 20 | * |
| 21 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 22 | * CA 95054 USA or visit www.sun.com if you need additional information or |
| 23 | * have any questions. |
| 24 | */ |
| 25 | package sun.awt.X11; |
| 26 | |
| 27 | import java.util.Vector; |
| 28 | import java.awt.*; |
| 29 | import java.awt.peer.*; |
| 30 | import java.awt.event.*; |
| 31 | import sun.awt.im.*; |
| 32 | import sun.awt.*; |
| 33 | import java.util.logging.*; |
| 34 | import java.lang.reflect.Field; |
| 35 | import java.util.*; |
| 36 | |
| 37 | class XFramePeer extends XDecoratedPeer implements FramePeer, XConstants { |
| 38 | private static Logger log = Logger.getLogger("sun.awt.X11.XFramePeer"); |
| 39 | private static Logger stateLog = Logger.getLogger("sun.awt.X11.states"); |
| 40 | private static Logger insLog = Logger.getLogger("sun.awt.X11.insets.XFramePeer"); |
| 41 | |
| 42 | XMenuBarPeer menubarPeer; |
| 43 | MenuBar menubar; |
| 44 | int state; |
| 45 | private Boolean undecorated; |
| 46 | |
| 47 | private static final int MENUBAR_HEIGHT_IF_NO_MENUBAR = 0; |
| 48 | private int lastAppliedMenubarHeight = MENUBAR_HEIGHT_IF_NO_MENUBAR; |
| 49 | |
| 50 | XFramePeer(Frame target) { |
| 51 | super(target); |
| 52 | } |
| 53 | |
| 54 | XFramePeer(XCreateWindowParams params) { |
| 55 | super(params); |
| 56 | } |
| 57 | |
| 58 | void preInit(XCreateWindowParams params) { |
| 59 | super.preInit(params); |
| 60 | Frame target = (Frame)(this.target); |
| 61 | // set the window attributes for this Frame |
| 62 | winAttr.initialState = target.getExtendedState(); |
| 63 | state = 0; |
| 64 | undecorated = Boolean.valueOf(target.isUndecorated()); |
| 65 | winAttr.nativeDecor = !target.isUndecorated(); |
| 66 | if (winAttr.nativeDecor) { |
| 67 | winAttr.decorations = winAttr.AWT_DECOR_ALL; |
| 68 | } else { |
| 69 | winAttr.decorations = winAttr.AWT_DECOR_NONE; |
| 70 | } |
| 71 | winAttr.functions = MWM_FUNC_ALL; |
| 72 | winAttr.isResizable = true; // target.isResizable(); |
| 73 | winAttr.title = target.getTitle(); |
| 74 | winAttr.initialResizability = target.isResizable(); |
| 75 | if (log.isLoggable(Level.FINE)) { |
| 76 | log.log(Level.FINE, "Frame''s initial attributes: decor {0}, resizable {1}, undecorated {2}, initial state {3}", |
| 77 | new Object[] {Integer.valueOf(winAttr.decorations), Boolean.valueOf(winAttr.initialResizability), |
| 78 | Boolean.valueOf(!winAttr.nativeDecor), Integer.valueOf(winAttr.initialState)}); |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | void postInit(XCreateWindowParams params) { |
| 83 | super.postInit(params); |
| 84 | setupState(true); |
| 85 | } |
| 86 | |
| 87 | protected Insets guessInsets() { |
| 88 | if (isTargetUndecorated()) { |
| 89 | return new Insets(0, 0, 0, 0); |
| 90 | } else { |
| 91 | return super.guessInsets(); |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | private boolean isTargetUndecorated() { |
| 96 | if (undecorated != null) { |
| 97 | return undecorated.booleanValue(); |
| 98 | } else { |
| 99 | return ((Frame)target).isUndecorated(); |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | void setupState(boolean onInit) { |
| 104 | if (onInit) { |
| 105 | state = winAttr.initialState; |
| 106 | } |
| 107 | if ((state & Frame.ICONIFIED) != 0) { |
| 108 | setInitialState(IconicState); |
| 109 | } else { |
| 110 | setInitialState(NormalState); |
| 111 | } |
| 112 | setExtendedState(state); |
| 113 | } |
| 114 | |
| 115 | public void setMenuBar(MenuBar mb) { |
| 116 | // state_lock should always be the second after awt_lock |
| 117 | XToolkit.awtLock(); |
| 118 | try { |
| 119 | synchronized(getStateLock()) { |
| 120 | if (mb == menubar) return; |
| 121 | if (mb == null) { |
| 122 | if (menubar != null) { |
| 123 | menubarPeer.xSetVisible(false); |
| 124 | menubar = null; |
| 125 | menubarPeer.dispose(); |
| 126 | menubarPeer = null; |
| 127 | } |
| 128 | } else { |
| 129 | menubar = mb; |
| 130 | menubarPeer = (XMenuBarPeer) mb.getPeer(); |
| 131 | if (menubarPeer != null) { |
| 132 | menubarPeer.init((Frame)target); |
| 133 | } |
| 134 | } |
| 135 | } |
| 136 | } finally { |
| 137 | XToolkit.awtUnlock(); |
| 138 | } |
| 139 | |
| 140 | reshapeMenubarPeer(); |
| 141 | } |
| 142 | |
| 143 | XMenuBarPeer getMenubarPeer() { |
| 144 | return menubarPeer; |
| 145 | } |
| 146 | |
| 147 | int getMenuBarHeight() { |
| 148 | if (menubarPeer != null) { |
| 149 | return menubarPeer.getDesiredHeight(); |
| 150 | } else { |
| 151 | return MENUBAR_HEIGHT_IF_NO_MENUBAR; |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | void updateChildrenSizes() { |
| 156 | super.updateChildrenSizes(); |
| 157 | // XWindow.reshape calls XBaseWindow.xSetBounds, which acquires |
| 158 | // the AWT lock, so we have to acquire the AWT lock here |
| 159 | // before getStateLock() to avoid a deadlock with the Toolkit thread |
| 160 | // when this method is called on the EDT. |
| 161 | XToolkit.awtLock(); |
| 162 | try { |
| 163 | synchronized(getStateLock()) { |
| 164 | int width = dimensions.getClientSize().width; |
| 165 | if (menubarPeer != null) { |
| 166 | menubarPeer.reshape(0, 0, width, getMenuBarHeight()); |
| 167 | } |
| 168 | } |
| 169 | } finally { |
| 170 | XToolkit.awtUnlock(); |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | /** |
| 175 | * In addition to reshaping menubarPeer (by using 'updateChildrenSizes') |
| 176 | * this method also performs some frame reaction on this (i.e. layouts |
| 177 | * other frame children, if required) |
| 178 | */ |
| 179 | final void reshapeMenubarPeer() { |
| 180 | XToolkit.executeOnEventHandlerThread( |
| 181 | target, |
| 182 | new Runnable() { |
| 183 | public void run() { |
| 184 | updateChildrenSizes(); |
| 185 | boolean heightChanged = false; |
| 186 | |
| 187 | int height = getMenuBarHeight(); |
| 188 | // Neither 'XToolkit.awtLock()' nor 'getStateLock()' |
| 189 | // is acquired under this call, and it looks to run |
| 190 | // thread-safely. I currently see no reason to move |
| 191 | // it under following 'synchronized' clause. |
| 192 | |
| 193 | synchronized(getStateLock()) { |
| 194 | if (height != lastAppliedMenubarHeight) { |
| 195 | lastAppliedMenubarHeight = height; |
| 196 | heightChanged = true; |
| 197 | } |
| 198 | } |
| 199 | if (heightChanged) { |
| 200 | // To make frame contents be re-layout (copied from |
| 201 | // 'XDecoratedPeer.revalidate()'). These are not |
| 202 | // 'synchronized', because can recursively call client |
| 203 | // methods, which are not supposed to be called with locks |
| 204 | // acquired. |
| 205 | target.invalidate(); |
| 206 | target.validate(); |
| 207 | } |
| 208 | } |
| 209 | } |
| 210 | ); |
| 211 | } |
| 212 | |
| 213 | public void setMaximizedBounds(Rectangle b) { |
| 214 | if (insLog.isLoggable(Level.FINE)) insLog.fine("Setting maximized bounds to " + b); |
| 215 | if (b == null) return; |
| 216 | maxBounds = new Rectangle(b); |
| 217 | XToolkit.awtLock(); |
| 218 | try { |
| 219 | XSizeHints hints = getHints(); |
| 220 | hints.set_flags(hints.get_flags() | (int)XlibWrapper.PMaxSize); |
| 221 | if (b.width != Integer.MAX_VALUE) { |
| 222 | hints.set_max_width(b.width); |
| 223 | } else { |
| 224 | hints.set_max_width((int)XlibWrapper.DisplayWidth(XToolkit.getDisplay(), XlibWrapper.DefaultScreen(XToolkit.getDisplay()))); |
| 225 | } |
| 226 | if (b.height != Integer.MAX_VALUE) { |
| 227 | hints.set_max_height(b.height); |
| 228 | } else { |
| 229 | hints.set_max_height((int)XlibWrapper.DisplayHeight(XToolkit.getDisplay(), XlibWrapper.DefaultScreen(XToolkit.getDisplay()))); |
| 230 | } |
| 231 | if (insLog.isLoggable(Level.FINER)) insLog.finer("Setting hints, flags " + XlibWrapper.hintsToString(hints.get_flags())); |
| 232 | XlibWrapper.XSetWMNormalHints(XToolkit.getDisplay(), window, hints.pData); |
| 233 | } finally { |
| 234 | XToolkit.awtUnlock(); |
| 235 | } |
| 236 | } |
| 237 | |
| 238 | public int getState() { return state; } |
| 239 | |
| 240 | public void setState(int newState) { |
| 241 | if (!isShowing()) { |
| 242 | stateLog.finer("Frame is not showing"); |
| 243 | state = newState; |
| 244 | return; |
| 245 | } |
| 246 | changeState(newState); |
| 247 | } |
| 248 | |
| 249 | void changeState(int newState) { |
| 250 | int changed = state ^ newState; |
| 251 | int changeIconic = changed & Frame.ICONIFIED; |
| 252 | boolean iconic = (newState & Frame.ICONIFIED) != 0; |
| 253 | stateLog.log(Level.FINER, "Changing state, old state {0}, new state {1}(iconic {2})", |
| 254 | new Object[] {Integer.valueOf(state), Integer.valueOf(newState), Boolean.valueOf(iconic)}); |
| 255 | if (changeIconic != 0 && iconic) { |
| 256 | if (stateLog.isLoggable(Level.FINER)) stateLog.finer("Iconifying shell " + getShell() + ", this " + this + ", screen " + getScreenNumber()); |
| 257 | XToolkit.awtLock(); |
| 258 | try { |
| 259 | int res = XlibWrapper.XIconifyWindow(XToolkit.getDisplay(), getShell(), getScreenNumber()); |
| 260 | if (stateLog.isLoggable(Level.FINER)) stateLog.finer("XIconifyWindow returned " + res); |
| 261 | } |
| 262 | finally { |
| 263 | XToolkit.awtUnlock(); |
| 264 | } |
| 265 | } |
| 266 | if ((changed & ~Frame.ICONIFIED) != 0) { |
| 267 | setExtendedState(newState); |
| 268 | } |
| 269 | if (changeIconic != 0 && !iconic) { |
| 270 | if (stateLog.isLoggable(Level.FINER)) stateLog.finer("DeIconifying " + this); |
| 271 | xSetVisible(true); |
| 272 | } |
| 273 | } |
| 274 | |
| 275 | void setExtendedState(int newState) { |
| 276 | XWM.getWM().setExtendedState(this, newState); |
| 277 | } |
| 278 | |
| 279 | public void handlePropertyNotify(XEvent xev) { |
| 280 | super.handlePropertyNotify(xev); |
| 281 | XPropertyEvent ev = xev.get_xproperty(); |
| 282 | |
| 283 | log.log(Level.FINER, "Property change {0}", new Object[] {ev}); |
| 284 | /* |
| 285 | * Let's see if this is a window state protocol message, and |
| 286 | * if it is - decode a new state in terms of java constants. |
| 287 | */ |
| 288 | Integer newState = XWM.getWM().isStateChange(this, ev); |
| 289 | if (newState == null) { |
| 290 | return; |
| 291 | } |
| 292 | |
| 293 | int changed = state ^ newState.intValue(); |
| 294 | if (changed == 0) { |
| 295 | stateLog.finer("State is the same: " + state); |
| 296 | return; |
| 297 | } |
| 298 | |
| 299 | int old_state = state; |
| 300 | state = newState.intValue(); |
| 301 | |
| 302 | if ((changed & Frame.ICONIFIED) != 0) { |
| 303 | if ((state & Frame.ICONIFIED) != 0) { |
| 304 | stateLog.finer("Iconified"); |
| 305 | handleIconify(); |
| 306 | } else { |
| 307 | stateLog.finer("DeIconified"); |
| 308 | content.purgeIconifiedExposeEvents(); |
| 309 | handleDeiconify(); |
| 310 | } |
| 311 | } |
| 312 | handleStateChange(old_state, state); |
| 313 | } |
| 314 | |
| 315 | // NOTE: This method may be called by privileged threads. |
| 316 | // DO NOT INVOKE CLIENT CODE ON THIS THREAD! |
| 317 | public void handleStateChange(int oldState, int newState) { |
| 318 | super.handleStateChange(oldState, newState); |
| 319 | for (ToplevelStateListener topLevelListenerTmp : toplevelStateListeners) { |
| 320 | topLevelListenerTmp.stateChangedJava(oldState, newState); |
| 321 | } |
| 322 | } |
| 323 | |
| 324 | public void setVisible(boolean vis) { |
| 325 | if (vis) { |
| 326 | setupState(false); |
| 327 | } else { |
| 328 | if ((state & Frame.MAXIMIZED_BOTH) != 0) { |
| 329 | XWM.getWM().setExtendedState(this, state & ~Frame.MAXIMIZED_BOTH); |
| 330 | } |
| 331 | } |
| 332 | super.setVisible(vis); |
| 333 | if (vis && maxBounds != null) { |
| 334 | setMaximizedBounds(maxBounds); |
| 335 | } |
| 336 | } |
| 337 | |
| 338 | void setInitialState(int wm_state) { |
| 339 | XToolkit.awtLock(); |
| 340 | try { |
| 341 | XWMHints hints = getWMHints(); |
| 342 | hints.set_flags((int)XlibWrapper.StateHint | hints.get_flags()); |
| 343 | hints.set_initial_state(wm_state); |
| 344 | if (stateLog.isLoggable(Level.FINE)) stateLog.fine("Setting initial WM state on " + this + " to " + wm_state); |
| 345 | XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData); |
| 346 | } |
| 347 | finally { |
| 348 | XToolkit.awtUnlock(); |
| 349 | } |
| 350 | } |
| 351 | |
| 352 | public void dispose() { |
| 353 | if (menubarPeer != null) { |
| 354 | menubarPeer.dispose(); |
| 355 | } |
| 356 | super.dispose(); |
| 357 | } |
| 358 | |
| 359 | boolean isMaximized() { |
| 360 | return (state & (Frame.MAXIMIZED_VERT | Frame.MAXIMIZED_HORIZ)) != 0; |
| 361 | } |
| 362 | |
| 363 | |
| 364 | |
| 365 | |
| 366 | static final int CROSSHAIR_INSET = 5; |
| 367 | |
| 368 | static final int BUTTON_Y = CROSSHAIR_INSET + 1; |
| 369 | static final int BUTTON_W = 17; |
| 370 | static final int BUTTON_H = 17; |
| 371 | |
| 372 | static final int SYS_MENU_X = CROSSHAIR_INSET + 1; |
| 373 | static final int SYS_MENU_CONTAINED_X = SYS_MENU_X + 5; |
| 374 | static final int SYS_MENU_CONTAINED_Y = BUTTON_Y + 7; |
| 375 | static final int SYS_MENU_CONTAINED_W = 8; |
| 376 | static final int SYS_MENU_CONTAINED_H = 3; |
| 377 | |
| 378 | static final int MAXIMIZE_X_DIFF = CROSSHAIR_INSET + BUTTON_W; |
| 379 | static final int MAXIMIZE_CONTAINED_X_DIFF = MAXIMIZE_X_DIFF - 5; |
| 380 | static final int MAXIMIZE_CONTAINED_Y = BUTTON_Y + 5; |
| 381 | static final int MAXIMIZE_CONTAINED_W = 8; |
| 382 | static final int MAXIMIZE_CONTAINED_H = 8; |
| 383 | |
| 384 | static final int MINIMIZE_X_DIFF = MAXIMIZE_X_DIFF + BUTTON_W; |
| 385 | static final int MINIMIZE_CONTAINED_X_DIFF = MINIMIZE_X_DIFF - 7; |
| 386 | static final int MINIMIZE_CONTAINED_Y = BUTTON_Y + 7; |
| 387 | static final int MINIMIZE_CONTAINED_W = 3; |
| 388 | static final int MINIMIZE_CONTAINED_H = 3; |
| 389 | |
| 390 | static final int TITLE_X = SYS_MENU_X + BUTTON_W; |
| 391 | static final int TITLE_W_DIFF = BUTTON_W * 3 + CROSSHAIR_INSET * 2 - 1; |
| 392 | static final int TITLE_MID_Y = BUTTON_Y + (BUTTON_H / 2); |
| 393 | |
| 394 | static final int MENUBAR_X = CROSSHAIR_INSET + 1; |
| 395 | static final int MENUBAR_Y = BUTTON_Y + BUTTON_H; |
| 396 | |
| 397 | static final int HORIZ_RESIZE_INSET = CROSSHAIR_INSET + BUTTON_H; |
| 398 | static final int VERT_RESIZE_INSET = CROSSHAIR_INSET + BUTTON_W; |
| 399 | |
| 400 | |
| 401 | /* |
| 402 | * Print the native component by rendering the Motif look ourselves. |
| 403 | * We also explicitly print the MenuBar since a MenuBar isn't a subclass |
| 404 | * of Component (and thus it has no "print" method which gets called by |
| 405 | * default). |
| 406 | */ |
| 407 | public void print(Graphics g) { |
| 408 | super.print(g); |
| 409 | |
| 410 | Frame f = (Frame)target; |
| 411 | Insets finsets = f.getInsets(); |
| 412 | Dimension fsize = f.getSize(); |
| 413 | |
| 414 | Color bg = f.getBackground(); |
| 415 | Color fg = f.getForeground(); |
| 416 | Color highlight = bg.brighter(); |
| 417 | Color shadow = bg.darker(); |
| 418 | |
| 419 | // Well, we could query for the currently running window manager |
| 420 | // and base the look on that, or we could just always do dtwm. |
| 421 | // aim, tball, and levenson all agree we'll just do dtwm. |
| 422 | |
| 423 | if (hasDecorations(XWindowAttributesData.AWT_DECOR_BORDER)) { |
| 424 | |
| 425 | // top outer -- because we'll most likely be drawing on white paper, |
| 426 | // for aesthetic reasons, don't make any part of the outer border |
| 427 | // pure white |
| 428 | if (highlight.equals(Color.white)) { |
| 429 | g.setColor(new Color(230, 230, 230)); |
| 430 | } |
| 431 | else { |
| 432 | g.setColor(highlight); |
| 433 | } |
| 434 | g.drawLine(0, 0, fsize.width, 0); |
| 435 | g.drawLine(0, 1, fsize.width - 1, 1); |
| 436 | |
| 437 | // left outer |
| 438 | // if (highlight.equals(Color.white)) { |
| 439 | // g.setColor(new Color(230, 230, 230)); |
| 440 | // } |
| 441 | // else { |
| 442 | // g.setColor(highlight); |
| 443 | // } |
| 444 | g.drawLine(0, 0, 0, fsize.height); |
| 445 | g.drawLine(1, 0, 1, fsize.height - 1); |
| 446 | |
| 447 | // bottom cross-hair |
| 448 | g.setColor(highlight); |
| 449 | g.drawLine(CROSSHAIR_INSET + 1, fsize.height - CROSSHAIR_INSET, |
| 450 | fsize.width - CROSSHAIR_INSET, |
| 451 | fsize.height - CROSSHAIR_INSET); |
| 452 | |
| 453 | // right cross-hair |
| 454 | // g.setColor(highlight); |
| 455 | g.drawLine(fsize.width - CROSSHAIR_INSET, CROSSHAIR_INSET + 1, |
| 456 | fsize.width - CROSSHAIR_INSET, |
| 457 | fsize.height - CROSSHAIR_INSET); |
| 458 | |
| 459 | // bottom outer |
| 460 | g.setColor(shadow); |
| 461 | g.drawLine(1, fsize.height, fsize.width, fsize.height); |
| 462 | g.drawLine(2, fsize.height - 1, fsize.width, fsize.height - 1); |
| 463 | |
| 464 | // right outer |
| 465 | // g.setColor(shadow); |
| 466 | g.drawLine(fsize.width, 1, fsize.width, fsize.height); |
| 467 | g.drawLine(fsize.width - 1, 2, fsize.width - 1, fsize.height); |
| 468 | |
| 469 | // top cross-hair |
| 470 | // g.setColor(shadow); |
| 471 | g.drawLine(CROSSHAIR_INSET, CROSSHAIR_INSET, |
| 472 | fsize.width - CROSSHAIR_INSET, CROSSHAIR_INSET); |
| 473 | |
| 474 | // left cross-hair |
| 475 | // g.setColor(shadow); |
| 476 | g.drawLine(CROSSHAIR_INSET, CROSSHAIR_INSET, CROSSHAIR_INSET, |
| 477 | fsize.height - CROSSHAIR_INSET); |
| 478 | } |
| 479 | |
| 480 | if (hasDecorations(XWindowAttributesData.AWT_DECOR_TITLE)) { |
| 481 | |
| 482 | if (hasDecorations(XWindowAttributesData.AWT_DECOR_MENU)) { |
| 483 | |
| 484 | // system menu |
| 485 | g.setColor(bg); |
| 486 | g.fill3DRect(SYS_MENU_X, BUTTON_Y, BUTTON_W, BUTTON_H, true); |
| 487 | g.fill3DRect(SYS_MENU_CONTAINED_X, SYS_MENU_CONTAINED_Y, |
| 488 | SYS_MENU_CONTAINED_W, SYS_MENU_CONTAINED_H, true); |
| 489 | } |
| 490 | |
| 491 | // title bar |
| 492 | // g.setColor(bg); |
| 493 | g.fill3DRect(TITLE_X, BUTTON_Y, fsize.width - TITLE_W_DIFF, BUTTON_H, |
| 494 | true); |
| 495 | |
| 496 | if (hasDecorations(XWindowAttributesData.AWT_DECOR_MINIMIZE)) { |
| 497 | |
| 498 | // minimize button |
| 499 | // g.setColor(bg); |
| 500 | g.fill3DRect(fsize.width - MINIMIZE_X_DIFF, BUTTON_Y, BUTTON_W, |
| 501 | BUTTON_H, true); |
| 502 | g.fill3DRect(fsize.width - MINIMIZE_CONTAINED_X_DIFF, |
| 503 | MINIMIZE_CONTAINED_Y, MINIMIZE_CONTAINED_W, |
| 504 | MINIMIZE_CONTAINED_H, true); |
| 505 | } |
| 506 | |
| 507 | if (hasDecorations(XWindowAttributesData.AWT_DECOR_MAXIMIZE)) { |
| 508 | |
| 509 | // maximize button |
| 510 | // g.setColor(bg); |
| 511 | g.fill3DRect(fsize.width - MAXIMIZE_X_DIFF, BUTTON_Y, BUTTON_W, |
| 512 | BUTTON_H, true); |
| 513 | g.fill3DRect(fsize.width - MAXIMIZE_CONTAINED_X_DIFF, |
| 514 | MAXIMIZE_CONTAINED_Y, MAXIMIZE_CONTAINED_W, |
| 515 | MAXIMIZE_CONTAINED_H, true); |
| 516 | } |
| 517 | |
| 518 | // title bar text |
| 519 | g.setColor(fg); |
| 520 | Font sysfont = new Font(Font.SANS_SERIF, Font.PLAIN, 10); |
| 521 | g.setFont(sysfont); |
| 522 | FontMetrics sysfm = g.getFontMetrics(); |
| 523 | String ftitle = f.getTitle(); |
| 524 | g.drawString(ftitle, |
| 525 | ((TITLE_X + TITLE_X + fsize.width - TITLE_W_DIFF) / 2) - |
| 526 | (sysfm.stringWidth(ftitle) / 2), |
| 527 | TITLE_MID_Y + sysfm.getMaxDescent()); |
| 528 | } |
| 529 | |
| 530 | if (f.isResizable() && |
| 531 | hasDecorations(XWindowAttributesData.AWT_DECOR_RESIZEH)) { |
| 532 | |
| 533 | // add resize cross hairs |
| 534 | |
| 535 | // upper-left horiz (shadow) |
| 536 | g.setColor(shadow); |
| 537 | g.drawLine(1, HORIZ_RESIZE_INSET, CROSSHAIR_INSET, |
| 538 | HORIZ_RESIZE_INSET); |
| 539 | // upper-left vert (shadow) |
| 540 | // g.setColor(shadow); |
| 541 | g.drawLine(VERT_RESIZE_INSET, 1, VERT_RESIZE_INSET, CROSSHAIR_INSET); |
| 542 | // upper-right horiz (shadow) |
| 543 | // g.setColor(shadow); |
| 544 | g.drawLine(fsize.width - CROSSHAIR_INSET + 1, HORIZ_RESIZE_INSET, |
| 545 | fsize.width, HORIZ_RESIZE_INSET); |
| 546 | // upper-right vert (shadow) |
| 547 | // g.setColor(shadow); |
| 548 | g.drawLine(fsize.width - VERT_RESIZE_INSET - 1, 2, |
| 549 | fsize.width - VERT_RESIZE_INSET - 1, CROSSHAIR_INSET + 1); |
| 550 | // lower-left horiz (shadow) |
| 551 | // g.setColor(shadow); |
| 552 | g.drawLine(1, fsize.height - HORIZ_RESIZE_INSET - 1, |
| 553 | CROSSHAIR_INSET, fsize.height - HORIZ_RESIZE_INSET - 1); |
| 554 | // lower-left vert (shadow) |
| 555 | // g.setColor(shadow); |
| 556 | g.drawLine(VERT_RESIZE_INSET, fsize.height - CROSSHAIR_INSET + 1, |
| 557 | VERT_RESIZE_INSET, fsize.height); |
| 558 | // lower-right horiz (shadow) |
| 559 | // g.setColor(shadow); |
| 560 | g.drawLine(fsize.width - CROSSHAIR_INSET + 1, |
| 561 | fsize.height - HORIZ_RESIZE_INSET - 1, fsize.width, |
| 562 | fsize.height - HORIZ_RESIZE_INSET - 1); |
| 563 | // lower-right vert (shadow) |
| 564 | // g.setColor(shadow); |
| 565 | g.drawLine(fsize.width - VERT_RESIZE_INSET - 1, |
| 566 | fsize.height - CROSSHAIR_INSET + 1, |
| 567 | fsize.width - VERT_RESIZE_INSET - 1, fsize.height); |
| 568 | |
| 569 | // upper-left horiz (highlight) |
| 570 | g.setColor(highlight); |
| 571 | g.drawLine(2, HORIZ_RESIZE_INSET + 1, CROSSHAIR_INSET, |
| 572 | HORIZ_RESIZE_INSET + 1); |
| 573 | // upper-left vert (highlight) |
| 574 | // g.setColor(highlight); |
| 575 | g.drawLine(VERT_RESIZE_INSET + 1, 2, VERT_RESIZE_INSET + 1, |
| 576 | CROSSHAIR_INSET); |
| 577 | // upper-right horiz (highlight) |
| 578 | // g.setColor(highlight); |
| 579 | g.drawLine(fsize.width - CROSSHAIR_INSET + 1, |
| 580 | HORIZ_RESIZE_INSET + 1, fsize.width - 1, |
| 581 | HORIZ_RESIZE_INSET + 1); |
| 582 | // upper-right vert (highlight) |
| 583 | // g.setColor(highlight); |
| 584 | g.drawLine(fsize.width - VERT_RESIZE_INSET, 2, |
| 585 | fsize.width - VERT_RESIZE_INSET, CROSSHAIR_INSET); |
| 586 | // lower-left horiz (highlight) |
| 587 | // g.setColor(highlight); |
| 588 | g.drawLine(2, fsize.height - HORIZ_RESIZE_INSET, CROSSHAIR_INSET, |
| 589 | fsize.height - HORIZ_RESIZE_INSET); |
| 590 | // lower-left vert (highlight) |
| 591 | // g.setColor(highlight); |
| 592 | g.drawLine(VERT_RESIZE_INSET + 1, |
| 593 | fsize.height - CROSSHAIR_INSET + 1, |
| 594 | VERT_RESIZE_INSET + 1, fsize.height - 1); |
| 595 | // lower-right horiz (highlight) |
| 596 | // g.setColor(highlight); |
| 597 | g.drawLine(fsize.width - CROSSHAIR_INSET + 1, |
| 598 | fsize.height - HORIZ_RESIZE_INSET, fsize.width - 1, |
| 599 | fsize.height - HORIZ_RESIZE_INSET); |
| 600 | // lower-right vert (highlight) |
| 601 | // g.setColor(highlight); |
| 602 | g.drawLine(fsize.width - VERT_RESIZE_INSET, |
| 603 | fsize.height - CROSSHAIR_INSET + 1, |
| 604 | fsize.width - VERT_RESIZE_INSET, fsize.height - 1); |
| 605 | } |
| 606 | |
| 607 | XMenuBarPeer peer = menubarPeer; |
| 608 | if (peer != null) { |
| 609 | Insets insets = getInsets(); |
| 610 | Graphics ng = g.create(); |
| 611 | int menubarX = 0; |
| 612 | int menubarY = 0; |
| 613 | if (hasDecorations(XWindowAttributesData.AWT_DECOR_BORDER)) { |
| 614 | menubarX += CROSSHAIR_INSET + 1; |
| 615 | menubarY += CROSSHAIR_INSET + 1; |
| 616 | } |
| 617 | if (hasDecorations(XWindowAttributesData.AWT_DECOR_TITLE)) { |
| 618 | menubarY += BUTTON_H; |
| 619 | } |
| 620 | try { |
| 621 | ng.translate(menubarX, menubarY); |
| 622 | peer.print(ng); |
| 623 | } finally { |
| 624 | ng.dispose(); |
| 625 | } |
| 626 | } |
| 627 | } |
| 628 | |
| 629 | public void setBoundsPrivate(int x, int y, int width, int height) { |
| 630 | setBounds(x, y, width, height, SET_BOUNDS); |
| 631 | } |
| 632 | |
| 633 | public Rectangle getBoundsPrivate() { |
| 634 | return getBounds(); |
| 635 | } |
| 636 | } |