Browse Source

Merge pull request #19509 from SaracenOne/ime

IME context detection.
Rémi Verschelde 7 years ago
parent
commit
d6d8237a5a

+ 5 - 0
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);

+ 1 - 0
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);

+ 1 - 0
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) {}
 

+ 2 - 0
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);
 

+ 6 - 1
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;

+ 27 - 2
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);
 }

+ 5 - 0
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();

+ 21 - 1
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;
 

+ 5 - 0
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;

+ 3 - 0
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();
 

+ 3 - 0
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();