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