Merge develop into master.
This commit is contained in:
Pier Luigi Fiorini 2017-10-05 08:24:24 +02:00 committed by GitHub
parent e26c1e619d
commit 65662cb694
71 changed files with 1626 additions and 81 deletions

View File

@ -13,7 +13,7 @@ endif()
# Set version
set(SDDM_VERSION_MAJOR 0)
set(SDDM_VERSION_MINOR 15)
set(SDDM_VERSION_MINOR 16)
set(SDDM_VERSION_PATCH 0)
set(SDDM_VERSION_STRING "${SDDM_VERSION_MAJOR}.${SDDM_VERSION_MINOR}.${SDDM_VERSION_PATCH}")
@ -82,6 +82,10 @@ if(ENABLE_PAM)
endif()
add_feature_info("PAM" PAM_FOUND "PAM support")
# getspnam and shadow(5) support
include(CheckFunctionExists)
check_function_exists(getspnam HAVE_GETSPNAM)
# XCB
find_package(XCB REQUIRED)
@ -180,6 +184,8 @@ set(SESSION_COMMAND "${DATA_INSTALL_DIR}/scripts/Xsession"
set(WAYLAND_SESSION_COMMAND "${DATA_INSTALL_DIR}/scripts/wayland-session" CACHE PATH "Script to execute when starting the Wayland desktop session")
set(CONFIG_FILE "${CMAKE_INSTALL_FULL_SYSCONFDIR}/sddm.conf" CACHE PATH "Path of the sddm config file")
set(CONFIG_DIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}/sddm.conf.d" CACHE PATH "Path of the sddm config directory")
set(SYSTEM_CONFIG_DIR "${CMAKE_INSTALL_PREFIX}/lib/sddm/sddm.conf.d" CACHE PATH "Path of the system sddm config directory")
set(LOG_FILE "${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/log/sddm.log" CACHE PATH "Path of the sddm log file")
set(DBUS_CONFIG_FILENAME "org.freedesktop.DisplayManager.conf" CACHE STRING "Name of the sddm config file")
set(COMPONENTS_TRANSLATION_DIR "${DATA_INSTALL_DIR}/translations" CACHE PATH "Components translations directory")

View File

@ -4,14 +4,39 @@
- Bug fixes
* Others
## 0.16.0 - 2017-10-04
----------------------
+ Support non-latin characters in theme settings.
+ Support fish shell in Xsession and wayland-session.
+ Unlock GNOME keyring at login.
+ Configuration directory.
- Make the default cursor themed.
- Update date and time in elarun theme.
- Fix theme metadata default values.
- Fix session selection in elarun.
- Do not truncate XAUTHORITY on login.
- Make enabled property of Button functional.
- Fix typos in documentation.
* Re-use existing sessions.
* Add ConsoleKit 2 support.
* Stop assuming shadow(5) is always available.
* Explicitely set XDG_SEAT when starting a user session.
* Suppress errors when pam_elogind is not available.
* Suppress errors when pam_systemd is not available.
* Added possibility to change color of dropdown menu.
* Add Hindi translation.
* Completed Swedish translation.
* Update French translation.
## 0.15.0 - 2017-08-30
- Fix display of avatars
+ New sddm.conf option EnableHiDPI to allow opt out of auto scaling
- Theme cursor
+ Support optional kwallet PAM opening
+ Autologin, try last successful login if not explicitly set
+ Ignore session desktop files with hidden=true
+ Support elogind
----------------------
- Fix display of avatars.
+ New sddm.conf option EnableHiDPI to allow opt out of auto scaling.
- Theme cursor.
+ Support optional kwallet PAM opening.
+ Autologin, try last successful login if not explicitly set.
+ Ignore session desktop files with hidden=true.
+ Support elogind.
## 0.14.0 - 2016-08-28
----------------------

View File

@ -99,7 +99,8 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
hoverEnabled: container.enabled
enabled: container.enabled
acceptedButtons: Qt.LeftButton

View File

@ -32,7 +32,9 @@ FocusScope {
property color borderColor: "#ababab"
property color focusColor: "#266294"
property color hoverColor: "#5692c4"
property color menuColor: "white"
property color textColor: "black"
property font font
property alias model: listView.model
property int index: 0
@ -148,6 +150,8 @@ FocusScope {
anchors.top: container.bottom
anchors.topMargin: -1
color: container.menuColor
clip: true
Behavior on height { NumberAnimation { duration: 100 } }

View File

@ -0,0 +1,220 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.login1.Manager">
<property name="NAutoVTs" type="u" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="KillOnlyUsers" type="as" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="KillExcludeUsers" type="as" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="KillUserProcesses" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="IdleHint" type="b" access="read">
</property>
<property name="IdleSinceHint" type="t" access="read">
</property>
<property name="IdleSinceHintMonotonic" type="t" access="read">
</property>
<property name="BlockInhibited" type="s" access="read">
</property>
<property name="DelayInhibited" type="s" access="read">
</property>
<property name="InhibitDelayMaxUSec" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="HandlePowerKey" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="HandleSuspendKey" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="HandleHibernateKey" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="HandleLidSwitch" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="IdleAction" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="IdleActionUSec" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="PreparingForShutdown" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="PreparingForSleep" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<method name="GetSession">
<arg type="s" direction="in"/>
<arg type="o" direction="out"/>
</method>
<method name="GetSessionByPID">
<arg type="u" direction="in"/>
<arg type="o" direction="out"/>
</method>
<method name="GetUser">
<arg type="u" direction="in"/>
<arg type="o" direction="out"/>
</method>
<method name="GetUserByPID">
<arg type="u" direction="in"/>
<arg type="o" direction="out"/>
</method>
<method name="GetSeat">
<arg type="s" direction="in"/>
<arg type="o" direction="out"/>
</method>
<method name="ListSessions">
<arg type="a(susso)" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="SessionInfoList"/>
</method>
<method name="ListUsers">
<arg type="a(uso)" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="UserInfoList"/>
</method>
<method name="ListSeats">
<arg type="a(so)" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="NamedSeatPathList"/>
</method>
<method name="ListInhibitors">
<arg type="a(ssssuu)" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="InhibitorList"/>
</method>
<method name="ReleaseSession">
<arg type="s" direction="in"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="ActivateSession">
<arg type="s" direction="in"/>
</method>
<method name="ActivateSessionOnSeat">
<arg type="s" direction="in"/>
<arg type="s" direction="in"/>
</method>
<method name="LockSession">
<arg type="s" direction="in"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="UnlockSession">
<arg type="s" direction="in"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="LockSessions">
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="UnlockSessions">
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="KillSession">
<arg type="s" direction="in"/>
<arg type="s" direction="in"/>
<arg type="i" direction="in"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="KillUser">
<arg type="u" direction="in"/>
<arg type="i" direction="in"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="TerminateSession">
<arg type="s" direction="in"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="TerminateUser">
<arg type="u" direction="in"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="TerminateSeat">
<arg type="s" direction="in"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="SetUserLinger">
<arg type="u" direction="in"/>
<arg type="b" direction="in"/>
<arg type="b" direction="in"/>
</method>
<method name="AttachDevice">
<arg type="s" direction="in"/>
<arg type="s" direction="in"/>
<arg type="b" direction="in"/>
</method>
<method name="FlushDevices">
<arg type="b" direction="in"/>
</method>
<method name="PowerOff">
<arg type="b" direction="in"/>
</method>
<method name="Reboot">
<arg type="b" direction="in"/>
</method>
<method name="Suspend">
<arg type="b" direction="in"/>
</method>
<method name="Hibernate">
<arg type="b" direction="in"/>
</method>
<method name="HybridSleep">
<arg type="b" direction="in"/>
</method>
<method name="CanPowerOff">
<arg type="s" direction="out"/>
</method>
<method name="CanReboot">
<arg type="s" direction="out"/>
</method>
<method name="CanSuspend">
<arg type="s" direction="out"/>
</method>
<method name="CanHibernate">
<arg type="s" direction="out"/>
</method>
<method name="CanHybridSleep">
<arg type="s" direction="out"/>
</method>
<method name="Inhibit">
<arg type="s" direction="in"/>
<arg type="s" direction="in"/>
<arg type="s" direction="in"/>
<arg type="s" direction="in"/>
<arg type="h" direction="out"/>
</method>
<signal name="SessionNew">
<arg type="s"/>
<arg type="o"/>
</signal>
<signal name="SessionRemoved">
<arg type="s"/>
<arg type="o"/>
</signal>
<signal name="UserNew">
<arg type="u"/>
<arg type="o"/>
</signal>
<signal name="UserRemoved">
<arg type="u"/>
<arg type="o"/>
</signal>
<signal name="SeatNew">
<arg type="s"/>
<arg type="o"/>
</signal>
<signal name="SeatRemoved">
<arg type="s"/>
<arg type="o"/>
</signal>
<signal name="PrepareForShutdown">
<arg type="b"/>
</signal>
<signal name="PrepareForSleep">
<arg type="b"/>
</signal>
</interface>
</node>

View File

@ -0,0 +1,43 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.login1.Seat">
<property name="Id" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="ActiveSession" type="(so)" access="read">
<annotation name="org.qtproject.QtDBus.QtTypeName" value="NamedSessionPath"/>
</property>
<property name="CanMultiSession" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="CanTTY" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="CanGraphical" type="b" access="read">
</property>
<property name="Sessions" type="a(so)" access="read">
<annotation name="org.qtproject.QtDBus.QtTypeName" value="QList<NamedSessionPath>"/>
</property>
<property name="IdleHint" type="b" access="read">
</property>
<property name="IdleSinceHint" type="t" access="read">
</property>
<property name="IdleSinceHintMonotonic" type="t" access="read">
</property>
<method name="Terminate">
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="ActivateSession">
<arg type="s" direction="in"/>
</method>
<method name="SwitchTo">
<arg type="u" direction="in"/>
</method>
<method name="SwitchToNext">
</method>
<method name="SwitchToPrevious">
</method>
</interface>
</node>

View File

@ -0,0 +1,132 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.login1.Session">
<property name="Id" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="User" type="(uo)" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
<annotation name="org.qtproject.QtDBus.QtTypeName" value="NamedUserPath"/>
</property>
<property name="Name" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Timestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="TimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="VTNr" type="u" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Seat" type="(so)" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
<annotation name="org.qtproject.QtDBus.QtTypeName" value="NamedSeatPath"/>
</property>
<property name="TTY" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Display" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Remote" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="RemoteHost" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="RemoteUser" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Service" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Desktop" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Scope" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Leader" type="u" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Audit" type="u" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Type" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Class" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
<annotation name="org.qtproject.QtDBus.PropertyGetter" value="className"/>
</property>
<property name="Active" type="b" access="read">
</property>
<property name="State" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="IdleHint" type="b" access="read">
</property>
<property name="IdleSinceHint" type="t" access="read">
</property>
<property name="IdleSinceHintMonotonic" type="t" access="read">
</property>
<method name="Terminate">
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="Activate">
</method>
<method name="Lock">
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
<annotation name="org.qtproject.QtDBus.MethodName" value="requestLock"/>
</method>
<method name="Unlock">
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
<annotation name="org.qtproject.QtDBus.MethodName" value="requestUnlock"/>
</method>
<method name="SetIdleHint">
<arg type="b" direction="in"/>
</method>
<method name="Kill">
<arg type="s" direction="in"/>
<arg type="i" direction="in"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="TakeControl">
<arg type="b" direction="in"/>
</method>
<method name="ReleaseControl">
</method>
<method name="TakeDevice">
<arg type="u" direction="in"/>
<arg type="u" direction="in"/>
<arg type="h" direction="out"/>
<arg type="b" direction="out"/>
</method>
<method name="ReleaseDevice">
<arg type="u" direction="in"/>
<arg type="u" direction="in"/>
</method>
<method name="PauseDeviceComplete">
<arg type="u" direction="in"/>
<arg type="u" direction="in"/>
</method>
<signal name="PauseDevice">
<arg type="u"/>
<arg type="u"/>
<arg type="s"/>
</signal>
<signal name="ResumeDevice">
<arg type="u"/>
<arg type="u"/>
<arg type="h"/>
</signal>
<signal name="Lock">
</signal>
<signal name="Unlock">
</signal>
</interface>
</node>

View File

@ -0,0 +1,56 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.login1.User">
<property name="UID" type="u" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="GID" type="u" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Name" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Timestamp" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="TimestampMonotonic" type="t" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="RuntimePath" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Service" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Slice" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="const"/>
</property>
<property name="Display" type="(so)" access="read">
<annotation name="org.qtproject.QtDBus.QtTypeName" value="NamedSessionPath"/>
</property>
<property name="State" type="s" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<property name="Sessions" type="a(so)" access="read">
<annotation name="org.qtproject.QtDBus.QtTypeName" value="QList<NamedSessionPath>"/>
</property>
<property name="IdleHint" type="b" access="read">
</property>
<property name="IdleSinceHint" type="t" access="read">
</property>
<property name="IdleSinceHintMonotonic" type="t" access="read">
</property>
<property name="Linger" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
</property>
<method name="Terminate">
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
<method name="Kill">
<arg type="i" direction="in"/>
<annotation name="org.freedesktop.systemd1.Privileged" value="true"/>
</method>
</interface>
</node>

View File

@ -14,7 +14,7 @@ sddm display manager greeter
SYNOPSIS
========
sddm-greeter [OPTIONS...]
sddm-greeter [OPTIONS...]
DESCRIPTION
===========

View File

@ -14,7 +14,7 @@ sddm display manager configuration
SYNOPSIS
========
~sddm/state.conf
~sddm/state.conf
DESCRIPTION
===========

View File

@ -14,7 +14,16 @@ sddm display manager configuration
SYNOPSIS
========
@CONFIG_FILE@
Configuration loads all files in the configuration directories followed by the configuration file in the order listed below with the latter having the most precedent. Changes should be made to the local configurations.
**@SYSTEM_CONFIG_DIR@*
System configuration directory
**@CONFIG_DIR@**
Local configuration directory
**@CONFIG_FILE@**
Local configuration file for compatibility
DESCRIPTION
===========

View File

@ -14,7 +14,7 @@ the simple desktop display manager
SYNOPSIS
========
sddm [OPTIONS...]
sddm [OPTIONS...]
DESCRIPTION
===========
@ -46,6 +46,9 @@ OPTIONS
FILES
=====
**@CONFIG_DIR@**
System configuration directory
**@CONFIG_FILE@**
System configuration file

View File

@ -13,7 +13,11 @@ foreach(THEME ${THEMES})
qt5_add_translation(QM_FILES "${TRANSLATION_SOURCES}")
install(DIRECTORY "${THEME}" DESTINATION "${DATA_INSTALL_DIR}/themes" PATTERN "${THEME}/*.ts" EXCLUDE PATTERN "${THEME}/Main.qml" EXCLUDE PATTERN "${THEME}/metadata.desktop" EXCLUDE)
install(DIRECTORY "${THEME}" DESTINATION "${DATA_INSTALL_DIR}/themes" PATTERN "${THEME}/*.ts"
EXCLUDE PATTERN "${THEME}/Main.qml"
EXCLUDE PATTERN "${THEME}/metadata.desktop"
EXCLUDE PATTERN "${THEME}/.gitattributes"
EXCLUDE)
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${THEME}" DESTINATION "${DATA_INSTALL_DIR}/themes")
list(APPEND THEMES_QM_FILES ${QM_FILES})

View File

@ -33,6 +33,8 @@ Rectangle {
LayoutMirroring.enabled: Qt.locale().textDirection == Qt.RightToLeft
LayoutMirroring.childrenInherit: true
property int sessionIndex: session.index
TextConstants { id: textConstants }
Connections {
@ -132,7 +134,7 @@ Rectangle {
Keys.onPressed: {
if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
sddm.login(user_entry.text, pw_entry.text, menu_session.index)
sddm.login(user_entry.text, pw_entry.text, sessionIndex)
event.accepted = true
}
}
@ -148,7 +150,7 @@ Rectangle {
source: "images/login_normal.png"
onClicked: sddm.login(user_entry.text, pw_entry.text, menu_session.index)
onClicked: sddm.login(user_entry.text, pw_entry.text, sessionIndex)
KeyNavigation.backtab: pw_entry; KeyNavigation.tab: session_button
}
@ -221,15 +223,6 @@ Rectangle {
font.bold: true
font.pixelSize: 12
}
Menu {
id: menu_session
width: 200; height: 0
anchors.top: buttonRow.bottom; anchors.left: buttonRow.left
model: sessionModel
index: sessionModel.lastIndex
}
}
}
}

View File

@ -33,6 +33,8 @@ Rectangle {
LayoutMirroring.enabled: Qt.locale().textDirection == Qt.RightToLeft
LayoutMirroring.childrenInherit: true
property int sessionIndex: session.index
TextConstants { id: textConstants }
Connections {
@ -121,7 +123,7 @@ Rectangle {
Keys.onPressed: {
if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
sddm.login(name.text, password.text, session.index)
sddm.login(name.text, password.text, sessionIndex)
event.accepted = true
}
}
@ -148,7 +150,7 @@ Rectangle {
Keys.onPressed: {
if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
sddm.login(name.text, password.text, session.index)
sddm.login(name.text, password.text, sessionIndex)
event.accepted = true
}
}
@ -237,7 +239,7 @@ Rectangle {
text: textConstants.login
width: parent.btnWidth
onClicked: sddm.login(name.text, password.text, session.index)
onClicked: sddm.login(name.text, password.text, sessionIndex)
KeyNavigation.backtab: layoutBox; KeyNavigation.tab: shutdownButton
}

View File

@ -235,6 +235,7 @@ Rectangle {
focusColor : accentLight
hoverColor : accentHue2
textColor : normalText
menuColor : primaryHue1
font.family : opensans_cond_light.name
font.pixelSize : spFontNormal
@ -277,6 +278,7 @@ Rectangle {
focusColor : accentLight
hoverColor : accentHue2
textColor : normalText
menuColor : primaryHue1
font.family : opensans_cond_light.name
font.pixelSize : spFontNormal

View File

@ -12,22 +12,26 @@ set(TRANSLATION_FILES
hu.ts
it.ts
ja.ts
kk.ts
ko.ts
lt.ts
lv.ts
nb.ts
nl.ts
nn.ts
pl.ts
pt_BR.ts
pt_PT.ts
ro.ts
ru.ts
sk.ts
sr.ts
sr@ijekavian.ts
sr@ijekavianlatin.ts
sr@latin.ts
sv.ts
ru.ts
tr.ts
uk.ts
zh_CN.ts
zh_TW.ts
)

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ar">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ca">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="cs">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="de">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="es">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="et">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="fi">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="fr">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="hi_IN">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="hu">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="it">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ja">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="kk">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ko">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="lt">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="lv">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -12,7 +12,7 @@
<context>
<name>QObject</name>
<message>
<location filename="../../src/common/Session.cpp" line="137"/>
<location filename="../../src/common/Session.cpp" line="166"/>
<source>%1 (Wayland)</source>
<translation>%1 (Wayland)</translation>
</message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0" language="nl">
<TS version="2.1" language="nl">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -12,7 +12,7 @@
<context>
<name>QObject</name>
<message>
<location filename="../../src/common/Session.cpp" line="137"/>
<location filename="../../src/common/Session.cpp" line="166"/>
<source>%1 (Wayland)</source>
<translation>%1 (Wayland)</translation>
</message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="pt_BR">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="pt_PT">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ro">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ru">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="sk">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="sr">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="sr@ijekavian">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="sr@ijekavianlatin">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="sr@latin">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -12,7 +12,7 @@
<context>
<name>QObject</name>
<message>
<location filename="../../src/common/Session.cpp" line="137"/>
<location filename="../../src/common/Session.cpp" line="166"/>
<source>%1 (Wayland)</source>
<translation>%1 (Wayland)</translation>
</message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="tr">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -49,11 +49,11 @@
</message>
<message>
<source>User name</source>
<translation>Ім'я користувача/translation>
<translation>Ім'я користувача</translation>
</message>
<message>
<source>Select your user and enter password</source>
<translation>Оберіть користувача та введіть пароль</translation>
</message>
</context>
</TS>
</TS>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="zh_CN">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="zh_TW">
<context>
<name>PictureBox</name>
<message>
<source>Press to login</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>%1 (Wayland)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TextConstants</name>
<message>

View File

@ -14,5 +14,5 @@ password required pam_deny.so
# Setup session
session required pam_unix.so
session optional pam_systemd.so
session optional pam_elogind.so
-session optional pam_systemd.so
-session optional pam_elogind.so

View File

@ -100,6 +100,12 @@ namespace SDDM {
m_parent->save(this, entry);
}
void ConfigSection::clear() {
for (auto it : m_entries) {
it->setDefault();
}
}
QString ConfigSection::toConfigFull() const {
QString final = QStringLiteral("[%1]\n").arg(m_name);
for (const ConfigEntryBase *entry : m_entries)
@ -113,11 +119,11 @@ namespace SDDM {
ConfigBase::ConfigBase(const QString &configPath) : m_path(configPath) {
}
const QString &ConfigBase::path() const {
return m_path;
ConfigBase::ConfigBase(const QString &configPath, const QString &configDir, const QString &sysConfigDir) :
m_path(configPath),
m_configDir(configDir),
m_sysConfigDir(sysConfigDir)
{
}
bool ConfigBase::hasUnused() const {
@ -133,21 +139,59 @@ namespace SDDM {
return ret;
}
void ConfigBase::load() {
// first check if there's at least anything to read, otherwise stick to default values
if (!QFile::exists(m_path))
return;
void ConfigBase::load()
{
//order of priority from least influence to most influence, is
// * m_sysConfigDir (system settings /usr/lib/sddm/sddm.conf.d/) in alphabetical order
// * m_configDir (user settings in /etc/sddm.conf.d/) in alphabetical order
// * m_path (classic fallback /etc/sddm.conf)
QString currentSection = QStringLiteral(IMPLICIT_SECTION);
QStringList files;
QDateTime latestModificationTime = QFileInfo(m_path).lastModified();
QFile in(m_path);
QDateTime modificationTime = QFileInfo(in).lastModified();
if (modificationTime <= m_fileModificationTime) {
if (!m_sysConfigDir.isEmpty()) {
//include the configDir in modification time so we also reload on any files added/removed
QDir dir(m_sysConfigDir);
if (dir.exists()) {
latestModificationTime = std::max(latestModificationTime, QFileInfo(m_sysConfigDir).lastModified());
foreach (const QFileInfo &file, dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot, QDir::LocaleAware)) {
files << (file.absoluteFilePath());
latestModificationTime = std::max(latestModificationTime, file.lastModified());
}
}
}
if (!m_configDir.isEmpty()) {
//include the configDir in modification time so we also reload on any files added/removed
QDir dir(m_configDir);
if (dir.exists()) {
latestModificationTime = std::max(latestModificationTime, QFileInfo(m_configDir).lastModified());
foreach (const QFileInfo &file, dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot, QDir::LocaleAware)) {
files << (file.absoluteFilePath());
latestModificationTime = std::max(latestModificationTime, file.lastModified());
}
}
}
files << m_path;
if (latestModificationTime <= m_fileModificationTime) {
return;
}
m_fileModificationTime = modificationTime;
m_fileModificationTime = latestModificationTime;
in.open(QIODevice::ReadOnly);
foreach (const QString &filepath, files) {
loadInternal(filepath);
}
}
void ConfigBase::loadInternal(const QString &filepath) {
QString currentSection = QStringLiteral(IMPLICIT_SECTION);
QFile in(filepath);
if (!in.open(QIODevice::ReadOnly))
return;
while (!in.atEnd()) {
QString line = QString::fromUtf8(in.readLine());
QStringRef lineRef = QStringRef(&line).trimmed();
@ -307,4 +351,10 @@ namespace SDDM {
}
}
}
void ConfigBase::wipe() {
for (auto it : m_sections) {
it->clear();
}
}
}

View File

@ -26,6 +26,7 @@
#include <QtCore/QStringList>
#include <QtCore/QDebug>
#include <QtCore/QDateTime>
#include <QtCore/QDir>
#define IMPLICIT_SECTION "General"
#define UNUSED_VARIABLE_COMMENT "# Unused variable"
@ -36,10 +37,10 @@
#define _S(x) QStringLiteral(x)
// config wrapper
#define Config(name, file, ...) \
#define Config(name, file, dir, sysDir, ...) \
class name : public SDDM::ConfigBase, public SDDM::ConfigSection { \
public: \
name() : SDDM::ConfigBase(file), SDDM::ConfigSection(this, QStringLiteral(IMPLICIT_SECTION)) { \
name() : SDDM::ConfigBase(file, dir, sysDir), SDDM::ConfigSection(this, QStringLiteral(IMPLICIT_SECTION)) { \
load(); \
} \
void save() { SDDM::ConfigBase::save(nullptr, nullptr); } \
@ -79,6 +80,7 @@ namespace SDDM {
virtual QString toConfigFull() const = 0;
virtual bool matchesDefault() const = 0;
virtual bool isDefault() const = 0;
virtual bool setDefault() = 0;
};
class ConfigSection {
@ -87,6 +89,7 @@ namespace SDDM {
ConfigEntryBase *entry(const QString &name);
const ConfigEntryBase *entry(const QString &name) const;
void save(ConfigEntryBase *entry);
void clear();
const QString &name() const;
QString toConfigShort() const;
QString toConfigFull() const;
@ -183,21 +186,25 @@ namespace SDDM {
// Base has to be separate from the Config itself - order of initialization
class ConfigBase {
public:
ConfigBase(const QString &configPath);
ConfigBase(const QString &configPath, const QString &configDir=QString(), const QString &sysConfigDir=QString());
void load();
void save(const ConfigSection *section = nullptr, const ConfigEntryBase *entry = nullptr);
void wipe();
bool hasUnused() const;
const QString &path() const;
QString toConfigFull() const;
protected:
bool m_unusedVariables { false };
bool m_unusedSections { false };
QString m_path {};
QString m_configDir;
QString m_sysConfigDir;
QMap<QString, ConfigSection*> m_sections;
friend class ConfigSection;
private:
QDateTime dirLatestModifiedTime(const QString &directory);
void loadInternal(const QString &filepath);
QDateTime m_fileModificationTime;
};
}

View File

@ -33,7 +33,7 @@
namespace SDDM {
// Name File Sections and/or Entries (but anything else too, it's a class) - Entries in a Config are assumed to be in the General section
Config(MainConfig, QStringLiteral(CONFIG_FILE),
Config(MainConfig, QStringLiteral(CONFIG_FILE), QStringLiteral(CONFIG_DIR), QStringLiteral(SYSTEM_CONFIG_DIR),
enum NumState { NUM_NONE, NUM_SET_ON, NUM_SET_OFF };
// Name Type Default value Description
@ -88,6 +88,8 @@ namespace SDDM {
"Users with these shells as their default won't be listed"));
Entry(RememberLastUser, bool, true, _S("Remember the last successfully logged in user"));
Entry(RememberLastSession, bool, true, _S("Remember the session of the last successfully logged in user"));
Entry(ReuseSession, bool, false, _S("When logging in as the same user twice, restore the original session, rather than create a new one"));
);
Section(Autologin,
@ -97,7 +99,7 @@ namespace SDDM {
);
);
Config(StateConfig, []()->QString{auto tmp = getpwnam("sddm"); return tmp ? QString::fromLocal8Bit(tmp->pw_dir) : QStringLiteral(STATE_DIR);}().append(QStringLiteral("/state.conf")),
Config(StateConfig, []()->QString{auto tmp = getpwnam("sddm"); return tmp ? QString::fromLocal8Bit(tmp->pw_dir) : QStringLiteral(STATE_DIR);}().append(QStringLiteral("/state.conf")), QString(), QString(),
Section(Last,
Entry(Session, QString, QString(), _S("Name of the session for the last logged-in user.\n"
"This session will be preselected when the login screen appears."));

View File

@ -33,6 +33,9 @@
#define WAYLAND_SESSION_COMMAND "@WAYLAND_SESSION_COMMAND@"
#define CONFIG_FILE "@CONFIG_FILE@"
#define CONFIG_DIR "@CONFIG_DIR@"
#define SYSTEM_CONFIG_DIR "@SYSTEM_CONFIG_DIR@"
#define LOG_FILE "@LOG_FILE@"
#define MINIMUM_VT @MINIMUM_VT@

View File

@ -21,6 +21,7 @@
#include "ThemeConfig.h"
#include <QDebug>
#include <QSettings>
#include <QStringList>
@ -32,6 +33,8 @@ namespace SDDM {
void ThemeConfig::setTo(const QString &path) {
clear();
qDebug() << "Loading theme configuration from" << path;
QSettings settings(path, QSettings::IniFormat);
QSettings userSettings(path + QStringLiteral(".user"), QSettings::IniFormat);

View File

@ -53,8 +53,8 @@ namespace SDDM {
void ThemeMetadata::setTo(const QString &path) {
QSettings settings(path, QSettings::IniFormat);
// read values
d->mainScript = settings.value(QStringLiteral("SddmGreeterTheme/MainScript"), d->mainScript).toString();
d->configFile = settings.value(QStringLiteral("SddmGreeterTheme/ConfigFile"), d->configFile).toString();
d->translationsDirectory = settings.value(QStringLiteral("SddmGreeterTheme/TranslationsDirectory"), d->translationsDirectory).toString();
d->mainScript = settings.value(QStringLiteral("SddmGreeterTheme/MainScript"), QStringLiteral("Main.qml")).toString();
d->configFile = settings.value(QStringLiteral("SddmGreeterTheme/ConfigFile"), QStringLiteral("theme.conf")).toString();
d->translationsDirectory = settings.value(QStringLiteral("SddmGreeterTheme/TranslationsDirectory"), QStringLiteral(".")).toString();
}
}

View File

@ -16,10 +16,12 @@ set(DAEMON_SOURCES
${CMAKE_SOURCE_DIR}/src/auth/Auth.cpp
${CMAKE_SOURCE_DIR}/src/auth/AuthPrompt.cpp
${CMAKE_SOURCE_DIR}/src/auth/AuthRequest.cpp
DaemonApp.cpp
Display.cpp
DisplayManager.cpp
DisplayServer.cpp
LogindDBusTypes.cpp
XorgDisplayServer.cpp
Greeter.cpp
PowerManager.cpp
@ -34,6 +36,22 @@ qt5_add_dbus_adaptor(DAEMON_SOURCES "${CMAKE_SOURCE_DIR}/data/interfaces/org.fre
qt5_add_dbus_adaptor(DAEMON_SOURCES "${CMAKE_SOURCE_DIR}/data/interfaces/org.freedesktop.DisplayManager.Seat.xml" "DisplayManager.h" SDDM::DisplayManagerSeat)
qt5_add_dbus_adaptor(DAEMON_SOURCES "${CMAKE_SOURCE_DIR}/data/interfaces/org.freedesktop.DisplayManager.Session.xml" "DisplayManager.h" SDDM::DisplayManagerSession)
set_source_files_properties("${CMAKE_SOURCE_DIR}/data/interfaces/org.freedesktop.login1.Manager.xml" PROPERTIES
INCLUDE "LogindDBusTypes.h"
)
set_source_files_properties("${CMAKE_SOURCE_DIR}/data/interfaces/org.freedesktop.login1.Seat.xml" PROPERTIES
INCLUDE "LogindDBusTypes.h"
)
set_source_files_properties("${CMAKE_SOURCE_DIR}/data/interfaces/org.freedesktop.login1.Session.xml" PROPERTIES
INCLUDE "LogindDBusTypes.h"
)
qt5_add_dbus_interface(DAEMON_SOURCES "${CMAKE_SOURCE_DIR}/data/interfaces/org.freedesktop.login1.Manager.xml" "Login1Manager")
qt5_add_dbus_interface(DAEMON_SOURCES "${CMAKE_SOURCE_DIR}/data/interfaces/org.freedesktop.login1.Seat.xml" "Login1Seat")
qt5_add_dbus_interface(DAEMON_SOURCES "${CMAKE_SOURCE_DIR}/data/interfaces/org.freedesktop.login1.Session.xml" "Login1Session")
add_executable(sddm ${DAEMON_SOURCES})
target_link_libraries(sddm
Qt5::DBus

View File

@ -75,9 +75,6 @@ namespace SDDM {
// log message
qDebug() << "Starting...";
// add a seat
m_seatManager->createSeat(QStringLiteral("seat0"));
}
bool DaemonApp::testing() const {
@ -127,6 +124,7 @@ int main(int argc, char **argv) {
// spit a complete config file on stdout and quit on demand
if (arguments.contains(QStringLiteral("--example-config"))) {
SDDM::mainConfig.wipe();
QTextStream(stdout) << SDDM::mainConfig.toConfigFull();
return EXIT_SUCCESS;
}

View File

@ -39,6 +39,14 @@
#include <pwd.h>
#include <unistd.h>
#include <QDBusConnection>
#include <QDBusMessage>
#include <QDBusReply>
#include "Login1Manager.h"
#include "Login1Session.h"
namespace SDDM {
Display::Display(const int terminalId, Seat *parent) : QObject(parent),
m_terminalId(terminalId),
@ -272,6 +280,24 @@ namespace SDDM {
return;
}
QString existingSessionId;
if (Logind::isAvailable() && mainConfig.Users.ReuseSession.get()) {
OrgFreedesktopLogin1ManagerInterface manager(Logind::serviceName(), Logind::managerPath(), QDBusConnection::systemBus());
auto reply = manager.ListSessions();
reply.waitForFinished();
foreach(const SessionInfo &s, reply.value()) {
if (s.userName == user) {
OrgFreedesktopLogin1SessionInterface session(Logind::serviceName(), s.sessionPath.path(), QDBusConnection::systemBus());
if (session.service() == QLatin1String("sddm")) {
existingSessionId = s.sessionId;
break;
}
}
}
}
// cache last session
m_lastSession = session;
@ -292,19 +318,34 @@ namespace SDDM {
env.insert(QStringLiteral("PATH"), mainConfig.Users.DefaultPath.get());
if (session.xdgSessionType() == QLatin1String("x11"))
env.insert(QStringLiteral("DISPLAY"), name());
env.insert(QStringLiteral("XDG_SEAT"), seat()->name());
env.insert(QStringLiteral("XDG_SEAT_PATH"), daemonApp->displayManager()->seatPath(seat()->name()));
env.insert(QStringLiteral("XDG_SESSION_PATH"), daemonApp->displayManager()->sessionPath(QStringLiteral("Session%1").arg(daemonApp->newSessionId())));
env.insert(QStringLiteral("XDG_VTNR"), QString::number(vt));
env.insert(QStringLiteral("DESKTOP_SESSION"), session.desktopSession());
env.insert(QStringLiteral("XDG_CURRENT_DESKTOP"), session.desktopNames());
env.insert(QStringLiteral("XDG_SESSION_CLASS"), QStringLiteral("user"));
env.insert(QStringLiteral("XDG_SESSION_TYPE"), session.xdgSessionType());
env.insert(QStringLiteral("XDG_SEAT"), seat()->name());
env.insert(QStringLiteral("XDG_SESSION_DESKTOP"), session.desktopNames());
if (seat()->name() == QLatin1String("seat0")) {
env.insert(QStringLiteral("XDG_VTNR"), QString::number(vt));
}
m_auth->insertEnvironment(env);
m_auth->setUser(user);
m_auth->setSession(session.exec());
if (existingSessionId.isNull()) {
m_auth->setSession(session.exec());
} else {
//we only want to unlock the session if we can lock in, so we want to go via PAM auth, but not start a new session
//by not setting the session and the helper will emit authentication and then quit
connect(m_auth, &Auth::authentication, this, [=](){
qDebug() << "activating existing seat";
OrgFreedesktopLogin1ManagerInterface manager(Logind::serviceName(), Logind::managerPath(), QDBusConnection::systemBus());
manager.UnlockSession(existingSessionId);
manager.ActivateSession(existingSessionId);
});
}
m_auth->start();
}

View File

@ -0,0 +1,111 @@
#include "LogindDBusTypes.h"
#include <QDBusArgument>
#include <QDBusMetaType>
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDebug>
class LogindPathInternal {
public:
LogindPathInternal();
bool available = false;
QString serviceName;
QString managerPath;
QString managerIfaceName;
QString sessionIfaceName;
QString seatIfaceName;
QString userIfaceName;
};
LogindPathInternal::LogindPathInternal()
{
qRegisterMetaType<NamedSeatPath>("NamedSeatPath");
qDBusRegisterMetaType<NamedSeatPath>();
qRegisterMetaType<NamedSeatPathList>("NamedSeatPathList");
qDBusRegisterMetaType<NamedSeatPathList>();
qRegisterMetaType<NamedSessionPath>("NamedSessionPath");
qDBusRegisterMetaType<NamedSessionPath>();
qRegisterMetaType<NamedSessionPathList>("NamedSessionPathList");
qDBusRegisterMetaType<NamedSessionPathList>();
qRegisterMetaType<SessionInfo>("SessionInfo");
qDBusRegisterMetaType<SessionInfo>();
qRegisterMetaType<SessionInfoList>("SessionInfoList");
qDBusRegisterMetaType<SessionInfoList>();
qRegisterMetaType<UserInfo>("UserInfo");
qDBusRegisterMetaType<UserInfo>();
qRegisterMetaType<UserInfoList>("UserInfoList");
qDBusRegisterMetaType<UserInfoList>();
if (QDBusConnection::systemBus().interface()->isServiceRegistered(QStringLiteral("org.freedesktop.login1"))) {
qDebug() << "Logind interface found";
available = true;
serviceName = QStringLiteral("org.freedesktop.login1");
managerPath = QStringLiteral("/org/freedesktop/login1");
managerIfaceName = QStringLiteral("org.freedesktop.login1.Manager");
seatIfaceName = QStringLiteral("org.freedesktop.login1.Seat");
sessionIfaceName = QStringLiteral("org.freedesktop.login1.Session");
userIfaceName = QStringLiteral("org.freedesktop.login1.User");
return;
}
if (QDBusConnection::systemBus().interface()->isServiceRegistered(QStringLiteral("org.freedesktop.ConsoleKit"))) {
qDebug() << "Console kit interface found";
available = true;
serviceName = QStringLiteral("org.freedesktop.ConsoleKit");
managerPath = QStringLiteral("/org/freedesktop/ConsoleKit/Manager");
managerIfaceName = QStringLiteral("/org.freedesktop.ConsoleKit.Manager"); //note this doesn't match logind
seatIfaceName = QStringLiteral("org.freedesktop.ConsoleKit.Seat");
sessionIfaceName = QStringLiteral("org.freedesktop.ConsoleKit.Session");
userIfaceName = QStringLiteral("org.freedesktop.ConsoleKit.User");
return;
}
qDebug() << "No session manager found";
}
Q_GLOBAL_STATIC(LogindPathInternal, s_instance);
bool Logind::isAvailable()
{
return s_instance->available;
}
QString Logind::serviceName()
{
return s_instance->serviceName;
}
QString Logind::managerPath()
{
return s_instance->managerPath;
}
QString Logind::managerIfaceName()
{
return s_instance->managerIfaceName;
}
QString Logind::seatIfaceName()
{
return s_instance->seatIfaceName;
}
QString Logind::sessionIfaceName()
{
return s_instance->sessionIfaceName;
}
QString Logind::userIfaceName()
{
return s_instance->userIfaceName;
}

View File

@ -0,0 +1,194 @@
#ifndef LOGIND_DBUSTYPES
#define LOGIND_DBUSTYPES
#include <QDBusObjectPath>
#include <QDBusArgument>
struct Logind
{
static bool isAvailable();
static QString serviceName();
static QString managerPath();
static QString managerIfaceName();
static QString sessionIfaceName();
static QString seatIfaceName();
static QString userIfaceName();
};
struct SessionInfo
{
QString sessionId;
uint userId;
QString userName;
QString seatId;
QDBusObjectPath sessionPath;
};
typedef QList<SessionInfo> SessionInfoList;
inline QDBusArgument &operator<<(QDBusArgument &argument, const SessionInfo& sessionInfo)
{
argument.beginStructure();
argument << sessionInfo.sessionId;
argument << sessionInfo.userId;
argument << sessionInfo.userName;
argument << sessionInfo.seatId;
argument << sessionInfo.sessionPath;
argument.endStructure();
return argument;
}
inline const QDBusArgument &operator>>(const QDBusArgument &argument, SessionInfo &sessionInfo)
{
argument.beginStructure();
argument >> sessionInfo.sessionId;
argument >> sessionInfo.userId;
argument >> sessionInfo.userName;
argument >> sessionInfo.seatId;
argument >> sessionInfo.sessionPath;
argument.endStructure();
return argument;
}
struct UserInfo
{
uint userId;
QString name;
QDBusObjectPath path;
};
typedef QList<UserInfo> UserInfoList;
inline QDBusArgument &operator<<(QDBusArgument &argument, const UserInfo& userInfo)
{
argument.beginStructure();
argument << userInfo.userId;
argument << userInfo.name;
argument << userInfo.path;
argument.endStructure();
return argument;
}
inline const QDBusArgument &operator>>(const QDBusArgument &argument, UserInfo& userInfo)
{
argument.beginStructure();
argument >> userInfo.userId;
argument >> userInfo.name;
argument >> userInfo.path;
argument.endStructure();
return argument;
}
struct NamedSeatPath
{
QString name;
QDBusObjectPath path;
};
inline QDBusArgument &operator<<(QDBusArgument &argument, const NamedSeatPath& namedSeat)
{
argument.beginStructure();
argument << namedSeat.name;
argument << namedSeat.path;
argument.endStructure();
return argument;
}
inline const QDBusArgument &operator>>(const QDBusArgument &argument, NamedSeatPath& namedSeat)
{
argument.beginStructure();
argument >> namedSeat.name;
argument >> namedSeat.path;
argument.endStructure();
return argument;
}
typedef QList<NamedSeatPath> NamedSeatPathList;
typedef NamedSeatPath NamedSessionPath;
typedef NamedSeatPathList NamedSessionPathList;
class NamedUserPath
{
public:
uint userId;
QDBusObjectPath path;
};
inline QDBusArgument &operator<<(QDBusArgument &argument, const NamedUserPath& namedUser)
{
argument.beginStructure();
argument << namedUser.userId;
argument << namedUser.path;
argument.endStructure();
return argument;
}
inline const QDBusArgument &operator>>(const QDBusArgument &argument, NamedUserPath& namedUser)
{
argument.beginStructure();
argument >> namedUser.userId;
argument >> namedUser.path;
argument.endStructure();
return argument;
}
class Inhibitor
{
public:
QString what;
QString who;
QString why;
QString mode;
int userId;
uint processId;
};
typedef QList<Inhibitor> InhibitorList;
inline QDBusArgument &operator<<(QDBusArgument &argument, const Inhibitor& inhibitor)
{
argument.beginStructure();
argument << inhibitor.what;
argument << inhibitor.who;
argument << inhibitor.why;
argument << inhibitor.mode;
argument << inhibitor.userId;
argument << inhibitor.processId;
argument.endStructure();
return argument;
}
inline const QDBusArgument &operator>>(const QDBusArgument &argument, Inhibitor& inhibitor)
{
argument.beginStructure();
argument >> inhibitor.what;
argument >> inhibitor.who;
argument >> inhibitor.why;
argument >> inhibitor.mode;
argument >> inhibitor.userId;
argument >> inhibitor.processId;
argument.endStructure();
return argument;
}
Q_DECLARE_METATYPE(SessionInfo);
Q_DECLARE_METATYPE(QList<SessionInfo>);
Q_DECLARE_METATYPE(UserInfo);
Q_DECLARE_METATYPE(QList<UserInfo>);
Q_DECLARE_METATYPE(NamedSeatPath);
Q_DECLARE_METATYPE(QList<NamedSeatPath>);
Q_DECLARE_METATYPE(NamedUserPath);
Q_DECLARE_METATYPE(Inhibitor);
Q_DECLARE_METATYPE(QList<Inhibitor>);
#endif

View File

@ -19,10 +19,102 @@
#include "SeatManager.h"
#include "DaemonApp.h"
#include "Seat.h"
#include <QDBusConnection>
#include <QDBusMessage>
#include <QDBusPendingReply>
#include <QDBusContext>
#include "LogindDBusTypes.h"
namespace SDDM {
class LogindSeat : public QObject {
Q_OBJECT
public:
LogindSeat(const QString &name, const QDBusObjectPath &objectPath, QObject *parent);
QString name() const;
bool canGraphical() const;
Q_SIGNALS:
void canGraphicalChanged(bool);
private Q_SLOTS:
void propertiesChanged(const QString &interface, QVariantMap &changedProperties , const QStringList &invalidatedProperties);
private:
QString m_name;
bool m_canGraphical;
};
LogindSeat::LogindSeat(const QString& name, const QDBusObjectPath& objectPath, QObject* parent):
m_name(name),
m_canGraphical(false)
{
QDBusConnection::systemBus().connect(Logind::serviceName(), objectPath.path(), QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("PropertiesChanged"), this, SLOT(propertiesChanged(QString,QVariantMap,QStringList)));
auto canGraphicalMsg = QDBusMessage::createMethodCall(Logind::serviceName(), objectPath.path(), QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("Get"));
canGraphicalMsg << Logind::seatIfaceName() << QStringLiteral("CanGraphical");
QDBusPendingReply<QVariant> reply = QDBusConnection::systemBus().asyncCall(canGraphicalMsg);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply);
connect(watcher, &QDBusPendingCallWatcher::finished, this, [=]() {
watcher->deleteLater();
if (!reply.isValid())
return;
bool value = reply.value().toBool();
if (value != m_canGraphical) {
m_canGraphical = value;
emit canGraphicalChanged(m_canGraphical);
}
});
}
bool LogindSeat::canGraphical() const
{
return m_canGraphical;
}
QString LogindSeat::name() const
{
return m_name;
}
void LogindSeat::propertiesChanged(const QString& interface, QVariantMap& changedProperties, const QStringList& invalidatedProperties)
{
Q_UNUSED(invalidatedProperties);
if (interface != Logind::seatIfaceName()) {
return;
}
if (changedProperties.contains(QStringLiteral("CanGraphical"))) {
m_canGraphical = changedProperties[QStringLiteral("CanGraphical")].toBool();
emit canGraphicalChanged(m_canGraphical);
}
}
SeatManager::SeatManager(QObject *parent) : QObject(parent) {
if (DaemonApp::instance()->testing() || !Logind::isAvailable()) {
//if we don't have logind/CK2, just create a single seat immediately and don't do any other connections
createSeat(QStringLiteral("seat0"));
return;
}
//fetch seats
auto listSeatsMsg = QDBusMessage::createMethodCall(Logind::serviceName(), Logind::managerPath(), Logind::managerIfaceName(), QStringLiteral("ListSeats"));
QDBusPendingReply<NamedSeatPathList> reply = QDBusConnection::systemBus().asyncCall(listSeatsMsg);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply);
connect(watcher, &QDBusPendingCallWatcher::finished, this, [=]() {
watcher->deleteLater();
foreach(const NamedSeatPath &seat, reply.value()) {
logindSeatAdded(seat.name, seat.path);
}
});
QDBusConnection::systemBus().connect(Logind::serviceName(), Logind::managerPath(), Logind::managerIfaceName(), QStringLiteral("SeatNew"), this, SLOT(logindSeatAdded(QString,QDBusObjectPath)));
QDBusConnection::systemBus().connect(Logind::serviceName(), Logind::managerPath(), Logind::managerIfaceName(), QStringLiteral("SeatRemoved"), this, SLOT(logindSeatRemoved(QString,QDBusObjectPath)));
}
void SeatManager::createSeat(const QString &name) {
@ -59,4 +151,28 @@ namespace SDDM {
// switch to greeter
m_seats.value(name)->createDisplay();
}
void SDDM::SeatManager::logindSeatAdded(const QString& name, const QDBusObjectPath& objectPath)
{
auto logindSeat = new LogindSeat(name, objectPath, this);
connect(logindSeat, &LogindSeat::canGraphicalChanged, this, [=]() {
if (logindSeat->canGraphical()) {
createSeat(logindSeat->name());
} else {
removeSeat(logindSeat->name());
}
});
m_systemSeats.insert(name, logindSeat);
}
void SDDM::SeatManager::logindSeatRemoved(const QString& name, const QDBusObjectPath& objectPath)
{
Q_UNUSED(objectPath);
auto logindSeat = m_systemSeats.take(name);
delete logindSeat;
removeSeat(name);
}
}
#include "SeatManager.moc"

View File

@ -22,28 +22,32 @@
#include <QObject>
#include <QHash>
#include <QDBusObjectPath>
namespace SDDM {
class Seat;
class LogindSeat;
class SeatManager : public QObject {
Q_OBJECT
Q_DISABLE_COPY(SeatManager)
public:
explicit SeatManager(QObject *parent = 0);
public slots:
void createSeat(const QString &name);
void removeSeat(const QString &name);
void switchToGreeter(const QString &seat);
signals:
Q_SIGNALS:
void seatCreated(const QString &name);
void seatRemoved(const QString &name);
private Q_SLOTS:
void logindSeatAdded(const QString &name, const QDBusObjectPath &objectPath);
void logindSeatRemoved(const QString &name, const QDBusObjectPath &objectPath);
private:
QHash<QString, Seat *> m_seats;
QHash<QString, Seat *> m_seats; //these will exist only for graphical seats
QHash<QString, LogindSeat*> m_systemSeats; //these will exist for all seats
};
}

View File

@ -24,6 +24,7 @@
#include "DaemonApp.h"
#include "Display.h"
#include "SignalHandler.h"
#include "Seat.h"
#include <QDebug>
#include <QFile>
@ -92,7 +93,7 @@ namespace SDDM {
// Touch file
QFile file_handler(file);
file_handler.open(QIODevice::WriteOnly);
file_handler.open(QIODevice::Append);
file_handler.close();
QString cmd = QStringLiteral("%1 -f %2 -q").arg(mainConfig.X11.XauthPath.get()).arg(file);
@ -159,7 +160,11 @@ namespace SDDM {
<< QStringLiteral("-background") << QStringLiteral("none")
<< QStringLiteral("-noreset")
<< QStringLiteral("-displayfd") << QString::number(pipeFds[1])
<< QStringLiteral("vt%1").arg(displayPtr()->terminalId());
<< QStringLiteral("-seat") << displayPtr()->seat()->name();
if (displayPtr()->seat()->name() == QLatin1String("seat0")) {
args << QStringLiteral("vt%1").arg(displayPtr()->terminalId());
}
qDebug() << "Running:"
<< qPrintable(mainConfig.X11.ServerPath.get())
<< qPrintable(args.join(QLatin1Char(' ')));
@ -191,7 +196,7 @@ namespace SDDM {
displayNumber.prepend(QByteArray(":"));
displayNumber.remove(displayNumber.size() -1, 1); //trim trailing whitespace
m_display = QString::fromLocal8Bit(displayNumber);
// close our pipe
close(pipeFds[0]);

View File

@ -24,10 +24,14 @@ else()
${HELPER_SOURCES}
backend/PasswdBackend.cpp
)
if(HAVE_GETSPNAM)
add_definitions(-DHAVE_GETSPNAM=1)
endif()
endif()
add_executable(sddm-helper ${HELPER_SOURCES})
target_link_libraries(sddm-helper Qt5::Network)
target_link_libraries(sddm-helper Qt5::Network Qt5::DBus)
if(PAM_FOUND)
target_link_libraries(sddm-helper ${PAM_LIBRARIES})
else()

View File

@ -34,6 +34,7 @@
#include <unistd.h>
#include <sys/socket.h>
namespace SDDM {
HelperApp::HelperApp(int& argc, char** argv)
: QCoreApplication(argc, argv)

View File

@ -179,7 +179,7 @@ namespace SDDM {
QDir().mkpath(finfo.absolutePath());
QFile file_handler(file);
file_handler.open(QIODevice::WriteOnly);
file_handler.open(QIODevice::Append);
file_handler.close();
QString cmd = QStringLiteral("%1 -f %2 -q").arg(mainConfig.X11.XauthPath.get()).arg(file);

View File

@ -27,8 +27,11 @@
#include <sys/types.h>
#include <pwd.h>
#include <unistd.h>
#ifdef HAVE_GETSPNAM
#include <shadow.h>
#include <crypt.h>
#endif
namespace SDDM {
PasswdBackend::PasswdBackend(HelperApp *parent)
@ -71,7 +74,9 @@ namespace SDDM {
m_app->error(QStringLiteral("Wrong user/password combination"), Auth::ERROR_AUTHENTICATION);
return false;
}
const char *system_passwd = pw->pw_passwd;
#ifdef HAVE_GETSPNAM
struct spwd *spw = getspnam(pw->pw_name);
if (!spw) {
qWarning() << "[Passwd] Could get passwd but not shadow";
@ -81,8 +86,11 @@ namespace SDDM {
if(!spw->sp_pwdp || !spw->sp_pwdp[0])
return true;
char *crypted = crypt(qPrintable(password), spw->sp_pwdp);
if (0 == strcmp(crypted, spw->sp_pwdp)) {
system_passwd = spw->sp_pwdp;
#endif
const char * const crypted = crypt(qPrintable(password), system_passwd);
if (0 == strcmp(crypted, system_passwd)) {
return true;
}

View File

@ -33,12 +33,18 @@ void ConfigurationTest::cleanupTestCase() { }
void ConfigurationTest::init() {
QFile::remove(CONF_FILE);
QDir(CONF_DIR).removeRecursively();
QDir().mkdir(CONF_DIR);
QDir(SYS_CONF_DIR).removeRecursively();
QDir().mkdir(SYS_CONF_DIR);
QFile::remove(CONF_FILE_COPY);
config = new TestConfig;
}
void ConfigurationTest::cleanup() {
QFile::remove(CONF_FILE);
QDir(CONF_DIR).removeRecursively();
QDir(SYS_CONF_DIR).removeRecursively();
QFile::remove(CONF_FILE_COPY);
if (config)
delete config;
@ -118,6 +124,8 @@ void ConfigurationTest::LineChanges() {
}
void ConfigurationTest::CustomEnum() {
QTest::qWait(2000);
QFile confFile(CONF_FILE);
confFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
confFile.write("Custom=bar\n");
@ -152,10 +160,50 @@ void ConfigurationTest::RightOnInit() {
QVERIFY(config->Custom.get() == TestConfig::BAZ);
}
void ConfigurationTest::RightOnInitDir() {
delete config;
QFile confFileA(SYS_CONF_DIR+QStringLiteral("/0001A"));
confFileA.open(QIODevice::WriteOnly | QIODevice::Truncate);
confFileA.write("Custom=Foo\n"); //overriden by B
confFileA.write("Boolean=false\n");
confFileA.close();
QFile confFileB(CONF_DIR+QStringLiteral("/0001A"));
confFileB.open(QIODevice::WriteOnly | QIODevice::Truncate);
confFileB.write("String=a\n"); //overriden by C
confFileB.write("Custom=Bar\n");
confFileB.write("StringList=a,b,c\n");
confFileB.write("Int=1111111\n"); //this is set in this config file but overriden in CONF_FILE
confFileB.close();
QFile confFileC(CONF_DIR+QStringLiteral("/0001B"));
confFileC.open(QIODevice::WriteOnly | QIODevice::Truncate);
confFileC.write("String=b\n");
confFileC.write("Int=1111111\n"); //overriden in CONF_FILE
confFileC.close();
QFile confFileMain(CONF_FILE);
confFileMain.open(QIODevice::WriteOnly | QIODevice::Truncate);
confFileMain.write("Int=99999\n");
confFileMain.close();
confFileB.close();
config = new TestConfig;
QVERIFY(config->StringList.get() == QStringList({QStringLiteral("a"), QStringLiteral("b"), QStringLiteral("c")}));
QVERIFY(config->String.get() == QStringLiteral("b"));
QVERIFY(config->Int.get() == 99999);
QVERIFY(config->Custom.get() == TestConfig::BAR);
QVERIFY(config->Boolean.get() == false);
}
void ConfigurationTest::FileChanged()
{
QVERIFY(config->String.get() == QStringLiteral("Test Variable Initial String"));
QTest::qWait(2000);
//test from no file to a file
QFile confFile(CONF_FILE);
confFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
@ -175,6 +223,25 @@ void ConfigurationTest::FileChanged()
config->load();
QVERIFY(config->String.get() == QStringLiteral("b"));
QTest::qWait(2000);
//add file to conf dir
QFile confFileA(CONF_DIR+QStringLiteral("/0001A"));
confFileA.open(QIODevice::WriteOnly | QIODevice::Truncate);
confFileA.write("Int=1111111\n"); //this is set in this config file but overriden in CONF_FILE
confFileA.close();
config->load();
QVERIFY(config->Int.get() ==1111111);
QTest::qWait(2000);
//modify existing file in conf dir
confFileA.open(QIODevice::WriteOnly | QIODevice::Truncate);
confFileA.write("Int=222222\n"); //this is set in this config file but overriden in CONF_FILE
confFileA.close();
config->load();
QVERIFY(config->Int.get() == 222222);
}
#include "moc_ConfigurationTest.cpp"

View File

@ -27,6 +27,8 @@
#include "ConfigReader.h"
#define CONF_FILE QStringLiteral("test.conf")
#define CONF_DIR QStringLiteral("testconfdir")
#define SYS_CONF_DIR QStringLiteral("testconfdir2")
#define CONF_FILE_COPY QStringLiteral("test_copy.conf")
#define TEST_STRING_1_PLAIN "Test Variable Initial String"
@ -35,7 +37,7 @@
#define TEST_STRINGLIST_1 {QStringLiteral("String1"), QStringLiteral("String2")}
#define TEST_BOOL_1 true
Config (TestConfig, CONF_FILE,
Config (TestConfig, CONF_FILE, CONF_DIR, SYS_CONF_DIR,
enum CustomType {
FOO,
BAR,
@ -91,6 +93,7 @@ private slots:
void LineChanges();
void CustomEnum();
void RightOnInit();
void RightOnInitDir();
void FileChanged();
private: