Skip to content

Commit 5cba6eb

Browse files
authored
feat(core): add window center API, closes #1822 (#1954)
1 parent f877aa5 commit 5cba6eb

File tree

14 files changed

+90
-3
lines changed

14 files changed

+90
-3
lines changed

.changes/api-window-center.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"api": patch
3+
---
4+
5+
Adds `center?: boolean` to `WindowOptions` and `center()` API to the `appWindow`.

.changes/window-center.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"tauri-runtime": patch
3+
"tauri-runtime-wry": patch
4+
"tauri": patch
5+
---
6+
7+
Adds `Window#center` and `WindowBuilder#center` APIs.

core/tauri-runtime-wry/src/lib.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ impl From<Position> for PositionWrapper {
243243
#[derive(Debug, Clone, Default)]
244244
pub struct WindowBuilderWrapper {
245245
inner: WryWindowBuilder,
246+
center: bool,
246247
#[cfg(feature = "menu")]
247248
menu_items: HashMap<u32, WryCustomMenuItem>,
248249
}
@@ -295,6 +296,11 @@ impl WindowBuilder for WindowBuilderWrapper {
295296
self
296297
}
297298

299+
fn center(mut self) -> Self {
300+
self.center = true;
301+
self
302+
}
303+
298304
fn position(mut self, x: f64, y: f64) -> Self {
299305
self.inner = self.inner.with_position(WryLogicalPosition::new(x, y));
300306
self
@@ -453,6 +459,7 @@ enum WindowMessage {
453459
#[cfg(windows)]
454460
Hwnd(Sender<Hwnd>),
455461
// Setters
462+
Center(Sender<Result<()>>),
456463
SetResizable(bool),
457464
SetTitle(String),
458465
Maximize,
@@ -638,6 +645,10 @@ impl Dispatch for WryDispatcher {
638645

639646
// Setters
640647

648+
fn center(&self) -> Result<()> {
649+
dispatcher_getter!(self, WindowMessage::Center)
650+
}
651+
641652
fn print(&self) -> Result<()> {
642653
self
643654
.context
@@ -1278,6 +1289,9 @@ fn handle_event_loop(
12781289
tx.send(Hwnd(window.hwnd())).unwrap()
12791290
}
12801291
// Setters
1292+
WindowMessage::Center(tx) => {
1293+
tx.send(center_window(window)).unwrap();
1294+
}
12811295
WindowMessage::SetResizable(resizable) => window.set_resizable(resizable),
12821296
WindowMessage::SetTitle(title) => window.set_title(&title),
12831297
WindowMessage::Maximize => window.set_maximized(true),
@@ -1409,6 +1423,19 @@ fn handle_event_loop(
14091423
}
14101424
}
14111425

1426+
fn center_window(window: &Window) -> Result<()> {
1427+
if let Some(monitor) = window.current_monitor() {
1428+
let screen_size = monitor.size();
1429+
let window_size = window.inner_size();
1430+
let x = (screen_size.width - window_size.width) / 2;
1431+
let y = (screen_size.height - window_size.height) / 2;
1432+
window.set_outer_position(WryPhysicalPosition::new(x, y));
1433+
Ok(())
1434+
} else {
1435+
Err(Error::FailedToGetMonitor)
1436+
}
1437+
}
1438+
14121439
fn create_webview<P: Params<Runtime = Wry>>(
14131440
event_loop: &EventLoopWindowTarget<Message>,
14141441
context: DispatcherContext,
@@ -1428,6 +1455,9 @@ fn create_webview<P: Params<Runtime = Wry>>(
14281455
#[cfg(feature = "menu")]
14291456
let menu_items = window_builder.menu_items;
14301457
let window = window_builder.inner.build(event_loop).unwrap();
1458+
if window_builder.center {
1459+
let _ = center_window(&window);
1460+
}
14311461
let mut webview_builder = WebViewBuilder::new(window)
14321462
.map_err(|e| Error::CreateWebview(Box::new(e)))?
14331463
.with_url(&url)

core/tauri-runtime/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ pub enum Error {
9999
/// Failed to load window icon.
100100
#[error("invalid icon: {0}")]
101101
InvalidIcon(Box<dyn std::error::Error + Send>),
102+
/// Failed to get monitor on window operation.
103+
#[error("failed to get monitor")]
104+
FailedToGetMonitor,
102105
}
103106

104107
/// Result type.
@@ -317,6 +320,9 @@ pub trait Dispatch: Clone + Send + Sized + 'static {
317320

318321
// SETTERS
319322

323+
/// Centers the window.
324+
fn center(&self) -> crate::Result<()>;
325+
320326
/// Opens the dialog to prints the contents of the webview.
321327
fn print(&self) -> crate::Result<()>;
322328

core/tauri-runtime/src/webview.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ pub trait WindowBuilder: WindowBuilderBase {
103103
#[cfg_attr(doc_cfg, doc(cfg(feature = "menu")))]
104104
fn menu<I: MenuId>(self, menu: Menu<I>) -> Self;
105105

106+
/// Show window in the center of the screen.
107+
fn center(self) -> Self;
108+
106109
/// The initial position of the window's.
107110
fn position(self, x: f64, y: f64) -> Self;
108111

core/tauri-utils/src/config.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ pub struct WindowConfig {
4242
/// The window webview URL.
4343
#[serde(default)]
4444
pub url: WindowUrl,
45+
/// Center the window.
46+
#[serde(default)]
47+
pub center: bool,
4548
/// The horizontal position of the window's top left corner
4649
pub x: Option<f64>,
4750
/// The vertical position of the window's top left corner
@@ -125,6 +128,7 @@ impl Default for WindowConfig {
125128
Self {
126129
label: default_window_label(),
127130
url: WindowUrl::default(),
131+
center: false,
128132
x: None,
129133
y: None,
130134
width: default_width(),
@@ -649,6 +653,7 @@ mod build {
649653
fn to_tokens(&self, tokens: &mut TokenStream) {
650654
let label = str_lit(&self.label);
651655
let url = &self.url;
656+
let center = self.center;
652657
let x = opt_lit(self.x.as_ref());
653658
let y = opt_lit(self.y.as_ref());
654659
let width = self.width;
@@ -673,6 +678,7 @@ mod build {
673678
WindowConfig,
674679
label,
675680
url,
681+
center,
676682
x,
677683
y,
678684
width,
@@ -937,6 +943,7 @@ mod test {
937943
windows: vec![WindowConfig {
938944
label: "main".to_string(),
939945
url: WindowUrl::default(),
946+
center: false,
940947
x: None,
941948
y: None,
942949
width: 800f64,

core/tauri/scripts/bundle.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/tauri/src/endpoints/window.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub enum Cmd {
5353
PrimaryMonitor,
5454
AvailableMonitors,
5555
// Setters
56+
Center,
5657
SetResizable(bool),
5758
SetTitle(String),
5859
Maximize,
@@ -141,6 +142,7 @@ impl Cmd {
141142
Self::PrimaryMonitor => return Ok(window.primary_monitor()?.into()),
142143
Self::AvailableMonitors => return Ok(window.available_monitors()?.into()),
143144
// Setters
145+
Self::Center => window.center()?,
144146
Self::SetResizable(resizable) => window.set_resizable(resizable)?,
145147
Self::SetTitle(title) => window.set_title(&title)?,
146148
Self::Maximize => window.maximize()?,

core/tauri/src/window.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,11 @@ impl<P: Params> Window<P> {
403403

404404
// Setters
405405

406+
/// Centers the window.
407+
pub fn center(&self) -> crate::Result<()> {
408+
self.window.dispatcher.center().map_err(Into::into)
409+
}
410+
406411
/// Opens the dialog to prints the contents of the webview.
407412
/// Currently only supported on macOS on `wry`.
408413
/// `window.print()` works on all platforms.

docs/api/config.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ It's composed of the following properties:
250250
<Properties anchorRoot="tauri.windows" rows={[
251251
{ property: "label", type: "string", description: `Window id to reference on the codebase.` },
252252
{ property: "url", type: "string", description: `URL to load on the webview.` },
253+
{ property: "center", type: "boolean", description: `Show window in the center of the screen.` },
253254
{ property: "x", type: "number", description: `The horizontal position of the window's top left corner.` },
254255
{ property: "y", type: "number", description: `The vertical position of the window's top left corner.` },
255256
{ property: "width", optional: true, type: "number", description: `Initial window width.` },

0 commit comments

Comments
 (0)