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