# How to Create Modal Dialogs and Popup Windows in ImGui

> Learn to create modal dialogs and popup windows in ImGui. Understand BeginPopupModal vs BeginPopup for blocking interaction or allowing dismissals. Build better UIs.

- Repository: [omar/imgui](https://github.com/ocornut/imgui)
- Tags: how-to-guide
- Published: 2026-07-16

---

**Modal dialogs in ImGui block all background interaction and require `BeginPopupModal()`, while standard popups use `BeginPopup()` and allow clicking outside to dismiss.**

Creating user interface overlays in the ocornut/imgui library requires understanding the distinction between blocking modal dialogs and transient popup windows. While both constructs share the same underlying window system in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp), they differ significantly in their API entry points, input handling, and dismissal behavior. This guide explains how to correctly implement each pattern using the exact function signatures defined in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h).

## Modal vs. Popup: Understanding the Architectural Distinction

Dear ImGui distinguishes between two primary overlay types based on their interaction model and rendering flags.

**Modal Dialogs** are blocking windows that capture all input and automatically dim the background. They must be dismissed programmatically or via explicit user action before the user can interact with other UI elements.

**Regular Popups** are non-blocking overlays typically attached to a parent item (such as a right-click context menu). They do not prevent interaction with other windows and automatically close when the user clicks outside their bounds or presses **Esc**.

The key differences are summarized in the implementation details:

- **Blocking Behavior**: Modals prevent all other UI interaction until `CloseCurrentPopup()` is called or the open flag is cleared. Popups only block interaction with their own contents.
- **Background Dimming**: Modals automatically darken the screen behind them via the internal `ImGuiWindowFlags_Modal` flag (defined at line 1199 in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h)). Popups leave the background fully interactive and undimmed.
- **Close Mechanisms**: Modals require explicit closing logic in your code. Popups support implicit closing through outside clicks or the **Esc** key.

## Core API Functions and Flags

The public API in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) exposes specific entry points for each dialog type.

### BeginPopupModal

To create a modal dialog, call `BeginPopupModal()` with a unique identifier string. As declared at line 849 of [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h):

```cpp
IMGUI_API bool BeginPopupModal(const char* name,
                               bool* p_open = NULL,
                               ImGuiWindowFlags flags = 0);

```

This function returns `true` only when the modal is actually open, allowing you to emit its contents. The optional `p_open` pointer enables automatic handling of the title bar close button; ImGui will set this boolean to `false` if the user clicks "X".

**Important**: Do not manually set the `ImGuiWindowFlags_Modal` flag. This bit is reserved for internal use (as noted at line 1199) and is applied automatically by `BeginPopupModal()`.

### BeginPopup and Context Wrappers

For non-blocking popups, use `BeginPopup()` or convenience wrappers like `BeginPopupContextItem()` and `BeginPopupContextWindow()`. These functions also return `true` when the popup is active:

```cpp
if (ImGui::BeginPopup("MyContext")) {
    // Render popup contents
    ImGui::EndPopup();
}

```

### Closing Popups

Regardless of type, always end the popup scope with `EndPopup()`. To close the popup from within its body, call `CloseCurrentPopup()`. The modal or popup is automatically removed from the internal stack on the next frame.

## Step-by-Step Implementation Guide

### Opening a Modal Dialog

Unlike regular windows, modals require an explicit open request. The standard pattern uses a state boolean to trigger the modal on the next frame:

1. Set a boolean flag to `true` when the user triggers the action (e.g., clicking a delete button).
2. In your main UI loop, check this flag and call `BeginPopupModal()`.
3. Render the contents inside the `if` block.
4. Call `EndPopup()` to close the scope.

This deferred opening ensures ImGui correctly manages the window focus stack in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp).

### Handling the Close Button and State Management

When you pass a boolean pointer (`p_open`) to `BeginPopupModal()`, ImGui automatically checks for title bar close clicks. However, you must preserve this state after the call:

```cpp
bool keep_open = true;
if (ImGui::BeginPopupModal("Settings", &keep_open)) {
    // ... contents ...
    ImGui::EndPopup();
}
if (!keep_open) {
    // Handle closure logic here
}

```

If you do not provide the `p_open` pointer, you must explicitly call `CloseCurrentPopup()` or rely on programmatic logic to stop calling `BeginPopupModal()` in subsequent frames.

### Creating Regular Context Menu Popups

For transient menus, use `OpenPopup()` to push the ID to the stack, then test `BeginPopup()`:

