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