Open with no row selected passed nil to -_setFilename:, and NSOpenPanel boxed it in an
array literal, so the action threw before the modal session was stopped and the panel
stayed up. Both buttons now go through one helper that stops the session only when
this panel is the modal window and always orders the panel out; Open accepts the
selection (filtered by canChooseFiles/canChooseDirectories and multiple-selection),
or the shown directory for directory choosers. Escape cancels.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Restack and makeKey no longer map a window AppKit considers hidden, and
setIsVisible: NO always unmaps, so the client's splash stays hidden.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Synchronize Motif decoration hints on style and titlebar-property changes, including native-window recreation and restoring ordinary WM decorations. Add a ten-case standalone Cocoa/X11 regression probe and document validation on KWin/Xwayland.
Right Alt (keycode 108) was hard-coded as Mod5/AltGr. On layouts where it
is Mod1, the swallowed-release reconcile accepted Mod1 as held but rebuilt
the state with Mod5, so the guest could see Option and Function together.
Read the per-key masks from XGetModifierMapping (refreshed on
MappingNotify) and use them everywhere; the old table is the fallback for
unmapped keys. The probe now checks Right Alt against whichever mask the
backend reports.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
GNOME's overview delivers the Super press to the game window, eats the
release and hands the keyboard back without a FocusOut. The backend kept
Command held, so every later key and click reached the game as a Command
shortcut until a real focus change reconciled it (issue #74).
Each key, button, motion and crossing event carries the server's modifier
state; release any modifier key we track as down whose modifier is missing
from it. Synthetic events from other clients are ignored.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Riot's splash screens draw on a black rectangle: LeagueClient's is a
borderless NSWindow with setOpaque:NO and a pattern-image background, the
Riot Client's an Electron BrowserWindow with transparent: true. X11Window
created every window with a 24-bit visual and -setOpaque: only stored the
flag, so there was no alpha channel.
A non-opaque window whose background can show through (alpha below 1, or a
pattern image) now gets the 32-bit ARGB visual. League's game window is
non-opaque on an opaque background and stays on the opaque visual, which
X11IsLeagueGameWindow also enforces. The X window exists before apps set
opacity and background, so the choice is checked again when the first
subwindow is created (layer subwindows inherit the visual) and before the
first map, and the window recreated while unmapped if it changed. Its
background is transparent instead of None, so no black frame shows before
the first draw. Its surface comes from an alpha EGL config for that visual
(CGLGetWindowWithAlpha) and its compositing context from the surface's
config (CGLCreateContextForWindow): NVIDIA refuses the default config on a
32-bit window, and no driver makes a context from it current on the alpha
surface. Without an alpha config the window falls back to the opaque
visual.
A translucent window above the normal level (Electron's alwaysOnTop
splash) is typed _NET_WM_WINDOW_TYPE_SPLASH with _NET_WM_STATE_ABOVE before
it is mapped: window managers float it and draw no frame around it.
Electron's level never arrived, though: CGWindowLevelForKey returned the
normal level for every key, and the SDK turns NSFloatingWindowLevel into a
call to it. It now returns the levels macOS does; Cocotron only stores
levels, so nothing else changes.
The drag loop runs run loop sources and main queue blocks between moves,
and Chromium can tear down a web view or close a window there. Hold both
until the drag ends, after -draggedImage:endedAt:operation:.
The X11 backend has no NSDraggingManager, so -[NSWindow dragImage:...]
returned at once without calling -draggedImage:endedAt:operation:.
Chromium waits for that callback before the page takes mouse input again,
so any HTML5 drag in a CEF/Electron window (the League client's emote
wheel) left the page ignoring the mouse.
NSWindow now runs the drag itself between the app's own windows, with the
drag image under the pointer, and always ends it with the callback.
X11Pasteboard sends the optional -pasteboardChangedOwner: only to owners
that implement it (Chromium's drag source doesn't; the second drag
crashed). NSView's default -prepareForDragOperation: returns YES, as
AppKit does for destinations that don't implement it.
Rebuild the remaining NVIDIA changes on current main, preserving the merged visual, draw-buffer, descriptor ownership and mixed Metal-tree fixes. Scope native-thread forwarding to resize notifications and make completion polling per device, bounded and part of the caller timeout budget.
Co-authored-by: Pirrandi <[email protected]>
The stub returned nil and left the language output untouched. Chromium
pre-fills that output with a sentinel and reads it whenever it is
non-NULL, so the League client UI read garbage. Return CTFontCopyName
and always write NULL to the language output. The CoreText font-list
check now covers both.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The unimplemented method returned whatever was left in a register.
Chromium forwards the style to its renderer, which rejected the
out-of-range value (VALIDATION_ERROR_DESERIALIZATION_FAILED) and left
the Riot Client window black. Report NSScrollerStyleLegacy, as macOS
does without a trackpad.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The Riot Client (Electron) aborted with unrecognized selectors in
Cocotron's AppKit:
- -[NSOpenPanel setShowsTagField:]: Electron sets it on every file
dialog. Add the missing NSSavePanel setters it uses (showsTagField,
nameFieldLabel, extensionHidden, canSelectHiddenExtension) as no-ops,
and implement beginWithCompletionHandler: and
beginSheetModalForWindow:completionHandler: by running the panel
modally and calling the handler (the old stub never called it).
- -[MacWorkspace openURLs:withAppBundleIdentifier:options:
additionalEventParamDescriptor:launchIdentifiers:]: used by
shell.openExternal for the third-party sign-in buttons. Open each URL
through openURL: (LaunchServices).
Fixes#28
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Second half of the NVIDIA black screen (#3). With the visual fix the
compositor gets a window surface and drawables recycle, but the window
stays black: after CARenderer draws, the back buffer reads back black and
even a glClear to blue changes nothing. GL_DRAW_BUFFER and GL_READ_BUFFER
are GL_NONE.
CALayerContext -setSubwindow: creates the context and then notifies the
layer tree; CAMetalLayer -_setContext: makes the context current (to
create its textures) before any window surface is attached. Per
EGL_KHR_surfaceless_context, a context first made current without a
default framebuffer starts with DRAW_BUFFER = NONE, and attaching a
window later doesn't change it. NVIDIA follows that; Mesa resets it on
bind, which is why AMD works.
After CGLContextMakeCurrentAndAttachToWindow in -renderLayer:, set the
draw and read buffers to GL_BACK.
On NVIDIA (RTX 2070 SUPER, driver 615.78, Xwayland) the game showed a
black screen and logged "Metal Device timed out giving us a Drawable to
present" every second (#3).
X11Window picked its visual with glXChooseVisual, which on NVIDIA returns
a GLX-only visual (0x304 here). NVIDIA's EGL configs only map to the
default visual (0x69) and the 32-bit one (0x99), so CGLGetWindow's
eglCreateWindowSurface failed with EGL_BAD_CONFIG for the window and its
subwindows, for every one of the 40 window configs. CGLGetWindow returns
NULL without logging, CALayerContext keeps _cglWindow == NULL, -render
returns before prepareMetalLayers, and CAMetalLayer never gets its three
drawables back. Mesa accepts the GLX visual, which is why AMD works.
Use the default visual when it is TrueColor with depth >= 24, falling
back to glXChooseVisual otherwise. This also fixes every other Darling
window on NVIDIA: plain AppKit windows (title bars included),
layer-backed views and NSOpenGLView were all black without it.
League enters relative mouse mode on GNOME (Xwayland) and inside gamescope, but
keeps a visible cursor and warps it every frame at its own mouse speed. Xwayland
cannot move a visible pointer, so those warps never took effect: the virtual
cursor, where clicks land, drifted hundreds of pixels from the cursor on screen
and never reached the screen edges, which also stopped edge panning.
Where warps are not honoured, the virtual cursor now follows the physical
pointer and the game's warps leave it in place. With a hidden cursor, or on a
server that honours warps, nothing changes. The host model test gains a case
replaying the drift from an in-game trace.
Tested manually in the practice tool under gamescope 3.16.31 on GNOME 51 with
AMD RADV: clicks land on the cursor and edge panning works.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Port the fullscreen policy omitted when adapting PR #12. Track requested fullscreen state across frame and style changes, exclude unmanaged windows, and use EWMH REMOVE when leaving fullscreen.
Extend the native geometry probe and document passive tracing for the reported vertical click offset, whose cause remains unconfirmed.
CGDisplayScreenSize returned 0x0 for any display with EDID (upstream left
that branch unimplemented). League divides by it for its camera aspect
ratio, so the view-projection x row became NaN: every 3D vertex was
discarded, the scene showed only its blue clear colour, and world clicks
were ignored. Read the size from the EDID detailed timing (mm) or basic
parameters (cm), fall back to 96 dpi, and use the main display for an
unknown id.
CGDisplayCopyAllDisplayModes returned NULL for display 0 (a window off
every screen), which League passes straight to CFArrayGetCount. Fall back
to the main display, then to an empty array.
Add riot-display-modes-check covering both for the main display,
display 0 and an unknown id.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Adapt the geometry fix from PR #12 to the current relative-mouse implementation. Keep display IDs independent of primary-first screen ordering, translate window and pointer coordinates consistently, and invalidate geometry on both RandR event types.
Handle failed RandR snapshots and free EDID data. Add isolated native geometry regression coverage and use the configured SDK when linking the X11 probe.
Validated all 30 component patches, the X11 and CoreGraphics builds, six native geometry groups, and the existing relative-mouse checks. The user confirmed the installed fix works on 2026-10-16.
Co-authored-by: Maka <[email protected]>