diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index b7f20588f26..372cff44129 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -348,6 +348,11 @@ bool _OS::get_borderless_window() const { return OS::get_singleton()->get_borderless_window(); } +void _OS::set_ime_active(const bool p_active) { + + return OS::get_singleton()->set_ime_active(p_active); +} + void _OS::set_ime_position(const Point2 &p_pos) { return OS::get_singleton()->set_ime_position(p_pos); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 1de5e43b276..560d9e98734 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -183,6 +183,7 @@ public: virtual bool get_window_per_pixel_transparency_enabled() const; virtual void set_window_per_pixel_transparency_enabled(bool p_enabled); + virtual void set_ime_active(const bool p_active); virtual void set_ime_position(const Point2 &p_pos); Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track); diff --git a/core/os/os.h b/core/os/os.h index b36f94060c5..adf01a90e7a 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -232,6 +232,7 @@ public: virtual Size2 get_layered_buffer_size() { return Size2(0, 0); } virtual void swap_layered_buffer() {} + virtual void set_ime_active(const bool p_active) {} virtual void set_ime_position(const Point2 &p_pos) {} virtual void set_ime_intermediate_text_callback(ImeCallback p_callback, void *p_inp) {} diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index 2b2d21553bb..7bd5b16f36f 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -117,6 +117,7 @@ public: String open_with_filename; Point2 im_position; + bool im_active; ImeCallback im_callback; void *im_target; @@ -233,6 +234,7 @@ public: virtual bool get_window_per_pixel_transparency_enabled() const; virtual void set_window_per_pixel_transparency_enabled(bool p_enabled); + virtual void set_ime_active(const bool p_active); virtual void set_ime_position(const Point2 &p_pos); virtual void set_ime_intermediate_text_callback(ImeCallback p_callback, void *p_inp); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index a49ae1a2f38..4ece1e0325c 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -959,7 +959,7 @@ static int remapKey(unsigned int key) { push_to_key_event_buffer(ke); } - if ((OS_OSX::singleton->im_position.x != 0) && (OS_OSX::singleton->im_position.y != 0)) + if (OS_OSX::singleton->im_active == true) [self interpretKeyEvents:[NSArray arrayWithObject:event]]; } @@ -1129,6 +1129,10 @@ String OS_OSX::get_unique_id() const { return serial_number; } +void OS_OSX::set_ime_active(const bool p_active) { + im_active = p_active; +} + void OS_OSX::set_ime_position(const Point2 &p_pos) { im_position = p_pos; } @@ -2542,6 +2546,7 @@ OS_OSX::OS_OSX() { mouse_mode = OS::MOUSE_MODE_VISIBLE; main_loop = NULL; singleton = this; + im_active = false; im_position = Point2(); im_callback = NULL; im_target = NULL; diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 3e0c4a7c0c1..ca6c793d5d9 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1181,6 +1181,15 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int if (p_desired.layered_splash) { set_window_per_pixel_transparency_enabled(true); } + + // IME + im_himc = ImmGetContext(hWnd); + ImmReleaseContext(hWnd, im_himc); + + im_position = Vector2(); + + set_ime_active(false); + return OK; } @@ -2659,13 +2668,29 @@ String OS_Windows::get_unique_id() const { return String(HwProfInfo.szHwProfileGuid); } +void OS_Windows::set_ime_active(const bool p_active) { + + if (p_active) { + ImmAssociateContext(hWnd, im_himc); + + set_ime_position(im_position); + } else { + ImmAssociateContext(hWnd, (HIMC)0); + } +} + void OS_Windows::set_ime_position(const Point2 &p_pos) { + im_position = p_pos; + HIMC himc = ImmGetContext(hWnd); + if (himc == (HIMC)0) + return; + COMPOSITIONFORM cps; cps.dwStyle = CFS_FORCE_POSITION; - cps.ptCurrentPos.x = p_pos.x; - cps.ptCurrentPos.y = p_pos.y; + cps.ptCurrentPos.x = im_position.x; + cps.ptCurrentPos.y = im_position.y; ImmSetCompositionWindow(himc, &cps); ImmReleaseContext(hWnd, himc); } diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 81849497eed..19af63bae0f 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -111,6 +111,10 @@ class OS_Windows : public OS { WNDPROC user_proc; + // IME + HIMC im_himc; + Vector2 im_position; + MouseMode mouse_mode; bool alt_mem; bool gr_mem; @@ -282,6 +286,7 @@ public: virtual String get_unique_id() const; + virtual void set_ime_active(const bool p_active); virtual void set_ime_position(const Point2 &p_pos); virtual void release_rendering_thread(); diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 1fa69933061..d7f042b4fe3 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -391,6 +391,9 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a wm_delete = XInternAtom(x11_display, "WM_DELETE_WINDOW", true); XSetWMProtocols(x11_display, x11_window, &wm_delete, 1); + im_active = false; + im_position = Vector2(); + if (xim && xim_style) { xic = XCreateIC(xim, XNInputStyle, xim_style, XNClientWindow, x11_window, XNFocusWindow, x11_window, (char *)NULL); @@ -400,7 +403,7 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a xic = NULL; } if (xic) { - XSetICFocus(xic); + XUnsetICFocus(xic); } else { WARN_PRINT("XCreateIC couldn't create xic"); } @@ -541,8 +544,25 @@ void OS_X11::xim_destroy_callback(::XIM im, ::XPointer client_data, os->xic = NULL; } +void OS_X11::set_ime_active(const bool p_active) { + + im_active = p_active; + + if (!xic) + return; + + if (p_active) { + XSetICFocus(xic); + set_ime_position(im_position); + } else { + XUnsetICFocus(xic); + } +} + void OS_X11::set_ime_position(const Point2 &p_pos) { + im_position = p_pos; + if (!xic) return; diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index 09ed9588c40..8cab23fe63f 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -116,6 +116,10 @@ class OS_X11 : public OS_Unix { static void xim_destroy_callback(::XIM im, ::XPointer client_data, ::XPointer call_data); + // IME + bool im_active; + Vector2 im_position; + Point2i last_mouse_pos; bool last_mouse_pos_valid; Point2i last_click_pos; @@ -269,6 +273,7 @@ public: virtual bool get_window_per_pixel_transparency_enabled() const; virtual void set_window_per_pixel_transparency_enabled(bool p_enabled); + virtual void set_ime_active(const bool p_active); virtual void set_ime_position(const Point2 &p_pos); virtual String get_unique_id() const; diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index f1f1a66b47b..71cb01d2eed 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -756,6 +756,7 @@ void LineEdit::_notification(int p_what) { if (has_focus()) { + OS::get_singleton()->set_ime_active(true); OS::get_singleton()->set_ime_position(get_global_position() + Point2(x_ofs, y_ofs + caret_height)); OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this); } @@ -766,6 +767,7 @@ void LineEdit::_notification(int p_what) { draw_caret = true; } + OS::get_singleton()->set_ime_active(true); Point2 cursor_pos = Point2(get_cursor_position(), 1) * get_minimum_size().height; OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos); OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this); @@ -778,6 +780,7 @@ void LineEdit::_notification(int p_what) { OS::get_singleton()->set_ime_position(Point2()); OS::get_singleton()->set_ime_intermediate_text_callback(NULL, NULL); + OS::get_singleton()->set_ime_active(false); ime_text = ""; ime_selection = Point2(); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 1c6ac50b1c8..215ba0271f7 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1388,6 +1388,7 @@ void TextEdit::_notification(int p_what) { } if (has_focus()) { + OS::get_singleton()->set_ime_active(true); OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos + Point2(0, get_row_height())); OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this); } @@ -1399,6 +1400,7 @@ void TextEdit::_notification(int p_what) { draw_caret = true; } + OS::get_singleton()->set_ime_active(true); Point2 cursor_pos = Point2(cursor_get_column(), cursor_get_line()) * get_row_height(); OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos); OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this); @@ -1413,6 +1415,7 @@ void TextEdit::_notification(int p_what) { OS::get_singleton()->set_ime_position(Point2()); OS::get_singleton()->set_ime_intermediate_text_callback(NULL, NULL); + OS::get_singleton()->set_ime_active(false); ime_text = ""; ime_selection = Point2();