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