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