存档

文章标签 ‘gnome’

Openfetion for ubuntu messaging menu开发手记

五月 3rd, {2011 7 条评论 11,441 人阅读过  

自从ubuntu11.04发布之后Openfetion就遇到了一个比较麻烦的问题,把Openfetion飞信最小化到托盘之后就找不到了,没用过ubuntu11.04,不过据说它的unity桌面貌似没有status icon这回事,所以把Openfetion塞进Messaging Menu也成了一个很重要的任务,在这里把开发过程和大家分享。

首先要感谢@YunQiangSu提供的关于ubuntu messaging menu的资料,是在ubuntu wiki上关于Messaging Menu的介绍,链接在此:https://wiki.ubuntu.com/MessagingMenu/,这篇文章是关于Messaging Menu的一个介绍,以及它的行为和样式的一个指南,虽然没有涉及到具体的开发细则,但也不失为一个很重要的参考。很惭愧地说,在这之前我甚至不知道在ubuntu右上角看到的那个信封到底叫什么名字,后来知道它原来是一个Indicator,ubuntu的status icon区域很多软件都是用libappindicator来实现的,所以它们的行为和其它的发行版不太一致,比如Dropbox和Transimission左键点击Status Icon就可以弹出菜单,而在Slackware里面就只能用右键才能弹出菜单,这就是它们的不同,一个是Indicator,一个是普通的Gnome Status Icon,而这里面提到的右上角的那个信封便是Indiactor的一种,名字叫做Messaging Menu。好吧,我相信很多ubuntu用户会过来鄙视我的,写下这些给那些和我一样的小白扫扫盲,有误请指正。

我们可以把软件安装到Messaging Menu里面,这样即使软件没有启动也可以在Messaging Menu里面找到该软件,并可以从那里启动该软件,方法很简单。下面是pidgin的做法:

mkdir -p debian/pidgin/usr/share/indicators/messages/applications
echo /usr/share/applications/pidgin.desktop > \
		 debian/pidgin/usr/share/indicators/messages/applications/pidgin

这两句话的功能一眼就看地出来,无须解释了。

Messaging Menu相关的开发需要用到libindicate这个库,首先得确保在系统里面安装了这个库的开发版本:

sudo apt-get install libindicate-dev

首先我们需要获取默认IndicateServer对象的引用,并对其进行初始化:

IndicateServer *server = indicate_server_ref_default();
/* 这句话给软件分类,主要是保存位置不同 */
indicate_server_set_type(server, "message.openfetion");
/* 这句话比较重要,它会让已安装在Messaging Menu里面的软件项前面带一个箭头,
 * 表示该软件当前正在运行,效果图见下面 */
indicate_server_set_desktop_file(server, DESKTOP_DIR"openfetion.desktop");
indicate_server_show(server);
g_signal_connect(G_OBJECT(server), INDICATE_SERVER_SIGNAL_SERVER_DISPLAY, 
		G_CALLBACK(server_display), fxmain);

当收到好友发送过来的消息时可以在该项后面显示哪个好友发送过来的消息,以及显示未读消息的条数,效果图如下:

这时候就需要给当前的这个IndicateServer对象添加一个IndicateIndicator对象,并为该对象设置相关的属性,如name(即显示Indicator上显示的名字),count(未读消息的数目),time(消息发送的时间),icon(像如发送消息好友的头像),draw-attention(这个属性可以随便设置一个非空字符串,以使Indicator高亮提示用户有消息到达,同理设置空字符串可取消高亮)。
上面的几个属性除了time和icon之外都可以用indicate_indicator_set_property()函数来搞定,该函数设置的属性值都是字符串,time是一个时间值,需要使用indicate_indicator_set_property_time()函数来进行设置,至于icon属性的设置需要用到另外一个库libindicate-gtk,这个库仅提供了两个函数,其中一个便是indicate_indicator_set_proper_icon()用来设置icon属性,属性值是一个GdkPixbuf对象。下面看Openfetion上收到一条消息时Messaging Menu所对的动作:

/* no indicator found, create one :) */
indicator = indicate_indicator_new();
/* add it to the global indicator list */
indicators = g_slist_append(indicators, indicator);
indicate_server_add_indicator(server, indicator);
 
indicate_indicator_set_property(indicator, INDICATE_INDICATOR_MESSAGES_PROP_COUNT, "0");
indicate_indicator_set_property(indicator, "sid", sid);
/* set icon */
snprintf(portrait, sizeof(portrait) - 1, "%s/%s.jpg", fxmain->user->config->iconPath, sid);
pixbuf = gdk_pixbuf_new_from_file(portrait, NULL);
indicate_indicator_set_property_icon(indicator, INDICATE_INDICATOR_MESSAGES_PROP_ICON, pixbuf);
g_object_unref(pixbuf);
 
g_signal_connect(G_OBJECT(indicator), INDICATE_INDICATOR_SIGNAL_DISPLAY,
		G_CALLBACK(message_display), NULL);
 
indicate_indicator_show(indicator);

首先我们需要确定在Messaging Menu中是否已经有该用户对应的Indicator存在,如果有就没有必要再创建一个新的造成重复,而检测重复性这个问题费了我不小的力气,libindicate没有提供获取列表的API,但查了一下它的源码,发现它确实实现了一个获取列表的函数,它把它定义为虚函数,推荐用户从这个类继承,我对GTK的C语言面向对象的机制不太了解,不知道该怎么去继承,但既然有这个函数就可以想办法拿来调用,能获取到Indicator列表,但这个列表简直让我抓狂,一个GArray列表,里面存放的是Indicator的id,一个毫无用处的数字,通过它根本获取不到Indicator对象,更不用说Indicator对象的属性了,因此我只能用自己的方法来实现了,其实很简单,就是每创建一个Indicator对象就把它塞到一个GSList里面,创建之前搜索该链表,如果其中有indicator的sid值与要创建的sid相同,则表示已存在,无需再重新创建,把它的count值加1即可。

有一点需要注意的是libindicate-gtk新旧版本的pc文件名是不同的(感谢@riku的测试),在10.04上是旧版pc文件名是indicate-gtk.pc,因此编译选项可以是

pkg-config --cflags --libs indicate-gtk

而在ubuntu 11.04中文件名是indicate-gtk-0.5.pc,编译选项便是:

pkg-config --cflags --libs indicate-gtk-0.5

我在CMakeLists.txt做了一些处理来让它自动识别这两个版本的不同。

分类: C/C++ 标签: ,

slackware13.1安装配置手记

八月 17th, {2010 9 条评论 10,375 人阅读过  

近日实验室一台thinkpad挂在我名下,为了防止资源的闲置浪费我决定拿过来用一段时间,正好也是项目需要,之前的程序需要gnome NetworkManager的支持,我前一段不得已时间在slackware13.0上将xfce换成了gnome,然后又装NetworkManager,后来还是没有成功,装是装好了,可 dbus仍有问题,程序跑不起来,不得已用了在这台机器上装了个ubuntu用了几天,现在项目中期已过,差不多该回过头来整理一下操作系统了,还是钟爱于slackware,而且早就想试一下13.1,正好借这个机会尝试一下。

从slackware官网上下了前两个cd,把vmlinz和initrd.gz解压出来放到了ubuntu的某个目录下,然后把第一个cd解压出来或者在安装的时候临时挂载也行,我是解压出来了,然后就是硬盘安装的各种熟悉的步骤了,只不过这次的grub是ubuntu的grub2,有一点不一样,在加载内核文件的时候需要用linux命令,而不是kernel命令,其它的都一样,之前在安装系统的时候分区用的是cfdisk,这次联想把这个分区表弄得很乱,cfdisk打不开,于是用fdisk分区,其实我已经划好了一块分区准备留给slackware的,只要用mkfs格式化成ext3或者ext4就可以了,格式化完之后还不行,slackware还是检测不到linux分区,需要修改分区的system id:

1
sudo fdisk /dev/sda

然后选择t将分区的system id修改为83,也就是linux分区,w写进分区表就可以啦,fdisk就会显示分区是Linux,而不是FAT12了,这样就可以进行系统安装了,setup就可以了,其它的就没什么特别的了。

这次在系统安装的时候我只安装了cd1,cd2是系统安装完成之后手动安装的,里面有linux source和一些常用的软件还有xorg,这次没有安装xfce,xfce已经让我审美疲劳了,而且这台机器配置也不错,装gnome也不会慢多少,接下来就要安装gnome了。

其实slackware的包管理工具也是很出色的,有slackpkg和slapt-get可以用,而且也都很不错,只不过在国内都找不到它们可用的源,能用的只有官方提供的源,而且都放在国外,教育网要用的话只能加代理,用起来有点麻烦,我比较喜欢slap-get,首先到gsb(Gnome Slackbuild)上下载slapt-get安装,更新一下配置文件

1
sudo vim /etc/slapt-get/slapt-getrc

我把所有的源都注释掉了,只用了下面的一个:

SOURCE=http://get.gnomeslackbuild.org/gsb/gsb-2.30_slackware-13.1/:PREFERRED

然后更新一下源:

1
sudo slapt-get --update

获取密钥:

1
sudo slapt-get --add-keys

在教育网内这些操作之前需要设置代理的环境变量

1
export http_proxy=http://username:password@proxy.bupt.edu.cn:8080

教育网就这点让人不爽,我边githug,sourceforge的svn都用不了。

更新一下系统:

1
sudo slapt-get --upgrade

更新完之后会有一个神奇的现象,我在环境变量里面设置代理貌似对slapt-get就不好用了,每次用slapt-get的时候需要为每条命令都设置代理环境变量才行,如下:

1
sudo http_proxy=http://username:password@proxy.bupt.edu.cn:8080 slapt-get --install gsb-desktop

不知道是什么原因,有懂行的帮忙解释下。

另外上面那条命令就是安装gnome的命令,大约过个十几二十分钟就装完了。

系统的汉化应该没什么问题,不像ubuntu那样还要去下载语言包,slackware已经集成了中文包,只要在/etc/profile.d/lang.sh里面改一下locale的环境变量就可以了。

1
2
3
export LANG=zh_CN
export LC_CTYPE=zh_CN.UTF-8
export LC_TIME=zh_CN.UTF-8

另外这里还要提一下ubuntu的locale设置,它貌似默认的设置都是zh_CN.ut8,其实locale对大小写是敏感的,如果是utf8的话大部分功能都没问题,就是gvim会出问题,各种报错和菜单的中文不显示等问题,最好还是改成zh_CN.UTF-8

OK,汉化也没问题了,重启一下就是中文的了,而且gnome也不会乱码。至于怎么装gdm怎么设置启动的运行级别以前写的一篇安装手记里面貌似都提过了,也很简单,没什么好说的了。

输入法还是小企鹅用得最顺手,去他们官网上下了个最新版的,好像是今天2月份才发布的版本,很不错,界面现在很漂亮,不像以前那些版本那么老土,不过这几天 fcitx经常自己消失了,不知道是不是有什么bug,也可能是我设置的有问题,不过影响不大。

gnome还是很强大的,既然用它就要把它的功能都利用起来,gnome的自动挂载那个功能是用起来最方便的,也不用自己再费劲去改fstab了,但slackware默认情况下是不好用的。

点击分区符的时候报下面的错误:

Cannot mount volume

Error org.freedesktop.DBus.Error.AccessDenied.

这个错误搭眼一看就知道是dbus的问题,幸亏之前耕宇的代码用到了dbus,我也跟着对dbus的原理有了点简单的了解,不过看这错误的命名规则跟java挺像的,不知道它底层是不是用java实现的,谁知道的。

不管怎么说,错误很明显地告诉我这是权限的问题,找了一顿在/etc/dbus-1/system.d/hal.conf里面找到了关于Volume和Storage的相关配置内容。

里面有这样一段话:

<policy group=”plugdev”>
<allow send_destination=”org.freedesktop.Hal”
send_interface=”org.freedesktop.Hal.Device.Storage”/>
<allow send_destination=”org.freedesktop.Hal”
send_interface=”org.freedesktop.Hal.Device.Storage.Removable”/>
<allow send_destination=”org.freedesktop.Hal”
send_interface=”org.freedesktop.Hal.Device.Volume”/>
<allow send_destination=”org.freedesktop.Hal”
send_interface=”org.freedesktop.Hal.Device.Volume.Crypto”/>
</policy>

很显然,只有在plugdev分组里面的用户才有这些权限,这个简单,把用户添加到这个分组里面就可以了,用户是可以属于多个分组的,用下面命令:

1
sudo usermod -G plugdev,audio levin

如果用户要属于多个分组的话就必须将多个分组用逗号隔开,否则用户就只会被添加到一个分组里面去,即只属于那一个分组了。

当然也可以修改/etc/group文件,之后最好再运行一下grpck命令更新一下gshadow文件。

这样就应该就没问题了,再点击分区符就可以成功挂载分区了。另外我上面把用户也添加到audio分组里面了,因为我新创建的用户不属于audio组,导致我的系统没有声音,这个很悲剧,alsaconf配置一下声卡就可以了。

对于挂载的另一种解决方案就是添加一段跟上面的xml相同的话,把groups改成当前用户的分组,那样也可以,我是那么干的。

最烦人的问题是 NetworkManager,我之前都不用的,现在因为项目程序里面用到了,最好还是装上,要不然这台机器就只能用来干私活了。

其实gsb为slackware13.1做的gnome里面已经集成了NetworkManager,但是默认的是跑不起来的, NetworkManager也用了dbus,用刚才的办法去找它的配置文件,修改分组也好,修改配置文件也行。

然后把/etc/rc.d/rc.networkmanager这个脚本的可执行权限给加上。

这样NetworkManager虽然能用了,但还是不能开机启动,关健的方法我自己没琢磨出来,到网上找到的解决方案:

在/etc/NetworkManager/nm-system-settings.conf这个文件里面添加下面这一句话就可以让NetworkManager开机自动启动。

managed=true

另外,还需要NetworkManager的托盘图标,就是nm-applet,把它直接在“启动应用程序”里面添加上就可以让它自动启动了。

一个神奇的问题是,开机后虽然NetworkManager启动了,而且也显示连接成功了,可ifconfig里面的eth0就是没有地址,系统安装完成之后我用

1
sudo netconfig

配置网络为dhcp方式自动获取地址,而且在启动的过程中它也确实显示成功获取到了地址,但开机这后就是没有地址。

而且我用

1
sudo dhclient eth0

获取地址之后,过个2s之后地址又没了,我都晕了,然后我尝试一下用下而把方法把网络停止:

1
sudo /etc/rc.d/rc.inet1 stop

之后再用dhclient获取地址,或者用NetworkManager获取地址都可以,能够正常上网,但这种情况下我的firefox时面菜单弹出相当迟钝,而且还有更神奇的问题是我的gvim里面会有闪铄,这都是些什么问题,我也不清楚slackware自己的网络配置和NetworkManager到底有什么冲突,反正后来我无耐之下用netconfig 把网络地址设成loopback,之后再重启让NetworkManager获取地址就OK了,问题是解决了,但还是觉得挺神奇的,不知道NetworkManager都干了些什么。

其它的就没什么问题了,换了我长期使用的主题T-ish,图标主题是从gsb的源里面找到的一个,感觉不错,也用了很久,叫Neu,在gnome-look上没找到。

删掉了slackware安装cd里面带的firefox3.6.3,安装了3.6.8中文版。

字体以前是用Vera Sans YuanTi,后来用了几天的ubuntu,发现其实微软雅黑看上去确实挺漂亮的,也装了一下,挺舒服的。其它的就没什么特别的了,我也几乎不需要什么娱乐,有个smplayer能看个电影就行,把所有的音乐播放器都删了,电脑上一首歌也没有,都是在线听的,另外有个Adobe Reader和Vim就够了。

分类: Linux 标签: ,