updated ebiten version from 2.7.9 to 2.9.9

This commit is contained in:
2026-06-15 19:06:55 +02:00
parent 21edbc41c4
commit db1b625069
405 changed files with 31913 additions and 12595 deletions
+13 -11
View File
@@ -4,7 +4,7 @@
package glfw
// #include "internal_unix.h"
// #include <pthread.h>
import "C"
import (
@@ -18,16 +18,18 @@ type mach_timebase_info_data_t struct {
denom uint32
}
var mach_absolute_time func() uint64
var mach_timebase_info func(*mach_timebase_info_data_t)
var pthread_key_create func(key *C.pthread_key_t, destructor uintptr) int32
var pthread_key_delete func(key C.pthread_key_t) int32
var pthread_getspecific func(key C.pthread_key_t) uintptr
var pthread_setspecific func(key C.pthread_key_t, value uintptr) int32
var pthread_mutex_init func(mutex *C.pthread_mutex_t, attr *C.pthread_mutexattr_t) int32
var pthread_mutex_destroy func(mutex *C.pthread_mutex_t) int32
var pthread_mutex_lock func(mutex *C.pthread_mutex_t) int32
var pthread_mutex_unlock func(mutex *C.pthread_mutex_t) int32
var (
mach_absolute_time func() uint64
mach_timebase_info func(*mach_timebase_info_data_t)
pthread_key_create func(key *C.pthread_key_t, destructor uintptr) int32
pthread_key_delete func(key C.pthread_key_t) int32
pthread_getspecific func(key C.pthread_key_t) uintptr
pthread_setspecific func(key C.pthread_key_t, value uintptr) int32
pthread_mutex_init func(mutex *C.pthread_mutex_t, attr *C.pthread_mutexattr_t) int32
pthread_mutex_destroy func(mutex *C.pthread_mutex_t) int32
pthread_mutex_lock func(mutex *C.pthread_mutex_t) int32
pthread_mutex_unlock func(mutex *C.pthread_mutex_t) int32
)
// TODO: replace with Go error handling
var _glfwInputError func(code int32, format *C.char)
+40
View File
@@ -100,6 +100,7 @@ const (
_MAPVK_VSC_TO_VK = 1
_MONITOR_DEFAULTTONEAREST = 0x00000002
_MOUSE_MOVE_ABSOLUTE = 0x01
_MOUSE_VIRTUAL_DESKTOP = 0x02
_MSGFLT_ALLOW = 1
_OCR_CROSS = 32515
_OCR_HAND = 32649
@@ -121,6 +122,7 @@ const (
_PFD_SUPPORT_OPENGL = 0x00000020
_PFD_TYPE_RGBA = 0
_QS_ALLEVENTS = _QS_INPUT | _QS_POSTMESSAGE | _QS_TIMER | _QS_PAINT | _QS_HOTKEY
_QS_ALLINPUT = _QS_INPUT | _QS_POSTMESSAGE | _QS_TIMER | _QS_PAINT | _QS_HOTKEY | _QS_SENDMESSAGE
_QS_HOTKEY = 0x0080
_QS_INPUT = _QS_MOUSE | _QS_KEY | _QS_RAWINPUT
_QS_KEY = 0x0001
@@ -130,6 +132,7 @@ const (
_QS_PAINT = 0x0020
_QS_POSTMESSAGE = 0x0008
_QS_RAWINPUT = 0x0400
_QS_SENDMESSAGE = 0x0040
_QS_TIMER = 0x0010
_RID_INPUT = 0x10000003
_RIDEV_REMOVE = 0x00000001
@@ -139,11 +142,18 @@ const (
_SIZE_MAXIMIZED = 2
_SIZE_MINIMIZED = 1
_SIZE_RESTORED = 0
_SM_CXCURSOR = 13
_SM_CXICON = 11
_SM_CXSCREEN = 0
_SM_CXSMICON = 49
_SM_CYCAPTION = 4
_SM_CYCURSOR = 14
_SM_CYICON = 12
_SM_CYSCREEN = 1
_SM_CYSMICON = 50
_SM_CXVIRTUALSCREEN = 78
_SM_CYVIRTUALSCREEN = 79
_SM_REMOTESESSION = 0x1000
_SPI_GETFOREGROUNDLOCKTIMEOUT = 0x2000
_SPI_GETMOUSETRAILS = 94
_SPI_SETFOREGROUNDLOCKTIMEOUT = 0x2001
@@ -753,9 +763,11 @@ var (
procChangeWindowMessageFilterEx = user32.NewProc("ChangeWindowMessageFilterEx")
procClientToScreen = user32.NewProc("ClientToScreen")
procClipCursor = user32.NewProc("ClipCursor")
procCreateCursor = user32.NewProc("CreateCursor")
procCreateIconIndirect = user32.NewProc("CreateIconIndirect")
procCreateWindowExW = user32.NewProc("CreateWindowExW")
procDefWindowProcW = user32.NewProc("DefWindowProcW")
procDestroyCursor = user32.NewProc("DestroyCursor")
procDestroyIcon = user32.NewProc("DestroyIcon")
procDestroyWindow = user32.NewProc("DestroyWindow")
procDispatchMessageW = user32.NewProc("DispatchMessageW")
@@ -913,6 +925,26 @@ func _ClipCursor(lpRect *_RECT) error {
return nil
}
func _CreateCursor(hInst _HINSTANCE, xHotSpot int32, yHotSpot int32, nWidth int32, nHeight int32, pvANDPlane, pvXORPlane []byte) (_HCURSOR, error) {
var andPlane *byte
if len(pvANDPlane) > 0 {
andPlane = &pvANDPlane[0]
}
var xorPlane *byte
if len(pvXORPlane) > 0 {
xorPlane = &pvXORPlane[0]
}
r, _, e := procCreateCursor.Call(uintptr(hInst), uintptr(xHotSpot), uintptr(yHotSpot), uintptr(nWidth), uintptr(nHeight), uintptr(unsafe.Pointer(andPlane)), uintptr(unsafe.Pointer(xorPlane)))
runtime.KeepAlive(pvANDPlane)
runtime.KeepAlive(pvXORPlane)
if _HCURSOR(r) == 0 && !errors.Is(e, windows.ERROR_SUCCESS) {
return 0, fmt.Errorf("glfw: CreateCursor failed: %w", e)
}
return _HCURSOR(r), nil
}
func _CreateBitmap(nWidth int32, nHeight int32, nPlanes uint32, nBitCount uint32, lpBits unsafe.Pointer) (_HBITMAP, error) {
r, _, e := procCreateBitmap.Call(uintptr(nWidth), uintptr(nHeight), uintptr(nPlanes), uintptr(nBitCount), uintptr(lpBits))
if _HBITMAP(r) == 0 {
@@ -984,6 +1016,14 @@ func _DefWindowProcW(hWnd windows.HWND, uMsg uint32, wParam _WPARAM, lParam _LPA
return _LRESULT(r)
}
func _DestroyCursor(hCursor _HCURSOR) error {
r, _, e := procDestroyCursor.Call(uintptr(hCursor))
if int32(r) == 0 && !errors.Is(e, windows.ERROR_SUCCESS) {
return fmt.Errorf("glfw: DestroyCursor failed: %w", e)
}
return nil
}
func _DestroyIcon(hIcon _HICON) error {
r, _, e := procDestroyIcon.Call(uintptr(hIcon))
if int32(r) == 0 && !errors.Is(e, windows.ERROR_SUCCESS) {
-2
View File
@@ -6,8 +6,6 @@
package glfw
import "C"
// #cgo pkg-config: x11 xau xcb xdmcp
// #cgo CFLAGS: -D_GLFW_HAS_DLOPEN -D_GLFW_X11 -D_GLFW_HAS_GLXGETPROCADDRESSARB
// #cgo LDFLAGS: -lm
+5 -19
View File
@@ -227,7 +227,7 @@ static void createKeyTables(void)
_glfw.ns.keycodes[0x6D] = GLFW_KEY_F10;
_glfw.ns.keycodes[0x67] = GLFW_KEY_F11;
_glfw.ns.keycodes[0x6F] = GLFW_KEY_F12;
_glfw.ns.keycodes[0x69] = GLFW_KEY_F13;
_glfw.ns.keycodes[0x69] = GLFW_KEY_PRINT_SCREEN;
_glfw.ns.keycodes[0x6B] = GLFW_KEY_F14;
_glfw.ns.keycodes[0x71] = GLFW_KEY_F15;
_glfw.ns.keycodes[0x6A] = GLFW_KEY_F16;
@@ -420,7 +420,6 @@ static GLFWbool initializeTIS(void)
- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
_glfw.ns.finishedLaunching = GLFW_TRUE;
_glfwPlatformPostEmptyEvent();
// In case we are unbundled, make us a proper UI application
@@ -455,9 +454,6 @@ int _glfwPlatformInit(void)
toTarget:_glfw.ns.helper
withObject:nil];
if (NSApp)
_glfw.ns.finishedLaunching = GLFW_TRUE;
[NSApplication sharedApplication];
_glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init];
@@ -485,10 +481,6 @@ int _glfwPlatformInit(void)
if (_glfw.hints.init.ns.chdir)
changeToResourcesDirectory();
// Press and Hold prevents some keys from emitting repeated characters
NSDictionary* defaults = @{@"ApplePressAndHoldEnabled":@NO};
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
[[NSNotificationCenter defaultCenter]
addObserver:_glfw.ns.helper
selector:@selector(selectedKeyboardInputSourceChanged:)
@@ -509,6 +501,10 @@ int _glfwPlatformInit(void)
_glfwInitTimerNS();
_glfwPollMonitorsNS();
if (![[NSRunningApplication currentApplication] isFinishedLaunching])
[NSApp run];
return GLFW_TRUE;
} // autoreleasepool
@@ -561,13 +557,3 @@ void _glfwPlatformTerminate(void)
} // autoreleasepool
}
const char* _glfwPlatformGetVersionString(void)
{
return _GLFW_VERSION_NUMBER " Cocoa NSGL EGL OSMesa"
#if defined(_GLFW_BUILD_DLL)
" dynamic"
#endif
;
}
@@ -109,7 +109,6 @@ typedef struct _GLFWlibraryNS
{
CGEventSourceRef eventSource;
id delegate;
GLFWbool finishedLaunching;
GLFWbool cursorHidden;
TISInputSourceRef inputSource;
id unicodeData;
+13 -22
View File
@@ -285,10 +285,15 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)windowDidChangeOcclusionState:(NSNotification* )notification
{
if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible)
window->ns.occluded = GLFW_FALSE;
else
window->ns.occluded = GLFW_TRUE;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
if ([window->ns.object respondsToSelector:@selector(occlusionState)])
{
if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible)
window->ns.occluded = GLFW_FALSE;
else
window->ns.occluded = GLFW_TRUE;
}
#endif
}
@end
@@ -878,9 +883,6 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
{
@autoreleasepool {
if (!_glfw.ns.finishedLaunching)
[NSApp run];
if (!createNativeWindow(window, wndconfig, fbconfig))
return GLFW_FALSE;
@@ -1239,7 +1241,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
if (window->monitor)
{
styleMask &= ~(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
styleMask &= ~(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable);
styleMask |= NSWindowStyleMaskBorderless;
}
else
@@ -1472,9 +1474,6 @@ void _glfwPlatformPollEvents(void)
{
@autoreleasepool {
if (!_glfw.ns.finishedLaunching)
[NSApp run];
for (;;)
{
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
@@ -1494,9 +1493,6 @@ void _glfwPlatformWaitEvents(void)
{
@autoreleasepool {
if (!_glfw.ns.finishedLaunching)
[NSApp run];
// I wanted to pass NO to dequeue:, and rely on PollEvents to
// dequeue and send. For reasons not at all clear to me, passing
// NO to dequeue: causes this method never to return.
@@ -1515,9 +1511,6 @@ void _glfwPlatformWaitEventsTimeout(double timeout)
{
@autoreleasepool {
if (!_glfw.ns.finishedLaunching)
[NSApp run];
NSDate* date = [NSDate dateWithTimeIntervalSinceNow:timeout];
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:date
@@ -1535,9 +1528,6 @@ void _glfwPlatformPostEmptyEvent(void)
{
@autoreleasepool {
if (!_glfw.ns.finishedLaunching)
[NSApp run];
NSEvent* event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
location:NSMakePoint(0, 0)
modifierFlags:0
@@ -1616,14 +1606,15 @@ const char* _glfwPlatformGetScancodeName(int scancode)
{
@autoreleasepool {
if (scancode < 0 || scancode > 0xff ||
_glfw.ns.keycodes[scancode] == GLFW_KEY_UNKNOWN)
if (scancode < 0 || scancode > 0xff)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode %i", scancode);
return NULL;
}
const int key = _glfw.ns.keycodes[scancode];
if (key == GLFW_KEY_UNKNOWN)
return NULL;
UInt32 deadKeyState = 0;
UniChar characters[4];
+37 -44
View File
@@ -26,16 +26,6 @@
//
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
{
if (ctxconfig->share)
{
if (ctxconfig->client == GLFW_NO_API ||
ctxconfig->share->context.client == GLFW_NO_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return GLFW_FALSE;
}
}
if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
ctxconfig->source != GLFW_EGL_CONTEXT_API &&
ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
@@ -56,6 +46,23 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
return GLFW_FALSE;
}
if (ctxconfig->share)
{
if (ctxconfig->client == GLFW_NO_API ||
ctxconfig->share->context.client == GLFW_NO_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return GLFW_FALSE;
}
if (ctxconfig->source != ctxconfig->share->context.source)
{
_glfwInputError(GLFW_INVALID_ENUM,
"Context creation APIs do not match between contexts");
return GLFW_FALSE;
}
}
if (ctxconfig->client == GLFW_OPENGL_API)
{
if ((ctxconfig->major < 1 || ctxconfig->minor < 0) ||
@@ -319,7 +326,6 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig)
{
int i;
_GLFWwindow* previous;
const char* version;
const char* prefixes[] =
{
@@ -332,7 +338,8 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
window->context.source = ctxconfig->source;
window->context.client = GLFW_OPENGL_API;
previous = _glfwPlatformGetTls(&_glfw.contextSlot);
// In Ebitengine, only one window is created.
// Always assume that the current context is not set.
glfwMakeContextCurrent((GLFWwindow*) window);
window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
@@ -342,7 +349,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
if (!window->context.GetIntegerv || !window->context.GetString)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
glfwMakeContextCurrent((GLFWwindow*) previous);
glfwMakeContextCurrent(NULL);
return GLFW_FALSE;
}
@@ -360,7 +367,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
"OpenGL ES version string retrieval is broken");
}
glfwMakeContextCurrent((GLFWwindow*) previous);
glfwMakeContextCurrent(NULL);
return GLFW_FALSE;
}
@@ -392,7 +399,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
"No version found in OpenGL ES version string");
}
glfwMakeContextCurrent((GLFWwindow*) previous);
glfwMakeContextCurrent(NULL);
return GLFW_FALSE;
}
@@ -422,7 +429,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
window->context.major, window->context.minor);
}
glfwMakeContextCurrent((GLFWwindow*) previous);
glfwMakeContextCurrent(NULL);
return GLFW_FALSE;
}
@@ -438,7 +445,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Entry point retrieval is broken");
glfwMakeContextCurrent((GLFWwindow*) previous);
glfwMakeContextCurrent(NULL);
return GLFW_FALSE;
}
}
@@ -456,7 +463,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
window->context.debug = GLFW_TRUE;
else if (glfwExtensionSupported("GL_ARB_debug_output") &&
else if (glfwExtensionSupported((GLFWwindow*) window, "GL_ARB_debug_output") &&
ctxconfig->debug)
{
// HACK: This is a workaround for older drivers (pre KHR_debug)
@@ -480,7 +487,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
else if (mask & GL_CONTEXT_CORE_PROFILE_BIT)
window->context.profile = GLFW_OPENGL_CORE_PROFILE;
else if (glfwExtensionSupported("GL_ARB_compatibility"))
else if (glfwExtensionSupported((GLFWwindow*) window, "GL_ARB_compatibility"))
{
// HACK: This is a workaround for the compatibility profile bit
// not being set in the context flags if an OpenGL 3.2+
@@ -491,7 +498,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
}
// Read back robustness strategy
if (glfwExtensionSupported("GL_ARB_robustness"))
if (glfwExtensionSupported((GLFWwindow*) window, "GL_ARB_robustness"))
{
// NOTE: We avoid using the context flags for detection, as they are
// only present from 3.0 while the extension applies from 1.1
@@ -509,7 +516,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
else
{
// Read back robustness strategy
if (glfwExtensionSupported("GL_EXT_robustness"))
if (glfwExtensionSupported((GLFWwindow*) window, "GL_EXT_robustness"))
{
// NOTE: The values of these constants match those of the OpenGL ARB
// one, so we can reuse them here
@@ -525,7 +532,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
}
}
if (glfwExtensionSupported("GL_KHR_context_flush_control"))
if (glfwExtensionSupported((GLFWwindow*) window, "GL_KHR_context_flush_control"))
{
GLint behavior;
window->context.GetIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &behavior);
@@ -547,7 +554,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
window->context.swapBuffers(window);
}
glfwMakeContextCurrent((GLFWwindow*) previous);
glfwMakeContextCurrent(NULL);
return GLFW_TRUE;
}
@@ -633,38 +640,24 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
window->context.swapBuffers(window);
}
GLFWAPI void glfwSwapInterval(int interval)
GLFWAPI void glfwSwapInterval(GLFWwindow* handle, int interval)
{
_GLFWwindow* window;
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT();
window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (!window)
{
_glfwInputError(GLFW_NO_CURRENT_CONTEXT,
"Cannot set swap interval without a current OpenGL or OpenGL ES context");
return;
}
window->context.swapInterval(interval);
window->context.swapInterval(window, interval);
}
GLFWAPI int glfwExtensionSupported(const char* extension)
GLFWAPI int glfwExtensionSupported(GLFWwindow* handle, const char* extension)
{
_GLFWwindow* window;
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(extension != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (!window)
{
_glfwInputError(GLFW_NO_CURRENT_CONTEXT,
"Cannot query extension without a current OpenGL or OpenGL ES context");
return GLFW_FALSE;
}
if (*extension == '\0')
{
_glfwInputError(GLFW_INVALID_VALUE, "Extension name cannot be an empty string");
+4 -4
View File
@@ -73,8 +73,8 @@ func (w *Window) SwapBuffers() error {
//
// Some GPU drivers do not honor the requested swap interval, either because of
// user settings that override the request or due to bugs in the driver.
func SwapInterval(interval int) error {
C.glfwSwapInterval(C.int(interval))
func (w *Window) SwapInterval(interval int) error {
C.glfwSwapInterval(w.data, C.int(interval))
if err := fetchErrorIgnoringPlatformError(); err != nil {
return err
}
@@ -89,10 +89,10 @@ func SwapInterval(interval int) error {
// recommended that you cache its results if it's going to be used frequently.
// The extension strings will not change during the lifetime of a context, so
// there is no danger in doing this.
func ExtensionSupported(extension string) (bool, error) {
func (w *Window) ExtensionSupported(extension string) (bool, error) {
e := C.CString(extension)
defer C.free(unsafe.Pointer(e))
ret := C.glfwExtensionSupported(e) != 0
ret := C.glfwExtensionSupported(w.data, e) != 0
if err := fetchErrorIgnoringPlatformError(); err != nil {
return false, err
}
+26 -45
View File
@@ -17,12 +17,6 @@ import (
)
func checkValidContextConfig(ctxconfig *ctxconfig) error {
if ctxconfig.share != nil {
if ctxconfig.client == NoAPI || ctxconfig.share.context.client == NoAPI {
return NoWindowContext
}
}
if ctxconfig.source != NativeContextAPI &&
ctxconfig.source != EGLContextAPI &&
ctxconfig.source != OSMesaContextAPI {
@@ -35,6 +29,15 @@ func checkValidContextConfig(ctxconfig *ctxconfig) error {
return fmt.Errorf("glfw: invalid client API 0x%08X: %w", ctxconfig.client, InvalidEnum)
}
if ctxconfig.share != nil {
if ctxconfig.client == NoAPI || ctxconfig.share.context.client == NoAPI {
return NoWindowContext
}
if ctxconfig.source != ctxconfig.share.context.source {
return fmt.Errorf("glfw: context creation APIs do not match between contexts: %w", InvalidEnum)
}
}
if ctxconfig.client == OpenGLAPI {
if (ctxconfig.major < 1 || ctxconfig.minor < 0) ||
(ctxconfig.major == 1 && ctxconfig.minor > 5) ||
@@ -249,13 +252,10 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) {
w.context.source = ctxconfig.source
w.context.client = OpenGLAPI
p, err := _glfw.contextSlot.get()
if err != nil {
return err
}
previous := (*Window)(unsafe.Pointer(p))
// In Ebitengine, only one window is created.
// Always assume that the current context is not set.
defer func() {
err := previous.MakeContextCurrent()
err := (*Window)(nil).MakeContextCurrent()
if ferr == nil {
ferr = err
}
@@ -342,7 +342,7 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) {
if flags&GL_CONTEXT_FLAG_DEBUG_BIT != 0 {
w.context.debug = true
} else {
ok, err := ExtensionSupported("GL_ARB_debug_output")
ok, err := w.ExtensionSupported("GL_ARB_debug_output")
if err != nil {
return err
}
@@ -369,7 +369,7 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) {
} else if mask&GL_CONTEXT_CORE_PROFILE_BIT != 0 {
w.context.profile = OpenGLCoreProfile
} else {
ok, err := ExtensionSupported("GL_ARB_compatibility")
ok, err := w.ExtensionSupported("GL_ARB_compatibility")
if err != nil {
return err
}
@@ -384,7 +384,7 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) {
}
// Read back robustness strategy
ok, err := ExtensionSupported("GL_ARB_robustness")
ok, err := w.ExtensionSupported("GL_ARB_robustness")
if err != nil {
return err
}
@@ -403,7 +403,7 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) {
}
} else {
// Read back robustness strategy
ok, err := ExtensionSupported("GL_EXT_robustness")
ok, err := w.ExtensionSupported("GL_EXT_robustness")
if err != nil {
return err
}
@@ -422,7 +422,7 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) {
}
}
ok, err := ExtensionSupported("GL_KHR_context_flush_control")
ok, err := w.ExtensionSupported("GL_KHR_context_flush_control")
if err != nil {
return err
}
@@ -508,27 +508,18 @@ func (w *Window) SwapBuffers() error {
return nil
}
func SwapInterval(interval int) error {
func (w *Window) SwapInterval(interval int) error {
if !_glfw.initialized {
return NotInitialized
}
ptr, err := _glfw.contextSlot.get()
if err != nil {
return err
}
window := (*Window)(unsafe.Pointer(ptr))
if window == nil {
return fmt.Errorf("glfw: cannot set swap interval without a current OpenGL or OpenGL ES context %w", NoCurrentContext)
}
if err := window.context.swapInterval(interval); err != nil {
if err := w.context.swapInterval(w, interval); err != nil {
return err
}
return nil
}
func ExtensionSupported(extension string) (bool, error) {
func (w *Window) ExtensionSupported(extension string) (bool, error) {
const (
GL_EXTENSIONS = 0x1F03
GL_NUM_EXTENSIONS = 0x821D
@@ -538,23 +529,14 @@ func ExtensionSupported(extension string) (bool, error) {
return false, NotInitialized
}
ptr, err := _glfw.contextSlot.get()
if err != nil {
return false, err
}
window := (*Window)(unsafe.Pointer(ptr))
if window == nil {
return false, fmt.Errorf("glfw: cannot query extension without a current OpenGL or OpenGL ES context %w", NoCurrentContext)
}
if window.context.major >= 3 {
if w.context.major >= 3 {
// Check if extension is in the modern OpenGL extensions string list
glGetIntegerv := window.context.getProcAddress("glGetIntegerv")
glGetIntegerv := w.context.getProcAddress("glGetIntegerv")
var count int32
_, _, _ = purego.SyscallN(glGetIntegerv, GL_NUM_EXTENSIONS, uintptr(unsafe.Pointer(&count)))
glGetStringi := window.context.getProcAddress("glGetStringi")
glGetStringi := w.context.getProcAddress("glGetStringi")
for i := 0; i < int(count); i++ {
r, _, _ := purego.SyscallN(glGetStringi, GL_EXTENSIONS, uintptr(i))
if r == 0 {
@@ -569,7 +551,7 @@ func ExtensionSupported(extension string) (bool, error) {
} else {
// Check if extension is in the old style OpenGL extensions string
glGetString := window.context.getProcAddress("glGetString")
glGetString := w.context.getProcAddress("glGetString")
r, _, _ := purego.SyscallN(glGetString, GL_EXTENSIONS)
if r == 0 {
return false, fmt.Errorf("glfw: extension string retrieval is broken: %w", PlatformError)
@@ -584,7 +566,7 @@ func ExtensionSupported(extension string) (bool, error) {
}
// Check if extension is in the platform-specific string
return window.context.extensionSupported(extension), nil
return w.context.extensionSupported(extension), nil
}
// bytePtrToString takes a pointer to a sequence of text and returns the corresponding string.
@@ -605,6 +587,5 @@ func bytePtrToString(p *byte) string {
ptr = unsafe.Add(ptr, 1)
}
// unsafe.String(p, n) is available as of Go 1.20.
return string(unsafe.Slice(p, n))
return unsafe.String(p, n)
}
+63 -39
View File
@@ -66,13 +66,30 @@ static int getEGLConfigAttrib(EGLConfig config, int attrib)
// Return the EGLConfig most closely matching the specified hints
//
static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* desired,
const _GLFWfbconfig* fbconfig,
EGLConfig* result)
{
EGLConfig* nativeConfigs;
_GLFWfbconfig* usableConfigs;
const _GLFWfbconfig* closest;
int i, nativeCount, usableCount;
int i, nativeCount, usableCount, apiBit;
GLFWbool wrongApiAvailable = GLFW_FALSE;
if (ctxconfig->client == GLFW_OPENGL_ES_API)
{
if (ctxconfig->major == 1)
apiBit = EGL_OPENGL_ES_BIT;
else
apiBit = EGL_OPENGL_ES2_BIT;
}
else
apiBit = EGL_OPENGL_BIT;
if (fbconfig->stereo)
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE, "EGL: Stereo rendering not supported");
return GLFW_FALSE;
}
eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
if (!nativeCount)
@@ -109,7 +126,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
if (!vi.visualid)
continue;
if (desired->transparent)
if (fbconfig->transparent)
{
int count;
XVisualInfo* vis =
@@ -123,23 +140,10 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
}
#endif // _GLFW_X11
if (ctxconfig->client == GLFW_OPENGL_ES_API)
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & apiBit))
{
if (ctxconfig->major == 1)
{
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))
continue;
}
else
{
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))
continue;
}
}
else if (ctxconfig->client == GLFW_OPENGL_API)
{
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
continue;
wrongApiAvailable = GLFW_TRUE;
continue;
}
u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE);
@@ -151,15 +155,44 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE);
u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);
u->doublebuffer = desired->doublebuffer;
u->doublebuffer = fbconfig->doublebuffer;
u->handle = (uintptr_t) n;
usableCount++;
}
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount);
if (closest)
*result = (EGLConfig) closest->handle;
else
{
if (wrongApiAvailable)
{
if (ctxconfig->client == GLFW_OPENGL_ES_API)
{
if (ctxconfig->major == 1)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to find support for OpenGL ES 1.x");
}
else
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to find support for OpenGL ES 2 or later");
}
}
else
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"EGL: Failed to find support for OpenGL");
}
}
else
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"EGL: Failed to find a suitable EGLConfig");
}
}
free(nativeConfigs);
free(usableConfigs);
@@ -211,7 +244,7 @@ static void swapBuffersEGL(_GLFWwindow* window)
eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
}
static void swapIntervalEGL(int interval)
static void swapIntervalEGL(_GLFWwindow* window, int interval)
{
eglSwapInterval(_glfw.egl.display, interval);
}
@@ -231,6 +264,7 @@ static int extensionSupportedEGL(const char* extension)
static GLFWglproc getProcAddressEGL(const char* procname)
{
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
assert(window != NULL);
if (window->context.egl.client)
{
@@ -454,11 +488,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
share = ctxconfig->share->context.egl.handle;
if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"EGL: Failed to find a suitable EGLConfig");
return GLFW_FALSE;
}
if (ctxconfig->client == GLFW_OPENGL_ES_API)
{
@@ -515,18 +545,18 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
}
if (ctxconfig->noerror)
{
if (_glfw.egl.KHR_create_context_no_error)
setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
}
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{
setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
}
if (ctxconfig->noerror)
{
if (_glfw.egl.KHR_create_context_no_error)
setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
}
if (mask)
setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
@@ -578,9 +608,6 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
if (!fbconfig->doublebuffer)
setAttrib(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
if (_glfw.egl.EXT_present_opaque)
setAttrib(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent);
setAttrib(EGL_NONE, EGL_NONE);
window->context.egl.surface =
@@ -640,6 +667,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
#elif defined(__OpenBSD__) || defined(__NetBSD__)
"libGL.so",
#else
"libOpenGL.so.0",
"libGL.so.1",
#endif
NULL
@@ -702,11 +730,7 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
const long vimask = VisualScreenMask | VisualIDMask;
if (!chooseEGLConfig(ctxconfig, fbconfig, &native))
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"EGL: Failed to find a suitable EGLConfig");
return GLFW_FALSE;
}
eglGetConfigAttrib(_glfw.egl.display, native,
EGL_NATIVE_VISUAL_ID, &visualID);
+1
View File
@@ -11,6 +11,7 @@ package glfw
//
// void goErrorCB(int code, char* desc);
//
// #cgo noescape glfwSetErrorCallbackCB
// static void glfwSetErrorCallbackCB() {
// glfwSetErrorCallback((GLFWerrorfun)goErrorCB);
// }
+53 -41
View File
@@ -249,7 +249,7 @@ extern "C" {
* release is made that does not contain any API changes.
* @ingroup init
*/
#define GLFW_VERSION_REVISION 8
#define GLFW_VERSION_REVISION 10
/*! @} */
/*! @brief One.
@@ -296,8 +296,12 @@ extern "C" {
#define GLFW_REPEAT 2
/*! @} */
/*! @defgroup keys Keyboard keys
* @brief Keyboard key IDs.
/*! @ingroup input
*/
#define GLFW_KEY_UNKNOWN -1
/*! @defgroup keys Keyboard key tokens
* @brief Keyboard key tokens.
*
* See [key input](@ref input_key) for how these are used.
*
@@ -320,8 +324,6 @@ extern "C" {
* @{
*/
/* The unknown key */
#define GLFW_KEY_UNKNOWN -1
/* Printable keys */
#define GLFW_KEY_SPACE 32
@@ -1590,6 +1592,14 @@ typedef struct GLFWimage
* bundle, if present. This can be disabled with the @ref
* GLFW_COCOA_CHDIR_RESOURCES init hint.
*
* @remark @macos This function will create the main menu and dock icon for the
* application. If GLFW finds a `MainMenu.nib` it is loaded and assumed to
* contain a menu bar. Otherwise a minimal menu bar is created manually with
* common commands like Hide, Quit and About. The About entry opens a minimal
* about dialog with information from the application's bundle. The menu bar
* and dock icon can be disabled entirely with the @ref GLFW_COCOA_MENUBAR init
* hint.
*
* @remark @x11 This function will set the `LC_CTYPE` category of the
* application locale according to the current environment if that category is
* still "C". This is because the "C" locale breaks Unicode text input.
@@ -2410,8 +2420,8 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref
* GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref
* GLFW_PLATFORM_ERROR.
* GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE, @ref
* GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.
*
* @remark @win32 Window creation will fail if the Microsoft GDI software
* OpenGL implementation is the only one available.
@@ -2437,13 +2447,6 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
* [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
* in the Mac Developer Library.
*
* @remark @macos The first time a window is created the menu bar is created.
* If GLFW finds a `MainMenu.nib` it is loaded and assumed to contain a menu
* bar. Otherwise a minimal menu bar is created manually with common commands
* like Hide, Quit and About. The About entry opens a minimal about dialog
* with information from the application's bundle. Menu bar creation can be
* disabled entirely with the @ref GLFW_COCOA_MENUBAR init hint.
*
* @remark @macos On OS X 10.10 and later the window frame will not be rendered
* at full resolution on Retina displays unless the
* [GLFW_COCOA_RETINA_FRAMEBUFFER](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint)
@@ -3360,11 +3363,15 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
* @param[in] value `GLFW_TRUE` or `GLFW_FALSE`.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
* GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_PLATFORM_ERROR.
*
* @remark Calling @ref glfwGetWindowAttrib will always return the latest
* value, even if that value is ignored by the current mode of the window.
*
* @remark @wayland The [GLFW_FLOATING](@ref GLFW_FLOATING_attrib) window
* attribute is not supported. Setting this will emit @ref
* GLFW_PLATFORM_ERROR.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_attribs
@@ -4039,8 +4046,8 @@ GLFWAPI int glfwRawMouseMotionSupported(void);
* @param[in] scancode The scancode of the key to query.
* @return The UTF-8 encoded, layout-specific name of the key, or `NULL`.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_INVALID_VALUE, @ref GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
*
* @remark The contents of the returned string may change when a keyboard
* layout change event is received.
@@ -4062,15 +4069,18 @@ GLFWAPI const char* glfwGetKeyName(int key, int scancode);
*
* This function returns the platform-specific scancode of the specified key.
*
* If the key is `GLFW_KEY_UNKNOWN` or does not exist on the keyboard this
* method will return `-1`.
* If the specified [key token](@ref keys) corresponds to a physical key not
* supported on the current platform then this method will return `-1`.
* Calling this function with anything other than a key token will return `-1`
* and generate a @ref GLFW_INVALID_ENUM error.
*
* @param[in] key Any [named key](@ref keys).
* @return The platform-specific scancode for the key, or `-1` if an
* [error](@ref error_handling) occurred.
* @param[in] key Any [key token](@ref keys).
* @return The platform-specific scancode for the key, or `-1` if the key is
* not supported on the current platform or an [error](@ref error_handling)
* occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_INVALID_ENUM.
*
* @thread_safety This function may be called from any thread.
*
@@ -4354,10 +4364,9 @@ GLFWAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor);
* [character callback](@ref glfwSetCharCallback) instead.
*
* When a window loses input focus, it will generate synthetic key release
* events for all pressed keys. You can tell these events from user-generated
* events by the fact that the synthetic ones are generated after the focus
* loss event has been processed, i.e. after the
* [window focus callback](@ref glfwSetWindowFocusCallback) has been called.
* events for all pressed keys with associated key tokens. You can tell these
* events from user-generated events by the fact that the synthetic ones are
* generated after the focus loss event has been processed, i.e. after the
*
* The scancode of a key is specific to that platform or sometimes even to that
* machine. Scancodes are intended to allow users to bind keys that don't have
@@ -4708,12 +4717,15 @@ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window);
* thread.
*
* This function makes the OpenGL or OpenGL ES context of the specified window
* current on the calling thread. A context must only be made current on
* a single thread at a time and each thread can have only a single current
* context at a time.
* current on the calling thread. It can also detach the current context from
* the calling thread without making a new one current by passing in `NULL`.
*
* When moving a context between threads, you must make it non-current on the
* old thread before making it current on the new one.
* A context must only be made current on a single thread at a time and each
* thread can have only a single current context at a time. Making a context
* current detaches any previously current context on the calling thread.
*
* When moving a context between threads, you must detach it (make it
* non-current) on the old thread before making it current on the new one.
*
* By default, making a context non-current implicitly forces a pipeline flush.
* On machines that support `GL_KHR_context_flush_control`, you can control
@@ -4728,6 +4740,10 @@ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window);
* @param[in] window The window whose context to make current, or `NULL` to
* detach the current context.
*
* @remarks If the previously current context was created via a different
* context creation API than the one passed to this function, GLFW will still
* detach the previous one from its API before making the new one current.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.
*
@@ -4808,9 +4824,7 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* window);
* arrives a little bit late. You can check for these extensions with @ref
* glfwExtensionSupported.
*
* A context must be current on the calling thread. Calling this function
* without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
*
* @param[in] window The window whose context to make current.
* @param[in] interval The minimum number of screen updates to wait for
* until the buffers are swapped by @ref glfwSwapBuffers.
*
@@ -4835,7 +4849,7 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* window);
*
* @ingroup context
*/
GLFWAPI void glfwSwapInterval(int interval);
GLFWAPI void glfwSwapInterval(GLFWwindow* window, int interval);
/*! @brief Returns whether the specified extension is available.
*
@@ -4844,14 +4858,12 @@ GLFWAPI void glfwSwapInterval(int interval);
* OpenGL ES context. It searches both for client API extension and context
* creation API extensions.
*
* A context must be current on the calling thread. Calling this function
* without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
*
* As this functions retrieves and searches one or more extension strings each
* call, it is recommended that you cache its results if it is going to be used
* frequently. The extension strings will not change during the lifetime of
* a context, so there is no danger in doing this.
*
* @param[in] window The window whose context to make current.
* @param[in] extension The ASCII encoded name of the extension.
* @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE`
* otherwise.
@@ -4869,7 +4881,7 @@ GLFWAPI void glfwSwapInterval(int interval);
*
* @ingroup context
*/
GLFWAPI int glfwExtensionSupported(const char* extension);
GLFWAPI int glfwExtensionSupported(GLFWwindow* window, const char* extension);
/*! @brief Returns the address of the specified function for the current
* context.
+3 -1
View File
@@ -99,7 +99,9 @@ extern "C" {
#include <ApplicationServices/ApplicationServices.h>
#include <objc/objc.h>
#endif
#elif defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX)
#endif
#if defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX)
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
#endif
-33
View File
@@ -16,13 +16,6 @@ import (
"unsafe"
)
// Version constants.
const (
VersionMajor = C.GLFW_VERSION_MAJOR // This is incremented when the API is changed in non-compatible ways.
VersionMinor = C.GLFW_VERSION_MINOR // This is incremented when features are added to the API but it remains backward-compatible.
VersionRevision = C.GLFW_VERSION_REVISION // This is incremented when a bug fix release is made that does not contain any API changes.
)
// Init initializes the GLFW library. Before most GLFW functions can be used,
// GLFW must be initialized, and before a program terminates GLFW should be
// terminated in order to free any resources allocated during or after
@@ -83,32 +76,6 @@ func InitHint(hint Hint, value int) {
C.glfwInitHint(C.int(hint), C.int(value))
}
// GetVersion retrieves the major, minor and revision numbers of the GLFW
// library. It is intended for when you are using GLFW as a shared library and
// want to ensure that you are using the minimum required version.
//
// This function may be called before Init.
func GetVersion() (major, minor, revision int) {
var (
maj C.int
min C.int
rev C.int
)
C.glfwGetVersion(&maj, &min, &rev)
return int(maj), int(min), int(rev)
}
// GetVersionString returns a static string generated at compile-time according
// to which configuration macros were defined. This is intended for use when
// submitting bug reports, to allow developers to see which code paths are
// enabled in a binary.
//
// This function may be called before Init.
func GetVersionString() string {
return C.GoString(C.glfwGetVersionString())
}
// GetClipboardString returns the contents of the system clipboard, if it
// contains or is convertible to a UTF-8 encoded string.
//
@@ -165,10 +165,8 @@ static void swapBuffersGLX(_GLFWwindow* window)
glXSwapBuffers(_glfw.x11.display, window->context.glx.window);
}
static void swapIntervalGLX(int interval)
static void swapIntervalGLX(_GLFWwindow* window, int interval)
{
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (_glfw.glx.EXT_swap_control)
{
_glfw.glx.SwapIntervalEXT(_glfw.x11.display,
@@ -204,7 +202,10 @@ static GLFWglproc getProcAddressGLX(const char* procname)
else if (_glfw.glx.GetProcAddressARB)
return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
else
{
// NOTE: glvnd provides GLX 1.4, so this can only happen with libGL
return _glfw_dlsym(_glfw.glx.handle, procname);
}
}
static void destroyContextGLX(_GLFWwindow* window)
@@ -107,7 +107,6 @@ typedef struct _GLFWlibraryGLX
int eventBase;
int errorBase;
// dlopen handle for libGL.so.1
void* handle;
// GLX 1.3 functions
-15
View File
@@ -340,21 +340,6 @@ GLFWAPI void glfwInitHint(int hint, int value)
"Invalid init hint 0x%08X", hint);
}
GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
{
if (major != NULL)
*major = GLFW_VERSION_MAJOR;
if (minor != NULL)
*minor = GLFW_VERSION_MINOR;
if (rev != NULL)
*rev = GLFW_VERSION_REVISION;
}
GLFWAPI const char* glfwGetVersionString(void)
{
return _glfwPlatformGetVersionString();
}
GLFWAPI int glfwGetError(const char** description)
{
_GLFWerror* error;
+8 -2
View File
@@ -280,6 +280,12 @@ GLFWAPI const char* glfwGetKeyName(int key, int scancode)
if (key != GLFW_KEY_UNKNOWN)
{
if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
{
_glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
return NULL;
}
if (key != GLFW_KEY_KP_EQUAL &&
(key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) &&
(key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_WORLD_2))
@@ -295,12 +301,12 @@ GLFWAPI const char* glfwGetKeyName(int key, int scancode)
GLFWAPI int glfwGetKeyScancode(int key)
{
_GLFW_REQUIRE_INIT_OR_RETURN(-1);
_GLFW_REQUIRE_INIT_OR_RETURN(0);
if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
{
_glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
return GLFW_RELEASE;
return -1;
}
return _glfwPlatformGetKeyScancode(key);
+8
View File
@@ -19,34 +19,42 @@ package glfw
// void goScrollCB(void* window, double xoff, double yoff);
// void goDropCB(void* window, int count, char** names);
//
// #cgo noescape glfwSetKeyCallbackCB
// static void glfwSetKeyCallbackCB(GLFWwindow *window) {
// glfwSetKeyCallback(window, (GLFWkeyfun)goKeyCB);
// }
//
// #cgo noescape glfwSetCharCallbackCB
// static void glfwSetCharCallbackCB(GLFWwindow *window) {
// glfwSetCharCallback(window, (GLFWcharfun)goCharCB);
// }
//
// #cgo noescape glfwSetCharModsCallbackCB
// static void glfwSetCharModsCallbackCB(GLFWwindow *window) {
// glfwSetCharModsCallback(window, (GLFWcharmodsfun)goCharModsCB);
// }
//
// #cgo noescape glfwSetMouseButtonCallbackCB
// static void glfwSetMouseButtonCallbackCB(GLFWwindow *window) {
// glfwSetMouseButtonCallback(window, (GLFWmousebuttonfun)goMouseButtonCB);
// }
//
// #cgo noescape glfwSetCursorPosCallbackCB
// static void glfwSetCursorPosCallbackCB(GLFWwindow *window) {
// glfwSetCursorPosCallback(window, (GLFWcursorposfun)goCursorPosCB);
// }
//
// #cgo noescape glfwSetCursorEnterCallbackCB
// static void glfwSetCursorEnterCallbackCB(GLFWwindow *window) {
// glfwSetCursorEnterCallback(window, (GLFWcursorenterfun)goCursorEnterCB);
// }
//
// #cgo noescape glfwSetScrollCallbackCB
// static void glfwSetScrollCallbackCB(GLFWwindow *window) {
// glfwSetScrollCallback(window, (GLFWscrollfun)goScrollCB);
// }
//
// #cgo noescape glfwSetDropCallbackCB
// static void glfwSetDropCallbackCB(GLFWwindow *window) {
// glfwSetDropCallback(window, (GLFWdropfun)goDropCB);
// }
@@ -246,6 +246,9 @@ func GetKeyName(key Key, scancode int) (string, error) {
}
if key != KeyUnknown {
if key < KeySpace || key > KeyLast {
return "", fmt.Errorf("glfw: invalid key %d: %w", key, InvalidEnum)
}
if key != KeyKPEqual && (key < KeyKP0 || key > KeyKPAdd) && (key < KeyApostrophe || key > KeyWorld2) {
return "", nil
}
+1 -1
View File
@@ -55,7 +55,7 @@ typedef struct _GLFWmutex _GLFWmutex;
typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*);
typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*);
typedef void (* _GLFWswapintervalfun)(int);
typedef void (* _GLFWswapintervalfun)(_GLFWwindow*, int);
typedef int (* _GLFWextensionsupportedfun)(const char*);
typedef GLFWglproc (* _GLFWgetprocaddressfun)(const char*);
typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);
+1 -1
View File
@@ -87,7 +87,7 @@ type context struct {
// TODO: Put these functions in an interface type.
makeCurrent func(*Window) error
swapBuffers func(*Window) error
swapInterval func(int) error
swapInterval func(*Window, int) error
extensionSupported func(string) bool
getProcAddress func(string) uintptr
destroy func(*Window) error
@@ -11,22 +11,31 @@ package glfw
//
// void goMonitorCB(void* monitor, int event);
//
// #cgo noescape GetMonitorAtIndex
// #cgo nocallback GetMonitorAtIndex
// static GLFWmonitor *GetMonitorAtIndex(GLFWmonitor **monitors, int index) {
// return monitors[index];
// }
//
// #cgo noescape GetVidmodeAtIndex
// #cgo nocallback GetVidmodeAtIndex
// static GLFWvidmode GetVidmodeAtIndex(GLFWvidmode *vidmodes, int index) {
// return vidmodes[index];
// }
//
// #cgo noescape glfwSetMonitorCallbackCB
// static void glfwSetMonitorCallbackCB() {
// glfwSetMonitorCallback((GLFWmonitorfun)goMonitorCB);
// }
//
// #cgo noescape GetGammaAtIndex
// #cgo nocallback GetGammaAtIndex
// static unsigned int GetGammaAtIndex(unsigned short *color, int i) {
// return color[i];
// }
//
// #cgo noescape SetGammaAtIndex
// #cgo nocallback SetGammaAtIndex
// static void SetGammaAtIndex(unsigned short *color, int i, unsigned short value) {
// color[i] = value;
// }
@@ -12,9 +12,14 @@ package glfw
// workaround wrappers needed due to a cgo and/or LLVM bug.
// See: https://github.com/go-gl/glfw/issues/136
#cgo noescape workaround_glfwGetCocoaWindow
#cgo nocallback workaround_glfwGetCocoaWindow
static void *workaround_glfwGetCocoaWindow(GLFWwindow *w) {
return (void *)glfwGetCocoaWindow(w);
}
#cgo noescape workaround_glfwGetNSGLContext
#cgo nocallback workaround_glfwGetNSGLContext
static void *workaround_glfwGetNSGLContext(GLFWwindow *w) {
return (void *)glfwGetNSGLContext(w);
}
@@ -52,16 +52,12 @@ static void swapBuffersNSGL(_GLFWwindow* window)
} // autoreleasepool
}
static void swapIntervalNSGL(int interval)
static void swapIntervalNSGL(_GLFWwindow* window, int interval)
{
@autoreleasepool {
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (window)
{
[window->context.nsgl.object setValues:&interval
forParameter:NSOpenGLContextParameterSwapInterval];
}
[window->context.nsgl.object setValues:&interval
forParameter:NSOpenGLContextParameterSwapInterval];
} // autoreleasepool
}
@@ -138,7 +134,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
if (ctxconfig->client == GLFW_OPENGL_ES_API)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"NSGL: OpenGL ES is not available on macOS");
"NSGL: OpenGL ES is not available via NSGL");
return GLFW_FALSE;
}
@@ -5,13 +5,12 @@
//go:build darwin || freebsd || linux || netbsd || openbsd
#include "internal_unix.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "internal_unix.h"
static void makeContextCurrentOSMesa(_GLFWwindow* window)
{
if (window)
@@ -72,7 +71,7 @@ static void swapBuffersOSMesa(_GLFWwindow* window)
// No double buffering on OSMesa
}
static void swapIntervalOSMesa(int interval)
static void swapIntervalOSMesa(_GLFWwindow* window, int interval)
{
// No swap interval on OSMesa
}
@@ -19,8 +19,9 @@ func _glfwPlatformCreateTls(tls *C._GLFWtls) C.GLFWbool {
panic("glfw: TLS must not be allocated")
}
if pthread_key_create(&tls.posix.key, 0) != 0 {
_glfwInputError(int32(PlatformError),
C.CString("POSIX: Failed to create context TLS"))
errstr := C.CString("POSIX: Failed to create context TLS")
defer C.free(unsafe.Pointer(errstr))
_glfwInputError(int32(PlatformError), errstr)
return False
}
tls.posix.allocated = True
@@ -58,7 +59,9 @@ func _glfwPlatformCreateMutex(mutex *C._GLFWmutex) C.GLFWbool {
panic("glfw: mutex must not be allocated")
}
if pthread_mutex_init(&mutex.posix.handle, nil) != 0 {
_glfwInputError(int32(PlatformError), C.CString("POSIX: Failed to create mutex"))
errstr := C.CString("POSIX: Failed to create mutex")
defer C.free(unsafe.Pointer(errstr))
_glfwInputError(int32(PlatformError), errstr)
return False
}
mutex.posix.allocated = True
+16 -15
View File
@@ -53,10 +53,23 @@ func (w *Window) choosePixelFormat(ctxconfig *ctxconfig, fbconfig_ *fbconfig) (i
var nativeCount int32
var attribs []int32
c, err := _DescribePixelFormat(w.context.platform.dc, 1, uint32(unsafe.Sizeof(_PIXELFORMATDESCRIPTOR{})), nil)
if err != nil {
return 0, err
}
nativeCount = c
if _glfw.platformContext.ARB_pixel_format {
// NOTE: In a Parallels VM WGL_ARB_pixel_format returns fewer pixel formats than
// DescribePixelFormat, violating the guarantees of the extension spec
// HACK: Iterate through the minimum of both counts
var attrib int32 = _WGL_NUMBER_PIXEL_FORMATS_ARB
if err := wglGetPixelFormatAttribivARB(w.context.platform.dc, 1, 0, 1, &attrib, &nativeCount); err != nil {
return 0, err
var extensionCount int32
if err := wglGetPixelFormatAttribivARB(w.context.platform.dc, 1, 0, 1, &attrib, &extensionCount); err != nil {
return 0, fmt.Errorf("glfw: WGL: failed to retrieve pixel format attribute: %w", err)
}
if nativeCount > extensionCount {
nativeCount = extensionCount
}
attribs = append(attribs,
@@ -96,12 +109,6 @@ func (w *Window) choosePixelFormat(ctxconfig *ctxconfig, fbconfig_ *fbconfig) (i
attribs = append(attribs, _WGL_COLORSPACE_EXT)
}
}
} else {
c, err := _DescribePixelFormat(w.context.platform.dc, 1, uint32(unsafe.Sizeof(_PIXELFORMATDESCRIPTOR{})), nil)
if err != nil {
return 0, err
}
nativeCount = c
}
usableConfigs := make([]*fbconfig, 0, nativeCount)
@@ -281,13 +288,7 @@ func swapBuffersWGL(window *Window) error {
return nil
}
func swapIntervalWGL(interval int) error {
ptr, err := _glfw.contextSlot.get()
if err != nil {
return err
}
window := (*Window)(unsafe.Pointer(ptr))
func swapIntervalWGL(window *Window, interval int) error {
window.context.platform.interval = interval
if window.monitor == nil && winver.IsWindowsVistaOrGreater() {
@@ -239,6 +239,55 @@ func createHelperWindow() error {
return nil
}
func createBlankCursor() error {
// HACK: Create a transparent cursor as using the NULL cursor breaks
// using SetCursorPos when connected over RDP
cursorWidth, err := _GetSystemMetrics(_SM_CXCURSOR)
if err != nil {
return err
}
cursorHeight, err := _GetSystemMetrics(_SM_CYCURSOR)
if err != nil {
return err
}
andMask := make([]byte, cursorWidth*cursorHeight/8)
for i := range andMask {
andMask[i] = 0xff
}
xorMask := make([]byte, cursorWidth*cursorHeight/8)
// Cursor creation might fail, but that's fine as we get NULL in that case,
// which serves as an acceptable fallback blank cursor (other than on RDP)
c, _ := _CreateCursor(0, 0, 0, cursorWidth, cursorHeight, andMask, xorMask)
_glfw.platformWindow.blankCursor = c
return nil
}
func initRemoteSession() error {
if microsoftgdk.IsXbox() {
return nil
}
// Check if the current progress was started with Remote Desktop.
r, err := _GetSystemMetrics(_SM_REMOTESESSION)
if err != nil {
return err
}
_glfw.platformWindow.isRemoteSession = r > 0
// With Remote desktop, we need to create a blank cursor because of the cursor is Set to nil
// if cannot be moved to center in capture mode. If not Remote Desktop platformWindow.blankCursor stays nil
// and will perform has before (normal).
if _glfw.platformWindow.isRemoteSession {
if err := createBlankCursor(); err != nil {
return err
}
}
return nil
}
func platformInit() error {
// Changing the foreground lock timeout was removed from the original code.
// See https://github.com/glfw/glfw/commit/58b48a3a00d9c2a5ca10cc23069a71d8773cc7a4
@@ -293,6 +342,10 @@ func platformInit() error {
return err
}
} else {
// Some hacks are needed to support Remote Desktop...
if err := initRemoteSession(); err != nil {
return err
}
if err := pollMonitorsWin32(); err != nil {
return err
}
@@ -301,6 +354,12 @@ func platformInit() error {
}
func platformTerminate() error {
if _glfw.platformWindow.blankCursor != 0 {
if err := _DestroyCursor(_glfw.platformWindow.blankCursor); err != nil {
return err
}
}
if _glfw.platformWindow.deviceNotificationHandle != 0 {
if err := _UnregisterDeviceNotification(_glfw.platformWindow.deviceNotificationHandle); err != nil {
return err
@@ -66,12 +66,18 @@ type platformLibraryWindowState struct {
scancodes [KeyLast + 1]int
keynames [KeyLast + 1]string
// Where to place the cursor when re-enabled
// restoreCursorPosX and restoreCursorPosY indicates where to place the cursor when re-enabled
restoreCursorPosX float64
restoreCursorPosY float64
// The window whose disabled cursor mode is active
// disabledCursorWindow is the window whose disabled cursor mode is active
disabledCursorWindow *Window
// capturedCursorWindow is the window the cursor is captured in
capturedCursorWindow *Window
rawInput []byte
mouseTrailSize uint32
// isRemoteSession indicates if the process was started behind Remote Destop
isRemoteSession bool
// blankCursor is an invisible cursor, needed for special cases (see WM_INPUT handler)
blankCursor _HCURSOR
}
+174 -96
View File
@@ -127,48 +127,29 @@ func createIcon(image *Image, xhot, yhot int, icon bool) (_HICON, error) {
return handle, nil
}
func getFullWindowSize(style uint32, exStyle uint32, contentWidth, contentHeight int, dpi uint32) (fullWidth, fullHeight int, err error) {
if microsoftgdk.IsXbox() {
return contentWidth, contentHeight, nil
}
func (w *Window) applyAspectRatio(edge int, area *_RECT) error {
var frame _RECT
ratio := float32(w.numer) / float32(w.denom)
style := w.getWindowStyle()
exStyle := w.getWindowExStyle()
rect := _RECT{
left: 0,
top: 0,
right: int32(contentWidth),
bottom: int32(contentHeight),
}
if winver.IsWindows10AnniversaryUpdateOrGreater() {
if err := _AdjustWindowRectExForDpi(&rect, style, false, exStyle, dpi); err != nil {
return 0, 0, err
if err := _AdjustWindowRectExForDpi(&frame, style, false, exStyle, _GetDpiForWindow(w.platform.handle)); err != nil {
return err
}
} else {
if err := _AdjustWindowRectEx(&rect, style, false, exStyle); err != nil {
return 0, 0, err
if err := _AdjustWindowRectEx(&frame, style, false, exStyle); err != nil {
return err
}
}
return int(rect.right - rect.left), int(rect.bottom - rect.top), nil
}
func (w *Window) applyAspectRatio(edge int, area *_RECT) error {
ratio := float32(w.numer) / float32(w.denom)
var dpi uint32 = _USER_DEFAULT_SCREEN_DPI
if winver.IsWindows10AnniversaryUpdateOrGreater() {
dpi = _GetDpiForWindow(w.platform.handle)
}
xoff, yoff, err := getFullWindowSize(w.getWindowStyle(), w.getWindowExStyle(), 0, 0, dpi)
if err != nil {
return err
}
if edge == _WMSZ_LEFT || edge == _WMSZ_BOTTOMLEFT || edge == _WMSZ_RIGHT || edge == _WMSZ_BOTTOMRIGHT {
area.bottom = area.top + int32(yoff) + int32(float32(area.right-area.left-int32(xoff))/ratio)
area.bottom = area.top + int32(frame.bottom-frame.top) + int32(float32(area.right-area.left-int32(frame.right-frame.left))/ratio)
} else if edge == _WMSZ_TOPLEFT || edge == _WMSZ_TOPRIGHT {
area.top = area.bottom - int32(yoff) - int32(float32(area.right-area.left-int32(xoff))/ratio)
area.top = area.bottom - int32(frame.bottom-frame.top) - int32(float32(area.right-area.left-int32(frame.right-frame.left))/ratio)
} else if edge == _WMSZ_TOP || edge == _WMSZ_BOTTOM {
area.right = area.left + int32(xoff) + int32(float32(area.bottom-area.top-int32(yoff))*ratio)
area.right = area.left + int32(frame.right-frame.left) + int32(float32(area.bottom-area.top-int32(frame.bottom-frame.top))*ratio)
}
return nil
@@ -186,7 +167,10 @@ func (w *Window) updateCursorImage() error {
_SetCursor(cursor)
}
} else {
_SetCursor(0)
// Connected via Remote Desktop, nil cursor will present SetCursorPos the move the cursor.
// using a blank cursor fix that.
// When not via Remote Desktop, platformWindow.blankCursor should be nil.
_SetCursor(_glfw.platformWindow.blankCursor)
}
return nil
}
@@ -214,26 +198,35 @@ func (w *Window) clientToScreen(rect _RECT) (_RECT, error) {
return rect, nil
}
func updateClipRect(window *Window) error {
if window != nil {
clipRect, err := _GetClientRect(window.platform.handle)
if err != nil {
return err
}
clipRect, err = window.clientToScreen(clipRect)
if err != nil {
return err
}
if err := _ClipCursor(&clipRect); err != nil {
return err
}
} else {
if err := _ClipCursor(nil); err != nil {
return err
}
func captureCursor(window *Window) error {
if microsoftgdk.IsXbox() {
return nil
}
clipRect, err := _GetClientRect(window.platform.handle)
if err != nil {
return err
}
clipRect, err = window.clientToScreen(clipRect)
if err != nil {
return err
}
if err := _ClipCursor(&clipRect); err != nil {
return err
}
_glfw.platformWindow.capturedCursorWindow = window
return nil
}
func releaseCursor() error {
if microsoftgdk.IsXbox() {
return nil
}
if err := _ClipCursor(nil); err != nil {
return err
}
_glfw.platformWindow.capturedCursorWindow = nil
return nil
}
@@ -274,7 +267,7 @@ func (w *Window) disableCursor() error {
if err := w.centerCursorInContentArea(); err != nil {
return err
}
if err := updateClipRect(w); err != nil {
if err := captureCursor(w); err != nil {
return err
}
if w.rawMouseMotion {
@@ -292,7 +285,7 @@ func (w *Window) enableCursor() error {
}
}
_glfw.platformWindow.disabledCursorWindow = nil
if err := updateClipRect(nil); err != nil {
if err := releaseCursor(); err != nil {
return err
}
if err := w.platformSetCursorPos(_glfw.platformWindow.restoreCursorPosX, _glfw.platformWindow.restoreCursorPosY); err != nil {
@@ -925,8 +918,46 @@ func windowProc(hWnd windows.HWND, uMsg uint32, wParam _WPARAM, lParam _LPARAM)
var dx, dy int
data := (*_RAWINPUT)(unsafe.Pointer(&_glfw.platformWindow.rawInput[0]))
if data.mouse.usFlags&_MOUSE_MOVE_ABSOLUTE != 0 {
dx = int(data.mouse.lLastX) - window.platform.lastCursorPosX
dy = int(data.mouse.lLastY) - window.platform.lastCursorPosY
if _glfw.platformWindow.isRemoteSession {
// Remote Desktop Mode
// As per https://github.com/Microsoft/DirectXTK/commit/ef56b63f3739381e451f7a5a5bd2c9779d2a7555
// MOUSE_MOVE_ABSOLUTE is a range from 0 through 65535, based on the screen size.
// Apparently, absolute mode only occurs over RDP though.
var smx int32 = _SM_CXSCREEN
var smy int32 = _SM_CYSCREEN
if data.mouse.usFlags&_MOUSE_VIRTUAL_DESKTOP != 0 {
smx = _SM_CXVIRTUALSCREEN
smy = _SM_CYVIRTUALSCREEN
}
width, err := _GetSystemMetrics(smx)
if err != nil {
_glfw.errors = append(_glfw.errors, err)
return 0
}
height, err := _GetSystemMetrics(smy)
if err != nil {
_glfw.errors = append(_glfw.errors, err)
return 0
}
pos := _POINT{
x: int32(float64(data.mouse.lLastX) / 65535.0 * float64(width)),
y: int32(float64(data.mouse.lLastY) / 65535.0 * float64(height)),
}
if err := _ScreenToClient(window.platform.handle, &pos); err != nil {
_glfw.errors = append(_glfw.errors, err)
return 0
}
dx = int(pos.x) - window.platform.lastCursorPosX
dy = int(pos.y) - window.platform.lastCursorPosY
} else {
// Normal mode
// We should have the right absolute coords in data.mouse
dx = int(data.mouse.lLastX) - window.platform.lastCursorPosX
dy = int(data.mouse.lLastY) - window.platform.lastCursorPosY
}
} else {
dx = int(data.mouse.lLastX)
dy = int(data.mouse.lLastY)
@@ -986,8 +1017,8 @@ func windowProc(hWnd windows.HWND, uMsg uint32, wParam _WPARAM, lParam _LPARAM)
iconified := wParam == _SIZE_MINIMIZED
maximized := wParam == _SIZE_MAXIMIZED || (window.platform.maximized && wParam != _SIZE_RESTORED)
if _glfw.platformWindow.disabledCursorWindow == window {
if err := updateClipRect(window); err != nil {
if _glfw.platformWindow.capturedCursorWindow == window {
if err := captureCursor(window); err != nil {
_glfw.errors = append(_glfw.errors, err)
return 0
}
@@ -1032,8 +1063,8 @@ func windowProc(hWnd windows.HWND, uMsg uint32, wParam _WPARAM, lParam _LPARAM)
return 0
case _WM_MOVE:
if _glfw.platformWindow.disabledCursorWindow == window {
if err := updateClipRect(window); err != nil {
if _glfw.platformWindow.capturedCursorWindow == window {
if err := captureCursor(window); err != nil {
_glfw.errors = append(_glfw.errors, err)
return 0
}
@@ -1056,31 +1087,35 @@ func windowProc(hWnd windows.HWND, uMsg uint32, wParam _WPARAM, lParam _LPARAM)
return 1
case _WM_GETMINMAXINFO:
var dpi uint32 = _USER_DEFAULT_SCREEN_DPI
var frame _RECT
mmi := (*_MINMAXINFO)(unsafe.Pointer(lParam))
style := window.getWindowStyle()
exStyle := window.getWindowExStyle()
if window.monitor != nil {
break
}
if winver.IsWindows10AnniversaryUpdateOrGreater() {
dpi = _GetDpiForWindow(window.platform.handle)
}
xoff, yoff, err := getFullWindowSize(window.getWindowStyle(), window.getWindowExStyle(), 0, 0, dpi)
if err != nil {
_glfw.errors = append(_glfw.errors, err)
return 0
if err := _AdjustWindowRectExForDpi(&frame, style, false, exStyle, _GetDpiForWindow(window.platform.handle)); err != nil {
_glfw.errors = append(_glfw.errors, err)
return 0
}
} else {
if err := _AdjustWindowRectEx(&frame, style, false, exStyle); err != nil {
_glfw.errors = append(_glfw.errors, err)
return 0
}
}
if window.minwidth != DontCare && window.minheight != DontCare {
mmi.ptMinTrackSize.x = int32(window.minwidth + xoff)
mmi.ptMinTrackSize.y = int32(window.minheight + yoff)
mmi.ptMinTrackSize.x = int32(window.minwidth) + (frame.right - frame.left)
mmi.ptMinTrackSize.y = int32(window.minheight) + (frame.bottom - frame.top)
}
if window.maxwidth != DontCare && window.maxheight != DontCare {
mmi.ptMaxTrackSize.x = int32(window.maxwidth + xoff)
mmi.ptMaxTrackSize.y = int32(window.maxheight + yoff)
mmi.ptMaxTrackSize.x = int32(window.maxwidth) + (frame.right - frame.left)
mmi.ptMaxTrackSize.y = int32(window.maxheight) + (frame.bottom - frame.top)
}
if !window.decorated {
@@ -1205,7 +1240,7 @@ func (w *Window) createNativeWindow(wndconfig *wndconfig, fbconfig *fbconfig) er
style := w.getWindowStyle()
exStyle := w.getWindowExStyle()
var xpos, ypos, fullWidth, fullHeight int32
var frameX, frameY, frameWidth, frameHeight int32
if w.monitor != nil {
mi, ok := _GetMonitorInfoW(w.monitor.platform.handle)
if !ok {
@@ -1214,27 +1249,29 @@ func (w *Window) createNativeWindow(wndconfig *wndconfig, fbconfig *fbconfig) er
// NOTE: This window placement is temporary and approximate, as the
// correct position and size cannot be known until the monitor
// video mode has been picked in _glfwSetVideoModeWin32
xpos = mi.rcMonitor.left
ypos = mi.rcMonitor.top
fullWidth = mi.rcMonitor.right - mi.rcMonitor.left
fullHeight = mi.rcMonitor.bottom - mi.rcMonitor.top
frameX = mi.rcMonitor.left
frameY = mi.rcMonitor.top
frameWidth = mi.rcMonitor.right - mi.rcMonitor.left
frameHeight = mi.rcMonitor.bottom - mi.rcMonitor.top
} else {
xpos = _CW_USEDEFAULT
ypos = _CW_USEDEFAULT
rect := _RECT{0, 0, int32(wndconfig.width), int32(wndconfig.height)}
w.platform.maximized = wndconfig.maximized
if wndconfig.maximized {
style |= _WS_MAXIMIZE
}
w, h, err := getFullWindowSize(style, exStyle, wndconfig.width, wndconfig.height, _USER_DEFAULT_SCREEN_DPI)
if err != nil {
if err := _AdjustWindowRectEx(&rect, style, false, exStyle); err != nil {
return err
}
fullWidth, fullHeight = int32(w), int32(h)
frameX = _CW_USEDEFAULT
frameY = _CW_USEDEFAULT
frameWidth = rect.right - rect.left
frameHeight = rect.bottom - rect.top
}
h, err := _CreateWindowExW(exStyle, _GLFW_WNDCLASSNAME, wndconfig.title, style, xpos, ypos, fullWidth, fullHeight,
h, err := _CreateWindowExW(exStyle, _GLFW_WNDCLASSNAME, wndconfig.title, style, frameX, frameY, frameWidth, frameHeight,
0, // No parent window
0, // No window menu
_glfw.platformWindow.instance, unsafe.Pointer(wndconfig))
@@ -1459,7 +1496,15 @@ func (w *Window) platformDestroyWindow() error {
}
if _glfw.platformWindow.disabledCursorWindow == w {
_glfw.platformWindow.disabledCursorWindow = nil
if err := w.enableCursor(); err != nil {
return err
}
}
if _glfw.platformWindow.capturedCursorWindow == w {
if err := releaseCursor(); err != nil {
return err
}
}
if w.platform.handle != 0 {
@@ -2163,6 +2208,7 @@ func platformPollEvents() error {
// NOTE: Re-center the cursor only if it has moved since the last call,
// to avoid breaking glfwWaitEvents with WM_MOUSEMOVE
// The re-center is required in order to prevent the mouse cursor stopping at the edges of the screen.
if window.platform.lastCursorPosX != width/2 || window.platform.lastCursorPosY != height/2 {
if err := window.platformSetCursorPos(float64(width/2), float64(height/2)); err != nil {
return err
@@ -2184,7 +2230,7 @@ func platformWaitEvents() error {
}
func platformWaitEventsTimeout(timeout float64) error {
if _, err := _MsgWaitForMultipleObjects(0, nil, false, uint32(timeout*1e3), _QS_ALLEVENTS); err != nil {
if _, err := _MsgWaitForMultipleObjects(0, nil, false, uint32(timeout*1e3), _QS_ALLINPUT); err != nil {
return err
}
if err := platformPollEvents(); err != nil {
@@ -2235,20 +2281,48 @@ func (w *Window) platformSetCursorPos(xpos, ypos float64) error {
}
func (w *Window) platformSetCursorMode(mode int) error {
if mode == CursorDisabled {
if w.platformWindowFocused() {
if err := w.disableCursor(); err != nil {
if w.platformWindowFocused() {
if mode == CursorDisabled {
xpos, ypos, err := w.platformGetCursorPos()
if err != nil {
return err
}
_glfw.platformWindow.restoreCursorPosX = xpos
_glfw.platformWindow.restoreCursorPosY = ypos
if err := w.centerCursorInContentArea(); err != nil {
return err
}
if w.rawMouseMotion {
if err := w.enableRawMouseMotion(); err != nil {
return err
}
}
} else if _glfw.platformWindow.disabledCursorWindow == w {
if w.rawMouseMotion {
if err := w.disableRawMouseMotion(); err != nil {
return err
}
}
}
if mode == CursorDisabled {
if err := captureCursor(w); err != nil {
return err
}
} else {
if err := releaseCursor(); err != nil {
return err
}
}
return nil
}
if _glfw.platformWindow.disabledCursorWindow == w {
if err := w.enableCursor(); err != nil {
return err
if mode == CursorDisabled {
_glfw.platformWindow.disabledCursorWindow = w
} else if _glfw.platformWindow.disabledCursorWindow == w {
_glfw.platformWindow.disabledCursorWindow = nil
if err := w.platformSetCursorPos(_glfw.platformWindow.restoreCursorPosX, _glfw.platformWindow.restoreCursorPosY); err != nil {
return err
}
}
return nil
}
in, err := w.cursorInContentArea()
@@ -2265,10 +2339,14 @@ func (w *Window) platformSetCursorMode(mode int) error {
}
func platformGetScancodeName(scancode int) (string, error) {
if scancode < 0 || scancode > (_KF_EXTENDED|0xff) || _glfw.platformWindow.keycodes[scancode] == KeyUnknown {
if scancode < 0 || scancode > (_KF_EXTENDED|0xff) {
return "", fmt.Errorf("glwfwin: invalid scancode %d: %w", scancode, InvalidValue)
}
return _glfw.platformWindow.keynames[_glfw.platformWindow.keycodes[scancode]], nil
key := _glfw.platformWindow.keycodes[scancode]
if key == KeyUnknown {
return "", nil
}
return _glfw.platformWindow.keynames[key], nil
}
func platformGetKeyScancode(key Key) int {
+1 -1
View File
@@ -676,7 +676,7 @@ GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle)
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(1.f);
_GLFW_REQUIRE_INIT_OR_RETURN(0.f);
return _glfwPlatformGetWindowOpacity(window);
}
+12 -2
View File
@@ -20,38 +20,47 @@ package glfw
// void goWindowMaximizeCB(void* window, int maximized);
// void goWindowContentScaleCB(void* window, float x, float y);
//
// #cgo noescape glfwSetWindowPosCallbackCB
// static void glfwSetWindowPosCallbackCB(GLFWwindow *window) {
// glfwSetWindowPosCallback(window, (GLFWwindowposfun)goWindowPosCB);
// }
//
// #cgo noescape glfwSetWindowSizeCallbackCB
// static void glfwSetWindowSizeCallbackCB(GLFWwindow *window) {
// glfwSetWindowSizeCallback(window, (GLFWwindowsizefun)goWindowSizeCB);
// }
//
// #cgo noescape glfwSetWindowCloseCallbackCB
// static void glfwSetWindowCloseCallbackCB(GLFWwindow *window) {
// glfwSetWindowCloseCallback(window, (GLFWwindowclosefun)goWindowCloseCB);
// }
//
// #cgo noescape glfwSetWindowRefreshCallbackCB
// static void glfwSetWindowRefreshCallbackCB(GLFWwindow *window) {
// glfwSetWindowRefreshCallback(window, (GLFWwindowrefreshfun)goWindowRefreshCB);
// }
//
// #cgo noescape glfwSetWindowFocusCallbackCB
// static void glfwSetWindowFocusCallbackCB(GLFWwindow *window) {
// glfwSetWindowFocusCallback(window, (GLFWwindowfocusfun)goWindowFocusCB);
// }
//
// #cgo noescape glfwSetWindowIconifyCallbackCB
// static void glfwSetWindowIconifyCallbackCB(GLFWwindow *window) {
// glfwSetWindowIconifyCallback(window, (GLFWwindowiconifyfun)goWindowIconifyCB);
// }
//
// #cgo noescape glfwSetFramebufferSizeCallbackCB
// static void glfwSetFramebufferSizeCallbackCB(GLFWwindow *window) {
// glfwSetFramebufferSizeCallback(window, (GLFWframebuffersizefun)goFramebufferSizeCB);
// }
//
// #cgo noescape glfwSetWindowMaximizeCallbackCB
// static void glfwSetWindowMaximizeCallbackCB(GLFWwindow *window) {
// glfwSetWindowMaximizeCallback(window, (GLFWwindowmaximizefun)goWindowMaximizeCB);
// }
//
// #cgo noescape glfwSetWindowContentScaleCallbackCB
// static void glfwSetWindowContentScaleCallbackCB(GLFWwindow *window) {
// glfwSetWindowContentScaleCallback(window, (GLFWwindowcontentscalefun)goWindowContentScaleCB);
// }
@@ -538,7 +547,7 @@ func (w *Window) SetOpacity(opacity float32) {
C.glfwSetWindowOpacity(w.data, C.float(opacity))
}
// RequestWindowAttention funciton requests user attention to the specified
// RequestAttention function requests user attention to the specified
// window. On platforms where this is not supported, attention is requested to
// the application as a whole.
//
@@ -546,8 +555,9 @@ func (w *Window) SetOpacity(opacity float32) {
// application, the system will end the request automatically.
//
// This function must only be called from the main thread.
func (w *Window) RequestAttention() {
func (w *Window) RequestAttention() error {
C.glfwRequestWindowAttention(w.data)
return nil
}
// Focus brings the specified window to front and sets input focus.
@@ -1264,21 +1264,3 @@ void _glfwPlatformTerminate(void)
close(_glfw.x11.emptyEventPipe[1]);
}
}
const char* _glfwPlatformGetVersionString(void)
{
return _GLFW_VERSION_NUMBER " X11 GLX EGL OSMesa"
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
" clock_gettime"
#else
" gettimeofday"
#endif
#if defined(__linux__)
" evdev"
#endif
#if defined(_GLFW_BUILD_DLL)
" shared"
#endif
;
}
+89 -26
View File
@@ -357,6 +357,11 @@ static void updateNormalHints(_GLFWwindow* window, int width, int height)
{
XSizeHints* hints = XAllocSizeHints();
long supplied;
XGetWMNormalHints(_glfw.x11.display, window->x11.handle, hints, &supplied);
hints->flags &= ~(PMinSize | PMaxSize | PAspect);
if (!window->monitor)
{
if (window->resizable)
@@ -393,9 +398,6 @@ static void updateNormalHints(_GLFWwindow* window, int width, int height)
}
}
hints->flags |= PWinGravity;
hints->win_gravity = StaticGravity;
XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);
XFree(hints);
@@ -561,6 +563,25 @@ static void updateCursorImage(_GLFWwindow* window)
}
}
// Grabs the cursor and confines it to the window
//
static void captureCursor(_GLFWwindow* window)
{
XGrabPointer(_glfw.x11.display, window->x11.handle, True,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync,
window->x11.handle,
None,
CurrentTime);
}
// Ungrabs the cursor
//
static void releaseCursor(void)
{
XUngrabPointer(_glfw.x11.display, CurrentTime);
}
// Enable XI2 raw mouse motion events
//
static void enableRawMouseMotion(_GLFWwindow* window)
@@ -603,12 +624,7 @@ static void disableCursor(_GLFWwindow* window)
&_glfw.x11.restoreCursorPosY);
updateCursorImage(window);
_glfwCenterCursorInContentArea(window);
XGrabPointer(_glfw.x11.display, window->x11.handle, True,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync,
window->x11.handle,
_glfw.x11.hiddenCursorHandle,
CurrentTime);
captureCursor(window);
}
// Exit disabled cursor mode for the specified window
@@ -619,7 +635,7 @@ static void enableCursor(_GLFWwindow* window)
disableRawMouseMotion(window);
_glfw.x11.disabledCursorWindow = NULL;
XUngrabPointer(_glfw.x11.display, CurrentTime);
releaseCursor();
_glfwPlatformSetCursorPos(window,
_glfw.x11.restoreCursorPosX,
_glfw.x11.restoreCursorPosY);
@@ -764,7 +780,28 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
XFree(hints);
}
updateNormalHints(window, width, height);
// Set ICCCM WM_NORMAL_HINTS property
{
XSizeHints* hints = XAllocSizeHints();
if (!hints)
{
_glfwInputError(GLFW_OUT_OF_MEMORY, "X11: Failed to allocate size hints");
return GLFW_FALSE;
}
if (!wndconfig->resizable)
{
hints->flags |= (PMinSize | PMaxSize);
hints->min_width = hints->max_width = width;
hints->min_height = hints->max_height = height;
}
hints->flags |= PWinGravity;
hints->win_gravity = StaticGravity;
XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);
XFree(hints);
}
// Set ICCCM WM_CLASS property
{
@@ -1563,6 +1600,9 @@ static void processEvent(XEvent *event)
if (event->xconfigure.width != window->x11.width ||
event->xconfigure.height != window->x11.height)
{
window->x11.width = event->xconfigure.width;
window->x11.height = event->xconfigure.height;
_glfwInputFramebufferSize(window,
event->xconfigure.width,
event->xconfigure.height);
@@ -1570,9 +1610,6 @@ static void processEvent(XEvent *event)
_glfwInputWindowSize(window,
event->xconfigure.width,
event->xconfigure.height);
window->x11.width = event->xconfigure.width;
window->x11.height = event->xconfigure.height;
}
int xpos = event->xconfigure.x;
@@ -1600,9 +1637,10 @@ static void processEvent(XEvent *event)
if (xpos != window->x11.xpos || ypos != window->x11.ypos)
{
_glfwInputWindowPos(window, xpos, ypos);
window->x11.xpos = xpos;
window->x11.ypos = ypos;
_glfwInputWindowPos(window, xpos, ypos);
}
return;
@@ -2085,7 +2123,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
{
if (_glfw.x11.disabledCursorWindow == window)
_glfw.x11.disabledCursorWindow = NULL;
enableCursor(window);
if (window->monitor)
releaseMonitor(window);
@@ -2891,16 +2929,40 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{
if (mode == GLFW_CURSOR_DISABLED)
if (_glfwPlatformWindowFocused(window))
{
if (_glfwPlatformWindowFocused(window))
disableCursor(window);
}
else if (_glfw.x11.disabledCursorWindow == window)
enableCursor(window);
else
updateCursorImage(window);
if (mode == GLFW_CURSOR_DISABLED)
{
_glfwPlatformGetCursorPos(window,
&_glfw.x11.restoreCursorPosX,
&_glfw.x11.restoreCursorPosY);
_glfwCenterCursorInContentArea(window);
if (window->rawMouseMotion)
enableRawMouseMotion(window);
}
else if (_glfw.x11.disabledCursorWindow == window)
{
if (window->rawMouseMotion)
disableRawMouseMotion(window);
}
if (mode == GLFW_CURSOR_DISABLED)
captureCursor(window);
else
releaseCursor();
if (mode == GLFW_CURSOR_DISABLED)
_glfw.x11.disabledCursorWindow = window;
else if (_glfw.x11.disabledCursorWindow == window)
{
_glfw.x11.disabledCursorWindow = NULL;
_glfwPlatformSetCursorPos(window,
_glfw.x11.restoreCursorPosX,
_glfw.x11.restoreCursorPosY);
}
}
updateCursorImage(window);
XFlush(_glfw.x11.display);
}
@@ -2909,14 +2971,15 @@ const char* _glfwPlatformGetScancodeName(int scancode)
if (!_glfw.x11.xkb.available)
return NULL;
if (scancode < 0 || scancode > 0xff ||
_glfw.x11.keycodes[scancode] == GLFW_KEY_UNKNOWN)
if (scancode < 0 || scancode > 0xff)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode %i", scancode);
return NULL;
}
const int key = _glfw.x11.keycodes[scancode];
if (key == GLFW_KEY_UNKNOWN)
return NULL;
const KeySym keysym = XkbKeycodeToKeysym(_glfw.x11.display,
scancode, _glfw.x11.xkb.group, 0);
if (keysym == NoSymbol)
@@ -1,920 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2002-2006 Marcus Geelnard
// SPDX-FileCopyrightText: 2006-2017 Camilla Löwy <elmindreda@glfw.org>
// SPDX-FileCopyrightText: 2023 The Ebitengine Authors
//go:build freebsd || linux || netbsd || openbsd
#include "internal_unix.h"
/*
* Marcus: This code was originally written by Markus G. Kuhn.
* I have made some slight changes (trimmed it down a bit from >60 KB to
* 20 KB), but the functionality is the same.
*/
/*
* This module converts keysym values into the corresponding ISO 10646
* (UCS, Unicode) values.
*
* The array keysymtab[] contains pairs of X11 keysym values for graphical
* characters and the corresponding Unicode value. The function
* _glfwKeySym2Unicode() maps a keysym onto a Unicode value using a binary
* search, therefore keysymtab[] must remain SORTED by keysym value.
*
* We allow to represent any UCS character in the range U-00000000 to
* U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.
* This admittedly does not cover the entire 31-bit space of UCS, but
* it does cover all of the characters up to U-10FFFF, which can be
* represented by UTF-16, and more, and it is very unlikely that higher
* UCS codes will ever be assigned by ISO. So to get Unicode character
* U+ABCD you can directly use keysym 0x0100abcd.
*
* Original author: Markus G. Kuhn <mkuhn@acm.org>, University of
* Cambridge, April 2001
*
* Special thanks to Richard Verhoeven <river@win.tue.nl> for preparing
* an initial draft of the mapping table.
*
*/
//************************************************************************
//**** KeySym to Unicode mapping table ****
//************************************************************************
static const struct codepair {
unsigned short keysym;
unsigned short ucs;
} keysymtab[] = {
{ 0x01a1, 0x0104 },
{ 0x01a2, 0x02d8 },
{ 0x01a3, 0x0141 },
{ 0x01a5, 0x013d },
{ 0x01a6, 0x015a },
{ 0x01a9, 0x0160 },
{ 0x01aa, 0x015e },
{ 0x01ab, 0x0164 },
{ 0x01ac, 0x0179 },
{ 0x01ae, 0x017d },
{ 0x01af, 0x017b },
{ 0x01b1, 0x0105 },
{ 0x01b2, 0x02db },
{ 0x01b3, 0x0142 },
{ 0x01b5, 0x013e },
{ 0x01b6, 0x015b },
{ 0x01b7, 0x02c7 },
{ 0x01b9, 0x0161 },
{ 0x01ba, 0x015f },
{ 0x01bb, 0x0165 },
{ 0x01bc, 0x017a },
{ 0x01bd, 0x02dd },
{ 0x01be, 0x017e },
{ 0x01bf, 0x017c },
{ 0x01c0, 0x0154 },
{ 0x01c3, 0x0102 },
{ 0x01c5, 0x0139 },
{ 0x01c6, 0x0106 },
{ 0x01c8, 0x010c },
{ 0x01ca, 0x0118 },
{ 0x01cc, 0x011a },
{ 0x01cf, 0x010e },
{ 0x01d0, 0x0110 },
{ 0x01d1, 0x0143 },
{ 0x01d2, 0x0147 },
{ 0x01d5, 0x0150 },
{ 0x01d8, 0x0158 },
{ 0x01d9, 0x016e },
{ 0x01db, 0x0170 },
{ 0x01de, 0x0162 },
{ 0x01e0, 0x0155 },
{ 0x01e3, 0x0103 },
{ 0x01e5, 0x013a },
{ 0x01e6, 0x0107 },
{ 0x01e8, 0x010d },
{ 0x01ea, 0x0119 },
{ 0x01ec, 0x011b },
{ 0x01ef, 0x010f },
{ 0x01f0, 0x0111 },
{ 0x01f1, 0x0144 },
{ 0x01f2, 0x0148 },
{ 0x01f5, 0x0151 },
{ 0x01f8, 0x0159 },
{ 0x01f9, 0x016f },
{ 0x01fb, 0x0171 },
{ 0x01fe, 0x0163 },
{ 0x01ff, 0x02d9 },
{ 0x02a1, 0x0126 },
{ 0x02a6, 0x0124 },
{ 0x02a9, 0x0130 },
{ 0x02ab, 0x011e },
{ 0x02ac, 0x0134 },
{ 0x02b1, 0x0127 },
{ 0x02b6, 0x0125 },
{ 0x02b9, 0x0131 },
{ 0x02bb, 0x011f },
{ 0x02bc, 0x0135 },
{ 0x02c5, 0x010a },
{ 0x02c6, 0x0108 },
{ 0x02d5, 0x0120 },
{ 0x02d8, 0x011c },
{ 0x02dd, 0x016c },
{ 0x02de, 0x015c },
{ 0x02e5, 0x010b },
{ 0x02e6, 0x0109 },
{ 0x02f5, 0x0121 },
{ 0x02f8, 0x011d },
{ 0x02fd, 0x016d },
{ 0x02fe, 0x015d },
{ 0x03a2, 0x0138 },
{ 0x03a3, 0x0156 },
{ 0x03a5, 0x0128 },
{ 0x03a6, 0x013b },
{ 0x03aa, 0x0112 },
{ 0x03ab, 0x0122 },
{ 0x03ac, 0x0166 },
{ 0x03b3, 0x0157 },
{ 0x03b5, 0x0129 },
{ 0x03b6, 0x013c },
{ 0x03ba, 0x0113 },
{ 0x03bb, 0x0123 },
{ 0x03bc, 0x0167 },
{ 0x03bd, 0x014a },
{ 0x03bf, 0x014b },
{ 0x03c0, 0x0100 },
{ 0x03c7, 0x012e },
{ 0x03cc, 0x0116 },
{ 0x03cf, 0x012a },
{ 0x03d1, 0x0145 },
{ 0x03d2, 0x014c },
{ 0x03d3, 0x0136 },
{ 0x03d9, 0x0172 },
{ 0x03dd, 0x0168 },
{ 0x03de, 0x016a },
{ 0x03e0, 0x0101 },
{ 0x03e7, 0x012f },
{ 0x03ec, 0x0117 },
{ 0x03ef, 0x012b },
{ 0x03f1, 0x0146 },
{ 0x03f2, 0x014d },
{ 0x03f3, 0x0137 },
{ 0x03f9, 0x0173 },
{ 0x03fd, 0x0169 },
{ 0x03fe, 0x016b },
{ 0x047e, 0x203e },
{ 0x04a1, 0x3002 },
{ 0x04a2, 0x300c },
{ 0x04a3, 0x300d },
{ 0x04a4, 0x3001 },
{ 0x04a5, 0x30fb },
{ 0x04a6, 0x30f2 },
{ 0x04a7, 0x30a1 },
{ 0x04a8, 0x30a3 },
{ 0x04a9, 0x30a5 },
{ 0x04aa, 0x30a7 },
{ 0x04ab, 0x30a9 },
{ 0x04ac, 0x30e3 },
{ 0x04ad, 0x30e5 },
{ 0x04ae, 0x30e7 },
{ 0x04af, 0x30c3 },
{ 0x04b0, 0x30fc },
{ 0x04b1, 0x30a2 },
{ 0x04b2, 0x30a4 },
{ 0x04b3, 0x30a6 },
{ 0x04b4, 0x30a8 },
{ 0x04b5, 0x30aa },
{ 0x04b6, 0x30ab },
{ 0x04b7, 0x30ad },
{ 0x04b8, 0x30af },
{ 0x04b9, 0x30b1 },
{ 0x04ba, 0x30b3 },
{ 0x04bb, 0x30b5 },
{ 0x04bc, 0x30b7 },
{ 0x04bd, 0x30b9 },
{ 0x04be, 0x30bb },
{ 0x04bf, 0x30bd },
{ 0x04c0, 0x30bf },
{ 0x04c1, 0x30c1 },
{ 0x04c2, 0x30c4 },
{ 0x04c3, 0x30c6 },
{ 0x04c4, 0x30c8 },
{ 0x04c5, 0x30ca },
{ 0x04c6, 0x30cb },
{ 0x04c7, 0x30cc },
{ 0x04c8, 0x30cd },
{ 0x04c9, 0x30ce },
{ 0x04ca, 0x30cf },
{ 0x04cb, 0x30d2 },
{ 0x04cc, 0x30d5 },
{ 0x04cd, 0x30d8 },
{ 0x04ce, 0x30db },
{ 0x04cf, 0x30de },
{ 0x04d0, 0x30df },
{ 0x04d1, 0x30e0 },
{ 0x04d2, 0x30e1 },
{ 0x04d3, 0x30e2 },
{ 0x04d4, 0x30e4 },
{ 0x04d5, 0x30e6 },
{ 0x04d6, 0x30e8 },
{ 0x04d7, 0x30e9 },
{ 0x04d8, 0x30ea },
{ 0x04d9, 0x30eb },
{ 0x04da, 0x30ec },
{ 0x04db, 0x30ed },
{ 0x04dc, 0x30ef },
{ 0x04dd, 0x30f3 },
{ 0x04de, 0x309b },
{ 0x04df, 0x309c },
{ 0x05ac, 0x060c },
{ 0x05bb, 0x061b },
{ 0x05bf, 0x061f },
{ 0x05c1, 0x0621 },
{ 0x05c2, 0x0622 },
{ 0x05c3, 0x0623 },
{ 0x05c4, 0x0624 },
{ 0x05c5, 0x0625 },
{ 0x05c6, 0x0626 },
{ 0x05c7, 0x0627 },
{ 0x05c8, 0x0628 },
{ 0x05c9, 0x0629 },
{ 0x05ca, 0x062a },
{ 0x05cb, 0x062b },
{ 0x05cc, 0x062c },
{ 0x05cd, 0x062d },
{ 0x05ce, 0x062e },
{ 0x05cf, 0x062f },
{ 0x05d0, 0x0630 },
{ 0x05d1, 0x0631 },
{ 0x05d2, 0x0632 },
{ 0x05d3, 0x0633 },
{ 0x05d4, 0x0634 },
{ 0x05d5, 0x0635 },
{ 0x05d6, 0x0636 },
{ 0x05d7, 0x0637 },
{ 0x05d8, 0x0638 },
{ 0x05d9, 0x0639 },
{ 0x05da, 0x063a },
{ 0x05e0, 0x0640 },
{ 0x05e1, 0x0641 },
{ 0x05e2, 0x0642 },
{ 0x05e3, 0x0643 },
{ 0x05e4, 0x0644 },
{ 0x05e5, 0x0645 },
{ 0x05e6, 0x0646 },
{ 0x05e7, 0x0647 },
{ 0x05e8, 0x0648 },
{ 0x05e9, 0x0649 },
{ 0x05ea, 0x064a },
{ 0x05eb, 0x064b },
{ 0x05ec, 0x064c },
{ 0x05ed, 0x064d },
{ 0x05ee, 0x064e },
{ 0x05ef, 0x064f },
{ 0x05f0, 0x0650 },
{ 0x05f1, 0x0651 },
{ 0x05f2, 0x0652 },
{ 0x06a1, 0x0452 },
{ 0x06a2, 0x0453 },
{ 0x06a3, 0x0451 },
{ 0x06a4, 0x0454 },
{ 0x06a5, 0x0455 },
{ 0x06a6, 0x0456 },
{ 0x06a7, 0x0457 },
{ 0x06a8, 0x0458 },
{ 0x06a9, 0x0459 },
{ 0x06aa, 0x045a },
{ 0x06ab, 0x045b },
{ 0x06ac, 0x045c },
{ 0x06ae, 0x045e },
{ 0x06af, 0x045f },
{ 0x06b0, 0x2116 },
{ 0x06b1, 0x0402 },
{ 0x06b2, 0x0403 },
{ 0x06b3, 0x0401 },
{ 0x06b4, 0x0404 },
{ 0x06b5, 0x0405 },
{ 0x06b6, 0x0406 },
{ 0x06b7, 0x0407 },
{ 0x06b8, 0x0408 },
{ 0x06b9, 0x0409 },
{ 0x06ba, 0x040a },
{ 0x06bb, 0x040b },
{ 0x06bc, 0x040c },
{ 0x06be, 0x040e },
{ 0x06bf, 0x040f },
{ 0x06c0, 0x044e },
{ 0x06c1, 0x0430 },
{ 0x06c2, 0x0431 },
{ 0x06c3, 0x0446 },
{ 0x06c4, 0x0434 },
{ 0x06c5, 0x0435 },
{ 0x06c6, 0x0444 },
{ 0x06c7, 0x0433 },
{ 0x06c8, 0x0445 },
{ 0x06c9, 0x0438 },
{ 0x06ca, 0x0439 },
{ 0x06cb, 0x043a },
{ 0x06cc, 0x043b },
{ 0x06cd, 0x043c },
{ 0x06ce, 0x043d },
{ 0x06cf, 0x043e },
{ 0x06d0, 0x043f },
{ 0x06d1, 0x044f },
{ 0x06d2, 0x0440 },
{ 0x06d3, 0x0441 },
{ 0x06d4, 0x0442 },
{ 0x06d5, 0x0443 },
{ 0x06d6, 0x0436 },
{ 0x06d7, 0x0432 },
{ 0x06d8, 0x044c },
{ 0x06d9, 0x044b },
{ 0x06da, 0x0437 },
{ 0x06db, 0x0448 },
{ 0x06dc, 0x044d },
{ 0x06dd, 0x0449 },
{ 0x06de, 0x0447 },
{ 0x06df, 0x044a },
{ 0x06e0, 0x042e },
{ 0x06e1, 0x0410 },
{ 0x06e2, 0x0411 },
{ 0x06e3, 0x0426 },
{ 0x06e4, 0x0414 },
{ 0x06e5, 0x0415 },
{ 0x06e6, 0x0424 },
{ 0x06e7, 0x0413 },
{ 0x06e8, 0x0425 },
{ 0x06e9, 0x0418 },
{ 0x06ea, 0x0419 },
{ 0x06eb, 0x041a },
{ 0x06ec, 0x041b },
{ 0x06ed, 0x041c },
{ 0x06ee, 0x041d },
{ 0x06ef, 0x041e },
{ 0x06f0, 0x041f },
{ 0x06f1, 0x042f },
{ 0x06f2, 0x0420 },
{ 0x06f3, 0x0421 },
{ 0x06f4, 0x0422 },
{ 0x06f5, 0x0423 },
{ 0x06f6, 0x0416 },
{ 0x06f7, 0x0412 },
{ 0x06f8, 0x042c },
{ 0x06f9, 0x042b },
{ 0x06fa, 0x0417 },
{ 0x06fb, 0x0428 },
{ 0x06fc, 0x042d },
{ 0x06fd, 0x0429 },
{ 0x06fe, 0x0427 },
{ 0x06ff, 0x042a },
{ 0x07a1, 0x0386 },
{ 0x07a2, 0x0388 },
{ 0x07a3, 0x0389 },
{ 0x07a4, 0x038a },
{ 0x07a5, 0x03aa },
{ 0x07a7, 0x038c },
{ 0x07a8, 0x038e },
{ 0x07a9, 0x03ab },
{ 0x07ab, 0x038f },
{ 0x07ae, 0x0385 },
{ 0x07af, 0x2015 },
{ 0x07b1, 0x03ac },
{ 0x07b2, 0x03ad },
{ 0x07b3, 0x03ae },
{ 0x07b4, 0x03af },
{ 0x07b5, 0x03ca },
{ 0x07b6, 0x0390 },
{ 0x07b7, 0x03cc },
{ 0x07b8, 0x03cd },
{ 0x07b9, 0x03cb },
{ 0x07ba, 0x03b0 },
{ 0x07bb, 0x03ce },
{ 0x07c1, 0x0391 },
{ 0x07c2, 0x0392 },
{ 0x07c3, 0x0393 },
{ 0x07c4, 0x0394 },
{ 0x07c5, 0x0395 },
{ 0x07c6, 0x0396 },
{ 0x07c7, 0x0397 },
{ 0x07c8, 0x0398 },
{ 0x07c9, 0x0399 },
{ 0x07ca, 0x039a },
{ 0x07cb, 0x039b },
{ 0x07cc, 0x039c },
{ 0x07cd, 0x039d },
{ 0x07ce, 0x039e },
{ 0x07cf, 0x039f },
{ 0x07d0, 0x03a0 },
{ 0x07d1, 0x03a1 },
{ 0x07d2, 0x03a3 },
{ 0x07d4, 0x03a4 },
{ 0x07d5, 0x03a5 },
{ 0x07d6, 0x03a6 },
{ 0x07d7, 0x03a7 },
{ 0x07d8, 0x03a8 },
{ 0x07d9, 0x03a9 },
{ 0x07e1, 0x03b1 },
{ 0x07e2, 0x03b2 },
{ 0x07e3, 0x03b3 },
{ 0x07e4, 0x03b4 },
{ 0x07e5, 0x03b5 },
{ 0x07e6, 0x03b6 },
{ 0x07e7, 0x03b7 },
{ 0x07e8, 0x03b8 },
{ 0x07e9, 0x03b9 },
{ 0x07ea, 0x03ba },
{ 0x07eb, 0x03bb },
{ 0x07ec, 0x03bc },
{ 0x07ed, 0x03bd },
{ 0x07ee, 0x03be },
{ 0x07ef, 0x03bf },
{ 0x07f0, 0x03c0 },
{ 0x07f1, 0x03c1 },
{ 0x07f2, 0x03c3 },
{ 0x07f3, 0x03c2 },
{ 0x07f4, 0x03c4 },
{ 0x07f5, 0x03c5 },
{ 0x07f6, 0x03c6 },
{ 0x07f7, 0x03c7 },
{ 0x07f8, 0x03c8 },
{ 0x07f9, 0x03c9 },
{ 0x08a1, 0x23b7 },
{ 0x08a2, 0x250c },
{ 0x08a3, 0x2500 },
{ 0x08a4, 0x2320 },
{ 0x08a5, 0x2321 },
{ 0x08a6, 0x2502 },
{ 0x08a7, 0x23a1 },
{ 0x08a8, 0x23a3 },
{ 0x08a9, 0x23a4 },
{ 0x08aa, 0x23a6 },
{ 0x08ab, 0x239b },
{ 0x08ac, 0x239d },
{ 0x08ad, 0x239e },
{ 0x08ae, 0x23a0 },
{ 0x08af, 0x23a8 },
{ 0x08b0, 0x23ac },
{ 0x08bc, 0x2264 },
{ 0x08bd, 0x2260 },
{ 0x08be, 0x2265 },
{ 0x08bf, 0x222b },
{ 0x08c0, 0x2234 },
{ 0x08c1, 0x221d },
{ 0x08c2, 0x221e },
{ 0x08c5, 0x2207 },
{ 0x08c8, 0x223c },
{ 0x08c9, 0x2243 },
{ 0x08cd, 0x21d4 },
{ 0x08ce, 0x21d2 },
{ 0x08cf, 0x2261 },
{ 0x08d6, 0x221a },
{ 0x08da, 0x2282 },
{ 0x08db, 0x2283 },
{ 0x08dc, 0x2229 },
{ 0x08dd, 0x222a },
{ 0x08de, 0x2227 },
{ 0x08df, 0x2228 },
{ 0x08ef, 0x2202 },
{ 0x08f6, 0x0192 },
{ 0x08fb, 0x2190 },
{ 0x08fc, 0x2191 },
{ 0x08fd, 0x2192 },
{ 0x08fe, 0x2193 },
{ 0x09e0, 0x25c6 },
{ 0x09e1, 0x2592 },
{ 0x09e2, 0x2409 },
{ 0x09e3, 0x240c },
{ 0x09e4, 0x240d },
{ 0x09e5, 0x240a },
{ 0x09e8, 0x2424 },
{ 0x09e9, 0x240b },
{ 0x09ea, 0x2518 },
{ 0x09eb, 0x2510 },
{ 0x09ec, 0x250c },
{ 0x09ed, 0x2514 },
{ 0x09ee, 0x253c },
{ 0x09ef, 0x23ba },
{ 0x09f0, 0x23bb },
{ 0x09f1, 0x2500 },
{ 0x09f2, 0x23bc },
{ 0x09f3, 0x23bd },
{ 0x09f4, 0x251c },
{ 0x09f5, 0x2524 },
{ 0x09f6, 0x2534 },
{ 0x09f7, 0x252c },
{ 0x09f8, 0x2502 },
{ 0x0aa1, 0x2003 },
{ 0x0aa2, 0x2002 },
{ 0x0aa3, 0x2004 },
{ 0x0aa4, 0x2005 },
{ 0x0aa5, 0x2007 },
{ 0x0aa6, 0x2008 },
{ 0x0aa7, 0x2009 },
{ 0x0aa8, 0x200a },
{ 0x0aa9, 0x2014 },
{ 0x0aaa, 0x2013 },
{ 0x0aae, 0x2026 },
{ 0x0aaf, 0x2025 },
{ 0x0ab0, 0x2153 },
{ 0x0ab1, 0x2154 },
{ 0x0ab2, 0x2155 },
{ 0x0ab3, 0x2156 },
{ 0x0ab4, 0x2157 },
{ 0x0ab5, 0x2158 },
{ 0x0ab6, 0x2159 },
{ 0x0ab7, 0x215a },
{ 0x0ab8, 0x2105 },
{ 0x0abb, 0x2012 },
{ 0x0abc, 0x2329 },
{ 0x0abe, 0x232a },
{ 0x0ac3, 0x215b },
{ 0x0ac4, 0x215c },
{ 0x0ac5, 0x215d },
{ 0x0ac6, 0x215e },
{ 0x0ac9, 0x2122 },
{ 0x0aca, 0x2613 },
{ 0x0acc, 0x25c1 },
{ 0x0acd, 0x25b7 },
{ 0x0ace, 0x25cb },
{ 0x0acf, 0x25af },
{ 0x0ad0, 0x2018 },
{ 0x0ad1, 0x2019 },
{ 0x0ad2, 0x201c },
{ 0x0ad3, 0x201d },
{ 0x0ad4, 0x211e },
{ 0x0ad6, 0x2032 },
{ 0x0ad7, 0x2033 },
{ 0x0ad9, 0x271d },
{ 0x0adb, 0x25ac },
{ 0x0adc, 0x25c0 },
{ 0x0add, 0x25b6 },
{ 0x0ade, 0x25cf },
{ 0x0adf, 0x25ae },
{ 0x0ae0, 0x25e6 },
{ 0x0ae1, 0x25ab },
{ 0x0ae2, 0x25ad },
{ 0x0ae3, 0x25b3 },
{ 0x0ae4, 0x25bd },
{ 0x0ae5, 0x2606 },
{ 0x0ae6, 0x2022 },
{ 0x0ae7, 0x25aa },
{ 0x0ae8, 0x25b2 },
{ 0x0ae9, 0x25bc },
{ 0x0aea, 0x261c },
{ 0x0aeb, 0x261e },
{ 0x0aec, 0x2663 },
{ 0x0aed, 0x2666 },
{ 0x0aee, 0x2665 },
{ 0x0af0, 0x2720 },
{ 0x0af1, 0x2020 },
{ 0x0af2, 0x2021 },
{ 0x0af3, 0x2713 },
{ 0x0af4, 0x2717 },
{ 0x0af5, 0x266f },
{ 0x0af6, 0x266d },
{ 0x0af7, 0x2642 },
{ 0x0af8, 0x2640 },
{ 0x0af9, 0x260e },
{ 0x0afa, 0x2315 },
{ 0x0afb, 0x2117 },
{ 0x0afc, 0x2038 },
{ 0x0afd, 0x201a },
{ 0x0afe, 0x201e },
{ 0x0ba3, 0x003c },
{ 0x0ba6, 0x003e },
{ 0x0ba8, 0x2228 },
{ 0x0ba9, 0x2227 },
{ 0x0bc0, 0x00af },
{ 0x0bc2, 0x22a5 },
{ 0x0bc3, 0x2229 },
{ 0x0bc4, 0x230a },
{ 0x0bc6, 0x005f },
{ 0x0bca, 0x2218 },
{ 0x0bcc, 0x2395 },
{ 0x0bce, 0x22a4 },
{ 0x0bcf, 0x25cb },
{ 0x0bd3, 0x2308 },
{ 0x0bd6, 0x222a },
{ 0x0bd8, 0x2283 },
{ 0x0bda, 0x2282 },
{ 0x0bdc, 0x22a2 },
{ 0x0bfc, 0x22a3 },
{ 0x0cdf, 0x2017 },
{ 0x0ce0, 0x05d0 },
{ 0x0ce1, 0x05d1 },
{ 0x0ce2, 0x05d2 },
{ 0x0ce3, 0x05d3 },
{ 0x0ce4, 0x05d4 },
{ 0x0ce5, 0x05d5 },
{ 0x0ce6, 0x05d6 },
{ 0x0ce7, 0x05d7 },
{ 0x0ce8, 0x05d8 },
{ 0x0ce9, 0x05d9 },
{ 0x0cea, 0x05da },
{ 0x0ceb, 0x05db },
{ 0x0cec, 0x05dc },
{ 0x0ced, 0x05dd },
{ 0x0cee, 0x05de },
{ 0x0cef, 0x05df },
{ 0x0cf0, 0x05e0 },
{ 0x0cf1, 0x05e1 },
{ 0x0cf2, 0x05e2 },
{ 0x0cf3, 0x05e3 },
{ 0x0cf4, 0x05e4 },
{ 0x0cf5, 0x05e5 },
{ 0x0cf6, 0x05e6 },
{ 0x0cf7, 0x05e7 },
{ 0x0cf8, 0x05e8 },
{ 0x0cf9, 0x05e9 },
{ 0x0cfa, 0x05ea },
{ 0x0da1, 0x0e01 },
{ 0x0da2, 0x0e02 },
{ 0x0da3, 0x0e03 },
{ 0x0da4, 0x0e04 },
{ 0x0da5, 0x0e05 },
{ 0x0da6, 0x0e06 },
{ 0x0da7, 0x0e07 },
{ 0x0da8, 0x0e08 },
{ 0x0da9, 0x0e09 },
{ 0x0daa, 0x0e0a },
{ 0x0dab, 0x0e0b },
{ 0x0dac, 0x0e0c },
{ 0x0dad, 0x0e0d },
{ 0x0dae, 0x0e0e },
{ 0x0daf, 0x0e0f },
{ 0x0db0, 0x0e10 },
{ 0x0db1, 0x0e11 },
{ 0x0db2, 0x0e12 },
{ 0x0db3, 0x0e13 },
{ 0x0db4, 0x0e14 },
{ 0x0db5, 0x0e15 },
{ 0x0db6, 0x0e16 },
{ 0x0db7, 0x0e17 },
{ 0x0db8, 0x0e18 },
{ 0x0db9, 0x0e19 },
{ 0x0dba, 0x0e1a },
{ 0x0dbb, 0x0e1b },
{ 0x0dbc, 0x0e1c },
{ 0x0dbd, 0x0e1d },
{ 0x0dbe, 0x0e1e },
{ 0x0dbf, 0x0e1f },
{ 0x0dc0, 0x0e20 },
{ 0x0dc1, 0x0e21 },
{ 0x0dc2, 0x0e22 },
{ 0x0dc3, 0x0e23 },
{ 0x0dc4, 0x0e24 },
{ 0x0dc5, 0x0e25 },
{ 0x0dc6, 0x0e26 },
{ 0x0dc7, 0x0e27 },
{ 0x0dc8, 0x0e28 },
{ 0x0dc9, 0x0e29 },
{ 0x0dca, 0x0e2a },
{ 0x0dcb, 0x0e2b },
{ 0x0dcc, 0x0e2c },
{ 0x0dcd, 0x0e2d },
{ 0x0dce, 0x0e2e },
{ 0x0dcf, 0x0e2f },
{ 0x0dd0, 0x0e30 },
{ 0x0dd1, 0x0e31 },
{ 0x0dd2, 0x0e32 },
{ 0x0dd3, 0x0e33 },
{ 0x0dd4, 0x0e34 },
{ 0x0dd5, 0x0e35 },
{ 0x0dd6, 0x0e36 },
{ 0x0dd7, 0x0e37 },
{ 0x0dd8, 0x0e38 },
{ 0x0dd9, 0x0e39 },
{ 0x0dda, 0x0e3a },
{ 0x0ddf, 0x0e3f },
{ 0x0de0, 0x0e40 },
{ 0x0de1, 0x0e41 },
{ 0x0de2, 0x0e42 },
{ 0x0de3, 0x0e43 },
{ 0x0de4, 0x0e44 },
{ 0x0de5, 0x0e45 },
{ 0x0de6, 0x0e46 },
{ 0x0de7, 0x0e47 },
{ 0x0de8, 0x0e48 },
{ 0x0de9, 0x0e49 },
{ 0x0dea, 0x0e4a },
{ 0x0deb, 0x0e4b },
{ 0x0dec, 0x0e4c },
{ 0x0ded, 0x0e4d },
{ 0x0df0, 0x0e50 },
{ 0x0df1, 0x0e51 },
{ 0x0df2, 0x0e52 },
{ 0x0df3, 0x0e53 },
{ 0x0df4, 0x0e54 },
{ 0x0df5, 0x0e55 },
{ 0x0df6, 0x0e56 },
{ 0x0df7, 0x0e57 },
{ 0x0df8, 0x0e58 },
{ 0x0df9, 0x0e59 },
{ 0x0ea1, 0x3131 },
{ 0x0ea2, 0x3132 },
{ 0x0ea3, 0x3133 },
{ 0x0ea4, 0x3134 },
{ 0x0ea5, 0x3135 },
{ 0x0ea6, 0x3136 },
{ 0x0ea7, 0x3137 },
{ 0x0ea8, 0x3138 },
{ 0x0ea9, 0x3139 },
{ 0x0eaa, 0x313a },
{ 0x0eab, 0x313b },
{ 0x0eac, 0x313c },
{ 0x0ead, 0x313d },
{ 0x0eae, 0x313e },
{ 0x0eaf, 0x313f },
{ 0x0eb0, 0x3140 },
{ 0x0eb1, 0x3141 },
{ 0x0eb2, 0x3142 },
{ 0x0eb3, 0x3143 },
{ 0x0eb4, 0x3144 },
{ 0x0eb5, 0x3145 },
{ 0x0eb6, 0x3146 },
{ 0x0eb7, 0x3147 },
{ 0x0eb8, 0x3148 },
{ 0x0eb9, 0x3149 },
{ 0x0eba, 0x314a },
{ 0x0ebb, 0x314b },
{ 0x0ebc, 0x314c },
{ 0x0ebd, 0x314d },
{ 0x0ebe, 0x314e },
{ 0x0ebf, 0x314f },
{ 0x0ec0, 0x3150 },
{ 0x0ec1, 0x3151 },
{ 0x0ec2, 0x3152 },
{ 0x0ec3, 0x3153 },
{ 0x0ec4, 0x3154 },
{ 0x0ec5, 0x3155 },
{ 0x0ec6, 0x3156 },
{ 0x0ec7, 0x3157 },
{ 0x0ec8, 0x3158 },
{ 0x0ec9, 0x3159 },
{ 0x0eca, 0x315a },
{ 0x0ecb, 0x315b },
{ 0x0ecc, 0x315c },
{ 0x0ecd, 0x315d },
{ 0x0ece, 0x315e },
{ 0x0ecf, 0x315f },
{ 0x0ed0, 0x3160 },
{ 0x0ed1, 0x3161 },
{ 0x0ed2, 0x3162 },
{ 0x0ed3, 0x3163 },
{ 0x0ed4, 0x11a8 },
{ 0x0ed5, 0x11a9 },
{ 0x0ed6, 0x11aa },
{ 0x0ed7, 0x11ab },
{ 0x0ed8, 0x11ac },
{ 0x0ed9, 0x11ad },
{ 0x0eda, 0x11ae },
{ 0x0edb, 0x11af },
{ 0x0edc, 0x11b0 },
{ 0x0edd, 0x11b1 },
{ 0x0ede, 0x11b2 },
{ 0x0edf, 0x11b3 },
{ 0x0ee0, 0x11b4 },
{ 0x0ee1, 0x11b5 },
{ 0x0ee2, 0x11b6 },
{ 0x0ee3, 0x11b7 },
{ 0x0ee4, 0x11b8 },
{ 0x0ee5, 0x11b9 },
{ 0x0ee6, 0x11ba },
{ 0x0ee7, 0x11bb },
{ 0x0ee8, 0x11bc },
{ 0x0ee9, 0x11bd },
{ 0x0eea, 0x11be },
{ 0x0eeb, 0x11bf },
{ 0x0eec, 0x11c0 },
{ 0x0eed, 0x11c1 },
{ 0x0eee, 0x11c2 },
{ 0x0eef, 0x316d },
{ 0x0ef0, 0x3171 },
{ 0x0ef1, 0x3178 },
{ 0x0ef2, 0x317f },
{ 0x0ef3, 0x3181 },
{ 0x0ef4, 0x3184 },
{ 0x0ef5, 0x3186 },
{ 0x0ef6, 0x318d },
{ 0x0ef7, 0x318e },
{ 0x0ef8, 0x11eb },
{ 0x0ef9, 0x11f0 },
{ 0x0efa, 0x11f9 },
{ 0x0eff, 0x20a9 },
{ 0x13a4, 0x20ac },
{ 0x13bc, 0x0152 },
{ 0x13bd, 0x0153 },
{ 0x13be, 0x0178 },
{ 0x20ac, 0x20ac },
{ 0xfe50, '`' },
{ 0xfe51, 0x00b4 },
{ 0xfe52, '^' },
{ 0xfe53, '~' },
{ 0xfe54, 0x00af },
{ 0xfe55, 0x02d8 },
{ 0xfe56, 0x02d9 },
{ 0xfe57, 0x00a8 },
{ 0xfe58, 0x02da },
{ 0xfe59, 0x02dd },
{ 0xfe5a, 0x02c7 },
{ 0xfe5b, 0x00b8 },
{ 0xfe5c, 0x02db },
{ 0xfe5d, 0x037a },
{ 0xfe5e, 0x309b },
{ 0xfe5f, 0x309c },
{ 0xfe63, '/' },
{ 0xfe64, 0x02bc },
{ 0xfe65, 0x02bd },
{ 0xfe66, 0x02f5 },
{ 0xfe67, 0x02f3 },
{ 0xfe68, 0x02cd },
{ 0xfe69, 0xa788 },
{ 0xfe6a, 0x02f7 },
{ 0xfe6e, ',' },
{ 0xfe6f, 0x00a4 },
{ 0xfe80, 'a' }, // XK_dead_a
{ 0xfe81, 'A' }, // XK_dead_A
{ 0xfe82, 'e' }, // XK_dead_e
{ 0xfe83, 'E' }, // XK_dead_E
{ 0xfe84, 'i' }, // XK_dead_i
{ 0xfe85, 'I' }, // XK_dead_I
{ 0xfe86, 'o' }, // XK_dead_o
{ 0xfe87, 'O' }, // XK_dead_O
{ 0xfe88, 'u' }, // XK_dead_u
{ 0xfe89, 'U' }, // XK_dead_U
{ 0xfe8a, 0x0259 },
{ 0xfe8b, 0x018f },
{ 0xfe8c, 0x00b5 },
{ 0xfe90, '_' },
{ 0xfe91, 0x02c8 },
{ 0xfe92, 0x02cc },
{ 0xff80 /*XKB_KEY_KP_Space*/, ' ' },
{ 0xff95 /*XKB_KEY_KP_7*/, 0x0037 },
{ 0xff96 /*XKB_KEY_KP_4*/, 0x0034 },
{ 0xff97 /*XKB_KEY_KP_8*/, 0x0038 },
{ 0xff98 /*XKB_KEY_KP_6*/, 0x0036 },
{ 0xff99 /*XKB_KEY_KP_2*/, 0x0032 },
{ 0xff9a /*XKB_KEY_KP_9*/, 0x0039 },
{ 0xff9b /*XKB_KEY_KP_3*/, 0x0033 },
{ 0xff9c /*XKB_KEY_KP_1*/, 0x0031 },
{ 0xff9d /*XKB_KEY_KP_5*/, 0x0035 },
{ 0xff9e /*XKB_KEY_KP_0*/, 0x0030 },
{ 0xffaa /*XKB_KEY_KP_Multiply*/, '*' },
{ 0xffab /*XKB_KEY_KP_Add*/, '+' },
{ 0xffac /*XKB_KEY_KP_Separator*/, ',' },
{ 0xffad /*XKB_KEY_KP_Subtract*/, '-' },
{ 0xffae /*XKB_KEY_KP_Decimal*/, '.' },
{ 0xffaf /*XKB_KEY_KP_Divide*/, '/' },
{ 0xffb0 /*XKB_KEY_KP_0*/, 0x0030 },
{ 0xffb1 /*XKB_KEY_KP_1*/, 0x0031 },
{ 0xffb2 /*XKB_KEY_KP_2*/, 0x0032 },
{ 0xffb3 /*XKB_KEY_KP_3*/, 0x0033 },
{ 0xffb4 /*XKB_KEY_KP_4*/, 0x0034 },
{ 0xffb5 /*XKB_KEY_KP_5*/, 0x0035 },
{ 0xffb6 /*XKB_KEY_KP_6*/, 0x0036 },
{ 0xffb7 /*XKB_KEY_KP_7*/, 0x0037 },
{ 0xffb8 /*XKB_KEY_KP_8*/, 0x0038 },
{ 0xffb9 /*XKB_KEY_KP_9*/, 0x0039 },
{ 0xffbd /*XKB_KEY_KP_Equal*/, '=' }
};
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Convert XKB KeySym to Unicode
//
uint32_t _glfwKeySym2Unicode(unsigned int keysym)
{
int min = 0;
int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
int mid;
// First check for Latin-1 characters (1:1 mapping)
if ((keysym >= 0x0020 && keysym <= 0x007e) ||
(keysym >= 0x00a0 && keysym <= 0x00ff))
{
return keysym;
}
// Also check for directly encoded 24-bit UCS characters
if ((keysym & 0xff000000) == 0x01000000)
return keysym & 0x00ffffff;
// Binary search in table
while (max >= min)
{
mid = (min + max) / 2;
if (keysymtab[mid].keysym < keysym)
min = mid + 1;
else if (keysymtab[mid].keysym > keysym)
max = mid - 1;
else
return keysymtab[mid].ucs;
}
// No matching Unicode value found
return GLFW_INVALID_CODEPOINT;
}
@@ -0,0 +1,893 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2014 Jonas Ådahl <jadahl@gmail.com>
// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
//go:build freebsd || linux || netbsd || openbsd
package glfw
// #include "xkb_unicode_linbsd.h"
import "C"
/*
* Marcus: This code was originally written by Markus G. Kuhn.
* I have made some slight changes (trimmed it down a bit from >60 KB to
* 20 KB), but the functionality is the same.
*/
/*
* This module converts keysym values into the corresponding ISO 10646
* (UCS, Unicode) values.
*
* The array keysymtab[] contains pairs of X11 keysym values for graphical
* characters and the corresponding Unicode value. The function
* _glfwKeySym2Unicode() maps a keysym onto a Unicode value using a binary
* search, therefore keysymtab[] must remain SORTED by keysym value.
*
* We allow to represent any UCS character in the range U-00000000 to
* U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.
* This admittedly does not cover the entire 31-bit space of UCS, but
* it does cover all of the characters up to U-10FFFF, which can be
* represented by UTF-16, and more, and it is very unlikely that higher
* UCS codes will ever be assigned by ISO. So to get Unicode character
* U+ABCD you can directly use keysym 0x0100abcd.
*
* Original author: Markus G. Kuhn <mkuhn@acm.org>, University of
* Cambridge, April 2001
*
* Special thanks to Richard Verhoeven <river@win.tue.nl> for preparing
* an initial draft of the mapping table.
*
*/
var keysymtab = map[uint32]uint32{
0x01a1: 0x0104,
0x01a2: 0x02d8,
0x01a3: 0x0141,
0x01a5: 0x013d,
0x01a6: 0x015a,
0x01a9: 0x0160,
0x01aa: 0x015e,
0x01ab: 0x0164,
0x01ac: 0x0179,
0x01ae: 0x017d,
0x01af: 0x017b,
0x01b1: 0x0105,
0x01b2: 0x02db,
0x01b3: 0x0142,
0x01b5: 0x013e,
0x01b6: 0x015b,
0x01b7: 0x02c7,
0x01b9: 0x0161,
0x01ba: 0x015f,
0x01bb: 0x0165,
0x01bc: 0x017a,
0x01bd: 0x02dd,
0x01be: 0x017e,
0x01bf: 0x017c,
0x01c0: 0x0154,
0x01c3: 0x0102,
0x01c5: 0x0139,
0x01c6: 0x0106,
0x01c8: 0x010c,
0x01ca: 0x0118,
0x01cc: 0x011a,
0x01cf: 0x010e,
0x01d0: 0x0110,
0x01d1: 0x0143,
0x01d2: 0x0147,
0x01d5: 0x0150,
0x01d8: 0x0158,
0x01d9: 0x016e,
0x01db: 0x0170,
0x01de: 0x0162,
0x01e0: 0x0155,
0x01e3: 0x0103,
0x01e5: 0x013a,
0x01e6: 0x0107,
0x01e8: 0x010d,
0x01ea: 0x0119,
0x01ec: 0x011b,
0x01ef: 0x010f,
0x01f0: 0x0111,
0x01f1: 0x0144,
0x01f2: 0x0148,
0x01f5: 0x0151,
0x01f8: 0x0159,
0x01f9: 0x016f,
0x01fb: 0x0171,
0x01fe: 0x0163,
0x01ff: 0x02d9,
0x02a1: 0x0126,
0x02a6: 0x0124,
0x02a9: 0x0130,
0x02ab: 0x011e,
0x02ac: 0x0134,
0x02b1: 0x0127,
0x02b6: 0x0125,
0x02b9: 0x0131,
0x02bb: 0x011f,
0x02bc: 0x0135,
0x02c5: 0x010a,
0x02c6: 0x0108,
0x02d5: 0x0120,
0x02d8: 0x011c,
0x02dd: 0x016c,
0x02de: 0x015c,
0x02e5: 0x010b,
0x02e6: 0x0109,
0x02f5: 0x0121,
0x02f8: 0x011d,
0x02fd: 0x016d,
0x02fe: 0x015d,
0x03a2: 0x0138,
0x03a3: 0x0156,
0x03a5: 0x0128,
0x03a6: 0x013b,
0x03aa: 0x0112,
0x03ab: 0x0122,
0x03ac: 0x0166,
0x03b3: 0x0157,
0x03b5: 0x0129,
0x03b6: 0x013c,
0x03ba: 0x0113,
0x03bb: 0x0123,
0x03bc: 0x0167,
0x03bd: 0x014a,
0x03bf: 0x014b,
0x03c0: 0x0100,
0x03c7: 0x012e,
0x03cc: 0x0116,
0x03cf: 0x012a,
0x03d1: 0x0145,
0x03d2: 0x014c,
0x03d3: 0x0136,
0x03d9: 0x0172,
0x03dd: 0x0168,
0x03de: 0x016a,
0x03e0: 0x0101,
0x03e7: 0x012f,
0x03ec: 0x0117,
0x03ef: 0x012b,
0x03f1: 0x0146,
0x03f2: 0x014d,
0x03f3: 0x0137,
0x03f9: 0x0173,
0x03fd: 0x0169,
0x03fe: 0x016b,
0x047e: 0x203e,
0x04a1: 0x3002,
0x04a2: 0x300c,
0x04a3: 0x300d,
0x04a4: 0x3001,
0x04a5: 0x30fb,
0x04a6: 0x30f2,
0x04a7: 0x30a1,
0x04a8: 0x30a3,
0x04a9: 0x30a5,
0x04aa: 0x30a7,
0x04ab: 0x30a9,
0x04ac: 0x30e3,
0x04ad: 0x30e5,
0x04ae: 0x30e7,
0x04af: 0x30c3,
0x04b0: 0x30fc,
0x04b1: 0x30a2,
0x04b2: 0x30a4,
0x04b3: 0x30a6,
0x04b4: 0x30a8,
0x04b5: 0x30aa,
0x04b6: 0x30ab,
0x04b7: 0x30ad,
0x04b8: 0x30af,
0x04b9: 0x30b1,
0x04ba: 0x30b3,
0x04bb: 0x30b5,
0x04bc: 0x30b7,
0x04bd: 0x30b9,
0x04be: 0x30bb,
0x04bf: 0x30bd,
0x04c0: 0x30bf,
0x04c1: 0x30c1,
0x04c2: 0x30c4,
0x04c3: 0x30c6,
0x04c4: 0x30c8,
0x04c5: 0x30ca,
0x04c6: 0x30cb,
0x04c7: 0x30cc,
0x04c8: 0x30cd,
0x04c9: 0x30ce,
0x04ca: 0x30cf,
0x04cb: 0x30d2,
0x04cc: 0x30d5,
0x04cd: 0x30d8,
0x04ce: 0x30db,
0x04cf: 0x30de,
0x04d0: 0x30df,
0x04d1: 0x30e0,
0x04d2: 0x30e1,
0x04d3: 0x30e2,
0x04d4: 0x30e4,
0x04d5: 0x30e6,
0x04d6: 0x30e8,
0x04d7: 0x30e9,
0x04d8: 0x30ea,
0x04d9: 0x30eb,
0x04da: 0x30ec,
0x04db: 0x30ed,
0x04dc: 0x30ef,
0x04dd: 0x30f3,
0x04de: 0x309b,
0x04df: 0x309c,
0x05ac: 0x060c,
0x05bb: 0x061b,
0x05bf: 0x061f,
0x05c1: 0x0621,
0x05c2: 0x0622,
0x05c3: 0x0623,
0x05c4: 0x0624,
0x05c5: 0x0625,
0x05c6: 0x0626,
0x05c7: 0x0627,
0x05c8: 0x0628,
0x05c9: 0x0629,
0x05ca: 0x062a,
0x05cb: 0x062b,
0x05cc: 0x062c,
0x05cd: 0x062d,
0x05ce: 0x062e,
0x05cf: 0x062f,
0x05d0: 0x0630,
0x05d1: 0x0631,
0x05d2: 0x0632,
0x05d3: 0x0633,
0x05d4: 0x0634,
0x05d5: 0x0635,
0x05d6: 0x0636,
0x05d7: 0x0637,
0x05d8: 0x0638,
0x05d9: 0x0639,
0x05da: 0x063a,
0x05e0: 0x0640,
0x05e1: 0x0641,
0x05e2: 0x0642,
0x05e3: 0x0643,
0x05e4: 0x0644,
0x05e5: 0x0645,
0x05e6: 0x0646,
0x05e7: 0x0647,
0x05e8: 0x0648,
0x05e9: 0x0649,
0x05ea: 0x064a,
0x05eb: 0x064b,
0x05ec: 0x064c,
0x05ed: 0x064d,
0x05ee: 0x064e,
0x05ef: 0x064f,
0x05f0: 0x0650,
0x05f1: 0x0651,
0x05f2: 0x0652,
0x06a1: 0x0452,
0x06a2: 0x0453,
0x06a3: 0x0451,
0x06a4: 0x0454,
0x06a5: 0x0455,
0x06a6: 0x0456,
0x06a7: 0x0457,
0x06a8: 0x0458,
0x06a9: 0x0459,
0x06aa: 0x045a,
0x06ab: 0x045b,
0x06ac: 0x045c,
0x06ae: 0x045e,
0x06af: 0x045f,
0x06b0: 0x2116,
0x06b1: 0x0402,
0x06b2: 0x0403,
0x06b3: 0x0401,
0x06b4: 0x0404,
0x06b5: 0x0405,
0x06b6: 0x0406,
0x06b7: 0x0407,
0x06b8: 0x0408,
0x06b9: 0x0409,
0x06ba: 0x040a,
0x06bb: 0x040b,
0x06bc: 0x040c,
0x06be: 0x040e,
0x06bf: 0x040f,
0x06c0: 0x044e,
0x06c1: 0x0430,
0x06c2: 0x0431,
0x06c3: 0x0446,
0x06c4: 0x0434,
0x06c5: 0x0435,
0x06c6: 0x0444,
0x06c7: 0x0433,
0x06c8: 0x0445,
0x06c9: 0x0438,
0x06ca: 0x0439,
0x06cb: 0x043a,
0x06cc: 0x043b,
0x06cd: 0x043c,
0x06ce: 0x043d,
0x06cf: 0x043e,
0x06d0: 0x043f,
0x06d1: 0x044f,
0x06d2: 0x0440,
0x06d3: 0x0441,
0x06d4: 0x0442,
0x06d5: 0x0443,
0x06d6: 0x0436,
0x06d7: 0x0432,
0x06d8: 0x044c,
0x06d9: 0x044b,
0x06da: 0x0437,
0x06db: 0x0448,
0x06dc: 0x044d,
0x06dd: 0x0449,
0x06de: 0x0447,
0x06df: 0x044a,
0x06e0: 0x042e,
0x06e1: 0x0410,
0x06e2: 0x0411,
0x06e3: 0x0426,
0x06e4: 0x0414,
0x06e5: 0x0415,
0x06e6: 0x0424,
0x06e7: 0x0413,
0x06e8: 0x0425,
0x06e9: 0x0418,
0x06ea: 0x0419,
0x06eb: 0x041a,
0x06ec: 0x041b,
0x06ed: 0x041c,
0x06ee: 0x041d,
0x06ef: 0x041e,
0x06f0: 0x041f,
0x06f1: 0x042f,
0x06f2: 0x0420,
0x06f3: 0x0421,
0x06f4: 0x0422,
0x06f5: 0x0423,
0x06f6: 0x0416,
0x06f7: 0x0412,
0x06f8: 0x042c,
0x06f9: 0x042b,
0x06fa: 0x0417,
0x06fb: 0x0428,
0x06fc: 0x042d,
0x06fd: 0x0429,
0x06fe: 0x0427,
0x06ff: 0x042a,
0x07a1: 0x0386,
0x07a2: 0x0388,
0x07a3: 0x0389,
0x07a4: 0x038a,
0x07a5: 0x03aa,
0x07a7: 0x038c,
0x07a8: 0x038e,
0x07a9: 0x03ab,
0x07ab: 0x038f,
0x07ae: 0x0385,
0x07af: 0x2015,
0x07b1: 0x03ac,
0x07b2: 0x03ad,
0x07b3: 0x03ae,
0x07b4: 0x03af,
0x07b5: 0x03ca,
0x07b6: 0x0390,
0x07b7: 0x03cc,
0x07b8: 0x03cd,
0x07b9: 0x03cb,
0x07ba: 0x03b0,
0x07bb: 0x03ce,
0x07c1: 0x0391,
0x07c2: 0x0392,
0x07c3: 0x0393,
0x07c4: 0x0394,
0x07c5: 0x0395,
0x07c6: 0x0396,
0x07c7: 0x0397,
0x07c8: 0x0398,
0x07c9: 0x0399,
0x07ca: 0x039a,
0x07cb: 0x039b,
0x07cc: 0x039c,
0x07cd: 0x039d,
0x07ce: 0x039e,
0x07cf: 0x039f,
0x07d0: 0x03a0,
0x07d1: 0x03a1,
0x07d2: 0x03a3,
0x07d4: 0x03a4,
0x07d5: 0x03a5,
0x07d6: 0x03a6,
0x07d7: 0x03a7,
0x07d8: 0x03a8,
0x07d9: 0x03a9,
0x07e1: 0x03b1,
0x07e2: 0x03b2,
0x07e3: 0x03b3,
0x07e4: 0x03b4,
0x07e5: 0x03b5,
0x07e6: 0x03b6,
0x07e7: 0x03b7,
0x07e8: 0x03b8,
0x07e9: 0x03b9,
0x07ea: 0x03ba,
0x07eb: 0x03bb,
0x07ec: 0x03bc,
0x07ed: 0x03bd,
0x07ee: 0x03be,
0x07ef: 0x03bf,
0x07f0: 0x03c0,
0x07f1: 0x03c1,
0x07f2: 0x03c3,
0x07f3: 0x03c2,
0x07f4: 0x03c4,
0x07f5: 0x03c5,
0x07f6: 0x03c6,
0x07f7: 0x03c7,
0x07f8: 0x03c8,
0x07f9: 0x03c9,
0x08a1: 0x23b7,
0x08a2: 0x250c,
0x08a3: 0x2500,
0x08a4: 0x2320,
0x08a5: 0x2321,
0x08a6: 0x2502,
0x08a7: 0x23a1,
0x08a8: 0x23a3,
0x08a9: 0x23a4,
0x08aa: 0x23a6,
0x08ab: 0x239b,
0x08ac: 0x239d,
0x08ad: 0x239e,
0x08ae: 0x23a0,
0x08af: 0x23a8,
0x08b0: 0x23ac,
0x08bc: 0x2264,
0x08bd: 0x2260,
0x08be: 0x2265,
0x08bf: 0x222b,
0x08c0: 0x2234,
0x08c1: 0x221d,
0x08c2: 0x221e,
0x08c5: 0x2207,
0x08c8: 0x223c,
0x08c9: 0x2243,
0x08cd: 0x21d4,
0x08ce: 0x21d2,
0x08cf: 0x2261,
0x08d6: 0x221a,
0x08da: 0x2282,
0x08db: 0x2283,
0x08dc: 0x2229,
0x08dd: 0x222a,
0x08de: 0x2227,
0x08df: 0x2228,
0x08ef: 0x2202,
0x08f6: 0x0192,
0x08fb: 0x2190,
0x08fc: 0x2191,
0x08fd: 0x2192,
0x08fe: 0x2193,
0x09e0: 0x25c6,
0x09e1: 0x2592,
0x09e2: 0x2409,
0x09e3: 0x240c,
0x09e4: 0x240d,
0x09e5: 0x240a,
0x09e8: 0x2424,
0x09e9: 0x240b,
0x09ea: 0x2518,
0x09eb: 0x2510,
0x09ec: 0x250c,
0x09ed: 0x2514,
0x09ee: 0x253c,
0x09ef: 0x23ba,
0x09f0: 0x23bb,
0x09f1: 0x2500,
0x09f2: 0x23bc,
0x09f3: 0x23bd,
0x09f4: 0x251c,
0x09f5: 0x2524,
0x09f6: 0x2534,
0x09f7: 0x252c,
0x09f8: 0x2502,
0x0aa1: 0x2003,
0x0aa2: 0x2002,
0x0aa3: 0x2004,
0x0aa4: 0x2005,
0x0aa5: 0x2007,
0x0aa6: 0x2008,
0x0aa7: 0x2009,
0x0aa8: 0x200a,
0x0aa9: 0x2014,
0x0aaa: 0x2013,
0x0aae: 0x2026,
0x0aaf: 0x2025,
0x0ab0: 0x2153,
0x0ab1: 0x2154,
0x0ab2: 0x2155,
0x0ab3: 0x2156,
0x0ab4: 0x2157,
0x0ab5: 0x2158,
0x0ab6: 0x2159,
0x0ab7: 0x215a,
0x0ab8: 0x2105,
0x0abb: 0x2012,
0x0abc: 0x2329,
0x0abe: 0x232a,
0x0ac3: 0x215b,
0x0ac4: 0x215c,
0x0ac5: 0x215d,
0x0ac6: 0x215e,
0x0ac9: 0x2122,
0x0aca: 0x2613,
0x0acc: 0x25c1,
0x0acd: 0x25b7,
0x0ace: 0x25cb,
0x0acf: 0x25af,
0x0ad0: 0x2018,
0x0ad1: 0x2019,
0x0ad2: 0x201c,
0x0ad3: 0x201d,
0x0ad4: 0x211e,
0x0ad6: 0x2032,
0x0ad7: 0x2033,
0x0ad9: 0x271d,
0x0adb: 0x25ac,
0x0adc: 0x25c0,
0x0add: 0x25b6,
0x0ade: 0x25cf,
0x0adf: 0x25ae,
0x0ae0: 0x25e6,
0x0ae1: 0x25ab,
0x0ae2: 0x25ad,
0x0ae3: 0x25b3,
0x0ae4: 0x25bd,
0x0ae5: 0x2606,
0x0ae6: 0x2022,
0x0ae7: 0x25aa,
0x0ae8: 0x25b2,
0x0ae9: 0x25bc,
0x0aea: 0x261c,
0x0aeb: 0x261e,
0x0aec: 0x2663,
0x0aed: 0x2666,
0x0aee: 0x2665,
0x0af0: 0x2720,
0x0af1: 0x2020,
0x0af2: 0x2021,
0x0af3: 0x2713,
0x0af4: 0x2717,
0x0af5: 0x266f,
0x0af6: 0x266d,
0x0af7: 0x2642,
0x0af8: 0x2640,
0x0af9: 0x260e,
0x0afa: 0x2315,
0x0afb: 0x2117,
0x0afc: 0x2038,
0x0afd: 0x201a,
0x0afe: 0x201e,
0x0ba3: 0x003c,
0x0ba6: 0x003e,
0x0ba8: 0x2228,
0x0ba9: 0x2227,
0x0bc0: 0x00af,
0x0bc2: 0x22a5,
0x0bc3: 0x2229,
0x0bc4: 0x230a,
0x0bc6: 0x005f,
0x0bca: 0x2218,
0x0bcc: 0x2395,
0x0bce: 0x22a4,
0x0bcf: 0x25cb,
0x0bd3: 0x2308,
0x0bd6: 0x222a,
0x0bd8: 0x2283,
0x0bda: 0x2282,
0x0bdc: 0x22a2,
0x0bfc: 0x22a3,
0x0cdf: 0x2017,
0x0ce0: 0x05d0,
0x0ce1: 0x05d1,
0x0ce2: 0x05d2,
0x0ce3: 0x05d3,
0x0ce4: 0x05d4,
0x0ce5: 0x05d5,
0x0ce6: 0x05d6,
0x0ce7: 0x05d7,
0x0ce8: 0x05d8,
0x0ce9: 0x05d9,
0x0cea: 0x05da,
0x0ceb: 0x05db,
0x0cec: 0x05dc,
0x0ced: 0x05dd,
0x0cee: 0x05de,
0x0cef: 0x05df,
0x0cf0: 0x05e0,
0x0cf1: 0x05e1,
0x0cf2: 0x05e2,
0x0cf3: 0x05e3,
0x0cf4: 0x05e4,
0x0cf5: 0x05e5,
0x0cf6: 0x05e6,
0x0cf7: 0x05e7,
0x0cf8: 0x05e8,
0x0cf9: 0x05e9,
0x0cfa: 0x05ea,
0x0da1: 0x0e01,
0x0da2: 0x0e02,
0x0da3: 0x0e03,
0x0da4: 0x0e04,
0x0da5: 0x0e05,
0x0da6: 0x0e06,
0x0da7: 0x0e07,
0x0da8: 0x0e08,
0x0da9: 0x0e09,
0x0daa: 0x0e0a,
0x0dab: 0x0e0b,
0x0dac: 0x0e0c,
0x0dad: 0x0e0d,
0x0dae: 0x0e0e,
0x0daf: 0x0e0f,
0x0db0: 0x0e10,
0x0db1: 0x0e11,
0x0db2: 0x0e12,
0x0db3: 0x0e13,
0x0db4: 0x0e14,
0x0db5: 0x0e15,
0x0db6: 0x0e16,
0x0db7: 0x0e17,
0x0db8: 0x0e18,
0x0db9: 0x0e19,
0x0dba: 0x0e1a,
0x0dbb: 0x0e1b,
0x0dbc: 0x0e1c,
0x0dbd: 0x0e1d,
0x0dbe: 0x0e1e,
0x0dbf: 0x0e1f,
0x0dc0: 0x0e20,
0x0dc1: 0x0e21,
0x0dc2: 0x0e22,
0x0dc3: 0x0e23,
0x0dc4: 0x0e24,
0x0dc5: 0x0e25,
0x0dc6: 0x0e26,
0x0dc7: 0x0e27,
0x0dc8: 0x0e28,
0x0dc9: 0x0e29,
0x0dca: 0x0e2a,
0x0dcb: 0x0e2b,
0x0dcc: 0x0e2c,
0x0dcd: 0x0e2d,
0x0dce: 0x0e2e,
0x0dcf: 0x0e2f,
0x0dd0: 0x0e30,
0x0dd1: 0x0e31,
0x0dd2: 0x0e32,
0x0dd3: 0x0e33,
0x0dd4: 0x0e34,
0x0dd5: 0x0e35,
0x0dd6: 0x0e36,
0x0dd7: 0x0e37,
0x0dd8: 0x0e38,
0x0dd9: 0x0e39,
0x0dda: 0x0e3a,
0x0ddf: 0x0e3f,
0x0de0: 0x0e40,
0x0de1: 0x0e41,
0x0de2: 0x0e42,
0x0de3: 0x0e43,
0x0de4: 0x0e44,
0x0de5: 0x0e45,
0x0de6: 0x0e46,
0x0de7: 0x0e47,
0x0de8: 0x0e48,
0x0de9: 0x0e49,
0x0dea: 0x0e4a,
0x0deb: 0x0e4b,
0x0dec: 0x0e4c,
0x0ded: 0x0e4d,
0x0df0: 0x0e50,
0x0df1: 0x0e51,
0x0df2: 0x0e52,
0x0df3: 0x0e53,
0x0df4: 0x0e54,
0x0df5: 0x0e55,
0x0df6: 0x0e56,
0x0df7: 0x0e57,
0x0df8: 0x0e58,
0x0df9: 0x0e59,
0x0ea1: 0x3131,
0x0ea2: 0x3132,
0x0ea3: 0x3133,
0x0ea4: 0x3134,
0x0ea5: 0x3135,
0x0ea6: 0x3136,
0x0ea7: 0x3137,
0x0ea8: 0x3138,
0x0ea9: 0x3139,
0x0eaa: 0x313a,
0x0eab: 0x313b,
0x0eac: 0x313c,
0x0ead: 0x313d,
0x0eae: 0x313e,
0x0eaf: 0x313f,
0x0eb0: 0x3140,
0x0eb1: 0x3141,
0x0eb2: 0x3142,
0x0eb3: 0x3143,
0x0eb4: 0x3144,
0x0eb5: 0x3145,
0x0eb6: 0x3146,
0x0eb7: 0x3147,
0x0eb8: 0x3148,
0x0eb9: 0x3149,
0x0eba: 0x314a,
0x0ebb: 0x314b,
0x0ebc: 0x314c,
0x0ebd: 0x314d,
0x0ebe: 0x314e,
0x0ebf: 0x314f,
0x0ec0: 0x3150,
0x0ec1: 0x3151,
0x0ec2: 0x3152,
0x0ec3: 0x3153,
0x0ec4: 0x3154,
0x0ec5: 0x3155,
0x0ec6: 0x3156,
0x0ec7: 0x3157,
0x0ec8: 0x3158,
0x0ec9: 0x3159,
0x0eca: 0x315a,
0x0ecb: 0x315b,
0x0ecc: 0x315c,
0x0ecd: 0x315d,
0x0ece: 0x315e,
0x0ecf: 0x315f,
0x0ed0: 0x3160,
0x0ed1: 0x3161,
0x0ed2: 0x3162,
0x0ed3: 0x3163,
0x0ed4: 0x11a8,
0x0ed5: 0x11a9,
0x0ed6: 0x11aa,
0x0ed7: 0x11ab,
0x0ed8: 0x11ac,
0x0ed9: 0x11ad,
0x0eda: 0x11ae,
0x0edb: 0x11af,
0x0edc: 0x11b0,
0x0edd: 0x11b1,
0x0ede: 0x11b2,
0x0edf: 0x11b3,
0x0ee0: 0x11b4,
0x0ee1: 0x11b5,
0x0ee2: 0x11b6,
0x0ee3: 0x11b7,
0x0ee4: 0x11b8,
0x0ee5: 0x11b9,
0x0ee6: 0x11ba,
0x0ee7: 0x11bb,
0x0ee8: 0x11bc,
0x0ee9: 0x11bd,
0x0eea: 0x11be,
0x0eeb: 0x11bf,
0x0eec: 0x11c0,
0x0eed: 0x11c1,
0x0eee: 0x11c2,
0x0eef: 0x316d,
0x0ef0: 0x3171,
0x0ef1: 0x3178,
0x0ef2: 0x317f,
0x0ef3: 0x3181,
0x0ef4: 0x3184,
0x0ef5: 0x3186,
0x0ef6: 0x318d,
0x0ef7: 0x318e,
0x0ef8: 0x11eb,
0x0ef9: 0x11f0,
0x0efa: 0x11f9,
0x0eff: 0x20a9,
0x13a4: 0x20ac,
0x13bc: 0x0152,
0x13bd: 0x0153,
0x13be: 0x0178,
0x20ac: 0x20ac,
0xfe50: '`',
0xfe51: 0x00b4,
0xfe52: '^',
0xfe53: '~',
0xfe54: 0x00af,
0xfe55: 0x02d8,
0xfe56: 0x02d9,
0xfe57: 0x00a8,
0xfe58: 0x02da,
0xfe59: 0x02dd,
0xfe5a: 0x02c7,
0xfe5b: 0x00b8,
0xfe5c: 0x02db,
0xfe5d: 0x037a,
0xfe5e: 0x309b,
0xfe5f: 0x309c,
0xfe63: '/',
0xfe64: 0x02bc,
0xfe65: 0x02bd,
0xfe66: 0x02f5,
0xfe67: 0x02f3,
0xfe68: 0x02cd,
0xfe69: 0xa788,
0xfe6a: 0x02f7,
0xfe6e: ',',
0xfe6f: 0x00a4,
0xfe80: 'a', // XK_dead_a
0xfe81: 'A', // XK_dead_A
0xfe82: 'e', // XK_dead_e
0xfe83: 'E', // XK_dead_E
0xfe84: 'i', // XK_dead_i
0xfe85: 'I', // XK_dead_I
0xfe86: 'o', // XK_dead_o
0xfe87: 'O', // XK_dead_O
0xfe88: 'u', // XK_dead_u
0xfe89: 'U', // XK_dead_U
0xfe8a: 0x0259,
0xfe8b: 0x018f,
0xfe8c: 0x00b5,
0xfe90: '_',
0xfe91: 0x02c8,
0xfe92: 0x02cc,
0xff80: ' ', // XKB_KEY_KP_Space
0xff95: 0x0037, // XKB_KEY_KP_7
0xff96: 0x0034, // XKB_KEY_KP_4
0xff97: 0x0038, // XKB_KEY_KP_8
0xff98: 0x0036, // XKB_KEY_KP_6
0xff99: 0x0032, // XKB_KEY_KP_2
0xff9a: 0x0039, // XKB_KEY_KP_9
0xff9b: 0x0033, // XKB_KEY_KP_3
0xff9c: 0x0031, // XKB_KEY_KP_1
0xff9d: 0x0035, // XKB_KEY_KP_5
0xff9e: 0x0030, // XKB_KEY_KP_0
0xffaa: '*', // XKB_KEY_KP_Multiply
0xffab: '+', // XKB_KEY_KP_Add
0xffac: ',', // XKB_KEY_KP_Separator
0xffad: '-', // XKB_KEY_KP_Subtract
0xffae: '.', // XKB_KEY_KP_Decimal
0xffaf: '/', // XKB_KEY_KP_Divide
0xffb0: 0x0030, // XKB_KEY_KP_0
0xffb1: 0x0031, // XKB_KEY_KP_1
0xffb2: 0x0032, // XKB_KEY_KP_2
0xffb3: 0x0033, // XKB_KEY_KP_3
0xffb4: 0x0034, // XKB_KEY_KP_4
0xffb5: 0x0035, // XKB_KEY_KP_5
0xffb6: 0x0036, // XKB_KEY_KP_6
0xffb7: 0x0037, // XKB_KEY_KP_7
0xffb8: 0x0038, // XKB_KEY_KP_8
0xffb9: 0x0039, // XKB_KEY_KP_9
0xffbd: '=', // XKB_KEY_KP_Equal
}
// _glfwKeySym2Unicode converts XKB KeySym to Unicode.
//
//export _glfwKeySym2Unicode
func _glfwKeySym2Unicode(keysym C.uint) C.uint32_t {
// First check for Latin-1 characters (1:1 mapping)
if (keysym >= 0x0020 && keysym <= 0x007e) || (keysym >= 0x00a0 && keysym <= 0x00ff) {
return keysym
}
// Also check for directly encoded 24-bit UCS characters
if (keysym & 0xff000000) == 0x01000000 {
return keysym & 0x00ffffff
}
ucs, ok := keysymtab[uint32(keysym)]
if !ok {
return C.GLFW_INVALID_CODEPOINT
}
return C.uint32_t(ucs)
}
@@ -4,7 +4,8 @@
//go:build freebsd || linux || netbsd || openbsd
#include <stdint.h>
#define GLFW_INVALID_CODEPOINT 0xffffffffu
uint32_t _glfwKeySym2Unicode(unsigned int keysym);