主要原因是因为他来暴我的菊花。
代码行数
fcitx-googlepinyin:695行,scim-googlepinyin:3892行
fcitx-sunpinyin:697行,scim-sunpinyin:1856行,ibus-sunpinyin:引擎 2944 行 + py配置 597行。
今天被GNOME3操暴了。
录视频骂他。
首先是gnome3的alt tab,我从firefox 切到gnome-terminal很正常,反过来就会默认高亮在gnome-terminal上,导致我按一下切不过去。怎么用都不顺手.
其次改窗口大小,即使有aero snap,有时候我也想要点别的大小的窗口,首先边框太窄,左右下角很难按到,然后是左上正常,右上不能调整。
然后是搜索程序界面,这对于geek来说怎么样也应该是个纯键盘的操作,然后我搜出来3个,横向排列。结果直接他妈必须用上下而不是左右键选择。
再其次是gnome-tweak-tool的小问题,tab不能靠拖着切换。然后随便用kwrite对比了一下。(小问题而已。)
最后就是纯傻逼的把托盘图标分成两份,和indicator不一样的是,老式图标其实可以放在上面,其实只需要一个过滤器。这直接把所有应用程序强暴了。(这个我早知道了,前面的是今天遇到的问题,我以后一定要在程序里面放彩蛋骂gnome)
今天我刚一开始用就感觉呼吸不畅胸闷,然后它就立马把我给操了。要不是我想要为可怜的fcitx+gnome3用户开发插件,我才他妈不装这破玩意呢。
Welcome for test
$ pacman -Q fcitx-hg fcitx-hg 600-1
Welcome for test. 我确定它一定会有bug的……我也刚刚开始日常使用而已。
另外皮肤配置有改动(抱歉抱歉……不过功能没少……),改日再写一个新的说明。
PKGBUILD:
http://www.wuala.com/csslayer/pkgbuild/
关于代码风格和宏
这是个反思的时机。
由于现在fcitx只有我一个人修改,不需要合作的时候怎么写都无所谓。主要是让一位兄弟望而却步。
我的代码风格到底猎奇吗?
他对于libfcitx-config这个库的意见最大
fcitx的代码现在总体上受了很多其他的代码影响,比如插件的设计,灵感来源于compiz,包括配置文件的设计,比如采用独立文件描述配置文件,这样fcitx-config-gtk就可以像ccsm一样简单设计了。同时为了易于手动修改,于是采用了类ini的写法。
然后为了在代码中方便取用配置文件的值,可以将配置文件的值和一个c的struct绑定,为了方便描述这种绑定这里使用了大量的宏。
使用宏的习惯是我从Postgresql继承来的,学校的开发涉及Postgresql,里面也使用了很多宏,比如系统表的初始值,系统表的定义。
CONFIG_BINDING_BEGIN(FcitxPinyinConfig);
CONFIG_BINDING_REGISTER("Pinyin", "PinyinPriority", iPinyinPriority);
CONFIG_BINDING_REGISTER("Pinyin", "ShuangpinPriority", iShuangpinPriority);
CONFIG_BINDING_REGISTER("Pinyin", "DefaultShuangpinSchema", strDefaultSP);
CONFIG_BINDING_REGISTER("Pinyin", "UseCompletePinyin", bFullPY);
CONFIG_BINDING_REGISTER("Pinyin", "AutoCreatePhrase", bPYCreateAuto);
CONFIG_BINDING_REGISTER("Pinyin", "SaveAutoPhrase", bPYSaveAutoAsPhrase);
CONFIG_BINDING_REGISTER("Pinyin", "AddFreqWordKey", hkPYAddFreq);
CONFIG_BINDING_REGISTER("Pinyin", "DeleteFreqWordKey", hkPYDelFreq);
CONFIG_BINDING_REGISTER("Pinyin", "DeleteUserPhraseKey", hkPYDelUserPhr);
CONFIG_BINDING_REGISTER_WITH_FILTER("Pinyin", "InputWordFromPhraseKey", strPYGetWordFromPhrase, FilterGetWordFromPhrase);
CONFIG_BINDING_REGISTER("Pinyin", "BaseOrder", baseOrder);
CONFIG_BINDING_REGISTER("Pinyin", "PhraseOrder", phraseOrder);
CONFIG_BINDING_REGISTER("Pinyin", "FreqOrder", freqOrder);
CONFIG_BINDING_REGISTER_WITH_FILTER("Pinyin", "FuzzyAnAng", MHPY_C[0].bMode, FilterAnAng);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzyEnEng", MHPY_C[1].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzyIanIang", MHPY_C[2].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzyInIng", MHPY_C[3].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzyOuU", MHPY_C[4].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzyUanUang", MHPY_C[5].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzyCCh", MHPY_S[0].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzyFH", MHPY_S[1].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzyLN", MHPY_S[2].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzySSH", MHPY_S[3].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzyZZH", MHPY_S[4].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "Misstype", bMisstype);
CONFIG_BINDING_END()
比如这段代码。
宏的目的是为了使得机械重复的代码变得精简已读。那么这里如何呢?我觉得除了分号的使用(最后应该统一不用分号最好……),明显把这部分变得更加易读了(个人观点)。如果宏加上合适的文档说明,应该可以明确表达出这段代码的含义。
再谈到关于模块之间的互相调用。这部分的思想同样来源于Postgresql。以及之前看到的关于ABI的文章。
每个模块有自己的名称(固定不变),每个模块注册对应的函数,每个函数有自己的ID(固定不变),每个函数有固定的参数。真实参数通过这个固定参数的一个结构体传递,全部传递指针。
#define FCITX_X11_NAME "fcitx-x11"
#define FCITX_X11_GETDISPLAY 0
#define FCITX_X11_GETDISPLAY_RETURNTYPE Display*
#define FCITX_X11_ADDXEVENTHANDLER 1
#define FCITX_X11_ADDXEVENTHANDLER_RETURNTYPE void
#define FCITX_X11_REMOVEXEVENTHANDLER 2
#define FCITX_X11_REMOVEXEVENTHANDLER_RETURNTYPE void
#define FCITX_X11_FINDARGBVISUAL 3
#define FCITX_X11_FINDARGBVISUAL_RETURNTYPE Visual*
#define FCITX_X11_INITWINDOWATTR 4
#define FCITX_X11_INITWINDOWATTR_RETURNTYPE void
#define FCITX_X11_SETWINDOWPROP 5
#define FCITX_X11_SETWINDOWPROP_RETURNTYPE void
#define FCITX_X11_GETSCREENSIZE 6
#define FCITX_X11_GETSCREENSIZE_RETURNTYPE void
#define FCITX_X11_MOUSECLICK 7
#define FCITX_X11_MOUSECLICK_RETURNTYPE void
// 实际函数示例
static void* X11GetDisplay(void* x11priv, FcitxModuleFunctionArg arg);
这里注册的是X11的模块名称以及相关函数。宏名称的定义的格式是约定好的。
typedef struct FcitxModuleFunctionArg
{
void* args[10];
} FcitxModuleFunctionArg;
void* InvokeModuleFunctionWithName(struct FcitxInstance* instance, const char* name, int functionId, FcitxModuleFunctionArg args);
#define InvokeFunction(INST, MODULE, FUNC, ARG) \
((MODULE##_##FUNC##_RETURNTYPE) InvokeModuleFunctionWithName(INST, MODULE##_NAME, MODULE##_##FUNC, ARG))
实际调用的时候使用InvokeFunction这个宏。这样实际调用的时候就是这样子。可以明显看出是调用FCITX_X11的GETDISPLAY函数。
dpy = InvokeFunction(instance, FCITX_X11, GETDISPLAY, arg);
关于以上写法,诸君,你们以为呢。(实际毫无反省之意……)