macOS: Allow IME to actively get the cursor position in real time
IME will automatically get the display position when needed, which keeps it consistent with the overlay as much as possible. Fix the issue that when IME is activated after mouse click, it is displayed at the wrong position.
This commit is contained in:
parent
126aaddccb
commit
9a598237c6
@ -1454,15 +1454,11 @@ is_ascii_control_char(char x) {
|
||||
}
|
||||
|
||||
void _glfwPlatformUpdateIMEState(_GLFWwindow *w, const GLFWIMEUpdateEvent *ev) {
|
||||
[w->ns.view updateIMEStateFor: ev->type focused:(bool)ev->focused left:(CGFloat)ev->cursor.left top:(CGFloat)ev->cursor.top cellWidth:(CGFloat)ev->cursor.width cellHeight:(CGFloat)ev->cursor.height];
|
||||
[w->ns.view updateIMEStateFor: ev->type focused:(bool)ev->focused];
|
||||
}
|
||||
|
||||
- (void)updateIMEStateFor:(GLFWIMEUpdateType)which
|
||||
focused:(bool)focused
|
||||
left:(CGFloat)left
|
||||
top:(CGFloat)top
|
||||
cellWidth:(CGFloat)cellWidth
|
||||
cellHeight:(CGFloat)cellHeight
|
||||
{
|
||||
if (which == GLFW_IME_UPDATE_FOCUS && !focused && [self hasMarkedText] && window) {
|
||||
[input_context discardMarkedText];
|
||||
@ -1472,16 +1468,7 @@ void _glfwPlatformUpdateIMEState(_GLFWwindow *w, const GLFWIMEUpdateEvent *ev) {
|
||||
_glfw.ns.text[0] = 0;
|
||||
}
|
||||
if (which != GLFW_IME_UPDATE_CURSOR_POSITION) return;
|
||||
left /= window->ns.xscale;
|
||||
top /= window->ns.yscale;
|
||||
cellWidth /= window->ns.xscale;
|
||||
cellHeight /= window->ns.yscale;
|
||||
debug_key("updateIMEPosition: left=%f, top=%f, width=%f, height=%f\n", left, top, cellWidth, cellHeight);
|
||||
const NSRect frame = [window->ns.view frame];
|
||||
const NSRect rectInView = NSMakeRect(left,
|
||||
frame.size.height - top - cellHeight,
|
||||
cellWidth, cellHeight);
|
||||
markedRect = [window->ns.object convertRectToScreen: rectInView];
|
||||
|
||||
if (_glfwPlatformWindowFocused(window)) [[window->ns.view inputContext] invalidateCharacterCoordinates];
|
||||
}
|
||||
|
||||
@ -1507,6 +1494,21 @@ void _glfwPlatformUpdateIMEState(_GLFWwindow *w, const GLFWIMEUpdateEvent *ev) {
|
||||
actualRange:(NSRangePointer)actualRange
|
||||
{
|
||||
(void)range; (void)actualRange;
|
||||
if (_glfw.callbacks.get_ime_cursor_position) {
|
||||
GLFWIMEUpdateEvent ev = { .type = GLFW_IME_UPDATE_CURSOR_POSITION };
|
||||
if (_glfw.callbacks.get_ime_cursor_position((GLFWwindow*)window, &ev)) {
|
||||
const CGFloat left = (CGFloat)ev.cursor.left / window->ns.xscale;
|
||||
const CGFloat top = (CGFloat)ev.cursor.top / window->ns.yscale;
|
||||
const CGFloat cellWidth = (CGFloat)ev.cursor.width / window->ns.xscale;
|
||||
const CGFloat cellHeight = (CGFloat)ev.cursor.height / window->ns.yscale;
|
||||
debug_key("updateIMEPosition: left=%f, top=%f, width=%f, height=%f\n", left, top, cellWidth, cellHeight);
|
||||
const NSRect frame = [window->ns.view frame];
|
||||
const NSRect rectInView = NSMakeRect(left,
|
||||
frame.size.height - top - cellHeight,
|
||||
cellWidth, cellHeight);
|
||||
markedRect = [window->ns.object convertRectToScreen: rectInView];
|
||||
}
|
||||
}
|
||||
return markedRect;
|
||||
}
|
||||
|
||||
|
||||
2
glfw/glfw3.h
vendored
2
glfw/glfw3.h
vendored
@ -1732,6 +1732,7 @@ typedef enum {
|
||||
} GLFWClipboardType;
|
||||
typedef GLFWDataChunk (* GLFWclipboarditerfun)(const char *mime_type, void *iter, GLFWClipboardType ctype);
|
||||
typedef bool (* GLFWclipboardwritedatafun)(void *object, const char *data, size_t sz);
|
||||
typedef bool (* GLFWimecursorpositionfun)(GLFWwindow *window, GLFWIMEUpdateEvent *ev);
|
||||
|
||||
/*! @brief Video mode type.
|
||||
*
|
||||
@ -1891,6 +1892,7 @@ GLFWAPI void glfwRemoveTimer(unsigned long long);
|
||||
GLFWAPI GLFWdrawtextfun glfwSetDrawTextFunction(GLFWdrawtextfun function);
|
||||
GLFWAPI GLFWcurrentselectionfun glfwSetCurrentSelectionCallback(GLFWcurrentselectionfun callback);
|
||||
GLFWAPI GLFWhascurrentselectionfun glfwSetHasCurrentSelectionCallback(GLFWhascurrentselectionfun callback);
|
||||
GLFWAPI GLFWimecursorpositionfun glfwSetIMECursorPositionCallback(GLFWimecursorpositionfun callback);
|
||||
|
||||
/*! @brief Terminates the GLFW library.
|
||||
*
|
||||
|
||||
7
glfw/init.c
vendored
7
glfw/init.c
vendored
@ -402,3 +402,10 @@ GLFWAPI GLFWhascurrentselectionfun glfwSetHasCurrentSelectionCallback(GLFWhascur
|
||||
_GLFW_SWAP_POINTERS(_glfw.callbacks.has_current_selection, cbfun);
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWimecursorpositionfun glfwSetIMECursorPositionCallback(GLFWimecursorpositionfun cbfun)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
_GLFW_SWAP_POINTERS(_glfw.callbacks.get_ime_cursor_position, cbfun);
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
1
glfw/internal.h
vendored
1
glfw/internal.h
vendored
@ -635,6 +635,7 @@ struct _GLFWlibrary
|
||||
GLFWdrawtextfun draw_text;
|
||||
GLFWcurrentselectionfun get_current_selection;
|
||||
GLFWhascurrentselectionfun has_current_selection;
|
||||
GLFWimecursorpositionfun get_ime_cursor_position;
|
||||
} callbacks;
|
||||
|
||||
|
||||
|
||||
3
kitty/glfw-wrapper.c
generated
3
kitty/glfw-wrapper.c
generated
@ -44,6 +44,9 @@ load_glfw(const char* path) {
|
||||
*(void **) (&glfwSetHasCurrentSelectionCallback_impl) = dlsym(handle, "glfwSetHasCurrentSelectionCallback");
|
||||
if (glfwSetHasCurrentSelectionCallback_impl == NULL) fail("Failed to load glfw function glfwSetHasCurrentSelectionCallback with error: %s", dlerror());
|
||||
|
||||
*(void **) (&glfwSetIMECursorPositionCallback_impl) = dlsym(handle, "glfwSetIMECursorPositionCallback");
|
||||
if (glfwSetIMECursorPositionCallback_impl == NULL) fail("Failed to load glfw function glfwSetIMECursorPositionCallback with error: %s", dlerror());
|
||||
|
||||
*(void **) (&glfwTerminate_impl) = dlsym(handle, "glfwTerminate");
|
||||
if (glfwTerminate_impl == NULL) fail("Failed to load glfw function glfwTerminate with error: %s", dlerror());
|
||||
|
||||
|
||||
5
kitty/glfw-wrapper.h
generated
5
kitty/glfw-wrapper.h
generated
@ -1470,6 +1470,7 @@ typedef enum {
|
||||
} GLFWClipboardType;
|
||||
typedef GLFWDataChunk (* GLFWclipboarditerfun)(const char *mime_type, void *iter, GLFWClipboardType ctype);
|
||||
typedef bool (* GLFWclipboardwritedatafun)(void *object, const char *data, size_t sz);
|
||||
typedef bool (* GLFWimecursorpositionfun)(GLFWwindow *window, GLFWIMEUpdateEvent *ev);
|
||||
|
||||
/*! @brief Video mode type.
|
||||
*
|
||||
@ -1667,6 +1668,10 @@ typedef GLFWhascurrentselectionfun (*glfwSetHasCurrentSelectionCallback_func)(GL
|
||||
GFW_EXTERN glfwSetHasCurrentSelectionCallback_func glfwSetHasCurrentSelectionCallback_impl;
|
||||
#define glfwSetHasCurrentSelectionCallback glfwSetHasCurrentSelectionCallback_impl
|
||||
|
||||
typedef GLFWimecursorpositionfun (*glfwSetIMECursorPositionCallback_func)(GLFWimecursorpositionfun);
|
||||
GFW_EXTERN glfwSetIMECursorPositionCallback_func glfwSetIMECursorPositionCallback_impl;
|
||||
#define glfwSetIMECursorPositionCallback glfwSetIMECursorPositionCallback_impl
|
||||
|
||||
typedef void (*glfwTerminate_func)(void);
|
||||
GFW_EXTERN glfwTerminate_func glfwTerminate_impl;
|
||||
#define glfwTerminate glfwTerminate_impl
|
||||
|
||||
21
kitty/glfw.c
21
kitty/glfw.c
@ -507,6 +507,26 @@ has_current_selection(void) {
|
||||
return ans;
|
||||
}
|
||||
|
||||
void prepare_ime_position_update_event(OSWindow *osw, Window *w, Screen *screen, GLFWIMEUpdateEvent *ev);
|
||||
|
||||
static bool
|
||||
get_ime_cursor_position(GLFWwindow *glfw_window, GLFWIMEUpdateEvent *ev) {
|
||||
if (!set_callback_window(glfw_window)) return false;
|
||||
bool ans = false;
|
||||
OSWindow *osw = global_state.callback_os_window;
|
||||
if (osw && osw->is_focused && is_window_ready_for_callbacks()) {
|
||||
Tab *tab = osw->tabs + osw->active_tab;
|
||||
Window *w = tab->windows + tab->active_window;
|
||||
Screen *screen = w->render_data.screen;
|
||||
if (screen) {
|
||||
prepare_ime_position_update_event(osw, w, screen, ev);
|
||||
ans = true;
|
||||
}
|
||||
}
|
||||
global_state.callback_os_window = NULL;
|
||||
return ans;
|
||||
}
|
||||
|
||||
|
||||
static void get_window_dpi(GLFWwindow *w, double *x, double *y);
|
||||
|
||||
@ -832,6 +852,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
|
||||
glfwSetApplicationCloseCallback(application_close_requested_callback);
|
||||
glfwSetCurrentSelectionCallback(get_current_selection);
|
||||
glfwSetHasCurrentSelectionCallback(has_current_selection);
|
||||
glfwSetIMECursorPositionCallback(get_ime_cursor_position);
|
||||
#ifdef __APPLE__
|
||||
cocoa_set_activation_policy(OPT(macos_hide_from_tasks));
|
||||
glfwWindowHint(GLFW_COCOA_GRAPHICS_SWITCHING, true);
|
||||
|
||||
13
kitty/keys.c
13
kitty/keys.c
@ -102,8 +102,8 @@ update_ime_focus(OSWindow *osw, bool focused) {
|
||||
}
|
||||
|
||||
void
|
||||
update_ime_position(Window* w, Screen *screen) {
|
||||
unsigned int cell_width = global_state.callback_os_window->fonts_data->cell_width, cell_height = global_state.callback_os_window->fonts_data->cell_height;
|
||||
prepare_ime_position_update_event(OSWindow *osw, Window *w, Screen *screen, GLFWIMEUpdateEvent *ev) {
|
||||
unsigned int cell_width = osw->fonts_data->cell_width, cell_height = osw->fonts_data->cell_height;
|
||||
unsigned int left = w->geometry.left, top = w->geometry.top;
|
||||
if (screen_is_overlay_active(screen)) {
|
||||
left += screen->overlay_line.cursor_x * cell_width;
|
||||
@ -112,8 +112,15 @@ update_ime_position(Window* w, Screen *screen) {
|
||||
left += screen->cursor->x * cell_width;
|
||||
top += screen->cursor->y * cell_height;
|
||||
}
|
||||
ev->cursor.left = left; ev->cursor.top = top; ev->cursor.width = cell_width; ev->cursor.height = cell_height;
|
||||
}
|
||||
|
||||
void
|
||||
update_ime_position(Window* w UNUSED, Screen *screen UNUSED) {
|
||||
GLFWIMEUpdateEvent ev = { .type = GLFW_IME_UPDATE_CURSOR_POSITION };
|
||||
ev.cursor.left = left; ev.cursor.top = top; ev.cursor.width = cell_width; ev.cursor.height = cell_height;
|
||||
#ifndef __APPLE__
|
||||
prepare_ime_position_update_event(global_state.callback_os_window, w, screen, &ev);
|
||||
#endif
|
||||
glfwUpdateIMEState(global_state.callback_os_window->handle, &ev);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user