```cpp
if (ImGui::Button("Options")) {
    ImGui::OpenPopup("ContextMenu");
}
if (ImGui::BeginPopup("ContextMenu")) {
    if (ImGui::MenuItem("Copy")) { /* ... */ }
    ImGui::EndPopup();
}

```

This pattern does not block the background and automatically handles dismissal when the user clicks elsewhere.

## Practical Code Examples

### Simple Confirmation Modal

This example demonstrates a blocking confirmation dialog with explicit state management. The modal opens when `show_confirm` is true and closes via `CloseCurrentPopup()`:

```cpp
static bool show_confirm = false;
static bool confirm_result = false;

if (ImGui::Button("Delete File")) {
    show_confirm = true;
}

if (show_confirm && ImGui::BeginPopupModal("Confirm Delete", nullptr,
                                           ImGuiWindowFlags_AlwaysAutoResize)) {
    ImGui::TextWrapped("Are you sure you want to delete this file?");
    ImGui::Separator();
    
    if (ImGui::Button("Yes", ImVec2(120, 0))) {
        confirm_result = true;
        show_confirm = false;
        ImGui::CloseCurrentPopup();
    }
    ImGui::SameLine();
    if (ImGui::Button("Cancel", ImVec2(120, 0))) {
        confirm_result = false;
        show_confirm = false;
        ImGui::CloseCurrentPopup();
    }
    ImGui::EndPopup();
}

```

### Modal with Title Bar Close Button

Passing the state pointer allows ImGui to handle the "X" button automatically. Synchronize the flag after the call to capture title bar closures:

```cpp
static bool open_settings = false;
if (ImGui::MenuItem("Settings")) {
    open_settings = true;
}

bool keep_open = open_settings;
if (ImGui::BeginPopupModal("Settings", &keep_open,
                           ImGuiWindowFlags_NoResize)) {
    ImGui::Text("Adjust application options here.");
    
    if (ImGui::Button("Save")) {
        keep_open = false;
    }
    ImGui::EndPopup();
}
open_settings = keep_open;  // Update state if user clicked title bar X

```

### Regular Context Popup

This non-blocking popup attaches to a button and allows background interaction:

```cpp
if (ImGui::Button("Right-Click Me")) {
    ImGui::OpenPopup("MyContext");
}

if (ImGui::BeginPopup("MyContext")) {
    if (ImGui::MenuItem("Option A")) { /* handle A */ }
    if (ImGui::MenuItem("Option B")) { /* handle B */ }
    ImGui::EndPopup();
}

```

## Summary

- **Use `BeginPopupModal()`** for blocking dialogs that must capture all input and dim the background, as implemented in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp).
- **Pass `p_open`** to `BeginPopupModal()` to enable the title bar close button, but remember to synchronize the boolean after the call.
- **Use `BeginPopup()`** for non-blocking context menus that should close when clicking outside.
- **Always call `EndPopup()`** to close the scope, and use `CloseCurrentPopup()` to dismiss the popup programmatically.
- **Never manually set `ImGuiWindowFlags_Modal`** (line 1199 of [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h)); this flag is internal to the library.

## Frequently Asked Questions

### What is the difference between `BeginPopup()` and `BeginPopupModal()`?

`BeginPopup()` creates a transient overlay that does not block other windows and closes automatically when clicking outside or pressing **Esc**. `BeginPopupModal()` creates a blocking dialog that dims the background and prevents interaction with other UI elements until explicitly dismissed via `CloseCurrentPopup()` or a cleared boolean flag.

### How do I close a modal dialog when the user clicks a button?

Call `ImGui::CloseCurrentPopup()` inside the modal's body. If you passed a `bool* p_open` to `BeginPopupModal()`, you can also set `*p_open = false`. The modal will be removed from the internal stack on the next frame after `EndPopup()` is called.

### Why does my modal not open when I call `BeginPopupModal()`?

`BeginPopupModal()` returns `false` unless the popup is actually open in the current frame. You must either call `ImGui::OpenPopup()` before testing `BeginPopupModal()`, or use a persistent boolean flag to trigger the modal on the next frame. This deferred opening mechanism allows ImGui to manage focus and z-order correctly in the internal window system.

### Can I manually add the `ImGuiWindowFlags_Modal` flag to a regular window?

No. According to the source code at line 1199 of [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h), `ImGuiWindowFlags_Modal` is marked for internal use only. The flag is automatically applied by `BeginPopupModal()`. Manually setting it on a regular window created with `Begin()` will result in undefined behavior or failed assertions in debug builds.