summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormichi_cc <michi_cc@openttd.org>2013-08-05 20:37:14 +0000
committermichi_cc <michi_cc@openttd.org>2013-08-05 20:37:14 +0000
commitda09fd3077c288317aaa897b4665c30150358321 (patch)
treefeadeb4b523c314216133329c14d59095591cdda
parent21126aec623c4d5a9afea786f2d57d8897a407bc (diff)
downloadopenttd-da09fd3077c288317aaa897b4665c30150358321.tar.xz
(svn r25681) -Change: [Win32] Position the IME composition window at the caret position.
-rw-r--r--src/console_gui.cpp8
-rw-r--r--src/misc_gui.cpp28
-rw-r--r--src/querystring_gui.h2
-rw-r--r--src/video/win32_v.cpp32
-rw-r--r--src/window.cpp14
-rw-r--r--src/window_func.h2
-rw-r--r--src/window_gui.h2
7 files changed, 88 insertions, 0 deletions
diff --git a/src/console_gui.cpp b/src/console_gui.cpp
index 0cc2f670e..772ead610 100644
--- a/src/console_gui.cpp
+++ b/src/console_gui.cpp
@@ -317,6 +317,14 @@ struct IConsoleWindow : Window
}
}
+ 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);
diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp
index 87847ba70..37a317733 100644
--- a/src/misc_gui.cpp
+++ b/src/misc_gui.cpp
@@ -785,6 +785,34 @@ void QueryString::DrawEditBox(const Window *w, int wid) const
_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);
diff --git a/src/querystring_gui.h b/src/querystring_gui.h
index b2c91f354..a652b382d 100644
--- a/src/querystring_gui.h
+++ b/src/querystring_gui.h
@@ -53,6 +53,8 @@ public:
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);
diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp
index a0da4b06f..f7394ba99 100644
--- 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>
@@ -500,6 +501,28 @@ static LRESULT HandleCharMsg(uint keycode, WChar charcode)
}
#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)
{
@@ -515,6 +538,7 @@ static LRESULT HandleIMEComposition(HWND hwnd, WPARAM wParam, LPARAM lParam)
/* 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);
@@ -535,6 +559,7 @@ static void CancelIMEComposition(HWND hwnd)
#else
+static void SetCompositionPos(HWND hwnd) {}
static void CancelIMEComposition(HWND hwnd) {}
#endif /* !defined(WINCE) || _WIN32_WCE >= 0x400 */
@@ -548,6 +573,7 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
switch (msg) {
case WM_CREATE:
SetTimer(hwnd, TID_POLLMOUSE, MOUSE_POLL_DELAY, (TIMERPROC)TrackMouseTimerProc);
+ SetCompositionPos(hwnd);
break;
case WM_ENTERSIZEMOVE:
@@ -674,6 +700,10 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
}
#if !defined(WINCE) || _WIN32_WCE >= 0x400
+ case WM_IME_STARTCOMPOSITION:
+ SetCompositionPos(hwnd);
+ break;
+
case WM_IME_COMPOSITION:
return HandleIMEComposition(hwnd, wParam, lParam);
@@ -861,6 +891,7 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
case WM_SETFOCUS:
_wnd.has_focus = true;
+ SetCompositionPos(hwnd);
break;
case WM_KILLFOCUS:
@@ -1220,4 +1251,5 @@ bool VideoDriver_Win32::AfterBlitterChange()
void VideoDriver_Win32::EditBoxLostFocus()
{
CancelIMEComposition(_wnd.main_wnd);
+ SetCompositionPos(_wnd.main_wnd);
}
diff --git a/src/window.cpp b/src/window.cpp
index 522a10a6f..2805301f0 100644
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -323,6 +323,20 @@ QueryString *Window::GetQueryString(uint widnum)
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
diff --git a/src/window_func.h b/src/window_func.h
index ee494592b..453b88978 100644
--- 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 DeleteWindowById(WindowClass cls, WindowNumber number, bool force = true);
void DeleteWindowByClass(WindowClass cls);
bool EditBoxInGlobalFocus();
+Point GetCaretPosition();
#endif /* WINDOW_FUNC_H */
diff --git a/src/window_gui.h b/src/window_gui.h
index 557fd3145..fe2c8ef62 100644
--- a/src/window_gui.h
+++ b/src/window_gui.h
@@ -345,6 +345,8 @@ public:
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);