gdharness 1.3.59 → 1.3.60

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.
@@ -40,6 +40,7 @@ const HEADINGS: int = PROPERTY_USAGE_CATEGORY | PROPERTY_USAGE_GROUP | PROPERTY_
40
40
  ## Control's layout_mode values, which the engine does not expose as constants.
41
41
  const LAYOUT_MODE_POSITION: int = 0
42
42
  const LAYOUT_MODE_ANCHORS: int = 1
43
+ const LAYOUT_MODE_UNCONTROLLED: int = 3
43
44
  ## What a container sets on each child it lays out, beside the anchors and offsets.
44
45
  const PLACED_BY_A_CONTAINER: Array[String] = ["position", "size", "global_position"]
45
46
 
@@ -366,8 +367,14 @@ func _laid_out(control: Control, name: String) -> String:
366
367
  )
367
368
  % [control.name, parent.name, parent.get_class(), base]
368
369
  )
369
- if anchoring and GdhRead.as_int(control.get("layout_mode")) == LAYOUT_MODE_POSITION:
370
+ var mode: int = GdhRead.as_int(control.get("layout_mode"))
371
+ if anchoring and mode == LAYOUT_MODE_POSITION:
370
372
  control.set("layout_mode", LAYOUT_MODE_ANCHORS)
373
+ # A scene's root reads as Uncontrolled but keeps the Position mode it was made with until it
374
+ # enters a tree, and the engine ignores a preset in that stored mode, so full rect read back as
375
+ # top left on every root a headless edit wrote.
376
+ elif anchoring and mode == LAYOUT_MODE_UNCONTROLLED:
377
+ control.set("layout_mode", LAYOUT_MODE_UNCONTROLLED)
371
378
  return ""
372
379
 
373
380
 
@@ -40,6 +40,7 @@ const HEADINGS: int = PROPERTY_USAGE_CATEGORY | PROPERTY_USAGE_GROUP | PROPERTY_
40
40
  ## Control's layout_mode values, which the engine does not expose as constants.
41
41
  const LAYOUT_MODE_POSITION: int = 0
42
42
  const LAYOUT_MODE_ANCHORS: int = 1
43
+ const LAYOUT_MODE_UNCONTROLLED: int = 3
43
44
  ## What a container sets on each child it lays out, beside the anchors and offsets.
44
45
  const PLACED_BY_A_CONTAINER: Array[String] = ["position", "size", "global_position"]
45
46
 
@@ -366,8 +367,14 @@ func _laid_out(control: Control, name: String) -> String:
366
367
  )
367
368
  % [control.name, parent.name, parent.get_class(), base]
368
369
  )
369
- if anchoring and GdhRead.as_int(control.get("layout_mode")) == LAYOUT_MODE_POSITION:
370
+ var mode: int = GdhRead.as_int(control.get("layout_mode"))
371
+ if anchoring and mode == LAYOUT_MODE_POSITION:
370
372
  control.set("layout_mode", LAYOUT_MODE_ANCHORS)
373
+ # A scene's root reads as Uncontrolled but keeps the Position mode it was made with until it
374
+ # enters a tree, and the engine ignores a preset in that stored mode, so full rect read back as
375
+ # top left on every root a headless edit wrote.
376
+ elif anchoring and mode == LAYOUT_MODE_UNCONTROLLED:
377
+ control.set("layout_mode", LAYOUT_MODE_UNCONTROLLED)
371
378
  return ""
372
379
 
373
380
 
@@ -549,7 +549,25 @@ class GdhRunner:
549
549
  return
550
550
  if Engine.is_embedded_in_editor():
551
551
  return
552
- if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_MINIMIZED:
552
+ var mode: DisplayServer.WindowMode = DisplayServer.window_get_mode()
553
+ if mode == DisplayServer.WINDOW_MODE_MAXIMIZED and not DisplayServer.window_can_draw():
554
+ # On macOS Godot reads a window whose frame fills the usable screen as maximised before
555
+ # asking whether it is minimised, and changing the mode from that reading unzooms it, so
556
+ # a minimised window that size, as a small screen makes the default one, stayed
557
+ # minimised. A point off it reads as what it is, and goes back once restored. Godot
558
+ # divides pixels by the scale into whole points, so a pixel moves nothing on a scaled
559
+ # screen.
560
+ var at: Vector2i = DisplayServer.window_get_position()
561
+ DisplayServer.window_set_position(
562
+ at + Vector2i(ceili(DisplayServer.screen_get_max_scale()), 0)
563
+ )
564
+ mode = DisplayServer.window_get_mode()
565
+ if mode == DisplayServer.WINDOW_MODE_MINIMIZED:
566
+ DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
567
+ minimise_pending = false
568
+ DisplayServer.window_set_position(at)
569
+ return
570
+ if mode == DisplayServer.WINDOW_MODE_MINIMIZED:
553
571
  DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
