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