# How Tabby Implements the Quake Console Dockable Window Feature

> Discover how Tabby implements its Quake console dockable window feature using ElectronDockingService and a global hotkey. Learn the technical details behind this convenient terminal.

- Repository: [Eugene/tabby](https://github.com/Eugeny/tabby)
- Tags: internals
- Published: 2026-03-03

---

**TLDR:** Tabby's Quake console is not a separate terminal widget but the main application window repositioned to a screen edge by `ElectronDockingService`, toggled via a global `Ctrl-Space` hotkey registered in the main Electron process.

The **Tabby Quake console dockable window** feature transforms the standard terminal into a drop-down console that slides from any monitor edge. Implemented in the Eugeny/tabby repository, this feature leverages Electron's `BrowserWindow` API alongside a reactive docking service to resize and reposition the primary window on demand. Unlike traditional overlay implementations, Tabby treats the main window itself as the dockable console, enabling deep integration with the application's configuration and hotkey systems.

## Configuration Layer

All dockable window behavior originates in [`tabby-electron/src/config.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-electron/src/config.ts), which defines the default **toggle-window** hotkey and the appearance settings governing dock position and dimensions.

```typescript
// tabby-electron/src/config.ts (excerpt)
{
    appearance: {
        dock: 'off' | 'top' | 'bottom' | 'left' | 'right',
        dockScreen: number,          // target display index
        dockFill: number,            // 0-1 fraction of screen width/height
        dockSpace: number,           // 0-1 margin fraction
        dockAlwaysOnTop: boolean,
    },
    hotkeys: {
        'toggle-window': ['Ctrl-Space']
    }
}

```

When users adjust these values through **Settings → Window**, the `config.changed$` observable emits, triggering the docking service to recalculate the window bounds immediately.

## Docking Service Logic

The `ElectronDockingService` in [`tabby-electron/src/services/docking.service.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-electron/src/services/docking.service.ts) implements the abstract `DockingService` from tabby-core. This service computes the target geometry and applies it to the native Electron window whenever the display layout or configuration changes.

### Reactive Positioning

The service subscribes to multiple event streams to ensure the window remains correctly positioned across monitor configuration changes:

```typescript
this.screensChanged$.subscribe(() => this.repositionWindow())
platform.displayMetricsChanged$.subscribe(() => this.repositionWindow())
electron.ipcRenderer.on('host:displays-changed', () => {
    this.zone.run(() => this.screensChanged.next())
})

```

### Bounds Calculation

When repositioning, the service calculates the absolute pixel bounds based on the selected edge, fill percentage, and reserved space:

```typescript
const newBounds: Bounds = { x: 0, y: 0, width: 0, height: 0 }
const fill = this.config.store.appearance.dockFill <= 1 
    ? this.config.store.appearance.dockFill 
    : 1
const space = this.config.store.appearance.dockSpace <= 1 
    ? this.config.store.appearance.dockSpace 
    : 1
const [minWidth, minHeight] = this.hostWindow.getWindow().getMinimumSize()
// Width/height and x/y calculations vary by edge (top/bottom/left/right)

```

After computing the geometry, the service applies the bounds and always-on-top flag through the host window wrapper:

```typescript
const alwaysOnTop = this.config.store.appearance.dockAlwaysOnTop
this.hostWindow.setAlwaysOnTop(alwaysOnTop)
setImmediate(() => {
    this.hostWindow.setBounds(newBounds)
})

```

If the user sets `dock: 'off'`, the service clears the always-on-top flag and returns window management to the standard logic.

## Window Control and Hotkey Handling

Low-level window manipulation resides in [`tabby-electron/src/services/hostWindow.service.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-electron/src/services/hostWindow.service.ts) within the `ElectronHostWindow` class. This abstraction wraps Electron's `BrowserWindow` to provide controlled methods for the docking service.

### Host Window Methods

The Quake feature specifically utilizes these methods from `ElectronHostWindow`:

- **`setBounds(bounds)`**: Applies the calculated dock geometry to the native window.
- **`setAlwaysOnTop(flag)`**: Enables the window to float above other applications when docked.
- **`bringToFront()`**: Raises the window when the toggle hotkey activates it.

### Global Hotkey Registration

The global shortcut registration occurs in [`tabby-electron/src/index.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-electron/src/index.ts). The renderer process sends the hotkey specification to the main process via IPC:

```typescript
private registerGlobalHotkey () {
    let value = this.config.store.hotkeys['toggle-window'] || []
    // Normalization logic for Electron accelerator specs...
    this.electron.ipcRenderer.send('app:register-global-hotkey', specs)
}

```

On the main process side, an `ipcMain` listener handles the actual toggle logic:

```typescript
ipcMain.on('app:global-hotkey-pressed', (event, id) => {
    if (id === 'toggle-window') {
        const win = electron.BrowserWindow.fromId(mainWindowId)
        if (win.isVisible()) {
            win.hide()
        } else {
            win.show()
            win.focus()
        }
    }
})

```

Pressing **Ctrl-Space** (or the user-defined equivalent) therefore triggers this IPC handler, which either hides the visible docked window or shows and focuses the hidden one, creating the characteristic Quake-style drop-down effect.

## Summary

- **Tabby's Quake console is the main window**, not a separate terminal component, docked to screen edges via `ElectronDockingService`.
- **Configuration** resides in [`tabby-electron/src/config.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-electron/src/config.ts), defining the `dock` position, fill ratios, and the `toggle-window` hotkey (default `Ctrl-Space`).
- **Positioning logic** in [`tabby-electron/src/services/docking.service.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-electron/src/services/docking.service.ts) calculates bounds reactively based on screen metrics and user preferences.
- **Window control** is abstracted through `ElectronHostWindow` in [`tabby-electron/src/services/hostWindow.service.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-electron/src/services/hostWindow.service.ts), applying bounds and always-on-top states.
- **Hotkey handling** bridges the renderer and main process through IPC events registered in [`tabby-electron/src/index.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-electron/src/index.ts), executing the actual show/hide toggle on the native `BrowserWindow`.

## Frequently Asked Questions

### Is the Quake console a separate window in Tabby?

No. Unlike traditional implementations that create a distinct overlay widget, Tabby's Quake console is the **main application window** itself. The `ElectronDockingService` repositions and resizes this primary window to occupy a screen edge, while the `ElectronHostWindow` service manages its visibility state.

### How do I change the default toggle hotkey?

Modify the `hotkeys['toggle-window']` array in [`tabby-electron/src/config.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-electron/src/config.ts) or use the Settings UI (backed by [`tabby-settings/src/components/windowSettingsTab.component.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-settings/src/components/windowSettingsTab.component.ts)) to register a new accelerator. The application normalizes this specification and registers it via `app:register-global-hotkey` IPC calls to the main process.

### Why does the window reposition when I change monitors?

The `ElectronDockingService` subscribes to `displayMetricsChanged$` and `host:displays-changed` events. When the display configuration changes, `repositionWindow()` recalculates the absolute bounds based on the current `dockScreen` index and reapplies them through `setBounds()`, ensuring the console remains anchored to the correct edge on the correct monitor.

### Can I dock the window to multiple edges simultaneously?

No. The `dock` configuration accepts a single string value: `'off'`, `'top'`, `'bottom'`, `'left'`, or `'right'`. The bounds calculation logic in [`docking.service.ts`](https://github.com/Eugeny/tabby/blob/main/docking.service.ts) processes one edge at a time to determine the window's `x`, `y`, `width`, and `height`, making simultaneous multi-edge docking architecturally incompatible with the current implementation.