554
572
  minimise_pending = false
555
573
 
package/build/keeper.js CHANGED
@@ -6946,7 +6946,7 @@ var require_public_api = __commonJS(function(exports) {
6946
6946
  });
6947
6947
 
6948
6948
  // src/keeper.ts
6949
- import { closeSync as closeSync3, existsSync as existsSync3, mkdtempSync as mkdtempSync4, openSync as openSync4, readFileSync as readFileSync9, rmSync as rmSync7, writeFileSync as writeFileSync4 } from "node:fs";
6949
+ import { closeSync as closeSync3, existsSync as existsSync4, mkdtempSync as mkdtempSync4, openSync as openSync4, readFileSync as readFileSync9, rmSync as rmSync7, writeFileSync as writeFileSync4 } from "node:fs";
6950
6950
  import { tmpdir as tmpdir8 } from "node:os";
6951
6951
  import { join as join10 } from "node:path";
6952
6952
  import { setTimeout as delay3 } from "node:timers/promises";
@@ -7435,6 +7435,7 @@ function throughHelper(how, command, args, files, assembly = helperAssembly()) {
7435
7435
  // src/engine-slots.ts
7436
7436
  import {
7437
7437
  closeSync as closeSync2,
7438
+ existsSync as existsSync2,
7438
7439
  mkdirSync,
7439
7440
  openSync as openSync2,
7440
7441
  readdirSync,
@@ -9338,7 +9339,7 @@ var IMPORTABLE = new Set(IMPORTABLE_EXTENSIONS);
9338
9339
  var hashes = new Map;
9339
9340
 
9340
9341
  // src/scratch.ts
9341
- import { existsSync as existsSync2, mkdtempSync as mkdtempSync2, readdirSync as readdirSync2, rmSync as rmSync4 } from "node:fs";
9342
+ import { existsSync as existsSync3, mkdtempSync as mkdtempSync2, readdirSync as readdirSync2, rmSync as rmSync4 } from "node:fs";
9342
9343
  import { tmpdir as tmpdir5 } from "node:os";
9343
9344
  import { join as join4 } from "node:path";
9344
9345
  import process6 from "node:process";
@@ -9383,7 +9384,7 @@ function tryAgain(path, attempt) {
9383
9384
  lastTryOnExit();
9384
9385
  }
9385
9386
  const after = AGAIN_AFTER_MS[attempt];
9386
- if (after === undefined || !existsSync2(path)) {
9387
+ if (after === undefined || !existsSync3(path)) {
9387
9388
  waiting.delete(path);
9388
9389
  if (after === undefined) {
9389
9390
  atExit.add(path);
@@ -10888,7 +10889,7 @@ async function startThroughHelper(spec, output, stopFile) {
10888
10889
  exited.now = true;
10889
10890
  });
10890
10891
  for (let waited = 0;waited < DESKTOP_START_MS; waited += 50) {
10891
- const pid = existsSync3(pidFile) ? Number(readFileSync9(pidFile, "utf8").trim()) : Number.NaN;
10892
+ const pid = existsSync4(pidFile) ? Number(readFileSync9(pidFile, "utf8").trim()) : Number.NaN;
10892
10893
  if (Number.isInteger(pid) && pid > 0) {
10893
10894
  return { child: started.child, pid };
10894
10895
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdharness",
3
- "version": "1.3.59",
3
+ "version": "1.3.60",
4
4
  "mcpName": "io.github.Aureliolo/gdharness",
5
5
  "description": "A harness for driving a Godot 4 project from an agent: editor addons, a runtime bridge into the running game, an MCP server in front of them, and a CLI that installs and diagnoses the Godot side.",
6
6
  "type": "module",