diff --git a/src/bar.rs b/src/bar.rs
index 49147555..85f7ec03 100644
--- a/src/bar.rs
+++ b/src/bar.rs
@@ -22,6 +22,7 @@ enum Inner {
 pub struct Bar {
     name: String,
     monitor_name: String,
+    monitor_size: (i32, i32),
     position: BarPosition,
 
     ironbar: Rc<Ironbar>,
@@ -41,6 +42,7 @@ impl Bar {
     pub fn new(
         app: &Application,
         monitor_name: String,
+        monitor_size: (i32, i32),
         config: BarConfig,
         ironbar: Rc<Ironbar>,
     ) -> Self {
@@ -89,6 +91,7 @@ impl Bar {
         Self {
             name,
             monitor_name,
+            monitor_size,
             position,
             ironbar,
             window,
@@ -146,7 +149,7 @@ impl Bar {
             }
         }
 
-        let load_result = self.load_modules(config, monitor)?;
+        let load_result = self.load_modules(config, monitor, self.monitor_size)?;
 
         self.show(!start_hidden);
 
@@ -243,7 +246,12 @@ impl Bar {
     }
 
     /// Loads the configured modules onto a bar.
-    fn load_modules(&self, config: BarConfig, monitor: &Monitor) -> Result<BarLoadResult> {
+    fn load_modules(
+        &self,
+        config: BarConfig,
+        monitor: &Monitor,
+        output_size: (i32, i32),
+    ) -> Result<BarLoadResult> {
         let icon_theme = IconTheme::new();
         if let Some(ref theme) = config.icon_theme {
             icon_theme.set_custom_theme(Some(theme));
@@ -265,7 +273,7 @@ impl Bar {
         }
 
         // popup ignores module location so can bodge this for now
-        let popup = Popup::new(&info!(ModuleLocation::Left), config.popup_gap);
+        let popup = Popup::new(&info!(ModuleLocation::Left), output_size, config.popup_gap);
         let popup = Rc::new(popup);
 
         if let Some(modules) = config.start {
@@ -384,9 +392,10 @@ pub fn create_bar(
     app: &Application,
     monitor: &Monitor,
     monitor_name: String,
+    monitor_size: (i32, i32),
     config: BarConfig,
     ironbar: Rc<Ironbar>,
 ) -> Result<Bar> {
-    let bar = Bar::new(app, monitor_name, config, ironbar);
+    let bar = Bar::new(app, monitor_name, monitor_size, config, ironbar);
     bar.init(monitor)
 }
diff --git a/src/main.rs b/src/main.rs
index 4657574d..5deae779 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -363,6 +363,8 @@ fn load_output_bars(
     // We also need this static to ensure hot-reloading continues to work as best we can.
     static INDEX_MAP: OnceLock<Mutex<Vec<String>>> = OnceLock::new();
 
+    let output_size = output.logical_size.unwrap_or_default();
+
     let Some(monitor_name) = &output.name else {
         return Err(Report::msg("Output missing monitor name"));
     };
@@ -401,6 +403,7 @@ fn load_output_bars(
                 app,
                 &monitor,
                 monitor_name.to_string(),
+                output_size,
                 config.clone(),
                 ironbar.clone(),
             )?]
@@ -412,6 +415,7 @@ fn load_output_bars(
                     app,
                     &monitor,
                     monitor_name.to_string(),
+                    output_size,
                     config.clone(),
                     ironbar.clone(),
                 )
@@ -421,6 +425,7 @@ fn load_output_bars(
             app,
             &monitor,
             monitor_name.to_string(),
+            output_size,
             config.bar.clone(),
             ironbar.clone(),
         )?],
diff --git a/src/popup.rs b/src/popup.rs
index 5946e994..f04ef7b5 100644
--- a/src/popup.rs
+++ b/src/popup.rs
@@ -3,16 +3,14 @@ use std::cell::RefCell;
 use std::collections::HashMap;
 use std::rc::Rc;
 
-use gtk::gdk::Monitor;
-use gtk::prelude::*;
-use gtk::{ApplicationWindow, Button, Orientation};
-use gtk_layer_shell::LayerShell;
-use tracing::{debug, trace};
-
 use crate::config::BarPosition;
 use crate::gtk_helpers::{IronbarGtkExt, WidgetGeometry};
 use crate::modules::{ModuleInfo, ModulePopupParts, PopupButton};
 use crate::rc_mut;
+use gtk::prelude::*;
+use gtk::{ApplicationWindow, Button, Orientation};
+use gtk_layer_shell::LayerShell;
+use tracing::{debug, trace};
 
 #[derive(Debug, Clone)]
 pub struct PopupCacheValue {
@@ -25,16 +23,16 @@ pub struct Popup {
     pub window: ApplicationWindow,
     pub container_cache: Rc<RefCell<HashMap<usize, PopupCacheValue>>>,
     pub button_cache: Rc<RefCell<Vec<Button>>>,
-    monitor: Monitor,
     pos: BarPosition,
     current_widget: Rc<RefCell<Option<(usize, usize)>>>,
+    output_size: (i32, i32),
 }
 
 impl Popup {
     /// Creates a new popup window.
     /// This includes setting up gtk-layer-shell
     /// and an empty `gtk::Box` container.
-    pub fn new(module_info: &ModuleInfo, gap: i32) -> Self {
+    pub fn new(module_info: &ModuleInfo, output_size: (i32, i32), gap: i32) -> Self {
         let pos = module_info.bar_position;
         let orientation = pos.orientation();
 
@@ -109,9 +107,9 @@ impl Popup {
             window: win,
             container_cache: rc_mut!(HashMap::new()),
             button_cache: rc_mut!(vec![]),
-            monitor: module_info.monitor.clone(),
             pos,
             current_widget: rc_mut!(None),
+            output_size,
         }
     }
 
@@ -123,13 +121,14 @@ impl Popup {
         }
 
         let orientation = self.pos.orientation();
-        let monitor = self.monitor.clone();
         let window = self.window.clone();
 
         let current_widget = self.current_widget.clone();
         let cache = self.container_cache.clone();
         let button_cache = self.button_cache.clone();
 
+        let output_size = self.output_size;
+
         content
             .container
             .connect_size_allocate(move |container, rect| {
@@ -142,8 +141,8 @@ impl Popup {
                                 &button_cache.borrow(),
                                 button_id,
                                 orientation,
-                                &monitor,
                                 &window,
+                                output_size,
                             );
                         }
                     }
@@ -175,8 +174,8 @@ impl Popup {
                 &self.button_cache.borrow(),
                 button_id,
                 self.pos.orientation(),
-                &self.monitor,
                 &self.window,
+                self.output_size,
             );
         }
     }
@@ -193,8 +192,8 @@ impl Popup {
             Self::set_pos(
                 geometry,
                 self.pos.orientation(),
-                &self.monitor,
                 &self.window,
+                self.output_size,
             );
         }
     }
@@ -203,8 +202,8 @@ impl Popup {
         buttons: &[Button],
         button_id: usize,
         orientation: Orientation,
-        monitor: &Monitor,
         window: &ApplicationWindow,
+        output_size: (i32, i32),
     ) {
         let button = buttons
             .iter()
@@ -212,7 +211,7 @@ impl Popup {
             .expect("to find valid button");
 
         let geometry = button.geometry(orientation);
-        Self::set_pos(geometry, orientation, monitor, window);
+        Self::set_pos(geometry, orientation, window, output_size);
     }
 
     fn clear_window(&self) {
@@ -242,14 +241,13 @@ impl Popup {
     fn set_pos(
         geometry: WidgetGeometry,
         orientation: Orientation,
-        monitor: &Monitor,
         window: &ApplicationWindow,
+        output_size: (i32, i32),
     ) {
-        let mon_workarea = monitor.workarea();
         let screen_size = if orientation == Orientation::Horizontal {
-            mon_workarea.width()
+            output_size.0
         } else {
-            mon_workarea.height()
+            output_size.1
         };
 
         let (popup_width, popup_height) = window.size();