diff --git a/scripts/app-drive.sh b/scripts/app-drive.sh index 5658b58e6..21c2abdb6 100755 --- a/scripts/app-drive.sh +++ b/scripts/app-drive.sh @@ -265,9 +265,16 @@ press_at() { # application to attach, and -d spaces the keys so none is lost to the same race. send_keys_spec() { case "$1" in - # Raw wtype arguments, for a shortcut: "raw:-M logo n -m logo" is Command and N, since the + # Raw wtype arguments, for a shortcut: "raw:-M,logo,n,-m,logo" is Command and N, since the # backend maps Mod4 to NSCommandKeyMask. A menu item several clicks deep is not reachable # any other way from here. + # + # A NAMED KEY NEEDS -k, AND A BARE WORD IS TYPED AS TEXT. "raw:-M,logo,comma,-m,logo" does + # NOT send Command and comma: wtype types the five letters c, o, m, m, a with Command held, + # so the application receives Command C, Command O, Command M, Command M and Command A. + # Command M minimised the window, which then stopped updating its frame on every later + # resize, and I filed that as a two window resize defect before finding the cause was my own + # shortcut. The correct form is "raw:-M,logo,-k,comma,-m,logo". A single letter is fine bare. # COMMAS BECOME SPACES, because STEPS splits on whitespace so a raw sequence cannot contain # one. The comment above the sequencer has promised this since the verb was added and the # code never did it: "raw:-M,logo,comma,-m,logo" reached wtype as ONE argument, wtype diff --git a/src/darwin/wayland/window.rs b/src/darwin/wayland/window.rs index 7508a070d..f8f6278c1 100644 --- a/src/darwin/wayland/window.rs +++ b/src/darwin/wayland/window.rs @@ -616,6 +616,15 @@ pub fn deliver_pending_configures() { objc::msg_send_rect_ret(st.delegate, objc::sel_registerName(cstr!("frame"))); let aw = actual.size.width as i32; let ah = actual.size.height as i32; + /* WHAT THE WINDOW SAYS IT IS, against what we just gave it. A frame that reads back + * as the PREVIOUS size is indistinguishable here from one clamped to a minimum, and + * both grow the bitmap, so print the pair rather than infer it from insist. */ + if crate::env_flag!("CIDER_WAYLAND_TRACE_GEOMETRY") { + println!( + "cider-wayland-frameback number={} gave={}x{} frame={}x{} insist={}x{}", + st.number, width, height, aw, ah, st.insist_w, st.insist_h + ); + } if aw > width || ah > height { st.insist_w = aw.max(width); st.insist_h = ah.max(height); diff --git a/vendor/patches/cocotron/0077-name-who-asked-a-window-to-miniaturize.patch b/vendor/patches/cocotron/0077-name-who-asked-a-window-to-miniaturize.patch new file mode 100644 index 000000000..4ee9f4339 --- /dev/null +++ b/vendor/patches/cocotron/0077-name-who-asked-a-window-to-miniaturize.patch @@ -0,0 +1,56 @@ +Name who asked a window to miniaturize. + +A window that believes it is miniaturized never updates its frame again: +-platformWindow:frameChanged:didSize: skips the assignment for a miniaturized window, so every +later resize reads back the old size, the backing bitmap is grown to hold a window that is no +longer that big, and the compositor is shown the wrong rows of it. From outside that looks exactly +like a resize defect. + +It reached that state with the window MAIN, KEY and VISIBLE, and as its own sender, so the caller +was the whole question and no state dump could answer it. The backtrace named it in one run: + + CIDER_MINI miniaturize: window=0x7087febf1a00 sender=iTermWindow + CIDER_MINI AppKit -[NSApplication sendAction:to:from:] + CIDER_MINI AppKit -[NSMenu performKeyEquivalent:] + CIDER_MINI iTerm2 -[PTYTextView performKeyEquivalent:] + +which is the Minimize item matching a Command M that the harness sent by accident. So the trace +earned its place by exonerating the port rather than by finding a defect in it, and it stays +because the next window that miniaturizes itself will raise the same question. + +Gated on CIDER_TRACE_MINIATURIZE, and miniaturize: is rare enough that a getenv per call costs +nothing. + +Task #252. + +--- a/AppKit/NSWindow.m ++++ b/AppKit/NSWindow.m +@@ -3735,6 +3735,28 @@ + } + + - (void) miniaturize: (id) sender { ++ /* WHO ASKED. A window that believes it is miniaturized never updates its frame again, because ++ * -platformWindow:frameChanged:didSize: skips the assignment for a miniaturized window, and ++ * that leaves every later resize stale. iTerm2 reaches this with the window as its own sender ++ * while it is main, key and visible, so the caller is the whole question. Task #252. */ ++ if (getenv("CIDER_TRACE_MINIATURIZE") != NULL) { ++ void *frames[24]; ++ int count = backtrace(frames, 24); ++ ++ fprintf(stderr, "CIDER_MINI miniaturize: window=%p sender=%s\n", self, ++ sender != nil ? object_getClassName(sender) : "(nil)"); ++ for (int i = 1; i < count; i++) { ++ Dl_info info; ++ ++ if (dladdr(frames[i], &info) != 0 && info.dli_sname != NULL) { ++ const char *image = info.dli_fname ? strrchr(info.dli_fname, '/') : NULL; ++ ++ fprintf(stderr, "CIDER_MINI %-26s %s\n", image ? image + 1 : "?", ++ info.dli_sname); ++ } ++ } ++ fflush(stderr); ++ } + [[self cider_platformWindow] miniaturize]; + } +