Browse Source

Merge pull request #9366 from GodotExplorer/pr-ime-position-flow-cursor

IME window follow the input cursor.
Rémi Verschelde 8 years ago
parent
commit
a5bb77d523

+ 7 - 0
core/bind/core_bind.cpp

@@ -300,6 +300,11 @@ bool _OS::get_borderless_window() const {
 	return OS::get_singleton()->get_borderless_window();
 	return OS::get_singleton()->get_borderless_window();
 }
 }
 
 
+void _OS::set_ime_position(const Point2 &p_pos) {
+
+	return OS::get_singleton()->set_ime_position(p_pos);
+}
+
 void _OS::set_use_file_access_save_and_swap(bool p_enable) {
 void _OS::set_use_file_access_save_and_swap(bool p_enable) {
 
 
 	FileAccess::set_backup_save(p_enable);
 	FileAccess::set_backup_save(p_enable);
@@ -993,6 +998,8 @@ void _OS::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_borderless_window", "borderless"), &_OS::set_borderless_window);
 	ClassDB::bind_method(D_METHOD("set_borderless_window", "borderless"), &_OS::set_borderless_window);
 	ClassDB::bind_method(D_METHOD("get_borderless_window"), &_OS::get_borderless_window);
 	ClassDB::bind_method(D_METHOD("get_borderless_window"), &_OS::get_borderless_window);
 
 
+	ClassDB::bind_method(D_METHOD("set_ime_position"), &_OS::set_ime_position);
+
 	ClassDB::bind_method(D_METHOD("set_screen_orientation", "orientation"), &_OS::set_screen_orientation);
 	ClassDB::bind_method(D_METHOD("set_screen_orientation", "orientation"), &_OS::set_screen_orientation);
 	ClassDB::bind_method(D_METHOD("get_screen_orientation"), &_OS::get_screen_orientation);
 	ClassDB::bind_method(D_METHOD("get_screen_orientation"), &_OS::get_screen_orientation);
 
 

+ 2 - 0
core/bind/core_bind.h

@@ -158,6 +158,8 @@ public:
 	virtual void set_borderless_window(bool p_borderless);
 	virtual void set_borderless_window(bool p_borderless);
 	virtual bool get_borderless_window() const;
 	virtual bool get_borderless_window() const;
 
 
+	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);
 	Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track);
 	bool native_video_is_playing();
 	bool native_video_is_playing();
 	void native_video_pause();
 	void native_video_pause();

+ 2 - 0
core/os/os.h

@@ -179,6 +179,8 @@ public:
 	virtual void set_borderless_window(int p_borderless) {}
 	virtual void set_borderless_window(int p_borderless) {}
 	virtual bool get_borderless_window() { return 0; }
 	virtual bool get_borderless_window() { return 0; }
 
 
+	virtual void set_ime_position(const Point2 &p_pos) {}
+
 	virtual Error open_dynamic_library(const String p_path, void *&p_library_handle) { return ERR_UNAVAILABLE; };
 	virtual Error open_dynamic_library(const String p_path, void *&p_library_handle) { return ERR_UNAVAILABLE; };
 	virtual Error close_dynamic_library(void *p_library_handle) { return ERR_UNAVAILABLE; };
 	virtual Error close_dynamic_library(void *p_library_handle) { return ERR_UNAVAILABLE; };
 	virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle) { return ERR_UNAVAILABLE; };
 	virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle) { return ERR_UNAVAILABLE; };

+ 8 - 13
platform/x11/os_x11.cpp

@@ -508,22 +508,17 @@ void OS_X11::xim_destroy_callback(::XIM im, ::XPointer client_data,
 	os->xic = NULL;
 	os->xic = NULL;
 }
 }
 
 
