1 /*************************************************************************/
2 /*  os_x11.h                                                             */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 
31 #ifndef OS_X11_H
32 #define OS_X11_H
33 
34 #include "context_gl_x11.h"
35 #include "core/os/input.h"
36 #include "crash_handler_x11.h"
37 #include "drivers/alsa/audio_driver_alsa.h"
38 #include "drivers/alsamidi/midi_driver_alsamidi.h"
39 #include "drivers/pulseaudio/audio_driver_pulseaudio.h"
40 #include "drivers/unix/os_unix.h"
41 #include "joypad_linux.h"
42 #include "main/input_default.h"
43 #include "power_x11.h"
44 #include "servers/audio_server.h"
45 #include "servers/visual/rasterizer.h"
46 #include "servers/visual_server.h"
47 
48 #include <X11/Xcursor/Xcursor.h>
49 #include <X11/Xlib.h>
50 #include <X11/extensions/XInput2.h>
51 #include <X11/extensions/Xrandr.h>
52 #include <X11/keysym.h>
53 
54 // Hints for X11 fullscreen
55 typedef struct {
56 	unsigned long flags;
57 	unsigned long functions;
58 	unsigned long decorations;
59 	long inputMode;
60 	unsigned long status;
61 } Hints;
62 
63 typedef struct _xrr_monitor_info {
64 	Atom name;
65 	Bool primary;
66 	Bool automatic;
67 	int noutput;
68 	int x;
69 	int y;
70 	int width;
71 	int height;
72 	int mwidth;
73 	int mheight;
74 	RROutput *outputs;
75 } xrr_monitor_info;
76 
77 #undef CursorShape
78 
79 class OS_X11 : public OS_Unix {
80 
81 	Atom wm_delete;
82 	Atom xdnd_enter;
83 	Atom xdnd_position;
84 	Atom xdnd_status;
85 	Atom xdnd_action_copy;
86 	Atom xdnd_drop;
87 	Atom xdnd_finished;
88 	Atom xdnd_selection;
89 	Atom requested;
90 
91 	int xdnd_version;
92 
93 #if defined(OPENGL_ENABLED)
94 	ContextGL_X11 *context_gl;
95 #endif
96 	//Rasterizer *rasterizer;
97 	VisualServer *visual_server;
98 	VideoMode current_videomode;
99 	List<String> args;
100 	Window x11_window;
101 	Window xdnd_source_window;
102 	MainLoop *main_loop;
103 	::Display *x11_display;
104 	char *xmbstring;
105 	int xmblen;
106 	unsigned long last_timestamp;
107 	::Time last_keyrelease_time;
108 	::XIC xic;
109 	::XIM xim;
110 	::XIMStyle xim_style;
111 	static void xim_destroy_callback(::XIM im, ::XPointer client_data,
112 			::XPointer call_data);
113 
114 	// IME
115 	bool im_active;
116 	Vector2 im_position;
117 	Vector2 last_position_before_fs;
118 
119 	Size2 min_size;
120 	Size2 max_size;
121 
122 	Point2 last_mouse_pos;
123 	bool last_mouse_pos_valid;
124 	Point2i last_click_pos;
125 	uint64_t last_click_ms;
126 	int last_click_button_index;
127 	uint32_t last_button_state;
128 
129 	struct {
130 		int opcode;
131 		Vector<int> touch_devices;
132 		Map<int, Vector2> absolute_devices;
133 		Map<int, Vector2> pen_pressure_range;
134 		Map<int, Vector2> pen_tilt_x_range;
135 		Map<int, Vector2> pen_tilt_y_range;
136 		XIEventMask all_event_mask;
137 		XIEventMask all_master_event_mask;
138 		Map<int, Vector2> state;
139 		double pressure;
140 		bool pressure_supported;
141 		Vector2 tilt;
142 		Vector2 mouse_pos_to_filter;
143 		Vector2 relative_motion;
144 		Vector2 raw_pos;
145 		Vector2 old_raw_pos;
146 		::Time last_relative_time;
147 	} xi;
148 
149 	bool refresh_device_info();
150 
151 	unsigned int get_mouse_button_state(unsigned int p_x11_button, int p_x11_type);
152 	void get_key_modifier_state(unsigned int p_x11_state, Ref<InputEventWithModifiers> state);
153 	void flush_mouse_motion();
154 
155 	MouseMode mouse_mode;
156 	Point2i center;
157 
158 	void handle_key_event(XKeyEvent *p_event, bool p_echo = false);
159 	void process_xevents();
160 	virtual void delete_main_loop();
161 
162 	bool force_quit;
163 	bool minimized;
164 	bool window_has_focus;
165 	bool do_mouse_warp;
166 
167 	const char *cursor_theme;
168 	int cursor_size;
169 	XcursorImage *img[CURSOR_MAX];
170 	Cursor cursors[CURSOR_MAX];
171 	Cursor null_cursor;
172 	CursorShape current_cursor;
173 	Map<CursorShape, Vector<Variant> > cursors_cache;
174 
175 	InputDefault *input;
176 
177 #ifdef JOYDEV_ENABLED
178 	JoypadLinux *joypad;
179 #endif
180 
181 #ifdef ALSA_ENABLED
182 	AudioDriverALSA driver_alsa;
183 #endif
184 
185 #ifdef ALSAMIDI_ENABLED
186 	MIDIDriverALSAMidi driver_alsamidi;
187 #endif
188 
189 #ifdef PULSEAUDIO_ENABLED
190 	AudioDriverPulseAudio driver_pulseaudio;
191 #endif
192 
193 	PowerX11 *power_manager;
194 
195 	bool layered_window;
196 
197 	CrashHandler crash_handler;
198 
199 	int video_driver_index;
200 	bool maximized;
201 	bool window_focused;
202 	//void set_wm_border(bool p_enabled);
203 	void set_wm_fullscreen(bool p_enabled);
204 	void set_wm_above(bool p_enabled);
205 
206 	typedef xrr_monitor_info *(*xrr_get_monitors_t)(Display *dpy, Window window, Bool get_active, int *nmonitors);
207 	typedef void (*xrr_free_monitors_t)(xrr_monitor_info *monitors);
208 	xrr_get_monitors_t xrr_get_monitors;
209 	xrr_free_monitors_t xrr_free_monitors;
210 	void *xrandr_handle;
211 	Bool xrandr_ext_ok;
212 
213 protected:
214 	virtual int get_current_video_driver() const;
215 
216 	virtual void initialize_core();
217 	virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
218 	virtual void finalize();
219 
220 	virtual void set_main_loop(MainLoop *p_main_loop);
221 
222 	void _window_changed(XEvent *event);
223 
224 	bool window_maximize_check(const char *p_atom_name) const;
225 	bool is_window_maximize_allowed() const;
226 
227 public:
228 	virtual String get_name() const;
229 
230 	virtual void set_cursor_shape(CursorShape p_shape);
231 	virtual CursorShape get_cursor_shape() const;
232 	virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot);
233 
234 	void set_mouse_mode(MouseMode p_mode);
235 	MouseMode get_mouse_mode() const;
236 
237 	virtual void warp_mouse_position(const Point2 &p_to);
238 	virtual Point2 get_mouse_position() const;
239 	virtual int get_mouse_button_state() const;
240 	virtual void set_window_title(const String &p_title);
241 
242 	virtual void set_icon(const Ref<Image> &p_icon);
243 
244 	virtual MainLoop *get_main_loop() const;
245 
246 	virtual bool can_draw() const;
247 
248 	virtual void set_clipboard(const String &p_text);
249 	virtual String get_clipboard() const;
250 
251 	virtual void release_rendering_thread();
252 	virtual void make_rendering_thread();
253 	virtual void swap_buffers();
254 
255 	virtual String get_config_path() const;
256 	virtual String get_data_path() const;
257 	virtual String get_cache_path() const;
258 
259 	virtual String get_system_dir(SystemDir p_dir) const;
260 
261 	virtual Error shell_open(String p_uri);
262 
263 	virtual void set_video_mode(const VideoMode &p_video_mode, int p_screen = 0);
264 	virtual VideoMode get_video_mode(int p_screen = 0) const;
265 	virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const;
266 
267 	virtual int get_screen_count() const;
268 	virtual int get_current_screen() const;
269 	virtual void set_current_screen(int p_screen);
270 	virtual Point2 get_screen_position(int p_screen = -1) const;
271 	virtual Size2 get_screen_size(int p_screen = -1) const;
272 	virtual int get_screen_dpi(int p_screen = -1) const;
273 	virtual Point2 get_window_position() const;
274 	virtual void set_window_position(const Point2 &p_position);
275 	virtual Size2 get_window_size() const;
276 	virtual Size2 get_real_window_size() const;
277 	virtual Size2 get_max_window_size() const;
278 	virtual Size2 get_min_window_size() const;
279 	virtual void set_min_window_size(const Size2 p_size);
280 	virtual void set_max_window_size(const Size2 p_size);
281 	virtual void set_window_size(const Size2 p_size);
282 	virtual void set_window_fullscreen(bool p_enabled);
283 	virtual bool is_window_fullscreen() const;
284 	virtual void set_window_resizable(bool p_enabled);
285 	virtual bool is_window_resizable() const;
286 	virtual void set_window_minimized(bool p_enabled);
287 	virtual bool is_window_minimized() const;
288 	virtual void set_window_maximized(bool p_enabled);
289 	virtual bool is_window_maximized() const;
290 	virtual void set_window_always_on_top(bool p_enabled);
291 	virtual bool is_window_always_on_top() const;
292 	virtual bool is_window_focused() const;
293 	virtual void request_attention();
294 
295 	virtual void set_borderless_window(bool p_borderless);
296 	virtual bool get_borderless_window();
297 
298 	virtual bool get_window_per_pixel_transparency_enabled() const;
299 	virtual void set_window_per_pixel_transparency_enabled(bool p_enabled);
300 
301 	virtual void set_ime_active(const bool p_active);
302 	virtual void set_ime_position(const Point2 &p_pos);
303 
304 	virtual String get_unique_id() const;
305 
306 	virtual void move_window_to_foreground();
307 	virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
308 
309 	virtual bool is_joy_known(int p_device);
310 	virtual String get_joy_guid(int p_device) const;
311 
312 	virtual void set_context(int p_context);
313 
314 	virtual void _set_use_vsync(bool p_enable);
315 	//virtual bool is_vsync_enabled() const;
316 
317 	virtual OS::PowerState get_power_state();
318 	virtual int get_power_seconds_left();
319 	virtual int get_power_percent_left();
320 
321 	virtual bool _check_internal_feature_support(const String &p_feature);
322 
323 	virtual void force_process_input();
324 	void run();
325 
326 	void disable_crash_handler();
327 	bool is_disable_crash_handler() const;
328 
329 	virtual Error move_to_trash(const String &p_path);
330 
331 	virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
332 	virtual int keyboard_get_layout_count() const;
333 	virtual int keyboard_get_current_layout() const;
334 	virtual void keyboard_set_current_layout(int p_index);
335 	virtual String keyboard_get_layout_language(int p_index) const;
336 	virtual String keyboard_get_layout_name(int p_index) const;
337 
338 	void update_real_mouse_position();
339 	OS_X11();
340 };
341 
342 #endif
343