diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8112d59..f17f764 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,19 +17,37 @@ permissions: jobs: deb: - name: Debian package + name: Debian package (${{ matrix.name }}) runs-on: ubuntu-latest - # Plasma 6 arrived in Debian with trixie. - container: debian:trixie + # The package depends on the exact Qt it was built against, so each + # distribution gets a build and an APT repository of its own. + strategy: + matrix: + include: + # Plasma 6 arrived in Debian with trixie. + - name: Debian 13 + image: debian:trixie + codename: trixie + suffix: "~deb13" + - name: Kubuntu 26.04 + image: ubuntu:26.04 + codename: resolute + suffix: "~ubuntu26.04" + container: ${{ matrix.image }} + env: + DEBIAN_FRONTEND: noninteractive steps: - name: Install the build tools run: | apt-get update -qq + # Older Qt has the Wayland client tools in a package of their own. + extra="" + [ -n "$(apt-cache madison qt6-wayland-dev-tools)" ] && extra="qt6-wayland-dev-tools" apt-get install -y --no-install-recommends \ ca-certificates curl git make cmake g++ pkg-config gettext scdoc dpkg-dev \ - qt6-base-dev qt6-base-private-dev qt6-declarative-dev \ - qt6-wayland-dev qt6-wayland-dev-tools qt6-wayland-private-dev \ - liblayershellqtinterface-dev libkf6idletime-dev libkf6i18n-dev \ + qt6-base-dev qt6-base-dev-tools qt6-base-private-dev qt6-declarative-dev \ + qt6-wayland-dev qt6-wayland-private-dev $extra \ + liblayershellqtinterface-dev libkf6i18n-dev \ libopencv-dev libpam0g-dev libsystemd-dev - uses: actions/checkout@v7 @@ -38,6 +56,8 @@ jobs: run: packaging/check-version.sh "${{ github.ref_name }}" - run: packaging/build-deb.sh + env: + DEB_SUFFIX: ${{ matrix.suffix }} - name: Look inside what was built run: | @@ -46,7 +66,7 @@ jobs: - uses: actions/upload-artifact@v7 with: - name: deb + name: deb-${{ matrix.codename }} path: dist/*.deb if-no-files-found: error @@ -174,8 +194,10 @@ jobs: - name: Check that what was written can be verified if: steps.key.outputs.present == 'yes' run: | - gpg --verify pages/deb/InRelease - gpg --verify pages/deb/Release.gpg pages/deb/Release + for suite in pages/deb/*/; do + gpg --verify "$suite/InRelease" + gpg --verify "$suite/Release.gpg" "$suite/Release" + done gpg --verify pages/rpm/repodata/repomd.xml.asc pages/rpm/repodata/repomd.xml - uses: actions/upload-artifact@v7 @@ -199,11 +221,22 @@ jobs: git push "https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git" HEAD:gh-pages verify-apt: - name: Install from the APT repository + name: Install from the APT repository (${{ matrix.name }}) needs: publish if: inputs.dry_run runs-on: ubuntu-latest - container: debian:trixie + strategy: + matrix: + include: + - name: Debian 13 + image: debian:trixie + codename: trixie + - name: Kubuntu 26.04 + image: ubuntu:26.04 + codename: resolute + container: ${{ matrix.image }} + env: + DEBIAN_FRONTEND: noninteractive steps: - uses: actions/download-artifact@v8 with: @@ -214,7 +247,7 @@ jobs: apt-get update -qq && apt-get install -y --no-install-recommends gpg install -d -m 0755 /etc/apt/keyrings gpg --dearmor -o /etc/apt/keyrings/plasma-face-unlock.gpg < pages/KEY.gpg - echo "deb [signed-by=/etc/apt/keyrings/plasma-face-unlock.gpg] file://$PWD/pages/deb ./" \ + echo "deb [signed-by=/etc/apt/keyrings/plasma-face-unlock.gpg] file://$PWD/pages/deb/${{ matrix.codename }} ./" \ > /etc/apt/sources.list.d/plasma-face-unlock.list apt-get update apt-get install -y plasma-face-unlock diff --git a/CMakeLists.txt b/CMakeLists.txt index 74bceb3..440fd8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -133,8 +133,12 @@ if(PFU_BUILD_AGENT) find_package(Qt6 6.5 REQUIRED COMPONENTS Gui Quick WaylandClient) # The bubble needs the Wayland surface of its window, which only the # private API hands out. It is the same one Plasma itself uses for this. - set(QT_NO_PRIVATE_MODULE_WARNING ON) - find_package(Qt6 REQUIRED COMPONENTS GuiPrivate WaylandClientPrivate) + # Newer Qt ships the private modules as packages of their own; older Qt + # (6.8 in Debian 13) brings them along with the public ones. + if(EXISTS "${Qt6_DIR}/../Qt6GuiPrivate/Qt6GuiPrivateConfig.cmake") + set(QT_NO_PRIVATE_MODULE_WARNING ON) + find_package(Qt6 REQUIRED COMPONENTS GuiPrivate WaylandClientPrivate) + endif() find_package(LayerShellQt REQUIRED) find_package(KF6I18n REQUIRED) diff --git a/README.md b/README.md index 1cefdfd..6a59caa 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,12 @@

