ruby-glfw 0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +1 -0
- data/README.API +73 -0
- data/Rakefile +120 -0
- data/examples/boing.rb +519 -0
- data/examples/gears.rb +327 -0
- data/examples/keytest.rb +117 -0
- data/examples/listmodes.rb +20 -0
- data/examples/mipmaps.rb +104 -0
- data/examples/mipmaps.tga +0 -0
- data/examples/particles.rb +837 -0
- data/examples/pong3d.rb +741 -0
- data/examples/pong3d_field.tga +0 -0
- data/examples/pong3d_instr.tga +0 -0
- data/examples/pong3d_menu.tga +0 -0
- data/examples/pong3d_title.tga +0 -0
- data/examples/pong3d_winner1.tga +0 -0
- data/examples/pong3d_winner2.tga +0 -0
- data/examples/splitview.rb +432 -0
- data/examples/triangle.rb +89 -0
- data/examples/wave.rb +294 -0
- data/ext/glfw/glfw.c +1094 -0
- data/ext/glfw/mkrf_conf.rb +70 -0
- data/glfw-src/Makefile +220 -0
- data/glfw-src/compile.ami +61 -0
- data/glfw-src/compile.bat +217 -0
- data/glfw-src/compile.sh +607 -0
- data/glfw-src/docs/Makefile +57 -0
- data/glfw-src/docs/Reference.pdf +0 -0
- data/glfw-src/docs/UsersGuide.pdf +0 -0
- data/glfw-src/docs/cleanup.bat +22 -0
- data/glfw-src/docs/glfwdoc.sty +80 -0
- data/glfw-src/docs/glfwrm.tex +3034 -0
- data/glfw-src/docs/glfwug.tex +2024 -0
- data/glfw-src/docs/readme.txt +80 -0
- data/glfw-src/examples/Makefile.amigaos.gcc +70 -0
- data/glfw-src/examples/Makefile.amigaos.vbcc +70 -0
- data/glfw-src/examples/Makefile.dos.djgpp +71 -0
- data/glfw-src/examples/Makefile.macosx.gcc +96 -0
- data/glfw-src/examples/Makefile.win32.bcc +75 -0
- data/glfw-src/examples/Makefile.win32.cross-mgw +79 -0
- data/glfw-src/examples/Makefile.win32.cygwin +79 -0
- data/glfw-src/examples/Makefile.win32.lcc +74 -0
- data/glfw-src/examples/Makefile.win32.mgw +75 -0
- data/glfw-src/examples/Makefile.win32.msvc +74 -0
- data/glfw-src/examples/Makefile.win32.ow +74 -0
- data/glfw-src/examples/Makefile.win32.pellesc +74 -0
- data/glfw-src/examples/Makefile.x11.in +54 -0
- data/glfw-src/examples/boing.c +606 -0
- data/glfw-src/examples/bundle.sh +46 -0
- data/glfw-src/examples/gears.c +382 -0
- data/glfw-src/examples/keytest.c +264 -0
- data/glfw-src/examples/listmodes.c +48 -0
- data/glfw-src/examples/mipmaps.c +126 -0
- data/glfw-src/examples/mipmaps.tga +0 -0
- data/glfw-src/examples/mtbench.c +301 -0
- data/glfw-src/examples/mthello.c +48 -0
- data/glfw-src/examples/particles.c +1148 -0
- data/glfw-src/examples/pong3d.c +839 -0
- data/glfw-src/examples/pong3d_field.tga +0 -0
- data/glfw-src/examples/pong3d_instr.tga +0 -0
- data/glfw-src/examples/pong3d_menu.tga +0 -0
- data/glfw-src/examples/pong3d_title.tga +0 -0
- data/glfw-src/examples/pong3d_winner1.tga +0 -0
- data/glfw-src/examples/pong3d_winner2.tga +0 -0
- data/glfw-src/examples/splitview.c +506 -0
- data/glfw-src/examples/triangle.c +108 -0
- data/glfw-src/examples/wave.c +397 -0
- data/glfw-src/images/opengl.gif +0 -0
- data/glfw-src/images/osicert.gif +0 -0
- data/glfw-src/include/GL/glfw.h +486 -0
- data/glfw-src/lib/amigaos/Makefile.amigaos.gcc +128 -0
- data/glfw-src/lib/amigaos/Makefile.amigaos.vbcc +128 -0
- data/glfw-src/lib/amigaos/SDI_compiler.h +94 -0
- data/glfw-src/lib/amigaos/amigaos_enable.c +51 -0
- data/glfw-src/lib/amigaos/amigaos_fullscreen.c +319 -0
- data/glfw-src/lib/amigaos/amigaos_glext.c +61 -0
- data/glfw-src/lib/amigaos/amigaos_init.c +284 -0
- data/glfw-src/lib/amigaos/amigaos_joystick.c +359 -0
- data/glfw-src/lib/amigaos/amigaos_thread.c +494 -0
- data/glfw-src/lib/amigaos/amigaos_time.c +206 -0
- data/glfw-src/lib/amigaos/amigaos_window.c +830 -0
- data/glfw-src/lib/amigaos/platform.h +337 -0
- data/glfw-src/lib/dos/Makefile.dos.djgpp +146 -0
- data/glfw-src/lib/dos/dos_enable.c +51 -0
- data/glfw-src/lib/dos/dos_events.c +173 -0
- data/glfw-src/lib/dos/dos_fullscreen.c +101 -0
- data/glfw-src/lib/dos/dos_glext.c +59 -0
- data/glfw-src/lib/dos/dos_init.c +105 -0
- data/glfw-src/lib/dos/dos_irq.s +246 -0
- data/glfw-src/lib/dos/dos_joystick.c +94 -0
- data/glfw-src/lib/dos/dos_keyboard.c +694 -0
- data/glfw-src/lib/dos/dos_mouse.c +337 -0
- data/glfw-src/lib/dos/dos_thread.c +267 -0
- data/glfw-src/lib/dos/dos_time.c +309 -0
- data/glfw-src/lib/dos/dos_window.c +563 -0
- data/glfw-src/lib/dos/platform.h +341 -0
- data/glfw-src/lib/enable.c +295 -0
- data/glfw-src/lib/fullscreen.c +95 -0
- data/glfw-src/lib/glext.c +201 -0
- data/glfw-src/lib/image.c +629 -0
- data/glfw-src/lib/init.c +108 -0
- data/glfw-src/lib/input.c +280 -0
- data/glfw-src/lib/internal.h +210 -0
- data/glfw-src/lib/joystick.c +101 -0
- data/glfw-src/lib/macosx/Makefile.macosx.gcc +172 -0
- data/glfw-src/lib/macosx/Makefile.macosx.gcc.universal +166 -0
- data/glfw-src/lib/macosx/libglfw.pc.in +11 -0
- data/glfw-src/lib/macosx/macosx_enable.c +42 -0
- data/glfw-src/lib/macosx/macosx_fullscreen.c +126 -0
- data/glfw-src/lib/macosx/macosx_glext.c +52 -0
- data/glfw-src/lib/macosx/macosx_init.c +194 -0
- data/glfw-src/lib/macosx/macosx_joystick.c +50 -0
- data/glfw-src/lib/macosx/macosx_thread.c +414 -0
- data/glfw-src/lib/macosx/macosx_time.c +112 -0
- data/glfw-src/lib/macosx/macosx_window.c +1279 -0
- data/glfw-src/lib/macosx/platform.h +349 -0
- data/glfw-src/lib/stream.c +194 -0
- data/glfw-src/lib/tga.c +405 -0
- data/glfw-src/lib/thread.c +340 -0
- data/glfw-src/lib/time.c +83 -0
- data/glfw-src/lib/win32/Makefile.win32.bcc +265 -0
- data/glfw-src/lib/win32/Makefile.win32.cross-mgw +274 -0
- data/glfw-src/lib/win32/Makefile.win32.cygwin +279 -0
- data/glfw-src/lib/win32/Makefile.win32.lcc +246 -0
- data/glfw-src/lib/win32/Makefile.win32.mgw +243 -0
- data/glfw-src/lib/win32/Makefile.win32.msvc +242 -0
- data/glfw-src/lib/win32/Makefile.win32.ow +242 -0
- data/glfw-src/lib/win32/Makefile.win32.pellesc +242 -0
- data/glfw-src/lib/win32/glfwdll.def +67 -0
- data/glfw-src/lib/win32/glfwdll_mgw1.def +67 -0
- data/glfw-src/lib/win32/glfwdll_mgw2.def +67 -0
- data/glfw-src/lib/win32/glfwdll_pellesc.def +65 -0
- data/glfw-src/lib/win32/libglfw.pc.in +11 -0
- data/glfw-src/lib/win32/platform.h +474 -0
- data/glfw-src/lib/win32/win32_dllmain.c +60 -0
- data/glfw-src/lib/win32/win32_enable.c +155 -0
- data/glfw-src/lib/win32/win32_fullscreen.c +317 -0
- data/glfw-src/lib/win32/win32_glext.c +85 -0
- data/glfw-src/lib/win32/win32_init.c +356 -0
- data/glfw-src/lib/win32/win32_joystick.c +234 -0
- data/glfw-src/lib/win32/win32_thread.c +511 -0
- data/glfw-src/lib/win32/win32_time.c +146 -0
- data/glfw-src/lib/win32/win32_window.c +1714 -0
- data/glfw-src/lib/window.c +727 -0
- data/glfw-src/lib/x11/Makefile.x11.in +243 -0
- data/glfw-src/lib/x11/platform.h +415 -0
- data/glfw-src/lib/x11/x11_enable.c +51 -0
- data/glfw-src/lib/x11/x11_fullscreen.c +524 -0
- data/glfw-src/lib/x11/x11_glext.c +69 -0
- data/glfw-src/lib/x11/x11_init.c +275 -0
- data/glfw-src/lib/x11/x11_joystick.c +371 -0
- data/glfw-src/lib/x11/x11_keysym2unicode.c +902 -0
- data/glfw-src/lib/x11/x11_thread.c +507 -0
- data/glfw-src/lib/x11/x11_time.c +154 -0
- data/glfw-src/lib/x11/x11_window.c +1746 -0
- data/glfw-src/license.txt +21 -0
- data/glfw-src/readme.html +927 -0
- data/glfw-src/support/d/examples/Makefile +59 -0
- data/glfw-src/support/d/examples/boing.d +610 -0
- data/glfw-src/support/d/examples/gears.d +379 -0
- data/glfw-src/support/d/examples/keytest.d +272 -0
- data/glfw-src/support/d/examples/listmodes.d +48 -0
- data/glfw-src/support/d/examples/mipmaps.d +126 -0
- data/glfw-src/support/d/examples/mtbench.d +304 -0
- data/glfw-src/support/d/examples/mthello.d +54 -0
- data/glfw-src/support/d/examples/particles.d +1150 -0
- data/glfw-src/support/d/examples/pong3d.d +840 -0
- data/glfw-src/support/d/examples/splitview.d +486 -0
- data/glfw-src/support/d/examples/triangle.d +108 -0
- data/glfw-src/support/d/examples/wave.d +400 -0
- data/glfw-src/support/d/imports/gl.d +4539 -0
- data/glfw-src/support/d/imports/glfw.d +349 -0
- data/glfw-src/support/d/imports/glu.d +328 -0
- data/glfw-src/support/d/lib/glfwdll.def +64 -0
- data/glfw-src/support/d/lib/glu32.def +56 -0
- data/glfw-src/support/d/lib/makefile +12 -0
- data/glfw-src/support/d/lib/opengl32.def +372 -0
- data/glfw-src/support/d/readme.html +83 -0
- data/glfw-src/support/delphi/examples/Triangle.dpr +105 -0
- data/glfw-src/support/delphi/lib/glfw.pas +437 -0
- data/glfw-src/support/delphi/readme.html +97 -0
- data/glfw-src/support/lua/examples/gears.lua +383 -0
- data/glfw-src/support/lua/examples/test1.lua +68 -0
- data/glfw-src/support/lua/readme.html +128 -0
- data/glfw-src/support/lua/src/luaglfw.c +1179 -0
- data/glfw-src/support/lua/src/luaglfw.h +48 -0
- data/glfw-src/support/lua/src/runlua.c +82 -0
- data/glfw-src/support/masm/examples/fpc.mac +47 -0
- data/glfw-src/support/masm/examples/makeit.bat +66 -0
- data/glfw-src/support/masm/examples/triangle.asm +232 -0
- data/glfw-src/support/masm/include/glfw.inc +326 -0
- data/glfw-src/support/masm/include/glu32.inc +55 -0
- data/glfw-src/support/masm/include/opengl32.inc +372 -0
- data/glfw-src/support/masm/lib/glfwdll.lib +0 -0
- data/glfw-src/support/masm/readme.html +170 -0
- data/glfw-src/support/msvc80/GLFW.sln +26 -0
- data/glfw-src/support/msvc80/GLFW.vcproj +257 -0
- data/glfw-src/support/msvc80/GLFWDLL.vcproj +287 -0
- data/glfw-src/support/visualbasic/bindings/glfw.bas +320 -0
- data/glfw-src/support/visualbasic/bindings/glu32.bas +284 -0
- data/glfw-src/support/visualbasic/bindings/opengl32.bas +999 -0
- data/glfw-src/support/visualbasic/examples/Triangle.bas +101 -0
- data/glfw-src/support/visualbasic/readme.html +164 -0
- data/website/index.html +84 -0
- data/website/style.css +110 -0
- metadata +301 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
//========================================================================
|
|
2
|
+
// GLFW - An OpenGL framework
|
|
3
|
+
// File: x11_time.c
|
|
4
|
+
// Platform: X11 (Unix)
|
|
5
|
+
// API version: 2.6
|
|
6
|
+
// WWW: http://glfw.sourceforge.net
|
|
7
|
+
//------------------------------------------------------------------------
|
|
8
|
+
// Copyright (c) 2002-2006 Camilla Berglund
|
|
9
|
+
//
|
|
10
|
+
// This software is provided 'as-is', without any express or implied
|
|
11
|
+
// warranty. In no event will the authors be held liable for any damages
|
|
12
|
+
// arising from the use of this software.
|
|
13
|
+
//
|
|
14
|
+
// Permission is granted to anyone to use this software for any purpose,
|
|
15
|
+
// including commercial applications, and to alter it and redistribute it
|
|
16
|
+
// freely, subject to the following restrictions:
|
|
17
|
+
//
|
|
18
|
+
// 1. The origin of this software must not be misrepresented; you must not
|
|
19
|
+
// claim that you wrote the original software. If you use this software
|
|
20
|
+
// in a product, an acknowledgment in the product documentation would
|
|
21
|
+
// be appreciated but is not required.
|
|
22
|
+
//
|
|
23
|
+
// 2. Altered source versions must be plainly marked as such, and must not
|
|
24
|
+
// be misrepresented as being the original software.
|
|
25
|
+
//
|
|
26
|
+
// 3. This notice may not be removed or altered from any source
|
|
27
|
+
// distribution.
|
|
28
|
+
//
|
|
29
|
+
//========================================================================
|
|
30
|
+
|
|
31
|
+
#include "internal.h"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
//========================================================================
|
|
35
|
+
// Initialise timer
|
|
36
|
+
//========================================================================
|
|
37
|
+
|
|
38
|
+
void _glfwInitTimer( void )
|
|
39
|
+
{
|
|
40
|
+
struct timeval tv;
|
|
41
|
+
|
|
42
|
+
// "Resolution" is 1 us
|
|
43
|
+
_glfwLibrary.Timer.Resolution = 1e-6;
|
|
44
|
+
|
|
45
|
+
// Set start-time for timer
|
|
46
|
+
gettimeofday( &tv, NULL );
|
|
47
|
+
_glfwLibrary.Timer.t0 = (long long) tv.tv_sec * (long long) 1000000 +
|
|
48
|
+
(long long) tv.tv_usec;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
//************************************************************************
|
|
53
|
+
//**** Platform implementation functions ****
|
|
54
|
+
//************************************************************************
|
|
55
|
+
|
|
56
|
+
//========================================================================
|
|
57
|
+
// Return timer value in seconds
|
|
58
|
+
//========================================================================
|
|
59
|
+
|
|
60
|
+
double _glfwPlatformGetTime( void )
|
|
61
|
+
{
|
|
62
|
+
long long t;
|
|
63
|
+
struct timeval tv;
|
|
64
|
+
|
|
65
|
+
gettimeofday( &tv, NULL );
|
|
66
|
+
t = (long long) tv.tv_sec * (long long) 1000000 +
|
|
67
|
+
(long long) tv.tv_usec;
|
|
68
|
+
|
|
69
|
+
return (double)(t - _glfwLibrary.Timer.t0) * _glfwLibrary.Timer.Resolution;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
//========================================================================
|
|
74
|
+
// Set timer value in seconds
|
|
75
|
+
//========================================================================
|
|
76
|
+
|
|
77
|
+
void _glfwPlatformSetTime( double t )
|
|
78
|
+
{
|
|
79
|
+
long long t0;
|
|
80
|
+
struct timeval tv;
|
|
81
|
+
|
|
82
|
+
gettimeofday( &tv, NULL );
|
|
83
|
+
t0 = (long long) tv.tv_sec * (long long) 1000000 +
|
|
84
|
+
(long long) tv.tv_usec;
|
|
85
|
+
|
|
86
|
+
// Calulate new starting time
|
|
87
|
+
_glfwLibrary.Timer.t0 = t0 - (long long)(t/_glfwLibrary.Timer.Resolution);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
//========================================================================
|
|
92
|
+
// Put a thread to sleep for a specified amount of time
|
|
93
|
+
//========================================================================
|
|
94
|
+
|
|
95
|
+
void _glfwPlatformSleep( double time )
|
|
96
|
+
{
|
|
97
|
+
#ifdef _GLFW_HAS_PTHREAD
|
|
98
|
+
|
|
99
|
+
if( time == 0.0 )
|
|
100
|
+
{
|
|
101
|
+
#ifdef _GLFW_HAS_SCHED_YIELD
|
|
102
|
+
sched_yield();
|
|
103
|
+
#endif
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
struct timeval currenttime;
|
|
108
|
+
struct timespec wait;
|
|
109
|
+
pthread_mutex_t mutex;
|
|
110
|
+
pthread_cond_t cond;
|
|
111
|
+
long dt_sec, dt_usec;
|
|
112
|
+
|
|
113
|
+
// Not all pthread implementations have a pthread_sleep() function. We
|
|
114
|
+
// do it the portable way, using a timed wait for a condition that we
|
|
115
|
+
// will never signal. NOTE: The unistd functions sleep/usleep suspends
|
|
116
|
+
// the entire PROCESS, not a signle thread, which is why we can not
|
|
117
|
+
// use them to implement glfwSleep.
|
|
118
|
+
|
|
119
|
+
// Set timeout time, relatvie to current time
|
|
120
|
+
gettimeofday( ¤ttime, NULL );
|
|
121
|
+
dt_sec = (long) time;
|
|
122
|
+
dt_usec = (long) ((time - (double)dt_sec) * 1000000.0);
|
|
123
|
+
wait.tv_nsec = (currenttime.tv_usec + dt_usec) * 1000L;
|
|
124
|
+
if( wait.tv_nsec > 1000000000L )
|
|
125
|
+
{
|
|
126
|
+
wait.tv_nsec -= 1000000000L;
|
|
127
|
+
dt_sec++;
|
|
128
|
+
}
|
|
129
|
+
wait.tv_sec = currenttime.tv_sec + dt_sec;
|
|
130
|
+
|
|
131
|
+
// Initialize condition and mutex objects
|
|
132
|
+
pthread_mutex_init( &mutex, NULL );
|
|
133
|
+
pthread_cond_init( &cond, NULL );
|
|
134
|
+
|
|
135
|
+
// Do a timed wait
|
|
136
|
+
pthread_mutex_lock( &mutex );
|
|
137
|
+
pthread_cond_timedwait( &cond, &mutex, &wait );
|
|
138
|
+
pthread_mutex_unlock( &mutex );
|
|
139
|
+
|
|
140
|
+
// Destroy condition and mutex objects
|
|
141
|
+
pthread_mutex_destroy( &mutex );
|
|
142
|
+
pthread_cond_destroy( &cond );
|
|
143
|
+
|
|
144
|
+
#else
|
|
145
|
+
|
|
146
|
+
// For systems without PTHREAD, use unistd usleep
|
|
147
|
+
if( time > 0 )
|
|
148
|
+
{
|
|
149
|
+
usleep( (unsigned int) (time*1000000) );
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
#endif // _GLFW_HAS_PTHREAD
|
|
153
|
+
}
|
|
154
|
+
|
|
@@ -0,0 +1,1746 @@
|
|
|
1
|
+
//========================================================================
|
|
2
|
+
// GLFW - An OpenGL framework
|
|
3
|
+
// File: x11_window.c
|
|
4
|
+
// Platform: X11 (Unix)
|
|
5
|
+
// API version: 2.6
|
|
6
|
+
// WWW: http://glfw.sourceforge.net
|
|
7
|
+
//------------------------------------------------------------------------
|
|
8
|
+
// Copyright (c) 2002-2006 Camilla Berglund
|
|
9
|
+
//
|
|
10
|
+
// This software is provided 'as-is', without any express or implied
|
|
11
|
+
// warranty. In no event will the authors be held liable for any damages
|
|
12
|
+
// arising from the use of this software.
|
|
13
|
+
//
|
|
14
|
+
// Permission is granted to anyone to use this software for any purpose,
|
|
15
|
+
// including commercial applications, and to alter it and redistribute it
|
|
16
|
+
// freely, subject to the following restrictions:
|
|
17
|
+
//
|
|
18
|
+
// 1. The origin of this software must not be misrepresented; you must not
|
|
19
|
+
// claim that you wrote the original software. If you use this software
|
|
20
|
+
// in a product, an acknowledgment in the product documentation would
|
|
21
|
+
// be appreciated but is not required.
|
|
22
|
+
//
|
|
23
|
+
// 2. Altered source versions must be plainly marked as such, and must not
|
|
24
|
+
// be misrepresented as being the original software.
|
|
25
|
+
//
|
|
26
|
+
// 3. This notice may not be removed or altered from any source
|
|
27
|
+
// distribution.
|
|
28
|
+
//
|
|
29
|
+
//========================================================================
|
|
30
|
+
|
|
31
|
+
#include "internal.h"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
/* Defines some GLX FSAA tokens if not yet defined */
|
|
35
|
+
#ifndef GLX_SAMPLE_BUFFERS
|
|
36
|
+
# define GLX_SAMPLE_BUFFERS 100000
|
|
37
|
+
#endif
|
|
38
|
+
#ifndef GLX_SAMPLES
|
|
39
|
+
# define GLX_SAMPLES 100001
|
|
40
|
+
#endif
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
/* KDE decoration values */
|
|
44
|
+
enum {
|
|
45
|
+
KDE_noDecoration = 0,
|
|
46
|
+
KDE_normalDecoration = 1,
|
|
47
|
+
KDE_tinyDecoration = 2,
|
|
48
|
+
KDE_noFocus = 256,
|
|
49
|
+
KDE_standaloneMenuBar = 512,
|
|
50
|
+
KDE_desktopIcon = 1024 ,
|
|
51
|
+
KDE_staysOnTop = 2048
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
//************************************************************************
|
|
56
|
+
//**** GLFW internal functions ****
|
|
57
|
+
//************************************************************************
|
|
58
|
+
|
|
59
|
+
//========================================================================
|
|
60
|
+
// _glfwWaitForMapNotify()
|
|
61
|
+
//========================================================================
|
|
62
|
+
|
|
63
|
+
Bool _glfwWaitForMapNotify( Display *d, XEvent *e, char *arg )
|
|
64
|
+
{
|
|
65
|
+
return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
//========================================================================
|
|
70
|
+
// _glfwWaitForUnmapNotify()
|
|
71
|
+
//========================================================================
|
|
72
|
+
|
|
73
|
+
Bool _glfwWaitForUnmapNotify( Display *d, XEvent *e, char *arg )
|
|
74
|
+
{
|
|
75
|
+
return (e->type == UnmapNotify) && (e->xmap.window == (Window)arg);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
//========================================================================
|
|
80
|
+
// _glfwDisableDecorations() - Turn off window decorations
|
|
81
|
+
// Based on xawdecode: src/wmhooks.c
|
|
82
|
+
//========================================================================
|
|
83
|
+
|
|
84
|
+
#define MWM_HINTS_DECORATIONS (1L << 1)
|
|
85
|
+
|
|
86
|
+
static void _glfwDisableDecorations( void )
|
|
87
|
+
{
|
|
88
|
+
int RemovedDecorations;
|
|
89
|
+
Atom HintAtom;
|
|
90
|
+
XSetWindowAttributes attributes;
|
|
91
|
+
|
|
92
|
+
RemovedDecorations = 0;
|
|
93
|
+
|
|
94
|
+
// First try to set MWM hints
|
|
95
|
+
HintAtom = XInternAtom( _glfwLibrary.Dpy, "_MOTIF_WM_HINTS", True );
|
|
96
|
+
if ( HintAtom != None )
|
|
97
|
+
{
|
|
98
|
+
struct {
|
|
99
|
+
unsigned long flags;
|
|
100
|
+
unsigned long functions;
|
|
101
|
+
unsigned long decorations;
|
|
102
|
+
long input_mode;
|
|
103
|
+
unsigned long status;
|
|
104
|
+
} MWMHints = { MWM_HINTS_DECORATIONS, 0, 0, 0, 0 };
|
|
105
|
+
|
|
106
|
+
XChangeProperty( _glfwLibrary.Dpy, _glfwWin.Win, HintAtom, HintAtom,
|
|
107
|
+
32, PropModeReplace, (unsigned char *)&MWMHints,
|
|
108
|
+
sizeof(MWMHints)/4 );
|
|
109
|
+
RemovedDecorations = 1;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Now try to set KWM hints
|
|
113
|
+
HintAtom = XInternAtom( _glfwLibrary.Dpy, "KWM_WIN_DECORATION", True );
|
|
114
|
+
if ( HintAtom != None )
|
|
115
|
+
{
|
|
116
|
+
long KWMHints = KDE_tinyDecoration;
|
|
117
|
+
|
|
118
|
+
XChangeProperty( _glfwLibrary.Dpy, _glfwWin.Win, HintAtom, HintAtom,
|
|
119
|
+
32, PropModeReplace, (unsigned char *)&KWMHints,
|
|
120
|
+
sizeof(KWMHints)/4 );
|
|
121
|
+
RemovedDecorations = 1;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Now try to set GNOME hints
|
|
125
|
+
HintAtom = XInternAtom(_glfwLibrary.Dpy, "_WIN_HINTS", True );
|
|
126
|
+
if ( HintAtom != None )
|
|
127
|
+
{
|
|
128
|
+
long GNOMEHints = 0;
|
|
129
|
+
|
|
130
|
+
XChangeProperty( _glfwLibrary.Dpy, _glfwWin.Win, HintAtom, HintAtom,
|
|
131
|
+
32, PropModeReplace, (unsigned char *)&GNOMEHints,
|
|
132
|
+
sizeof(GNOMEHints)/4 );
|
|
133
|
+
RemovedDecorations = 1;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Now try to set KDE NET_WM hints
|
|
137
|
+
HintAtom = XInternAtom( _glfwLibrary.Dpy, "_NET_WM_WINDOW_TYPE", True );
|
|
138
|
+
if ( HintAtom != None )
|
|
139
|
+
{
|
|
140
|
+
Atom NET_WMHints[2];
|
|
141
|
+
|
|
142
|
+
NET_WMHints[0] = XInternAtom( _glfwLibrary.Dpy, "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE", True );
|
|
143
|
+
/* define a fallback... */
|
|
144
|
+
NET_WMHints[1] = XInternAtom( _glfwLibrary.Dpy, "_NET_WM_WINDOW_TYPE_NORMAL", True );
|
|
145
|
+
|
|
146
|
+
XChangeProperty( _glfwLibrary.Dpy, _glfwWin.Win, HintAtom, XA_ATOM,
|
|
147
|
+
32, PropModeReplace, (unsigned char *)&NET_WMHints,
|
|
148
|
+
2 );
|
|
149
|
+
RemovedDecorations = 1;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Set ICCCM fullscreen WM hint
|
|
153
|
+
HintAtom = XInternAtom( _glfwLibrary.Dpy, "_NET_WM_STATE", True );
|
|
154
|
+
if ( HintAtom != None )
|
|
155
|
+
{
|
|
156
|
+
Atom NET_WMHints[1];
|
|
157
|
+
|
|
158
|
+
NET_WMHints[0] = XInternAtom( _glfwLibrary.Dpy, "_NET_WM_STATE_FULLSCREEN", True );
|
|
159
|
+
|
|
160
|
+
XChangeProperty( _glfwLibrary.Dpy, _glfwWin.Win, HintAtom, XA_ATOM,
|
|
161
|
+
32, PropModeReplace, (unsigned char *)&NET_WMHints, 1 );
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
// Did we sucessfully remove the window decorations?
|
|
166
|
+
if( RemovedDecorations )
|
|
167
|
+
{
|
|
168
|
+
// Finally set the transient hints
|
|
169
|
+
XSetTransientForHint( _glfwLibrary.Dpy, _glfwWin.Win, RootWindow(_glfwLibrary.Dpy, _glfwWin.Scrn) );
|
|
170
|
+
XUnmapWindow( _glfwLibrary.Dpy, _glfwWin.Win );
|
|
171
|
+
XMapWindow( _glfwLibrary.Dpy, _glfwWin.Win );
|
|
172
|
+
}
|
|
173
|
+
else
|
|
174
|
+
{
|
|
175
|
+
// The Butcher way of removing window decorations
|
|
176
|
+
attributes.override_redirect = True;
|
|
177
|
+
XChangeWindowAttributes( _glfwLibrary.Dpy, _glfwWin.Win,
|
|
178
|
+
CWOverrideRedirect, &attributes );
|
|
179
|
+
_glfwWin.OverrideRedirect = GL_TRUE;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
//========================================================================
|
|
185
|
+
// _glfwEnableDecorations() - Turn on window decorations
|
|
186
|
+
//========================================================================
|
|
187
|
+
|
|
188
|
+
static void _glfwEnableDecorations( void )
|
|
189
|
+
{
|
|
190
|
+
int ActivatedDecorations;
|
|
191
|
+
Atom HintAtom;
|
|
192
|
+
|
|
193
|
+
// If this is an override redirect window, skip it...
|
|
194
|
+
if( _glfwWin.OverrideRedirect )
|
|
195
|
+
{
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
ActivatedDecorations = 0;
|
|
200
|
+
|
|
201
|
+
// First try to unset MWM hints
|
|
202
|
+
HintAtom = XInternAtom( _glfwLibrary.Dpy, "_MOTIF_WM_HINTS", True );
|
|
203
|
+
if ( HintAtom != None )
|
|
204
|
+
{
|
|
205
|
+
XDeleteProperty( _glfwLibrary.Dpy, _glfwWin.Win, HintAtom );
|
|
206
|
+
ActivatedDecorations = 1;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Now try to unset KWM hints
|
|
210
|
+
HintAtom = XInternAtom( _glfwLibrary.Dpy, "KWM_WIN_DECORATION", True );
|
|
211
|
+
if ( HintAtom != None )
|
|
212
|
+
{
|
|
213
|
+
XDeleteProperty( _glfwLibrary.Dpy, _glfwWin.Win, HintAtom );
|
|
214
|
+
ActivatedDecorations = 1;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Now try to unset GNOME hints
|
|
218
|
+
HintAtom = XInternAtom( _glfwLibrary.Dpy, "_WIN_HINTS", True );
|
|
219
|
+
if ( HintAtom != None )
|
|
220
|
+
{
|
|
221
|
+
XDeleteProperty( _glfwLibrary.Dpy, _glfwWin.Win, HintAtom );
|
|
222
|
+
ActivatedDecorations = 1;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Now try to unset NET_WM hints
|
|
226
|
+
HintAtom = XInternAtom( _glfwLibrary.Dpy, "_NET_WM_WINDOW_TYPE", True );
|
|
227
|
+
if ( HintAtom != None )
|
|
228
|
+
{
|
|
229
|
+
Atom NET_WMHints = XInternAtom( _glfwLibrary.Dpy, "_NET_WM_WINDOW_TYPE_NORMAL", True);
|
|
230
|
+
if( NET_WMHints != None )
|
|
231
|
+
{
|
|
232
|
+
XChangeProperty( _glfwLibrary.Dpy, _glfwWin.Win,
|
|
233
|
+
HintAtom, XA_ATOM, 32, PropModeReplace,
|
|
234
|
+
(unsigned char *)&NET_WMHints, 1 );
|
|
235
|
+
ActivatedDecorations = 1;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Finally unset the transient hints if necessary
|
|
240
|
+
if( ActivatedDecorations )
|
|
241
|
+
{
|
|
242
|
+
// NOTE: Does this work?
|
|
243
|
+
XSetTransientForHint( _glfwLibrary.Dpy, _glfwWin.Win, None);
|
|
244
|
+
XUnmapWindow( _glfwLibrary.Dpy, _glfwWin.Win );
|
|
245
|
+
XMapWindow( _glfwLibrary.Dpy, _glfwWin.Win );
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
//========================================================================
|
|
251
|
+
// _glfwChooseVisual() - We do our own function here, since
|
|
252
|
+
// glXChooseVisual does not behave as we want it to (not according to the
|
|
253
|
+
// GLFW specs)
|
|
254
|
+
//========================================================================
|
|
255
|
+
|
|
256
|
+
XVisualInfo * _glfwChooseVisual( Display *Dpy, int Screen, int r, int g,
|
|
257
|
+
int b, int a, int d, int s, int ar, int ag, int ab, int aa, int aux,
|
|
258
|
+
int fsaa, int stereo)
|
|
259
|
+
{
|
|
260
|
+
XVisualInfo *VI, *VI_list, VI_tmp;
|
|
261
|
+
int nitems_return, i;
|
|
262
|
+
int vi_gl, vi_rgba, vi_double, vi_stereo;
|
|
263
|
+
int vi_r, vi_g, vi_b, vi_a, vi_d, vi_s, vi_ar, vi_ag, vi_ab, vi_aa;
|
|
264
|
+
int vi_aux;
|
|
265
|
+
int color, accum, vi_accum;
|
|
266
|
+
int missing, color_diff, extra_diff;
|
|
267
|
+
int best_vis, best_missing, best_color_diff, best_extra_diff;
|
|
268
|
+
int samples, samplebuffers, vi_samples, vi_samplebuffers;
|
|
269
|
+
|
|
270
|
+
// Get list of visuals for this screen & display
|
|
271
|
+
VI_tmp.screen = Screen;
|
|
272
|
+
VI_list = XGetVisualInfo( Dpy, VisualScreenMask, &VI_tmp,
|
|
273
|
+
&nitems_return );
|
|
274
|
+
if( VI_list == NULL )
|
|
275
|
+
{
|
|
276
|
+
return NULL;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Pick some prefered color depth if the user did not request a
|
|
280
|
+
// specific depth (note: if the user did not request a specific color
|
|
281
|
+
// depth, this will not be a driving demand, it's only here to avoid
|
|
282
|
+
// selection randomness)
|
|
283
|
+
color = (r > 0 || g > 0 || b > 0);
|
|
284
|
+
if( !color )
|
|
285
|
+
{
|
|
286
|
+
r = g = b = 8;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Make sure that stereo is 1 or 0
|
|
290
|
+
stereo = stereo ? 1 : 0;
|
|
291
|
+
|
|
292
|
+
// Convenience pre-calculation
|
|
293
|
+
accum = (ar > 0 || ag > 0 || ab > 0 || aa > 0);
|
|
294
|
+
|
|
295
|
+
samples = fsaa;
|
|
296
|
+
samplebuffers = (fsaa > 0) ? 1 : 0;
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
// Loop through list of visuals to find best match
|
|
301
|
+
best_vis = -1;
|
|
302
|
+
best_missing = 0x7fffffff;
|
|
303
|
+
best_color_diff = 0x7fffffff;
|
|
304
|
+
best_extra_diff = 0x7fffffff;
|
|
305
|
+
for( i = 0; i < nitems_return; i ++ )
|
|
306
|
+
{
|
|
307
|
+
// We want GL, RGBA & DOUBLEBUFFER, and NOT STEREO / STEREO
|
|
308
|
+
glXGetConfig( Dpy, &VI_list[i], GLX_USE_GL, &vi_gl );
|
|
309
|
+
glXGetConfig( Dpy, &VI_list[i], GLX_RGBA, &vi_rgba );
|
|
310
|
+
glXGetConfig( Dpy, &VI_list[i], GLX_DOUBLEBUFFER, &vi_double );
|
|
311
|
+
glXGetConfig( Dpy, &VI_list[i], GLX_STEREO, &vi_stereo );
|
|
312
|
+
vi_stereo = vi_stereo ? 1 : 0;
|
|
313
|
+
if( vi_gl && vi_rgba && vi_double && (vi_stereo == stereo) )
|
|
314
|
+
{
|
|
315
|
+
// Get visual color parameters
|
|
316
|
+
glXGetConfig( Dpy, &VI_list[i], GLX_RED_SIZE, &vi_r );
|
|
317
|
+
glXGetConfig( Dpy, &VI_list[i], GLX_GREEN_SIZE, &vi_g );
|
|
318
|
+
glXGetConfig( Dpy, &VI_list[i], GLX_BLUE_SIZE, &vi_b );
|
|
319
|
+
|
|
320
|
+
// Get visual "extra" parameters
|
|
321
|
+
glXGetConfig( Dpy, &VI_list[i], GLX_ALPHA_SIZE, &vi_a );
|
|
322
|
+
glXGetConfig( Dpy, &VI_list[i], GLX_DEPTH_SIZE, &vi_d );
|
|
323
|
+
glXGetConfig( Dpy, &VI_list[i], GLX_STENCIL_SIZE, &vi_s );
|
|
324
|
+
glXGetConfig( Dpy, &VI_list[i], GLX_ACCUM_RED_SIZE, &vi_ar );
|
|
325
|
+
glXGetConfig( Dpy, &VI_list[i], GLX_ACCUM_GREEN_SIZE, &vi_ag );
|
|
326
|
+
glXGetConfig( Dpy, &VI_list[i], GLX_ACCUM_BLUE_SIZE, &vi_ab );
|
|
327
|
+
glXGetConfig( Dpy, &VI_list[i], GLX_ACCUM_ALPHA_SIZE, &vi_aa );
|
|
328
|
+
glXGetConfig( Dpy, &VI_list[i], GLX_AUX_BUFFERS, &vi_aux );
|
|
329
|
+
glXGetConfig( Dpy, &VI_list[i], GLX_SAMPLE_BUFFERS, &vi_samplebuffers );
|
|
330
|
+
glXGetConfig( Dpy, &VI_list[i], GLX_SAMPLES, &vi_samples );
|
|
331
|
+
|
|
332
|
+
vi_accum = (vi_ar > 0 || vi_ag > 0 || vi_ab > 0 || vi_aa > 0);
|
|
333
|
+
|
|
334
|
+
// Check how many buffers are missing
|
|
335
|
+
missing = 0;
|
|
336
|
+
if( a > 0 && vi_a == 0 ) missing ++;
|
|
337
|
+
if( d > 0 && vi_d == 0 ) missing ++;
|
|
338
|
+
if( s > 0 && vi_s == 0 ) missing ++;
|
|
339
|
+
if( accum && !vi_accum ) missing ++;
|
|
340
|
+
if( aux > 0 && vi_aux == 0 ) missing ++;
|
|
341
|
+
if( samplebuffers > 0 && vi_samplebuffers == 0 ) missing ++;
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
// Calculate color diff
|
|
345
|
+
color_diff = (r - vi_r) * (r - vi_r) +
|
|
346
|
+
(g - vi_g) * (g - vi_g) +
|
|
347
|
+
(b - vi_b) * (b - vi_b);
|
|
348
|
+
|
|
349
|
+
// Calculate "extra" diff
|
|
350
|
+
extra_diff = 0;
|
|
351
|
+
if( a > 0 )
|
|
352
|
+
{
|
|
353
|
+
extra_diff += (a - vi_a) * (a - vi_a);
|
|
354
|
+
}
|
|
355
|
+
if( d > 0 )
|
|
356
|
+
{
|
|
357
|
+
extra_diff += (d - vi_d) * (d - vi_d);
|
|
358
|
+
}
|
|
359
|
+
if( s > 0 )
|
|
360
|
+
{
|
|
361
|
+
extra_diff += (s - vi_s) * (s - vi_s);
|
|
362
|
+
}
|
|
363
|
+
if( accum )
|
|
364
|
+
{
|
|
365
|
+
extra_diff += (ar - vi_ar) * (ar - vi_ar) +
|
|
366
|
+
(ag - vi_ag) * (ag - vi_ag) +
|
|
367
|
+
(ab - vi_ab) * (ab - vi_ab) +
|
|
368
|
+
(aa - vi_aa) * (aa - vi_aa);
|
|
369
|
+
}
|
|
370
|
+
if( aux > 0 )
|
|
371
|
+
{
|
|
372
|
+
extra_diff += (aux - vi_aux) * (aux - vi_aux);
|
|
373
|
+
}
|
|
374
|
+
if( samples > 0 )
|
|
375
|
+
{
|
|
376
|
+
extra_diff += (samples - vi_samples) * (samples - vi_samples);
|
|
377
|
+
|
|
378
|
+
}
|
|
379
|
+
// Check if this is a better match. We implement some
|
|
380
|
+
// complicated rules, by prioritizing in this order:
|
|
381
|
+
// 1) Visuals with the least number of missing buffers always
|
|
382
|
+
// have priority
|
|
383
|
+
// 2a) If (r,g,b)!=(0,0,0), color depth has priority over
|
|
384
|
+
// other buffers
|
|
385
|
+
// 2b) If (r,g,b)==(0,0,0), other buffers have priority over
|
|
386
|
+
// color depth
|
|
387
|
+
if( missing < best_missing )
|
|
388
|
+
{
|
|
389
|
+
best_vis = i;
|
|
390
|
+
}
|
|
391
|
+
else if( missing == best_missing )
|
|
392
|
+
{
|
|
393
|
+
if( color )
|
|
394
|
+
{
|
|
395
|
+
if( (color_diff < best_color_diff) ||
|
|
396
|
+
(color_diff == best_color_diff &&
|
|
397
|
+
extra_diff < best_extra_diff) )
|
|
398
|
+
{
|
|
399
|
+
best_vis = i;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
else
|
|
403
|
+
{
|
|
404
|
+
if( (extra_diff < best_extra_diff) ||
|
|
405
|
+
(extra_diff == best_extra_diff &&
|
|
406
|
+
color_diff < best_color_diff) )
|
|
407
|
+
{
|
|
408
|
+
best_vis = i;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
if( best_vis == i )
|
|
413
|
+
{
|
|
414
|
+
best_missing = missing;
|
|
415
|
+
best_color_diff = color_diff;
|
|
416
|
+
best_extra_diff = extra_diff;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Copy best visual to a visual to return
|
|
422
|
+
if( best_vis >= 0 )
|
|
423
|
+
{
|
|
424
|
+
VI = XGetVisualInfo( Dpy, VisualIDMask, &VI_list[ best_vis ],
|
|
425
|
+
&nitems_return );
|
|
426
|
+
}
|
|
427
|
+
else
|
|
428
|
+
{
|
|
429
|
+
VI = NULL;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Free visuals list
|
|
433
|
+
XFree( VI_list );
|
|
434
|
+
|
|
435
|
+
return VI;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
//========================================================================
|
|
440
|
+
// _glfwTranslateKey() - Translates an X Window key to internal coding
|
|
441
|
+
//========================================================================
|
|
442
|
+
|
|
443
|
+
static int _glfwTranslateKey( int keycode )
|
|
444
|
+
{
|
|
445
|
+
KeySym key, key_lc, key_uc;
|
|
446
|
+
|
|
447
|
+
// Try secondary keysym, for numeric keypad keys
|
|
448
|
+
// Note: This way we always force "NumLock = ON", which at least
|
|
449
|
+
// enables GLFW users to detect numeric keypad keys
|
|
450
|
+
key = XKeycodeToKeysym( _glfwLibrary.Dpy, keycode, 1 );
|
|
451
|
+
switch( key )
|
|
452
|
+
{
|
|
453
|
+
// Numeric keypad
|
|
454
|
+
case XK_KP_0: return GLFW_KEY_KP_0;
|
|
455
|
+
case XK_KP_1: return GLFW_KEY_KP_1;
|
|
456
|
+
case XK_KP_2: return GLFW_KEY_KP_2;
|
|
457
|
+
case XK_KP_3: return GLFW_KEY_KP_3;
|
|
458
|
+
case XK_KP_4: return GLFW_KEY_KP_4;
|
|
459
|
+
case XK_KP_5: return GLFW_KEY_KP_5;
|
|
460
|
+
case XK_KP_6: return GLFW_KEY_KP_6;
|
|
461
|
+
case XK_KP_7: return GLFW_KEY_KP_7;
|
|
462
|
+
case XK_KP_8: return GLFW_KEY_KP_8;
|
|
463
|
+
case XK_KP_9: return GLFW_KEY_KP_9;
|
|
464
|
+
case XK_KP_Separator:
|
|
465
|
+
case XK_KP_Decimal: return GLFW_KEY_KP_DECIMAL;
|
|
466
|
+
case XK_KP_Equal: return GLFW_KEY_KP_EQUAL;
|
|
467
|
+
case XK_KP_Enter: return GLFW_KEY_KP_ENTER;
|
|
468
|
+
default: break;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// Now try pimary keysym
|
|
472
|
+
key = XKeycodeToKeysym( _glfwLibrary.Dpy, keycode, 0 );
|
|
473
|
+
switch( key )
|
|
474
|
+
{
|
|
475
|
+
// Special keys (non character keys)
|
|
476
|
+
case XK_Escape: return GLFW_KEY_ESC;
|
|
477
|
+
case XK_Tab: return GLFW_KEY_TAB;
|
|
478
|
+
case XK_Shift_L: return GLFW_KEY_LSHIFT;
|
|
479
|
+
case XK_Shift_R: return GLFW_KEY_RSHIFT;
|
|
480
|
+
case XK_Control_L: return GLFW_KEY_LCTRL;
|
|
481
|
+
case XK_Control_R: return GLFW_KEY_RCTRL;
|
|
482
|
+
case XK_Meta_L:
|
|
483
|
+
case XK_Alt_L: return GLFW_KEY_LALT;
|
|
484
|
+
case XK_Mode_switch: // Mapped to Alt_R on many keyboards
|
|
485
|
+
case XK_Meta_R:
|
|
486
|
+
case XK_Alt_R: return GLFW_KEY_RALT;
|
|
487
|
+
case XK_KP_Delete:
|
|
488
|
+
case XK_Delete: return GLFW_KEY_DEL;
|
|
489
|
+
case XK_BackSpace: return GLFW_KEY_BACKSPACE;
|
|
490
|
+
case XK_Return: return GLFW_KEY_ENTER;
|
|
491
|
+
case XK_KP_Home:
|
|
492
|
+
case XK_Home: return GLFW_KEY_HOME;
|
|
493
|
+
case XK_KP_End:
|
|
494
|
+
case XK_End: return GLFW_KEY_END;
|
|
495
|
+
case XK_KP_Page_Up:
|
|
496
|
+
case XK_Page_Up: return GLFW_KEY_PAGEUP;
|
|
497
|
+
case XK_KP_Page_Down:
|
|
498
|
+
case XK_Page_Down: return GLFW_KEY_PAGEDOWN;
|
|
499
|
+
case XK_KP_Insert:
|
|
500
|
+
case XK_Insert: return GLFW_KEY_INSERT;
|
|
501
|
+
case XK_KP_Left:
|
|
502
|
+
case XK_Left: return GLFW_KEY_LEFT;
|
|
503
|
+
case XK_KP_Right:
|
|
504
|
+
case XK_Right: return GLFW_KEY_RIGHT;
|
|
505
|
+
case XK_KP_Down:
|
|
506
|
+
case XK_Down: return GLFW_KEY_DOWN;
|
|
507
|
+
case XK_KP_Up:
|
|
508
|
+
case XK_Up: return GLFW_KEY_UP;
|
|
509
|
+
case XK_F1: return GLFW_KEY_F1;
|
|
510
|
+
case XK_F2: return GLFW_KEY_F2;
|
|
511
|
+
case XK_F3: return GLFW_KEY_F3;
|
|
512
|
+
case XK_F4: return GLFW_KEY_F4;
|
|
513
|
+
case XK_F5: return GLFW_KEY_F5;
|
|
514
|
+
case XK_F6: return GLFW_KEY_F6;
|
|
515
|
+
case XK_F7: return GLFW_KEY_F7;
|
|
516
|
+
case XK_F8: return GLFW_KEY_F8;
|
|
517
|
+
case XK_F9: return GLFW_KEY_F9;
|
|
518
|
+
case XK_F10: return GLFW_KEY_F10;
|
|
519
|
+
case XK_F11: return GLFW_KEY_F11;
|
|
520
|
+
case XK_F12: return GLFW_KEY_F12;
|
|
521
|
+
case XK_F13: return GLFW_KEY_F13;
|
|
522
|
+
case XK_F14: return GLFW_KEY_F14;
|
|
523
|
+
case XK_F15: return GLFW_KEY_F15;
|
|
524
|
+
case XK_F16: return GLFW_KEY_F16;
|
|
525
|
+
case XK_F17: return GLFW_KEY_F17;
|
|
526
|
+
case XK_F18: return GLFW_KEY_F18;
|
|
527
|
+
case XK_F19: return GLFW_KEY_F19;
|
|
528
|
+
case XK_F20: return GLFW_KEY_F20;
|
|
529
|
+
case XK_F21: return GLFW_KEY_F21;
|
|
530
|
+
case XK_F22: return GLFW_KEY_F22;
|
|
531
|
+
case XK_F23: return GLFW_KEY_F23;
|
|
532
|
+
case XK_F24: return GLFW_KEY_F24;
|
|
533
|
+
case XK_F25: return GLFW_KEY_F25;
|
|
534
|
+
|
|
535
|
+
// Numeric keypad (should have been detected in secondary keysym!)
|
|
536
|
+
case XK_KP_Divide: return GLFW_KEY_KP_DIVIDE;
|
|
537
|
+
case XK_KP_Multiply: return GLFW_KEY_KP_MULTIPLY;
|
|
538
|
+
case XK_KP_Subtract: return GLFW_KEY_KP_SUBTRACT;
|
|
539
|
+
case XK_KP_Add: return GLFW_KEY_KP_ADD;
|
|
540
|
+
case XK_KP_Equal: return GLFW_KEY_KP_EQUAL;
|
|
541
|
+
case XK_KP_Enter: return GLFW_KEY_KP_ENTER;
|
|
542
|
+
|
|
543
|
+
// The rest (should be printable keys)
|
|
544
|
+
default:
|
|
545
|
+
// Make uppercase
|
|
546
|
+
XConvertCase( key, &key_lc, &key_uc );
|
|
547
|
+
key = key_uc;
|
|
548
|
+
|
|
549
|
+
// Valid ISO 8859-1 character?
|
|
550
|
+
if( (key >= 32 && key <= 126) ||
|
|
551
|
+
(key >= 160 && key <= 255) )
|
|
552
|
+
{
|
|
553
|
+
return (int) key;
|
|
554
|
+
}
|
|
555
|
+
return GLFW_KEY_UNKNOWN;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
//========================================================================
|
|
561
|
+
// _glfwTranslateChar() - Translates an X Window event to Unicode
|
|
562
|
+
//========================================================================
|
|
563
|
+
|
|
564
|
+
static int _glfwTranslateChar( XKeyEvent *event )
|
|
565
|
+
{
|
|
566
|
+
KeySym keysym;
|
|
567
|
+
|
|
568
|
+
// Get X11 keysym
|
|
569
|
+
XLookupString( event, NULL, 0, &keysym, NULL );
|
|
570
|
+
|
|
571
|
+
// Convert to Unicode (see x11_keysym2unicode.c)
|
|
572
|
+
return (int) _glfwKeySym2Unicode( keysym );
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
//========================================================================
|
|
578
|
+
// Get next X event (called by glfwPollEvents)
|
|
579
|
+
//========================================================================
|
|
580
|
+
|
|
581
|
+
static int _glfwGetNextEvent( void )
|
|
582
|
+
{
|
|
583
|
+
XEvent event, next_event;
|
|
584
|
+
|
|
585
|
+
// Pull next event from event queue
|
|
586
|
+
XNextEvent( _glfwLibrary.Dpy, &event );
|
|
587
|
+
|
|
588
|
+
// Handle certain window messages
|
|
589
|
+
switch( event.type )
|
|
590
|
+
{
|
|
591
|
+
// Is a key being pressed?
|
|
592
|
+
case KeyPress:
|
|
593
|
+
{
|
|
594
|
+
// Translate and report key press
|
|
595
|
+
_glfwInputKey( _glfwTranslateKey( event.xkey.keycode ), GLFW_PRESS );
|
|
596
|
+
|
|
597
|
+
// Translate and report character input
|
|
598
|
+
if( _glfwWin.CharCallback )
|
|
599
|
+
{
|
|
600
|
+
_glfwInputChar( _glfwTranslateChar( &event.xkey ), GLFW_PRESS );
|
|
601
|
+
}
|
|
602
|
+
break;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// Is a key being released?
|
|
606
|
+
case KeyRelease:
|
|
607
|
+
{
|
|
608
|
+
// Do not report key releases for key repeats. For key repeats
|
|
609
|
+
// we will get KeyRelease/KeyPress pairs with identical time
|
|
610
|
+
// stamps. User selected key repeat filtering is handled in
|
|
611
|
+
// _glfwInputKey()/_glfwInputChar().
|
|
612
|
+
if( XEventsQueued( _glfwLibrary.Dpy, QueuedAfterReading ) )
|
|
613
|
+
{
|
|
614
|
+
XPeekEvent( _glfwLibrary.Dpy, &next_event );
|
|
615
|
+
if( next_event.type == KeyPress &&
|
|
616
|
+
next_event.xkey.window == event.xkey.window &&
|
|
617
|
+
next_event.xkey.keycode == event.xkey.keycode &&
|
|
618
|
+
next_event.xkey.time == event.xkey.time )
|
|
619
|
+
{
|
|
620
|
+
// Do not report anything for this event
|
|
621
|
+
break;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// Translate and report key release
|
|
626
|
+
_glfwInputKey( _glfwTranslateKey( event.xkey.keycode ), GLFW_RELEASE );
|
|
627
|
+
|
|
628
|
+
// Translate and report character input
|
|
629
|
+
if( _glfwWin.CharCallback )
|
|
630
|
+
{
|
|
631
|
+
_glfwInputChar( _glfwTranslateChar( &event.xkey ), GLFW_RELEASE );
|
|
632
|
+
}
|
|
633
|
+
break;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// Were any of the mouse-buttons pressed?
|
|
637
|
+
case ButtonPress:
|
|
638
|
+
{
|
|
639
|
+
if( event.xbutton.button == Button1 )
|
|
640
|
+
{
|
|
641
|
+
_glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS );
|
|
642
|
+
}
|
|
643
|
+
else if( event.xbutton.button == Button2 )
|
|
644
|
+
{
|
|
645
|
+
_glfwInputMouseClick( GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS );
|
|
646
|
+
}
|
|
647
|
+
else if( event.xbutton.button == Button3 )
|
|
648
|
+
{
|
|
649
|
+
_glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS );
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// XFree86 3.3.2 and later translates mouse wheel up/down into
|
|
653
|
+
// mouse button 4 & 5 presses
|
|
654
|
+
else if( event.xbutton.button == Button4 )
|
|
655
|
+
{
|
|
656
|
+
_glfwInput.WheelPos++; // To verify: is this up or down?
|
|
657
|
+
if( _glfwWin.MouseWheelCallback )
|
|
658
|
+
{
|
|
659
|
+
_glfwWin.MouseWheelCallback( _glfwInput.WheelPos );
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
else if( event.xbutton.button == Button5 )
|
|
663
|
+
{
|
|
664
|
+
_glfwInput.WheelPos--;
|
|
665
|
+
if( _glfwWin.MouseWheelCallback )
|
|
666
|
+
{
|
|
667
|
+
_glfwWin.MouseWheelCallback( _glfwInput.WheelPos );
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
break;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// Were any of the mouse-buttons released?
|
|
674
|
+
case ButtonRelease:
|
|
675
|
+
{
|
|
676
|
+
if( event.xbutton.button == Button1 )
|
|
677
|
+
{
|
|
678
|
+
_glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT,
|
|
679
|
+
GLFW_RELEASE );
|
|
680
|
+
}
|
|
681
|
+
else if( event.xbutton.button == Button2 )
|
|
682
|
+
{
|
|
683
|
+
_glfwInputMouseClick( GLFW_MOUSE_BUTTON_MIDDLE,
|
|
684
|
+
GLFW_RELEASE );
|
|
685
|
+
}
|
|
686
|
+
else if( event.xbutton.button == Button3 )
|
|
687
|
+
{
|
|
688
|
+
_glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT,
|
|
689
|
+
GLFW_RELEASE );
|
|
690
|
+
}
|
|
691
|
+
break;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// Was the mouse moved?
|
|
695
|
+
case MotionNotify:
|
|
696
|
+
{
|
|
697
|
+
if( event.xmotion.x != _glfwInput.CursorPosX ||
|
|
698
|
+
event.xmotion.y != _glfwInput.CursorPosY )
|
|
699
|
+
{
|
|
700
|
+
if( _glfwWin.MouseLock )
|
|
701
|
+
{
|
|
702
|
+
_glfwInput.MousePosX += event.xmotion.x -
|
|
703
|
+
_glfwInput.CursorPosX;
|
|
704
|
+
_glfwInput.MousePosY += event.xmotion.y -
|
|
705
|
+
_glfwInput.CursorPosY;
|
|
706
|
+
}
|
|
707
|
+
else
|
|
708
|
+
{
|
|
709
|
+
_glfwInput.MousePosX = event.xmotion.x;
|
|
710
|
+
_glfwInput.MousePosY = event.xmotion.y;
|
|
711
|
+
}
|
|
712
|
+
_glfwInput.CursorPosX = event.xmotion.x;
|
|
713
|
+
_glfwInput.CursorPosY = event.xmotion.y;
|
|
714
|
+
_glfwInput.MouseMoved = GL_TRUE;
|
|
715
|
+
|
|
716
|
+
// Call user callback function
|
|
717
|
+
if( _glfwWin.MousePosCallback )
|
|
718
|
+
{
|
|
719
|
+
_glfwWin.MousePosCallback( _glfwInput.MousePosX,
|
|
720
|
+
_glfwInput.MousePosY );
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
break;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
// Was the window resized?
|
|
727
|
+
case ConfigureNotify:
|
|
728
|
+
{
|
|
729
|
+
if( event.xconfigure.width != _glfwWin.Width ||
|
|
730
|
+
event.xconfigure.height != _glfwWin.Height )
|
|
731
|
+
{
|
|
732
|
+
_glfwWin.Width = event.xconfigure.width;
|
|
733
|
+
_glfwWin.Height = event.xconfigure.height;
|
|
734
|
+
if( _glfwWin.WindowSizeCallback )
|
|
735
|
+
{
|
|
736
|
+
_glfwWin.WindowSizeCallback( _glfwWin.Width,
|
|
737
|
+
_glfwWin.Height );
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
break;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
// Was the window closed by the window manager?
|
|
744
|
+
case ClientMessage:
|
|
745
|
+
{
|
|
746
|
+
if( (Atom) event.xclient.data.l[ 0 ] == _glfwWin.WMDeleteWindow )
|
|
747
|
+
{
|
|
748
|
+
return GL_TRUE;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
if( (Atom) event.xclient.data.l[ 0 ] == _glfwWin.WMPing )
|
|
752
|
+
{
|
|
753
|
+
XSendEvent( _glfwLibrary.Dpy,
|
|
754
|
+
RootWindow( _glfwLibrary.Dpy, _glfwWin.VI->screen ),
|
|
755
|
+
False, SubstructureNotifyMask | SubstructureRedirectMask, &event );
|
|
756
|
+
}
|
|
757
|
+
break;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
// Was the window mapped (un-iconified)?
|
|
761
|
+
case MapNotify:
|
|
762
|
+
_glfwWin.MapNotifyCount++;
|
|
763
|
+
break;
|
|
764
|
+
|
|
765
|
+
// Was the window unmapped (iconified)?
|
|
766
|
+
case UnmapNotify:
|
|
767
|
+
_glfwWin.MapNotifyCount--;
|
|
768
|
+
break;
|
|
769
|
+
|
|
770
|
+
// Was the window activated?
|
|
771
|
+
case FocusIn:
|
|
772
|
+
_glfwWin.FocusInCount++;
|
|
773
|
+
break;
|
|
774
|
+
|
|
775
|
+
// Was the window de-activated?
|
|
776
|
+
case FocusOut:
|
|
777
|
+
_glfwWin.FocusInCount--;
|
|
778
|
+
break;
|
|
779
|
+
|
|
780
|
+
// Was the window contents damaged?
|
|
781
|
+
case Expose:
|
|
782
|
+
{
|
|
783
|
+
// Call user callback function
|
|
784
|
+
if( _glfwWin.WindowRefreshCallback )
|
|
785
|
+
{
|
|
786
|
+
_glfwWin.WindowRefreshCallback();
|
|
787
|
+
}
|
|
788
|
+
break;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
// Was the window destroyed?
|
|
792
|
+
case DestroyNotify:
|
|
793
|
+
return GL_TRUE;
|
|
794
|
+
|
|
795
|
+
default:
|
|
796
|
+
{
|
|
797
|
+
#if defined( _GLFW_HAS_XRANDR )
|
|
798
|
+
switch( event.type - _glfwLibrary.XRandR.EventBase )
|
|
799
|
+
{
|
|
800
|
+
case RRScreenChangeNotify:
|
|
801
|
+
{
|
|
802
|
+
// Show XRandR that we really care
|
|
803
|
+
XRRUpdateConfiguration( &event );
|
|
804
|
+
break;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
#endif
|
|
808
|
+
break;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
// The window was not destroyed
|
|
813
|
+
return GL_FALSE;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
//========================================================================
|
|
818
|
+
// _glfwCreateNULLCursor() - Create a blank cursor (for locked mouse mode)
|
|
819
|
+
//========================================================================
|
|
820
|
+
|
|
821
|
+
Cursor _glfwCreateNULLCursor( Display *display, Window root )
|
|
822
|
+
{
|
|
823
|
+
Pixmap cursormask;
|
|
824
|
+
XGCValues xgc;
|
|
825
|
+
GC gc;
|
|
826
|
+
XColor col;
|
|
827
|
+
Cursor cursor;
|
|
828
|
+
|
|
829
|
+
cursormask = XCreatePixmap( display, root, 1, 1, 1 );
|
|
830
|
+
xgc.function = GXclear;
|
|
831
|
+
gc = XCreateGC( display, cursormask, GCFunction, &xgc );
|
|
832
|
+
XFillRectangle( display, cursormask, gc, 0, 0, 1, 1 );
|
|
833
|
+
col.pixel = 0;
|
|
834
|
+
col.red = 0;
|
|
835
|
+
col.flags = 4;
|
|
836
|
+
cursor = XCreatePixmapCursor( display, cursormask, cursormask,
|
|
837
|
+
&col,&col, 0,0 );
|
|
838
|
+
XFreePixmap( display, cursormask );
|
|
839
|
+
XFreeGC( display, gc );
|
|
840
|
+
|
|
841
|
+
return cursor;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
|
|
845
|
+
//========================================================================
|
|
846
|
+
// _glfwInitGLXExtensions() - Initialize GLX-specific extensions
|
|
847
|
+
//========================================================================
|
|
848
|
+
|
|
849
|
+
static void _glfwInitGLXExtensions( void )
|
|
850
|
+
{
|
|
851
|
+
int has_swap_control;
|
|
852
|
+
|
|
853
|
+
// Initialize OpenGL extension: GLX_SGI_swap_control
|
|
854
|
+
has_swap_control = _glfwPlatformExtensionSupported(
|
|
855
|
+
"GLX_SGI_swap_control"
|
|
856
|
+
);
|
|
857
|
+
|
|
858
|
+
if( has_swap_control )
|
|
859
|
+
{
|
|
860
|
+
_glfwWin.SwapInterval = (GLXSWAPINTERVALSGI_T)
|
|
861
|
+
_glfw_glXGetProcAddress( (GLubyte*) "glXSwapIntervalSGI" );
|
|
862
|
+
}
|
|
863
|
+
else
|
|
864
|
+
{
|
|
865
|
+
_glfwWin.SwapInterval = NULL;
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
|
|
870
|
+
|
|
871
|
+
//************************************************************************
|
|
872
|
+
//**** Platform implementation functions ****
|
|
873
|
+
//************************************************************************
|
|
874
|
+
|
|
875
|
+
//========================================================================
|
|
876
|
+
// _glfwPlatformOpenWindow() - Here is where the window is created, and
|
|
877
|
+
// the OpenGL rendering context is created
|
|
878
|
+
//========================================================================
|
|
879
|
+
|
|
880
|
+
int _glfwPlatformOpenWindow( int width, int height, int redbits,
|
|
881
|
+
int greenbits, int bluebits, int alphabits, int depthbits,
|
|
882
|
+
int stencilbits, int mode, _GLFWhints* hints )
|
|
883
|
+
{
|
|
884
|
+
Colormap cmap;
|
|
885
|
+
XSetWindowAttributes wa;
|
|
886
|
+
XEvent event;
|
|
887
|
+
Atom protocols[2];
|
|
888
|
+
|
|
889
|
+
// Clear platform specific GLFW window state
|
|
890
|
+
_glfwWin.VI = NULL;
|
|
891
|
+
_glfwWin.CX = (GLXContext)0;
|
|
892
|
+
_glfwWin.Win = (Window)0;
|
|
893
|
+
_glfwWin.Hints = NULL;
|
|
894
|
+
_glfwWin.PointerGrabbed = GL_FALSE;
|
|
895
|
+
_glfwWin.KeyboardGrabbed = GL_FALSE;
|
|
896
|
+
_glfwWin.OverrideRedirect = GL_FALSE;
|
|
897
|
+
_glfwWin.FS.ModeChanged = GL_FALSE;
|
|
898
|
+
_glfwWin.Saver.Changed = GL_FALSE;
|
|
899
|
+
_glfwWin.RefreshRate = hints->RefreshRate;
|
|
900
|
+
|
|
901
|
+
// Fullscreen & screen saver settings
|
|
902
|
+
// Check if GLX is supported on this display
|
|
903
|
+
if( !glXQueryExtension( _glfwLibrary.Dpy, NULL, NULL ) )
|
|
904
|
+
{
|
|
905
|
+
_glfwPlatformCloseWindow();
|
|
906
|
+
return GL_FALSE;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
// Get screen ID for this window
|
|
910
|
+
_glfwWin.Scrn = _glfwLibrary.DefaultScreen;
|
|
911
|
+
|
|
912
|
+
// Get an appropriate visual
|
|
913
|
+
_glfwWin.VI = _glfwChooseVisual( _glfwLibrary.Dpy,
|
|
914
|
+
_glfwWin.Scrn,
|
|
915
|
+
redbits, greenbits, bluebits,
|
|
916
|
+
alphabits, depthbits, stencilbits,
|
|
917
|
+
hints->AccumRedBits, hints->AccumGreenBits,
|
|
918
|
+
hints->AccumBlueBits, hints->AccumAlphaBits,
|
|
919
|
+
hints->AuxBuffers, hints->Samples, hints->Stereo );
|
|
920
|
+
if( _glfwWin.VI == NULL )
|
|
921
|
+
{
|
|
922
|
+
_glfwPlatformCloseWindow();
|
|
923
|
+
return GL_FALSE;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
// Create a GLX context
|
|
927
|
+
_glfwWin.CX = glXCreateContext( _glfwLibrary.Dpy, _glfwWin.VI, 0, GL_TRUE );
|
|
928
|
+
if( _glfwWin.CX == NULL )
|
|
929
|
+
{
|
|
930
|
+
_glfwPlatformCloseWindow();
|
|
931
|
+
return GL_FALSE;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
// Create a colormap
|
|
935
|
+
cmap = XCreateColormap( _glfwLibrary.Dpy, RootWindow( _glfwLibrary.Dpy,
|
|
936
|
+
_glfwWin.VI->screen), _glfwWin.VI->visual, AllocNone );
|
|
937
|
+
|
|
938
|
+
// Do we want fullscreen?
|
|
939
|
+
if( mode == GLFW_FULLSCREEN )
|
|
940
|
+
{
|
|
941
|
+
// Change video mode
|
|
942
|
+
_glfwSetVideoMode( _glfwWin.Scrn, &_glfwWin.Width,
|
|
943
|
+
&_glfwWin.Height, &_glfwWin.RefreshRate );
|
|
944
|
+
|
|
945
|
+
// Remember old screen saver settings
|
|
946
|
+
XGetScreenSaver( _glfwLibrary.Dpy, &_glfwWin.Saver.Timeout,
|
|
947
|
+
&_glfwWin.Saver.Interval, &_glfwWin.Saver.Blanking,
|
|
948
|
+
&_glfwWin.Saver.Exposure );
|
|
949
|
+
|
|
950
|
+
// Disable screen saver
|
|
951
|
+
XSetScreenSaver( _glfwLibrary.Dpy, 0, 0, DontPreferBlanking,
|
|
952
|
+
DefaultExposures );
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
// Attributes for window
|
|
956
|
+
wa.colormap = cmap;
|
|
957
|
+
wa.border_pixel = 0;
|
|
958
|
+
wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask |
|
|
959
|
+
PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
|
|
960
|
+
ExposureMask | FocusChangeMask | VisibilityChangeMask;
|
|
961
|
+
|
|
962
|
+
// Create a window
|
|
963
|
+
_glfwWin.Win = XCreateWindow(
|
|
964
|
+
_glfwLibrary.Dpy,
|
|
965
|
+
RootWindow( _glfwLibrary.Dpy, _glfwWin.VI->screen ),
|
|
966
|
+
0, 0, // Upper left corner
|
|
967
|
+
_glfwWin.Width, _glfwWin.Height, // Width, height
|
|
968
|
+
0, // Borderwidth
|
|
969
|
+
_glfwWin.VI->depth, // Depth
|
|
970
|
+
InputOutput,
|
|
971
|
+
_glfwWin.VI->visual,
|
|
972
|
+
CWBorderPixel | CWColormap | CWEventMask,
|
|
973
|
+
&wa
|
|
974
|
+
);
|
|
975
|
+
if( !_glfwWin.Win )
|
|
976
|
+
{
|
|
977
|
+
_glfwPlatformCloseWindow();
|
|
978
|
+
return GL_FALSE;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
// Get the delete window WM protocol atom
|
|
982
|
+
_glfwWin.WMDeleteWindow = XInternAtom( _glfwLibrary.Dpy,
|
|
983
|
+
"WM_DELETE_WINDOW",
|
|
984
|
+
False );
|
|
985
|
+
|
|
986
|
+
// Get the ping WM protocol atom
|
|
987
|
+
_glfwWin.WMPing = XInternAtom( _glfwLibrary.Dpy, "_NET_WM_PING", False );
|
|
988
|
+
|
|
989
|
+
protocols[0] = _glfwWin.WMDeleteWindow;
|
|
990
|
+
protocols[1] = _glfwWin.WMPing;
|
|
991
|
+
|
|
992
|
+
// Allow us to trap the Window Close protocol
|
|
993
|
+
XSetWMProtocols( _glfwLibrary.Dpy, _glfwWin.Win, protocols,
|
|
994
|
+
sizeof(protocols) / sizeof(Atom) );
|
|
995
|
+
|
|
996
|
+
// Remove window decorations for fullscreen windows
|
|
997
|
+
if( mode == GLFW_FULLSCREEN )
|
|
998
|
+
{
|
|
999
|
+
_glfwDisableDecorations();
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
_glfwWin.Hints = XAllocSizeHints();
|
|
1003
|
+
|
|
1004
|
+
if( hints->WindowNoResize )
|
|
1005
|
+
{
|
|
1006
|
+
_glfwWin.Hints->flags |= (PMinSize | PMaxSize);
|
|
1007
|
+
_glfwWin.Hints->min_width = _glfwWin.Hints->max_width = _glfwWin.Width;
|
|
1008
|
+
_glfwWin.Hints->min_height = _glfwWin.Hints->max_height = _glfwWin.Height;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
if( mode == GLFW_FULLSCREEN )
|
|
1012
|
+
{
|
|
1013
|
+
_glfwWin.Hints->flags |= PPosition;
|
|
1014
|
+
_glfwWin.Hints->x = 0;
|
|
1015
|
+
_glfwWin.Hints->y = 0;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
XSetWMNormalHints( _glfwLibrary.Dpy, _glfwWin.Win, _glfwWin.Hints );
|
|
1019
|
+
|
|
1020
|
+
// Map window
|
|
1021
|
+
XMapWindow( _glfwLibrary.Dpy, _glfwWin.Win );
|
|
1022
|
+
|
|
1023
|
+
// Wait for map notification
|
|
1024
|
+
XIfEvent( _glfwLibrary.Dpy, &event, _glfwWaitForMapNotify,
|
|
1025
|
+
(char*)_glfwWin.Win );
|
|
1026
|
+
|
|
1027
|
+
// Make sure that our window ends up on top of things
|
|
1028
|
+
XRaiseWindow( _glfwLibrary.Dpy, _glfwWin.Win );
|
|
1029
|
+
|
|
1030
|
+
// Fullscreen mode "post processing"
|
|
1031
|
+
if( mode == GLFW_FULLSCREEN )
|
|
1032
|
+
{
|
|
1033
|
+
#if defined( _GLFW_HAS_XRANDR )
|
|
1034
|
+
// Request screen change notifications
|
|
1035
|
+
if( _glfwLibrary.XRandR.Available )
|
|
1036
|
+
{
|
|
1037
|
+
XRRSelectInput( _glfwLibrary.Dpy,
|
|
1038
|
+
_glfwWin.Win,
|
|
1039
|
+
RRScreenChangeNotifyMask );
|
|
1040
|
+
}
|
|
1041
|
+
#endif
|
|
1042
|
+
|
|
1043
|
+
// Force window position/size (some WMs do their own window
|
|
1044
|
+
// geometry, which we want to override)
|
|
1045
|
+
XMoveWindow( _glfwLibrary.Dpy, _glfwWin.Win, 0, 0 );
|
|
1046
|
+
XResizeWindow( _glfwLibrary.Dpy, _glfwWin.Win, _glfwWin.Width,
|
|
1047
|
+
_glfwWin.Height );
|
|
1048
|
+
|
|
1049
|
+
// Grab keyboard
|
|
1050
|
+
if( XGrabKeyboard( _glfwLibrary.Dpy, _glfwWin.Win, True,
|
|
1051
|
+
GrabModeAsync, GrabModeAsync, CurrentTime ) ==
|
|
1052
|
+
GrabSuccess )
|
|
1053
|
+
{
|
|
1054
|
+
_glfwWin.KeyboardGrabbed = GL_TRUE;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
// Grab mouse cursor
|
|
1058
|
+
if( XGrabPointer( _glfwLibrary.Dpy, _glfwWin.Win, True,
|
|
1059
|
+
ButtonPressMask | ButtonReleaseMask |
|
|
1060
|
+
PointerMotionMask, GrabModeAsync, GrabModeAsync,
|
|
1061
|
+
_glfwWin.Win, None, CurrentTime ) ==
|
|
1062
|
+
GrabSuccess )
|
|
1063
|
+
{
|
|
1064
|
+
_glfwWin.PointerGrabbed = GL_TRUE;
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
// Try to get window inside viewport (for virtual displays) by
|
|
1068
|
+
// moving the mouse cursor to the upper left corner (and then to
|
|
1069
|
+
// the center) - this works for XFree86
|
|
1070
|
+
XWarpPointer( _glfwLibrary.Dpy, None, _glfwWin.Win, 0,0,0,0, 0,0 );
|
|
1071
|
+
XWarpPointer( _glfwLibrary.Dpy, None, _glfwWin.Win, 0,0,0,0,
|
|
1072
|
+
_glfwWin.Width/2, _glfwWin.Height/2 );
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
// Set window & icon name
|
|
1076
|
+
_glfwPlatformSetWindowTitle( "GLFW Window" );
|
|
1077
|
+
|
|
1078
|
+
// Connect the context to the window
|
|
1079
|
+
glXMakeCurrent( _glfwLibrary.Dpy, _glfwWin.Win, _glfwWin.CX );
|
|
1080
|
+
|
|
1081
|
+
// Start by clearing the front buffer to black (avoid ugly desktop
|
|
1082
|
+
// remains in our OpenGL window)
|
|
1083
|
+
glClear( GL_COLOR_BUFFER_BIT );
|
|
1084
|
+
glXSwapBuffers( _glfwLibrary.Dpy, _glfwWin.Win );
|
|
1085
|
+
|
|
1086
|
+
// Initialize GLX-specific OpenGL extensions
|
|
1087
|
+
_glfwInitGLXExtensions();
|
|
1088
|
+
|
|
1089
|
+
return GL_TRUE;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
|
|
1093
|
+
//========================================================================
|
|
1094
|
+
// Properly kill the window/video display
|
|
1095
|
+
//========================================================================
|
|
1096
|
+
|
|
1097
|
+
void _glfwPlatformCloseWindow( void )
|
|
1098
|
+
{
|
|
1099
|
+
#if defined( _GLFW_HAS_XRANDR )
|
|
1100
|
+
XRRScreenConfiguration *sc;
|
|
1101
|
+
Window root;
|
|
1102
|
+
#endif
|
|
1103
|
+
|
|
1104
|
+
// Free WM size hints
|
|
1105
|
+
if( _glfwWin.Hints )
|
|
1106
|
+
{
|
|
1107
|
+
XFree( _glfwWin.Hints );
|
|
1108
|
+
_glfwWin.Hints = NULL;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
// Do we have a rendering context?
|
|
1112
|
+
if( _glfwWin.CX )
|
|
1113
|
+
{
|
|
1114
|
+
// Release the context
|
|
1115
|
+
glXMakeCurrent( _glfwLibrary.Dpy, None, NULL );
|
|
1116
|
+
|
|
1117
|
+
// Delete the context
|
|
1118
|
+
glXDestroyContext( _glfwLibrary.Dpy, _glfwWin.CX );
|
|
1119
|
+
_glfwWin.CX = NULL;
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
// Ungrab pointer and/or keyboard?
|
|
1123
|
+
if( _glfwWin.KeyboardGrabbed )
|
|
1124
|
+
{
|
|
1125
|
+
XUngrabKeyboard( _glfwLibrary.Dpy, CurrentTime );
|
|
1126
|
+
_glfwWin.KeyboardGrabbed = GL_FALSE;
|
|
1127
|
+
}
|
|
1128
|
+
if( _glfwWin.PointerGrabbed )
|
|
1129
|
+
{
|
|
1130
|
+
XUngrabPointer( _glfwLibrary.Dpy, CurrentTime );
|
|
1131
|
+
_glfwWin.PointerGrabbed = GL_FALSE;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
// Do we have a window?
|
|
1135
|
+
if( _glfwWin.Win )
|
|
1136
|
+
{
|
|
1137
|
+
// Unmap the window
|
|
1138
|
+
XUnmapWindow( _glfwLibrary.Dpy, _glfwWin.Win );
|
|
1139
|
+
|
|
1140
|
+
// Destroy the window
|
|
1141
|
+
XDestroyWindow( _glfwLibrary.Dpy, _glfwWin.Win );
|
|
1142
|
+
_glfwWin.Win = (Window) 0;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
// Did we change the fullscreen resolution?
|
|
1146
|
+
if( _glfwWin.FS.ModeChanged )
|
|
1147
|
+
{
|
|
1148
|
+
#if defined( _GLFW_HAS_XRANDR )
|
|
1149
|
+
if( _glfwLibrary.XRandR.Available )
|
|
1150
|
+
{
|
|
1151
|
+
root = RootWindow( _glfwLibrary.Dpy, _glfwWin.Scrn );
|
|
1152
|
+
sc = XRRGetScreenInfo( _glfwLibrary.Dpy, root );
|
|
1153
|
+
|
|
1154
|
+
XRRSetScreenConfig( _glfwLibrary.Dpy,
|
|
1155
|
+
sc,
|
|
1156
|
+
root,
|
|
1157
|
+
_glfwWin.FS.OldSizeID,
|
|
1158
|
+
_glfwWin.FS.OldRotation,
|
|
1159
|
+
CurrentTime );
|
|
1160
|
+
|
|
1161
|
+
XRRFreeScreenConfigInfo( sc );
|
|
1162
|
+
}
|
|
1163
|
+
#elif defined( _GLFW_HAS_XF86VIDMODE )
|
|
1164
|
+
if( _glfwLibrary.XF86VidMode.Available )
|
|
1165
|
+
{
|
|
1166
|
+
// Unlock mode switch
|
|
1167
|
+
XF86VidModeLockModeSwitch( _glfwLibrary.Dpy,
|
|
1168
|
+
_glfwWin.Scrn,
|
|
1169
|
+
0 );
|
|
1170
|
+
|
|
1171
|
+
// Change the video mode back to the old mode
|
|
1172
|
+
XF86VidModeSwitchToMode( _glfwLibrary.Dpy,
|
|
1173
|
+
_glfwWin.Scrn, &_glfwWin.FS.OldMode );
|
|
1174
|
+
}
|
|
1175
|
+
#endif
|
|
1176
|
+
_glfwWin.FS.ModeChanged = GL_FALSE;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
// Did we change the screen saver setting?
|
|
1180
|
+
if( _glfwWin.Saver.Changed )
|
|
1181
|
+
{
|
|
1182
|
+
// Restore old screen saver settings
|
|
1183
|
+
XSetScreenSaver( _glfwLibrary.Dpy, _glfwWin.Saver.Timeout,
|
|
1184
|
+
_glfwWin.Saver.Interval, _glfwWin.Saver.Blanking,
|
|
1185
|
+
_glfwWin.Saver.Exposure );
|
|
1186
|
+
_glfwWin.Saver.Changed = GL_FALSE;
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
XSync( _glfwLibrary.Dpy, True );
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
|
|
1193
|
+
//========================================================================
|
|
1194
|
+
// _glfwPlatformSetWindowTitle() - Set the window title.
|
|
1195
|
+
//========================================================================
|
|
1196
|
+
|
|
1197
|
+
void _glfwPlatformSetWindowTitle( const char *title )
|
|
1198
|
+
{
|
|
1199
|
+
// Set window & icon title
|
|
1200
|
+
XStoreName( _glfwLibrary.Dpy, _glfwWin.Win, title );
|
|
1201
|
+
XSetIconName( _glfwLibrary.Dpy, _glfwWin.Win, title );
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
|
|
1205
|
+
//========================================================================
|
|
1206
|
+
// _glfwPlatformSetWindowSize() - Set the window size.
|
|
1207
|
+
//========================================================================
|
|
1208
|
+
|
|
1209
|
+
void _glfwPlatformSetWindowSize( int width, int height )
|
|
1210
|
+
{
|
|
1211
|
+
int mode = 0, rate, sizechanged = GL_FALSE;
|
|
1212
|
+
GLint drawbuffer;
|
|
1213
|
+
GLfloat clearcolor[4];
|
|
1214
|
+
|
|
1215
|
+
rate = _glfwWin.RefreshRate;
|
|
1216
|
+
|
|
1217
|
+
// If we are in fullscreen mode, get some info about the current mode
|
|
1218
|
+
if( _glfwWin.Fullscreen )
|
|
1219
|
+
{
|
|
1220
|
+
// Get closest match for target video mode
|
|
1221
|
+
mode = _glfwGetClosestVideoMode( _glfwWin.Scrn, &width, &height, &rate );
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
if( _glfwWin.WindowNoResize )
|
|
1225
|
+
{
|
|
1226
|
+
_glfwWin.Hints->min_width = _glfwWin.Hints->max_width = width;
|
|
1227
|
+
_glfwWin.Hints->min_height = _glfwWin.Hints->max_height = height;
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
XSetWMNormalHints( _glfwLibrary.Dpy, _glfwWin.Win, _glfwWin.Hints );
|
|
1231
|
+
|
|
1232
|
+
// Change window size before changing fullscreen mode?
|
|
1233
|
+
if( _glfwWin.Fullscreen && (width > _glfwWin.Width) )
|
|
1234
|
+
{
|
|
1235
|
+
XResizeWindow( _glfwLibrary.Dpy, _glfwWin.Win, width, height );
|
|
1236
|
+
sizechanged = GL_TRUE;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
// Change fullscreen video mode?
|
|
1240
|
+
if( _glfwWin.Fullscreen )
|
|
1241
|
+
{
|
|
1242
|
+
// Change video mode (keeping current rate)
|
|
1243
|
+
_glfwSetVideoModeMODE( _glfwWin.Scrn, mode, _glfwWin.RefreshRate );
|
|
1244
|
+
|
|
1245
|
+
// Clear the front buffer to black (avoid ugly desktop remains in
|
|
1246
|
+
// our OpenGL window)
|
|
1247
|
+
glGetIntegerv( GL_DRAW_BUFFER, &drawbuffer );
|
|
1248
|
+
glGetFloatv( GL_COLOR_CLEAR_VALUE, clearcolor );
|
|
1249
|
+
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
|
|
1250
|
+
glClear( GL_COLOR_BUFFER_BIT );
|
|
1251
|
+
if( drawbuffer == GL_BACK )
|
|
1252
|
+
{
|
|
1253
|
+
glXSwapBuffers( _glfwLibrary.Dpy, _glfwWin.Win );
|
|
1254
|
+
}
|
|
1255
|
+
glClearColor( clearcolor[0], clearcolor[1], clearcolor[2],
|
|
1256
|
+
clearcolor[3] );
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
// Set window size (if not already changed)
|
|
1260
|
+
if( !sizechanged )
|
|
1261
|
+
{
|
|
1262
|
+
XResizeWindow( _glfwLibrary.Dpy, _glfwWin.Win, width, height );
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
|
|
1267
|
+
//========================================================================
|
|
1268
|
+
// _glfwPlatformSetWindowPos() - Set the window position.
|
|
1269
|
+
//========================================================================
|
|
1270
|
+
|
|
1271
|
+
void _glfwPlatformSetWindowPos( int x, int y )
|
|
1272
|
+
{
|
|
1273
|
+
// Set window position
|
|
1274
|
+
XMoveWindow( _glfwLibrary.Dpy, _glfwWin.Win, x, y );
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
|
|
1278
|
+
//========================================================================
|
|
1279
|
+
// _glfwPlatformIconfyWindow() - Window iconification
|
|
1280
|
+
//========================================================================
|
|
1281
|
+
|
|
1282
|
+
void _glfwPlatformIconifyWindow( void )
|
|
1283
|
+
{
|
|
1284
|
+
// We can't do this for override redirect windows
|
|
1285
|
+
if( _glfwWin.OverrideRedirect )
|
|
1286
|
+
{
|
|
1287
|
+
return;
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
// In fullscreen mode, we need to restore the desktop video mode
|
|
1291
|
+
if( _glfwWin.Fullscreen )
|
|
1292
|
+
{
|
|
1293
|
+
#if defined( _GLFW_HAS_XF86VIDMODE )
|
|
1294
|
+
if( _glfwLibrary.XF86VidMode.Available )
|
|
1295
|
+
{
|
|
1296
|
+
// Unlock mode switch
|
|
1297
|
+
XF86VidModeLockModeSwitch( _glfwLibrary.Dpy,
|
|
1298
|
+
_glfwWin.Scrn,
|
|
1299
|
+
0 );
|
|
1300
|
+
|
|
1301
|
+
// Change the video mode back to the old mode
|
|
1302
|
+
XF86VidModeSwitchToMode( _glfwLibrary.Dpy,
|
|
1303
|
+
_glfwWin.Scrn, &_glfwWin.FS.OldMode );
|
|
1304
|
+
}
|
|
1305
|
+
#endif
|
|
1306
|
+
_glfwWin.FS.ModeChanged = GL_FALSE;
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
// Show mouse pointer
|
|
1310
|
+
if( _glfwWin.PointerHidden )
|
|
1311
|
+
{
|
|
1312
|
+
XUndefineCursor( _glfwLibrary.Dpy, _glfwWin.Win );
|
|
1313
|
+
_glfwWin.PointerHidden = GL_FALSE;
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
// Un-grab mouse pointer
|
|
1317
|
+
if( _glfwWin.PointerGrabbed )
|
|
1318
|
+
{
|
|
1319
|
+
XUngrabPointer( _glfwLibrary.Dpy, CurrentTime );
|
|
1320
|
+
_glfwWin.PointerGrabbed = GL_FALSE;
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
// Iconify window
|
|
1324
|
+
XIconifyWindow( _glfwLibrary.Dpy, _glfwWin.Win,
|
|
1325
|
+
_glfwWin.Scrn );
|
|
1326
|
+
|
|
1327
|
+
// Window is now iconified
|
|
1328
|
+
_glfwWin.Iconified = GL_TRUE;
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
|
|
1332
|
+
//========================================================================
|
|
1333
|
+
// Window un-iconification
|
|
1334
|
+
//========================================================================
|
|
1335
|
+
|
|
1336
|
+
void _glfwPlatformRestoreWindow( void )
|
|
1337
|
+
{
|
|
1338
|
+
// We can't do this for override redirect windows
|
|
1339
|
+
if( _glfwWin.OverrideRedirect )
|
|
1340
|
+
{
|
|
1341
|
+
return;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
// In fullscreen mode, change back video mode to user selected mode
|
|
1345
|
+
if( _glfwWin.Fullscreen )
|
|
1346
|
+
{
|
|
1347
|
+
_glfwSetVideoMode( _glfwWin.Scrn,
|
|
1348
|
+
&_glfwWin.Width, &_glfwWin.Height, &_glfwWin.RefreshRate );
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
// Un-iconify window
|
|
1352
|
+
XMapWindow( _glfwLibrary.Dpy, _glfwWin.Win );
|
|
1353
|
+
|
|
1354
|
+
// In fullscreen mode...
|
|
1355
|
+
if( _glfwWin.Fullscreen )
|
|
1356
|
+
{
|
|
1357
|
+
// Make sure window is in upper left corner
|
|
1358
|
+
XMoveWindow( _glfwLibrary.Dpy, _glfwWin.Win, 0, 0 );
|
|
1359
|
+
|
|
1360
|
+
// Get input focus
|
|
1361
|
+
XSetInputFocus( _glfwLibrary.Dpy, _glfwWin.Win, RevertToParent,
|
|
1362
|
+
CurrentTime );
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
// Lock mouse, if necessary
|
|
1366
|
+
if( _glfwWin.MouseLock )
|
|
1367
|
+
{
|
|
1368
|
+
// Hide cursor
|
|
1369
|
+
if( !_glfwWin.PointerHidden )
|
|
1370
|
+
{
|
|
1371
|
+
XDefineCursor( _glfwLibrary.Dpy, _glfwWin.Win,
|
|
1372
|
+
_glfwCreateNULLCursor( _glfwLibrary.Dpy,
|
|
1373
|
+
_glfwWin.Win ) );
|
|
1374
|
+
_glfwWin.PointerHidden = GL_TRUE;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
// Grab cursor
|
|
1378
|
+
if( !_glfwWin.PointerGrabbed )
|
|
1379
|
+
{
|
|
1380
|
+
if( XGrabPointer( _glfwLibrary.Dpy, _glfwWin.Win, True,
|
|
1381
|
+
ButtonPressMask | ButtonReleaseMask |
|
|
1382
|
+
PointerMotionMask, GrabModeAsync,
|
|
1383
|
+
GrabModeAsync, _glfwWin.Win, None,
|
|
1384
|
+
CurrentTime ) == GrabSuccess )
|
|
1385
|
+
{
|
|
1386
|
+
_glfwWin.PointerGrabbed = GL_TRUE;
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
// Window is no longer iconified
|
|
1392
|
+
_glfwWin.Iconified = GL_FALSE;
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
|
|
1396
|
+
//========================================================================
|
|
1397
|
+
// _glfwPlatformSwapBuffers() - Swap buffers (double-buffering) and poll
|
|
1398
|
+
// any new events.
|
|
1399
|
+
//========================================================================
|
|
1400
|
+
|
|
1401
|
+
void _glfwPlatformSwapBuffers( void )
|
|
1402
|
+
{
|
|
1403
|
+
// Update display-buffer
|
|
1404
|
+
glXSwapBuffers( _glfwLibrary.Dpy, _glfwWin.Win );
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
|
|
1408
|
+
//========================================================================
|
|
1409
|
+
// _glfwPlatformSwapInterval() - Set double buffering swap interval
|
|
1410
|
+
//========================================================================
|
|
1411
|
+
|
|
1412
|
+
void _glfwPlatformSwapInterval( int interval )
|
|
1413
|
+
{
|
|
1414
|
+
if( _glfwWin.SwapInterval )
|
|
1415
|
+
{
|
|
1416
|
+
_glfwWin.SwapInterval( interval );
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
|
|
1421
|
+
//========================================================================
|
|
1422
|
+
// _glfwPlatformRefreshWindowParams()
|
|
1423
|
+
//========================================================================
|
|
1424
|
+
|
|
1425
|
+
void _glfwPlatformRefreshWindowParams( void )
|
|
1426
|
+
{
|
|
1427
|
+
#if defined( _GLFW_HAS_XRANDR )
|
|
1428
|
+
XRRScreenConfiguration *sc;
|
|
1429
|
+
#elif defined( _GLFW_HAS_XF86VIDMODE )
|
|
1430
|
+
XF86VidModeModeLine modeline;
|
|
1431
|
+
int dotclock;
|
|
1432
|
+
float pixels_per_second, pixels_per_frame;
|
|
1433
|
+
#endif
|
|
1434
|
+
int sample_buffers;
|
|
1435
|
+
|
|
1436
|
+
// AFAIK, there is no easy/sure way of knowing if OpenGL is hardware
|
|
1437
|
+
// accelerated
|
|
1438
|
+
_glfwWin.Accelerated = GL_TRUE;
|
|
1439
|
+
|
|
1440
|
+
// "Standard" window parameters
|
|
1441
|
+
glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_RED_SIZE,
|
|
1442
|
+
&_glfwWin.RedBits );
|
|
1443
|
+
glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_GREEN_SIZE,
|
|
1444
|
+
&_glfwWin.GreenBits );
|
|
1445
|
+
glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_BLUE_SIZE,
|
|
1446
|
+
&_glfwWin.BlueBits );
|
|
1447
|
+
glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_ALPHA_SIZE,
|
|
1448
|
+
&_glfwWin.AlphaBits );
|
|
1449
|
+
glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_DEPTH_SIZE,
|
|
1450
|
+
&_glfwWin.DepthBits );
|
|
1451
|
+
glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_STENCIL_SIZE,
|
|
1452
|
+
&_glfwWin.StencilBits );
|
|
1453
|
+
glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_ACCUM_RED_SIZE,
|
|
1454
|
+
&_glfwWin.AccumRedBits );
|
|
1455
|
+
glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_ACCUM_GREEN_SIZE,
|
|
1456
|
+
&_glfwWin.AccumGreenBits );
|
|
1457
|
+
glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_ACCUM_BLUE_SIZE,
|
|
1458
|
+
&_glfwWin.AccumBlueBits );
|
|
1459
|
+
glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_ACCUM_ALPHA_SIZE,
|
|
1460
|
+
&_glfwWin.AccumAlphaBits );
|
|
1461
|
+
glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_AUX_BUFFERS,
|
|
1462
|
+
&_glfwWin.AuxBuffers );
|
|
1463
|
+
|
|
1464
|
+
// Get stereo rendering setting
|
|
1465
|
+
glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_STEREO,
|
|
1466
|
+
&_glfwWin.Stereo );
|
|
1467
|
+
_glfwWin.Stereo = _glfwWin.Stereo ? 1 : 0;
|
|
1468
|
+
|
|
1469
|
+
// Get multisample buffer samples
|
|
1470
|
+
glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_SAMPLES,
|
|
1471
|
+
&_glfwWin.Samples );
|
|
1472
|
+
glXGetConfig( _glfwLibrary.Dpy, _glfwWin.VI, GLX_SAMPLE_BUFFERS,
|
|
1473
|
+
&sample_buffers );
|
|
1474
|
+
if( sample_buffers == 0 )
|
|
1475
|
+
_glfwWin.Samples = 0;
|
|
1476
|
+
|
|
1477
|
+
// Default to refresh rate unknown (=0 according to GLFW spec)
|
|
1478
|
+
_glfwWin.RefreshRate = 0;
|
|
1479
|
+
|
|
1480
|
+
// Retrieve refresh rate, if possible
|
|
1481
|
+
#if defined( _GLFW_HAS_XRANDR )
|
|
1482
|
+
if( _glfwLibrary.XRandR.Available )
|
|
1483
|
+
{
|
|
1484
|
+
sc = XRRGetScreenInfo( _glfwLibrary.Dpy,
|
|
1485
|
+
RootWindow( _glfwLibrary.Dpy, _glfwWin.Scrn ) );
|
|
1486
|
+
_glfwWin.RefreshRate = XRRConfigCurrentRate( sc );
|
|
1487
|
+
XRRFreeScreenConfigInfo( sc );
|
|
1488
|
+
}
|
|
1489
|
+
#elif defined( _GLFW_HAS_XF86VIDMODE )
|
|
1490
|
+
if( _glfwLibrary.XF86VidMode.Available )
|
|
1491
|
+
{
|
|
1492
|
+
// Use the XF86VidMode extension to get current video mode
|
|
1493
|
+
XF86VidModeGetModeLine( _glfwLibrary.Dpy, _glfwWin.Scrn,
|
|
1494
|
+
&dotclock, &modeline );
|
|
1495
|
+
pixels_per_second = 1000.0f * (float) dotclock;
|
|
1496
|
+
pixels_per_frame = (float) modeline.htotal * modeline.vtotal;
|
|
1497
|
+
_glfwWin.RefreshRate = (int)(pixels_per_second/pixels_per_frame+0.5);
|
|
1498
|
+
}
|
|
1499
|
+
#endif
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
|
|
1503
|
+
//========================================================================
|
|
1504
|
+
// _glfwPlatformPollEvents() - Poll for new window and input events
|
|
1505
|
+
//========================================================================
|
|
1506
|
+
|
|
1507
|
+
void _glfwPlatformPollEvents( void )
|
|
1508
|
+
{
|
|
1509
|
+
int winclosed = GL_FALSE;
|
|
1510
|
+
|
|
1511
|
+
// Flag that the cursor has not moved
|
|
1512
|
+
_glfwInput.MouseMoved = GL_FALSE;
|
|
1513
|
+
|
|
1514
|
+
// Clear MapNotify and FocusIn counts
|
|
1515
|
+
_glfwWin.MapNotifyCount = 0;
|
|
1516
|
+
_glfwWin.FocusInCount = 0;
|
|
1517
|
+
|
|
1518
|
+
// Use XSync to synchronise events to the X display.
|
|
1519
|
+
// I don't know if this can have a serious performance impact. My
|
|
1520
|
+
// benchmarks with a GeForce card under Linux shows no difference with
|
|
1521
|
+
// or without XSync, but when the GL window is rendered over a slow
|
|
1522
|
+
// network I have noticed bad event syncronisation problems when XSync
|
|
1523
|
+
// is not used, so I decided to use it.
|
|
1524
|
+
XSync( _glfwLibrary.Dpy, False );
|
|
1525
|
+
|
|
1526
|
+
// Empty the window event queue
|
|
1527
|
+
while( XPending( _glfwLibrary.Dpy ) )
|
|
1528
|
+
{
|
|
1529
|
+
if( _glfwGetNextEvent() )
|
|
1530
|
+
{
|
|
1531
|
+
winclosed = GL_TRUE;
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
// Did we get mouse movement in locked cursor mode?
|
|
1536
|
+
if( _glfwInput.MouseMoved && _glfwWin.MouseLock )
|
|
1537
|
+
{
|
|
1538
|
+
int maxx, minx, maxy, miny;
|
|
1539
|
+
|
|
1540
|
+
// Calculate movement threshold
|
|
1541
|
+
minx = _glfwWin.Width / 4;
|
|
1542
|
+
maxx = (_glfwWin.Width * 3) / 4;
|
|
1543
|
+
miny = _glfwWin.Height / 4;
|
|
1544
|
+
maxy = (_glfwWin.Height * 3) / 4;
|
|
1545
|
+
|
|
1546
|
+
// Did the mouse cursor move beyond our movement threshold
|
|
1547
|
+
if(_glfwInput.CursorPosX < minx || _glfwInput.CursorPosX > maxx ||
|
|
1548
|
+
_glfwInput.CursorPosY < miny || _glfwInput.CursorPosY > maxy)
|
|
1549
|
+
{
|
|
1550
|
+
// Move the mouse pointer back to the window center so that it
|
|
1551
|
+
// does not wander off...
|
|
1552
|
+
_glfwPlatformSetMouseCursorPos( _glfwWin.Width/2,
|
|
1553
|
+
_glfwWin.Height/2 );
|
|
1554
|
+
XSync( _glfwLibrary.Dpy, False );
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
// Was the window (un)iconified?
|
|
1559
|
+
if( _glfwWin.MapNotifyCount < 0 && !_glfwWin.Iconified )
|
|
1560
|
+
{
|
|
1561
|
+
// Show mouse pointer
|
|
1562
|
+
if( _glfwWin.PointerHidden )
|
|
1563
|
+
{
|
|
1564
|
+
XUndefineCursor( _glfwLibrary.Dpy, _glfwWin.Win );
|
|
1565
|
+
_glfwWin.PointerHidden = GL_FALSE;
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
// Un-grab mouse pointer
|
|
1569
|
+
if( _glfwWin.PointerGrabbed )
|
|
1570
|
+
{
|
|
1571
|
+
XUngrabPointer( _glfwLibrary.Dpy, CurrentTime );
|
|
1572
|
+
_glfwWin.PointerGrabbed = GL_FALSE;
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
_glfwWin.Iconified = GL_TRUE;
|
|
1576
|
+
}
|
|
1577
|
+
else if( _glfwWin.MapNotifyCount > 0 && _glfwWin.Iconified )
|
|
1578
|
+
{
|
|
1579
|
+
// Restore fullscreen mode properties
|
|
1580
|
+
if( _glfwWin.Fullscreen )
|
|
1581
|
+
{
|
|
1582
|
+
// Change back video mode to user selected mode
|
|
1583
|
+
_glfwSetVideoMode( _glfwWin.Scrn, &_glfwWin.Width,
|
|
1584
|
+
&_glfwWin.Height, &_glfwWin.RefreshRate );
|
|
1585
|
+
|
|
1586
|
+
// Disable window manager decorations
|
|
1587
|
+
_glfwEnableDecorations();
|
|
1588
|
+
|
|
1589
|
+
// Make sure window is in upper left corner
|
|
1590
|
+
XMoveWindow( _glfwLibrary.Dpy, _glfwWin.Win, 0, 0 );
|
|
1591
|
+
|
|
1592
|
+
// Get input focus
|
|
1593
|
+
XSetInputFocus( _glfwLibrary.Dpy, _glfwWin.Win,
|
|
1594
|
+
RevertToParent, CurrentTime );
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
// Hide cursor if necessary
|
|
1598
|
+
if( _glfwWin.MouseLock && !_glfwWin.PointerHidden )
|
|
1599
|
+
{
|
|
1600
|
+
if( !_glfwWin.PointerHidden )
|
|
1601
|
+
{
|
|
1602
|
+
XDefineCursor( _glfwLibrary.Dpy, _glfwWin.Win,
|
|
1603
|
+
_glfwCreateNULLCursor( _glfwLibrary.Dpy,
|
|
1604
|
+
_glfwWin.Win ) );
|
|
1605
|
+
_glfwWin.PointerHidden = GL_TRUE;
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
// Grab cursor if necessary
|
|
1610
|
+
if( (_glfwWin.MouseLock || _glfwWin.Fullscreen) &&
|
|
1611
|
+
!_glfwWin.PointerGrabbed )
|
|
1612
|
+
{
|
|
1613
|
+
if( XGrabPointer( _glfwLibrary.Dpy, _glfwWin.Win, True,
|
|
1614
|
+
ButtonPressMask | ButtonReleaseMask |
|
|
1615
|
+
PointerMotionMask, GrabModeAsync,
|
|
1616
|
+
GrabModeAsync, _glfwWin.Win, None,
|
|
1617
|
+
CurrentTime ) == GrabSuccess )
|
|
1618
|
+
{
|
|
1619
|
+
_glfwWin.PointerGrabbed = GL_TRUE;
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
_glfwWin.Iconified = GL_FALSE;
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
// Did the window get/lose focus
|
|
1627
|
+
if( _glfwWin.FocusInCount > 0 && !_glfwWin.Active )
|
|
1628
|
+
{
|
|
1629
|
+
// If we are in fullscreen mode, restore window
|
|
1630
|
+
if( _glfwWin.Fullscreen && _glfwWin.Iconified )
|
|
1631
|
+
{
|
|
1632
|
+
_glfwPlatformRestoreWindow();
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
// Window is now active
|
|
1636
|
+
_glfwWin.Active = GL_TRUE;
|
|
1637
|
+
}
|
|
1638
|
+
else if( _glfwWin.FocusInCount < 0 && _glfwWin.Active )
|
|
1639
|
+
{
|
|
1640
|
+
// If we are in fullscreen mode, iconfify window
|
|
1641
|
+
if( _glfwWin.Fullscreen )
|
|
1642
|
+
{
|
|
1643
|
+
_glfwPlatformIconifyWindow();
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
// Window is not active
|
|
1647
|
+
_glfwWin.Active = GL_FALSE;
|
|
1648
|
+
_glfwInputDeactivation();
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
// Was there a window close request?
|
|
1652
|
+
if( winclosed && _glfwWin.WindowCloseCallback )
|
|
1653
|
+
{
|
|
1654
|
+
// Check if the program wants us to close the window
|
|
1655
|
+
winclosed = _glfwWin.WindowCloseCallback();
|
|
1656
|
+
}
|
|
1657
|
+
if( winclosed )
|
|
1658
|
+
{
|
|
1659
|
+
glfwCloseWindow();
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
|
|
1664
|
+
//========================================================================
|
|
1665
|
+
// _glfwPlatformWaitEvents() - Wait for new window and input events
|
|
1666
|
+
//========================================================================
|
|
1667
|
+
|
|
1668
|
+
void _glfwPlatformWaitEvents( void )
|
|
1669
|
+
{
|
|
1670
|
+
XEvent event;
|
|
1671
|
+
|
|
1672
|
+
// Wait for new events (blocking)
|
|
1673
|
+
XNextEvent( _glfwLibrary.Dpy, &event );
|
|
1674
|
+
XPutBackEvent( _glfwLibrary.Dpy, &event );
|
|
1675
|
+
|
|
1676
|
+
// Poll events from queue
|
|
1677
|
+
_glfwPlatformPollEvents();
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
|
|
1681
|
+
//========================================================================
|
|
1682
|
+
// _glfwPlatformHideMouseCursor() - Hide mouse cursor (lock it)
|
|
1683
|
+
//========================================================================
|
|
1684
|
+
|
|
1685
|
+
void _glfwPlatformHideMouseCursor( void )
|
|
1686
|
+
{
|
|
1687
|
+
// Hide cursor
|
|
1688
|
+
if( !_glfwWin.PointerHidden )
|
|
1689
|
+
{
|
|
1690
|
+
XDefineCursor( _glfwLibrary.Dpy, _glfwWin.Win,
|
|
1691
|
+
_glfwCreateNULLCursor( _glfwLibrary.Dpy,
|
|
1692
|
+
_glfwWin.Win ) );
|
|
1693
|
+
_glfwWin.PointerHidden = GL_TRUE;
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
// Grab cursor to user window
|
|
1697
|
+
if( !_glfwWin.PointerGrabbed )
|
|
1698
|
+
{
|
|
1699
|
+
if( XGrabPointer( _glfwLibrary.Dpy, _glfwWin.Win, True,
|
|
1700
|
+
ButtonPressMask | ButtonReleaseMask |
|
|
1701
|
+
PointerMotionMask, GrabModeAsync, GrabModeAsync,
|
|
1702
|
+
_glfwWin.Win, None, CurrentTime ) ==
|
|
1703
|
+
GrabSuccess )
|
|
1704
|
+
{
|
|
1705
|
+
_glfwWin.PointerGrabbed = GL_TRUE;
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
|
|
1711
|
+
//========================================================================
|
|
1712
|
+
// _glfwPlatformShowMouseCursor() - Show mouse cursor (unlock it)
|
|
1713
|
+
//========================================================================
|
|
1714
|
+
|
|
1715
|
+
void _glfwPlatformShowMouseCursor( void )
|
|
1716
|
+
{
|
|
1717
|
+
// Un-grab cursor (only in windowed mode: in fullscreen mode we still
|
|
1718
|
+
// want the mouse grabbed in order to confine the cursor to the window
|
|
1719
|
+
// area)
|
|
1720
|
+
if( _glfwWin.PointerGrabbed && !_glfwWin.Fullscreen )
|
|
1721
|
+
{
|
|
1722
|
+
XUngrabPointer( _glfwLibrary.Dpy, CurrentTime );
|
|
1723
|
+
_glfwWin.PointerGrabbed = GL_FALSE;
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
// Show cursor
|
|
1727
|
+
if( _glfwWin.PointerHidden )
|
|
1728
|
+
{
|
|
1729
|
+
XUndefineCursor( _glfwLibrary.Dpy, _glfwWin.Win );
|
|
1730
|
+
_glfwWin.PointerHidden = GL_FALSE;
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
|
|
1735
|
+
//========================================================================
|
|
1736
|
+
// _glfwPlatformSetMouseCursorPos() - Set physical mouse cursor position
|
|
1737
|
+
//========================================================================
|
|
1738
|
+
|
|
1739
|
+
void _glfwPlatformSetMouseCursorPos( int x, int y )
|
|
1740
|
+
{
|
|
1741
|
+
// Change cursor position
|
|
1742
|
+
_glfwInput.CursorPosX = x;
|
|
1743
|
+
_glfwInput.CursorPosY = y;
|
|
1744
|
+
XWarpPointer( _glfwLibrary.Dpy, None, _glfwWin.Win, 0,0,0,0, x, y );
|
|
1745
|
+
}
|
|
1746
|
+
|