1 /*
   2  * Copyright (c) 2002, 2018, 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 Insets getInsets() {
 734         return new Insets(0, 0, 0, 0);
 735     }
 736 
 737     public void beginValidate() {
 738     }
 739 
 740     public void endValidate() {
 741     }
 742 
 743     // Returns true if we are inside begin/endLayout and
 744     // are waiting for native painting
 745     public boolean isPaintPending() {
 746         return paintPending && isLayouting;
 747     }
 748 
 749     public boolean handlesWheelScrolling() {
 750         return false;
 751     }
 752 
 753     public void beginLayout() {
 754         // Skip all painting till endLayout
 755         isLayouting = true;
 756 
 757     }
 758 
 759     public void endLayout() {
 760         if (!paintPending && !paintArea.isEmpty()
 761             && !AWTAccessor.getComponentAccessor().getIgnoreRepaint(target))
 762         {
 763             // if not waiting for native painting repaint damaged area
 764             postEvent(new PaintEvent(target, PaintEvent.PAINT,
 765                                      new Rectangle()));
 766         }
 767         isLayouting = false;
 768     }
 769 
 770     public Color getWinBackground() {
 771         return getPeerBackground();
 772     }
 773 
 774     static int[] getRGBvals(Color c) {
 775 
 776         int[] rgbvals = new int[3];
 777 
 778         rgbvals[0] = c.getRed();
 779         rgbvals[1] = c.getGreen();
 780         rgbvals[2] = c.getBlue();
 781 
 782         return rgbvals;
 783     }
 784 
 785     static final int BACKGROUND_COLOR = 0;
 786     static final int HIGHLIGHT_COLOR = 1;
 787     static final int SHADOW_COLOR = 2;
 788     static final int FOREGROUND_COLOR = 3;
 789 
 790     public Color[] getGUIcolors() {
 791         Color[] c = new Color[4];
 792         float backb, highb, shadowb, hue, saturation;
 793         c[BACKGROUND_COLOR] = getWinBackground();
 794         if (c[BACKGROUND_COLOR] == null) {
 795             c[BACKGROUND_COLOR] = super.getWinBackground();
 796         }
 797         if (c[BACKGROUND_COLOR] == null) {
 798             c[BACKGROUND_COLOR] = Color.lightGray;
 799         }
 800 
 801         int[] rgb = getRGBvals(c[BACKGROUND_COLOR]);
 802 
 803         float[] hsb = Color.RGBtoHSB(rgb[0],rgb[1],rgb[2],null);
 804 
 805         hue = hsb[0];
 806         saturation = hsb[1];
 807         backb = hsb[2];
 808 
 809 
 810 /*      Calculate Highlight Brightness  */
 811 
 812         highb = backb + 0.2f;
 813         shadowb = backb - 0.4f;
 814         if ((highb > 1.0) ) {
 815             if  ((1.0 - backb) < 0.05) {
 816                 highb = shadowb + 0.25f;
 817             } else {
 818                 highb = 1.0f;
 819             }
 820         } else {
 821             if (shadowb < 0.0) {
 822                 if ((backb - 0.0) < 0.25) {
 823                     highb = backb + 0.75f;
 824                     shadowb = highb - 0.2f;
 825                 } else {
 826                     shadowb = 0.0f;
 827                 }
 828             }
 829         }
 830         c[HIGHLIGHT_COLOR] = Color.getHSBColor(hue,saturation,highb);
 831         c[SHADOW_COLOR] = Color.getHSBColor(hue,saturation,shadowb);
 832 
 833 
 834 /*
 835   c[SHADOW_COLOR] = c[BACKGROUND_COLOR].darker();
 836   int r2 = c[SHADOW_COLOR].getRed();
 837   int g2 = c[SHADOW_COLOR].getGreen();
 838   int b2 = c[SHADOW_COLOR].getBlue();
 839 */
 840 
 841         c[FOREGROUND_COLOR] = getPeerForeground();
 842         if (c[FOREGROUND_COLOR] == null) {
 843             c[FOREGROUND_COLOR] = Color.black;
 844         }
 845 /*
 846   if ((c[BACKGROUND_COLOR].equals(c[HIGHLIGHT_COLOR]))
 847   && (c[BACKGROUND_COLOR].equals(c[SHADOW_COLOR]))) {
 848   c[SHADOW_COLOR] = new Color(c[BACKGROUND_COLOR].getRed() + 75,
 849   c[BACKGROUND_COLOR].getGreen() + 75,
 850   c[BACKGROUND_COLOR].getBlue() + 75);
 851   c[HIGHLIGHT_COLOR] = c[SHADOW_COLOR].brighter();
 852   } else if (c[BACKGROUND_COLOR].equals(c[HIGHLIGHT_COLOR])) {
 853   c[HIGHLIGHT_COLOR] = c[SHADOW_COLOR];
 854   c[SHADOW_COLOR] = c[SHADOW_COLOR].darker();
 855   }
 856 */
 857         if (! isEnabled()) {
 858             c[BACKGROUND_COLOR] = c[BACKGROUND_COLOR].darker();
 859             // Reduce the contrast
 860             // Calculate the NTSC gray (NB: REC709 L* might be better!)
 861             // for foreground and background; then multiply the foreground
 862             // by the average lightness
 863 
 864 
 865             Color tc = c[BACKGROUND_COLOR];
 866             int bg = tc.getRed() * 30 + tc.getGreen() * 59 + tc.getBlue() * 11;
 867 
 868             tc = c[FOREGROUND_COLOR];
 869             int fg = tc.getRed() * 30 + tc.getGreen() * 59 + tc.getBlue() * 11;
 870 
 871             float ave = (float) ((fg + bg) / 51000.0);
 872             // 255 * 100 * 2
 873 
 874             Color newForeground = new Color((int) (tc.getRed() * ave),
 875                                             (int) (tc.getGreen() * ave),
 876                                             (int) (tc.getBlue() * ave));
 877 
 878             if (newForeground.equals(c[FOREGROUND_COLOR])) {
 879                 // This probably means the foreground color is black or white
 880                 newForeground = new Color(ave, ave, ave);
 881             }
 882             c[FOREGROUND_COLOR] = newForeground;
 883 
 884         }
 885 
 886 
 887         return c;
 888     }
 889 
 890     /**
 891      * Returns an array of Colors similar to getGUIcolors(), but using the
 892      * System colors.  This is useful if pieces of a Component (such as
 893      * the integrated scrollbars of a List) should retain the System color
 894      * instead of the background color set by Component.setBackground().
 895      */
 896     static Color[] getSystemColors() {
 897         if (systemColors == null) {
 898             systemColors = new Color[4];
 899             systemColors[BACKGROUND_COLOR] = SystemColor.window;
 900             systemColors[HIGHLIGHT_COLOR] = SystemColor.controlLtHighlight;
 901             systemColors[SHADOW_COLOR] = SystemColor.controlShadow;
 902             systemColors[FOREGROUND_COLOR] = SystemColor.windowText;
 903         }
 904         return systemColors;
 905     }
 906 
 907     /**
 908      * Draw a 3D oval.
 909      */
 910     public void draw3DOval(Graphics g, Color[] colors,
 911                            int x, int y, int w, int h, boolean raised)
 912         {
 913         Color c = g.getColor();
 914         g.setColor(raised ? colors[HIGHLIGHT_COLOR] : colors[SHADOW_COLOR]);
 915         g.drawArc(x, y, w, h, 45, 180);
 916         g.setColor(raised ? colors[SHADOW_COLOR] : colors[HIGHLIGHT_COLOR]);
 917         g.drawArc(x, y, w, h, 225, 180);
 918         g.setColor(c);
 919     }
 920 
 921     public void draw3DRect(Graphics g, Color[] colors,
 922                            int x, int y, int width, int height, boolean raised)
 923         {
 924             Color c = g.getColor();
 925             g.setColor(raised ? colors[HIGHLIGHT_COLOR] : colors[SHADOW_COLOR]);
 926             g.drawLine(x, y, x, y + height);
 927             g.drawLine(x + 1, y, x + width - 1, y);
 928             g.setColor(raised ? colors[SHADOW_COLOR] : colors[HIGHLIGHT_COLOR]);
 929             g.drawLine(x + 1, y + height, x + width, y + height);
 930             g.drawLine(x + width, y, x + width, y + height - 1);
 931             g.setColor(c);
 932         }
 933 
 934     /*
 935      * drawXXX() methods are used to print the native components by
 936      * rendering the Motif look ourselves.
 937      * ToDo(aim): needs to query native motif for more accurate color
 938      * information.
 939      */
 940     void draw3DOval(Graphics g, Color bg,
 941                     int x, int y, int w, int h, boolean raised)
 942         {
 943             Color c = g.getColor();
 944             Color shadow = bg.darker();
 945             Color highlight = bg.brighter();
 946 
 947             g.setColor(raised ? highlight : shadow);
 948             g.drawArc(x, y, w, h, 45, 180);
 949             g.setColor(raised ? shadow : highlight);
 950             g.drawArc(x, y, w, h, 225, 180);
 951             g.setColor(c);
 952         }
 953 
 954     void draw3DRect(Graphics g, Color bg,
 955                     int x, int y, int width, int height,
 956                     boolean raised) {
 957         Color c = g.getColor();
 958         Color shadow = bg.darker();
 959         Color highlight = bg.brighter();
 960 
 961         g.setColor(raised ? highlight : shadow);
 962         g.drawLine(x, y, x, y + height);
 963         g.drawLine(x + 1, y, x + width - 1, y);
 964         g.setColor(raised ? shadow : highlight);
 965         g.drawLine(x + 1, y + height, x + width, y + height);
 966         g.drawLine(x + width, y, x + width, y + height - 1);
 967         g.setColor(c);
 968     }
 969 
 970     void drawScrollbar(Graphics g, Color bg, int thickness, int length,
 971                int min, int max, int val, int vis, boolean horizontal) {
 972         Color c = g.getColor();
 973         double f = (double)(length - 2*(thickness-1)) / Math.max(1, ((max - min) + vis));
 974         int v1 = thickness + (int)(f * (val - min));
 975         int v2 = (int)(f * vis);
 976         int w2 = thickness-4;
 977         int[] tpts_x = new int[3];
 978         int[] tpts_y = new int[3];
 979 
 980         if (length < 3*w2 ) {
 981             v1 = v2 = 0;
 982             if (length < 2*w2 + 2) {
 983                 w2 = (length-2)/2;
 984             }
 985         } else  if (v2 < 7) {
 986             // enforce a minimum handle size
 987             v1 = Math.max(0, v1 - ((7 - v2)>>1));
 988             v2 = 7;
 989         }
 990 
 991         int ctr   = thickness/2;
 992         int sbmin = ctr - w2/2;
 993         int sbmax = ctr + w2/2;
 994 
 995         // paint the background slightly darker
 996         {
 997             Color d = new Color((int) (bg.getRed()   * 0.85),
 998                                 (int) (bg.getGreen() * 0.85),
 999                                 (int) (bg.getBlue()  * 0.85));
1000 
1001             g.setColor(d);
1002             if (horizontal) {
1003                 g.fillRect(0, 0, length, thickness);
1004             } else {
1005                 g.fillRect(0, 0, thickness, length);
1006             }
1007         }
1008 
1009         // paint the thumb and arrows in the normal background color
1010         g.setColor(bg);
1011         if (v1 > 0) {
1012             if (horizontal) {
1013                 g.fillRect(v1, 3, v2, thickness-3);
1014             } else {
1015                 g.fillRect(3, v1, thickness-3, v2);
1016             }
1017         }
1018 
1019         tpts_x[0] = ctr;    tpts_y[0] = 2;
1020         tpts_x[1] = sbmin;  tpts_y[1] = w2;
1021         tpts_x[2] = sbmax;  tpts_y[2] = w2;
1022         if (horizontal) {
1023             g.fillPolygon(tpts_y, tpts_x, 3);
1024         } else {
1025             g.fillPolygon(tpts_x, tpts_y, 3);
1026         }
1027 
1028         tpts_y[0] = length-2;
1029         tpts_y[1] = length-w2;
1030         tpts_y[2] = length-w2;
1031         if (horizontal) {
1032             g.fillPolygon(tpts_y, tpts_x, 3);
1033         } else {
1034             g.fillPolygon(tpts_x, tpts_y, 3);
1035         }
1036 
1037         Color highlight = bg.brighter();
1038 
1039         // // // // draw the "highlighted" edges
1040         g.setColor(highlight);
1041 
1042         // outline & arrows
1043         if (horizontal) {
1044             g.drawLine(1, thickness, length - 1, thickness);
1045             g.drawLine(length - 1, 1, length - 1, thickness);
1046 
1047             // arrows
1048             g.drawLine(1, ctr, w2, sbmin);
1049             g.drawLine(length - w2, sbmin, length - w2, sbmax);
1050             g.drawLine(length - w2, sbmin, length - 2, ctr);
1051 
1052         } else {
1053             g.drawLine(thickness, 1, thickness, length - 1);
1054             g.drawLine(1, length - 1, thickness, length - 1);
1055 
1056             // arrows
1057             g.drawLine(ctr, 1, sbmin, w2);
1058             g.drawLine(sbmin, length - w2, sbmax, length - w2);
1059             g.drawLine(sbmin, length - w2, ctr, length - 2);
1060         }
1061 
1062         // thumb
1063         if (v1 > 0) {
1064             if (horizontal) {
1065                 g.drawLine(v1, 2, v1 + v2, 2);
1066                 g.drawLine(v1, 2, v1, thickness-3);
1067             } else {
1068                 g.drawLine(2, v1, 2, v1 + v2);
1069                 g.drawLine(2, v1, thickness-3, v1);
1070             }
1071         }
1072 
1073         Color shadow = bg.darker();
1074 
1075         // // // // draw the "shadowed" edges
1076         g.setColor(shadow);
1077 
1078         // outline && arrows
1079         if (horizontal) {
1080             g.drawLine(0, 0, 0, thickness);
1081             g.drawLine(0, 0, length - 1, 0);
1082 
1083             // arrows
1084             g.drawLine(w2, sbmin, w2, sbmax);
1085             g.drawLine(w2, sbmax, 1, ctr);
1086             g.drawLine(length-2, ctr, length-w2, sbmax);
1087 
1088         } else {
1089             g.drawLine(0, 0, thickness, 0);
1090             g.drawLine(0, 0, 0, length - 1);
1091 
1092             // arrows
1093             g.drawLine(sbmin, w2, sbmax, w2);
1094             g.drawLine(sbmax, w2, ctr, 1);
1095             g.drawLine(ctr, length-2, sbmax, length-w2);
1096         }
1097 
1098         // thumb
1099         if (v1 > 0) {
1100             if (horizontal) {
1101                 g.drawLine(v1 + v2, 2, v1 + v2, thickness-2);
1102                 g.drawLine(v1, thickness-2, v1 + v2, thickness-2);
1103             } else {
1104                 g.drawLine(2, v1 + v2, thickness-2, v1 + v2);
1105                 g.drawLine(thickness-2, v1, thickness-2, v1 + v2);
1106             }
1107         }
1108         g.setColor(c);
1109     }
1110 
1111     /**
1112      * The following multibuffering-related methods delegate to our
1113      * associated GraphicsConfig (X11 or GLX) to handle the appropriate
1114      * native windowing system specific actions.
1115      */
1116 
1117     private BufferCapabilities backBufferCaps;
1118 
1119     public void createBuffers(int numBuffers, BufferCapabilities caps)
1120       throws AWTException
1121     {
1122         if (buffersLog.isLoggable(PlatformLogger.Level.FINE)) {
1123             buffersLog.fine("createBuffers(" + numBuffers + ", " + caps + ")");
1124         }
1125         // set the caps first, they're used when creating the bb
1126         backBufferCaps = caps;
1127         backBuffer = graphicsConfig.createBackBuffer(this, numBuffers, caps);
1128         xBackBuffer = graphicsConfig.createBackBufferImage(target,
1129                                                            backBuffer);
1130     }
1131 
1132     @Override
1133     public BufferCapabilities getBackBufferCaps() {
1134         return backBufferCaps;
1135     }
1136 
1137     public void flip(int x1, int y1, int x2, int y2,
1138                      BufferCapabilities.FlipContents flipAction)
1139     {
1140         if (buffersLog.isLoggable(PlatformLogger.Level.FINE)) {
1141             buffersLog.fine("flip(" + flipAction + ")");
1142         }
1143         if (backBuffer == 0) {
1144             throw new IllegalStateException("Buffers have not been created");
1145         }
1146         graphicsConfig.flip(this, target, xBackBuffer,
1147                             x1, y1, x2, y2, flipAction);
1148     }
1149 
1150     public Image getBackBuffer() {
1151         if (buffersLog.isLoggable(PlatformLogger.Level.FINE)) {
1152             buffersLog.fine("getBackBuffer()");
1153         }
1154         if (backBuffer == 0) {
1155             throw new IllegalStateException("Buffers have not been created");
1156         }
1157         return xBackBuffer;
1158     }
1159 
1160     public void destroyBuffers() {
1161         if (buffersLog.isLoggable(PlatformLogger.Level.FINE)) {
1162             buffersLog.fine("destroyBuffers()");
1163         }
1164         graphicsConfig.destroyBackBuffer(backBuffer);
1165         backBuffer = 0;
1166         xBackBuffer = null;
1167     }
1168 
1169     // End of multi-buffering
1170 
1171     public void notifyTextComponentChange(boolean add){
1172         Container parent = AWTAccessor.getComponentAccessor().getParent(target);
1173         while(!(parent == null ||
1174                 parent instanceof java.awt.Frame ||
1175                 parent instanceof java.awt.Dialog)) {
1176             parent = AWTAccessor.getComponentAccessor().getParent(parent);
1177         }
1178 
1179 /*      FIX ME - FIX ME need to implement InputMethods
1180     if (parent instanceof java.awt.Frame ||
1181         parent instanceof java.awt.Dialog) {
1182         if (add)
1183         ((MInputMethodControl)parent.getPeer()).addTextComponent((MComponentPeer)this);
1184         else
1185         ((MInputMethodControl)parent.getPeer()).removeTextComponent((MComponentPeer)this);
1186     }
1187 */
1188     }
1189 
1190     /**
1191      * Returns true if this event is disabled and shouldn't be processed by window
1192      * Currently if target component is disabled the following event will be disabled on window:
1193      * ButtonPress, ButtonRelease, KeyPress, KeyRelease, EnterNotify, LeaveNotify, MotionNotify
1194      */
1195     protected boolean isEventDisabled(XEvent e) {
1196         if (enableLog.isLoggable(PlatformLogger.Level.FINEST)) {
1197             enableLog.finest("Component is {1}, checking for disabled event {0}", e, (isEnabled()?"enabled":"disable"));
1198         }
1199         if (!isEnabled()) {
1200             switch (e.get_type()) {
1201               case XConstants.ButtonPress:
1202               case XConstants.ButtonRelease:
1203               case XConstants.KeyPress:
1204               case XConstants.KeyRelease:
1205               case XConstants.EnterNotify:
1206               case XConstants.LeaveNotify:
1207               case XConstants.MotionNotify:
1208                   if (enableLog.isLoggable(PlatformLogger.Level.FINER)) {
1209                       enableLog.finer("Event {0} is disable", e);
1210                   }
1211                   return true;
1212             }
1213         }
1214         switch(e.get_type()) {
1215           case XConstants.MapNotify:
1216           case XConstants.UnmapNotify:
1217               return true;
1218         }
1219         return super.isEventDisabled(e);
1220     }
1221 
1222     Color getPeerBackground() {
1223         return background;
1224     }
1225 
1226     Color getPeerForeground() {
1227         return foreground;
1228     }
1229 
1230     Font getPeerFont() {
1231         return font;
1232     }
1233 
1234     Dimension getPeerSize() {
1235         return new Dimension(width,height);
1236     }
1237 
1238     public void setBoundsOperation(int operation) {
1239         synchronized(getStateLock()) {
1240             if (boundsOperation == DEFAULT_OPERATION) {
1241                 boundsOperation = operation;
1242             } else if (operation == RESET_OPERATION) {
1243                 boundsOperation = DEFAULT_OPERATION;
1244             }
1245         }
1246     }
1247 
1248     static String operationToString(int operation) {
1249         switch (operation) {
1250           case SET_LOCATION:
1251               return "SET_LOCATION";
1252           case SET_SIZE:
1253               return "SET_SIZE";
1254           case SET_CLIENT_SIZE:
1255               return "SET_CLIENT_SIZE";
1256           default:
1257           case SET_BOUNDS:
1258               return "SET_BOUNDS";
1259         }
1260     }
1261 
1262     /**
1263      * Lowers this component at the bottom of the above HW peer. If the above parameter
1264      * is null then the method places this component at the top of the Z-order.
1265      */
1266     public void setZOrder(ComponentPeer above) {
1267         long aboveWindow = (above != null) ? ((XComponentPeer)above).getWindow() : 0;
1268 
1269         XToolkit.awtLock();
1270         try{
1271             XlibWrapper.SetZOrder(XToolkit.getDisplay(), getWindow(), aboveWindow);
1272         }finally{
1273             XToolkit.awtUnlock();
1274         }
1275     }
1276 
1277     private void addTree(Collection<Long> order, Set<Long> set, Container cont) {
1278         for (int i = 0; i < cont.getComponentCount(); i++) {
1279             Component comp = cont.getComponent(i);
1280             Object peer = AWTAccessor.getComponentAccessor().getPeer(comp);
1281             if (peer instanceof XComponentPeer) {
1282                 Long window = Long.valueOf(((XComponentPeer)peer).getWindow());
1283                 if (!set.contains(window)) {
1284                     set.add(window);
1285                     order.add(window);
1286                 }
1287             } else if (comp instanceof Container) {
1288                 // It is lightweight container, it might contain heavyweight components attached to this
1289                 // peer
1290                 addTree(order, set, (Container)comp);
1291             }
1292         }
1293     }
1294 
1295     /****** DropTargetPeer implementation ********************/
1296 
1297     public void addDropTarget(DropTarget dt) {
1298         Component comp = target;
1299         while(!(comp == null || comp instanceof Window)) {
1300             comp = comp.getParent();
1301         }
1302 
1303         if (comp instanceof Window) {
1304             XWindowPeer wpeer = AWTAccessor.getComponentAccessor().getPeer(comp);
1305             if (wpeer != null) {
1306                 wpeer.addDropTarget();
1307             }
1308         }
1309     }
1310 
1311     public void removeDropTarget(DropTarget dt) {
1312         Component comp = target;
1313         while(!(comp == null || comp instanceof Window)) {
1314             comp = comp.getParent();
1315         }
1316 
1317         if (comp instanceof Window) {
1318             XWindowPeer wpeer = AWTAccessor.getComponentAccessor()
1319                                            .getPeer(comp);
1320             if (wpeer != null) {
1321                 wpeer.removeDropTarget();
1322             }
1323         }
1324     }
1325 
1326     /**
1327      * Applies the shape to the X-window.
1328      * @since 1.7
1329      */
1330     public void applyShape(Region shape) {
1331         if (XlibUtil.isShapingSupported()) {
1332             if (shapeLog.isLoggable(PlatformLogger.Level.FINER)) {
1333                 shapeLog.finer(
1334                         "*** INFO: Setting shape: PEER: " + this
1335                         + "; WINDOW: " + getWindow()
1336                         + "; TARGET: " + target
1337                         + "; SHAPE: " + shape);
1338             }
1339             XToolkit.awtLock();
1340             try {
1341                 if (shape != null) {
1342 
1343                     int scale = getScale();
1344                     if (scale != 1) {
1345                         shape = shape.getScaledRegion(scale, scale);
1346                     }
1347 
1348                     XlibWrapper.SetRectangularShape(
1349                             XToolkit.getDisplay(),
1350                             getWindow(),
1351                             shape.getLoX(), shape.getLoY(),
1352                             shape.getHiX(), shape.getHiY(),
1353                             (shape.isRectangular() ? null : shape)
1354                             );
1355                 } else {
1356                     XlibWrapper.SetRectangularShape(
1357                             XToolkit.getDisplay(),
1358                             getWindow(),
1359                             0, 0,
1360                             0, 0,
1361                             null
1362                             );
1363                 }
1364             } finally {
1365                 XToolkit.awtUnlock();
1366             }
1367         } else {
1368             if (shapeLog.isLoggable(PlatformLogger.Level.FINER)) {
1369                 shapeLog.finer("*** WARNING: Shaping is NOT supported!");
1370             }
1371         }
1372     }
1373 
1374     public boolean updateGraphicsData(GraphicsConfiguration gc) {
1375         int oldVisual = -1, newVisual = -1;
1376 
1377         if (graphicsConfig != null) {
1378             oldVisual = graphicsConfig.getVisual();
1379         }
1380         if (gc != null && gc instanceof X11GraphicsConfig) {
1381             newVisual = ((X11GraphicsConfig)gc).getVisual();
1382         }
1383 
1384         // If the new visual differs from the old one, the peer must be
1385         // recreated because X11 does not allow changing the visual on the fly.
1386         // So we even skip the initGraphicsConfiguration() call.
1387         // The initial assignment should happen though, hence the != -1 thing.
1388         if (oldVisual != -1 && oldVisual != newVisual) {
1389             return true;
1390         }
1391 
1392         initGraphicsConfiguration();
1393         doValidateSurface();
1394         return false;
1395     }
1396 }