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