github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/raylib/external/glfw/src/input.c (about) 1 //======================================================================== 2 // GLFW 3.4 - www.glfw.org 3 //------------------------------------------------------------------------ 4 // Copyright (c) 2002-2006 Marcus Geelnard 5 // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> 6 // 7 // This software is provided 'as-is', without any express or implied 8 // warranty. In no event will the authors be held liable for any damages 9 // arising from the use of this software. 10 // 11 // Permission is granted to anyone to use this software for any purpose, 12 // including commercial applications, and to alter it and redistribute it 13 // freely, subject to the following restrictions: 14 // 15 // 1. The origin of this software must not be misrepresented; you must not 16 // claim that you wrote the original software. If you use this software 17 // in a product, an acknowledgment in the product documentation would 18 // be appreciated but is not required. 19 // 20 // 2. Altered source versions must be plainly marked as such, and must not 21 // be misrepresented as being the original software. 22 // 23 // 3. This notice may not be removed or altered from any source 24 // distribution. 25 // 26 //======================================================================== 27 // Please use C89 style variable declarations in this file because VS 2010 28 //======================================================================== 29 30 #include "internal.h" 31 #include "mappings.h" 32 33 #include <assert.h> 34 #include <float.h> 35 #include <math.h> 36 #include <stdlib.h> 37 #include <string.h> 38 39 // Internal key state used for sticky keys 40 #define _GLFW_STICK 3 41 42 // Internal constants for gamepad mapping source types 43 #define _GLFW_JOYSTICK_AXIS 1 44 #define _GLFW_JOYSTICK_BUTTON 2 45 #define _GLFW_JOYSTICK_HATBIT 3 46 47 #define GLFW_MOD_MASK (GLFW_MOD_SHIFT | \ 48 GLFW_MOD_CONTROL | \ 49 GLFW_MOD_ALT | \ 50 GLFW_MOD_SUPER | \ 51 GLFW_MOD_CAPS_LOCK | \ 52 GLFW_MOD_NUM_LOCK) 53 54 // Initializes the platform joystick API if it has not been already 55 // 56 static GLFWbool initJoysticks(void) 57 { 58 if (!_glfw.joysticksInitialized) 59 { 60 if (!_glfw.platform.initJoysticks()) 61 { 62 _glfw.platform.terminateJoysticks(); 63 return GLFW_FALSE; 64 } 65 } 66 67 return _glfw.joysticksInitialized = GLFW_TRUE; 68 } 69 70 // Finds a mapping based on joystick GUID 71 // 72 static _GLFWmapping* findMapping(const char* guid) 73 { 74 int i; 75 76 for (i = 0; i < _glfw.mappingCount; i++) 77 { 78 if (strcmp(_glfw.mappings[i].guid, guid) == 0) 79 return _glfw.mappings + i; 80 } 81 82 return NULL; 83 } 84 85 // Checks whether a gamepad mapping element is present in the hardware 86 // 87 static GLFWbool isValidElementForJoystick(const _GLFWmapelement* e, 88 const _GLFWjoystick* js) 89 { 90 if (e->type == _GLFW_JOYSTICK_HATBIT && (e->index >> 4) >= js->hatCount) 91 return GLFW_FALSE; 92 else if (e->type == _GLFW_JOYSTICK_BUTTON && e->index >= js->buttonCount) 93 return GLFW_FALSE; 94 else if (e->type == _GLFW_JOYSTICK_AXIS && e->index >= js->axisCount) 95 return GLFW_FALSE; 96 97 return GLFW_TRUE; 98 } 99 100 // Finds a mapping based on joystick GUID and verifies element indices 101 // 102 static _GLFWmapping* findValidMapping(const _GLFWjoystick* js) 103 { 104 _GLFWmapping* mapping = findMapping(js->guid); 105 if (mapping) 106 { 107 int i; 108 109 for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++) 110 { 111 if (!isValidElementForJoystick(mapping->buttons + i, js)) 112 return NULL; 113 } 114 115 for (i = 0; i <= GLFW_GAMEPAD_AXIS_LAST; i++) 116 { 117 if (!isValidElementForJoystick(mapping->axes + i, js)) 118 return NULL; 119 } 120 } 121 122 return mapping; 123 } 124 125 // Parses an SDL_GameControllerDB line and adds it to the mapping list 126 // 127 static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string) 128 { 129 const char* c = string; 130 size_t i, length; 131 struct 132 { 133 const char* name; 134 _GLFWmapelement* element; 135 } fields[] = 136 { 137 { "platform", NULL }, 138 { "a", mapping->buttons + GLFW_GAMEPAD_BUTTON_A }, 139 { "b", mapping->buttons + GLFW_GAMEPAD_BUTTON_B }, 140 { "x", mapping->buttons + GLFW_GAMEPAD_BUTTON_X }, 141 { "y", mapping->buttons + GLFW_GAMEPAD_BUTTON_Y }, 142 { "back", mapping->buttons + GLFW_GAMEPAD_BUTTON_BACK }, 143 { "start", mapping->buttons + GLFW_GAMEPAD_BUTTON_START }, 144 { "guide", mapping->buttons + GLFW_GAMEPAD_BUTTON_GUIDE }, 145 { "leftshoulder", mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_BUMPER }, 146 { "rightshoulder", mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER }, 147 { "leftstick", mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_THUMB }, 148 { "rightstick", mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_THUMB }, 149 { "dpup", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_UP }, 150 { "dpright", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_RIGHT }, 151 { "dpdown", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_DOWN }, 152 { "dpleft", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_LEFT }, 153 { "lefttrigger", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_TRIGGER }, 154 { "righttrigger", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER }, 155 { "leftx", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_X }, 156 { "lefty", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_Y }, 157 { "rightx", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_X }, 158 { "righty", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_Y } 159 }; 160 161 length = strcspn(c, ","); 162 if (length != 32 || c[length] != ',') 163 { 164 _glfwInputError(GLFW_INVALID_VALUE, NULL); 165 return GLFW_FALSE; 166 } 167 168 memcpy(mapping->guid, c, length); 169 c += length + 1; 170 171 length = strcspn(c, ","); 172 if (length >= sizeof(mapping->name) || c[length] != ',') 173 { 174 _glfwInputError(GLFW_INVALID_VALUE, NULL); 175 return GLFW_FALSE; 176 } 177 178 memcpy(mapping->name, c, length); 179 c += length + 1; 180 181 while (*c) 182 { 183 // TODO: Implement output modifiers 184 if (*c == '+' || *c == '-') 185 return GLFW_FALSE; 186 187 for (i = 0; i < sizeof(fields) / sizeof(fields[0]); i++) 188 { 189 length = strlen(fields[i].name); 190 if (strncmp(c, fields[i].name, length) != 0 || c[length] != ':') 191 continue; 192 193 c += length + 1; 194 195 if (fields[i].element) 196 { 197 _GLFWmapelement* e = fields[i].element; 198 int8_t minimum = -1; 199 int8_t maximum = 1; 200 201 if (*c == '+') 202 { 203 minimum = 0; 204 c += 1; 205 } 206 else if (*c == '-') 207 { 208 maximum = 0; 209 c += 1; 210 } 211 212 if (*c == 'a') 213 e->type = _GLFW_JOYSTICK_AXIS; 214 else if (*c == 'b') 215 e->type = _GLFW_JOYSTICK_BUTTON; 216 else if (*c == 'h') 217 e->type = _GLFW_JOYSTICK_HATBIT; 218 else 219 break; 220 221 if (e->type == _GLFW_JOYSTICK_HATBIT) 222 { 223 const unsigned long hat = strtoul(c + 1, (char**) &c, 10); 224 const unsigned long bit = strtoul(c + 1, (char**) &c, 10); 225 e->index = (uint8_t) ((hat << 4) | bit); 226 } 227 else 228 e->index = (uint8_t) strtoul(c + 1, (char**) &c, 10); 229 230 if (e->type == _GLFW_JOYSTICK_AXIS) 231 { 232 e->axisScale = 2 / (maximum - minimum); 233 e->axisOffset = -(maximum + minimum); 234 235 if (*c == '~') 236 { 237 e->axisScale = -e->axisScale; 238 e->axisOffset = -e->axisOffset; 239 } 240 } 241 } 242 else 243 { 244 const char* name = _glfw.platform.getMappingName(); 245 length = strlen(name); 246 if (strncmp(c, name, length) != 0) 247 return GLFW_FALSE; 248 } 249 250 break; 251 } 252 253 c += strcspn(c, ","); 254 c += strspn(c, ","); 255 } 256 257 for (i = 0; i < 32; i++) 258 { 259 if (mapping->guid[i] >= 'A' && mapping->guid[i] <= 'F') 260 mapping->guid[i] += 'a' - 'A'; 261 } 262 263 _glfw.platform.updateGamepadGUID(mapping->guid); 264 return GLFW_TRUE; 265 } 266 267 268 ////////////////////////////////////////////////////////////////////////// 269 ////// GLFW event API ////// 270 ////////////////////////////////////////////////////////////////////////// 271 272 // Notifies shared code of a physical key event 273 // 274 void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods) 275 { 276 assert(window != NULL); 277 assert(key >= 0 || key == GLFW_KEY_UNKNOWN); 278 assert(key <= GLFW_KEY_LAST); 279 assert(action == GLFW_PRESS || action == GLFW_RELEASE); 280 assert(mods == (mods & GLFW_MOD_MASK)); 281 282 if (key >= 0 && key <= GLFW_KEY_LAST) 283 { 284 GLFWbool repeated = GLFW_FALSE; 285 286 if (action == GLFW_RELEASE && window->keys[key] == GLFW_RELEASE) 287 return; 288 289 if (action == GLFW_PRESS && window->keys[key] == GLFW_PRESS) 290 repeated = GLFW_TRUE; 291 292 if (action == GLFW_RELEASE && window->stickyKeys) 293 window->keys[key] = _GLFW_STICK; 294 else 295 window->keys[key] = (char) action; 296 297 if (repeated) 298 action = GLFW_REPEAT; 299 } 300 301 if (!window->lockKeyMods) 302 mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK); 303 304 if (window->callbacks.key) 305 window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods); 306 } 307 308 // Notifies shared code of a Unicode codepoint input event 309 // The 'plain' parameter determines whether to emit a regular character event 310 // 311 void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool plain) 312 { 313 assert(window != NULL); 314 assert(mods == (mods & GLFW_MOD_MASK)); 315 assert(plain == GLFW_TRUE || plain == GLFW_FALSE); 316 317 if (codepoint < 32 || (codepoint > 126 && codepoint < 160)) 318 return; 319 320 if (!window->lockKeyMods) 321 mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK); 322 323 if (window->callbacks.charmods) 324 window->callbacks.charmods((GLFWwindow*) window, codepoint, mods); 325 326 if (plain) 327 { 328 if (window->callbacks.character) 329 window->callbacks.character((GLFWwindow*) window, codepoint); 330 } 331 } 332 333 // Notifies shared code of a scroll event 334 // 335 void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset) 336 { 337 assert(window != NULL); 338 assert(xoffset > -FLT_MAX); 339 assert(xoffset < FLT_MAX); 340 assert(yoffset > -FLT_MAX); 341 assert(yoffset < FLT_MAX); 342 343 if (window->callbacks.scroll) 344 window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset); 345 } 346 347 // Notifies shared code of a mouse button click event 348 // 349 void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods) 350 { 351 assert(window != NULL); 352 assert(button >= 0); 353 assert(button <= GLFW_MOUSE_BUTTON_LAST); 354 assert(action == GLFW_PRESS || action == GLFW_RELEASE); 355 assert(mods == (mods & GLFW_MOD_MASK)); 356 357 if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST) 358 return; 359 360 if (!window->lockKeyMods) 361 mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK); 362 363 if (action == GLFW_RELEASE && window->stickyMouseButtons) 364 window->mouseButtons[button] = _GLFW_STICK; 365 else 366 window->mouseButtons[button] = (char) action; 367 368 if (window->callbacks.mouseButton) 369 window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods); 370 } 371 372 // Notifies shared code of a cursor motion event 373 // The position is specified in content area relative screen coordinates 374 // 375 void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos) 376 { 377 assert(window != NULL); 378 assert(xpos > -FLT_MAX); 379 assert(xpos < FLT_MAX); 380 assert(ypos > -FLT_MAX); 381 assert(ypos < FLT_MAX); 382 383 if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos) 384 return; 385 386 window->virtualCursorPosX = xpos; 387 window->virtualCursorPosY = ypos; 388 389 if (window->callbacks.cursorPos) 390 window->callbacks.cursorPos((GLFWwindow*) window, xpos, ypos); 391 } 392 393 // Notifies shared code of a cursor enter/leave event 394 // 395 void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered) 396 { 397 assert(window != NULL); 398 assert(entered == GLFW_TRUE || entered == GLFW_FALSE); 399 400 if (window->callbacks.cursorEnter) 401 window->callbacks.cursorEnter((GLFWwindow*) window, entered); 402 } 403 404 // Notifies shared code of files or directories dropped on a window 405 // 406 void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths) 407 { 408 assert(window != NULL); 409 assert(count > 0); 410 assert(paths != NULL); 411 412 if (window->callbacks.drop) 413 window->callbacks.drop((GLFWwindow*) window, count, paths); 414 } 415 416 // Notifies shared code of a joystick connection or disconnection 417 // 418 void _glfwInputJoystick(_GLFWjoystick* js, int event) 419 { 420 assert(js != NULL); 421 assert(event == GLFW_CONNECTED || event == GLFW_DISCONNECTED); 422 423 if (event == GLFW_CONNECTED) 424 js->connected = GLFW_TRUE; 425 else if (event == GLFW_DISCONNECTED) 426 js->connected = GLFW_FALSE; 427 428 if (_glfw.callbacks.joystick) 429 _glfw.callbacks.joystick((int) (js - _glfw.joysticks), event); 430 } 431 432 // Notifies shared code of the new value of a joystick axis 433 // 434 void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value) 435 { 436 assert(js != NULL); 437 assert(axis >= 0); 438 assert(axis < js->axisCount); 439 440 js->axes[axis] = value; 441 } 442 443 // Notifies shared code of the new value of a joystick button 444 // 445 void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value) 446 { 447 assert(js != NULL); 448 assert(button >= 0); 449 assert(button < js->buttonCount); 450 assert(value == GLFW_PRESS || value == GLFW_RELEASE); 451 452 js->buttons[button] = value; 453 } 454 455 // Notifies shared code of the new value of a joystick hat 456 // 457 void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value) 458 { 459 int base; 460 461 assert(js != NULL); 462 assert(hat >= 0); 463 assert(hat < js->hatCount); 464 465 // Valid hat values only use the least significant nibble and have at most two bits 466 // set, which can be considered adjacent plus an arbitrary rotation within the nibble 467 assert((value & 0xf0) == 0); 468 assert((value & ((value << 2) | (value >> 2))) == 0); 469 470 base = js->buttonCount + hat * 4; 471 472 js->buttons[base + 0] = (value & 0x01) ? GLFW_PRESS : GLFW_RELEASE; 473 js->buttons[base + 1] = (value & 0x02) ? GLFW_PRESS : GLFW_RELEASE; 474 js->buttons[base + 2] = (value & 0x04) ? GLFW_PRESS : GLFW_RELEASE; 475 js->buttons[base + 3] = (value & 0x08) ? GLFW_PRESS : GLFW_RELEASE; 476 477 js->hats[hat] = value; 478 } 479 480 481 ////////////////////////////////////////////////////////////////////////// 482 ////// GLFW internal API ////// 483 ////////////////////////////////////////////////////////////////////////// 484 485 // Adds the built-in set of gamepad mappings 486 // 487 void _glfwInitGamepadMappings(void) 488 { 489 size_t i; 490 const size_t count = sizeof(_glfwDefaultMappings) / sizeof(char*); 491 _glfw.mappings = _glfw_calloc(count, sizeof(_GLFWmapping)); 492 493 for (i = 0; i < count; i++) 494 { 495 if (parseMapping(&_glfw.mappings[_glfw.mappingCount], _glfwDefaultMappings[i])) 496 _glfw.mappingCount++; 497 } 498 } 499 500 // Returns an available joystick object with arrays and name allocated 501 // 502 _GLFWjoystick* _glfwAllocJoystick(const char* name, 503 const char* guid, 504 int axisCount, 505 int buttonCount, 506 int hatCount) 507 { 508 int jid; 509 _GLFWjoystick* js; 510 511 for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) 512 { 513 if (!_glfw.joysticks[jid].allocated) 514 break; 515 } 516 517 if (jid > GLFW_JOYSTICK_LAST) 518 return NULL; 519 520 js = _glfw.joysticks + jid; 521 js->allocated = GLFW_TRUE; 522 js->axes = _glfw_calloc(axisCount, sizeof(float)); 523 js->buttons = _glfw_calloc(buttonCount + (size_t) hatCount * 4, 1); 524 js->hats = _glfw_calloc(hatCount, 1); 525 js->axisCount = axisCount; 526 js->buttonCount = buttonCount; 527 js->hatCount = hatCount; 528 529 strncpy(js->name, name, sizeof(js->name) - 1); 530 strncpy(js->guid, guid, sizeof(js->guid) - 1); 531 js->mapping = findValidMapping(js); 532 533 return js; 534 } 535 536 // Frees arrays and name and flags the joystick object as unused 537 // 538 void _glfwFreeJoystick(_GLFWjoystick* js) 539 { 540 _glfw_free(js->axes); 541 _glfw_free(js->buttons); 542 _glfw_free(js->hats); 543 memset(js, 0, sizeof(_GLFWjoystick)); 544 } 545 546 // Center the cursor in the content area of the specified window 547 // 548 void _glfwCenterCursorInContentArea(_GLFWwindow* window) 549 { 550 int width, height; 551 552 _glfw.platform.getWindowSize(window, &width, &height); 553 _glfw.platform.setCursorPos(window, width / 2.0, height / 2.0); 554 } 555 556 557 ////////////////////////////////////////////////////////////////////////// 558 ////// GLFW public API ////// 559 ////////////////////////////////////////////////////////////////////////// 560 561 GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode) 562 { 563 _GLFWwindow* window = (_GLFWwindow*) handle; 564 assert(window != NULL); 565 566 _GLFW_REQUIRE_INIT_OR_RETURN(0); 567 568 switch (mode) 569 { 570 case GLFW_CURSOR: 571 return window->cursorMode; 572 case GLFW_STICKY_KEYS: 573 return window->stickyKeys; 574 case GLFW_STICKY_MOUSE_BUTTONS: 575 return window->stickyMouseButtons; 576 case GLFW_LOCK_KEY_MODS: 577 return window->lockKeyMods; 578 case GLFW_RAW_MOUSE_MOTION: 579 return window->rawMouseMotion; 580 } 581 582 _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); 583 return 0; 584 } 585 586 GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) 587 { 588 _GLFWwindow* window = (_GLFWwindow*) handle; 589 assert(window != NULL); 590 591 _GLFW_REQUIRE_INIT(); 592 593 switch (mode) 594 { 595 case GLFW_CURSOR: 596 { 597 if (value != GLFW_CURSOR_NORMAL && 598 value != GLFW_CURSOR_HIDDEN && 599 value != GLFW_CURSOR_DISABLED && 600 value != GLFW_CURSOR_CAPTURED) 601 { 602 _glfwInputError(GLFW_INVALID_ENUM, 603 "Invalid cursor mode 0x%08X", 604 value); 605 return; 606 } 607 608 if (window->cursorMode == value) 609 return; 610 611 window->cursorMode = value; 612 613 _glfw.platform.getCursorPos(window, 614 &window->virtualCursorPosX, 615 &window->virtualCursorPosY); 616 _glfw.platform.setCursorMode(window, value); 617 return; 618 } 619 620 case GLFW_STICKY_KEYS: 621 { 622 value = value ? GLFW_TRUE : GLFW_FALSE; 623 if (window->stickyKeys == value) 624 return; 625 626 if (!value) 627 { 628 int i; 629 630 // Release all sticky keys 631 for (i = 0; i <= GLFW_KEY_LAST; i++) 632 { 633 if (window->keys[i] == _GLFW_STICK) 634 window->keys[i] = GLFW_RELEASE; 635 } 636 } 637 638 window->stickyKeys = value; 639 return; 640 } 641 642 case GLFW_STICKY_MOUSE_BUTTONS: 643 { 644 value = value ? GLFW_TRUE : GLFW_FALSE; 645 if (window->stickyMouseButtons == value) 646 return; 647 648 if (!value) 649 { 650 int i; 651 652 // Release all sticky mouse buttons 653 for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++) 654 { 655 if (window->mouseButtons[i] == _GLFW_STICK) 656 window->mouseButtons[i] = GLFW_RELEASE; 657 } 658 } 659 660 window->stickyMouseButtons = value; 661 return; 662 } 663 664 case GLFW_LOCK_KEY_MODS: 665 { 666 window->lockKeyMods = value ? GLFW_TRUE : GLFW_FALSE; 667 return; 668 } 669 670 case GLFW_RAW_MOUSE_MOTION: 671 { 672 if (!_glfw.platform.rawMouseMotionSupported()) 673 { 674 _glfwInputError(GLFW_PLATFORM_ERROR, 675 "Raw mouse motion is not supported on this system"); 676 return; 677 } 678 679 value = value ? GLFW_TRUE : GLFW_FALSE; 680 if (window->rawMouseMotion == value) 681 return; 682 683 window->rawMouseMotion = value; 684 _glfw.platform.setRawMouseMotion(window, value); 685 return; 686 } 687 } 688 689 _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); 690 } 691 692 GLFWAPI int glfwRawMouseMotionSupported(void) 693 { 694 _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); 695 return _glfw.platform.rawMouseMotionSupported(); 696 } 697 698 GLFWAPI const char* glfwGetKeyName(int key, int scancode) 699 { 700 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 701 702 if (key != GLFW_KEY_UNKNOWN) 703 { 704 if (key != GLFW_KEY_KP_EQUAL && 705 (key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) && 706 (key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_WORLD_2)) 707 { 708 return NULL; 709 } 710 711 scancode = _glfw.platform.getKeyScancode(key); 712 } 713 714 return _glfw.platform.getScancodeName(scancode); 715 } 716 717 GLFWAPI int glfwGetKeyScancode(int key) 718 { 719 _GLFW_REQUIRE_INIT_OR_RETURN(-1); 720 721 if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST) 722 { 723 _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key); 724 return GLFW_RELEASE; 725 } 726 727 return _glfw.platform.getKeyScancode(key); 728 } 729 730 GLFWAPI int glfwGetKey(GLFWwindow* handle, int key) 731 { 732 _GLFWwindow* window = (_GLFWwindow*) handle; 733 assert(window != NULL); 734 735 _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE); 736 737 if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST) 738 { 739 _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key); 740 return GLFW_RELEASE; 741 } 742 743 if (window->keys[key] == _GLFW_STICK) 744 { 745 // Sticky mode: release key now 746 window->keys[key] = GLFW_RELEASE; 747 return GLFW_PRESS; 748 } 749 750 return (int) window->keys[key]; 751 } 752 753 GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button) 754 { 755 _GLFWwindow* window = (_GLFWwindow*) handle; 756 assert(window != NULL); 757 758 _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE); 759 760 if (button < GLFW_MOUSE_BUTTON_1 || button > GLFW_MOUSE_BUTTON_LAST) 761 { 762 _glfwInputError(GLFW_INVALID_ENUM, "Invalid mouse button %i", button); 763 return GLFW_RELEASE; 764 } 765 766 if (window->mouseButtons[button] == _GLFW_STICK) 767 { 768 // Sticky mode: release mouse button now 769 window->mouseButtons[button] = GLFW_RELEASE; 770 return GLFW_PRESS; 771 } 772 773 return (int) window->mouseButtons[button]; 774 } 775 776 GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos) 777 { 778 _GLFWwindow* window = (_GLFWwindow*) handle; 779 assert(window != NULL); 780 781 if (xpos) 782 *xpos = 0; 783 if (ypos) 784 *ypos = 0; 785 786 _GLFW_REQUIRE_INIT(); 787 788 if (window->cursorMode == GLFW_CURSOR_DISABLED) 789 { 790 if (xpos) 791 *xpos = window->virtualCursorPosX; 792 if (ypos) 793 *ypos = window->virtualCursorPosY; 794 } 795 else 796 _glfw.platform.getCursorPos(window, xpos, ypos); 797 } 798 799 GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos) 800 { 801 _GLFWwindow* window = (_GLFWwindow*) handle; 802 assert(window != NULL); 803 804 _GLFW_REQUIRE_INIT(); 805 806 if (xpos != xpos || xpos < -DBL_MAX || xpos > DBL_MAX || 807 ypos != ypos || ypos < -DBL_MAX || ypos > DBL_MAX) 808 { 809 _glfwInputError(GLFW_INVALID_VALUE, 810 "Invalid cursor position %f %f", 811 xpos, ypos); 812 return; 813 } 814 815 if (!_glfw.platform.windowFocused(window)) 816 return; 817 818 if (window->cursorMode == GLFW_CURSOR_DISABLED) 819 { 820 // Only update the accumulated position if the cursor is disabled 821 window->virtualCursorPosX = xpos; 822 window->virtualCursorPosY = ypos; 823 } 824 else 825 { 826 // Update system cursor position 827 _glfw.platform.setCursorPos(window, xpos, ypos); 828 } 829 } 830 831 GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot) 832 { 833 _GLFWcursor* cursor; 834 835 assert(image != NULL); 836 assert(image->pixels != NULL); 837 838 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 839 840 if (image->width <= 0 || image->height <= 0) 841 { 842 _glfwInputError(GLFW_INVALID_VALUE, "Invalid image dimensions for cursor"); 843 return NULL; 844 } 845 846 cursor = _glfw_calloc(1, sizeof(_GLFWcursor)); 847 cursor->next = _glfw.cursorListHead; 848 _glfw.cursorListHead = cursor; 849 850 if (!_glfw.platform.createCursor(cursor, image, xhot, yhot)) 851 { 852 glfwDestroyCursor((GLFWcursor*) cursor); 853 return NULL; 854 } 855 856 return (GLFWcursor*) cursor; 857 } 858 859 GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape) 860 { 861 _GLFWcursor* cursor; 862 863 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 864 865 if (shape != GLFW_ARROW_CURSOR && 866 shape != GLFW_IBEAM_CURSOR && 867 shape != GLFW_CROSSHAIR_CURSOR && 868 shape != GLFW_POINTING_HAND_CURSOR && 869 shape != GLFW_RESIZE_EW_CURSOR && 870 shape != GLFW_RESIZE_NS_CURSOR && 871 shape != GLFW_RESIZE_NWSE_CURSOR && 872 shape != GLFW_RESIZE_NESW_CURSOR && 873 shape != GLFW_RESIZE_ALL_CURSOR && 874 shape != GLFW_NOT_ALLOWED_CURSOR) 875 { 876 _glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor 0x%08X", shape); 877 return NULL; 878 } 879 880 cursor = _glfw_calloc(1, sizeof(_GLFWcursor)); 881 cursor->next = _glfw.cursorListHead; 882 _glfw.cursorListHead = cursor; 883 884 if (!_glfw.platform.createStandardCursor(cursor, shape)) 885 { 886 glfwDestroyCursor((GLFWcursor*) cursor); 887 return NULL; 888 } 889 890 return (GLFWcursor*) cursor; 891 } 892 893 GLFWAPI void glfwDestroyCursor(GLFWcursor* handle) 894 { 895 _GLFWcursor* cursor = (_GLFWcursor*) handle; 896 897 _GLFW_REQUIRE_INIT(); 898 899 if (cursor == NULL) 900 return; 901 902 // Make sure the cursor is not being used by any window 903 { 904 _GLFWwindow* window; 905 906 for (window = _glfw.windowListHead; window; window = window->next) 907 { 908 if (window->cursor == cursor) 909 glfwSetCursor((GLFWwindow*) window, NULL); 910 } 911 } 912 913 _glfw.platform.destroyCursor(cursor); 914 915 // Unlink cursor from global linked list 916 { 917 _GLFWcursor** prev = &_glfw.cursorListHead; 918 919 while (*prev != cursor) 920 prev = &((*prev)->next); 921 922 *prev = cursor->next; 923 } 924 925 _glfw_free(cursor); 926 } 927 928 GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle) 929 { 930 _GLFWwindow* window = (_GLFWwindow*) windowHandle; 931 _GLFWcursor* cursor = (_GLFWcursor*) cursorHandle; 932 assert(window != NULL); 933 934 _GLFW_REQUIRE_INIT(); 935 936 window->cursor = cursor; 937 938 _glfw.platform.setCursor(window, cursor); 939 } 940 941 GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun) 942 { 943 _GLFWwindow* window = (_GLFWwindow*) handle; 944 assert(window != NULL); 945 946 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 947 _GLFW_SWAP(GLFWkeyfun, window->callbacks.key, cbfun); 948 return cbfun; 949 } 950 951 GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* handle, GLFWcharfun cbfun) 952 { 953 _GLFWwindow* window = (_GLFWwindow*) handle; 954 assert(window != NULL); 955 956 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 957 _GLFW_SWAP(GLFWcharfun, window->callbacks.character, cbfun); 958 return cbfun; 959 } 960 961 GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* handle, GLFWcharmodsfun cbfun) 962 { 963 _GLFWwindow* window = (_GLFWwindow*) handle; 964 assert(window != NULL); 965 966 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 967 _GLFW_SWAP(GLFWcharmodsfun, window->callbacks.charmods, cbfun); 968 return cbfun; 969 } 970 971 GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle, 972 GLFWmousebuttonfun cbfun) 973 { 974 _GLFWwindow* window = (_GLFWwindow*) handle; 975 assert(window != NULL); 976 977 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 978 _GLFW_SWAP(GLFWmousebuttonfun, window->callbacks.mouseButton, cbfun); 979 return cbfun; 980 } 981 982 GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* handle, 983 GLFWcursorposfun cbfun) 984 { 985 _GLFWwindow* window = (_GLFWwindow*) handle; 986 assert(window != NULL); 987 988 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 989 _GLFW_SWAP(GLFWcursorposfun, window->callbacks.cursorPos, cbfun); 990 return cbfun; 991 } 992 993 GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* handle, 994 GLFWcursorenterfun cbfun) 995 { 996 _GLFWwindow* window = (_GLFWwindow*) handle; 997 assert(window != NULL); 998 999 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1000 _GLFW_SWAP(GLFWcursorenterfun, window->callbacks.cursorEnter, cbfun); 1001 return cbfun; 1002 } 1003 1004 GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* handle, 1005 GLFWscrollfun cbfun) 1006 { 1007 _GLFWwindow* window = (_GLFWwindow*) handle; 1008 assert(window != NULL); 1009 1010 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1011 _GLFW_SWAP(GLFWscrollfun, window->callbacks.scroll, cbfun); 1012 return cbfun; 1013 } 1014 1015 GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun) 1016 { 1017 _GLFWwindow* window = (_GLFWwindow*) handle; 1018 assert(window != NULL); 1019 1020 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1021 _GLFW_SWAP(GLFWdropfun, window->callbacks.drop, cbfun); 1022 return cbfun; 1023 } 1024 1025 GLFWAPI int glfwJoystickPresent(int jid) 1026 { 1027 _GLFWjoystick* js; 1028 1029 assert(jid >= GLFW_JOYSTICK_1); 1030 assert(jid <= GLFW_JOYSTICK_LAST); 1031 1032 _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); 1033 1034 if (jid < 0 || jid > GLFW_JOYSTICK_LAST) 1035 { 1036 _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid); 1037 return GLFW_FALSE; 1038 } 1039 1040 if (!initJoysticks()) 1041 return GLFW_FALSE; 1042 1043 js = _glfw.joysticks + jid; 1044 if (!js->connected) 1045 return GLFW_FALSE; 1046 1047 return _glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE); 1048 } 1049 1050 GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count) 1051 { 1052 _GLFWjoystick* js; 1053 1054 assert(jid >= GLFW_JOYSTICK_1); 1055 assert(jid <= GLFW_JOYSTICK_LAST); 1056 assert(count != NULL); 1057 1058 *count = 0; 1059 1060 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1061 1062 if (jid < 0 || jid > GLFW_JOYSTICK_LAST) 1063 { 1064 _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid); 1065 return NULL; 1066 } 1067 1068 if (!initJoysticks()) 1069 return NULL; 1070 1071 js = _glfw.joysticks + jid; 1072 if (!js->connected) 1073 return NULL; 1074 1075 if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_AXES)) 1076 return NULL; 1077 1078 *count = js->axisCount; 1079 return js->axes; 1080 } 1081 1082 GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count) 1083 { 1084 _GLFWjoystick* js; 1085 1086 assert(jid >= GLFW_JOYSTICK_1); 1087 assert(jid <= GLFW_JOYSTICK_LAST); 1088 assert(count != NULL); 1089 1090 *count = 0; 1091 1092 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1093 1094 if (jid < 0 || jid > GLFW_JOYSTICK_LAST) 1095 { 1096 _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid); 1097 return NULL; 1098 } 1099 1100 if (!initJoysticks()) 1101 return NULL; 1102 1103 js = _glfw.joysticks + jid; 1104 if (!js->connected) 1105 return NULL; 1106 1107 if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_BUTTONS)) 1108 return NULL; 1109 1110 if (_glfw.hints.init.hatButtons) 1111 *count = js->buttonCount + js->hatCount * 4; 1112 else 1113 *count = js->buttonCount; 1114 1115 return js->buttons; 1116 } 1117 1118 GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count) 1119 { 1120 _GLFWjoystick* js; 1121 1122 assert(jid >= GLFW_JOYSTICK_1); 1123 assert(jid <= GLFW_JOYSTICK_LAST); 1124 assert(count != NULL); 1125 1126 *count = 0; 1127 1128 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1129 1130 if (jid < 0 || jid > GLFW_JOYSTICK_LAST) 1131 { 1132 _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid); 1133 return NULL; 1134 } 1135 1136 if (!initJoysticks()) 1137 return NULL; 1138 1139 js = _glfw.joysticks + jid; 1140 if (!js->connected) 1141 return NULL; 1142 1143 if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_BUTTONS)) 1144 return NULL; 1145 1146 *count = js->hatCount; 1147 return js->hats; 1148 } 1149 1150 GLFWAPI const char* glfwGetJoystickName(int jid) 1151 { 1152 _GLFWjoystick* js; 1153 1154 assert(jid >= GLFW_JOYSTICK_1); 1155 assert(jid <= GLFW_JOYSTICK_LAST); 1156 1157 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1158 1159 if (jid < 0 || jid > GLFW_JOYSTICK_LAST) 1160 { 1161 _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid); 1162 return NULL; 1163 } 1164 1165 if (!initJoysticks()) 1166 return NULL; 1167 1168 js = _glfw.joysticks + jid; 1169 if (!js->connected) 1170 return NULL; 1171 1172 if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE)) 1173 return NULL; 1174 1175 return js->name; 1176 } 1177 1178 GLFWAPI const char* glfwGetJoystickGUID(int jid) 1179 { 1180 _GLFWjoystick* js; 1181 1182 assert(jid >= GLFW_JOYSTICK_1); 1183 assert(jid <= GLFW_JOYSTICK_LAST); 1184 1185 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1186 1187 if (jid < 0 || jid > GLFW_JOYSTICK_LAST) 1188 { 1189 _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid); 1190 return NULL; 1191 } 1192 1193 if (!initJoysticks()) 1194 return NULL; 1195 1196 js = _glfw.joysticks + jid; 1197 if (!js->connected) 1198 return NULL; 1199 1200 if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE)) 1201 return NULL; 1202 1203 return js->guid; 1204 } 1205 1206 GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer) 1207 { 1208 _GLFWjoystick* js; 1209 1210 assert(jid >= GLFW_JOYSTICK_1); 1211 assert(jid <= GLFW_JOYSTICK_LAST); 1212 1213 _GLFW_REQUIRE_INIT(); 1214 1215 js = _glfw.joysticks + jid; 1216 if (!js->allocated) 1217 return; 1218 1219 js->userPointer = pointer; 1220 } 1221 1222 GLFWAPI void* glfwGetJoystickUserPointer(int jid) 1223 { 1224 _GLFWjoystick* js; 1225 1226 assert(jid >= GLFW_JOYSTICK_1); 1227 assert(jid <= GLFW_JOYSTICK_LAST); 1228 1229 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1230 1231 js = _glfw.joysticks + jid; 1232 if (!js->allocated) 1233 return NULL; 1234 1235 return js->userPointer; 1236 } 1237 1238 GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun) 1239 { 1240 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1241 1242 if (!initJoysticks()) 1243 return NULL; 1244 1245 _GLFW_SWAP(GLFWjoystickfun, _glfw.callbacks.joystick, cbfun); 1246 return cbfun; 1247 } 1248 1249 GLFWAPI int glfwUpdateGamepadMappings(const char* string) 1250 { 1251 int jid; 1252 const char* c = string; 1253 1254 assert(string != NULL); 1255 1256 _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); 1257 1258 while (*c) 1259 { 1260 if ((*c >= '0' && *c <= '9') || 1261 (*c >= 'a' && *c <= 'f') || 1262 (*c >= 'A' && *c <= 'F')) 1263 { 1264 char line[1024]; 1265 1266 const size_t length = strcspn(c, "\r\n"); 1267 if (length < sizeof(line)) 1268 { 1269 _GLFWmapping mapping = {{0}}; 1270 1271 memcpy(line, c, length); 1272 line[length] = '\0'; 1273 1274 if (parseMapping(&mapping, line)) 1275 { 1276 _GLFWmapping* previous = findMapping(mapping.guid); 1277 if (previous) 1278 *previous = mapping; 1279 else 1280 { 1281 _glfw.mappingCount++; 1282 _glfw.mappings = 1283 _glfw_realloc(_glfw.mappings, 1284 sizeof(_GLFWmapping) * _glfw.mappingCount); 1285 _glfw.mappings[_glfw.mappingCount - 1] = mapping; 1286 } 1287 } 1288 } 1289 1290 c += length; 1291 } 1292 else 1293 { 1294 c += strcspn(c, "\r\n"); 1295 c += strspn(c, "\r\n"); 1296 } 1297 } 1298 1299 for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) 1300 { 1301 _GLFWjoystick* js = _glfw.joysticks + jid; 1302 if (js->connected) 1303 js->mapping = findValidMapping(js); 1304 } 1305 1306 return GLFW_TRUE; 1307 } 1308 1309 GLFWAPI int glfwJoystickIsGamepad(int jid) 1310 { 1311 _GLFWjoystick* js; 1312 1313 assert(jid >= GLFW_JOYSTICK_1); 1314 assert(jid <= GLFW_JOYSTICK_LAST); 1315 1316 _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); 1317 1318 if (jid < 0 || jid > GLFW_JOYSTICK_LAST) 1319 { 1320 _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid); 1321 return GLFW_FALSE; 1322 } 1323 1324 if (!initJoysticks()) 1325 return GLFW_FALSE; 1326 1327 js = _glfw.joysticks + jid; 1328 if (!js->connected) 1329 return GLFW_FALSE; 1330 1331 if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE)) 1332 return GLFW_FALSE; 1333 1334 return js->mapping != NULL; 1335 } 1336 1337 GLFWAPI const char* glfwGetGamepadName(int jid) 1338 { 1339 _GLFWjoystick* js; 1340 1341 assert(jid >= GLFW_JOYSTICK_1); 1342 assert(jid <= GLFW_JOYSTICK_LAST); 1343 1344 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1345 1346 if (jid < 0 || jid > GLFW_JOYSTICK_LAST) 1347 { 1348 _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid); 1349 return NULL; 1350 } 1351 1352 if (!initJoysticks()) 1353 return NULL; 1354 1355 js = _glfw.joysticks + jid; 1356 if (!js->connected) 1357 return NULL; 1358 1359 if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE)) 1360 return NULL; 1361 1362 if (!js->mapping) 1363 return NULL; 1364 1365 return js->mapping->name; 1366 } 1367 1368 GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state) 1369 { 1370 int i; 1371 _GLFWjoystick* js; 1372 1373 assert(jid >= GLFW_JOYSTICK_1); 1374 assert(jid <= GLFW_JOYSTICK_LAST); 1375 assert(state != NULL); 1376 1377 memset(state, 0, sizeof(GLFWgamepadstate)); 1378 1379 _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); 1380 1381 if (jid < 0 || jid > GLFW_JOYSTICK_LAST) 1382 { 1383 _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid); 1384 return GLFW_FALSE; 1385 } 1386 1387 if (!initJoysticks()) 1388 return GLFW_FALSE; 1389 1390 js = _glfw.joysticks + jid; 1391 if (!js->connected) 1392 return GLFW_FALSE; 1393 1394 if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_ALL)) 1395 return GLFW_FALSE; 1396 1397 if (!js->mapping) 1398 return GLFW_FALSE; 1399 1400 for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++) 1401 { 1402 const _GLFWmapelement* e = js->mapping->buttons + i; 1403 if (e->type == _GLFW_JOYSTICK_AXIS) 1404 { 1405 const float value = js->axes[e->index] * e->axisScale + e->axisOffset; 1406 // HACK: This should be baked into the value transform 1407 // TODO: Bake into transform when implementing output modifiers 1408 if (e->axisOffset < 0 || (e->axisOffset == 0 && e->axisScale > 0)) 1409 { 1410 if (value >= 0.f) 1411 state->buttons[i] = GLFW_PRESS; 1412 } 1413 else 1414 { 1415 if (value <= 0.f) 1416 state->buttons[i] = GLFW_PRESS; 1417 } 1418 } 1419 else if (e->type == _GLFW_JOYSTICK_HATBIT) 1420 { 1421 const unsigned int hat = e->index >> 4; 1422 const unsigned int bit = e->index & 0xf; 1423 if (js->hats[hat] & bit) 1424 state->buttons[i] = GLFW_PRESS; 1425 } 1426 else if (e->type == _GLFW_JOYSTICK_BUTTON) 1427 state->buttons[i] = js->buttons[e->index]; 1428 } 1429 1430 for (i = 0; i <= GLFW_GAMEPAD_AXIS_LAST; i++) 1431 { 1432 const _GLFWmapelement* e = js->mapping->axes + i; 1433 if (e->type == _GLFW_JOYSTICK_AXIS) 1434 { 1435 const float value = js->axes[e->index] * e->axisScale + e->axisOffset; 1436 state->axes[i] = _glfw_fminf(_glfw_fmaxf(value, -1.f), 1.f); 1437 } 1438 else if (e->type == _GLFW_JOYSTICK_HATBIT) 1439 { 1440 const unsigned int hat = e->index >> 4; 1441 const unsigned int bit = e->index & 0xf; 1442 if (js->hats[hat] & bit) 1443 state->axes[i] = 1.f; 1444 else 1445 state->axes[i] = -1.f; 1446 } 1447 else if (e->type == _GLFW_JOYSTICK_BUTTON) 1448 state->axes[i] = js->buttons[e->index] * 2.f - 1.f; 1449 } 1450 1451 return GLFW_TRUE; 1452 } 1453 1454 GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string) 1455 { 1456 assert(string != NULL); 1457 1458 _GLFW_REQUIRE_INIT(); 1459 _glfw.platform.setClipboardString(string); 1460 } 1461 1462 GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle) 1463 { 1464 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 1465 return _glfw.platform.getClipboardString(); 1466 } 1467 1468 GLFWAPI double glfwGetTime(void) 1469 { 1470 _GLFW_REQUIRE_INIT_OR_RETURN(0.0); 1471 return (double) (_glfwPlatformGetTimerValue() - _glfw.timer.offset) / 1472 _glfwPlatformGetTimerFrequency(); 1473 } 1474 1475 GLFWAPI void glfwSetTime(double time) 1476 { 1477 _GLFW_REQUIRE_INIT(); 1478 1479 if (time != time || time < 0.0 || time > 18446744073.0) 1480 { 1481 _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", time); 1482 return; 1483 } 1484 1485 _glfw.timer.offset = _glfwPlatformGetTimerValue() - 1486 (uint64_t) (time * _glfwPlatformGetTimerFrequency()); 1487 } 1488 1489 GLFWAPI uint64_t glfwGetTimerValue(void) 1490 { 1491 _GLFW_REQUIRE_INIT_OR_RETURN(0); 1492 return _glfwPlatformGetTimerValue(); 1493 } 1494 1495 GLFWAPI uint64_t glfwGetTimerFrequency(void) 1496 { 1497 _GLFW_REQUIRE_INIT_OR_RETURN(0); 1498 return _glfwPlatformGetTimerFrequency(); 1499 } 1500