1 /*
   2  * Copyright 2002-2008 Sun Microsystems, Inc.  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.  Sun designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22  * CA 95054 USA or visit www.sun.com if you need additional information or
  23  * have any questions.
  24  */
  25 package sun.awt.X11;
  26 
  27 import java.awt.AWTEvent;
  28 import java.awt.AWTException;
  29 import java.awt.BufferCapabilities;
  30 import java.awt.Color;
  31 import java.awt.Component;
  32 import java.awt.Container;
  33 import java.awt.Cursor;
  34 import java.awt.Dimension;
  35 import java.awt.Font;
  36 import java.awt.FontMetrics;
  37 import java.awt.Graphics;
  38 import java.awt.GraphicsConfiguration;
  39 import java.awt.Image;
  40 import java.awt.Insets;
  41 import java.awt.KeyboardFocusManager;
  42 import java.awt.Rectangle;
  43 import java.awt.SystemColor;
  44 import java.awt.Toolkit;
  45 import java.awt.Window;
  46 import java.awt.dnd.DropTarget;
  47 import java.awt.dnd.peer.DropTargetPeer;
  48 import java.awt.event.FocusEvent;
  49 import java.awt.event.InputEvent;
  50 import java.awt.event.InputMethodEvent;
  51 import java.awt.event.KeyEvent;
  52 import java.awt.event.MouseEvent;
  53 import java.awt.event.MouseWheelEvent;
  54 import java.awt.event.PaintEvent;
  55 import java.awt.event.WindowEvent;
  56 import java.awt.event.InvocationEvent;
  57 import java.awt.image.ImageObserver;
  58 import java.awt.image.ImageProducer;
  59 import java.awt.image.VolatileImage;
  60 import java.awt.peer.ComponentPeer;
  61 import java.awt.peer.ContainerPeer;
  62 import java.awt.peer.LightweightPeer;
  63 import java.lang.reflect.*;
  64 import java.security.*;
  65 import java.util.Collection;
  66 import java.util.HashSet;
  67 import java.util.Set;
  68 import java.util.Vector;
  69 import java.util.logging.*;
  70 import sun.awt.*;
  71 import sun.awt.event.IgnorePaintEvent;
  72 import sun.awt.image.SunVolatileImage;
  73 import sun.awt.image.ToolkitImage;
  74 import sun.java2d.BackBufferCapsProvider;
  75 import sun.java2d.pipe.Region;
  76 
  77 public class XComponentPeer extends XWindow implements ComponentPeer, DropTargetPeer,
  78     BackBufferCapsProvider
  79 {
  80     private static final Logger log = Logger.getLogger("sun.awt.X11.XComponentPeer");
  81     private static final Logger buffersLog = Logger.getLogger("sun.awt.X11.XComponentPeer.multibuffer");
  82     private static final Logger focusLog = Logger.getLogger("sun.awt.X11.focus.XComponentPeer");
  83     private static final Logger fontLog = Logger.getLogger("sun.awt.X11.font.XComponentPeer");
  84     private static final Logger enableLog = Logger.getLogger("sun.awt.X11.enable.XComponentPeer");
  85     private static final Logger shapeLog = Logger.getLogger("sun.awt.X11.shape.XComponentPeer");
  86 
  87     boolean paintPending = false;
  88     boolean isLayouting = false;
  89     boolean enabled;
  90 
  91     // Actually used only by XDecoratedPeer
  92     protected int boundsOperation;
  93 
  94     Color foreground;
  95     Color background;
  96 
  97     // Colors calculated as on Motif using MotifColorUtilties.
  98     // If you use these, call updateMotifColors() in the peer's Constructor and
  99     // setBackground().  Examples are XCheckboxPeer and XButtonPeer.
 100     Color darkShadow;
 101     Color lightShadow;
 102     Color selectColor;
 103 
 104     Font font;
 105     private long backBuffer = 0;
 106     private VolatileImage xBackBuffer = null;
 107 
 108     static Color[] systemColors;
 109 
 110     XComponentPeer() {
 111     }
 112 
 113     XComponentPeer (XCreateWindowParams params) {
 114         super(params);
 115     }
 116 
 117     XComponentPeer(Component target, long parentWindow, Rectangle bounds) {
 118         super(target, parentWindow, bounds);
 119     }
 120 
 121     /**
 122      * Standard peer constructor, with corresponding Component
 123      */
 124     XComponentPeer(Component target) {
 125         super(target);
 126     }
 127 
 128 
 129     void preInit(XCreateWindowParams params) {
 130         super.preInit(params);
 131         boundsOperation = DEFAULT_OPERATION;
 132     }
 133     void postInit(XCreateWindowParams params) {
 134         super.postInit(params);
 135         Color c;
 136         Font  f;
 137         Cursor cursor;
 138 
 139         pSetCursor(target.getCursor());
 140 
 141         foreground = target.getForeground();
 142         background = target.getBackground();
 143         font = target.getFont();
 144 
 145         if (isInitialReshape()) {
 146             Rectangle r = target.getBounds();
 147             reshape(r.x, r.y, r.width, r.height);
 148         }
 149 
 150         enabled = target.isEnabled();
 151 
 152         // If any of our heavyweight ancestors are disable, we should be too
 153         // See 6176875 for more information
 154         Component comp = target;
 155         while( !(comp == null || comp instanceof Window) ) {
 156             comp = comp.getParent();
 157             if( comp != null && !comp.isEnabled() && !comp.isLightweight() ){
 158                 setEnabled(false);
 159                 break;
 160             }
 161         }
 162         enableLog.log(Level.FINE, "Initial enable state: {0}", new Object[] {Boolean.valueOf(enabled)});
 163 
 164         if (target.isVisible()) {
 165             setVisible(true);
 166         }
 167     }
 168 
 169     protected boolean isInitialReshape() {
 170         return true;
 171     }
 172 
 173     public void reparent(ContainerPeer newNativeParent) {
 174         XComponentPeer newPeer = (XComponentPeer)newNativeParent;
 175         XToolkit.awtLock();
 176         try {
 177             XlibWrapper.XReparentWindow(XToolkit.getDisplay(), getWindow(), newPeer.getContentWindow(), x, y);
 178             parentWindow = newPeer;
 179         } finally {
 180             XToolkit.awtUnlock();
 181         }
 182     }
 183     public boolean isReparentSupported() {
 184         return System.getProperty("sun.awt.X11.XComponentPeer.reparentNotSupported", "false").equals("false");
 185     }
 186 
 187     public boolean isObscured() {
 188         Container container  = (target instanceof Container) ?
 189             (Container)target : target.getParent();
 190 
 191         if (container == null) {
 192             return true;
 193         }
 194 
 195         Container parent;
 196         while ((parent = container.getParent()) != null) {
 197             container = parent;
 198         }
 199 
 200         if (container instanceof Window) {
 201             XWindowPeer wpeer = (XWindowPeer)(container.getPeer());
 202             if (wpeer != null) {
 203                 return (wpeer.winAttr.visibilityState !=
 204                         wpeer.winAttr.AWT_UNOBSCURED);
 205             }
 206         }
 207         return true;
 208     }
 209 
 210     public boolean canDetermineObscurity() {
 211         return true;
 212     }
 213 
 214     static XComponentPeer getNativeContainer(Component comp) {
 215         if (comp == null) {
 216             return null;
 217         }
 218 
 219         synchronized(comp.getTreeLock()) {
 220             while (comp != null && (ComponentAccessor.getPeer(comp) instanceof LightweightPeer)) {
 221                 comp = ComponentAccessor.getParent_NoClientCode(comp);
 222             }
 223 
 224             if (comp != null) {
 225                 ComponentPeer peer = ComponentAccessor.getPeer(comp);
 226                 if (peer != null && peer instanceof XComponentPeer) {
 227                     return (XComponentPeer)peer;
 228                 }
 229             }
 230         }
 231 
 232         return null;
 233     }
 234 
 235     /*************************************************
 236      * FOCUS STUFF
 237      *************************************************/
 238 
 239     /**
 240      * Keeps the track of focused state of the _NATIVE_ window
 241      */
 242     boolean bHasFocus = false;
 243 
 244     /**
 245      * Descendants should use this method to determine whether or not native window
 246      * has focus.
 247      */
 248     final public boolean hasFocus() {
 249         return bHasFocus;
 250     }
 251 
 252     /**
 253      * Called when component receives focus
 254      */
 255     public void focusGained(FocusEvent e) {
 256         focusLog.log(Level.FINE, "{0}", new Object[] {e});
 257         bHasFocus = true;
 258     }
 259 
 260     /**
 261      * Called when component loses focus
 262      */
 263     public void focusLost(FocusEvent e) {
 264         focusLog.log(Level.FINE, "{0}", new Object[] {e});
 265         bHasFocus = false;
 266     }
 267 
 268     public boolean isFocusable() {
 269         /* should be implemented by other sub-classes */
 270         return false;
 271     }
 272 
 273     private static Class seClass;
 274     private static Constructor seCtor;
 275 
 276     final static AWTEvent wrapInSequenced(AWTEvent event) {
 277         try {
 278             if (seClass == null) {
 279                 seClass = Class.forName("java.awt.SequencedEvent");
 280             }
 281 
 282             if (seCtor == null) {
 283                 seCtor = (Constructor) AccessController.doPrivileged(new PrivilegedExceptionAction() {
 284                         public Object run() throws Exception {
 285                             Constructor ctor = seClass.getConstructor(new Class[] { AWTEvent.class });
 286                             ctor.setAccessible(true);
 287                             return ctor;
 288                         }
 289                     });
 290             }
 291 
 292             return (AWTEvent) seCtor.newInstance(new Object[] { event });
 293         }
 294         catch (ClassNotFoundException e) {
 295             throw new NoClassDefFoundError("java.awt.SequencedEvent.");
 296         }
 297         catch (PrivilegedActionException ex) {
 298             throw new NoClassDefFoundError("java.awt.SequencedEvent.");
 299         }
 300         catch (InstantiationException e) {
 301             assert false;
 302         }
 303         catch (IllegalAccessException e) {
 304             assert false;
 305         }
 306         catch (InvocationTargetException e) {
 307             assert false;
 308         }
 309 
 310         return null;
 311     }
 312 
 313     // TODO: consider moving it to KeyboardFocusManagerPeerImpl
 314     final public boolean requestFocus(Component lightweightChild, boolean temporary,
 315                                       boolean focusedWindowChangeAllowed, long time,
 316                                       CausedFocusEvent.Cause cause)
 317     {
 318         if (XKeyboardFocusManagerPeer.
 319             processSynchronousLightweightTransfer(target, lightweightChild, temporary,
 320                                                   focusedWindowChangeAllowed, time))
 321         {
 322             return true;
 323         }
 324 
 325         int result = XKeyboardFocusManagerPeer.
 326             shouldNativelyFocusHeavyweight(target, lightweightChild,
 327                                            temporary, focusedWindowChangeAllowed,
 328                                            time, cause);
 329 
 330         switch (result) {
 331           case XKeyboardFocusManagerPeer.SNFH_FAILURE:
 332               return false;
 333           case XKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED:
 334               // Currently we just generate focus events like we deal with lightweight instead of calling
 335               // XSetInputFocus on native window
 336               if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Proceeding with request to " +
 337                   lightweightChild + " in " + target);
 338               /**
 339                * The problems with requests in non-focused window arise because shouldNativelyFocusHeavyweight
 340                * checks that native window is focused while appropriate WINDOW_GAINED_FOCUS has not yet
 341                * been processed - it is in EventQueue. Thus, SNFH allows native request and stores request record
 342                * in requests list - and it breaks our requests sequence as first record on WGF should be the last
 343                * focus owner which had focus before WLF. So, we should not add request record for such requests
 344                * but store this component in mostRecent - and return true as before for compatibility.
 345                */
 346               Window parentWindow = SunToolkit.getContainingWindow(target);
 347               if (parentWindow == null) {
 348                   return rejectFocusRequestHelper("WARNING: Parent window is null");
 349               }
 350               XWindowPeer wpeer = (XWindowPeer)parentWindow.getPeer();
 351               if (wpeer == null) {
 352                   return rejectFocusRequestHelper("WARNING: Parent window's peer is null");
 353               }
 354               /*
 355                * Passing null 'actualFocusedWindow' as we don't want to restore focus on it
 356                * when a component inside a Frame is requesting focus.
 357                * See 6314575 for details.
 358                */
 359               boolean res = wpeer.requestWindowFocus(null);
 360 
 361               if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Requested window focus: " + res);
 362               // If parent window can be made focused and has been made focused(synchronously)
 363               // then we can proceed with children, otherwise we retreat.
 364               if (!(res && parentWindow.isFocused())) {
 365                   return rejectFocusRequestHelper("Waiting for asynchronous processing of the request");
 366               }
 367               return XKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
 368                                                             (Component)target,
 369                                                             temporary,
 370                                                             focusedWindowChangeAllowed,
 371                                                             time, cause);
 372               // Motif compatibility code
 373           case XKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
 374               // Either lightweight or excessive request - all events are generated.
 375               return true;
 376         }
 377         return false;
 378     }
 379 
 380     private boolean rejectFocusRequestHelper(String logMsg) {
 381         if (focusLog.isLoggable(Level.FINER)) focusLog.finer(logMsg);
 382         XKeyboardFocusManagerPeer.removeLastFocusRequest(target);
 383         return false;
 384     }
 385 
 386     void handleJavaFocusEvent(AWTEvent e) {
 387         if (focusLog.isLoggable(Level.FINER)) focusLog.finer(e.toString());
 388         if (e.getID() == FocusEvent.FOCUS_GAINED) {
 389             focusGained((FocusEvent)e);
 390         } else {
 391             focusLost((FocusEvent)e);
 392         }
 393     }
 394 
 395     void handleJavaWindowFocusEvent(AWTEvent e) {
 396     }
 397 
 398     /*************************************************
 399      * END OF FOCUS STUFF
 400      *************************************************/
 401 
 402 
 403 
 404     public void setVisible(boolean b) {
 405         xSetVisible(b);
 406     }
 407 
 408     public void hide() {
 409         setVisible(false);
 410     }
 411 
 412 
 413     /**
 414      * @see java.awt.peer.ComponentPeer
 415      */
 416     public void setEnabled(boolean value) {
 417         enableLog.log(Level.FINE, "{0}ing {1}", new Object[] {(value?"Enabl":"Disabl"), this});
 418         boolean repaintNeeded = (enabled != value);
 419         enabled = value;
 420         if (target instanceof Container) {
 421             Component list[] = ((Container)target).getComponents();
 422             for (int i = 0; i < list.length; ++i) {
 423                 boolean childEnabled = list[i].isEnabled();
 424                 ComponentPeer p = list[i].getPeer();
 425                 if ( p != null ) {
 426                     p.setEnabled(value && childEnabled);
 427                 }
 428             }
 429         }
 430         if (repaintNeeded) {
 431             repaint();
 432         }
 433     }
 434 
 435     //
 436     // public so aw/Window can call it
 437     //
 438     public boolean isEnabled() {
 439         return enabled;
 440     }
 441 
 442 
 443 
 444     public void enable() {
 445         setEnabled(true);
 446     }
 447 
 448     public void disable() {
 449         setEnabled(false);
 450     }
 451 
 452     public void paint(Graphics g) {
 453     }
 454     public void repaint(long tm, int x, int y, int width, int height) {
 455         repaint();
 456     }
 457 
 458 
 459     public Graphics getGraphics() {
 460         return getGraphics(surfaceData, getPeerForeground(), getPeerBackground(), getPeerFont());
 461     }
 462 
 463 
 464 
 465     public void print(Graphics g) {
 466         // clear rect here to emulate X clears rect before Expose
 467         g.setColor(target.getBackground());
 468         g.fillRect(0, 0, target.getWidth(), target.getHeight());
 469         g.setColor(target.getForeground());
 470         // paint peer
 471         paint(g);
 472         // allow target to change the picture
 473         target.print(g);
 474     }
 475 
 476     public void setBounds(int x, int y, int width, int height, int op) {
 477         this.x = x;
 478         this.y = y;
 479         this.width = width;
 480         this.height = height;
 481         xSetBounds(x,y,width,height);
 482         validateSurface();
 483         layout();
 484     }
 485 
 486     public void reshape(int x, int y, int width, int height) {
 487         setBounds(x, y, width, height, SET_BOUNDS);
 488     }
 489 
 490     public void coalescePaintEvent(PaintEvent e) {
 491         Rectangle r = e.getUpdateRect();
 492         if (!(e instanceof IgnorePaintEvent)) {
 493             paintArea.add(r, e.getID());
 494         }
 495         if (true) {
 496             switch(e.getID()) {
 497               case PaintEvent.UPDATE:
 498                   log.finer("XCP coalescePaintEvent : UPDATE : add : x = " +
 499                             r.x + ", y = " + r.y + ", width = " + r.width + ",height = " + r.height);
 500                   return;
 501               case PaintEvent.PAINT:
 502                   log.finer("XCP coalescePaintEvent : PAINT : add : x = " +
 503                             r.x + ", y = " + r.y + ", width = " + r.width + ",height = " + r.height);
 504                   return;
 505             }
 506         }
 507     }
 508 
 509     XWindowPeer getParentTopLevel() {
 510         Container parent = (target instanceof Container) ? ((Container)target) : (ComponentAccessor.getParent_NoClientCode(target));
 511         // Search for parent window
 512         while (parent != null && !(parent instanceof Window)) {
 513             parent = ComponentAccessor.getParent_NoClientCode(parent);
 514         }
 515         if (parent != null) {
 516             return (XWindowPeer)ComponentAccessor.getPeer(parent);
 517         } else {
 518             return null;
 519         }
 520     }
 521 
 522     /* This method is intended to be over-ridden by peers to perform user interaction */
 523     void handleJavaMouseEvent(MouseEvent e) {
 524         switch (e.getID()) {
 525           case MouseEvent.MOUSE_PRESSED:
 526               if (target == e.getSource() &&
 527                   !target.isFocusOwner() &&
 528                   XKeyboardFocusManagerPeer.shouldFocusOnClick(target))
 529               {
 530                   XWindowPeer parentXWindow = getParentTopLevel();
 531                   Window parentWindow = ((Window)parentXWindow.getTarget());
 532                   // Simple windows are non-focusable in X terms but focusable in Java terms.
 533                   // As X-non-focusable they don't receive any focus events - we should generate them
 534                   // by ourselfves.
 535 //                   if (parentXWindow.isFocusableWindow() /*&& parentXWindow.isSimpleWindow()*/ &&
 536 //                       !(getCurrentNativeFocusedWindow() == parentWindow))
 537 //                   {
 538 //                       setCurrentNativeFocusedWindow(parentWindow);
 539 //                       WindowEvent wfg = new WindowEvent(parentWindow, WindowEvent.WINDOW_GAINED_FOCUS);
 540 //                       parentWindow.dispatchEvent(wfg);
 541 //                   }
 542                   XKeyboardFocusManagerPeer.requestFocusFor(target, CausedFocusEvent.Cause.MOUSE_EVENT);
 543               }
 544               break;
 545         }
 546     }
 547 
 548     /* This method is intended to be over-ridden by peers to perform user interaction */
 549     void handleJavaKeyEvent(KeyEvent e) {
 550     }
 551 
 552     /* This method is intended to be over-ridden by peers to perform user interaction */
 553     void handleJavaMouseWheelEvent(MouseWheelEvent e) {
 554     }
 555 
 556 
 557     /* This method is intended to be over-ridden by peers to perform user interaction */
 558     void handleJavaInputMethodEvent(InputMethodEvent e) {
 559     }
 560 
 561     void handleF10JavaKeyEvent(KeyEvent e) {
 562         if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_F10) {
 563             XWindowPeer winPeer = this.getToplevelXWindow();
 564             if (winPeer instanceof XFramePeer) {
 565                 XMenuBarPeer mPeer = ((XFramePeer)winPeer).getMenubarPeer();
 566                 if (mPeer != null) {
 567                     mPeer.handleF10KeyPress(e);
 568                 }
 569             }
 570         }
 571     }
 572 
 573     public void handleEvent(java.awt.AWTEvent e) {
 574         if ((e instanceof InputEvent) && !((InputEvent)e).isConsumed() && target.isEnabled())  {
 575             if (e instanceof MouseEvent) {
 576                 if (e instanceof MouseWheelEvent) {
 577                     handleJavaMouseWheelEvent((MouseWheelEvent) e);
 578                 }
 579                 else
 580                     handleJavaMouseEvent((MouseEvent) e);
 581             }
 582             else if (e instanceof KeyEvent) {
 583                 handleF10JavaKeyEvent((KeyEvent)e);
 584                 handleJavaKeyEvent((KeyEvent)e);
 585             }
 586         }
 587         else if (e instanceof KeyEvent && !((InputEvent)e).isConsumed()) {
 588             // even if target is disabled.
 589             handleF10JavaKeyEvent((KeyEvent)e);
 590         }
 591         else if (e instanceof InputMethodEvent) {
 592             handleJavaInputMethodEvent((InputMethodEvent) e);
 593         }
 594 
 595         int id = e.getID();
 596 
 597         switch(id) {
 598           case PaintEvent.PAINT:
 599               // Got native painting
 600               paintPending = false;
 601               // Fallthrough to next statement
 602           case PaintEvent.UPDATE:
 603               // Skip all painting while layouting and all UPDATEs
 604               // while waiting for native paint
 605               if (!isLayouting && !paintPending) {
 606                   paintArea.paint(target,false);
 607               }
 608               return;
 609           case FocusEvent.FOCUS_LOST:
 610           case FocusEvent.FOCUS_GAINED:
 611               handleJavaFocusEvent(e);
 612               break;
 613           case WindowEvent.WINDOW_LOST_FOCUS:
 614           case WindowEvent.WINDOW_GAINED_FOCUS:
 615               handleJavaWindowFocusEvent(e);
 616               break;
 617           default:
 618               break;
 619         }
 620 
 621     }
 622 
 623     public void handleButtonPressRelease(XEvent xev) {
 624         /*
 625          * Fix for 6385277.
 626          * We request focus on simple Window by click in order
 627          * to make it behave like Frame/Dialog in this case and also to unify
 628          * the behaviour with what we have on MS Windows.
 629          * handleJavaMouseEvent() would be more suitable place to do this
 630          * but we want Swing to have this functionality also.
 631          */
 632         if (xev.get_type() == XConstants.ButtonPress) {
 633             final XWindowPeer parentXWindow = getParentTopLevel();
 634             Window parentWindow = (Window)parentXWindow.getTarget();
 635             if (parentXWindow.isFocusableWindow() && parentXWindow.isSimpleWindow() &&
 636                 XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow() != parentWindow)
 637             {
 638                 postEvent(new InvocationEvent(parentWindow, new  Runnable() {
 639                         public void run() {
 640                             // Request focus on the EDT of 'parentWindow' because
 641                             // XDecoratedPeer.requestWindowFocus() calls client code.
 642                             parentXWindow.requestXFocus();
 643                         }
 644                     }));
 645             }
 646         }
 647         super.handleButtonPressRelease(xev);
 648     }
 649 
 650     public Dimension getMinimumSize() {
 651         return target.getSize();
 652     }
 653 
 654     public Dimension getPreferredSize() {
 655         return getMinimumSize();
 656     }
 657 
 658     public void layout() {}
 659 
 660     public java.awt.Toolkit getToolkit() {
 661         return Toolkit.getDefaultToolkit();
 662     }
 663 
 664     void updateMotifColors(Color bg) {
 665         int red = bg.getRed();
 666         int green = bg.getGreen();
 667         int blue = bg.getBlue();
 668 
 669         darkShadow = new Color(MotifColorUtilities.calculateBottomShadowFromBackground(red,green,blue));
 670         lightShadow = new Color(MotifColorUtilities.calculateTopShadowFromBackground(red,green,blue));
 671         selectColor= new Color(MotifColorUtilities.calculateSelectFromBackground(red,green,blue));
 672     }
 673 
 674     /*
 675      * Draw a 3D rectangle using the Motif colors.
 676      * "Normal" rectangles have shadows on the bottom.
 677      * "Depressed" rectangles (such as pressed buttons) have shadows on the top,
 678      * in which case true should be passed for topShadow.
 679      */
 680     public void drawMotif3DRect(Graphics g,
 681                                           int x, int y, int width, int height,
 682                                           boolean topShadow) {
 683         g.setColor(topShadow ? darkShadow : lightShadow);
 684         g.drawLine(x, y, x+width, y);       // top
 685         g.drawLine(x, y+height, x, y);      // left
 686 
 687         g.setColor(topShadow ? lightShadow : darkShadow );
 688         g.drawLine(x+1, y+height, x+width, y+height); // bottom
 689         g.drawLine(x+width, y+height, x+width, y+1);  // right
 690     }
 691 
 692     public void setBackground(Color c) {
 693         if (log.isLoggable(Level.FINE)) log.fine("Set background to " + c);
 694         synchronized (getStateLock()) {
 695             background = c;
 696         }
 697         super.setBackground(c);
 698         repaint();
 699     }
 700 
 701     public void setForeground(Color c) {
 702         if (log.isLoggable(Level.FINE)) log.fine("Set foreground to " + c);
 703         synchronized (getStateLock()) {
 704             foreground = c;
 705         }
 706         repaint();
 707     }
 708 
 709     /**
 710      * Gets the font metrics for the specified font.
 711      * @param font the font for which font metrics is to be
 712      *      obtained
 713      * @return the font metrics for <code>font</code>
 714      * @see       #getFont
 715      * @see       #getPeer
 716      * @see       java.awt.peer.ComponentPeer#getFontMetrics(Font)
 717      * @see       Toolkit#getFontMetrics(Font)
 718      * @since     JDK1.0
 719      */
 720     public FontMetrics getFontMetrics(Font font) {
 721         if (fontLog.isLoggable(Level.FINE)) fontLog.fine("Getting font metrics for " + font);
 722         return sun.font.FontDesignMetrics.getMetrics(font);
 723     }
 724 
 725     public void setFont(Font f) {
 726         synchronized (getStateLock()) {
 727             if (f == null) {
 728                 f = XWindow.getDefaultFont();
 729             }
 730             font = f;
 731         }
 732         // as it stands currently we dont need to do layout or repaint since
 733         // layout is done in the Component upon setFont.
 734         //layout();
 735         // target.repaint();
 736         //repaint()?
 737     }
 738 
 739     public Font getFont() {
 740         return font;
 741     }
 742 
 743     public void updateCursorImmediately() {
 744         XGlobalCursorManager.getCursorManager().updateCursorImmediately();
 745     }
 746 
 747     public void pSetCursor(Cursor cursor) {
 748         XToolkit.awtLock();
 749         try {
 750             long xcursor = XGlobalCursorManager.getCursor(cursor);
 751 
 752             XSetWindowAttributes xwa = new XSetWindowAttributes();
 753             xwa.set_cursor(xcursor);
 754 
 755             long valuemask = XConstants.CWCursor;
 756 
 757             XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),getWindow(),valuemask,xwa.pData);
 758             XlibWrapper.XFlush(XToolkit.getDisplay());
 759             xwa.dispose();
 760         } finally {
 761             XToolkit.awtUnlock();
 762         }
 763     }
 764 
 765     public Image createImage(ImageProducer producer) {
 766         return new ToolkitImage(producer);
 767     }
 768 
 769     public Image createImage(int width, int height) {
 770         return graphicsConfig.createAcceleratedImage(target, width, height);
 771     }
 772 
 773     public VolatileImage createVolatileImage(int width, int height) {
 774         return new SunVolatileImage(target, width, height);
 775     }
 776 
 777     public boolean prepareImage(Image img, int w, int h, ImageObserver o) {
 778         return getToolkit().prepareImage(img, w, h, o);
 779     }
 780 
 781     public int checkImage(Image img, int w, int h, ImageObserver o) {
 782         return getToolkit().checkImage(img, w, h, o);
 783     }
 784 
 785     public Dimension preferredSize() {
 786         return getPreferredSize();
 787     }
 788 
 789     public Dimension minimumSize() {
 790         return getMinimumSize();
 791     }
 792 
 793     public Insets getInsets() {
 794         return new Insets(0, 0, 0, 0);
 795     }
 796 
 797     public void beginValidate() {
 798     }
 799 
 800     public void endValidate() {
 801     }
 802 
 803     // Returns true if we are inside begin/endLayout and
 804     // are waiting for native painting
 805     public boolean isPaintPending() {
 806         return paintPending && isLayouting;
 807     }
 808 
 809     public boolean handlesWheelScrolling() {
 810         return false;
 811     }
 812 
 813     public void beginLayout() {
 814         // Skip all painting till endLayout
 815         isLayouting = true;
 816 
 817     }
 818 
 819     public void endLayout() {
 820         if (!paintPending && !paintArea.isEmpty()
 821             && !ComponentAccessor.getIgnoreRepaint(target))
 822         {
 823             // if not waiting for native painting repaint damaged area
 824             postEvent(new PaintEvent(target, PaintEvent.PAINT,
 825                                      new Rectangle()));
 826         }
 827         isLayouting = false;
 828     }
 829 
 830     public Color getWinBackground() {
 831         return getPeerBackground();
 832     }
 833 
 834     static int[] getRGBvals(Color c) {
 835 
 836         int rgbvals[] = new int[3];
 837 
 838         rgbvals[0] = c.getRed();
 839         rgbvals[1] = c.getGreen();
 840         rgbvals[2] = c.getBlue();
 841 
 842         return rgbvals;
 843     }
 844 
 845     static final int BACKGROUND_COLOR = 0;
 846     static final int HIGHLIGHT_COLOR = 1;
 847     static final int SHADOW_COLOR = 2;
 848     static final int FOREGROUND_COLOR = 3;
 849 
 850     public Color[] getGUIcolors() {
 851         Color c[] = new Color[4];
 852         float backb, highb, shadowb, hue, saturation;
 853         c[BACKGROUND_COLOR] = getWinBackground();
 854         if (c[BACKGROUND_COLOR] == null) {
 855             c[BACKGROUND_COLOR] = super.getWinBackground();
 856         }
 857         if (c[BACKGROUND_COLOR] == null) {
 858             c[BACKGROUND_COLOR] = Color.lightGray;
 859         }
 860 
 861         int[] rgb = getRGBvals(c[BACKGROUND_COLOR]);
 862 
 863         float[] hsb = Color.RGBtoHSB(rgb[0],rgb[1],rgb[2],null);
 864 
 865         hue = hsb[0];
 866         saturation = hsb[1];
 867         backb = hsb[2];
 868 
 869 
 870 /*      Calculate Highlight Brightness  */
 871 
 872         highb = backb + 0.2f;
 873         shadowb = backb - 0.4f;
 874         if ((highb > 1.0) ) {
 875             if  ((1.0 - backb) < 0.05) {
 876                 highb = shadowb + 0.25f;
 877             } else {
 878                 highb = 1.0f;
 879             }
 880         } else {
 881             if (shadowb < 0.0) {
 882                 if ((backb - 0.0) < 0.25) {
 883                     highb = backb + 0.75f;
 884                     shadowb = highb - 0.2f;
 885                 } else {
 886                     shadowb = 0.0f;
 887                 }
 888             }
 889         }
 890         c[HIGHLIGHT_COLOR] = Color.getHSBColor(hue,saturation,highb);
 891         c[SHADOW_COLOR] = Color.getHSBColor(hue,saturation,shadowb);
 892 
 893 
 894 /*
 895   c[SHADOW_COLOR] = c[BACKGROUND_COLOR].darker();
 896   int r2 = c[SHADOW_COLOR].getRed();
 897   int g2 = c[SHADOW_COLOR].getGreen();
 898   int b2 = c[SHADOW_COLOR].getBlue();
 899 */
 900 
 901         c[FOREGROUND_COLOR] = getPeerForeground();
 902         if (c[FOREGROUND_COLOR] == null) {
 903             c[FOREGROUND_COLOR] = Color.black;
 904         }
 905 /*
 906   if ((c[BACKGROUND_COLOR].equals(c[HIGHLIGHT_COLOR]))
 907   && (c[BACKGROUND_COLOR].equals(c[SHADOW_COLOR]))) {
 908   c[SHADOW_COLOR] = new Color(c[BACKGROUND_COLOR].getRed() + 75,
 909   c[BACKGROUND_COLOR].getGreen() + 75,
 910   c[BACKGROUND_COLOR].getBlue() + 75);
 911   c[HIGHLIGHT_COLOR] = c[SHADOW_COLOR].brighter();
 912   } else if (c[BACKGROUND_COLOR].equals(c[HIGHLIGHT_COLOR])) {
 913   c[HIGHLIGHT_COLOR] = c[SHADOW_COLOR];
 914   c[SHADOW_COLOR] = c[SHADOW_COLOR].darker();
 915   }
 916 */
 917         if (! isEnabled()) {
 918             c[BACKGROUND_COLOR] = c[BACKGROUND_COLOR].darker();
 919             // Reduce the contrast
 920             // Calculate the NTSC gray (NB: REC709 L* might be better!)
 921             // for foreground and background; then multiply the foreground
 922             // by the average lightness
 923 
 924 
 925             Color tc = c[BACKGROUND_COLOR];
 926             int bg = tc.getRed() * 30 + tc.getGreen() * 59 + tc.getBlue() * 11;
 927 
 928             tc = c[FOREGROUND_COLOR];
 929             int fg = tc.getRed() * 30 + tc.getGreen() * 59 + tc.getBlue() * 11;
 930 
 931             float ave = (float) ((fg + bg) / 51000.0);
 932             // 255 * 100 * 2
 933 
 934             Color newForeground = new Color((int) (tc.getRed() * ave),
 935                                             (int) (tc.getGreen() * ave),
 936                                             (int) (tc.getBlue() * ave));
 937 
 938             if (newForeground.equals(c[FOREGROUND_COLOR])) {
 939                 // This probably means the foreground color is black or white
 940                 newForeground = new Color(ave, ave, ave);
 941             }
 942             c[FOREGROUND_COLOR] = newForeground;
 943 
 944         }
 945 
 946 
 947         return c;
 948     }
 949 
 950     /**
 951      * Returns an array of Colors similar to getGUIcolors(), but using the
 952      * System colors.  This is useful if pieces of a Component (such as
 953      * the integrated scrollbars of a List) should retain the System color
 954      * instead of the background color set by Component.setBackground().
 955      */
 956     static Color[] getSystemColors() {
 957         if (systemColors == null) {
 958             systemColors = new Color[4];
 959             systemColors[BACKGROUND_COLOR] = SystemColor.window;
 960             systemColors[HIGHLIGHT_COLOR] = SystemColor.controlLtHighlight;
 961             systemColors[SHADOW_COLOR] = SystemColor.controlShadow;
 962             systemColors[FOREGROUND_COLOR] = SystemColor.windowText;
 963         }
 964         return systemColors;
 965     }
 966 
 967     /**
 968      * Draw a 3D oval.
 969      */
 970     public void draw3DOval(Graphics g, Color colors[],
 971                            int x, int y, int w, int h, boolean raised)
 972         {
 973         Color c = g.getColor();
 974         g.setColor(raised ? colors[HIGHLIGHT_COLOR] : colors[SHADOW_COLOR]);
 975         g.drawArc(x, y, w, h, 45, 180);
 976         g.setColor(raised ? colors[SHADOW_COLOR] : colors[HIGHLIGHT_COLOR]);
 977         g.drawArc(x, y, w, h, 225, 180);
 978         g.setColor(c);
 979     }
 980 
 981     public void draw3DRect(Graphics g, Color colors[],
 982                            int x, int y, int width, int height, boolean raised)
 983         {
 984             Color c = g.getColor();
 985             g.setColor(raised ? colors[HIGHLIGHT_COLOR] : colors[SHADOW_COLOR]);
 986             g.drawLine(x, y, x, y + height);
 987             g.drawLine(x + 1, y, x + width - 1, y);
 988             g.setColor(raised ? colors[SHADOW_COLOR] : colors[HIGHLIGHT_COLOR]);
 989             g.drawLine(x + 1, y + height, x + width, y + height);
 990             g.drawLine(x + width, y, x + width, y + height - 1);
 991             g.setColor(c);
 992         }
 993 
 994     /*
 995      * drawXXX() methods are used to print the native components by
 996      * rendering the Motif look ourselves.
 997      * ToDo(aim): needs to query native motif for more accurate color
 998      * information.
 999      */
