window.ts 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172
  1. // Copyright 2019-2022 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. /**
  5. * Provides APIs to create windows, communicate with other windows and manipulate the current window.
  6. *
  7. * This package is also accessible with `window.__TAURI__.window` when [`build.withGlobalTauri`](https://tauri.app/v1/api/config/#buildconfig.withglobaltauri) in `tauri.conf.json` is set to `true`.
  8. *
  9. * The APIs must be added to [`tauri.allowlist.window`](https://tauri.app/v1/api/config/#allowlistconfig.window) in `tauri.conf.json`:
  10. * ```json
  11. * {
  12. * "tauri": {
  13. * "allowlist": {
  14. * "window": {
  15. * "all": true, // enable all window APIs
  16. * "create": true, // enable window creation
  17. * "center": true,
  18. * "requestUserAttention": true,
  19. * "setResizable": true,
  20. * "setTitle": true,
  21. * "maximize": true,
  22. * "unmaximize": true,
  23. * "minimize": true,
  24. * "unminimize": true,
  25. * "show": true,
  26. * "hide": true,
  27. * "close": true,
  28. * "setDecorations": true,
  29. * "setAlwaysOnTop": true,
  30. * "setSize": true,
  31. * "setMinSize": true,
  32. * "setMaxSize": true,
  33. * "setPosition": true,
  34. * "setFullscreen": true,
  35. * "setFocus": true,
  36. * "setIcon": true,
  37. * "setSkipTaskbar": true,
  38. * "setCursorGrab": true,
  39. * "setCursorVisible": true,
  40. * "setCursorIcon": true,
  41. * "setCursorPosition": true,
  42. * "setIgnoreCursorEvents": true,
  43. * "startDragging": true,
  44. * "print": true
  45. * }
  46. * }
  47. * }
  48. * }
  49. * ```
  50. * It is recommended to allowlist only the APIs you use for optimal bundle size and security.
  51. *
  52. * # Window events
  53. *
  54. * Events can be listened using `appWindow.listen`:
  55. * ```typescript
  56. * import { appWindow } from "@tauri-apps/api/window";
  57. * appWindow.listen("my-window-event", ({ event, payload }) => { });
  58. * ```
  59. *
  60. * @module
  61. */
  62. import { invokeTauriCommand } from './helpers/tauri'
  63. import type { EventName, EventCallback, UnlistenFn } from './event'
  64. import { emit, Event, listen, once } from './helpers/event'
  65. import { TauriEvent } from './event'
  66. type Theme = 'light' | 'dark'
  67. type TitleBarStyle = 'visible' | 'transparent' | 'overlay'
  68. /**
  69. * Allows you to retrieve information about a given monitor.
  70. *
  71. * @since 1.0.0
  72. */
  73. interface Monitor {
  74. /** Human-readable name of the monitor */
  75. name: string | null
  76. /** The monitor's resolution. */
  77. size: PhysicalSize
  78. /** the Top-left corner position of the monitor relative to the larger full screen area. */
  79. position: PhysicalPosition
  80. /** The scale factor that can be used to map physical pixels to logical pixels. */
  81. scaleFactor: number
  82. }
  83. /**
  84. * The payload for the `scaleChange` event.
  85. *
  86. * @since 1.0.2
  87. */
  88. interface ScaleFactorChanged {
  89. /** The new window scale factor. */
  90. scaleFactor: number
  91. /** The new window size */
  92. size: PhysicalSize
  93. }
  94. /** The file drop event types. */
  95. type FileDropEvent =
  96. | { type: 'hover'; paths: string[] }
  97. | { type: 'drop'; paths: string[] }
  98. | { type: 'cancel' }
  99. /**
  100. * A size represented in logical pixels.
  101. *
  102. * @since 1.0.0
  103. */
  104. class LogicalSize {
  105. type = 'Logical'
  106. width: number
  107. height: number
  108. constructor(width: number, height: number) {
  109. this.width = width
  110. this.height = height
  111. }
  112. }
  113. /**
  114. * A size represented in physical pixels.
  115. *
  116. * @since 1.0.0
  117. */
  118. class PhysicalSize {
  119. type = 'Physical'
  120. width: number
  121. height: number
  122. constructor(width: number, height: number) {
  123. this.width = width
  124. this.height = height
  125. }
  126. /**
  127. * Converts the physical size to a logical one.
  128. * @example
  129. * ```typescript
  130. * import { appWindow } from '@tauri-apps/api/window';
  131. * const factor = await appWindow.scaleFactor();
  132. * const size = await appWindow.innerSize();
  133. * const logical = size.toLogical(factor);
  134. * ```
  135. * */
  136. toLogical(scaleFactor: number): LogicalSize {
  137. return new LogicalSize(this.width / scaleFactor, this.height / scaleFactor)
  138. }
  139. }
  140. /**
  141. * A position represented in logical pixels.
  142. *
  143. * @since 1.0.0
  144. */
  145. class LogicalPosition {
  146. type = 'Logical'
  147. x: number
  148. y: number
  149. constructor(x: number, y: number) {
  150. this.x = x
  151. this.y = y
  152. }
  153. }
  154. /**
  155. * A position represented in physical pixels.
  156. *
  157. * @since 1.0.0
  158. */
  159. class PhysicalPosition {
  160. type = 'Physical'
  161. x: number
  162. y: number
  163. constructor(x: number, y: number) {
  164. this.x = x
  165. this.y = y
  166. }
  167. /**
  168. * Converts the physical position to a logical one.
  169. * @example
  170. * ```typescript
  171. * import { appWindow } from '@tauri-apps/api/window';
  172. * const factor = await appWindow.scaleFactor();
  173. * const position = await appWindow.innerPosition();
  174. * const logical = position.toLogical(factor);
  175. * ```
  176. * */
  177. toLogical(scaleFactor: number): LogicalPosition {
  178. return new LogicalPosition(this.x / scaleFactor, this.y / scaleFactor)
  179. }
  180. }
  181. /** @ignore */
  182. interface WindowDef {
  183. label: string
  184. }
  185. /** @ignore */
  186. declare global {
  187. interface Window {
  188. __TAURI_METADATA__: {
  189. __windows: WindowDef[]
  190. __currentWindow: WindowDef
  191. }
  192. }
  193. }
  194. /**
  195. * Attention type to request on a window.
  196. *
  197. * @since 1.0.0
  198. */
  199. enum UserAttentionType {
  200. /**
  201. * #### Platform-specific
  202. * - **macOS:** Bounces the dock icon until the application is in focus.
  203. * - **Windows:** Flashes both the window and the taskbar button until the application is in focus.
  204. */
  205. Critical = 1,
  206. /**
  207. * #### Platform-specific
  208. * - **macOS:** Bounces the dock icon once.
  209. * - **Windows:** Flashes the taskbar button until the application is in focus.
  210. */
  211. Informational
  212. }
  213. export type CursorIcon =
  214. | 'default'
  215. | 'crosshair'
  216. | 'hand'
  217. | 'arrow'
  218. | 'move'
  219. | 'text'
  220. | 'wait'
  221. | 'help'
  222. | 'progress'
  223. // something cannot be done
  224. | 'notAllowed'
  225. | 'contextMenu'
  226. | 'cell'
  227. | 'verticalText'
  228. | 'alias'
  229. | 'copy'
  230. | 'noDrop'
  231. // something can be grabbed
  232. | 'grab'
  233. /// something is grabbed
  234. | 'grabbing'
  235. | 'allScroll'
  236. | 'zoomIn'
  237. | 'zoomOut'
  238. // edge is to be moved
  239. | 'eResize'
  240. | 'nResize'
  241. | 'neResize'
  242. | 'nwResize'
  243. | 'sResize'
  244. | 'seResize'
  245. | 'swResize'
  246. | 'wResize'
  247. | 'ewResize'
  248. | 'nsResize'
  249. | 'neswResize'
  250. | 'nwseResize'
  251. | 'colResize'
  252. | 'rowResize'
  253. /**
  254. * Get an instance of `WebviewWindow` for the current webview window.
  255. *
  256. * @since 1.0.0
  257. */
  258. function getCurrent(): WebviewWindow {
  259. return new WebviewWindow(window.__TAURI_METADATA__.__currentWindow.label, {
  260. // @ts-expect-error
  261. skip: true
  262. })
  263. }
  264. /**
  265. * Gets a list of instances of `WebviewWindow` for all available webview windows.
  266. *
  267. * @since 1.0.0
  268. */
  269. function getAll(): WebviewWindow[] {
  270. return window.__TAURI_METADATA__.__windows.map(
  271. (w) =>
  272. new WebviewWindow(w.label, {
  273. // @ts-expect-error
  274. skip: true
  275. })
  276. )
  277. }
  278. /** @ignore */
  279. // events that are emitted right here instead of by the created webview
  280. const localTauriEvents = ['tauri://created', 'tauri://error']
  281. /** @ignore */
  282. export type WindowLabel = string
  283. /**
  284. * A webview window handle allows emitting and listening to events from the backend that are tied to the window.
  285. *
  286. * @since 1.0.0
  287. */
  288. class WebviewWindowHandle {
  289. /** The window label. It is a unique identifier for the window, can be used to reference it later. */
  290. label: WindowLabel
  291. /** Local event listeners. */
  292. listeners: { [key: string]: Array<EventCallback<any>> }
  293. constructor(label: WindowLabel) {
  294. this.label = label
  295. // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
  296. this.listeners = Object.create(null)
  297. }
  298. /**
  299. * Listen to an event emitted by the backend that is tied to the webview window.
  300. *
  301. * @example
  302. * ```typescript
  303. * import { appWindow } from '@tauri-apps/api/window';
  304. * const unlisten = await appWindow.listen<string>('state-changed', (event) => {
  305. * console.log(`Got error: ${payload}`);
  306. * });
  307. *
  308. * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
  309. * unlisten();
  310. * ```
  311. *
  312. * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`.
  313. * @param handler Event handler.
  314. * @returns A promise resolving to a function to unlisten to the event.
  315. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
  316. */
  317. async listen<T>(
  318. event: EventName,
  319. handler: EventCallback<T>
  320. ): Promise<UnlistenFn> {
  321. if (this._handleTauriEvent(event, handler)) {
  322. return Promise.resolve(() => {
  323. // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, security/detect-object-injection
  324. const listeners = this.listeners[event]
  325. listeners.splice(listeners.indexOf(handler), 1)
  326. })
  327. }
  328. return listen(event, this.label, handler)
  329. }
  330. /**
  331. * Listen to an one-off event emitted by the backend that is tied to the webview window.
  332. *
  333. * @example
  334. * ```typescript
  335. * import { appWindow } from '@tauri-apps/api/window';
  336. * const unlisten = await appWindow.once<null>('initialized', (event) => {
  337. * console.log(`Window initialized!`);
  338. * });
  339. *
  340. * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
  341. * unlisten();
  342. * ```
  343. *
  344. * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`.
  345. * @param handler Event handler.
  346. * @returns A promise resolving to a function to unlisten to the event.
  347. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
  348. */
  349. async once<T>(event: string, handler: EventCallback<T>): Promise<UnlistenFn> {
  350. if (this._handleTauriEvent(event, handler)) {
  351. return Promise.resolve(() => {
  352. // eslint-disable-next-line security/detect-object-injection
  353. const listeners = this.listeners[event]
  354. listeners.splice(listeners.indexOf(handler), 1)
  355. })
  356. }
  357. return once(event, this.label, handler)
  358. }
  359. /**
  360. * Emits an event to the backend, tied to the webview window.
  361. * @example
  362. * ```typescript
  363. * import { appWindow } from '@tauri-apps/api/window';
  364. * await appWindow.emit('window-loaded', { loggedIn: true, token: 'authToken' });
  365. * ```
  366. *
  367. * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`.
  368. * @param payload Event payload.
  369. */
  370. async emit(event: string, payload?: unknown): Promise<void> {
  371. if (localTauriEvents.includes(event)) {
  372. // eslint-disable-next-line
  373. for (const handler of this.listeners[event] || []) {
  374. handler({ event, id: -1, windowLabel: this.label, payload })
  375. }
  376. return Promise.resolve()
  377. }
  378. return emit(event, this.label, payload)
  379. }
  380. _handleTauriEvent<T>(event: string, handler: EventCallback<T>): boolean {
  381. if (localTauriEvents.includes(event)) {
  382. if (!(event in this.listeners)) {
  383. // eslint-disable-next-line
  384. this.listeners[event] = [handler]
  385. } else {
  386. // eslint-disable-next-line
  387. this.listeners[event].push(handler)
  388. }
  389. return true
  390. }
  391. return false
  392. }
  393. }
  394. /**
  395. * Manage the current window object.
  396. *
  397. * @since 1.0.0
  398. */
  399. class WindowManager extends WebviewWindowHandle {
  400. // Getters
  401. /**
  402. * The scale factor that can be used to map physical pixels to logical pixels.
  403. * @example
  404. * ```typescript
  405. * import { appWindow } from '@tauri-apps/api/window';
  406. * const factor = await appWindow.scaleFactor();
  407. * ```
  408. *
  409. * @returns The window's monitor scale factor.
  410. * */
  411. async scaleFactor(): Promise<number> {
  412. return invokeTauriCommand({
  413. __tauriModule: 'Window',
  414. message: {
  415. cmd: 'manage',
  416. data: {
  417. label: this.label,
  418. cmd: {
  419. type: 'scaleFactor'
  420. }
  421. }
  422. }
  423. })
  424. }
  425. /**
  426. * The position of the top-left hand corner of the window's client area relative to the top-left hand corner of the desktop.
  427. * @example
  428. * ```typescript
  429. * import { appWindow } from '@tauri-apps/api/window';
  430. * const position = await appWindow.innerPosition();
  431. * ```
  432. *
  433. * @returns The window's inner position.
  434. * */
  435. async innerPosition(): Promise<PhysicalPosition> {
  436. return invokeTauriCommand<{ x: number; y: number }>({
  437. __tauriModule: 'Window',
  438. message: {
  439. cmd: 'manage',
  440. data: {
  441. label: this.label,
  442. cmd: {
  443. type: 'innerPosition'
  444. }
  445. }
  446. }
  447. }).then(({ x, y }) => new PhysicalPosition(x, y))
  448. }
  449. /**
  450. * The position of the top-left hand corner of the window relative to the top-left hand corner of the desktop.
  451. * @example
  452. * ```typescript
  453. * import { appWindow } from '@tauri-apps/api/window';
  454. * const position = await appWindow.outerPosition();
  455. * ```
  456. *
  457. * @returns The window's outer position.
  458. * */
  459. async outerPosition(): Promise<PhysicalPosition> {
  460. return invokeTauriCommand<{ x: number; y: number }>({
  461. __tauriModule: 'Window',
  462. message: {
  463. cmd: 'manage',
  464. data: {
  465. label: this.label,
  466. cmd: {
  467. type: 'outerPosition'
  468. }
  469. }
  470. }
  471. }).then(({ x, y }) => new PhysicalPosition(x, y))
  472. }
  473. /**
  474. * The physical size of the window's client area.
  475. * The client area is the content of the window, excluding the title bar and borders.
  476. * @example
  477. * ```typescript
  478. * import { appWindow } from '@tauri-apps/api/window';
  479. * const size = await appWindow.innerSize();
  480. * ```
  481. *
  482. * @returns The window's inner size.
  483. */
  484. async innerSize(): Promise<PhysicalSize> {
  485. return invokeTauriCommand<{ width: number; height: number }>({
  486. __tauriModule: 'Window',
  487. message: {
  488. cmd: 'manage',
  489. data: {
  490. label: this.label,
  491. cmd: {
  492. type: 'innerSize'
  493. }
  494. }
  495. }
  496. }).then(({ width, height }) => new PhysicalSize(width, height))
  497. }
  498. /**
  499. * The physical size of the entire window.
  500. * These dimensions include the title bar and borders. If you don't want that (and you usually don't), use inner_size instead.
  501. * @example
  502. * ```typescript
  503. * import { appWindow } from '@tauri-apps/api/window';
  504. * const size = await appWindow.outerSize();
  505. * ```
  506. *
  507. * @returns The window's outer size.
  508. */
  509. async outerSize(): Promise<PhysicalSize> {
  510. return invokeTauriCommand<{ width: number; height: number }>({
  511. __tauriModule: 'Window',
  512. message: {
  513. cmd: 'manage',
  514. data: {
  515. label: this.label,
  516. cmd: {
  517. type: 'outerSize'
  518. }
  519. }
  520. }
  521. }).then(({ width, height }) => new PhysicalSize(width, height))
  522. }
  523. /**
  524. * Gets the window's current fullscreen state.
  525. * @example
  526. * ```typescript
  527. * import { appWindow } from '@tauri-apps/api/window';
  528. * const fullscreen = await appWindow.isFullscreen();
  529. * ```
  530. *
  531. * @returns Whether the window is in fullscreen mode or not.
  532. * */
  533. async isFullscreen(): Promise<boolean> {
  534. return invokeTauriCommand({
  535. __tauriModule: 'Window',
  536. message: {
  537. cmd: 'manage',
  538. data: {
  539. label: this.label,
  540. cmd: {
  541. type: 'isFullscreen'
  542. }
  543. }
  544. }
  545. })
  546. }
  547. /**
  548. * Gets the window's current maximized state.
  549. * @example
  550. * ```typescript
  551. * import { appWindow } from '@tauri-apps/api/window';
  552. * const maximized = await appWindow.isMaximized();
  553. * ```
  554. *
  555. * @returns Whether the window is maximized or not.
  556. * */
  557. async isMaximized(): Promise<boolean> {
  558. return invokeTauriCommand({
  559. __tauriModule: 'Window',
  560. message: {
  561. cmd: 'manage',
  562. data: {
  563. label: this.label,
  564. cmd: {
  565. type: 'isMaximized'
  566. }
  567. }
  568. }
  569. })
  570. }
  571. /**
  572. * Gets the window's current decorated state.
  573. * @example
  574. * ```typescript
  575. * import { appWindow } from '@tauri-apps/api/window';
  576. * const decorated = await appWindow.isDecorated();
  577. * ```
  578. *
  579. * @returns Whether the window is decorated or not.
  580. * */
  581. async isDecorated(): Promise<boolean> {
  582. return invokeTauriCommand({
  583. __tauriModule: 'Window',
  584. message: {
  585. cmd: 'manage',
  586. data: {
  587. label: this.label,
  588. cmd: {
  589. type: 'isDecorated'
  590. }
  591. }
  592. }
  593. })
  594. }
  595. /**
  596. * Gets the window's current resizable state.
  597. * @example
  598. * ```typescript
  599. * import { appWindow } from '@tauri-apps/api/window';
  600. * const resizable = await appWindow.isResizable();
  601. * ```
  602. *
  603. * @returns Whether the window is resizable or not.
  604. * */
  605. async isResizable(): Promise<boolean> {
  606. return invokeTauriCommand({
  607. __tauriModule: 'Window',
  608. message: {
  609. cmd: 'manage',
  610. data: {
  611. label: this.label,
  612. cmd: {
  613. type: 'isResizable'
  614. }
  615. }
  616. }
  617. })
  618. }
  619. /**
  620. * Gets the window's current visible state.
  621. * @example
  622. * ```typescript
  623. * import { appWindow } from '@tauri-apps/api/window';
  624. * const visible = await appWindow.isVisible();
  625. * ```
  626. *
  627. * @returns Whether the window is visible or not.
  628. * */
  629. async isVisible(): Promise<boolean> {
  630. return invokeTauriCommand({
  631. __tauriModule: 'Window',
  632. message: {
  633. cmd: 'manage',
  634. data: {
  635. label: this.label,
  636. cmd: {
  637. type: 'isVisible'
  638. }
  639. }
  640. }
  641. })
  642. }
  643. /**
  644. * Gets the window's current theme.
  645. *
  646. * #### Platform-specific
  647. *
  648. * - **Linux:** Not implemented, always returns `light`.
  649. * - **macOS:** Theme was introduced on macOS 10.14. Returns `light` on macOS 10.13 and below.
  650. *
  651. * @example
  652. * ```typescript
  653. * import { appWindow } from '@tauri-apps/api/window';
  654. * const theme = await appWindow.theme();
  655. * ```
  656. *
  657. * @returns The window theme.
  658. * */
  659. async theme(): Promise<Theme | null> {
  660. return invokeTauriCommand({
  661. __tauriModule: 'Window',
  662. message: {
  663. cmd: 'manage',
  664. data: {
  665. label: this.label,
  666. cmd: {
  667. type: 'theme'
  668. }
  669. }
  670. }
  671. })
  672. }
  673. // Setters
  674. /**
  675. * Centers the window.
  676. * @example
  677. * ```typescript
  678. * import { appWindow } from '@tauri-apps/api/window';
  679. * await appWindow.center();
  680. * ```
  681. *
  682. * @param resizable
  683. * @returns A promise indicating the success or failure of the operation.
  684. */
  685. async center(): Promise<void> {
  686. return invokeTauriCommand({
  687. __tauriModule: 'Window',
  688. message: {
  689. cmd: 'manage',
  690. data: {
  691. label: this.label,
  692. cmd: {
  693. type: 'center'
  694. }
  695. }
  696. }
  697. })
  698. }
  699. /**
  700. * Requests user attention to the window, this has no effect if the application
  701. * is already focused. How requesting for user attention manifests is platform dependent,
  702. * see `UserAttentionType` for details.
  703. *
  704. * Providing `null` will unset the request for user attention. Unsetting the request for
  705. * user attention might not be done automatically by the WM when the window receives input.
  706. *
  707. * #### Platform-specific
  708. *
  709. * - **macOS:** `null` has no effect.
  710. * - **Linux:** Urgency levels have the same effect.
  711. * @example
  712. * ```typescript
  713. * import { appWindow } from '@tauri-apps/api/window';
  714. * await appWindow.requestUserAttention();
  715. * ```
  716. *
  717. * @param resizable
  718. * @returns A promise indicating the success or failure of the operation.
  719. */
  720. async requestUserAttention(
  721. requestType: UserAttentionType | null
  722. ): Promise<void> {
  723. let requestType_ = null
  724. if (requestType) {
  725. if (requestType === UserAttentionType.Critical) {
  726. requestType_ = { type: 'Critical' }
  727. } else {
  728. requestType_ = { type: 'Informational' }
  729. }
  730. }
  731. return invokeTauriCommand({
  732. __tauriModule: 'Window',
  733. message: {
  734. cmd: 'manage',
  735. data: {
  736. label: this.label,
  737. cmd: {
  738. type: 'requestUserAttention',
  739. payload: requestType_
  740. }
  741. }
  742. }
  743. })
  744. }
  745. /**
  746. * Updates the window resizable flag.
  747. * @example
  748. * ```typescript
  749. * import { appWindow } from '@tauri-apps/api/window';
  750. * await appWindow.setResizable(false);
  751. * ```
  752. *
  753. * @param resizable
  754. * @returns A promise indicating the success or failure of the operation.
  755. */
  756. async setResizable(resizable: boolean): Promise<void> {
  757. return invokeTauriCommand({
  758. __tauriModule: 'Window',
  759. message: {
  760. cmd: 'manage',
  761. data: {
  762. label: this.label,
  763. cmd: {
  764. type: 'setResizable',
  765. payload: resizable
  766. }
  767. }
  768. }
  769. })
  770. }
  771. /**
  772. * Sets the window title.
  773. * @example
  774. * ```typescript
  775. * import { appWindow } from '@tauri-apps/api/window';
  776. * await appWindow.setTitle('Tauri');
  777. * ```
  778. *
  779. * @param title The new title
  780. * @returns A promise indicating the success or failure of the operation.
  781. */
  782. async setTitle(title: string): Promise<void> {
  783. return invokeTauriCommand({
  784. __tauriModule: 'Window',
  785. message: {
  786. cmd: 'manage',
  787. data: {
  788. label: this.label,
  789. cmd: {
  790. type: 'setTitle',
  791. payload: title
  792. }
  793. }
  794. }
  795. })
  796. }
  797. /**
  798. * Maximizes the window.
  799. * @example
  800. * ```typescript
  801. * import { appWindow } from '@tauri-apps/api/window';
  802. * await appWindow.maximize();
  803. * ```
  804. *
  805. * @returns A promise indicating the success or failure of the operation.
  806. */
  807. async maximize(): Promise<void> {
  808. return invokeTauriCommand({
  809. __tauriModule: 'Window',
  810. message: {
  811. cmd: 'manage',
  812. data: {
  813. label: this.label,
  814. cmd: {
  815. type: 'maximize'
  816. }
  817. }
  818. }
  819. })
  820. }
  821. /**
  822. * Unmaximizes the window.
  823. * @example
  824. * ```typescript
  825. * import { appWindow } from '@tauri-apps/api/window';
  826. * await appWindow.unmaximize();
  827. * ```
  828. *
  829. * @returns A promise indicating the success or failure of the operation.
  830. */
  831. async unmaximize(): Promise<void> {
  832. return invokeTauriCommand({
  833. __tauriModule: 'Window',
  834. message: {
  835. cmd: 'manage',
  836. data: {
  837. label: this.label,
  838. cmd: {
  839. type: 'unmaximize'
  840. }
  841. }
  842. }
  843. })
  844. }
  845. /**
  846. * Toggles the window maximized state.
  847. * @example
  848. * ```typescript
  849. * import { appWindow } from '@tauri-apps/api/window';
  850. * await appWindow.toggleMaximize();
  851. * ```
  852. *
  853. * @returns A promise indicating the success or failure of the operation.
  854. */
  855. async toggleMaximize(): Promise<void> {
  856. return invokeTauriCommand({
  857. __tauriModule: 'Window',
  858. message: {
  859. cmd: 'manage',
  860. data: {
  861. label: this.label,
  862. cmd: {
  863. type: 'toggleMaximize'
  864. }
  865. }
  866. }
  867. })
  868. }
  869. /**
  870. * Minimizes the window.
  871. * @example
  872. * ```typescript
  873. * import { appWindow } from '@tauri-apps/api/window';
  874. * await appWindow.minimize();
  875. * ```
  876. *
  877. * @returns A promise indicating the success or failure of the operation.
  878. */
  879. async minimize(): Promise<void> {
  880. return invokeTauriCommand({
  881. __tauriModule: 'Window',
  882. message: {
  883. cmd: 'manage',
  884. data: {
  885. label: this.label,
  886. cmd: {
  887. type: 'minimize'
  888. }
  889. }
  890. }
  891. })
  892. }
  893. /**
  894. * Unminimizes the window.
  895. * @example
  896. * ```typescript
  897. * import { appWindow } from '@tauri-apps/api/window';
  898. * await appWindow.unminimize();
  899. * ```
  900. *
  901. * @returns A promise indicating the success or failure of the operation.
  902. */
  903. async unminimize(): Promise<void> {
  904. return invokeTauriCommand({
  905. __tauriModule: 'Window',
  906. message: {
  907. cmd: 'manage',
  908. data: {
  909. label: this.label,
  910. cmd: {
  911. type: 'unminimize'
  912. }
  913. }
  914. }
  915. })
  916. }
  917. /**
  918. * Sets the window visibility to true.
  919. * @example
  920. * ```typescript
  921. * import { appWindow } from '@tauri-apps/api/window';
  922. * await appWindow.show();
  923. * ```
  924. *
  925. * @returns A promise indicating the success or failure of the operation.
  926. */
  927. async show(): Promise<void> {
  928. return invokeTauriCommand({
  929. __tauriModule: 'Window',
  930. message: {
  931. cmd: 'manage',
  932. data: {
  933. label: this.label,
  934. cmd: {
  935. type: 'show'
  936. }
  937. }
  938. }
  939. })
  940. }
  941. /**
  942. * Sets the window visibility to false.
  943. * @example
  944. * ```typescript
  945. * import { appWindow } from '@tauri-apps/api/window';
  946. * await appWindow.hide();
  947. * ```
  948. *
  949. * @returns A promise indicating the success or failure of the operation.
  950. */
  951. async hide(): Promise<void> {
  952. return invokeTauriCommand({
  953. __tauriModule: 'Window',
  954. message: {
  955. cmd: 'manage',
  956. data: {
  957. label: this.label,
  958. cmd: {
  959. type: 'hide'
  960. }
  961. }
  962. }
  963. })
  964. }
  965. /**
  966. * Closes the window.
  967. * @example
  968. * ```typescript
  969. * import { appWindow } from '@tauri-apps/api/window';
  970. * await appWindow.close();
  971. * ```
  972. *
  973. * @returns A promise indicating the success or failure of the operation.
  974. */
  975. async close(): Promise<void> {
  976. return invokeTauriCommand({
  977. __tauriModule: 'Window',
  978. message: {
  979. cmd: 'manage',
  980. data: {
  981. label: this.label,
  982. cmd: {
  983. type: 'close'
  984. }
  985. }
  986. }
  987. })
  988. }
  989. /**
  990. * Whether the window should have borders and bars.
  991. * @example
  992. * ```typescript
  993. * import { appWindow } from '@tauri-apps/api/window';
  994. * await appWindow.setDecorations(false);
  995. * ```
  996. *
  997. * @param decorations Whether the window should have borders and bars.
  998. * @returns A promise indicating the success or failure of the operation.
  999. */
  1000. async setDecorations(decorations: boolean): Promise<void> {
  1001. return invokeTauriCommand({
  1002. __tauriModule: 'Window',
  1003. message: {
  1004. cmd: 'manage',
  1005. data: {
  1006. label: this.label,
  1007. cmd: {
  1008. type: 'setDecorations',
  1009. payload: decorations
  1010. }
  1011. }
  1012. }
  1013. })
  1014. }
  1015. /**
  1016. * Whether the window should always be on top of other windows.
  1017. * @example
  1018. * ```typescript
  1019. * import { appWindow } from '@tauri-apps/api/window';
  1020. * await appWindow.setAlwaysOnTop(true);
  1021. * ```
  1022. *
  1023. * @param alwaysOnTop Whether the window should always be on top of other windows or not.
  1024. * @returns A promise indicating the success or failure of the operation.
  1025. */
  1026. async setAlwaysOnTop(alwaysOnTop: boolean): Promise<void> {
  1027. return invokeTauriCommand({
  1028. __tauriModule: 'Window',
  1029. message: {
  1030. cmd: 'manage',
  1031. data: {
  1032. label: this.label,
  1033. cmd: {
  1034. type: 'setAlwaysOnTop',
  1035. payload: alwaysOnTop
  1036. }
  1037. }
  1038. }
  1039. })
  1040. }
  1041. /**
  1042. * Resizes the window with a new inner size.
  1043. * @example
  1044. * ```typescript
  1045. * import { appWindow, LogicalSize } from '@tauri-apps/api/window';
  1046. * await appWindow.setSize(new LogicalSize(600, 500));
  1047. * ```
  1048. *
  1049. * @param size The logical or physical inner size.
  1050. * @returns A promise indicating the success or failure of the operation.
  1051. */
  1052. async setSize(size: LogicalSize | PhysicalSize): Promise<void> {
  1053. if (!size || (size.type !== 'Logical' && size.type !== 'Physical')) {
  1054. throw new Error(
  1055. 'the `size` argument must be either a LogicalSize or a PhysicalSize instance'
  1056. )
  1057. }
  1058. return invokeTauriCommand({
  1059. __tauriModule: 'Window',
  1060. message: {
  1061. cmd: 'manage',
  1062. data: {
  1063. label: this.label,
  1064. cmd: {
  1065. type: 'setSize',
  1066. payload: {
  1067. type: size.type,
  1068. data: {
  1069. width: size.width,
  1070. height: size.height
  1071. }
  1072. }
  1073. }
  1074. }
  1075. }
  1076. })
  1077. }
  1078. /**
  1079. * Sets the window minimum inner size. If the `size` argument is not provided, the constraint is unset.
  1080. * @example
  1081. * ```typescript
  1082. * import { appWindow, PhysicalSize } from '@tauri-apps/api/window';
  1083. * await appWindow.setMinSize(new PhysicalSize(600, 500));
  1084. * ```
  1085. *
  1086. * @param size The logical or physical inner size, or `null` to unset the constraint.
  1087. * @returns A promise indicating the success or failure of the operation.
  1088. */
  1089. async setMinSize(
  1090. size: LogicalSize | PhysicalSize | null | undefined
  1091. ): Promise<void> {
  1092. if (size && size.type !== 'Logical' && size.type !== 'Physical') {
  1093. throw new Error(
  1094. 'the `size` argument must be either a LogicalSize or a PhysicalSize instance'
  1095. )
  1096. }
  1097. return invokeTauriCommand({
  1098. __tauriModule: 'Window',
  1099. message: {
  1100. cmd: 'manage',
  1101. data: {
  1102. label: this.label,
  1103. cmd: {
  1104. type: 'setMinSize',
  1105. payload: size
  1106. ? {
  1107. type: size.type,
  1108. data: {
  1109. width: size.width,
  1110. height: size.height
  1111. }
  1112. }
  1113. : null
  1114. }
  1115. }
  1116. }
  1117. })
  1118. }
  1119. /**
  1120. * Sets the window maximum inner size. If the `size` argument is undefined, the constraint is unset.
  1121. * @example
  1122. * ```typescript
  1123. * import { appWindow, LogicalSize } from '@tauri-apps/api/window';
  1124. * await appWindow.setMaxSize(new LogicalSize(600, 500));
  1125. * ```
  1126. *
  1127. * @param size The logical or physical inner size, or `null` to unset the constraint.
  1128. * @returns A promise indicating the success or failure of the operation.
  1129. */
  1130. async setMaxSize(
  1131. size: LogicalSize | PhysicalSize | null | undefined
  1132. ): Promise<void> {
  1133. if (size && size.type !== 'Logical' && size.type !== 'Physical') {
  1134. throw new Error(
  1135. 'the `size` argument must be either a LogicalSize or a PhysicalSize instance'
  1136. )
  1137. }
  1138. return invokeTauriCommand({
  1139. __tauriModule: 'Window',
  1140. message: {
  1141. cmd: 'manage',
  1142. data: {
  1143. label: this.label,
  1144. cmd: {
  1145. type: 'setMaxSize',
  1146. payload: size
  1147. ? {
  1148. type: size.type,
  1149. data: {
  1150. width: size.width,
  1151. height: size.height
  1152. }
  1153. }
  1154. : null
  1155. }
  1156. }
  1157. }
  1158. })
  1159. }
  1160. /**
  1161. * Sets the window outer position.
  1162. * @example
  1163. * ```typescript
  1164. * import { appWindow, LogicalPosition } from '@tauri-apps/api/window';
  1165. * await appWindow.setPosition(new LogicalPosition(600, 500));
  1166. * ```
  1167. *
  1168. * @param position The new position, in logical or physical pixels.
  1169. * @returns A promise indicating the success or failure of the operation.
  1170. */
  1171. async setPosition(
  1172. position: LogicalPosition | PhysicalPosition
  1173. ): Promise<void> {
  1174. if (
  1175. !position ||
  1176. (position.type !== 'Logical' && position.type !== 'Physical')
  1177. ) {
  1178. throw new Error(
  1179. 'the `position` argument must be either a LogicalPosition or a PhysicalPosition instance'
  1180. )
  1181. }
  1182. return invokeTauriCommand({
  1183. __tauriModule: 'Window',
  1184. message: {
  1185. cmd: 'manage',
  1186. data: {
  1187. label: this.label,
  1188. cmd: {
  1189. type: 'setPosition',
  1190. payload: {
  1191. type: position.type,
  1192. data: {
  1193. x: position.x,
  1194. y: position.y
  1195. }
  1196. }
  1197. }
  1198. }
  1199. }
  1200. })
  1201. }
  1202. /**
  1203. * Sets the window fullscreen state.
  1204. * @example
  1205. * ```typescript
  1206. * import { appWindow } from '@tauri-apps/api/window';
  1207. * await appWindow.setFullscreen(true);
  1208. * ```
  1209. *
  1210. * @param fullscreen Whether the window should go to fullscreen or not.
  1211. * @returns A promise indicating the success or failure of the operation.
  1212. */
  1213. async setFullscreen(fullscreen: boolean): Promise<void> {
  1214. return invokeTauriCommand({
  1215. __tauriModule: 'Window',
  1216. message: {
  1217. cmd: 'manage',
  1218. data: {
  1219. label: this.label,
  1220. cmd: {
  1221. type: 'setFullscreen',
  1222. payload: fullscreen
  1223. }
  1224. }
  1225. }
  1226. })
  1227. }
  1228. /**
  1229. * Bring the window to front and focus.
  1230. * @example
  1231. * ```typescript
  1232. * import { appWindow } from '@tauri-apps/api/window';
  1233. * await appWindow.setFocus();
  1234. * ```
  1235. *
  1236. * @returns A promise indicating the success or failure of the operation.
  1237. */
  1238. async setFocus(): Promise<void> {
  1239. return invokeTauriCommand({
  1240. __tauriModule: 'Window',
  1241. message: {
  1242. cmd: 'manage',
  1243. data: {
  1244. label: this.label,
  1245. cmd: {
  1246. type: 'setFocus'
  1247. }
  1248. }
  1249. }
  1250. })
  1251. }
  1252. /**
  1253. * Sets the window icon.
  1254. * @example
  1255. * ```typescript
  1256. * import { appWindow } from '@tauri-apps/api/window';
  1257. * await appWindow.setIcon('/tauri/awesome.png');
  1258. * ```
  1259. *
  1260. * Note that you need the `icon-ico` or `icon-png` Cargo features to use this API.
  1261. * To enable it, change your Cargo.toml file:
  1262. * ```toml
  1263. * [dependencies]
  1264. * tauri = { version = "...", features = ["...", "icon-png"] }
  1265. * ```
  1266. *
  1267. * @param icon Icon bytes or path to the icon file.
  1268. * @returns A promise indicating the success or failure of the operation.
  1269. */
  1270. async setIcon(icon: string | Uint8Array): Promise<void> {
  1271. return invokeTauriCommand({
  1272. __tauriModule: 'Window',
  1273. message: {
  1274. cmd: 'manage',
  1275. data: {
  1276. label: this.label,
  1277. cmd: {
  1278. type: 'setIcon',
  1279. payload: {
  1280. // correctly serialize Uint8Arrays
  1281. icon: typeof icon === 'string' ? icon : Array.from(icon)
  1282. }
  1283. }
  1284. }
  1285. }
  1286. })
  1287. }
  1288. /**
  1289. * Whether to show the window icon in the task bar or not.
  1290. * @example
  1291. * ```typescript
  1292. * import { appWindow } from '@tauri-apps/api/window';
  1293. * await appWindow.setSkipTaskbar(true);
  1294. * ```
  1295. *
  1296. * @param skip true to hide window icon, false to show it.
  1297. * @returns A promise indicating the success or failure of the operation.
  1298. */
  1299. async setSkipTaskbar(skip: boolean): Promise<void> {
  1300. return invokeTauriCommand({
  1301. __tauriModule: 'Window',
  1302. message: {
  1303. cmd: 'manage',
  1304. data: {
  1305. label: this.label,
  1306. cmd: {
  1307. type: 'setSkipTaskbar',
  1308. payload: skip
  1309. }
  1310. }
  1311. }
  1312. })
  1313. }
  1314. /**
  1315. * Grabs the cursor, preventing it from leaving the window.
  1316. *
  1317. * There's no guarantee that the cursor will be hidden. You should
  1318. * hide it by yourself if you want so.
  1319. *
  1320. * #### Platform-specific
  1321. *
  1322. * - **Linux:** Unsupported.
  1323. * - **macOS:** This locks the cursor in a fixed location, which looks visually awkward.
  1324. * @example
  1325. * ```typescript
  1326. * import { appWindow } from '@tauri-apps/api/window';
  1327. * await appWindow.setCursorGrab(true);
  1328. * ```
  1329. *
  1330. * @param grab `true` to grab the cursor icon, `false` to release it.
  1331. * @returns A promise indicating the success or failure of the operation.
  1332. */
  1333. async setCursorGrab(grab: boolean): Promise<void> {
  1334. return invokeTauriCommand({
  1335. __tauriModule: 'Window',
  1336. message: {
  1337. cmd: 'manage',
  1338. data: {
  1339. label: this.label,
  1340. cmd: {
  1341. type: 'setCursorGrab',
  1342. payload: grab
  1343. }
  1344. }
  1345. }
  1346. })
  1347. }
  1348. /**
  1349. * Modifies the cursor's visibility.
  1350. *
  1351. * #### Platform-specific
  1352. *
  1353. * - **Windows:** The cursor is only hidden within the confines of the window.
  1354. * - **macOS:** The cursor is hidden as long as the window has input focus, even if the cursor is
  1355. * outside of the window.
  1356. * @example
  1357. * ```typescript
  1358. * import { appWindow } from '@tauri-apps/api/window';
  1359. * await appWindow.setCursorVisible(false);
  1360. * ```
  1361. *
  1362. * @param visible If `false`, this will hide the cursor. If `true`, this will show the cursor.
  1363. * @returns A promise indicating the success or failure of the operation.
  1364. */
  1365. async setCursorVisible(visible: boolean): Promise<void> {
  1366. return invokeTauriCommand({
  1367. __tauriModule: 'Window',
  1368. message: {
  1369. cmd: 'manage',
  1370. data: {
  1371. label: this.label,
  1372. cmd: {
  1373. type: 'setCursorVisible',
  1374. payload: visible
  1375. }
  1376. }
  1377. }
  1378. })
  1379. }
  1380. /**
  1381. * Modifies the cursor icon of the window.
  1382. * @example
  1383. * ```typescript
  1384. * import { appWindow } from '@tauri-apps/api/window';
  1385. * await appWindow.setCursorIcon('help');
  1386. * ```
  1387. *
  1388. * @param icon The new cursor icon.
  1389. * @returns A promise indicating the success or failure of the operation.
  1390. */
  1391. async setCursorIcon(icon: CursorIcon): Promise<void> {
  1392. return invokeTauriCommand({
  1393. __tauriModule: 'Window',
  1394. message: {
  1395. cmd: 'manage',
  1396. data: {
  1397. label: this.label,
  1398. cmd: {
  1399. type: 'setCursorIcon',
  1400. payload: icon
  1401. }
  1402. }
  1403. }
  1404. })
  1405. }
  1406. /**
  1407. * Changes the position of the cursor in window coordinates.
  1408. * @example
  1409. * ```typescript
  1410. * import { appWindow, LogicalPosition } from '@tauri-apps/api/window';
  1411. * await appWindow.setCursorPosition(new LogicalPosition(600, 300));
  1412. * ```
  1413. *
  1414. * @param position The new cursor position.
  1415. * @returns A promise indicating the success or failure of the operation.
  1416. */
  1417. async setCursorPosition(
  1418. position: LogicalPosition | PhysicalPosition
  1419. ): Promise<void> {
  1420. if (
  1421. !position ||
  1422. (position.type !== 'Logical' && position.type !== 'Physical')
  1423. ) {
  1424. throw new Error(
  1425. 'the `position` argument must be either a LogicalPosition or a PhysicalPosition instance'
  1426. )
  1427. }
  1428. return invokeTauriCommand({
  1429. __tauriModule: 'Window',
  1430. message: {
  1431. cmd: 'manage',
  1432. data: {
  1433. label: this.label,
  1434. cmd: {
  1435. type: 'setCursorPosition',
  1436. payload: {
  1437. type: position.type,
  1438. data: {
  1439. x: position.x,
  1440. y: position.y
  1441. }
  1442. }
  1443. }
  1444. }
  1445. }
  1446. })
  1447. }
  1448. /**
  1449. * Changes the cursor events behavior.
  1450. *
  1451. * @example
  1452. * ```typescript
  1453. * import { appWindow } from '@tauri-apps/api/window';
  1454. * await appWindow.setIgnoreCursorEvents(true);
  1455. * ```
  1456. *
  1457. * @param ignore `true` to ignore the cursor events; `false` to process them as usual.
  1458. * @returns A promise indicating the success or failure of the operation.
  1459. */
  1460. async setIgnoreCursorEvents(ignore: boolean): Promise<void> {
  1461. return invokeTauriCommand({
  1462. __tauriModule: 'Window',
  1463. message: {
  1464. cmd: 'manage',
  1465. data: {
  1466. label: this.label,
  1467. cmd: {
  1468. type: 'setIgnoreCursorEvents',
  1469. payload: ignore
  1470. }
  1471. }
  1472. }
  1473. })
  1474. }
  1475. /**
  1476. * Starts dragging the window.
  1477. * @example
  1478. * ```typescript
  1479. * import { appWindow } from '@tauri-apps/api/window';
  1480. * await appWindow.startDragging();
  1481. * ```
  1482. *
  1483. * @return A promise indicating the success or failure of the operation.
  1484. */
  1485. async startDragging(): Promise<void> {
  1486. return invokeTauriCommand({
  1487. __tauriModule: 'Window',
  1488. message: {
  1489. cmd: 'manage',
  1490. data: {
  1491. label: this.label,
  1492. cmd: {
  1493. type: 'startDragging'
  1494. }
  1495. }
  1496. }
  1497. })
  1498. }
  1499. // Listeners
  1500. /**
  1501. * Listen to window resize.
  1502. *
  1503. * @example
  1504. * ```typescript
  1505. * import { appWindow } from "@tauri-apps/api/window";
  1506. * const unlisten = await appWindow.onResized(({ payload: size }) => {
  1507. * console.log('Window resized', size);
  1508. * });
  1509. *
  1510. * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
  1511. * unlisten();
  1512. * ```
  1513. *
  1514. * @returns A promise resolving to a function to unlisten to the event.
  1515. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
  1516. *
  1517. * @since 1.0.2
  1518. */
  1519. async onResized(handler: EventCallback<PhysicalSize>): Promise<UnlistenFn> {
  1520. return this.listen<PhysicalSize>(TauriEvent.WINDOW_RESIZED, handler)
  1521. }
  1522. /**
  1523. * Listen to window move.
  1524. *
  1525. * @example
  1526. * ```typescript
  1527. * import { appWindow } from "@tauri-apps/api/window";
  1528. * const unlisten = await appWindow.onMoved(({ payload: position }) => {
  1529. * console.log('Window moved', position);
  1530. * });
  1531. *
  1532. * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
  1533. * unlisten();
  1534. * ```
  1535. *
  1536. * @returns A promise resolving to a function to unlisten to the event.
  1537. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
  1538. *
  1539. * @since 1.0.2
  1540. */
  1541. async onMoved(handler: EventCallback<PhysicalPosition>): Promise<UnlistenFn> {
  1542. return this.listen<PhysicalPosition>(TauriEvent.WINDOW_MOVED, handler)
  1543. }
  1544. /**
  1545. * Listen to window close requested. Emitted when the user requests to closes the window.
  1546. *
  1547. * @example
  1548. * ```typescript
  1549. * import { appWindow } from "@tauri-apps/api/window";
  1550. * import { confirm } from '@tauri-apps/api/dialog';
  1551. * const unlisten = await appWindow.onCloseRequested(async (event) => {
  1552. * const confirmed = await confirm('Are you sure?');
  1553. * if (!confirmed) {
  1554. * // user did not confirm closing the window; let's prevent it
  1555. * event.preventDefault();
  1556. * }
  1557. * });
  1558. *
  1559. * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
  1560. * unlisten();
  1561. * ```
  1562. *
  1563. * @returns A promise resolving to a function to unlisten to the event.
  1564. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
  1565. *
  1566. * @since 1.0.2
  1567. */
  1568. async onCloseRequested(
  1569. handler: (event: CloseRequestedEvent) => void
  1570. ): Promise<UnlistenFn> {
  1571. return this.listen<null>(TauriEvent.WINDOW_CLOSE_REQUESTED, (event) => {
  1572. const evt = new CloseRequestedEvent(event)
  1573. void Promise.resolve(handler(evt)).then(() => {
  1574. if (!evt.isPreventDefault()) {
  1575. return this.close()
  1576. }
  1577. })
  1578. })
  1579. }
  1580. /**
  1581. * Listen to window focus change.
  1582. *
  1583. * @example
  1584. * ```typescript
  1585. * import { appWindow } from "@tauri-apps/api/window";
  1586. * const unlisten = await appWindow.onFocusChanged(({ payload: focused }) => {
  1587. * console.log('Focus changed, window is focused? ' + focused);
  1588. * });
  1589. *
  1590. * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
  1591. * unlisten();
  1592. * ```
  1593. *
  1594. * @returns A promise resolving to a function to unlisten to the event.
  1595. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
  1596. *
  1597. * @since 1.0.2
  1598. */
  1599. async onFocusChanged(handler: EventCallback<boolean>): Promise<UnlistenFn> {
  1600. const unlistenFocus = await this.listen<PhysicalPosition>(
  1601. TauriEvent.WINDOW_FOCUS,
  1602. (event) => {
  1603. handler({ ...event, payload: true })
  1604. }
  1605. )
  1606. const unlistenBlur = await this.listen<PhysicalPosition>(
  1607. TauriEvent.WINDOW_BLUR,
  1608. (event) => {
  1609. handler({ ...event, payload: false })
  1610. }
  1611. )
  1612. return () => {
  1613. unlistenFocus()
  1614. unlistenBlur()
  1615. }
  1616. }
  1617. /**
  1618. * Listen to window scale change. Emitted when the window's scale factor has changed.
  1619. * The following user actions can cause DPI changes:
  1620. * - Changing the display's resolution.
  1621. * - Changing the display's scale factor (e.g. in Control Panel on Windows).
  1622. * - Moving the window to a display with a different scale factor.
  1623. *
  1624. * @example
  1625. * ```typescript
  1626. * import { appWindow } from "@tauri-apps/api/window";
  1627. * const unlisten = await appWindow.onScaleChanged(({ payload }) => {
  1628. * console.log('Scale changed', payload.scaleFactor, payload.size);
  1629. * });
  1630. *
  1631. * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
  1632. * unlisten();
  1633. * ```
  1634. *
  1635. * @returns A promise resolving to a function to unlisten to the event.
  1636. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
  1637. *
  1638. * @since 1.0.2
  1639. */
  1640. async onScaleChanged(
  1641. handler: EventCallback<ScaleFactorChanged>
  1642. ): Promise<UnlistenFn> {
  1643. return this.listen<ScaleFactorChanged>(
  1644. TauriEvent.WINDOW_SCALE_FACTOR_CHANGED,
  1645. handler
  1646. )
  1647. }
  1648. /**
  1649. * Listen to the window menu item click. The payload is the item id.
  1650. *
  1651. * @example
  1652. * ```typescript
  1653. * import { appWindow } from "@tauri-apps/api/window";
  1654. * const unlisten = await appWindow.onMenuClicked(({ payload: menuId }) => {
  1655. * console.log('Menu clicked: ' + menuId);
  1656. * });
  1657. *
  1658. * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
  1659. * unlisten();
  1660. * ```
  1661. *
  1662. * @returns A promise resolving to a function to unlisten to the event.
  1663. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
  1664. *
  1665. * @since 1.0.2
  1666. */
  1667. async onMenuClicked(handler: EventCallback<string>): Promise<UnlistenFn> {
  1668. return this.listen<string>(TauriEvent.MENU, handler)
  1669. }
  1670. /**
  1671. * Listen to a file drop event.
  1672. * The listener is triggered when the user hovers the selected files on the window,
  1673. * drops the files or cancels the operation.
  1674. *
  1675. * @example
  1676. * ```typescript
  1677. * import { appWindow } from "@tauri-apps/api/window";
  1678. * const unlisten = await appWindow.onFileDropEvent((event) => {
  1679. * if (event.payload.type === 'hover') {
  1680. * console.log('User hovering', event.payload.paths);
  1681. * } else if (event.payload.type === 'drop') {
  1682. * console.log('User dropped', event.payload.paths);
  1683. * } else {
  1684. * console.log('File drop cancelled');
  1685. * }
  1686. * });
  1687. *
  1688. * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
  1689. * unlisten();
  1690. * ```
  1691. *
  1692. * @returns A promise resolving to a function to unlisten to the event.
  1693. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
  1694. *
  1695. * @since 1.0.2
  1696. */
  1697. async onFileDropEvent(
  1698. handler: EventCallback<FileDropEvent>
  1699. ): Promise<UnlistenFn> {
  1700. const unlistenFileDrop = await this.listen<string[]>(
  1701. TauriEvent.WINDOW_FILE_DROP,
  1702. (event) => {
  1703. handler({ ...event, payload: { type: 'drop', paths: event.payload } })
  1704. }
  1705. )
  1706. const unlistenFileHover = await this.listen<string[]>(
  1707. TauriEvent.WINDOW_FILE_DROP_HOVER,
  1708. (event) => {
  1709. handler({ ...event, payload: { type: 'hover', paths: event.payload } })
  1710. }
  1711. )
  1712. const unlistenCancel = await this.listen<null>(
  1713. TauriEvent.WINDOW_FILE_DROP_CANCELLED,
  1714. (event) => {
  1715. handler({ ...event, payload: { type: 'cancel' } })
  1716. }
  1717. )
  1718. return () => {
  1719. unlistenFileDrop()
  1720. unlistenFileHover()
  1721. unlistenCancel()
  1722. }
  1723. }
  1724. /**
  1725. * Listen to the system theme change.
  1726. *
  1727. * @example
  1728. * ```typescript
  1729. * import { appWindow } from "@tauri-apps/api/window";
  1730. * const unlisten = await appWindow.onThemeChanged(({ payload: theme }) => {
  1731. * console.log('New theme: ' + theme);
  1732. * });
  1733. *
  1734. * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
  1735. * unlisten();
  1736. * ```
  1737. *
  1738. * @returns A promise resolving to a function to unlisten to the event.
  1739. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
  1740. *
  1741. * @since 1.0.2
  1742. */
  1743. async onThemeChanged(handler: EventCallback<Theme>): Promise<UnlistenFn> {
  1744. return this.listen<Theme>(TauriEvent.WINDOW_THEME_CHANGED, handler)
  1745. }
  1746. }
  1747. /**
  1748. * @since 1.0.2
  1749. */
  1750. class CloseRequestedEvent {
  1751. /** Event name */
  1752. event: EventName
  1753. /** The label of the window that emitted this event. */
  1754. windowLabel: string
  1755. /** Event identifier used to unlisten */
  1756. id: number
  1757. private _preventDefault = false
  1758. constructor(event: Event<null>) {
  1759. this.event = event.event
  1760. this.windowLabel = event.windowLabel
  1761. this.id = event.id
  1762. }
  1763. preventDefault(): void {
  1764. this._preventDefault = true
  1765. }
  1766. isPreventDefault(): boolean {
  1767. return this._preventDefault
  1768. }
  1769. }
  1770. /**
  1771. * Create new webview windows and get a handle to existing ones.
  1772. *
  1773. * Windows are identified by a *label* a unique identifier that can be used to reference it later.
  1774. * It may only contain alphanumeric characters `a-zA-Z` plus the following special characters `-`, `/`, `:` and `_`.
  1775. *
  1776. * @example
  1777. * ```typescript
  1778. * // loading embedded asset:
  1779. * const webview = new WebviewWindow('theUniqueLabel', {
  1780. * url: 'path/to/page.html'
  1781. * });
  1782. * // alternatively, load a remote URL:
  1783. * const webview = new WebviewWindow('theUniqueLabel', {
  1784. * url: 'https://github.com/tauri-apps/tauri'
  1785. * });
  1786. *
  1787. * webview.once('tauri://created', function () {
  1788. * // webview window successfully created
  1789. * });
  1790. * webview.once('tauri://error', function (e) {
  1791. * // an error happened creating the webview window
  1792. * });
  1793. *
  1794. * // emit an event to the backend
  1795. * await webview.emit("some event", "data");
  1796. * // listen to an event from the backend
  1797. * const unlisten = await webview.listen("event name", e => {});
  1798. * unlisten();
  1799. * ```
  1800. *
  1801. * @since 1.0.2
  1802. */
  1803. class WebviewWindow extends WindowManager {
  1804. /**
  1805. * Creates a new WebviewWindow.
  1806. * @example
  1807. * ```typescript
  1808. * import { WebviewWindow } from '@tauri-apps/api/window';
  1809. * const webview = new WebviewWindow('my-label', {
  1810. * url: 'https://github.com/tauri-apps/tauri'
  1811. * });
  1812. * webview.once('tauri://created', function () {
  1813. * // webview window successfully created
  1814. * });
  1815. * webview.once('tauri://error', function (e) {
  1816. * // an error happened creating the webview window
  1817. * });
  1818. * ```
  1819. *
  1820. * * @param label The unique webview window label. Must be alphanumeric: `a-zA-Z-/:_`.
  1821. * @returns The WebviewWindow instance to communicate with the webview.
  1822. */
  1823. constructor(label: WindowLabel, options: WindowOptions = {}) {
  1824. super(label)
  1825. // @ts-expect-error
  1826. if (!options?.skip) {
  1827. invokeTauriCommand({
  1828. __tauriModule: 'Window',
  1829. message: {
  1830. cmd: 'createWebview',
  1831. data: {
  1832. options: {
  1833. label,
  1834. ...options
  1835. }
  1836. }
  1837. }
  1838. })
  1839. .then(async () => this.emit('tauri://created'))
  1840. .catch(async (e: string) => this.emit('tauri://error', e))
  1841. }
  1842. }
  1843. /**
  1844. * Gets the WebviewWindow for the webview associated with the given label.
  1845. * @example
  1846. * ```typescript
  1847. * import { WebviewWindow } from '@tauri-apps/api/window';
  1848. * const mainWindow = WebviewWindow.getByLabel('main');
  1849. * ```
  1850. *
  1851. * @param label The webview window label.
  1852. * @returns The WebviewWindow instance to communicate with the webview or null if the webview doesn't exist.
  1853. */
  1854. static getByLabel(label: string): WebviewWindow | null {
  1855. if (getAll().some((w) => w.label === label)) {
  1856. // @ts-expect-error
  1857. return new WebviewWindow(label, { skip: true })
  1858. }
  1859. return null
  1860. }
  1861. }
  1862. /** The WebviewWindow for the current window. */
  1863. let appWindow: WebviewWindow
  1864. if ('__TAURI_METADATA__' in window) {
  1865. appWindow = new WebviewWindow(
  1866. window.__TAURI_METADATA__.__currentWindow.label,
  1867. {
  1868. // @ts-expect-error
  1869. skip: true
  1870. }
  1871. )
  1872. } else {
  1873. console.warn(
  1874. `Could not find "window.__TAURI_METADATA__". The "appWindow" value will reference the "main" window label.\nNote that this is not an issue if running this frontend on a browser instead of a Tauri window.`
  1875. )
  1876. appWindow = new WebviewWindow('main', {
  1877. // @ts-expect-error
  1878. skip: true
  1879. })
  1880. }
  1881. /**
  1882. * Configuration for the window to create.
  1883. *
  1884. * @since 1.0.0
  1885. */
  1886. interface WindowOptions {
  1887. /**
  1888. * Remote URL or local file path to open.
  1889. *
  1890. * - URL such as `https://github.com/tauri-apps` is opened directly on a Tauri window.
  1891. * - data: URL such as `data:text/html,<html>...` is only supported with the `window-data-url` Cargo feature for the `tauri` dependency.
  1892. * - local file path or route such as `/path/to/page.html` or `/users` is appended to the application URL (the devServer URL on development, or `tauri://localhost/` and `https://tauri.localhost/` on production).
  1893. */
  1894. url?: string
  1895. /** Show window in the center of the screen.. */
  1896. center?: boolean
  1897. /** The initial vertical position. Only applies if `y` is also set. */
  1898. x?: number
  1899. /** The initial horizontal position. Only applies if `x` is also set. */
  1900. y?: number
  1901. /** The initial width. */
  1902. width?: number
  1903. /** The initial height. */
  1904. height?: number
  1905. /** The minimum width. Only applies if `minHeight` is also set. */
  1906. minWidth?: number
  1907. /** The minimum height. Only applies if `minWidth` is also set. */
  1908. minHeight?: number
  1909. /** The maximum width. Only applies if `maxHeight` is also set. */
  1910. maxWidth?: number
  1911. /** The maximum height. Only applies if `maxWidth` is also set. */
  1912. maxHeight?: number
  1913. /** Whether the window is resizable or not. */
  1914. resizable?: boolean
  1915. /** Window title. */
  1916. title?: string
  1917. /** Whether the window is in fullscreen mode or not. */
  1918. fullscreen?: boolean
  1919. /** Whether the window will be initially focused or not. */
  1920. focus?: boolean
  1921. /**
  1922. * Whether the window is transparent or not.
  1923. * Note that on `macOS` this requires the `macos-private-api` feature flag, enabled under `tauri.conf.json > tauri > macOSPrivateApi`.
  1924. * WARNING: Using private APIs on `macOS` prevents your application from being accepted to the `App Store`.
  1925. */
  1926. transparent?: boolean
  1927. /** Whether the window should be maximized upon creation or not. */
  1928. maximized?: boolean
  1929. /** Whether the window should be immediately visible upon creation or not. */
  1930. visible?: boolean
  1931. /** Whether the window should have borders and bars or not. */
  1932. decorations?: boolean
  1933. /** Whether the window should always be on top of other windows or not. */
  1934. alwaysOnTop?: boolean
  1935. /** Whether or not the window icon should be added to the taskbar. */
  1936. skipTaskbar?: boolean
  1937. /**
  1938. * Whether the file drop is enabled or not on the webview. By default it is enabled.
  1939. *
  1940. * Disabling it is required to use drag and drop on the frontend on Windows.
  1941. */
  1942. fileDropEnabled?: boolean
  1943. /**
  1944. * The initial window theme. Defaults to the system theme.
  1945. *
  1946. * Only implemented on Windows and macOS 10.14+.
  1947. */
  1948. theme?: Theme
  1949. /**
  1950. * The style of the macOS title bar.
  1951. */
  1952. titleBarStyle?: TitleBarStyle
  1953. /**
  1954. * If `true`, sets the window title to be hidden on macOS.
  1955. */
  1956. hiddenTitle?: boolean
  1957. /**
  1958. * Whether clicking an inactive window also clicks through to the webview.
  1959. */
  1960. acceptFirstMouse?: boolean
  1961. /**
  1962. * Defines the window [tabbing identifier](https://developer.apple.com/documentation/appkit/nswindow/1644704-tabbingidentifier) on macOS.
  1963. *
  1964. * Windows with the same tabbing identifier will be grouped together.
  1965. * If the tabbing identifier is not set, automatic tabbing will be disabled.
  1966. */
  1967. tabbingIdentifier?: string
  1968. /**
  1969. * The user agent for the webview.
  1970. */
  1971. userAgent?: string
  1972. }
  1973. function mapMonitor(m: Monitor | null): Monitor | null {
  1974. return m === null
  1975. ? null
  1976. : {
  1977. name: m.name,
  1978. scaleFactor: m.scaleFactor,
  1979. position: new PhysicalPosition(m.position.x, m.position.y),
  1980. size: new PhysicalSize(m.size.width, m.size.height)
  1981. }
  1982. }
  1983. /**
  1984. * Returns the monitor on which the window currently resides.
  1985. * Returns `null` if current monitor can't be detected.
  1986. * @example
  1987. * ```typescript
  1988. * import { currentMonitor } from '@tauri-apps/api/window';
  1989. * const monitor = currentMonitor();
  1990. * ```
  1991. *
  1992. * @since 1.0.0
  1993. */
  1994. async function currentMonitor(): Promise<Monitor | null> {
  1995. return invokeTauriCommand<Monitor | null>({
  1996. __tauriModule: 'Window',
  1997. message: {
  1998. cmd: 'manage',
  1999. data: {
  2000. cmd: {
  2001. type: 'currentMonitor'
  2002. }
  2003. }
  2004. }
  2005. }).then(mapMonitor)
  2006. }
  2007. /**
  2008. * Returns the primary monitor of the system.
  2009. * Returns `null` if it can't identify any monitor as a primary one.
  2010. * @example
  2011. * ```typescript
  2012. * import { primaryMonitor } from '@tauri-apps/api/window';
  2013. * const monitor = primaryMonitor();
  2014. * ```
  2015. *
  2016. * @since 1.0.0
  2017. */
  2018. async function primaryMonitor(): Promise<Monitor | null> {
  2019. return invokeTauriCommand<Monitor | null>({
  2020. __tauriModule: 'Window',
  2021. message: {
  2022. cmd: 'manage',
  2023. data: {
  2024. cmd: {
  2025. type: 'primaryMonitor'
  2026. }
  2027. }
  2028. }
  2029. }).then(mapMonitor)
  2030. }
  2031. /**
  2032. * Returns the list of all the monitors available on the system.
  2033. * @example
  2034. * ```typescript
  2035. * import { availableMonitors } from '@tauri-apps/api/window';
  2036. * const monitors = availableMonitors();
  2037. * ```
  2038. *
  2039. * @since 1.0.0
  2040. */
  2041. async function availableMonitors(): Promise<Monitor[]> {
  2042. return invokeTauriCommand<Monitor[]>({
  2043. __tauriModule: 'Window',
  2044. message: {
  2045. cmd: 'manage',
  2046. data: {
  2047. cmd: {
  2048. type: 'availableMonitors'
  2049. }
  2050. }
  2051. }
  2052. }).then((ms) => ms.map(mapMonitor) as Monitor[])
  2053. }
  2054. export {
  2055. WebviewWindow,
  2056. WebviewWindowHandle,
  2057. WindowManager,
  2058. CloseRequestedEvent,
  2059. getCurrent,
  2060. getAll,
  2061. appWindow,
  2062. LogicalSize,
  2063. PhysicalSize,
  2064. LogicalPosition,
  2065. PhysicalPosition,
  2066. UserAttentionType,
  2067. currentMonitor,
  2068. primaryMonitor,
  2069. availableMonitors
  2070. }
  2071. export type {
  2072. Theme,
  2073. TitleBarStyle,
  2074. Monitor,
  2075. ScaleFactorChanged,
  2076. FileDropEvent,
  2077. WindowOptions
  2078. }