ScrapExplorer - input.c

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