View | Details | Raw Unified | Return to bug 254451 | Differences between
and this patch

Collapse All | Expand All

(-)b/include/GL/freeglut_ext.h (+10 lines)
Lines 145-150 FGAPI void FGAPIENTRY glutSetMenuFont( int menuID, void* font ); Link Here
145
/*
145
/*
146
 * Window-specific callback functions, see fg_callbacks.c
146
 * Window-specific callback functions, see fg_callbacks.c
147
 */
147
 */
148
FGAPI void    FGAPIENTRY glutKeyboardExtFunc( void (* callback)( int, int, int ) );
148
FGAPI void    FGAPIENTRY glutMouseWheelFunc( void (* callback)( int, int, int, int ) );
149
FGAPI void    FGAPIENTRY glutMouseWheelFunc( void (* callback)( int, int, int, int ) );
149
FGAPI void    FGAPIENTRY glutPositionFunc( void (* callback)( int, int ) );
150
FGAPI void    FGAPIENTRY glutPositionFunc( void (* callback)( int, int ) );
150
FGAPI void    FGAPIENTRY glutCloseFunc( void (* callback)( void ) );
151
FGAPI void    FGAPIENTRY glutCloseFunc( void (* callback)( void ) );
Lines 163-168 FGAPI void FGAPIENTRY glutSetWindowData(void* data); Link Here
163
FGAPI void*   FGAPIENTRY glutGetMenuData( void );
164
FGAPI void*   FGAPIENTRY glutGetMenuData( void );
164
FGAPI void    FGAPIENTRY glutSetMenuData(void* data);
165
FGAPI void    FGAPIENTRY glutSetMenuData(void* data);
165
166
167
/*
168
 * Clipboard access
169
 */
170
#define GLUT_CLIPBOARD 0
171
#define GLUT_PRIMARY 1
172
#define GLUT_SECONDARY 2
173
FGAPI void         FGAPIENTRY glutSetClipboard(int selection, const char *string);
174
FGAPI const char * FGAPIENTRY glutGetClipboard(int selection);
175
166
/*
176
/*
167
 * Font stuff, see fg_font.c
177
 * Font stuff, see fg_font.c
168
 */
178
 */
(-)b/include/GL/freeglut_std.h (-1 / +2 lines)
Lines 120-126 Link Here
120
 * The freeglut and GLUT API versions
120
 * The freeglut and GLUT API versions
121
 */
121
 */
122
#define  FREEGLUT             1
122
#define  FREEGLUT             1
123
#define  GLUT_API_VERSION     4
123
#define  GLUT_API_VERSION     6
124
#define  GLUT_XLIB_IMPLEMENTATION 13
124
#define  GLUT_XLIB_IMPLEMENTATION 13
125
/* Deprecated:
125
/* Deprecated:
126
   cf. http://sourceforge.net/mailarchive/forum.php?thread_name=CABcAi1hw7cr4xtigckaGXB5X8wddLfMcbA_rZ3NAuwMrX_zmsw%40mail.gmail.com&forum_name=freeglut-developer */
126
   cf. http://sourceforge.net/mailarchive/forum.php?thread_name=CABcAi1hw7cr4xtigckaGXB5X8wddLfMcbA_rZ3NAuwMrX_zmsw%40mail.gmail.com&forum_name=freeglut-developer */
Lines 498-503 FGAPI void FGAPIENTRY glutMotionFunc( void (* callback)( int, int ) ); Link Here
498
FGAPI void    FGAPIENTRY glutPassiveMotionFunc( void (* callback)( int, int ) );
498
FGAPI void    FGAPIENTRY glutPassiveMotionFunc( void (* callback)( int, int ) );
499
FGAPI void    FGAPIENTRY glutEntryFunc( void (* callback)( int ) );
499
FGAPI void    FGAPIENTRY glutEntryFunc( void (* callback)( int ) );
500
500
501
FGAPI void    FGAPIENTRY glutKeyboardDownFunc( void (* callback)( unsigned char, int, int ) );
501
FGAPI void    FGAPIENTRY glutKeyboardUpFunc( void (* callback)( unsigned char, int, int ) );
502
FGAPI void    FGAPIENTRY glutKeyboardUpFunc( void (* callback)( unsigned char, int, int ) );
502
FGAPI void    FGAPIENTRY glutSpecialUpFunc( void (* callback)( int, int, int ) );
503
FGAPI void    FGAPIENTRY glutSpecialUpFunc( void (* callback)( int, int, int ) );
503
FGAPI void    FGAPIENTRY glutJoystickFunc( void (* callback)( unsigned int, int, int, int ), int pollInterval );
504
FGAPI void    FGAPIENTRY glutJoystickFunc( void (* callback)( unsigned int, int, int, int ), int pollInterval );
(-)b/src/fg_callbacks.c (+2 lines)
Lines 124-129 void FGAPIENTRY glut##a##Func( FGCB##b callback ) \ Link Here
124
/* Implement all these callback setter functions... */
124
/* Implement all these callback setter functions... */
125
IMPLEMENT_CALLBACK_FUNC(Position)
125
IMPLEMENT_CALLBACK_FUNC(Position)
126
IMPLEMENT_CALLBACK_FUNC(Keyboard)
126
IMPLEMENT_CALLBACK_FUNC(Keyboard)
127
IMPLEMENT_CALLBACK_FUNC(KeyboardExt)
128
IMPLEMENT_CALLBACK_FUNC(KeyboardDown)
127
IMPLEMENT_CALLBACK_FUNC(KeyboardUp)
129
IMPLEMENT_CALLBACK_FUNC(KeyboardUp)
128
IMPLEMENT_CALLBACK_FUNC(Special)
130
IMPLEMENT_CALLBACK_FUNC(Special)
129
IMPLEMENT_CALLBACK_FUNC(SpecialUp)
131
IMPLEMENT_CALLBACK_FUNC(SpecialUp)
(-)b/src/fg_ext.c (+4 lines)
Lines 111-116 static GLUTproc fghGetGLUTProcAddress( const char* procName ) Link Here
111
    CHECK_NAME(glutMenuStatusFunc);
111
    CHECK_NAME(glutMenuStatusFunc);
112
    CHECK_NAME(glutOverlayDisplayFunc);
112
    CHECK_NAME(glutOverlayDisplayFunc);
113
    CHECK_NAME(glutWindowStatusFunc);
113
    CHECK_NAME(glutWindowStatusFunc);
114
    CHECK_NAME(glutKeyboardDownFunc);
114
    CHECK_NAME(glutKeyboardUpFunc);
115
    CHECK_NAME(glutKeyboardUpFunc);
115
    CHECK_NAME(glutSpecialUpFunc);
116
    CHECK_NAME(glutSpecialUpFunc);
116
    CHECK_NAME(glutSetColor);
117
    CHECK_NAME(glutSetColor);
Lines 186-192 static GLUTproc fghGetGLUTProcAddress( const char* procName ) Link Here
186
    CHECK_NAME(glutBitmapString);
187
    CHECK_NAME(glutBitmapString);
187
    CHECK_NAME(glutStrokeString);
188
    CHECK_NAME(glutStrokeString);
188
    CHECK_NAME(glutGetProcAddress);
189
    CHECK_NAME(glutGetProcAddress);
