1 /* 2 * This program is free software; you can redistribute it and/or 3 * modify it under the terms of the GNU General Public License 4 * as published by the Free Software Foundation; either version 2 5 * of the License, or (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software Foundation, 14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 15 * 16 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 17 * All rights reserved. 18 */ 19 20 /** \file 21 * \ingroup GHOST 22 * Declaration of GHOST_SystemX11 class. 23 */ 24 25 #pragma once 26 27 #include <X11/XKBlib.h> /* allow detectable autorepeate */ 28 #include <X11/Xlib.h> 29 30 #include "../GHOST_Types.h" 31 #include "GHOST_System.h" 32 33 // For tablets 34 #ifdef WITH_X11_XINPUT 35 # include <X11/extensions/XInput.h> 36 37 /* Disable xinput warp, currently not implemented by Xorg for multi-head display. 38 * (see comment in xserver "Xi/xiwarppointer.c" -> "FIXME: panoramix stuff is missing" ~ v1.13.4) 39 * If this is supported we can add back xinput for warping (fixing T48901). 40 * For now disable (see T50383). */ 41 // # define USE_X11_XINPUT_WARP 42 #endif 43 44 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING) 45 # define GHOST_X11_RES_NAME "Blender" /* res_name */ 46 # define GHOST_X11_RES_CLASS "Blender" /* res_class */ 47 #endif 48 49 /* generic error handlers */ 50 int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent); 51 int GHOST_X11_ApplicationIOErrorHandler(Display *display); 52 53 #define GHOST_X11_ERROR_HANDLERS_OVERRIDE(var) \ 54 struct { \ 55 XErrorHandler handler; \ 56 XIOErrorHandler handler_io; \ 57 } var = { \ 58 XSetErrorHandler(GHOST_X11_ApplicationErrorHandler), \ 59 XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler), \ 60 } 61 62 #define GHOST_X11_ERROR_HANDLERS_RESTORE(var) \ 63 { \ 64 (void)XSetErrorHandler(var.handler); \ 65 (void)XSetIOErrorHandler(var.handler_io); \ 66 } \ 67 ((void)0) 68 69 class GHOST_WindowX11; 70 71 /** 72 * X11 Implementation of GHOST_System class. 73 * \see GHOST_System. 74 */ 75 76 class GHOST_SystemX11 : public GHOST_System { 77 public: 78 /** 79 * Constructor 80 * this class should only be instantiated by GHOST_ISystem. 81 */ 82 83 GHOST_SystemX11(); 84 85 /** 86 * Destructor. 87 */ 88 ~GHOST_SystemX11(); 89 90 GHOST_TSuccess init(); 91 92 /** 93 * \section Interface Inherited from GHOST_ISystem 94 */ 95 96 /** 97 * Returns the system time. 98 * Returns the number of milliseconds since the start of the system process. 99 * \return The number of milliseconds. 100 */ 101 GHOST_TUns64 getMilliSeconds() const; 102 103 /** 104 * Returns the number of displays on this system. 105 * \return The number of displays. 106 */ 107 GHOST_TUns8 getNumDisplays() const; 108 109 /** 110 * Returns the dimensions of the main display on this system. 111 * \return The dimension of the main display. 112 */ 113 void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const; 114 115 /** 116 * Returns the dimensions of all displays on this system. 117 * \return The dimension of the main display. 118 */ 119 void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const; 120 121 /** 122 * Create a new window. 123 * The new window is added to the list of windows managed. 124 * Never explicitly delete the window, use disposeWindow() instead. 125 * \param title The name of the window 126 * (displayed in the title bar of the window if the OS supports it). 127 * \param left The coordinate of the left edge of the window. 128 * \param top The coordinate of the top edge of the window. 129 * \param width The width the window. 130 * \param height The height the window. 131 * \param state The state of the window when opened. 132 * \param type The type of drawing context installed in this window. 133 * \param stereoVisual Create a stereo visual for quad buffered stereo. 134 * \param exclusive Use to show the window ontop and ignore others 135 * (used fullscreen). 136 * \param parentWindow Parent (embedder) window 137 * \return The new window (or 0 if creation failed). 138 */ 139 GHOST_IWindow *createWindow(const char *title, 140 GHOST_TInt32 left, 141 GHOST_TInt32 top, 142 GHOST_TUns32 width, 143 GHOST_TUns32 height, 144 GHOST_TWindowState state, 145 GHOST_TDrawingContextType type, 146 GHOST_GLSettings glSettings, 147 const bool exclusive = false, 148 const bool is_dialog = false, 149 const GHOST_IWindow *parentWindow = 0); 150 151 /** 152 * Create a new offscreen context. 153 * Never explicitly delete the context, use disposeContext() instead. 154 * \return The new context (or 0 if creation failed). 155 */ 156 GHOST_IContext *createOffscreenContext(GHOST_GLSettings glSettings); 157 158 /** 159 * Dispose of a context. 160 * \param context Pointer to the context to be disposed. 161 * \return Indication of success. 162 */ 163 GHOST_TSuccess disposeContext(GHOST_IContext *context); 164 165 /** 166 * Retrieves events from the system and stores them in the queue. 167 * \param waitForEvent Flag to wait for an event (or return immediately). 168 * \return Indication of the presence of events. 169 */ 170 bool processEvents(bool waitForEvent); 171 172 GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const; 173 174 GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); 175 176 /** 177 * Returns the state of all modifier keys. 178 * \param keys The state of all modifier keys (true == pressed). 179 * \return Indication of success. 180 */ 181 GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const; 182 183 /** 184 * Returns the state of the mouse buttons (outside the message queue). 185 * \param buttons The state of the buttons. 186 * \return Indication of success. 187 */ 188 GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const; 189 190 /** 191 * Flag a window as dirty. This will 192 * generate a GHOST window update event on a call to processEvents() 193 */ 194 195 void addDirtyWindow(GHOST_WindowX11 *bad_wind); 196 197 /** 198 * return a pointer to the X11 display structure 199 */ 200 getXDisplay()201 Display *getXDisplay() 202 { 203 return m_display; 204 } 205 206 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING) getX11_XIM()207 XIM getX11_XIM() 208 { 209 return m_xim; 210 } 211 #endif 212 213 /** Helped function for get data from the clipboard. */ 214 void getClipboard_xcout(const XEvent *evt, 215 Atom sel, 216 Atom target, 217 unsigned char **txt, 218 unsigned long *len, 219 unsigned int *context) const; 220 221 /** 222 * Returns unsigned char from CUT_BUFFER0 223 * \param selection Get selection, X11 only feature 224 * \return Returns the Clipboard indicated by Flag 225 */ 226 GHOST_TUns8 *getClipboard(bool selection) const; 227 228 /** 229 * Puts buffer to system clipboard 230 * \param buffer The buffer to copy to the clipboard 231 * \param selection Set the selection into the clipboard, X11 only feature 232 */ 233 void putClipboard(GHOST_TInt8 *buffer, bool selection) const; 234 235 /** 236 * Show a system message box 237 * \param title The title of the message box 238 * \param message The message to display 239 * \param help_label Help button label 240 * \param continue_label Continue button label 241 * \param link An optional hyperlink 242 * \param dialog_options Options how to display the message 243 */ 244 GHOST_TSuccess showMessageBox(const char *title, 245 const char *message, 246 const char *help_label, 247 const char *continue_label, 248 const char *link, 249 GHOST_DialogOptions dialog_options) const; 250 #ifdef WITH_XDND 251 /** 252 * Creates a drag'n'drop event and pushes it immediately onto the event queue. 253 * Called by GHOST_DropTargetX11 class. 254 * \param eventType The type of drag'n'drop event 255 * \param draggedObjectType The type object concerned 256 * (currently array of file names, string, ?bitmap) 257 * \param mouseX x mouse coordinate (in window coordinates) 258 * \param mouseY y mouse coordinate 259 * \param window The window on which the event occurred 260 * \return Indication whether the event was handled. 261 */ 262 static GHOST_TSuccess pushDragDropEvent(GHOST_TEventType eventType, 263 GHOST_TDragnDropTypes draggedObjectType, 264 GHOST_IWindow *window, 265 int mouseX, 266 int mouseY, 267 void *data); 268 #endif 269 270 /** 271 * \see GHOST_ISystem 272 */ toggleConsole(int)273 int toggleConsole(int /*action*/) 274 { 275 return 0; 276 } 277 278 #ifdef WITH_X11_XINPUT 279 typedef struct GHOST_TabletX11 { 280 GHOST_TTabletMode mode; 281 XDevice *Device; 282 XID ID; 283 284 int MotionEvent; 285 int ProxInEvent; 286 int ProxOutEvent; 287 int PressEvent; 288 289 int PressureLevels; 290 int XtiltLevels, YtiltLevels; 291 } GHOST_TabletX11; 292 GetXTablets()293 std::vector<GHOST_TabletX11> &GetXTablets() 294 { 295 return m_xtablets; 296 } 297 #endif // WITH_X11_XINPUT 298 299 struct { 300 /** 301 * Atom used for ICCCM, WM-spec and Motif. 302 * We only need get this atom at the start, it's relative 303 * to the display not the window and are public for every 304 * window that need it. 305 */ 306 Atom WM_STATE; 307 Atom WM_CHANGE_STATE; 308 Atom _NET_WM_STATE; 309 Atom _NET_WM_STATE_MAXIMIZED_HORZ; 310 Atom _NET_WM_STATE_MAXIMIZED_VERT; 311 Atom _NET_WM_STATE_FULLSCREEN; 312 Atom _MOTIF_WM_HINTS; 313 Atom WM_TAKE_FOCUS; 314 Atom WM_PROTOCOLS; 315 Atom WM_DELETE_WINDOW; 316 317 /* Atoms for Selection, copy & paste. */ 318 Atom TARGETS; 319 Atom STRING; 320 Atom COMPOUND_TEXT; 321 Atom TEXT; 322 Atom CLIPBOARD; 323 Atom PRIMARY; 324 Atom XCLIP_OUT; 325 Atom INCR; 326 Atom UTF8_STRING; 327 #ifdef WITH_X11_XINPUT 328 Atom TABLET; 329 #endif 330 } m_atom; 331 332 #ifdef WITH_X11_XINPUT 333 XExtensionVersion m_xinput_version; 334 #endif 335 336 private: 337 Display *m_display; 338 339 /** Use for scan-code look-ups. */ 340 XkbDescRec *m_xkb_descr; 341 342 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING) 343 XIM m_xim; 344 #endif 345 346 #ifdef WITH_X11_XINPUT 347 /* Tablet devices */ 348 std::vector<GHOST_TabletX11> m_xtablets; 349 #endif 350 351 /** The vector of windows that need to be updated. */ 352 std::vector<GHOST_WindowX11 *> m_dirty_windows; 353 354 /** Start time at initialization. */ 355 GHOST_TUns64 m_start_time; 356 357 /** A vector of keyboard key masks. */ 358 char m_keyboard_vector[32]; 359 360 /** 361 * To prevent multiple warp, we store the time of the last warp event 362 * and stop accumulating all events generated before that. 363 */ 364 Time m_last_warp_x; 365 Time m_last_warp_y; 366 367 /* Detect auto-repeat glitch. */ 368 unsigned int m_last_release_keycode; 369 Time m_last_release_time; 370 371 uint m_keycode_last_repeat_key; 372 373 /** 374 * Return the ghost window associated with the 375 * X11 window xwind 376 */ 377 378 #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING) 379 bool openX11_IM(); 380 #endif 381 382 #ifdef WITH_X11_XINPUT 383 void clearXInputDevices(); 384 void refreshXInputDevices(); 385 #endif 386 387 GHOST_WindowX11 *findGhostWindow(Window xwind) const; 388 389 void processEvent(XEvent *xe); 390 391 Time lastEventTime(Time default_time); 392 393 bool generateWindowExposeEvents(); 394 }; 395