Xfce漫游(4) - 进入桌面环境
书接上文,在连接到dbus之后,xfce4-session就进入事件循环了,而在之前的几步被跳过了。Xfconf是管理各种设置项的,其实就是管理设置项并基于dbus让其他进程能访问整个桌面的设置的进程。顺便一提,xfconfd是个systemd单元而不是xfce4-session手动启动的。总之我们还是关心一下桌面绘制出来的流程吧。
会话恢复或新会话
上回看到了bus_acquired的行为,它首先是创建了实例并把接口信息注册到DBus中。之后的步骤中从xfconf加载了会话(xfsm_manager_load (*manager, channel);),一步步走到xfsm_manager_load_settings:
session_loaded = xfsm_manager_load_session (manager, channel);
if (session_loaded)
{
xfsm_verbose ("Session \"%s\" loaded successfully.\n\n", manager->session_name);
manager->failsafe_mode = FALSE;
}
else
{
gchar *errorstr = NULL;
if (!xfsm_manager_load_failsafe (manager, channel, &errorstr))
{
/* FIXME: migrate this into the splash screen somehow so the
* window doesn't look ugly (right now no WM is running, so it
* won't have window decorations). */
xfce_message_dialog (NULL, _("Session Manager Error"),
"dialog-error", _("Unable to load a failsafe session"),
errorstr,
XFCE_BUTTON_TYPE_MIXED, "application-exit", _("_Quit"), GTK_RESPONSE_ACCEPT, NULL);
g_free (errorstr);
exit (EXIT_FAILURE);
}
manager->failsafe_mode = TRUE;
}
}
代码大意就是读取~/.cache/sessions/xfce4-session-<uuid>中的会话,如果无就failsafe模式加载默认会话。我用了这么久xfce从来不保存会话,所以都是进入了failsafe模式,继续看load_failsafe,其内容大致就是将conf中一个FailSafe方案都推入manager->pending_properties队列中,这个方案的内容是:
- xfwm4: Xfce4的窗口管理器
- xfsettingsd: 管理系统设置
- xfce4-panel: 面板
- Thunar --daemon: 文件管理器的daemon
- xfdesktop: 桌面
当然,如果保存了会话的话,会话中每个保存了的程序都会附有更加详细的信息,程序就按照那里的内容读取。
接下来就是调用xfsm_manager_restart (*manager);启动会话队列中的程序了,兜兜转转之下:
void
xfsm_startup_session_continue (XfsmManager *manager)
{
GQueue *pending_properties = xfsm_manager_get_queue (manager, XFSM_MANAGER_QUEUE_PENDING_PROPS);
gboolean client_started = FALSE;
/* try to start some clients. if we fail to start anything in the current
* priority group, move right to the next one. if we *did* start something,
* the failed/registered handlers will take care of moving us on to the
* next priority group */
while (client_started == FALSE && g_queue_peek_head (pending_properties) != NULL)
client_started = xfsm_startup_session_next_prio_group (manager);
代码的大致意思就是不断从队列弹出,然后启动它。根据如上所述,队列中应该是有5个元素,因此就启动了它们。
应用程序自启动
但是实际上他还需要启动输入法、redshift以及其他用户自定义的自启动程序等。这些东西一般位于~/.config/autostart和/etc/xdg/autostart底下,属于XDG Autostart的管理的部分之一。
之前略过了ENABLE_X11之下的内容,因为代码编辑器没认出这个宏把他标灰色了= = 漏了个init_display没看,反正快进到sm_init,这里向XSM和ICE注册了manager。这俩又是啥。。这就得去找libSM和libICE了,两个都是Xorg提供的库,重点关注第一个就行了,后者是辅助session manager库的。
- libSM: https://www.x.org/releases/current/doc/libSM/SMlib.pdf
- libICE: https://www.x.org/releases/current/doc/libICE/ice.pdf
总之从代码看,当Sm client连入时,会调用sm_new_client。sm client一般指的是一个包含需要在X display上进行显示的进程,不过也不一定,比如各种什么什么d。sm client的功能有:
- 建立与关闭到sm server的连接
- 修改callback
- 设定、删除、修改会话管理器属性
- 与用户交互
- 进行"Save Yourself"系列操作(将自己保存到会话文件)
总之xfce session manager会为每个client都创建一个XfsmClient,它们各自对应DBus connection中的一个对象。之前当会话启动时,从那个队列中不断启动程序时,像xfwm这样的程序就会作为client加入到session manager,于是调用sm_new_client。新client沿用manager的dbus连接,并在那里创建表示自身的新对象。根据协议,当连接建立后,会立刻调用regist client对应的callback。兜兜转转后来到这里:
if ((previous_id != NULL || manager->failsafe_mode)
&& manager->state == XFSM_MANAGER_STARTUP)
{
/* Only continue the startup if the previous_id matched one of
* the starting_properties. If there was no match above,
* previous_id will be NULL here. We don't need to continue when
* in failsafe mode because in that case the failsafe session is
* started all at once.
*/
if (manager->failsafe_mode)
{
if (--manager->failsafe_clients_pending == 0)
g_queue_clear (manager->starting_properties);
}
if (g_queue_peek_head (manager->starting_properties) == NULL)
xfsm_startup_session_continue (manager);
}
这里会多次调用xfsm_startup_session_continue。当队列空时,表示优先级高的程序都已启动,最后完成自启动程序的启动:
if (G_UNLIKELY (client_started == FALSE && g_queue_peek_head (pending_properties) == NULL))
{
/* we failed to start anything, and we don't have anything else,
* to start, so just move on to the autostart items and signal
* the manager that we're finished */
xfsm_verbose ("Nothing started and nothing to start, moving to autostart items\n");
xfsm_startup_autostart (manager);
xfsm_manager_signal_startup_done (manager);
}
}
顺着带autostart的函数稍微探索一下之后,就能找到读取与执行自启动文件的代码。

浙公网安备 33010602011771号