-void OS_X11::set_ime_position(short x, short y) {
+void OS_X11::set_ime_position(const Point2 &p_pos) {
 
 
-	if (!xic) {
+	if (!xic)
 		return;
 		return;
-	}
+
 	::XPoint spot;
 	::XPoint spot;
-	spot.x = x;
-	spot.y = y;
-	XVaNestedList preedit_attr = XVaCreateNestedList(0,
-			XNSpotLocation, &spot,
-			NULL);
-	XSetICValues(xic,
-			XNPreeditAttributes, preedit_attr,
-			NULL);
+	spot.x = short(p_pos.x);
+	spot.y = short(p_pos.y);
+	XVaNestedList preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL);
+	XSetICValues(xic, XNPreeditAttributes, preedit_attr, NULL);
 	XFree(preedit_attr);
 	XFree(preedit_attr);
-	return;
 }
 }
 
 
 void OS_X11::finalize() {
 void OS_X11::finalize() {
@@ -1489,7 +1484,7 @@ void OS_X11::process_xevents() {
 			case ConfigureNotify:
 			case ConfigureNotify:
 				if (xic) {
 				if (xic) {
 					//  Not portable.
 					//  Not portable.
-					set_ime_position(0, 1);
+					set_ime_position(Point2(0, 1));
 				}
 				}
 				/* call resizeGLScene only if our window-size changed */
 				/* call resizeGLScene only if our window-size changed */
 
 

+ 1 - 1
platform/x11/os_x11.h

@@ -115,7 +115,6 @@ class OS_X11 : public OS_Unix {
 	::XIMStyle xim_style;
 	::XIMStyle xim_style;
 	static void xim_destroy_callback(::XIM im, ::XPointer client_data,
 	static void xim_destroy_callback(::XIM im, ::XPointer client_data,
 			::XPointer call_data);
 			::XPointer call_data);
-	void set_ime_position(short x, short y);
 
 
 	Point2i last_mouse_pos;
 	Point2i last_mouse_pos;
 	bool last_mouse_pos_valid;
 	bool last_mouse_pos_valid;
@@ -253,6 +252,7 @@ public:
 
 
 	virtual void set_borderless_window(int p_borderless);
 	virtual void set_borderless_window(int p_borderless);
 	virtual bool get_borderless_window();
 	virtual bool get_borderless_window();
+	virtual void set_ime_position(const Point2 &p_pos);
 
 
 	virtual void move_window_to_foreground();
 	virtual void move_window_to_foreground();
 	virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
 	virtual void alert(const String &p_alert, const String &p_title = "ALERT!");

+ 10 - 0
scene/gui/line_edit.cpp

@@ -660,6 +660,11 @@ void LineEdit::_notification(int p_what) {
 																				Point2(x_ofs, y_ofs), Size2(1, caret_height)),
 																				Point2(x_ofs, y_ofs), Size2(1, caret_height)),
 						cursor_color);
 						cursor_color);
 			}
 			}
+
+			if (has_focus()) {
+
+				OS::get_singleton()->set_ime_position(get_global_position() + Point2(x_ofs, y_ofs + caret_height));
+			}
 		} break;
 		} break;
 		case NOTIFICATION_FOCUS_ENTER: {
 		case NOTIFICATION_FOCUS_ENTER: {
 
 
@@ -667,12 +672,17 @@ void LineEdit::_notification(int p_what) {
 				draw_caret = true;
 				draw_caret = true;
 			}
 			}
 
 
+			Point2 cursor_pos = Point2(get_cursor_pos(), 1) * get_minimum_size().height;
+			OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos);
+
 			if (OS::get_singleton()->has_virtual_keyboard())
 			if (OS::get_singleton()->has_virtual_keyboard())
 				OS::get_singleton()->show_virtual_keyboard(text, get_global_rect());
 				OS::get_singleton()->show_virtual_keyboard(text, get_global_rect());
 
 
 		} break;
 		} break;
 		case NOTIFICATION_FOCUS_EXIT: {
 		case NOTIFICATION_FOCUS_EXIT: {
 
 
+			OS::get_singleton()->set_ime_position(Point2());
+
 			if (OS::get_singleton()->has_virtual_keyboard())
 			if (OS::get_singleton()->has_virtual_keyboard())
 				OS::get_singleton()->hide_virtual_keyboard();
 				OS::get_singleton()->hide_virtual_keyboard();
 
 

+ 9 - 0
scene/gui/text_edit.cpp

@@ -1191,12 +1191,19 @@ void TextEdit::_notification(int p_what) {
 				}
 				}
 			}
 			}
 
 
+			if (has_focus()) {
+				OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos + Point2(0, get_row_height()));
+			}
 		} break;
 		} break;
 		case NOTIFICATION_FOCUS_ENTER: {
 		case NOTIFICATION_FOCUS_ENTER: {
 
 
 			if (!caret_blink_enabled) {
 			if (!caret_blink_enabled) {
 				draw_caret = true;
 				draw_caret = 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);
+
 			if (OS::get_singleton()->has_virtual_keyboard())
 			if (OS::get_singleton()->has_virtual_keyboard())
 				OS::get_singleton()->show_virtual_keyboard(get_text(), get_global_rect());
 				OS::get_singleton()->show_virtual_keyboard(get_text(), get_global_rect());
 			if (raised_from_completion) {
 			if (raised_from_completion) {
@@ -1206,6 +1213,8 @@ void TextEdit::_notification(int p_what) {
 		} break;
 		} break;
 		case NOTIFICATION_FOCUS_EXIT: {
 		case NOTIFICATION_FOCUS_EXIT: {
 
 
+			OS::get_singleton()->set_ime_position(Point2());
+
 			if (OS::get_singleton()->has_virtual_keyboard())
 			if (OS::get_singleton()->has_virtual_keyboard())
 				OS::get_singleton()->hide_virtual_keyboard();
 				OS::get_singleton()->hide_virtual_keyboard();
 			if (raised_from_completion) {
 			if (raised_from_completion) {