# How to Use Tauri Commands for Window Management Operations in the ChatGPT Desktop App

> Master Tauri commands for window management in your desktop app. Learn to define Rust functions and invoke them from your frontend for seamless control.

- Repository: [lencx/ChatGPT](https://github.com/lencx/ChatGPT)
- Tags: how-to-guide
- Published: 2026-03-06

---

**To use Tauri commands for window management operations in the ChatGPT desktop app, define Rust functions with `#[tauri::command]` in the core modules, register them in [`main.rs`](https://github.com/lencx/ChatGPT/blob/main/main.rs) via `tauri::generate_handler!`, and invoke them from the React frontend using `@tauri-apps/api/tauri`.**

The **lencx/ChatGPT** desktop client leverages Tauri to bridge the React/TypeScript frontend with native OS window controls. This pattern enables secure, type-safe communication between the UI layer and Rust-based system APIs for creating webviews, managing window states, and handling navigation.

## Understanding the Tauri Command Architecture

Tauri commands function as the IPC (Inter-Process Communication) layer between the webview and the native Rust runtime. In the ChatGPT application, window management commands are defined in the Rust core layer within `src-tauri/src/core/` and exposed to the UI through the `invoke_handler` configured in [`src-tauri/src/main.rs`](https://github.com/lencx/ChatGPT/blob/main/src-tauri/src/main.rs). The frontend transmits JSON payloads via the `invoke` function, which Tauri deserializes and routes to the appropriate Rust implementation, returning results as JavaScript promises.

## Defining Window Management Commands in Rust

Window management operations reside in `src-tauri/src/core/*.rs` files and utilize the `#[tauri::command]` macro to expose functions to the JavaScript runtime.

### Creating the Settings Window

The `open_settings` command in [`src-tauri/src/core/window.rs`](https://github.com/lencx/ChatGPT/blob/main/src-tauri/src/core/window.rs) demonstrates conditional window creation. It checks for an existing Settings window instance and either reveals it or constructs a new webview using `WebviewWindowBuilder`:

```rust
// src-tauri/src/core/window.rs
#[command]
pub fn open_settings(app: AppHandle) {
    match app.get_webview_window(WINDOW_SETTINGS) {
        Some(window) => { window.show().unwrap(); }
        None => {
            WebviewWindowBuilder::new(
                &app,
                WINDOW_SETTINGS,
                WebviewUrl::App("index.html".into()),
            )
            .build()
            .unwrap();
        }
    }
}

```

### Pinning and Unpinning Windows

The `window_pin` command controls the always-on-top behavior. Implemented in [`src-tauri/src/core/cmd.rs`](https://github.com/lencx/ChatGPT/blob/main/src-tauri/src/core/cmd.rs), it accepts a boolean parameter to toggle the window state:

```rust
// src-tauri/src/core/cmd.rs
#[command]
pub fn window_pin(window: Window, pinned: bool) {
    window.set_always_on_top(pinned).unwrap();
}

```

## Registering Commands in the Tauri Application

Before the frontend can invoke these functions, they must be registered in the Tauri builder within [`src-tauri/src/main.rs`](https://github.com/lencx/ChatGPT/blob/main/src-tauri/src/main.rs). The `tauri::generate_handler!` macro aggregates all available commands into the invoke handler:

```rust
// src-tauri/src/main.rs
tauri::Builder::default()
    .invoke_handler(tauri::generate_handler![
        cmd::view_reload,
        cmd::view_url,
        cmd::view_go_forward,
        cmd::view_go_back,
        cmd::set_view_ask,
        cmd::get_app_conf,
        cmd::window_pin,          // toggle always-on-top
        cmd::ask_sync,
        cmd::ask_send,
        cmd::set_theme,
        window::open_settings,   // open Settings window
    ])

```

## Invoking Commands from the React Frontend

In React components such as [`src/view/Titlebar.tsx`](https://github.com/lencx/ChatGPT/blob/main/src/view/Titlebar.tsx), commands are triggered using the `invoke` function from `@tauri-apps/api/tauri`. Standard window operations like minimize or close use the built-in `appWindow` API from `@tauri-apps/api/window`.

Opening the Settings window:

```typescript
import { invoke } from '@tauri-apps/api/tauri';

const openSettings = async () => {
  await invoke('open_settings');
};

```

Toggling the pin state with parameters:

```typescript
const togglePin = async (pinned: boolean) => {
  await invoke('window_pin', { pinned });
};

```

Built-in window controls (no custom command required):

```typescript
import { appWindow } from '@tauri-apps/api/window';

const minimize = () => appWindow.minimize();
const maximize = () => appWindow.toggleMaximize();
const close = () => appWindow.close();

```

## Summary

- **Define commands** in Rust using `#[tauri::command]` in files like [`src-tauri/src/core/window.rs`](https://github.com/lencx/ChatGPT/blob/main/src-tauri/src/core/window.rs) and [`src-tauri/src/core/cmd.rs`](https://github.com/lencx/ChatGPT/blob/main/src-tauri/src/core/cmd.rs).
- **Register handlers** in [`src-tauri/src/main.rs`](https://github.com/lencx/ChatGPT/blob/main/src-tauri/src/main.rs) using `tauri::generate_handler!` to expose functions to the frontend.
- **Invoke from TypeScript** using `invoke('command_name', { args })` from `@tauri-apps/api/tauri` to trigger native window operations.
- **Use WebviewWindowBuilder** in Rust to create new windows dynamically, checking for existing instances with `get_webview_window`.
- **Leverage AppHandle** to access application-wide state and window management capabilities from within command functions.

## Frequently Asked Questions

### How do I add a new window management command to the ChatGPT app?

Create a new function in [`src-tauri/src/core/window.rs`](https://github.com/lencx/ChatGPT/blob/main/src-tauri/src/core/window.rs) or [`src-tauri/src/core/cmd.rs`](https://github.com/lencx/ChatGPT/blob/main/src-tauri/src/core/cmd.rs) with the `#[tauri::command]` attribute. Add the function name to the `generate_handler!` macro in [`src-tauri/src/main.rs`](https://github.com/lencx/ChatGPT/blob/main/src-tauri/src/main.rs). Finally, call `invoke('your_command_name')` from your React component using the Tauri API.

### What is the difference between using `invoke` and the `appWindow` API?

The `invoke` function calls custom Rust commands defined in the Tauri backend, enabling complex logic like creating new webviews or persisting state. The `appWindow` API provides direct access to standard window operations (minimize, maximize, close) without requiring custom Rust code, operating entirely within the frontend.

### Where are the window management commands implemented in the source code?

Window creation logic resides in [`src-tauri/src/core/window.rs`](https://github.com/lencx/ChatGPT/blob/main/src-tauri/src/core/window.rs), while state control commands like `window_pin` and navigation controls are located in [`src-tauri/src/core/cmd.rs`](https://github.com/lencx/ChatGPT/blob/main/src-tauri/src/core/cmd.rs). The command registration happens in [`src-tauri/src/main.rs`](https://github.com/lencx/ChatGPT/blob/main/src-tauri/src/main.rs), and the UI triggers are in [`src/view/Titlebar.tsx`](https://github.com/lencx/ChatGPT/blob/main/src/view/Titlebar.tsx).

### How does Tauri handle the communication between frontend and backend for these commands?

Tauri uses an IPC bridge to serialize JavaScript arguments into JSON, transmit them to the Rust runtime, deserialize them into function parameters, execute the command, and return the result or error back to the JavaScript promise. This happens transparently when calling `invoke`.