[gtk+] [broadway] Add some initial work for in-window frames



commit 618dc872b048804ba4214035a6c4777851a50865
Author: Alexander Larsson <alexl redhat com>
Date:   Fri Apr 8 11:45:51 2011 +0200

    [broadway] Add some initial work for in-window frames
    
    The css is based on work by Jasper St Pierre:
    http://magcius.mecheye.net/vista/

 gdk/broadway/broadway.js |  155 ++++++++++++++++++++++++++++++++++++++++------
 gdk/broadway/client.html |   60 ++++++++++++++++++
 2 files changed, 196 insertions(+), 19 deletions(-)
---
diff --git a/gdk/broadway/broadway.js b/gdk/broadway/broadway.js
index 4a9b054..167834b 100644
--- a/gdk/broadway/broadway.js
+++ b/gdk/broadway/broadway.js
@@ -107,12 +107,13 @@ function resizeCanvas(canvas, w, h)
     context.drawImage(tmpCanvas, 0, 0, tmpCanvas.width, tmpCanvas.height);
 }
 
-var useToplevelWindows = true;
+var useToplevelWindows = false;
 var toplevelWindows = [];
 var grab = new Object();
 grab.window = null;
 grab.ownerEvents = false;
 grab.implicit = false;
+var localGrab = null;
 var lastSerial = 0;
 var lastX = 0;
 var lastY = 0;
@@ -126,7 +127,6 @@ var inputSocket = null;
 var frameSizeX = -1;
 var frameSizeY = -1;
 
-
 var GDK_CROSSING_NORMAL = 0;
 var GDK_CROSSING_GRAB = 1;
 var GDK_CROSSING_UNGRAB = 2;
@@ -321,6 +321,18 @@ function getTransientToplevel(surface)
     return null;
 }
 
+function getFrameOffset(surface) {
+    var x = 1;
+    var y = 1;
+    var el = surface.canvas;
+    while (el != null && el != surface.frame) {
+	x += el.offsetLeft;
+	y += el.offsetTop;
+	el = el.offsetParent;
+    }
+    return {x: x, y: y};
+}
+
 function cmdCreateSurface(id, x, y, width, height, isTemp)
 {
     var surface = { id: id, x: x, y:y, width: width, height: height, isTemp: isTemp };
@@ -330,18 +342,49 @@ function cmdCreateSurface(id, x, y, width, height, isTemp)
     surface.window = null;
     surface.document = document;
     surface.transientToplevel = null;
+    surface.frame = null;
 
     var canvas = document.createElement("canvas");
     canvas.width = width;
     canvas.height = height;
     canvas.surface = surface;
-    canvas.style["position"] = "absolute";
-    canvas.style["left"] = "0px";
-    canvas.style["top"] = "0px";
-    canvas.style["display"] = "none";
-    document.body.appendChild(canvas);
     surface.canvas = canvas;
 
+    if (useToplevelWindows || isTemp) {
+	canvas.style["position"] = "absolute";
+	canvas.style["left"] = "0px";
+	canvas.style["top"] = "0px";
+	canvas.style["display"] = "none";
+	document.body.appendChild(canvas);
+    } else {
+	var frame = document.createElement("div");
+	frame.frameFor = surface;
+	frame.style["position"] = "absolute";
+	frame.style["left"] = "0px";
+	frame.style["top"] = "0px";
+	frame.style["display"] = "inline";
+	// We hide the frame with visibility rather than display none
+	// so getFrameOffset still works with hidden windows
+	frame.style["visibility"] = "hidden";
+	frame.className = "frame-window";
+
+	var button = document.createElement("center");
+	var X = document.createTextNode("X");
+	button.appendChild(X);
+	button.className = "frame-close";
+	frame.appendChild(button);
+
+	var contents = document.createElement("div");
+	contents.className = "frame-contents";
+	frame.appendChild(contents);
+
+	document.body.appendChild(frame);
+	contents.appendChild(canvas);
+	canvas.style["display"] = "block";
+
+	surface.frame = frame;
+    }
+
     var context = canvas.getContext("2d");
     context.globalCompositeOperation = "source-over";
     surface.context = context;
@@ -357,6 +400,7 @@ function cmdShowSurface(id)
 	return;
     surface.visible = true;
 
+    var element = surface.canvas;
     var xOffset = surface.x;
     var yOffset = surface.y;
 
@@ -387,12 +431,21 @@ function cmdShowSurface(id)
 	}
 
 	ensureSurfaceInDocument(surface, doc);
+    } else {
+	if (surface.frame) {
+	    element = surface.frame;
+	    var offset = getFrameOffset(surface);
+	    xOffset -= offset.x;
+	    yOffset -= offset.y;
+	}
     }
 
