How the Active Bar Is Determined in Omarchy's shell.json
The active bar in Omarchy is determined at runtime by matching the currently focused monitor against the screen name stored in each BarModel instance, using the pickPanelSlot function to select the appropriate panel slot.
Omarchy’s desktop environment uses a dynamic panel system where the "active" bar—the one receiving input events and hosting open widgets—switches automatically based on monitor focus. This behavior is defined in the shell.json configuration but resolved through JavaScript logic in the Quickshell runtime. Understanding how the active bar is determined requires examining both the static configuration and the runtime selection algorithm.
The Configuration Foundation in shell.json
The static definition of Omarchy’s top-level panel resides in config/omarchy/shell.json under the bar object. This JSON structure specifies the layout, position, and widget IDs for the desktop bar, but it does not explicitly designate which monitor displays the active instance.
When Quickshell initializes, it reads this configuration and creates a BarModel instance for every connected monitor that has a bar configuration. Each instance registers its slots (widgets) with the panel system and stores the monitor’s identifier—referred to as the screenName—within the model for later comparison.
Runtime Bar Selection via BarModel.js
The core logic for determining which bar is active lives in shell/plugins/bar/BarModel.js. As implemented in the omacom/omarchy repository, the system maintains a list of candidate panel slots across all monitors and selects the active one based on current focus.
The selection process relies on two key inputs:
focusedScreen– The monitor identifier provided by Quickshell’s environment that indicates which screen currently has user focuscandidates– An array of panel slots, each tagged with itsscreenNameand anopenedstatus flag
The pickPanelSlot Algorithm
The pickPanelSlot(candidates, focusedScreen) function implements a three-tier fallback strategy to identify the active bar:
- Prefer opened slots – If any slot has its
openedflag set totrue, that slot takes priority regardless of focus - Fallback to focused screen – If no slots are open, select the slot whose
screenNamematchesfocusedScreen - Visibility check – Use
pickDrawnSlotto ensure the selected slot is actually visible and has non-zero dimensions
When the user moves focus to a different monitor, the next invocation of pickPanelSlot automatically selects that monitor’s bar, seamlessly switching the active panel context.
Practical Implementation Example
The following code demonstrates how to determine and interact with the active bar programmatically:
// 1. Determine the focused screen (provided by Quickshell)
const focusedScreen = Quickshell.env("focusedScreen");
// 2. Build an array of candidate panel slots (one per monitor)
const candidates = [
{ slot: barModelA.slot, screenName: "DP-1", opened: false },
{ slot: barModelB.slot, screenName: "HDMI-1", opened: true },
// …
];
// 3. Choose the active slot – the bar on the focused monitor wins
const activeSlot = pickPanelSlot(candidates, focusedScreen);
// 4. The activeSlot is now used for popup routing, panel toggles, etc.
if (activeSlot) {
// e.g. open the power panel on the active bar
activeSlot.slot.openPanel("omarchy.power");
}
In this example, even though barModelA might correspond to the primary monitor, barModelB becomes the active bar because its monitor has focus (or because it has an opened widget).
Key Files in the Active Bar System
Understanding the full implementation requires examining these specific source files:
config/omarchy/shell.json– Provides the static bar configuration including position, layout, and widget IDsshell/plugins/bar/BarModel.js– Implements bar creation, widget registration, and thepickPanelSlotlogic that selects the active bar based on the focused screenshell/plugins/bar/widgets/TrayModel.js– Example widget implementation that participates in the active-bar decision via the slot system
Summary
- The active bar is not statically assigned in
shell.jsonbut determined dynamically at runtime based on monitor focus. BarModel.jscreates a model instance per monitor, storing thescreenNamefor comparison against the focused screen.pickPanelSlotselects the active bar by preferring opened slots, then falling back to the slot matchingfocusedScreen, and finally verifying visibility viapickDrawnSlot.- When focus moves between monitors, the active bar switches automatically without requiring configuration changes.
Frequently Asked Questions
How does Omarchy handle the active bar on single-monitor setups?
On single-monitor setups, the logic remains identical but simplified. Since only one BarModel instance exists in the candidates array, pickPanelSlot returns that instance by default regardless of focus state. If no monitor reports focus (a rare edge case), the first available bar instance becomes the default active bar.
Can a widget force its bar to become active without changing monitor focus?
Yes. Widgets can influence the active bar selection through the opened flag. When a widget sets its slot's opened property to true, pickPanelSlot prioritizes that slot over others, even if the monitor does not currently have focus. This allows popups and system trays to maintain context on their original bar.
What happens if the focused screen does not have a bar configured?
If the currently focused monitor lacks a bar configuration in shell.json, no BarModel exists for that screen name. In this scenario, pickPanelSlot skips the focus-matching logic and falls back to selecting the first opened slot, or if none are open, the first drawn (visible) slot from any monitor that has a bar.
Where does the focusedScreen value originate?
The focusedScreen value originates from the Quickshell runtime environment, accessed via Quickshell.env("focusedScreen"). This environment variable is updated automatically by the compositor whenever the user shifts focus between monitors, triggering the bar selection logic to re-evaluate and potentially switch the active bar.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →