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 */
25package sun.awt.X11;
26
27import java.awt.Color;
28import java.awt.Dimension;
29import java.awt.Font;
30import java.awt.FontMetrics;
31import java.awt.Frame;
32import java.awt.Graphics;
33import java.awt.Insets;
34import java.awt.MenuBar;
35import java.awt.Rectangle;
36import java.awt.peer.FramePeer;
37import sun.util.logging.PlatformLogger;
38import sun.awt.AWTAccessor;
39
40class 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 (vis) {
357            setupState(false);
358        } else {
359            if ((state & Frame.MAXIMIZED_BOTH) != 0) {
360                XWM.getWM().setExtendedState(this, state & ~Frame.MAXIMIZED_BOTH);
361            }
362        }
363        super.setVisible(vis);
364        if (vis && maxBounds != null) {
365            setMaximizedBounds(maxBounds);
366        }
367    }
368
369    void setInitialState(int wm_state) {
370        XToolkit.awtLock();
371        try {
372            XWMHints hints = getWMHints();
373            hints.set_flags((int)XUtilConstants.StateHint | hints.get_flags());
374            hints.set_initial_state(wm_state);
375            if (stateLog.isLoggable(PlatformLogger.Level.FINE)) {
376                stateLog.fine("Setting initial WM state on " + this + " to " + wm_state);
377            }
378            XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData);
379        }
380        finally {
381            XToolkit.awtUnlock();
382        }
383    }
384
385    public void dispose() {
386        if (menubarPeer != null) {
387            menubarPeer.dispose();
388        }
389        super.dispose();
390    }
391
392    boolean isMaximized() {
393        return (state & (Frame.MAXIMIZED_VERT  | Frame.MAXIMIZED_HORIZ)) != 0;
394    }
395
396
397
398
399    static final int CROSSHAIR_INSET = 5;
400
401    static final int BUTTON_Y = CROSSHAIR_INSET + 1;
402    static final int BUTTON_W = 17;
403    static final int BUTTON_H = 17;
404
405    static final int SYS_MENU_X = CROSSHAIR_INSET + 1;
406    static final int SYS_MENU_CONTAINED_X = SYS_MENU_X + 5;
407    static final int SYS_MENU_CONTAINED_Y = BUTTON_Y + 7;
408    static final int SYS_MENU_CONTAINED_W = 8;
409    static final int SYS_MENU_CONTAINED_H = 3;
410
411    static final int MAXIMIZE_X_DIFF = CROSSHAIR_INSET + BUTTON_W;
412    static final int MAXIMIZE_CONTAINED_X_DIFF = MAXIMIZE_X_DIFF - 5;
413    static final int MAXIMIZE_CONTAINED_Y = BUTTON_Y + 5;
414    static final int MAXIMIZE_CONTAINED_W = 8;
415    static final int MAXIMIZE_CONTAINED_H = 8;
416
417    static final int MINIMIZE_X_DIFF = MAXIMIZE_X_DIFF + BUTTON_W;
418    static final int MINIMIZE_CONTAINED_X_DIFF = MINIMIZE_X_DIFF - 7;
419    static final int MINIMIZE_CONTAINED_Y = BUTTON_Y + 7;
420    static final int MINIMIZE_CONTAINED_W = 3;
421    static final int MINIMIZE_CONTAINED_H = 3;
422
423    static final int TITLE_X = SYS_MENU_X + BUTTON_W;
424    static final int TITLE_W_DIFF = BUTTON_W * 3 + CROSSHAIR_INSET * 2 - 1;
425    static final int TITLE_MID_Y = BUTTON_Y + (BUTTON_H / 2);
426
427    static final int MENUBAR_X = CROSSHAIR_INSET + 1;
428    static final int MENUBAR_Y = BUTTON_Y + BUTTON_H;
429
430    static final int HORIZ_RESIZE_INSET = CROSSHAIR_INSET + BUTTON_H;
431    static final int VERT_RESIZE_INSET = CROSSHAIR_INSET + BUTTON_W;
432
433
434    /*
435     * Print the native component by rendering the Motif look ourselves.
436     * We also explicitly print the MenuBar since a MenuBar isn't a subclass
437     * of Component (and thus it has no "print" method which gets called by
438     * default).
439     */
440    public void print(Graphics g) {
441        super.print(g);
442
443        Frame f = (Frame)target;
444        Insets finsets = f.getInsets();
445        Dimension fsize = f.getSize();
446
447        Color bg = f.getBackground();
448        Color fg = f.getForeground();
449        Color highlight = bg.brighter();
450        Color shadow = bg.darker();
451
452        // Well, we could query for the currently running window manager
453        // and base the look on that, or we could just always do dtwm.
454        // aim, tball, and levenson all agree we'll just do dtwm.
455
456        if (hasDecorations(XWindowAttributesData.AWT_DECOR_BORDER)) {
457
458            // top outer -- because we'll most likely be drawing on white paper,
459            // for aesthetic reasons, don't make any part of the outer border
460            // pure white
461            if (highlight.equals(Color.white)) {
462                g.setColor(new Color(230, 230, 230));
463            }
464            else {
465                g.setColor(highlight);
466            }
467            g.drawLine(0, 0, fsize.width, 0);
468            g.drawLine(0, 1, fsize.width - 1, 1);
469
470            // left outer
471            // if (highlight.equals(Color.white)) {
472            //     g.setColor(new Color(230, 230, 230));
473            // }
474            // else {
475            //     g.setColor(highlight);
476            // }
477            g.drawLine(0, 0, 0, fsize.height);
478            g.drawLine(1, 0, 1, fsize.height - 1);
479
480            // bottom cross-hair
481            g.setColor(highlight);
482            g.drawLine(CROSSHAIR_INSET + 1, fsize.height - CROSSHAIR_INSET,
483                       fsize.width - CROSSHAIR_INSET,
484                       fsize.height - CROSSHAIR_INSET);
485
486            // right cross-hair
487            // g.setColor(highlight);
488            g.drawLine(fsize.width - CROSSHAIR_INSET, CROSSHAIR_INSET + 1,
489                       fsize.width - CROSSHAIR_INSET,
490                       fsize.height - CROSSHAIR_INSET);
491
492            // bottom outer
493            g.setColor(shadow);
494            g.drawLine(1, fsize.height, fsize.width, fsize.height);
495            g.drawLine(2, fsize.height - 1, fsize.width, fsize.height - 1);
496
497            // right outer
498            // g.setColor(shadow);
499            g.drawLine(fsize.width, 1, fsize.width, fsize.height);
500            g.drawLine(fsize.width - 1, 2, fsize.width - 1, fsize.height);
501
502            // top cross-hair
503            // g.setColor(shadow);
504            g.drawLine(CROSSHAIR_INSET, CROSSHAIR_INSET,
505                       fsize.width - CROSSHAIR_INSET, CROSSHAIR_INSET);
506
507            // left cross-hair
508            // g.setColor(shadow);
509            g.drawLine(CROSSHAIR_INSET, CROSSHAIR_INSET, CROSSHAIR_INSET,
510                       fsize.height - CROSSHAIR_INSET);
511        }
512
513        if (hasDecorations(XWindowAttributesData.AWT_DECOR_TITLE)) {
514
515            if (hasDecorations(XWindowAttributesData.AWT_DECOR_MENU)) {
516
517                // system menu
518                g.setColor(bg);
519                g.fill3DRect(SYS_MENU_X, BUTTON_Y, BUTTON_W, BUTTON_H, true);
520                g.fill3DRect(SYS_MENU_CONTAINED_X, SYS_MENU_CONTAINED_Y,
521                             SYS_MENU_CONTAINED_W, SYS_MENU_CONTAINED_H, true);
522            }
523
524            // title bar
525            // g.setColor(bg);
526            g.fill3DRect(TITLE_X, BUTTON_Y, fsize.width - TITLE_W_DIFF, BUTTON_H,
527                         true);
528
529            if (hasDecorations(XWindowAttributesData.AWT_DECOR_MINIMIZE)) {
530
531                // minimize button
532                // g.setColor(bg);
533                g.fill3DRect(fsize.width - MINIMIZE_X_DIFF, BUTTON_Y, BUTTON_W,
534                             BUTTON_H, true);
535                g.fill3DRect(fsize.width - MINIMIZE_CONTAINED_X_DIFF,
536                             MINIMIZE_CONTAINED_Y, MINIMIZE_CONTAINED_W,
537                             MINIMIZE_CONTAINED_H, true);
538            }
539
540            if (hasDecorations(XWindowAttributesData.AWT_DECOR_MAXIMIZE)) {
541
542                // maximize button
543                // g.setColor(bg);
544                g.fill3DRect(fsize.width - MAXIMIZE_X_DIFF, BUTTON_Y, BUTTON_W,
545                             BUTTON_H, true);
546                g.fill3DRect(fsize.width - MAXIMIZE_CONTAINED_X_DIFF,
547                             MAXIMIZE_CONTAINED_Y, MAXIMIZE_CONTAINED_W,
548                             MAXIMIZE_CONTAINED_H, true);
549            }
550
551            // title bar text
552            g.setColor(fg);
553            Font sysfont = new Font(Font.SANS_SERIF, Font.PLAIN, 10);
554            g.setFont(sysfont);
555            FontMetrics sysfm = g.getFontMetrics();
556            String ftitle = f.getTitle();
557            g.drawString(ftitle,
558                         ((TITLE_X + TITLE_X + fsize.width - TITLE_W_DIFF) / 2) -
559                         (sysfm.stringWidth(ftitle) / 2),
560                         TITLE_MID_Y + sysfm.getMaxDescent());
561        }
562
563        if (f.isResizable() &&
564            hasDecorations(XWindowAttributesData.AWT_DECOR_RESIZEH)) {
565
566            // add resize cross hairs
567
568            // upper-left horiz (shadow)
569            g.setColor(shadow);
570            g.drawLine(1, HORIZ_RESIZE_INSET, CROSSHAIR_INSET,
571                       HORIZ_RESIZE_INSET);
572            // upper-left vert (shadow)
573            // g.setColor(shadow);
574            g.drawLine(VERT_RESIZE_INSET, 1, VERT_RESIZE_INSET, CROSSHAIR_INSET);
575            // upper-right horiz (shadow)
576            // g.setColor(shadow);
577            g.drawLine(fsize.width - CROSSHAIR_INSET + 1, HORIZ_RESIZE_INSET,
578                       fsize.width, HORIZ_RESIZE_INSET);
579            // upper-right vert (shadow)
580            // g.setColor(shadow);
581            g.drawLine(fsize.width - VERT_RESIZE_INSET - 1, 2,
582                       fsize.width - VERT_RESIZE_INSET - 1, CROSSHAIR_INSET + 1);
583            // lower-left horiz (shadow)
584            // g.setColor(shadow);
585            g.drawLine(1, fsize.height - HORIZ_RESIZE_INSET - 1,
586                       CROSSHAIR_INSET, fsize.height - HORIZ_RESIZE_INSET - 1);
587            // lower-left vert (shadow)
588            // g.setColor(shadow);
589            g.drawLine(VERT_RESIZE_INSET, fsize.height - CROSSHAIR_INSET + 1,
590                       VERT_RESIZE_INSET, fsize.height);
591            // lower-right horiz (shadow)
592            // g.setColor(shadow);
593            g.drawLine(fsize.width - CROSSHAIR_INSET + 1,
594                       fsize.height - HORIZ_RESIZE_INSET - 1, fsize.width,
595                       fsize.height - HORIZ_RESIZE_INSET - 1);
596            // lower-right vert (shadow)
597            // g.setColor(shadow);
598            g.drawLine(fsize.width - VERT_RESIZE_INSET - 1,
599                       fsize.height - CROSSHAIR_INSET + 1,
600                       fsize.width - VERT_RESIZE_INSET - 1, fsize.height);
601
602            // upper-left horiz (highlight)
603            g.setColor(highlight);
604            g.drawLine(2, HORIZ_RESIZE_INSET + 1, CROSSHAIR_INSET,
605                       HORIZ_RESIZE_INSET + 1);
606            // upper-left vert (highlight)
607            // g.setColor(highlight);
608            g.drawLine(VERT_RESIZE_INSET + 1, 2, VERT_RESIZE_INSET + 1,
609                       CROSSHAIR_INSET);
610            // upper-right horiz (highlight)
611            // g.setColor(highlight);
612            g.drawLine(fsize.width - CROSSHAIR_INSET + 1,
613                       HORIZ_RESIZE_INSET + 1, fsize.width - 1,
614                       HORIZ_RESIZE_INSET + 1);
615            // upper-right vert (highlight)
616            // g.setColor(highlight);
617            g.drawLine(fsize.width - VERT_RESIZE_INSET, 2,
618                       fsize.width - VERT_RESIZE_INSET, CROSSHAIR_INSET);
619            // lower-left horiz (highlight)
620            // g.setColor(highlight);
621            g.drawLine(2, fsize.height - HORIZ_RESIZE_INSET, CROSSHAIR_INSET,
622                       fsize.height - HORIZ_RESIZE_INSET);
623            // lower-left vert (highlight)
624            // g.setColor(highlight);
625            g.drawLine(VERT_RESIZE_INSET + 1,
626                       fsize.height - CROSSHAIR_INSET + 1,
627                       VERT_RESIZE_INSET + 1, fsize.height - 1);
628            // lower-right horiz (highlight)
629            // g.setColor(highlight);
630            g.drawLine(fsize.width - CROSSHAIR_INSET + 1,
631                       fsize.height - HORIZ_RESIZE_INSET, fsize.width - 1,
632                       fsize.height - HORIZ_RESIZE_INSET);
633            // lower-right vert (highlight)
634            // g.setColor(highlight);
635            g.drawLine(fsize.width - VERT_RESIZE_INSET,
636                       fsize.height - CROSSHAIR_INSET + 1,
637                       fsize.width - VERT_RESIZE_INSET, fsize.height - 1);
638        }
639
640        XMenuBarPeer peer = menubarPeer;
641        if (peer != null) {
642            Insets insets = getInsets();
643            Graphics ng = g.create();
644            int menubarX = 0;
645            int menubarY = 0;
646            if (hasDecorations(XWindowAttributesData.AWT_DECOR_BORDER)) {
647                menubarX += CROSSHAIR_INSET + 1;
648                    menubarY += CROSSHAIR_INSET + 1;
649            }
650            if (hasDecorations(XWindowAttributesData.AWT_DECOR_TITLE)) {
651                menubarY += BUTTON_H;
652            }
653            try {
654                ng.translate(menubarX, menubarY);
655                peer.print(ng);
656            } finally {
657                ng.dispose();
658            }
659        }
660    }
661
662    public void setBoundsPrivate(int x, int y, int width, int height) {
663        setBounds(x, y, width, height, SET_BOUNDS);
664    }
665
666    public Rectangle getBoundsPrivate() {
667        return getBounds();
668    }
669
670    public void emulateActivation(boolean doActivate) {
671        if (doActivate) {
672            handleWindowFocusIn(0);
673        } else {
674            handleWindowFocusOut(null, 0);
675        }
676    }
677}
678