Face ID for KDE Plasma.

- Look at the screen and it unlocks. Works for the lock screen, sudo and admin prompts, and a photo of you is not enough. + Look at the screen and it unlocks: the lock screen, sudo and admin prompts. A photo of you is not enough.

+ Install | How to use | - Install | Is it safe? | Report a bug
@@ -29,84 +29,19 @@ The bubble above the lock screen: looking, recognised, not recognised

-Come back to your locked screen, move the mouse, look at it: a little bubble drops down at the top, -the face in it looks around, two green rings spin and land around a tick, and you are in. The same -for `sudo` in a terminal and for the admin password prompts of Plasma, if you want. Everything runs -on your machine, and your face is stored as numbers, never as a picture. +Come back to your locked screen and look at it. A bubble drops down at the top, finds your face, +and you are in. It works for `sudo` and Plasma's admin prompts too, if you want. Everything runs on +your computer, and your face is saved as numbers, never as a picture. -The look of the bubble and the photo check are inspired by [Glance](https://github.com/jonnyoo/glance) -(face unlock for the Mac). The code is written from scratch for Plasma. +## Install -## How to use - -Just run `plasma-face-unlock`. This will open the configuration TUI that looks like this: - -``` - Plasma Face Unlock - - Face unlock ON - - Faces 2 (Felix, Felix with glasses) - Camera Integrated Camera - Lock screen on - sudo on - Admin prompts off - Photo check strict (blink or turn your head) - Last unlock 2 minutes ago - - [1] Turn face unlock on or off - [2] Add a face - [3] Faces - [4] Settings - [5] Try it - [q] Quit - - > -``` - -Press `[1]`. The first time, it opens the setup window: look at the camera, then move your head -slowly in a circle until the ring around the picture is full (like setting up Face ID on a phone). -It asks for your password once before it adds the face. After that, lock the screen and look at it. - -`[5]` does one scan and shows what the camera sees, which helps a lot when something does not work. -`[4]` has everything else: - -``` - Settings - - ▸ Unlock the lock screen ON - Look when somebody comes back to the screen ON - Look right after the screen locks OFF - - Use for sudo in a terminal* ON - Use for admin prompts* OFF - - Photo check* strict (blink or turn your head) - How closely a face has to match* normal - Only while looking at the screen* ON - Camera* automatic (Integrated Camera) - How long one look lasts* 5 seconds - Learn from every unlock* ON - Not while the lid is closed* ON - - Show the bubble at the top ON - Bubble style island with the face - Animation speed normal - Bubble for sudo and admin prompts too ON - - Settings marked * are for the whole computer and ask for your password. - Up/Down: select, Space or Right: change, q: back -``` - -## How to install - -**Arch** +**Arch, CachyOS, EndeavourOS, Manjaro** (AUR) ```bash yay -S plasma-face-unlock ``` -**Fedora** +**Fedora 44** ```bash sudo curl -fsSL -o /etc/yum.repos.d/plasma-face-unlock.repo \ @@ -114,117 +49,96 @@ sudo curl -fsSL -o /etc/yum.repos.d/plasma-face-unlock.repo \ sudo dnf install plasma-face-unlock ``` -**Debian** (13 or newer) **and Kubuntu** (25.04 or newer) +**Debian 13** ```bash sudo install -d -m 0755 /etc/apt/keyrings curl -fsSL https://loonixtools.github.io/plasma-face-unlock/KEY.gpg \ | sudo gpg --dearmor -o /etc/apt/keyrings/plasma-face-unlock.gpg -echo "deb [signed-by=/etc/apt/keyrings/plasma-face-unlock.gpg] https://loonixtools.github.io/plasma-face-unlock/deb ./" \ +echo "deb [signed-by=/etc/apt/keyrings/plasma-face-unlock.gpg] https://loonixtools.github.io/plasma-face-unlock/deb/trixie ./" \ | sudo tee /etc/apt/sources.list.d/plasma-face-unlock.list sudo apt update && sudo apt install plasma-face-unlock ``` -You need Plasma 6 on Wayland and a camera. An infrared camera (the Windows Hello kind) works too. +**Kubuntu 26.04** + +```bash +sudo install -d -m 0755 /etc/apt/keyrings +curl -fsSL https://loonixtools.github.io/plasma-face-unlock/KEY.gpg \ + | sudo gpg --dearmor -o /etc/apt/keyrings/plasma-face-unlock.gpg +echo "deb [signed-by=/etc/apt/keyrings/plasma-face-unlock.gpg] https://loonixtools.github.io/plasma-face-unlock/deb/resolute ./" \ + | sudo tee /etc/apt/sources.list.d/plasma-face-unlock.list +sudo apt update && sudo apt install plasma-face-unlock +``` + +Updates then come with your normal system updates. + +You need Plasma 6 on Wayland and a camera. Infrared cameras (the Windows Hello kind) work too. + +## How to use + +```bash +plasma-face-unlock +``` + +This opens a menu. Press **1** and follow the setup window: look at the camera, then turn your head +slowly in a circle until the ring is full. Then lock the screen and look at it. + +| Key | | +|---|---| +| **1** | Turn face unlock on or off | +| **2** | Add another face, for example with glasses | +| **3** | Rename, turn off or delete faces | +| **4** | Settings: sudo, admin prompts, photo check, camera, bubble style, animation speed and more | +| **5** | One test scan that shows what the camera sees. Try this first when something does not work. | + +Without the menu: `plasma-face-unlock enable`, `disable`, `setup [NAME]`, `faces`, `remove ID`, +`test` and `status`. ## Is it safe? -**It is a convenience, not a security upgrade.** A phone builds a 3D map of your face with a dot -projector. A webcam only sees a flat picture, so this cannot be as safe as Face ID. What it does: +It is a convenience, not a security upgrade. Face ID on a phone sees your face in 3D. A webcam only +sees a flat picture. -- A photo, printed or on a phone, held up and turned any way, **does not** get in. With the photo - check on *strict* (the default) the face has to blink or turn a little, and a photo can do neither. -- A screen or a glossy print held up to the camera throws back one big flat reflection, and a phone - has straight edges around the face. Both fail the scan straight away. -- A **video** of you blinking can still get through. So can, some of the time, a photo that is - curled a lot and turned a lot. +- A photo does not get in: the face has to blink or turn a little, and a photo can do neither. +- A phone or tablet held up to the camera is caught by its reflection and its straight edges. +- A video of you can still get in. - Five failed tries in a row pause it for 15 minutes, or until you use your password. -- Your face data can only be read by root. Adding or deleting a face always needs your password, - never a face. -- sudo and admin prompts never take a face over SSH, or when you are not sitting at the machine. +- Only root can read your face data. Adding or deleting a face always needs your password. +- sudo and admin prompts never take a face over SSH. -If the machine guards something that matters, leave sudo and admin prompts off. +If the computer guards something important, leave sudo and admin prompts off. ## How it works -Four parts: - | | | |---|---| -| `plasma-face-unlockd` | Runs as root, started on demand. Owns the camera and the face data, and decides. | -| `plasma-face-unlock-agent` | Runs in your session. Watches the lock screen, draws the bubble, is the setup window. | -| `pam_plasma_face_unlock.so` | Lets sudo and polkit ask the daemon. | -| `plasma-face-unlock` | This menu. | +| `plasma-face-unlockd` | Runs as root when needed. It owns the camera and the face data and decides. | +| `plasma-face-unlock-agent` | Runs in your session. It watches the lock screen and draws the bubble. | +| `pam_plasma_face_unlock.so` | Lets sudo and admin prompts ask the daemon. No match: you type your password as usual. | +| `plasma-face-unlock` | The menu. | -Faces are found with **YuNet** and turned into 128 numbers with **SFace**, two small networks from -the OpenCV model zoo that run on the CPU in a few milliseconds. Two pictures of the same person give -numbers that point the same way; how much they do is the match. +Two small networks from the OpenCV model zoo find the face (YuNet) and turn it into numbers (SFace). +They run on the CPU in a few milliseconds. The lock screen is unlocked through logind, the same way +`loginctl unlock-session` does it. `man plasma-face-unlock` has all the details. -**The photo check** looks for a sign of life on top of the match: - -- **Blink:** the dark of both eyes shrinks to a line and comes back within the fraction of a second a - blink takes, while the rest of the face holds still. -- **Head turn:** the eyes and the corners of the mouth lie close to one plane, so for a flat picture - they predict exactly where the nose has to go when it is turned. A real nose sticks out of that - plane and misses the prediction by about as much as the head turned. - -The head turn check is tested against simulated heads and photos (`make test`): photos turned up to -60 degrees at heavy camera noise never pass, real heads of all shapes pass 98% of the time. - -**The lock screen** is not unlocked through its password prompt (Plasma runs fingerprints there, but -only once per lock). Instead the agent notices the screen locking, scans when you come back (a key, -the mouse, the lid, waking from sleep), and unlocks the session through logind, just like -`loginctl unlock-session`. KWin lets the bubble show above the lock screen because the agent's desktop -file asks for it. - -**sudo and admin prompts** get one line in front of their PAM stack: - -``` --auth sufficient /usr/lib/security/pam_plasma_face_unlock.so -``` - -A match lets you in, anything else falls through to the password. The dash makes PAM skip it quietly -if the module is ever missing, so sudo keeps working even after uninstalling. Turning it off takes out -exactly that line. - -The man page (`man plasma-face-unlock`) has all the details. - -## Commands - -| Command | | -|---|---| -| `plasma-face-unlock` | Interactive menu | -| `… enable` | Turn on (sets up a face first if needed) | -| `… disable` | Turn off, keep the faces | -| `… setup [NAME]` | Add a face | -| `… faces` | List the faces | -| `… remove ID` | Delete a face | -| `… test` | One scan, with what the camera sees | -| `… status` | What is on | - -## Building from source +## Build from source ```bash -make models # downloads the two networks, checked against pinned checksums +make models # downloads the two networks and checks them make make test sudo make install ``` -Needs CMake, a C++20 compiler, Qt 6 (Core, DBus, Network, Gui, Quick, WaylandClient), LayerShellQt, -KI18n, OpenCV 4.5.4 or newer with the DNN module, Linux-PAM and libsystemd. Optionally -`msgfmt` (gettext) for translations and `scdoc` for the man page. Supports `PREFIX` and `DESTDIR`. -`make check` runs syntax checks and shellcheck. - -To try it without a camera, point the camera setting at a folder of pictures (`images:/path`) or a -video (`file:/path.mp4`) in `/etc/plasma-face-unlock/config`. - -See [packaging/README.md](packaging/README.md) for release builds and repo signing. +You need CMake, a C++20 compiler, Qt 6, LayerShellQt, KI18n, OpenCV 4.5.4 or newer (with DNN), +Linux-PAM and libsystemd. `scdoc` and `msgfmt` are optional (man page, translations). +[packaging/README.md](packaging/README.md) explains releases. ## Credits -- [Glance](https://github.com/jonnyoo/glance) by Jonathan Zhou (MIT): the idea, the look of the bubble - and the model of deny and confirm cues. +- [Glance](https://github.com/jonnyoo/glance) by Jonathan Zhou (MIT): face unlock for the Mac. The + idea, the look of the bubble and the photo check come from there. The code here is new. - [YuNet](https://github.com/opencv/opencv_zoo/tree/main/models/face_detection_yunet) (MIT) and [SFace](https://github.com/opencv/opencv_zoo/tree/main/models/face_recognition_sface) (Apache-2.0) from the OpenCV model zoo. diff --git a/packaging/README.md b/packaging/README.md index da2a811..d587f10 100644 --- a/packaging/README.md +++ b/packaging/README.md @@ -20,6 +20,12 @@ development packages to build: Debian 13 (trixie) and current Fedora have them. The Debian package's library dependencies are read off the binaries by `dpkg-shlibdeps`; RPM does the same on its own. +The program uses Qt's private API, so a package only fits the Qt it was built +against. The `.deb` is therefore built twice, in Debian 13 and in Ubuntu 26.04 +(for Kubuntu), with a suffix on the version (`~deb13`, `~ubuntu26.04`), and each +gets an APT repository of its own: `deb/trixie` and `deb/resolute`. The RPM is +built on the current Fedora. + The two networks (YuNet and SFace, from the OpenCV model zoo) are not in the repository. `make models` downloads them and checks them against the checksums in the Makefile. The RPM spec and the PKGBUILD list them as sources diff --git a/packaging/build-deb.sh b/packaging/build-deb.sh index b752633..ad978b5 100755 --- a/packaging/build-deb.sh +++ b/packaging/build-deb.sh @@ -18,6 +18,9 @@ set -euo pipefail here="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)" version="${1:-$(make -s -C "$here" version)}" +# The package depends on the exact Qt of the distribution it is built on, so +# each one gets a build of its own, told apart by a suffix: ~deb13, ~ubuntu26.04. +debversion="$version${DEB_SUFFIX:-}" name=plasma-face-unlock # A package without its man page or its translations is not a package this @@ -49,7 +52,7 @@ depends="$(cd "$work" && dpkg-shlibdeps -O "${elves[@]/#/-e}" 2>/dev/null | sed [[ -n $depends ]] || { echo "$0: dpkg-shlibdeps found no dependencies" >&2; exit 1; } install -d "$root/DEBIAN" -sed -e "s|@VERSION@|$version|g" -e "s|@ARCH@|$arch|g" -e "s|@DEPENDS@|$depends|g" \ +sed -e "s|@VERSION@|$debversion|g" -e "s|@ARCH@|$arch|g" -e "s|@DEPENDS@|$depends|g" \ "$here/packaging/deb/control" > "$root/DEBIAN/control" install -Dm644 "$here/packaging/deb/copyright" "$root/usr/share/doc/$name/copyright" @@ -69,7 +72,7 @@ chmod 755 "$root/DEBIAN/prerm" | LC_ALL=C sort -z | xargs -0 md5sum > DEBIAN/md5sums ) mkdir -p "$here/dist" -out="$here/dist/${name}_${version}_${arch}.deb" +out="$here/dist/${name}_${debversion}_${arch}.deb" dpkg-deb --root-owner-group --build "$root" "$out" > /dev/null echo "$out" diff --git a/packaging/pages/index.html b/packaging/pages/index.html index 384ebeb..e43605b 100644 --- a/packaging/pages/index.html +++ b/packaging/pages/index.html @@ -76,16 +76,25 @@ documentation are on GitHub.

