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 
  26 package sun.awt.X11;
  27 
  28 import java.awt.*;
  29 import java.awt.event.*;
  30 import java.awt.peer.ComponentPeer;
  31 import java.awt.image.ColorModel;
  32 
  33 import java.lang.ref.WeakReference;
  34 
  35 import java.util.logging.Level;
  36 import java.util.logging.Logger;
  37 
  38 import sun.awt.*;
  39 
  40 import sun.awt.image.PixelConverter;
  41 
  42 import sun.java2d.SunGraphics2D;
  43 import sun.java2d.SurfaceData;
  44 
  45 public class XWindow extends XBaseWindow implements X11ComponentPeer {
  46     private static Logger log = Logger.getLogger("sun.awt.X11.XWindow");
  47     private static Logger insLog = Logger.getLogger("sun.awt.X11.insets.XWindow");
  48     private static Logger eventLog = Logger.getLogger("sun.awt.X11.event.XWindow");
  49     private static final Logger focusLog = Logger.getLogger("sun.awt.X11.focus.XWindow");
  50     private static Logger keyEventLog = Logger.getLogger("sun.awt.X11.kye.XWindow");
  51   /* If a motion comes in while a multi-click is pending,
  52    * allow a smudge factor so that moving the mouse by a small
  53    * amount does not wipe out the multi-click state variables.
  54    */
  55     private final static int AWT_MULTICLICK_SMUDGE = 4;
  56     // ButtonXXX events stuff
  57     static int rbutton = 0;
  58     static int lastX = 0, lastY = 0;
  59     static long lastTime = 0;
  60     static long lastButton = 0;
  61     static WeakReference lastWindowRef = null;
  62     static int clickCount = 0;
  63 
  64     // used to check if we need to re-create surfaceData.
  65     int oldWidth = -1;
  66     int oldHeight = -1;
  67 
  68 
  69     protected X11GraphicsConfig graphicsConfig;
  70     protected AwtGraphicsConfigData graphicsConfigData;
  71 
  72     private boolean reparented;
  73 
  74     XWindow parent;
  75 
  76     Component target;
  77 
  78     private static int JAWT_LOCK_ERROR=0x00000001;
  79     private static int JAWT_LOCK_CLIP_CHANGED=0x00000002;
  80     private static int JAWT_LOCK_BOUNDS_CHANGED=0x00000004;
  81     private static int JAWT_LOCK_SURFACE_CHANGED=0x00000008;
  82     private int drawState = JAWT_LOCK_CLIP_CHANGED |
  83     JAWT_LOCK_BOUNDS_CHANGED |
  84     JAWT_LOCK_SURFACE_CHANGED;
  85 
  86     public static final String TARGET = "target",
  87         REPARENTED = "reparented"; // whether it is reparented by default
  88 
  89     SurfaceData surfaceData;
  90 
  91     XRepaintArea paintArea;
  92     // fallback default font object
  93     final static Font defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12);
  94 
  95     /*
  96      * Keeps all buttons which were pressed at the time of the last mouse
  97      * drag until all buttons will be released, contains state as bit masks
  98      * Button1Mask, Button2Mask, Button3Mask
  99      */
 100     private int mouseDragState = 0;
 101 
 102     native int getNativeColor(Color clr, GraphicsConfiguration gc);
 103     native void getWMInsets(long window, long left, long top, long right, long bottom, long border);
 104     native long getTopWindow(long window, long rootWin);
 105     native void getWindowBounds(long window, long x, long y, long width, long height);
 106     private native static void initIDs();
 107 
 108     static {
 109         initIDs();
 110     }
 111 
 112     XWindow(XCreateWindowParams params) {
 113         super(params);
 114     }
 115 
 116     XWindow() {
 117     }
 118 
 119     XWindow(long parentWindow, Rectangle bounds) {
 120         super(new XCreateWindowParams(new Object[] {
 121             BOUNDS, bounds,
 122             PARENT_WINDOW, Long.valueOf(parentWindow)}));
 123     }
 124 
 125     XWindow(Component target, long parentWindow, Rectangle bounds) {
 126         super(new XCreateWindowParams(new Object[] {
 127             BOUNDS, bounds,
 128             PARENT_WINDOW, Long.valueOf(parentWindow),
 129             TARGET, target}));
 130     }
 131 
 132     XWindow(Component target, long parentWindow) {
 133         this(target, parentWindow, target.getBounds());
 134     }
 135 
 136     XWindow(Component target) {
 137         this(target, (target.getParent() == null) ? 0 : getParentWindowID(target), target.getBounds());
 138     }
 139 
 140     XWindow(Object target) {
 141         this(null, 0, null);
 142     }
 143 
 144     /* This create is used by the XEmbeddedFramePeer since it has to create the window
 145        as a child of the netscape window. This netscape window is passed in as wid */
 146     XWindow(long parentWindow) {
 147         super(new XCreateWindowParams(new Object[] {
 148             PARENT_WINDOW, Long.valueOf(parentWindow),
 149             REPARENTED, Boolean.TRUE,
 150             EMBEDDED, Boolean.TRUE}));
 151     }
 152 
 153     protected void initGraphicsConfiguration() {
 154         graphicsConfig = (X11GraphicsConfig) target.getGraphicsConfiguration();
 155         graphicsConfigData = new AwtGraphicsConfigData(graphicsConfig.getAData());
 156     }
 157 
 158     void preInit(XCreateWindowParams params) {
 159         super.preInit(params);
 160         reparented = Boolean.TRUE.equals(params.get(REPARENTED));
 161 
 162         target = (Component)params.get(TARGET);
 163 
 164         initGraphicsConfiguration();
 165 
 166         AwtGraphicsConfigData gData = getGraphicsConfigurationData();
 167         X11GraphicsConfig config = (X11GraphicsConfig) getGraphicsConfiguration();
 168         XVisualInfo visInfo = gData.get_awt_visInfo();
 169         params.putIfNull(EVENT_MASK, KeyPressMask | KeyReleaseMask
 170             | FocusChangeMask | ButtonPressMask | ButtonReleaseMask
 171             | EnterWindowMask | LeaveWindowMask | PointerMotionMask
 172             | ButtonMotionMask | ExposureMask | StructureNotifyMask);
 173 
 174         if (target != null) {
 175             params.putIfNull(BOUNDS, target.getBounds());
 176         } else {
 177             params.putIfNull(BOUNDS, new Rectangle(0, 0, MIN_SIZE, MIN_SIZE));
 178         }
 179         params.putIfNull(BORDER_PIXEL, Long.valueOf(0));
 180         getColorModel(); // fix 4948833: this call forces the color map to be initialized
 181         params.putIfNull(COLORMAP, gData.get_awt_cmap());
 182         params.putIfNull(DEPTH, gData.get_awt_depth());
 183         params.putIfNull(VISUAL_CLASS, Integer.valueOf((int)XlibWrapper.InputOutput));
 184         params.putIfNull(VISUAL, visInfo.get_visual());
 185         params.putIfNull(VALUE_MASK, XlibWrapper.CWBorderPixel | XlibWrapper.CWEventMask | XlibWrapper.CWColormap);
 186         Long parentWindow = (Long)params.get(PARENT_WINDOW);
 187         if (parentWindow == null || parentWindow.longValue() == 0) {
 188             XToolkit.awtLock();
 189             try {
 190                 int screen = visInfo.get_screen();
 191                 if (screen != -1) {
 192                     params.add(PARENT_WINDOW, XlibWrapper.RootWindow(XToolkit.getDisplay(), screen));
 193                 } else {
 194                     params.add(PARENT_WINDOW, XToolkit.getDefaultRootWindow());
 195                 }
 196             } finally {
 197                 XToolkit.awtUnlock();
 198             }
 199         }
 200 
 201         paintArea = new XRepaintArea();
 202         if (target != null) {
 203             this.parent = getParentXWindowObject(target.getParent());
 204         }
 205 
 206         params.putIfNull(BACKING_STORE, XToolkit.getBackingStoreType());
 207 
 208         XToolkit.awtLock();
 209         try {
 210             if (wm_protocols == null) {
 211                 wm_protocols = XAtom.get("WM_PROTOCOLS");
 212                 wm_delete_window = XAtom.get("WM_DELETE_WINDOW");
 213                 wm_take_focus = XAtom.get("WM_TAKE_FOCUS");
 214             }
 215         }
 216         finally {
 217             XToolkit.awtUnlock();
 218         }
 219         winAttr = new XWindowAttributesData();
 220         savedState = XUtilConstants.WithdrawnState;
 221     }
 222 
 223     void postInit(XCreateWindowParams params) {
 224         super.postInit(params);
 225 
 226         setWMClass(getWMClass());
 227 
 228         surfaceData = graphicsConfig.createSurfaceData(this);
 229         Color c;
 230         if (target != null && (c = target.getBackground()) != null) {
 231             // We need a version of setBackground that does not call repaint !!
 232             // and one that does not get overridden. The problem is that in postInit
 233             // we call setBackground and we dont have all the stuff initialized to
 234             // do a full paint for most peers. So we cannot call setBackground in postInit.
 235             // instead we need to call xSetBackground.
 236             xSetBackground(c);
 237         }
 238     }
 239 
 240     public GraphicsConfiguration getGraphicsConfiguration() {
 241         if (graphicsConfig == null) {
 242             initGraphicsConfiguration();
 243         }
 244         return graphicsConfig;
 245     }
 246 
 247     public AwtGraphicsConfigData getGraphicsConfigurationData() {
 248         if (graphicsConfigData == null) {
 249             initGraphicsConfiguration();
 250         }
 251         return graphicsConfigData;
 252     }
 253 
 254     protected String[] getWMClass() {
 255         return new String[] {XToolkit.getCorrectXIDString(getClass().getName()), XToolkit.getAWTAppClassName()};
 256     }
 257 
 258     void setReparented(boolean newValue) {
 259         reparented = newValue;
 260     }
 261 
 262     boolean isReparented() {
 263         return reparented;
 264     }
 265 
 266     static long getParentWindowID(Component target) {
 267 
 268         ComponentPeer peer = target.getParent().getPeer();
 269         Component temp = target.getParent();
 270         while (!(peer instanceof XWindow))
 271         {
 272             temp = temp.getParent();
 273             peer = temp.getPeer();
 274         }
 275 
 276         if (peer != null && peer instanceof XWindow)
 277             return ((XWindow)peer).getContentWindow();
 278         else return 0;
 279     }
 280 
 281     protected PropMwmHints mwm_hints;
 282     protected static XAtom wm_protocols;
 283     protected static XAtom wm_delete_window;
 284     protected static XAtom wm_take_focus;
 285 
 286     private boolean stateChanged; // Indicates whether the value on savedState is valid
 287     private int savedState; // Holds last known state of the top-level window
 288 
 289     XWindowAttributesData winAttr;
 290 
 291     static XWindow getParentXWindowObject(Component target) {
 292         if (target == null) return null;
 293         Component temp = target.getParent();
 294         if (temp == null) return null;
 295         ComponentPeer peer = temp.getPeer();
 296         if (peer == null) return null;
 297         while ((peer != null) && !(peer instanceof XWindow))
 298         {
 299             temp = temp.getParent();
 300             peer = temp.getPeer();
 301         }
 302         if (peer != null && peer instanceof XWindow)
 303             return (XWindow) peer;
 304         else return null;
 305     }
 306 
 307 
 308     boolean isParentOf(XWindow win) {
 309         if (!(target instanceof Container) || win == null || win.getTarget() == null) {
 310             return false;
 311         }
 312         Container parent = ComponentAccessor.getParent_NoClientCode(win.target);
 313         while (parent != null && parent != target) {
 314             parent = ComponentAccessor.getParent_NoClientCode(parent);
 315         }
 316         return (parent == target);
 317     }
 318 
 319     public Object getTarget() {
 320         return target;
 321     }
 322     public Component getEventSource() {
 323         return target;
 324     }
 325 
 326     public ColorModel getColorModel(int transparency) {
 327         return graphicsConfig.getColorModel (transparency);
 328     }
 329 
 330     public ColorModel getColorModel() {
 331         if (graphicsConfig != null) {
 332             return graphicsConfig.getColorModel ();
 333         }
 334         else {
 335             return XToolkit.getStaticColorModel();
 336         }
 337     }
 338 
 339     Graphics getGraphics(SurfaceData surfData, Color afore, Color aback, Font afont) {
 340         if (surfData == null) return null;
 341 
 342         Component target = (Component) this.target;
 343 
 344         /* Fix for bug 4746122. Color and Font shouldn't be null */
 345         Color bgColor = aback;
 346         if (bgColor == null) {
 347             bgColor = SystemColor.window;
 348         }
 349         Color fgColor = afore;
 350         if (fgColor == null) {
 351             fgColor = SystemColor.windowText;
 352         }
 353         Font font = afont;
 354         if (font == null) {
 355             font = defaultFont;
 356         }
 357         return new SunGraphics2D(surfData, fgColor, bgColor, font);
 358     }
 359 
 360     public Graphics getGraphics() {
 361         return getGraphics(surfaceData,
 362                            target.getForeground(),
 363                            target.getBackground(),
 364                            target.getFont());
 365     }
 366 
 367     public FontMetrics getFontMetrics(Font font) {
 368         return Toolkit.getDefaultToolkit().getFontMetrics(font);
 369     }
 370 
 371     public Rectangle getTargetBounds() {
 372         return target.getBounds();
 373     }
 374 
 375     /**
 376      * Returns true if the event has been handled and should not be
 377      * posted to Java.
 378      */
 379     boolean prePostEvent(AWTEvent e) {
 380         return false;
 381     }
 382 
 383     static void sendEvent(final AWTEvent e) {
 384         PeerEvent pe = new PeerEvent(Toolkit.getDefaultToolkit(), new Runnable() {
 385                 public void run() {
 386                     AWTAccessor.getAWTEventAccessor().setPosted(e);
 387                     ((Component)e.getSource()).dispatchEvent(e);
 388                 }
 389             }, PeerEvent.ULTIMATE_PRIORITY_EVENT);
 390         if (focusLog.isLoggable(Level.FINER) && (e instanceof FocusEvent)) focusLog.finer("Sending " + e);
 391         XToolkit.postEvent(XToolkit.targetToAppContext(e.getSource()), pe);
 392     }
 393 
 394 
 395 /*
 396  * Post an event to the event queue.
 397  */
 398 // NOTE: This method may be called by privileged threads.
 399 //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 400     void postEvent(AWTEvent event) {
 401         XToolkit.postEvent(XToolkit.targetToAppContext(event.getSource()), event);
 402     }
 403 
 404     static void postEventStatic(AWTEvent event) {
 405         XToolkit.postEvent(XToolkit.targetToAppContext(event.getSource()), event);
 406     }
 407 
 408     public void postEventToEventQueue(final AWTEvent event) {
 409         //fix for 6239938 : Choice drop-down does not disappear when it loses focus, on XToolkit
 410         if (!prePostEvent(event)) {
 411             //event hasn't been handled and must be posted to EventQueue
 412             postEvent(event);
 413         }
 414     }
 415 
 416     // overriden in XCanvasPeer
 417     protected boolean doEraseBackground() {
 418         return true;
 419     }
 420 
 421     // We need a version of setBackground that does not call repaint !!
 422     // and one that does not get overridden. The problem is that in postInit
 423     // we call setBackground and we dont have all the stuff initialized to
 424     // do a full paint for most peers. So we cannot call setBackground in postInit.
 425     final public void xSetBackground(Color c) {
 426         XToolkit.awtLock();
 427         try {
 428             winBackground(c);
 429             // fix for 6558510: handle sun.awt.noerasebackground flag,
 430             // see doEraseBackground() and preInit() methods in XCanvasPeer
 431             if (!doEraseBackground()) {
 432                 return;
 433             }
 434             // 6304250: XAWT: Items in choice show a blue border on OpenGL + Solaris10 when background color is set
 435             // Note: When OGL is enabled, surfaceData.pixelFor() will not
 436             // return a pixel value appropriate for passing to
 437             // XSetWindowBackground().  Therefore, we will use the ColorModel
 438             // for this component in order to calculate a pixel value from
 439             // the given RGB value.
 440             ColorModel cm = getColorModel();
 441             int pixel = PixelConverter.instance.rgbToPixel(c.getRGB(), cm);
 442             XlibWrapper.XSetWindowBackground(XToolkit.getDisplay(), getContentWindow(), pixel);
 443         }
 444         finally {
 445             XToolkit.awtUnlock();
 446         }
 447     }
 448 
 449     public void setBackground(Color c) {
 450         xSetBackground(c);
 451     }
 452 
 453     Color backgroundColor;
 454     void winBackground(Color c) {
 455         backgroundColor = c;
 456     }
 457 
 458     public Color getWinBackground() {
 459         Color c = null;
 460 
 461         if (backgroundColor != null) {
 462             c = backgroundColor;
 463         } else if (parent != null) {
 464             c = parent.getWinBackground();
 465         }
 466 
 467         if (c instanceof SystemColor) {
 468             c = new Color(c.getRGB());
 469         }
 470 
 471         return c;
 472     }
 473 
 474     public boolean isEmbedded() {
 475         return embedded;
 476     }
 477 
 478     public final void repaint(int x,int y, int width, int height) {
 479         if (!isVisible()) {
 480             return;
 481         }
 482         Graphics g = getGraphics();
 483         if (g != null) {
 484             try {
 485                 g.setClip(x, y, width, height);
 486                 paint(g);
 487             } finally {
 488                 g.dispose();
 489             }
 490         }
 491     }
 492 
 493     public  void repaint() {
 494         repaint(0, 0, getWidth(), getHeight());
 495     }
 496 
 497     void paint(Graphics g) {
 498     }
 499 
 500     //used by Peers to avoid flickering withing paint()
 501     protected void flush(){
 502         XToolkit.awtLock();
 503         try {
 504             XlibWrapper.XFlush(XToolkit.getDisplay());
 505         } finally {
 506             XToolkit.awtUnlock();
 507         }
 508     }
 509 
 510     public void popup(int x, int y, int width, int height) {
 511         // TBD: grab the pointer
 512         xSetBounds(x, y, width, height);
 513     }
 514 
 515     public void handleExposeEvent(XEvent xev) {
 516         super.handleExposeEvent(xev);
 517         XExposeEvent xe = xev.get_xexpose();
 518         if (isEventDisabled(xev)) {
 519             return;
 520         }
 521         int x = xe.get_x();
 522         int y = xe.get_y();
 523         int w = xe.get_width();
 524         int h = xe.get_height();
 525 
 526         Component target = (Component)getEventSource();
 527 
 528         if (!ComponentAccessor.getIgnoreRepaint(target)
 529             && ComponentAccessor.getWidth(target) != 0
 530             && ComponentAccessor.getHeight(target) != 0)
 531         {
 532             postPaintEvent(target, x, y, w, h);
 533         }
 534     }
 535 
 536     public void postPaintEvent(Component target, int x, int y, int w, int h) {
 537         PaintEvent event = PaintEventDispatcher.getPaintEventDispatcher().
 538             createPaintEvent(target, x, y, w, h);
 539         if (event != null) {
 540             postEventToEventQueue(event);
 541         }
 542     }
 543 
 544     static int getModifiers(int state, int button, int keyCode) {
 545         int modifiers = 0;
 546 
 547         if (((state & XlibWrapper.ShiftMask) != 0) ^ (keyCode == KeyEvent.VK_SHIFT)) {
 548             modifiers |= InputEvent.SHIFT_DOWN_MASK;
 549         }
 550         if (((state & XlibWrapper.ControlMask) != 0) ^ (keyCode == KeyEvent.VK_CONTROL)) {
 551             modifiers |= InputEvent.CTRL_DOWN_MASK;
 552         }
 553         if (((state & XToolkit.metaMask) != 0) ^ (keyCode == KeyEvent.VK_META)) {
 554             modifiers |= InputEvent.META_DOWN_MASK;
 555         }
 556         if (((state & XToolkit.altMask) != 0) ^ (keyCode == KeyEvent.VK_ALT)) {
 557             modifiers |= InputEvent.ALT_DOWN_MASK;
 558         }
 559         if (((state & XToolkit.modeSwitchMask) != 0) ^ (keyCode == KeyEvent.VK_ALT_GRAPH)) {
 560             modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK;
 561         }
 562         if (((state & XlibWrapper.Button1Mask) != 0) ^ (button == MouseEvent.BUTTON1)) {
 563             modifiers |= InputEvent.BUTTON1_DOWN_MASK;
 564         }
 565         if (((state & XlibWrapper.Button2Mask) != 0) ^ (button == MouseEvent.BUTTON2)) {
 566             modifiers |= InputEvent.BUTTON2_DOWN_MASK;
 567         }
 568         if (((state & XlibWrapper.Button3Mask) != 0) ^ (button == MouseEvent.BUTTON3)) {
 569             modifiers |= InputEvent.BUTTON3_DOWN_MASK;
 570         }
 571         return modifiers;
 572     }
 573 
 574     static int getXModifiers(AWTKeyStroke stroke) {
 575         int mods = stroke.getModifiers();
 576         int res = 0;
 577         if ((mods & (InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK)) != 0) {
 578             res |= XToolkit.ShiftMask;
 579         }
 580         if ((mods & (InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK)) != 0) {
 581             res |= XToolkit.ControlMask;
 582         }
 583         if ((mods & (InputEvent.ALT_DOWN_MASK | InputEvent.ALT_MASK)) != 0) {
 584             res |= XToolkit.altMask;
 585         }
 586         if ((mods & (InputEvent.META_DOWN_MASK | InputEvent.META_MASK)) != 0) {
 587             res |= XToolkit.metaMask;
 588         }
 589         if ((mods & (InputEvent.ALT_GRAPH_DOWN_MASK | InputEvent.ALT_GRAPH_MASK)) != 0) {
 590             res |= XToolkit.modeSwitchMask;
 591         }
 592         return res;
 593     }
 594 
 595     private static int getButtonMask(long mouseButton) {
 596         if (mouseButton == XlibWrapper.Button1) {
 597             return XlibWrapper.Button1Mask;
 598         } else if (mouseButton == XlibWrapper.Button2) {
 599             return XlibWrapper.Button2Mask;
 600         } else if (mouseButton == XlibWrapper.Button3) {
 601             return XlibWrapper.Button3Mask;
 602         }
 603         return 0;
 604     }
 605 
 606     /**
 607      * Returns true if this event is disabled and shouldn't be passed to Java.
 608      * Default implementation returns false for all events.
 609      */
 610     static int getRightButtonNumber() {
 611         if (rbutton == 0) { // not initialized yet
 612             XToolkit.awtLock();
 613             try {
 614                 rbutton = XlibWrapper.XGetPointerMapping(XToolkit.getDisplay(), XlibWrapper.ibuffer, 3);
 615             }
 616             finally {
 617                 XToolkit.awtUnlock();
 618             }
 619         }
 620         return rbutton;
 621     }
 622 
 623     static int getMouseMovementSmudge() {
 624         //TODO: It's possible to read corresponding settings
 625         return AWT_MULTICLICK_SMUDGE;
 626     }
 627 
 628     public void handleButtonPressRelease(XEvent xev) {
 629         super.handleButtonPressRelease(xev);
 630         XButtonEvent xbe = xev.get_xbutton();
 631         if (isEventDisabled(xev)) {
 632             return;
 633         }
 634         if (eventLog.isLoggable(Level.FINE)) eventLog.fine(xbe.toString());
 635         long when;
 636         int modifiers;
 637         boolean popupTrigger = false;
 638         int button=0;
 639         boolean wheel_mouse = false;
 640         long lbutton = xbe.get_button();
 641         int type = xev.get_type();
 642         when = xbe.get_time();
 643         long jWhen = XToolkit.nowMillisUTC_offset(when);
 644 
 645         int x = xbe.get_x();
 646         int y = xbe.get_y();
 647         if (xev.get_xany().get_window() != window) {
 648             Point localXY = toLocal(xbe.get_x_root(), xbe.get_y_root());
 649             x = localXY.x;
 650             y = localXY.y;
 651         }
 652 
 653         if (type == XlibWrapper.ButtonPress) {
 654             XWindow lastWindow = (lastWindowRef != null) ? ((XWindow)lastWindowRef.get()):(null);
 655             /*
 656                multiclick checking
 657             */
 658             if (eventLog.isLoggable(Level.FINEST)) eventLog.finest("lastWindow = " + lastWindow + ", lastButton "
 659                                                                    + lastButton + ", lastTime " + lastTime + ", multiClickTime "
 660                                                                    + XToolkit.getMultiClickTime());
 661             if (lastWindow == this && lastButton == lbutton && (when - lastTime) < XToolkit.getMultiClickTime()) {
 662                 clickCount++;
 663             } else {
 664                 clickCount = 1;
 665                 lastWindowRef = new WeakReference(this);
 666                 lastButton = lbutton;
 667                 lastX = x;
 668                 lastY = y;
 669             }
 670             lastTime = when;
 671 
 672 
 673             /*
 674                Check for popup trigger !!
 675             */
 676             if (lbutton == getRightButtonNumber() || lbutton > 2) {
 677                 popupTrigger = true;
 678             } else {
 679                 popupTrigger = false;
 680             }
 681         }
 682 
 683         if (lbutton == XlibWrapper.Button1)
 684             button = MouseEvent.BUTTON1;
 685         else if (lbutton ==  XlibWrapper.Button2 )
 686             button = MouseEvent.BUTTON2;
 687         else if (lbutton == XlibWrapper.Button3)
 688             button = MouseEvent.BUTTON3;
 689         else if (lbutton == XlibWrapper.Button4) {
 690             button = 4;
 691             wheel_mouse = true;
 692         } else if (lbutton == XlibWrapper.Button5) {
 693             button = 5;
 694             wheel_mouse = true;
 695         }
 696 
 697         modifiers = getModifiers(xbe.get_state(),button,0);
 698 
 699         if (!wheel_mouse) {
 700             MouseEvent me = new MouseEvent((Component)getEventSource(),
 701                                            type == XlibWrapper.ButtonPress ? MouseEvent.MOUSE_PRESSED : MouseEvent.MOUSE_RELEASED,
 702                                            jWhen,modifiers, x, y,
 703                                            xbe.get_x_root(),
 704                                            xbe.get_y_root(),
 705                                            clickCount,popupTrigger,button);
 706 
 707             postEventToEventQueue(me);
 708 
 709             if (((mouseDragState & getButtonMask(lbutton)) == 0) && // No up-button in the drag-state
 710                 (type == XlibWrapper.ButtonRelease))
 711             {
 712                 postEventToEventQueue(me = new MouseEvent((Component)getEventSource(),
 713                                                      MouseEvent.MOUSE_CLICKED,
 714                                                      jWhen,
 715                                                      modifiers,
 716                                                      x, y,
 717                                                      xbe.get_x_root(),
 718                                                      xbe.get_y_root(),
 719                                                      clickCount,
 720                                                      false, button));
 721             }
 722 
 723         }
 724         else {
 725             if (xev.get_type() == XlibWrapper.ButtonPress) {
 726                 MouseWheelEvent mwe = new MouseWheelEvent((Component)getEventSource(),MouseEvent.MOUSE_WHEEL, jWhen,
 727                                                           modifiers,
 728                                                           x, y,
 729                                                           xbe.get_x_root(),
 730                                                           xbe.get_y_root(),
 731                                                           clickCount,false,MouseWheelEvent.WHEEL_UNIT_SCROLL,
 732                                                           3,button==4 ?  -1 : 1);
 733                 postEventToEventQueue(mwe);
 734             }
 735         }
 736 
 737         mouseDragState &= ~getButtonMask(lbutton); // Exclude the up-button from the drag-state
 738     }
 739 
 740     public void handleMotionNotify(XEvent xev) {
 741         super.handleMotionNotify(xev);
 742         XMotionEvent xme = xev.get_xmotion();
 743         if (isEventDisabled(xev)) {
 744             return;
 745         }
 746 
 747         int mouseKeyState = (xme.get_state() & (Button1Mask | Button2Mask | Button3Mask));
 748         boolean isDragging = (mouseKeyState != 0);
 749         int mouseEventType = 0;
 750 
 751         if (isDragging) {
 752             mouseEventType = MouseEvent.MOUSE_DRAGGED;
 753         } else {
 754             mouseEventType = MouseEvent.MOUSE_MOVED;
 755         }
 756 
 757         /*
 758            Fix for 6176814 .  Add multiclick checking.
 759         */
 760         int x = xme.get_x();
 761         int y = xme.get_y();
 762         XWindow lastWindow = (lastWindowRef != null) ? ((XWindow)lastWindowRef.get()):(null);
 763 
 764         if (!(lastWindow == this &&
 765               (xme.get_time() - lastTime) < XToolkit.getMultiClickTime()  &&
 766               (Math.abs(lastX - x) < AWT_MULTICLICK_SMUDGE &&
 767                Math.abs(lastY - y) < AWT_MULTICLICK_SMUDGE))) {
 768           clickCount = 0;
 769           lastWindowRef = null;
 770           mouseDragState = mouseKeyState;
 771           lastTime = 0;
 772           lastX = 0;
 773           lastY = 0;
 774         }
 775 
 776         long jWhen = XToolkit.nowMillisUTC_offset(xme.get_time());
 777         int modifiers = getModifiers(xme.get_state(), 0, 0);
 778         boolean popupTrigger = false;
 779 
 780         Component source = (Component)getEventSource();
 781 
 782         if (xme.get_window() != window) {
 783             Point localXY = toLocal(xme.get_x_root(), xme.get_y_root());
 784             x = localXY.x;
 785             y = localXY.y;
 786         }
 787         /* Fix for 5039416.
 788          * According to canvas.c we shouldn't post any MouseEvent if mouse is dragging and clickCount!=0.
 789          */
 790         if ((isDragging && clickCount == 0) || !isDragging) {
 791             MouseEvent mme = new MouseEvent(source, mouseEventType, jWhen,
 792                                             modifiers, x, y, xme.get_x_root(), xme.get_y_root(),
 793                                             clickCount, popupTrigger, MouseEvent.NOBUTTON);
 794             postEventToEventQueue(mme);
 795         }
 796     }
 797 
 798 
 799     // REMIND: need to implement looking for disabled events
 800     public native boolean x11inputMethodLookupString(long event, long [] keysymArray);
 801     native boolean haveCurrentX11InputMethodInstance();
 802 
 803     private boolean mouseAboveMe;
 804 
 805     public boolean isMouseAbove() {
 806         synchronized (getStateLock()) {
 807             return mouseAboveMe;
 808         }
 809     }
 810     protected void setMouseAbove(boolean above) {
 811         synchronized (getStateLock()) {
 812             mouseAboveMe = above;
 813         }
 814     }
 815 
 816     protected void enterNotify(long window) {
 817         if (window == getWindow()) {
 818             setMouseAbove(true);
 819         }
 820     }
 821     protected void leaveNotify(long window) {
 822         if (window == getWindow()) {
 823             setMouseAbove(false);
 824         }
 825     }
 826 
 827     public void handleXCrossingEvent(XEvent xev) {
 828         super.handleXCrossingEvent(xev);
 829         XCrossingEvent xce = xev.get_xcrossing();
 830 
 831         if (eventLog.isLoggable(Level.FINEST)) eventLog.finest(xce.toString());
 832 
 833         if (xce.get_type() == XConstants.EnterNotify) {
 834             enterNotify(xce.get_window());
 835         } else { // LeaveNotify:
 836             leaveNotify(xce.get_window());
 837         }
 838 
 839         // Skip event If it was caused by a grab
 840         // This is needed because on displays with focus-follows-mouse on MousePress X system generates
 841         // two XCrossing events with mode != NormalNotify. First of them notifies that the mouse has left
 842         // current component. Second one notifies that it has entered into the same component.
 843         // This looks like the window under the mouse has actually changed and Java handle these  events
 844         // accordingly. This leads to impossibility to make a double click on Component (6404708)
 845         XWindowPeer toplevel = getToplevelXWindow();
 846         if (toplevel != null && !toplevel.isModalBlocked()){
 847             if (xce.get_mode() != NotifyNormal) {
 848                 // 6404708 : need update cursor in accordance with skipping Leave/EnterNotify event
 849                 // whereas it doesn't need to handled further.
 850                 if (xce.get_type() == EnterNotify) {
 851                     XAwtState.setComponentMouseEntered(getEventSource());
 852                     XGlobalCursorManager.nativeUpdateCursor(getEventSource());
 853                 } else { // LeaveNotify:
 854                     XAwtState.setComponentMouseEntered(null);
 855                 }
 856                 return;
 857             }
 858         }
 859         // X sends XCrossing to all hierarchy so if the edge of child equals to
 860         // ancestor and mouse enters child, the ancestor will get an event too.
 861         // From java point the event is bogus as ancestor is obscured, so if
 862         // the child can get java event itself, we skip it on ancestor.
 863         long childWnd = xce.get_subwindow();
 864         if (childWnd != None) {
 865             XBaseWindow child = XToolkit.windowToXWindow(childWnd);
 866             if (child != null && child instanceof XWindow &&
 867                 !child.isEventDisabled(xev))
 868             {
 869                 return;
 870             }
 871         }
 872 
 873         // Remember old component with mouse to have the opportunity to send it MOUSE_EXITED.
 874         final Component compWithMouse = XAwtState.getComponentMouseEntered();
 875         if (toplevel != null) {
 876             if(!toplevel.isModalBlocked()){
 877                 if (xce.get_type() == EnterNotify) {
 878                     // Change XAwtState's component mouse entered to the up-to-date one before requesting
 879                     // to update the cursor since XAwtState.getComponentMouseEntered() is used when the
 880                     // cursor is updated (in XGlobalCursorManager.findHeavyweightUnderCursor()).
 881                     XAwtState.setComponentMouseEntered(getEventSource());
 882                     XGlobalCursorManager.nativeUpdateCursor(getEventSource());
 883                 } else { // LeaveNotify:
 884                     XAwtState.setComponentMouseEntered(null);
 885                 }
 886             } else {
 887                 ((XComponentPeer) ComponentAccessor.getPeer(target))
 888                     .pSetCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
 889             }
 890         }
 891 
 892         if (isEventDisabled(xev)) {
 893             return;
 894         }
 895 
 896         long jWhen = XToolkit.nowMillisUTC_offset(xce.get_time());
 897         int modifiers = getModifiers(xce.get_state(),0,0);
 898         int clickCount = 0;
 899         boolean popupTrigger = false;
 900         int x = xce.get_x();
 901         int y = xce.get_y();
 902         if (xce.get_window() != window) {
 903             Point localXY = toLocal(xce.get_x_root(), xce.get_y_root());
 904             x = localXY.x;
 905             y = localXY.y;
 906         }
 907 
 908         // This code tracks boundary crossing and ensures MOUSE_ENTER/EXIT
 909         // are posted in alternate pairs
 910         if (compWithMouse != null) {
 911             MouseEvent me = new MouseEvent(compWithMouse,
 912                 MouseEvent.MOUSE_EXITED, jWhen, modifiers, xce.get_x(),
 913                 xce.get_y(), xce.get_x_root(), xce.get_y_root(), clickCount, popupTrigger,
 914                 MouseEvent.NOBUTTON);
 915             postEventToEventQueue(me);
 916             eventLog.finest("Clearing last window ref");
 917             lastWindowRef = null;
 918         }
 919         if (xce.get_type() == EnterNotify) {
 920             MouseEvent me = new MouseEvent(getEventSource(), MouseEvent.MOUSE_ENTERED,
 921                 jWhen, modifiers, xce.get_x(), xce.get_y(), xce.get_x_root(), xce.get_y_root(), clickCount,
 922                 popupTrigger, MouseEvent.NOBUTTON);
 923             postEventToEventQueue(me);
 924         }
 925     }
 926 
 927     public void doLayout(int x, int y, int width, int height) {}
 928 
 929     public void handleConfigureNotifyEvent(XEvent xev) {
 930         Rectangle oldBounds = getBounds();
 931 
 932         super.handleConfigureNotifyEvent(xev);
 933         if (insLog.isLoggable(Level.FINER)) {
 934             insLog.log(Level.FINER, "Configure, {0}, event disabled: {1}",
 935                        new Object[] {String.valueOf(xev), isEventDisabled(xev)});
 936         }
 937         if (isEventDisabled(xev)) {
 938             return;
 939         }
 940 
 941         long eventWindow = xev.get_xany().get_window();
 942 
 943 //  if ( Check if it's a resize, a move, or a stacking order change )
 944 //  {
 945         Rectangle bounds = getBounds();
 946         if (!bounds.getSize().equals(oldBounds.getSize())) {
 947             postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_RESIZED));
 948         }
 949         if (!bounds.getLocation().equals(oldBounds.getLocation())) {
 950             postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_MOVED));
 951         }
 952 //  }
 953     }
 954 
 955     public void handleMapNotifyEvent(XEvent xev) {
 956         super.handleMapNotifyEvent(xev);
 957         if (log.isLoggable(Level.FINE)) {
 958             log.log(Level.FINE, "Mapped {0}", new Object[] {String.valueOf(this)});
 959         }
 960         if (isEventDisabled(xev)) {
 961             return;
 962         }
 963         ComponentEvent ce;
 964 
 965         ce = new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_SHOWN);
 966         postEventToEventQueue(ce);
 967     }
 968 
 969     public void handleUnmapNotifyEvent(XEvent xev) {
 970         super.handleUnmapNotifyEvent(xev);
 971         if (isEventDisabled(xev)) {
 972             return;
 973         }
 974         ComponentEvent ce;
 975 
 976         ce = new ComponentEvent(target, ComponentEvent.COMPONENT_HIDDEN);
 977         postEventToEventQueue(ce);
 978     }
 979 
 980     private void dumpKeysymArray(XKeyEvent ev) {
 981         keyEventLog.fine("  "+Long.toHexString(XlibWrapper.XKeycodeToKeysym(XToolkit.getDisplay(), ev.get_keycode(), 0))+
 982                          "\n        "+Long.toHexString(XlibWrapper.XKeycodeToKeysym(XToolkit.getDisplay(), ev.get_keycode(), 1))+
 983                          "\n        "+Long.toHexString(XlibWrapper.XKeycodeToKeysym(XToolkit.getDisplay(), ev.get_keycode(), 2))+
 984                          "\n        "+Long.toHexString(XlibWrapper.XKeycodeToKeysym(XToolkit.getDisplay(), ev.get_keycode(), 3)));
 985     }
 986     /**
 987        Return unicode character or 0 if no correspondent character found.
 988        Parameter is a keysym basically from keysymdef.h
 989        XXX: how about vendor keys? Is there some with Unicode value and not in the list?
 990     */
 991     char keysymToUnicode( long keysym, int state ) {
 992         return XKeysym.convertKeysym( keysym, state );
 993     }
 994     int keyEventType2Id( int xEventType ) {
 995         return xEventType == XConstants.KeyPress ? java.awt.event.KeyEvent.KEY_PRESSED :
 996                xEventType == XConstants.KeyRelease ? java.awt.event.KeyEvent.KEY_RELEASED : 0;
 997     }
 998     static private long xkeycodeToKeysym(XKeyEvent ev) {
 999         return XKeysym.getKeysym( ev );
1000     }
1001     void logIncomingKeyEvent(XKeyEvent ev) {
1002         keyEventLog.fine("--XWindow.java:handleKeyEvent:"+ev);
1003         dumpKeysymArray(ev);
1004         keyEventLog.fine("XXXXXXXXXXXXXX javakeycode will be most probably:0x"+ Integer.toHexString(XKeysym.getJavaKeycodeOnly(ev)));
1005     }
1006     public void handleKeyPress(XEvent xev) {
1007         super.handleKeyPress(xev);
1008         XKeyEvent ev = xev.get_xkey();
1009         if (eventLog.isLoggable(Level.FINE)) eventLog.fine(ev.toString());
1010         if (isEventDisabled(xev)) {
1011             return;
1012         }
1013         handleKeyPress(ev);
1014     }
1015     // called directly from this package, unlike handleKeyRelease.
1016     // un-final it if you need to override it in a subclass.
1017     final void handleKeyPress(XKeyEvent ev) {
1018         int keycode = java.awt.event.KeyEvent.VK_UNDEFINED;
1019         long keysym[] = new long[2];
1020         char unicodeKey = 0;
1021         keysym[0] = NoSymbol;
1022 
1023         if (keyEventLog.isLoggable(Level.FINE)) {
1024             logIncomingKeyEvent( ev );
1025         }
1026         if ( //TODO check if there's an active input method instance
1027              // without calling a native method. Is it necessary though?
1028             haveCurrentX11InputMethodInstance()) {
1029             if (x11inputMethodLookupString(ev.pData, keysym)) {
1030                 if (keyEventLog.isLoggable(Level.FINE)) {
1031                     keyEventLog.fine("--XWindow.java XIM did process event; return; dec keysym processed:"+(keysym[0])+
1032                                    "; hex keysym processed:"+Long.toHexString(keysym[0])
1033                                    );
1034                 }
1035                 return;
1036             }else {
1037                 unicodeKey = keysymToUnicode( keysym[0], ev.get_state() );
1038                 if (keyEventLog.isLoggable(Level.FINE)) {
1039                     keyEventLog.fine("--XWindow.java XIM did NOT process event, hex keysym:"+Long.toHexString(keysym[0])+"\n"+
1040                                      "                                         unicode key:"+Integer.toHexString((int)unicodeKey));
1041                 }
1042             }
1043         }else  {
1044             // No input method instance found. For example, there's a Java Input Method.
1045             // Produce do-it-yourself keysym and perhaps unicode character.
1046             keysym[0] = xkeycodeToKeysym(ev);
1047             unicodeKey = keysymToUnicode( keysym[0], ev.get_state() );
1048             if (keyEventLog.isLoggable(Level.FINE)) {
1049                 keyEventLog.fine("--XWindow.java XIM is absent;             hex keysym:"+Long.toHexString(keysym[0])+"\n"+
1050                                  "                                         unicode key:"+Integer.toHexString((int)unicodeKey));
1051             }
1052         }
1053         // Keysym should be converted to Unicode, if possible and necessary,
1054         // and Java KeyEvent keycode should be calculated.
1055         // For press we should post pressed & typed Java events.
1056         //
1057         // Press event might be not processed to this time because
1058         //  (1) either XIM could not handle it or
1059         //  (2) it was Latin 1:1 mapping.
1060         //
1061         XKeysym.Keysym2JavaKeycode jkc = XKeysym.getJavaKeycode(ev);
1062         if( jkc == null ) {
1063             jkc = new XKeysym.Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN);
1064         }
1065         if (keyEventLog.isLoggable(Level.FINE)) {
1066             keyEventLog.fine(">>>Fire Event:"+
1067                (ev.get_type() == XConstants.KeyPress ? "KEY_PRESSED; " : "KEY_RELEASED; ")+
1068                "jkeycode:decimal="+jkc.getJavaKeycode()+
1069                ", hex=0x"+Integer.toHexString(jkc.getJavaKeycode())+"; "
1070             );
1071         }
1072         postKeyEvent( java.awt.event.KeyEvent.KEY_PRESSED,
1073                           ev.get_time(),
1074                           jkc.getJavaKeycode(),
1075                           (unicodeKey == 0 ? java.awt.event.KeyEvent.CHAR_UNDEFINED : unicodeKey),
1076                           jkc.getKeyLocation(),
1077                           ev.get_state(),ev.getPData(), XKeyEvent.getSize());
1078         if( unicodeKey > 0 ) {
1079                 keyEventLog.fine("fire _TYPED on "+unicodeKey);
1080                 postKeyEvent( java.awt.event.KeyEvent.KEY_TYPED,
1081                               ev.get_time(),
1082                               java.awt.event.KeyEvent.VK_UNDEFINED,
1083                               unicodeKey,
1084                               java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN,
1085                               ev.get_state(),ev.getPData(), XKeyEvent.getSize());
1086         }
1087 
1088 
1089     }
1090 
1091     public void handleKeyRelease(XEvent xev) {
1092         super.handleKeyRelease(xev);
1093         XKeyEvent ev = xev.get_xkey();
1094         if (eventLog.isLoggable(Level.FINE)) eventLog.fine(ev.toString());
1095         if (isEventDisabled(xev)) {
1096             return;
1097         }
1098         handleKeyRelease(ev);
1099     }
1100     // un-private it if you need to call it from elsewhere
1101     private void handleKeyRelease(XKeyEvent ev) {
1102         int keycode = java.awt.event.KeyEvent.VK_UNDEFINED;
1103         long keysym[] = new long[2];
1104         char unicodeKey = 0;
1105         keysym[0] = NoSymbol;
1106 
1107         if (keyEventLog.isLoggable(Level.FINE)) {
1108             logIncomingKeyEvent( ev );
1109         }
1110         // Keysym should be converted to Unicode, if possible and necessary,
1111         // and Java KeyEvent keycode should be calculated.
1112         // For release we should post released event.
1113         //
1114         XKeysym.Keysym2JavaKeycode jkc = XKeysym.getJavaKeycode(ev);
1115         if( jkc == null ) {
1116             jkc = new XKeysym.Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN);
1117         }
1118         if (keyEventLog.isLoggable(Level.FINE)) {
1119             keyEventLog.fine(">>>Fire Event:"+
1120                (ev.get_type() == XConstants.KeyPress ? "KEY_PRESSED; " : "KEY_RELEASED; ")+
1121                "jkeycode:decimal="+jkc.getJavaKeycode()+
1122                ", hex=0x"+Integer.toHexString(jkc.getJavaKeycode())+"; "
1123             );
1124         }
1125         // We obtain keysym from IM and derive unicodeKey from it for KeyPress only.
1126         // We used to cache that value and retrieve it on KeyRelease,
1127         // but in case for example of a dead key+vowel pair, a vowel after a deadkey
1128         // might never be cached before.
1129         // Also, switching between keyboard layouts, we might cache a wrong letter.
1130         // That's why we use the same procedure as if there was no IM instance: do-it-yourself unicode.
1131         unicodeKey = keysymToUnicode( xkeycodeToKeysym(ev), ev.get_state() );
1132 
1133         postKeyEvent(  java.awt.event.KeyEvent.KEY_RELEASED,
1134                           ev.get_time(),
1135                           jkc.getJavaKeycode(),
1136                           (unicodeKey == 0 ? java.awt.event.KeyEvent.CHAR_UNDEFINED : unicodeKey),
1137                           jkc.getKeyLocation(),
1138                           ev.get_state(),ev.getPData(), XKeyEvent.getSize());
1139 
1140     }
1141 
1142     /*
1143      * XmNiconic and Map/UnmapNotify (that XmNiconic relies on) are
1144      * unreliable, since mapping changes can happen for a virtual desktop
1145      * switch or MacOS style shading that became quite popular under X as
1146      * well.  Yes, it probably should not be this way, as it violates
1147      * ICCCM, but reality is that quite a lot of window managers abuse
1148      * mapping state.
1149      */
1150     int getWMState() {
1151         if (stateChanged) {
1152             stateChanged = false;
1153             WindowPropertyGetter getter =
1154                 new WindowPropertyGetter(window, XWM.XA_WM_STATE, 0, 1, false,
1155                                          XWM.XA_WM_STATE);
1156             try {
1157                 int status = getter.execute();
1158                 if (status != XConstants.Success || getter.getData() == 0) {
1159                     return savedState = XUtilConstants.WithdrawnState;
1160                 }
1161 
1162                 if (getter.getActualType() != XWM.XA_WM_STATE.getAtom() && getter.getActualFormat() != 32) {
1163                     return savedState = XUtilConstants.WithdrawnState;
1164                 }
1165                 savedState = (int)Native.getCard32(getter.getData());
1166             } finally {
1167                 getter.dispose();
1168             }
1169         }
1170         return savedState;
1171     }
1172 
1173     /**
1174      * Override this methods to get notifications when top-level window state changes. The state is
1175      * meant in terms of ICCCM: WithdrawnState, IconicState, NormalState
1176      */
1177     protected void stateChanged(long time, int oldState, int newState) {
1178     }
1179 
1180     @Override
1181     public void handlePropertyNotify(XEvent xev) {
1182         super.handlePropertyNotify(xev);
1183         XPropertyEvent ev = xev.get_xproperty();
1184         if (ev.get_atom() == XWM.XA_WM_STATE.getAtom()) {
1185             // State has changed, invalidate saved value
1186             stateChanged = true;
1187             stateChanged(ev.get_time(), savedState, getWMState());
1188         }
1189     }
1190 
1191     public void reshape(Rectangle bounds) {
1192         reshape(bounds.x, bounds.y, bounds.width, bounds.height);
1193     }
1194 
1195     public void reshape(int x, int y, int width, int height) {
1196         if (width <= 0) {
1197             width = 1;
1198         }
1199         if (height <= 0) {
1200             height = 1;
1201         }
1202         this.x = x;
1203         this.y = y;
1204         this.width = width;
1205         this.height = height;
1206         xSetBounds(x, y, width, height);
1207         // Fixed 6322593, 6304251, 6315137:
1208         // XWindow's SurfaceData should be invalidated and recreated as part
1209         // of the process of resizing the window
1210         // see the evaluation of the bug 6304251 for more information
1211         validateSurface();
1212         layout();
1213     }
1214 
1215     public void layout() {}
1216 
1217     boolean isShowing() {
1218         return visible;
1219     }
1220 
1221     boolean isResizable() {
1222         return true;
1223     }
1224 
1225     boolean isLocationByPlatform() {
1226         return false;
1227     }
1228 
1229     void updateSizeHints() {
1230         updateSizeHints(x, y, width, height);
1231     }
1232 
1233     void updateSizeHints(int x, int y, int width, int height) {
1234         long flags = XlibWrapper.PSize | (isLocationByPlatform() ? 0 : (XlibWrapper.PPosition | XlibWrapper.USPosition));
1235         if (!isResizable()) {
1236             if (log.isLoggable(Level.FINER)) {
1237                 log.log(Level.FINER, "Window {0} is not resizable", new Object[] {String.valueOf(this)});
1238             }
1239             flags |= XlibWrapper.PMinSize | XlibWrapper.PMaxSize;
1240         } else {
1241             if (log.isLoggable(Level.FINER)) {
1242                 log.log(Level.FINER, "Window {0} is resizable", new Object[] {String.valueOf(this)});
1243             }
1244         }
1245         setSizeHints(flags, x, y, width, height);
1246     }
1247 
1248     void updateSizeHints(int x, int y) {
1249         long flags = isLocationByPlatform() ? 0 : (XlibWrapper.PPosition | XlibWrapper.USPosition);
1250         if (!isResizable()) {
1251             if (log.isLoggable(Level.FINER)) {
1252                 log.log(Level.FINER, "Window {0} is not resizable", new Object[] {String.valueOf(this)});
1253             }
1254             flags |= XlibWrapper.PMinSize | XlibWrapper.PMaxSize | XlibWrapper.PSize;
1255         } else {
1256             if (log.isLoggable(Level.FINER)) {
1257                 log.log(Level.FINER, "Window {0} is resizable", new Object[] {String.valueOf(this)});
1258             }
1259         }
1260         setSizeHints(flags, x, y, width, height);
1261     }
1262 
1263       void validateSurface() {
1264         if ((width != oldWidth) || (height != oldHeight)) {
1265             SurfaceData oldData = surfaceData;
1266             if (oldData != null) {
1267                 surfaceData = graphicsConfig.createSurfaceData(this);
1268                 oldData.invalidate();
1269             }
1270             oldWidth = width;
1271             oldHeight = height;
1272         }
1273     }
1274 
1275     public SurfaceData getSurfaceData() {
1276         return surfaceData;
1277     }
1278 
1279     public void dispose() {
1280         SurfaceData oldData = surfaceData;
1281         surfaceData = null;
1282         if (oldData != null) {
1283             oldData.invalidate();
1284         }
1285         XToolkit.targetDisposedPeer(target, this);
1286         destroy();
1287     }
1288 
1289     public Point getLocationOnScreen() {
1290         synchronized (target.getTreeLock()) {
1291             Component comp = target;
1292 
1293             while (comp != null && !(comp instanceof Window)) {
1294                 comp = ComponentAccessor.getParent_NoClientCode(comp);
1295             }
1296 
1297             // applets, embedded, etc - translate directly
1298             // XXX: override in subclass?
1299             if (comp == null || comp instanceof sun.awt.EmbeddedFrame) {
1300                 return toGlobal(0, 0);
1301             }
1302 
1303             XToolkit.awtLock();
1304             try {
1305                 Object wpeer = XToolkit.targetToPeer(comp);
1306                 if (wpeer == null
1307                     || !(wpeer instanceof XDecoratedPeer)
1308                     || ((XDecoratedPeer)wpeer).configure_seen)
1309                 {
1310                     return toGlobal(0, 0);
1311                 }
1312 
1313                 // wpeer is an XDecoratedPeer not yet fully adopted by WM
1314                 Point pt = toOtherWindow(getContentWindow(),
1315                                          ((XDecoratedPeer)wpeer).getContentWindow(),
1316                                          0, 0);
1317 
1318                 if (pt == null) {
1319                     pt = new Point(((XBaseWindow)wpeer).getAbsoluteX(), ((XBaseWindow)wpeer).getAbsoluteY());
1320                 }
1321                 pt.x += comp.getX();
1322                 pt.y += comp.getY();
1323                 return pt;
1324             } finally {
1325                 XToolkit.awtUnlock();
1326             }
1327         }
1328     }
1329 
1330 
1331     static void setBData(KeyEvent e, byte[] data) {
1332         AWTAccessor.getAWTEventAccessor().setBData(e, data);
1333     }
1334 
1335     public void postKeyEvent(int id, long when, int keyCode, char keyChar,
1336         int keyLocation, int state, long event, int eventSize)
1337     {
1338         long jWhen = XToolkit.nowMillisUTC_offset(when);
1339         int modifiers = getModifiers(state, 0, keyCode);
1340         KeyEvent ke = new KeyEvent((Component)getEventSource(), id, jWhen,
1341                                    modifiers, keyCode, keyChar, keyLocation);
1342         if (event != 0) {
1343             byte[] data = Native.toBytes(event, eventSize);
1344             setBData(ke, data);
1345         }
1346         postEventToEventQueue(ke);
1347     }
1348 
1349     static native int getAWTKeyCodeForKeySym(int keysym);
1350     static native int getKeySymForAWTKeyCode(int keycode);
1351 
1352     /* These two methods are actually applicable to toplevel windows only.
1353      * However, the functionality is required by both the XWindowPeer and
1354      * XWarningWindow, both of which have the XWindow as a common ancestor.
1355      * See XWM.setMotifDecor() for details.
1356      */
1357     public PropMwmHints getMWMHints() {
1358         if (mwm_hints == null) {
1359             mwm_hints = new PropMwmHints();
1360             if (!XWM.XA_MWM_HINTS.getAtomData(getWindow(), mwm_hints.pData, MWMConstants.PROP_MWM_HINTS_ELEMENTS)) {
1361                 mwm_hints.zero();
1362             }
1363         }
1364         return mwm_hints;
1365     }
1366 
1367     public void setMWMHints(PropMwmHints hints) {
1368         mwm_hints = hints;
1369         if (hints != null) {
1370             XWM.XA_MWM_HINTS.setAtomData(getWindow(), mwm_hints.pData, MWMConstants.PROP_MWM_HINTS_ELEMENTS);
1371         }
1372     }
1373 
1374     protected final void initWMProtocols() {
1375         wm_protocols.setAtomListProperty(this, getWMProtocols());
1376     }
1377 
1378     /**
1379      * Returns list of protocols which should be installed on this window.
1380      * Descendants can override this method to add class-specific protocols
1381      */
1382     protected XAtomList getWMProtocols() {
1383         // No protocols on simple window
1384         return new XAtomList();
1385     }
1386 
1387 }