1 /*
2  * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.awt.X11;
27 
28 import java.awt.*;
29 import sun.awt.*;
30 import java.util.*;
31 import sun.util.logging.PlatformLogger;
32 
33 public class XBaseWindow {
34     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XBaseWindow");
35     private static final PlatformLogger insLog = PlatformLogger.getLogger("sun.awt.X11.insets.XBaseWindow");
36     private static final PlatformLogger eventLog = PlatformLogger.getLogger("sun.awt.X11.event.XBaseWindow");
37     private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.X11.focus.XBaseWindow");
38     private static final PlatformLogger grabLog = PlatformLogger.getLogger("sun.awt.X11.grab.XBaseWindow");
39 
40     public static final String
41         PARENT_WINDOW = "parent window", // parent window, Long
42         BOUNDS = "bounds", // bounds of the window, Rectangle
43         OVERRIDE_REDIRECT = "overrideRedirect", // override_redirect setting, Boolean
44         EVENT_MASK = "event mask", // event mask, Integer
45         VALUE_MASK = "value mask", // value mask, Long
46         BORDER_PIXEL = "border pixel", // border pixel value, Integer
47         COLORMAP = "color map", // color map, Long
48         DEPTH = "visual depth", // depth, Integer
49         VISUAL_CLASS = "visual class", // visual class, Integer
50         VISUAL = "visual", // visual, Long
51         EMBEDDED = "embedded", // is embedded?, Boolean
52         DELAYED = "delayed", // is creation delayed?, Boolean
53         PARENT = "parent", // parent peer
54         BACKGROUND_PIXMAP = "pixmap", // background pixmap
55         VISIBLE = "visible", // whether it is visible by default
56         SAVE_UNDER = "save under", // save content under this window
57         BACKING_STORE = "backing store", // enables double buffering
58         BIT_GRAVITY = "bit gravity"; // copy old content on geometry change
59     private XCreateWindowParams delayedParams;
60 
61     Set<Long> children = new HashSet<Long>();
62     long window;
63     boolean visible;
64     boolean mapped;
65     boolean embedded;
66     Rectangle maxBounds;
67     volatile XBaseWindow parentWindow;
68 
69     private boolean disposed;
70 
71     private long screen;
72     private XSizeHints hints;
73     private XWMHints wmHints;
74 
75     static final int MIN_SIZE = 1;
76     static final int DEF_LOCATION = 1;
77 
78     private static XAtom wm_client_leader;
79 
80     static enum InitialiseState {
81         INITIALISING,
82         INITIALISED,
83         FAILED_INITIALISATION
84     };
85 
86     private InitialiseState initialising;
87 
88     int x;
89     int y;
90     int width;
91     int height;
92 
awtLock()93     void awtLock() {
94         XToolkit.awtLock();
95     }
96 
awtUnlock()97     void awtUnlock() {
98         XToolkit.awtUnlock();
99     }
100 
awtLockNotifyAll()101     void awtLockNotifyAll() {
102         XToolkit.awtLockNotifyAll();
103     }
104 
awtLockWait()105     void awtLockWait() throws InterruptedException {
106         XToolkit.awtLockWait();
107     }
108 
109     // To prevent errors from overriding obsolete methods
init(long parentWindow, Rectangle bounds)110     protected final void init(long parentWindow, Rectangle bounds) {}
preInit()111     protected final void preInit() {}
postInit()112     protected final void postInit() {}
113 
114     // internal lock for synchronizing state changes and paint calls, initialized in preInit.
115     // the order with other locks: AWTLock -> stateLock
116     static class StateLock { }
117     protected StateLock state_lock;
118 
119     /**
120      * Called for delayed inits during construction
121      */
instantPreInit(XCreateWindowParams params)122     void instantPreInit(XCreateWindowParams params) {
123         state_lock = new StateLock();
124     }
125 
126     /**
127      * Called before window creation, descendants should override to initialize the data,
128      * initialize params.
129      */
preInit(XCreateWindowParams params)130     void preInit(XCreateWindowParams params) {
131         state_lock = new StateLock();
132         embedded = Boolean.TRUE.equals(params.get(EMBEDDED));
133         visible = Boolean.TRUE.equals(params.get(VISIBLE));
134 
135         Object parent = params.get(PARENT);
136         if (parent instanceof XBaseWindow) {
137             parentWindow = (XBaseWindow)parent;
138         } else {
139             Long parentWindowID = (Long)params.get(PARENT_WINDOW);
140             if (parentWindowID != null) {
141                 parentWindow = XToolkit.windowToXWindow(parentWindowID);
142             }
143         }
144 
145         Long eventMask = (Long)params.get(EVENT_MASK);
146         if (eventMask != null) {
147             long mask = eventMask.longValue();
148             mask |= XConstants.SubstructureNotifyMask;
149             params.put(EVENT_MASK, mask);
150         }
151 
152         screen = -1;
153     }
154 
155     /**
156      * Called after window creation, descendants should override to initialize Window
157      * with class-specific values and perform post-initialization actions.
158      */
postInit(XCreateWindowParams params)159     void postInit(XCreateWindowParams params) {
160         if (log.isLoggable(PlatformLogger.Level.FINE)) {
161             log.fine("WM name is " + getWMName());
162         }
163         updateWMName();
164 
165         // Set WM_CLIENT_LEADER property
166         initClientLeader();
167     }
168 
169     /**
170      * Creates window using parameters {@code params}
171      * If params contain flag DELAYED doesn't do anything.
172      * Note: Descendants can call this method to create the window
173      * at the time different to instance construction.
174      */
init(XCreateWindowParams params)175     protected final void init(XCreateWindowParams params) {
176         awtLock();
177         initialising = InitialiseState.INITIALISING;
178         awtUnlock();
179 
180         try {
181             if (!Boolean.TRUE.equals(params.get(DELAYED))) {
182                 preInit(params);
183                 create(params);
184                 postInit(params);
185             } else {
186                 instantPreInit(params);
187                 delayedParams = params;
188             }
189             awtLock();
190             initialising = InitialiseState.INITIALISED;
191             awtLockNotifyAll();
192             awtUnlock();
193         } catch (RuntimeException re) {
194             awtLock();
195             initialising = InitialiseState.FAILED_INITIALISATION;
196             awtLockNotifyAll();
197             awtUnlock();
198             throw re;
199         } catch (Throwable t) {
200             log.warning("Exception during peer initialization", t);
201             awtLock();
202             initialising = InitialiseState.FAILED_INITIALISATION;
203             awtLockNotifyAll();
204             awtUnlock();
205         }
206     }
207 
checkInitialised()208     public boolean checkInitialised() {
209         awtLock();
210         try {
211             switch (initialising) {
212               case INITIALISED:
213                   return true;
214               case INITIALISING:
215                   try {
216                       while (initialising != InitialiseState.INITIALISED) {
217                           awtLockWait();
218                       }
219                   } catch (InterruptedException ie) {
220                       return false;
221                   }
222                   return true;
223               case FAILED_INITIALISATION:
224                   return false;
225               default:
226                   return false;
227             }
228         } finally {
229             awtUnlock();
230         }
231     }
232 
233     /*
234      * Creates an invisible InputOnly window without an associated Component.
235      */
XBaseWindow()236     XBaseWindow() {
237         this(new XCreateWindowParams());
238     }
239 
240     /**
241      * Creates normal child window
242      */
XBaseWindow(long parentWindow, Rectangle bounds)243     XBaseWindow(long parentWindow, Rectangle bounds) {
244         this(new XCreateWindowParams(new Object[] {
245             BOUNDS, bounds,
246             PARENT_WINDOW, Long.valueOf(parentWindow)}));
247     }
248 
249     /**
250      * Creates top-level window
251      */
XBaseWindow(Rectangle bounds)252     XBaseWindow(Rectangle bounds) {
253         this(new XCreateWindowParams(new Object[] {
254             BOUNDS, bounds
255         }));
256     }
257 
XBaseWindow(XCreateWindowParams params)258     public XBaseWindow (XCreateWindowParams params) {
259         init(params);
260     }
261 
262     /* This create is used by the XEmbeddedFramePeer since it has to create the window
263        as a child of the netscape window. This netscape window is passed in as wid */
XBaseWindow(long parentWindow)264     XBaseWindow(long parentWindow) {
265         this(new XCreateWindowParams(new Object[] {
266             PARENT_WINDOW, Long.valueOf(parentWindow),
267             EMBEDDED, Boolean.TRUE
268         }));
269     }
270 
271     /**
272      * Verifies that all required parameters are set. If not, sets them to default values.
273      * Verifies values of critical parameters, adjust their values when needed.
274      * @throws IllegalArgumentException if params is null
275      */
checkParams(XCreateWindowParams params)276     protected void checkParams(XCreateWindowParams params) {
277         if (params == null) {
278             throw new IllegalArgumentException("Window creation parameters are null");
279         }
280         params.putIfNull(PARENT_WINDOW, Long.valueOf(XToolkit.getDefaultRootWindow()));
281         params.putIfNull(BOUNDS, new Rectangle(DEF_LOCATION, DEF_LOCATION, MIN_SIZE, MIN_SIZE));
282         params.putIfNull(DEPTH, Integer.valueOf((int)XConstants.CopyFromParent));
283         params.putIfNull(VISUAL, Long.valueOf(XConstants.CopyFromParent));
284         params.putIfNull(VISUAL_CLASS, Integer.valueOf(XConstants.InputOnly));
285         params.putIfNull(VALUE_MASK, Long.valueOf(XConstants.CWEventMask));
286         Rectangle bounds = (Rectangle)params.get(BOUNDS);
287         bounds.width = Math.max(MIN_SIZE, bounds.width);
288         bounds.height = Math.max(MIN_SIZE, bounds.height);
289 
290         Long eventMaskObj = (Long)params.get(EVENT_MASK);
291         long eventMask = eventMaskObj != null ? eventMaskObj.longValue() : 0;
292         // We use our own synthetic grab see XAwtState.getGrabWindow()
293         // (see X vol. 1, 8.3.3.2)
294         eventMask |= XConstants.PropertyChangeMask | XConstants.OwnerGrabButtonMask;
295         params.put(EVENT_MASK, Long.valueOf(eventMask));
296     }
297 
298     /**
299      * Returns scale factor of the window. It is used to convert native
300      * coordinates to local and vice verse.
301      */
getScale()302     protected int getScale() {
303         return 1;
304     }
305 
scaleUp(int x)306     protected int scaleUp(int x) {
307         return x;
308     }
309 
scaleDown(int x)310     protected int scaleDown(int x) {
311         return x;
312     }
313 
314     /**
315      * Creates window with parameters specified by {@code params}
316      * @see #init
317      */
create(XCreateWindowParams params)318     private void create(XCreateWindowParams params) {
319         XToolkit.awtLock();
320         try {
321             XSetWindowAttributes xattr = new XSetWindowAttributes();
322             try {
323                 checkParams(params);
324 
325                 long value_mask = ((Long)params.get(VALUE_MASK)).longValue();
326 
327                 Long eventMask = (Long)params.get(EVENT_MASK);
328                 xattr.set_event_mask(eventMask.longValue());
329                 value_mask |= XConstants.CWEventMask;
330 
331                 Long border_pixel = (Long)params.get(BORDER_PIXEL);
332                 if (border_pixel != null) {
333                     xattr.set_border_pixel(border_pixel.longValue());
334                     value_mask |= XConstants.CWBorderPixel;
335                 }
336 
337                 Long colormap = (Long)params.get(COLORMAP);
338                 if (colormap != null) {
339                     xattr.set_colormap(colormap.longValue());
340                     value_mask |= XConstants.CWColormap;
341                 }
342                 Long background_pixmap = (Long)params.get(BACKGROUND_PIXMAP);
343                 if (background_pixmap != null) {
344                     xattr.set_background_pixmap(background_pixmap.longValue());
345                     value_mask |= XConstants.CWBackPixmap;
346                 }
347 
348                 Long parentWindow = (Long)params.get(PARENT_WINDOW);
349                 Rectangle bounds = (Rectangle)params.get(BOUNDS);
350                 Integer depth = (Integer)params.get(DEPTH);
351                 Integer visual_class = (Integer)params.get(VISUAL_CLASS);
352                 Long visual = (Long)params.get(VISUAL);
353                 Boolean overrideRedirect = (Boolean)params.get(OVERRIDE_REDIRECT);
354                 if (overrideRedirect != null) {
355                     xattr.set_override_redirect(overrideRedirect.booleanValue());
356                     value_mask |= XConstants.CWOverrideRedirect;
357                 }
358 
359                 Boolean saveUnder = (Boolean)params.get(SAVE_UNDER);
360                 if (saveUnder != null) {
361                     xattr.set_save_under(saveUnder.booleanValue());
362                     value_mask |= XConstants.CWSaveUnder;
363                 }
364 
365                 Integer backingStore = (Integer)params.get(BACKING_STORE);
366                 if (backingStore != null) {
367                     xattr.set_backing_store(backingStore.intValue());
368                     value_mask |= XConstants.CWBackingStore;
369                 }
370 
371                 Integer bitGravity = (Integer)params.get(BIT_GRAVITY);
372                 if (bitGravity != null) {
373                     xattr.set_bit_gravity(bitGravity.intValue());
374                     value_mask |= XConstants.CWBitGravity;
375                 }
376 
377                 if (log.isLoggable(PlatformLogger.Level.FINE)) {
378                     log.fine("Creating window for " + this + " with the following attributes: \n" + params);
379                 }
380                 window = XlibWrapper.XCreateWindow(XToolkit.getDisplay(),
381                                                    parentWindow.longValue(),
382                                                    scaleUp(bounds.x),
383                                                    scaleUp(bounds.y),
384                                                    scaleUp(bounds.width),
385                                                    scaleUp(bounds.height),
386                                                    0, // border
387                                                    depth.intValue(), // depth
388                                                    visual_class.intValue(), // class
389                                                    visual.longValue(), // visual
390                                                    value_mask,  // value mask
391                                                    xattr.pData); // attributes
392 
393                 if (window == 0) {
394                     throw new IllegalStateException("Couldn't create window because of wrong parameters. Run with NOISY_AWT to see details");
395                 }
396                 XToolkit.addToWinMap(window, this);
397             } finally {
398                 xattr.dispose();
399             }
400         } finally {
401             XToolkit.awtUnlock();
402         }
403     }
404 
getDelayedParams()405     public XCreateWindowParams getDelayedParams() {
406         return delayedParams;
407     }
408 
getWMName()409     protected String getWMName() {
410         return XToolkit.getCorrectXIDString(getClass().getName());
411     }
412 
initClientLeader()413     protected void initClientLeader() {
414         XToolkit.awtLock();
415         try {
416             if (wm_client_leader == null) {
417                 wm_client_leader = XAtom.get("WM_CLIENT_LEADER");
418             }
419             wm_client_leader.setWindowProperty(this, getXAWTRootWindow());
420         } finally {
421             XToolkit.awtUnlock();
422         }
423     }
424 
getXAWTRootWindow()425     static XRootWindow getXAWTRootWindow() {
426         return XRootWindow.getInstance();
427     }
428 
destroy()429     void destroy() {
430         XToolkit.awtLock();
431         try {
432             if (hints != null) {
433                 XlibWrapper.XFree(hints.pData);
434                 hints = null;
435             }
436             XToolkit.removeFromWinMap(getWindow(), this);
437             XlibWrapper.XDestroyWindow(XToolkit.getDisplay(), getWindow());
438             if (XPropertyCache.isCachingSupported()) {
439                 XPropertyCache.clearCache(window);
440             }
441             window = -1;
442             if( !isDisposed() ) {
443                 setDisposed( true );
444             }
445 
446             XAwtState.getGrabWindow(); // Magic - getGrabWindow clear state if grabbing window is disposed of.
447         } finally {
448             XToolkit.awtUnlock();
449         }
450     }
451 
flush()452     void flush() {
453         XToolkit.awtLock();
454         try {
455             XlibWrapper.XFlush(XToolkit.getDisplay());
456         } finally {
457             XToolkit.awtUnlock();
458         }
459     }
460 
461     /**
462      * Helper function to set W
463      */
setWMHints(XWMHints hints)464     public final void setWMHints(XWMHints hints) {
465         XToolkit.awtLock();
466         try {
467             XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData);
468         } finally {
469             XToolkit.awtUnlock();
470         }
471     }
472 
getWMHints()473     public XWMHints getWMHints() {
474         if (wmHints == null) {
475             wmHints = new XWMHints(XlibWrapper.XAllocWMHints());
476 //              XlibWrapper.XGetWMHints(XToolkit.getDisplay(),
477 //                                      getWindow(),
478 //                                      wmHints.pData);
479         }
480         return wmHints;
481     }
482 
483 
484     /*
485      * Call this method under AWTLock.
486      * The lock should be acquired untill all operations with XSizeHints are completed.
487      */
getHints()488     public XSizeHints getHints() {
489         if (hints == null) {
490             long p_hints = XlibWrapper.XAllocSizeHints();
491             hints = new XSizeHints(p_hints);
492 //              XlibWrapper.XGetWMNormalHints(XToolkit.getDisplay(), getWindow(), p_hints, XlibWrapper.larg1);
493             // TODO: Shouldn't we listen for WM updates on this property?
494         }
495         return hints;
496     }
497 
setSizeHints(long flags, int x, int y, int width, int height)498     public void setSizeHints(long flags, int x, int y, int width, int height) {
499         if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
500             insLog.finer("Setting hints, flags " + XlibWrapper.hintsToString(flags));
501         }
502         XToolkit.awtLock();
503         try {
504             XSizeHints hints = getHints();
505             // Note: if PPosition is not set in flags this means that
506             // we want to reset PPosition in hints.  This is necessary
507             // for locationByPlatform functionality
508             if ((flags & XUtilConstants.PPosition) != 0) {
509                 hints.set_x(scaleUp(x));
510                 hints.set_y(scaleUp(y));
511             }
512             if ((flags & XUtilConstants.PSize) != 0) {
513                 hints.set_width(scaleUp(width));
514                 hints.set_height(scaleUp(height));
515             } else if ((hints.get_flags() & XUtilConstants.PSize) != 0) {
516                 flags |= XUtilConstants.PSize;
517             }
518             if ((flags & XUtilConstants.PMinSize) != 0) {
519                 hints.set_min_width(scaleUp(width));
520                 hints.set_min_height(scaleUp(height));
521             } else if ((hints.get_flags() & XUtilConstants.PMinSize) != 0) {
522                 flags |= XUtilConstants.PMinSize;
523                 //Fix for 4320050: Minimum size for java.awt.Frame is not being enforced.
524                 //We don't need to reset minimum size if it's already set
525             }
526             if ((flags & XUtilConstants.PMaxSize) != 0) {
527                 if (maxBounds != null) {
528                     if (maxBounds.width != Integer.MAX_VALUE) {
529                         hints.set_max_width(scaleUp(maxBounds.width));
530                     } else {
531                         hints.set_max_width(XToolkit.getMaxWindowWidthInPixels());
532                     }
533                     if (maxBounds.height != Integer.MAX_VALUE) {
534                         hints.set_max_height(scaleUp(maxBounds.height));
535                     } else {
536                         hints.set_max_height(XToolkit.getMaxWindowHeightInPixels());
537                     }
538                 } else {
539                     hints.set_max_width(scaleUp(width));
540                     hints.set_max_height(scaleUp(height));
541                 }
542             } else if ((hints.get_flags() & XUtilConstants.PMaxSize) != 0) {
543                 flags |= XUtilConstants.PMaxSize;
544                 if (maxBounds != null) {
545                     if (maxBounds.width != Integer.MAX_VALUE) {
546                         hints.set_max_width(scaleUp(maxBounds.width));
547                     } else {
548                         hints.set_max_width(XToolkit.getMaxWindowWidthInPixels());
549                     }
550                     if (maxBounds.height != Integer.MAX_VALUE) {
551                         hints.set_max_height(scaleUp(maxBounds.height));
552                     } else {
553                         hints.set_max_height(XToolkit.getMaxWindowHeightInPixels());
554                     }
555                 } else {
556                     // Leave intact
557                 }
558             }
559             flags |= XUtilConstants.PWinGravity;
560             hints.set_flags(flags);
561             hints.set_win_gravity(XConstants.NorthWestGravity);
562             if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
563                 insLog.finer("Setting hints, resulted flags " + XlibWrapper.hintsToString(flags) +
564                              ", values " + hints);
565             }
566             XlibWrapper.XSetWMNormalHints(XToolkit.getDisplay(), getWindow(), hints.pData);
567         } finally {
568             XToolkit.awtUnlock();
569         }
570     }
571 
isMinSizeSet()572     public boolean isMinSizeSet() {
573         XSizeHints hints = getHints();
574         long flags = hints.get_flags();
575         return ((flags & XUtilConstants.PMinSize) == XUtilConstants.PMinSize);
576     }
577 
578     /**
579      * This lock object can be used to protect instance data from concurrent access
580      * by two threads. If both state lock and AWT lock are taken, AWT Lock should be taken first.
581      */
getStateLock()582     Object getStateLock() {
583         return state_lock;
584     }
585 
getWindow()586     public long getWindow() {
587         return window;
588     }
getContentWindow()589     public long getContentWindow() {
590         return window;
591     }
592 
getContentXWindow()593     public XBaseWindow getContentXWindow() {
594         return XToolkit.windowToXWindow(getContentWindow());
595     }
596 
getBounds()597     public Rectangle getBounds() {
598         return new Rectangle(x, y, width, height);
599     }
getSize()600     public Dimension getSize() {
601         return new Dimension(width, height);
602     }
603 
604 
toFront()605     public void toFront() {
606         XToolkit.awtLock();
607         try {
608             XlibWrapper.XRaiseWindow(XToolkit.getDisplay(), getWindow());
609         } finally {
610             XToolkit.awtUnlock();
611         }
612     }
xRequestFocus(long time)613     public void xRequestFocus(long time) {
614         XToolkit.awtLock();
615         try {
616             if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
617                 focusLog.finer("XSetInputFocus on " + Long.toHexString(getWindow()) + " with time " + time);
618             }
619             XlibWrapper.XSetInputFocus2(XToolkit.getDisplay(), getWindow(), time);
620         } finally {
621             XToolkit.awtUnlock();
622         }
623     }
xRequestFocus()624     public void xRequestFocus() {
625         XToolkit.awtLock();
626         try {
627             if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
628                 focusLog.finer("XSetInputFocus on " + Long.toHexString(getWindow()));
629             }
630              XlibWrapper.XSetInputFocus(XToolkit.getDisplay(), getWindow());
631         } finally {
632             XToolkit.awtUnlock();
633         }
634     }
635 
xGetInputFocus()636     public static long xGetInputFocus() {
637         XToolkit.awtLock();
638         try {
639             return XlibWrapper.XGetInputFocus(XToolkit.getDisplay());
640         } finally {
641             XToolkit.awtUnlock();
642         }
643     }
644 
xSetVisible(boolean visible)645     public void xSetVisible(boolean visible) {
646         if (log.isLoggable(PlatformLogger.Level.FINE)) {
647             log.fine("Setting visible on " + this + " to " + visible);
648         }
649         XToolkit.awtLock();
650         try {
651             this.visible = visible;
652             if (visible) {
653                 XlibWrapper.XMapWindow(XToolkit.getDisplay(), getWindow());
654             }
655             else {
656                 XlibWrapper.XUnmapWindow(XToolkit.getDisplay(), getWindow());
657             }
658             XlibWrapper.XFlush(XToolkit.getDisplay());
659         } finally {
660             XToolkit.awtUnlock();
661         }
662     }
663 
isMapped()664     boolean isMapped() {
665         return mapped;
666     }
667 
updateWMName()668     void updateWMName() {
669         String name = getWMName();
670         XToolkit.awtLock();
671         try {
672             if (name == null) {
673                 name = " ";
674             }
675             XAtom nameAtom = XAtom.get(XAtom.XA_WM_NAME);
676             nameAtom.setProperty(getWindow(), name);
677             XAtom netNameAtom = XAtom.get("_NET_WM_NAME");
678             netNameAtom.setPropertyUTF8(getWindow(), name);
679         } finally {
680             XToolkit.awtUnlock();
681         }
682     }
setWMClass(String[] cl)683     void setWMClass(String[] cl) {
684         if (cl.length != 2) {
685             throw new IllegalArgumentException("WM_CLASS_NAME consists of exactly two strings");
686         }
687         XToolkit.awtLock();
688         try {
689             XAtom xa = XAtom.get(XAtom.XA_WM_CLASS);
690             xa.setProperty8(getWindow(), cl[0] + '\0' + cl[1] + '\0');
691         } finally {
692             XToolkit.awtUnlock();
693         }
694     }
695 
isVisible()696     boolean isVisible() {
697         return visible;
698     }
699 
getScreenOfWindow(long window)700     static long getScreenOfWindow(long window) {
701         XToolkit.awtLock();
702         try {
703             return XlibWrapper.getScreenOfWindow(XToolkit.getDisplay(), window);
704         } finally {
705             XToolkit.awtUnlock();
706         }
707     }
getScreenNumber()708     long getScreenNumber() {
709         XToolkit.awtLock();
710         try {
711             return XlibWrapper.XScreenNumberOfScreen(getScreen());
712         } finally {
713             XToolkit.awtUnlock();
714         }
715     }
716 
getScreen()717     long getScreen() {
718         if (screen == -1) { // Not initialized
719             screen = getScreenOfWindow(window);
720         }
721         return screen;
722     }
723 
xSetBounds(Rectangle bounds)724     public void xSetBounds(Rectangle bounds) {
725         xSetBounds(bounds.x, bounds.y, bounds.width, bounds.height);
726     }
727 
xSetBounds(int x, int y, int width, int height)728     public void xSetBounds(int x, int y, int width, int height) {
729         if (getWindow() == 0) {
730             insLog.warning("Attempt to resize uncreated window");
731             throw new IllegalStateException("Attempt to resize uncreated window");
732         }
733         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
734             insLog.fine("Setting bounds on " + this + " to (" + x + ", " + y + "), " + width + "x" + height);
735         }
736         width = Math.max(MIN_SIZE, width);
737         height = Math.max(MIN_SIZE, height);
738         XToolkit.awtLock();
739         try {
740             XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), getWindow(),
741                                           scaleUp(x), scaleUp(y),
742                                           scaleUp(width), scaleUp(height));
743         } finally {
744             XToolkit.awtUnlock();
745         }
746     }
747 
748     /**
749      * Translate coordinates from one window into another.  Optimized
750      * for XAWT - uses cached data when possible.  Preferable over
751      * pure XTranslateCoordinates.
752      * @return coordinates relative to dst, or null if error happened
753      */
toOtherWindow(long src, long dst, int x, int y)754     static Point toOtherWindow(long src, long dst, int x, int y) {
755         Point rpt = new Point(0, 0);
756 
757         // Check if both windows belong to XAWT - then no X calls are necessary
758 
759         XBaseWindow srcPeer = XToolkit.windowToXWindow(src);
760         XBaseWindow dstPeer = XToolkit.windowToXWindow(dst);
761 
762         if (srcPeer != null && dstPeer != null) {
763             // (x, y) is relative to src
764             rpt.x = x + srcPeer.getAbsoluteX() - dstPeer.getAbsoluteX();
765             rpt.y = y + srcPeer.getAbsoluteY() - dstPeer.getAbsoluteY();
766         } else if (dstPeer != null && XlibUtil.isRoot(src, dstPeer.getScreenNumber())) {
767             // from root into peer
768             rpt.x = x - dstPeer.getAbsoluteX();
769             rpt.y = y - dstPeer.getAbsoluteY();
770         } else if (srcPeer != null && XlibUtil.isRoot(dst, srcPeer.getScreenNumber())) {
771             // from peer into root
772             rpt.x = x + srcPeer.getAbsoluteX();
773             rpt.y = y + srcPeer.getAbsoluteY();
774         } else {
775             int scale = srcPeer == null ? 1 : srcPeer.getScale();
776             rpt = XlibUtil.translateCoordinates(src, dst, new Point(x, y), scale);
777         }
778         return rpt;
779     }
780 
781     /*
782      * Convert to global coordinates.
783      */
toGlobal(Rectangle rec)784     Rectangle toGlobal(Rectangle rec) {
785         Point p = toGlobal(rec.getLocation());
786         Rectangle newRec = new Rectangle(rec);
787         if (p != null) {
788             newRec.setLocation(p);
789         }
790         return newRec;
791     }
792 
toGlobal(Point pt)793     Point toGlobal(Point pt) {
794         Point p = toGlobal(pt.x, pt.y);
795         if (p != null) {
796             return p;
797         } else {
798             return new Point(pt);
799         }
800     }
801 
toGlobal(int x, int y)802     Point toGlobal(int x, int y) {
803         long root;
804         XToolkit.awtLock();
805         try {
806             root = XlibWrapper.RootWindow(XToolkit.getDisplay(),
807                     getScreenNumber());
808         } finally {
809             XToolkit.awtUnlock();
810         }
811         Point p = toOtherWindow(getContentWindow(), root, x, y);
812         if (p != null) {
813             return p;
814         } else {
815             return new Point(x, y);
816         }
817     }
818 
819     /*
820      * Convert to local coordinates.
821      */
toLocal(Point pt)822     Point toLocal(Point pt) {
823         Point p = toLocal(pt.x, pt.y);
824         if (p != null) {
825             return p;
826         } else {
827             return new Point(pt);
828         }
829     }
830 
toLocal(int x, int y)831     Point toLocal(int x, int y) {
832         long root;
833         XToolkit.awtLock();
834         try {
835             root = XlibWrapper.RootWindow(XToolkit.getDisplay(),
836                     getScreenNumber());
837         } finally {
838             XToolkit.awtUnlock();
839         }
840         Point p = toOtherWindow(root, getContentWindow(), x, y);
841         if (p != null) {
842             return p;
843         } else {
844             return new Point(x, y);
845         }
846     }
847 
848     /**
849      * We should always grab both keyboard and pointer to control event flow
850      * on popups. This also simplifies synthetic grab implementation.
851      * The active grab overrides activated automatic grab.
852      */
grabInput()853     public boolean grabInput() {
854         if (grabLog.isLoggable(PlatformLogger.Level.FINE)) {
855             grabLog.fine("Grab input on {0}", this);
856         }
857 
858         XToolkit.awtLock();
859         try {
860             if (XAwtState.getGrabWindow() == this &&
861                 XAwtState.isManualGrab())
862             {
863                 grabLog.fine("    Already Grabbed");
864                 return true;
865             }
866             //6273031: PIT. Choice drop down does not close once it is right clicked to show a popup menu
867             //remember previous window having grab and if it's not null ungrab it.
868             XBaseWindow prevGrabWindow = XAwtState.getGrabWindow();
869             final int eventMask = (int) (XConstants.ButtonPressMask | XConstants.ButtonReleaseMask
870                 | XConstants.EnterWindowMask | XConstants.LeaveWindowMask | XConstants.PointerMotionMask
871                 | XConstants.ButtonMotionMask);
872             final int ownerEvents = 1;
873 
874 
875             //6714678: IDE (Netbeans, Eclipse, JDeveloper) Debugger hangs
876             //process on Linux
877             //The user must pass the sun.awt.disablegrab property to disable
878             //taking grabs. This prevents hanging of the GUI when a breakpoint
879             //is hit while a popup window taking the grab is open.
880             if (!XToolkit.getSunAwtDisableGrab()) {
881                 int ptrGrab = XlibWrapper.XGrabPointer(XToolkit.getDisplay(),
882                         getContentWindow(), ownerEvents, eventMask, XConstants.GrabModeAsync,
883                         XConstants.GrabModeAsync, XConstants.None, (XWM.isMotif() ? XToolkit.arrowCursor : XConstants.None),
884                         XConstants.CurrentTime);
885                 // Check grab results to be consistent with X server grab
886                 if (ptrGrab != XConstants.GrabSuccess) {
887                     XlibWrapper.XUngrabPointer(XToolkit.getDisplay(), XConstants.CurrentTime);
888                     XAwtState.setGrabWindow(null);
889                     grabLog.fine("    Grab Failure - mouse");
890                     return false;
891                 }
892 
893                 int keyGrab = XlibWrapper.XGrabKeyboard(XToolkit.getDisplay(),
894                         getContentWindow(), ownerEvents, XConstants.GrabModeAsync, XConstants.GrabModeAsync,
895                         XConstants.CurrentTime);
896                 if (keyGrab != XConstants.GrabSuccess) {
897                     XlibWrapper.XUngrabPointer(XToolkit.getDisplay(), XConstants.CurrentTime);
898                     XlibWrapper.XUngrabKeyboard(XToolkit.getDisplay(), XConstants.CurrentTime);
899                     XAwtState.setGrabWindow(null);
900                     grabLog.fine("    Grab Failure - keyboard");
901                     return false;
902                 }
903             }
904             if (prevGrabWindow != null) {
905                 prevGrabWindow.ungrabInputImpl();
906             }
907             XAwtState.setGrabWindow(this);
908             grabLog.fine("    Grab - success");
909             return true;
910         } finally {
911             XToolkit.awtUnlock();
912         }
913     }
914 
ungrabInput()915     static void ungrabInput() {
916         XToolkit.awtLock();
917         try {
918             XBaseWindow grabWindow = XAwtState.getGrabWindow();
919             if (grabLog.isLoggable(PlatformLogger.Level.FINE)) {
920                 grabLog.fine("UnGrab input on {0}", grabWindow);
921             }
922             if (grabWindow != null) {
923                 grabWindow.ungrabInputImpl();
924                 if (!XToolkit.getSunAwtDisableGrab()) {
925                     XlibWrapper.XUngrabPointer(XToolkit.getDisplay(), XConstants.CurrentTime);
926                     XlibWrapper.XUngrabKeyboard(XToolkit.getDisplay(), XConstants.CurrentTime);
927                 }
928                 XAwtState.setGrabWindow(null);
929                 // we need to call XFlush() here to force ungrab
930                 // see 6384219 for details
931                 XlibWrapper.XFlush(XToolkit.getDisplay());
932             }
933         } finally {
934             XToolkit.awtUnlock();
935         }
936     }
937 
938     // called from ungrabInput, used in popup windows to hide theirselfs in ungrabbing
ungrabInputImpl()939     void ungrabInputImpl() {
940     }
941 
checkSecurity()942     static void checkSecurity() {
943         if (XToolkit.isSecurityWarningEnabled() && XToolkit.isToolkitThread()) {
944             StackTraceElement[] stack = (new Throwable()).getStackTrace();
945             log.warning(stack[1] + ": Security violation: calling user code on toolkit thread");
946         }
947     }
948 
getChildren()949     public Set<Long> getChildren() {
950         synchronized (getStateLock()) {
951             return new HashSet<Long>(children);
952         }
953     }
954 
955     // -------------- Event handling ----------------
handleMapNotifyEvent(XEvent xev)956     public void handleMapNotifyEvent(XEvent xev) {
957         mapped = true;
958     }
handleUnmapNotifyEvent(XEvent xev)959     public void handleUnmapNotifyEvent(XEvent xev) {
960         mapped = false;
961     }
handleReparentNotifyEvent(XEvent xev)962     public void handleReparentNotifyEvent(XEvent xev) {
963         if (eventLog.isLoggable(PlatformLogger.Level.FINER)) {
964             XReparentEvent msg = xev.get_xreparent();
965             eventLog.finer(msg.toString());
966         }
967     }
handlePropertyNotify(XEvent xev)968     public void handlePropertyNotify(XEvent xev) {
969         XPropertyEvent msg = xev.get_xproperty();
970         if (XPropertyCache.isCachingSupported()) {
971             XPropertyCache.clearCache(window, XAtom.get(msg.get_atom()));
972         }
973         if (eventLog.isLoggable(PlatformLogger.Level.FINER)) {
974             eventLog.finer("{0}", msg);
975         }
976     }
977 
handleDestroyNotify(XEvent xev)978     public void handleDestroyNotify(XEvent xev) {
979         XAnyEvent xany = xev.get_xany();
980         if (xany.get_window() == getWindow()) {
981             XToolkit.removeFromWinMap(getWindow(), this);
982             if (XPropertyCache.isCachingSupported()) {
983                 XPropertyCache.clearCache(getWindow());
984             }
985         }
986         if (xany.get_window() != getWindow()) {
987             synchronized (getStateLock()) {
988                 children.remove(xany.get_window());
989             }
990         }
991     }
992 
handleCreateNotify(XEvent xev)993     public void handleCreateNotify(XEvent xev) {
994         XAnyEvent xany = xev.get_xany();
995         if (xany.get_window() != getWindow()) {
996             synchronized (getStateLock()) {
997                 children.add(xany.get_window());
998             }
999         }
1000     }
1001 
handleClientMessage(XEvent xev)1002     public void handleClientMessage(XEvent xev) {
1003         if (eventLog.isLoggable(PlatformLogger.Level.FINER)) {
1004             XClientMessageEvent msg = xev.get_xclient();
1005             eventLog.finer(msg.toString());
1006         }
1007     }
1008 
handleVisibilityEvent(XEvent xev)1009     public void handleVisibilityEvent(XEvent xev) {
1010     }
handleKeyPress(XEvent xev)1011     public void handleKeyPress(XEvent xev) {
1012     }
handleKeyRelease(XEvent xev)1013     public void handleKeyRelease(XEvent xev) {
1014     }
handleExposeEvent(XEvent xev)1015     public void handleExposeEvent(XEvent xev) {
1016     }
1017     /**
1018      * Activate automatic grab on first ButtonPress,
1019      * deactivate on full mouse release
1020      */
handleButtonPressRelease(XEvent xev)1021     public void handleButtonPressRelease(XEvent xev) {
1022         XButtonEvent xbe = xev.get_xbutton();
1023         /*
1024          * Ignore the buttons above 20 due to the bit limit for
1025          * InputEvent.BUTTON_DOWN_MASK.
1026          * One more bit is reserved for FIRST_HIGH_BIT.
1027          */
1028         int theButton = xbe.get_button();
1029         if (theButton > SunToolkit.MAX_BUTTONS_SUPPORTED) {
1030             return;
1031         }
1032         int buttonState = 0;
1033         buttonState = xbe.get_state() & XConstants.ALL_BUTTONS_MASK;
1034 
1035         boolean isWheel = (theButton == XConstants.MouseWheelUp ||
1036                            theButton == XConstants.MouseWheelDown);
1037 
1038         // don't give focus if it's just the mouse wheel turning
1039         if (!isWheel) {
1040             switch (xev.get_type()) {
1041                 case XConstants.ButtonPress:
1042                     if (buttonState == 0) {
1043                         XWindowPeer parent = getToplevelXWindow();
1044                         // See 6385277, 6981400.
1045                         if (parent != null && parent.isFocusableWindow()) {
1046                             // A click in a client area drops the actual focused window retaining.
1047                             parent.setActualFocusedWindow(null);
1048                             parent.requestWindowFocus(xbe.get_time(), true);
1049                         }
1050                         XAwtState.setAutoGrabWindow(this);
1051                     }
1052                     break;
1053                 case XConstants.ButtonRelease:
1054                     if (isFullRelease(buttonState, xbe.get_button())) {
1055                         XAwtState.setAutoGrabWindow(null);
1056                     }
1057                     break;
1058             }
1059         }
1060     }
handleMotionNotify(XEvent xev)1061     public void handleMotionNotify(XEvent xev) {
1062     }
handleXCrossingEvent(XEvent xev)1063     public void handleXCrossingEvent(XEvent xev) {
1064     }
handleConfigureNotifyEvent(XEvent xev)1065     public void handleConfigureNotifyEvent(XEvent xev) {
1066         XConfigureEvent xe = xev.get_xconfigure();
1067         if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
1068             insLog.finer("Configure, {0}", xe);
1069         }
1070 
1071         x = scaleDown(xe.get_x());
1072         y = scaleDown(xe.get_y());
1073         width = scaleDown(xe.get_width());
1074         height = scaleDown(xe.get_height());
1075     }
1076     /**
1077      * Checks ButtonRelease released all Mouse buttons
1078      */
isFullRelease(int buttonState, int button)1079     static boolean isFullRelease(int buttonState, int button) {
1080         final int buttonsNumber = XToolkit.getNumberOfButtonsForMask();
1081 
1082         if (button < 0 || button > buttonsNumber) {
1083             return buttonState == 0;
1084         } else {
1085             return buttonState == XlibUtil.getButtonMask(button);
1086         }
1087     }
1088 
isGrabbedEvent(XEvent ev, XBaseWindow target)1089     static boolean isGrabbedEvent(XEvent ev, XBaseWindow target) {
1090         switch (ev.get_type()) {
1091           case XConstants.ButtonPress:
1092           case XConstants.ButtonRelease:
1093           case XConstants.MotionNotify:
1094           case XConstants.KeyPress:
1095           case XConstants.KeyRelease:
1096               return true;
1097           case XConstants.LeaveNotify:
1098           case XConstants.EnterNotify:
1099               // We shouldn't dispatch this events to the grabbed components (see 6317481)
1100               // But this logic is important if the grabbed component is top-level (see realSync)
1101               return (target instanceof XWindowPeer);
1102           default:
1103               return false;
1104         }
1105     }
1106     /**
1107      * Dispatches event to the grab Window or event source window depending
1108      * on whether the grab is active and on the event type
1109      */
dispatchToWindow(XEvent ev)1110     static void dispatchToWindow(XEvent ev) {
1111         XBaseWindow target = XAwtState.getGrabWindow();
1112         if (target == null || !isGrabbedEvent(ev, target)) {
1113             target = XToolkit.windowToXWindow(ev.get_xany().get_window());
1114         }
1115         if (target != null && target.checkInitialised()) {
1116             target.dispatchEvent(ev);
1117         }
1118     }
1119 
dispatchEvent(XEvent xev)1120     public void dispatchEvent(XEvent xev) {
1121         if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) {
1122             eventLog.finest(xev.toString());
1123         }
1124         int type = xev.get_type();
1125 
1126         if (isDisposed()) {
1127             return;
1128         }
1129 
1130         switch (type)
1131         {
1132           case XConstants.VisibilityNotify:
1133               handleVisibilityEvent(xev);
1134               break;
1135           case XConstants.ClientMessage:
1136               handleClientMessage(xev);
1137               break;
1138           case XConstants.Expose :
1139           case XConstants.GraphicsExpose :
1140               handleExposeEvent(xev);
1141               break;
1142           case XConstants.ButtonPress:
1143           case XConstants.ButtonRelease:
1144               handleButtonPressRelease(xev);
1145               break;
1146 
1147           case XConstants.MotionNotify:
1148               handleMotionNotify(xev);
1149               break;
1150           case XConstants.KeyPress:
1151               handleKeyPress(xev);
1152               break;
1153           case XConstants.KeyRelease:
1154               handleKeyRelease(xev);
1155               break;
1156           case XConstants.EnterNotify:
1157           case XConstants.LeaveNotify:
1158               handleXCrossingEvent(xev);
1159               break;
1160           case XConstants.ConfigureNotify:
1161               handleConfigureNotifyEvent(xev);
1162               break;
1163           case XConstants.MapNotify:
1164               handleMapNotifyEvent(xev);
1165               break;
1166           case XConstants.UnmapNotify:
1167               handleUnmapNotifyEvent(xev);
1168               break;
1169           case XConstants.ReparentNotify:
1170               handleReparentNotifyEvent(xev);
1171               break;
1172           case XConstants.PropertyNotify:
1173               handlePropertyNotify(xev);
1174               break;
1175           case XConstants.DestroyNotify:
1176               handleDestroyNotify(xev);
1177               break;
1178           case XConstants.CreateNotify:
1179               handleCreateNotify(xev);
1180               break;
1181         }
1182     }
isEventDisabled(XEvent e)1183     protected boolean isEventDisabled(XEvent e) {
1184         return false;
1185     }
1186 
getX()1187     int getX() {
1188         return x;
1189     }
1190 
getY()1191     int getY() {
1192         return y;
1193     }
1194 
getWidth()1195     int getWidth() {
1196         return width;
1197     }
1198 
getHeight()1199     int getHeight() {
1200         return height;
1201     }
1202 
setDisposed(boolean d)1203     void setDisposed(boolean d) {
1204         disposed = d;
1205     }
1206 
isDisposed()1207     boolean isDisposed() {
1208         return disposed;
1209     }
1210 
getAbsoluteX()1211     public int getAbsoluteX() {
1212         XBaseWindow pw = getParentWindow();
1213         if (pw != null) {
1214             return pw.getAbsoluteX() + getX();
1215         } else {
1216             // Overridden for top-levels as their (x,y) is Java (x, y), not native location
1217             return getX();
1218         }
1219     }
1220 
getAbsoluteY()1221     public int getAbsoluteY() {
1222         XBaseWindow pw = getParentWindow();
1223         if (pw != null) {
1224             return pw.getAbsoluteY() + getY();
1225         } else {
1226             return getY();
1227         }
1228     }
1229 
getParentWindow()1230     public XBaseWindow getParentWindow() {
1231         return parentWindow;
1232     }
1233 
getToplevelXWindow()1234     public XWindowPeer getToplevelXWindow() {
1235         XBaseWindow bw = this;
1236         while (bw != null && !(bw instanceof XWindowPeer)) {
1237             bw = bw.getParentWindow();
1238         }
1239         return (XWindowPeer)bw;
1240     }
toString()1241     public String toString() {
1242         return super.toString() + "(" + Long.toString(getWindow(), 16) + ")";
1243     }
1244 
1245     /**
1246      * Returns whether the given point is inside of the window.  Coordinates are local.
1247      */
contains(int x, int y)1248     public boolean contains(int x, int y) {
1249         return x >= 0 && y >= 0 && x < getWidth() && y < getHeight();
1250     }
1251 
1252     /**
1253      * Returns whether the given point is inside of the window.  Coordinates are global.
1254      */
containsGlobal(int x, int y)1255     public boolean containsGlobal(int x, int y) {
1256         return x >= getAbsoluteX() && y >= getAbsoluteY() && x < (getAbsoluteX()+getWidth()) && y < (getAbsoluteY()+getHeight());
1257     }
1258 
1259 }
1260