2 * $Id: GHOST_SystemX11.cpp 10348 2007-03-24 18:41:54Z scourage $
3 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version. The Blender
9 * Foundation also sells licenses for use in proprietary software under
10 * the Blender License. See http://www.blender.org/BL/ for information
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23 * All rights reserved.
25 * The Original Code is: all of this file.
27 * Contributor(s): none yet.
29 * ***** END GPL/BL DUAL LICENSE BLOCK *****
33 * $Id: GHOST_SystemX11.cpp 10348 2007-03-24 18:41:54Z scourage $
34 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
36 * This program is free software; you can redistribute it and/or
37 * modify it under the terms of the GNU General Public License
38 * as published by the Free Software Foundation; either version 2
39 * of the License, or (at your option) any later version. The Blender
40 * Foundation also sells licenses for use in proprietary software under
41 * the Blender License. See http://www.blender.org/BL/ for information
44 * This program is distributed in the hope that it will be useful,
45 * but WITHOUT ANY WARRANTY; without even the implied warranty of
46 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47 * GNU General Public License for more details.
49 * You should have received a copy of the GNU General Public License
50 * along with this program; if not, write to the Free Software Foundation,
51 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
53 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
54 * All rights reserved.
56 * The Original Code is: all of this file.
58 * Contributor(s): none yet.
60 * ***** END GPL/BL DUAL LICENSE BLOCK *****
67 #include "GHOST_SystemX11.h"
68 #include "GHOST_WindowX11.h"
69 #include "GHOST_WindowManager.h"
70 #include "GHOST_TimerManager.h"
71 #include "GHOST_EventCursor.h"
72 #include "GHOST_EventKey.h"
73 #include "GHOST_EventButton.h"
74 #include "GHOST_EventWheel.h"
75 #include "GHOST_DisplayManagerX11.h"
77 #include "GHOST_Debug.h"
79 #include <X11/Xatom.h>
80 #include <X11/keysym.h>
84 #if defined(_SGI_EXTRA_PREDEFINES) && !defined(NO_FAST_ATOMS)
85 #include <X11/SGIFastAtom.h>
87 #define XSGIFastInternAtom(dpy,string,fast_name,how) XInternAtom(dpy,string,how)
99 #include <stdio.h> // for fprintf only
101 //these are for copy and select copy
102 static char *txt_cut_buffer
= NULL
;
103 static char *txt_select_buffer
= NULL
;
113 m_display
= XOpenDisplay(NULL
);
115 if (!m_display
) return;
119 = XSGIFastInternAtom(m_display
,
121 SGI_XA_WM_DELETE_WINDOW
, False
);
124 = XInternAtom(m_display
, "WM_DELETE_WINDOW", True
);
127 // compute the initial time
129 if (gettimeofday(&tv
,NULL
) == -1) {
130 GHOST_ASSERT(false,"Could not instantiate timer!");
133 m_start_time
= GHOST_TUns64(tv
.tv_sec
*1000 + tv
.tv_usec
/1000);
140 GHOST_TSuccess success
= GHOST_System::init();
143 m_keyboard_vector
= new char[32];
145 m_displayManager
= new GHOST_DisplayManagerX11(this);
147 if (m_keyboard_vector
&& m_displayManager
) {
148 return GHOST_kSuccess
;
152 return GHOST_kFailure
;
162 if (gettimeofday(&tv
,NULL
) == -1) {
163 GHOST_ASSERT(false,"Could not compute time!");
166 return GHOST_TUns64(tv
.tv_sec
*1000 + tv
.tv_usec
/1000) - m_start_time
;
173 return GHOST_TUns8(1);
177 * Returns the dimensions of the main display on this system.
178 * @return The dimension of the main display.
182 getMainDisplayDimensions(
187 width
= DisplayWidth(m_display
, DefaultScreen(m_display
));
188 height
= DisplayHeight(m_display
, DefaultScreen(m_display
));
193 * Create a new window.
194 * The new window is added to the list of windows managed.
195 * Never explicitly delete the window, use disposeWindow() instead.
196 * @param title The name of the window (displayed in the title bar of the window if the OS supports it).
197 * @param left The coordinate of the left edge of the window.
198 * @param top The coordinate of the top edge of the window.
199 * @param width The width the window.
200 * @param height The height the window.
201 * @param state The state of the window when opened.
202 * @param type The type of drawing context installed in this window.
203 * @return The new window (or 0 if creation failed).
208 const STR_String
& title
,
213 GHOST_TWindowState state
,
214 GHOST_TDrawingContextType type
,
217 GHOST_WindowX11
* window
= 0;
219 if (!m_display
) return 0;
221 window
= new GHOST_WindowX11 (
222 this,m_display
,title
, left
, top
, width
, height
, state
, type
, stereoVisual
227 // Install a new protocol for this window - so we can overide
228 // the default window closure mechanism.
230 XSetWMProtocols(m_display
, window
->getXWindow(), &m_delete_window_atom
, 1);
232 if (window
->getValid()) {
233 // Store the pointer to the window
234 m_windowManager
->addWindow(window
);
236 pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize
, window
) );
253 if (xwind
== 0) return NULL
;
255 // It is not entirely safe to do this as the backptr may point
256 // to a window that has recently been removed.
257 // We should always check the window manager's list of windows
258 // and only process events on these windows.
260 vector
<GHOST_IWindow
*> & win_vec
= m_windowManager
->getWindows();
262 vector
<GHOST_IWindow
*>::iterator win_it
= win_vec
.begin();
263 vector
<GHOST_IWindow
*>::const_iterator win_end
= win_vec
.end();
265 for (; win_it
!= win_end
; ++win_it
) {
266 GHOST_WindowX11
* window
= static_cast<GHOST_WindowX11
*>(*win_it
);
267 if (window
->getXWindow() == xwind
) {
275 static void SleepTillEvent(Display
*display
, GHOST_TInt64 maxSleep
) {
276 int fd
= ConnectionNumber(display
);
282 if (maxSleep
== -1) {
283 select(fd
+ 1, &fds
, NULL
, NULL
, NULL
);
287 tv
.tv_sec
= maxSleep
/1000;
288 tv
.tv_usec
= (maxSleep
- tv
.tv_sec
*1000)*1000;
290 select(fd
+ 1, &fds
, NULL
, NULL
, &tv
);
299 // Get all the current events -- translate them into
300 // ghost events and call base class pushEvent() method.
302 bool anyProcessed
= false;
305 GHOST_TimerManager
* timerMgr
= getTimerManager();
307 if (waitForEvent
&& m_dirty_windows
.empty() && !XPending(m_display
)) {
308 GHOST_TUns64 next
= timerMgr
->nextFireTime();
310 if (next
==GHOST_kFireTimeNever
) {
311 SleepTillEvent(m_display
, -1);
313 SleepTillEvent(m_display
, next
- getMilliSeconds());
317 if (timerMgr
->fireTimers(getMilliSeconds())) {
321 while (XPending(m_display
)) {
323 XNextEvent(m_display
, &xevent
);
324 processEvent(&xevent
);
328 if (generateWindowExposeEvents()) {
331 } while (waitForEvent
&& !anyProcessed
);
337 GHOST_SystemX11::processEvent(XEvent
*xe
)
339 GHOST_WindowX11
* window
= findGhostWindow(xe
->xany
.window
);
340 GHOST_Event
* g_event
= NULL
;
349 XExposeEvent
& xee
= xe
->xexpose
;
351 if (xee
.count
== 0) {
352 // Only generate a single expose event
353 // per read of the event queue.
358 GHOST_kEventWindowUpdate
,
367 XMotionEvent
&xme
= xe
->xmotion
;
372 GHOST_kEventCursorMove
,
383 XKeyEvent
*xke
= &(xe
->xkey
);
385 KeySym key_sym
= XLookupKeysym(xke
,0);
388 GHOST_TKey gkey
= convertXKey(key_sym
);
389 GHOST_TEventType type
= (xke
->type
== KeyPress
) ?
390 GHOST_kEventKeyDown
: GHOST_kEventKeyUp
;
392 if (!XLookupString(xke
, &ascii
, 1, NULL
, NULL
)) {
410 /* process wheel mouse events and break */
411 if (xe
->xbutton
.button
== 4) {
412 g_event
= new GHOST_EventWheel(getMilliSeconds(), window
, 1);
415 if (xe
->xbutton
.button
== 5) {
416 g_event
= new GHOST_EventWheel(getMilliSeconds(), window
, -1);
423 XButtonEvent
& xbe
= xe
->xbutton
;
424 GHOST_TButtonMask gbmask
= GHOST_kButtonMaskLeft
;
426 switch (xbe
.button
) {
427 case Button1
: gbmask
= GHOST_kButtonMaskLeft
; break;
428 case Button3
: gbmask
= GHOST_kButtonMaskRight
; break;
430 case Button2
: gbmask
= GHOST_kButtonMaskMiddle
; break;
433 GHOST_TEventType type
= (xbe
.type
== ButtonPress
) ?
434 GHOST_kEventButtonDown
: GHOST_kEventButtonUp
;
446 // change of size, border, layer etc.
447 case ConfigureNotify
:
449 /* XConfigureEvent & xce = xe->xconfigure; */
454 GHOST_kEventWindowSize
,
463 XFocusChangeEvent
&xfe
= xe
->xfocus
;
465 // May have to look at the type of event and filter some
468 GHOST_TEventType gtype
= (xfe
.type
== FocusIn
) ?
469 GHOST_kEventWindowActivate
: GHOST_kEventWindowDeactivate
;
482 XClientMessageEvent
& xcme
= xe
->xclient
;
485 if ((Atom
) xcme
.data
.l
[0] == m_delete_window_atom
) {
489 GHOST_kEventWindowClose
,
493 /* Unknown client message, ignore */
499 // We're not interested in the following things.(yet...)
501 case GraphicsExpose
:
505 // XCrossingEvents pointer leave enter window.
513 case SelectionRequest
:
516 Atom target
, string
, compound_text
, c_string
;
517 XSelectionRequestEvent
*xse
= &xe
->xselectionrequest
;
519 target
= XInternAtom(m_display
, "TARGETS", False
);
520 string
= XInternAtom(m_display
, "STRING", False
);
521 compound_text
= XInternAtom(m_display
, "COMPOUND_TEXT", False
);
522 c_string
= XInternAtom(m_display
, "C_STRING", False
);
524 /* support obsolete clients */
525 if (xse
->property
== None
) {
526 xse
->property
= xse
->target
;
529 nxe
.xselection
.type
= SelectionNotify
;
530 nxe
.xselection
.requestor
= xse
->requestor
;
531 nxe
.xselection
.property
= xse
->property
;
532 nxe
.xselection
.display
= xse
->display
;
533 nxe
.xselection
.selection
= xse
->selection
;
534 nxe
.xselection
.target
= xse
->target
;
535 nxe
.xselection
.time
= xse
->time
;
537 /*Check to see if the requestor is asking for String*/
538 if(xse
->target
== string
|| xse
->target
== compound_text
|| xse
->target
== c_string
) {
539 if (xse
->selection
== XInternAtom(m_display
, "PRIMARY", False
)) {
540 XChangeProperty(m_display
, xse
->requestor
, xse
->property
, xse
->target
, 8, PropModeReplace
, (unsigned char*)txt_select_buffer
, strlen(txt_select_buffer
));
541 } else if (xse
->selection
== XInternAtom(m_display
, "CLIPBOARD", False
)) {
542 XChangeProperty(m_display
, xse
->requestor
, xse
->property
, xse
->target
, 8, PropModeReplace
, (unsigned char*)txt_cut_buffer
, strlen(txt_cut_buffer
));
544 } else if (xse
->target
== target
) {
548 alist
[2] = compound_text
;
550 XChangeProperty(m_display
, xse
->requestor
, xse
->property
, xse
->target
, 32, PropModeReplace
, (unsigned char*)alist
, 4);
553 //Change property to None because we do not support anything but STRING
554 nxe
.xselection
.property
= None
;
557 //Send the event to the client 0 0 == False, SelectionNotify
558 XSendEvent(m_display
, xse
->requestor
, 0, 0, &nxe
);
564 if(xe
->type
== window
->GetXTablet().MotionEvent
)
566 XDeviceMotionEvent
* data
= (XDeviceMotionEvent
*)xe
;
567 window
->GetXTablet().CommonData
.Pressure
=
568 data
->axis_data
[2]/((float)window
->GetXTablet().PressureLevels
);
570 /* the (short) cast and the &0xffff is bizarre and unexplained anywhere,
571 * but I got garbage data without it. Found it in the xidump.c source --matt */
572 window
->GetXTablet().CommonData
.Xtilt
=
573 (short)(data
->axis_data
[3]&0xffff)/((float)window
->GetXTablet().XtiltLevels
);
574 window
->GetXTablet().CommonData
.Ytilt
=
575 (short)(data
->axis_data
[4]&0xffff)/((float)window
->GetXTablet().YtiltLevels
);
577 else if(xe
->type
== window
->GetXTablet().ProxInEvent
)
579 XProximityNotifyEvent
* data
= (XProximityNotifyEvent
*)xe
;
580 if(data
->deviceid
== window
->GetXTablet().StylusID
)
581 window
->GetXTablet().CommonData
.Active
= 1;
582 else if(data
->deviceid
== window
->GetXTablet().EraserID
)
583 window
->GetXTablet().CommonData
.Active
= 2;
585 else if(xe
->type
== window
->GetXTablet().ProxOutEvent
)
586 window
->GetXTablet().CommonData
.Active
= 0;
601 GHOST_ModifierKeys
& keys
604 // analyse the masks retuned from XQueryPointer.
606 memset(m_keyboard_vector
,0,sizeof(m_keyboard_vector
));
608 XQueryKeymap(m_display
,m_keyboard_vector
);
610 // now translate key symobols into keycodes and
613 const KeyCode shift_l
= XKeysymToKeycode(m_display
,XK_Shift_L
);
614 const KeyCode shift_r
= XKeysymToKeycode(m_display
,XK_Shift_R
);
615 const KeyCode control_l
= XKeysymToKeycode(m_display
,XK_Control_L
);
616 const KeyCode control_r
= XKeysymToKeycode(m_display
,XK_Control_R
);
617 const KeyCode alt_l
= XKeysymToKeycode(m_display
,XK_Alt_L
);
618 const KeyCode alt_r
= XKeysymToKeycode(m_display
,XK_Alt_R
);
621 if ((m_keyboard_vector
[shift_l
>> 3] >> (shift_l
& 7)) & 1) {
622 keys
.set(GHOST_kModifierKeyLeftShift
,true);
624 keys
.set(GHOST_kModifierKeyLeftShift
,false);
626 if ((m_keyboard_vector
[shift_r
>> 3] >> (shift_r
& 7)) & 1) {
628 keys
.set(GHOST_kModifierKeyRightShift
,true);
630 keys
.set(GHOST_kModifierKeyRightShift
,false);
634 if ((m_keyboard_vector
[control_l
>> 3] >> (control_l
& 7)) & 1) {
635 keys
.set(GHOST_kModifierKeyLeftControl
,true);
637 keys
.set(GHOST_kModifierKeyLeftControl
,false);
639 if ((m_keyboard_vector
[control_r
>> 3] >> (control_r
& 7)) & 1) {
640 keys
.set(GHOST_kModifierKeyRightControl
,true);
642 keys
.set(GHOST_kModifierKeyRightControl
,false);
646 if ((m_keyboard_vector
[alt_l
>> 3] >> (alt_l
& 7)) & 1) {
647 keys
.set(GHOST_kModifierKeyLeftAlt
,true);
649 keys
.set(GHOST_kModifierKeyLeftAlt
,false);
651 if ((m_keyboard_vector
[alt_r
>> 3] >> (alt_r
& 7)) & 1) {
652 keys
.set(GHOST_kModifierKeyRightAlt
,true);
654 keys
.set(GHOST_kModifierKeyRightAlt
,false);
656 return GHOST_kSuccess
;
662 GHOST_Buttons
& buttons
665 Window root_return
, child_return
;
667 unsigned int mask_return
;
671 RootWindow(m_display
,DefaultScreen(m_display
)),
678 return GHOST_kFailure
;
681 if (mask_return
& Button1Mask
) {
682 buttons
.set(GHOST_kButtonMaskLeft
,true);
684 buttons
.set(GHOST_kButtonMaskLeft
,false);
687 if (mask_return
& Button2Mask
) {
688 buttons
.set(GHOST_kButtonMaskMiddle
,true);
690 buttons
.set(GHOST_kButtonMaskMiddle
,false);
693 if (mask_return
& Button3Mask
) {
694 buttons
.set(GHOST_kButtonMaskRight
,true);
696 buttons
.set(GHOST_kButtonMaskRight
,false);
700 return GHOST_kSuccess
;
711 Window root_return
, child_return
;
713 unsigned int mask_return
;
717 RootWindow(m_display
,DefaultScreen(m_display
)),
724 return GHOST_kFailure
;
729 return GHOST_kSuccess
;
740 // This is a brute force move in screen coordinates
741 // XWarpPointer does relative moves so first determine the
742 // current pointer position.
745 if (getCursorPosition(cx
,cy
) == GHOST_kFailure
) {
746 return GHOST_kFailure
;
752 XWarpPointer(m_display
,None
,None
,0,0,0,0,relx
,rely
);
755 return GHOST_kSuccess
;
762 GHOST_WindowX11
* bad_wind
765 GHOST_ASSERT((bad_wind
!= NULL
), "addDirtyWindow() NULL ptr trapped (window)");
767 m_dirty_windows
.push_back(bad_wind
);
773 generateWindowExposeEvents(
776 vector
<GHOST_WindowX11
*>::iterator w_start
= m_dirty_windows
.begin();
777 vector
<GHOST_WindowX11
*>::const_iterator w_end
= m_dirty_windows
.end();
778 bool anyProcessed
= false;
780 for (;w_start
!= w_end
; ++w_start
) {
781 GHOST_Event
* g_event
= new
784 GHOST_kEventWindowUpdate
,
788 (*w_start
)->validate();
796 m_dirty_windows
.clear();
800 #define GXMAP(k,x,y) case x: k = y; break;
809 if ((key
>= XK_A
) && (key
<= XK_Z
)) {
810 type
= GHOST_TKey( key
- XK_A
+ int(GHOST_kKeyA
));
811 } else if ((key
>= XK_a
) && (key
<= XK_z
)) {
812 type
= GHOST_TKey(key
- XK_a
+ int(GHOST_kKeyA
));
813 } else if ((key
>= XK_0
) && (key
<= XK_9
)) {
814 type
= GHOST_TKey(key
- XK_0
+ int(GHOST_kKey0
));
815 } else if ((key
>= XK_F1
) && (key
<= XK_F24
)) {
816 type
= GHOST_TKey(key
- XK_F1
+ int(GHOST_kKeyF1
));
817 #if defined(__sun) || defined(__sun__)
818 /* This is a bit of a hack, but it looks like sun
819 Used F11 and friends for its special keys Stop,again etc..
820 So this little patch enables F11 and F12 to work as expected
821 following link has documentation on it:
822 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4734408
823 also from /usr/include/X11/Sunkeysym.h
824 #define SunXK_F36 0x1005FF10 // Labeled F11
825 #define SunXK_F37 0x1005FF11 // Labeled F12
830 } else if (key
== 268828432) {
831 type
= GHOST_kKeyF11
;
832 } else if (key
== 268828433) {
833 type
= GHOST_kKeyF12
;
837 GXMAP(type
,XK_BackSpace
, GHOST_kKeyBackSpace
);
838 GXMAP(type
,XK_Tab
, GHOST_kKeyTab
);
839 GXMAP(type
,XK_Return
, GHOST_kKeyEnter
);
840 GXMAP(type
,XK_Escape
, GHOST_kKeyEsc
);
841 GXMAP(type
,XK_space
, GHOST_kKeySpace
);
843 GXMAP(type
,XK_Linefeed
, GHOST_kKeyLinefeed
);
844 GXMAP(type
,XK_semicolon
, GHOST_kKeySemicolon
);
845 GXMAP(type
,XK_period
, GHOST_kKeyPeriod
);
846 GXMAP(type
,XK_comma
, GHOST_kKeyComma
);
847 GXMAP(type
,XK_quoteright
, GHOST_kKeyQuote
);
848 GXMAP(type
,XK_quoteleft
, GHOST_kKeyAccentGrave
);
849 GXMAP(type
,XK_minus
, GHOST_kKeyMinus
);
850 GXMAP(type
,XK_slash
, GHOST_kKeySlash
);
851 GXMAP(type
,XK_backslash
, GHOST_kKeyBackslash
);
852 GXMAP(type
,XK_equal
, GHOST_kKeyEqual
);
853 GXMAP(type
,XK_bracketleft
, GHOST_kKeyLeftBracket
);
854 GXMAP(type
,XK_bracketright
, GHOST_kKeyRightBracket
);
855 GXMAP(type
,XK_Pause
, GHOST_kKeyPause
);
857 GXMAP(type
,XK_Shift_L
, GHOST_kKeyLeftShift
);
858 GXMAP(type
,XK_Shift_R
, GHOST_kKeyRightShift
);
859 GXMAP(type
,XK_Control_L
, GHOST_kKeyLeftControl
);
860 GXMAP(type
,XK_Control_R
, GHOST_kKeyRightControl
);
861 GXMAP(type
,XK_Alt_L
, GHOST_kKeyLeftAlt
);
862 GXMAP(type
,XK_Alt_R
, GHOST_kKeyRightAlt
);
864 GXMAP(type
,XK_Insert
, GHOST_kKeyInsert
);
865 GXMAP(type
,XK_Delete
, GHOST_kKeyDelete
);
866 GXMAP(type
,XK_Home
, GHOST_kKeyHome
);
867 GXMAP(type
,XK_End
, GHOST_kKeyEnd
);
868 GXMAP(type
,XK_Page_Up
, GHOST_kKeyUpPage
);
869 GXMAP(type
,XK_Page_Down
, GHOST_kKeyDownPage
);
871 GXMAP(type
,XK_Left
, GHOST_kKeyLeftArrow
);
872 GXMAP(type
,XK_Right
, GHOST_kKeyRightArrow
);
873 GXMAP(type
,XK_Up
, GHOST_kKeyUpArrow
);
874 GXMAP(type
,XK_Down
, GHOST_kKeyDownArrow
);
876 GXMAP(type
,XK_Caps_Lock
, GHOST_kKeyCapsLock
);
877 GXMAP(type
,XK_Scroll_Lock
, GHOST_kKeyScrollLock
);
878 GXMAP(type
,XK_Num_Lock
, GHOST_kKeyNumLock
);
882 GXMAP(type
,XK_KP_0
, GHOST_kKeyNumpad0
);
883 GXMAP(type
,XK_KP_1
, GHOST_kKeyNumpad1
);
884 GXMAP(type
,XK_KP_2
, GHOST_kKeyNumpad2
);
885 GXMAP(type
,XK_KP_3
, GHOST_kKeyNumpad3
);
886 GXMAP(type
,XK_KP_4
, GHOST_kKeyNumpad4
);
887 GXMAP(type
,XK_KP_5
, GHOST_kKeyNumpad5
);
888 GXMAP(type
,XK_KP_6
, GHOST_kKeyNumpad6
);
889 GXMAP(type
,XK_KP_7
, GHOST_kKeyNumpad7
);
890 GXMAP(type
,XK_KP_8
, GHOST_kKeyNumpad8
);
891 GXMAP(type
,XK_KP_9
, GHOST_kKeyNumpad9
);
892 GXMAP(type
,XK_KP_Decimal
, GHOST_kKeyNumpadPeriod
);
894 GXMAP(type
,XK_KP_Insert
, GHOST_kKeyNumpad0
);
895 GXMAP(type
,XK_KP_End
, GHOST_kKeyNumpad1
);
896 GXMAP(type
,XK_KP_Down
, GHOST_kKeyNumpad2
);
897 GXMAP(type
,XK_KP_Page_Down
, GHOST_kKeyNumpad3
);
898 GXMAP(type
,XK_KP_Left
, GHOST_kKeyNumpad4
);
899 GXMAP(type
,XK_KP_Begin
, GHOST_kKeyNumpad5
);
900 GXMAP(type
,XK_KP_Right
, GHOST_kKeyNumpad6
);
901 GXMAP(type
,XK_KP_Home
, GHOST_kKeyNumpad7
);
902 GXMAP(type
,XK_KP_Up
, GHOST_kKeyNumpad8
);
903 GXMAP(type
,XK_KP_Page_Up
, GHOST_kKeyNumpad9
);
904 GXMAP(type
,XK_KP_Delete
, GHOST_kKeyNumpadPeriod
);
906 GXMAP(type
,XK_KP_Enter
, GHOST_kKeyNumpadEnter
);
907 GXMAP(type
,XK_KP_Add
, GHOST_kKeyNumpadPlus
);
908 GXMAP(type
,XK_KP_Subtract
, GHOST_kKeyNumpadMinus
);
909 GXMAP(type
,XK_KP_Multiply
, GHOST_kKeyNumpadAsterisk
);
910 GXMAP(type
,XK_KP_Divide
, GHOST_kKeyNumpadSlash
);
912 /* some extra sun cruft (NICE KEYBOARD!) */
914 GXMAP(type
,0xffde, GHOST_kKeyNumpad1
);
915 GXMAP(type
,0xffe0, GHOST_kKeyNumpad3
);
916 GXMAP(type
,0xffdc, GHOST_kKeyNumpad5
);
917 GXMAP(type
,0xffd8, GHOST_kKeyNumpad7
);
918 GXMAP(type
,0xffda, GHOST_kKeyNumpad9
);
920 GXMAP(type
,0xffd6, GHOST_kKeyNumpadSlash
);
921 GXMAP(type
,0xffd7, GHOST_kKeyNumpadAsterisk
);
925 type
= GHOST_kKeyUnknown
;
937 getClipboard(int flag
940 //0 = Regular clipboard 1 = selection
941 static Atom Primary_atom
, clip_String
, compound_text
;
943 Window m_window
, owner
;
944 unsigned char *data
, *tmp_data
;
946 unsigned long len
, bytes
;
949 vector
<GHOST_IWindow
*> & win_vec
= m_windowManager
->getWindows();
950 vector
<GHOST_IWindow
*>::iterator win_it
= win_vec
.begin();
951 GHOST_WindowX11
* window
= static_cast<GHOST_WindowX11
*>(*win_it
);
952 m_window
= window
->getXWindow();
954 clip_String
= XInternAtom(m_display
, "_BLENDER_STRING", False
);
955 compound_text
= XInternAtom(m_display
, "COMPOUND_TEXT", False
);
957 //lets check the owner and if it is us then return the static buffer
959 Primary_atom
= XInternAtom(m_display
, "CLIPBOARD", False
);
960 owner
= XGetSelectionOwner(m_display
, Primary_atom
);
961 if (owner
== m_window
) {
962 data
= (unsigned char*) malloc(strlen(txt_cut_buffer
));
963 strcpy((char*)data
, txt_cut_buffer
);
964 return (GHOST_TUns8
*)data
;
965 } else if (owner
== None
) {
969 Primary_atom
= XInternAtom(m_display
, "PRIMARY", False
);
970 owner
= XGetSelectionOwner(m_display
, Primary_atom
);
971 if (owner
== m_window
) {
972 data
= (unsigned char*) malloc(strlen(txt_select_buffer
));
973 strcpy((char*)data
, txt_select_buffer
);
974 return (GHOST_TUns8
*)data
;
975 } else if (owner
== None
) {
984 XDeleteProperty(m_display
, m_window
, Primary_atom
);
985 XConvertSelection(m_display
, Primary_atom
, compound_text
, clip_String
, m_window
, CurrentTime
); //XA_STRING
988 //This needs to change so we do not wait for ever or check owner first
990 XNextEvent(m_display
, &xevent
);
991 if(xevent
.type
== SelectionNotify
) {
992 if(XGetWindowProperty(m_display
, m_window
, xevent
.xselection
.property
, 0L, 4096L, False
, AnyPropertyType
, &rtype
, &bits
, &len
, &bytes
, &data
) == Success
) {
994 tmp_data
= (unsigned char*) malloc(strlen((char*)data
));
995 strcpy((char*)tmp_data
, (char*)data
);
997 return (GHOST_TUns8
*)tmp_data
;
1008 GHOST_TInt8
*buffer
, int flag
) const
1010 static Atom Primary_atom
;
1011 Window m_window
, owner
;
1013 if(!buffer
) {return;}
1016 Primary_atom
= XInternAtom(m_display
, "CLIPBOARD", False
);
1017 if(txt_cut_buffer
) { free((void*)txt_cut_buffer
); }
1019 txt_cut_buffer
= (char*) malloc(strlen(buffer
));
1020 strcpy(txt_cut_buffer
, buffer
);
1022 Primary_atom
= XInternAtom(m_display
, "PRIMARY", False
);
1023 if(txt_select_buffer
) { free((void*)txt_select_buffer
); }
1025 txt_select_buffer
= (char*) malloc(strlen(buffer
));
1026 strcpy(txt_select_buffer
, buffer
);
1029 vector
<GHOST_IWindow
*> & win_vec
= m_windowManager
->getWindows();
1030 vector
<GHOST_IWindow
*>::iterator win_it
= win_vec
.begin();
1031 GHOST_WindowX11
* window
= static_cast<GHOST_WindowX11
*>(*win_it
);
1032 m_window
= window
->getXWindow();
1038 XSetSelectionOwner(m_display
, Primary_atom
, m_window
, CurrentTime
);
1039 owner
= XGetSelectionOwner(m_display
, Primary_atom
);
1040 if (owner
!= m_window
)
1041 fprintf(stderr
, "failed to own primary\n");