wine-staging/patches/winex11-CandidateWindowPos/0001-winex11.drv-Update-a-candidate-window-s-position-wit.patch

243 lines
8.0 KiB
Diff
Raw Normal View History

From ed940af97f6488f87739b4d332101e69ed624412 Mon Sep 17 00:00:00 2001
From: Felix Yan <felixonmars@gmail.com>
Date: Tue, 23 Sep 2014 23:22:17 +0800
Subject: [PATCH] winex11.drv: Update a candidate window's position with
over-the-spot style
In the current implementation, the candidate window position of a input
method is fixed because XNSpotLocation isn't updated after an input
context (XIC) is created in X11DRV_CreateIC().
X11DRV_UpdateCandidatePos() in this patch updates the position. You can
see the change of a position with ibus, scim or fcitx when input style
is set to "over the spot" in the registry key:
[HKEY_CURRENT_USER\Software\Wine\X11 Driver]
"InputStyle"="OverTheSpot"
This patch was based on the original work by Muneyuki Noguchi, and
received a lot of help from Sebastian Lackner.
---
dlls/user32/caret.c | 4 +++
dlls/user32/driver.c | 19 +++++++++--
dlls/user32/user_private.h | 2 ++
dlls/winex11.drv/winex11.drv.spec | 1 +
dlls/winex11.drv/xim.c | 72 ++++++++++++++++++++++++++++++++++++++-
5 files changed, 95 insertions(+), 3 deletions(-)
diff --git a/dlls/user32/caret.c b/dlls/user32/caret.c
index 53bb5b4..fff9e3e 100644
--- a/dlls/user32/caret.c
+++ b/dlls/user32/caret.c
@@ -30,6 +30,8 @@
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
+#include "user_private.h"
+
#include "wine/server.h"
#include "wine/debug.h"
@@ -277,6 +279,7 @@ BOOL WINAPI SetCaretPos( INT x, INT y )
r.left = x;
r.top = y;
CARET_DisplayCaret( hwnd, &r );
+ USER_Driver->pUpdateCandidatePos( hwnd, &r );
SetSystemTimer( hwnd, TIMERID, Caret.timeout, CARET_Callback );
}
return ret;
@@ -355,6 +358,7 @@ BOOL WINAPI ShowCaret( HWND hwnd )
if (ret && (hidden == 1)) /* hidden was 1 so it's now 0 */
{
CARET_DisplayCaret( hwnd, &r );
+ USER_Driver->pUpdateCandidatePos( hwnd, &r );
SetSystemTimer( hwnd, TIMERID, Caret.timeout, CARET_Callback );
}
return ret;
diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c
index e0bc38c..0e8b007 100644
--- a/dlls/user32/driver.c
+++ b/dlls/user32/driver.c
@@ -154,6 +154,7 @@ static const USER_DRIVER *load_driver(void)
GET_USER_FUNC(WindowPosChanging);
GET_USER_FUNC(WindowPosChanged);
GET_USER_FUNC(SystemParametersInfo);
+ GET_USER_FUNC(UpdateCandidatePos);
#undef GET_USER_FUNC
}
@@ -512,6 +513,10 @@ static BOOL CDECL nulldrv_SystemParametersInfo( UINT action, UINT int_param, voi
return FALSE;
}
+static void CDECL nulldrv_UpdateCandidatePos( HWND hwnd, const RECT *caret_rect )
+{
+}
+
static USER_DRIVER null_driver =
{
/* keyboard functions */
@@ -572,7 +577,9 @@ static USER_DRIVER null_driver =
nulldrv_WindowPosChanging,
nulldrv_WindowPosChanged,
/* system parameters */
- nulldrv_SystemParametersInfo
+ nulldrv_SystemParametersInfo,
+ /* candidate pos functions */
+ nulldrv_UpdateCandidatePos
};
@@ -767,6 +774,12 @@ static BOOL CDECL loaderdrv_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDW
return load_driver()->pUpdateLayeredWindow( hwnd, info, window_rect );
}
+static void CDECL loaderdrv_UpdateCandidatePos( HWND hwnd, const RECT *caret_rect )
+{
+ load_driver()->pUpdateCandidatePos( hwnd, caret_rect );
+}
+
+
static USER_DRIVER lazy_load_driver =
{
/* keyboard functions */
@@ -827,5 +840,7 @@ static USER_DRIVER lazy_load_driver =
nulldrv_WindowPosChanging,
nulldrv_WindowPosChanged,
/* system parameters */
- nulldrv_SystemParametersInfo
+ nulldrv_SystemParametersInfo,
+ /* candidate pos functions */
+ loaderdrv_UpdateCandidatePos
};
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
index adf3f7d..6202818 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -117,6 +117,8 @@ typedef struct tagUSER_DRIVER {
void (CDECL *pWindowPosChanged)(HWND,HWND,UINT,const RECT *,const RECT *,const RECT *,const RECT *,struct window_surface*);
/* system parameters */
BOOL (CDECL *pSystemParametersInfo)(UINT,UINT,void*,UINT);
+ /* candidate pos functions */
+ void (CDECL *pUpdateCandidatePos)(HWND,const RECT *);
} USER_DRIVER;
extern const USER_DRIVER *USER_Driver DECLSPEC_HIDDEN;
diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec
index b6e5c05..2a0d737 100644
--- a/dlls/winex11.drv/winex11.drv.spec
+++ b/dlls/winex11.drv/winex11.drv.spec
@@ -53,6 +53,7 @@
@ cdecl WindowPosChanging(long long long ptr ptr ptr ptr) X11DRV_WindowPosChanging
@ cdecl WindowPosChanged(long long long ptr ptr ptr ptr ptr) X11DRV_WindowPosChanged
@ cdecl SystemParametersInfo(long long ptr long) X11DRV_SystemParametersInfo
+@ cdecl UpdateCandidatePos(long ptr) X11DRV_UpdateCandidatePos
# WinTab32
@ cdecl AttachEventQueueToTablet(long) X11DRV_AttachEventQueueToTablet
diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c
index e0548b8..187323f 100644
--- a/dlls/winex11.drv/xim.c
+++ b/dlls/winex11.drv/xim.c
@@ -31,6 +31,7 @@
#include "x11drv.h"
#include "imm.h"
#include "wine/debug.h"
+#include "wine/server.h"
WINE_DEFAULT_DEBUG_CHANNEL(xim);
@@ -471,6 +472,48 @@ static BOOL X11DRV_DestroyIC(XIC xic, XPointer p, XPointer data)
return TRUE;
}
+/***********************************************************************
+ * X11DRV_UpdateCandidatePos
+ */
+void X11DRV_UpdateCandidatePos( HWND hwnd, const RECT *caret_rect )
+{
+ if (ximStyle & XIMPreeditPosition)
+ {
+ struct x11drv_win_data *data;
+ HWND parent;
+
+ for (parent = hwnd; parent && parent != GetDesktopWindow(); parent = GetAncestor( parent, GA_PARENT ))
+ {
+ if (!(data = get_win_data( parent ))) continue;
+ if (data->xic)
+ {
+ XVaNestedList preedit;
+ XPoint xpoint;
+ POINT pt;
+
+ pt.x = caret_rect->left;
+ pt.y = caret_rect->bottom;
+
+ if (hwnd != data->hwnd)
+ MapWindowPoints( hwnd, data->hwnd, &pt, 1 );
+
+ if (GetWindowLongW( data->hwnd, GWL_EXSTYLE ) & WS_EX_LAYOUTRTL)
+ pt.x = data->client_rect.right - data->client_rect.left - 1 - pt.x;
+
+ xpoint.x = pt.x + data->client_rect.left - data->whole_rect.left;
+ xpoint.y = pt.y + data->client_rect.top - data->whole_rect.top;
+
+ preedit = XVaCreateNestedList( 0, XNSpotLocation, &xpoint, NULL );
+ if (preedit)
+ {
+ XSetICValues( data->xic, XNPreeditAttributes, preedit, NULL );
+ XFree( preedit );
+ }
+ }
+ release_win_data( data );
+ }
+ }
+}
XIC X11DRV_CreateIC(XIM xim, struct x11drv_win_data *data)
{
@@ -498,7 +541,7 @@ XIC X11DRV_CreateIC(XIM xim, struct x11drv_win_data *data)
XNDestroyCallback, &destroy,
NULL);
data->xic = xic;
- return xic;
+ goto return_xic;
}
/* create callbacks */
@@ -596,5 +639,32 @@ XIC X11DRV_CreateIC(XIM xim, struct x11drv_win_data *data)
if (status != NULL)
XFree(status);
+return_xic:
+ if (xic != NULL && (ximStyle & XIMPreeditPosition))
+ {
+ SERVER_START_REQ( set_caret_info )
+ {
+ req->flags = 0; /* don't set anything */
+ req->handle = 0;
+ req->x = 0;
+ req->y = 0;
+ req->hide = 0;
+ req->state = 0;
+ if (!wine_server_call_err( req ))
+ {
+ HWND hwnd;
+ RECT r;
+
+ hwnd = wine_server_ptr_handle( reply->full_handle );
+ r.left = reply->old_rect.left;
+ r.top = reply->old_rect.top;
+ r.right = reply->old_rect.right;
+ r.bottom = reply->old_rect.bottom;
+ X11DRV_UpdateCandidatePos( hwnd, &r );
+ }
+ }
+ SERVER_END_REQ;
+ }
+
return xic;
}
--
2.1.0