Recover Rime faults, persist window modes and fix GPU allocation
This commit is contained in:
1 parent
8e9a5838ab
commit
6f34fd080f
27 files changed
+1260
-34
No files matched your search
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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" => {
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
Reference in new issue
Block a user