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