Skip to content

Commit b795cd8

Browse files
committed
bugfix(applications): Ensure launch waits for long processes like lutris
1 parent 060f780 commit b795cd8

3 files changed

Lines changed: 82 additions & 56 deletions

File tree

oxirun/src/main.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -353,10 +353,14 @@ impl OxiRun {
353353
}) => match key {
354354
Named::Escape => Some(Message::Exit),
355355
Named::Enter => Some(Message::LaunchFocusedEntry),
356-
Named::Tab => match modifier {
357-
Modifiers::SHIFT => Some(Message::MoveApplicationFocus(FocusDirection::Up)),
358-
_ => Some(Message::MoveApplicationFocus(FocusDirection::Down)),
359-
},
356+
Named::ArrowUp => Some(Message::MoveApplicationFocus(FocusDirection::Up)),
357+
Named::Tab if modifier == Modifiers::SHIFT => {
358+
Some(Message::MoveApplicationFocus(FocusDirection::Up))
359+
}
360+
Named::ArrowDown => Some(Message::MoveApplicationFocus(FocusDirection::Down)),
361+
Named::Tab if modifier == Modifiers::empty() => {
362+
Some(Message::MoveApplicationFocus(FocusDirection::Down))
363+
}
360364
_ => None,
361365
},
362366
_ => Some(Message::FocusSearch),

oxirun/src/plugins.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
use std::{cell::RefCell, sync::Arc};
1+
use std::sync::{Arc, RwLock};
22

33
use iced::{Element, Task};
44
use libloading::Library;
55
use oxiced::any_send::OxiAny;
66
use toml::Table;
77

8-
pub type PluginModel = Arc<RefCell<&'static mut dyn OxiAny>>;
8+
pub type PluginModel = Arc<RwLock<&'static mut dyn OxiAny>>;
99
pub type PluginMsg = Arc<&'static mut dyn OxiAny>;
1010