190
    CHECK_NAME(glutKeyboardExtFunc);
189
    CHECK_NAME(glutMouseWheelFunc);
191
    CHECK_NAME(glutMouseWheelFunc);
192
    CHECK_NAME(glutGetClipboard);
193
    CHECK_NAME(glutSetClipboard);
190
    CHECK_NAME(glutJoystickGetNumAxes);
194
    CHECK_NAME(glutJoystickGetNumAxes);
191
    CHECK_NAME(glutJoystickGetNumButtons);
195
    CHECK_NAME(glutJoystickGetNumButtons);
192
    CHECK_NAME(glutJoystickNotWorking);
196
    CHECK_NAME(glutJoystickNotWorking);
(-)b/src/fg_internal.h (+7 lines)
Lines 210-215 typedef void (* FGCBReshape )( int, int ); Link Here
210
typedef void (* FGCBPosition      )( int, int );
210
typedef void (* FGCBPosition      )( int, int );
211
typedef void (* FGCBVisibility    )( int );
211
typedef void (* FGCBVisibility    )( int );
212
typedef void (* FGCBKeyboard      )( unsigned char, int, int );
212
typedef void (* FGCBKeyboard      )( unsigned char, int, int );
213
typedef void (* FGCBKeyboardExt   )( int, int, int );
214
typedef void (* FGCBKeyboardDown  )( unsigned char, int, int );
213
typedef void (* FGCBKeyboardUp    )( unsigned char, int, int );
215
typedef void (* FGCBKeyboardUp    )( unsigned char, int, int );
214
typedef void (* FGCBSpecial       )( int, int, int );
216
typedef void (* FGCBSpecial       )( int, int, int );
215
typedef void (* FGCBSpecialUp     )( int, int, int );
217
typedef void (* FGCBSpecialUp     )( int, int, int );
Lines 595-600 enum Link Here
595
    WCB_Reshape,
597
    WCB_Reshape,
596
    WCB_Position,
598
    WCB_Position,
597
    WCB_Keyboard,
599
    WCB_Keyboard,
600
    WCB_KeyboardExt,
601
    WCB_KeyboardDown,
598
    WCB_KeyboardUp,
602
    WCB_KeyboardUp,
599
    WCB_Special,
603
    WCB_Special,
600
    WCB_SpecialUp,
604
    WCB_SpecialUp,
Lines 1061-1066 void fgWarning( const char *fmt, ... ); Link Here
1061
1065
1062
SFG_Proc fgPlatformGetProcAddress( const char *procName );
1066
SFG_Proc fgPlatformGetProcAddress( const char *procName );
1063
1067
1068
void fgPlatformSetClipboard(int selection, const char *text);
1069
const char *fgPlatformGetClipboard(int selection);
1070
1064
/* pushing attribute/value pairs into an array */
1071
/* pushing attribute/value pairs into an array */
1065
#define ATTRIB(a) attributes[where++]=(a)
1072
#define ATTRIB(a) attributes[where++]=(a)
1066
#define ATTRIB_VAL(a,v) {ATTRIB(a); ATTRIB(v);}
1073
#define ATTRIB_VAL(a,v) {ATTRIB(a); ATTRIB(v);}
(-)b/src/fg_window.c (+23 lines)
Lines 357-362 void FGAPIENTRY glutSetIconTitle( const char* title ) Link Here
357
    }
357
    }
358
}
358
}
359
359
360
/*
361
 * This function sets the clipboard content to the UTF-8 encoded text.
362
 */
363
void FGAPIENTRY glutSetClipboard(int selection, const char *text)
364
{
365
    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetClipboard" );
366
    FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetClipboard" );
367
368
    fgPlatformSetClipboard(selection, text);
369
}
370
371
/*
372
 * This function returns the clipboard content as UTF-8 encoded text,
373
 * or NULL if no content was available.
374
 */
375
const char* FGAPIENTRY glutGetClipboard(int selection)
376
{
377
    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetClipboard" );
378
    FREEGLUT_EXIT_IF_NO_WINDOW ( "glutGetClipboard" );
379
380
    return fgPlatformGetClipboard(selection);
381
}
382
360
/*
383
/*
361
 * Change the current window's size
384
 * Change the current window's size
362
 */
385
 */
(-)b/src/freeglutdll.def.in (+2 lines)
Lines 65-70 EXPORTS Link Here
65
	glutEntryFunc
65
	glutEntryFunc
66
	glutCloseFunc
66
	glutCloseFunc
67
	glutWMCloseFunc
67
	glutWMCloseFunc
68
	glutKeyboardExtFunc
69
	glutKeyboardDownFunc
68
	glutKeyboardUpFunc
70
	glutKeyboardUpFunc
69
	glutSpecialUpFunc
71
	glutSpecialUpFunc
70
	glutJoystickFunc
72
	glutJoystickFunc
(-)b/src/mswin/fg_init_mswin.c (+10 lines)
Lines 36-41 extern LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, Link Here
36
extern void fgPlatformInitSystemTime();
36
extern void fgPlatformInitSystemTime();
37
extern void fghCloseInputDevices(void);
37
extern void fghCloseInputDevices(void);
38
38
39
char *fgClipboardBuffer[3] = { NULL, NULL, NULL };
40
39
41
40
/*
42
/*
41
 * A call to this function should initialize all the display stuff...
43
 * A call to this function should initialize all the display stuff...
Lines 150-161 void fgPlatformDeinitialiseInputDevices ( void ) Link Here
150
152
151
void fgPlatformCloseDisplay ( void )
153
void fgPlatformCloseDisplay ( void )
152
{
154
{
155
    int i;
156
153
    if( fgDisplay.pDisplay.DisplayName )
157
    if( fgDisplay.pDisplay.DisplayName )
154
    {
158
    {
155
        free( fgDisplay.pDisplay.DisplayName );
159
        free( fgDisplay.pDisplay.DisplayName );
156
        fgDisplay.pDisplay.DisplayName = NULL;
160
        fgDisplay.pDisplay.DisplayName = NULL;
157
    }
161
    }
158
162
163
    for (i = 0; i < 3; ++i)
164
    {
165
        free(fgClipboardBuffer[i]);
166
        fgClipboardBuffer[i] = NULL;
167
    }
168
159
    /* Reset the timer granularity */
169
    /* Reset the timer granularity */
160
    timeEndPeriod ( 1 );
170
    timeEndPeriod ( 1 );
161
}
171
}
(-)b/src/mswin/fg_main_mswin.c (-17 / +105 lines)
Lines 28-33 Link Here
28
#include <GL/freeglut.h>
28
#include <GL/freeglut.h>
29
#include "../fg_internal.h"
29
#include "../fg_internal.h"
30
30
31
#ifndef MAPVK_VK_TO_CHAR
32
#define MAPVK_VK_TO_CHAR 2
33
#endif
34
31
extern void fghRedrawWindow ( SFG_Window *window );
35
extern void fghRedrawWindow ( SFG_Window *window );
32
extern void fghRedrawWindowAndChildren ( SFG_Window *window );
36
extern void fghRedrawWindowAndChildren ( SFG_Window *window );
33
extern void fghOnReshapeNotify(SFG_Window *window, int width, int height, GLboolean forceNotify);
37
extern void fghOnReshapeNotify(SFG_Window *window, int width, int height, GLboolean forceNotify);
Lines 480-485 fg_time_t fgPlatformSystemTime ( void ) Link Here
480
    return currTime32 | timeEpoch << 32;
