Bool HandleRFBServerMessage() { rfbServerToClientMsg msg; if (!ReadFromRFBServer((char *)&msg, 1)) return False; switch (msg.type) { case rfbSetColourMapEntries: { int i; CARD16 rgb[3]; XColor xc; if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbSetColourMapEntriesMsg - 1)) return False; msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour); msg.scme.nColours = Swap16IfLE(msg.scme.nColours); for (i = 0; i < msg.scme.nColours; i++) { if (!ReadFromRFBServer((char *)rgb, 6)) return False; xc.pixel = msg.scme.firstColour + i; xc.red = Swap16IfLE(rgb[0]); xc.green = Swap16IfLE(rgb[1]); xc.blue = Swap16IfLE(rgb[2]); xc.flags = DoRed|DoGreen|DoBlue; XStoreColor(dpy, cmap, &xc); } break; } case rfbFramebufferUpdate: { rfbFramebufferUpdateRectHeader rect; int linesToRead; int bytesPerLine; int i; int usecs; if (!ReadFromRFBServer(((char *)&msg.fu) + 1, sz_rfbFramebufferUpdateMsg - 1)) return False; msg.fu.nRects = Swap16IfLE(msg.fu.nRects); for (i = 0; i < msg.fu.nRects; i++) { if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader)) return False; rect.encoding = Swap32IfLE(rect.encoding); if (rect.encoding == rfbEncodingLastRect) break; rect.r.x = Swap16IfLE(rect.r.x); rect.r.y = Swap16IfLE(rect.r.y); rect.r.w = Swap16IfLE(rect.r.w); rect.r.h = Swap16IfLE(rect.r.h); if (rect.encoding == rfbEncodingXCursor || rect.encoding == rfbEncodingRichCursor) { if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h, rect.encoding)) { return False; } continue; } if (rect.encoding == rfbEncodingPointerPos) { if (!HandleCursorPos(rect.r.x, rect.r.y)) { return False; } continue; } if ((rect.r.x + rect.r.w > si.framebufferWidth) || (rect.r.y + rect.r.h > si.framebufferHeight)) { fprintf(stderr,"Rect too large: %dx%d at (%d, %d)\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y); return False; } if (rect.r.h * rect.r.w == 0) { fprintf(stderr,"Zero size rect - ignoring\n"); continue; } /* If RichCursor encoding is used, we should prevent collisions between framebuffer updates and cursor drawing operations. */ SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h); switch (rect.encoding) { case rfbEncodingRaw: bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8; linesToRead = BUFFER_SIZE / bytesPerLine; while (rect.r.h > 0) { if (linesToRead > rect.r.h) linesToRead = rect.r.h; if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead)) return False; CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w, linesToRead); rect.r.h -= linesToRead; rect.r.y += linesToRead; } break; case rfbEncodingCopyRect: { rfbCopyRect cr; if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect)) return False; cr.srcX = Swap16IfLE(cr.srcX); cr.srcY = Swap16IfLE(cr.srcY); /* If RichCursor encoding is used, we should extend our "cursor lock area" (previously set to destination rectangle) to the source rectangle as well. */ SoftCursorLockArea(cr.srcX, cr.srcY, rect.r.w, rect.r.h); if (appData.copyRectDelay != 0) { XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); #if VNC_CAPTURE myxfillrec(dpy, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); #endif XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, rect.r.w, rect.r.h); #if VNC_CAPTURE myxfillrec(dpy, dstGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); #endif XSync(dpy,False); usleep(appData.copyRectDelay * 1000); XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, rect.r.w, rect.r.h); #if VNC_CAPTURE myxfillrec(dpy, dstGC, rect.r.x, rect.r.y, rect.r.w, rect.r.h); #endif XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); #if VNC_CAPTURE myxfillrec(dpy, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); #endif } XCopyArea(dpy, desktopWin, desktopWin, gc, cr.srcX, cr.srcY, rect.r.w, rect.r.h, rect.r.x, rect.r.y); #if VNC_CAPTURE myxcparea(dpy, gc, cr.srcX, cr.srcY, rect.r.w, rect.r.h,rect.r.x,rect.r.y); #endif break; } case rfbEncodingRRE: { switch (myFormat.bitsPerPixel) { case 8: if (!HandleRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 16: if (!HandleRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 32: if (!HandleRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } break; } case rfbEncodingCoRRE: { switch (myFormat.bitsPerPixel) { case 8: if (!HandleCoRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 16: if (!HandleCoRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 32: if (!HandleCoRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } break; } case rfbEncodingHextile: { switch (myFormat.bitsPerPixel) { case 8: if (!HandleHextile8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 16: if (!HandleHextile16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 32: if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } break; } case rfbEncodingZlib: { switch (myFormat.bitsPerPixel) { case 8: if (!HandleZlib8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 16: if (!HandleZlib16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 32: if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } break; } case rfbEncodingTight: { switch (myFormat.bitsPerPixel) { case 8: if (!HandleTight8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 16: if (!HandleTight16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; case 32: if (!HandleTight32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } break; } default: fprintf(stderr,"Unknown rect encoding %d\n", (int)rect.encoding); return False; } /* Now we may discard "soft cursor locks". */ SoftCursorUnlockScreen(); } #ifdef MITSHM /* if using shared memory PutImage, make sure that the X server has updated its framebuffer before we reuse the shared memory. This is mainly to avoid copyrect using invalid screen contents - not sure if we'd need it otherwise. */ if (appData.useShm) XSync(dpy, False); #endif if (!SendIncrementalFramebufferUpdateRequest()) return False; break; } case rfbBell: { Window toplevelWin; XBell(dpy, 0); if (appData.raiseOnBeep) { toplevelWin = XtWindow(toplevel); XMapRaised(dpy, toplevelWin); } break; } case rfbServerCutText: { if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbServerCutTextMsg - 1)) return False; msg.sct.length = Swap32IfLE(msg.sct.length); if (serverCutText) free(serverCutText); serverCutText = malloc(msg.sct.length+1); if (!ReadFromRFBServer(serverCutText, msg.sct.length)) return False; serverCutText[msg.sct.length] = 0; newServerCutText = True; break; } default: fprintf(stderr,"Unknown message type %d from VNC server\n",msg.type); return False; } return True; }
static Bool HandleHextileBPP (int rx, int ry, int rw, int rh) { CARDBPP bg, fg; XGCValues gcv; int i; CARD8 *ptr; int x, y, w, h; int sx, sy, sw, sh; CARD8 subencoding; CARD8 nSubrects; for (y = ry; y < ry+rh; y += 16) { for (x = rx; x < rx+rw; x += 16) { w = h = 16; if (rx+rw - x < 16) w = rx+rw - x; if (ry+rh - y < 16) h = ry+rh - y; if (!ReadFromRFBServer((char *)&subencoding, 1)) return False; if (subencoding & rfbHextileRaw) { if (!ReadFromRFBServer(buffer, w * h * (BPP / 8))) return False; CopyDataToScreen(buffer, x, y, w, h); continue; } if (subencoding & rfbHextileBackgroundSpecified) if (!ReadFromRFBServer((char *)&bg, sizeof(bg))) return False; #if (BPP == 8) if (appData.useBGR233) gcv.foreground = BGR233ToPixel[bg]; else #endif gcv.foreground = bg; XChangeGC(dpy, gc, GCForeground, &gcv); XFillRectangle(dpy, desktopWin, gc, x, y, w, h); #if VNC_CAPTURE myxfillrec(dpy, gc, x, y, w, h); #endif if (subencoding & rfbHextileForegroundSpecified) if (!ReadFromRFBServer((char *)&fg, sizeof(fg))) return False; if (!(subencoding & rfbHextileAnySubrects)) { continue; } if (!ReadFromRFBServer((char *)&nSubrects, 1)) return False; ptr = (CARD8 *)buffer; if (subencoding & rfbHextileSubrectsColoured) { if (!ReadFromRFBServer(buffer, nSubrects * (2 + (BPP / 8)))) return False; for (i = 0; i < nSubrects; i++) { GET_PIXEL(fg, ptr); sx = rfbHextileExtractX(*ptr); sy = rfbHextileExtractY(*ptr); ptr++; sw = rfbHextileExtractW(*ptr); sh = rfbHextileExtractH(*ptr); ptr++; #if (BPP == 8) if (appData.useBGR233) gcv.foreground = BGR233ToPixel[fg]; else #endif gcv.foreground = fg; XChangeGC(dpy, gc, GCForeground, &gcv); XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh); #if VNC_CAPTURE myxfillrec(dpy, gc,x+sx, y+sy, sw, sh); #endif } } else { if (!ReadFromRFBServer(buffer, nSubrects * 2)) return False; #if (BPP == 8) if (appData.useBGR233) gcv.foreground = BGR233ToPixel[fg]; else #endif gcv.foreground = fg; XChangeGC(dpy, gc, GCForeground, &gcv); for (i = 0; i < nSubrects; i++) { sx = rfbHextileExtractX(*ptr); sy = rfbHextileExtractY(*ptr); ptr++; sw = rfbHextileExtractW(*ptr); sh = rfbHextileExtractH(*ptr); ptr++; XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh); #if VNC_CAPTURE myxfillrec(dpy, gc,x+sx, y+sy, sw, sh); #endif } } } } return True; }
Bool HandleRFBServerMessage() { rfbServerToClientMsg msg; if (!ReadFromRFBServer((char *)&msg, 1)) return False; switch (msg.type) { case rfbSetColourMapEntries: { fprintf(stderr, "Received unsupported rfbSetColourMapEntries\n"); return False; /* unsupported */ } case rfbFramebufferUpdate: { rfbFramebufferUpdateRectHeader rect; int linesToRead; int bytesPerLine; int i; if (!ReadFromRFBServer(((char *)&msg.fu) + 1, sz_rfbFramebufferUpdateMsg - 1)) return False; msg.fu.nRects = Swap16IfLE(msg.fu.nRects); for (i = 0; i < msg.fu.nRects; i++) { if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader)) return False; rect.r.x = Swap16IfLE(rect.r.x); rect.r.y = Swap16IfLE(rect.r.y); rect.r.w = Swap16IfLE(rect.r.w); rect.r.h = Swap16IfLE(rect.r.h); rect.encoding = Swap32IfLE(rect.encoding); if (rect.encoding == rfbEncodingXCursor) { if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h, rfbEncodingXCursor)) { return False; } continue; } if (rect.encoding == rfbEncodingRichCursor) { if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h, rfbEncodingRichCursor)) { return False; } continue; } if (rect.encoding == rfbEncodingPointerPos) { if (!HandleCursorPos(rect.r.x, rect.r.y)) { return False; } appData.gotCursorPos = 1; continue; } if ((rect.r.x + rect.r.w > si.framebufferWidth) || (rect.r.y + rect.r.h > si.framebufferHeight)) { fprintf(stderr,"Rect too large: %dx%d at (%d, %d)\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y); return False; } if ((rect.r.h * rect.r.w) == 0) { fprintf(stderr,"Zero size rect - ignoring\n"); continue; } /* If RichCursor encoding is used, we should prevent collisions between framebuffer updates and cursor drawing operations. */ SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h); switch (rect.encoding) { case rfbEncodingRaw: bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8; linesToRead = BUFFER_SIZE / bytesPerLine; while (rect.r.h > 0) { if (linesToRead > rect.r.h) linesToRead = rect.r.h; if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead)) return False; CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w, linesToRead); rect.r.h -= linesToRead; rect.r.y += linesToRead; } break; case rfbEncodingCopyRect: { rfbCopyRect cr; char *buffer; if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect)) return False; if (!BufferWritten()) { /* Ignore attempts to do copy-rect when we have nothing to * copy from. */ break; } cr.srcX = Swap16IfLE(cr.srcX); cr.srcY = Swap16IfLE(cr.srcY); /* If RichCursor encoding is used, we should extend our "cursor lock area" (previously set to destination rectangle) to the source rectangle as well. */ SoftCursorLockArea(cr.srcX, cr.srcY, rect.r.w, rect.r.h); buffer = CopyScreenToData(cr.srcX, cr.srcY, rect.r.w, rect.r.h); CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w, rect.r.h); free(buffer); break; } case rfbEncodingRRE: { if (!HandleRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } case rfbEncodingCoRRE: { if (!HandleCoRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } case rfbEncodingHextile: { if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } case rfbEncodingZlib: { if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } case rfbEncodingTight: { if (!HandleTight32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; } case rfbEncodingZRLE: if (!zrleDecode(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) return False; break; default: fprintf(stderr,"Unknown rect encoding %d\n", (int)rect.encoding); return False; } /* Now we may discard "soft cursor locks". */ SoftCursorUnlockScreen(); /* Done. Save the screen image. */ } /* RealVNC sometimes returns an initial black screen. */ if (BufferIsBlank() && appData.ignoreBlank) { if (!appData.quiet && appData.ignoreBlank != 1) { /* user did not specify either -quiet or -ignoreblank */ fprintf(stderr, "Warning: discarding received blank screen (use -allowblank to accept,\n or -ignoreblank to suppress this message)\n"); appData.ignoreBlank = 1; } RequestNewUpdate(); } else { return False; } break; } case rfbBell: /* ignore */ break; case rfbServerCutText: { if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbServerCutTextMsg - 1)) return False; msg.sct.length = Swap32IfLE(msg.sct.length); if (serverCutText) free(serverCutText); serverCutText = malloc(msg.sct.length+1); if (!ReadFromRFBServer(serverCutText, msg.sct.length)) return False; serverCutText[msg.sct.length] = 0; newServerCutText = True; break; } default: fprintf(stderr,"Unknown message type %d from VNC server\n",msg.type); return False; } return True; }
inline Bool HandleRFBServerMessage() { rfbServerToClientMsg msg; if(!ReadExact(rfbsock, (char *)&msg, 1)) return False; dprintf("HandleRFBServerMessage %d\n",msg.type); switch(msg.type) { case rfbSetColourMapEntries: { dprintf("rfbSetColourMapEntries\n"); int i; CARD16 rgb[3]; XColor xc; if(!ReadExact(rfbsock, ((char *)&msg.scme) + 1, sz_rfbSetColourMapEntriesMsg - 1)) return False; msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour); msg.scme.nColours = Swap16IfLE(msg.scme.nColours); INIT_PALETTE(msg.scme.nColours); for(i = 0; i < msg.scme.nColours; i++) { xc.pixel = msg.scme.firstColour + i; if(addUseAlpha) { if(!ReadExact(rfbsock, (char *)rgb, 8)) return False; xc.transp = ((double)(0xff - (Swap16IfLE(rgb[0]) >> 8))) / ((double)0xff / (double)0xA0); xc.red = Swap16IfLE(rgb[1]) >> 8; xc.green = Swap16IfLE(rgb[2]) >> 8; xc.blue = Swap16IfLE(rgb[3]) >> 8; } else { if(!ReadExact(rfbsock, (char *)rgb, 6)) return False; xc.transp = 0; xc.red = Swap16IfLE(rgb[0]) >> 8; xc.green = Swap16IfLE(rgb[1]) >> 8; xc.blue = Swap16IfLE(rgb[2]) >> 8; } xc.flags = DoRed|DoGreen|DoBlue; INSERT_COLOUR (xc); } STORE_PALETTE(NULL); break; } case rfbFramebufferUpdate: { dprintf("rfbFramebufferUpdate\n"); //ShowOsd(True); rfbFramebufferUpdateRectHeader rect; int linesToRead; int bytesPerLine; int i; if(!ReadExact(rfbsock, ((char *)&msg.fu) + 1, sz_rfbFramebufferUpdateMsg - 1)) return False; msg.fu.nRects = Swap16IfLE(msg.fu.nRects); dprintf("# Rect %d\n",msg.fu.nRects); for(i = 0; i < msg.fu.nRects; i++) { if(!ReadExact(rfbsock, (char *)&rect, sz_rfbFramebufferUpdateRectHeader)) return False; rect.r.x = Swap16IfLE(rect.r.x); rect.r.y = Swap16IfLE(rect.r.y); rect.r.w = Swap16IfLE(rect.r.w); rect.r.h = Swap16IfLE(rect.r.h); rect.encoding = Swap32IfLE(rect.encoding); dprintf("Rect x/y/w/h %d/%d/%d/%d %u\n",rect.r.x,rect.r.y,rect.r.w,rect.r.h, (uint)rect.encoding); if((rect.r.x + rect.r.w > si.framebufferWidth) || (rect.r.y + rect.r.h > si.framebufferHeight)) { fprintf(stderr,"%s: rect too large: %dx%d at (%d, %d)\n", programName, rect.r.w, rect.r.h, rect.r.x, rect.r.y); return False; } if((rect.r.h * rect.r.w) == 0) { fprintf(stderr,"%s: zero size rect - ignoring\n",programName); continue; } switch(rect.encoding) { case rfbEncodingRaw: bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8; linesToRead = BUFFER_SIZE / bytesPerLine; while(rect.r.h > 0) { if(linesToRead > rect.r.h) linesToRead = rect.r.h; if(!ReadExact(rfbsock, buffer,bytesPerLine * linesToRead)) return False; CopyDataToScreen((CARD8 *)buffer, rect.r.x, rect.r.y, rect.r.w, linesToRead); rect.r.h -= linesToRead; rect.r.y += linesToRead; } break; case rfbEncodingCopyRect: { dprintf("rfbEncodingCopyRect\n"); rfbCopyRect cr; if(!ReadExact(rfbsock, (char *)&cr, sz_rfbCopyRect)) return False; cr.srcX = Swap16IfLE(cr.srcX); cr.srcY = Swap16IfLE(cr.srcY); COPY_AREA (cr.srcX, cr.srcY, rect.r.w, rect.r.h, rect.r.x, rect.r.y); break; } case rfbEncodingRRE: { dprintf("RRE\n"); rfbRREHeader hdr; CARD8 pix8; CARD16 pix16; CARD32 pix32; rfbRectangle subrect; int j; int dataSize; char *netbuff; char *p; if(!ReadExact(rfbsock, (char *)&hdr, sz_rfbRREHeader)) return False; hdr.nSubrects = Swap32IfLE(hdr.nSubrects); switch(myFormat.bitsPerPixel) { case 8: if(!ReadExact(rfbsock, (char *)&pix8, 1)) return False; FILL_RECTNOREDRAW (rect.r.x, rect.r.y, rect.r.w, rect.r.h, pix8); dataSize = (sizeof(pix8) + sz_rfbRectangle) * hdr.nSubrects; netbuff = malloc(dataSize + 256); if(!ReadExact(rfbsock, netbuff, dataSize)) return False; p = netbuff; for(j = 0; j < hdr.nSubrects; j++) { memcpy((char*)&pix8, p, sizeof(pix8)); p += sizeof(pix8); memcpy((char*)&subrect, p, sz_rfbRectangle); p += sz_rfbRectangle; subrect.x = Swap16IfLE(subrect.x); subrect.y = Swap16IfLE(subrect.y); subrect.w = Swap16IfLE(subrect.w); subrect.h = Swap16IfLE(subrect.h); FILL_RECTNOREDRAW (rect.r.x + subrect.x, rect.r.y + subrect.y, subrect.w, subrect.h, pix8); } free(netbuff); REDRAWBOX(rect.r.x, rect.r.y, rect.r.w, rect.r.h); break; case 16: if(!ReadExact(rfbsock, (char *)&pix16, 2)) return False; FILL_RECTNOREDRAW (rect.r.x, rect.r.y, rect.r.w, rect.r.h, pix16); dataSize = (sizeof(pix16) + sz_rfbRectangle) * hdr.nSubrects; netbuff = malloc(dataSize + 256); if(!ReadExact(rfbsock, netbuff, dataSize)) return False; p = netbuff; for(j = 0; j < hdr.nSubrects; j++) { memcpy((char*)&pix16, p, sizeof(pix16)); p += sizeof(pix16); memcpy((char*)&subrect, p, sz_rfbRectangle); p += sz_rfbRectangle; subrect.x = Swap16IfLE(subrect.x); subrect.y = Swap16IfLE(subrect.y); subrect.w = Swap16IfLE(subrect.w); subrect.h = Swap16IfLE(subrect.h); FILL_RECTNOREDRAW (rect.r.x + subrect.x, rect.r.y + subrect.y, subrect.w, subrect.h, pix16); } free(netbuff); REDRAWBOX(rect.r.x, rect.r.y, rect.r.w, rect.r.h); break; case 32: if(!ReadExact(rfbsock, (char *)&pix32, 4)) return False; FILL_RECTNOREDRAW (rect.r.x, rect.r.y, rect.r.w, rect.r.h, pix32); dataSize = (sizeof(pix32) + sz_rfbRectangle) * hdr.nSubrects; netbuff = malloc(dataSize + 256); if(!ReadExact(rfbsock, netbuff, dataSize)) return False; p = netbuff; for(j = 0; j < hdr.nSubrects; j++) { memcpy((char*)&pix32, p, sizeof(pix32)); p += sizeof(pix32); memcpy((char*)&subrect, p, sz_rfbRectangle); p += sz_rfbRectangle; subrect.x = Swap16IfLE(subrect.x); subrect.y = Swap16IfLE(subrect.y); subrect.w = Swap16IfLE(subrect.w); subrect.h = Swap16IfLE(subrect.h); FILL_RECTNOREDRAW (rect.r.x + subrect.x, rect.r.y + subrect.y, subrect.w, subrect.h, pix32); } free(netbuff); REDRAWBOX(rect.r.x, rect.r.y, rect.r.w, rect.r.h); break; } break; } case rfbEncodingCoRRE: { dprintf("rfbEncodingCoRRE\n"); rfbRREHeader hdr; CARD8 pix8; CARD16 pix16; CARD32 pix32; int j; CARD8 *ptr; register int x, y, w, h; if(!ReadExact(rfbsock, (char *)&hdr, sz_rfbRREHeader)) return False; hdr.nSubrects = Swap32IfLE(hdr.nSubrects); switch(myFormat.bitsPerPixel) { case 8: if(!ReadExact(rfbsock, (char *)&pix8, 1)) return False; FILL_RECT (rect.r.x, rect.r.y, rect.r.w, rect.r.h, pix8); if(!ReadExact(rfbsock, buffer, hdr.nSubrects * 5)) return False; ptr = (CARD8 *)buffer; for(j = 0; j < hdr.nSubrects; j++) { pix8 = *ptr++; x = *ptr++; y = *ptr++; w = *ptr++; h = *ptr++; FILL_RECT (rect.r.x + x, rect.r.y + y, w, h, pix8); } break; case 16: if(!ReadExact(rfbsock, (char *)&pix16, 2)) return False; FILL_RECT (rect.r.x, rect.r.y, rect.r.w, rect.r.h, pix16); if(!ReadExact(rfbsock, buffer, hdr.nSubrects * 6)) return False; ptr = (CARD8 *)buffer; for(j = 0; j < hdr.nSubrects; j++) { pix16 = *(CARD16 *)ptr; ptr += 2; x = *ptr++; y = *ptr++; w = *ptr++; h = *ptr++; FILL_RECT (rect.r.x + x, rect.r.y + y, w, h, pix16); } break; case 32: if(!ReadExact(rfbsock, (char *)&pix32, 4)) return False; FILL_RECT (rect.r.x, rect.r.y, rect.r.w, rect.r.h, pix32); if(!ReadExact(rfbsock, buffer, hdr.nSubrects * 8)) return False; ptr = (CARD8 *)buffer; for(j = 0; j < hdr.nSubrects; j++) { pix32 = *(CARD32 *)ptr; ptr += 4; x = *ptr++; y = *ptr++; w = *ptr++; h = *ptr++; FILL_RECT (rect.r.x + x, rect.r.y + y, w, h, pix32); } break; } break; } case rfbEncodingHextile: { dprintf("Hextile\n"); switch(myFormat.bitsPerPixel) { case 8: if(!HandleHextileEncoding8(rect.r.x, rect.r.y, rect.r.w, rect.r.h)) return False; break; case 16: if(!HandleHextileEncoding16(rect.r.x, rect.r.y, rect.r.w, rect.r.h)) return False; break; case 32: if(!HandleHextileEncoding32(rect.r.x, rect.r.y, rect.r.w, rect.r.h)) return False; break; } break; } default: printf("vnc: unknown rect encoding %u\n",(uint)rect.encoding); return False; } } //sendUpdateRequest = True; break; } case rfbBell: BELL; //ShowOsd(False); break; case rfbServerCutText: { char *str; if(!ReadExact(rfbsock, ((char *)&msg.sct) + 1, sz_rfbServerCutTextMsg - 1)) return False; msg.sct.length = Swap32IfLE(msg.sct.length); str = malloc(msg.sct.length); if(!ReadExact(rfbsock, str, msg.sct.length)) { free(str); return False; } /* XSelectInput(dpy, DefaultRootWindow(dpy), 0); XStoreBytes(dpy, str, msg.sct.length); XSetSelectionOwner(dpy, XA_PRIMARY, None, CurrentTime); XSelectInput(dpy, DefaultRootWindow(dpy), PropertyChangeMask); */ free(str); break; } case rfbReSizeFrameBuffer: { if(!ReadExact(rfbsock, ((char *)&msg.rsfb) + 1, sz_rfbReSizeFrameBufferMsg - 1)) return False; dprintf("rfbReSizeFrameBuffer: %d/%d | %d/%d\n",msg.rsfb.buffer_w,msg.rsfb.buffer_h,msg.rsfb.desktop_w,msg.rsfb.desktop_h); si.framebufferWidth = Swap16IfLE(msg.rsfb.buffer_w); si.framebufferHeight = Swap16IfLE(msg.rsfb.buffer_h); FILL_RECT(0, 0, si.framebufferWidth, si.framebufferHeight, 0); if(!SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, si.framebufferHeight, False)) return False; } break; default: printf("%s: unknown message type %d from VNC server\n", programName,msg.type); return False; }