1111
#[allow(improper_ctypes_definitions)]
@@ -58,7 +58,7 @@ pub fn load_plugin(lib: &'static Library) -> Option<PluginFuncs> {
5858
libloading::Symbol<
5959
unsafe extern "C" fn(
6060
filter_text: String,
61-
model: Arc<RefCell<&mut dyn OxiAny>>,
61+
model: Arc<RwLock<&mut dyn OxiAny>>,
6262
msg: PluginMsg,
6363
) -> Option<Task<PluginMsg>>,
6464
>,

plugins/applications/src/lib.rs

Lines changed: 71 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
use std::{
2-
cell::RefCell,
32
collections::HashMap,
43
env,
54
fmt::Debug,
65
fs::{self, DirEntry},
76
io::BufRead,
87
path::PathBuf,
98
process::Command,
10-
sync::Arc,
9+
sync::{Arc, RwLock},
1110
};
1211

1312
use config::{Config, get_config};
@@ -153,7 +152,7 @@ fn read_single_entry(
153152
if first_line != "[Desktop Entry]" && !first_line.starts_with("#") {
154153
return;
155154
}
156-
for line in iter.flatten() {
155+
for line in iter.map_while(Result::ok) {
157156
if line.starts_with("[Desktop Action") {
158157
break;
159158
}
@@ -352,7 +351,11 @@ pub async fn to_oxiany_async(msg: Message) -> Arc<dyn OxiAny> {
352351
}
353352

354353
pub fn run_command(command: &str) {
355-
let res = Command::new("sh").arg("-c").arg(command).spawn();
354+
let res = Command::new("sh")
355+
.arg("-c")
356+
.arg(format!("nohup {command} >/dev/null 2>&1 &"))
357+
.spawn();
358+
356359
if let Err(error) = res {
357360
panic!("Failed to spawn command: {error}");
358361
}
@@ -363,7 +366,7 @@ pub fn run_command(command: &str) {
363366
pub extern "C" fn model(
364367
global_config: Table,
365368
) -> (
366-
Arc<RefCell<&'static mut dyn OxiAny>>,
369+
Arc<RwLock<&'static mut dyn OxiAny>>,
367370
Option<Task<Arc<dyn OxiAny>>>,
368371
) {
369372
let model = Box::leak(Box::new(Model::new(global_config)));
@@ -377,7 +380,7 @@ pub extern "C" fn model(
377380

378381
// TODO get config from main app perhaps? if so how? this should only take subkeys
379382
(
380-
Arc::new(RefCell::new(model as &'static mut dyn OxiAny)),
383+
Arc::new(RwLock::new(model as &'static mut dyn OxiAny)),
381384
Some(Task::future(to_oxiany_async(entries))),
382385
)
383386
}
@@ -386,10 +389,10 @@ pub extern "C" fn model(
386389
#[allow(improper_ctypes_definitions)]
387390
pub extern "C" fn update(
388391
filter_text: String,
389-
model: Arc<RefCell<&'static mut dyn OxiAny>>,
392+
model: Arc<RwLock<&'static mut dyn OxiAny>>,
390393
msg: Arc<&'static mut dyn OxiAny>,
391394
) -> Option<Task<Arc<dyn OxiAny>>> {
392-
let mut model_borrow = model.borrow_mut();
395+
let mut model_borrow = model.try_write().ok()?;
393396
let model = model_borrow.downcast_mut::<Model>()?;
394397
let msg_opt = msg.downcast_ref::<Message>();
395398
if msg_opt.is_none() {
@@ -420,9 +423,9 @@ pub extern "C" fn update(
420423
#[allow(improper_ctypes_definitions)]
421424
pub extern "C" fn sort(
422425
filter_text: String,
423-
model: Arc<RefCell<&'static mut dyn OxiAny>>,
426+
model: Arc<RwLock<&'static mut dyn OxiAny>>,
424427
) -> Option<Task<Arc<dyn OxiAny>>> {
425-
let mut model_borrow = model.borrow_mut();
428+
let mut model_borrow = model.try_write().ok()?;
426429
let model = model_borrow.downcast_mut::<Model>()?;
427430
let applications = model.applications.clone();
428431
Some(Task::future(to_oxiany_async(sort_appliations(
@@ -436,46 +439,57 @@ pub extern "C" fn sort(
436439
#[allow(improper_ctypes_definitions)]
437440
pub extern "C" fn launch(
438441
focused_index: usize,
439-
model: Arc<RefCell<&'static mut dyn OxiAny>>,
442+
model: Arc<RwLock<&'static mut dyn OxiAny>>,
440443
) -> Option<Task<&'static dyn OxiAny>> {
441-
let mut model_borrow = model.borrow_mut();
442-
let model = model_borrow.downcast_mut::<Model>()?;
443-
let exec_opt = &model.sorted_applications.get(focused_index);
444-
if exec_opt.is_none() {
445-
model.errors.push("Could not get entry for index".into());
446-
return None;
444+
let lock = model.try_write();
445+
if let Ok(mut model_borrow) = lock {
446+
let model_opt = model_borrow.downcast_mut::<Model>();
447+
if let Some(model) = model_opt {
448+
let exec_opt = &model.sorted_applications.get(focused_index);
449+
if exec_opt.is_none() {
450+
model.errors.push("Could not get entry for index".into());
451+
return None;
452+
}
453+
let exec = &exec_opt.unwrap().entry.exec;
454+
run_command(exec);
455+
}
447456
}
448-
let exec = &exec_opt.unwrap().entry.exec;
449-
run_command(exec);
450457
None
451458
}
452459

453460
#[unsafe(no_mangle)]
454461
#[allow(improper_ctypes_definitions)]
455462
pub extern "C" fn view(
456-
model: Arc<RefCell<&'static mut dyn OxiAny>>,
463+
model: Arc<RwLock<&'static mut dyn OxiAny>>,
457464
) -> Result<Vec<(i64, Element<'static, Arc<dyn OxiAny>>)>, std::io::Error> {
458-
let model_borrow = model.borrow();
459-
let model = model_borrow
460-
.downcast_ref::<Model>()
461-
.ok_or(std::io::Error::new(
465+
let lock = model.try_read();
466+
if let Ok(model_borrow) = lock {
467+
let model = model_borrow
468+
.downcast_ref::<Model>()
469+
.ok_or(std::io::Error::new(
470+
std::io::ErrorKind::InvalidInput,
471+
"Could not get model in view",
472+
))?;
473+
let entries: Vec<(i64, Element<Arc<dyn OxiAny>>)> = model
474+
.sorted_applications
475+
.clone()
476+
.into_iter()
477+
.take(model.config.max_entries)
478+
.map(|scored_entry| {
479+
(
480+
scored_entry.score,
481+
Into::<Element<Message>>::into(create_entry_card(scored_entry.entry))
482+
.map(to_oxiany_rc),
483+
)
484+
})
485+
.collect::<Vec<_>>();
486+
Ok(entries)
487+
} else {
488+
Err(std::io::Error::new(
462489
std::io::ErrorKind::InvalidInput,
463490
"Could not get model in view",
464-
))?;
465-
let entries: Vec<(i64, Element<Arc<dyn OxiAny>>)> = model
466-
.sorted_applications
467-
.clone()
468-
.into_iter()
469-
.take(model.config.max_entries)
470-
.map(|scored_entry| {
471-
(
472-
scored_entry.score,
473-
Into::<Element<Message>>::into(create_entry_card(scored_entry.entry))
474-
.map(to_oxiany_rc),
475-
)
476-
})
477-
.collect::<Vec<_>>();
478-
Ok(entries)
491+
))
492+
}
479493
}
480494

481495
#[unsafe(no_mangle)]
@@ -486,23 +500,31 @@ pub extern "C" fn name() -> &'static str {
486500

487501
#[unsafe(no_mangle)]
488502
#[allow(improper_ctypes_definitions)]
489-
pub extern "C" fn errors(model: Arc<RefCell<&'static mut dyn OxiAny>>) -> Vec<String> {
490-
let model_borrow = model.borrow();
491-
let model_opt = model_borrow.downcast_ref::<Model>();
492-
if let Some(model) = model_opt {
493-
model.errors.clone()
503+
pub extern "C" fn errors(model: Arc<RwLock<&'static mut dyn OxiAny>>) -> Vec<String> {
504+
let lock = model.try_read();
505+
if let Ok(model_borrow) = lock {
506+
let model_opt = model_borrow.downcast_ref::<Model>();
507+
if let Some(model) = model_opt {
508+
model.errors.clone()
509+
} else {
510+
vec![String::from("Could not get model while fetching errors")]
511+
}
494512
} else {
495513
vec![String::from("Could not get model while fetching errors")]
496514
}
497515
}
498516

499517
#[unsafe(no_mangle)]
500518
#[allow(improper_ctypes_definitions)]
501-
pub extern "C" fn count(model: Arc<RefCell<&'static mut dyn OxiAny>>) -> usize {
502-
let model_borrow = model.borrow();
503-
let model_opt = model_borrow.downcast_ref::<Model>();
504-
if let Some(model) = model_opt {
505-
usize::min(model.sorted_applications.len(), model.config.max_entries)
519+
pub extern "C" fn count(model: Arc<RwLock<&'static mut dyn OxiAny>>) -> usize {
520+
let lock = model.try_read();
521+
if let Ok(model_borrow) = lock {
522+
let model_opt = model_borrow.downcast_ref::<Model>();
523+
if let Some(model) = model_opt {
524+
usize::min(model.sorted_applications.len(), model.config.max_entries)
525+
} else {
526+
0
527+
}
506528
} else {
507529
0
508530
}

0 commit comments

Comments
 (0)