X11: support multiple tablet devices.
[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 //For DPI value
60 #include <X11/Xresource.h>
61
62 #include <cstring>
63 #include <cstdio>
64
65 /* gethostname */
66 #include <unistd.h>
67
68 #include <algorithm>
69 #include <string>
70 #include <math.h>
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       m_taskbar("blender.desktop"),
338 #ifdef WITH_XDND
339       m_dropTarget(NULL),
340 #endif
341 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
342       m_xic(NULL),
343 #endif
344       m_valid_setup(false),
345       m_is_debug_context(is_debug)
346 {
347         if (type == GHOST_kDrawingContextTypeOpenGL) {
348                 m_visualInfo = x11_visualinfo_from_glx(m_display, stereoVisual, &m_wantNumOfAASamples, alphaBackground, (GLXFBConfig*)&m_fbconfig);
349         }
350         else {
351                 XVisualInfo tmp = {0};
352                 int n;
353                 m_visualInfo = XGetVisualInfo(m_display, 0, &tmp, &n);
354         }
355
356         /* caller needs to check 'getValid()' */
357         if (m_visualInfo == NULL) {
358                 fprintf(stderr, "initial window could not find the GLX extension\n");
359                 return;
360         }
361
362         unsigned int xattributes_valuemask = 0;
363
364         XSetWindowAttributes xattributes;
365         memset(&xattributes, 0, sizeof(xattributes));
366
367         xattributes_valuemask |= CWBorderPixel;
368         xattributes.border_pixel = 0;
369
370         /* Specify which events we are interested in hearing. */
371
372         xattributes_valuemask |= CWEventMask;
373         xattributes.event_mask =
374                 ExposureMask | StructureNotifyMask |
375                 KeyPressMask | KeyReleaseMask |
376                 EnterWindowMask | LeaveWindowMask |
377                 ButtonPressMask | ButtonReleaseMask |
378                 PointerMotionMask | FocusChangeMask |
379                 PropertyChangeMask | KeymapStateMask;
380
381         if (exclusive) {
382                 xattributes_valuemask |= CWOverrideRedirect;
383                 xattributes.override_redirect = True;
384         }
385
386         xattributes_valuemask |= CWColormap;
387         xattributes.colormap = XCreateColormap(
388                 m_display,
389                 RootWindow(m_display, m_visualInfo->screen),
390                 m_visualInfo->visual,
391                 AllocNone
392                 );
393
394         /* create the window! */
395         if (parentWindow == 0) {
396                 m_window =  XCreateWindow(
397                         m_display,
398                         RootWindow(m_display, m_visualInfo->screen),
399                         left, top, width, height,
400                         0, /* no border. */
401                         m_visualInfo->depth,
402                         InputOutput,
403                         m_visualInfo->visual,
404                         xattributes_valuemask,
405                         &xattributes);
406         }
407         else {
408                 Window root_return;
409                 int x_return, y_return;
410                 unsigned int w_return, h_return, border_w_return, depth_return;
411
412                 XGetGeometry(m_display, parentWindow, &root_return, &x_return, &y_return,
413                              &w_return, &h_return, &border_w_return, &depth_return);
414
415                 left = 0;
416                 top = 0;
417                 width = w_return;
418                 height = h_return;
419
420
421                 m_window = XCreateWindow(
422                         m_display,
423                         parentWindow, /* reparent against embedder */
424                         left, top, width, height,
425                         0, /* no border. */
426                         m_visualInfo->depth,
427                         InputOutput,
428                         m_visualInfo->visual,
429                         xattributes_valuemask,
430                         &xattributes);
431
432                 XSelectInput(m_display, parentWindow, SubstructureNotifyMask);
433
434         }
435
436 #ifdef WITH_XDND
437         /* initialize drop target for newly created window */
438         m_dropTarget = new GHOST_DropTargetX11(this, m_system);
439         GHOST_PRINT("Set drop target\n");
440 #endif
441
442         if (state == GHOST_kWindowStateMaximized || state == GHOST_kWindowStateFullScreen) {
443                 Atom atoms[2];
444                 int count = 0;
445                 if (state == GHOST_kWindowStateMaximized) {
446                         atoms[count++] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT;
447                         atoms[count++] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_HORZ;
448                 }
449                 else {
450                         atoms[count++] = m_system->m_atom._NET_WM_STATE_FULLSCREEN;
451                 }
452
453                 XChangeProperty(m_display, m_window, m_system->m_atom._NET_WM_STATE, XA_ATOM, 32,
454                                 PropModeReplace, (unsigned char *)atoms, count);
455                 m_post_init = False;
456         }
457         /*
458          * One of the problem with WM-spec is that can't set a property
459          * to a window that isn't mapped. That is why we can't "just
460          * call setState" here.
461          *
462          * To fix this, we first need know that the window is really
463          * map waiting for the MapNotify event.
464          *
465          * So, m_post_init indicate that we need wait for the MapNotify
466          * event and then set the Window state to the m_post_state.
467          */
468         else if ((state != GHOST_kWindowStateNormal) && (state != GHOST_kWindowStateMinimized)) {
469                 m_post_init = True;
470                 m_post_state = state;
471         }
472         else {
473                 m_post_init = False;
474                 m_post_state = GHOST_kWindowStateNormal;
475         }
476
477
478         /* Create some hints for the window manager on how
479          * we want this window treated. */
480         {
481                 XSizeHints *xsizehints = XAllocSizeHints();
482                 xsizehints->flags = PPosition | PSize | PMinSize | PMaxSize;
483                 xsizehints->x = left;
484                 xsizehints->y = top;
485                 xsizehints->width = width;
486                 xsizehints->height = height;
487                 xsizehints->min_width = 320;     /* size hints, could be made apart of the ghost api */
488                 xsizehints->min_height = 240;    /* limits are also arbitrary, but should not allow 1x1 window */
489                 xsizehints->max_width = 65535;
490                 xsizehints->max_height = 65535;
491                 XSetWMNormalHints(m_display, m_window, xsizehints);
492                 XFree(xsizehints);
493         }
494
495
496         /* XClassHint, title */
497         {
498                 XClassHint *xclasshint = XAllocClassHint();
499                 const int len = title.Length() + 1;
500                 char *wmclass = (char *)malloc(sizeof(char) * len);
501                 memcpy(wmclass, title.ReadPtr(), len * sizeof(char));
502                 xclasshint->res_name = wmclass;
503                 xclasshint->res_class = wmclass;
504                 XSetClassHint(m_display, m_window, xclasshint);
505                 free(wmclass);
506                 XFree(xclasshint);
507         }
508
509
510         /* The basic for a good ICCCM "work" */
511         if (m_system->m_atom.WM_PROTOCOLS) {
512                 Atom atoms[2];
513                 int natom = 0;
514
515                 if (m_system->m_atom.WM_DELETE_WINDOW) {
516                         atoms[natom] = m_system->m_atom.WM_DELETE_WINDOW;
517                         natom++;
518                 }
519
520                 if (m_system->m_atom.WM_TAKE_FOCUS && m_system->m_windowFocus) {
521                         atoms[natom] = m_system->m_atom.WM_TAKE_FOCUS;
522                         natom++;
523                 }
524
525                 if (natom) {
526                         /* printf("Register atoms: %d\n", natom); */
527                         XSetWMProtocols(m_display, m_window, atoms, natom);
528                 }
529         }
530
531         /* Set the window hints */
532         {
533                 XWMHints *xwmhints = XAllocWMHints();
534                 xwmhints->initial_state = NormalState;
535                 xwmhints->input = (m_system->m_windowFocus) ? True : False;
536                 xwmhints->flags = InputHint | StateHint;
537                 XSetWMHints(display, m_window, xwmhints);
538                 XFree(xwmhints);
539         }
540
541
542         /* set the icon */
543         {
544                 Atom _NET_WM_ICON     = XInternAtom(m_display, "_NET_WM_ICON", False);
545                 XChangeProperty(m_display, m_window, _NET_WM_ICON, XA_CARDINAL,
546                                 32, PropModeReplace, (unsigned char *)BLENDER_ICON_48x48x32,
547                                 BLENDER_ICON_48x48x32[0] * BLENDER_ICON_48x48x32[1] + 2);
548         }
549
550         /* set the process ID (_NET_WM_PID) */
551         {
552                 Atom _NET_WM_PID = XInternAtom(m_display, "_NET_WM_PID", False);
553                 pid_t pid = getpid();
554                 XChangeProperty(m_display, m_window, _NET_WM_PID, XA_CARDINAL,
555                                 32, PropModeReplace, (unsigned char *)&pid, 1);
556         }
557
558
559         /* set the hostname (WM_CLIENT_MACHINE) */
560         {
561                 char  hostname[HOST_NAME_MAX];
562                 char *text_array[1];
563                 XTextProperty text_prop;
564
565                 gethostname(hostname, sizeof(hostname));
566                 hostname[sizeof(hostname) - 1] = '\0';
567                 text_array[0] = hostname;
568
569                 XStringListToTextProperty(text_array, 1, &text_prop);
570                 XSetWMClientMachine(m_display, m_window, &text_prop);
571                 XFree(text_prop.value);
572         }
573
574 #ifdef WITH_X11_XINPUT
575         refreshXInputDevices();
576
577         m_tabletData.Active = GHOST_kTabletModeNone;
578 #endif
579
580
581         /* now set up the rendering context. */
582         if (setDrawingContextType(type) == GHOST_kSuccess) {
583                 m_valid_setup = true;
584                 GHOST_PRINT("Created window\n");
585         }
586
587         setTitle(title);
588
589         if (exclusive && system->m_windowFocus) {
590                 XMapRaised(m_display, m_window);
591         }
592         else {
593                 XMapWindow(m_display, m_window);
594
595                 if (!system->m_windowFocus) {
596                         XLowerWindow(m_display, m_window);
597                 }
598         }
599         GHOST_PRINT("Mapped window\n");
600
601         XFlush(m_display);
602 }
603
604 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
605 static Bool destroyICCallback(XIC /*xic*/, XPointer ptr, XPointer /*data*/)
606 {
607         GHOST_PRINT("XIM input context destroyed\n");
608
609         if (ptr) {
610                 *(XIC *)ptr = NULL;
611         }
612         /* Ignored by X11. */
613         return True;
614 }
615
616 bool GHOST_WindowX11::createX11_XIC()
617 {
618         XIM xim = m_system->getX11_XIM();
619         if (!xim)
620                 return false;
621
622         XICCallback destroy;
623         destroy.callback = (XICProc)destroyICCallback;
624         destroy.client_data = (XPointer)&m_xic;
625         m_xic = XCreateIC(xim, XNClientWindow, m_window, XNFocusWindow, m_window,
626                           XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
627                           XNResourceName, GHOST_X11_RES_NAME,
628                           XNResourceClass, GHOST_X11_RES_CLASS,
629                           XNDestroyCallback, &destroy,
630                           NULL);
631         if (!m_xic)
632                 return false;
633
634         unsigned long fevent;
635         XGetICValues(m_xic, XNFilterEvents, &fevent, NULL);
636         XSelectInput(m_display, m_window,
637                      ExposureMask | StructureNotifyMask |
638                      KeyPressMask | KeyReleaseMask |
639                      EnterWindowMask | LeaveWindowMask |
640                      ButtonPressMask | ButtonReleaseMask |
641                      PointerMotionMask | FocusChangeMask |
642                      PropertyChangeMask | KeymapStateMask | fevent);
643         return true;
644 }
645 #endif
646
647 #ifdef WITH_X11_XINPUT
648 void GHOST_WindowX11::refreshXInputDevices()
649 {
650         if (m_system->m_xinput_version.present) {
651                 std::vector<XEventClass> xevents;
652
653                 for (GHOST_SystemX11::GHOST_TabletX11& xtablet: m_system->GetXTablets()) {
654                         /* With modern XInput (xlib 1.6.2 at least and/or evdev 2.9.0) and some 'no-name' tablets
655                          * like 'UC-LOGIC Tablet WP5540U', we also need to 'select' ButtonPress for motion event,
656                          * otherwise we do not get any tablet motion event once pen is pressed... See T43367.
657                          */
658                         XEventClass ev;
659
660                         DeviceMotionNotify(xtablet.Device, xtablet.MotionEvent, ev);
661                         if (ev) xevents.push_back(ev);
662                         DeviceButtonPress(xtablet.Device, xtablet.PressEvent, ev);
663                         if (ev) xevents.push_back(ev);
664                         ProximityIn(xtablet.Device, xtablet.ProxInEvent, ev);
665                         if (ev) xevents.push_back(ev);
666                         ProximityOut(xtablet.Device, xtablet.ProxOutEvent, ev);
667                         if (ev) xevents.push_back(ev);
668                 }
669
670                 XSelectExtensionEvent(m_display, m_window, xevents.data(), (int)xevents.size());
671         }
672 }
673
674 #endif /* WITH_X11_XINPUT */
675
676 Window
677 GHOST_WindowX11::
678 getXWindow()
679 {
680         return m_window;
681 }
682
683 bool
684 GHOST_WindowX11::
685 getValid() const
686 {
687         return GHOST_Window::getValid() && m_valid_setup;
688 }
689
690 void
691 GHOST_WindowX11::
692 setTitle(
693                 const STR_String& title)
694 {
695         Atom name = XInternAtom(m_display, "_NET_WM_NAME", 0);
696         Atom utf8str = XInternAtom(m_display, "UTF8_STRING", 0);
697         XChangeProperty(m_display, m_window,
698                         name, utf8str, 8, PropModeReplace,
699                         (const unsigned char *) title.ReadPtr(),
700                         title.Length());
701
702         /* This should convert to valid x11 string
703          * and getTitle would need matching change */
704         XStoreName(m_display, m_window, title);
705
706         XFlush(m_display);
707 }
708
709 void
710 GHOST_WindowX11::
711 getTitle(
712                 STR_String& title) const
713 {
714         char *name = NULL;
715
716         XFetchName(m_display, m_window, &name);
717         title = name ? name : "untitled";
718         XFree(name);
719 }
720
721 void
722 GHOST_WindowX11::
723 getWindowBounds(
724                 GHOST_Rect& bounds) const
725 {
726         /* Getting the window bounds under X11 is not
727          * really supported (nor should it be desired). */
728         getClientBounds(bounds);
729 }
730
731 void
732 GHOST_WindowX11::
733 getClientBounds(
734                 GHOST_Rect& bounds) const
735 {
736         Window root_return;
737         int x_return, y_return;
738         unsigned int w_return, h_return, border_w_return, depth_return;
739         GHOST_TInt32 screen_x, screen_y;
740
741         XGetGeometry(m_display, m_window, &root_return, &x_return, &y_return,
742                      &w_return, &h_return, &border_w_return, &depth_return);
743
744         clientToScreen(0, 0, screen_x, screen_y);
745
746         bounds.m_l = screen_x;
747         bounds.m_r = bounds.m_l + w_return;
748         bounds.m_t = screen_y;
749         bounds.m_b = bounds.m_t + h_return;
750
751 }
752
753 GHOST_TSuccess
754 GHOST_WindowX11::
755 setClientWidth(
756                 GHOST_TUns32 width)
757 {
758         XWindowChanges values;
759         unsigned int value_mask = CWWidth;
760         values.width = width;
761         XConfigureWindow(m_display, m_window, value_mask, &values);
762
763         return GHOST_kSuccess;
764 }
765
766 GHOST_TSuccess
767 GHOST_WindowX11::
768 setClientHeight(
769                 GHOST_TUns32 height)
770 {
771         XWindowChanges values;
772         unsigned int value_mask = CWHeight;
773         values.height = height;
774         XConfigureWindow(m_display, m_window, value_mask, &values);
775         return GHOST_kSuccess;
776
777 }
778
779 GHOST_TSuccess
780 GHOST_WindowX11::
781 setClientSize(
782                 GHOST_TUns32 width,
783                 GHOST_TUns32 height)
784 {
785         XWindowChanges values;
786         unsigned int value_mask = CWWidth | CWHeight;
787         values.width = width;
788         values.height = height;
789         XConfigureWindow(m_display, m_window, value_mask, &values);
790         return GHOST_kSuccess;
791
792 }
793
794 void
795 GHOST_WindowX11::
796 screenToClient(
797                 GHOST_TInt32 inX,
798                 GHOST_TInt32 inY,
799                 GHOST_TInt32& outX,
800                 GHOST_TInt32& outY) const
801 {
802         /* This is correct! */
803
804         int ax, ay;
805         Window temp;
806
807         XTranslateCoordinates(m_display,
808                               RootWindow(m_display, m_visualInfo->screen),
809                               m_window,
810                               inX, inY,
811                               &ax, &ay,
812                               &temp);
813         outX = ax;
814         outY = ay;
815 }
816
817 void
818 GHOST_WindowX11::
819 clientToScreen(
820                 GHOST_TInt32 inX,
821                 GHOST_TInt32 inY,
822                 GHOST_TInt32& outX,
823                 GHOST_TInt32& outY) const
824 {
825         int ax, ay;
826         Window temp;
827
828         XTranslateCoordinates(
829             m_display,
830             m_window,
831             RootWindow(m_display, m_visualInfo->screen),
832             inX, inY,
833             &ax, &ay,
834             &temp);
835         outX = ax;
836         outY = ay;
837 }
838
839 void GHOST_WindowX11::icccmSetState(int state)
840 {
841         XEvent xev;
842
843         if (state != IconicState)
844                 return;
845
846         xev.xclient.type = ClientMessage;
847         xev.xclient.serial = 0;
848         xev.xclient.send_event = True;
849         xev.xclient.display = m_display;
850         xev.xclient.window = m_window;
851         xev.xclient.format = 32;
852         xev.xclient.message_type = m_system->m_atom.WM_CHANGE_STATE;
853         xev.xclient.data.l[0] = state;
854         XSendEvent(m_display, RootWindow(m_display, m_visualInfo->screen),
855                    False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
856 }
857
858 int GHOST_WindowX11::icccmGetState(void) const
859 {
860         struct {
861                 CARD32 state;
862                 XID    icon;
863         } *prop_ret;
864         unsigned long bytes_after, num_ret;
865         Atom type_ret;
866         int ret, format_ret;
867         CARD32 st;
868
869         prop_ret = NULL;
870         ret = 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 ((ret == Success) && (prop_ret != NULL) && (num_ret == 2)) {
875                 st = prop_ret->state;
876         }
877         else {
878                 st = NormalState;
879         }
880
881         if (prop_ret) {
882                 XFree(prop_ret);
883         }
884
885         return st;
886 }
887
888 void GHOST_WindowX11::netwmMaximized(bool set)
889 {
890         XEvent xev;
891
892         xev.xclient.type = ClientMessage;
893         xev.xclient.serial = 0;
894         xev.xclient.send_event = True;
895         xev.xclient.window = m_window;
896         xev.xclient.message_type = m_system->m_atom._NET_WM_STATE;
897         xev.xclient.format = 32;
898
899         if (set == True)
900                 xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
901         else
902                 xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
903
904         xev.xclient.data.l[1] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_HORZ;
905         xev.xclient.data.l[2] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT;
906         xev.xclient.data.l[3] = 0;
907         xev.xclient.data.l[4] = 0;
908         XSendEvent(m_display, RootWindow(m_display, m_visualInfo->screen),
909                    False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
910 }
911
912 bool GHOST_WindowX11::netwmIsMaximized(void) const
913 {
914         Atom *prop_ret;
915         unsigned long bytes_after, num_ret, i;
916         Atom type_ret;
917         bool st;
918         int format_ret, ret, count;
919
920         prop_ret = NULL;
921         st = False;
922         ret = XGetWindowProperty(
923                 m_display, m_window, m_system->m_atom._NET_WM_STATE, 0, INT_MAX,
924                 False, XA_ATOM, &type_ret, &format_ret,
925                 &num_ret, &bytes_after, (unsigned char **)&prop_ret);
926         if ((ret == Success) && (prop_ret) && (format_ret == 32)) {
927                 count = 0;
928                 for (i = 0; i < num_ret; i++) {
929                         if (prop_ret[i] == m_system->m_atom._NET_WM_STATE_MAXIMIZED_HORZ) {
930                                 count++;
931                         }
932                         if (prop_ret[i] == m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT) {
933                                 count++;
934                         }
935                         if (count == 2) {
936                                 st = True;
937                                 break;
938                         }
939                 }
940         }
941
942         if (prop_ret)
943                 XFree(prop_ret);
944         return (st);
945 }
946
947 void GHOST_WindowX11::netwmFullScreen(bool set)
948 {
949         XEvent xev;
950
951         xev.xclient.type = ClientMessage;
952         xev.xclient.serial = 0;
953         xev.xclient.send_event = True;
954         xev.xclient.window = m_window;
955         xev.xclient.message_type = m_system->m_atom._NET_WM_STATE;
956         xev.xclient.format = 32;
957
958         if (set == True)
959                 xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
960         else
961                 xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
962
963         xev.xclient.data.l[1] = m_system->m_atom._NET_WM_STATE_FULLSCREEN;
964         xev.xclient.data.l[2] = 0;
965         xev.xclient.data.l[3] = 0;
966         xev.xclient.data.l[4] = 0;
967         XSendEvent(m_display, RootWindow(m_display, m_visualInfo->screen),
968                    False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
969 }
970
971 bool GHOST_WindowX11::netwmIsFullScreen(void) const
972 {
973         Atom *prop_ret;
974         unsigned long bytes_after, num_ret, i;
975         Atom type_ret;
976         bool st;
977         int format_ret, ret;
978
979         prop_ret = NULL;
980         st = False;
981         ret = XGetWindowProperty(
982                 m_display, m_window, m_system->m_atom._NET_WM_STATE, 0, INT_MAX,
983                 False, XA_ATOM, &type_ret, &format_ret,
984                 &num_ret, &bytes_after, (unsigned char **)&prop_ret);
985         if ((ret == Success) && (prop_ret) && (format_ret == 32)) {
986                 for (i = 0; i < num_ret; i++) {
987                         if (prop_ret[i] == m_system->m_atom._NET_WM_STATE_FULLSCREEN) {
988                                 st = True;
989                                 break;
990                         }
991                 }
992         }
993
994         if (prop_ret)
995                 XFree(prop_ret);
996         return (st);
997 }
998
999 void GHOST_WindowX11::motifFullScreen(bool set)
1000 {
1001         MotifWmHints hints;
1002
1003         hints.flags = MWM_HINTS_DECORATIONS;
1004         if (set == True)
1005                 hints.decorations = 0;
1006         else
1007                 hints.decorations = 1;
1008
1009         XChangeProperty(m_display, m_window, m_system->m_atom._MOTIF_WM_HINTS,
1010                         m_system->m_atom._MOTIF_WM_HINTS, 32, PropModeReplace,
1011                         (unsigned char *) &hints, 4);
1012 }
1013
1014 bool GHOST_WindowX11::motifIsFullScreen(void) const
1015 {
1016         MotifWmHints *prop_ret;
1017         unsigned long bytes_after, num_ret;
1018         Atom type_ret;
1019         bool state;
1020         int format_ret, st;
1021
1022         prop_ret = NULL;
1023         state = False;
1024         st = XGetWindowProperty(
1025                 m_display, m_window, m_system->m_atom._MOTIF_WM_HINTS, 0, INT_MAX,
1026                 False, m_system->m_atom._MOTIF_WM_HINTS,
1027                 &type_ret, &format_ret, &num_ret,
1028                 &bytes_after, (unsigned char **)&prop_ret);
1029         if ((st == Success) && prop_ret) {
1030                 if (prop_ret->flags & MWM_HINTS_DECORATIONS) {
1031                         if (!prop_ret->decorations)
1032                                 state = True;
1033                 }
1034         }
1035
1036         if (prop_ret)
1037                 XFree(prop_ret);
1038         return (state);
1039 }
1040
1041 GHOST_TWindowState GHOST_WindowX11::getState() const
1042 {
1043         GHOST_TWindowState state_ret;
1044         int state;
1045
1046         state_ret = GHOST_kWindowStateNormal;
1047         state = icccmGetState();
1048         /*
1049          * In the Iconic and Withdrawn state, the window
1050          * is unmaped, so only need return a Minimized state.
1051          */
1052         if ((state == IconicState) || (state == WithdrawnState))
1053                 state_ret = GHOST_kWindowStateMinimized;
1054         else if (netwmIsFullScreen() == True)
1055                 state_ret = GHOST_kWindowStateFullScreen;
1056         else if (motifIsFullScreen() == True)
1057                 state_ret = GHOST_kWindowStateFullScreen;
1058         else if (netwmIsMaximized() == True)
1059                 state_ret = GHOST_kWindowStateMaximized;
1060         return (state_ret);
1061 }
1062
1063 GHOST_TSuccess GHOST_WindowX11::setState(GHOST_TWindowState state)
1064 {
1065         GHOST_TWindowState cur_state;
1066         bool is_max, is_full, is_motif_full;
1067
1068         cur_state = getState();
1069         if (state == (int)cur_state)
1070                 return GHOST_kSuccess;
1071
1072         if (cur_state != GHOST_kWindowStateMinimized) {
1073                 /*
1074                  * The window don't have this property's
1075                  * if it's not mapped.
1076                  */
1077                 is_max = netwmIsMaximized();
1078                 is_full = netwmIsFullScreen();
1079         }
1080         else {
1081                 is_max = False;
1082                 is_full = False;
1083         }
1084
1085         is_motif_full = motifIsFullScreen();
1086
1087         if (state == GHOST_kWindowStateNormal)
1088                 state = m_normal_state;
1089
1090         if (state == GHOST_kWindowStateNormal) {
1091                 if (is_max == True)
1092                         netwmMaximized(False);
1093                 if (is_full == True)
1094                         netwmFullScreen(False);
1095                 if (is_motif_full == True)
1096                         motifFullScreen(False);
1097                 icccmSetState(NormalState);
1098                 return (GHOST_kSuccess);
1099         }
1100
1101         if (state == GHOST_kWindowStateFullScreen) {
1102                 /*
1103                  * We can't change to full screen if the window
1104                  * isn't mapped.
1105                  */
1106                 if (cur_state == GHOST_kWindowStateMinimized)
1107                         return (GHOST_kFailure);
1108
1109                 m_normal_state = cur_state;
1110
1111                 if (is_max == True)
1112                         netwmMaximized(False);
1113                 if (is_full == False)
1114                         netwmFullScreen(True);
1115                 if (is_motif_full == False)
1116                         motifFullScreen(True);
1117                 return (GHOST_kSuccess);
1118         }
1119
1120         if (state == GHOST_kWindowStateMaximized) {
1121                 /*
1122                  * We can't change to Maximized if the window
1123                  * isn't mapped.
1124                  */
1125                 if (cur_state == GHOST_kWindowStateMinimized)
1126                         return (GHOST_kFailure);
1127
1128                 if (is_full == True)
1129                         netwmFullScreen(False);
1130                 if (is_motif_full == True)
1131                         motifFullScreen(False);
1132                 if (is_max == False)
1133                         netwmMaximized(True);
1134                 return (GHOST_kSuccess);
1135         }
1136
1137         if (state == GHOST_kWindowStateMinimized) {
1138                 /*
1139                  * The window manager need save the current state of
1140                  * the window (maximized, full screen, etc).
1141                  */
1142                 icccmSetState(IconicState);
1143                 return (GHOST_kSuccess);
1144         }
1145
1146         return (GHOST_kFailure);
1147 }
1148
1149 #include <iostream>
1150
1151 GHOST_TSuccess
1152 GHOST_WindowX11::
1153 setOrder(
1154                 GHOST_TWindowOrder order)
1155 {
1156         if (order == GHOST_kWindowOrderTop) {
1157                 XWindowAttributes attr;
1158                 Atom atom;
1159
1160                 /* We use both XRaiseWindow and _NET_ACTIVE_WINDOW, since some
1161                  * window managers ignore the former (e.g. kwin from kde) and others
1162                  * don't implement the latter (e.g. fluxbox pre 0.9.9) */
1163
1164                 XRaiseWindow(m_display, m_window);
1165
1166                 atom = XInternAtom(m_display, "_NET_ACTIVE_WINDOW", True);
1167
1168                 if (atom != None) {
1169                         Window root;
1170                         XEvent xev;
1171                         long eventmask;
1172
1173                         xev.xclient.type = ClientMessage;
1174                         xev.xclient.serial = 0;
1175                         xev.xclient.send_event = True;
1176                         xev.xclient.window = m_window;
1177                         xev.xclient.message_type = atom;
1178
1179                         xev.xclient.format = 32;
1180                         xev.xclient.data.l[0] = 1;
1181                         xev.xclient.data.l[1] = CurrentTime;
1182                         xev.xclient.data.l[2] = m_window;
1183                         xev.xclient.data.l[3] = 0;
1184                         xev.xclient.data.l[4] = 0;
1185
1186                         root = RootWindow(m_display, m_visualInfo->screen);
1187                         eventmask = SubstructureRedirectMask | SubstructureNotifyMask;
1188
1189                         XSendEvent(m_display, root, False, eventmask, &xev);
1190                 }
1191
1192                 XGetWindowAttributes(m_display, m_window, &attr);
1193
1194                 /* iconized windows give bad match error */
1195                 if (attr.map_state == IsViewable)
1196                         XSetInputFocus(m_display, m_window, RevertToPointerRoot,
1197                                        CurrentTime);
1198                 XFlush(m_display);
1199         }
1200         else if (order == GHOST_kWindowOrderBottom) {
1201                 XLowerWindow(m_display, m_window);
1202                 XFlush(m_display);
1203         }
1204         else {
1205                 return GHOST_kFailure;
1206         }
1207
1208         return GHOST_kSuccess;
1209 }
1210
1211 GHOST_TSuccess
1212 GHOST_WindowX11::
1213 invalidate()
1214 {
1215         /* So the idea of this function is to generate an expose event
1216          * for the window.
1217          * Unfortunately X does not handle expose events for you and
1218          * it is the client's job to refresh the dirty part of the window.
1219          * We need to queue up invalidate calls and generate GHOST events
1220          * for them in the system.
1221          *
1222          * We implement this by setting a boolean in this class to concatenate
1223          * all such calls into a single event for this window.
1224          *
1225          * At the same time we queue the dirty windows in the system class
1226          * and generate events for them at the next processEvents call. */
1227
1228         if (m_invalid_window == false) {
1229                 m_system->addDirtyWindow(this);
1230                 m_invalid_window = true;
1231         }
1232
1233         return GHOST_kSuccess;
1234 }
1235
1236 /**
1237  * called by the X11 system implementation when expose events
1238  * for the window have been pushed onto the GHOST queue
1239  */
1240
1241 void
1242 GHOST_WindowX11::
1243 validate()
1244 {
1245         m_invalid_window = false;
1246 }
1247
1248
1249 /**
1250  * Destructor.
1251  * Closes the window and disposes resources allocated.
1252  */
1253
1254 GHOST_WindowX11::
1255 ~GHOST_WindowX11()
1256 {
1257         std::map<unsigned int, Cursor>::iterator it = m_standard_cursors.begin();
1258         for (; it != m_standard_cursors.end(); ++it) {
1259                 XFreeCursor(m_display, it->second);
1260         }
1261
1262         if (m_empty_cursor) {
1263                 XFreeCursor(m_display, m_empty_cursor);
1264         }
1265         if (m_custom_cursor) {
1266                 XFreeCursor(m_display, m_custom_cursor);
1267         }
1268
1269         if (m_valid_setup) {
1270                 static Atom Primary_atom, Clipboard_atom;
1271                 Window p_owner, c_owner;
1272                 /*Change the owner of the Atoms to None if we are the owner*/
1273                 Primary_atom = XInternAtom(m_display, "PRIMARY", False);
1274                 Clipboard_atom = XInternAtom(m_display, "CLIPBOARD", False);
1275
1276
1277                 p_owner = XGetSelectionOwner(m_display, Primary_atom);
1278                 c_owner = XGetSelectionOwner(m_display, Clipboard_atom);
1279
1280                 if (p_owner == m_window) {
1281                         XSetSelectionOwner(m_display, Primary_atom, None, CurrentTime);
1282                 }
1283                 if (c_owner == m_window) {
1284                         XSetSelectionOwner(m_display, Clipboard_atom, None, CurrentTime);
1285                 }
1286         }
1287
1288         if (m_visualInfo) {
1289                 XFree(m_visualInfo);
1290         }
1291
1292 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
1293         if (m_xic) {
1294                 XDestroyIC(m_xic);
1295         }
1296 #endif
1297
1298 #ifdef WITH_XDND
1299         delete m_dropTarget;
1300 #endif
1301
1302         releaseNativeHandles();
1303
1304         if (m_valid_setup) {
1305                 XDestroyWindow(m_display, m_window);
1306         }
1307 }
1308
1309
1310 GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type)
1311 {
1312         if (type == GHOST_kDrawingContextTypeOpenGL) {
1313 #if !defined(WITH_GL_EGL)
1314
1315 #if defined(WITH_GL_PROFILE_CORE)
1316                 GHOST_Context *context = new GHOST_ContextGLX(
1317                         m_wantStereoVisual,
1318                         m_wantNumOfAASamples,
1319                         m_window,
1320                         m_display,
1321                         m_visualInfo,
1322                         (GLXFBConfig)m_fbconfig,
1323                         GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
1324                         3, 2,
1325                         GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
1326                         GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
1327 #elif defined(WITH_GL_PROFILE_ES20)
1328                 GHOST_Context *context = new GHOST_ContextGLX(
1329                         m_wantStereoVisual,
1330                         m_wantNumOfAASamples,
1331                         m_window,
1332                         m_display,
1333                         m_visualInfo,
1334                         (GLXFBConfig)m_fbconfig,
1335                         GLX_CONTEXT_ES2_PROFILE_BIT_EXT,
1336                         2, 0,
1337                         GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
1338                         GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
1339 #elif defined(WITH_GL_PROFILE_COMPAT)
1340                 GHOST_Context *context = new GHOST_ContextGLX(
1341                         m_wantStereoVisual,
1342                         m_wantNumOfAASamples,
1343                         m_window,
1344                         m_display,
1345                         m_visualInfo,
1346                         (GLXFBConfig)m_fbconfig,
1347                         0, // profile bit
1348                         0, 0,
1349                         GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
1350                         GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
1351 #else
1352 #  error
1353 #endif
1354
1355 #else
1356
1357 #if defined(WITH_GL_PROFILE_CORE)
1358                 GHOST_Context *context = new GHOST_ContextEGL(
1359                         m_wantStereoVisual,
1360                         m_wantNumOfAASamples,
1361                         m_window,
1362                         m_display,
1363                         EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
1364                         3, 2,
1365                         GHOST_OPENGL_EGL_CONTEXT_FLAGS,
1366                         GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
1367                         EGL_OPENGL_API);
1368 #elif defined(WITH_GL_PROFILE_ES20)
1369                 GHOST_Context *context = new GHOST_ContextEGL(
1370                         m_wantStereoVisual,
1371                         m_wantNumOfAASamples,
1372                         m_window,
1373                         m_display,
1374                         0, // profile bit
1375                         2, 0,
1376                         GHOST_OPENGL_EGL_CONTEXT_FLAGS,
1377                         GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
1378                         EGL_OPENGL_ES_API);
1379 #elif defined(WITH_GL_PROFILE_COMPAT)
1380                 GHOST_Context *context = new GHOST_ContextEGL(
1381                         m_wantStereoVisual,
1382                         m_wantNumOfAASamples,
1383                         m_window,
1384                         m_display,
1385                         0, // profile bit
1386                         0, 0,
1387                         GHOST_OPENGL_EGL_CONTEXT_FLAGS,
1388                         GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
1389                         EGL_OPENGL_API);
1390 #else
1391 #  error
1392 #endif
1393
1394 #endif
1395                 if (context->initializeDrawingContext())
1396                         return context;
1397                 else
1398                         delete context;
1399         }
1400
1401         return NULL;
1402 }
1403
1404
1405 Cursor
1406 GHOST_WindowX11::
1407 getStandardCursor(
1408                 GHOST_TStandardCursor g_cursor)
1409 {
1410         unsigned int xcursor_id;
1411
1412 #define GtoX(gcurs, xcurs)  case gcurs: xcursor_id = xcurs
1413         switch (g_cursor) {
1414                 GtoX(GHOST_kStandardCursorRightArrow, XC_arrow); break;
1415                 GtoX(GHOST_kStandardCursorLeftArrow, XC_top_left_arrow); break;
1416                 GtoX(GHOST_kStandardCursorInfo, XC_hand1); break;
1417                 GtoX(GHOST_kStandardCursorDestroy, XC_pirate); break;
1418                 GtoX(GHOST_kStandardCursorHelp, XC_question_arrow); break;
1419                 GtoX(GHOST_kStandardCursorCycle, XC_exchange); break;
1420                 GtoX(GHOST_kStandardCursorSpray, XC_spraycan); break;
1421                 GtoX(GHOST_kStandardCursorWait, XC_watch); break;
1422                 GtoX(GHOST_kStandardCursorText, XC_xterm); break;
1423                 GtoX(GHOST_kStandardCursorCrosshair, XC_crosshair); break;
1424                 GtoX(GHOST_kStandardCursorUpDown, XC_sb_v_double_arrow); break;
1425                 GtoX(GHOST_kStandardCursorLeftRight, XC_sb_h_double_arrow); break;
1426                 GtoX(GHOST_kStandardCursorTopSide, XC_top_side); break;
1427                 GtoX(GHOST_kStandardCursorBottomSide, XC_bottom_side); break;
1428                 GtoX(GHOST_kStandardCursorLeftSide, XC_left_side); break;
1429                 GtoX(GHOST_kStandardCursorRightSide, XC_right_side); break;
1430                 GtoX(GHOST_kStandardCursorTopLeftCorner, XC_top_left_corner); break;
1431                 GtoX(GHOST_kStandardCursorTopRightCorner, XC_top_right_corner); break;
1432                 GtoX(GHOST_kStandardCursorBottomRightCorner, XC_bottom_right_corner); break;
1433                 GtoX(GHOST_kStandardCursorBottomLeftCorner, XC_bottom_left_corner); break;
1434                 GtoX(GHOST_kStandardCursorPencil, XC_pencil); break;
1435                 GtoX(GHOST_kStandardCursorCopy, XC_arrow); break;
1436                 default:
1437                         xcursor_id = 0;
1438         }
1439 #undef GtoX
1440
1441         if (xcursor_id) {
1442                 Cursor xcursor = m_standard_cursors[xcursor_id];
1443
1444                 if (!xcursor) {
1445                         xcursor = XCreateFontCursor(m_display, xcursor_id);
1446
1447                         m_standard_cursors[xcursor_id] = xcursor;
1448                 }
1449
1450                 return xcursor;
1451         }
1452         else {
1453                 return None;
1454         }
1455 }
1456
1457 Cursor
1458 GHOST_WindowX11::
1459 getEmptyCursor(
1460         ) {
1461         if (!m_empty_cursor) {
1462                 Pixmap blank;
1463                 XColor dummy = {0};
1464                 char data[1] = {0};
1465
1466                 /* make a blank cursor */
1467                 blank = XCreateBitmapFromData(
1468                     m_display,
1469                     RootWindow(m_display, m_visualInfo->screen),
1470                     data, 1, 1
1471                     );
1472
1473                 m_empty_cursor = XCreatePixmapCursor(m_display, blank, blank, &dummy, &dummy, 0, 0);
1474                 XFreePixmap(m_display, blank);
1475         }
1476
1477         return m_empty_cursor;
1478 }
1479
1480 GHOST_TSuccess
1481 GHOST_WindowX11::
1482 setWindowCursorVisibility(
1483                 bool visible)
1484 {
1485         Cursor xcursor;
1486
1487         if (visible) {
1488                 if (m_visible_cursor)
1489                         xcursor = m_visible_cursor;
1490                 else
1491                         xcursor = getStandardCursor(getCursorShape() );
1492         }
1493         else {
1494                 xcursor = getEmptyCursor();
1495         }
1496
1497         XDefineCursor(m_display, m_window, xcursor);
1498         XFlush(m_display);
1499
1500         return GHOST_kSuccess;
1501 }
1502
1503 GHOST_TSuccess
1504 GHOST_WindowX11::
1505 setWindowCursorGrab(
1506                 GHOST_TGrabCursorMode mode)
1507 {
1508         if (mode != GHOST_kGrabDisable) {
1509                 if (mode != GHOST_kGrabNormal) {
1510                         m_system->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
1511                         setCursorGrabAccum(0, 0);
1512
1513                         if (mode == GHOST_kGrabHide)
1514                                 setWindowCursorVisibility(false);
1515
1516                 }
1517 #ifdef GHOST_X11_GRAB
1518                 XGrabPointer(m_display, m_window, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
1519                              GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
1520 #endif
1521         }
1522         else {
1523                 if (m_cursorGrab == GHOST_kGrabHide) {
1524                         m_system->setCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
1525                 }
1526
1527                 if (m_cursorGrab != GHOST_kGrabNormal) {
1528                         /* use to generate a mouse move event, otherwise the last event
1529                          * blender gets can be outside the screen causing menus not to show
1530                          * properly unless the user moves the mouse */
1531
1532 #ifdef WITH_X11_XINPUT
1533                         if ((m_system->m_xinput_version.present) &&
1534                             (m_system->m_xinput_version.major_version >= 2))
1535                         {
1536                                 int device_id;
1537                                 if (XIGetClientPointer(m_display, None, &device_id) != False) {
1538                                         XIWarpPointer(m_display, device_id, None, None, 0, 0, 0, 0, 0, 0);
1539                                 }
1540                         }
1541                         else
1542 #endif
1543                         {
1544                                 XWarpPointer(m_display, None, None, 0, 0, 0, 0, 0, 0);
1545                         }
1546                 }
1547
1548                 /* Perform this last so to workaround XWayland bug, see: T53004. */
1549                 if (m_cursorGrab == GHOST_kGrabHide) {
1550                         setWindowCursorVisibility(true);
1551                 }
1552
1553                 /* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
1554                 setCursorGrabAccum(0, 0);
1555                 m_cursorGrabBounds.m_l = m_cursorGrabBounds.m_r = -1; /* disable */
1556 #ifdef GHOST_X11_GRAB
1557                 XUngrabPointer(m_display, CurrentTime);
1558 #endif
1559         }
1560
1561         XFlush(m_display);
1562
1563         return GHOST_kSuccess;
1564 }
1565
1566 GHOST_TSuccess
1567 GHOST_WindowX11::
1568 setWindowCursorShape(
1569                 GHOST_TStandardCursor shape)
1570 {
1571         Cursor xcursor = getStandardCursor(shape);
1572
1573         m_visible_cursor = xcursor;
1574
1575         XDefineCursor(m_display, m_window, xcursor);
1576         XFlush(m_display);
1577
1578         return GHOST_kSuccess;
1579 }
1580
1581 GHOST_TSuccess
1582 GHOST_WindowX11::
1583 setWindowCustomCursorShape(
1584                 GHOST_TUns8 bitmap[16][2],
1585                 GHOST_TUns8 mask[16][2],
1586                 int hotX,
1587                 int hotY)
1588 {
1589         setWindowCustomCursorShape((GHOST_TUns8 *)bitmap, (GHOST_TUns8 *)mask,
1590                                    16, 16, hotX, hotY, 0, 1);
1591         return GHOST_kSuccess;
1592 }
1593
1594 GHOST_TSuccess
1595 GHOST_WindowX11::
1596 setWindowCustomCursorShape(
1597                 GHOST_TUns8 *bitmap,
1598                 GHOST_TUns8 *mask,
1599                 int sizex,
1600                 int sizey,
1601                 int hotX,
1602                 int hotY,
1603                 int /*fg_color*/,
1604                 int /*bg_color*/)
1605 {
1606         Colormap colormap = DefaultColormap(m_display, m_visualInfo->screen);
1607         Pixmap bitmap_pix, mask_pix;
1608         XColor fg, bg;
1609
1610         if (XAllocNamedColor(m_display, colormap, "White", &fg, &fg) == 0) return GHOST_kFailure;
1611         if (XAllocNamedColor(m_display, colormap, "Black", &bg, &bg) == 0) return GHOST_kFailure;
1612
1613         if (m_custom_cursor) {
1614                 XFreeCursor(m_display, m_custom_cursor);
1615         }
1616
1617         bitmap_pix = XCreateBitmapFromData(m_display, m_window, (char *) bitmap, sizex, sizey);
1618         mask_pix = XCreateBitmapFromData(m_display, m_window, (char *) mask, sizex, sizey);
1619
1620         m_custom_cursor = XCreatePixmapCursor(m_display, bitmap_pix, mask_pix, &fg, &bg, hotX, hotY);
1621         XDefineCursor(m_display, m_window, m_custom_cursor);
1622         XFlush(m_display);
1623
1624         m_visible_cursor = m_custom_cursor;
1625
1626         XFreePixmap(m_display, bitmap_pix);
1627         XFreePixmap(m_display, mask_pix);
1628
1629         XFreeColors(m_display, colormap, &fg.pixel, 1, 0L);
1630         XFreeColors(m_display, colormap, &bg.pixel, 1, 0L);
1631
1632         return GHOST_kSuccess;
1633 }
1634
1635
1636 GHOST_TSuccess
1637 GHOST_WindowX11::
1638 beginFullScreen() const
1639 {
1640         {
1641                 Window root_return;
1642                 int x_return, y_return;
1643                 unsigned int w_return, h_return, border_w_return, depth_return;
1644
1645                 XGetGeometry(m_display, m_window, &root_return, &x_return, &y_return,
1646                              &w_return, &h_return, &border_w_return, &depth_return);
1647
1648                 m_system->setCursorPosition(w_return / 2, h_return / 2);
1649         }
1650
1651
1652         /* Grab Keyboard & Mouse */
1653         int err;
1654
1655         err = XGrabKeyboard(m_display, m_window, False,
1656                             GrabModeAsync, GrabModeAsync, CurrentTime);
1657         if (err != GrabSuccess) printf("XGrabKeyboard failed %d\n", err);
1658
1659         err = XGrabPointer(m_display, m_window, False,  PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
1660                            GrabModeAsync, GrabModeAsync, m_window, None, CurrentTime);
1661         if (err != GrabSuccess) printf("XGrabPointer failed %d\n", err);
1662
1663         return GHOST_kSuccess;
1664 }
1665
1666 GHOST_TSuccess
1667 GHOST_WindowX11::
1668 endFullScreen() const
1669 {
1670         XUngrabKeyboard(m_display, CurrentTime);
1671         XUngrabPointer(m_display, CurrentTime);
1672
1673         return GHOST_kSuccess;
1674 }
1675
1676 GHOST_TUns16
1677 GHOST_WindowX11::
1678 getDPIHint()
1679 {
1680         /* Try to read DPI setting set using xrdb */
1681         char* resMan = XResourceManagerString(m_display);
1682         if (resMan) {
1683                 XrmDatabase xrdb = XrmGetStringDatabase(resMan);
1684                 if (xrdb) {
1685                         char* type = NULL;
1686                         XrmValue val;
1687
1688                         int success = XrmGetResource(xrdb, "Xft.dpi", "Xft.Dpi", &type, &val);
1689                         if (success && type) {
1690                                 if (strcmp(type, "String") == 0) {
1691                                         return atoi((char*)val.addr);
1692                                 }
1693                         }
1694                 }
1695                 XrmDestroyDatabase(xrdb);
1696         }
1697
1698         /* Fallback to calculating DPI using X reported DPI, set using xrandr --dpi */
1699         XWindowAttributes attr;
1700         if (!XGetWindowAttributes(m_display, m_window, &attr)) {
1701                 /* Failed to get window attributes, return X11 default DPI */
1702                 return 96;
1703         }
1704
1705         Screen* screen = attr.screen;
1706         int pixelWidth = WidthOfScreen(screen);
1707         int pixelHeight = HeightOfScreen(screen);
1708         int mmWidth = WidthMMOfScreen(screen);
1709         int mmHeight = HeightMMOfScreen(screen);
1710
1711         double pixelDiagonal = sqrt((pixelWidth * pixelWidth) + (pixelHeight * pixelHeight));
1712         double mmDiagonal = sqrt((mmWidth * mmWidth) + (mmHeight * mmHeight));
1713         float inchDiagonal = mmDiagonal * 0.039f;
1714         int dpi = pixelDiagonal / inchDiagonal;
1715         return dpi;
1716 }
1717
1718 GHOST_TSuccess GHOST_WindowX11::setProgressBar(float progress)
1719 {
1720         if (m_taskbar.is_valid()) {
1721                 m_taskbar.set_progress(progress);
1722                 m_taskbar.set_progress_enabled(true);
1723                 return GHOST_kSuccess;
1724         }
1725
1726         return GHOST_kFailure;
1727 }
1728
1729 GHOST_TSuccess GHOST_WindowX11::endProgressBar()
1730 {
1731         if (m_taskbar.is_valid()) {
1732                 m_taskbar.set_progress_enabled(false);
1733                 return GHOST_kSuccess;
1734         }
1735
1736         return GHOST_kFailure;
1737 }