1
0
Fork 0
forked from wry/wry

egui: add integration

This commit is contained in:
Julian Orth 2026-02-22 00:26:52 +01:00
parent 85b9b7222d
commit 008e8a671a
49 changed files with 4110 additions and 149 deletions

View file

@ -392,6 +392,7 @@ fn start_compositor2(
eventfd_cache,
lazy_event_sources: Default::default(),
bo_drop_queue: Rc::new(ObjectDropQueue::new(&ring)),
egg_state: Default::default(),
});
state.tracker.register(ClientId::from_raw(0));
create_dummy_output(&state);

View file

@ -1807,6 +1807,10 @@ impl ConfigProxyHandler {
Ok(())
}
fn handle_set_egui_fonts(&self, proportional: Option<Vec<&str>>, monospace: Option<Vec<&str>>) {
self.state.set_egui_fonts(proportional, monospace);
}
fn handle_set_log_level(&self, level: ConfigLogLevel) {
self.state.set_log_level(level.into());
}
@ -3311,6 +3315,10 @@ impl ConfigProxyHandler {
fds,
tag,
} => self.handle_run(prog, args, env, fds, tag).wrn("run")?,
ClientMessage::SetEguiFonts {
proportional,
monospace,
} => self.handle_set_egui_fonts(proportional, monospace),
}
Ok(())
}

3
src/egui_adapter.rs Normal file
View file

@ -0,0 +1,3 @@
pub mod egui_oklch;
pub mod egui_platform;
mod egui_vulkan;

View file

