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

223 lines
7.7 KiB
Diff
Raw Normal View History

From f57059086630af68cf9469074c1630d32e607e15 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. (try 2)
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/win32u/driver.c | 7 ++++
dlls/win32u/input.c | 2 ++
dlls/winex11.drv/init.c | 1 +
dlls/winex11.drv/x11drv.h | 1 +
dlls/winex11.drv/xim.c | 72 ++++++++++++++++++++++++++++++++++++++-
include/wine/gdi_driver.h | 2 ++
6 files changed, 84 insertions(+), 1 deletion(-)
diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c
index 526bb5db19c..d18a8121f1f 100644
--- a/dlls/win32u/driver.c
+++ b/dlls/win32u/driver.c
@@ -893,6 +893,11 @@ static struct opengl_funcs *nulldrv_wine_get_wgl_driver( UINT version )
return (void *)-1;
}
+static void nulldrv_UpdateCandidatePos( HWND hwnd, const RECT *caret_rect )
+{
+
+}
+
static void nulldrv_ThreadDetach( void )
{
}
@@ -1188,6 +1193,7 @@ static const struct user_driver_funcs lazy_load_driver =
2022-03-19 14:45:32 -07:00
loaderdrv_wine_get_vulkan_driver,
/* opengl support */
nulldrv_wine_get_wgl_driver,
+ nulldrv_UpdateCandidatePos,
/* thread management */
nulldrv_ThreadDetach,
};
@@ -1258,6 +1264,7 @@ void CDECL __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT v
SET_USER_FUNC(SystemParametersInfo);
SET_USER_FUNC(wine_get_vulkan_driver);
SET_USER_FUNC(wine_get_wgl_driver);
+ SET_USER_FUNC(UpdateCandidatePos);
SET_USER_FUNC(ThreadDetach);
#undef SET_USER_FUNC
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c
index 658258f73ee..8ecacb763c7 100644
--- a/dlls/win32u/input.c
+++ b/dlls/win32u/input.c
@@ -2035,6 +2035,7 @@ BOOL set_caret_pos( int x, int y )
r.left = x;
r.top = y;
display_caret( hwnd, &r );
+ user_driver->pUpdateCandidatePos( hwnd, &r );
NtUserSetSystemTimer( hwnd, SYSTEM_TIMER_CARET, caret.timeout );
}
return ret;
@@ -2072,6 +2073,7 @@ BOOL WINAPI NtUserShowCaret( HWND hwnd )
if (ret && hidden == 1) /* hidden was 1 so it's now 0 */
{
display_caret( hwnd, &r );
+ user_driver->pUpdateCandidatePos( hwnd, &r );
NtUserSetSystemTimer( hwnd, SYSTEM_TIMER_CARET, caret.timeout );
}
return ret;
diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c
index 60232e4ca7b..846ead80a4a 100644
--- a/dlls/winex11.drv/init.c
+++ b/dlls/winex11.drv/init.c
@@ -433,6 +433,7 @@ static const struct user_driver_funcs x11drv_funcs =
.pSystemParametersInfo = X11DRV_SystemParametersInfo,
.pwine_get_vulkan_driver = X11DRV_wine_get_vulkan_driver,
.pwine_get_wgl_driver = X11DRV_wine_get_wgl_driver,
+ .pUpdateCandidatePos = X11DRV_UpdateCandidatePos,
.pThreadDetach = X11DRV_ThreadDetach,
};
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index ac540df004c..ba56b1e127c 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -245,6 +245,7 @@ extern void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flag
struct window_surface *surface ) DECLSPEC_HIDDEN;
extern BOOL X11DRV_SystemParametersInfo( UINT action, UINT int_param, void *ptr_param,
UINT flags ) DECLSPEC_HIDDEN;
+extern void X11DRV_UpdateCandidatePos( HWND hwnd, const RECT *caret_rect ) DECLSPEC_HIDDEN;
extern void X11DRV_ThreadDetach(void) DECLSPEC_HIDDEN;
/* X11 driver internal functions */
diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c
index 00c15bb3bcf..280bfe5bf3c 100644
--- a/dlls/winex11.drv/xim.c
+++ b/dlls/winex11.drv/xim.c
@@ -34,6 +34,7 @@
#include "x11drv.h"
#include "imm.h"
#include "wine/debug.h"
+#include "wine/server.h"
WINE_DEFAULT_DEBUG_CHANNEL(xim);
@@ -449,6 +450,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 != NtUserGetDesktopWindow(); parent = NtUserGetAncestor( 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)
+ NtUserMapWindowPoints( hwnd, data->hwnd, &pt, 1 );
+
+ if (NtUserGetWindowLongW( 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)
{
@@ -483,7 +526,7 @@ XIC X11DRV_CreateIC(XIM xim, struct x11drv_win_data *data)
XNDestroyCallback, &destroy,
NULL);
data->xic = xic;
- return xic;
+ goto return_xic;
}
/* create callbacks */
@@ -581,5 +624,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;
}
diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h
index d9c52777dd8..532e4bdcd9e 100644
--- a/include/wine/gdi_driver.h
+++ b/include/wine/gdi_driver.h
@@ -325,6 +325,8 @@ struct user_driver_funcs
const struct vulkan_funcs * (*pwine_get_vulkan_driver)(UINT);
/* opengl support */
struct opengl_funcs * (*pwine_get_wgl_driver)(UINT);
+ /* IME functions */
+ void (*pUpdateCandidatePos)(HWND, const RECT *);
/* thread management */
void (*pThreadDetach)(void);
};
--
2.35.1