-    surface.canvas.style["position"] = "absolute";
-    surface.canvas.style["left"] = xOffset + "px";
-    surface.canvas.style["top"] = yOffset + "px";
-    surface.canvas.style["display"] = "inline";
+    element.style["position"] = "absolute";
+    element.style["left"] = xOffset + "px";
+    element.style["top"] = yOffset + "px";
+    element.style["display"] = "inline";
+    if (surface.frame)
+	surface.frame.style["visibility"] = "visible";
 }
 
 function cmdHideSurface(id)
@@ -403,7 +456,14 @@ function cmdHideSurface(id)
 	return;
     surface.visible = false;
 
-    surface.canvas.style["display"] = "none";
+    var element = surface.canvas;
+    if (surface.frame)
+	element = surface.frame;
+
+    if (surface.frame)
+	surface.frame.style["visibility"] = "hidden";
+    else
+	element.style["display"] = "none";
 
     // Import the canvas into the main document
     ensureSurfaceInDocument(surface, document);
@@ -458,8 +518,16 @@ function cmdMoveSurface(id, x, y)
 		yOffset = surface.y - transientToplevel.y;
 	    }
 
-	    surface.canvas.style["left"] = xOffset + "px";
-	    surface.canvas.style["top"] = yOffset + "px";
+	    var element = surface.canvas;
+	    if (surface.frame) {
+		element = surface.frame;
+		var offset = getFrameOffset(surface);
+		xOffset -= offset.x;
+		yOffset -= offset.y;
+	    }
+
+	    element.style["left"] = xOffset + "px";
+	    element.style["top"] = yOffset + "px";
 	}
     }
 }
