271 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			271 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								// 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;
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								}
							 |