Merge branch 'master' into blender2.8
[blender.git] / intern / ghost / intern / GHOST_WindowX11.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file ghost/intern/GHOST_WindowX11.cpp
29  *  \ingroup GHOST
30  */
31
32 /* For standard X11 cursors */
33 #include <X11/cursorfont.h>
34 #include <X11/Xatom.h>
35 #include <X11/Xutil.h>
36 #ifdef WITH_X11_ALPHA
37 #include <X11/extensions/Xrender.h>
38 #endif
39 #include "GHOST_WindowX11.h"
40 #include "GHOST_SystemX11.h"
41 #include "STR_String.h"
42 #include "GHOST_Debug.h"
43
44 #ifdef WITH_XDND
45 #  include "GHOST_DropTargetX11.h"
46 #endif
47
48 #if defined(WITH_GL_EGL)
49 #  include "GHOST_ContextEGL.h"
50 #else
51 #  include "GHOST_ContextGLX.h"
52 #endif
53
54 /* for XIWarpPointer */
55 #ifdef WITH_X11_XINPUT
56 #  include <X11/extensions/XInput2.h>
57 #endif
58
59 //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) {
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 = True;
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) {
590                 XMapRaised(m_display, m_window);
591         }
592         else {
593                 XMapWindow(m_display, m_window);
594         }
595         GHOST_PRINT("Mapped window\n");
596
597         XFlush(m_display);
598 }
599
600 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
601 static void destroyICCallback(XIC /*xic*/, XPointer ptr, XPointer /*data*/)
602 {
603         GHOST_PRINT("XIM input context destroyed\n");
604
605         if (ptr) {
606                 *(XIC *)ptr = NULL;
607         }
608 }
609
610 bool GHOST_WindowX11::createX11_XIC()
611 {
612         XIM xim = m_system->getX11_XIM();
613         if (!xim)
614                 return false;
615
616         XICCallback destroy;
617         destroy.callback = (XICProc)destroyICCallback;
618         destroy.client_data = (XPointer)&m_xic;
619         m_xic = XCreateIC(xim, XNClientWindow, m_window, XNFocusWindow, m_window,
620                           XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
621                           XNResourceName, GHOST_X11_RES_NAME,
622                           XNResourceClass, GHOST_X11_RES_CLASS,
623                           XNDestroyCallback, &destroy,
624                           NULL);
625         if (!m_xic)
626                 return false;
627
628         unsigned long fevent;
629         XGetICValues(m_xic, XNFilterEvents, &fevent, NULL);
630         XSelectInput(m_display, m_window,
631                      ExposureMask | StructureNotifyMask |
632                      KeyPressMask | KeyReleaseMask |
633                      EnterWindowMask | LeaveWindowMask |
634                      ButtonPressMask | ButtonReleaseMask |
635                      PointerMotionMask | FocusChangeMask |
636                      PropertyChangeMask | KeymapStateMask | fevent);
637         return true;
638 }
639 #endif
640
641 #ifdef WITH_X11_XINPUT
642 void GHOST_WindowX11::refreshXInputDevices()
643 {
644         if (m_system->m_xinput_version.present) {
645                 GHOST_SystemX11::GHOST_TabletX11 &xtablet = m_system->GetXTablet();
646                 XEventClass xevents[8], ev;
647                 int dcount = 0;
648
649                 /* With modern XInput (xlib 1.6.2 at least and/or evdev 2.9.0) and some 'no-name' tablets
650                  * like 'UC-LOGIC Tablet WP5540U', we also need to 'select' ButtonPress for motion event,
651                  * otherwise we do not get any tablet motion event once pen is pressed... See T43367.
652                  */
653
654                 if (xtablet.StylusDevice) {
655                         DeviceMotionNotify(xtablet.StylusDevice, xtablet.MotionEvent, ev);
656                         if (ev) xevents[dcount++] = ev;
657                         DeviceButtonPress(xtablet.StylusDevice, xtablet.PressEvent, ev);
658                         if (ev) xevents[dcount++] = ev;
659                         ProximityIn(xtablet.StylusDevice, xtablet.ProxInEvent, ev);
660                         if (ev) xevents[dcount++] = ev;
661                         ProximityOut(xtablet.StylusDevice, xtablet.ProxOutEvent, ev);
662                         if (ev) xevents[dcount++] = ev;
663                 }
664                 if (xtablet.EraserDevice) {
665                         DeviceMotionNotify(xtablet.EraserDevice, xtablet.MotionEventEraser, ev);
666                         if (ev) xevents[dcount++] = ev;
667                         DeviceButtonPress(xtablet.EraserDevice, xtablet.PressEventEraser, ev);
668                         if (ev) xevents[dcount++] = ev;
669                         ProximityIn(xtablet.EraserDevice, xtablet.ProxInEventEraser, ev);
670                         if (ev) xevents[dcount++] = ev;
671                         ProximityOut(xtablet.EraserDevice, xtablet.ProxOutEventEraser, ev);
672                         if (ev) xevents[dcount++] = ev;
673                 }
674
675                 XSelectExtensionEvent(m_display, m_window, xevents, dcount);
676         }
677 }
678
679 #endif /* WITH_X11_XINPUT */
680
681 Window
682 GHOST_WindowX11::
683 getXWindow()
684 {
685         return m_window;
686 }
687
688 bool
689 GHOST_WindowX11::
690 getValid() const
691 {
692         return GHOST_Window::getValid() && m_valid_setup;
693 }
694
695 void
696 GHOST_WindowX11::
697 setTitle(
698                 const STR_String& title)
699 {
700         Atom name = XInternAtom(m_display, "_NET_WM_NAME", 0);
701         Atom utf8str = XInternAtom(m_display, "UTF8_STRING", 0);
702         XChangeProperty(m_display, m_window,
703                         name, utf8str, 8, PropModeReplace,
704                         (const unsigned char *) title.ReadPtr(),
705                         title.Length());
706
707         /* This should convert to valid x11 string
708          * and getTitle would need matching change */
709         XStoreName(m_display, m_window, title);
710
711         XFlush(m_display);
712 }
713
714 void
715 GHOST_WindowX11::
716 getTitle(
717                 STR_String& title) const
718 {
719         char *name = NULL;
720
721         XFetchName(m_display, m_window, &name);
722         title = name ? name : "untitled";
723         XFree(name);
724 }
725
726 void
727 GHOST_WindowX11::
728 getWindowBounds(
729                 GHOST_Rect& bounds) const
730 {
731         /* Getting the window bounds under X11 is not
732          * really supported (nor should it be desired). */
733         getClientBounds(bounds);
734 }
735
736 void
737 GHOST_WindowX11::
738 getClientBounds(
739                 GHOST_Rect& bounds) const
740 {
741         Window root_return;
742         int x_return, y_return;
743         unsigned int w_return, h_return, border_w_return, depth_return;
744         GHOST_TInt32 screen_x, screen_y;
745
746         XGetGeometry(m_display, m_window, &root_return, &x_return, &y_return,
747                      &w_return, &h_return, &border_w_return, &depth_return);
748
749         clientToScreen(0, 0, screen_x, screen_y);
750
751         bounds.m_l = screen_x;
752         bounds.m_r = bounds.m_l + w_return;
753         bounds.m_t = screen_y;
754         bounds.m_b = bounds.m_t + h_return;
755
756 }
757
758 GHOST_TSuccess
759 GHOST_WindowX11::
760 setClientWidth(
761                 GHOST_TUns32 width)
762 {
763         XWindowChanges values;
764         unsigned int value_mask = CWWidth;
765         values.width = width;
766         XConfigureWindow(m_display, m_window, value_mask, &values);
767
768         return GHOST_kSuccess;
769 }
770
771 GHOST_TSuccess
772 GHOST_WindowX11::
773 setClientHeight(
774                 GHOST_TUns32 height)
775 {
776         XWindowChanges values;
777         unsigned int value_mask = CWHeight;
778         values.height = height;
779         XConfigureWindow(m_display, m_window, value_mask, &values);
780         return GHOST_kSuccess;
781
782 }
783
784 GHOST_TSuccess
785 GHOST_WindowX11::
786 setClientSize(
787                 GHOST_TUns32 width,
788                 GHOST_TUns32 height)
789 {
790         XWindowChanges values;
791         unsigned int value_mask = CWWidth | CWHeight;
792         values.width = width;
793         values.height = height;
794         XConfigureWindow(m_display, m_window, value_mask, &values);
795         return GHOST_kSuccess;
796
797 }
798
799 void
800 GHOST_WindowX11::
801 screenToClient(
802                 GHOST_TInt32 inX,
803                 GHOST_TInt32 inY,
804                 GHOST_TInt32& outX,
805                 GHOST_TInt32& outY) const
806 {
807         /* This is correct! */
808
809         int ax, ay;
810         Window temp;
811
812         XTranslateCoordinates(m_display,
813                               RootWindow(m_display, m_visualInfo->screen),
814                               m_window,
815                               inX, inY,
816                               &ax, &ay,
817                               &temp);
818         outX = ax;
819         outY = ay;
820 }
821
822 void
823 GHOST_WindowX11::
824 clientToScreen(
825                 GHOST_TInt32 inX,
826                 GHOST_TInt32 inY,
827                 GHOST_TInt32& outX,
828                 GHOST_TInt32& outY) const
829 {
830         int ax, ay;
831         Window temp;
832
833         XTranslateCoordinates(
834             m_display,
835             m_window,
836             RootWindow(m_display, m_visualInfo->screen),
837             inX, inY,
838             &ax, &ay,
839             &temp);
840         outX = ax;
841         outY = ay;
842 }
843
844 void GHOST_WindowX11::icccmSetState(int state)
845 {
846         XEvent xev;
847
848         if (state != IconicState)
849                 return;
850
851         xev.xclient.type = ClientMessage;
852         xev.xclient.serial = 0;
853         xev.xclient.send_event = True;
854         xev.xclient.display = m_display;
855         xev.xclient.window = m_window;
856         xev.xclient.format = 32;
857         xev.xclient.message_type = m_system->m_atom.WM_CHANGE_STATE;
858         xev.xclient.data.l[0] = state;
859         XSendEvent(m_display, RootWindow(m_display, m_visualInfo->screen),
860                    False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
861 }
862
863 int GHOST_WindowX11::icccmGetState(void) const
864 {
865         struct {
866                 CARD32 state;
867                 XID    icon;
868         } *prop_ret;
869         unsigned long bytes_after, num_ret;
870         Atom type_ret;
871         int ret, format_ret;
872         CARD32 st;
873
874         prop_ret = NULL;
875         ret = XGetWindowProperty(
876                 m_display, m_window, m_system->m_atom.WM_STATE, 0, 2,
877                 False, m_system->m_atom.WM_STATE, &type_ret,
878                 &format_ret, &num_ret, &bytes_after, ((unsigned char **)&prop_ret));
879         if ((ret == Success) && (prop_ret != NULL) && (num_ret == 2)) {
880                 st = prop_ret->state;
881         }
882         else {
883                 st = NormalState;
884         }
885
886         if (prop_ret) {
887                 XFree(prop_ret);
888         }
889
890         return st;
891 }
892
893 void GHOST_WindowX11::netwmMaximized(bool set)
894 {
895         XEvent xev;
896
897         xev.xclient.type = ClientMessage;
898         xev.xclient.serial = 0;
899         xev.xclient.send_event = True;
900         xev.xclient.window = m_window;
901         xev.xclient.message_type = m_system->m_atom._NET_WM_STATE;
902         xev.xclient.format = 32;
903
904         if (set == True)
905                 xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
906         else
907                 xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
908
909         xev.xclient.data.l[1] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_HORZ;
910         xev.xclient.data.l[2] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT;
911         xev.xclient.data.l[3] = 0;
912         xev.xclient.data.l[4] = 0;
913         XSendEvent(m_display, RootWindow(m_display, m_visualInfo->screen),
914                    False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
915 }
916
917 bool GHOST_WindowX11::netwmIsMaximized(void) const
918 {
919         Atom *prop_ret;
920         unsigned long bytes_after, num_ret, i;
921         Atom type_ret;
922         bool st;
923         int format_ret, ret, count;
924
925         prop_ret = NULL;
926         st = False;
927         ret = XGetWindowProperty(
928                 m_display, m_window, m_system->m_atom._NET_WM_STATE, 0, INT_MAX,
929                 False, XA_ATOM, &type_ret, &format_ret,
930                 &num_ret, &bytes_after, (unsigned char **)&prop_ret);
931         if ((ret == Success) && (prop_ret) && (format_ret == 32)) {
932                 count = 0;
933                 for (i = 0; i < num_ret; i++) {
934                         if (prop_ret[i] == m_system->m_atom._NET_WM_STATE_MAXIMIZED_HORZ) {
935                                 count++;
936                         }
937                         if (prop_ret[i] == m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT) {
938                                 count++;
939                         }
940                         if (count == 2) {
941                                 st = True;
942                                 break;
943                         }
944                 }
945         }
946
947         if (prop_ret)
948                 XFree(prop_ret);
949         return (st);
950 }
951
952 void GHOST_WindowX11::netwmFullScreen(bool set)
953 {
954         XEvent xev;
955
956         xev.xclient.type = ClientMessage;
957         xev.xclient.serial = 0;
958         xev.xclient.send_event = True;
959         xev.xclient.window = m_window;
960         xev.xclient.message_type = m_system->m_atom._NET_WM_STATE;
961         xev.xclient.format = 32;
962
963         if (set == True)
964                 xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
965         else
966                 xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
967
968         xev.xclient.data.l[1] = m_system->m_atom._NET_WM_STATE_FULLSCREEN;
969         xev.xclient.data.l[2] = 0;
970         xev.xclient.data.l[3] = 0;
971         xev.xclient.data.l[4] = 0;
972         XSendEvent(m_display, RootWindow(m_display, m_visualInfo->screen),
973                    False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
974 }
975
976 bool GHOST_WindowX11::netwmIsFullScreen(void) const
977 {
978         Atom *prop_ret;
979         unsigned long bytes_after, num_ret, i;
980         Atom type_ret;
981         bool st;
982         int format_ret, ret;
983
984         prop_ret = NULL;
985         st = False;
986         ret = XGetWindowProperty(
987                 m_display, m_window, m_system->m_atom._NET_WM_STATE, 0, INT_MAX,
988                 False, XA_ATOM, &type_ret, &format_ret,
989                 &num_ret, &bytes_after, (unsigned char **)&prop_ret);
990         if ((ret == Success) && (prop_ret) && (format_ret == 32)) {
991                 for (i = 0; i < num_ret; i++) {
992                         if (prop_ret[i] == m_system->m_atom._NET_WM_STATE_FULLSCREEN) {
993                                 st = True;
994                                 break;
995                         }
996                 }
997         }
998
999         if (prop_ret)
1000                 XFree(prop_ret);
1001         return (st);
1002 }
1003
1004 void GHOST_WindowX11::motifFullScreen(bool set)
1005 {
1006         MotifWmHints hints;
1007
1008         hints.flags = MWM_HINTS_DECORATIONS;
1009         if (set == True)
1010                 hints.decorations = 0;
1011         else
1012                 hints.decorations = 1;
1013
1014         XChangeProperty(m_display, m_window, m_system->m_atom._MOTIF_WM_HINTS,
1015                         m_system->m_atom._MOTIF_WM_HINTS, 32, PropModeReplace,
1016                         (unsigned char *) &hints, 4);
1017 }
1018
1019 bool GHOST_WindowX11::motifIsFullScreen(void) const
1020 {
1021         MotifWmHints *prop_ret;
1022         unsigned long bytes_after, num_ret;
1023         Atom type_ret;
1024         bool state;
1025         int format_ret, st;
1026
1027         prop_ret = NULL;
1028         state = False;
1029         st = XGetWindowProperty(
1030                 m_display, m_window, m_system->m_atom._MOTIF_WM_HINTS, 0, INT_MAX,
1031                 False, m_system->m_atom._MOTIF_WM_HINTS,
1032                 &type_ret, &format_ret, &num_ret,
1033                 &bytes_after, (unsigned char **)&prop_ret);
1034         if ((st == Success) && prop_ret) {
1035                 if (prop_ret->flags & MWM_HINTS_DECORATIONS) {
1036                         if (!prop_ret->decorations)
1037                                 state = True;
1038                 }
1039         }
1040
1041         if (prop_ret)
1042                 XFree(prop_ret);
1043         return (state);
1044 }
1045
1046 GHOST_TWindowState GHOST_WindowX11::getState() const
1047 {
1048         GHOST_TWindowState state_ret;
1049         int state;
1050
1051         state_ret = GHOST_kWindowStateNormal;
1052         state = icccmGetState();
1053         /*
1054          * In the Iconic and Withdrawn state, the window
1055          * is unmaped, so only need return a Minimized state.
1056          */
1057         if ((state == IconicState) || (state == WithdrawnState))
1058                 state_ret = GHOST_kWindowStateMinimized;
1059         else if (netwmIsFullScreen() == True)
1060                 state_ret = GHOST_kWindowStateFullScreen;
1061         else if (motifIsFullScreen() == True)
1062                 state_ret = GHOST_kWindowStateFullScreen;
1063         else if (netwmIsMaximized() == True)
1064                 state_ret = GHOST_kWindowStateMaximized;
1065         return (state_ret);
1066 }
1067
1068 GHOST_TSuccess GHOST_WindowX11::setState(GHOST_TWindowState state)
1069 {
1070         GHOST_TWindowState cur_state;
1071         bool is_max, is_full, is_motif_full;
1072
1073         cur_state = getState();
1074         if (state == (int)cur_state)
1075                 return GHOST_kSuccess;
1076
1077         if (cur_state != GHOST_kWindowStateMinimized) {
1078                 /*
1079                  * The window don't have this property's
1080                  * if it's not mapped.
1081                  */
1082                 is_max = netwmIsMaximized();
1083                 is_full = netwmIsFullScreen();
1084         }
1085         else {
1086                 is_max = False;
1087                 is_full = False;
1088         }
1089
1090         is_motif_full = motifIsFullScreen();
1091
1092         if (state == GHOST_kWindowStateNormal)
1093                 state = m_normal_state;
1094
1095         if (state == GHOST_kWindowStateNormal) {
1096                 if (is_max == True)
1097                         netwmMaximized(False);
1098                 if (is_full == True)
1099                         netwmFullScreen(False);
1100                 if (is_motif_full == True)
1101                         motifFullScreen(False);
1102                 icccmSetState(NormalState);
1103                 return (GHOST_kSuccess);
1104         }
1105
1106         if (state == GHOST_kWindowStateFullScreen) {
1107                 /*
1108                  * We can't change to full screen if the window
1109                  * isn't mapped.
1110                  */
1111                 if (cur_state == GHOST_kWindowStateMinimized)
1112                         return (GHOST_kFailure);
1113
1114                 m_normal_state = cur_state;
1115
1116                 if (is_max == True)
1117                         netwmMaximized(False);
1118                 if (is_full == False)
1119                         netwmFullScreen(True);
1120                 if (is_motif_full == False)
1121                         motifFullScreen(True);
1122                 return (GHOST_kSuccess);
1123         }
1124
1125         if (state == GHOST_kWindowStateMaximized) {
1126                 /*
1127                  * We can't change to Maximized if the window
1128                  * isn't mapped.
1129                  */
1130                 if (cur_state == GHOST_kWindowStateMinimized)
1131                         return (GHOST_kFailure);
1132
1133                 if (is_full == True)
1134                         netwmFullScreen(False);
1135                 if (is_motif_full == True)
1136                         motifFullScreen(False);
1137                 if (is_max == False)
1138                         netwmMaximized(True);
1139                 return (GHOST_kSuccess);
1140         }
1141
1142         if (state == GHOST_kWindowStateMinimized) {
1143                 /*
1144                  * The window manager need save the current state of
1145                  * the window (maximized, full screen, etc).
1146                  */
1147                 icccmSetState(IconicState);
1148                 return (GHOST_kSuccess);
1149         }
1150
1151         return (GHOST_kFailure);
1152 }
1153
1154 #include <iostream>
1155
1156 GHOST_TSuccess
1157 GHOST_WindowX11::
1158 setOrder(
1159                 GHOST_TWindowOrder order)
1160 {
1161         if (order == GHOST_kWindowOrderTop) {
1162                 XWindowAttributes attr;
1163                 Atom atom;
1164
1165                 /* We use both XRaiseWindow and _NET_ACTIVE_WINDOW, since some
1166                  * window managers ignore the former (e.g. kwin from kde) and others
1167                  * don't implement the latter (e.g. fluxbox pre 0.9.9) */
1168
1169                 XRaiseWindow(m_display, m_window);
1170
1171                 atom = XInternAtom(m_display, "_NET_ACTIVE_WINDOW", True);
1172
1173                 if (atom != None) {
1174                         Window root;
1175                         XEvent xev;
1176                         long eventmask;
1177
1178                         xev.xclient.type = ClientMessage;
1179                         xev.xclient.serial = 0;
1180                         xev.xclient.send_event = True;
1181                         xev.xclient.window = m_window;
1182                         xev.xclient.message_type = atom;
1183
1184                         xev.xclient.format = 32;
1185                         xev.xclient.data.l[0] = 1;
1186                         xev.xclient.data.l[1] = CurrentTime;
1187                         xev.xclient.data.l[2] = m_window;
1188                         xev.xclient.data.l[3] = 0;
1189                         xev.xclient.data.l[4] = 0;
1190
1191                         root = RootWindow(m_display, m_visualInfo->screen);
1192                         eventmask = SubstructureRedirectMask | SubstructureNotifyMask;
1193
1194                         XSendEvent(m_display, root, False, eventmask, &xev);
1195                 }
1196
1197                 XGetWindowAttributes(m_display, m_window, &attr);
1198
1199                 /* iconized windows give bad match error */
1200                 if (attr.map_state == IsViewable)
1201                         XSetInputFocus(m_display, m_window, RevertToPointerRoot,
1202                                        CurrentTime);
1203                 XFlush(m_display);
1204         }
1205         else if (order == GHOST_kWindowOrderBottom) {
1206                 XLowerWindow(m_display, m_window);
1207                 XFlush(m_display);
1208         }
1209         else {
1210                 return GHOST_kFailure;
1211         }
1212
1213         return GHOST_kSuccess;
1214 }
1215
1216 GHOST_TSuccess
1217 GHOST_WindowX11::
1218 invalidate()
1219 {
1220         /* So the idea of this function is to generate an expose event
1221          * for the window.
1222          * Unfortunately X does not handle expose events for you and
1223          * it is the client's job to refresh the dirty part of the window.
1224          * We need to queue up invalidate calls and generate GHOST events
1225          * for them in the system.
1226          *
1227          * We implement this by setting a boolean in this class to concatenate
1228          * all such calls into a single event for this window.
1229          *
1230          * At the same time we queue the dirty windows in the system class
1231          * and generate events for them at the next processEvents call. */
1232
1233         if (m_invalid_window == false) {
1234                 m_system->addDirtyWindow(this);
1235                 m_invalid_window = true;
1236         }
1237
1238         return GHOST_kSuccess;
1239 }
1240
1241 /**
1242  * called by the X11 system implementation when expose events
1243  * for the window have been pushed onto the GHOST queue
1244  */
1245
1246 void
1247 GHOST_WindowX11::
1248 validate()
1249 {
1250         m_invalid_window = false;
1251 }
1252
1253
1254 /**
1255  * Destructor.
1256  * Closes the window and disposes resources allocated.
1257  */
1258
1259 GHOST_WindowX11::
1260 ~GHOST_WindowX11()
1261 {
1262         std::map<unsigned int, Cursor>::iterator it = m_standard_cursors.begin();
1263         for (; it != m_standard_cursors.end(); ++it) {
1264                 XFreeCursor(m_display, it->second);
1265         }
1266
1267         if (m_empty_cursor) {
1268                 XFreeCursor(m_display, m_empty_cursor);
1269         }
1270         if (m_custom_cursor) {
1271                 XFreeCursor(m_display, m_custom_cursor);
1272         }
1273
1274         if (m_valid_setup) {
1275                 static Atom Primary_atom, Clipboard_atom;
1276                 Window p_owner, c_owner;
1277                 /*Change the owner of the Atoms to None if we are the owner*/
1278                 Primary_atom = XInternAtom(m_display, "PRIMARY", False);
1279                 Clipboard_atom = XInternAtom(m_display, "CLIPBOARD", False);
1280
1281
1282                 p_owner = XGetSelectionOwner(m_display, Primary_atom);
1283                 c_owner = XGetSelectionOwner(m_display, Clipboard_atom);
1284
1285                 if (p_owner == m_window) {
1286                         XSetSelectionOwner(m_display, Primary_atom, None, CurrentTime);
1287                 }
1288                 if (c_owner == m_window) {
1289                         XSetSelectionOwner(m_display, Clipboard_atom, None, CurrentTime);
1290                 }
1291         }
1292
1293         if (m_visualInfo) {
1294                 XFree(m_visualInfo);
1295         }
1296
1297 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
1298         if (m_xic) {
1299                 XDestroyIC(m_xic);
1300         }
1301 #endif
1302
1303 #ifdef WITH_XDND
1304         delete m_dropTarget;
1305 #endif
1306
1307         releaseNativeHandles();
1308
1309         if (m_valid_setup) {
1310                 XDestroyWindow(m_display, m_window);
1311         }
1312 }
1313
1314
1315 GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type)
1316 {
1317         if (type == GHOST_kDrawingContextTypeOpenGL) {
1318
1319                 // During development:
1320                 //   try 4.x compatibility profile
1321                 //   try 3.3 compatibility profile
1322                 //   fall back to 3.0 if needed
1323                 //
1324                 // Final Blender 2.8:
1325                 //   try 4.x core profile
1326                 //   try 3.3 core profile
1327                 //   no fallbacks
1328
1329 #if defined(WITH_GL_PROFILE_CORE)
1330                 {
1331                         const char *version_major = (char*)glewGetString(GLEW_VERSION_MAJOR);
1332                         if (version_major != NULL && version_major[0] == '1') {
1333                                 fprintf(stderr, "Error: GLEW version 2.0 and above is required.\n");
1334                                 abort();
1335                         }
1336                 }
1337 #endif
1338
1339                 const int profile_mask =
1340 #if defined(WITH_GL_PROFILE_CORE)
1341                         GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
1342 #elif defined(WITH_GL_PROFILE_COMPAT)
1343                         GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
1344 #else
1345 #  error // must specify either core or compat at build time
1346 #endif
1347
1348                 GHOST_Context *context;
1349
1350                 for (int minor = 5; minor >= 0; --minor) {
1351                         context = new GHOST_ContextGLX(
1352                                 m_wantStereoVisual,
1353                                 m_wantNumOfAASamples,
1354                                 m_window,
1355                                 m_display,
1356                                 (GLXFBConfig)m_fbconfig,
1357                                 profile_mask,
1358                                 4, minor,
1359                                 GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
1360                                 GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
1361
1362                         if (context->initializeDrawingContext())
1363                                 return context;
1364                         else
1365                                 delete context;
1366                 }
1367
1368                 context = new GHOST_ContextGLX(
1369                         m_wantStereoVisual,
1370                         m_wantNumOfAASamples,
1371                         m_window,
1372                         m_display,
1373                         (GLXFBConfig)m_fbconfig,
1374                         profile_mask,
1375                         3, 3,
1376                         GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
1377                         GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
1378
1379                 if (context->initializeDrawingContext())
1380                         return context;
1381                 else
1382                         delete context;
1383
1384         }
1385
1386         return NULL;
1387 }
1388
1389
1390 Cursor
1391 GHOST_WindowX11::
1392 getStandardCursor(
1393                 GHOST_TStandardCursor g_cursor)
1394 {
1395         unsigned int xcursor_id;
1396
1397 #define GtoX(gcurs, xcurs)  case gcurs: xcursor_id = xcurs
1398         switch (g_cursor) {
1399                 GtoX(GHOST_kStandardCursorRightArrow, XC_arrow); break;
1400                 GtoX(GHOST_kStandardCursorLeftArrow, XC_top_left_arrow); break;
1401                 GtoX(GHOST_kStandardCursorInfo, XC_hand1); break;
1402                 GtoX(GHOST_kStandardCursorDestroy, XC_pirate); break;
1403                 GtoX(GHOST_kStandardCursorHelp, XC_question_arrow); break;
1404                 GtoX(GHOST_kStandardCursorCycle, XC_exchange); break;
1405                 GtoX(GHOST_kStandardCursorSpray, XC_spraycan); break;
1406                 GtoX(GHOST_kStandardCursorWait, XC_watch); break;
1407                 GtoX(GHOST_kStandardCursorText, XC_xterm); break;
1408                 GtoX(GHOST_kStandardCursorCrosshair, XC_crosshair); break;
1409                 GtoX(GHOST_kStandardCursorUpDown, XC_sb_v_double_arrow); break;
1410                 GtoX(GHOST_kStandardCursorLeftRight, XC_sb_h_double_arrow); break;
1411                 GtoX(GHOST_kStandardCursorTopSide, XC_top_side); break;
1412                 GtoX(GHOST_kStandardCursorBottomSide, XC_bottom_side); break;
1413                 GtoX(GHOST_kStandardCursorLeftSide, XC_left_side); break;
1414                 GtoX(GHOST_kStandardCursorRightSide, XC_right_side); break;
1415                 GtoX(GHOST_kStandardCursorTopLeftCorner, XC_top_left_corner); break;
1416                 GtoX(GHOST_kStandardCursorTopRightCorner, XC_top_right_corner); break;
1417                 GtoX(GHOST_kStandardCursorBottomRightCorner, XC_bottom_right_corner); break;
1418                 GtoX(GHOST_kStandardCursorBottomLeftCorner, XC_bottom_left_corner); break;
1419                 GtoX(GHOST_kStandardCursorPencil, XC_pencil); break;
1420                 GtoX(GHOST_kStandardCursorCopy, XC_arrow); break;
1421                 default:
1422                         xcursor_id = 0;
1423         }
1424 #undef GtoX
1425
1426         if (xcursor_id) {
1427                 Cursor xcursor = m_standard_cursors[xcursor_id];
1428
1429                 if (!xcursor) {
1430                         xcursor = XCreateFontCursor(m_display, xcursor_id);
1431
1432                         m_standard_cursors[xcursor_id] = xcursor;
1433                 }
1434
1435                 return xcursor;
1436         }
1437         else {
1438                 return None;
1439         }
1440 }
1441
1442 Cursor
1443 GHOST_WindowX11::
1444 getEmptyCursor(
1445         ) {
1446         if (!m_empty_cursor) {
1447                 Pixmap blank;
1448                 XColor dummy = {0};
1449                 char data[1] = {0};
1450
1451                 /* make a blank cursor */
1452                 blank = XCreateBitmapFromData(
1453                     m_display,
1454                     RootWindow(m_display, m_visualInfo->screen),
1455                     data, 1, 1
1456                     );
1457
1458                 m_empty_cursor = XCreatePixmapCursor(m_display, blank, blank, &dummy, &dummy, 0, 0);
1459                 XFreePixmap(m_display, blank);
1460         }
1461
1462         return m_empty_cursor;
1463 }
1464
1465 GHOST_TSuccess
1466 GHOST_WindowX11::
1467 setWindowCursorVisibility(
1468                 bool visible)
1469 {
1470         Cursor xcursor;
1471
1472         if (visible) {
1473                 if (m_visible_cursor)
1474                         xcursor = m_visible_cursor;
1475                 else
1476                         xcursor = getStandardCursor(getCursorShape() );
1477         }
1478         else {
1479                 xcursor = getEmptyCursor();
1480         }
1481
1482         XDefineCursor(m_display, m_window, xcursor);
1483         XFlush(m_display);
1484
1485         return GHOST_kSuccess;
1486 }
1487
1488 GHOST_TSuccess
1489 GHOST_WindowX11::
1490 setWindowCursorGrab(
1491                 GHOST_TGrabCursorMode mode)
1492 {
1493         if (mode != GHOST_kGrabDisable) {
1494                 if (mode != GHOST_kGrabNormal) {
1495                         m_system->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
1496                         setCursorGrabAccum(0, 0);
1497
1498                         if (mode == GHOST_kGrabHide)
1499                                 setWindowCursorVisibility(false);
1500
1501                 }
1502 #ifdef GHOST_X11_GRAB
1503                 XGrabPointer(m_display, m_window, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
1504                              GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
1505 #endif
1506         }
1507         else {
1508                 if (m_cursorGrab == GHOST_kGrabHide) {
1509                         m_system->setCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
1510                 }
1511
1512                 if (m_cursorGrab != GHOST_kGrabNormal) {
1513                         /* use to generate a mouse move event, otherwise the last event
1514                          * blender gets can be outside the screen causing menus not to show
1515                          * properly unless the user moves the mouse */
1516
1517 #ifdef WITH_X11_XINPUT
1518                         if ((m_system->m_xinput_version.present) &&
1519                             (m_system->m_xinput_version.major_version >= 2))
1520                         {
1521                                 int device_id;
1522                                 if (XIGetClientPointer(m_display, None, &device_id) != False) {
1523                                         XIWarpPointer(m_display, device_id, None, None, 0, 0, 0, 0, 0, 0);
1524                                 }
1525                         }
1526                         else
1527 #endif
1528                         {
1529                                 XWarpPointer(m_display, None, None, 0, 0, 0, 0, 0, 0);
1530                         }
1531                 }
1532
1533                 /* Perform this last so to workaround XWayland bug, see: T53004. */
1534                 if (m_cursorGrab == GHOST_kGrabHide) {
1535                         setWindowCursorVisibility(true);
1536                 }
1537
1538                 /* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
1539                 setCursorGrabAccum(0, 0);
1540                 m_cursorGrabBounds.m_l = m_cursorGrabBounds.m_r = -1; /* disable */
1541 #ifdef GHOST_X11_GRAB
1542                 XUngrabPointer(m_display, CurrentTime);
1543 #endif
1544         }
1545
1546         XFlush(m_display);
1547
1548         return GHOST_kSuccess;
1549 }
1550
1551 GHOST_TSuccess
1552 GHOST_WindowX11::
1553 setWindowCursorShape(
1554                 GHOST_TStandardCursor shape)
1555 {
1556         Cursor xcursor = getStandardCursor(shape);
1557
1558         m_visible_cursor = xcursor;
1559
1560         XDefineCursor(m_display, m_window, xcursor);
1561         XFlush(m_display);
1562
1563         return GHOST_kSuccess;
1564 }
1565
1566 GHOST_TSuccess
1567 GHOST_WindowX11::
1568 setWindowCustomCursorShape(
1569                 GHOST_TUns8 bitmap[16][2],
1570                 GHOST_TUns8 mask[16][2],
1571                 int hotX,
1572                 int hotY)
1573 {
1574         setWindowCustomCursorShape((GHOST_TUns8 *)bitmap, (GHOST_TUns8 *)mask,
1575                                    16, 16, hotX, hotY, 0, 1);
1576         return GHOST_kSuccess;
1577 }
1578
1579 GHOST_TSuccess
1580 GHOST_WindowX11::
1581 setWindowCustomCursorShape(
1582                 GHOST_TUns8 *bitmap,
1583                 GHOST_TUns8 *mask,
1584                 int sizex,
1585                 int sizey,
1586                 int hotX,
1587                 int hotY,
1588                 int /*fg_color*/,
1589                 int /*bg_color*/)
1590 {
1591         Colormap colormap = DefaultColormap(m_display, m_visualInfo->screen);
1592         Pixmap bitmap_pix, mask_pix;
1593         XColor fg, bg;
1594
1595         if (XAllocNamedColor(m_display, colormap, "White", &fg, &fg) == 0) return GHOST_kFailure;
1596         if (XAllocNamedColor(m_display, colormap, "Black", &bg, &bg) == 0) return GHOST_kFailure;
1597
1598         if (m_custom_cursor) {
1599                 XFreeCursor(m_display, m_custom_cursor);
1600         }
1601
1602         bitmap_pix = XCreateBitmapFromData(m_display, m_window, (char *) bitmap, sizex, sizey);
1603         mask_pix = XCreateBitmapFromData(m_display, m_window, (char *) mask, sizex, sizey);
1604
1605         m_custom_cursor = XCreatePixmapCursor(m_display, bitmap_pix, mask_pix, &fg, &bg, hotX, hotY);
1606         XDefineCursor(m_display, m_window, m_custom_cursor);
1607         XFlush(m_display);
1608
1609         m_visible_cursor = m_custom_cursor;
1610
1611         XFreePixmap(m_display, bitmap_pix);
1612         XFreePixmap(m_display, mask_pix);
1613
1614         XFreeColors(m_display, colormap, &fg.pixel, 1, 0L);
1615         XFreeColors(m_display, colormap, &bg.pixel, 1, 0L);
1616
1617         return GHOST_kSuccess;
1618 }
1619
1620
1621 GHOST_TSuccess
1622 GHOST_WindowX11::
1623 beginFullScreen() const
1624 {
1625         {
1626                 Window root_return;
1627                 int x_return, y_return;
1628                 unsigned int w_return, h_return, border_w_return, depth_return;
1629
1630                 XGetGeometry(m_display, m_window, &root_return, &x_return, &y_return,
1631                              &w_return, &h_return, &border_w_return, &depth_return);
1632
1633                 m_system->setCursorPosition(w_return / 2, h_return / 2);
1634         }
1635
1636
1637         /* Grab Keyboard & Mouse */
1638         int err;
1639
1640         err = XGrabKeyboard(m_display, m_window, False,
1641                             GrabModeAsync, GrabModeAsync, CurrentTime);
1642         if (err != GrabSuccess) printf("XGrabKeyboard failed %d\n", err);
1643
1644         err = XGrabPointer(m_display, m_window, False,  PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
1645                            GrabModeAsync, GrabModeAsync, m_window, None, CurrentTime);
1646         if (err != GrabSuccess) printf("XGrabPointer failed %d\n", err);
1647
1648         return GHOST_kSuccess;
1649 }
1650
1651 GHOST_TSuccess
1652 GHOST_WindowX11::
1653 endFullScreen() const
1654 {
1655         XUngrabKeyboard(m_display, CurrentTime);
1656         XUngrabPointer(m_display, CurrentTime);
1657
1658         return GHOST_kSuccess;
1659 }
1660
1661 GHOST_TUns16
1662 GHOST_WindowX11::
1663 getDPIHint()
1664 {
1665         /* Try to read DPI setting set using xrdb */
1666         char* resMan = XResourceManagerString(m_display);
1667         if (resMan) {
1668                 XrmDatabase xrdb = XrmGetStringDatabase(resMan);
1669                 if (xrdb) {
1670                         char* type = NULL;
1671                         XrmValue val;
1672
1673                         int success = XrmGetResource(xrdb, "Xft.dpi", "Xft.Dpi", &type, &val);
1674                         if (success && type) {
1675                                 if (strcmp(type, "String") == 0) {
1676                                         return atoi((char*)val.addr);
1677                                 }
1678                         }
1679                 }
1680         }
1681
1682         /* Fallback to calculating DPI using X reported DPI, set using xrandr --dpi */
1683         XWindowAttributes attr;
1684         if (!XGetWindowAttributes(m_display, m_window, &attr)) {
1685                 /* Failed to get window attributes, return X11 default DPI */
1686                 return 96;
1687         }
1688
1689         Screen* screen = attr.screen;
1690         int pixelWidth = WidthOfScreen(screen);
1691         int pixelHeight = HeightOfScreen(screen);
1692         int mmWidth = WidthMMOfScreen(screen);
1693         int mmHeight = HeightMMOfScreen(screen);
1694
1695         double pixelDiagonal = sqrt((pixelWidth * pixelWidth) + (pixelHeight * pixelHeight));
1696         double mmDiagonal = sqrt((mmWidth * mmWidth) + (mmHeight * mmHeight));
1697         float inchDiagonal = mmDiagonal * 0.039f;
1698         int dpi = pixelDiagonal / inchDiagonal;
1699         return dpi;
1700 }
1701
1702 GHOST_TSuccess GHOST_WindowX11::setProgressBar(float progress)
1703 {
1704         if (m_taskbar.is_valid()) {
1705                 m_taskbar.set_progress(progress);
1706                 m_taskbar.set_progress_enabled(true);
1707                 return GHOST_kSuccess;
1708         }
1709
1710         return GHOST_kFailure;
1711 }
1712
1713 GHOST_TSuccess GHOST_WindowX11::endProgressBar()
1714 {
1715         if (m_taskbar.is_valid()) {
1716                 m_taskbar.set_progress_enabled(false);
1717                 return GHOST_kSuccess;
1718         }
1719
1720         return GHOST_kFailure;
1721 }