sassc: error while loading shared libraries: libsass.so: cannot open shared object file: No such file or directory
重新安装以下sassc即可:
1 2 3 |
sudo pacman -S sassc |
…Continue reading...
sassc: error while loading shared libraries: libsass.so: cannot open shared object file: No such file or directory
重新安装以下sassc即可:
1 2 3 |
sudo pacman -S sassc |
…Continue reading...
代码如下,将Widget传进函数即可,之后相关属性会相应改变.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
GtkWidget *setWidgetProperties( GtkWidget *entry ) { PangoAttrList *pangoAttrList = pango_attr_list_new(); PangoAttribute *pangoAttribute = pango_attr_weight_new ( PANGO_WEIGHT_BOLD ); pango_attr_list_insert ( pangoAttrList, pangoAttribute ); /* Set bold type*/ pangoAttribute = pango_attr_underline_new(PANGO_UNDERLINE_LOW); pango_attr_list_insert ( pangoAttrList, pangoAttribute ); pangoAttribute = pango_attr_underline_color_new(0x00, 0xc7ff, 0xffff); /* Color Cyan*/ pango_attr_list_insert ( pangoAttrList, pangoAttribute ); pangoAttribute = pango_attr_scale_new( 1.5 ); /* Set font size*/ pango_attr_list_insert ( pangoAttrList, pangoAttribute ); GdkRGBA rgbacolor = { 0, 0, 0, 1 }; /* rgb a: black*/ gtk_widget_override_color( entry, 0, &rgbacolor); gtk_entry_set_attributes ( GTK_ENTRY(entry), pangoAttrList ) ; return entry; } |
详情见注释
也可以进一步封装,根据widget类型,自动调整逻辑,同时适应Entry和Label等的属性设置:
背景:
GTK编程,在函数内部定义了一个结构体,作为指针传递给其他函数,在其他函数内部调用结构体内部成员变量,发现有一个成员变量总是为空,另外一个不会。
原因:
定义结构体的位置在回调函数内部,回调函数运行完成后,结构体所在内存即被回收。
然而有时候在一定时间内回收内存里的数据没有发生改变,所以有些结构体的成员变量还是能够正常获取。
但是在执行其他指令的时候,原结构体部分成员变量的内存会被重用,造成内部数据改变,再去调用的时候,得到的就是完全随机的数据,如果把它当做指针使用,它指向的内存是未知的,未被申请的,再去操作这段内存就会发生段错误。
解决办法:
将结构体定义成 static 类型,让他在程序的整个生命周期内有效,不会被回收。
…Continue reading...
检查是否捕获了 key-press-event,然后又没有 return TRUE,这将导致发生键盘点击事件时,执行完对应回调函数后信号没有再继续传递,没办法被searchEntry捕获,也就没有办法继续输入文本了。
…Continue reading...
Gtk TextView在某些情况下显示的文字会有白色的背景框,显得跟界面格格不入,如下图所示:
上图的源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
#include <gtk/gtk.h> gboolean key_press ( GtkWidget *window, GdkEventKey *event, gpointer *data ); int main(int argc, char **argv) { GtkWidget *window; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(window), 400, 300); gtk_window_set_title(GTK_WINDOW(window), ""); GtkWidget *view = gtk_text_view_new(); GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view)); gtk_text_buffer_set_text ( buf, "窗含西岭千秋雪\n门泊东吴万里船", -1); gtk_text_view_set_editable ( GTK_TEXT_VIEW(view), FALSE ); GtkWidget *hBox = gtk_box_new ( GTK_ORIENTATION_VERTICAL, 0 ); gtk_container_add ( GTK_CONTAINER(window), hBox ); gtk_box_pack_start (GTK_BOX(hBox), view, 0, 0, 0); //GdkColor windowColor = gtk_widget_get_style(window)->bg[GTK_STATE_NORMAL]; //gtk_widget_modify_bg ( view, GTK_STATE_NORMAL, &windowColor ); g_signal_connect(G_OBJECT(window), "destroy", \ G_CALLBACK(gtk_main_quit),NULL); g_signal_connect(G_OBJECT(window), "key-press-event", \ G_CALLBACK(key_press),NULL); gtk_widget_show_all(window); gtk_main() |
方法一:直接调用函数获得
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
int ax, ay; /* absolutely postition*/ int wx, wy; /* The absolutely position of the left up corner of window*/ int rx, ry; /* The position of the pointer relative to the left up corner of window*/ GdkDisplay *display = gdk_display_get_default (); GdkSeat *device_manager = gdk_display_get_default_seat (display); GdkDevice *device = gdk_seat_get_pointer (device_manager); /*获取指针在屏幕上的绝对坐标*/ gdk_device_get_position (device, NULL, &ax, &ay); /*获取窗口左上角在屏幕上的绝对坐标*/ gdk_window_get_position ( gtk_widget_get_window(window), &wx, &wy ); rx = ax - wx; /*通过计算获取指针相对于窗口的坐标rx*/ ry = ay - wy; /*通过计算获取指针相对于窗口的坐标ry*/ |
详情见注释,注意window变量来自 Gtkwidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 代码中没有给出
方法二: 注册回调函数获得
1 2 3 4 |
/*主函数内*/ g_signal_connect(window, "motion-notify-event", G_CALLBACK(deal_motion_notify_event), NULL); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/*回调函数*/ gboolean deal_motion_notify_event ( GtkWidget *widget, GdkEventMotion *event, gpointer *data) { int wx, wy; /* The absolutely position of the left up corner of window*/ int rx, ry; /* The position of the pointer relative to the left up corner of window*/ gdk_window_get_position ( gtk_widget_get_window(window), &wx, &wy ); |
在做Linux取词翻译软件的时候,UI编程使用的是Gtk,翻译界面的逻辑代码被放置于某个线程内,途中会进行多次的创建与销毁,Gtk窗口除了第一次能够成功聚焦,之后就再也无法成功,写了短小的测试用例,发现每次进行进程创建可以保证窗口聚焦。
但是考虑到各个线程中众多的共享数据,另开进程进行数据通信的代价太过于大,主要是进程有独立的地址空间,彼此间通信要借助IPC的方式,而且无论是代码的重构还是之后的调试都将耗费巨大的精力。
而后开始寻找解决办法,尝试了好几个小时在Gtk内部查找问题,换了或增加了各种各样的窗口聚焦相关代码,仍旧不可行。
接着想到了另一个突破口,平时Alt-tab键可以进行窗口切换,本质就是聚焦窗口的改变,巡着这条路想起xdotool好像有这个功能可以激活特定窗口(亦即聚焦窗口)。
然后在终端尝试了一下,果然,用 xdotool windowactivate <窗口id>
可以激活窗口!马上阅读源码,很快找到了相关实现的函数,在里面添加了些log的打印进行进一步定位,或者注释掉一些可能实际起作用的代码后,程序窗口激活功能即刻失效,由此得到几行关键代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
int xdo_activate_window(const xdo_t *xdo, Window wid) { int ret = 0; long desktop = 0; XEvent xev; XWindowAttributes wattr; if (_xdo_ewmh_is_supported(xdo, "_NET_ACTIVE_WINDOW") == False) { fprintf(stderr, "Your windowmanager claims not to support _NET_ACTIVE_WINDOW, " "so the attempt to activate the window was aborted.\n"); return XDO_ERROR; } /* If this window is on another desktop, let's go to that desktop first */ if (_xdo_ewmh_is_supported(xdo, "_NET_WM_DESKTOP") == True && _xdo_ewmh_is_supported(xdo, "_NET_CURRENT_DESKTOP") == True) { xdo_get_desktop_for_window(xdo, wid, &desktop); xdo_set_current_desktop(xdo, desktop); } memset(&xev, 0, sizeof(xev)); xev.type |
最近用到GtkSearchEntry的编程,其中一个信号是stop-search,对应绑定的默认快捷键是ESC,一般捕获为退出信号,感觉不顺手,想绑定到Ctrl-C,中途遇到了问题,查看全网没有发现解决方案,但是从StackOverFlow的这篇文章里找到一点灵感 Gtk3 keys bindings in css files。特此记录此问题的解决过程和思路。
查看Gtk开发手册,如下:
1 2 3 4 5 |
void user_function (GtkSearchEntry *entry, gpointer user_data) |
The ::stop-search signal is a keybinding signal which gets emitted when the user stops a search via keyboard input.
Applications should connect to it, to implement hiding the search entry in this case.
The default bindings for this signal is Escape.
entry | the entry on which the signal was emitted | |
user_data | user data set when the signal handler was connected. |
Flags: Action
Since: 3.16
通过描述可以看到stop-search是键盘绑定信号,用户输入特定键盘触发后发射出该信号。
点进 keybinding signal ,找到文章开头的一些函数:
void | gtk_binding_entry_add_signall () |
GtkBindingSet * | gtk_binding_set_new () |
GtkBindingSet * | gtk_binding_set_by_class () |
GtkBindingSet * | gtk_binding_set_find () |
gboolean | gtk_bindings_activate () |
gboolean | gtk_bindings_activate_event () |
gboolean | gtk_binding_set_activate () |
void | gtk_binding_entry_add_signal () |
GTokenType | gtk_binding_entry_add_signal_from_string () |
void | gtk_binding_entry_skip () |
void | gtk_binding_entry_remove () |
void | gtk_binding_set_add_path () |
其中看着比较像的是gtk_binding_entry_add_signal (),点进去看函数原型:
1 2 3 4 5 6 7 8 9 |
void gtk_binding_entry_add_signal (GtkBindingSet *binding_set, guint keyval, GdkModifierType modifiers, const gchar *signal_name, guint n_args, ...); |
Override or install a new key binding for keyval with modifiers on binding_set . When the binding is activated, signal_name will be emitted on the target widget, with n_args Varargs used as arguments.
Each argument to the signal must be passed as a pair of varargs: the GType of the argument, followed by the argument value (which must be of the given type). There must be n_args pairs in total.
keyval(键值),modifiers(修饰符),和signal_name(信号名)容易知道,比如我想要绑定到Ctrl-C,那么keyval就是c,modifiers就是control,signal-name就是stop-search,但是写法可能要替换成一些特定的宏,这些问题不大,从gtk的源码中找到规律,keyval一般写成 GDK_KEY_c 这种格式,Control写成 GDK_CONTROL_MASK , signal-name还是原来的字符串不用变。
问题最大的是GtkBindingSet如何获取,它的原型是一个结构体,里面包含很多变量,我们不可能自己定义一个,因为这在Gtk源码中肯定已经定义过了,目的到现在变成了如何获取这个GtkBindingSet。
再细看上面的一些函数,其中有3个返回值都是GtkBindingSet,大概率是从这里入手,通过名称可以排除包含new的函数,因为是获取已有的,而不是new一个新的,剩下两个通过对比确定为如下目标函数:
1 2 3 4 |
GtkBindingSet * gtk_binding_set_by_class (gpointer object_class); |
This function returns the binding set named after the type name of the passed in class structure. New binding sets are created on demand by this function.
Parameters
object_class | a valid GObject class |
the binding set corresponding to object_class .
至于为什么选这个,首先从它的内部传参可以看出,只需要传进一个有效的GObject class 即可。
因此,问题再进一步,变成:如何获取GObject class
到这里,感觉离目标已经越来越接近,但是对于Gtk Class了解不够,且不太懂得该如何获取,其内部机制也不了解。
一个很关键的思路转折出现了,既然GtkSearchEntry是继承自GtkEntry,那么关键突破点不应该只在GtkSearchEntry中找,很有可能在其继承的基类中存在一些我们要的结果。
而类名一般与部件widget名相关,即,可能对我们有帮助的类名是GtkSearchEntryClass或者是GtkEntryClass,接着我在Gtk源码根目录输入如下命令:
1 2 3 |
grep GtkEntryClass -r |
从输出结果中看到这么一行
1 2 3 |
gtkentry.c: GtkEntryClass *class |
let headTxt=getline(1) 获取第一行赋值给字符串headTxt
1 2 3 4 5 6 7 8 9 10 11 |
if &filetype == "c" let headTxt=getline(1) if headTxt == "#include <gtk/gtk.h>" exec "!gcc `pkg-config --cflags --libs gtk+-3.0` % -o %<" exec "!./%<" else exec "!gcc % -o %< -lm -lreadline" exec "!./%<" endif |
可以将上述逻辑放在一个函数里,绑定到特定键盘,当调用这个函数的时候,自动判断,如果是关于Gtk的C文件,则执行第一个gcc编译操作,否则执行第二个。…
Continue reading...