@@ -363,14 +363,15 @@ impl<T: UserEvent> Context<T> {
363363 self ,
364364 Message :: CreateWebview (
365365 window_id,
366- Box :: new ( move |window| {
366+ Box :: new ( move |window, options | {
367367 create_webview (
368368 WebviewKind :: WindowChild ,
369369 window,
370370 window_id_wrapper_,
371371 webview_id,
372372 & context,
373373 pending,
374+ options. focused_webview ,
374375 )
375376 } ) ,
376377 ) ,
@@ -485,6 +486,59 @@ impl TryFrom<Icon<'_>> for TaoIcon {
485486pub struct WindowEventWrapper ( pub Option < WindowEvent > ) ;
486487
487488impl WindowEventWrapper {
489+ fn map_from_tao (
490+ event : & TaoWindowEvent < ' _ > ,
491+ #[ allow( unused_variables) ] window : & WindowWrapper ,
492+ ) -> Self {
493+ let event = match event {
494+ TaoWindowEvent :: Resized ( size) => WindowEvent :: Resized ( PhysicalSizeWrapper ( * size) . into ( ) ) ,
495+ TaoWindowEvent :: Moved ( position) => {
496+ WindowEvent :: Moved ( PhysicalPositionWrapper ( * position) . into ( ) )
497+ }
498+ TaoWindowEvent :: Destroyed => WindowEvent :: Destroyed ,
499+ TaoWindowEvent :: ScaleFactorChanged {
500+ scale_factor,
501+ new_inner_size,
502+ } => WindowEvent :: ScaleFactorChanged {
503+ scale_factor : * scale_factor,
504+ new_inner_size : PhysicalSizeWrapper ( * * new_inner_size) . into ( ) ,
505+ } ,
506+ TaoWindowEvent :: Focused ( focused) => {
507+ #[ cfg( not( windows) ) ]
508+ return Self ( Some ( WindowEvent :: Focused ( * focused) ) ) ;
509+ // on multiwebview mode, if there's no focused webview, it means we're receiving a direct window focus change
510+ // (without receiving a webview focus, such as when clicking the taskbar app icon or using Alt + Tab)
511+ // in this case we must send the focus change event here
512+ #[ cfg( windows) ]
513+ if window. has_children . load ( Ordering :: Relaxed ) {
514+ const FOCUSED_WEBVIEW_MARKER : & str = "__tauriWindow?" ;
515+ let mut focused_webview = window. focused_webview . lock ( ) . unwrap ( ) ;
516+ // when we focus a webview and the window was previously focused, we get a blur event here
517+ // so on blur we should only send events if the current focus is owned by the window
518+ if !* focused
519+ && focused_webview
520+ . as_deref ( )
521+ . map_or ( false , |w| w != FOCUSED_WEBVIEW_MARKER )
522+ {
523+ return Self ( None ) ;
524+ }
525+
526+ // reset focused_webview on blur, or set to a dummy value on focus
527+ // (to prevent double focus event when we click a webview after focusing a window)
528+ * focused_webview = ( * focused) . then ( || FOCUSED_WEBVIEW_MARKER . to_string ( ) ) ;
529+
530+ return Self ( Some ( WindowEvent :: Focused ( * focused) ) ) ;
531+ } else {
532+ // when not on multiwebview mode, we handle focus change events on the webview (add_GotFocus and add_LostFocus)
533+ return Self ( None ) ;
534+ }
535+ }
536+ TaoWindowEvent :: ThemeChanged ( theme) => WindowEvent :: ThemeChanged ( map_theme ( theme) ) ,
537+ _ => return Self ( None ) ,
538+ } ;
539+ Self ( Some ( event) )
540+ }
541+
488542 fn parse ( window : & WindowWrapper , event : & TaoWindowEvent < ' _ > ) -> Self {
489543 match event {
490544 // resized event from tao doesn't include a reliable size on macOS
@@ -501,7 +555,7 @@ impl WindowEventWrapper {
501555 Self ( None )
502556 }
503557 }
504- e => e . into ( ) ,
558+ e => Self :: map_from_tao ( e , window ) ,
505559 }
506560 }
507561}
@@ -524,30 +578,6 @@ fn tao_activation_policy(activation_policy: ActivationPolicy) -> TaoActivationPo
524578 }
525579}
526580
527- impl < ' a > From < & TaoWindowEvent < ' a > > for WindowEventWrapper {
528- fn from ( event : & TaoWindowEvent < ' a > ) -> Self {
529- let event = match event {
530- TaoWindowEvent :: Resized ( size) => WindowEvent :: Resized ( PhysicalSizeWrapper ( * size) . into ( ) ) ,
531- TaoWindowEvent :: Moved ( position) => {
532- WindowEvent :: Moved ( PhysicalPositionWrapper ( * position) . into ( ) )
533- }
534- TaoWindowEvent :: Destroyed => WindowEvent :: Destroyed ,
535- TaoWindowEvent :: ScaleFactorChanged {
536- scale_factor,
537- new_inner_size,
538- } => WindowEvent :: ScaleFactorChanged {
539- scale_factor : * scale_factor,
540- new_inner_size : PhysicalSizeWrapper ( * * new_inner_size) . into ( ) ,
541- } ,
542- #[ cfg( any( target_os = "linux" , target_os = "macos" ) ) ]
543- TaoWindowEvent :: Focused ( focused) => WindowEvent :: Focused ( * focused) ,
544- TaoWindowEvent :: ThemeChanged ( theme) => WindowEvent :: ThemeChanged ( map_theme ( theme) ) ,
545- _ => return Self ( None ) ,
546- } ;
547- Self ( Some ( event) )
548- }
549- }
550-
551581pub struct MonitorHandleWrapper ( pub MonitorHandle ) ;
552582
553583impl From < MonitorHandleWrapper > for Monitor {
@@ -1402,7 +1432,12 @@ pub enum EventLoopWindowTargetMessage {
14021432pub type CreateWindowClosure < T > =
14031433 Box < dyn FnOnce ( & EventLoopWindowTarget < Message < T > > ) -> Result < WindowWrapper > + Send > ;
14041434
1405- pub type CreateWebviewClosure = Box < dyn FnOnce ( & Window ) -> Result < WebviewWrapper > + Send > ;
1435+ pub type CreateWebviewClosure =
1436+ Box < dyn FnOnce ( & Window , CreateWebviewOptions ) -> Result < WebviewWrapper > + Send > ;
1437+
1438+ pub struct CreateWebviewOptions {
1439+ pub focused_webview : Arc < Mutex < Option < String > > > ,
1440+ }
14061441
14071442pub enum Message < T : ' static > {
14081443 Task ( Box < dyn FnOnce ( ) + Send > ) ,
@@ -2349,6 +2384,7 @@ pub struct WindowWrapper {
23492384 is_window_transparent : bool ,
23502385 #[ cfg( windows) ]
23512386 surface : Option < softbuffer:: Surface < Arc < Window > , Arc < Window > > > ,
2387+ focused_webview : Arc < Mutex < Option < String > > > ,
23522388}
23532389
23542390impl fmt:: Debug for WindowWrapper {
@@ -2805,8 +2841,8 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
28052841 . 0
28062842 . borrow ( )
28072843 . get ( & window_id)
2808- . and_then ( |w| w. inner . clone ( ) ) ;
2809- if let Some ( window) = window {
2844+ . map ( |w| ( w. inner . clone ( ) , w . focused_webview . clone ( ) ) ) ;
2845+ if let Some ( ( Some ( window) , focused_webview ) ) = window {
28102846 let window_id_wrapper = Arc :: new ( Mutex :: new ( window_id) ) ;
28112847
28122848 let webview_id = self . context . next_webview_id ( ) ;
@@ -2818,6 +2854,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
28182854 webview_id,
28192855 & self . context ,
28202856 pending,
2857+ focused_webview,
28212858 ) ?;
28222859
28232860 #[ allow( unknown_lints, clippy:: manual_inspect) ]
@@ -3750,9 +3787,9 @@ fn handle_user_message<T: UserEvent>(
37503787 . 0
37513788 . borrow ( )
37523789 . get ( & window_id)
3753- . and_then ( |w| w. inner . clone ( ) ) ;
3754- if let Some ( window) = window {
3755- match handler ( & window) {
3790+ . map ( |w| ( w. inner . clone ( ) , w . focused_webview . clone ( ) ) ) ;
3791+ if let Some ( ( Some ( window) , focused_webview ) ) = window {
3792+ match handler ( & window, CreateWebviewOptions { focused_webview } ) {
37563793 Ok ( webview) => {
37573794 #[ allow( unknown_lints, clippy:: manual_inspect) ]
37583795 windows. 0 . borrow_mut ( ) . get_mut ( & window_id) . map ( |w| {
@@ -3818,6 +3855,7 @@ fn handle_user_message<T: UserEvent>(
38183855 is_window_transparent,
38193856 #[ cfg( windows) ]
38203857 surface,
3858+ focused_webview : Default :: default ( ) ,
38213859 } ,
38223860 ) ;
38233861 sender. send ( Ok ( Arc :: downgrade ( & window) ) ) . unwrap ( ) ;
@@ -4307,6 +4345,8 @@ fn create_window<T: UserEvent, F: Fn(RawWindow) + Send + 'static>(
43074345
43084346 let mut webviews = Vec :: new ( ) ;
43094347
4348+ let focused_webview = Arc :: new ( Mutex :: new ( None ) ) ;
4349+
43104350 if let Some ( webview) = webview {
43114351 webviews. push ( create_webview (
43124352 #[ cfg( feature = "unstable" ) ]
@@ -4318,6 +4358,7 @@ fn create_window<T: UserEvent, F: Fn(RawWindow) + Send + 'static>(
43184358 webview_id,
43194359 context,
43204360 webview,
4361+ focused_webview. clone ( ) ,
43214362 ) ?) ;
43224363 }
43234364
@@ -4351,6 +4392,7 @@ fn create_window<T: UserEvent, F: Fn(RawWindow) + Send + 'static>(
43514392 is_window_transparent,
43524393 #[ cfg( windows) ]
43534394 surface,
4395+ focused_webview,
43544396 } )
43554397}
43564398
@@ -4378,6 +4420,7 @@ fn create_webview<T: UserEvent>(
43784420 id : WebviewId ,
43794421 context : & Context < T > ,
43804422 pending : PendingWebview < T , Wry < T > > ,
4423+ #[ allow( unused_variables) ] focused_webview : Arc < Mutex < Option < String > > > ,
43814424) -> Result < WebviewWrapper > {
43824425 #[ allow( unused_mut) ]
43834426 let PendingWebview {
@@ -4766,34 +4809,60 @@ fn create_webview<T: UserEvent>(
47664809 }
47674810
47684811 #[ cfg( windows) ]
4769- if kind == WebviewKind :: WindowContent {
4812+ {
47704813 let controller = webview. controller ( ) ;
47714814 let proxy = context. proxy . clone ( ) ;
47724815 let proxy_ = proxy. clone ( ) ;
47734816 let window_id_ = window_id. clone ( ) ;
47744817 let mut token = 0 ;
47754818 unsafe {
4819+ let label_ = label. clone ( ) ;
4820+ let focused_webview_ = focused_webview. clone ( ) ;
47764821 controller. add_GotFocus (
47774822 & FocusChangedEventHandler :: create ( Box :: new ( move |_, _| {
4778- let _ = proxy. send_event ( Message :: Webview (
4779- * window_id_. lock ( ) . unwrap ( ) ,
4780- id,
4781- WebviewMessage :: SynthesizedWindowEvent ( SynthesizedWindowEvent :: Focused ( true ) ) ,
4782- ) ) ;
4823+ let mut focused_webview = focused_webview_. lock ( ) . unwrap ( ) ;
4824+ // when using multiwebview mode, we should check if the focus change is actually a "webview focus change"
4825+ // instead of a window focus change (here we're patching window events, so we only care about the actual window changing focus)
4826+ let already_focused = focused_webview. is_some ( ) ;
4827+ focused_webview. replace ( label_. clone ( ) ) ;
4828+
4829+ if !already_focused {
4830+ let _ = proxy. send_event ( Message :: Webview (
4831+ * window_id_. lock ( ) . unwrap ( ) ,
4832+ id,
4833+ WebviewMessage :: SynthesizedWindowEvent ( SynthesizedWindowEvent :: Focused ( true ) ) ,
4834+ ) ) ;
4835+ }
47834836 Ok ( ( ) )
47844837 } ) ) ,
47854838 & mut token,
47864839 )
47874840 }
47884841 . unwrap ( ) ;
47894842 unsafe {
4843+ let label_ = label. clone ( ) ;
4844+ let focused_webview_ = focused_webview. clone ( ) ;
47904845 controller. add_LostFocus (
47914846 & FocusChangedEventHandler :: create ( Box :: new ( move |_, _| {
4792- let _ = proxy_. send_event ( Message :: Webview (
4793- * window_id. lock ( ) . unwrap ( ) ,
4794- id,
4795- WebviewMessage :: SynthesizedWindowEvent ( SynthesizedWindowEvent :: Focused ( false ) ) ,
4796- ) ) ;
4847+ let mut focused_webview = focused_webview_. lock ( ) . unwrap ( ) ;
4848+ // when using multiwebview mode, we should handle webview focus changes
4849+ // so we check is the currently focused webview matches this webview's
4850+ // (in this case, it means we lost the window focus)
4851+ //
4852+ // on multiwebview mode if we change focus to a different webview
4853+ // we get the gotFocus event of the other webview before the lostFocus
4854+ // so this check makes sense
4855+ let lost_window_focus = focused_webview. as_ref ( ) . map_or ( true , |w| w == & label_) ;
4856+
4857+ if lost_window_focus {
4858+ // only reset when we lost window focus - otherwise some other webview is focused
4859+ * focused_webview = None ;
4860+ let _ = proxy_. send_event ( Message :: Webview (
4861+ * window_id. lock ( ) . unwrap ( ) ,
4862+ id,
4863+ WebviewMessage :: SynthesizedWindowEvent ( SynthesizedWindowEvent :: Focused ( false ) ) ,
4864+ ) ) ;
4865+ }
47974866 Ok ( ( ) )
47984867 } ) ) ,
47994868 & mut token,
0 commit comments