From 86eddf727aa579063ebc3c800fa3d67946a79203 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Wed, 13 Sep 2006 11:59:23 -0400 Subject: [PATCH] Added support for batching of redraws. Initial support for hextile, albeit faaaaar to slow to turn on. Fix signature of cursor method --- src/vncViewer/rfb.py | 4 +-- src/vncViewer/vnc.py | 62 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/src/vncViewer/rfb.py b/src/vncViewer/rfb.py index e75cc551d..d962acf50 100644 --- a/src/vncViewer/rfb.py +++ b/src/vncViewer/rfb.py @@ -95,7 +95,7 @@ class RFBFrameBuffer: raise NotImplementedError # data is given as ARGB - def change_cursor(self, width, height, data): + def change_cursor(self, width, height, x, y, data): #print >>stderr, 'change_cursor' raise NotImplementedError @@ -542,7 +542,7 @@ class RFBNetworkClient(RFBProxy): def send(self, s): return self.sock.send(s) - + def getpass(self): import getpass if self.pwdfile: diff --git a/src/vncViewer/vnc.py b/src/vncViewer/vnc.py index 9817b66b4..69f79b766 100755 --- a/src/vncViewer/vnc.py +++ b/src/vncViewer/vnc.py @@ -21,7 +21,7 @@ import gobject import rfb import sys -from struct import pack +from struct import pack, unpack import pygtk import gtk @@ -40,6 +40,7 @@ class GRFBFrameBuffer(rfb.RFBFrameBuffer, gobject.GObject): self.canvas = canvas self.pixmap = None self.name = "VNC" + self.dirtyregion = None def get_name(self): return self.name @@ -62,6 +63,7 @@ class GRFBFrameBuffer(rfb.RFBFrameBuffer, gobject.GObject): def resize_screen(self, width, height): self.pixmap = gtk.gdk.Pixmap(self.canvas.window, width, height) + self.gc = self.pixmap.new_gc() self.emit("resize", width, height) return (0, 0, width, height) @@ -69,19 +71,43 @@ class GRFBFrameBuffer(rfb.RFBFrameBuffer, gobject.GObject): if self.pixmap == None: return - gc = self.pixmap.new_gc() - self.pixmap.draw_rgb_32_image(gc, x, y, width, height, gtk.gdk.RGB_DITHER_NONE, data) - self.emit("invalidate", x, y, width, height) + self.pixmap.draw_rgb_32_image(self.gc, x, y, width, height, gtk.gdk.RGB_DITHER_NONE, data) + self.dirty(x,y,width,height) + def dirty(self, x, y, width, height): + if self.dirtyregion == None: + self.dirtyregion = { "x1": x, "y1": y, "x2": x+width, "y2": y+height } + else: + if x < self.dirtyregion["x1"]: + self.dirtyregion["x1"] = x + if (x + width) > self.dirtyregion["x2"]: + self.dirtyregion["x2"] = (x + width) + if y < self.dirtyregion["y1"]: + self.dirtyregion["y1"] = y + if (y + height) > self.dirtyregion["y2"]: + self.dirtyregion["y2"] = (y + height) def process_solid(self, x, y, width, height, color): - print >>stderr, 'process_solid: %dx%d at (%d,%d), color=%r' % (width,height,x,y, color) + # XXX very very evil assumes pure 32-bit RGBA format + (r,g,b,a) = unpack('BBBB', color) + self.gc.set_rgb_fg_color(gtk.gdk.Color(red=r*255,green=g*255,blue=b*255)) + if width == 1 and height == 1: + self.pixmap.draw_point(self.gc, x, y) + else: + self.pixmap.draw_rectangle(self.gc, True, x, y, width, height) + self.dirty(x,y,width,height) def update_screen(self, t): - #print >>stderr, 'update_screen' - pass + if self.dirtyregion != None: + x1 = self.dirtyregion["x1"] + x2 = self.dirtyregion["x2"] + y1 = self.dirtyregion["y1"] + y2 = self.dirtyregion["y2"] + #print "Update %d,%d (%dx%d)" % (x1, y1, (x2-x1), (y2-y1)) + self.emit("invalidate", x1, y1, x2-x1, y2-y1) + self.dirtyregion = None - def change_cursor(self, width, height, data): + def change_cursor(self, width, height, x, y, data): print >>stderr, 'change_cursor' def move_cursor(self, x, y): @@ -95,8 +121,8 @@ class GRFBNetworkClient(rfb.RFBNetworkClient, gobject.GObject): "disconnected": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, []) } - def __init__(self, host, port, converter, debug=0): - rfb.RFBNetworkClient.__init__(self, host, port, converter, debug=debug,preferred_encoding=(rfb.ENCODING_RAW,rfb.ENCODING_DESKTOP_RESIZE)) + def __init__(self, host, port, converter, debug=0, preferred_encoding=(rfb.ENCODING_RAW)): + rfb.RFBNetworkClient.__init__(self, host, port, converter, debug=debug,preferred_encoding=preferred_encoding) self.__gobject_init__() self.watch = None @@ -115,7 +141,8 @@ class GRFBNetworkClient(rfb.RFBNetworkClient, gobject.GObject): try: self.loop1() - except: + except Exception, e: + print str(e) self.close() self.emit("disconnected") return 0 @@ -157,6 +184,10 @@ class GRFBViewer(gtk.DrawingArea): self.client = None self.authenticated = False self.needpw = True + self.preferred_encoding = (rfb.ENCODING_RAW, rfb.ENCODING_DESKTOP_RESIZE) + # Current impl of draw_solid is *far* too slow to be practical + # for Hextile which likes lots of 1x1 pixels solid rectangles + #self.preferred_encoding = (rfb.ENCODING_HEXTILE, rfb.ENCODING_RAW, rfb.ENCODING_DESKTOP_RESIZE) self.fb.connect("resize", self.resize_display) self.fb.connect("invalidate", self.repaint_region) @@ -184,12 +215,12 @@ class GRFBViewer(gtk.DrawingArea): def get_framebuffer_name(self): return self.fb.get_name() - def connect_to_host(self, host, port): + def connect_to_host(self, host, port, debug=0): if self.client != None: self.disconnect_from_host() self.client = NOne - client = GRFBNetworkClient(host, port, self.fb) + client = GRFBNetworkClient(host, port, self.fb, debug=debug, preferred_encoding=self.preferred_encoding) client.connect("disconnected", self._client_disconnected) auth_types = client.init() @@ -203,6 +234,7 @@ class GRFBViewer(gtk.DrawingArea): self.needpw = False else: self.needpw = True + return self.needpw def _client_disconnected(self, src): self.client = None @@ -328,8 +360,10 @@ def main(): win.show_all() win.present() - if vnc.connect_to_host(host, port): + if vnc.connect_to_host(host, port, debug=0): print "Need password" + if password == None: + return 1 else: print "No password needed" vnc.authenticate(password)