diff --git a/devices/wim/config/ags/bin/osk-toggle.sh b/devices/wim/config/ags/bin/osk-toggle.sh
deleted file mode 100755
index 4c5cea13..00000000
--- a/devices/wim/config/ags/bin/osk-toggle.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env bash
-
-state () {
-    if [[ $(busctl get-property --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 Visible) == "b true" ]]; then
-        echo "Running"
-    else
-        echo "Stopped"
-    fi
-}
-
-toggle () {
-    if [[ $(busctl get-property --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 Visible) == "b true" ]]; then
-        echo "Running"
-        busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b false
-    else
-        echo "Stopped"
-        busctl call --user sm.puri.OSK0 /sm/puri/OSK0 sm.puri.OSK0 SetVisible b true
-    fi
-}
-
-if [[ $1 == "getState" ]]; then
-    while true; do
-        sleep 0.2
-        state
-    done
-fi
-
-if [[ $1 == "toggle" ]];then
-    toggle
-fi
diff --git a/devices/wim/config/ags/js/bar/osk-toggle.js b/devices/wim/config/ags/js/bar/osk-toggle.js
index 7fc7401b..044ed1f7 100644
--- a/devices/wim/config/ags/js/bar/osk-toggle.js
+++ b/devices/wim/config/ags/js/bar/osk-toggle.js
@@ -1,33 +1,21 @@
 import { Box, Label } from 'resource:///com/github/Aylur/ags/widget.js';
-import { subprocess } from 'resource:///com/github/Aylur/ags/utils.js';
 
 import EventBox from '../misc/cursorbox.js';
 
 
 export default () => EventBox({
     className: 'toggle-off',
-    setup: self => {
-        subprocess(
-            ['bash', '-c', '$AGS_PATH/osk-toggle.sh getState'],
-            output => self.toggleClassName('toggle-on', output === 'Running'),
-        );
-    },
+    onPrimaryClickRelease: () => Tablet.toggleOsk(),
 
-    onPrimaryClickRelease: self => {
-        subprocess(
-            ['bash', '-c', '$AGS_PATH/osk-toggle.sh toggle'],
-            output => self.toggleClassName('toggle-on', output !== 'Running'),
-        );
-    },
+    connections: [[Tablet, self => {
+        self.toggleClassName('toggle-on', Tablet.oskState);
+    }, 'osk-toggled']],
 
     child: Box({
         className: 'osk-toggle',
         vertical: false,
-
-        children: [
-            Label({
-                label: ' 󰌌 ',
-            }),
-        ],
+        children: [Label({
+            label: ' 󰌌 ',
+        })],
     }),
 });
diff --git a/devices/wim/config/ags/js/bar/tablet-toggle.js b/devices/wim/config/ags/js/bar/tablet-toggle.js
index 0a93d009..96476251 100644
--- a/devices/wim/config/ags/js/bar/tablet-toggle.js
+++ b/devices/wim/config/ags/js/bar/tablet-toggle.js
@@ -14,8 +14,8 @@ export default () => EventBox({
     child: Box({
         className: 'tablet-toggle',
         vertical: false,
-        child: Label({
+        children: [Label({
             label: ' 󰦧 ',
-        }),
+        })],
     }),
 });
diff --git a/devices/wim/config/ags/services/tablet.js b/devices/wim/config/ags/services/tablet.js
index d2d8233f..eb22f2b8 100644
--- a/devices/wim/config/ags/services/tablet.js
+++ b/devices/wim/config/ags/services/tablet.js
@@ -11,6 +11,7 @@ const ROTATION_MAPPING = {
 const SCREEN = 'desc:BOE 0x0964';
 
 
+// TODO: Make autorotate reset lisgd
 class Tablet extends Service {
     static {
         Service.register(this, {
@@ -22,11 +23,13 @@ class Tablet extends Service {
             'laptop-mode': ['boolean'],
             'tablet-mode': ['boolean'],
             'mode-toggled': ['boolean'],
+            'osk-toggled': ['boolean'],
         });
     }
 
     tabletMode = false;
     autorotate = undefined;
+    oskState = false;
     blockedInputs = undefined;
     udevClient = GUdev.Client.new(['input']);
 
@@ -36,6 +39,7 @@ class Tablet extends Service {
     constructor() {
         super();
         this.initUdevConnection();
+        this.listenOskState();
     }
 
     blockInputs() {
@@ -156,6 +160,40 @@ class Tablet extends Service {
             this.emit('autorotate-destroyed', true);
         }
     }
+
+    listenOskState() {
+        subprocess(
+            ['bash', '-c', 'busctl monitor --user sm.puri.OSK0'],
+            output => {
+                if (output.includes('BOOLEAN')) {
+                    this.oskState = output.match('true|false')[0] === 'true';
+                    this.emit('osk-toggled', this.oskState);
+                }
+            },
+            err => logError(err),
+        );
+    }
+
+    openOsk() {
+        execAsync(['busctl', 'call', '--user',
+            'sm.puri.OSK0', '/sm/puri/OSK0', 'sm.puri.OSK0',
+            'SetVisible', 'b', 'true'])
+            .catch(print);
+    }
+
+    closeOsk() {
+        execAsync(['busctl', 'call', '--user',
+            'sm.puri.OSK0', '/sm/puri/OSK0', 'sm.puri.OSK0',
+            'SetVisible', 'b', 'false'])
+            .catch(print);
+    }
+
+    toggleOsk() {
+        if (this.oskState)
+            this.closeOsk();
+        else
+            this.openOsk();
+    }
 }
 
 const tabletService = new Tablet();