-

Debian 13 or newer, Kubuntu 25.04 or newer

+

Debian 13

sudo install -d -m 0755 /etc/apt/keyrings
 curl -fsSL @BASEURL@/KEY.gpg \
   | sudo gpg --dearmor -o /etc/apt/keyrings/plasma-face-unlock.gpg
-echo "deb [signed-by=/etc/apt/keyrings/plasma-face-unlock.gpg] @BASEURL@/deb ./" \
+echo "deb [signed-by=/etc/apt/keyrings/plasma-face-unlock.gpg] @BASEURL@/deb/trixie ./" \
   | sudo tee /etc/apt/sources.list.d/plasma-face-unlock.list
 sudo apt update
 sudo apt install plasma-face-unlock
-

Fedora (KDE Plasma)

+

Kubuntu 26.04

+
sudo install -d -m 0755 /etc/apt/keyrings
+curl -fsSL @BASEURL@/KEY.gpg \
+  | sudo gpg --dearmor -o /etc/apt/keyrings/plasma-face-unlock.gpg
+echo "deb [signed-by=/etc/apt/keyrings/plasma-face-unlock.gpg] @BASEURL@/deb/resolute ./" \
+  | sudo tee /etc/apt/sources.list.d/plasma-face-unlock.list
+sudo apt update
+sudo apt install plasma-face-unlock
+ +

