@wailsio/runtime 3.0.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/application.js +46 -0
- package/browser.js +24 -0
- package/calls.js +123 -0
- package/clipboard.js +35 -0
- package/contextmenu.js +96 -0
- package/dialogs.js +138 -0
- package/drag.js +125 -0
- package/events.js +134 -0
- package/flags.js +63 -0
- package/index.js +56 -0
- package/package.json +17 -0
- package/runtime.js +122 -0
- package/screens.js +45 -0
- package/system.js +118 -0
- package/types.d.ts +130 -0
- package/window.js +122 -0
- package/wml.js +148 -0
package/application.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ __ _ __
|
|
3
|
+
| | / /___ _(_) /____
|
|
4
|
+
| | /| / / __ `/ / / ___/
|
|
5
|
+
| |/ |/ / /_/ / / (__ )
|
|
6
|
+
|__/|__/\__,_/_/_/____/
|
|
7
|
+
The electron alternative for Go
|
|
8
|
+
(c) Lea Anthony 2019-present
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/* jshint esversion: 9 */
|
|
12
|
+
|
|
13
|
+
import { newRuntimeCallerWithID, objectNames } from "./runtime";
|
|
14
|
+
const call = newRuntimeCallerWithID(objectNames.Application);
|
|
15
|
+
|
|
16
|
+
const HideMethod = 0;
|
|
17
|
+
const ShowMethod = 1;
|
|
18
|
+
const QuitMethod = 2;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Hides a certain method by calling the HideMethod function.
|
|
22
|
+
*
|
|
23
|
+
* @return {Promise<void>}
|
|
24
|
+
*
|
|
25
|
+
*/
|
|
26
|
+
export function Hide() {
|
|
27
|
+
return call(HideMethod);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Calls the ShowMethod and returns the result.
|
|
32
|
+
*
|
|
33
|
+
* @return {Promise<void>}
|
|
34
|
+
*/
|
|
35
|
+
export function Show() {
|
|
36
|
+
return call(ShowMethod);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Calls the QuitMethod to terminate the program.
|
|
41
|
+
*
|
|
42
|
+
* @return {Promise<void>}
|
|
43
|
+
*/
|
|
44
|
+
export function Quit() {
|
|
45
|
+
return call(QuitMethod);
|
|
46
|
+
}
|
package/browser.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ __ _ __
|
|
3
|
+
| | / /___ _(_) /____
|
|
4
|
+
| | /| / / __ `/ / / ___/
|
|
5
|
+
| |/ |/ / /_/ / / (__ )
|
|
6
|
+
|__/|__/\__,_/_/_/____/
|
|
7
|
+
The electron alternative for Go
|
|
8
|
+
(c) Lea Anthony 2019-present
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/* jshint esversion: 9 */
|
|
12
|
+
import {newRuntimeCallerWithID, objectNames} from "./runtime";
|
|
13
|
+
|
|
14
|
+
const call = newRuntimeCallerWithID(objectNames.Browser, '');
|
|
15
|
+
const BrowserOpenURL = 0;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Open a browser window to the given URL
|
|
19
|
+
* @param {string} url - The URL to open
|
|
20
|
+
* @returns {Promise<string>}
|
|
21
|
+
*/
|
|
22
|
+
export function OpenURL(url) {
|
|
23
|
+
return call(BrowserOpenURL, {url});
|
|
24
|
+
}
|
package/calls.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ __ _ __
|
|
3
|
+
| | / /___ _(_) /____
|
|
4
|
+
| | /| / / __ `/ / / ___/
|
|
5
|
+
| |/ |/ / /_/ / / (__ )
|
|
6
|
+
|__/|__/\__,_/_/_/____/
|
|
7
|
+
The electron alternative for Go
|
|
8
|
+
(c) Lea Anthony 2019-present
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/* jshint esversion: 9 */
|
|
12
|
+
import { newRuntimeCallerWithID, objectNames } from "./runtime";
|
|
13
|
+
import { nanoid } from 'nanoid/non-secure';
|
|
14
|
+
|
|
15
|
+
const CallBinding = 0;
|
|
16
|
+
const call = newRuntimeCallerWithID(objectNames.Call, '');
|
|
17
|
+
let callResponses = new Map();
|
|
18
|
+
|
|
19
|
+
window._wails = window._wails || {};
|
|
20
|
+
window._wails.callCallback = resultHandler;
|
|
21
|
+
window._wails.callErrorCallback = errorHandler;
|
|
22
|
+
|
|
23
|
+
function generateID() {
|
|
24
|
+
let result;
|
|
25
|
+
do {
|
|
26
|
+
result = nanoid();
|
|
27
|
+
} while (callResponses.has(result));
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function resultHandler(id, data, isJSON) {
|
|
32
|
+
const promiseHandler = getAndDeleteResponse(id);
|
|
33
|
+
if (promiseHandler) {
|
|
34
|
+
promiseHandler.resolve(isJSON ? JSON.parse(data) : data);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function errorHandler(id, message) {
|
|
39
|
+
const promiseHandler = getAndDeleteResponse(id);
|
|
40
|
+
if (promiseHandler) {
|
|
41
|
+
promiseHandler.reject(message);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function getAndDeleteResponse(id) {
|
|
46
|
+
const response = callResponses.get(id);
|
|
47
|
+
callResponses.delete(id);
|
|
48
|
+
return response;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function callBinding(type, options = {}) {
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
const id = generateID();
|
|
54
|
+
options["call-id"] = id;
|
|
55
|
+
callResponses.set(id, { resolve, reject });
|
|
56
|
+
call(type, options).catch((error) => {
|
|
57
|
+
reject(error);
|
|
58
|
+
callResponses.delete(id);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Call method.
|
|
65
|
+
*
|
|
66
|
+
* @param {Object} options - The options for the method.
|
|
67
|
+
* @returns {Object} - The result of the call.
|
|
68
|
+
*/
|
|
69
|
+
export function Call(options) {
|
|
70
|
+
return callBinding(CallBinding, options);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Executes a method by name.
|
|
75
|
+
*
|
|
76
|
+
* @param {string} name - The name of the method in the format 'package.struct.method'.
|
|
77
|
+
* @param {...*} args - The arguments to pass to the method.
|
|
78
|
+
* @throws {Error} If the name is not a string or is not in the correct format.
|
|
79
|
+
* @returns {*} The result of the method execution.
|
|
80
|
+
*/
|
|
81
|
+
export function ByName(name, ...args) {
|
|
82
|
+
if (typeof name !== "string" || name.split(".").length !== 3) {
|
|
83
|
+
throw new Error("CallByName requires a string in the format 'package.struct.method'");
|
|
84
|
+
}
|
|
85
|
+
let [packageName, structName, methodName] = name.split(".");
|
|
86
|
+
return callBinding(CallBinding, {
|
|
87
|
+
packageName,
|
|
88
|
+
structName,
|
|
89
|
+
methodName,
|
|
90
|
+
args
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Calls a method by its ID with the specified arguments.
|
|
96
|
+
*
|
|
97
|
+
* @param {string} methodID - The ID of the method to call.
|
|
98
|
+
* @param {...*} args - The arguments to pass to the method.
|
|
99
|
+
* @return {*} - The result of the method call.
|
|
100
|
+
*/
|
|
101
|
+
export function ByID(methodID, ...args) {
|
|
102
|
+
return callBinding(CallBinding, {
|
|
103
|
+
methodID,
|
|
104
|
+
args
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Calls a method on a plugin.
|
|
110
|
+
*
|
|
111
|
+
* @param {string} pluginName - The name of the plugin.
|
|
112
|
+
* @param {string} methodName - The name of the method to call.
|
|
113
|
+
* @param {...*} args - The arguments to pass to the method.
|
|
114
|
+
* @returns {*} - The result of the method call.
|
|
115
|
+
*/
|
|
116
|
+
export function Plugin(pluginName, methodName, ...args) {
|
|
117
|
+
return callBinding(CallBinding, {
|
|
118
|
+
packageName: "wails-plugins",
|
|
119
|
+
structName: pluginName,
|
|
120
|
+
methodName,
|
|
121
|
+
args
|
|
122
|
+
});
|
|
123
|
+
}
|
package/clipboard.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ __ _ __
|
|
3
|
+
| | / /___ _(_) /____
|
|
4
|
+
| | /| / / __ `/ / / ___/
|
|
5
|
+
| |/ |/ / /_/ / / (__ )
|
|
6
|
+
|__/|__/\__,_/_/_/____/
|
|
7
|
+
The electron alternative for Go
|
|
8
|
+
(c) Lea Anthony 2019-present
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/* jshint esversion: 9 */
|
|
12
|
+
|
|
13
|
+
import {newRuntimeCallerWithID, objectNames} from "./runtime";
|
|
14
|
+
|
|
15
|
+
const call = newRuntimeCallerWithID(objectNames.Clipboard, '');
|
|
16
|
+
const ClipboardSetText = 0;
|
|
17
|
+
const ClipboardText = 1;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Sets the text to the Clipboard.
|
|
21
|
+
*
|
|
22
|
+
* @param {string} text - The text to be set to the Clipboard.
|
|
23
|
+
* @return {Promise} - A Promise that resolves when the operation is successful.
|
|
24
|
+
*/
|
|
25
|
+
export function SetText(text) {
|
|
26
|
+
return call(ClipboardSetText, {text});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get the Clipboard text
|
|
31
|
+
* @returns {Promise<string>} A promise that resolves with the text from the Clipboard.
|
|
32
|
+
*/
|
|
33
|
+
export function Text() {
|
|
34
|
+
return call(ClipboardText);
|
|
35
|
+
}
|
package/contextmenu.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ __ _ __
|
|
3
|
+
| | / /___ _(_) /____
|
|
4
|
+
| | /| / / __ `/ / / ___/
|
|
5
|
+
| |/ |/ / /_/ / / (__ )
|
|
6
|
+
|__/|__/\__,_/_/_/____/
|
|
7
|
+
The electron alternative for Go
|
|
8
|
+
(c) Lea Anthony 2019-present
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/* jshint esversion: 9 */
|
|
12
|
+
|
|
13
|
+
import {newRuntimeCallerWithID, objectNames} from "./runtime";
|
|
14
|
+
|
|
15
|
+
const call = newRuntimeCallerWithID(objectNames.ContextMenu, '');
|
|
16
|
+
const ContextMenuOpen = 0;
|
|
17
|
+
|
|
18
|
+
function openContextMenu(id, x, y, data) {
|
|
19
|
+
void call(ContextMenuOpen, {id, x, y, data});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function setupContextMenus() {
|
|
23
|
+
window.addEventListener('contextmenu', contextMenuHandler);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function contextMenuHandler(event) {
|
|
27
|
+
// Check for custom context menu
|
|
28
|
+
let element = event.target;
|
|
29
|
+
let customContextMenu = window.getComputedStyle(element).getPropertyValue("--custom-contextmenu");
|
|
30
|
+
customContextMenu = customContextMenu ? customContextMenu.trim() : "";
|
|
31
|
+
if (customContextMenu) {
|
|
32
|
+
event.preventDefault();
|
|
33
|
+
let customContextMenuData = window.getComputedStyle(element).getPropertyValue("--custom-contextmenu-data");
|
|
34
|
+
openContextMenu(customContextMenu, event.clientX, event.clientY, customContextMenuData);
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
processDefaultContextMenu(event);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
/*
|
|
43
|
+
--default-contextmenu: auto; (default) will show the default context menu if contentEditable is true OR text has been selected OR element is input or textarea
|
|
44
|
+
--default-contextmenu: show; will always show the default context menu
|
|
45
|
+
--default-contextmenu: hide; will always hide the default context menu
|
|
46
|
+
|
|
47
|
+
This rule is inherited like normal CSS rules, so nesting works as expected
|
|
48
|
+
*/
|
|
49
|
+
function processDefaultContextMenu(event) {
|
|
50
|
+
// Debug builds always show the menu
|
|
51
|
+
if (DEBUG) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Process default context menu
|
|
56
|
+
const element = event.target;
|
|
57
|
+
const computedStyle = window.getComputedStyle(element);
|
|
58
|
+
const defaultContextMenuAction = computedStyle.getPropertyValue("--default-contextmenu").trim();
|
|
59
|
+
switch (defaultContextMenuAction) {
|
|
60
|
+
case "show":
|
|
61
|
+
return;
|
|
62
|
+
case "hide":
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
return;
|
|
65
|
+
default:
|
|
66
|
+
// Check if contentEditable is true
|
|
67
|
+
if (element.isContentEditable) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Check if text has been selected
|
|
72
|
+
const selection = window.getSelection();
|
|
73
|
+
const hasSelection = (selection.toString().length > 0)
|
|
74
|
+
if (hasSelection) {
|
|
75
|
+
for (let i = 0; i < selection.rangeCount; i++) {
|
|
76
|
+
const range = selection.getRangeAt(i);
|
|
77
|
+
const rects = range.getClientRects();
|
|
78
|
+
for (let j = 0; j < rects.length; j++) {
|
|
79
|
+
const rect = rects[j];
|
|
80
|
+
if (document.elementFromPoint(rect.left, rect.top) === element) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Check if tagname is input or textarea
|
|
87
|
+
if (element.tagName === "INPUT" || element.tagName === "TEXTAREA") {
|
|
88
|
+
if (hasSelection || (!element.readOnly && !element.disabled)) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// hide default context menu
|
|
94
|
+
event.preventDefault();
|
|
95
|
+
}
|
|
96
|
+
}
|
package/dialogs.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ __ _ __
|
|
3
|
+
| | / /___ _(_) /____
|
|
4
|
+
| | /| / / __ `/ / / ___/
|
|
5
|
+
| |/ |/ / /_/ / / (__ )
|
|
6
|
+
|__/|__/\__,_/_/_/____/
|
|
7
|
+
The electron alternative for Go
|
|
8
|
+
(c) Lea Anthony 2019-present
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/* jshint esversion: 9 */
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {import("./types").MessageDialogOptions} MessageDialogOptions
|
|
15
|
+
* @typedef {import("./types").OpenDialogOptions} OpenDialogOptions
|
|
16
|
+
* @typedef {import("./types").SaveDialogOptions} SaveDialogOptions
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import {newRuntimeCallerWithID, objectNames} from "./runtime";
|
|
20
|
+
|
|
21
|
+
import { nanoid } from 'nanoid/non-secure';
|
|
22
|
+
|
|
23
|
+
// Define constants from the `methods` object in Title Case
|
|
24
|
+
const DialogInfo = 0;
|
|
25
|
+
const DialogWarning = 1;
|
|
26
|
+
const DialogError = 2;
|
|
27
|
+
const DialogQuestion = 3;
|
|
28
|
+
const DialogOpenFile = 4;
|
|
29
|
+
const DialogSaveFile = 5;
|
|
30
|
+
|
|
31
|
+
const call = newRuntimeCallerWithID(objectNames.Dialog, '');
|
|
32
|
+
const dialogResponses = new Map();
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Generates a unique id that is not present in dialogResponses.
|
|
36
|
+
* @returns {string} unique id
|
|
37
|
+
*/
|
|
38
|
+
function generateID() {
|
|
39
|
+
let result;
|
|
40
|
+
do {
|
|
41
|
+
result = nanoid();
|
|
42
|
+
} while (dialogResponses.has(result));
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Shows a dialog of specified type with the given options.
|
|
48
|
+
* @param {number} type - type of dialog
|
|
49
|
+
* @param {object} options - options for the dialog
|
|
50
|
+
* @returns {Promise} promise that resolves with result of dialog
|
|
51
|
+
*/
|
|
52
|
+
function dialog(type, options = {}) {
|
|
53
|
+
const id = generateID();
|
|
54
|
+
options["dialog-id"] = id;
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
dialogResponses.set(id, {resolve, reject});
|
|
57
|
+
call(type, options).catch((error) => {
|
|
58
|
+
reject(error);
|
|
59
|
+
dialogResponses.delete(id);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Handles the callback from a dialog.
|
|
66
|
+
*
|
|
67
|
+
* @param {string} id - The ID of the dialog response.
|
|
68
|
+
* @param {string} data - The data received from the dialog.
|
|
69
|
+
* @param {boolean} isJSON - Flag indicating whether the data is in JSON format.
|
|
70
|
+
*
|
|
71
|
+
* @return {undefined}
|
|
72
|
+
*/
|
|
73
|
+
export function dialogCallback(id, data, isJSON) {
|
|
74
|
+
let p = dialogResponses.get(id);
|
|
75
|
+
if (p) {
|
|
76
|
+
if (isJSON) {
|
|
77
|
+
p.resolve(JSON.parse(data));
|
|
78
|
+
} else {
|
|
79
|
+
p.resolve(data);
|
|
80
|
+
}
|
|
81
|
+
dialogResponses.delete(id);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Callback function for handling errors in dialog.
|
|
87
|
+
*
|
|
88
|
+
* @param {string} id - The id of the dialog response.
|
|
89
|
+
* @param {string} message - The error message.
|
|
90
|
+
*
|
|
91
|
+
* @return {void}
|
|
92
|
+
*/
|
|
93
|
+
export function dialogErrorCallback(id, message) {
|
|
94
|
+
let p = dialogResponses.get(id);
|
|
95
|
+
if (p) {
|
|
96
|
+
p.reject(message);
|
|
97
|
+
dialogResponses.delete(id);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
// Replace `methods` with constants in Title Case
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @param {MessageDialogOptions} options - Dialog options
|
|
106
|
+
* @returns {Promise<string>} - The label of the button pressed
|
|
107
|
+
*/
|
|
108
|
+
export const Info = (options) => dialog(DialogInfo, options);
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @param {MessageDialogOptions} options - Dialog options
|
|
112
|
+
* @returns {Promise<string>} - The label of the button pressed
|
|
113
|
+
*/
|
|
114
|
+
export const Warning = (options) => dialog(DialogWarning, options);
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @param {MessageDialogOptions} options - Dialog options
|
|
118
|
+
* @returns {Promise<string>} - The label of the button pressed
|
|
119
|
+
*/
|
|
120
|
+
export const Error = (options) => dialog(DialogError, options);
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @param {MessageDialogOptions} options - Dialog options
|
|
124
|
+
* @returns {Promise<string>} - The label of the button pressed
|
|
125
|
+
*/
|
|
126
|
+
export const Question = (options) => dialog(DialogQuestion, options);
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @param {OpenDialogOptions} options - Dialog options
|
|
130
|
+
* @returns {Promise<string[]|string>} Returns selected file or list of files. Returns blank string if no file is selected.
|
|
131
|
+
*/
|
|
132
|
+
export const OpenFile = (options) => dialog(DialogOpenFile, options);
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* @param {SaveDialogOptions} options - Dialog options
|
|
136
|
+
* @returns {Promise<string>} Returns the selected file. Returns blank string if no file is selected.
|
|
137
|
+
*/
|
|
138
|
+
export const SaveFile = (options) => dialog(DialogSaveFile, options);
|
package/drag.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ __ _ __
|
|
3
|
+
| | / /___ _(_) /____
|
|
4
|
+
| | /| / / __ `/ / / ___/
|
|
5
|
+
| |/ |/ / /_/ / / (__ )
|
|
6
|
+
|__/|__/\__,_/_/_/____/
|
|
7
|
+
The electron alternative for Go
|
|
8
|
+
(c) Lea Anthony 2019-present
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/* jshint esversion: 9 */
|
|
12
|
+
|
|
13
|
+
import {invoke, IsWindows} from "./system";
|
|
14
|
+
import {GetFlag} from "./flags";
|
|
15
|
+
|
|
16
|
+
let shouldDrag = false;
|
|
17
|
+
let resizeEdge = null;
|
|
18
|
+
let resizable = false;
|
|
19
|
+
let defaultCursor = "auto";
|
|
20
|
+
window._wails = window._wails || {};
|
|
21
|
+
window._wails.setResizable = setResizable;
|
|
22
|
+
window._wails.endDrag = endDrag;
|
|
23
|
+
|
|
24
|
+
export function dragTest(e) {
|
|
25
|
+
let val = window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");
|
|
26
|
+
if (val && val.trim() !== "drag" || e.buttons !== 1) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
return e.detail === 1;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function setupDrag() {
|
|
33
|
+
window.addEventListener('mousedown', onMouseDown);
|
|
34
|
+
window.addEventListener('mousemove', onMouseMove);
|
|
35
|
+
window.addEventListener('mouseup', onMouseUp);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function setResizable(value) {
|
|
39
|
+
resizable = value;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function endDrag() {
|
|
43
|
+
document.body.style.cursor = 'default';
|
|
44
|
+
shouldDrag = false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function testResize() {
|
|
48
|
+
if( resizeEdge ) {
|
|
49
|
+
invoke(`resize:${resizeEdge}`);
|
|
50
|
+
return true
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function onMouseDown(e) {
|
|
56
|
+
if(IsWindows() && testResize() || dragTest(e)) {
|
|
57
|
+
shouldDrag = !!isValidDrag(e);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function isValidDrag(e) {
|
|
62
|
+
// Ignore drag on scrollbars
|
|
63
|
+
return !(e.offsetX > e.target.clientWidth || e.offsetY > e.target.clientHeight);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function onMouseUp(e) {
|
|
67
|
+
let mousePressed = e.buttons !== undefined ? e.buttons : e.which;
|
|
68
|
+
if (mousePressed > 0) {
|
|
69
|
+
endDrag();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function setResize(cursor = defaultCursor) {
|
|
74
|
+
document.documentElement.style.cursor = cursor;
|
|
75
|
+
resizeEdge = cursor;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function onMouseMove(e) {
|
|
79
|
+
shouldDrag = checkDrag(e);
|
|
80
|
+
if (IsWindows() && resizable) {
|
|
81
|
+
handleResize(e);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function checkDrag(e) {
|
|
86
|
+
let mousePressed = e.buttons !== undefined ? e.buttons : e.which;
|
|
87
|
+
if(shouldDrag && mousePressed > 0) {
|
|
88
|
+
invoke("drag");
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
return shouldDrag;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function handleResize(e) {
|
|
95
|
+
let resizeHandleHeight = GetFlag("system.resizeHandleHeight") || 5;
|
|
96
|
+
let resizeHandleWidth = GetFlag("system.resizeHandleWidth") || 5;
|
|
97
|
+
|
|
98
|
+
// Extra pixels for the corner areas
|
|
99
|
+
let cornerExtra = GetFlag("resizeCornerExtra") || 10;
|
|
100
|
+
|
|
101
|
+
let rightBorder = window.outerWidth - e.clientX < resizeHandleWidth;
|
|
102
|
+
let leftBorder = e.clientX < resizeHandleWidth;
|
|
103
|
+
let topBorder = e.clientY < resizeHandleHeight;
|
|
104
|
+
let bottomBorder = window.outerHeight - e.clientY < resizeHandleHeight;
|
|
105
|
+
|
|
106
|
+
// Adjust for corners
|
|
107
|
+
let rightCorner = window.outerWidth - e.clientX < (resizeHandleWidth + cornerExtra);
|
|
108
|
+
let leftCorner = e.clientX < (resizeHandleWidth + cornerExtra);
|
|
109
|
+
let topCorner = e.clientY < (resizeHandleHeight + cornerExtra);
|
|
110
|
+
let bottomCorner = window.outerHeight - e.clientY < (resizeHandleHeight + cornerExtra);
|
|
111
|
+
|
|
112
|
+
// If we aren't on an edge, but were, reset the cursor to default
|
|
113
|
+
if (!leftBorder && !rightBorder && !topBorder && !bottomBorder && resizeEdge !== undefined) {
|
|
114
|
+
setResize();
|
|
115
|
+
}
|
|
116
|
+
// Adjusted for corner areas
|
|
117
|
+
else if (rightCorner && bottomCorner) setResize("se-resize");
|
|
118
|
+
else if (leftCorner && bottomCorner) setResize("sw-resize");
|
|
119
|
+
else if (leftCorner && topCorner) setResize("nw-resize");
|
|
120
|
+
else if (topCorner && rightCorner) setResize("ne-resize");
|
|
121
|
+
else if (leftBorder) setResize("w-resize");
|
|
122
|
+
else if (topBorder) setResize("n-resize");
|
|
123
|
+
else if (bottomBorder) setResize("s-resize");
|
|
124
|
+
else if (rightBorder) setResize("e-resize");
|
|
125
|
+
}
|