e68e0901dabb9973a554c7f5df4859f8abc13d0a
[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
37 #include "GHOST_WindowX11.h"
38 #include "GHOST_SystemX11.h"
39 #include "STR_String.h"
40 #include "GHOST_Debug.h"
41
42 #ifdef WITH_XDND
43 #  include "GHOST_DropTargetX11.h"
44 #endif
45
46 #if defined(WITH_GL_EGL)
47 #  include "GHOST_ContextEGL.h"
48 #else
49 #  include "GHOST_ContextGLX.h"
50 #endif
51
52 #if defined(__sun__) || defined(__sun) || defined(__sparc) || defined(__sparc__) || defined(_AIX)
53 #  include <strings.h>
54 #endif
55
56 #include <cstring>
57 #include <cstdio>
58
59 /* gethostname */
60 #include <unistd.h>
61
62 #include <algorithm>
63 #include <string>
64
65 /* For obscure full screen mode stuff
66  * lifted verbatim from blut. */
67
68 typedef struct {
69         long flags;
70         long functions;
71         long decorations;
72         long input_mode;
73 } MotifWmHints;
74
75 #define MWM_HINTS_DECORATIONS         (1L << 1)
76
77 #ifndef HOST_NAME_MAX
78 #  define HOST_NAME_MAX 64
79 #endif
80
81 // #define GHOST_X11_GRAB
82
83 /*
84  * A Client can't change the window property, that is
85  * the work of the window manager. In case, we send
86  * a ClientMessage to the RootWindow with the property
87  * and the Action (WM-spec define this):
88  */
89 #define _NET_WM_STATE_REMOVE 0
90 #define _NET_WM_STATE_ADD 1
91 // #define _NET_WM_STATE_TOGGLE 2 // UNUSED
92
93 /*
94  * import bpy
95  * ima = bpy.data.images["blender.png"]
96  * w, h = ima.size
97  * print("%d,%d," % (w, h))
98  * for y in range(h - 1, -1, -1):
99  *     px = []
100  *     for x in range(w):
101  *         p = ((y * w) + x) * 4
102  *         rgba = ima.pixels[p : p + 4]
103  *         rgba = rgba[2], rgba[1], rgba[0], rgba[3]
104  *         px.append(sum((int(p * 255) << (8 * i)) for i, p in enumerate(rgba)))
105  *     print(", ".join([str(p) for p in px]), end=",\n")
106  */
107
108 /**
109  * See the python script above to regenerate the 48x48 icon within blender
110  *
111  * \note Using 'unsigned' to avoid `-Wnarrowing` warning.
112  */
113 static const unsigned long BLENDER_ICON_48x48x32[] = {
114         48,48,
115         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
116         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
117         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
118         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,
119         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,
120         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,
121         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,
122         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,
123         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,
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, 399726848, 3452984576, 4107887616, 4294281765, 4294485590, 4294485591, 4294485590, 4294418767, 4124931612, 3469762048, 449730560, 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, 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,
126         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,
127         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,
128         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,
129         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,
130         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,
131         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,
132         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,
133         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,
134         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,
135         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,
136         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,
137         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,
138         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,
139         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,
140         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,
141         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,
142         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,
143         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,
144         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,
145         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,
146         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,
147         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,
148         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,
149         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,
150         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,
151         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,
152         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,
153         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,
154         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,
155         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,
156         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,
157         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,
158         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
159         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
160         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
161         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
162         4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303, 4671303,
163 };
164
165 static XVisualInfo *x11_visualinfo_from_glx(
166         Display *display,
167         bool stereoVisual, GHOST_TUns16 *r_numOfAASamples)
168 {
169         XVisualInfo *visualInfo = NULL;
170         GHOST_TUns16 numOfAASamples = *r_numOfAASamples;
171         GHOST_TUns16 actualSamples;
172
173         /* Set up the minimum attributes that we require and see if
174          * X can find us a visual matching those requirements. */
175         int glx_major, glx_minor; /* GLX version: major.minor */
176
177         if (!glXQueryVersion(display, &glx_major, &glx_minor)) {
178                 fprintf(stderr,
179                         "%s:%d: X11 glXQueryVersion() failed, "
180                         "verify working openGL system!\n",
181                         __FILE__, __LINE__);
182
183                 return NULL;
184         }
185
186         /* GLX >= 1.4 required for multi-sample */
187         if ((glx_major > 1) || (glx_major == 1 && glx_minor >= 4)) {
188                 actualSamples = numOfAASamples;
189         }
190         else {
191                 numOfAASamples = 0;
192                 actualSamples = 0;
193         }
194
195         /* Find the display with highest samples, starting at level requested */
196         for (;;) {
197                 int glx_attribs[64];
198
199                 GHOST_X11_GL_GetAttributes(glx_attribs, 64, actualSamples, stereoVisual, false);
200
201                 visualInfo = glXChooseVisual(display, DefaultScreen(display), glx_attribs);
202
203                 /* Any sample level or even zero, which means oversampling disabled, is good
204                  * but we need a valid visual to continue */
205                 if (visualInfo != NULL) {
206                         if (actualSamples < numOfAASamples) {
207                                 fprintf(stderr,
208                                         "Warning! Unable to find a multisample pixel format that supports exactly %d samples. "
209                                         "Substituting one that uses %d samples.\n",
210                                         numOfAASamples, actualSamples);
211                         }
212                         break;
213                 }
214
215                 if (actualSamples == 0) {
216                         /* All options exhausted, cannot continue */
217                         fprintf(stderr,
218                                 "%s:%d: X11 glXChooseVisual() failed, "
219                                 "verify working openGL system!\n",
220                                 __FILE__, __LINE__);
221
222                         return NULL;
223                 }
224                 else {
225                         --actualSamples;
226                 }
227         }
228
229         *r_numOfAASamples = actualSamples;
230
231         return visualInfo;
232 }
233
234 GHOST_WindowX11::
235 GHOST_WindowX11(GHOST_SystemX11 *system,
236         Display *display,
237         const STR_String &title,
238         GHOST_TInt32 left,
239         GHOST_TInt32 top,
240         GHOST_TUns32 width,
241         GHOST_TUns32 height,
242         GHOST_TWindowState state,
243         const GHOST_TEmbedderWindowID parentWindow,
244         GHOST_TDrawingContextType type,
245         const bool stereoVisual,
246         const bool exclusive,
247         const GHOST_TUns16 numOfAASamples, const bool is_debug)
248     : GHOST_Window(width, height, state, stereoVisual, exclusive, numOfAASamples),
249       m_display(display),
250       m_visualInfo(NULL),
251       m_normal_state(GHOST_kWindowStateNormal),
252       m_system(system),
253       m_invalid_window(false),
254       m_empty_cursor(None),
255       m_custom_cursor(None),
256       m_visible_cursor(None),
257 #ifdef WITH_XDND
258       m_dropTarget(NULL),
259 #endif
260 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
261       m_xic(NULL),
262 #endif
263       m_valid_setup(false),
264       m_is_debug_context(is_debug)
265 {
266         if (type == GHOST_kDrawingContextTypeOpenGL) {
267                 m_visualInfo = x11_visualinfo_from_glx(m_display, stereoVisual, &m_wantNumOfAASamples);
268         }
269         else {
270                 XVisualInfo tmp = {0};
271                 int n;
272                 m_visualInfo = XGetVisualInfo(m_display, 0, &tmp, &n);
273         }
274
275         /* caller needs to check 'getValid()' */
276         if (m_visualInfo == NULL) {
277                 fprintf(stderr, "initial window could not find the GLX extension\n");
278                 return;
279         }
280
281         unsigned int xattributes_valuemask = 0;
282
283         XSetWindowAttributes xattributes;
284         memset(&xattributes, 0, sizeof(xattributes));
285
286         xattributes_valuemask |= CWBorderPixel;
287         xattributes.border_pixel = 0;
288
289         /* Specify which events we are interested in hearing. */
290
291         xattributes_valuemask |= CWEventMask;
292         xattributes.event_mask =
293                 ExposureMask | StructureNotifyMask |
294                 KeyPressMask | KeyReleaseMask |
295                 EnterWindowMask | LeaveWindowMask |
296                 ButtonPressMask | ButtonReleaseMask |
297                 PointerMotionMask | FocusChangeMask |
298                 PropertyChangeMask | KeymapStateMask;
299
300         if (exclusive) {
301                 xattributes_valuemask |= CWOverrideRedirect;
302                 xattributes.override_redirect = True;
303         }
304
305         xattributes_valuemask |= CWColormap;
306         xattributes.colormap = XCreateColormap(
307                 m_display,
308                 RootWindow(m_display, m_visualInfo->screen),
309                 m_visualInfo->visual,
310                 AllocNone
311                 );
312
313         /* create the window! */
314         if (parentWindow == 0) {
315                 m_window =  XCreateWindow(
316                         m_display,
317                         RootWindow(m_display, m_visualInfo->screen),
318                         left, top, width, height,
319                         0, /* no border. */
320                         m_visualInfo->depth,
321                         InputOutput,
322                         m_visualInfo->visual,
323                         xattributes_valuemask,
324                         &xattributes);
325         }
326         else {
327                 Window root_return;
328                 int x_return, y_return;
329                 unsigned int w_return, h_return, border_w_return, depth_return;
330                 
331                 XGetGeometry(m_display, parentWindow, &root_return, &x_return, &y_return,
332                              &w_return, &h_return, &border_w_return, &depth_return);
333
334                 left = 0;
335                 top = 0;
336                 width = w_return;
337                 height = h_return;
338
339
340                 m_window = XCreateWindow(
341                         m_display,
342                         parentWindow, /* reparent against embedder */
343                         left, top, width, height,
344                         0, /* no border. */
345                         m_visualInfo->depth,
346                         InputOutput,
347                         m_visualInfo->visual,
348                         xattributes_valuemask,
349                         &xattributes);
350
351                 XSelectInput(m_display, parentWindow, SubstructureNotifyMask);
352                 
353         }       
354
355 #ifdef WITH_XDND
356         /* initialize drop target for newly created window */
357         m_dropTarget = new GHOST_DropTargetX11(this, m_system);
358         GHOST_PRINT("Set drop target\n");
359 #endif
360
361         if (state == GHOST_kWindowStateMaximized || state == GHOST_kWindowStateFullScreen) {
362                 Atom atoms[2];
363                 int count = 0;
364                 if (state == GHOST_kWindowStateMaximized) {
365                         atoms[count++] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT;
366                         atoms[count++] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_HORZ;
367                 }
368                 else {
369                         atoms[count++] = m_system->m_atom._NET_WM_STATE_FULLSCREEN;
370                 }
371
372                 XChangeProperty(m_display, m_window, m_system->m_atom._NET_WM_STATE, XA_ATOM, 32,
373                                 PropModeReplace, (unsigned char *)atoms, count);
374                 m_post_init = False;
375         }
376         /*
377          * One of the problem with WM-spec is that can't set a property
378          * to a window that isn't mapped. That is why we can't "just
379          * call setState" here.
380          *
381          * To fix this, we first need know that the window is really
382          * map waiting for the MapNotify event.
383          *
384          * So, m_post_init indicate that we need wait for the MapNotify
385          * event and then set the Window state to the m_post_state.
386          */
387         else if ((state != GHOST_kWindowStateNormal) && (state != GHOST_kWindowStateMinimized)) {
388                 m_post_init = True;
389                 m_post_state = state;
390         }
391         else {
392                 m_post_init = False;
393                 m_post_state = GHOST_kWindowStateNormal;
394         }
395
396
397         /* Create some hints for the window manager on how
398          * we want this window treated. */
399         {
400                 XSizeHints *xsizehints = XAllocSizeHints();
401                 xsizehints->flags = PPosition | PSize | PMinSize | PMaxSize;
402                 xsizehints->x = left;
403                 xsizehints->y = top;
404                 xsizehints->width = width;
405                 xsizehints->height = height;
406                 xsizehints->min_width = 320;     /* size hints, could be made apart of the ghost api */
407                 xsizehints->min_height = 240;    /* limits are also arbitrary, but should not allow 1x1 window */
408                 xsizehints->max_width = 65535;
409                 xsizehints->max_height = 65535;
410                 XSetWMNormalHints(m_display, m_window, xsizehints);
411                 XFree(xsizehints);
412         }
413
414
415         /* XClassHint, title */
416         {
417                 XClassHint *xclasshint = XAllocClassHint();
418                 const int len = title.Length() + 1;
419                 char *wmclass = (char *)malloc(sizeof(char) * len);
420                 memcpy(wmclass, title.ReadPtr(), len * sizeof(char));
421                 xclasshint->res_name = wmclass;
422                 xclasshint->res_class = wmclass;
423                 XSetClassHint(m_display, m_window, xclasshint);
424                 free(wmclass);
425                 XFree(xclasshint);
426         }
427
428
429         /* The basic for a good ICCCM "work" */
430         if (m_system->m_atom.WM_PROTOCOLS) {
431                 Atom atoms[2];
432                 int natom = 0;
433
434                 if (m_system->m_atom.WM_DELETE_WINDOW) {
435                         atoms[natom] = m_system->m_atom.WM_DELETE_WINDOW;
436                         natom++;
437                 }
438
439                 if (m_system->m_atom.WM_TAKE_FOCUS) {
440                         atoms[natom] = m_system->m_atom.WM_TAKE_FOCUS;
441                         natom++;
442                 }
443
444                 if (natom) {
445                         /* printf("Register atoms: %d\n", natom); */
446                         XSetWMProtocols(m_display, m_window, atoms, natom);
447                 }
448         }
449
450         /* Set the window hints */
451         {
452                 XWMHints *xwmhints = XAllocWMHints();
453                 xwmhints->initial_state = NormalState;
454                 xwmhints->input = True;
455                 xwmhints->flags = InputHint | StateHint;
456                 XSetWMHints(display, m_window, xwmhints);
457                 XFree(xwmhints);
458         }
459
460
461         /* set the icon */
462         {
463                 Atom _NET_WM_ICON     = XInternAtom(m_display, "_NET_WM_ICON", False);
464                 XChangeProperty(m_display, m_window, _NET_WM_ICON, XA_CARDINAL,
465                                 32, PropModeReplace, (unsigned char *)BLENDER_ICON_48x48x32,
466                                 BLENDER_ICON_48x48x32[0] * BLENDER_ICON_48x48x32[1] + 2);
467         }
468
469         /* set the process ID (_NET_WM_PID) */
470         {
471                 Atom _NET_WM_PID = XInternAtom(m_display, "_NET_WM_PID", False);
472                 pid_t pid = getpid();
473                 XChangeProperty(m_display, m_window, _NET_WM_PID, XA_CARDINAL,
474                                 32, PropModeReplace, (unsigned char *)&pid, 1);
475         }
476
477
478         /* set the hostname (WM_CLIENT_MACHINE) */
479         {
480                 char  hostname[HOST_NAME_MAX];
481                 char *text_array[1];
482                 XTextProperty text_prop;
483
484                 gethostname(hostname, sizeof(hostname));
485                 hostname[sizeof(hostname) - 1] = '\0';
486                 text_array[0] = hostname;
487
488                 XStringListToTextProperty(text_array, 1, &text_prop);
489                 XSetWMClientMachine(m_display, m_window, &text_prop);
490                 XFree(text_prop.value);
491         }
492
493 #ifdef WITH_X11_XINPUT
494         initXInputDevices();
495
496         m_tabletData.Active = GHOST_kTabletModeNone;
497 #endif
498
499
500         /* now set up the rendering context. */
501         if (setDrawingContextType(type) == GHOST_kSuccess) {
502                 m_valid_setup = true;
503                 GHOST_PRINT("Created window\n");
504         }
505
506         setTitle(title);
507
508         if (exclusive) {
509                 XMapRaised(m_display, m_window);
510         }
511         else {
512                 XMapWindow(m_display, m_window);
513         }
514         GHOST_PRINT("Mapped window\n");
515
516         XFlush(m_display);
517 }
518
519 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
520 static void destroyICCallback(XIC /*xic*/, XPointer ptr, XPointer /*data*/)
521 {
522         GHOST_PRINT("XIM input context destroyed\n");
523
524         if (ptr) {
525                 *(XIC *)ptr = NULL;
526         }
527 }
528
529 bool GHOST_WindowX11::createX11_XIC()
530 {
531         XIM xim = m_system->getX11_XIM();
532         if (!xim)
533                 return false;
534
535         XICCallback destroy;
536         destroy.callback = (XICProc)destroyICCallback;
537         destroy.client_data = (XPointer)&m_xic;
538         m_xic = XCreateIC(xim, XNClientWindow, m_window, XNFocusWindow, m_window,
539                           XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
540                           XNResourceName, GHOST_X11_RES_NAME,
541                           XNResourceClass, GHOST_X11_RES_CLASS,
542                           XNDestroyCallback, &destroy,
543                           NULL);
544         if (!m_xic)
545                 return false;
546
547         unsigned long fevent;
548         XGetICValues(m_xic, XNFilterEvents, &fevent, NULL);
549         XSelectInput(m_display, m_window,
550                      ExposureMask | StructureNotifyMask |
551                      KeyPressMask | KeyReleaseMask |
552                      EnterWindowMask | LeaveWindowMask |
553                      ButtonPressMask | ButtonReleaseMask |
554                      PointerMotionMask | FocusChangeMask |
555                      PropertyChangeMask | KeymapStateMask | fevent);
556         return true;
557 }
558 #endif
559
560 #ifdef WITH_X11_XINPUT
561 void GHOST_WindowX11::initXInputDevices()
562 {
563         XExtensionVersion *version = XGetExtensionVersion(m_display, INAME);
564
565         if (version && (version != (XExtensionVersion *)NoSuchExtension)) {
566                 if (version->present) {
567                         GHOST_SystemX11::GHOST_TabletX11 &xtablet = m_system->GetXTablet();
568                         XEventClass xevents[8], ev;
569                         int dcount = 0;
570
571                         /* With modern XInput (xlib 1.6.2 at least and/or evdev 2.9.0) and some 'no-name' tablets
572                          * like 'UC-LOGIC Tablet WP5540U', we also need to 'select' ButtonPress for motion event,
573                          * otherwise we do not get any tablet motion event once pen is pressed... See T43367.
574                          */
575
576                         if (xtablet.StylusDevice) {
577                                 DeviceMotionNotify(xtablet.StylusDevice, xtablet.MotionEvent, ev);
578                                 if (ev) xevents[dcount++] = ev;
579                                 DeviceButtonPress(xtablet.StylusDevice, xtablet.PressEvent, ev);
580                                 if (ev) xevents[dcount++] = ev;
581                                 ProximityIn(xtablet.StylusDevice, xtablet.ProxInEvent, ev);
582                                 if (ev) xevents[dcount++] = ev;
583                                 ProximityOut(xtablet.StylusDevice, xtablet.ProxOutEvent, ev);
584                                 if (ev) xevents[dcount++] = ev;
585                         }
586                         if (xtablet.EraserDevice) {
587                                 DeviceMotionNotify(xtablet.EraserDevice, xtablet.MotionEventEraser, ev);
588                                 if (ev) xevents[dcount++] = ev;
589                                 DeviceButtonPress(xtablet.EraserDevice, xtablet.PressEventEraser, ev);
590                                 if (ev) xevents[dcount++] = ev;
591                                 ProximityIn(xtablet.EraserDevice, xtablet.ProxInEventEraser, ev);
592                                 if (ev) xevents[dcount++] = ev;
593                                 ProximityOut(xtablet.EraserDevice, xtablet.ProxOutEventEraser, ev);
594                                 if (ev) xevents[dcount++] = ev;
595                         }
596
597                         XSelectExtensionEvent(m_display, m_window, xevents, dcount);
598                 }
599                 XFree(version);
600         }
601 }
602
603 #endif /* WITH_X11_XINPUT */
604
605 Window
606 GHOST_WindowX11::
607 getXWindow()
608 {
609         return m_window;
610 }
611
612 bool
613 GHOST_WindowX11::
614 getValid() const
615 {
616         return GHOST_Window::getValid() && m_valid_setup;
617 }
618
619 void
620 GHOST_WindowX11::
621 setTitle(
622                 const STR_String& title)
623 {
624         Atom name = XInternAtom(m_display, "_NET_WM_NAME", 0);
625         Atom utf8str = XInternAtom(m_display, "UTF8_STRING", 0);
626         XChangeProperty(m_display, m_window,
627                         name, utf8str, 8, PropModeReplace,
628                         (const unsigned char *) title.ReadPtr(),
629                         title.Length());
630
631         /* This should convert to valid x11 string
632          * and getTitle would need matching change */
633         XStoreName(m_display, m_window, title);
634
635         XFlush(m_display);
636 }
637
638 void
639 GHOST_WindowX11::
640 getTitle(
641                 STR_String& title) const
642 {
643         char *name = NULL;
644         
645         XFetchName(m_display, m_window, &name);
646         title = name ? name : "untitled";
647         XFree(name);
648 }
649         
650 void
651 GHOST_WindowX11::
652 getWindowBounds(
653                 GHOST_Rect& bounds) const
654 {
655         /* Getting the window bounds under X11 is not
656          * really supported (nor should it be desired). */
657         getClientBounds(bounds);
658 }
659
660 void
661 GHOST_WindowX11::
662 getClientBounds(
663                 GHOST_Rect& bounds) const
664 {
665         Window root_return;
666         int x_return, y_return;
667         unsigned int w_return, h_return, border_w_return, depth_return;
668         GHOST_TInt32 screen_x, screen_y;
669         
670         XGetGeometry(m_display, m_window, &root_return, &x_return, &y_return,
671                      &w_return, &h_return, &border_w_return, &depth_return);
672
673         clientToScreen(0, 0, screen_x, screen_y);
674         
675         bounds.m_l = screen_x;
676         bounds.m_r = bounds.m_l + w_return;
677         bounds.m_t = screen_y;
678         bounds.m_b = bounds.m_t + h_return;
679
680 }
681
682 GHOST_TSuccess
683 GHOST_WindowX11::
684 setClientWidth(
685                 GHOST_TUns32 width)
686 {
687         XWindowChanges values;
688         unsigned int value_mask = CWWidth;
689         values.width = width;
690         XConfigureWindow(m_display, m_window, value_mask, &values);
691
692         return GHOST_kSuccess;
693 }
694
695 GHOST_TSuccess
696 GHOST_WindowX11::
697 setClientHeight(
698                 GHOST_TUns32 height)
699 {
700         XWindowChanges values;
701         unsigned int value_mask = CWHeight;
702         values.height = height;
703         XConfigureWindow(m_display, m_window, value_mask, &values);
704         return GHOST_kSuccess;
705
706 }
707
708 GHOST_TSuccess
709 GHOST_WindowX11::
710 setClientSize(
711                 GHOST_TUns32 width,
712                 GHOST_TUns32 height)
713 {
714         XWindowChanges values;
715         unsigned int value_mask = CWWidth | CWHeight;
716         values.width = width;
717         values.height = height;
718         XConfigureWindow(m_display, m_window, value_mask, &values);
719         return GHOST_kSuccess;
720
721 }       
722
723 void
724 GHOST_WindowX11::
725 screenToClient(
726                 GHOST_TInt32 inX,
727                 GHOST_TInt32 inY,
728                 GHOST_TInt32& outX,
729                 GHOST_TInt32& outY) const
730 {
731         /* This is correct! */
732
733         int ax, ay;
734         Window temp;
735
736         XTranslateCoordinates(m_display,
737                               RootWindow(m_display, m_visualInfo->screen),
738                               m_window,
739                               inX, inY,
740                               &ax, &ay,
741                               &temp);
742         outX = ax;
743         outY = ay;
744 }
745                  
746 void
747 GHOST_WindowX11::
748 clientToScreen(
749                 GHOST_TInt32 inX,
750                 GHOST_TInt32 inY,
751                 GHOST_TInt32& outX,
752                 GHOST_TInt32& outY) const
753 {
754         int ax, ay;
755         Window temp;
756
757         XTranslateCoordinates(
758             m_display,
759             m_window,
760             RootWindow(m_display, m_visualInfo->screen),
761             inX, inY,
762             &ax, &ay,
763             &temp);
764         outX = ax;
765         outY = ay;
766 }
767
768 void GHOST_WindowX11::icccmSetState(int state)
769 {
770         XEvent xev;
771
772         if (state != IconicState)
773                 return;
774
775         xev.xclient.type = ClientMessage;
776         xev.xclient.serial = 0;
777         xev.xclient.send_event = True;
778         xev.xclient.display = m_display;
779         xev.xclient.window = m_window;
780         xev.xclient.format = 32;
781         xev.xclient.message_type = m_system->m_atom.WM_CHANGE_STATE;
782         xev.xclient.data.l[0] = state;
783         XSendEvent(m_display, RootWindow(m_display, m_visualInfo->screen),
784                    False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
785 }
786
787 int GHOST_WindowX11::icccmGetState(void) const
788 {
789         Atom *prop_ret;
790         unsigned long bytes_after, num_ret;
791         Atom type_ret;
792         int format_ret, st;
793
794         prop_ret = NULL;
795         st = XGetWindowProperty(
796                 m_display, m_window, m_system->m_atom.WM_STATE, 0, 2,
797                 False, m_system->m_atom.WM_STATE, &type_ret,
798                 &format_ret, &num_ret, &bytes_after, ((unsigned char **)&prop_ret));
799         if ((st == Success) && (prop_ret) && (num_ret == 2))
800                 st = prop_ret[0];
801         else
802                 st = NormalState;
803
804         if (prop_ret)
805                 XFree(prop_ret);
806         return (st);
807 }
808
809 void GHOST_WindowX11::netwmMaximized(bool set)
810 {
811         XEvent xev;
812
813         xev.xclient.type = ClientMessage;
814         xev.xclient.serial = 0;
815         xev.xclient.send_event = True;
816         xev.xclient.window = m_window;
817         xev.xclient.message_type = m_system->m_atom._NET_WM_STATE;
818         xev.xclient.format = 32;
819
820         if (set == True)
821                 xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
822         else
823                 xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
824
825         xev.xclient.data.l[1] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_HORZ;
826         xev.xclient.data.l[2] = m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT;
827         xev.xclient.data.l[3] = 0;
828         xev.xclient.data.l[4] = 0;
829         XSendEvent(m_display, RootWindow(m_display, m_visualInfo->screen),
830                    False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
831 }
832
833 bool GHOST_WindowX11::netwmIsMaximized(void) const
834 {
835         Atom *prop_ret;
836         unsigned long bytes_after, num_ret, i;
837         Atom type_ret;
838         bool st;
839         int format_ret, ret, count;
840
841         prop_ret = NULL;
842         st = False;
843         ret = XGetWindowProperty(
844                 m_display, m_window, m_system->m_atom._NET_WM_STATE, 0, INT_MAX,
845                 False, XA_ATOM, &type_ret, &format_ret,
846                 &num_ret, &bytes_after, (unsigned char **)&prop_ret);
847         if ((ret == Success) && (prop_ret) && (format_ret == 32)) {
848                 count = 0;
849                 for (i = 0; i < num_ret; i++) {
850                         if (prop_ret[i] == m_system->m_atom._NET_WM_STATE_MAXIMIZED_HORZ) {
851                                 count++;
852                         }
853                         if (prop_ret[i] == m_system->m_atom._NET_WM_STATE_MAXIMIZED_VERT) {
854                                 count++;
855                         }
856                         if (count == 2) {
857                                 st = True;
858                                 break;
859                         }
860                 }
861         }
862
863         if (prop_ret)
864                 XFree(prop_ret);
865         return (st);
866 }
867
868 void GHOST_WindowX11::netwmFullScreen(bool set)
869 {
870         XEvent xev;
871
872         xev.xclient.type = ClientMessage;
873         xev.xclient.serial = 0;
874         xev.xclient.send_event = True;
875         xev.xclient.window = m_window;
876         xev.xclient.message_type = m_system->m_atom._NET_WM_STATE;
877         xev.xclient.format = 32;
878
879         if (set == True)
880                 xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
881         else
882                 xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
883
884         xev.xclient.data.l[1] = m_system->m_atom._NET_WM_STATE_FULLSCREEN;
885         xev.xclient.data.l[2] = 0;
886         xev.xclient.data.l[3] = 0;
887         xev.xclient.data.l[4] = 0;
888         XSendEvent(m_display, RootWindow(m_display, m_visualInfo->screen),
889                    False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
890 }
891
892 bool GHOST_WindowX11::netwmIsFullScreen(void) const
893 {
894         Atom *prop_ret;
895         unsigned long bytes_after, num_ret, i;
896         Atom type_ret;
897         bool st;
898         int format_ret, ret;
899
900         prop_ret = NULL;
901         st = False;
902         ret = XGetWindowProperty(
903                 m_display, m_window, m_system->m_atom._NET_WM_STATE, 0, INT_MAX,
904                 False, XA_ATOM, &type_ret, &format_ret,
905                 &num_ret, &bytes_after, (unsigned char **)&prop_ret);
906         if ((ret == Success) && (prop_ret) && (format_ret == 32)) {
907                 for (i = 0; i < num_ret; i++) {
908                         if (prop_ret[i] == m_system->m_atom._NET_WM_STATE_FULLSCREEN) {
909                                 st = True;
910                                 break;
911                         }
912                 }
913         }
914
915         if (prop_ret)
916                 XFree(prop_ret);
917         return (st);
918 }
919
920 void GHOST_WindowX11::motifFullScreen(bool set)
921 {
922         MotifWmHints hints;
923
924         hints.flags = MWM_HINTS_DECORATIONS;
925         if (set == True)
926                 hints.decorations = 0;
927         else
928                 hints.decorations = 1;
929
930         XChangeProperty(m_display, m_window, m_system->m_atom._MOTIF_WM_HINTS,
931                         m_system->m_atom._MOTIF_WM_HINTS, 32, PropModeReplace,
932                         (unsigned char *) &hints, 4);
933 }
934
935 bool GHOST_WindowX11::motifIsFullScreen(void) const
936 {
937         MotifWmHints *prop_ret;
938         unsigned long bytes_after, num_ret;
939         Atom type_ret;
940         bool state;
941         int format_ret, st;
942
943         prop_ret = NULL;
944         state = False;
945         st = XGetWindowProperty(
946                 m_display, m_window, m_system->m_atom._MOTIF_WM_HINTS, 0, INT_MAX,
947                 False, m_system->m_atom._MOTIF_WM_HINTS,
948                 &type_ret, &format_ret, &num_ret,
949                 &bytes_after, (unsigned char **)&prop_ret);
950         if ((st == Success) && prop_ret) {
951                 if (prop_ret->flags & MWM_HINTS_DECORATIONS) {
952                         if (!prop_ret->decorations)
953                                 state = True;
954                 }
955         }
956
957         if (prop_ret)
958                 XFree(prop_ret);
959         return (state);
960 }
961
962 GHOST_TWindowState GHOST_WindowX11::getState() const
963 {
964         GHOST_TWindowState state_ret;
965         int state;
966
967         state_ret = GHOST_kWindowStateNormal;
968         state = icccmGetState();
969         /*
970          * In the Iconic and Withdrawn state, the window
971          * is unmaped, so only need return a Minimized state.
972          */
973         if ((state == IconicState) || (state == WithdrawnState))
974                 state_ret = GHOST_kWindowStateMinimized;
975         else if (netwmIsFullScreen() == True)
976                 state_ret = GHOST_kWindowStateFullScreen;
977         else if (motifIsFullScreen() == True)
978                 state_ret = GHOST_kWindowStateFullScreen;
979         else if (netwmIsMaximized() == True)
980                 state_ret = GHOST_kWindowStateMaximized;
981         return (state_ret);
982 }
983
984 GHOST_TSuccess GHOST_WindowX11::setState(GHOST_TWindowState state)
985 {
986         GHOST_TWindowState cur_state;
987         bool is_max, is_full, is_motif_full;
988
989         cur_state = getState();
990         if (state == (int)cur_state)
991                 return GHOST_kSuccess;
992
993         if (cur_state != GHOST_kWindowStateMinimized) {
994                 /*
995                  * The window don't have this property's
996                  * if it's not mapped.
997                  */
998                 is_max = netwmIsMaximized();
999                 is_full = netwmIsFullScreen();
1000         }
1001         else {
1002                 is_max = False;
1003                 is_full = False;
1004         }
1005
1006         is_motif_full = motifIsFullScreen();
1007
1008         if (state == GHOST_kWindowStateNormal)
1009                 state = m_normal_state;
1010
1011         if (state == GHOST_kWindowStateNormal) {
1012                 if (is_max == True)
1013                         netwmMaximized(False);
1014                 if (is_full == True)
1015                         netwmFullScreen(False);
1016                 if (is_motif_full == True)
1017                         motifFullScreen(False);
1018                 icccmSetState(NormalState);
1019                 return (GHOST_kSuccess);
1020         }
1021
1022         if (state == GHOST_kWindowStateFullScreen) {
1023                 /*
1024                  * We can't change to full screen if the window
1025                  * isn't mapped.
1026                  */
1027                 if (cur_state == GHOST_kWindowStateMinimized)
1028                         return (GHOST_kFailure);
1029
1030                 m_normal_state = cur_state;
1031
1032                 if (is_max == True)
1033                         netwmMaximized(False);
1034                 if (is_full == False)
1035                         netwmFullScreen(True);
1036                 if (is_motif_full == False)
1037                         motifFullScreen(True);
1038                 return (GHOST_kSuccess);
1039         }
1040
1041         if (state == GHOST_kWindowStateMaximized) {
1042                 /*
1043                  * We can't change to Maximized if the window
1044                  * isn't mapped.
1045                  */
1046                 if (cur_state == GHOST_kWindowStateMinimized)
1047                         return (GHOST_kFailure);
1048
1049                 if (is_full == True)
1050                         netwmFullScreen(False);
1051                 if (is_motif_full == True)
1052                         motifFullScreen(False);
1053                 if (is_max == False)
1054                         netwmMaximized(True);
1055                 return (GHOST_kSuccess);
1056         }
1057
1058         if (state == GHOST_kWindowStateMinimized) {
1059                 /*
1060                  * The window manager need save the current state of
1061                  * the window (maximized, full screen, etc).
1062                  */
1063                 icccmSetState(IconicState);
1064                 return (GHOST_kSuccess);
1065         }
1066
1067         return (GHOST_kFailure);
1068 }
1069
1070 #include <iostream>
1071
1072 GHOST_TSuccess
1073 GHOST_WindowX11::
1074 setOrder(
1075                 GHOST_TWindowOrder order)
1076 {
1077         if (order == GHOST_kWindowOrderTop) {
1078                 XWindowAttributes attr;   
1079                 Atom atom;
1080
1081                 /* We use both XRaiseWindow and _NET_ACTIVE_WINDOW, since some
1082                  * window managers ignore the former (e.g. kwin from kde) and others
1083                  * don't implement the latter (e.g. fluxbox pre 0.9.9) */
1084
1085                 XRaiseWindow(m_display, m_window);
1086
1087                 atom = XInternAtom(m_display, "_NET_ACTIVE_WINDOW", True);
1088
1089                 if (atom != None) {
1090                         Window root;
1091                         XEvent xev;
1092                         long eventmask;
1093
1094                         xev.xclient.type = ClientMessage;
1095                         xev.xclient.serial = 0;
1096                         xev.xclient.send_event = True;
1097                         xev.xclient.window = m_window;
1098                         xev.xclient.message_type = atom;
1099
1100                         xev.xclient.format = 32;
1101                         xev.xclient.data.l[0] = 1;
1102                         xev.xclient.data.l[1] = CurrentTime;
1103                         xev.xclient.data.l[2] = m_window;
1104                         xev.xclient.data.l[3] = 0;
1105                         xev.xclient.data.l[4] = 0;
1106
1107                         root = RootWindow(m_display, m_visualInfo->screen);
1108                         eventmask = SubstructureRedirectMask | SubstructureNotifyMask;
1109
1110                         XSendEvent(m_display, root, False, eventmask, &xev);
1111                 }
1112
1113                 XGetWindowAttributes(m_display, m_window, &attr);
1114
1115                 /* iconized windows give bad match error */
1116                 if (attr.map_state == IsViewable)
1117                         XSetInputFocus(m_display, m_window, RevertToPointerRoot,
1118                                        CurrentTime);
1119                 XFlush(m_display);
1120         }
1121         else if (order == GHOST_kWindowOrderBottom) {
1122                 XLowerWindow(m_display, m_window);
1123                 XFlush(m_display);
1124         }
1125         else {
1126                 return GHOST_kFailure;
1127         }
1128         
1129         return GHOST_kSuccess;
1130 }
1131
1132 GHOST_TSuccess
1133 GHOST_WindowX11::
1134 invalidate()
1135 {
1136         /* So the idea of this function is to generate an expose event
1137          * for the window.
1138          * Unfortunately X does not handle expose events for you and
1139          * it is the client's job to refresh the dirty part of the window.
1140          * We need to queue up invalidate calls and generate GHOST events
1141          * for them in the system.
1142          *
1143          * We implement this by setting a boolean in this class to concatenate
1144          * all such calls into a single event for this window.
1145          *
1146          * At the same time we queue the dirty windows in the system class
1147          * and generate events for them at the next processEvents call. */
1148
1149         if (m_invalid_window == false) {
1150                 m_system->addDirtyWindow(this);
1151                 m_invalid_window = true;
1152         } 
1153  
1154         return GHOST_kSuccess;
1155 }
1156
1157 /**
1158  * called by the X11 system implementation when expose events
1159  * for the window have been pushed onto the GHOST queue
1160  */
1161  
1162 void
1163 GHOST_WindowX11::
1164 validate()
1165 {
1166         m_invalid_window = false;
1167 }       
1168  
1169  
1170 /**
1171  * Destructor.
1172  * Closes the window and disposes resources allocated.
1173  */
1174
1175 GHOST_WindowX11::
1176 ~GHOST_WindowX11()
1177 {
1178         std::map<unsigned int, Cursor>::iterator it = m_standard_cursors.begin();
1179         for (; it != m_standard_cursors.end(); ++it) {
1180                 XFreeCursor(m_display, it->second);
1181         }
1182
1183         if (m_empty_cursor) {
1184                 XFreeCursor(m_display, m_empty_cursor);
1185         }
1186         if (m_custom_cursor) {
1187                 XFreeCursor(m_display, m_custom_cursor);
1188         }
1189
1190         if (m_valid_setup) {
1191                 static Atom Primary_atom, Clipboard_atom;
1192                 Window p_owner, c_owner;
1193                 /*Change the owner of the Atoms to None if we are the owner*/
1194                 Primary_atom = XInternAtom(m_display, "PRIMARY", False);
1195                 Clipboard_atom = XInternAtom(m_display, "CLIPBOARD", False);
1196
1197
1198                 p_owner = XGetSelectionOwner(m_display, Primary_atom);
1199                 c_owner = XGetSelectionOwner(m_display, Clipboard_atom);
1200
1201                 if (p_owner == m_window) {
1202                         XSetSelectionOwner(m_display, Primary_atom, None, CurrentTime);
1203                 }
1204                 if (c_owner == m_window) {
1205                         XSetSelectionOwner(m_display, Clipboard_atom, None, CurrentTime);
1206                 }
1207         }
1208         
1209         if (m_visualInfo) {
1210                 XFree(m_visualInfo);
1211         }
1212
1213 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
1214         if (m_xic) {
1215                 XDestroyIC(m_xic);
1216         }
1217 #endif
1218
1219 #ifdef WITH_XDND
1220         delete m_dropTarget;
1221 #endif
1222
1223         releaseNativeHandles();
1224
1225         if (m_valid_setup) {
1226                 XDestroyWindow(m_display, m_window);
1227         }
1228 }
1229
1230
1231 GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type)
1232 {
1233         if (type == GHOST_kDrawingContextTypeOpenGL) {
1234 #if !defined(WITH_GL_EGL)
1235
1236 #if defined(WITH_GL_PROFILE_CORE)
1237                 GHOST_Context *context = new GHOST_ContextGLX(
1238                         m_wantStereoVisual,
1239                         m_wantNumOfAASamples,
1240                         m_window,
1241                         m_display,
1242                         m_visualInfo,
1243                         GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
1244                         3, 2,
1245                         GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
1246                         GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
1247 #elif defined(WITH_GL_PROFILE_ES20)
1248                 GHOST_Context *context = new GHOST_ContextGLX(
1249                         m_wantStereoVisual,
1250                         m_wantNumOfAASamples,
1251                         m_window,
1252                         m_display,
1253                         m_visualInfo,
1254                         GLX_CONTEXT_ES2_PROFILE_BIT_EXT,
1255                         2, 0,
1256                         GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
1257                         GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
1258 #elif defined(WITH_GL_PROFILE_COMPAT)
1259                 GHOST_Context *context = new GHOST_ContextGLX(
1260                         m_wantStereoVisual,
1261                         m_wantNumOfAASamples,
1262                         m_window,
1263                         m_display,
1264                         m_visualInfo,
1265                         0, // profile bit
1266                         0, 0,
1267                         GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
1268                         GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
1269 #else
1270 #  error
1271 #endif
1272
1273 #else
1274
1275 #if defined(WITH_GL_PROFILE_CORE)
1276                 GHOST_Context *context = new GHOST_ContextEGL(
1277                         m_wantStereoVisual,
1278                         m_wantNumOfAASamples,
1279                         m_window,
1280                         m_display,
1281                         EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
1282                         3, 2,
1283                         GHOST_OPENGL_EGL_CONTEXT_FLAGS,
1284                         GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
1285                         EGL_OPENGL_API);
1286 #elif defined(WITH_GL_PROFILE_ES20)
1287                 GHOST_Context *context = new GHOST_ContextEGL(
1288                         m_wantStereoVisual,
1289                         m_wantNumOfAASamples,
1290                         m_window,
1291                         m_display,
1292                         0, // profile bit
1293                         2, 0,
1294                         GHOST_OPENGL_EGL_CONTEXT_FLAGS,
1295                         GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
1296                         EGL_OPENGL_ES_API);
1297 #elif defined(WITH_GL_PROFILE_COMPAT)
1298                 GHOST_Context *context = new GHOST_ContextEGL(
1299                         m_wantStereoVisual,
1300                         m_wantNumOfAASamples,
1301                         m_window,
1302                         m_display,
1303                         0, // profile bit
1304                         0, 0,
1305                         GHOST_OPENGL_EGL_CONTEXT_FLAGS,
1306                         GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
1307                         EGL_OPENGL_API);
1308 #else
1309 #  error
1310 #endif
1311
1312 #endif
1313                 if (context->initializeDrawingContext())
1314                         return context;
1315                 else
1316                         delete context;
1317         }
1318
1319         return NULL;
1320 }
1321
1322
1323 Cursor
1324 GHOST_WindowX11::
1325 getStandardCursor(
1326                 GHOST_TStandardCursor g_cursor)
1327 {
1328         unsigned int xcursor_id;
1329
1330 #define GtoX(gcurs, xcurs)  case gcurs: xcursor_id = xcurs
1331         switch (g_cursor) {
1332                 GtoX(GHOST_kStandardCursorRightArrow, XC_arrow); break;
1333                 GtoX(GHOST_kStandardCursorLeftArrow, XC_top_left_arrow); break;
1334                 GtoX(GHOST_kStandardCursorInfo, XC_hand1); break;
1335                 GtoX(GHOST_kStandardCursorDestroy, XC_pirate); break;
1336                 GtoX(GHOST_kStandardCursorHelp, XC_question_arrow); break;
1337                 GtoX(GHOST_kStandardCursorCycle, XC_exchange); break;
1338                 GtoX(GHOST_kStandardCursorSpray, XC_spraycan); break;
1339                 GtoX(GHOST_kStandardCursorWait, XC_watch); break;
1340                 GtoX(GHOST_kStandardCursorText, XC_xterm); break;
1341                 GtoX(GHOST_kStandardCursorCrosshair, XC_crosshair); break;
1342                 GtoX(GHOST_kStandardCursorUpDown, XC_sb_v_double_arrow); break;
1343                 GtoX(GHOST_kStandardCursorLeftRight, XC_sb_h_double_arrow); break;
1344                 GtoX(GHOST_kStandardCursorTopSide, XC_top_side); break;
1345                 GtoX(GHOST_kStandardCursorBottomSide, XC_bottom_side); break;
1346                 GtoX(GHOST_kStandardCursorLeftSide, XC_left_side); break;
1347                 GtoX(GHOST_kStandardCursorRightSide, XC_right_side); break;
1348                 GtoX(GHOST_kStandardCursorTopLeftCorner, XC_top_left_corner); break;
1349                 GtoX(GHOST_kStandardCursorTopRightCorner, XC_top_right_corner); break;
1350                 GtoX(GHOST_kStandardCursorBottomRightCorner, XC_bottom_right_corner); break;
1351                 GtoX(GHOST_kStandardCursorBottomLeftCorner, XC_bottom_left_corner); break;
1352                 GtoX(GHOST_kStandardCursorPencil, XC_pencil); break;
1353                 GtoX(GHOST_kStandardCursorCopy, XC_arrow); break;
1354                 default:
1355                         xcursor_id = 0;
1356         }
1357 #undef GtoX
1358
1359         if (xcursor_id) {
1360                 Cursor xcursor = m_standard_cursors[xcursor_id];
1361                 
1362                 if (!xcursor) {
1363                         xcursor = XCreateFontCursor(m_display, xcursor_id);
1364
1365                         m_standard_cursors[xcursor_id] = xcursor;
1366                 }
1367                 
1368                 return xcursor;
1369         }
1370         else {
1371                 return None;
1372         }
1373 }
1374
1375 Cursor
1376 GHOST_WindowX11::
1377 getEmptyCursor(
1378         ) {
1379         if (!m_empty_cursor) {
1380                 Pixmap blank;
1381                 XColor dummy = {0};
1382                 char data[1] = {0};
1383                         
1384                 /* make a blank cursor */
1385                 blank = XCreateBitmapFromData(
1386                     m_display,
1387                     RootWindow(m_display, m_visualInfo->screen),
1388                     data, 1, 1
1389                     );
1390
1391                 m_empty_cursor = XCreatePixmapCursor(m_display, blank, blank, &dummy, &dummy, 0, 0);
1392                 XFreePixmap(m_display, blank);
1393         }
1394
1395         return m_empty_cursor;
1396 }
1397
1398 GHOST_TSuccess
1399 GHOST_WindowX11::
1400 setWindowCursorVisibility(
1401                 bool visible)
1402 {
1403         Cursor xcursor;
1404         
1405         if (visible) {
1406                 if (m_visible_cursor)
1407                         xcursor = m_visible_cursor;
1408                 else
1409                         xcursor = getStandardCursor(getCursorShape() );
1410         }
1411         else {
1412                 xcursor = getEmptyCursor();
1413         }
1414
1415         XDefineCursor(m_display, m_window, xcursor);
1416         XFlush(m_display);
1417         
1418         return GHOST_kSuccess;
1419 }
1420
1421 GHOST_TSuccess
1422 GHOST_WindowX11::
1423 setWindowCursorGrab(
1424                 GHOST_TGrabCursorMode mode)
1425 {
1426         if (mode != GHOST_kGrabDisable) {
1427                 if (mode != GHOST_kGrabNormal) {
1428                         m_system->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
1429                         setCursorGrabAccum(0, 0);
1430
1431                         if (mode == GHOST_kGrabHide)
1432                                 setWindowCursorVisibility(false);
1433
1434                 }
1435 #ifdef GHOST_X11_GRAB
1436                 XGrabPointer(m_display, m_window, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
1437                              GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
1438 #endif
1439         }
1440         else {
1441                 if (m_cursorGrab == GHOST_kGrabHide) {
1442                         m_system->setCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
1443                         setWindowCursorVisibility(true);
1444                 }
1445
1446                 if (m_cursorGrab != GHOST_kGrabNormal) {
1447                         /* use to generate a mouse move event, otherwise the last event
1448                          * blender gets can be outside the screen causing menus not to show
1449                          * properly unless the user moves the mouse */
1450                         XWarpPointer(m_display, None, None, 0, 0, 0, 0, 0, 0);
1451                 }
1452
1453                 /* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
1454                 setCursorGrabAccum(0, 0);
1455                 m_cursorGrabBounds.m_l = m_cursorGrabBounds.m_r = -1; /* disable */
1456 #ifdef GHOST_X11_GRAB
1457                 XUngrabPointer(m_display, CurrentTime);
1458 #endif
1459         }
1460
1461         XFlush(m_display);
1462         
1463         return GHOST_kSuccess;
1464 }
1465
1466 GHOST_TSuccess
1467 GHOST_WindowX11::
1468 setWindowCursorShape(
1469                 GHOST_TStandardCursor shape)
1470 {
1471         Cursor xcursor = getStandardCursor(shape);
1472
1473         m_visible_cursor = xcursor;
1474         
1475         XDefineCursor(m_display, m_window, xcursor);
1476         XFlush(m_display);
1477
1478         return GHOST_kSuccess;
1479 }
1480
1481 GHOST_TSuccess
1482 GHOST_WindowX11::
1483 setWindowCustomCursorShape(
1484                 GHOST_TUns8 bitmap[16][2],
1485                 GHOST_TUns8 mask[16][2],
1486                 int hotX,
1487                 int hotY)
1488 {
1489         setWindowCustomCursorShape((GHOST_TUns8 *)bitmap, (GHOST_TUns8 *)mask,
1490                                    16, 16, hotX, hotY, 0, 1);
1491         return GHOST_kSuccess;
1492 }
1493
1494 GHOST_TSuccess
1495 GHOST_WindowX11::
1496 setWindowCustomCursorShape(     
1497                 GHOST_TUns8 *bitmap,
1498                 GHOST_TUns8 *mask,
1499                 int sizex,
1500                 int sizey,
1501                 int hotX,
1502                 int hotY,
1503                 int /*fg_color*/,
1504                 int /*bg_color*/)
1505 {
1506         Colormap colormap = DefaultColormap(m_display, m_visualInfo->screen);
1507         Pixmap bitmap_pix, mask_pix;
1508         XColor fg, bg;
1509         
1510         if (XAllocNamedColor(m_display, colormap, "White", &fg, &fg) == 0) return GHOST_kFailure;
1511         if (XAllocNamedColor(m_display, colormap, "Black", &bg, &bg) == 0) return GHOST_kFailure;
1512
1513         if (m_custom_cursor) {
1514                 XFreeCursor(m_display, m_custom_cursor);
1515         }
1516
1517         bitmap_pix = XCreateBitmapFromData(m_display, m_window, (char *) bitmap, sizex, sizey);
1518         mask_pix = XCreateBitmapFromData(m_display, m_window, (char *) mask, sizex, sizey);
1519                 
1520         m_custom_cursor = XCreatePixmapCursor(m_display, bitmap_pix, mask_pix, &fg, &bg, hotX, hotY);
1521         XDefineCursor(m_display, m_window, m_custom_cursor);
1522         XFlush(m_display);
1523
1524         m_visible_cursor = m_custom_cursor;
1525         
1526         XFreePixmap(m_display, bitmap_pix);
1527         XFreePixmap(m_display, mask_pix);
1528
1529         XFreeColors(m_display, colormap, &fg.pixel, 1, 0L);
1530         XFreeColors(m_display, colormap, &bg.pixel, 1, 0L);
1531
1532         return GHOST_kSuccess;
1533 }
1534
1535
1536 GHOST_TSuccess
1537 GHOST_WindowX11::
1538 beginFullScreen() const
1539 {
1540         {
1541                 Window root_return;
1542                 int x_return, y_return;
1543                 unsigned int w_return, h_return, border_w_return, depth_return;
1544
1545                 XGetGeometry(m_display, m_window, &root_return, &x_return, &y_return,
1546                              &w_return, &h_return, &border_w_return, &depth_return);
1547
1548                 m_system->setCursorPosition(w_return / 2, h_return / 2);
1549         }
1550
1551
1552         /* Grab Keyboard & Mouse */
1553         int err;
1554
1555         err = XGrabKeyboard(m_display, m_window, False,
1556                             GrabModeAsync, GrabModeAsync, CurrentTime);
1557         if (err != GrabSuccess) printf("XGrabKeyboard failed %d\n", err);
1558
1559         err = XGrabPointer(m_display, m_window, False,  PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
1560                            GrabModeAsync, GrabModeAsync, m_window, None, CurrentTime);
1561         if (err != GrabSuccess) printf("XGrabPointer failed %d\n", err);
1562
1563         return GHOST_kSuccess;
1564 }
1565
1566 GHOST_TSuccess
1567 GHOST_WindowX11::
1568 endFullScreen() const
1569 {
1570         XUngrabKeyboard(m_display, CurrentTime);
1571         XUngrabPointer(m_display, CurrentTime);
1572
1573         return GHOST_kSuccess;
1574 }