xref: /aosp_15_r20/external/angle/util/linux/x11/X11Window.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker 
7*8975f5c5SAndroid Build Coastguard Worker // X11Window.cpp: Implementation of OSWindow for X11
8*8975f5c5SAndroid Build Coastguard Worker 
9*8975f5c5SAndroid Build Coastguard Worker #include "util/linux/x11/X11Window.h"
10*8975f5c5SAndroid Build Coastguard Worker 
11*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
12*8975f5c5SAndroid Build Coastguard Worker #include "util/Timer.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "util/test_utils.h"
14*8975f5c5SAndroid Build Coastguard Worker 
15*8975f5c5SAndroid Build Coastguard Worker #include <X11/Xlib.h>
16*8975f5c5SAndroid Build Coastguard Worker #include <X11/Xresource.h>
17*8975f5c5SAndroid Build Coastguard Worker #include <X11/Xutil.h>
18*8975f5c5SAndroid Build Coastguard Worker 
19*8975f5c5SAndroid Build Coastguard Worker namespace
20*8975f5c5SAndroid Build Coastguard Worker {
21*8975f5c5SAndroid Build Coastguard Worker 
WaitForMapNotify(Display * dpy,XEvent * event,XPointer window)22*8975f5c5SAndroid Build Coastguard Worker Bool WaitForMapNotify(Display *dpy, XEvent *event, XPointer window)
23*8975f5c5SAndroid Build Coastguard Worker {
24*8975f5c5SAndroid Build Coastguard Worker     return event->type == MapNotify && event->xmap.window == reinterpret_cast<Window>(window);
25*8975f5c5SAndroid Build Coastguard Worker }
26*8975f5c5SAndroid Build Coastguard Worker 
X11CodeToKey(Display * display,unsigned int scancode)27*8975f5c5SAndroid Build Coastguard Worker static Key X11CodeToKey(Display *display, unsigned int scancode)
28*8975f5c5SAndroid Build Coastguard Worker {
29*8975f5c5SAndroid Build Coastguard Worker     int temp;
30*8975f5c5SAndroid Build Coastguard Worker     KeySym *keySymbols;
31*8975f5c5SAndroid Build Coastguard Worker     keySymbols = XGetKeyboardMapping(display, scancode, 1, &temp);
32*8975f5c5SAndroid Build Coastguard Worker 
33*8975f5c5SAndroid Build Coastguard Worker     KeySym keySymbol = keySymbols[0];
34*8975f5c5SAndroid Build Coastguard Worker     XFree(keySymbols);
35*8975f5c5SAndroid Build Coastguard Worker 
36*8975f5c5SAndroid Build Coastguard Worker     switch (keySymbol)
37*8975f5c5SAndroid Build Coastguard Worker     {
38*8975f5c5SAndroid Build Coastguard Worker         case XK_Shift_L:
39*8975f5c5SAndroid Build Coastguard Worker             return KEY_LSHIFT;
40*8975f5c5SAndroid Build Coastguard Worker         case XK_Shift_R:
41*8975f5c5SAndroid Build Coastguard Worker             return KEY_RSHIFT;
42*8975f5c5SAndroid Build Coastguard Worker         case XK_Alt_L:
43*8975f5c5SAndroid Build Coastguard Worker             return KEY_LALT;
44*8975f5c5SAndroid Build Coastguard Worker         case XK_Alt_R:
45*8975f5c5SAndroid Build Coastguard Worker             return KEY_RALT;
46*8975f5c5SAndroid Build Coastguard Worker         case XK_Control_L:
47*8975f5c5SAndroid Build Coastguard Worker             return KEY_LCONTROL;
48*8975f5c5SAndroid Build Coastguard Worker         case XK_Control_R:
49*8975f5c5SAndroid Build Coastguard Worker             return KEY_RCONTROL;
50*8975f5c5SAndroid Build Coastguard Worker         case XK_Super_L:
51*8975f5c5SAndroid Build Coastguard Worker             return KEY_LSYSTEM;
52*8975f5c5SAndroid Build Coastguard Worker         case XK_Super_R:
53*8975f5c5SAndroid Build Coastguard Worker             return KEY_RSYSTEM;
54*8975f5c5SAndroid Build Coastguard Worker         case XK_Menu:
55*8975f5c5SAndroid Build Coastguard Worker             return KEY_MENU;
56*8975f5c5SAndroid Build Coastguard Worker 
57*8975f5c5SAndroid Build Coastguard Worker         case XK_semicolon:
58*8975f5c5SAndroid Build Coastguard Worker             return KEY_SEMICOLON;
59*8975f5c5SAndroid Build Coastguard Worker         case XK_slash:
60*8975f5c5SAndroid Build Coastguard Worker             return KEY_SLASH;
61*8975f5c5SAndroid Build Coastguard Worker         case XK_equal:
62*8975f5c5SAndroid Build Coastguard Worker             return KEY_EQUAL;
63*8975f5c5SAndroid Build Coastguard Worker         case XK_minus:
64*8975f5c5SAndroid Build Coastguard Worker             return KEY_DASH;
65*8975f5c5SAndroid Build Coastguard Worker         case XK_bracketleft:
66*8975f5c5SAndroid Build Coastguard Worker             return KEY_LBRACKET;
67*8975f5c5SAndroid Build Coastguard Worker         case XK_bracketright:
68*8975f5c5SAndroid Build Coastguard Worker             return KEY_RBRACKET;
69*8975f5c5SAndroid Build Coastguard Worker         case XK_comma:
70*8975f5c5SAndroid Build Coastguard Worker             return KEY_COMMA;
71*8975f5c5SAndroid Build Coastguard Worker         case XK_period:
72*8975f5c5SAndroid Build Coastguard Worker             return KEY_PERIOD;
73*8975f5c5SAndroid Build Coastguard Worker         case XK_backslash:
74*8975f5c5SAndroid Build Coastguard Worker             return KEY_BACKSLASH;
75*8975f5c5SAndroid Build Coastguard Worker         case XK_asciitilde:
76*8975f5c5SAndroid Build Coastguard Worker             return KEY_TILDE;
77*8975f5c5SAndroid Build Coastguard Worker         case XK_Escape:
78*8975f5c5SAndroid Build Coastguard Worker             return KEY_ESCAPE;
79*8975f5c5SAndroid Build Coastguard Worker         case XK_space:
80*8975f5c5SAndroid Build Coastguard Worker             return KEY_SPACE;
81*8975f5c5SAndroid Build Coastguard Worker         case XK_Return:
82*8975f5c5SAndroid Build Coastguard Worker             return KEY_RETURN;
83*8975f5c5SAndroid Build Coastguard Worker         case XK_BackSpace:
84*8975f5c5SAndroid Build Coastguard Worker             return KEY_BACK;
85*8975f5c5SAndroid Build Coastguard Worker         case XK_Tab:
86*8975f5c5SAndroid Build Coastguard Worker             return KEY_TAB;
87*8975f5c5SAndroid Build Coastguard Worker         case XK_Page_Up:
88*8975f5c5SAndroid Build Coastguard Worker             return KEY_PAGEUP;
89*8975f5c5SAndroid Build Coastguard Worker         case XK_Page_Down:
90*8975f5c5SAndroid Build Coastguard Worker             return KEY_PAGEDOWN;
91*8975f5c5SAndroid Build Coastguard Worker         case XK_End:
92*8975f5c5SAndroid Build Coastguard Worker             return KEY_END;
93*8975f5c5SAndroid Build Coastguard Worker         case XK_Home:
94*8975f5c5SAndroid Build Coastguard Worker             return KEY_HOME;
95*8975f5c5SAndroid Build Coastguard Worker         case XK_Insert:
96*8975f5c5SAndroid Build Coastguard Worker             return KEY_INSERT;
97*8975f5c5SAndroid Build Coastguard Worker         case XK_Delete:
98*8975f5c5SAndroid Build Coastguard Worker             return KEY_DELETE;
99*8975f5c5SAndroid Build Coastguard Worker         case XK_KP_Add:
100*8975f5c5SAndroid Build Coastguard Worker             return KEY_ADD;
101*8975f5c5SAndroid Build Coastguard Worker         case XK_KP_Subtract:
102*8975f5c5SAndroid Build Coastguard Worker             return KEY_SUBTRACT;
103*8975f5c5SAndroid Build Coastguard Worker         case XK_KP_Multiply:
104*8975f5c5SAndroid Build Coastguard Worker             return KEY_MULTIPLY;
105*8975f5c5SAndroid Build Coastguard Worker         case XK_KP_Divide:
106*8975f5c5SAndroid Build Coastguard Worker             return KEY_DIVIDE;
107*8975f5c5SAndroid Build Coastguard Worker         case XK_Pause:
108*8975f5c5SAndroid Build Coastguard Worker             return KEY_PAUSE;
109*8975f5c5SAndroid Build Coastguard Worker 
110*8975f5c5SAndroid Build Coastguard Worker         case XK_F1:
111*8975f5c5SAndroid Build Coastguard Worker             return KEY_F1;
112*8975f5c5SAndroid Build Coastguard Worker         case XK_F2:
113*8975f5c5SAndroid Build Coastguard Worker             return KEY_F2;
114*8975f5c5SAndroid Build Coastguard Worker         case XK_F3:
115*8975f5c5SAndroid Build Coastguard Worker             return KEY_F3;
116*8975f5c5SAndroid Build Coastguard Worker         case XK_F4:
117*8975f5c5SAndroid Build Coastguard Worker             return KEY_F4;
118*8975f5c5SAndroid Build Coastguard Worker         case XK_F5:
119*8975f5c5SAndroid Build Coastguard Worker             return KEY_F5;
120*8975f5c5SAndroid Build Coastguard Worker         case XK_F6:
121*8975f5c5SAndroid Build Coastguard Worker             return KEY_F6;
122*8975f5c5SAndroid Build Coastguard Worker         case XK_F7:
123*8975f5c5SAndroid Build Coastguard Worker             return KEY_F7;
124*8975f5c5SAndroid Build Coastguard Worker         case XK_F8:
125*8975f5c5SAndroid Build Coastguard Worker             return KEY_F8;
126*8975f5c5SAndroid Build Coastguard Worker         case XK_F9:
127*8975f5c5SAndroid Build Coastguard Worker             return KEY_F9;
128*8975f5c5SAndroid Build Coastguard Worker         case XK_F10:
129*8975f5c5SAndroid Build Coastguard Worker             return KEY_F10;
130*8975f5c5SAndroid Build Coastguard Worker         case XK_F11:
131*8975f5c5SAndroid Build Coastguard Worker             return KEY_F11;
132*8975f5c5SAndroid Build Coastguard Worker         case XK_F12:
133*8975f5c5SAndroid Build Coastguard Worker             return KEY_F12;
134*8975f5c5SAndroid Build Coastguard Worker         case XK_F13:
135*8975f5c5SAndroid Build Coastguard Worker             return KEY_F13;
136*8975f5c5SAndroid Build Coastguard Worker         case XK_F14:
137*8975f5c5SAndroid Build Coastguard Worker             return KEY_F14;
138*8975f5c5SAndroid Build Coastguard Worker         case XK_F15:
139*8975f5c5SAndroid Build Coastguard Worker             return KEY_F15;
140*8975f5c5SAndroid Build Coastguard Worker 
141*8975f5c5SAndroid Build Coastguard Worker         case XK_Left:
142*8975f5c5SAndroid Build Coastguard Worker             return KEY_LEFT;
143*8975f5c5SAndroid Build Coastguard Worker         case XK_Right:
144*8975f5c5SAndroid Build Coastguard Worker             return KEY_RIGHT;
145*8975f5c5SAndroid Build Coastguard Worker         case XK_Down:
146*8975f5c5SAndroid Build Coastguard Worker             return KEY_DOWN;
147*8975f5c5SAndroid Build Coastguard Worker         case XK_Up:
148*8975f5c5SAndroid Build Coastguard Worker             return KEY_UP;
149*8975f5c5SAndroid Build Coastguard Worker 
150*8975f5c5SAndroid Build Coastguard Worker         case XK_KP_Insert:
151*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUMPAD0;
152*8975f5c5SAndroid Build Coastguard Worker         case XK_KP_End:
153*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUMPAD1;
154*8975f5c5SAndroid Build Coastguard Worker         case XK_KP_Down:
155*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUMPAD2;
156*8975f5c5SAndroid Build Coastguard Worker         case XK_KP_Page_Down:
157*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUMPAD3;
158*8975f5c5SAndroid Build Coastguard Worker         case XK_KP_Left:
159*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUMPAD4;
160*8975f5c5SAndroid Build Coastguard Worker         case XK_KP_5:
161*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUMPAD5;
162*8975f5c5SAndroid Build Coastguard Worker         case XK_KP_Right:
163*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUMPAD6;
164*8975f5c5SAndroid Build Coastguard Worker         case XK_KP_Home:
165*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUMPAD7;
166*8975f5c5SAndroid Build Coastguard Worker         case XK_KP_Up:
167*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUMPAD8;
168*8975f5c5SAndroid Build Coastguard Worker         case XK_KP_Page_Up:
169*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUMPAD9;
170*8975f5c5SAndroid Build Coastguard Worker 
171*8975f5c5SAndroid Build Coastguard Worker         case XK_a:
172*8975f5c5SAndroid Build Coastguard Worker             return KEY_A;
173*8975f5c5SAndroid Build Coastguard Worker         case XK_b:
174*8975f5c5SAndroid Build Coastguard Worker             return KEY_B;
175*8975f5c5SAndroid Build Coastguard Worker         case XK_c:
176*8975f5c5SAndroid Build Coastguard Worker             return KEY_C;
177*8975f5c5SAndroid Build Coastguard Worker         case XK_d:
178*8975f5c5SAndroid Build Coastguard Worker             return KEY_D;
179*8975f5c5SAndroid Build Coastguard Worker         case XK_e:
180*8975f5c5SAndroid Build Coastguard Worker             return KEY_E;
181*8975f5c5SAndroid Build Coastguard Worker         case XK_f:
182*8975f5c5SAndroid Build Coastguard Worker             return KEY_F;
183*8975f5c5SAndroid Build Coastguard Worker         case XK_g:
184*8975f5c5SAndroid Build Coastguard Worker             return KEY_G;
185*8975f5c5SAndroid Build Coastguard Worker         case XK_h:
186*8975f5c5SAndroid Build Coastguard Worker             return KEY_H;
187*8975f5c5SAndroid Build Coastguard Worker         case XK_i:
188*8975f5c5SAndroid Build Coastguard Worker             return KEY_I;
189*8975f5c5SAndroid Build Coastguard Worker         case XK_j:
190*8975f5c5SAndroid Build Coastguard Worker             return KEY_J;
191*8975f5c5SAndroid Build Coastguard Worker         case XK_k:
192*8975f5c5SAndroid Build Coastguard Worker             return KEY_K;
193*8975f5c5SAndroid Build Coastguard Worker         case XK_l:
194*8975f5c5SAndroid Build Coastguard Worker             return KEY_L;
195*8975f5c5SAndroid Build Coastguard Worker         case XK_m:
196*8975f5c5SAndroid Build Coastguard Worker             return KEY_M;
197*8975f5c5SAndroid Build Coastguard Worker         case XK_n:
198*8975f5c5SAndroid Build Coastguard Worker             return KEY_N;
199*8975f5c5SAndroid Build Coastguard Worker         case XK_o:
200*8975f5c5SAndroid Build Coastguard Worker             return KEY_O;
201*8975f5c5SAndroid Build Coastguard Worker         case XK_p:
202*8975f5c5SAndroid Build Coastguard Worker             return KEY_P;
203*8975f5c5SAndroid Build Coastguard Worker         case XK_q:
204*8975f5c5SAndroid Build Coastguard Worker             return KEY_Q;
205*8975f5c5SAndroid Build Coastguard Worker         case XK_r:
206*8975f5c5SAndroid Build Coastguard Worker             return KEY_R;
207*8975f5c5SAndroid Build Coastguard Worker         case XK_s:
208*8975f5c5SAndroid Build Coastguard Worker             return KEY_S;
209*8975f5c5SAndroid Build Coastguard Worker         case XK_t:
210*8975f5c5SAndroid Build Coastguard Worker             return KEY_T;
211*8975f5c5SAndroid Build Coastguard Worker         case XK_u:
212*8975f5c5SAndroid Build Coastguard Worker             return KEY_U;
213*8975f5c5SAndroid Build Coastguard Worker         case XK_v:
214*8975f5c5SAndroid Build Coastguard Worker             return KEY_V;
215*8975f5c5SAndroid Build Coastguard Worker         case XK_w:
216*8975f5c5SAndroid Build Coastguard Worker             return KEY_W;
217*8975f5c5SAndroid Build Coastguard Worker         case XK_x:
218*8975f5c5SAndroid Build Coastguard Worker             return KEY_X;
219*8975f5c5SAndroid Build Coastguard Worker         case XK_y:
220*8975f5c5SAndroid Build Coastguard Worker             return KEY_Y;
221*8975f5c5SAndroid Build Coastguard Worker         case XK_z:
222*8975f5c5SAndroid Build Coastguard Worker             return KEY_Z;
223*8975f5c5SAndroid Build Coastguard Worker 
224*8975f5c5SAndroid Build Coastguard Worker         case XK_1:
225*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUM1;
226*8975f5c5SAndroid Build Coastguard Worker         case XK_2:
227*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUM2;
228*8975f5c5SAndroid Build Coastguard Worker         case XK_3:
229*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUM3;
230*8975f5c5SAndroid Build Coastguard Worker         case XK_4:
231*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUM4;
232*8975f5c5SAndroid Build Coastguard Worker         case XK_5:
233*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUM5;
234*8975f5c5SAndroid Build Coastguard Worker         case XK_6:
235*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUM6;
236*8975f5c5SAndroid Build Coastguard Worker         case XK_7:
237*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUM7;
238*8975f5c5SAndroid Build Coastguard Worker         case XK_8:
239*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUM8;
240*8975f5c5SAndroid Build Coastguard Worker         case XK_9:
241*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUM9;
242*8975f5c5SAndroid Build Coastguard Worker         case XK_0:
243*8975f5c5SAndroid Build Coastguard Worker             return KEY_NUM0;
244*8975f5c5SAndroid Build Coastguard Worker     }
245*8975f5c5SAndroid Build Coastguard Worker 
246*8975f5c5SAndroid Build Coastguard Worker     return Key(0);
247*8975f5c5SAndroid Build Coastguard Worker }
248*8975f5c5SAndroid Build Coastguard Worker 
AddX11KeyStateToEvent(Event * event,unsigned int state)249*8975f5c5SAndroid Build Coastguard Worker static void AddX11KeyStateToEvent(Event *event, unsigned int state)
250*8975f5c5SAndroid Build Coastguard Worker {
251*8975f5c5SAndroid Build Coastguard Worker     event->Key.Shift   = state & ShiftMask;
252*8975f5c5SAndroid Build Coastguard Worker     event->Key.Control = state & ControlMask;
253*8975f5c5SAndroid Build Coastguard Worker     event->Key.Alt     = state & Mod1Mask;
254*8975f5c5SAndroid Build Coastguard Worker     event->Key.System  = state & Mod4Mask;
255*8975f5c5SAndroid Build Coastguard Worker }
256*8975f5c5SAndroid Build Coastguard Worker 
setWindowSizeHints(Display * display,Window window,int width,int height)257*8975f5c5SAndroid Build Coastguard Worker void setWindowSizeHints(Display *display, Window window, int width, int height)
258*8975f5c5SAndroid Build Coastguard Worker {
259*8975f5c5SAndroid Build Coastguard Worker     // Set PMinSize and PMaxSize on XSizeHints so windows larger than the screen do not get adjusted
260*8975f5c5SAndroid Build Coastguard Worker     // to screen size
261*8975f5c5SAndroid Build Coastguard Worker     XSizeHints *sizeHints = XAllocSizeHints();
262*8975f5c5SAndroid Build Coastguard Worker     sizeHints->flags      = PMinSize | PMaxSize;
263*8975f5c5SAndroid Build Coastguard Worker     sizeHints->min_width  = width;
264*8975f5c5SAndroid Build Coastguard Worker     sizeHints->min_height = height;
265*8975f5c5SAndroid Build Coastguard Worker     sizeHints->max_width  = width;
266*8975f5c5SAndroid Build Coastguard Worker     sizeHints->max_height = height;
267*8975f5c5SAndroid Build Coastguard Worker 
268*8975f5c5SAndroid Build Coastguard Worker     XSetWMNormalHints(display, window, sizeHints);
269*8975f5c5SAndroid Build Coastguard Worker 
270*8975f5c5SAndroid Build Coastguard Worker     XFree(sizeHints);
271*8975f5c5SAndroid Build Coastguard Worker }
272*8975f5c5SAndroid Build Coastguard Worker 
273*8975f5c5SAndroid Build Coastguard Worker }  // namespace
274*8975f5c5SAndroid Build Coastguard Worker 
275*8975f5c5SAndroid Build Coastguard Worker class ANGLE_UTIL_EXPORT X11Window : public OSWindow
276*8975f5c5SAndroid Build Coastguard Worker {
277*8975f5c5SAndroid Build Coastguard Worker   public:
278*8975f5c5SAndroid Build Coastguard Worker     X11Window();
279*8975f5c5SAndroid Build Coastguard Worker     X11Window(int visualId);
280*8975f5c5SAndroid Build Coastguard Worker     ~X11Window() override;
281*8975f5c5SAndroid Build Coastguard Worker 
282*8975f5c5SAndroid Build Coastguard Worker     void disableErrorMessageDialog() override;
283*8975f5c5SAndroid Build Coastguard Worker     void destroy() override;
284*8975f5c5SAndroid Build Coastguard Worker 
285*8975f5c5SAndroid Build Coastguard Worker     void resetNativeWindow() override;
286*8975f5c5SAndroid Build Coastguard Worker     EGLNativeWindowType getNativeWindow() const override;
287*8975f5c5SAndroid Build Coastguard Worker     void *getPlatformExtension() override;
288*8975f5c5SAndroid Build Coastguard Worker     EGLNativeDisplayType getNativeDisplay() const override;
289*8975f5c5SAndroid Build Coastguard Worker 
290*8975f5c5SAndroid Build Coastguard Worker     void messageLoop() override;
291*8975f5c5SAndroid Build Coastguard Worker 
292*8975f5c5SAndroid Build Coastguard Worker     void setMousePosition(int x, int y) override;
293*8975f5c5SAndroid Build Coastguard Worker     bool setOrientation(int width, int height) override;
294*8975f5c5SAndroid Build Coastguard Worker     bool setPosition(int x, int y) override;
295*8975f5c5SAndroid Build Coastguard Worker     bool resize(int width, int height) override;
296*8975f5c5SAndroid Build Coastguard Worker     void setVisible(bool isVisible) override;
297*8975f5c5SAndroid Build Coastguard Worker 
298*8975f5c5SAndroid Build Coastguard Worker     void signalTestEvent() override;
299*8975f5c5SAndroid Build Coastguard Worker 
300*8975f5c5SAndroid Build Coastguard Worker   private:
301*8975f5c5SAndroid Build Coastguard Worker     bool initializeImpl(const std::string &name, int width, int height) override;
302*8975f5c5SAndroid Build Coastguard Worker     void processEvent(const XEvent &event);
303*8975f5c5SAndroid Build Coastguard Worker 
304*8975f5c5SAndroid Build Coastguard Worker     Atom WM_DELETE_WINDOW;
305*8975f5c5SAndroid Build Coastguard Worker     Atom WM_PROTOCOLS;
306*8975f5c5SAndroid Build Coastguard Worker     Atom TEST_EVENT;
307*8975f5c5SAndroid Build Coastguard Worker 
308*8975f5c5SAndroid Build Coastguard Worker     Display *mDisplay;
309*8975f5c5SAndroid Build Coastguard Worker     Window mWindow;
310*8975f5c5SAndroid Build Coastguard Worker     int mRequestedVisualId;
311*8975f5c5SAndroid Build Coastguard Worker     bool mVisible;
312*8975f5c5SAndroid Build Coastguard Worker     bool mConfigured = false;
313*8975f5c5SAndroid Build Coastguard Worker     bool mDestroyed  = false;
314*8975f5c5SAndroid Build Coastguard Worker };
315*8975f5c5SAndroid Build Coastguard Worker 
X11Window()316*8975f5c5SAndroid Build Coastguard Worker X11Window::X11Window()
317*8975f5c5SAndroid Build Coastguard Worker     : WM_DELETE_WINDOW(None),
318*8975f5c5SAndroid Build Coastguard Worker       WM_PROTOCOLS(None),
319*8975f5c5SAndroid Build Coastguard Worker       TEST_EVENT(None),
320*8975f5c5SAndroid Build Coastguard Worker       mDisplay(nullptr),
321*8975f5c5SAndroid Build Coastguard Worker       mWindow(0),
322*8975f5c5SAndroid Build Coastguard Worker       mRequestedVisualId(-1),
323*8975f5c5SAndroid Build Coastguard Worker       mVisible(false)
324*8975f5c5SAndroid Build Coastguard Worker {}
325*8975f5c5SAndroid Build Coastguard Worker 
X11Window(int visualId)326*8975f5c5SAndroid Build Coastguard Worker X11Window::X11Window(int visualId)
327*8975f5c5SAndroid Build Coastguard Worker     : WM_DELETE_WINDOW(None),
328*8975f5c5SAndroid Build Coastguard Worker       WM_PROTOCOLS(None),
329*8975f5c5SAndroid Build Coastguard Worker       TEST_EVENT(None),
330*8975f5c5SAndroid Build Coastguard Worker       mDisplay(nullptr),
331*8975f5c5SAndroid Build Coastguard Worker       mWindow(0),
332*8975f5c5SAndroid Build Coastguard Worker       mRequestedVisualId(visualId),
333*8975f5c5SAndroid Build Coastguard Worker       mVisible(false)
334*8975f5c5SAndroid Build Coastguard Worker {}
335*8975f5c5SAndroid Build Coastguard Worker 
~X11Window()336*8975f5c5SAndroid Build Coastguard Worker X11Window::~X11Window()
337*8975f5c5SAndroid Build Coastguard Worker {
338*8975f5c5SAndroid Build Coastguard Worker     destroy();
339*8975f5c5SAndroid Build Coastguard Worker }
340*8975f5c5SAndroid Build Coastguard Worker 
initializeImpl(const std::string & name,int width,int height)341*8975f5c5SAndroid Build Coastguard Worker bool X11Window::initializeImpl(const std::string &name, int width, int height)
342*8975f5c5SAndroid Build Coastguard Worker {
343*8975f5c5SAndroid Build Coastguard Worker     destroy();
344*8975f5c5SAndroid Build Coastguard Worker 
345*8975f5c5SAndroid Build Coastguard Worker     mDisplay = XOpenDisplay(nullptr);
346*8975f5c5SAndroid Build Coastguard Worker     if (!mDisplay)
347*8975f5c5SAndroid Build Coastguard Worker     {
348*8975f5c5SAndroid Build Coastguard Worker         return false;
349*8975f5c5SAndroid Build Coastguard Worker     }
350*8975f5c5SAndroid Build Coastguard Worker 
351*8975f5c5SAndroid Build Coastguard Worker     {
352*8975f5c5SAndroid Build Coastguard Worker         int screen  = DefaultScreen(mDisplay);
353*8975f5c5SAndroid Build Coastguard Worker         Window root = RootWindow(mDisplay, screen);
354*8975f5c5SAndroid Build Coastguard Worker 
355*8975f5c5SAndroid Build Coastguard Worker         Visual *visual;
356*8975f5c5SAndroid Build Coastguard Worker         if (mRequestedVisualId == -1)
357*8975f5c5SAndroid Build Coastguard Worker         {
358*8975f5c5SAndroid Build Coastguard Worker             visual = DefaultVisual(mDisplay, screen);
359*8975f5c5SAndroid Build Coastguard Worker         }
360*8975f5c5SAndroid Build Coastguard Worker         else
361*8975f5c5SAndroid Build Coastguard Worker         {
362*8975f5c5SAndroid Build Coastguard Worker             XVisualInfo visualTemplate;
363*8975f5c5SAndroid Build Coastguard Worker             visualTemplate.visualid = mRequestedVisualId;
364*8975f5c5SAndroid Build Coastguard Worker 
365*8975f5c5SAndroid Build Coastguard Worker             int numVisuals = 0;
366*8975f5c5SAndroid Build Coastguard Worker             XVisualInfo *visuals =
367*8975f5c5SAndroid Build Coastguard Worker                 XGetVisualInfo(mDisplay, VisualIDMask, &visualTemplate, &numVisuals);
368*8975f5c5SAndroid Build Coastguard Worker             if (numVisuals <= 0)
369*8975f5c5SAndroid Build Coastguard Worker             {
370*8975f5c5SAndroid Build Coastguard Worker                 return false;
371*8975f5c5SAndroid Build Coastguard Worker             }
372*8975f5c5SAndroid Build Coastguard Worker             ASSERT(numVisuals == 1);
373*8975f5c5SAndroid Build Coastguard Worker 
374*8975f5c5SAndroid Build Coastguard Worker             visual = visuals[0].visual;
375*8975f5c5SAndroid Build Coastguard Worker             XFree(visuals);
376*8975f5c5SAndroid Build Coastguard Worker         }
377*8975f5c5SAndroid Build Coastguard Worker 
378*8975f5c5SAndroid Build Coastguard Worker         int depth         = DefaultDepth(mDisplay, screen);
379*8975f5c5SAndroid Build Coastguard Worker         Colormap colormap = XCreateColormap(mDisplay, root, visual, AllocNone);
380*8975f5c5SAndroid Build Coastguard Worker 
381*8975f5c5SAndroid Build Coastguard Worker         XSetWindowAttributes attributes;
382*8975f5c5SAndroid Build Coastguard Worker         unsigned long attributeMask = CWBorderPixel | CWColormap | CWEventMask;
383*8975f5c5SAndroid Build Coastguard Worker 
384*8975f5c5SAndroid Build Coastguard Worker         attributes.event_mask = StructureNotifyMask | PointerMotionMask | ButtonPressMask |
385*8975f5c5SAndroid Build Coastguard Worker                                 ButtonReleaseMask | FocusChangeMask | EnterWindowMask |
386*8975f5c5SAndroid Build Coastguard Worker                                 LeaveWindowMask | KeyPressMask | KeyReleaseMask;
387*8975f5c5SAndroid Build Coastguard Worker         attributes.border_pixel = 0;
388*8975f5c5SAndroid Build Coastguard Worker         attributes.colormap     = colormap;
389*8975f5c5SAndroid Build Coastguard Worker 
390*8975f5c5SAndroid Build Coastguard Worker         mWindow = XCreateWindow(mDisplay, root, 0, 0, width, height, 0, depth, InputOutput, visual,
391*8975f5c5SAndroid Build Coastguard Worker                                 attributeMask, &attributes);
392*8975f5c5SAndroid Build Coastguard Worker         XFreeColormap(mDisplay, colormap);
393*8975f5c5SAndroid Build Coastguard Worker     }
394*8975f5c5SAndroid Build Coastguard Worker 
395*8975f5c5SAndroid Build Coastguard Worker     if (!mWindow)
396*8975f5c5SAndroid Build Coastguard Worker     {
397*8975f5c5SAndroid Build Coastguard Worker         destroy();
398*8975f5c5SAndroid Build Coastguard Worker         return false;
399*8975f5c5SAndroid Build Coastguard Worker     }
400*8975f5c5SAndroid Build Coastguard Worker 
401*8975f5c5SAndroid Build Coastguard Worker     // Tell the window manager to notify us when the user wants to close the
402*8975f5c5SAndroid Build Coastguard Worker     // window so we can do it ourselves.
403*8975f5c5SAndroid Build Coastguard Worker     WM_DELETE_WINDOW = XInternAtom(mDisplay, "WM_DELETE_WINDOW", False);
404*8975f5c5SAndroid Build Coastguard Worker     WM_PROTOCOLS     = XInternAtom(mDisplay, "WM_PROTOCOLS", False);
405*8975f5c5SAndroid Build Coastguard Worker     if (WM_DELETE_WINDOW == None || WM_PROTOCOLS == None)
406*8975f5c5SAndroid Build Coastguard Worker     {
407*8975f5c5SAndroid Build Coastguard Worker         destroy();
408*8975f5c5SAndroid Build Coastguard Worker         return false;
409*8975f5c5SAndroid Build Coastguard Worker     }
410*8975f5c5SAndroid Build Coastguard Worker 
411*8975f5c5SAndroid Build Coastguard Worker     if (XSetWMProtocols(mDisplay, mWindow, &WM_DELETE_WINDOW, 1) == 0)
412*8975f5c5SAndroid Build Coastguard Worker     {
413*8975f5c5SAndroid Build Coastguard Worker         destroy();
414*8975f5c5SAndroid Build Coastguard Worker         return false;
415*8975f5c5SAndroid Build Coastguard Worker     }
416*8975f5c5SAndroid Build Coastguard Worker 
417*8975f5c5SAndroid Build Coastguard Worker     // Create an atom to identify our test event
418*8975f5c5SAndroid Build Coastguard Worker     TEST_EVENT = XInternAtom(mDisplay, "ANGLE_TEST_EVENT", False);
419*8975f5c5SAndroid Build Coastguard Worker     if (TEST_EVENT == None)
420*8975f5c5SAndroid Build Coastguard Worker     {
421*8975f5c5SAndroid Build Coastguard Worker         destroy();
422*8975f5c5SAndroid Build Coastguard Worker         return false;
423*8975f5c5SAndroid Build Coastguard Worker     }
424*8975f5c5SAndroid Build Coastguard Worker 
425*8975f5c5SAndroid Build Coastguard Worker     setWindowSizeHints(mDisplay, mWindow, width, height);
426*8975f5c5SAndroid Build Coastguard Worker 
427*8975f5c5SAndroid Build Coastguard Worker     XFlush(mDisplay);
428*8975f5c5SAndroid Build Coastguard Worker 
429*8975f5c5SAndroid Build Coastguard Worker     mX      = 0;
430*8975f5c5SAndroid Build Coastguard Worker     mY      = 0;
431*8975f5c5SAndroid Build Coastguard Worker     mWidth  = width;
432*8975f5c5SAndroid Build Coastguard Worker     mHeight = height;
433*8975f5c5SAndroid Build Coastguard Worker 
434*8975f5c5SAndroid Build Coastguard Worker     return true;
435*8975f5c5SAndroid Build Coastguard Worker }
436*8975f5c5SAndroid Build Coastguard Worker 
disableErrorMessageDialog()437*8975f5c5SAndroid Build Coastguard Worker void X11Window::disableErrorMessageDialog() {}
438*8975f5c5SAndroid Build Coastguard Worker 
destroy()439*8975f5c5SAndroid Build Coastguard Worker void X11Window::destroy()
440*8975f5c5SAndroid Build Coastguard Worker {
441*8975f5c5SAndroid Build Coastguard Worker     if (mWindow)
442*8975f5c5SAndroid Build Coastguard Worker     {
443*8975f5c5SAndroid Build Coastguard Worker         XDestroyWindow(mDisplay, mWindow);
444*8975f5c5SAndroid Build Coastguard Worker         XFlush(mDisplay);
445*8975f5c5SAndroid Build Coastguard Worker         // There appears to be a race condition where XDestroyWindow+XCreateWindow ignores
446*8975f5c5SAndroid Build Coastguard Worker         // the new size (the same window normally gets reused but this only happens sometimes on
447*8975f5c5SAndroid Build Coastguard Worker         // some X11 versions). Wait until we get the destroy notification.
448*8975f5c5SAndroid Build Coastguard Worker         mWindow = 0;  // Set before messageLoop() to avoid a race in processEvent().
449*8975f5c5SAndroid Build Coastguard Worker         while (!mDestroyed)
450*8975f5c5SAndroid Build Coastguard Worker         {
451*8975f5c5SAndroid Build Coastguard Worker             messageLoop();
452*8975f5c5SAndroid Build Coastguard Worker             angle::Sleep(10);
453*8975f5c5SAndroid Build Coastguard Worker         }
454*8975f5c5SAndroid Build Coastguard Worker     }
455*8975f5c5SAndroid Build Coastguard Worker     if (mDisplay)
456*8975f5c5SAndroid Build Coastguard Worker     {
457*8975f5c5SAndroid Build Coastguard Worker         XCloseDisplay(mDisplay);
458*8975f5c5SAndroid Build Coastguard Worker         mDisplay = nullptr;
459*8975f5c5SAndroid Build Coastguard Worker     }
460*8975f5c5SAndroid Build Coastguard Worker     WM_DELETE_WINDOW = None;
461*8975f5c5SAndroid Build Coastguard Worker     WM_PROTOCOLS     = None;
462*8975f5c5SAndroid Build Coastguard Worker }
463*8975f5c5SAndroid Build Coastguard Worker 
resetNativeWindow()464*8975f5c5SAndroid Build Coastguard Worker void X11Window::resetNativeWindow() {}
465*8975f5c5SAndroid Build Coastguard Worker 
getNativeWindow() const466*8975f5c5SAndroid Build Coastguard Worker EGLNativeWindowType X11Window::getNativeWindow() const
467*8975f5c5SAndroid Build Coastguard Worker {
468*8975f5c5SAndroid Build Coastguard Worker     return mWindow;
469*8975f5c5SAndroid Build Coastguard Worker }
470*8975f5c5SAndroid Build Coastguard Worker 
getPlatformExtension()471*8975f5c5SAndroid Build Coastguard Worker void *X11Window::getPlatformExtension()
472*8975f5c5SAndroid Build Coastguard Worker {
473*8975f5c5SAndroid Build Coastguard Worker     // X11 native window for eglCreateSurfacePlatformEXT is Window*
474*8975f5c5SAndroid Build Coastguard Worker     return &mWindow;
475*8975f5c5SAndroid Build Coastguard Worker }
476*8975f5c5SAndroid Build Coastguard Worker 
getNativeDisplay() const477*8975f5c5SAndroid Build Coastguard Worker EGLNativeDisplayType X11Window::getNativeDisplay() const
478*8975f5c5SAndroid Build Coastguard Worker {
479*8975f5c5SAndroid Build Coastguard Worker     return reinterpret_cast<EGLNativeDisplayType>(mDisplay);
480*8975f5c5SAndroid Build Coastguard Worker }
481*8975f5c5SAndroid Build Coastguard Worker 
messageLoop()482*8975f5c5SAndroid Build Coastguard Worker void X11Window::messageLoop()
483*8975f5c5SAndroid Build Coastguard Worker {
484*8975f5c5SAndroid Build Coastguard Worker     int eventCount = XPending(mDisplay);
485*8975f5c5SAndroid Build Coastguard Worker     while (eventCount--)
486*8975f5c5SAndroid Build Coastguard Worker     {
487*8975f5c5SAndroid Build Coastguard Worker         XEvent event;
488*8975f5c5SAndroid Build Coastguard Worker         XNextEvent(mDisplay, &event);
489*8975f5c5SAndroid Build Coastguard Worker         processEvent(event);
490*8975f5c5SAndroid Build Coastguard Worker     }
491*8975f5c5SAndroid Build Coastguard Worker }
492*8975f5c5SAndroid Build Coastguard Worker 
setMousePosition(int x,int y)493*8975f5c5SAndroid Build Coastguard Worker void X11Window::setMousePosition(int x, int y)
494*8975f5c5SAndroid Build Coastguard Worker {
495*8975f5c5SAndroid Build Coastguard Worker     XWarpPointer(mDisplay, None, mWindow, 0, 0, 0, 0, x, y);
496*8975f5c5SAndroid Build Coastguard Worker }
497*8975f5c5SAndroid Build Coastguard Worker 
setOrientation(int width,int height)498*8975f5c5SAndroid Build Coastguard Worker bool X11Window::setOrientation(int width, int height)
499*8975f5c5SAndroid Build Coastguard Worker {
500*8975f5c5SAndroid Build Coastguard Worker     UNIMPLEMENTED();
501*8975f5c5SAndroid Build Coastguard Worker     return false;
502*8975f5c5SAndroid Build Coastguard Worker }
503*8975f5c5SAndroid Build Coastguard Worker 
setPosition(int x,int y)504*8975f5c5SAndroid Build Coastguard Worker bool X11Window::setPosition(int x, int y)
505*8975f5c5SAndroid Build Coastguard Worker {
506*8975f5c5SAndroid Build Coastguard Worker     XMoveWindow(mDisplay, mWindow, x, y);
507*8975f5c5SAndroid Build Coastguard Worker     XFlush(mDisplay);
508*8975f5c5SAndroid Build Coastguard Worker     return true;
509*8975f5c5SAndroid Build Coastguard Worker }
510*8975f5c5SAndroid Build Coastguard Worker 
resize(int width,int height)511*8975f5c5SAndroid Build Coastguard Worker bool X11Window::resize(int width, int height)
512*8975f5c5SAndroid Build Coastguard Worker {
513*8975f5c5SAndroid Build Coastguard Worker     setWindowSizeHints(mDisplay, mWindow, width, height);
514*8975f5c5SAndroid Build Coastguard Worker     XResizeWindow(mDisplay, mWindow, width, height);
515*8975f5c5SAndroid Build Coastguard Worker 
516*8975f5c5SAndroid Build Coastguard Worker     XFlush(mDisplay);
517*8975f5c5SAndroid Build Coastguard Worker 
518*8975f5c5SAndroid Build Coastguard Worker     Timer timer;
519*8975f5c5SAndroid Build Coastguard Worker     timer.start();
520*8975f5c5SAndroid Build Coastguard Worker 
521*8975f5c5SAndroid Build Coastguard Worker     // Wait until the window has actually been resized so that the code calling resize
522*8975f5c5SAndroid Build Coastguard Worker     // can assume the window has been resized.
523*8975f5c5SAndroid Build Coastguard Worker     const double kResizeWaitDelay = 0.2;
524*8975f5c5SAndroid Build Coastguard Worker     while ((mHeight != height || mWidth != width) &&
525*8975f5c5SAndroid Build Coastguard Worker            timer.getElapsedWallClockTime() < kResizeWaitDelay)
526*8975f5c5SAndroid Build Coastguard Worker     {
527*8975f5c5SAndroid Build Coastguard Worker         messageLoop();
528*8975f5c5SAndroid Build Coastguard Worker         angle::Sleep(10);
529*8975f5c5SAndroid Build Coastguard Worker     }
530*8975f5c5SAndroid Build Coastguard Worker 
531*8975f5c5SAndroid Build Coastguard Worker     return true;
532*8975f5c5SAndroid Build Coastguard Worker }
533*8975f5c5SAndroid Build Coastguard Worker 
setVisible(bool isVisible)534*8975f5c5SAndroid Build Coastguard Worker void X11Window::setVisible(bool isVisible)
535*8975f5c5SAndroid Build Coastguard Worker {
536*8975f5c5SAndroid Build Coastguard Worker     if (mVisible == isVisible)
537*8975f5c5SAndroid Build Coastguard Worker     {
538*8975f5c5SAndroid Build Coastguard Worker         return;
539*8975f5c5SAndroid Build Coastguard Worker     }
540*8975f5c5SAndroid Build Coastguard Worker 
541*8975f5c5SAndroid Build Coastguard Worker     if (isVisible)
542*8975f5c5SAndroid Build Coastguard Worker     {
543*8975f5c5SAndroid Build Coastguard Worker         XMapWindow(mDisplay, mWindow);
544*8975f5c5SAndroid Build Coastguard Worker 
545*8975f5c5SAndroid Build Coastguard Worker         // Wait until we get an event saying this window is mapped so that the
546*8975f5c5SAndroid Build Coastguard Worker         // code calling setVisible can assume the window is visible.
547*8975f5c5SAndroid Build Coastguard Worker         // This is important when creating a framebuffer as the framebuffer content
548*8975f5c5SAndroid Build Coastguard Worker         // is undefined when the window is not visible.
549*8975f5c5SAndroid Build Coastguard Worker         XEvent placeholderEvent;
550*8975f5c5SAndroid Build Coastguard Worker         XIfEvent(mDisplay, &placeholderEvent, WaitForMapNotify,
551*8975f5c5SAndroid Build Coastguard Worker                  reinterpret_cast<XPointer>(mWindow));
552*8975f5c5SAndroid Build Coastguard Worker     }
553*8975f5c5SAndroid Build Coastguard Worker     else
554*8975f5c5SAndroid Build Coastguard Worker     {
555*8975f5c5SAndroid Build Coastguard Worker         XUnmapWindow(mDisplay, mWindow);
556*8975f5c5SAndroid Build Coastguard Worker         XFlush(mDisplay);
557*8975f5c5SAndroid Build Coastguard Worker     }
558*8975f5c5SAndroid Build Coastguard Worker 
559*8975f5c5SAndroid Build Coastguard Worker     // Block until we get ConfigureNotify to set up fully before returning.
560*8975f5c5SAndroid Build Coastguard Worker     mConfigured = false;
561*8975f5c5SAndroid Build Coastguard Worker     while (!mConfigured)
562*8975f5c5SAndroid Build Coastguard Worker     {
563*8975f5c5SAndroid Build Coastguard Worker         messageLoop();
564*8975f5c5SAndroid Build Coastguard Worker         angle::Sleep(10);
565*8975f5c5SAndroid Build Coastguard Worker     }
566*8975f5c5SAndroid Build Coastguard Worker 
567*8975f5c5SAndroid Build Coastguard Worker     mVisible = isVisible;
568*8975f5c5SAndroid Build Coastguard Worker }
569*8975f5c5SAndroid Build Coastguard Worker 
signalTestEvent()570*8975f5c5SAndroid Build Coastguard Worker void X11Window::signalTestEvent()
571*8975f5c5SAndroid Build Coastguard Worker {
572*8975f5c5SAndroid Build Coastguard Worker     XEvent event;
573*8975f5c5SAndroid Build Coastguard Worker     event.type                 = ClientMessage;
574*8975f5c5SAndroid Build Coastguard Worker     event.xclient.message_type = TEST_EVENT;
575*8975f5c5SAndroid Build Coastguard Worker     // Format needs to be valid or a BadValue is generated
576*8975f5c5SAndroid Build Coastguard Worker     event.xclient.format = 32;
577*8975f5c5SAndroid Build Coastguard Worker 
578*8975f5c5SAndroid Build Coastguard Worker     // Hijack StructureNotifyMask as we know we will be listening for it.
579*8975f5c5SAndroid Build Coastguard Worker     XSendEvent(mDisplay, mWindow, False, StructureNotifyMask, &event);
580*8975f5c5SAndroid Build Coastguard Worker 
581*8975f5c5SAndroid Build Coastguard Worker     // For test events, the tests want to check that it really did arrive, and they don't wait
582*8975f5c5SAndroid Build Coastguard Worker     // long.  XSync here makes sure the event is sent by the time the messageLoop() is called.
583*8975f5c5SAndroid Build Coastguard Worker     XSync(mDisplay, false);
584*8975f5c5SAndroid Build Coastguard Worker }
585*8975f5c5SAndroid Build Coastguard Worker 
processEvent(const XEvent & xEvent)586*8975f5c5SAndroid Build Coastguard Worker void X11Window::processEvent(const XEvent &xEvent)
587*8975f5c5SAndroid Build Coastguard Worker {
588*8975f5c5SAndroid Build Coastguard Worker     // TODO(cwallez) text events
589*8975f5c5SAndroid Build Coastguard Worker     switch (xEvent.type)
590*8975f5c5SAndroid Build Coastguard Worker     {
591*8975f5c5SAndroid Build Coastguard Worker         case ButtonPress:
592*8975f5c5SAndroid Build Coastguard Worker         {
593*8975f5c5SAndroid Build Coastguard Worker             Event event;
594*8975f5c5SAndroid Build Coastguard Worker             MouseButton button = MOUSEBUTTON_UNKNOWN;
595*8975f5c5SAndroid Build Coastguard Worker             int wheelY         = 0;
596*8975f5c5SAndroid Build Coastguard Worker 
597*8975f5c5SAndroid Build Coastguard Worker             // The mouse wheel updates are sent via button events.
598*8975f5c5SAndroid Build Coastguard Worker             switch (xEvent.xbutton.button)
599*8975f5c5SAndroid Build Coastguard Worker             {
600*8975f5c5SAndroid Build Coastguard Worker                 case Button4:
601*8975f5c5SAndroid Build Coastguard Worker                     wheelY = 1;
602*8975f5c5SAndroid Build Coastguard Worker                     break;
603*8975f5c5SAndroid Build Coastguard Worker                 case Button5:
604*8975f5c5SAndroid Build Coastguard Worker                     wheelY = -1;
605*8975f5c5SAndroid Build Coastguard Worker                     break;
606*8975f5c5SAndroid Build Coastguard Worker                 case 6:
607*8975f5c5SAndroid Build Coastguard Worker                     break;
608*8975f5c5SAndroid Build Coastguard Worker                 case 7:
609*8975f5c5SAndroid Build Coastguard Worker                     break;
610*8975f5c5SAndroid Build Coastguard Worker 
611*8975f5c5SAndroid Build Coastguard Worker                 case Button1:
612*8975f5c5SAndroid Build Coastguard Worker                     button = MOUSEBUTTON_LEFT;
613*8975f5c5SAndroid Build Coastguard Worker                     break;
614*8975f5c5SAndroid Build Coastguard Worker                 case Button2:
615*8975f5c5SAndroid Build Coastguard Worker                     button = MOUSEBUTTON_MIDDLE;
616*8975f5c5SAndroid Build Coastguard Worker                     break;
617*8975f5c5SAndroid Build Coastguard Worker                 case Button3:
618*8975f5c5SAndroid Build Coastguard Worker                     button = MOUSEBUTTON_RIGHT;
619*8975f5c5SAndroid Build Coastguard Worker                     break;
620*8975f5c5SAndroid Build Coastguard Worker                 case 8:
621*8975f5c5SAndroid Build Coastguard Worker                     button = MOUSEBUTTON_BUTTON4;
622*8975f5c5SAndroid Build Coastguard Worker                     break;
623*8975f5c5SAndroid Build Coastguard Worker                 case 9:
624*8975f5c5SAndroid Build Coastguard Worker                     button = MOUSEBUTTON_BUTTON5;
625*8975f5c5SAndroid Build Coastguard Worker                     break;
626*8975f5c5SAndroid Build Coastguard Worker 
627*8975f5c5SAndroid Build Coastguard Worker                 default:
628*8975f5c5SAndroid Build Coastguard Worker                     break;
629*8975f5c5SAndroid Build Coastguard Worker             }
630*8975f5c5SAndroid Build Coastguard Worker 
631*8975f5c5SAndroid Build Coastguard Worker             if (wheelY != 0)
632*8975f5c5SAndroid Build Coastguard Worker             {
633*8975f5c5SAndroid Build Coastguard Worker                 event.Type             = Event::EVENT_MOUSE_WHEEL_MOVED;
634*8975f5c5SAndroid Build Coastguard Worker                 event.MouseWheel.Delta = wheelY;
635*8975f5c5SAndroid Build Coastguard Worker                 pushEvent(event);
636*8975f5c5SAndroid Build Coastguard Worker             }
637*8975f5c5SAndroid Build Coastguard Worker 
638*8975f5c5SAndroid Build Coastguard Worker             if (button != MOUSEBUTTON_UNKNOWN)
639*8975f5c5SAndroid Build Coastguard Worker             {
640*8975f5c5SAndroid Build Coastguard Worker                 event.Type               = Event::EVENT_MOUSE_BUTTON_RELEASED;
641*8975f5c5SAndroid Build Coastguard Worker                 event.MouseButton.Button = button;
642*8975f5c5SAndroid Build Coastguard Worker                 event.MouseButton.X      = xEvent.xbutton.x;
643*8975f5c5SAndroid Build Coastguard Worker                 event.MouseButton.Y      = xEvent.xbutton.y;
644*8975f5c5SAndroid Build Coastguard Worker                 pushEvent(event);
645*8975f5c5SAndroid Build Coastguard Worker             }
646*8975f5c5SAndroid Build Coastguard Worker         }
647*8975f5c5SAndroid Build Coastguard Worker         break;
648*8975f5c5SAndroid Build Coastguard Worker 
649*8975f5c5SAndroid Build Coastguard Worker         case ButtonRelease:
650*8975f5c5SAndroid Build Coastguard Worker         {
651*8975f5c5SAndroid Build Coastguard Worker             Event event;
652*8975f5c5SAndroid Build Coastguard Worker             MouseButton button = MOUSEBUTTON_UNKNOWN;
653*8975f5c5SAndroid Build Coastguard Worker 
654*8975f5c5SAndroid Build Coastguard Worker             switch (xEvent.xbutton.button)
655*8975f5c5SAndroid Build Coastguard Worker             {
656*8975f5c5SAndroid Build Coastguard Worker                 case Button1:
657*8975f5c5SAndroid Build Coastguard Worker                     button = MOUSEBUTTON_LEFT;
658*8975f5c5SAndroid Build Coastguard Worker                     break;
659*8975f5c5SAndroid Build Coastguard Worker                 case Button2:
660*8975f5c5SAndroid Build Coastguard Worker                     button = MOUSEBUTTON_MIDDLE;
661*8975f5c5SAndroid Build Coastguard Worker                     break;
662*8975f5c5SAndroid Build Coastguard Worker                 case Button3:
663*8975f5c5SAndroid Build Coastguard Worker                     button = MOUSEBUTTON_RIGHT;
664*8975f5c5SAndroid Build Coastguard Worker                     break;
665*8975f5c5SAndroid Build Coastguard Worker                 case 8:
666*8975f5c5SAndroid Build Coastguard Worker                     button = MOUSEBUTTON_BUTTON4;
667*8975f5c5SAndroid Build Coastguard Worker                     break;
668*8975f5c5SAndroid Build Coastguard Worker                 case 9:
669*8975f5c5SAndroid Build Coastguard Worker                     button = MOUSEBUTTON_BUTTON5;
670*8975f5c5SAndroid Build Coastguard Worker                     break;
671*8975f5c5SAndroid Build Coastguard Worker 
672*8975f5c5SAndroid Build Coastguard Worker                 default:
673*8975f5c5SAndroid Build Coastguard Worker                     break;
674*8975f5c5SAndroid Build Coastguard Worker             }
675*8975f5c5SAndroid Build Coastguard Worker 
676*8975f5c5SAndroid Build Coastguard Worker             if (button != MOUSEBUTTON_UNKNOWN)
677*8975f5c5SAndroid Build Coastguard Worker             {
678*8975f5c5SAndroid Build Coastguard Worker                 event.Type               = Event::EVENT_MOUSE_BUTTON_RELEASED;
679*8975f5c5SAndroid Build Coastguard Worker                 event.MouseButton.Button = button;
680*8975f5c5SAndroid Build Coastguard Worker                 event.MouseButton.X      = xEvent.xbutton.x;
681*8975f5c5SAndroid Build Coastguard Worker                 event.MouseButton.Y      = xEvent.xbutton.y;
682*8975f5c5SAndroid Build Coastguard Worker                 pushEvent(event);
683*8975f5c5SAndroid Build Coastguard Worker             }
684*8975f5c5SAndroid Build Coastguard Worker         }
685*8975f5c5SAndroid Build Coastguard Worker         break;
686*8975f5c5SAndroid Build Coastguard Worker 
687*8975f5c5SAndroid Build Coastguard Worker         case KeyPress:
688*8975f5c5SAndroid Build Coastguard Worker         {
689*8975f5c5SAndroid Build Coastguard Worker             Event event;
690*8975f5c5SAndroid Build Coastguard Worker             event.Type     = Event::EVENT_KEY_PRESSED;
691*8975f5c5SAndroid Build Coastguard Worker             event.Key.Code = X11CodeToKey(mDisplay, xEvent.xkey.keycode);
692*8975f5c5SAndroid Build Coastguard Worker             AddX11KeyStateToEvent(&event, xEvent.xkey.state);
693*8975f5c5SAndroid Build Coastguard Worker             pushEvent(event);
694*8975f5c5SAndroid Build Coastguard Worker         }
695*8975f5c5SAndroid Build Coastguard Worker         break;
696*8975f5c5SAndroid Build Coastguard Worker 
697*8975f5c5SAndroid Build Coastguard Worker         case KeyRelease:
698*8975f5c5SAndroid Build Coastguard Worker         {
699*8975f5c5SAndroid Build Coastguard Worker             Event event;
700*8975f5c5SAndroid Build Coastguard Worker             event.Type     = Event::EVENT_KEY_RELEASED;
701*8975f5c5SAndroid Build Coastguard Worker             event.Key.Code = X11CodeToKey(mDisplay, xEvent.xkey.keycode);
702*8975f5c5SAndroid Build Coastguard Worker             AddX11KeyStateToEvent(&event, xEvent.xkey.state);
703*8975f5c5SAndroid Build Coastguard Worker             pushEvent(event);
704*8975f5c5SAndroid Build Coastguard Worker         }
705*8975f5c5SAndroid Build Coastguard Worker         break;
706*8975f5c5SAndroid Build Coastguard Worker 
707*8975f5c5SAndroid Build Coastguard Worker         case EnterNotify:
708*8975f5c5SAndroid Build Coastguard Worker         {
709*8975f5c5SAndroid Build Coastguard Worker             Event event;
710*8975f5c5SAndroid Build Coastguard Worker             event.Type = Event::EVENT_MOUSE_ENTERED;
711*8975f5c5SAndroid Build Coastguard Worker             pushEvent(event);
712*8975f5c5SAndroid Build Coastguard Worker         }
713*8975f5c5SAndroid Build Coastguard Worker         break;
714*8975f5c5SAndroid Build Coastguard Worker 
715*8975f5c5SAndroid Build Coastguard Worker         case LeaveNotify:
716*8975f5c5SAndroid Build Coastguard Worker         {
717*8975f5c5SAndroid Build Coastguard Worker             Event event;
718*8975f5c5SAndroid Build Coastguard Worker             event.Type = Event::EVENT_MOUSE_LEFT;
719*8975f5c5SAndroid Build Coastguard Worker             pushEvent(event);
720*8975f5c5SAndroid Build Coastguard Worker         }
721*8975f5c5SAndroid Build Coastguard Worker         break;
722*8975f5c5SAndroid Build Coastguard Worker 
723*8975f5c5SAndroid Build Coastguard Worker         case MotionNotify:
724*8975f5c5SAndroid Build Coastguard Worker         {
725*8975f5c5SAndroid Build Coastguard Worker             Event event;
726*8975f5c5SAndroid Build Coastguard Worker             event.Type        = Event::EVENT_MOUSE_MOVED;
727*8975f5c5SAndroid Build Coastguard Worker             event.MouseMove.X = xEvent.xmotion.x;
728*8975f5c5SAndroid Build Coastguard Worker             event.MouseMove.Y = xEvent.xmotion.y;
729*8975f5c5SAndroid Build Coastguard Worker             pushEvent(event);
730*8975f5c5SAndroid Build Coastguard Worker         }
731*8975f5c5SAndroid Build Coastguard Worker         break;
732*8975f5c5SAndroid Build Coastguard Worker 
733*8975f5c5SAndroid Build Coastguard Worker         case ConfigureNotify:
734*8975f5c5SAndroid Build Coastguard Worker         {
735*8975f5c5SAndroid Build Coastguard Worker             mConfigured = true;
736*8975f5c5SAndroid Build Coastguard Worker             if (mWindow == 0)
737*8975f5c5SAndroid Build Coastguard Worker             {
738*8975f5c5SAndroid Build Coastguard Worker                 break;
739*8975f5c5SAndroid Build Coastguard Worker             }
740*8975f5c5SAndroid Build Coastguard Worker             if (xEvent.xconfigure.width != mWidth || xEvent.xconfigure.height != mHeight)
741*8975f5c5SAndroid Build Coastguard Worker             {
742*8975f5c5SAndroid Build Coastguard Worker                 Event event;
743*8975f5c5SAndroid Build Coastguard Worker                 event.Type        = Event::EVENT_RESIZED;
744*8975f5c5SAndroid Build Coastguard Worker                 event.Size.Width  = xEvent.xconfigure.width;
745*8975f5c5SAndroid Build Coastguard Worker                 event.Size.Height = xEvent.xconfigure.height;
746*8975f5c5SAndroid Build Coastguard Worker                 pushEvent(event);
747*8975f5c5SAndroid Build Coastguard Worker             }
748*8975f5c5SAndroid Build Coastguard Worker             if (xEvent.xconfigure.x != mX || xEvent.xconfigure.y != mY)
749*8975f5c5SAndroid Build Coastguard Worker             {
750*8975f5c5SAndroid Build Coastguard Worker                 // Sometimes, the window manager reparents our window (for example
751*8975f5c5SAndroid Build Coastguard Worker                 // when resizing) then the X and Y coordinates will be with respect to
752*8975f5c5SAndroid Build Coastguard Worker                 // the new parent and not what the user wants to know. Use
753*8975f5c5SAndroid Build Coastguard Worker                 // XTranslateCoordinates to get the coordinates on the screen.
754*8975f5c5SAndroid Build Coastguard Worker                 int screen  = DefaultScreen(mDisplay);
755*8975f5c5SAndroid Build Coastguard Worker                 Window root = RootWindow(mDisplay, screen);
756*8975f5c5SAndroid Build Coastguard Worker 
757*8975f5c5SAndroid Build Coastguard Worker                 int x, y;
758*8975f5c5SAndroid Build Coastguard Worker                 Window child;
759*8975f5c5SAndroid Build Coastguard Worker                 XTranslateCoordinates(mDisplay, mWindow, root, 0, 0, &x, &y, &child);
760*8975f5c5SAndroid Build Coastguard Worker 
761*8975f5c5SAndroid Build Coastguard Worker                 if (x != mX || y != mY)
762*8975f5c5SAndroid Build Coastguard Worker                 {
763*8975f5c5SAndroid Build Coastguard Worker                     Event event;
764*8975f5c5SAndroid Build Coastguard Worker                     event.Type   = Event::EVENT_MOVED;
765*8975f5c5SAndroid Build Coastguard Worker                     event.Move.X = x;
766*8975f5c5SAndroid Build Coastguard Worker                     event.Move.Y = y;
767*8975f5c5SAndroid Build Coastguard Worker                     pushEvent(event);
768*8975f5c5SAndroid Build Coastguard Worker                 }
769*8975f5c5SAndroid Build Coastguard Worker             }
770*8975f5c5SAndroid Build Coastguard Worker         }
771*8975f5c5SAndroid Build Coastguard Worker         break;
772*8975f5c5SAndroid Build Coastguard Worker 
773*8975f5c5SAndroid Build Coastguard Worker         case FocusIn:
774*8975f5c5SAndroid Build Coastguard Worker             if (xEvent.xfocus.mode == NotifyNormal || xEvent.xfocus.mode == NotifyWhileGrabbed)
775*8975f5c5SAndroid Build Coastguard Worker             {
776*8975f5c5SAndroid Build Coastguard Worker                 Event event;
777*8975f5c5SAndroid Build Coastguard Worker                 event.Type = Event::EVENT_GAINED_FOCUS;
778*8975f5c5SAndroid Build Coastguard Worker                 pushEvent(event);
779*8975f5c5SAndroid Build Coastguard Worker             }
780*8975f5c5SAndroid Build Coastguard Worker             break;
781*8975f5c5SAndroid Build Coastguard Worker 
782*8975f5c5SAndroid Build Coastguard Worker         case FocusOut:
783*8975f5c5SAndroid Build Coastguard Worker             if (xEvent.xfocus.mode == NotifyNormal || xEvent.xfocus.mode == NotifyWhileGrabbed)
784*8975f5c5SAndroid Build Coastguard Worker             {
785*8975f5c5SAndroid Build Coastguard Worker                 Event event;
786*8975f5c5SAndroid Build Coastguard Worker                 event.Type = Event::EVENT_LOST_FOCUS;
787*8975f5c5SAndroid Build Coastguard Worker                 pushEvent(event);
788*8975f5c5SAndroid Build Coastguard Worker             }
789*8975f5c5SAndroid Build Coastguard Worker             break;
790*8975f5c5SAndroid Build Coastguard Worker 
791*8975f5c5SAndroid Build Coastguard Worker         case DestroyNotify:
792*8975f5c5SAndroid Build Coastguard Worker             // Note: we already received WM_DELETE_WINDOW
793*8975f5c5SAndroid Build Coastguard Worker             mDestroyed = true;
794*8975f5c5SAndroid Build Coastguard Worker             break;
795*8975f5c5SAndroid Build Coastguard Worker 
796*8975f5c5SAndroid Build Coastguard Worker         case ClientMessage:
797*8975f5c5SAndroid Build Coastguard Worker             if (xEvent.xclient.message_type == WM_PROTOCOLS &&
798*8975f5c5SAndroid Build Coastguard Worker                 static_cast<Atom>(xEvent.xclient.data.l[0]) == WM_DELETE_WINDOW)
799*8975f5c5SAndroid Build Coastguard Worker             {
800*8975f5c5SAndroid Build Coastguard Worker                 Event event;
801*8975f5c5SAndroid Build Coastguard Worker                 event.Type = Event::EVENT_CLOSED;
802*8975f5c5SAndroid Build Coastguard Worker                 pushEvent(event);
803*8975f5c5SAndroid Build Coastguard Worker             }
804*8975f5c5SAndroid Build Coastguard Worker             else if (xEvent.xclient.message_type == TEST_EVENT)
805*8975f5c5SAndroid Build Coastguard Worker             {
806*8975f5c5SAndroid Build Coastguard Worker                 Event event;
807*8975f5c5SAndroid Build Coastguard Worker                 event.Type = Event::EVENT_TEST;
808*8975f5c5SAndroid Build Coastguard Worker                 pushEvent(event);
809*8975f5c5SAndroid Build Coastguard Worker             }
810*8975f5c5SAndroid Build Coastguard Worker             break;
811*8975f5c5SAndroid Build Coastguard Worker     }
812*8975f5c5SAndroid Build Coastguard Worker }
813*8975f5c5SAndroid Build Coastguard Worker 
CreateX11Window()814*8975f5c5SAndroid Build Coastguard Worker OSWindow *CreateX11Window()
815*8975f5c5SAndroid Build Coastguard Worker {
816*8975f5c5SAndroid Build Coastguard Worker     return new X11Window();
817*8975f5c5SAndroid Build Coastguard Worker }
818*8975f5c5SAndroid Build Coastguard Worker 
CreateX11WindowWithVisualId(int visualId)819*8975f5c5SAndroid Build Coastguard Worker OSWindow *CreateX11WindowWithVisualId(int visualId)
820*8975f5c5SAndroid Build Coastguard Worker {
821*8975f5c5SAndroid Build Coastguard Worker     return new X11Window(visualId);
822*8975f5c5SAndroid Build Coastguard Worker }
823*8975f5c5SAndroid Build Coastguard Worker 
IsX11WindowAvailable()824*8975f5c5SAndroid Build Coastguard Worker bool IsX11WindowAvailable()
825*8975f5c5SAndroid Build Coastguard Worker {
826*8975f5c5SAndroid Build Coastguard Worker     Display *display = XOpenDisplay(nullptr);
827*8975f5c5SAndroid Build Coastguard Worker     if (!display)
828*8975f5c5SAndroid Build Coastguard Worker     {
829*8975f5c5SAndroid Build Coastguard Worker         return false;
830*8975f5c5SAndroid Build Coastguard Worker     }
831*8975f5c5SAndroid Build Coastguard Worker     XCloseDisplay(display);
832*8975f5c5SAndroid Build Coastguard Worker     return true;
833*8975f5c5SAndroid Build Coastguard Worker }
834