1000     void draw3DOval(Graphics g, Color bg,
1001                     int x, int y, int w, int h, boolean raised)
1002         {
1003             Color c = g.getColor();
1004             Color shadow = bg.darker();
1005             Color highlight = bg.brighter();
1006 
1007             g.setColor(raised ? highlight : shadow);
1008             g.drawArc(x, y, w, h, 45, 180);
1009             g.setColor(raised ? shadow : highlight);
1010             g.drawArc(x, y, w, h, 225, 180);
1011             g.setColor(c);
1012         }
1013 
1014     void draw3DRect(Graphics g, Color bg,
1015                     int x, int y, int width, int height,
1016                     boolean raised) {
1017         Color c = g.getColor();
1018         Color shadow = bg.darker();
1019         Color highlight = bg.brighter();
1020 
1021         g.setColor(raised ? highlight : shadow);
1022         g.drawLine(x, y, x, y + height);
1023         g.drawLine(x + 1, y, x + width - 1, y);
1024         g.setColor(raised ? shadow : highlight);
1025         g.drawLine(x + 1, y + height, x + width, y + height);
1026         g.drawLine(x + width, y, x + width, y + height - 1);
1027         g.setColor(c);
1028     }
1029 
1030     void drawScrollbar(Graphics g, Color bg, int thickness, int length,
1031                int min, int max, int val, int vis, boolean horizontal) {
1032         Color c = g.getColor();
1033         double f = (double)(length - 2*(thickness-1)) / Math.max(1, ((max - min) + vis));
1034         int v1 = thickness + (int)(f * (val - min));
1035         int v2 = (int)(f * vis);
1036         int w2 = thickness-4;
1037         int tpts_x[] = new int[3];
1038         int tpts_y[] = new int[3];
1039 
1040         if (length < 3*w2 ) {
1041             v1 = v2 = 0;
1042             if (length < 2*w2 + 2) {
1043                 w2 = (length-2)/2;
1044             }
1045         } else  if (v2 < 7) {
1046             // enforce a minimum handle size
1047             v1 = Math.max(0, v1 - ((7 - v2)>>1));
1048             v2 = 7;
1049         }
1050 
1051         int ctr   = thickness/2;
1052         int sbmin = ctr - w2/2;
1053         int sbmax = ctr + w2/2;
1054 
1055         // paint the background slightly darker
1056         {
1057             Color d = new Color((int) (bg.getRed()   * 0.85),
1058                                 (int) (bg.getGreen() * 0.85),
1059                                 (int) (bg.getBlue()  * 0.85));
1060 
1061             g.setColor(d);
1062             if (horizontal) {
1063                 g.fillRect(0, 0, length, thickness);
1064             } else {
1065                 g.fillRect(0, 0, thickness, length);
1066             }
1067         }
1068 
1069         // paint the thumb and arrows in the normal background color
1070         g.setColor(bg);
1071         if (v1 > 0) {
1072             if (horizontal) {
1073                 g.fillRect(v1, 3, v2, thickness-3);
1074             } else {
1075                 g.fillRect(3, v1, thickness-3, v2);
1076             }
1077         }
1078 
1079         tpts_x[0] = ctr;    tpts_y[0] = 2;
1080         tpts_x[1] = sbmin;  tpts_y[1] = w2;
1081         tpts_x[2] = sbmax;  tpts_y[2] = w2;
1082         if (horizontal) {
1083             g.fillPolygon(tpts_y, tpts_x, 3);
1084         } else {
1085             g.fillPolygon(tpts_x, tpts_y, 3);
1086         }
1087 
1088         tpts_y[0] = length-2;
1089         tpts_y[1] = length-w2;
1090         tpts_y[2] = length-w2;
1091         if (horizontal) {
1092             g.fillPolygon(tpts_y, tpts_x, 3);
1093         } else {
1094             g.fillPolygon(tpts_x, tpts_y, 3);
1095         }
1096 
1097         Color highlight = bg.brighter();
1098 
1099         // // // // draw the "highlighted" edges
1100         g.setColor(highlight);
1101 
1102         // outline & arrows
1103         if (horizontal) {
1104             g.drawLine(1, thickness, length - 1, thickness);
1105             g.drawLine(length - 1, 1, length - 1, thickness);
1106 
1107             // arrows
1108             g.drawLine(1, ctr, w2, sbmin);
1109             g.drawLine(length - w2, sbmin, length - w2, sbmax);
1110             g.drawLine(length - w2, sbmin, length - 2, ctr);
1111 
1112         } else {
1113             g.drawLine(thickness, 1, thickness, length - 1);
1114             g.drawLine(1, length - 1, thickness, length - 1);
1115 
1116             // arrows
1117             g.drawLine(ctr, 1, sbmin, w2);
1118             g.drawLine(sbmin, length - w2, sbmax, length - w2);
1119             g.drawLine(sbmin, length - w2, ctr, length - 2);
1120         }
1121 
1122         // thumb
1123         if (v1 > 0) {
1124             if (horizontal) {
1125                 g.drawLine(v1, 2, v1 + v2, 2);
1126                 g.drawLine(v1, 2, v1, thickness-3);
1127             } else {
1128                 g.drawLine(2, v1, 2, v1 + v2);
1129                 g.drawLine(2, v1, thickness-3, v1);
1130             }
1131         }
1132 
1133         Color shadow = bg.darker();
1134 
1135         // // // // draw the "shadowed" edges
1136         g.setColor(shadow);
1137 
1138         // outline && arrows
1139         if (horizontal) {
1140             g.drawLine(0, 0, 0, thickness);
1141             g.drawLine(0, 0, length - 1, 0);
1142 
1143             // arrows
1144             g.drawLine(w2, sbmin, w2, sbmax);
1145             g.drawLine(w2, sbmax, 1, ctr);
1146             g.drawLine(length-2, ctr, length-w2, sbmax);
1147 
1148         } else {
1149             g.drawLine(0, 0, thickness, 0);
1150             g.drawLine(0, 0, 0, length - 1);
1151 
1152             // arrows
1153             g.drawLine(sbmin, w2, sbmax, w2);
1154             g.drawLine(sbmax, w2, ctr, 1);
1155             g.drawLine(ctr, length-2, sbmax, length-w2);
1156         }
1157 
1158         // thumb
1159         if (v1 > 0) {
1160             if (horizontal) {
1161                 g.drawLine(v1 + v2, 2, v1 + v2, thickness-2);
1162                 g.drawLine(v1, thickness-2, v1 + v2, thickness-2);
1163             } else {
1164                 g.drawLine(2, v1 + v2, thickness-2, v1 + v2);
1165                 g.drawLine(thickness-2, v1, thickness-2, v1 + v2);
1166             }
1167         }
1168         g.setColor(c);
1169     }
1170 
1171     /**
1172      * The following multibuffering-related methods delegate to our
1173      * associated GraphicsConfig (X11 or GLX) to handle the appropriate
1174      * native windowing system specific actions.
1175      */
1176 
1177     private BufferCapabilities backBufferCaps;
1178 
1179     public void createBuffers(int numBuffers, BufferCapabilities caps)
1180       throws AWTException
1181     {
1182         if (buffersLog.isLoggable(Level.FINE)) {
1183             buffersLog.fine("createBuffers(" + numBuffers + ", " + caps + ")");
1184         }
1185         // set the caps first, they're used when creating the bb
1186         backBufferCaps = caps;
1187         backBuffer = graphicsConfig.createBackBuffer(this, numBuffers, caps);
1188         xBackBuffer = graphicsConfig.createBackBufferImage(target,
1189                                                            backBuffer);
1190     }
1191 
1192     @Override
1193     public BufferCapabilities getBackBufferCaps() {
1194         return backBufferCaps;
1195     }
1196 
1197     public void flip(int x1, int y1, int x2, int y2,
1198                      BufferCapabilities.FlipContents flipAction)
1199     {
1200         if (buffersLog.isLoggable(Level.FINE)) {
1201             buffersLog.fine("flip(" + flipAction + ")");
1202         }
1203         if (backBuffer == 0) {
1204             throw new IllegalStateException("Buffers have not been created");
1205         }
1206         graphicsConfig.flip(this, target, xBackBuffer,
1207                             x1, y1, x2, y2, flipAction);
1208     }
1209 
1210     public Image getBackBuffer() {
1211         if (buffersLog.isLoggable(Level.FINE)) {
1212             buffersLog.fine("getBackBuffer()");
1213         }
1214         if (backBuffer == 0) {
1215             throw new IllegalStateException("Buffers have not been created");
1216         }
1217         return xBackBuffer;
1218     }
1219 
1220     public void destroyBuffers() {
1221         if (buffersLog.isLoggable(Level.FINE)) {
1222             buffersLog.fine("destroyBuffers()");
1223         }
1224         graphicsConfig.destroyBackBuffer(backBuffer);
1225         backBuffer = 0;
1226         xBackBuffer = null;
1227     }
1228 
1229     // End of multi-buffering
1230 
1231     public void notifyTextComponentChange(boolean add){
1232         Container parent = ComponentAccessor.getParent_NoClientCode(target);
1233         while(!(parent == null ||
1234                 parent instanceof java.awt.Frame ||
1235                 parent instanceof java.awt.Dialog)) {
1236         parent = ComponentAccessor.getParent_NoClientCode(parent);
1237         }
1238 
1239 /*      FIX ME - FIX ME need to implement InputMethods
1240     if (parent instanceof java.awt.Frame ||
1241         parent instanceof java.awt.Dialog) {
1242         if (add)
1243         ((MInputMethodControl)parent.getPeer()).addTextComponent((MComponentPeer)this);
1244         else
1245         ((MInputMethodControl)parent.getPeer()).removeTextComponent((MComponentPeer)this);
1246     }
1247 */
1248     }
1249 
1250     /**
1251      * Returns true if this event is disabled and shouldn't be processed by window
1252      * Currently if target component is disabled the following event will be disabled on window:
1253      * ButtonPress, ButtonRelease, KeyPress, KeyRelease, EnterNotify, LeaveNotify, MotionNotify
1254      */
1255     protected boolean isEventDisabled(XEvent e) {
1256         enableLog.log(Level.FINEST, "Component is {1}, checking for disabled event {0}", new Object[] {e, (isEnabled()?"enabled":"disable")});
1257         if (!isEnabled()) {
1258             switch (e.get_type()) {
1259               case XConstants.ButtonPress:
1260               case XConstants.ButtonRelease:
1261               case XConstants.KeyPress:
1262               case XConstants.KeyRelease:
1263               case XConstants.EnterNotify:
1264               case XConstants.LeaveNotify:
1265               case XConstants.MotionNotify:
1266                   enableLog.log(Level.FINER, "Event {0} is disable", new Object[] {e});
1267                   return true;
1268             }
1269         }
1270         switch(e.get_type()) {
1271           case XConstants.MapNotify:
1272           case XConstants.UnmapNotify:
1273               return true;
1274         }
1275         return super.isEventDisabled(e);
1276     }
1277 
1278     Color getPeerBackground() {
1279         return background;
1280     }
1281 
1282     Color getPeerForeground() {
1283         return foreground;
1284     }
1285 
1286     Font getPeerFont() {
1287         return font;
1288     }
1289 
1290     Dimension getPeerSize() {
1291         return new Dimension(width,height);
1292     }
1293 
1294     public void setBoundsOperation(int operation) {
1295         synchronized(getStateLock()) {
1296             if (boundsOperation == DEFAULT_OPERATION) {
1297                 boundsOperation = operation;
1298             } else if (operation == RESET_OPERATION) {
1299                 boundsOperation = DEFAULT_OPERATION;
1300             }
1301         }
1302     }
1303 
1304     static String operationToString(int operation) {
1305         switch (operation) {
1306           case SET_LOCATION:
1307               return "SET_LOCATION";
1308           case SET_SIZE:
1309               return "SET_SIZE";
1310           case SET_CLIENT_SIZE:
1311               return "SET_CLIENT_SIZE";
1312           default:
1313           case SET_BOUNDS:
1314               return "SET_BOUNDS";
1315         }
1316     }
1317 
1318     /**
1319      * Lowers this component at the bottom of the above HW peer. If the above parameter
1320      * is null then the method places this component at the top of the Z-order.
1321      */
1322     public void setZOrder(ComponentPeer above) {
1323         long aboveWindow = (above != null) ? ((XComponentPeer)above).getWindow() : 0;
1324 
1325         XToolkit.awtLock();
1326         try{
1327             XlibWrapper.SetZOrder(XToolkit.getDisplay(), getWindow(), aboveWindow);
1328         }finally{
1329             XToolkit.awtUnlock();
1330         }
1331     }
1332 
1333     private void addTree(Collection order, Set set, Container cont) {
1334         for (int i = 0; i < cont.getComponentCount(); i++) {
1335             Component comp = cont.getComponent(i);
1336             ComponentPeer peer = comp.getPeer();
1337             if (peer instanceof XComponentPeer) {
1338                 Long window = Long.valueOf(((XComponentPeer)peer).getWindow());
1339                 if (!set.contains(window)) {
1340                     set.add(window);
1341                     order.add(window);
1342                 }
1343             } else if (comp instanceof Container) {
1344                 // It is lightweight container, it might contain heavyweight components attached to this
1345                 // peer
1346                 addTree(order, set, (Container)comp);
1347             }
1348         }
1349     }
1350 
1351     /****** DropTargetPeer implementation ********************/
1352 
1353     public void addDropTarget(DropTarget dt) {
1354         Component comp = target;
1355         while(!(comp == null || comp instanceof Window)) {
1356             comp = comp.getParent();
1357         }
1358 
1359         if (comp instanceof Window) {
1360             XWindowPeer wpeer = (XWindowPeer)(comp.getPeer());
1361             if (wpeer != null) {
1362                 wpeer.addDropTarget();
1363             }
1364         }
1365     }
1366 
1367     public void removeDropTarget(DropTarget dt) {
1368         Component comp = target;
1369         while(!(comp == null || comp instanceof Window)) {
1370             comp = comp.getParent();
1371         }
1372 
1373         if (comp instanceof Window) {
1374             XWindowPeer wpeer = (XWindowPeer)(comp.getPeer());
1375             if (wpeer != null) {
1376                 wpeer.removeDropTarget();
1377             }
1378         }
1379     }
1380 
1381     /**
1382      * Applies the shape to the X-window.
1383      * @since 1.7
1384      */
1385     public void applyShape(Region shape) {
1386         if (XlibUtil.isShapingSupported()) {
1387             if (shapeLog.isLoggable(Level.FINER)) {
1388                 shapeLog.finer(
1389                         "*** INFO: Setting shape: PEER: " + this
1390                         + "; WINDOW: " + getWindow()
1391                         + "; TARGET: " + target
1392                         + "; SHAPE: " + shape);
1393             }
1394             XToolkit.awtLock();
1395             try {
1396                 if (shape != null) {
1397                     XlibWrapper.SetRectangularShape(
1398                             XToolkit.getDisplay(),
1399                             getWindow(),
1400                             shape.getLoX(), shape.getLoY(),
1401                             shape.getHiX(), shape.getHiY(),
1402                             (shape.isRectangular() ? null : shape)
1403                             );
1404                 } else {
1405                     XlibWrapper.SetRectangularShape(
1406                             XToolkit.getDisplay(),
1407                             getWindow(),
1408                             0, 0,
1409                             0, 0,
1410                             null
1411                             );
1412                 }
1413             } finally {
1414                 XToolkit.awtUnlock();
1415             }
1416         } else {
1417             if (shapeLog.isLoggable(Level.FINER)) {
1418                 shapeLog.finer("*** WARNING: Shaping is NOT supported!");
1419             }
1420         }
1421     }
1422 
1423     public boolean updateGraphicsData(GraphicsConfiguration gc) {
1424         int oldVisual = -1, newVisual = -1;
1425 
1426         if (graphicsConfig != null) {
1427             oldVisual = graphicsConfig.getVisual();
1428         }
1429         if (gc != null && gc instanceof X11GraphicsConfig) {
1430             newVisual = ((X11GraphicsConfig)gc).getVisual();
1431         }
1432 
1433         // If the new visual differs from the old one, the peer must be
1434         // recreated because X11 does not allow changing the visual on the fly.
1435         // So we even skip the initGraphicsConfiguration() call.
1436         // The initial assignment should happen though, hence the != -1 thing.
1437         if (oldVisual != -1 && oldVisual != newVisual) {
1438             return true;
1439         }
1440 
1441         initGraphicsConfiguration();
1442         doValidateSurface();
1443         return false;
1444     }
1445 }