Merge branch 'blender2.7'
[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
1314                 // During development:
1315                 //   try 4.x compatibility profile
1316                 //   try 3.3 compatibility profile
1317                 //   fall back to 3.0 if needed
1318                 //
1319                 // Final Blender 2.8:
1320                 //   try 4.x core profile
1321                 //   try 3.3 core profile
1322                 //   no fallbacks
1323
1324 #if defined(WITH_GL_PROFILE_CORE)
1325                 {
1326                         const char *version_major = (char*)glewGetString(GLEW_VERSION_MAJOR);
1327                         if (version_major != NULL && version_major[0] == '1') {
1328                                 fprintf(stderr, "Error: GLEW version 2.0 and above is required.\n");
1329                                 abort();
1330                         }
1331                 }
1332 #endif
1333
1334                 const int profile_mask =
1335 #if defined(WITH_GL_PROFILE_CORE)
1336                         GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
1337 #elif defined(WITH_GL_PROFILE_COMPAT)
1338                         GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
1339 #else
1340 #  error // must specify either core or compat at build time
1341 #endif
1342
1343                 GHOST_Context *context;
1344
1345                 for (int minor = 5; minor >= 0; --minor) {
1346                         context = new GHOST_ContextGLX(
1347                                 m_wantStereoVisual,
1348                                 m_wantNumOfAASamples,
1349                                 m_window,
1350                                 m_display,
1351                                 (GLXFBConfig)m_fbconfig,
1352                                 profile_mask,
1353                                 4, minor,
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                 context = new GHOST_ContextGLX(
1364                         m_wantStereoVisual,
1365                         m_wantNumOfAASamples,
1366                         m_window,
1367                         m_display,
1368                         (GLXFBConfig)m_fbconfig,
1369                         profile_mask,
1370                         3, 3,
1371                         GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
1372                         GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
1373
1374                 if (context->initializeDrawingContext())
1375                         return context;
1376                 else
1377                         delete context;
1378
1379         }
1380
1381         return NULL;
1382 }
1383
1384
1385 Cursor
1386 GHOST_WindowX11::
1387 getStandardCursor(
1388                 GHOST_TStandardCursor g_cursor)
1389 {
1390         unsigned int xcursor_id;
1391
1392 #define GtoX(gcurs, xcurs)  case gcurs: xcursor_id = xcurs
1393         switch (g_cursor) {
1394                 GtoX(GHOST_kStandardCursorRightArrow, XC_arrow); break;
1395                 GtoX(GHOST_kStandardCursorLeftArrow, XC_top_left_arrow); break;
1396                 GtoX(GHOST_kStandardCursorInfo, XC_hand1); break;
1397                 GtoX(GHOST_kStandardCursorDestroy, XC_pirate); break;
1398                 GtoX(GHOST_kStandardCursorHelp, XC_question_arrow); break;
1399                 GtoX(GHOST_kStandardCursorCycle, XC_exchange); break;
1400                 GtoX(GHOST_kStandardCursorSpray, XC_spraycan); break;
1401                 GtoX(GHOST_kStandardCursorWait, XC_watch); break;
1402                 GtoX(GHOST_kStandardCursorText, XC_xterm); break;
1403                 GtoX(GHOST_kStandardCursorCrosshair, XC_crosshair); break;
1404                 GtoX(GHOST_kStandardCursorUpDown, XC_sb_v_double_arrow); break;
1405                 GtoX(GHOST_kStandardCursorLeftRight, XC_sb_h_double_arrow); break;
1406                 GtoX(GHOST_kStandardCursorTopSide, XC_top_side); break;
1407                 GtoX(GHOST_kStandardCursorBottomSide, XC_bottom_side); break;
1408                 GtoX(GHOST_kStandardCursorLeftSide, XC_left_side); break;
1409                 GtoX(GHOST_kStandardCursorRightSide, XC_right_side); break;
1410                 GtoX(GHOST_kStandardCursorTopLeftCorner, XC_top_left_corner); break;
1411                 GtoX(GHOST_kStandardCursorTopRightCorner, XC_top_right_corner); break;
1412                 GtoX(GHOST_kStandardCursorBottomRightCorner, XC_bottom_right_corner); break;
1413                 GtoX(GHOST_kStandardCursorBottomLeftCorner, XC_bottom_left_corner); break;
1414                 GtoX(GHOST_kStandardCursorPencil, XC_pencil); break;
1415                 GtoX(GHOST_kStandardCursorCopy, XC_arrow); break;
1416                 default:
1417                         xcursor_id = 0;
1418         }
1419 #undef GtoX
1420
1421         if (xcursor_id) {
1422                 Cursor xcursor = m_standard_cursors[xcursor_id];
1423
1424                 if (!xcursor) {
1425                         xcursor = XCreateFontCursor(m_display, xcursor_id);
1426
1427                         m_standard_cursors[xcursor_id] = xcursor;
1428                 }
1429
1430                 return xcursor;
1431         }
1432         else {
1433                 return None;
1434         }
1435 }
1436
1437 Cursor
1438 GHOST_WindowX11::
1439 getEmptyCursor(
1440         ) {
1441         if (!m_empty_cursor) {
1442                 Pixmap blank;
1443                 XColor dummy = {0};
1444                 char data[1] = {0};
1445
1446                 /* make a blank cursor */
1447                 blank = XCreateBitmapFromData(
1448                     m_display,
1449                     RootWindow(m_display, m_visualInfo->screen),
1450                     data, 1, 1
1451                     );
1452
1453                 m_empty_cursor = XCreatePixmapCursor(m_display, blank, blank, &dummy, &dummy, 0, 0);
1454                 XFreePixmap(m_display, blank);
1455         }
1456
1457         return m_empty_cursor;
1458 }
1459
1460 GHOST_TSuccess
1461 GHOST_WindowX11::
1462 setWindowCursorVisibility(
1463                 bool visible)
1464 {
1465         Cursor xcursor;
1466
1467         if (visible) {
1468                 if (m_visible_cursor)
1469                         xcursor = m_visible_cursor;
1470                 else
1471                         xcursor = getStandardCursor(getCursorShape() );
1472         }
1473         else {
1474                 xcursor = getEmptyCursor();
1475         }
1476
1477         XDefineCursor(m_display, m_window, xcursor);
1478         XFlush(m_display);
1479
1480         return GHOST_kSuccess;
1481 }
1482
1483 GHOST_TSuccess
1484 GHOST_WindowX11::
1485 setWindowCursorGrab(
1486                 GHOST_TGrabCursorMode mode)
1487 {
1488         if (mode != GHOST_kGrabDisable) {
1489                 if (mode != GHOST_kGrabNormal) {
1490                         m_system->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
1491                         setCursorGrabAccum(0, 0);
1492
1493                         if (mode == GHOST_kGrabHide)
1494                                 setWindowCursorVisibility(false);
1495
1496                 }
1497 #ifdef GHOST_X11_GRAB
1498                 XGrabPointer(m_display, m_window, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
1499                              GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
1500 #endif
1501         }
1502         else {
1503                 if (m_cursorGrab == GHOST_kGrabHide) {
1504                         m_system->setCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
1505                 }
1506
1507                 if (m_cursorGrab != GHOST_kGrabNormal) {
1508                         /* use to generate a mouse move event, otherwise the last event
1509                          * blender gets can be outside the screen causing menus not to show
1510                          * properly unless the user moves the mouse */
1511
1512 #ifdef WITH_X11_XINPUT
1513                         if ((m_system->m_xinput_version.present) &&
1514                             (m_system->m_xinput_version.major_version >= 2))
1515                         {
1516                                 int device_id;
1517                                 if (XIGetClientPointer(m_display, None, &device_id) != False) {
1518                                         XIWarpPointer(m_display, device_id, None, None, 0, 0, 0, 0, 0, 0);
1519                                 }
1520                         }
1521                         else
1522 #endif
1523                         {
1524                                 XWarpPointer(m_display, None, None, 0, 0, 0, 0, 0, 0);
1525                         }
1526                 }
1527
1528                 /* Perform this last so to workaround XWayland bug, see: T53004. */
1529                 if (m_cursorGrab == GHOST_kGrabHide) {
1530                         setWindowCursorVisibility(true);
1531                 }
1532
1533                 /* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
1534                 setCursorGrabAccum(0, 0);
1535                 m_cursorGrabBounds.m_l = m_cursorGrabBounds.m_r = -1; /* disable */
1536 #ifdef GHOST_X11_GRAB
1537                 XUngrabPointer(m_display, CurrentTime);
1538 #endif
1539         }
1540
1541         XFlush(m_display);
1542
1543         return GHOST_kSuccess;
1544 }
1545
1546 GHOST_TSuccess
1547 GHOST_WindowX11::
1548 setWindowCursorShape(
1549                 GHOST_TStandardCursor shape)
1550 {
1551         Cursor xcursor = getStandardCursor(shape);
1552
1553         m_visible_cursor = xcursor;
1554
1555         XDefineCursor(m_display, m_window, xcursor);
1556         XFlush(m_display);
1557
1558         return GHOST_kSuccess;
1559 }
1560
1561 GHOST_TSuccess
1562 GHOST_WindowX11::
1563 setWindowCustomCursorShape(
1564                 GHOST_TUns8 bitmap[16][2],
1565                 GHOST_TUns8 mask[16][2],
1566                 int hotX,
1567                 int hotY)
1568 {
1569         setWindowCustomCursorShape((GHOST_TUns8 *)bitmap, (GHOST_TUns8 *)mask,
1570                                    16, 16, hotX, hotY, 0, 1);
1571         return GHOST_kSuccess;
1572 }
1573
1574 GHOST_TSuccess
1575 GHOST_WindowX11::
1576 setWindowCustomCursorShape(
1577                 GHOST_TUns8 *bitmap,
1578                 GHOST_TUns8 *mask,
1579                 int sizex,
1580                 int sizey,
1581                 int hotX,
1582                 int hotY,
1583                 int /*fg_color*/,
1584                 int /*bg_color*/)
1585 {
1586         Colormap colormap = DefaultColormap(m_display, m_visualInfo->screen);
1587         Pixmap bitmap_pix, mask_pix;
1588         XColor fg, bg;
1589
1590         if (XAllocNamedColor(m_display, colormap, "White", &fg, &fg) == 0) return GHOST_kFailure;
1591         if (XAllocNamedColor(m_display, colormap, "Black", &bg, &bg) == 0) return GHOST_kFailure;
1592
1593         if (m_custom_cursor) {
1594                 XFreeCursor(m_display, m_custom_cursor);
1595         }
1596
1597         bitmap_pix = XCreateBitmapFromData(m_display, m_window, (char *) bitmap, sizex, sizey);
1598         mask_pix = XCreateBitmapFromData(m_display, m_window, (char *) mask, sizex, sizey);
1599
1600         m_custom_cursor = XCreatePixmapCursor(m_display, bitmap_pix, mask_pix, &fg, &bg, hotX, hotY);
1601         XDefineCursor(m_display, m_window, m_custom_cursor);
1602         XFlush(m_display);
1603
1604         m_visible_cursor = m_custom_cursor;
1605
1606         XFreePixmap(m_display, bitmap_pix);
1607         XFreePixmap(m_display, mask_pix);
1608
1609         XFreeColors(m_display, colormap, &fg.pixel, 1, 0L);
1610         XFreeColors(m_display, colormap, &bg.pixel, 1, 0L);
1611
1612         return GHOST_kSuccess;
1613 }
1614
1615
1616 GHOST_TSuccess
1617 GHOST_WindowX11::
1618 beginFullScreen() const
1619 {
1620         {
1621                 Window root_return;
1622                 int x_return, y_return;
1623                 unsigned int w_return, h_return, border_w_return, depth_return;
1624
1625                 XGetGeometry(m_display, m_window, &root_return, &x_return, &y_return,
1626                              &w_return, &h_return, &border_w_return, &depth_return);
1627
1628                 m_system->setCursorPosition(w_return / 2, h_return / 2);
1629         }
1630
1631
1632         /* Grab Keyboard & Mouse */
1633         int err;
1634
1635         err = XGrabKeyboard(m_display, m_window, False,
1636                             GrabModeAsync, GrabModeAsync, CurrentTime);
1637         if (err != GrabSuccess) printf("XGrabKeyboard failed %d\n", err);
1638
1639         err = XGrabPointer(m_display, m_window, False,  PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
1640                            GrabModeAsync, GrabModeAsync, m_window, None, CurrentTime);
1641         if (err != GrabSuccess) printf("XGrabPointer failed %d\n", err);
1642
1643         return GHOST_kSuccess;
1644 }
1645
1646 GHOST_TSuccess
1647 GHOST_WindowX11::
1648 endFullScreen() const
1649 {
1650         XUngrabKeyboard(m_display, CurrentTime);
1651         XUngrabPointer(m_display, CurrentTime);
1652
1653         return GHOST_kSuccess;
1654 }
1655
1656 GHOST_TUns16
1657 GHOST_WindowX11::
1658 getDPIHint()
1659 {
1660         /* Try to read DPI setting set using xrdb */
1661         char* resMan = XResourceManagerString(m_display);
1662         if (resMan) {
1663                 XrmDatabase xrdb = XrmGetStringDatabase(resMan);
1664                 if (xrdb) {
1665                         char* type = NULL;
1666                         XrmValue val;
1667
1668                         int success = XrmGetResource(xrdb, "Xft.dpi", "Xft.Dpi", &type, &val);
1669                         if (success && type) {
1670                                 if (strcmp(type, "String") == 0) {
1671                                         return atoi((char*)val.addr);
1672                                 }
1673                         }
1674                 }
1675                 XrmDestroyDatabase(xrdb);
1676         }
1677
1678         /* Fallback to calculating DPI using X reported DPI, set using xrandr --dpi */
1679         XWindowAttributes attr;
1680         if (!XGetWindowAttributes(m_display, m_window, &attr)) {
1681                 /* Failed to get window attributes, return X11 default DPI */
1682                 return 96;
1683         }
1684
1685         Screen* screen = attr.screen;
1686         int pixelWidth = WidthOfScreen(screen);
1687         int pixelHeight = HeightOfScreen(screen);
1688         int mmWidth = WidthMMOfScreen(screen);
1689         int mmHeight = HeightMMOfScreen(screen);
1690
1691         double pixelDiagonal = sqrt((pixelWidth * pixelWidth) + (pixelHeight * pixelHeight));
1692         double mmDiagonal = sqrt((mmWidth * mmWidth) + (mmHeight * mmHeight));
1693         float inchDiagonal = mmDiagonal * 0.039f;
1694         int dpi = pixelDiagonal / inchDiagonal;
1695         return dpi;
1696 }
1697
1698 GHOST_TSuccess GHOST_WindowX11::setProgressBar(float progress)
1699 {
1700         if (m_taskbar.is_valid()) {
1701                 m_taskbar.set_progress(progress);
1702                 m_taskbar.set_progress_enabled(true);
1703                 return GHOST_kSuccess;
1704         }
1705
1706         return GHOST_kFailure;
1707 }
1708
1709 GHOST_TSuccess GHOST_WindowX11::endProgressBar()
1710 {
1711         if (m_taskbar.is_valid()) {
1712                 m_taskbar.set_progress_enabled(false);
1713                 return GHOST_kSuccess;
1714         }
1715
1716         return GHOST_kFailure;
1717 }