mirror of
https://github.com/davatorium/rofi.git
synced 2024-11-18 13:54:36 -05:00
input method (#1735)
* input method draft * restoring relese event * using unused macro, removing debug code, handling disconnection * review fixes, new update_im_window_pos method * initializing variables correctly * initializing im pos queue correctly * ime window positioning * add widget_get_y_pos() position * [Build] Update makefile with imdkit * [CI] Add imdkit as dependency. * [XCB] rofi_view_paste don't throw warning, print debug. * [XCB] rofi_view_paste lower 'failed to convert selection' * [Build] Add minimum version check to imdkit * new macro XCB_IMDKIT_1_0_3_LOWER * [Build] Try to support old version of imdkit in meson/makefile. * [Build] Fix typo in meson.build * [XIM] Don't set use compound/set use utf8 when on old version. * [Build] Allow building without imdkit. * [Doc] Add imdkit to dependency list. Co-authored-by: Dave Davenport <qball@gmpclient.org>
This commit is contained in:
parent
579902deff
commit
6d02648d3a
11 changed files with 308 additions and 21 deletions
1
.github/actions/setup/action.yml
vendored
1
.github/actions/setup/action.yml
vendored
|
@ -29,6 +29,7 @@ runs:
|
|||
libxcb-xkb-dev \
|
||||
libxcb-xrm-dev \
|
||||
libxcb-cursor-dev \
|
||||
libxcb-imdkit-dev \
|
||||
libxkbcommon-dev \
|
||||
libxkbcommon-dev \
|
||||
libxkbcommon-x11-dev \
|
||||
|
|
|
@ -39,6 +39,7 @@ You can also use [Meson](https://mesonbuild.com/) as an alternative.
|
|||
* xcb-util
|
||||
* xcb-util-wm (sometimes split as libxcb-ewmh and libxcb-icccm)
|
||||
* xcb-util-cursor
|
||||
* xcb-imdkit (optional, 1.0.3 or up preferred)
|
||||
|
||||
On debian based systems, the developer packages are in the form of: `<package>-dev` on rpm based
|
||||
`<package>-devel`.
|
||||
|
|
|
@ -145,6 +145,7 @@ rofi_CFLAGS=\
|
|||
$(libsn_CFLAGS)\
|
||||
$(cairo_CFLAGS)\
|
||||
$(gdkpixbuf_CFLAGS)\
|
||||
$(imdclient_CFLAGS)\
|
||||
-DMANPAGE_PATH="\"$(mandir)/\""\
|
||||
-I$(top_srcdir)/include/\
|
||||
-I$(top_builddir)/lexer/\
|
||||
|
@ -165,6 +166,7 @@ rofi_LDADD=\
|
|||
$(pango_LIBS)\
|
||||
$(cairo_LIBS)\
|
||||
$(gdkpixbuf_LIBS)\
|
||||
$(imdclient_LIBS)\
|
||||
$(LIBS)
|
||||
|
||||
##
|
||||
|
|
|
@ -145,7 +145,11 @@ NK_INIT([bindings xdg-theme])
|
|||
PKG_CHECK_MODULES([glib], [glib-2.0 >= ${glib_min_version} gio-unix-2.0 gmodule-2.0])
|
||||
AC_DEFINE_UNQUOTED([GLIB_VERSION_MIN_REQUIRED], [(G_ENCODE_VERSION(${glib_min_major},${glib_min_minor}))], [The lower GLib version supported])
|
||||
AC_DEFINE_UNQUOTED([GLIB_VERSION_MAX_ALLOWED], [(G_ENCODE_VERSION(${glib_min_major},${glib_min_minor}))], [The highest GLib version supported])
|
||||
GW_CHECK_XCB([xcb-aux xcb-xkb xkbcommon xkbcommon-x11 xcb-ewmh xcb-icccm xcb-cursor xcb-randr xcb-xinerama])
|
||||
GW_CHECK_XCB([xcb-aux xcb-xkb xkbcommon xkbcommon-x11 xcb-ewmh xcb-icccm xcb-cursor xcb-randr xcb-xinerama ])
|
||||
PKG_CHECK_MODULES([imdclient], [xcb-imdkit <= 1.0.2 ],
|
||||
[AC_DEFINE([XCB_IMDKIT_1_0_3_LOWER], [1], [Indicate lower version of imdclient])
|
||||
AC_DEFINE([XCB_IMDKIT],[1], [IMD Kit missing])],
|
||||
[PKG_CHECK_MODULES([imdclient], [xcb-imdkit >= 1.0.3],[AC_DEFINE([XCB_IMDKIT],[1], [IMD Kit missing])],[HAVE_IMDKIT=0])])
|
||||
PKG_CHECK_MODULES([pango], [pango pangocairo])
|
||||
PKG_CHECK_MODULES([cairo], [cairo cairo-xcb])
|
||||
PKG_CHECK_MODULES([libsn], [libstartup-notification-1.0 ])
|
||||
|
|
|
@ -341,5 +341,15 @@ void rofi_view_set_window_title(const char *title);
|
|||
* set ellipsize mode to start.
|
||||
*/
|
||||
void rofi_view_ellipsize_start(RofiViewState *state);
|
||||
|
||||
/**
|
||||
* @param new_x New XIM window x pos
|
||||
* @param new_y New XIM window y pos
|
||||
*
|
||||
* Updates the XIM window position to new_x and new_y, relative to the
|
||||
* main_window
|
||||
*/
|
||||
gboolean rofi_set_im_window_pos(int new_x, int new_y);
|
||||
|
||||
/** @} */
|
||||
#endif
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <glib.h>
|
||||
#include <libsn/sn.h>
|
||||
|
||||
#include "xcb.h"
|
||||
#include <libgwater-xcb.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xcb_ewmh.h>
|
||||
|
@ -45,6 +46,10 @@ struct _xcb_stuff {
|
|||
GMainLoop *main_loop;
|
||||
GWaterXcbSource *source;
|
||||
xcb_connection_t *connection;
|
||||
#ifdef XCB_IMDKIT
|
||||
xcb_xic_t ic;
|
||||
xcb_xim_t *im;
|
||||
#endif
|
||||
xcb_ewmh_connection_t ewmh;
|
||||
xcb_screen_t *screen;
|
||||
int screen_nbr;
|
||||
|
|
|
@ -29,6 +29,10 @@
|
|||
#define ROFI_XCB_H
|
||||
|
||||
#include <cairo.h>
|
||||
#include <config.h>
|
||||
#ifdef XCB_IMDKIT
|
||||
#include <xcb-imdkit/imclient.h>
|
||||
#endif
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
/**
|
||||
|
@ -220,6 +224,7 @@ extern WindowManagerQuirk current_window_manager;
|
|||
* @returns NULL if window was not found, or unmapped, otherwise returns a
|
||||
* cairo_surface.
|
||||
*/
|
||||
|
||||
cairo_surface_t *x11_helper_get_screenshot_surface_window(xcb_window_t window,
|
||||
int size);
|
||||
|
||||
|
@ -233,4 +238,11 @@ cairo_surface_t *x11_helper_get_screenshot_surface_window(xcb_window_t window,
|
|||
void cairo_image_surface_blur(cairo_surface_t *surface, double radius,
|
||||
double deviation);
|
||||
|
||||
#ifdef XCB_IMDKIT
|
||||
/**
|
||||
* IME Forwarding
|
||||
*/
|
||||
void x11_event_handler_fowarding(xcb_xim_t *im, xcb_xic_t ic,
|
||||
xcb_key_press_event_t *event, void *user_data);
|
||||
#endif
|
||||
#endif
|
||||
|
|
20
meson.build
20
meson.build
|
@ -74,9 +74,27 @@ deps += [
|
|||
dependency('libstartup-notification-1.0'),
|
||||
]
|
||||
|
||||
check = dependency('check', version: '>= 0.11.0', required: get_option('check'))
|
||||
imdkit_new = dependency('xcb-imdkit', version: '>= 1.0.3', required: false)
|
||||
imdkit_old = dependency('xcb-imdkit', version: '<= 1.0.2', required: false)
|
||||
|
||||
|
||||
check = dependency('check', version: '>= 0.11.0', required: get_option('check'))
|
||||
header_conf = configuration_data()
|
||||
|
||||
if imdkit_new.found()
|
||||
deps += imdkit_new
|
||||
header_conf.set('XCB_IMDKIT_1_0_3_LOWER', false)
|
||||
header_conf.set('XCB_IMDKIT', true)
|
||||
elif imdkit_old.found()
|
||||
deps+= imdkit_old
|
||||
header_conf.set('XCB_IMDKIT_1_0_3_LOWER', true)
|
||||
header_conf.set('XCB_IMDKIT', true)
|
||||
else
|
||||
header_conf.set('XCB_IMDKIT_1_0_3_LOWER', false)
|
||||
header_conf.set('XCB_IMDKIT', false)
|
||||
endif
|
||||
|
||||
|
||||
header_conf.set_quoted('PACKAGE_NAME', meson.project_name())
|
||||
header_conf.set_quoted('PACKAGE_VERSION', meson.project_version())
|
||||
header_conf.set_quoted('VERSION', meson.project_version())
|
||||
|
|
|
@ -379,6 +379,13 @@ static void help(G_GNUC_UNUSED int argc, char **argv) {
|
|||
#else
|
||||
printf("\t• asan %sdisabled%s\n", is_term ? color_red : "",
|
||||
is_term ? color_reset : "");
|
||||
#endif
|
||||
#ifdef XCB_IMDKIT
|
||||
printf("\t• imdkit %senabled%s\n", is_term ? color_green : "",
|
||||
is_term ? color_reset : "");
|
||||
#else
|
||||
printf("\t• imdkit %sdisabled%s\n", is_term ? color_red : "",
|
||||
is_term ? color_reset : "");
|
||||
#endif
|
||||
printf("\n");
|
||||
printf("For more information see: %sman rofi%s\n", is_term ? color_bold : "",
|
||||
|
|
116
source/view.c
116
source/view.c
|
@ -38,6 +38,9 @@
|
|||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#ifdef XCB_IMDKIT
|
||||
#include <xcb-imdkit/encoding.h>
|
||||
#endif
|
||||
#include <xcb/xcb_ewmh.h>
|
||||
#include <xcb/xcb_icccm.h>
|
||||
#include <xcb/xkb.h>
|
||||
|
@ -79,6 +82,20 @@ void rofi_view_update(RofiViewState *state, gboolean qr);
|
|||
|
||||
static int rofi_view_calculate_height(RofiViewState *state);
|
||||
|
||||
#ifdef XCB_IMDKIT
|
||||
static void xim_commit_string(xcb_xim_t *im, G_GNUC_UNUSED xcb_xic_t ic,
|
||||
G_GNUC_UNUSED uint32_t flag, char *str,
|
||||
uint32_t length, G_GNUC_UNUSED uint32_t *keysym,
|
||||
G_GNUC_UNUSED size_t nKeySym,
|
||||
G_GNUC_UNUSED void *user_data);
|
||||
static void xim_disconnected(G_GNUC_UNUSED xcb_xim_t *im,
|
||||
G_GNUC_UNUSED void *user_data);
|
||||
xcb_xim_im_callback xim_callback = {.forward_event =
|
||||
x11_event_handler_fowarding,
|
||||
.commit_string = xim_commit_string,
|
||||
.disconnected = xim_disconnected};
|
||||
#endif
|
||||
|
||||
/** Thread pool used for filtering */
|
||||
GThreadPool *tpool = NULL;
|
||||
|
||||
|
@ -784,6 +801,86 @@ rofi_view_setup_fake_transparency(widget *win,
|
|||
TICK_N("Fake transparency");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef XCB_IMDKIT
|
||||
static void xim_commit_string(xcb_xim_t *im, G_GNUC_UNUSED xcb_xic_t ic,
|
||||
G_GNUC_UNUSED uint32_t flag, char *str,
|
||||
uint32_t length, G_GNUC_UNUSED uint32_t *keysym,
|
||||
G_GNUC_UNUSED size_t nKeySym,
|
||||
G_GNUC_UNUSED void *user_data) {
|
||||
RofiViewState *state = rofi_view_get_active();
|
||||
if (state == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef XCB_IMDKIT_1_0_3_LOWER
|
||||
if (xcb_xim_get_encoding(im) == XCB_XIM_UTF8_STRING) {
|
||||
rofi_view_handle_text(state, str);
|
||||
} else if (xcb_xim_get_encoding(im) == XCB_XIM_COMPOUND_TEXT) {
|
||||
size_t newLength = 0;
|
||||
char *utf8 = xcb_compound_text_to_utf8(str, length, &newLength);
|
||||
if (utf8) {
|
||||
rofi_view_handle_text(state, utf8);
|
||||
}
|
||||
}
|
||||
#else
|
||||
size_t newLength = 0;
|
||||
char *utf8 = xcb_compound_text_to_utf8(str, length, &newLength);
|
||||
if (utf8) {
|
||||
rofi_view_handle_text(state, utf8);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void xim_disconnected(G_GNUC_UNUSED xcb_xim_t *im,
|
||||
G_GNUC_UNUSED void *user_data) {
|
||||
xcb->ic = 0;
|
||||
}
|
||||
|
||||
static void create_ic_callback(xcb_xim_t *im, xcb_xic_t new_ic,
|
||||
G_GNUC_UNUSED void *user_data) {
|
||||
xcb->ic = new_ic;
|
||||
if (xcb->ic) {
|
||||
xcb_xim_set_ic_focus(im, xcb->ic);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean rofi_set_im_window_pos(int new_x, int new_y) {
|
||||
if (!xcb->ic)
|
||||
return false;
|
||||
|
||||
static xcb_point_t spot = {.x = 0, .y = 0};
|
||||
if (spot.x != new_x || spot.y != new_y) {
|
||||
spot.x = new_x;
|
||||
spot.y = new_y;
|
||||
xcb_xim_nested_list nested = xcb_xim_create_nested_list(
|
||||
xcb->im, XCB_XIM_XNSpotLocation, &spot, NULL);
|
||||
xcb_xim_set_ic_values(xcb->im, xcb->ic, NULL, NULL, XCB_XIM_XNClientWindow,
|
||||
&CacheState.main_window, XCB_XIM_XNFocusWindow,
|
||||
&CacheState.main_window, XCB_XIM_XNPreeditAttributes,
|
||||
&nested, NULL);
|
||||
free(nested.data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static void open_xim_callback(xcb_xim_t *im, G_GNUC_UNUSED void *user_data) {
|
||||
RofiViewState *state = rofi_view_get_active();
|
||||
uint32_t input_style = XCB_IM_PreeditPosition | XCB_IM_StatusArea;
|
||||
xcb_point_t spot;
|
||||
spot.x += widget_get_x_pos(&state->text->widget) +
|
||||
textbox_get_cursor_x_pos(state->text);
|
||||
spot.y += widget_get_y_pos(&state->text->widget) +
|
||||
widget_get_height(&state->text->widget);
|
||||
xcb_xim_nested_list nested =
|
||||
xcb_xim_create_nested_list(im, XCB_XIM_XNSpotLocation, &spot, NULL);
|
||||
xcb_xim_create_ic(
|
||||
im, create_ic_callback, NULL, XCB_XIM_XNInputStyle, &input_style,
|
||||
XCB_XIM_XNClientWindow, &CacheState.main_window, XCB_XIM_XNFocusWindow,
|
||||
&CacheState.main_window, XCB_XIM_XNPreeditAttributes, &nested, NULL);
|
||||
free(nested.data);
|
||||
}
|
||||
#endif
|
||||
|
||||
void __create_window(MenuFlags menu_flags) {
|
||||
uint32_t selmask = XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL |
|
||||
XCB_CW_BIT_GRAVITY | XCB_CW_BACKING_STORE |
|
||||
|
@ -799,6 +896,15 @@ void __create_window(MenuFlags menu_flags) {
|
|||
XCB_GRAVITY_STATIC, XCB_BACKING_STORE_NOT_USEFUL,
|
||||
xcb_event_masks, map};
|
||||
|
||||
#ifdef XCB_IMDKIT
|
||||
xcb_xim_set_im_callback(xcb->im, &xim_callback, NULL);
|
||||
#endif
|
||||
|
||||
// Open connection to XIM server.
|
||||
#ifdef XCB_IMDKIT
|
||||
xcb_xim_open(xcb->im, open_xim_callback, true, NULL);
|
||||
#endif
|
||||
|
||||
xcb_window_t box_window = xcb_generate_id(xcb->connection);
|
||||
xcb_void_cookie_t cc = xcb_create_window_checked(
|
||||
xcb->connection, depth->depth, box_window, xcb_stuff_get_root_window(), 0,
|
||||
|
@ -810,6 +916,7 @@ void __create_window(MenuFlags menu_flags) {
|
|||
g_error("xcb_create_window() failed error=0x%x\n", error->error_code);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
TICK_N("xcb create window");
|
||||
CacheState.gc = xcb_generate_id(xcb->connection);
|
||||
xcb_create_gc(xcb->connection, CacheState.gc, box_window, 0, 0);
|
||||
|
@ -1107,6 +1214,7 @@ static void update_callback(textbox *t, icon *ico, unsigned int index,
|
|||
textbox_set_pango_attributes(t, list);
|
||||
pango_attr_list_unref(list);
|
||||
}
|
||||
|
||||
g_list_free(add_list);
|
||||
g_free(text);
|
||||
} else {
|
||||
|
@ -1149,6 +1257,14 @@ void rofi_view_update(RofiViewState *state, gboolean qr) {
|
|||
cairo_set_operator(d, CAIRO_OPERATOR_OVER);
|
||||
widget_draw(WIDGET(state->main_window), d);
|
||||
|
||||
#ifdef XCB_IMDKIT
|
||||
int x = widget_get_x_pos(&state->text->widget) +
|
||||
textbox_get_cursor_x_pos(state->text);
|
||||
int y = widget_get_y_pos(&state->text->widget) +
|
||||
widget_get_height(&state->text->widget);
|
||||
rofi_set_im_window_pos(x, y);
|
||||
#endif
|
||||
|
||||
TICK_N("widgets");
|
||||
cairo_surface_flush(CacheState.edit_surf);
|
||||
if (qr) {
|
||||
|
|
149
source/xcb.c
149
source/xcb.c
|
@ -30,6 +30,9 @@
|
|||
#define G_LOG_DOMAIN "X11Helper"
|
||||
|
||||
#include "config.h"
|
||||
#ifdef XCB_IMDKIT
|
||||
#include <xcb-imdkit/encoding.h>
|
||||
#endif
|
||||
#include <cairo-xcb.h>
|
||||
#include <cairo.h>
|
||||
#include <glib.h>
|
||||
|
@ -62,6 +65,7 @@
|
|||
#include "xcb-internal.h"
|
||||
#include "xcb.h"
|
||||
#include <libsn/sn.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "mode.h"
|
||||
#include "modes/window.h"
|
||||
|
@ -84,6 +88,9 @@ WindowManagerQuirk current_window_manager = WM_EWHM;
|
|||
*/
|
||||
struct _xcb_stuff xcb_int = {.connection = NULL,
|
||||
.screen = NULL,
|
||||
#ifdef XCB_IMDKIT
|
||||
.im = NULL,
|
||||
#endif
|
||||
.screen_nbr = -1,
|
||||
.sndisplay = NULL,
|
||||
.sncontext = NULL,
|
||||
|
@ -1061,6 +1068,35 @@ int monitor_active(workarea *mon) {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static bool get_atom_name(xcb_connection_t *conn, xcb_atom_t atom, char **out) {
|
||||
xcb_get_atom_name_cookie_t cookie;
|
||||
xcb_get_atom_name_reply_t *reply;
|
||||
int length;
|
||||
char *name;
|
||||
|
||||
if (atom == 0) {
|
||||
*out = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
cookie = xcb_get_atom_name(conn, atom);
|
||||
reply = xcb_get_atom_name_reply(conn, cookie, NULL);
|
||||
if (!reply)
|
||||
return false;
|
||||
|
||||
length = xcb_get_atom_name_name_length(reply);
|
||||
name = xcb_get_atom_name_name(reply);
|
||||
|
||||
(*out) = g_strndup(name, length);
|
||||
if (!(*out)) {
|
||||
free(reply);
|
||||
return false;
|
||||
}
|
||||
|
||||
free(reply);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param state Internal state of the menu.
|
||||
* @param xse X selection event.
|
||||
|
@ -1070,7 +1106,7 @@ int monitor_active(workarea *mon) {
|
|||
static void rofi_view_paste(RofiViewState *state,
|
||||
xcb_selection_notify_event_t *xse) {
|
||||
if (xse->property == XCB_ATOM_NONE) {
|
||||
g_warning("Failed to convert selection");
|
||||
g_debug("Failed to convert selection");
|
||||
} else if (xse->property == xcb->ewmh.UTF8_STRING) {
|
||||
gchar *text = window_get_text_prop(xse->requestor, xcb->ewmh.UTF8_STRING);
|
||||
if (text != NULL && text[0] != '\0') {
|
||||
|
@ -1085,7 +1121,13 @@ static void rofi_view_paste(RofiViewState *state,
|
|||
}
|
||||
g_free(text);
|
||||
} else {
|
||||
g_warning("Failed");
|
||||
char *out = NULL;
|
||||
if (get_atom_name(xcb->connection, xse->property, &out)) {
|
||||
g_debug("rofi_view_paste: Got unknown atom: %s", out);
|
||||
g_free(out);
|
||||
} else {
|
||||
g_debug("rofi_view_paste: Got unknown, unnamed: %s", out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1142,6 +1184,32 @@ static gboolean x11_button_to_nk_bindings_scroll(guint32 x11_button,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void rofi_key_press_event_handler(xcb_key_press_event_t *xkpe,
|
||||
RofiViewState *state) {
|
||||
gchar *text;
|
||||
|
||||
xcb->last_timestamp = xkpe->time;
|
||||
if (config.xserver_i300_workaround) {
|
||||
text = nk_bindings_seat_handle_key_with_modmask(
|
||||
xcb->bindings_seat, NULL, xkpe->state, xkpe->detail,
|
||||
NK_BINDINGS_KEY_STATE_PRESS);
|
||||
} else {
|
||||
text = nk_bindings_seat_handle_key(xcb->bindings_seat, NULL, xkpe->detail,
|
||||
NK_BINDINGS_KEY_STATE_PRESS);
|
||||
}
|
||||
if (text != NULL) {
|
||||
rofi_view_handle_text(state, text);
|
||||
g_free(text);
|
||||
}
|
||||
}
|
||||
|
||||
static void rofi_key_release_event_handler(xcb_key_release_event_t *xkre,
|
||||
G_GNUC_UNUSED RofiViewState *state) {
|
||||
xcb->last_timestamp = xkre->time;
|
||||
nk_bindings_seat_handle_key(xcb->bindings_seat, NULL, xkre->detail,
|
||||
NK_BINDINGS_KEY_STATE_RELEASE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process X11 events in the main-loop (gui-thread) of the application.
|
||||
*/
|
||||
|
@ -1301,28 +1369,26 @@ static void main_loop_x11_event_handler_view(xcb_generic_event_t *event) {
|
|||
}
|
||||
case XCB_KEY_PRESS: {
|
||||
xcb_key_press_event_t *xkpe = (xcb_key_press_event_t *)event;
|
||||
gchar *text;
|
||||
|
||||
xcb->last_timestamp = xkpe->time;
|
||||
if (config.xserver_i300_workaround) {
|
||||
text = nk_bindings_seat_handle_key_with_modmask(
|
||||
xcb->bindings_seat, NULL, xkpe->state, xkpe->detail,
|
||||
NK_BINDINGS_KEY_STATE_PRESS);
|
||||
} else {
|
||||
text = nk_bindings_seat_handle_key(xcb->bindings_seat, NULL, xkpe->detail,
|
||||
NK_BINDINGS_KEY_STATE_PRESS);
|
||||
}
|
||||
if (text != NULL) {
|
||||
rofi_view_handle_text(state, text);
|
||||
g_free(text);
|
||||
#ifdef XCB_IMDKIT
|
||||
if (xcb->ic) {
|
||||
xcb_xim_forward_event(xcb->im, xcb->ic, xkpe);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
rofi_key_press_event_handler(xkpe, state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XCB_KEY_RELEASE: {
|
||||
xcb_key_release_event_t *xkre = (xcb_key_release_event_t *)event;
|
||||
xcb->last_timestamp = xkre->time;
|
||||
nk_bindings_seat_handle_key(xcb->bindings_seat, NULL, xkre->detail,
|
||||
NK_BINDINGS_KEY_STATE_RELEASE);
|
||||
#ifdef XCB_IMDKIT
|
||||
if (xcb->ic) {
|
||||
xcb_xim_forward_event(xcb->im, xcb->ic, xkre);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
rofi_key_release_event_handler(xkre, state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -1331,6 +1397,25 @@ static void main_loop_x11_event_handler_view(xcb_generic_event_t *event) {
|
|||
rofi_view_maybe_update(state);
|
||||
}
|
||||
|
||||
#ifdef XCB_IMDKIT
|
||||
void x11_event_handler_fowarding(G_GNUC_UNUSED xcb_xim_t *im,
|
||||
G_GNUC_UNUSED xcb_xic_t ic,
|
||||
xcb_key_press_event_t *event,
|
||||
G_GNUC_UNUSED void *user_data) {
|
||||
RofiViewState *state = rofi_view_get_active();
|
||||
if (state == NULL) {
|
||||
return;
|
||||
}
|
||||
uint8_t type = event->response_type & ~0x80;
|
||||
if (type == XCB_KEY_PRESS) {
|
||||
rofi_key_press_event_handler(event, state);
|
||||
} else if (type == XCB_KEY_RELEASE) {
|
||||
xcb_key_release_event_t *xkre = (xcb_key_release_event_t *)event;
|
||||
rofi_key_release_event_handler(xkre, state);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean main_loop_x11_event_handler(xcb_generic_event_t *ev,
|
||||
G_GNUC_UNUSED gpointer user_data) {
|
||||
if (ev == NULL) {
|
||||
|
@ -1346,6 +1431,13 @@ static gboolean main_loop_x11_event_handler(xcb_generic_event_t *ev,
|
|||
// status);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
#ifdef XCB_IMDKIT
|
||||
if (xcb->im && xcb_xim_filter_event(xcb->im, ev)) {
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t type = ev->response_type & ~0x80;
|
||||
if (type == xcb->xkb.first_event) {
|
||||
switch (ev->pad0) {
|
||||
|
@ -1375,6 +1467,7 @@ static gboolean main_loop_x11_event_handler(xcb_generic_event_t *ev,
|
|||
if (xcb->sndisplay != NULL) {
|
||||
sn_xcb_display_process_event(xcb->sndisplay, ev);
|
||||
}
|
||||
|
||||
main_loop_x11_event_handler_view(ev);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
@ -1542,6 +1635,9 @@ gboolean display_setup(GMainLoop *main_loop, NkBindings *bindings) {
|
|||
find_arg_str("-display", &display_str);
|
||||
|
||||
xcb->main_loop = main_loop;
|
||||
#ifdef XCB_IMDKIT
|
||||
xcb_compound_text_init();
|
||||
#endif
|
||||
xcb->source = g_water_xcb_source_new(g_main_loop_get_context(xcb->main_loop),
|
||||
display_str, &xcb->screen_nbr,
|
||||
main_loop_x11_event_handler, NULL, NULL);
|
||||
|
@ -1550,6 +1646,16 @@ gboolean display_setup(GMainLoop *main_loop, NkBindings *bindings) {
|
|||
return FALSE;
|
||||
}
|
||||
xcb->connection = g_water_xcb_source_get_connection(xcb->source);
|
||||
#ifdef XCB_IMDKIT
|
||||
xcb->im = xcb_xim_create(xcb->connection, xcb->screen_nbr, NULL);
|
||||
#endif
|
||||
|
||||
#ifdef XCB_IMDKIT
|
||||
#ifndef XCB_IMDKIT_1_0_3_LOWER
|
||||
xcb_xim_set_use_compound_text(xcb->im, true);
|
||||
xcb_xim_set_use_utf8_string(xcb->im, true);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
TICK_N("Open Display");
|
||||
|
||||
|
@ -1819,6 +1925,11 @@ void display_cleanup(void) {
|
|||
xcb_ewmh_connection_wipe(&(xcb->ewmh));
|
||||
xcb_flush(xcb->connection);
|
||||
xcb_aux_sync(xcb->connection);
|
||||
#ifdef XCB_IMDKIT
|
||||
xcb_xim_close(xcb->im);
|
||||
xcb_xim_destroy(xcb->im);
|
||||
xcb->im = NULL;
|
||||
#endif
|
||||
g_water_xcb_source_free(xcb->source);
|
||||
xcb->source = NULL;
|
||||
xcb->connection = NULL;
|
||||
|
|
Loading…
Reference in a new issue