example: Fix to hide WebView when switch tab. (#764)
fixes #763 it also prevent crashing on linux due to gtk not initialized --------- Co-authored-by: Jason Lee <huacnlee@gmail.com>
This commit is contained in:
parent
99e7f8ee70
commit
4f0617e96f
5 changed files with 92 additions and 13 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -6257,6 +6257,7 @@ dependencies = [
|
|||
"fake",
|
||||
"gpui",
|
||||
"gpui-component",
|
||||
"gtk",
|
||||
"rand 0.8.5",
|
||||
"raw-window-handle",
|
||||
"regex",
|
||||
|
|
|
|||
|
|
@ -20,5 +20,8 @@ serde = "1"
|
|||
serde_json = "1"
|
||||
unindent = "0.2.3"
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
gtk = { version = "0.18" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
|
|||
|
|
@ -209,6 +209,7 @@ pub fn init(cx: &mut App) {
|
|||
input_story::init(cx);
|
||||
dropdown_story::init(cx);
|
||||
popup_story::init(cx);
|
||||
webview_story::init(cx);
|
||||
|
||||
let http_client = std::sync::Arc::new(
|
||||
reqwest_client::ReqwestClient::user_agent("gpui-component/story").unwrap(),
|
||||
|
|
@ -226,9 +227,11 @@ pub fn init(cx: &mut App) {
|
|||
};
|
||||
|
||||
let view = cx.new(|cx| {
|
||||
let (title, description, closable, zoomable, story) = story_state.to_story(window, cx);
|
||||
let mut container =
|
||||
StoryContainer::new(window, cx).story(story, story_state.story_klass);
|
||||
let (title, description, closable, zoomable, story, on_active) =
|
||||
story_state.to_story(window, cx);
|
||||
let mut container = StoryContainer::new(window, cx)
|
||||
.story(story, story_state.story_klass)
|
||||
.on_active(on_active);
|
||||
|
||||
cx.on_focus_in(
|
||||
&container.focus_handle,
|
||||
|
|
@ -279,6 +282,7 @@ pub struct StoryContainer {
|
|||
story_klass: Option<SharedString>,
|
||||
closable: bool,
|
||||
zoomable: Option<PanelControl>,
|
||||
on_active: Option<fn(AnyView, bool, &mut Window, &mut App)>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -305,6 +309,22 @@ pub trait Story: Focusable + Render {
|
|||
None
|
||||
}
|
||||
fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render + Focusable>;
|
||||
|
||||
fn on_active(&mut self, active: bool, window: &mut Window, cx: &mut App) {
|
||||
let _ = active;
|
||||
let _ = window;
|
||||
let _ = cx;
|
||||
}
|
||||
fn on_active_any(view: AnyView, active: bool, window: &mut Window, cx: &mut App)
|
||||
where
|
||||
Self: 'static,
|
||||
{
|
||||
if let Some(story) = view.downcast::<Self>().ok() {
|
||||
cx.update_entity(&story, |story, cx| {
|
||||
story.on_active(active, window, cx);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<ContainerEvent> for StoryContainer {}
|
||||
|
|
@ -324,6 +344,7 @@ impl StoryContainer {
|
|||
story_klass: None,
|
||||
closable: true,
|
||||
zoomable: Some(PanelControl::default()),
|
||||
on_active: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -335,7 +356,9 @@ impl StoryContainer {
|
|||
let focus_handle = story.focus_handle(cx);
|
||||
|
||||
let view = cx.new(|cx| {
|
||||
let mut story = Self::new(window, cx).story(story.into(), story_klass);
|
||||
let mut story = Self::new(window, cx)
|
||||
.story(story.into(), story_klass)
|
||||
.on_active(S::on_active_any);
|
||||
story.focus_handle = focus_handle;
|
||||
story.closable = S::closable();
|
||||
story.zoomable = S::zoomable();
|
||||
|
|
@ -363,6 +386,10 @@ impl StoryContainer {
|
|||
self.story_klass = Some(story_klass.into());
|
||||
self
|
||||
}
|
||||
pub fn on_active(mut self, on_active: fn(AnyView, bool, &mut Window, &mut App)) -> Self {
|
||||
self.on_active = Some(on_active);
|
||||
self
|
||||
}
|
||||
|
||||
fn on_action_panel_info(
|
||||
&mut self,
|
||||
|
|
@ -420,6 +447,7 @@ impl StoryState {
|
|||
bool,
|
||||
Option<PanelControl>,
|
||||
AnyView,
|
||||
fn(AnyView, bool, &mut Window, &mut App),
|
||||
) {
|
||||
macro_rules! story {
|
||||
($klass:tt) => {
|
||||
|
|
@ -429,6 +457,7 @@ impl StoryState {
|
|||
$klass::closable(),
|
||||
$klass::zoomable(),
|
||||
$klass::view(window, cx).into(),
|
||||
$klass::on_active_any,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
|
@ -500,8 +529,13 @@ impl Panel for StoryContainer {
|
|||
println!("panel: {} zoomed: {}", self.name, zoomed);
|
||||
}
|
||||
|
||||
fn set_active(&mut self, active: bool, _window: &mut Window, _cx: &mut App) {
|
||||
fn set_active(&mut self, active: bool, _window: &mut Window, cx: &mut App) {
|
||||
println!("panel: {} active: {}", self.name, active);
|
||||
if let Some(on_active) = self.on_active {
|
||||
if let Some(story) = self.story.clone() {
|
||||
on_active(story, active, _window, cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn popup_menu(&self, menu: PopupMenu, _window: &Window, _cx: &App) -> PopupMenu {
|
||||
|
|
|
|||
|
|
@ -4,15 +4,18 @@ use gpui_component::{
|
|||
button::{Button, ButtonVariants as _},
|
||||
dock::{DockArea, DockAreaState, DockEvent, DockItem, DockPlacement},
|
||||
popup_menu::PopupMenuExt,
|
||||
IconName, Root, Sizable, Theme, TitleBar,
|
||||
IconName, Root, Sizable,
|
||||
};
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
use gpui_component::{Theme, TitleBar};
|
||||
|
||||
use serde::Deserialize;
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use story::{
|
||||
AccordionStory, AppState, AppTitleBar, Assets, ButtonStory, CalendarStory, DropdownStory,
|
||||
FormStory, IconStory, ImageStory, InputStory, ListStory, ModalStory, Open, PopupStory,
|
||||
ProgressStory, Quit, ResizableStory, ScrollableStory, SidebarStory, StoryContainer,
|
||||
SwitchStory, TableStory, TextStory, TooltipStory,
|
||||
SwitchStory, TableStory, TextStory, TooltipStory, WebViewStory,
|
||||
};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Deserialize)]
|
||||
|
|
@ -365,7 +368,7 @@ impl StoryWorkspace {
|
|||
Arc::new(StoryContainer::panel::<AccordionStory>(window, cx)),
|
||||
Arc::new(StoryContainer::panel::<SidebarStory>(window, cx)),
|
||||
Arc::new(StoryContainer::panel::<FormStory>(window, cx)),
|
||||
// Arc::new(StoryContainer::panel::<WebViewStory>(window, cx)),
|
||||
Arc::new(StoryContainer::panel::<WebViewStory>(window, cx)),
|
||||
],
|
||||
None,
|
||||
&dock_area,
|
||||
|
|
@ -452,7 +455,7 @@ impl StoryWorkspace {
|
|||
14 => Arc::new(StoryContainer::panel::<ResizableStory>(window, cx)),
|
||||
15 => Arc::new(StoryContainer::panel::<ScrollableStory>(window, cx)),
|
||||
16 => Arc::new(StoryContainer::panel::<AccordionStory>(window, cx)),
|
||||
// 17 => Arc::new(StoryContainer::panel::<WebViewStory>(window, cx)),
|
||||
17 => Arc::new(StoryContainer::panel::<WebViewStory>(window, cx)),
|
||||
_ => Arc::new(StoryContainer::panel::<ButtonStory>(window, cx)),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,11 @@ use gpui_component::{
|
|||
webview::WebView,
|
||||
wry, ActiveTheme,
|
||||
};
|
||||
use raw_window_handle::HasWindowHandle;
|
||||
|
||||
pub fn init(_: &mut App) {
|
||||
#[cfg(target_os = "linux")]
|
||||
gtk::init().unwrap();
|
||||
}
|
||||
|
||||
pub struct WebViewStory {
|
||||
focus_handle: FocusHandle,
|
||||
|
|
@ -25,6 +29,13 @@ impl super::Story for WebViewStory {
|
|||
fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render + Focusable> {
|
||||
Self::view(window, cx)
|
||||
}
|
||||
fn on_active(&mut self, active: bool, _window: &mut Window, cx: &mut App) {
|
||||
if active {
|
||||
self.webview.update(cx, |webview, _| webview.show());
|
||||
} else {
|
||||
self.webview.update(cx, |webview, _| webview.hide());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WebViewStory {
|
||||
|
|
@ -32,9 +43,36 @@ impl WebViewStory {
|
|||
let focus_handle = cx.focus_handle();
|
||||
|
||||
let webview = cx.new(|cx| {
|
||||
let webview = wry::WebViewBuilder::new()
|
||||
.build_as_child(&window.window_handle().expect("No window handle"))
|
||||
.unwrap();
|
||||
let builder = wry::WebViewBuilder::new();
|
||||
#[cfg(not(any(
|
||||
target_os = "windows",
|
||||
target_os = "macos",
|
||||
target_os = "ios",
|
||||
target_os = "android"
|
||||
)))]
|
||||
let webview = {
|
||||
use gtk::prelude::*;
|
||||
use wry::WebViewBuilderExtUnix;
|
||||
// borrowed from https://github.com/tauri-apps/wry/blob/dev/examples/gtk_multiwebview.rs
|
||||
// doesn't work yet
|
||||
// TODO: How to initialize this fixed?
|
||||
let fixed = gtk::Fixed::builder().build();
|
||||
fixed.show_all();
|
||||
builder.build_gtk(&fixed).unwrap()
|
||||
};
|
||||
#[cfg(any(
|
||||
target_os = "windows",
|
||||
target_os = "macos",
|
||||
target_os = "ios",
|
||||
target_os = "android"
|
||||
))]
|
||||
let webview = {
|
||||
use raw_window_handle::HasWindowHandle;
|
||||
|
||||
let window_handle = window.window_handle().expect("No window handle");
|
||||
builder.build_as_child(&window_handle).unwrap()
|
||||
};
|
||||
|
||||
WebView::new(webview, window, cx)
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue