lib.rs 113 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900
  1. // Copyright 2019-2023 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. //! [![](https://github.com/tauri-apps/tauri/raw/dev/.github/splash.png)](https://tauri.app)
  5. //!
  6. //! The [`wry`] Tauri [`Runtime`].
  7. #![doc(
  8. html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png",
  9. html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png"
  10. )]
  11. use raw_window_handle::{DisplayHandle, HasDisplayHandle, HasWindowHandle};
  12. use tauri_runtime::{
  13. monitor::Monitor,
  14. webview::{DetachedWebview, DownloadEvent, PendingWebview, WebviewIpcHandler},
  15. window::{
  16. dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size},
  17. CursorIcon, DetachedWindow, FileDropEvent, PendingWindow, RawWindow, WebviewEvent,
  18. WindowBuilder, WindowBuilderBase, WindowEvent, WindowId,
  19. },
  20. DeviceEventFilter, Error, EventLoopProxy, ExitRequestedEventAction, Icon, ProgressBarState,
  21. ProgressBarStatus, Result, RunEvent, Runtime, RuntimeHandle, RuntimeInitArgs, UserAttentionType,
  22. UserEvent, WebviewDispatch, WebviewEventId, WindowDispatch, WindowEventId,
  23. };
  24. #[cfg(target_os = "macos")]
  25. use tao::platform::macos::{EventLoopWindowTargetExtMacOS, WindowBuilderExtMacOS};
  26. #[cfg(target_os = "linux")]
  27. use tao::platform::unix::{WindowBuilderExtUnix, WindowExtUnix};
  28. #[cfg(windows)]
  29. use tao::platform::windows::{WindowBuilderExtWindows, WindowExtWindows};
  30. #[cfg(windows)]
  31. use webview2_com::FocusChangedEventHandler;
  32. #[cfg(windows)]
  33. use windows::Win32::{Foundation::HWND, System::WinRT::EventRegistrationToken};
  34. #[cfg(windows)]
  35. use wry::WebViewBuilderExtWindows;
  36. use tao::{
  37. dpi::{
  38. LogicalPosition as TaoLogicalPosition, LogicalSize as TaoLogicalSize,
  39. PhysicalPosition as TaoPhysicalPosition, PhysicalSize as TaoPhysicalSize,
  40. Position as TaoPosition, Size as TaoSize,
  41. },
  42. event::{Event, StartCause, WindowEvent as TaoWindowEvent},
  43. event_loop::{
  44. ControlFlow, DeviceEventFilter as TaoDeviceEventFilter, EventLoop, EventLoopBuilder,
  45. EventLoopProxy as TaoEventLoopProxy, EventLoopWindowTarget,
  46. },
  47. monitor::MonitorHandle,
  48. window::{
  49. CursorIcon as TaoCursorIcon, Fullscreen, Icon as TaoWindowIcon,
  50. ProgressBarState as TaoProgressBarState, ProgressState as TaoProgressState, Theme as TaoTheme,
  51. UserAttentionType as TaoUserAttentionType,
  52. },
  53. };
  54. #[cfg(target_os = "macos")]
  55. use tauri_utils::TitleBarStyle;
  56. use tauri_utils::{config::WindowConfig, debug_eprintln, Theme};
  57. use url::Url;
  58. use wry::{
  59. FileDropEvent as WryFileDropEvent, ProxyConfig, ProxyEndpoint, WebContext, WebView,
  60. WebViewBuilder,
  61. };
  62. pub use tao;
  63. pub use tao::window::{Window, WindowBuilder as TaoWindowBuilder, WindowId as TaoWindowId};
  64. pub use wry;
  65. pub use wry::webview_version;
  66. #[cfg(windows)]
  67. use wry::WebViewExtWindows;
  68. #[cfg(target_os = "android")]
  69. use wry::{
  70. prelude::{dispatch, find_class},
  71. WebViewBuilderExtAndroid, WebViewExtAndroid,
  72. };
  73. #[cfg(not(any(
  74. target_os = "windows",
  75. target_os = "macos",
  76. target_os = "ios",
  77. target_os = "android"
  78. )))]
  79. use wry::{WebViewBuilderExtUnix, WebViewExtUnix};
  80. #[cfg(target_os = "macos")]
  81. pub use tao::platform::macos::{
  82. ActivationPolicy as TaoActivationPolicy, EventLoopExtMacOS, WindowExtMacOS,
  83. };
  84. #[cfg(target_os = "macos")]
  85. use tauri_runtime::ActivationPolicy;
  86. use std::{
  87. cell::RefCell,
  88. collections::{
  89. hash_map::Entry::{Occupied, Vacant},
  90. BTreeMap, HashMap,
  91. },
  92. fmt,
  93. ops::Deref,
  94. path::PathBuf,
  95. rc::Rc,
  96. sync::{
  97. atomic::{AtomicBool, AtomicU32, Ordering},
  98. mpsc::{channel, Sender},
  99. Arc, Mutex, Weak,
  100. },
  101. thread::{current as current_thread, ThreadId},
  102. };
  103. pub type WebviewId = u32;
  104. type IpcHandler = dyn Fn(String) + 'static;
  105. #[cfg(any(
  106. windows,
  107. target_os = "linux",
  108. target_os = "dragonfly",
  109. target_os = "freebsd",
  110. target_os = "netbsd",
  111. target_os = "openbsd"
  112. ))]
  113. mod undecorated_resizing;
  114. mod webview;
  115. pub use webview::Webview;
  116. pub type WebContextStore = Arc<Mutex<HashMap<Option<PathBuf>, WebContext>>>;
  117. // window
  118. pub type WindowEventHandler = Box<dyn Fn(&WindowEvent) + Send>;
  119. pub type WindowEventListeners = Arc<Mutex<HashMap<WindowEventId, WindowEventHandler>>>;
  120. pub type WebviewEventHandler = Box<dyn Fn(&WebviewEvent) + Send>;
  121. pub type WebviewEventListeners = Arc<Mutex<HashMap<WebviewEventId, WebviewEventHandler>>>;
  122. #[derive(Debug, Clone, Default)]
  123. pub struct WindowIdStore(Arc<Mutex<HashMap<TaoWindowId, WindowId>>>);
  124. impl WindowIdStore {
  125. pub fn insert(&self, w: TaoWindowId, id: WindowId) {
  126. self.0.lock().unwrap().insert(w, id);
  127. }
  128. fn get(&self, w: &TaoWindowId) -> Option<WindowId> {
  129. self.0.lock().unwrap().get(w).copied()
  130. }
  131. }
  132. #[macro_export]
  133. macro_rules! getter {
  134. ($self: ident, $rx: expr, $message: expr) => {{
  135. $crate::send_user_message(&$self.context, $message)?;
  136. $rx
  137. .recv()
  138. .map_err(|_| $crate::Error::FailedToReceiveMessage)
  139. }};
  140. }
  141. macro_rules! window_getter {
  142. ($self: ident, $message: expr) => {{
  143. let (tx, rx) = channel();
  144. getter!($self, rx, Message::Window($self.window_id, $message(tx)))
  145. }};
  146. }
  147. macro_rules! webview_getter {
  148. ($self: ident, $message: expr) => {{
  149. let (tx, rx) = channel();
  150. getter!(
  151. $self,
  152. rx,
  153. Message::Webview(
  154. *$self.window_id.lock().unwrap(),
  155. $self.webview_id,
  156. $message(tx)
  157. )
  158. )
  159. }};
  160. }
  161. pub(crate) fn send_user_message<T: UserEvent>(
  162. context: &Context<T>,
  163. message: Message<T>,
  164. ) -> Result<()> {
  165. if current_thread().id() == context.main_thread_id {
  166. handle_user_message(
  167. &context.main_thread.window_target,
  168. message,
  169. UserMessageContext {
  170. window_id_map: context.window_id_map.clone(),
  171. windows: context.main_thread.windows.clone(),
  172. },
  173. );
  174. Ok(())
  175. } else {
  176. context
  177. .proxy
  178. .send_event(message)
  179. .map_err(|_| Error::FailedToSendMessage)
  180. }
  181. }
  182. #[derive(Clone)]
  183. pub struct Context<T: UserEvent> {
  184. pub window_id_map: WindowIdStore,
  185. main_thread_id: ThreadId,
  186. pub proxy: TaoEventLoopProxy<Message<T>>,
  187. main_thread: DispatcherMainThreadContext<T>,
  188. plugins: Arc<Mutex<Vec<Box<dyn Plugin<T> + Send>>>>,
  189. next_window_id: Arc<AtomicU32>,
  190. next_webview_id: Arc<AtomicU32>,
  191. next_window_event_id: Arc<AtomicU32>,
  192. next_webview_event_id: Arc<AtomicU32>,
  193. next_webcontext_id: Arc<AtomicU32>,
  194. }
  195. impl<T: UserEvent> Context<T> {
  196. pub fn run_threaded<R, F>(&self, f: F) -> R
  197. where
  198. F: FnOnce(Option<&DispatcherMainThreadContext<T>>) -> R,
  199. {
  200. f(if current_thread().id() == self.main_thread_id {
  201. Some(&self.main_thread)
  202. } else {
  203. None
  204. })
  205. }
  206. fn next_window_id(&self) -> WindowId {
  207. self.next_window_id.fetch_add(1, Ordering::Relaxed).into()
  208. }
  209. fn next_webview_id(&self) -> WebviewId {
  210. self.next_webview_id.fetch_add(1, Ordering::Relaxed)
  211. }
  212. fn next_window_event_id(&self) -> u32 {
  213. self.next_window_event_id.fetch_add(1, Ordering::Relaxed)
  214. }
  215. fn next_webview_event_id(&self) -> u32 {
  216. self.next_webview_event_id.fetch_add(1, Ordering::Relaxed)
  217. }
  218. fn next_webcontext_id(&self) -> u32 {
  219. self.next_webcontext_id.fetch_add(1, Ordering::Relaxed)
  220. }
  221. }
  222. impl<T: UserEvent> Context<T> {
  223. fn create_window<F: Fn(RawWindow) + Send + 'static>(
  224. &self,
  225. pending: PendingWindow<T, Wry<T>>,
  226. after_window_creation: Option<F>,
  227. ) -> Result<DetachedWindow<T, Wry<T>>> {
  228. let label = pending.label.clone();
  229. let context = self.clone();
  230. let window_id = self.next_window_id();
  231. let webview_id = pending.webview.as_ref().map(|_| context.next_webview_id());
  232. send_user_message(
  233. self,
  234. Message::CreateWindow(
  235. window_id,
  236. Box::new(move |event_loop| {
  237. create_window(
  238. window_id,
  239. webview_id.unwrap_or_default(),
  240. event_loop,
  241. &context,
  242. pending,
  243. after_window_creation,
  244. )
  245. }),
  246. ),
  247. )?;
  248. let dispatcher = WryWindowDispatcher {
  249. window_id,
  250. context: self.clone(),
  251. };
  252. let detached_webview = webview_id.map(|id| DetachedWebview {
  253. label: label.clone(),
  254. dispatcher: WryWebviewDispatcher {
  255. window_id: Arc::new(Mutex::new(window_id)),
  256. webview_id: id,
  257. context: self.clone(),
  258. },
  259. });
  260. Ok(DetachedWindow {
  261. id: window_id,
  262. label,
  263. dispatcher,
  264. webview: detached_webview,
  265. })
  266. }
  267. fn create_webview(
  268. &self,
  269. window_id: WindowId,
  270. pending: PendingWebview<T, Wry<T>>,
  271. ) -> Result<DetachedWebview<T, Wry<T>>> {
  272. let label = pending.label.clone();
  273. let context = self.clone();
  274. let webview_id = self.next_webview_id();
  275. let window_id_wrapper = Arc::new(Mutex::new(window_id));
  276. let window_id_wrapper_ = window_id_wrapper.clone();
  277. send_user_message(
  278. self,
  279. Message::CreateWebview(
  280. window_id,
  281. Box::new(move |window| {
  282. create_webview(
  283. WebviewKind::WindowChild,
  284. window,
  285. window_id_wrapper_,
  286. webview_id,
  287. &context,
  288. pending,
  289. )
  290. }),
  291. ),
  292. )?;
  293. let dispatcher = WryWebviewDispatcher {
  294. window_id: window_id_wrapper,
  295. webview_id,
  296. context: self.clone(),
  297. };
  298. Ok(DetachedWebview { label, dispatcher })
  299. }
  300. }
  301. #[cfg(feature = "tracing")]
  302. #[derive(Debug, Clone, Default)]
  303. pub struct ActiveTraceSpanStore(Rc<RefCell<Vec<ActiveTracingSpan>>>);
  304. #[cfg(feature = "tracing")]
  305. impl ActiveTraceSpanStore {
  306. pub fn remove_window_draw(&self, window_id: TaoWindowId) {
  307. let mut store = self.0.borrow_mut();
  308. if let Some(index) = store
  309. .iter()
  310. .position(|t| matches!(t, ActiveTracingSpan::WindowDraw { id, span: _ } if id == &window_id))
  311. {
  312. store.remove(index);
  313. }
  314. }
  315. }
  316. #[cfg(feature = "tracing")]
  317. #[derive(Debug)]
  318. pub enum ActiveTracingSpan {
  319. WindowDraw {
  320. id: TaoWindowId,
  321. span: tracing::span::EnteredSpan,
  322. },
  323. }
  324. #[derive(Debug)]
  325. pub struct WindowsStore(RefCell<BTreeMap<WindowId, WindowWrapper>>);
  326. // SAFETY: we ensure this type is only used on the main thread.
  327. #[allow(clippy::non_send_fields_in_send_ty)]
  328. unsafe impl Send for WindowsStore {}
  329. // SAFETY: we ensure this type is only used on the main thread.
  330. #[allow(clippy::non_send_fields_in_send_ty)]
  331. unsafe impl Sync for WindowsStore {}
  332. #[derive(Debug, Clone)]
  333. pub struct DispatcherMainThreadContext<T: UserEvent> {
  334. pub window_target: EventLoopWindowTarget<Message<T>>,
  335. pub web_context: WebContextStore,
  336. // changing this to an Rc will cause frequent app crashes.
  337. pub windows: Arc<WindowsStore>,
  338. #[cfg(feature = "tracing")]
  339. pub active_tracing_spans: ActiveTraceSpanStore,
  340. }
  341. // SAFETY: we ensure this type is only used on the main thread.
  342. #[allow(clippy::non_send_fields_in_send_ty)]
  343. unsafe impl<T: UserEvent> Send for DispatcherMainThreadContext<T> {}
  344. // SAFETY: we ensure this type is only used on the main thread.
  345. #[allow(clippy::non_send_fields_in_send_ty)]
  346. unsafe impl<T: UserEvent> Sync for DispatcherMainThreadContext<T> {}
  347. impl<T: UserEvent> fmt::Debug for Context<T> {
  348. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  349. f.debug_struct("Context")
  350. .field("main_thread_id", &self.main_thread_id)
  351. .field("proxy", &self.proxy)
  352. .field("main_thread", &self.main_thread)
  353. .finish()
  354. }
  355. }
  356. pub struct DeviceEventFilterWrapper(pub TaoDeviceEventFilter);
  357. impl From<DeviceEventFilter> for DeviceEventFilterWrapper {
  358. fn from(item: DeviceEventFilter) -> Self {
  359. match item {
  360. DeviceEventFilter::Always => Self(TaoDeviceEventFilter::Always),
  361. DeviceEventFilter::Never => Self(TaoDeviceEventFilter::Never),
  362. DeviceEventFilter::Unfocused => Self(TaoDeviceEventFilter::Unfocused),
  363. }
  364. }
  365. }
  366. /// Wrapper around a [`tao::window::Icon`] that can be created from an [`Icon`].
  367. pub struct TaoIcon(pub TaoWindowIcon);
  368. fn icon_err<E: std::error::Error + Send + Sync + 'static>(e: E) -> Error {
  369. Error::InvalidIcon(Box::new(e))
  370. }
  371. impl TryFrom<Icon> for TaoIcon {
  372. type Error = Error;
  373. fn try_from(icon: Icon) -> std::result::Result<Self, Self::Error> {
  374. TaoWindowIcon::from_rgba(icon.rgba, icon.width, icon.height)
  375. .map(Self)
  376. .map_err(icon_err)
  377. }
  378. }
  379. pub struct WindowEventWrapper(pub Option<WindowEvent>);
  380. impl WindowEventWrapper {
  381. fn parse(window: &WindowWrapper, event: &TaoWindowEvent<'_>) -> Self {
  382. match event {
  383. // resized event from tao doesn't include a reliable size on macOS
  384. // because wry replaces the NSView
  385. TaoWindowEvent::Resized(_) => {
  386. if let Some(w) = &window.inner {
  387. Self(Some(WindowEvent::Resized(
  388. PhysicalSizeWrapper(inner_size(
  389. w,
  390. &window.webviews,
  391. window.has_children.load(Ordering::Relaxed),
  392. ))
  393. .into(),
  394. )))
  395. } else {
  396. Self(None)
  397. }
  398. }
  399. e => e.into(),
  400. }
  401. }
  402. }
  403. pub fn map_theme(theme: &TaoTheme) -> Theme {
  404. match theme {
  405. TaoTheme::Light => Theme::Light,
  406. TaoTheme::Dark => Theme::Dark,
  407. _ => Theme::Light,
  408. }
  409. }
  410. #[cfg(target_os = "macos")]
  411. fn tao_activation_policy(activation_policy: ActivationPolicy) -> TaoActivationPolicy {
  412. match activation_policy {
  413. ActivationPolicy::Regular => TaoActivationPolicy::Regular,
  414. ActivationPolicy::Accessory => TaoActivationPolicy::Accessory,
  415. ActivationPolicy::Prohibited => TaoActivationPolicy::Prohibited,
  416. _ => unimplemented!(),
  417. }
  418. }
  419. impl<'a> From<&TaoWindowEvent<'a>> for WindowEventWrapper {
  420. fn from(event: &TaoWindowEvent<'a>) -> Self {
  421. let event = match event {
  422. TaoWindowEvent::Resized(size) => WindowEvent::Resized(PhysicalSizeWrapper(*size).into()),
  423. TaoWindowEvent::Moved(position) => {
  424. WindowEvent::Moved(PhysicalPositionWrapper(*position).into())
  425. }
  426. TaoWindowEvent::Destroyed => WindowEvent::Destroyed,
  427. TaoWindowEvent::ScaleFactorChanged {
  428. scale_factor,
  429. new_inner_size,
  430. } => WindowEvent::ScaleFactorChanged {
  431. scale_factor: *scale_factor,
  432. new_inner_size: PhysicalSizeWrapper(**new_inner_size).into(),
  433. },
  434. #[cfg(any(target_os = "linux", target_os = "macos"))]
  435. TaoWindowEvent::Focused(focused) => WindowEvent::Focused(*focused),
  436. TaoWindowEvent::ThemeChanged(theme) => WindowEvent::ThemeChanged(map_theme(theme)),
  437. _ => return Self(None),
  438. };
  439. Self(Some(event))
  440. }
  441. }
  442. pub struct MonitorHandleWrapper(pub MonitorHandle);
  443. impl From<MonitorHandleWrapper> for Monitor {
  444. fn from(monitor: MonitorHandleWrapper) -> Monitor {
  445. Self {
  446. name: monitor.0.name(),
  447. position: PhysicalPositionWrapper(monitor.0.position()).into(),
  448. size: PhysicalSizeWrapper(monitor.0.size()).into(),
  449. scale_factor: monitor.0.scale_factor(),
  450. }
  451. }
  452. }
  453. pub struct PhysicalPositionWrapper<T>(pub TaoPhysicalPosition<T>);
  454. impl<T> From<PhysicalPositionWrapper<T>> for PhysicalPosition<T> {
  455. fn from(position: PhysicalPositionWrapper<T>) -> Self {
  456. Self {
  457. x: position.0.x,
  458. y: position.0.y,
  459. }
  460. }
  461. }
  462. impl<T> From<PhysicalPosition<T>> for PhysicalPositionWrapper<T> {
  463. fn from(position: PhysicalPosition<T>) -> Self {
  464. Self(TaoPhysicalPosition {
  465. x: position.x,
  466. y: position.y,
  467. })
  468. }
  469. }
  470. struct LogicalPositionWrapper<T>(TaoLogicalPosition<T>);
  471. impl<T> From<LogicalPosition<T>> for LogicalPositionWrapper<T> {
  472. fn from(position: LogicalPosition<T>) -> Self {
  473. Self(TaoLogicalPosition {
  474. x: position.x,
  475. y: position.y,
  476. })
  477. }
  478. }
  479. pub struct PhysicalSizeWrapper<T>(pub TaoPhysicalSize<T>);
  480. impl<T> From<PhysicalSizeWrapper<T>> for PhysicalSize<T> {
  481. fn from(size: PhysicalSizeWrapper<T>) -> Self {
  482. Self {
  483. width: size.0.width,
  484. height: size.0.height,
  485. }
  486. }
  487. }
  488. impl<T> From<PhysicalSize<T>> for PhysicalSizeWrapper<T> {
  489. fn from(size: PhysicalSize<T>) -> Self {
  490. Self(TaoPhysicalSize {
  491. width: size.width,
  492. height: size.height,
  493. })
  494. }
  495. }
  496. struct LogicalSizeWrapper<T>(TaoLogicalSize<T>);
  497. impl<T> From<LogicalSize<T>> for LogicalSizeWrapper<T> {
  498. fn from(size: LogicalSize<T>) -> Self {
  499. Self(TaoLogicalSize {
  500. width: size.width,
  501. height: size.height,
  502. })
  503. }
  504. }
  505. pub struct SizeWrapper(pub TaoSize);
  506. impl From<Size> for SizeWrapper {
  507. fn from(size: Size) -> Self {
  508. match size {
  509. Size::Logical(s) => Self(TaoSize::Logical(LogicalSizeWrapper::from(s).0)),
  510. Size::Physical(s) => Self(TaoSize::Physical(PhysicalSizeWrapper::from(s).0)),
  511. }
  512. }
  513. }
  514. pub struct PositionWrapper(pub TaoPosition);
  515. impl From<Position> for PositionWrapper {
  516. fn from(position: Position) -> Self {
  517. match position {
  518. Position::Logical(s) => Self(TaoPosition::Logical(LogicalPositionWrapper::from(s).0)),
  519. Position::Physical(s) => Self(TaoPosition::Physical(PhysicalPositionWrapper::from(s).0)),
  520. }
  521. }
  522. }
  523. #[derive(Debug, Clone)]
  524. pub struct UserAttentionTypeWrapper(pub TaoUserAttentionType);
  525. impl From<UserAttentionType> for UserAttentionTypeWrapper {
  526. fn from(request_type: UserAttentionType) -> Self {
  527. let o = match request_type {
  528. UserAttentionType::Critical => TaoUserAttentionType::Critical,
  529. UserAttentionType::Informational => TaoUserAttentionType::Informational,
  530. };
  531. Self(o)
  532. }
  533. }
  534. #[derive(Debug)]
  535. pub struct CursorIconWrapper(pub TaoCursorIcon);
  536. impl From<CursorIcon> for CursorIconWrapper {
  537. fn from(icon: CursorIcon) -> Self {
  538. use CursorIcon::*;
  539. let i = match icon {
  540. Default => TaoCursorIcon::Default,
  541. Crosshair => TaoCursorIcon::Crosshair,
  542. Hand => TaoCursorIcon::Hand,
  543. Arrow => TaoCursorIcon::Arrow,
  544. Move => TaoCursorIcon::Move,
  545. Text => TaoCursorIcon::Text,
  546. Wait => TaoCursorIcon::Wait,
  547. Help => TaoCursorIcon::Help,
  548. Progress => TaoCursorIcon::Progress,
  549. NotAllowed => TaoCursorIcon::NotAllowed,
  550. ContextMenu => TaoCursorIcon::ContextMenu,
  551. Cell => TaoCursorIcon::Cell,
  552. VerticalText => TaoCursorIcon::VerticalText,
  553. Alias => TaoCursorIcon::Alias,
  554. Copy => TaoCursorIcon::Copy,
  555. NoDrop => TaoCursorIcon::NoDrop,
  556. Grab => TaoCursorIcon::Grab,
  557. Grabbing => TaoCursorIcon::Grabbing,
  558. AllScroll => TaoCursorIcon::AllScroll,
  559. ZoomIn => TaoCursorIcon::ZoomIn,
  560. ZoomOut => TaoCursorIcon::ZoomOut,
  561. EResize => TaoCursorIcon::EResize,
  562. NResize => TaoCursorIcon::NResize,
  563. NeResize => TaoCursorIcon::NeResize,
  564. NwResize => TaoCursorIcon::NwResize,
  565. SResize => TaoCursorIcon::SResize,
  566. SeResize => TaoCursorIcon::SeResize,
  567. SwResize => TaoCursorIcon::SwResize,
  568. WResize => TaoCursorIcon::WResize,
  569. EwResize => TaoCursorIcon::EwResize,
  570. NsResize => TaoCursorIcon::NsResize,
  571. NeswResize => TaoCursorIcon::NeswResize,
  572. NwseResize => TaoCursorIcon::NwseResize,
  573. ColResize => TaoCursorIcon::ColResize,
  574. RowResize => TaoCursorIcon::RowResize,
  575. _ => TaoCursorIcon::Default,
  576. };
  577. Self(i)
  578. }
  579. }
  580. pub struct ProgressStateWrapper(pub TaoProgressState);
  581. impl From<ProgressBarStatus> for ProgressStateWrapper {
  582. fn from(status: ProgressBarStatus) -> Self {
  583. let state = match status {
  584. ProgressBarStatus::None => TaoProgressState::None,
  585. ProgressBarStatus::Normal => TaoProgressState::Normal,
  586. ProgressBarStatus::Indeterminate => TaoProgressState::Indeterminate,
  587. ProgressBarStatus::Paused => TaoProgressState::Paused,
  588. ProgressBarStatus::Error => TaoProgressState::Error,
  589. };
  590. Self(state)
  591. }
  592. }
  593. pub struct ProgressBarStateWrapper(pub TaoProgressBarState);
  594. impl From<ProgressBarState> for ProgressBarStateWrapper {
  595. fn from(progress_state: ProgressBarState) -> Self {
  596. Self(TaoProgressBarState {
  597. progress: progress_state.progress,
  598. state: progress_state
  599. .status
  600. .map(|state| ProgressStateWrapper::from(state).0),
  601. desktop_filename: progress_state.desktop_filename,
  602. })
  603. }
  604. }
  605. #[derive(Clone, Default)]
  606. pub struct WindowBuilderWrapper {
  607. inner: TaoWindowBuilder,
  608. center: bool,
  609. #[cfg(target_os = "macos")]
  610. tabbing_identifier: Option<String>,
  611. }
  612. impl std::fmt::Debug for WindowBuilderWrapper {
  613. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  614. let mut s = f.debug_struct("WindowBuilderWrapper");
  615. s.field("inner", &self.inner).field("center", &self.center);
  616. #[cfg(target_os = "macos")]
  617. {
  618. s.field("tabbing_identifier", &self.tabbing_identifier);
  619. }
  620. s.finish()
  621. }
  622. }
  623. // SAFETY: this type is `Send` since `menu_items` are read only here
  624. #[allow(clippy::non_send_fields_in_send_ty)]
  625. unsafe impl Send for WindowBuilderWrapper {}
  626. impl WindowBuilderBase for WindowBuilderWrapper {}
  627. impl WindowBuilder for WindowBuilderWrapper {
  628. fn new() -> Self {
  629. Self::default().focused(true)
  630. }
  631. fn with_config(config: &WindowConfig) -> Self {
  632. let mut window = WindowBuilderWrapper::new();
  633. #[cfg(target_os = "macos")]
  634. {
  635. window = window
  636. .hidden_title(config.hidden_title)
  637. .title_bar_style(config.title_bar_style);
  638. if let Some(identifier) = &config.tabbing_identifier {
  639. window = window.tabbing_identifier(identifier);
  640. }
  641. }
  642. #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))]
  643. {
  644. window = window.transparent(config.transparent);
  645. }
  646. #[cfg(all(
  647. target_os = "macos",
  648. not(feature = "macos-private-api"),
  649. debug_assertions
  650. ))]
  651. if config.transparent {
  652. eprintln!(
  653. "The window is set to be transparent but the `macos-private-api` is not enabled.
  654. This can be enabled via the `tauri.macOSPrivateApi` configuration property <https://tauri.app/docs/api/config#tauri.macOSPrivateApi>
  655. ");
  656. }
  657. #[cfg(target_os = "linux")]
  658. {
  659. // Mouse event is disabled on Linux since sudden event bursts could block event loop.
  660. window.inner = window.inner.with_cursor_moved_event(false);
  661. }
  662. #[cfg(desktop)]
  663. {
  664. window = window
  665. .title(config.title.to_string())
  666. .inner_size(config.width, config.height)
  667. .visible(config.visible)
  668. .resizable(config.resizable)
  669. .fullscreen(config.fullscreen)
  670. .decorations(config.decorations)
  671. .maximized(config.maximized)
  672. .always_on_bottom(config.always_on_bottom)
  673. .always_on_top(config.always_on_top)
  674. .visible_on_all_workspaces(config.visible_on_all_workspaces)
  675. .content_protected(config.content_protected)
  676. .skip_taskbar(config.skip_taskbar)
  677. .theme(config.theme)
  678. .shadow(config.shadow);
  679. if let (Some(min_width), Some(min_height)) = (config.min_width, config.min_height) {
  680. window = window.min_inner_size(min_width, min_height);
  681. }
  682. if let (Some(max_width), Some(max_height)) = (config.max_width, config.max_height) {
  683. window = window.max_inner_size(max_width, max_height);
  684. }
  685. if let (Some(x), Some(y)) = (config.x, config.y) {
  686. window = window.position(x, y);
  687. }
  688. if config.center {
  689. window = window.center();
  690. }
  691. }
  692. window
  693. }
  694. fn center(mut self) -> Self {
  695. self.center = true;
  696. self
  697. }
  698. fn position(mut self, x: f64, y: f64) -> Self {
  699. self.inner = self.inner.with_position(TaoLogicalPosition::new(x, y));
  700. self
  701. }
  702. fn inner_size(mut self, width: f64, height: f64) -> Self {
  703. self.inner = self
  704. .inner
  705. .with_inner_size(TaoLogicalSize::new(width, height));
  706. self
  707. }
  708. fn min_inner_size(mut self, min_width: f64, min_height: f64) -> Self {
  709. self.inner = self
  710. .inner
  711. .with_min_inner_size(TaoLogicalSize::new(min_width, min_height));
  712. self
  713. }
  714. fn max_inner_size(mut self, max_width: f64, max_height: f64) -> Self {
  715. self.inner = self
  716. .inner
  717. .with_max_inner_size(TaoLogicalSize::new(max_width, max_height));
  718. self
  719. }
  720. fn resizable(mut self, resizable: bool) -> Self {
  721. self.inner = self.inner.with_resizable(resizable);
  722. self
  723. }
  724. fn maximizable(mut self, maximizable: bool) -> Self {
  725. self.inner = self.inner.with_maximizable(maximizable);
  726. self
  727. }
  728. fn minimizable(mut self, minimizable: bool) -> Self {
  729. self.inner = self.inner.with_minimizable(minimizable);
  730. self
  731. }
  732. fn closable(mut self, closable: bool) -> Self {
  733. self.inner = self.inner.with_closable(closable);
  734. self
  735. }
  736. fn title<S: Into<String>>(mut self, title: S) -> Self {
  737. self.inner = self.inner.with_title(title.into());
  738. self
  739. }
  740. fn fullscreen(mut self, fullscreen: bool) -> Self {
  741. self.inner = if fullscreen {
  742. self
  743. .inner
  744. .with_fullscreen(Some(Fullscreen::Borderless(None)))
  745. } else {
  746. self.inner.with_fullscreen(None)
  747. };
  748. self
  749. }
  750. fn focused(mut self, focused: bool) -> Self {
  751. self.inner = self.inner.with_focused(focused);
  752. self
  753. }
  754. fn maximized(mut self, maximized: bool) -> Self {
  755. self.inner = self.inner.with_maximized(maximized);
  756. self
  757. }
  758. fn visible(mut self, visible: bool) -> Self {
  759. self.inner = self.inner.with_visible(visible);
  760. self
  761. }
  762. #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))]
  763. fn transparent(mut self, transparent: bool) -> Self {
  764. self.inner = self.inner.with_transparent(transparent);
  765. self
  766. }
  767. fn decorations(mut self, decorations: bool) -> Self {
  768. self.inner = self.inner.with_decorations(decorations);
  769. self
  770. }
  771. fn always_on_bottom(mut self, always_on_bottom: bool) -> Self {
  772. self.inner = self.inner.with_always_on_bottom(always_on_bottom);
  773. self
  774. }
  775. fn always_on_top(mut self, always_on_top: bool) -> Self {
  776. self.inner = self.inner.with_always_on_top(always_on_top);
  777. self
  778. }
  779. fn visible_on_all_workspaces(mut self, visible_on_all_workspaces: bool) -> Self {
  780. self.inner = self
  781. .inner
  782. .with_visible_on_all_workspaces(visible_on_all_workspaces);
  783. self
  784. }
  785. fn content_protected(mut self, protected: bool) -> Self {
  786. self.inner = self.inner.with_content_protection(protected);
  787. self
  788. }
  789. fn shadow(#[allow(unused_mut)] mut self, _enable: bool) -> Self {
  790. #[cfg(windows)]
  791. {
  792. self.inner = self.inner.with_undecorated_shadow(_enable);
  793. }
  794. #[cfg(target_os = "macos")]
  795. {
  796. self.inner = self.inner.with_has_shadow(_enable);
  797. }
  798. self
  799. }
  800. #[cfg(windows)]
  801. fn owner(mut self, owner: HWND) -> Self {
  802. self.inner = self.inner.with_owner_window(owner.0);
  803. self
  804. }
  805. #[cfg(windows)]
  806. fn parent(mut self, parent: HWND) -> Self {
  807. self.inner = self.inner.with_parent_window(parent.0);
  808. self
  809. }
  810. #[cfg(target_os = "macos")]
  811. fn parent(mut self, parent: *mut std::ffi::c_void) -> Self {
  812. self.inner = self.inner.with_parent_window(parent);
  813. self
  814. }
  815. #[cfg(any(
  816. target_os = "linux",
  817. target_os = "dragonfly",
  818. target_os = "freebsd",
  819. target_os = "netbsd",
  820. target_os = "openbsd"
  821. ))]
  822. fn transient_for(mut self, parent: &impl gtk::glib::IsA<gtk::Window>) -> Self {
  823. self.inner = self.inner.with_transient_for(parent);
  824. self
  825. }
  826. #[cfg(windows)]
  827. fn drag_and_drop(mut self, enabled: bool) -> Self {
  828. self.inner = self.inner.with_drag_and_drop(enabled);
  829. self
  830. }
  831. #[cfg(target_os = "macos")]
  832. fn title_bar_style(mut self, style: TitleBarStyle) -> Self {
  833. match style {
  834. TitleBarStyle::Visible => {
  835. self.inner = self.inner.with_titlebar_transparent(false);
  836. // Fixes rendering issue when resizing window with devtools open (https://github.com/tauri-apps/tauri/issues/3914)
  837. self.inner = self.inner.with_fullsize_content_view(true);
  838. }
  839. TitleBarStyle::Transparent => {
  840. self.inner = self.inner.with_titlebar_transparent(true);
  841. self.inner = self.inner.with_fullsize_content_view(false);
  842. }
  843. TitleBarStyle::Overlay => {
  844. self.inner = self.inner.with_titlebar_transparent(true);
  845. self.inner = self.inner.with_fullsize_content_view(true);
  846. }
  847. }
  848. self
  849. }
  850. #[cfg(target_os = "macos")]
  851. fn hidden_title(mut self, hidden: bool) -> Self {
  852. self.inner = self.inner.with_title_hidden(hidden);
  853. self
  854. }
  855. #[cfg(target_os = "macos")]
  856. fn tabbing_identifier(mut self, identifier: &str) -> Self {
  857. self.inner = self.inner.with_tabbing_identifier(identifier);
  858. self.tabbing_identifier.replace(identifier.into());
  859. self
  860. }
  861. fn icon(mut self, icon: Icon) -> Result<Self> {
  862. self.inner = self
  863. .inner
  864. .with_window_icon(Some(TaoIcon::try_from(icon)?.0));
  865. Ok(self)
  866. }
  867. #[cfg(any(windows, target_os = "linux"))]
  868. fn skip_taskbar(mut self, skip: bool) -> Self {
  869. self.inner = self.inner.with_skip_taskbar(skip);
  870. self
  871. }
  872. #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))]
  873. fn skip_taskbar(self, _skip: bool) -> Self {
  874. self
  875. }
  876. #[allow(unused_variables, unused_mut)]
  877. fn theme(mut self, theme: Option<Theme>) -> Self {
  878. self.inner = self.inner.with_theme(if let Some(t) = theme {
  879. match t {
  880. Theme::Dark => Some(TaoTheme::Dark),
  881. _ => Some(TaoTheme::Light),
  882. }
  883. } else {
  884. None
  885. });
  886. self
  887. }
  888. fn has_icon(&self) -> bool {
  889. self.inner.window.window_icon.is_some()
  890. }
  891. }
  892. #[cfg(any(
  893. target_os = "linux",
  894. target_os = "dragonfly",
  895. target_os = "freebsd",
  896. target_os = "netbsd",
  897. target_os = "openbsd"
  898. ))]
  899. pub struct GtkWindow(pub gtk::ApplicationWindow);
  900. #[cfg(any(
  901. target_os = "linux",
  902. target_os = "dragonfly",
  903. target_os = "freebsd",
  904. target_os = "netbsd",
  905. target_os = "openbsd"
  906. ))]
  907. #[allow(clippy::non_send_fields_in_send_ty)]
  908. unsafe impl Send for GtkWindow {}
  909. #[cfg(any(
  910. target_os = "linux",
  911. target_os = "dragonfly",
  912. target_os = "freebsd",
  913. target_os = "netbsd",
  914. target_os = "openbsd"
  915. ))]
  916. pub struct GtkBox(pub gtk::Box);
  917. #[cfg(any(
  918. target_os = "linux",
  919. target_os = "dragonfly",
  920. target_os = "freebsd",
  921. target_os = "netbsd",
  922. target_os = "openbsd"
  923. ))]
  924. #[allow(clippy::non_send_fields_in_send_ty)]
  925. unsafe impl Send for GtkBox {}
  926. pub struct SendRawWindowHandle(pub raw_window_handle::RawWindowHandle);
  927. unsafe impl Send for SendRawWindowHandle {}
  928. #[cfg(target_os = "macos")]
  929. #[derive(Debug, Clone)]
  930. pub enum ApplicationMessage {
  931. Show,
  932. Hide,
  933. }
  934. pub enum WindowMessage {
  935. AddEventListener(WindowEventId, Box<dyn Fn(&WindowEvent) + Send>),
  936. // Getters
  937. ScaleFactor(Sender<f64>),
  938. InnerPosition(Sender<Result<PhysicalPosition<i32>>>),
  939. OuterPosition(Sender<Result<PhysicalPosition<i32>>>),
  940. InnerSize(Sender<PhysicalSize<u32>>),
  941. OuterSize(Sender<PhysicalSize<u32>>),
  942. IsFullscreen(Sender<bool>),
  943. IsMinimized(Sender<bool>),
  944. IsMaximized(Sender<bool>),
  945. IsFocused(Sender<bool>),
  946. IsDecorated(Sender<bool>),
  947. IsResizable(Sender<bool>),
  948. IsMaximizable(Sender<bool>),
  949. IsMinimizable(Sender<bool>),
  950. IsClosable(Sender<bool>),
  951. IsVisible(Sender<bool>),
  952. Title(Sender<String>),
  953. CurrentMonitor(Sender<Option<MonitorHandle>>),
  954. PrimaryMonitor(Sender<Option<MonitorHandle>>),
  955. AvailableMonitors(Sender<Vec<MonitorHandle>>),
  956. #[cfg(any(
  957. target_os = "linux",
  958. target_os = "dragonfly",
  959. target_os = "freebsd",
  960. target_os = "netbsd",
  961. target_os = "openbsd"
  962. ))]
  963. GtkWindow(Sender<GtkWindow>),
  964. #[cfg(any(
  965. target_os = "linux",
  966. target_os = "dragonfly",
  967. target_os = "freebsd",
  968. target_os = "netbsd",
  969. target_os = "openbsd"
  970. ))]
  971. GtkBox(Sender<GtkBox>),
  972. RawWindowHandle(Sender<std::result::Result<SendRawWindowHandle, raw_window_handle::HandleError>>),
  973. Theme(Sender<Theme>),
  974. // Setters
  975. Center,
  976. RequestUserAttention(Option<UserAttentionTypeWrapper>),
  977. SetResizable(bool),
  978. SetMaximizable(bool),
  979. SetMinimizable(bool),
  980. SetClosable(bool),
  981. SetTitle(String),
  982. Maximize,
  983. Unmaximize,
  984. Minimize,
  985. Unminimize,
  986. Show,
  987. Hide,
  988. Close,
  989. Destroy,
  990. SetDecorations(bool),
  991. SetShadow(bool),
  992. SetAlwaysOnBottom(bool),
  993. SetAlwaysOnTop(bool),
  994. SetVisibleOnAllWorkspaces(bool),
  995. SetContentProtected(bool),
  996. SetSize(Size),
  997. SetMinSize(Option<Size>),
  998. SetMaxSize(Option<Size>),
  999. SetPosition(Position),
  1000. SetFullscreen(bool),
  1001. SetFocus,
  1002. SetIcon(TaoWindowIcon),
  1003. SetSkipTaskbar(bool),
  1004. SetCursorGrab(bool),
  1005. SetCursorVisible(bool),
  1006. SetCursorIcon(CursorIcon),
  1007. SetCursorPosition(Position),
  1008. SetIgnoreCursorEvents(bool),
  1009. SetProgressBar(ProgressBarState),
  1010. DragWindow,
  1011. ResizeDragWindow(tauri_runtime::ResizeDirection),
  1012. RequestRedraw,
  1013. }
  1014. #[derive(Debug, Clone)]
  1015. pub enum SynthesizedWindowEvent {
  1016. Focused(bool),
  1017. FileDrop(FileDropEvent),
  1018. }
  1019. impl From<SynthesizedWindowEvent> for WindowEventWrapper {
  1020. fn from(event: SynthesizedWindowEvent) -> Self {
  1021. let event = match event {
  1022. SynthesizedWindowEvent::Focused(focused) => WindowEvent::Focused(focused),
  1023. SynthesizedWindowEvent::FileDrop(event) => WindowEvent::FileDrop(event),
  1024. };
  1025. Self(Some(event))
  1026. }
  1027. }
  1028. pub enum WebviewMessage {
  1029. AddEventListener(WebviewEventId, Box<dyn Fn(&WebviewEvent) + Send>),
  1030. #[cfg(not(all(feature = "tracing", not(target_os = "android"))))]
  1031. EvaluateScript(String),
  1032. #[cfg(all(feature = "tracing", not(target_os = "android")))]
  1033. EvaluateScript(String, Sender<()>, tracing::Span),
  1034. WebviewEvent(WebviewEvent),
  1035. SynthesizedWindowEvent(SynthesizedWindowEvent),
  1036. Navigate(Url),
  1037. Print,
  1038. Close,
  1039. SetPosition(Position),
  1040. SetSize(Size),
  1041. SetFocus,
  1042. Reparent(WindowId),
  1043. // Getters
  1044. Url(Sender<Url>),
  1045. Position(Sender<PhysicalPosition<i32>>),
  1046. Size(Sender<PhysicalSize<u32>>),
  1047. WithWebview(Box<dyn FnOnce(Webview) + Send>),
  1048. // Devtools
  1049. #[cfg(any(debug_assertions, feature = "devtools"))]
  1050. OpenDevTools,
  1051. #[cfg(any(debug_assertions, feature = "devtools"))]
  1052. CloseDevTools,
  1053. #[cfg(any(debug_assertions, feature = "devtools"))]
  1054. IsDevToolsOpen(Sender<bool>),
  1055. }
  1056. pub type CreateWindowClosure<T> =
  1057. Box<dyn FnOnce(&EventLoopWindowTarget<Message<T>>) -> Result<WindowWrapper> + Send>;
  1058. pub type CreateWebviewClosure = Box<dyn FnOnce(&Window) -> Result<WebviewWrapper> + Send>;
  1059. pub enum Message<T: 'static> {
  1060. Task(Box<dyn FnOnce() + Send>),
  1061. #[cfg(target_os = "macos")]
  1062. SetActivationPolicy(ActivationPolicy),
  1063. RequestExit(i32),
  1064. #[cfg(target_os = "macos")]
  1065. Application(ApplicationMessage),
  1066. Window(WindowId, WindowMessage),
  1067. Webview(WindowId, WebviewId, WebviewMessage),
  1068. CreateWebview(WindowId, CreateWebviewClosure),
  1069. CreateWindow(WindowId, CreateWindowClosure<T>),
  1070. CreateRawWindow(
  1071. WindowId,
  1072. Box<dyn FnOnce() -> (String, TaoWindowBuilder) + Send>,
  1073. Sender<Result<Weak<Window>>>,
  1074. ),
  1075. UserEvent(T),
  1076. }
  1077. impl<T: UserEvent> Clone for Message<T> {
  1078. fn clone(&self) -> Self {
  1079. match self {
  1080. Self::UserEvent(t) => Self::UserEvent(t.clone()),
  1081. _ => unimplemented!(),
  1082. }
  1083. }
  1084. }
  1085. /// The Tauri [`WebviewDispatch`] for [`Wry`].
  1086. #[derive(Debug, Clone)]
  1087. pub struct WryWebviewDispatcher<T: UserEvent> {
  1088. window_id: Arc<Mutex<WindowId>>,
  1089. webview_id: WebviewId,
  1090. context: Context<T>,
  1091. }
  1092. impl<T: UserEvent> WebviewDispatch<T> for WryWebviewDispatcher<T> {
  1093. type Runtime = Wry<T>;
  1094. fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> Result<()> {
  1095. send_user_message(&self.context, Message::Task(Box::new(f)))
  1096. }
  1097. fn on_webview_event<F: Fn(&WebviewEvent) + Send + 'static>(&self, f: F) -> WindowEventId {
  1098. let id = self.context.next_webview_event_id();
  1099. let _ = self.context.proxy.send_event(Message::Webview(
  1100. *self.window_id.lock().unwrap(),
  1101. self.webview_id,
  1102. WebviewMessage::AddEventListener(id, Box::new(f)),
  1103. ));
  1104. id
  1105. }
  1106. fn with_webview<F: FnOnce(Box<dyn std::any::Any>) + Send + 'static>(&self, f: F) -> Result<()> {
  1107. send_user_message(
  1108. &self.context,
  1109. Message::Webview(
  1110. *self.window_id.lock().unwrap(),
  1111. self.webview_id,
  1112. WebviewMessage::WithWebview(Box::new(move |webview| f(Box::new(webview)))),
  1113. ),
  1114. )
  1115. }
  1116. #[cfg(any(debug_assertions, feature = "devtools"))]
  1117. fn open_devtools(&self) {
  1118. let _ = send_user_message(
  1119. &self.context,
  1120. Message::Webview(
  1121. *self.window_id.lock().unwrap(),
  1122. self.webview_id,
  1123. WebviewMessage::OpenDevTools,
  1124. ),
  1125. );
  1126. }
  1127. #[cfg(any(debug_assertions, feature = "devtools"))]
  1128. fn close_devtools(&self) {
  1129. let _ = send_user_message(
  1130. &self.context,
  1131. Message::Webview(
  1132. *self.window_id.lock().unwrap(),
  1133. self.webview_id,
  1134. WebviewMessage::CloseDevTools,
  1135. ),
  1136. );
  1137. }
  1138. /// Gets the devtools window's current open state.
  1139. #[cfg(any(debug_assertions, feature = "devtools"))]
  1140. fn is_devtools_open(&self) -> Result<bool> {
  1141. webview_getter!(self, WebviewMessage::IsDevToolsOpen)
  1142. }
  1143. // Getters
  1144. fn url(&self) -> Result<Url> {
  1145. webview_getter!(self, WebviewMessage::Url)
  1146. }
  1147. fn position(&self) -> Result<PhysicalPosition<i32>> {
  1148. webview_getter!(self, WebviewMessage::Position)
  1149. }
  1150. fn size(&self) -> Result<PhysicalSize<u32>> {
  1151. webview_getter!(self, WebviewMessage::Size)
  1152. }
  1153. // Setters
  1154. fn navigate(&self, url: Url) -> Result<()> {
  1155. send_user_message(
  1156. &self.context,
  1157. Message::Webview(
  1158. *self.window_id.lock().unwrap(),
  1159. self.webview_id,
  1160. WebviewMessage::Navigate(url),
  1161. ),
  1162. )
  1163. }
  1164. fn print(&self) -> Result<()> {
  1165. send_user_message(
  1166. &self.context,
  1167. Message::Webview(
  1168. *self.window_id.lock().unwrap(),
  1169. self.webview_id,
  1170. WebviewMessage::Print,
  1171. ),
  1172. )
  1173. }
  1174. fn close(&self) -> Result<()> {
  1175. send_user_message(
  1176. &self.context,
  1177. Message::Webview(
  1178. *self.window_id.lock().unwrap(),
  1179. self.webview_id,
  1180. WebviewMessage::Close,
  1181. ),
  1182. )
  1183. }
  1184. fn set_size(&self, size: Size) -> Result<()> {
  1185. send_user_message(
  1186. &self.context,
  1187. Message::Webview(
  1188. *self.window_id.lock().unwrap(),
  1189. self.webview_id,
  1190. WebviewMessage::SetSize(size),
  1191. ),
  1192. )
  1193. }
  1194. fn set_position(&self, position: Position) -> Result<()> {
  1195. send_user_message(
  1196. &self.context,
  1197. Message::Webview(
  1198. *self.window_id.lock().unwrap(),
  1199. self.webview_id,
  1200. WebviewMessage::SetPosition(position),
  1201. ),
  1202. )
  1203. }
  1204. fn set_focus(&self) -> Result<()> {
  1205. send_user_message(
  1206. &self.context,
  1207. Message::Webview(
  1208. *self.window_id.lock().unwrap(),
  1209. self.webview_id,
  1210. WebviewMessage::SetFocus,
  1211. ),
  1212. )
  1213. }
  1214. fn reparent(&self, window_id: WindowId) -> Result<()> {
  1215. let mut current_window_id = self.window_id.lock().unwrap();
  1216. send_user_message(
  1217. &self.context,
  1218. Message::Webview(
  1219. *current_window_id,
  1220. self.webview_id,
  1221. WebviewMessage::Reparent(window_id),
  1222. ),
  1223. )?;
  1224. *current_window_id = window_id;
  1225. Ok(())
  1226. }
  1227. #[cfg(all(feature = "tracing", not(target_os = "android")))]
  1228. fn eval_script<S: Into<String>>(&self, script: S) -> Result<()> {
  1229. // use a channel so the EvaluateScript task uses the current span as parent
  1230. let (tx, rx) = channel();
  1231. getter!(
  1232. self,
  1233. rx,
  1234. Message::Webview(
  1235. *self.window_id.lock().unwrap(),
  1236. self.webview_id,
  1237. WebviewMessage::EvaluateScript(script.into(), tx, tracing::Span::current()),
  1238. )
  1239. )
  1240. }
  1241. #[cfg(not(all(feature = "tracing", not(target_os = "android"))))]
  1242. fn eval_script<S: Into<String>>(&self, script: S) -> Result<()> {
  1243. send_user_message(
  1244. &self.context,
  1245. Message::Webview(
  1246. *self.window_id.lock().unwrap(),
  1247. self.webview_id,
  1248. WebviewMessage::EvaluateScript(script.into()),
  1249. ),
  1250. )
  1251. }
  1252. }
  1253. /// The Tauri [`WindowDispatch`] for [`Wry`].
  1254. #[derive(Debug, Clone)]
  1255. pub struct WryWindowDispatcher<T: UserEvent> {
  1256. window_id: WindowId,
  1257. context: Context<T>,
  1258. }
  1259. // SAFETY: this is safe since the `Context` usage is guarded on `send_user_message`.
  1260. #[allow(clippy::non_send_fields_in_send_ty)]
  1261. unsafe impl<T: UserEvent> Sync for WryWindowDispatcher<T> {}
  1262. fn get_raw_window_handle<T: UserEvent>(
  1263. dispatcher: &WryWindowDispatcher<T>,
  1264. ) -> Result<std::result::Result<SendRawWindowHandle, raw_window_handle::HandleError>> {
  1265. window_getter!(dispatcher, WindowMessage::RawWindowHandle)
  1266. }
  1267. impl<T: UserEvent> WindowDispatch<T> for WryWindowDispatcher<T> {
  1268. type Runtime = Wry<T>;
  1269. type WindowBuilder = WindowBuilderWrapper;
  1270. fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> Result<()> {
  1271. send_user_message(&self.context, Message::Task(Box::new(f)))
  1272. }
  1273. fn on_window_event<F: Fn(&WindowEvent) + Send + 'static>(&self, f: F) -> WindowEventId {
  1274. let id = self.context.next_window_event_id();
  1275. let _ = self.context.proxy.send_event(Message::Window(
  1276. self.window_id,
  1277. WindowMessage::AddEventListener(id, Box::new(f)),
  1278. ));
  1279. id
  1280. }
  1281. // Getters
  1282. fn scale_factor(&self) -> Result<f64> {
  1283. window_getter!(self, WindowMessage::ScaleFactor)
  1284. }
  1285. fn inner_position(&self) -> Result<PhysicalPosition<i32>> {
  1286. window_getter!(self, WindowMessage::InnerPosition)?
  1287. }
  1288. fn outer_position(&self) -> Result<PhysicalPosition<i32>> {
  1289. window_getter!(self, WindowMessage::OuterPosition)?
  1290. }
  1291. fn inner_size(&self) -> Result<PhysicalSize<u32>> {
  1292. window_getter!(self, WindowMessage::InnerSize)
  1293. }
  1294. fn outer_size(&self) -> Result<PhysicalSize<u32>> {
  1295. window_getter!(self, WindowMessage::OuterSize)
  1296. }
  1297. fn is_fullscreen(&self) -> Result<bool> {
  1298. window_getter!(self, WindowMessage::IsFullscreen)
  1299. }
  1300. fn is_minimized(&self) -> Result<bool> {
  1301. window_getter!(self, WindowMessage::IsMinimized)
  1302. }
  1303. fn is_maximized(&self) -> Result<bool> {
  1304. window_getter!(self, WindowMessage::IsMaximized)
  1305. }
  1306. fn is_focused(&self) -> Result<bool> {
  1307. window_getter!(self, WindowMessage::IsFocused)
  1308. }
  1309. /// Gets the window’s current decoration state.
  1310. fn is_decorated(&self) -> Result<bool> {
  1311. window_getter!(self, WindowMessage::IsDecorated)
  1312. }
  1313. /// Gets the window’s current resizable state.
  1314. fn is_resizable(&self) -> Result<bool> {
  1315. window_getter!(self, WindowMessage::IsResizable)
  1316. }
  1317. /// Gets the current native window's maximize button state
  1318. fn is_maximizable(&self) -> Result<bool> {
  1319. window_getter!(self, WindowMessage::IsMaximizable)
  1320. }
  1321. /// Gets the current native window's minimize button state
  1322. fn is_minimizable(&self) -> Result<bool> {
  1323. window_getter!(self, WindowMessage::IsMinimizable)
  1324. }
  1325. /// Gets the current native window's close button state
  1326. fn is_closable(&self) -> Result<bool> {
  1327. window_getter!(self, WindowMessage::IsClosable)
  1328. }
  1329. fn is_visible(&self) -> Result<bool> {
  1330. window_getter!(self, WindowMessage::IsVisible)
  1331. }
  1332. fn title(&self) -> Result<String> {
  1333. window_getter!(self, WindowMessage::Title)
  1334. }
  1335. fn current_monitor(&self) -> Result<Option<Monitor>> {
  1336. Ok(window_getter!(self, WindowMessage::CurrentMonitor)?.map(|m| MonitorHandleWrapper(m).into()))
  1337. }
  1338. fn primary_monitor(&self) -> Result<Option<Monitor>> {
  1339. Ok(window_getter!(self, WindowMessage::PrimaryMonitor)?.map(|m| MonitorHandleWrapper(m).into()))
  1340. }
  1341. fn available_monitors(&self) -> Result<Vec<Monitor>> {
  1342. Ok(
  1343. window_getter!(self, WindowMessage::AvailableMonitors)?
  1344. .into_iter()
  1345. .map(|m| MonitorHandleWrapper(m).into())
  1346. .collect(),
  1347. )
  1348. }
  1349. fn theme(&self) -> Result<Theme> {
  1350. window_getter!(self, WindowMessage::Theme)
  1351. }
  1352. #[cfg(any(
  1353. target_os = "linux",
  1354. target_os = "dragonfly",
  1355. target_os = "freebsd",
  1356. target_os = "netbsd",
  1357. target_os = "openbsd"
  1358. ))]
  1359. fn gtk_window(&self) -> Result<gtk::ApplicationWindow> {
  1360. window_getter!(self, WindowMessage::GtkWindow).map(|w| w.0)
  1361. }
  1362. #[cfg(any(
  1363. target_os = "linux",
  1364. target_os = "dragonfly",
  1365. target_os = "freebsd",
  1366. target_os = "netbsd",
  1367. target_os = "openbsd"
  1368. ))]
  1369. fn default_vbox(&self) -> Result<gtk::Box> {
  1370. window_getter!(self, WindowMessage::GtkBox).map(|w| w.0)
  1371. }
  1372. fn window_handle(
  1373. &self,
  1374. ) -> std::result::Result<raw_window_handle::WindowHandle<'_>, raw_window_handle::HandleError> {
  1375. get_raw_window_handle(self)
  1376. .map_err(|_| raw_window_handle::HandleError::Unavailable)
  1377. .and_then(|r| r.map(|h| unsafe { raw_window_handle::WindowHandle::borrow_raw(h.0) }))
  1378. }
  1379. // Setters
  1380. fn center(&self) -> Result<()> {
  1381. send_user_message(
  1382. &self.context,
  1383. Message::Window(self.window_id, WindowMessage::Center),
  1384. )
  1385. }
  1386. fn request_user_attention(&self, request_type: Option<UserAttentionType>) -> Result<()> {
  1387. send_user_message(
  1388. &self.context,
  1389. Message::Window(
  1390. self.window_id,
  1391. WindowMessage::RequestUserAttention(request_type.map(Into::into)),
  1392. ),
  1393. )
  1394. }
  1395. // Creates a window by dispatching a message to the event loop.
  1396. // Note that this must be called from a separate thread, otherwise the channel will introduce a deadlock.
  1397. fn create_window<F: Fn(RawWindow) + Send + 'static>(
  1398. &mut self,
  1399. pending: PendingWindow<T, Self::Runtime>,
  1400. after_window_creation: Option<F>,
  1401. ) -> Result<DetachedWindow<T, Self::Runtime>> {
  1402. self.context.create_window(pending, after_window_creation)
  1403. }
  1404. // Creates a webview by dispatching a message to the event loop.
  1405. // Note that this must be called from a separate thread, otherwise the channel will introduce a deadlock.
  1406. fn create_webview(
  1407. &mut self,
  1408. pending: PendingWebview<T, Self::Runtime>,
  1409. ) -> Result<DetachedWebview<T, Self::Runtime>> {
  1410. self.context.create_webview(self.window_id, pending)
  1411. }
  1412. fn set_resizable(&self, resizable: bool) -> Result<()> {
  1413. send_user_message(
  1414. &self.context,
  1415. Message::Window(self.window_id, WindowMessage::SetResizable(resizable)),
  1416. )
  1417. }
  1418. fn set_maximizable(&self, maximizable: bool) -> Result<()> {
  1419. send_user_message(
  1420. &self.context,
  1421. Message::Window(self.window_id, WindowMessage::SetMaximizable(maximizable)),
  1422. )
  1423. }
  1424. fn set_minimizable(&self, minimizable: bool) -> Result<()> {
  1425. send_user_message(
  1426. &self.context,
  1427. Message::Window(self.window_id, WindowMessage::SetMinimizable(minimizable)),
  1428. )
  1429. }
  1430. fn set_closable(&self, closable: bool) -> Result<()> {
  1431. send_user_message(
  1432. &self.context,
  1433. Message::Window(self.window_id, WindowMessage::SetClosable(closable)),
  1434. )
  1435. }
  1436. fn set_title<S: Into<String>>(&self, title: S) -> Result<()> {
  1437. send_user_message(
  1438. &self.context,
  1439. Message::Window(self.window_id, WindowMessage::SetTitle(title.into())),
  1440. )
  1441. }
  1442. fn maximize(&self) -> Result<()> {
  1443. send_user_message(
  1444. &self.context,
  1445. Message::Window(self.window_id, WindowMessage::Maximize),
  1446. )
  1447. }
  1448. fn unmaximize(&self) -> Result<()> {
  1449. send_user_message(
  1450. &self.context,
  1451. Message::Window(self.window_id, WindowMessage::Unmaximize),
  1452. )
  1453. }
  1454. fn minimize(&self) -> Result<()> {
  1455. send_user_message(
  1456. &self.context,
  1457. Message::Window(self.window_id, WindowMessage::Minimize),
  1458. )
  1459. }
  1460. fn unminimize(&self) -> Result<()> {
  1461. send_user_message(
  1462. &self.context,
  1463. Message::Window(self.window_id, WindowMessage::Unminimize),
  1464. )
  1465. }
  1466. fn show(&self) -> Result<()> {
  1467. send_user_message(
  1468. &self.context,
  1469. Message::Window(self.window_id, WindowMessage::Show),
  1470. )
  1471. }
  1472. fn hide(&self) -> Result<()> {
  1473. send_user_message(
  1474. &self.context,
  1475. Message::Window(self.window_id, WindowMessage::Hide),
  1476. )
  1477. }
  1478. fn close(&self) -> Result<()> {
  1479. // NOTE: close cannot use the `send_user_message` function because it accesses the event loop callback
  1480. self
  1481. .context
  1482. .proxy
  1483. .send_event(Message::Window(self.window_id, WindowMessage::Close))
  1484. .map_err(|_| Error::FailedToSendMessage)
  1485. }
  1486. fn destroy(&self) -> Result<()> {
  1487. // NOTE: destroy cannot use the `send_user_message` function because it accesses the event loop callback
  1488. self
  1489. .context
  1490. .proxy
  1491. .send_event(Message::Window(self.window_id, WindowMessage::Destroy))
  1492. .map_err(|_| Error::FailedToSendMessage)
  1493. }
  1494. fn set_decorations(&self, decorations: bool) -> Result<()> {
  1495. send_user_message(
  1496. &self.context,
  1497. Message::Window(self.window_id, WindowMessage::SetDecorations(decorations)),
  1498. )
  1499. }
  1500. fn set_shadow(&self, enable: bool) -> Result<()> {
  1501. send_user_message(
  1502. &self.context,
  1503. Message::Window(self.window_id, WindowMessage::SetShadow(enable)),
  1504. )
  1505. }
  1506. fn set_always_on_bottom(&self, always_on_bottom: bool) -> Result<()> {
  1507. send_user_message(
  1508. &self.context,
  1509. Message::Window(
  1510. self.window_id,
  1511. WindowMessage::SetAlwaysOnBottom(always_on_bottom),
  1512. ),
  1513. )
  1514. }
  1515. fn set_always_on_top(&self, always_on_top: bool) -> Result<()> {
  1516. send_user_message(
  1517. &self.context,
  1518. Message::Window(self.window_id, WindowMessage::SetAlwaysOnTop(always_on_top)),
  1519. )
  1520. }
  1521. fn set_visible_on_all_workspaces(&self, visible_on_all_workspaces: bool) -> Result<()> {
  1522. send_user_message(
  1523. &self.context,
  1524. Message::Window(
  1525. self.window_id,
  1526. WindowMessage::SetVisibleOnAllWorkspaces(visible_on_all_workspaces),
  1527. ),
  1528. )
  1529. }
  1530. fn set_content_protected(&self, protected: bool) -> Result<()> {
  1531. send_user_message(
  1532. &self.context,
  1533. Message::Window(
  1534. self.window_id,
  1535. WindowMessage::SetContentProtected(protected),
  1536. ),
  1537. )
  1538. }
  1539. fn set_size(&self, size: Size) -> Result<()> {
  1540. send_user_message(
  1541. &self.context,
  1542. Message::Window(self.window_id, WindowMessage::SetSize(size)),
  1543. )
  1544. }
  1545. fn set_min_size(&self, size: Option<Size>) -> Result<()> {
  1546. send_user_message(
  1547. &self.context,
  1548. Message::Window(self.window_id, WindowMessage::SetMinSize(size)),
  1549. )
  1550. }
  1551. fn set_max_size(&self, size: Option<Size>) -> Result<()> {
  1552. send_user_message(
  1553. &self.context,
  1554. Message::Window(self.window_id, WindowMessage::SetMaxSize(size)),
  1555. )
  1556. }
  1557. fn set_position(&self, position: Position) -> Result<()> {
  1558. send_user_message(
  1559. &self.context,
  1560. Message::Window(self.window_id, WindowMessage::SetPosition(position)),
  1561. )
  1562. }
  1563. fn set_fullscreen(&self, fullscreen: bool) -> Result<()> {
  1564. send_user_message(
  1565. &self.context,
  1566. Message::Window(self.window_id, WindowMessage::SetFullscreen(fullscreen)),
  1567. )
  1568. }
  1569. fn set_focus(&self) -> Result<()> {
  1570. send_user_message(
  1571. &self.context,
  1572. Message::Window(self.window_id, WindowMessage::SetFocus),
  1573. )
  1574. }
  1575. fn set_icon(&self, icon: Icon) -> Result<()> {
  1576. send_user_message(
  1577. &self.context,
  1578. Message::Window(
  1579. self.window_id,
  1580. WindowMessage::SetIcon(TaoIcon::try_from(icon)?.0),
  1581. ),
  1582. )
  1583. }
  1584. fn set_skip_taskbar(&self, skip: bool) -> Result<()> {
  1585. send_user_message(
  1586. &self.context,
  1587. Message::Window(self.window_id, WindowMessage::SetSkipTaskbar(skip)),
  1588. )
  1589. }
  1590. fn set_cursor_grab(&self, grab: bool) -> crate::Result<()> {
  1591. send_user_message(
  1592. &self.context,
  1593. Message::Window(self.window_id, WindowMessage::SetCursorGrab(grab)),
  1594. )
  1595. }
  1596. fn set_cursor_visible(&self, visible: bool) -> crate::Result<()> {
  1597. send_user_message(
  1598. &self.context,
  1599. Message::Window(self.window_id, WindowMessage::SetCursorVisible(visible)),
  1600. )
  1601. }
  1602. fn set_cursor_icon(&self, icon: CursorIcon) -> crate::Result<()> {
  1603. send_user_message(
  1604. &self.context,
  1605. Message::Window(self.window_id, WindowMessage::SetCursorIcon(icon)),
  1606. )
  1607. }
  1608. fn set_cursor_position<Pos: Into<Position>>(&self, position: Pos) -> crate::Result<()> {
  1609. send_user_message(
  1610. &self.context,
  1611. Message::Window(
  1612. self.window_id,
  1613. WindowMessage::SetCursorPosition(position.into()),
  1614. ),
  1615. )
  1616. }
  1617. fn set_ignore_cursor_events(&self, ignore: bool) -> crate::Result<()> {
  1618. send_user_message(
  1619. &self.context,
  1620. Message::Window(self.window_id, WindowMessage::SetIgnoreCursorEvents(ignore)),
  1621. )
  1622. }
  1623. fn start_dragging(&self) -> Result<()> {
  1624. send_user_message(
  1625. &self.context,
  1626. Message::Window(self.window_id, WindowMessage::DragWindow),
  1627. )
  1628. }
  1629. fn start_resize_dragging(&self, direction: tauri_runtime::ResizeDirection) -> Result<()> {
  1630. send_user_message(
  1631. &self.context,
  1632. Message::Window(self.window_id, WindowMessage::ResizeDragWindow(direction)),
  1633. )
  1634. }
  1635. fn set_progress_bar(&self, progress_state: ProgressBarState) -> Result<()> {
  1636. send_user_message(
  1637. &self.context,
  1638. Message::Window(
  1639. self.window_id,
  1640. WindowMessage::SetProgressBar(progress_state),
  1641. ),
  1642. )
  1643. }
  1644. }
  1645. #[derive(Clone)]
  1646. pub struct WebviewWrapper {
  1647. label: String,
  1648. id: WebviewId,
  1649. inner: Rc<WebView>,
  1650. context_store: WebContextStore,
  1651. webview_event_listeners: WebviewEventListeners,
  1652. // the key of the WebContext if it's not shared
  1653. context_key: Option<PathBuf>,
  1654. bounds: Option<Arc<Mutex<WebviewBounds>>>,
  1655. }
  1656. impl Deref for WebviewWrapper {
  1657. type Target = WebView;
  1658. #[inline(always)]
  1659. fn deref(&self) -> &Self::Target {
  1660. &self.inner
  1661. }
  1662. }
  1663. impl Drop for WebviewWrapper {
  1664. fn drop(&mut self) {
  1665. if Rc::get_mut(&mut self.inner).is_some() {
  1666. self.context_store.lock().unwrap().remove(&self.context_key);
  1667. }
  1668. }
  1669. }
  1670. pub struct WindowWrapper {
  1671. label: String,
  1672. inner: Option<Arc<Window>>,
  1673. // whether this window has child webviews
  1674. // or it's just a container for a single webview
  1675. has_children: AtomicBool,
  1676. webviews: Vec<WebviewWrapper>,
  1677. window_event_listeners: WindowEventListeners,
  1678. #[cfg(windows)]
  1679. is_window_fullscreen: bool,
  1680. #[cfg(windows)]
  1681. is_window_transparent: bool,
  1682. #[cfg(windows)]
  1683. surface: Option<softbuffer::Surface<Arc<Window>, Arc<Window>>>,
  1684. }
  1685. impl fmt::Debug for WindowWrapper {
  1686. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  1687. f.debug_struct("WindowWrapper")
  1688. .field("label", &self.label)
  1689. .field("inner", &self.inner)
  1690. .finish()
  1691. }
  1692. }
  1693. #[derive(Debug, Clone)]
  1694. pub struct EventProxy<T: UserEvent>(TaoEventLoopProxy<Message<T>>);
  1695. #[cfg(target_os = "ios")]
  1696. #[allow(clippy::non_send_fields_in_send_ty)]
  1697. unsafe impl<T: UserEvent> Sync for EventProxy<T> {}
  1698. impl<T: UserEvent> EventLoopProxy<T> for EventProxy<T> {
  1699. fn send_event(&self, event: T) -> Result<()> {
  1700. self
  1701. .0
  1702. .send_event(Message::UserEvent(event))
  1703. .map_err(|_| Error::EventLoopClosed)
  1704. }
  1705. }
  1706. pub trait PluginBuilder<T: UserEvent> {
  1707. type Plugin: Plugin<T>;
  1708. fn build(self, context: Context<T>) -> Self::Plugin;
  1709. }
  1710. pub trait Plugin<T: UserEvent> {
  1711. fn on_event(
  1712. &mut self,
  1713. event: &Event<Message<T>>,
  1714. event_loop: &EventLoopWindowTarget<Message<T>>,
  1715. proxy: &TaoEventLoopProxy<Message<T>>,
  1716. control_flow: &mut ControlFlow,
  1717. context: EventLoopIterationContext<'_, T>,
  1718. web_context: &WebContextStore,
  1719. ) -> bool;
  1720. }
  1721. /// A Tauri [`Runtime`] wrapper around wry.
  1722. pub struct Wry<T: UserEvent> {
  1723. context: Context<T>,
  1724. event_loop: EventLoop<Message<T>>,
  1725. }
  1726. impl<T: UserEvent> fmt::Debug for Wry<T> {
  1727. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  1728. f.debug_struct("Wry")
  1729. .field("main_thread_id", &self.context.main_thread_id)
  1730. .field("event_loop", &self.event_loop)
  1731. .field("windows", &self.context.main_thread.windows)
  1732. .field("web_context", &self.context.main_thread.web_context)
  1733. .finish()
  1734. }
  1735. }
  1736. /// A handle to the Wry runtime.
  1737. #[derive(Debug, Clone)]
  1738. pub struct WryHandle<T: UserEvent> {
  1739. context: Context<T>,
  1740. }
  1741. // SAFETY: this is safe since the `Context` usage is guarded on `send_user_message`.
  1742. #[allow(clippy::non_send_fields_in_send_ty)]
  1743. unsafe impl<T: UserEvent> Sync for WryHandle<T> {}
  1744. impl<T: UserEvent> WryHandle<T> {
  1745. /// Creates a new tao window using a callback, and returns its window id.
  1746. pub fn create_tao_window<F: FnOnce() -> (String, TaoWindowBuilder) + Send + 'static>(
  1747. &self,
  1748. f: F,
  1749. ) -> Result<Weak<Window>> {
  1750. let id = self.context.next_window_id();
  1751. let (tx, rx) = channel();
  1752. send_user_message(&self.context, Message::CreateRawWindow(id, Box::new(f), tx))?;
  1753. rx.recv().unwrap()
  1754. }
  1755. /// Gets the [`WebviewId'] associated with the given [`WindowId`].
  1756. pub fn window_id(&self, window_id: TaoWindowId) -> WindowId {
  1757. *self
  1758. .context
  1759. .window_id_map
  1760. .0
  1761. .lock()
  1762. .unwrap()
  1763. .get(&window_id)
  1764. .unwrap()
  1765. }
  1766. /// Send a message to the event loop.
  1767. pub fn send_event(&self, message: Message<T>) -> Result<()> {
  1768. self
  1769. .context
  1770. .proxy
  1771. .send_event(message)
  1772. .map_err(|_| Error::FailedToSendMessage)?;
  1773. Ok(())
  1774. }
  1775. pub fn plugin<P: PluginBuilder<T> + 'static>(&mut self, plugin: P)
  1776. where
  1777. <P as PluginBuilder<T>>::Plugin: Send,
  1778. {
  1779. self
  1780. .context
  1781. .plugins
  1782. .lock()
  1783. .unwrap()
  1784. .push(Box::new(plugin.build(self.context.clone())));
  1785. }
  1786. }
  1787. impl<T: UserEvent> RuntimeHandle<T> for WryHandle<T> {
  1788. type Runtime = Wry<T>;
  1789. fn create_proxy(&self) -> EventProxy<T> {
  1790. EventProxy(self.context.proxy.clone())
  1791. }
  1792. #[cfg(target_os = "macos")]
  1793. fn set_activation_policy(&self, activation_policy: ActivationPolicy) -> Result<()> {
  1794. send_user_message(
  1795. &self.context,
  1796. Message::SetActivationPolicy(activation_policy),
  1797. )
  1798. }
  1799. fn request_exit(&self, code: i32) -> Result<()> {
  1800. // NOTE: request_exit cannot use the `send_user_message` function because it accesses the event loop callback
  1801. self
  1802. .context
  1803. .proxy
  1804. .send_event(Message::RequestExit(code))
  1805. .map_err(|_| Error::FailedToSendMessage)
  1806. }
  1807. // Creates a window by dispatching a message to the event loop.
  1808. // Note that this must be called from a separate thread, otherwise the channel will introduce a deadlock.
  1809. fn create_window<F: Fn(RawWindow) + Send + 'static>(
  1810. &self,
  1811. pending: PendingWindow<T, Self::Runtime>,
  1812. after_window_creation: Option<F>,
  1813. ) -> Result<DetachedWindow<T, Self::Runtime>> {
  1814. self.context.create_window(pending, after_window_creation)
  1815. }
  1816. // Creates a webview by dispatching a message to the event loop.
  1817. // Note that this must be called from a separate thread, otherwise the channel will introduce a deadlock.
  1818. fn create_webview(
  1819. &self,
  1820. window_id: WindowId,
  1821. pending: PendingWebview<T, Self::Runtime>,
  1822. ) -> Result<DetachedWebview<T, Self::Runtime>> {
  1823. self.context.create_webview(window_id, pending)
  1824. }
  1825. fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> Result<()> {
  1826. send_user_message(&self.context, Message::Task(Box::new(f)))
  1827. }
  1828. fn display_handle(&self) -> std::result::Result<DisplayHandle, raw_window_handle::HandleError> {
  1829. self.context.main_thread.window_target.display_handle()
  1830. }
  1831. fn primary_monitor(&self) -> Option<Monitor> {
  1832. self
  1833. .context
  1834. .main_thread
  1835. .window_target
  1836. .primary_monitor()
  1837. .map(|m| MonitorHandleWrapper(m).into())
  1838. }
  1839. fn available_monitors(&self) -> Vec<Monitor> {
  1840. self
  1841. .context
  1842. .main_thread
  1843. .window_target
  1844. .available_monitors()
  1845. .map(|m| MonitorHandleWrapper(m).into())
  1846. .collect()
  1847. }
  1848. #[cfg(target_os = "macos")]
  1849. fn show(&self) -> tauri_runtime::Result<()> {
  1850. send_user_message(
  1851. &self.context,
  1852. Message::Application(ApplicationMessage::Show),
  1853. )
  1854. }
  1855. #[cfg(target_os = "macos")]
  1856. fn hide(&self) -> tauri_runtime::Result<()> {
  1857. send_user_message(
  1858. &self.context,
  1859. Message::Application(ApplicationMessage::Hide),
  1860. )
  1861. }
  1862. #[cfg(target_os = "android")]
  1863. fn find_class<'a>(
  1864. &self,
  1865. env: &mut jni::JNIEnv<'a>,
  1866. activity: &jni::objects::JObject<'_>,
  1867. name: impl Into<String>,
  1868. ) -> std::result::Result<jni::objects::JClass<'a>, jni::errors::Error> {
  1869. find_class(env, activity, name.into())
  1870. }
  1871. #[cfg(target_os = "android")]
  1872. fn run_on_android_context<F>(&self, f: F)
  1873. where
  1874. F: FnOnce(&mut jni::JNIEnv, &jni::objects::JObject, &jni::objects::JObject) + Send + 'static,
  1875. {
  1876. dispatch(f)
  1877. }
  1878. }
  1879. impl<T: UserEvent> Wry<T> {
  1880. fn init_with_builder(
  1881. mut event_loop_builder: EventLoopBuilder<Message<T>>,
  1882. #[allow(unused_variables)] args: RuntimeInitArgs,
  1883. ) -> Result<Self> {
  1884. #[cfg(windows)]
  1885. if let Some(hook) = args.msg_hook {
  1886. use tao::platform::windows::EventLoopBuilderExtWindows;
  1887. event_loop_builder.with_msg_hook(hook);
  1888. }
  1889. Self::init(event_loop_builder.build())
  1890. }
  1891. fn init(event_loop: EventLoop<Message<T>>) -> Result<Self> {
  1892. let main_thread_id = current_thread().id();
  1893. let web_context = WebContextStore::default();
  1894. let windows = Arc::new(WindowsStore(RefCell::new(BTreeMap::default())));
  1895. let window_id_map = WindowIdStore::default();
  1896. let context = Context {
  1897. window_id_map,
  1898. main_thread_id,
  1899. proxy: event_loop.create_proxy(),
  1900. main_thread: DispatcherMainThreadContext {
  1901. window_target: event_loop.deref().clone(),
  1902. web_context,
  1903. windows,
  1904. #[cfg(feature = "tracing")]
  1905. active_tracing_spans: Default::default(),
  1906. },
  1907. plugins: Default::default(),
  1908. next_window_id: Default::default(),
  1909. next_webview_id: Default::default(),
  1910. next_window_event_id: Default::default(),
  1911. next_webview_event_id: Default::default(),
  1912. next_webcontext_id: Default::default(),
  1913. };
  1914. Ok(Self {
  1915. context,
  1916. event_loop,
  1917. })
  1918. }
  1919. }
  1920. impl<T: UserEvent> Runtime<T> for Wry<T> {
  1921. type WindowDispatcher = WryWindowDispatcher<T>;
  1922. type WebviewDispatcher = WryWebviewDispatcher<T>;
  1923. type Handle = WryHandle<T>;
  1924. type EventLoopProxy = EventProxy<T>;
  1925. fn new(args: RuntimeInitArgs) -> Result<Self> {
  1926. Self::init_with_builder(EventLoopBuilder::<Message<T>>::with_user_event(), args)
  1927. }
  1928. #[cfg(any(
  1929. target_os = "linux",
  1930. target_os = "dragonfly",
  1931. target_os = "freebsd",
  1932. target_os = "netbsd",
  1933. target_os = "openbsd"
  1934. ))]
  1935. fn new_any_thread(args: RuntimeInitArgs) -> Result<Self> {
  1936. use tao::platform::unix::EventLoopBuilderExtUnix;
  1937. let mut event_loop_builder = EventLoopBuilder::<Message<T>>::with_user_event();
  1938. event_loop_builder.with_any_thread(true);
  1939. Self::init_with_builder(event_loop_builder, args)
  1940. }
  1941. #[cfg(windows)]
  1942. fn new_any_thread(args: RuntimeInitArgs) -> Result<Self> {
  1943. use tao::platform::windows::EventLoopBuilderExtWindows;
  1944. let mut event_loop_builder = EventLoopBuilder::<Message<T>>::with_user_event();
  1945. event_loop_builder.with_any_thread(true);
  1946. Self::init_with_builder(event_loop_builder, args)
  1947. }
  1948. fn create_proxy(&self) -> EventProxy<T> {
  1949. EventProxy(self.event_loop.create_proxy())
  1950. }
  1951. fn handle(&self) -> Self::Handle {
  1952. WryHandle {
  1953. context: self.context.clone(),
  1954. }
  1955. }
  1956. fn create_window<F: Fn(RawWindow) + Send + 'static>(
  1957. &self,
  1958. pending: PendingWindow<T, Self>,
  1959. after_window_creation: Option<F>,
  1960. ) -> Result<DetachedWindow<T, Self>> {
  1961. let label = pending.label.clone();
  1962. let window_id = self.context.next_window_id();
  1963. let webview_id = pending
  1964. .webview
  1965. .as_ref()
  1966. .map(|_| self.context.next_webview_id());
  1967. let window = create_window(
  1968. window_id,
  1969. webview_id.unwrap_or_default(),
  1970. &self.event_loop,
  1971. &self.context,
  1972. pending,
  1973. after_window_creation,
  1974. )?;
  1975. let dispatcher = WryWindowDispatcher {
  1976. window_id,
  1977. context: self.context.clone(),
  1978. };
  1979. self
  1980. .context
  1981. .main_thread
  1982. .windows
  1983. .0
  1984. .borrow_mut()
  1985. .insert(window_id, window);
  1986. let detached_webview = webview_id.map(|id| DetachedWebview {
  1987. label: label.clone(),
  1988. dispatcher: WryWebviewDispatcher {
  1989. window_id: Arc::new(Mutex::new(window_id)),
  1990. webview_id: id,
  1991. context: self.context.clone(),
  1992. },
  1993. });
  1994. Ok(DetachedWindow {
  1995. id: window_id,
  1996. label,
  1997. dispatcher,
  1998. webview: detached_webview,
  1999. })
  2000. }
  2001. fn create_webview(
  2002. &self,
  2003. window_id: WindowId,
  2004. pending: PendingWebview<T, Self>,
  2005. ) -> Result<DetachedWebview<T, Self>> {
  2006. let label = pending.label.clone();
  2007. let window = self
  2008. .context
  2009. .main_thread
  2010. .windows
  2011. .0
  2012. .borrow()
  2013. .get(&window_id)
  2014. .and_then(|w| w.inner.clone());
  2015. if let Some(window) = window {
  2016. let window_id_wrapper = Arc::new(Mutex::new(window_id));
  2017. let webview_id = self.context.next_webview_id();
  2018. let webview = create_webview(
  2019. WebviewKind::WindowChild,
  2020. &window,
  2021. window_id_wrapper.clone(),
  2022. webview_id,
  2023. &self.context,
  2024. pending,
  2025. )?;
  2026. self
  2027. .context
  2028. .main_thread
  2029. .windows
  2030. .0
  2031. .borrow_mut()
  2032. .get_mut(&window_id)
  2033. .map(|w| {
  2034. w.webviews.push(webview);
  2035. w.has_children.store(true, Ordering::Relaxed);
  2036. w
  2037. });
  2038. let dispatcher = WryWebviewDispatcher {
  2039. window_id: window_id_wrapper,
  2040. webview_id,
  2041. context: self.context.clone(),
  2042. };
  2043. Ok(DetachedWebview { label, dispatcher })
  2044. } else {
  2045. Err(Error::WindowNotFound)
  2046. }
  2047. }
  2048. fn primary_monitor(&self) -> Option<Monitor> {
  2049. self
  2050. .context
  2051. .main_thread
  2052. .window_target
  2053. .primary_monitor()
  2054. .map(|m| MonitorHandleWrapper(m).into())
  2055. }
  2056. fn available_monitors(&self) -> Vec<Monitor> {
  2057. self
  2058. .context
  2059. .main_thread
  2060. .window_target
  2061. .available_monitors()
  2062. .map(|m| MonitorHandleWrapper(m).into())
  2063. .collect()
  2064. }
  2065. #[cfg(target_os = "macos")]
  2066. fn set_activation_policy(&mut self, activation_policy: ActivationPolicy) {
  2067. self
  2068. .event_loop
  2069. .set_activation_policy(tao_activation_policy(activation_policy));
  2070. }
  2071. #[cfg(target_os = "macos")]
  2072. fn show(&self) {
  2073. self.event_loop.show_application();
  2074. }
  2075. #[cfg(target_os = "macos")]
  2076. fn hide(&self) {
  2077. self.event_loop.hide_application();
  2078. }
  2079. fn set_device_event_filter(&mut self, filter: DeviceEventFilter) {
  2080. self
  2081. .event_loop
  2082. .set_device_event_filter(DeviceEventFilterWrapper::from(filter).0);
  2083. }
  2084. #[cfg(desktop)]
  2085. fn run_iteration<F: FnMut(RunEvent<T>) + 'static>(&mut self, mut callback: F) {
  2086. use tao::platform::run_return::EventLoopExtRunReturn;
  2087. let windows = self.context.main_thread.windows.clone();
  2088. let window_id_map = self.context.window_id_map.clone();
  2089. let web_context = &self.context.main_thread.web_context;
  2090. let plugins = self.context.plugins.clone();
  2091. #[cfg(feature = "tracing")]
  2092. let active_tracing_spans = self.context.main_thread.active_tracing_spans.clone();
  2093. let proxy = self.event_loop.create_proxy();
  2094. self
  2095. .event_loop
  2096. .run_return(|event, event_loop, control_flow| {
  2097. *control_flow = ControlFlow::Wait;
  2098. if let Event::MainEventsCleared = &event {
  2099. *control_flow = ControlFlow::Exit;
  2100. }
  2101. for p in plugins.lock().unwrap().iter_mut() {
  2102. let prevent_default = p.on_event(
  2103. &event,
  2104. event_loop,
  2105. &proxy,
  2106. control_flow,
  2107. EventLoopIterationContext {
  2108. callback: &mut callback,
  2109. window_id_map: window_id_map.clone(),
  2110. windows: windows.clone(),
  2111. #[cfg(feature = "tracing")]
  2112. active_tracing_spans: active_tracing_spans.clone(),
  2113. },
  2114. web_context,
  2115. );
  2116. if prevent_default {
  2117. return;
  2118. }
  2119. }
  2120. handle_event_loop(
  2121. event,
  2122. event_loop,
  2123. control_flow,
  2124. EventLoopIterationContext {
  2125. callback: &mut callback,
  2126. windows: windows.clone(),
  2127. window_id_map: window_id_map.clone(),
  2128. #[cfg(feature = "tracing")]
  2129. active_tracing_spans: active_tracing_spans.clone(),
  2130. },
  2131. );
  2132. });
  2133. }
  2134. fn run<F: FnMut(RunEvent<T>) + 'static>(self, mut callback: F) {
  2135. let windows = self.context.main_thread.windows.clone();
  2136. let window_id_map = self.context.window_id_map.clone();
  2137. let web_context = self.context.main_thread.web_context;
  2138. let plugins = self.context.plugins.clone();
  2139. #[cfg(feature = "tracing")]
  2140. let active_tracing_spans = self.context.main_thread.active_tracing_spans.clone();
  2141. let proxy = self.event_loop.create_proxy();
  2142. self.event_loop.run(move |event, event_loop, control_flow| {
  2143. for p in plugins.lock().unwrap().iter_mut() {
  2144. let prevent_default = p.on_event(
  2145. &event,
  2146. event_loop,
  2147. &proxy,
  2148. control_flow,
  2149. EventLoopIterationContext {
  2150. callback: &mut callback,
  2151. window_id_map: window_id_map.clone(),
  2152. windows: windows.clone(),
  2153. #[cfg(feature = "tracing")]
  2154. active_tracing_spans: active_tracing_spans.clone(),
  2155. },
  2156. &web_context,
  2157. );
  2158. if prevent_default {
  2159. return;
  2160. }
  2161. }
  2162. handle_event_loop(
  2163. event,
  2164. event_loop,
  2165. control_flow,
  2166. EventLoopIterationContext {
  2167. callback: &mut callback,
  2168. window_id_map: window_id_map.clone(),
  2169. windows: windows.clone(),
  2170. #[cfg(feature = "tracing")]
  2171. active_tracing_spans: active_tracing_spans.clone(),
  2172. },
  2173. );
  2174. })
  2175. }
  2176. }
  2177. pub struct EventLoopIterationContext<'a, T: UserEvent> {
  2178. pub callback: &'a mut (dyn FnMut(RunEvent<T>) + 'static),
  2179. pub window_id_map: WindowIdStore,
  2180. pub windows: Arc<WindowsStore>,
  2181. #[cfg(feature = "tracing")]
  2182. pub active_tracing_spans: ActiveTraceSpanStore,
  2183. }
  2184. struct UserMessageContext {
  2185. windows: Arc<WindowsStore>,
  2186. window_id_map: WindowIdStore,
  2187. }
  2188. fn handle_user_message<T: UserEvent>(
  2189. event_loop: &EventLoopWindowTarget<Message<T>>,
  2190. message: Message<T>,
  2191. context: UserMessageContext,
  2192. ) {
  2193. let UserMessageContext {
  2194. window_id_map,
  2195. windows,
  2196. } = context;
  2197. match message {
  2198. Message::Task(task) => task(),
  2199. #[cfg(target_os = "macos")]
  2200. Message::SetActivationPolicy(activation_policy) => {
  2201. event_loop.set_activation_policy_at_runtime(tao_activation_policy(activation_policy))
  2202. }
  2203. Message::RequestExit(_code) => panic!("cannot handle RequestExit on the main thread"),
  2204. #[cfg(target_os = "macos")]
  2205. Message::Application(application_message) => match application_message {
  2206. ApplicationMessage::Show => {
  2207. event_loop.show_application();
  2208. }
  2209. ApplicationMessage::Hide => {
  2210. event_loop.hide_application();
  2211. }
  2212. },
  2213. Message::Window(id, window_message) => {
  2214. let w = windows.0.borrow().get(&id).map(|w| {
  2215. (
  2216. w.inner.clone(),
  2217. w.webviews.clone(),
  2218. w.has_children.load(Ordering::Relaxed),
  2219. w.window_event_listeners.clone(),
  2220. )
  2221. });
  2222. if let Some((Some(window), webviews, has_children, window_event_listeners)) = w {
  2223. match window_message {
  2224. WindowMessage::AddEventListener(id, listener) => {
  2225. window_event_listeners.lock().unwrap().insert(id, listener);
  2226. }
  2227. // Getters
  2228. WindowMessage::ScaleFactor(tx) => tx.send(window.scale_factor()).unwrap(),
  2229. WindowMessage::InnerPosition(tx) => tx
  2230. .send(
  2231. window
  2232. .inner_position()
  2233. .map(|p| PhysicalPositionWrapper(p).into())
  2234. .map_err(|_| Error::FailedToSendMessage),
  2235. )
  2236. .unwrap(),
  2237. WindowMessage::OuterPosition(tx) => tx
  2238. .send(
  2239. window
  2240. .outer_position()
  2241. .map(|p| PhysicalPositionWrapper(p).into())
  2242. .map_err(|_| Error::FailedToSendMessage),
  2243. )
  2244. .unwrap(),
  2245. WindowMessage::InnerSize(tx) => tx
  2246. .send(PhysicalSizeWrapper(inner_size(&window, &webviews, has_children)).into())
  2247. .unwrap(),
  2248. WindowMessage::OuterSize(tx) => tx
  2249. .send(PhysicalSizeWrapper(window.outer_size()).into())
  2250. .unwrap(),
  2251. WindowMessage::IsFullscreen(tx) => tx.send(window.fullscreen().is_some()).unwrap(),
  2252. WindowMessage::IsMinimized(tx) => tx.send(window.is_minimized()).unwrap(),
  2253. WindowMessage::IsMaximized(tx) => tx.send(window.is_maximized()).unwrap(),
  2254. WindowMessage::IsFocused(tx) => tx.send(window.is_focused()).unwrap(),
  2255. WindowMessage::IsDecorated(tx) => tx.send(window.is_decorated()).unwrap(),
  2256. WindowMessage::IsResizable(tx) => tx.send(window.is_resizable()).unwrap(),
  2257. WindowMessage::IsMaximizable(tx) => tx.send(window.is_maximizable()).unwrap(),
  2258. WindowMessage::IsMinimizable(tx) => tx.send(window.is_minimizable()).unwrap(),
  2259. WindowMessage::IsClosable(tx) => tx.send(window.is_closable()).unwrap(),
  2260. WindowMessage::IsVisible(tx) => tx.send(window.is_visible()).unwrap(),
  2261. WindowMessage::Title(tx) => tx.send(window.title()).unwrap(),
  2262. WindowMessage::CurrentMonitor(tx) => tx.send(window.current_monitor()).unwrap(),
  2263. WindowMessage::PrimaryMonitor(tx) => tx.send(window.primary_monitor()).unwrap(),
  2264. WindowMessage::AvailableMonitors(tx) => {
  2265. tx.send(window.available_monitors().collect()).unwrap()
  2266. }
  2267. #[cfg(any(
  2268. target_os = "linux",
  2269. target_os = "dragonfly",
  2270. target_os = "freebsd",
  2271. target_os = "netbsd",
  2272. target_os = "openbsd"
  2273. ))]
  2274. WindowMessage::GtkWindow(tx) => tx.send(GtkWindow(window.gtk_window().clone())).unwrap(),
  2275. #[cfg(any(
  2276. target_os = "linux",
  2277. target_os = "dragonfly",
  2278. target_os = "freebsd",
  2279. target_os = "netbsd",
  2280. target_os = "openbsd"
  2281. ))]
  2282. WindowMessage::GtkBox(tx) => tx
  2283. .send(GtkBox(window.default_vbox().unwrap().clone()))
  2284. .unwrap(),
  2285. WindowMessage::RawWindowHandle(tx) => tx
  2286. .send(
  2287. window
  2288. .window_handle()
  2289. .map(|h| SendRawWindowHandle(h.as_raw())),
  2290. )
  2291. .unwrap(),
  2292. WindowMessage::Theme(tx) => {
  2293. tx.send(map_theme(&window.theme())).unwrap();
  2294. }
  2295. // Setters
  2296. WindowMessage::Center => {
  2297. if let Some(monitor) = window.current_monitor() {
  2298. let window_size = inner_size(&window, &webviews, has_children);
  2299. let screen_size = monitor.size();
  2300. let monitor_pos = monitor.position();
  2301. let x = (screen_size.width as i32 - window_size.width as i32) / 2 + monitor_pos.x;
  2302. let y = (screen_size.height as i32 - window_size.height as i32) / 2 + monitor_pos.y;
  2303. window.set_outer_position(TaoPhysicalPosition::new(x, y));
  2304. }
  2305. }
  2306. WindowMessage::RequestUserAttention(request_type) => {
  2307. window.request_user_attention(request_type.map(|r| r.0));
  2308. }
  2309. WindowMessage::SetResizable(resizable) => window.set_resizable(resizable),
  2310. WindowMessage::SetMaximizable(maximizable) => window.set_maximizable(maximizable),
  2311. WindowMessage::SetMinimizable(minimizable) => window.set_minimizable(minimizable),
  2312. WindowMessage::SetClosable(closable) => window.set_closable(closable),
  2313. WindowMessage::SetTitle(title) => window.set_title(&title),
  2314. WindowMessage::Maximize => window.set_maximized(true),
  2315. WindowMessage::Unmaximize => window.set_maximized(false),
  2316. WindowMessage::Minimize => window.set_minimized(true),
  2317. WindowMessage::Unminimize => window.set_minimized(false),
  2318. WindowMessage::Show => window.set_visible(true),
  2319. WindowMessage::Hide => window.set_visible(false),
  2320. WindowMessage::Close => {
  2321. panic!("cannot handle `WindowMessage::Close` on the main thread")
  2322. }
  2323. WindowMessage::Destroy => {
  2324. panic!("cannot handle `WindowMessage::Destroy` on the main thread")
  2325. }
  2326. WindowMessage::SetDecorations(decorations) => window.set_decorations(decorations),
  2327. WindowMessage::SetShadow(_enable) => {
  2328. #[cfg(windows)]
  2329. window.set_undecorated_shadow(_enable);
  2330. #[cfg(target_os = "macos")]
  2331. window.set_has_shadow(_enable);
  2332. }
  2333. WindowMessage::SetAlwaysOnBottom(always_on_bottom) => {
  2334. window.set_always_on_bottom(always_on_bottom)
  2335. }
  2336. WindowMessage::SetAlwaysOnTop(always_on_top) => window.set_always_on_top(always_on_top),
  2337. WindowMessage::SetVisibleOnAllWorkspaces(visible_on_all_workspaces) => {
  2338. window.set_visible_on_all_workspaces(visible_on_all_workspaces)
  2339. }
  2340. WindowMessage::SetContentProtected(protected) => window.set_content_protection(protected),
  2341. WindowMessage::SetSize(size) => {
  2342. window.set_inner_size(SizeWrapper::from(size).0);
  2343. }
  2344. WindowMessage::SetMinSize(size) => {
  2345. window.set_min_inner_size(size.map(|s| SizeWrapper::from(s).0));
  2346. }
  2347. WindowMessage::SetMaxSize(size) => {
  2348. window.set_max_inner_size(size.map(|s| SizeWrapper::from(s).0));
  2349. }
  2350. WindowMessage::SetPosition(position) => {
  2351. window.set_outer_position(PositionWrapper::from(position).0)
  2352. }
  2353. WindowMessage::SetFullscreen(fullscreen) => {
  2354. if fullscreen {
  2355. window.set_fullscreen(Some(Fullscreen::Borderless(None)))
  2356. } else {
  2357. window.set_fullscreen(None)
  2358. }
  2359. #[cfg(windows)]
  2360. if let Some(w) = windows.0.borrow_mut().get_mut(&id) {
  2361. w.is_window_fullscreen = fullscreen;
  2362. }
  2363. }
  2364. WindowMessage::SetFocus => {
  2365. window.set_focus();
  2366. }
  2367. WindowMessage::SetIcon(icon) => {
  2368. window.set_window_icon(Some(icon));
  2369. }
  2370. #[allow(unused_variables)]
  2371. WindowMessage::SetSkipTaskbar(skip) => {
  2372. #[cfg(any(windows, target_os = "linux"))]
  2373. window.set_skip_taskbar(skip);
  2374. }
  2375. WindowMessage::SetCursorGrab(grab) => {
  2376. let _ = window.set_cursor_grab(grab);
  2377. }
  2378. WindowMessage::SetCursorVisible(visible) => {
  2379. window.set_cursor_visible(visible);
  2380. }
  2381. WindowMessage::SetCursorIcon(icon) => {
  2382. window.set_cursor_icon(CursorIconWrapper::from(icon).0);
  2383. }
  2384. WindowMessage::SetCursorPosition(position) => {
  2385. let _ = window.set_cursor_position(PositionWrapper::from(position).0);
  2386. }
  2387. WindowMessage::SetIgnoreCursorEvents(ignore) => {
  2388. let _ = window.set_ignore_cursor_events(ignore);
  2389. }
  2390. WindowMessage::DragWindow => {
  2391. let _ = window.drag_window();
  2392. }
  2393. WindowMessage::ResizeDragWindow(direction) => {
  2394. let _ = window.drag_resize_window(match direction {
  2395. tauri_runtime::ResizeDirection::East => tao::window::ResizeDirection::East,
  2396. tauri_runtime::ResizeDirection::North => tao::window::ResizeDirection::North,
  2397. tauri_runtime::ResizeDirection::NorthEast => tao::window::ResizeDirection::NorthEast,
  2398. tauri_runtime::ResizeDirection::NorthWest => tao::window::ResizeDirection::NorthWest,
  2399. tauri_runtime::ResizeDirection::South => tao::window::ResizeDirection::South,
  2400. tauri_runtime::ResizeDirection::SouthEast => tao::window::ResizeDirection::SouthEast,
  2401. tauri_runtime::ResizeDirection::SouthWest => tao::window::ResizeDirection::SouthWest,
  2402. tauri_runtime::ResizeDirection::West => tao::window::ResizeDirection::West,
  2403. });
  2404. }
  2405. WindowMessage::RequestRedraw => {
  2406. window.request_redraw();
  2407. }
  2408. WindowMessage::SetProgressBar(progress_state) => {
  2409. window.set_progress_bar(ProgressBarStateWrapper::from(progress_state).0);
  2410. }
  2411. }
  2412. }
  2413. }
  2414. Message::Webview(window_id, webview_id, webview_message) => {
  2415. if let WebviewMessage::Reparent(new_parent_window_id) = webview_message {
  2416. let webview_handle = windows.0.borrow_mut().get_mut(&window_id).and_then(|w| {
  2417. w.webviews
  2418. .iter()
  2419. .position(|w| w.id == webview_id)
  2420. .map(|webview_index| w.webviews.remove(webview_index))
  2421. });
  2422. if let Some(webview) = webview_handle {
  2423. if let Some((Some(new_parent_window), new_parent_window_webviews)) = windows
  2424. .0
  2425. .borrow_mut()
  2426. .get_mut(&new_parent_window_id)
  2427. .map(|w| (w.inner.clone(), &mut w.webviews))
  2428. {
  2429. #[cfg(target_os = "macos")]
  2430. {
  2431. use wry::WebViewExtMacOS;
  2432. webview.inner.reparent(new_parent_window.ns_window() as _);
  2433. new_parent_window_webviews.push(webview);
  2434. }
  2435. #[cfg(windows)]
  2436. {
  2437. webview.inner.reparent(new_parent_window.hwnd());
  2438. new_parent_window_webviews.push(webview);
  2439. }
  2440. #[cfg(any(
  2441. target_os = "linux",
  2442. target_os = "dragonfly",
  2443. target_os = "freebsd",
  2444. target_os = "netbsd",
  2445. target_os = "openbsd"
  2446. ))]
  2447. {
  2448. if let Some(container) = new_parent_window.default_vbox() {
  2449. webview.inner.reparent(container);
  2450. new_parent_window_webviews.push(webview);
  2451. }
  2452. }
  2453. }
  2454. }
  2455. } else {
  2456. let webview_handle = windows.0.borrow().get(&window_id).map(|w| {
  2457. (
  2458. w.inner.clone(),
  2459. w.webviews.iter().find(|w| w.id == webview_id).cloned(),
  2460. )
  2461. });
  2462. if let Some((Some(window), Some(webview))) = webview_handle {
  2463. match webview_message {
  2464. WebviewMessage::WebviewEvent(_) => { /* already handled */ }
  2465. WebviewMessage::SynthesizedWindowEvent(_) => { /* already handled */ }
  2466. WebviewMessage::Reparent(_window_id) => { /* already handled */ }
  2467. WebviewMessage::AddEventListener(id, listener) => {
  2468. webview
  2469. .webview_event_listeners
  2470. .lock()
  2471. .unwrap()
  2472. .insert(id, listener);
  2473. }
  2474. #[cfg(all(feature = "tracing", not(target_os = "android")))]
  2475. WebviewMessage::EvaluateScript(script, tx, span) => {
  2476. let _span = span.entered();
  2477. if let Err(e) = webview.evaluate_script(&script) {
  2478. debug_eprintln!("{}", e);
  2479. }
  2480. tx.send(()).unwrap();
  2481. }
  2482. #[cfg(not(all(feature = "tracing", not(target_os = "android"))))]
  2483. WebviewMessage::EvaluateScript(script) => {
  2484. if let Err(e) = webview.evaluate_script(&script) {
  2485. debug_eprintln!("{}", e);
  2486. }
  2487. }
  2488. WebviewMessage::Navigate(url) => webview.load_url(url.as_str()),
  2489. WebviewMessage::Print => {
  2490. let _ = webview.print();
  2491. }
  2492. WebviewMessage::Close => {
  2493. windows.0.borrow_mut().get_mut(&window_id).map(|window| {
  2494. if let Some(i) = window.webviews.iter().position(|w| w.id == webview.id) {
  2495. window.webviews.remove(i);
  2496. }
  2497. window
  2498. });
  2499. }
  2500. WebviewMessage::SetSize(size) => {
  2501. let mut bounds = webview.bounds();
  2502. let size = size.to_logical(window.scale_factor());
  2503. bounds.width = size.width;
  2504. bounds.height = size.height;
  2505. if let Some(b) = &webview.bounds {
  2506. let window_size = window.inner_size();
  2507. let mut bounds = b.lock().unwrap();
  2508. bounds.width_rate = size.width as f32 / window_size.width as f32;
  2509. bounds.height_rate = size.height as f32 / window_size.height as f32;
  2510. }
  2511. webview.set_bounds(bounds);
  2512. }
  2513. WebviewMessage::SetPosition(position) => {
  2514. let mut bounds = webview.bounds();
  2515. let position = position.to_logical(window.scale_factor());
  2516. bounds.x = position.x;
  2517. bounds.y = position.y;
  2518. if let Some(b) = &webview.bounds {
  2519. let window_size = window.inner_size();
  2520. let mut bounds = b.lock().unwrap();
  2521. bounds.width_rate = position.x as f32 / window_size.width as f32;
  2522. bounds.height_rate = position.y as f32 / window_size.height as f32;
  2523. }
  2524. webview.set_bounds(bounds);
  2525. }
  2526. // Getters
  2527. WebviewMessage::Url(tx) => {
  2528. tx.send(webview.url().parse().unwrap()).unwrap();
  2529. }
  2530. WebviewMessage::Position(tx) => {
  2531. let bounds = webview.bounds();
  2532. let position =
  2533. LogicalPosition::new(bounds.x, bounds.y).to_physical(window.scale_factor());
  2534. tx.send(position).unwrap();
  2535. }
  2536. WebviewMessage::Size(tx) => {
  2537. let bounds = webview.bounds();
  2538. let size =
  2539. LogicalSize::new(bounds.width, bounds.height).to_physical(window.scale_factor());
  2540. tx.send(size).unwrap();
  2541. }
  2542. WebviewMessage::SetFocus => {
  2543. webview.focus();
  2544. }
  2545. WebviewMessage::WithWebview(f) => {
  2546. #[cfg(any(
  2547. target_os = "linux",
  2548. target_os = "dragonfly",
  2549. target_os = "freebsd",
  2550. target_os = "netbsd",
  2551. target_os = "openbsd"
  2552. ))]
  2553. {
  2554. f(webview.webview());
  2555. }
  2556. #[cfg(target_os = "macos")]
  2557. {
  2558. use wry::WebViewExtMacOS;
  2559. f(Webview {
  2560. webview: webview.webview(),
  2561. manager: webview.manager(),
  2562. ns_window: webview.ns_window(),
  2563. });
  2564. }
  2565. #[cfg(target_os = "ios")]
  2566. {
  2567. use tao::platform::ios::WindowExtIOS;
  2568. use wry::WebViewExtIOS;
  2569. f(Webview {
  2570. webview: webview.inner.webview(),
  2571. manager: webview.inner.manager(),
  2572. view_controller: window.ui_view_controller() as cocoa::base::id,
  2573. });
  2574. }
  2575. #[cfg(windows)]
  2576. {
  2577. f(Webview {
  2578. controller: webview.controller(),
  2579. });
  2580. }
  2581. #[cfg(target_os = "android")]
  2582. {
  2583. f(webview.handle())
  2584. }
  2585. }
  2586. #[cfg(any(debug_assertions, feature = "devtools"))]
  2587. WebviewMessage::OpenDevTools => {
  2588. webview.open_devtools();
  2589. }
  2590. #[cfg(any(debug_assertions, feature = "devtools"))]
  2591. WebviewMessage::CloseDevTools => {
  2592. webview.close_devtools();
  2593. }
  2594. #[cfg(any(debug_assertions, feature = "devtools"))]
  2595. WebviewMessage::IsDevToolsOpen(tx) => {
  2596. tx.send(webview.is_devtools_open()).unwrap();
  2597. }
  2598. }
  2599. }
  2600. }
  2601. }
  2602. Message::CreateWebview(window_id, handler) => {
  2603. let window = windows
  2604. .0
  2605. .borrow()
  2606. .get(&window_id)
  2607. .and_then(|w| w.inner.clone());
  2608. if let Some(window) = window {
  2609. match handler(&window) {
  2610. Ok(webview) => {
  2611. windows.0.borrow_mut().get_mut(&window_id).map(|w| {
  2612. w.webviews.push(webview);
  2613. w
  2614. });
  2615. }
  2616. Err(e) => {
  2617. debug_eprintln!("{}", e);
  2618. }
  2619. }
  2620. }
  2621. }
  2622. Message::CreateWindow(window_id, handler) => match handler(event_loop) {
  2623. Ok(webview) => {
  2624. windows.0.borrow_mut().insert(window_id, webview);
  2625. }
  2626. Err(e) => {
  2627. debug_eprintln!("{}", e);
  2628. }
  2629. },
  2630. Message::CreateRawWindow(window_id, handler, sender) => {
  2631. let (label, builder) = handler();
  2632. #[cfg(windows)]
  2633. let is_window_fullscreen = builder.window.fullscreen.is_some();
  2634. #[cfg(windows)]
  2635. let is_window_transparent = builder.window.transparent;
  2636. if let Ok(window) = builder.build(event_loop) {
  2637. window_id_map.insert(window.id(), window_id);
  2638. let window = Arc::new(window);
  2639. #[cfg(windows)]
  2640. let surface = if is_window_transparent {
  2641. if let Ok(context) = softbuffer::Context::new(window.clone()) {
  2642. if let Ok(mut surface) = softbuffer::Surface::new(&context, window.clone()) {
  2643. clear_window_surface(&window, &mut surface);
  2644. Some(surface)
  2645. } else {
  2646. None
  2647. }
  2648. } else {
  2649. None
  2650. }
  2651. } else {
  2652. None
  2653. };
  2654. windows.0.borrow_mut().insert(
  2655. window_id,
  2656. WindowWrapper {
  2657. label,
  2658. has_children: AtomicBool::new(false),
  2659. inner: Some(window.clone()),
  2660. window_event_listeners: Default::default(),
  2661. webviews: Vec::new(),
  2662. #[cfg(windows)]
  2663. is_window_fullscreen,
  2664. #[cfg(windows)]
  2665. is_window_transparent,
  2666. #[cfg(windows)]
  2667. surface,
  2668. },
  2669. );
  2670. sender.send(Ok(Arc::downgrade(&window))).unwrap();
  2671. } else {
  2672. sender.send(Err(Error::CreateWindow)).unwrap();
  2673. }
  2674. }
  2675. Message::UserEvent(_) => (),
  2676. }
  2677. }
  2678. fn handle_event_loop<T: UserEvent>(
  2679. event: Event<'_, Message<T>>,
  2680. event_loop: &EventLoopWindowTarget<Message<T>>,
  2681. control_flow: &mut ControlFlow,
  2682. context: EventLoopIterationContext<'_, T>,
  2683. ) {
  2684. let EventLoopIterationContext {
  2685. callback,
  2686. window_id_map,
  2687. windows,
  2688. #[cfg(feature = "tracing")]
  2689. active_tracing_spans,
  2690. } = context;
  2691. if *control_flow != ControlFlow::Exit {
  2692. *control_flow = ControlFlow::Wait;
  2693. }
  2694. match event {
  2695. Event::NewEvents(StartCause::Init) => {
  2696. callback(RunEvent::Ready);
  2697. }
  2698. Event::NewEvents(StartCause::Poll) => {
  2699. callback(RunEvent::Resumed);
  2700. }
  2701. Event::MainEventsCleared => {
  2702. callback(RunEvent::MainEventsCleared);
  2703. }
  2704. Event::LoopDestroyed => {
  2705. callback(RunEvent::Exit);
  2706. }
  2707. #[cfg(any(feature = "tracing", windows))]
  2708. Event::RedrawRequested(id) => {
  2709. #[cfg(windows)]
  2710. if let Some(window_id) = window_id_map.get(&id) {
  2711. let mut windows_ref = windows.0.borrow_mut();
  2712. if let Some(window) = windows_ref.get_mut(&window_id) {
  2713. if window.is_window_transparent {
  2714. if let Some(surface) = &mut window.surface {
  2715. if let Some(window) = &window.inner {
  2716. clear_window_surface(window, surface)
  2717. }
  2718. }
  2719. }
  2720. }
  2721. }
  2722. #[cfg(feature = "tracing")]
  2723. active_tracing_spans.remove_window_draw(id);
  2724. }
  2725. Event::UserEvent(Message::Webview(
  2726. window_id,
  2727. webview_id,
  2728. WebviewMessage::WebviewEvent(event),
  2729. )) => {
  2730. let windows_ref = windows.0.borrow();
  2731. if let Some(window) = windows_ref.get(&window_id) {
  2732. if let Some(webview) = window.webviews.iter().find(|w| w.id == webview_id) {
  2733. let label = webview.label.clone();
  2734. let webview_event_listeners = webview.webview_event_listeners.clone();
  2735. drop(windows_ref);
  2736. callback(RunEvent::WebviewEvent {
  2737. label,
  2738. event: event.clone(),
  2739. });
  2740. let listeners = webview_event_listeners.lock().unwrap();
  2741. let handlers = listeners.values();
  2742. for handler in handlers {
  2743. handler(&event);
  2744. }
  2745. }
  2746. }
  2747. }
  2748. Event::UserEvent(Message::Webview(
  2749. window_id,
  2750. _webview_id,
  2751. WebviewMessage::SynthesizedWindowEvent(event),
  2752. )) => {
  2753. if let Some(event) = WindowEventWrapper::from(event).0 {
  2754. let windows_ref = windows.0.borrow();
  2755. let window = windows_ref.get(&window_id);
  2756. if let Some(window) = window {
  2757. let label = window.label.clone();
  2758. let window_event_listeners = window.window_event_listeners.clone();
  2759. drop(windows_ref);
  2760. callback(RunEvent::WindowEvent {
  2761. label,
  2762. event: event.clone(),
  2763. });
  2764. let listeners = window_event_listeners.lock().unwrap();
  2765. let handlers = listeners.values();
  2766. for handler in handlers {
  2767. handler(&event);
  2768. }
  2769. }
  2770. }
  2771. }
  2772. Event::WindowEvent {
  2773. event, window_id, ..
  2774. } => {
  2775. if let Some(window_id) = window_id_map.get(&window_id) {
  2776. {
  2777. let windows_ref = windows.0.borrow();
  2778. if let Some(window) = windows_ref.get(&window_id) {
  2779. if let Some(event) = WindowEventWrapper::parse(window, &event).0 {
  2780. let label = window.label.clone();
  2781. let window_event_listeners = window.window_event_listeners.clone();
  2782. drop(windows_ref);
  2783. callback(RunEvent::WindowEvent {
  2784. label,
  2785. event: event.clone(),
  2786. });
  2787. let listeners = window_event_listeners.lock().unwrap();
  2788. let handlers = listeners.values();
  2789. for handler in handlers {
  2790. handler(&event);
  2791. }
  2792. }
  2793. }
  2794. }
  2795. match event {
  2796. #[cfg(windows)]
  2797. TaoWindowEvent::ThemeChanged(theme) => {
  2798. if let Some(window) = windows.0.borrow().get(&window_id) {
  2799. for webview in &window.webviews {
  2800. let theme = match theme {
  2801. TaoTheme::Dark => wry::Theme::Dark,
  2802. TaoTheme::Light => wry::Theme::Light,
  2803. _ => wry::Theme::Light,
  2804. };
  2805. webview.set_theme(theme);
  2806. }
  2807. }
  2808. }
  2809. TaoWindowEvent::CloseRequested => {
  2810. on_close_requested(callback, window_id, windows.clone());
  2811. }
  2812. TaoWindowEvent::Destroyed => {
  2813. let removed = windows.0.borrow_mut().remove(&window_id).is_some();
  2814. if removed {
  2815. let is_empty = windows.0.borrow().is_empty();
  2816. if is_empty {
  2817. let (tx, rx) = channel();
  2818. callback(RunEvent::ExitRequested { code: None, tx });
  2819. let recv = rx.try_recv();
  2820. let should_prevent = matches!(recv, Ok(ExitRequestedEventAction::Prevent));
  2821. if !should_prevent {
  2822. *control_flow = ControlFlow::Exit;
  2823. }
  2824. }
  2825. }
  2826. }
  2827. TaoWindowEvent::Resized(size) => {
  2828. if let Some(webviews) = windows
  2829. .0
  2830. .borrow()
  2831. .get(&window_id)
  2832. .map(|w| w.webviews.clone())
  2833. {
  2834. for webview in webviews {
  2835. if let Some(bounds) = &webview.bounds {
  2836. let b = bounds.lock().unwrap();
  2837. webview.set_bounds(wry::Rect {
  2838. x: (size.width as f32 * b.x_rate) as i32,
  2839. y: (size.height as f32 * b.y_rate) as i32,
  2840. width: (size.width as f32 * b.width_rate) as u32,
  2841. height: (size.height as f32 * b.height_rate) as u32,
  2842. });
  2843. }
  2844. }
  2845. }
  2846. }
  2847. _ => {}
  2848. }
  2849. }
  2850. }
  2851. Event::UserEvent(message) => match message {
  2852. Message::RequestExit(code) => {
  2853. let (tx, rx) = channel();
  2854. callback(RunEvent::ExitRequested {
  2855. code: Some(code),
  2856. tx,
  2857. });
  2858. let recv = rx.try_recv();
  2859. let should_prevent = matches!(recv, Ok(ExitRequestedEventAction::Prevent));
  2860. if !should_prevent {
  2861. *control_flow = ControlFlow::Exit;
  2862. }
  2863. }
  2864. Message::Window(id, WindowMessage::Close) => {
  2865. on_close_requested(callback, id, windows.clone());
  2866. }
  2867. Message::Window(id, WindowMessage::Destroy) => {
  2868. on_window_close(id, windows.clone());
  2869. }
  2870. Message::UserEvent(t) => callback(RunEvent::UserEvent(t)),
  2871. message => {
  2872. handle_user_message(
  2873. event_loop,
  2874. message,
  2875. UserMessageContext {
  2876. window_id_map,
  2877. windows,
  2878. },
  2879. );
  2880. }
  2881. },
  2882. #[cfg(any(target_os = "macos", target_os = "ios"))]
  2883. Event::Opened { urls } => {
  2884. callback(RunEvent::Opened { urls });
  2885. }
  2886. _ => (),
  2887. }
  2888. }
  2889. fn on_close_requested<'a, T: UserEvent>(
  2890. callback: &'a mut (dyn FnMut(RunEvent<T>) + 'static),
  2891. window_id: WindowId,
  2892. windows: Arc<WindowsStore>,
  2893. ) {
  2894. let (tx, rx) = channel();
  2895. let windows_ref = windows.0.borrow();
  2896. if let Some(w) = windows_ref.get(&window_id) {
  2897. let label = w.label.clone();
  2898. let window_event_listeners = w.window_event_listeners.clone();
  2899. drop(windows_ref);
  2900. let listeners = window_event_listeners.lock().unwrap();
  2901. let handlers = listeners.values();
  2902. for handler in handlers {
  2903. handler(&WindowEvent::CloseRequested {
  2904. signal_tx: tx.clone(),
  2905. });
  2906. }
  2907. callback(RunEvent::WindowEvent {
  2908. label,
  2909. event: WindowEvent::CloseRequested { signal_tx: tx },
  2910. });
  2911. if let Ok(true) = rx.try_recv() {
  2912. } else {
  2913. on_window_close(window_id, windows);
  2914. }
  2915. }
  2916. }
  2917. fn on_window_close(window_id: WindowId, windows: Arc<WindowsStore>) {
  2918. if let Some(window_wrapper) = windows.0.borrow_mut().get_mut(&window_id) {
  2919. window_wrapper.inner = None;
  2920. #[cfg(windows)]
  2921. window_wrapper.surface.take();
  2922. }
  2923. }
  2924. fn parse_proxy_url(url: &Url) -> Result<ProxyConfig> {
  2925. let host = url.host().map(|h| h.to_string()).unwrap_or_default();
  2926. let port = url.port().map(|p| p.to_string()).unwrap_or_default();
  2927. if url.scheme() == "http" {
  2928. let config = ProxyConfig::Http(ProxyEndpoint { host, port });
  2929. Ok(config)
  2930. } else if url.scheme() == "socks5" {
  2931. let config = ProxyConfig::Socks5(ProxyEndpoint { host, port });
  2932. Ok(config)
  2933. } else {
  2934. Err(Error::InvalidProxyUrl)
  2935. }
  2936. }
  2937. fn create_window<T: UserEvent, F: Fn(RawWindow) + Send + 'static>(
  2938. window_id: WindowId,
  2939. webview_id: u32,
  2940. event_loop: &EventLoopWindowTarget<Message<T>>,
  2941. context: &Context<T>,
  2942. pending: PendingWindow<T, Wry<T>>,
  2943. after_window_creation: Option<F>,
  2944. ) -> Result<WindowWrapper> {
  2945. #[allow(unused_mut)]
  2946. let PendingWindow {
  2947. mut window_builder,
  2948. label,
  2949. webview,
  2950. } = pending;
  2951. #[cfg(feature = "tracing")]
  2952. let _webview_create_span = tracing::debug_span!("wry::webview::create").entered();
  2953. #[cfg(feature = "tracing")]
  2954. let window_draw_span = tracing::debug_span!("wry::window::draw").entered();
  2955. #[cfg(feature = "tracing")]
  2956. let window_create_span =
  2957. tracing::debug_span!(parent: &window_draw_span, "wry::window::create").entered();
  2958. let window_event_listeners = WindowEventListeners::default();
  2959. #[cfg(windows)]
  2960. let is_window_transparent = window_builder.inner.window.transparent;
  2961. #[cfg(windows)]
  2962. let is_window_fullscreen = window_builder.inner.window.fullscreen.is_some();
  2963. #[cfg(target_os = "macos")]
  2964. {
  2965. if window_builder.tabbing_identifier.is_none()
  2966. || window_builder.inner.window.transparent
  2967. || !window_builder.inner.window.decorations
  2968. {
  2969. window_builder.inner = window_builder.inner.with_automatic_window_tabbing(false);
  2970. }
  2971. }
  2972. #[cfg(desktop)]
  2973. if window_builder.center {
  2974. let monitor = if let Some(window_position) = &window_builder.inner.window.position {
  2975. event_loop.available_monitors().find(|m| {
  2976. let monitor_pos = m.position();
  2977. let monitor_size = m.size();
  2978. let window_position = window_position.to_logical(m.scale_factor());
  2979. monitor_pos.x <= window_position.x
  2980. && window_position.x <= monitor_pos.x + monitor_size.width as i32
  2981. && monitor_pos.y <= window_position.y
  2982. && window_position.y <= monitor_pos.y + monitor_size.height as i32
  2983. })
  2984. } else {
  2985. event_loop.primary_monitor()
  2986. };
  2987. if let Some(monitor) = monitor {
  2988. let desired_size = window_builder
  2989. .inner
  2990. .window
  2991. .inner_size
  2992. .unwrap_or_else(|| TaoPhysicalSize::new(800, 600).into());
  2993. let window_size = window_builder
  2994. .inner
  2995. .window
  2996. .inner_size_constraints
  2997. .clamp(desired_size, monitor.scale_factor())
  2998. .to_logical::<i32>(monitor.scale_factor());
  2999. let screen_size = monitor.size();
  3000. let monitor_pos = monitor.position();
  3001. let x = (screen_size.width as i32 - window_size.width) / 2 + monitor_pos.x;
  3002. let y = (screen_size.height as i32 - window_size.height) / 2 + monitor_pos.y;
  3003. window_builder = window_builder.position(x as f64, y as f64);
  3004. }
  3005. }
  3006. let window = window_builder.inner.build(event_loop).unwrap();
  3007. #[cfg(feature = "tracing")]
  3008. {
  3009. drop(window_create_span);
  3010. context
  3011. .main_thread
  3012. .active_tracing_spans
  3013. .0
  3014. .borrow_mut()
  3015. .push(ActiveTracingSpan::WindowDraw {
  3016. id: window.id(),
  3017. span: window_draw_span,
  3018. });
  3019. }
  3020. context.window_id_map.insert(window.id(), window_id);
  3021. if let Some(handler) = after_window_creation {
  3022. let raw = RawWindow {
  3023. #[cfg(windows)]
  3024. hwnd: window.hwnd(),
  3025. #[cfg(any(
  3026. target_os = "linux",
  3027. target_os = "dragonfly",
  3028. target_os = "freebsd",
  3029. target_os = "netbsd",
  3030. target_os = "openbsd"
  3031. ))]
  3032. gtk_window: window.gtk_window(),
  3033. #[cfg(any(
  3034. target_os = "linux",
  3035. target_os = "dragonfly",
  3036. target_os = "freebsd",
  3037. target_os = "netbsd",
  3038. target_os = "openbsd"
  3039. ))]
  3040. default_vbox: window.default_vbox(),
  3041. _marker: &std::marker::PhantomData,
  3042. };
  3043. handler(raw);
  3044. }
  3045. let mut webviews = Vec::new();
  3046. if let Some(webview) = webview {
  3047. webviews.push(create_webview(
  3048. WebviewKind::WindowContent,
  3049. &window,
  3050. Arc::new(Mutex::new(window_id)),
  3051. webview_id,
  3052. context,
  3053. webview,
  3054. )?);
  3055. }
  3056. let window = Arc::new(window);
  3057. #[cfg(windows)]
  3058. let surface = if is_window_transparent {
  3059. if let Ok(context) = softbuffer::Context::new(window.clone()) {
  3060. if let Ok(mut surface) = softbuffer::Surface::new(&context, window.clone()) {
  3061. clear_window_surface(&window, &mut surface);
  3062. Some(surface)
  3063. } else {
  3064. None
  3065. }
  3066. } else {
  3067. None
  3068. }
  3069. } else {
  3070. None
  3071. };
  3072. Ok(WindowWrapper {
  3073. label,
  3074. has_children: AtomicBool::new(false),
  3075. inner: Some(window),
  3076. webviews,
  3077. window_event_listeners,
  3078. #[cfg(windows)]
  3079. is_window_fullscreen,
  3080. #[cfg(windows)]
  3081. is_window_transparent,
  3082. #[cfg(windows)]
  3083. surface,
  3084. })
  3085. }
  3086. /// the kind of the webview
  3087. #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
  3088. enum WebviewKind {
  3089. // webview is the entire window content
  3090. WindowContent,
  3091. // webview is a child of the window, which can contain other webviews too
  3092. WindowChild,
  3093. }
  3094. #[derive(Debug, Clone)]
  3095. struct WebviewBounds {
  3096. x_rate: f32,
  3097. y_rate: f32,
  3098. width_rate: f32,
  3099. height_rate: f32,
  3100. }
  3101. fn create_webview<T: UserEvent>(
  3102. kind: WebviewKind,
  3103. window: &Window,
  3104. window_id: Arc<Mutex<WindowId>>,
  3105. id: WebviewId,
  3106. context: &Context<T>,
  3107. pending: PendingWebview<T, Wry<T>>,
  3108. ) -> Result<WebviewWrapper> {
  3109. #[allow(unused_mut)]
  3110. let PendingWebview {
  3111. webview_attributes,
  3112. uri_scheme_protocols,
  3113. label,
  3114. ipc_handler,
  3115. url,
  3116. ..
  3117. } = pending;
  3118. let builder = match kind {
  3119. #[cfg(not(any(
  3120. target_os = "windows",
  3121. target_os = "macos",
  3122. target_os = "ios",
  3123. target_os = "android"
  3124. )))]
  3125. WebviewKind::WindowChild => {
  3126. // only way to account for menu bar height, and also works for multiwebviews :)
  3127. let vbox = window.default_vbox().unwrap();
  3128. WebViewBuilder::new_gtk(vbox)
  3129. }
  3130. #[cfg(any(
  3131. target_os = "windows",
  3132. target_os = "macos",
  3133. target_os = "ios",
  3134. target_os = "android"
  3135. ))]
  3136. WebviewKind::WindowChild => WebViewBuilder::new_as_child(&window),
  3137. WebviewKind::WindowContent => {
  3138. #[cfg(any(
  3139. target_os = "windows",
  3140. target_os = "macos",
  3141. target_os = "ios",
  3142. target_os = "android"
  3143. ))]
  3144. let builder = WebViewBuilder::new(&window);
  3145. #[cfg(not(any(
  3146. target_os = "windows",
  3147. target_os = "macos",
  3148. target_os = "ios",
  3149. target_os = "android"
  3150. )))]
  3151. let builder = {
  3152. let vbox = window.default_vbox().unwrap();
  3153. WebViewBuilder::new_gtk(vbox)
  3154. };
  3155. builder
  3156. }
  3157. };
  3158. let mut webview_builder = builder
  3159. .with_focused(window.is_focused())
  3160. .with_url(&url)
  3161. .with_transparent(webview_attributes.transparent)
  3162. .with_accept_first_mouse(webview_attributes.accept_first_mouse);
  3163. #[cfg(windows)]
  3164. if kind == WebviewKind::WindowContent {
  3165. webview_builder = webview_builder.with_initialization_script(undecorated_resizing::SCRIPT);
  3166. }
  3167. if webview_attributes.file_drop_handler_enabled {
  3168. let proxy = context.proxy.clone();
  3169. let window_id_ = window_id.clone();
  3170. webview_builder = webview_builder.with_file_drop_handler(move |event| {
  3171. let event = match event {
  3172. WryFileDropEvent::Hovered {
  3173. paths,
  3174. position: (x, y),
  3175. } => FileDropEvent::Hovered {
  3176. paths,
  3177. position: PhysicalPosition::new(x as _, y as _),
  3178. },
  3179. WryFileDropEvent::Dropped {
  3180. paths,
  3181. position: (x, y),
  3182. } => FileDropEvent::Dropped {
  3183. paths,
  3184. position: PhysicalPosition::new(x as _, y as _),
  3185. },
  3186. WryFileDropEvent::Cancelled => FileDropEvent::Cancelled,
  3187. _ => unimplemented!(),
  3188. };
  3189. let message = if kind == WebviewKind::WindowContent {
  3190. WebviewMessage::SynthesizedWindowEvent(SynthesizedWindowEvent::FileDrop(event))
  3191. } else {
  3192. WebviewMessage::WebviewEvent(WebviewEvent::FileDrop(event))
  3193. };
  3194. let _ = proxy.send_event(Message::Webview(*window_id_.lock().unwrap(), id, message));
  3195. true
  3196. });
  3197. }
  3198. if let Some(navigation_handler) = pending.navigation_handler {
  3199. webview_builder = webview_builder.with_navigation_handler(move |url| {
  3200. Url::parse(&url)
  3201. .map(|url| navigation_handler(&url))
  3202. .unwrap_or(true)
  3203. });
  3204. }
  3205. let webview_bounds = if let Some((position, size)) = webview_attributes.bounds {
  3206. let size = size.to_logical(window.scale_factor());
  3207. let position = position.to_logical(window.scale_factor());
  3208. webview_builder = webview_builder.with_bounds(wry::Rect {
  3209. x: position.x,
  3210. y: position.y,
  3211. width: size.width,
  3212. height: size.height,
  3213. });
  3214. let window_size = window.inner_size();
  3215. if webview_attributes.auto_resize {
  3216. Some(WebviewBounds {
  3217. x_rate: (position.x as f32) / window_size.width as f32,
  3218. y_rate: (position.y as f32) / window_size.height as f32,
  3219. width_rate: (size.width as f32) / window_size.width as f32,
  3220. height_rate: (size.height as f32) / window_size.height as f32,
  3221. })
  3222. } else {
  3223. None
  3224. }
  3225. } else {
  3226. None
  3227. };
  3228. if let Some(download_handler) = pending.download_handler {
  3229. let download_handler_ = download_handler.clone();
  3230. webview_builder = webview_builder.with_download_started_handler(move |url, path| {
  3231. if let Ok(url) = url.parse() {
  3232. download_handler_(DownloadEvent::Requested {
  3233. url,
  3234. destination: path,
  3235. })
  3236. } else {
  3237. false
  3238. }
  3239. });
  3240. webview_builder = webview_builder.with_download_completed_handler(move |url, path, success| {
  3241. if let Ok(url) = url.parse() {
  3242. download_handler(DownloadEvent::Finished { url, path, success });
  3243. }
  3244. });
  3245. }
  3246. if let Some(page_load_handler) = pending.on_page_load_handler {
  3247. webview_builder = webview_builder.with_on_page_load_handler(move |event, url| {
  3248. let _ = Url::parse(&url).map(|url| {
  3249. page_load_handler(
  3250. url,
  3251. match event {
  3252. wry::PageLoadEvent::Started => tauri_runtime::webview::PageLoadEvent::Started,
  3253. wry::PageLoadEvent::Finished => tauri_runtime::webview::PageLoadEvent::Finished,
  3254. },
  3255. )
  3256. });
  3257. });
  3258. }
  3259. if let Some(user_agent) = webview_attributes.user_agent {
  3260. webview_builder = webview_builder.with_user_agent(&user_agent);
  3261. }
  3262. if let Some(proxy_url) = webview_attributes.proxy_url {
  3263. let config = parse_proxy_url(&proxy_url)?;
  3264. webview_builder = webview_builder.with_proxy_config(config);
  3265. }
  3266. #[cfg(windows)]
  3267. {
  3268. if let Some(additional_browser_args) = webview_attributes.additional_browser_args {
  3269. webview_builder = webview_builder.with_additional_browser_args(&additional_browser_args);
  3270. }
  3271. webview_builder = webview_builder.with_theme(match window.theme() {
  3272. TaoTheme::Dark => wry::Theme::Dark,
  3273. TaoTheme::Light => wry::Theme::Light,
  3274. _ => wry::Theme::Light,
  3275. });
  3276. }
  3277. #[cfg(windows)]
  3278. {
  3279. webview_builder = webview_builder.with_https_scheme(false);
  3280. }
  3281. webview_builder = webview_builder.with_ipc_handler(create_ipc_handler(
  3282. kind,
  3283. window_id.clone(),
  3284. id,
  3285. context.clone(),
  3286. label.clone(),
  3287. ipc_handler,
  3288. ));
  3289. for (scheme, protocol) in uri_scheme_protocols {
  3290. webview_builder =
  3291. webview_builder.with_asynchronous_custom_protocol(scheme, move |request, responder| {
  3292. protocol(
  3293. request,
  3294. Box::new(move |response| responder.respond(response)),
  3295. )
  3296. });
  3297. }
  3298. for script in webview_attributes.initialization_scripts {
  3299. webview_builder = webview_builder.with_initialization_script(&script);
  3300. }
  3301. let mut web_context = context
  3302. .main_thread
  3303. .web_context
  3304. .lock()
  3305. .expect("poisoned WebContext store");
  3306. let is_first_context = web_context.is_empty();
  3307. let automation_enabled = std::env::var("TAURI_WEBVIEW_AUTOMATION").as_deref() == Ok("true");
  3308. let web_context_key = // force a unique WebContext when automation is false;
  3309. // the context must be stored on the HashMap because it must outlive the WebView on macOS
  3310. if automation_enabled {
  3311. webview_attributes.data_directory.clone()
  3312. } else {
  3313. // unique key
  3314. let key = context.next_webcontext_id().to_string().into();
  3315. Some(key)
  3316. };
  3317. let entry = web_context.entry(web_context_key.clone());
  3318. let web_context = match entry {
  3319. Occupied(occupied) => occupied.into_mut(),
  3320. Vacant(vacant) => {
  3321. let mut web_context = WebContext::new(webview_attributes.data_directory);
  3322. web_context.set_allows_automation(if automation_enabled {
  3323. is_first_context
  3324. } else {
  3325. false
  3326. });
  3327. vacant.insert(web_context)
  3328. }
  3329. };
  3330. if webview_attributes.clipboard {
  3331. webview_builder.attrs.clipboard = true;
  3332. }
  3333. if webview_attributes.incognito {
  3334. webview_builder.attrs.incognito = true;
  3335. }
  3336. #[cfg(any(debug_assertions, feature = "devtools"))]
  3337. {
  3338. webview_builder = webview_builder.with_devtools(true);
  3339. }
  3340. #[cfg(target_os = "android")]
  3341. {
  3342. if let Some(on_webview_created) = pending.on_webview_created {
  3343. webview_builder = webview_builder.on_webview_created(move |ctx| {
  3344. on_webview_created(tauri_runtime::webview::CreationContext {
  3345. env: ctx.env,
  3346. activity: ctx.activity,
  3347. webview: ctx.webview,
  3348. })
  3349. });
  3350. }
  3351. }
  3352. let webview = webview_builder
  3353. .with_web_context(web_context)
  3354. .build()
  3355. .map_err(|e| Error::CreateWebview(Box::new(e)))?;
  3356. #[cfg(any(
  3357. target_os = "linux",
  3358. target_os = "dragonfly",
  3359. target_os = "freebsd",
  3360. target_os = "netbsd",
  3361. target_os = "openbsd"
  3362. ))]
  3363. if kind == WebviewKind::WindowContent {
  3364. undecorated_resizing::attach_resize_handler(&webview);
  3365. }
  3366. #[cfg(windows)]
  3367. if kind == WebviewKind::WindowContent {
  3368. let controller = webview.controller();
  3369. let proxy = context.proxy.clone();
  3370. let proxy_ = proxy.clone();
  3371. let window_id_ = window_id.clone();
  3372. let mut token = EventRegistrationToken::default();
  3373. unsafe {
  3374. controller.add_GotFocus(
  3375. &FocusChangedEventHandler::create(Box::new(move |_, _| {
  3376. let _ = proxy.send_event(Message::Webview(
  3377. *window_id_.lock().unwrap(),
  3378. id,
  3379. WebviewMessage::SynthesizedWindowEvent(SynthesizedWindowEvent::Focused(true)),
  3380. ));
  3381. Ok(())
  3382. })),
  3383. &mut token,
  3384. )
  3385. }
  3386. .unwrap();
  3387. unsafe {
  3388. controller.add_LostFocus(
  3389. &FocusChangedEventHandler::create(Box::new(move |_, _| {
  3390. let _ = proxy_.send_event(Message::Webview(
  3391. *window_id.lock().unwrap(),
  3392. id,
  3393. WebviewMessage::SynthesizedWindowEvent(SynthesizedWindowEvent::Focused(false)),
  3394. ));
  3395. Ok(())
  3396. })),
  3397. &mut token,
  3398. )
  3399. }
  3400. .unwrap();
  3401. }
  3402. Ok(WebviewWrapper {
  3403. label,
  3404. id,
  3405. inner: Rc::new(webview),
  3406. context_store: context.main_thread.web_context.clone(),
  3407. webview_event_listeners: Default::default(),
  3408. context_key: if automation_enabled {
  3409. None
  3410. } else {
  3411. web_context_key
  3412. },
  3413. bounds: webview_bounds.map(|b| Arc::new(Mutex::new(b))),
  3414. })
  3415. }
  3416. /// Create a wry ipc handler from a tauri ipc handler.
  3417. fn create_ipc_handler<T: UserEvent>(
  3418. _kind: WebviewKind,
  3419. window_id: Arc<Mutex<WindowId>>,
  3420. webview_id: WebviewId,
  3421. context: Context<T>,
  3422. label: String,
  3423. ipc_handler: Option<WebviewIpcHandler<T, Wry<T>>>,
  3424. ) -> Box<IpcHandler> {
  3425. Box::new(move |request| {
  3426. #[cfg(windows)]
  3427. if _kind == WebviewKind::WindowContent
  3428. && undecorated_resizing::handle_request(context.clone(), *window_id.lock().unwrap(), &request)
  3429. {
  3430. return;
  3431. }
  3432. if let Some(handler) = &ipc_handler {
  3433. handler(
  3434. DetachedWebview {
  3435. label: label.clone(),
  3436. dispatcher: WryWebviewDispatcher {
  3437. window_id: window_id.clone(),
  3438. webview_id,
  3439. context: context.clone(),
  3440. },
  3441. },
  3442. request,
  3443. );
  3444. }
  3445. })
  3446. }
  3447. #[cfg(target_os = "macos")]
  3448. fn inner_size(
  3449. window: &Window,
  3450. webviews: &[WebviewWrapper],
  3451. has_children: bool,
  3452. ) -> TaoPhysicalSize<u32> {
  3453. if has_children && webviews.len() == 1 {
  3454. use wry::WebViewExtMacOS;
  3455. let webview = webviews.first().unwrap();
  3456. let view_frame = unsafe { cocoa::appkit::NSView::frame(webview.webview()) };
  3457. let logical: TaoLogicalSize<f64> = (view_frame.size.width, view_frame.size.height).into();
  3458. return logical.to_physical(window.scale_factor());
  3459. }
  3460. window.inner_size()
  3461. }
  3462. #[cfg(not(target_os = "macos"))]
  3463. #[allow(unused_variables)]
  3464. fn inner_size(
  3465. window: &Window,
  3466. webviews: &[WebviewWrapper],
  3467. has_children: bool,
  3468. ) -> TaoPhysicalSize<u32> {
  3469. window.inner_size()
  3470. }
  3471. #[cfg(windows)]
  3472. fn clear_window_surface(
  3473. window: &Window,
  3474. surface: &mut softbuffer::Surface<Arc<Window>, Arc<Window>>,
  3475. ) {
  3476. let size = window.inner_size();
  3477. if let (Some(width), Some(height)) = (
  3478. std::num::NonZeroU32::new(size.width),
  3479. std::num::NonZeroU32::new(size.height),
  3480. ) {
  3481. surface.resize(width, height).unwrap();
  3482. let mut buffer = surface.buffer_mut().unwrap();
  3483. buffer.fill(0);
  3484. let _ = buffer.present();
  3485. }
  3486. }