diff --git a/native/libwinbridge/bridge.cpp b/native/libwinbridge/bridge.cpp
index 0f6bf53..f459755 100644
--- a/native/libwinbridge/bridge.cpp
+++ b/native/libwinbridge/bridge.cpp
@@ -331,12 +331,7 @@ LRESULT CALLBACK notification_worker_procedure(HWND window, unsigned int msg, WP
 	}
 }
 
-int32_t show_notification(wchar_t * message, wchar_t * icon_path) {
-    if (nw != NULL) {
-        SetWindowText(hwnd_st_u, L"                                                 ");
-        SetWindowText(hwnd_st_u, message);
-    }
-
+int32_t initialize_notification(wchar_t * icon_path) {
     g_espanso_icon = (HBITMAP)LoadImage(NULL, icon_path, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
 
     SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
@@ -381,12 +376,12 @@ int32_t show_notification(wchar_t * message, wchar_t * icon_path) {
             y = 40; h = 30;
             x = 100; w = 180;
             hwnd_st_u = CreateWindowEx(0, L"static", L"ST_U",
-                                     WS_CHILD | WS_VISIBLE | WS_TABSTOP | SS_CENTER,
-                                     x, y, w, h,
-                                     nw, (HMENU)(501),
-                                     (HINSTANCE)GetWindowLong(nw, GWLP_HINSTANCE), NULL);
+                                       WS_CHILD | WS_VISIBLE | WS_TABSTOP | SS_CENTER,
+                                       x, y, w, h,
+                                       nw, (HMENU)(501),
+                                       (HINSTANCE)GetWindowLong(nw, GWLP_HINSTANCE), NULL);
 
-            SetWindowText(hwnd_st_u, message);
+            SetWindowText(hwnd_st_u, L"Loading...");
 
             int posX = GetSystemMetrics(SM_CXSCREEN) - 350;
             int posY = GetSystemMetrics(SM_CYSCREEN) - 200;
@@ -394,7 +389,7 @@ int32_t show_notification(wchar_t * message, wchar_t * icon_path) {
             SetWindowPos(nw, HWND_TOP, posX, posY, 0, 0, SWP_NOSIZE);
 
             // Hide the window
-            ShowWindow(nw, SW_SHOW);
+            ShowWindow(nw, SW_HIDE);
 
             // Enter the Event loop
             MSG msg;
@@ -403,13 +398,26 @@ int32_t show_notification(wchar_t * message, wchar_t * icon_path) {
     }
     else {
         // Something went wrong, error.
-        return -1;
+        return GetLastError();
     }
 
     return 1;
 }
 
+int32_t show_notification(wchar_t * message) {
+    if (nw != NULL) {
+        SetWindowText(hwnd_st_u, L"                                                 ");
+        SetWindowText(hwnd_st_u, message);
+
+        // Show the window
+        ShowWindow(nw, SW_SHOW);
+        return 1;
+    }
+
+    return -1;
+}
+
 void close_notification() {
-    SendMessage(nw, WM_CLOSE, 0, 0);
-    nw = NULL;
+    // Hide the window
+    ShowWindow(nw, SW_HIDE);
 }
\ No newline at end of file
diff --git a/native/libwinbridge/bridge.h b/native/libwinbridge/bridge.h
index d7bfd6e..0676032 100644
--- a/native/libwinbridge/bridge.h
+++ b/native/libwinbridge/bridge.h
@@ -56,10 +56,15 @@ extern "C" int32_t get_active_window_executable(wchar_t * buffer, int32_t size);
 
 // UI
 
+/*
+ * Initialize the notification window.
+ */
+extern "C" int32_t initialize_notification(wchar_t * icon_path);
+
 /*
  * Show a window containing the notification.
  */
-extern "C" int32_t show_notification(wchar_t * message, wchar_t * icon_path);
+extern "C" int32_t show_notification(wchar_t * message);
 
 /*
  * Close the notification if present
diff --git a/src/bridge/windows.rs b/src/bridge/windows.rs
index 50f114b..8814e96 100644
--- a/src/bridge/windows.rs
+++ b/src/bridge/windows.rs
@@ -8,7 +8,8 @@ extern {
     pub fn get_active_window_executable(buffer: *mut u16, size: i32) -> i32;
 
     // UI
-    pub fn show_notification(message: *const u16, icon_path: *const u16) -> i32;
+    pub fn initialize_notification(icon_path: *const u16) -> i32;
+    pub fn show_notification(message: *const u16) -> i32;
     pub fn close_notification();
 
     // KEYBOARD
diff --git a/src/engine.rs b/src/engine.rs
index 82ebfe4..6f59732 100644
--- a/src/engine.rs
+++ b/src/engine.rs
@@ -3,20 +3,27 @@ use crate::keyboard::KeyboardSender;
 use crate::config::ConfigManager;
 use crate::config::BackendType;
 use crate::clipboard::ClipboardManager;
+use log::{info};
+use crate::ui::UIManager;
 
-pub struct Engine<'a, S: KeyboardSender, C: ClipboardManager, M: ConfigManager> {
+pub struct Engine<'a, S: KeyboardSender, C: ClipboardManager, M: ConfigManager,
+                  U: UIManager> {
     sender: S,
     clipboard_manager: &'a C,
     config_manager: &'a M,
+    ui_manager: &'a U,
 }
 
-impl <'a, S: KeyboardSender, C: ClipboardManager, M: ConfigManager> Engine<'a, S, C, M> {
-    pub fn new<'b>(sender: S, clipboard_manager: &'b C, config_manager: &'b M) -> Engine<'b, S, C, M> {
-        Engine{sender, clipboard_manager, config_manager }
+impl <'a, S: KeyboardSender, C: ClipboardManager, M: ConfigManager, U: UIManager>
+    Engine<'a, S, C, M, U> {
+    pub fn new<'b>(sender: S, clipboard_manager: &'b C, config_manager: &'b M, ui_manager: &'b U) -> Engine<'b, S, C, M, U> {
+        Engine{sender, clipboard_manager, config_manager, ui_manager }
     }
 }
 
-impl <'a, S: KeyboardSender, C: ClipboardManager, M: ConfigManager> MatchReceiver for Engine<'a, S, C, M>{
+impl <'a, S: KeyboardSender, C: ClipboardManager, M: ConfigManager, U: UIManager>
+    MatchReceiver for Engine<'a, S, C, M, U>{
+
     fn on_match(&self, m: &Match) {
         let config = self.config_manager.default_config();
 
@@ -48,4 +55,16 @@ impl <'a, S: KeyboardSender, C: ClipboardManager, M: ConfigManager> MatchReceive
             },
         }
     }
+
+    fn on_toggle(&self, status: bool) {
+        let message = if status {
+            "espanso enabled"
+        }else{
+            "espanso disabled"
+        };
+
+        info!("Toggled: {}", message);
+
+        self.ui_manager.notify(message);
+    }
 }
\ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index 21e31a6..248bab1 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -95,9 +95,6 @@ fn espanso_background(rxc: Receiver<KeyEvent>, config_set: ConfigSet) {
     let config_manager = RuntimeConfigManager::new(config_set, system_manager);
 
     let ui_manager = ui::get_uimanager();
-    ui_manager.notify("Hello guys");
-    thread::sleep(time::Duration::from_millis(600));
-    ui_manager.notify("There");
 
     let clipboard_manager = clipboard::get_manager();
 
@@ -105,7 +102,9 @@ fn espanso_background(rxc: Receiver<KeyEvent>, config_set: ConfigSet) {
 
     let engine = Engine::new(sender,
                              &clipboard_manager,
-                             &config_manager);
+                             &config_manager,
+                             &ui_manager
+    );
 
     let matcher = ScrollingMatcher::new(&config_manager, engine);
     matcher.watch(rxc);
diff --git a/src/matcher/mod.rs b/src/matcher/mod.rs
index 46b9236..55a1c04 100644
--- a/src/matcher/mod.rs
+++ b/src/matcher/mod.rs
@@ -12,6 +12,7 @@ pub struct Match {
 
 pub trait MatchReceiver {
     fn on_match(&self, m: &Match);
+    fn on_toggle(&self, status: bool);
 }
 
 pub trait Matcher {
diff --git a/src/matcher/scrolling.rs b/src/matcher/scrolling.rs
index 7b630ae..2dbd6ea 100644
--- a/src/matcher/scrolling.rs
+++ b/src/matcher/scrolling.rs
@@ -86,7 +86,7 @@ impl <'a, R: MatchReceiver, M: ConfigManager> super::Matcher for ScrollingMatche
                         self.current_set_queue.borrow_mut().clear();
                     }
 
-                    println!("Enabled {}", *is_enabled);
+                    self.receiver.on_toggle(*is_enabled);
                 }
             }
 
diff --git a/src/ui/windows.rs b/src/ui/windows.rs
index c03a188..520c9ed 100644
--- a/src/ui/windows.rs
+++ b/src/ui/windows.rs
@@ -1,5 +1,5 @@
 use std::process::Command;
-use crate::bridge::windows::{show_notification, close_notification};
+use crate::bridge::windows::{show_notification, close_notification, initialize_notification};
 use widestring::U16CString;
 use std::{fs, thread, time};
 use log::{info, debug};
@@ -41,15 +41,10 @@ impl super::UIManager for WindowsUIManager {
         });
 
         // Create and show a window notification
-        let message = message.to_owned();
-        let icon_file = self.icon_file.clone();
-        thread::spawn( move || {
-            unsafe {
-                let message = U16CString::from_str(message).unwrap();
-                let icon_file = U16CString::from_str(&icon_file).unwrap();
-                show_notification(message.as_ptr(), icon_file.as_ptr());
-            }
-        });
+        unsafe {
+            let message = U16CString::from_str(message).unwrap();
+            show_notification(message.as_ptr());
+        }
 
     }
 }
@@ -70,6 +65,14 @@ impl WindowsUIManager {
         info!("Extracted cached icon to: {}", icon_file);
 
         let id = Arc::new(Mutex::new(0));
+        let icon_file_c = U16CString::from_str(&icon_file).unwrap();
+
+        thread::spawn(move || {
+            unsafe {
+                initialize_notification(icon_file_c.as_ptr());
+            }
+        });
+
         WindowsUIManager {
             icon_file,
             id