From 37f8b8a559a25f4e81c8136b970b28c3a5e81dad Mon Sep 17 00:00:00 2001 From: sbosse Date: Mon, 21 Jul 2025 23:03:24 +0200 Subject: [PATCH] Mon 21 Jul 22:43:21 CEST 2025 --- js/x11/core/ext/apple-wm.js | 270 ++++++++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 js/x11/core/ext/apple-wm.js diff --git a/js/x11/core/ext/apple-wm.js b/js/x11/core/ext/apple-wm.js new file mode 100644 index 0000000..d9c9803 --- /dev/null +++ b/js/x11/core/ext/apple-wm.js @@ -0,0 +1,270 @@ +// http://www.xfree86.org/current/AppleWM.3.html +// http://opensource.apple.com/source/X11server/X11server-106.3/Xquartz/xorg-server-1.10.2/hw/xquartz/applewm.c +// /usr/X11/include/X11/extensions/applewm.h + +var x11 = Require('x11/core/x11'); +var xutil = Require('x11/core/xutil'); +// TODO: move to templates + +/* +#define X_AppleWMFrameGetRect 1 +#define X_AppleWMFrameHitTest 2 +#define X_AppleWMFrameDraw 3 +#define X_AppleWMDisableUpdate 4 +#define X_AppleWMReenableUpdate 5 +#define X_AppleWMSetWindowMenuCheck 7 +#define X_AppleWMSetWindowMenu 11 +#define X_AppleWMSendPSN 12 +#define X_AppleWMAttachTransient 13 +*/ + +exports.requireExt = function(display, callback) +{ + var X = display.client; + X.QueryExtension('Apple-WM', function(err, ext) { + + if (!ext.present) + callback(new Error('extension not available')); + + ext.QueryVersion = function(cb) + { + X.seq_num++; + X.pack_stream.pack('CCS', [ext.majorOpcode, 0, 1]); + X.replies[X.seq_num] = [ + function(buf, opt) { + var res = buf.unpack('SSL'); + return res; + }, + cb + ]; + X.pack_stream.flush(); + } + + ext.FrameRect = { + Titlebar: 1, + Tracking: 2, + Growbox: 3 + }; + + ext.FrameGetRect = function(frame_class, frame_rect, ix, iy, iw, ih, ox, oy, ow, oh, cb) + { + X.seq_num++; + X.pack_stream.pack('CCSSSSSSSSSSS', [ext.majorOpcode, 1, 6, frame_class, frame_rect, ix, iy, iw, ih, ox, oy, ow, oh, cb]); + X.replies[X.seq_num] = [ + function(buf, opt) { + var res = buf.unpack('SSSS'); + return { + x: res[0], + y: res[1], + w: res[2], + h: res[3] + }; + }, + cb + ]; + X.pack_stream.flush(); + } + + ext.FrameHitTest = function(frame_class, px, py, ix, iy, iw, ih, ox, oy, ow, oh, cb) + { + X.seq_num++; + X.pack_stream.pack('CCSSxxSSSSSSSSSS', [ext.majorOpcode, 2, 7, frame_class, px, py, ix, iy, iw, ih, ox, oy, ow, oh]); + X.replies[X.seq_num] = [ + function(buf, opt) { + var res = buf.unpack('L'); + return res[0]; + }, + cb + ]; + X.pack_stream.flush(); + } + + +// from /usr/include/Xplugin.h + ext.FrameClass = { + DecorLarge: 1, + Reserved1: 2, + Reserved2: 4, + Reserved3: 8, + DecorSmall: 16, + Reserved5: 32, + Reserved6: 64, + Reserved8: 128, + Managed: 1<<15, + Transient: 1<<16, + Stationary: 1<<17 + }; + + ext.FrameAttr = { + Active: 1, + Urgent: 2, + Title: 4, + Prelight: 8, + Shaded: 16, + CloseBox: 0x100, + Collapse: 0x200, + Zoom: 0x400, + CloseBoxClicked: 0x800, + CollapseBoxClicked: 0x1000, + ZoomBoxClicked: 0x2000, + GrowBox: 0x4000 + }; + + ext.FrameDraw = function(screen, window, frameClass, attr, ix, iy, iw, ih, ox, oy, ow, oh, title) + { + X.seq_num++; + var titleReqWords = xutil.padded_length(title.length)/4; + X.pack_stream.pack('CCSLLSSSSSSSSSSLp', [ext.majorOpcode, 3, 9+titleReqWords, screen, window, frameClass, attr, ix, iy, iw, ih, ox, oy, ow, oh, title.length, title]); + X.pack_stream.flush(); + } + + ext.NotifyMask = { + Controller: 1, + Activation: 2, + Pasteboard: 4, + All: 7 + }; + +// TODO: decode events +/* +#define AppleWMMinimizeWindow 0 +#define AppleWMZoomWindow 1 +#define AppleWMCloseWindow 2 +#define AppleWMBringAllToFront 3 +#define AppleWMHideWindow 4 +#define AppleWMHideAll 5 +#define AppleWMShowAll 6 +#define AppleWMWindowMenuItem 9 +#define AppleWMWindowMenuNotify 10 +#define AppleWMNextWindow 11 +#define AppleWMPreviousWindow 12 + +#define AppleWMIsActive 0 +#define AppleWMIsInactive 1 +#define AppleWMReloadPreferences 2 + +#define AppleWMCopyToPasteboard 0 +*/ + + ext.SelectInput = function(mask) + { + X.seq_num++; + X.pack_stream.pack('CCSL', [ext.majorOpcode, 6, 2, mask]); + X.pack_stream.flush(); + } + + ext.SetFrontProcess = function() + { + X.seq_num++; + X.pack_stream.pack('CCS', [ext.majorOpcode, 8, 1]); + X.pack_stream.flush(); + } + + ext.WindowLevel = { + Normal: 0, + Floating: 1, + TornOff: 2, + Dock: 3, + Desktop: 4 + }; + + ext.SetWindowLevel = function(window, level) + { + X.seq_num++; + X.pack_stream.pack('CCSLL', [ext.majorOpcode, 9, 3, window, level]); + X.pack_stream.flush(); + } + + ext.CanQuit = function(state) + { + X.seq_num++; + X.pack_stream.pack('CCSCxxx', [ext.majorOpcode, 10, 2, state]); + X.pack_stream.flush(); + } + + // shortcut is single-byte ASCII (optional, 0=no shortcut) + // items example: [ 'item1', 'some item', ['C', 'item with C shortcut'] ] + ext.SetWindowMenu = function(items) + { + var reqlen = 8; + var extlength = 0; + items.forEach(function(i) { + + }); + } + + // https://developer.apple.com + // /library/mac/documentation/Carbon/Reference/Process_Manager/Reference/reference.html#//apple_ref/doc/c_ref/ProcessSerialNumber + ext.SendPSN = function(hi, lo) + { + X.seq_num++; + X.pack_stream.pack('CCSLL', [ext.majorOpcode, 12, 3, hi, lo]); + X.pack_stream.flush(); + } + + ext.AttachTransient = function(child, parent) + { + X.seq_num++; + X.pack_stream.pack('CCSLL', [ext.majorOpcode, 13, 3, child, parent]); + X.pack_stream.flush(); + } + + callback(null, ext); + /* + ext.QueryVersion(function(err, vers) { + ext.major = vers[0]; + ext.minor = vers[1]; + ext.patch = vers[2]; + callback(null, ext); + }); + */ + + ext.events = { + AppleWMControllerNotify: 0, + AppleWMActivationNotify: 1, + AppleWMPasteboardNotify: 2, + } + + ext.EventKind = { + Controller: { + MinimizeWindow: 0, + ZoomWindow: 1, + CloseWindow: 2, + BringAllToFront: 3, + WideWindow: 4, + HideAll: 5, + ShowAll: 6, + WindowMenuItem: 9, + WindowMenuNotify: 10, + NextWindow: 11, + PreviousWindow: 12 + }, + Activation: { + IsActive: 0, + IsInactive:1, + ReloadPreferences: 2 + }, + Pasteboard: { + CopyToPasteboard: 0 + } + }; + + X.eventParsers[ext.firstEvent + ext.events.AppleWMControllerNotify] = + X.eventParsers[ext.firstEvent + ext.events.AppleWMActivationNotify] = + X.eventParsers[ext.firstEvent + ext.events.AppleWMPasteboardNotify] = function(type, seq, extra, code, raw) + { + var event = {}; + switch(type) { + case ext.firstEvent + ext.events.AppleWMControllerNotify: event.name = 'AppleWMControllerNotify'; break; + case ext.firstEvent + ext.events.AppleWMActivationNotify: event.name = 'AppleWMActivationNotify'; break; + case ext.firstEvent + ext.events.AppleWMPasteboardNotify: event.name = 'AppleWMPasteboardNotify'; break; + } + event.type = code; + event.time = extra; + event.arg = raw.unpack('xxL')[0]; + return event; + }; + + + }); +}