Recover Rime faults, persist window modes and fix GPU allocation

This commit is contained in:
aria committed 2026-10-28 02:32:19 +09:00
1 parent 8e9a5838ab
commit 6f34fd080f
27 files changed
+1260 -34

No files matched your search

+13 -1
View File
@@ -999,6 +999,14 @@ fn open_device(state: &mut Ferese, path: &Path) -> Result<DrmNode, Box<dyn Error
.session
.clone();
let node = DrmNode::from_path(path)?;
// Advertise one allocation entry point. Otherwise clients may bind an
// idle secondary GPU's global and allocate buffers that the display GPU
// cannot import. Per-surface feedback still describes output tranches.
let allocation_device = primary_gpu(session.seat())
.ok()
.flatten()
.and_then(|path| DrmNode::from_path(path).ok())
.is_none_or(|primary| primary == node);
let session_device = session_device::SessionDevice::open(session, path)?;
let fd = DrmDeviceFd::new(session_device.device_fd()?);
let (drm, notifier) = DrmDevice::new(fd.clone(), true)?;
@@ -1177,7 +1185,11 @@ fn open_device(state: &mut Ferese, path: &Path) -> Result<DrmNode, Box<dyn Error
let dmabuf_global = state
.dmabuf_state
.create_global_with_default_feedback::<Ferese>(&display_handle, &feedback);
.create_global_with_filter_and_default_feedback::<Ferese, _>(
&display_handle,
&feedback,
move |_| allocation_device,
);
state.dmabuf_imports.register(dmabuf_global);
state.dmabuf_feedback.register(dmabuf_global, feedback);
state
+2
View File
@@ -53,6 +53,8 @@ macro_rules! delegate_protocols {
}
delegate_protocols!(
wlr::virtual_pointer::v1::server::zwlr_virtual_pointer_manager_v1::ZwlrVirtualPointerManagerV1,
wlr::virtual_pointer::v1::server::zwlr_virtual_pointer_v1::ZwlrVirtualPointerV1,
protocols::ext::image_capture_source::v1::server::ext_image_capture_source_v1::ExtImageCaptureSourceV1,
protocols::ext::image_capture_source::v1::server::ext_output_image_capture_source_manager_v1::ExtOutputImageCaptureSourceManagerV1,
protocols::ext::image_copy_capture::v1::server::ext_image_copy_capture_manager_v1::ExtImageCopyCaptureManagerV1,
+1
View File
@@ -12,6 +12,7 @@ pub(crate) mod security_context;
#[cfg(test)]
mod toplevel_icon_tests;
mod virtual_keyboard;
mod virtual_pointer;
pub(crate) mod window_capture;
mod xdg_shell;
@@ -0,0 +1,13 @@
use crate::Ferese;
use smithay::backend::input::InputEvent;
use smithay::wayland::virtual_pointer::{VirtualPointerBackend, VirtualPointerHandler};
impl VirtualPointerHandler for Ferese {
fn process_virtual_pointer_event(&mut self, event: InputEvent<VirtualPointerBackend>) {
// The global exists only with the explicit test-pointer environment
// switch. Synthetic pointers must never enter a real lock surface.
if !self.session_lock.active() {
self.process_input_event(event);
}
}
}
+59
View File
@@ -1205,6 +1205,27 @@ impl Ferese {
.reload_config()
.map_err(|e| CommandError::new("invalid_config", e))?,
"focus" => self.focus_direction(direction_arg(args)?),
"focus-output" => {
let name = args["name"]
.as_str()
.ok_or_else(|| CommandError::new("invalid_argument", "Missing output name"))?;
let geometry = self
.space
.outputs()
.find(|output| output.name() == name)
.and_then(|output| self.space.output_geometry(output))
.ok_or_else(|| {
CommandError::new("invalid_argument", "Output is not enabled")
})?;
self.focus_output_at(
(
geometry.loc.x as f64 + geometry.size.w as f64 / 2.,
geometry.loc.y as f64 + geometry.size.h as f64 / 2.,
)
.into(),
);
self.restore_keyboard_focus();
}
"focus-last-window" => self.focus_last_window(),
"focus-floating" => self.focus_floating(),
"focus-mru-next" => self.cycle_focus(false, false),
@@ -1249,6 +1270,44 @@ impl Ferese {
"expel" => self.expel_focused_window(),
"close" => self.close_focused_window(),
"get-focused-window" => return Ok(self.focused_window_json()),
"focus-window" => {
let id = args["window"]
.as_u64()
.map(ferese_layout::WindowId)
.ok_or_else(|| CommandError::new("invalid_argument", "Missing window ID"))?;
if self.windows.record(id).is_none() {
return Err(CommandError::new(
"invalid_argument",
"Window does not exist",
));
}
self.activate_managed_window(id);
}
"get-input-context" => {
// No window titles or application input are exposed to the IME.
// A fresh compositor session cannot reuse another session's IDs.
static SESSION: std::sync::OnceLock<String> = std::sync::OnceLock::new();
let session = SESSION.get_or_init(|| {
format!(
"{}-{}",
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_nanos()
)
});
let context = self
.seat
.get_keyboard()
.and_then(|keyboard| keyboard.current_focus())
.and_then(|surface| self.windows.id_for_surface(&surface))
.and_then(|id| {
self.windows.record(id).map(|record|
json!({"session":session,"window":id.0,"app_id":record.app_id}))
});
return Ok(context.unwrap_or(Value::Null));
}
"get-windows" => return Ok(self.windows_json()),
"media-get" => return Ok(self.media_engine.value()),
"get-idle-inhibition" => {
+11
View File
@@ -573,6 +573,8 @@ pub struct Ferese {
pub idle_notifier_state: IdleNotifierState<Self>,
pub input_method_manager_state: InputMethodManagerState,
pub virtual_keyboard_manager_state: VirtualKeyboardManagerState,
pub virtual_pointer_manager_state:
Option<smithay::wayland::virtual_pointer::VirtualPointerManagerState>,
pub keyboard_shortcuts_inhibit_state: KeyboardShortcutsInhibitState,
pub output_manager_state: OutputManagerState,
pub pointer_constraints_state: PointerConstraintsState,
@@ -680,6 +682,14 @@ impl Ferese {
VirtualKeyboardManagerState::new::<Self, _>(&display_handle, move |_| {
input_method_enabled
});
let virtual_pointer_manager_state = (std::env::var_os("FERESE_ENABLE_TEST_POINTER")
.is_some_and(|value| value == "1"))
.then(|| {
smithay::wayland::virtual_pointer::VirtualPointerManagerState::new::<Self, _>(
&display_handle,
|_| true,
)
});
let keyboard_shortcuts_inhibit_state =
KeyboardShortcutsInhibitState::new::<Self>(&display_handle);
let shortcut_inhibit_enabled =
@@ -900,6 +910,7 @@ impl Ferese {
idle_notifier_state,
input_method_manager_state,
virtual_keyboard_manager_state,
virtual_pointer_manager_state,
keyboard_shortcuts_inhibit_state,
output_manager_state,
pointer_constraints_state,
+20 -3
View File
@@ -3,6 +3,7 @@ use std::error::Error;
use std::rc::Rc;
use std::time::{Duration, Instant};
use smithay::backend::egl::EGLDevice;
use smithay::backend::renderer::damage::OutputDamageTracker;
use smithay::backend::renderer::element::RenderElementStates;
use smithay::backend::renderer::gles::GlesRenderer;
@@ -13,6 +14,7 @@ use smithay::output::{Mode, Output, PhysicalProperties, Scale, Subpixel};
use smithay::reexports::calloop::EventLoop;
use smithay::reexports::calloop::timer::{TimeoutAction, Timer};
use smithay::utils::{Physical, Rectangle, Size, Transform};
use smithay::wayland::dmabuf::DmabufFeedbackBuilder;
use crate::Ferese;
use crate::metrics::{FrameEffectMetrics, RenderMetrics};
@@ -35,9 +37,24 @@ pub fn init(event_loop: &mut EventLoop<Ferese>, state: &mut Ferese) -> Result<()
let drawable = Rc::new(Cell::new(usable_size(initial_size)));
let dmabuf_formats = backend.renderer().dmabuf_formats();
let display_handle = state.display_handle.clone();
let dmabuf_global = state
.dmabuf_state
.create_global::<Ferese>(&display_handle, dmabuf_formats);
// V3 formats alone leave multi-GPU clients choosing their system default
// GPU. Publish the actual renderer device so new buffers match this EGL
// context instead of requiring an unrelated cross-GPU import.
let node = EGLDevice::device_for_display(backend.renderer().egl_context().display())
.ok()
.and_then(|device| device.try_get_render_node().ok().flatten());
let dmabuf_global = if let Some(node) = node {
let feedback = DmabufFeedbackBuilder::new(node.dev_id(), dmabuf_formats).build()?;
let global = state
.dmabuf_state
.create_global_with_default_feedback::<Ferese>(&display_handle, &feedback);
state.dmabuf_feedback.register(global, feedback);
global
} else {
state
.dmabuf_state
.create_global::<Ferese>(&display_handle, dmabuf_formats)
};
state.dmabuf_imports.register(dmabuf_global);
let initial_scale = normalized_scale(backend.scale_factor());
let mode = Mode {