重要的概念
LightDM Greeter是什么?它是一个登录管理器,用于在Ubuntu或其他基于Linux的操作系统中管理用户登录。它提供了一个图形化用户界面,用户可以在其中输入他们的用户名和密码以及选择登录的桌面环境。LightDM Greeter还提供了可定制的选项,如自定义主题和背景图像。它是一个轻量级的登录管理器,可以与各种桌面环境和窗口管理器一起使用。
如果把系统比作一栋建筑,Greeter就像是那个门卫——它还不算是警卫。通过LightDM的配置把它屏蔽,用户可以长驱直入。下文以Linux Deepin系统开发的lightdm-deepin-greeter为样本。其它系统大同小异。LightDM视角下Greeter流程如下图所示:
配置部分
lightdm配置
LightDM支持以下位置的配置文件:
/usr/share/lightdm/lightdm.conf.d/*.conf
/etc/lightdm/lightdm.conf.d/*.conf
/etc/lightdm/lightdm.conf
当多个配置文件存在相同配置时以最后的配置文件的配置为依据,读取顺序从上到下。dde-session-shell直接修改最后一个配置文件/etc/lightdm/lightdm.conf
,把greeter-session
设置为lightdm-deepin-greeter
。
Desktop文件
代码里面的files文件夹下的lightdm-deepin-greeter.desktop
文件就是按照LightDM的要求写的配置文件,内容如下:
[Desktop Entry]
Name=Deepin Lightdm Greeter
Comment=Deepin Lightdm Greeter
Exec=/usr/bin/deepin-greeter
Type=Application
X-Ubuntu-Gettext-Domain=deepin-lightdm-greeter
CMakeLists.txt
第396行代码是关于这个文件的安装规则代码,它指定安装包把这个Desktop文件复制到/usr/share/xgreeters/
下面。
Desktop文件其中的Exec
指定启动/usr/bin/deepin-greeter
这个文件。
Shell部分
deepin-greeter
deepin-greeter
是一个shell文件,代码位于files
文件夹下,代码如下:
for i in /etc/deepin/greeters.d/*; do
$i
done
CMakeLists.txt
第387行代码是关于这个文件的安装规则代码,它指定安装包把这个shell文件复制到/usr/bin/
下面。
它的作用是遍历/etc/deepin/greeters.d/
下面的所有可执行文件,把它们依次轮流启动执行。
深度shell
这部分shell代码不在dde-session-shell工程代码里面。其中存在2个关键的shell,第一个是00-xrandr
。文件名为什么要加00-
呢?因为这个shell是用来获取显示设备最大支持的分辨率并改变分辨率。按照deepin-greeter
这个shell的依次循环执行做法,为了保证先设置分辨率后启动界面应用,所以加了这个前缀。它的代码如下:
#!/bin/bash
#
# xrandr 输出的主屏幕有可能是断开的
# $ xrandr|egrep -o '^.* (connected|primary)'
# DVI-I-0 disconnected primary
# DVI-I-1 connected
# VGA-1-1 connected
xinfo(){
local IFS=$'\n'
XINFO=($(xrandr|egrep -o '^.* connected( primary)?'))
}
# 仅当连接两个屏幕时进行如下操作
if xinfo && ((${#XINFO[@]} == 2)); then
# 假设第一行为主屏
primary=(${XINFO[0]})
second=(${XINFO[1]})
# 如果第二行输出含有 primary, 则交换
if ((${#second[@]} == 3)); then
primary=(${XINFO[1]})
second=(${XINFO[0]})
fi
xrandr --output ${second[0]} --right-of ${primary[0]} --auto
fi
第二个是lightdm-deepin-greeter
。注意这还是个shell,不是Qt编译的二进制可执行文件。它的代码是:
#!/bin/bash
display_daemon="/usr/lib/deepin-daemon/greeter-display-daemon"
if [ -x $display_daemon ]; then
$display_daemon &
fi
/usr/bin/lightdm-deepin-greeter
为了计时,编者把代码改成了:
#!/bin/bash
display_daemon="/usr/lib/deepin-daemon/greeter-display-daemon"
if [ -x $display_daemon ]; then
echo $(date +"%Y-%m-%d %H:%M:%S") $display_daemon >> /home/log/greeter-elapse.log
$display_daemon &
fi
echo $(date +"%Y-%m-%d %H:%M:%S") /usr/bin/lightdm-deepin-greeter started >> /home/log/greeter-elapse.log
/usr/bin/lightdm-deepin-greeter
echo $(date +"%Y-%m-%d %H:%M:%S") /usr/bin/lightdm-deepin-greeter ended >> /home/log/greeter-elapse.log
增加到代码都是把时刻打印到/home/log/greeter-elapse.log
。需要注意是的这些shell的启动身份是lightdm
这个用户。这个用户权限很低,/home/log/
的权限须为755
且greeter-elapse.log
的权限须为777
。
可执行文件部分
/usr/bin/lightdm-deepin-greeter
是最终的可执行文件,它才是dde-session-shell
的编译结果。CMakeLists.txt
第386行代码指定安装包把lightdm-deepin-greeter
复制到/usr/bin
。
主程序入口
main
函数位于lightdm-deepin-greeter.cpp
第181行。开始启动时调用DTK
加载主题,设置Qt主程序相关信息,设置Qt的调色板等等。最重要的是判断当系统环境是不是X11,如果是则加载XCB插件。
SessionBaseModel
和GreeterWorkek
类型虽然不是单例模式的实现,但是单例模式的用法,它在界面类型中层层传递,确认只有这些类型的单个对象。GreeterWorkek
实现了登录逻辑。
多屏的信号监听由MultiScreenManager
提供支持。每个屏幕信号都触发一次std::function<QWidget *(QScreen *)>
类型的回调。
LoginWindow类型
这个类型是主窗口,继承自FullscreenBackground
类型。FullscreenBackground
的作用是全屏遮挡,但它作用一个通用类型不提供界面的实现细节,也不实现对鼠标和键盘信号的抓取并屏蔽功能。它特别提供了一个调试功能,debug模式编译的程序可按Esc键退出。
绘制的背景图片之前要获取用户设置的背景图片。曾经的做法是从com.deepin.daemon.Accounts
服务获取用户的背景图片的路径,然后调用com.deepin.daemon.ImageEffect
生成虚化的背景图片,用虚化的背景图片填充效果。这样的做法存在一个巨大的敝端:无论用户是否修改过背景图片,它在每次登录操作都要生成一次。对于龙芯这样的没有真实GPU只能模拟图形处理的硬件平台造成不必要的启动缓慢问题。后来引入共享内存技术,通过保存用户修改背景图片设置时的保存的缓存图片,一定程序上提高了greeter启动速度,特别对于开机后的注销、锁屏操作,速度提升效果更加明显。
LoginContent类型
LoginContent
类型继承自LockContent
类型。这里是greeter和锁屏程序的逻辑存在共用的地方。框架上的整体布局由它管理和设置,它管理的LogoWidget
对象实现了左下角UOS的标志,MediaWidget
对象实现了锁屏播放音乐,UserLoginInfo
对象实现中间的登录界面,ControlWidget
实现了切换用户、关机、重启等界面。
关于服务器版本
服务器版本不显示用户列表,不过它并非通过LightDM的配置实现,而是自己写了一个配置文件,代码位于files文件夹下的dde-session-ui.conf.in
,代码是:
[Power]
sleep=$$ENABLE_SLEEP
hibernate=$$ENABLE_HIBERNATE
[OS]
isDeepin=$$IS_DEEPIN
[General]
loginPromptAvatar=$$LOGIN_PROMPT_AVATAR
loginPromptInput=$$LOGIN_PROMPT_INPUT
lockNoPassword=false
[Lock]
#[always | ondemand | disabled]
showSwitchUserButton=$$SHOW_SWITCH_USER_BUTTON
其中$ENABLE_SLEEP
、$$LOGIN_PROMPT_INPUT
、$$IS_DEEPIN
、$$LOGIN_PROMPT_INPUT
、$$SHOW_SWITCH_USER_BUTTON
是CMake传递过来的变量。showSwitchUserButton
指明是否显示切换用户按钮,sleep
指明是否显示休眠按钮,hibernate
指明是否显示待机按钮,isDeepin
指示是否深度系统,loginPromptAvatar
指示是否显示用户头像。
dde-session-ui.conf.in
由CMakeLists.txt
指定安装到/usr/share/dde-session-ui/dde-session-ui.conf
。
作者: | 岬淢箫声 |
日期: | 2020年12月16日 |
版本: | 1.0 |
博客: | http://caowei.blog.csdn.net |
创作不易,请大家多多支持关注、转发。转发请注明来源。 |