@@ -748,6 +816,20 @@ function updateForEvent(ev) {
 
 function onMouseMove (ev) {
     updateForEvent(ev);
+    if (localGrab) {
+	var dx = ev.pageX - localGrab.lastX;
+	var dy = ev.pageY - localGrab.lastY;
+	var surface = localGrab.frame.frameFor;
+	surface.x += dx;
+	surface.y += dy;
+	var offset = getFrameOffset(surface);
+	localGrab.frame.style["left"] = (surface.x - offset.x) + "px";
+	localGrab.frame.style["top"] = (surface.y - offset.y) + "px";
+	sendInput ("w", [surface.id, surface.x, surface.y, surface.width, surface.height]);
+	localGrab.lastX = ev.pageX;
+	localGrab.lastY = ev.pageY;
+	return;
+    }
     var id = getSurfaceId(ev);
     id = getEffectiveEventTarget (id);
     var pos = getPositionsFromEvent(ev, id);
@@ -756,6 +838,8 @@ function onMouseMove (ev) {
 
 function onMouseOver (ev) {
     updateForEvent(ev);
+    if (localGrab)
+	return;
     var id = getSurfaceId(ev);
     realWindowWithMouse = id;
     id = getEffectiveEventTarget (id);
@@ -768,6 +852,8 @@ function onMouseOver (ev) {
 
 function onMouseOut (ev) {
     updateForEvent(ev);
+    if (localGrab)
+	return;
     var id = getSurfaceId(ev);
     var origId = id;
     id = getEffectiveEventTarget (id);
@@ -816,23 +902,48 @@ function doUngrab() {
 
 function onMouseDown (ev) {
     updateForEvent(ev);
+    var button = ev.button + 1;
+    lastState = lastState | getButtonMask (button);
     var id = getSurfaceId(ev);
     id = getEffectiveEventTarget (id);
+
+    if (id == 0 && ev.target.frameFor) { /* mouse click on frame */
+	localGrab = new Object();
+	localGrab.frame = ev.target;
+	localGrab.lastX = ev.pageX;
+	localGrab.lastY = ev.pageY;
+	return;
+    }
+
     var pos = getPositionsFromEvent(ev, id);
     if (grab.window == null)
 	doGrab (id, false, true);
-    var button = ev.button + 1;
-    lastState = lastState | getButtonMask (button);
     sendInput ("b", [realWindowWithMouse, id, pos.rootX, pos.rootY, pos.winX, pos.winY, lastState, button]);
 }
 
 function onMouseUp (ev) {
     updateForEvent(ev);
-    var id = getSurfaceId(ev);
-    id = getEffectiveEventTarget (id);
-    var pos = getPositionsFromEvent(ev, id);
     var button = ev.button + 1;
     lastState = lastState & ~getButtonMask (button);
+    var evId = getSurfaceId(ev);
+    id = getEffectiveEventTarget (evId);
+    var pos = getPositionsFromEvent(ev, id);
+
+    if (localGrab) {
+	localGrab = null;
+	realWindowWithMouse = evId;
+	if (windowWithMouse != id) {
+	    if (windowWithMouse != 0) {
+		sendInput ("l", [realWindowWithMouse, windowWithMouse, pos.rootX, pos.rootY, pos.winX, pos.winY, lastState, GDK_CROSSING_NORMAL]);
+	    }
+	    windowWithMouse = id;
+	    if (windowWithMouse != 0) {
+		sendInput ("e", [realWindowWithMouse, id, pos.rootX, pos.rootY, pos.winX, pos.winY, lastState, GDK_CROSSING_NORMAL]);
+	    }
+	}
+	return;
+    }
+
     sendInput ("B", [realWindowWithMouse, id, pos.rootX, pos.rootY, pos.winX, pos.winY, lastState, button]);
 
     if (grab.window != null && grab.implicit)
@@ -842,6 +953,8 @@ function onMouseUp (ev) {
 var lastKeyDown = 0;
 function onKeyDown (ev) {
     updateForEvent(ev);
+    if (localGrab)
+	return;
     var keyCode = ev.keyCode;
     if (keyCode != lastKeyDown) {
 	sendInput ("k", [keyCode]);
@@ -851,6 +964,8 @@ function onKeyDown (ev) {
 
 function onKeyUp (ev) {
     updateForEvent(ev);
+    if (localGrab)
+	return;
     var keyCode = ev.keyCode;
     sendInput ("K", [keyCode]);
     lastKeyDown = 0;
@@ -872,6 +987,8 @@ function cancelEvent(ev)
 function onMouseWheel(ev)
 {
     updateForEvent(ev);
+    if (localGrab)
+	return;
     ev = ev ? ev : window.event;
 
     var id = getSurfaceId(ev);
diff --git a/gdk/broadway/client.html b/gdk/broadway/client.html
index a699612..10a8515 100644
--- a/gdk/broadway/client.html
+++ b/gdk/broadway/client.html
@@ -4,6 +4,66 @@
 <meta http-equiv="Content-Type" content="text/html; charset=utf8" />
 <title>broadway 2.0</title>
 <script type="text/javascript" src="broadway.js"></script>
+<style type="text/css">
+
+.frame-window {
+    background-color: rgba(179, 230, 255, 0.35);
+    background-image: -moz-linear-gradient(rgba(250, 253, 255, 0.1) 0px, rgba(250, 253, 255, 0.65) 40px, rgba(250, 253, 255, 0.75) 50px, rgba(250, 253, 255, 0) 54px);
+    background-image: -webkit-gradient(linear, left top, left 50, from(rgba(250, 253, 255, 0.9)), to(rgba(250, 253, 255, 0)), color-stop(88%, rgba(250, 253, 255, 0.75)));
+    border-radius: 6px;
+    -moz-border-radius: 6px;
+    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.65) inset, 0 0 0 1px rgba(0, 0, 0, 0.75), 0 1px 10px 2px rgba(0, 0, 0, 0.65);
+    -webkit-box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.65) inset, 0 0 0 1px rgba(0, 0, 0, 0.75), 0 1px 10px 2px rgba(0, 0, 0, 0.65);
+    padding: 0 7px 7px 7px;
+}
+
+.frame-contents {
+    border-radius: 3px;
+    -moz-border-radius: 3px;
+    border: 1px solid rgba(255, 255, 255, 0.4);
+    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.9) inset;
+    -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.9) inset;
+    clear: both;
+    padding: 1px;
+    position: relative;
+}
+
+.frame-close {
+    margin: 0 2px 3px 2px;
+    background-color: #CC3333;
+    background-image: -moz-linear-gradient(rgba(255, 255, 255, 0.35) 0%, rgba(255, 255, 255, 0.5) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0.5) 100%);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255, 255, 255, 0.35)), to(rgba(255, 255, 255, 0.5)), color-stop(50%, rgba(255, 255, 255, 0.5)), color-stop(50%, rgba(255, 255, 255, 0)));
+    border-radius: 2px;
+    border-top-left-radius: 0;
+    border-top-right-radius: 0;
+    -moz-border-radius: 2px;
+    -moz-border-top-left-radius: 0;
+    -moz-border-top-right-radius: 0;
+    border: 1px solid #550000;
+    border-top: none;
+    float: right;
+    color: white;
+    width: 36px;
+    text-shadow: black -1px 0 0, black 1px 0 0, black 0 1px 0, black 0 -1px 0;
+    box-shadow: 0 0 2px 1px rgba(255, 255, 255, 0.5) inset;
+    -webkit-box-shadow: 0 0 2px 1px rgba(255, 255, 255, 0.5) inset;
+    font-weight: bold;
+    cursor: pointer;
+}
+
+.frame-close:focus {
+    left: 0;
+}
+
+.frame-close:hover {
+    background-color: #EE4A4A;
+}
+
+.frame-close:active {
+    background-color: #AA2020;
+}
+
+</style>
 </head>
 
 <body onload="connect()">



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]