# How to Set Up Hyprland Window Grouping (Tabbed Mode)

> Learn to set up Hyprland window grouping tabbed mode with easy steps. Organize your workspace efficiently and boost productivity. Master Hyprland's tabbed layout today.

- Repository: [Hypr Development/Hyprland](https://github.com/hyprwm/Hyprland)
- Tags: how-to-guide
- Published: 2026-07-26

---

**Hyprland window grouping** creates tabbed containers by wrapping windows in a `CGroup` instance, managing them through `CWindowGroupTarget`, and rendering a configurable bar via `CHyprGroupBarDecoration`.

Hyprland window grouping (often called tabbed mode) allows you to stack multiple windows into a single container with a clickable tab bar. According to the hyprwm/Hyprland source code, this feature is implemented through three tightly-coupled C++ components that handle data modeling, layout targeting, and UI rendering.

## Core Architecture of Hyprland Window Grouping

The implementation spans three primary classes that separate concerns between data storage, layout management, and visual presentation.

### CGroup – The Data Model

The `CGroup` class, defined in [`src/desktop/View/CGroup.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/desktop/View/CGroup.cpp), serves as the central data structure for window grouping. It stores the list of member windows, tracks the currently active window, and maintains group-wide state. All windows belonging to the same group share a single `CGroup` instance, enabling synchronized state management across the container.

Key methods include `add()` to insert windows, `remove()` to delete them, `setCurrent()` to change the active tab, and `moveCurrent()` to reorder tabs within the group.

### CWindowGroupTarget – The Layout Engine Bridge

Located in [`src/layout/target/WindowGroupTarget.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/layout/target/WindowGroupTarget.cpp), `CWindowGroupTarget` makes the compositor treat the entire group as a single logical window for positioning and resizing. When the layout engine calls `setPositionGlobal()` or `assignToSpace()`, this target propagates those changes to every member window through `updatePos()`.

This design ensures that geometry changes apply uniformly—moving the group moves all windows simultaneously, and workspace assignments update the internal workspace reference via `m_group->updateWorkspace()`.

### CHyprGroupBarDecoration – The Tab Bar Renderer

The visual tab bar is implemented in [`src/render/decorations/CHyprGroupBarDecoration.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/render/decorations/CHyprGroupBarDecoration.cpp). This decoration renders on top of the group's master window and handles mouse interactions. Configuration values starting at line 28 (such as `group:groupbar:enabled` and `group:groupbar:height`) control its appearance.

Mouse click handling around line 420 intercepts tab selection events and translates them into calls to `CGroup::setCurrent()`, which triggers the layout target to update the active window and schedule a repaint.

## Enabling and Configuring the Group Bar

The tab bar is controlled through configuration keys defined in [`CHyprGroupBarDecoration.cpp`](https://github.com/hyprwm/Hyprland/blob/main/CHyprGroupBarDecoration.cpp) (lines 28–43). Add these settings to your [`hyprland.conf`](https://github.com/hyprwm/Hyprland/blob/main/hyprland.conf) to enable the default tabbed appearance:

```ini

# Enable the group bar

group:groupbar:enabled = 1

# Height of the bar in pixels

group:groupbar:height = 24

# Display window titles inside tabs

group:groupbar:render_titles = 1

# Gap between the bar and window content

group:groupbar:gaps_out = 5

# Enable mouse scrolling to switch tabs

group:groupbar:scrolling = 1

# Enable gradient backgrounds for tabs

group:groupbar:gradients = 1

```

These configuration values are read as `CConfigValue` instances and determine how the decoration paints itself within the rendering pipeline, automatically respecting compositor settings like scaling, rounding, and blur.

## Keybinds for Group Management

Window groups are manipulated through `hyprctl` dispatchers that map directly to `CGroup` methods. Define keybinds in your configuration to control grouping without mouse interaction:

```ini

# Create a new group with the focused window

bind = SUPER, G, exec, hyprctl dispatch groupadd

# Add the focused window to the group under the cursor

bind = SUPER SHIFT, G, exec, hyprctl dispatch groupaddfocused

# Switch to the next tab in the current group

bind = SUPER CTRL, Right, exec, hyprctl dispatch groupnext

# Switch to the previous tab

bind = SUPER CTRL, Left, exec, hyprctl dispatch groupprev

# Remove the focused window from its group

bind = SUPER SHIFT, R, exec, hyprctl dispatch groupremove

```

The `groupadd` and `groupaddfocused` commands call `CGroup::add()`, while `groupnext` and `groupprev` invoke `CGroup::moveCurrent()` to cycle through the window list. These actions propagate through `CWindowGroupTarget` and automatically refresh the group bar state.

## Internal Geometry Propagation

When you move or resize a grouped window, the compositor interacts with `CWindowGroupTarget` rather than individual windows. The `setPositionGlobal()` method first applies the geometry change to the target itself, then iterates through all members to synchronize their positions via `updatePos()`.

This propagation ensures that the entire group moves as a rigid unit. When the group switches workspaces through `assignToSpace()`, the target updates the internal workspace reference in `CGroup` and ensures all member windows follow the master window to the new space.

## Programmatic Control via Plugins

If you are developing a Hyprland plugin in C++, you can manipulate groups directly using the internal API:

```cpp
// pWindow is a pointer to the window you want to group
auto group = pWindow->m_group ? pWindow->m_group : makeShared<Desktop::View::CGroup>();

// Add the window to the group and replace its target
group->add(pWindow);
pWindow->m_target = WindowGroupTarget::create(group);

// Make this window the active tab
group->setCurrent(pWindow);

```

This snippet mirrors the logic found in [`CHyprGroupBarDecoration.cpp`](https://github.com/hyprwm/Hyprland/blob/main/CHyprGroupBarDecoration.cpp) (around lines 425–429) where drag-and-drop operations add windows to existing groups. The `WindowGroupTarget::create()` factory function establishes the link between the window and the shared group state.

## Summary

- **Hyprland window grouping** relies on three components: `CGroup` for data, `CWindowGroupTarget` for layout, and `CHyprGroupBarDecoration` for rendering.
- The group bar is configured through `group:groupbar:*` keys in [`CHyprGroupBarDecoration.cpp`](https://github.com/hyprwm/Hyprland/blob/main/CHyprGroupBarDecoration.cpp) and participates automatically in the compositor's rendering pipeline.
- Dispatchers like `groupadd`, `groupnext`, and `groupprev` provide keyboard-driven control over tab creation and navigation.
- Geometry changes propagate through `CWindowGroupTarget` methods like `setPositionGlobal()` and `updatePos()`, ensuring groups move as unified entities.

## Frequently Asked Questions

### How do I enable the tab bar in Hyprland?

Add `group:groupbar:enabled = 1` to your [`hyprland.conf`](https://github.com/hyprwm/Hyprland/blob/main/hyprland.conf) file. Additional options like `group:groupbar:height` and `group:groupbar:render_titles` control the bar's appearance, as defined in [`src/render/decorations/CHyprGroupBarDecoration.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/render/decorations/CHyprGroupBarDecoration.cpp).

### What is the difference between `groupadd` and `groupaddfocused`?

The `groupadd` dispatcher creates a new group containing only the currently focused window. The `groupaddfocused` dispatcher adds the focused window to the existing group that contains the window currently under the cursor, effectively merging windows into a shared `CGroup` instance.

### Why does moving one window move the entire group?

Because `CWindowGroupTarget` (in [`src/layout/target/WindowGroupTarget.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/layout/target/WindowGroupTarget.cpp)) intercepts geometry changes and forwards them to every member window via `updatePos()`. This makes the compositor treat the group as a single entity for positioning and resizing operations.

### Can I change the active tab with my mouse wheel?

Yes, set `group:groupbar:scrolling = 1` in your configuration. The `CHyprGroupBarDecoration` class handles scroll events (around line 420 in its source file) and translates them into calls to `CGroup::moveCurrent()`, cycling through the tab list without keyboard interaction.