萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 作業系統 >  >> Linux 教學

Linux Sublime Text 無法輸入中文解決方案:LD_PRELOAD 輸入法修復

Sublime Text 在 Linux 下存在輸入法不跟隨、無法輸入中文問題。本文提供 C 語言編寫的共享庫透過 LD_PRELOAD 注入修復 GTK 輸入法上下文。

核心原理

攔截 gtk_im_context_set_client_window 與 gdk_region_get_clipbox,修正輸入法上下文視窗綁定與游標位置計算。

實施步驟

1. 建立原始碼 sublime_imfix.c

/* sublime-imfix.c
 * gcc -shared -o libsublime-imfix.so sublime_imfix.c `pkg-config --libs --cflags gtk+-2.0` -fPIC
 * LD_PRELOAD=./libsublime-imfix.so sublime_text
 */
#include 
#include 

typedef GdkSegment GdkRegionBox;
struct _GdkRegion {
    long size;
    long numRects;
    GdkRegionBox *rects;
    GdkRegionBox extents;
};

GtkIMContext *local_context;

void gdk_region_get_clipbox(const GdkRegion *region, GdkRectangle *rectangle) {
    g_return_if_fail(region != NULL);
    g_return_if_fail(rectangle != NULL);
    rectangle->x = region->extents.x1;
    rectangle->y = region->extents.y1;
    rectangle->width = region->extents.x2 - region->extents.x1;
    rectangle->height = region->extents.y2 - region->extents.y1;
    GdkRectangle rect;
    rect.x = rectangle->x;
    rect.y = rectangle->y;
    rect.width = 0;
    rect.height = rectangle->height;
    if (rectangle->width == 2 && GTK_IS_IM_CONTEXT(local_context)) {
        gtk_im_context_set_cursor_location(local_context, rectangle);
    }
}

static GdkFilterReturn event_filter(GdkXEvent *xevent, GdkEvent *event, gpointer im_context) {
    XEvent *xev = (XEvent *)xevent;
    if (xev->type == KeyRelease && GTK_IS_IM_CONTEXT(im_context)) {
        GdkWindow *win = g_object_get_data(G_OBJECT(im_context), "window");
        if (GDK_IS_WINDOW(win))
            gtk_im_context_set_client_window(im_context, win);
    }
    return GDK_FILTER_CONTINUE;
}

void gtk_im_context_set_client_window(GtkIMContext *context, GdkWindow *window) {
    GtkIMContextClass *klass;
    g_return_if_fail(GTK_IS_IM_CONTEXT(context));
    klass = GTK_IM_CONTEXT_GET_CLASS(context);
    if (klass->set_client_window)
        klass->set_client_window(context, window);
    if (!GDK_IS_WINDOW(window)) return;
    g_object_set_data(G_OBJECT(context), "window", window);
    int width = gdk_window_get_width(window);
    int height = gdk_window_get_height(window);
    if (width != 0 && height != 0) {
        gtk_im_context_focus_in(context);
        local_context = context;
    }
    gdk_window_add_filter(window, event_filter, context);
}

2. 編譯共享庫

gcc -shared -o libsublime-imfix.so sublime_imfix.c `pkg-config --libs --cflags gtk+-2.0` -fPIC

3. 啟動腳本自動化

#!/bin/bash
SUBLIME_HOME="/opt/sublime_text"
LD_LIB="$SUBLIME_HOME/libsublime-imfix.so"
sh -c "LD_PRELOAD=$LD_LIB $SUBLIME_HOME/sublime_text $@"
  • 將 libsublime-imfix.so 放入 Sublime 目錄
  • 修改腳本 SUBLIME_HOME 路徑
  • 以此腳本啟動即可正常輸入中文

適用版本

  • Sublime Text 2/3
  • GTK+ 2.0 環境 (主流桌面環境)
  • fcitx、ibus 等主流輸入法框架
copyright © 萬盛學電腦網 all rights reserved