Fedora 44 (KDE Plasma)

sudo curl -fsSL -o /etc/yum.repos.d/plasma-face-unlock.repo \
   @BASEURL@/plasma-face-unlock.repo
 sudo dnf install plasma-face-unlock
diff --git a/packaging/publish-repos.sh b/packaging/publish-repos.sh index 2512159..ae9444c 100755 --- a/packaging/publish-repos.sh +++ b/packaging/publish-repos.sh @@ -24,46 +24,34 @@ base_url="${PFU_REPO_URL:-https://loonixtools.github.io/plasma-face-unlock}" keyid="$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/ { print $5; exit }')" [[ -n $keyid ]] || { echo "$0: no secret key in the keyring" >&2; exit 1; } -mkdir -p "$pages/deb" "$pages/rpm" -cp -- "$incoming"/*.deb "$pages/deb/" +mkdir -p "$pages/rpm" cp -- "$incoming"/*.rpm "$pages/rpm/" -# --------------------------------------------------------------------------- -# APT -# --------------------------------------------------------------------------- -# A flat repository: the packages and their index sit in one directory and the -# sources line ends in "./". There is one distribution here and it is the same -# package for all of them, so the suite and component machinery of a pool -# layout would describe nothing. -( - cd "$pages/deb" +# One APT repository per distribution: each .deb depends on the exact Qt it was +# built against, and its version carries the suffix saying which one that was. +for suite in trixie:deb13 resolute:ubuntu26.04; do + codename="${suite%%:*}" + tag="${suite#*:}" + mkdir -p "$pages/deb/$codename" + cp -- "$incoming"/*"~${tag}_"*.deb "$pages/deb/$codename/" + ( + cd "$pages/deb/$codename" + rm -f Packages Packages.gz Release Release.gpg InRelease + dpkg-scanpackages --multiversion . > Packages + gzip -9kf Packages + apt-ftparchive \ + -o APT::FTPArchive::Release::Origin=plasma-face-unlock \ + -o APT::FTPArchive::Release::Label=plasma-face-unlock \ + -o APT::FTPArchive::Release::Suite="$codename" \ + -o APT::FTPArchive::Release::Codename="$codename" \ + -o APT::FTPArchive::Release::Architectures=amd64 \ + -o APT::FTPArchive::Release::Components=main \ + release . > Release + gpg --batch --yes --local-user "$keyid" --clearsign --output InRelease Release + gpg --batch --yes --local-user "$keyid" --detach-sign --armor --output Release.gpg Release + ) +done - # The old index must be gone before the new one is written: apt-ftparchive - # hashes every file in the directory, and a Release that hashes the - # previous Release is a Release that cannot be verified. - rm -f Packages Packages.gz Release Release.gpg InRelease - - dpkg-scanpackages --multiversion . > Packages - gzip -9kf Packages - - apt-ftparchive \ - -o APT::FTPArchive::Release::Origin=plasma-face-unlock \ - -o APT::FTPArchive::Release::Label=plasma-face-unlock \ - -o APT::FTPArchive::Release::Suite=stable \ - -o APT::FTPArchive::Release::Codename=stable \ - -o APT::FTPArchive::Release::Architectures=amd64 \ - -o APT::FTPArchive::Release::Components=main \ - release . > Release - - # Both signatures: InRelease is what current apt fetches, Release.gpg is - # what an older one falls back to. - gpg --batch --yes --local-user "$keyid" --clearsign --output InRelease Release - gpg --batch --yes --local-user "$keyid" --detach-sign --armor --output Release.gpg Release -) - -# --------------------------------------------------------------------------- -# RPM -# --------------------------------------------------------------------------- ( cd "$pages/rpm" createrepo_c --quiet --update . @@ -85,4 +73,4 @@ sed "s|@BASEURL@|$base_url|g" "$here/packaging/pages/plasma-face-unlock.repo" \ touch "$pages/.nojekyll" echo "signed with $keyid" -ls -1 "$pages/deb" "$pages/rpm" +ls -1 "$pages"/deb/* "$pages/rpm" diff --git a/src/agent/bubblewindow.cpp b/src/agent/bubblewindow.cpp index af1afc3..4f9b28b 100644 --- a/src/agent/bubblewindow.cpp +++ b/src/agent/bubblewindow.cpp @@ -68,7 +68,6 @@ void BubbleWindow::create() // rather than being pushed down below it. layer->setExclusiveZone(-1); layer->setKeyboardInteractivity(LayerShellQt::Window::KeyboardInteractivityNone); - layer->setActivateOnShow(false); // KWin makes a window type of the scope and takes one it does not // know for a normal window. Its scale effect then opens and closes // that with a blur forced behind the whole, mostly clear window: a