~siretart/ubuntu/utopic/blender/libav10

« back to all changes in this revision

Viewing changes to .pc/0001-install_in_usr_lib.patch/intern/ghost/intern/GHOST_SystemX11.cpp

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2012-07-23 08:54:18 UTC
  • mfrom: (14.2.16 sid)
  • mto: (14.2.19 sid)
  • mto: This revision was merged to the branch mainline in revision 42.
  • Revision ID: package-import@ubuntu.com-20120723085418-9foz30v6afaf5ffs
Tags: 2.63a-2
* debian/: Cycles support added (Closes: #658075)
  For now, this top feature has been enabled only
  on [any-amd64 any-i386] architectures because
  of OpenImageIO failing on all others
* debian/: scripts installation path changed
  from /usr/lib to /usr/share:
  + debian/patches/: patchset re-worked for path changing
  + debian/control: "Breaks" field added on yafaray-exporter

Show diffs side-by-side

added added

removed removed

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