Merge branch 'master' into blender2.8
[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 /* For standard X11 cursors */
33 #include <X11/cursorfont.h>
34 #include <X11/Xatom.h>
35 #include <X11/Xutil.h>
36 #ifdef WITH_X11_ALPHA
37 #include <X11/extensions/Xrender.h>
38 #endif
39 #include "GHOST_WindowX11.h"
40 #include "GHOST_SystemX11.h"
41 #include "STR_String.h"
42 #include "GHOST_Debug.h"
43
44 #ifdef WITH_XDND
45 #  include "GHOST_DropTargetX11.h"
46 #endif
47
48 #if defined(WITH_GL_EGL)
49 #  include "GHOST_ContextEGL.h"
50 #else
51 #  include "GHOST_ContextGLX.h"
52 #endif
53
54 /* for XIWarpPointer */
55 #ifdef WITH_X11_XINPUT
56 #  include <X11/extensions/XInput2.h>
57 #endif
58
59 #if defined(__sun__) || defined(__sun) || defined(__sparc) || defined(__sparc__) || defined(_AIX)
60 #  include <strings.h>
61 #endif
62
63 #include <cstring>
64 #include <cstdio>
65
66 /* gethostname */
67 #include <unistd.h>
68
69 #include <algorithm>
70 #include <string>
71
72 /* For obscure full screen mode stuff
73  * lifted verbatim from blut. */
74
75 typedef struct {
76         long flags;
77         long functions;
78         long decorations;
79         long input_mode;
80 } MotifWmHints;
81
82 #define MWM_HINTS_DECORATIONS         (1L << 1)
83
84 #ifndef HOST_NAME_MAX
85 #  define HOST_NAME_MAX 64
86 #endif
87
88 // #define GHOST_X11_GRAB
89
90 /*
91  * A Client can't change the window property, that is
92  * the work of the window manager. In case, we send
93  * a ClientMessage to the RootWindow with the property
94  * and the Action (WM-spec define this):
95  */
96 #define _NET_WM_STATE_REMOVE 0
97 #define _NET_WM_STATE_ADD 1
98 // #define _NET_WM_STATE_TOGGLE 2 // UNUSED
99
100 /*
101  * import bpy
102  * ima = bpy.data.images["blender.png"]
103  * w, h = ima.size
104  * print("%d,%d," % (w, h))
105  * for y in range(h - 1, -1, -1):
106  *     px = []
107  *     for x in range(w):
108  *         p = ((y * w) + x) * 4
109  *         rgba = ima.pixels[p : p + 4]
110  *         rgba = rgba[2], rgba[1], rgba[0], rgba[3]
111  *         px.append(sum((int(p * 255) << (8 * i)) for i, p in enumerate(rgba)))
112  *     print(", ".join([str(p) for p in px]), end=",\n")
113  */
114
115 /**
116  * See the python script above to regenerate the 48x48 icon within blender
117  *
118  * \note Using 'unsigned' to avoid `-Wnarrowing` warning.
119  */
120 static const unsigned long BLENDER_ICON_48x48x32[] = {
121         48,48,
122         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,
123         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,
124         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,
125         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,
126         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,
127         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,
128         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,
129         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,
130         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,
131         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,
132         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,
133         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,
134         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,
135         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,
136         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,
137         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,
138         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,
139         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,
140         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,
141         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,
142         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,
143         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,
144         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,
145         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,
146         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,
147         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,
148         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,
149         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,
150         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,
151         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,
152         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,
153         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,
154         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,
155         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,
156         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,
157         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,
158         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,
159         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,
160         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,
161         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,
162         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,
163         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,
164         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,
165         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,
166         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,
167         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,
168         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,
169         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,
170 };
171
172 static XVisualInfo *x11_visualinfo_from_glx(
173         Display *display,
174         bool stereoVisual,
175         GHOST_TUns16 *r_numOfAASamples,
176         bool needAlpha,
177         GLXFBConfig *fbconfig)
178 {
179         XVisualInfo *visual = NULL;
180         GHOST_TUns16 numOfAASamples = *r_numOfAASamples;
181         int glx_major, glx_minor, glx_version; /* GLX version: major.minor */
182         GHOST_TUns16 actualSamples;
183         int glx_attribs[64];
184
185         *fbconfig = NULL;
186
187         /* Set up the minimum attributes that we require and see if
188          * X can find us a visual matching those requirements. */
189
190         if (!glXQueryVersion(display, &glx_major, &glx_minor)) {
191                 fprintf(stderr,
192                         "%s:%d: X11 glXQueryVersion() failed, "
193                         "verify working openGL system!\n",
194                         __FILE__, __LINE__);
195
196                 return NULL;
197         }
198         glx_version = glx_major*100 + glx_minor;
199
200         if (glx_version >= 104) {
201                 actualSamples = numOfAASamples;
202         }
203         else {
204                 numOfAASamples = 0;
205                 actualSamples = 0;
206         }
207         
208 #ifdef WITH_X11_ALPHA
209         if (   needAlpha
210             && glx_version >= 103
211             && (glXChooseFBConfig ||
212                 (glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)glXGetProcAddressARB((const GLubyte *)"glXChooseFBConfig")) != NULL)
213             && (glXGetVisualFromFBConfig ||
214                 (glXGetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)glXGetProcAddressARB((const GLubyte *)"glXGetVisualFromFBConfig")) != NULL)
215             ) {
216                 GLXFBConfig *fbconfigs;
217                 int nbfbconfig;
218                 int i;
219
220                 for (;;) {
221
222                         GHOST_X11_GL_GetAttributes(glx_attribs, 64, actualSamples, stereoVisual, needAlpha, true);
223
224                         fbconfigs = glXChooseFBConfig(display, DefaultScreen(display), glx_attribs, &nbfbconfig);
225
226                         /* Any sample level or even zero, which means oversampling disabled, is good
227                          * but we need a valid visual to continue */
228                         if (nbfbconfig > 0) {
229                                 /* take a frame buffer config that has alpha cap */
230                                 for (i=0 ;i<nbfbconfig; i++) {
231                                         visual = (XVisualInfo*)glXGetVisualFromFBConfig(display, fbconfigs[i]);
232                                         if (!visual)
233                                                 continue;
234                                         /* if we don't need a alpha background, the first config will do, otherwise
235                                          * test the alphaMask as it won't necessarily be present */
236                                         if (needAlpha) {
237                                                 XRenderPictFormat *pict_format = XRenderFindVisualFormat(display, visual->visual);
238                                                 if (!pict_format)
239                                                         continue;
240                                                 if (pict_format->direct.alphaMask <= 0)
241                                                         continue;
242                                         }
243                                         *fbconfig = fbconfigs[i];
244                                         break;
245                                 }
246                                 XFree(fbconfigs);
247                                 if (i<nbfbconfig) {
248                                         if (actualSamples < numOfAASamples) {
249                                                 fprintf(stderr,
250                                                         "Warning! Unable to find a multisample pixel format that supports exactly %d samples. "
251                                                         "Substituting one that uses %d samples.\n",
252                                                         numOfAASamples, actualSamples);
253                                         }
254                                         break;
255                                 }
256                                 visual = NULL;
257                         }
258
259                         if (actualSamples == 0) {
260                                 /* All options exhausted, cannot continue */
261                                 fprintf(stderr,
262                                         "%s:%d: X11 glXChooseVisual() failed, "
263                                         "verify working openGL system!\n",
264                                         __FILE__, __LINE__);
265
266                                 return NULL;
267                         }
268                         else {
269                                 --actualSamples;
270                         }
271                 }
272         }
273         else
274 #endif
275         {
276                 /* legacy, don't use extension */
277                 for (;;) {
278                         GHOST_X11_GL_GetAttributes(glx_attribs, 64, actualSamples, stereoVisual, needAlpha, false);
279                         
280                         visual = glXChooseVisual(display, DefaultScreen(display), glx_attribs);
281
282                         /* Any sample level or even zero, which means oversampling disabled, is good
283                          * but we need a valid visual to continue */
284                         if (visual != NULL) {
285                                 if (actualSamples < numOfAASamples) {
286                                         fprintf(stderr,
287                                                 "Warning! Unable to find a multisample pixel format that supports exactly %d samples. "
288                                                 "Substituting one that uses %d samples.\n",
289                                                 numOfAASamples, actualSamples);
290                                 }
291                                 break;
292                         }
293
294                         if (actualSamples == 0) {
295                                 /* All options exhausted, cannot continue */
296                                 fprintf(stderr,
297                                         "%s:%d: X11 glXChooseVisual() failed, "
298                                         "verify working openGL system!\n",
299                                         __FILE__, __LINE__);
300
301                                 return NULL;
302                         }
303                         else {
304                                 --actualSamples;
305                         }
306                 }
307         }
308         *r_numOfAASamples = actualSamples;
309         return visual;
310 }
311
312 GHOST_WindowX11::
313 GHOST_WindowX11(GHOST_SystemX11 *system,
314         Display *display,
315         const STR_String &title,
316         GHOST_TInt32 left,
317         GHOST_TInt32 top,
318         GHOST_TUns32 width,
319         GHOST_TUns32 height,
320         GHOST_TWindowState state,
321         const GHOST_TEmbedderWindowID parentWindow,
322         GHOST_TDrawingContextType type,
323         const bool stereoVisual,
324         const bool exclusive,
325         const bool alphaBackground,
326         const GHOST_TUns16 numOfAASamples, const bool is_debug)
327     : GHOST_Window(width, height, state, stereoVisual, exclusive, numOfAASamples),
328       m_display(display),
329       m_visualInfo(NULL),
330       m_fbconfig(NULL),
331       m_normal_state(GHOST_kWindowStateNormal),
332       m_system(system),
333       m_invalid_window(false),
334       m_empty_cursor(None),
335       m_custom_cursor(None),
336       m_visible_cursor(None),
337 #ifdef WITH_XDND
338       m_dropTarget(NULL),
339 #endif
340 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
341       m_xic(NULL),
342 #endif
343       m_valid_setup(false),
344       m_is_debug_context(is_debug)
345 {
346         if (type == GHOST_kDrawingContextTypeOpenGL) {
347                 m_visualInfo = x11_visualinfo_from_glx(m_display, stereoVisual, &m_wantNumOfAASamples, alphaBackground, (GLXFBConfig*)&m_fbconfig);
348         }
349         else {
350                 XVisualInfo tmp = {0};
351                 int n;
352                 m_visualInfo = XGetVisualInfo(m_display, 0, &tmp, &n);
353         }
354
355         /* caller needs to check 'getValid()' */
356         if (m_visualInfo == NULL) {
357                 fprintf(stderr, "initial window could not find the GLX extension\n");
358                 return;
359         }
360
361         unsigned int xattributes_valuemask = 0;
362
363         XSetWindowAttributes xattributes;
364         memset(&xattributes, 0, sizeof(xattributes));
365
366         xattributes_valuemask |= CWBorderPixel;
367         xattributes.border_pixel = 0;
368
369         /* Specify which events we are interested in hearing. */
370
371         xattributes_valuemask |= CWEventMask;
372         xattributes.event_mask =
373                 ExposureMask | StructureNotifyMask |
374                 KeyPressMask | KeyReleaseMask |
375                 EnterWindowMask | LeaveWindowMask |
376                 ButtonPressMask | ButtonReleaseMask |
377                 PointerMotionMask | FocusChangeMask |
378                 PropertyChangeMask | KeymapStateMask;
379
380         if (exclusive) {
381                 xattributes_valuemask |= CWOverrideRedirect;
382                 xattributes.override_redirect = True;
383         }
384
385         xattributes_valuemask |= CWColormap;
386         xattributes.colormap = XCreateColormap(
387                 m_display,
388                 RootWindow(m_display, m_visualInfo->screen),
389                 m_visualInfo->visual,
390                 AllocNone
391                 );
392
393         /* create the window! */
394         if (parentWindow == 0) {
395                 m_window =  XCreateWindow(
396                         m_display,
397                         RootWindow(m_display, m_visualInfo->screen),
398                         left, top, width, height,
399                         0, /* no border. */
400                         m_visualInfo->depth,
401                         InputOutput,
402                         m_visualInfo->visual,
403                         xattributes_valuemask,
404                         &xattributes);
405         }
406         else {
407                 Window root_return;
408                 int x_return, y_return;
409                 unsigned int w_return, h_return, border_w_return, depth_return;
410                 
411                 XGetGeometry(m_display, parentWindow, &root_return, &x_return, &y_return,
412                              &w_return, &h_return, &border_w_return, &depth_return);
413
414                 left = 0;
415                 top = 0;
416                 width = w_return;
417                 height = h_return;
418
419
420                 m_window = XCreateWindow(
421                         m_display,
422                         parentWindow, /* reparent against embedder */
423                         left, top, width, height,
424                         0, /* no border. */
425                         m_visualInfo->depth,
426                         InputOutput,
427                         m_visualInfo->visual,
428                         xattributes_valuemask,
429                         &xattributes);
430
431                 XSelectInput(m_display, parentWindow, SubstructureNotifyMask);
432                 
433         }       
434
435 #ifdef WITH_XDND
436         /* initialize drop target for newly created window */
437         m_dropTarget = new GHOST_DropTargetX11(this, m_system);
438         GHOST_PRINT("Set drop target\n");
439 #endif
440
441         if (state == GHOST_kWindowStateMaximized || state == GHOST_kWindowStateFullScreen) {
442                 Atom atoms[2];
443                 int count = 0;
444                 if (state == GHOST_kWindowStateMaximized) {
445                         atoms[count++] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT;
446                         atoms[count++] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_HORZ;
447                 }
448                 else {
449                         atoms[count++] = m_system->m_atom._NET_WM_STATE_FULLSCREEN;
450                 }
451
452                 XChangeProperty(m_display, m_window, m_system->m_atom._NET_WM_STATE, XA_ATOM, 32,
453                                 PropModeReplace, (unsigned char *)atoms, count);
454                 m_post_init = False;
455         }
456         /*
457          * One of the problem with WM-spec is that can't set a property
458          * to a window that isn't mapped. That is why we can't "just
459          * call setState" here.
460          *
461          * To fix this, we first need know that the window is really
462          * map waiting for the MapNotify event.
463          *
464          * So, m_post_init indicate that we need wait for the MapNotify
465          * event and then set the Window state to the m_post_state.
466          */
467         else if ((state != GHOST_kWindowStateNormal) && (state != GHOST_kWindowStateMinimized)) {
468                 m_post_init = True;
469                 m_post_state = state;
470         }
471         else {
472                 m_post_init = False;
473                 m_post_state = GHOST_kWindowStateNormal;
474         }
475
476
477         /* Create some hints for the window manager on how
478          * we want this window treated. */
479         {
480                 XSizeHints *xsizehints = XAllocSizeHints();
481                 xsizehints->flags = PPosition | PSize | PMinSize | PMaxSize;
482                 xsizehints->x = left;
483                 xsizehints->y = top;
484                 xsizehints->width = width;
485                 xsizehints->height = height;
486                 xsizehints->min_width = 320;     /* size hints, could be made apart of the ghost api */
487                 xsizehints->min_height = 240;    /* limits are also arbitrary, but should not allow 1x1 window */
488                 xsizehints->max_width = 65535;
489                 xsizehints->max_height = 65535;
490                 XSetWMNormalHints(m_display, m_window, xsizehints);
491                 XFree(xsizehints);
492         }
493
494
495         /* XClassHint, title */
496         {
497                 XClassHint *xclasshint = XAllocClassHint();
498                 const int len = title.Length() + 1;
499                 char *wmclass = (char *)malloc(sizeof(char) * len);
500                 memcpy(wmclass, title.ReadPtr(), len * sizeof(char));
501                 xclasshint->res_name = wmclass;
502                 xclasshint->res_class = wmclass;
503                 XSetClassHint(m_display, m_window, xclasshint);
504                 free(wmclass);
505                 XFree(xclasshint);
506         }
507
508
509         /* The basic for a good ICCCM "work" */
510         if (m_system->m_atom.WM_PROTOCOLS) {
511                 Atom atoms[2];
512                 int natom = 0;
513
514                 if (m_system->m_atom.WM_DELETE_WINDOW) {
515                         atoms[natom] = m_system->m_atom.WM_DELETE_WINDOW;
516                         natom++;
517                 }
518
519                 if (m_system->m_atom.WM_TAKE_FOCUS) {
520                         atoms[natom] = m_system->m_atom.WM_TAKE_FOCUS;
521                         natom++;
522                 }
523
524                 if (natom) {
525                         /* printf("Register atoms: %d\n", natom); */
526                         XSetWMProtocols(m_display, m_window, atoms, natom);
527                 }
528         }
529
530         /* Set the window hints */
531         {
532                 XWMHints *xwmhints = XAllocWMHints();
533                 xwmhints->initial_state = NormalState;
534                 xwmhints->input = True;
535                 xwmhints->flags = InputHint | StateHint;
536                 XSetWMHints(display, m_window, xwmhints);
537                 XFree(xwmhints);
538         }
539
540
541         /* set the icon */
542         {
543                 Atom _NET_WM_ICON     = XInternAtom(m_display, "_NET_WM_ICON", False);
544                 XChangeProperty(m_display, m_window, _NET_WM_ICON, XA_CARDINAL,
545                                 32, PropModeReplace, (unsigned char *)BLENDER_ICON_48x48x32,
546                                 BLENDER_ICON_48x48x32[0] * BLENDER_ICON_48x48x32[1] + 2);
547         }
548
549         /* set the process ID (_NET_WM_PID) */
550         {
551                 Atom _NET_WM_PID = XInternAtom(m_display, "_NET_WM_PID", False);
552                 pid_t pid = getpid();
553                 XChangeProperty(m_display, m_window, _NET_WM_PID, XA_CARDINAL,
554                                 32, PropModeReplace, (unsigned char *)&pid, 1);
555         }
556
557
558         /* set the hostname (WM_CLIENT_MACHINE) */
559         {
560                 char  hostname[HOST_NAME_MAX];
561                 char *text_array[1];
562                 XTextProperty text_prop;
563
564                 gethostname(hostname, sizeof(hostname));
565                 hostname[sizeof(hostname) - 1] = '\0';
566                 text_array[0] = hostname;
567
568                 XStringListToTextProperty(text_array, 1, &text_prop);
569                 XSetWMClientMachine(m_display, m_window, &text_prop);
570                 XFree(text_prop.value);
571         }
572
573 #ifdef WITH_X11_XINPUT
574         refreshXInputDevices();
575
576         m_tabletData.Active = GHOST_kTabletModeNone;
577 #endif
578
579
580         /* now set up the rendering context. */
581         if (setDrawingContextType(type) == GHOST_kSuccess) {
582                 m_valid_setup = true;
583                 GHOST_PRINT("Created window\n");
584         }
585
586         setTitle(title);
587
588         if (exclusive) {
589                 XMapRaised(m_display, m_window);
590         }
591         else {
592                 XMapWindow(m_display, m_window);
593         }
594         GHOST_PRINT("Mapped window\n");
595
596         XFlush(m_display);
597 }
598
599 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
600 static void destroyICCallback(XIC /*xic*/, XPointer ptr, XPointer /*data*/)
601 {
602         GHOST_PRINT("XIM input context destroyed\n");
603
604         if (ptr) {
605                 *(XIC *)ptr = NULL;
606         }
607 }
608
609 bool GHOST_WindowX11::createX11_XIC()
610 {
611         XIM xim = m_system->getX11_XIM();
612         if (!xim)
613                 return false;
614
615         XICCallback destroy;
616         destroy.callback = (XICProc)destroyICCallback;
617         destroy.client_data = (XPointer)&m_xic;
618         m_xic = XCreateIC(xim, XNClientWindow, m_window, XNFocusWindow, m_window,
619                           XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
620                           XNResourceName, GHOST_X11_RES_NAME,
621                           XNResourceClass, GHOST_X11_RES_CLASS,
622                           XNDestroyCallback, &destroy,
623                           NULL);
624         if (!m_xic)
625                 return false;
626
627         unsigned long fevent;
628         XGetICValues(m_xic, XNFilterEvents, &fevent, NULL);
629         XSelectInput(m_display, m_window,
630                      ExposureMask | StructureNotifyMask |
631                      KeyPressMask | KeyReleaseMask |
632                      EnterWindowMask | LeaveWindowMask |
633                      ButtonPressMask | ButtonReleaseMask |
634                      PointerMotionMask | FocusChangeMask |
635                      PropertyChangeMask | KeymapStateMask | fevent);
636         return true;
637 }
638 #endif
639
640 #ifdef WITH_X11_XINPUT
641 void GHOST_WindowX11::refreshXInputDevices()
642 {
643         if (m_system->m_xinput_version.present) {
644                 GHOST_SystemX11::GHOST_TabletX11 &xtablet = m_system->GetXTablet();
645                 XEventClass xevents[8], ev;
646                 int dcount = 0;
647
648                 /* With modern XInput (xlib 1.6.2 at least and/or evdev 2.9.0) and some 'no-name' tablets
649                  * like 'UC-LOGIC Tablet WP5540U', we also need to 'select' ButtonPress for motion event,
650                  * otherwise we do not get any tablet motion event once pen is pressed... See T43367.
651                  */
652
653                 if (xtablet.StylusDevice) {
654                         DeviceMotionNotify(xtablet.StylusDevice, xtablet.MotionEvent, ev);
655                         if (ev) xevents[dcount++] = ev;
656                         DeviceButtonPress(xtablet.StylusDevice, xtablet.PressEvent, ev);
657                         if (ev) xevents[dcount++] = ev;
658                         ProximityIn(xtablet.StylusDevice, xtablet.ProxInEvent, ev);
659                         if (ev) xevents[dcount++] = ev;
660                         ProximityOut(xtablet.StylusDevice, xtablet.ProxOutEvent, ev);
661                         if (ev) xevents[dcount++] = ev;
662                 }
663                 if (xtablet.EraserDevice) {
664                         DeviceMotionNotify(xtablet.EraserDevice, xtablet.MotionEventEraser, ev);
665                         if (ev) xevents[dcount++] = ev;
666                         DeviceButtonPress(xtablet.EraserDevice, xtablet.PressEventEraser, ev);
667                         if (ev) xevents[dcount++] = ev;
668                         ProximityIn(xtablet.EraserDevice, xtablet.ProxInEventEraser, ev);
669                         if (ev) xevents[dcount++] = ev;
670                         ProximityOut(xtablet.EraserDevice, xtablet.ProxOutEventEraser, ev);
671                         if (ev) xevents[dcount++] = ev;
672                 }
673
674                 XSelectExtensionEvent(m_display, m_window, xevents, dcount);
675         }
676 }
677
678 #endif /* WITH_X11_XINPUT */
679
680 Window
681 GHOST_WindowX11::
682 getXWindow()
683 {
684         return m_window;
685 }
686
687 bool
688 GHOST_WindowX11::
689 getValid() const
690 {
691         return GHOST_Window::getValid() && m_valid_setup;
692 }
693
694 void
695 GHOST_WindowX11::
696 setTitle(
697                 const STR_String& title)
698 {
699         Atom name = XInternAtom(m_display, "_NET_WM_NAME", 0);
700         Atom utf8str = XInternAtom(m_display, "UTF8_STRING", 0);
701         XChangeProperty(m_display, m_window,
702                         name, utf8str, 8, PropModeReplace,
703                         (const unsigned char *) title.ReadPtr(),
704                         title.Length());
705
706         /* This should convert to valid x11 string
707          * and getTitle would need matching change */
708         XStoreName(m_display, m_window, title);
709
710         XFlush(m_display);
711 }
712
713 void
714 GHOST_WindowX11::
715 getTitle(
716                 STR_String& title) const
717 {
718         char *name = NULL;
719         
720         XFetchName(m_display, m_window, &name);
721         title = name ? name : "untitled";
722         XFree(name);
723 }
724         
725 void
726 GHOST_WindowX11::
727 getWindowBounds(
728                 GHOST_Rect& bounds) const
729 {
730         /* Getting the window bounds under X11 is not
731          * really supported (nor should it be desired). */
732         getClientBounds(bounds);
733 }
734
735 void
736 GHOST_WindowX11::
737 getClientBounds(
738                 GHOST_Rect& bounds) const
739 {
740         Window root_return;
741         int x_return, y_return;
742         unsigned int w_return, h_return, border_w_return, depth_return;
743         GHOST_TInt32 screen_x, screen_y;
744         
745         XGetGeometry(m_display, m_window, &root_return, &x_return, &y_return,
746                      &w_return, &h_return, &border_w_return, &depth_return);
747
748         clientToScreen(0, 0, screen_x, screen_y);
749         
750         bounds.m_l = screen_x;
751         bounds.m_r = bounds.m_l + w_return;
752         bounds.m_t = screen_y;
753         bounds.m_b = bounds.m_t + h_return;
754
755 }
756
757 GHOST_TSuccess
758 GHOST_WindowX11::
759 setClientWidth(
760                 GHOST_TUns32 width)
761 {
762         XWindowChanges values;
763         unsigned int value_mask = CWWidth;
764         values.width = width;
765         XConfigureWindow(m_display, m_window, value_mask, &values);
766
767         return GHOST_kSuccess;
768 }
769
770 GHOST_TSuccess
771 GHOST_WindowX11::
772 setClientHeight(
773                 GHOST_TUns32 height)
774 {
775         XWindowChanges values;
776         unsigned int value_mask = CWHeight;
777         values.height = height;
778         XConfigureWindow(m_display, m_window, value_mask, &values);
779         return GHOST_kSuccess;
780
781 }
782
783 GHOST_TSuccess
784 GHOST_WindowX11::
785 setClientSize(
786                 GHOST_TUns32 width,
787                 GHOST_TUns32 height)
788 {
789         XWindowChanges values;
790         unsigned int value_mask = CWWidth | CWHeight;
791         values.width = width;
792         values.height = height;
793         XConfigureWindow(m_display, m_window, value_mask, &values);
794         return GHOST_kSuccess;
795
796 }       
797
798 void
799 GHOST_WindowX11::
800 screenToClient(
801                 GHOST_TInt32 inX,
802                 GHOST_TInt32 inY,
803                 GHOST_TInt32& outX,
804                 GHOST_TInt32& outY) const
805 {
806         /* This is correct! */
807
808         int ax, ay;
809         Window temp;
810
811         XTranslateCoordinates(m_display,
812                               RootWindow(m_display, m_visualInfo->screen),
813                               m_window,
814                               inX, inY,
815                               &ax, &ay,
816                               &temp);
817         outX = ax;
818         outY = ay;
819 }
820                  
821 void
822 GHOST_WindowX11::
823 clientToScreen(
824                 GHOST_TInt32 inX,
825                 GHOST_TInt32 inY,
826                 GHOST_TInt32& outX,
827                 GHOST_TInt32& outY) const
828 {
829         int ax, ay;
830         Window temp;
831
832         XTranslateCoordinates(
833             m_display,
834             m_window,
835             RootWindow(m_display, m_visualInfo->screen),
836             inX, inY,
837             &ax, &ay,
838             &temp);
839         outX = ax;
840         outY = ay;
841 }
842
843 void GHOST_WindowX11::icccmSetState(int state)
844 {
845         XEvent xev;
846
847         if (state != IconicState)
848                 return;
849
850         xev.xclient.type = ClientMessage;
851         xev.xclient.serial = 0;
852         xev.xclient.send_event = True;
853         xev.xclient.display = m_display;
854         xev.xclient.window = m_window;
855         xev.xclient.format = 32;
856         xev.xclient.message_type = m_system->m_atom.WM_CHANGE_STATE;
857         xev.xclient.data.l[0] = state;
858         XSendEvent(m_display, RootWindow(m_display, m_visualInfo->screen),
859                    False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
860 }
861
862 int GHOST_WindowX11::icccmGetState(void) const
863 {
864         Atom *prop_ret;
865         unsigned long bytes_after, num_ret;
866         Atom type_ret;
867         int format_ret, st;
868
869         prop_ret = NULL;
870         st = XGetWindowProperty(
871                 m_display, m_window, m_system->m_atom.WM_STATE, 0, 2,
872                 False, m_system->m_atom.WM_STATE, &type_ret,
873                 &format_ret, &num_ret, &bytes_after, ((unsigned char **)&prop_ret));
874         if ((st == Success) && (prop_ret) && (num_ret == 2))
875                 st = prop_ret[0];
876         else
877                 st = NormalState;
878
879         if (prop_ret)
880                 XFree(prop_ret);
881         return (st);
882 }
883
884 void GHOST_WindowX11::netwmMaximized(bool set)
885 {
886         XEvent xev;
887
888         xev.xclient.type = ClientMessage;
889         xev.xclient.serial = 0;
890         xev.xclient.send_event = True;
891         xev.xclient.window = m_window;
892         xev.xclient.message_type = m_system->m_atom._NET_WM_STATE;
893         xev.xclient.format = 32;
894
895         if (set == True)
896                 xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
897         else
898                 xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
899
900         xev.xclient.data.l[1] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_HORZ;
901         xev.xclient.data.l[2] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT;
902         xev.xclient.data.l[3] = 0;
903         xev.xclient.data.l[4] = 0;
904         XSendEvent(m_display, RootWindow(m_display, m_visualInfo->screen),
905                    False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
906 }
907
908 bool GHOST_WindowX11::netwmIsMaximized(void) const
909 {
910         Atom *prop_ret;
911         unsigned long bytes_after, num_ret, i;
912         Atom type_ret;
913         bool st;
914         int format_ret, ret, count;
915
916         prop_ret = NULL;
917         st = False;
918         ret = XGetWindowProperty(
919                 m_display, m_window, m_system->m_atom._NET_WM_STATE, 0, INT_MAX,
920                 False, XA_ATOM, &type_ret, &format_ret,
921                 &num_ret, &bytes_after, (unsigned char **)&prop_ret);
922         if ((ret == Success) && (prop_ret) && (format_ret == 32)) {
923                 count = 0;
924                 for (i = 0; i < num_ret; i++) {
925                         if (prop_ret[i] == m_system->m_atom._NET_WM_STATE_MAXIMIZED_HORZ) {
926                                 count++;
927                         }
928                         if (prop_ret[i] == m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT) {
929                                 count++;
930                         }
931                         if (count == 2) {
932                                 st = True;
933                                 break;
934                         }
935                 }
936         }
937
938         if (prop_ret)
939                 XFree(prop_ret);
940         return (st);
941 }
942
943 void GHOST_WindowX11::netwmFullScreen(bool set)
944 {
945         XEvent xev;
946
947         xev.xclient.type = ClientMessage;
948         xev.xclient.serial = 0;
949         xev.xclient.send_event = True;
950         xev.xclient.window = m_window;
951         xev.xclient.message_type = m_system->m_atom._NET_WM_STATE;
952         xev.xclient.format = 32;
953
954         if (set == True)
955                 xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
956         else
957                 xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
958
959         xev.xclient.data.l[1] = m_system->m_atom._NET_WM_STATE_FULLSCREEN;
960         xev.xclient.data.l[2] = 0;
961         xev.xclient.data.l[3] = 0;
962         xev.xclient.data.l[4] = 0;
963         XSendEvent(m_display, RootWindow(m_display, m_visualInfo->screen),
964                    False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
965 }
966
967 bool GHOST_WindowX11::netwmIsFullScreen(void) const
968 {
969         Atom *prop_ret;
970         unsigned long bytes_after, num_ret, i;
971         Atom type_ret;
972         bool st;
973         int format_ret, ret;
974
975         prop_ret = NULL;
976         st = False;
977         ret = XGetWindowProperty(
978                 m_display, m_window, m_system->m_atom._NET_WM_STATE, 0, INT_MAX,
979                 False, XA_ATOM, &type_ret, &format_ret,
980                 &num_ret, &bytes_after, (unsigned char **)&prop_ret);
981         if ((ret == Success) && (prop_ret) && (format_ret == 32)) {
982                 for (i = 0; i < num_ret; i++) {
983                         if (prop_ret[i] == m_system->m_atom._NET_WM_STATE_FULLSCREEN) {
984                                 st = True;
985                                 break;
986                         }
987                 }
988         }
989
990         if (prop_ret)
991                 XFree(prop_ret);
992         return (st);
993 }
994
995 void GHOST_WindowX11::motifFullScreen(bool set)
996 {
997         MotifWmHints hints;
998
999         hints.flags = MWM_HINTS_DECORATIONS;
1000         if (set == True)
1001                 hints.decorations = 0;
1002         else
1003                 hints.decorations = 1;
1004
1005         XChangeProperty(m_display, m_window, m_system->m_atom._MOTIF_WM_HINTS,
1006                         m_system->m_atom._MOTIF_WM_HINTS, 32, PropModeReplace,
1007                         (unsigned char *) &hints, 4);
1008 }
1009
1010 bool GHOST_WindowX11::motifIsFullScreen(void) const
1011 {
1012         MotifWmHints *prop_ret;
1013         unsigned long bytes_after, num_ret;
1014         Atom type_ret;
1015         bool state;
1016         int format_ret, st;
1017
1018         prop_ret = NULL;
1019         state = False;
1020         st = XGetWindowProperty(
1021                 m_display, m_window, m_system->m_atom._MOTIF_WM_HINTS, 0, INT_MAX,
1022                 False, m_system->m_atom._MOTIF_WM_HINTS,
1023                 &type_ret, &format_ret, &num_ret,
1024                 &bytes_after, (unsigned char **)&prop_ret);
1025         if ((st == Success) && prop_ret) {
1026                 if (prop_ret->flags & MWM_HINTS_DECORATIONS) {
1027                         if (!prop_ret->decorations)
1028                                 state = True;
1029                 }
1030         }
1031
1032         if (prop_ret)
1033                 XFree(prop_ret);
1034         return (state);
1035 }
1036
1037 GHOST_TWindowState GHOST_WindowX11::getState() const
1038 {
1039         GHOST_TWindowState state_ret;
1040         int state;
1041
1042         state_ret = GHOST_kWindowStateNormal;
1043         state = icccmGetState();
1044         /*
1045          * In the Iconic and Withdrawn state, the window
1046          * is unmaped, so only need return a Minimized state.
1047          */
1048         if ((state == IconicState) || (state == WithdrawnState))
1049                 state_ret = GHOST_kWindowStateMinimized;
1050         else if (netwmIsFullScreen() == True)
1051                 state_ret = GHOST_kWindowStateFullScreen;
1052         else if (motifIsFullScreen() == True)
1053                 state_ret = GHOST_kWindowStateFullScreen;
1054         else if (netwmIsMaximized() == True)
1055                 state_ret = GHOST_kWindowStateMaximized;
1056         return (state_ret);
1057 }
1058
1059 GHOST_TSuccess GHOST_WindowX11::setState(GHOST_TWindowState state)
1060 {
1061         GHOST_TWindowState cur_state;
1062         bool is_max, is_full, is_motif_full;
1063
1064         cur_state = getState();
1065         if (state == (int)cur_state)
1066                 return GHOST_kSuccess;
1067
1068         if (cur_state != GHOST_kWindowStateMinimized) {
1069                 /*
1070                  * The window don't have this property's
1071                  * if it's not mapped.
1072                  */
1073                 is_max = netwmIsMaximized();
1074                 is_full = netwmIsFullScreen();
1075         }
1076         else {
1077                 is_max = False;
1078                 is_full = False;
1079         }
1080
1081         is_motif_full = motifIsFullScreen();
1082
1083         if (state == GHOST_kWindowStateNormal)
1084                 state = m_normal_state;
1085
1086         if (state == GHOST_kWindowStateNormal) {
1087                 if (is_max == True)
1088                         netwmMaximized(False);
1089                 if (is_full == True)
1090                         netwmFullScreen(False);
1091                 if (is_motif_full == True)
1092                         motifFullScreen(False);
1093                 icccmSetState(NormalState);
1094                 return (GHOST_kSuccess);
1095         }
1096
1097         if (state == GHOST_kWindowStateFullScreen) {
1098                 /*
1099                  * We can't change to full screen if the window
1100                  * isn't mapped.
1101                  */
1102                 if (cur_state == GHOST_kWindowStateMinimized)
1103                         return (GHOST_kFailure);
1104
1105                 m_normal_state = cur_state;
1106
1107                 if (is_max == True)
1108                         netwmMaximized(False);
1109                 if (is_full == False)
1110                         netwmFullScreen(True);
1111                 if (is_motif_full == False)
1112                         motifFullScreen(True);
1113                 return (GHOST_kSuccess);
1114         }
1115
1116         if (state == GHOST_kWindowStateMaximized) {
1117                 /*
1118                  * We can't change to Maximized if the window
1119                  * isn't mapped.
1120                  */
1121                 if (cur_state == GHOST_kWindowStateMinimized)
1122                         return (GHOST_kFailure);
1123
1124                 if (is_full == True)
1125                         netwmFullScreen(False);
1126                 if (is_motif_full == True)
1127                         motifFullScreen(False);
1128                 if (is_max == False)
1129                         netwmMaximized(True);
1130                 return (GHOST_kSuccess);
1131         }
1132
1133         if (state == GHOST_kWindowStateMinimized) {
1134                 /*
1135                  * The window manager need save the current state of
1136                  * the window (maximized, full screen, etc).
1137                  */
1138                 icccmSetState(IconicState);
1139                 return (GHOST_kSuccess);
1140         }
1141
1142         return (GHOST_kFailure);
1143 }
1144
1145 #include <iostream>
1146
1147 GHOST_TSuccess
1148 GHOST_WindowX11::
1149 setOrder(
1150                 GHOST_TWindowOrder order)
1151 {
1152         if (order == GHOST_kWindowOrderTop) {
1153                 XWindowAttributes attr;   
1154                 Atom atom;
1155
1156                 /* We use both XRaiseWindow and _NET_ACTIVE_WINDOW, since some
1157                  * window managers ignore the former (e.g. kwin from kde) and others
1158                  * don't implement the latter (e.g. fluxbox pre 0.9.9) */
1159
1160                 XRaiseWindow(m_display, m_window);
1161
1162                 atom = XInternAtom(m_display, "_NET_ACTIVE_WINDOW", True);
1163
1164                 if (atom != None) {
1165                         Window root;
1166                         XEvent xev;
1167                         long eventmask;
1168
1169                         xev.xclient.type = ClientMessage;
1170                         xev.xclient.serial = 0;
1171                         xev.xclient.send_event = True;
1172                         xev.xclient.window = m_window;
1173                         xev.xclient.message_type = atom;
1174
1175                         xev.xclient.format = 32;
1176                         xev.xclient.data.l[0] = 1;
1177                         xev.xclient.data.l[1] = CurrentTime;
1178                         xev.xclient.data.l[2] = m_window;
1179                         xev.xclient.data.l[3] = 0;
1180                         xev.xclient.data.l[4] = 0;
1181
1182                         root = RootWindow(m_display, m_visualInfo->screen);
1183                         eventmask = SubstructureRedirectMask | SubstructureNotifyMask;
1184
1185                         XSendEvent(m_display, root, False, eventmask, &xev);
1186                 }
1187
1188                 XGetWindowAttributes(m_display, m_window, &attr);
1189
1190                 /* iconized windows give bad match error */
1191                 if (attr.map_state == IsViewable)
1192                         XSetInputFocus(m_display, m_window, RevertToPointerRoot,
1193                                        CurrentTime);
1194                 XFlush(m_display);
1195         }
1196         else if (order == GHOST_kWindowOrderBottom) {
1197                 XLowerWindow(m_display, m_window);
1198                 XFlush(m_display);
1199         }
1200         else {
1201                 return GHOST_kFailure;
1202         }
1203         
1204         return GHOST_kSuccess;
1205 }
1206
1207 GHOST_TSuccess
1208 GHOST_WindowX11::
1209 invalidate()
1210 {
1211         /* So the idea of this function is to generate an expose event
1212          * for the window.
1213          * Unfortunately X does not handle expose events for you and
1214          * it is the client's job to refresh the dirty part of the window.
1215          * We need to queue up invalidate calls and generate GHOST events
1216          * for them in the system.
1217          *
1218          * We implement this by setting a boolean in this class to concatenate
1219          * all such calls into a single event for this window.
1220          *
1221          * At the same time we queue the dirty windows in the system class
1222          * and generate events for them at the next processEvents call. */
1223
1224         if (m_invalid_window == false) {
1225                 m_system->addDirtyWindow(this);
1226                 m_invalid_window = true;
1227         } 
1228  
1229         return GHOST_kSuccess;
1230 }
1231
1232 /**
1233  * called by the X11 system implementation when expose events
1234  * for the window have been pushed onto the GHOST queue
1235  */
1236  
1237 void
1238 GHOST_WindowX11::
1239 validate()
1240 {
1241         m_invalid_window = false;
1242 }       
1243  
1244  
1245 /**
1246  * Destructor.
1247  * Closes the window and disposes resources allocated.
1248  */
1249
1250 GHOST_WindowX11::
1251 ~GHOST_WindowX11()
1252 {
1253         std::map<unsigned int, Cursor>::iterator it = m_standard_cursors.begin();
1254         for (; it != m_standard_cursors.end(); ++it) {
1255                 XFreeCursor(m_display, it->second);
1256         }
1257
1258         if (m_empty_cursor) {
1259                 XFreeCursor(m_display, m_empty_cursor);
1260         }
1261         if (m_custom_cursor) {
1262                 XFreeCursor(m_display, m_custom_cursor);
1263         }
1264
1265         if (m_valid_setup) {
1266                 static Atom Primary_atom, Clipboard_atom;
1267                 Window p_owner, c_owner;
1268                 /*Change the owner of the Atoms to None if we are the owner*/
1269                 Primary_atom = XInternAtom(m_display, "PRIMARY", False);
1270                 Clipboard_atom = XInternAtom(m_display, "CLIPBOARD", False);
1271
1272
1273                 p_owner = XGetSelectionOwner(m_display, Primary_atom);
1274                 c_owner = XGetSelectionOwner(m_display, Clipboard_atom);
1275
1276                 if (p_owner == m_window) {
1277                         XSetSelectionOwner(m_display, Primary_atom, None, CurrentTime);
1278                 }
1279                 if (c_owner == m_window) {
1280                         XSetSelectionOwner(m_display, Clipboard_atom, None, CurrentTime);
1281                 }
1282         }
1283         
1284         if (m_visualInfo) {
1285                 XFree(m_visualInfo);
1286         }
1287
1288 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
1289         if (m_xic) {
1290                 XDestroyIC(m_xic);
1291         }
1292 #endif
1293
1294 #ifdef WITH_XDND
1295         delete m_dropTarget;
1296 #endif
1297
1298         releaseNativeHandles();
1299
1300         if (m_valid_setup) {
1301                 XDestroyWindow(m_display, m_window);
1302         }
1303 }
1304
1305
1306 GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type)
1307 {
1308         if (type == GHOST_kDrawingContextTypeOpenGL) {
1309
1310                 // During development:
1311                 //   try 3.2 compatibility profile
1312                 //   fall back to 3.0 if needed
1313                 //
1314                 // Final Blender 2.8:
1315                 //   try 3.2 core profile
1316                 //   no fallbacks
1317
1318                 const int profile_mask =
1319 #if defined(WITH_GL_PROFILE_CORE)
1320                         GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
1321 #elif defined(WITH_GL_PROFILE_COMPAT)
1322                         GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
1323 #else
1324 #  error // must specify either core or compat at build time
1325 #endif
1326
1327                 GHOST_Context *context = new GHOST_ContextGLX(
1328                         m_wantStereoVisual,
1329                         m_wantNumOfAASamples,
1330                         m_window,
1331                         m_display,
1332                         m_visualInfo,
1333                         (GLXFBConfig)m_fbconfig,
1334                         profile_mask,
1335                         3, 2,
1336                         GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
1337                         GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
1338
1339                 if (context->initializeDrawingContext())
1340                         return context;
1341                 else {
1342                         delete context;
1343
1344                         // since that failed try 3.0 (mostly for Mesa, which doesn't implement compatibility profile)
1345                         context = new GHOST_ContextGLX(
1346                                 m_wantStereoVisual,
1347                                 m_wantNumOfAASamples,
1348                                 m_window,
1349                                 m_display,
1350                                 m_visualInfo,
1351                                 (GLXFBConfig)m_fbconfig,
1352                                 0, // no profile bit
1353                                 3, 0,
1354                                 GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
1355                                 GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
1356
1357                         if (context->initializeDrawingContext())
1358                                 return context;
1359                         else
1360                                 delete context;
1361                 }
1362         }
1363
1364         return NULL;
1365 }
1366
1367
1368 Cursor
1369 GHOST_WindowX11::
1370 getStandardCursor(
1371                 GHOST_TStandardCursor g_cursor)
1372 {
1373         unsigned int xcursor_id;
1374
1375 #define GtoX(gcurs, xcurs)  case gcurs: xcursor_id = xcurs
1376         switch (g_cursor) {
1377                 GtoX(GHOST_kStandardCursorRightArrow, XC_arrow); break;
1378                 GtoX(GHOST_kStandardCursorLeftArrow, XC_top_left_arrow); break;
1379                 GtoX(GHOST_kStandardCursorInfo, XC_hand1); break;
1380                 GtoX(GHOST_kStandardCursorDestroy, XC_pirate); break;
1381                 GtoX(GHOST_kStandardCursorHelp, XC_question_arrow); break;
1382                 GtoX(GHOST_kStandardCursorCycle, XC_exchange); break;
1383                 GtoX(GHOST_kStandardCursorSpray, XC_spraycan); break;
1384                 GtoX(GHOST_kStandardCursorWait, XC_watch); break;
1385                 GtoX(GHOST_kStandardCursorText, XC_xterm); break;
1386                 GtoX(GHOST_kStandardCursorCrosshair, XC_crosshair); break;
1387                 GtoX(GHOST_kStandardCursorUpDown, XC_sb_v_double_arrow); break;
1388                 GtoX(GHOST_kStandardCursorLeftRight, XC_sb_h_double_arrow); break;
1389                 GtoX(GHOST_kStandardCursorTopSide, XC_top_side); break;
1390                 GtoX(GHOST_kStandardCursorBottomSide, XC_bottom_side); break;
1391                 GtoX(GHOST_kStandardCursorLeftSide, XC_left_side); break;
1392                 GtoX(GHOST_kStandardCursorRightSide, XC_right_side); break;
1393                 GtoX(GHOST_kStandardCursorTopLeftCorner, XC_top_left_corner); break;
1394                 GtoX(GHOST_kStandardCursorTopRightCorner, XC_top_right_corner); break;
1395                 GtoX(GHOST_kStandardCursorBottomRightCorner, XC_bottom_right_corner); break;
1396                 GtoX(GHOST_kStandardCursorBottomLeftCorner, XC_bottom_left_corner); break;
1397                 GtoX(GHOST_kStandardCursorPencil, XC_pencil); break;
1398                 GtoX(GHOST_kStandardCursorCopy, XC_arrow); break;
1399                 default:
1400                         xcursor_id = 0;
1401         }
1402 #undef GtoX
1403
1404         if (xcursor_id) {
1405                 Cursor xcursor = m_standard_cursors[xcursor_id];
1406                 
1407                 if (!xcursor) {
1408                         xcursor = XCreateFontCursor(m_display, xcursor_id);
1409
1410                         m_standard_cursors[xcursor_id] = xcursor;
1411                 }
1412                 
1413                 return xcursor;
1414         }
1415         else {
1416                 return None;
1417         }
1418 }
1419
1420 Cursor
1421 GHOST_WindowX11::
1422 getEmptyCursor(
1423         ) {
1424         if (!m_empty_cursor) {
1425                 Pixmap blank;
1426                 XColor dummy = {0};
1427                 char data[1] = {0};
1428                         
1429                 /* make a blank cursor */
1430                 blank = XCreateBitmapFromData(
1431                     m_display,
1432                     RootWindow(m_display, m_visualInfo->screen),
1433                     data, 1, 1
1434                     );
1435
1436                 m_empty_cursor = XCreatePixmapCursor(m_display, blank, blank, &dummy, &dummy, 0, 0);
1437                 XFreePixmap(m_display, blank);
1438         }
1439
1440         return m_empty_cursor;
1441 }
1442
1443 GHOST_TSuccess
1444 GHOST_WindowX11::
1445 setWindowCursorVisibility(
1446                 bool visible)
1447 {
1448         Cursor xcursor;
1449         
1450         if (visible) {
1451                 if (m_visible_cursor)
1452                         xcursor = m_visible_cursor;
1453                 else
1454                         xcursor = getStandardCursor(getCursorShape() );
1455         }
1456         else {
1457                 xcursor = getEmptyCursor();
1458         }
1459
1460         XDefineCursor(m_display, m_window, xcursor);
1461         XFlush(m_display);
1462         
1463         return GHOST_kSuccess;
1464 }
1465
1466 GHOST_TSuccess
1467 GHOST_WindowX11::
1468 setWindowCursorGrab(
1469                 GHOST_TGrabCursorMode mode)
1470 {
1471         if (mode != GHOST_kGrabDisable) {
1472                 if (mode != GHOST_kGrabNormal) {
1473                         m_system->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
1474                         setCursorGrabAccum(0, 0);
1475
1476                         if (mode == GHOST_kGrabHide)
1477                                 setWindowCursorVisibility(false);
1478
1479                 }
1480 #ifdef GHOST_X11_GRAB
1481                 XGrabPointer(m_display, m_window, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
1482                              GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
1483 #endif
1484         }
1485         else {
1486                 if (m_cursorGrab == GHOST_kGrabHide) {
1487                         m_system->setCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
1488                         setWindowCursorVisibility(true);
1489                 }
1490
1491                 if (m_cursorGrab != GHOST_kGrabNormal) {
1492                         /* use to generate a mouse move event, otherwise the last event
1493                          * blender gets can be outside the screen causing menus not to show
1494                          * properly unless the user moves the mouse */
1495
1496 #ifdef WITH_X11_XINPUT
1497                         if ((m_system->m_xinput_version.present) &&
1498                             (m_system->m_xinput_version.major_version >= 2))
1499                         {
1500                                 int device_id;
1501                                 if (XIGetClientPointer(m_display, None, &device_id) != False) {
1502                                         XIWarpPointer(m_display, device_id, None, None, 0, 0, 0, 0, 0, 0);
1503                                 }
1504                         }
1505                         else
1506 #endif
1507                         {
1508                                 XWarpPointer(m_display, None, None, 0, 0, 0, 0, 0, 0);
1509                         }
1510                 }
1511
1512                 /* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
1513                 setCursorGrabAccum(0, 0);
1514                 m_cursorGrabBounds.m_l = m_cursorGrabBounds.m_r = -1; /* disable */
1515 #ifdef GHOST_X11_GRAB
1516                 XUngrabPointer(m_display, CurrentTime);
1517 #endif
1518         }
1519
1520         XFlush(m_display);
1521         
1522         return GHOST_kSuccess;
1523 }
1524
1525 GHOST_TSuccess
1526 GHOST_WindowX11::
1527 setWindowCursorShape(
1528                 GHOST_TStandardCursor shape)
1529 {
1530         Cursor xcursor = getStandardCursor(shape);
1531
1532         m_visible_cursor = xcursor;
1533         
1534         XDefineCursor(m_display, m_window, xcursor);
1535         XFlush(m_display);
1536
1537         return GHOST_kSuccess;
1538 }
1539
1540 GHOST_TSuccess
1541 GHOST_WindowX11::
1542 setWindowCustomCursorShape(
1543                 GHOST_TUns8 bitmap[16][2],
1544                 GHOST_TUns8 mask[16][2],
1545                 int hotX,
1546                 int hotY)
1547 {
1548         setWindowCustomCursorShape((GHOST_TUns8 *)bitmap, (GHOST_TUns8 *)mask,
1549                                    16, 16, hotX, hotY, 0, 1);
1550         return GHOST_kSuccess;
1551 }
1552
1553 GHOST_TSuccess
1554 GHOST_WindowX11::
1555 setWindowCustomCursorShape(     
1556                 GHOST_TUns8 *bitmap,
1557                 GHOST_TUns8 *mask,
1558                 int sizex,
1559                 int sizey,
1560                 int hotX,
1561                 int hotY,
1562                 int /*fg_color*/,
1563                 int /*bg_color*/)
1564 {
1565         Colormap colormap = DefaultColormap(m_display, m_visualInfo->screen);
1566         Pixmap bitmap_pix, mask_pix;
1567         XColor fg, bg;
1568         
1569         if (XAllocNamedColor(m_display, colormap, "White", &fg, &fg) == 0) return GHOST_kFailure;
1570         if (XAllocNamedColor(m_display, colormap, "Black", &bg, &bg) == 0) return GHOST_kFailure;
1571
1572         if (m_custom_cursor) {
1573                 XFreeCursor(m_display, m_custom_cursor);
1574         }
1575
1576         bitmap_pix = XCreateBitmapFromData(m_display, m_window, (char *) bitmap, sizex, sizey);
1577         mask_pix = XCreateBitmapFromData(m_display, m_window, (char *) mask, sizex, sizey);
1578                 
1579         m_custom_cursor = XCreatePixmapCursor(m_display, bitmap_pix, mask_pix, &fg, &bg, hotX, hotY);
1580         XDefineCursor(m_display, m_window, m_custom_cursor);
1581         XFlush(m_display);
1582
1583         m_visible_cursor = m_custom_cursor;
1584         
1585         XFreePixmap(m_display, bitmap_pix);
1586         XFreePixmap(m_display, mask_pix);
1587
1588         XFreeColors(m_display, colormap, &fg.pixel, 1, 0L);
1589         XFreeColors(m_display, colormap, &bg.pixel, 1, 0L);
1590
1591         return GHOST_kSuccess;
1592 }
1593
1594
1595 GHOST_TSuccess
1596 GHOST_WindowX11::
1597 beginFullScreen() const
1598 {
1599         {
1600                 Window root_return;
1601                 int x_return, y_return;
1602                 unsigned int w_return, h_return, border_w_return, depth_return;
1603
1604                 XGetGeometry(m_display, m_window, &root_return, &x_return, &y_return,
1605                              &w_return, &h_return, &border_w_return, &depth_return);
1606
1607                 m_system->setCursorPosition(w_return / 2, h_return / 2);
1608         }
1609
1610
1611         /* Grab Keyboard & Mouse */
1612         int err;
1613
1614         err = XGrabKeyboard(m_display, m_window, False,
1615                             GrabModeAsync, GrabModeAsync, CurrentTime);
1616         if (err != GrabSuccess) printf("XGrabKeyboard failed %d\n", err);
1617
1618         err = XGrabPointer(m_display, m_window, False,  PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
1619                            GrabModeAsync, GrabModeAsync, m_window, None, CurrentTime);
1620         if (err != GrabSuccess) printf("XGrabPointer failed %d\n", err);
1621
1622         return GHOST_kSuccess;
1623 }
1624
1625 GHOST_TSuccess
1626 GHOST_WindowX11::
1627 endFullScreen() const
1628 {
1629         XUngrabKeyboard(m_display, CurrentTime);
1630         XUngrabPointer(m_display, CurrentTime);
1631
1632         return GHOST_kSuccess;
1633 }