/// <summary> /// This is a javascript application. /// </summary> /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param> public Application(IApp page) { // can we inject ourselves into a chrome tab // before the page loads? // http://stackoverflow.com/questions/19191679/chrome-extension-inject-js-before-page-load // If you want to dynamically run a script as soon as possible, then call chrome.tabs.executeScript when the chrome.webNavigation.onCommitted event is triggered. // when does that happen? // if we are able to preload, would we be able to act as adblock? // as per X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionShadowExperiment\ChromeExtensionShadowExperiment\Application.cs // first lets get this test running in chrome dynamic self = Native.self; dynamic self_chrome = self.chrome; object self_chrome_tabs = self_chrome.tabs; if (self_chrome_tabs != null) { #region Installed chrome.runtime.Installed += delegate { // our API does not have a Show new chrome.Notification { Message = "ChromeExtensionPreShadow Installed!" }; }; #endregion // what about // Error code: ERR_INTERNET_DISCONNECTED var once = new { tabId = default(TabIdInteger), url = default(string) }.ToEmptyList(); new { }.With( async delegate { // X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionWithWorker\ChromeExtensionWithWorker\Application.cs var code = await new WebClient().DownloadStringTaskAsync( new Uri(Worker.ScriptApplicationSource, UriKind.Relative) ); new chrome.Notification { Message = "code " + new { code.Length } }; chrome.webNavigation.Committed += async z => { // 0:5212ms at Delay {{ _title = , _message = webNavigation! Committed {{ url = http://example.com/, tabId = 99, transitionType = typed, transitionQualifiers = from_address_bar }} }} if (z.url.StartsWith("https://www.google.ee/_/chrome/newtab?")) { //Unchecked runtime.lastError while running tabs.executeScript: Cannot access a chrome:// URL return; } // 0:487298ms at Delay { // { // _title = , _message = webNavigation!Committed { // { // url = chrome://chrome/extensions/, tabId = 158, transitionType = auto_bookmark, transitionQualifiers = }} }} view-source:41478 //Unchecked runtime.lastError while running tabs.executeScript: Cannot access a chrome:// URL if (z.transitionType == "auto_subframe") { // this seems to be an ad? // https://developer.chrome.com/extensions/history return; } if (z.url.StartsWith("chrome-devtools://")) return; if (z.url.StartsWith("chrome://")) return; // now would be nice to check if this tab was already injected. once.Add(new { z.tabId, z.url }); var n = new chrome.Notification { Message = "webNavigation! Committed " + new { z.url, z.tabId, z.transitionType, z.transitionQualifiers } }; // 0:3388ms at Delay { // { // _title = , _message = webNavigation!Committed { // { // url = https://www.google.ee/_/chrome/newtab?espv=2&ie=UTF-8, tabId = 125, transitionType = typed, transitionQualifiers = }} }} view-source:41478 //Unchecked runtime.lastError while running tabs.executeScript: Cannot access a chrome:// URL // https://developer.chrome.com/extensions/tabs#method-executeScript //z.tabId.executeScript( // new // { // code = "document.body.style.borderLeft='1em solid yellow';", // runAt = "document_start" // } //); // we should now be able to take command of that web page. // yet. we might not want to change its DOM yet? // maybe wait for context menu, keyboard or action icon click? // Content scripts execute in a special environment called an isolated world. // They have access to the DOM of the page they are injected into, but not to any JavaScript variables or // functions created by the page. It looks to each content script as if there is no other JavaScript executing // on the page it is running on. The same is true in reverse: JavaScript running on the page cannot call any // functions or access any variables defined by content scripts. var result = await z.tabId.executeScript( //new { file = url } new { code, runAt = "document_start" } ); }; } ); //chrome.tabs.Created += // (z) => // { // var n = new Notification // { // Message = "Created! " + new { z.id } // }; // }; //chrome.tabs.Activated += // (z) => // { // var n = new Notification // { // Message = "Activated! " + new { z } // }; // }; return; } // inside executeScript Native.document.documentElement.style.borderTop = "1em solid yellow"; //Native.body.style.borderTop = "1em solid yellow"; Console.WriteLine("injected!"); // save view-source to B: // reload extension // 0:6311ms injected! // lets test agiainst file:// // it works. // either do the workers now or lets test register element? // Uncaught NotSupportedError: Failed to execute 'registerElement' on 'Document': Registration failed for type 'x-foo'. Elements cannot be registered from extensions. //Native.document.registerElement("x-foo", // (IHTMLElement e) => // { // e.shadow.appendChild("x-foo element provided by ChromeExtensionPreShadow"); // } //); // !! Elements cannot be registered from extensions. // X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionPreShadow\ChromeExtensionPreShadow\Application.cs // https://code.google.com/p/chromium/issues/detail?id=390807 Native.document.querySelectorAll("x-foo").WithEach( e => { // what about elements added later? e.shadow.appendChild("x-foo element provided by ChromeExtensionPreShadow without registerElement"); //MutationCallback } ); // ILMutationObserver new MutationObserver( new MutationCallback( (MutationRecord[] mutations, MutationObserver observer) => { // MutationCallback: {{ Length = 3 }} // MutationCallback: {{ type = childList }} // MutationCallback: {{ type = characterData }} mutations.WithEach( m => { // not a good idea. recursive //new IHTMLPre { "MutationCallback: " + new { m.type } }.AttachToDocument(); if (m.type == "childList") { m.addedNodes.WithEach( addedNode => { //new IHTMLPre { "MutationCallback: " + new { addedNode } }.AttachToDocument(); //MutationCallback: { { addedNode = [object HTMLElement] } } if (addedNode.nodeType == INode.NodeTypeEnum.ElementNode) { var addedElement = (IHTMLElement)addedNode; //MutationCallback: addedElement { { localName = x - foo } } //new IHTMLPre { "MutationCallback: addedElement " + new { addedElement.localName } }.AttachToDocument(); if (addedElement.localName == "x-foo") { addedElement.shadow.appendChild("x-foo element provided by ChromeExtensionPreShadow without registerElement"); } } } ); } } ); } ) ).observe(Native.document.documentElement, new { // Set to true if mutations to target's children are to be observed. childList = true, // Set to true if mutations to target's attributes are to be observed. Can be omitted if attributeOldValue and/or attributeFilter is specified. //attributes = true, // Set to true if mutations to target's data are to be observed. Can be omitted if characterDataOldValue is specified. //characterData = true, // Set to true if mutations to not just target, but also target's descendants are to be observed. subtree = true, } ); }
/// <summary> /// This is a javascript application. /// </summary> /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param> public Application(IApp page) { // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150824 // http://stackoverflow.com/questions/14103986/canvas-and-spritematerial // X:\jsc.svn\examples\javascript\WebGL\WebGLSVGAnonymous\WebGLSVGAnonymous\Application.cs // X:\jsc.svn\examples\javascript\WebGL\WebGLVRCreativeLeadership\WebGLVRCreativeLeadership\Application.cs // X:\jsc.svn\examples\javascript\WebGL\WebGLSVGSprite\WebGLSVGSprite\Application.cs //var l = new NotificationLayout().layout; //l.AttachToDocument(); // : INodeConvertible<IHTMLElement> //var c = (IHTMLCanvas)l.layout; //var c = (IHTMLCanvas)l; // look we have a databound 2D image! // make it implicit operator for assetslibrary? //l.style //c.AttachToDocument(); // https://play.google.com/store/apps/details?id=com.abstractatech.vr // could we display LAN UDP notifications too. like // which youtube video is playing? Native.body.Clear(); Native.body.style.margin = "0px"; Native.body.style.backgroundColor = "black"; // https://vronecontest.zeiss.com/index.php?controller=ideas&view=show&id=652 // hResolution: 1920, //vResolution: 1080, // "X:\jsc.svn\examples\javascript\synergy\webgl\WebGLEquirectangularPanorama\WebGLEquirectangularPanorama.sln" // http://oculusstreetview.eu.pn/?lat=44.301987&lng=9.211561999999958&q=3&s=false&heading=0 // https://github.com/troffmo5/OculusStreetView // http://stackoverflow.com/questions/23817633/threejs-using-a-sprite-with-the-oculusrifteffect // http://laht.info/dk2-parameters-for-three-oculusrifteffect-js/ // http://stemkoski.github.io/Three.js/Sprites.html // http://stemkoski.github.io/Three.js/Texture-Animation.html // http://blog.thematicmapping.org/2013/10/terrain-visualization-with-threejs-and.html // http://mrdoob.github.io/three.js/examples/webgl_panorama_equirectangular.html var window = Native.window; var fov = 70.0; var camera = new THREE.PerspectiveCamera(fov, 1920.0 / 1080.0, //window.aspect, 1, 1100); var target = new THREE.Vector3(0, 0, 0); //(camera as dynamic).target = target; var scene = new THREE.Scene(); //scene.add(new THREE.AmbientLight(0xffffff)); //scene.add(new THREE.AmbientLight(0xafafaf)); // http://www.html5canvastutorials.com/three/html5-canvas-webgl-ambient-lighting-with-three-js/ // http://stackoverflow.com/questions/14717135/three-js-ambient-light-unexpected-effect scene.add(new THREE.AmbientLight(0x2f2f2f)); //var light = new THREE.DirectionalLight(0xffffff, 1.0); #region light var light = new THREE.DirectionalLight(0xffffff, 2.5); //var light = new THREE.DirectionalLight(0xffffff, 2.5); //var light = new THREE.DirectionalLight(0xffffff, 1.5); //var lightOffset = new THREE.Vector3(0, 1000, 2500.0); var lightOffset = new THREE.Vector3( 2000, 700, // lower makes longer shadows 700.0 ); light.position.copy(lightOffset); light.castShadow = true; var xlight = light as dynamic; xlight.shadowMapWidth = 4096; xlight.shadowMapHeight = 2048; xlight.shadowDarkness = 0.3; //xlight.shadowDarkness = 0.5; xlight.shadowCameraNear = 10; xlight.shadowCameraFar = 10000; xlight.shadowBias = 0.00001; xlight.shadowCameraRight = 4000; xlight.shadowCameraLeft = -4000; xlight.shadowCameraTop = 4000; xlight.shadowCameraBottom = -4000; xlight.shadowCameraVisible = true; scene.add(light); #endregion var mesh = new THREE.Mesh(new THREE.SphereGeometry(500, 60, 40), new THREE.MeshBasicMaterial(new { map = THREE.ImageUtils.loadTexture( new _2294472375_24a3b8ef46_o().src //new WebGLEquirectangularPanorama.HTML.Images.FromAssets.PANO_20130616_222058().src //new WebGLEquirectangularPanorama.HTML.Images.FromAssets.PANO_20121225_210448().src ) })); mesh.scale.x = -1; scene.add(mesh); var labove = new NotificationLayout(); #region sprite2 above { labove.Message.innerText = "VR CREATIVE LEADERSHIP"; labove.layout.style.background = ""; new { }.With( async delegate { retry: // make it blink. gaze cursor is on it? labove.box.style.background = "rgba(255,255,0,0.7)"; labove.box.setAttribute("invoke", "onmutation1"); await Task.Delay(1500); // is mutation observer noticing it? labove.box.style.background = "rgba(255,255,255,0.7)"; labove.box.setAttribute("invoke", "onmutation2"); await Task.Delay(1500); goto retry; } ); var c = labove.AsCanvas(); var xcrateTexture = new THREE.Texture(c); // like video texture Native.window.onframe += delegate { xcrateTexture.needsUpdate = true; }; var xcrateMaterial = new THREE.SpriteMaterial( new { map = xcrateTexture, useScreenCoordinates = false, //color = 0xff0000 color = 0xffffff } ); var xsprite2 = new THREE.Sprite(xcrateMaterial); //floor //sprite2.position.set(0, -200, 0); // left xsprite2.position.set(200, 0, 0); //sprite2.position.set(0, 0, 200); //sprite2.position.set(-100, 0, 0); xsprite2.scale.set( c.width * 0.5, c.height * 0.5, //64, 64, 1.0); // imageWidth, imageHeight scene.add(xsprite2); } #endregion //var lineTo = new List<THREE.Vector3>(); var others = new { ui = default(NotificationLayout), canvas = default(IHTMLCanvas), map = default(THREE.Texture), sprite = default(THREE.Sprite) }.ToEmptyList(); #region add Action<NotificationLayout> add = ui => { ui.layout.style.background = ""; var canvas = ui.AsCanvas(); var index = others.Count; //ui.Message += new { index }; //ui.Message.innerText += new { index }; //lbelow0.Message = new { THREE.REVISION }.ToString(); // THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter is set to THREE.LinearFilter or THREE.NearestFilter. ( undefined ) var map = new THREE.Texture(canvas); map.minFilter = THREE.LinearFilter; // like video texture var xcrateMaterial = new THREE.SpriteMaterial( new { map, useScreenCoordinates = false, //color = 0xff0000 color = 0xffffff } ); var sprite = new THREE.Sprite(xcrateMaterial); //floor //sprite2.position.set(0, -200, 0); // left middle //sprite2.position.set(200, 0, 0); //sprite.position.set(250, -50, 50); //lineTo.Add(sprite.position); //sprite2.position.set(0, 0, 200); //sprite2.position.set(-100, 0, 0); sprite.scale.set( canvas.width * 0.5, canvas.height * 0.5, //64, 64, 1.0); // imageWidth, imageHeight scene.add(sprite); others.Add( new { ui, canvas, map, sprite } ); var sw = Stopwatch.StartNew(); Native.window.onframe += delegate { // can we get some of the crazy c++ template bitmapbuffer code from the past? map.needsUpdate = true; var offset = Math.PI * 2 * ((double)(index + 1) / others.Count); sprite.position.x = 300; sprite.position.z = Math.Sin(sw.ElapsedMilliseconds * 0.00001 + offset) * 120; sprite.position.y = Math.Cos(sw.ElapsedMilliseconds * 0.00001 + offset) * 120; }; }; #endregion add( new NotificationLayout { // keep attributes around? // like we do with XElement sync? Icon = new HTML.Images.FromAssets._0_10122014_ECAF4B1F638429B44F4B142C2A4F38EE().With( x => { x.style.width = "96px"; x.style.height = "96px"; } ), Message = "Advanced Mechanics by Portugal Design Lab" } ); add( new NotificationLayout { // keep attributes around? // like we do with XElement sync? Icon = new HTML.Images.FromAssets._42_08122014_D2639E0AAA3E54E5F4568760AEE605EE().With( x => { x.style.width = "96px"; x.style.height = "96px"; } ), Message = "Face Value by mshariful" } ); add( new NotificationLayout { // keep attributes around? // like we do with XElement sync? Icon = new HTML.Images.FromAssets._371_28122014_2045510F2F7974319A9F7E9F4B39DF07().With( x => { x.style.width = "96px"; x.style.height = "96px"; } ), Message = "Mind Wall. by Sumit Goski" } ); #region lines { var geometry = new THREE.Geometry { // how can we keep streaming verticies data points to gpu? vertices = others.SelectMany( lineTo => new[] { new THREE.Vector3(200, 0, 0), lineTo.sprite.position } ).ToArray() // https://github.com/mrdoob/three.js/wiki/Updates // http://stackoverflow.com/questions/17842521/adding-geometry-to-a-three-js-mesh-after-render //verticesNeedUpdate = true }; Native.window.onframe += delegate { geometry.verticesNeedUpdate = true; }; var o = new THREE.Line(geometry, new THREE.LineDashedMaterial( new { color = 0x00aaff, dashSize = 1, gapSize = 0.5, linewidth = 1 } ), THREE.LineStrip); //objects.Add(o); scene.add(o); } #endregion // // DK2 // hResolution: 1920, //vResolution: 1080, var renderer = new THREE.WebGLRenderer(); renderer.setSize(1920, 1080); #region HMD // broken? var distortionK = new double[] { 1.0, 0.22, 0.24, 0.0 }; var chromaAbParameter = new double[] { 0.996, -0.004, 1.014, 0.0 }; var HMD = new OculusRiftEffectOptions { hResolution = window.Width, vResolution = window.Height, hScreenSize = 0.12576, vScreenSize = 0.07074, interpupillaryDistance = 0.0635, lensSeparationDistance = 0.0635, eyeToScreenDistance = 0.041, // j.distortionK = [0, 1.875, -71.68, 1.595, -3.218644E+26, 1.615, 0, 0]; //distortionK = new double[] { 1.0, 0.22, 0.24, 0.0 }, distortionK = distortionK, // j.chromaAbParameter = [1.609382E+22, 1.874, -5.189695E+11, -0.939, 4.463059E-29, 1.87675, 0, 0]; //chromaAbParameter = new double[] { 0.996, -0.004, 1.014, 0.0 } chromaAbParameter = chromaAbParameter }; #endregion //var effect = new THREE.OculusRiftEffect( // renderer, new // { // worldScale = 100, // //HMD // } // ); //effect.setSize(1920, 1080); renderer.domElement.AttachToDocument(); //renderer.domElement.style.position = IStyle.PositionEnum.absolute; renderer.domElement.style.SetLocation(0, 0); Native.document.body.style.overflow = IStyle.OverflowEnum.hidden; // x:\jsc.svn\examples\javascript\synergy\comanchebysiorki\comanchebysiorki\application.cs new { }.With( async delegate { retry: var s = (double)Native.window.Width / 1920.0; Native.document.body.style.transform = "scale(" + s + ")"; Native.document.body.style.transformOrigin = "0% 0%"; await Native.window.async.onresize; goto retry; } ); //#region onresize //Native.window.onresize += // delegate // { // camera.aspect = Native.window.aspect; // camera.updateProjectionMatrix(); // renderer.setSize(window.Width, window.Height); // effect.setSize(window.Width, window.Height); // }; //#endregion //Native.document.body.onmousewheel += // e => // { // fov -= e.WheelDirection * 5.0; // camera.projectionMatrix.makePerspective(fov, // (double)window.Width / window.Height, 1, 1100); // }; var lon0 = -45.0; var lon1 = 0.0; var lon = new sum( () => lon0, () => lon1 ); var lat0 = 0.0; var lat1 = 0.0; // or could we do it with byref or pointers? var lat = new sum( () => lat0, () => lat1 ); var phi = 0.0; var theta = 0.0; //var controls = new THREE.OrbitControls(camera); var camera_rotation_z = 0.0; //Native.document.onmousemove += // e => // { // l.Message = new { e.CursorX, e.CursorY }.ToString(); // }; Native.window.onframe += ee => { //labove.Message = new //{ // lon, // lat, // ee.counter //}.ToString(); //if (Native.document.pointerLockElement == Native.document.body) // lon += 0.00; //else // lon += 0.01; //lat = Math.Max(-85, Math.Min(85, lat)); //Native.document.title = new { lon, lat }.ToString(); phi = THREE.Math.degToRad(90 - lat); theta = THREE.Math.degToRad(lon); target.x = 500 * Math.Sin(phi) * Math.Cos(theta); target.y = 500 * Math.Cos(phi); target.z = 500 * Math.Sin(phi) * Math.Sin(theta); //controls.update(); //camera.position = controls.center.clone(); camera.lookAt(target); camera.rotation.z += camera_rotation_z; renderer.render(scene, camera); //effect.render(scene, camera); }; // http://blog.thematicmapping.org/2013/10/terrain-visualization-with-threejs-and.html // http://stackoverflow.com/questions/13278087/determine-vertical-direction-of-a-touchmove var compassHeadingOffset = 0.0; var compassHeadingInitialized = 0; #region compassHeading // X:\jsc.svn\examples\javascript\android\Test\TestCompassHeading\TestCompassHeading\Application.cs Native.window.ondeviceorientation += dataValues => { // Convert degrees to radians var alphaRad = dataValues.alpha * (Math.PI / 180); var betaRad = dataValues.beta * (Math.PI / 180); var gammaRad = dataValues.gamma * (Math.PI / 180); // Calculate equation components var cA = Math.Cos(alphaRad); var sA = Math.Sin(alphaRad); var cB = Math.Cos(betaRad); var sB = Math.Sin(betaRad); var cG = Math.Cos(gammaRad); var sG = Math.Sin(gammaRad); // Calculate A, B, C rotation components var rA = -cA * sG - sA * sB * cG; var rB = -sA * sG + cA * sB * cG; var rC = -cB * cG; // Calculate compass heading var compassHeading = Math.Atan(rA / rB); // Convert from half unit circle to whole unit circle if (rB < 0) { compassHeading += Math.PI; } else if (rA < 0) { compassHeading += 2 * Math.PI; } /* Alternative calculation (replacing lines 99-107 above): var compassHeading = Math.atan2(rA, rB); if(rA < 0) { compassHeading += 2 * Math.PI; } */ // Convert radians to degrees compassHeading *= 180 / Math.PI; // Compass heading can only be derived if returned values are 'absolute' // X:\jsc.svn\examples\javascript\android\Test\TestCompassHeadingWithReset\TestCompassHeadingWithReset\Application.cs //Native.document.body.innerText = new { compassHeading }.ToString(); if (compassHeadingInitialized > 0) { lon1 = compassHeading - compassHeadingOffset; } else { compassHeadingOffset = compassHeading; compassHeadingInitialized++; } }; #endregion #region gamma Native.window.ondeviceorientation += //e => Native.body.innerText = new { e.alpha, e.beta, e.gamma }.ToString(); //e => lon = e.gamma; e => { lat1 = e.gamma; // after servicing a running instance would be nice // either by patching or just re running the whole iteration in the backgrou camera_rotation_z = e.beta * 0.02; }; #endregion #region camera rotation var old = new { clientX = 0, clientY = 0 }; Native.document.body.ontouchstart += e => { var n = new { e.touches[0].clientX, e.touches[0].clientY }; old = n; }; Native.document.body.ontouchmove += e => { var n = new { e.touches[0].clientX, e.touches[0].clientY }; e.preventDefault(); lon0 += (n.clientX - old.clientX) * 0.2; lat0 -= (n.clientY - old.clientY) * 0.2; old = n; }; Native.document.body.onmousemove += e => { e.preventDefault(); if (Native.document.pointerLockElement == Native.document.body) { lon0 += e.movementX * 0.1; lat0 -= e.movementY * 0.1; //Console.WriteLine(new { lon, lat, e.movementX, e.movementY }); } }; Native.document.body.onmouseup += e => { //drag = false; e.preventDefault(); }; Native.document.body.onmousedown += e => { //e.CaptureMouse(); //drag = true; e.preventDefault(); Native.document.body.requestPointerLock(); }; Native.document.body.ondblclick += e => { e.preventDefault(); Console.WriteLine("requestPointerLock"); }; #endregion Native.body.onmousewheel += e => { camera_rotation_z += 0.1 * e.WheelDirection; ; }; // https://developer.android.com/training/system-ui/immersive.html //var ze = new ZeProperties(); //ze.Show(); //ze.treeView1.Nodes.Clear(); //ze.Add(() => renderer); ////ze.Add(() => controls); //ze.Add(() => scene); //ze.Left = 0; }
/// <summary> /// This is a javascript application. /// </summary> /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param> public Application(IApp page) { page.clear.WhenClicked( delegate { //page.search.Clear(); page.search.value = ""; } ); new IHTMLButton { innerText = "Install" }.AttachToDocument().With( btn => { // http://help.adobe.com/en_US/air/build/WSfffb011ac560372f-5d0f4f25128cc9cd0cb-7ffd.html btn.onclick += delegate { service.Install("assets/AndroidListApplications/foo.apk"); }; } ); var items = new { div = default(IHTMLDiv), packageName = "", name = "", Remove = default(IHTMLButton), Launch = default(IHTMLButton) }.ToEmptyList(); Action queryIntentActivities = async delegate { var a = new List<string>(); // Send data from JavaScript to the server tier await service.queryIntentActivities( yield: (packageName, name, icon_base64, label) => { #region yield a.Add(packageName); // already have it if (items.Any(k => k.packageName == packageName)) return; var div = new IHTMLDiv(); div.style.margin = "1em"; if (Native.Document.body.firstChild == null) div.AttachToDocument(); else Native.Document.body.insertBefore(div, Native.Document.body.firstChild); new IHTMLImage { src = "data:image/png;base64," + icon_base64 }.AttachTo(div); new IHTMLSpan { innerText = label }.AttachTo(div); var Remove = new IHTMLButton { innerText = "Remove" }.AttachTo(div).WhenClicked( btn => { // http://help.adobe.com/en_US/air/build/WSfffb011ac560372f-5d0f4f25128cc9cd0cb-7ffd.html if (!Native.window.confirm("Remove " + name + "?")) return; service.Remove(packageName, name); } ); //div.appendChild(new { icon_base64.Length }.ToString()); var Launch = new IHTMLButton { innerText = "Launch" }.AttachTo(div).WhenClicked( btn => { // http://help.adobe.com/en_US/air/build/WSfffb011ac560372f-5d0f4f25128cc9cd0cb-7ffd.html service.Launch(packageName, name); } ); var LaunchFloat = new IHTMLButton { innerText = "Launch Float" }.AttachTo(div).WhenClicked( btn => { service.Launch(packageName, name, ExtraKey: "Float", ExtraValue: "Float" ); } ); // var LaunchWebService = new IHTMLButton { innerText = "Launch WebService" }.AttachTo(div).WhenClicked( // btn => // { // //service.Launch(packageName, name); // } //); var item = new { div, packageName, name, Remove, Launch }; items.Add(item); //https://play.google.com/store/apps/details?id=com.abstractatech.battery new IHTMLAnchor { href = "https://play.google.com/store/apps/details?id=" + packageName, innerText = name }.AttachTo(div); #endregion } ); items.WithEach( item => { if (a.Contains(item.packageName)) return; item.div.style.color = "red"; item.Launch.disabled = true; item.Remove.disabled = true; } ); // remove others! }; queryIntentActivities(); new Timer( delegate { items.WithEach( item => { if (string.IsNullOrEmpty(page.search.value)) { item.div.Show(); } else { if (item.packageName.Contains(page.search.value)) { item.div.Show(); } else { item.div.Hide(); } } } ); queryIntentActivities(); } ).StartInterval(2000); }
/// <summary> /// This is a javascript application. /// </summary> /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param> public Application(IApp page) { var y = page.ThePath_y; var x = page.ThePath_x; var z = page.ThePath_z; page.TheText.textContent = "pointer lock movement"; // script: error JSC1000: No implementation found for this native method, please implement [static Microsoft.CSharp.RuntimeBinder.Binder.IsEvent(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, System.String, System.Type)] //pp.setAttribute("d", pp.getAttribute("d") + " l100,-10 "); var history = new { x = 0.0, y = 0.0, z = 0.0 }.ToEmptyList(); 50.Times( delegate { history.Add( // vec2? new { x = 0.0, y = 0.0, z = 0.0 } ); } ); var movementX = 0.0; var movementY = 0.0; var movementZ = 0.0; Native.Document.body.onmousedown += e => { Native.Document.body.requestPointerLock(); }; Native.Document.body.onmousemove += e => { if (Native.Document.body == Native.Document.pointerLockElement) { movementX += e.movementX; movementY += e.movementY; } }; new ScriptCoreLib.JavaScript.Runtime.Timer( delegate { history.Add( // vec2? new { x = movementX, y = movementY, z = movementZ } ); movementX = 0; movementY = 0; movementZ = 0; if (history.Count > 500) { history.RemoveAt(0); } // http://www.w3.org/TR/SVG/paths.html#PathDataMovetoCommands var xw = new StringBuilder().Append("M10,200 "); var yw = new StringBuilder().Append("M10,300 "); var zw = new StringBuilder().Append("M10,400 "); history.WithEachIndex( (p, i) => { xw.Append(" L" + (10 + 2 * i) + "," + (p.x + 200)); yw.Append(" L" + (10 + 2 * i) + "," + (p.y + 300)); zw.Append(" L" + (10 + 2 * i) + "," + (p.z + 400)); } ); xw.Append(" L" + (10 + 2 * history.Count) + "," + (201)); yw.Append(" L" + (10 + 2 * history.Count) + "," + (301)); zw.Append(" L" + (10 + 2 * history.Count) + "," + (401)); //Console.WriteLine(new { xw, yw }); y.d = yw.ToString(); x.d = xw.ToString(); z.d = zw.ToString(); } ).StartInterval(1000 / 10); Native.Document.onkeydown += delegate { movementZ = 100; }; Native.Document.onkeyup += delegate { movementZ = 0; }; Native.window.ondeviceorientation += eventData => { movementX = eventData.alpha; movementY = eventData.beta; movementZ = eventData.gamma; }; }
/// <summary> /// This is a javascript application. /// </summary> /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param> public Application(IApp page) { var random = new Random(); device_id = random.Next(); #region con var con = new ConsoleForm(); con.InitializeConsoleFormWriter(); con.StartPosition = FormStartPosition.Manual; con.Show(); // make it slim con.Height = 100; // TopMost con.GetHTMLTarget().style.zIndex = 20002; con.Opacity = 0.9; Action Toggle = delegate { if (con.WindowState == FormWindowState.Minimized) { con.WindowState = FormWindowState.Normal; } else { con.WindowState = FormWindowState.Minimized; } // put the console far right bottom con.MoveTo( Native.window.Width - con.Width, Native.window.Height - con.Height ); }; Action<int> AtKeyCode = KeyCode => { Console.WriteLine( new { KeyCode } ); // US if (KeyCode == 222) { Toggle(); } // EE if (KeyCode == 192) { Toggle(); } }; #if onorientationchange Native.window.onorientationchange += e => { Toggle(); }; #endif Native.document.onkeyup += e => { AtKeyCode(e.KeyCode); }; Toggle(); #endregion Console.WriteLine("console ready for " + new { id = device_id }); var x = 0; var y = 0; #region Virtual Screen FormStyler.AtFormCreated = LikeDesktop; var fs = new Form { }; //fs.FormBorderStyle = FormBorderStyle.None; fs.BackColor = Color.FromArgb(0, 148, 155); fs.Width = Native.screen.width / 4; fs.Height = Native.screen.height / 4; fs.Show(); fs.Opacity = 0.5; FormStyler.AtFormCreated = LikeVirtualScreen; var fvs = new Form { Text = "Virtual Screen" }; fvs.BackColor = Color.Transparent; FormStyler.AtFormCreated = FormStyler.LikeWindowsClassic; fvs.Width = Native.screen.width / 4; fvs.Height = Native.screen.height / 4; fvs.Show(); fvs.Owner = fs; var fw = new Form { }; fw.Width = Native.window.Width / 4; fw.Height = Native.window.Height / 4; fw.Show(); fw.Owner = fvs; fw.Opacity = 0.8; KeepOwnedFormsLinkedToOwnerLocation(fs); KeepOwnedFormsLinkedToOwnerLocation(fvs); KeepOwnedFormsLinkedToOwnerLocation(fw); #endregion // doesnt work yet? //fw.SizeGripStyle = SizeGripStyle.Hide; var svg = new ISVGSVGElement().AttachTo(page.content); svg.style.SetLocation(0, 0); var vsvg = new ISVGSVGElement().AttachTo(fvs.GetHTMLTarget()); vsvg.style.SetLocation(0, 0); #region VirtualScreenUpdate Action VirtualScreenUpdate = delegate { if (fs.Capture) return; // dragging it? if (fvs.Capture) return; var max_right = fvs.OwnedForms.Max(k => k.Right); var min_left = fvs.OwnedForms.Min(k => k.Left); var max_bottom = fvs.OwnedForms.Max(k => k.Bottom); var min_top = fvs.OwnedForms.Min(k => k.Top); DisableKeepOwnedFormsLinkedToOwnerLocation = true; fvs.Left = min_left; fvs.Top = min_top; fvs.Width = max_right - min_left; fvs.Height = max_bottom - min_top; page.content.style.SetLocation( (min_left - fw.Left) * 4, (min_top - fw.Top) * 4, (max_right - min_left) * 4, (max_bottom - min_top) * 4 ); DisableKeepOwnedFormsLinkedToOwnerLocation = false; }; #endregion fw.LocationChanged += delegate { VirtualScreenUpdate(); }; #region AtResize Action AtResize = delegate { // screen can change, but only once, when window is moved to the other monitor? fs.Text = "Screen " + new { Native.screen.width, Native.screen.height }; fs.Width = Native.screen.width / 4; fs.Height = Native.screen.height / 4; fw.Text = " " + new { Native.window.Width, Native.window.Height #if onorientationchange , Native.window.orientation #endif }; fw.Width = Native.window.Width / 4; fw.Height = Native.window.Height / 4; VirtualScreenUpdate(); }; Native.window.onresize += delegate { AtResize(); }; Native.window.onfocus += delegate { AtResize(); }; Native.window.onblur += delegate { AtResize(); }; new ScriptCoreLib.JavaScript.Runtime.Timer( delegate { AtResize(); } ).StartInterval(1000 / 2); #endregion // what is attaching what? // what about await var svgcursor1ghost = new cursor1().AttachTo(page.content).ToSVG(); var svgcursor1 = new cursor1().AttachTo(page.content).ToSVG(); svgcursor1.fill += svgcursor1ghost.fill; var vcursor = new cursor1().AttachTo(fvs.GetHTMLTarget()).ToSVG(); var Shadows = new List<Form>(); Func<Form, Form> CreateShadow = _fw => { FormStyler.AtFormCreated = LikeVirtualWindow; var fwshadow = new Form(); Shadows.Add(fwshadow); fwshadow.BackColor = Color.Transparent; FormStyler.AtFormCreated = FormStyler.LikeWindowsClassic; fwshadow.Width = Native.screen.width / 4; fwshadow.Height = Native.screen.height / 4; fwshadow.Show(); Action fwshadow_update = delegate { fwshadow.MoveTo(_fw.Left, _fw.Top); fwshadow.SizeTo(_fw.Width, _fw.Height); }; _fw.LocationChanged += delegate { fwshadow_update(); }; _fw.SizeChanged += delegate { fwshadow_update(); }; fwshadow_update(); _fw.BringToFront(); return fwshadow; }; Shadows.Add(CreateShadow(fw)); bool canexit = false; bool canenter = true; Action at_exit_MultiMouseMode = delegate { //Console.WriteLine("at_exit_MultiMouseMode"); }; Action at_enter_MultiMouseMode = delegate { //Console.WriteLine("at_enter_MultiMouseMode"); }; Action<IEvent.MouseButtonEnum> at_mousedown = button => { //Console.WriteLine("at_enter_mousedown: " + button); }; Action at_mouseup = delegate { //Console.WriteLine("at_enter_mouseup"); }; var path = new ISVGPathElement().AttachTo(svg); path.setAttribute("style", "stroke: black; stroke-width: 4; fill: none;"); var path_d = ""; var vpath = new ISVGPathElement().AttachTo(vsvg); vpath.setAttribute("style", "stroke: black; stroke-width: 1; fill: none;"); var vpath_d = ""; bool internal_ismousedown = false; Action<IEvent.MouseButtonEnum> internal_mousedown = button => { internal_ismousedown = true; path = new ISVGPathElement().AttachTo(svg); if (button == IEvent.MouseButtonEnum.Left) path.setAttribute("style", "stroke: black; stroke-width: 4; fill: none;"); else path.setAttribute("style", "stroke: rgb(0, 108, 115); stroke-width: 32; fill: none;"); path_d = ""; vpath = new ISVGPathElement().AttachTo(vsvg); if (button == IEvent.MouseButtonEnum.Left) vpath.setAttribute("style", "stroke: black; stroke-width: 1; fill: none;"); else vpath.setAttribute("style", "stroke: rgb(0, 108, 115); stroke-width: 8; fill: none;"); vpath_d = ""; svgcursor1.fill(0, 0, 255); vcursor.fill(0, 0, 255); //path.d = " M100,50 L10,10 L200,200 "; path_d += " M" + x + "," + y; path.d = path_d; vpath_d += " M" + (x / 4) + "," + (y / 4); vpath.d = vpath_d; }; Action<IEvent.MouseButtonEnum> mousedown = button => { at_mousedown(button); internal_mousedown(button); }; Action internal_mouseup = delegate { internal_ismousedown = false; svgcursor1.fill(0, 255, 0); vcursor.fill(0, 255, 0); }; Action mouseup = delegate { at_mouseup(); internal_mouseup(); }; #region exit_MultiMouseMode Action internal_exit_MultiMouseMode = delegate { svgcursor1.fill(0, 0, 0); vcursor.fill(0, 0, 0); con.Opacity = 0.9; page.content.style.Opacity = 0.3; page.content.style.zIndex = 0; page.content.style.backgroundColor = "rgba(0, 148, 155, 1)"; Native.Document.body.style.backgroundColor = "black"; page.content.style.With( (dynamic s) => { s.webkitFilter = "blur(3px)"; } ); page.info.style.With( (dynamic s) => { s.webkitFilter = ""; } ); Shadows.WithEach( f => f.GetHTMLTarget().style.With( (dynamic s) => { s.webkitFilter = ""; } ) ); fs.FormsByOwnership().WithEach( f => f.GetHTMLTarget().style.With( (dynamic s) => { s.webkitFilter = ""; } ) ); fvs.OwnedForms.WithEach( k => { k.GetHTMLTarget().style.display = IStyle.DisplayEnum.block; } ); }; Action exit_MultiMouseMode = delegate { if (!canexit) return; canexit = false; canenter = true; at_exit_MultiMouseMode(); internal_exit_MultiMouseMode(); }; #endregion #region enter_MultiMouseMode Action internal_enter_MultiMouseMode = delegate { svgcursor1.fill(255, 0, 0); vcursor.fill(255, 0, 0); con.Opacity = 0.5; page.content.style.Opacity = 1.0; page.content.style.backgroundColor = ""; Native.Document.body.style.backgroundColor = "rgba(0, 148, 155, 1)"; page.content.style.zIndex = 20000; con.GetHTMLTarget().style.zIndex = 20002; page.content.style.With( (dynamic s) => { s.webkitFilter = ""; } ); page.info.style.With( (dynamic s) => { s.webkitFilter = "blur(3px)"; } ); fvs.OwnedForms.WithEach( k => { k.GetHTMLTarget().style.display = IStyle.DisplayEnum.none; } ); Shadows.WithEach( f => f.GetHTMLTarget().style.With( (dynamic s) => { s.webkitFilter = "blur(3px)"; } ) ); fs.FormsByOwnership().WithEach( f => f.GetHTMLTarget().style.With( (dynamic s) => { s.webkitFilter = "blur(3px)"; } ) ); }; Action enter_MultiMouseMode = delegate { if (!canenter) return; canexit = true; canenter = false; at_enter_MultiMouseMode(); internal_enter_MultiMouseMode(); }; #endregion #region onmousemove Native.Document.body.onmouseup += e => { if (Native.Document.pointerLockElement == Native.Document.body) { mouseup(); return; } }; Native.Document.body.onmousedown += e => { if (Native.Document.pointerLockElement == Native.Document.body) { mousedown(e.MouseButton); return; } Console.WriteLine("requesting MultiMouse mode!"); x = e.CursorX; y = e.CursorY; e.preventDefault(); Native.Document.body.requestPointerLock(); }; Action<int, int> at_set_cursor_position = delegate { }; var pxx = 0; var pyy = 0; var ghost_busy = false; Action<int, int> internal_set_cursor_position = (xx, yy) => { // already set to that exact location! if (pxx == xx) if (pyy == yy) return; pxx = xx; pyy = yy; vcursor.Element.style.SetSize( cursor1.ImageDefaultWidth / 4, cursor1.ImageDefaultHeight / 4 ); vcursor.Element.style.SetLocation( (xx - 14) / 4, (yy - (64 - 56)) / 4 ); svgcursor1.Element.style.SetLocation( xx - 14, // inscaope/svg Y is upside down! yy - (64 - 56) ); if (!ghost_busy) { ghost_busy = true; svgcursor1ghost.Element.style.Opacity = 0.2; svgcursor1ghost.Element.style.With( (dynamic s) => s.webkitTransition = "all 0.5s linear" ); svgcursor1ghost.Element.style.SetLocation( pxx - 14, // inscaope/svg Y is upside down! pyy - (64 - 56) ); new ScriptCoreLib.JavaScript.Runtime.Timer( delegate { svgcursor1ghost.Element.style.SetLocation( pxx - 14, // inscaope/svg Y is upside down! pyy - (64 - 56) ); ghost_busy = false; } ).StartTimeout(500); } // if this window will be activated next time we can continue where we were // told to.. x = xx; y = yy; if (internal_ismousedown) { path_d += " L" + x + "," + y; path.d = path_d; vpath_d += " L" + (x / 4) + "," + (y / 4); vpath.d = vpath_d; } }; Action<int, int> set_cursor_position = (xx, yy) => { at_set_cursor_position(xx, yy); internal_set_cursor_position(xx, yy); }; Native.Document.body.onmousemove += e => { if (Native.Document.pointerLockElement == Native.Document.body) { enter_MultiMouseMode(); x += e.movementX; y += e.movementY; // clip it // fullscreen behaves differently? x = x.Min(fvs.Width * 4).Max(0); y = y.Min(fvs.Height * 4).Max(0); set_cursor_position(x, y); } else { exit_MultiMouseMode(); } }; #endregion internal_exit_MultiMouseMode(); internal_set_cursor_position(0, 0); Native.document.body.ontouchstart += e => { e.preventDefault(); e.stopPropagation(); e.touches[0].With( touch => { // how do we enter? enter_MultiMouseMode(); // exit by broswer history move? set_cursor_position(touch.clientX, touch.clientY); // ipad has 11 touchpoints. multiply that with the number of devices/ // for now we support 1 pointer per session :) if (e.touches.length == 1) mousedown(IEvent.MouseButtonEnum.Left); else mousedown(IEvent.MouseButtonEnum.Right); } ); }; Native.document.body.ontouchend += e => { e.preventDefault(); e.stopPropagation(); // ipad has 11 touchpoints. multiply that with the number of devices/ // for now we support 1 pointer per session :) if (e.touches.length == 0) mouseup(); else mousedown(IEvent.MouseButtonEnum.Left); }; Native.document.body.ontouchmove += e => { e.preventDefault(); e.stopPropagation(); e.touches[0].With( touch => { set_cursor_position(touch.clientX, touch.clientY); } ); }; #region onmessage bool disable_bind_reconfigure = false; Action<int, int> internal_reconfigure = delegate { }; Action<MessageEvent, XElement> internal_onmessage = (e, xml) => { device_onmessage(0, xml); }; Native.window.onmessage += e => { // who sent this? :P var source = (string)e.data; //var now = DateTime.Now; //Console.WriteLine(now + " " + source); var xml = XElement.Parse(source); internal_onmessage(e, xml); }; var friendly_devices = new { source_device_id = 0, f = default(Form), children = new { child_id = 0, fc = default(Form) }.ToEmptyList() }.ToEmptyList(); #region device_onmessage this.device_onmessage = (source_device_id, xml) => { // mothership to local network? // source_device_id = 0 means it came from one of our virtual screens? if (xml.Name.LocalName == "at_mousedown") { int button = int.Parse(xml.Attribute("button").Value); internal_mousedown((IEvent.MouseButtonEnum)button); } if (xml.Name.LocalName == "at_mouseup") { internal_mouseup(); } if (xml.Name.LocalName == "at_enter_MultiMouseMode") { internal_enter_MultiMouseMode(); } if (xml.Name.LocalName == "at_exit_MultiMouseMode") { internal_exit_MultiMouseMode(); } if (xml.Name.LocalName == "at_set_cursor_position") { int xx = int.Parse(xml.Attribute("x").Value); int yy = int.Parse(xml.Attribute("y").Value); internal_set_cursor_position(xx, yy); } }; #endregion var ListOfChildren = new { child_id = 0, fc = default(Form) }.ToEmptyList(); // when is this called? this.device_bind = (mothership_postXElement) => { // we might now be able to invoke the server, and via that any other device Console.WriteLine("device_bind"); #region at_enter_MultiMouseMode at_enter_MultiMouseMode += delegate { var xml = new XElement("at_enter_MultiMouseMode"); mothership_postXElement(xml); }; #endregion #region at_exit_MultiMouseMode at_exit_MultiMouseMode += delegate { mothership_postXElement(new XElement("at_exit_MultiMouseMode")); }; #endregion #region at_mousedown at_mousedown += button => { mothership_postXElement(new XElement("at_mousedown", new XAttribute("button", "" + (int)button))); }; #endregion #region at_mouseup at_mouseup += delegate { mothership_postXElement(new XElement("at_mouseup")); }; #endregion #region at_set_cursor_position at_set_cursor_position += (xx, yy) => { var xml = new XElement("at_set_cursor_position", // int not yet supported? new XAttribute("x", "" + xx), new XAttribute("y", "" + yy) ); mothership_postXElement( xml ); }; #endregion // now we can reply.. this.device_onmessage += (source_device_id, xml) => { #region at_virtualwindowsync_reconfigure if (source_device_id != 0) if (xml.Name.LocalName == "at_virtualwindowsync_reconfigure") { int __device_id = int.Parse(xml.Attribute("device_id").Value); if (__device_id == device_id) { // are we being reconfigured? friendly_devices.Where(k => k.source_device_id == source_device_id).WithEach( q => { int dx = int.Parse(xml.Attribute("dx").Value); int dy = int.Parse(xml.Attribute("dy").Value); disable_bind_reconfigure = true; q.f.MoveTo( fw.Left - dx, fw.Top - dy ); disable_bind_reconfigure = false; } ); } } #endregion #region at_virtualwindowsync if (source_device_id != 0) if (xml.Name.LocalName == "at_virtualwindowsync") { Console.WriteLine("got at_virtualwindowsync"); // do we know this device? var q = friendly_devices.FirstOrDefault(k => k.source_device_id == source_device_id); int w = int.Parse(xml.Attribute("w").Value); int h = int.Parse(xml.Attribute("h").Value); Action reposition = delegate { }; if (q == null) { var fc = new Form { Text = new { source_device_id }.ToString() }; q = new { source_device_id, f = fc, children = new { child_id = 0, fc = default(Form) }.ToEmptyList() }; friendly_devices.Add(q); q.f.StartPosition = FormStartPosition.Manual; q.f.Show(); // show should respect opacity? q.f.Opacity = 0.3; // where to put it? // left or right? var max_right = fvs.OwnedForms.Max(k => k.Right); var min_left = fvs.OwnedForms.Min(k => k.Left); if (source_device_id < device_id) q.f.Left = min_left - w; else q.f.Left = max_right; q.f.Top = fw.Top; q.f.Owner = fvs; var fcShadow = CreateShadow(q.f); Shadows.Add(fcShadow); #region from now on if we move any of our screens // in relation to this source_device_id we have to notify it Action SendDelta = delegate { var pdx = fc.Left - fw.Left; var pdy = fc.Top - fw.Top; mothership_postXElement( new XElement("at_virtualwindowsync_reconfigure", new XAttribute("device_id", "" + source_device_id), new XAttribute("dx", "" + pdx), new XAttribute("dy", "" + pdy) ) ); }; fw.LocationChanged += delegate { if (disable_bind_reconfigure) return; SendDelta(); }; fc.LocationChanged += delegate { if (disable_bind_reconfigure) return; SendDelta(); }; #endregion } // thanks for letting us know that you changed your size... q.f.Width = w; q.f.Height = h; xml.Elements("child").WithEach( cxml => { // any new children? int child_id = int.Parse(cxml.Attribute("child_id").Value); int pdx = int.Parse(cxml.Attribute("pdx").Value); int pdy = int.Parse(cxml.Attribute("pdy").Value); int cw = int.Parse(cxml.Attribute("w").Value); int ch = int.Parse(cxml.Attribute("h").Value); var cq = q.children.FirstOrDefault(k => k.child_id == child_id); if (cq == null) { var fc = new Form { Text = new { source_device_id, child_id }.ToString() }; cq = new { child_id, fc }; q.children.Add(cq); cq.fc.StartPosition = FormStartPosition.Manual; cq.fc.Show(); // show should respect opacity? cq.fc.Opacity = 0.2; // if this child needs to be between then add it // before reposition cq.fc.Owner = fvs; var fcShadow = CreateShadow(cq.fc); Shadows.Add(fcShadow); } cq.fc.Left = q.f.Left + pdx; cq.fc.Top = q.f.Top + pdy; // thanks for letting us know that you changed your size... cq.fc.Width = cw; cq.fc.Height = ch; } ); } #endregion }; // lets tell the world about virtual screens owned by us. // lets start by advertising our size. #region at_virtualwindowsync var t = new ScriptCoreLib.JavaScript.Runtime.Timer( delegate { // do we know whats the dx to other windows? var xml = new XElement("at_virtualwindowsync", // int not yet supported? new XAttribute("w", "" + fw.Width), new XAttribute("h", "" + fw.Height) ); #region what about children? ListOfChildren.WithEach( c => { var pdx = c.fc.Left - fw.Left; var pdy = c.fc.Top - fw.Top; xml.Add( new XElement("child", new XAttribute("child_id", "" + c.child_id), // int not yet supported? new XAttribute("pdx", "" + pdx), new XAttribute("pdy", "" + pdy), new XAttribute("w", "" + c.fc.Width), new XAttribute("h", "" + c.fc.Height) ) ); } ); #endregion mothership_postXElement( xml ); Console.WriteLine("sent at_virtualwindowsync"); } ); t.StartInterval(5000); #endregion }; Action<IWindow, Form> bind = (w, fc) => { this.device_bind(w.postXElement); internal_onmessage += (e, xml) => { if (xml.Name.LocalName == "reconfigure") { // how do we know this reconfigrue event is for us? if (e.source == w) { disable_bind_reconfigure = true; int dx = int.Parse(xml.Attribute("dx").Value); int dy = int.Parse(xml.Attribute("dy").Value); //Console.WriteLine("reconfigure " + new { dx, dy, fw.Left }); //fw.Left += dx; //fw.Top += dy; fc.MoveTo( fw.Left - dx, fw.Top - dy ); disable_bind_reconfigure = false; } } }; Action SendDelta = delegate { var pdx = fc.Left - fw.Left; var pdy = fc.Top - fw.Top; w.postXElement( new XElement("reconfigure", new XAttribute("dx", "" + pdx), new XAttribute("dy", "" + pdy) ) ); }; fw.LocationChanged += delegate { if (disable_bind_reconfigure) return; SendDelta(); }; fc.LocationChanged += delegate { if (disable_bind_reconfigure) return; SendDelta(); }; }; #endregion #region opener Native.window.opener.With( w => { // disable features page.info.Hide(); Console.WriteLine("we have opener: " + w.document.location.href); var fc = new Form { Text = "opener" }; fc.Owner = fvs; Action cAtResize = delegate { fc.Text = "Opener " + new { w.Width, w.Height }; fc.Width = w.Width / 4; fc.Height = w.Height / 4; }; w.onresize += delegate { cAtResize(); }; var ct = new ScriptCoreLib.JavaScript.Runtime.Timer( delegate { cAtResize(); } ); ct.StartInterval(1000 / 15); cAtResize(); fc.StartPosition = FormStartPosition.Manual; fc.Show(); fc.Opacity = 0.7; fc.BackColor = Color.Transparent; var fcShadow = CreateShadow(fc); Shadows.Add(fcShadow); Native.window.requestAnimationFrame += delegate { // ScriptCoreLib Windows Forms has a few bugs:P fc.MoveTo(fw.Left - fc.Width, fw.Top); bind(w, fc); }; } ); #endregion #region make info clickable page.info.onmousedown += e => { if (internal_ismousedown) return; e.stopPropagation(); }; page.info.ontouchstart += e => { if (internal_ismousedown) return; e.stopPropagation(); }; page.info.ontouchmove += e => { if (internal_ismousedown) return; e.stopPropagation(); }; page.info.ontouchend += e => { if (internal_ismousedown) return; e.stopPropagation(); }; #endregion #region OpenChildSession page.OpenChildSession.onclick += e => { e.preventDefault(); Console.WriteLine("open child session..."); Native.window.open( Native.Document.location.href, "_blank", 400, 400, true).With( w => { w.onload += delegate { if (w.document.location.href == "about:blank") return; Console.WriteLine("child onload " + w.document.location.href); var fc = new Form { Text = "child" }; Action cAtResize = delegate { fc.Text = "Child " + new { w.Width, w.Height }; fc.Width = w.Width / 4; fc.Height = w.Height / 4; VirtualScreenUpdate(); }; w.onresize += delegate { cAtResize(); }; var ct = new ScriptCoreLib.JavaScript.Runtime.Timer( delegate { cAtResize(); } ); ct.StartInterval(1000 / 2); //cAtResize(); fc.StartPosition = FormStartPosition.Manual; fc.Show(); fc.Opacity = 0.5; // first child could be a monitor to our right fc.MoveTo(fw.Right, fw.Top); fc.Owner = fvs; fc.BackColor = Color.Transparent; fc.Width = 400 / 4; fc.Height = 400 / 4; VirtualScreenUpdate(); fc.LocationChanged += delegate { VirtualScreenUpdate(); }; var fcShadow = CreateShadow(fc); Shadows.Add(fcShadow); var token = new { child_id = random.Next(), fc }; ListOfChildren.Add(token); #region FormClosing w.onbeforeunload += delegate { if (fc == null) return; w = null; ct.Stop(); fc.Close(); fc = null; }; Native.window.onbeforeunload += delegate { if (w == null) return; w.close(); w = null; }; fc.FormClosing += delegate { if (w == null) return; ListOfChildren.Remove(token); Shadows.Remove(fcShadow); fc = null; w.close(); w = null; }; #endregion bind(w, fc); }; } ); }; #endregion Native.document.documentElement.style.overflow = IStyle.OverflowEnum.hidden; }