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