Comments (29)
BTW, here is a small demo of the result:
http://www.youtube.com/watch?v=c5MzTc-dGs8
from novnc.
Nice demo.
It's a good idea. Unfortunately, zoom doesn't seem to do anything in firefox 3.5 and when zoom is set in Chrome, the 'offsetParent' value is missing on that element and mouse position calculation (in include/util.js:getPosition) breaks.
I'll keep the bug open as an enhancement idea, but I suspect the more browser compatible way to do this will be with the width and height styles of the canvas element rather than the zoom style.
Also, as a note to myself, mouse event scaling should be implemented in include/util.js:getEventPosition().
from novnc.
yup, I saw the offsetParent bug. I'm working on it.
But I have a question: If I play with height, and width, do the ratio will be kept by noVNC or screen will juste be cropped ?
from novnc.
Actually, I think the CSS3 transform capability is probably the right approach:
http://www.westciv.com/tools/transforms/index.html
https://developer.mozilla.org/en/CSS/-moz-transform
http://www.webresourcesdepot.com/cross-browser-css-transforms-csssandpaper/
http://www.zachstronaut.com/posts/2009/02/17/animate-css-transforms-firefox-webkit.html
I've actually coded up a prototype patch. It works on Chrome and firefox. The main remaining problem is that the element still occupies the same amount of space in the layout as if it were full size. Probably the solution is to make the canvas a floating element and anchor it inside a
diff --git a/include/canvas.js b/include/canvas.js
index af52227..e88b75d 100644
--- a/include/canvas.js
+++ b/include/canvas.js
@@ -33,6 +33,7 @@ force_canvas : false,
true_color : false,
colourMap : [],
+scale: 1,
c_wx : 0,
c_wy : 0,
ctx : null,
@@ -47,7 +48,7 @@ mouseMove : null,
onMouseButton: function(e, down) {
var evt, pos, bmask;
evt = (e ? e : window.event);
- pos = Util.getEventPosition(e, $(Canvas.id));
+ pos = Util.getEventPosition(e, $(Canvas.id), Canvas.scale);
bmask = 1 << evt.button;
//Util.Debug('mouse ' + pos.x + "," + pos.y + " down: " + down + " bmask: " + bmask);
if (Canvas.mouseButton) {
@@ -68,7 +69,7 @@ onMouseUp: function (e) {
onMouseWheel: function (e) {
var evt, pos, bmask, wheelData;
evt = (e ? e : window.event);
- pos = Util.getEventPosition(e, $(Canvas.id));
+ pos = Util.getEventPosition(e, $(Canvas.id), Canvas.scale);
wheelData = evt.detail ? evt.detail * -1 : evt.wheelDelta / 40;
if (wheelData > 0) {
bmask = 1 << 3;
@@ -88,7 +89,7 @@ onMouseWheel: function (e) {
onMouseMove: function (e) {
var evt, pos;
evt = (e ? e : window.event);
- pos = Util.getEventPosition(e, $(Canvas.id));
+ pos = Util.getEventPosition(e, $(Canvas.id), Canvas.scale);
//Util.Debug('mouse ' + evt.which + '/' + evt.button + ' up:' + pos.x + "," + pos.y);
if (Canvas.mouseMove) {
Canvas.mouseMove(pos.x, pos.y);
@@ -158,6 +159,8 @@ init: function (id) {
Canvas.clear();
+ Canvas.rescale(0.5);
+
/*
* Determine browser Canvas feature support
* and select fastest rendering methods
@@ -248,6 +251,33 @@ resize: function (width, height, true_color) {
Canvas.c_wx = c.offsetWidth;
Canvas.c_wy = c.offsetHeight;
+
+ Canvas.rescale(Canvas.scale);
+},
+
+rescale: function (factor) {
+ var c, tp, x, y,
+ properties = ['transform', 'WebkitTransform', 'MozTransform', null];
+ c = $(Canvas.id);
+ while (tp = properties.shift()) {
+ if (typeof c.style[tp] != 'undefined') {
+ break;
+ }
+ }
+
+ if (tp === null) {
+ Util.Debug("No scaling support");
+ return;
+ }
+
+ if (Canvas.scale === factor) {
+ Util.Debug("Canvas already scaled to '" + factor + "'");
+ }
+
+ Canvas.scale = factor;
+ x = c.width - c.width * factor;
+ y = c.height - c.height * factor;
+ c.style[tp] = "scale(" + Canvas.scale + ") translate(-" + x + "px, -" + y + "px)";
},
stop: function () {
diff --git a/include/util.js b/include/util.js
index 64e3f93..0b22472 100644
--- a/include/util.js
+++ b/include/util.js
@@ -171,7 +171,7 @@ Util.getPosition = function (obj) {
};
// Get mouse event position in DOM element
-Util.getEventPosition = function (e, obj) {
+Util.getEventPosition = function (e, obj, scale) {
var evt, docX, docY, pos;
//if (!e) evt = window.event;
evt = (e ? e : window.event);
@@ -185,7 +185,10 @@ Util.getEventPosition = function (e, obj) {
document.documentElement.scrollTop;
}
pos = Util.getPosition(obj);
- return {'x': docX - pos.x, 'y': docY - pos.y};
+ if (typeof scale === "undefined") {
+ scale = 1;
+ }
+ return {'x': (docX - pos.x) / scale, 'y': (docY - pos.y) / scale};
};
from novnc.
Ok. I'm on it. I'll see this tomorow
from novnc.
her.. git is not my cup of tea.
I copy your patch in a patch.ptc and then from my fork, I did
git apply ./patch.ptc
It tells me that the patch is corrupted at line 104, (the last)
Any clue ?
from novnc.
ok.. problem with number of line. This is OK.
By the way, is it OK for you to remove the "var" keyword in variable declaration?
I'm actually working with Cappuccino, and putting var to a varialble make the variable scope only from the file it comes.
And as the include of vnc.js (using @import) is processed to Cappuccino, the Canvas, RFB etc are not accessible to my application.
from novnc.
It's okay, but I'm trying to keep it JSLint clean and JSLint.
Note that in the near future I'm going to be scoping all global variables using standard Javascript function scoping and the caller will instantiate them. That should solve both issues (easy importing and JSLint clean).
from novnc.
scoping would be good.
I've move the initialization function (that includes extra JS file) in another file, arbitrary call "init.js", (but maybe renaming it vnc.js and old vnc.js to rfb.js would be better) in order to be able to not automatically include other JS file.
From my Cappuccino point of view, I use @import directive that solve the path alone without the need to give the prefix variable (which is unpredictable).
Is that also ok to you ?
from novnc.
Or (I think to myself) it would be better to add a function includeExtra() in RFB namespace directly.
from novnc.
I've gone with the approach of doing the loading in vnc.js. rfb.js now just contains the RFB namespace. Separating core code from UI/DOM and loading mechanisms has always been a goal of mine so that makes a lot of sense.
You can skip pulling in vnc.js and just load the files using whatever mechanism works best for you.
from novnc.
Great! I've also notice a problem with the stop() procedure of Canvas. Sometimes the canvas is gone from the DOM before the the stop is terminate. So it fails with removeEvents and resize. In my fork, I add simple tests for that: if Canvas is gone, there no need to remove anything more.
EDIT: it works like a charm, by the way. The only things I need to change from your code is the var Canvas, var RFB, and add the if (!c) {return} to resize and Canvas.{resize,rescale,stop} and it works great with my VNCCappuccino http://bitbucket.org/primalmotion/vnccappuccino)
from novnc.
Can you expand a bit on how the canvas element is going away and Canvas.stop() is still getting called? What code is calling it? Is RFB code calling it, or in VNCCappuccino?
I don't dynamically create and destroy canvas elements so I've not seen this. I think instead of putting conditionals everywhere, it's probably better to have some sort of tear-down in whoever is calling it.
from novnc.
This is Cappuccino that dynamically destroys element. VNCCappucino is a framework used by a module (equivalent to NSBundle in Cocoa) that can be arbitrary loaded or unloaded. And I saw a timer in your code about disconnection. It is obvious that Cappuccino's bundle loading doesn't care about this timer :)
What do you mean by "tear-down" ?
from novnc.
For example, if you can hook the event that destroys the canvas element, the Canvas.ctx variable should really be set to null at that point since there is no longer a rendering context. When a disconnect happens, I check to make sure that Canvas.ctx is valid before calling the stop() and clear() methods.
from novnc.
Ok I think I've finally understood my problem. Random error (not width property to undefined, can't dettachEvent of null, obj is undefined, etc..) is due to all the timers.
Sometimes, timers are still in the loop. the module unload and destroy DOM canvas. Timer is triggered, and boom.
So I need to keep track of all timers and be able to stop them all if I need to.
What do you think ?
from novnc.
Yeah, that would be my suggestion. All timer and intervals should be cleared when no longer valid. For example, the native Javascript routines setTimeout and setInterval return numbers which can later be used to clear them using clearTimeout and clearInterval.
There are a couple of approaches: the timers can be cleared externally by the "tear-down" event, or the timer functions them selves can detect if they are still valid and terminate the timer themselves.
For example, often intervals are done with setTimeout (rather that setInterval) and in the timer function the function sets a timeout for itself before it returns using setTimeout again.
For example, the following fires once a second until statevalid is no longer true:
function periodic () {
if (! statevalid) {
return;
}
// do something
setTimeout(periodic, 1000);
}
setTimeout(periodic, 1000);
from novnc.
ok it works fine and all errors are gone. This is pushed to my fork.
Oh, and I also pass oldstate to RFB.externalUpdateState() because it is usefull to follow the events flow :)
from novnc.
I've pushed a couple of fixes to the scaling hooks that were introduced by recent keyboard/mouse handling refactor into include/input.js.
I've not pushed a UI change to support scaling since the DOM alignment is still screwy but here is a gist patch that adds the UI functionality in buggy form:
https://gist.github.com/948826
from novnc.
Hi, I'm just beginning to try out NoVNC. I like the idea that it's Ajaxy and nothing needs to be installed at client side. And it's responsive and fast! Great job here.
One of the problems I face is client-side scaling. I need to auto-fit the VNC screen to my client display and not follow the server-side resolution.
What is the best way to do this? I tried UI.rfb.set_scale=0.7 but this didn't work.
Also, if I manually resize the width and height of VNC_canvas like this:
#VNC_canvas {
background: #eee;
width: 100%; height:1000px;
}
It works, but breaks the mouse pointer positioning.
I'll keep on trying, but if you have some quick tips, please let me know.
from novnc.
As part of working on small form factor support such as phones and tablets (#48) I have implemented experimental viewport support into the tests/viewport.html
file and it seems to work fairly well. The viewport is sized to the screen/browser size and you can scroll around. I will probably be integrating that into noVNC itself in the next couple of weeks.
I may also implement some level of scaling at some point too, but that's not my most immediate priority. The current scaling code in noVNC is really just experimental and is not fully cross-browser yet.
from novnc.
Hi joel,
Thanks, I've tried it out, and ported the code from viewport.html to vnc.html and ui.js. Looks like it's working, except that I see the default "fabric-like" graphics after a resize. Hovering my mouse over the canvas will update some pixels.
So I need a screen refresh feature so that I can get back my whole screen after a resize operation.
Also, I'm not sure if resize(), drawArea(), and canvas.resize() are going to rescale the screen? Or will they clip parts of the screen?
I just notice the canvas size got resized, but not sure if my whole screen gets "fitted" (or auto-scaled) into that canvas area.
I can't be certain until I perform a screen refresh.
Any ideas on how to do this? Where do I find the code for initial screen update immediately after a "VNC connect"?
I'm willing to share my code back to this project.
-daniel
from novnc.
Yes, the repeating pattern in viewport.html is just for testing out the principle. In the real thing, rather than drawing the pattern I will issue a series of framebuffer requests for the "dirty" regions that need to be redrawn.
Now that @snorkeyg has solved the keyboard input issue for touch devices, I have a pretty clear idea in my mind how to integrate all the pieces together and I'm planning on doing so in the next couple weeks. You're welcome to play around with it in the meantime and post your code in a fork. If it lines up with the direction I want to go (or it's better than what I have in mind) then I will pull in your changes.
from novnc.
hi joel,
i've just played around abit, and made tiny UI changes (basically porting some of the nice features in vnc_auto.html to vnc.html).
I'm still stuck at finding how to get a screen refresh. I'm in the middle of setting up Git and stuff, so you can have a look at my fork once I've got everything set up.
regards, daniel
from novnc.
@danielkho, I'll look at your fork. However, @snorkeyg has some pending refactoring that will enable noVNC on iOS (iPhone and iOS) that those changes will likely be landing in the next few days.
from novnc.
Hi joel, sorry I'm new to github and git. How do I do a fork? Do I do a "git
commit"?
I'm looking forward to the new updates by snorkeyg. Hopefully it has all the
good browser rescale features. :)
On Thu, Sep 1, 2011 at 11:14 PM, kanaka <
[email protected]>wrote:
@danielkho, I'll look at your fork. However, @snorkeyg has some pending
refactoring that will enable noVNC on iOS (iPhone and iOS) that those
changes will likely be landing in the next few days.Reply to this email directly or view it on GitHub:
#12 (comment)
from novnc.
Go to a project page on github that you want to fork. In the upper right at the same level as the project name is a button called "Fork" which will create a copy of the repository for you as your own user (but with the same name). You can then clone that, make changes, commit, and then push those changes. Once you have the changes committed, in about the same place on the page for you project is a button labeled "Pull request". This will create a new pull issue in the original project where I can review and comment on the code changes and merge them into the upstream.
from novnc.
@danielkho. Scaling support will probably be a little ways down the road. Initially it will be viewport support since this will work across a range of devices. With scaling, you still have to download and render exactly the same amount of data so it would be unusable for iPhone 3G as an example. Scaling support is on the roadmap but it's less important to me right now that viewport support. For the next generation of smartphones (e.g. dual-core, LTE), scaling will make more sense.
from novnc.
closing due to age.
from novnc.
Related Issues (20)
- Alt Tab support HOT 1
- Clipboard not transparent HOT 1
- Nginx Config does Not work. HOT 3
- Compatibility with wayvnc on Raspberry Pi OS/Debian Bookworm and its default security type 262 HOT 5
- realVNC on Raspberry Pi HOT 10
- Remove unused devDependencies. HOT 1
- Support running via `npx` HOT 1
- When I introduced Novnc in Vue, it got stuck when deployed to the server HOT 1
- Oculus Quest compatibility/Keyboard not shown/Enter+Del not working HOT 19
- Virtual keyboard button is not always shown when needed HOT 1
- fail to install using npm i HOT 1
- Autoconnect with Password doesn't work HOT 7
- Windows 11 targets do not respect resizeSession HOT 2
- Korean characters are not displayed properly HOT 1
- How to integrate noVNC in Angular 16 HOT 1
- Colour Problem HOT 1
- In the 2012 version of novnc.js, using the numeric keyboard to input "*" results in "8",and "+"results in "="; HOT 2
- Weston VNC server (neatvnc) HOT 1
- Colour Problem HOT 4
- Rewrite page title using 'title' query parameter HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from novnc.