484
    return currTime32 | timeEpoch << 32;
481
}
485
}
482
486
487
extern char *fgClipboardBuffer[3];
488
489
void fgPlatformSetClipboard(int selection, const char *text)
490
{
491
	if (selection == GLUT_PRIMARY)
492
	{
493
		free(fgClipboardBuffer[GLUT_PRIMARY]);
494
		fgClipboardBuffer[GLUT_PRIMARY] = strdup(text);
495
	}
496
	else if (selection == GLUT_SECONDARY)
497
	{
498
		free(fgClipboardBuffer[GLUT_SECONDARY]);
499
		fgClipboardBuffer[GLUT_SECONDARY] = strdup(text);
500
	}
501
	else if (selection == GLUT_CLIPBOARD && text)
502
	{
503
		int n = MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0);
504
		if (n > 0)
505
		{
506
			HANDLE object = GlobalAlloc(0, n * sizeof(WCHAR));
507
			if (object)
508
			{
509
				WCHAR *wtext = GlobalLock(object);
510
				if (wtext)
511
				{
512
					MultiByteToWideChar(CP_UTF8, 0, text, -1, wtext, n);
513
					GlobalUnlock(object);
514
					if (OpenClipboard(NULL))
515
					{
516
						EmptyClipboard();
517
						SetClipboardData(CF_UNICODETEXT, object);
518
						CloseClipboard();
519
					}
520
				}
521
				GlobalFree(object);
522
			}
523
		}
524
	}
