Free yourself from fixing complex.
eleven

Sublime Text实在太好用了,我都好久没有用过VIM了。
不知道从什么时候起,ubuntu下的中文输入突然不能用了(fcitx/ibus都无效)。在这里,我找到一个比较完美的解决方案:

  • 安装编译依赖:
    [cc lang="bash"]sudo apt-get install libgtk2.0-d[/cc]
  • 然后在任意位置以下面的内容新建文件sublime\_imfix.c:
    [cc lang="c"]
    /*
    sublime-imfix.c
    Use LD\_PRELOAD to interpose some function to fix sublime input method support for linux.
    By Cjacker Huang
    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;
    //The caret width is 2;
    //Maybe sometimes we will make a mistake, but for most of the time, it should be the caret.
    if(rectangle->width == 2 && GTK\_IS\_IM\_CONTEXT(local\_context)) {
    gtk\_im\_context\_set\_cursor\_location(local\_context, rectangle);
    }
    }
    //this is needed, for example, if you input something in file dialog and return back the edit area
    //context will lost, so here we set it again.
    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);
    }
    [/cc]

  • 编译这个文件:
    [cc lang="bash"]gcc -shared -o libsublime-imfix.so sublime\_imfix.c pkg-config --libs --cflags gtk+-2.0 -fPIC[/cc]
    如果一切顺利,会生成一个libsublime-imfix.so,把它移动到sublime text的安装目录,如:
    [cc lang="bash"]mv libsublime-imfix.so /opt/sublime\_text[/cc]
  • 修改/usr/bin/subl的内容为:
    [cc lang="bash"]

    !/bin/sh

    sh -c "LD\_PRELOAD=/opt/sublime\_text/libsublime-imfix.so /opt/sublime\_text/sublime\_text '$@'"

    exec /opt/sublime\_text/sublime\_text "$@"

    [/cc]
    修改/usr/share/applications/sublime\_text.desktop内容为:
    [cc lang="bash"]
    [Desktop Entry]
    Version=1.0
    Type=Application
    Name=Sublime Text
    GenericName=Text Editor
    Comment=Sophisticated text editor for code, markup and prose
    Exec=/usr/bin/subl %F
    Terminal=false
    MimeType=text/plain;
    Icon=sublime-text
    Categories=TextEditor;Development;
    StartupNotify=true
    Actions=Window;Document;
    [Desktop Action Window]
    Name=New Window
    Exec=/usr/bin/subl -n
    OnlyShowIn=Unity;
    [Desktop Action Document]
    Name=New File
    Exec=/usr/bin/subl --command new\_file
    OnlyShowIn=Unity;[/cc]

     

    最后得到:

    之所以前面说“比较完美”,是因为如果以root权限运行:sudo subl something,输入法依然不可用。我估摸着大概是因为系统不允许以root身份加载那个so文件吧。

补丁作者的信息可以从C代码的头部注释中找到。

2013-09-18