diff --git a/backends/imgui_impl_emscripten.cpp b/backends/imgui_impl_emscripten.cpp index 8b7dee021..46414efe9 100644 --- a/backends/imgui_impl_emscripten.cpp +++ b/backends/imgui_impl_emscripten.cpp @@ -25,160 +25,160 @@ namespace { // A map of HTML5 key names to imgui keys static const std::unordered_map key_translate_lookup{ - // main character keys - {"Backquote", ImGuiKey_GraveAccent}, - {"Backslash", ImGuiKey_Backslash}, - {"BracketLeft", ImGuiKey_LeftBracket}, - {"BracketRight", ImGuiKey_RightBracket}, - {"Comma", ImGuiKey_Comma}, - {"Digit0", ImGuiKey_0}, - {"Digit1", ImGuiKey_1}, - {"Digit2", ImGuiKey_2}, - {"Digit3", ImGuiKey_3}, - {"Digit4", ImGuiKey_4}, - {"Digit5", ImGuiKey_5}, - {"Digit6", ImGuiKey_6}, - {"Digit7", ImGuiKey_7}, - {"Digit8", ImGuiKey_8}, - {"Digit9", ImGuiKey_9}, - {"Equal", ImGuiKey_Equal}, - {"IntlBackslash", ImGuiKey_Backslash}, // Mapping to generic backslash - {"IntlRo", ImGuiKey_Slash}, // Closest match for non-standard layouts - {"IntlYen", ImGuiKey_Backslash}, // Closest match for non-standard layouts - {"KeyA", ImGuiKey_A}, - {"KeyB", ImGuiKey_B}, - {"KeyC", ImGuiKey_C}, - {"KeyD", ImGuiKey_D}, - {"KeyE", ImGuiKey_E}, - {"KeyF", ImGuiKey_F}, - {"KeyG", ImGuiKey_G}, - {"KeyH", ImGuiKey_H}, - {"KeyI", ImGuiKey_I}, - {"KeyJ", ImGuiKey_J}, - {"KeyK", ImGuiKey_K}, - {"KeyL", ImGuiKey_L}, - {"KeyM", ImGuiKey_M}, - {"KeyN", ImGuiKey_N}, - {"KeyO", ImGuiKey_O}, - {"KeyP", ImGuiKey_P}, - {"KeyQ", ImGuiKey_Q}, - {"KeyR", ImGuiKey_R}, - {"KeyS", ImGuiKey_S}, - {"KeyT", ImGuiKey_T}, - {"KeyU", ImGuiKey_U}, - {"KeyV", ImGuiKey_V}, - {"KeyW", ImGuiKey_W}, - {"KeyX", ImGuiKey_X}, - {"KeyY", ImGuiKey_Y}, - {"KeyZ", ImGuiKey_Z}, - {"Minus", ImGuiKey_Minus}, - {"Period", ImGuiKey_Period}, - {"Quote", ImGuiKey_Apostrophe}, - {"Semicolon", ImGuiKey_Semicolon}, - {"Slash", ImGuiKey_Slash}, + // main character keys + {"Backquote", ImGuiKey_GraveAccent}, + {"Backslash", ImGuiKey_Backslash}, + {"BracketLeft", ImGuiKey_LeftBracket}, + {"BracketRight", ImGuiKey_RightBracket}, + {"Comma", ImGuiKey_Comma}, + {"Digit0", ImGuiKey_0}, + {"Digit1", ImGuiKey_1}, + {"Digit2", ImGuiKey_2}, + {"Digit3", ImGuiKey_3}, + {"Digit4", ImGuiKey_4}, + {"Digit5", ImGuiKey_5}, + {"Digit6", ImGuiKey_6}, + {"Digit7", ImGuiKey_7}, + {"Digit8", ImGuiKey_8}, + {"Digit9", ImGuiKey_9}, + {"Equal", ImGuiKey_Equal}, + {"IntlBackslash", ImGuiKey_Backslash}, // Mapping to generic backslash + {"IntlRo", ImGuiKey_Slash}, // Closest match for non-standard layouts + {"IntlYen", ImGuiKey_Backslash}, // Closest match for non-standard layouts + {"KeyA", ImGuiKey_A}, + {"KeyB", ImGuiKey_B}, + {"KeyC", ImGuiKey_C}, + {"KeyD", ImGuiKey_D}, + {"KeyE", ImGuiKey_E}, + {"KeyF", ImGuiKey_F}, + {"KeyG", ImGuiKey_G}, + {"KeyH", ImGuiKey_H}, + {"KeyI", ImGuiKey_I}, + {"KeyJ", ImGuiKey_J}, + {"KeyK", ImGuiKey_K}, + {"KeyL", ImGuiKey_L}, + {"KeyM", ImGuiKey_M}, + {"KeyN", ImGuiKey_N}, + {"KeyO", ImGuiKey_O}, + {"KeyP", ImGuiKey_P}, + {"KeyQ", ImGuiKey_Q}, + {"KeyR", ImGuiKey_R}, + {"KeyS", ImGuiKey_S}, + {"KeyT", ImGuiKey_T}, + {"KeyU", ImGuiKey_U}, + {"KeyV", ImGuiKey_V}, + {"KeyW", ImGuiKey_W}, + {"KeyX", ImGuiKey_X}, + {"KeyY", ImGuiKey_Y}, + {"KeyZ", ImGuiKey_Z}, + {"Minus", ImGuiKey_Minus}, + {"Period", ImGuiKey_Period}, + {"Quote", ImGuiKey_Apostrophe}, + {"Semicolon", ImGuiKey_Semicolon}, + {"Slash", ImGuiKey_Slash}, - // control keys - {"AltLeft", ImGuiKey_LeftAlt}, - {"AltRight", ImGuiKey_RightAlt}, - {"Backspace", ImGuiKey_Backspace}, - {"CapsLock", ImGuiKey_CapsLock}, - {"ContextMenu", ImGuiKey_Menu}, - {"ControlLeft", ImGuiKey_LeftCtrl}, - {"ControlRight", ImGuiKey_RightCtrl}, - {"Enter", ImGuiKey_Enter}, - {"MetaLeft", ImGuiKey_LeftSuper}, - {"MetaRight", ImGuiKey_RightSuper}, - {"ShiftLeft", ImGuiKey_LeftShift}, - {"ShiftRight", ImGuiKey_RightShift}, - {"Space", ImGuiKey_Space}, - {"Tab", ImGuiKey_Tab}, + // control keys + {"AltLeft", ImGuiKey_LeftAlt}, + {"AltRight", ImGuiKey_RightAlt}, + {"Backspace", ImGuiKey_Backspace}, + {"CapsLock", ImGuiKey_CapsLock}, + {"ContextMenu", ImGuiKey_Menu}, + {"ControlLeft", ImGuiKey_LeftCtrl}, + {"ControlRight", ImGuiKey_RightCtrl}, + {"Enter", ImGuiKey_Enter}, + {"MetaLeft", ImGuiKey_LeftSuper}, + {"MetaRight", ImGuiKey_RightSuper}, + {"ShiftLeft", ImGuiKey_LeftShift}, + {"ShiftRight", ImGuiKey_RightShift}, + {"Space", ImGuiKey_Space}, + {"Tab", ImGuiKey_Tab}, - // navigation key group - {"Delete", ImGuiKey_Delete}, - {"End", ImGuiKey_End}, - //{"Help", ImGuiKey_PrintScreen}, // Best approximation - {"Home", ImGuiKey_Home}, - {"Insert", ImGuiKey_Insert}, - {"PageDown", ImGuiKey_PageDown}, - {"PageUp", ImGuiKey_PageUp}, + // navigation key group + {"Delete", ImGuiKey_Delete}, + {"End", ImGuiKey_End}, + //{"Help", ImGuiKey_PrintScreen}, // Best approximation + {"Home", ImGuiKey_Home}, + {"Insert", ImGuiKey_Insert}, + {"PageDown", ImGuiKey_PageDown}, + {"PageUp", ImGuiKey_PageUp}, - // arrow key group - {"ArrowDown", ImGuiKey_DownArrow}, - {"ArrowLeft", ImGuiKey_LeftArrow}, - {"ArrowRight", ImGuiKey_RightArrow}, - {"ArrowUp", ImGuiKey_UpArrow}, + // arrow key group + {"ArrowDown", ImGuiKey_DownArrow}, + {"ArrowLeft", ImGuiKey_LeftArrow}, + {"ArrowRight", ImGuiKey_RightArrow}, + {"ArrowUp", ImGuiKey_UpArrow}, - // number pad group - {"NumLock", ImGuiKey_NumLock}, - {"Numpad0", ImGuiKey_Keypad0}, - {"Numpad1", ImGuiKey_Keypad1}, - {"Numpad2", ImGuiKey_Keypad2}, - {"Numpad3", ImGuiKey_Keypad3}, - {"Numpad4", ImGuiKey_Keypad4}, - {"Numpad5", ImGuiKey_Keypad5}, - {"Numpad6", ImGuiKey_Keypad6}, - {"Numpad7", ImGuiKey_Keypad7}, - {"Numpad8", ImGuiKey_Keypad8}, - {"Numpad9", ImGuiKey_Keypad9}, - {"NumpadAdd", ImGuiKey_KeypadAdd}, - {"NumpadBackspace", ImGuiKey_Backspace}, // No direct mapping; backspace functionality - //{"NumpadClear", ImGuiKey_KeypadClear}, // Custom-defined if needed - //{"NumpadClearEntry", ImGuiKey_KeypadClear}, // Custom-defined if needed - {"NumpadComma", ImGuiKey_KeypadDecimal}, // Closest match - {"NumpadDecimal", ImGuiKey_KeypadDecimal}, - {"NumpadDivide", ImGuiKey_KeypadDivide}, - {"NumpadEnter", ImGuiKey_KeypadEnter}, - {"NumpadEqual", ImGuiKey_KeypadEqual}, - {"NumpadHash", ImGuiKey_Backslash}, // Mapped to # on UK keyboard - //{"NumpadMemoryAdd", ImGuiKey_None}, // No defined mapping - //{"NumpadMemoryClear", ImGuiKey_None}, // No defined mapping - //{"NumpadMemoryRecall", ImGuiKey_None}, // No defined mapping - //{"NumpadMemoryStore", ImGuiKey_None}, // No defined mapping - //{"NumpadMemorySubtract", ImGuiKey_None}, // No defined mapping - {"NumpadMultiply", ImGuiKey_KeypadMultiply}, - {"NumpadParenLeft", ImGuiKey_LeftBracket}, // Closest available - {"NumpadParenRight", ImGuiKey_RightBracket}, // Closest available - {"NumpadStar", ImGuiKey_KeypadMultiply}, // Same as multiply - {"NumpadSubtract", ImGuiKey_KeypadSubtract}, + // number pad group + {"NumLock", ImGuiKey_NumLock}, + {"Numpad0", ImGuiKey_Keypad0}, + {"Numpad1", ImGuiKey_Keypad1}, + {"Numpad2", ImGuiKey_Keypad2}, + {"Numpad3", ImGuiKey_Keypad3}, + {"Numpad4", ImGuiKey_Keypad4}, + {"Numpad5", ImGuiKey_Keypad5}, + {"Numpad6", ImGuiKey_Keypad6}, + {"Numpad7", ImGuiKey_Keypad7}, + {"Numpad8", ImGuiKey_Keypad8}, + {"Numpad9", ImGuiKey_Keypad9}, + {"NumpadAdd", ImGuiKey_KeypadAdd}, + {"NumpadBackspace", ImGuiKey_Backspace}, // No direct mapping; backspace functionality + //{"NumpadClear", ImGuiKey_KeypadClear}, // Custom-defined if needed + //{"NumpadClearEntry", ImGuiKey_KeypadClear}, // Custom-defined if needed + {"NumpadComma", ImGuiKey_KeypadDecimal}, // Closest match + {"NumpadDecimal", ImGuiKey_KeypadDecimal}, + {"NumpadDivide", ImGuiKey_KeypadDivide}, + {"NumpadEnter", ImGuiKey_KeypadEnter}, + {"NumpadEqual", ImGuiKey_KeypadEqual}, + {"NumpadHash", ImGuiKey_Backslash}, // Mapped to # on UK keyboard + //{"NumpadMemoryAdd", ImGuiKey_None}, // No defined mapping + //{"NumpadMemoryClear", ImGuiKey_None}, // No defined mapping + //{"NumpadMemoryRecall", ImGuiKey_None}, // No defined mapping + //{"NumpadMemoryStore", ImGuiKey_None}, // No defined mapping + //{"NumpadMemorySubtract", ImGuiKey_None}, // No defined mapping + {"NumpadMultiply", ImGuiKey_KeypadMultiply}, + {"NumpadParenLeft", ImGuiKey_LeftBracket}, // Closest available + {"NumpadParenRight", ImGuiKey_RightBracket}, // Closest available + {"NumpadStar", ImGuiKey_KeypadMultiply}, // Same as multiply + {"NumpadSubtract", ImGuiKey_KeypadSubtract}, - // top row key groups - {"Escape", ImGuiKey_Escape}, - {"F1", ImGuiKey_F1}, - {"F2", ImGuiKey_F2}, - {"F3", ImGuiKey_F3}, - {"F4", ImGuiKey_F4}, - {"F5", ImGuiKey_F5}, - {"F6", ImGuiKey_F6}, - {"F6", ImGuiKey_F6}, - {"F7", ImGuiKey_F7}, - {"F8", ImGuiKey_F8}, - {"F9", ImGuiKey_F9}, - {"F10", ImGuiKey_F10}, - {"F11", ImGuiKey_F11}, - {"F12", ImGuiKey_F12}, - //{"Fn", ImGuiKey_None}, // No direct mapping - //{"FnLock", ImGuiKey_None}, // No direct mapping - {"PrintScreen", ImGuiKey_PrintScreen}, - {"ScrollLock", ImGuiKey_ScrollLock}, - {"Pause", ImGuiKey_Pause}, + // top row key groups + {"Escape", ImGuiKey_Escape}, + {"F1", ImGuiKey_F1}, + {"F2", ImGuiKey_F2}, + {"F3", ImGuiKey_F3}, + {"F4", ImGuiKey_F4}, + {"F5", ImGuiKey_F5}, + {"F6", ImGuiKey_F6}, + {"F6", ImGuiKey_F6}, + {"F7", ImGuiKey_F7}, + {"F8", ImGuiKey_F8}, + {"F9", ImGuiKey_F9}, + {"F10", ImGuiKey_F10}, + {"F11", ImGuiKey_F11}, + {"F12", ImGuiKey_F12}, + //{"Fn", ImGuiKey_None}, // No direct mapping + //{"FnLock", ImGuiKey_None}, // No direct mapping + {"PrintScreen", ImGuiKey_PrintScreen}, + {"ScrollLock", ImGuiKey_ScrollLock}, + {"Pause", ImGuiKey_Pause}, }; ImGuiKey translate_key(char const* emscripten_key) __attribute__((__const__)); ImGuiKey translate_key(char const* emscripten_key) { - // Translate an emscripten-provided browser string describing a keycode to an imgui key code - if(auto it{key_translate_lookup.find(emscripten_key)}; it != key_translate_lookup.end()) { - return it->second; - } - return ImGuiKey_None; + // Translate an emscripten-provided browser string describing a keycode to an imgui key code + if(auto it{key_translate_lookup.find(emscripten_key)}; it != key_translate_lookup.end()) { + return it->second; + } + return ImGuiKey_None; } constexpr ImGuiMouseButton translate_mousebutton(unsigned short emscripten_button) __attribute__((__const__)); constexpr ImGuiMouseButton translate_mousebutton(unsigned short emscripten_button) { - // Translate an emscripten-provided integer describing a mouse button to an imgui mouse button - if(emscripten_button == 1) return ImGuiMouseButton_Middle; // 1 = middle mouse button - if(emscripten_button == 2) return ImGuiMouseButton_Right; // 2 = right mouse button - if(emscripten_button > ImGuiMouseButton_COUNT) return ImGuiMouseButton_Middle; // treat any weird clicks on unexpected buttons (button 6 upwards) as middle mouse - return emscripten_button; // any other button translates 1:1 + // Translate an emscripten-provided integer describing a mouse button to an imgui mouse button + if(emscripten_button == 1) return ImGuiMouseButton_Middle; // 1 = middle mouse button + if(emscripten_button == 2) return ImGuiMouseButton_Right; // 2 = right mouse button + if(emscripten_button > ImGuiMouseButton_COUNT) return ImGuiMouseButton_Middle; // treat any weird clicks on unexpected buttons (button 6 upwards) as middle mouse + return emscripten_button; // any other button translates 1:1 } } // anonymous namespace @@ -188,56 +188,56 @@ namespace emscripten_browser_cursor_internal { // Browser cursor helpers enum class cursor { - // General - cursor_auto, // The UA will determine the cursor to display based on the current context. E.g., equivalent to text when hovering text. - cursor_default, // The platform-dependent default cursor. Typically an arrow. - none, // No cursor is rendered. + // General + cursor_auto, // The UA will determine the cursor to display based on the current context. E.g., equivalent to text when hovering text. + cursor_default, // The platform-dependent default cursor. Typically an arrow. + none, // No cursor is rendered. - // Links & status - context_menu, // cursor slightly obscuring a menu icon - A context menu is available. - help, // cursor next to a question mark - Help information is available. - pointer, // right hand with an index finger pointing up - The cursor is a pointer that indicates a link. Typically an image of a pointing hand. - progress, // cursor and hour glass - The program is busy in the background, but the user can still interact with the interface (in contrast to wait). - wait, // hour glass - The program is busy, and the user can't interact with the interface (in contrast to progress). Sometimes an image of an hourglass or a watch. + // Links & status + context_menu, // cursor slightly obscuring a menu icon - A context menu is available. + help, // cursor next to a question mark - Help information is available. + pointer, // right hand with an index finger pointing up - The cursor is a pointer that indicates a link. Typically an image of a pointing hand. + progress, // cursor and hour glass - The program is busy in the background, but the user can still interact with the interface (in contrast to wait). + wait, // hour glass - The program is busy, and the user can't interact with the interface (in contrast to progress). Sometimes an image of an hourglass or a watch. - // Selection - cell, // plus symbol - The table cell or set of cells can be selected. - crosshair, // crosshair - Cross cursor, often used to indicate selection in a bitmap. - text, // vertical i-beam - The text can be selected. Typically the shape of an I-beam. - vertical_text, // horizontal i-beam - The vertical text can be selected. Typically the shape of a sideways I-beam. + // Selection + cell, // plus symbol - The table cell or set of cells can be selected. + crosshair, // crosshair - Cross cursor, often used to indicate selection in a bitmap. + text, // vertical i-beam - The text can be selected. Typically the shape of an I-beam. + vertical_text, // horizontal i-beam - The vertical text can be selected. Typically the shape of a sideways I-beam. - // Drag & drop - alias, // cursor next to a folder icon with a curved arrow pointing up and to the right - An alias or shortcut is to be created. - copy, // cursor next to a smaller folder icon with a plus sign - Something is to be copied. - move, // plus sign made of two thin lines, with small arrows facing out - Something is to be moved. - no_drop, // cursor next to circle with a line through it - An item may not be dropped at the current location. - not_allowed, // Circle with a line through it - The requested action will not be carried out. - grab, // fully opened hand - Something can be grabbed (dragged to be moved). - grabbing, // closed hand - Something is being grabbed (dragged to be moved). + // Drag & drop + alias, // cursor next to a folder icon with a curved arrow pointing up and to the right - An alias or shortcut is to be created. + copy, // cursor next to a smaller folder icon with a plus sign - Something is to be copied. + move, // plus sign made of two thin lines, with small arrows facing out - Something is to be moved. + no_drop, // cursor next to circle with a line through it - An item may not be dropped at the current location. + not_allowed, // Circle with a line through it - The requested action will not be carried out. + grab, // fully opened hand - Something can be grabbed (dragged to be moved). + grabbing, // closed hand - Something is being grabbed (dragged to be moved). - // Resizing & scrolling - all_scroll, // dot with four triangles around it - Something can be scrolled in any direction (panned). - col_resize, // The item/column can be resized horizontally. Often rendered as arrows pointing left and right with a vertical bar separating them. - row_resize, // The item/row can be resized vertically. Often rendered as arrows pointing up and down with a horizontal bar separating them. - n_resize, // arrow pointing up - Some edge is to be moved. For example, the se-resize cursor is used when the movement starts from the south-east corner of the box. - e_resize, // arrow pointing right - s_resize, // arrow pointing down - w_resize, // arrow pointing left - ne_resize, // arrow pointing top-right - nw_resize, // arrow pointing top-left - se_resize, // arrow pointing bottom-right - sw_resize, // arrow pointing bottom-left - ew_resize, // arrow pointing left and right - Bidirectional resize cursor. - ns_resize, // arrow pointing up and down - nesw_resize, // arrow pointing both to the top-right and bottom-left - nwse_resize, // arrow pointing both to the top-left and bottom-right + // Resizing & scrolling + all_scroll, // dot with four triangles around it - Something can be scrolled in any direction (panned). + col_resize, // The item/column can be resized horizontally. Often rendered as arrows pointing left and right with a vertical bar separating them. + row_resize, // The item/row can be resized vertically. Often rendered as arrows pointing up and down with a horizontal bar separating them. + n_resize, // arrow pointing up - Some edge is to be moved. For example, the se-resize cursor is used when the movement starts from the south-east corner of the box. + e_resize, // arrow pointing right + s_resize, // arrow pointing down + w_resize, // arrow pointing left + ne_resize, // arrow pointing top-right + nw_resize, // arrow pointing top-left + se_resize, // arrow pointing bottom-right + sw_resize, // arrow pointing bottom-left + ew_resize, // arrow pointing left and right - Bidirectional resize cursor. + ns_resize, // arrow pointing up and down + nesw_resize, // arrow pointing both to the top-right and bottom-left + nwse_resize, // arrow pointing both to the top-left and bottom-right - // Zooming - zoom_in, // magnifying glass with a plus sign - Something can be zoomed (magnified) in or out. - zoom_out, + // Zooming + zoom_in, // magnifying glass with a plus sign - Something can be zoomed (magnified) in or out. + zoom_out, - // Special invalid value - invalid = std::numeric_limits::max() + // Special invalid value + invalid = std::numeric_limits::max() }; void set(cursor new_cursor); // set a new cursor from a cursor enum @@ -246,62 +246,62 @@ void unset(); // Browser cursor helper implementation bool is_set() { - // Returns whether the cursor is currently set - return EM_ASM_INT( - return !(!document.body.style.cursor || document.body.style.cursor.length === 0 ); - ); + // Returns whether the cursor is currently set + return EM_ASM_INT( + return !(!document.body.style.cursor || document.body.style.cursor.length === 0 ); + ); } std::string get_string() { - // Return the current cursor setting as a string - auto cursor_str_ptr{reinterpret_cast(EM_ASM_PTR( - return stringToNewUTF8(document.body.style.cursor); - ))}; - std::string const cursor_str{cursor_str_ptr}; - free(cursor_str_ptr); - return cursor_str; + // Return the current cursor setting as a string + auto cursor_str_ptr{reinterpret_cast(EM_ASM_PTR( + return stringToNewUTF8(document.body.style.cursor); + ))}; + std::string const cursor_str{cursor_str_ptr}; + free(cursor_str_ptr); + return cursor_str; } void set(cursor new_cursor) { - // Set the cursor according to the given enum - // Note, implementations omitted for cursors not used by imgui. For full implementation, use https://github.com/Armchair-Software/emscripten-browser-cursor - switch(new_cursor) { - case cursor::cursor_default: - default: - EM_ASM(document.body.style.cursor = 'default';); - break; - case cursor::pointer: - EM_ASM(document.body.style.cursor = 'pointer';); - break; - case cursor::text: - EM_ASM(document.body.style.cursor = 'text';); - break; - case cursor::move: - EM_ASM(document.body.style.cursor = 'move';); - break; - case cursor::not_allowed: - EM_ASM(document.body.style.cursor = 'not-allowed';); - break; - case cursor::ew_resize: - EM_ASM(document.body.style.cursor = 'ew-resize';); - break; - case cursor::ns_resize: - EM_ASM(document.body.style.cursor = 'ns-resize';); - break; - case cursor::nesw_resize: - EM_ASM(document.body.style.cursor = 'nesw-resize';); - break; - case cursor::nwse_resize: - EM_ASM(document.body.style.cursor = 'nwse-resize';); - break; - } + // Set the cursor according to the given enum + // Note, implementations omitted for cursors not used by imgui. For full implementation, use https://github.com/Armchair-Software/emscripten-browser-cursor + switch(new_cursor) { + case cursor::cursor_default: + default: + EM_ASM(document.body.style.cursor = 'default';); + break; + case cursor::pointer: + EM_ASM(document.body.style.cursor = 'pointer';); + break; + case cursor::text: + EM_ASM(document.body.style.cursor = 'text';); + break; + case cursor::move: + EM_ASM(document.body.style.cursor = 'move';); + break; + case cursor::not_allowed: + EM_ASM(document.body.style.cursor = 'not-allowed';); + break; + case cursor::ew_resize: + EM_ASM(document.body.style.cursor = 'ew-resize';); + break; + case cursor::ns_resize: + EM_ASM(document.body.style.cursor = 'ns-resize';); + break; + case cursor::nesw_resize: + EM_ASM(document.body.style.cursor = 'nesw-resize';); + break; + case cursor::nwse_resize: + EM_ASM(document.body.style.cursor = 'nwse-resize';); + break; + } } void set(std::string const &new_cursor) { - // Set the cursor from an arbitrary string - EM_ASM({ - document.body.style.cursor = UTF8ToString($0); - }, new_cursor.c_str()); + // Set the cursor from an arbitrary string + EM_ASM({ + document.body.style.cursor = UTF8ToString($0); + }, new_cursor.c_str()); } } // namespace emscripten_browser_cursor @@ -309,311 +309,311 @@ void set(std::string const &new_cursor) { namespace { void update_cursor() { - // Sync any cursor changes due to ImGui to the browser's cursor - static emscripten_browser_cursor_internal::cursor current_cursor{emscripten_browser_cursor_internal::cursor::invalid}; - static std::optional cursor_to_restore; + // Sync any cursor changes due to ImGui to the browser's cursor + static emscripten_browser_cursor_internal::cursor current_cursor{emscripten_browser_cursor_internal::cursor::invalid}; + static std::optional cursor_to_restore; - auto set_cursor_if_necessary{[&](emscripten_browser_cursor_internal::cursor new_cursor){ - if(new_cursor == current_cursor) return; // don't do anything if the current cursor is already set - current_cursor = new_cursor; - emscripten_browser_cursor_internal::set(new_cursor); - }}; + auto set_cursor_if_necessary{[&](emscripten_browser_cursor_internal::cursor new_cursor){ + if(new_cursor == current_cursor) return; // don't do anything if the current cursor is already set + current_cursor = new_cursor; + emscripten_browser_cursor_internal::set(new_cursor); + }}; - if(ImGui::GetIO().WantCaptureMouse) { // mouse is hovering over the gui - if(!cursor_to_restore && emscripten_browser_cursor_internal::is_set()) { - cursor_to_restore = emscripten_browser_cursor_internal::get_string(); // back up the existing cursor when entering the imgui capture space - } + if(ImGui::GetIO().WantCaptureMouse) { // mouse is hovering over the gui + if(!cursor_to_restore && emscripten_browser_cursor_internal::is_set()) { + cursor_to_restore = emscripten_browser_cursor_internal::get_string(); // back up the existing cursor when entering the imgui capture space + } - switch(ImGui::GetMouseCursor()) { - case ImGuiMouseCursor_Arrow: - set_cursor_if_necessary(emscripten_browser_cursor_internal::cursor::cursor_default); - break; - case ImGuiMouseCursor_TextInput: // When hovering over InputText, etc. - set_cursor_if_necessary(emscripten_browser_cursor_internal::cursor::text); - break; - case ImGuiMouseCursor_ResizeAll: // (Unused by Dear ImGui functions) - set_cursor_if_necessary(emscripten_browser_cursor_internal::cursor::move); - break; - case ImGuiMouseCursor_ResizeNS: // When hovering over a horizontal border - set_cursor_if_necessary(emscripten_browser_cursor_internal::cursor::ns_resize); - break; - case ImGuiMouseCursor_ResizeEW: // When hovering over a vertical border or a column - set_cursor_if_necessary(emscripten_browser_cursor_internal::cursor::ew_resize); - break; - case ImGuiMouseCursor_ResizeNESW: // When hovering over the bottom-left corner of a window - set_cursor_if_necessary(emscripten_browser_cursor_internal::cursor::nesw_resize); - break; - case ImGuiMouseCursor_ResizeNWSE: // When hovering over the bottom-right corner of a window - set_cursor_if_necessary(emscripten_browser_cursor_internal::cursor::nwse_resize); - break; - case ImGuiMouseCursor_Hand: // (Unused by Dear ImGui functions. Use for e.g. hyperlinks) - set_cursor_if_necessary(emscripten_browser_cursor_internal::cursor::pointer); - break; - case ImGuiMouseCursor_NotAllowed: // When hovering something with disallowed interaction. Usually a crossed circle. - set_cursor_if_necessary(emscripten_browser_cursor_internal::cursor::not_allowed); - break; + switch(ImGui::GetMouseCursor()) { + case ImGuiMouseCursor_Arrow: + set_cursor_if_necessary(emscripten_browser_cursor_internal::cursor::cursor_default); + break; + case ImGuiMouseCursor_TextInput: // When hovering over InputText, etc. + set_cursor_if_necessary(emscripten_browser_cursor_internal::cursor::text); + break; + case ImGuiMouseCursor_ResizeAll: // (Unused by Dear ImGui functions) + set_cursor_if_necessary(emscripten_browser_cursor_internal::cursor::move); + break; + case ImGuiMouseCursor_ResizeNS: // When hovering over a horizontal border + set_cursor_if_necessary(emscripten_browser_cursor_internal::cursor::ns_resize); + break; + case ImGuiMouseCursor_ResizeEW: // When hovering over a vertical border or a column + set_cursor_if_necessary(emscripten_browser_cursor_internal::cursor::ew_resize); + break; + case ImGuiMouseCursor_ResizeNESW: // When hovering over the bottom-left corner of a window + set_cursor_if_necessary(emscripten_browser_cursor_internal::cursor::nesw_resize); + break; + case ImGuiMouseCursor_ResizeNWSE: // When hovering over the bottom-right corner of a window + set_cursor_if_necessary(emscripten_browser_cursor_internal::cursor::nwse_resize); + break; + case ImGuiMouseCursor_Hand: // (Unused by Dear ImGui functions. Use for e.g. hyperlinks) + set_cursor_if_necessary(emscripten_browser_cursor_internal::cursor::pointer); + break; + case ImGuiMouseCursor_NotAllowed: // When hovering something with disallowed interaction. Usually a crossed circle. + set_cursor_if_necessary(emscripten_browser_cursor_internal::cursor::not_allowed); + break; + } + } else { // mouse is away from the gui, hovering over some other part of the viewport + if(cursor_to_restore) { + emscripten_browser_cursor_internal::set(*cursor_to_restore); // restore the previous cursor when leaving the imgui capture space + cursor_to_restore = std::nullopt; + current_cursor = emscripten_browser_cursor_internal::cursor::invalid; // select an unused value for current cursor to force a set next time set_cursor_if_necessary is called + } } - } else { // mouse is away from the gui, hovering over some other part of the viewport - if(cursor_to_restore) { - emscripten_browser_cursor_internal::set(*cursor_to_restore); // restore the previous cursor when leaving the imgui capture space - cursor_to_restore = std::nullopt; - current_cursor = emscripten_browser_cursor_internal::cursor::invalid; // select an unused value for current cursor to force a set next time set_cursor_if_necessary is called - } - } } } // anonymous namespace void ImGui_ImplEmscripten_Init() { - // Initialise the Emscripten backend, setting input callbacks - auto &imgui_io{ImGui::GetIO()}; - imgui_io.BackendPlatformName = "imgui_impl_emscripten"; - imgui_io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; + // Initialise the Emscripten backend, setting input callbacks + auto &imgui_io{ImGui::GetIO()}; + imgui_io.BackendPlatformName = "imgui_impl_emscripten"; + imgui_io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; - // set up initial display size values - imgui_io.DisplaySize.x = emscripten::val::global("window")["innerWidth"].as(); - imgui_io.DisplaySize.y = emscripten::val::global("window")["innerHeight"].as(); + // set up initial display size values + imgui_io.DisplaySize.x = emscripten::val::global("window")["innerWidth"].as(); + imgui_io.DisplaySize.y = emscripten::val::global("window")["innerHeight"].as(); - emscripten_set_mousemove_callback( - EMSCRIPTEN_EVENT_TARGET_WINDOW, // target - nullptr, // userData - false, // useCapture - [](int /*event_type*/, EmscriptenMouseEvent const *mouse_event, void */*data*/){ // callback, event_type == EMSCRIPTEN_EVENT_MOUSEMOVE - ImGui::GetIO().AddMousePosEvent( - static_cast(mouse_event->clientX), - static_cast(mouse_event->clientY) - ); - return true; // the event was consumed - } - ); - emscripten_set_mousedown_callback( - EMSCRIPTEN_EVENT_TARGET_WINDOW, // target - nullptr, // userData - false, // useCapture - [](int /*event_type*/, EmscriptenMouseEvent const *mouse_event, void */*data*/){ // callback, event_type == EMSCRIPTEN_EVENT_MOUSEDOWN - ImGui::GetIO().AddMouseButtonEvent(translate_mousebutton(mouse_event->button), true); // translated button, down - return true; // the event was consumed - } - ); - emscripten_set_mouseup_callback( - EMSCRIPTEN_EVENT_TARGET_WINDOW, // target - nullptr, // userData - false, // useCapture - [](int /*event_type*/, EmscriptenMouseEvent const *mouse_event, void */*data*/){ // callback, event_type == EMSCRIPTEN_EVENT_MOUSEUP - ImGui::GetIO().AddMouseButtonEvent(translate_mousebutton(mouse_event->button), false); // translated button, up - return true; // the event was consumed - } - ); - emscripten_set_mouseenter_callback( - EMSCRIPTEN_EVENT_TARGET_DOCUMENT, // target - WINDOW doesn't produce mouseenter events - nullptr, // userData - false, // useCapture - [](int /*event_type*/, EmscriptenMouseEvent const *mouse_event, void */*data*/){ // callback, event_type == EMSCRIPTEN_EVENT_MOUSEENTER - ImGui::GetIO().AddMousePosEvent( - static_cast(mouse_event->clientX), - static_cast(mouse_event->clientY) - ); - return true; // the event was consumed - } - ); - emscripten_set_mouseleave_callback( - EMSCRIPTEN_EVENT_TARGET_DOCUMENT, // target - WINDOW doesn't produce mouseenter events - nullptr, // userData - false, // useCapture - [](int /*event_type*/, EmscriptenMouseEvent const */*mouse_event*/, void */*data*/){ // callback, event_type == EMSCRIPTEN_EVENT_MOUSELEAVE - auto &imgui_io{ImGui::GetIO()}; - imgui_io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); // cursor is not in the window - imgui_io.ClearInputKeys(); // clear pending input keys on mouse exit - return true; // the event was consumed - } - ); - emscripten_set_wheel_callback( - EMSCRIPTEN_EVENT_TARGET_WINDOW, // target - nullptr, // userData - false, // useCapture - [](int /*event_type*/, EmscriptenWheelEvent const *wheel_event, void */*data*/){ // callback, event_type == EMSCRIPTEN_EVENT_WHEEL - float scale{1.0f}; - switch(wheel_event->deltaMode) { - case DOM_DELTA_PIXEL: // scrolling in pixels - scale = 1.0f / 100.0f; - break; - case DOM_DELTA_LINE: // scrolling by lines - scale = 1.0f / 3.0f; - break; - case DOM_DELTA_PAGE: // scrolling by pages - scale = 80.0f; - break; - } - // TODO: make scrolling speeds configurable - ImGui::GetIO().AddMouseWheelEvent( - -static_cast(wheel_event->deltaX) * scale, - -static_cast(wheel_event->deltaY) * scale - ); - return false; // the event was not consumed - } - ); - emscripten_set_keydown_callback( - EMSCRIPTEN_EVENT_TARGET_WINDOW, // target - nullptr, // userData - false, // useCapture - [](int /*event_type*/, EmscriptenKeyboardEvent const *key_event, void */*data*/){ // callback, event_type == EMSCRIPTEN_EVENT_KEYDOWN - auto const key{translate_key(key_event->code)}; - auto &imgui_io{ImGui::GetIO()}; - imgui_io.AddKeyEvent(key, true); - switch(key) { // special cases for certain key events - case ImGuiKey_LeftCtrl: // additional events for modifier keys - case ImGuiKey_RightCtrl: - imgui_io.AddKeyEvent(ImGuiMod_Ctrl, true); - break; - case ImGuiKey_LeftShift: - case ImGuiKey_RightShift: - imgui_io.AddKeyEvent(ImGuiMod_Shift, true); - break; - case ImGuiKey_LeftAlt: - case ImGuiKey_RightAlt: - imgui_io.AddKeyEvent(ImGuiMod_Alt, true); - break; - case ImGuiKey_LeftSuper: - case ImGuiKey_RightSuper: - imgui_io.AddKeyEvent(ImGuiMod_Super, true); - break; - // TODO: case ImGuiKey_Menu: do we want to do anything with this? - case ImGuiKey_Tab: // consuming tab prevents the user tabbing to other parts of the browser interface outside the window content - return imgui_io.WantCaptureKeyboard; // the event was consumed only if imgui wants to capture the keyboard - case ImGuiKey_Enter: // consuming enter prevents the word "Enter" appearing in text input via the keypress callback - case ImGuiKey_Delete: // consuming enter prevents the word "Delete" appearing in text input via the keypress callback - return imgui_io.WantTextInput; // the event was consumed only if we're currently accepting text input - default: - break; - } - return false; // if no special handling, the event was not consumed - } - ); - emscripten_set_keyup_callback( - EMSCRIPTEN_EVENT_TARGET_WINDOW, // target - nullptr, // userData - false, // useCapture - [](int /*event_type*/, EmscriptenKeyboardEvent const *key_event, void */*data*/){ // callback, event_type == EMSCRIPTEN_EVENT_KEYUP - auto const key{translate_key(key_event->code)}; - auto &imgui_io{ImGui::GetIO()}; - imgui_io.AddKeyEvent(key, false); - switch(key) { // special cases for certain key events - case ImGuiKey_LeftCtrl: // additional events for modifier keys - case ImGuiKey_RightCtrl: - imgui_io.AddKeyEvent(ImGuiMod_Ctrl, false); - break; - case ImGuiKey_LeftShift: - case ImGuiKey_RightShift: - imgui_io.AddKeyEvent(ImGuiMod_Shift, false); - break; - case ImGuiKey_LeftAlt: - case ImGuiKey_RightAlt: - imgui_io.AddKeyEvent(ImGuiMod_Alt, false); - break; - case ImGuiKey_LeftSuper: - case ImGuiKey_RightSuper: - imgui_io.AddKeyEvent(ImGuiMod_Super, false); - break; - default: - break; - } - return false; // the event was not consumed - } - ); - emscripten_set_keypress_callback( - EMSCRIPTEN_EVENT_TARGET_WINDOW, // target - nullptr, // userData - false, // useCapture - [](int /*event_type*/, EmscriptenKeyboardEvent const *key_event, void */*data*/){ // callback, event_type == EMSCRIPTEN_EVENT_KEYPRESS - auto &imgui_io{ImGui::GetIO()}; - imgui_io.AddInputCharactersUTF8(key_event->key); - return imgui_io.WantCaptureKeyboard; // the event was consumed only if imgui wants to capture the keyboard - } - ); - emscripten_set_resize_callback( - EMSCRIPTEN_EVENT_TARGET_WINDOW, // target - nullptr, // userData - false, // useCapture - [](int /*event_type*/, EmscriptenUiEvent const *event, void */*data*/) { // event_type == EMSCRIPTEN_EVENT_RESIZE - auto &imgui_io{ImGui::GetIO()}; - imgui_io.DisplaySize.x = static_cast(event->windowInnerWidth); - imgui_io.DisplaySize.y = static_cast(event->windowInnerHeight); - return true; // the event was consumed - } - ); - emscripten_set_blur_callback( - EMSCRIPTEN_EVENT_TARGET_WINDOW, // target - nullptr, // userData - false, // useCapture - [](int /*event_type*/, EmscriptenFocusEvent const */*event*/, void */*data*/) { // event_type == EMSCRIPTEN_EVENT_BLUR - auto &imgui_io{ImGui::GetIO()}; - imgui_io.AddFocusEvent(false); - imgui_io.ClearInputKeys(); // clear pending input keys on focus gain - return true; // the event was consumed - } - ); - emscripten_set_focus_callback( - EMSCRIPTEN_EVENT_TARGET_WINDOW, // target - nullptr, // userData - false, // useCapture - [](int /*event_type*/, EmscriptenFocusEvent const */*event*/, void */*data*/) { // event_type == EMSCRIPTEN_EVENT_FOCUS - auto &imgui_io{ImGui::GetIO()}; - imgui_io.AddFocusEvent(true); - imgui_io.ClearInputKeys(); // clear pending input keys on focus loss - for example if you press tab to cycle to another part of the UI - return true; // the event was consumed - } - ); - emscripten_set_focusin_callback( - EMSCRIPTEN_EVENT_TARGET_WINDOW, // target - nullptr, // userData - false, // useCapture - [](int /*event_type*/, EmscriptenFocusEvent const */*event*/, void */*data*/) { // event_type == EMSCRIPTEN_EVENT_FOCUSIN - auto &imgui_io{ImGui::GetIO()}; - imgui_io.AddFocusEvent(true); - imgui_io.ClearInputKeys(); // clear pending input keys on focus gain - return true; // the event was consumed - } - ); - emscripten_set_focusout_callback( - EMSCRIPTEN_EVENT_TARGET_WINDOW, // target - nullptr, // userData - false, // useCapture - [](int /*event_type*/, EmscriptenFocusEvent const */*event*/, void */*data*/) { // event_type == EMSCRIPTEN_EVENT_FOCUSOUT - auto &imgui_io{ImGui::GetIO()}; - imgui_io.AddFocusEvent(false); - imgui_io.ClearInputKeys(); // clear pending input keys on focus loss - for example if you press tab to cycle to another part of the UI - return true; // the event was consumed - } - ); + emscripten_set_mousemove_callback( + EMSCRIPTEN_EVENT_TARGET_WINDOW, // target + nullptr, // userData + false, // useCapture + [](int /*event_type*/, EmscriptenMouseEvent const *mouse_event, void */*data*/){ // callback, event_type == EMSCRIPTEN_EVENT_MOUSEMOVE + ImGui::GetIO().AddMousePosEvent( + static_cast(mouse_event->clientX), + static_cast(mouse_event->clientY) + ); + return true; // the event was consumed + } + ); + emscripten_set_mousedown_callback( + EMSCRIPTEN_EVENT_TARGET_WINDOW, // target + nullptr, // userData + false, // useCapture + [](int /*event_type*/, EmscriptenMouseEvent const *mouse_event, void */*data*/){ // callback, event_type == EMSCRIPTEN_EVENT_MOUSEDOWN + ImGui::GetIO().AddMouseButtonEvent(translate_mousebutton(mouse_event->button), true); // translated button, down + return true; // the event was consumed + } + ); + emscripten_set_mouseup_callback( + EMSCRIPTEN_EVENT_TARGET_WINDOW, // target + nullptr, // userData + false, // useCapture + [](int /*event_type*/, EmscriptenMouseEvent const *mouse_event, void */*data*/){ // callback, event_type == EMSCRIPTEN_EVENT_MOUSEUP + ImGui::GetIO().AddMouseButtonEvent(translate_mousebutton(mouse_event->button), false); // translated button, up + return true; // the event was consumed + } + ); + emscripten_set_mouseenter_callback( + EMSCRIPTEN_EVENT_TARGET_DOCUMENT, // target - WINDOW doesn't produce mouseenter events + nullptr, // userData + false, // useCapture + [](int /*event_type*/, EmscriptenMouseEvent const *mouse_event, void */*data*/){ // callback, event_type == EMSCRIPTEN_EVENT_MOUSEENTER + ImGui::GetIO().AddMousePosEvent( + static_cast(mouse_event->clientX), + static_cast(mouse_event->clientY) + ); + return true; // the event was consumed + } + ); + emscripten_set_mouseleave_callback( + EMSCRIPTEN_EVENT_TARGET_DOCUMENT, // target - WINDOW doesn't produce mouseenter events + nullptr, // userData + false, // useCapture + [](int /*event_type*/, EmscriptenMouseEvent const */*mouse_event*/, void */*data*/){ // callback, event_type == EMSCRIPTEN_EVENT_MOUSELEAVE + auto &imgui_io{ImGui::GetIO()}; + imgui_io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); // cursor is not in the window + imgui_io.ClearInputKeys(); // clear pending input keys on mouse exit + return true; // the event was consumed + } + ); + emscripten_set_wheel_callback( + EMSCRIPTEN_EVENT_TARGET_WINDOW, // target + nullptr, // userData + false, // useCapture + [](int /*event_type*/, EmscriptenWheelEvent const *wheel_event, void */*data*/){ // callback, event_type == EMSCRIPTEN_EVENT_WHEEL + float scale{1.0f}; + switch(wheel_event->deltaMode) { + case DOM_DELTA_PIXEL: // scrolling in pixels + scale = 1.0f / 100.0f; + break; + case DOM_DELTA_LINE: // scrolling by lines + scale = 1.0f / 3.0f; + break; + case DOM_DELTA_PAGE: // scrolling by pages + scale = 80.0f; + break; + } + // TODO: make scrolling speeds configurable + ImGui::GetIO().AddMouseWheelEvent( + -static_cast(wheel_event->deltaX) * scale, + -static_cast(wheel_event->deltaY) * scale + ); + return false; // the event was not consumed + } + ); + emscripten_set_keydown_callback( + EMSCRIPTEN_EVENT_TARGET_WINDOW, // target + nullptr, // userData + false, // useCapture + [](int /*event_type*/, EmscriptenKeyboardEvent const *key_event, void */*data*/){ // callback, event_type == EMSCRIPTEN_EVENT_KEYDOWN + auto const key{translate_key(key_event->code)}; + auto &imgui_io{ImGui::GetIO()}; + imgui_io.AddKeyEvent(key, true); + switch(key) { // special cases for certain key events + case ImGuiKey_LeftCtrl: // additional events for modifier keys + case ImGuiKey_RightCtrl: + imgui_io.AddKeyEvent(ImGuiMod_Ctrl, true); + break; + case ImGuiKey_LeftShift: + case ImGuiKey_RightShift: + imgui_io.AddKeyEvent(ImGuiMod_Shift, true); + break; + case ImGuiKey_LeftAlt: + case ImGuiKey_RightAlt: + imgui_io.AddKeyEvent(ImGuiMod_Alt, true); + break; + case ImGuiKey_LeftSuper: + case ImGuiKey_RightSuper: + imgui_io.AddKeyEvent(ImGuiMod_Super, true); + break; + // TODO: case ImGuiKey_Menu: do we want to do anything with this? + case ImGuiKey_Tab: // consuming tab prevents the user tabbing to other parts of the browser interface outside the window content + return imgui_io.WantCaptureKeyboard; // the event was consumed only if imgui wants to capture the keyboard + case ImGuiKey_Enter: // consuming enter prevents the word "Enter" appearing in text input via the keypress callback + case ImGuiKey_Delete: // consuming enter prevents the word "Delete" appearing in text input via the keypress callback + return imgui_io.WantTextInput; // the event was consumed only if we're currently accepting text input + default: + break; + } + return false; // if no special handling, the event was not consumed + } + ); + emscripten_set_keyup_callback( + EMSCRIPTEN_EVENT_TARGET_WINDOW, // target + nullptr, // userData + false, // useCapture + [](int /*event_type*/, EmscriptenKeyboardEvent const *key_event, void */*data*/){ // callback, event_type == EMSCRIPTEN_EVENT_KEYUP + auto const key{translate_key(key_event->code)}; + auto &imgui_io{ImGui::GetIO()}; + imgui_io.AddKeyEvent(key, false); + switch(key) { // special cases for certain key events + case ImGuiKey_LeftCtrl: // additional events for modifier keys + case ImGuiKey_RightCtrl: + imgui_io.AddKeyEvent(ImGuiMod_Ctrl, false); + break; + case ImGuiKey_LeftShift: + case ImGuiKey_RightShift: + imgui_io.AddKeyEvent(ImGuiMod_Shift, false); + break; + case ImGuiKey_LeftAlt: + case ImGuiKey_RightAlt: + imgui_io.AddKeyEvent(ImGuiMod_Alt, false); + break; + case ImGuiKey_LeftSuper: + case ImGuiKey_RightSuper: + imgui_io.AddKeyEvent(ImGuiMod_Super, false); + break; + default: + break; + } + return false; // the event was not consumed + } + ); + emscripten_set_keypress_callback( + EMSCRIPTEN_EVENT_TARGET_WINDOW, // target + nullptr, // userData + false, // useCapture + [](int /*event_type*/, EmscriptenKeyboardEvent const *key_event, void */*data*/){ // callback, event_type == EMSCRIPTEN_EVENT_KEYPRESS + auto &imgui_io{ImGui::GetIO()}; + imgui_io.AddInputCharactersUTF8(key_event->key); + return imgui_io.WantCaptureKeyboard; // the event was consumed only if imgui wants to capture the keyboard + } + ); + emscripten_set_resize_callback( + EMSCRIPTEN_EVENT_TARGET_WINDOW, // target + nullptr, // userData + false, // useCapture + [](int /*event_type*/, EmscriptenUiEvent const *event, void */*data*/) { // event_type == EMSCRIPTEN_EVENT_RESIZE + auto &imgui_io{ImGui::GetIO()}; + imgui_io.DisplaySize.x = static_cast(event->windowInnerWidth); + imgui_io.DisplaySize.y = static_cast(event->windowInnerHeight); + return true; // the event was consumed + } + ); + emscripten_set_blur_callback( + EMSCRIPTEN_EVENT_TARGET_WINDOW, // target + nullptr, // userData + false, // useCapture + [](int /*event_type*/, EmscriptenFocusEvent const */*event*/, void */*data*/) { // event_type == EMSCRIPTEN_EVENT_BLUR + auto &imgui_io{ImGui::GetIO()}; + imgui_io.AddFocusEvent(false); + imgui_io.ClearInputKeys(); // clear pending input keys on focus gain + return true; // the event was consumed + } + ); + emscripten_set_focus_callback( + EMSCRIPTEN_EVENT_TARGET_WINDOW, // target + nullptr, // userData + false, // useCapture + [](int /*event_type*/, EmscriptenFocusEvent const */*event*/, void */*data*/) { // event_type == EMSCRIPTEN_EVENT_FOCUS + auto &imgui_io{ImGui::GetIO()}; + imgui_io.AddFocusEvent(true); + imgui_io.ClearInputKeys(); // clear pending input keys on focus loss - for example if you press tab to cycle to another part of the UI + return true; // the event was consumed + } + ); + emscripten_set_focusin_callback( + EMSCRIPTEN_EVENT_TARGET_WINDOW, // target + nullptr, // userData + false, // useCapture + [](int /*event_type*/, EmscriptenFocusEvent const */*event*/, void */*data*/) { // event_type == EMSCRIPTEN_EVENT_FOCUSIN + auto &imgui_io{ImGui::GetIO()}; + imgui_io.AddFocusEvent(true); + imgui_io.ClearInputKeys(); // clear pending input keys on focus gain + return true; // the event was consumed + } + ); + emscripten_set_focusout_callback( + EMSCRIPTEN_EVENT_TARGET_WINDOW, // target + nullptr, // userData + false, // useCapture + [](int /*event_type*/, EmscriptenFocusEvent const */*event*/, void */*data*/) { // event_type == EMSCRIPTEN_EVENT_FOCUSOUT + auto &imgui_io{ImGui::GetIO()}; + imgui_io.AddFocusEvent(false); + imgui_io.ClearInputKeys(); // clear pending input keys on focus loss - for example if you press tab to cycle to another part of the UI + return true; // the event was consumed + } + ); - // TODO: touch events + // TODO: touch events } void ImGui_ImplEmscripten_Shutdown() { - // Unset any callbacks set by Init - emscripten_set_mousemove_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); - emscripten_set_mousedown_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); - emscripten_set_mouseup_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); - emscripten_set_mouseenter_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, nullptr); - emscripten_set_mouseleave_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, nullptr); - emscripten_set_wheel_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); - emscripten_set_keydown_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); - emscripten_set_keyup_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); - emscripten_set_keypress_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); - emscripten_set_resize_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); - emscripten_set_focusin_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); - emscripten_set_focusout_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); - // TODO: touch events + // Unset any callbacks set by Init + emscripten_set_mousemove_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); + emscripten_set_mousedown_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); + emscripten_set_mouseup_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); + emscripten_set_mouseenter_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, nullptr); + emscripten_set_mouseleave_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, nullptr); + emscripten_set_wheel_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); + emscripten_set_keydown_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); + emscripten_set_keyup_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); + emscripten_set_keypress_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); + emscripten_set_resize_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); + emscripten_set_focusin_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); + emscripten_set_focusout_callback( EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, nullptr); + // TODO: touch events - auto &imgui_io{ImGui::GetIO()}; - imgui_io.BackendPlatformName = nullptr; - imgui_io.BackendPlatformUserData = nullptr; - imgui_io.BackendFlags &= ~ImGuiBackendFlags_HasMouseCursors; + auto &imgui_io{ImGui::GetIO()}; + imgui_io.BackendPlatformName = nullptr; + imgui_io.BackendPlatformUserData = nullptr; + imgui_io.BackendFlags &= ~ImGuiBackendFlags_HasMouseCursors; } void ImGui_ImplEmscripten_NewFrame() { - // Update any state that needs to be polled - update_cursor(); + // Update any state that needs to be polled + update_cursor(); } #endif // IMGUI_DISABLE diff --git a/backends/imgui_impl_emscripten.h b/backends/imgui_impl_emscripten.h index fb15af075..be2b7280d 100644 --- a/backends/imgui_impl_emscripten.h +++ b/backends/imgui_impl_emscripten.h @@ -36,7 +36,7 @@ #pragma once #ifndef __EMSCRIPTEN__ - #error The imgui_impl_emscripten backend reqiuires Emscripten. +#error The imgui_impl_emscripten backend reqiuires Emscripten. #endif // Initialise the Emscripten backend, setting input callbacks. This should be called after ImGui::CreateContext();