525
}
526
527
const char *fgPlatformGetClipboard(int selection)
528
{
529
	if (selection == GLUT_PRIMARY)
530
		return fgClipboardBuffer[GLUT_PRIMARY];
531
	if (selection == GLUT_SECONDARY)
532
		return fgClipboardBuffer[GLUT_SECONDARY];
533
	if (selection == GLUT_CLIPBOARD)
534
	{
535
		free(fgClipboardBuffer[GLUT_CLIPBOARD]);
536
		fgClipboardBuffer[GLUT_CLIPBOARD] = NULL;
537
		if (OpenClipboard(NULL))
538
		{
539
			HANDLE object = GetClipboardData(CF_UNICODETEXT);
540
			if (object)
541
			{
542
				WCHAR *wtext = GlobalLock(object);
543
				if (wtext)
544
				{
545
					int n = WideCharToMultiByte(CP_UTF8, 0, wtext, -1, NULL, 0, NULL, NULL);
546
					if (n > 0)
547
					{
548
						char *text = malloc(n);
549
						fgClipboardBuffer[GLUT_CLIPBOARD] = text;
550
						WideCharToMultiByte(CP_UTF8, 0, wtext, -1, text, n, NULL, NULL);
551
					}
552
					GlobalUnlock(object);
553
				}
554
				GlobalFree(object);
555
			}
556
			CloseClipboard();
557
		}
558
		return fgClipboardBuffer[GLUT_CLIPBOARD];
559
	}
560
	return NULL;
561
}
483
562
484
void fgPlatformSleepForEvents( fg_time_t msec )
563
void fgPlatformSleepForEvents( fg_time_t msec )
485
{
564
{
Lines 664-672 static LRESULT fghWindowProcKeyPress(SFG_Window *window, UINT uMsg, GLboolean ke Link Here
664
    case VK_DELETE:
743
    case VK_DELETE:
665
        /* The delete key should be treated as an ASCII keypress: */
744
        /* The delete key should be treated as an ASCII keypress: */
666
        if (keydown)
745
        if (keydown)
746
        {
747
            INVOKE_WCB( *window, KeyboardDown,
748
                        ( 127, window->State.MouseX, window->State.MouseY )
749
            );
750
            INVOKE_WCB( *window, KeyboardExt,
751
                        ( 127, window->State.MouseX, window->State.MouseY )
752
            );
667
            INVOKE_WCB( *window, Keyboard,
753
            INVOKE_WCB( *window, Keyboard,
668
                        ( 127, window->State.MouseX, window->State.MouseY )
754
                        ( 127, window->State.MouseX, window->State.MouseY )
669
            );
755
            );
756
        }
670
        else
757
        else
671
            INVOKE_WCB( *window, KeyboardUp,
758
            INVOKE_WCB( *window, KeyboardUp,
672
                        ( 127, window->State.MouseX, window->State.MouseY )
759
                        ( 127, window->State.MouseX, window->State.MouseY )
Lines 675-695 static LRESULT fghWindowProcKeyPress(SFG_Window *window, UINT uMsg, GLboolean ke Link Here
675
762
676
#if !defined(_WIN32_WCE)
763
#if !defined(_WIN32_WCE)
677
    default:
764
    default:
678
        /* keydown displayable characters are handled with WM_CHAR message, but no corresponding up is generated. So get that here. */
765
        /* Mapped characters are handled with the WM_CHAR message. Handle low-level ASCII press/release callbacks here. */
679
        if (!keydown)
680
        {
766
        {
681
            BYTE state[ 256 ];
767
            UINT ascii = (UINT)MapVirtualKey((UINT)wParam, MAPVK_VK_TO_CHAR);
682
            WORD code[ 2 ];
768
            if (ascii >= 32 && ascii < 256)
683
769
            {
684
            GetKeyboardState( state );
770
				/* Always send lowercase (unshifted) values */
685
771
				if (ascii >= 'A' && ascii <= 'Z')
686
            if( ToAscii( (UINT)wParam, 0, state, code, 0 ) == 1 )
772
						ascii = ascii - 'A' + 'a';
687
                wParam=code[ 0 ];
773
                if (keydown)
688
774
                    INVOKE_WCB(*window, KeyboardDown, ((unsigned char)ascii, window->State.MouseX, window->State.MouseY) );
689
            INVOKE_WCB( *window, KeyboardUp,
775
                else
690
                   ( (char)(wParam & 0xFF), /* and with 0xFF to indicate to runtime that we want to strip out higher bits - otherwise we get a runtime error when "Smaller Type Checks" is enabled */
776
                    INVOKE_WCB(*window, KeyboardUp, ((unsigned char)ascii, window->State.MouseX, window->State.MouseY) );
691
                        window->State.MouseX, window->State.MouseY )
777
            }
692
            );
693
        }
778
        }
694
#endif
779
#endif
695
    }
780
    }
Lines 1375-1384 LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR Link Here
1375
            break;
1460
            break;
1376
1461
1377
        fgState.Modifiers = fgPlatformGetModifiers( );
1462
        fgState.Modifiers = fgPlatformGetModifiers( );
1378
        INVOKE_WCB( *window, Keyboard,
1463
        INVOKE_WCB( *window, KeyboardExt,
1379
                    ( (char)wParam,
1464
                ( (int)wParam, window->State.MouseX, window->State.MouseY )
1380
                      window->State.MouseX, window->State.MouseY )
1381
        );
1465
        );
1466
        if (wParam < 256)
1467
            INVOKE_WCB( *window, Keyboard,
1468
                    ( (unsigned char)wParam, window->State.MouseX, window->State.MouseY )
1469
            );
1382
        fgState.Modifiers = INVALID_MODIFIERS;
1470
        fgState.Modifiers = INVALID_MODIFIERS;
1383
    }
1471
    }
1384
    break;
1472
    break;
(-)b/src/x11/fg_init_x11.c (-1 / +52 lines)
Lines 33-44 Link Here
33
#include "fg_init.h"
33
#include "fg_init.h"
34
#include "egl/fg_init_egl.h"
34
#include "egl/fg_init_egl.h"
35
35
36
#include <locale.h>
37
36
/* Return the atom associated with "name". */
38
/* Return the atom associated with "name". */
37
static Atom fghGetAtom(const char * name)
39
static Atom fghGetAtom(const char * name)
38
{
40
{
39
  return XInternAtom(fgDisplay.pDisplay.Display, name, False);
41
  return XInternAtom(fgDisplay.pDisplay.Display, name, False);
40
}
42
}
41
43
44
char *fgClipboardBuffer[3] = { NULL, NULL, NULL };
45
42
/*
46
/*
43
 * Check if "property" is set on "window".  The property's values are returned
47
 * Check if "property" is set on "window".  The property's values are returned
44
 * through "data".  If the property is set and is of type "type", return the
48
 * through "data".  If the property is set and is of type "type", return the
Lines 256-265 void fgPlatformInitialize( const char* displayName ) Link Here
256
      fgDisplay.pDisplay.ClientMachine = fghGetAtom("WM_CLIENT_MACHINE");
260
      fgDisplay.pDisplay.ClientMachine = fghGetAtom("WM_CLIENT_MACHINE");
257
    }
261
    }
258
262
263
    /* Open an input method */
264
    setlocale(LC_ALL, ""); /* ugh! but we can't force the client to do it for us... */
265
    if (!XSupportsLocale())
266
        fgWarning("X doesn't support the current locale.");
267
    if (!XSetLocaleModifiers(""))
268
        fgWarning("Couldn't set X locale modifiers.");
269
    fgDisplay.pDisplay.IM = XOpenIM(fgDisplay.pDisplay.Display, NULL, NULL, NULL);
270
    if (!fgDisplay.pDisplay.IM)
271
	fgWarning("Couldn't open X input method.");
272
    else
273
    {
274
        XIMStyles *styles;
275
        XIMStyle supported = XIMPreeditNothing | XIMStatusNothing;
276
        XIMStyle best = 0;
277
        unsigned int i;
278
        char *res = XGetIMValues(fgDisplay.pDisplay.IM, XNQueryInputStyle, &styles, NULL);
279
        if (res)
280
            fgWarning("Couldn't get input method style: %s.", res);
281
        else
282
        {
283
            for (i = 0; i < styles->count_styles; ++i)
284
            {
285
                XIMStyle style = styles->supported_styles[i];
286
                if ((style & supported) == style)
287
                    best = style;
288
            }
289
            fgDisplay.pDisplay.InputStyle = best;
290
        }
291
        XFree(styles);
292
        if (best == 0)
293
        {
294
            fgWarning("Couldn't find a usable input method style.");
295
            XCloseIM(fgDisplay.pDisplay.IM);
296
            fgDisplay.pDisplay.IM = NULL;
297
        }
298
    }
299
259
    /* Get start time */
300
    /* Get start time */
260
    fgState.Time = fgSystemTime();
301
    fgState.Time = fgSystemTime();
261
    
302
    
262
263
    fgState.Initialised = GL_TRUE;
303
    fgState.Initialised = GL_TRUE;
264
304
265
    atexit(fgDeinitialize);
305
    atexit(fgDeinitialize);
Lines 279-295 void fgPlatformDeinitialiseInputDevices ( void ) Link Here
279
319
280
void fgPlatformCloseDisplay ( void )
320
void fgPlatformCloseDisplay ( void )
281
{
321
{
322
    int i;
323
282
    /*
324
    /*
283
     * Make sure all X-client data we have created will be destroyed on
325
     * Make sure all X-client data we have created will be destroyed on
284
     * display closing
326
     * display closing
285
     */
327
     */
286
    XSetCloseDownMode( fgDisplay.pDisplay.Display, DestroyAll );
328
    XSetCloseDownMode( fgDisplay.pDisplay.Display, DestroyAll );
287
329
330
    if (fgDisplay.pDisplay.IM)
331
        XCloseIM(fgDisplay.pDisplay.IM);
332
288
    /*
333
    /*
289
     * Close the display connection, destroying all windows we have
334
     * Close the display connection, destroying all windows we have
290
     * created so far
335
     * created so far
291
     */
336
     */
292
    XCloseDisplay( fgDisplay.pDisplay.Display );
337
    XCloseDisplay( fgDisplay.pDisplay.Display );
338
339
    for (i = 0; i < 3; ++i)
340
    {
341
        free(fgClipboardBuffer[i]);
342
        fgClipboardBuffer[i] = NULL;
343
    }
293
}
344
}
294
345
295
346
(-)b/src/x11/fg_internal_x11.h (+3 lines)
Lines 63-68 struct tagSFG_PlatformDisplay Link Here
63
    int             NetWMSupported;     /* Flag for EWMH Window Managers     */
63
    int             NetWMSupported;     /* Flag for EWMH Window Managers     */
64
    Atom            NetWMPid;           /* The _NET_WM_PID atom              */
64
    Atom            NetWMPid;           /* The _NET_WM_PID atom              */
65
    Atom            ClientMachine;      /* The client machine name atom      */
65
    Atom            ClientMachine;      /* The client machine name atom      */
66
    XIM             IM;                 /* The input method                  */
67
    XIMStyle        InputStyle;         /* The input method style            */
66
68
67
#ifdef HAVE_X11_EXTENSIONS_XRANDR_H
69
#ifdef HAVE_X11_EXTENSIONS_XRANDR_H
68
    int prev_xsz, prev_ysz;
70
    int prev_xsz, prev_ysz;
Lines 107-112 struct tagSFG_PlatformContext Link Here
107
#else
109
#else
108
    GLXFBConfig    FBConfig;        /* The window's FBConfig               */
110
    GLXFBConfig    FBConfig;        /* The window's FBConfig               */
109
#endif
111
#endif
112
    XIC IC;                         /* The window's input context          */
110
};
113
};
111
114
112
115
(-)b/src/x11/fg_main_x11.c (-83 / +423 lines)
Lines 29-36 Link Here
29
#include <GL/freeglut.h>
29
#include <GL/freeglut.h>
30
#include "../fg_internal.h"
30
#include "../fg_internal.h"
31
#include <errno.h>
31
#include <errno.h>
32
#include <limits.h>
32
#include <stdarg.h>
33
#include <stdarg.h>
33
34
#include <sys/select.h>
34
35
35
/*
36
/*
36
 * Try to get the maximum value allowed for ints, falling back to the minimum
37
 * Try to get the maximum value allowed for ints, falling back to the minimum
Lines 579-584 __fg_unused static void fghPrintEvent( XEvent *event ) Link Here
579
    }
580
    }
580
}
581
}
581
582
583
/* UTF-8 decoding routine */
584
enum
585
{
586
    Runeerror = 0xFFFD, /* decoding error in UTF */
587
588
    Bit1 = 7,
589
    Bitx = 6,
590
    Bit2 = 5,
591
    Bit3 = 4,
592
    Bit4 = 3,
593
    Bit5 = 2,
594
595
    T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */
596
    Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */
597
    T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */
598
    T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */
599
    T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */
600
    T5 = ((1<<(Bit5+1))-1) ^ 0xFF, /* 1111 1000 */
601
602
    Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 1111 */
603
    Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */
604
    Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 1111 */
605
    Rune4 = (1<<(Bit4+3*Bitx))-1, /* 0001 1111 1111 1111 1111 1111 */
606
607
    Maskx = (1<<Bitx)-1,	/* 0011 1111 */
608
    Testx = Maskx ^ 0xFF,	/* 1100 0000 */
609
610
    Bad = Runeerror,
611
};
612
613
static int chartorune(int *rune, const char *str)
614
{
615
    int c, c1, c2, c3;
616
    int l;
617
618
    /*
619
     * one character sequence
620
     *	00000-0007F => T1
621
     */
622
    c = *(const unsigned char*)str;
623
    if(c < Tx) {
624
        *rune = c;
625
        return 1;
626
    }
627
628
    /*
629
     * two character sequence
630
     *	0080-07FF => T2 Tx
631
     */
632
    c1 = *(const unsigned char*)(str+1) ^ Tx;
633
    if(c1 & Testx)
634
        goto bad;
635
    if(c < T3) {
636
        if(c < T2)
637
            goto bad;
638
        l = ((c << Bitx) | c1) & Rune2;
639
        if(l <= Rune1)
640
            goto bad;
641
        *rune = l;
642
        return 2;
643
    }
644
645
    /*
646
     * three character sequence
647
     *	0800-FFFF => T3 Tx Tx
648
     */
649
    c2 = *(const unsigned char*)(str+2) ^ Tx;
650
    if(c2 & Testx)
651
        goto bad;
652
    if(c < T4) {
653
        l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
654
        if(l <= Rune2)
655
            goto bad;
656
        *rune = l;
657
        return 3;
658
    }
659
660
    /*
661
     * four character sequence (21-bit value)
662
     *	10000-1FFFFF => T4 Tx Tx Tx
663
     */
664
    c3 = *(const unsigned char*)(str+3) ^ Tx;
665
    if (c3 & Testx)
666
        goto bad;
667
    if (c < T5) {
668
        l = ((((((c << Bitx) | c1) << Bitx) | c2) << Bitx) | c3) & Rune4;
669
        if (l <= Rune3)
670
            goto bad;
671
        *rune = l;
672
        return 4;
673
    }
674
    /*
675
     * Support for 5-byte or longer UTF-8 would go here, but
676
     * since we don't have that, we'll just fall through to bad.
677
     */
678
679
    /*
680
     * bad decoding
681
     */
682
bad:
683
    *rune = Bad;
684
    return 1;
685
}
686
687
extern char *fgClipboardBuffer[3];
688
689
static Atom fghGetAtom(const char *name)
690
{
691
    return XInternAtom(fgDisplay.pDisplay.Display, name, False);
692
}
693
694
static void fgHandleSelectionNotify(XEvent *event)
695
{
696
    Display *dpy = fgDisplay.pDisplay.Display;
697
    Atom actual_type;
698
    int actual_format;
699
    unsigned long item_count;
700
    unsigned long bytes_after;
701
    unsigned char *prop;
702
703
    if (event->xselection.property == None)
704
    {
705
        fgWarning("Couldn't convert selection to UTF-8 string.");
706
        return;
707
    }
708
709
    XGetWindowProperty(dpy, event->xselection.requestor, event->xselection.property,
710
            0, LONG_MAX, True, AnyPropertyType,
711
            &actual_type, &actual_format, &item_count, &bytes_after, &prop);
712
713
    if (actual_type == fghGetAtom("UTF8_STRING"))
714
    {
715
        if (event->xselection.selection == fghGetAtom("CLIPBOARD"))
716
        {
717
            free(fgClipboardBuffer[GLUT_CLIPBOARD]);
718
            fgClipboardBuffer[GLUT_CLIPBOARD] = strdup((char*)prop);
719
        }
720
        if (event->xselection.selection == XA_PRIMARY)
721
        {
722
            free(fgClipboardBuffer[GLUT_PRIMARY]);
723
            fgClipboardBuffer[GLUT_PRIMARY] = strdup((char*)prop);
724
        }
725
        if (event->xselection.selection == XA_SECONDARY)
726
        {
727
            free(fgClipboardBuffer[GLUT_SECONDARY]);
728
            fgClipboardBuffer[GLUT_SECONDARY] = strdup((char*)prop);
729
        }
730
    }
731
732
    XFree(prop);
733
}
734
735
static void fgHandleSelectionClear(XEvent *event)
736
{
737
    if (event->xselectionclear.selection == fghGetAtom("CLIPBOARD"))
738
    {
739
        free(fgClipboardBuffer[GLUT_CLIPBOARD]);
740
        fgClipboardBuffer[GLUT_CLIPBOARD] = NULL;
741
    }
742
    else if (event->xselectionclear.selection == XA_PRIMARY)
743
    {
744
        free(fgClipboardBuffer[GLUT_PRIMARY]);
745
        fgClipboardBuffer[GLUT_PRIMARY] = NULL;
746
    }
747
    else if (event->xselectionclear.selection == XA_SECONDARY)
748
    {
749
        free(fgClipboardBuffer[GLUT_SECONDARY]);
750
        fgClipboardBuffer[GLUT_SECONDARY] = NULL;
751
    }
752
}
753
754
static void fgHandleSelectionRequest(XEvent *event)
755
{
756
    Display *dpy = fgDisplay.pDisplay.Display;
757
    Window requestor = event->xselectionrequest.requestor;
758
    Atom selection = event->xselectionrequest.selection;
759
    Atom target = event->xselectionrequest.target;
760
    Atom property = event->xselectionrequest.property;
761
    Atom time = event->xselectionrequest.time;
762
    XEvent response;
763
    char *text;
764
765
    if (property == None)
766
        property = target;
767
768
    response.xselection.type = SelectionNotify;
769
    response.xselection.send_event = True;
770
    response.xselection.display = dpy;
771
    response.xselection.requestor = requestor;
772
    response.xselection.selection = selection;
773
    response.xselection.target = target;
774
    response.xselection.property = property;
775
    response.xselection.time = time;
776
777
    if (selection == fghGetAtom("CLIPBOARD"))
778
        text = fgClipboardBuffer[GLUT_CLIPBOARD];
779
    else if (selection == XA_PRIMARY)
780
        text = fgClipboardBuffer[GLUT_PRIMARY];
781
    else if (selection == XA_SECONDARY)
782
        text = fgClipboardBuffer[GLUT_SECONDARY];
783
    else
784
        return;
785
    if (!text)
786
        return;
787
788
    if (target == fghGetAtom("TARGETS"))
789
    {
790
        Atom list[4] = {
791
            fghGetAtom("TARGETS"),
792
            fghGetAtom("TIMESTAMP"),
793
            XA_STRING,
794
            fghGetAtom("UTF8_STRING")
795
        };
796
        XChangeProperty(dpy, requestor, property, target,
797
                32, PropModeReplace, (unsigned char *)list, sizeof(list)/sizeof(Atom));
798
    }
799
    else if (target == XA_STRING || target == fghGetAtom("UTF8_STRING"))
800
    {
801
        XChangeProperty(dpy, requestor, property, target,
802
                8, PropModeReplace, (unsigned char *)text, strlen(text));
803
    }
804
805
    XSendEvent(dpy, requestor, False, 0, &response);
806
}
807
808
void fgPlatformSetClipboard(int selection, const char *text)
809
{
810
    Display *dpy = fgDisplay.pDisplay.Display;
811
    Window window = fgStructure.CurrentWindow->Window.Handle;
812
    Atom xselection;
813
    if (selection == GLUT_CLIPBOARD)
814
        xselection = fghGetAtom("CLIPBOARD");
815
    else if (selection == GLUT_PRIMARY)
816
        xselection = XA_PRIMARY;
817
    else if (selection == GLUT_SECONDARY)
818
        xselection = XA_SECONDARY;
819
    else
820
        return;
821
822
    free(fgClipboardBuffer[selection]);
823
    fgClipboardBuffer[selection] = strdup(text);
824
825
    XSetSelectionOwner(dpy, xselection, window, CurrentTime);
826
}
827
828
static Bool isSelectionNotify(Display *dpi, XEvent *event, XPointer arg)
829
{
830
    return (event->type == SelectionNotify);
831
}
832
833
const char *fgPlatformGetClipboard(int selection)
834
{
835
    Display *dpy = fgDisplay.pDisplay.Display;
836
    Window window = fgStructure.CurrentWindow->Window.Handle;
837
    Atom xselection;
838
    Window owner;
839
    XEvent event;
840
841
    if (selection == GLUT_CLIPBOARD)
842
        xselection = fghGetAtom("CLIPBOARD");
843
    else if (selection == GLUT_PRIMARY)
844
        xselection = XA_PRIMARY;
845
    else if (selection == GLUT_SECONDARY)
846
        xselection = XA_SECONDARY;
847
    else
848
        return NULL;
849
850
    owner = XGetSelectionOwner(dpy, xselection);
851
    if (!owner)
852
        return NULL;
853
    if (owner != window)
854
    {
855
        XConvertSelection(dpy, xselection, fghGetAtom("UTF8_STRING"), xselection, window, CurrentTime);
856
        XIfEvent(dpy, &event, isSelectionNotify, NULL);
857
        fgHandleSelectionNotify(&event);
858
    }
859
860
    return fgClipboardBuffer[selection];
861
}
582
862
583
void fgPlatformProcessSingleEvent ( void )
863
void fgPlatformProcessSingleEvent ( void )
584
{
864
{
Lines 603-608 void fgPlatformProcessSingleEvent ( void ) Link Here
603
#if _DEBUG
883
#if _DEBUG
604
        fghPrintEvent( &event );
884
        fghPrintEvent( &event );
605
#endif
885
#endif
886
	if (XFilterEvent(&event, None))
887
		continue;
606
888
607
        switch( event.type )
889
        switch( event.type )
608
        {
890
        {
Lines 631-636 void fgPlatformProcessSingleEvent ( void ) Link Here
631
            }
913
            }
632
            break;
914
            break;
633
915
916
        case SelectionClear:
917
            fgHandleSelectionClear(&event);
918
            break;
919
        case SelectionRequest:
920
            fgHandleSelectionRequest(&event);
921
            break;
922
        case SelectionNotify:
923
            fgHandleSelectionNotify(&event);
924
            break;
925
634
            /*
926
            /*
635
             * CreateNotify causes a configure-event so that sub-windows are
927
             * CreateNotify causes a configure-event so that sub-windows are
636
             * handled compatibly with GLUT.  Otherwise, your sub-windows
928
             * handled compatibly with GLUT.  Otherwise, your sub-windows
Lines 890-897 void fgPlatformProcessSingleEvent ( void ) Link Here
890
        case KeyRelease:
1182
        case KeyRelease:
891
        case KeyPress:
1183
        case KeyPress:
892
        {
1184
        {
893
            FGCBKeyboard keyboard_cb;
1185
            FGCBKeyboardExt keyboard_ext_cb;
1186
            FGCBKeyboard keyboard_cb, keyboard_low_cb;
894
            FGCBSpecial special_cb;
1187
            FGCBSpecial special_cb;
1188
            int did_keyboard_cb = 0;
895
1189
896
            GETWINDOW( xkey );
1190
            GETWINDOW( xkey );
897
            GETMOUSE( xkey );
1191
            GETMOUSE( xkey );
Lines 932-1039 void fgPlatformProcessSingleEvent ( void ) Link Here
932
1226
933
            if( event.type == KeyPress )
1227
            if( event.type == KeyPress )
934
            {
1228
            {
1229
                keyboard_ext_cb = (FGCBKeyboardExt)( FETCH_WCB( *window, KeyboardExt ));
1230
                keyboard_low_cb = (FGCBKeyboard)( FETCH_WCB( *window, KeyboardDown ));
935
                keyboard_cb = (FGCBKeyboard)( FETCH_WCB( *window, Keyboard ));
1231
                keyboard_cb = (FGCBKeyboard)( FETCH_WCB( *window, Keyboard ));
936
                special_cb  = (FGCBSpecial) ( FETCH_WCB( *window, Special  ));
1232
                special_cb  = (FGCBSpecial) ( FETCH_WCB( *window, Special  ));
937
            }
1233
            }
938
            else
1234
            else
939
            {
1235
            {
940
                keyboard_cb = (FGCBKeyboard)( FETCH_WCB( *window, KeyboardUp ));
1236
                keyboard_ext_cb = NULL;
1237
                keyboard_low_cb = (FGCBKeyboard)( FETCH_WCB( *window, KeyboardUp ));
1238
                keyboard_cb = NULL;
941
                special_cb  = (FGCBSpecial) ( FETCH_WCB( *window, SpecialUp  ));
1239
                special_cb  = (FGCBSpecial) ( FETCH_WCB( *window, SpecialUp  ));
942
            }
1240
            }
943
1241
944
            /* Is there a keyboard/special callback hooked for this window? */
1242
            /* Is there a character keyboard callback hooked for this window? */
945
            if( keyboard_cb || special_cb )
1243
            if (keyboard_ext_cb || keyboard_cb)
946
            {
1244
            {
947
                XComposeStatus composeStatus;
1245
                static XComposeStatus composeStatus = { 0 }; /* keep state across invocations */
948
                char asciiCode[ 32 ];
1246
                XIC ic = window->Window.pContext.IC;
1247
                Status status;
1248
                char buf[32], *utf8 = buf;
949
                KeySym keySym;
1249
                KeySym keySym;
950
                int len;
1250
                int i, c, len;
951
1251
952
                /* Check for the ASCII/KeySym codes associated with the event: */
1252
                /* Check for the Unicode text associated with the event: */
953
                len = XLookupString( &event.xkey, asciiCode, sizeof(asciiCode),
1253
                if (ic)
954
                                     &keySym, &composeStatus
955
                );
956
957
                /* GLUT API tells us to have two separate callbacks... */
958
                if( len > 0 )
959
                {
1254
                {
960
                    /* ...one for the ASCII translateable keypresses... */
1255
                    len = Xutf8LookupString(ic, &event.xkey, buf, sizeof buf, &keySym, &status);
961
                    if( keyboard_cb )
1256
                    if (status == XBufferOverflow)
962
                    {
1257
                    {
963
                        fgSetWindow( window );
1258
                        utf8 = malloc(len);
964
                        fgState.Modifiers = fgPlatformGetModifiers( event.xkey.state );
1259
                        len = Xutf8LookupString(ic, &event.xkey, utf8, len, &keySym, &status);
965
                        keyboard_cb( asciiCode[ 0 ],
966
                                     event.xkey.x, event.xkey.y
967
                        );
968
                        fgState.Modifiers = INVALID_MODIFIERS;
969
                    }
1260
                    }
970
                }
1261
                }
971
                else
1262
                else
972
                {
1263
                {
973
                    int special = -1;
1264
                    len = XLookupString(&event.xkey, buf, sizeof buf, &keySym, &composeStatus);
1265
                }
974
1266
975
                    /*
1267
                if (len > 0)
976
                     * ...and one for all the others, which need to be
1268
                {
977
                     * translated to GLUT_KEY_Xs...
1269
                    fgSetWindow(window);
978
                     */
1270
                    fgState.Modifiers = fgPlatformGetModifiers(event.xkey.state);
979
                    switch( keySym )
980
                    {
981
                    case XK_F1:     special = GLUT_KEY_F1;     break;
982
                    case XK_F2:     special = GLUT_KEY_F2;     break;
983
                    case XK_F3:     special = GLUT_KEY_F3;     break;
984
                    case XK_F4:     special = GLUT_KEY_F4;     break;
985
                    case XK_F5:     special = GLUT_KEY_F5;     break;
986
                    case XK_F6:     special = GLUT_KEY_F6;     break;
987
                    case XK_F7:     special = GLUT_KEY_F7;     break;
988
                    case XK_F8:     special = GLUT_KEY_F8;     break;
989
                    case XK_F9:     special = GLUT_KEY_F9;     break;
990
                    case XK_F10:    special = GLUT_KEY_F10;    break;
991
                    case XK_F11:    special = GLUT_KEY_F11;    break;
992
                    case XK_F12:    special = GLUT_KEY_F12;    break;
993
994
                    case XK_KP_Left:
995
                    case XK_Left:   special = GLUT_KEY_LEFT;   break;
996
                    case XK_KP_Right:
997
                    case XK_Right:  special = GLUT_KEY_RIGHT;  break;
998
                    case XK_KP_Up:
999
                    case XK_Up:     special = GLUT_KEY_UP;     break;
1000
                    case XK_KP_Down:
1001
                    case XK_Down:   special = GLUT_KEY_DOWN;   break;
1002
1003
                    case XK_KP_Prior:
1004
                    case XK_Prior:  special = GLUT_KEY_PAGE_UP; break;
1005
                    case XK_KP_Next:
1006
                    case XK_Next:   special = GLUT_KEY_PAGE_DOWN; break;
1007
                    case XK_KP_Home:
1008
                    case XK_Home:   special = GLUT_KEY_HOME;   break;
1009
                    case XK_KP_End:
1010
                    case XK_End:    special = GLUT_KEY_END;    break;
1011
                    case XK_KP_Insert:
1012
                    case XK_Insert: special = GLUT_KEY_INSERT; break;
1013
1014
                    case XK_Num_Lock :  special = GLUT_KEY_NUM_LOCK;  break;
1015
                    case XK_KP_Begin :  special = GLUT_KEY_BEGIN;     break;
1016
                    case XK_KP_Delete:  special = GLUT_KEY_DELETE;    break;
1017
1018
                    case XK_Shift_L:   special = GLUT_KEY_SHIFT_L;    break;
1019
                    case XK_Shift_R:   special = GLUT_KEY_SHIFT_R;    break;
1020
                    case XK_Control_L: special = GLUT_KEY_CTRL_L;     break;
1021
                    case XK_Control_R: special = GLUT_KEY_CTRL_R;     break;
1022
                    case XK_Alt_L:     special = GLUT_KEY_ALT_L;      break;
1023
                    case XK_Alt_R:     special = GLUT_KEY_ALT_R;      break;
1024
                    }
1025
1271
1026
                    /*
1272
                    i = 0;
1027
                     * Execute the callback (if one has been specified),
1273
                    while (i < len)
1028
                     * given that the special code seems to be valid...
1029
                     */
1030
                    if( special_cb && (special != -1) )
1031
                    {
1274
                    {
1032
                        fgSetWindow( window );
1275
                        i += chartorune(&c, utf8 + i);
1033
                        fgState.Modifiers = fgPlatformGetModifiers( event.xkey.state );
1276
1034
                        special_cb( special, event.xkey.x, event.xkey.y );
1277
                        /* ...for the Unicode translateable keypresses... */
1035
                        fgState.Modifiers = INVALID_MODIFIERS;
1278
                        if (keyboard_ext_cb)
1279
                            keyboard_ext_cb(c, event.xkey.x, event.xkey.y);
1280
1281
                        /* ...for the Latin-1 translateable keypresses... */
1282
                        if (keyboard_cb)
1283
                            if (c < 256)
1284
                                keyboard_cb(c, event.xkey.x, event.xkey.y);
1036
                    }
1285
                    }
1286
1287
                    fgState.Modifiers = INVALID_MODIFIERS;
1288
1289
                    did_keyboard_cb = 1;
1290
                }
1291
1292
                if (utf8 != buf)
1293
                    free(utf8);
1294
            }
1295
1296
            /* Is there a low-level keyboard callback hooked for this window? */
1297
            if (keyboard_low_cb || special_cb)
1298
            {
1299
                int special = -1;
1300
                int ascii = 0;
1301
1302
                KeySym keySym = XLookupKeysym(&event.xkey, 0);
1303
1304
                /* ...for low-level keys, which need to be
1305
                 * translated to GLUT_KEY_Xs or ASCII values...
1306
                 */
1307
                switch( keySym )
1308
                {
1309
                case XK_F1:     special = GLUT_KEY_F1;     break;
1310
                case XK_F2:     special = GLUT_KEY_F2;     break;
1311
                case XK_F3:     special = GLUT_KEY_F3;     break;
1312
                case XK_F4:     special = GLUT_KEY_F4;     break;
1313
                case XK_F5:     special = GLUT_KEY_F5;     break;
1314
                case XK_F6:     special = GLUT_KEY_F6;     break;
1315
                case XK_F7:     special = GLUT_KEY_F7;     break;
1316
                case XK_F8:     special = GLUT_KEY_F8;     break;
1317
                case XK_F9:     special = GLUT_KEY_F9;     break;
1318
                case XK_F10:    special = GLUT_KEY_F10;    break;
1319
                case XK_F11:    special = GLUT_KEY_F11;    break;
1320
                case XK_F12:    special = GLUT_KEY_F12;    break;
1321
1322
                case XK_KP_Left:
1323
                case XK_Left:   special = GLUT_KEY_LEFT;   break;
1324
                case XK_KP_Right:
1325
                case XK_Right:  special = GLUT_KEY_RIGHT;  break;
1326
                case XK_KP_Up:
1327
                case XK_Up:     special = GLUT_KEY_UP;     break;
1328
                case XK_KP_Down:
1329
                case XK_Down:   special = GLUT_KEY_DOWN;   break;
1330
1331
                case XK_KP_Prior:
1332
                case XK_Prior:  special = GLUT_KEY_PAGE_UP; break;
1333
                case XK_KP_Next:
1334
                case XK_Next:   special = GLUT_KEY_PAGE_DOWN; break;
1335
                case XK_KP_Home:
1336
                case XK_Home:   special = GLUT_KEY_HOME;   break;
1337
                case XK_KP_End:
1338
                case XK_End:    special = GLUT_KEY_END;    break;
1339
                case XK_KP_Insert:
1340
                case XK_Insert: special = GLUT_KEY_INSERT; break;
1341
1342
                case XK_Num_Lock :  special = GLUT_KEY_NUM_LOCK;  break;
1343
                case XK_KP_Begin :  special = GLUT_KEY_BEGIN;     break;
1344
                case XK_KP_Delete:  special = GLUT_KEY_DELETE;    break;
1345
1346
                case XK_Shift_L:   special = GLUT_KEY_SHIFT_L;    break;
1347
                case XK_Shift_R:   special = GLUT_KEY_SHIFT_R;    break;
1348
                case XK_Control_L: special = GLUT_KEY_CTRL_L;     break;
1349
                case XK_Control_R: special = GLUT_KEY_CTRL_R;     break;
1350
                case XK_Alt_L:     special = GLUT_KEY_ALT_L;      break;
1351
                case XK_Alt_R:     special = GLUT_KEY_ALT_R;      break;
1352
                default:
1353
                    if( keySym >= XK_space && keySym <= XK_ydiaeresis )
1354
                        ascii = keySym;
1355
                    break;
1356
                }
1357
1358
                /*
1359
                 * Execute the callback (if one has been specified),
1360
                 * given that the special code seems to be valid...
1361
                 * But only if we haven't already sent translated text for it,
1362
                 * such as numeric keypad keys with numlock on.
1363
                 */
1364
                if( special_cb && (special != -1) && !did_keyboard_cb )
1365
                {
1366
                    fgSetWindow( window );
1367
                    fgState.Modifiers = fgPlatformGetModifiers( event.xkey.state );
1368
                    special_cb( special, event.xkey.x, event.xkey.y );
1369
                    fgState.Modifiers = INVALID_MODIFIERS;
1370
                }
1371
                else if( keyboard_low_cb && (ascii >= 32 && ascii < 256) )
1372
                {
1373
                    fgSetWindow( window );
1374
                    fgState.Modifiers = fgPlatformGetModifiers( event.xkey.state );
1375
                    keyboard_low_cb( ascii, event.xkey.x, event.xkey.y );
1376
                    fgState.Modifiers = INVALID_MODIFIERS;
1037
                }
1377
                }
1038
            }
1378
            }
1039
        }
