Mercurial > hg > openttd
changeset 20706:79930f9362c3 draft
-Change: [Win32] Position the IME composition window at the caret position.
author | Michael Lutz <michi@icosahedron.de> |
---|---|
date | Sun, 07 Apr 2013 17:10:38 +0200 |
parents | 3b9077f142b8 |
children | 59932ff02821 |
files | src/console_gui.cpp src/misc_gui.cpp src/querystring_gui.h src/video/win32_v.cpp src/window.cpp src/window_func.h src/window_gui.h |
diffstat | 7 files changed, 88 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/console_gui.cpp +++ b/src/console_gui.cpp @@ -317,6 +317,14 @@ } } + virtual Point GetCaretPosition() const + { + int delta = min(this->width - this->line_offset - _iconsole_cmdline.pixels - ICON_RIGHT_BORDERWIDTH, 0); + Point pt = {this->line_offset + delta + _iconsole_cmdline.caretxoffs, this->height - this->line_height}; + + return pt; + } + virtual void OnMouseWheel(int wheel) { this->Scroll(-wheel);
--- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -785,6 +785,34 @@ _cur_dpi = old_dpi; } +/** + * Get the current caret position. + * @param w Window the edit box is in. + * @param wid Widget index. + * @return Top-left location of the caret, relative to the window. + */ +Point QueryString::GetCaretPosition(const Window *w, int wid) const +{ + const NWidgetLeaf *wi = w->GetWidget<NWidgetLeaf>(wid); + + assert((wi->type & WWT_MASK) == WWT_EDITBOX); + + bool rtl = _current_text_dir == TD_RTL; + Dimension sprite_size = GetSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT); + int clearbtn_width = sprite_size.width + WD_IMGBTN_LEFT + WD_IMGBTN_RIGHT; + + int left = wi->pos_x + (rtl ? clearbtn_width : 0); + int right = wi->pos_x + (rtl ? wi->current_x : wi->current_x - clearbtn_width) - 1; + + /* Clamp caret position to be inside out current width. */ + const Textbuf *tb = &this->text; + int delta = min(0, (right - left) - tb->pixels - 10); + if (tb->caretxoffs + delta < 0) delta = -tb->caretxoffs; + + Point pt = {left + WD_FRAMERECT_LEFT + tb->caretxoffs + delta, wi->pos_y + WD_FRAMERECT_TOP}; + return pt; +} + void QueryString::ClickEditBox(Window *w, Point pt, int wid, int click_count, bool focus_changed) { const NWidgetLeaf *wi = w->GetWidget<NWidgetLeaf>(wid);
--- a/src/querystring_gui.h +++ b/src/querystring_gui.h @@ -53,6 +53,8 @@ void DrawEditBox(const Window *w, int wid) const; void ClickEditBox(Window *w, Point pt, int wid, int click_count, bool focus_changed); void HandleEditBox(Window *w, int wid); + + Point GetCaretPosition(const Window *w, int wid) const; }; void ShowOnScreenKeyboard(Window *parent, int button);
--- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -21,6 +21,7 @@ #include "../texteff.hpp" #include "../thread/thread.h" #include "../progress.h" +#include "../window_gui.h" #include "../window_func.h" #include "win32_v.h" #include <windows.h> @@ -494,6 +495,28 @@ } #if !defined(WINCE) || _WIN32_WCE >= 0x400 +/** Set position of the composition window to the caret position. */ +static void SetCompositionPos(HWND hwnd) +{ + HIMC hIMC = ImmGetContext(hwnd); + if (hIMC != NULL) { + COMPOSITIONFORM cf; + cf.dwStyle = CFS_POINT; + + if (EditBoxInGlobalFocus()) { + /* Get caret position. */ + Point pt = _focused_window->GetCaretPosition(); + cf.ptCurrentPos.x = _focused_window->left + pt.x; + cf.ptCurrentPos.y = _focused_window->top + pt.y; + } else { + cf.ptCurrentPos.x = 0; + cf.ptCurrentPos.y = 0; + } + ImmSetCompositionWindow(hIMC, &cf); + } + ImmReleaseContext(hwnd, hIMC); +} + /** Handle WM_IME_COMPOSITION messages. */ static LRESULT HandleIMEComposition(HWND hwnd, WPARAM wParam, LPARAM lParam) { @@ -509,6 +532,7 @@ /* Transmit text to windowing system. */ if (len > 0) HandleTextInput(FS2OTTD(str)); + SetCompositionPos(hwnd); /* Don't pass the result string on to the default window proc. */ lParam &= ~(GCS_RESULTSTR | GCS_RESULTCLAUSE | GCS_RESULTREADCLAUSE | GCS_RESULTREADSTR); @@ -529,6 +553,7 @@ #else +static void SetCompositionPos(HWND hwnd) {} static void CancelIMEComposition(HWND hwnd) {} #endif /* !defined(WINCE) || _WIN32_WCE >= 0x400 */ @@ -542,6 +567,7 @@ switch (msg) { case WM_CREATE: SetTimer(hwnd, TID_POLLMOUSE, MOUSE_POLL_DELAY, (TIMERPROC)TrackMouseTimerProc); + SetCompositionPos(hwnd); break; case WM_ENTERSIZEMOVE: @@ -668,6 +694,10 @@ } #if !defined(WINCE) || _WIN32_WCE >= 0x400 + case WM_IME_STARTCOMPOSITION: + SetCompositionPos(hwnd); + break; + case WM_IME_COMPOSITION: return HandleIMEComposition(hwnd, wParam, lParam); @@ -855,6 +885,7 @@ case WM_SETFOCUS: _wnd.has_focus = true; + SetCompositionPos(hwnd); break; case WM_KILLFOCUS: @@ -1214,4 +1245,5 @@ void VideoDriver_Win32::EditBoxLostFocus() { CancelIMEComposition(_wnd.main_wnd); + SetCompositionPos(_wnd.main_wnd); }
--- a/src/window.cpp +++ b/src/window.cpp @@ -323,6 +323,20 @@ return query != this->querystrings.End() ? query->second : NULL; } +/** + * Get the current caret position if an edit box has the focus. + * @return Top-left location of the caret, relative to the window. + */ +/* virtual */ Point Window::GetCaretPosition() const +{ + if (this->nested_focus != NULL && this->nested_focus->type == WWT_EDITBOX) { + return this->GetQueryString(this->nested_focus->index)->GetCaretPosition(this, this->nested_focus->index); + } + + Point pt = {0, 0}; + return pt; +} + /** * Set the window that has the focus
--- a/src/window_func.h +++ b/src/window_func.h @@ -14,6 +14,7 @@ #include "window_type.h" #include "company_type.h" +#include "core/geometry_type.hpp" Window *FindWindowById(WindowClass cls, WindowNumber number); Window *FindWindowByClass(WindowClass cls); @@ -53,5 +54,6 @@ void DeleteWindowByClass(WindowClass cls); bool EditBoxInGlobalFocus(); +Point GetCaretPosition(); #endif /* WINDOW_FUNC_H */
--- a/src/window_gui.h +++ b/src/window_gui.h @@ -345,6 +345,8 @@ const QueryString *GetQueryString(uint widnum) const; QueryString *GetQueryString(uint widnum); + virtual Point GetCaretPosition() const; + void InitNested(WindowNumber number = 0); void CreateNestedTree(bool fill_nested = true); void FinishInitNested(WindowNumber window_number = 0);