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