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