Repository navigation
Description
What
In threaded mode the renderer calls the bridge from a worker, and an AppKit object touched from there is an abort (createWindow2 from a Worker: NSWindow should only be instantiated on the main thread!). Every verb that touches one has to reach the UI thread through the command queue — and since JS never waits on the UI thread, any verb that returns something from AppKit changes shape. This issue is the inventory of 0.9.0's verbs and the shape each one takes.
Proposed shapes (mechanism only)
Stays on the calling thread, unchanged. Verified from a Worker for CG drawing with readback and for CoreText.
- Surfaces:
createSurface,createSurfaceIOSurface,surfaceFromIOSurfaceID,releaseSurface,surfaceLock,surfaceUnlock,surfaceSize,blitSurface,copySurfaceRegion,scrollSurface - Drawing: every
ctx*verb - Text:
createLayout,drawLayout,drawLayoutGradient,layoutCaret,layoutIndexAt;font*,cgFontWithSize,listFonts,matchFont,loadFontData - Type lookups:
pasteboardTypeForMIME,pasteboardTypeInfo,contentTypeFor,colorSpace
A command — fire and forget.
initApp, setActivationPolicy, setAppName, activateApp, showWindow, hideWindow, setWindowFrame, setWindowTitle, setWindowMinMax, setWindowIgnoresMouseEvents, invalidateWindowShadow, destroyWindow2, setCursor, setMainMenu, setDockMenu, setDockBadge, cancelUserAttention, setStatusItem, setStatusItemMenu, removeStatusItem, registerDropTypes, setDropResponse (it already sets a standing answer, which is the right shape), pasteboardWriteText, pasteboardClear, cancelPanel.
A handle allocated at the call, bound when the UI thread makes the object:
createWindow2returns the bridge's own handle at once; awindow-created { handle, windowNumber }event follows. Every window event carries the handle, so the renderer can stop keying windows bywindowNumber.windowRootLayer— the root layer's handle, allocated with the window's.createStatusItemandrequestUserAttention(its request id), the same way.
Published state, read without a hop (#50): getWindowFrame, windowIsVisible, windowNumber once the window exists, listScreens, accessibilityDisplayOptions, activationPolicy, appInfo, pasteboardChangeCount.
An async answer, by callback or by event:
pasteboardReadTexttakes a callback. react-x11's clipboard contract is a Promise already.snapshotWindowandsnapshotStatusItemtake a callback.beginDrag: itsbeganboolean becomes thedrag-session-beganevent it already has, or adrag-session-endedwith nothing dropped.dragItemString,dragItemData,dragItems: the cheap forms (strings, file URLs, the type list) are read intodrag-performitself, since the drag pasteboard is only certain inside the destination callbacks. Anything larger becomes an async read.windowNumberAtPointtakes a callback.measureControlanddrawControlIntoSurface— see measureControl / drawControlIntoSurface are main-thread only: from a Worker they draw, then crash at exit #54.
Already callback-shaped. Only the part that touches AppKit moves.
openPanelandsavePanel: the result callback becomes a threadsafe function in the caller's environment. The sheet orrunModalruns on the UI thread, where a modal panel no longer parks JS.sampleScreenColoranswers through a threadsafe function today.showSamplerWithSelectionHandler:moves to the UI thread.- Notifications, calendars and permissions answer through threadsafe functions from their own queues today. Audit that each AppKit or main-queue call they make is reached through
OnUI, and that their threadsafe functions are created in the calling environment, which is then the worker.
Test-only posts are commands: postMouseEvent, postKeyEvent, postDragEvent, postAppleEvent, postAccessibilityDisplayChange, postNotificationResponse, postCalendarStoreChanged, activateMenuItem, activateDockMenuItem, activateStatusItemMenuItem, clickStatusItem. Their reads (mainMenuInfo, dockMenuInfo, statusItemInfo) are async.
Gone in threaded mode: pump2. The first-generation addon.mm API (pump, createWindow, setEventCallback, closeWindow, windowContentSize, windowScale, hitTest, drawControl, appearanceIsDark) either follows or is declared pump-mode only.
Notes
- react-x11 uses about 130 of the 182 verbs. Thirteen of its call sites use a return value from AppKit:
createWindow2,windowNumber,windowRootLayer,getWindowFrame,windowIsVisible,listScreens,pasteboardReadText,snapshotWindow,beginDrag,dragItemString,measureControl,createStatusItem,requestUserAttention. Those are the ones whose shape changes for the renderer. - In pump mode every verb keeps today's synchronous behaviour, via the
OnUIhelper in Threaded mode: the threading core — runMain, a command queue drained in the common modes, one batched event channel, published state #50.
Consumer
react-x11 src/cocoa/ — window.js, app.js, dnd.js, statusitem.js, bezels.js; docs/macos.md §"JS on a worker: a UI thread of the bridge's own", sidorares/react-x11#539.
Activity