diff --git a/Cargo.lock b/Cargo.lock index 440b5b9..902d709 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -565,7 +565,7 @@ dependencies = [ [[package]] name = "counter" -version = "0.3.0" +version = "0.4.0-dev" dependencies = [ "iced", "iced_layershell", @@ -574,7 +574,7 @@ dependencies = [ [[package]] name = "counter_lock" -version = "0.3.0" +version = "0.4.0-dev" dependencies = [ "iced", "iced_runtime", @@ -583,7 +583,7 @@ dependencies = [ [[package]] name = "counter_multi" -version = "0.3.0" +version = "0.4.0-dev" dependencies = [ "iced", "iced_layershell", @@ -592,7 +592,7 @@ dependencies = [ [[package]] name = "counter_virtual_keyboard" -version = "0.3.0" +version = "0.4.0-dev" dependencies = [ "iced", "iced_layershell", @@ -1365,7 +1365,7 @@ dependencies = [ [[package]] name = "iced_layershell" -version = "0.3.0" +version = "0.4.0-dev" dependencies = [ "futures", "iced", @@ -1407,7 +1407,7 @@ dependencies = [ [[package]] name = "iced_sessionlock" -version = "0.3.0" +version = "0.4.0-dev" dependencies = [ "futures", "iced", @@ -1658,7 +1658,7 @@ dependencies = [ [[package]] name = "layershellev" -version = "0.3.0" +version = "0.4.0-dev" dependencies = [ "bitflags 2.6.0", "log", @@ -2725,7 +2725,7 @@ dependencies = [ [[package]] name = "sessionlockev" -version = "0.3.0" +version = "0.4.0-dev" dependencies = [ "bitflags 2.6.0", "log", @@ -3241,7 +3241,7 @@ checksum = "8686b91785aff82828ed725225925b33b4fde44c4bb15876e5f7c832724c420a" [[package]] name = "ulauncher" -version = "0.3.0" +version = "0.4.0-dev" dependencies = [ "gio", "iced", @@ -3490,7 +3490,7 @@ dependencies = [ [[package]] name = "waycrate_xkbkeycode" -version = "0.3.0" +version = "0.4.0-dev" dependencies = [ "bitflags 2.6.0", "log", diff --git a/Cargo.toml b/Cargo.toml index 4522b01..7d21373 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ authors = [ "Aakash Sen Sharma ", ] edition = "2021" -version = "0.3.0" +version = "0.4.0-dev" license = "MIT" repository = "https://github.com/waycrate/exwlshelleventloop" description = "Wayland extra shell lib" @@ -24,12 +24,12 @@ keywords = ["wayland", "wlroots"] readme = "README.md" [workspace.dependencies] -layershellev = { version = "0.3.0", path = "./layershellev" } -sessionlockev = { version = "0.3.0", path = "./sessionlockev" } +layershellev = { version = "0.4.0-dev", path = "./layershellev" } +sessionlockev = { version = "0.4.0-dev", path = "./sessionlockev" } -iced_layershell = { version = "0.3.0", path = "./iced_layershell" } -iced_sessionlock = { version = "0.3.0", path = "./iced_sessionlock" } -waycrate_xkbkeycode = { version = "0.3.0", path = "./waycrate_xkbkeycode" } +iced_layershell = { version = "0.4.0-dev", path = "./iced_layershell" } +iced_sessionlock = { version = "0.4.0-dev", path = "./iced_sessionlock" } +waycrate_xkbkeycode = { version = "0.4.0-dev", path = "./waycrate_xkbkeycode" } tempfile = "3.10.1" thiserror = "1.0.63" diff --git a/iced_sessionlock/src/multi_window.rs b/iced_sessionlock/src/multi_window.rs index c00b520..524d254 100644 --- a/iced_sessionlock/src/multi_window.rs +++ b/iced_sessionlock/src/multi_window.rs @@ -145,7 +145,7 @@ where runtime.enter(|| A::new(flags)) }; - let mut ev: WindowState<()> = sessionlockev::WindowState::new() + let ev: WindowState<()> = sessionlockev::WindowState::new() .with_use_display_handle(true) .build() .unwrap(); diff --git a/layershellev/src/lib.rs b/layershellev/src/lib.rs index ee1df8f..a1648e2 100644 --- a/layershellev/src/lib.rs +++ b/layershellev/src/lib.rs @@ -1358,8 +1358,37 @@ impl WindowState { /// /// Different with running, it receiver a receiver pub fn running_with_proxy( - mut self, + self, message_receiver: std::sync::mpsc::Receiver, + event_handler: F, + ) -> Result<(), LayerEventError> + where + F: FnMut(LayerEvent, &mut WindowState, Option) -> ReturnData, + { + self.running_with_proxy_option(Some(message_receiver), event_handler) + } + /// main event loop, every time dispatch, it will store the messages, and do callback. it will + /// pass a LayerEvent, with self as mut, the last `Option` describe which unit the event + /// happened on, like tell you this time you do a click, what surface it is on. you can use the + /// index to get the unit, with [WindowState::get_unit] if the even is not spical on one surface, + /// it will return [None]. + /// main event loop, every time dispatch, it will store the messages, and do callback. it will + /// pass a LayerEvent, with self as mut, the last `Option` describe which unit the event + /// happened on, like tell you this time you do a click, what surface it is on. you can use the + /// index to get the unit, with [WindowState::get_unit] if the even is not spical on one surface, + /// it will return [None]. + /// + /// + pub fn running(self, event_handler: F) -> Result<(), LayerEventError> + where + F: FnMut(LayerEvent, &mut WindowState, Option) -> ReturnData, + { + self.running_with_proxy_option(None, event_handler) + } + + fn running_with_proxy_option( + mut self, + message_receiver: Option>, mut event_handler: F, ) -> Result<(), LayerEventError> where @@ -1582,7 +1611,7 @@ impl WindowState { } } } - if let Ok(event) = message_receiver.try_recv() { + if let Some(event) = message_receiver.as_ref().and_then(|rv| rv.try_recv().ok()) { match event_handler(LayerEvent::UserEvent(event), &mut self, None) { ReturnData::RequestExist => { break 'out; @@ -1699,239 +1728,6 @@ impl WindowState { } Ok(()) } - /// main event loop, every time dispatch, it will store the messages, and do callback. it will - /// pass a LayerEvent, with self as mut, the last `Option` describe which unit the event - /// happened on, like tell you this time you do a click, what surface it is on. you can use the - /// index to get the unit, with [WindowState::get_unit] if the even is not spical on one surface, - /// it will return [None]. - /// main event loop, every time dispatch, it will store the messages, and do callback. it will - /// pass a LayerEvent, with self as mut, the last `Option` describe which unit the event - /// happened on, like tell you this time you do a click, what surface it is on. you can use the - /// index to get the unit, with [WindowState::get_unit] if the even is not spical on one surface, - /// it will return [None]. - /// - /// - pub fn running(mut self, mut event_handler: F) -> Result<(), LayerEventError> - where - F: FnMut(LayerEvent, &mut WindowState, Option) -> ReturnData, - { - let globals = self.globals.take().unwrap(); - let event_queue = self.event_queue.take().unwrap(); - let qh = event_queue.handle(); - let wmcompositer = self.wl_compositor.take().unwrap(); - let shm = self.shm.take().unwrap(); - let fractional_scale_manager = self.fractional_scale_manager.take(); - let cursor_manager: Option = self.cursor_manager.take(); - let xdg_output_manager = self.xdg_output_manager.take().unwrap(); - let connection = self.connection.take().unwrap(); - let mut init_event = None; - - while !matches!(init_event, Some(ReturnData::None)) { - match init_event { - None => { - init_event = Some(event_handler(LayerEvent::InitRequest, &mut self, None)); - } - Some(ReturnData::RequestBind) => { - init_event = Some(event_handler( - LayerEvent::BindProvide(&globals, &qh), - &mut self, - None, - )); - } - _ => panic!("Not provide server here"), - } - } - let mut event_loop: EventLoop = - EventLoop::try_new().expect("Failed to initialize the event loop"); - - WaylandSource::new(connection.clone(), event_queue) - .insert(event_loop.handle()) - .expect("Failed to init wayland source"); - 'out: loop { - event_loop.dispatch(Duration::from_millis(1), &mut self)?; - - let mut messages = Vec::new(); - std::mem::swap(&mut messages, &mut self.message); - for msg in messages.iter() { - match msg { - (Some(unit_index), DispatchMessageInner::RefreshSurface { width, height }) => { - let index = *unit_index; - // NOTE: is is use_display_handle, just send request_refresh - // I will use it in iced - if self.units[index].buffer.is_none() && !self.use_display_handle { - let mut file = tempfile::tempfile()?; - let ReturnData::WlBuffer(buffer) = event_handler( - LayerEvent::RequestBuffer(&mut file, &shm, &qh, *width, *height), - &mut self, - Some(index), - ) else { - panic!("You cannot return this one"); - }; - let surface = &self.units[index].wl_surface; - surface.attach(Some(&buffer), 0, 0); - self.units[index].buffer = Some(buffer); - } else { - event_handler( - LayerEvent::RequestMessages(&DispatchMessage::RequestRefresh { - width: *width, - height: *height, - }), - &mut self, - Some(index), - ); - } - let surface = &self.units[index].wl_surface; - - surface.commit(); - } - (index_info, DispatchMessageInner::XdgInfoChanged(change_type)) => { - event_handler( - LayerEvent::XdgInfoChanged(*change_type), - &mut self, - *index_info, - ); - } - (_, DispatchMessageInner::NewDisplay(display)) => { - if self.is_single { - continue; - } - let wl_surface = wmcompositer.create_surface(&qh, ()); // and create a surface. if two or more, - let layer_shell = globals - .bind::(&qh, 3..=4, ()) - .unwrap(); - let layer = layer_shell.get_layer_surface( - &wl_surface, - Some(display), - self.layer, - self.namespace.clone(), - &qh, - (), - ); - layer.set_anchor(self.anchor); - layer.set_keyboard_interactivity(self.keyboard_interactivity); - if let Some((init_w, init_h)) = self.size { - layer.set_size(init_w, init_h); - } - - if let Some(zone) = self.exclusive_zone { - layer.set_exclusive_zone(zone); - } - - if let Some((top, right, bottom, left)) = self.margin { - layer.set_margin(top, right, bottom, left); - } - - wl_surface.commit(); - - let zxdgoutput = xdg_output_manager.get_xdg_output(display, &qh, ()); - let mut fractional_scale = None; - if let Some(ref fractional_scale_manager) = fractional_scale_manager { - fractional_scale = Some(fractional_scale_manager.get_fractional_scale( - &wl_surface, - &qh, - (), - )); - } - // so during the init Configure of the shell, a buffer, atleast a buffer is needed. - // and if you need to reconfigure it, you need to commit the wl_surface again - // so because this is just an example, so we just commit it once - // like if you want to reset anchor or KeyboardInteractivity or resize, commit is needed - - self.units.push(WindowStateUnit { - id: id::Id::unique(), - display: connection.display(), - wl_surface, - size: (0, 0), - buffer: None, - layer_shell: layer, - zxdgoutput: Some(ZxdgOutputInfo::new(zxdgoutput)), - fractional_scale, - binding: None, - }); - } - _ => { - let (index_message, msg) = msg; - let msg: DispatchMessage = msg.clone().into(); - match event_handler( - LayerEvent::RequestMessages(&msg), - &mut self, - *index_message, - ) { - ReturnData::RequestExist => { - break 'out; - } - ReturnData::RequestSetCursorShape((shape_name, pointer, serial)) => { - if let Some(ref cursor_manager) = cursor_manager { - let Some(shape) = str_to_shape(&shape_name) else { - eprintln!("Not supported shape"); - continue; - }; - let device = cursor_manager.get_pointer(&pointer, &qh, ()); - device.set_shape(serial, shape); - device.destroy(); - } else { - let Some(cursor_buffer) = - get_cursor_buffer(&shape_name, &connection, &shm) - else { - eprintln!("Cannot find cursor {shape_name}"); - continue; - }; - let cursor_surface = wmcompositer.create_surface(&qh, ()); - cursor_surface.attach(Some(&cursor_buffer), 0, 0); - // and create a surface. if two or more, - let (hotspot_x, hotspot_y) = cursor_buffer.hotspot(); - pointer.set_cursor( - serial, - Some(&cursor_surface), - hotspot_x as i32, - hotspot_y as i32, - ); - cursor_surface.commit(); - } - } - _ => {} - } - } - } - } - match event_handler(LayerEvent::NormalDispatch, &mut self, None) { - ReturnData::RequestExist => { - break 'out; - } - ReturnData::RequestSetCursorShape((shape_name, pointer, serial)) => { - if let Some(ref cursor_manager) = cursor_manager { - let Some(shape) = str_to_shape(&shape_name) else { - eprintln!("Not supported shape"); - continue; - }; - let device = cursor_manager.get_pointer(&pointer, &qh, ()); - device.set_shape(serial, shape); - device.destroy(); - } else { - let Some(cursor_buffer) = get_cursor_buffer(&shape_name, &connection, &shm) - else { - eprintln!("Cannot find cursor {shape_name}"); - continue; - }; - let cursor_surface = wmcompositer.create_surface(&qh, ()); - cursor_surface.attach(Some(&cursor_buffer), 0, 0); - // and create a surface. if two or more, - let (hotspot_x, hotspot_y) = cursor_buffer.hotspot(); - pointer.set_cursor( - serial, - Some(&cursor_surface), - hotspot_x as i32, - hotspot_y as i32, - ); - cursor_surface.commit(); - } - } - _ => {} - } - continue; - } - Ok(()) - } } fn get_cursor_buffer( diff --git a/sessionlockev/src/lib.rs b/sessionlockev/src/lib.rs index 37a9f42..c3a56d5 100644 --- a/sessionlockev/src/lib.rs +++ b/sessionlockev/src/lib.rs @@ -1005,8 +1005,30 @@ impl WindowState { /// /// Different with running, it receiver a receiver pub fn running_with_proxy( - &mut self, + self, message_receiver: std::sync::mpsc::Receiver, + event_handler: F, + ) -> Result<(), SessonLockEventError> + where + F: FnMut(SessionLockEvent, &mut WindowState, Option) -> ReturnData, + { + self.running_with_proxy_option(Some(message_receiver), event_handler) + } + /// main event loop, every time dispatch, it will store the messages, and do callback. it will + /// pass a LayerEvent, with self as mut, the last `Option` describe which unit the event + /// happened on, like tell you this time you do a click, what surface it is on. you can use the + /// index to get the unit, with [WindowState::get_unit] if the even is not spical on one surface, + /// it will return [None]. + pub fn running(self, event_handler: F) -> Result<(), SessonLockEventError> + where + F: FnMut(SessionLockEvent, &mut WindowState, Option) -> ReturnData, + { + self.running_with_proxy_option(None, event_handler) + } + + fn running_with_proxy_option( + mut self, + message_receiver: Option>, mut event_handler: F, ) -> Result<(), SessonLockEventError> where @@ -1026,12 +1048,16 @@ impl WindowState { while !matches!(init_event, Some(ReturnData::None)) { match init_event { None => { - init_event = Some(event_handler(SessionLockEvent::InitRequest, self, None)); + init_event = Some(event_handler( + SessionLockEvent::InitRequest, + &mut self, + None, + )); } Some(ReturnData::RequestBind) => { init_event = Some(event_handler( SessionLockEvent::BindProvide(&globals, &qh), - self, + &mut self, None, )); } @@ -1048,7 +1074,7 @@ impl WindowState { .expect("Failed to init Wayland Source"); 'out: loop { - event_loop.dispatch(Duration::from_millis(1), self)?; + event_loop.dispatch(Duration::from_millis(1), &mut self)?; let mut messages = Vec::new(); std::mem::swap(&mut messages, &mut self.message); for msg in messages.iter() { @@ -1061,7 +1087,7 @@ impl WindowState { SessionLockEvent::RequestBuffer( &mut file, &shm, &qh, *width, *height, ), - self, + &mut self, Some(index), ) else { panic!("You cannot return this one"); @@ -1077,7 +1103,7 @@ impl WindowState { height: *height, }, ), - self, + &mut self, Some(index), ); } @@ -1121,7 +1147,7 @@ impl WindowState { let msg: DispatchMessage = msg.clone().into(); match event_handler( SessionLockEvent::RequestMessages(&msg), - self, + &mut self, *index_message, ) { ReturnData::RequestUnlockAndExist => { @@ -1163,8 +1189,8 @@ impl WindowState { } } } - if let Ok(event) = message_receiver.try_recv() { - match event_handler(SessionLockEvent::UserEvent(event), self, None) { + if let Some(event) = message_receiver.as_ref().and_then(|rv| rv.try_recv().ok()) { + match event_handler(SessionLockEvent::UserEvent(event), &mut self, None) { ReturnData::RequestUnlockAndExist => { lock.unlock_and_destroy(); connection.roundtrip()?; @@ -1202,7 +1228,11 @@ impl WindowState { _ => {} } } - let mut return_data = vec![event_handler(SessionLockEvent::NormalDispatch, self, None)]; + let mut return_data = vec![event_handler( + SessionLockEvent::NormalDispatch, + &mut self, + None, + )]; loop { let mut replace_data = Vec::new(); for data in return_data { @@ -1217,7 +1247,7 @@ impl WindowState { height: unit.size.1, }, ), - self, + &mut self, Some(index), )); } @@ -1236,7 +1266,7 @@ impl WindowState { height: unit.size.1, }, ), - self, + &mut self, Some(*index), )); } @@ -1287,165 +1317,6 @@ impl WindowState { } Ok(()) } - /// main event loop, every time dispatch, it will store the messages, and do callback. it will - /// pass a LayerEvent, with self as mut, the last `Option` describe which unit the event - /// happened on, like tell you this time you do a click, what surface it is on. you can use the - /// index to get the unit, with [WindowState::get_unit] if the even is not spical on one surface, - /// it will return [None]. - pub fn running(&mut self, mut event_handler: F) -> Result<(), SessonLockEventError> - where - F: FnMut(SessionLockEvent, &mut WindowState, Option) -> ReturnData, - { - let globals = self.globals.take().unwrap(); - let mut event_queue = self.event_queue.take().unwrap(); - let qh = event_queue.handle(); - let wmcompositer = self.wl_compositor.take().unwrap(); - let shm = self.shm.take().unwrap(); - let fractional_scale_manager = self.fractional_scale_manager.take(); - let cursor_manager: Option = self.cursor_manager.take(); - let connection = self.connection.take().unwrap(); - let lock = self.lock.take().unwrap(); - let mut init_event = None; - - while !matches!(init_event, Some(ReturnData::None)) { - match init_event { - None => { - init_event = Some(event_handler(SessionLockEvent::InitRequest, self, None)); - } - Some(ReturnData::RequestBind) => { - init_event = Some(event_handler( - SessionLockEvent::BindProvide(&globals, &qh), - self, - None, - )); - } - _ => panic!("Not provide server here"), - } - } - - self.message.clear(); - 'out: loop { - event_queue.blocking_dispatch(self)?; - if self.message.is_empty() { - continue; - } - let mut messages = Vec::new(); - std::mem::swap(&mut messages, &mut self.message); - for msg in messages.iter() { - match msg { - (Some(unit_index), DispatchMessageInner::RefreshSurface { width, height }) => { - let index = *unit_index; - if self.units[index].buffer.is_none() { - let mut file = tempfile::tempfile()?; - let ReturnData::WlBuffer(buffer) = event_handler( - SessionLockEvent::RequestBuffer( - &mut file, &shm, &qh, *width, *height, - ), - self, - Some(index), - ) else { - panic!("You cannot return this one"); - }; - let surface = &self.units[index].wl_surface; - surface.attach(Some(&buffer), 0, 0); - self.units[index].buffer = Some(buffer); - } else { - event_handler( - SessionLockEvent::RequestMessages( - &DispatchMessage::RequestRefresh { - width: *width, - height: *height, - }, - ), - self, - Some(index), - ); - } - let surface = &self.units[index].wl_surface; - - surface.commit(); - } - (_, DispatchMessageInner::NewDisplay(display)) => { - let wl_surface = wmcompositer.create_surface(&qh, ()); // and create a surface. if two or more, - // - wl_surface.commit(); - let session_lock_surface = - lock.get_lock_surface(&wl_surface, display, &qh, ()); - - let mut fractional_scale = None; - if let Some(ref fractional_scale_manager) = fractional_scale_manager { - fractional_scale = Some(fractional_scale_manager.get_fractional_scale( - &wl_surface, - &qh, - (), - )); - } - // so during the init Configure of the shell, a buffer, atleast a buffer is needed. - // and if you need to reconfigure it, you need to commit the wl_surface again - // so because this is just an example, so we just commit it once - // like if you want to reset anchor or KeyboardInteractivity or resize, commit is needed - - self.units.push(WindowStateUnit { - id: id::Id::unique(), - display: connection.display(), - wl_surface, - size: (0, 0), - buffer: None, - session_shell: session_lock_surface, - fractional_scale, - binding: None, - }); - } - _ => { - let (index_message, msg) = msg; - let msg: DispatchMessage = msg.clone().into(); - match event_handler( - SessionLockEvent::RequestMessages(&msg), - self, - *index_message, - ) { - ReturnData::RequestUnlockAndExist => { - lock.unlock_and_destroy(); - event_queue.blocking_dispatch(self)?; - break 'out; - } - ReturnData::RequestSetCursorShape((shape_name, pointer, serial)) => { - if let Some(ref cursor_manager) = cursor_manager { - let Some(shape) = str_to_shape(&shape_name) else { - eprintln!("Not supported shape"); - continue; - }; - let device = cursor_manager.get_pointer(&pointer, &qh, ()); - device.set_shape(serial, shape); - device.destroy(); - } else { - let Some(cursor_buffer) = - get_cursor_buffer(&shape_name, &connection, &shm) - else { - eprintln!("Cannot find cursor {shape_name}"); - continue; - }; - let cursor_surface = wmcompositer.create_surface(&qh, ()); - cursor_surface.attach(Some(&cursor_buffer), 0, 0); - // and create a surface. if two or more, - let (hotspot_x, hotspot_y) = cursor_buffer.hotspot(); - pointer.set_cursor( - serial, - Some(&cursor_surface), - hotspot_x as i32, - hotspot_y as i32, - ); - cursor_surface.commit(); - } - } - _ => {} - } - } - } - } - } - Ok(()) - } } fn get_cursor_buffer(