diff --git a/code/__defines/tgui.dm b/code/__defines/tgui.dm
index 96664cf2b3..127f7859ec 100644
--- a/code/__defines/tgui.dm
+++ b/code/__defines/tgui.dm
@@ -28,6 +28,16 @@
"%7b%22type%22%3a%22[type]%22%2c%22payload%22%3a[url_encode(json_encode(payload))]%7d" \
)
+/// Though not the maximum renderable ByondUis within tgui, this is the maximum that the server will manage per-UI
+#define TGUI_MANAGED_BYONDUI_LIMIT 10
+
+// These are defines instead of being inline, as they're being sent over
+// from tgui-core, so can't be easily played with
+#define TGUI_MANAGED_BYONDUI_TYPE_RENDER "renderByondUi"
+#define TGUI_MANAGED_BYONDUI_TYPE_UNMOUNT "unmountByondUi"
+
+#define TGUI_MANAGED_BYONDUI_PAYLOAD_ID "renderByondUi"
+
/// Max length for Modal Input
#define TGUI_MODAL_INPUT_MAX_LENGTH 1024
/// Max length for Modal Input for names
diff --git a/code/modules/tgui/tgui.dm b/code/modules/tgui/tgui.dm
index e2fd46c67d..e965b4f69b 100644
--- a/code/modules/tgui/tgui.dm
+++ b/code/modules/tgui/tgui.dm
@@ -37,8 +37,8 @@
var/datum/tgui_state/state = null
/// Rate limit client refreshes to prevent DoS.
COOLDOWN_DECLARE(refresh_cooldown)
- /// Are byond mouse events beyond the window passed in to the ui
- var/mouse_hooked = FALSE
+ /// The id of any ByondUi elements that we have opened
+ var/list/open_byondui_elements
/// The map z-level to display.
var/map_z_level = 1
/// The Parent UI
@@ -50,6 +50,7 @@
/// If the window should be closed with other windows when requested
var/closeable = TRUE
+
/**
* public
*
@@ -128,8 +129,6 @@
window.send_message("update", get_payload(
with_data = TRUE,
with_static_data = TRUE))
- if(mouse_hooked)
- window.set_mouse_macro()
SStgui.on_open(src)
return TRUE
@@ -172,12 +171,29 @@
window.close(can_be_suspended, logout)
src_object.tgui_close(user)
SStgui.on_close(src)
+
+ if(user.client)
+ terminate_byondui_elements()
+
state = null
if(parent_ui)
parent_ui.children -= src
parent_ui = null
qdel(src)
+/**
+ * public
+ *
+ * Closes all ByondUI elements, left dangling by a forceful TGUI exit,
+ * such as via Alt+F4, closing in non-fancy mode, or terminating the process
+ *
+ */
+/datum/tgui/proc/terminate_byondui_elements()
+ set waitfor = FALSE
+
+ for(var/byondui_element in open_byondui_elements)
+ winset(user.client, byondui_element, list("parent" = ""))
+
/**
* public
*
@@ -188,17 +204,6 @@
/datum/tgui/proc/set_autoupdate(autoupdate)
src.autoupdate = autoupdate
-/**
- * public
- *
- * Enable/disable passing through byond mouse events to the window
- *
- * required value bool Enable/disable hooking.
- */
-/datum/tgui/proc/set_mouse_hook(value)
- src.mouse_hooked = value
- //Handle unhooking/hooking on already open windows ?
-
/**
* public
*
@@ -422,6 +427,18 @@
log_tgui(user, "Fallback Triggered: [href_list["payload"]], Window: [window.id], Source: [src_object]")
#endif
src_object.tgui_fallback(payload)
+ if(TGUI_MANAGED_BYONDUI_TYPE_RENDER)
+ var/byond_ui_id = payload[TGUI_MANAGED_BYONDUI_PAYLOAD_ID]
+ if(!byond_ui_id || LAZYLEN(open_byondui_elements) > TGUI_MANAGED_BYONDUI_LIMIT)
+ return
+
+ LAZYOR(open_byondui_elements, byond_ui_id)
+ if(TGUI_MANAGED_BYONDUI_TYPE_UNMOUNT)
+ var/byond_ui_id = payload[TGUI_MANAGED_BYONDUI_PAYLOAD_ID]
+ if(!byond_ui_id)
+ return
+
+ LAZYREMOVE(open_byondui_elements, byond_ui_id)
/// Wrapper for behavior to potentially wait until the next tick if the server is overloaded
/datum/tgui/proc/on_act_message(act_type, payload, state)
diff --git a/code/modules/tgui/tgui_window.dm b/code/modules/tgui/tgui_window.dm
index 06ebd09478..38675b150d 100644
--- a/code/modules/tgui/tgui_window.dm
+++ b/code/modules/tgui/tgui_window.dm
@@ -27,19 +27,6 @@
var/initial_inline_css
var/list/oversized_payloads = list()
- var/mouse_event_macro_set = FALSE
-
- /**
- * Static list used to map in macros that will then emit execute events to the tgui window
- * A small disclaimer though I'm no tech wiz: I don't think it's possible to map in right or middle
- * clicks in the current state, as they're keywords rather than modifiers.
- */
- var/static/list/byondToTguiEventMap = list(
- "MouseDown" = "byond/mousedown",
- "MouseUp" = "byond/mouseup",
- "Ctrl" = "byond/ctrldown",
- "Ctrl+UP" = "byond/ctrlup",
- )
/**
* public
@@ -235,8 +222,6 @@
/datum/tgui_window/proc/close(can_be_suspended = TRUE)
if(!client)
return
- if(mouse_event_macro_set)
- remove_mouse_macro()
if(can_be_suspended && can_be_suspended())
#ifdef TGUI_DEBUGGING
log_tgui(client, "[id]/close: suspending")
@@ -441,32 +426,3 @@
/datum/tgui_window/proc/remove_oversized_payload(payload_id)
oversized_payloads -= payload_id
-
-
-/datum/tgui_window/proc/set_mouse_macro()
- if(mouse_event_macro_set)
- return
-
- for(var/mouseMacro in byondToTguiEventMap)
- var/command_template = ".output CONTROL PAYLOAD"
- var/event_message = TGUI_CREATE_MESSAGE(byondToTguiEventMap[mouseMacro], null)
- var target_control = is_browser \
- ? "[id]:update" \
- : "[id].browser:update"
- var/with_id = replacetext(command_template, "CONTROL", target_control)
- var/full_command = replacetext(with_id, "PAYLOAD", event_message)
-
- var/list/params = list()
- params["parent"] = "default" //Technically this is external to tgui but whatever
- params["name"] = mouseMacro
- params["command"] = full_command
-
- winset(client, "[mouseMacro]Window[id]Macro", params)
- mouse_event_macro_set = TRUE
-
-/datum/tgui_window/proc/remove_mouse_macro()
- if(!mouse_event_macro_set)
- stack_trace("Unsetting mouse macro on tgui window that has none")
- for(var/mouseMacro in byondToTguiEventMap)
- winset(client, null, "[mouseMacro]Window[id]Macro.parent=null")
- mouse_event_macro_set = FALSE
diff --git a/tgui/packages/tgui-bench/package.json b/tgui/packages/tgui-bench/package.json
index 674ba315bb..71d1b8a09b 100644
--- a/tgui/packages/tgui-bench/package.json
+++ b/tgui/packages/tgui-bench/package.json
@@ -11,7 +11,7 @@
"react": "^19.1.0",
"react-dom": "^19.1.0",
"tgui": "workspace:*",
- "tgui-core": "^4.0.1"
+ "tgui-core": "^4.0.2"
},
"devDependencies": {
"@types/react": "^19.1.0",
diff --git a/tgui/packages/tgui-panel/package.json b/tgui/packages/tgui-panel/package.json
index 15b171b3d7..c78d06f6da 100644
--- a/tgui/packages/tgui-panel/package.json
+++ b/tgui/packages/tgui-panel/package.json
@@ -8,7 +8,7 @@
"react": "^19.1.0",
"react-dom": "^19.1.0",
"tgui": "workspace:*",
- "tgui-core": "^4.0.1",
+ "tgui-core": "^4.0.2",
"tgui-dev-server": "workspace:*"
},
"devDependencies": {
diff --git a/tgui/packages/tgui-say/package.json b/tgui/packages/tgui-say/package.json
index bb1cb416e4..ea06a4ef03 100644
--- a/tgui/packages/tgui-say/package.json
+++ b/tgui/packages/tgui-say/package.json
@@ -7,7 +7,7 @@
"react": "^19.1.0",
"react-dom": "^19.1.0",
"tgui": "workspace:*",
- "tgui-core": "^4.0.1"
+ "tgui-core": "^4.0.2"
},
"devDependencies": {
"@types/react": "^19.1.0",
diff --git a/tgui/packages/tgui/backend.ts b/tgui/packages/tgui/backend.ts
index 09a8a4c49d..a18bbe4156 100644
--- a/tgui/packages/tgui/backend.ts
+++ b/tgui/packages/tgui/backend.ts
@@ -13,7 +13,6 @@
import { perf } from 'common/perf';
import { createAction } from 'common/redux';
-import { globalEvents } from 'tgui-core/events';
import type { BooleanLike } from 'tgui-core/react';
import { setupDrag } from './drag';
@@ -97,14 +96,6 @@ export const backendReducer = (state = initialState, action) => {
};
}
- if (type === 'byond/ctrldown') {
- globalEvents.emit('byond/ctrldown');
- }
-
- if (type === 'byond/ctrlup') {
- globalEvents.emit('byond/ctrlup');
- }
-
if (type === 'backend/suspendStart') {
return {
...state,
@@ -154,22 +145,6 @@ export const backendMiddleware = (store) => {
return;
}
- if (type === 'byond/mousedown') {
- globalEvents.emit('byond/mousedown');
- }
-
- if (type === 'byond/mouseup') {
- globalEvents.emit('byond/mouseup');
- }
-
- if (type === 'byond/ctrldown') {
- globalEvents.emit('byond/ctrldown');
- }
-
- if (type === 'byond/ctrlup') {
- globalEvents.emit('byond/ctrlup');
- }
-
if (type === 'backend/suspendStart' && !suspendInterval) {
logger.log(`suspending (${Byond.windowId})`);
// Keep sending suspend messages until it succeeds.
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/bay_prefs/general/SubtabBody.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/bay_prefs/general/SubtabBody.tsx
index a94ba59f61..f91020fcd0 100644
--- a/tgui/packages/tgui/interfaces/PreferencesMenu/bay_prefs/general/SubtabBody.tsx
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/bay_prefs/general/SubtabBody.tsx
@@ -121,17 +121,15 @@ export const SubtabBody = (props: {
) : null}
- {
-
-
-
- }
+
+
+