(svn r25681) -Change: [Win32] Position the IME composition window at the caret position.

replace/41b28d7194a279bdc17475d4fbe2ea6ec885a466
michi_cc 11 years ago
parent 21126aec62
commit da09fd3077

@ -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);

@ -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);

@ -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);

@ -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);
}

@ -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

@ -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 */

@ -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);

Loading…
Cancel
Save