1 /*
   2  * Copyright (c) 2002, 2014, 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 /**
  29  * XAtom is a class that allows you to create and modify X Window properties.
  30  * An X Atom is an identifier for a property that you can set on any X Window.
  31  * Standard X Atom are defined by X11 and these atoms are defined in this class
  32  * for convenience. Common X Atoms like {@code XA_WM_NAME} are used to communicate with the
  33  * Window manager to let it know the Window name. The use and protocol for these
  34  * atoms are defined in the Inter client communications converntions manual.
  35  * User specified XAtoms are defined by specifying a name that gets Interned
  36  * by the XServer and an {@code XAtom} object is returned. An {@code XAtom} can also be created
  37  * by using a pre-exisiting atom like {@code XA_WM_CLASS}. A {@code display} has to be specified
  38  * in order to create an {@code XAtom}. <p> <p>
  39  *
  40  * Once an {@code XAtom} instance is created, you can call get and set property methods to
  41  * set the values for a particular window. <p> <p>
  42  *
  43  *
  44  * Example usage : To set the window name for a top level: <p>
  45  * <pre>{@code
  46  * XAtom xa = new XAtom(display,XAtom.XA_WM_NAME);
  47  * xa.setProperty(window,"Hello World");
  48  * }</pre>
  49  * <p>
  50  * <p>
  51  * To get the cut buffer:
  52  * <pre>{@code
  53  * XAtom xa = new XAtom(display,XAtom.XA_CUT_BUFFER0);
  54  * String selection = xa.getProperty(root_window);
  55  * }</pre>
  56  *
  57  * @author  Bino George
  58  * @since       1.5
  59  */
  60 
  61 import sun.misc.Unsafe;
  62 import java.util.HashMap;
  63 
  64 public final class XAtom {
  65 
  66     // Order of lock:  XAWTLock -> XAtom.class
  67 
  68     /* Predefined Atoms - automatically extracted from XAtom.h */
  69     private static Unsafe unsafe = XlibWrapper.unsafe;
  70     private static XAtom[] emptyList = new XAtom[0];
  71 
  72     public static final long XA_PRIMARY=1;
  73     public static final long XA_SECONDARY=2;
  74     public static final long XA_ARC=3;
  75     public static final long XA_ATOM=4;
  76     public static final long XA_BITMAP=5;
  77     public static final long XA_CARDINAL=6;
  78     public static final long XA_COLORMAP=7;
  79     public static final long XA_CURSOR=8;
  80     public static final long XA_CUT_BUFFER0=9;
  81     public static final long XA_CUT_BUFFER1=10;
  82     public static final long XA_CUT_BUFFER2=11;
  83     public static final long XA_CUT_BUFFER3=12;
  84     public static final long XA_CUT_BUFFER4=13;
  85     public static final long XA_CUT_BUFFER5=14;
  86     public static final long XA_CUT_BUFFER6=15;
  87     public static final long XA_CUT_BUFFER7=16;
  88     public static final long XA_DRAWABLE=17;
  89     public static final long XA_FONT=18;
  90     public static final long XA_INTEGER=19;
  91     public static final long XA_PIXMAP=20;
  92     public static final long XA_POINT=21;
  93     public static final long XA_RECTANGLE=22;
  94     public static final long XA_RESOURCE_MANAGER=23;
  95     public static final long XA_RGB_COLOR_MAP=24;
  96     public static final long XA_RGB_BEST_MAP=25;
  97     public static final long XA_RGB_BLUE_MAP=26;
  98     public static final long XA_RGB_DEFAULT_MAP=27;
  99     public static final long XA_RGB_GRAY_MAP=28;
 100     public static final long XA_RGB_GREEN_MAP=29;
 101     public static final long XA_RGB_RED_MAP=30;
 102     public static final long XA_STRING=31;
 103     public static final long XA_VISUALID=32;
 104     public static final long XA_WINDOW=33;
 105     public static final long XA_WM_COMMAND=34;
 106     public static final long XA_WM_HINTS=35;
 107     public static final long XA_WM_CLIENT_MACHINE=36;
 108     public static final long XA_WM_ICON_NAME=37;
 109     public static final long XA_WM_ICON_SIZE=38;
 110     public static final long XA_WM_NAME=39;
 111     public static final long XA_WM_NORMAL_HINTS=40;
 112     public static final long XA_WM_SIZE_HINTS=41;
 113     public static final long XA_WM_ZOOM_HINTS=42;
 114     public static final long XA_MIN_SPACE=43;
 115     public static final long XA_NORM_SPACE=44;
 116     public static final long XA_MAX_SPACE=45;
 117     public static final long XA_END_SPACE=46;
 118     public static final long XA_SUPERSCRIPT_X=47;
 119     public static final long XA_SUPERSCRIPT_Y=48;
 120     public static final long XA_SUBSCRIPT_X=49;
 121     public static final long XA_SUBSCRIPT_Y=50;
 122     public static final long XA_UNDERLINE_POSITION=51;
 123     public static final long XA_UNDERLINE_THICKNESS=52 ;
 124     public static final long XA_STRIKEOUT_ASCENT=53;
 125     public static final long XA_STRIKEOUT_DESCENT=54;
 126     public static final long XA_ITALIC_ANGLE=55;
 127     public static final long XA_X_HEIGHT=56;
 128     public static final long XA_QUAD_WIDTH=57;
 129     public static final long XA_WEIGHT=58;
 130     public static final long XA_POINT_SIZE=59;
 131     public static final long XA_RESOLUTION=60;
 132     public static final long XA_COPYRIGHT=61;
 133     public static final long XA_NOTICE=62;
 134     public static final long XA_FONT_NAME=63;
 135     public static final long XA_FAMILY_NAME=64;
 136     public static final long XA_FULL_NAME=65;
 137     public static final long XA_CAP_HEIGHT=66;
 138     public static final long XA_WM_CLASS=67;
 139     public static final long XA_WM_TRANSIENT_FOR=68;
 140     public static final long XA_LAST_PREDEFINED=68;
 141     static HashMap<Long, XAtom> atomToAtom = new HashMap<Long, XAtom>();
 142     static HashMap<String, XAtom> nameToAtom = new HashMap<String, XAtom>();
 143     static void register(XAtom at) {
 144         if (at == null) {
 145             return;
 146         }
 147         synchronized (XAtom.class) {
 148             if (at.atom != 0) {
 149                 atomToAtom.put(Long.valueOf(at.atom), at);
 150             }
 151             if (at.name != null) {
 152                 nameToAtom.put(at.name, at);
 153             }
 154         }
 155     }
 156     static XAtom lookup(long atom) {
 157         synchronized (XAtom.class) {
 158             return atomToAtom.get(Long.valueOf(atom));
 159         }
 160     }
 161     static XAtom lookup(String name) {
 162         synchronized (XAtom.class) {
 163             return nameToAtom.get(name);
 164         }
 165     }
 166     /*
 167      * [das]Suggestion:
 168      * 1.Make XAtom immutable.
 169      * 2.Replace public ctors with factory methods (e.g. get() below).
 170      */
 171     static XAtom get(long atom) {
 172         XAtom xatom = lookup(atom);
 173         if (xatom == null) {
 174             xatom = new XAtom(XToolkit.getDisplay(), atom);
 175         }
 176         return xatom;
 177     }
 178     public static XAtom get(String name) {
 179         XAtom xatom = lookup(name);
 180         if (xatom == null) {
 181             xatom = new XAtom(XToolkit.getDisplay(), name);
 182         }
 183         return xatom;
 184     }
 185     public String getName() {
 186         if (name == null) {
 187             XToolkit.awtLock();
 188             try {
 189                 this.name = XlibWrapper.XGetAtomName(display, atom);
 190             } finally {
 191                 XToolkit.awtUnlock();
 192             }
 193             register();
 194         }
 195         return name;
 196     }
 197     static String asString(long atom) {
 198         XAtom at = lookup(atom);
 199         if (at == null) {
 200             return Long.toString(atom);
 201         } else {
 202             return at.toString();
 203         }
 204     }
 205     void register() {
 206         register(this);
 207     }
 208     public String toString() {
 209         if (name != null) {
 210             return name + ":" + atom;
 211         } else {
 212             return Long.toString(atom);
 213         }
 214     }
 215 
 216     /* interned value of Atom */
 217     long atom = 0;
 218 
 219     /* name of atom */
 220     String name;
 221 
 222     /* display for X connection */
 223     long display;
 224 
 225 
 226     /**  This constructor will create and intern a new XAtom that is specified
 227      *  by the supplied name.
 228      *
 229      * @param display X display to use
 230      * @param name name of the XAtom to create.
 231      * @since 1.5
 232      */
 233 
 234     private XAtom(long display, String name) {
 235         this(display, name, true);
 236     }
 237 
 238     public XAtom(String name, boolean autoIntern) {
 239         this(XToolkit.getDisplay(), name, autoIntern);
 240     }
 241 
 242     /**  This constructor will create an instance of XAtom that is specified
 243      *  by the predefined XAtom specified by u {@code latom}
 244      *
 245      * @param display X display to use.
 246      * @param atom a predefined XAtom.
 247      * @since 1.5
 248      */
 249     public XAtom(long display, long atom) {
 250         this.atom = atom;
 251         this.display = display;
 252         register();
 253     }
 254 
 255     /**  This constructor will create the instance,
 256      *  and if {@code autoIntern} is true intern a new XAtom that is specified
 257      *  by the supplied name.
 258      *
 259      * @param display X display to use
 260      * @param name name of the XAtom to create.
 261      * @since 1.5
 262      */
 263 
 264     private XAtom(long display, String name, boolean autoIntern) {
 265         this.name = name;
 266         this.display = display;
 267         if (autoIntern) {
 268             XToolkit.awtLock();
 269             try {
 270                 atom = XlibWrapper.InternAtom(display,name,0);
 271             } finally {
 272                 XToolkit.awtUnlock();
 273             }
 274         }
 275         register();
 276     }
 277 
 278     /**
 279      * Creates uninitialized instance of
 280      */
 281     public XAtom() {
 282     }
 283 
 284     /**  Sets the window property for the specified window
 285      * @param window window id to use
 286      * @param str value to set to.
 287      * @since 1.5
 288      */
 289     public void setProperty(long window, String str) {
 290         if (atom == 0) {
 291             throw new IllegalStateException("Atom should be initialized");
 292         }
 293         checkWindow(window);
 294         XToolkit.awtLock();
 295         try {
 296             XlibWrapper.SetProperty(display,window,atom,str);
 297         } finally {
 298             XToolkit.awtUnlock();
 299         }
 300     }
 301 
 302     /**
 303      * Sets UTF8_STRING type property. Explicitly converts str to UTF-8 byte sequence.
 304      */
 305     public void setPropertyUTF8(long window, String str) {
 306         XAtom XA_UTF8_STRING = XAtom.get("UTF8_STRING");   /* like STRING but encoding is UTF-8 */
 307         if (atom == 0) {
 308             throw new IllegalStateException("Atom should be initialized");
 309         }
 310         checkWindow(window);
 311         byte[] bdata = null;
 312         try {
 313             bdata = str.getBytes("UTF-8");
 314         } catch (java.io.UnsupportedEncodingException uee) {
 315             uee.printStackTrace();
 316         }
 317         if (bdata != null) {
 318             setAtomData(window, XA_UTF8_STRING.atom, bdata);
 319         }
 320     }
 321 
 322     /**
 323      * Sets STRING/8 type property. Explicitly converts str to Latin-1 byte sequence.
 324      */
 325     public void setProperty8(long window, String str) {
 326         if (atom == 0) {
 327             throw new IllegalStateException("Atom should be initialized");
 328         }
 329         checkWindow(window);
 330         byte[] bdata = null;
 331         try {
 332             bdata = str.getBytes("ISO-8859-1");
 333         } catch (java.io.UnsupportedEncodingException uee) {
 334             uee.printStackTrace();
 335         }
 336         if (bdata != null) {
 337             setAtomData(window, XA_STRING, bdata);
 338         }
 339     }
 340 
 341 
 342     /**  Gets the window property for the specified window
 343      * @param window window id to use
 344      * @return string with the property.
 345      * @since 1.5
 346      */
 347     public String getProperty(long window) {
 348         if (atom == 0) {
 349             throw new IllegalStateException("Atom should be initialized");
 350         }
 351         checkWindow(window);
 352         XToolkit.awtLock();
 353         try {
 354             return XlibWrapper.GetProperty(display,window,atom);
 355         } finally {
 356             XToolkit.awtUnlock();
 357         }
 358     }
 359 
 360 
 361     /*
 362      * Auxiliary function that returns the value of 'property' of type
 363      * 'property_type' on window 'window'.  Format of the property must be 32.
 364      */
 365     public long get32Property(long window, long property_type) {
 366         if (atom == 0) {
 367             throw new IllegalStateException("Atom should be initialized");
 368         }
 369         checkWindow(window);
 370         WindowPropertyGetter getter =
 371             new WindowPropertyGetter(window, this, 0, 1,
 372                                      false, property_type);
 373         try {
 374             int status = getter.execute();
 375             if (status != XConstants.Success || getter.getData() == 0) {
 376                 return 0;
 377             }
 378             if (getter.getActualType() != property_type || getter.getActualFormat() != 32) {
 379                 return 0;
 380             }
 381             return Native.getCard32(getter.getData());
 382         } finally {
 383             getter.dispose();
 384         }
 385     }
 386 
 387     /**
 388      *  Returns value of property of type CARDINAL/32 of this window
 389      */
 390     public long getCard32Property(XBaseWindow window) {
 391         return get32Property(window.getWindow(), XA_CARDINAL);
 392     }
 393 
 394     /**
 395      * Sets property of type CARDINAL on the window
 396      */
 397     public void setCard32Property(long window, long value) {
 398         if (atom == 0) {
 399             throw new IllegalStateException("Atom should be initialized");
 400         }
 401         checkWindow(window);
 402         XToolkit.awtLock();
 403         try {
 404             Native.putCard32(XlibWrapper.larg1, value);
 405             XlibWrapper.XChangeProperty(XToolkit.getDisplay(), window,
 406                 atom, XA_CARDINAL, 32, XConstants.PropModeReplace,
 407                 XlibWrapper.larg1, 1);
 408         } finally {
 409             XToolkit.awtUnlock();
 410         }
 411     }
 412 
 413     /**
 414      * Sets property of type CARDINAL/32 on the window
 415      */
 416     public void setCard32Property(XBaseWindow window, long value) {
 417         setCard32Property(window.getWindow(), value);
 418     }
 419 
 420     /**
 421      * Gets uninterpreted set of data from property and stores them in data_ptr.
 422      * Property type is the same as current atom, property is current atom.
 423      * Property format is 32. Property 'delete' is false.
 424      * Returns boolean if requested type, format, length match returned values
 425      * and returned data pointer is not null.
 426      */
 427     public boolean getAtomData(long window, long data_ptr, int length) {
 428         if (atom == 0) {
 429             throw new IllegalStateException("Atom should be initialized");
 430         }
 431         checkWindow(window);
 432         WindowPropertyGetter getter =
 433             new WindowPropertyGetter(window, this, 0, (long)length,
 434                                      false, this);
 435         try {
 436             int status = getter.execute();
 437             if (status != XConstants.Success || getter.getData() == 0) {
 438                 return false;
 439             }
 440             if (getter.getActualType() != atom
 441                 || getter.getActualFormat() != 32
 442                 || getter.getNumberOfItems() != length
 443                 )
 444                 {
 445                     return false;
 446                 }
 447             XlibWrapper.memcpy(data_ptr, getter.getData(), length*getAtomSize());
 448             return true;
 449         } finally {
 450             getter.dispose();
 451         }
 452     }
 453 
 454     /**
 455      * Gets uninterpreted set of data from property and stores them in data_ptr.
 456      * Property type is {@code type}, property is current atom.
 457      * Property format is 32. Property 'delete' is false.
 458      * Returns boolean if requested type, format, length match returned values
 459      * and returned data pointer is not null.
 460      */
 461     public boolean getAtomData(long window, long type, long data_ptr, int length) {
 462         if (atom == 0) {
 463             throw new IllegalStateException("Atom should be initialized");
 464         }
 465         checkWindow(window);
 466         WindowPropertyGetter getter =
 467             new WindowPropertyGetter(window, this, 0, (long)length,
 468                                      false, type);
 469         try {
 470             int status = getter.execute();
 471             if (status != XConstants.Success || getter.getData() == 0) {
 472                 return false;
 473             }
 474             if (getter.getActualType() != type
 475                 || getter.getActualFormat() != 32
 476                 || getter.getNumberOfItems() != length
 477                 )
 478                 {
 479                     return false;
 480                 }
 481             XlibWrapper.memcpy(data_ptr, getter.getData(), length*getAtomSize());
 482             return true;
 483         } finally {
 484             getter.dispose();
 485         }
 486     }
 487 
 488     /**
 489      * Sets uninterpreted set of data into property from data_ptr.
 490      * Property type is the same as current atom, property is current atom.
 491      * Property format is 32. Mode is PropModeReplace. length is a number
 492      * of items pointer by data_ptr.
 493      */
 494     public void setAtomData(long window, long data_ptr, int length) {
 495         if (atom == 0) {
 496             throw new IllegalStateException("Atom should be initialized");
 497         }
 498         checkWindow(window);
 499         XToolkit.awtLock();
 500         try {
 501             XlibWrapper.XChangeProperty(XToolkit.getDisplay(), window,
 502                 atom, atom, 32, XConstants.PropModeReplace,
 503                 data_ptr, length);
 504         } finally {
 505             XToolkit.awtUnlock();
 506         }
 507     }
 508 
 509     /**
 510      * Sets uninterpreted set of data into property from data_ptr.
 511      * Property type is {@code type}, property is current atom.
 512      * Property format is 32. Mode is PropModeReplace. length is a number
 513      * of items pointer by data_ptr.
 514      */
 515     public void setAtomData(long window, long type, long data_ptr, int length) {
 516         if (atom == 0) {
 517             throw new IllegalStateException("Atom should be initialized");
 518         }
 519         checkWindow(window);
 520         XToolkit.awtLock();
 521         try {
 522             XlibWrapper.XChangeProperty(XToolkit.getDisplay(), window,
 523                 atom, type, 32, XConstants.PropModeReplace,
 524                 data_ptr, length);
 525         } finally {
 526             XToolkit.awtUnlock();
 527         }
 528     }
 529 
 530     /**
 531      * Sets uninterpreted set of data into property from data_ptr.
 532      * Property type is {@code type}, property is current atom.
 533      * Property format is 8. Mode is PropModeReplace. length is a number
 534      * of bytes pointer by data_ptr.
 535      */
 536     public void setAtomData8(long window, long type, long data_ptr, int length) {
 537         if (atom == 0) {
 538             throw new IllegalStateException("Atom should be initialized");
 539         }
 540         checkWindow(window);
 541         XToolkit.awtLock();
 542         try {
 543             XlibWrapper.XChangeProperty(XToolkit.getDisplay(), window,
 544                 atom, type, 8, XConstants.PropModeReplace,
 545                 data_ptr, length);
 546         } finally {
 547             XToolkit.awtUnlock();
 548         }
 549     }
 550 
 551     /**
 552      * Deletes property specified by this item on the window.
 553      */
 554     public void DeleteProperty(long window) {
 555         if (atom == 0) {
 556             throw new IllegalStateException("Atom should be initialized");
 557         }
 558         checkWindow(window);
 559         XToolkit.awtLock();
 560         try {
 561              XlibWrapper.XDeleteProperty(XToolkit.getDisplay(), window, atom);
 562         } finally {
 563             XToolkit.awtUnlock();
 564         }
 565     }
 566 
 567     /**
 568      * Deletes property specified by this item on the window.
 569      */
 570     public void DeleteProperty(XBaseWindow window) {
 571         if (atom == 0) {
 572             throw new IllegalStateException("Atom should be initialized");
 573         }
 574         checkWindow(window.getWindow());
 575         XToolkit.awtLock();
 576         try {
 577             XlibWrapper.XDeleteProperty(XToolkit.getDisplay(),
 578                 window.getWindow(), atom);
 579         } finally {
 580             XToolkit.awtUnlock();
 581         }
 582     }
 583 
 584     public void setAtomData(long window, long property_type, byte[] data) {
 585         long bdata = Native.toData(data);
 586         try {
 587             setAtomData8(window, property_type, bdata, data.length);
 588         } finally {
 589             unsafe.freeMemory(bdata);
 590         }
 591     }
 592 
 593     /*
 594      * Auxiliary function that returns the value of 'property' of type
 595      * 'property_type' on window 'window'.  Format of the property must be 8.
 596      */
 597     public byte[] getByteArrayProperty(long window, long property_type) {
 598         if (atom == 0) {
 599             throw new IllegalStateException("Atom should be initialized");
 600         }
 601         checkWindow(window);
 602         WindowPropertyGetter getter =
 603             new WindowPropertyGetter(window, this, 0, 0xFFFF,
 604                                      false, property_type);
 605         try {
 606             int status = getter.execute();
 607             if (status != XConstants.Success || getter.getData() == 0) {
 608                 return null;
 609             }
 610             if (getter.getActualType() != property_type || getter.getActualFormat() != 8) {
 611                 return null;
 612             }
 613             byte[] res = XlibWrapper.getStringBytes(getter.getData());
 614             return res;
 615         } finally {
 616             getter.dispose();
 617         }
 618     }
 619 
 620     /**
 621      * Interns the XAtom
 622      */
 623     public void intern(boolean onlyIfExists) {
 624         XToolkit.awtLock();
 625         try {
 626             atom = XlibWrapper.InternAtom(display,name, onlyIfExists?1:0);
 627         } finally {
 628             XToolkit.awtUnlock();
 629         }
 630         register();
 631     }
 632 
 633     public boolean isInterned() {
 634         if (atom == 0) {
 635             XToolkit.awtLock();
 636             try {
 637                 atom = XlibWrapper.InternAtom(display, name, 1);
 638             } finally {
 639                 XToolkit.awtUnlock();
 640             }
 641             if (atom == 0) {
 642                 return false;
 643             } else {
 644                 register();
 645                 return true;
 646             }
 647         } else {
 648             return true;
 649         }
 650     }
 651 
 652     public void setValues(long display, String name, long atom) {
 653         this.display = display;
 654         this.atom = atom;
 655         this.name = name;
 656         register();
 657     }
 658 
 659     static int getAtomSize() {
 660         return Native.getLongSize();
 661     }
 662 
 663     /*
 664      * Returns the value of property ATOM[]/32 as array of XAtom objects
 665      * @return array of atoms, array of length 0 if the atom list is empty
 666      *         or has different format
 667      */
 668     XAtom[] getAtomListProperty(long window) {
 669         if (atom == 0) {
 670             throw new IllegalStateException("Atom should be initialized");
 671         }
 672         checkWindow(window);
 673 
 674         WindowPropertyGetter getter =
 675             new WindowPropertyGetter(window, this, 0, 0xFFFF,
 676                                      false, XA_ATOM);
 677         try {
 678             int status = getter.execute();
 679             if (status != XConstants.Success || getter.getData() == 0) {
 680                 return emptyList;
 681             }
 682             if (getter.getActualType() != XA_ATOM || getter.getActualFormat() != 32) {
 683                 return emptyList;
 684             }
 685 
 686             int count = getter.getNumberOfItems();
 687             if (count == 0) {
 688                 return emptyList;
 689             }
 690             long list_atoms = getter.getData();
 691             XAtom[] res = new XAtom[count];
 692             for (int index = 0; index < count; index++) {
 693                 res[index] = XAtom.get(XAtom.getAtom(list_atoms+index*getAtomSize()));
 694             }
 695             return res;
 696         } finally {
 697             getter.dispose();
 698         }
 699     }
 700 
 701     /*
 702      * Returns the value of property of type ATOM[]/32 as XAtomList
 703      * @return list of atoms, empty list if the atom list is empty
 704      *         or has different format
 705      */
 706     XAtomList getAtomListPropertyList(long window) {
 707         return new XAtomList(getAtomListProperty(window));
 708     }
 709     XAtomList getAtomListPropertyList(XBaseWindow window) {
 710         return getAtomListPropertyList(window.getWindow());
 711     }
 712     XAtom[] getAtomListProperty(XBaseWindow window) {
 713         return getAtomListProperty(window.getWindow());
 714     }
 715 
 716     /**
 717      * Sets property value of type ATOM list to the list of atoms.
 718      */
 719     void setAtomListProperty(long window, XAtom[] atoms) {
 720         long data = toData(atoms);
 721         setAtomData(window, XAtom.XA_ATOM, data, atoms.length);
 722         unsafe.freeMemory(data);
 723     }
 724 
 725     /**
 726      * Sets property value of type ATOM list to the list of atoms specified by XAtomList
 727      */
 728     void setAtomListProperty(long window, XAtomList atoms) {
 729         long data = atoms.getAtomsData();
 730         setAtomData(window, XAtom.XA_ATOM, data, atoms.size());
 731         unsafe.freeMemory(data);
 732     }
 733     /**
 734      * Sets property value of type ATOM list to the list of atoms.
 735      */
 736     public void setAtomListProperty(XBaseWindow window, XAtom[] atoms) {
 737         setAtomListProperty(window.getWindow(), atoms);
 738     }
 739 
 740     /**
 741      * Sets property value of type ATOM list to the list of atoms specified by XAtomList
 742      */
 743     public void setAtomListProperty(XBaseWindow window, XAtomList atoms) {
 744         setAtomListProperty(window.getWindow(), atoms);
 745     }
 746 
 747     long getAtom() {
 748         return atom;
 749     }
 750 
 751     void putAtom(long ptr) {
 752         Native.putLong(ptr, atom);
 753     }
 754 
 755     static long getAtom(long ptr) {
 756         return Native.getLong(ptr);
 757     }
 758     /**
 759      * Allocated memory to hold the list of native atom data and returns unsafe pointer to it
 760      * Caller should free the memory by himself.
 761      */
 762     static long toData(XAtom[] atoms) {
 763         long data = unsafe.allocateMemory(getAtomSize() * atoms.length);
 764         for (int i = 0; i < atoms.length; i++ ) {
 765             if (atoms[i] != null) {
 766                 atoms[i].putAtom(data + i * getAtomSize());
 767             }
 768         }
 769         return data;
 770     }
 771 
 772     void checkWindow(long window) {
 773         if (window == 0) {
 774             throw new IllegalArgumentException("Window must not be zero");
 775         }
 776     }
 777 
 778     public boolean equals(Object o) {
 779         if (!(o instanceof XAtom)) {
 780             return false;
 781         }
 782         XAtom ot = (XAtom)o;
 783         return (atom == ot.atom && display == ot.display);
 784     }
 785     public int hashCode() {
 786         return (int)((atom ^ display)& 0xFFFFL);
 787     }
 788 
 789     /**
 790      * Sets property on the {@code window} to the value {@code window_value}
 791      * Property is assumed to be of type WINDOW/32
 792      */
 793     public void setWindowProperty(long window, long window_value) {
 794         if (atom == 0) {
 795             throw new IllegalStateException("Atom should be initialized");
 796         }
 797         checkWindow(window);
 798         XToolkit.awtLock();
 799         try {
 800             Native.putWindow(XlibWrapper.larg1, window_value);
 801             XlibWrapper.XChangeProperty(XToolkit.getDisplay(), window,
 802                                     atom, XA_WINDOW, 32, XConstants.PropModeReplace,
 803                                     XlibWrapper.larg1, 1);
 804         } finally {
 805             XToolkit.awtUnlock();
 806         }
 807     }
 808     public void setWindowProperty(XBaseWindow window, XBaseWindow window_value) {
 809         setWindowProperty(window.getWindow(), window_value.getWindow());
 810     }
 811 
 812     /**
 813      * Gets property on the {@code window}. Property is assumed to be
 814      * of type WINDOW/32.
 815      */
 816     public long getWindowProperty(long window) {
 817         if (atom == 0) {
 818             throw new IllegalStateException("Atom should be initialized");
 819         }
 820         checkWindow(window);
 821         WindowPropertyGetter getter =
 822             new WindowPropertyGetter(window, this, 0, 1,
 823                                      false, XA_WINDOW);
 824         try {
 825             int status = getter.execute();
 826             if (status != XConstants.Success || getter.getData() == 0) {
 827                 return 0;
 828             }
 829             if (getter.getActualType() != XA_WINDOW || getter.getActualFormat() != 32) {
 830                 return 0;
 831             }
 832             return Native.getWindow(getter.getData());
 833         } finally {
 834             getter.dispose();
 835         }
 836     }
 837 }
--- EOF ---