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