Merge branch 'master' into fullscreen_panic_fix
This commit is contained in:
commit
00bf8fe215
43 changed files with 632 additions and 1790 deletions
8
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
8
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
- [ ] 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.
|
||||||
|
|
||||||
41
Cargo.lock
generated
41
Cargo.lock
generated
|
|
@ -1268,7 +1268,7 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"option-ext",
|
"option-ext",
|
||||||
"redox_users",
|
"redox_users",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1578,7 +1578,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2875,7 +2875,7 @@ version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d463f34ca3c400fde3a054da0e0b8c6ffa21e4590922f3e18281bb5eeef4cbdc"
|
checksum = "d463f34ca3c400fde3a054da0e0b8c6ffa21e4590922f3e18281bb5eeef4cbdc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -3499,7 +3499,7 @@ version = "0.50.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -4342,9 +4342,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-xml"
|
name = "quick-xml"
|
||||||
version = "0.37.5"
|
version = "0.38.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb"
|
checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
@ -4685,7 +4685,7 @@ dependencies = [
|
||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys 0.11.0",
|
"linux-raw-sys 0.11.0",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -4992,7 +4992,7 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smithay"
|
name = "smithay"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
source = "git+https://github.com/smithay/smithay.git?rev=8148d67#8148d67ea3ee3959a84970e8f80f591e068e65ce"
|
source = "git+https://github.com/smithay/smithay.git?rev=3d3f9e3#3d3f9e359352d95cffd1e53287d57df427fcbd34"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aliasable",
|
"aliasable",
|
||||||
"appendlist",
|
"appendlist",
|
||||||
|
|
@ -5028,6 +5028,7 @@ dependencies = [
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"thiserror 2.0.17",
|
"thiserror 2.0.17",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
"tracy-client",
|
||||||
"udev",
|
"udev",
|
||||||
"wayland-client",
|
"wayland-client",
|
||||||
"wayland-cursor",
|
"wayland-cursor",
|
||||||
|
|
@ -5331,7 +5332,7 @@ dependencies = [
|
||||||
"getrandom 0.3.4",
|
"getrandom 0.3.4",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustix 1.1.2",
|
"rustix 1.1.2",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -5638,9 +5639,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracy-client"
|
name = "tracy-client"
|
||||||
version = "0.18.2"
|
version = "0.18.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ef54005d3d760186fd662dad4b7bb27ecd5531cdef54d1573ebd3f20a9205ed7"
|
checksum = "a4f6fc3baeac5d86ab90c772e9e30620fc653bf1864295029921a15ef478e6a5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"loom",
|
"loom",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
|
@ -6033,9 +6034,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-backend"
|
name = "wayland-backend"
|
||||||
version = "0.3.11"
|
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 = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35"
|
checksum = "fee64194ccd96bf648f42a65a7e589547096dfa702f7cadef84347b66ad164f9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"downcast-rs",
|
"downcast-rs",
|
||||||
|
|
@ -6158,9 +6159,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-scanner"
|
name = "wayland-scanner"
|
||||||
version = "0.31.7"
|
version = "0.31.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3"
|
checksum = "5423e94b6a63e68e439803a3e153a9252d5ead12fd853334e2ad33997e3889e3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quick-xml",
|
"quick-xml",
|
||||||
|
|
@ -6169,9 +6170,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-server"
|
name = "wayland-server"
|
||||||
version = "0.31.10"
|
version = "0.31.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fcbd4f3aba6c9fba70445ad2a484c0ef0356c1a9459b1e8e435bedc1971a6222"
|
checksum = "9297ab90f8d1f597711d36455c5b1b2290eca59b8134485e377a296b80b118c9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.4",
|
"bitflags 2.9.4",
|
||||||
"downcast-rs",
|
"downcast-rs",
|
||||||
|
|
@ -6182,9 +6183,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-sys"
|
name = "wayland-sys"
|
||||||
version = "0.31.7"
|
version = "0.31.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142"
|
checksum = "1e6dbfc3ac5ef974c92a2235805cc0114033018ae1290a72e474aa8b28cbbdfd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dlib",
|
"dlib",
|
||||||
"log",
|
"log",
|
||||||
|
|
@ -6352,7 +6353,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.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,7 @@ debug = ["egui", "egui_plot", "smithay-egui", "anyhow/backtrace"]
|
||||||
default = ["systemd"]
|
default = ["systemd"]
|
||||||
systemd = ["libsystemd", "logind-zbus"]
|
systemd = ["libsystemd", "logind-zbus"]
|
||||||
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.dev.package.tiny-skia]
|
[profile.dev.package.tiny-skia]
|
||||||
opt-level = 2
|
opt-level = 2
|
||||||
|
|
@ -147,4 +148,4 @@ cosmic-protocols = { git = "https://github.com/pop-os//cosmic-protocols", branch
|
||||||
cosmic-client-toolkit = { git = "https://github.com/pop-os//cosmic-protocols", branch = "main" }
|
cosmic-client-toolkit = { git = "https://github.com/pop-os//cosmic-protocols", branch = "main" }
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
smithay = { git = "https://github.com/smithay/smithay.git", rev = "8148d67" }
|
smithay = { git = "https://github.com/smithay/smithay.git", rev = "3d3f9e3" }
|
||||||
|
|
|
||||||
|
|
@ -4,24 +4,18 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::EdidProduct;
|
use crate::EdidProduct;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct WorkspaceConfig {
|
pub struct WorkspaceConfig {
|
||||||
pub workspace_mode: WorkspaceMode,
|
pub workspace_mode: WorkspaceMode,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub workspace_layout: WorkspaceLayout,
|
pub workspace_layout: WorkspaceLayout,
|
||||||
|
#[serde(default)]
|
||||||
|
pub action_on_typing: Action,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for WorkspaceConfig {
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
workspace_mode: WorkspaceMode::OutputBound,
|
|
||||||
workspace_layout: WorkspaceLayout::Vertical,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
|
||||||
pub enum WorkspaceMode {
|
pub enum WorkspaceMode {
|
||||||
|
#[default]
|
||||||
OutputBound,
|
OutputBound,
|
||||||
Global,
|
Global,
|
||||||
}
|
}
|
||||||
|
|
@ -33,6 +27,14 @@ pub enum WorkspaceLayout {
|
||||||
Horizontal,
|
Horizontal,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum Action {
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
|
OpenLauncher,
|
||||||
|
OpenApplications,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct OutputMatch {
|
pub struct OutputMatch {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ unknown-keybinding = <غير محدد>
|
||||||
window-menu-minimize = صغِّر
|
window-menu-minimize = صغِّر
|
||||||
window-menu-maximize = كبِّر
|
window-menu-maximize = كبِّر
|
||||||
window-menu-fullscreen = ملء الشاشة
|
window-menu-fullscreen = ملء الشاشة
|
||||||
window-menu-tiled = جعل النافذة تطفو
|
window-menu-tiled = نافذة عائمة
|
||||||
window-menu-screenshot = التقط لقطة شاشة
|
window-menu-screenshot = التقط لقطة شاشة
|
||||||
window-menu-move = حرِّك
|
window-menu-move = حرِّك
|
||||||
window-menu-resize = تغيير الحجم
|
window-menu-resize = تغيير الحجم
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
a11y-zoom-move-continuously = Zobrazení se pohybuje plynule s ukazatelem
|
a11y-zoom-move-continuously = Zobrazení se pohybuje plynule s ukazatelem
|
||||||
a11y-zoom-move-onedge = Zobrazení se pohybuje, když ukazatel dosáhne kraje
|
a11y-zoom-move-onedge = Zobrazení se pohybuje, když ukazatel dosáhne okraje
|
||||||
a11y-zoom-move-centered = Zobrazení se pohybuje tak, aby ukazatel zůstal uprostřed
|
a11y-zoom-move-centered = Zobrazení se pohybuje tak, aby ukazatel zůstal uprostřed
|
||||||
a11y-zoom-settings = Nastavení lupy...
|
a11y-zoom-settings = Nastavení lupy...
|
||||||
grow-window = Zvětšit
|
grow-window = Zvětšit
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
a11y-zoom-move-continuously = Tampilan bergerak terus menerus dengan penunjuk
|
||||||
|
a11y-zoom-move-onedge = Tampilan bergerak saat penunjuk mencapai tepi
|
||||||
|
a11y-zoom-move-centered = Tampilan bergerak untuk menjaga penunjuk tetap di tengah
|
||||||
|
a11y-zoom-settings = Pengaturan kaca pembesar...
|
||||||
|
unknown-keybinding = <unset>
|
||||||
|
window-menu-resize-edge-top = Atas
|
||||||
|
window-menu-resize-edge-left = Kiri
|
||||||
|
window-menu-resize-edge-right = Kanan
|
||||||
|
window-menu-resize-edge-bottom = Bawah
|
||||||
|
window-menu-close = Tutup
|
||||||
|
window-menu-close-all = Tutup semua jendela
|
||||||
|
grow-window = Perbesar
|
||||||
|
shrink-window = Perkecil
|
||||||
|
swap-windows = Tukarkan Jendela
|
||||||
|
stack-windows = Tumpukkan Jendela
|
||||||
|
window-menu-screenshot = Ambil tangkapan layar
|
||||||
|
window-menu-move = Pindahkan
|
||||||
|
window-menu-resize = Ukur ulang
|
||||||
|
window-menu-minimize = Perkecil
|
||||||
|
window-menu-maximize = Perbesar
|
||||||
|
window-menu-fullscreen = Layar penuh
|
||||||
|
window-menu-tiled = Jendela apung
|
||||||
|
window-menu-move-prev-workspace = Pindahkan ke ruang kerja sebelumnya
|
||||||
|
window-menu-move-next-workspace = Pindahkan ke ruang kerja selanjutnya
|
||||||
|
window-menu-stack = Buat tumpukan jendela
|
||||||
|
window-menu-sticky = Jendela lengket
|
||||||
|
window-menu-unstack-all = Bongkar tumpukan jendela
|
||||||
|
window-menu-unstack = Bongkar tumpukan jendela
|
||||||
28
resources/i18n/kk/cosmic_comp.ftl
Normal file
28
resources/i18n/kk/cosmic_comp.ftl
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
a11y-zoom-move-continuously = Көрініс курсормен бірге үздіксіз қозғалады
|
||||||
|
a11y-zoom-move-onedge = Көрініс курсор жиекке жеткенде қозғалады
|
||||||
|
a11y-zoom-move-centered = Көрініс курсорды ортада сақтау үшін қозғалады
|
||||||
|
a11y-zoom-settings = Үлкейткіш баптаулары...
|
||||||
|
grow-window = Үлкейту
|
||||||
|
shrink-window = Кішірейту
|
||||||
|
swap-windows = Терезелерді алмастыру
|
||||||
|
stack-windows = Терезелерді жинақтау
|
||||||
|
unknown-keybinding = <орнатылмаған>
|
||||||
|
window-menu-minimize = Қайыру
|
||||||
|
window-menu-maximize = Жазық қылу
|
||||||
|
window-menu-fullscreen = Толық экран
|
||||||
|
window-menu-tiled = Қалқымалы терезе
|
||||||
|
window-menu-screenshot = Скриншот түсіру
|
||||||
|
window-menu-move = Жылжыту
|
||||||
|
window-menu-resize = Өлшемін өзгерту
|
||||||
|
window-menu-move-prev-workspace = Алдыңғы жұмыс орнына жылжыту
|
||||||
|
window-menu-move-next-workspace = Келесі жұмыс орнына жылжыту
|
||||||
|
window-menu-stack = Терезелер жинағын жасау
|
||||||
|
window-menu-unstack-all = Терезелерді жинақтан шығару
|
||||||
|
window-menu-unstack = Терезені жинақтан шығару
|
||||||
|
window-menu-sticky = Жабысқақ терезе
|
||||||
|
window-menu-close = Жабу
|
||||||
|
window-menu-close-all = Барлық терезелерді жабу
|
||||||
|
window-menu-resize-edge-top = Жоғарғы
|
||||||
|
window-menu-resize-edge-left = Сол жақ
|
||||||
|
window-menu-resize-edge-right = Оң жақ
|
||||||
|
window-menu-resize-edge-bottom = Төменгі
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
window-menu-resize-edge-top = 상단
|
||||||
|
window-menu-resize-edge-left = 좌측
|
||||||
|
window-menu-resize-edge-right = 우측
|
||||||
|
window-menu-resize-edge-bottom = 하단
|
||||||
|
window-menu-move = 이동
|
||||||
|
window-menu-minimize = 최소화
|
||||||
|
window-menu-maximize = 최대화
|
||||||
|
window-menu-fullscreen = 전체 화면
|
||||||
|
window-menu-move-prev-workspace = 이전 작업 공간으로 이동
|
||||||
|
window-menu-move-next-workspace = 다음 작업 공간으로 이동
|
||||||
|
a11y-zoom-settings = 돋보기 설정...
|
||||||
|
grow-window = 확대
|
||||||
|
shrink-window = 축소
|
||||||
|
swap-windows = 창 바꾸기
|
||||||
|
stack-windows = 창 스택
|
||||||
|
window-menu-tiled = 플로팅 창으로 전환
|
||||||
|
window-menu-screenshot = 스크린샷 찍기
|
||||||
|
window-menu-resize = 크기 조정
|
||||||
|
window-menu-stack = 창 스택 생성
|
||||||
|
window-menu-unstack-all = 모든 창 스택 해제
|
||||||
|
window-menu-unstack = 창 스택 해제
|
||||||
|
a11y-zoom-move-continuously = 포인터를 따라 화면이 계속 이동
|
||||||
|
a11y-zoom-move-onedge = 포인터가 가장자리에 도달할 때 화면 이동
|
||||||
|
a11y-zoom-move-centered = 포인터를 화면 중앙에 유지하며 이동
|
||||||
|
window-menu-close = 닫기
|
||||||
|
window-menu-close-all = 모든 창 닫기
|
||||||
|
unknown-keybinding = <unset>
|
||||||
|
window-menu-sticky = 고정된 창
|
||||||
0
resources/i18n/ml/cosmic_comp.ftl
Normal file
0
resources/i18n/ml/cosmic_comp.ftl
Normal file
0
resources/i18n/ms/cosmic_comp.ftl
Normal file
0
resources/i18n/ms/cosmic_comp.ftl
Normal file
|
|
@ -1,26 +1,26 @@
|
||||||
a11y-zoom-move-continuously = Vergroting volgt muispijltje
|
a11y-zoom-move-continuously = Aanzicht met de cursor mee laten bewegen
|
||||||
a11y-zoom-move-onedge = Vergroting verplaatst als muispijltje een schermrand raakt
|
a11y-zoom-move-onedge = Aanzicht verplaatst zich pas als de cursor een schermrand raakt
|
||||||
a11y-zoom-move-centered = Vergroting houdt muispijltje steeds in het midden
|
a11y-zoom-move-centered = Aanzicht houdt de cursor gecentreerd
|
||||||
a11y-zoom-settings = Vergrootglasinstellingen…
|
a11y-zoom-settings = Instellingen van het vergrootglas…
|
||||||
grow-window = Vergroten
|
grow-window = Vergroten
|
||||||
shrink-window = Verkleinen
|
shrink-window = Verkleinen
|
||||||
swap-windows = Vensters omwisselen
|
swap-windows = Vensters omwisselen
|
||||||
stack-windows = Vensters stapelen
|
stack-windows = Vensters stapelen
|
||||||
unknown-keybinding = <niet ingesteld>
|
unknown-keybinding = <unset>
|
||||||
window-menu-minimize = Minimaliseer
|
window-menu-minimize = Minimaliseren
|
||||||
window-menu-maximize = Maximaliseer
|
window-menu-maximize = Maximaliseren
|
||||||
window-menu-tiled = Laat venster zweven
|
window-menu-tiled = Venster laten zweven
|
||||||
window-menu-screenshot = Maak schermafdruk
|
window-menu-screenshot = Schermafdruk maken
|
||||||
window-menu-move = Verplaats
|
window-menu-move = Verplaatsen
|
||||||
window-menu-resize = Pas grootte aan
|
window-menu-resize = Grootte aanpassen
|
||||||
window-menu-move-prev-workspace = Verplaats naar vorig werkblad
|
window-menu-move-prev-workspace = Naar vorig werkblad verplaatsen
|
||||||
window-menu-move-next-workspace = Verplaats naar volgend werkblad
|
window-menu-move-next-workspace = Naar volgend werkblad verplaatsen
|
||||||
window-menu-stack = Begin een vensterstapel
|
window-menu-stack = Vensterstapel beginnen
|
||||||
window-menu-unstack-all = Beëindig vensterstapel
|
window-menu-unstack-all = Vensterstapel opheffen
|
||||||
window-menu-unstack = Haal venster uit stapel
|
window-menu-unstack = Venster uit stapel halen
|
||||||
window-menu-sticky = Vastgezet venster
|
window-menu-sticky = Venster vastzetten
|
||||||
window-menu-close = Sluit
|
window-menu-close = Sluiten
|
||||||
window-menu-close-all = Sluit alle vensters
|
window-menu-close-all = Alle vensters sluiten
|
||||||
window-menu-resize-edge-top = Boven
|
window-menu-resize-edge-top = Boven
|
||||||
window-menu-resize-edge-left = Links
|
window-menu-resize-edge-left = Links
|
||||||
window-menu-resize-edge-right = Rechts
|
window-menu-resize-edge-right = Rechts
|
||||||
|
|
|
||||||
0
resources/i18n/oc/cosmic_comp.ftl
Normal file
0
resources/i18n/oc/cosmic_comp.ftl
Normal file
0
resources/i18n/pa/cosmic_comp.ftl
Normal file
0
resources/i18n/pa/cosmic_comp.ftl
Normal file
|
|
@ -19,7 +19,7 @@ window-menu-move-next-workspace = На след. рабочий стол
|
||||||
window-menu-stack = Создать стопку окон
|
window-menu-stack = Создать стопку окон
|
||||||
window-menu-unstack-all = Распустить стопку окон
|
window-menu-unstack-all = Распустить стопку окон
|
||||||
window-menu-unstack = Убрать из стопки
|
window-menu-unstack = Убрать из стопки
|
||||||
window-menu-sticky = Прилипание окна
|
window-menu-sticky = Закрепить окно поверх других
|
||||||
window-menu-close = Закрыть
|
window-menu-close = Закрыть
|
||||||
window-menu-close-all = Закрыть все окна
|
window-menu-close-all = Закрыть все окна
|
||||||
window-menu-resize-edge-top = Наверх
|
window-menu-resize-edge-top = Наверх
|
||||||
|
|
|
||||||
0
resources/i18n/ti/cosmic_comp.ftl
Normal file
0
resources/i18n/ti/cosmic_comp.ftl
Normal file
|
|
@ -5,7 +5,7 @@ stack-windows = Групувати вікна
|
||||||
unknown-keybinding = <unset>
|
unknown-keybinding = <unset>
|
||||||
window-menu-minimize = Згорнути
|
window-menu-minimize = Згорнути
|
||||||
window-menu-maximize = Розгорнути
|
window-menu-maximize = Розгорнути
|
||||||
window-menu-tiled = Плаваюче вікно
|
window-menu-tiled = Плавуче вікно
|
||||||
window-menu-screenshot = Зробити знімок екрана
|
window-menu-screenshot = Зробити знімок екрана
|
||||||
window-menu-move = Перемістити
|
window-menu-move = Перемістити
|
||||||
window-menu-resize = Змінити розмір
|
window-menu-resize = Змінити розмір
|
||||||
|
|
|
||||||
0
resources/i18n/uz/cosmic_comp.ftl
Normal file
0
resources/i18n/uz/cosmic_comp.ftl
Normal file
|
|
@ -8,7 +8,7 @@ use crate::{
|
||||||
config::{CompTransformDef, EdidProduct, ScreenFilter},
|
config::{CompTransformDef, EdidProduct, ScreenFilter},
|
||||||
shell::Shell,
|
shell::Shell,
|
||||||
utils::{env::dev_list_var, prelude::*},
|
utils::{env::dev_list_var, prelude::*},
|
||||||
wayland::handlers::screencopy::PendingImageCopyData,
|
wayland::handlers::image_copy_capture::PendingImageCopyData,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
|
@ -95,6 +95,7 @@ pub struct Device {
|
||||||
pub drm: GbmDrmOutputManager,
|
pub drm: GbmDrmOutputManager,
|
||||||
|
|
||||||
supports_atomic: bool,
|
supports_atomic: bool,
|
||||||
|
pub texture_formats: FormatSet,
|
||||||
event_token: Option<RegistrationToken>,
|
event_token: Option<RegistrationToken>,
|
||||||
pub socket: Option<Socket>,
|
pub socket: Option<Socket>,
|
||||||
}
|
}
|
||||||
|
|
@ -285,7 +286,7 @@ impl State {
|
||||||
.with_context(|| format!("Failed to add drm device to event loop: {}", dev))?;
|
.with_context(|| format!("Failed to add drm device to event loop: {}", dev))?;
|
||||||
|
|
||||||
let socket = match (!is_software)
|
let socket = match (!is_software)
|
||||||
.then(|| self.create_socket(dh, render_node, texture_formats))
|
.then(|| self.create_socket(dh, render_node, texture_formats.clone()))
|
||||||
.transpose()
|
.transpose()
|
||||||
{
|
{
|
||||||
Ok(socket) => socket,
|
Ok(socket) => socket,
|
||||||
|
|
@ -349,6 +350,7 @@ impl State {
|
||||||
},
|
},
|
||||||
|
|
||||||
supports_atomic,
|
supports_atomic,
|
||||||
|
texture_formats,
|
||||||
event_token: Some(token),
|
event_token: Some(token),
|
||||||
socket,
|
socket,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ use indexmap::IndexMap;
|
||||||
use render::gles::GbmGlowBackend;
|
use render::gles::GbmGlowBackend;
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::{
|
backend::{
|
||||||
allocator::{dmabuf::Dmabuf, format::FormatSet},
|
allocator::{Buffer, dmabuf::Dmabuf, format::FormatSet},
|
||||||
drm::{DrmDeviceFd, DrmNode, NodeType, VrrSupport, output::DrmOutputRenderElements},
|
drm::{DrmDeviceFd, DrmNode, NodeType, VrrSupport, output::DrmOutputRenderElements},
|
||||||
egl::{EGLContext, EGLDevice, EGLDisplay},
|
egl::{EGLContext, EGLDevice, EGLDisplay},
|
||||||
input::InputEvent,
|
input::InputEvent,
|
||||||
|
|
@ -491,7 +491,7 @@ impl KmsState {
|
||||||
global: &DmabufGlobal,
|
global: &DmabufGlobal,
|
||||||
dmabuf: Dmabuf,
|
dmabuf: Dmabuf,
|
||||||
) -> Result<DrmNode> {
|
) -> Result<DrmNode> {
|
||||||
let device = self
|
let mut device = self
|
||||||
.drm_devices
|
.drm_devices
|
||||||
.values_mut()
|
.values_mut()
|
||||||
.find(|device| {
|
.find(|device| {
|
||||||
|
|
@ -503,6 +503,21 @@ impl KmsState {
|
||||||
})
|
})
|
||||||
.context("Couldn't find gpu for dmabuf global")?;
|
.context("Couldn't find gpu for dmabuf global")?;
|
||||||
|
|
||||||
|
// If device advertised to client doesn't support format/modifier, select
|
||||||
|
// first device that does. This is needed for image-copy from
|
||||||
|
// output/toplevel on a different node.
|
||||||
|
//
|
||||||
|
// TODO: After
|
||||||
|
// https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/268,
|
||||||
|
// only try the device specified explicitly by the client, if set.
|
||||||
|
if !device.texture_formats.contains(&dmabuf.format()) {
|
||||||
|
device = self
|
||||||
|
.drm_devices
|
||||||
|
.values_mut()
|
||||||
|
.find(|device| device.texture_formats.contains(&dmabuf.format()))
|
||||||
|
.context("Dmabuf cannot be imported on any gpu")?;
|
||||||
|
}
|
||||||
|
|
||||||
let new_client = if let Some(client) = client {
|
let new_client = if let Some(client) = client {
|
||||||
let new = device.inner.active_clients.insert(client.id());
|
let new = device.inner.active_clients.insert(client.id());
|
||||||
device.inner.update_egl(
|
device.inner.update_egl(
|
||||||
|
|
|
||||||
|
|
@ -11,14 +11,9 @@ use crate::{
|
||||||
shell::Shell,
|
shell::Shell,
|
||||||
state::SurfaceDmabufFeedback,
|
state::SurfaceDmabufFeedback,
|
||||||
utils::prelude::*,
|
utils::prelude::*,
|
||||||
wayland::{
|
wayland::handlers::{
|
||||||
handlers::{
|
compositor::recursive_frame_time_estimation,
|
||||||
compositor::recursive_frame_time_estimation,
|
image_copy_capture::{FrameHolder, PendingImageCopyData, SessionData, submit_buffer},
|
||||||
screencopy::{FrameHolder, PendingImageCopyData, SessionData, submit_buffer},
|
|
||||||
},
|
|
||||||
protocols::screencopy::{
|
|
||||||
FailureReason, Frame as ScreencopyFrame, SessionRef as ScreencopySessionRef,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -82,6 +77,9 @@ use smithay::{
|
||||||
utils::{Clock, Monotonic, Physical, Point, Rectangle, Transform},
|
utils::{Clock, Monotonic, Physical, Point, Rectangle, Transform},
|
||||||
wayland::{
|
wayland::{
|
||||||
dmabuf::{DmabufFeedbackBuilder, get_dmabuf},
|
dmabuf::{DmabufFeedbackBuilder, get_dmabuf},
|
||||||
|
image_copy_capture::{
|
||||||
|
CaptureFailureReason, Frame as ScreencopyFrame, SessionRef as ScreencopySessionRef,
|
||||||
|
},
|
||||||
presentation::Refresh,
|
presentation::Refresh,
|
||||||
seat::WaylandFocus,
|
seat::WaylandFocus,
|
||||||
shm::{shm_format_to_fourcc, with_buffer_contents},
|
shm::{shm_format_to_fourcc, with_buffer_contents},
|
||||||
|
|
@ -1082,7 +1080,7 @@ impl SurfaceThreadState {
|
||||||
let frames = self
|
let frames = self
|
||||||
.mirroring
|
.mirroring
|
||||||
.is_none()
|
.is_none()
|
||||||
.then(|| take_screencopy_frames(&self.output, &mut elements, &mut has_cursor_mode_none))
|
.then(|| take_screencopy_frames(&self.output, &elements, &mut has_cursor_mode_none))
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
// actual rendering
|
// actual rendering
|
||||||
|
|
@ -1355,13 +1353,6 @@ impl SurfaceThreadState {
|
||||||
(&session, frame, res),
|
(&session, frame, res),
|
||||||
now.into(),
|
now.into(),
|
||||||
) {
|
) {
|
||||||
session
|
|
||||||
.user_data()
|
|
||||||
.get::<SessionData>()
|
|
||||||
.unwrap()
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.reset();
|
|
||||||
tracing::warn!(?err, "Failed to screencopy");
|
tracing::warn!(?err, "Failed to screencopy");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1390,15 +1381,8 @@ impl SurfaceThreadState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
for (session, frame, _) in frames {
|
for (_session, frame, _) in frames {
|
||||||
session
|
frame.fail(CaptureFailureReason::Unknown);
|
||||||
.user_data()
|
|
||||||
.get::<SessionData>()
|
|
||||||
.unwrap()
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.reset();
|
|
||||||
frame.fail(FailureReason::Unknown);
|
|
||||||
}
|
}
|
||||||
return Err(err).with_context(|| "Failed to submit result for display");
|
return Err(err).with_context(|| "Failed to submit result for display");
|
||||||
}
|
}
|
||||||
|
|
@ -1608,10 +1592,9 @@ fn get_surface_dmabuf_feedback(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Don't mutate `elements`
|
|
||||||
fn take_screencopy_frames(
|
fn take_screencopy_frames(
|
||||||
output: &Output,
|
output: &Output,
|
||||||
elements: &mut Vec<CosmicElement<GlMultiRenderer>>,
|
elements: &[CosmicElement<GlMultiRenderer>],
|
||||||
has_cursor_mode_none: &mut bool,
|
has_cursor_mode_none: &mut bool,
|
||||||
) -> Vec<(
|
) -> Vec<(
|
||||||
ScreencopySessionRef,
|
ScreencopySessionRef,
|
||||||
|
|
@ -1626,7 +1609,15 @@ fn take_screencopy_frames(
|
||||||
let session_data = session.user_data().get::<SessionData>().unwrap();
|
let session_data = session.user_data().get::<SessionData>().unwrap();
|
||||||
let mut damage_tracking = session_data.lock().unwrap();
|
let mut damage_tracking = session_data.lock().unwrap();
|
||||||
|
|
||||||
let old_len = if !additional_damage.is_empty() {
|
let buffer = frame.buffer();
|
||||||
|
let age = if matches!(buffer_type(&buffer), Some(BufferType::Shm)) {
|
||||||
|
// TODO re-use offscreen buffer to damage track screencopy to shm
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
};
|
||||||
|
|
||||||
|
if !additional_damage.is_empty() {
|
||||||
let area = output
|
let area = output
|
||||||
.current_mode()
|
.current_mode()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
@ -1636,41 +1627,26 @@ fn take_screencopy_frames(
|
||||||
.to_buffer(1, Transform::Normal)
|
.to_buffer(1, Transform::Normal)
|
||||||
.to_f64();
|
.to_f64();
|
||||||
|
|
||||||
let old_len = elements.len();
|
let additional_damage_elements: Vec<_> = additional_damage
|
||||||
elements.extend(
|
.into_iter()
|
||||||
additional_damage
|
.map(|rect| {
|
||||||
.into_iter()
|
rect.to_f64()
|
||||||
.map(|rect| {
|
.to_logical(
|
||||||
rect.to_f64()
|
output.current_scale().fractional_scale(),
|
||||||
.to_logical(
|
output.current_transform(),
|
||||||
output.current_scale().fractional_scale(),
|
&area,
|
||||||
output.current_transform(),
|
)
|
||||||
&area,
|
.to_i32_round()
|
||||||
)
|
})
|
||||||
.to_i32_round()
|
.map(DamageElement::new)
|
||||||
})
|
.collect();
|
||||||
.map(DamageElement::new)
|
let _ = damage_tracking
|
||||||
.map(Into::into),
|
.dt
|
||||||
);
|
.damage_output(age, &additional_damage_elements);
|
||||||
|
|
||||||
Some(old_len)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let buffer = frame.buffer();
|
|
||||||
let age = if matches!(buffer_type(&frame.buffer()), Some(BufferType::Shm)) {
|
|
||||||
// TODO re-use offscreen buffer to damage track screencopy to shm
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
damage_tracking.age_for_buffer(&buffer)
|
|
||||||
};
|
|
||||||
let res = damage_tracking.dt.damage_output(age, elements);
|
let res = damage_tracking.dt.damage_output(age, elements);
|
||||||
|
|
||||||
if let Some(old_len) = old_len {
|
|
||||||
elements.truncate(old_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !session.draw_cursor() {
|
if !session.draw_cursor() {
|
||||||
*has_cursor_mode_none = true;
|
*has_cursor_mode_none = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ where
|
||||||
Cursor(RescaleRenderElement<RelocateRenderElement<CursorRenderElement<R>>>),
|
Cursor(RescaleRenderElement<RelocateRenderElement<CursorRenderElement<R>>>),
|
||||||
Dnd(WaylandSurfaceRenderElement<R>),
|
Dnd(WaylandSurfaceRenderElement<R>),
|
||||||
MoveGrab(RescaleRenderElement<CosmicMappedRenderElement<R>>),
|
MoveGrab(RescaleRenderElement<CosmicMappedRenderElement<R>>),
|
||||||
AdditionalDamage(DamageElement),
|
|
||||||
Postprocess(
|
Postprocess(
|
||||||
CropRenderElement<RelocateRenderElement<RescaleRenderElement<TextureShaderElement>>>,
|
CropRenderElement<RelocateRenderElement<RescaleRenderElement<TextureShaderElement>>>,
|
||||||
),
|
),
|
||||||
|
|
@ -53,7 +52,6 @@ where
|
||||||
CosmicElement::Cursor(elem) => elem.id(),
|
CosmicElement::Cursor(elem) => elem.id(),
|
||||||
CosmicElement::Dnd(elem) => elem.id(),
|
CosmicElement::Dnd(elem) => elem.id(),
|
||||||
CosmicElement::MoveGrab(elem) => elem.id(),
|
CosmicElement::MoveGrab(elem) => elem.id(),
|
||||||
CosmicElement::AdditionalDamage(elem) => elem.id(),
|
|
||||||
CosmicElement::Postprocess(elem) => elem.id(),
|
CosmicElement::Postprocess(elem) => elem.id(),
|
||||||
CosmicElement::Zoom(elem) => elem.id(),
|
CosmicElement::Zoom(elem) => elem.id(),
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
|
|
@ -67,7 +65,6 @@ where
|
||||||
CosmicElement::Cursor(elem) => elem.current_commit(),
|
CosmicElement::Cursor(elem) => elem.current_commit(),
|
||||||
CosmicElement::Dnd(elem) => elem.current_commit(),
|
CosmicElement::Dnd(elem) => elem.current_commit(),
|
||||||
CosmicElement::MoveGrab(elem) => elem.current_commit(),
|
CosmicElement::MoveGrab(elem) => elem.current_commit(),
|
||||||
CosmicElement::AdditionalDamage(elem) => elem.current_commit(),
|
|
||||||
CosmicElement::Postprocess(elem) => elem.current_commit(),
|
CosmicElement::Postprocess(elem) => elem.current_commit(),
|
||||||
CosmicElement::Zoom(elem) => elem.current_commit(),
|
CosmicElement::Zoom(elem) => elem.current_commit(),
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
|
|
@ -81,7 +78,6 @@ where
|
||||||
CosmicElement::Cursor(elem) => elem.src(),
|
CosmicElement::Cursor(elem) => elem.src(),
|
||||||
CosmicElement::Dnd(elem) => elem.src(),
|
CosmicElement::Dnd(elem) => elem.src(),
|
||||||
CosmicElement::MoveGrab(elem) => elem.src(),
|
CosmicElement::MoveGrab(elem) => elem.src(),
|
||||||
CosmicElement::AdditionalDamage(elem) => elem.src(),
|
|
||||||
CosmicElement::Postprocess(elem) => elem.src(),
|
CosmicElement::Postprocess(elem) => elem.src(),
|
||||||
CosmicElement::Zoom(elem) => elem.src(),
|
CosmicElement::Zoom(elem) => elem.src(),
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
|
|
@ -95,7 +91,6 @@ where
|
||||||
CosmicElement::Cursor(elem) => elem.geometry(scale),
|
CosmicElement::Cursor(elem) => elem.geometry(scale),
|
||||||
CosmicElement::Dnd(elem) => elem.geometry(scale),
|
CosmicElement::Dnd(elem) => elem.geometry(scale),
|
||||||
CosmicElement::MoveGrab(elem) => elem.geometry(scale),
|
CosmicElement::MoveGrab(elem) => elem.geometry(scale),
|
||||||
CosmicElement::AdditionalDamage(elem) => elem.geometry(scale),
|
|
||||||
CosmicElement::Postprocess(elem) => elem.geometry(scale),
|
CosmicElement::Postprocess(elem) => elem.geometry(scale),
|
||||||
CosmicElement::Zoom(elem) => elem.geometry(scale),
|
CosmicElement::Zoom(elem) => elem.geometry(scale),
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
|
|
@ -109,7 +104,6 @@ where
|
||||||
CosmicElement::Cursor(elem) => elem.location(scale),
|
CosmicElement::Cursor(elem) => elem.location(scale),
|
||||||
CosmicElement::Dnd(elem) => elem.location(scale),
|
CosmicElement::Dnd(elem) => elem.location(scale),
|
||||||
CosmicElement::MoveGrab(elem) => elem.location(scale),
|
CosmicElement::MoveGrab(elem) => elem.location(scale),
|
||||||
CosmicElement::AdditionalDamage(elem) => elem.location(scale),
|
|
||||||
CosmicElement::Postprocess(elem) => elem.location(scale),
|
CosmicElement::Postprocess(elem) => elem.location(scale),
|
||||||
CosmicElement::Zoom(elem) => elem.location(scale),
|
CosmicElement::Zoom(elem) => elem.location(scale),
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
|
|
@ -123,7 +117,6 @@ where
|
||||||
CosmicElement::Cursor(elem) => elem.transform(),
|
CosmicElement::Cursor(elem) => elem.transform(),
|
||||||
CosmicElement::Dnd(elem) => elem.transform(),
|
CosmicElement::Dnd(elem) => elem.transform(),
|
||||||
CosmicElement::MoveGrab(elem) => elem.transform(),
|
CosmicElement::MoveGrab(elem) => elem.transform(),
|
||||||
CosmicElement::AdditionalDamage(elem) => elem.transform(),
|
|
||||||
CosmicElement::Postprocess(elem) => elem.transform(),
|
CosmicElement::Postprocess(elem) => elem.transform(),
|
||||||
CosmicElement::Zoom(elem) => elem.transform(),
|
CosmicElement::Zoom(elem) => elem.transform(),
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
|
|
@ -141,7 +134,6 @@ where
|
||||||
CosmicElement::Cursor(elem) => elem.damage_since(scale, commit),
|
CosmicElement::Cursor(elem) => elem.damage_since(scale, commit),
|
||||||
CosmicElement::Dnd(elem) => elem.damage_since(scale, commit),
|
CosmicElement::Dnd(elem) => elem.damage_since(scale, commit),
|
||||||
CosmicElement::MoveGrab(elem) => elem.damage_since(scale, commit),
|
CosmicElement::MoveGrab(elem) => elem.damage_since(scale, commit),
|
||||||
CosmicElement::AdditionalDamage(elem) => elem.damage_since(scale, commit),
|
|
||||||
CosmicElement::Postprocess(elem) => elem.damage_since(scale, commit),
|
CosmicElement::Postprocess(elem) => elem.damage_since(scale, commit),
|
||||||
CosmicElement::Zoom(elem) => elem.damage_since(scale, commit),
|
CosmicElement::Zoom(elem) => elem.damage_since(scale, commit),
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
|
|
@ -155,7 +147,6 @@ where
|
||||||
CosmicElement::Cursor(elem) => elem.opaque_regions(scale),
|
CosmicElement::Cursor(elem) => elem.opaque_regions(scale),
|
||||||
CosmicElement::Dnd(elem) => elem.opaque_regions(scale),
|
CosmicElement::Dnd(elem) => elem.opaque_regions(scale),
|
||||||
CosmicElement::MoveGrab(elem) => elem.opaque_regions(scale),
|
CosmicElement::MoveGrab(elem) => elem.opaque_regions(scale),
|
||||||
CosmicElement::AdditionalDamage(elem) => elem.opaque_regions(scale),
|
|
||||||
CosmicElement::Postprocess(elem) => elem.opaque_regions(scale),
|
CosmicElement::Postprocess(elem) => elem.opaque_regions(scale),
|
||||||
CosmicElement::Zoom(elem) => elem.opaque_regions(scale),
|
CosmicElement::Zoom(elem) => elem.opaque_regions(scale),
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
|
|
@ -169,7 +160,6 @@ where
|
||||||
CosmicElement::Cursor(elem) => elem.alpha(),
|
CosmicElement::Cursor(elem) => elem.alpha(),
|
||||||
CosmicElement::Dnd(elem) => elem.alpha(),
|
CosmicElement::Dnd(elem) => elem.alpha(),
|
||||||
CosmicElement::MoveGrab(elem) => elem.alpha(),
|
CosmicElement::MoveGrab(elem) => elem.alpha(),
|
||||||
CosmicElement::AdditionalDamage(elem) => elem.alpha(),
|
|
||||||
CosmicElement::Postprocess(elem) => elem.alpha(),
|
CosmicElement::Postprocess(elem) => elem.alpha(),
|
||||||
CosmicElement::Zoom(elem) => elem.alpha(),
|
CosmicElement::Zoom(elem) => elem.alpha(),
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
|
|
@ -183,7 +173,6 @@ where
|
||||||
CosmicElement::Cursor(elem) => elem.kind(),
|
CosmicElement::Cursor(elem) => elem.kind(),
|
||||||
CosmicElement::Dnd(elem) => elem.kind(),
|
CosmicElement::Dnd(elem) => elem.kind(),
|
||||||
CosmicElement::MoveGrab(elem) => elem.kind(),
|
CosmicElement::MoveGrab(elem) => elem.kind(),
|
||||||
CosmicElement::AdditionalDamage(elem) => elem.kind(),
|
|
||||||
CosmicElement::Postprocess(elem) => elem.kind(),
|
CosmicElement::Postprocess(elem) => elem.kind(),
|
||||||
CosmicElement::Zoom(elem) => elem.kind(),
|
CosmicElement::Zoom(elem) => elem.kind(),
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
|
|
@ -212,9 +201,6 @@ where
|
||||||
CosmicElement::Cursor(elem) => elem.draw(frame, src, dst, damage, opaque_regions),
|
CosmicElement::Cursor(elem) => elem.draw(frame, src, dst, damage, opaque_regions),
|
||||||
CosmicElement::Dnd(elem) => elem.draw(frame, src, dst, damage, opaque_regions),
|
CosmicElement::Dnd(elem) => elem.draw(frame, src, dst, damage, opaque_regions),
|
||||||
CosmicElement::MoveGrab(elem) => elem.draw(frame, src, dst, damage, opaque_regions),
|
CosmicElement::MoveGrab(elem) => elem.draw(frame, src, dst, damage, opaque_regions),
|
||||||
CosmicElement::AdditionalDamage(elem) => {
|
|
||||||
RenderElement::<R>::draw(elem, frame, src, dst, damage, opaque_regions)
|
|
||||||
}
|
|
||||||
CosmicElement::Postprocess(elem) => {
|
CosmicElement::Postprocess(elem) => {
|
||||||
let glow_frame = R::glow_frame_mut(frame);
|
let glow_frame = R::glow_frame_mut(frame);
|
||||||
RenderElement::<GlowRenderer>::draw(
|
RenderElement::<GlowRenderer>::draw(
|
||||||
|
|
@ -250,7 +236,6 @@ where
|
||||||
CosmicElement::Cursor(elem) => elem.underlying_storage(renderer),
|
CosmicElement::Cursor(elem) => elem.underlying_storage(renderer),
|
||||||
CosmicElement::Dnd(elem) => elem.underlying_storage(renderer),
|
CosmicElement::Dnd(elem) => elem.underlying_storage(renderer),
|
||||||
CosmicElement::MoveGrab(elem) => elem.underlying_storage(renderer),
|
CosmicElement::MoveGrab(elem) => elem.underlying_storage(renderer),
|
||||||
CosmicElement::AdditionalDamage(elem) => elem.underlying_storage(renderer),
|
|
||||||
CosmicElement::Postprocess(elem) => {
|
CosmicElement::Postprocess(elem) => {
|
||||||
let glow_renderer = renderer.glow_renderer_mut();
|
let glow_renderer = renderer.glow_renderer_mut();
|
||||||
elem.underlying_storage(glow_renderer)
|
elem.underlying_storage(glow_renderer)
|
||||||
|
|
@ -281,17 +266,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> From<DamageElement> for CosmicElement<R>
|
|
||||||
where
|
|
||||||
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
|
|
||||||
R::TextureId: 'static,
|
|
||||||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
|
||||||
{
|
|
||||||
fn from(elem: DamageElement) -> Self {
|
|
||||||
Self::AdditionalDamage(elem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R> From<MemoryRenderBufferRenderElement<R>> for CosmicElement<R>
|
impl<R> From<MemoryRenderBufferRenderElement<R>> for CosmicElement<R>
|
||||||
where
|
where
|
||||||
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
|
R: Renderer + ImportAll + ImportMem + AsGlowRenderer,
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ use crate::{
|
||||||
handlers::{
|
handlers::{
|
||||||
compositor::FRAME_TIME_FILTER,
|
compositor::FRAME_TIME_FILTER,
|
||||||
data_device::get_dnd_icon,
|
data_device::get_dnd_icon,
|
||||||
screencopy::{FrameHolder, SessionData, render_session},
|
image_copy_capture::{FrameHolder, SessionData, render_session},
|
||||||
},
|
},
|
||||||
protocols::workspace::WorkspaceHandle,
|
protocols::workspace::WorkspaceHandle,
|
||||||
},
|
},
|
||||||
|
|
@ -1393,21 +1393,20 @@ where
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let old_len = elements.len();
|
let old_len = elements.len();
|
||||||
elements.extend(
|
let additional_damage_elements: Vec<_> = additional_damage
|
||||||
additional_damage
|
.into_iter()
|
||||||
.into_iter()
|
.map(|rect| {
|
||||||
.map(|rect| {
|
rect.to_f64()
|
||||||
rect.to_f64()
|
.to_logical(
|
||||||
.to_logical(
|
output.current_scale().fractional_scale(),
|
||||||
output.current_scale().fractional_scale(),
|
output.current_transform(),
|
||||||
output.current_transform(),
|
&area,
|
||||||
&area,
|
)
|
||||||
)
|
.to_i32_round()
|
||||||
.to_i32_round()
|
})
|
||||||
})
|
.map(DamageElement::new)
|
||||||
.map(DamageElement::new)
|
.collect();
|
||||||
.map(Into::into),
|
dt.damage_output(age, &additional_damage_elements)?;
|
||||||
);
|
|
||||||
|
|
||||||
Some(old_len)
|
Some(old_len)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1513,7 +1512,7 @@ where
|
||||||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
CosmicMappedRenderElement<R>: RenderElement<R>,
|
||||||
WorkspaceRenderElement<R>: RenderElement<R>,
|
WorkspaceRenderElement<R>: RenderElement<R>,
|
||||||
{
|
{
|
||||||
let mut elements: Vec<CosmicElement<R>> = workspace_elements(
|
let elements: Vec<CosmicElement<R>> = workspace_elements(
|
||||||
gpu,
|
gpu,
|
||||||
renderer,
|
renderer,
|
||||||
shell,
|
shell,
|
||||||
|
|
@ -1528,13 +1527,12 @@ where
|
||||||
|
|
||||||
if let Some(additional_damage) = additional_damage {
|
if let Some(additional_damage) = additional_damage {
|
||||||
let output_geo = output.geometry().to_local(output).as_logical();
|
let output_geo = output.geometry().to_local(output).as_logical();
|
||||||
elements.extend(
|
let additional_damage_elements: Vec<_> = additional_damage
|
||||||
additional_damage
|
.into_iter()
|
||||||
.into_iter()
|
.filter_map(|rect| rect.intersection(output_geo))
|
||||||
.filter_map(|rect| rect.intersection(output_geo))
|
.map(DamageElement::new)
|
||||||
.map(DamageElement::new)
|
.collect();
|
||||||
.map(Into::<CosmicElement<R>>::into),
|
damage_tracker.damage_output(age, &additional_damage_elements)?;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = damage_tracker.render_output(
|
let res = damage_tracker.render_output(
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,8 @@ use crate::{
|
||||||
zoom::ZoomState,
|
zoom::ZoomState,
|
||||||
},
|
},
|
||||||
utils::{prelude::*, quirks::workspace_overview_is_open},
|
utils::{prelude::*, quirks::workspace_overview_is_open},
|
||||||
wayland::{
|
wayland::handlers::{
|
||||||
handlers::{screencopy::SessionHolder, xwayland_keyboard_grab::XWaylandGrabSeat},
|
image_copy_capture::SessionHolder, xwayland_keyboard_grab::XWaylandGrabSeat,
|
||||||
protocols::screencopy::{BufferConstraints, CursorSessionRef},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use calloop::{
|
use calloop::{
|
||||||
|
|
@ -62,6 +61,7 @@ use smithay::{
|
||||||
},
|
},
|
||||||
utils::{Point, Rectangle, SERIAL_COUNTER, Serial},
|
utils::{Point, Rectangle, SERIAL_COUNTER, Serial},
|
||||||
wayland::{
|
wayland::{
|
||||||
|
image_copy_capture::{BufferConstraints, CursorSessionRef},
|
||||||
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitorSeat,
|
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitorSeat,
|
||||||
pointer_constraints::{PointerConstraint, with_pointer_constraint},
|
pointer_constraints::{PointerConstraint, with_pointer_constraint},
|
||||||
seat::WaylandFocus,
|
seat::WaylandFocus,
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ use crate::{
|
||||||
zoom::ZoomFocusTarget,
|
zoom::ZoomFocusTarget,
|
||||||
},
|
},
|
||||||
utils::prelude::*,
|
utils::prelude::*,
|
||||||
wayland::handlers::{screencopy::SessionHolder, xdg_shell::popup::get_popup_toplevel},
|
wayland::handlers::{image_copy_capture::SessionHolder, xdg_shell::popup::get_popup_toplevel},
|
||||||
};
|
};
|
||||||
use id_tree::NodeId;
|
use id_tree::NodeId;
|
||||||
use smithay::{
|
use smithay::{
|
||||||
|
|
|
||||||
|
|
@ -906,20 +906,22 @@ impl Drop for MoveGrab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut shell = state.common.shell.write();
|
|
||||||
shell
|
|
||||||
.workspaces
|
|
||||||
.active_mut(&cursor_output)
|
|
||||||
.unwrap()
|
|
||||||
.tiling_layer
|
|
||||||
.cleanup_drag();
|
|
||||||
shell.set_overview_mode(None, state.common.event_loop_handle.clone());
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut shell = state.common.shell.write();
|
||||||
|
shell
|
||||||
|
.workspaces
|
||||||
|
.active_mut(&cursor_output)
|
||||||
|
.unwrap()
|
||||||
|
.tiling_layer
|
||||||
|
.cleanup_drag();
|
||||||
|
shell.set_overview_mode(None, state.common.event_loop_handle.clone());
|
||||||
|
drop(shell);
|
||||||
|
|
||||||
{
|
{
|
||||||
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();
|
||||||
|
|
|
||||||
|
|
@ -1384,6 +1384,13 @@ impl TilingLayout {
|
||||||
) -> Option<NodeId> {
|
) -> Option<NodeId> {
|
||||||
let node_id = window.tiling_node_id.lock().unwrap().take()?;
|
let node_id = window.tiling_node_id.lock().unwrap().take()?;
|
||||||
|
|
||||||
|
// Initialize last_overview_hover to the placeholder position so that
|
||||||
|
// dropping without mouse movement restores the window to its original position
|
||||||
|
if matches!(type_, PlaceholderType::GrabbedWindow) {
|
||||||
|
self.last_overview_hover =
|
||||||
|
Some((None, TargetZone::InitialPlaceholder(node_id.clone())));
|
||||||
|
}
|
||||||
|
|
||||||
let data = self
|
let data = self
|
||||||
.queue
|
.queue
|
||||||
.trees
|
.trees
|
||||||
|
|
@ -2630,28 +2637,36 @@ impl TilingLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cleanup_drag(&mut self) {
|
pub fn cleanup_drag(&mut self) {
|
||||||
let gaps = self.gaps();
|
let old_tree = &self.queue.trees.back().unwrap().0;
|
||||||
|
let mut new_tree = None;
|
||||||
|
|
||||||
let mut tree = self.queue.trees.back().unwrap().0.copy_clone();
|
if let Some(root) = old_tree.root_node_id() {
|
||||||
|
for id in old_tree.traverse_pre_order_ids(root).unwrap() {
|
||||||
if let Some(root) = tree.root_node_id() {
|
match old_tree.get(&id).map(|node| node.data()) {
|
||||||
for id in tree
|
Ok(Data::Placeholder { .. }) => {
|
||||||
.traverse_pre_order_ids(root)
|
// Copy a tree on write
|
||||||
.unwrap()
|
let new_tree = new_tree.get_or_insert_with(|| old_tree.copy_clone());
|
||||||
.collect::<Vec<_>>()
|
TilingLayout::unmap_internal(new_tree, &id)
|
||||||
.into_iter()
|
}
|
||||||
{
|
|
||||||
match tree.get_mut(&id).map(|node| node.data_mut()) {
|
|
||||||
Ok(Data::Placeholder { .. }) => TilingLayout::unmap_internal(&mut tree, &id),
|
|
||||||
Ok(Data::Group { pill_indicator, .. }) if pill_indicator.is_some() => {
|
Ok(Data::Group { pill_indicator, .. }) if pill_indicator.is_some() => {
|
||||||
pill_indicator.take();
|
let new_tree = new_tree.get_or_insert_with(|| old_tree.copy_clone());
|
||||||
|
match new_tree.get_mut(&id).unwrap().data_mut() {
|
||||||
|
Data::Group { pill_indicator, .. } => {
|
||||||
|
*pill_indicator = None;
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let blocker = TilingLayout::update_positions(&self.output, &mut tree, gaps);
|
// If anything was changed, push updated tree
|
||||||
self.queue.push_tree(tree, ANIMATION_DURATION, blocker);
|
if let Some(mut new_tree) = new_tree {
|
||||||
|
let blocker =
|
||||||
|
TilingLayout::update_positions(&self.output, &mut new_tree, self.gaps());
|
||||||
|
self.queue.push_tree(new_tree, ANIMATION_DURATION, blocker);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2666,7 +2681,7 @@ impl TilingLayout {
|
||||||
window.set_bounds(layer_map.non_exclusive_zone().size);
|
window.set_bounds(layer_map.non_exclusive_zone().size);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mapped = match self.last_overview_hover.as_ref().map(|x| &x.1) {
|
let mapped = match self.last_overview_hover.as_ref().map(|(_, zone)| zone) {
|
||||||
Some(TargetZone::GroupEdge(group_id, direction)) if tree.get(group_id).is_ok() => {
|
Some(TargetZone::GroupEdge(group_id, direction)) if tree.get(group_id).is_ok() => {
|
||||||
let new_id = tree
|
let new_id = tree
|
||||||
.insert(
|
.insert(
|
||||||
|
|
@ -4039,7 +4054,7 @@ impl TilingLayout {
|
||||||
|
|
||||||
let is_overview = !matches!(overview.0, OverviewMode::None);
|
let is_overview = !matches!(overview.0, OverviewMode::None);
|
||||||
let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_))))
|
let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_))))
|
||||||
.then(|| self.last_overview_hover.as_ref().map(|x| &x.1));
|
.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 {
|
||||||
|
|
@ -4190,7 +4205,7 @@ impl TilingLayout {
|
||||||
let mut elements = Vec::default();
|
let mut elements = Vec::default();
|
||||||
|
|
||||||
let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_))))
|
let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_))))
|
||||||
.then(|| self.last_overview_hover.as_ref().map(|x| &x.1));
|
.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 {
|
||||||
|
|
@ -5563,11 +5578,18 @@ where
|
||||||
let elem_geometry = mapped.geometry().to_physical_precise_round(output_scale);
|
let elem_geometry = mapped.geometry().to_physical_precise_round(output_scale);
|
||||||
|
|
||||||
let scale = geo.size.to_f64() / original_geo.size.to_f64();
|
let scale = geo.size.to_f64() / original_geo.size.to_f64();
|
||||||
|
// In overview mode, don't pass max_size to avoid pre-clipping.
|
||||||
|
// Let constrain_render_elements handle scaling instead.
|
||||||
|
let max_size = if is_overview {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(geo.size.as_logical())
|
||||||
|
};
|
||||||
let shadow_element = mapped.shadow_render_element(
|
let shadow_element = mapped.shadow_render_element(
|
||||||
renderer,
|
renderer,
|
||||||
geo.loc.as_logical().to_physical_precise_round(output_scale)
|
geo.loc.as_logical().to_physical_precise_round(output_scale)
|
||||||
- elem_geometry.loc,
|
- elem_geometry.loc,
|
||||||
Some(geo.size.as_logical()),
|
max_size,
|
||||||
Scale::from(output_scale),
|
Scale::from(output_scale),
|
||||||
scale.x.min(scale.y),
|
scale.x.min(scale.y),
|
||||||
alpha,
|
alpha,
|
||||||
|
|
@ -5577,7 +5599,7 @@ where
|
||||||
//original_location,
|
//original_location,
|
||||||
geo.loc.as_logical().to_physical_precise_round(output_scale)
|
geo.loc.as_logical().to_physical_precise_round(output_scale)
|
||||||
- elem_geometry.loc,
|
- elem_geometry.loc,
|
||||||
Some(geo.size.as_logical()),
|
max_size,
|
||||||
Scale::from(output_scale),
|
Scale::from(output_scale),
|
||||||
alpha,
|
alpha,
|
||||||
None,
|
None,
|
||||||
|
|
|
||||||
|
|
@ -3135,8 +3135,8 @@ impl Shell {
|
||||||
toplevel_enter_workspace(window, to);
|
toplevel_enter_workspace(window, to);
|
||||||
|
|
||||||
// we can't restore to a given position
|
// we can't restore to a given position
|
||||||
if let WorkspaceRestoreData::Tiling(state) = &mut window_state {
|
if let WorkspaceRestoreData::Tiling(Some(state)) = &mut window_state {
|
||||||
state.take();
|
state.state.take();
|
||||||
}
|
}
|
||||||
// update fullscreen state to restore to the new workspace
|
// update fullscreen state to restore to the new workspace
|
||||||
if let WorkspaceRestoreData::Fullscreen(Some(FullscreenRestoreData {
|
if let WorkspaceRestoreData::Fullscreen(Some(FullscreenRestoreData {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ use crate::{
|
||||||
state::State,
|
state::State,
|
||||||
utils::{prelude::*, tween::EaseRectangle},
|
utils::{prelude::*, tween::EaseRectangle},
|
||||||
wayland::{
|
wayland::{
|
||||||
handlers::screencopy::ScreencopySessions,
|
handlers::image_copy_capture::ImageCopySessions,
|
||||||
protocols::{
|
protocols::{
|
||||||
toplevel_info::{toplevel_enter_output, toplevel_leave_output},
|
toplevel_info::{toplevel_enter_output, toplevel_leave_output},
|
||||||
workspace::{WorkspaceHandle, WorkspaceUpdateGuard},
|
workspace::{WorkspaceHandle, WorkspaceUpdateGuard},
|
||||||
|
|
@ -110,7 +110,7 @@ pub struct Workspace {
|
||||||
|
|
||||||
pub handle: WorkspaceHandle,
|
pub handle: WorkspaceHandle,
|
||||||
pub focus_stack: FocusStacks,
|
pub focus_stack: FocusStacks,
|
||||||
pub screencopy: ScreencopySessions,
|
pub image_copy: ImageCopySessions,
|
||||||
output_stack: VecDeque<OutputMatch>,
|
output_stack: VecDeque<OutputMatch>,
|
||||||
pub(super) backdrop_id: Id,
|
pub(super) backdrop_id: Id,
|
||||||
pub dirty: AtomicBool,
|
pub dirty: AtomicBool,
|
||||||
|
|
@ -377,7 +377,7 @@ impl Workspace {
|
||||||
id: None,
|
id: None,
|
||||||
handle,
|
handle,
|
||||||
focus_stack: FocusStacks::default(),
|
focus_stack: FocusStacks::default(),
|
||||||
screencopy: ScreencopySessions::default(),
|
image_copy: ImageCopySessions::default(),
|
||||||
output_stack: {
|
output_stack: {
|
||||||
let mut queue = VecDeque::new();
|
let mut queue = VecDeque::new();
|
||||||
queue.push_back(output_match);
|
queue.push_back(output_match);
|
||||||
|
|
@ -410,7 +410,7 @@ impl Workspace {
|
||||||
id: pinned.id.clone(),
|
id: pinned.id.clone(),
|
||||||
handle,
|
handle,
|
||||||
focus_stack: FocusStacks::default(),
|
focus_stack: FocusStacks::default(),
|
||||||
screencopy: ScreencopySessions::default(),
|
image_copy: ImageCopySessions::default(),
|
||||||
output_stack: {
|
output_stack: {
|
||||||
let mut queue = VecDeque::new();
|
let mut queue = VecDeque::new();
|
||||||
queue.push_back(pinned.output.clone());
|
queue.push_back(pinned.output.clone());
|
||||||
|
|
|
||||||
32
src/state.rs
32
src/state.rs
|
|
@ -13,16 +13,15 @@ use crate::{
|
||||||
shell::{CosmicSurface, SeatExt, Shell, grabs::SeatMoveGrabState},
|
shell::{CosmicSurface, SeatExt, Shell, grabs::SeatMoveGrabState},
|
||||||
utils::prelude::OutputExt,
|
utils::prelude::OutputExt,
|
||||||
wayland::{
|
wayland::{
|
||||||
handlers::{data_device::get_dnd_icon, screencopy::SessionHolder},
|
handlers::{data_device::get_dnd_icon, image_copy_capture::SessionHolder},
|
||||||
protocols::{
|
protocols::{
|
||||||
a11y::A11yState,
|
a11y::A11yState,
|
||||||
corner_radius::CornerRadiusState,
|
corner_radius::CornerRadiusState,
|
||||||
drm::WlDrmState,
|
drm::WlDrmState,
|
||||||
image_capture_source::ImageCaptureSourceState,
|
image_capture_source::CosmicImageCaptureSourceState,
|
||||||
output_configuration::OutputConfigurationState,
|
output_configuration::OutputConfigurationState,
|
||||||
output_power::OutputPowerState,
|
output_power::OutputPowerState,
|
||||||
overlap_notify::OverlapNotifyState,
|
overlap_notify::OverlapNotifyState,
|
||||||
screencopy::ScreencopyState,
|
|
||||||
toplevel_info::ToplevelInfoState,
|
toplevel_info::ToplevelInfoState,
|
||||||
toplevel_management::{ManagementCapabilities, ToplevelManagementState},
|
toplevel_management::{ManagementCapabilities, ToplevelManagementState},
|
||||||
workspace::{WorkspaceState, WorkspaceUpdateGuard},
|
workspace::{WorkspaceState, WorkspaceUpdateGuard},
|
||||||
|
|
@ -77,9 +76,12 @@ use smithay::{
|
||||||
compositor::{CompositorClientState, CompositorState, SurfaceData},
|
compositor::{CompositorClientState, CompositorState, SurfaceData},
|
||||||
cursor_shape::CursorShapeManagerState,
|
cursor_shape::CursorShapeManagerState,
|
||||||
dmabuf::{DmabufFeedback, DmabufGlobal, DmabufState},
|
dmabuf::{DmabufFeedback, DmabufGlobal, DmabufState},
|
||||||
|
fixes::FixesState,
|
||||||
fractional_scale::{FractionalScaleManagerState, with_fractional_scale},
|
fractional_scale::{FractionalScaleManagerState, with_fractional_scale},
|
||||||
idle_inhibit::IdleInhibitManagerState,
|
idle_inhibit::IdleInhibitManagerState,
|
||||||
idle_notify::IdleNotifierState,
|
idle_notify::IdleNotifierState,
|
||||||
|
image_capture_source::{OutputCaptureSourceState, ToplevelCaptureSourceState},
|
||||||
|
image_copy_capture::ImageCopyCaptureState,
|
||||||
input_method::InputMethodManagerState,
|
input_method::InputMethodManagerState,
|
||||||
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitState,
|
keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitState,
|
||||||
output::OutputManagerState,
|
output::OutputManagerState,
|
||||||
|
|
@ -260,8 +262,10 @@ pub struct Common {
|
||||||
pub primary_selection_state: PrimarySelectionState,
|
pub primary_selection_state: PrimarySelectionState,
|
||||||
pub ext_data_control_state: ExtDataControlState,
|
pub ext_data_control_state: ExtDataControlState,
|
||||||
pub wlr_data_control_state: WlrDataControlState,
|
pub wlr_data_control_state: WlrDataControlState,
|
||||||
pub image_capture_source_state: ImageCaptureSourceState,
|
pub cosmic_image_capture_source_state: CosmicImageCaptureSourceState,
|
||||||
pub screencopy_state: ScreencopyState,
|
pub output_capture_source_state: OutputCaptureSourceState,
|
||||||
|
pub toplevel_capture_source_state: ToplevelCaptureSourceState,
|
||||||
|
pub image_copy_capture_state: ImageCopyCaptureState,
|
||||||
pub seat_state: SeatState<State>,
|
pub seat_state: SeatState<State>,
|
||||||
pub session_lock_manager_state: SessionLockManagerState,
|
pub session_lock_manager_state: SessionLockManagerState,
|
||||||
pub idle_notifier_state: IdleNotifierState<State>,
|
pub idle_notifier_state: IdleNotifierState<State>,
|
||||||
|
|
@ -645,9 +649,14 @@ impl State {
|
||||||
OverlapNotifyState::new::<Self, _>(dh, client_has_no_security_context);
|
OverlapNotifyState::new::<Self, _>(dh, client_has_no_security_context);
|
||||||
let presentation_state = PresentationState::new::<Self>(dh, clock.id() as u32);
|
let presentation_state = PresentationState::new::<Self>(dh, clock.id() as u32);
|
||||||
let primary_selection_state = PrimarySelectionState::new::<Self>(dh);
|
let primary_selection_state = PrimarySelectionState::new::<Self>(dh);
|
||||||
let image_capture_source_state =
|
let cosmic_image_capture_source_state =
|
||||||
ImageCaptureSourceState::new::<Self, _>(dh, client_not_sandboxed);
|
CosmicImageCaptureSourceState::new::<Self, _>(dh, client_not_sandboxed);
|
||||||
let screencopy_state = ScreencopyState::new::<Self, _>(dh, client_not_sandboxed);
|
let output_capture_source_state =
|
||||||
|
OutputCaptureSourceState::new_with_filter::<State, _>(&dh, client_not_sandboxed);
|
||||||
|
let toplevel_capture_source_state =
|
||||||
|
ToplevelCaptureSourceState::new_with_filter::<State, _>(&dh, client_not_sandboxed);
|
||||||
|
let image_copy_capture_state =
|
||||||
|
ImageCopyCaptureState::new_with_filter::<Self, _>(dh, client_not_sandboxed);
|
||||||
let shm_state =
|
let shm_state =
|
||||||
ShmState::new::<Self>(dh, vec![wl_shm::Format::Xbgr8888, wl_shm::Format::Abgr8888]);
|
ShmState::new::<Self>(dh, vec![wl_shm::Format::Xbgr8888, wl_shm::Format::Abgr8888]);
|
||||||
let cursor_shape_manager_state = CursorShapeManagerState::new::<State>(dh);
|
let cursor_shape_manager_state = CursorShapeManagerState::new::<State>(dh);
|
||||||
|
|
@ -669,6 +678,7 @@ impl State {
|
||||||
VirtualKeyboardManagerState::new::<State, _>(dh, client_not_sandboxed);
|
VirtualKeyboardManagerState::new::<State, _>(dh, client_not_sandboxed);
|
||||||
AlphaModifierState::new::<Self>(dh);
|
AlphaModifierState::new::<Self>(dh);
|
||||||
SinglePixelBufferState::new::<Self>(dh);
|
SinglePixelBufferState::new::<Self>(dh);
|
||||||
|
FixesState::new::<Self>(&dh);
|
||||||
|
|
||||||
let idle_notifier_state = IdleNotifierState::<Self>::new(dh, handle.clone());
|
let idle_notifier_state = IdleNotifierState::<Self>::new(dh, handle.clone());
|
||||||
let idle_inhibit_manager_state = IdleInhibitManagerState::new::<State>(dh);
|
let idle_inhibit_manager_state = IdleInhibitManagerState::new::<State>(dh);
|
||||||
|
|
@ -754,8 +764,10 @@ impl State {
|
||||||
idle_notifier_state,
|
idle_notifier_state,
|
||||||
idle_inhibit_manager_state,
|
idle_inhibit_manager_state,
|
||||||
idle_inhibiting_surfaces,
|
idle_inhibiting_surfaces,
|
||||||
image_capture_source_state,
|
cosmic_image_capture_source_state,
|
||||||
screencopy_state,
|
output_capture_source_state,
|
||||||
|
toplevel_capture_source_state,
|
||||||
|
image_copy_capture_state,
|
||||||
shm_state,
|
shm_state,
|
||||||
cursor_shape_manager_state,
|
cursor_shape_manager_state,
|
||||||
seat_state,
|
seat_state,
|
||||||
|
|
|
||||||
6
src/wayland/handlers/fixes.rs
Normal file
6
src/wayland/handlers/fixes.rs
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
use crate::state::State;
|
||||||
|
use smithay::delegate_fixes;
|
||||||
|
|
||||||
|
delegate_fixes!(State);
|
||||||
|
|
@ -1,4 +1,59 @@
|
||||||
use crate::state::State;
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
use crate::wayland::protocols::image_capture_source::delegate_image_capture_source;
|
|
||||||
|
|
||||||
delegate_image_capture_source!(State);
|
use crate::{
|
||||||
|
state::State,
|
||||||
|
wayland::protocols::{
|
||||||
|
image_capture_source::{ImageCaptureSourceKind, delegate_cosmic_image_capture_source},
|
||||||
|
toplevel_info::window_from_ext,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use smithay::{
|
||||||
|
output::Output,
|
||||||
|
wayland::{
|
||||||
|
foreign_toplevel_list::ForeignToplevelHandle,
|
||||||
|
image_capture_source::{
|
||||||
|
ImageCaptureSource, ImageCaptureSourceHandler, OutputCaptureSourceHandler,
|
||||||
|
OutputCaptureSourceState, ToplevelCaptureSourceHandler, ToplevelCaptureSourceState,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
impl ImageCaptureSourceHandler for State {
|
||||||
|
fn source_destroyed(&mut self, _source: ImageCaptureSource) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutputCaptureSourceHandler for State {
|
||||||
|
fn output_capture_source_state(&mut self) -> &mut OutputCaptureSourceState {
|
||||||
|
&mut self.common.output_capture_source_state
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output_source_created(&mut self, source: ImageCaptureSource, output: &Output) {
|
||||||
|
source
|
||||||
|
.user_data()
|
||||||
|
.insert_if_missing(|| ImageCaptureSourceKind::Output(output.downgrade()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToplevelCaptureSourceHandler for State {
|
||||||
|
fn toplevel_capture_source_state(&mut self) -> &mut ToplevelCaptureSourceState {
|
||||||
|
&mut self.common.toplevel_capture_source_state
|
||||||
|
}
|
||||||
|
|
||||||
|
fn toplevel_source_created(
|
||||||
|
&mut self,
|
||||||
|
source: ImageCaptureSource,
|
||||||
|
toplevel: &ForeignToplevelHandle,
|
||||||
|
) {
|
||||||
|
let data = match window_from_ext(self, toplevel) {
|
||||||
|
Some(toplevel) => ImageCaptureSourceKind::Toplevel(toplevel.clone()),
|
||||||
|
None => ImageCaptureSourceKind::Destroyed,
|
||||||
|
};
|
||||||
|
source.user_data().insert_if_missing(|| data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
smithay::delegate_image_capture_source!(State);
|
||||||
|
smithay::delegate_output_capture_source!(State);
|
||||||
|
smithay::delegate_toplevel_capture_source!(State);
|
||||||
|
|
||||||
|
delegate_cosmic_image_capture_source!(State);
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use std::{borrow::Borrow, collections::HashMap, sync::Mutex};
|
use std::{borrow::Borrow, collections::HashMap, sync::Mutex};
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
|
|
@ -15,7 +17,15 @@ use smithay::{
|
||||||
output::Output,
|
output::Output,
|
||||||
reexports::wayland_server::protocol::wl_shm::Format as ShmFormat,
|
reexports::wayland_server::protocol::wl_shm::Format as ShmFormat,
|
||||||
utils::{Buffer as BufferCoords, Point, Size, Transform},
|
utils::{Buffer as BufferCoords, Point, Size, Transform},
|
||||||
wayland::{dmabuf::get_dmabuf, seat::WaylandFocus},
|
wayland::{
|
||||||
|
dmabuf::get_dmabuf,
|
||||||
|
image_capture_source::ImageCaptureSource,
|
||||||
|
image_copy_capture::{
|
||||||
|
BufferConstraints, CursorSession, CursorSessionRef, DmabufConstraints, Frame, FrameRef,
|
||||||
|
ImageCopyCaptureHandler, ImageCopyCaptureState, Session, SessionRef,
|
||||||
|
},
|
||||||
|
seat::WaylandFocus,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -24,45 +34,41 @@ use crate::{
|
||||||
utils::prelude::{
|
utils::prelude::{
|
||||||
OutputExt, PointExt, PointGlobalExt, PointLocalExt, RectExt, RectLocalExt, SeatExt,
|
OutputExt, PointExt, PointGlobalExt, PointLocalExt, RectExt, RectLocalExt, SeatExt,
|
||||||
},
|
},
|
||||||
wayland::protocols::{
|
wayland::protocols::image_capture_source::ImageCaptureSourceKind,
|
||||||
image_capture_source::ImageCaptureSourceData,
|
|
||||||
screencopy::{
|
|
||||||
BufferConstraints, CursorSession, CursorSessionRef, DmabufConstraints, Frame, FrameRef,
|
|
||||||
ScreencopyHandler, ScreencopyState, Session, SessionRef, delegate_screencopy,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mod render;
|
mod render;
|
||||||
mod user_data;
|
mod user_data;
|
||||||
pub use self::render::*;
|
pub use self::render::*;
|
||||||
use self::user_data::*;
|
use self::user_data::*;
|
||||||
pub use self::user_data::{FrameHolder, ScreencopySessions, SessionData, SessionHolder};
|
pub use self::user_data::{FrameHolder, ImageCopySessions, SessionData, SessionHolder};
|
||||||
|
|
||||||
impl ScreencopyHandler for State {
|
impl ImageCopyCaptureHandler for State {
|
||||||
fn screencopy_state(&mut self) -> &mut ScreencopyState {
|
fn image_copy_capture_state(&mut self) -> &mut ImageCopyCaptureState {
|
||||||
&mut self.common.screencopy_state
|
&mut self.common.image_copy_capture_state
|
||||||
}
|
}
|
||||||
|
|
||||||
fn capture_source(&mut self, source: &ImageCaptureSourceData) -> Option<BufferConstraints> {
|
fn capture_constraints(&mut self, source: &ImageCaptureSource) -> Option<BufferConstraints> {
|
||||||
match source {
|
let kind = source.user_data().get::<ImageCaptureSourceKind>().unwrap();
|
||||||
ImageCaptureSourceData::Output(weak) => weak
|
match kind {
|
||||||
|
ImageCaptureSourceKind::Output(weak) => weak
|
||||||
.upgrade()
|
.upgrade()
|
||||||
.and_then(|output| constraints_for_output(&output, &mut self.backend)),
|
.and_then(|output| constraints_for_output(&output, &mut self.backend)),
|
||||||
ImageCaptureSourceData::Workspace(handle) => {
|
ImageCaptureSourceKind::Workspace(handle) => {
|
||||||
let shell = self.common.shell.read();
|
let shell = self.common.shell.read();
|
||||||
let output = shell.workspaces.space_for_handle(handle)?.output();
|
let output = shell.workspaces.space_for_handle(handle)?.output();
|
||||||
constraints_for_output(output, &mut self.backend)
|
constraints_for_output(output, &mut self.backend)
|
||||||
}
|
}
|
||||||
ImageCaptureSourceData::Toplevel(window) => {
|
ImageCaptureSourceKind::Toplevel(window) => {
|
||||||
constraints_for_toplevel(window, &mut self.backend)
|
constraints_for_toplevel(window, &mut self.backend)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn capture_cursor_source(
|
|
||||||
|
fn cursor_capture_constraints(
|
||||||
&mut self,
|
&mut self,
|
||||||
_source: &ImageCaptureSourceData,
|
_source: &ImageCaptureSource,
|
||||||
) -> Option<BufferConstraints> {
|
) -> Option<BufferConstraints> {
|
||||||
let size = if let Some((geometry, _)) = self
|
let size = if let Some((geometry, _)) = self
|
||||||
.common
|
.common
|
||||||
|
|
@ -85,8 +91,14 @@ impl ScreencopyHandler for State {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_session(&mut self, session: Session) {
|
fn new_session(&mut self, session: Session) {
|
||||||
match session.source() {
|
let kind = session
|
||||||
ImageCaptureSourceData::Output(weak) => {
|
.source()
|
||||||
|
.user_data()
|
||||||
|
.get::<ImageCaptureSourceKind>()
|
||||||
|
.unwrap()
|
||||||
|
.clone();
|
||||||
|
match kind {
|
||||||
|
ImageCaptureSourceKind::Output(weak) => {
|
||||||
let Some(mut output) = weak.upgrade() else {
|
let Some(mut output) = weak.upgrade() else {
|
||||||
session.stop();
|
session.stop();
|
||||||
return;
|
return;
|
||||||
|
|
@ -100,7 +112,7 @@ impl ScreencopyHandler for State {
|
||||||
|
|
||||||
output.add_session(session);
|
output.add_session(session);
|
||||||
}
|
}
|
||||||
ImageCaptureSourceData::Workspace(handle) => {
|
ImageCaptureSourceKind::Workspace(handle) => {
|
||||||
let mut shell = self.common.shell.write();
|
let mut shell = self.common.shell.write();
|
||||||
let Some(workspace) = shell.workspaces.space_for_handle_mut(&handle) else {
|
let Some(workspace) = shell.workspaces.space_for_handle_mut(&handle) else {
|
||||||
session.stop();
|
session.stop();
|
||||||
|
|
@ -114,7 +126,7 @@ impl ScreencopyHandler for State {
|
||||||
});
|
});
|
||||||
workspace.add_session(session);
|
workspace.add_session(session);
|
||||||
}
|
}
|
||||||
ImageCaptureSourceData::Toplevel(mut toplevel) => {
|
ImageCaptureSourceKind::Toplevel(mut toplevel) => {
|
||||||
let size = toplevel.geometry().size.to_physical(1);
|
let size = toplevel.geometry().size.to_physical(1);
|
||||||
session.user_data().insert_if_missing_threadsafe(|| {
|
session.user_data().insert_if_missing_threadsafe(|| {
|
||||||
Mutex::new(SessionUserData::new(OutputDamageTracker::new(
|
Mutex::new(SessionUserData::new(OutputDamageTracker::new(
|
||||||
|
|
@ -125,9 +137,10 @@ impl ScreencopyHandler for State {
|
||||||
});
|
});
|
||||||
toplevel.add_session(session);
|
toplevel.add_session(session);
|
||||||
}
|
}
|
||||||
ImageCaptureSourceData::Destroyed => unreachable!(),
|
ImageCaptureSourceKind::Destroyed => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_cursor_session(&mut self, session: CursorSession) {
|
fn new_cursor_session(&mut self, session: CursorSession) {
|
||||||
let (pointer_loc, pointer_size, hotspot) = {
|
let (pointer_loc, pointer_size, hotspot) = {
|
||||||
let seat = self.common.shell.read().seats.last_active().clone();
|
let seat = self.common.shell.read().seats.last_active().clone();
|
||||||
|
|
@ -154,8 +167,14 @@ impl ScreencopyHandler for State {
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
|
|
||||||
match session.source() {
|
let kind = session
|
||||||
ImageCaptureSourceData::Output(weak) => {
|
.source()
|
||||||
|
.user_data()
|
||||||
|
.get::<ImageCaptureSourceKind>()
|
||||||
|
.unwrap()
|
||||||
|
.clone();
|
||||||
|
match kind {
|
||||||
|
ImageCaptureSourceKind::Output(weak) => {
|
||||||
let Some(mut output) = weak.upgrade() else {
|
let Some(mut output) = weak.upgrade() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
@ -184,7 +203,7 @@ impl ScreencopyHandler for State {
|
||||||
|
|
||||||
output.add_cursor_session(session);
|
output.add_cursor_session(session);
|
||||||
}
|
}
|
||||||
ImageCaptureSourceData::Workspace(handle) => {
|
ImageCaptureSourceKind::Workspace(handle) => {
|
||||||
let mut shell = self.common.shell.write();
|
let mut shell = self.common.shell.write();
|
||||||
let Some(workspace) = shell.workspaces.space_for_handle_mut(&handle) else {
|
let Some(workspace) = shell.workspaces.space_for_handle_mut(&handle) else {
|
||||||
return;
|
return;
|
||||||
|
|
@ -215,7 +234,7 @@ impl ScreencopyHandler for State {
|
||||||
|
|
||||||
workspace.add_cursor_session(session);
|
workspace.add_cursor_session(session);
|
||||||
}
|
}
|
||||||
ImageCaptureSourceData::Toplevel(mut toplevel) => {
|
ImageCaptureSourceKind::Toplevel(mut toplevel) => {
|
||||||
let shell = self.common.shell.read();
|
let shell = self.common.shell.read();
|
||||||
if let Some(element) = shell.element_for_surface(&toplevel) {
|
if let Some(element) = shell.element_for_surface(&toplevel) {
|
||||||
if element.has_active_window(&toplevel) {
|
if element.has_active_window(&toplevel) {
|
||||||
|
|
@ -238,38 +257,44 @@ impl ScreencopyHandler for State {
|
||||||
|
|
||||||
toplevel.add_cursor_session(session);
|
toplevel.add_cursor_session(session);
|
||||||
}
|
}
|
||||||
ImageCaptureSourceData::Destroyed => unreachable!(),
|
ImageCaptureSourceKind::Destroyed => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frame(&mut self, session: SessionRef, frame: Frame) {
|
fn frame(&mut self, session: &SessionRef, frame: Frame) {
|
||||||
match session.source() {
|
let kind = session
|
||||||
ImageCaptureSourceData::Output(weak) => {
|
.source()
|
||||||
|
.user_data()
|
||||||
|
.get::<ImageCaptureSourceKind>()
|
||||||
|
.unwrap()
|
||||||
|
.clone();
|
||||||
|
match kind {
|
||||||
|
ImageCaptureSourceKind::Output(weak) => {
|
||||||
let Some(mut output) = weak.upgrade() else {
|
let Some(mut output) = weak.upgrade() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
output.add_frame(session, frame);
|
output.add_frame(session.clone(), frame);
|
||||||
self.backend.schedule_render(&output);
|
self.backend.schedule_render(&output);
|
||||||
}
|
}
|
||||||
ImageCaptureSourceData::Workspace(handle) => {
|
ImageCaptureSourceKind::Workspace(handle) => {
|
||||||
render_workspace_to_buffer(self, session, frame, handle)
|
render_workspace_to_buffer(self, session, frame, handle)
|
||||||
}
|
}
|
||||||
ImageCaptureSourceData::Toplevel(toplevel) => {
|
ImageCaptureSourceKind::Toplevel(toplevel) => {
|
||||||
render_window_to_buffer(self, session, frame, &toplevel)
|
render_window_to_buffer(self, session, frame, &toplevel)
|
||||||
}
|
}
|
||||||
ImageCaptureSourceData::Destroyed => unreachable!(),
|
ImageCaptureSourceKind::Destroyed => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cursor_frame(&mut self, session: CursorSessionRef, frame: Frame) {
|
fn cursor_frame(&mut self, session: &CursorSessionRef, frame: Frame) {
|
||||||
if !session.has_cursor() {
|
if !session.has_cursor() {
|
||||||
frame.success(Transform::Normal, Vec::new(), self.common.clock.now());
|
frame.success(Transform::Normal, Vec::new(), self.common.clock.now());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let seat = self.common.shell.read().seats.last_active().clone();
|
let seat = self.common.shell.read().seats.last_active().clone();
|
||||||
render_cursor_to_buffer(self, &session, frame, &seat);
|
render_cursor_to_buffer(self, session, frame, &seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frame_aborted(&mut self, frame: FrameRef) {
|
fn frame_aborted(&mut self, frame: FrameRef) {
|
||||||
|
|
@ -280,13 +305,19 @@ impl ScreencopyHandler for State {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn session_destroyed(&mut self, session: SessionRef) {
|
fn session_destroyed(&mut self, session: SessionRef) {
|
||||||
match session.source() {
|
let kind = session
|
||||||
ImageCaptureSourceData::Output(weak) => {
|
.source()
|
||||||
|
.user_data()
|
||||||
|
.get::<ImageCaptureSourceKind>()
|
||||||
|
.unwrap()
|
||||||
|
.clone();
|
||||||
|
match kind {
|
||||||
|
ImageCaptureSourceKind::Output(weak) => {
|
||||||
if let Some(mut output) = weak.upgrade() {
|
if let Some(mut output) = weak.upgrade() {
|
||||||
output.remove_session(&session);
|
output.remove_session(&session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImageCaptureSourceData::Workspace(handle) => {
|
ImageCaptureSourceKind::Workspace(handle) => {
|
||||||
if let Some(workspace) = self
|
if let Some(workspace) = self
|
||||||
.common
|
.common
|
||||||
.shell
|
.shell
|
||||||
|
|
@ -297,19 +328,25 @@ impl ScreencopyHandler for State {
|
||||||
workspace.remove_session(&session)
|
workspace.remove_session(&session)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImageCaptureSourceData::Toplevel(mut toplevel) => toplevel.remove_session(&session),
|
ImageCaptureSourceKind::Toplevel(mut toplevel) => toplevel.remove_session(&session),
|
||||||
ImageCaptureSourceData::Destroyed => unreachable!(),
|
ImageCaptureSourceKind::Destroyed => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cursor_session_destroyed(&mut self, session: CursorSessionRef) {
|
fn cursor_session_destroyed(&mut self, session: CursorSessionRef) {
|
||||||
match session.source() {
|
let kind = session
|
||||||
ImageCaptureSourceData::Output(weak) => {
|
.source()
|
||||||
|
.user_data()
|
||||||
|
.get::<ImageCaptureSourceKind>()
|
||||||
|
.unwrap()
|
||||||
|
.clone();
|
||||||
|
match kind {
|
||||||
|
ImageCaptureSourceKind::Output(weak) => {
|
||||||
if let Some(mut output) = weak.upgrade() {
|
if let Some(mut output) = weak.upgrade() {
|
||||||
output.remove_cursor_session(&session);
|
output.remove_cursor_session(&session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImageCaptureSourceData::Workspace(handle) => {
|
ImageCaptureSourceKind::Workspace(handle) => {
|
||||||
if let Some(workspace) = self
|
if let Some(workspace) = self
|
||||||
.common
|
.common
|
||||||
.shell
|
.shell
|
||||||
|
|
@ -320,10 +357,10 @@ impl ScreencopyHandler for State {
|
||||||
workspace.remove_cursor_session(&session)
|
workspace.remove_cursor_session(&session)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImageCaptureSourceData::Toplevel(mut toplevel) => {
|
ImageCaptureSourceKind::Toplevel(mut toplevel) => {
|
||||||
toplevel.remove_cursor_session(&session)
|
toplevel.remove_cursor_session(&session)
|
||||||
}
|
}
|
||||||
ImageCaptureSourceData::Destroyed => unreachable!(),
|
ImageCaptureSourceKind::Destroyed => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -413,4 +450,4 @@ fn constraints_for_renderer(
|
||||||
constraints
|
constraints
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate_screencopy!(State);
|
smithay::delegate_image_copy_capture!(State);
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use calloop::LoopHandle;
|
use calloop::LoopHandle;
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::{
|
backend::{
|
||||||
|
|
@ -26,6 +28,9 @@ use smithay::{
|
||||||
},
|
},
|
||||||
wayland::{
|
wayland::{
|
||||||
dmabuf::get_dmabuf,
|
dmabuf::get_dmabuf,
|
||||||
|
image_copy_capture::{
|
||||||
|
BufferConstraints, CaptureFailureReason, CursorSessionRef, Frame, SessionRef,
|
||||||
|
},
|
||||||
seat::WaylandFocus,
|
seat::WaylandFocus,
|
||||||
shm::{shm_format_to_fourcc, with_buffer_contents, with_buffer_contents_mut},
|
shm::{shm_format_to_fourcc, with_buffer_contents, with_buffer_contents_mut},
|
||||||
},
|
},
|
||||||
|
|
@ -43,13 +48,10 @@ use crate::{
|
||||||
state::{Common, KmsNodes, State},
|
state::{Common, KmsNodes, State},
|
||||||
utils::prelude::{PointExt, PointGlobalExt, RectExt, RectLocalExt, SeatExt},
|
utils::prelude::{PointExt, PointGlobalExt, RectExt, RectLocalExt, SeatExt},
|
||||||
wayland::{
|
wayland::{
|
||||||
handlers::screencopy::{
|
handlers::image_copy_capture::{
|
||||||
SessionData, SessionUserData, constraints_for_output, constraints_for_toplevel,
|
SessionData, SessionUserData, constraints_for_output, constraints_for_toplevel,
|
||||||
},
|
},
|
||||||
protocols::{
|
protocols::workspace::WorkspaceHandle,
|
||||||
screencopy::{BufferConstraints, CursorSessionRef, FailureReason, Frame, SessionRef},
|
|
||||||
workspace::WorkspaceHandle,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -165,7 +167,7 @@ where
|
||||||
.map_err(|err| R::Error::from_gles_error(GlesError::BufferAccessError(err)))
|
.map_err(|err| R::Error::from_gles_error(GlesError::BufferAccessError(err)))
|
||||||
.and_then(|x| x)
|
.and_then(|x| x)
|
||||||
{
|
{
|
||||||
frame.fail(FailureReason::Unknown);
|
frame.fail(CaptureFailureReason::Unknown);
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -223,7 +225,7 @@ where
|
||||||
// TODO re-use offscreen buffer to damage track screencopy to shm
|
// TODO re-use offscreen buffer to damage track screencopy to shm
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
session_damage_tracking.age_for_buffer(&buffer)
|
1
|
||||||
};
|
};
|
||||||
let mut fb = offscreen
|
let mut fb = offscreen
|
||||||
.as_mut()
|
.as_mut()
|
||||||
|
|
@ -249,7 +251,7 @@ where
|
||||||
)
|
)
|
||||||
.map_err(DTError::Rendering),
|
.map_err(DTError::Rendering),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
frame.fail(FailureReason::Unknown);
|
frame.fail(CaptureFailureReason::Unknown);
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -257,7 +259,7 @@ where
|
||||||
|
|
||||||
pub fn render_workspace_to_buffer(
|
pub fn render_workspace_to_buffer(
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
session: SessionRef,
|
session: &SessionRef,
|
||||||
frame: Frame,
|
frame: Frame,
|
||||||
handle: WorkspaceHandle,
|
handle: WorkspaceHandle,
|
||||||
) {
|
) {
|
||||||
|
|
@ -278,14 +280,14 @@ pub fn render_workspace_to_buffer(
|
||||||
let buffer_size = buffer_dimensions(&buffer).unwrap();
|
let buffer_size = buffer_dimensions(&buffer).unwrap();
|
||||||
if mode != Some(buffer_size) {
|
if mode != Some(buffer_size) {
|
||||||
let Some(constraints) = constraints_for_output(&output, &mut state.backend) else {
|
let Some(constraints) = constraints_for_output(&output, &mut state.backend) else {
|
||||||
output.remove_session(&session);
|
output.remove_session(session);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
session.update_constraints(constraints);
|
session.update_constraints(constraints);
|
||||||
if let Some(data) = session.user_data().get::<SessionData>() {
|
if let Some(data) = session.user_data().get::<SessionData>() {
|
||||||
*data.lock().unwrap() = SessionUserData::new(OutputDamageTracker::from_output(&output));
|
*data.lock().unwrap() = SessionUserData::new(OutputDamageTracker::from_output(&output));
|
||||||
}
|
}
|
||||||
frame.fail(FailureReason::BufferConstraints);
|
frame.fail(CaptureFailureReason::BufferConstraints);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -414,7 +416,7 @@ pub fn render_workspace_to_buffer(
|
||||||
Ok(renderer) => renderer,
|
Ok(renderer) => renderer,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(?err, "Couldn't use node for screencopy");
|
warn!(?err, "Couldn't use node for screencopy");
|
||||||
frame.fail(FailureReason::Unknown);
|
frame.fail(CaptureFailureReason::Unknown);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -490,17 +492,16 @@ smithay::render_elements! {
|
||||||
pub WindowCaptureElement<R> where R: ImportAll + ImportMem;
|
pub WindowCaptureElement<R> where R: ImportAll + ImportMem;
|
||||||
WaylandElement=WaylandSurfaceRenderElement<R>,
|
WaylandElement=WaylandSurfaceRenderElement<R>,
|
||||||
CursorElement=RelocateRenderElement<cursor::CursorRenderElement<R>>,
|
CursorElement=RelocateRenderElement<cursor::CursorRenderElement<R>>,
|
||||||
AdditionalDamage=DamageElement,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_window_to_buffer(
|
pub fn render_window_to_buffer(
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
session: SessionRef,
|
session: &SessionRef,
|
||||||
frame: Frame,
|
frame: Frame,
|
||||||
toplevel: &CosmicSurface,
|
toplevel: &CosmicSurface,
|
||||||
) {
|
) {
|
||||||
if !toplevel.alive() {
|
if !toplevel.alive() {
|
||||||
toplevel.clone().remove_session(&session);
|
toplevel.clone().remove_session(session);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -509,7 +510,7 @@ pub fn render_window_to_buffer(
|
||||||
let buffer_size = buffer_dimensions(&buffer).unwrap();
|
let buffer_size = buffer_dimensions(&buffer).unwrap();
|
||||||
if buffer_size != geometry.size.to_buffer(1, Transform::Normal) {
|
if buffer_size != geometry.size.to_buffer(1, Transform::Normal) {
|
||||||
let Some(constraints) = constraints_for_toplevel(toplevel, &mut state.backend) else {
|
let Some(constraints) = constraints_for_toplevel(toplevel, &mut state.backend) else {
|
||||||
toplevel.clone().remove_session(&session);
|
toplevel.clone().remove_session(session);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
session.update_constraints(constraints);
|
session.update_constraints(constraints);
|
||||||
|
|
@ -518,7 +519,7 @@ pub fn render_window_to_buffer(
|
||||||
*data.lock().unwrap() =
|
*data.lock().unwrap() =
|
||||||
SessionUserData::new(OutputDamageTracker::new(size, 1.0, Transform::Normal));
|
SessionUserData::new(OutputDamageTracker::new(size, 1.0, Transform::Normal));
|
||||||
}
|
}
|
||||||
frame.fail(FailureReason::BufferConstraints);
|
frame.fail(CaptureFailureReason::BufferConstraints);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -541,22 +542,19 @@ pub fn render_window_to_buffer(
|
||||||
CosmicElement<R>: RenderElement<R>,
|
CosmicElement<R>: RenderElement<R>,
|
||||||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
CosmicMappedRenderElement<R>: RenderElement<R>,
|
||||||
{
|
{
|
||||||
let mut elements = Vec::new();
|
let additional_damage_elements: Vec<_> = additional_damage
|
||||||
|
.into_iter()
|
||||||
elements.extend(
|
.filter_map(|rect| {
|
||||||
additional_damage
|
let logical_rect = rect.to_logical(
|
||||||
.into_iter()
|
1,
|
||||||
.filter_map(|rect| {
|
Transform::Normal,
|
||||||
let logical_rect = rect.to_logical(
|
&geometry.size.to_buffer(1, Transform::Normal),
|
||||||
1,
|
);
|
||||||
Transform::Normal,
|
logical_rect.intersection(Rectangle::from_size(geometry.size))
|
||||||
&geometry.size.to_buffer(1, Transform::Normal),
|
})
|
||||||
);
|
.map(DamageElement::new)
|
||||||
logical_rect.intersection(Rectangle::from_size(geometry.size))
|
.collect();
|
||||||
})
|
dt.damage_output(age, &additional_damage_elements)?;
|
||||||
.map(DamageElement::new)
|
|
||||||
.map(Into::<WindowCaptureElement<R>>::into),
|
|
||||||
);
|
|
||||||
|
|
||||||
let shell = common.shell.read();
|
let shell = common.shell.read();
|
||||||
let seat = shell.seats.last_active().clone();
|
let seat = shell.seats.last_active().clone();
|
||||||
|
|
@ -579,6 +577,8 @@ pub fn render_window_to_buffer(
|
||||||
};
|
};
|
||||||
std::mem::drop(shell);
|
std::mem::drop(shell);
|
||||||
|
|
||||||
|
let mut elements = Vec::new();
|
||||||
|
|
||||||
if let Some(location) = location {
|
if let Some(location) = location {
|
||||||
if draw_cursor {
|
if draw_cursor {
|
||||||
elements.extend(
|
elements.extend(
|
||||||
|
|
@ -666,7 +666,7 @@ pub fn render_window_to_buffer(
|
||||||
Ok(renderer) => renderer,
|
Ok(renderer) => renderer,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(?err, "Couldn't use node for screencopy");
|
warn!(?err, "Couldn't use node for screencopy");
|
||||||
frame.fail(FailureReason::Unknown);
|
frame.fail(CaptureFailureReason::Unknown);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -760,7 +760,7 @@ pub fn render_cursor_to_buffer(
|
||||||
Transform::Normal,
|
Transform::Normal,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
frame.fail(FailureReason::BufferConstraints);
|
frame.fail(CaptureFailureReason::BufferConstraints);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -781,7 +781,17 @@ pub fn render_cursor_to_buffer(
|
||||||
CosmicElement<R>: RenderElement<R>,
|
CosmicElement<R>: RenderElement<R>,
|
||||||
CosmicMappedRenderElement<R>: RenderElement<R>,
|
CosmicMappedRenderElement<R>: RenderElement<R>,
|
||||||
{
|
{
|
||||||
let mut elements = cursor::draw_cursor(
|
let additional_damage_elements: Vec<_> = additional_damage
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|rect| {
|
||||||
|
let logical_rect = rect.to_logical(1, Transform::Normal, &Size::from((64, 64)));
|
||||||
|
logical_rect.intersection(Rectangle::from_size((64, 64).into()))
|
||||||
|
})
|
||||||
|
.map(DamageElement::new)
|
||||||
|
.collect();
|
||||||
|
dt.damage_output(age, &additional_damage_elements)?;
|
||||||
|
|
||||||
|
let elements = cursor::draw_cursor(
|
||||||
renderer,
|
renderer,
|
||||||
seat,
|
seat,
|
||||||
Point::from((0.0, 0.0)),
|
Point::from((0.0, 0.0)),
|
||||||
|
|
@ -795,17 +805,6 @@ pub fn render_cursor_to_buffer(
|
||||||
.map(WindowCaptureElement::from)
|
.map(WindowCaptureElement::from)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
elements.extend(
|
|
||||||
additional_damage
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(|rect| {
|
|
||||||
let logical_rect = rect.to_logical(1, Transform::Normal, &Size::from((64, 64)));
|
|
||||||
logical_rect.intersection(Rectangle::from_size((64, 64).into()))
|
|
||||||
})
|
|
||||||
.map(DamageElement::new)
|
|
||||||
.map(Into::<WindowCaptureElement<R>>::into),
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Ok(dmabuf) = get_dmabuf(buffer) {
|
if let Ok(dmabuf) = get_dmabuf(buffer) {
|
||||||
let mut dmabuf_clone = dmabuf.clone();
|
let mut dmabuf_clone = dmabuf.clone();
|
||||||
let mut fb = renderer
|
let mut fb = renderer
|
||||||
|
|
@ -826,7 +825,7 @@ pub fn render_cursor_to_buffer(
|
||||||
Ok(renderer) => renderer,
|
Ok(renderer) => renderer,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(?err, "Couldn't use node for screencopy");
|
warn!(?err, "Couldn't use node for screencopy");
|
||||||
frame.fail(FailureReason::Unknown);
|
frame.fail(CaptureFailureReason::Unknown);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1,60 +1,34 @@
|
||||||
use std::{cell::RefCell, collections::HashMap, sync::Mutex};
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
use std::{cell::RefCell, sync::Mutex};
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::renderer::{damage::OutputDamageTracker, utils::CommitCounter},
|
backend::renderer::damage::OutputDamageTracker,
|
||||||
output::Output,
|
output::Output,
|
||||||
reexports::wayland_server::{Resource, Weak, protocol::wl_buffer::WlBuffer},
|
wayland::image_copy_capture::{
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
shell::{CosmicSurface, Workspace},
|
|
||||||
wayland::protocols::screencopy::{
|
|
||||||
CursorSession, CursorSessionRef, Frame, FrameRef, Session, SessionRef,
|
CursorSession, CursorSessionRef, Frame, FrameRef, Session, SessionRef,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
type ScreencopySessionsData = RefCell<ScreencopySessions>;
|
use crate::shell::{CosmicSurface, Workspace};
|
||||||
type PendingScreencopyBuffers = Mutex<Vec<(SessionRef, Frame)>>;
|
|
||||||
|
type ImageCopySessionsData = RefCell<ImageCopySessions>;
|
||||||
|
type PendingImageCopyBuffers = Mutex<Vec<(SessionRef, Frame)>>;
|
||||||
|
|
||||||
pub type SessionData = Mutex<SessionUserData>;
|
pub type SessionData = Mutex<SessionUserData>;
|
||||||
|
|
||||||
pub struct SessionUserData {
|
pub struct SessionUserData {
|
||||||
pub dt: OutputDamageTracker,
|
pub dt: OutputDamageTracker,
|
||||||
commit_counter: CommitCounter,
|
|
||||||
buffer_age: HashMap<Weak<WlBuffer>, CommitCounter>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SessionUserData {
|
impl SessionUserData {
|
||||||
pub fn new(tracker: OutputDamageTracker) -> SessionUserData {
|
pub fn new(tracker: OutputDamageTracker) -> SessionUserData {
|
||||||
SessionUserData {
|
SessionUserData { dt: tracker }
|
||||||
dt: tracker,
|
|
||||||
commit_counter: CommitCounter::default(),
|
|
||||||
buffer_age: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn age_for_buffer(&mut self, buffer: &WlBuffer) -> usize {
|
|
||||||
self.buffer_age.retain(|k, _| k.upgrade().is_ok());
|
|
||||||
|
|
||||||
let weak = buffer.downgrade();
|
|
||||||
let age = self
|
|
||||||
.commit_counter
|
|
||||||
.distance(self.buffer_age.get(&weak).copied())
|
|
||||||
.unwrap_or(0);
|
|
||||||
self.buffer_age.insert(weak, self.commit_counter);
|
|
||||||
|
|
||||||
self.commit_counter.increment();
|
|
||||||
age
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reset(&mut self) {
|
|
||||||
self.commit_counter = CommitCounter::default();
|
|
||||||
self.buffer_age.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct ScreencopySessions {
|
pub struct ImageCopySessions {
|
||||||
sessions: Vec<Session>,
|
sessions: Vec<Session>,
|
||||||
cursor_sessions: Vec<CursorSession>,
|
cursor_sessions: Vec<CursorSession>,
|
||||||
}
|
}
|
||||||
|
|
@ -78,9 +52,9 @@ pub trait FrameHolder {
|
||||||
impl SessionHolder for Output {
|
impl SessionHolder for Output {
|
||||||
fn add_session(&mut self, session: Session) {
|
fn add_session(&mut self, session: Session) {
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.insert_if_missing(ScreencopySessionsData::default);
|
.insert_if_missing(ImageCopySessionsData::default);
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.get::<ScreencopySessionsData>()
|
.get::<ImageCopySessionsData>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.sessions
|
.sessions
|
||||||
|
|
@ -89,7 +63,7 @@ impl SessionHolder for Output {
|
||||||
|
|
||||||
fn remove_session(&mut self, session: &SessionRef) {
|
fn remove_session(&mut self, session: &SessionRef) {
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.get::<ScreencopySessionsData>()
|
.get::<ImageCopySessionsData>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.sessions
|
.sessions
|
||||||
|
|
@ -98,7 +72,7 @@ impl SessionHolder for Output {
|
||||||
|
|
||||||
fn sessions(&self) -> Vec<SessionRef> {
|
fn sessions(&self) -> Vec<SessionRef> {
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.get::<ScreencopySessionsData>()
|
.get::<ImageCopySessionsData>()
|
||||||
.map_or(Vec::new(), |sessions| {
|
.map_or(Vec::new(), |sessions| {
|
||||||
sessions
|
sessions
|
||||||
.borrow()
|
.borrow()
|
||||||
|
|
@ -111,9 +85,9 @@ impl SessionHolder for Output {
|
||||||
|
|
||||||
fn add_cursor_session(&mut self, session: CursorSession) {
|
fn add_cursor_session(&mut self, session: CursorSession) {
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.insert_if_missing(ScreencopySessionsData::default);
|
.insert_if_missing(ImageCopySessionsData::default);
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.get::<ScreencopySessionsData>()
|
.get::<ImageCopySessionsData>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.cursor_sessions
|
.cursor_sessions
|
||||||
|
|
@ -122,7 +96,7 @@ impl SessionHolder for Output {
|
||||||
|
|
||||||
fn remove_cursor_session(&mut self, session: &CursorSessionRef) {
|
fn remove_cursor_session(&mut self, session: &CursorSessionRef) {
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.get::<ScreencopySessionsData>()
|
.get::<ImageCopySessionsData>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.cursor_sessions
|
.cursor_sessions
|
||||||
|
|
@ -131,7 +105,7 @@ impl SessionHolder for Output {
|
||||||
|
|
||||||
fn cursor_sessions(&self) -> Vec<CursorSessionRef> {
|
fn cursor_sessions(&self) -> Vec<CursorSessionRef> {
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.get::<ScreencopySessionsData>()
|
.get::<ImageCopySessionsData>()
|
||||||
.map_or(Vec::new(), |sessions| {
|
.map_or(Vec::new(), |sessions| {
|
||||||
sessions
|
sessions
|
||||||
.borrow()
|
.borrow()
|
||||||
|
|
@ -146,22 +120,22 @@ impl SessionHolder for Output {
|
||||||
impl FrameHolder for Output {
|
impl FrameHolder for Output {
|
||||||
fn add_frame(&mut self, session: SessionRef, frame: Frame) {
|
fn add_frame(&mut self, session: SessionRef, frame: Frame) {
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.insert_if_missing_threadsafe(PendingScreencopyBuffers::default);
|
.insert_if_missing_threadsafe(PendingImageCopyBuffers::default);
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.get::<PendingScreencopyBuffers>()
|
.get::<PendingImageCopyBuffers>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.push((session, frame));
|
.push((session, frame));
|
||||||
}
|
}
|
||||||
fn remove_frame(&mut self, frame: &FrameRef) {
|
fn remove_frame(&mut self, frame: &FrameRef) {
|
||||||
if let Some(pending) = self.user_data().get::<PendingScreencopyBuffers>() {
|
if let Some(pending) = self.user_data().get::<PendingImageCopyBuffers>() {
|
||||||
pending.lock().unwrap().retain(|(_, f)| f != frame);
|
pending.lock().unwrap().retain(|(_, f)| f != frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn take_pending_frames(&self) -> Vec<(SessionRef, Frame)> {
|
fn take_pending_frames(&self) -> Vec<(SessionRef, Frame)> {
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.get::<PendingScreencopyBuffers>()
|
.get::<PendingImageCopyBuffers>()
|
||||||
.map(|pending| std::mem::take(&mut *pending.lock().unwrap()))
|
.map(|pending| std::mem::take(&mut *pending.lock().unwrap()))
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
@ -169,14 +143,14 @@ impl FrameHolder for Output {
|
||||||
|
|
||||||
impl SessionHolder for Workspace {
|
impl SessionHolder for Workspace {
|
||||||
fn add_session(&mut self, session: Session) {
|
fn add_session(&mut self, session: Session) {
|
||||||
self.screencopy.sessions.push(session);
|
self.image_copy.sessions.push(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_session(&mut self, session: &SessionRef) {
|
fn remove_session(&mut self, session: &SessionRef) {
|
||||||
self.screencopy.sessions.retain(|s| s != session);
|
self.image_copy.sessions.retain(|s| s != session);
|
||||||
}
|
}
|
||||||
fn sessions(&self) -> Vec<SessionRef> {
|
fn sessions(&self) -> Vec<SessionRef> {
|
||||||
self.screencopy
|
self.image_copy
|
||||||
.sessions
|
.sessions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| (*s).clone())
|
.map(|s| (*s).clone())
|
||||||
|
|
@ -184,14 +158,14 @@ impl SessionHolder for Workspace {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_cursor_session(&mut self, session: CursorSession) {
|
fn add_cursor_session(&mut self, session: CursorSession) {
|
||||||
self.screencopy.cursor_sessions.push(session);
|
self.image_copy.cursor_sessions.push(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_cursor_session(&mut self, session: &CursorSessionRef) {
|
fn remove_cursor_session(&mut self, session: &CursorSessionRef) {
|
||||||
self.screencopy.cursor_sessions.retain(|s| s != session);
|
self.image_copy.cursor_sessions.retain(|s| s != session);
|
||||||
}
|
}
|
||||||
fn cursor_sessions(&self) -> Vec<CursorSessionRef> {
|
fn cursor_sessions(&self) -> Vec<CursorSessionRef> {
|
||||||
self.screencopy
|
self.image_copy
|
||||||
.cursor_sessions
|
.cursor_sessions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| (*s).clone())
|
.map(|s| (*s).clone())
|
||||||
|
|
@ -202,9 +176,9 @@ impl SessionHolder for Workspace {
|
||||||
impl SessionHolder for CosmicSurface {
|
impl SessionHolder for CosmicSurface {
|
||||||
fn add_session(&mut self, session: Session) {
|
fn add_session(&mut self, session: Session) {
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.insert_if_missing(ScreencopySessionsData::default);
|
.insert_if_missing(ImageCopySessionsData::default);
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.get::<ScreencopySessionsData>()
|
.get::<ImageCopySessionsData>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.sessions
|
.sessions
|
||||||
|
|
@ -213,7 +187,7 @@ impl SessionHolder for CosmicSurface {
|
||||||
|
|
||||||
fn remove_session(&mut self, session: &SessionRef) {
|
fn remove_session(&mut self, session: &SessionRef) {
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.get::<ScreencopySessionsData>()
|
.get::<ImageCopySessionsData>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.sessions
|
.sessions
|
||||||
|
|
@ -221,7 +195,7 @@ impl SessionHolder for CosmicSurface {
|
||||||
}
|
}
|
||||||
fn sessions(&self) -> Vec<SessionRef> {
|
fn sessions(&self) -> Vec<SessionRef> {
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.get::<ScreencopySessionsData>()
|
.get::<ImageCopySessionsData>()
|
||||||
.map_or(Vec::new(), |sessions| {
|
.map_or(Vec::new(), |sessions| {
|
||||||
sessions
|
sessions
|
||||||
.borrow()
|
.borrow()
|
||||||
|
|
@ -234,9 +208,9 @@ impl SessionHolder for CosmicSurface {
|
||||||
|
|
||||||
fn add_cursor_session(&mut self, session: CursorSession) {
|
fn add_cursor_session(&mut self, session: CursorSession) {
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.insert_if_missing(ScreencopySessionsData::default);
|
.insert_if_missing(ImageCopySessionsData::default);
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.get::<ScreencopySessionsData>()
|
.get::<ImageCopySessionsData>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.cursor_sessions
|
.cursor_sessions
|
||||||
|
|
@ -245,7 +219,7 @@ impl SessionHolder for CosmicSurface {
|
||||||
|
|
||||||
fn remove_cursor_session(&mut self, session: &CursorSessionRef) {
|
fn remove_cursor_session(&mut self, session: &CursorSessionRef) {
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.get::<ScreencopySessionsData>()
|
.get::<ImageCopySessionsData>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.cursor_sessions
|
.cursor_sessions
|
||||||
|
|
@ -254,7 +228,7 @@ impl SessionHolder for CosmicSurface {
|
||||||
|
|
||||||
fn cursor_sessions(&self) -> Vec<CursorSessionRef> {
|
fn cursor_sessions(&self) -> Vec<CursorSessionRef> {
|
||||||
self.user_data()
|
self.user_data()
|
||||||
.get::<ScreencopySessionsData>()
|
.get::<ImageCopySessionsData>()
|
||||||
.map_or(Vec::new(), |sessions| {
|
.map_or(Vec::new(), |sessions| {
|
||||||
sessions
|
sessions
|
||||||
.borrow()
|
.borrow()
|
||||||
|
|
@ -12,11 +12,13 @@ pub mod dmabuf;
|
||||||
pub mod drm;
|
pub mod drm;
|
||||||
pub mod drm_lease;
|
pub mod drm_lease;
|
||||||
pub mod drm_syncobj;
|
pub mod drm_syncobj;
|
||||||
|
pub mod fixes;
|
||||||
pub mod foreign_toplevel_list;
|
pub mod foreign_toplevel_list;
|
||||||
pub mod fractional_scale;
|
pub mod fractional_scale;
|
||||||
pub mod idle_inhibit;
|
pub mod idle_inhibit;
|
||||||
pub mod idle_notify;
|
pub mod idle_notify;
|
||||||
pub mod image_capture_source;
|
pub mod image_capture_source;
|
||||||
|
pub mod image_copy_capture;
|
||||||
pub mod input_method;
|
pub mod input_method;
|
||||||
pub mod keyboard_shortcuts_inhibit;
|
pub mod keyboard_shortcuts_inhibit;
|
||||||
pub mod layer_shell;
|
pub mod layer_shell;
|
||||||
|
|
@ -29,7 +31,6 @@ pub mod pointer_gestures;
|
||||||
pub mod presentation;
|
pub mod presentation;
|
||||||
pub mod primary_selection;
|
pub mod primary_selection;
|
||||||
pub mod relative_pointer;
|
pub mod relative_pointer;
|
||||||
pub mod screencopy;
|
|
||||||
pub mod seat;
|
pub mod seat;
|
||||||
pub mod security_context;
|
pub mod security_context;
|
||||||
pub mod selection;
|
pub mod selection;
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,10 @@ impl ToplevelManagementHandler for State {
|
||||||
|
|
||||||
std::mem::drop(shell);
|
std::mem::drop(shell);
|
||||||
|
|
||||||
if seat.active_output() != *output {
|
// move pointer to window if it’s on a different monitor/output
|
||||||
|
if seat.active_output() != *output
|
||||||
|
&& self.common.config.cosmic_conf.cursor_follows_focus
|
||||||
|
{
|
||||||
if let Some(new_pos) = new_pos {
|
if let Some(new_pos) = new_pos {
|
||||||
seat.set_active_output(output);
|
seat.set_active_output(output);
|
||||||
if let Some(ptr) = seat.get_pointer() {
|
if let Some(ptr) = seat.get_pointer() {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,35 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use crate::state::State;
|
use crate::state::State;
|
||||||
use smithay::delegate_virtual_keyboard_manager;
|
use smithay::{
|
||||||
|
backend::input::KeyState,
|
||||||
|
delegate_virtual_keyboard_manager,
|
||||||
|
input::keyboard::{FilterResult, KeyboardHandle, Keycode, xkb::ModMask},
|
||||||
|
utils::SERIAL_COUNTER,
|
||||||
|
wayland::virtual_keyboard::VirtualKeyboardHandler,
|
||||||
|
};
|
||||||
|
|
||||||
|
impl VirtualKeyboardHandler for State {
|
||||||
|
fn on_keyboard_event(
|
||||||
|
&mut self,
|
||||||
|
keycode: Keycode,
|
||||||
|
state: KeyState,
|
||||||
|
time: u32,
|
||||||
|
keyboard: KeyboardHandle<Self>,
|
||||||
|
) {
|
||||||
|
let serial = SERIAL_COUNTER.next_serial();
|
||||||
|
keyboard.input(self, keycode, state, serial, time, |_, _, _| {
|
||||||
|
FilterResult::Forward::<bool>
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fn on_keyboard_modifiers(
|
||||||
|
&mut self,
|
||||||
|
_depressed_mods: ModMask,
|
||||||
|
_latched_mods: ModMask,
|
||||||
|
_locked_mods: ModMask,
|
||||||
|
_keyboard: KeyboardHandle<Self>,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
delegate_virtual_keyboard_manager!(State);
|
delegate_virtual_keyboard_manager!(State);
|
||||||
|
|
|
||||||
|
|
@ -172,12 +172,6 @@ impl XdgShellHandler for State {
|
||||||
|
|
||||||
self.common.shell.read().unconstrain_popup(&surface);
|
self.common.shell.read().unconstrain_popup(&surface);
|
||||||
surface.send_repositioned(token);
|
surface.send_repositioned(token);
|
||||||
if let Err(err) = surface.send_configure() {
|
|
||||||
warn!(
|
|
||||||
?err,
|
|
||||||
"Client bug: Unable to re-configure repositioned popup.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_request(&mut self, surface: ToplevelSurface, seat: WlSeat, serial: Serial) {
|
fn move_request(&mut self, surface: ToplevelSurface, seat: WlSeat, serial: Serial) {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
use super::{
|
use super::{
|
||||||
toplevel_info::window_from_ext_handle,
|
|
||||||
workspace::{WorkspaceHandle, WorkspaceHandler},
|
workspace::{WorkspaceHandle, WorkspaceHandler},
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
shell::CosmicSurface,
|
shell::CosmicSurface,
|
||||||
wayland::protocols::toplevel_info::ToplevelInfoHandler,
|
|
||||||
};
|
};
|
||||||
use cosmic_protocols::image_capture_source::v1::server::{
|
use cosmic_protocols::image_capture_source::v1::server::{
|
||||||
zcosmic_workspace_image_capture_source_manager_v1::{
|
zcosmic_workspace_image_capture_source_manager_v1::{
|
||||||
|
|
@ -12,75 +10,54 @@ use cosmic_protocols::image_capture_source::v1::server::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use smithay::reexports::wayland_protocols::ext::image_capture_source::v1::server::{
|
use smithay::reexports::wayland_protocols::ext::image_capture_source::v1::server::{
|
||||||
ext_foreign_toplevel_image_capture_source_manager_v1::{
|
|
||||||
Request as ToplevelSourceRequest, ExtForeignToplevelImageCaptureSourceManagerV1,
|
|
||||||
},
|
|
||||||
ext_image_capture_source_v1::ExtImageCaptureSourceV1,
|
ext_image_capture_source_v1::ExtImageCaptureSourceV1,
|
||||||
ext_output_image_capture_source_manager_v1::{
|
|
||||||
Request as OutputSourceRequest, ExtOutputImageCaptureSourceManagerV1,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use smithay::{
|
use smithay::{
|
||||||
output::{Output, WeakOutput},
|
output::WeakOutput,
|
||||||
reexports::wayland_server::{
|
reexports::wayland_server::{
|
||||||
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource,
|
Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource,
|
||||||
},
|
},
|
||||||
|
wayland::image_capture_source::{ImageCaptureSource, ImageCaptureSourceData},
|
||||||
};
|
};
|
||||||
use wayland_backend::server::GlobalId;
|
use wayland_backend::server::GlobalId;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ImageCaptureSourceState {
|
pub struct CosmicImageCaptureSourceState {
|
||||||
output_source_global: GlobalId,
|
|
||||||
workspace_source_global: GlobalId,
|
workspace_source_global: GlobalId,
|
||||||
toplevel_source_global: GlobalId,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct OutputImageCaptureSourceManagerGlobalData {
|
|
||||||
filter: Box<dyn for<'a> Fn(&'a Client) -> bool + Send + Sync>,
|
|
||||||
}
|
|
||||||
pub struct WorkspaceImageCaptureSourceManagerGlobalData {
|
pub struct WorkspaceImageCaptureSourceManagerGlobalData {
|
||||||
filter: Box<dyn for<'a> Fn(&'a Client) -> bool + Send + Sync>,
|
filter: Box<dyn for<'a> Fn(&'a Client) -> bool + Send + Sync>,
|
||||||
}
|
}
|
||||||
pub struct ToplevelImageCaptureSourceManagerGlobalData {
|
|
||||||
filter: Box<dyn for<'a> Fn(&'a Client) -> bool + Send + Sync>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum ImageCaptureSourceData {
|
pub enum ImageCaptureSourceKind {
|
||||||
Output(WeakOutput),
|
Output(WeakOutput),
|
||||||
Workspace(WorkspaceHandle),
|
Workspace(WorkspaceHandle),
|
||||||
Toplevel(CosmicSurface),
|
Toplevel(CosmicSurface),
|
||||||
Destroyed,
|
Destroyed,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImageCaptureSourceState {
|
impl ImageCaptureSourceKind {
|
||||||
pub fn new<D, F>(display: &DisplayHandle, client_filter: F) -> ImageCaptureSourceState
|
pub fn from_resource(resource: &ExtImageCaptureSourceV1) -> Option<Self> {
|
||||||
|
let source = ImageCaptureSource::from_resource(resource)?;
|
||||||
|
source.user_data().get::<ImageCaptureSourceKind>().cloned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CosmicImageCaptureSourceState {
|
||||||
|
pub fn new<D, F>(display: &DisplayHandle, client_filter: F) -> CosmicImageCaptureSourceState
|
||||||
where
|
where
|
||||||
D: GlobalDispatch<
|
D: GlobalDispatch<
|
||||||
ExtOutputImageCaptureSourceManagerV1,
|
|
||||||
OutputImageCaptureSourceManagerGlobalData,
|
|
||||||
> + Dispatch<ExtOutputImageCaptureSourceManagerV1, ()>
|
|
||||||
+ GlobalDispatch<
|
|
||||||
ZcosmicWorkspaceImageCaptureSourceManagerV1,
|
ZcosmicWorkspaceImageCaptureSourceManagerV1,
|
||||||
WorkspaceImageCaptureSourceManagerGlobalData,
|
WorkspaceImageCaptureSourceManagerGlobalData,
|
||||||
> + Dispatch<ZcosmicWorkspaceImageCaptureSourceManagerV1, ()>
|
> + Dispatch<ZcosmicWorkspaceImageCaptureSourceManagerV1, ()>
|
||||||
+ GlobalDispatch<
|
|
||||||
ExtForeignToplevelImageCaptureSourceManagerV1,
|
|
||||||
ToplevelImageCaptureSourceManagerGlobalData,
|
|
||||||
> + Dispatch<ExtForeignToplevelImageCaptureSourceManagerV1, ()>
|
|
||||||
+ Dispatch<ExtImageCaptureSourceV1, ImageCaptureSourceData>
|
+ Dispatch<ExtImageCaptureSourceV1, ImageCaptureSourceData>
|
||||||
+ WorkspaceHandler
|
+ WorkspaceHandler
|
||||||
+ 'static,
|
+ 'static,
|
||||||
F: for<'a> Fn(&'a Client) -> bool + Send + Sync + Clone + 'static,
|
F: for<'a> Fn(&'a Client) -> bool + Send + Sync + Clone + 'static,
|
||||||
{
|
{
|
||||||
ImageCaptureSourceState {
|
CosmicImageCaptureSourceState {
|
||||||
output_source_global: display
|
|
||||||
.create_global::<D, ExtOutputImageCaptureSourceManagerV1, _>(
|
|
||||||
1,
|
|
||||||
OutputImageCaptureSourceManagerGlobalData {
|
|
||||||
filter: Box::new(client_filter.clone()),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
workspace_source_global: display
|
workspace_source_global: display
|
||||||
.create_global::<D, ZcosmicWorkspaceImageCaptureSourceManagerV1, _>(
|
.create_global::<D, ZcosmicWorkspaceImageCaptureSourceManagerV1, _>(
|
||||||
1,
|
1,
|
||||||
|
|
@ -88,57 +65,12 @@ impl ImageCaptureSourceState {
|
||||||
filter: Box::new(client_filter.clone()),
|
filter: Box::new(client_filter.clone()),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
toplevel_source_global: display
|
|
||||||
.create_global::<D, ExtForeignToplevelImageCaptureSourceManagerV1, _>(
|
|
||||||
1,
|
|
||||||
ToplevelImageCaptureSourceManagerGlobalData {
|
|
||||||
filter: Box::new(client_filter),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn output_source_id(&self) -> &GlobalId {
|
|
||||||
&self.output_source_global
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn workspace_source_id(&self) -> &GlobalId {
|
pub fn workspace_source_id(&self) -> &GlobalId {
|
||||||
&self.workspace_source_global
|
&self.workspace_source_global
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toplevel_source_id(&self) -> &GlobalId {
|
|
||||||
&self.toplevel_source_global
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<D>
|
|
||||||
GlobalDispatch<
|
|
||||||
ExtOutputImageCaptureSourceManagerV1,
|
|
||||||
OutputImageCaptureSourceManagerGlobalData,
|
|
||||||
D,
|
|
||||||
> for ImageCaptureSourceState
|
|
||||||
where
|
|
||||||
D: GlobalDispatch<
|
|
||||||
ExtOutputImageCaptureSourceManagerV1,
|
|
||||||
OutputImageCaptureSourceManagerGlobalData,
|
|
||||||
> + Dispatch<ExtOutputImageCaptureSourceManagerV1, ()>
|
|
||||||
+ Dispatch<ExtImageCaptureSourceV1, ImageCaptureSourceData>
|
|
||||||
+ 'static,
|
|
||||||
{
|
|
||||||
fn bind(
|
|
||||||
_state: &mut D,
|
|
||||||
_handle: &DisplayHandle,
|
|
||||||
_client: &Client,
|
|
||||||
resource: New<ExtOutputImageCaptureSourceManagerV1>,
|
|
||||||
_global_data: &OutputImageCaptureSourceManagerGlobalData,
|
|
||||||
data_init: &mut DataInit<'_, D>,
|
|
||||||
) {
|
|
||||||
data_init.init(resource, ());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn can_view(client: Client, global_data: &OutputImageCaptureSourceManagerGlobalData) -> bool {
|
|
||||||
(global_data.filter)(&client)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D>
|
impl<D>
|
||||||
|
|
@ -146,7 +78,7 @@ impl<D>
|
||||||
ZcosmicWorkspaceImageCaptureSourceManagerV1,
|
ZcosmicWorkspaceImageCaptureSourceManagerV1,
|
||||||
WorkspaceImageCaptureSourceManagerGlobalData,
|
WorkspaceImageCaptureSourceManagerGlobalData,
|
||||||
D,
|
D,
|
||||||
> for ImageCaptureSourceState
|
> for CosmicImageCaptureSourceState
|
||||||
where
|
where
|
||||||
D: GlobalDispatch<
|
D: GlobalDispatch<
|
||||||
ZcosmicWorkspaceImageCaptureSourceManagerV1,
|
ZcosmicWorkspaceImageCaptureSourceManagerV1,
|
||||||
|
|
@ -174,70 +106,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D>
|
impl<D> Dispatch<ZcosmicWorkspaceImageCaptureSourceManagerV1, (), D>
|
||||||
GlobalDispatch<
|
for CosmicImageCaptureSourceState
|
||||||
ExtForeignToplevelImageCaptureSourceManagerV1,
|
|
||||||
ToplevelImageCaptureSourceManagerGlobalData,
|
|
||||||
D,
|
|
||||||
> for ImageCaptureSourceState
|
|
||||||
where
|
|
||||||
D: GlobalDispatch<
|
|
||||||
ExtForeignToplevelImageCaptureSourceManagerV1,
|
|
||||||
ToplevelImageCaptureSourceManagerGlobalData,
|
|
||||||
> + Dispatch<ExtForeignToplevelImageCaptureSourceManagerV1, ()>
|
|
||||||
+ Dispatch<ExtImageCaptureSourceV1, ImageCaptureSourceData>
|
|
||||||
+ 'static,
|
|
||||||
{
|
|
||||||
fn bind(
|
|
||||||
_state: &mut D,
|
|
||||||
_handle: &DisplayHandle,
|
|
||||||
_client: &Client,
|
|
||||||
resource: New<ExtForeignToplevelImageCaptureSourceManagerV1>,
|
|
||||||
_global_data: &ToplevelImageCaptureSourceManagerGlobalData,
|
|
||||||
data_init: &mut DataInit<'_, D>,
|
|
||||||
) {
|
|
||||||
data_init.init(resource, ());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn can_view(client: Client, global_data: &ToplevelImageCaptureSourceManagerGlobalData) -> bool {
|
|
||||||
(global_data.filter)(&client)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<D> Dispatch<ExtOutputImageCaptureSourceManagerV1, (), D> for ImageCaptureSourceState
|
|
||||||
where
|
|
||||||
D: Dispatch<ExtOutputImageCaptureSourceManagerV1, ()>
|
|
||||||
+ Dispatch<ExtImageCaptureSourceV1, ImageCaptureSourceData>
|
|
||||||
+ 'static,
|
|
||||||
{
|
|
||||||
fn request(
|
|
||||||
_state: &mut D,
|
|
||||||
_client: &Client,
|
|
||||||
_resource: &ExtOutputImageCaptureSourceManagerV1,
|
|
||||||
request: <ExtOutputImageCaptureSourceManagerV1 as Resource>::Request,
|
|
||||||
_data: &(),
|
|
||||||
_dhandle: &DisplayHandle,
|
|
||||||
data_init: &mut DataInit<'_, D>,
|
|
||||||
) {
|
|
||||||
if let OutputSourceRequest::CreateSource { source, output } = request {
|
|
||||||
let data = match Output::from_resource(&output) {
|
|
||||||
Some(output) => ImageCaptureSourceData::Output(output.downgrade()),
|
|
||||||
None => ImageCaptureSourceData::Destroyed,
|
|
||||||
};
|
|
||||||
data_init.init(source, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn destroyed(
|
|
||||||
_state: &mut D,
|
|
||||||
_client: wayland_backend::server::ClientId,
|
|
||||||
_resource: &ExtOutputImageCaptureSourceManagerV1,
|
|
||||||
_data: &(),
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<D> Dispatch<ZcosmicWorkspaceImageCaptureSourceManagerV1, (), D> for ImageCaptureSourceState
|
|
||||||
where
|
where
|
||||||
D: Dispatch<ZcosmicWorkspaceImageCaptureSourceManagerV1, ()>
|
D: Dispatch<ZcosmicWorkspaceImageCaptureSourceManagerV1, ()>
|
||||||
+ Dispatch<ExtImageCaptureSourceV1, ImageCaptureSourceData>
|
+ Dispatch<ExtImageCaptureSourceV1, ImageCaptureSourceData>
|
||||||
|
|
@ -253,110 +123,36 @@ where
|
||||||
_dhandle: &DisplayHandle,
|
_dhandle: &DisplayHandle,
|
||||||
data_init: &mut DataInit<'_, D>,
|
data_init: &mut DataInit<'_, D>,
|
||||||
) {
|
) {
|
||||||
if let CosmicWorkspaceSourceRequest::CreateSource { source, output } = request {
|
if let CosmicWorkspaceSourceRequest::CreateSource {
|
||||||
let data = match state.workspace_state().get_ext_workspace_handle(&output) {
|
source: source_handle,
|
||||||
Some(workspace) => ImageCaptureSourceData::Workspace(workspace),
|
output,
|
||||||
None => ImageCaptureSourceData::Destroyed,
|
|
||||||
};
|
|
||||||
data_init.init(source, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn destroyed(
|
|
||||||
_state: &mut D,
|
|
||||||
_client: wayland_backend::server::ClientId,
|
|
||||||
_resource: &ZcosmicWorkspaceImageCaptureSourceManagerV1,
|
|
||||||
_data: &(),
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<D> Dispatch<ExtForeignToplevelImageCaptureSourceManagerV1, (), D> for ImageCaptureSourceState
|
|
||||||
where
|
|
||||||
D: Dispatch<ExtForeignToplevelImageCaptureSourceManagerV1, ()>
|
|
||||||
+ Dispatch<ExtImageCaptureSourceV1, ImageCaptureSourceData>
|
|
||||||
+ ToplevelInfoHandler<Window = CosmicSurface>
|
|
||||||
+ 'static,
|
|
||||||
{
|
|
||||||
fn request(
|
|
||||||
state: &mut D,
|
|
||||||
_client: &Client,
|
|
||||||
_resource: &ExtForeignToplevelImageCaptureSourceManagerV1,
|
|
||||||
request: <ExtForeignToplevelImageCaptureSourceManagerV1 as Resource>::Request,
|
|
||||||
_data: &(),
|
|
||||||
_dhandle: &DisplayHandle,
|
|
||||||
data_init: &mut DataInit<'_, D>,
|
|
||||||
) {
|
|
||||||
if let ToplevelSourceRequest::CreateSource {
|
|
||||||
source,
|
|
||||||
toplevel_handle,
|
|
||||||
} = request
|
} = request
|
||||||
{
|
{
|
||||||
let data = match window_from_ext_handle(state, &toplevel_handle) {
|
let data = match state.workspace_state().get_ext_workspace_handle(&output) {
|
||||||
Some(toplevel) => ImageCaptureSourceData::Toplevel(toplevel.clone()),
|
Some(workspace) => ImageCaptureSourceKind::Workspace(workspace),
|
||||||
None => ImageCaptureSourceData::Destroyed,
|
None => ImageCaptureSourceKind::Destroyed,
|
||||||
};
|
};
|
||||||
data_init.init(source, data);
|
let source = ImageCaptureSource::new();
|
||||||
|
source.user_data().insert_if_missing(|| data);
|
||||||
|
let instance = data_init.init(
|
||||||
|
source_handle,
|
||||||
|
ImageCaptureSourceData {
|
||||||
|
source: source.clone(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
source.add_instance(&instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn destroyed(
|
|
||||||
_state: &mut D,
|
|
||||||
_client: wayland_backend::server::ClientId,
|
|
||||||
_resource: &ExtForeignToplevelImageCaptureSourceManagerV1,
|
|
||||||
_data: &(),
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> Dispatch<ExtImageCaptureSourceV1, ImageCaptureSourceData, D> for ImageCaptureSourceState
|
macro_rules! delegate_cosmic_image_capture_source {
|
||||||
where
|
|
||||||
D: Dispatch<ExtImageCaptureSourceV1, ImageCaptureSourceData> + 'static,
|
|
||||||
{
|
|
||||||
fn request(
|
|
||||||
_state: &mut D,
|
|
||||||
_client: &Client,
|
|
||||||
_resource: &ExtImageCaptureSourceV1,
|
|
||||||
_request: <ExtImageCaptureSourceV1 as Resource>::Request,
|
|
||||||
_data: &ImageCaptureSourceData,
|
|
||||||
_dhandle: &DisplayHandle,
|
|
||||||
_data_init: &mut DataInit<'_, D>,
|
|
||||||
) {
|
|
||||||
{}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn destroyed(
|
|
||||||
_state: &mut D,
|
|
||||||
_client: wayland_backend::server::ClientId,
|
|
||||||
_resource: &ExtImageCaptureSourceV1,
|
|
||||||
_data: &ImageCaptureSourceData,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! delegate_image_capture_source {
|
|
||||||
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
|
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
|
||||||
smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
|
|
||||||
smithay::reexports::wayland_protocols::ext::image_capture_source::v1::server::ext_output_image_capture_source_manager_v1::ExtOutputImageCaptureSourceManagerV1: $crate::wayland::protocols::image_capture_source::OutputImageCaptureSourceManagerGlobalData
|
|
||||||
] => $crate::wayland::protocols::image_capture_source::ImageCaptureSourceState);
|
|
||||||
smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
|
|
||||||
smithay::reexports::wayland_protocols::ext::image_capture_source::v1::server::ext_output_image_capture_source_manager_v1::ExtOutputImageCaptureSourceManagerV1: ()
|
|
||||||
] => $crate::wayland::protocols::image_capture_source::ImageCaptureSourceState);
|
|
||||||
smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
|
smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
|
||||||
cosmic_protocols::image_capture_source::v1::server::zcosmic_workspace_image_capture_source_manager_v1::ZcosmicWorkspaceImageCaptureSourceManagerV1: $crate::wayland::protocols::image_capture_source::WorkspaceImageCaptureSourceManagerGlobalData
|
cosmic_protocols::image_capture_source::v1::server::zcosmic_workspace_image_capture_source_manager_v1::ZcosmicWorkspaceImageCaptureSourceManagerV1: $crate::wayland::protocols::image_capture_source::WorkspaceImageCaptureSourceManagerGlobalData
|
||||||
] => $crate::wayland::protocols::image_capture_source::ImageCaptureSourceState);
|
] => $crate::wayland::protocols::image_capture_source::CosmicImageCaptureSourceState);
|
||||||
smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
|
smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
|
||||||
cosmic_protocols::image_capture_source::v1::server::zcosmic_workspace_image_capture_source_manager_v1::ZcosmicWorkspaceImageCaptureSourceManagerV1: ()
|
cosmic_protocols::image_capture_source::v1::server::zcosmic_workspace_image_capture_source_manager_v1::ZcosmicWorkspaceImageCaptureSourceManagerV1: ()
|
||||||
] => $crate::wayland::protocols::image_capture_source::ImageCaptureSourceState);
|
] => $crate::wayland::protocols::image_capture_source::CosmicImageCaptureSourceState);
|
||||||
smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
|
|
||||||
smithay::reexports::wayland_protocols::ext::image_capture_source::v1::server::ext_foreign_toplevel_image_capture_source_manager_v1::ExtForeignToplevelImageCaptureSourceManagerV1: $crate::wayland::protocols::image_capture_source::ToplevelImageCaptureSourceManagerGlobalData
|
|
||||||
] => $crate::wayland::protocols::image_capture_source::ImageCaptureSourceState);
|
|
||||||
smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
|
|
||||||
smithay::reexports::wayland_protocols::ext::image_capture_source::v1::server::ext_foreign_toplevel_image_capture_source_manager_v1::ExtForeignToplevelImageCaptureSourceManagerV1: ()
|
|
||||||
] => $crate::wayland::protocols::image_capture_source::ImageCaptureSourceState);
|
|
||||||
smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
|
|
||||||
smithay::reexports::wayland_protocols::ext::image_capture_source::v1::server::ext_image_capture_source_v1::ExtImageCaptureSourceV1: $crate::wayland::protocols::image_capture_source::ImageCaptureSourceData
|
|
||||||
] => $crate::wayland::protocols::image_capture_source::ImageCaptureSourceState);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub(crate) use delegate_image_capture_source;
|
pub(crate) use delegate_cosmic_image_capture_source;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ pub mod image_capture_source;
|
||||||
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 screencopy;
|
|
||||||
pub mod toplevel_info;
|
pub mod toplevel_info;
|
||||||
pub mod toplevel_management;
|
pub mod toplevel_management;
|
||||||
pub mod workspace;
|
pub mod workspace;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -635,14 +635,13 @@ pub fn window_from_handle<W: Window + 'static>(handle: ZcosmicToplevelHandleV1)
|
||||||
.and_then(|state| state.lock().unwrap().window.clone())
|
.and_then(|state| state.lock().unwrap().window.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn window_from_ext_handle<'a, W: Window + 'static, D>(
|
pub fn window_from_ext<'a, W: Window + 'static, D>(
|
||||||
state: &'a D,
|
state: &'a D,
|
||||||
foreign_toplevel: &ExtForeignToplevelHandleV1,
|
handle: &ForeignToplevelHandle,
|
||||||
) -> Option<&'a W>
|
) -> Option<&'a W>
|
||||||
where
|
where
|
||||||
D: ToplevelInfoHandler<Window = W>,
|
D: ToplevelInfoHandler<Window = W>,
|
||||||
{
|
{
|
||||||
let handle = ForeignToplevelHandle::from_resource(foreign_toplevel)?;
|
|
||||||
state.toplevel_info_state().toplevels.iter().find(|w| {
|
state.toplevel_info_state().toplevels.iter().find(|w| {
|
||||||
w.user_data().get::<ToplevelState>().and_then(|inner| {
|
w.user_data().get::<ToplevelState>().and_then(|inner| {
|
||||||
inner
|
inner
|
||||||
|
|
@ -655,6 +654,17 @@ where
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn window_from_ext_handle<'a, W: Window + 'static, D>(
|
||||||
|
state: &'a D,
|
||||||
|
foreign_toplevel: &ExtForeignToplevelHandleV1,
|
||||||
|
) -> Option<&'a W>
|
||||||
|
where
|
||||||
|
D: ToplevelInfoHandler<Window = W>,
|
||||||
|
{
|
||||||
|
let handle = ForeignToplevelHandle::from_resource(foreign_toplevel)?;
|
||||||
|
window_from_ext(state, &handle)
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! delegate_toplevel_info {
|
macro_rules! delegate_toplevel_info {
|
||||||
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty, $window: ty) => {
|
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty, $window: ty) => {
|
||||||
smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
|
smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue