1a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* 2a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * scale.c - deal with server-side scaling. 3a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */ 4a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 5a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* 6a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin 7a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Copyright (C) 2002 RealVNC Ltd. 8a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>. 9a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. 10a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * All Rights Reserved. 11a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * 12a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * This is free software; you can redistribute it and/or modify 13a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * it under the terms of the GNU General Public License as published by 14a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * the Free Software Foundation; either version 2 of the License, or 15a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * (at your option) any later version. 16a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * 17a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * This software is distributed in the hope that it will be useful, 18a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * but WITHOUT ANY WARRANTY; without even the implied warranty of 19a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * GNU General Public License for more details. 21a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * 22a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * You should have received a copy of the GNU General Public License 23a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * along with this software; if not, write to the Free Software 24a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 25a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * USA. 26a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */ 27a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 28a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef __STRICT_ANSI__ 29a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define _BSD_SOURCE 30a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 31a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <string.h> 32a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <rfb/rfb.h> 33a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <rfb/rfbregion.h> 34a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include "private.h" 35a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 36a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_FCNTL_H 37a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <fcntl.h> 38a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 39a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 40a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef WIN32 41a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define write(sock,buf,len) send(sock,buf,len,0) 42a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else 43a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_UNISTD_H 44a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <unistd.h> 45a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 46a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <pwd.h> 47a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H 48a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <sys/socket.h> 49a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 50a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H 51a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <netinet/in.h> 52a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <netinet/tcp.h> 53a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <arpa/inet.h> 54a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 55a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 56a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 57a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef DEBUGPROTO 58a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#undef DEBUGPROTO 59a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define DEBUGPROTO(x) x 60a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else 61a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define DEBUGPROTO(x) 62a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif 63a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 64a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/****************************/ 65a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define CEIL(x) ( (double) ((int) (x)) == (x) ? \ 66a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat (double) ((int) (x)) : (double) ((int) (x) + 1) ) 67a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define FLOOR(x) ( (double) ((int) (x)) ) 68a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 69a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 70a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint ScaleX(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int x) 71a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 72a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if ((from==to) || (from==NULL) || (to==NULL)) return x; 73a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return ((int)(((double) x / (double)from->width) * (double)to->width )); 74a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 75a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 76a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint ScaleY(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int y) 77a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 78a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if ((from==to) || (from==NULL) || (to==NULL)) return y; 79a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return ((int)(((double) y / (double)from->height) * (double)to->height )); 80a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 81a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 82a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* So, all of the encodings point to the ->screen->frameBuffer, 83a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * We need to change this! 84a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */ 85a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid rfbScaledCorrection(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int *x, int *y, int *w, int *h, const char *function) 86a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 87a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat double x1,y1,w1,h1, x2, y2, w2, h2; 88a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat double scaleW = ((double) to->width) / ((double) from->width); 89a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat double scaleH = ((double) to->height) / ((double) from->height); 90a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 91a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 92a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* 93a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbLog("rfbScaledCorrection(%p -> %p, %dx%d->%dx%d (%dXx%dY-%dWx%dH)\n", 94a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * from, to, from->width, from->height, to->width, to->height, *x, *y, *w, *h); 95a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */ 96a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 97a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* If it's the original framebuffer... */ 98a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (from==to) return; 99a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 100a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat x1 = ((double) *x) * scaleW; 101a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat y1 = ((double) *y) * scaleH; 102a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat w1 = ((double) *w) * scaleW; 103a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat h1 = ((double) *h) * scaleH; 104a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 105a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 106a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /*cast from double to int is same as "*x = floor(x1);" */ 107a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat x2 = FLOOR(x1); 108a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat y2 = FLOOR(y1); 109a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 110a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* include into W and H the jitter of scaling X and Y */ 111a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat w2 = CEIL(w1 + ( x1 - x2 )); 112a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat h2 = CEIL(h1 + ( y1 - y2 )); 113a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 114a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* 115a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbLog("%s (%dXx%dY-%dWx%dH -> %fXx%fY-%fWx%fH) {%dWx%dH -> %dWx%dH}\n", 116a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * function, *x, *y, *w, *h, x2, y2, w2, h2, 117a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * from->width, from->height, to->width, to->height); 118a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */ 119a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 120a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* simulate ceil() without math library */ 121a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *x = (int)x2; 122a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *y = (int)y2; 123a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *w = (int)w2; 124a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *h = (int)h2; 125a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 126a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Small changes for a thumbnail may be scaled to zero */ 127a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (*w==0) (*w)++; 128a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (*h==0) (*h)++; 129a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* scaling from small to big may overstep the size a bit */ 130a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (*x+*w > to->width) *w=to->width - *x; 131a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (*y+*h > to->height) *h=to->height - *y; 132a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 133a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 134a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid rfbScaledScreenUpdateRect(rfbScreenInfoPtr screen, rfbScreenInfoPtr ptr, int x0, int y0, int w0, int h0) 135a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 136a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat int x,y,w,v,z; 137a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat int x1, y1, w1, h1; 138a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat int bitsPerPixel, bytesPerPixel, bytesPerLine, areaX, areaY, area2; 139a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat unsigned char *srcptr, *dstptr; 140a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 141a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Nothing to do!!! */ 142a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (screen==ptr) return; 143a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 144a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat x1 = x0; 145a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat y1 = y0; 146a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat w1 = w0; 147a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat h1 = h0; 148a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 149a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScaledCorrection(screen, ptr, &x1, &y1, &w1, &h1, "rfbScaledScreenUpdateRect"); 150a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat x0 = ScaleX(ptr, screen, x1); 151a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat y0 = ScaleY(ptr, screen, y1); 152a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat w0 = ScaleX(ptr, screen, w1); 153a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat h0 = ScaleY(ptr, screen, h1); 154a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 155a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat bitsPerPixel = screen->bitsPerPixel; 156a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat bytesPerPixel = bitsPerPixel / 8; 157a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat bytesPerLine = w1 * bytesPerPixel; 158a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat srcptr = (unsigned char *)(screen->frameBuffer + 159a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat (y0 * screen->paddedWidthInBytes + x0 * bytesPerPixel)); 160a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat dstptr = (unsigned char *)(ptr->frameBuffer + 161a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ( y1 * ptr->paddedWidthInBytes + x1 * bytesPerPixel)); 162a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* The area of the source framebuffer for each destination pixel */ 163a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat areaX = ScaleX(ptr,screen,1); 164a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat areaY = ScaleY(ptr,screen,1); 165a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat area2 = areaX*areaY; 166a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 167a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 168a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Ensure that we do not go out of bounds */ 169a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if ((x1+w1) > (ptr->width)) 170a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat { 171a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (x1==0) w1=ptr->width; else x1 = ptr->width - w1; 172a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 173a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if ((y1+h1) > (ptr->height)) 174a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat { 175a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (y1==0) h1=ptr->height; else y1 = ptr->height - h1; 176a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 177a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* 178a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbLog("rfbScaledScreenUpdateRect(%dXx%dY-%dWx%dH -> %dXx%dY-%dWx%dH <%dx%d>) {%dWx%dH -> %dWx%dH} 0x%p\n", 179a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * x0, y0, w0, h0, x1, y1, w1, h1, areaX, areaY, 180a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * screen->width, screen->height, ptr->width, ptr->height, ptr->frameBuffer); 181a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */ 182a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 183a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (screen->serverFormat.trueColour) { /* Blend neighbouring pixels together */ 184a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat unsigned char *srcptr2; 185a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat unsigned long pixel_value, red, green, blue; 186a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat unsigned int redShift = screen->serverFormat.redShift; 187a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat unsigned int greenShift = screen->serverFormat.greenShift; 188a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat unsigned int blueShift = screen->serverFormat.blueShift; 189a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat unsigned long redMax = screen->serverFormat.redMax; 190a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat unsigned long greenMax = screen->serverFormat.greenMax; 191a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat unsigned long blueMax = screen->serverFormat.blueMax; 192a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 193a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* for each *destination* pixel... */ 194a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat for (y = 0; y < h1; y++) { 195a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat for (x = 0; x < w1; x++) { 196a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat red = green = blue = 0; 197a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Get the totals for rgb from the source grid... */ 198a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat for (w = 0; w < areaX; w++) { 199a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat for (v = 0; v < areaY; v++) { 200a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat srcptr2 = &srcptr[(((x * areaX) + w) * bytesPerPixel) + 201a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat (v * screen->paddedWidthInBytes)]; 202a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat pixel_value = 0; 203a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 204a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 205a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat switch (bytesPerPixel) { 206a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat case 4: pixel_value = *((unsigned int *)srcptr2); break; 207a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat case 2: pixel_value = *((unsigned short *)srcptr2); break; 208a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat case 1: pixel_value = *((unsigned char *)srcptr2); break; 209a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat default: 210a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* fixme: endianess problem? */ 211a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat for (z = 0; z < bytesPerPixel; z++) 212a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat pixel_value += (srcptr2[z] << (8 * z)); 213a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat break; 214a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 215a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* 216a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat srcptr2 += bytesPerPixel; 217a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */ 218a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 219a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat red += ((pixel_value >> redShift) & redMax); 220a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat green += ((pixel_value >> greenShift) & greenMax); 221a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat blue += ((pixel_value >> blueShift) & blueMax); 222a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 223a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 224a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 225a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* We now have a total for all of the colors, find the average! */ 226a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat red /= area2; 227a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat green /= area2; 228a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat blue /= area2; 229a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Stuff the new value back into memory */ 230a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat pixel_value = ((red & redMax) << redShift) | ((green & greenMax) << greenShift) | ((blue & blueMax) << blueShift); 231a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 232a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat switch (bytesPerPixel) { 233a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat case 4: *((unsigned int *)dstptr) = (unsigned int) pixel_value; break; 234a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat case 2: *((unsigned short *)dstptr) = (unsigned short) pixel_value; break; 235a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat case 1: *((unsigned char *)dstptr) = (unsigned char) pixel_value; break; 236a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat default: 237a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* fixme: endianess problem? */ 238a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat for (z = 0; z < bytesPerPixel; z++) 239a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat dstptr[z]=(pixel_value >> (8 * z)) & 0xff; 240a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat break; 241a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 242a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat dstptr += bytesPerPixel; 243a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 244a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat srcptr += (screen->paddedWidthInBytes * areaY); 245a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat dstptr += (ptr->paddedWidthInBytes - bytesPerLine); 246a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 247a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } else 248a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat { /* Not truecolour, so we can't blend. Just use the top-left pixel instead */ 249a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat for (y = y1; y < (y1+h1); y++) { 250a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat for (x = x1; x < (x1+w1); x++) 251a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat memcpy (&ptr->frameBuffer[(y *ptr->paddedWidthInBytes) + (x * bytesPerPixel)], 252a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat &screen->frameBuffer[(y * areaY * screen->paddedWidthInBytes) + (x *areaX * bytesPerPixel)], bytesPerPixel); 253a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 254a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 255a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 256a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 257a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2) 258a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 259a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* ok, now the task is to update each and every scaled version of the framebuffer 260a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * and we only have to do this for this specific changed rectangle! 261a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */ 262a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScreenInfoPtr ptr; 263a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat int count=0; 264a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 265a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* We don't point to cl->screen as it is the original */ 266a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat for (ptr=screen->scaledScreenNext;ptr!=NULL;ptr=ptr->scaledScreenNext) 267a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat { 268a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Only update if it has active clients... */ 269a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (ptr->scaledScreenRefCount>0) 270a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat { 271a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScaledScreenUpdateRect(screen, ptr, x1, y1, x2-x1, y2-y1); 272a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat count++; 273a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 274a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 275a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 276a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 277a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* Create a new scaled version of the framebuffer */ 278a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbScreenInfoPtr rfbScaledScreenAllocate(rfbClientPtr cl, int width, int height) 279a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 280a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScreenInfoPtr ptr; 281a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ptr = malloc(sizeof(rfbScreenInfo)); 282a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (ptr!=NULL) 283a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat { 284a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* copy *everything* (we don't use most of it, but just in case) */ 285a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat memcpy(ptr, cl->screen, sizeof(rfbScreenInfo)); 286a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ptr->width = width; 287a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ptr->height = height; 288a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ptr->paddedWidthInBytes = (ptr->bitsPerPixel/8)*ptr->width; 289a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 290a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Need to by multiples of 4 for Sparc systems */ 291a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ptr->paddedWidthInBytes += (ptr->paddedWidthInBytes % 4); 292a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 293a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Reset the reference count to 0! */ 294a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ptr->scaledScreenRefCount = 0; 295a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 296a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ptr->sizeInBytes = ptr->paddedWidthInBytes * ptr->height; 297a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ptr->serverFormat = cl->screen->serverFormat; 298a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 299a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ptr->frameBuffer = malloc(ptr->sizeInBytes); 300a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (ptr->frameBuffer!=NULL) 301a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat { 302a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Reset to a known condition: scale the entire framebuffer */ 303a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScaledScreenUpdateRect(cl->screen, ptr, 0, 0, cl->screen->width, cl->screen->height); 304a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Now, insert into the chain */ 305a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat LOCK(cl->updateMutex); 306a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ptr->scaledScreenNext = cl->screen->scaledScreenNext; 307a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat cl->screen->scaledScreenNext = ptr; 308a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat UNLOCK(cl->updateMutex); 309a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 310a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat else 311a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat { 312a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Failed to malloc the new frameBuffer, cleanup */ 313a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat free(ptr); 314a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ptr=NULL; 315a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 316a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 317a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return ptr; 318a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 319a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 320a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* Find an active scaled version of the framebuffer 321a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * TODO: implement a refcount per scaled screen to prevent 322a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * unreferenced scaled screens from hanging around 323a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */ 324a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatrfbScreenInfoPtr rfbScalingFind(rfbClientPtr cl, int width, int height) 325a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 326a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScreenInfoPtr ptr; 327a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* include the original in the search (ie: fine 1:1 scaled version of the frameBuffer) */ 328a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat for (ptr=cl->screen; ptr!=NULL; ptr=ptr->scaledScreenNext) 329a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat { 330a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if ((ptr->width==width) && (ptr->height==height)) 331a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return ptr; 332a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 333a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return NULL; 334a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 335a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 336a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/* Future needs "scale to 320x240, as that's the client's screen size */ 337a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid rfbScalingSetup(rfbClientPtr cl, int width, int height) 338a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 339a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScreenInfoPtr ptr; 340a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 341a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ptr = rfbScalingFind(cl,width,height); 342a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (ptr==NULL) 343a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ptr = rfbScaledScreenAllocate(cl,width,height); 344a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Now, there is a new screen available (if ptr is not NULL) */ 345a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (ptr!=NULL) 346a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat { 347a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* Update it! */ 348a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (ptr->scaledScreenRefCount<1) 349a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbScaledScreenUpdateRect(cl->screen, ptr, 0, 0, cl->screen->width, cl->screen->height); 350a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* 351a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * rfbLog("Taking one from %dx%d-%d and adding it to %dx%d-%d\n", 352a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * cl->scaledScreen->width, cl->scaledScreen->height, 353a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * cl->scaledScreen->scaledScreenRefCount, 354a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * ptr->width, ptr->height, ptr->scaledScreenRefCount); 355a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */ 356a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 357a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat LOCK(cl->updateMutex); 358a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat cl->scaledScreen->scaledScreenRefCount--; 359a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat ptr->scaledScreenRefCount++; 360a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat cl->scaledScreen=ptr; 361a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat cl->newFBSizePending = TRUE; 362a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat UNLOCK(cl->updateMutex); 363a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 364a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLog("Scaling to %dx%d (refcount=%d)\n",width,height,ptr->scaledScreenRefCount); 365a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 366a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat else 367a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLog("Scaling to %dx%d failed, leaving things alone\n",width,height); 368a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 369a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 370a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint rfbSendNewScaleSize(rfbClientPtr cl) 371a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{ 372a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat /* if the client supports newFBsize Encoding, use it */ 373a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (cl->useNewFBSize && cl->newFBSizePending) 374a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return FALSE; 375a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 376a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat LOCK(cl->updateMutex); 377a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat cl->newFBSizePending = FALSE; 378a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat UNLOCK(cl->updateMutex); 379a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 380a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (cl->PalmVNC==TRUE) 381a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat { 382a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbPalmVNCReSizeFrameBufferMsg pmsg; 383a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat pmsg.type = rfbPalmVNCReSizeFrameBuffer; 384a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat pmsg.pad1 = 0; 385a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat pmsg.desktop_w = Swap16IfLE(cl->screen->width); 386a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat pmsg.desktop_h = Swap16IfLE(cl->screen->height); 387a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat pmsg.buffer_w = Swap16IfLE(cl->scaledScreen->width); 388a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat pmsg.buffer_h = Swap16IfLE(cl->scaledScreen->height); 389a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat pmsg.pad2 = 0; 390a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat 391a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLog("Sending a response to a PalmVNC style frameuffer resize event (%dx%d)\n", cl->scaledScreen->width, cl->scaledScreen->height); 392a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (rfbWriteExact(cl, (char *)&pmsg, sz_rfbPalmVNCReSizeFrameBufferMsg) < 0) { 393a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLogPerror("rfbNewClient: write"); 394a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbCloseClient(cl); 395a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbClientConnectionGone(cl); 396a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return FALSE; 397a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 398a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 399a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat else 400a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat { 401a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbResizeFrameBufferMsg rmsg; 402a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rmsg.type = rfbResizeFrameBuffer; 403a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rmsg.pad1=0; 404a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rmsg.framebufferWidth = Swap16IfLE(cl->scaledScreen->width); 405a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rmsg.framebufferHeigth = Swap16IfLE(cl->scaledScreen->height); 406a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLog("Sending a response to a UltraVNC style frameuffer resize event (%dx%d)\n", cl->scaledScreen->width, cl->scaledScreen->height); 407a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat if (rfbWriteExact(cl, (char *)&rmsg, sz_rfbResizeFrameBufferMsg) < 0) { 408a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbLogPerror("rfbNewClient: write"); 409a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbCloseClient(cl); 410a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat rfbClientConnectionGone(cl); 411a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return FALSE; 412a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 413a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat } 414a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat return TRUE; 415a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat} 416a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/****************************/ 417