-
-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy pathwindow-tiler.gd
132 lines (96 loc) · 3.64 KB
/
window-tiler.gd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
extends Node
# Settings
var _is_enabled: bool = ProjectSettings.get_setting(&"netfox/extras/auto_tile_windows", false)
var _is_borderless: bool = ProjectSettings.get_setting(&"netfox/extras/borderless", false)
var _tile_screen: int = ProjectSettings.get_setting(&"netfox/extras/screen", 0)
# Hash the game name, so we always get a valid filename
var _prefix: String = "netfox-window-tiler-%x" % [ProjectSettings.get_setting(&"application/config/name").hash()]
var _sid: String = "%x" % [hash(int(Time.get_unix_time_from_system() / 2.))]
var _uid: String = "%d" % [Time.get_unix_time_from_system() * 1000_0000.]
static var _logger: _NetfoxLogger = _NetfoxLogger.for_extras("WindowTiler")
func _ready() -> void:
# Running on a non-editor (export template) build
if OS.has_feature("template"):
return
# Running in headless mode
if DisplayServer.get_name() == "headless":
return
# Cleanup in case some files were left
_cleanup()
# Running embedded in editor
if _is_embedded():
return
# Don't tile if disabled
if not _is_enabled:
return
_logger.debug("Tiling with sid: %s, uid: %s", [_sid, _uid])
var err = _make_lock(_sid, _uid)
if err != Error.OK:
_logger.warning("Failed to create lock for tiling, reason: %s", [error_string(err)])
return
# Search for locks, stop once no new locks are found
var locks = []
await get_tree().create_timer(0.25).timeout
for i in range(20):
await get_tree().create_timer(0.1).timeout
var new_locks = _list_lock_ids()
if locks == new_locks:
break
locks = new_locks
var tile_count = locks.size()
var idx = locks.find(_uid)
_logger.debug("Tiling as idx %d / %d - %s in %s", [idx, tile_count, _uid, locks])
_tile_window(idx, tile_count)
func _is_embedded() -> bool:
if Engine.has_method("is_embedded_in_editor"):
return Engine.call("is_embedded_in_editor")
return false
func _make_lock(sid: String, uid: String) -> Error:
var path = "%s/%s-%s-%s" % [OS.get_cache_dir(), _prefix, sid, uid]
var file := FileAccess.open(path, FileAccess.WRITE)
if file == null:
return FileAccess.get_open_error()
file.close()
return Error.OK
func _list_lock_ids() -> Array[String]:
var result: Array[String] = []
var dir := DirAccess.open(OS.get_cache_dir())
if dir:
for f in dir.get_files():
if f.begins_with(_prefix):
result.append(_get_uid(f))
return result
func _cleanup():
var result: Array[String] = []
var dir := DirAccess.open(OS.get_cache_dir())
if dir:
for f in dir.get_files():
if f.begins_with(_prefix) and _get_sid(f) != _sid:
_logger.trace("Cleaned up lock: %s", [f])
dir.remove(OS.get_cache_dir() + "/" + f)
func _get_sid(filename: String) -> String:
return filename.substr(_prefix.length() + 1).get_slice("-", 0)
func _get_uid(filename: String) -> String:
return filename.substr(_prefix.length() + 1).get_slice("-", 1)
func _tile_window(i: int, total: int) -> void:
var screen = _tile_screen
var screen_rect = DisplayServer.screen_get_usable_rect(screen)
var window: Window = get_tree().get_root()
window.set_current_screen(screen)
if total == 1:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_MAXIMIZED)
return
window.borderless = _is_borderless
# Divide up the screen
var windows_per_row = int(ceil(sqrt(total)))
var windows_per_col = int(ceil(total / float(windows_per_row)))
var window_size = Vector2(
screen_rect.size.x / windows_per_row, screen_rect.size.y / windows_per_col
)
window.set_size(window_size)
# Position of the window based on index.
var row = i / windows_per_row
var col = i % windows_per_row
var x = screen_rect.position.x + col * window_size.x
var y = screen_rect.position.y + row * window_size.y
window.set_position(Vector2(x, y))