code cleanup:
[blender.git] / intern / ghost / intern / GHOST_WindowX11.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file ghost/intern/GHOST_WindowX11.cpp
29  *  \ingroup GHOST
30  */
31
32
33 #include "GHOST_WindowX11.h"
34 #include "GHOST_SystemX11.h"
35 #include "STR_String.h"
36 #include "GHOST_Debug.h"
37
38 #ifdef WITH_XDND
39 #include "GHOST_DropTargetX11.h"
40 #endif
41
42 /* For standard X11 cursors */
43 #include <X11/cursorfont.h>
44 #include <X11/Xatom.h>
45
46 #if defined(__sun__) || defined(__sun) || defined(__sparc) || defined(__sparc__) || defined(_AIX)
47 #include <strings.h>
48 #endif
49
50 #include <cstring>
51 #include <cstdio>
52
53 #include <algorithm>
54 #include <string>
55
56 /* For obscure full screen mode stuuf
57  * lifted verbatim from blut. */
58
59 typedef struct {
60         long flags;
61         long functions;
62         long decorations;
63         long input_mode;
64 } MotifWmHints;
65
66 #define MWM_HINTS_DECORATIONS         (1L << 1)
67
68
69 // #define GHOST_X11_GRAB
70
71 /*
72  * A Client can't change the window property, that is
73  * the work of the window manager. In case, we send
74  * a ClientMessage to the RootWindow with the property
75  * and the Action (WM-spec define this):
76  */
77 #define _NET_WM_STATE_REMOVE 0
78 #define _NET_WM_STATE_ADD 1
79 // #define _NET_WM_STATE_TOGGLE 2 // UNUSED
80
81 /*
82  * import bpy
83  * ima = bpy.data.images["blender.png"]
84  * w, h = ima.size
85  * print("%d,%d," % (w, h))
86  * for y in range(h - 1, -1, -1):
87  *     px = []
88  *     for x in range(w):
89  *         p = ((y * w) + x) * 4
90  *         rgba = ima.pixels[p : p + 4]
91  *         rgba = rgba[2], rgba[1], rgba[0], rgba[3]
92  *         px.append(sum((int(p * 255) << (8 * i)) for i, p in enumerate(rgba)))
93  *     print(", ".join([str(p) for p in px]), end=",\n")
94  */
95
96 /* See the python script above to regenerate the 48x48 icon within blender */
97 static long BLENDER_ICON_48x48x32[] = {
98         48,48,
99         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
100         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
101         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
102         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 131820800, 1305304320, 2547014912, 1808620800, 432823296, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
103         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 3218103552, 4074070530, 4276450320, 4124995601, 4090518785, 1624202496, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
104         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 1053710848, 4140916224, 4294348072, 4294483011, 4294483268, 4294153273, 4107626765, 2765053184, 146759680, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
105         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 282025984, 4124007680, 4293884685, 4294482752, 4294483785, 4294483785, 4294417734, 4141905692, 3671088640, 600596224, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
106         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 1573804544, 4124073472, 4293555207, 4294416700, 4294484558, 4294484558, 4294484558, 4260005935, 4073807875, 1355766784, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
107         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 936140032, 3973012736, 4192300034, 4294415154, 4294485331, 4294485074, 4294485074, 4294088514, 4107560459, 2463128832, 79642624, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
108         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 399726848, 3452984576, 4107887616, 4294281765, 4294485590, 4294485591, 4294485590, 4294418767, 4124931612, 3469762048, 449730560, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
109         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 97281536, 2597412096, 4107427584, 4293951767, 4294485590, 4294551642, 4294486105, 4294485847, 4226320176, 4023344642, 1120754944, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
110         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 1389190400, 2949668096, 4073741568, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4291714048, 4158482693, 4294484301, 4294552415, 4294552157, 4294551899, 4294486105, 4293957442, 4124206089, 2144427008, 33488896, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
111         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 1171217408, 4107361792, 4293425685, 4294218035, 4294482753, 4294483268, 4294483783, 4294484043, 4294484558, 4294484817, 4294485331, 4294485591, 4294486105, 4294551899, 4294552157, 4294552415, 4294552672, 4294552673, 4294552930, 4294552674, 4294552674, 4294553188, 4294553190, 4294552932, 4294552674, 4294552415, 4294552156, 4294551642, 4294287696, 4124733464, 3234946560, 315970816, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
112         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 3838860800, 4293620999, 4294416700, 4294482753, 4294483269, 4294483784, 4294484300, 4294484816, 4294485331, 4294485591, 4294551642, 4294552157, 4294552672, 4294552931, 4294553446, 4294553704, 4294553962, 4294554220, 4294554221, 4294554221, 4294554220, 4294554220, 4294553962, 4294553704, 4294553190, 4294552931, 4294552416, 4294552157, 4294551642, 4294485590, 4192502315, 3939458305, 919624192, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
113         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 3838860800, 4293751810, 4294415669, 4294482753, 4294483268, 4294483784, 4294484300, 4294484816, 4294485331, 4294485591, 4294551642, 4294552157, 4294552932, 4294553447, 4294553962, 4294554220, 4294554479, 4294554737, 4294554994, 4294554994, 4294554994, 4294554737, 4294554479, 4294554220, 4294553705, 4294553446, 4294552931, 4294552416, 4294552156, 4294486105, 4294485589, 4293824827, 4124140038, 1741708800, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
114         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 2463128832, 4191905024, 4294145792, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294345234, 4294553447, 4294554221, 4294554736, 4294620787, 4294621045, 4294621047, 4294621303, 4294621047, 4294621045, 4294554995, 4294554737, 4294554220, 4294553705, 4294553190, 4294552930, 4294552414, 4294551899, 4294485847, 4294485590, 4294155594, 4141050128, 1573936384, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
115         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 248011520, 2983288320, 4191116288, 4174405120, 4174405120, 4174405120, 4174405120, 4174405120, 4174405120, 4174405120, 4174405120, 4207959552, 4294214422, 4294554220, 4294554736, 4294620787, 4294621046, 4294621562, 4294621820, 4294690967, 4294761660, 4294830292, 4294899180, 4294966780, 4294898406, 4294829002, 4294759597, 4294621304, 4294552416, 4294551900, 4294485848, 4294485332, 4294485590, 4294221646, 4140984079, 1204641024, 4671303, 4671303, 4671303, 4671303, 4671303,
116         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 79642624, 282025984, 282025984, 282025984, 282025984, 282025984, 282025984, 1540316160, 4124007680, 4226185237, 4294552156, 4294554221, 4294554737, 4294620789, 4294621561, 4294623367, 4294829774, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294966778, 4294759856, 4294552674, 4294486105, 4294485589, 4294484817, 4294551127, 4294089804, 4090651658, 885939456, 4671303, 4671303, 4671303, 4671303,
117         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 97281536, 2513394688, 4124139264, 4293888040, 4294552931, 4294553705, 4294554478, 4294554737, 4294621045, 4294692513, 4294900470, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294898922, 4294621046, 4294485589, 4294484817, 4294484558, 4294551383, 4293891393, 4023344385, 432823296, 4671303, 4671303, 4671303,
118         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 583752192, 3604045056, 4124796420, 4294285115, 4294552672, 4294553189, 4294553704, 4294554220, 4294554736, 4294623367, 4294769142, 4294835709, 4294835709, 4294835709, 4293192946, 4289446870, 4287803851, 4286620866, 4287738058, 4289446871, 4293850103, 4294901502, 4294901502, 4294901502, 4294898406, 4294552157, 4294484816, 4294484301, 4294484299, 4294486105, 4192502057, 2530172416, 4671303, 4671303, 4671303,
119         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 1473075968, 4090518784, 4259673101, 4294484042, 4294551899, 4294552415, 4294552931, 4294553447, 4294553962, 4294554995, 4294700770, 4294704123, 4294704123, 4294769916, 4290169563, 4286555330, 4286423745, 4286292416, 4286095038, 4285897917, 4285635259, 4285766844, 4291155427, 4294769916, 4294769916, 4294769916, 4294628011, 4294278923, 4294278408, 4294278149, 4294279181, 4294149404, 4140784896, 365846784, 4671303, 4671303,
120         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 163992832, 2731564288, 4124205057, 4293952286, 4294484816, 4294485590, 4294551642, 4294552157, 4294552673, 4294553188, 4294553704, 4294561702, 4294572537, 4294572537, 4294638330, 4291023841, 4286226623, 4286226623, 4286160831, 4286029502, 4285832381, 4285700795, 4284977846, 4282414755, 4280706199, 4290629597, 4294572537, 4294572537, 4294572537, 4294350393, 4294277376, 4294277376, 4294277633, 4294413864, 4158482692, 1875663872, 4671303, 4671303,
121         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 718166784, 3738197248, 4141705477, 4294283568, 4294484815, 4294484816, 4294485332, 4294485848, 4294551899, 4294552158, 4294552673, 4294553188, 4294500036, 4294440951, 4294506744, 4294243830, 4286292159, 4285963709, 4285898173, 4285832381, 4285766588, 4285372345, 4282349219, 4279391885, 4279063179, 4279063179, 4281954719, 4294375158, 4294375158, 4294375158, 4294357617, 4294277376, 4294277376, 4294277376, 4294346781, 4293557270, 3218103552, 4671303, 4671303,
122         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 1691311104, 4124007936, 4276647182, 4294416701, 4294483784, 4294484043, 4294484558, 4294485073, 4294485332, 4294485848, 4294551899, 4294552158, 4294552672, 4294372579, 4294375158, 4294375158, 4291943654, 4285569467, 4285635003, 4285569467, 4285503674, 4282875047, 4279654800, 4279063179, 4279063179, 4279063179, 4279063179, 4279128971, 4292732137, 4294177779, 4294177779, 4294233511, 4294277376, 4294277376, 4294277376, 4294344717, 4294217516, 4140784640, 50298880, 4671303,
123         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 232284672, 2949668096, 4107559426, 4294017820, 4294416960, 4294482753, 4294483268, 4294416959, 4294413348, 4294347296, 4294417474, 4294485332, 4294485848, 4294551642, 4294487137, 4294177779, 4294243572, 4294243572, 4290958047, 4285306552, 4285306553, 4284583603, 4280509077, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4291417567, 4293980400, 4294046193, 4294107085, 4294277376, 4294277376, 4294277376, 4294277376, 4294416185, 4207959811, 232284672, 4671303,
124         4671303, 4671303, 4671303, 4671303, 4671303, 852253696, 3855638016, 4158614278, 4294348586, 4294416701, 4294416443, 4294416958, 4294415411, 4294280731, 4108283403, 4243290129, 4294414638, 4294484817, 4294485331, 4294485590, 4294485848, 4294174941, 4294111986, 4294111986, 4292206309, 4284977846, 4283137961, 4279457678, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279457422, 4293454571, 4293848814, 4293848814, 4294035617, 4294277376, 4294277376, 4294277376, 4294277376, 4294416443, 4140916998, 365846784, 4671303,
125         4671303, 4671303, 4671303, 4671303, 1909480704, 4124073472, 4293490704, 4294415154, 4294415669, 4294415669, 4294416184, 4294414123, 4294083611, 4090914310, 4040055808, 4293161999, 4294414379, 4294484557, 4294484815, 4294485074, 4294485331, 4294104247, 4293914607, 4293914607, 4293783279, 4283334569, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4284057260, 4293585642, 4293651435, 4293651435, 4293962857, 4294277376, 4294277376, 4294277376, 4294277376, 4294416959, 4124205832, 499800064, 4671303,
126         4671303, 4671303, 298998272, 3150929152, 4107690755, 4294018076, 4294415410, 4294414636, 4294414638, 4294415153, 4294413606, 4293886234, 4124205059, 2110675968, 2060409856, 4225921807, 4294414895, 4294483785, 4294484043, 4294484557, 4294484815, 4294164622, 4293783021, 4293717228, 4293388263, 4290299602, 4279326093, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4280245907, 4292205535, 4293454056, 4293454056, 4293454056, 4294086704, 4294277376, 4294277376, 4294277376, 4294277891, 4294417992, 4207894017, 97281536, 4671303,
127         4671303, 50298880, 3503250688, 4192169224, 4294282278, 4294414381, 4294347813, 4294413865, 4294414122, 4294348070, 4259937303, 4090519041, 1305304320, 4671303, 1238260480, 4024002053, 4294415926, 4294483269, 4294483527, 4294483784, 4294484043, 4294419022, 4293712069, 4293190884, 4293059298, 4293059298, 4289905102, 4281297305, 4279063179, 4279063179, 4279063179, 4279063179, 4279063179, 4282677154, 4291351001, 4293256677, 4293256677, 4293256677, 4293639310, 4294277376, 4294277376, 4294277376, 4294277376, 4294345490, 4294022463, 3671088640, 4671303, 4671303,
128         4671303, 2077187328, 4107822598, 4294348586, 4294347555, 4294347039, 4294347554, 4294348069, 4294348327, 4175590163, 3872349440, 718166784, 4671303, 4671303, 449730560, 4124073472, 4294414379, 4294417217, 4294483010, 4294483268, 4294483269, 4294415927, 4294084898, 4292925905, 4292861919, 4292861919, 4292927712, 4292533470, 4288656582, 4286094006, 4284517036, 4286685370, 4289379531, 4292927713, 4293059298, 4293059298, 4293059298, 4293251260, 4294212873, 4294277376, 4294277376, 4294277376, 4294277376, 4294414896, 4259939884, 2681167104, 4671303, 4671303,
129         97281536, 4191116288, 4294084386, 4294413347, 4294346265, 4294346780, 4294413091, 4294282281, 4124732172, 3335609856, 315970816, 4671303, 4671303, 4671303, 16777216, 3452853504, 4293624609, 4294415670, 4294416702, 4294416959, 4294414121, 4294277634, 4294277376, 4293825597, 4292793547, 4292664540, 4292730333, 4292730333, 4292730333, 4292730333, 4292796126, 4292796126, 4292796126, 4292796126, 4292861919, 4292861919, 4293120190, 4294085156, 4294277376, 4294277376, 4294277376, 4294277376, 4294278149, 4294485332, 4074071305, 969825792, 4671303, 4671303,
130         198270208, 4224605184, 4294282535, 4294413347, 4294346524, 4294348070, 4294085417, 4107559687, 2563792384, 79642624, 4671303, 4671303, 83886080, 184549376, 268435456, 1605258752, 4074137355, 4294416185, 4294346522, 4294278666, 4294277376, 4294277376, 4294277376, 4294277376, 4294213647, 4293243263, 4292532696, 4292532954, 4292532954, 4292598747, 4292598747, 4292598747, 4292598747, 4292664540, 4292794579, 4293568616, 4294212357, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294414895, 4293890877, 3570425344, 4671303, 4671303, 4671303,
131         4671303, 3352387072, 4192301839, 4294282279, 4294019626, 4192302873, 4124139523, 1708088576, 4671303, 4671303, 67108864, 184549376, 285212672, 385875968, 486539264, 638387968, 3888864256, 4276847393, 4294414896, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4293954086, 4293502050, 4293179274, 4292855728, 4292662218, 4292920489, 4293243778, 4293501275, 4294083608, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294345491, 4294420571, 4107626251, 1322146816, 4671303, 4671303, 4671303,
132         4671303, 382819584, 3134217472, 4191116288, 3939458560, 2211470592, 533617152, 4671303, 4671303, 117440512, 218103808, 335544320, 436207616, 553648128, 654311424, 771751936, 1534079488, 4157496833, 4294219326, 4294346523, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294278150, 4294485590, 4175527207, 2932497152, 117440512, 4671303, 4671303, 4671303,
133         4671303, 4671303, 4671303, 50298880, 33488896, 4671303, 4671303, 4671303, 83886080, 201326592, 318767104, 436207616, 553648128, 671088640, 788529152, 889192448, 1006632960, 2493203712, 4157958415, 4294352457, 4294347039, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294278924, 4294486105, 4260073533, 3872218112, 525476096, 218103808, 100663296, 4671303, 4671303,
134         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 16777216, 134217728, 251658240, 369098752, 486539264, 603979776, 721420288, 855638016, 973078528, 1090519040, 1207959552, 2930002688, 4174604044, 4294221386, 4294414637, 4294277634, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294346522, 4294552931, 4226189107, 3888929792, 997536768, 385875968, 251658240, 150994944, 16777216, 4671303,
135         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 16777216, 134217728, 251658240, 369098752, 486539264, 603979776, 721420288, 855638016, 956301312, 1073741824, 1191182336, 1325400064, 2693873664, 4191117319, 4293891393, 4294485073, 4294347296, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294344717, 4294484299, 4294421863, 4208884260, 3687340544, 910958848, 503316480, 385875968, 251658240, 134217728, 16777216, 4671303,
136         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 83886080, 201326592, 318767104, 436207616, 536870912, 671088640, 771751936, 889192448, 989855744, 1107296256, 1207959552, 1325400064, 2187996928, 3972487680, 4191711513, 4294156111, 4294485591, 4294415926, 4294346007, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294277376, 4294278408, 4294414379, 4294484817, 4294554221, 4259941691, 4157628420, 2746568960, 807735296, 553648128, 436207616, 318767104, 218103808, 83886080, 4671303, 4671303,
137         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 100663296, 218103808, 318767104, 436207616, 536870912, 637534208, 754974720, 855638016, 956301312, 1040187392, 1140850688, 1224736768, 1342833408, 2677293568, 4174142464, 4157959447, 4276718648, 4294288986, 4294554220, 4294552415, 4294485074, 4294484300, 4294551641, 4294553705, 4294554738, 4294025043, 4175528237, 4174405895, 3384956928, 1264790528, 654311424, 553648128, 436207616, 335544320, 218103808, 117440512, 4671303, 4671303, 4671303,
138         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 50331648, 167772160, 268435456, 385875968, 469762048, 553648128, 654311424, 738197504, 822083584, 905969664, 973078528, 1023410176, 1090519040, 1208878848, 2054632960, 3165868032, 4123810816, 4224671493, 4157762069, 4124604196, 4141644844, 4124471839, 4174538769, 4241448451, 3586611712, 2275493888, 1078731776, 671088640, 570425344, 486539264, 385875968, 285212672, 184549376, 67108864, 4671303, 4671303, 4671303, 4671303,
139         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 67108864, 167772160, 251658240, 335544320, 419430400, 503316480, 570425344, 637534208, 704643072, 738197504, 788529152, 822083584, 855638016, 872415232, 889192448, 1042616320, 1365125376, 1702770688, 1821064448, 1467299072, 1095443200, 738985472, 637534208, 587202560, 503316480, 436207616, 352321536, 268435456, 184549376, 67108864, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
140         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 16777216, 67108864, 150994944, 234881024, 301989888, 352321536, 402653184, 452984832, 486539264, 520093696, 536870912, 553648128, 570425344, 570425344, 553648128, 536870912, 520093696, 486539264, 452984832, 402653184, 352321536, 301989888, 234881024, 167772160, 67108864, 16777216, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
141         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 50331648, 83886080, 134217728, 167772160, 201326592, 218103808, 234881024, 251658240, 251658240, 234881024, 218103808, 201326592, 167772160, 134217728, 83886080, 50331648, 16777216, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
142         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
143         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
144         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
145         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
146         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
147 };
148
149
150 GLXContext GHOST_WindowX11::s_firstContext = NULL;
151
152 GHOST_WindowX11::
153 GHOST_WindowX11(
154     GHOST_SystemX11 *system,
155     Display *display,
156     const STR_String& title,
157     GHOST_TInt32 left,
158     GHOST_TInt32 top,
159     GHOST_TUns32 width,
160     GHOST_TUns32 height,
161     GHOST_TWindowState state,
162     const GHOST_TEmbedderWindowID parentWindow,
163     GHOST_TDrawingContextType type,
164     const bool stereoVisual,
165     const bool exclusive,
166     const GHOST_TUns16 numOfAASamples
167     ) :
168         GHOST_Window(width, height, state, type, stereoVisual, exclusive, numOfAASamples),
169         m_context(NULL),
170         m_display(display),
171         m_normal_state(GHOST_kWindowStateNormal),
172         m_system(system),
173         m_valid_setup(false),
174         m_invalid_window(false),
175         m_empty_cursor(None),
176         m_custom_cursor(None)
177 {
178         
179         /* Set up the minimum atrributes that we require and see if
180          * X can find us a visual matching those requirements. */
181
182         int attributes[40], i, samples;
183         Atom atoms[2];
184         int natom;
185         int glxVersionMajor, glxVersionMinor; /* As in GLX major.minor */
186
187         m_visual = NULL;
188
189         if (!glXQueryVersion(m_display, &glxVersionMajor, &glxVersionMinor)) {
190                 printf("%s:%d: X11 glXQueryVersion() failed, verify working openGL system!\n", __FILE__, __LINE__);
191                 
192                 /* exit if this is the first window */
193                 if (s_firstContext == NULL) {
194                         printf("initial window could not find the GLX extension, exit!\n");
195                         exit(1);
196                 }
197
198                 return;
199         }
200
201         /* Find the display with highest samples, starting at level requested */
202         for (samples = m_numOfAASamples; samples >= 0; samples--) {
203                 i = 0; /* Reusing attributes array, so reset counter */
204
205                 if (m_stereoVisual)
206                         attributes[i++] = GLX_STEREO;
207
208                 attributes[i++] = GLX_RGBA;
209                 attributes[i++] = GLX_DOUBLEBUFFER;
210                 attributes[i++] = GLX_RED_SIZE;   attributes[i++] = 1;
211                 attributes[i++] = GLX_BLUE_SIZE;  attributes[i++] = 1;
212                 attributes[i++] = GLX_GREEN_SIZE; attributes[i++] = 1;
213                 attributes[i++] = GLX_DEPTH_SIZE; attributes[i++] = 1;
214                 attributes[i++] = GLX_ALPHA_SIZE; attributes[i++] = 1;
215                 /* GLX >= 1.4 required for multi-sample */
216                 if (samples && (glxVersionMajor >= 1) && (glxVersionMinor >= 4)) {
217                         attributes[i++] = GLX_SAMPLE_BUFFERS; attributes[i++] = 1;
218                         attributes[i++] = GLX_SAMPLES; attributes[i++] = samples;
219                 }
220                 attributes[i] = None;
221
222                 m_visual = glXChooseVisual(m_display, DefaultScreen(m_display), attributes);
223
224                 /* Any sample level or even zero, which means oversampling disabled, is good
225                  * but we need a valid visual to continue */
226                 if (m_visual == NULL) {
227                         if (samples == 0) {
228                                 /* All options exhausted, cannot continue */
229                                 printf("%s:%d: X11 glXChooseVisual() failed, verify working openGL system!\n", __FILE__, __LINE__);
230                                 
231                                 if (s_firstContext == NULL) {
232                                         printf("initial window could not find the GLX extension, exit!\n");
233                                         exit(1);
234                                 }
235                                 
236                                 return;
237                         }
238                 }
239                 else {
240                         if (m_numOfAASamples && (m_numOfAASamples > samples)) {
241                                 printf("%s:%d: oversampling requested %i but using %i samples\n",
242                                        __FILE__, __LINE__, m_numOfAASamples, samples);
243                         }
244                         break;
245                 }
246         }
247
248         /* Create a bunch of attributes needed to create an X window. */
249
250
251         /* First create a colormap for the window and visual.
252          * This seems pretty much a legacy feature as we are in rgba mode anyway. */
253
254         XSetWindowAttributes xattributes;
255         unsigned int xattributes_valuemask = (CWBorderPixel | CWColormap | CWEventMask);
256         memset(&xattributes, 0, sizeof(xattributes));
257
258         xattributes.colormap = XCreateColormap(m_display,
259                                                RootWindow(m_display, m_visual->screen),
260                                                m_visual->visual,
261                                                AllocNone
262                                                );
263
264         xattributes.border_pixel = 0;
265
266         /* Specify which events we are interested in hearing. */
267
268         xattributes.event_mask =
269                 ExposureMask | StructureNotifyMask |
270                 KeyPressMask | KeyReleaseMask |
271                 EnterWindowMask | LeaveWindowMask |
272                 ButtonPressMask | ButtonReleaseMask |
273                 PointerMotionMask | FocusChangeMask |
274                 PropertyChangeMask | KeymapStateMask;
275
276         if (exclusive) {
277                 xattributes_valuemask |= CWOverrideRedirect;
278                 xattributes.override_redirect = True;
279         }
280
281         /* create the window! */
282         if (parentWindow == 0) {
283                 m_window =  XCreateWindow(m_display,
284                                           RootWindow(m_display, m_visual->screen),
285                                           left,
286                                           top,
287                                           width,
288                                           height,
289                                           0,  /* no border. */
290                                           m_visual->depth,
291                                           InputOutput,
292                                           m_visual->visual,
293                                           xattributes_valuemask,
294                                           &xattributes
295                                           );
296         }
297         else {
298
299                 Window root_return;
300                 int x_return, y_return;
301                 unsigned int w_return, h_return, border_w_return, depth_return;
302                 
303                 XGetGeometry(m_display, parentWindow, &root_return, &x_return, &y_return,
304                              &w_return, &h_return, &border_w_return, &depth_return);
305
306                 left = 0;
307                 top = 0;
308                 width = w_return;
309                 height = h_return;
310
311
312                 m_window = XCreateWindow(m_display,
313                                          parentWindow,  /* reparent against embedder */
314                                          left,
315                                          top,
316                                          width,
317                                          height,
318                                          0,     /* no border. */
319                                          m_visual->depth,
320                                          InputOutput,
321                                          m_visual->visual,
322                                          xattributes_valuemask,
323                                          &xattributes
324                                          );
325
326                 XSelectInput(m_display, parentWindow, SubstructureNotifyMask);
327                 
328         }       
329
330 #ifdef WITH_XDND
331         /* initialize drop target for newly created window */
332         m_dropTarget = new GHOST_DropTargetX11(this, m_system);
333         GHOST_PRINT("Set drop target\n");
334 #endif
335
336         if (state == GHOST_kWindowStateMaximized || state == GHOST_kWindowStateFullScreen) {
337                 Atom _NET_WM_STATE = XInternAtom(m_display, "_NET_WM_STATE", False);
338                 Atom _NET_WM_STATE_MAXIMIZED_VERT = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
339                 Atom _NET_WM_STATE_MAXIMIZED_HORZ = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
340                 Atom _NET_WM_STATE_FULLSCREEN     = XInternAtom(m_display, "_NET_WM_STATE_FULLSCREEN", False);
341                 Atom atoms[2];
342                 int count = 0;
343
344                 if (state == GHOST_kWindowStateMaximized) {
345                         atoms[count++] = _NET_WM_STATE_MAXIMIZED_VERT;
346                         atoms[count++] = _NET_WM_STATE_MAXIMIZED_HORZ;
347                 }
348                 else {
349                         atoms[count++] = _NET_WM_STATE_FULLSCREEN;
350                 }
351
352                 XChangeProperty(m_display, m_window, _NET_WM_STATE, XA_ATOM, 32,
353                                 PropModeReplace, (unsigned char *)atoms, count);
354                 m_post_init = False;
355         }
356         /*
357          * One of the problem with WM-spec is that can't set a property
358          * to a window that isn't mapped. That is why we can't "just
359          * call setState" here.
360          *
361          * To fix this, we first need know that the window is really
362          * map waiting for the MapNotify event.
363          *
364          * So, m_post_init indicate that we need wait for the MapNotify
365          * event and then set the Window state to the m_post_state.
366          */
367         else if ((state != GHOST_kWindowStateNormal) && (state != GHOST_kWindowStateMinimized)) {
368                 m_post_init = True;
369                 m_post_state = state;
370         }
371         else {
372                 m_post_init = False;
373                 m_post_state = GHOST_kWindowStateNormal;
374         }
375
376         /* Create some hints for the window manager on how
377          * we want this window treated. */
378
379         XSizeHints *xsizehints = XAllocSizeHints();
380         xsizehints->flags = PPosition | PSize | PMinSize | PMaxSize;
381         xsizehints->x = left;
382         xsizehints->y = top;
383         xsizehints->width = width;
384         xsizehints->height = height;
385         xsizehints->min_width = 320;     /* size hints, could be made apart of the ghost api */
386         xsizehints->min_height = 240;    /* limits are also arbitrary, but should not allow 1x1 window */
387         xsizehints->max_width = 65535;
388         xsizehints->max_height = 65535;
389         XSetWMNormalHints(m_display, m_window, xsizehints);
390         XFree(xsizehints);
391
392         XClassHint *xclasshint = XAllocClassHint();
393         const int len = title.Length() + 1;
394         char *wmclass = (char *)malloc(sizeof(char) * len);
395         strncpy(wmclass, (const char *)title, sizeof(char) * len);
396         xclasshint->res_name = wmclass;
397         xclasshint->res_class = wmclass;
398         XSetClassHint(m_display, m_window, xclasshint);
399         free(wmclass);
400         XFree(xclasshint);
401
402         /* The basic for a good ICCCM "work" */
403         if (m_system->m_atom.WM_PROTOCOLS) {
404                 natom = 0;
405
406                 if (m_system->m_atom.WM_DELETE_WINDOW) {
407                         atoms[natom] = m_system->m_atom.WM_DELETE_WINDOW;
408                         natom++;
409                 }
410
411                 if (m_system->m_atom.WM_TAKE_FOCUS) {
412                         atoms[natom] = m_system->m_atom.WM_TAKE_FOCUS;
413                         natom++;
414                 }
415
416                 if (natom) {
417                         /* printf("Register atoms: %d\n", natom); */
418                         XSetWMProtocols(m_display, m_window, atoms, natom);
419                 }
420         }
421
422 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
423         m_xic = NULL;
424 #endif
425
426         /* Set the window hints */
427         XWMHints *xwmhints = XAllocWMHints();
428         xwmhints->initial_state = NormalState;
429         xwmhints->input = True;
430         xwmhints->flags = InputHint | StateHint;
431         XSetWMHints(display, m_window, xwmhints);
432         XFree(xwmhints);
433         /* done setting the hints */
434
435         /* set the icon */
436         Atom _NET_WM_ICON     = XInternAtom(m_display, "_NET_WM_ICON", False);
437         XChangeProperty(m_display, m_window, _NET_WM_ICON, XA_CARDINAL,
438                         32, PropModeReplace, (unsigned char *)BLENDER_ICON_48x48x32,
439                         BLENDER_ICON_48x48x32[0] * BLENDER_ICON_48x48x32[1] + 2);
440         /* done setting the icon */
441
442         setTitle(title);
443
444 #ifdef WITH_X11_XINPUT
445         initXInputDevices();
446
447         m_tabletData.Active = GHOST_kTabletModeNone;
448 #endif
449
450         /* now set up the rendering context. */
451         if (installDrawingContext(type) == GHOST_kSuccess) {
452                 m_valid_setup = true;
453                 GHOST_PRINT("Created window\n");
454         }
455
456         if (exclusive) {
457                 XMapRaised(m_display, m_window);
458         }
459         else {
460                 XMapWindow(m_display, m_window);
461         }
462         GHOST_PRINT("Mapped window\n");
463
464         XFlush(m_display);
465 }
466
467 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
468 static void destroyICCallback(XIC xic, XPointer ptr, XPointer data)
469 {
470         GHOST_PRINT("XIM input context destroyed\n");
471
472         if (ptr) {
473                 *(XIC *)ptr = NULL;
474         }
475 }
476
477 bool GHOST_WindowX11::createX11_XIC()
478 {
479         XIM xim = m_system->getX11_XIM();
480         if (!xim)
481                 return false;
482
483         XICCallback destroy;
484         destroy.callback = (XICProc)destroyICCallback;
485         destroy.client_data = (XPointer)&m_xic;
486         m_xic = XCreateIC(xim, XNClientWindow, m_window, XNFocusWindow, m_window,
487                           XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
488                           XNResourceName, GHOST_X11_RES_NAME,
489                           XNResourceClass, GHOST_X11_RES_CLASS,
490                           XNDestroyCallback, &destroy,
491                           NULL);
492         if (!m_xic)
493                 return false;
494
495         unsigned long fevent;
496         XGetICValues(m_xic, XNFilterEvents, &fevent, NULL);
497         XSelectInput(m_display, m_window,
498                      ExposureMask | StructureNotifyMask |
499                      KeyPressMask | KeyReleaseMask |
500                      EnterWindowMask | LeaveWindowMask |
501                      ButtonPressMask | ButtonReleaseMask |
502                      PointerMotionMask | FocusChangeMask |
503                      PropertyChangeMask | KeymapStateMask | fevent);
504         return true;
505 }
506 #endif
507
508 #ifdef WITH_X11_XINPUT
509 void GHOST_WindowX11::initXInputDevices()
510 {
511         XExtensionVersion *version = XGetExtensionVersion(m_display, INAME);
512
513         if (version && (version != (XExtensionVersion *)NoSuchExtension)) {
514                 if (version->present) {
515                         GHOST_SystemX11::GHOST_TabletX11 &xtablet = m_system->GetXTablet();
516                         XEventClass xevents[10], ev;
517                         int dcount = 0;
518
519                         if (xtablet.StylusDevice) {
520                                 DeviceMotionNotify(xtablet.StylusDevice, xtablet.MotionEvent, ev);
521                                 if (ev) xevents[dcount++] = ev;
522                                 ProximityIn(xtablet.StylusDevice, xtablet.ProxInEvent, ev);
523                                 if (ev) xevents[dcount++] = ev;
524                                 ProximityOut(xtablet.StylusDevice, xtablet.ProxOutEvent, ev);
525                                 if (ev) xevents[dcount++] = ev;
526                         }
527                         if (xtablet.EraserDevice) {
528                                 DeviceMotionNotify(xtablet.EraserDevice, xtablet.MotionEvent, ev);
529                                 if (ev) xevents[dcount++] = ev;
530                                 ProximityIn(xtablet.EraserDevice, xtablet.ProxInEvent, ev);
531                                 if (ev) xevents[dcount++] = ev;
532                                 ProximityOut(xtablet.EraserDevice, xtablet.ProxOutEvent, ev);
533                                 if (ev) xevents[dcount++] = ev;
534                         }
535
536                         XSelectExtensionEvent(m_display, m_window, xevents, dcount);
537                 }
538                 XFree(version);
539         }
540 }
541
542 #endif /* WITH_X11_XINPUT */
543
544 Window
545 GHOST_WindowX11::
546 getXWindow()
547 {
548         return m_window;
549 }
550
551 bool
552 GHOST_WindowX11::
553 getValid() const
554 {
555         return m_valid_setup;
556 }
557
558 void
559 GHOST_WindowX11::
560 setTitle(
561                 const STR_String& title)
562 {
563         Atom name = XInternAtom(m_display, "_NET_WM_NAME", 0);
564         Atom utf8str = XInternAtom(m_display, "UTF8_STRING", 0);
565         XChangeProperty(m_display, m_window,
566                         name, utf8str, 8, PropModeReplace,
567                         (const unsigned char *) title.ReadPtr(),
568                         title.Length());
569
570         /* This should convert to valid x11 string
571          * and getTitle would need matching change */
572         XStoreName(m_display, m_window, title);
573
574         XFlush(m_display);
575 }
576
577 void
578 GHOST_WindowX11::
579 getTitle(
580                 STR_String& title) const
581 {
582         char *name = NULL;
583         
584         XFetchName(m_display, m_window, &name);
585         title = name ? name : "untitled";
586         XFree(name);
587 }
588         
589 void
590 GHOST_WindowX11::
591 getWindowBounds(
592                 GHOST_Rect& bounds) const
593 {
594         /* Getting the window bounds under X11 is not
595          * really supported (nor should it be desired). */
596         getClientBounds(bounds);
597 }
598
599 void
600 GHOST_WindowX11::
601 getClientBounds(
602                 GHOST_Rect& bounds) const
603 {
604         Window root_return;
605         int x_return, y_return;
606         unsigned int w_return, h_return, border_w_return, depth_return;
607         GHOST_TInt32 screen_x, screen_y;
608         
609         XGetGeometry(m_display, m_window, &root_return, &x_return, &y_return,
610                      &w_return, &h_return, &border_w_return, &depth_return);
611
612         clientToScreen(0, 0, screen_x, screen_y);
613         
614         bounds.m_l = screen_x;
615         bounds.m_r = bounds.m_l + w_return;
616         bounds.m_t = screen_y;
617         bounds.m_b = bounds.m_t + h_return;
618
619 }
620
621 GHOST_TSuccess
622 GHOST_WindowX11::
623 setClientWidth(
624                 GHOST_TUns32 width)
625 {
626         XWindowChanges values;
627         unsigned int value_mask = CWWidth;
628         values.width = width;
629         XConfigureWindow(m_display, m_window, value_mask, &values);
630
631         return GHOST_kSuccess;
632 }
633
634 GHOST_TSuccess
635 GHOST_WindowX11::
636 setClientHeight(
637                 GHOST_TUns32 height)
638 {
639         XWindowChanges values;
640         unsigned int value_mask = CWHeight;
641         values.height = height;
642         XConfigureWindow(m_display, m_window, value_mask, &values);
643         return GHOST_kSuccess;
644
645 }
646
647 GHOST_TSuccess
648 GHOST_WindowX11::
649 setClientSize(
650                 GHOST_TUns32 width,
651                 GHOST_TUns32 height)
652 {
653         XWindowChanges values;
654         unsigned int value_mask = CWWidth | CWHeight;
655         values.width = width;
656         values.height = height;
657         XConfigureWindow(m_display, m_window, value_mask, &values);
658         return GHOST_kSuccess;
659
660 }       
661
662 void
663 GHOST_WindowX11::
664 screenToClient(
665                 GHOST_TInt32 inX,
666                 GHOST_TInt32 inY,
667                 GHOST_TInt32& outX,
668                 GHOST_TInt32& outY) const
669 {
670         /* This is correct! */
671
672         int ax, ay;
673         Window temp;
674
675         XTranslateCoordinates(m_display,
676                               RootWindow(m_display, m_visual->screen),
677                               m_window,
678                               inX, inY,
679                               &ax, &ay,
680                               &temp);
681         outX = ax;
682         outY = ay;
683 }
684                  
685 void
686 GHOST_WindowX11::
687 clientToScreen(
688                 GHOST_TInt32 inX,
689                 GHOST_TInt32 inY,
690                 GHOST_TInt32& outX,
691                 GHOST_TInt32& outY) const
692 {
693         int ax, ay;
694         Window temp;
695
696         XTranslateCoordinates(
697             m_display,
698             m_window,
699             RootWindow(m_display, m_visual->screen),
700             inX, inY,
701             &ax, &ay,
702             &temp);
703         outX = ax;
704         outY = ay;
705 }
706
707 void GHOST_WindowX11::icccmSetState(int state)
708 {
709         XEvent xev;
710
711         if (state != IconicState)
712                 return;
713
714         xev.xclient.type = ClientMessage;
715         xev.xclient.serial = 0;
716         xev.xclient.send_event = True;
717         xev.xclient.display = m_display;
718         xev.xclient.window = m_window;
719         xev.xclient.format = 32;
720         xev.xclient.message_type = m_system->m_atom.WM_CHANGE_STATE;
721         xev.xclient.data.l[0] = state;
722         XSendEvent(m_display, RootWindow(m_display, DefaultScreen(m_display)),
723                    False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
724 }
725
726 int GHOST_WindowX11::icccmGetState(void) const
727 {
728         unsigned char *prop_ret;
729         unsigned long bytes_after, num_ret;
730         Atom type_ret;
731         int format_ret, st;
732
733         prop_ret = NULL;
734         st = XGetWindowProperty(m_display, m_window, m_system->m_atom.WM_STATE, 0,
735                                 0x7fffffff, False, m_system->m_atom.WM_STATE, &type_ret,
736                                 &format_ret, &num_ret, &bytes_after, &prop_ret);
737
738         if ((st == Success) && (prop_ret) && (num_ret == 2))
739                 st = prop_ret[0];
740         else
741                 st = NormalState;
742
743         if (prop_ret)
744                 XFree(prop_ret);
745         return (st);
746 }
747
748 void GHOST_WindowX11::netwmMaximized(bool set)
749 {
750         XEvent xev;
751
752         xev.xclient.type = ClientMessage;
753         xev.xclient.serial = 0;
754         xev.xclient.send_event = True;
755         xev.xclient.window = m_window;
756         xev.xclient.message_type = m_system->m_atom._NET_WM_STATE;
757         xev.xclient.format = 32;
758
759         if (set == True)
760                 xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
761         else
762                 xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
763
764         xev.xclient.data.l[1] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_HORZ;
765         xev.xclient.data.l[2] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT;
766         xev.xclient.data.l[3] = 0;
767         xev.xclient.data.l[4] = 0;
768         XSendEvent(m_display, RootWindow(m_display, DefaultScreen(m_display)),
769                    False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
770 }
771
772 bool GHOST_WindowX11::netwmIsMaximized(void) const
773 {
774         unsigned char *prop_ret;
775         unsigned long bytes_after, num_ret, i;
776         Atom type_ret;
777         bool st;
778         int format_ret, ret, count;
779
780         prop_ret = NULL;
781         st = False;
782         ret = XGetWindowProperty(m_display, m_window, m_system->m_atom._NET_WM_STATE, 0,
783                                  0x7fffffff, False, XA_ATOM, &type_ret, &format_ret,
784                                  &num_ret, &bytes_after, &prop_ret);
785         if ((ret == Success) && (prop_ret) && (format_ret == 32)) {
786                 count = 0;
787                 for (i = 0; i < num_ret; i++) {
788                         if (((unsigned long *) prop_ret)[i] == m_system->m_atom._NET_WM_STATE_MAXIMIZED_HORZ)
789                                 count++;
790                         if (((unsigned long *) prop_ret)[i] == m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT)
791                                 count++;
792                         if (count == 2) {
793                                 st = True;
794                                 break;
795                         }
796                 }
797         }
798
799         if (prop_ret)
800                 XFree(prop_ret);
801         return (st);
802 }
803
804 void GHOST_WindowX11::netwmFullScreen(bool set)
805 {
806         XEvent xev;
807
808         xev.xclient.type = ClientMessage;
809         xev.xclient.serial = 0;
810         xev.xclient.send_event = True;
811         xev.xclient.window = m_window;
812         xev.xclient.message_type = m_system->m_atom._NET_WM_STATE;
813         xev.xclient.format = 32;
814
815         if (set == True)
816                 xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
817         else
818                 xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
819
820         xev.xclient.data.l[1] = m_system->m_atom._NET_WM_STATE_FULLSCREEN;
821         xev.xclient.data.l[2] = 0;
822         xev.xclient.data.l[3] = 0;
823         xev.xclient.data.l[4] = 0;
824         XSendEvent(m_display, RootWindow(m_display, DefaultScreen(m_display)),
825                    False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
826 }
827
828 bool GHOST_WindowX11::netwmIsFullScreen(void) const
829 {
830         unsigned char *prop_ret;
831         unsigned long bytes_after, num_ret, i;
832         Atom type_ret;
833         bool st;
834         int format_ret, ret;
835
836         prop_ret = NULL;
837         st = False;
838         ret = XGetWindowProperty(m_display, m_window, m_system->m_atom._NET_WM_STATE, 0,
839                                  0x7fffffff, False, XA_ATOM, &type_ret, &format_ret,
840                                  &num_ret, &bytes_after, &prop_ret);
841         if ((ret == Success) && (prop_ret) && (format_ret == 32)) {
842                 for (i = 0; i < num_ret; i++) {
843                         if (((unsigned long *) prop_ret)[i] == m_system->m_atom._NET_WM_STATE_FULLSCREEN) {
844                                 st = True;
845                                 break;
846                         }
847                 }
848         }
849
850         if (prop_ret)
851                 XFree(prop_ret);
852         return (st);
853 }
854
855 void GHOST_WindowX11::motifFullScreen(bool set)
856 {
857         MotifWmHints hints;
858
859         hints.flags = MWM_HINTS_DECORATIONS;
860         if (set == True)
861                 hints.decorations = 0;
862         else
863                 hints.decorations = 1;
864
865         XChangeProperty(m_display, m_window, m_system->m_atom._MOTIF_WM_HINTS,
866                         m_system->m_atom._MOTIF_WM_HINTS, 32, PropModeReplace,
867                         (unsigned char *) &hints, 4);
868 }
869
870 bool GHOST_WindowX11::motifIsFullScreen(void) const
871 {
872         unsigned char *prop_ret;
873         unsigned long bytes_after, num_ret;
874         MotifWmHints *hints;
875         Atom type_ret;
876         bool state;
877         int format_ret, st;
878
879         prop_ret = NULL;
880         state = False;
881         st = XGetWindowProperty(m_display, m_window, m_system->m_atom._MOTIF_WM_HINTS, 0,
882                                 0x7fffffff, False, m_system->m_atom._MOTIF_WM_HINTS,
883                                 &type_ret, &format_ret, &num_ret,
884                                 &bytes_after, &prop_ret);
885         if ((st == Success) && (prop_ret)) {
886                 hints = (MotifWmHints *) prop_ret;
887                 if (hints->flags & MWM_HINTS_DECORATIONS) {
888                         if (!hints->decorations)
889                                 state = True;
890                 }
891         }
892
893         if (prop_ret)
894                 XFree(prop_ret);
895         return (state);
896 }
897
898 GHOST_TWindowState GHOST_WindowX11::getState() const
899 {
900         GHOST_TWindowState state_ret;
901         int state;
902
903         state_ret = GHOST_kWindowStateNormal;
904         state = icccmGetState();
905         /*
906          * In the Iconic and Withdrawn state, the window
907          * is unmaped, so only need return a Minimized state.
908          */
909         if ((state == IconicState) || (state == WithdrawnState))
910                 state_ret = GHOST_kWindowStateMinimized;
911         else if (netwmIsFullScreen() == True)
912                 state_ret = GHOST_kWindowStateFullScreen;
913         else if (motifIsFullScreen() == True)
914                 state_ret = GHOST_kWindowStateFullScreen;
915         else if (netwmIsMaximized() == True)
916                 state_ret = GHOST_kWindowStateMaximized;
917         return (state_ret);
918 }
919
920 GHOST_TSuccess GHOST_WindowX11::setState(GHOST_TWindowState state)
921 {
922         GHOST_TWindowState cur_state;
923         bool is_max, is_full, is_motif_full;
924
925         cur_state = getState();
926         if (state == (int)cur_state)
927                 return GHOST_kSuccess;
928
929         if (cur_state != GHOST_kWindowStateMinimized) {
930                 /*
931                  * The window don't have this property's
932                  * if it's not mapped.
933                  */
934                 is_max = netwmIsMaximized();
935                 is_full = netwmIsFullScreen();
936         }
937         else {
938                 is_max = False;
939                 is_full = False;
940         }
941
942         is_motif_full = motifIsFullScreen();
943
944         if (state == GHOST_kWindowStateNormal)
945                 state = m_normal_state;
946
947         if (state == GHOST_kWindowStateNormal) {
948                 if (is_max == True)
949                         netwmMaximized(False);
950                 if (is_full == True)
951                         netwmFullScreen(False);
952                 if (is_motif_full == True)
953                         motifFullScreen(False);
954                 icccmSetState(NormalState);
955                 return (GHOST_kSuccess);
956         }
957
958         if (state == GHOST_kWindowStateFullScreen) {
959                 /*
960                  * We can't change to full screen if the window
961                  * isn't mapped.
962                  */
963                 if (cur_state == GHOST_kWindowStateMinimized)
964                         return (GHOST_kFailure);
965
966                 m_normal_state = cur_state;
967
968                 if (is_max == True)
969                         netwmMaximized(False);
970                 if (is_full == False)
971                         netwmFullScreen(True);
972                 if (is_motif_full == False)
973                         motifFullScreen(True);
974                 return (GHOST_kSuccess);
975         }
976
977         if (state == GHOST_kWindowStateMaximized) {
978                 /*
979                  * We can't change to Maximized if the window
980                  * isn't mapped.
981                  */
982                 if (cur_state == GHOST_kWindowStateMinimized)
983                         return (GHOST_kFailure);
984
985                 if (is_full == True)
986                         netwmFullScreen(False);
987                 if (is_motif_full == True)
988                         motifFullScreen(False);
989                 if (is_max == False)
990                         netwmMaximized(True);
991                 return (GHOST_kSuccess);
992         }
993
994         if (state == GHOST_kWindowStateMinimized) {
995                 /*
996                  * The window manager need save the current state of
997                  * the window (maximized, full screen, etc).
998                  */
999                 icccmSetState(IconicState);
1000                 return (GHOST_kSuccess);
1001         }
1002
1003         return (GHOST_kFailure);
1004 }
1005
1006 #include <iostream>
1007
1008 GHOST_TSuccess
1009 GHOST_WindowX11::
1010 setOrder(
1011                 GHOST_TWindowOrder order)
1012 {
1013         if (order == GHOST_kWindowOrderTop) {
1014                 XWindowAttributes attr;   
1015                 Atom atom;
1016
1017                 /* We use both XRaiseWindow and _NET_ACTIVE_WINDOW, since some
1018                  * window managers ignore the former (e.g. kwin from kde) and others
1019                  * don't implement the latter (e.g. fluxbox pre 0.9.9) */
1020
1021                 XRaiseWindow(m_display, m_window);
1022
1023                 atom = XInternAtom(m_display, "_NET_ACTIVE_WINDOW", True);
1024
1025                 if (atom != None) {
1026                         Window root;
1027                         XEvent xev;
1028                         long eventmask;
1029
1030                         xev.xclient.type = ClientMessage;
1031                         xev.xclient.serial = 0;
1032                         xev.xclient.send_event = True;
1033                         xev.xclient.window = m_window;
1034                         xev.xclient.message_type = atom;
1035
1036                         xev.xclient.format = 32;
1037                         xev.xclient.data.l[0] = 1;
1038                         xev.xclient.data.l[1] = CurrentTime;
1039                         xev.xclient.data.l[2] = m_window;
1040                         xev.xclient.data.l[3] = 0;
1041                         xev.xclient.data.l[4] = 0;
1042
1043                         root = RootWindow(m_display, m_visual->screen),
1044                         eventmask = SubstructureRedirectMask | SubstructureNotifyMask;
1045
1046                         XSendEvent(m_display, root, False, eventmask, &xev);
1047                 }
1048
1049                 XGetWindowAttributes(m_display, m_window, &attr);
1050
1051                 /* iconized windows give bad match error */
1052                 if (attr.map_state == IsViewable)
1053                         XSetInputFocus(m_display, m_window, RevertToPointerRoot,
1054                                        CurrentTime);
1055                 XFlush(m_display);
1056         }
1057         else if (order == GHOST_kWindowOrderBottom) {
1058                 XLowerWindow(m_display, m_window);
1059                 XFlush(m_display);
1060         }
1061         else {
1062                 return GHOST_kFailure;
1063         }
1064         
1065         return GHOST_kSuccess;
1066 }
1067
1068 GHOST_TSuccess
1069 GHOST_WindowX11::
1070 swapBuffers()
1071 {
1072         if (getDrawingContextType() == GHOST_kDrawingContextTypeOpenGL) {
1073                 glXSwapBuffers(m_display, m_window);
1074                 return GHOST_kSuccess;
1075         }
1076         else {
1077                 return GHOST_kFailure;
1078         }
1079 }
1080
1081 GHOST_TSuccess
1082 GHOST_WindowX11::
1083 activateDrawingContext()
1084 {
1085         if (m_context != NULL) {
1086                 glXMakeCurrent(m_display, m_window, m_context);
1087                 /* Disable AA by default */
1088                 if (m_numOfAASamples > 0) {
1089                         glDisable(GL_MULTISAMPLE_ARB);
1090                 }
1091                 return GHOST_kSuccess;
1092         } 
1093         return GHOST_kFailure;
1094 }
1095
1096 GHOST_TSuccess
1097 GHOST_WindowX11::
1098 invalidate()
1099 {
1100         /* So the idea of this function is to generate an expose event
1101          * for the window.
1102          * Unfortunately X does not handle expose events for you and
1103          * it is the client's job to refresh the dirty part of the window.
1104          * We need to queue up invalidate calls and generate GHOST events
1105          * for them in the system.
1106          *
1107          * We implement this by setting a boolean in this class to concatenate
1108          * all such calls into a single event for this window.
1109          *
1110          * At the same time we queue the dirty windows in the system class
1111          * and generate events for them at the next processEvents call. */
1112
1113         if (m_invalid_window == false) {
1114                 m_system->addDirtyWindow(this);
1115                 m_invalid_window = true;
1116         } 
1117  
1118         return GHOST_kSuccess;
1119 }
1120
1121 /**
1122  * called by the X11 system implementation when expose events
1123  * for the window have been pushed onto the GHOST queue
1124  */
1125  
1126 void
1127 GHOST_WindowX11::
1128 validate()
1129 {
1130         m_invalid_window = false;
1131 }       
1132  
1133  
1134 /**
1135  * Destructor.
1136  * Closes the window and disposes resources allocated.
1137  */
1138
1139 GHOST_WindowX11::
1140 ~GHOST_WindowX11()
1141 {
1142         static Atom Primary_atom, Clipboard_atom;
1143         Window p_owner, c_owner;
1144         /*Change the owner of the Atoms to None if we are the owner*/
1145         Primary_atom = XInternAtom(m_display, "PRIMARY", False);
1146         Clipboard_atom = XInternAtom(m_display, "CLIPBOARD", False);
1147         
1148         p_owner = XGetSelectionOwner(m_display, Primary_atom);
1149         c_owner = XGetSelectionOwner(m_display, Clipboard_atom);
1150         
1151         std::map<unsigned int, Cursor>::iterator it = m_standard_cursors.begin();
1152         for (; it != m_standard_cursors.end(); ++it) {
1153                 XFreeCursor(m_display, it->second);
1154         }
1155
1156         if (m_empty_cursor) {
1157                 XFreeCursor(m_display, m_empty_cursor);
1158         }
1159         if (m_custom_cursor) {
1160                 XFreeCursor(m_display, m_custom_cursor);
1161         }
1162
1163         if (m_context != s_firstContext) {
1164                 glXDestroyContext(m_display, m_context);
1165         }
1166         
1167         if (p_owner == m_window) {
1168                 XSetSelectionOwner(m_display, Primary_atom, None, CurrentTime);
1169         }
1170         if (c_owner == m_window) {
1171                 XSetSelectionOwner(m_display, Clipboard_atom, None, CurrentTime);
1172         }
1173         
1174 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
1175         if (m_xic) {
1176                 XDestroyIC(m_xic);
1177         }
1178 #endif
1179
1180 #ifdef WITH_XDND
1181         delete m_dropTarget;
1182 #endif
1183
1184         XDestroyWindow(m_display, m_window);
1185         XFree(m_visual);
1186 }
1187
1188
1189
1190
1191 /**
1192  * Tries to install a rendering context in this window.
1193  * \param type  The type of rendering context installed.
1194  * \return Indication as to whether installation has succeeded.
1195  */
1196 GHOST_TSuccess
1197 GHOST_WindowX11::
1198 installDrawingContext(
1199                 GHOST_TDrawingContextType type)
1200 {
1201         /* only support openGL for now. */
1202         GHOST_TSuccess success;
1203         switch (type) {
1204                 case GHOST_kDrawingContextTypeOpenGL:
1205                 {
1206 #ifdef WITH_X11_XINPUT
1207                         /* use our own event handlers to avoid exiting blender,
1208                          * this would happen for eg:
1209                          * if you open blender, unplug a tablet, then open a new window. */
1210                         XErrorHandler old_handler      = XSetErrorHandler(GHOST_X11_ApplicationErrorHandler);
1211                         XIOErrorHandler old_handler_io = XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler);
1212 #endif
1213
1214                         m_context = glXCreateContext(m_display, m_visual, s_firstContext, True);
1215                         if (m_context != NULL) {
1216                                 if (!s_firstContext) {
1217                                         s_firstContext = m_context;
1218                                 }
1219                                 glXMakeCurrent(m_display, m_window, m_context);
1220                                 glClearColor(0.447, 0.447, 0.447, 0);
1221                                 glClear(GL_COLOR_BUFFER_BIT);
1222                                 success = GHOST_kSuccess;
1223                         }
1224                         else {
1225                                 success = GHOST_kFailure;
1226                         }
1227
1228 #ifdef WITH_X11_XINPUT
1229                         /* Restore handler */
1230                         (void) XSetErrorHandler(old_handler);
1231                         (void) XSetIOErrorHandler(old_handler_io);
1232 #endif
1233                         break;
1234                 }
1235                 case GHOST_kDrawingContextTypeNone:
1236                 {
1237                         success = GHOST_kSuccess;
1238                         break;
1239                 }
1240                 default:
1241                         success = GHOST_kFailure;
1242         }
1243         return success;
1244 }
1245
1246
1247
1248 /**
1249  * Removes the current drawing context.
1250  * \return Indication as to whether removal has succeeded.
1251  */
1252 GHOST_TSuccess
1253 GHOST_WindowX11::
1254 removeDrawingContext()
1255 {
1256         GHOST_TSuccess success;
1257
1258         if (m_context != NULL) {
1259                 glXDestroyContext(m_display, m_context);
1260                 success = GHOST_kSuccess;
1261         }
1262         else {
1263                 success = GHOST_kFailure;
1264         }
1265         return success; 
1266 }
1267
1268
1269 Cursor
1270 GHOST_WindowX11::
1271 getStandardCursor(
1272                 GHOST_TStandardCursor g_cursor)
1273 {
1274         unsigned int xcursor_id;
1275
1276 #define GtoX(gcurs, xcurs)  case gcurs: xcursor_id = xcurs
1277         switch (g_cursor) {
1278                 GtoX(GHOST_kStandardCursorRightArrow, XC_arrow); break;
1279                 GtoX(GHOST_kStandardCursorLeftArrow, XC_top_left_arrow); break;
1280                 GtoX(GHOST_kStandardCursorInfo, XC_hand1); break;
1281                 GtoX(GHOST_kStandardCursorDestroy, XC_pirate); break;
1282                 GtoX(GHOST_kStandardCursorHelp, XC_question_arrow); break;
1283                 GtoX(GHOST_kStandardCursorCycle, XC_exchange); break;
1284                 GtoX(GHOST_kStandardCursorSpray, XC_spraycan); break;
1285                 GtoX(GHOST_kStandardCursorWait, XC_watch); break;
1286                 GtoX(GHOST_kStandardCursorText, XC_xterm); break;
1287                 GtoX(GHOST_kStandardCursorCrosshair, XC_crosshair); break;
1288                 GtoX(GHOST_kStandardCursorUpDown, XC_sb_v_double_arrow); break;
1289                 GtoX(GHOST_kStandardCursorLeftRight, XC_sb_h_double_arrow); break;
1290                 GtoX(GHOST_kStandardCursorTopSide, XC_top_side); break;
1291                 GtoX(GHOST_kStandardCursorBottomSide, XC_bottom_side); break;
1292                 GtoX(GHOST_kStandardCursorLeftSide, XC_left_side); break;
1293                 GtoX(GHOST_kStandardCursorRightSide, XC_right_side); break;
1294                 GtoX(GHOST_kStandardCursorTopLeftCorner, XC_top_left_corner); break;
1295                 GtoX(GHOST_kStandardCursorTopRightCorner, XC_top_right_corner); break;
1296                 GtoX(GHOST_kStandardCursorBottomRightCorner, XC_bottom_right_corner); break;
1297                 GtoX(GHOST_kStandardCursorBottomLeftCorner, XC_bottom_left_corner); break;
1298                 GtoX(GHOST_kStandardCursorPencil, XC_pencil); break;
1299                 GtoX(GHOST_kStandardCursorCopy, XC_arrow); break;
1300                 default:
1301                         xcursor_id = 0;
1302         }
1303 #undef GtoX
1304
1305         if (xcursor_id) {
1306                 Cursor xcursor = m_standard_cursors[xcursor_id];
1307                 
1308                 if (!xcursor) {
1309                         xcursor = XCreateFontCursor(m_display, xcursor_id);
1310
1311                         m_standard_cursors[xcursor_id] = xcursor;
1312                 }
1313                 
1314                 return xcursor;
1315         }
1316         else {
1317                 return None;
1318         }
1319 }
1320
1321 Cursor
1322 GHOST_WindowX11::
1323 getEmptyCursor(
1324         ) {
1325         if (!m_empty_cursor) {
1326                 Pixmap blank;
1327                 XColor dummy;
1328                 char data[1] = {0};
1329                         
1330                 /* make a blank cursor */
1331                 blank = XCreateBitmapFromData(
1332                     m_display,
1333                     RootWindow(m_display, DefaultScreen(m_display)),
1334                     data, 1, 1
1335                     );
1336
1337                 m_empty_cursor = XCreatePixmapCursor(m_display, blank, blank, &dummy, &dummy, 0, 0);
1338                 XFreePixmap(m_display, blank);
1339         }
1340
1341         return m_empty_cursor;
1342 }
1343
1344 GHOST_TSuccess
1345 GHOST_WindowX11::
1346 setWindowCursorVisibility(
1347                 bool visible)
1348 {
1349         Cursor xcursor;
1350         
1351         if (visible) {
1352                 xcursor = getStandardCursor(getCursorShape() );
1353         }
1354         else {
1355                 xcursor = getEmptyCursor();
1356         }
1357
1358         XDefineCursor(m_display, m_window, xcursor);
1359         XFlush(m_display);
1360         
1361         return GHOST_kSuccess;
1362 }
1363
1364 GHOST_TSuccess
1365 GHOST_WindowX11::
1366 setWindowCursorGrab(
1367                 GHOST_TGrabCursorMode mode)
1368 {
1369         if (mode != GHOST_kGrabDisable) {
1370                 if (mode != GHOST_kGrabNormal) {
1371                         m_system->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
1372                         setCursorGrabAccum(0, 0);
1373
1374                         if (mode == GHOST_kGrabHide)
1375                                 setWindowCursorVisibility(false);
1376
1377                 }
1378 #ifdef GHOST_X11_GRAB
1379                 XGrabPointer(m_display, m_window, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
1380                              GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
1381 #endif
1382         }
1383         else {
1384                 if (m_cursorGrab == GHOST_kGrabHide) {
1385                         m_system->setCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
1386                         setWindowCursorVisibility(true);
1387                 }
1388
1389                 if (m_cursorGrab != GHOST_kGrabNormal) {
1390                         /* use to generate a mouse move event, otherwise the last event
1391                          * blender gets can be outside the screen causing menus not to show
1392                          * properly unless the user moves the mouse */
1393                         XWarpPointer(m_display, None, None, 0, 0, 0, 0, 0, 0);
1394                 }
1395
1396                 /* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
1397                 setCursorGrabAccum(0, 0);
1398                 m_cursorGrabBounds.m_l = m_cursorGrabBounds.m_r = -1; /* disable */
1399 #ifdef GHOST_X11_GRAB
1400                 XUngrabPointer(m_display, CurrentTime);
1401 #endif
1402         }
1403
1404         XFlush(m_display);
1405         
1406         return GHOST_kSuccess;
1407 }
1408
1409 GHOST_TSuccess
1410 GHOST_WindowX11::
1411 setWindowCursorShape(
1412                 GHOST_TStandardCursor shape)
1413 {
1414         Cursor xcursor = getStandardCursor(shape);
1415         
1416         XDefineCursor(m_display, m_window, xcursor);
1417         XFlush(m_display);
1418
1419         return GHOST_kSuccess;
1420 }
1421
1422 GHOST_TSuccess
1423 GHOST_WindowX11::
1424 setWindowCustomCursorShape(
1425                 GHOST_TUns8 bitmap[16][2],
1426                 GHOST_TUns8 mask[16][2],
1427                 int hotX,
1428                 int hotY)
1429 {
1430         setWindowCustomCursorShape((GHOST_TUns8 *)bitmap, (GHOST_TUns8 *)mask,
1431                                    16, 16, hotX, hotY, 0, 1);
1432         return GHOST_kSuccess;
1433 }
1434
1435 GHOST_TSuccess
1436 GHOST_WindowX11::
1437 setWindowCustomCursorShape(     
1438                 GHOST_TUns8 *bitmap,
1439                 GHOST_TUns8 *mask,
1440                 int sizex,
1441                 int sizey,
1442                 int hotX,
1443                 int hotY,
1444                 int fg_color,
1445                 int bg_color)
1446 {
1447         Colormap colormap = DefaultColormap(m_display, DefaultScreen(m_display));
1448         Pixmap bitmap_pix, mask_pix;
1449         XColor fg, bg;
1450         
1451         if (XAllocNamedColor(m_display, colormap, "White", &fg, &fg) == 0) return GHOST_kFailure;
1452         if (XAllocNamedColor(m_display, colormap, "Black", &bg, &bg) == 0) return GHOST_kFailure;
1453
1454         if (m_custom_cursor) {
1455                 XFreeCursor(m_display, m_custom_cursor);
1456         }
1457
1458         bitmap_pix = XCreateBitmapFromData(m_display, m_window, (char *) bitmap, sizex, sizey);
1459         mask_pix = XCreateBitmapFromData(m_display, m_window, (char *) mask, sizex, sizey);
1460                 
1461         m_custom_cursor = XCreatePixmapCursor(m_display, bitmap_pix, mask_pix, &fg, &bg, hotX, hotY);
1462         XDefineCursor(m_display, m_window, m_custom_cursor);
1463         XFlush(m_display);
1464         
1465         XFreePixmap(m_display, bitmap_pix);
1466         XFreePixmap(m_display, mask_pix);
1467
1468         XFreeColors(m_display, colormap, &fg.pixel, 1, 0L);
1469         XFreeColors(m_display, colormap, &bg.pixel, 1, 0L);
1470
1471         return GHOST_kSuccess;
1472 }
1473
1474
1475 GHOST_TSuccess
1476 GHOST_WindowX11::
1477 beginFullScreen() const
1478 {
1479         {
1480                 Window root_return;
1481                 int x_return, y_return;
1482                 unsigned int w_return, h_return, border_w_return, depth_return;
1483
1484                 XGetGeometry(m_display, m_window, &root_return, &x_return, &y_return,
1485                              &w_return, &h_return, &border_w_return, &depth_return);
1486
1487                 m_system->setCursorPosition(w_return / 2, h_return / 2);
1488         }
1489
1490
1491         /* Grab Keyboard & Mouse */
1492         int err;
1493
1494         err = XGrabKeyboard(m_display, m_window, False,
1495                             GrabModeAsync, GrabModeAsync, CurrentTime);
1496         if (err != GrabSuccess) printf("XGrabKeyboard failed %d\n", err);
1497
1498         err = XGrabPointer(m_display, m_window, False,  PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
1499                            GrabModeAsync, GrabModeAsync, m_window, None, CurrentTime);
1500         if (err != GrabSuccess) printf("XGrabPointer failed %d\n", err);
1501
1502         return GHOST_kSuccess;
1503 }
1504
1505 GHOST_TSuccess
1506 GHOST_WindowX11::
1507 endFullScreen() const
1508 {
1509         XUngrabKeyboard(m_display, CurrentTime);
1510         XUngrabPointer(m_display, CurrentTime);
1511
1512         return GHOST_kSuccess;
1513 }