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 
XFramePeer(Frame target)53     XFramePeer(Frame target) {
54         super(target);
55     }
56 
XFramePeer(XCreateWindowParams params)57     XFramePeer(XCreateWindowParams params) {
58         super(params);
59     }
60 
preInit(XCreateWindowParams params)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 
postInit(XCreateWindowParams params)85     void postInit(XCreateWindowParams params) {
86         super.postInit(params);
87         setupState(true);
88     }
89 
90     @Override
isTargetUndecorated()91     boolean isTargetUndecorated() {
92         if (undecorated != null) {
93             return undecorated.booleanValue();
94         } else {
95             return ((Frame)target).isUndecorated();
96         }
97     }
98 
setupState(boolean onInit)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")
setMenuBar(MenuBar mb)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 
getMenubarPeer()141     XMenuBarPeer getMenubarPeer() {
142         return menubarPeer;
143     }
144 
getMenuBarHeight()145     int getMenuBarHeight() {
146         if (menubarPeer != null) {
147             return menubarPeer.getDesiredHeight();
148         } else {
149             return MENUBAR_HEIGHT_IF_NO_MENUBAR;
150         }
151     }
152 
updateChildrenSizes()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      */
reshapeMenubarPeer()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 
setMaximizedBounds(Rectangle b)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 
getState()242     public int getState() {
243         synchronized(getStateLock()) {
244             return state;
245         }
246     }
247 
setState(int newState)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 
changeState(int newState)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 
setExtendedState(int newState)298     void setExtendedState(int newState) {
299         XWM.getWM().setExtendedState(this, newState);
300     }
301 
handlePropertyNotify(XEvent xev)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         // RepaintManager does not repaint iconified windows. Window needs to be
346         // repainted explicitly, when it is deiconified.
347         if (((changed & Frame.ICONIFIED) != 0) &&
348             ((state & Frame.ICONIFIED) == 0)) {
349             repaint();
350         }
351     }
352 
353     // NOTE: This method may be called by privileged threads.
354     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
handleStateChange(int oldState, int newState)355     public void handleStateChange(int oldState, int newState) {
356         super.handleStateChange(oldState, newState);
357         for (ToplevelStateListener topLevelListenerTmp : toplevelStateListeners) {
358             topLevelListenerTmp.stateChangedJava(oldState, newState);
359         }
360     }
361 
setVisible(boolean vis)362     public void setVisible(boolean vis) {
363         if (vis) {
364             setupState(false);
365         } else {
366             if ((state & Frame.MAXIMIZED_BOTH) != 0) {
367                 XWM.getWM().setExtendedState(this, state & ~Frame.MAXIMIZED_BOTH);
368             }
369         }
370         super.setVisible(vis);
371         if (vis && maxBounds != null) {
372             setMaximizedBounds(maxBounds);
373         }
374     }
375 
setInitialState(int wm_state)376     void setInitialState(int wm_state) {
377         XToolkit.awtLock();
378         try {
379             XWMHints hints = getWMHints();
380             hints.set_flags((int)XUtilConstants.StateHint | hints.get_flags());
381             hints.set_initial_state(wm_state);
382             if (stateLog.isLoggable(PlatformLogger.Level.FINE)) {
383                 stateLog.fine("Setting initial WM state on " + this + " to " + wm_state);
384             }
385             XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData);
386         }
387         finally {
388             XToolkit.awtUnlock();
389         }
390     }
391 
dispose()392     public void dispose() {
393         if (menubarPeer != null) {
394             menubarPeer.dispose();
395         }
396         super.dispose();
397     }
398 
isMaximized()399     boolean isMaximized() {
400         return (state & (Frame.MAXIMIZED_VERT  | Frame.MAXIMIZED_HORIZ)) != 0;
401     }
402 
403 
404 
405 
406     static final int CROSSHAIR_INSET = 5;
407 
408     static final int BUTTON_Y = CROSSHAIR_INSET + 1;
409     static final int BUTTON_W = 17;
410     static final int BUTTON_H = 17;
411 
412     static final int SYS_MENU_X = CROSSHAIR_INSET + 1;
413     static final int SYS_MENU_CONTAINED_X = SYS_MENU_X + 5;
414     static final int SYS_MENU_CONTAINED_Y = BUTTON_Y + 7;
415     static final int SYS_MENU_CONTAINED_W = 8;
416     static final int SYS_MENU_CONTAINED_H = 3;
417 
418     static final int MAXIMIZE_X_DIFF = CROSSHAIR_INSET + BUTTON_W;
419     static final int MAXIMIZE_CONTAINED_X_DIFF = MAXIMIZE_X_DIFF - 5;
420     static final int MAXIMIZE_CONTAINED_Y = BUTTON_Y + 5;
421     static final int MAXIMIZE_CONTAINED_W = 8;
422     static final int MAXIMIZE_CONTAINED_H = 8;
423 
424     static final int MINIMIZE_X_DIFF = MAXIMIZE_X_DIFF + BUTTON_W;
425     static final int MINIMIZE_CONTAINED_X_DIFF = MINIMIZE_X_DIFF - 7;
426     static final int MINIMIZE_CONTAINED_Y = BUTTON_Y + 7;
427     static final int MINIMIZE_CONTAINED_W = 3;
428     static final int MINIMIZE_CONTAINED_H = 3;
429 
430     static final int TITLE_X = SYS_MENU_X + BUTTON_W;
431     static final int TITLE_W_DIFF = BUTTON_W * 3 + CROSSHAIR_INSET * 2 - 1;
432     static final int TITLE_MID_Y = BUTTON_Y + (BUTTON_H / 2);
433 
434     static final int MENUBAR_X = CROSSHAIR_INSET + 1;
435     static final int MENUBAR_Y = BUTTON_Y + BUTTON_H;
436 
437     static final int HORIZ_RESIZE_INSET = CROSSHAIR_INSET + BUTTON_H;
438     static final int VERT_RESIZE_INSET = CROSSHAIR_INSET + BUTTON_W;
439 
440 
441     /*
442      * Print the native component by rendering the Motif look ourselves.
443      * We also explicitly print the MenuBar since a MenuBar isn't a subclass
444      * of Component (and thus it has no "print" method which gets called by
445      * default).
446      */
print(Graphics g)447     public void print(Graphics g) {
448         super.print(g);
449 
450         Frame f = (Frame)target;
451         Insets finsets = f.getInsets();
452         Dimension fsize = f.getSize();
453 
454         Color bg = f.getBackground();
455         Color fg = f.getForeground();
456         Color highlight = bg.brighter();
457         Color shadow = bg.darker();
458 
459         // Well, we could query for the currently running window manager
460         // and base the look on that, or we could just always do dtwm.
461         // aim, tball, and levenson all agree we'll just do dtwm.
462 
463         if (hasDecorations(XWindowAttributesData.AWT_DECOR_BORDER)) {
464 
465             // top outer -- because we'll most likely be drawing on white paper,
466             // for aesthetic reasons, don't make any part of the outer border
467             // pure white
468             if (highlight.equals(Color.white)) {
469                 g.setColor(new Color(230, 230, 230));
470             }
471             else {
472                 g.setColor(highlight);
473             }
474             g.drawLine(0, 0, fsize.width, 0);
475             g.drawLine(0, 1, fsize.width - 1, 1);
476 
477             // left outer
478             // if (highlight.equals(Color.white)) {
479             //     g.setColor(new Color(230, 230, 230));
480             // }
481             // else {
482             //     g.setColor(highlight);
483             // }
484             g.drawLine(0, 0, 0, fsize.height);
485             g.drawLine(1, 0, 1, fsize.height - 1);
486 
487             // bottom cross-hair
488             g.setColor(highlight);
489             g.drawLine(CROSSHAIR_INSET + 1, fsize.height - CROSSHAIR_INSET,
490                        fsize.width - CROSSHAIR_INSET,
491                        fsize.height - CROSSHAIR_INSET);
492 
493             // right cross-hair
494             // g.setColor(highlight);
495             g.drawLine(fsize.width - CROSSHAIR_INSET, CROSSHAIR_INSET + 1,
496                        fsize.width - CROSSHAIR_INSET,
497                        fsize.height - CROSSHAIR_INSET);
498 
499             // bottom outer
500             g.setColor(shadow);
501             g.drawLine(1, fsize.height, fsize.width, fsize.height);
502             g.drawLine(2, fsize.height - 1, fsize.width, fsize.height - 1);
503 
504             // right outer
505             // g.setColor(shadow);
506             g.drawLine(fsize.width, 1, fsize.width, fsize.height);
507             g.drawLine(fsize.width - 1, 2, fsize.width - 1, fsize.height);
508 
509             // top cross-hair
510             // g.setColor(shadow);
511             g.drawLine(CROSSHAIR_INSET, CROSSHAIR_INSET,
512                        fsize.width - CROSSHAIR_INSET, CROSSHAIR_INSET);
513 
514             // left cross-hair
515             // g.setColor(shadow);
516             g.drawLine(CROSSHAIR_INSET, CROSSHAIR_INSET, CROSSHAIR_INSET,
517                        fsize.height - CROSSHAIR_INSET);
518         }
519 
520         if (hasDecorations(XWindowAttributesData.AWT_DECOR_TITLE)) {
521 
522             if (hasDecorations(XWindowAttributesData.AWT_DECOR_MENU)) {
523 
524                 // system menu
525                 g.setColor(bg);
526                 g.fill3DRect(SYS_MENU_X, BUTTON_Y, BUTTON_W, BUTTON_H, true);
527                 g.fill3DRect(SYS_MENU_CONTAINED_X, SYS_MENU_CONTAINED_Y,
528                              SYS_MENU_CONTAINED_W, SYS_MENU_CONTAINED_H, true);
529             }
530 
531             // title bar
532             // g.setColor(bg);
533             g.fill3DRect(TITLE_X, BUTTON_Y, fsize.width - TITLE_W_DIFF, BUTTON_H,
534                          true);
535 
536             if (hasDecorations(XWindowAttributesData.AWT_DECOR_MINIMIZE)) {
537 
538                 // minimize button
539                 // g.setColor(bg);
540                 g.fill3DRect(fsize.width - MINIMIZE_X_DIFF, BUTTON_Y, BUTTON_W,
541                              BUTTON_H, true);
542                 g.fill3DRect(fsize.width - MINIMIZE_CONTAINED_X_DIFF,
543                              MINIMIZE_CONTAINED_Y, MINIMIZE_CONTAINED_W,
544                              MINIMIZE_CONTAINED_H, true);
545             }
546 
547             if (hasDecorations(XWindowAttributesData.AWT_DECOR_MAXIMIZE)) {
548 
549                 // maximize button
550                 // g.setColor(bg);
551                 g.fill3DRect(fsize.width - MAXIMIZE_X_DIFF, BUTTON_Y, BUTTON_W,
552                              BUTTON_H, true);
553                 g.fill3DRect(fsize.width - MAXIMIZE_CONTAINED_X_DIFF,
554                              MAXIMIZE_CONTAINED_Y, MAXIMIZE_CONTAINED_W,
555                              MAXIMIZE_CONTAINED_H, true);
556             }
557 
558             // title bar text
559             g.setColor(fg);
560             Font sysfont = new Font(Font.SANS_SERIF, Font.PLAIN, 10);
561             g.setFont(sysfont);
562             FontMetrics sysfm = g.getFontMetrics();
563             String ftitle = f.getTitle();
564             g.drawString(ftitle,
565                          ((TITLE_X + TITLE_X + fsize.width - TITLE_W_DIFF) / 2) -
566                          (sysfm.stringWidth(ftitle) / 2),
567                          TITLE_MID_Y + sysfm.getMaxDescent());
568         }
569 
570         if (f.isResizable() &&
571             hasDecorations(XWindowAttributesData.AWT_DECOR_RESIZEH)) {
572 
573             // add resize cross hairs
574 
575             // upper-left horiz (shadow)
576             g.setColor(shadow);
577             g.drawLine(1, HORIZ_RESIZE_INSET, CROSSHAIR_INSET,
578                        HORIZ_RESIZE_INSET);
579             // upper-left vert (shadow)
580             // g.setColor(shadow);
581             g.drawLine(VERT_RESIZE_INSET, 1, VERT_RESIZE_INSET, CROSSHAIR_INSET);
582             // upper-right horiz (shadow)
583             // g.setColor(shadow);
584             g.drawLine(fsize.width - CROSSHAIR_INSET + 1, HORIZ_RESIZE_INSET,
585                        fsize.width, HORIZ_RESIZE_INSET);
586             // upper-right vert (shadow)
587             // g.setColor(shadow);
588             g.drawLine(fsize.width - VERT_RESIZE_INSET - 1, 2,
589                        fsize.width - VERT_RESIZE_INSET - 1, CROSSHAIR_INSET + 1);
590             // lower-left horiz (shadow)
591             // g.setColor(shadow);
592             g.drawLine(1, fsize.height - HORIZ_RESIZE_INSET - 1,
593                        CROSSHAIR_INSET, fsize.height - HORIZ_RESIZE_INSET - 1);
594             // lower-left vert (shadow)
595             // g.setColor(shadow);
596             g.drawLine(VERT_RESIZE_INSET, fsize.height - CROSSHAIR_INSET + 1,
597                        VERT_RESIZE_INSET, fsize.height);
598             // lower-right horiz (shadow)
599             // g.setColor(shadow);
600             g.drawLine(fsize.width - CROSSHAIR_INSET + 1,
601                        fsize.height - HORIZ_RESIZE_INSET - 1, fsize.width,
602                        fsize.height - HORIZ_RESIZE_INSET - 1);
603             // lower-right vert (shadow)
604             // g.setColor(shadow);
605             g.drawLine(fsize.width - VERT_RESIZE_INSET - 1,
606                        fsize.height - CROSSHAIR_INSET + 1,
607                        fsize.width - VERT_RESIZE_INSET - 1, fsize.height);
608 
609             // upper-left horiz (highlight)
610             g.setColor(highlight);
611             g.drawLine(2, HORIZ_RESIZE_INSET + 1, CROSSHAIR_INSET,
612                        HORIZ_RESIZE_INSET + 1);
613             // upper-left vert (highlight)
614             // g.setColor(highlight);
615             g.drawLine(VERT_RESIZE_INSET + 1, 2, VERT_RESIZE_INSET + 1,
616                        CROSSHAIR_INSET);
617             // upper-right horiz (highlight)
618             // g.setColor(highlight);
619             g.drawLine(fsize.width - CROSSHAIR_INSET + 1,
620                        HORIZ_RESIZE_INSET + 1, fsize.width - 1,
621                        HORIZ_RESIZE_INSET + 1);
622             // upper-right vert (highlight)
623             // g.setColor(highlight);
624             g.drawLine(fsize.width - VERT_RESIZE_INSET, 2,
625                        fsize.width - VERT_RESIZE_INSET, CROSSHAIR_INSET);
626             // lower-left horiz (highlight)
627             // g.setColor(highlight);
628             g.drawLine(2, fsize.height - HORIZ_RESIZE_INSET, CROSSHAIR_INSET,
629                        fsize.height - HORIZ_RESIZE_INSET);
630             // lower-left vert (highlight)
631             // g.setColor(highlight);
632             g.drawLine(VERT_RESIZE_INSET + 1,
633                        fsize.height - CROSSHAIR_INSET + 1,
634                        VERT_RESIZE_INSET + 1, fsize.height - 1);
635             // lower-right horiz (highlight)
636             // g.setColor(highlight);
637             g.drawLine(fsize.width - CROSSHAIR_INSET + 1,
638                        fsize.height - HORIZ_RESIZE_INSET, fsize.width - 1,
639                        fsize.height - HORIZ_RESIZE_INSET);
640             // lower-right vert (highlight)
641             // g.setColor(highlight);
642             g.drawLine(fsize.width - VERT_RESIZE_INSET,
643                        fsize.height - CROSSHAIR_INSET + 1,
644                        fsize.width - VERT_RESIZE_INSET, fsize.height - 1);
645         }
646 
647         XMenuBarPeer peer = menubarPeer;
648         if (peer != null) {
649             Insets insets = getInsets();
650             Graphics ng = g.create();
651             int menubarX = 0;
652             int menubarY = 0;
653             if (hasDecorations(XWindowAttributesData.AWT_DECOR_BORDER)) {
654                 menubarX += CROSSHAIR_INSET + 1;
655                     menubarY += CROSSHAIR_INSET + 1;
656             }
657             if (hasDecorations(XWindowAttributesData.AWT_DECOR_TITLE)) {
658                 menubarY += BUTTON_H;
659             }
660             try {
661                 ng.translate(menubarX, menubarY);
662                 peer.print(ng);
663             } finally {
664                 ng.dispose();
665             }
666         }
667     }
668 
setBoundsPrivate(int x, int y, int width, int height)669     public void setBoundsPrivate(int x, int y, int width, int height) {
670         setBounds(x, y, width, height, SET_BOUNDS);
671     }
672 
getBoundsPrivate()673     public Rectangle getBoundsPrivate() {
674         return getBounds();
675     }
676 
emulateActivation(boolean doActivate)677     public void emulateActivation(boolean doActivate) {
678         if (doActivate) {
679             handleWindowFocusIn(0);
680         } else {
681             handleWindowFocusOut(null, 0);
682         }
683     }
684 }
685