docs

Popups and Dialogs

Create popup windows for menus and dropdowns, and display native modal message boxes.

On this page

You can display menus, dropdown lists, and context menus that extend outside the application window using popup windows. A popup is a small OS window owned by another window— it stays above its owner, leaves keyboard focus with the owner when clicked, and dismisses the way a native menu does.

For quick confirmations and alerts, native modal message boxes display standard OS dialogs that block until the user responds.

Creating a Popup

Call Window::CreatePopup() with an owner window, position coordinates, and dimensions:

C++
#include <AppCore/Window.h>

using namespace ultralight;

class MyApp {
 public:
  void ShowContextMenu(double x, double y) {
    ///
    /// Show a context menu at (x, y) within the owner's content area.
    ///
    menu_ = Window::CreatePopup(window_, x, y, 220, 320);
    menu_->SetBackdrop(BackdropMaterial::Popup);

    ///
    /// The popup is see-through, so its page needs a transparent View (and
    /// a transparent page background).
    ///
    ViewConfig config;
    config.is_transparent = true;
    menu_->AddPanel({}, config)->view()->LoadURL("file:///menu.html");
  }

 private:
  RefPtr<Window> window_;
  RefPtr<Window> menu_;
};

Popups are borderless, transparent windows that stay above their owner window without appearing in the OS taskbar. When the owner window hides, the popup hides with it.

Positioning Popups

Popup coordinates use logical pixels measured from the top-left of the owner window's content area— calls to Window::MoveTo(), Window::x(), and Window::y() use this same coordinate space.

When a panel fills the owner window, page coordinates match the owner's content area directly. Coordinates from getBoundingClientRect() pass straight into popup placement without conversion.

If a panel occupies only part of the window (such as below a toolbar), add the panel's offset to the page coordinates before positioning the popup.

Styling Popups

Call Window::SetBackdrop(BackdropMaterial::Popup) to apply the host OS's native menu material. The material shows through transparent areas, so the popup's View requires ViewConfig::is_transparent = true and the page needs a transparent background.

A popup never becomes the active window, so its material displays the active look by default.

Popups display with rounded corners and a drop shadow by default. Call Window::SetCornerStyle(CornerStyle::Square) for sharp corners without a shadow (see Native Window Styling).

Showing and Reusing Popups

Popups appear immediately when created unless passed WindowFlags::Hidden.

For menus that open repeatedly, create the popup once with WindowFlags::Hidden. When opening the menu, call Window::MoveTo() to set its position and Window::Show() to display it.

Dismissing a popup hides the window without destroying it, preserving the instance for subsequent opens.

📘 Choosing between popups and panels

Use a popup when UI content must extend outside the main window, such as a context menu or dropdown list. For content that stays within window boundaries (such as toast notifications or in-window dialogs), use a floating panel instead. See Floating Panels.

Dismissing Popups

Popups dismiss automatically the way native desktop menus do.

Automatic Dismissal

By default, popups use Dismiss::Auto. The library hides the popup whenever the OS would dismiss a native menu:

The dismissal check runs before the window receives input callbacks. Consuming an input event by returning false cannot keep a popup open.

Keeping Popups Open

Call Window::SetDismiss(Dismiss::Manual) to disable automatic dismissal. The popup remains visible until you hide it— useful for tool palettes and flyout panels.

Reacting to Dismissals

Implement WindowListener::OnDismiss() on the popup and assign it with Window::set_listener().

The callback fires whenever the library hides the popup automatically, including when its owner window is hidden. It never fires when you hide the popup directly with Window::Hide().

🚧 Menu button clicks

The press that dismisses a popup still reaches the owner window's page. Clicking a menu button while its popup is already open dismisses the popup and immediately reopens it. You should track dismissal times and ignore clicks that arrive right after WindowListener::OnDismiss() (see Native Look and Feel).

Hiding Child Popups

Hiding any window automatically hides every popup it owns, so hiding a parent menu hides all of its submenus as well.

The library fires WindowListener::OnDismiss() for each child popup hidden this way, but never for the window you hid directly.

Managing Keyboard Focus

Clicking inside a popup leaves keyboard focus with the owner window, and keystrokes continue to go to the owner. This matches standard desktop menu behavior.

Call Window::SetAcceptsKeyInput(true) for popups that include editable text fields. When enabled under Dismiss::Auto, pressing Esc while the popup has focus dismisses the popup.

Lifetime and Window Limits

When an owner window closes, all of its popups close with it, firing WindowListener::OnClose() for each popup. You still hold valid RefPtr<Window> handles, but calling Window::Show() or Window::MoveTo() on an orphaned popup only logs a warning. Reuse popups on a window that outlives them.

Calls to Window::Maximize(), Window::Minimize(), Window::Restore(), Window::SetWindowButtons(), and Window::MoveToCenter() are ignored on popups with a warning.

Showing Native Message Boxes

Call ShowMessageBox() from <AppCore/Dialogs.h> to display a modal OS dialog that blocks until the user responds:

C++
#include <AppCore/Dialogs.h>

using namespace ultralight;

///
/// Ask before discarding the user's edits.
///
bool ConfirmDiscard() {
  ButtonResult result = ShowMessageBox("Discard changes?",
                                       "Your unsaved edits will be lost.",
                                       DialogIcon::Question, ButtonType::YesNo);
  return result == ButtonResult::Yes;
}

The call returns a ButtonResult indicating which button the user selected (ButtonResult::OK, ButtonResult::Cancel, ButtonResult::Yes, or ButtonResult::No).

Pass optional icon and button configuration values to customize the dialog:

Parameter Default Values
icon DialogIcon::Info DialogIcon::Info, DialogIcon::Warning, DialogIcon::Error, DialogIcon::Question
buttons ButtonType::OK ButtonType::OK, ButtonType::OKCancel, ButtonType::YesNo

To build custom modal dialogs using HTML and CSS instead of native OS dialogs, create a floating panel configured with FocusPolicy::Grab (see Floating Panels).