FramebufferVNC.cpp revision e64031e20c39650a7bc902a3e1aba613b9415dee
/* $Id$ */
/** @file
* VBoxHeadless - VNC server implementation for VirtualBox.
*
* Uses LibVNCServer (http://sourceforge.net/projects/libvncserver/)
*/
/*
* Contributed by Ivo Smits <Ivo@UFO-Net.nl>
*
* Copyright (C) 2006-2007 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include "FramebufferVNC.h"
#include <png.h>
// constructor / destructor
/////////////////////////////////////////////////////////////////////////////
/**
* Perform parts of initialisation which are guaranteed not to fail
* unless we run out of memory. In this case, we just set the guest
* buffer to 0 so that RequestResize() does not free it the first time
* it is called.
*/
mBitsPerPixel(0),
mBytesPerLine(0),
mRGBBuffer(0),
mScreenBuffer(0),
mKeyboard(0),
mMouse(0),
vncServer(0),
{
LogFlow(("Creating VNC object %p, width=%u, height=%u, port=%u\n",
}
LogFlow(("Destroying VNCFB object %p\n", this));
if (vncServer) {
if (vncServer->authPasswdData) {
RTMemFree(papszPassword[0]);
}
}
mRGBBuffer = NULL;
}
LogFlow(("Initialising VNCFB object %p\n", this));
vncServer->screenData = (void*)this;
if (mVncPassword) {
} else {
}
/* Set the initial framebuffer size */
return S_OK;
}
{
return VINF_SUCCESS;
}
}
//RTPrintf("VNC mouse: button=%d x=%d y=%d\n", buttonMask, x, y);
if (!mMouse) {
if (!mMouse) {
RTPrintf("Warning: could not get mouse object!\n");
return;
}
}
//mMouse->PutMouseEventAbsolute(x + 1, y + 1, dz, 0, buttonMask);
mouseX = x;
mouseY = y;
}
}
if (state && !kbdShiftState) {
kbdShiftState = 1;
} else if (!state && kbdShiftState) {
kbdPutCode(0x2a, 0);
kbdShiftState = 0;
}
}
}
}
/* Handle VNC keyboard code (X11 compatible?) to AT scancode conversion.
* Have tried the code from the SDL frontend, but that didn't work.
* Now we're using one lookup table for the lower X11 key codes (ASCII characters)
* and a switch() block to handle some special keys. */
//RTPrintf("VNC keyboard: down=%d code=%d -> ", down, keycode);
if (!mKeyboard) {
RTPrintf("Warning: could not get keyboard object!\n");
return;
}
}
/* Conversion table for key code range 32-127 (which happen to equal the ASCII codes)
* The values in the table differ slightly from the actual scancode values that will be sent,
* values 0xe0?? indicate that a 0xe0 scancode will be sent first (extended keys), then code ?? is sent
* values 0x01?? indicate that the shift key must be 'down', then ?? is sent
* values 0x00?? or 0x?? indicate that the shift key must be 'up', then ?? is sent
* values 0x02?? indicate that the shift key can be ignored, and scancode ?? is sent
* This is necessary because the VNC protocol sends a shift key sequence, but also
* sends the 'shifted' version of the characters. */
static int codes_low[] = { //Conversion table for VNC key code range 32-127
0x0239, 0x0102, 0x0128, 0x0104, 0x0105, 0x0106, 0x0108, 0x0028, 0x010a, 0x010b, 0x0109, 0x010d, 0x0029, 0x000c, 0x0034, 0x0035, //space, !"#$%&'()*+`-./
0x0b, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, //0123456789
0x0127, 0x0027, 0x0133, 0x000d, 0x0134, 0x0135, 0x0103, //:;<=>?@
0x11e, 0x130, 0x12e, 0x120, 0x112, 0x121, 0x122, 0x123, 0x117, 0x124, 0x125, 0x126, 0x132, 0x131, 0x118, 0x119, 0x110, 0x113, 0x11f, 0x114, 0x116, 0x12f, 0x111, 0x12d, 0x115, 0x12c, //A-Z
0x001a, 0x002b, 0x001b, 0x0107, 0x010c, 0x0029, //[\]^_`
0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1f, 0x14, 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c, //a-z
0x011a, 0x012b, 0x011b, 0x0129 //{|}~
};
} else {
switch(keycode) {
/*Numpad keys - these have to be implemented yet
Todo: numpad arrows, home, pageup, pagedown, end, insert, delete
65421 Numpad return
65450 Numpad *
65451 Numpad +
65453 Numpad -
65454 Numpad .
65455 Numpad /
65457 Numpad 1
65458 Numpad 2
65459 Numpad 3
65460 Numpad 4
65461 Numpad 5
65462 Numpad 6
65463 Numpad 7
65464 Numpad 8
65465 Numpad 9
65456 Numpad 0
*/
//case 65377: break; //Print screen
}
}
//RTPrintf("down=%d shift=%d code=%d\n", down, shift, code);
} else if (shift != -1) {
} else if (code != -1) {
}
}
void VNCFB::handleVncKeyboardReleaseEvent() {
kbdSetShift(0);
}
}
}
// IFramebuffer properties
/////////////////////////////////////////////////////////////////////////////
/**
* Requests a resize of our "screen".
*
* @returns COM status code
* @param pixelFormat Layout of the guest video RAM (i.e. 16, 24,
* 32 bpp)
* @param vram host context pointer to the guest video RAM,
* in case we can cope with the format
* @param bitsPerPixel color depth of the guest video RAM
* @param bytesPerLine length of a screen line in the guest video RAM
* @param w video mode width in pixels
* @param h video mode height in pixels
* @retval finished set to true if the method is synchronous and
* to false otherwise
*
* This method is called when the guest attempts to resize the virtual
* screen. The pointer to the guest's video RAM is supplied in case
* the framebuffer can handle the pixel format. If it can't, it should
* allocate a memory buffer itself, and the virtual VGA device will copy
* the guest VRAM to that in a format we can handle. The
* COMGETTER(UsesGuestVRAM) method is used to tell the VGA device which method
* we have chosen, and the other COMGETTER methods tell the device about
* the layout of our buffer. We currently handle all VRAM layouts except
* FramebufferPixelFormat_Opaque (which cannot be handled by
* definition).
*/
/* For now, we are doing things synchronously */
*finished = true;
mWidth = w;
mHeight = h;
mRGBBuffer = NULL;
} else {
mBytesPerLine = w * 4;
mBitsPerPixel = 32;
}
}
RTPrintf("Set framebuffer: buffer=%d w=%lu h=%lu bpp=%d\n", mBufferAddress, mWidth, mHeight, (int)mBitsPerPixel);
return S_OK;
}
//Guest framebuffer update notification
}
rfbMarkRectAsModified(vncServer, x, y, x+w, y+h);
return S_OK;
}
/**
* Return the address of the frame buffer for the virtual VGA device to
* write to. If COMGETTER(UsesGuestVRAM) returns FLASE (or if this address
* is not the same as the guests VRAM buffer), the device will perform
* translation.
*
* @returns COM status code
* @retval address The address of the buffer
*/
return S_OK;
}
/**
* Return the width of our frame buffer.
*
* @returns COM status code
* @retval width The width of the frame buffer
*/
return S_OK;
}
/**
* Return the height of our frame buffer.
*
* @returns COM status code
* @retval height The height of the frame buffer
*/
return S_OK;
}
/**
* Return the colour depth of our frame buffer. Note that we actually
* store the pixel format, not the colour depth internally, since
* when display sets FramebufferPixelFormat_Opaque, it
* wants to retreive FramebufferPixelFormat_Opaque and
* nothing else.
*
* @returns COM status code
* @retval bitsPerPixel The colour depth of the frame buffer
*/
if (!bitsPerPixel) return E_POINTER;
LogFlow(("FFmpeg::COMGETTER(BitsPerPixel): returning depth %lu\n",
(unsigned long) *bitsPerPixel));
return S_OK;
}
/**
* Return the number of bytes per line in our frame buffer.
*
* @returns COM status code
* @retval bytesPerLine The number of bytes per line
*/
if (!bytesPerLine) return E_POINTER;
LogFlow(("FFmpeg::COMGETTER(BytesPerLine): returning line size %lu\n", (unsigned long) mBytesPerLine));
return S_OK;
}
/**
* Return the pixel layout of our frame buffer.
*
* @returns COM status code
* @retval pixelFormat The pixel layout
*/
if (!pixelFormat) return E_POINTER;
LogFlow(("FFmpeg::COMGETTER(PixelFormat): returning pixel format: %lu\n", (unsigned long) mPixelFormat));
return S_OK;
}
/**
* Return whether we use the guest VRAM directly.
*
* @returns COM status code
* @retval pixelFormat The pixel layout
*/
if (!usesGuestVRAM) return E_POINTER;
return S_OK;
}
/**
* Return the number of lines of our frame buffer which can not be used
* (e.g. for status lines etc?).
*
* @returns COM status code
* @retval heightReduction The number of unused lines
*/
if (!heightReduction) return E_POINTER;
/* no reduction */
*heightReduction = 0;
LogFlow(("FFmpeg::COMGETTER(HeightReduction): returning 0\n"));
return S_OK;
}
/**
* Return a pointer to the alpha-blended overlay used to render status icons
* etc above the framebuffer.
*
* @returns COM status code
* @retval aOverlay The overlay framebuffer
*/
/* not yet implemented */
*aOverlay = 0;
LogFlow(("FFmpeg::COMGETTER(Overlay): returning 0\n"));
return S_OK;
}
/**
* Return id of associated window
*
* @returns COM status code
* @retval winId Associated window id
*/
*winId = 0;
return S_OK;
}
// IFramebuffer methods
/////////////////////////////////////////////////////////////////////////////
LogFlow(("VNCFB::Lock: called\n"));
return E_UNEXPECTED;
}
LogFlow(("VNCFB::Unlock: called\n"));
return S_OK;
}
/**
* Returns whether we like the given video mode.
*
* @returns COM status code
*/
*supported = true;
return S_OK;
}
/** Stubbed */
STDMETHODIMP VNCFB::GetVisibleRegion(BYTE *rectangles, ULONG /* count */, ULONG * /* countCopied */) {
if (!rectangles) return E_POINTER;
*rectangles = 0;
return S_OK;
}
/** Stubbed */
if (!rectangles) return E_POINTER;
return S_OK;
}
return E_NOTIMPL;
}
#ifdef VBOX_WITH_XPCOM
#endif