Compare commits

..

No commits in common. "local/yoda-main" and "pre-1.8-merge-20260910" have entirely different histories.

69 changed files with 1047 additions and 4508 deletions

View file

@ -1,10 +1,8 @@
Replace this text with a description of your changes, and why these changes are important. Read and acknowledge the list below. PRs without a completed checkbox will be closed. - [ ] I have disclosed use of any AI generated code in my commit messages.
- If you are using an LLM, and do not fully understand the changes it is making to the code base, do not create a PR.
- In our experience, AI generated code often results in overly complex code that lacks enough context for a proper fix or feature inclusion. This results in considerably longer code reviews. Due to this, AI authored or partially authored PRs may be closed without comment.
- [ ] I understand these changes in full and will be able to respond to review comments.
- [ ] My change is accurately described in the commit message.
- [ ] My contribution is tested and working as described.
- [ ] I have read the [Developer Certificate of Origin](https://developercertificate.org/) and certify my contribution under its conditions.
---
- I have not included any LLM (also known as AI) generated content in this PR, including code, comments, and descriptions.
- I understand these changes in full and will be able to respond to review comments.
- My change is accurately described in the commit message.
- My contribution is tested and working as described.
- I have read the [Developer Certificate of Origin](https://developercertificate.org/) and certify my contribution under its conditions.
- [ ] I have read and followed all of the above requirements. For more information, see our [contributor guide](https://github.com/pop-os/pop/blob/master/CONTRIBUTING.md).

View file

@ -13,12 +13,18 @@ jobs:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: Rust toolchain - name: Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1 uses: dtolnay/rust-toolchain@stable
with: with:
components: rustfmt components: rustfmt
rustflags: "" - name: Cargo cache
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }}
- name: Format - name: Format
run: cargo fmt --all -- --check run: cargo +stable fmt --all -- --check
clippy-check: clippy-check:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -26,14 +32,20 @@ jobs:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: Rust toolchain - name: Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1 uses: dtolnay/rust-toolchain@stable
with: with:
components: clippy components: clippy
rustflags: "" - name: Cargo cache
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }}
- name: System dependencies - name: System dependencies
run: sudo apt-get update; sudo apt-get install libudev-dev libgbm-dev libxkbcommon-dev libegl1-mesa-dev libwayland-dev libinput-dev libdbus-1-dev libsystemd-dev libseat-dev libdisplay-info-dev run: sudo apt-get update; sudo apt-get install libudev-dev libgbm-dev libxkbcommon-dev libegl1-mesa-dev libwayland-dev libinput-dev libdbus-1-dev libsystemd-dev libseat-dev libdisplay-info-dev
- name: Clippy - name: Clippy
run: cargo clippy --all-features -- -D warnings run: cargo +stable clippy --all-features -- -D warnings
check-features: check-features:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -41,15 +53,20 @@ jobs:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: Rust toolchain - name: Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1 uses: dtolnay/rust-toolchain@stable
- name: Cargo cache
uses: actions/cache@v5
with: with:
rustflags: "" path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }}
- name: System dependencies - name: System dependencies
run: sudo apt-get update; sudo apt-get install libudev-dev libgbm-dev libxkbcommon-dev libegl1-mesa-dev libwayland-dev libinput-dev libdbus-1-dev libsystemd-dev libseat-dev libdisplay-info-dev run: sudo apt-get update; sudo apt-get install libudev-dev libgbm-dev libxkbcommon-dev libegl1-mesa-dev libwayland-dev libinput-dev libdbus-1-dev libsystemd-dev libseat-dev libdisplay-info-dev
- run: cargo check --no-default-features - run: cargo +stable check --no-default-features
- run: cargo check --features debug - run: cargo +stable check --features debug
- run: cargo check --features profile-with-tracy - run: cargo +stable check --features profile-with-tracy
- run: cargo check --features profile-with-tracy-gpu - run: cargo +stable check --features profile-with-tracy-gpu
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -57,11 +74,21 @@ jobs:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v6 uses: actions/checkout@v6
- name: Rust toolchain - name: Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1 uses: dtolnay/rust-toolchain@stable
- name: Cargo cache
uses: actions/cache@v5
with: with:
rustflags: "" path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }}
- name: System dependencies - name: System dependencies
run: sudo apt-get update; sudo apt-get install libudev-dev libgbm-dev libxkbcommon-dev libegl1-mesa-dev libwayland-dev libinput-dev libdbus-1-dev libsystemd-dev libdisplay-info-dev libpixman-1-dev meson ninja-build run: sudo apt-get update; sudo apt-get install libudev-dev libgbm-dev libxkbcommon-dev libegl1-mesa-dev libwayland-dev libinput-dev libdbus-1-dev libsystemd-dev libdisplay-info-dev libpixman-1-dev meson ninja-build
- name: Build cache
uses: actions/cache@v5
with:
path: target
key: ${{ runner.os }}-build-${{ hashFiles('**/Cargo.toml') }}
- name: Build and install Libseat - name: Build and install Libseat
run: | run: |
wget https://git.sr.ht/~kennylevinsen/seatd/archive/0.9.1.tar.gz -O libseat-source.tar.gz wget https://git.sr.ht/~kennylevinsen/seatd/archive/0.9.1.tar.gz -O libseat-source.tar.gz

View file

@ -1,14 +0,0 @@
# From https://github.com/mheap/require-checklist-action, license MIT
name: Require Checklist
on:
pull_request:
types: [opened, edited, synchronize]
jobs:
job1:
runs-on: ubuntu-latest
steps:
- uses: mheap/require-checklist-action@v2
with:
requireChecklist: true

265
Cargo.lock generated
View file

@ -21,7 +21,7 @@ checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618"
[[package]] [[package]]
name = "accesskit" name = "accesskit"
version = "0.22.0" version = "0.22.0"
source = "git+https://github.com/wash2/accesskit?rev=6c20249#6c20249d3b9fd45e7002efad9f6b6171a9257912" source = "git+https://github.com/wash2/accesskit?tag=cosmic-0.14#f0599eed5f18111228266fe3f28991cc48b5964f"
dependencies = [ dependencies = [
"uuid", "uuid",
] ]
@ -29,7 +29,7 @@ dependencies = [
[[package]] [[package]]
name = "accesskit_consumer" name = "accesskit_consumer"
version = "0.32.0" version = "0.32.0"
source = "git+https://github.com/wash2/accesskit?rev=6c20249#6c20249d3b9fd45e7002efad9f6b6171a9257912" source = "git+https://github.com/wash2/accesskit?tag=cosmic-0.14#f0599eed5f18111228266fe3f28991cc48b5964f"
dependencies = [ dependencies = [
"accesskit", "accesskit",
"hashbrown 0.16.1", "hashbrown 0.16.1",
@ -38,7 +38,7 @@ dependencies = [
[[package]] [[package]]
name = "accesskit_macos" name = "accesskit_macos"
version = "0.23.0" version = "0.23.0"
source = "git+https://github.com/wash2/accesskit?rev=6c20249#6c20249d3b9fd45e7002efad9f6b6171a9257912" source = "git+https://github.com/wash2/accesskit?tag=cosmic-0.14#f0599eed5f18111228266fe3f28991cc48b5964f"
dependencies = [ dependencies = [
"accesskit", "accesskit",
"accesskit_consumer", "accesskit_consumer",
@ -51,7 +51,7 @@ dependencies = [
[[package]] [[package]]
name = "accesskit_windows" name = "accesskit_windows"
version = "0.30.0" version = "0.30.0"
source = "git+https://github.com/wash2/accesskit?rev=6c20249#6c20249d3b9fd45e7002efad9f6b6171a9257912" source = "git+https://github.com/wash2/accesskit?tag=cosmic-0.14#f0599eed5f18111228266fe3f28991cc48b5964f"
dependencies = [ dependencies = [
"accesskit", "accesskit",
"accesskit_consumer", "accesskit_consumer",
@ -64,7 +64,7 @@ dependencies = [
[[package]] [[package]]
name = "accesskit_winit" name = "accesskit_winit"
version = "0.30.0" version = "0.30.0"
source = "git+https://github.com/wash2/accesskit?rev=6c20249#6c20249d3b9fd45e7002efad9f6b6171a9257912" source = "git+https://github.com/wash2/accesskit?tag=cosmic-0.14#f0599eed5f18111228266fe3f28991cc48b5964f"
dependencies = [ dependencies = [
"accesskit", "accesskit",
"accesskit_macos", "accesskit_macos",
@ -135,7 +135,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046"
dependencies = [ dependencies = [
"android-properties", "android-properties",
"bitflags 2.13.2", "bitflags 2.13.1",
"cc", "cc",
"cesu8", "cesu8",
"jni", "jni",
@ -182,6 +182,15 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f47b57fc4521e3cae26a4d45b5227f8fadee4c345be0fefd8d5d1711afb8aeb9" checksum = "f47b57fc4521e3cae26a4d45b5227f8fadee4c345be0fefd8d5d1711afb8aeb9"
[[package]]
name = "approx"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278"
dependencies = [
"num-traits",
]
[[package]] [[package]]
name = "approx" name = "approx"
version = "0.5.1" version = "0.5.1"
@ -236,7 +245,7 @@ dependencies = [
"enumflags2", "enumflags2",
"futures-channel", "futures-channel",
"futures-util", "futures-util",
"rand 0.9.5", "rand 0.9.2",
"serde", "serde",
"serde_repr", "serde_repr",
"url", "url",
@ -470,9 +479,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.13.2" version = "2.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
dependencies = [ dependencies = [
"serde_core", "serde_core",
] ]
@ -610,7 +619,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7" checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7"
dependencies = [ dependencies = [
"async-task", "async-task",
"bitflags 2.13.2", "bitflags 2.13.1",
"futures-core", "futures-core",
"polling", "polling",
"rustix 1.1.4", "rustix 1.1.4",
@ -670,6 +679,16 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "cgmath"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a98d30140e3296250832bbaaff83b27dcd6fa3cc70fb6f1f3e5c9c0023b5317"
dependencies = [
"approx 0.4.0",
"num-traits",
]
[[package]] [[package]]
name = "chacha20" name = "chacha20"
version = "0.10.0" version = "0.10.0"
@ -854,7 +873,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"core-foundation 0.10.1", "core-foundation 0.10.1",
"libc", "libc",
] ]
@ -872,7 +891,7 @@ dependencies = [
name = "cosmic-client-toolkit" name = "cosmic-client-toolkit"
version = "0.2.0" version = "0.2.0"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"cosmic-protocols", "cosmic-protocols",
"libc", "libc",
"smithay-client-toolkit", "smithay-client-toolkit",
@ -885,7 +904,7 @@ name = "cosmic-comp"
version = "1.0.0" version = "1.0.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bitflags 2.13.2", "bitflags 2.13.1",
"calloop", "calloop",
"clap_lex", "clap_lex",
"cosmic-comp-config", "cosmic-comp-config",
@ -1001,7 +1020,7 @@ dependencies = [
name = "cosmic-protocols" name = "cosmic-protocols"
version = "0.2.0" version = "0.2.0"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"wayland-backend", "wayland-backend",
"wayland-client", "wayland-client",
"wayland-protocols", "wayland-protocols",
@ -1012,7 +1031,7 @@ dependencies = [
[[package]] [[package]]
name = "cosmic-randr-shell" name = "cosmic-randr-shell"
version = "1.10.0" version = "1.3.0"
dependencies = [ dependencies = [
"kdl", "kdl",
"slotmap", "slotmap",
@ -1021,7 +1040,7 @@ dependencies = [
[[package]] [[package]]
name = "cosmic-settings-config" name = "cosmic-settings-config"
version = "1.10.0" version = "0.1.0"
dependencies = [ dependencies = [
"cosmic-config", "cosmic-config",
"ron 0.11.0", "ron 0.11.0",
@ -1040,7 +1059,7 @@ dependencies = [
[[package]] [[package]]
name = "cosmic-settings-daemon-config" name = "cosmic-settings-daemon-config"
version = "1.10.0" version = "0.1.0"
dependencies = [ dependencies = [
"cosmic-config", "cosmic-config",
"cosmic-theme", "cosmic-theme",
@ -1051,7 +1070,7 @@ dependencies = [
name = "cosmic-text" name = "cosmic-text"
version = "0.19.0" version = "0.19.0"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"fontdb", "fontdb",
"harfrust", "harfrust",
"linebender_resource_handle", "linebender_resource_handle",
@ -1289,7 +1308,7 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"objc2 0.6.4", "objc2 0.6.4",
] ]
@ -1317,7 +1336,7 @@ dependencies = [
name = "dnd" name = "dnd"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"mime 0.1.0", "mime 0.1.0",
"raw-window-handle", "raw-window-handle",
"smithay-client-toolkit", "smithay-client-toolkit",
@ -1355,7 +1374,7 @@ version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80bc8c5c6c2941f70a55c15f8d9f00f9710ebda3ffda98075f996a0e6c92756f" checksum = "80bc8c5c6c2941f70a55c15f8d9f00f9710ebda3ffda98075f996a0e6c92756f"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"bytemuck", "bytemuck",
"drm-ffi", "drm-ffi",
"drm-fourcc", "drm-fourcc",
@ -1412,7 +1431,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25dd34cec49ab55d85ebf70139cb1ccd29c977ef6b6ba4fe85489d6877ee9ef3" checksum = "25dd34cec49ab55d85ebf70139cb1ccd29c977ef6b6ba4fe85489d6877ee9ef3"
dependencies = [ dependencies = [
"ahash", "ahash",
"bitflags 2.13.2", "bitflags 2.13.1",
"emath", "emath",
"epaint", "epaint",
"nohash-hasher", "nohash-hasher",
@ -1564,7 +1583,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys 0.52.0", "windows-sys 0.61.2",
] ]
[[package]] [[package]]
@ -1936,7 +1955,7 @@ version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce852e998d3ca5e4a97014fb31c940dc5ef344ec7d364984525fd11e8a547e6a" checksum = "ce852e998d3ca5e4a97014fb31c940dc5ef344ec7d364984525fd11e8a547e6a"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"drm", "drm",
"drm-fourcc", "drm-fourcc",
"gbm-sys", "gbm-sys",
@ -1963,8 +1982,8 @@ dependencies = [
"libc", "libc",
"log", "log",
"rustversion", "rustversion",
"windows-link 0.1.3", "windows-link 0.2.1",
"windows-result 0.3.4", "windows-result 0.4.1",
] ]
[[package]] [[package]]
@ -2104,7 +2123,7 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"gpu-descriptor-types", "gpu-descriptor-types",
"hashbrown 0.15.5", "hashbrown 0.15.5",
] ]
@ -2115,7 +2134,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
] ]
[[package]] [[package]]
@ -2152,7 +2171,7 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f9f40651a03bc0f7316bd75267ff5767e93017ef3cfffe76c6aa7252cc5a31c" checksum = "4f9f40651a03bc0f7316bd75267ff5767e93017ef3cfffe76c6aa7252cc5a31c"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"bytemuck", "bytemuck",
"core_maths", "core_maths",
"read-fonts 0.37.0", "read-fonts 0.37.0",
@ -2329,7 +2348,7 @@ dependencies = [
"js-sys", "js-sys",
"log", "log",
"wasm-bindgen", "wasm-bindgen",
"windows-core 0.61.2", "windows-core 0.62.2",
] ]
[[package]] [[package]]
@ -2374,7 +2393,7 @@ dependencies = [
name = "iced_core" name = "iced_core"
version = "0.14.0" version = "0.14.0"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"build_helpers", "build_helpers",
"bytes", "bytes",
"cosmic-client-toolkit", "cosmic-client-toolkit",
@ -2420,7 +2439,7 @@ dependencies = [
name = "iced_graphics" name = "iced_graphics"
version = "0.14.0" version = "0.14.0"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"bytemuck", "bytemuck",
"cosmic-text", "cosmic-text",
"half", "half",
@ -2490,7 +2509,7 @@ dependencies = [
name = "iced_wgpu" name = "iced_wgpu"
version = "0.14.0" version = "0.14.0"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"build_helpers", "build_helpers",
"bytemuck", "bytemuck",
"cosmic-client-toolkit", "cosmic-client-toolkit",
@ -2752,7 +2771,7 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"inotify-sys", "inotify-sys",
"libc", "libc",
] ]
@ -2772,7 +2791,7 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9793345a65d71317763a33066b5d8351f8760dde8d4930fe9e39b5f14a7959d" checksum = "f9793345a65d71317763a33066b5d8351f8760dde8d4930fe9e39b5f14a7959d"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"input-sys", "input-sys",
"libc", "libc",
"log", "log",
@ -2833,7 +2852,7 @@ dependencies = [
"portable-atomic", "portable-atomic",
"portable-atomic-util", "portable-atomic-util",
"serde_core", "serde_core",
"windows-sys 0.52.0", "windows-sys 0.61.2",
] ]
[[package]] [[package]]
@ -2930,7 +2949,7 @@ version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fbe853b403ae61a04233030ae8a79d94975281ed9770a1f9e246732b534b28d" checksum = "0fbe853b403ae61a04233030ae8a79d94975281ed9770a1f9e246732b534b28d"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"serde", "serde",
] ]
@ -3034,9 +3053,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.182" version = "0.2.189"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
[[package]] [[package]]
name = "libcosmic-yoda" name = "libcosmic-yoda"
@ -3072,7 +3091,6 @@ dependencies = [
"log", "log",
"palette", "palette",
"phf 0.13.1", "phf 0.13.1",
"roxmltree 0.20.0",
"rust-embed", "rust-embed",
"serde", "serde",
"slotmap", "slotmap",
@ -3090,7 +3108,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59fd96dbb2381ff31f314f07accbdf8550febdcc5cd8761ecaf7c1763361c359" checksum = "59fd96dbb2381ff31f314f07accbdf8550febdcc5cd8761ecaf7c1763361c359"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"libc", "libc",
"libdisplay-info-derive", "libdisplay-info-derive",
"libdisplay-info-sys", "libdisplay-info-sys",
@ -3136,14 +3154,14 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
[[package]] [[package]]
name = "libredox" name = "libredox"
version = "0.1.25" version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61ff90caf6077a803a240f62fdbe88645a890bbca49ef8174c3cb0404362171d" checksum = "28d0a00925a9f930d679b6789b721e3a7f9ed110f41b86d2497caa780c3a070a"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"libc", "libc",
"plain", "plain",
"redox_syscall 0.9.4", "redox_syscall 0.9.2",
] ]
[[package]] [[package]]
@ -3402,7 +3420,7 @@ version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7047791b5bc903b8cd963014b355f71dc9864a9a0b727057676c1dcae5cbc15" checksum = "c7047791b5bc903b8cd963014b355f71dc9864a9a0b727057676c1dcae5cbc15"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"block", "block",
"core-graphics-types 0.2.0", "core-graphics-types 0.2.0",
"foreign-types", "foreign-types",
@ -3464,9 +3482,9 @@ checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff"
[[package]] [[package]]
name = "mio" name = "mio"
version = "1.1.1" version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427"
dependencies = [ dependencies = [
"libc", "libc",
"log", "log",
@ -3498,7 +3516,7 @@ checksum = "618f667225063219ddfc61251087db8a9aec3c3f0950c916b614e403486f1135"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"bit-set", "bit-set",
"bitflags 2.13.2", "bitflags 2.13.1",
"cfg-if", "cfg-if",
"cfg_aliases", "cfg_aliases",
"codespan-reporting", "codespan-reporting",
@ -3522,7 +3540,7 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"jni-sys", "jni-sys",
"log", "log",
"ndk-sys", "ndk-sys",
@ -3552,7 +3570,7 @@ version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"cfg-if", "cfg-if",
"cfg_aliases", "cfg_aliases",
"libc", "libc",
@ -3580,7 +3598,7 @@ version = "8.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"fsevent-sys", "fsevent-sys",
"inotify", "inotify",
"kqueue", "kqueue",
@ -3598,7 +3616,7 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
] ]
[[package]] [[package]]
@ -3763,7 +3781,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"block2 0.5.1", "block2 0.5.1",
"libc", "libc",
"objc2 0.5.2", "objc2 0.5.2",
@ -3779,7 +3797,7 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"objc2 0.6.4", "objc2 0.6.4",
"objc2-core-foundation", "objc2-core-foundation",
"objc2-foundation 0.3.2", "objc2-foundation 0.3.2",
@ -3791,7 +3809,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"block2 0.5.1", "block2 0.5.1",
"objc2 0.5.2", "objc2 0.5.2",
"objc2-foundation 0.2.2", "objc2-foundation 0.2.2",
@ -3803,7 +3821,7 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"block2 0.6.2", "block2 0.6.2",
"dispatch2", "dispatch2",
"objc2 0.6.4", "objc2 0.6.4",
@ -3815,7 +3833,7 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"libc", "libc",
"objc2-core-foundation", "objc2-core-foundation",
] ]
@ -3838,7 +3856,7 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"objc2-core-foundation", "objc2-core-foundation",
"objc2-core-graphics", "objc2-core-graphics",
] ]
@ -3855,7 +3873,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"block2 0.5.1", "block2 0.5.1",
"libc", "libc",
"objc2 0.5.2", "objc2 0.5.2",
@ -3867,7 +3885,7 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"block2 0.6.2", "block2 0.6.2",
"objc2 0.6.4", "objc2 0.6.4",
"objc2-core-foundation", "objc2-core-foundation",
@ -3879,7 +3897,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"block2 0.5.1", "block2 0.5.1",
"objc2 0.5.2", "objc2 0.5.2",
"objc2-foundation 0.2.2", "objc2-foundation 0.2.2",
@ -3891,7 +3909,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"block2 0.5.1", "block2 0.5.1",
"objc2 0.5.2", "objc2 0.5.2",
"objc2-foundation 0.2.2", "objc2-foundation 0.2.2",
@ -3904,7 +3922,7 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"objc2 0.6.4", "objc2 0.6.4",
"objc2-core-foundation", "objc2-core-foundation",
"objc2-foundation 0.3.2", "objc2-foundation 0.3.2",
@ -4008,7 +4026,7 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6"
dependencies = [ dependencies = [
"approx", "approx 0.5.1",
"fast-srgb8", "fast-srgb8",
"palette_derive", "palette_derive",
"phf 0.11.3", "phf 0.11.3",
@ -4255,7 +4273,7 @@ version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"crc32fast", "crc32fast",
"fdeflate", "fdeflate",
"flate2", "flate2",
@ -4456,9 +4474,9 @@ dependencies = [
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.9.5" version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
dependencies = [ dependencies = [
"rand_chacha 0.9.0", "rand_chacha 0.9.0",
"rand_core 0.9.5", "rand_core 0.9.5",
@ -4570,7 +4588,7 @@ version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5018d583d6d2f5499352aea8d177e9067d1eb03ab17c78169d5ba7a30001b15" checksum = "c5018d583d6d2f5499352aea8d177e9067d1eb03ab17c78169d5ba7a30001b15"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"libredox", "libredox",
] ]
@ -4580,16 +4598,16 @@ version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
] ]
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.9.4" version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "737970939a87c6fa31e7acad13307bccbb017a073b695b6089a2c484f929e20e" checksum = "f1c93da5bb2c5d4e6c0ef7abeead62c89169a0a4882bfb83ac892f2423aea2fe"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
] ]
[[package]] [[package]]
@ -4717,7 +4735,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db09040cc89e461f1a265139777a2bde7f8d8c67c4936f700c63ce3e2904d468" checksum = "db09040cc89e461f1a265139777a2bde7f8d8c67c4936f700c63ce3e2904d468"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"bitflags 2.13.2", "bitflags 2.13.1",
"serde", "serde",
"serde_derive", "serde_derive",
"unicode-ident", "unicode-ident",
@ -4729,7 +4747,7 @@ version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd490c5b18261893f14449cbd28cb9c0b637aebf161cd77900bfdedaff21ec32" checksum = "fd490c5b18261893f14449cbd28cb9c0b637aebf161cd77900bfdedaff21ec32"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"once_cell", "once_cell",
"serde", "serde",
"serde_derive", "serde_derive",
@ -4807,11 +4825,11 @@ version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"errno", "errno",
"libc", "libc",
"linux-raw-sys 0.4.15", "linux-raw-sys 0.4.15",
"windows-sys 0.52.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@ -4820,11 +4838,11 @@ version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"errno", "errno",
"libc", "libc",
"linux-raw-sys 0.12.1", "linux-raw-sys 0.12.1",
"windows-sys 0.52.0", "windows-sys 0.61.2",
] ]
[[package]] [[package]]
@ -4839,7 +4857,7 @@ version = "0.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd3c7c96f8a08ee34eff8857b11b49b07d71d1c3f4e88f8a88d4c9e9f90b1702" checksum = "fd3c7c96f8a08ee34eff8857b11b49b07d71d1c3f4e88f8a88d4c9e9f90b1702"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"bytemuck", "bytemuck",
"core_maths", "core_maths",
"log", "log",
@ -5132,12 +5150,12 @@ checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
[[package]] [[package]]
name = "smithay" name = "smithay"
version = "0.7.0" version = "0.7.0"
source = "git+https://github.com/smithay/smithay.git?rev=e3d461a#e3d461a057ba244d213a8498ec372b0799cca103" source = "git+https://github.com/smithay/smithay.git?rev=5fb12b8#5fb12b87407b3680135c45d94214c5f1b1d0fbea"
dependencies = [ dependencies = [
"aliasable", "aliasable",
"appendlist", "appendlist",
"ash", "ash",
"bitflags 2.13.2", "bitflags 2.13.1",
"calloop", "calloop",
"cc", "cc",
"cursor-icon", "cursor-icon",
@ -5161,7 +5179,7 @@ dependencies = [
"pkg-config", "pkg-config",
"portable-atomic", "portable-atomic",
"profiling", "profiling",
"rand 0.10.0", "rand 0.9.2",
"reis", "reis",
"rustix 1.1.4", "rustix 1.1.4",
"scopeguard", "scopeguard",
@ -5190,7 +5208,7 @@ version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"bytemuck", "bytemuck",
"calloop", "calloop",
"calloop-wayland-source", "calloop-wayland-source",
@ -5227,13 +5245,16 @@ dependencies = [
[[package]] [[package]]
name = "smithay-egui" name = "smithay-egui"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/Smithay/smithay-egui.git?rev=6511552#65115521c756f356a7bcac8f1eeb715817a4666f" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6794c95b83518f9f91ae8c2faee52302d521c0d541d016b4ed632374041d9c42"
dependencies = [ dependencies = [
"cgmath",
"egui", "egui",
"egui_extras", "egui_extras",
"egui_glow", "egui_glow",
"image", "image",
"log", "log",
"memoffset",
"smithay", "smithay",
"xkbcommon 0.8.0", "xkbcommon 0.8.0",
] ]
@ -5288,7 +5309,7 @@ version = "0.3.0+sdk-1.3.268.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
] ]
[[package]] [[package]]
@ -5433,7 +5454,7 @@ dependencies = [
"getrandom 0.4.1", "getrandom 0.4.1",
"once_cell", "once_cell",
"rustix 1.1.4", "rustix 1.1.4",
"windows-sys 0.52.0", "windows-sys 0.61.2",
] ]
[[package]] [[package]]
@ -6168,7 +6189,7 @@ version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"hashbrown 0.15.5", "hashbrown 0.15.5",
"indexmap 2.13.0", "indexmap 2.13.0",
"semver", "semver",
@ -6208,7 +6229,7 @@ version = "0.31.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144" checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"rustix 1.1.4", "rustix 1.1.4",
"wayland-backend", "wayland-backend",
"wayland-scanner", "wayland-scanner",
@ -6220,7 +6241,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"cursor-icon", "cursor-icon",
"wayland-backend", "wayland-backend",
] ]
@ -6252,7 +6273,7 @@ version = "0.32.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23d0c813de3daa2ed6520af85a3bd49b0e722a3078506899aa9686fea58dc4b6" checksum = "23d0c813de3daa2ed6520af85a3bd49b0e722a3078506899aa9686fea58dc4b6"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"wayland-backend", "wayland-backend",
"wayland-client", "wayland-client",
"wayland-scanner", "wayland-scanner",
@ -6265,7 +6286,7 @@ version = "20250721.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"wayland-backend", "wayland-backend",
"wayland-client", "wayland-client",
"wayland-protocols", "wayland-protocols",
@ -6278,7 +6299,7 @@ version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e9567599ef23e09b8dad6e429e5738d4509dfc46b3b21f32841a304d16b29c8" checksum = "6e9567599ef23e09b8dad6e429e5738d4509dfc46b3b21f32841a304d16b29c8"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"wayland-backend", "wayland-backend",
"wayland-client", "wayland-client",
"wayland-protocols", "wayland-protocols",
@ -6292,7 +6313,7 @@ version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa98634619300a535a9a97f338aed9a5ff1e01a461943e8346ff4ae26007306b" checksum = "aa98634619300a535a9a97f338aed9a5ff1e01a461943e8346ff4ae26007306b"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"wayland-backend", "wayland-backend",
"wayland-client", "wayland-client",
"wayland-protocols", "wayland-protocols",
@ -6305,7 +6326,7 @@ version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"wayland-backend", "wayland-backend",
"wayland-client", "wayland-client",
"wayland-protocols", "wayland-protocols",
@ -6330,7 +6351,7 @@ version = "0.31.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc1846eb04c49182e04f4a099e2a830a2b745610bbc1d61246e206f29c7000a0" checksum = "cc1846eb04c49182e04f4a099e2a830a2b745610bbc1d61246e206f29c7000a0"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"downcast-rs", "downcast-rs",
"rustix 1.1.4", "rustix 1.1.4",
"wayland-backend", "wayland-backend",
@ -6382,7 +6403,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9cb534d5ffd109c7d1135f34cdae29e60eab94855a625dcfe1705f8bc7ad79f" checksum = "f9cb534d5ffd109c7d1135f34cdae29e60eab94855a625dcfe1705f8bc7ad79f"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"bitflags 2.13.2", "bitflags 2.13.1",
"bytemuck", "bytemuck",
"cfg-if", "cfg-if",
"cfg_aliases", "cfg_aliases",
@ -6414,7 +6435,7 @@ dependencies = [
"arrayvec", "arrayvec",
"bit-set", "bit-set",
"bit-vec", "bit-vec",
"bitflags 2.13.2", "bitflags 2.13.1",
"bytemuck", "bytemuck",
"cfg_aliases", "cfg_aliases",
"document-features", "document-features",
@ -6474,7 +6495,7 @@ dependencies = [
"arrayvec", "arrayvec",
"ash", "ash",
"bit-set", "bit-set",
"bitflags 2.13.2", "bitflags 2.13.1",
"block", "block",
"bytemuck", "bytemuck",
"cfg-if", "cfg-if",
@ -6518,7 +6539,7 @@ version = "28.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e18308757e594ed2cd27dddbb16a139c42a683819d32a2e0b1b0167552f5840c" checksum = "e18308757e594ed2cd27dddbb16a139c42a683819d32a2e0b1b0167552f5840c"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"bytemuck", "bytemuck",
"js-sys", "js-sys",
"log", "log",
@ -6547,7 +6568,7 @@ version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.61.2",
] ]
[[package]] [[package]]
@ -7069,7 +7090,7 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
name = "winit" name = "winit"
version = "0.31.0-beta.2" version = "0.31.0-beta.2"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"cfg_aliases", "cfg_aliases",
"cursor-icon", "cursor-icon",
"dpi 0.1.2", "dpi 0.1.2",
@ -7095,7 +7116,7 @@ version = "0.31.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2879d2854d1a43e48f67322d4bd097afcb6eb8f8f775c8de0260a71aea1df1aa" checksum = "2879d2854d1a43e48f67322d4bd097afcb6eb8f8f775c8de0260a71aea1df1aa"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"cfg_aliases", "cfg_aliases",
"cursor-icon", "cursor-icon",
"dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -7121,7 +7142,7 @@ name = "winit-android"
version = "0.31.0-beta.2" version = "0.31.0-beta.2"
dependencies = [ dependencies = [
"android-activity", "android-activity",
"bitflags 2.13.2", "bitflags 2.13.1",
"dpi 0.1.2", "dpi 0.1.2",
"ndk", "ndk",
"raw-window-handle", "raw-window-handle",
@ -7137,7 +7158,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d9c0d2cd93efec3a9f9ad819cfaf0834782403af7c0d248c784ec0c61761df" checksum = "51d9c0d2cd93efec3a9f9ad819cfaf0834782403af7c0d248c784ec0c61761df"
dependencies = [ dependencies = [
"android-activity", "android-activity",
"bitflags 2.13.2", "bitflags 2.13.1",
"dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ndk", "ndk",
"raw-window-handle", "raw-window-handle",
@ -7150,7 +7171,7 @@ dependencies = [
name = "winit-appkit" name = "winit-appkit"
version = "0.31.0-beta.2" version = "0.31.0-beta.2"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"block2 0.6.2", "block2 0.6.2",
"dispatch2", "dispatch2",
"dpi 0.1.2", "dpi 0.1.2",
@ -7173,7 +7194,7 @@ version = "0.31.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21310ca07851a49c348e0c2cc768e36b52ca65afda2c2354d78ed4b90074d8aa" checksum = "21310ca07851a49c348e0c2cc768e36b52ca65afda2c2354d78ed4b90074d8aa"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"block2 0.6.2", "block2 0.6.2",
"dispatch2", "dispatch2",
"dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -7223,7 +7244,7 @@ dependencies = [
name = "winit-core" name = "winit-core"
version = "0.31.0-beta.2" version = "0.31.0-beta.2"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"cursor-icon", "cursor-icon",
"dpi 0.1.2", "dpi 0.1.2",
"keyboard-types", "keyboard-types",
@ -7238,7 +7259,7 @@ version = "0.31.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4f0ccd7abb43740e2c6124ac7cae7d865ecec74eec63783e8922577ac232583" checksum = "e4f0ccd7abb43740e2c6124ac7cae7d865ecec74eec63783e8922577ac232583"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"cursor-icon", "cursor-icon",
"dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"keyboard-types", "keyboard-types",
@ -7251,7 +7272,7 @@ dependencies = [
name = "winit-orbital" name = "winit-orbital"
version = "0.31.0-beta.2" version = "0.31.0-beta.2"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"dpi 0.1.2", "dpi 0.1.2",
"libredox", "libredox",
"orbclient", "orbclient",
@ -7268,7 +7289,7 @@ version = "0.31.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51ea1fb262e7209f265f12bd0cc792c399b14355675e65531e9c8a87db287d46" checksum = "51ea1fb262e7209f265f12bd0cc792c399b14355675e65531e9c8a87db287d46"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"orbclient", "orbclient",
"raw-window-handle", "raw-window-handle",
@ -7282,7 +7303,7 @@ dependencies = [
name = "winit-uikit" name = "winit-uikit"
version = "0.31.0-beta.2" version = "0.31.0-beta.2"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"block2 0.6.2", "block2 0.6.2",
"dispatch2", "dispatch2",
"dpi 0.1.2", "dpi 0.1.2",
@ -7303,7 +7324,7 @@ version = "0.31.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "680a356e798837d8eb274d4556e83bceaf81698194e31aafc5cfb8a9f2fab643" checksum = "680a356e798837d8eb274d4556e83bceaf81698194e31aafc5cfb8a9f2fab643"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"block2 0.6.2", "block2 0.6.2",
"dispatch2", "dispatch2",
"dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -7323,7 +7344,7 @@ name = "winit-wayland"
version = "0.31.0-beta.2" version = "0.31.0-beta.2"
dependencies = [ dependencies = [
"ahash", "ahash",
"bitflags 2.13.2", "bitflags 2.13.1",
"calloop", "calloop",
"cursor-icon", "cursor-icon",
"dpi 0.1.2", "dpi 0.1.2",
@ -7350,7 +7371,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce5afb2ba07da603f84b722c95f9f9396d2cedae3944fb6c0cda4a6f88de545" checksum = "8ce5afb2ba07da603f84b722c95f9f9396d2cedae3944fb6c0cda4a6f88de545"
dependencies = [ dependencies = [
"ahash", "ahash",
"bitflags 2.13.2", "bitflags 2.13.1",
"calloop", "calloop",
"cursor-icon", "cursor-icon",
"dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -7374,7 +7395,7 @@ name = "winit-web"
version = "0.31.0-beta.2" version = "0.31.0-beta.2"
dependencies = [ dependencies = [
"atomic-waker", "atomic-waker",
"bitflags 2.13.2", "bitflags 2.13.1",
"concurrent-queue", "concurrent-queue",
"cursor-icon", "cursor-icon",
"dpi 0.1.2", "dpi 0.1.2",
@ -7397,7 +7418,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c2490a953fb776fbbd5e295d54f1c3847f4f15b6c3929ec53c09acda6487a92" checksum = "8c2490a953fb776fbbd5e295d54f1c3847f4f15b6c3929ec53c09acda6487a92"
dependencies = [ dependencies = [
"atomic-waker", "atomic-waker",
"bitflags 2.13.2", "bitflags 2.13.1",
"concurrent-queue", "concurrent-queue",
"cursor-icon", "cursor-icon",
"dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -7417,7 +7438,7 @@ dependencies = [
name = "winit-win32" name = "winit-win32"
version = "0.31.0-beta.2" version = "0.31.0-beta.2"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"cursor-icon", "cursor-icon",
"dpi 0.1.2", "dpi 0.1.2",
"raw-window-handle", "raw-window-handle",
@ -7434,7 +7455,7 @@ version = "0.31.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "644ea78af0e858aa3b092e5d1c67c41995a98220c81813f1353b28bc8bb91eaa" checksum = "644ea78af0e858aa3b092e5d1c67c41995a98220c81813f1353b28bc8bb91eaa"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"cursor-icon", "cursor-icon",
"dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"raw-window-handle", "raw-window-handle",
@ -7451,7 +7472,7 @@ version = "0.31.0-beta.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa5b600756534c7041aa93cd0d244d44b09fca1b89e202bd1cd80dd9f3636c46" checksum = "aa5b600756534c7041aa93cd0d244d44b09fca1b89e202bd1cd80dd9f3636c46"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"bytemuck", "bytemuck",
"calloop", "calloop",
"cursor-icon", "cursor-icon",
@ -7554,7 +7575,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bitflags 2.13.2", "bitflags 2.13.1",
"indexmap 2.13.0", "indexmap 2.13.0",
"log", "log",
"serde", "serde",
@ -7684,7 +7705,7 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5"
dependencies = [ dependencies = [
"bitflags 2.13.2", "bitflags 2.13.1",
"dlib", "dlib",
"log", "log",
"once_cell", "once_cell",

View file

@ -65,7 +65,7 @@ tracing = { version = "0.1.44", features = [
"max_level_debug", "max_level_debug",
"release_max_level_info", "release_max_level_info",
] } ] }
tracing-journald = { version = "0.3.2", optional = true } tracing-journald = "0.3.2"
tracing-subscriber = { version = "0.3.22", features = [ tracing-subscriber = { version = "0.3.22", features = [
"env-filter", "env-filter",
"tracing-log", "tracing-log",
@ -125,7 +125,7 @@ optional = true
debug = ["egui", "egui_plot", "smithay-egui", "anyhow/backtrace"] debug = ["egui", "egui_plot", "smithay-egui", "anyhow/backtrace"]
default = ["systemd"] default = ["systemd"]
logind = ["logind-zbus"] logind = ["logind-zbus"]
systemd = ["libsystemd", "logind", "tracing-journald"] systemd = ["libsystemd", "logind"]
profile-with-tracy = ["profiling/profile-with-tracy", "tracy-client/default"] profile-with-tracy = ["profiling/profile-with-tracy", "tracy-client/default"]
profile-with-tracy-gpu = ["profile-with-tracy", "smithay/tracy_gpu_profiling"] profile-with-tracy-gpu = ["profile-with-tracy", "smithay/tracy_gpu_profiling"]
@ -177,5 +177,4 @@ dnd = { path = "../window_clipboard/dnd" }
mime = { path = "../window_clipboard/mime" } mime = { path = "../window_clipboard/mime" }
[patch.crates-io] [patch.crates-io]
smithay = { git = "https://github.com/smithay/smithay.git", rev = "e3d461a" } smithay = { git = "https://github.com/smithay/smithay.git", rev = "5fb12b8" }
smithay-egui = { git = "https://github.com/Smithay/smithay-egui.git", rev = "6511552" }

67
Makefile Normal file
View file

@ -0,0 +1,67 @@
export prefix ?= /usr
sysconfdir ?= /etc
bindir = $(prefix)/bin
libdir = $(prefix)/lib
sharedir = $(prefix)/share
BINARY = cosmic-comp
CARGO_TARGET_DIR ?= target
TARGET = debug
DEBUG ?= 0
.PHONY = all clean install uninstall vendor
ifeq ($(DEBUG),0)
TARGET = release
ARGS += --release
endif
VENDOR ?= 0
ifneq ($(VENDOR),0)
ARGS += --offline --locked
endif
TARGET_BIN="$(DESTDIR)$(bindir)/$(BINARY)"
KEYBINDINGS_CONF="$(DESTDIR)$(sharedir)/cosmic/com.system76.CosmicSettings.Shortcuts/v1/defaults"
TILING_EXCEPTIONS_CONF="$(DESTDIR)$(sharedir)/cosmic/com.system76.CosmicSettings.WindowRules/v1/tiling_exception_defaults"
all: extract-vendor
cargo build $(ARGS)
clean:
cargo clean
distclean:
rm -rf .cargo vendor vendor.tar target
vendor:
mkdir -p .cargo
cargo vendor | head -n -1 > .cargo/config
echo 'directory = "vendor"' >> .cargo/config
[ -n "$(SOURCE_GIT_HASH)" ] && printf '\n[env]\nGIT_HASH = "%s"\n' "$(SOURCE_GIT_HASH)" >> .cargo/config || true
tar pcf vendor.tar vendor
rm -rf vendor
extract-vendor:
ifeq ($(VENDOR),1)
rm -rf vendor; tar pxf vendor.tar
endif
install:
install -Dm0755 "$(CARGO_TARGET_DIR)/$(TARGET)/$(BINARY)" "$(TARGET_BIN)"
install -Dm0644 "data/keybindings.ron" "$(KEYBINDINGS_CONF)"
install -Dm0644 "data/tiling-exceptions.ron" "$(TILING_EXCEPTIONS_CONF)"
install-bare-session: install
install -Dm0644 "data/cosmic.desktop" "$(DESTDIR)$(sharedir)/wayland-sessions/cosmic.desktop"
install -Dm0644 "data/cosmic-session.target" "$(DESTDIR)$(libdir)/systemd/user/cosmic-session.target"
install -Dm0644 "data/cosmic-session-pre.target" "$(DESTDIR)$(libdir)/systemd/user/cosmic-session-pre.target"
install -Dm0644 "data/cosmic-comp.service" "$(DESTDIR)$(libdir)/systemd/user/cosmic-comp.service"
install -Dm0755 "data/cosmic-service" "$(DESTDIR)/$(bindir)/cosmic-service"
uninstall:
rm "$(TARGET_BIN)" "$(KEYBINDINGS_CONF)"
uninstall-bare-session:
rm "$(DESTDIR)$(sharedir)/wayland-sessions/cosmic.desktop"

View file

@ -1,31 +0,0 @@
# cosmic-comp
Compositor for the COSMIC desktop environment
## Development
This project uses [just](https://github.com/casey/just) as a command runner.
### Available Commands
#### Building
- `just build-debug` - Compile with debug profile
- `just build-release` - Compile with release profile (default)
- `just build-vendored` - Compile release profile with vendored dependencies
- Requires vendoring first, which can be done with `just vendor`
#### Code Quality
- `just check` - Run clippy linter with pedantic warnings
#### Installation
- `just install` - Install binary and configuration files
- `just install-bare-session` - Install with bare session files (wayland session, systemd units)
- `just uninstall` - Remove installed files
- `just uninstall-bare-session` - Remove installed files including bare session files
#### Cleanup
- `just clean` - Run `cargo clean`
- `just clean-dist` - Run `cargo clean` and remove vendored dependencies
#### Vendoring
- `just vendor` - Vendor dependencies locally and create vendor.tar
- `just vendor-extract` - Extract vendored dependencies from vendor.tar

View file

@ -1,53 +0,0 @@
cargo-target-dir := env('CARGO_TARGET_DIR', 'target')
# Compile with debug profile
build-debug *args:
cargo build {{ args }}
# Compile with release profile
build-release *args: (build-debug '--release' args)
# Compile with a vendored tarball
build-vendored *args: vendor-extract (build-release '--frozen --offline' args)
# Check for errors and linter warnings
check *args:
cargo clippy --all-features {{ args }} -- -W clippy::pedantic
# Remove Cargo build artifacts
[no-cd]
clean:
cargo clean
# Also remove .cargo and vendored dependencies
[no-cd]
clean-dist: clean
rm -rf .cargo vendor vendor.tar
# Vendor Cargo dependencies locally
[no-cd]
vendor:
#!/usr/bin/env sh
mkdir -p .cargo
cargo vendor --sync Cargo.toml | head -n -1 > .cargo/config.toml
echo 'directory = "vendor"' >> .cargo/config.toml
echo >> .cargo/config.toml
echo '[env]' >> .cargo/config.toml
if [ -n "${SOURCE_DATE_EPOCH}" ]
then
source_date="$(date -d "@${SOURCE_DATE_EPOCH}" "+%Y-%m-%d")"
echo "VERGEN_GIT_COMMIT_DATE = \"${source_date}\"" >> .cargo/config.toml
fi
if [ -n "${SOURCE_GIT_HASH}" ]
then
echo "GIT_HASH = \"${SOURCE_GIT_HASH}\"" >> .cargo/config.toml
fi
tar pcf vendor.tar .cargo vendor
rm -rf .cargo vendor
# Extracts vendored dependencies
[no-cd]
[private]
vendor-extract:
rm -rf vendor
tar pxf vendor.tar

View file

@ -3,7 +3,6 @@
use cosmic_config::{CosmicConfigEntry, cosmic_config_derive::CosmicConfigEntry}; use cosmic_config::{CosmicConfigEntry, cosmic_config_derive::CosmicConfigEntry};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use std::time::Duration;
use crate::input::TouchpadOverride; use crate::input::TouchpadOverride;
@ -67,13 +66,6 @@ impl Default for AppearanceConfig {
} }
} }
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub enum DecorationPreference {
#[default]
ClientSide,
ServerSide,
}
#[derive(Clone, Debug, PartialEq, CosmicConfigEntry)] #[derive(Clone, Debug, PartialEq, CosmicConfigEntry)]
#[version = 1] #[version = 1]
pub struct CosmicCompConfig { pub struct CosmicCompConfig {
@ -107,12 +99,11 @@ pub struct CosmicCompConfig {
pub edge_snap_threshold: u32, pub edge_snap_threshold: u32,
pub accessibility_zoom: ZoomConfig, pub accessibility_zoom: ZoomConfig,
pub appearance_settings: AppearanceConfig, pub appearance_settings: AppearanceConfig,
/// When the cursor hides itself: idle, fullscreen idle, typing, touch /// Hide the cursor after this many seconds of pointer inactivity (None disables)
pub cursor_hide: CursorHideConfig, pub cursor_hide_timeout: Option<u32>,
/// Briefly magnify the cursor when the pointer is shaken, to help locate it /// Briefly magnify the cursor when the pointer is shaken, to help locate it
pub cursor_shake_to_find: bool, pub cursor_shake_to_find: bool,
pub activation_policy: ActivationPolicy, pub activation_policy: ActivationPolicy,
pub decoration_preference: DecorationPreference,
} }
impl Default for CosmicCompConfig { impl Default for CosmicCompConfig {
@ -149,10 +140,9 @@ impl Default for CosmicCompConfig {
edge_snap_threshold: 0, edge_snap_threshold: 0,
accessibility_zoom: ZoomConfig::default(), accessibility_zoom: ZoomConfig::default(),
appearance_settings: AppearanceConfig::default(), appearance_settings: AppearanceConfig::default(),
cursor_hide: CursorHideConfig::default(), cursor_hide_timeout: None,
cursor_shake_to_find: true, cursor_shake_to_find: true,
activation_policy: ActivationPolicy::default(), activation_policy: ActivationPolicy::default(),
decoration_preference: DecorationPreference::default(),
} }
} }
} }
@ -199,81 +189,6 @@ fn default_repeat_delay() -> u32 {
600 600
} }
/// What the cursor idle timer should do when it fires.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HideDecision {
/// Nothing applies in this context; drop the timer until the next activity.
Drop,
/// Hide the cursor now.
Hide,
/// Not yet — re-arm for this long.
RearmAfter(Duration),
}
/// When the cursor hides itself. Every trigger is revealed by pointer input, so
/// these differ only in what arms the hide and after how long.
// `default`: a trigger added later must not make every existing file fail to
// deserialize, which `get_entry` would swallow as "reset everyone to defaults".
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
#[serde(default)]
pub struct CursorHideConfig {
/// Seconds of pointer inactivity before hiding, anywhere. `None` disables.
pub idle_timeout: Option<u32>,
/// Seconds of pointer inactivity before hiding over a fullscreen window.
/// Shortens `idle_timeout` in fullscreen; it never lengthens it.
pub fullscreen_idle_timeout: Option<u32>,
/// Hide as soon as a key is pressed.
pub while_typing: bool,
/// Hide on touch input, until the pointer next moves.
pub after_touch: bool,
}
impl CursorHideConfig {
/// The shortest timeout that applies right now, if any.
pub fn effective_timeout(&self, fullscreen: bool) -> Option<Duration> {
let secs = if fullscreen {
match (self.idle_timeout, self.fullscreen_idle_timeout) {
(Some(a), Some(b)) => Some(a.min(b)),
(a, b) => a.or(b),
}
} else {
self.idle_timeout
}?;
Some(Duration::from_secs(secs as u64))
}
/// What to do when the idle timer fires after `elapsed` without pointer input.
pub fn resolve(&self, elapsed: Duration, fullscreen: bool) -> HideDecision {
match self.effective_timeout(fullscreen) {
None => HideDecision::Drop,
Some(timeout) if elapsed >= timeout => HideDecision::Hide,
Some(timeout) => HideDecision::RearmAfter(timeout - elapsed),
}
}
/// How long to wait before the idle timer should next fire, given how long
/// it has been since the last pointer event. Pessimistic: fullscreen only
/// ever shortens a timeout, so arming as if fullscreen cannot fire too
/// late, and `resolve` corrects an early fire once the context is known.
pub fn arm_delay(&self, since_pointer_activity: Duration) -> Option<Duration> {
Some(
self.effective_timeout(true)?
.saturating_sub(since_pointer_activity),
)
}
}
impl Default for CursorHideConfig {
fn default() -> Self {
CursorHideConfig {
idle_timeout: None,
fullscreen_idle_timeout: Some(3),
while_typing: false,
after_touch: true,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
pub struct ZoomConfig { pub struct ZoomConfig {
pub start_on_login: bool, pub start_on_login: bool,
@ -339,109 +254,3 @@ pub enum XwaylandDescaling {
#[default] #[default]
Fractional, Fractional,
} }
#[cfg(test)]
mod test {
use super::{CursorHideConfig, HideDecision};
use std::time::Duration;
const OFF: CursorHideConfig = CursorHideConfig {
idle_timeout: None,
fullscreen_idle_timeout: None,
while_typing: false,
after_touch: false,
};
fn secs(n: u64) -> Duration {
Duration::from_secs(n)
}
#[test]
fn no_timeout_never_hides() {
assert_eq!(OFF.resolve(secs(600), false), HideDecision::Drop);
assert_eq!(OFF.resolve(secs(600), true), HideDecision::Drop);
}
#[test]
fn global_timeout_applies_everywhere() {
let cfg = CursorHideConfig {
idle_timeout: Some(10),
..OFF
};
assert_eq!(
cfg.resolve(secs(4), false),
HideDecision::RearmAfter(secs(6))
);
assert_eq!(cfg.resolve(secs(10), false), HideDecision::Hide);
// A fullscreen window must not suppress an enabled global timeout.
assert_eq!(cfg.resolve(secs(10), true), HideDecision::Hide);
}
#[test]
fn fullscreen_timeout_only_applies_in_fullscreen() {
let cfg = CursorHideConfig {
fullscreen_idle_timeout: Some(3),
..OFF
};
assert_eq!(cfg.resolve(secs(3), true), HideDecision::Hide);
assert_eq!(cfg.resolve(secs(600), false), HideDecision::Drop);
}
#[test]
fn fullscreen_shortens_but_never_lengthens() {
let short_fs = CursorHideConfig {
idle_timeout: Some(10),
fullscreen_idle_timeout: Some(3),
..OFF
};
assert_eq!(short_fs.resolve(secs(3), true), HideDecision::Hide);
assert_eq!(
short_fs.resolve(secs(3), false),
HideDecision::RearmAfter(secs(7))
);
let long_fs = CursorHideConfig {
idle_timeout: Some(3),
fullscreen_idle_timeout: Some(30),
..OFF
};
assert_eq!(long_fs.resolve(secs(3), true), HideDecision::Hide);
}
#[test]
fn boundary_is_inclusive() {
let cfg = CursorHideConfig {
idle_timeout: Some(5),
..OFF
};
assert_eq!(
cfg.resolve(Duration::from_millis(4999), false),
HideDecision::RearmAfter(Duration::from_millis(1))
);
assert_eq!(cfg.resolve(secs(5), false), HideDecision::Hide);
assert_eq!(cfg.resolve(secs(6), false), HideDecision::Hide);
}
#[test]
fn arm_delay_measures_from_the_last_pointer_event() {
let cfg = CursorHideConfig {
idle_timeout: Some(10),
..OFF
};
assert_eq!(cfg.arm_delay(Duration::ZERO), Some(secs(10)));
assert_eq!(cfg.arm_delay(secs(4)), Some(secs(6)));
// Exactly due, and past due: fire immediately rather than deferring.
assert_eq!(cfg.arm_delay(secs(10)), Some(Duration::ZERO));
assert_eq!(cfg.arm_delay(secs(600)), Some(Duration::ZERO));
// Armed against the shortest timeout that any context could want.
let fs = CursorHideConfig {
idle_timeout: Some(10),
fullscreen_idle_timeout: Some(3),
..OFF
};
assert_eq!(fs.arm_delay(secs(1)), Some(secs(2)));
assert_eq!(OFF.arm_delay(Duration::ZERO), None);
}
}

1
debian/control vendored
View file

@ -6,7 +6,6 @@ Build-Depends:
cargo, cargo,
cmake, cmake,
debhelper-compat (=10), debhelper-compat (=10),
just,
libegl1-mesa-dev, libegl1-mesa-dev,
libfontconfig-dev, libfontconfig-dev,
libgbm-dev, libgbm-dev,

12
debian/rules vendored
View file

@ -1,6 +1,6 @@
#!/usr/bin/make -f #!/usr/bin/make -f
DESTDIR = debian/cosmic-comp export sysconfdir = "/usr/share"
export VENDOR ?= 1 export VENDOR ?= 1
CLEAN ?= 1 CLEAN ?= 1
@ -9,18 +9,12 @@ CLEAN ?= 1
override_dh_auto_clean: override_dh_auto_clean:
ifeq ($(CLEAN),1) ifeq ($(CLEAN),1)
ischroot && just clean || just clean-dist ischroot && make clean || make distclean
endif endif
ifeq ($(VENDOR),1) ifeq ($(VENDOR),1)
ischroot || just vendor ischroot || make vendor
endif endif
override_dh_auto_build:
just build-vendored
override_dh_auto_install:
just rootdir=$(DESTDIR) install
override_dh_installinit: override_dh_installinit:
dh_installinit -r dh_installinit -r

View file

@ -1,64 +0,0 @@
name := 'cosmic-comp'
rootdir := ''
prefix := '/usr'
sysconfdir := '/etc'
base-dir := absolute_path(clean(rootdir / prefix))
sysconfdir-dir := absolute_path(clean(rootdir / sysconfdir))
bin-dir := base-dir / 'bin'
lib-dir := base-dir / 'lib'
share-dir := base-dir / 'share'
bin-src := cargo-target-dir / 'release' / name
bin-dst := bin-dir / name
keybindings-src := 'data' / 'keybindings.ron'
keybindings-dst := share-dir / 'cosmic' / 'com.system76.CosmicSettings.Shortcuts' / 'v1' / 'defaults'
tiling-exceptions-src := 'data' / 'tiling-exceptions.ron'
tiling-exceptions-dst := share-dir / 'cosmic' / 'com.system76.CosmicSettings.WindowRules' / 'v1' / 'tiling_exception_defaults'
session-desktop-src := 'data' / 'cosmic.desktop'
session-desktop-dst := share-dir / 'wayland-sessions' / 'cosmic.desktop'
systemd-session-target-src := 'data' / 'cosmic-session.target'
systemd-session-target-dst := lib-dir / 'systemd' / 'user' / 'cosmic-session.target'
systemd-session-pre-target-src := 'data' / 'cosmic-session-pre.target'
systemd-session-pre-target-dst := lib-dir / 'systemd' / 'user' / 'cosmic-session-pre.target'
systemd-comp-service-src := 'data' / 'cosmic-comp.service'
systemd-comp-service-dst := lib-dir / 'systemd' / 'user' / 'cosmic-comp.service'
cosmic-service-src := 'data' / 'cosmic-service'
cosmic-service-dst := bin-dir / 'cosmic-service'
import 'cargo.just'
# Default recipe which runs `just build-release`
[private]
default: build-release
# Installs files
install:
install -Dm0755 {{bin-src}} {{bin-dst}}
install -Dm0644 {{keybindings-src}} {{keybindings-dst}}
install -Dm0644 {{tiling-exceptions-src}} {{tiling-exceptions-dst}}
# Installs files including bare session files
install-bare-session: install
install -Dm0644 {{session-desktop-src}} {{session-desktop-dst}}
install -Dm0644 {{systemd-session-target-src}} {{systemd-session-target-dst}}
install -Dm0644 {{systemd-session-pre-target-src}} {{systemd-session-pre-target-dst}}
install -Dm0644 {{systemd-comp-service-src}} {{systemd-comp-service-dst}}
install -Dm0755 {{cosmic-service-src}} {{cosmic-service-dst}}
# Uninstalls installed files
uninstall:
rm {{bin-dst}} {{keybindings-dst}} {{tiling-exceptions-dst}}
# Uninstalls installed files including bare session files
uninstall-bare-session: uninstall
rm {{session-desktop-dst}} {{systemd-session-target-dst}} {{systemd-session-pre-target-dst}} {{systemd-comp-service-dst}} {{cosmic-service-dst}}

View file

@ -1,20 +0,0 @@
a11y-zoom-move-continuously = La vista bolega de contunh amb lo ponchador
a11y-zoom-move-onedge = La lista bolega quand lo ponchador atenh un caire
a11y-zoom-move-centered = La vista bolega per gardar lo ponchador al centre
a11y-zoom-settings = Paramètres de la lópia...
unknown-keybinding = <unset>
window-menu-tiled = Fenèstras bandejanta
window-menu-screenshot = Prendre una captura d’ecran
window-menu-resize = Redimensionar
window-menu-move-prev-workspace = Desplaçar a l’espaci de trabalh precedent
window-menu-move-next-workspace = Desplaçar a l'espaci de trabalh seguent
window-menu-stack = Crear una pila de fenèstras
window-menu-unstack-all = Desapilar totas las fenèstras
window-menu-unstack = Desapilar la fenèstra
window-menu-sticky = Fenèstra adesiva
window-menu-close = Tampar
window-menu-close-all = Tampar totas las fenèstras
window-menu-resize-edge-top = Amont
window-menu-resize-edge-left = Esquèrra
window-menu-resize-edge-right = Drecha
window-menu-resize-edge-bottom = Aval

View file

@ -693,7 +693,7 @@ impl Device {
) )
.with_context(|| { .with_context(|| {
format!( format!(
"Failed to obtain file descriptor for drm device: {}", "Failed to optain file descriptor for drm device: {}",
path.display() path.display()
) )
})?, })?,

View file

@ -32,11 +32,7 @@ use smithay::{
calloop::{Dispatcher, EventLoop, LoopHandle}, calloop::{Dispatcher, EventLoop, LoopHandle},
drm::{ drm::{
Device as _, Device as _,
control::{ control::{Device as _, connector::Interface, crtc},
Device as _,
connector::{Interface, State as ConnectorState},
crtc,
},
}, },
input::{self, Libinput}, input::{self, Libinput},
wayland_protocols::wp::linux_dmabuf::zv1::server::zwp_linux_dmabuf_feedback_v1::TrancheFlags, wayland_protocols::wp::linux_dmabuf::zv1::server::zwp_linux_dmabuf_feedback_v1::TrancheFlags,
@ -254,18 +250,13 @@ fn determine_primary_gpu(
// try to find builtin display // try to find builtin display
for dev in drm_devices.values() { for dev in drm_devices.values() {
let drm = dev.drm.device(); if dev.inner.surfaces.values().any(|s| {
let res_handles = drm.resource_handles()?; if let Ok(conn_info) = dev.drm.device().get_connector(s.connector, false) {
let connectors = res_handles.connectors(); let i = conn_info.interface();
if connectors.iter().any(|conn| { i == Interface::EmbeddedDisplayPort || i == Interface::LVDS || i == Interface::DSI
let Ok(conn_info) = drm.get_connector(*conn, false) else { } else {
return false; false
}; }
let i = conn_info.interface();
conn_info.state() == ConnectorState::Connected
&& (i == Interface::EmbeddedDisplayPort
|| i == Interface::LVDS
|| i == Interface::DSI)
}) { }) {
return Ok(Some(dev.inner.render_node)); return Ok(Some(dev.inner.render_node));
} }
@ -615,13 +606,7 @@ impl State {
.clone(); .clone();
let mut feedback = let mut feedback =
DmabufFeedbackBuilder::new(primary_node.dev_id(), primary_formats.clone()) DmabufFeedbackBuilder::new(primary_node.dev_id(), primary_formats.clone());
.add_preference_tranche(
primary_node.dev_id(),
TrancheFlags::Sampling,
primary_formats.iter().cloned(),
3..=6,
);
for dev in kms for dev in kms
.drm_devices .drm_devices
.values() .values()

View file

@ -5,11 +5,9 @@ use crate::{
element::AsGlowRenderer, element::AsGlowRenderer,
wayland::{SurfaceRenderElement, push_render_elements_from_surface_tree}, wayland::{SurfaceRenderElement, push_render_elements_from_surface_tree},
}, },
shell::focus::target::KeyboardFocusTarget,
utils::prelude::*, utils::prelude::*,
wayland::handlers::compositor::FRAME_TIME_FILTER, wayland::handlers::compositor::FRAME_TIME_FILTER,
}; };
use cosmic_comp_config::HideDecision;
use keyframe::{ease, functions::EaseInOutCubic}; use keyframe::{ease, functions::EaseInOutCubic};
use resvg::{tiny_skia, usvg}; use resvg::{tiny_skia, usvg};
use serde::Deserialize; use serde::Deserialize;
@ -453,32 +451,6 @@ pub fn draw_dnd_icon<R>(
); );
} }
/// Why the cursor is currently hidden. Determines what brings it back.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HideReason {
/// No pointer activity for the configured timeout.
Idle,
/// A key was pressed while `while_typing` is enabled.
Typing,
/// Touch input arrived while `after_touch` is enabled.
Touch,
}
/// Whether a pointer event carries movement. A touch-hidden cursor comes back
/// only on real movement, so the distinction has to reach the call site.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PointerEventKind {
Motion,
Other,
}
impl HideReason {
/// Whether an event of this kind should reveal the cursor.
fn revealed_by(self, kind: PointerEventKind) -> bool {
matches!(kind, PointerEventKind::Motion) || !matches!(self, HideReason::Touch)
}
}
pub type CursorState = Mutex<CursorStateInner>; pub type CursorState = Mutex<CursorStateInner>;
pub struct CursorStateInner { pub struct CursorStateInner {
current_cursor: Option<CursorIcon>, current_cursor: Option<CursorIcon>,
@ -490,10 +462,9 @@ pub struct CursorStateInner {
current_image: Option<Image>, current_image: Option<Image>,
image_cache: Vec<CachedFrame>, image_cache: Vec<CachedFrame>,
hidden: Option<HideReason>, hidden: bool,
idle_timer: Option<RegistrationToken>, idle_timer: Option<RegistrationToken>,
last_armed: Option<Instant>, last_armed: Option<Instant>,
last_pointer_activity: Instant,
// shake-to-find // shake-to-find
shake_path: VecDeque<PathSample>, shake_path: VecDeque<PathSample>,
@ -723,8 +694,7 @@ impl Default for CursorStateInner {
current_image: None, current_image: None,
image_cache: Vec::new(), image_cache: Vec::new(),
hidden: None, hidden: false,
last_pointer_activity: Instant::now(),
idle_timer: None, idle_timer: None,
last_armed: None, last_armed: None,
@ -777,7 +747,7 @@ pub fn draw_cursor<R>(
let mut state_ref = seat_userdata.get::<CursorState>().unwrap().lock().unwrap(); let mut state_ref = seat_userdata.get::<CursorState>().unwrap().lock().unwrap();
let state = &mut *state_ref; let state = &mut *state_ref;
if state.hidden.is_some() { if state.hidden {
return; return;
} }
@ -867,175 +837,68 @@ pub fn draw_cursor<R>(
const ACTIVITY_THROTTLE: Duration = Duration::from_millis(100); const ACTIVITY_THROTTLE: Duration = Duration::from_millis(100);
/// Reveal the cursor if this event should, and (re)arm the idle-hide timer. /// Reveal the cursor and (re)arm the idle-hide timer; returns true if it was previously hidden
/// Returns true if the cursor was previously hidden and is now visible. pub fn notify_cursor_activity(state: &State, seat: &Seat<State>) -> bool {
pub fn notify_cursor_activity(state: &State, seat: &Seat<State>, kind: PointerEventKind) -> bool { let timeout = state.common.config.cosmic_conf.cursor_hide_timeout;
let cursor_state = seat.user_data().get::<CursorState>().unwrap();
let revealed = {
let mut inner = cursor_state.lock().unwrap();
inner.last_pointer_activity = Instant::now();
match inner.hidden {
Some(reason) if reason.revealed_by(kind) => {
inner.hidden = None;
true
}
// Still hidden on purpose: leave the timer alone.
Some(_) => return false,
None => false,
}
};
refresh_idle_timer(state, seat);
revealed
}
/// (Re)arm the idle-hide timer without counting as pointer activity.
///
/// The deadline is measured from the last *pointer* event, not from now, so a
/// caller that does not stamp activity — a keystroke, a config reload — cannot
/// postpone the hide by re-arming.
///
/// Armed with the shortest timeout any context could want: the input that arms
/// the timer is usually what goes on to make a window fullscreen, so the
/// context is not yet knowable here. `on_idle_timer` evaluates it on fire and
/// re-arms for the remainder if nothing applied yet.
pub fn refresh_idle_timer(state: &State, seat: &Seat<State>) {
let config = state.common.config.cosmic_conf.cursor_hide;
let loop_handle = &state.common.event_loop_handle; let loop_handle = &state.common.event_loop_handle;
let cursor_state = seat.user_data().get::<CursorState>().unwrap(); let cursor_state = seat.user_data().get::<CursorState>().unwrap();
let now = Instant::now(); let now = Instant::now();
let (old_token, since_activity) = { let (was_hidden, old_token) = {
let mut inner = cursor_state.lock().unwrap(); let mut inner = cursor_state.lock().unwrap();
if inner.hidden.is_some() { let was_hidden = inner.hidden;
return; inner.hidden = false;
}
// Coalesce bursts from high-frequency pointers. let throttled = timeout.is_some()
let throttled = inner.idle_timer.is_some() && !was_hidden
&& inner.idle_timer.is_some()
&& inner && inner
.last_armed .last_armed
.is_some_and(|t| now.duration_since(t) < ACTIVITY_THROTTLE); .is_some_and(|t| now.duration_since(t) < ACTIVITY_THROTTLE);
if throttled { if throttled {
return; return was_hidden;
} }
let since_activity = now.duration_since(inner.last_pointer_activity);
let old_token = inner.idle_timer.take();
inner.last_armed = None; inner.last_armed = None;
(inner.idle_timer.take(), since_activity) (was_hidden, old_token)
}; };
if let Some(token) = old_token { if let Some(token) = old_token {
loop_handle.remove(token); loop_handle.remove(token);
} }
let Some(delay) = config.arm_delay(since_activity) else { if let Some(secs) = timeout {
return; let timer = Timer::from_duration(Duration::from_secs(secs as u64));
}; let seat = seat.clone();
if let Ok(token) = loop_handle.insert_source(timer, move |_, _, state| {
let timer = Timer::from_duration(delay); hide_cursor(state, &seat);
let timer_seat = seat.clone(); TimeoutAction::Drop
match loop_handle.insert_source(timer, move |_, _, state| on_idle_timer(state, &timer_seat)) { }) {
Ok(token) => {
let mut inner = cursor_state.lock().unwrap(); let mut inner = cursor_state.lock().unwrap();
inner.idle_timer = Some(token); inner.idle_timer = Some(token);
inner.last_armed = Some(now); inner.last_armed = Some(now);
} }
// `idle_timer` stays `None`, so the next activity is unthrottled and retries.
Err(err) => warn!(?err, "Failed to arm the cursor idle-hide timer"),
} }
was_hidden
} }
/// Whether the seat is focusing a fullscreen surface. A fullscreen window that fn hide_cursor(state: &mut State, seat: &Seat<State>) {
/// is not focused can be stacked behind others, so its presence on the output if let Some(ptr) = seat.get_pointer()
/// says nothing about what the user is looking at. && ptr.is_grabbed()
fn fullscreen_focused(seat: &Seat<State>) -> bool { {
matches!( return;
seat.get_keyboard().and_then(|kbd| kbd.current_focus()),
Some(KeyboardFocusTarget::Fullscreen(_))
)
}
fn on_idle_timer(state: &mut State, seat: &Seat<State>) -> TimeoutAction {
let config = state.common.config.cosmic_conf.cursor_hide;
let fullscreen = fullscreen_focused(seat);
let cursor_state = seat.user_data().get::<CursorState>().unwrap();
let elapsed = {
let inner = cursor_state.lock().unwrap();
Instant::now().duration_since(inner.last_pointer_activity)
};
match config.resolve(elapsed, fullscreen) {
HideDecision::Hide => {
hide_cursor(state, seat, HideReason::Idle);
TimeoutAction::Drop
}
HideDecision::Drop => {
let mut inner = cursor_state.lock().unwrap();
inner.idle_timer = None;
inner.last_armed = None;
TimeoutAction::Drop
}
HideDecision::RearmAfter(delay) => {
cursor_state.lock().unwrap().last_armed = Some(Instant::now());
TimeoutAction::ToDuration(delay)
}
} }
}
/// Hide the cursor immediately, for a trigger that does not wait on the timer.
pub fn hide_cursor_now(state: &mut State, seat: &Seat<State>, reason: HideReason) {
let loop_handle = state.common.event_loop_handle.clone();
let token = {
let cursor_state = seat.user_data().get::<CursorState>().unwrap();
let mut inner = cursor_state.lock().unwrap();
inner.idle_timer.take()
};
if let Some(token) = token {
loop_handle.remove(token);
}
hide_cursor(state, seat, reason);
}
fn hide_cursor(state: &mut State, seat: &Seat<State>, reason: HideReason) {
let grabbed = seat.get_pointer().is_some_and(|ptr| ptr.is_grabbed());
let cursor_state = seat.user_data().get::<CursorState>().unwrap(); let cursor_state = seat.user_data().get::<CursorState>().unwrap();
{ {
let mut inner = cursor_state.lock().unwrap(); let mut inner = cursor_state.lock().unwrap();
// Every caller has already disposed of the timer source, so clear the inner.hidden = true;
// bookkeeping before the grab check rather than only on success.
inner.idle_timer = None; inner.idle_timer = None;
inner.last_armed = None; inner.last_armed = None;
// The reason only ever tightens: `Touch` waits for real movement, so a
// later trigger must not relax it back to click-or-scroll.
if grabbed || inner.hidden == Some(reason) || inner.hidden == Some(HideReason::Touch) {
return;
}
inner.hidden = Some(reason);
} }
let outputs: Vec<_> = state.common.shell.read().outputs().cloned().collect(); let outputs: Vec<_> = state.common.shell.read().outputs().cloned().collect();
for output in outputs { for output in outputs {
state.backend.schedule_render(&output); state.backend.schedule_render(&output);
} }
} }
#[cfg(test)]
mod test {
use super::{HideReason, PointerEventKind};
#[test]
fn touch_hidden_cursor_waits_for_movement() {
assert!(HideReason::Touch.revealed_by(PointerEventKind::Motion));
assert!(!HideReason::Touch.revealed_by(PointerEventKind::Other));
}
#[test]
fn idle_and_typing_hidden_cursors_are_revealed_by_any_pointer_event() {
for reason in [HideReason::Idle, HideReason::Typing] {
assert!(reason.revealed_by(PointerEventKind::Motion));
// A click or a scroll must rescue the cursor rather than forcing a
// blind click.
assert!(reason.revealed_by(PointerEventKind::Other));
}
}
}

View file

@ -286,10 +286,10 @@ impl IndicatorShader {
Uniform::new( Uniform::new(
"radius", "radius",
[ [
outer_radius[0] as f32,
outer_radius[1] as f32,
outer_radius[2] as f32,
outer_radius[3] as f32, outer_radius[3] as f32,
outer_radius[1] as f32,
outer_radius[0] as f32,
outer_radius[2] as f32,
], ],
), ),
Uniform::new("scale", scale as f32), Uniform::new("scale", scale as f32),
@ -899,7 +899,8 @@ where
let geometry = geometry.to_local(output).as_logical(); let geometry = geometry.to_local(output).as_logical();
let padded = with_states(layer.wl_surface(), |states| { let padded = with_states(layer.wl_surface(), |states| {
surface_padding(states).and_then(|padding| pad_rect(geometry, &padding)) surface_padding(states, geometry.size)
.and_then(|padding| pad_rect(geometry, &padding))
}) })
.unwrap_or(geometry); .unwrap_or(geometry);
let radii = with_states(layer.wl_surface(), |states| { let radii = with_states(layer.wl_surface(), |states| {

View file

@ -86,6 +86,12 @@ impl ShadowShader {
let offset = [0., 5.]; let offset = [0., 5.];
let color = [0., 0., 0., if dark_mode { 0.45 } else { 0.35 }]; let color = [0., 0., 0., if dark_mode { 0.45 } else { 0.35 }];
let radius = radius.map(|r| ceil(r as f64)); let radius = radius.map(|r| ceil(r as f64));
let radius = [
radius[3], // top_left
radius[1], // top_right
radius[0], // bottom_right
radius[2], // bottom_left
];
let width = softness; let width = softness;
let sigma = width / 2.; let sigma = width / 2.;

View file

@ -247,10 +247,10 @@ impl BlurElement {
Uniform::new( Uniform::new(
"corner_radius", "corner_radius",
[ [
radii[0] as f32,
radii[1] as f32,
radii[2] as f32,
radii[3] as f32, radii[3] as f32,
radii[1] as f32,
radii[0] as f32,
radii[2] as f32,
], ],
), ),
Uniform::new( Uniform::new(

View file

@ -99,10 +99,10 @@ where
Uniform::new( Uniform::new(
"corner_radius", "corner_radius",
[ [
radius[0] as f32,
radius[1] as f32,
radius[2] as f32,
radius[3] as f32, radius[3] as f32,
radius[1] as f32,
radius[0] as f32,
radius[2] as f32,
], ],
), ),
Uniform::new( Uniform::new(
@ -145,10 +145,10 @@ where
geo: Rectangle<f64, Logical>, geo: Rectangle<f64, Logical>,
radius: [u8; 4], radius: [u8; 4],
) -> [Rectangle<f64, Logical>; 4] { ) -> [Rectangle<f64, Logical>; 4] {
let top_left = radius[0] as f64; let top_left = radius[3] as f64;
let top_right = radius[1] as f64; let top_right = radius[1] as f64;
let bottom_right = radius[2] as f64; let bottom_right = radius[0] as f64;
let bottom_left = radius[3] as f64; let bottom_left = radius[2] as f64;
[ [
Rectangle::new(geo.loc, Size::from((top_left, top_left))), Rectangle::new(geo.loc, Size::from((top_left, top_left))),

View file

@ -10,15 +10,12 @@ use crate::{
}, },
}; };
use anyhow::Context; use anyhow::Context;
use cosmic_config::{ConfigGet, ConfigSet, CosmicConfigEntry}; use cosmic_config::{ConfigGet, CosmicConfigEntry};
use cosmic_settings_config::window_rules::ApplicationException; use cosmic_settings_config::window_rules::ApplicationException;
use cosmic_settings_config::{Shortcuts, shortcuts, window_rules}; use cosmic_settings_config::{Shortcuts, shortcuts, window_rules};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use smithay::utils::{Clock, Monotonic};
use smithay::wayland::xdg_activation::XdgActivationState; use smithay::wayland::xdg_activation::XdgActivationState;
use smithay::{
backend::input::InputTime,
utils::{Clock, Monotonic},
};
pub use smithay::{ pub use smithay::{
backend::input::{self as smithay_input, KeyState}, backend::input::{self as smithay_input, KeyState},
input::keyboard::{Keysym, ModifiersState, keysyms as KeySyms}, input::keyboard::{Keysym, ModifiersState, keysyms as KeySyms},
@ -49,8 +46,8 @@ mod types;
use cosmic::config::CosmicTk; use cosmic::config::CosmicTk;
pub use cosmic_comp_config::EdidProduct; pub use cosmic_comp_config::EdidProduct;
use cosmic_comp_config::{ use cosmic_comp_config::{
ActivationPolicy, AppearanceConfig, CosmicCompConfig, CursorHideConfig, DecorationPreference, ActivationPolicy, AppearanceConfig, CosmicCompConfig, KeyboardConfig, TileBehavior, XkbConfig,
KeyboardConfig, TileBehavior, XkbConfig, XwaylandDescaling, XwaylandEavesdropping, ZoomConfig, XwaylandDescaling, XwaylandEavesdropping, ZoomConfig,
input::{DeviceState as InputDeviceState, InputConfig, TouchpadOverride}, input::{DeviceState as InputDeviceState, InputConfig, TouchpadOverride},
output::comp::{ output::comp::{
OutputConfig, OutputInfo, OutputState, OutputsConfig, TransformDef, load_outputs, OutputConfig, OutputInfo, OutputState, OutputsConfig, TransformDef, load_outputs,
@ -172,7 +169,7 @@ pub enum ColorFilter {
} }
impl Config { impl Config {
pub fn load(loop_handle: &LoopHandle<'_, State>, kiosk_mode: bool) -> Config { pub fn load(loop_handle: &LoopHandle<'_, State>) -> Config {
let config = cosmic_config::Config::new("com.system76.CosmicComp", 1).unwrap(); let config = cosmic_config::Config::new("com.system76.CosmicComp", 1).unwrap();
let source = cosmic_config::calloop::ConfigWatchSource::new(&config).unwrap(); let source = cosmic_config::calloop::ConfigWatchSource::new(&config).unwrap();
loop_handle loop_handle
@ -182,7 +179,7 @@ impl Config {
.expect("Failed to add cosmic-config to the event loop"); .expect("Failed to add cosmic-config to the event loop");
let xdg = xdg::BaseDirectories::new(); let xdg = xdg::BaseDirectories::new();
let mut cosmic_comp_config = let cosmic_comp_config =
CosmicCompConfig::get_entry(&config).unwrap_or_else(|(errs, c)| { CosmicCompConfig::get_entry(&config).unwrap_or_else(|(errs, c)| {
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
for err in errs { for err in errs {
@ -192,18 +189,6 @@ impl Config {
c c
}); });
// `cursor_hide_timeout` was replaced by the grouped `cursor_hide` key.
// Seed the new key once so configs hand-edited before the rename keep
// working; the old file is left in place so a downgrade still reads it.
if config.get::<CursorHideConfig>("cursor_hide").is_err()
&& let Ok(legacy) = config.get::<Option<u32>>("cursor_hide_timeout")
{
cosmic_comp_config.cursor_hide.idle_timeout = legacy;
if let Err(err) = config.set("cursor_hide", cosmic_comp_config.cursor_hide) {
warn!(?err, "Failed to migrate cursor_hide_timeout to cursor_hide");
}
}
// Listen for updates to the toolkit config // Listen for updates to the toolkit config
if let Ok(tk_config) = cosmic_config::Config::new("com.system76.CosmicTk", 1) { if let Ok(tk_config) = cosmic_config::Config::new("com.system76.CosmicTk", 1) {
fn handle_new_toolkit_config(config: CosmicTk, state: &mut State) { fn handle_new_toolkit_config(config: CosmicTk, state: &mut State) {
@ -260,48 +245,40 @@ impl Config {
// Source key bindings from com.system76.CosmicSettings.Shortcuts // Source key bindings from com.system76.CosmicSettings.Shortcuts
let settings_context = shortcuts::context().expect("Failed to load shortcuts config"); let settings_context = shortcuts::context().expect("Failed to load shortcuts config");
let mut system_actions = Default::default(); let system_actions = shortcuts::system_actions(&settings_context);
let mut shortcuts = Default::default(); let shortcuts = shortcuts::shortcuts(&settings_context);
// Kiosk mode disables shortcuts
if !kiosk_mode {
system_actions = shortcuts::system_actions(&settings_context);
shortcuts = shortcuts::shortcuts(&settings_context);
// Listen for updates to the keybindings config. // Listen for updates to the keybindings config.
match cosmic_config::calloop::ConfigWatchSource::new(&settings_context) { match cosmic_config::calloop::ConfigWatchSource::new(&settings_context) {
Ok(source) => { Ok(source) => {
if let Err(err) = if let Err(err) = loop_handle.insert_source(source, |(config, keys), (), state| {
loop_handle.insert_source(source, |(config, keys), (), state| { for key in keys {
for key in keys { match key.as_str() {
match key.as_str() { // Reload the keyboard shortcuts config.
// Reload the keyboard shortcuts config. "custom" | "defaults" => {
"custom" | "defaults" => { state.common.config.shortcuts = shortcuts::shortcuts(&config);
state.common.config.shortcuts =
shortcuts::shortcuts(&config);
}
"system_actions" => {
state.common.config.system_actions =
shortcuts::system_actions(&config);
}
_ => (),
}
} }
})
{ "system_actions" => {
warn!( state.common.config.system_actions =
?err, shortcuts::system_actions(&config);
"Failed to watch com.system76.CosmicSettings.Shortcuts config" }
);
_ => (),
}
} }
}) {
warn!(
?err,
"Failed to watch com.system76.CosmicSettings.Shortcuts config"
);
} }
Err(err) => warn!( }
?err, Err(err) => warn!(
"failed to create config watch source for com.system76.CosmicSettings.Shortcuts" ?err,
), "failed to create config watch source for com.system76.CosmicSettings.Shortcuts"
}; ),
} };
let window_rules_context = let window_rules_context =
window_rules::context().expect("Failed to load window rules config"); window_rules::context().expect("Failed to load window rules config");
@ -561,13 +538,7 @@ impl Config {
primary.config_mut().xwayland_primary = true; primary.config_mut().xwayland_primary = true;
} }
} }
// sort by connector name for a deterministic layout independent of hotplug order for output in outputs.iter().filter(|o| o.mirroring().is_none()) {
let mut sorted_outputs = outputs
.iter()
.filter(|o| o.mirroring().is_none())
.collect::<Vec<_>>();
sorted_outputs.sort_by_key(|o| o.name());
for output in sorted_outputs {
{ {
let mut config = output.config_mut(); let mut config = output.config_mut();
config.position = (w, 0); config.position = (w, 0);
@ -799,12 +770,13 @@ pub fn change_modifier_state(
const X11_KEYCODE_OFFSET: u32 = 8; const X11_KEYCODE_OFFSET: u32 = 8;
let mut input = |key_state, scan_code| { let mut input = |key_state, scan_code| {
let time = state.common.clock.now().as_millis();
let _ = keyboard.input( let _ = keyboard.input(
state, state,
smithay_input::Keycode::new(scan_code + X11_KEYCODE_OFFSET), smithay_input::Keycode::new(scan_code + X11_KEYCODE_OFFSET),
key_state, key_state,
SERIAL_COUNTER.next_serial(), SERIAL_COUNTER.next_serial(),
InputTime::now(), time,
|_, _, _| smithay::input::keyboard::FilterResult::<()>::Forward, |_, _, _| smithay::input::keyboard::FilterResult::<()>::Forward,
); );
}; };
@ -868,9 +840,7 @@ fn config_changed(config: cosmic_config::Config, keys: Vec<String>, state: &mut
} }
if !state.common.ei_seats.is_empty() { if !state.common.ei_seats.is_empty() {
let seat = state.common.shell.read().seats.last_active().clone(); let seat = state.common.shell.read().seats.last_active().clone();
if let Some(keyboard) = seat.get_keyboard() { state.broadcast_ei_keyboard_modifiers(&seat);
state.broadcast_ei_keyboard_modifiers(&keyboard);
}
} }
state.common.config.cosmic_conf.xkb_config = value; state.common.config.cosmic_conf.xkb_config = value;
} }
@ -1003,21 +973,15 @@ fn config_changed(config: cosmic_config::Config, keys: Vec<String>, state: &mut
let new = get_config::<bool>(&config, "cursor_shake_to_find"); let new = get_config::<bool>(&config, "cursor_shake_to_find");
state.common.config.cosmic_conf.cursor_shake_to_find = new; state.common.config.cosmic_conf.cursor_shake_to_find = new;
} }
"cursor_hide" => { "cursor_hide_timeout" => {
let new = get_config::<CursorHideConfig>(&config, "cursor_hide"); let new = get_config::<Option<u32>>(&config, "cursor_hide_timeout");
if new != state.common.config.cosmic_conf.cursor_hide { if new != state.common.config.cosmic_conf.cursor_hide_timeout {
state.common.config.cosmic_conf.cursor_hide = new; state.common.config.cosmic_conf.cursor_hide_timeout = new;
// Reveal on every change: a visible cursor is the safe state,
// and it avoids stranding a hidden cursor when the trigger
// that hid it is switched off.
let seats: Vec<_> = state.common.shell.read().seats.iter().cloned().collect(); let seats: Vec<_> = state.common.shell.read().seats.iter().cloned().collect();
let mut needs_render = false; let mut needs_render = false;
for seat in seats { for seat in seats {
needs_render |= crate::backend::render::cursor::notify_cursor_activity( needs_render |=
state, crate::backend::render::cursor::notify_cursor_activity(state, &seat);
&seat,
crate::backend::render::cursor::PointerEventKind::Motion,
);
} }
if needs_render { if needs_render {
let outputs: Vec<_> = let outputs: Vec<_> =
@ -1034,13 +998,6 @@ fn config_changed(config: cosmic_config::Config, keys: Vec<String>, state: &mut
state.common.config.cosmic_conf.activation_policy = new; state.common.config.cosmic_conf.activation_policy = new;
} }
} }
"decoration_preference" => {
let new = get_config::<DecorationPreference>(&config, "decoration_preference");
if new != state.common.config.cosmic_conf.decoration_preference {
state.common.config.cosmic_conf.decoration_preference = new;
state.update_decorations();
}
}
_ => {} _ => {}
} }
} }

View file

@ -18,7 +18,6 @@ use cosmic_config::ConfigSet;
use cosmic_settings_config::shortcuts; use cosmic_settings_config::shortcuts;
use cosmic_settings_config::shortcuts::action::{Direction, FocusDirection}; use cosmic_settings_config::shortcuts::action::{Direction, FocusDirection};
use smithay::{ use smithay::{
backend::input::InputTime,
input::{Seat, pointer::MotionEvent}, input::{Seat, pointer::MotionEvent},
utils::{Point, Serial}, utils::{Point, Serial},
}; };
@ -46,7 +45,7 @@ impl State {
backend_id: &InputBackendId, backend_id: &InputBackendId,
seat: &Seat<State>, seat: &Seat<State>,
serial: Serial, serial: Serial,
time: InputTime, time: u32,
pattern: shortcuts::Binding, pattern: shortcuts::Binding,
direction: Option<Direction>, direction: Option<Direction>,
) { ) {
@ -151,7 +150,7 @@ impl State {
backend_id: &InputBackendId, backend_id: &InputBackendId,
seat: &Seat<State>, seat: &Seat<State>,
serial: Serial, serial: Serial,
time: InputTime, time: u32,
pattern: shortcuts::Binding, pattern: shortcuts::Binding,
direction: Option<Direction>, direction: Option<Direction>,
propagate: bool, propagate: bool,

View file

@ -1,10 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use crate::{ use crate::{
backend::render::{ backend::render::{ElementFilter, cursor::notify_cursor_activity},
ElementFilter,
cursor::{PointerEventKind, notify_cursor_activity},
},
config::{ config::{
Action, Config, PrivateAction, Action, Config, PrivateAction,
key_bindings::{ key_bindings::{
@ -12,17 +9,14 @@ use crate::{
cosmic_modifiers_from_smithay, cosmic_modifiers_from_smithay,
}, },
}, },
input::{ input::gestures::{GestureState, SwipeAction},
gestures::{GestureState, SwipeAction},
tablet_emu::PointerEmulationGrab,
},
shell::{ shell::{
SeatExt, Trigger, SeatExt, Trigger,
focus::{ focus::{
Stage, render_input_order, Stage, render_input_order,
target::{KeyboardFocusTarget, PointerFocusTarget}, target::{KeyboardFocusTarget, PointerFocusTarget},
}, },
grabs::{MenuGrab, MoveGrab, ReleaseMode, ResizeEdge, ResizeGrab}, grabs::{ReleaseMode, ResizeEdge},
layout::{ layout::{
floating::ResizeGrabMarker, floating::ResizeGrabMarker,
tiling::{NodeDesc, SwapWindowGrab, TilingLayout}, tiling::{NodeDesc, SwapWindowGrab, TilingLayout},
@ -48,21 +42,19 @@ use smithay::{
backend::input::{ backend::input::{
AbsolutePositionEvent, Axis, AxisRelativeDirection, AxisSource, Device, DeviceCapability, AbsolutePositionEvent, Axis, AxisRelativeDirection, AxisSource, Device, DeviceCapability,
GestureBeginEvent, GestureEndEvent, GesturePinchUpdateEvent as _, GestureBeginEvent, GestureEndEvent, GesturePinchUpdateEvent as _,
GestureSwipeUpdateEvent as _, InputBackend, InputEvent, InputTime, KeyState, GestureSwipeUpdateEvent as _, InputBackend, InputEvent, KeyState, PointerAxisEvent,
PointerAxisEvent, ProximityState, TabletToolButtonEvent, TabletToolEvent, ProximityState, TabletToolButtonEvent, TabletToolEvent, TabletToolProximityEvent,
TabletToolProximityEvent, TabletToolTipEvent, TabletToolTipState, TouchEvent, TabletToolTipEvent, TabletToolTipState, TouchEvent,
}, },
desktop::{WindowSurfaceType, utils::under_from_surface_tree}, desktop::{PopupKeyboardGrab, WindowSurfaceType, utils::under_from_surface_tree},
input::{ input::{
Seat, Seat,
keyboard::KeyboardHandle,
keyboard::{FilterResult, KeyboardSource, KeysymHandle, ModifiersState}, keyboard::{FilterResult, KeyboardSource, KeysymHandle, ModifiersState},
pointer::{ pointer::{
AxisFrame, ButtonEvent as PointerButtonEvent, Focus, GestureHoldBeginEvent, AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent,
GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent,
GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, PointerGrab, PointerHandle, PointerGrab, PointerHandle, RelativeMotionEvent,
RelativeMotionEvent,
}, },
tablet::{TabletDescriptor, TabletSeatTrait, tool}, tablet::{TabletDescriptor, TabletSeatTrait, tool},
touch::{DownEvent, MotionEvent as TouchMotionEvent, UpEvent}, touch::{DownEvent, MotionEvent as TouchMotionEvent, UpEvent},
@ -95,7 +87,6 @@ use std::{
pub mod actions; pub mod actions;
pub mod gestures; pub mod gestures;
pub mod tablet_emu;
/// Identifies the input backend instance an event came from, used to disambiguate device ids /// Identifies the input backend instance an event came from, used to disambiguate device ids
/// (which are only unique within a single backend instance, see /// (which are only unique within a single backend instance, see
@ -223,16 +214,7 @@ impl State {
) where ) where
<B as InputBackend>::Device: 'static, <B as InputBackend>::Device: 'static,
{ {
// An input device going away is not user activity, e.g. a wireless keyboard crate::wayland::handlers::output_power::set_all_surfaces_dpms_on(self);
// dropping its link when it sleeps, so it must not power displays back on.
// Device additions still wake: after a system resume the re-enumerated
// devices may be the only input seen, and the wake resets idle anyway.
if !matches!(
&event,
InputEvent::DeviceRemoved { .. } | InputEvent::Special(_)
) {
crate::wayland::handlers::output_power::set_all_surfaces_dpms_on(self);
}
use smithay::backend::input::Event; use smithay::backend::input::Event;
match event { match event {
@ -289,7 +271,7 @@ impl State {
trace!(?keycode, ?state, "key"); trace!(?keycode, ?state, "key");
let serial = SERIAL_COUNTER.next_serial(); let serial = SERIAL_COUNTER.next_serial();
let time = Event::time(&event); let time = Event::time_msec(&event);
let keyboard = seat.get_keyboard().unwrap(); let keyboard = seat.get_keyboard().unwrap();
let previous_modifiers = keyboard.modifier_state(); let previous_modifiers = keyboard.modifier_state();
if let Some((action, pattern)) = keyboard if let Some((action, pattern)) = keyboard
@ -339,31 +321,11 @@ impl State {
keyboard.modifier_state().num_lock; keyboard.modifier_state().num_lock;
} }
} }
// A bare modifier press changes the modifier state; a real
// keystroke does not. Super+drag moves windows, so hiding on
// Super-down would take the cursor away exactly as the user
// reaches for it. Super+1 still counts as typing.
let bare_modifier = previous_modifiers != keyboard.modifier_state();
if self.common.config.cosmic_conf.cursor_hide.while_typing
&& state == KeyState::Pressed
&& !bare_modifier
{
crate::backend::render::cursor::hide_cursor_now(
self,
&seat,
crate::backend::render::cursor::HideReason::Typing,
);
} else {
// Still refresh: this is how entering fullscreen by
// keyboard arms the fullscreen timeout.
crate::backend::render::cursor::refresh_idle_timer(self, &seat);
}
} }
} }
InputEvent::PointerMotion { event, .. } => { InputEvent::PointerMotion { event, .. } => {
use smithay::backend::input::PointerMotionEvent as _; use smithay::backend::input::PointerMotionEvent;
let shell = self.common.shell.write(); let shell = self.common.shell.write();
if let Some(seat) = shell if let Some(seat) = shell
@ -372,13 +334,10 @@ impl State {
.cloned() .cloned()
{ {
self.common.idle_notifier_state.notify_activity(&seat); self.common.idle_notifier_state.notify_activity(&seat);
notify_cursor_activity(self, &seat, PointerEventKind::Motion); notify_cursor_activity(self, &seat);
let current_output = seat.active_output(); let current_output = seat.active_output();
if self.common.config.cosmic_conf.cursor_shake_to_find if self.common.config.cosmic_conf.cursor_shake_to_find
&& seat
.get_pointer()
.is_some_and(|pointer| !pointer.is_grabbed())
&& let Some(cursor_state) = && let Some(cursor_state) =
seat.user_data() seat.user_data()
.get::<crate::backend::render::cursor::CursorState>() .get::<crate::backend::render::cursor::CursorState>()
@ -438,7 +397,7 @@ impl State {
&RelativeMotionEvent { &RelativeMotionEvent {
delta: event.delta(), delta: event.delta(),
delta_unaccel: event.delta_unaccel(), delta_unaccel: event.delta_unaccel(),
time: event.time(), utime: event.time(),
}, },
); );
@ -676,10 +635,10 @@ impl State {
ptr.motion( ptr.motion(
self, self,
under, under,
&PointerMotionEvent { &MotionEvent {
location: position.as_logical(), location: position.as_logical(),
serial, serial,
time: event.time(), time: event.time_msec(),
}, },
); );
ptr.frame(self); ptr.frame(self);
@ -746,7 +705,7 @@ impl State {
.cloned(); .cloned();
if let Some(seat) = maybe_seat { if let Some(seat) = maybe_seat {
self.common.idle_notifier_state.notify_activity(&seat); self.common.idle_notifier_state.notify_activity(&seat);
notify_cursor_activity(self, &seat, PointerEventKind::Motion); notify_cursor_activity(self, &seat);
let (output, position) = if matches!(&backend_id, InputBackendId::Ei(_)) { let (output, position) = if matches!(&backend_id, InputBackendId::Ei(_)) {
// EI absolute coordinates are in the compositor's *global* // EI absolute coordinates are in the compositor's *global*
// logical space: each advertised region carries its output's // logical space: each advertised region carries its output's
@ -791,33 +750,23 @@ impl State {
ptr.motion( ptr.motion(
self, self,
under, under,
&PointerMotionEvent { &MotionEvent {
location: position.as_logical(), location: position.as_logical(),
serial, serial,
time: event.time(), time: event.time_msec(),
}, },
); );
ptr.frame(self); ptr.frame(self);
let mut shell = self.common.shell.write();
// Keep the seat's active output following the pointer. Click-to- // Keep the seat's active output following the pointer. Click-to-
// focus (PointerButton) resolves its target via // focus (PointerButton) resolves its target via
// `seat.active_output()` // `seat.active_output()`
let previous_output = seat.active_output(); let previous_output = seat.active_output();
if previous_output != output { if previous_output != output {
for session in cursor_sessions_for_output(&shell, &previous_output) {
session.set_cursor_pos(None);
}
seat.set_active_output(&output); seat.set_active_output(&output);
} }
shell.update_pointer_position(position.to_local(&output), &output); let shell = self.common.shell.read();
shell.update_focal_point(
&seat,
position,
self.common.config.cosmic_conf.accessibility_zoom.view_moves,
);
update_output_image_copy_cursor_position( update_output_image_copy_cursor_position(
&shell, &shell,
&self.common.clock, &self.common.clock,
@ -828,8 +777,9 @@ impl State {
} }
} }
InputEvent::PointerButton { event, .. } => { InputEvent::PointerButton { event, .. } => {
use smithay::backend::input::{ButtonState, PointerButtonEvent as _}; use smithay::backend::input::{ButtonState, PointerButtonEvent};
//
let Some(seat) = self let Some(seat) = self
.common .common
.shell .shell
@ -841,7 +791,7 @@ impl State {
return; return;
}; };
self.common.idle_notifier_state.notify_activity(&seat); self.common.idle_notifier_state.notify_activity(&seat);
notify_cursor_activity(self, &seat, PointerEventKind::Other); notify_cursor_activity(self, &seat);
let current_focus = seat.get_keyboard().unwrap().current_focus(); let current_focus = seat.get_keyboard().unwrap().current_focus();
let shortcuts_inhibited = current_focus.as_ref().is_some_and(|f| { let shortcuts_inhibited = current_focus.as_ref().is_some_and(|f| {
@ -903,7 +853,7 @@ impl State {
&& !shortcuts_inhibited && !shortcuts_inhibited
{ {
let seat_clone = seat.clone(); let seat_clone = seat.clone();
let mouse_button = event.button(); let mouse_button = PointerButtonEvent::button(&event);
let mut supress_button = || { let mut supress_button = || {
// If the logo is held then the pointer event is // If the logo is held then the pointer event is
@ -1055,7 +1005,7 @@ impl State {
button, button,
event.state(), event.state(),
serial, serial,
event.time(), event.time_msec(),
); );
} }
@ -1063,16 +1013,16 @@ impl State {
if pass_event { if pass_event {
ptr.button( ptr.button(
self, self,
&PointerButtonEvent { &ButtonEvent {
button, button,
state: event.state(), state: event.state(),
serial, serial,
time: event.time(), time: event.time_msec(),
}, },
); );
ptr.frame(self); ptr.frame(self);
} else if event.state() == ButtonState::Released { } else if event.state() == ButtonState::Released {
ptr.unset_grab(self, serial, event.time()) ptr.unset_grab(self, serial, event.time_msec())
} }
} }
InputEvent::PointerAxis { event, .. } => { InputEvent::PointerAxis { event, .. } => {
@ -1092,7 +1042,7 @@ impl State {
.cloned(); .cloned();
if let Some(seat) = maybe_seat { if let Some(seat) = maybe_seat {
self.common.idle_notifier_state.notify_activity(&seat); self.common.idle_notifier_state.notify_activity(&seat);
notify_cursor_activity(self, &seat, PointerEventKind::Other); notify_cursor_activity(self, &seat);
if self.source_modifiers(&backend_id, &seat).logo if self.source_modifiers(&backend_id, &seat).logo
&& self && self
@ -1123,7 +1073,7 @@ impl State {
self.update_zoom(&seat, change, event.source() == AxisSource::Wheel); self.update_zoom(&seat, change, event.source() == AxisSource::Wheel);
} }
} else { } else {
let mut frame = AxisFrame::new(event.time()).source(event.source()); let mut frame = AxisFrame::new(event.time_msec()).source(event.source());
let horizontal_amount = event let horizontal_amount = event
.amount(Axis::Horizontal) .amount(Axis::Horizontal)
.or_else(|| Some(event.amount_v120(Axis::Horizontal)? * 15.0 / 120.)); .or_else(|| Some(event.amount_v120(Axis::Horizontal)? * 15.0 / 120.));
@ -1192,7 +1142,7 @@ impl State {
self, self,
&GestureSwipeBeginEvent { &GestureSwipeBeginEvent {
serial, serial,
time: event.time(), time: event.time_msec(),
fingers: event.fingers(), fingers: event.fingers(),
}, },
); );
@ -1213,7 +1163,7 @@ impl State {
if let Some(ref mut gesture_state) = self.common.gesture_state { if let Some(ref mut gesture_state) = self.common.gesture_state {
let first_update = gesture_state.update( let first_update = gesture_state.update(
event.delta(), event.delta(),
Duration::from_millis(event.time().millis() as u64), Duration::from_millis(event.time_msec() as u64),
); );
// Decide on action if first update // Decide on action if first update
if first_update { if first_update {
@ -1289,7 +1239,7 @@ impl State {
pointer.gesture_swipe_update( pointer.gesture_swipe_update(
self, self,
&GestureSwipeUpdateEvent { &GestureSwipeUpdateEvent {
time: event.time(), time: event.time_msec(),
delta: event.delta(), delta: event.delta(),
}, },
); );
@ -1338,7 +1288,7 @@ impl State {
self, self,
&GestureSwipeEndEvent { &GestureSwipeEndEvent {
serial, serial,
time: event.time(), time: event.time_msec(),
cancelled: event.cancelled(), cancelled: event.cancelled(),
}, },
); );
@ -1361,7 +1311,7 @@ impl State {
self, self,
&GesturePinchBeginEvent { &GesturePinchBeginEvent {
serial, serial,
time: event.time(), time: event.time_msec(),
fingers: event.fingers(), fingers: event.fingers(),
}, },
); );
@ -1381,7 +1331,7 @@ impl State {
pointer.gesture_pinch_update( pointer.gesture_pinch_update(
self, self,
&GesturePinchUpdateEvent { &GesturePinchUpdateEvent {
time: event.time(), time: event.time_msec(),
delta: event.delta(), delta: event.delta(),
scale: event.scale(), scale: event.scale(),
rotation: event.rotation(), rotation: event.rotation(),
@ -1405,7 +1355,7 @@ impl State {
self, self,
&GesturePinchEndEvent { &GesturePinchEndEvent {
serial, serial,
time: event.time(), time: event.time_msec(),
cancelled: event.cancelled(), cancelled: event.cancelled(),
}, },
); );
@ -1427,7 +1377,7 @@ impl State {
self, self,
&GestureHoldBeginEvent { &GestureHoldBeginEvent {
serial, serial,
time: event.time(), time: event.time_msec(),
fingers: event.fingers(), fingers: event.fingers(),
}, },
); );
@ -1449,7 +1399,7 @@ impl State {
self, self,
&GestureHoldEndEvent { &GestureHoldEndEvent {
serial, serial,
time: event.time(), time: event.time_msec(),
cancelled: event.cancelled(), cancelled: event.cancelled(),
}, },
); );
@ -1494,18 +1444,11 @@ impl State {
}; };
let under = State::surface_under(position, &output, &shell) let under = State::surface_under(position, &output, &shell)
.map(|(target, pos)| (target, pos.as_logical())); .map(|(target, pos)| (target, pos.as_logical()));
let focus_target = State::element_under(position, &output, &shell, &seat);
std::mem::drop(shell); std::mem::drop(shell);
let serial = SERIAL_COUNTER.next_serial(); let serial = SERIAL_COUNTER.next_serial();
let touch = seat.get_touch().unwrap(); let touch = seat.get_touch().unwrap();
// change the keyboard focus unless the touch is grabbed, like pointer buttons
if !touch.is_grabbed()
&& let Some(target) = focus_target.as_ref()
{
Shell::set_focus(self, Some(target), &seat, Some(serial), false);
}
touch.down( touch.down(
self, self,
under, under,
@ -1513,17 +1456,9 @@ impl State {
slot: event.slot(), slot: event.slot(),
location: position.as_logical(), location: position.as_logical(),
serial, serial,
time: event.time(), time: event.time_msec(),
}, },
); );
if self.common.config.cosmic_conf.cursor_hide.after_touch {
crate::backend::render::cursor::hide_cursor_now(
self,
&seat,
crate::backend::render::cursor::HideReason::Touch,
);
}
} }
} }
InputEvent::TouchMotion { event, .. } => { InputEvent::TouchMotion { event, .. } => {
@ -1570,7 +1505,7 @@ impl State {
&TouchMotionEvent { &TouchMotionEvent {
slot: event.slot(), slot: event.slot(),
location: position.as_logical(), location: position.as_logical(),
time: event.time(), time: event.time_msec(),
}, },
); );
} }
@ -1596,7 +1531,7 @@ impl State {
self, self,
&UpEvent { &UpEvent {
slot: event.slot(), slot: event.slot(),
time: event.time(), time: event.time_msec(),
serial, serial,
}, },
); );
@ -1639,7 +1574,7 @@ impl State {
.cloned() .cloned()
{ {
self.common.idle_notifier_state.notify_activity(&seat); self.common.idle_notifier_state.notify_activity(&seat);
notify_cursor_activity(self, &seat, PointerEventKind::Motion); notify_cursor_activity(self, &seat);
let Some(output) = let Some(output) =
mapped_output_for_device(&self.common.config, &shell, &event.device()) mapped_output_for_device(&self.common.config, &shell, &event.device())
.cloned() .cloned()
@ -1647,7 +1582,6 @@ impl State {
return; return;
}; };
let current_output = seat.active_output();
let position = let position =
transform_output_mapped_position(&output, &event, shell.zoom_state()); transform_output_mapped_position(&output, &event, shell.zoom_state());
let under = State::surface_under(position, &output, &shell) let under = State::surface_under(position, &output, &shell)
@ -1656,33 +1590,21 @@ impl State {
std::mem::drop(shell); std::mem::drop(shell);
let pointer = seat.get_pointer().unwrap(); let pointer = seat.get_pointer().unwrap();
pointer.set_location(position.as_logical()); pointer.motion(
self,
under.clone(),
&MotionEvent {
location: position.as_logical(),
serial: SERIAL_COUNTER.next_serial(),
time: self.common.clock.now().as_millis(),
},
);
let tablet_seat = seat.tablet_seat(); let tablet_seat = seat.tablet_seat();
let tool = tablet_seat.get_tool(&event.tool()); let tool = tablet_seat.get_tool(&event.tool());
if let Some(tool) = tool { if let Some(tool) = tool {
let serial = SERIAL_COUNTER.next_serial();
if !tool.is_grabbed()
&& under
.as_ref()
.is_some_and(|(target, _)| !target.supports_tool(&tool))
{
let start_data = tool::GrabStartData {
focus: under.clone(),
trigger: tool::GrabTrigger::Proximity,
location: position.as_logical(),
};
tool.set_grab(
self,
PointerEmulationGrab::new(start_data, seat.clone()),
event.time(),
serial,
Focus::Keep,
);
}
let frame = tool::AxisFrame { let frame = tool::AxisFrame {
pressure: event.pressure_has_changed().then(|| event.pressure()), pressure: event.pressure_has_changed().then(|| event.pressure()),
distance: event.distance_has_changed().then(|| event.distance()), distance: event.distance_has_changed().then(|| event.distance()),
@ -1700,39 +1622,17 @@ impl State {
tool.motion( tool.motion(
self, self,
under, under
.and_then(|(f, loc)| f.wl_surface().map(|s| (s.into_owned(), loc))),
&tool::MotionEvent { &tool::MotionEvent {
location: position.as_logical(), location: position.as_logical(),
serial, serial: SERIAL_COUNTER.next_serial(),
time: event.time(), time: event.time_msec(),
}, },
); );
tool.frame(self, event.time()); tool.frame(self, event.time_msec());
} }
let mut shell = self.common.shell.write();
shell.update_pointer_position(position.to_local(&output), &output);
shell.update_focal_point(
&seat,
position,
self.common.config.cosmic_conf.accessibility_zoom.view_moves,
);
if output != current_output {
for session in cursor_sessions_for_output(&shell, &current_output) {
session.set_cursor_pos(None);
}
seat.set_active_output(&output);
}
update_output_image_copy_cursor_position(
&shell,
&self.common.clock,
&output,
&seat,
position,
);
} }
} }
InputEvent::TabletToolProximity { event, .. } => { InputEvent::TabletToolProximity { event, .. } => {
@ -1743,7 +1643,7 @@ impl State {
.cloned() .cloned()
{ {
self.common.idle_notifier_state.notify_activity(&seat); self.common.idle_notifier_state.notify_activity(&seat);
notify_cursor_activity(self, &seat, PointerEventKind::Motion); notify_cursor_activity(self, &seat);
let Some(output) = let Some(output) =
mapped_output_for_device(&self.common.config, &shell, &event.device()) mapped_output_for_device(&self.common.config, &shell, &event.device())
.cloned() .cloned()
@ -1751,7 +1651,6 @@ impl State {
return; return;
}; };
let current_output = seat.active_output();
let position = let position =
transform_output_mapped_position(&output, &event, shell.zoom_state()); transform_output_mapped_position(&output, &event, shell.zoom_state());
let under = State::surface_under(position, &output, &shell) let under = State::surface_under(position, &output, &shell)
@ -1760,7 +1659,15 @@ impl State {
std::mem::drop(shell); std::mem::drop(shell);
let pointer = seat.get_pointer().unwrap(); let pointer = seat.get_pointer().unwrap();
pointer.set_location(position.as_logical()); pointer.motion(
self,
under.clone(),
&MotionEvent {
location: position.as_logical(),
serial: SERIAL_COUNTER.next_serial(),
time: self.common.clock.now().as_millis(),
},
);
let tablet_seat = seat.tablet_seat(); let tablet_seat = seat.tablet_seat();
@ -1773,25 +1680,6 @@ impl State {
if let Some(tablet) = tablet { if let Some(tablet) = tablet {
let serial = SERIAL_COUNTER.next_serial(); let serial = SERIAL_COUNTER.next_serial();
if !tool.is_grabbed()
&& under
.as_ref()
.is_some_and(|(target, _)| !target.supports_tool(&tool))
{
let start_data = tool::GrabStartData {
focus: under.clone(),
trigger: tool::GrabTrigger::Proximity,
location: position.as_logical(),
};
tool.set_grab(
self,
PointerEmulationGrab::new(start_data, seat.clone()),
event.time(),
serial,
Focus::Keep,
);
}
let frame = tool::AxisFrame { let frame = tool::AxisFrame {
pressure: event.pressure_has_changed().then(|| event.pressure()), pressure: event.pressure_has_changed().then(|| event.pressure()),
distance: event.distance_has_changed().then(|| event.distance()), distance: event.distance_has_changed().then(|| event.distance()),
@ -1807,6 +1695,9 @@ impl State {
match event.state() { match event.state() {
ProximityState::In => { ProximityState::In => {
let under = under.and_then(|(f, loc)| {
f.wl_surface().map(|s| (s.into_owned(), loc))
});
tool.proximity_in( tool.proximity_in(
self, self,
under, under,
@ -1814,75 +1705,25 @@ impl State {
&tool::ProximityInEvent { &tool::ProximityInEvent {
location: position.as_logical(), location: position.as_logical(),
axis: Some(frame), axis: Some(frame),
serial, serial: SERIAL_COUNTER.next_serial(),
time: event.time(), time: event.time_msec(),
}, },
); )
}
ProximityState::Out => {
tool.proximity_out(
self,
&tool::ProximityOutEvent {
serial,
time: event.time(),
},
);
if let Some(pointer) = seat.get_pointer() {
pointer.motion(
self,
None,
&PointerMotionEvent {
location: position.as_logical(),
serial,
time: event.time(),
},
);
}
} }
ProximityState::Out => tool.proximity_out(
self,
&tool::ProximityOutEvent {
serial,
time: event.time_msec(),
},
),
} }
tool.frame(self, event.time()); tool.frame(self, event.time_msec());
}
if event.state() == ProximityState::In {
let mut shell = self.common.shell.write();
shell.update_pointer_position(position.to_local(&output), &output);
shell.update_focal_point(
&seat,
position,
self.common.config.cosmic_conf.accessibility_zoom.view_moves,
);
if output != current_output {
for session in cursor_sessions_for_output(&shell, &current_output) {
session.set_cursor_pos(None);
}
seat.set_active_output(&output);
}
update_output_image_copy_cursor_position(
&shell,
&self.common.clock,
&output,
&seat,
position,
);
} }
} }
} }
InputEvent::TabletToolTip { event, .. } => { InputEvent::TabletToolTip { event, .. } => {
{
let mut shell = self.common.shell.write();
if let Some(Trigger::Tool(desc, trigger)) =
shell.overview_mode().0.active_trigger()
&& event.tool() == *desc
&& matches!(*trigger, tool::GrabTrigger::Tip)
&& event.tip_state() == TabletToolTipState::Up
{
shell.set_overview_mode(None, self.common.event_loop_handle.clone());
}
}
let maybe_seat = self let maybe_seat = self
.common .common
.shell .shell
@ -1892,22 +1733,7 @@ impl State {
.cloned(); .cloned();
if let Some(seat) = maybe_seat { if let Some(seat) = maybe_seat {
self.common.idle_notifier_state.notify_activity(&seat); self.common.idle_notifier_state.notify_activity(&seat);
notify_cursor_activity(self, &seat, PointerEventKind::Other); notify_cursor_activity(self, &seat);
let serial = SERIAL_COUNTER.next_serial();
let output = seat.active_output();
let shell = self.common.shell.write();
let position =
transform_output_mapped_position(&output, &event, shell.zoom_state());
let under = State::element_under(position, &output, &shell, &seat);
drop(shell);
if event.tip_state() == TabletToolTipState::Down
&& let Some(target) = under.as_ref()
{
Shell::set_focus(self, Some(target), &seat, Some(serial), false);
}
if let Some(tool) = seat.tablet_seat().get_tool(&event.tool()) { if let Some(tool) = seat.tablet_seat().get_tool(&event.tool()) {
let serial = SERIAL_COUNTER.next_serial(); let serial = SERIAL_COUNTER.next_serial();
match event.tip_state() { match event.tip_state() {
@ -1916,7 +1742,7 @@ impl State {
self, self,
&tool::DownEvent { &tool::DownEvent {
serial, serial,
time: event.time(), time: event.time_msec(),
}, },
); );
} }
@ -1925,13 +1751,13 @@ impl State {
self, self,
&tool::UpEvent { &tool::UpEvent {
serial, serial,
time: event.time(), time: event.time_msec(),
}, },
); );
} }
} }
tool.frame(self, event.time()); tool.frame(self, event.time_msec());
} }
} }
} }
@ -1945,7 +1771,7 @@ impl State {
.cloned(); .cloned();
if let Some(seat) = maybe_seat { if let Some(seat) = maybe_seat {
self.common.idle_notifier_state.notify_activity(&seat); self.common.idle_notifier_state.notify_activity(&seat);
notify_cursor_activity(self, &seat, PointerEventKind::Other); notify_cursor_activity(self, &seat);
if let Some(tool) = seat.tablet_seat().get_tool(&event.tool()) { if let Some(tool) = seat.tablet_seat().get_tool(&event.tool()) {
tool.button( tool.button(
self, self,
@ -1953,11 +1779,11 @@ impl State {
button: event.button(), button: event.button(),
state: event.button_state(), state: event.button_state(),
serial: SERIAL_COUNTER.next_serial(), serial: SERIAL_COUNTER.next_serial(),
time: event.time(), time: event.time_msec(),
}, },
); );
tool.frame(self, event.time()); tool.frame(self, event.time_msec());
} }
} }
} }
@ -2060,7 +1886,7 @@ impl State {
let Some(pointer) = seat.get_pointer() else { let Some(pointer) = seat.get_pointer() else {
return; return;
}; };
let time = InputTime::now(); let time = self.common.clock.now().as_millis();
for button in buttons { for button in buttons {
let serial = SERIAL_COUNTER.next_serial(); let serial = SERIAL_COUNTER.next_serial();
pointer.button( pointer.button(
@ -2078,7 +1904,13 @@ impl State {
/// Mirror the seat's current modifier state to every libei sender with a keyboard via /// Mirror the seat's current modifier state to every libei sender with a keyboard via
/// `ei_keyboard.modifiers` /// `ei_keyboard.modifiers`
pub(crate) fn broadcast_ei_keyboard_modifiers(&self, keyboard: &KeyboardHandle<State>) { pub(crate) fn broadcast_ei_keyboard_modifiers(&self, seat: &Seat<State>) {
if self.common.ei_seats.is_empty() {
return;
}
let Some(keyboard) = seat.get_keyboard() else {
return;
};
let s = keyboard.modifier_state().serialized; let s = keyboard.modifier_state().serialized;
for ei_seat in self.common.ei_seats.values() { for ei_seat in self.common.ei_seats.values() {
ei_seat.keyboard_modifiers(s.depressed, s.locked, s.latched, s.layout_effective); ei_seat.keyboard_modifiers(s.depressed, s.locked, s.latched, s.layout_effective);
@ -2116,14 +1948,14 @@ impl State {
modifiers: &ModifiersState, modifiers: &ModifiersState,
handle: KeysymHandle<'_>, handle: KeysymHandle<'_>,
serial: Serial, serial: Serial,
time: InputTime, time: u32,
keycode: Keycode, keycode: Keycode,
key_state: KeyState, key_state: KeyState,
previous_modifiers: ModifiersState, previous_modifiers: ModifiersState,
) -> FilterResult<Option<(Action, shortcuts::Binding)>> { ) -> FilterResult<Option<(Action, shortcuts::Binding)>> {
if previous_modifiers != *modifiers { if previous_modifiers != *modifiers {
seat.set_last_modifier_change(backend_id, serial); seat.set_last_modifier_change(backend_id, serial);
self.broadcast_ei_keyboard_modifiers(&seat.get_keyboard().unwrap()); self.broadcast_ei_keyboard_modifiers(seat);
} }
let current_focus = seat.get_keyboard().unwrap().current_focus(); let current_focus = seat.get_keyboard().unwrap().current_focus();
@ -2143,21 +1975,6 @@ impl State {
backend_id, seat, modifiers, handle, serial, keycode, key_state, time, backend_id, seat, modifiers, handle, serial, keycode, key_state, time,
); );
// A modifier-only binding fires on the modifier's release, but its press was already
// forwarded. Forward the release too.
if key_state == KeyState::Released
&& matches!(&result, FilterResult::Intercept(Some((_, binding))) if binding.key.is_none())
{
seat.get_keyboard().unwrap().input_forward(
self,
keycode,
key_state,
serial,
time,
previous_modifiers != *modifiers,
);
}
if (matches!(result, FilterResult::Forward) if (matches!(result, FilterResult::Forward)
&& !seat.get_keyboard().unwrap().is_grabbed() && !seat.get_keyboard().unwrap().is_grabbed()
&& !shortcuts_inhibited && !shortcuts_inhibited
@ -2191,7 +2008,7 @@ impl State {
return; return;
}; };
let serial = SERIAL_COUNTER.next_serial(); let serial = SERIAL_COUNTER.next_serial();
let time = InputTime::now(); let time = self.common.clock.now().as_millis();
let previous_modifiers = keyboard.modifier_state(); let previous_modifiers = keyboard.modifier_state();
let result = keyboard let result = keyboard
.input_from_source( .input_from_source(
@ -2340,7 +2157,7 @@ impl State {
serial: Serial, serial: Serial,
keycode: Keycode, keycode: Keycode,
key_state: KeyState, key_state: KeyState,
time: InputTime, time: u32,
) -> FilterResult<Option<(Action, shortcuts::Binding)>> { ) -> FilterResult<Option<(Action, shortcuts::Binding)>> {
// Pre-compute for layout-agnostic shortcut matching // Pre-compute for layout-agnostic shortcut matching
let raw_syms = handle.raw_syms(); let raw_syms = handle.raw_syms();
@ -2353,15 +2170,17 @@ impl State {
let keyboard = seat.get_keyboard().unwrap(); let keyboard = seat.get_keyboard().unwrap();
let pointer = seat.get_pointer().unwrap(); let pointer = seat.get_pointer().unwrap();
// Escape only cancels grabs the compositor started for its own interactions // We're only interested in filtering keyboard grabs if we initiated them.
// For keyboard: SwapWindowGrab // The easiest way to check that is to check the type of the grab.
// For pointer: MoveGrab, ResizeGrab, and MenuGrab let keyboard_grabbed = keyboard.with_grab(|_serial, grab| {
let keyboard_grabbed = grab.is::<SwapWindowGrab>() || grab.is::<PopupKeyboardGrab<State>>()
keyboard.with_grab(|_serial, grab| grab.is::<SwapWindowGrab>()) == Some(true);
let pointer_grabbed = pointer.with_grab(|_serial, grab| {
grab.is::<MoveGrab>() || grab.is::<ResizeGrab>() || grab.is::<MenuGrab>()
}) == Some(true); }) == Some(true);
let is_grabbed = keyboard_grabbed || pointer_grabbed; // A virtual-keyboard key can arrive while the seat's pointer is grabbed by that
// same on-screen keyboard's own button press (the implicit grab from clicking an OSK
// key). That pointer grab must not capture the injected key, otherwise e.g.
// pressing esc on a virtual keyboard gets swallowed here
let from_vk = matches!(backend_id, InputBackendId::VirtualKeyboard);
let is_grabbed = keyboard_grabbed || (pointer.is_grabbed() && !from_vk);
let current_focus = keyboard.current_focus(); let current_focus = keyboard.current_focus();
//this should fall back to active output since there may not be a focused output //this should fall back to active output since there may not be a focused output
@ -2503,9 +2322,7 @@ impl State {
&backend_id_clone, &backend_id_clone,
&seat_clone, &seat_clone,
serial, serial,
InputTime::from_millis( time.overflowing_add(duration as u32).0,
time.millis().overflowing_add(duration as u32).0,
),
key_pattern_clone.clone(), key_pattern_clone.clone(),
None, None,
); );
@ -2557,7 +2374,7 @@ impl State {
self.common.event_loop_handle.insert_idle(move |state| { self.common.event_loop_handle.insert_idle(move |state| {
if let Some(keyboard) = seat.get_keyboard() { if let Some(keyboard) = seat.get_keyboard() {
let serial = SERIAL_COUNTER.next_serial(); let serial = SERIAL_COUNTER.next_serial();
let time = InputTime::now(); let time = state.common.clock.now().as_millis();
keyboard.input( keyboard.input(
state, state,
key_code, key_code,
@ -3083,7 +2900,6 @@ impl State {
surface: &WlSurface, surface: &WlSurface,
pointer: &PointerHandle<Self>, pointer: &PointerHandle<Self>,
mut location: Point<f64, Logical>, mut location: Point<f64, Logical>,
constraint: Option<&PointerConstraint>,
) { ) {
let Some(client) = surface.client() else { let Some(client) = surface.client() else {
return; return;
@ -3108,13 +2924,15 @@ impl State {
return false; return false;
} }
if let Some(constraint) = constraint with_pointer_constraint(surface, pointer, |constraint| {
&& let Some(region) = constraint.region() if let Some(constraint) = constraint
{ && let Some(region) = constraint.region()
let point_in_surface = (p - surface_offset.to_f64()).to_i32_floor(); {
return region.contains(point_in_surface); let point_in_surface = (p - surface_offset.to_f64()).to_i32_floor();
} return region.contains(point_in_surface);
true }
true
})
}; };
let workspace_origin = output.geometry().loc.to_f64(); let workspace_origin = output.geometry().loc.to_f64();
@ -3138,23 +2956,23 @@ impl State {
let serial = SERIAL_COUNTER.next_serial(); let serial = SERIAL_COUNTER.next_serial();
let under = State::surface_under(point, &output, &self.common.shell.write()) let under = State::surface_under(point, &output, &self.common.shell.write())
.map(|(target, pos)| (target, pos.as_logical())); .map(|(target, pos)| (target, pos.as_logical()));
let time = InputTime::now(); let time = self.common.clock.now();
pointer.relative_motion( pointer.relative_motion(
self, self,
under.clone(), under.clone(),
&RelativeMotionEvent { &RelativeMotionEvent {
delta: (0., 0.).into(), delta: (0., 0.).into(),
delta_unaccel: (0., 0.).into(), delta_unaccel: (0., 0.).into(),
time, utime: time.as_micros(),
}, },
); );
pointer.motion( pointer.motion(
self, self,
under, under,
&PointerMotionEvent { &MotionEvent {
location: point.as_logical(), location: point.as_logical(),
serial, serial,
time, time: time.as_millis(),
}, },
); );
pointer.frame(self); pointer.frame(self);

View file

@ -1,256 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-only
//! Pointer Emulating TabletTool grab.
use crate::{shell::focus::target::PointerFocusTarget, state::State};
use smithay::{
backend::input::{ButtonState, InputTime, MouseButton},
input::{
Seat, pointer,
tablet::{
self,
tool::{
AxisFrame, ButtonEvent, DownEvent, GrabStartData, ProximityInEvent,
ProximityOutEvent, TabletToolGrab, TabletToolInnerHandle, UpEvent,
},
},
},
utils::{Logical, Point, SERIAL_COUNTER},
};
// from https://gitlab.freedesktop.org/libinput/libinput/-/blob/main/include/linux/linux/input-event-codes.h
const BTN_STYLUS: u32 = 0x14b;
const BTN_STYLUS_2: u32 = 0x14c;
const BTN_LEFT: u32 = 0x110;
const BTN_RIGHT: u32 = 0x111;
const BTN_MIDDLE: u32 = 0x112;
const BTN_FORWARD: u32 = 0x115;
const BTN_BACK: u32 = 0x116;
pub struct PointerEmulationGrab {
start_data: GrabStartData<State>,
seat: Seat<State>,
above_source: bool,
tip_down: bool,
button_down: Vec<u32>,
}
impl PointerEmulationGrab {
pub fn new(start_data: GrabStartData<State>, seat: Seat<State>) -> Self {
Self {
start_data,
seat,
above_source: true,
tip_down: false,
button_down: Vec::new(),
}
}
fn button_to_mouse(&self, button: u32) -> Option<MouseButton> {
// FIXME: This should be configurable.
if button == BTN_STYLUS {
Some(MouseButton::Right)
} else if button == BTN_STYLUS_2 {
Some(MouseButton::Middle)
} else {
None
}
}
fn pointer_button(&self, data: &mut State, button: MouseButton, state: ButtonState) {
if let Some(pointer) = self.seat.get_pointer() {
let button = match button {
MouseButton::Left => BTN_LEFT,
MouseButton::Right => BTN_RIGHT,
MouseButton::Middle => BTN_MIDDLE,
MouseButton::Back => BTN_BACK,
MouseButton::Forward => BTN_FORWARD,
_ => return,
};
pointer.button(
data,
&pointer::ButtonEvent {
serial: SERIAL_COUNTER.next_serial(),
button,
state,
time: InputTime::now(),
},
);
pointer.frame(data);
}
}
}
type Type = tablet::tool::MotionEvent;
impl TabletToolGrab<State> for PointerEmulationGrab {
fn proximity_in(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &ProximityInEvent,
) {
handle.proximity_in(data, focus.clone(), event);
if !self.above_source && !self.tip_down && self.button_down.is_empty() {
handle.unset_grab(
self,
data,
SERIAL_COUNTER.next_serial(),
InputTime::now(),
true,
);
} else if let Some(pointer) = self.seat.get_pointer() {
pointer.motion(
data,
focus,
&pointer::MotionEvent {
location: event.location,
serial: SERIAL_COUNTER.next_serial(),
time: InputTime::now(),
},
);
pointer.frame(data);
}
}
fn proximity_out(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &ProximityOutEvent,
) {
handle.proximity_out(data, event);
handle.unset_grab(self, data, event.serial, event.time, true);
}
fn down(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &DownEvent,
) {
handle.down(data, event);
self.tip_down = true;
self.pointer_button(data, MouseButton::Left, ButtonState::Pressed);
}
fn up(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &UpEvent,
) {
handle.up(data, event);
self.pointer_button(data, MouseButton::Left, ButtonState::Released);
self.tip_down = false;
if !self.above_source && !self.tip_down && self.button_down.is_empty() {
handle.unset_grab(self, data, event.serial, event.time, true);
}
}
fn motion(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &Type,
) {
self.above_source = focus.as_ref().map(|(target, _)| target)
== self.start_data.focus.as_ref().map(|(target, _)| target);
handle.motion(data, self.start_data.focus.clone(), event);
if !self.above_source && !self.tip_down && self.button_down.is_empty() {
handle.unset_grab(
self,
data,
SERIAL_COUNTER.next_serial(),
InputTime::now(),
true,
);
} else if let Some(pointer) = self.seat.get_pointer() {
pointer.motion(
data,
focus,
&pointer::MotionEvent {
location: event.location,
serial: SERIAL_COUNTER.next_serial(),
time: InputTime::now(),
},
);
pointer.frame(data);
}
}
fn button(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &ButtonEvent,
) {
handle.button(data, event);
self.button_down.retain(|b| b != &event.button);
if matches!(event.state, ButtonState::Pressed) {
self.button_down.push(event.button);
}
if let Some(button) = self.button_to_mouse(event.button) {
self.pointer_button(data, button, event.state);
}
if !self.above_source && !self.tip_down && self.button_down.is_empty() {
handle.unset_grab(
self,
data,
SERIAL_COUNTER.next_serial(),
InputTime::now(),
true,
);
}
}
fn axis(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
frame: AxisFrame,
) {
handle.axis(data, frame);
}
fn frame(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
time: InputTime,
) {
handle.frame(data, time);
}
fn unset(&mut self, data: &mut State) {
if self.tip_down {
self.pointer_button(data, MouseButton::Left, ButtonState::Released);
}
let buttons = std::mem::take(&mut self.button_down);
for button in buttons.into_iter() {
if let Some(button) = self.button_to_mouse(button) {
self.pointer_button(data, button, ButtonState::Released);
}
}
}
fn start_data(&self) -> &GrabStartData<State> {
&self.start_data
}
}

View file

@ -289,7 +289,7 @@ Project home page: https://github.com/pop-os/cosmic-comp
Options: Options:
-h, --help Show this message -h, --help Show this message
--no-xwayland Run without Xwayland --no-xwayland Run without Xwayland
-V, --version Show the version of cosmic-comp"# -v, --version Show the version of cosmic-comp"#
); );
} }

View file

@ -124,9 +124,7 @@ pub fn setup_ei(
data.update_ei_input_method(); data.update_ei_input_method();
// Notify the remaining libei clients of the now-cleared modifier state // Notify the remaining libei clients of the now-cleared modifier state
let seat = data.common.shell.read().seats.last_active().clone(); let seat = data.common.shell.read().seats.last_active().clone();
if let Some(keyboard) = seat.get_keyboard() { data.broadcast_ei_keyboard_modifiers(&seat);
data.broadcast_ei_keyboard_modifiers(&keyboard);
}
} }
EiInputEvent::Event(event) => { EiInputEvent::Event(event) => {
use smithay::backend::input::{InputEvent, KeyboardKeyEvent}; use smithay::backend::input::{InputEvent, KeyboardKeyEvent};

View file

@ -4,10 +4,7 @@ use std::str::FromStr;
use anyhow::Result; use anyhow::Result;
#[cfg(feature = "systemd")] use tracing::{debug, info, warn};
use tracing::warn;
use tracing::{debug, info};
#[cfg(feature = "systemd")]
use tracing_journald as journald; use tracing_journald as journald;
use tracing_subscriber::{EnvFilter, filter::Directive, fmt, prelude::*}; use tracing_subscriber::{EnvFilter, filter::Directive, fmt, prelude::*};
@ -32,7 +29,6 @@ pub fn init_logger() -> Result<()> {
let fmt_layer = fmt::layer().compact(); let fmt_layer = fmt::layer().compact();
#[cfg(feature = "systemd")]
match journald::layer() { match journald::layer() {
Ok(journald_layer) => tracing_subscriber::registry() Ok(journald_layer) => tracing_subscriber::registry()
.with(fmt_layer) .with(fmt_layer)
@ -47,11 +43,6 @@ pub fn init_logger() -> Result<()> {
warn!(?err, "Failed to init journald logging."); warn!(?err, "Failed to init journald logging.");
} }
}; };
#[cfg(not(feature = "systemd"))]
tracing_subscriber::registry()
.with(fmt_layer)
.with(filter)
.init();
log_panics::init(); log_panics::init();
info!("Version: {}", std::env!("CARGO_PKG_VERSION")); info!("Version: {}", std::env!("CARGO_PKG_VERSION"));

View file

@ -12,7 +12,7 @@ use id_tree::NodeId;
use smithay::{ use smithay::{
backend::{ backend::{
drm::DrmNode, drm::DrmNode,
input::{InputTime, KeyState}, input::KeyState,
renderer::{ renderer::{
element::{ element::{
Element, Kind, RenderElement, UnderlyingStorage, Element, Kind, RenderElement, UnderlyingStorage,
@ -430,10 +430,6 @@ impl CosmicMapped {
} }
} }
pub fn is_sticky(&self) -> bool {
self.active_window().is_sticky()
}
pub fn pending_size(&self) -> Option<Size<i32, Logical>> { pub fn pending_size(&self) -> Option<Size<i32, Logical>> {
match &self.element { match &self.element {
CosmicMappedInternal::Stack(s) => s.pending_size(), CosmicMappedInternal::Stack(s) => s.pending_size(),
@ -1016,7 +1012,7 @@ impl KeyboardTarget<State> for CosmicMapped {
key: KeysymHandle<'_>, key: KeysymHandle<'_>,
state: KeyState, state: KeyState,
serial: Serial, serial: Serial,
time: InputTime, time: u32,
) { ) {
match &self.element { match &self.element {
CosmicMappedInternal::Stack(s) => { CosmicMappedInternal::Stack(s) => {

View file

@ -11,7 +11,7 @@ use crate::{
shell::{ shell::{
element::{CosmicMappedKey, CosmicMappedKeyInner}, element::{CosmicMappedKey, CosmicMappedKeyInner},
focus::target::PointerFocusTarget, focus::target::PointerFocusTarget,
grabs::{GrabType, ReleaseMode, ResizeEdge}, grabs::{ReleaseMode, ResizeEdge},
layout::tiling::NodeDesc, layout::tiling::NodeDesc,
}, },
state::State, state::State,
@ -38,7 +38,7 @@ use shortcuts::action::{Direction, FocusDirection};
use smithay::{ use smithay::{
backend::{ backend::{
drm::DrmNode, drm::DrmNode,
input::{InputTime, KeyState, TabletToolDescriptor}, input::KeyState,
renderer::{ renderer::{
ImportAll, ImportMem, Renderer, ImportAll, ImportMem, Renderer,
element::{Element, Id as RendererId, Kind, RenderElement, UnderlyingStorage}, element::{Element, Id as RendererId, Kind, RenderElement, UnderlyingStorage},
@ -52,23 +52,14 @@ use smithay::{
Seat, Seat,
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
pointer::{ pointer::{
AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorImageStatus, AxisFrame, ButtonEvent, CursorImageStatus, GestureHoldBeginEvent, GestureHoldEndEvent,
GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent,
PointerTarget, RelativeMotionEvent, PointerTarget, RelativeMotionEvent,
}, },
tablet::{
Tablet, TabletSeatTrait,
tool::{
AxisFrame as ToolAxisFrame, ButtonEvent as ToolButtonEvent,
DownEvent as ToolDownEvent, MotionEvent as ToolMotionEvent, TabletToolTarget,
UpEvent as ToolUpEvent,
},
},
touch::{ touch::{
DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent,
OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, TouchTarget, UpEvent,
}, },
}, },
output::Output, output::Output,
@ -121,7 +112,6 @@ pub struct CosmicStackInternal {
previous_keyboard: AtomicUsize, previous_keyboard: AtomicUsize,
pointer_entered: AtomicU8, pointer_entered: AtomicU8,
touch_serial: AtomicU32, touch_serial: AtomicU32,
tablet_serial: AtomicU32,
reenter: AtomicBool, reenter: AtomicBool,
potential_drag: Mutex<Option<usize>>, potential_drag: Mutex<Option<usize>>,
override_alive: AtomicBool, override_alive: AtomicBool,
@ -181,7 +171,6 @@ impl CosmicStack {
previous_keyboard: AtomicUsize::new(0), previous_keyboard: AtomicUsize::new(0),
pointer_entered: AtomicU8::new(0), pointer_entered: AtomicU8::new(0),
touch_serial: AtomicU32::new(0), touch_serial: AtomicU32::new(0),
tablet_serial: AtomicU32::new(0),
reenter: AtomicBool::new(false), reenter: AtomicBool::new(false),
potential_drag: Mutex::new(None), potential_drag: Mutex::new(None),
override_alive: AtomicBool::new(true), override_alive: AtomicBool::new(true),
@ -842,7 +831,7 @@ impl CosmicStack {
))); )));
}; };
let radii = radii.map(|[_, _, c, d]| [0, 0, c, d]); let radii = radii.map(|[a, _, c, _]| [a, 0, c, 0]);
windows[active].push_render_elements( windows[active].push_render_elements(
renderer, renderer,
window_loc, window_loc,
@ -920,19 +909,12 @@ impl CosmicStack {
false, false,
); );
if let Some((grab, focus)) = res { if let Some((grab, focus)) = res {
match grab.grab_type() { if grab.is_touch_grab() {
GrabType::Touch => { seat.get_touch().unwrap().set_grab(state, grab, serial);
seat.get_touch().unwrap().set_grab(state, grab, serial) } else {
} seat.get_pointer()
GrabType::Pointer => seat
.get_pointer()
.unwrap() .unwrap()
.set_grab(state, grab, serial, focus), .set_grab(state, grab, serial, focus);
GrabType::TabletTool => seat
.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus),
} }
} }
}); });
@ -1015,17 +997,17 @@ impl CosmicStack {
.corner_radius(geometry_size) .corner_radius(geometry_size)
.unwrap_or([default_radius; 4]); .unwrap_or([default_radius; 4]);
corners[0] = 0;
corners[1] = 0; corners[1] = 0;
corners[3] = 0;
corners corners
} else { } else {
let mut corners = active_window.corner_radius(geometry_size).unwrap_or(radii); let mut corners = active_window.corner_radius(geometry_size).unwrap_or(radii);
corners[0] = radii[0]; corners[0] = radii[0].max(corners[0]);
corners[1] = radii[1]; corners[1] = radii[1];
corners[2] = radii[2].max(corners[2]); corners[2] = radii[2].max(corners[2]);
corners[3] = radii[3].max(corners[3]); corners[3] = radii[3];
corners corners
} }
@ -1107,19 +1089,12 @@ impl Program for CosmicStackInternal {
false, false,
); );
if let Some((grab, focus)) = res { if let Some((grab, focus)) = res {
match grab.grab_type() { if grab.is_touch_grab() {
GrabType::Touch => { seat.get_touch().unwrap().set_grab(state, grab, serial);
seat.get_touch().unwrap().set_grab(state, grab, serial) } else {
} seat.get_pointer()
GrabType::Pointer => seat
.get_pointer()
.unwrap() .unwrap()
.set_grab(state, grab, serial, focus), .set_grab(state, grab, serial, focus);
GrabType::TabletTool => seat
.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus),
} }
} }
}); });
@ -1572,7 +1547,7 @@ impl KeyboardTarget<State> for CosmicStack {
key: KeysymHandle<'_>, key: KeysymHandle<'_>,
state: KeyState, state: KeyState,
serial: Serial, serial: Serial,
time: InputTime, time: u32,
) { ) {
let active = self.keyboard_leave_if_previous(seat, data, serial); let active = self.keyboard_leave_if_previous(seat, data, serial);
self.0.with_program(|p| { self.0.with_program(|p| {
@ -1612,7 +1587,7 @@ impl KeyboardTarget<State> for CosmicStack {
} }
impl PointerTarget<State> for CosmicStack { impl PointerTarget<State> for CosmicStack {
fn enter(&self, seat: &Seat<State>, data: &mut State, event: &PointerMotionEvent) { fn enter(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) {
let mut event = event.clone(); let mut event = event.clone();
self.0.with_program(|p| { self.0.with_program(|p| {
let active_window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; let active_window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)];
@ -1640,7 +1615,7 @@ impl PointerTarget<State> for CosmicStack {
PointerTarget::enter(&self.0, seat, data, &event) PointerTarget::enter(&self.0, seat, data, &event)
} }
fn motion(&self, seat: &Seat<State>, data: &mut State, event: &PointerMotionEvent) { fn motion(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) {
let mut event = event.clone(); let mut event = event.clone();
self.0.with_program(|p| { self.0.with_program(|p| {
let active = p.active.load(Ordering::SeqCst); let active = p.active.load(Ordering::SeqCst);
@ -1683,7 +1658,7 @@ impl PointerTarget<State> for CosmicStack {
) { ) {
} }
fn button(&self, seat: &Seat<State>, data: &mut State, event: &PointerButtonEvent) { fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) {
match self.0.with_program(|p| p.current_focus()) { match self.0.with_program(|p| p.current_focus()) {
Some(Focus::Header) => PointerTarget::button(&self.0, seat, data, event), Some(Focus::Header) => PointerTarget::button(&self.0, seat, data, event),
Some(x) => { Some(x) => {
@ -1714,12 +1689,14 @@ impl PointerTarget<State> for CosmicStack {
state.common.config.cosmic_conf.edge_snap_threshold, state.common.config.cosmic_conf.edge_snap_threshold,
false, false,
); );
if let Some((grab, focus)) = res if let Some((grab, focus)) = res {
&& let GrabType::Pointer = grab.grab_type() if grab.is_touch_grab() {
{ seat.get_touch().unwrap().set_grab(state, grab, serial);
seat.get_pointer() } else {
.unwrap() seat.get_pointer()
.set_grab(state, grab, serial, focus); .unwrap()
.set_grab(state, grab, serial, focus);
}
} }
}); });
} }
@ -1727,7 +1704,7 @@ impl PointerTarget<State> for CosmicStack {
} }
} }
fn axis(&self, seat: &Seat<State>, data: &mut State, frame: PointerAxisFrame) { fn axis(&self, seat: &Seat<State>, data: &mut State, frame: AxisFrame) {
if let Some(Focus::Header) = self.0.with_program(|p| p.current_focus()) { if let Some(Focus::Header) = self.0.with_program(|p| p.current_focus()) {
PointerTarget::axis(&self.0, seat, data, frame) PointerTarget::axis(&self.0, seat, data, frame)
} }
@ -1739,7 +1716,7 @@ impl PointerTarget<State> for CosmicStack {
} }
} }
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: InputTime) { fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
self.0.with_program(|p| { self.0.with_program(|p| {
let mut cursor_state = seat let mut cursor_state = seat
.user_data() .user_data()
@ -1775,12 +1752,14 @@ impl PointerTarget<State> for CosmicStack {
&state.common.event_loop_handle, &state.common.event_loop_handle,
false, false,
); );
if let Some((grab, focus)) = res if let Some((grab, focus)) = res {
&& let GrabType::Pointer = grab.grab_type() if grab.is_touch_grab() {
{ seat.get_touch().unwrap().set_grab(state, grab, serial);
seat.get_pointer() } else {
.unwrap() seat.get_pointer()
.set_grab(state, grab, serial, focus); .unwrap()
.set_grab(state, grab, serial, focus);
}
} }
}); });
} }
@ -1853,7 +1832,7 @@ impl PointerTarget<State> for CosmicStack {
} }
impl TouchTarget<State> for CosmicStack { impl TouchTarget<State> for CosmicStack {
fn down(&self, seat: &Seat<State>, data: &mut State, event: &TouchDownEvent) { fn down(&self, seat: &Seat<State>, data: &mut State, event: &DownEvent) {
let mut event = event.clone(); let mut event = event.clone();
let active_window_geo = self.0.with_program(|p| { let active_window_geo = self.0.with_program(|p| {
p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].geometry() p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].geometry()
@ -1864,7 +1843,7 @@ impl TouchTarget<State> for CosmicStack {
TouchTarget::down(&self.0, seat, data, &event) TouchTarget::down(&self.0, seat, data, &event)
} }
fn up(&self, seat: &Seat<State>, data: &mut State, event: &TouchUpEvent) { fn up(&self, seat: &Seat<State>, data: &mut State, event: &UpEvent) {
TouchTarget::up(&self.0, seat, data, event) TouchTarget::up(&self.0, seat, data, event)
} }
@ -1912,185 +1891,6 @@ impl TouchTarget<State> for CosmicStack {
} }
} }
impl TabletToolTarget<State> for CosmicStack {
fn proximity_in(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
tablet: &Tablet,
serial: Serial,
) {
TabletToolTarget::proximity_in(&self.0, seat, data, tool_descriptor, tablet, serial)
}
fn proximity_out(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
) {
self.0.with_program(|p| {
let mut cursor_state = seat
.user_data()
.get::<CursorState>()
.unwrap()
.lock()
.unwrap();
cursor_state.unset_shape();
let _previous = p.swap_focus(None);
});
TabletToolTarget::proximity_out(&self.0, seat, data, tool_descriptor);
}
fn down(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolDownEvent,
) {
self.0.with_program(|p| {
p.tablet_serial
.store(event.serial.into(), Ordering::Release)
});
match self.0.with_program(|p| p.current_focus()) {
Some(Focus::Header) => {
TabletToolTarget::down(&self.0, seat, data, tool_descriptor, event)
}
Some(x) => {
let serial = self
.0
.with_program(|p| p.tablet_serial.load(Ordering::Acquire))
.into();
let seat = seat.clone();
let Some(surface) = self.0.with_program(|p| {
let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)];
window.wl_surface().map(Cow::into_owned)
}) else {
return;
};
self.0.loop_handle().insert_idle(move |state| {
let res = state.common.shell.write().resize_request(
&surface,
&seat,
serial,
match x {
Focus::ResizeTop => ResizeEdge::TOP,
Focus::ResizeTopLeft => ResizeEdge::TOP_LEFT,
Focus::ResizeTopRight => ResizeEdge::TOP_RIGHT,
Focus::ResizeBottom => ResizeEdge::BOTTOM,
Focus::ResizeBottomLeft => ResizeEdge::BOTTOM_LEFT,
Focus::ResizeBottomRight => ResizeEdge::BOTTOM_RIGHT,
Focus::ResizeLeft => ResizeEdge::LEFT,
Focus::ResizeRight => ResizeEdge::RIGHT,
Focus::Header => unreachable!(),
},
state.common.config.cosmic_conf.edge_snap_threshold,
false,
);
if let Some((grab, focus)) = res
&& let GrabType::TabletTool = grab.grab_type()
{
seat.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus);
}
});
}
None => {}
}
}
fn up(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolUpEvent,
) {
TabletToolTarget::up(&self.0, seat, data, tool_descriptor, event)
}
fn motion(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolMotionEvent,
) {
let mut event = event.clone();
self.0.with_program(|p| {
let active = p.active.load(Ordering::SeqCst);
let active_window = &p.windows.lock().unwrap()[active];
let Some(next) = Focus::under(active_window, TAB_HEIGHT, event.location) else {
return;
};
let _previous = p.swap_focus(Some(next));
let mut cursor_state = seat
.user_data()
.get::<CursorState>()
.unwrap()
.lock()
.unwrap();
cursor_state.set_shape(next.cursor_shape());
seat.set_cursor_image_status(CursorImageStatus::default_named());
});
let active_window_geo = self.0.with_program(|p| {
p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].geometry()
});
event.location -= active_window_geo.loc.to_f64();
TabletToolTarget::motion(&self.0, seat, data, tool_descriptor, &event);
if event.location.y < 0.0
|| event.location.y > TAB_HEIGHT as f64
|| event.location.x < 64.0
|| event.location.x > (active_window_geo.size.w as f64 - 64.0)
{
self.start_drag(
data,
seat,
self.0
.with_program(|p| p.tablet_serial.load(Ordering::Acquire))
.into(),
);
}
}
fn axis(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
frame: ToolAxisFrame,
) {
TabletToolTarget::axis(&self.0, seat, data, tool_descriptor, frame)
}
fn button(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolButtonEvent,
) {
TabletToolTarget::button(&self.0, seat, data, tool_descriptor, event)
}
fn frame(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
time: InputTime,
) {
TabletToolTarget::frame(&self.0, seat, data, tool_descriptor, time)
}
}
pub enum CosmicStackRenderElement<R: Renderer + ImportAll + ImportMem> { pub enum CosmicStackRenderElement<R: Renderer + ImportAll + ImportMem> {
Header(IcedRenderElement<R>), Header(IcedRenderElement<R>),
Shadow(PixelShaderElement), Shadow(PixelShaderElement),

View file

@ -8,7 +8,6 @@ use cosmic::{
layout::{Layout, Limits, Node}, layout::{Layout, Limits, Node},
mouse, overlay, renderer, mouse, overlay, renderer,
text::{Ellipsize, EllipsizeHeightLimit, Shaping, Wrapping}, text::{Ellipsize, EllipsizeHeightLimit, Shaping, Wrapping},
touch,
widget::{Id, Widget, operation::Operation, tree::Tree}, widget::{Id, Widget, operation::Operation, tree::Tree},
}, },
widget::{self, container::draw_background, rule::FillMode, scrollable::AbsoluteOffset}, widget::{self, container::draw_background, rule::FillMode, scrollable::AbsoluteOffset},
@ -371,7 +370,6 @@ where
if matches!( if matches!(
event, event,
event::Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) event::Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
| event::Event::Touch(touch::Event::FingerPressed { .. })
) && let Some(message) = self.press_message.clone() ) && let Some(message) = self.press_message.clone()
{ {
shell.publish(message); shell.publish(message);
@ -390,7 +388,6 @@ where
if matches!( if matches!(
event, event,
event::Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) event::Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left))
| event::Event::Touch(touch::Event::FingerLifted { .. })
) { ) {
shell.publish(Message::activate(self.idx)); shell.publish(Message::activate(self.idx));
shell.capture_event(); shell.capture_event();

View file

@ -31,7 +31,7 @@ use keyframe::{
functions::{EaseInOutCubic, EaseOutCubic}, functions::{EaseInOutCubic, EaseOutCubic},
}; };
use std::{ use std::{
collections::{HashMap, VecDeque}, collections::{HashMap, HashSet, VecDeque},
time::{Duration, Instant}, time::{Duration, Instant},
}; };
@ -757,10 +757,12 @@ where
state.last_state = Some(current_state.clone()); state.last_state = Some(current_state.clone());
} }
let last_state = state.last_state.as_mut().unwrap(); let last_state = state.last_state.as_mut().unwrap();
let unknown_keys = current_state.len() != last_state.len() let unknown_keys = current_state
|| current_state .keys()
.keys() .collect::<HashSet<_>>()
.any(|key| !last_state.contains_key(key)); .symmetric_difference(&last_state.keys().collect::<HashSet<_>>())
.next()
.is_some();
enum Difference { enum Difference {
NewOrRemoved, NewOrRemoved,

View file

@ -21,7 +21,6 @@ use std::{
use smithay::{ use smithay::{
backend::{ backend::{
drm::DrmNode, drm::DrmNode,
input::InputTime,
renderer::{ renderer::{
ImportAll, Renderer, buffer_has_alpha, ImportAll, Renderer, buffer_has_alpha,
element::{Kind, RenderElementStates, surface::KindEvaluation}, element::{Kind, RenderElementStates, surface::KindEvaluation},
@ -1085,7 +1084,7 @@ impl KeyboardTarget<State> for CosmicSurface {
key: KeysymHandle<'_>, key: KeysymHandle<'_>,
state: smithay::backend::input::KeyState, state: smithay::backend::input::KeyState,
serial: smithay::utils::Serial, serial: smithay::utils::Serial,
time: InputTime, time: u32,
) { ) {
match self.0.underlying_surface() { match self.0.underlying_surface() {
WindowSurface::Wayland(toplevel) => { WindowSurface::Wayland(toplevel) => {

View file

@ -7,7 +7,7 @@ use crate::{
shell::{ shell::{
element::{CosmicMappedKey, CosmicMappedKeyInner}, element::{CosmicMappedKey, CosmicMappedKeyInner},
focus::target::PointerFocusTarget, focus::target::PointerFocusTarget,
grabs::{GrabType, ReleaseMode, ResizeEdge}, grabs::{ReleaseMode, ResizeEdge},
}, },
state::State, state::State,
utils::{ utils::{
@ -21,7 +21,7 @@ use cosmic_comp_config::AppearanceConfig;
use smithay::{ use smithay::{
backend::{ backend::{
drm::DrmNode, drm::DrmNode,
input::{InputTime, KeyState, TabletToolDescriptor}, input::KeyState,
renderer::{ renderer::{
ImportAll, ImportMem, Renderer, ImportAll, ImportMem, Renderer,
element::{Element, Id as RendererId, Kind, RenderElement, UnderlyingStorage}, element::{Element, Id as RendererId, Kind, RenderElement, UnderlyingStorage},
@ -35,23 +35,14 @@ use smithay::{
Seat, Seat,
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
pointer::{ pointer::{
AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorIcon, AxisFrame, ButtonEvent, CursorIcon, CursorImageStatus, GestureHoldBeginEvent,
CursorImageStatus, GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchEndEvent,
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, GestureSwipeUpdateEvent, MotionEvent, PointerTarget, RelativeMotionEvent,
PointerTarget, RelativeMotionEvent,
},
tablet::{
Tablet, TabletSeatTrait,
tool::{
AxisFrame as ToolAxisFrame, ButtonEvent as ToolButtonEvent,
DownEvent as ToolDownEvent, MotionEvent as ToolMotionEvent, TabletToolTarget,
UpEvent as ToolUpEvent,
},
}, },
touch::{ touch::{
DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent,
OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, TouchTarget, UpEvent,
}, },
}, },
output::Output, output::Output,
@ -438,12 +429,12 @@ impl CosmicWindow {
.map(|x| (x * scale as f32).round() as u8); .map(|x| (x * scale as f32).round() as u8);
if has_ssd && !clip { if has_ssd && !clip {
// bottom corners // bottom corners
radii[0] = 0;
radii[2] = 0; radii[2] = 0;
radii[3] = 0;
if is_tiled { if is_tiled {
// top corners // top corners
radii[0] = 0;
radii[1] = 0; radii[1] = 0;
radii[3] = 0;
} }
} }
@ -510,12 +501,12 @@ impl CosmicWindow {
&& !is_maximized; && !is_maximized;
if has_ssd && !clip { if has_ssd && !clip {
// bottom corners // bottom corners
radii[0] = 0;
radii[2] = 0; radii[2] = 0;
radii[3] = 0;
if is_tiled { if is_tiled {
// top corners // top corners
radii[0] = 0;
radii[1] = 0; radii[1] = 0;
radii[3] = 0;
} }
} }
@ -560,8 +551,8 @@ impl CosmicWindow {
self.0.with_program(|p| { self.0.with_program(|p| {
let mut radii = radii; let mut radii = radii;
if has_ssd { if has_ssd {
radii[0] = 0;
radii[1] = 0; radii[1] = 0;
radii[3] = 0;
} }
let theme = p.theme.lock().unwrap(); let theme = p.theme.lock().unwrap();
let frosted = if theme.cosmic().frosted_windows { let frosted = if theme.cosmic().frosted_windows {
@ -585,8 +576,8 @@ impl CosmicWindow {
}); });
if has_ssd { if has_ssd {
radii[0] = 0;
radii[2] = 0; radii[2] = 0;
radii[3] = 0;
let ssd_loc = location let ssd_loc = location
+ self + self
.0 .0
@ -691,26 +682,26 @@ impl CosmicWindow {
(has_ssd, true) => { (has_ssd, true) => {
let mut corners = p.window.corner_radius(geometry_size).unwrap_or(radii); let mut corners = p.window.corner_radius(geometry_size).unwrap_or(radii);
corners[0] = if has_ssd { corners[0] = radii[0].max(corners[0]);
radii[0]
} else {
radii[0].max(corners[0])
};
corners[1] = if has_ssd { corners[1] = if has_ssd {
radii[1] radii[1]
} else { } else {
radii[1].max(corners[1]) radii[1].max(corners[1])
}; };
corners[2] = radii[2].max(corners[2]); corners[2] = radii[2].max(corners[2]);
corners[3] = radii[3].max(corners[3]); corners[3] = if has_ssd {
radii[3]
} else {
radii[3].max(corners[3])
};
corners corners
} }
(true, false) => p (true, false) => p
.window .window
.corner_radius(geometry_size) .corner_radius(geometry_size)
.map(|[_, _, c, d]| [radii[0], radii[1], c, d]) .map(|[a, _, c, _]| [a, radii[1], c, radii[3]])
.unwrap_or([radii[0], radii[1], default_radius, default_radius]), .unwrap_or([default_radius, radii[1], default_radius, radii[3]]),
(false, false) => p (false, false) => p
.window .window
.corner_radius(geometry_size) .corner_radius(geometry_size)
@ -755,19 +746,12 @@ impl Program for CosmicWindowInternal {
false, false,
); );
if let Some((grab, focus)) = res { if let Some((grab, focus)) = res {
match grab.grab_type() { if grab.is_touch_grab() {
GrabType::Touch => { seat.get_touch().unwrap().set_grab(state, grab, serial);
seat.get_touch().unwrap().set_grab(state, grab, serial) } else {
} seat.get_pointer()
GrabType::Pointer => seat
.get_pointer()
.unwrap() .unwrap()
.set_grab(state, grab, serial, focus), .set_grab(state, grab, serial, focus);
GrabType::TabletTool => seat
.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus),
} }
} }
}); });
@ -997,7 +981,7 @@ impl KeyboardTarget<State> for CosmicWindow {
key: KeysymHandle<'_>, key: KeysymHandle<'_>,
state: KeyState, state: KeyState,
serial: Serial, serial: Serial,
time: InputTime, time: u32,
) { ) {
self.0 self.0
.with_program(|p| KeyboardTarget::key(&p.window, seat, data, key, state, serial, time)) .with_program(|p| KeyboardTarget::key(&p.window, seat, data, key, state, serial, time))
@ -1015,7 +999,7 @@ impl KeyboardTarget<State> for CosmicWindow {
} }
impl PointerTarget<State> for CosmicWindow { impl PointerTarget<State> for CosmicWindow {
fn enter(&self, seat: &Seat<State>, data: &mut State, event: &PointerMotionEvent) { fn enter(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) {
let mut event = event.clone(); let mut event = event.clone();
self.0.with_program(|p| { self.0.with_program(|p| {
let has_ssd = p.has_ssd(false); let has_ssd = p.has_ssd(false);
@ -1028,7 +1012,8 @@ impl PointerTarget<State> for CosmicWindow {
return; return;
}; };
let _ = p.swap_focus(Some(next)); let old_focus = p.swap_focus(Some(next));
assert_eq!(old_focus, None);
let cursor_state = seat.user_data().get::<CursorState>().unwrap(); let cursor_state = seat.user_data().get::<CursorState>().unwrap();
cursor_state.lock().unwrap().set_shape(next.cursor_shape()); cursor_state.lock().unwrap().set_shape(next.cursor_shape());
@ -1040,7 +1025,7 @@ impl PointerTarget<State> for CosmicWindow {
PointerTarget::enter(&self.0, seat, data, &event) PointerTarget::enter(&self.0, seat, data, &event)
} }
fn motion(&self, seat: &Seat<State>, data: &mut State, event: &PointerMotionEvent) { fn motion(&self, seat: &Seat<State>, data: &mut State, event: &MotionEvent) {
let mut event = event.clone(); let mut event = event.clone();
self.0.with_program(|p| { self.0.with_program(|p| {
let has_ssd = p.has_ssd(false); let has_ssd = p.has_ssd(false);
@ -1072,7 +1057,7 @@ impl PointerTarget<State> for CosmicWindow {
) { ) {
} }
fn button(&self, seat: &Seat<State>, data: &mut State, event: &PointerButtonEvent) { fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) {
match self.0.with_program(|p| p.current_focus()) { match self.0.with_program(|p| p.current_focus()) {
Some(Focus::Header) => PointerTarget::button(&self.0, seat, data, event), Some(Focus::Header) => PointerTarget::button(&self.0, seat, data, event),
Some(x) => { Some(x) => {
@ -1108,12 +1093,14 @@ impl PointerTarget<State> for CosmicWindow {
false, false,
); );
if let Some((grab, focus)) = res if let Some((grab, focus)) = res {
&& let GrabType::Pointer = grab.grab_type() if grab.is_touch_grab() {
{ seat.get_touch().unwrap().set_grab(state, grab, serial);
seat.get_pointer() } else {
.unwrap() seat.get_pointer()
.set_grab(state, grab, serial, focus) .unwrap()
.set_grab(state, grab, serial, focus);
}
} }
}); });
} }
@ -1121,7 +1108,7 @@ impl PointerTarget<State> for CosmicWindow {
} }
} }
fn axis(&self, seat: &Seat<State>, data: &mut State, frame: PointerAxisFrame) { fn axis(&self, seat: &Seat<State>, data: &mut State, frame: AxisFrame) {
if let Some(Focus::Header) = self.0.with_program(|p| p.current_focus()) { if let Some(Focus::Header) = self.0.with_program(|p| p.current_focus()) {
PointerTarget::axis(&self.0, seat, data, frame) PointerTarget::axis(&self.0, seat, data, frame)
} }
@ -1133,7 +1120,7 @@ impl PointerTarget<State> for CosmicWindow {
} }
} }
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: InputTime) { fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
self.0.with_program(|p| { self.0.with_program(|p| {
let cursor_state = seat.user_data().get::<CursorState>().unwrap(); let cursor_state = seat.user_data().get::<CursorState>().unwrap();
cursor_state.lock().unwrap().unset_shape(); cursor_state.lock().unwrap().unset_shape();
@ -1208,7 +1195,7 @@ impl PointerTarget<State> for CosmicWindow {
} }
impl TouchTarget<State> for CosmicWindow { impl TouchTarget<State> for CosmicWindow {
fn down(&self, seat: &Seat<State>, data: &mut State, event: &TouchDownEvent) { fn down(&self, seat: &Seat<State>, data: &mut State, event: &DownEvent) {
let mut event = event.clone(); let mut event = event.clone();
self.0.with_program(|p| { self.0.with_program(|p| {
event.location -= p.window.geometry().loc.to_f64(); event.location -= p.window.geometry().loc.to_f64();
@ -1216,7 +1203,7 @@ impl TouchTarget<State> for CosmicWindow {
TouchTarget::down(&self.0, seat, data, &event) TouchTarget::down(&self.0, seat, data, &event)
} }
fn up(&self, seat: &Seat<State>, data: &mut State, event: &TouchUpEvent) { fn up(&self, seat: &Seat<State>, data: &mut State, event: &UpEvent) {
TouchTarget::up(&self.0, seat, data, event) TouchTarget::up(&self.0, seat, data, event)
} }
@ -1247,155 +1234,6 @@ impl TouchTarget<State> for CosmicWindow {
} }
} }
impl TabletToolTarget<State> for CosmicWindow {
fn proximity_in(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
tablet: &Tablet,
serial: Serial,
) {
TabletToolTarget::proximity_in(&self.0, seat, data, tool_descriptor, tablet, serial)
}
fn proximity_out(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
) {
self.0.with_program(|p| {
let cursor_state = seat.user_data().get::<CursorState>().unwrap();
cursor_state.lock().unwrap().unset_shape();
let _previous = p.swap_focus(None);
});
TabletToolTarget::proximity_out(&self.0, seat, data, tool_descriptor)
}
fn down(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolDownEvent,
) {
match self.0.with_program(|p| p.current_focus()) {
Some(Focus::Header) => {
TabletToolTarget::down(&self.0, seat, data, tool_descriptor, event)
}
Some(x) => {
let serial = event.serial;
let seat = seat.clone();
let Some(surface) = self.wl_surface().map(Cow::into_owned) else {
return;
};
self.0.loop_handle().insert_idle(move |state| {
let res = state.common.shell.write().resize_request(
&surface,
&seat,
serial,
match x {
Focus::ResizeTop => ResizeEdge::TOP,
Focus::ResizeTopLeft => ResizeEdge::TOP_LEFT,
Focus::ResizeTopRight => ResizeEdge::TOP_RIGHT,
Focus::ResizeBottom => ResizeEdge::BOTTOM,
Focus::ResizeBottomLeft => ResizeEdge::BOTTOM_LEFT,
Focus::ResizeBottomRight => ResizeEdge::BOTTOM_RIGHT,
Focus::ResizeLeft => ResizeEdge::LEFT,
Focus::ResizeRight => ResizeEdge::RIGHT,
Focus::Header => unreachable!(),
},
state.common.config.cosmic_conf.edge_snap_threshold,
false,
);
if let Some((grab, focus)) = res
&& let GrabType::TabletTool = grab.grab_type()
{
seat.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus)
}
});
}
None => {}
}
}
fn up(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolUpEvent,
) {
TabletToolTarget::up(&self.0, seat, data, tool_descriptor, event)
}
fn motion(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolMotionEvent,
) {
let mut event = event.clone();
self.0.with_program(|p| {
let has_ssd = p.has_ssd(false);
if has_ssd || p.has_tiled_state() {
let Some(next) = Focus::under(
&p.window,
if has_ssd { SSD_HEIGHT } else { 0 },
event.location,
) else {
return;
};
let _previous = p.swap_focus(Some(next));
let cursor_state = seat.user_data().get::<CursorState>().unwrap();
cursor_state.lock().unwrap().set_shape(next.cursor_shape());
seat.set_cursor_image_status(CursorImageStatus::default_named());
}
});
event.location -= self.0.with_program(|p| p.window.geometry().loc.to_f64());
TabletToolTarget::motion(&self.0, seat, data, tool_descriptor, &event)
}
fn axis(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
frame: ToolAxisFrame,
) {
TabletToolTarget::axis(&self.0, seat, data, tool_descriptor, frame)
}
fn button(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolButtonEvent,
) {
TabletToolTarget::button(&self.0, seat, data, tool_descriptor, event)
}
fn frame(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
time: InputTime,
) {
TabletToolTarget::frame(&self.0, seat, data, tool_descriptor, time)
}
}
impl WaylandFocus for CosmicWindow { impl WaylandFocus for CosmicWindow {
fn wl_surface(&self) -> Option<Cow<'_, WlSurface>> { fn wl_surface(&self) -> Option<Cow<'_, WlSurface>> {
self.0.with_program(|p| { self.0.with_program(|p| {

View file

@ -2,18 +2,11 @@ use crate::{
shell::{CosmicSurface, MinimizedWindow, Shell, Trigger, element::CosmicMapped}, shell::{CosmicSurface, MinimizedWindow, Shell, Trigger, element::CosmicMapped},
state::{Common, State}, state::{Common, State},
utils::prelude::*, utils::prelude::*,
wayland::{ wayland::handlers::{xdg_shell::PopupGrabData, xwayland_keyboard_grab::XWaylandGrabSeatData},
handlers::{xdg_shell::PopupGrabData, xwayland_keyboard_grab::XWaylandGrabSeatData},
protocols::session_lock_layer::layer_show_on_lock,
},
}; };
use indexmap::IndexSet; use indexmap::IndexSet;
use smithay::{ use smithay::{
backend::input::InputTime, desktop::{PopupUngrabStrategy, layer_map_for_output},
desktop::{
LayerSurface, PopupUngrabStrategy, WindowSurfaceType, find_popup_root_surface,
layer_map_for_output,
},
input::{Seat, pointer::MotionEvent}, input::{Seat, pointer::MotionEvent},
output::Output, output::Output,
reexports::wayland_server::{Resource, protocol::wl_surface::WlSurface}, reexports::wayland_server::{Resource, protocol::wl_surface::WlSurface},
@ -255,17 +248,8 @@ impl Shell {
let workspace = if let Some(workspace) = workspace { let workspace = if let Some(workspace) = workspace {
self.workspaces.space_for_handle_mut(&workspace.0).unwrap() self.workspaces.space_for_handle_mut(&workspace.0).unwrap()
} else { } else {
let output = match &target { //should this be the active output or the focused output?
FocusTarget::Window(mapped) => self self.active_space_mut(&seat.focused_or_active_output())
.workspaces
.sets
.iter()
.find(|(_, set)| set.sticky_layer.mapped().any(|m| m == mapped))
.map(|(output, _)| output.clone()),
FocusTarget::Fullscreen(_) => None,
};
self.active_space_mut(&output.unwrap_or_else(|| seat.active_output()))
.unwrap() .unwrap()
}; };
@ -435,7 +419,7 @@ fn update_focus_state(
&MotionEvent { &MotionEvent {
location: new_pos.as_logical(), location: new_pos.as_logical(),
serial: SERIAL_COUNTER.next_serial(), serial: SERIAL_COUNTER.next_serial(),
time: InputTime::now(), time: 0,
}, },
); );
} }
@ -642,42 +626,19 @@ fn focus_target_is_valid(
output: &Output, output: &Output,
target: KeyboardFocusTarget, target: KeyboardFocusTarget,
) -> bool { ) -> bool {
// If a session lock is active, only lock surfaces and lock layers can be focused // If a session lock is active, only lock surfaces can be focused
if shell.session_lock.is_some() { if shell.session_lock.is_some() {
if let KeyboardFocusTarget::LayerSurface(layer) = &target {
return layer_show_on_lock(layer.wl_surface());
} else if let KeyboardFocusTarget::Popup(popup) = &target
&& let Ok(root) = find_popup_root_surface(popup)
{
return layer_show_on_lock(&root);
}
return matches!(target, KeyboardFocusTarget::LockSurface(_)); return matches!(target, KeyboardFocusTarget::LockSurface(_));
} }
// If an exclusive layer shell surface exists (on any output), only exclusive // If an exclusive layer shell surface exists (on any output), only exclusive
// shell surfaces can have focus, on the highest layer with exclusive surfaces. // shell surfaces can have focus, on the highest layer with exclusive surfaces.
// Popups are judged by their root surface, so an exclusive surface can
// still open grabbing popups (menus, dropdowns, context menus).
if let Some(layer) = exclusive_layer_surface_layer(shell) { if let Some(layer) = exclusive_layer_surface_layer(shell) {
let is_exclusive_on_layer = |layer_surface: &LayerSurface| { return if let KeyboardFocusTarget::LayerSurface(layer_surface) = target {
let data = layer_surface.cached_state(); let data = layer_surface.cached_state();
(data.keyboard_interactivity, data.layer) == (KeyboardInteractivity::Exclusive, layer) (data.keyboard_interactivity, data.layer) == (KeyboardInteractivity::Exclusive, layer)
}; } else {
return match target { false
KeyboardFocusTarget::LayerSurface(layer_surface) => {
is_exclusive_on_layer(&layer_surface)
}
KeyboardFocusTarget::Popup(popup) => find_popup_root_surface(&popup)
.ok()
.and_then(|root| {
shell.outputs().find_map(|o| {
layer_map_for_output(o)
.layer_for_surface(&root, WindowSurfaceType::ALL)
.map(&is_exclusive_on_layer)
})
})
.unwrap_or(false),
_ => false,
}; };
} }
@ -807,7 +768,7 @@ fn update_pointer_focus(state: &mut State, seat: &Seat<State>) {
&MotionEvent { &MotionEvent {
location: pointer.current_location(), location: pointer.current_location(),
serial: SERIAL_COUNTER.next_serial(), serial: SERIAL_COUNTER.next_serial(),
time: InputTime::now(), time: state.common.clock.now().as_millis(),
}, },
); );
} }

View file

@ -22,7 +22,7 @@ use crate::{
prelude::OutputExt, prelude::OutputExt,
quirks::{WORKSPACE_OVERVIEW_NAMESPACE, workspace_overview_is_open}, quirks::{WORKSPACE_OVERVIEW_NAMESPACE, workspace_overview_is_open},
}, },
wayland::protocols::{session_lock_layer::layer_show_on_lock, workspace::WorkspaceHandle}, wayland::protocols::workspace::WorkspaceHandle,
}; };
pub enum Stage<'a> { pub enum Stage<'a> {
@ -77,8 +77,6 @@ fn render_input_order_internal<R: 'static>(
element_filter: ElementFilter, element_filter: ElementFilter,
mut callback: impl FnMut(Stage) -> ControlFlow<Result<R, OutputNoMode>, ()>, mut callback: impl FnMut(Stage) -> ControlFlow<Result<R, OutputNoMode>, ()>,
) -> ControlFlow<Result<R, OutputNoMode>, ()> { ) -> ControlFlow<Result<R, OutputNoMode>, ()> {
// NOTE: Keep in sync with other surface iteration functions
if shell if shell
.zoom_state .zoom_state
.as_ref() .as_ref()
@ -89,92 +87,7 @@ fn render_input_order_internal<R: 'static>(
// Session Lock // Session Lock
if let Some(session_lock) = &shell.session_lock { if let Some(session_lock) = &shell.session_lock {
for (layer, popup, location) in layer_popups(output, Layer::Overlay, element_filter) { return callback(Stage::SessionLock(session_lock.surfaces.get(output)));
if !layer_show_on_lock(layer.wl_surface()) {
continue;
}
callback(Stage::LayerPopup {
layer,
popup: &popup,
location,
workspace_idx: current.1,
})?;
}
for (layer, location) in layer_surfaces(output, Layer::Overlay, element_filter) {
if !layer_show_on_lock(layer.wl_surface()) {
continue;
}
callback(Stage::LayerSurface {
layer,
location,
workspace_idx: current.1,
})?;
}
for (layer, popup, location) in layer_popups(output, Layer::Top, element_filter) {
if !layer_show_on_lock(layer.wl_surface()) {
continue;
}
callback(Stage::LayerPopup {
layer,
popup: &popup,
location,
workspace_idx: current.1,
})?;
}
for (layer, location) in layer_surfaces(output, Layer::Top, element_filter) {
if !layer_show_on_lock(layer.wl_surface()) {
continue;
}
callback(Stage::LayerSurface {
layer,
location,
workspace_idx: current.1,
})?;
}
callback(Stage::SessionLock(session_lock.surfaces.get(output)))?;
for (layer, popup, location) in layer_popups(output, Layer::Bottom, element_filter) {
if !layer_show_on_lock(layer.wl_surface()) {
continue;
}
callback(Stage::LayerPopup {
layer,
popup: &popup,
location,
workspace_idx: current.1,
})?;
}
for (layer, popup, location) in layer_popups(output, Layer::Background, element_filter) {
if !layer_show_on_lock(layer.wl_surface()) {
continue;
}
callback(Stage::LayerPopup {
layer,
popup: &popup,
location,
workspace_idx: current.1,
})?;
}
for (layer, location) in layer_surfaces(output, Layer::Bottom, element_filter) {
if !layer_show_on_lock(layer.wl_surface()) {
continue;
}
callback(Stage::LayerSurface {
layer,
location,
workspace_idx: current.1,
})?;
}
for (layer, location) in layer_surfaces(output, Layer::Background, element_filter) {
if !layer_show_on_lock(layer.wl_surface()) {
continue;
}
callback(Stage::LayerSurface {
layer,
location,
workspace_idx: current.1,
})?;
}
return ControlFlow::Continue(());
} }
// Overlay-level layer shell // Overlay-level layer shell

View file

@ -16,30 +16,21 @@ use crate::{
}; };
use id_tree::NodeId; use id_tree::NodeId;
use smithay::{ use smithay::{
backend::input::{InputTime, KeyState, TabletToolDescriptor}, backend::input::KeyState,
desktop::{LayerSurface, PopupKind, WindowSurface, WindowSurfaceType, space::SpaceElement}, desktop::{LayerSurface, PopupKind, WindowSurface, WindowSurfaceType, space::SpaceElement},
input::{ input::{
Seat, Seat,
dnd::{DndFocus, OfferData, Source}, dnd::{DndFocus, OfferData, Source},
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
pointer::{ pointer::{
AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent,
GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, MotionEvent as PointerMotionEvent, PointerTarget, RelativeMotionEvent,
PointerTarget, RelativeMotionEvent,
},
tablet::{
Tablet,
tool::{
AxisFrame as ToolAxisFrame, ButtonEvent as ToolButtonEvent,
DownEvent as ToolDownEvent, MotionEvent as ToolMotionEvent, TabletToolHandle,
TabletToolTarget, UpEvent as ToolUpEvent,
},
}, },
touch::{ touch::{
DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent,
OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, TouchTarget, UpEvent,
}, },
}, },
reexports::wayland_server::{ reexports::wayland_server::{
@ -173,17 +164,6 @@ impl PointerFocusTarget {
} }
} }
fn inner_tablet_tool_target(&self) -> &dyn TabletToolTarget<State> {
match self {
PointerFocusTarget::WlSurface { surface, .. } => surface,
PointerFocusTarget::X11Surface { surface, .. } => surface,
PointerFocusTarget::StackUI(u) => u,
PointerFocusTarget::WindowUI(u) => u,
PointerFocusTarget::ResizeFork(f) => f,
PointerFocusTarget::ZoomUI(e) => e,
}
}
pub fn under_surface<P: Into<Point<f64, Logical>>>( pub fn under_surface<P: Into<Point<f64, Logical>>>(
surface: &CosmicSurface, surface: &CosmicSurface,
point: P, point: P,
@ -292,10 +272,9 @@ impl PointerFocusTarget {
None None
}; };
let cursor_hotspot = if let Some(CursorGeometry { hotspot, .. }) = seat.cursor_geometry( let cursor_hotspot = if let Some(CursorGeometry { hotspot, .. }) =
(0.0, 0.0), seat.cursor_geometry((0.0, 0.0), Duration::from_millis(event.time as u64).into())
Duration::from_millis(event.time.millis() as u64).into(), {
) {
hotspot hotspot
} else { } else {
Point::from((0, 0)) Point::from((0, 0))
@ -306,16 +285,6 @@ impl PointerFocusTarget {
session.set_cursor_hotspot(cursor_hotspot); session.set_cursor_hotspot(cursor_hotspot);
} }
} }
pub fn supports_tool(&self, tool_handle: &TabletToolHandle<State>) -> bool {
match self {
Self::WlSurface { surface, .. } if surface.client().is_some() => tool_handle
.client_tools(&surface.client().unwrap())
.next()
.is_some(),
_ => true,
}
}
} }
impl KeyboardFocusTarget { impl KeyboardFocusTarget {
@ -439,16 +408,16 @@ impl PointerTarget<State> for PointerFocusTarget {
self.inner_pointer_target() self.inner_pointer_target()
.relative_motion(seat, data, event); .relative_motion(seat, data, event);
} }
fn button(&self, seat: &Seat<State>, data: &mut State, event: &PointerButtonEvent) { fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) {
self.inner_pointer_target().button(seat, data, event); self.inner_pointer_target().button(seat, data, event);
} }
fn axis(&self, seat: &Seat<State>, data: &mut State, frame: PointerAxisFrame) { fn axis(&self, seat: &Seat<State>, data: &mut State, frame: AxisFrame) {
self.inner_pointer_target().axis(seat, data, frame); self.inner_pointer_target().axis(seat, data, frame);
} }
fn frame(&self, seat: &Seat<State>, data: &mut State) { fn frame(&self, seat: &Seat<State>, data: &mut State) {
self.inner_pointer_target().frame(seat, data); self.inner_pointer_target().frame(seat, data);
} }
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: InputTime) { fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
let toplevel = self.toplevel(&data.common.shell.read()); let toplevel = self.toplevel(&data.common.shell.read());
if let Some(element) = toplevel { if let Some(element) = toplevel {
for session in element.cursor_sessions() { for session in element.cursor_sessions() {
@ -528,102 +497,12 @@ impl PointerTarget<State> for PointerFocusTarget {
} }
} }
impl TabletToolTarget<State> for PointerFocusTarget {
fn proximity_in(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
tablet: &Tablet,
serial: Serial,
) {
self.inner_tablet_tool_target()
.proximity_in(seat, data, tool_descriptor, tablet, serial);
}
fn proximity_out(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
) {
self.inner_tablet_tool_target()
.proximity_out(seat, data, tool_descriptor);
}
fn down(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolDownEvent,
) {
self.inner_tablet_tool_target()
.down(seat, data, tool_descriptor, event);
}
fn up(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolUpEvent,
) {
self.inner_tablet_tool_target()
.up(seat, data, tool_descriptor, event);
}
fn motion(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolMotionEvent,
) {
self.inner_tablet_tool_target()
.motion(seat, data, tool_descriptor, event);
}
fn axis(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
frame: ToolAxisFrame,
) {
self.inner_tablet_tool_target()
.axis(seat, data, tool_descriptor, frame);
}
fn button(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &ToolButtonEvent,
) {
self.inner_tablet_tool_target()
.button(seat, data, tool_descriptor, event);
}
fn frame(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
time: InputTime,
) {
self.inner_tablet_tool_target()
.frame(seat, data, tool_descriptor, time);
}
}
impl TouchTarget<State> for PointerFocusTarget { impl TouchTarget<State> for PointerFocusTarget {
fn down(&self, seat: &Seat<State>, data: &mut State, event: &TouchDownEvent) { fn down(&self, seat: &Seat<State>, data: &mut State, event: &DownEvent) {
self.inner_touch_target().down(seat, data, event); self.inner_touch_target().down(seat, data, event);
} }
fn up(&self, seat: &Seat<State>, data: &mut State, event: &TouchUpEvent) { fn up(&self, seat: &Seat<State>, data: &mut State, event: &UpEvent) {
self.inner_touch_target().up(seat, data, event); self.inner_touch_target().up(seat, data, event);
} }
@ -714,7 +593,7 @@ impl DndFocus<State> for PointerFocusTarget {
offer: Option<&mut CosmicOfferData<S>>, offer: Option<&mut CosmicOfferData<S>>,
seat: &Seat<State>, seat: &Seat<State>,
location: Point<f64, Logical>, location: Point<f64, Logical>,
time: InputTime, time: u32,
) { ) {
match self { match self {
PointerFocusTarget::WlSurface { surface, .. } => { PointerFocusTarget::WlSurface { surface, .. } => {
@ -816,7 +695,7 @@ impl KeyboardTarget<State> for KeyboardFocusTarget {
key: KeysymHandle<'_>, key: KeysymHandle<'_>,
state: KeyState, state: KeyState,
serial: Serial, serial: Serial,
time: InputTime, time: u32,
) { ) {
if let Some(inner) = self.inner_keyboard_target() { if let Some(inner) = self.inner_keyboard_target() {
inner.key(seat, data, key, state, serial, time); inner.key(seat, data, key, state, serial, time);

View file

@ -1,34 +1,22 @@
use smithay::{ use smithay::{
backend::input::{InputTime, TabletToolDescriptor},
input::{ input::{
Seat, SeatHandler, Seat, SeatHandler,
pointer::{ pointer::{
AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, Focus, AxisFrame, ButtonEvent, Focus, GestureHoldBeginEvent, GestureHoldEndEvent,
GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, GrabStartData as PointerGrabStartData, MotionEvent as PointerMotionEvent, PointerGrab,
MotionEvent as PointerMotionEvent, PointerGrab, PointerInnerHandle, PointerInnerHandle, RelativeMotionEvent,
RelativeMotionEvent,
},
tablet::{
TabletSeatHandler, TabletSeatTrait,
tool::{
AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent,
DownEvent as TabletDownEvent, GrabStartData as TabletGrabStartData,
MotionEvent as TabletMotionEvent, ProximityInEvent, ProximityOutEvent,
TabletToolGrab, TabletToolInnerHandle, UpEvent as TabletUpEvent,
},
}, },
touch::{ touch::{
DownEvent as TouchDownEvent, GrabStartData as TouchGrabStartData, DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent,
MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab, OrientationEvent, ShapeEvent, TouchGrab, TouchInnerHandle, UpEvent,
TouchInnerHandle, UpEvent as TouchUpEvent,
}, },
}, },
utils::{Logical, Point, SERIAL_COUNTER, Serial}, utils::{Logical, Point, SERIAL_COUNTER, Serial},
}; };
use crate::{shell::grabs::GrabType, state::State}; use crate::state::State;
use super::GrabStartData; use super::GrabStartData;
@ -56,15 +44,10 @@ impl<G> DelayGrab<G> {
} }
} }
pub fn grab_type(&self) -> GrabType { pub fn is_touch_grab(&self) -> bool {
self.start_data.type_() match self.start_data {
} GrabStartData::Touch(_) => true,
GrabStartData::Pointer(_) => false,
pub fn tool(&self) -> Option<&TabletToolDescriptor> {
if let GrabStartData::TabletTool { tool, .. } = &self.start_data {
Some(tool)
} else {
None
} }
} }
} }
@ -109,7 +92,7 @@ impl<G: PointerGrab<State>> PointerGrab<State> for DelayGrab<G> {
&mut self, &mut self,
data: &mut State, data: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
event: &PointerButtonEvent, event: &ButtonEvent,
) { ) {
handle.button(data, event); handle.button(data, event);
if handle.current_pressed().is_empty() { if handle.current_pressed().is_empty() {
@ -121,7 +104,7 @@ impl<G: PointerGrab<State>> PointerGrab<State> for DelayGrab<G> {
&mut self, &mut self,
data: &mut State, data: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
details: PointerAxisFrame, details: AxisFrame,
) { ) {
handle.axis(data, details); handle.axis(data, details);
} }
@ -218,17 +201,12 @@ impl<G: TouchGrab<State>> TouchGrab<State> for DelayGrab<G> {
data: &mut State, data: &mut State,
handle: &mut TouchInnerHandle<'_, State>, handle: &mut TouchInnerHandle<'_, State>,
focus: Option<(<State as SeatHandler>::TouchFocus, Point<f64, Logical>)>, focus: Option<(<State as SeatHandler>::TouchFocus, Point<f64, Logical>)>,
event: &TouchDownEvent, event: &DownEvent,
) { ) {
handle.down(data, focus, event); handle.down(data, focus, event);
} }
fn up( fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) {
&mut self,
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
event: &TouchUpEvent,
) {
handle.up(data, event); handle.up(data, event);
if event.slot == TouchGrab::start_data(self).slot { if event.slot == TouchGrab::start_data(self).slot {
@ -295,110 +273,3 @@ impl<G: TouchGrab<State>> TouchGrab<State> for DelayGrab<G> {
fn unset(&mut self, _data: &mut State) {} fn unset(&mut self, _data: &mut State) {}
} }
impl<G: TabletToolGrab<State>> TabletToolGrab<State> for DelayGrab<G> {
fn start_data(&self) -> &TabletGrabStartData<State> {
match &self.start_data {
GrabStartData::TabletTool { data, .. } => data,
_ => unreachable!(),
}
}
fn proximity_out(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &ProximityOutEvent,
) {
handle.proximity_out(data, event);
}
fn motion(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
focus: Option<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &TabletMotionEvent,
) {
handle.motion(data, focus, event);
let distance = self.start_data.distance(event.location);
if distance >= 1.
&& let Some(factory) = self.grab_factory.take()
{
let seat = self.seat.clone();
let serial = self.serial.unwrap_or_else(|| SERIAL_COUNTER.next_serial());
let time = InputTime::now();
let Some(tool) = self.tool().cloned() else {
handle.unset_grab(self, data, serial, time, true);
return;
};
data.common.event_loop_handle.insert_idle(move |data| {
if let Some((grab, focus)) = factory(data) {
seat.tablet_seat()
.get_tool(&tool)
.unwrap()
.set_grab(data, grab, time, serial, focus);
}
});
}
}
fn down(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletDownEvent,
) {
handle.down(data, event)
}
fn up(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletUpEvent,
) {
handle.up(data, event);
handle.unset_grab(self, data, event.serial, event.time, false);
}
fn button(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletButtonEvent,
) {
handle.button(data, event);
}
fn axis(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
frame: TabletAxisFrame,
) {
handle.axis(data, frame)
}
fn frame(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
time: InputTime,
) {
handle.frame(data, time)
}
fn unset(&mut self, _data: &mut State) {}
fn proximity_in(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
focus: Option<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &ProximityInEvent,
) {
handle.proximity_in(data, focus, event);
}
}

View file

@ -1,10 +1,7 @@
use cosmic_settings_config::shortcuts::Action; use cosmic_settings_config::shortcuts::Action;
use smithay::{ use smithay::{
backend::input::InputTime, input::pointer::MotionEvent, reexports::wayland_server::protocol::wl_surface::WlSurface,
input::{pointer::MotionEvent, tablet::TabletSeatTrait}, utils::SERIAL_COUNTER, wayland::seat::WaylandFocus,
reexports::wayland_server::protocol::wl_surface::WlSurface,
utils::SERIAL_COUNTER,
wayland::seat::WaylandFocus,
}; };
use crate::{ use crate::{
@ -13,7 +10,7 @@ use crate::{
shell::{ shell::{
CosmicSurface, PointGlobalExt, Shell, CosmicSurface, PointGlobalExt, Shell,
element::{CosmicMapped, CosmicWindow}, element::{CosmicMapped, CosmicWindow},
grabs::{GrabType, ReleaseMode}, grabs::ReleaseMode,
}, },
state::State, state::State,
utils::{prelude::SeatExt, screenshot::screenshot_window}, utils::{prelude::SeatExt, screenshot::screenshot_window},
@ -355,20 +352,19 @@ pub fn window_items(
std::mem::drop(shell); std::mem::drop(shell);
if let Some((grab, focus)) = res { if let Some((grab, focus)) = res {
let serial = SERIAL_COUNTER.next_serial(); if grab.is_touch_grab() {
match grab.grab_type() { seat.get_touch().unwrap().set_grab(
GrabType::Touch => { state,
seat.get_touch().unwrap().set_grab(state, grab, serial) grab,
} SERIAL_COUNTER.next_serial(),
GrabType::Pointer => seat )
.get_pointer() } else {
.unwrap() seat.get_pointer().unwrap().set_grab(
.set_grab(state, grab, serial, focus), state,
GrabType::TabletTool => seat grab,
.tablet_seat() SERIAL_COUNTER.next_serial(),
.get_tool(grab.tool().unwrap()) focus,
.unwrap() );
.set_grab(state, grab, InputTime::now(), serial, focus),
} }
} }
} }
@ -392,29 +388,21 @@ pub fn window_items(
std::mem::drop(shell); std::mem::drop(shell);
if let Some(((target, loc), (grab, focus))) = res { if let Some(((target, loc), (grab, focus))) = res {
let serial = SERIAL_COUNTER.next_serial(); let serial = SERIAL_COUNTER.next_serial();
match grab.grab_type() { if grab.is_touch_grab() {
GrabType::Touch => { seat.get_touch().unwrap().set_grab(state, grab, serial);
seat.get_touch().unwrap().set_grab(state, grab, serial) } else {
} let pointer = seat.get_pointer().unwrap();
GrabType::TabletTool => seat pointer.motion(
.tablet_seat() state,
.get_tool(grab.tool().unwrap()) target,
.unwrap() &MotionEvent {
.set_grab(state, grab, InputTime::now(), serial, focus), location: loc.as_logical().to_f64(),
GrabType::Pointer => { serial,
let pointer = seat.get_pointer().unwrap(); time: state.common.clock.now().as_millis(),
pointer.motion( },
state, );
target, pointer.frame(state);
&MotionEvent { pointer.set_grab(state, grab, serial, focus);
location: loc.as_logical().to_f64(),
serial,
time: InputTime::now(),
},
);
pointer.frame(state);
pointer.set_grab(state, grab, serial, focus);
}
} }
} }
}); });
@ -435,30 +423,21 @@ pub fn window_items(
std::mem::drop(shell); std::mem::drop(shell);
if let Some(((target, loc), (grab, focus))) = res { if let Some(((target, loc), (grab, focus))) = res {
let serial = SERIAL_COUNTER.next_serial(); let serial = SERIAL_COUNTER.next_serial();
match grab.grab_type() { if grab.is_touch_grab() {
GrabType::Touch => { seat.get_touch().unwrap().set_grab(state, grab, serial);
seat.get_touch().unwrap().set_grab(state, grab, serial) } else {
} let pointer = seat.get_pointer().unwrap();
GrabType::Pointer => { pointer.motion(
let pointer = seat.get_pointer().unwrap(); state,
pointer.motion( target,
state, &MotionEvent {
target, location: loc.as_logical().to_f64(),
&MotionEvent { serial,
location: loc.as_logical().to_f64(), time: state.common.clock.now().as_millis(),
serial, },
time: InputTime::now(), );
}, pointer.frame(state);
); pointer.set_grab(state, grab, serial, focus);
pointer.frame(state);
pointer.set_grab(state, grab, serial, focus);
}
GrabType::TabletTool => {
seat.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus);
}
} }
} }
}); });
@ -479,30 +458,21 @@ pub fn window_items(
std::mem::drop(shell); std::mem::drop(shell);
if let Some(((target, loc), (grab, focus))) = res { if let Some(((target, loc), (grab, focus))) = res {
let serial = SERIAL_COUNTER.next_serial(); let serial = SERIAL_COUNTER.next_serial();
match grab.grab_type() { if grab.is_touch_grab() {
GrabType::Touch => { seat.get_touch().unwrap().set_grab(state, grab, serial);
seat.get_touch().unwrap().set_grab(state, grab, serial) } else {
} let pointer = seat.get_pointer().unwrap();
GrabType::Pointer => { pointer.motion(
let pointer = seat.get_pointer().unwrap(); state,
pointer.motion( target,
state, &MotionEvent {
target, location: loc.as_logical().to_f64(),
&MotionEvent { serial,
location: loc.as_logical().to_f64(), time: state.common.clock.now().as_millis(),
serial, },
time: InputTime::now(), );
}, pointer.frame(state);
); pointer.set_grab(state, grab, serial, focus);
pointer.frame(state);
pointer.set_grab(state, grab, serial, focus);
}
GrabType::TabletTool => {
seat.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus);
}
} }
} }
}); });
@ -523,29 +493,21 @@ pub fn window_items(
std::mem::drop(shell); std::mem::drop(shell);
if let Some(((target, loc), (grab, focus))) = res { if let Some(((target, loc), (grab, focus))) = res {
let serial = SERIAL_COUNTER.next_serial(); let serial = SERIAL_COUNTER.next_serial();
match grab.grab_type() { if grab.is_touch_grab() {
GrabType::Touch => { seat.get_touch().unwrap().set_grab(state, grab, serial);
seat.get_touch().unwrap().set_grab(state, grab, serial) } else {
} let pointer = seat.get_pointer().unwrap();
GrabType::Pointer => { pointer.motion(
let pointer = seat.get_pointer().unwrap(); state,
pointer.motion( target,
state, &MotionEvent {
target, location: loc.as_logical().to_f64(),
&MotionEvent { serial,
location: loc.as_logical().to_f64(), time: state.common.clock.now().as_millis(),
serial, },
time: InputTime::now(), );
}, pointer.frame(state);
); pointer.set_grab(state, grab, serial, focus);
pointer.frame(state);
pointer.set_grab(state, grab, serial, focus);
}
GrabType::TabletTool => seat
.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(state, grab, InputTime::now(), serial, focus),
} }
} }
}); });
@ -665,20 +627,19 @@ pub fn fullscreen_items(window: &CosmicSurface, config: &Config) -> impl Iterato
std::mem::drop(shell); std::mem::drop(shell);
if let Some((grab, focus)) = res { if let Some((grab, focus)) = res {
let serial = SERIAL_COUNTER.next_serial(); if grab.is_touch_grab() {
match grab.grab_type() { seat.get_touch().unwrap().set_grab(
GrabType::Touch => { state,
seat.get_touch().unwrap().set_grab(state, grab, serial) grab,
} SERIAL_COUNTER.next_serial(),
GrabType::Pointer => seat )
.get_pointer() } else {
.unwrap() seat.get_pointer().unwrap().set_grab(
.set_grab(state, grab, serial, focus), state,
GrabType::TabletTool => seat grab,
.tablet_seat() SERIAL_COUNTER.next_serial(),
.get_tool(grab.tool().unwrap()) focus,
.unwrap() );
.set_grab(state, grab, InputTime::now(), serial, focus),
} }
} }
} }

View file

@ -19,33 +19,22 @@ use cosmic::{
}; };
use smithay::{ use smithay::{
backend::{ backend::{
input::{ButtonState, InputTime, TabletToolDescriptor, TouchSlot}, input::{ButtonState, TouchSlot},
renderer::ImportMem, renderer::ImportMem,
}, },
desktop::space::SpaceElement, desktop::space::SpaceElement,
input::{ input::{
Seat, Seat,
pointer::{ pointer::{
AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent,
GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, GrabStartData as PointerGrabStartData, MotionEvent as PointerMotionEvent, PointerGrab,
MotionEvent as PointerMotionEvent, PointerGrab, PointerInnerHandle, PointerTarget, PointerInnerHandle, PointerTarget, RelativeMotionEvent,
RelativeMotionEvent,
},
tablet::{
TabletSeatHandler,
tool::{
AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent,
DownEvent as TabletDownEvent, GrabStartData as TabletGrabStartData,
MotionEvent as TabletMotionEvent, ProximityInEvent, ProximityOutEvent,
TabletToolGrab, TabletToolInnerHandle, TabletToolTarget, UpEvent as TabletUpEvent,
},
}, },
touch::{ touch::{
DownEvent as TouchDownEvent, GrabStartData as TouchGrabStartData, DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent,
MotionEvent as TouchMotionEvent, TouchGrab, TouchInnerHandle, TouchTarget, TouchGrab, TouchInnerHandle, TouchTarget, UpEvent,
UpEvent as TouchUpEvent,
}, },
}, },
output::Output, output::Output,
@ -54,7 +43,7 @@ use smithay::{
use crate::{ use crate::{
backend::render::element::AsGlowRenderer, backend::render::element::AsGlowRenderer,
shell::{SeatExt, focus::target::PointerFocusTarget, grabs::GrabType}, shell::{SeatExt, focus::target::PointerFocusTarget},
state::State, state::State,
utils::{ utils::{
iced::{IcedElement, IcedRenderElement, Program}, iced::{IcedElement, IcedRenderElement, Program},
@ -361,7 +350,6 @@ impl Program for ContextMenu {
position, position,
pointer_entered: false, pointer_entered: false,
touch_entered: None, touch_entered: None,
tablet_entered: None,
}) })
} }
}); });
@ -521,7 +509,6 @@ pub struct Element {
position: Point<i32, Global>, position: Point<i32, Global>,
pointer_entered: bool, pointer_entered: bool,
touch_entered: Option<TouchSlot>, touch_entered: Option<TouchSlot>,
tablet_entered: Option<TabletToolDescriptor>,
} }
pub struct MenuGrab { pub struct MenuGrab {
@ -530,7 +517,6 @@ pub struct MenuGrab {
seat: Seat<State>, seat: Seat<State>,
screen_space_relative: Option<Output>, screen_space_relative: Option<Output>,
scale: Arc<Mutex<f64>>, scale: Arc<Mutex<f64>>,
last_tablet_idx: Option<usize>,
} }
impl PointerGrab<State> for MenuGrab { impl PointerGrab<State> for MenuGrab {
@ -579,12 +565,10 @@ impl PointerGrab<State> for MenuGrab {
PointerTarget::motion(&element.iced, &self.seat, state, &new_event); PointerTarget::motion(&element.iced, &self.seat, state, &new_event);
} }
} else { } else {
// Keep the root menu hovered while a submenu is open
let keep_root = usize::from(elements.len() > 1);
elements elements
.iter_mut() .iter_mut()
.filter(|element| element.pointer_entered) .filter(|element| element.pointer_entered)
.skip(keep_root) .skip(1)
.for_each(|element| { .for_each(|element| {
PointerTarget::leave( PointerTarget::leave(
&element.iced, &element.iced,
@ -615,7 +599,7 @@ impl PointerGrab<State> for MenuGrab {
&mut self, &mut self,
state: &mut State, state: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
event: &PointerButtonEvent, event: &ButtonEvent,
) { ) {
let any_entered = self let any_entered = self
.elements .elements
@ -649,7 +633,7 @@ impl PointerGrab<State> for MenuGrab {
&mut self, &mut self,
state: &mut State, state: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
details: PointerAxisFrame, details: AxisFrame,
) { ) {
handle.axis(state, details); handle.axis(state, details);
} }
@ -746,7 +730,7 @@ impl TouchGrab<State> for MenuGrab {
data: &mut State, data: &mut State,
handle: &mut TouchInnerHandle<'_, State>, handle: &mut TouchInnerHandle<'_, State>,
_focus: Option<(PointerFocusTarget, Point<f64, Logical>)>, _focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &TouchDownEvent, event: &DownEvent,
) { ) {
{ {
let mut guard = self.elements.lock().unwrap(); let mut guard = self.elements.lock().unwrap();
@ -774,7 +758,7 @@ impl TouchGrab<State> for MenuGrab {
}) { }) {
let element = &mut elements[i]; let element = &mut elements[i];
let new_event = TouchDownEvent { let new_event = DownEvent {
slot: event.slot, slot: event.slot,
location: event_location - element.position.as_logical().to_f64(), location: event_location - element.position.as_logical().to_f64(),
serial: event.serial, serial: event.serial,
@ -789,12 +773,7 @@ impl TouchGrab<State> for MenuGrab {
handle.down(data, None, event); handle.down(data, None, event);
} }
fn up( fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) {
&mut self,
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
event: &TouchUpEvent,
) {
{ {
let elements = self.elements.lock().unwrap(); let elements = self.elements.lock().unwrap();
for element in elements.iter().filter(|elem| { for element in elements.iter().filter(|elem| {
@ -870,249 +849,6 @@ impl TouchGrab<State> for MenuGrab {
fn unset(&mut self, _data: &mut State) {} fn unset(&mut self, _data: &mut State) {}
} }
impl TabletToolGrab<State> for MenuGrab {
fn start_data(&self) -> &TabletGrabStartData<State> {
match &self.start_data {
GrabStartData::TabletTool { data, .. } => data,
_ => unreachable!(),
}
}
fn proximity_in(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
_focus: Option<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &ProximityInEvent,
) {
{
let location = if let Some(output) = self.screen_space_relative.as_ref() {
if data.common.shell.read().zoom_state().is_some() {
event
.location
.as_global()
.to_zoomed(output)
.to_global(output)
.as_logical()
} else {
event.location
}
} else {
event.location
};
let mut elements = self.elements.lock().unwrap();
if let Some(i) = elements.iter().position(|elem| {
let mut bbox = elem.iced.bbox();
bbox.loc = elem.position.as_logical();
bbox.contains(location.to_i32_floor())
}) {
let element = &mut elements[i];
let new_event = TabletMotionEvent {
location: location - element.position.as_logical().to_f64(),
serial: event.serial,
time: event.time,
};
TabletToolTarget::proximity_in(
&element.iced,
&self.seat,
data,
handle.descriptor(),
&handle.current_tablet(),
event.serial,
);
element.tablet_entered = Some(handle.descriptor().clone());
TabletToolTarget::motion(
&element.iced,
&self.seat,
data,
handle.descriptor(),
&new_event,
);
self.last_tablet_idx = Some(i);
}
}
handle.proximity_in(data, None, event);
}
fn proximity_out(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &ProximityOutEvent,
) {
{
let mut elements = self.elements.lock().unwrap();
for element in elements.iter_mut().filter(|elem| {
elem.tablet_entered
.as_ref()
.is_some_and(|tool| tool == handle.descriptor())
}) {
TabletToolTarget::proximity_out(
&element.iced,
&self.seat,
data,
handle.descriptor(),
);
element.tablet_entered.take();
}
self.last_tablet_idx.take();
}
handle.unset_grab(self, data, event.serial, event.time, true);
}
fn motion(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
_focus: Option<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &TabletMotionEvent,
) {
{
let location = if let Some(output) = self.screen_space_relative.as_ref() {
if data.common.shell.read().zoom_state().is_some() {
event
.location
.as_global()
.to_zoomed(output)
.to_global(output)
.as_logical()
} else {
event.location
}
} else {
event.location
};
let mut elements = self.elements.lock().unwrap();
if let Some(i) = elements.iter().position(|elem| {
let mut bbox = elem.iced.bbox();
bbox.loc = elem.position.as_logical();
bbox.contains(location.to_i32_floor())
}) {
let element = &mut elements[i];
let new_event = TabletMotionEvent {
location: location - element.position.as_logical().to_f64(),
serial: event.serial,
time: event.time,
};
if element.tablet_entered.is_none() {
TabletToolTarget::proximity_in(
&element.iced,
&self.seat,
data,
handle.descriptor(),
&handle.current_tablet(),
event.serial,
);
element.tablet_entered = Some(handle.descriptor().clone());
}
TabletToolTarget::motion(
&element.iced,
&self.seat,
data,
handle.descriptor(),
&new_event,
);
self.last_tablet_idx = Some(i);
} else {
let keep_root = usize::from(elements.len() > 1);
elements
.iter_mut()
.filter(|element| element.tablet_entered.is_some())
.skip(keep_root)
.for_each(|element| {
TabletToolTarget::proximity_out(
&element.iced,
&self.seat,
data,
handle.descriptor(),
);
});
self.last_tablet_idx.take();
}
}
handle.motion(data, None, event);
}
fn down(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletDownEvent,
) {
let mut guard = self.elements.lock().unwrap();
let elements = &mut *guard;
if let Some(elem) = self.last_tablet_idx.and_then(|i| elements.get_mut(i))
&& elem
.tablet_entered
.as_ref()
.is_some_and(|desc| desc == handle.descriptor())
{
TabletToolTarget::down(&elem.iced, &self.seat, data, handle.descriptor(), event);
} else {
handle.down(data, event);
}
}
fn up(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletUpEvent,
) {
let mut guard = self.elements.lock().unwrap();
let elements = &mut *guard;
if let Some(elem) = self.last_tablet_idx.and_then(|i| elements.get_mut(i))
&& elem
.tablet_entered
.as_ref()
.is_some_and(|desc| desc == handle.descriptor())
{
TabletToolTarget::up(&elem.iced, &self.seat, data, handle.descriptor(), event);
} else {
handle.up(data, event);
}
}
fn button(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletButtonEvent,
) {
handle.button(data, event);
}
fn axis(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
frame: TabletAxisFrame,
) {
handle.axis(data, frame);
}
fn frame(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
time: InputTime,
) {
handle.frame(data, time);
}
fn unset(&mut self, _data: &mut State) {}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MenuAlignment { pub struct MenuAlignment {
pub x: AxisAlignment, pub x: AxisAlignment,
@ -1316,7 +1052,6 @@ impl MenuGrab {
position, position,
pointer_entered: false, pointer_entered: false,
touch_entered: None, touch_entered: None,
tablet_entered: None,
}])); }]));
let scale = Arc::new(Mutex::new(screen_space_relative.unwrap_or(1.))); let scale = Arc::new(Mutex::new(screen_space_relative.unwrap_or(1.)));
@ -1341,7 +1076,6 @@ impl MenuGrab {
seat: seat.clone(), seat: seat.clone(),
screen_space_relative, screen_space_relative,
scale, scale,
last_tablet_idx: None,
} }
} }
@ -1352,15 +1086,10 @@ impl MenuGrab {
} }
} }
pub fn grab_type(&self) -> GrabType { pub fn is_touch_grab(&self) -> bool {
self.start_data.type_() match self.start_data {
} GrabStartData::Touch(_) => true,
GrabStartData::Pointer(_) => false,
pub fn tool(&self) -> Option<&TabletToolDescriptor> {
if let GrabStartData::TabletTool { tool, .. } = &self.start_data {
Some(tool)
} else {
None
} }
} }
} }

View file

@ -1,26 +1,18 @@
use calloop::LoopHandle; use calloop::LoopHandle;
use cosmic_settings_config::shortcuts; use cosmic_settings_config::shortcuts;
use smithay::{ use smithay::{
backend::input::{InputTime, TabletToolDescriptor},
input::{ input::{
Seat, Seat,
pointer::{ pointer::{
AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent,
GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle,
MotionEvent, PointerGrab, PointerInnerHandle, RelativeMotionEvent, RelativeMotionEvent,
},
tablet::tool::{
AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent,
DownEvent as TabletDownEvent, GrabStartData as TabletGrabStartData,
MotionEvent as TabletMotionEvent, ProximityOutEvent, TabletToolGrab,
TabletToolInnerHandle, UpEvent as TabletUpEvent,
}, },
touch::{ touch::{
DownEvent as TouchDownEvent, GrabStartData as TouchGrabStartData, DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent,
MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab, OrientationEvent, ShapeEvent, TouchGrab, TouchInnerHandle, UpEvent,
TouchInnerHandle, UpEvent as TouchUpEvent,
}, },
}, },
output::Output, output::Output,
@ -47,17 +39,6 @@ use super::{
pub enum GrabStartData { pub enum GrabStartData {
Touch(TouchGrabStartData<State>), Touch(TouchGrabStartData<State>),
Pointer(PointerGrabStartData<State>), Pointer(PointerGrabStartData<State>),
TabletTool {
tool: TabletToolDescriptor,
data: TabletGrabStartData<State>,
},
}
#[derive(Debug, Clone)]
pub enum GrabType {
Touch,
Pointer,
TabletTool,
} }
impl GrabStartData { impl GrabStartData {
@ -65,7 +46,6 @@ impl GrabStartData {
match self { match self {
Self::Touch(touch) => touch.focus.as_ref(), Self::Touch(touch) => touch.focus.as_ref(),
Self::Pointer(pointer) => pointer.focus.as_ref(), Self::Pointer(pointer) => pointer.focus.as_ref(),
Self::TabletTool { data, .. } => data.focus.as_ref(),
} }
} }
@ -73,7 +53,6 @@ impl GrabStartData {
match self { match self {
Self::Touch(touch) => touch.focus = focus, Self::Touch(touch) => touch.focus = focus,
Self::Pointer(pointer) => pointer.focus = focus, Self::Pointer(pointer) => pointer.focus = focus,
Self::TabletTool { data, .. } => data.focus = focus,
} }
} }
@ -81,7 +60,6 @@ impl GrabStartData {
match self { match self {
Self::Touch(touch) => touch.location, Self::Touch(touch) => touch.location,
Self::Pointer(pointer) => pointer.location, Self::Pointer(pointer) => pointer.location,
Self::TabletTool { data, .. } => data.location,
} }
} }
@ -89,7 +67,6 @@ impl GrabStartData {
match self { match self {
Self::Touch(touch) => touch.location = location, Self::Touch(touch) => touch.location = location,
Self::Pointer(pointer) => pointer.location = location, Self::Pointer(pointer) => pointer.location = location,
Self::TabletTool { data, .. } => data.location = location,
} }
} }
@ -99,14 +76,6 @@ impl GrabStartData {
((new.x - old.x).powi(2) + (new.y - old.y).powi(2)).sqrt() ((new.x - old.x).powi(2) + (new.y - old.y).powi(2)).sqrt()
} }
pub fn type_(&self) -> GrabType {
match self {
Self::Pointer(_) => GrabType::Pointer,
Self::Touch(_) => GrabType::Touch,
Self::TabletTool { .. } => GrabType::TabletTool,
}
}
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -234,17 +203,10 @@ impl From<ResizeForkGrab> for ResizeGrab {
} }
impl ResizeGrab { impl ResizeGrab {
pub fn grab_type(&self) -> GrabType { pub fn is_touch_grab(&self) -> bool {
match self { match self {
ResizeGrab::Floating(grab) => grab.grab_type(), ResizeGrab::Floating(grab) => grab.is_touch_grab(),
ResizeGrab::Tiling(grab) => grab.grab_type(), ResizeGrab::Tiling(grab) => grab.is_touch_grab(),
}
}
pub fn tool(&self) -> Option<&TabletToolDescriptor> {
match self {
ResizeGrab::Floating(grab) => grab.tool(),
ResizeGrab::Tiling(grab) => grab.tool(),
} }
} }
} }
@ -280,11 +242,11 @@ impl PointerGrab<State> for ResizeGrab {
&mut self, &mut self,
data: &mut State, data: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
event: &PointerButtonEvent, event: &ButtonEvent,
) { ) {
match self { match self {
ResizeGrab::Floating(grab) => PointerGrab::button(grab, data, handle, event), ResizeGrab::Floating(grab) => grab.button(data, handle, event),
ResizeGrab::Tiling(grab) => PointerGrab::button(grab, data, handle, event), ResizeGrab::Tiling(grab) => grab.button(data, handle, event),
} }
} }
@ -292,11 +254,11 @@ impl PointerGrab<State> for ResizeGrab {
&mut self, &mut self,
data: &mut State, data: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
details: PointerAxisFrame, details: AxisFrame,
) { ) {
match self { match self {
ResizeGrab::Floating(grab) => PointerGrab::axis(grab, data, handle, details), ResizeGrab::Floating(grab) => grab.axis(data, handle, details),
ResizeGrab::Tiling(grab) => PointerGrab::axis(grab, data, handle, details), ResizeGrab::Tiling(grab) => grab.axis(data, handle, details),
} }
} }
@ -424,7 +386,7 @@ impl TouchGrab<State> for ResizeGrab {
data: &mut State, data: &mut State,
handle: &mut TouchInnerHandle<'_, State>, handle: &mut TouchInnerHandle<'_, State>,
focus: Option<(PointerFocusTarget, Point<f64, Logical>)>, focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &TouchDownEvent, event: &DownEvent,
) { ) {
match self { match self {
ResizeGrab::Floating(grab) => TouchGrab::down(grab, data, handle, focus, event), ResizeGrab::Floating(grab) => TouchGrab::down(grab, data, handle, focus, event),
@ -432,12 +394,7 @@ impl TouchGrab<State> for ResizeGrab {
} }
} }
fn up( fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) {
&mut self,
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
event: &TouchUpEvent,
) {
match self { match self {
ResizeGrab::Floating(grab) => TouchGrab::up(grab, data, handle, event), ResizeGrab::Floating(grab) => TouchGrab::up(grab, data, handle, event),
ResizeGrab::Tiling(grab) => TouchGrab::up(grab, data, handle, event), ResizeGrab::Tiling(grab) => TouchGrab::up(grab, data, handle, event),
@ -510,107 +467,6 @@ impl TouchGrab<State> for ResizeGrab {
} }
} }
impl TabletToolGrab<State> for ResizeGrab {
fn down(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletDownEvent,
) {
match self {
ResizeGrab::Floating(grab) => TabletToolGrab::down(grab, data, handle, event),
ResizeGrab::Tiling(grab) => TabletToolGrab::down(grab, data, handle, event),
}
}
fn up(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletUpEvent,
) {
match self {
ResizeGrab::Floating(grab) => TabletToolGrab::up(grab, data, handle, event),
ResizeGrab::Tiling(grab) => TabletToolGrab::up(grab, data, handle, event),
}
}
fn motion(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &TabletMotionEvent,
) {
match self {
ResizeGrab::Floating(grab) => TabletToolGrab::motion(grab, data, handle, focus, event),
ResizeGrab::Tiling(grab) => TabletToolGrab::motion(grab, data, handle, focus, event),
}
}
fn frame(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
serial: InputTime,
) {
match self {
ResizeGrab::Floating(grab) => TabletToolGrab::frame(grab, data, handle, serial),
ResizeGrab::Tiling(grab) => TabletToolGrab::frame(grab, data, handle, serial),
}
}
fn button(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletButtonEvent,
) {
match self {
ResizeGrab::Floating(grab) => TabletToolGrab::button(grab, data, handle, event),
ResizeGrab::Tiling(grab) => TabletToolGrab::button(grab, data, handle, event),
}
}
fn axis(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
details: TabletAxisFrame,
) {
match self {
ResizeGrab::Floating(grab) => TabletToolGrab::axis(grab, data, handle, details),
ResizeGrab::Tiling(grab) => TabletToolGrab::axis(grab, data, handle, details),
}
}
fn proximity_out(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &ProximityOutEvent,
) {
match self {
ResizeGrab::Floating(grab) => TabletToolGrab::proximity_out(grab, data, handle, event),
ResizeGrab::Tiling(grab) => TabletToolGrab::proximity_out(grab, data, handle, event),
}
}
fn start_data(&self) -> &TabletGrabStartData<State> {
match self {
ResizeGrab::Floating(grab) => TabletToolGrab::start_data(grab),
ResizeGrab::Tiling(grab) => TabletToolGrab::start_data(grab),
}
}
fn unset(&mut self, data: &mut State) {
match self {
ResizeGrab::Floating(grab) => TabletToolGrab::unset(grab, data),
ResizeGrab::Tiling(grab) => TabletToolGrab::unset(grab, data),
}
}
}
pub enum MoveGrab { pub enum MoveGrab {
Move(moving::MoveGrab), Move(moving::MoveGrab),
Delayed(delay::DelayGrab<MoveGrab>), Delayed(delay::DelayGrab<MoveGrab>),
@ -680,17 +536,10 @@ impl MoveGrab {
} }
} }
pub fn grab_type(&self) -> GrabType { pub fn is_touch_grab(&self) -> bool {
match self { match self {
MoveGrab::Move(m) => m.grab_type(), MoveGrab::Move(m) => m.is_touch_grab(),
MoveGrab::Delayed(d) => d.grab_type(), MoveGrab::Delayed(d) => d.is_touch_grab(),
}
}
pub fn tool(&self) -> Option<&TabletToolDescriptor> {
match self {
MoveGrab::Move(m) => m.tool(),
MoveGrab::Delayed(d) => d.tool(),
} }
} }
} }
@ -725,11 +574,11 @@ impl PointerGrab<State> for MoveGrab {
&mut self, &mut self,
data: &mut State, data: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
event: &PointerButtonEvent, event: &ButtonEvent,
) { ) {
match self { match self {
MoveGrab::Move(grab) => PointerGrab::button(grab, data, handle, event), MoveGrab::Move(grab) => grab.button(data, handle, event),
MoveGrab::Delayed(grab) => PointerGrab::button(grab, data, handle, event), MoveGrab::Delayed(grab) => grab.button(data, handle, event),
} }
} }
@ -737,11 +586,11 @@ impl PointerGrab<State> for MoveGrab {
&mut self, &mut self,
data: &mut State, data: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
details: PointerAxisFrame, details: AxisFrame,
) { ) {
match self { match self {
MoveGrab::Move(grab) => PointerGrab::axis(grab, data, handle, details), MoveGrab::Move(grab) => grab.axis(data, handle, details),
MoveGrab::Delayed(grab) => PointerGrab::axis(grab, data, handle, details), MoveGrab::Delayed(grab) => grab.axis(data, handle, details),
} }
} }
@ -869,7 +718,7 @@ impl TouchGrab<State> for MoveGrab {
data: &mut State, data: &mut State,
handle: &mut TouchInnerHandle<'_, State>, handle: &mut TouchInnerHandle<'_, State>,
focus: Option<(PointerFocusTarget, Point<f64, Logical>)>, focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &TouchDownEvent, event: &DownEvent,
) { ) {
match self { match self {
MoveGrab::Move(grab) => TouchGrab::down(grab, data, handle, focus, event), MoveGrab::Move(grab) => TouchGrab::down(grab, data, handle, focus, event),
@ -877,12 +726,7 @@ impl TouchGrab<State> for MoveGrab {
} }
} }
fn up( fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) {
&mut self,
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
event: &TouchUpEvent,
) {
match self { match self {
MoveGrab::Move(grab) => TouchGrab::up(grab, data, handle, event), MoveGrab::Move(grab) => TouchGrab::up(grab, data, handle, event),
MoveGrab::Delayed(grab) => TouchGrab::up(grab, data, handle, event), MoveGrab::Delayed(grab) => TouchGrab::up(grab, data, handle, event),
@ -954,104 +798,3 @@ impl TouchGrab<State> for MoveGrab {
} }
} }
} }
impl TabletToolGrab<State> for MoveGrab {
fn down(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletDownEvent,
) {
match self {
MoveGrab::Move(grab) => TabletToolGrab::down(grab, data, handle, event),
MoveGrab::Delayed(grab) => TabletToolGrab::down(grab, data, handle, event),
}
}
fn up(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletUpEvent,
) {
match self {
MoveGrab::Move(grab) => TabletToolGrab::up(grab, data, handle, event),
MoveGrab::Delayed(grab) => TabletToolGrab::up(grab, data, handle, event),
}
}
fn motion(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &TabletMotionEvent,
) {
match self {
MoveGrab::Move(grab) => TabletToolGrab::motion(grab, data, handle, focus, event),
MoveGrab::Delayed(grab) => TabletToolGrab::motion(grab, data, handle, focus, event),
}
}
fn frame(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
serial: InputTime,
) {
match self {
MoveGrab::Move(grab) => TabletToolGrab::frame(grab, data, handle, serial),
MoveGrab::Delayed(grab) => TabletToolGrab::frame(grab, data, handle, serial),
}
}
fn button(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletButtonEvent,
) {
match self {
MoveGrab::Move(grab) => TabletToolGrab::button(grab, data, handle, event),
MoveGrab::Delayed(grab) => TabletToolGrab::button(grab, data, handle, event),
}
}
fn axis(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
details: TabletAxisFrame,
) {
match self {
MoveGrab::Move(grab) => TabletToolGrab::axis(grab, data, handle, details),
MoveGrab::Delayed(grab) => TabletToolGrab::axis(grab, data, handle, details),
}
}
fn proximity_out(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &ProximityOutEvent,
) {
match self {
MoveGrab::Move(grab) => TabletToolGrab::proximity_out(grab, data, handle, event),
MoveGrab::Delayed(grab) => TabletToolGrab::proximity_out(grab, data, handle, event),
}
}
fn start_data(&self) -> &TabletGrabStartData<State> {
match self {
MoveGrab::Move(grab) => TabletToolGrab::start_data(grab),
MoveGrab::Delayed(grab) => TabletToolGrab::start_data(grab),
}
}
fn unset(&mut self, data: &mut State) {
match self {
MoveGrab::Move(grab) => TabletToolGrab::unset(grab, data),
MoveGrab::Delayed(grab) => TabletToolGrab::unset(grab, data),
}
}
}

View file

@ -8,7 +8,6 @@ use crate::{
CosmicMapped, CosmicSurface, Direction, ManagedLayer, CosmicMapped, CosmicSurface, Direction, ManagedLayer,
element::{CosmicMappedRenderElement, stack_hover::StackHover}, element::{CosmicMappedRenderElement, stack_hover::StackHover},
focus::target::{KeyboardFocusTarget, PointerFocusTarget}, focus::target::{KeyboardFocusTarget, PointerFocusTarget},
grabs::GrabType,
layout::floating::TiledCorners, layout::floating::TiledCorners,
}, },
utils::prelude::*, utils::prelude::*,
@ -21,7 +20,7 @@ use smallvec::SmallVec;
use smithay::{ use smithay::{
backend::{ backend::{
drm::DrmNode, drm::DrmNode,
input::{ButtonState, InputTime, TabletToolDescriptor}, input::ButtonState,
renderer::{ renderer::{
ImportAll, ImportMem, ImportAll, ImportMem,
element::{RenderElement, utils::RescaleRenderElement}, element::{RenderElement, utils::RescaleRenderElement},
@ -31,27 +30,13 @@ use smithay::{
input::{ input::{
Seat, Seat,
pointer::{ pointer::{
AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorIcon, AxisFrame, ButtonEvent, CursorIcon, GestureHoldBeginEvent, GestureHoldEndEvent,
GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle,
MotionEvent as PointerMotionEvent, PointerGrab, PointerInnerHandle,
RelativeMotionEvent, RelativeMotionEvent,
}, },
tablet::{ touch::{self, GrabStartData as TouchGrabStartData, TouchGrab, TouchInnerHandle},
TabletSeatHandler,
tool::{
AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent,
DownEvent as TabletDownEvent, GrabStartData as TabletGrabStartData,
MotionEvent as TabletMotionEvent, ProximityInEvent, ProximityOutEvent,
TabletToolGrab, TabletToolInnerHandle, UpEvent as TabletUpEvent,
},
},
touch::{
DownEvent as TouchDownEvent, GrabStartData as TouchGrabStartData,
MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab,
TouchInnerHandle, UpEvent as TouchUpEvent,
},
}, },
output::Output, output::Output,
utils::{IsAlive, Logical, Point, Rectangle, SERIAL_COUNTER, Scale}, utils::{IsAlive, Logical, Point, Rectangle, SERIAL_COUNTER, Scale},
@ -518,7 +503,7 @@ impl PointerGrab<State> for MoveGrab {
state: &mut State, state: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
_focus: Option<(PointerFocusTarget, Point<f64, Logical>)>, _focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &PointerMotionEvent, event: &MotionEvent,
) { ) {
self.update_location(state, event.location); self.update_location(state, event.location);
@ -544,7 +529,7 @@ impl PointerGrab<State> for MoveGrab {
&mut self, &mut self,
state: &mut State, state: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
event: &PointerButtonEvent, event: &ButtonEvent,
) { ) {
handle.button(state, event); handle.button(state, event);
match self.release { match self.release {
@ -565,7 +550,7 @@ impl PointerGrab<State> for MoveGrab {
&mut self, &mut self,
state: &mut State, state: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
details: PointerAxisFrame, details: AxisFrame,
) { ) {
handle.axis(state, details); handle.axis(state, details);
} }
@ -662,7 +647,7 @@ impl TouchGrab<State> for MoveGrab {
data: &mut State, data: &mut State,
handle: &mut TouchInnerHandle<'_, State>, handle: &mut TouchInnerHandle<'_, State>,
_focus: Option<(PointerFocusTarget, Point<f64, Logical>)>, _focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &TouchDownEvent, event: &touch::DownEvent,
) { ) {
handle.down(data, None, event) handle.down(data, None, event)
} }
@ -671,7 +656,7 @@ impl TouchGrab<State> for MoveGrab {
&mut self, &mut self,
data: &mut State, data: &mut State,
handle: &mut TouchInnerHandle<'_, State>, handle: &mut TouchInnerHandle<'_, State>,
event: &TouchUpEvent, event: &touch::UpEvent,
) { ) {
if event.slot == <Self as TouchGrab<State>>::start_data(self).slot { if event.slot == <Self as TouchGrab<State>>::start_data(self).slot {
handle.unset_grab(self, data); handle.unset_grab(self, data);
@ -685,7 +670,7 @@ impl TouchGrab<State> for MoveGrab {
data: &mut State, data: &mut State,
handle: &mut TouchInnerHandle<'_, State>, handle: &mut TouchInnerHandle<'_, State>,
_focus: Option<(PointerFocusTarget, Point<f64, Logical>)>, _focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &TouchMotionEvent, event: &touch::MotionEvent,
) { ) {
if event.slot == <Self as TouchGrab<State>>::start_data(self).slot { if event.slot == <Self as TouchGrab<State>>::start_data(self).slot {
self.update_location(data, event.location); self.update_location(data, event.location);
@ -706,7 +691,7 @@ impl TouchGrab<State> for MoveGrab {
&mut self, &mut self,
data: &mut State, data: &mut State,
handle: &mut TouchInnerHandle<'_, State>, handle: &mut TouchInnerHandle<'_, State>,
event: &ShapeEvent, event: &touch::ShapeEvent,
) { ) {
handle.shape(data, event) handle.shape(data, event)
} }
@ -715,7 +700,7 @@ impl TouchGrab<State> for MoveGrab {
&mut self, &mut self,
data: &mut State, data: &mut State,
handle: &mut TouchInnerHandle<'_, State>, handle: &mut TouchInnerHandle<'_, State>,
event: &OrientationEvent, event: &touch::OrientationEvent,
) { ) {
handle.orientation(data, event) handle.orientation(data, event)
} }
@ -730,98 +715,6 @@ impl TouchGrab<State> for MoveGrab {
fn unset(&mut self, _data: &mut State) {} fn unset(&mut self, _data: &mut State) {}
} }
impl TabletToolGrab<State> for MoveGrab {
fn start_data(&self) -> &TabletGrabStartData<State> {
match &self.start_data {
GrabStartData::TabletTool { data, .. } => data,
_ => unreachable!(),
}
}
fn proximity_out(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &ProximityOutEvent,
) {
handle.proximity_out(data, event);
handle.unset_grab(self, data, event.serial, event.time, false);
}
fn motion(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
_focus: Option<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &TabletMotionEvent,
) {
handle.motion(data, None, event);
self.update_location(data, event.location);
if !self.window.alive() {
handle.unset_grab(self, data, event.serial, event.time, true);
}
}
fn down(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletDownEvent,
) {
handle.down(data, event)
}
fn up(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletUpEvent,
) {
handle.up(data, event);
handle.unset_grab(self, data, event.serial, event.time, false);
}
fn button(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletButtonEvent,
) {
handle.button(data, event)
}
fn axis(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
frame: TabletAxisFrame,
) {
handle.axis(data, frame)
}
fn frame(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
time: InputTime,
) {
handle.frame(data, time)
}
fn proximity_in(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
focus: Option<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &ProximityInEvent,
) {
handle.proximity_in(data, focus, event);
}
fn unset(&mut self, _data: &mut State) {}
}
impl MoveGrab { impl MoveGrab {
pub fn new( pub fn new(
start_data: GrabStartData, start_data: GrabStartData,
@ -885,15 +778,10 @@ impl MoveGrab {
self.previous == ManagedLayer::Tiling self.previous == ManagedLayer::Tiling
} }
pub fn grab_type(&self) -> GrabType { pub fn is_touch_grab(&self) -> bool {
self.start_data.type_() match self.start_data {
} GrabStartData::Touch(_) => true,
GrabStartData::Pointer(_) => false,
pub fn tool(&self) -> Option<&TabletToolDescriptor> {
if let GrabStartData::TabletTool { tool, .. } = &self.start_data {
Some(tool)
} else {
None
} }
} }
} }
@ -905,7 +793,7 @@ impl Drop for MoveGrab {
let seat = self.seat.clone(); let seat = self.seat.clone();
// false-positive: `Output`s hash is based on it's inner ptr // false-positive: `Output`s hash is based on it's inner ptr
#[allow(clippy::mutable_key_type)] #[allow(clippy::mutable_key_type)]
let window_outputs = std::mem::take(&mut self.window_outputs); let window_outputs = self.window_outputs.drain().collect::<HashSet<_>>();
let previous = self.previous; let previous = self.previous;
let window = self.window.clone(); let window = self.window.clone();
let is_touch_grab = matches!(self.start_data, GrabStartData::Touch(_)); let is_touch_grab = matches!(self.start_data, GrabStartData::Touch(_));
@ -1065,10 +953,10 @@ impl Drop for MoveGrab {
position.as_logical().to_f64() - window.geometry().loc.to_f64() position.as_logical().to_f64() - window.geometry().loc.to_f64()
+ offset, + offset,
)), )),
&PointerMotionEvent { &MotionEvent {
location: pointer.current_location(), location: pointer.current_location(),
serial, serial,
time: InputTime::now(), time: state.common.clock.now().as_millis(),
}, },
); );
} }

View file

@ -7,36 +7,25 @@ use crate::{
shell::{ shell::{
element::CosmicMapped, element::CosmicMapped,
focus::target::PointerFocusTarget, focus::target::PointerFocusTarget,
grabs::{GrabStartData, GrabType, ReleaseMode, ResizeEdge}, grabs::{GrabStartData, ReleaseMode, ResizeEdge},
}, },
utils::prelude::*, utils::prelude::*,
}; };
use smithay::{ use smithay::{
backend::input::{ButtonState, InputTime, TabletToolDescriptor}, backend::input::ButtonState,
desktop::{WindowSurface, space::SpaceElement}, desktop::{WindowSurface, space::SpaceElement},
input::{ input::{
Seat, Seat,
pointer::{ pointer::{
AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorIcon, AxisFrame, ButtonEvent, CursorIcon, GestureHoldBeginEvent, GestureHoldEndEvent,
GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle,
MotionEvent as PointerMotionEvent, PointerGrab, PointerInnerHandle,
RelativeMotionEvent, RelativeMotionEvent,
}, },
tablet::{
TabletSeatHandler,
tool::{
AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent,
DownEvent as TabletDownEvent, GrabStartData as TabletGrabStartData,
MotionEvent as TabletMotionEvent, ProximityInEvent, ProximityOutEvent,
TabletToolGrab, TabletToolInnerHandle, UpEvent as TabletUpEvent,
},
},
touch::{ touch::{
DownEvent as TouchDownEvent, GrabStartData as TouchGrabStartData, DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent,
MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab, OrientationEvent, ShapeEvent, TouchGrab, TouchInnerHandle, UpEvent,
TouchInnerHandle, UpEvent as TouchUpEvent,
}, },
}, },
output::Output, output::Output,
@ -181,19 +170,10 @@ impl ResizeSurfaceGrab {
false false
} }
pub fn grab_type(&self) -> GrabType { pub fn is_touch_grab(&self) -> bool {
match self.start_data { match self.start_data {
GrabStartData::Pointer(_) => GrabType::Pointer, GrabStartData::Touch(_) => true,
GrabStartData::Touch(_) => GrabType::Touch, GrabStartData::Pointer(_) => false,
GrabStartData::TabletTool { .. } => GrabType::TabletTool,
}
}
pub fn tool(&self) -> Option<&TabletToolDescriptor> {
if let GrabStartData::TabletTool { tool, .. } = &self.start_data {
Some(tool)
} else {
None
} }
} }
} }
@ -204,7 +184,7 @@ impl PointerGrab<State> for ResizeSurfaceGrab {
data: &mut State, data: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
_focus: Option<(PointerFocusTarget, Point<f64, Logical>)>, _focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &PointerMotionEvent, event: &MotionEvent,
) { ) {
// While the grab is active, no client has pointer focus // While the grab is active, no client has pointer focus
handle.motion(data, None, event); handle.motion(data, None, event);
@ -229,7 +209,7 @@ impl PointerGrab<State> for ResizeSurfaceGrab {
&mut self, &mut self,
data: &mut State, data: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
event: &PointerButtonEvent, event: &ButtonEvent,
) { ) {
handle.button(data, event); handle.button(data, event);
match self.release { match self.release {
@ -250,7 +230,7 @@ impl PointerGrab<State> for ResizeSurfaceGrab {
&mut self, &mut self,
data: &mut State, data: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
details: PointerAxisFrame, details: AxisFrame,
) { ) {
handle.axis(data, details) handle.axis(data, details)
} }
@ -349,17 +329,12 @@ impl TouchGrab<State> for ResizeSurfaceGrab {
data: &mut State, data: &mut State,
handle: &mut TouchInnerHandle<'_, State>, handle: &mut TouchInnerHandle<'_, State>,
_focus: Option<(PointerFocusTarget, Point<f64, Logical>)>, _focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &TouchDownEvent, event: &DownEvent,
) { ) {
handle.down(data, None, event) handle.down(data, None, event)
} }
fn up( fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) {
&mut self,
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
event: &TouchUpEvent,
) {
if event.slot == <Self as TouchGrab<State>>::start_data(self).slot { if event.slot == <Self as TouchGrab<State>>::start_data(self).slot {
handle.unset_grab(self, data); handle.unset_grab(self, data);
} }
@ -421,99 +396,6 @@ impl TouchGrab<State> for ResizeSurfaceGrab {
} }
} }
impl TabletToolGrab<State> for ResizeSurfaceGrab {
fn start_data(&self) -> &TabletGrabStartData<State> {
match &self.start_data {
GrabStartData::TabletTool { data, .. } => data,
_ => unreachable!(),
}
}
fn proximity_out(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &ProximityOutEvent,
) {
handle.unset_grab(self, data, event.serial, event.time, true);
handle.proximity_out(data, event);
}
fn motion(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
_focus: Option<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &TabletMotionEvent,
) {
if self.update_location(event.location.as_global()) {
handle.unset_grab(self, data, event.serial, event.time, true);
}
handle.motion(data, None, event);
}
fn down(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletDownEvent,
) {
handle.down(data, event)
}
fn up(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletUpEvent,
) {
handle.unset_grab(self, data, event.serial, event.time, true);
handle.up(data, event);
}
fn button(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletButtonEvent,
) {
handle.button(data, event)
}
fn axis(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
frame: TabletAxisFrame,
) {
handle.axis(data, frame)
}
fn frame(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
time: InputTime,
) {
handle.frame(data, time)
}
fn unset(&mut self, _data: &mut State) {
self.ungrab()
}
fn proximity_in(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
_focus: Option<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &ProximityInEvent,
) {
handle.proximity_in(data, None, event);
}
}
pub struct ResizeGrabMarker(AtomicBool); pub struct ResizeGrabMarker(AtomicBool);
impl ResizeGrabMarker { impl ResizeGrabMarker {

View file

@ -4,42 +4,31 @@ use crate::{
backend::render::cursor::CursorState, backend::render::cursor::CursorState,
shell::{ shell::{
focus::target::PointerFocusTarget, focus::target::PointerFocusTarget,
grabs::{GrabStartData, GrabType, ReleaseMode}, grabs::{GrabStartData, ReleaseMode},
layout::Orientation, layout::Orientation,
}, },
utils::prelude::*, utils::prelude::*,
}; };
use id_tree::{NodeId, Tree}; use id_tree::{NodeId, Tree};
use smithay::{ use smithay::{
backend::input::{ButtonState, InputTime, TabletToolDescriptor}, backend::input::ButtonState,
input::{ input::{
Seat, Seat,
pointer::{ pointer::{
AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorIcon, Focus, AxisFrame, ButtonEvent, CursorIcon, Focus, GestureHoldBeginEvent, GestureHoldEndEvent,
GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle,
MotionEvent as PointerMotionEvent, PointerGrab, PointerInnerHandle, PointerTarget, PointerTarget, RelativeMotionEvent,
RelativeMotionEvent,
},
tablet::{
Tablet, TabletSeatHandler, TabletSeatTrait,
tool::{
AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent,
DownEvent as TabletDownEvent, GrabStartData as TabletToolGrabStartData,
GrabTrigger as TabletToolGrabTrigger, MotionEvent as TabletMotionEvent,
ProximityInEvent, ProximityOutEvent, TabletToolGrab, TabletToolInnerHandle,
TabletToolTarget, UpEvent as TabletUpEvent,
},
}, },
touch::{ touch::{
DownEvent as TouchDownEvent, FrameMarker, GrabStartData as TouchGrabStartData, DownEvent, FrameMarker, GrabStartData as TouchGrabStartData,
MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab,
TouchInnerHandle, TouchTarget, UpEvent as TouchUpEvent, TouchInnerHandle, TouchTarget, UpEvent,
}, },
}, },
output::WeakOutput, output::WeakOutput,
utils::{IsAlive, Logical, Point, Serial}, utils::{IsAlive, Logical, Point},
}; };
use super::super::{Data, TilingLayout}; use super::super::{Data, TilingLayout};
@ -59,7 +48,7 @@ impl IsAlive for ResizeForkTarget {
} }
impl PointerTarget<State> for ResizeForkTarget { impl PointerTarget<State> for ResizeForkTarget {
fn enter(&self, seat: &Seat<State>, _data: &mut State, _event: &PointerMotionEvent) { fn enter(&self, seat: &Seat<State>, _data: &mut State, _event: &MotionEvent) {
let user_data = seat.user_data(); let user_data = seat.user_data();
let cursor_state = user_data.get::<CursorState>().unwrap(); let cursor_state = user_data.get::<CursorState>().unwrap();
cursor_state cursor_state
@ -71,13 +60,19 @@ impl PointerTarget<State> for ResizeForkTarget {
}); });
} }
fn leave(&self, seat: &Seat<State>, _data: &mut State, _serial: Serial, _time: InputTime) { fn leave(
&self,
seat: &Seat<State>,
_data: &mut State,
_serial: smithay::utils::Serial,
_time: u32,
) {
let user_data = seat.user_data(); let user_data = seat.user_data();
let cursor_state = user_data.get::<CursorState>().unwrap(); let cursor_state = user_data.get::<CursorState>().unwrap();
cursor_state.lock().unwrap().unset_shape(); cursor_state.lock().unwrap().unset_shape();
} }
fn button(&self, seat: &Seat<State>, data: &mut State, event: &PointerButtonEvent) { fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) {
if event.button == 0x110 && event.state == ButtonState::Pressed { if event.button == 0x110 && event.state == ButtonState::Pressed {
let seat = seat.clone(); let seat = seat.clone();
let node = self.node.clone(); let node = self.node.clone();
@ -111,7 +106,7 @@ impl PointerTarget<State> for ResizeForkTarget {
} }
} }
fn motion(&self, _seat: &Seat<State>, _data: &mut State, _event: &PointerMotionEvent) {} fn motion(&self, _seat: &Seat<State>, _data: &mut State, _event: &MotionEvent) {}
fn relative_motion( fn relative_motion(
&self, &self,
_seat: &Seat<State>, _seat: &Seat<State>,
@ -119,7 +114,7 @@ impl PointerTarget<State> for ResizeForkTarget {
_event: &RelativeMotionEvent, _event: &RelativeMotionEvent,
) { ) {
} }
fn axis(&self, _seat: &Seat<State>, _data: &mut State, _frame: PointerAxisFrame) {} fn axis(&self, _seat: &Seat<State>, _data: &mut State, _frame: AxisFrame) {}
fn frame(&self, _seat: &Seat<State>, _data: &mut State) {} fn frame(&self, _seat: &Seat<State>, _data: &mut State) {}
fn gesture_swipe_begin(&self, _: &Seat<State>, _: &mut State, _: &GestureSwipeBeginEvent) {} fn gesture_swipe_begin(&self, _: &Seat<State>, _: &mut State, _: &GestureSwipeBeginEvent) {}
fn gesture_swipe_update(&self, _: &Seat<State>, _: &mut State, _: &GestureSwipeUpdateEvent) {} fn gesture_swipe_update(&self, _: &Seat<State>, _: &mut State, _: &GestureSwipeUpdateEvent) {}
@ -132,7 +127,7 @@ impl PointerTarget<State> for ResizeForkTarget {
} }
impl TouchTarget<State> for ResizeForkTarget { impl TouchTarget<State> for ResizeForkTarget {
fn down(&self, seat: &Seat<State>, data: &mut State, event: &TouchDownEvent) { fn down(&self, seat: &Seat<State>, data: &mut State, event: &DownEvent) {
let seat = seat.clone(); let seat = seat.clone();
let node = self.node.clone(); let node = self.node.clone();
let output = self.output.clone(); let output = self.output.clone();
@ -163,7 +158,7 @@ impl TouchTarget<State> for ResizeForkTarget {
}); });
} }
fn up(&self, _seat: &Seat<State>, _data: &mut State, _event: &TouchUpEvent) {} fn up(&self, _seat: &Seat<State>, _data: &mut State, _event: &UpEvent) {}
fn motion(&self, _seat: &Seat<State>, _data: &mut State, _event: &TouchMotionEvent) {} fn motion(&self, _seat: &Seat<State>, _data: &mut State, _event: &TouchMotionEvent) {}
fn frame(&self, _seat: &Seat<State>, _data: &mut State, _frame: FrameMarker) {} fn frame(&self, _seat: &Seat<State>, _data: &mut State, _frame: FrameMarker) {}
fn cancel(&self, _seat: &Seat<State>, _data: &mut State, _frame: FrameMarker) {} fn cancel(&self, _seat: &Seat<State>, _data: &mut State, _frame: FrameMarker) {}
@ -174,121 +169,6 @@ impl TouchTarget<State> for ResizeForkTarget {
} }
} }
impl TabletToolTarget<State> for ResizeForkTarget {
fn down(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &TabletDownEvent,
) {
let seat = seat.clone();
let node = self.node.clone();
let output = self.output.clone();
let left_up_idx = self.left_up_idx;
let orientation = self.orientation;
let serial = event.serial;
let time = event.time;
let tool = tool_descriptor.clone();
data.common.event_loop_handle.insert_idle(move |state| {
let pointer = seat.get_pointer().unwrap();
let location = pointer.current_location();
let tablet = seat.tablet_seat().get_tool(&tool).unwrap();
tablet.set_grab(
state,
ResizeForkGrab::new(
GrabStartData::TabletTool {
tool,
data: TabletToolGrabStartData {
focus: None,
location,
trigger: TabletToolGrabTrigger::Tip,
},
},
location.as_global(),
node,
left_up_idx,
orientation,
output,
ReleaseMode::NoMouseButtons,
),
time,
serial,
Focus::Keep,
)
});
}
fn motion(
&self,
_seat: &Seat<State>,
_data: &mut State,
_tool_descriptor: &TabletToolDescriptor,
_event: &TabletMotionEvent,
) {
}
fn proximity_out(
&self,
seat: &Seat<State>,
_data: &mut State,
_tool_descriptor: &TabletToolDescriptor,
) {
let user_data = seat.user_data();
let cursor_state = user_data.get::<CursorState>().unwrap();
cursor_state.lock().unwrap().unset_shape();
}
fn proximity_in(
&self,
seat: &Seat<State>,
_data: &mut State,
_tool_descriptor: &TabletToolDescriptor,
_tablet: &Tablet,
_serial: Serial,
) {
let user_data = seat.user_data();
let cursor_state = user_data.get::<CursorState>().unwrap();
cursor_state
.lock()
.unwrap()
.set_shape(match self.orientation {
Orientation::Horizontal => CursorIcon::RowResize,
Orientation::Vertical => CursorIcon::ColResize,
});
}
fn up(
&self,
_seat: &Seat<State>,
_data: &mut State,
_tool_descriptor: &TabletToolDescriptor,
_event: &TabletUpEvent,
) {
}
fn axis(
&self,
_seat: &Seat<State>,
_data: &mut State,
_tool_descriptor: &TabletToolDescriptor,
_frame: TabletAxisFrame,
) {
}
fn button(
&self,
_seat: &Seat<State>,
_data: &mut State,
_tool_descriptor: &TabletToolDescriptor,
_event: &TabletButtonEvent,
) {
}
fn frame(
&self,
_seat: &Seat<State>,
_data: &mut State,
_tool_descriptor: &TabletToolDescriptor,
_time: InputTime,
) {
}
}
pub struct ResizeForkGrab { pub struct ResizeForkGrab {
start_data: GrabStartData, start_data: GrabStartData,
last_loc: Point<f64, Global>, last_loc: Point<f64, Global>,
@ -458,19 +338,10 @@ impl ResizeForkGrab {
false false
} }
pub fn grab_type(&self) -> GrabType { pub fn is_touch_grab(&self) -> bool {
match self.start_data { match self.start_data {
GrabStartData::Pointer(_) => GrabType::Pointer, GrabStartData::Touch(_) => true,
GrabStartData::Touch(_) => GrabType::Touch, GrabStartData::Pointer(_) => false,
GrabStartData::TabletTool { .. } => GrabType::TabletTool,
}
}
pub fn tool(&self) -> Option<&TabletToolDescriptor> {
if let GrabStartData::TabletTool { tool, .. } = &self.start_data {
Some(tool)
} else {
None
} }
} }
} }
@ -481,7 +352,7 @@ impl PointerGrab<State> for ResizeForkGrab {
data: &mut State, data: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
_focus: Option<(PointerFocusTarget, Point<f64, Logical>)>, _focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &PointerMotionEvent, event: &MotionEvent,
) { ) {
// While the grab is active, no client has pointer focus // While the grab is active, no client has pointer focus
handle.motion(data, None, event); handle.motion(data, None, event);
@ -506,7 +377,7 @@ impl PointerGrab<State> for ResizeForkGrab {
&mut self, &mut self,
data: &mut State, data: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
event: &PointerButtonEvent, event: &ButtonEvent,
) { ) {
handle.button(data, event); handle.button(data, event);
match self.release { match self.release {
@ -527,7 +398,7 @@ impl PointerGrab<State> for ResizeForkGrab {
&mut self, &mut self,
data: &mut State, data: &mut State,
handle: &mut PointerInnerHandle<'_, State>, handle: &mut PointerInnerHandle<'_, State>,
details: PointerAxisFrame, details: AxisFrame,
) { ) {
handle.axis(data, details) handle.axis(data, details)
} }
@ -626,17 +497,12 @@ impl TouchGrab<State> for ResizeForkGrab {
data: &mut State, data: &mut State,
handle: &mut TouchInnerHandle<'_, State>, handle: &mut TouchInnerHandle<'_, State>,
_focus: Option<(PointerFocusTarget, Point<f64, Logical>)>, _focus: Option<(PointerFocusTarget, Point<f64, Logical>)>,
event: &TouchDownEvent, event: &DownEvent,
) { ) {
handle.down(data, None, event) handle.down(data, None, event)
} }
fn up( fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) {
&mut self,
data: &mut State,
handle: &mut TouchInnerHandle<'_, State>,
event: &TouchUpEvent,
) {
if event.slot == <Self as TouchGrab<State>>::start_data(self).slot { if event.slot == <Self as TouchGrab<State>>::start_data(self).slot {
handle.unset_grab(self, data); handle.unset_grab(self, data);
} }
@ -697,96 +563,3 @@ impl TouchGrab<State> for ResizeForkGrab {
self.update_location(data, self.last_loc.as_logical(), true); self.update_location(data, self.last_loc.as_logical(), true);
} }
} }
impl TabletToolGrab<State> for ResizeForkGrab {
fn start_data(&self) -> &TabletToolGrabStartData<State> {
match &self.start_data {
GrabStartData::TabletTool { data, .. } => data,
_ => unreachable!(),
}
}
fn proximity_out(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &ProximityOutEvent,
) {
handle.proximity_out(data, event);
handle.unset_grab(self, data, event.serial, event.time, true);
}
fn motion(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
_focus: Option<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &TabletMotionEvent,
) {
handle.motion(data, None, event);
if self.update_location(data, event.location, false) {
handle.unset_grab(self, data, event.serial, event.time, true);
}
}
fn down(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletDownEvent,
) {
handle.down(data, event);
}
fn up(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletUpEvent,
) {
handle.up(data, event);
handle.unset_grab(self, data, event.serial, event.time, true);
}
fn button(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
event: &TabletButtonEvent,
) {
handle.button(data, event)
}
fn axis(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
frame: TabletAxisFrame,
) {
handle.axis(data, frame)
}
fn frame(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
time: InputTime,
) {
handle.frame(data, time)
}
fn unset(&mut self, data: &mut State) {
self.update_location(data, self.last_loc.as_logical(), true);
}
fn proximity_in(
&mut self,
data: &mut State,
handle: &mut TabletToolInnerHandle<'_, State>,
focus: Option<(<State as TabletSeatHandler>::ToolFocus, Point<f64, Logical>)>,
event: &ProximityInEvent,
) {
handle.proximity_in(data, focus, event);
}
}

View file

@ -1,6 +1,6 @@
use cosmic_settings_config::shortcuts; use cosmic_settings_config::shortcuts;
use smithay::{ use smithay::{
backend::input::{InputTime, KeyState, Keycode}, backend::input::{KeyState, Keycode},
input::{ input::{
Seat, SeatHandler, Seat, SeatHandler,
keyboard::{ keyboard::{
@ -38,7 +38,7 @@ impl KeyboardGrab<State> for SwapWindowGrab {
state: KeyState, state: KeyState,
modifiers: Option<ModifiersState>, modifiers: Option<ModifiersState>,
serial: Serial, serial: Serial,
time: InputTime, time: u32,
) { ) {
if !matches!(&data.common.shell.read().overview_mode.active_trigger(), Some(Trigger::KeyboardSwap(_, d)) if d == &self.desc) if !matches!(&data.common.shell.read().overview_mode.active_trigger(), Some(Trigger::KeyboardSwap(_, d)) if d == &self.desc)
{ {

View file

@ -3271,34 +3271,12 @@ impl TilingLayout {
} }
} }
let (_, inner) = self.gaps();
let mut result = None; let mut result = None;
let mut fork = None;
let mut lookup = Some(root.clone()); let mut lookup = Some(root.clone());
while let Some(node) = lookup { while let Some(node) = lookup {
let data = tree.get(&node).unwrap().data(); let data = tree.get(&node).unwrap().data();
if data.geometry().contains(location) { if data.geometry().contains(location) {
result = Some(node.clone()); result = Some(node.clone());
if let Data::Group {
orientation,
sizes,
last_geometry,
..
} = data
{
let (pos, mut split) = match orientation {
Orientation::Vertical => (location.x, last_geometry.loc.x),
Orientation::Horizontal => (location.y, last_geometry.loc.y),
};
for (idx, size) in
sizes.iter().take(sizes.len().saturating_sub(1)).enumerate()
{
split += size;
if (pos - split).abs() <= inner / 2 {
fork = Some((node.clone(), idx));
}
}
}
} }
lookup = None; lookup = None;
@ -3345,16 +3323,25 @@ impl TilingLayout {
) )
}) })
} }
Some((_, Data::Group { .. })) => { Some((
let (id, idx) = fork?; id,
let Data::Group { Data::Group {
orientation, orientation,
last_geometry, last_geometry,
.. ..
} = tree.get(&id).unwrap().data().clone() },
else { )) => {
unreachable!() let idx = tree
}; .children(&id)
.unwrap()
.position(|node| {
let data = node.data();
match orientation {
Orientation::Vertical => location.x < data.geometry().loc.x,
Orientation::Horizontal => location.y < data.geometry().loc.y,
}
})
.and_then(|x| x.checked_sub(1))?;
Some(( Some((
ResizeForkTarget { ResizeForkTarget {
node: id.clone(), node: id.clone(),
@ -3394,7 +3381,7 @@ impl TilingLayout {
let Some(root) = tree.root_node_id() else { let Some(root) = tree.root_node_id() else {
if matches!( if matches!(
overview.active_trigger(), overview.active_trigger(),
Some(Trigger::Pointer(_) | Trigger::Touch(_) | Trigger::Tool(_, _)) Some(Trigger::Pointer(_) | Trigger::Touch(_))
) && location_f64.is_some() ) && location_f64.is_some()
{ {
let mut tree = tree.copy_clone(); let mut tree = tree.copy_clone();
@ -3427,7 +3414,7 @@ impl TilingLayout {
if matches!( if matches!(
overview.active_trigger(), overview.active_trigger(),
Some(Trigger::Pointer(_) | Trigger::Touch(_) | Trigger::Tool(_, _)) Some(Trigger::Pointer(_) | Trigger::Touch(_))
) { ) {
let non_exclusive_zone = layer_map_for_output(&self.output) let non_exclusive_zone = layer_map_for_output(&self.output)
.non_exclusive_zone() .non_exclusive_zone()
@ -4075,11 +4062,8 @@ impl TilingLayout {
let draw_groups = overview.0.alpha(); let draw_groups = overview.0.alpha();
let is_overview = !matches!(overview.0, OverviewMode::None); let is_overview = !matches!(overview.0, OverviewMode::None);
let is_mouse_tiling = (matches!( let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_))))
overview.0.trigger(), .then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone));
Some(Trigger::Pointer(_) | Trigger::Tool(_, _))
))
.then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone));
let swap_desc = if let Some(Trigger::KeyboardSwap(_, desc)) = overview.0.trigger() { let swap_desc = if let Some(Trigger::KeyboardSwap(_, desc)) = overview.0.trigger() {
Some(desc.clone()) Some(desc.clone())
} else { } else {
@ -4232,11 +4216,8 @@ impl TilingLayout {
}; };
let draw_groups = overview.0.alpha(); let draw_groups = overview.0.alpha();
let is_mouse_tiling = (matches!( let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_))))
overview.0.trigger(), .then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone));
Some(Trigger::Pointer(_) | Trigger::Tool(_, _))
))
.then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone));
let swap_desc = if let Some(Trigger::KeyboardSwap(_, desc)) = overview.0.trigger() { let swap_desc = if let Some(Trigger::KeyboardSwap(_, desc)) = overview.0.trigger() {
Some(desc.clone()) Some(desc.clone())
} else { } else {

View file

@ -19,10 +19,7 @@ use crate::{
utils, utils,
wayland::{ wayland::{
handlers::data_device::{self, get_dnd_icon}, handlers::data_device::{self, get_dnd_icon},
protocols::{ protocols::workspace::{State as WState, WorkspaceCapabilities},
session_lock_layer::layer_show_on_lock,
workspace::{State as WState, WorkspaceCapabilities},
},
}, },
}; };
use cosmic_comp_config::{ use cosmic_comp_config::{
@ -35,10 +32,7 @@ use cosmic_settings_config::shortcuts::action::{Direction, FocusDirection, Resiz
use cosmic_settings_config::{shortcuts, window_rules::ApplicationException}; use cosmic_settings_config::{shortcuts, window_rules::ApplicationException};
use keyframe::{ease, functions::EaseInOutCubic}; use keyframe::{ease, functions::EaseInOutCubic};
use smithay::{ use smithay::{
backend::{ backend::{input::TouchSlot, renderer::element::RenderElementStates},
input::{TabletToolDescriptor, TouchSlot},
renderer::element::RenderElementStates,
},
desktop::{ desktop::{
LayerSurface, PopupKind, WindowSurface, WindowSurfaceType, layer_map_for_output, LayerSurface, PopupKind, WindowSurface, WindowSurfaceType, layer_map_for_output,
space::SpaceElement, space::SpaceElement,
@ -52,7 +46,6 @@ use smithay::{
pointer::{ pointer::{
CursorImageStatus, CursorImageSurfaceData, Focus, GrabStartData as PointerGrabStartData, CursorImageStatus, CursorImageSurfaceData, Focus, GrabStartData as PointerGrabStartData,
}, },
tablet::{TabletSeatTrait, tool::GrabTrigger as TabletGrabTrigger},
}, },
output::{Output, WeakOutput}, output::{Output, WeakOutput},
reexports::{ reexports::{
@ -137,7 +130,6 @@ pub enum Trigger {
KeyboardMove(shortcuts::Modifiers), KeyboardMove(shortcuts::Modifiers),
Pointer(u32), Pointer(u32),
Touch(TouchSlot), Touch(TouchSlot),
Tool(TabletToolDescriptor, TabletGrabTrigger),
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -262,7 +254,6 @@ pub struct PendingWindow {
pub surface: CosmicSurface, pub surface: CosmicSurface,
pub seat: Seat<State>, pub seat: Seat<State>,
pub fullscreen: Option<Output>, pub fullscreen: Option<Output>,
pub minimized: bool,
pub maximized: bool, pub maximized: bool,
pub sticky: bool, pub sticky: bool,
} }
@ -516,12 +507,6 @@ impl WorkspaceSet {
} }
} }
fn refresh_focus_stacks(&mut self) {
for workspace in &mut self.workspaces {
workspace.refresh_focus_stack();
}
}
fn activate( fn activate(
&mut self, &mut self,
idx: usize, idx: usize,
@ -626,7 +611,6 @@ impl WorkspaceSet {
self.workspaces[self.active].refresh(); self.workspaces[self.active].refresh();
} }
self.sticky_layer.refresh(); self.sticky_layer.refresh();
self.refresh_focus_stacks();
} }
fn add_empty_workspace(&mut self, state: &mut WorkspaceUpdateGuard<State>) { fn add_empty_workspace(&mut self, state: &mut WorkspaceUpdateGuard<State>) {
@ -1770,7 +1754,7 @@ impl Shell {
if let Some(set) = self.workspaces.sets.get_mut(output) { if let Some(set) = self.workspaces.sets.get_mut(output) {
if matches!( if matches!(
self.overview_mode.active_trigger(), self.overview_mode.active_trigger(),
Some(Trigger::Pointer(_) | Trigger::Touch(_) | Trigger::Tool(_, _)) Some(Trigger::Pointer(_) | Trigger::Touch(_))
) { ) {
set.workspaces[set.active].tiling_layer.cleanup_drag(); set.workspaces[set.active].tiling_layer.cleanup_drag();
} }
@ -1821,7 +1805,7 @@ impl Shell {
if let Some(set) = self.workspaces.sets.get_mut(output) { if let Some(set) = self.workspaces.sets.get_mut(output) {
if matches!( if matches!(
self.overview_mode.active_trigger(), self.overview_mode.active_trigger(),
Some(Trigger::Pointer(_) | Trigger::Touch(_) | Trigger::Tool(_, _)) Some(Trigger::Pointer(_) | Trigger::Touch(_))
) { ) {
set.workspaces[set.active].tiling_layer.cleanup_drag(); set.workspaces[set.active].tiling_layer.cleanup_drag();
} }
@ -2056,27 +2040,12 @@ impl Shell {
} }
pub fn visible_output_for_surface(&self, surface: &WlSurface) -> Option<&Output> { pub fn visible_output_for_surface(&self, surface: &WlSurface) -> Option<&Output> {
// NOTE: Keep in sync with surface iteration in `render_input_order_internal`
if let Some(session_lock) = &self.session_lock { if let Some(session_lock) = &self.session_lock {
if let Some((output, _)) = session_lock return session_lock
.surfaces .surfaces
.iter() .iter()
.find(|(_, v)| v.wl_surface() == surface) .find(|(_, v)| v.wl_surface() == surface)
{ .map(|(k, _)| k);
return Some(output);
}
for o in self.outputs() {
let map = layer_map_for_output(o);
if let Some(layer_surface) = map.layer_for_surface(surface, WindowSurfaceType::ALL)
{
if layer_show_on_lock(layer_surface.wl_surface()) {
return Some(o);
} else {
return None;
}
}
}
} }
self.outputs() self.outputs()
@ -2887,7 +2856,6 @@ impl Shell {
surface: window, surface: window,
seat, seat,
fullscreen: output, fullscreen: output,
minimized: should_be_minimized,
maximized: should_be_maximized, maximized: should_be_maximized,
sticky: mut should_be_sticky, sticky: mut should_be_sticky,
} = self.pending_windows.remove(pos); } = self.pending_windows.remove(pos);
@ -2971,7 +2939,6 @@ impl Shell {
if let Some(FocusTarget::Window(focused)) = maybe_focused if let Some(FocusTarget::Window(focused)) = maybe_focused
&& let Some(stack) = focused.stack_ref() && let Some(stack) = focused.stack_ref()
&& !is_dialog && !is_dialog
&& !should_be_minimized
&& !should_be_maximized && !should_be_maximized
&& !(workspace.is_tiled(&focused.active_window()) && floating_exception) && !(workspace.is_tiled(&focused.active_window()) && floating_exception)
{ {
@ -3021,13 +2988,8 @@ impl Shell {
self.maximize_request(&mapped, &seat, false, loop_handle); self.maximize_request(&mapped, &seat, false, loop_handle);
} }
if should_be_minimized { let new_target = if (workspace_output == seat.active_output()
self.minimize_request(&window); && active_handle == workspace_handle)
}
let new_target = if should_be_minimized {
None
} else if (workspace_output == seat.active_output() && active_handle == workspace_handle)
|| should_be_sticky || should_be_sticky
{ {
// TODO: enforce focus stealing prevention by also checking the same rules as for the else case. // TODO: enforce focus stealing prevention by also checking the same rules as for the else case.
@ -3151,7 +3113,6 @@ impl Shell {
surface, surface,
seat: seat.clone(), seat: seat.clone(),
fullscreen: None, fullscreen: None,
minimized: false,
maximized: false, maximized: false,
sticky: false, sticky: false,
}); });
@ -3870,7 +3831,6 @@ impl Shell {
let trigger = match &start_data { let trigger = match &start_data {
GrabStartData::Pointer(start_data) => Trigger::Pointer(start_data.button), GrabStartData::Pointer(start_data) => Trigger::Pointer(start_data.button),
GrabStartData::Touch(start_data) => Trigger::Touch(start_data.slot), GrabStartData::Touch(start_data) => Trigger::Touch(start_data.slot),
GrabStartData::TabletTool { tool, data } => Trigger::Tool(tool.clone(), data.trigger),
}; };
let active_hint = if config.cosmic_conf.active_hint { let active_hint = if config.cosmic_conf.active_hint {
self.theme.cosmic().active_hint as u8 self.theme.cosmic().active_hint as u8
@ -5189,19 +5149,10 @@ pub fn check_grab_preconditions(
let pointer = seat.get_pointer().unwrap(); let pointer = seat.get_pointer().unwrap();
let touch = seat.get_touch().unwrap(); let touch = seat.get_touch().unwrap();
let tablet = seat.tablet_seat();
let tools = tablet.get_tools();
let start_data = let start_data =
if serial.is_some_and(|serial| touch.has_grab(serial)) { if serial.is_some_and(|serial| touch.has_grab(serial)) {
GrabStartData::Touch(touch.grab_start_data().unwrap()) GrabStartData::Touch(touch.grab_start_data().unwrap())
} else if let Some((desc, tool)) =
serial.and_then(|serial| tools.iter().find(|(_, tool)| tool.has_grab(serial)))
{
GrabStartData::TabletTool {
tool: desc.clone(),
data: tool.grab_start_data().unwrap(),
}
} else { } else {
GrabStartData::Pointer(pointer.grab_start_data().unwrap_or_else(|| { GrabStartData::Pointer(pointer.grab_start_data().unwrap_or_else(|| {
PointerGrabStartData { PointerGrabStartData {
@ -5215,16 +5166,8 @@ pub fn check_grab_preconditions(
if let Some(surface) = client_initiated { if let Some(surface) = client_initiated {
// Check that this surface has a click or touch down grab. // Check that this surface has a click or touch down grab.
if !match serial { if !match serial {
Some(serial) => { Some(serial) => pointer.has_grab(serial) || touch.has_grab(serial),
pointer.has_grab(serial) None => pointer.is_grabbed() | touch.is_grabbed(),
|| touch.has_grab(serial)
|| tools.values().any(|tool| tool.has_grab(serial))
}
None => {
pointer.is_grabbed()
|| touch.is_grabbed()
|| tools.values().any(|tool| tool.is_grabbed())
}
} { } {
return None; return None;
} }

View file

@ -526,16 +526,10 @@ impl Workspace {
.mapped() .mapped()
.chain(self.tiling_layer.mapped().map(|(w, _)| w)) .chain(self.tiling_layer.mapped().map(|(w, _)| w))
.chain(move_mapped.iter()) .chain(move_mapped.iter())
.chain(
self.minimized_windows
.iter()
.flat_map(MinimizedWindow::mapped),
)
}; };
stack.retain(|w| match w { stack.retain(|w| match w {
FocusTarget::Fullscreen(s) => fullscreen_surfaces.contains(&s), FocusTarget::Fullscreen(s) => fullscreen_surfaces.contains(&s),
// Sticky windows live in the `WorkspaceSet` but are shown on whichever workspace is current FocusTarget::Window(w) => mapped().any(|m| w == m),
FocusTarget::Window(w) => w.is_sticky() || mapped().any(|m| w == m),
}); });
} }
} }
@ -1773,17 +1767,13 @@ impl Workspace {
self.floating_layer.render( self.floating_layer.render(
renderer, renderer,
render_focus focused.as_ref().and_then(|target| {
.then(|| { if let FocusTarget::Window(mapped) = target {
focused.as_ref().and_then(|target| { Some(mapped)
if let FocusTarget::Window(mapped) = target { } else {
Some(mapped) None
} else { }
None }),
}
})
})
.flatten(),
resize_indicator.clone(), resize_indicator.clone(),
indicator_thickness, indicator_thickness,
alpha, alpha,

View file

@ -11,31 +11,19 @@ use cosmic_comp_config::{ZoomConfig, ZoomMovement};
use cosmic_config::ConfigSet; use cosmic_config::ConfigSet;
use keyframe::{ease, functions::Linear}; use keyframe::{ease, functions::Linear};
use smithay::{ use smithay::{
backend::{ backend::renderer::ImportMem,
input::{InputTime, TabletToolDescriptor},
renderer::ImportMem,
},
desktop::space::SpaceElement, desktop::space::SpaceElement,
input::{ input::{
Seat, Seat,
pointer::{ pointer::{
AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, Focus, AxisFrame, ButtonEvent, Focus, GestureHoldBeginEvent, GestureHoldEndEvent,
GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, MotionEvent as PointerMotionEvent, PointerTarget, RelativeMotionEvent,
PointerTarget, RelativeMotionEvent,
},
tablet::{
Tablet, TabletSeatTrait,
tool::{
AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent,
DownEvent as TabletDownEvent, MotionEvent as TabletMotionEvent, TabletToolTarget,
UpEvent as TabletUpEvent,
},
}, },
touch::{ touch::{
DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent,
OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, TouchTarget, UpEvent,
}, },
}, },
output::Output, output::Output,
@ -45,7 +33,6 @@ use tracing::error;
use crate::{ use crate::{
backend::render::element::AsGlowRenderer, backend::render::element::AsGlowRenderer,
shell::grabs::GrabType,
state::State, state::State,
utils::{ utils::{
iced::{IcedElement, IcedRenderElement, Program}, iced::{IcedElement, IcedRenderElement, Program},
@ -712,27 +699,15 @@ impl Program for ZoomProgram {
); );
std::mem::drop(shell); std::mem::drop(shell);
match grab.grab_type() { if grab.is_touch_grab() {
GrabType::Touch => { seat.get_touch().unwrap().set_grab(state, grab, serial);
seat.get_touch().unwrap().set_grab(state, grab, serial) } else {
} seat.get_pointer().unwrap().set_grab(
GrabType::Pointer => seat.get_pointer().unwrap().set_grab(
state, state,
grab, grab,
serial, serial,
Focus::Clear, Focus::Clear,
), );
GrabType::TabletTool => seat
.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(
state,
grab,
InputTime::now(),
serial,
Focus::Clear,
),
} }
} }
} }
@ -811,27 +786,15 @@ impl Program for ZoomProgram {
); );
std::mem::drop(shell); std::mem::drop(shell);
match grab.grab_type() { if grab.is_touch_grab() {
GrabType::Touch => { seat.get_touch().unwrap().set_grab(state, grab, serial);
seat.get_touch().unwrap().set_grab(state, grab, serial) } else {
} seat.get_pointer().unwrap().set_grab(
GrabType::Pointer => seat.get_pointer().unwrap().set_grab(
state, state,
grab, grab,
serial, serial,
Focus::Clear, Focus::Clear,
), );
GrabType::TabletTool => seat
.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(
state,
grab,
InputTime::now(),
serial,
Focus::Clear,
),
} }
} }
} }
@ -921,14 +884,14 @@ impl PointerTarget<State> for ZoomFocusTarget {
} }
} }
fn button(&self, seat: &Seat<State>, data: &mut State, event: &PointerButtonEvent) { fn button(&self, seat: &Seat<State>, data: &mut State, event: &ButtonEvent) {
match self { match self {
ZoomFocusTarget::Main(elem) => PointerTarget::button(elem, seat, data, event), ZoomFocusTarget::Main(elem) => PointerTarget::button(elem, seat, data, event),
ZoomFocusTarget::Menu(elem) => PointerTarget::button(elem, seat, data, event), ZoomFocusTarget::Menu(elem) => PointerTarget::button(elem, seat, data, event),
} }
} }
fn axis(&self, seat: &Seat<State>, data: &mut State, frame: PointerAxisFrame) { fn axis(&self, seat: &Seat<State>, data: &mut State, frame: AxisFrame) {
match self { match self {
ZoomFocusTarget::Main(elem) => PointerTarget::axis(elem, seat, data, frame), ZoomFocusTarget::Main(elem) => PointerTarget::axis(elem, seat, data, frame),
ZoomFocusTarget::Menu(elem) => PointerTarget::axis(elem, seat, data, frame), ZoomFocusTarget::Menu(elem) => PointerTarget::axis(elem, seat, data, frame),
@ -1061,7 +1024,7 @@ impl PointerTarget<State> for ZoomFocusTarget {
} }
} }
fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: InputTime) { fn leave(&self, seat: &Seat<State>, data: &mut State, serial: Serial, time: u32) {
match self { match self {
ZoomFocusTarget::Main(elem) => PointerTarget::leave(elem, seat, data, serial, time), ZoomFocusTarget::Main(elem) => PointerTarget::leave(elem, seat, data, serial, time),
ZoomFocusTarget::Menu(elem) => PointerTarget::leave(elem, seat, data, serial, time), ZoomFocusTarget::Menu(elem) => PointerTarget::leave(elem, seat, data, serial, time),
@ -1070,14 +1033,14 @@ impl PointerTarget<State> for ZoomFocusTarget {
} }
impl TouchTarget<State> for ZoomFocusTarget { impl TouchTarget<State> for ZoomFocusTarget {
fn down(&self, seat: &Seat<State>, data: &mut State, event: &TouchDownEvent) { fn down(&self, seat: &Seat<State>, data: &mut State, event: &DownEvent) {
match self { match self {
ZoomFocusTarget::Main(elem) => TouchTarget::down(elem, seat, data, event), ZoomFocusTarget::Main(elem) => TouchTarget::down(elem, seat, data, event),
ZoomFocusTarget::Menu(elem) => TouchTarget::down(elem, seat, data, event), ZoomFocusTarget::Menu(elem) => TouchTarget::down(elem, seat, data, event),
} }
} }
fn up(&self, seat: &Seat<State>, data: &mut State, event: &TouchUpEvent) { fn up(&self, seat: &Seat<State>, data: &mut State, event: &UpEvent) {
match self { match self {
ZoomFocusTarget::Main(elem) => TouchTarget::up(elem, seat, data, event), ZoomFocusTarget::Main(elem) => TouchTarget::up(elem, seat, data, event),
ZoomFocusTarget::Menu(elem) => TouchTarget::up(elem, seat, data, event), ZoomFocusTarget::Menu(elem) => TouchTarget::up(elem, seat, data, event),
@ -1127,144 +1090,6 @@ impl TouchTarget<State> for ZoomFocusTarget {
} }
} }
impl TabletToolTarget<State> for ZoomFocusTarget {
fn proximity_in(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
tablet: &Tablet,
serial: Serial,
) {
match self {
ZoomFocusTarget::Main(elem) => {
TabletToolTarget::proximity_in(elem, seat, data, tool_descriptor, tablet, serial)
}
ZoomFocusTarget::Menu(elem) => {
TabletToolTarget::proximity_in(elem, seat, data, tool_descriptor, tablet, serial)
}
}
}
fn proximity_out(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
) {
match self {
ZoomFocusTarget::Main(elem) => {
TabletToolTarget::proximity_out(elem, seat, data, tool_descriptor)
}
ZoomFocusTarget::Menu(elem) => {
TabletToolTarget::proximity_out(elem, seat, data, tool_descriptor)
}
}
}
fn down(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &TabletDownEvent,
) {
match self {
ZoomFocusTarget::Main(elem) => {
TabletToolTarget::down(elem, seat, data, tool_descriptor, event)
}
ZoomFocusTarget::Menu(elem) => {
TabletToolTarget::down(elem, seat, data, tool_descriptor, event)
}
}
}
fn up(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &TabletUpEvent,
) {
match self {
ZoomFocusTarget::Main(elem) => {
TabletToolTarget::up(elem, seat, data, tool_descriptor, event)
}
ZoomFocusTarget::Menu(elem) => {
TabletToolTarget::up(elem, seat, data, tool_descriptor, event)
}
}
}
fn motion(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &TabletMotionEvent,
) {
match self {
ZoomFocusTarget::Main(elem) => {
TabletToolTarget::motion(elem, seat, data, tool_descriptor, event)
}
ZoomFocusTarget::Menu(elem) => {
TabletToolTarget::motion(elem, seat, data, tool_descriptor, event)
}
}
}
fn axis(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
frame: TabletAxisFrame,
) {
match self {
ZoomFocusTarget::Main(elem) => {
TabletToolTarget::axis(elem, seat, data, tool_descriptor, frame)
}
ZoomFocusTarget::Menu(elem) => {
TabletToolTarget::axis(elem, seat, data, tool_descriptor, frame)
}
}
}
fn button(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
event: &TabletButtonEvent,
) {
match self {
ZoomFocusTarget::Main(elem) => {
TabletToolTarget::button(elem, seat, data, tool_descriptor, event)
}
ZoomFocusTarget::Menu(elem) => {
TabletToolTarget::button(elem, seat, data, tool_descriptor, event)
}
}
}
fn frame(
&self,
seat: &Seat<State>,
data: &mut State,
tool_descriptor: &TabletToolDescriptor,
time: InputTime,
) {
match self {
ZoomFocusTarget::Main(elem) => {
TabletToolTarget::frame(elem, seat, data, tool_descriptor, time)
}
ZoomFocusTarget::Menu(elem) => {
TabletToolTarget::frame(elem, seat, data, tool_descriptor, time)
}
}
}
}
impl IsAlive for ZoomFocusTarget { impl IsAlive for ZoomFocusTarget {
fn alive(&self) -> bool { fn alive(&self) -> bool {
match self { match self {

View file

@ -23,7 +23,6 @@ use crate::{
output_configuration::OutputConfigurationState, output_configuration::OutputConfigurationState,
output_power::OutputPowerState, output_power::OutputPowerState,
overlap_notify::OverlapNotifyState, overlap_notify::OverlapNotifyState,
session_lock_layer::SessionLockLayerState,
toplevel_info::ToplevelInfoState, toplevel_info::ToplevelInfoState,
toplevel_management::{ManagementCapabilities, ToplevelManagementState}, toplevel_management::{ManagementCapabilities, ToplevelManagementState},
workspace::{WorkspaceState, WorkspaceUpdateGuard}, workspace::{WorkspaceState, WorkspaceUpdateGuard},
@ -321,7 +320,6 @@ pub struct Common {
pub xwayland_state: Option<XWaylandState>, pub xwayland_state: Option<XWaylandState>,
pub xwayland_shell_state: XWaylandShellState, pub xwayland_shell_state: XWaylandShellState,
pub pointer_focus_state: Option<PointerFocusState>, pub pointer_focus_state: Option<PointerFocusState>,
pub session_lock_layer_state: SessionLockLayerState,
#[cfg(feature = "logind")] #[cfg(feature = "logind")]
pub inhibit_lid_fd: Option<OwnedFd>, pub inhibit_lid_fd: Option<OwnedFd>,
@ -667,7 +665,7 @@ impl State {
.unwrap(); .unwrap();
let clock = Clock::new(); let clock = Clock::new();
let config = Config::load(&handle, kiosk_command.is_some()); let config = Config::load(&handle);
let compositor_state = CompositorState::new::<Self>(dh); let compositor_state = CompositorState::new::<Self>(dh);
let corner_radius_state = CornerRadiusState::new::<Self>(dh); let corner_radius_state = CornerRadiusState::new::<Self>(dh);
let data_device_state = DataDeviceState::new::<Self>(dh); let data_device_state = DataDeviceState::new::<Self>(dh);
@ -765,9 +763,6 @@ impl State {
let dbus_state = DBusState::init(&handle); let dbus_state = DBusState::init(&handle);
let session_lock_layer_state =
SessionLockLayerState::new::<State, _>(dh, client_not_sandboxed);
State { State {
common: Common { common: Common {
config, config,
@ -835,7 +830,6 @@ impl State {
pointer_focus_state: None, pointer_focus_state: None,
dbus_state, dbus_state,
keyboard_layout_state, keyboard_layout_state,
session_lock_layer_state,
#[cfg(feature = "logind")] #[cfg(feature = "logind")]
inhibit_lid_fd: None, inhibit_lid_fd: None,
@ -974,8 +968,6 @@ impl Common {
output: &Output, output: &Output,
render_element_states: &RenderElementStates, render_element_states: &RenderElementStates,
) { ) {
// NOTE: Keep in sync with surface iteration in `render_input_order_internal`
let shell = self.shell.read(); let shell = self.shell.read();
let processor = |namespace: Option<usize>| { let processor = |namespace: Option<usize>| {
move |surface: &WlSurface, states: &SurfaceData| { move |surface: &WlSurface, states: &SurfaceData| {
@ -1082,8 +1074,6 @@ impl Common {
render_element_states: &RenderElementStates, render_element_states: &RenderElementStates,
mut dmabuf_feedback: impl FnMut(DrmNode) -> Option<SurfaceDmabufFeedback>, mut dmabuf_feedback: impl FnMut(DrmNode) -> Option<SurfaceDmabufFeedback>,
) { ) {
// NOTE: Keep in sync with surface iteration in `render_input_order_internal`
let shell = self.shell.read(); let shell = self.shell.read();
if let Some(session_lock) = shell.session_lock.as_ref() if let Some(session_lock) = shell.session_lock.as_ref()
@ -1297,8 +1287,6 @@ impl Common {
#[profiling::function] #[profiling::function]
pub fn send_frames(&self, output: &Output, sequence: Option<usize>) { pub fn send_frames(&self, output: &Output, sequence: Option<usize>) {
// NOTE: Keep in sync with surface iteration in `render_input_order_internal`
let time = self.clock.now(); let time = self.clock.now();
let should_send = |surface: &WlSurface, states: &SurfaceData| { let should_send = |surface: &WlSurface, states: &SurfaceData| {
// Do the standard primary scanout output check. For pointer surfaces it deduplicates // Do the standard primary scanout output check. For pointer surfaces it deduplicates
@ -1340,12 +1328,8 @@ impl Common {
const THROTTLE: Option<Duration> = Some(Duration::from_millis(995)); const THROTTLE: Option<Duration> = Some(Duration::from_millis(995));
const SCREENCOPY_THROTTLE: Option<Duration> = Some(Duration::from_nanos(16_666_666)); const SCREENCOPY_THROTTLE: Option<Duration> = Some(Duration::from_nanos(16_666_666));
fn throttle(session_holder: &impl SessionHolder, is_xwayland: bool) -> Option<Duration> { fn throttle(session_holder: &impl SessionHolder) -> Option<Duration> {
if is_xwayland { if session_holder.sessions().is_empty() && session_holder.cursor_sessions().is_empty() {
Some(Duration::ZERO)
} else if session_holder.sessions().is_empty()
&& session_holder.cursor_sessions().is_empty()
{
THROTTLE THROTTLE
} else { } else {
SCREENCOPY_THROTTLE SCREENCOPY_THROTTLE
@ -1381,8 +1365,7 @@ impl Common {
&& let Some(grab_state) = move_grab.lock().unwrap().as_ref() && let Some(grab_state) = move_grab.lock().unwrap().as_ref()
{ {
for (window, _) in grab_state.element().windows() { for (window, _) in grab_state.element().windows() {
let throttle = throttle(&window, window.x11_surface().is_some()); window.send_frame(output, time, throttle(&window), should_send);
window.send_frame(output, time, throttle, should_send);
} }
} }
@ -1406,28 +1389,25 @@ impl Common {
.mapped() .mapped()
.for_each(|mapped| { .for_each(|mapped| {
for (window, _) in mapped.windows() { for (window, _) in mapped.windows() {
let throttle = throttle(&window, window.x11_surface().is_some()); window.send_frame(output, time, throttle(&window), should_send);
window.send_frame(output, time, throttle, should_send);
} }
}); });
if let Some(active) = shell.active_space(output) { if let Some(active) = shell.active_space(output) {
if let Some(fs) = active.get_fullscreen(shell.seats.last_active()) { if let Some(fs) = active.get_fullscreen(shell.seats.last_active()) {
let throttle = throttle(&fs.surface, fs.surface.x11_surface().is_some()); fs.surface
fs.surface.send_frame(output, time, throttle, should_send); .send_frame(output, time, throttle(&fs.surface), should_send);
} }
active.mapped().for_each(|mapped| { active.mapped().for_each(|mapped| {
for (window, _) in mapped.windows() { for (window, _) in mapped.windows() {
let throttle = throttle(&window, window.x11_surface().is_some()); window.send_frame(output, time, throttle(&window), should_send);
window.send_frame(output, time, throttle, should_send);
} }
}); });
// other (throttled) windows // other (throttled) windows
active.minimized_windows.iter().for_each(|m| { active.minimized_windows.iter().for_each(|m| {
for window in m.windows() { for window in m.windows() {
let throttle = throttle(&window, window.x11_surface().is_some()); window.send_frame(output, time, throttle(&window), |_, _| None);
window.send_frame(output, time, throttle, |_, _| None);
} }
}); });
@ -1437,25 +1417,18 @@ impl Common {
.filter(|w| w.handle != active.handle) .filter(|w| w.handle != active.handle)
{ {
if let Some(fs) = space.get_fullscreen(shell.seats.last_active()) { if let Some(fs) = space.get_fullscreen(shell.seats.last_active()) {
let throttle = min( let throttle = min(throttle(space), throttle(&fs.surface));
throttle(space, false),
throttle(&fs.surface, fs.surface.x11_surface().is_some()),
);
fs.surface.send_frame(output, time, throttle, |_, _| None); fs.surface.send_frame(output, time, throttle, |_, _| None);
} }
space.mapped().for_each(|mapped| { space.mapped().for_each(|mapped| {
for (window, _) in mapped.windows() { for (window, _) in mapped.windows() {
let throttle = min( let throttle = min(throttle(space), throttle(&window));
throttle(space, false),
throttle(&window, window.x11_surface().is_some()),
);
window.send_frame(output, time, throttle, |_, _| None); window.send_frame(output, time, throttle, |_, _| None);
} }
}); });
space.minimized_windows.iter().for_each(|m| { space.minimized_windows.iter().for_each(|m| {
for window in m.windows() { for window in m.windows() {
let throttle = throttle(&window, window.x11_surface().is_some()); window.send_frame(output, time, throttle(&window), |_, _| None);
window.send_frame(output, time, throttle, |_, _| None);
} }
}) })
} }

View file

@ -31,7 +31,7 @@ use ordered_float::OrderedFloat;
use smithay::{ use smithay::{
backend::{ backend::{
allocator::Fourcc, allocator::Fourcc,
input::{ButtonState, InputTime, KeyState, TabletToolDescriptor}, input::{ButtonState, KeyState},
renderer::{ renderer::{
ImportMem, ImportMem,
element::{ element::{
@ -45,23 +45,14 @@ use smithay::{
Seat, Seat,
keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState},
pointer::{ pointer::{
AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent,
GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent,
GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent,
PointerTarget, RelativeMotionEvent, PointerTarget, RelativeMotionEvent,
}, },
tablet::{
Tablet,
tool::{
AxisFrame as ToolAxisFrame, ButtonEvent as ToolButtonEvent,
DownEvent as ToolDownEvent, MotionEvent as ToolMotionEvent, TabletToolTarget,
UpEvent as ToolUpEvent,
},
},
touch::{ touch::{
DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent,
OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, TouchTarget, UpEvent,
}, },
}, },
output::Output, output::Output,
@ -198,7 +189,6 @@ pub(crate) struct IcedElementInternal<P: Program + Send + 'static> {
touch_map: HashMap<Finger, IcedPoint>, touch_map: HashMap<Finger, IcedPoint>,
last_touch_frame: Option<FrameMarker>, last_touch_frame: Option<FrameMarker>,
last_touch_serial: Option<Serial>, last_touch_serial: Option<Serial>,
last_tablet_serial: Option<Serial>,
// iced // iced
theme: Theme, theme: Theme,
@ -250,7 +240,6 @@ impl<P: Program + Send + Clone + 'static> Clone for IcedElementInternal<P> {
touch_map: self.touch_map.clone(), touch_map: self.touch_map.clone(),
last_touch_frame: None, last_touch_frame: None,
last_touch_serial: None, last_touch_serial: None,
last_tablet_serial: None,
theme: self.theme.clone(), theme: self.theme.clone(),
renderer, renderer,
state, state,
@ -278,7 +267,6 @@ impl<P: Program + Send + 'static> fmt::Debug for IcedElementInternal<P> {
.field("touch_map", &self.touch_map) .field("touch_map", &self.touch_map)
.field("last_touch_frame", &self.last_touch_frame) .field("last_touch_frame", &self.last_touch_frame)
.field("last_touch_serial", &self.last_touch_serial) .field("last_touch_serial", &self.last_touch_serial)
.field("last_tablet_serial", &self.last_tablet_serial)
.field("theme", &"...") .field("theme", &"...")
.field("renderer", &"...") .field("renderer", &"...")
.field("state", &"...") .field("state", &"...")
@ -338,7 +326,6 @@ impl<P: Program + Send + 'static> IcedElement<P> {
touch_map: HashMap::new(), touch_map: HashMap::new(),
last_touch_frame: None, last_touch_frame: None,
last_touch_serial: None, last_touch_serial: None,
last_tablet_serial: None,
theme, theme,
renderer, renderer,
state, state,
@ -494,144 +481,12 @@ impl<P: Program + Send + 'static> IcedElementInternal<P> {
} }
} }
impl<P: Program + Send + 'static> TabletToolTarget<crate::state::State> for IcedElement<P> {
fn proximity_in(
&self,
seat: &Seat<crate::state::State>,
_data: &mut crate::state::State,
_tool_descriptor: &TabletToolDescriptor,
_tablet: &Tablet,
serial: Serial,
) {
let mut internal = self.0.lock().unwrap();
internal
.state
.queue_event(Event::Mouse(MouseEvent::CursorEntered));
internal.last_tablet_serial = Some(serial);
*internal.last_seat.lock().unwrap() = Some((seat.clone(), serial));
internal.update(false);
}
fn proximity_out(
&self,
_seat: &Seat<crate::state::State>,
_data: &mut crate::state::State,
_tool_descriptor: &TabletToolDescriptor,
) {
let mut internal = self.0.lock().unwrap();
internal.cursor_pos = None;
internal
.state
.queue_event(Event::Mouse(MouseEvent::CursorLeft));
internal.update(false);
}
fn down(
&self,
seat: &Seat<crate::state::State>,
_data: &mut crate::state::State,
_tool_descriptor: &TabletToolDescriptor,
event: &ToolDownEvent,
) {
let mut internal = self.0.lock().unwrap();
let id = Finger(0);
let Some(event_location) = internal.cursor_pos else {
return;
};
let position = IcedPoint::new(event_location.x as f32, event_location.y as f32);
internal
.state
.queue_event(Event::Touch(TouchEvent::FingerPressed { id, position }));
internal.last_tablet_serial = Some(event.serial);
*internal.last_seat.lock().unwrap() = Some((seat.clone(), event.serial));
internal.update(false);
}
fn up(
&self,
seat: &Seat<crate::state::State>,
_data: &mut crate::state::State,
_tool_descriptor: &TabletToolDescriptor,
_event: &ToolUpEvent,
) {
let mut internal = self.0.lock().unwrap();
let id = Finger(0);
if let Some(event_location) = internal.cursor_pos {
*internal.last_seat.lock().unwrap() =
Some((seat.clone(), internal.last_tablet_serial.unwrap()));
let position = IcedPoint::new(event_location.x as f32, event_location.y as f32);
internal
.state
.queue_event(Event::Touch(TouchEvent::FingerLifted { id, position }));
internal.update(false);
}
}
fn motion(
&self,
seat: &Seat<crate::state::State>,
_data: &mut crate::state::State,
_tool_descriptor: &TabletToolDescriptor,
event: &ToolMotionEvent,
) {
let mut internal = self.0.lock().unwrap();
let event_location = event.location.downscale(internal.additional_scale);
let position = IcedPoint::new(event_location.x as f32, event_location.y as f32);
internal
.state
.queue_event(Event::Mouse(MouseEvent::CursorMoved { position }));
internal.cursor_pos = Some(event_location);
*internal.last_seat.lock().unwrap() =
Some((seat.clone(), internal.last_tablet_serial.unwrap()));
internal.update(false);
}
fn axis(
&self,
_seat: &Seat<crate::state::State>,
_data: &mut crate::state::State,
_tool_descriptor: &TabletToolDescriptor,
_frame: ToolAxisFrame,
) {
}
fn button(
&self,
seat: &Seat<crate::state::State>,
_data: &mut crate::state::State,
_tool_descriptor: &TabletToolDescriptor,
event: &ToolButtonEvent,
) {
let mut internal = self.0.lock().unwrap();
let button = match event.button {
0x14b => MouseButton::Right,
0x14c => MouseButton::Middle,
_ => return,
};
internal.state.queue_event(Event::Mouse(match event.state {
ButtonState::Pressed => MouseEvent::ButtonPressed(button),
ButtonState::Released => MouseEvent::ButtonReleased(button),
}));
*internal.last_seat.lock().unwrap() = Some((seat.clone(), event.serial));
internal.update(false);
}
fn frame(
&self,
_seat: &Seat<crate::state::State>,
_data: &mut crate::state::State,
_tool_descriptor: &TabletToolDescriptor,
_time: InputTime,
) {
}
}
impl<P: Program + Send + 'static> PointerTarget<crate::state::State> for IcedElement<P> { impl<P: Program + Send + 'static> PointerTarget<crate::state::State> for IcedElement<P> {
fn enter( fn enter(
&self, &self,
seat: &Seat<crate::state::State>, seat: &Seat<crate::state::State>,
_data: &mut crate::state::State, _data: &mut crate::state::State,
event: &PointerMotionEvent, event: &MotionEvent,
) { ) {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
internal internal
@ -652,7 +507,7 @@ impl<P: Program + Send + 'static> PointerTarget<crate::state::State> for IcedEle
&self, &self,
seat: &Seat<crate::state::State>, seat: &Seat<crate::state::State>,
_data: &mut crate::state::State, _data: &mut crate::state::State,
event: &PointerMotionEvent, event: &MotionEvent,
) { ) {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
let event_location = event.location.downscale(internal.additional_scale); let event_location = event.location.downscale(internal.additional_scale);
@ -677,7 +532,7 @@ impl<P: Program + Send + 'static> PointerTarget<crate::state::State> for IcedEle
&self, &self,
seat: &Seat<crate::state::State>, seat: &Seat<crate::state::State>,
_data: &mut crate::state::State, _data: &mut crate::state::State,
event: &PointerButtonEvent, event: &ButtonEvent,
) { ) {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
let button = match event.button { let button = match event.button {
@ -698,7 +553,7 @@ impl<P: Program + Send + 'static> PointerTarget<crate::state::State> for IcedEle
&self, &self,
_seat: &Seat<crate::state::State>, _seat: &Seat<crate::state::State>,
_data: &mut crate::state::State, _data: &mut crate::state::State,
frame: PointerAxisFrame, frame: AxisFrame,
) { ) {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
internal internal
@ -726,10 +581,9 @@ impl<P: Program + Send + 'static> PointerTarget<crate::state::State> for IcedEle
_seat: &Seat<crate::state::State>, _seat: &Seat<crate::state::State>,
_data: &mut crate::state::State, _data: &mut crate::state::State,
_serial: Serial, _serial: Serial,
_time: InputTime, _time: u32,
) { ) {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
internal.cursor_pos = None;
internal internal
.state .state
.queue_event(Event::Mouse(MouseEvent::CursorLeft)); .queue_event(Event::Mouse(MouseEvent::CursorLeft));
@ -799,7 +653,7 @@ impl<P: Program + Send + 'static> TouchTarget<crate::state::State> for IcedEleme
&self, &self,
seat: &Seat<crate::state::State>, seat: &Seat<crate::state::State>,
_data: &mut crate::state::State, _data: &mut crate::state::State,
event: &TouchDownEvent, event: &DownEvent,
) { ) {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
let id = Finger(i32::from(event.slot) as u64); let id = Finger(i32::from(event.slot) as u64);
@ -819,7 +673,7 @@ impl<P: Program + Send + 'static> TouchTarget<crate::state::State> for IcedEleme
&self, &self,
seat: &Seat<crate::state::State>, seat: &Seat<crate::state::State>,
_data: &mut crate::state::State, _data: &mut crate::state::State,
event: &TouchUpEvent, event: &UpEvent,
) { ) {
let mut internal = self.0.lock().unwrap(); let mut internal = self.0.lock().unwrap();
let id = Finger(i32::from(event.slot) as u64); let id = Finger(i32::from(event.slot) as u64);
@ -930,7 +784,7 @@ impl<P: Program + Send + 'static> KeyboardTarget<crate::state::State> for IcedEl
_key: KeysymHandle<'_>, _key: KeysymHandle<'_>,
_state: KeyState, _state: KeyState,
_serial: Serial, _serial: Serial,
_time: InputTime, _time: u32,
) { ) {
// TODO convert keys // TODO convert keys
} }

View file

@ -3,12 +3,9 @@
use crate::{shell::grabs::SeatMoveGrabState, state::ClientState, utils::prelude::*}; use crate::{shell::grabs::SeatMoveGrabState, state::ClientState, utils::prelude::*};
use calloop::Interest; use calloop::Interest;
use smithay::{ use smithay::{
backend::{ backend::renderer::{
input::InputTime, element::{Kind, surface::KindEvaluation},
renderer::{ utils::{on_commit_buffer_handler, with_renderer_surface_state},
element::{Kind, surface::KindEvaluation},
utils::{on_commit_buffer_handler, with_renderer_surface_state},
},
}, },
desktop::{LayerSurface, PopupKind, WindowSurfaceType, layer_map_for_output}, desktop::{LayerSurface, PopupKind, WindowSurfaceType, layer_map_for_output},
reexports::wayland_server::{Client, Resource, protocol::wl_surface::WlSurface}, reexports::wayland_server::{Client, Resource, protocol::wl_surface::WlSurface},
@ -328,11 +325,9 @@ impl CompositorHandler for State {
} }
} else { } else {
std::mem::drop(shell); std::mem::drop(shell);
seat.get_pointer().unwrap().unset_grab( seat.get_pointer()
self, .unwrap()
SERIAL_COUNTER.next_serial(), .unset_grab(self, SERIAL_COUNTER.next_serial(), 0);
InputTime::now(),
);
return; return;
} }
} }

View file

@ -45,11 +45,18 @@ pub fn surface_corners(states: &SurfaceData, size: Size<i32, Logical>) -> Option
]) ])
} }
pub fn surface_padding(states: &SurfaceData) -> Option<[i32; 4]> { pub fn surface_padding(states: &SurfaceData, size: Size<i32, Logical>) -> Option<[i32; 4]> {
let mut guard = states.cached_state.get::<CacheablePadding>(); let mut guard = states.cached_state.get::<CacheablePadding>();
let padding = guard.current().0?; let padding = guard.current().0?;
Some([padding.top, padding.right, padding.bottom, padding.left])
// guard against padding being too large
Some([
padding.top.min(size.h / 2),
padding.right.min(size.w / 2),
padding.bottom.min(size.h / 2),
padding.left.min(size.w / 2),
])
} }
pub fn pad_rect( pub fn pad_rect(

View file

@ -1,6 +1,5 @@
use std::{cell::RefCell, sync::Mutex}; use std::{cell::RefCell, sync::Mutex};
use cosmic_comp_config::DecorationPreference;
use smithay::{ use smithay::{
desktop::Window, desktop::Window,
reexports::{ reexports::{
@ -21,7 +20,7 @@ use smithay::{
}; };
use wayland_backend::protocol::WEnum; use wayland_backend::protocol::WEnum;
use crate::{shell::CosmicMapped, state::State}; use crate::state::State;
pub struct PreferredDecorationMode(RefCell<Option<XdgMode>>); pub struct PreferredDecorationMode(RefCell<Option<XdgMode>>);
@ -30,7 +29,7 @@ impl PreferredDecorationMode {
window window
.user_data() .user_data()
.get::<PreferredDecorationMode>() .get::<PreferredDecorationMode>()
.is_none_or(|mode| mode.0.borrow().is_none()) .is_none()
} }
pub fn mode(window: &Window) -> Option<XdgMode> { pub fn mode(window: &Window) -> Option<XdgMode> {
@ -54,72 +53,6 @@ impl PreferredDecorationMode {
} }
} }
impl State {
pub fn default_decoration(&self) -> DecorationPreference {
self.common.config.cosmic_conf.decoration_preference
}
pub fn update_decorations(&self) {
let shell = self.common.shell.read();
let update = |mapped: &CosmicMapped| {
let mode = if mapped.is_stack() {
XdgMode::ServerSide
} else {
XdgMode::from_preference(self.default_decoration())
};
for (window, _) in mapped.windows() {
if PreferredDecorationMode::is_unset(&window.0)
&& let Some(toplevel) = window.0.toplevel()
&& toplevel.with_committed_state(|state| {
state.is_some_and(|state| state.decoration_mode.is_some())
})
{
toplevel.with_pending_state(|state| {
state.decoration_mode = Some(mode);
});
toplevel.send_configure();
}
}
};
for set in shell.workspaces.sets.values() {
set.sticky_layer.mapped().for_each(update);
}
for space in shell.workspaces.spaces() {
space.mapped().for_each(update);
space
.minimized_windows
.iter()
.filter_map(|m| m.mapped())
.for_each(update);
}
}
}
trait FromDecorationPreference {
fn from_preference(preference: DecorationPreference) -> Self;
}
impl FromDecorationPreference for XdgMode {
fn from_preference(preference: DecorationPreference) -> Self {
match preference {
DecorationPreference::ClientSide => XdgMode::ClientSide,
DecorationPreference::ServerSide => XdgMode::ServerSide,
}
}
}
impl FromDecorationPreference for KdeMode {
fn from_preference(preference: DecorationPreference) -> Self {
match preference {
DecorationPreference::ClientSide => KdeMode::Client,
DecorationPreference::ServerSide => KdeMode::Server,
}
}
}
pub type KdeDecorationData = Mutex<KdeDecorationSurfaceState>; pub type KdeDecorationData = Mutex<KdeDecorationSurfaceState>;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct KdeDecorationSurfaceState { pub struct KdeDecorationSurfaceState {
@ -134,7 +67,7 @@ impl XdgDecorationHandler for State {
let mode = if mapped.is_stack() { let mode = if mapped.is_stack() {
XdgMode::ServerSide XdgMode::ServerSide
} else { } else {
XdgMode::from_preference(self.default_decoration()) XdgMode::ClientSide
}; };
if let Some((window, _)) = mapped if let Some((window, _)) = mapped
@ -147,10 +80,6 @@ impl XdgDecorationHandler for State {
}); });
toplevel.send_configure(); toplevel.send_configure();
} }
} else {
toplevel.with_pending_state(|state| {
state.decoration_mode = Some(XdgMode::from_preference(self.default_decoration()))
})
} }
} }
@ -170,13 +99,6 @@ impl XdgDecorationHandler for State {
} }
} else { } else {
toplevel.with_pending_state(|state| state.decoration_mode = Some(mode)); toplevel.with_pending_state(|state| state.decoration_mode = Some(mode));
if let Some(pending) = shell
.pending_windows
.iter()
.find(|pending| pending.surface.0.toplevel().is_some_and(|t| t == &toplevel))
{
PreferredDecorationMode::update(&pending.surface.0, Some(mode));
}
} }
} }
@ -188,28 +110,11 @@ impl XdgDecorationHandler for State {
.find(|(window, _)| window.wl_surface().as_deref() == Some(toplevel.wl_surface())) .find(|(window, _)| window.wl_surface().as_deref() == Some(toplevel.wl_surface()))
&& let Some(toplevel) = window.0.toplevel() && let Some(toplevel) = window.0.toplevel()
{ {
let mode = if mapped.is_stack() {
XdgMode::ServerSide
} else {
XdgMode::from_preference(self.default_decoration())
};
PreferredDecorationMode::update(&window.0, None); PreferredDecorationMode::update(&window.0, None);
toplevel.with_pending_state(|state| { toplevel.with_pending_state(|state| {
state.decoration_mode = Some(mode); state.decoration_mode = None;
}); });
toplevel.send_configure(); toplevel.send_configure();
} else {
toplevel.with_pending_state(|state| {
state.decoration_mode = Some(XdgMode::from_preference(self.default_decoration()))
});
if let Some(pending) = shell
.pending_windows
.iter()
.find(|pending| pending.surface.0.toplevel().is_some_and(|t| t == &toplevel))
{
PreferredDecorationMode::update(&pending.surface.0, None);
}
} }
} }
} }
@ -224,10 +129,10 @@ impl KdeDecorationHandler for State {
if mapped.is_stack() { if mapped.is_stack() {
KdeMode::Server KdeMode::Server
} else { } else {
KdeMode::from_preference(self.default_decoration()) KdeMode::Client
} }
} else { } else {
KdeMode::from_preference(self.default_decoration()) KdeMode::Client
}; };
with_states(surface, |states| { with_states(surface, |states| {

View file

@ -1,8 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use std::{borrow::Borrow, sync::Mutex}; use std::{borrow::Borrow, collections::HashMap, sync::Mutex};
use indexmap::IndexMap;
use smithay::{ use smithay::{
backend::{ backend::{
@ -454,28 +452,23 @@ fn constraints_for_renderer(
.ok() .ok()
.and_then(|device| device.try_get_render_node().ok().flatten()) .and_then(|device| device.try_get_render_node().ok().flatten())
{ {
let mut formats = renderer constraints.dma = Some(DmabufConstraints {
.egl_context() node,
.dmabuf_render_formats() formats: renderer
.iter() .egl_context()
.fold( .dmabuf_render_formats()
IndexMap::<Fourcc, Vec<Modifier>>::new(), .iter()
|mut map, format| { .fold(
map.entry(format.code).or_default().push(format.modifier); HashMap::<Fourcc, Vec<Modifier>>::new(),
map |mut map, format| {
}, map.entry(format.code).or_default().push(format.modifier);
) map
.into_iter() },
.collect::<Vec<_>>(); )
formats.sort_by_key(|(code, _)| !is_preferred_capture_format(*code)); .into_iter()
constraints.dma = Some(DmabufConstraints { node, formats }); .collect::<Vec<_>>(),
});
} }
constraints constraints
} }
/// Formats most screencast consumers handle natively, offered first. WebRTC, for
/// example, swaps RGBA frames to BGRA on the CPU for every captured frame.
fn is_preferred_capture_format(code: Fourcc) -> bool {
matches!(code, Fourcc::Argb8888 | Fourcc::Xrgb8888)
}

View file

@ -1,7 +1,5 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use smithay::input::keyboard::KeyboardHandle;
use crate::state::State; use crate::state::State;
use crate::wayland::protocols::keyboard_layout::{KeyboardLayoutHandler, KeyboardLayoutState}; use crate::wayland::protocols::keyboard_layout::{KeyboardLayoutHandler, KeyboardLayoutState};
@ -9,8 +7,4 @@ impl KeyboardLayoutHandler for State {
fn keyboard_layout_state(&mut self) -> &mut KeyboardLayoutState { fn keyboard_layout_state(&mut self) -> &mut KeyboardLayoutState {
&mut self.common.keyboard_layout_state &mut self.common.keyboard_layout_state
} }
fn group_changed(&mut self, keyboard: &KeyboardHandle<Self>) {
self.broadcast_ei_keyboard_modifiers(keyboard);
}
} }

View file

@ -21,11 +21,6 @@ pub fn set_all_surfaces_dpms_on(state: &mut State) {
} }
if changed { if changed {
// Powering an output on because of input is activity. Without this the idle
// notifier stays idled, the idle daemon never sees `resumed`, and nothing
// powers the output off again until real input arrives.
let seat = state.common.shell.read().seats.last_active().clone();
state.common.idle_notifier_state.notify_activity(&seat);
OutputPowerState::refresh(state); OutputPowerState::refresh(state);
} }
} }

View file

@ -5,10 +5,7 @@ use smithay::{
input::pointer::PointerHandle, input::pointer::PointerHandle,
reexports::wayland_server::protocol::wl_surface::WlSurface, reexports::wayland_server::protocol::wl_surface::WlSurface,
utils::{Logical, Point}, utils::{Logical, Point},
wayland::{ wayland::{pointer_constraints::PointerConstraintsHandler, seat::WaylandFocus},
pointer_constraints::{ConstraintRemove, PointerConstraintsHandler},
seat::WaylandFocus,
},
}; };
pub use smithay::wayland::pointer_constraints::{PointerConstraintRef, with_pointer_constraint}; pub use smithay::wayland::pointer_constraints::{PointerConstraintRef, with_pointer_constraint};
@ -79,37 +76,23 @@ impl PointerConstraintsHandler for State {
} }
} }
fn remove_constraint( fn remove_constraint(&mut self, surface: &WlSurface, pointer: &PointerHandle<Self>) {
&mut self, if with_pointer_constraint(surface, pointer, |constraint| constraint.is_none()) {
surface: &WlSurface, let seat = self
pointer: &PointerHandle<Self>, .common
constraint_remove: ConstraintRemove, .shell
) { .read()
match constraint_remove { .seats
ConstraintRemove::PointerLeave(_) => { .iter()
// If the constraint was broken by the pointer forcibly leaving the surface, then it doesn't .find(|s| s.get_pointer().as_ref() == Some(pointer))
// make much sense to warp it. .cloned();
}
ConstraintRemove::Destroyed(constraint) => {
let Some(seat) = self
.common
.shell
.read()
.seats
.iter()
.find(|s| s.get_pointer().as_ref() == Some(pointer))
.cloned()
else {
return;
};
let Some((hint_surface, hint_location)) = seat.pointer_constraint_hint() else {
return;
};
if hint_surface == *surface { if let Some(seat) = seat
self.apply_cursor_hint(surface, pointer, hint_location, Some(&constraint)); && let Some((hint_surface, hint_location)) = seat.pointer_constraint_hint()
seat.set_pointer_constraint_hint(None); && hint_surface == *surface
} {
self.apply_cursor_hint(surface, pointer, hint_location);
seat.set_pointer_constraint_hint(None);
} }
} }
} }

View file

@ -38,7 +38,7 @@ impl PointerWarpHandler for State {
drop(shell); drop(shell);
if let Some(pointer_handle) = pointer_handle { if let Some(pointer_handle) = pointer_handle {
self.apply_cursor_hint(&surface, &pointer_handle, pos, None); self.apply_cursor_hint(&surface, &pointer_handle, pos);
} }
} }
} }

View file

@ -1,13 +1,13 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use crate::{shell::focus::target::PointerFocusTarget, state::State}; use crate::state::State;
use smithay::{ use smithay::{
backend::input::TabletToolDescriptor, input::pointer::CursorImageStatus, backend::input::TabletToolDescriptor, input::pointer::CursorImageStatus,
input::tablet::TabletSeatHandler, input::tablet::TabletSeatHandler, reexports::wayland_server::protocol::wl_surface,
}; };
impl TabletSeatHandler for State { impl TabletSeatHandler for State {
type ToolFocus = PointerFocusTarget; type ToolFocus = wl_surface::WlSurface;
fn tablet_tool_image(&mut self, _tool: &TabletToolDescriptor, _image: CursorImageStatus) { fn tablet_tool_image(&mut self, _tool: &TabletToolDescriptor, _image: CursorImageStatus) {
// TODO display cursor for each tablet tool // TODO display cursor for each tablet tool

View file

@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use smithay::{ use smithay::{
backend::input::InputTime,
desktop::{WindowSurfaceType, layer_map_for_output}, desktop::{WindowSurfaceType, layer_map_for_output},
input::{Seat, pointer::MotionEvent}, input::{Seat, pointer::MotionEvent},
output::Output, output::Output,
@ -125,7 +124,7 @@ impl ToplevelManagementHandler for State {
&MotionEvent { &MotionEvent {
location: new_pos.to_f64().as_logical(), location: new_pos.to_f64().as_logical(),
serial, serial,
time: InputTime::now(), time: self.common.clock.now().as_millis(),
}, },
); );
ptr.frame(self); ptr.frame(self);

View file

@ -243,7 +243,7 @@ impl State {
{ {
for mapped in current_workspace for mapped in current_workspace
.mapped() .mapped()
.filter(|m| m.maximized_state.lock().unwrap().is_some() && *m != &element) .filter(|m| m.maximized_state.lock().unwrap().is_some())
.cloned() .cloned()
.collect::<Vec<_>>() .collect::<Vec<_>>()
.into_iter() .into_iter()

View file

@ -1,15 +1,11 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use crate::{ use crate::{
shell::{ shell::{CosmicSurface, PendingWindow, focus::target::KeyboardFocusTarget, grabs::ReleaseMode},
CosmicSurface, PendingWindow,
focus::target::KeyboardFocusTarget,
grabs::{GrabType, ReleaseMode},
},
utils::prelude::*, utils::prelude::*,
}; };
use smithay::desktop::layer_map_for_output;
use smithay::{ use smithay::{
backend::input::InputTime,
desktop::{ desktop::{
PopupGrab, PopupKeyboardGrab, PopupKind, PopupPointerGrab, PopupUngrabStrategy, PopupGrab, PopupKeyboardGrab, PopupKind, PopupPointerGrab, PopupUngrabStrategy,
WindowSurfaceType, find_popup_root_surface, WindowSurfaceType, find_popup_root_surface,
@ -30,7 +26,6 @@ use smithay::{
}, },
}, },
}; };
use smithay::{desktop::layer_map_for_output, input::tablet::TabletSeatTrait};
use std::cell::Cell; use std::cell::Cell;
use tracing::warn; use tracing::warn;
@ -55,7 +50,6 @@ impl XdgShellHandler for State {
surface, surface,
seat, seat,
fullscreen: None, fullscreen: None,
minimized: false,
maximized: false, maximized: false,
sticky: false, sticky: false,
}) })
@ -195,17 +189,12 @@ impl XdgShellHandler for State {
true, true,
) { ) {
std::mem::drop(shell); std::mem::drop(shell);
match grab.grab_type() { if grab.is_touch_grab() {
GrabType::Touch => seat.get_touch().unwrap().set_grab(self, grab, serial), seat.get_touch().unwrap().set_grab(self, grab, serial);
GrabType::Pointer => seat } else {
.get_pointer() seat.get_pointer()
.unwrap() .unwrap()
.set_grab(self, grab, serial, focus), .set_grab(self, grab, serial, focus)
GrabType::TabletTool => seat
.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(self, grab, InputTime::now(), serial, focus),
} }
} }
} }
@ -228,17 +217,12 @@ impl XdgShellHandler for State {
true, true,
) { ) {
std::mem::drop(shell); std::mem::drop(shell);
match grab.grab_type() { if grab.is_touch_grab() {
GrabType::Touch => seat.get_touch().unwrap().set_grab(self, grab, serial), seat.get_touch().unwrap().set_grab(self, grab, serial)
GrabType::Pointer => seat } else {
.get_pointer() seat.get_pointer()
.unwrap() .unwrap()
.set_grab(self, grab, serial, focus), .set_grab(self, grab, serial, focus)
GrabType::TabletTool => seat
.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(self, grab, InputTime::now(), serial, focus),
} }
} }
} }

View file

@ -5,19 +5,17 @@ use cosmic_protocols::corner_radius::v1::server::cosmic_corner_radius_toplevel_v
use cosmic_protocols::corner_radius::v1::server::{ use cosmic_protocols::corner_radius::v1::server::{
cosmic_corner_radius_manager_v1, cosmic_corner_radius_toplevel_v1, cosmic_corner_radius_manager_v1, cosmic_corner_radius_toplevel_v1,
}; };
use smithay::backend::renderer::buffer_dimensions; use smithay::desktop::utils::bbox_from_surface_tree;
use smithay::backend::renderer::utils::RendererSurfaceStateUserData;
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_popup::XdgPopup; use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_popup::XdgPopup;
use smithay::reexports::wayland_protocols_wlr::layer_shell::v1::server::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1; use smithay::reexports::wayland_protocols_wlr::layer_shell::v1::server::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1;
use smithay::reexports::wayland_server::New; use smithay::reexports::wayland_server::New;
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
use smithay::utils::{HookId, Logical, Rectangle}; use smithay::utils::{HookId, Logical, Point, Rectangle};
use smithay::wayland::compositor::Cacheable;
use smithay::wayland::compositor::add_pre_commit_hook; use smithay::wayland::compositor::add_pre_commit_hook;
use smithay::wayland::compositor::with_states; use smithay::wayland::compositor::with_states;
use smithay::wayland::compositor::{BufferAssignment, Cacheable, SurfaceAttributes};
use smithay::wayland::shell::wlr_layer::WlrLayerShellHandler; use smithay::wayland::shell::wlr_layer::WlrLayerShellHandler;
use smithay::wayland::shell::xdg::{SurfaceCachedState, XdgShellSurfaceUserData}; use smithay::wayland::shell::xdg::{SurfaceCachedState, XdgShellSurfaceUserData};
use smithay::wayland::viewporter::ViewportCachedState;
use smithay::{ use smithay::{
reexports::{ reexports::{
wayland_protocols::xdg::shell::server::xdg_toplevel::XdgToplevel, wayland_protocols::xdg::shell::server::xdg_toplevel::XdgToplevel,
@ -657,6 +655,7 @@ fn pad_rect(
} }
fn layer_radius_hook<D: 'static>(_state: &mut D, _dh: &DisplayHandle, surface: &WlSurface) { fn layer_radius_hook<D: 'static>(_state: &mut D, _dh: &DisplayHandle, surface: &WlSurface) {
let bbox = bbox_from_surface_tree(surface, Point::default());
with_states(surface, |surface_data| { with_states(surface, |surface_data| {
let corners = *surface_data let corners = *surface_data
.cached_state .cached_state
@ -666,40 +665,8 @@ fn layer_radius_hook<D: 'static>(_state: &mut D, _dh: &DisplayHandle, surface: &
.cached_state .cached_state
.get::<CacheablePadding>() .get::<CacheablePadding>()
.pending(); .pending();
// The wl_surface size after this commit is:
// - viewport destination if set
// - else the logical size of the buffer that will be current attached now
// - else existing
let size = surface_data
.cached_state
.get::<ViewportCachedState>()
.pending()
.size()
.or_else(|| {
let mut guard = surface_data.cached_state.get::<SurfaceAttributes>();
let attrs = guard.pending();
match &attrs.buffer {
Some(BufferAssignment::NewBuffer(buffer)) => buffer_dimensions(buffer)
.map(|d| d.to_logical(attrs.buffer_scale, attrs.buffer_transform.into())),
_ => None,
}
})
.or_else(|| {
surface_data
.data_map
.get::<RendererSurfaceStateUserData>()
.and_then(|state| state.lock().unwrap().surface_size())
});
let Some(size) = size else {
return;
};
let empty = Padding::default(); let empty = Padding::default();
let Some(padded_box) = pad_rect( let Some(padded_box) = pad_rect(bbox, padding.0.as_ref().unwrap_or(&empty)) else {
Rectangle::from_size(size),
padding.0.as_ref().unwrap_or(&empty),
) else {
if let Some(hook) = surface_data.data_map.get::<LayerHookId>() { if let Some(hook) = surface_data.data_map.get::<LayerHookId>() {
let hook_ref = hook.lock().unwrap(); let hook_ref = hook.lock().unwrap();
if let Some((_, obj)) = hook_ref.as_ref() if let Some((_, obj)) = hook_ref.as_ref()

View file

@ -17,10 +17,8 @@ use smithay::{
use std::mem; use std::mem;
use wayland_backend::server::{ClientId, GlobalId}; use wayland_backend::server::{ClientId, GlobalId};
pub trait KeyboardLayoutHandler: SeatHandler { pub trait KeyboardLayoutHandler {
fn keyboard_layout_state(&mut self) -> &mut KeyboardLayoutState; fn keyboard_layout_state(&mut self) -> &mut KeyboardLayoutState;
/// Group has been changed through the protocol
fn group_changed(&mut self, keyboard: &KeyboardHandle<Self>);
} }
#[derive(Debug)] #[derive(Debug)]
@ -59,7 +57,6 @@ impl KeyboardLayoutState {
let active_layout = handle.with_xkb_state(state, |context| { let active_layout = handle.with_xkb_state(state, |context| {
context.xkb().lock().unwrap().active_layout() context.xkb().lock().unwrap().active_layout()
}); });
state.group_changed(handle);
if *last_layout != Some(active_layout) { if *last_layout != Some(active_layout) {
keyboard_layout.group(active_layout.0); keyboard_layout.group(active_layout.0);
*last_layout = Some(active_layout); *last_layout = Some(active_layout);

View file

@ -8,7 +8,6 @@ pub mod keyboard_layout;
pub mod output_configuration; pub mod output_configuration;
pub mod output_power; pub mod output_power;
pub mod overlap_notify; pub mod overlap_notify;
pub mod session_lock_layer;
pub mod toplevel_info; pub mod toplevel_info;
pub mod toplevel_management; pub mod toplevel_management;
pub mod workspace; pub mod workspace;

View file

@ -1,136 +0,0 @@
use cosmic_protocols::session_lock_layer::v1::server::cosmic_session_lock_layer_manager_v1;
use smithay::{
reexports::wayland_server::{
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, backend::GlobalId,
protocol::wl_surface,
},
wayland::{
Dispatch2, GlobalDispatch2,
compositor::{Cacheable, with_states},
shell::wlr_layer::WlrLayerShellHandler,
},
};
struct SessionLockLayerData;
#[derive(Debug)]
pub struct SessionLockLayerState {
global: GlobalId,
}
impl SessionLockLayerState {
pub fn new<D, F>(dh: &DisplayHandle, client_filter: F) -> Self
where
F: for<'a> Fn(&'a Client) -> bool + Clone + Send + Sync + 'static,
D: GlobalDispatch<
cosmic_session_lock_layer_manager_v1::CosmicSessionLockLayerManagerV1,
SessionLockLayerGlobalData,
> + 'static,
{
let global = dh
.create_global::<D, cosmic_session_lock_layer_manager_v1::CosmicSessionLockLayerManagerV1, _>(
1,
SessionLockLayerGlobalData {
filter: Box::new(client_filter.clone()),
},
);
Self { global }
}
pub fn global_id(&self) -> GlobalId {
self.global.clone()
}
}
#[doc(hidden)]
pub struct SessionLockLayerGlobalData {
filter: Box<dyn for<'a> Fn(&'a Client) -> bool + Send + Sync>,
}
impl<D> GlobalDispatch2<cosmic_session_lock_layer_manager_v1::CosmicSessionLockLayerManagerV1, D>
for SessionLockLayerGlobalData
where
D: Dispatch<
cosmic_session_lock_layer_manager_v1::CosmicSessionLockLayerManagerV1,
SessionLockLayerData,
>,
{
fn bind(
&self,
_state: &mut D,
_handle: &DisplayHandle,
_client: &Client,
resource: New<cosmic_session_lock_layer_manager_v1::CosmicSessionLockLayerManagerV1>,
data_init: &mut DataInit<'_, D>,
) {
data_init.init(resource, SessionLockLayerData);
}
fn can_view(&self, client: &Client) -> bool {
(self.filter)(client)
}
}
#[derive(Clone, Copy, Default)]
struct SessionLockLayerSurfaceData {
show_on_lock: bool,
}
impl Cacheable for SessionLockLayerSurfaceData {
fn commit(&mut self, _dh: &DisplayHandle) -> Self {
*self
}
fn merge_into(self, into: &mut Self, _dh: &DisplayHandle) {
*into = self;
}
}
pub fn layer_show_on_lock(wl_surface: &wl_surface::WlSurface) -> bool {
with_states(wl_surface, |states| {
if states.cached_state.has::<SessionLockLayerSurfaceData>() {
let mut state = states.cached_state.get::<SessionLockLayerSurfaceData>();
state.current().show_on_lock
} else {
false
}
})
}
impl<D> Dispatch2<cosmic_session_lock_layer_manager_v1::CosmicSessionLockLayerManagerV1, D>
for SessionLockLayerData
where
D: WlrLayerShellHandler,
{
fn request(
&self,
state: &mut D,
_: &Client,
_: &cosmic_session_lock_layer_manager_v1::CosmicSessionLockLayerManagerV1,
request: cosmic_session_lock_layer_manager_v1::Request,
_: &DisplayHandle,
_: &mut DataInit<'_, D>,
) {
let (layer, value) = match request {
cosmic_session_lock_layer_manager_v1::Request::SetShowOnLock { layer } => (layer, true),
cosmic_session_lock_layer_manager_v1::Request::UnsetShowOnLock { layer } => {
(layer, false)
}
cosmic_session_lock_layer_manager_v1::Request::Destroy => {
return;
}
_ => unreachable!(),
};
if let Some(layer) = state
.shell_state()
.layer_surfaces()
.find(|surface| surface.shell_surface() == &layer)
{
with_states(layer.wl_surface(), |states| {
let mut state = states.cached_state.get::<SessionLockLayerSurfaceData>();
state.pending().show_on_lock = value;
});
}
}
}

View file

@ -418,12 +418,6 @@ where
handle.closed(); handle.closed();
} }
} }
// Remove the foreign handle too, so new subscribers cannot
// discover a toplevel whose window has already been destroyed.
if let Some(handle) = state.foreign_handle.take() {
self.foreign_toplevel_list.remove_toplevel(&handle);
}
*state = Default::default();
dirty = true; dirty = true;
false false
} }

View file

@ -9,9 +9,7 @@ use std::{
use crate::{ use crate::{
backend::render::cursor::{Cursor, load_cursor_env, load_cursor_theme}, backend::render::cursor::{Cursor, load_cursor_env, load_cursor_theme},
shell::{ shell::{
CosmicSurface, PendingWindow, Shell, CosmicSurface, PendingWindow, Shell, focus::target::KeyboardFocusTarget, grabs::ReleaseMode,
focus::target::KeyboardFocusTarget,
grabs::{GrabType, ReleaseMode},
}, },
state::State, state::State,
utils::prelude::*, utils::prelude::*,
@ -22,7 +20,7 @@ use smithay::{
backend::{ backend::{
allocator::Fourcc, allocator::Fourcc,
drm::DrmNode, drm::DrmNode,
input::{ButtonState, InputTime, KeyState, Keycode}, input::{ButtonState, KeyState, Keycode},
renderer::{ renderer::{
Bind, Frame, Offscreen, Renderer, Bind, Frame, Offscreen, Renderer,
element::{ element::{
@ -34,7 +32,7 @@ use smithay::{
}, },
}, },
desktop::space::SpaceElement, desktop::space::SpaceElement,
input::{keyboard::ModifiersState, pointer::CursorIcon, tablet::TabletSeatTrait}, input::{keyboard::ModifiersState, pointer::CursorIcon},
reexports::{wayland_server::Client, x11rb::protocol::xproto::Window as X11Window}, reexports::{wayland_server::Client, x11rb::protocol::xproto::Window as X11Window},
utils::{ utils::{
Buffer as BufferCoords, Logical, Point, Rectangle, SERIAL_COUNTER, Serial, Size, Transform, Buffer as BufferCoords, Logical, Point, Rectangle, SERIAL_COUNTER, Serial, Size, Transform,
@ -398,7 +396,7 @@ impl Common {
state: KeyState, state: KeyState,
modifiers: ModifiersState, modifiers: ModifiersState,
serial: Serial, serial: Serial,
time: InputTime, time: u32,
) { ) {
let config = self.config.cosmic_conf.xwayland_eavesdropping.keyboard; let config = self.config.cosmic_conf.xwayland_eavesdropping.keyboard;
if config == EavesdroppingKeyboardMode::None { if config == EavesdroppingKeyboardMode::None {
@ -460,7 +458,7 @@ impl Common {
tracing::trace!("Forwaring key {} {:?} to xwayland", code.raw() - 8, state); tracing::trace!("Forwaring key {} {:?} to xwayland", code.raw() - 8, state);
for wl_keyboard in keyboard.client_keyboards(&xstate.client) { for wl_keyboard in keyboard.client_keyboards(&xstate.client) {
wl_keyboard.key(serial.into(), time.millis(), code.raw() - 8, state.into()); wl_keyboard.key(serial.into(), time, code.raw() - 8, state.into());
if xstate.last_modifier_state != Some(modifiers) { if xstate.last_modifier_state != Some(modifiers) {
xstate.last_modifier_state = Some(modifiers); xstate.last_modifier_state = Some(modifiers);
wl_keyboard.modifiers( wl_keyboard.modifiers(
@ -480,7 +478,7 @@ impl Common {
button: u32, button: u32,
state: ButtonState, state: ButtonState,
serial: Serial, serial: Serial,
time: InputTime, time: u32,
) { ) {
if !self.config.cosmic_conf.xwayland_eavesdropping.pointer { if !self.config.cosmic_conf.xwayland_eavesdropping.pointer {
return; return;
@ -520,7 +518,7 @@ impl Common {
tracing::trace!("Forwaring ptr button {} {:?} to Xwayland", button, state); tracing::trace!("Forwaring ptr button {} {:?} to Xwayland", button, state);
for wl_pointer in pointer.client_pointers(&xstate.client) { for wl_pointer in pointer.client_pointers(&xstate.client) {
wl_pointer.button(serial.into(), time.millis(), button, state.into()); wl_pointer.button(serial.into(), time, button, state.into());
} }
} }
@ -810,7 +808,6 @@ impl XwmHandler for State {
); );
} }
let fullscreen = window.is_fullscreen().then(|| seat.active_output()); let fullscreen = window.is_fullscreen().then(|| seat.active_output());
let minimized = window.is_hidden();
let maximized = window.is_maximized(); let maximized = window.is_maximized();
if let Some(pending) = shell if let Some(pending) = shell
.pending_windows .pending_windows
@ -819,7 +816,6 @@ impl XwmHandler for State {
{ {
pending.seat = seat; pending.seat = seat;
pending.fullscreen = fullscreen; pending.fullscreen = fullscreen;
pending.minimized = minimized;
pending.maximized = maximized; pending.maximized = maximized;
} else { } else {
let surface = CosmicSurface::from(window); let surface = CosmicSurface::from(window);
@ -827,7 +823,6 @@ impl XwmHandler for State {
surface, surface,
seat, seat,
fullscreen, fullscreen,
minimized,
maximized, maximized,
sticky: false, sticky: false,
}) })
@ -1047,29 +1042,17 @@ impl XwmHandler for State {
true, true,
) { ) {
std::mem::drop(shell); std::mem::drop(shell);
match grab.grab_type() { if grab.is_touch_grab() {
GrabType::Touch => { seat.get_touch()
seat.get_touch() .unwrap()
.unwrap() .set_grab(self, grab, SERIAL_COUNTER.next_serial())
.set_grab(self, grab, SERIAL_COUNTER.next_serial()) } else {
} seat.get_pointer().unwrap().set_grab(
GrabType::Pointer => seat.get_pointer().unwrap().set_grab(
self, self,
grab, grab,
SERIAL_COUNTER.next_serial(), SERIAL_COUNTER.next_serial(),
focus, focus,
), )
GrabType::TabletTool => seat
.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(
self,
grab,
InputTime::now(),
SERIAL_COUNTER.next_serial(),
focus,
),
} }
} }
} }
@ -1090,29 +1073,17 @@ impl XwmHandler for State {
true, true,
) { ) {
std::mem::drop(shell); std::mem::drop(shell);
match grab.grab_type() { if grab.is_touch_grab() {
GrabType::Touch => { seat.get_touch()
seat.get_touch() .unwrap()
.unwrap() .set_grab(self, grab, SERIAL_COUNTER.next_serial())
.set_grab(self, grab, SERIAL_COUNTER.next_serial()) } else {
} seat.get_pointer().unwrap().set_grab(
GrabType::Pointer => seat.get_pointer().unwrap().set_grab(
self, self,
grab, grab,
SERIAL_COUNTER.next_serial(), SERIAL_COUNTER.next_serial(),
focus, focus,
), )
GrabType::TabletTool => seat
.tablet_seat()
.get_tool(grab.tool().unwrap())
.unwrap()
.set_grab(
self,
grab,
InputTime::now(),
SERIAL_COUNTER.next_serial(),
focus,
),
} }
} }
} }