@ -0,0 +1,37 @@
use {
crate::{
cmm::cmm_eotf::Eotf,
theme::{Color, Oklab, Oklch},
},
egui::{Color32, Rgba},
};
#[expect(dead_code)]
pub trait Color32Ext {
fn to_oklab(self) -> Oklab;
fn to_oklch(self) -> Oklch;
}
impl Color32Ext for Color32 {
fn to_oklab(self) -> Oklab {
let [r, g, b, a] = self.to_array();
Color::from_srgba_premultiplied(r, g, b, a).srgb_to_oklab()
}
fn to_oklch(self) -> Oklch {
self.to_oklab().to_oklch()
}
}
impl Into<Color32> for Oklch {
fn into(self) -> Color32 {
self.to_oklab().into()
}
}
impl Into<Color32> for Oklab {
fn into(self) -> Color32 {
let [r, g, b, a] = self.to_srgb().to_array(Eotf::Linear);
Rgba::from_rgba_premultiplied(r, g, b, a).into()
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

BIN
src/egui_adapter/icons.ttf Normal file

Binary file not shown.

View file

@ -0,0 +1,13 @@
#version 450
layout(location = 0) in vec4 color;
layout(location = 1) in vec2 pos;
layout(binding = 0, set = 0) uniform sampler2D tex;
layout(location = 0) out vec4 res;
void main() {
vec4 src = texture(tex, pos);
res = color * src;
}

View file

@ -0,0 +1,19 @@
#version 450
layout(location = 0) in vec2 if_pos;
layout(location = 1) in vec2 it_pos;
layout(location = 2) in vec4 i_color;
layout(location = 0) out vec4 o_color;
layout(location = 1) out vec2 ot_pos;
void main() {
o_color = i_color;
o_color.rgb = mix(
o_color.rgb / vec3(12.92),
pow((o_color.rgb + vec3(0.055)) / vec3(1.055), vec3(2.4)),
greaterThan(o_color.rgb, vec3(0.04045))
);
ot_pos = it_pos;
gl_Position = vec4(if_pos.x, if_pos.y, 0.0, 1.0);
}

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,2 @@
7eb8fae39ae513bc4f6973c12227aa4aa43734bdf34c90e1b3b69294ad98db87 src/egui_adapter/shaders/shader.frag
501f4d0c5c5f10a371659b89f12d87abb03e5b57a31dbae5f3c6ca5726e4db01 src/egui_adapter/shaders/shader.vert

View file

@ -34,14 +34,12 @@ pub enum FontconfigError {
}
#[derive(Debug)]
#[expect(dead_code)]
pub struct Font {
pub fullname: String,
pub file: PathBuf,
pub index: Option<i32>,
}
#[expect(dead_code)]
pub fn match_font(family: &str) -> Result<Font, FontconfigError> {
thread_local! {
static CONFIG: *mut FcConfig = FcConfigGetCurrent();

View file

@ -256,7 +256,7 @@ pub struct Globals {
removed: CopyHashMap<GlobalName, Rc<dyn Global>>,
pub outputs: CopyHashMap<GlobalName, Rc<WlOutputGlobal>>,
pub seats: CopyHashMap<GlobalName, Rc<WlSeatGlobal>>,
singletons: StaticMap<Singleton, GlobalName>,
pub singletons: StaticMap<Singleton, GlobalName>,
exposed: StaticMap<Singleton, Cell<bool>>,
}

View file

@ -138,6 +138,9 @@ const MISSING_CAPABILITY: u32 = 0;
pub const BTN_LEFT: u32 = 0x110;
pub const BTN_RIGHT: u32 = 0x111;
pub const BTN_MIDDLE: u32 = 0x112;
pub const BTN_SIDE: u32 = 0x113;
pub const BTN_EXTRA: u32 = 0x114;
pub const SEAT_NAME_SINCE: Version = Version(2);

View file

@ -67,6 +67,7 @@ mod damage;
mod dbus;
mod drm_feedback;
mod edid;
mod egui_adapter;
mod ei;
mod eventfd_cache;
mod fixed;

View file

@ -42,6 +42,15 @@ pub struct AcceptorMetadata {
pub tag: Option<String>,
}
impl AcceptorMetadata {
pub fn secure() -> Self {
Self {
secure: true,
..Default::default()
}
}
}
impl SecurityContextAcceptors {
pub fn clear(&self) {
for acceptor in self.acceptors.lock().drain_values() {

View file

@ -24,6 +24,7 @@ use {
damage::DamageVisualizer,
dbus::Dbus,
drm_feedback::{DrmFeedback, DrmFeedbackIds},
egui_adapter::egui_platform::EggState,
ei::{
ei_acceptor::EiAcceptor,
ei_client::{EiClient, EiClients},
@ -226,7 +227,7 @@ pub struct State {
pub activation_tokens: CopyHashMap<ActivationToken, ()>,
pub toplevel_lists:
CopyHashMap<(ClientId, ExtForeignToplevelListV1Id), Rc<ExtForeignToplevelListV1>>,
pub dma_buf_ids: DmaBufIds,
pub dma_buf_ids: Rc<DmaBufIds>,
pub drm_feedback_ids: DrmFeedbackIds,
pub direct_scanout_enabled: Cell<bool>,
pub persistent_output_states: CopyHashMap<Rc<OutputId>, Rc<PersistentOutputState>>,
@ -295,6 +296,7 @@ pub struct State {
pub eventfd_cache: Rc<EventfdCache>,
pub lazy_event_sources: Rc<LazyEventSources>,
pub bo_drop_queue: Rc<ObjectDropQueue<Rc<dyn BufferObject>>>,
pub egg_state: EggState,
}
// impl Drop for State {
@ -645,6 +647,7 @@ impl State {
}
pub fn set_render_ctx(&self, ctx: Option<Rc<dyn GfxContext>>) {
self.egg_state.clear();
self.explicit_sync_supported.set(false);
self.render_ctx.set(ctx.clone());
self.render_ctx_version.fetch_add(1);
@ -1158,6 +1161,7 @@ impl State {
self.xdg_surface_configure_events.clear();
self.lazy_event_sources.clear();
self.bo_drop_queue.kill();
self.egg_state.clear();
}
pub fn remove_toplevel_id(&self, id: ToplevelIdentifier) {
@ -1876,6 +1880,7 @@ impl State {
theme.font.set(self.theme.default_font.clone());
theme.bar_font.set(None);
theme.title_font.set(None);
self.egg_state.reset_fonts();
self.fonts_changed();
}
@ -1896,6 +1901,16 @@ impl State {
self.fonts_changed();
}
pub fn set_egui_fonts(&self, proportional: Option<Vec<&str>>, monospace: Option<Vec<&str>>) {
if let Some(fonts) = &proportional {
self.egg_state.set_proportional_fonts(fonts);
}
if let Some(fonts) = &monospace {
self.egg_state.set_monospace_fonts(fonts);
}
self.fonts_changed();
}
pub fn set_bar_position(&self, p: BarPosition) {
self.theme.bar_position.set(p);
self.spaces_changed();

View file

@ -32,7 +32,6 @@ impl<T> ObjectDropQueue<T> {
}
}
#[expect(dead_code)]
pub fn push(self: &Rc<Self>, fd: &Rc<OwnedFd>, t: T)
where
T: 'static,

View file

@ -14,7 +14,6 @@ pub fn pipe() -> Result<Pipe<OwnedFd, OwnedFd>, OsError> {
}
impl<L, R> Pipe<L, R> {
#[expect(dead_code)]
pub fn map_read<Lprime>(self, map: impl FnOnce(L) -> Lprime) -> Pipe<Lprime, R> {
Pipe {
read: map(self.read),
@ -22,7 +21,6 @@ impl<L, R> Pipe<L, R> {
}
}
#[expect(dead_code)]
pub fn map_write<Rprime>(self, map: impl FnOnce(R) -> Rprime) -> Pipe<L, Rprime> {
Pipe {
read: self.read,

View file

@ -1,8 +1,12 @@
use {
crate::{
format::Format,
gfx_api::SyncFile,
utils::{compat::IoctlNumber, oserror::OsError},
video::{LINEAR_MODIFIER, Modifier},
video::{
LINEAR_MODIFIER, Modifier,
drm::{DrmError, syncobj::merge_sync_files},
},
},
arrayvec::ArrayVec,
std::{cell::OnceCell, rc::Rc, sync::OnceLock},
@ -113,6 +117,22 @@ impl DmaBuf {
}
Ok(())
}
pub fn export_sync_file(&self, flags: u32) -> Result<Option<SyncFile>, DrmError> {
let mut sf = PlaneVec::new();
for plane in &self.planes {
sf.push(
dma_buf_export_sync_file(&plane.fd, flags)
.map(Rc::new)
.map(SyncFile)
.map_err(DrmError::ExportSyncFile)?,
);
if self.is_one_file() {
break;
}
}
merge_sync_files(sf.iter())
}
}
const DMA_BUF_BASE: u64 = b'b' as _;

View file

@ -189,7 +189,6 @@ impl UsrJayCompositor {
obj
}
#[expect(dead_code)]
pub fn get_sync_file_surface(&self, surface: &UsrWlSurface) -> Rc<UsrJaySyncFileSurface> {
let obj = Rc::new(UsrJaySyncFileSurface {
id: self.con.id(),

View file

@ -18,7 +18,6 @@ pub struct UsrJaySyncFileSurface {
}
impl UsrJaySyncFileSurface {
#[expect(dead_code)]
pub fn set_acquire(&self, sf: Option<&FdSync>) {
match sf.and_then(|s| s.get_sync_file()) {
None => {
@ -33,7 +32,6 @@ impl UsrJaySyncFileSurface {
}
}
#[expect(dead_code)]
pub fn get_release(&self) -> Rc<UsrJaySyncFileRelease> {
let obj = Rc::new(UsrJaySyncFileRelease {
id: self.con.id(),

View file

@ -21,7 +21,6 @@ pub struct UsrWlDataDevice {
}
impl UsrWlDataDevice {
#[expect(dead_code)]
pub fn set_selection(&self, serial: u32, source: &UsrWlDataSource) {
self.con.request(SetSelection {
self_id: self.id,

View file

@ -21,7 +21,6 @@ pub struct UsrWlDataDeviceManager {
}
impl UsrWlDataDeviceManager {
#[expect(dead_code)]
pub fn create_data_source(&self) -> Rc<UsrWlDataSource> {
let obj = Rc::new(UsrWlDataSource {
id: self.con.id(),
@ -37,7 +36,6 @@ impl UsrWlDataDeviceManager {
obj
}
#[expect(dead_code)]
pub fn get_data_device(&self, seat: &UsrWlSeat) -> Rc<UsrWlDataDevice> {
let obj = Rc::new(UsrWlDataDevice {
id: self.con.id(),

View file

@ -17,7 +17,6 @@ pub struct UsrWlDataOffer {
}
impl UsrWlDataOffer {
#[expect(dead_code)]
pub fn receive(&self, mime_type: &str, fd: &Rc<OwnedFd>) {
self.con.request(Receive {
self_id: self.id,

View file

@ -21,7 +21,6 @@ pub trait UsrWlDataSourceOwner {
}
impl UsrWlDataSource {
#[expect(dead_code)]
pub fn offer(&self, mime_type: &str) {
self.con.request(Offer {
self_id: self.id,

View file

@ -41,7 +41,6 @@ pub trait UsrWlPointerOwner {
}
impl UsrWlPointer {
#[expect(dead_code)]
pub fn set_cursor(&self, serial: u32, cursor: Option<&UsrWlSurface>, hot_x: i32, hot_y: i32) {
self.con.request(SetCursor {
self_id: self.id,

View file

@ -47,7 +47,6 @@ impl UsrWlSeat {
ptr
}
#[expect(dead_code)]
pub fn get_keyboard(&self) -> Rc<UsrWlKeyboard> {
let kb = Rc::new(UsrWlKeyboard {
id: self.con.id(),

View file

@ -15,7 +15,6 @@ pub struct UsrWpCursorShapeDeviceV1 {
}
impl UsrWpCursorShapeDeviceV1 {
#[expect(dead_code)]
pub fn set_shape(&self, serial: u32, cursor: KnownCursor) {
self.con.request(SetShape {
self_id: self.id,

View file

@ -21,7 +21,6 @@ pub struct UsrWpCursorShapeManagerV1 {
}
impl UsrWpCursorShapeManagerV1 {
#[expect(dead_code)]
pub fn get_pointer(&self, pointer: &UsrWlPointer) -> Rc<UsrWpCursorShapeDeviceV1> {
let obj = Rc::new(UsrWpCursorShapeDeviceV1 {
id: self.con.id(),

View file

@ -22,7 +22,6 @@ pub trait UsrXdgSurfaceOwner {
}
impl UsrXdgSurface {
#[expect(dead_code)]
pub fn get_toplevel(&self) -> Rc<UsrXdgToplevel> {
let obj = Rc::new(UsrXdgToplevel {
id: self.con.id(),

View file

@ -16,7 +16,6 @@ pub struct UsrXdgToplevel {
}
impl UsrXdgToplevel {
#[expect(dead_code)]
pub fn set_title(&self, title: &str) {
self.con.request(SetTitle {
self_id: self.id,
@ -24,7 +23,6 @@ impl UsrXdgToplevel {
});
}
#[expect(dead_code)]
pub fn set_fullscreen(&self, fullscreen: bool) {
match fullscreen {
true => {

View file

@ -18,7 +18,6 @@ pub struct UsrXdgWmBase {
}
impl UsrXdgWmBase {
#[expect(dead_code)]
pub fn get_xdg_surface(&self, surface: &UsrWlSurface) -> Rc<UsrXdgSurface> {
let obj = Rc::new(UsrXdgSurface {
id: self.con.id(),

View file

@ -22,7 +22,6 @@ pub struct UsrZwpLinuxDmabufV1 {
}
impl UsrZwpLinuxDmabufV1 {
#[expect(dead_code)]
pub fn create_buffer(&self, buffer: &DmaBuf) -> Rc<UsrWlBuffer> {
let params = Rc::new(UsrZwpLinuxBufferParamsV1 {
id: self.con.id(),