1379
        }
(-)b/src/x11/fg_window_x11.c (-6 / +29 lines)
Lines 154-159 void fgPlatformOpenWindow( SFG_Window* window, const char* title, Link Here
154
    unsigned long mask;
154
    unsigned long mask;
155
    unsigned int current_DisplayMode = fgState.DisplayMode ;
155
    unsigned int current_DisplayMode = fgState.DisplayMode ;
156
    XEvent fakeEvent = {0};
156
    XEvent fakeEvent = {0};
157
    long event_mask;
157
158
158
    /* Save the display mode if we are creating a menu window */
159
    /* Save the display mode if we are creating a menu window */
159
    if( window->IsMenu && ( ! fgStructure.MenuContext ) )
160
    if( window->IsMenu && ( ! fgStructure.MenuContext ) )
Lines 223-233 void fgPlatformOpenWindow( SFG_Window* window, const char* title, Link Here
223
     * XXX    more pleasant to trace.  (Think mouse-motion!  Tons of
224
     * XXX    more pleasant to trace.  (Think mouse-motion!  Tons of
224
     * XXX    ``bonus'' GUI events stream in.)
225
     * XXX    ``bonus'' GUI events stream in.)
225
     */
226
     */
226
    winAttr.event_mask        =
227
        StructureNotifyMask | SubstructureNotifyMask | ExposureMask |
228
        ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
229
        VisibilityChangeMask | EnterWindowMask | LeaveWindowMask |
230
        PointerMotionMask | ButtonMotionMask;
231
    winAttr.background_pixmap = None;
227
    winAttr.background_pixmap = None;
232
    winAttr.background_pixel  = 0;
228
    winAttr.background_pixel  = 0;
233
    winAttr.border_pixel      = 0;
229
    winAttr.border_pixel      = 0;
Lines 237-243 void fgPlatformOpenWindow( SFG_Window* window, const char* title, Link Here
237
        visualInfo->visual, AllocNone
233
        visualInfo->visual, AllocNone
238
    );
234
    );
239
235
240
    mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
236
    mask = CWBackPixmap | CWBorderPixel | CWColormap;
241
237
242
    if( window->IsMenu || ( gameMode == GL_TRUE ) )
238
    if( window->IsMenu || ( gameMode == GL_TRUE ) )
243
    {
239
    {
Lines 260-265 void fgPlatformOpenWindow( SFG_Window* window, const char* title, Link Here
260
        &winAttr
256
        &winAttr
261
    );
257
    );
262
258
259
    event_mask =
260
        StructureNotifyMask | SubstructureNotifyMask | ExposureMask |
261
        ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
262
        VisibilityChangeMask | EnterWindowMask | LeaveWindowMask |
263
        PointerMotionMask | ButtonMotionMask;
264
265
    /* Create input context */
266
    window->Window.pContext.IC = NULL;
267
    if (fgDisplay.pDisplay.IM)
268
    {
269
        long im_event_mask;
270
        window->Window.pContext.IC =
271
            XCreateIC(fgDisplay.pDisplay.IM,
272
                    XNInputStyle, fgDisplay.pDisplay.InputStyle,
273
                    XNClientWindow, window->Window.Handle,
274
                    XNFocusWindow, window->Window.Handle,
275
                    NULL);
276
        XGetICValues(window->Window.pContext.IC, XNFilterEvents, &im_event_mask, NULL);
277
        event_mask |= im_event_mask;
278
        XSetICFocus(window->Window.pContext.IC);
279
    }
280
    XSelectInput(fgDisplay.pDisplay.Display, window->Window.Handle, event_mask);
281
263
    /* Fake configure event to force viewport setup
282
    /* Fake configure event to force viewport setup
264
     * even with no window manager.
283
     * even with no window manager.
265
     */
284
     */
Lines 466-471 void fgPlatformCloseWindow( SFG_Window* window ) Link Here
466
    window->Window.pContext.FBConfig = NULL;
485
    window->Window.pContext.FBConfig = NULL;
467
#endif
486
#endif
468
487
488
    if (window->Window.pContext.IC) {
489
        XDestroyIC(window->Window.pContext.IC);
490
    }
491
469
    if( window->Window.Handle ) {
492
    if( window->Window.Handle ) {
470
        XDestroyWindow( fgDisplay.pDisplay.Display, window->Window.Handle );
493
        XDestroyWindow( fgDisplay.pDisplay.Display, window->Window.Handle );
471
    }
494
    }

Return to bug 254451