summaryrefslogtreecommitdiff
path: root/scene/gui
diff options
context:
space:
mode:
authorbruvzg <7645683+bruvzg@users.noreply.github.com>2017-08-07 14:09:56 +0300
committerbruvzg <7645683+bruvzg@users.noreply.github.com>2017-08-09 19:09:33 +0300
commit8aa86cb9bcb5db8a1909d4b1595e90dbffbff11e (patch)
tree22df47c5dc375ed1ef40e1da0eab29c7be4e704c /scene/gui
parentb5c6b0cf1c3d644321ed134dbb26e111d6dbd43f (diff)
Implement NSTextInputClient protocol for IME
Diffstat (limited to 'scene/gui')
-rw-r--r--scene/gui/line_edit.cpp82
-rw-r--r--scene/gui/line_edit.h3
-rw-r--r--scene/gui/text_edit.cpp99
-rw-r--r--scene/gui/text_edit.h5
4 files changed, 167 insertions, 22 deletions
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 8556ce5db1..aa4651df24 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -641,6 +641,35 @@ void LineEdit::_notification(int p_what) {
if (char_ofs >= t.length())
break;
+ if (char_ofs == cursor_pos) {
+ if (ime_text.length() > 0) {
+ int ofs = 0;
+ while (true) {
+ if (ofs >= ime_text.length())
+ break;
+
+ CharType cchar = (pass && !text.empty()) ? '*' : ime_text[ofs];
+ CharType next = (pass && !text.empty()) ? '*' : ime_text[ofs + 1];
+ int im_char_width = font->get_char_size(cchar, next).width;
+
+ if ((x_ofs + im_char_width) > ofs_max)
+ break;
+
+ bool selected = ofs >= ime_selection.x && ofs < ime_selection.x + ime_selection.y;
+ if (selected) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs + caret_height), Size2(im_char_width, 3)), font_color);
+ } else {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs + caret_height), Size2(im_char_width, 1)), font_color);
+ }
+
+ font->draw_char(ci, Point2(x_ofs, y_ofs + font_ascent), cchar, next, font_color);
+
+ x_ofs += im_char_width;
+ ofs++;
+ }
+ }
+ }
+
CharType cchar = (pass && !text.empty()) ? '*' : t[char_ofs];
CharType next = (pass && !text.empty()) ? '*' : t[char_ofs + 1];
int char_width = font->get_char_size(cchar, next).width;
@@ -657,24 +686,54 @@ void LineEdit::_notification(int p_what) {
font->draw_char(ci, Point2(x_ofs, y_ofs + font_ascent), cchar, next, selected ? font_color_selected : font_color);
if (char_ofs == cursor_pos && draw_caret) {
- VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(
- Point2(x_ofs, y_ofs), Size2(1, caret_height)),
- cursor_color);
+ if (ime_text.length() == 0) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(1, caret_height)), cursor_color);
+ }
}
x_ofs += char_width;
char_ofs++;
}
+ if (char_ofs == cursor_pos) {
+ if (ime_text.length() > 0) {
+ int ofs = 0;
+ while (true) {
+ if (ofs >= ime_text.length())
+ break;
+
+ CharType cchar = (pass && !text.empty()) ? '*' : ime_text[ofs];
+ CharType next = (pass && !text.empty()) ? '*' : ime_text[ofs + 1];
+ int im_char_width = font->get_char_size(cchar, next).width;
+
+ if ((x_ofs + im_char_width) > ofs_max)
+ break;
+
+ bool selected = ofs >= ime_selection.x && ofs < ime_selection.x + ime_selection.y;
+ if (selected) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs + caret_height), Size2(im_char_width, 3)), font_color);
+ } else {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs + caret_height), Size2(im_char_width, 1)), font_color);
+ }
+
+ font->draw_char(ci, Point2(x_ofs, y_ofs + font_ascent), cchar, next, font_color);
+
+ x_ofs += im_char_width;
+ ofs++;
+ }
+ }
+ }
+
if (char_ofs == cursor_pos && draw_caret) { //may be at the end
- VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(
- Point2(x_ofs, y_ofs), Size2(1, caret_height)),
- cursor_color);
+ if (ime_text.length() == 0) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(1, caret_height)), cursor_color);
+ }
}
if (has_focus()) {
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);
}
} break;
case NOTIFICATION_FOCUS_ENTER: {
@@ -685,6 +744,7 @@ void LineEdit::_notification(int p_what) {
Point2 cursor_pos = Point2(get_cursor_pos(), 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);
if (OS::get_singleton()->has_virtual_keyboard())
OS::get_singleton()->show_virtual_keyboard(text, get_global_rect());
@@ -693,6 +753,9 @@ void LineEdit::_notification(int p_what) {
case NOTIFICATION_FOCUS_EXIT: {
OS::get_singleton()->set_ime_position(Point2());
+ OS::get_singleton()->set_ime_intermediate_text_callback(NULL, NULL);
+ ime_text = "";
+ ime_selection = Point2();
if (OS::get_singleton()->has_virtual_keyboard())
OS::get_singleton()->hide_virtual_keyboard();
@@ -1231,6 +1294,13 @@ bool LineEdit::get_expand_to_text_length() const {
return expand_to_text_length;
}
+void LineEdit::_ime_text_callback(void *p_self, String p_text, Point2 p_selection) {
+ LineEdit *self = (LineEdit *)p_self;
+ self->ime_text = p_text;
+ self->ime_selection = p_selection;
+ self->update();
+}
+
void LineEdit::_text_changed() {
if (expand_to_text_length)
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index 1167cfb6d0..73c5a46937 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -70,6 +70,8 @@ private:
String text;
String placeholder;
float placeholder_alpha;
+ String ime_text;
+ Point2 ime_selection;
PopupMenu *menu;
@@ -92,6 +94,7 @@ private:
Timer *caret_blink_timer;
+ static void _ime_text_callback(void *p_self, String p_text, Point2 p_selection);
void _text_changed();
bool expand_to_text_length;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index a7c31361e8..acc8639350 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -987,13 +987,41 @@ void TextEdit::_notification(int p_what) {
}
int caret_w = (str[j] == '\t') ? cache.font->get_char_size(' ').width : char_w;
- if (draw_caret) {
- if (insert_mode) {
- int caret_h = (block_caret) ? 4 : 1;
- VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, caret_h)), cache.caret_color);
- } else {
- caret_w = (block_caret) ? caret_w : 1;
- VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, get_row_height())), cache.caret_color);
+ if (ime_text.length() > 0) {
+ int ofs = 0;
+ while (true) {
+ if (ofs >= ime_text.length())
+ break;
+
+ CharType cchar = ime_text[ofs];
+ CharType next = ime_text[ofs + 1];
+ int im_char_width = cache.font->get_char_size(cchar, next).width;
+
+ if ((char_ofs + char_margin + im_char_width) >= xmargin_end)
+ break;
+
+ bool selected = ofs >= ime_selection.x && ofs < ime_selection.x + ime_selection.y;
+ if (selected) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_ofs + char_margin, ofs_y + get_row_height()), Size2(im_char_width, 3)), color);
+ } else {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_ofs + char_margin, ofs_y + get_row_height()), Size2(im_char_width, 1)), color);
+ }
+
+ cache.font->draw_char(ci, Point2(char_ofs + char_margin, ofs_y + ascent), cchar, next, color);
+
+ char_ofs += im_char_width;
+ ofs++;
+ }
+ }
+ if (ime_text.length() == 0) {
+ if (draw_caret) {
+ if (insert_mode) {
+ int caret_h = (block_caret) ? 4 : 1;
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, caret_h)), cache.caret_color);
+ } else {
+ caret_w = (block_caret) ? caret_w : 1;
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, get_row_height())), cache.caret_color);
+ }
}
}
}
@@ -1024,16 +1052,43 @@ void TextEdit::_notification(int p_what) {
if (insert_mode) {
cursor_pos.y += (get_row_height() - 3);
}
+ if (ime_text.length() > 0) {
+ int ofs = 0;
+ while (true) {
+ if (ofs >= ime_text.length())
+ break;
- if (draw_caret) {
- if (insert_mode) {
- int char_w = cache.font->get_char_size(' ').width;
- int caret_h = (block_caret) ? 4 : 1;
- VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(char_w, caret_h)), cache.caret_color);
- } else {
- int char_w = cache.font->get_char_size(' ').width;
- int caret_w = (block_caret) ? char_w : 1;
- VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, get_row_height())), cache.caret_color);
+ CharType cchar = ime_text[ofs];
+ CharType next = ime_text[ofs + 1];
+ int im_char_width = cache.font->get_char_size(cchar, next).width;
+
+ if ((char_ofs + char_margin + im_char_width) >= xmargin_end)
+ break;
+
+ bool selected = ofs >= ime_selection.x && ofs < ime_selection.x + ime_selection.y;
+ if (selected) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_ofs + char_margin, ofs_y + get_row_height()), Size2(im_char_width, 3)), color);
+ } else {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_ofs + char_margin, ofs_y + get_row_height()), Size2(im_char_width, 1)), color);
+ }
+
+ cache.font->draw_char(ci, Point2(char_ofs + char_margin, ofs_y + ascent), cchar, next, color);
+
+ char_ofs += im_char_width;
+ ofs++;
+ }
+ }
+ if (ime_text.length() == 0) {
+ if (draw_caret) {
+ if (insert_mode) {
+ int char_w = cache.font->get_char_size(' ').width;
+ int caret_h = (block_caret) ? 4 : 1;
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(char_w, caret_h)), cache.caret_color);
+ } else {
+ int char_w = cache.font->get_char_size(' ').width;
+ int caret_w = (block_caret) ? char_w : 1;
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, get_row_height())), cache.caret_color);
+ }
}
}
}
@@ -1197,6 +1252,7 @@ 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()));
+ OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this);
}
} break;
case NOTIFICATION_FOCUS_ENTER: {
@@ -1207,6 +1263,7 @@ void TextEdit::_notification(int p_what) {
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);
if (OS::get_singleton()->has_virtual_keyboard())
OS::get_singleton()->show_virtual_keyboard(get_text(), get_global_rect());
@@ -1218,6 +1275,9 @@ void TextEdit::_notification(int p_what) {
case NOTIFICATION_FOCUS_EXIT: {
OS::get_singleton()->set_ime_position(Point2());
+ OS::get_singleton()->set_ime_intermediate_text_callback(NULL, NULL);
+ ime_text = "";
+ ime_selection = Point2();
if (OS::get_singleton()->has_virtual_keyboard())
OS::get_singleton()->hide_virtual_keyboard();
@@ -1228,6 +1288,13 @@ void TextEdit::_notification(int p_what) {
}
}
+void TextEdit::_ime_text_callback(void *p_self, String p_text, Point2 p_selection) {
+ TextEdit *self = (TextEdit *)p_self;
+ self->ime_text = p_text;
+ self->ime_selection = p_selection;
+ self->update();
+}
+
void TextEdit::_consume_pair_symbol(CharType ch) {
int cursor_position_to_move = cursor_get_column() + 1;
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index f8f60d2b03..afb4b1c547 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -184,6 +184,9 @@ class TextEdit : public Control {
bool chain_backward;
};
+ String ime_text;
+ Point2 ime_selection;
+
TextOperation current_op;
List<TextOperation> undo_stack;
@@ -299,6 +302,8 @@ class TextEdit : public Control {
void _scroll_lines_up();
void _scroll_lines_down();
+ static void _ime_text_callback(void *p_self, String p_text, Point2 p_selection);
+
//void mouse_motion(const Point& p_pos, const Point& p_rel, int p_button_mask);
Size2 get_minimum_size() const;