merged from trunk 20741:20848
[blender.git] / intern / ghost / intern / GHOST_SystemX11.cpp
1 /**
2  * $Id$
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
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.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32
33 #include "GHOST_SystemX11.h"
34 #include "GHOST_WindowX11.h"
35 #include "GHOST_WindowManager.h"
36 #include "GHOST_TimerManager.h"
37 #include "GHOST_EventCursor.h"
38 #include "GHOST_EventKey.h"
39 #include "GHOST_EventButton.h"
40 #include "GHOST_EventWheel.h"
41 #include "GHOST_EventNDOF.h"
42 #include "GHOST_NDOFManager.h"
43 #include "GHOST_DisplayManagerX11.h"
44
45 #include "GHOST_Debug.h"
46
47 #include <X11/Xatom.h>
48 #include <X11/keysym.h>
49 #include <X11/XKBlib.h> /* allow detectable autorepeate */
50
51 #ifdef __sgi
52
53 #if defined(_SGI_EXTRA_PREDEFINES) && !defined(NO_FAST_ATOMS)
54 #include <X11/SGIFastAtom.h>
55 #else
56 #define XSGIFastInternAtom(dpy,string,fast_name,how) XInternAtom(dpy,string,how)
57 #endif
58
59 #endif
60
61 // For timing
62
63 #include <sys/time.h>
64 #include <unistd.h>
65
66 #include <vector>
67 #include <stdio.h> // for fprintf only
68
69 typedef struct NDOFPlatformInfo {
70         Display *display;
71         Window window;
72         volatile GHOST_TEventNDOFData *currValues;
73         Atom cmdAtom;
74         Atom motionAtom;
75         Atom btnPressAtom;
76         Atom btnRelAtom;
77 } NDOFPlatformInfo;
78
79 static NDOFPlatformInfo sNdofInfo = {NULL, 0, NULL, 0, 0, 0, 0};
80
81
82 //these are for copy and select copy
83 static char *txt_cut_buffer= NULL;
84 static char *txt_select_buffer= NULL;
85
86 using namespace std;
87
88 GHOST_SystemX11::
89 GHOST_SystemX11(
90 ) : 
91         GHOST_System(),
92         m_start_time(0)
93 {
94         m_display = XOpenDisplay(NULL);
95         
96         if (!m_display) return;
97         
98 #ifdef __sgi
99         m_delete_window_atom 
100           = XSGIFastInternAtom(m_display,
101                                "WM_DELETE_WINDOW", 
102                                SGI_XA_WM_DELETE_WINDOW, False);
103 #else
104         m_delete_window_atom 
105           = XInternAtom(m_display, "WM_DELETE_WINDOW", True);
106 #endif
107
108         m_wm_protocols= XInternAtom(m_display, "WM_PROTOCOLS", False);
109         m_wm_take_focus= XInternAtom(m_display, "WM_TAKE_FOCUS", False);
110         m_wm_state= XInternAtom(m_display, "WM_STATE", False);
111         m_wm_change_state= XInternAtom(m_display, "WM_CHANGE_STATE", False);
112         m_net_state= XInternAtom(m_display, "_NET_WM_STATE", False);
113         m_net_max_horz= XInternAtom(m_display,
114                                         "_NET_WM_STATE_MAXIMIZED_HORZ", False);
115         m_net_max_vert= XInternAtom(m_display,
116                                         "_NET_WM_STATE_MAXIMIZED_VERT", False);
117         m_net_fullscreen= XInternAtom(m_display,
118                                         "_NET_WM_STATE_FULLSCREEN", False);
119         m_motif= XInternAtom(m_display, "_MOTIF_WM_HINTS", False);
120         m_targets= XInternAtom(m_display, "TARGETS", False);
121         m_string= XInternAtom(m_display, "STRING", False);
122         m_compound_text= XInternAtom(m_display, "COMPOUND_TEXT", False);
123         m_text= XInternAtom(m_display, "TEXT", False);
124         m_clipboard= XInternAtom(m_display, "CLIPBOARD", False);
125         m_primary= XInternAtom(m_display, "PRIMARY", False);
126         m_xclip_out= XInternAtom(m_display, "XCLIP_OUT", False);
127         m_incr= XInternAtom(m_display, "INCR", False);
128         m_utf8_string= XInternAtom(m_display, "UTF8_STRING", False);
129
130         // compute the initial time
131         timeval tv;
132         if (gettimeofday(&tv,NULL) == -1) {
133                 GHOST_ASSERT(false,"Could not instantiate timer!");
134         }
135
136         m_start_time = GHOST_TUns64(tv.tv_sec*1000 + tv.tv_usec/1000);
137         
138         
139         /* use detectable autorepeate, mac and windows also do this */
140         int use_xkb;
141         int xkb_opcode, xkb_event, xkb_error;
142         int xkb_major = XkbMajorVersion, xkb_minor = XkbMinorVersion;
143         
144         use_xkb = XkbQueryExtension(m_display, &xkb_opcode, &xkb_event, &xkb_error, &xkb_major, &xkb_minor);
145         if (use_xkb) {
146                 XkbSetDetectableAutoRepeat(m_display, true, NULL);
147         }
148         
149 }
150
151         GHOST_TSuccess 
152 GHOST_SystemX11::
153 init(
154 ){
155         GHOST_TSuccess success = GHOST_System::init();
156
157         if (success) {
158                 m_keyboard_vector = new char[32];
159
160                 m_displayManager = new GHOST_DisplayManagerX11(this);
161
162                 if (m_keyboard_vector && m_displayManager) {
163                         return GHOST_kSuccess;
164                 }
165         }
166
167         return GHOST_kFailure;
168 }
169
170         GHOST_TUns64
171 GHOST_SystemX11::
172 getMilliSeconds(
173 ) const {
174         timeval tv;
175         if (gettimeofday(&tv,NULL) == -1) {
176                 GHOST_ASSERT(false,"Could not compute time!");
177         }
178
179         return  GHOST_TUns64(tv.tv_sec*1000 + tv.tv_usec/1000) - m_start_time;
180 }
181         
182         GHOST_TUns8 
183 GHOST_SystemX11::
184 getNumDisplays(
185 ) const {
186         return GHOST_TUns8(1);
187 }
188
189         /**
190          * Returns the dimensions of the main display on this system.
191          * @return The dimension of the main display.
192          */
193         void 
194 GHOST_SystemX11::
195 getMainDisplayDimensions(
196         GHOST_TUns32& width,
197         GHOST_TUns32& height
198 ) const {       
199         if (m_display) {
200                 width  = DisplayWidth(m_display, DefaultScreen(m_display));
201                 height = DisplayHeight(m_display, DefaultScreen(m_display));
202         }
203 }
204
205         /**
206          * Create a new window.
207          * The new window is added to the list of windows managed.
208          * Never explicitly delete the window, use disposeWindow() instead.
209          * @param       title   The name of the window (displayed in the title bar of the window if the OS supports it).
210          * @param       left    The coordinate of the left edge of the window.
211          * @param       top             The coordinate of the top edge of the window.
212          * @param       width   The width the window.
213          * @param       height  The height the window.
214          * @param       state   The state of the window when opened.
215          * @param       type    The type of drawing context installed in this window.
216          * @param       parentWindow    Parent (embedder) window
217          * @return      The new window (or 0 if creation failed).
218          */
219         GHOST_IWindow* 
220 GHOST_SystemX11::
221 createWindow(
222         const STR_String& title,
223         GHOST_TInt32 left,
224         GHOST_TInt32 top,
225         GHOST_TUns32 width,
226         GHOST_TUns32 height,
227         GHOST_TWindowState state,
228         GHOST_TDrawingContextType type,
229         bool stereoVisual,
230         const GHOST_TEmbedderWindowID parentWindow
231 ){
232         GHOST_WindowX11 * window = 0;
233         
234         if (!m_display) return 0;
235         
236
237         
238
239         window = new GHOST_WindowX11 (
240                 this,m_display,title, left, top, width, height, state, parentWindow, type, stereoVisual
241         );
242
243         if (window) {
244                 // Both are now handle in GHOST_WindowX11.cpp
245                 // Focus and Delete atoms.
246
247                 if (window->getValid()) {
248                         // Store the pointer to the window 
249                         m_windowManager->addWindow(window);
250                         
251                         pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
252                 }
253                 else {
254                         delete window;
255                         window = 0;
256                 }
257         }
258         return window;
259 }
260
261         GHOST_WindowX11 * 
262 GHOST_SystemX11::
263 findGhostWindow(
264         Window xwind
265 ) const {
266         
267         if (xwind == 0) return NULL;
268
269         // It is not entirely safe to do this as the backptr may point
270         // to a window that has recently been removed. 
271         // We should always check the window manager's list of windows 
272         // and only process events on these windows.
273
274         vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
275
276         vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
277         vector<GHOST_IWindow *>::const_iterator win_end = win_vec.end();
278         
279         for (; win_it != win_end; ++win_it) {
280                 GHOST_WindowX11 * window = static_cast<GHOST_WindowX11 *>(*win_it);
281                 if (window->getXWindow() == xwind) {
282                         return window;
283                 }
284         }
285         return NULL;
286         
287 }
288
289 static void SleepTillEvent(Display *display, GHOST_TInt64 maxSleep) {
290         int fd = ConnectionNumber(display);
291         fd_set fds;
292         
293         FD_ZERO(&fds);
294         FD_SET(fd, &fds);
295
296         if (maxSleep == -1) {
297             select(fd + 1, &fds, NULL, NULL, NULL);
298         } else {
299                 timeval tv;
300
301                 tv.tv_sec = maxSleep/1000;
302                 tv.tv_usec = (maxSleep - tv.tv_sec*1000)*1000;
303         
304             select(fd + 1, &fds, NULL, NULL, &tv);
305         }
306 }
307
308         bool 
309 GHOST_SystemX11::
310 processEvents(
311         bool waitForEvent
312 ){
313         // Get all the current events -- translate them into 
314         // ghost events and call base class pushEvent() method.
315         
316         bool anyProcessed = false;
317         
318         do {
319                 GHOST_TimerManager* timerMgr = getTimerManager();
320                 
321                 if (waitForEvent && m_dirty_windows.empty() && !XPending(m_display)) {
322                         GHOST_TUns64 next = timerMgr->nextFireTime();
323                         
324                         if (next==GHOST_kFireTimeNever) {
325                                 SleepTillEvent(m_display, -1);
326                         } else {
327                                 GHOST_TInt64 maxSleep = next - getMilliSeconds();
328
329                                 if(maxSleep >= 0)
330                                         SleepTillEvent(m_display, next - getMilliSeconds());
331                         }
332                 }
333                 
334                 if (timerMgr->fireTimers(getMilliSeconds())) {
335                         anyProcessed = true;
336                 }
337                 
338                 while (XPending(m_display)) {
339                         XEvent xevent;
340                         XNextEvent(m_display, &xevent);
341                         processEvent(&xevent);
342                         anyProcessed = true;
343                 }
344                 
345                 if (generateWindowExposeEvents()) {
346                         anyProcessed = true;
347                 }
348         } while (waitForEvent && !anyProcessed);
349         
350         return anyProcessed;
351 }
352
353         void
354 GHOST_SystemX11::processEvent(XEvent *xe)
355 {
356         GHOST_WindowX11 * window = findGhostWindow(xe->xany.window);    
357         GHOST_Event * g_event = NULL;
358
359         if (!window) {
360                 return;
361         }
362         
363         switch (xe->type) {
364                 case Expose:
365                 {
366                         XExposeEvent & xee = xe->xexpose;
367
368                         if (xee.count == 0) {
369                                 // Only generate a single expose event
370                                 // per read of the event queue.
371
372                                 g_event = new 
373                                 GHOST_Event(
374                                         getMilliSeconds(),
375                                         GHOST_kEventWindowUpdate,
376                                         window
377                                 );                      
378                         }
379                         break;
380                 }
381
382                 case MotionNotify:
383                 {
384                         XMotionEvent &xme = xe->xmotion;
385                         
386                         g_event = new 
387                         GHOST_EventCursor(
388                                 getMilliSeconds(),
389                                 GHOST_kEventCursorMove,
390                                 window,
391                                 xme.x_root,
392                                 xme.y_root
393                         );
394                         break;
395                 }
396
397                 case KeyPress:
398                 case KeyRelease:
399                 {
400                         XKeyEvent *xke = &(xe->xkey);
401                 
402                         KeySym key_sym = XLookupKeysym(xke,0);
403                         char ascii;
404                         
405                         GHOST_TKey gkey = convertXKey(key_sym);
406                         GHOST_TEventType type = (xke->type == KeyPress) ? 
407                                 GHOST_kEventKeyDown : GHOST_kEventKeyUp;
408                         
409                         if (!XLookupString(xke, &ascii, 1, NULL, NULL)) {
410                                 ascii = '\0';
411                         }
412                         
413                         g_event = new
414                         GHOST_EventKey(
415                                 getMilliSeconds(),
416                                 type,
417                                 window,
418                                 gkey,
419                                 ascii
420                         );
421                         
422                 break;
423                 }
424
425                 case ButtonPress:
426                 {
427                         /* process wheel mouse events and break */
428                         if (xe->xbutton.button == 4) {
429                                 g_event = new GHOST_EventWheel(getMilliSeconds(), window, 1);
430                                 break;
431                         }
432                         if (xe->xbutton.button == 5) {
433                                 g_event = new GHOST_EventWheel(getMilliSeconds(), window, -1);
434                                 break;
435                         }
436                 }
437                 case ButtonRelease:
438                 {
439
440                         XButtonEvent & xbe = xe->xbutton;
441                         GHOST_TButtonMask gbmask = GHOST_kButtonMaskLeft;
442
443                         switch (xbe.button) {
444                                 case Button1 : gbmask = GHOST_kButtonMaskLeft; break;
445                                 case Button3 : gbmask = GHOST_kButtonMaskRight; break;
446                                 default:
447                                 case Button2 : gbmask = GHOST_kButtonMaskMiddle; break;
448                         }
449                         
450                         GHOST_TEventType type = (xbe.type == ButtonPress) ? 
451                                 GHOST_kEventButtonDown : GHOST_kEventButtonUp;
452                         
453                         g_event = new
454                         GHOST_EventButton(
455                                 getMilliSeconds(),
456                                 type,
457                                 window,
458                                 gbmask
459                         );
460                         break;
461                 }
462                         
463                         // change of size, border, layer etc.
464                 case ConfigureNotify:
465                 {
466                         /* XConfigureEvent & xce = xe->xconfigure; */
467
468                         g_event = new 
469                         GHOST_Event(
470                                 getMilliSeconds(),
471                                 GHOST_kEventWindowSize,
472                                 window
473                         );                      
474                         break;
475                 }
476
477                 case FocusIn:
478                 case FocusOut:
479                 {
480                         XFocusChangeEvent &xfe = xe->xfocus;
481                 
482                         // May have to look at the type of event and filter some
483                         // out.
484                                                                         
485                         GHOST_TEventType gtype = (xfe.type == FocusIn) ? 
486                                 GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate;
487
488                         g_event = new 
489                         GHOST_Event(    
490                                 getMilliSeconds(),
491                                 gtype,
492                                 window
493                         );
494                         break;
495
496                 }
497                 case ClientMessage:
498                 {
499                         XClientMessageEvent & xcme = xe->xclient;
500
501 #ifndef __sgi                   
502                         if (((Atom)xcme.data.l[0]) == m_delete_window_atom) {
503                                 g_event = new 
504                                 GHOST_Event(    
505                                         getMilliSeconds(),
506                                         GHOST_kEventWindowClose,
507                                         window
508                                 );
509                         } else 
510 #endif
511                         if (sNdofInfo.currValues) {
512                                 static GHOST_TEventNDOFData data = {0,0,0,0,0,0,0,0,0,0,0};
513                                 if (xcme.message_type == sNdofInfo.motionAtom)
514                                 {
515                                         data.changed = 1;
516                                         data.delta = xcme.data.s[8] - data.time;
517                                         data.time = xcme.data.s[8];
518                                         data.tx = xcme.data.s[2] >> 2;
519                                         data.ty = xcme.data.s[3] >> 2;
520                                         data.tz = xcme.data.s[4] >> 2;
521                                         data.rx = xcme.data.s[5];
522                                         data.ry = xcme.data.s[6];
523                                         data.rz =-xcme.data.s[7];
524                                         g_event = new GHOST_EventNDOF(getMilliSeconds(),
525                                                                       GHOST_kEventNDOFMotion,
526                                                                       window, data);
527                                 } else if (xcme.message_type == sNdofInfo.btnPressAtom) {
528                                         data.changed = 2;
529                                         data.delta = xcme.data.s[8] - data.time;
530                                         data.time = xcme.data.s[8];
531                                         data.buttons = xcme.data.s[2];
532                                         g_event = new GHOST_EventNDOF(getMilliSeconds(),
533                                                                       GHOST_kEventNDOFButton,
534                                                                       window, data);
535                                 }
536                         } else if (((Atom)xcme.data.l[0]) == m_wm_take_focus) {
537                                 /* as ICCCM say, we need reply this event
538                                  * with a SetInputFocus, the data[1] have
539                                  * the valid timestamp (send by the wm).
540                                  */
541                                 XSetInputFocus(m_display, xcme.window, RevertToParent, xcme.data.l[1]);
542                         } else {
543                                 /* Unknown client message, ignore */
544                         }
545                         break;
546                 }
547                 
548                 case DestroyNotify:
549                         ::exit(-1);     
550                 // We're not interested in the following things.(yet...)
551                 case NoExpose : 
552                 case GraphicsExpose :
553                 
554                 case EnterNotify:
555                 case LeaveNotify:
556                         // XCrossingEvents pointer leave enter window.
557                         break;
558                 case MapNotify:
559                         /*
560                          * From ICCCM:
561                          * [ Clients can select for StructureNotify on their
562                          *   top-level windows to track transition between
563                          *   Normal and Iconic states. Receipt of a MapNotify
564                          *   event will indicate a transition to the Normal
565                          *   state, and receipt of an UnmapNotify event will
566                          *   indicate a transition to the Iconic state. ]
567                          */
568                         if (window->m_post_init == True) {
569                                 /*
570                                  * Now we are sure that the window is
571                                  * mapped, so only need change the state.
572                                  */
573                                 window->setState (window->m_post_state);
574                                 window->m_post_init = False;
575                         }
576                         break;
577                 case UnmapNotify:
578                         break;
579                 case MappingNotify:
580                 case ReparentNotify:
581                         break;
582                 case SelectionRequest:
583                 {
584                         XEvent nxe;
585                         Atom target, string, compound_text, c_string;
586                         XSelectionRequestEvent *xse = &xe->xselectionrequest;
587                         
588                         target = XInternAtom(m_display, "TARGETS", False);
589                         string = XInternAtom(m_display, "STRING", False);
590                         compound_text = XInternAtom(m_display, "COMPOUND_TEXT", False);
591                         c_string = XInternAtom(m_display, "C_STRING", False);
592                         
593                         /* support obsolete clients */
594                         if (xse->property == None) {
595                                 xse->property = xse->target;
596                         }
597                         
598                         nxe.xselection.type = SelectionNotify;
599                         nxe.xselection.requestor = xse->requestor;
600                         nxe.xselection.property = xse->property;
601                         nxe.xselection.display = xse->display;
602                         nxe.xselection.selection = xse->selection;
603                         nxe.xselection.target = xse->target;
604                         nxe.xselection.time = xse->time;
605                         
606                         /*Check to see if the requestor is asking for String*/
607                         if(xse->target == string || xse->target == compound_text || xse->target == c_string) {
608                                 if (xse->selection == XInternAtom(m_display, "PRIMARY", False)) {
609                                         XChangeProperty(m_display, xse->requestor, xse->property, xse->target, 8, PropModeReplace, (unsigned char*)txt_select_buffer, strlen(txt_select_buffer));
610                                 } else if (xse->selection == XInternAtom(m_display, "CLIPBOARD", False)) {
611                                         XChangeProperty(m_display, xse->requestor, xse->property, xse->target, 8, PropModeReplace, (unsigned char*)txt_cut_buffer, strlen(txt_cut_buffer));
612                                 }
613                         } else if (xse->target == target) {
614                                 Atom alist[4];
615                                 alist[0] = target;
616                                 alist[1] = string;
617                                 alist[2] = compound_text;
618                                 alist[3] = c_string;
619                                 XChangeProperty(m_display, xse->requestor, xse->property, xse->target, 32, PropModeReplace, (unsigned char*)alist, 4);
620                                 XFlush(m_display);
621                         } else  {
622                                 //Change property to None because we do not support anything but STRING
623                                 nxe.xselection.property = None;
624                         }
625                         
626                         //Send the event to the client 0 0 == False, SelectionNotify
627                         XSendEvent(m_display, xse->requestor, 0, 0, &nxe);
628                         XFlush(m_display);
629                         break;
630                 }
631                 
632                 default: {
633                         if(xe->type == window->GetXTablet().MotionEvent) 
634                         {
635                                 XDeviceMotionEvent* data = (XDeviceMotionEvent*)xe;
636                                 window->GetXTablet().CommonData.Pressure= 
637                                         data->axis_data[2]/((float)window->GetXTablet().PressureLevels);
638                         
639                         /* the (short) cast and the &0xffff is bizarre and unexplained anywhere,
640                          * but I got garbage data without it. Found it in the xidump.c source --matt */
641                                 window->GetXTablet().CommonData.Xtilt= 
642                                         (short)(data->axis_data[3]&0xffff)/((float)window->GetXTablet().XtiltLevels);
643                                 window->GetXTablet().CommonData.Ytilt= 
644                                         (short)(data->axis_data[4]&0xffff)/((float)window->GetXTablet().YtiltLevels);
645                         }
646                         else if(xe->type == window->GetXTablet().ProxInEvent) 
647                         {
648                                 XProximityNotifyEvent* data = (XProximityNotifyEvent*)xe;
649                                 if(data->deviceid == window->GetXTablet().StylusID)
650                                         window->GetXTablet().CommonData.Active= 1;
651                                 else if(data->deviceid == window->GetXTablet().EraserID)
652                                         window->GetXTablet().CommonData.Active= 2;
653                         }
654                         else if(xe->type == window->GetXTablet().ProxOutEvent)
655                                 window->GetXTablet().CommonData.Active= 0;
656
657                         break;
658                 }
659         }
660
661         if (g_event) {
662                 pushEvent(g_event);
663         }
664 }
665
666         void *
667 GHOST_SystemX11::
668 prepareNdofInfo(volatile GHOST_TEventNDOFData *currentNdofValues)
669 {
670         const vector<GHOST_IWindow*>& v(m_windowManager->getWindows());
671         if (v.size() > 0)
672                 sNdofInfo.window = static_cast<GHOST_WindowX11*>(v[0])->getXWindow();
673         sNdofInfo.display = m_display;
674         sNdofInfo.currValues = currentNdofValues;
675         return (void*)&sNdofInfo;
676 }
677
678         GHOST_TSuccess 
679 GHOST_SystemX11::
680 getModifierKeys(
681         GHOST_ModifierKeys& keys
682 ) const {
683
684         // analyse the masks retuned from XQueryPointer.
685
686         memset(m_keyboard_vector,0,sizeof(m_keyboard_vector));
687
688         XQueryKeymap(m_display,m_keyboard_vector);
689
690         // now translate key symobols into keycodes and
691         // test with vector.
692
693         const KeyCode shift_l = XKeysymToKeycode(m_display,XK_Shift_L);
694         const KeyCode shift_r = XKeysymToKeycode(m_display,XK_Shift_R);
695         const KeyCode control_l = XKeysymToKeycode(m_display,XK_Control_L);
696         const KeyCode control_r = XKeysymToKeycode(m_display,XK_Control_R);
697         const KeyCode alt_l = XKeysymToKeycode(m_display,XK_Alt_L);
698         const KeyCode alt_r = XKeysymToKeycode(m_display,XK_Alt_R);
699
700         // Shift
701         if ((m_keyboard_vector[shift_l >> 3] >> (shift_l & 7)) & 1) {
702                 keys.set(GHOST_kModifierKeyLeftShift,true);
703         } else {
704                 keys.set(GHOST_kModifierKeyLeftShift,false);
705         }
706         if ((m_keyboard_vector[shift_r >> 3] >> (shift_r & 7)) & 1) {
707
708                 keys.set(GHOST_kModifierKeyRightShift,true);
709         } else {
710                 keys.set(GHOST_kModifierKeyRightShift,false);
711         }
712
713         // control (weep)
714         if ((m_keyboard_vector[control_l >> 3] >> (control_l & 7)) & 1) {
715                 keys.set(GHOST_kModifierKeyLeftControl,true);
716         } else {
717                 keys.set(GHOST_kModifierKeyLeftControl,false);
718         }
719         if ((m_keyboard_vector[control_r >> 3] >> (control_r & 7)) & 1) {
720                 keys.set(GHOST_kModifierKeyRightControl,true);
721         } else {
722                 keys.set(GHOST_kModifierKeyRightControl,false);
723         }
724
725         // Alt (yawn)
726         if ((m_keyboard_vector[alt_l >> 3] >> (alt_l & 7)) & 1) {
727                 keys.set(GHOST_kModifierKeyLeftAlt,true);
728         } else {
729                 keys.set(GHOST_kModifierKeyLeftAlt,false);
730         }       
731         if ((m_keyboard_vector[alt_r >> 3] >> (alt_r & 7)) & 1) {
732                 keys.set(GHOST_kModifierKeyRightAlt,true);
733         } else {
734                 keys.set(GHOST_kModifierKeyRightAlt,false);
735         }
736         return GHOST_kSuccess;
737 }
738
739         GHOST_TSuccess 
740 GHOST_SystemX11::
741 getButtons(
742         GHOST_Buttons& buttons
743 ) const {
744
745         Window root_return, child_return;
746         int rx,ry,wx,wy;
747         unsigned int mask_return;
748
749         if (XQueryPointer(
750                 m_display,
751                 RootWindow(m_display,DefaultScreen(m_display)),
752                 &root_return,
753                 &child_return,
754                 &rx,&ry,
755                 &wx,&wy,
756                 &mask_return
757         ) == False) {
758                 return GHOST_kFailure;
759         } else {
760
761                 if (mask_return & Button1Mask) {
762                         buttons.set(GHOST_kButtonMaskLeft,true);
763                 } else {
764                         buttons.set(GHOST_kButtonMaskLeft,false);
765                 }
766
767                 if (mask_return & Button2Mask) {
768                         buttons.set(GHOST_kButtonMaskMiddle,true);
769                 } else {
770                         buttons.set(GHOST_kButtonMaskMiddle,false);
771                 }
772
773                 if (mask_return & Button3Mask) {
774                         buttons.set(GHOST_kButtonMaskRight,true);
775                 } else {
776                         buttons.set(GHOST_kButtonMaskRight,false);
777                 }
778         }       
779
780         return GHOST_kSuccess;
781 }
782
783
784         GHOST_TSuccess 
785 GHOST_SystemX11::
786 getCursorPosition(
787         GHOST_TInt32& x,
788         GHOST_TInt32& y
789 ) const {
790
791         Window root_return, child_return;
792         int rx,ry,wx,wy;
793         unsigned int mask_return;
794
795         if (XQueryPointer(
796                 m_display,
797                 RootWindow(m_display,DefaultScreen(m_display)),
798                 &root_return,
799                 &child_return,
800                 &rx,&ry,
801                 &wx,&wy,
802                 &mask_return
803         ) == False) {
804                 return GHOST_kFailure;
805         } else {
806                 x = rx;
807                 y = ry;
808         }       
809         return GHOST_kSuccess;
810 }
811
812
813         GHOST_TSuccess 
814 GHOST_SystemX11::
815 setCursorPosition(
816         GHOST_TInt32 x,
817         GHOST_TInt32 y
818 ) const {
819
820         // This is a brute force move in screen coordinates
821         // XWarpPointer does relative moves so first determine the
822         // current pointer position.
823
824         int cx,cy;
825         if (getCursorPosition(cx,cy) == GHOST_kFailure) {
826                 return GHOST_kFailure;
827         }
828
829         int relx = x-cx;
830         int rely = y-cy;
831
832         XWarpPointer(m_display,None,None,0,0,0,0,relx,rely);
833         XFlush(m_display);
834         
835         return GHOST_kSuccess;
836 }
837
838
839         void
840 GHOST_SystemX11::
841 addDirtyWindow(
842         GHOST_WindowX11 * bad_wind
843 ){
844
845         GHOST_ASSERT((bad_wind != NULL), "addDirtyWindow() NULL ptr trapped (window)");
846         
847         m_dirty_windows.push_back(bad_wind);
848 }
849
850
851         bool
852 GHOST_SystemX11::
853 generateWindowExposeEvents(
854 ){
855
856         vector<GHOST_WindowX11 *>::iterator w_start = m_dirty_windows.begin();
857         vector<GHOST_WindowX11 *>::const_iterator w_end = m_dirty_windows.end();
858         bool anyProcessed = false;
859         
860         for (;w_start != w_end; ++w_start) {
861                 GHOST_Event * g_event = new 
862                         GHOST_Event(
863                                 getMilliSeconds(),
864                                 GHOST_kEventWindowUpdate,
865                                 *w_start
866                         );                      
867
868                 (*w_start)->validate(); 
869                 
870                 if (g_event) {
871                         pushEvent(g_event);
872                         anyProcessed = true;
873                 }
874         }
875
876         m_dirty_windows.clear();
877         return anyProcessed;
878 }
879
880 #define GXMAP(k,x,y) case x: k = y; break; 
881
882         GHOST_TKey
883 GHOST_SystemX11::
884 convertXKey(
885         KeySym key
886 ){
887         GHOST_TKey type;
888
889         if ((key >= XK_A) && (key <= XK_Z)) {
890                 type = GHOST_TKey( key - XK_A + int(GHOST_kKeyA));
891         } else if ((key >= XK_a) && (key <= XK_z)) {
892                 type = GHOST_TKey(key - XK_a + int(GHOST_kKeyA));
893         } else if ((key >= XK_0) && (key <= XK_9)) {
894                 type = GHOST_TKey(key - XK_0 + int(GHOST_kKey0));
895         } else if ((key >= XK_F1) && (key <= XK_F24)) {
896                 type = GHOST_TKey(key - XK_F1 + int(GHOST_kKeyF1));
897 #if defined(__sun) || defined(__sun__) 
898                 /* This is a bit of a hack, but it looks like sun
899                    Used F11 and friends for its special keys Stop,again etc..
900                    So this little patch enables F11 and F12 to work as expected
901                    following link has documentation on it: 
902                    http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4734408
903                    also from /usr/include/X11/Sunkeysym.h 
904 #define SunXK_F36               0x1005FF10      // Labeled F11
905 #define SunXK_F37               0x1005FF11      // Labeled F12 
906
907                                 mein@cs.umn.edu
908                  */
909                 
910         } else if (key == 268828432) {
911                 type = GHOST_kKeyF11;
912         } else if (key == 268828433) {
913                 type = GHOST_kKeyF12;
914 #endif
915         } else {
916                 switch(key) {
917                         GXMAP(type,XK_BackSpace,        GHOST_kKeyBackSpace);
918                         GXMAP(type,XK_Tab,              GHOST_kKeyTab);
919                         GXMAP(type,XK_Return,           GHOST_kKeyEnter);
920                         GXMAP(type,XK_Escape,           GHOST_kKeyEsc);
921                         GXMAP(type,XK_space,            GHOST_kKeySpace);
922                         
923                         GXMAP(type,XK_Linefeed,         GHOST_kKeyLinefeed);
924                         GXMAP(type,XK_semicolon,        GHOST_kKeySemicolon);
925                         GXMAP(type,XK_period,           GHOST_kKeyPeriod);
926                         GXMAP(type,XK_comma,            GHOST_kKeyComma);
927                         GXMAP(type,XK_quoteright,       GHOST_kKeyQuote);
928                         GXMAP(type,XK_quoteleft,        GHOST_kKeyAccentGrave);
929                         GXMAP(type,XK_minus,            GHOST_kKeyMinus);
930                         GXMAP(type,XK_slash,            GHOST_kKeySlash);
931                         GXMAP(type,XK_backslash,        GHOST_kKeyBackslash);
932                         GXMAP(type,XK_equal,            GHOST_kKeyEqual);
933                         GXMAP(type,XK_bracketleft,      GHOST_kKeyLeftBracket);
934                         GXMAP(type,XK_bracketright,     GHOST_kKeyRightBracket);
935                         GXMAP(type,XK_Pause,            GHOST_kKeyPause);
936                         
937                         GXMAP(type,XK_Shift_L,          GHOST_kKeyLeftShift);
938                         GXMAP(type,XK_Shift_R,          GHOST_kKeyRightShift);
939                         GXMAP(type,XK_Control_L,        GHOST_kKeyLeftControl);
940                         GXMAP(type,XK_Control_R,        GHOST_kKeyRightControl);
941                         GXMAP(type,XK_Alt_L,            GHOST_kKeyLeftAlt);
942                         GXMAP(type,XK_Alt_R,            GHOST_kKeyRightAlt);
943
944                         GXMAP(type,XK_Insert,           GHOST_kKeyInsert);
945                         GXMAP(type,XK_Delete,           GHOST_kKeyDelete);
946                         GXMAP(type,XK_Home,                     GHOST_kKeyHome);
947                         GXMAP(type,XK_End,                      GHOST_kKeyEnd);
948                         GXMAP(type,XK_Page_Up,          GHOST_kKeyUpPage);
949                         GXMAP(type,XK_Page_Down,        GHOST_kKeyDownPage);
950
951                         GXMAP(type,XK_Left,                     GHOST_kKeyLeftArrow);
952                         GXMAP(type,XK_Right,            GHOST_kKeyRightArrow);
953                         GXMAP(type,XK_Up,                       GHOST_kKeyUpArrow);
954                         GXMAP(type,XK_Down,                     GHOST_kKeyDownArrow);
955
956                         GXMAP(type,XK_Caps_Lock,        GHOST_kKeyCapsLock);
957                         GXMAP(type,XK_Scroll_Lock,      GHOST_kKeyScrollLock);
958                         GXMAP(type,XK_Num_Lock,         GHOST_kKeyNumLock);
959                         
960                                 /* keypad events */
961                                 
962                         GXMAP(type,XK_KP_0,                     GHOST_kKeyNumpad0);
963                         GXMAP(type,XK_KP_1,                     GHOST_kKeyNumpad1);
964                         GXMAP(type,XK_KP_2,                     GHOST_kKeyNumpad2);
965                         GXMAP(type,XK_KP_3,                     GHOST_kKeyNumpad3);
966                         GXMAP(type,XK_KP_4,                     GHOST_kKeyNumpad4);
967                         GXMAP(type,XK_KP_5,                     GHOST_kKeyNumpad5);
968                         GXMAP(type,XK_KP_6,                     GHOST_kKeyNumpad6);
969                         GXMAP(type,XK_KP_7,                     GHOST_kKeyNumpad7);
970                         GXMAP(type,XK_KP_8,                     GHOST_kKeyNumpad8);
971                         GXMAP(type,XK_KP_9,                     GHOST_kKeyNumpad9);
972                         GXMAP(type,XK_KP_Decimal,       GHOST_kKeyNumpadPeriod);
973
974                         GXMAP(type,XK_KP_Insert,        GHOST_kKeyNumpad0);
975                         GXMAP(type,XK_KP_End,           GHOST_kKeyNumpad1);
976                         GXMAP(type,XK_KP_Down,          GHOST_kKeyNumpad2);
977                         GXMAP(type,XK_KP_Page_Down,     GHOST_kKeyNumpad3);
978                         GXMAP(type,XK_KP_Left,          GHOST_kKeyNumpad4);
979                         GXMAP(type,XK_KP_Begin,         GHOST_kKeyNumpad5);
980                         GXMAP(type,XK_KP_Right,         GHOST_kKeyNumpad6);
981                         GXMAP(type,XK_KP_Home,          GHOST_kKeyNumpad7);
982                         GXMAP(type,XK_KP_Up,            GHOST_kKeyNumpad8);
983                         GXMAP(type,XK_KP_Page_Up,       GHOST_kKeyNumpad9);
984                         GXMAP(type,XK_KP_Delete,        GHOST_kKeyNumpadPeriod);
985
986                         GXMAP(type,XK_KP_Enter,         GHOST_kKeyNumpadEnter);
987                         GXMAP(type,XK_KP_Add,           GHOST_kKeyNumpadPlus);
988                         GXMAP(type,XK_KP_Subtract,      GHOST_kKeyNumpadMinus);
989                         GXMAP(type,XK_KP_Multiply,      GHOST_kKeyNumpadAsterisk);
990                         GXMAP(type,XK_KP_Divide,        GHOST_kKeyNumpadSlash);
991
992                                 /* some extra sun cruft (NICE KEYBOARD!) */
993 #ifdef __sun__
994                         GXMAP(type,0xffde,                      GHOST_kKeyNumpad1);
995                         GXMAP(type,0xffe0,                      GHOST_kKeyNumpad3);
996                         GXMAP(type,0xffdc,                      GHOST_kKeyNumpad5);
997                         GXMAP(type,0xffd8,                      GHOST_kKeyNumpad7);
998                         GXMAP(type,0xffda,                      GHOST_kKeyNumpad9);
999
1000                         GXMAP(type,0xffd6,                      GHOST_kKeyNumpadSlash);
1001                         GXMAP(type,0xffd7,                      GHOST_kKeyNumpadAsterisk);
1002 #endif
1003
1004                         default :
1005                                 type = GHOST_kKeyUnknown;
1006                                 break;
1007                 }
1008         }
1009
1010         return type;
1011 }
1012
1013 #undef GXMAP
1014
1015 /* from xclip.c xcout() v0.11 */
1016
1017 #define XCLIB_XCOUT_NONE                0 /* no context */
1018 #define XCLIB_XCOUT_SENTCONVSEL         1 /* sent a request */
1019 #define XCLIB_XCOUT_INCR                2 /* in an incr loop */
1020 #define XCLIB_XCOUT_FALLBACK            3 /* STRING failed, need fallback to UTF8 */
1021 #define XCLIB_XCOUT_FALLBACK_UTF8       4 /* UTF8 failed, move to compouned */
1022 #define XCLIB_XCOUT_FALLBACK_COMP       5 /* compouned failed, move to text. */
1023 #define XCLIB_XCOUT_FALLBACK_TEXT       6
1024
1025 // Retrieves the contents of a selections.
1026 void GHOST_SystemX11::getClipboard_xcout(XEvent evt,
1027         Atom sel, Atom target, unsigned char **txt,
1028         unsigned long *len, unsigned int *context) const
1029 {
1030         Atom pty_type;
1031         int pty_format;
1032         unsigned char *buffer;
1033         unsigned long pty_size, pty_items;
1034         unsigned char *ltxt= *txt;
1035
1036         vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
1037         vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
1038         GHOST_WindowX11 * window = static_cast<GHOST_WindowX11 *>(*win_it);
1039         Window win = window->getXWindow();
1040
1041         switch (*context) {
1042                 // There is no context, do an XConvertSelection()
1043                 case XCLIB_XCOUT_NONE:
1044                         // Initialise return length to 0
1045                         if (*len > 0) {
1046                                 free(*txt);
1047                                 *len = 0;
1048                         }
1049
1050                         // Send a selection request
1051                         XConvertSelection(m_display, sel, target, m_xclip_out, win, CurrentTime);
1052                         *context = XCLIB_XCOUT_SENTCONVSEL;
1053                         return;
1054
1055                 case XCLIB_XCOUT_SENTCONVSEL:
1056                         if (evt.type != SelectionNotify)
1057                                 return;
1058
1059                         if (target == m_utf8_string && evt.xselection.property == None) {
1060                                 *context= XCLIB_XCOUT_FALLBACK_UTF8;
1061                                 return;
1062                         }
1063                         else if (target == m_compound_text && evt.xselection.property == None) {
1064                                 *context= XCLIB_XCOUT_FALLBACK_COMP;
1065                                 return;
1066                         }
1067                         else if (target == m_text && evt.xselection.property == None) {
1068                                 *context= XCLIB_XCOUT_FALLBACK_TEXT;
1069                                 return;
1070                         }
1071
1072                         // find the size and format of the data in property
1073                         XGetWindowProperty(m_display, win, m_xclip_out, 0, 0, False,
1074                                 AnyPropertyType, &pty_type, &pty_format,
1075                                 &pty_items, &pty_size, &buffer);
1076                         XFree(buffer);
1077
1078                         if (pty_type == m_incr) {
1079                                 // start INCR mechanism by deleting property
1080                                 XDeleteProperty(m_display, win, m_xclip_out);
1081                                 XFlush(m_display);
1082                                 *context = XCLIB_XCOUT_INCR;
1083                                 return;
1084                         }
1085
1086                         // if it's not incr, and not format == 8, then there's
1087                         // nothing in the selection (that xclip understands, anyway)
1088
1089                         if (pty_format != 8) {
1090                                 *context = XCLIB_XCOUT_NONE;
1091                                 return;
1092                         }
1093
1094                         // not using INCR mechanism, just read the property
1095                         XGetWindowProperty(m_display, win, m_xclip_out, 0, (long) pty_size,
1096                                         False, AnyPropertyType, &pty_type,
1097                                         &pty_format, &pty_items, &pty_size, &buffer);
1098
1099                         // finished with property, delete it
1100                         XDeleteProperty(m_display, win, m_xclip_out);
1101
1102                         // copy the buffer to the pointer for returned data
1103                         ltxt = (unsigned char *) malloc(pty_items);
1104                         memcpy(ltxt, buffer, pty_items);
1105
1106                         // set the length of the returned data
1107                         *len = pty_items;
1108                         *txt = ltxt;
1109
1110                         // free the buffer
1111                         XFree(buffer);
1112
1113                         *context = XCLIB_XCOUT_NONE;
1114
1115                         // complete contents of selection fetched, return 1
1116                         return;
1117
1118                 case XCLIB_XCOUT_INCR:
1119                         // To use the INCR method, we basically delete the
1120                         // property with the selection in it, wait for an
1121                         // event indicating that the property has been created,
1122                         // then read it, delete it, etc.
1123
1124                         // make sure that the event is relevant
1125                         if (evt.type != PropertyNotify)
1126                                 return;
1127
1128                         // skip unless the property has a new value
1129                         if (evt.xproperty.state != PropertyNewValue)
1130                                 return;
1131
1132                         // check size and format of the property
1133                         XGetWindowProperty(m_display, win, m_xclip_out, 0, 0, False,
1134                                 AnyPropertyType, &pty_type, &pty_format,
1135                                 &pty_items, &pty_size, (unsigned char **) &buffer);
1136
1137                         if (pty_format != 8) {
1138                                 // property does not contain text, delete it
1139                                 // to tell the other X client that we have read 
1140                                 // it and to send the next property
1141                                 XFree(buffer);
1142                                 XDeleteProperty(m_display, win, m_xclip_out);
1143                                 return;
1144                         }
1145
1146                         if (pty_size == 0) {
1147                                 // no more data, exit from loop
1148                                 XFree(buffer);
1149                                 XDeleteProperty(m_display, win, m_xclip_out);
1150                                 *context = XCLIB_XCOUT_NONE;
1151
1152                                 // this means that an INCR transfer is now
1153                                 // complete, return 1
1154                                 return;
1155                         }
1156
1157                         XFree(buffer);
1158
1159                         // if we have come this far, the propery contains
1160                         // text, we know the size.
1161                         XGetWindowProperty(m_display, win, m_xclip_out, 0, (long) pty_size,
1162                                 False, AnyPropertyType, &pty_type, &pty_format,
1163                                 &pty_items, &pty_size, (unsigned char **) &buffer);
1164
1165                         // allocate memory to accommodate data in *txt
1166                         if (*len == 0) {
1167                                 *len = pty_items;
1168                                 ltxt = (unsigned char *) malloc(*len);
1169                         }
1170                         else {
1171                                 *len += pty_items;
1172                                 ltxt = (unsigned char *) realloc(ltxt, *len);
1173                         }
1174
1175                         // add data to ltxt
1176                         memcpy(&ltxt[*len - pty_items], buffer, pty_items);
1177
1178                         *txt = ltxt;
1179                         XFree(buffer);
1180
1181                         // delete property to get the next item
1182                         XDeleteProperty(m_display, win, m_xclip_out);
1183                         XFlush(m_display);
1184                         return;
1185         }
1186         return;
1187 }
1188
1189 GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const
1190 {
1191         Atom sseln;
1192         Atom target= m_string;
1193         Window owner;
1194
1195         // from xclip.c doOut() v0.11
1196         unsigned char *sel_buf;
1197         unsigned long sel_len= 0;
1198         XEvent evt;
1199         unsigned int context= XCLIB_XCOUT_NONE;
1200
1201         if (selection == True)
1202                 sseln= m_primary;
1203         else
1204                 sseln= m_clipboard;
1205
1206         vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
1207         vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
1208         GHOST_WindowX11 * window = static_cast<GHOST_WindowX11 *>(*win_it);
1209         Window win = window->getXWindow();
1210
1211         /* check if we are the owner. */
1212         owner= XGetSelectionOwner(m_display, sseln);
1213         if (owner == win) {
1214                 if (sseln == m_clipboard) {
1215                         sel_buf= (unsigned char *)malloc(strlen(txt_cut_buffer)+1);
1216                         strcpy((char *)sel_buf, txt_cut_buffer);
1217                         return((GHOST_TUns8*)sel_buf);
1218                 }
1219                 else {
1220                         sel_buf= (unsigned char *)malloc(strlen(txt_select_buffer)+1);
1221                         strcpy((char *)sel_buf, txt_select_buffer);
1222                         return((GHOST_TUns8*)sel_buf);
1223                 }
1224         }
1225         else if (owner == None)
1226                 return(NULL);
1227
1228         while (1) {
1229                 /* only get an event if xcout() is doing something */
1230                 if (context != XCLIB_XCOUT_NONE)
1231                         XNextEvent(m_display, &evt);
1232
1233                 /* fetch the selection, or part of it */
1234                 getClipboard_xcout(evt, sseln, target, &sel_buf, &sel_len, &context);
1235
1236                 /* fallback is needed. set XA_STRING to target and restart the loop. */
1237                 if (context == XCLIB_XCOUT_FALLBACK) {
1238                         context= XCLIB_XCOUT_NONE;
1239                         target= m_string;
1240                         continue;
1241                 }
1242                 else if (context == XCLIB_XCOUT_FALLBACK_UTF8) {
1243                         /* utf8 fail, move to compouned text. */
1244                         context= XCLIB_XCOUT_NONE;
1245                         target= m_compound_text;
1246                         continue;
1247                 }
1248                 else if (context == XCLIB_XCOUT_FALLBACK_COMP) {
1249                         /* compouned text faile, move to text. */
1250                         context= XCLIB_XCOUT_NONE;
1251                         target= m_text;
1252                         continue;
1253                 }
1254
1255                 /* only continue if xcout() is doing something */
1256                 if (context == XCLIB_XCOUT_NONE)
1257                         break;
1258         }
1259
1260         if (sel_len) {
1261                 /* only print the buffer out, and free it, if it's not
1262                  * empty
1263                  */
1264                 unsigned char *tmp_data = (unsigned char*) malloc(sel_len+1);
1265                 memcpy((char*)tmp_data, (char*)sel_buf, sel_len);
1266                 tmp_data[sel_len] = '\0';
1267                 
1268                 if (sseln == m_string)
1269                         XFree(sel_buf);
1270                 else
1271                         free(sel_buf);
1272                 
1273                 return (GHOST_TUns8*)tmp_data;
1274         }
1275         return(NULL);
1276 }
1277
1278 void GHOST_SystemX11::putClipboard(GHOST_TInt8 *buffer, bool selection) const
1279 {
1280         Window m_window, owner;
1281
1282         vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();      
1283         vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
1284         GHOST_WindowX11 * window = static_cast<GHOST_WindowX11 *>(*win_it);
1285         m_window = window->getXWindow();
1286
1287         if (buffer) {
1288                 if (selection == False) {
1289                         XSetSelectionOwner(m_display, m_clipboard, m_window, CurrentTime);
1290                         owner= XGetSelectionOwner(m_display, m_clipboard);
1291                         if (txt_cut_buffer)
1292                                 free((void*)txt_cut_buffer);
1293
1294                         txt_cut_buffer = (char*) malloc(strlen(buffer)+1);
1295                         strcpy(txt_cut_buffer, buffer);
1296                 } else {
1297                         XSetSelectionOwner(m_display, m_primary, m_window, CurrentTime);
1298                         owner= XGetSelectionOwner(m_display, m_primary);
1299                         if (txt_select_buffer)
1300                                 free((void*)txt_select_buffer);
1301
1302                         txt_select_buffer = (char*) malloc(strlen(buffer)+1);
1303                         strcpy(txt_select_buffer, buffer);
1304                 }
1305         
1306                 if (owner != m_window)
1307                         fprintf(stderr, "failed to own primary\n");
1308         }
1309 }