274 lines
8.9 KiB
Rust
274 lines
8.9 KiB
Rust
pub fn open_popout_window(
|
|
app: >k::Application,
|
|
preview: &LauncherPreview,
|
|
state: &Rc<RefCell<LauncherState>>,
|
|
child_proc: &Rc<RefCell<Option<RelayChild>>>,
|
|
popouts: &Rc<RefCell<[Option<PopoutWindowHandle>; 2]>>,
|
|
widgets: &LauncherWidgets,
|
|
monitor_id: usize,
|
|
) {
|
|
let already_open = {
|
|
let popouts = popouts.borrow();
|
|
popouts[monitor_id].is_some()
|
|
};
|
|
if already_open {
|
|
return;
|
|
}
|
|
|
|
if let Some(binding) = widgets.display_panes[monitor_id]
|
|
.preview_binding
|
|
.borrow()
|
|
.as_ref()
|
|
{
|
|
binding.set_enabled(false);
|
|
}
|
|
|
|
let (breakout_size, breakout_limit) = {
|
|
let state = state.borrow();
|
|
(
|
|
state.breakout_size_choice(monitor_id),
|
|
state.breakout_display_size(),
|
|
)
|
|
};
|
|
let title = format!("Lesavka {}", widgets.display_panes[monitor_id].title);
|
|
let window = gtk::ApplicationWindow::builder()
|
|
.application(app)
|
|
.title(&title)
|
|
.default_width(breakout_size.width)
|
|
.default_height(breakout_size.height)
|
|
.build();
|
|
super::ui_components::install_css(&window);
|
|
super::ui_components::install_window_icon(&window);
|
|
super::ui_components::install_window_chrome(&window, &title);
|
|
window.set_resizable(false);
|
|
|
|
let picture = gtk::Picture::new();
|
|
picture.set_hexpand(true);
|
|
picture.set_vexpand(true);
|
|
picture.set_halign(gtk::Align::Fill);
|
|
picture.set_valign(gtk::Align::Fill);
|
|
picture.set_can_shrink(true);
|
|
picture.set_keep_aspect_ratio(true);
|
|
picture.set_size_request(breakout_size.width, breakout_size.height);
|
|
let root = gtk::Box::new(gtk::Orientation::Vertical, 0);
|
|
root.set_hexpand(true);
|
|
root.set_vexpand(true);
|
|
root.set_halign(gtk::Align::Fill);
|
|
root.set_valign(gtk::Align::Fill);
|
|
root.set_size_request(breakout_size.width, breakout_size.height);
|
|
let frame = gtk::AspectFrame::new(0.5, 0.5, 16.0 / 9.0, false);
|
|
frame.set_hexpand(true);
|
|
frame.set_vexpand(true);
|
|
frame.set_halign(gtk::Align::Fill);
|
|
frame.set_valign(gtk::Align::Fill);
|
|
frame.set_size_request(breakout_size.width, breakout_size.height);
|
|
frame.set_child(Some(&picture));
|
|
root.append(&frame);
|
|
|
|
let stream_status = gtk::Label::new(Some(""));
|
|
|
|
let binding = preview
|
|
.install_on_picture(monitor_id, PreviewSurface::Window, &picture, &stream_status)
|
|
.expect("preview binding for popout");
|
|
|
|
window.set_child(Some(&root));
|
|
install_popout_drag(&window, &picture);
|
|
apply_popout_window_geometry(&window, &root, &picture, breakout_size, breakout_limit);
|
|
|
|
let state_handle = Rc::clone(state);
|
|
let child_proc_handle = Rc::clone(child_proc);
|
|
let popouts_handle = Rc::clone(popouts);
|
|
let widgets_handle = widgets.clone();
|
|
let close_binding = binding.clone();
|
|
window.connect_close_request(move |_| {
|
|
let handle = {
|
|
let mut popouts = popouts_handle.borrow_mut();
|
|
popouts[monitor_id].take()
|
|
};
|
|
if let Some(handle) = handle {
|
|
handle.binding.close();
|
|
if let Some(preview_binding) = widgets_handle.display_panes[monitor_id]
|
|
.preview_binding
|
|
.borrow()
|
|
.as_ref()
|
|
{
|
|
preview_binding.set_enabled(true);
|
|
}
|
|
{
|
|
let mut state = state_handle.borrow_mut();
|
|
state.set_display_surface(monitor_id, DisplaySurface::Preview);
|
|
}
|
|
let child_running = child_proc_handle.borrow().is_some();
|
|
let state_snapshot = state_handle.borrow().clone();
|
|
refresh_launcher_ui(&widgets_handle, &state_snapshot, child_running);
|
|
} else {
|
|
close_binding.close();
|
|
}
|
|
glib::Propagation::Proceed
|
|
});
|
|
|
|
{
|
|
let mut state = state.borrow_mut();
|
|
state.set_display_surface(monitor_id, DisplaySurface::Window);
|
|
}
|
|
{
|
|
let mut popouts = popouts.borrow_mut();
|
|
popouts[monitor_id] = Some(PopoutWindowHandle {
|
|
window: window.clone(),
|
|
root: root.clone(),
|
|
frame: frame.clone(),
|
|
picture: picture.clone(),
|
|
status_label: stream_status.clone(),
|
|
binding,
|
|
});
|
|
}
|
|
let child_running = child_proc.borrow().is_some();
|
|
let state_snapshot = state.borrow().clone();
|
|
refresh_launcher_ui(widgets, &state_snapshot, child_running);
|
|
window.present();
|
|
schedule_popout_window_geometry(
|
|
window.clone(),
|
|
root.clone(),
|
|
picture.clone(),
|
|
breakout_size,
|
|
breakout_limit,
|
|
);
|
|
}
|
|
|
|
pub fn apply_popout_window_size(
|
|
handle: &PopoutWindowHandle,
|
|
size: BreakoutSizeChoice,
|
|
display_limit: super::state::PreviewSourceSize,
|
|
) {
|
|
handle.frame.set_size_request(size.width, size.height);
|
|
apply_popout_window_geometry(
|
|
&handle.window,
|
|
&handle.root,
|
|
&handle.picture,
|
|
size,
|
|
display_limit,
|
|
);
|
|
handle.window.present();
|
|
schedule_popout_window_geometry(
|
|
handle.window.clone(),
|
|
handle.root.clone(),
|
|
handle.picture.clone(),
|
|
size,
|
|
display_limit,
|
|
);
|
|
}
|
|
|
|
pub fn dock_display_to_preview(
|
|
state: &Rc<RefCell<LauncherState>>,
|
|
child_proc: &Rc<RefCell<Option<RelayChild>>>,
|
|
popouts: &Rc<RefCell<[Option<PopoutWindowHandle>; 2]>>,
|
|
widgets: &LauncherWidgets,
|
|
monitor_id: usize,
|
|
) {
|
|
let handle = {
|
|
let mut popouts = popouts.borrow_mut();
|
|
popouts[monitor_id].take()
|
|
};
|
|
if let Some(handle) = handle {
|
|
handle.binding.close();
|
|
handle.window.close();
|
|
}
|
|
if let Some(binding) = widgets.display_panes[monitor_id]
|
|
.preview_binding
|
|
.borrow()
|
|
.as_ref()
|
|
{
|
|
binding.set_enabled(true);
|
|
}
|
|
{
|
|
let mut state = state.borrow_mut();
|
|
state.set_display_surface(monitor_id, DisplaySurface::Preview);
|
|
}
|
|
let child_running = child_proc.borrow().is_some();
|
|
if !child_running {
|
|
let pane = &widgets.display_panes[monitor_id];
|
|
pane.picture.set_paintable(Option::<&gdk::Paintable>::None);
|
|
pane.preview_placeholder.set_visible(true);
|
|
pane.stream_status.set_text("Connect relay to preview.");
|
|
}
|
|
let state_snapshot = state.borrow().clone();
|
|
refresh_launcher_ui(widgets, &state_snapshot, child_running);
|
|
}
|
|
|
|
pub fn dock_all_displays_to_preview(
|
|
state: &Rc<RefCell<LauncherState>>,
|
|
child_proc: &Rc<RefCell<Option<RelayChild>>>,
|
|
popouts: &Rc<RefCell<[Option<PopoutWindowHandle>; 2]>>,
|
|
widgets: &LauncherWidgets,
|
|
) {
|
|
let mut handles = Vec::new();
|
|
{
|
|
let mut popouts = popouts.borrow_mut();
|
|
for monitor_id in 0..2 {
|
|
if let Some(handle) = popouts[monitor_id].take() {
|
|
handles.push(handle);
|
|
}
|
|
}
|
|
}
|
|
for handle in handles {
|
|
handle.binding.close();
|
|
handle.window.close();
|
|
}
|
|
|
|
for monitor_id in 0..2 {
|
|
if let Some(binding) = widgets.display_panes[monitor_id]
|
|
.preview_binding
|
|
.borrow()
|
|
.as_ref()
|
|
{
|
|
binding.set_enabled(true);
|
|
}
|
|
}
|
|
|
|
{
|
|
let mut state = state.borrow_mut();
|
|
for monitor_id in 0..2 {
|
|
state.set_display_surface(monitor_id, DisplaySurface::Preview);
|
|
}
|
|
}
|
|
|
|
let child_running = child_proc.borrow().is_some();
|
|
if !child_running {
|
|
for pane in &widgets.display_panes {
|
|
pane.picture.set_paintable(Option::<&gdk::Paintable>::None);
|
|
pane.preview_placeholder.set_visible(true);
|
|
pane.stream_status.set_text("Connect relay to preview.");
|
|
}
|
|
}
|
|
let state_snapshot = state.borrow().clone();
|
|
refresh_launcher_ui(widgets, &state_snapshot, child_running);
|
|
}
|
|
|
|
pub fn refresh_display_pane(pane: &DisplayPaneWidgets, surface: DisplaySurface) {
|
|
if let Some(binding) = pane.preview_binding.borrow().as_ref() {
|
|
binding.set_enabled(matches!(surface, DisplaySurface::Preview));
|
|
}
|
|
let preview_ready = pane.preview_binding.borrow().is_some();
|
|
pane.action_button.set_sensitive(preview_ready);
|
|
pane.clip_button.set_sensitive(preview_ready);
|
|
pane.record_button.set_sensitive(preview_ready);
|
|
pane.save_button.set_sensitive(true);
|
|
match surface {
|
|
DisplaySurface::Preview => {
|
|
pane.stack.set_visible_child_name("preview");
|
|
pane.action_button.set_label("Break Out");
|
|
pane.preview_placeholder
|
|
.set_visible(pane.picture.paintable().is_none());
|
|
if pane.preview_binding.borrow().is_none() {
|
|
pane.stream_status.set_text("Preview unavailable");
|
|
}
|
|
}
|
|
DisplaySurface::Window => {
|
|
pane.stack.set_visible_child_name("placeholder");
|
|
pane.action_button.set_label("Return");
|
|
pane.stream_status.set_text("Streaming in its own window");
|
|
pane.preview_placeholder.set_visible(false);
|
|
}
|
|
}
|
|
}
|