1 /*
   2  * Copyright (c) 2002, 2015, 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 = XWindowAttributesData.AWT_DECOR_ALL;
  71         } else {
  72             winAttr.decorations = XWindowAttributesData.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.Level.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     @SuppressWarnings("deprecation")
 112     public void setMenuBar(MenuBar mb) {
 113         // state_lock should always be the second after awt_lock
 114         XToolkit.awtLock();
 115         try {
 116             synchronized(getStateLock()) {
 117                 if (mb == menubar) return;
 118                 if (mb == null) {
 119                     if (menubar != null) {
 120                         menubarPeer.xSetVisible(false);
 121                         menubar = null;
 122                         menubarPeer.dispose();
 123                         menubarPeer = null;
 124                     }
 125                 } else {
 126                     menubar = mb;
 127                     menubarPeer = AWTAccessor.getMenuComponentAccessor()
 128                                              .getPeer(mb);
 129                     if (menubarPeer != null) {
 130                         menubarPeer.init((Frame)target);
 131                     }
 132                 }
 133             }
 134         } finally {
 135             XToolkit.awtUnlock();
 136         }
 137 
 138         reshapeMenubarPeer();
 139     }
 140 
 141     XMenuBarPeer getMenubarPeer() {
 142         return menubarPeer;
 143     }
 144 
 145     int getMenuBarHeight() {
 146         if (menubarPeer != null) {
 147             return menubarPeer.getDesiredHeight();
 148         } else {
 149             return MENUBAR_HEIGHT_IF_NO_MENUBAR;
 150         }
 151     }
 152 
 153     void updateChildrenSizes() {
 154         super.updateChildrenSizes();
 155         int height = getMenuBarHeight();
 156 
 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, height);
 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(PlatformLogger.Level.FINE)) {
 215             insLog.fine("Setting maximized bounds to " + b);
 216         }
 217         if (b == null) return;
 218         maxBounds = new Rectangle(b);
 219         XToolkit.awtLock();
 220         try {
 221             XSizeHints hints = getHints();
 222             hints.set_flags(hints.get_flags() | (int)XUtilConstants.PMaxSize);
 223             if (b.width != Integer.MAX_VALUE) {
 224                 hints.set_max_width(b.width);
 225             } else {
 226                 hints.set_max_width((int)XlibWrapper.DisplayWidth(XToolkit.getDisplay(), XlibWrapper.DefaultScreen(XToolkit.getDisplay())));
 227             }
 228             if (b.height != Integer.MAX_VALUE) {
 229                 hints.set_max_height(b.height);
 230             } else {
 231                 hints.set_max_height((int)XlibWrapper.DisplayHeight(XToolkit.getDisplay(), XlibWrapper.DefaultScreen(XToolkit.getDisplay())));
 232             }
 233             if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 234                 insLog.finer("Setting hints, flags " + XlibWrapper.hintsToString(hints.get_flags()));
 235             }
 236             XlibWrapper.XSetWMNormalHints(XToolkit.getDisplay(), window, hints.pData);
 237         } finally {
 238             XToolkit.awtUnlock();
 239         }
 240     }
 241 
 242     public int getState() {
 243         synchronized(getStateLock()) {
 244             return state;
 245         }
 246     }
 247 
 248     public void setState(int newState) {
 249         synchronized(getStateLock()) {
 250             if (!isShowing()) {
 251                 stateLog.finer("Frame is not showing");
 252                 state = newState;
 253                 return;
 254             }
 255         }
 256         changeState(newState);
 257     }
 258 
 259     void changeState(int newState) {
 260         int changed = state ^ newState;
 261         int changeIconic = changed & Frame.ICONIFIED;
 262         boolean iconic = (newState & Frame.ICONIFIED) != 0;
 263         if (stateLog.isLoggable(PlatformLogger.Level.FINER)) {
 264             stateLog.finer("Changing state, old state {0}, new state {1}(iconic {2})",
 265                        Integer.valueOf(state), Integer.valueOf(newState), Boolean.valueOf(iconic));
 266         }
 267         if (changeIconic != 0 && iconic) {
 268             if (stateLog.isLoggable(PlatformLogger.Level.FINER)) {
 269                 stateLog.finer("Iconifying shell " + getShell() + ", this " + this + ", screen " + getScreenNumber());
 270             }
 271             XToolkit.awtLock();
 272             try {
 273                 int res = XlibWrapper.XIconifyWindow(XToolkit.getDisplay(), getShell(), getScreenNumber());
 274                 if (stateLog.isLoggable(PlatformLogger.Level.FINER)) {
 275                     stateLog.finer("XIconifyWindow returned " + res);
 276                 }
 277             }
 278             finally {
 279                 XToolkit.awtUnlock();
 280             }
 281         }
 282         if ((changed & ~Frame.ICONIFIED) != 0) {
 283             setExtendedState(newState);
 284         }
 285         if (changeIconic != 0 && !iconic) {
 286             if (stateLog.isLoggable(PlatformLogger.Level.FINER)) {
 287                 stateLog.finer("DeIconifying " + this);
 288             }
 289 
 290             XNETProtocol net_protocol = XWM.getWM().getNETProtocol();
 291             if (net_protocol != null) {
 292                 net_protocol.setActiveWindow(getWindow());
 293             }
 294             xSetVisible(true);
 295         }
 296     }
 297 
 298     void setExtendedState(int newState) {
 299         XWM.getWM().setExtendedState(this, newState);
 300     }
 301 
 302     public void handlePropertyNotify(XEvent xev) {
 303         super.handlePropertyNotify(xev);
 304         XPropertyEvent ev = xev.get_xproperty();
 305 
 306         if (log.isLoggable(PlatformLogger.Level.FINER)) {
 307             log.finer("Property change {0}", ev);
 308         }
 309         /*
 310          * Let's see if this is a window state protocol message, and
 311          * if it is - decode a new state in terms of java constants.
 312          */
 313         if (!XWM.getWM().isStateChange(this, ev)) {
 314             stateLog.finer("either not a state atom or state has not been changed");
 315             return;
 316         }
 317 
 318         final int newState = XWM.getWM().getState(this);
 319         int changed = state ^ newState;
 320         if (changed == 0) {
 321             if (stateLog.isLoggable(PlatformLogger.Level.FINER)) {
 322                 stateLog.finer("State is the same: " + state);
 323             }
 324             return;
 325         }
 326 
 327         int old_state = state;
 328         state = newState;
 329 
 330         // sync target with peer
 331         AWTAccessor.getFrameAccessor().setExtendedState((Frame)target, state);
 332 
 333         if ((changed & Frame.ICONIFIED) != 0) {
 334             if ((state & Frame.ICONIFIED) != 0) {
 335                 stateLog.finer("Iconified");
 336                 handleIconify();
 337             } else {
 338                 stateLog.finer("DeIconified");
 339                 content.purgeIconifiedExposeEvents();
 340                 handleDeiconify();
 341             }
 342         }
 343         handleStateChange(old_state, state);
 344     }
 345 
 346     // NOTE: This method may be called by privileged threads.
 347     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 348     public void handleStateChange(int oldState, int newState) {
 349         super.handleStateChange(oldState, newState);
 350         for (ToplevelStateListener topLevelListenerTmp : toplevelStateListeners) {
 351             topLevelListenerTmp.stateChangedJava(oldState, newState);
 352         }
 353     }
 354 
 355     public void setVisible(boolean vis) {
 356         if (isDisposed()) {
 357             return;
 358         }
 359         if (vis) {
 360             setupState(false);
 361         } else {
 362             if ((state & Frame.MAXIMIZED_BOTH) != 0) {
 363                 XWM.getWM().setExtendedState(this, state & ~Frame.MAXIMIZED_BOTH);
 364             }
 365         }
 366         super.setVisible(vis);
 367         if (vis && maxBounds != null) {
 368             setMaximizedBounds(maxBounds);
 369         }
 370     }
 371 
 372     void setInitialState(int wm_state) {
 373         XToolkit.awtLock();
 374         try {
 375             XWMHints hints = getWMHints();
 376             hints.set_flags((int)XUtilConstants.StateHint | hints.get_flags());
 377             hints.set_initial_state(wm_state);
 378             if (stateLog.isLoggable(PlatformLogger.Level.FINE)) {
 379                 stateLog.fine("Setting initial WM state on " + this + " to " + wm_state);
 380             }
 381             XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData);
 382         }
 383         finally {
 384             XToolkit.awtUnlock();
 385         }
 386     }
 387 
 388     public void dispose() {
 389         if (menubarPeer != null) {
 390             menubarPeer.dispose();
 391         }
 392         super.dispose();
 393     }
 394 
 395     boolean isMaximized() {
 396         return (state & (Frame.MAXIMIZED_VERT  | Frame.MAXIMIZED_HORIZ)) != 0;
 397     }
 398 
 399 
 400 
 401 
 402     static final int CROSSHAIR_INSET = 5;
 403 
 404     static final int BUTTON_Y = CROSSHAIR_INSET + 1;
 405     static final int BUTTON_W = 17;
 406     static final int BUTTON_H = 17;
 407 
 408     static final int SYS_MENU_X = CROSSHAIR_INSET + 1;
 409     static final int SYS_MENU_CONTAINED_X = SYS_MENU_X + 5;
 410     static final int SYS_MENU_CONTAINED_Y = BUTTON_Y + 7;
 411     static final int SYS_MENU_CONTAINED_W = 8;
 412     static final int SYS_MENU_CONTAINED_H = 3;
 413 
 414     static final int MAXIMIZE_X_DIFF = CROSSHAIR_INSET + BUTTON_W;
 415     static final int MAXIMIZE_CONTAINED_X_DIFF = MAXIMIZE_X_DIFF - 5;
 416     static final int MAXIMIZE_CONTAINED_Y = BUTTON_Y + 5;
 417     static final int MAXIMIZE_CONTAINED_W = 8;
 418     static final int MAXIMIZE_CONTAINED_H = 8;
 419 
 420     static final int MINIMIZE_X_DIFF = MAXIMIZE_X_DIFF + BUTTON_W;
 421     static final int MINIMIZE_CONTAINED_X_DIFF = MINIMIZE_X_DIFF - 7;
 422     static final int MINIMIZE_CONTAINED_Y = BUTTON_Y + 7;
 423     static final int MINIMIZE_CONTAINED_W = 3;
 424     static final int MINIMIZE_CONTAINED_H = 3;
 425 
 426     static final int TITLE_X = SYS_MENU_X + BUTTON_W;
 427     static final int TITLE_W_DIFF = BUTTON_W * 3 + CROSSHAIR_INSET * 2 - 1;
 428     static final int TITLE_MID_Y = BUTTON_Y + (BUTTON_H / 2);
 429 
 430     static final int MENUBAR_X = CROSSHAIR_INSET + 1;
 431     static final int MENUBAR_Y = BUTTON_Y + BUTTON_H;
 432 
 433     static final int HORIZ_RESIZE_INSET = CROSSHAIR_INSET + BUTTON_H;
 434     static final int VERT_RESIZE_INSET = CROSSHAIR_INSET + BUTTON_W;
 435 
 436 
 437     /*
 438      * Print the native component by rendering the Motif look ourselves.
 439      * We also explicitly print the MenuBar since a MenuBar isn't a subclass
 440      * of Component (and thus it has no "print" method which gets called by
 441      * default).
 442      */
 443     public void print(Graphics g) {
 444         super.print(g);
 445 
 446         Frame f = (Frame)target;
 447         Insets finsets = f.getInsets();
 448         Dimension fsize = f.getSize();
 449 
 450         Color bg = f.getBackground();
 451         Color fg = f.getForeground();
 452         Color highlight = bg.brighter();
 453         Color shadow = bg.darker();
 454 
 455         // Well, we could query for the currently running window manager
 456         // and base the look on that, or we could just always do dtwm.
 457         // aim, tball, and levenson all agree we'll just do dtwm.
 458 
 459         if (hasDecorations(XWindowAttributesData.AWT_DECOR_BORDER)) {
 460 
 461             // top outer -- because we'll most likely be drawing on white paper,
 462             // for aesthetic reasons, don't make any part of the outer border
 463             // pure white
 464             if (highlight.equals(Color.white)) {
 465                 g.setColor(new Color(230, 230, 230));
 466             }
 467             else {
 468                 g.setColor(highlight);
 469             }
 470             g.drawLine(0, 0, fsize.width, 0);
 471             g.drawLine(0, 1, fsize.width - 1, 1);
 472 
 473             // left outer
 474             // if (highlight.equals(Color.white)) {
 475             //     g.setColor(new Color(230, 230, 230));
 476             // }
 477             // else {
 478             //     g.setColor(highlight);
 479             // }
 480             g.drawLine(0, 0, 0, fsize.height);
 481             g.drawLine(1, 0, 1, fsize.height - 1);
 482 
 483             // bottom cross-hair
 484             g.setColor(highlight);
 485             g.drawLine(CROSSHAIR_INSET + 1, fsize.height - CROSSHAIR_INSET,
 486                        fsize.width - CROSSHAIR_INSET,
 487                        fsize.height - CROSSHAIR_INSET);
 488 
 489             // right cross-hair
 490             // g.setColor(highlight);
 491             g.drawLine(fsize.width - CROSSHAIR_INSET, CROSSHAIR_INSET + 1,
 492                        fsize.width - CROSSHAIR_INSET,
 493                        fsize.height - CROSSHAIR_INSET);
 494 
 495             // bottom outer
 496             g.setColor(shadow);
 497             g.drawLine(1, fsize.height, fsize.width, fsize.height);
 498             g.drawLine(2, fsize.height - 1, fsize.width, fsize.height - 1);
 499 
 500             // right outer
 501             // g.setColor(shadow);
 502             g.drawLine(fsize.width, 1, fsize.width, fsize.height);
 503             g.drawLine(fsize.width - 1, 2, fsize.width - 1, fsize.height);
 504 
 505             // top cross-hair
 506             // g.setColor(shadow);
 507             g.drawLine(CROSSHAIR_INSET, CROSSHAIR_INSET,
 508                        fsize.width - CROSSHAIR_INSET, CROSSHAIR_INSET);
 509 
 510             // left cross-hair
 511             // g.setColor(shadow);
 512             g.drawLine(CROSSHAIR_INSET, CROSSHAIR_INSET, CROSSHAIR_INSET,
 513                        fsize.height - CROSSHAIR_INSET);
 514         }
 515 
 516         if (hasDecorations(XWindowAttributesData.AWT_DECOR_TITLE)) {
 517 
 518             if (hasDecorations(XWindowAttributesData.AWT_DECOR_MENU)) {
 519 
 520                 // system menu
 521                 g.setColor(bg);
 522                 g.fill3DRect(SYS_MENU_X, BUTTON_Y, BUTTON_W, BUTTON_H, true);
 523                 g.fill3DRect(SYS_MENU_CONTAINED_X, SYS_MENU_CONTAINED_Y,
 524                              SYS_MENU_CONTAINED_W, SYS_MENU_CONTAINED_H, true);
 525             }
 526 
 527             // title bar
 528             // g.setColor(bg);
 529             g.fill3DRect(TITLE_X, BUTTON_Y, fsize.width - TITLE_W_DIFF, BUTTON_H,
 530                          true);
 531 
 532             if (hasDecorations(XWindowAttributesData.AWT_DECOR_MINIMIZE)) {
 533 
 534                 // minimize button
 535                 // g.setColor(bg);
 536                 g.fill3DRect(fsize.width - MINIMIZE_X_DIFF, BUTTON_Y, BUTTON_W,
 537                              BUTTON_H, true);
 538                 g.fill3DRect(fsize.width - MINIMIZE_CONTAINED_X_DIFF,
 539                              MINIMIZE_CONTAINED_Y, MINIMIZE_CONTAINED_W,
 540                              MINIMIZE_CONTAINED_H, true);
 541             }
 542 
 543             if (hasDecorations(XWindowAttributesData.AWT_DECOR_MAXIMIZE)) {
 544 
 545                 // maximize button
 546                 // g.setColor(bg);
 547                 g.fill3DRect(fsize.width - MAXIMIZE_X_DIFF, BUTTON_Y, BUTTON_W,
 548                              BUTTON_H, true);
 549                 g.fill3DRect(fsize.width - MAXIMIZE_CONTAINED_X_DIFF,
 550                              MAXIMIZE_CONTAINED_Y, MAXIMIZE_CONTAINED_W,
 551                              MAXIMIZE_CONTAINED_H, true);
 552             }
 553 
 554             // title bar text
 555             g.setColor(fg);
 556             Font sysfont = new Font(Font.SANS_SERIF, Font.PLAIN, 10);
 557             g.setFont(sysfont);
 558             FontMetrics sysfm = g.getFontMetrics();
 559             String ftitle = f.getTitle();
 560             g.drawString(ftitle,
 561                          ((TITLE_X + TITLE_X + fsize.width - TITLE_W_DIFF) / 2) -
 562                          (sysfm.stringWidth(ftitle) / 2),
 563                          TITLE_MID_Y + sysfm.getMaxDescent());
 564         }
 565 
 566         if (f.isResizable() &&
 567             hasDecorations(XWindowAttributesData.AWT_DECOR_RESIZEH)) {
 568 
 569             // add resize cross hairs
 570 
 571             // upper-left horiz (shadow)
 572             g.setColor(shadow);
 573             g.drawLine(1, HORIZ_RESIZE_INSET, CROSSHAIR_INSET,
 574                        HORIZ_RESIZE_INSET);
 575             // upper-left vert (shadow)
 576             // g.setColor(shadow);
 577             g.drawLine(VERT_RESIZE_INSET, 1, VERT_RESIZE_INSET, CROSSHAIR_INSET);
 578             // upper-right horiz (shadow)
 579             // g.setColor(shadow);
 580             g.drawLine(fsize.width - CROSSHAIR_INSET + 1, HORIZ_RESIZE_INSET,
 581                        fsize.width, HORIZ_RESIZE_INSET);
 582             // upper-right vert (shadow)
 583             // g.setColor(shadow);
 584             g.drawLine(fsize.width - VERT_RESIZE_INSET - 1, 2,
 585                        fsize.width - VERT_RESIZE_INSET - 1, CROSSHAIR_INSET + 1);
 586             // lower-left horiz (shadow)
 587             // g.setColor(shadow);
 588             g.drawLine(1, fsize.height - HORIZ_RESIZE_INSET - 1,
 589                        CROSSHAIR_INSET, fsize.height - HORIZ_RESIZE_INSET - 1);
 590             // lower-left vert (shadow)
 591             // g.setColor(shadow);
 592             g.drawLine(VERT_RESIZE_INSET, fsize.height - CROSSHAIR_INSET + 1,
 593                        VERT_RESIZE_INSET, fsize.height);
 594             // lower-right horiz (shadow)
 595             // g.setColor(shadow);
 596             g.drawLine(fsize.width - CROSSHAIR_INSET + 1,
 597                        fsize.height - HORIZ_RESIZE_INSET - 1, fsize.width,
 598                        fsize.height - HORIZ_RESIZE_INSET - 1);
 599             // lower-right vert (shadow)
 600             // g.setColor(shadow);
 601             g.drawLine(fsize.width - VERT_RESIZE_INSET - 1,
 602                        fsize.height - CROSSHAIR_INSET + 1,
 603                        fsize.width - VERT_RESIZE_INSET - 1, fsize.height);
 604 
 605             // upper-left horiz (highlight)
 606             g.setColor(highlight);
 607             g.drawLine(2, HORIZ_RESIZE_INSET + 1, CROSSHAIR_INSET,
 608                        HORIZ_RESIZE_INSET + 1);
 609             // upper-left vert (highlight)
 610             // g.setColor(highlight);
 611             g.drawLine(VERT_RESIZE_INSET + 1, 2, VERT_RESIZE_INSET + 1,
 612                        CROSSHAIR_INSET);
 613             // upper-right horiz (highlight)
 614             // g.setColor(highlight);
 615             g.drawLine(fsize.width - CROSSHAIR_INSET + 1,
 616                        HORIZ_RESIZE_INSET + 1, fsize.width - 1,
 617                        HORIZ_RESIZE_INSET + 1);
 618             // upper-right vert (highlight)
 619             // g.setColor(highlight);
 620             g.drawLine(fsize.width - VERT_RESIZE_INSET, 2,
 621                        fsize.width - VERT_RESIZE_INSET, CROSSHAIR_INSET);
 622             // lower-left horiz (highlight)
 623             // g.setColor(highlight);
 624             g.drawLine(2, fsize.height - HORIZ_RESIZE_INSET, CROSSHAIR_INSET,
 625                        fsize.height - HORIZ_RESIZE_INSET);
 626             // lower-left vert (highlight)
 627             // g.setColor(highlight);
 628             g.drawLine(VERT_RESIZE_INSET + 1,
 629                        fsize.height - CROSSHAIR_INSET + 1,
 630                        VERT_RESIZE_INSET + 1, fsize.height - 1);
 631             // lower-right horiz (highlight)
 632             // g.setColor(highlight);
 633             g.drawLine(fsize.width - CROSSHAIR_INSET + 1,
 634                        fsize.height - HORIZ_RESIZE_INSET, fsize.width - 1,
 635                        fsize.height - HORIZ_RESIZE_INSET);
 636             // lower-right vert (highlight)
 637             // g.setColor(highlight);
 638             g.drawLine(fsize.width - VERT_RESIZE_INSET,
 639                        fsize.height - CROSSHAIR_INSET + 1,
 640                        fsize.width - VERT_RESIZE_INSET, fsize.height - 1);
 641         }
 642 
 643         XMenuBarPeer peer = menubarPeer;
 644         if (peer != null) {
 645             Insets insets = getInsets();
 646             Graphics ng = g.create();
 647             int menubarX = 0;
 648             int menubarY = 0;
 649             if (hasDecorations(XWindowAttributesData.AWT_DECOR_BORDER)) {
 650                 menubarX += CROSSHAIR_INSET + 1;
 651                     menubarY += CROSSHAIR_INSET + 1;
 652             }
 653             if (hasDecorations(XWindowAttributesData.AWT_DECOR_TITLE)) {
 654                 menubarY += BUTTON_H;
 655             }
 656             try {
 657                 ng.translate(menubarX, menubarY);
 658                 peer.print(ng);
 659             } finally {
 660                 ng.dispose();
 661             }
 662         }
 663     }
 664 
 665     public void setBoundsPrivate(int x, int y, int width, int height) {
 666         setBounds(x, y, width, height, SET_BOUNDS);
 667     }
 668 
 669     public Rectangle getBoundsPrivate() {
 670         return getBounds();
 671     }
 672 
 673     public void emulateActivation(boolean doActivate) {
 674         if (doActivate) {
 675             handleWindowFocusIn(0);
 676         } else {
 677             handleWindowFocusOut(null, 0);
 678         }
 679     }
 680 }