diff --git a/backends/imgui_impl_qnx.cpp b/backends/imgui_impl_qnx.cpp new file mode 100644 index 000000000..82c9cb376 --- /dev/null +++ b/backends/imgui_impl_qnx.cpp @@ -0,0 +1,763 @@ +// dear imgui: Platform Backend for QNX Screen +// This needs to be used along with a Renderer Backend (e.g. OpenGL3, Vulkan). + +// Implemented features: +// [X] Platform: Keyboard support. Uses io.AddKeyEvent() and native QNX key symbols. +// [X] Platform: Mouse support. Handles position, three buttons and horizontal/vertical wheels. +// [X] Platform: Touch support. Maps the first active touch contact to the primary mouse button. +// [X] Platform: Focus and window-size updates. +// Missing features or Issues: +// [ ] Platform: Clipboard support. +// [ ] Platform: Gamepad support. +// [ ] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). +// [ ] Platform: Multi-viewport support. + +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2026-07-30: Renamed backend from imgui_impl_screen to imgui_impl_qnx and embedded a compact keysym table. +// 2026-07-29: Reworked keyboard handling from the proven qterm Screen path: authoritative modifier masks, +// complete keypad/Hyper mapping, and QNX/X11 keysym-to-Unicode conversion. +// 2026-07-29: Fixed keyboard handling: use KEY_CAP for physical keys, SYM for text, and honor Screen validity flags. +// 2026-07-28: Initial QNX Screen backend. + +#include "imgui.h" +#ifndef IMGUI_DISABLE +#include "imgui_impl_qnx.h" + +#include +#include +#include +#include +#include + +static unsigned int ImGui_ImplQNX_KeySymToUnicode(unsigned int keysym); + +struct ImGui_ImplQNX_Data +{ + screen_context_t Context; + screen_window_t Window; + uint64_t TimeNanoseconds; + int MouseButtons; + int ActiveTouchId; + bool LeftSuper; + bool RightSuper; + + ImGui_ImplQNX_Data() + { + memset(this, 0, sizeof(*this)); + ActiveTouchId = -1; + } +}; + +static ImGui_ImplQNX_Data* ImGui_ImplQNX_GetBackendData() +{ + return ImGui::GetCurrentContext() != nullptr ? (ImGui_ImplQNX_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr; +} + +static uint64_t ImGui_ImplQNX_GetTimeNanoseconds() +{ + struct timespec timestamp = {}; + if (clock_gettime(CLOCK_MONOTONIC, ×tamp) != 0) + { + return 0; + } + return (uint64_t)timestamp.tv_sec * UINT64_C(1000000000) + (uint64_t)timestamp.tv_nsec; +} + +static ImGuiKey ImGui_ImplQNX_KeyCodeToImGuiKey(int key_code) +{ + switch (key_code) + { + case KEYCODE_TAB: return ImGuiKey_Tab; + case KEYCODE_LEFT: return ImGuiKey_LeftArrow; + case KEYCODE_RIGHT: return ImGuiKey_RightArrow; + case KEYCODE_UP: return ImGuiKey_UpArrow; + case KEYCODE_DOWN: return ImGuiKey_DownArrow; + case KEYCODE_PG_UP: return ImGuiKey_PageUp; + case KEYCODE_PG_DOWN: return ImGuiKey_PageDown; + case KEYCODE_HOME: return ImGuiKey_Home; + case KEYCODE_END: return ImGuiKey_End; + case KEYCODE_INSERT: return ImGuiKey_Insert; + case KEYCODE_DELETE: return ImGuiKey_Delete; + case KEYCODE_BACKSPACE: return ImGuiKey_Backspace; + case KEYCODE_SPACE: return ImGuiKey_Space; + case KEYCODE_RETURN: return ImGuiKey_Enter; + case KEYCODE_ESCAPE: return ImGuiKey_Escape; + case KEYCODE_APOSTROPHE: return ImGuiKey_Apostrophe; + case KEYCODE_COMMA: return ImGuiKey_Comma; + case KEYCODE_MINUS: return ImGuiKey_Minus; + case KEYCODE_PERIOD: return ImGuiKey_Period; + case KEYCODE_SLASH: return ImGuiKey_Slash; + case KEYCODE_SEMICOLON: return ImGuiKey_Semicolon; + case KEYCODE_EQUAL: return ImGuiKey_Equal; + case KEYCODE_LEFT_BRACKET: return ImGuiKey_LeftBracket; + case KEYCODE_BACK_SLASH: return ImGuiKey_Backslash; + case KEYCODE_RIGHT_BRACKET: return ImGuiKey_RightBracket; + case KEYCODE_GRAVE: return ImGuiKey_GraveAccent; + case KEYCODE_CAPS_LOCK: return ImGuiKey_CapsLock; + case KEYCODE_SCROLL_LOCK: return ImGuiKey_ScrollLock; + case KEYCODE_NUM_LOCK: return ImGuiKey_NumLock; + case KEYCODE_PRINT: return ImGuiKey_PrintScreen; + case KEYCODE_PAUSE: return ImGuiKey_Pause; + case KEYCODE_KP_DIVIDE: return ImGuiKey_KeypadDivide; + case KEYCODE_KP_MULTIPLY: return ImGuiKey_KeypadMultiply; + case KEYCODE_KP_MINUS: return ImGuiKey_KeypadSubtract; + case KEYCODE_KP_PLUS: return ImGuiKey_KeypadAdd; + case KEYCODE_KP_ENTER: return ImGuiKey_KeypadEnter; + // QNX reports keypad digits by their navigation key-cap names. + case KEYCODE_KP_INSERT: return ImGuiKey_Keypad0; + case KEYCODE_KP_END: return ImGuiKey_Keypad1; + case KEYCODE_KP_DOWN: return ImGuiKey_Keypad2; + case KEYCODE_KP_PG_DOWN: return ImGuiKey_Keypad3; + case KEYCODE_KP_LEFT: return ImGuiKey_Keypad4; + case KEYCODE_KP_FIVE: return ImGuiKey_Keypad5; + case KEYCODE_KP_RIGHT: return ImGuiKey_Keypad6; + case KEYCODE_KP_HOME: return ImGuiKey_Keypad7; + case KEYCODE_KP_UP: return ImGuiKey_Keypad8; + case KEYCODE_KP_PG_UP: return ImGuiKey_Keypad9; + case KEYCODE_KP_DELETE: return ImGuiKey_KeypadDecimal; + case KEYCODE_LEFT_CTRL: return ImGuiKey_LeftCtrl; + case KEYCODE_LEFT_SHIFT: return ImGuiKey_LeftShift; + case KEYCODE_LEFT_ALT: return ImGuiKey_LeftAlt; + case KEYCODE_RIGHT_CTRL: return ImGuiKey_RightCtrl; + case KEYCODE_RIGHT_SHIFT: return ImGuiKey_RightShift; + case KEYCODE_RIGHT_ALT: return ImGuiKey_RightAlt; + case KEYCODE_LEFT_HYPER: return ImGuiKey_LeftSuper; + case KEYCODE_RIGHT_HYPER: return ImGuiKey_RightSuper; + case KEYCODE_MENU: return ImGuiKey_Menu; + case KEYCODE_ZERO: return ImGuiKey_0; + case KEYCODE_ONE: return ImGuiKey_1; + case KEYCODE_TWO: return ImGuiKey_2; + case KEYCODE_THREE: return ImGuiKey_3; + case KEYCODE_FOUR: return ImGuiKey_4; + case KEYCODE_FIVE: return ImGuiKey_5; + case KEYCODE_SIX: return ImGuiKey_6; + case KEYCODE_SEVEN: return ImGuiKey_7; + case KEYCODE_EIGHT: return ImGuiKey_8; + case KEYCODE_NINE: return ImGuiKey_9; + case KEYCODE_A: return ImGuiKey_A; + case KEYCODE_B: return ImGuiKey_B; + case KEYCODE_C: return ImGuiKey_C; + case KEYCODE_D: return ImGuiKey_D; + case KEYCODE_E: return ImGuiKey_E; + case KEYCODE_F: return ImGuiKey_F; + case KEYCODE_G: return ImGuiKey_G; + case KEYCODE_H: return ImGuiKey_H; + case KEYCODE_I: return ImGuiKey_I; + case KEYCODE_J: return ImGuiKey_J; + case KEYCODE_K: return ImGuiKey_K; + case KEYCODE_L: return ImGuiKey_L; + case KEYCODE_M: return ImGuiKey_M; + case KEYCODE_N: return ImGuiKey_N; + case KEYCODE_O: return ImGuiKey_O; + case KEYCODE_P: return ImGuiKey_P; + case KEYCODE_Q: return ImGuiKey_Q; + case KEYCODE_R: return ImGuiKey_R; + case KEYCODE_S: return ImGuiKey_S; + case KEYCODE_T: return ImGuiKey_T; + case KEYCODE_U: return ImGuiKey_U; + case KEYCODE_V: return ImGuiKey_V; + case KEYCODE_W: return ImGuiKey_W; + case KEYCODE_X: return ImGuiKey_X; + case KEYCODE_Y: return ImGuiKey_Y; + case KEYCODE_Z: return ImGuiKey_Z; + case KEYCODE_F1: return ImGuiKey_F1; + case KEYCODE_F2: return ImGuiKey_F2; + case KEYCODE_F3: return ImGuiKey_F3; + case KEYCODE_F4: return ImGuiKey_F4; + case KEYCODE_F5: return ImGuiKey_F5; + case KEYCODE_F6: return ImGuiKey_F6; + case KEYCODE_F7: return ImGuiKey_F7; + case KEYCODE_F8: return ImGuiKey_F8; + case KEYCODE_F9: return ImGuiKey_F9; + case KEYCODE_F10: return ImGuiKey_F10; + case KEYCODE_F11: return ImGuiKey_F11; + case KEYCODE_F12: return ImGuiKey_F12; + default: return ImGuiKey_None; + } +} + +static void ImGui_ImplQNX_UpdateKeyModifiers(ImGuiIO& io, ImGui_ImplQNX_Data* bd, int modifiers, ImGuiKey key, bool down) +{ + // SCREEN_PROPERTY_MODIFIERS is the authoritative state for Shift/Ctrl/Alt. + // Tracking those keys locally loses sticky modifiers and can become stale if + // a key transition is consumed elsewhere. qterm uses this same Screen state. + if (key == ImGuiKey_LeftSuper) + { + bd->LeftSuper = down; + } + else if (key == ImGuiKey_RightSuper) + { + bd->RightSuper = down; + } + + io.AddKeyEvent(ImGuiMod_Ctrl, (modifiers & KEYMOD_CTRL) != 0); + io.AddKeyEvent(ImGuiMod_Shift, (modifiers & KEYMOD_SHIFT) != 0); + io.AddKeyEvent(ImGuiMod_Alt, (modifiers & KEYMOD_ALT) != 0); + io.AddKeyEvent(ImGuiMod_Super, bd->LeftSuper || bd->RightSuper); +} + +static void ImGui_ImplQNX_ClearModifierState(ImGuiIO& io, ImGui_ImplQNX_Data* bd) +{ + bd->LeftSuper = false; + bd->RightSuper = false; + io.AddKeyEvent(ImGuiMod_Ctrl, false); + io.AddKeyEvent(ImGuiMod_Shift, false); + io.AddKeyEvent(ImGuiMod_Alt, false); + io.AddKeyEvent(ImGuiMod_Super, false); +} + +static bool ImGui_ImplQNX_IsTextCodePoint(unsigned int code_point) +{ + // At this point the QNX keysym has already been converted to Unicode. + // Do not reject Unicode private-use characters: a user keymap may emit one. + const bool surrogate = code_point >= 0xd800u && code_point <= 0xdfffu; + const bool control = code_point < 0x20u || (code_point >= 0x7fu && code_point <= 0x9fu); + return code_point <= IM_UNICODE_CODEPOINT_MAX && !surrogate && !control; +} + +static bool ImGui_ImplQNX_ProcessKeyboardEvent(ImGui_ImplQNX_Data* bd, screen_event_t event) +{ + int flags = 0; + int modifiers = 0; + if (screen_get_event_property_iv(event, SCREEN_PROPERTY_FLAGS, &flags) != 0 || + screen_get_event_property_iv(event, SCREEN_PROPERTY_MODIFIERS, &modifiers) != 0) + { + return false; + } + + // KEY_CAP is the unmodified key identity used for ImGuiKey events. SYM is + // the layout/modifier-translated QNX keysym used for text input. + int key_cap = 0; + int key_sym = 0; + int scan_code = 0; + const bool cap_valid = (flags & SCREEN_FLAG_CAP_VALID) != 0; + const bool sym_valid = (flags & SCREEN_FLAG_SYM_VALID) != 0; + const bool scan_valid = (flags & SCREEN_FLAG_SCAN_VALID) != 0; + const bool down = (flags & (SCREEN_FLAG_KEY_DOWN | SCREEN_FLAG_KEY_REPEAT)) != 0; + + if (cap_valid && screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_CAP, &key_cap) != 0) + { + return false; + } + if (sym_valid && screen_get_event_property_iv(event, SCREEN_PROPERTY_SYM, &key_sym) != 0) + { + return false; + } + if (scan_valid && screen_get_event_property_iv(event, SCREEN_PROPERTY_SCAN, &scan_code) != 0) + { + scan_code = 0; + } + + const ImGuiKey key = cap_valid ? ImGui_ImplQNX_KeyCodeToImGuiKey(key_cap) : ImGuiKey_None; + ImGuiIO& io = ImGui::GetIO(); + + // Modifier events must precede the ordinary key event in Dear ImGui's queue. + // Unlike qterm, we still submit the individual modifier key because ImGui + // exposes Left/Right Ctrl, Shift, Alt and Super as named keys. + ImGui_ImplQNX_UpdateKeyModifiers(io, bd, modifiers, key, down); + + if (key != ImGuiKey_None) + { + io.AddKeyEvent(key, down); + io.SetKeyEventNativeData(key, key_cap, scan_code); + } + + bool text_added = false; + if (down && sym_valid && key_sym >= 0) + { + const unsigned int keysym = (unsigned int)key_sym; + // QNX special/function symbols begin at KEYCODE_PC_KEYS. Printable + // symbols below that boundary use X11 keysym encoding. Also accept the + // standard directly encoded UCS keysym form (0x01000000 | codepoint). + if (keysym < (unsigned int)KEYCODE_PC_KEYS || (keysym & 0xff000000u) == 0x01000000u) + { + const unsigned int code_point = ImGui_ImplQNX_KeySymToUnicode(keysym); + if (ImGui_ImplQNX_IsTextCodePoint(code_point)) + { + io.AddInputCharacter(code_point); + text_added = true; + } + } + } + + return key != ImGuiKey_None || text_added || cap_valid || sym_valid; +} + +static bool ImGui_ImplQNX_ProcessPointerEvent(ImGui_ImplQNX_Data* bd, screen_event_t event) +{ + int position[2] = {}; + int buttons = 0; + int wheel_vertical = 0; + int wheel_horizontal = 0; + + if (screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, position) != 0 && + screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, position) != 0) + { + return false; + } + if (screen_get_event_property_iv(event, SCREEN_PROPERTY_BUTTONS, &buttons) != 0) + { + buttons = bd->MouseButtons; + } + + ImGuiIO& io = ImGui::GetIO(); + io.AddMouseSourceEvent(ImGuiMouseSource_Mouse); + io.AddMousePosEvent((float)position[0], (float)position[1]); + + const int changed_buttons = buttons ^ bd->MouseButtons; + if ((changed_buttons & SCREEN_LEFT_MOUSE_BUTTON) != 0) + { + io.AddMouseButtonEvent(0, (buttons & SCREEN_LEFT_MOUSE_BUTTON) != 0); + } + if ((changed_buttons & SCREEN_RIGHT_MOUSE_BUTTON) != 0) + { + io.AddMouseButtonEvent(1, (buttons & SCREEN_RIGHT_MOUSE_BUTTON) != 0); + } + if ((changed_buttons & SCREEN_MIDDLE_MOUSE_BUTTON) != 0) + { + io.AddMouseButtonEvent(2, (buttons & SCREEN_MIDDLE_MOUSE_BUTTON) != 0); + } + bd->MouseButtons = buttons; + + if (screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_WHEEL, &wheel_vertical) != 0) + { + wheel_vertical = 0; + } + if (screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_HORIZONTAL_WHEEL, &wheel_horizontal) != 0) + { + wheel_horizontal = 0; + } + if (wheel_vertical != 0 || wheel_horizontal != 0) + { + // Screen: up/left are negative. Dear ImGui: up/left are positive. + io.AddMouseWheelEvent((float)-wheel_horizontal, (float)-wheel_vertical); + } + return true; +} + +static bool ImGui_ImplQNX_ProcessTouchEvent(ImGui_ImplQNX_Data* bd, screen_event_t event, int event_type) +{ + int touch_id = -1; + int position[2] = {}; + if (screen_get_event_property_iv(event, SCREEN_PROPERTY_TOUCH_ID, &touch_id) != 0) + { + return false; + } + + const bool is_release = event_type == SCREEN_EVENT_MTOUCH_RELEASE; + if (bd->ActiveTouchId != -1 && touch_id != bd->ActiveTouchId) + { + return false; + } + + ImGuiIO& io = ImGui::GetIO(); + io.AddMouseSourceEvent(ImGuiMouseSource_TouchScreen); + + if (!is_release) + { + if (screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, position) != 0 && + screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, position) != 0) + { + return false; + } + io.AddMousePosEvent((float)position[0], (float)position[1]); + } + + if (event_type == SCREEN_EVENT_MTOUCH_TOUCH) + { + bd->ActiveTouchId = touch_id; + io.AddMouseButtonEvent(0, true); + } + else if (is_release) + { + io.AddMouseButtonEvent(0, false); + io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); + bd->ActiveTouchId = -1; + } + return true; +} + +bool ImGui_ImplQNX_ProcessEvent(screen_event_t event) +{ + ImGui_ImplQNX_Data* bd = ImGui_ImplQNX_GetBackendData(); + IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplQNX_Init()?"); + if (bd == nullptr || event == nullptr) + { + return false; + } + + int event_type = SCREEN_EVENT_NONE; + if (screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &event_type) != 0 || event_type == SCREEN_EVENT_NONE) + { + return false; + } + switch (event_type) + { + case SCREEN_EVENT_KEYBOARD: + return ImGui_ImplQNX_ProcessKeyboardEvent(bd, event); + case SCREEN_EVENT_POINTER: + return ImGui_ImplQNX_ProcessPointerEvent(bd, event); + case SCREEN_EVENT_MTOUCH_TOUCH: + case SCREEN_EVENT_MTOUCH_MOVE: + case SCREEN_EVENT_MTOUCH_RELEASE: + return ImGui_ImplQNX_ProcessTouchEvent(bd, event, event_type); + case SCREEN_EVENT_PROPERTY: + { + int property = 0; + if (screen_get_event_property_iv(event, SCREEN_PROPERTY_NAME, &property) != 0) + { + return false; + } + if (property == SCREEN_PROPERTY_FOCUS) + { + int focused = 0; + if (screen_get_window_property_iv(bd->Window, SCREEN_PROPERTY_FOCUS, &focused) == 0) + { + ImGuiIO& io = ImGui::GetIO(); + io.AddFocusEvent(focused != 0); + if (focused == 0) + { + ImGui_ImplQNX_ClearModifierState(io, bd); + } + } + return true; + } + if (property == SCREEN_PROPERTY_SIZE || property == SCREEN_PROPERTY_BUFFER_SIZE || property == SCREEN_PROPERTY_VISIBLE) + { + return true; + } + return false; + } + case SCREEN_EVENT_CLOSE: + { + ImGuiIO& io = ImGui::GetIO(); + io.AddFocusEvent(false); + ImGui_ImplQNX_ClearModifierState(io, bd); + return true; + } + default: + return false; + } +} + +bool ImGui_ImplQNX_Init(screen_context_t context, screen_window_t window) +{ + ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); + IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); + IM_ASSERT(context != nullptr && window != nullptr); + if (context == nullptr || window == nullptr) + { + return false; + } + + ImGui_ImplQNX_Data* bd = IM_NEW(ImGui_ImplQNX_Data)(); + io.BackendPlatformUserData = (void*)bd; + io.BackendPlatformName = "imgui_impl_qnx"; + + bd->Context = context; + bd->Window = window; + bd->TimeNanoseconds = ImGui_ImplQNX_GetTimeNanoseconds(); + + int focused = 0; + if (screen_get_window_property_iv(window, SCREEN_PROPERTY_FOCUS, &focused) == 0) + { + io.AddFocusEvent(focused != 0); + } + return true; +} + +void ImGui_ImplQNX_Shutdown() +{ + ImGui_ImplQNX_Data* bd = ImGui_ImplQNX_GetBackendData(); + IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); + if (bd == nullptr) + { + return; + } + + ImGuiIO& io = ImGui::GetIO(); + io.BackendPlatformName = nullptr; + io.BackendPlatformUserData = nullptr; + IM_DELETE(bd); +} + +void ImGui_ImplQNX_NewFrame() +{ + ImGui_ImplQNX_Data* bd = ImGui_ImplQNX_GetBackendData(); + IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplQNX_Init()?"); + if (bd == nullptr) + { + return; + } + + ImGuiIO& io = ImGui::GetIO(); + int size[2] = {}; + if (screen_get_window_property_iv(bd->Window, SCREEN_PROPERTY_BUFFER_SIZE, size) != 0 || + size[0] <= 0 || size[1] <= 0) + { + size[0] = 0; + size[1] = 0; + (void)screen_get_window_property_iv(bd->Window, SCREEN_PROPERTY_SIZE, size); + } + if (size[0] > 0 && size[1] > 0) + { + io.DisplaySize = ImVec2((float)size[0], (float)size[1]); + io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f); + } + + const uint64_t current_time = ImGui_ImplQNX_GetTimeNanoseconds(); + if (current_time > bd->TimeNanoseconds && bd->TimeNanoseconds != 0) + { + io.DeltaTime = (float)((double)(current_time - bd->TimeNanoseconds) / 1000000000.0); + } + else + { + io.DeltaTime = 1.0f / 60.0f; + } + bd->TimeNanoseconds = current_time; +} + +// Generated by Markus Kuhn's public-domain unicode/convmap.pl from X11 keysymdef.h and UnicodeData. +// Original source: https://www.cl.cam.ac.uk/~mgk25/ucs/keysym2ucs.c +// The table must remain sorted by keysym for the binary search below. +struct ImGui_ImplQNX_KeySymPair +{ + uint16_t KeySym; + uint16_t Unicode; +}; + +static const ImGui_ImplQNX_KeySymPair ImGui_ImplQNX_KeySymTable[] = +{ + { 0x01a1, 0x0104 }, { 0x01a2, 0x02d8 }, { 0x01a3, 0x0141 }, { 0x01a5, 0x013d }, + { 0x01a6, 0x015a }, { 0x01a9, 0x0160 }, { 0x01aa, 0x015e }, { 0x01ab, 0x0164 }, + { 0x01ac, 0x0179 }, { 0x01ae, 0x017d }, { 0x01af, 0x017b }, { 0x01b1, 0x0105 }, + { 0x01b2, 0x02db }, { 0x01b3, 0x0142 }, { 0x01b5, 0x013e }, { 0x01b6, 0x015b }, + { 0x01b7, 0x02c7 }, { 0x01b9, 0x0161 }, { 0x01ba, 0x015f }, { 0x01bb, 0x0165 }, + { 0x01bc, 0x017a }, { 0x01bd, 0x02dd }, { 0x01be, 0x017e }, { 0x01bf, 0x017c }, + { 0x01c0, 0x0154 }, { 0x01c3, 0x0102 }, { 0x01c5, 0x0139 }, { 0x01c6, 0x0106 }, + { 0x01c8, 0x010c }, { 0x01ca, 0x0118 }, { 0x01cc, 0x011a }, { 0x01cf, 0x010e }, + { 0x01d0, 0x0110 }, { 0x01d1, 0x0143 }, { 0x01d2, 0x0147 }, { 0x01d5, 0x0150 }, + { 0x01d8, 0x0158 }, { 0x01d9, 0x016e }, { 0x01db, 0x0170 }, { 0x01de, 0x0162 }, + { 0x01e0, 0x0155 }, { 0x01e3, 0x0103 }, { 0x01e5, 0x013a }, { 0x01e6, 0x0107 }, + { 0x01e8, 0x010d }, { 0x01ea, 0x0119 }, { 0x01ec, 0x011b }, { 0x01ef, 0x010f }, + { 0x01f0, 0x0111 }, { 0x01f1, 0x0144 }, { 0x01f2, 0x0148 }, { 0x01f5, 0x0151 }, + { 0x01f8, 0x0159 }, { 0x01f9, 0x016f }, { 0x01fb, 0x0171 }, { 0x01fe, 0x0163 }, + { 0x01ff, 0x02d9 }, { 0x02a1, 0x0126 }, { 0x02a6, 0x0124 }, { 0x02a9, 0x0130 }, + { 0x02ab, 0x011e }, { 0x02ac, 0x0134 }, { 0x02b1, 0x0127 }, { 0x02b6, 0x0125 }, + { 0x02b9, 0x0131 }, { 0x02bb, 0x011f }, { 0x02bc, 0x0135 }, { 0x02c5, 0x010a }, + { 0x02c6, 0x0108 }, { 0x02d5, 0x0120 }, { 0x02d8, 0x011c }, { 0x02dd, 0x016c }, + { 0x02de, 0x015c }, { 0x02e5, 0x010b }, { 0x02e6, 0x0109 }, { 0x02f5, 0x0121 }, + { 0x02f8, 0x011d }, { 0x02fd, 0x016d }, { 0x02fe, 0x015d }, { 0x03a2, 0x0138 }, + { 0x03a3, 0x0156 }, { 0x03a5, 0x0128 }, { 0x03a6, 0x013b }, { 0x03aa, 0x0112 }, + { 0x03ab, 0x0122 }, { 0x03ac, 0x0166 }, { 0x03b3, 0x0157 }, { 0x03b5, 0x0129 }, + { 0x03b6, 0x013c }, { 0x03ba, 0x0113 }, { 0x03bb, 0x0123 }, { 0x03bc, 0x0167 }, + { 0x03bd, 0x014a }, { 0x03bf, 0x014b }, { 0x03c0, 0x0100 }, { 0x03c7, 0x012e }, + { 0x03cc, 0x0116 }, { 0x03cf, 0x012a }, { 0x03d1, 0x0145 }, { 0x03d2, 0x014c }, + { 0x03d3, 0x0136 }, { 0x03d9, 0x0172 }, { 0x03dd, 0x0168 }, { 0x03de, 0x016a }, + { 0x03e0, 0x0101 }, { 0x03e7, 0x012f }, { 0x03ec, 0x0117 }, { 0x03ef, 0x012b }, + { 0x03f1, 0x0146 }, { 0x03f2, 0x014d }, { 0x03f3, 0x0137 }, { 0x03f9, 0x0173 }, + { 0x03fd, 0x0169 }, { 0x03fe, 0x016b }, { 0x047e, 0x203e }, { 0x04a1, 0x3002 }, + { 0x04a2, 0x300c }, { 0x04a3, 0x300d }, { 0x04a4, 0x3001 }, { 0x04a5, 0x30fb }, + { 0x04a6, 0x30f2 }, { 0x04a7, 0x30a1 }, { 0x04a8, 0x30a3 }, { 0x04a9, 0x30a5 }, + { 0x04aa, 0x30a7 }, { 0x04ab, 0x30a9 }, { 0x04ac, 0x30e3 }, { 0x04ad, 0x30e5 }, + { 0x04ae, 0x30e7 }, { 0x04af, 0x30c3 }, { 0x04b0, 0x30fc }, { 0x04b1, 0x30a2 }, + { 0x04b2, 0x30a4 }, { 0x04b3, 0x30a6 }, { 0x04b4, 0x30a8 }, { 0x04b5, 0x30aa }, + { 0x04b6, 0x30ab }, { 0x04b7, 0x30ad }, { 0x04b8, 0x30af }, { 0x04b9, 0x30b1 }, + { 0x04ba, 0x30b3 }, { 0x04bb, 0x30b5 }, { 0x04bc, 0x30b7 }, { 0x04bd, 0x30b9 }, + { 0x04be, 0x30bb }, { 0x04bf, 0x30bd }, { 0x04c0, 0x30bf }, { 0x04c1, 0x30c1 }, + { 0x04c2, 0x30c4 }, { 0x04c3, 0x30c6 }, { 0x04c4, 0x30c8 }, { 0x04c5, 0x30ca }, + { 0x04c6, 0x30cb }, { 0x04c7, 0x30cc }, { 0x04c8, 0x30cd }, { 0x04c9, 0x30ce }, + { 0x04ca, 0x30cf }, { 0x04cb, 0x30d2 }, { 0x04cc, 0x30d5 }, { 0x04cd, 0x30d8 }, + { 0x04ce, 0x30db }, { 0x04cf, 0x30de }, { 0x04d0, 0x30df }, { 0x04d1, 0x30e0 }, + { 0x04d2, 0x30e1 }, { 0x04d3, 0x30e2 }, { 0x04d4, 0x30e4 }, { 0x04d5, 0x30e6 }, + { 0x04d6, 0x30e8 }, { 0x04d7, 0x30e9 }, { 0x04d8, 0x30ea }, { 0x04d9, 0x30eb }, + { 0x04da, 0x30ec }, { 0x04db, 0x30ed }, { 0x04dc, 0x30ef }, { 0x04dd, 0x30f3 }, + { 0x04de, 0x309b }, { 0x04df, 0x309c }, { 0x05ac, 0x060c }, { 0x05bb, 0x061b }, + { 0x05bf, 0x061f }, { 0x05c1, 0x0621 }, { 0x05c2, 0x0622 }, { 0x05c3, 0x0623 }, + { 0x05c4, 0x0624 }, { 0x05c5, 0x0625 }, { 0x05c6, 0x0626 }, { 0x05c7, 0x0627 }, + { 0x05c8, 0x0628 }, { 0x05c9, 0x0629 }, { 0x05ca, 0x062a }, { 0x05cb, 0x062b }, + { 0x05cc, 0x062c }, { 0x05cd, 0x062d }, { 0x05ce, 0x062e }, { 0x05cf, 0x062f }, + { 0x05d0, 0x0630 }, { 0x05d1, 0x0631 }, { 0x05d2, 0x0632 }, { 0x05d3, 0x0633 }, + { 0x05d4, 0x0634 }, { 0x05d5, 0x0635 }, { 0x05d6, 0x0636 }, { 0x05d7, 0x0637 }, + { 0x05d8, 0x0638 }, { 0x05d9, 0x0639 }, { 0x05da, 0x063a }, { 0x05e0, 0x0640 }, + { 0x05e1, 0x0641 }, { 0x05e2, 0x0642 }, { 0x05e3, 0x0643 }, { 0x05e4, 0x0644 }, + { 0x05e5, 0x0645 }, { 0x05e6, 0x0646 }, { 0x05e7, 0x0647 }, { 0x05e8, 0x0648 }, + { 0x05e9, 0x0649 }, { 0x05ea, 0x064a }, { 0x05eb, 0x064b }, { 0x05ec, 0x064c }, + { 0x05ed, 0x064d }, { 0x05ee, 0x064e }, { 0x05ef, 0x064f }, { 0x05f0, 0x0650 }, + { 0x05f1, 0x0651 }, { 0x05f2, 0x0652 }, { 0x06a1, 0x0452 }, { 0x06a2, 0x0453 }, + { 0x06a3, 0x0451 }, { 0x06a4, 0x0454 }, { 0x06a5, 0x0455 }, { 0x06a6, 0x0456 }, + { 0x06a7, 0x0457 }, { 0x06a8, 0x0458 }, { 0x06a9, 0x0459 }, { 0x06aa, 0x045a }, + { 0x06ab, 0x045b }, { 0x06ac, 0x045c }, { 0x06ae, 0x045e }, { 0x06af, 0x045f }, + { 0x06b0, 0x2116 }, { 0x06b1, 0x0402 }, { 0x06b2, 0x0403 }, { 0x06b3, 0x0401 }, + { 0x06b4, 0x0404 }, { 0x06b5, 0x0405 }, { 0x06b6, 0x0406 }, { 0x06b7, 0x0407 }, + { 0x06b8, 0x0408 }, { 0x06b9, 0x0409 }, { 0x06ba, 0x040a }, { 0x06bb, 0x040b }, + { 0x06bc, 0x040c }, { 0x06be, 0x040e }, { 0x06bf, 0x040f }, { 0x06c0, 0x044e }, + { 0x06c1, 0x0430 }, { 0x06c2, 0x0431 }, { 0x06c3, 0x0446 }, { 0x06c4, 0x0434 }, + { 0x06c5, 0x0435 }, { 0x06c6, 0x0444 }, { 0x06c7, 0x0433 }, { 0x06c8, 0x0445 }, + { 0x06c9, 0x0438 }, { 0x06ca, 0x0439 }, { 0x06cb, 0x043a }, { 0x06cc, 0x043b }, + { 0x06cd, 0x043c }, { 0x06ce, 0x043d }, { 0x06cf, 0x043e }, { 0x06d0, 0x043f }, + { 0x06d1, 0x044f }, { 0x06d2, 0x0440 }, { 0x06d3, 0x0441 }, { 0x06d4, 0x0442 }, + { 0x06d5, 0x0443 }, { 0x06d6, 0x0436 }, { 0x06d7, 0x0432 }, { 0x06d8, 0x044c }, + { 0x06d9, 0x044b }, { 0x06da, 0x0437 }, { 0x06db, 0x0448 }, { 0x06dc, 0x044d }, + { 0x06dd, 0x0449 }, { 0x06de, 0x0447 }, { 0x06df, 0x044a }, { 0x06e0, 0x042e }, + { 0x06e1, 0x0410 }, { 0x06e2, 0x0411 }, { 0x06e3, 0x0426 }, { 0x06e4, 0x0414 }, + { 0x06e5, 0x0415 }, { 0x06e6, 0x0424 }, { 0x06e7, 0x0413 }, { 0x06e8, 0x0425 }, + { 0x06e9, 0x0418 }, { 0x06ea, 0x0419 }, { 0x06eb, 0x041a }, { 0x06ec, 0x041b }, + { 0x06ed, 0x041c }, { 0x06ee, 0x041d }, { 0x06ef, 0x041e }, { 0x06f0, 0x041f }, + { 0x06f1, 0x042f }, { 0x06f2, 0x0420 }, { 0x06f3, 0x0421 }, { 0x06f4, 0x0422 }, + { 0x06f5, 0x0423 }, { 0x06f6, 0x0416 }, { 0x06f7, 0x0412 }, { 0x06f8, 0x042c }, + { 0x06f9, 0x042b }, { 0x06fa, 0x0417 }, { 0x06fb, 0x0428 }, { 0x06fc, 0x042d }, + { 0x06fd, 0x0429 }, { 0x06fe, 0x0427 }, { 0x06ff, 0x042a }, { 0x07a1, 0x0386 }, + { 0x07a2, 0x0388 }, { 0x07a3, 0x0389 }, { 0x07a4, 0x038a }, { 0x07a5, 0x03aa }, + { 0x07a7, 0x038c }, { 0x07a8, 0x038e }, { 0x07a9, 0x03ab }, { 0x07ab, 0x038f }, + { 0x07ae, 0x0385 }, { 0x07af, 0x2015 }, { 0x07b1, 0x03ac }, { 0x07b2, 0x03ad }, + { 0x07b3, 0x03ae }, { 0x07b4, 0x03af }, { 0x07b5, 0x03ca }, { 0x07b6, 0x0390 }, + { 0x07b7, 0x03cc }, { 0x07b8, 0x03cd }, { 0x07b9, 0x03cb }, { 0x07ba, 0x03b0 }, + { 0x07bb, 0x03ce }, { 0x07c1, 0x0391 }, { 0x07c2, 0x0392 }, { 0x07c3, 0x0393 }, + { 0x07c4, 0x0394 }, { 0x07c5, 0x0395 }, { 0x07c6, 0x0396 }, { 0x07c7, 0x0397 }, + { 0x07c8, 0x0398 }, { 0x07c9, 0x0399 }, { 0x07ca, 0x039a }, { 0x07cb, 0x039b }, + { 0x07cc, 0x039c }, { 0x07cd, 0x039d }, { 0x07ce, 0x039e }, { 0x07cf, 0x039f }, + { 0x07d0, 0x03a0 }, { 0x07d1, 0x03a1 }, { 0x07d2, 0x03a3 }, { 0x07d4, 0x03a4 }, + { 0x07d5, 0x03a5 }, { 0x07d6, 0x03a6 }, { 0x07d7, 0x03a7 }, { 0x07d8, 0x03a8 }, + { 0x07d9, 0x03a9 }, { 0x07e1, 0x03b1 }, { 0x07e2, 0x03b2 }, { 0x07e3, 0x03b3 }, + { 0x07e4, 0x03b4 }, { 0x07e5, 0x03b5 }, { 0x07e6, 0x03b6 }, { 0x07e7, 0x03b7 }, + { 0x07e8, 0x03b8 }, { 0x07e9, 0x03b9 }, { 0x07ea, 0x03ba }, { 0x07eb, 0x03bb }, + { 0x07ec, 0x03bc }, { 0x07ed, 0x03bd }, { 0x07ee, 0x03be }, { 0x07ef, 0x03bf }, + { 0x07f0, 0x03c0 }, { 0x07f1, 0x03c1 }, { 0x07f2, 0x03c3 }, { 0x07f3, 0x03c2 }, + { 0x07f4, 0x03c4 }, { 0x07f5, 0x03c5 }, { 0x07f6, 0x03c6 }, { 0x07f7, 0x03c7 }, + { 0x07f8, 0x03c8 }, { 0x07f9, 0x03c9 }, { 0x08a1, 0x23b7 }, { 0x08a2, 0x250c }, + { 0x08a3, 0x2500 }, { 0x08a4, 0x2320 }, { 0x08a5, 0x2321 }, { 0x08a6, 0x2502 }, + { 0x08a7, 0x23a1 }, { 0x08a8, 0x23a3 }, { 0x08a9, 0x23a4 }, { 0x08aa, 0x23a6 }, + { 0x08ab, 0x239b }, { 0x08ac, 0x239d }, { 0x08ad, 0x239e }, { 0x08ae, 0x23a0 }, + { 0x08af, 0x23a8 }, { 0x08b0, 0x23ac }, { 0x08bc, 0x2264 }, { 0x08bd, 0x2260 }, + { 0x08be, 0x2265 }, { 0x08bf, 0x222b }, { 0x08c0, 0x2234 }, { 0x08c1, 0x221d }, + { 0x08c2, 0x221e }, { 0x08c5, 0x2207 }, { 0x08c8, 0x223c }, { 0x08c9, 0x2243 }, + { 0x08cd, 0x21d4 }, { 0x08ce, 0x21d2 }, { 0x08cf, 0x2261 }, { 0x08d6, 0x221a }, + { 0x08da, 0x2282 }, { 0x08db, 0x2283 }, { 0x08dc, 0x2229 }, { 0x08dd, 0x222a }, + { 0x08de, 0x2227 }, { 0x08df, 0x2228 }, { 0x08ef, 0x2202 }, { 0x08f6, 0x0192 }, + { 0x08fb, 0x2190 }, { 0x08fc, 0x2191 }, { 0x08fd, 0x2192 }, { 0x08fe, 0x2193 }, + { 0x09e0, 0x25c6 }, { 0x09e1, 0x2592 }, { 0x09e2, 0x2409 }, { 0x09e3, 0x240c }, + { 0x09e4, 0x240d }, { 0x09e5, 0x240a }, { 0x09e8, 0x2424 }, { 0x09e9, 0x240b }, + { 0x09ea, 0x2518 }, { 0x09eb, 0x2510 }, { 0x09ec, 0x250c }, { 0x09ed, 0x2514 }, + { 0x09ee, 0x253c }, { 0x09ef, 0x23ba }, { 0x09f0, 0x23bb }, { 0x09f1, 0x2500 }, + { 0x09f2, 0x23bc }, { 0x09f3, 0x23bd }, { 0x09f4, 0x251c }, { 0x09f5, 0x2524 }, + { 0x09f6, 0x2534 }, { 0x09f7, 0x252c }, { 0x09f8, 0x2502 }, { 0x0aa1, 0x2003 }, + { 0x0aa2, 0x2002 }, { 0x0aa3, 0x2004 }, { 0x0aa4, 0x2005 }, { 0x0aa5, 0x2007 }, + { 0x0aa6, 0x2008 }, { 0x0aa7, 0x2009 }, { 0x0aa8, 0x200a }, { 0x0aa9, 0x2014 }, + { 0x0aaa, 0x2013 }, { 0x0aae, 0x2026 }, { 0x0aaf, 0x2025 }, { 0x0ab0, 0x2153 }, + { 0x0ab1, 0x2154 }, { 0x0ab2, 0x2155 }, { 0x0ab3, 0x2156 }, { 0x0ab4, 0x2157 }, + { 0x0ab5, 0x2158 }, { 0x0ab6, 0x2159 }, { 0x0ab7, 0x215a }, { 0x0ab8, 0x2105 }, + { 0x0abb, 0x2012 }, { 0x0abc, 0x2329 }, { 0x0abe, 0x232a }, { 0x0ac3, 0x215b }, + { 0x0ac4, 0x215c }, { 0x0ac5, 0x215d }, { 0x0ac6, 0x215e }, { 0x0ac9, 0x2122 }, + { 0x0aca, 0x2613 }, { 0x0acc, 0x25c1 }, { 0x0acd, 0x25b7 }, { 0x0ace, 0x25cb }, + { 0x0acf, 0x25af }, { 0x0ad0, 0x2018 }, { 0x0ad1, 0x2019 }, { 0x0ad2, 0x201c }, + { 0x0ad3, 0x201d }, { 0x0ad4, 0x211e }, { 0x0ad6, 0x2032 }, { 0x0ad7, 0x2033 }, + { 0x0ad9, 0x271d }, { 0x0adb, 0x25ac }, { 0x0adc, 0x25c0 }, { 0x0add, 0x25b6 }, + { 0x0ade, 0x25cf }, { 0x0adf, 0x25ae }, { 0x0ae0, 0x25e6 }, { 0x0ae1, 0x25ab }, + { 0x0ae2, 0x25ad }, { 0x0ae3, 0x25b3 }, { 0x0ae4, 0x25bd }, { 0x0ae5, 0x2606 }, + { 0x0ae6, 0x2022 }, { 0x0ae7, 0x25aa }, { 0x0ae8, 0x25b2 }, { 0x0ae9, 0x25bc }, + { 0x0aea, 0x261c }, { 0x0aeb, 0x261e }, { 0x0aec, 0x2663 }, { 0x0aed, 0x2666 }, + { 0x0aee, 0x2665 }, { 0x0af0, 0x2720 }, { 0x0af1, 0x2020 }, { 0x0af2, 0x2021 }, + { 0x0af3, 0x2713 }, { 0x0af4, 0x2717 }, { 0x0af5, 0x266f }, { 0x0af6, 0x266d }, + { 0x0af7, 0x2642 }, { 0x0af8, 0x2640 }, { 0x0af9, 0x260e }, { 0x0afa, 0x2315 }, + { 0x0afb, 0x2117 }, { 0x0afc, 0x2038 }, { 0x0afd, 0x201a }, { 0x0afe, 0x201e }, + { 0x0ba3, 0x003c }, { 0x0ba6, 0x003e }, { 0x0ba8, 0x2228 }, { 0x0ba9, 0x2227 }, + { 0x0bc0, 0x00af }, { 0x0bc2, 0x22a5 }, { 0x0bc3, 0x2229 }, { 0x0bc4, 0x230a }, + { 0x0bc6, 0x005f }, { 0x0bca, 0x2218 }, { 0x0bcc, 0x2395 }, { 0x0bce, 0x22a4 }, + { 0x0bcf, 0x25cb }, { 0x0bd3, 0x2308 }, { 0x0bd6, 0x222a }, { 0x0bd8, 0x2283 }, + { 0x0bda, 0x2282 }, { 0x0bdc, 0x22a2 }, { 0x0bfc, 0x22a3 }, { 0x0cdf, 0x2017 }, + { 0x0ce0, 0x05d0 }, { 0x0ce1, 0x05d1 }, { 0x0ce2, 0x05d2 }, { 0x0ce3, 0x05d3 }, + { 0x0ce4, 0x05d4 }, { 0x0ce5, 0x05d5 }, { 0x0ce6, 0x05d6 }, { 0x0ce7, 0x05d7 }, + { 0x0ce8, 0x05d8 }, { 0x0ce9, 0x05d9 }, { 0x0cea, 0x05da }, { 0x0ceb, 0x05db }, + { 0x0cec, 0x05dc }, { 0x0ced, 0x05dd }, { 0x0cee, 0x05de }, { 0x0cef, 0x05df }, + { 0x0cf0, 0x05e0 }, { 0x0cf1, 0x05e1 }, { 0x0cf2, 0x05e2 }, { 0x0cf3, 0x05e3 }, + { 0x0cf4, 0x05e4 }, { 0x0cf5, 0x05e5 }, { 0x0cf6, 0x05e6 }, { 0x0cf7, 0x05e7 }, + { 0x0cf8, 0x05e8 }, { 0x0cf9, 0x05e9 }, { 0x0cfa, 0x05ea }, { 0x0da1, 0x0e01 }, + { 0x0da2, 0x0e02 }, { 0x0da3, 0x0e03 }, { 0x0da4, 0x0e04 }, { 0x0da5, 0x0e05 }, + { 0x0da6, 0x0e06 }, { 0x0da7, 0x0e07 }, { 0x0da8, 0x0e08 }, { 0x0da9, 0x0e09 }, + { 0x0daa, 0x0e0a }, { 0x0dab, 0x0e0b }, { 0x0dac, 0x0e0c }, { 0x0dad, 0x0e0d }, + { 0x0dae, 0x0e0e }, { 0x0daf, 0x0e0f }, { 0x0db0, 0x0e10 }, { 0x0db1, 0x0e11 }, + { 0x0db2, 0x0e12 }, { 0x0db3, 0x0e13 }, { 0x0db4, 0x0e14 }, { 0x0db5, 0x0e15 }, + { 0x0db6, 0x0e16 }, { 0x0db7, 0x0e17 }, { 0x0db8, 0x0e18 }, { 0x0db9, 0x0e19 }, + { 0x0dba, 0x0e1a }, { 0x0dbb, 0x0e1b }, { 0x0dbc, 0x0e1c }, { 0x0dbd, 0x0e1d }, + { 0x0dbe, 0x0e1e }, { 0x0dbf, 0x0e1f }, { 0x0dc0, 0x0e20 }, { 0x0dc1, 0x0e21 }, + { 0x0dc2, 0x0e22 }, { 0x0dc3, 0x0e23 }, { 0x0dc4, 0x0e24 }, { 0x0dc5, 0x0e25 }, + { 0x0dc6, 0x0e26 }, { 0x0dc7, 0x0e27 }, { 0x0dc8, 0x0e28 }, { 0x0dc9, 0x0e29 }, + { 0x0dca, 0x0e2a }, { 0x0dcb, 0x0e2b }, { 0x0dcc, 0x0e2c }, { 0x0dcd, 0x0e2d }, + { 0x0dce, 0x0e2e }, { 0x0dcf, 0x0e2f }, { 0x0dd0, 0x0e30 }, { 0x0dd1, 0x0e31 }, + { 0x0dd2, 0x0e32 }, { 0x0dd3, 0x0e33 }, { 0x0dd4, 0x0e34 }, { 0x0dd5, 0x0e35 }, + { 0x0dd6, 0x0e36 }, { 0x0dd7, 0x0e37 }, { 0x0dd8, 0x0e38 }, { 0x0dd9, 0x0e39 }, + { 0x0dda, 0x0e3a }, { 0x0ddf, 0x0e3f }, { 0x0de0, 0x0e40 }, { 0x0de1, 0x0e41 }, + { 0x0de2, 0x0e42 }, { 0x0de3, 0x0e43 }, { 0x0de4, 0x0e44 }, { 0x0de5, 0x0e45 }, + { 0x0de6, 0x0e46 }, { 0x0de7, 0x0e47 }, { 0x0de8, 0x0e48 }, { 0x0de9, 0x0e49 }, + { 0x0dea, 0x0e4a }, { 0x0deb, 0x0e4b }, { 0x0dec, 0x0e4c }, { 0x0ded, 0x0e4d }, + { 0x0df0, 0x0e50 }, { 0x0df1, 0x0e51 }, { 0x0df2, 0x0e52 }, { 0x0df3, 0x0e53 }, + { 0x0df4, 0x0e54 }, { 0x0df5, 0x0e55 }, { 0x0df6, 0x0e56 }, { 0x0df7, 0x0e57 }, + { 0x0df8, 0x0e58 }, { 0x0df9, 0x0e59 }, { 0x0ea1, 0x3131 }, { 0x0ea2, 0x3132 }, + { 0x0ea3, 0x3133 }, { 0x0ea4, 0x3134 }, { 0x0ea5, 0x3135 }, { 0x0ea6, 0x3136 }, + { 0x0ea7, 0x3137 }, { 0x0ea8, 0x3138 }, { 0x0ea9, 0x3139 }, { 0x0eaa, 0x313a }, + { 0x0eab, 0x313b }, { 0x0eac, 0x313c }, { 0x0ead, 0x313d }, { 0x0eae, 0x313e }, + { 0x0eaf, 0x313f }, { 0x0eb0, 0x3140 }, { 0x0eb1, 0x3141 }, { 0x0eb2, 0x3142 }, + { 0x0eb3, 0x3143 }, { 0x0eb4, 0x3144 }, { 0x0eb5, 0x3145 }, { 0x0eb6, 0x3146 }, + { 0x0eb7, 0x3147 }, { 0x0eb8, 0x3148 }, { 0x0eb9, 0x3149 }, { 0x0eba, 0x314a }, + { 0x0ebb, 0x314b }, { 0x0ebc, 0x314c }, { 0x0ebd, 0x314d }, { 0x0ebe, 0x314e }, + { 0x0ebf, 0x314f }, { 0x0ec0, 0x3150 }, { 0x0ec1, 0x3151 }, { 0x0ec2, 0x3152 }, + { 0x0ec3, 0x3153 }, { 0x0ec4, 0x3154 }, { 0x0ec5, 0x3155 }, { 0x0ec6, 0x3156 }, + { 0x0ec7, 0x3157 }, { 0x0ec8, 0x3158 }, { 0x0ec9, 0x3159 }, { 0x0eca, 0x315a }, + { 0x0ecb, 0x315b }, { 0x0ecc, 0x315c }, { 0x0ecd, 0x315d }, { 0x0ece, 0x315e }, + { 0x0ecf, 0x315f }, { 0x0ed0, 0x3160 }, { 0x0ed1, 0x3161 }, { 0x0ed2, 0x3162 }, + { 0x0ed3, 0x3163 }, { 0x0ed4, 0x11a8 }, { 0x0ed5, 0x11a9 }, { 0x0ed6, 0x11aa }, + { 0x0ed7, 0x11ab }, { 0x0ed8, 0x11ac }, { 0x0ed9, 0x11ad }, { 0x0eda, 0x11ae }, + { 0x0edb, 0x11af }, { 0x0edc, 0x11b0 }, { 0x0edd, 0x11b1 }, { 0x0ede, 0x11b2 }, + { 0x0edf, 0x11b3 }, { 0x0ee0, 0x11b4 }, { 0x0ee1, 0x11b5 }, { 0x0ee2, 0x11b6 }, + { 0x0ee3, 0x11b7 }, { 0x0ee4, 0x11b8 }, { 0x0ee5, 0x11b9 }, { 0x0ee6, 0x11ba }, + { 0x0ee7, 0x11bb }, { 0x0ee8, 0x11bc }, { 0x0ee9, 0x11bd }, { 0x0eea, 0x11be }, + { 0x0eeb, 0x11bf }, { 0x0eec, 0x11c0 }, { 0x0eed, 0x11c1 }, { 0x0eee, 0x11c2 }, + { 0x0eef, 0x316d }, { 0x0ef0, 0x3171 }, { 0x0ef1, 0x3178 }, { 0x0ef2, 0x317f }, + { 0x0ef3, 0x3181 }, { 0x0ef4, 0x3184 }, { 0x0ef5, 0x3186 }, { 0x0ef6, 0x318d }, + { 0x0ef7, 0x318e }, { 0x0ef8, 0x11eb }, { 0x0ef9, 0x11f0 }, { 0x0efa, 0x11f9 }, + { 0x0eff, 0x20a9 }, { 0x13a4, 0x20ac }, { 0x13bc, 0x0152 }, { 0x13bd, 0x0153 }, + { 0x13be, 0x0178 }, { 0x20ac, 0x20ac }, +}; + +static unsigned int ImGui_ImplQNX_KeySymToUnicode(unsigned int keysym) +{ + // Latin-1 keysyms map directly to Unicode. + if ((keysym >= 0x0020u && keysym <= 0x007eu) || + (keysym >= 0x00a0u && keysym <= 0x00ffu)) + { + return keysym; + } + + // X11-style directly encoded UCS keysyms use 0x01000000 | codepoint. + if ((keysym & 0xff000000u) == 0x01000000u) + { + const unsigned int codepoint = keysym & 0x00ffffffu; + return codepoint <= IM_UNICODE_CODEPOINT_MAX ? codepoint : 0u; + } + + int min = 0; + int max = (int)(sizeof(ImGui_ImplQNX_KeySymTable) / sizeof(ImGui_ImplQNX_KeySymTable[0])) - 1; + while (max >= min) + { + const int mid = min + (max - min) / 2; + if (ImGui_ImplQNX_KeySymTable[mid].KeySym < keysym) + { + min = mid + 1; + } + else if (ImGui_ImplQNX_KeySymTable[mid].KeySym > keysym) + { + max = mid - 1; + } + else + { + return ImGui_ImplQNX_KeySymTable[mid].Unicode; + } + } + + return 0u; +} + +#endif // #ifndef IMGUI_DISABLE diff --git a/backends/imgui_impl_screen.h b/backends/imgui_impl_qnx.h similarity index 84% rename from backends/imgui_impl_screen.h rename to backends/imgui_impl_qnx.h index 5067de747..6436dfea9 100644 --- a/backends/imgui_impl_screen.h +++ b/backends/imgui_impl_qnx.h @@ -28,9 +28,9 @@ // The application owns the Screen context, window and event object. // Poll events with screen_get_event() and pass each non-NONE event to ProcessEvent(). -IMGUI_IMPL_API bool ImGui_ImplScreen_Init(screen_context_t context, screen_window_t window); -IMGUI_IMPL_API void ImGui_ImplScreen_Shutdown(); -IMGUI_IMPL_API void ImGui_ImplScreen_NewFrame(); -IMGUI_IMPL_API bool ImGui_ImplScreen_ProcessEvent(screen_event_t event); +IMGUI_IMPL_API bool ImGui_ImplQNX_Init(screen_context_t context, screen_window_t window); +IMGUI_IMPL_API void ImGui_ImplQNX_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplQNX_NewFrame(); +IMGUI_IMPL_API bool ImGui_ImplQNX_ProcessEvent(screen_event_t event); #endif // #ifndef IMGUI_DISABLE diff --git a/backends/imgui_impl_screen.cpp b/backends/imgui_impl_screen.cpp deleted file mode 100644 index de6427f03..000000000 --- a/backends/imgui_impl_screen.cpp +++ /dev/null @@ -1,521 +0,0 @@ -// dear imgui: Platform Backend for QNX Screen -// This needs to be used along with a Renderer Backend (e.g. OpenGL3, Vulkan). - -// Implemented features: -// [X] Platform: Keyboard support. Uses io.AddKeyEvent() and native QNX key symbols. -// [X] Platform: Mouse support. Handles position, three buttons and horizontal/vertical wheels. -// [X] Platform: Touch support. Maps the first active touch contact to the primary mouse button. -// [X] Platform: Focus and window-size updates. -// Missing features or Issues: -// [ ] Platform: Clipboard support. -// [ ] Platform: Gamepad support. -// [ ] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). -// [ ] Platform: Multi-viewport support. - -// CHANGELOG -// (minor and older changes stripped away, please see git history for details) -// 2026-07-29: Reworked keyboard handling from the proven qterm Screen path: authoritative modifier masks, -// complete keypad/Hyper mapping, and QNX/X11 keysym-to-Unicode conversion. -// 2026-07-29: Fixed keyboard handling: use KEY_CAP for physical keys, SYM for text, and honor Screen validity flags. -// 2026-07-28: Initial QNX Screen backend. - -#include "imgui.h" -#ifndef IMGUI_DISABLE -#include "imgui_impl_screen.h" - -#include -#include -#include -#include -#include - -#include "imgui_impl_screen_keysym2ucs.inl" - -struct ImGui_ImplScreen_Data -{ - screen_context_t Context; - screen_window_t Window; - uint64_t TimeNanoseconds; - int MouseButtons; - int ActiveTouchId; - bool LeftSuper; - bool RightSuper; - - ImGui_ImplScreen_Data() - { - memset(this, 0, sizeof(*this)); - ActiveTouchId = -1; - } -}; - -static ImGui_ImplScreen_Data* ImGui_ImplScreen_GetBackendData() -{ - return ImGui::GetCurrentContext() != nullptr ? (ImGui_ImplScreen_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr; -} - -static uint64_t ImGui_ImplScreen_GetTimeNanoseconds() -{ - struct timespec timestamp = {}; - if (clock_gettime(CLOCK_MONOTONIC, ×tamp) != 0) - { - return 0; - } - return (uint64_t)timestamp.tv_sec * UINT64_C(1000000000) + (uint64_t)timestamp.tv_nsec; -} - -static ImGuiKey ImGui_ImplScreen_KeyCodeToImGuiKey(int key_code) -{ - switch (key_code) - { - case KEYCODE_TAB: return ImGuiKey_Tab; - case KEYCODE_LEFT: return ImGuiKey_LeftArrow; - case KEYCODE_RIGHT: return ImGuiKey_RightArrow; - case KEYCODE_UP: return ImGuiKey_UpArrow; - case KEYCODE_DOWN: return ImGuiKey_DownArrow; - case KEYCODE_PG_UP: return ImGuiKey_PageUp; - case KEYCODE_PG_DOWN: return ImGuiKey_PageDown; - case KEYCODE_HOME: return ImGuiKey_Home; - case KEYCODE_END: return ImGuiKey_End; - case KEYCODE_INSERT: return ImGuiKey_Insert; - case KEYCODE_DELETE: return ImGuiKey_Delete; - case KEYCODE_BACKSPACE: return ImGuiKey_Backspace; - case KEYCODE_SPACE: return ImGuiKey_Space; - case KEYCODE_RETURN: return ImGuiKey_Enter; - case KEYCODE_ESCAPE: return ImGuiKey_Escape; - case KEYCODE_APOSTROPHE: return ImGuiKey_Apostrophe; - case KEYCODE_COMMA: return ImGuiKey_Comma; - case KEYCODE_MINUS: return ImGuiKey_Minus; - case KEYCODE_PERIOD: return ImGuiKey_Period; - case KEYCODE_SLASH: return ImGuiKey_Slash; - case KEYCODE_SEMICOLON: return ImGuiKey_Semicolon; - case KEYCODE_EQUAL: return ImGuiKey_Equal; - case KEYCODE_LEFT_BRACKET: return ImGuiKey_LeftBracket; - case KEYCODE_BACK_SLASH: return ImGuiKey_Backslash; - case KEYCODE_RIGHT_BRACKET: return ImGuiKey_RightBracket; - case KEYCODE_GRAVE: return ImGuiKey_GraveAccent; - case KEYCODE_CAPS_LOCK: return ImGuiKey_CapsLock; - case KEYCODE_SCROLL_LOCK: return ImGuiKey_ScrollLock; - case KEYCODE_NUM_LOCK: return ImGuiKey_NumLock; - case KEYCODE_PRINT: return ImGuiKey_PrintScreen; - case KEYCODE_PAUSE: return ImGuiKey_Pause; - case KEYCODE_KP_DIVIDE: return ImGuiKey_KeypadDivide; - case KEYCODE_KP_MULTIPLY: return ImGuiKey_KeypadMultiply; - case KEYCODE_KP_MINUS: return ImGuiKey_KeypadSubtract; - case KEYCODE_KP_PLUS: return ImGuiKey_KeypadAdd; - case KEYCODE_KP_ENTER: return ImGuiKey_KeypadEnter; - // QNX reports keypad digits by their navigation key-cap names. - case KEYCODE_KP_INSERT: return ImGuiKey_Keypad0; - case KEYCODE_KP_END: return ImGuiKey_Keypad1; - case KEYCODE_KP_DOWN: return ImGuiKey_Keypad2; - case KEYCODE_KP_PG_DOWN: return ImGuiKey_Keypad3; - case KEYCODE_KP_LEFT: return ImGuiKey_Keypad4; - case KEYCODE_KP_FIVE: return ImGuiKey_Keypad5; - case KEYCODE_KP_RIGHT: return ImGuiKey_Keypad6; - case KEYCODE_KP_HOME: return ImGuiKey_Keypad7; - case KEYCODE_KP_UP: return ImGuiKey_Keypad8; - case KEYCODE_KP_PG_UP: return ImGuiKey_Keypad9; - case KEYCODE_KP_DELETE: return ImGuiKey_KeypadDecimal; - case KEYCODE_LEFT_CTRL: return ImGuiKey_LeftCtrl; - case KEYCODE_LEFT_SHIFT: return ImGuiKey_LeftShift; - case KEYCODE_LEFT_ALT: return ImGuiKey_LeftAlt; - case KEYCODE_RIGHT_CTRL: return ImGuiKey_RightCtrl; - case KEYCODE_RIGHT_SHIFT: return ImGuiKey_RightShift; - case KEYCODE_RIGHT_ALT: return ImGuiKey_RightAlt; - case KEYCODE_LEFT_HYPER: return ImGuiKey_LeftSuper; - case KEYCODE_RIGHT_HYPER: return ImGuiKey_RightSuper; - case KEYCODE_MENU: return ImGuiKey_Menu; - case KEYCODE_ZERO: return ImGuiKey_0; - case KEYCODE_ONE: return ImGuiKey_1; - case KEYCODE_TWO: return ImGuiKey_2; - case KEYCODE_THREE: return ImGuiKey_3; - case KEYCODE_FOUR: return ImGuiKey_4; - case KEYCODE_FIVE: return ImGuiKey_5; - case KEYCODE_SIX: return ImGuiKey_6; - case KEYCODE_SEVEN: return ImGuiKey_7; - case KEYCODE_EIGHT: return ImGuiKey_8; - case KEYCODE_NINE: return ImGuiKey_9; - case KEYCODE_A: return ImGuiKey_A; - case KEYCODE_B: return ImGuiKey_B; - case KEYCODE_C: return ImGuiKey_C; - case KEYCODE_D: return ImGuiKey_D; - case KEYCODE_E: return ImGuiKey_E; - case KEYCODE_F: return ImGuiKey_F; - case KEYCODE_G: return ImGuiKey_G; - case KEYCODE_H: return ImGuiKey_H; - case KEYCODE_I: return ImGuiKey_I; - case KEYCODE_J: return ImGuiKey_J; - case KEYCODE_K: return ImGuiKey_K; - case KEYCODE_L: return ImGuiKey_L; - case KEYCODE_M: return ImGuiKey_M; - case KEYCODE_N: return ImGuiKey_N; - case KEYCODE_O: return ImGuiKey_O; - case KEYCODE_P: return ImGuiKey_P; - case KEYCODE_Q: return ImGuiKey_Q; - case KEYCODE_R: return ImGuiKey_R; - case KEYCODE_S: return ImGuiKey_S; - case KEYCODE_T: return ImGuiKey_T; - case KEYCODE_U: return ImGuiKey_U; - case KEYCODE_V: return ImGuiKey_V; - case KEYCODE_W: return ImGuiKey_W; - case KEYCODE_X: return ImGuiKey_X; - case KEYCODE_Y: return ImGuiKey_Y; - case KEYCODE_Z: return ImGuiKey_Z; - case KEYCODE_F1: return ImGuiKey_F1; - case KEYCODE_F2: return ImGuiKey_F2; - case KEYCODE_F3: return ImGuiKey_F3; - case KEYCODE_F4: return ImGuiKey_F4; - case KEYCODE_F5: return ImGuiKey_F5; - case KEYCODE_F6: return ImGuiKey_F6; - case KEYCODE_F7: return ImGuiKey_F7; - case KEYCODE_F8: return ImGuiKey_F8; - case KEYCODE_F9: return ImGuiKey_F9; - case KEYCODE_F10: return ImGuiKey_F10; - case KEYCODE_F11: return ImGuiKey_F11; - case KEYCODE_F12: return ImGuiKey_F12; - default: return ImGuiKey_None; - } -} - -static void ImGui_ImplScreen_UpdateKeyModifiers(ImGuiIO& io, ImGui_ImplScreen_Data* bd, int modifiers, ImGuiKey key, bool down) -{ - // SCREEN_PROPERTY_MODIFIERS is the authoritative state for Shift/Ctrl/Alt. - // Tracking those keys locally loses sticky modifiers and can become stale if - // a key transition is consumed elsewhere. qterm uses this same Screen state. - if (key == ImGuiKey_LeftSuper) - { - bd->LeftSuper = down; - } - else if (key == ImGuiKey_RightSuper) - { - bd->RightSuper = down; - } - - io.AddKeyEvent(ImGuiMod_Ctrl, (modifiers & KEYMOD_CTRL) != 0); - io.AddKeyEvent(ImGuiMod_Shift, (modifiers & KEYMOD_SHIFT) != 0); - io.AddKeyEvent(ImGuiMod_Alt, (modifiers & KEYMOD_ALT) != 0); - io.AddKeyEvent(ImGuiMod_Super, bd->LeftSuper || bd->RightSuper); -} - -static void ImGui_ImplScreen_ClearModifierState(ImGuiIO& io, ImGui_ImplScreen_Data* bd) -{ - bd->LeftSuper = false; - bd->RightSuper = false; - io.AddKeyEvent(ImGuiMod_Ctrl, false); - io.AddKeyEvent(ImGuiMod_Shift, false); - io.AddKeyEvent(ImGuiMod_Alt, false); - io.AddKeyEvent(ImGuiMod_Super, false); -} - -static bool ImGui_ImplScreen_IsTextCodePoint(unsigned int code_point) -{ - // At this point the QNX keysym has already been converted to Unicode. - // Do not reject Unicode private-use characters: a user keymap may emit one. - const bool surrogate = code_point >= 0xd800u && code_point <= 0xdfffu; - const bool control = code_point < 0x20u || (code_point >= 0x7fu && code_point <= 0x9fu); - return code_point <= IM_UNICODE_CODEPOINT_MAX && !surrogate && !control; -} - -static bool ImGui_ImplScreen_ProcessKeyboardEvent(ImGui_ImplScreen_Data* bd, screen_event_t event) -{ - int flags = 0; - int modifiers = 0; - if (screen_get_event_property_iv(event, SCREEN_PROPERTY_FLAGS, &flags) != 0 || - screen_get_event_property_iv(event, SCREEN_PROPERTY_MODIFIERS, &modifiers) != 0) - { - return false; - } - - // KEY_CAP is the unmodified key identity used for ImGuiKey events. SYM is - // the layout/modifier-translated QNX keysym used for text input. - int key_cap = 0; - int key_sym = 0; - int scan_code = 0; - const bool cap_valid = (flags & SCREEN_FLAG_CAP_VALID) != 0; - const bool sym_valid = (flags & SCREEN_FLAG_SYM_VALID) != 0; - const bool scan_valid = (flags & SCREEN_FLAG_SCAN_VALID) != 0; - const bool down = (flags & (SCREEN_FLAG_KEY_DOWN | SCREEN_FLAG_KEY_REPEAT)) != 0; - - if (cap_valid && screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_CAP, &key_cap) != 0) - { - return false; - } - if (sym_valid && screen_get_event_property_iv(event, SCREEN_PROPERTY_SYM, &key_sym) != 0) - { - return false; - } - if (scan_valid && screen_get_event_property_iv(event, SCREEN_PROPERTY_SCAN, &scan_code) != 0) - { - scan_code = 0; - } - - const ImGuiKey key = cap_valid ? ImGui_ImplScreen_KeyCodeToImGuiKey(key_cap) : ImGuiKey_None; - ImGuiIO& io = ImGui::GetIO(); - - // Modifier events must precede the ordinary key event in Dear ImGui's queue. - // Unlike qterm, we still submit the individual modifier key because ImGui - // exposes Left/Right Ctrl, Shift, Alt and Super as named keys. - ImGui_ImplScreen_UpdateKeyModifiers(io, bd, modifiers, key, down); - - if (key != ImGuiKey_None) - { - io.AddKeyEvent(key, down); - io.SetKeyEventNativeData(key, key_cap, scan_code); - } - - bool text_added = false; - if (down && sym_valid && key_sym >= 0) - { - const unsigned int keysym = (unsigned int)key_sym; - // QNX special/function symbols begin at KEYCODE_PC_KEYS. Printable - // symbols below that boundary use X11 keysym encoding. Also accept the - // standard directly encoded UCS keysym form (0x01000000 | codepoint). - if (keysym < (unsigned int)KEYCODE_PC_KEYS || (keysym & 0xff000000u) == 0x01000000u) - { - const unsigned int code_point = ImGui_ImplScreen_KeySymToUnicode(keysym); - if (ImGui_ImplScreen_IsTextCodePoint(code_point)) - { - io.AddInputCharacter(code_point); - text_added = true; - } - } - } - - return key != ImGuiKey_None || text_added || cap_valid || sym_valid; -} - -static bool ImGui_ImplScreen_ProcessPointerEvent(ImGui_ImplScreen_Data* bd, screen_event_t event) -{ - int position[2] = {}; - int buttons = 0; - int wheel_vertical = 0; - int wheel_horizontal = 0; - - if (screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, position) != 0 && - screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, position) != 0) - { - return false; - } - if (screen_get_event_property_iv(event, SCREEN_PROPERTY_BUTTONS, &buttons) != 0) - { - buttons = bd->MouseButtons; - } - - ImGuiIO& io = ImGui::GetIO(); - io.AddMouseSourceEvent(ImGuiMouseSource_Mouse); - io.AddMousePosEvent((float)position[0], (float)position[1]); - - const int changed_buttons = buttons ^ bd->MouseButtons; - if ((changed_buttons & SCREEN_LEFT_MOUSE_BUTTON) != 0) - { - io.AddMouseButtonEvent(0, (buttons & SCREEN_LEFT_MOUSE_BUTTON) != 0); - } - if ((changed_buttons & SCREEN_RIGHT_MOUSE_BUTTON) != 0) - { - io.AddMouseButtonEvent(1, (buttons & SCREEN_RIGHT_MOUSE_BUTTON) != 0); - } - if ((changed_buttons & SCREEN_MIDDLE_MOUSE_BUTTON) != 0) - { - io.AddMouseButtonEvent(2, (buttons & SCREEN_MIDDLE_MOUSE_BUTTON) != 0); - } - bd->MouseButtons = buttons; - - if (screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_WHEEL, &wheel_vertical) != 0) - { - wheel_vertical = 0; - } - if (screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_HORIZONTAL_WHEEL, &wheel_horizontal) != 0) - { - wheel_horizontal = 0; - } - if (wheel_vertical != 0 || wheel_horizontal != 0) - { - // Screen: up/left are negative. Dear ImGui: up/left are positive. - io.AddMouseWheelEvent((float)-wheel_horizontal, (float)-wheel_vertical); - } - return true; -} - -static bool ImGui_ImplScreen_ProcessTouchEvent(ImGui_ImplScreen_Data* bd, screen_event_t event, int event_type) -{ - int touch_id = -1; - int position[2] = {}; - if (screen_get_event_property_iv(event, SCREEN_PROPERTY_TOUCH_ID, &touch_id) != 0) - { - return false; - } - - const bool is_release = event_type == SCREEN_EVENT_MTOUCH_RELEASE; - if (bd->ActiveTouchId != -1 && touch_id != bd->ActiveTouchId) - { - return false; - } - - ImGuiIO& io = ImGui::GetIO(); - io.AddMouseSourceEvent(ImGuiMouseSource_TouchScreen); - - if (!is_release) - { - if (screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, position) != 0 && - screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, position) != 0) - { - return false; - } - io.AddMousePosEvent((float)position[0], (float)position[1]); - } - - if (event_type == SCREEN_EVENT_MTOUCH_TOUCH) - { - bd->ActiveTouchId = touch_id; - io.AddMouseButtonEvent(0, true); - } - else if (is_release) - { - io.AddMouseButtonEvent(0, false); - io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); - bd->ActiveTouchId = -1; - } - return true; -} - -bool ImGui_ImplScreen_ProcessEvent(screen_event_t event) -{ - ImGui_ImplScreen_Data* bd = ImGui_ImplScreen_GetBackendData(); - IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplScreen_Init()?"); - if (bd == nullptr || event == nullptr) - { - return false; - } - - int event_type = SCREEN_EVENT_NONE; - if (screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &event_type) != 0 || event_type == SCREEN_EVENT_NONE) - { - return false; - } - switch (event_type) - { - case SCREEN_EVENT_KEYBOARD: - return ImGui_ImplScreen_ProcessKeyboardEvent(bd, event); - case SCREEN_EVENT_POINTER: - return ImGui_ImplScreen_ProcessPointerEvent(bd, event); - case SCREEN_EVENT_MTOUCH_TOUCH: - case SCREEN_EVENT_MTOUCH_MOVE: - case SCREEN_EVENT_MTOUCH_RELEASE: - return ImGui_ImplScreen_ProcessTouchEvent(bd, event, event_type); - case SCREEN_EVENT_PROPERTY: - { - int property = 0; - if (screen_get_event_property_iv(event, SCREEN_PROPERTY_NAME, &property) != 0) - { - return false; - } - if (property == SCREEN_PROPERTY_FOCUS) - { - int focused = 0; - if (screen_get_window_property_iv(bd->Window, SCREEN_PROPERTY_FOCUS, &focused) == 0) - { - ImGuiIO& io = ImGui::GetIO(); - io.AddFocusEvent(focused != 0); - if (focused == 0) - { - ImGui_ImplScreen_ClearModifierState(io, bd); - } - } - return true; - } - if (property == SCREEN_PROPERTY_SIZE || property == SCREEN_PROPERTY_BUFFER_SIZE || property == SCREEN_PROPERTY_VISIBLE) - { - return true; - } - return false; - } - case SCREEN_EVENT_CLOSE: - { - ImGuiIO& io = ImGui::GetIO(); - io.AddFocusEvent(false); - ImGui_ImplScreen_ClearModifierState(io, bd); - return true; - } - default: - return false; - } -} - -bool ImGui_ImplScreen_Init(screen_context_t context, screen_window_t window) -{ - ImGuiIO& io = ImGui::GetIO(); - IMGUI_CHECKVERSION(); - IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); - IM_ASSERT(context != nullptr && window != nullptr); - if (context == nullptr || window == nullptr) - { - return false; - } - - ImGui_ImplScreen_Data* bd = IM_NEW(ImGui_ImplScreen_Data)(); - io.BackendPlatformUserData = (void*)bd; - io.BackendPlatformName = "imgui_impl_screen"; - - bd->Context = context; - bd->Window = window; - bd->TimeNanoseconds = ImGui_ImplScreen_GetTimeNanoseconds(); - - int focused = 0; - if (screen_get_window_property_iv(window, SCREEN_PROPERTY_FOCUS, &focused) == 0) - { - io.AddFocusEvent(focused != 0); - } - return true; -} - -void ImGui_ImplScreen_Shutdown() -{ - ImGui_ImplScreen_Data* bd = ImGui_ImplScreen_GetBackendData(); - IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); - if (bd == nullptr) - { - return; - } - - ImGuiIO& io = ImGui::GetIO(); - io.BackendPlatformName = nullptr; - io.BackendPlatformUserData = nullptr; - IM_DELETE(bd); -} - -void ImGui_ImplScreen_NewFrame() -{ - ImGui_ImplScreen_Data* bd = ImGui_ImplScreen_GetBackendData(); - IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplScreen_Init()?"); - if (bd == nullptr) - { - return; - } - - ImGuiIO& io = ImGui::GetIO(); - int size[2] = {}; - if (screen_get_window_property_iv(bd->Window, SCREEN_PROPERTY_BUFFER_SIZE, size) != 0 || - size[0] <= 0 || size[1] <= 0) - { - size[0] = 0; - size[1] = 0; - (void)screen_get_window_property_iv(bd->Window, SCREEN_PROPERTY_SIZE, size); - } - if (size[0] > 0 && size[1] > 0) - { - io.DisplaySize = ImVec2((float)size[0], (float)size[1]); - io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f); - } - - const uint64_t current_time = ImGui_ImplScreen_GetTimeNanoseconds(); - if (current_time > bd->TimeNanoseconds && bd->TimeNanoseconds != 0) - { - io.DeltaTime = (float)((double)(current_time - bd->TimeNanoseconds) / 1000000000.0); - } - else - { - io.DeltaTime = 1.0f / 60.0f; - } - bd->TimeNanoseconds = current_time; -} - -#endif // #ifndef IMGUI_DISABLE diff --git a/backends/imgui_impl_screen_keysym2ucs.inl b/backends/imgui_impl_screen_keysym2ucs.inl deleted file mode 100644 index ad17c3265..000000000 --- a/backends/imgui_impl_screen_keysym2ucs.inl +++ /dev/null @@ -1,858 +0,0 @@ -/* $XFree86$ - * This module converts keysym values into the corresponding ISO 10646 - * (UCS, Unicode) values. - * - * The array keysymtab[] contains pairs of X11 keysym values for graphical - * characters and the corresponding Unicode value. The function - * keysym2ucs() maps a keysym onto a Unicode value using a binary search, - * therefore keysymtab[] must remain SORTED by keysym value. - * - * The keysym -> UTF-8 conversion will hopefully one day be provided - * by Xlib via XmbLookupString() and should ideally not have to be - * done in X applications. But we are not there yet. - * - * We allow to represent any UCS character in the range U-00000000 to - * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff. - * This admittedly does not cover the entire 31-bit space of UCS, but - * it does cover all of the characters up to U-10FFFF, which can be - * represented by UTF-16, and more, and it is very unlikely that higher - * UCS codes will ever be assigned by ISO. So to get Unicode character - * U+ABCD you can directly use keysym 0x0100abcd. - * - * NOTE: The comments in the table below contain the actual character - * encoded in UTF-8, so for viewing and editing best use an editor in - * UTF-8 mode. - * - * Author: Markus G. Kuhn , - * University of Cambridge, April 2001 - * - * Special thanks to Richard Verhoeven for preparing - * an initial draft of the mapping table. - * - * This software is in the public domain. Share and enjoy! - * - * AUTOMATICALLY GENERATED FILE, DO NOT EDIT !!! (unicode/convmap.pl) - */ - -// Adapted for the Dear ImGui QNX Screen backend. This file is included by -// imgui_impl_screen.cpp and intentionally has internal linkage. - -struct ImGui_ImplScreen_KeySymPair { - uint16_t keysym; - uint16_t ucs; -}; - -static const ImGui_ImplScreen_KeySymPair ImGui_ImplScreen_KeySymTable[] = { - { 0x01a1, 0x0104 }, /* Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */ - { 0x01a2, 0x02d8 }, /* breve ˘ BREVE */ - { 0x01a3, 0x0141 }, /* Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */ - { 0x01a5, 0x013d }, /* Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */ - { 0x01a6, 0x015a }, /* Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */ - { 0x01a9, 0x0160 }, /* Scaron Š LATIN CAPITAL LETTER S WITH CARON */ - { 0x01aa, 0x015e }, /* Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */ - { 0x01ab, 0x0164 }, /* Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */ - { 0x01ac, 0x0179 }, /* Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */ - { 0x01ae, 0x017d }, /* Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */ - { 0x01af, 0x017b }, /* Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */ - { 0x01b1, 0x0105 }, /* aogonek ą LATIN SMALL LETTER A WITH OGONEK */ - { 0x01b2, 0x02db }, /* ogonek ˛ OGONEK */ - { 0x01b3, 0x0142 }, /* lstroke ł LATIN SMALL LETTER L WITH STROKE */ - { 0x01b5, 0x013e }, /* lcaron ľ LATIN SMALL LETTER L WITH CARON */ - { 0x01b6, 0x015b }, /* sacute ś LATIN SMALL LETTER S WITH ACUTE */ - { 0x01b7, 0x02c7 }, /* caron ˇ CARON */ - { 0x01b9, 0x0161 }, /* scaron š LATIN SMALL LETTER S WITH CARON */ - { 0x01ba, 0x015f }, /* scedilla ş LATIN SMALL LETTER S WITH CEDILLA */ - { 0x01bb, 0x0165 }, /* tcaron ť LATIN SMALL LETTER T WITH CARON */ - { 0x01bc, 0x017a }, /* zacute ź LATIN SMALL LETTER Z WITH ACUTE */ - { 0x01bd, 0x02dd }, /* doubleacute ˝ DOUBLE ACUTE ACCENT */ - { 0x01be, 0x017e }, /* zcaron ž LATIN SMALL LETTER Z WITH CARON */ - { 0x01bf, 0x017c }, /* zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */ - { 0x01c0, 0x0154 }, /* Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */ - { 0x01c3, 0x0102 }, /* Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */ - { 0x01c5, 0x0139 }, /* Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */ - { 0x01c6, 0x0106 }, /* Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */ - { 0x01c8, 0x010c }, /* Ccaron Č LATIN CAPITAL LETTER C WITH CARON */ - { 0x01ca, 0x0118 }, /* Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */ - { 0x01cc, 0x011a }, /* Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */ - { 0x01cf, 0x010e }, /* Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */ - { 0x01d0, 0x0110 }, /* Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */ - { 0x01d1, 0x0143 }, /* Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */ - { 0x01d2, 0x0147 }, /* Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */ - { 0x01d5, 0x0150 }, /* Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ - { 0x01d8, 0x0158 }, /* Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */ - { 0x01d9, 0x016e }, /* Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */ - { 0x01db, 0x0170 }, /* Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ - { 0x01de, 0x0162 }, /* Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */ - { 0x01e0, 0x0155 }, /* racute ŕ LATIN SMALL LETTER R WITH ACUTE */ - { 0x01e3, 0x0103 }, /* abreve ă LATIN SMALL LETTER A WITH BREVE */ - { 0x01e5, 0x013a }, /* lacute ĺ LATIN SMALL LETTER L WITH ACUTE */ - { 0x01e6, 0x0107 }, /* cacute ć LATIN SMALL LETTER C WITH ACUTE */ - { 0x01e8, 0x010d }, /* ccaron č LATIN SMALL LETTER C WITH CARON */ - { 0x01ea, 0x0119 }, /* eogonek ę LATIN SMALL LETTER E WITH OGONEK */ - { 0x01ec, 0x011b }, /* ecaron ě LATIN SMALL LETTER E WITH CARON */ - { 0x01ef, 0x010f }, /* dcaron ď LATIN SMALL LETTER D WITH CARON */ - { 0x01f0, 0x0111 }, /* dstroke đ LATIN SMALL LETTER D WITH STROKE */ - { 0x01f1, 0x0144 }, /* nacute ń LATIN SMALL LETTER N WITH ACUTE */ - { 0x01f2, 0x0148 }, /* ncaron ň LATIN SMALL LETTER N WITH CARON */ - { 0x01f5, 0x0151 }, /* odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */ - { 0x01f8, 0x0159 }, /* rcaron ř LATIN SMALL LETTER R WITH CARON */ - { 0x01f9, 0x016f }, /* uring ů LATIN SMALL LETTER U WITH RING ABOVE */ - { 0x01fb, 0x0171 }, /* udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */ - { 0x01fe, 0x0163 }, /* tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */ - { 0x01ff, 0x02d9 }, /* abovedot ˙ DOT ABOVE */ - { 0x02a1, 0x0126 }, /* Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */ - { 0x02a6, 0x0124 }, /* Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ - { 0x02a9, 0x0130 }, /* Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */ - { 0x02ab, 0x011e }, /* Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */ - { 0x02ac, 0x0134 }, /* Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ - { 0x02b1, 0x0127 }, /* hstroke ħ LATIN SMALL LETTER H WITH STROKE */ - { 0x02b6, 0x0125 }, /* hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */ - { 0x02b9, 0x0131 }, /* idotless ı LATIN SMALL LETTER DOTLESS I */ - { 0x02bb, 0x011f }, /* gbreve ğ LATIN SMALL LETTER G WITH BREVE */ - { 0x02bc, 0x0135 }, /* jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */ - { 0x02c5, 0x010a }, /* Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */ - { 0x02c6, 0x0108 }, /* Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ - { 0x02d5, 0x0120 }, /* Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */ - { 0x02d8, 0x011c }, /* Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ - { 0x02dd, 0x016c }, /* Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */ - { 0x02de, 0x015c }, /* Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ - { 0x02e5, 0x010b }, /* cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */ - { 0x02e6, 0x0109 }, /* ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */ - { 0x02f5, 0x0121 }, /* gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */ - { 0x02f8, 0x011d }, /* gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */ - { 0x02fd, 0x016d }, /* ubreve ŭ LATIN SMALL LETTER U WITH BREVE */ - { 0x02fe, 0x015d }, /* scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */ - { 0x03a2, 0x0138 }, /* kra ĸ LATIN SMALL LETTER KRA */ - { 0x03a3, 0x0156 }, /* Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */ - { 0x03a5, 0x0128 }, /* Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */ - { 0x03a6, 0x013b }, /* Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */ - { 0x03aa, 0x0112 }, /* Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */ - { 0x03ab, 0x0122 }, /* Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */ - { 0x03ac, 0x0166 }, /* Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */ - { 0x03b3, 0x0157 }, /* rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */ - { 0x03b5, 0x0129 }, /* itilde ĩ LATIN SMALL LETTER I WITH TILDE */ - { 0x03b6, 0x013c }, /* lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */ - { 0x03ba, 0x0113 }, /* emacron ē LATIN SMALL LETTER E WITH MACRON */ - { 0x03bb, 0x0123 }, /* gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */ - { 0x03bc, 0x0167 }, /* tslash ŧ LATIN SMALL LETTER T WITH STROKE */ - { 0x03bd, 0x014a }, /* ENG Ŋ LATIN CAPITAL LETTER ENG */ - { 0x03bf, 0x014b }, /* eng ŋ LATIN SMALL LETTER ENG */ - { 0x03c0, 0x0100 }, /* Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */ - { 0x03c7, 0x012e }, /* Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */ - { 0x03cc, 0x0116 }, /* Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */ - { 0x03cf, 0x012a }, /* Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */ - { 0x03d1, 0x0145 }, /* Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */ - { 0x03d2, 0x014c }, /* Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */ - { 0x03d3, 0x0136 }, /* Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */ - { 0x03d9, 0x0172 }, /* Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */ - { 0x03dd, 0x0168 }, /* Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */ - { 0x03de, 0x016a }, /* Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */ - { 0x03e0, 0x0101 }, /* amacron ā LATIN SMALL LETTER A WITH MACRON */ - { 0x03e7, 0x012f }, /* iogonek į LATIN SMALL LETTER I WITH OGONEK */ - { 0x03ec, 0x0117 }, /* eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */ - { 0x03ef, 0x012b }, /* imacron ī LATIN SMALL LETTER I WITH MACRON */ - { 0x03f1, 0x0146 }, /* ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */ - { 0x03f2, 0x014d }, /* omacron ō LATIN SMALL LETTER O WITH MACRON */ - { 0x03f3, 0x0137 }, /* kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */ - { 0x03f9, 0x0173 }, /* uogonek ų LATIN SMALL LETTER U WITH OGONEK */ - { 0x03fd, 0x0169 }, /* utilde ũ LATIN SMALL LETTER U WITH TILDE */ - { 0x03fe, 0x016b }, /* umacron ū LATIN SMALL LETTER U WITH MACRON */ - { 0x047e, 0x203e }, /* overline ‾ OVERLINE */ - { 0x04a1, 0x3002 }, /* kana_fullstop 。 IDEOGRAPHIC FULL STOP */ - { 0x04a2, 0x300c }, /* kana_openingbracket 「 LEFT CORNER BRACKET */ - { 0x04a3, 0x300d }, /* kana_closingbracket 」 RIGHT CORNER BRACKET */ - { 0x04a4, 0x3001 }, /* kana_comma 、 IDEOGRAPHIC COMMA */ - { 0x04a5, 0x30fb }, /* kana_conjunctive ・ KATAKANA MIDDLE DOT */ - { 0x04a6, 0x30f2 }, /* kana_WO ヲ KATAKANA LETTER WO */ - { 0x04a7, 0x30a1 }, /* kana_a ァ KATAKANA LETTER SMALL A */ - { 0x04a8, 0x30a3 }, /* kana_i ィ KATAKANA LETTER SMALL I */ - { 0x04a9, 0x30a5 }, /* kana_u ゥ KATAKANA LETTER SMALL U */ - { 0x04aa, 0x30a7 }, /* kana_e ェ KATAKANA LETTER SMALL E */ - { 0x04ab, 0x30a9 }, /* kana_o ォ KATAKANA LETTER SMALL O */ - { 0x04ac, 0x30e3 }, /* kana_ya ャ KATAKANA LETTER SMALL YA */ - { 0x04ad, 0x30e5 }, /* kana_yu ュ KATAKANA LETTER SMALL YU */ - { 0x04ae, 0x30e7 }, /* kana_yo ョ KATAKANA LETTER SMALL YO */ - { 0x04af, 0x30c3 }, /* kana_tsu ッ KATAKANA LETTER SMALL TU */ - { 0x04b0, 0x30fc }, /* prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */ - { 0x04b1, 0x30a2 }, /* kana_A ア KATAKANA LETTER A */ - { 0x04b2, 0x30a4 }, /* kana_I イ KATAKANA LETTER I */ - { 0x04b3, 0x30a6 }, /* kana_U ウ KATAKANA LETTER U */ - { 0x04b4, 0x30a8 }, /* kana_E エ KATAKANA LETTER E */ - { 0x04b5, 0x30aa }, /* kana_O オ KATAKANA LETTER O */ - { 0x04b6, 0x30ab }, /* kana_KA カ KATAKANA LETTER KA */ - { 0x04b7, 0x30ad }, /* kana_KI キ KATAKANA LETTER KI */ - { 0x04b8, 0x30af }, /* kana_KU ク KATAKANA LETTER KU */ - { 0x04b9, 0x30b1 }, /* kana_KE ケ KATAKANA LETTER KE */ - { 0x04ba, 0x30b3 }, /* kana_KO コ KATAKANA LETTER KO */ - { 0x04bb, 0x30b5 }, /* kana_SA サ KATAKANA LETTER SA */ - { 0x04bc, 0x30b7 }, /* kana_SHI シ KATAKANA LETTER SI */ - { 0x04bd, 0x30b9 }, /* kana_SU ス KATAKANA LETTER SU */ - { 0x04be, 0x30bb }, /* kana_SE セ KATAKANA LETTER SE */ - { 0x04bf, 0x30bd }, /* kana_SO ソ KATAKANA LETTER SO */ - { 0x04c0, 0x30bf }, /* kana_TA タ KATAKANA LETTER TA */ - { 0x04c1, 0x30c1 }, /* kana_CHI チ KATAKANA LETTER TI */ - { 0x04c2, 0x30c4 }, /* kana_TSU ツ KATAKANA LETTER TU */ - { 0x04c3, 0x30c6 }, /* kana_TE テ KATAKANA LETTER TE */ - { 0x04c4, 0x30c8 }, /* kana_TO ト KATAKANA LETTER TO */ - { 0x04c5, 0x30ca }, /* kana_NA ナ KATAKANA LETTER NA */ - { 0x04c6, 0x30cb }, /* kana_NI ニ KATAKANA LETTER NI */ - { 0x04c7, 0x30cc }, /* kana_NU ヌ KATAKANA LETTER NU */ - { 0x04c8, 0x30cd }, /* kana_NE ネ KATAKANA LETTER NE */ - { 0x04c9, 0x30ce }, /* kana_NO ノ KATAKANA LETTER NO */ - { 0x04ca, 0x30cf }, /* kana_HA ハ KATAKANA LETTER HA */ - { 0x04cb, 0x30d2 }, /* kana_HI ヒ KATAKANA LETTER HI */ - { 0x04cc, 0x30d5 }, /* kana_FU フ KATAKANA LETTER HU */ - { 0x04cd, 0x30d8 }, /* kana_HE ヘ KATAKANA LETTER HE */ - { 0x04ce, 0x30db }, /* kana_HO ホ KATAKANA LETTER HO */ - { 0x04cf, 0x30de }, /* kana_MA マ KATAKANA LETTER MA */ - { 0x04d0, 0x30df }, /* kana_MI ミ KATAKANA LETTER MI */ - { 0x04d1, 0x30e0 }, /* kana_MU ム KATAKANA LETTER MU */ - { 0x04d2, 0x30e1 }, /* kana_ME メ KATAKANA LETTER ME */ - { 0x04d3, 0x30e2 }, /* kana_MO モ KATAKANA LETTER MO */ - { 0x04d4, 0x30e4 }, /* kana_YA ヤ KATAKANA LETTER YA */ - { 0x04d5, 0x30e6 }, /* kana_YU ユ KATAKANA LETTER YU */ - { 0x04d6, 0x30e8 }, /* kana_YO ヨ KATAKANA LETTER YO */ - { 0x04d7, 0x30e9 }, /* kana_RA ラ KATAKANA LETTER RA */ - { 0x04d8, 0x30ea }, /* kana_RI リ KATAKANA LETTER RI */ - { 0x04d9, 0x30eb }, /* kana_RU ル KATAKANA LETTER RU */ - { 0x04da, 0x30ec }, /* kana_RE レ KATAKANA LETTER RE */ - { 0x04db, 0x30ed }, /* kana_RO ロ KATAKANA LETTER RO */ - { 0x04dc, 0x30ef }, /* kana_WA ワ KATAKANA LETTER WA */ - { 0x04dd, 0x30f3 }, /* kana_N ン KATAKANA LETTER N */ - { 0x04de, 0x309b }, /* voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */ - { 0x04df, 0x309c }, /* semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */ - { 0x05ac, 0x060c }, /* Arabic_comma ، ARABIC COMMA */ - { 0x05bb, 0x061b }, /* Arabic_semicolon ؛ ARABIC SEMICOLON */ - { 0x05bf, 0x061f }, /* Arabic_question_mark ؟ ARABIC QUESTION MARK */ - { 0x05c1, 0x0621 }, /* Arabic_hamza ء ARABIC LETTER HAMZA */ - { 0x05c2, 0x0622 }, /* Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */ - { 0x05c3, 0x0623 }, /* Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */ - { 0x05c4, 0x0624 }, /* Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */ - { 0x05c5, 0x0625 }, /* Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */ - { 0x05c6, 0x0626 }, /* Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */ - { 0x05c7, 0x0627 }, /* Arabic_alef ا ARABIC LETTER ALEF */ - { 0x05c8, 0x0628 }, /* Arabic_beh ب ARABIC LETTER BEH */ - { 0x05c9, 0x0629 }, /* Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */ - { 0x05ca, 0x062a }, /* Arabic_teh ت ARABIC LETTER TEH */ - { 0x05cb, 0x062b }, /* Arabic_theh ث ARABIC LETTER THEH */ - { 0x05cc, 0x062c }, /* Arabic_jeem ج ARABIC LETTER JEEM */ - { 0x05cd, 0x062d }, /* Arabic_hah ح ARABIC LETTER HAH */ - { 0x05ce, 0x062e }, /* Arabic_khah خ ARABIC LETTER KHAH */ - { 0x05cf, 0x062f }, /* Arabic_dal د ARABIC LETTER DAL */ - { 0x05d0, 0x0630 }, /* Arabic_thal ذ ARABIC LETTER THAL */ - { 0x05d1, 0x0631 }, /* Arabic_ra ر ARABIC LETTER REH */ - { 0x05d2, 0x0632 }, /* Arabic_zain ز ARABIC LETTER ZAIN */ - { 0x05d3, 0x0633 }, /* Arabic_seen س ARABIC LETTER SEEN */ - { 0x05d4, 0x0634 }, /* Arabic_sheen ش ARABIC LETTER SHEEN */ - { 0x05d5, 0x0635 }, /* Arabic_sad ص ARABIC LETTER SAD */ - { 0x05d6, 0x0636 }, /* Arabic_dad ض ARABIC LETTER DAD */ - { 0x05d7, 0x0637 }, /* Arabic_tah ط ARABIC LETTER TAH */ - { 0x05d8, 0x0638 }, /* Arabic_zah ظ ARABIC LETTER ZAH */ - { 0x05d9, 0x0639 }, /* Arabic_ain ع ARABIC LETTER AIN */ - { 0x05da, 0x063a }, /* Arabic_ghain غ ARABIC LETTER GHAIN */ - { 0x05e0, 0x0640 }, /* Arabic_tatweel ـ ARABIC TATWEEL */ - { 0x05e1, 0x0641 }, /* Arabic_feh ف ARABIC LETTER FEH */ - { 0x05e2, 0x0642 }, /* Arabic_qaf ق ARABIC LETTER QAF */ - { 0x05e3, 0x0643 }, /* Arabic_kaf ك ARABIC LETTER KAF */ - { 0x05e4, 0x0644 }, /* Arabic_lam ل ARABIC LETTER LAM */ - { 0x05e5, 0x0645 }, /* Arabic_meem م ARABIC LETTER MEEM */ - { 0x05e6, 0x0646 }, /* Arabic_noon ن ARABIC LETTER NOON */ - { 0x05e7, 0x0647 }, /* Arabic_ha ه ARABIC LETTER HEH */ - { 0x05e8, 0x0648 }, /* Arabic_waw و ARABIC LETTER WAW */ - { 0x05e9, 0x0649 }, /* Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */ - { 0x05ea, 0x064a }, /* Arabic_yeh ي ARABIC LETTER YEH */ - { 0x05eb, 0x064b }, /* Arabic_fathatan ً ARABIC FATHATAN */ - { 0x05ec, 0x064c }, /* Arabic_dammatan ٌ ARABIC DAMMATAN */ - { 0x05ed, 0x064d }, /* Arabic_kasratan ٍ ARABIC KASRATAN */ - { 0x05ee, 0x064e }, /* Arabic_fatha َ ARABIC FATHA */ - { 0x05ef, 0x064f }, /* Arabic_damma ُ ARABIC DAMMA */ - { 0x05f0, 0x0650 }, /* Arabic_kasra ِ ARABIC KASRA */ - { 0x05f1, 0x0651 }, /* Arabic_shadda ّ ARABIC SHADDA */ - { 0x05f2, 0x0652 }, /* Arabic_sukun ْ ARABIC SUKUN */ - { 0x06a1, 0x0452 }, /* Serbian_dje ђ CYRILLIC SMALL LETTER DJE */ - { 0x06a2, 0x0453 }, /* Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */ - { 0x06a3, 0x0451 }, /* Cyrillic_io ё CYRILLIC SMALL LETTER IO */ - { 0x06a4, 0x0454 }, /* Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */ - { 0x06a5, 0x0455 }, /* Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */ - { 0x06a6, 0x0456 }, /* Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */ - { 0x06a7, 0x0457 }, /* Ukrainian_yi ї CYRILLIC SMALL LETTER YI */ - { 0x06a8, 0x0458 }, /* Cyrillic_je ј CYRILLIC SMALL LETTER JE */ - { 0x06a9, 0x0459 }, /* Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */ - { 0x06aa, 0x045a }, /* Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */ - { 0x06ab, 0x045b }, /* Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */ - { 0x06ac, 0x045c }, /* Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */ - { 0x06ae, 0x045e }, /* Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */ - { 0x06af, 0x045f }, /* Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */ - { 0x06b0, 0x2116 }, /* numerosign № NUMERO SIGN */ - { 0x06b1, 0x0402 }, /* Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */ - { 0x06b2, 0x0403 }, /* Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */ - { 0x06b3, 0x0401 }, /* Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */ - { 0x06b4, 0x0404 }, /* Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */ - { 0x06b5, 0x0405 }, /* Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */ - { 0x06b6, 0x0406 }, /* Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */ - { 0x06b7, 0x0407 }, /* Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */ - { 0x06b8, 0x0408 }, /* Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */ - { 0x06b9, 0x0409 }, /* Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */ - { 0x06ba, 0x040a }, /* Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */ - { 0x06bb, 0x040b }, /* Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */ - { 0x06bc, 0x040c }, /* Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */ - { 0x06be, 0x040e }, /* Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */ - { 0x06bf, 0x040f }, /* Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */ - { 0x06c0, 0x044e }, /* Cyrillic_yu ю CYRILLIC SMALL LETTER YU */ - { 0x06c1, 0x0430 }, /* Cyrillic_a а CYRILLIC SMALL LETTER A */ - { 0x06c2, 0x0431 }, /* Cyrillic_be б CYRILLIC SMALL LETTER BE */ - { 0x06c3, 0x0446 }, /* Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */ - { 0x06c4, 0x0434 }, /* Cyrillic_de д CYRILLIC SMALL LETTER DE */ - { 0x06c5, 0x0435 }, /* Cyrillic_ie е CYRILLIC SMALL LETTER IE */ - { 0x06c6, 0x0444 }, /* Cyrillic_ef ф CYRILLIC SMALL LETTER EF */ - { 0x06c7, 0x0433 }, /* Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */ - { 0x06c8, 0x0445 }, /* Cyrillic_ha х CYRILLIC SMALL LETTER HA */ - { 0x06c9, 0x0438 }, /* Cyrillic_i и CYRILLIC SMALL LETTER I */ - { 0x06ca, 0x0439 }, /* Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */ - { 0x06cb, 0x043a }, /* Cyrillic_ka к CYRILLIC SMALL LETTER KA */ - { 0x06cc, 0x043b }, /* Cyrillic_el л CYRILLIC SMALL LETTER EL */ - { 0x06cd, 0x043c }, /* Cyrillic_em м CYRILLIC SMALL LETTER EM */ - { 0x06ce, 0x043d }, /* Cyrillic_en н CYRILLIC SMALL LETTER EN */ - { 0x06cf, 0x043e }, /* Cyrillic_o о CYRILLIC SMALL LETTER O */ - { 0x06d0, 0x043f }, /* Cyrillic_pe п CYRILLIC SMALL LETTER PE */ - { 0x06d1, 0x044f }, /* Cyrillic_ya я CYRILLIC SMALL LETTER YA */ - { 0x06d2, 0x0440 }, /* Cyrillic_er р CYRILLIC SMALL LETTER ER */ - { 0x06d3, 0x0441 }, /* Cyrillic_es с CYRILLIC SMALL LETTER ES */ - { 0x06d4, 0x0442 }, /* Cyrillic_te т CYRILLIC SMALL LETTER TE */ - { 0x06d5, 0x0443 }, /* Cyrillic_u у CYRILLIC SMALL LETTER U */ - { 0x06d6, 0x0436 }, /* Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */ - { 0x06d7, 0x0432 }, /* Cyrillic_ve в CYRILLIC SMALL LETTER VE */ - { 0x06d8, 0x044c }, /* Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */ - { 0x06d9, 0x044b }, /* Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */ - { 0x06da, 0x0437 }, /* Cyrillic_ze з CYRILLIC SMALL LETTER ZE */ - { 0x06db, 0x0448 }, /* Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */ - { 0x06dc, 0x044d }, /* Cyrillic_e э CYRILLIC SMALL LETTER E */ - { 0x06dd, 0x0449 }, /* Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */ - { 0x06de, 0x0447 }, /* Cyrillic_che ч CYRILLIC SMALL LETTER CHE */ - { 0x06df, 0x044a }, /* Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */ - { 0x06e0, 0x042e }, /* Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */ - { 0x06e1, 0x0410 }, /* Cyrillic_A А CYRILLIC CAPITAL LETTER A */ - { 0x06e2, 0x0411 }, /* Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */ - { 0x06e3, 0x0426 }, /* Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */ - { 0x06e4, 0x0414 }, /* Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */ - { 0x06e5, 0x0415 }, /* Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */ - { 0x06e6, 0x0424 }, /* Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */ - { 0x06e7, 0x0413 }, /* Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */ - { 0x06e8, 0x0425 }, /* Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */ - { 0x06e9, 0x0418 }, /* Cyrillic_I И CYRILLIC CAPITAL LETTER I */ - { 0x06ea, 0x0419 }, /* Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */ - { 0x06eb, 0x041a }, /* Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */ - { 0x06ec, 0x041b }, /* Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */ - { 0x06ed, 0x041c }, /* Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */ - { 0x06ee, 0x041d }, /* Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */ - { 0x06ef, 0x041e }, /* Cyrillic_O О CYRILLIC CAPITAL LETTER O */ - { 0x06f0, 0x041f }, /* Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */ - { 0x06f1, 0x042f }, /* Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */ - { 0x06f2, 0x0420 }, /* Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */ - { 0x06f3, 0x0421 }, /* Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */ - { 0x06f4, 0x0422 }, /* Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */ - { 0x06f5, 0x0423 }, /* Cyrillic_U У CYRILLIC CAPITAL LETTER U */ - { 0x06f6, 0x0416 }, /* Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */ - { 0x06f7, 0x0412 }, /* Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */ - { 0x06f8, 0x042c }, /* Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */ - { 0x06f9, 0x042b }, /* Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */ - { 0x06fa, 0x0417 }, /* Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */ - { 0x06fb, 0x0428 }, /* Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */ - { 0x06fc, 0x042d }, /* Cyrillic_E Э CYRILLIC CAPITAL LETTER E */ - { 0x06fd, 0x0429 }, /* Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */ - { 0x06fe, 0x0427 }, /* Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */ - { 0x06ff, 0x042a }, /* Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */ - { 0x07a1, 0x0386 }, /* Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */ - { 0x07a2, 0x0388 }, /* Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */ - { 0x07a3, 0x0389 }, /* Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */ - { 0x07a4, 0x038a }, /* Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */ - { 0x07a5, 0x03aa }, /* Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ - { 0x07a7, 0x038c }, /* Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */ - { 0x07a8, 0x038e }, /* Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */ - { 0x07a9, 0x03ab }, /* Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ - { 0x07ab, 0x038f }, /* Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */ - { 0x07ae, 0x0385 }, /* Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */ - { 0x07af, 0x2015 }, /* Greek_horizbar ― HORIZONTAL BAR */ - { 0x07b1, 0x03ac }, /* Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */ - { 0x07b2, 0x03ad }, /* Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */ - { 0x07b3, 0x03ae }, /* Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */ - { 0x07b4, 0x03af }, /* Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */ - { 0x07b5, 0x03ca }, /* Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */ - { 0x07b6, 0x0390 }, /* Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ - { 0x07b7, 0x03cc }, /* Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */ - { 0x07b8, 0x03cd }, /* Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */ - { 0x07b9, 0x03cb }, /* Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ - { 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ - { 0x07bb, 0x03ce }, /* Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */ - { 0x07c1, 0x0391 }, /* Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */ - { 0x07c2, 0x0392 }, /* Greek_BETA Β GREEK CAPITAL LETTER BETA */ - { 0x07c3, 0x0393 }, /* Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */ - { 0x07c4, 0x0394 }, /* Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */ - { 0x07c5, 0x0395 }, /* Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */ - { 0x07c6, 0x0396 }, /* Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */ - { 0x07c7, 0x0397 }, /* Greek_ETA Η GREEK CAPITAL LETTER ETA */ - { 0x07c8, 0x0398 }, /* Greek_THETA Θ GREEK CAPITAL LETTER THETA */ - { 0x07c9, 0x0399 }, /* Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */ - { 0x07ca, 0x039a }, /* Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */ - { 0x07cb, 0x039b }, /* Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */ - { 0x07cc, 0x039c }, /* Greek_MU Μ GREEK CAPITAL LETTER MU */ - { 0x07cd, 0x039d }, /* Greek_NU Ν GREEK CAPITAL LETTER NU */ - { 0x07ce, 0x039e }, /* Greek_XI Ξ GREEK CAPITAL LETTER XI */ - { 0x07cf, 0x039f }, /* Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */ - { 0x07d0, 0x03a0 }, /* Greek_PI Π GREEK CAPITAL LETTER PI */ - { 0x07d1, 0x03a1 }, /* Greek_RHO Ρ GREEK CAPITAL LETTER RHO */ - { 0x07d2, 0x03a3 }, /* Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */ - { 0x07d4, 0x03a4 }, /* Greek_TAU Τ GREEK CAPITAL LETTER TAU */ - { 0x07d5, 0x03a5 }, /* Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */ - { 0x07d6, 0x03a6 }, /* Greek_PHI Φ GREEK CAPITAL LETTER PHI */ - { 0x07d7, 0x03a7 }, /* Greek_CHI Χ GREEK CAPITAL LETTER CHI */ - { 0x07d8, 0x03a8 }, /* Greek_PSI Ψ GREEK CAPITAL LETTER PSI */ - { 0x07d9, 0x03a9 }, /* Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */ - { 0x07e1, 0x03b1 }, /* Greek_alpha α GREEK SMALL LETTER ALPHA */ - { 0x07e2, 0x03b2 }, /* Greek_beta β GREEK SMALL LETTER BETA */ - { 0x07e3, 0x03b3 }, /* Greek_gamma γ GREEK SMALL LETTER GAMMA */ - { 0x07e4, 0x03b4 }, /* Greek_delta δ GREEK SMALL LETTER DELTA */ - { 0x07e5, 0x03b5 }, /* Greek_epsilon ε GREEK SMALL LETTER EPSILON */ - { 0x07e6, 0x03b6 }, /* Greek_zeta ζ GREEK SMALL LETTER ZETA */ - { 0x07e7, 0x03b7 }, /* Greek_eta η GREEK SMALL LETTER ETA */ - { 0x07e8, 0x03b8 }, /* Greek_theta θ GREEK SMALL LETTER THETA */ - { 0x07e9, 0x03b9 }, /* Greek_iota ι GREEK SMALL LETTER IOTA */ - { 0x07ea, 0x03ba }, /* Greek_kappa κ GREEK SMALL LETTER KAPPA */ - { 0x07eb, 0x03bb }, /* Greek_lambda λ GREEK SMALL LETTER LAMDA */ - { 0x07ec, 0x03bc }, /* Greek_mu μ GREEK SMALL LETTER MU */ - { 0x07ed, 0x03bd }, /* Greek_nu ν GREEK SMALL LETTER NU */ - { 0x07ee, 0x03be }, /* Greek_xi ξ GREEK SMALL LETTER XI */ - { 0x07ef, 0x03bf }, /* Greek_omicron ο GREEK SMALL LETTER OMICRON */ - { 0x07f0, 0x03c0 }, /* Greek_pi π GREEK SMALL LETTER PI */ - { 0x07f1, 0x03c1 }, /* Greek_rho ρ GREEK SMALL LETTER RHO */ - { 0x07f2, 0x03c3 }, /* Greek_sigma σ GREEK SMALL LETTER SIGMA */ - { 0x07f3, 0x03c2 }, /* Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */ - { 0x07f4, 0x03c4 }, /* Greek_tau τ GREEK SMALL LETTER TAU */ - { 0x07f5, 0x03c5 }, /* Greek_upsilon υ GREEK SMALL LETTER UPSILON */ - { 0x07f6, 0x03c6 }, /* Greek_phi φ GREEK SMALL LETTER PHI */ - { 0x07f7, 0x03c7 }, /* Greek_chi χ GREEK SMALL LETTER CHI */ - { 0x07f8, 0x03c8 }, /* Greek_psi ψ GREEK SMALL LETTER PSI */ - { 0x07f9, 0x03c9 }, /* Greek_omega ω GREEK SMALL LETTER OMEGA */ - { 0x08a1, 0x23b7 }, /* leftradical ⎷ ??? */ - { 0x08a2, 0x250c }, /* topleftradical ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */ - { 0x08a3, 0x2500 }, /* horizconnector ─ BOX DRAWINGS LIGHT HORIZONTAL */ - { 0x08a4, 0x2320 }, /* topintegral ⌠ TOP HALF INTEGRAL */ - { 0x08a5, 0x2321 }, /* botintegral ⌡ BOTTOM HALF INTEGRAL */ - { 0x08a6, 0x2502 }, /* vertconnector │ BOX DRAWINGS LIGHT VERTICAL */ - { 0x08a7, 0x23a1 }, /* topleftsqbracket ⎡ ??? */ - { 0x08a8, 0x23a3 }, /* botleftsqbracket ⎣ ??? */ - { 0x08a9, 0x23a4 }, /* toprightsqbracket ⎤ ??? */ - { 0x08aa, 0x23a6 }, /* botrightsqbracket ⎦ ??? */ - { 0x08ab, 0x239b }, /* topleftparens ⎛ ??? */ - { 0x08ac, 0x239d }, /* botleftparens ⎝ ??? */ - { 0x08ad, 0x239e }, /* toprightparens ⎞ ??? */ - { 0x08ae, 0x23a0 }, /* botrightparens ⎠ ??? */ - { 0x08af, 0x23a8 }, /* leftmiddlecurlybrace ⎨ ??? */ - { 0x08b0, 0x23ac }, /* rightmiddlecurlybrace ⎬ ??? */ - /* { 0x08b1, 0x???? }, topleftsummation ? ??? */ - /* { 0x08b2, 0x???? }, botleftsummation ? ??? */ - /* { 0x08b3, 0x???? }, topvertsummationconnector ? ??? */ - /* { 0x08b4, 0x???? }, botvertsummationconnector ? ??? */ - /* { 0x08b5, 0x???? }, toprightsummation ? ??? */ - /* { 0x08b6, 0x???? }, botrightsummation ? ??? */ - /* { 0x08b7, 0x???? }, rightmiddlesummation ? ??? */ - { 0x08bc, 0x2264 }, /* lessthanequal ≤ LESS-THAN OR EQUAL TO */ - { 0x08bd, 0x2260 }, /* notequal ≠ NOT EQUAL TO */ - { 0x08be, 0x2265 }, /* greaterthanequal ≥ GREATER-THAN OR EQUAL TO */ - { 0x08bf, 0x222b }, /* integral ∫ INTEGRAL */ - { 0x08c0, 0x2234 }, /* therefore ∴ THEREFORE */ - { 0x08c1, 0x221d }, /* variation ∝ PROPORTIONAL TO */ - { 0x08c2, 0x221e }, /* infinity ∞ INFINITY */ - { 0x08c5, 0x2207 }, /* nabla ∇ NABLA */ - { 0x08c8, 0x223c }, /* approximate ∼ TILDE OPERATOR */ - { 0x08c9, 0x2243 }, /* similarequal ≃ ASYMPTOTICALLY EQUAL TO */ - { 0x08cd, 0x21d4 }, /* ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */ - { 0x08ce, 0x21d2 }, /* implies ⇒ RIGHTWARDS DOUBLE ARROW */ - { 0x08cf, 0x2261 }, /* identical ≡ IDENTICAL TO */ - { 0x08d6, 0x221a }, /* radical √ SQUARE ROOT */ - { 0x08da, 0x2282 }, /* includedin ⊂ SUBSET OF */ - { 0x08db, 0x2283 }, /* includes ⊃ SUPERSET OF */ - { 0x08dc, 0x2229 }, /* intersection ∩ INTERSECTION */ - { 0x08dd, 0x222a }, /* union ∪ UNION */ - { 0x08de, 0x2227 }, /* logicaland ∧ LOGICAL AND */ - { 0x08df, 0x2228 }, /* logicalor ∨ LOGICAL OR */ - { 0x08ef, 0x2202 }, /* partialderivative ∂ PARTIAL DIFFERENTIAL */ - { 0x08f6, 0x0192 }, /* function ƒ LATIN SMALL LETTER F WITH HOOK */ - { 0x08fb, 0x2190 }, /* leftarrow ← LEFTWARDS ARROW */ - { 0x08fc, 0x2191 }, /* uparrow ↑ UPWARDS ARROW */ - { 0x08fd, 0x2192 }, /* rightarrow → RIGHTWARDS ARROW */ - { 0x08fe, 0x2193 }, /* downarrow ↓ DOWNWARDS ARROW */ - /* { 0x09df, 0x???? }, blank ? ??? */ - { 0x09e0, 0x25c6 }, /* soliddiamond ◆ BLACK DIAMOND */ - { 0x09e1, 0x2592 }, /* checkerboard ▒ MEDIUM SHADE */ - { 0x09e2, 0x2409 }, /* ht ␉ SYMBOL FOR HORIZONTAL TABULATION */ - { 0x09e3, 0x240c }, /* ff ␌ SYMBOL FOR FORM FEED */ - { 0x09e4, 0x240d }, /* cr ␍ SYMBOL FOR CARRIAGE RETURN */ - { 0x09e5, 0x240a }, /* lf ␊ SYMBOL FOR LINE FEED */ - { 0x09e8, 0x2424 }, /* nl ␤ SYMBOL FOR NEWLINE */ - { 0x09e9, 0x240b }, /* vt ␋ SYMBOL FOR VERTICAL TABULATION */ - { 0x09ea, 0x2518 }, /* lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */ - { 0x09eb, 0x2510 }, /* uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */ - { 0x09ec, 0x250c }, /* upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */ - { 0x09ed, 0x2514 }, /* lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */ - { 0x09ee, 0x253c }, /* crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ - { 0x09ef, 0x23ba }, /* horizlinescan1 ⎺ HORIZONTAL SCAN LINE-1 (Unicode 3.2 draft) */ - { 0x09f0, 0x23bb }, /* horizlinescan3 ⎻ HORIZONTAL SCAN LINE-3 (Unicode 3.2 draft) */ - { 0x09f1, 0x2500 }, /* horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */ - { 0x09f2, 0x23bc }, /* horizlinescan7 ⎼ HORIZONTAL SCAN LINE-7 (Unicode 3.2 draft) */ - { 0x09f3, 0x23bd }, /* horizlinescan9 ⎽ HORIZONTAL SCAN LINE-9 (Unicode 3.2 draft) */ - { 0x09f4, 0x251c }, /* leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ - { 0x09f5, 0x2524 }, /* rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */ - { 0x09f6, 0x2534 }, /* bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */ - { 0x09f7, 0x252c }, /* topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ - { 0x09f8, 0x2502 }, /* vertbar │ BOX DRAWINGS LIGHT VERTICAL */ - { 0x0aa1, 0x2003 }, /* emspace   EM SPACE */ - { 0x0aa2, 0x2002 }, /* enspace   EN SPACE */ - { 0x0aa3, 0x2004 }, /* em3space   THREE-PER-EM SPACE */ - { 0x0aa4, 0x2005 }, /* em4space   FOUR-PER-EM SPACE */ - { 0x0aa5, 0x2007 }, /* digitspace   FIGURE SPACE */ - { 0x0aa6, 0x2008 }, /* punctspace   PUNCTUATION SPACE */ - { 0x0aa7, 0x2009 }, /* thinspace   THIN SPACE */ - { 0x0aa8, 0x200a }, /* hairspace   HAIR SPACE */ - { 0x0aa9, 0x2014 }, /* emdash — EM DASH */ - { 0x0aaa, 0x2013 }, /* endash – EN DASH */ - /* { 0x0aac, 0x???? }, signifblank ? ??? */ - { 0x0aae, 0x2026 }, /* ellipsis … HORIZONTAL ELLIPSIS */ - { 0x0aaf, 0x2025 }, /* doubbaselinedot ‥ TWO DOT LEADER */ - { 0x0ab0, 0x2153 }, /* onethird ⅓ VULGAR FRACTION ONE THIRD */ - { 0x0ab1, 0x2154 }, /* twothirds ⅔ VULGAR FRACTION TWO THIRDS */ - { 0x0ab2, 0x2155 }, /* onefifth ⅕ VULGAR FRACTION ONE FIFTH */ - { 0x0ab3, 0x2156 }, /* twofifths ⅖ VULGAR FRACTION TWO FIFTHS */ - { 0x0ab4, 0x2157 }, /* threefifths ⅗ VULGAR FRACTION THREE FIFTHS */ - { 0x0ab5, 0x2158 }, /* fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */ - { 0x0ab6, 0x2159 }, /* onesixth ⅙ VULGAR FRACTION ONE SIXTH */ - { 0x0ab7, 0x215a }, /* fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */ - { 0x0ab8, 0x2105 }, /* careof ℅ CARE OF */ - { 0x0abb, 0x2012 }, /* figdash ‒ FIGURE DASH */ - { 0x0abc, 0x2329 }, /* leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */ - /* { 0x0abd, 0x???? }, decimalpoint ? ??? */ - { 0x0abe, 0x232a }, /* rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */ - /* { 0x0abf, 0x???? }, marker ? ??? */ - { 0x0ac3, 0x215b }, /* oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */ - { 0x0ac4, 0x215c }, /* threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */ - { 0x0ac5, 0x215d }, /* fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */ - { 0x0ac6, 0x215e }, /* seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */ - { 0x0ac9, 0x2122 }, /* trademark ™ TRADE MARK SIGN */ - { 0x0aca, 0x2613 }, /* signaturemark ☓ SALTIRE */ - /* { 0x0acb, 0x???? }, trademarkincircle ? ??? */ - { 0x0acc, 0x25c1 }, /* leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */ - { 0x0acd, 0x25b7 }, /* rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */ - { 0x0ace, 0x25cb }, /* emopencircle ○ WHITE CIRCLE */ - { 0x0acf, 0x25af }, /* emopenrectangle ▯ WHITE VERTICAL RECTANGLE */ - { 0x0ad0, 0x2018 }, /* leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */ - { 0x0ad1, 0x2019 }, /* rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */ - { 0x0ad2, 0x201c }, /* leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */ - { 0x0ad3, 0x201d }, /* rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */ - { 0x0ad4, 0x211e }, /* prescription ℞ PRESCRIPTION TAKE */ - { 0x0ad6, 0x2032 }, /* minutes ′ PRIME */ - { 0x0ad7, 0x2033 }, /* seconds ″ DOUBLE PRIME */ - { 0x0ad9, 0x271d }, /* latincross ✝ LATIN CROSS */ - /* { 0x0ada, 0x???? }, hexagram ? ??? */ - { 0x0adb, 0x25ac }, /* filledrectbullet ▬ BLACK RECTANGLE */ - { 0x0adc, 0x25c0 }, /* filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */ - { 0x0add, 0x25b6 }, /* filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */ - { 0x0ade, 0x25cf }, /* emfilledcircle ● BLACK CIRCLE */ - { 0x0adf, 0x25ae }, /* emfilledrect ▮ BLACK VERTICAL RECTANGLE */ - { 0x0ae0, 0x25e6 }, /* enopencircbullet ◦ WHITE BULLET */ - { 0x0ae1, 0x25ab }, /* enopensquarebullet ▫ WHITE SMALL SQUARE */ - { 0x0ae2, 0x25ad }, /* openrectbullet ▭ WHITE RECTANGLE */ - { 0x0ae3, 0x25b3 }, /* opentribulletup △ WHITE UP-POINTING TRIANGLE */ - { 0x0ae4, 0x25bd }, /* opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */ - { 0x0ae5, 0x2606 }, /* openstar ☆ WHITE STAR */ - { 0x0ae6, 0x2022 }, /* enfilledcircbullet • BULLET */ - { 0x0ae7, 0x25aa }, /* enfilledsqbullet ▪ BLACK SMALL SQUARE */ - { 0x0ae8, 0x25b2 }, /* filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */ - { 0x0ae9, 0x25bc }, /* filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */ - { 0x0aea, 0x261c }, /* leftpointer ☜ WHITE LEFT POINTING INDEX */ - { 0x0aeb, 0x261e }, /* rightpointer ☞ WHITE RIGHT POINTING INDEX */ - { 0x0aec, 0x2663 }, /* club ♣ BLACK CLUB SUIT */ - { 0x0aed, 0x2666 }, /* diamond ♦ BLACK DIAMOND SUIT */ - { 0x0aee, 0x2665 }, /* heart ♥ BLACK HEART SUIT */ - { 0x0af0, 0x2720 }, /* maltesecross ✠ MALTESE CROSS */ - { 0x0af1, 0x2020 }, /* dagger † DAGGER */ - { 0x0af2, 0x2021 }, /* doubledagger ‡ DOUBLE DAGGER */ - { 0x0af3, 0x2713 }, /* checkmark ✓ CHECK MARK */ - { 0x0af4, 0x2717 }, /* ballotcross ✗ BALLOT X */ - { 0x0af5, 0x266f }, /* musicalsharp ♯ MUSIC SHARP SIGN */ - { 0x0af6, 0x266d }, /* musicalflat ♭ MUSIC FLAT SIGN */ - { 0x0af7, 0x2642 }, /* malesymbol ♂ MALE SIGN */ - { 0x0af8, 0x2640 }, /* femalesymbol ♀ FEMALE SIGN */ - { 0x0af9, 0x260e }, /* telephone ☎ BLACK TELEPHONE */ - { 0x0afa, 0x2315 }, /* telephonerecorder ⌕ TELEPHONE RECORDER */ - { 0x0afb, 0x2117 }, /* phonographcopyright ℗ SOUND RECORDING COPYRIGHT */ - { 0x0afc, 0x2038 }, /* caret ‸ CARET */ - { 0x0afd, 0x201a }, /* singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */ - { 0x0afe, 0x201e }, /* doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */ - /* { 0x0aff, 0x???? }, cursor ? ??? */ - { 0x0ba3, 0x003c }, /* leftcaret < LESS-THAN SIGN */ - { 0x0ba6, 0x003e }, /* rightcaret > GREATER-THAN SIGN */ - { 0x0ba8, 0x2228 }, /* downcaret ∨ LOGICAL OR */ - { 0x0ba9, 0x2227 }, /* upcaret ∧ LOGICAL AND */ - { 0x0bc0, 0x00af }, /* overbar ¯ MACRON */ - { 0x0bc2, 0x22a5 }, /* downtack ⊥ UP TACK */ - { 0x0bc3, 0x2229 }, /* upshoe ∩ INTERSECTION */ - { 0x0bc4, 0x230a }, /* downstile ⌊ LEFT FLOOR */ - { 0x0bc6, 0x005f }, /* underbar _ LOW LINE */ - { 0x0bca, 0x2218 }, /* jot ∘ RING OPERATOR */ - { 0x0bcc, 0x2395 }, /* quad ⎕ APL FUNCTIONAL SYMBOL QUAD */ - { 0x0bce, 0x22a4 }, /* uptack ⊤ DOWN TACK */ - { 0x0bcf, 0x25cb }, /* circle ○ WHITE CIRCLE */ - { 0x0bd3, 0x2308 }, /* upstile ⌈ LEFT CEILING */ - { 0x0bd6, 0x222a }, /* downshoe ∪ UNION */ - { 0x0bd8, 0x2283 }, /* rightshoe ⊃ SUPERSET OF */ - { 0x0bda, 0x2282 }, /* leftshoe ⊂ SUBSET OF */ - { 0x0bdc, 0x22a2 }, /* lefttack ⊢ RIGHT TACK */ - { 0x0bfc, 0x22a3 }, /* righttack ⊣ LEFT TACK */ - { 0x0cdf, 0x2017 }, /* hebrew_doublelowline ‗ DOUBLE LOW LINE */ - { 0x0ce0, 0x05d0 }, /* hebrew_aleph א HEBREW LETTER ALEF */ - { 0x0ce1, 0x05d1 }, /* hebrew_bet ב HEBREW LETTER BET */ - { 0x0ce2, 0x05d2 }, /* hebrew_gimel ג HEBREW LETTER GIMEL */ - { 0x0ce3, 0x05d3 }, /* hebrew_dalet ד HEBREW LETTER DALET */ - { 0x0ce4, 0x05d4 }, /* hebrew_he ה HEBREW LETTER HE */ - { 0x0ce5, 0x05d5 }, /* hebrew_waw ו HEBREW LETTER VAV */ - { 0x0ce6, 0x05d6 }, /* hebrew_zain ז HEBREW LETTER ZAYIN */ - { 0x0ce7, 0x05d7 }, /* hebrew_chet ח HEBREW LETTER HET */ - { 0x0ce8, 0x05d8 }, /* hebrew_tet ט HEBREW LETTER TET */ - { 0x0ce9, 0x05d9 }, /* hebrew_yod י HEBREW LETTER YOD */ - { 0x0cea, 0x05da }, /* hebrew_finalkaph ך HEBREW LETTER FINAL KAF */ - { 0x0ceb, 0x05db }, /* hebrew_kaph כ HEBREW LETTER KAF */ - { 0x0cec, 0x05dc }, /* hebrew_lamed ל HEBREW LETTER LAMED */ - { 0x0ced, 0x05dd }, /* hebrew_finalmem ם HEBREW LETTER FINAL MEM */ - { 0x0cee, 0x05de }, /* hebrew_mem מ HEBREW LETTER MEM */ - { 0x0cef, 0x05df }, /* hebrew_finalnun ן HEBREW LETTER FINAL NUN */ - { 0x0cf0, 0x05e0 }, /* hebrew_nun נ HEBREW LETTER NUN */ - { 0x0cf1, 0x05e1 }, /* hebrew_samech ס HEBREW LETTER SAMEKH */ - { 0x0cf2, 0x05e2 }, /* hebrew_ayin ע HEBREW LETTER AYIN */ - { 0x0cf3, 0x05e3 }, /* hebrew_finalpe ף HEBREW LETTER FINAL PE */ - { 0x0cf4, 0x05e4 }, /* hebrew_pe פ HEBREW LETTER PE */ - { 0x0cf5, 0x05e5 }, /* hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */ - { 0x0cf6, 0x05e6 }, /* hebrew_zade צ HEBREW LETTER TSADI */ - { 0x0cf7, 0x05e7 }, /* hebrew_qoph ק HEBREW LETTER QOF */ - { 0x0cf8, 0x05e8 }, /* hebrew_resh ר HEBREW LETTER RESH */ - { 0x0cf9, 0x05e9 }, /* hebrew_shin ש HEBREW LETTER SHIN */ - { 0x0cfa, 0x05ea }, /* hebrew_taw ת HEBREW LETTER TAV */ - { 0x0da1, 0x0e01 }, /* Thai_kokai ก THAI CHARACTER KO KAI */ - { 0x0da2, 0x0e02 }, /* Thai_khokhai ข THAI CHARACTER KHO KHAI */ - { 0x0da3, 0x0e03 }, /* Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */ - { 0x0da4, 0x0e04 }, /* Thai_khokhwai ค THAI CHARACTER KHO KHWAI */ - { 0x0da5, 0x0e05 }, /* Thai_khokhon ฅ THAI CHARACTER KHO KHON */ - { 0x0da6, 0x0e06 }, /* Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */ - { 0x0da7, 0x0e07 }, /* Thai_ngongu ง THAI CHARACTER NGO NGU */ - { 0x0da8, 0x0e08 }, /* Thai_chochan จ THAI CHARACTER CHO CHAN */ - { 0x0da9, 0x0e09 }, /* Thai_choching ฉ THAI CHARACTER CHO CHING */ - { 0x0daa, 0x0e0a }, /* Thai_chochang ช THAI CHARACTER CHO CHANG */ - { 0x0dab, 0x0e0b }, /* Thai_soso ซ THAI CHARACTER SO SO */ - { 0x0dac, 0x0e0c }, /* Thai_chochoe ฌ THAI CHARACTER CHO CHOE */ - { 0x0dad, 0x0e0d }, /* Thai_yoying ญ THAI CHARACTER YO YING */ - { 0x0dae, 0x0e0e }, /* Thai_dochada ฎ THAI CHARACTER DO CHADA */ - { 0x0daf, 0x0e0f }, /* Thai_topatak ฏ THAI CHARACTER TO PATAK */ - { 0x0db0, 0x0e10 }, /* Thai_thothan ฐ THAI CHARACTER THO THAN */ - { 0x0db1, 0x0e11 }, /* Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */ - { 0x0db2, 0x0e12 }, /* Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */ - { 0x0db3, 0x0e13 }, /* Thai_nonen ณ THAI CHARACTER NO NEN */ - { 0x0db4, 0x0e14 }, /* Thai_dodek ด THAI CHARACTER DO DEK */ - { 0x0db5, 0x0e15 }, /* Thai_totao ต THAI CHARACTER TO TAO */ - { 0x0db6, 0x0e16 }, /* Thai_thothung ถ THAI CHARACTER THO THUNG */ - { 0x0db7, 0x0e17 }, /* Thai_thothahan ท THAI CHARACTER THO THAHAN */ - { 0x0db8, 0x0e18 }, /* Thai_thothong ธ THAI CHARACTER THO THONG */ - { 0x0db9, 0x0e19 }, /* Thai_nonu น THAI CHARACTER NO NU */ - { 0x0dba, 0x0e1a }, /* Thai_bobaimai บ THAI CHARACTER BO BAIMAI */ - { 0x0dbb, 0x0e1b }, /* Thai_popla ป THAI CHARACTER PO PLA */ - { 0x0dbc, 0x0e1c }, /* Thai_phophung ผ THAI CHARACTER PHO PHUNG */ - { 0x0dbd, 0x0e1d }, /* Thai_fofa ฝ THAI CHARACTER FO FA */ - { 0x0dbe, 0x0e1e }, /* Thai_phophan พ THAI CHARACTER PHO PHAN */ - { 0x0dbf, 0x0e1f }, /* Thai_fofan ฟ THAI CHARACTER FO FAN */ - { 0x0dc0, 0x0e20 }, /* Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */ - { 0x0dc1, 0x0e21 }, /* Thai_moma ม THAI CHARACTER MO MA */ - { 0x0dc2, 0x0e22 }, /* Thai_yoyak ย THAI CHARACTER YO YAK */ - { 0x0dc3, 0x0e23 }, /* Thai_rorua ร THAI CHARACTER RO RUA */ - { 0x0dc4, 0x0e24 }, /* Thai_ru ฤ THAI CHARACTER RU */ - { 0x0dc5, 0x0e25 }, /* Thai_loling ล THAI CHARACTER LO LING */ - { 0x0dc6, 0x0e26 }, /* Thai_lu ฦ THAI CHARACTER LU */ - { 0x0dc7, 0x0e27 }, /* Thai_wowaen ว THAI CHARACTER WO WAEN */ - { 0x0dc8, 0x0e28 }, /* Thai_sosala ศ THAI CHARACTER SO SALA */ - { 0x0dc9, 0x0e29 }, /* Thai_sorusi ษ THAI CHARACTER SO RUSI */ - { 0x0dca, 0x0e2a }, /* Thai_sosua ส THAI CHARACTER SO SUA */ - { 0x0dcb, 0x0e2b }, /* Thai_hohip ห THAI CHARACTER HO HIP */ - { 0x0dcc, 0x0e2c }, /* Thai_lochula ฬ THAI CHARACTER LO CHULA */ - { 0x0dcd, 0x0e2d }, /* Thai_oang อ THAI CHARACTER O ANG */ - { 0x0dce, 0x0e2e }, /* Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */ - { 0x0dcf, 0x0e2f }, /* Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */ - { 0x0dd0, 0x0e30 }, /* Thai_saraa ะ THAI CHARACTER SARA A */ - { 0x0dd1, 0x0e31 }, /* Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */ - { 0x0dd2, 0x0e32 }, /* Thai_saraaa า THAI CHARACTER SARA AA */ - { 0x0dd3, 0x0e33 }, /* Thai_saraam ำ THAI CHARACTER SARA AM */ - { 0x0dd4, 0x0e34 }, /* Thai_sarai ิ THAI CHARACTER SARA I */ - { 0x0dd5, 0x0e35 }, /* Thai_saraii ี THAI CHARACTER SARA II */ - { 0x0dd6, 0x0e36 }, /* Thai_saraue ึ THAI CHARACTER SARA UE */ - { 0x0dd7, 0x0e37 }, /* Thai_sarauee ื THAI CHARACTER SARA UEE */ - { 0x0dd8, 0x0e38 }, /* Thai_sarau ุ THAI CHARACTER SARA U */ - { 0x0dd9, 0x0e39 }, /* Thai_sarauu ู THAI CHARACTER SARA UU */ - { 0x0dda, 0x0e3a }, /* Thai_phinthu ฺ THAI CHARACTER PHINTHU */ - /* { 0x0dde, 0x???? }, Thai_maihanakat_maitho ? ??? */ - { 0x0ddf, 0x0e3f }, /* Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */ - { 0x0de0, 0x0e40 }, /* Thai_sarae เ THAI CHARACTER SARA E */ - { 0x0de1, 0x0e41 }, /* Thai_saraae แ THAI CHARACTER SARA AE */ - { 0x0de2, 0x0e42 }, /* Thai_sarao โ THAI CHARACTER SARA O */ - { 0x0de3, 0x0e43 }, /* Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */ - { 0x0de4, 0x0e44 }, /* Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */ - { 0x0de5, 0x0e45 }, /* Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */ - { 0x0de6, 0x0e46 }, /* Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */ - { 0x0de7, 0x0e47 }, /* Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */ - { 0x0de8, 0x0e48 }, /* Thai_maiek ่ THAI CHARACTER MAI EK */ - { 0x0de9, 0x0e49 }, /* Thai_maitho ้ THAI CHARACTER MAI THO */ - { 0x0dea, 0x0e4a }, /* Thai_maitri ๊ THAI CHARACTER MAI TRI */ - { 0x0deb, 0x0e4b }, /* Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */ - { 0x0dec, 0x0e4c }, /* Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */ - { 0x0ded, 0x0e4d }, /* Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */ - { 0x0df0, 0x0e50 }, /* Thai_leksun ๐ THAI DIGIT ZERO */ - { 0x0df1, 0x0e51 }, /* Thai_leknung ๑ THAI DIGIT ONE */ - { 0x0df2, 0x0e52 }, /* Thai_leksong ๒ THAI DIGIT TWO */ - { 0x0df3, 0x0e53 }, /* Thai_leksam ๓ THAI DIGIT THREE */ - { 0x0df4, 0x0e54 }, /* Thai_leksi ๔ THAI DIGIT FOUR */ - { 0x0df5, 0x0e55 }, /* Thai_lekha ๕ THAI DIGIT FIVE */ - { 0x0df6, 0x0e56 }, /* Thai_lekhok ๖ THAI DIGIT SIX */ - { 0x0df7, 0x0e57 }, /* Thai_lekchet ๗ THAI DIGIT SEVEN */ - { 0x0df8, 0x0e58 }, /* Thai_lekpaet ๘ THAI DIGIT EIGHT */ - { 0x0df9, 0x0e59 }, /* Thai_lekkao ๙ THAI DIGIT NINE */ - { 0x0ea1, 0x3131 }, /* Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */ - { 0x0ea2, 0x3132 }, /* Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */ - { 0x0ea3, 0x3133 }, /* Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */ - { 0x0ea4, 0x3134 }, /* Hangul_Nieun ㄴ HANGUL LETTER NIEUN */ - { 0x0ea5, 0x3135 }, /* Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */ - { 0x0ea6, 0x3136 }, /* Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */ - { 0x0ea7, 0x3137 }, /* Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */ - { 0x0ea8, 0x3138 }, /* Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */ - { 0x0ea9, 0x3139 }, /* Hangul_Rieul ㄹ HANGUL LETTER RIEUL */ - { 0x0eaa, 0x313a }, /* Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */ - { 0x0eab, 0x313b }, /* Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */ - { 0x0eac, 0x313c }, /* Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */ - { 0x0ead, 0x313d }, /* Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */ - { 0x0eae, 0x313e }, /* Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */ - { 0x0eaf, 0x313f }, /* Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */ - { 0x0eb0, 0x3140 }, /* Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */ - { 0x0eb1, 0x3141 }, /* Hangul_Mieum ㅁ HANGUL LETTER MIEUM */ - { 0x0eb2, 0x3142 }, /* Hangul_Pieub ㅂ HANGUL LETTER PIEUP */ - { 0x0eb3, 0x3143 }, /* Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */ - { 0x0eb4, 0x3144 }, /* Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */ - { 0x0eb5, 0x3145 }, /* Hangul_Sios ㅅ HANGUL LETTER SIOS */ - { 0x0eb6, 0x3146 }, /* Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */ - { 0x0eb7, 0x3147 }, /* Hangul_Ieung ㅇ HANGUL LETTER IEUNG */ - { 0x0eb8, 0x3148 }, /* Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */ - { 0x0eb9, 0x3149 }, /* Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */ - { 0x0eba, 0x314a }, /* Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */ - { 0x0ebb, 0x314b }, /* Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */ - { 0x0ebc, 0x314c }, /* Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */ - { 0x0ebd, 0x314d }, /* Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */ - { 0x0ebe, 0x314e }, /* Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */ - { 0x0ebf, 0x314f }, /* Hangul_A ㅏ HANGUL LETTER A */ - { 0x0ec0, 0x3150 }, /* Hangul_AE ㅐ HANGUL LETTER AE */ - { 0x0ec1, 0x3151 }, /* Hangul_YA ㅑ HANGUL LETTER YA */ - { 0x0ec2, 0x3152 }, /* Hangul_YAE ㅒ HANGUL LETTER YAE */ - { 0x0ec3, 0x3153 }, /* Hangul_EO ㅓ HANGUL LETTER EO */ - { 0x0ec4, 0x3154 }, /* Hangul_E ㅔ HANGUL LETTER E */ - { 0x0ec5, 0x3155 }, /* Hangul_YEO ㅕ HANGUL LETTER YEO */ - { 0x0ec6, 0x3156 }, /* Hangul_YE ㅖ HANGUL LETTER YE */ - { 0x0ec7, 0x3157 }, /* Hangul_O ㅗ HANGUL LETTER O */ - { 0x0ec8, 0x3158 }, /* Hangul_WA ㅘ HANGUL LETTER WA */ - { 0x0ec9, 0x3159 }, /* Hangul_WAE ㅙ HANGUL LETTER WAE */ - { 0x0eca, 0x315a }, /* Hangul_OE ㅚ HANGUL LETTER OE */ - { 0x0ecb, 0x315b }, /* Hangul_YO ㅛ HANGUL LETTER YO */ - { 0x0ecc, 0x315c }, /* Hangul_U ㅜ HANGUL LETTER U */ - { 0x0ecd, 0x315d }, /* Hangul_WEO ㅝ HANGUL LETTER WEO */ - { 0x0ece, 0x315e }, /* Hangul_WE ㅞ HANGUL LETTER WE */ - { 0x0ecf, 0x315f }, /* Hangul_WI ㅟ HANGUL LETTER WI */ - { 0x0ed0, 0x3160 }, /* Hangul_YU ㅠ HANGUL LETTER YU */ - { 0x0ed1, 0x3161 }, /* Hangul_EU ㅡ HANGUL LETTER EU */ - { 0x0ed2, 0x3162 }, /* Hangul_YI ㅢ HANGUL LETTER YI */ - { 0x0ed3, 0x3163 }, /* Hangul_I ㅣ HANGUL LETTER I */ - { 0x0ed4, 0x11a8 }, /* Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */ - { 0x0ed5, 0x11a9 }, /* Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */ - { 0x0ed6, 0x11aa }, /* Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */ - { 0x0ed7, 0x11ab }, /* Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */ - { 0x0ed8, 0x11ac }, /* Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */ - { 0x0ed9, 0x11ad }, /* Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */ - { 0x0eda, 0x11ae }, /* Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */ - { 0x0edb, 0x11af }, /* Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */ - { 0x0edc, 0x11b0 }, /* Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */ - { 0x0edd, 0x11b1 }, /* Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */ - { 0x0ede, 0x11b2 }, /* Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */ - { 0x0edf, 0x11b3 }, /* Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */ - { 0x0ee0, 0x11b4 }, /* Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */ - { 0x0ee1, 0x11b5 }, /* Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */ - { 0x0ee2, 0x11b6 }, /* Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */ - { 0x0ee3, 0x11b7 }, /* Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */ - { 0x0ee4, 0x11b8 }, /* Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */ - { 0x0ee5, 0x11b9 }, /* Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */ - { 0x0ee6, 0x11ba }, /* Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */ - { 0x0ee7, 0x11bb }, /* Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */ - { 0x0ee8, 0x11bc }, /* Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */ - { 0x0ee9, 0x11bd }, /* Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */ - { 0x0eea, 0x11be }, /* Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */ - { 0x0eeb, 0x11bf }, /* Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */ - { 0x0eec, 0x11c0 }, /* Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */ - { 0x0eed, 0x11c1 }, /* Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */ - { 0x0eee, 0x11c2 }, /* Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */ - { 0x0eef, 0x316d }, /* Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */ - { 0x0ef0, 0x3171 }, /* Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */ - { 0x0ef1, 0x3178 }, /* Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */ - { 0x0ef2, 0x317f }, /* Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */ - { 0x0ef3, 0x3181 }, /* Hangul_KkogjiDalrinIeung ㆁ HANGUL LETTER YESIEUNG */ - { 0x0ef4, 0x3184 }, /* Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */ - { 0x0ef5, 0x3186 }, /* Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */ - { 0x0ef6, 0x318d }, /* Hangul_AraeA ㆍ HANGUL LETTER ARAEA */ - { 0x0ef7, 0x318e }, /* Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */ - { 0x0ef8, 0x11eb }, /* Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */ - { 0x0ef9, 0x11f0 }, /* Hangul_J_KkogjiDalrinIeung ᇰ HANGUL JONGSEONG YESIEUNG */ - { 0x0efa, 0x11f9 }, /* Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */ - { 0x0eff, 0x20a9 }, /* Korean_Won ₩ WON SIGN */ - { 0x13a4, 0x20ac }, /* Euro € EURO SIGN */ - { 0x13bc, 0x0152 }, /* OE Œ LATIN CAPITAL LIGATURE OE */ - { 0x13bd, 0x0153 }, /* oe œ LATIN SMALL LIGATURE OE */ - { 0x13be, 0x0178 }, /* Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */ - { 0x20ac, 0x20ac }, /* EuroSign € EURO SIGN */ -}; - - -static unsigned int ImGui_ImplScreen_KeySymToUnicode(unsigned int keysym) -{ - // Latin-1 keysyms map directly to Unicode. - if ((keysym >= 0x0020u && keysym <= 0x007eu) || - (keysym >= 0x00a0u && keysym <= 0x00ffu)) - { - return keysym; - } - - // X11-style directly encoded UCS keysyms use 0x01000000 | codepoint. - if ((keysym & 0xff000000u) == 0x01000000u) - { - const unsigned int codepoint = keysym & 0x00ffffffu; - return codepoint <= IM_UNICODE_CODEPOINT_MAX ? codepoint : 0u; - } - - int min = 0; - int max = (int)(sizeof(ImGui_ImplScreen_KeySymTable) / sizeof(ImGui_ImplScreen_KeySymTable[0])) - 1; - while (max >= min) - { - const int mid = min + (max - min) / 2; - if (ImGui_ImplScreen_KeySymTable[mid].keysym < keysym) - { - min = mid + 1; - } - else if (ImGui_ImplScreen_KeySymTable[mid].keysym > keysym) - { - max = mid - 1; - } - else - { - return ImGui_ImplScreen_KeySymTable[mid].ucs; - } - } - - return 0u; -} diff --git a/docs/BACKENDS.md b/docs/BACKENDS.md index 2d237c1d6..3bf1445e9 100644 --- a/docs/BACKENDS.md +++ b/docs/BACKENDS.md @@ -79,7 +79,7 @@ List of Platforms Backends: imgui_impl_osx.mm ; macOS native API (not as feature complete as glfw/sdl backends) imgui_impl_sdl2.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org imgui_impl_sdl3.cpp ; SDL3 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org - imgui_impl_screen.cpp ; Screen (QNX) + imgui_impl_qnx.cpp ; QNX Screen imgui_impl_win32.cpp ; Win32 native API (Windows) imgui_impl_glut.cpp ; GLUT/FreeGLUT (this is prehistoric software and absolutely not recommended today!) diff --git a/docs/EXAMPLES.md b/docs/EXAMPLES.md index 914642c01..89e9bd0df 100644 --- a/docs/EXAMPLES.md +++ b/docs/EXAMPLES.md @@ -117,14 +117,14 @@ Because this application doesn't create a window nor a graphic context, there's Please note that imgui_impl_null itself is a rather empty backend. We provide it for consistency but it is similarly easy to create a skeleton application without the null backend. -[example_screen_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_screen_opengl3/)
+[example_qnx_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_qnx_opengl3/)
QNX Screen + OpenGL ES 3 example.
-= main.cpp + imgui_impl_screen.cpp + imgui_impl_opengl3.cpp
+= main.cpp + imgui_impl_qnx.cpp + imgui_impl_opengl3.cpp
Uses the QNX recursive make build system and compiles the OpenGL3 renderer with `IMGUI_IMPL_OPENGL_ES3`. -[example_screen_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_screen_vulkan/)
+[example_qnx_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_qnx_vulkan/)
QNX Screen + Vulkan example using `VK_QNX_screen_surface`.
-= main.cpp + imgui_impl_screen.cpp + imgui_impl_vulkan.cpp
+= main.cpp + imgui_impl_qnx.cpp + imgui_impl_vulkan.cpp
Uses the QNX recursive make build system and the Vulkan backend's example helper structures. [example_sdl2_directx11/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_directx11/)
diff --git a/examples/example_qnx_opengl3/.gitignore b/examples/example_qnx_opengl3/.gitignore new file mode 100644 index 000000000..12b50871c --- /dev/null +++ b/examples/example_qnx_opengl3/.gitignore @@ -0,0 +1,19 @@ +# ignore all files +* + +# unignore all dirs +!/**/ + +# unignore all with extensions +!*.* + +# unignore makefiles +!Makefile + +# re-ignore qnx build artefacts +*.o +*.so* +*.a +*.pinfo +*.dep +*.gcno diff --git a/examples/example_screen_opengl3/Makefile b/examples/example_qnx_opengl3/Makefile similarity index 100% rename from examples/example_screen_opengl3/Makefile rename to examples/example_qnx_opengl3/Makefile diff --git a/examples/example_screen_opengl3/README.md b/examples/example_qnx_opengl3/README.md similarity index 73% rename from examples/example_screen_opengl3/README.md rename to examples/example_qnx_opengl3/README.md index d1cad4756..2fd97d6d3 100644 --- a/examples/example_screen_opengl3/README.md +++ b/examples/example_qnx_opengl3/README.md @@ -2,7 +2,7 @@ This example uses: -- `imgui_impl_screen.cpp` as the QNX Screen platform backend +- `imgui_impl_qnx.cpp` as the QNX Screen platform backend - `imgui_impl_opengl3.cpp` as the renderer backend - EGL to create an OpenGL ES 3 context and Screen window surface @@ -15,15 +15,15 @@ No separate Screen/OpenGL renderer backend is required. Load the QNX SDP environment, then run: ```sh -cd examples/example_screen_opengl3 +cd examples/example_qnx_opengl3 make ``` The QNX recursive make files build for the CPUs enabled in your SDP -configuration and install the program as `example_screen_opengl3`. +configuration and install the program as `example_qnx_opengl3`. ## Input The application polls its `screen_context_t` event queue and forwards every -non-`SCREEN_EVENT_NONE` event to `ImGui_ImplScreen_ProcessEvent()`. +non-`SCREEN_EVENT_NONE` event to `ImGui_ImplQNX_ProcessEvent()`. Escape exits the example. diff --git a/examples/example_screen_opengl3/common.mk b/examples/example_qnx_opengl3/common.mk similarity index 92% rename from examples/example_screen_opengl3/common.mk rename to examples/example_qnx_opengl3/common.mk index 4083879ca..d162d684e 100644 --- a/examples/example_screen_opengl3/common.mk +++ b/examples/example_qnx_opengl3/common.mk @@ -3,7 +3,7 @@ QCONFIG=qconfig.mk endif include $(QCONFIG) -NAME=example_screen_opengl3 +NAME=example_qnx_opengl3 SRCS = \ main.cpp \ @@ -12,7 +12,7 @@ SRCS = \ imgui_draw.cpp \ imgui_tables.cpp \ imgui_widgets.cpp \ - imgui_impl_screen.cpp \ + imgui_impl_qnx.cpp \ imgui_impl_opengl3.cpp EXTRA_SRCVPATH += $(PROJECT_ROOT)/../.. $(PROJECT_ROOT)/../../backends diff --git a/examples/example_screen_opengl3/example_screen_opengl3.use b/examples/example_qnx_opengl3/example_qnx_opengl3.use similarity index 87% rename from examples/example_screen_opengl3/example_screen_opengl3.use rename to examples/example_qnx_opengl3/example_qnx_opengl3.use index 75c844897..6361d35cc 100644 --- a/examples/example_screen_opengl3/example_screen_opengl3.use +++ b/examples/example_qnx_opengl3/example_qnx_opengl3.use @@ -1,6 +1,6 @@ Dear ImGui QNX Screen + OpenGL ES 3 example -Usage: example_screen_opengl3 +Usage: example_qnx_opengl3 The example uses the fullscreen size reported by QNX Screen, displays the Dear ImGui demo UI, and exits when Escape is pressed or the Screen window receives a close event. diff --git a/examples/example_qnx_opengl3/main.cpp b/examples/example_qnx_opengl3/main.cpp new file mode 100644 index 000000000..76cc3a866 --- /dev/null +++ b/examples/example_qnx_opengl3/main.cpp @@ -0,0 +1,299 @@ +// Dear ImGui: standalone example application for QNX Screen + OpenGL ES 3 + +// Learn about Dear ImGui: +// - FAQ https://dearimgui.com/faq +// - Getting Started https://dearimgui.com/getting-started +// - Documentation https://dearimgui.com/docs (same as your local docs/ folder). +// - Introduction, links and more at the top of imgui.cpp + +#include "imgui.h" +#include "imgui_impl_qnx.h" +#include "imgui_impl_opengl3.h" +#include // printf, fprintf +#include +#include +#include +#include +#include +#include + +#ifndef EGL_OPENGL_ES3_BIT +#ifdef EGL_OPENGL_ES3_BIT_KHR +#define EGL_OPENGL_ES3_BIT EGL_OPENGL_ES3_BIT_KHR +#else +#define EGL_OPENGL_ES3_BIT 0x0040 +#endif +#endif + +struct QNXWindow +{ + screen_context_t Context = nullptr; + screen_window_t Window = nullptr; + screen_event_t Event = nullptr; + EGLDisplay Display = EGL_NO_DISPLAY; + EGLContext GLContext = EGL_NO_CONTEXT; + EGLSurface GLSurface = EGL_NO_SURFACE; + int Size[2] = {}; +}; + +static bool CreateQNXWindow(QNXWindow* window) +{ + if (screen_create_context(&window->Context, 0) != 0 || + screen_create_window(&window->Window, window->Context) != 0 || + screen_create_event(&window->Event) != 0) + { + fprintf(stderr, "QNX Screen initialization failed: %s\n", strerror(errno)); + return false; + } + + // A newly created QNX Screen window reports the fullscreen dimensions. + if (screen_get_window_property_iv(window->Window, SCREEN_PROPERTY_SIZE, window->Size) != 0 || window->Size[0] <= 0 || window->Size[1] <= 0) + { + fprintf(stderr, "Failed to obtain QNX Screen window size: %s\n", strerror(errno)); + return false; + } + + const int usage = SCREEN_USAGE_OPENGL_ES2 | SCREEN_USAGE_OPENGL_ES3 | SCREEN_USAGE_NATIVE; + const int transparency = SCREEN_TRANSPARENCY_NONE; + const int swap_interval = 1; + if (screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_USAGE, &usage) != 0 || + screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_SIZE, window->Size) != 0 || + screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_TRANSPARENCY, &transparency) != 0 || + screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_SWAP_INTERVAL, &swap_interval) != 0) + { + fprintf(stderr, "Failed to configure QNX Screen window: %s\n", strerror(errno)); + return false; + } + + window->Display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (window->Display == EGL_NO_DISPLAY || eglInitialize(window->Display, nullptr, nullptr) != EGL_TRUE || eglBindAPI(EGL_OPENGL_ES_API) != EGL_TRUE) + { + fprintf(stderr, "EGL initialization failed: 0x%04x\n", eglGetError()); + return false; + } + + const EGLint config_attributes[] = + { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_DEPTH_SIZE, 24, + EGL_STENCIL_SIZE, 8, + EGL_NONE + }; + EGLConfig config = nullptr; + EGLint config_count = 0; + if (eglChooseConfig(window->Display, config_attributes, &config, 1, &config_count) != EGL_TRUE || config_count == 0) + { + fprintf(stderr, "eglChooseConfig() failed: 0x%04x\n", eglGetError()); + return false; + } + + EGLint native_visual = 0; + if (eglGetConfigAttrib(window->Display, config, EGL_NATIVE_VISUAL_ID, &native_visual) != EGL_TRUE || + screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_FORMAT, &native_visual) != 0 || + screen_create_window_buffers(window->Window, 2) != 0) + { + fprintf(stderr, "Failed to create QNX Screen buffers: %s\n", strerror(errno)); + return false; + } + + const EGLint context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE }; + window->GLContext = eglCreateContext(window->Display, config, EGL_NO_CONTEXT, context_attributes); + window->GLSurface = eglCreateWindowSurface(window->Display, config, window->Window, nullptr); + if (window->GLContext == EGL_NO_CONTEXT || window->GLSurface == EGL_NO_SURFACE || + eglMakeCurrent(window->Display, window->GLSurface, window->GLSurface, window->GLContext) != EGL_TRUE || + eglSwapInterval(window->Display, 1) != EGL_TRUE) + { + fprintf(stderr, "EGL context creation failed: 0x%04x\n", eglGetError()); + return false; + } + + const int visible = 1; + if (screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_VISIBLE, &visible) != 0) + { + fprintf(stderr, "Failed to show QNX Screen window: %s\n", strerror(errno)); + return false; + } + return true; +} + +static void DestroyQNXWindow(QNXWindow* window) +{ + if (window->Display != EGL_NO_DISPLAY) + { + eglMakeCurrent(window->Display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (window->GLSurface != EGL_NO_SURFACE) + eglDestroySurface(window->Display, window->GLSurface); + if (window->GLContext != EGL_NO_CONTEXT) + eglDestroyContext(window->Display, window->GLContext); + eglTerminate(window->Display); + } + if (window->Event != nullptr) + screen_destroy_event(window->Event); + if (window->Window != nullptr) + screen_destroy_window(window->Window); + if (window->Context != nullptr) + screen_destroy_context(window->Context); +} + +static bool ProcessQNXEvents(QNXWindow* window) +{ + for (;;) + { + if (screen_get_event(window->Context, window->Event, 0) != 0) + return false; + + int type = SCREEN_EVENT_NONE; + if (screen_get_event_property_iv(window->Event, SCREEN_PROPERTY_TYPE, &type) != 0) + return false; + if (type == SCREEN_EVENT_NONE) + return true; + + ImGui_ImplQNX_ProcessEvent(window->Event); + if (type == SCREEN_EVENT_CLOSE) + return false; + if (type == SCREEN_EVENT_KEYBOARD) + { + int flags = 0; + int key_cap = 0; + if (screen_get_event_property_iv(window->Event, SCREEN_PROPERTY_FLAGS, &flags) == 0 && + screen_get_event_property_iv(window->Event, SCREEN_PROPERTY_KEY_CAP, &key_cap) == 0 && + (flags & SCREEN_FLAG_KEY_DOWN) != 0 && key_cap == KEYCODE_ESCAPE) + return false; + } + } +} + +// Main code +int main(int, char**) +{ + // Setup QNX Screen and EGL + QNXWindow window; + if (!CreateQNXWindow(&window)) + { + DestroyQNXWindow(&window); + return 1; + } + + // GL ES 3.0 + GLSL 300 es + const char* glsl_version = "#version 300 es"; + float main_scale = 1.0f; + + // Setup Dear ImGui context + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); (void)io; + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + + // Setup Dear ImGui style + ImGui::StyleColorsDark(); + //ImGui::StyleColorsLight(); + + // Setup scaling + ImGuiStyle& style = ImGui::GetStyle(); + style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again) + style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor) + + // Setup Platform/Renderer backends + ImGui_ImplQNX_Init(window.Context, window.Window); + ImGui_ImplOpenGL3_Init(glsl_version); + + // Load Fonts + // - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap(). + // This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold. + // - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit). + // - Read 'docs/FONTS.md' for more instructions and details. + // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! + //style.FontSizeBase = 20.0f; + //io.Fonts->AddFontDefaultVector(); + //io.Fonts->AddFontDefaultBitmap(); + //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf"); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf"); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf"); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf"); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf"); + //IM_ASSERT(font != nullptr); + + // Our state + bool show_demo_window = true; + bool show_another_window = false; + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); + + // Main loop + bool done = false; + while (!done) + { + // Poll and handle events (inputs, window resize, etc.) + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. + if (!ProcessQNXEvents(&window)) + done = true; + + // Start the Dear ImGui frame + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplQNX_NewFrame(); + ImGui::NewFrame(); + + // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). + if (show_demo_window) + ImGui::ShowDemoWindow(&show_demo_window); + + // 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window. + { + static float f = 0.0f; + static int counter = 0; + + ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. + + ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); + ImGui::End(); + } + + // 3. Show another simple window. + if (show_another_window) + { + ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) + ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; + ImGui::End(); + } + + // Rendering + ImGui::Render(); + glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); + glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w); + glClear(GL_COLOR_BUFFER_BIT); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + eglSwapBuffers(window.Display, window.GLSurface); + } + + // Cleanup + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplQNX_Shutdown(); + ImGui::DestroyContext(); + + DestroyQNXWindow(&window); + + return 0; +} diff --git a/examples/example_screen_opengl3/nto/Makefile b/examples/example_qnx_opengl3/nto/Makefile similarity index 100% rename from examples/example_screen_opengl3/nto/Makefile rename to examples/example_qnx_opengl3/nto/Makefile diff --git a/examples/example_screen_opengl3/nto/aarch64/Makefile b/examples/example_qnx_opengl3/nto/aarch64/Makefile similarity index 100% rename from examples/example_screen_opengl3/nto/aarch64/Makefile rename to examples/example_qnx_opengl3/nto/aarch64/Makefile diff --git a/examples/example_screen_opengl3/nto/aarch64/o.le/Makefile b/examples/example_qnx_opengl3/nto/aarch64/o.le/Makefile similarity index 100% rename from examples/example_screen_opengl3/nto/aarch64/o.le/Makefile rename to examples/example_qnx_opengl3/nto/aarch64/o.le/Makefile diff --git a/examples/example_screen_opengl3/nto/x86_64/Makefile b/examples/example_qnx_opengl3/nto/x86_64/Makefile similarity index 100% rename from examples/example_screen_opengl3/nto/x86_64/Makefile rename to examples/example_qnx_opengl3/nto/x86_64/Makefile diff --git a/examples/example_screen_opengl3/nto/x86_64/o/Makefile b/examples/example_qnx_opengl3/nto/x86_64/o/Makefile similarity index 100% rename from examples/example_screen_opengl3/nto/x86_64/o/Makefile rename to examples/example_qnx_opengl3/nto/x86_64/o/Makefile diff --git a/examples/example_qnx_vulkan/.gitignore b/examples/example_qnx_vulkan/.gitignore new file mode 100644 index 000000000..12b50871c --- /dev/null +++ b/examples/example_qnx_vulkan/.gitignore @@ -0,0 +1,19 @@ +# ignore all files +* + +# unignore all dirs +!/**/ + +# unignore all with extensions +!*.* + +# unignore makefiles +!Makefile + +# re-ignore qnx build artefacts +*.o +*.so* +*.a +*.pinfo +*.dep +*.gcno diff --git a/examples/example_screen_vulkan/Makefile b/examples/example_qnx_vulkan/Makefile similarity index 100% rename from examples/example_screen_vulkan/Makefile rename to examples/example_qnx_vulkan/Makefile diff --git a/examples/example_screen_vulkan/README.md b/examples/example_qnx_vulkan/README.md similarity index 79% rename from examples/example_screen_vulkan/README.md rename to examples/example_qnx_vulkan/README.md index 501fe7451..13eba6f6f 100644 --- a/examples/example_screen_vulkan/README.md +++ b/examples/example_qnx_vulkan/README.md @@ -2,7 +2,7 @@ This example uses: -- `imgui_impl_screen.cpp` as the QNX Screen platform backend +- `imgui_impl_qnx.cpp` as the QNX Screen platform backend - the unmodified `imgui_impl_vulkan.cpp` renderer backend - `vkCreateScreenSurfaceQNX()` and `VK_QNX_screen_surface` @@ -15,7 +15,7 @@ surface creation. Load the QNX SDP environment, then run: ```sh -cd examples/example_screen_vulkan +cd examples/example_qnx_vulkan make ``` @@ -24,6 +24,6 @@ The build defines `VK_USE_PLATFORM_SCREEN_QNX` and links `libvulkan` and ## Input and resize -The application forwards Screen input events to `ImGui_ImplScreen_ProcessEvent()`. +The application forwards Screen input events to `ImGui_ImplQNX_ProcessEvent()`. It recreates the Vulkan swapchain when the Screen window size changes or Vulkan reports `VK_ERROR_OUT_OF_DATE_KHR` / `VK_SUBOPTIMAL_KHR`. Escape exits. diff --git a/examples/example_screen_vulkan/common.mk b/examples/example_qnx_vulkan/common.mk similarity index 92% rename from examples/example_screen_vulkan/common.mk rename to examples/example_qnx_vulkan/common.mk index a5f309311..7d99539aa 100644 --- a/examples/example_screen_vulkan/common.mk +++ b/examples/example_qnx_vulkan/common.mk @@ -3,7 +3,7 @@ QCONFIG=qconfig.mk endif include $(QCONFIG) -NAME=example_screen_vulkan +NAME=example_qnx_vulkan SRCS = \ main.cpp \ @@ -12,7 +12,7 @@ SRCS = \ imgui_draw.cpp \ imgui_tables.cpp \ imgui_widgets.cpp \ - imgui_impl_screen.cpp \ + imgui_impl_qnx.cpp \ imgui_impl_vulkan.cpp EXTRA_SRCVPATH += $(PROJECT_ROOT)/../.. $(PROJECT_ROOT)/../../backends diff --git a/examples/example_screen_vulkan/example_screen_vulkan.use b/examples/example_qnx_vulkan/example_qnx_vulkan.use similarity index 89% rename from examples/example_screen_vulkan/example_screen_vulkan.use rename to examples/example_qnx_vulkan/example_qnx_vulkan.use index 619e3d4fa..893eb5c41 100644 --- a/examples/example_screen_vulkan/example_screen_vulkan.use +++ b/examples/example_qnx_vulkan/example_qnx_vulkan.use @@ -1,6 +1,6 @@ Dear ImGui QNX Screen + Vulkan example -Usage: example_screen_vulkan +Usage: example_qnx_vulkan The example uses the fullscreen size reported by QNX Screen, creates a VK_QNX_screen_surface swapchain, displays the Dear ImGui demo UI, and exits when Escape is pressed diff --git a/examples/example_qnx_vulkan/main.cpp b/examples/example_qnx_vulkan/main.cpp new file mode 100644 index 000000000..ae309ad15 --- /dev/null +++ b/examples/example_qnx_vulkan/main.cpp @@ -0,0 +1,626 @@ +// Dear ImGui: standalone example application for QNX Screen + Vulkan + +// Learn about Dear ImGui: +// - FAQ https://dearimgui.com/faq +// - Getting Started https://dearimgui.com/getting-started +// - Documentation https://dearimgui.com/docs (same as your local docs/ folder). +// - Introduction, links and more at the top of imgui.cpp + +// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app. +// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h. +// You will use those if you want to use this rendering backend in your engine/app. +// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by +// the backend itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code. +// Read comments in imgui_impl_vulkan.h. + +#ifndef VK_USE_PLATFORM_SCREEN_QNX +#define VK_USE_PLATFORM_SCREEN_QNX +#endif +#include "imgui.h" +#include "imgui_impl_qnx.h" +#include "imgui_impl_vulkan.h" +#include // printf, fprintf +#include // abort +#include +#include +#include +#include +#include + +// Volk headers +#ifdef IMGUI_IMPL_VULKAN_USE_VOLK +#define VOLK_IMPLEMENTATION +#include +#endif + +//#define APP_USE_UNLIMITED_FRAME_RATE +#ifdef _DEBUG +#define APP_USE_VULKAN_DEBUG_REPORT +static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE; +#endif + +// Data +static VkAllocationCallbacks* g_Allocator = nullptr; +static VkInstance g_Instance = VK_NULL_HANDLE; +static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE; +static VkDevice g_Device = VK_NULL_HANDLE; +static uint32_t g_QueueFamily = (uint32_t)-1; +static VkQueue g_Queue = VK_NULL_HANDLE; +static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; +static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; + +static ImGui_ImplVulkanH_Window g_MainWindowData; +static uint32_t g_MinImageCount = 2; +static bool g_SwapChainRebuild = false; + +static void check_vk_result(VkResult err) +{ + if (err == VK_SUCCESS) + return; + fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err); + if (err < 0) + abort(); +} + +#ifdef APP_USE_VULKAN_DEBUG_REPORT +static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData) +{ + (void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguments + fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage); + return VK_FALSE; +} +#endif // APP_USE_VULKAN_DEBUG_REPORT + +static bool IsExtensionAvailable(const ImVector& properties, const char* extension) +{ + for (const VkExtensionProperties& p : properties) + if (strcmp(p.extensionName, extension) == 0) + return true; + return false; +} + +static void SetupVulkan(ImVector instance_extensions) +{ + VkResult err; +#ifdef IMGUI_IMPL_VULKAN_USE_VOLK + volkInitialize(); +#endif + + // Create Vulkan Instance + { + VkInstanceCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + + // Enumerate available extensions + uint32_t properties_count; + ImVector properties; + vkEnumerateInstanceExtensionProperties(nullptr, &properties_count, nullptr); + properties.resize(properties_count); + err = vkEnumerateInstanceExtensionProperties(nullptr, &properties_count, properties.Data); + check_vk_result(err); + + // Enable required extensions + if (IsExtensionAvailable(properties, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) + instance_extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); +#ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME + if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME)) + { + instance_extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); + create_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + } +#endif + + // Enabling validation layers +#ifdef APP_USE_VULKAN_DEBUG_REPORT + const char* layers[] = { "VK_LAYER_KHRONOS_validation" }; + create_info.enabledLayerCount = 1; + create_info.ppEnabledLayerNames = layers; + instance_extensions.push_back("VK_EXT_debug_report"); +#endif + + // Create Vulkan Instance + create_info.enabledExtensionCount = (uint32_t)instance_extensions.Size; + create_info.ppEnabledExtensionNames = instance_extensions.Data; + err = vkCreateInstance(&create_info, g_Allocator, &g_Instance); + check_vk_result(err); +#ifdef IMGUI_IMPL_VULKAN_USE_VOLK + volkLoadInstance(g_Instance); +#endif + + // Setup the debug report callback +#ifdef APP_USE_VULKAN_DEBUG_REPORT + auto f_vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT"); + IM_ASSERT(f_vkCreateDebugReportCallbackEXT != nullptr); + VkDebugReportCallbackCreateInfoEXT debug_report_ci = {}; + debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; + debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; + debug_report_ci.pfnCallback = debug_report; + debug_report_ci.pUserData = nullptr; + err = f_vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport); + check_vk_result(err); +#endif + } + + // Select Physical Device (GPU) + g_PhysicalDevice = ImGui_ImplVulkanH_SelectPhysicalDevice(g_Instance); + IM_ASSERT(g_PhysicalDevice != VK_NULL_HANDLE); + + // Select graphics queue family + g_QueueFamily = ImGui_ImplVulkanH_SelectQueueFamilyIndex(g_PhysicalDevice); + IM_ASSERT(g_QueueFamily != (uint32_t)-1); + + // Create Logical Device (with 1 queue) + { + ImVector device_extensions; + device_extensions.push_back("VK_KHR_swapchain"); + + // Enumerate physical device extension + uint32_t properties_count; + ImVector properties; + vkEnumerateDeviceExtensionProperties(g_PhysicalDevice, nullptr, &properties_count, nullptr); + properties.resize(properties_count); + vkEnumerateDeviceExtensionProperties(g_PhysicalDevice, nullptr, &properties_count, properties.Data); +#ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME + if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) + device_extensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME); +#endif + + const float queue_priority[] = { 1.0f }; + VkDeviceQueueCreateInfo queue_info[1] = {}; + queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_info[0].queueFamilyIndex = g_QueueFamily; + queue_info[0].queueCount = 1; + queue_info[0].pQueuePriorities = queue_priority; + VkDeviceCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + create_info.queueCreateInfoCount = sizeof(queue_info) / sizeof(queue_info[0]); + create_info.pQueueCreateInfos = queue_info; + create_info.enabledExtensionCount = (uint32_t)device_extensions.Size; + create_info.ppEnabledExtensionNames = device_extensions.Data; + err = vkCreateDevice(g_PhysicalDevice, &create_info, g_Allocator, &g_Device); + check_vk_result(err); + vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue); + } + + // Create Descriptor Pool + // If you wish to load e.g. additional textures you may need to alter pools sizes and maxSets. + { + VkDescriptorPoolSize pool_sizes[] = + { + { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE }, + { VK_DESCRIPTOR_TYPE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE }, + }; + VkDescriptorPoolCreateInfo pool_info = {}; + pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; + pool_info.maxSets = 0; + for (VkDescriptorPoolSize& pool_size : pool_sizes) + pool_info.maxSets += pool_size.descriptorCount; + pool_info.poolSizeCount = (uint32_t)IM_COUNTOF(pool_sizes); + pool_info.pPoolSizes = pool_sizes; + err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool); + check_vk_result(err); + } +} + +// All the ImGui_ImplVulkanH_XXX structures/functions are optional helpers used by the demo. +// Your real engine/app may not use them. +static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height) +{ + // Check for WSI support + VkBool32 res; + vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, surface, &res); + if (res != VK_TRUE) + { + fprintf(stderr, "Error no WSI support on physical device 0\n"); + exit(-1); + } + + // Select Surface Format + const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM }; + const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; + wd->Surface = surface; + wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_COUNTOF(requestSurfaceImageFormat), requestSurfaceColorSpace); + + // Select Present Mode +#ifdef APP_USE_UNLIMITED_FRAME_RATE + VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR }; +#else + VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR }; +#endif + wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_COUNTOF(present_modes)); + //printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode); + + // Create SwapChain, RenderPass, Framebuffer, etc. + IM_ASSERT(g_MinImageCount >= 2); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, 0); +} + +static void CleanupVulkan() +{ + vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator); + +#ifdef APP_USE_VULKAN_DEBUG_REPORT + // Remove the debug report callback + auto f_vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT"); + f_vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator); +#endif // APP_USE_VULKAN_DEBUG_REPORT + + vkDestroyDevice(g_Device, g_Allocator); + vkDestroyInstance(g_Instance, g_Allocator); +} + +static void CleanupVulkanWindow(ImGui_ImplVulkanH_Window* wd) +{ + ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, wd, g_Allocator); + vkDestroySurfaceKHR(g_Instance, wd->Surface, g_Allocator); +} + +static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data) +{ + VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore; + VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore; + VkResult err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex); + if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) + g_SwapChainRebuild = true; + if (err == VK_ERROR_OUT_OF_DATE_KHR) + return; + if (err != VK_SUBOPTIMAL_KHR) + check_vk_result(err); + + ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex]; + { + err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking + check_vk_result(err); + + err = vkResetFences(g_Device, 1, &fd->Fence); + check_vk_result(err); + } + { + err = vkResetCommandPool(g_Device, fd->CommandPool, 0); + check_vk_result(err); + VkCommandBufferBeginInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + err = vkBeginCommandBuffer(fd->CommandBuffer, &info); + check_vk_result(err); + } + { + VkRenderPassBeginInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + info.renderPass = wd->RenderPass; + info.framebuffer = fd->Framebuffer; + info.renderArea.extent.width = wd->Width; + info.renderArea.extent.height = wd->Height; + info.clearValueCount = 1; + info.pClearValues = &wd->ClearValue; + vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE); + } + + // Record dear imgui primitives into command buffer + ImGui_ImplVulkan_RenderDrawData(draw_data, fd->CommandBuffer); + + // Submit command buffer + vkCmdEndRenderPass(fd->CommandBuffer); + { + VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkSubmitInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + info.waitSemaphoreCount = 1; + info.pWaitSemaphores = &image_acquired_semaphore; + info.pWaitDstStageMask = &wait_stage; + info.commandBufferCount = 1; + info.pCommandBuffers = &fd->CommandBuffer; + info.signalSemaphoreCount = 1; + info.pSignalSemaphores = &render_complete_semaphore; + + err = vkEndCommandBuffer(fd->CommandBuffer); + check_vk_result(err); + err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence); + check_vk_result(err); + } +} + +static void FramePresent(ImGui_ImplVulkanH_Window* wd) +{ + if (g_SwapChainRebuild) + return; + VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore; + VkPresentInfoKHR info = {}; + info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + info.waitSemaphoreCount = 1; + info.pWaitSemaphores = &render_complete_semaphore; + info.swapchainCount = 1; + info.pSwapchains = &wd->Swapchain; + info.pImageIndices = &wd->FrameIndex; + VkResult err = vkQueuePresentKHR(g_Queue, &info); + if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) + g_SwapChainRebuild = true; + if (err == VK_ERROR_OUT_OF_DATE_KHR) + return; + if (err != VK_SUBOPTIMAL_KHR) + check_vk_result(err); + wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores +} + + +struct QNXWindow +{ + screen_context_t Context = nullptr; + screen_window_t Window = nullptr; + screen_event_t Event = nullptr; + int Size[2] = {}; +}; + +static bool CreateQNXWindow(QNXWindow* window) +{ + if (screen_create_context(&window->Context, 0) != 0 || + screen_create_window(&window->Window, window->Context) != 0 || + screen_create_event(&window->Event) != 0) + { + fprintf(stderr, "QNX Screen initialization failed: %s\n", strerror(errno)); + return false; + } + + // A newly created QNX Screen window reports the fullscreen dimensions. + if (screen_get_window_property_iv(window->Window, SCREEN_PROPERTY_SIZE, window->Size) != 0 || window->Size[0] <= 0 || window->Size[1] <= 0) + { + fprintf(stderr, "Failed to obtain QNX Screen window size: %s\n", strerror(errno)); + return false; + } + + const int usage = SCREEN_USAGE_VULKAN | SCREEN_USAGE_NATIVE; + const int transparency = SCREEN_TRANSPARENCY_NONE; + if (screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_USAGE, &usage) != 0 || + screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_SIZE, window->Size) != 0 || + screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_TRANSPARENCY, &transparency) != 0) + { + fprintf(stderr, "Failed to configure QNX Screen window: %s\n", strerror(errno)); + return false; + } + return true; +} + +static void DestroyQNXWindow(QNXWindow* window) +{ + if (window->Event != nullptr) + screen_destroy_event(window->Event); + if (window->Window != nullptr) + screen_destroy_window(window->Window); + if (window->Context != nullptr) + screen_destroy_context(window->Context); +} + +static bool ProcessQNXEvents(QNXWindow* window) +{ + for (;;) + { + if (screen_get_event(window->Context, window->Event, 0) != 0) + return false; + + int type = SCREEN_EVENT_NONE; + if (screen_get_event_property_iv(window->Event, SCREEN_PROPERTY_TYPE, &type) != 0) + return false; + if (type == SCREEN_EVENT_NONE) + return true; + + ImGui_ImplQNX_ProcessEvent(window->Event); + if (type == SCREEN_EVENT_CLOSE) + return false; + if (type == SCREEN_EVENT_KEYBOARD) + { + int flags = 0; + int key_cap = 0; + if (screen_get_event_property_iv(window->Event, SCREEN_PROPERTY_FLAGS, &flags) == 0 && + screen_get_event_property_iv(window->Event, SCREEN_PROPERTY_KEY_CAP, &key_cap) == 0 && + (flags & SCREEN_FLAG_KEY_DOWN) != 0 && key_cap == KEYCODE_ESCAPE) + return false; + } + } +} + +static void QNXSleep(int milliseconds) +{ + struct timespec request = { milliseconds / 1000, (milliseconds % 1000) * 1000000L }; + nanosleep(&request, nullptr); +} + +// Main code +int main(int, char**) +{ + // Create window with Vulkan graphics context + QNXWindow window; + if (!CreateQNXWindow(&window)) + { + DestroyQNXWindow(&window); + return 1; + } + float main_scale = 1.0f; + + ImVector extensions; + extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); + extensions.push_back(VK_QNX_SCREEN_SURFACE_EXTENSION_NAME); + SetupVulkan(extensions); + + // Create Window Surface + VkScreenSurfaceCreateInfoQNX surface_create_info = {}; + surface_create_info.sType = VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX; + surface_create_info.context = window.Context; + surface_create_info.window = window.Window; + VkSurfaceKHR surface; + VkResult err = vkCreateScreenSurfaceQNX(g_Instance, &surface_create_info, g_Allocator, &surface); + check_vk_result(err); + + // Create Framebuffers + int w = window.Size[0]; + int h = window.Size[1]; + ImGui_ImplVulkanH_Window* wd = &g_MainWindowData; + SetupVulkanWindow(wd, surface, w, h); + + const int visible = 1; + if (screen_set_window_property_iv(window.Window, SCREEN_PROPERTY_VISIBLE, &visible) != 0) + { + fprintf(stderr, "Failed to show QNX Screen window: %s\n", strerror(errno)); + return 1; + } + + // Setup Dear ImGui context + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); (void)io; + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + + // Setup Dear ImGui style + ImGui::StyleColorsDark(); + //ImGui::StyleColorsLight(); + + // Setup scaling + ImGuiStyle& style = ImGui::GetStyle(); + style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again) + style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor) + + // Setup Platform/Renderer backends + ImGui_ImplQNX_Init(window.Context, window.Window); + ImGui_ImplVulkan_InitInfo init_info = {}; + //init_info.ApiVersion = VK_API_VERSION_1_3; // Pass in your value of VkApplicationInfo::apiVersion, otherwise will default to header version. + init_info.Instance = g_Instance; + init_info.PhysicalDevice = g_PhysicalDevice; + init_info.Device = g_Device; + init_info.QueueFamily = g_QueueFamily; + init_info.Queue = g_Queue; + init_info.PipelineCache = g_PipelineCache; + init_info.DescriptorPool = g_DescriptorPool; + init_info.MinImageCount = g_MinImageCount; + init_info.ImageCount = wd->ImageCount; + init_info.Allocator = g_Allocator; + init_info.PipelineInfoMain.RenderPass = wd->RenderPass; + init_info.PipelineInfoMain.Subpass = 0; + init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT; + init_info.CheckVkResultFn = check_vk_result; + ImGui_ImplVulkan_Init(&init_info); + + // Load Fonts + // - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap(). + // This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold. + // - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit). + // - Read 'docs/FONTS.md' for more instructions and details. + // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! + //style.FontSizeBase = 20.0f; + //io.Fonts->AddFontDefaultVector(); + //io.Fonts->AddFontDefaultBitmap(); + //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf"); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf"); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf"); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf"); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf"); + //IM_ASSERT(font != nullptr); + + // Our state + bool show_demo_window = true; + bool show_another_window = false; + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); + + // Main loop + bool done = false; + while (!done) + { + // Poll and handle events (inputs, window resize, etc.) + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. + if (!ProcessQNXEvents(&window)) + done = true; + + // Resize swap chain? + int framebuffer_size[2] = {}; + if (screen_get_window_property_iv(window.Window, SCREEN_PROPERTY_SIZE, framebuffer_size) != 0) + done = true; + int fb_width = framebuffer_size[0]; + int fb_height = framebuffer_size[1]; + if (fb_width <= 0 || fb_height <= 0) + { + QNXSleep(10); + continue; + } + if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height)) + { + ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, 0); + g_MainWindowData.FrameIndex = 0; + g_SwapChainRebuild = false; + } + + // Start the Dear ImGui frame + ImGui_ImplVulkan_NewFrame(); + ImGui_ImplQNX_NewFrame(); + ImGui::NewFrame(); + + // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). + if (show_demo_window) + ImGui::ShowDemoWindow(&show_demo_window); + + // 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window. + { + static float f = 0.0f; + static int counter = 0; + + ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. + + ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); + ImGui::End(); + } + + // 3. Show another simple window. + if (show_another_window) + { + ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) + ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; + ImGui::End(); + } + + // Rendering + ImGui::Render(); + ImDrawData* draw_data = ImGui::GetDrawData(); + const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f); + if (!is_minimized) + { + wd->ClearValue.color.float32[0] = clear_color.x * clear_color.w; + wd->ClearValue.color.float32[1] = clear_color.y * clear_color.w; + wd->ClearValue.color.float32[2] = clear_color.z * clear_color.w; + wd->ClearValue.color.float32[3] = clear_color.w; + FrameRender(wd, draw_data); + FramePresent(wd); + } + } + + // Cleanup + err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + ImGui_ImplVulkan_Shutdown(); + ImGui_ImplQNX_Shutdown(); + ImGui::DestroyContext(); + + CleanupVulkanWindow(&g_MainWindowData); + CleanupVulkan(); + + DestroyQNXWindow(&window); + + return 0; +} diff --git a/examples/example_screen_vulkan/nto/Makefile b/examples/example_qnx_vulkan/nto/Makefile similarity index 100% rename from examples/example_screen_vulkan/nto/Makefile rename to examples/example_qnx_vulkan/nto/Makefile diff --git a/examples/example_screen_vulkan/nto/aarch64/Makefile b/examples/example_qnx_vulkan/nto/aarch64/Makefile similarity index 100% rename from examples/example_screen_vulkan/nto/aarch64/Makefile rename to examples/example_qnx_vulkan/nto/aarch64/Makefile diff --git a/examples/example_screen_vulkan/nto/aarch64/o.le/Makefile b/examples/example_qnx_vulkan/nto/aarch64/o.le/Makefile similarity index 100% rename from examples/example_screen_vulkan/nto/aarch64/o.le/Makefile rename to examples/example_qnx_vulkan/nto/aarch64/o.le/Makefile diff --git a/examples/example_screen_vulkan/nto/x86_64/Makefile b/examples/example_qnx_vulkan/nto/x86_64/Makefile similarity index 100% rename from examples/example_screen_vulkan/nto/x86_64/Makefile rename to examples/example_qnx_vulkan/nto/x86_64/Makefile diff --git a/examples/example_screen_vulkan/nto/x86_64/o/Makefile b/examples/example_qnx_vulkan/nto/x86_64/o/Makefile similarity index 100% rename from examples/example_screen_vulkan/nto/x86_64/o/Makefile rename to examples/example_qnx_vulkan/nto/x86_64/o/Makefile diff --git a/examples/example_screen_opengl3/main.cpp b/examples/example_screen_opengl3/main.cpp deleted file mode 100644 index b197e0e4d..000000000 --- a/examples/example_screen_opengl3/main.cpp +++ /dev/null @@ -1,388 +0,0 @@ -// Dear ImGui: standalone example application for QNX Screen + OpenGL ES 3 - -// Learn about Dear ImGui: -// - FAQ https://dearimgui.com/faq -// - Getting Started https://dearimgui.com/getting-started -// - Documentation https://dearimgui.com/docs (same as your local docs/ folder). -// - Introduction, links and more at the top of imgui.cpp - -#include "imgui.h" -#include "imgui_impl_opengl3.h" -#include "imgui_impl_screen.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef EGL_OPENGL_ES3_BIT -#ifdef EGL_OPENGL_ES3_BIT_KHR -#define EGL_OPENGL_ES3_BIT EGL_OPENGL_ES3_BIT_KHR -#else -#define EGL_OPENGL_ES3_BIT 0x0040 -#endif -#endif - -struct AppWindow -{ - screen_context_t ScreenContext; - screen_window_t ScreenWindow; - screen_event_t ScreenEvent; - EGLDisplay EglDisplay; - EGLConfig EglConfig; - EGLContext EglContext; - EGLSurface EglSurface; - int WindowSize[2]; - - AppWindow() - { - memset(this, 0, sizeof(*this)); - EglDisplay = EGL_NO_DISPLAY; - EglContext = EGL_NO_CONTEXT; - EglSurface = EGL_NO_SURFACE; - } -}; - -static void PrintEglError(const char* operation) -{ - fprintf(stderr, "%s failed: EGL error 0x%04x\n", operation, eglGetError()); -} - -static bool CreateScreenWindow(AppWindow* app) -{ - if (screen_create_context(&app->ScreenContext, 0) != 0) - { - fprintf(stderr, "screen_create_context() failed: %s\n", strerror(errno)); - return false; - } - if (screen_create_window(&app->ScreenWindow, app->ScreenContext) != 0) - { - fprintf(stderr, "screen_create_window() failed: %s\n", strerror(errno)); - return false; - } - if (screen_create_event(&app->ScreenEvent) != 0) - { - fprintf(stderr, "screen_create_event() failed: %s\n", strerror(errno)); - return false; - } - if (screen_get_window_property_iv(app->ScreenWindow, SCREEN_PROPERTY_SIZE, app->WindowSize) != 0) - { - fprintf(stderr, "screen_get_window_property_iv(SCREEN_PROPERTY_SIZE) failed: %s\n", strerror(errno)); - return false; - } - if (app->WindowSize[0] <= 0 || app->WindowSize[1] <= 0) - { - fprintf(stderr, "screen_get_window_property_iv(SCREEN_PROPERTY_SIZE) returned invalid size %dx%d\n", - app->WindowSize[0], app->WindowSize[1]); - return false; - } - - const char* id = "dear-imgui-screen-opengl3"; - (void)screen_set_window_property_cv(app->ScreenWindow, SCREEN_PROPERTY_ID_STRING, (int)strlen(id) + 1, id); - - const int usage = SCREEN_USAGE_OPENGL_ES2 | SCREEN_USAGE_OPENGL_ES3 | SCREEN_USAGE_NATIVE; - const int transparency = SCREEN_TRANSPARENCY_NONE; - const int swap_interval = 1; - if (screen_set_window_property_iv(app->ScreenWindow, SCREEN_PROPERTY_USAGE, &usage) != 0 || - screen_set_window_property_iv(app->ScreenWindow, SCREEN_PROPERTY_SIZE, app->WindowSize) != 0 || - screen_set_window_property_iv(app->ScreenWindow, SCREEN_PROPERTY_TRANSPARENCY, &transparency) != 0 || - screen_set_window_property_iv(app->ScreenWindow, SCREEN_PROPERTY_SWAP_INTERVAL, &swap_interval) != 0) - { - fprintf(stderr, "Failed to configure QNX Screen window: %s\n", strerror(errno)); - return false; - } - return true; -} - -static bool CreateEglContext(AppWindow* app) -{ - app->EglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (app->EglDisplay == EGL_NO_DISPLAY) - { - PrintEglError("eglGetDisplay()"); - return false; - } - if (eglInitialize(app->EglDisplay, nullptr, nullptr) != EGL_TRUE) - { - PrintEglError("eglInitialize()"); - return false; - } - if (eglBindAPI(EGL_OPENGL_ES_API) != EGL_TRUE) - { - PrintEglError("eglBindAPI()"); - return false; - } - - const EGLint config_attributes[] = - { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_DEPTH_SIZE, 0, - EGL_STENCIL_SIZE, 0, - EGL_NONE - }; - EGLint config_count = 0; - if (eglChooseConfig(app->EglDisplay, config_attributes, &app->EglConfig, 1, &config_count) != EGL_TRUE || config_count < 1) - { - PrintEglError("eglChooseConfig()"); - return false; - } - - EGLint native_visual = 0; - if (eglGetConfigAttrib(app->EglDisplay, app->EglConfig, EGL_NATIVE_VISUAL_ID, &native_visual) != EGL_TRUE) - { - PrintEglError("eglGetConfigAttrib(EGL_NATIVE_VISUAL_ID)"); - return false; - } - if (screen_set_window_property_iv(app->ScreenWindow, SCREEN_PROPERTY_FORMAT, &native_visual) != 0) - { - fprintf(stderr, "screen_set_window_property_iv(SCREEN_PROPERTY_FORMAT) failed: %s\n", strerror(errno)); - return false; - } - - const EGLint context_attributes[] = - { - EGL_CONTEXT_CLIENT_VERSION, 3, - EGL_NONE - }; - app->EglContext = eglCreateContext(app->EglDisplay, app->EglConfig, EGL_NO_CONTEXT, context_attributes); - if (app->EglContext == EGL_NO_CONTEXT) - { - PrintEglError("eglCreateContext()"); - return false; - } - - if (screen_create_window_buffers(app->ScreenWindow, 2) != 0) - { - fprintf(stderr, "screen_create_window_buffers() failed: %s\n", strerror(errno)); - return false; - } - - app->EglSurface = eglCreateWindowSurface(app->EglDisplay, app->EglConfig, app->ScreenWindow, nullptr); - if (app->EglSurface == EGL_NO_SURFACE) - { - PrintEglError("eglCreateWindowSurface()"); - return false; - } - if (eglMakeCurrent(app->EglDisplay, app->EglSurface, app->EglSurface, app->EglContext) != EGL_TRUE) - { - PrintEglError("eglMakeCurrent()"); - return false; - } - if (eglSwapInterval(app->EglDisplay, 1) != EGL_TRUE) - { - PrintEglError("eglSwapInterval()"); - return false; - } - - const int visible = 1; - if (screen_set_window_property_iv(app->ScreenWindow, SCREEN_PROPERTY_VISIBLE, &visible) != 0) - { - fprintf(stderr, "screen_set_window_property_iv(SCREEN_PROPERTY_VISIBLE) failed: %s\n", strerror(errno)); - return false; - } - return true; -} - -static bool IsExitEvent(screen_event_t event) -{ - int type = SCREEN_EVENT_NONE; - if (screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &type) != 0) - { - return false; - } - if (type == SCREEN_EVENT_KEYBOARD) - { - int flags = 0; - int symbol = 0; - if (screen_get_event_property_iv(event, SCREEN_PROPERTY_FLAGS, &flags) == 0 && - screen_get_event_property_iv(event, SCREEN_PROPERTY_SYM, &symbol) == 0 && - (flags & KEY_DOWN) != 0 && symbol == KEYCODE_ESCAPE) - { - return true; - } - } - if (type == SCREEN_EVENT_CLOSE) - { - return true; - } - return false; -} - -static bool ProcessScreenEvents(AppWindow* app) -{ - for (;;) - { - if (screen_get_event(app->ScreenContext, app->ScreenEvent, 0) != 0) - { - fprintf(stderr, "screen_get_event() failed: %s\n", strerror(errno)); - return false; - } - - int type = SCREEN_EVENT_NONE; - if (screen_get_event_property_iv(app->ScreenEvent, SCREEN_PROPERTY_TYPE, &type) != 0) - { - fprintf(stderr, "screen_get_event_property_iv(SCREEN_PROPERTY_TYPE) failed: %s\n", strerror(errno)); - return false; - } - if (type == SCREEN_EVENT_NONE) - { - break; - } - if (IsExitEvent(app->ScreenEvent)) - { - return false; - } - ImGui_ImplScreen_ProcessEvent(app->ScreenEvent); - } - return true; -} - -static void DestroyAppWindow(AppWindow* app) -{ - if (app->EglDisplay != EGL_NO_DISPLAY) - { - (void)eglMakeCurrent(app->EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (app->EglSurface != EGL_NO_SURFACE) - { - eglDestroySurface(app->EglDisplay, app->EglSurface); - } - if (app->EglContext != EGL_NO_CONTEXT) - { - eglDestroyContext(app->EglDisplay, app->EglContext); - } - eglTerminate(app->EglDisplay); - } - if (app->ScreenEvent != nullptr) - { - screen_destroy_event(app->ScreenEvent); - } - if (app->ScreenWindow != nullptr) - { - screen_destroy_window(app->ScreenWindow); - } - if (app->ScreenContext != nullptr) - { - screen_destroy_context(app->ScreenContext); - } -} - -int main(int, char**) -{ - AppWindow app; - if (!CreateScreenWindow(&app) || !CreateEglContext(&app)) - { - DestroyAppWindow(&app); - return EXIT_FAILURE; - } - - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); - io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; - - ImGui::StyleColorsDark(); - - const bool screen_backend_initialized = ImGui_ImplScreen_Init(app.ScreenContext, app.ScreenWindow); - const bool renderer_backend_initialized = screen_backend_initialized && ImGui_ImplOpenGL3_Init("#version 300 es"); - if (!screen_backend_initialized || !renderer_backend_initialized) - { - fprintf(stderr, "Failed to initialize Dear ImGui backends.\n"); - if (renderer_backend_initialized) - { - ImGui_ImplOpenGL3_Shutdown(); - } - if (screen_backend_initialized) - { - ImGui_ImplScreen_Shutdown(); - } - ImGui::DestroyContext(); - DestroyAppWindow(&app); - return EXIT_FAILURE; - } - - bool show_demo_window = true; - bool show_another_window = false; - ImVec4 clear_color = ImVec4(0.10f, 0.12f, 0.15f, 1.00f); - bool running = true; - while (running) - { - running = ProcessScreenEvents(&app); - if (!running) - { - break; - } - - ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplScreen_NewFrame(); - ImGui::NewFrame(); - - if (show_demo_window) - { - ImGui::ShowDemoWindow(&show_demo_window); - } - - static float value = 0.0f; - static int counter = 0; - static char text[128] = "Keyboard input is handled by QNX Screen"; - ImGui::Begin("QNX Screen + OpenGL ES 3"); - ImGui::Text("Renderer: %s", (const char*)glGetString(GL_RENDERER)); - ImGui::Checkbox("Demo Window", &show_demo_window); - ImGui::Checkbox("Another Window", &show_another_window); - ImGui::SliderFloat("float", &value, 0.0f, 1.0f); - ImGui::ColorEdit3("clear color", (float*)&clear_color); - ImGui::InputText("text", text, IM_ARRAYSIZE(text)); - if (ImGui::Button("Button")) - { - counter++; - } - ImGui::SameLine(); - ImGui::Text("counter = %d", counter); - ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); - ImGui::TextUnformatted("Press Esc to exit."); - ImGui::End(); - - if (show_another_window) - { - ImGui::Begin("Another Window", &show_another_window); - ImGui::TextUnformatted("Hello from QNX Screen!"); - if (ImGui::Button("Close Me")) - { - show_another_window = false; - } - ImGui::End(); - } - - ImGui::Render(); - EGLint framebuffer_width = 0; - EGLint framebuffer_height = 0; - eglQuerySurface(app.EglDisplay, app.EglSurface, EGL_WIDTH, &framebuffer_width); - eglQuerySurface(app.EglDisplay, app.EglSurface, EGL_HEIGHT, &framebuffer_height); - if (framebuffer_width > 0 && framebuffer_height > 0) - { - glViewport(0, 0, framebuffer_width, framebuffer_height); - glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w); - glClear(GL_COLOR_BUFFER_BIT); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - if (eglSwapBuffers(app.EglDisplay, app.EglSurface) != EGL_TRUE) - { - PrintEglError("eglSwapBuffers()"); - running = false; - } - } - } - - ImGui_ImplOpenGL3_Shutdown(); - ImGui_ImplScreen_Shutdown(); - ImGui::DestroyContext(); - DestroyAppWindow(&app); - return EXIT_SUCCESS; -} diff --git a/examples/example_screen_vulkan/main.cpp b/examples/example_screen_vulkan/main.cpp deleted file mode 100644 index 6fe69b9ba..000000000 --- a/examples/example_screen_vulkan/main.cpp +++ /dev/null @@ -1,745 +0,0 @@ -// Dear ImGui: standalone example application for QNX Screen + Vulkan - -// Important note to the reader who wishes to integrate imgui_impl_vulkan.cpp/.h in their own engine/app. -// - Common ImGui_ImplVulkan_XXX functions and structures interface with the renderer backend. -// - ImGui_ImplVulkanH_XXX helpers are used by examples and are not intended as an engine abstraction. - -#include "imgui.h" -#include "imgui_impl_screen.h" -#include "imgui_impl_vulkan.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -struct ScreenApp -{ - screen_context_t Context; - screen_window_t Window; - screen_event_t Event; - int WindowSize[2]; - - ScreenApp() - { - memset(this, 0, sizeof(*this)); - } -}; - -static VkAllocationCallbacks* g_Allocator = nullptr; -static VkInstance g_Instance = VK_NULL_HANDLE; -static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE; -static VkDevice g_Device = VK_NULL_HANDLE; -static uint32_t g_QueueFamily = UINT32_MAX; -static VkQueue g_Queue = VK_NULL_HANDLE; -static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; -static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; -static ImGui_ImplVulkanH_Window g_MainWindowData; -static uint32_t g_MinImageCount = 2; -static bool g_SwapChainRebuild = false; - -static void CheckVkResult(VkResult result) -{ - if (result == VK_SUCCESS) - { - return; - } - fprintf(stderr, "[vulkan] VkResult = %d\n", result); - if (result < 0) - { - abort(); - } -} - -static bool IsExtensionAvailable(const ImVector& properties, const char* name) -{ - for (const VkExtensionProperties& property : properties) - { - if (strcmp(property.extensionName, name) == 0) - { - return true; - } - } - return false; -} - -static bool CreateScreenWindow(ScreenApp* app) -{ - if (screen_create_context(&app->Context, 0) != 0) - { - fprintf(stderr, "screen_create_context() failed: %s\n", strerror(errno)); - return false; - } - if (screen_create_window(&app->Window, app->Context) != 0) - { - fprintf(stderr, "screen_create_window() failed: %s\n", strerror(errno)); - return false; - } - if (screen_create_event(&app->Event) != 0) - { - fprintf(stderr, "screen_create_event() failed: %s\n", strerror(errno)); - return false; - } - if (screen_get_window_property_iv(app->Window, SCREEN_PROPERTY_SIZE, app->WindowSize) != 0) - { - fprintf(stderr, "screen_get_window_property_iv(SCREEN_PROPERTY_SIZE) failed: %s\n", strerror(errno)); - return false; - } - if (app->WindowSize[0] <= 0 || app->WindowSize[1] <= 0) - { - fprintf(stderr, "screen_get_window_property_iv(SCREEN_PROPERTY_SIZE) returned invalid size %dx%d\n", - app->WindowSize[0], app->WindowSize[1]); - return false; - } - - const int usage = SCREEN_USAGE_VULKAN | SCREEN_USAGE_NATIVE; - const int transparency = SCREEN_TRANSPARENCY_NONE; - const char* id = "dear-imgui-screen-vulkan"; - (void)screen_set_window_property_cv(app->Window, SCREEN_PROPERTY_ID_STRING, (int)strlen(id) + 1, id); - if (screen_set_window_property_iv(app->Window, SCREEN_PROPERTY_USAGE, &usage) != 0 || - screen_set_window_property_iv(app->Window, SCREEN_PROPERTY_SIZE, app->WindowSize) != 0 || - screen_set_window_property_iv(app->Window, SCREEN_PROPERTY_TRANSPARENCY, &transparency) != 0) - { - fprintf(stderr, "Failed to configure QNX Screen window: %s\n", strerror(errno)); - return false; - } - return true; -} - -static bool CreateVulkanInstance() -{ - uint32_t extension_count = 0; - VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr); - if (result != VK_SUCCESS) - { - CheckVkResult(result); - return false; - } - - ImVector available_extensions; - available_extensions.resize(extension_count); - result = vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, available_extensions.Data); - if (result != VK_SUCCESS) - { - CheckVkResult(result); - return false; - } - - const char* required_extensions[] = - { - VK_KHR_SURFACE_EXTENSION_NAME, - VK_QNX_SCREEN_SURFACE_EXTENSION_NAME - }; - for (const char* extension : required_extensions) - { - if (!IsExtensionAvailable(available_extensions, extension)) - { - fprintf(stderr, "Required Vulkan instance extension is unavailable: %s\n", extension); - return false; - } - } - - VkApplicationInfo application_info = {}; - application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - application_info.pApplicationName = "Dear ImGui QNX Screen Vulkan example"; - application_info.applicationVersion = VK_MAKE_VERSION(1, 0, 0); - application_info.pEngineName = "None"; - application_info.engineVersion = VK_MAKE_VERSION(1, 0, 0); - application_info.apiVersion = VK_API_VERSION_1_0; - - VkInstanceCreateInfo create_info = {}; - create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - create_info.pApplicationInfo = &application_info; - create_info.enabledExtensionCount = IM_COUNTOF(required_extensions); - create_info.ppEnabledExtensionNames = required_extensions; - result = vkCreateInstance(&create_info, g_Allocator, &g_Instance); - if (result != VK_SUCCESS) - { - CheckVkResult(result); - return false; - } - return true; -} - -static bool CreateVulkanSurface(const ScreenApp* app, VkSurfaceKHR* surface) -{ - VkScreenSurfaceCreateInfoQNX create_info = {}; - create_info.sType = VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX; - create_info.context = app->Context; - create_info.window = app->Window; - const VkResult result = vkCreateScreenSurfaceQNX(g_Instance, &create_info, g_Allocator, surface); - if (result != VK_SUCCESS) - { - CheckVkResult(result); - return false; - } - return true; -} - -static int PhysicalDeviceScore(VkPhysicalDevice device) -{ - VkPhysicalDeviceProperties properties = {}; - vkGetPhysicalDeviceProperties(device, &properties); - switch (properties.deviceType) - { - case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: return 500; - case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: return 400; - case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: return 300; - case VK_PHYSICAL_DEVICE_TYPE_CPU: return 100; - default: return 200; - } -} - -static bool SelectPhysicalDeviceAndQueue(VkSurfaceKHR surface) -{ - uint32_t device_count = 0; - VkResult result = vkEnumeratePhysicalDevices(g_Instance, &device_count, nullptr); - if (result != VK_SUCCESS || device_count == 0) - { - CheckVkResult(result); - fprintf(stderr, "No Vulkan physical device is available.\n"); - return false; - } - - ImVector devices; - devices.resize(device_count); - result = vkEnumeratePhysicalDevices(g_Instance, &device_count, devices.Data); - if (result != VK_SUCCESS) - { - CheckVkResult(result); - return false; - } - - int best_score = -1; - for (VkPhysicalDevice device : devices) - { - uint32_t queue_count = 0; - vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_count, nullptr); - ImVector queues; - queues.resize(queue_count); - vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_count, queues.Data); - - for (uint32_t queue_index = 0; queue_index < queue_count; queue_index++) - { - VkBool32 present_supported = VK_FALSE; - result = vkGetPhysicalDeviceSurfaceSupportKHR(device, queue_index, surface, &present_supported); - if (result != VK_SUCCESS) - { - continue; - } - if ((queues[queue_index].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0 || present_supported != VK_TRUE) - { - continue; - } - - const int score = PhysicalDeviceScore(device); - if (score > best_score) - { - best_score = score; - g_PhysicalDevice = device; - g_QueueFamily = queue_index; - } - } - } - - if (g_PhysicalDevice == VK_NULL_HANDLE || g_QueueFamily == UINT32_MAX) - { - fprintf(stderr, "No Vulkan queue family supports both graphics and QNX Screen presentation.\n"); - return false; - } - return true; -} - -static bool CreateVulkanDevice() -{ - uint32_t extension_count = 0; - VkResult result = vkEnumerateDeviceExtensionProperties(g_PhysicalDevice, nullptr, &extension_count, nullptr); - if (result != VK_SUCCESS) - { - CheckVkResult(result); - return false; - } - - ImVector available_extensions; - available_extensions.resize(extension_count); - result = vkEnumerateDeviceExtensionProperties(g_PhysicalDevice, nullptr, &extension_count, available_extensions.Data); - if (result != VK_SUCCESS) - { - CheckVkResult(result); - return false; - } - if (!IsExtensionAvailable(available_extensions, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) - { - fprintf(stderr, "Required Vulkan device extension is unavailable: %s\n", VK_KHR_SWAPCHAIN_EXTENSION_NAME); - return false; - } - - const float priority = 1.0f; - VkDeviceQueueCreateInfo queue_info = {}; - queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_info.queueFamilyIndex = g_QueueFamily; - queue_info.queueCount = 1; - queue_info.pQueuePriorities = &priority; - - const char* device_extensions[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; - VkDeviceCreateInfo create_info = {}; - create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - create_info.queueCreateInfoCount = 1; - create_info.pQueueCreateInfos = &queue_info; - create_info.enabledExtensionCount = IM_COUNTOF(device_extensions); - create_info.ppEnabledExtensionNames = device_extensions; - result = vkCreateDevice(g_PhysicalDevice, &create_info, g_Allocator, &g_Device); - if (result != VK_SUCCESS) - { - CheckVkResult(result); - return false; - } - vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue); - return true; -} - -static bool CreateDescriptorPool() -{ - VkDescriptorPoolSize pool_sizes[] = - { - { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE }, - { VK_DESCRIPTOR_TYPE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE } - }; - VkDescriptorPoolCreateInfo pool_info = {}; - pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - pool_info.poolSizeCount = IM_COUNTOF(pool_sizes); - pool_info.pPoolSizes = pool_sizes; - for (const VkDescriptorPoolSize& pool_size : pool_sizes) - { - pool_info.maxSets += pool_size.descriptorCount; - } - - const VkResult result = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool); - if (result != VK_SUCCESS) - { - CheckVkResult(result); - return false; - } - return true; -} - -static bool SetupVulkanWindow(ImGui_ImplVulkanH_Window* window_data, VkSurfaceKHR surface, int width, int height) -{ - const VkFormat requested_formats[] = - { - VK_FORMAT_B8G8R8A8_UNORM, - VK_FORMAT_R8G8B8A8_UNORM, - }; - window_data->Surface = surface; - window_data->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat( - g_PhysicalDevice, - surface, - requested_formats, - IM_COUNTOF(requested_formats), - VK_COLORSPACE_SRGB_NONLINEAR_KHR); - if (window_data->SurfaceFormat.format == VK_FORMAT_UNDEFINED) - { - fprintf(stderr, "No suitable Vulkan surface format is available.\n"); - return false; - } - - const VkPresentModeKHR requested_present_modes[] = { VK_PRESENT_MODE_FIFO_KHR }; - window_data->PresentMode = ImGui_ImplVulkanH_SelectPresentMode( - g_PhysicalDevice, - surface, - requested_present_modes, - IM_COUNTOF(requested_present_modes)); - ImGui_ImplVulkanH_CreateOrResizeWindow( - g_Instance, - g_PhysicalDevice, - g_Device, - window_data, - g_QueueFamily, - g_Allocator, - width, - height, - g_MinImageCount, - 0); - return true; -} - -static void FrameRender(ImGui_ImplVulkanH_Window* window_data, ImDrawData* draw_data) -{ - VkSemaphore image_acquired = window_data->FrameSemaphores[window_data->SemaphoreIndex].ImageAcquiredSemaphore; - VkSemaphore render_complete = window_data->FrameSemaphores[window_data->SemaphoreIndex].RenderCompleteSemaphore; - VkResult result = vkAcquireNextImageKHR(g_Device, window_data->Swapchain, UINT64_MAX, image_acquired, VK_NULL_HANDLE, &window_data->FrameIndex); - if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) - { - g_SwapChainRebuild = true; - } - if (result == VK_ERROR_OUT_OF_DATE_KHR) - { - return; - } - if (result != VK_SUBOPTIMAL_KHR) - { - CheckVkResult(result); - } - - ImGui_ImplVulkanH_Frame* frame = &window_data->Frames[window_data->FrameIndex]; - result = vkWaitForFences(g_Device, 1, &frame->Fence, VK_TRUE, UINT64_MAX); - CheckVkResult(result); - result = vkResetFences(g_Device, 1, &frame->Fence); - CheckVkResult(result); - result = vkResetCommandPool(g_Device, frame->CommandPool, 0); - CheckVkResult(result); - - VkCommandBufferBeginInfo begin_info = {}; - begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - result = vkBeginCommandBuffer(frame->CommandBuffer, &begin_info); - CheckVkResult(result); - - VkRenderPassBeginInfo render_pass_info = {}; - render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - render_pass_info.renderPass = window_data->RenderPass; - render_pass_info.framebuffer = frame->Framebuffer; - render_pass_info.renderArea.extent.width = window_data->Width; - render_pass_info.renderArea.extent.height = window_data->Height; - render_pass_info.clearValueCount = 1; - render_pass_info.pClearValues = &window_data->ClearValue; - vkCmdBeginRenderPass(frame->CommandBuffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE); - ImGui_ImplVulkan_RenderDrawData(draw_data, frame->CommandBuffer); - vkCmdEndRenderPass(frame->CommandBuffer); - - result = vkEndCommandBuffer(frame->CommandBuffer); - CheckVkResult(result); - - const VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = &image_acquired; - submit_info.pWaitDstStageMask = &wait_stage; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &frame->CommandBuffer; - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &render_complete; - result = vkQueueSubmit(g_Queue, 1, &submit_info, frame->Fence); - CheckVkResult(result); -} - -static void FramePresent(ImGui_ImplVulkanH_Window* window_data) -{ - if (g_SwapChainRebuild) - { - return; - } - - VkSemaphore render_complete = window_data->FrameSemaphores[window_data->SemaphoreIndex].RenderCompleteSemaphore; - VkPresentInfoKHR present_info = {}; - present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - present_info.waitSemaphoreCount = 1; - present_info.pWaitSemaphores = &render_complete; - present_info.swapchainCount = 1; - present_info.pSwapchains = &window_data->Swapchain; - present_info.pImageIndices = &window_data->FrameIndex; - VkResult result = vkQueuePresentKHR(g_Queue, &present_info); - if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) - { - g_SwapChainRebuild = true; - } - else - { - CheckVkResult(result); - } - window_data->SemaphoreIndex = (window_data->SemaphoreIndex + 1) % window_data->SemaphoreCount; -} - -static bool IsExitEvent(screen_event_t event) -{ - int type = SCREEN_EVENT_NONE; - if (screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &type) != 0) - { - return false; - } - if (type == SCREEN_EVENT_KEYBOARD) - { - int flags = 0; - int symbol = 0; - if (screen_get_event_property_iv(event, SCREEN_PROPERTY_FLAGS, &flags) == 0 && - screen_get_event_property_iv(event, SCREEN_PROPERTY_SYM, &symbol) == 0 && - (flags & KEY_DOWN) != 0 && symbol == KEYCODE_ESCAPE) - { - return true; - } - } - if (type == SCREEN_EVENT_CLOSE) - { - return true; - } - return false; -} - -static bool ProcessScreenEvents(ScreenApp* app) -{ - for (;;) - { - if (screen_get_event(app->Context, app->Event, 0) != 0) - { - fprintf(stderr, "screen_get_event() failed: %s\n", strerror(errno)); - return false; - } - int type = SCREEN_EVENT_NONE; - if (screen_get_event_property_iv(app->Event, SCREEN_PROPERTY_TYPE, &type) != 0) - { - fprintf(stderr, "screen_get_event_property_iv(SCREEN_PROPERTY_TYPE) failed: %s\n", strerror(errno)); - return false; - } - if (type == SCREEN_EVENT_NONE) - { - break; - } - if (IsExitEvent(app->Event)) - { - return false; - } - ImGui_ImplScreen_ProcessEvent(app->Event); - } - return true; -} - -static void SleepMilliseconds(long milliseconds) -{ - struct timespec delay = {}; - delay.tv_sec = milliseconds / 1000; - delay.tv_nsec = (milliseconds % 1000) * 1000000L; - nanosleep(&delay, nullptr); -} - -static void CleanupVulkanWindow(ImGui_ImplVulkanH_Window* window_data) -{ - if (g_Device != VK_NULL_HANDLE && window_data->Surface != VK_NULL_HANDLE) - { - const VkSurfaceKHR surface = window_data->Surface; - ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, window_data, g_Allocator); - vkDestroySurfaceKHR(g_Instance, surface, g_Allocator); - } -} - -static void CleanupVulkan() -{ - if (g_Device != VK_NULL_HANDLE) - { - if (g_DescriptorPool != VK_NULL_HANDLE) - { - vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator); - } - vkDestroyDevice(g_Device, g_Allocator); - } - if (g_Instance != VK_NULL_HANDLE) - { - vkDestroyInstance(g_Instance, g_Allocator); - } -} - -static void DestroyScreenApp(ScreenApp* app) -{ - if (app->Event != nullptr) - { - screen_destroy_event(app->Event); - } - if (app->Window != nullptr) - { - screen_destroy_window(app->Window); - } - if (app->Context != nullptr) - { - screen_destroy_context(app->Context); - } -} - -int main(int, char**) -{ - ScreenApp app; - VkSurfaceKHR surface = VK_NULL_HANDLE; - if (!CreateScreenWindow(&app) || - !CreateVulkanInstance() || - !CreateVulkanSurface(&app, &surface) || - !SelectPhysicalDeviceAndQueue(surface) || - !CreateVulkanDevice() || - !CreateDescriptorPool()) - { - if (surface != VK_NULL_HANDLE && g_Instance != VK_NULL_HANDLE) - { - vkDestroySurfaceKHR(g_Instance, surface, g_Allocator); - } - CleanupVulkan(); - DestroyScreenApp(&app); - return EXIT_FAILURE; - } - - int window_size[2] = { app.WindowSize[0], app.WindowSize[1] }; - if (!SetupVulkanWindow(&g_MainWindowData, surface, window_size[0], window_size[1])) - { - fprintf(stderr, "Failed to set up the Vulkan swapchain.\n"); - vkDestroySurfaceKHR(g_Instance, surface, g_Allocator); - CleanupVulkan(); - DestroyScreenApp(&app); - return EXIT_FAILURE; - } - - const int visible = 1; - if (screen_set_window_property_iv(app.Window, SCREEN_PROPERTY_VISIBLE, &visible) != 0) - { - fprintf(stderr, "screen_set_window_property_iv(SCREEN_PROPERTY_VISIBLE) failed: %s\n", strerror(errno)); - CleanupVulkanWindow(&g_MainWindowData); - CleanupVulkan(); - DestroyScreenApp(&app); - return EXIT_FAILURE; - } - - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); - io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; - ImGui::StyleColorsDark(); - - bool screen_backend_initialized = ImGui_ImplScreen_Init(app.Context, app.Window); - ImGui_ImplVulkan_InitInfo init_info = {}; - init_info.ApiVersion = VK_API_VERSION_1_0; - init_info.Instance = g_Instance; - init_info.PhysicalDevice = g_PhysicalDevice; - init_info.Device = g_Device; - init_info.QueueFamily = g_QueueFamily; - init_info.Queue = g_Queue; - init_info.PipelineCache = g_PipelineCache; - init_info.DescriptorPool = g_DescriptorPool; - init_info.MinImageCount = g_MinImageCount; - init_info.ImageCount = g_MainWindowData.ImageCount; - init_info.Allocator = g_Allocator; - init_info.PipelineInfoMain.RenderPass = g_MainWindowData.RenderPass; - init_info.PipelineInfoMain.Subpass = 0; - init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT; - init_info.CheckVkResultFn = CheckVkResult; - const bool renderer_backend_initialized = ImGui_ImplVulkan_Init(&init_info); - if (!screen_backend_initialized || !renderer_backend_initialized) - { - fprintf(stderr, "Failed to initialize Dear ImGui backends.\n"); - if (renderer_backend_initialized) - { - ImGui_ImplVulkan_Shutdown(); - } - if (screen_backend_initialized) - { - ImGui_ImplScreen_Shutdown(); - } - ImGui::DestroyContext(); - CleanupVulkanWindow(&g_MainWindowData); - CleanupVulkan(); - DestroyScreenApp(&app); - return EXIT_FAILURE; - } - - bool show_demo_window = true; - bool show_another_window = false; - ImVec4 clear_color = ImVec4(0.10f, 0.12f, 0.15f, 1.00f); - bool running = true; - while (running) - { - running = ProcessScreenEvents(&app); - if (!running) - { - break; - } - - if (screen_get_window_property_iv(app.Window, SCREEN_PROPERTY_SIZE, window_size) != 0) - { - fprintf(stderr, "screen_get_window_property_iv(SCREEN_PROPERTY_SIZE) failed: %s\n", strerror(errno)); - break; - } - if (window_size[0] <= 0 || window_size[1] <= 0) - { - SleepMilliseconds(10); - continue; - } - if (g_SwapChainRebuild || g_MainWindowData.Width != window_size[0] || g_MainWindowData.Height != window_size[1]) - { - ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount); - ImGui_ImplVulkanH_CreateOrResizeWindow( - g_Instance, - g_PhysicalDevice, - g_Device, - &g_MainWindowData, - g_QueueFamily, - g_Allocator, - window_size[0], - window_size[1], - g_MinImageCount, - 0); - g_MainWindowData.FrameIndex = 0; - g_SwapChainRebuild = false; - } - - ImGui_ImplVulkan_NewFrame(); - ImGui_ImplScreen_NewFrame(); - ImGui::NewFrame(); - - if (show_demo_window) - { - ImGui::ShowDemoWindow(&show_demo_window); - } - - static float value = 0.0f; - static int counter = 0; - static char text[128] = "Keyboard input is handled by QNX Screen"; - ImGui::Begin("QNX Screen + Vulkan"); - ImGui::Checkbox("Demo Window", &show_demo_window); - ImGui::Checkbox("Another Window", &show_another_window); - ImGui::SliderFloat("float", &value, 0.0f, 1.0f); - ImGui::ColorEdit3("clear color", (float*)&clear_color); - ImGui::InputText("text", text, IM_ARRAYSIZE(text)); - if (ImGui::Button("Button")) - { - counter++; - } - ImGui::SameLine(); - ImGui::Text("counter = %d", counter); - ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); - ImGui::TextUnformatted("Press Esc to exit."); - ImGui::End(); - - if (show_another_window) - { - ImGui::Begin("Another Window", &show_another_window); - ImGui::TextUnformatted("Hello from QNX Screen!"); - if (ImGui::Button("Close Me")) - { - show_another_window = false; - } - ImGui::End(); - } - - ImGui::Render(); - ImDrawData* draw_data = ImGui::GetDrawData(); - const bool minimized = draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f; - if (!minimized) - { - g_MainWindowData.ClearValue.color.float32[0] = clear_color.x * clear_color.w; - g_MainWindowData.ClearValue.color.float32[1] = clear_color.y * clear_color.w; - g_MainWindowData.ClearValue.color.float32[2] = clear_color.z * clear_color.w; - g_MainWindowData.ClearValue.color.float32[3] = clear_color.w; - FrameRender(&g_MainWindowData, draw_data); - FramePresent(&g_MainWindowData); - } - } - - CheckVkResult(vkDeviceWaitIdle(g_Device)); - ImGui_ImplVulkan_Shutdown(); - ImGui_ImplScreen_Shutdown(); - ImGui::DestroyContext(); - CleanupVulkanWindow(&g_MainWindowData); - CleanupVulkan(); - DestroyScreenApp(&app); - return EXIT_SUCCESS; -}