Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
231 changes: 231 additions & 0 deletions extensions/community/SystemTrayManager.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
{
"author": "",
"category": "General",
"extensionNamespace": "",
"fullName": "System tray manager",
"gdevelopVersion": "",
"helpPath": "",
"iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0ibWRpLXRyYXktcGx1cyIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxwYXRoIGQ9Ik0yIDEySDRWMTdIMjBWMTJIMjJWMTdBMiAyIDAgMCAxIDIwIDE5SDRBMiAyIDAgMCAxIDIgMTdNMTEgNUgxM1Y4SDE2VjEwSDEzVjEzSDExVjEwSDhWOEgxMVoiIC8+PC9zdmc+",
"name": "SystemTrayManager",
"previewIconUrl": "https://asset-resources.gdevelop.io/public-resources/Icons/a2f86a77b5aa948a7d2b990e87f635cb29c56144c48942c2ea4f17483d61effc_tray-plus.svg",
"shortDescription": "Minimize your app to the Windows system tray, automatically giving it the app icon, and with the ablility to customize the cursor-hovering text and right-click options.",
"version": "1.0.0",
"description": [
"Send your app to the system tray when initializing the icon inside your project. This can be useful for things like:",
"- Creating a launcher that has to do processes in the background.",
"- Creating a tray icon for your app to replace the big icon on the taskbar when minimized, to simulate experiences like \"desktop pets\".",
"- Literally anything you ever dreamed of creating a tray icon for.",
"",
"It currently supports a \"Show label\" with customizable text, and \"Quit\" label with customizable text, and a fully custom third label, used for passing your own string into a scene variable called \"TrayAction\". Then, use that variable to trigger any events in your project."
],
"tags": [],
"authorIds": [],
"dependencies": [],
"globalVariables": [],
"sceneVariables": [],
"eventsFunctions": [
{
"description": "Initializes the system tray icon for the application. Use this event one time, from the moment you want the ability for your app to be minimized to the small system tray icon. For example, as the very first event of the very first scene.",
"fullName": "Initialize system tray",
"functionType": "Action",
"name": "InitializeSystemTray",
"sentence": "Initialize system tray, with the Tooltip Text _PARAM1_, Show Label _PARAM2_, Quit Label _PARAM3_, and if filled, Custom Label _PARAM4_ and Custom Value _PARAM5_",
"events": [
{
"type": "BuiltinCommonInstructions::JsCode",
"inlineCode": [
"if (typeof require === 'undefined') return;",
"",
"if (gdjs._systemTrayInitialized) return;",
"",
"const runtimeGame = runtimeScene.getGame();",
"",
"const renderer = runtimeGame.getRenderer();",
"",
"let electron = null;",
"",
"let remote = null;",
"",
"try {",
"",
" electron = renderer.getElectron ? renderer.getElectron() : null;",
"",
" remote = renderer.getElectronRemote ? renderer.getElectronRemote() : null;",
"",
" if (!electron || !remote) {",
"",
" const e = require('electron');",
"",
" electron = e;",
"",
" remote = e.remote || (e.require ? e.require('@electron/remote') : null);",
"",
" }",
"",
"} catch (e) { return; }",
"",
"if (!electron || !remote) return;",
"",
"const { Tray, Menu, app, nativeImage } = remote;",
"",
"const currentWindow = remote.getCurrentWindow();",
"",
"const tooltipText = eventsFunctionContext.getArgument(\"TooltipText\") || \"App is running\";",
"",
"const showLabel = eventsFunctionContext.getArgument(\"ShowLabel\") || \"Show\";",
"",
"const quitLabel = eventsFunctionContext.getArgument(\"QuitLabel\") || \"Quit\";",
"",
"const customLabel = eventsFunctionContext.getArgument(\"CustomLabel\") || \"\";",
"",
"const customValue = eventsFunctionContext.getArgument(\"CustomValue\") || \"\";",
"",
"const initializeTray = async () => {",
"",
" try {",
"",
" const exePath = app.getPath('exe');",
"",
" const icon = await app.getFileIcon(exePath, { size: 'small' });",
"",
" gdjs._systemTrayIcon = new Tray(icon);",
"",
" gdjs._systemTrayIcon.setToolTip(tooltipText);",
"",
" const menuTemplate = [",
"",
" { label: showLabel, click: () => { currentWindow.show(); currentWindow.focus(); } }",
"",
" ];",
"",
" if (customLabel && customLabel.trim() !== \"\") {",
"",
" menuTemplate.push({",
"",
" label: customLabel,",
"",
" click: () => {",
"",
" // Get the CURRENT active scene to ensure the variable is set where the logic is running",
"",
" const activeScene = runtimeGame.getSceneStack().getCurrentScene();",
"",
" if (activeScene) {",
"",
" const sceneVars = activeScene.getVariables();",
"",
" // Create the variable if it doesn't exist, then set the value",
"",
" sceneVars.get(\"TrayAction\").setString(customValue);",
"",
" }",
"",
" }",
"",
" });",
"",
" }",
"",
" menuTemplate.push({ type: 'separator' });",
"",
" menuTemplate.push({ ",
"",
" label: quitLabel, ",
"",
" click: () => {",
"",
" gdjs._systemTrayQuitting = true;",
"",
" gdjs._systemTrayIcon.destroy();",
"",
" app.quit(); ",
"",
" } ",
"",
" });",
"",
" gdjs._systemTrayIcon.setContextMenu(Menu.buildFromTemplate(menuTemplate));",
"",
" gdjs._systemTrayIcon.on('click', () => {",
"",
" currentWindow.isVisible() ? currentWindow.hide() : currentWindow.show();",
"",
" });",
"",
" currentWindow.on('minimize', (event) => {",
"",
" event.preventDefault();",
"",
" currentWindow.hide();",
"",
" });",
"",
" currentWindow.on('close', (event) => {",
"",
" if (!gdjs._systemTrayQuitting) {",
"",
" event.preventDefault();",
"",
" currentWindow.hide();",
"",
" }",
"",
" });",
"",
" gdjs._systemTrayInitialized = true;",
"",
" gdjs._systemTrayQuitting = false;",
"",
" } catch (err) { console.error(\"System Tray Error:\", err); }",
"",
"};",
"",
"initializeTray();"
],
"parameterObjects": "",
"useStrict": true,
"eventsSheetExpanded": false
}
],
"parameters": [
{
"description": "Tooltip Text",
"longDescription": "The text that shows upon hovering over the app's tray icon. By default, it's called \"My Game Name\", and you can change it however you want.",
"name": "TooltipText",
"supplementaryInformation": "[\"My Game Name\"]",
"type": "stringWithSelector"
},
{
"description": "Show Label",
"longDescription": "The label that restores the app window when clicked. By default, it's logically called \"Show\", but here's an option for you to change it however you want.",
"name": "ShowLabel",
"supplementaryInformation": "[\"Show\"]",
"type": "stringWithSelector"
},
{
"description": "Quit Label",
"longDescription": "The label that closes the app when clicked. By default, it's logically called \"Quit\", but here's an option for you to change it however you want.",
"name": "QuitLabel",
"supplementaryInformation": "[\"Quit\"]",
"type": "stringWithSelector"
},
{
"description": "Custom Label",
"longDescription": "A label that sends a string into a scene variable named \"TrayAction\" when clicked. By default, it's empty, and you don't have to use it if you don't want; in that case, just leave it like this.",
"name": "CustomLabel",
"supplementaryInformation": "[\"\"]",
"type": "string"
},
{
"description": "Custom Value",
"longDescription": "A custom string that gets sent into the \"TrayAction\" scene variable. Use it with the \"Custom Label\".",
"name": "CustomValue",
"type": "string"
}
],
"objectGroups": []
}
],
"eventsBasedBehaviors": [],
"eventsBasedObjects": []
}