Merge branch 'master' into blender2.8
[blender.git] / intern / ghost / intern / GHOST_SystemX11.h
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_SystemX11.h
29  *  \ingroup GHOST
30  * Declaration of GHOST_SystemX11 class.
31  */
32
33 #ifndef __GHOST_SYSTEMX11_H__
34 #define __GHOST_SYSTEMX11_H__
35
36 #include <X11/Xlib.h>
37 #include <X11/XKBlib.h> /* allow detectable autorepeate */
38
39 #include "GHOST_System.h"
40 #include "../GHOST_Types.h"
41
42 // For tablets
43 #ifdef WITH_X11_XINPUT
44 #  include <X11/extensions/XInput.h>
45 #endif
46
47 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
48 #  define GHOST_X11_RES_NAME  "Blender" /* res_name */
49 #  define GHOST_X11_RES_CLASS "Blender" /* res_class */
50 #endif
51
52 /* generic error handlers */
53 int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent);
54 int GHOST_X11_ApplicationIOErrorHandler(Display *display);
55
56 #define GHOST_X11_ERROR_HANDLERS_OVERRIDE(var) \
57         struct { \
58                 XErrorHandler handler; \
59                 XIOErrorHandler handler_io; \
60         } var = { \
61                 XSetErrorHandler(GHOST_X11_ApplicationErrorHandler), \
62                 XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler), \
63         }
64
65 #define GHOST_X11_ERROR_HANDLERS_RESTORE(var) \
66         { \
67                 (void)XSetErrorHandler(var.handler); \
68                 (void)XSetIOErrorHandler(var.handler_io); \
69         } ((void)0)
70
71 class GHOST_WindowX11;
72
73 /**
74  * X11 Implementation of GHOST_System class.
75  * \see GHOST_System.
76  * \author      Laurence Bourn
77  * \date        October 26, 2001
78  */
79
80 class GHOST_SystemX11 : public GHOST_System {
81 public:
82
83         /**
84          * Constructor
85          * this class should only be instanciated by GHOST_ISystem.
86          */
87
88         GHOST_SystemX11(
89             );
90
91         /**
92          * Destructor.
93          */
94         ~GHOST_SystemX11();
95
96
97         GHOST_TSuccess
98         init(
99             );
100
101         /**
102          * Informs if the system provides native dialogs (eg. confirm quit)
103          */
104         virtual bool supportsNativeDialogs(void);
105
106         /**
107          * \section Interface Inherited from GHOST_ISystem
108          */
109
110         /**
111          * Returns the system time.
112          * Returns the number of milliseconds since the start of the system process.
113          * \return The number of milliseconds.
114          */
115         GHOST_TUns64
116         getMilliSeconds(
117             ) const;
118
119
120         /**
121          * Returns the number of displays on this system.
122          * \return The number of displays.
123          */
124         GHOST_TUns8
125         getNumDisplays(
126             ) const;
127
128         /**
129          * Returns the dimensions of the main display on this system.
130          * \return The dimension of the main display.
131          */
132         void
133         getMainDisplayDimensions(
134             GHOST_TUns32& width,
135             GHOST_TUns32& height
136             ) const;
137
138         /**
139          * Returns the dimensions of all displays on this system.
140          * \return The dimension of the main display.
141          */
142         void
143         getAllDisplayDimensions(
144             GHOST_TUns32& width,
145             GHOST_TUns32& height
146             ) const;
147
148         /**
149          * Create a new window.
150          * The new window is added to the list of windows managed.
151          * Never explicitly delete the window, use disposeWindow() instead.
152          * \param       title   The name of the window (displayed in the title bar of the window if the OS supports it).
153          * \param       left            The coordinate of the left edge of the window.
154          * \param       top             The coordinate of the top edge of the window.
155          * \param       width           The width the window.
156          * \param       height          The height the window.
157          * \param       state           The state of the window when opened.
158          * \param       type            The type of drawing context installed in this window.
159          * \param       stereoVisual    Create a stereo visual for quad buffered stereo.
160          * \param       exclusive       Use to show the window ontop and ignore others
161          *                                              (used fullscreen).
162          * \param       parentWindow    Parent (embedder) window
163          * \return      The new window (or 0 if creation failed).
164          */
165         GHOST_IWindow *
166         createWindow(
167             const STR_String& title,
168             GHOST_TInt32 left,
169             GHOST_TInt32 top,
170             GHOST_TUns32 width,
171             GHOST_TUns32 height,
172             GHOST_TWindowState state,
173             GHOST_TDrawingContextType type,
174             GHOST_GLSettings glSettings,
175             const bool exclusive = false,
176             const GHOST_TEmbedderWindowID parentWindow = 0
177             );
178
179
180         /**
181          * Create a new offscreen context.
182          * Never explicitly delete the context, use disposeContext() instead.
183          * \return  The new context (or 0 if creation failed).
184          */
185         GHOST_IContext *
186         createOffscreenContext(
187             );
188
189         /**
190          * Dispose of a context.
191          * \param   context Pointer to the context to be disposed.
192          * \return  Indication of success.
193          */
194         GHOST_TSuccess
195         disposeContext(
196             GHOST_IContext *context
197             );
198
199         /**
200          * Retrieves events from the system and stores them in the queue.
201          * \param waitForEvent Flag to wait for an event (or return immediately).
202          * \return Indication of the presence of events.
203          */
204         bool
205         processEvents(
206             bool waitForEvent
207             );
208
209         GHOST_TSuccess
210         getCursorPosition(
211             GHOST_TInt32& x,
212             GHOST_TInt32& y
213             ) const;
214
215         GHOST_TSuccess
216         setCursorPosition(
217             GHOST_TInt32 x,
218             GHOST_TInt32 y
219             );
220
221         /**
222          * Returns the state of all modifier keys.
223          * \param keys  The state of all modifier keys (true == pressed).
224          * \return              Indication of success.
225          */
226         GHOST_TSuccess
227         getModifierKeys(
228             GHOST_ModifierKeys& keys
229             ) const;
230
231         /**
232          * Returns the state of the mouse buttons (ouside the message queue).
233          * \param buttons       The state of the buttons.
234          * \return                      Indication of success.
235          */
236         GHOST_TSuccess
237         getButtons(
238             GHOST_Buttons& buttons
239             ) const;
240
241         /**
242          * Flag a window as dirty. This will
243          * generate a GHOST window update event on a call to processEvents()
244          */
245
246         void
247         addDirtyWindow(
248             GHOST_WindowX11 *bad_wind
249             );
250
251
252         /**
253          * return a pointer to the X11 display structure
254          */
255
256         Display *
257         getXDisplay(
258                 ) {
259                 return m_display;
260         }
261
262 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
263         XIM
264         getX11_XIM()
265         {
266                 return m_xim;
267         }
268 #endif
269
270         /* Helped function for get data from the clipboard. */
271         void getClipboard_xcout(const XEvent *evt, Atom sel, Atom target,
272                                 unsigned char **txt, unsigned long *len,
273                                 unsigned int *context) const;
274
275         /**
276          * Returns unsigned char from CUT_BUFFER0
277          * \param selection             Get selection, X11 only feature
278          * \return                              Returns the Clipboard indicated by Flag
279          */
280         GHOST_TUns8 *getClipboard(bool selection) const;
281
282         /**
283          * Puts buffer to system clipboard
284          * \param buffer        The buffer to copy to the clipboard
285          * \param selection     Set the selection into the clipboard, X11 only feature
286          */
287         void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
288
289 #ifdef WITH_XDND
290         /**
291          * Creates a drag'n'drop event and pushes it immediately onto the event queue.
292          * Called by GHOST_DropTargetX11 class.
293          * \param eventType The type of drag'n'drop event
294          * \param draggedObjectType The type object concerned (currently array of file names, string, ?bitmap)
295          * \param mouseX x mouse coordinate (in window coordinates)
296          * \param mouseY y mouse coordinate
297          * \param window The window on which the event occurred
298          * \return Indication whether the event was handled.
299          */
300         static GHOST_TSuccess pushDragDropEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType, GHOST_IWindow *window, int mouseX, int mouseY, void *data);
301 #endif
302
303         /**
304          * \see GHOST_ISystem
305          */
306         int toggleConsole(int /*action*/) {
307                 return 0;
308         }
309
310 #ifdef WITH_X11_XINPUT
311         typedef struct GHOST_TabletX11 {
312                 XDevice *StylusDevice;
313                 XDevice *EraserDevice;
314
315                 XID StylusID, EraserID;
316
317                 int MotionEvent;
318                 int ProxInEvent;
319                 int ProxOutEvent;
320                 int PressEvent;
321
322                 int MotionEventEraser;
323                 int ProxInEventEraser;
324                 int ProxOutEventEraser;
325                 int PressEventEraser;
326
327                 int PressureLevels;
328                 int XtiltLevels, YtiltLevels;
329         } GHOST_TabletX11;
330
331         GHOST_TabletX11 &GetXTablet()
332         {
333                 return m_xtablet;
334         }
335 #endif // WITH_X11_XINPUT
336
337         struct {
338                 /**
339                  * Atom used for ICCCM, WM-spec and Motif.
340                  * We only need get this atom at the start, it's relative
341                  * to the display not the window and are public for every
342                  * window that need it.
343                  */
344                 Atom WM_STATE;
345                 Atom WM_CHANGE_STATE;
346                 Atom _NET_WM_STATE;
347                 Atom _NET_WM_STATE_MAXIMIZED_HORZ;
348                 Atom _NET_WM_STATE_MAXIMIZED_VERT;
349                 Atom _NET_WM_STATE_FULLSCREEN;
350                 Atom _MOTIF_WM_HINTS;
351                 Atom WM_TAKE_FOCUS;
352                 Atom WM_PROTOCOLS;
353                 Atom WM_DELETE_WINDOW;
354
355                 /* Atoms for Selection, copy & paste. */
356                 Atom TARGETS;
357                 Atom STRING;
358                 Atom COMPOUND_TEXT;
359                 Atom TEXT;
360                 Atom CLIPBOARD;
361                 Atom PRIMARY;
362                 Atom XCLIP_OUT;
363                 Atom INCR;
364                 Atom UTF8_STRING;
365 #ifdef WITH_X11_XINPUT
366                 Atom TABLET;
367 #endif
368         } m_atom;
369
370 #ifdef WITH_X11_XINPUT
371         XExtensionVersion m_xinput_version;
372 #endif
373
374 private:
375
376         Display *m_display;
377
378         /* Use for scancode lookups. */
379         XkbDescRec *m_xkb_descr;
380
381 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
382         XIM m_xim;
383 #endif
384
385 #ifdef WITH_X11_XINPUT
386         /* Tablet devices */
387         GHOST_TabletX11 m_xtablet;
388 #endif
389
390         /// The vector of windows that need to be updated.
391         std::vector<GHOST_WindowX11 *> m_dirty_windows;
392
393         /// Start time at initialization.
394         GHOST_TUns64 m_start_time;
395
396         /// A vector of keyboard key masks
397         char m_keyboard_vector[32];
398
399         /* to prevent multiple warp, we store the time of the last warp event
400          *  and stop accumulating all events generated before that */
401         Time m_last_warp;
402
403         /* detect autorepeat glitch */
404         unsigned int m_last_release_keycode;
405         Time m_last_release_time;
406
407         /**
408          * Return the ghost window associated with the
409          * X11 window xwind
410          */
411
412 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
413         bool openX11_IM();
414 #endif
415
416 #ifdef WITH_X11_XINPUT
417         void refreshXInputDevices();
418 #endif
419
420         GHOST_WindowX11 *
421         findGhostWindow(
422             Window xwind
423             ) const;
424
425         void
426         processEvent(
427             XEvent *xe
428             );
429
430         Time
431         lastEventTime(
432             Time default_time
433             );
434
435         bool
436         generateWindowExposeEvents(
437             );
438 };
439
440 #endif
441