app_server: Remove stubbed HTML5 HWInterface.
It was mostly a renamed copy of the remote HWInterface with beginnings of a webserver and client. It never became actually functional.
This commit is contained in:
@@ -7,7 +7,6 @@ UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing ] ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing interface local ] ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing interface remote ] ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing interface html5 ] ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src servers app stackandtile ] ;
|
||||
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src servers app decorator ] ;
|
||||
@@ -107,7 +106,7 @@ Server app_server :
|
||||
# libraries
|
||||
:
|
||||
libtranslation.so libbe.so libbnetapi.so
|
||||
libaslocal.a libasremote.a libashtml5.a
|
||||
libaslocal.a libasremote.a
|
||||
libasdrawing.a libpainter.a libagg.a
|
||||
[ BuildFeatureAttribute freetype : library ]
|
||||
[ BuildFeatureAttribute fontconfig : library ]
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "ServerConfig.h"
|
||||
|
||||
#include "RemoteHWInterface.h"
|
||||
#include "HTML5HWInterface.h"
|
||||
|
||||
#include <Autolock.h>
|
||||
#include <Entry.h>
|
||||
@@ -141,13 +140,9 @@ ScreenManager::AcquireScreens(ScreenOwner* owner, int32* wishList,
|
||||
// TODO: right now we only support remote screens, but we could
|
||||
// also target specific accelerants to support other graphics cards
|
||||
HWInterface* interface;
|
||||
/*
|
||||
if (strncmp(target, "vnc:", 4) == 0)
|
||||
/*if (strncmp(target, "vnc:", 4) == 0)
|
||||
interface = new(nothrow) VNCHWInterface(target);
|
||||
else*/
|
||||
if (strncmp(target, "html5:", 6) == 0)
|
||||
interface = new(nothrow) HTML5HWInterface(target);
|
||||
else
|
||||
interface = new(nothrow) RemoteHWInterface(target);
|
||||
if (interface != NULL) {
|
||||
screen_item* item = _AddHWInterface(interface);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
SubDir HAIKU_TOP src servers app drawing interface ;
|
||||
|
||||
SubInclude HAIKU_TOP src servers app drawing interface html5 ;
|
||||
SubInclude HAIKU_TOP src servers app drawing interface local ;
|
||||
SubInclude HAIKU_TOP src servers app drawing interface remote ;
|
||||
|
||||
@@ -1,218 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
#include "CanvasEventStream.h"
|
||||
|
||||
#include "CanvasMessage.h"
|
||||
#include "StreamingRingBuffer.h"
|
||||
|
||||
#include <Autolock.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
|
||||
CanvasEventStream::CanvasEventStream()
|
||||
:
|
||||
fEventList(10, true),
|
||||
fEventListLocker("canvas event list"),
|
||||
fEventNotification(-1),
|
||||
fWaitingOnEvent(false),
|
||||
fLatestMouseMovedEvent(NULL),
|
||||
fMousePosition(0, 0),
|
||||
fMouseButtons(0),
|
||||
fModifiers(0)
|
||||
{
|
||||
fEventNotification = create_sem(0, "canvas event notification");
|
||||
}
|
||||
|
||||
|
||||
CanvasEventStream::~CanvasEventStream()
|
||||
{
|
||||
delete_sem(fEventNotification);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CanvasEventStream::UpdateScreenBounds(BRect bounds)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CanvasEventStream::GetNextEvent(BMessage** _event)
|
||||
{
|
||||
BAutolock lock(fEventListLocker);
|
||||
while (fEventList.CountItems() == 0) {
|
||||
fWaitingOnEvent = true;
|
||||
lock.Unlock();
|
||||
|
||||
status_t result;
|
||||
do {
|
||||
result = acquire_sem(fEventNotification);
|
||||
} while (result == B_INTERRUPTED);
|
||||
|
||||
lock.Lock();
|
||||
if (!lock.IsLocked())
|
||||
return false;
|
||||
}
|
||||
|
||||
*_event = fEventList.RemoveItemAt(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CanvasEventStream::InsertEvent(BMessage* event)
|
||||
{
|
||||
BAutolock lock(fEventListLocker);
|
||||
if (!lock.IsLocked())
|
||||
return B_ERROR;
|
||||
|
||||
if (!fEventList.AddItem(event))
|
||||
return B_ERROR;
|
||||
|
||||
if (event->what == B_MOUSE_MOVED)
|
||||
fLatestMouseMovedEvent = event;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
BMessage*
|
||||
CanvasEventStream::PeekLatestMouseMoved()
|
||||
{
|
||||
return fLatestMouseMovedEvent;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CanvasEventStream::EventReceived(CanvasMessage& message)
|
||||
{
|
||||
uint16 code = message.Code();
|
||||
uint32 what = 0;
|
||||
switch (code) {
|
||||
case RP_MOUSE_MOVED:
|
||||
what = B_MOUSE_MOVED;
|
||||
break;
|
||||
case RP_MOUSE_DOWN:
|
||||
what = B_MOUSE_DOWN;
|
||||
break;
|
||||
case RP_MOUSE_UP:
|
||||
what = B_MOUSE_UP;
|
||||
break;
|
||||
case RP_MOUSE_WHEEL_CHANGED:
|
||||
what = B_MOUSE_WHEEL_CHANGED;
|
||||
break;
|
||||
case RP_KEY_DOWN:
|
||||
what = B_KEY_DOWN;
|
||||
break;
|
||||
case RP_KEY_UP:
|
||||
what = B_KEY_UP;
|
||||
break;
|
||||
case RP_MODIFIERS_CHANGED:
|
||||
what = B_MODIFIERS_CHANGED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (what == 0)
|
||||
return false;
|
||||
|
||||
BMessage* event = new BMessage(what);
|
||||
if (event == NULL)
|
||||
return false;
|
||||
|
||||
event->AddInt64("when", system_time());
|
||||
|
||||
switch (code) {
|
||||
case RP_MOUSE_MOVED:
|
||||
case RP_MOUSE_DOWN:
|
||||
case RP_MOUSE_UP:
|
||||
{
|
||||
message.Read(fMousePosition);
|
||||
if (code != RP_MOUSE_MOVED)
|
||||
message.Read(fMouseButtons);
|
||||
|
||||
event->AddPoint("where", fMousePosition);
|
||||
event->AddInt32("buttons", fMouseButtons);
|
||||
event->AddInt32("modifiers", fModifiers);
|
||||
|
||||
if (code == RP_MOUSE_DOWN) {
|
||||
int32 clicks;
|
||||
if (message.Read(clicks) == B_OK)
|
||||
event->AddInt32("clicks", clicks);
|
||||
}
|
||||
|
||||
if (code == RP_MOUSE_MOVED)
|
||||
fLatestMouseMovedEvent = event;
|
||||
break;
|
||||
}
|
||||
|
||||
case RP_MOUSE_WHEEL_CHANGED:
|
||||
{
|
||||
float xDelta, yDelta;
|
||||
message.Read(xDelta);
|
||||
message.Read(yDelta);
|
||||
event->AddFloat("be:wheel_delta_x", xDelta);
|
||||
event->AddFloat("be:wheel_delta_y", yDelta);
|
||||
break;
|
||||
}
|
||||
|
||||
case RP_KEY_DOWN:
|
||||
case RP_KEY_UP:
|
||||
{
|
||||
int32 numBytes;
|
||||
if (message.Read(numBytes) != B_OK)
|
||||
break;
|
||||
|
||||
char* bytes = (char*)malloc(numBytes + 1);
|
||||
if (bytes == NULL)
|
||||
break;
|
||||
|
||||
if (message.ReadList(bytes, numBytes) != B_OK) {
|
||||
free(bytes);
|
||||
break;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < numBytes; i++)
|
||||
event->AddInt8("byte", (int8)bytes[i]);
|
||||
|
||||
bytes[numBytes] = 0;
|
||||
event->AddData("bytes", B_STRING_TYPE, bytes, numBytes + 1, false);
|
||||
event->AddInt32("modifiers", fModifiers);
|
||||
|
||||
int32 rawChar;
|
||||
if (message.Read(rawChar) == B_OK)
|
||||
event->AddInt32("raw_char", rawChar);
|
||||
|
||||
int32 key;
|
||||
if (message.Read(key) == B_OK)
|
||||
event->AddInt32("key", key);
|
||||
|
||||
free(bytes);
|
||||
break;
|
||||
}
|
||||
|
||||
case RP_MODIFIERS_CHANGED:
|
||||
{
|
||||
event->AddInt32("be:old_modifiers", fModifiers);
|
||||
message.Read(fModifiers);
|
||||
event->AddInt32("modifiers", fModifiers);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BAutolock lock(fEventListLocker);
|
||||
fEventList.AddItem(event);
|
||||
if (fWaitingOnEvent) {
|
||||
fWaitingOnEvent = false;
|
||||
lock.Unlock();
|
||||
release_sem(fEventNotification);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
#ifndef CANVAS_EVENT_STREAM_H
|
||||
#define CANVAS_EVENT_STREAM_H
|
||||
|
||||
#include "EventStream.h"
|
||||
|
||||
#include <Locker.h>
|
||||
#include <ObjectList.h>
|
||||
|
||||
class CanvasMessage;
|
||||
|
||||
class CanvasEventStream : public EventStream {
|
||||
public:
|
||||
CanvasEventStream();
|
||||
virtual ~CanvasEventStream();
|
||||
|
||||
virtual bool IsValid() { return true; }
|
||||
virtual void SendQuit() {}
|
||||
|
||||
virtual void UpdateScreenBounds(BRect bounds);
|
||||
virtual bool GetNextEvent(BMessage** _event);
|
||||
virtual status_t InsertEvent(BMessage* event);
|
||||
virtual BMessage* PeekLatestMouseMoved();
|
||||
|
||||
bool EventReceived(CanvasMessage& message);
|
||||
|
||||
private:
|
||||
BObjectList<BMessage> fEventList;
|
||||
BLocker fEventListLocker;
|
||||
sem_id fEventNotification;
|
||||
bool fWaitingOnEvent;
|
||||
BMessage* fLatestMouseMovedEvent;
|
||||
|
||||
BPoint fMousePosition;
|
||||
uint32 fMouseButtons;
|
||||
uint32 fModifiers;
|
||||
};
|
||||
|
||||
#endif // CANVAS_EVENT_STREAM_H
|
||||
@@ -1,500 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
* François Revol <[email protected]>
|
||||
*/
|
||||
|
||||
#include "CanvasMessage.h"
|
||||
|
||||
#include "DrawState.h"
|
||||
#include "ServerBitmap.h"
|
||||
#include "ServerCursor.h"
|
||||
|
||||
#include <Bitmap.h>
|
||||
#include <Font.h>
|
||||
#include <View.h>
|
||||
|
||||
#include <Gradient.h>
|
||||
#include <GradientLinear.h>
|
||||
#include <GradientRadial.h>
|
||||
#include <GradientRadialFocus.h>
|
||||
#include <GradientDiamond.h>
|
||||
#include <GradientConic.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
|
||||
status_t
|
||||
CanvasMessage::NextMessage(uint16& code)
|
||||
{
|
||||
if (fDataLeft > 0) {
|
||||
// discard remainder of message
|
||||
int32 readSize = fSource->Read(NULL, fDataLeft);
|
||||
if (readSize < 0)
|
||||
return readSize;
|
||||
}
|
||||
|
||||
static const uint32 kHeaderSize = sizeof(uint16) + sizeof(uint32);
|
||||
|
||||
fDataLeft = kHeaderSize;
|
||||
Read(code);
|
||||
uint32 dataLeft;
|
||||
status_t result = Read(dataLeft);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
if (dataLeft < kHeaderSize)
|
||||
return B_ERROR;
|
||||
|
||||
fDataLeft = dataLeft - kHeaderSize;
|
||||
fCode = code;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CanvasMessage::Cancel()
|
||||
{
|
||||
fAvailable += fWriteIndex;
|
||||
fWriteIndex = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CanvasMessage::AddBitmap(const ServerBitmap& bitmap, bool minimal)
|
||||
{
|
||||
//TODO:send PNG / as data: or as http: url
|
||||
Add(bitmap.Width());
|
||||
Add(bitmap.Height());
|
||||
Add(bitmap.BytesPerRow());
|
||||
|
||||
if (!minimal) {
|
||||
Add(bitmap.ColorSpace());
|
||||
Add(bitmap.Flags());
|
||||
}
|
||||
|
||||
uint32 bitsLength = bitmap.BitsLength();
|
||||
Add(bitsLength);
|
||||
|
||||
if (!_MakeSpace(bitsLength))
|
||||
return;
|
||||
|
||||
memcpy(fBuffer + fWriteIndex, bitmap.Bits(), bitsLength);
|
||||
fWriteIndex += bitsLength;
|
||||
fAvailable -= bitsLength;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CanvasMessage::AddFont(const ServerFont& font)
|
||||
{
|
||||
//TODO:Use TTF/WOFF URL
|
||||
Add(font.Direction());
|
||||
Add((uint8)font.Encoding());
|
||||
Add(font.Flags());
|
||||
Add((uint8)font.Spacing());
|
||||
Add(font.Shear());
|
||||
Add(font.Rotation());
|
||||
Add(font.FalseBoldWidth());
|
||||
Add(font.Size());
|
||||
Add(font.Face());
|
||||
Add(font.GetFamilyAndStyle());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CanvasMessage::AddDrawState(const DrawState& drawState)
|
||||
{
|
||||
Add(drawState.PenSize());
|
||||
Add(drawState.SubPixelPrecise());
|
||||
Add(drawState.GetDrawingMode());
|
||||
Add(drawState.AlphaSrcMode());
|
||||
Add(drawState.AlphaFncMode());
|
||||
AddPattern(drawState.GetPattern());
|
||||
Add(drawState.LineCapMode());
|
||||
Add(drawState.LineJoinMode());
|
||||
Add(drawState.MiterLimit());
|
||||
Add(drawState.HighColor());
|
||||
Add(drawState.LowColor());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CanvasMessage::AddArrayLine(const ViewLineArrayInfo& line)
|
||||
{
|
||||
Add(line.startPoint);
|
||||
Add(line.endPoint);
|
||||
Add(line.color);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CanvasMessage::AddCursor(const ServerCursor& cursor)
|
||||
{
|
||||
//TODO:send as .cur data:
|
||||
Add(cursor.GetHotSpot());
|
||||
AddBitmap(cursor);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CanvasMessage::AddPattern(const Pattern& pattern)
|
||||
{
|
||||
Add(pattern.GetPattern());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CanvasMessage::AddGradient(const BGradient& gradient)
|
||||
{
|
||||
Add(gradient.GetType());
|
||||
|
||||
switch (gradient.GetType()) {
|
||||
case BGradient::TYPE_NONE:
|
||||
break;
|
||||
|
||||
case BGradient::TYPE_LINEAR:
|
||||
{
|
||||
const BGradientLinear* linear
|
||||
= dynamic_cast<const BGradientLinear *>(&gradient);
|
||||
if (linear == NULL)
|
||||
return;
|
||||
|
||||
Add(linear->Start());
|
||||
Add(linear->End());
|
||||
break;
|
||||
}
|
||||
|
||||
case BGradient::TYPE_RADIAL:
|
||||
{
|
||||
const BGradientRadial* radial
|
||||
= dynamic_cast<const BGradientRadial *>(&gradient);
|
||||
if (radial == NULL)
|
||||
return;
|
||||
|
||||
Add(radial->Center());
|
||||
Add(radial->Radius());
|
||||
break;
|
||||
}
|
||||
|
||||
case BGradient::TYPE_RADIAL_FOCUS:
|
||||
{
|
||||
const BGradientRadialFocus* radialFocus
|
||||
= dynamic_cast<const BGradientRadialFocus *>(&gradient);
|
||||
if (radialFocus == NULL)
|
||||
return;
|
||||
|
||||
Add(radialFocus->Center());
|
||||
Add(radialFocus->Focal());
|
||||
Add(radialFocus->Radius());
|
||||
break;
|
||||
}
|
||||
|
||||
case BGradient::TYPE_DIAMOND:
|
||||
{
|
||||
const BGradientDiamond* diamond
|
||||
= dynamic_cast<const BGradientDiamond *>(&gradient);
|
||||
if (diamond == NULL)
|
||||
return;
|
||||
|
||||
Add(diamond->Center());
|
||||
break;
|
||||
}
|
||||
|
||||
case BGradient::TYPE_CONIC:
|
||||
{
|
||||
const BGradientConic* conic
|
||||
= dynamic_cast<const BGradientConic *>(&gradient);
|
||||
if (conic == NULL)
|
||||
return;
|
||||
|
||||
Add(conic->Center());
|
||||
Add(conic->Angle());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int32 stopCount = gradient.CountColorStops();
|
||||
Add(stopCount);
|
||||
|
||||
for (int32 i = 0; i < stopCount; i++) {
|
||||
BGradient::ColorStop* stop = gradient.ColorStopAt(i);
|
||||
if (stop == NULL)
|
||||
return;
|
||||
|
||||
Add(stop->color);
|
||||
Add(stop->offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CanvasMessage::ReadString(char** _string, size_t& _length)
|
||||
{
|
||||
uint32 length;
|
||||
status_t result = Read(length);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
if (length > fDataLeft)
|
||||
return B_ERROR;
|
||||
|
||||
char *string = (char *)malloc(length + 1);
|
||||
if (string == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
int32 readSize = fSource->Read(string, length);
|
||||
if (readSize < 0) {
|
||||
free(string);
|
||||
return readSize;
|
||||
}
|
||||
|
||||
if ((uint32)readSize != length) {
|
||||
free(string);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
fDataLeft -= readSize;
|
||||
|
||||
string[length] = 0;
|
||||
*_string = string;
|
||||
_length = length;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CanvasMessage::ReadBitmap(BBitmap** _bitmap, bool minimal,
|
||||
color_space colorSpace, uint32 flags)
|
||||
{
|
||||
uint32 bitsLength;
|
||||
int32 width, height, bytesPerRow;
|
||||
|
||||
Read(width);
|
||||
Read(height);
|
||||
Read(bytesPerRow);
|
||||
|
||||
if (!minimal) {
|
||||
Read(colorSpace);
|
||||
Read(flags);
|
||||
}
|
||||
|
||||
Read(bitsLength);
|
||||
|
||||
if (bitsLength > fDataLeft)
|
||||
return B_ERROR;
|
||||
|
||||
#ifndef CLIENT_COMPILE
|
||||
flags = B_BITMAP_NO_SERVER_LINK;
|
||||
#endif
|
||||
|
||||
BBitmap *bitmap = new(std::nothrow) BBitmap(
|
||||
BRect(0, 0, width - 1, height - 1), flags, colorSpace, bytesPerRow);
|
||||
if (bitmap == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t result = bitmap->InitCheck();
|
||||
if (result != B_OK) {
|
||||
delete bitmap;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (bitmap->BitsLength() < (int32)bitsLength) {
|
||||
delete bitmap;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
int32 readSize = fSource->Read(bitmap->Bits(), bitsLength);
|
||||
if ((uint32)readSize != bitsLength) {
|
||||
delete bitmap;
|
||||
return readSize < 0 ? readSize : B_ERROR;
|
||||
}
|
||||
|
||||
fDataLeft -= readSize;
|
||||
*_bitmap = bitmap;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CanvasMessage::ReadFontState(BFont& font)
|
||||
{
|
||||
uint8 encoding, spacing;
|
||||
uint16 face;
|
||||
uint32 flags, familyAndStyle;
|
||||
font_direction direction;
|
||||
float falseBoldWidth, rotation, shear, size;
|
||||
|
||||
Read(direction);
|
||||
Read(encoding);
|
||||
Read(flags);
|
||||
Read(spacing);
|
||||
Read(shear);
|
||||
Read(rotation);
|
||||
Read(falseBoldWidth);
|
||||
Read(size);
|
||||
Read(face);
|
||||
status_t result = Read(familyAndStyle);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
font.SetFamilyAndStyle(familyAndStyle);
|
||||
font.SetEncoding(encoding);
|
||||
font.SetFlags(flags);
|
||||
font.SetSpacing(spacing);
|
||||
font.SetShear(shear);
|
||||
font.SetRotation(rotation);
|
||||
font.SetFalseBoldWidth(falseBoldWidth);
|
||||
font.SetSize(size);
|
||||
font.SetFace(face);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CanvasMessage::ReadViewState(BView& view, ::pattern& pattern)
|
||||
{
|
||||
bool subPixelPrecise;
|
||||
float penSize, miterLimit;
|
||||
drawing_mode drawingMode;
|
||||
source_alpha sourceAlpha;
|
||||
alpha_function alphaFunction;
|
||||
cap_mode capMode;
|
||||
join_mode joinMode;
|
||||
rgb_color highColor, lowColor;
|
||||
|
||||
Read(penSize);
|
||||
Read(subPixelPrecise);
|
||||
Read(drawingMode);
|
||||
Read(sourceAlpha);
|
||||
Read(alphaFunction);
|
||||
Read(pattern);
|
||||
Read(capMode);
|
||||
Read(joinMode);
|
||||
Read(miterLimit);
|
||||
Read(highColor);
|
||||
status_t result = Read(lowColor);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
uint32 flags = view.Flags() & ~B_SUBPIXEL_PRECISE;
|
||||
view.SetFlags(flags | (subPixelPrecise ? B_SUBPIXEL_PRECISE : 0));
|
||||
view.SetPenSize(penSize);
|
||||
view.SetDrawingMode(drawingMode);
|
||||
view.SetBlendingMode(sourceAlpha, alphaFunction);
|
||||
view.SetLineMode(capMode, joinMode, miterLimit);
|
||||
view.SetHighColor(highColor);
|
||||
view.SetLowColor(lowColor);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CanvasMessage::ReadGradient(BGradient** _gradient)
|
||||
{
|
||||
BGradient::Type type;
|
||||
Read(type);
|
||||
|
||||
BGradient *gradient = NULL;
|
||||
switch (type) {
|
||||
case BGradient::TYPE_NONE:
|
||||
break;
|
||||
|
||||
case BGradient::TYPE_LINEAR:
|
||||
{
|
||||
BPoint start, end;
|
||||
|
||||
Read(start);
|
||||
Read(end);
|
||||
|
||||
gradient = new(std::nothrow) BGradientLinear(start, end);
|
||||
break;
|
||||
}
|
||||
|
||||
case BGradient::TYPE_RADIAL:
|
||||
{
|
||||
BPoint center;
|
||||
float radius;
|
||||
|
||||
Read(center);
|
||||
Read(radius);
|
||||
|
||||
gradient = new(std::nothrow) BGradientRadial(center, radius);
|
||||
break;
|
||||
}
|
||||
|
||||
case BGradient::TYPE_RADIAL_FOCUS:
|
||||
{
|
||||
BPoint center, focal;
|
||||
float radius;
|
||||
|
||||
Read(center);
|
||||
Read(focal);
|
||||
Read(radius);
|
||||
|
||||
gradient = new(std::nothrow) BGradientRadialFocus(center, radius,
|
||||
focal);
|
||||
break;
|
||||
}
|
||||
|
||||
case BGradient::TYPE_DIAMOND:
|
||||
{
|
||||
BPoint center;
|
||||
|
||||
Read(center);
|
||||
|
||||
gradient = new(std::nothrow) BGradientDiamond(center);
|
||||
break;
|
||||
}
|
||||
|
||||
case BGradient::TYPE_CONIC:
|
||||
{
|
||||
BPoint center;
|
||||
float angle;
|
||||
|
||||
Read(center);
|
||||
Read(angle);
|
||||
|
||||
gradient = new(std::nothrow) BGradientConic(center, angle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (gradient == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
int32 stopCount;
|
||||
status_t result = Read(stopCount);
|
||||
if (result != B_OK) {
|
||||
delete gradient;
|
||||
return result;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < stopCount; i++) {
|
||||
rgb_color color;
|
||||
float offset;
|
||||
|
||||
Read(color);
|
||||
result = Read(offset);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
gradient->AddColor(color, offset);
|
||||
}
|
||||
|
||||
*_gradient = gradient;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CanvasMessage::ReadArrayLine(BPoint& startPoint, BPoint& endPoint,
|
||||
rgb_color& color)
|
||||
{
|
||||
Read(startPoint);
|
||||
Read(endPoint);
|
||||
return Read(color);
|
||||
}
|
||||
@@ -1,372 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
* François Revol <[email protected]>
|
||||
*/
|
||||
#ifndef CANVAS_MESSAGE_H
|
||||
#define CANVAS_MESSAGE_H
|
||||
|
||||
#include "PatternHandler.h"
|
||||
#include <ViewPrivate.h>
|
||||
|
||||
#include "StreamingRingBuffer.h"
|
||||
#include "base64.h"
|
||||
|
||||
#include <GraphicsDefs.h>
|
||||
#include <Region.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
class BBitmap;
|
||||
class BFont;
|
||||
class BGradient;
|
||||
class BView;
|
||||
class DrawState;
|
||||
class Pattern;
|
||||
class RemotePainter;
|
||||
class ServerBitmap;
|
||||
class ServerCursor;
|
||||
class ServerFont;
|
||||
class ViewLineArrayInfo;
|
||||
|
||||
enum {
|
||||
RP_INIT_CONNECTION = 1,
|
||||
RP_UPDATE_DISPLAY_MODE,
|
||||
RP_CLOSE_CONNECTION,
|
||||
|
||||
RP_CREATE_STATE = 20,
|
||||
RP_DELETE_STATE,
|
||||
RP_ENABLE_SYNC_DRAWING,
|
||||
RP_DISABLE_SYNC_DRAWING,
|
||||
RP_INVALIDATE_RECT,
|
||||
RP_INVALIDATE_REGION,
|
||||
|
||||
RP_SET_OFFSETS = 40,
|
||||
RP_SET_HIGH_COLOR,
|
||||
RP_SET_LOW_COLOR,
|
||||
RP_SET_PEN_SIZE,
|
||||
RP_SET_STROKE_MODE,
|
||||
RP_SET_BLENDING_MODE,
|
||||
RP_SET_PATTERN,
|
||||
RP_SET_DRAWING_MODE,
|
||||
RP_SET_FONT,
|
||||
|
||||
RP_CONSTRAIN_CLIPPING_REGION = 60,
|
||||
RP_COPY_RECT_NO_CLIPPING,
|
||||
RP_INVERT_RECT,
|
||||
RP_DRAW_BITMAP,
|
||||
RP_DRAW_BITMAP_RECTS,
|
||||
|
||||
RP_STROKE_ARC = 80,
|
||||
RP_STROKE_BEZIER,
|
||||
RP_STROKE_ELLIPSE,
|
||||
RP_STROKE_POLYGON,
|
||||
RP_STROKE_RECT,
|
||||
RP_STROKE_ROUND_RECT,
|
||||
RP_STROKE_SHAPE,
|
||||
RP_STROKE_TRIANGLE,
|
||||
RP_STROKE_LINE,
|
||||
RP_STROKE_LINE_ARRAY,
|
||||
|
||||
RP_FILL_ARC = 100,
|
||||
RP_FILL_BEZIER,
|
||||
RP_FILL_ELLIPSE,
|
||||
RP_FILL_POLYGON,
|
||||
RP_FILL_RECT,
|
||||
RP_FILL_ROUND_RECT,
|
||||
RP_FILL_SHAPE,
|
||||
RP_FILL_TRIANGLE,
|
||||
RP_FILL_REGION,
|
||||
|
||||
RP_FILL_ARC_GRADIENT = 120,
|
||||
RP_FILL_BEZIER_GRADIENT,
|
||||
RP_FILL_ELLIPSE_GRADIENT,
|
||||
RP_FILL_POLYGON_GRADIENT,
|
||||
RP_FILL_RECT_GRADIENT,
|
||||
RP_FILL_ROUND_RECT_GRADIENT,
|
||||
RP_FILL_SHAPE_GRADIENT,
|
||||
RP_FILL_TRIANGLE_GRADIENT,
|
||||
RP_FILL_REGION_GRADIENT,
|
||||
|
||||
RP_STROKE_POINT_COLOR = 140,
|
||||
RP_STROKE_LINE_1PX_COLOR,
|
||||
RP_STROKE_RECT_1PX_COLOR,
|
||||
|
||||
RP_FILL_RECT_COLOR = 160,
|
||||
RP_FILL_REGION_COLOR_NO_CLIPPING,
|
||||
|
||||
RP_DRAW_STRING = 180,
|
||||
RP_DRAW_STRING_WITH_OFFSETS,
|
||||
RP_DRAW_STRING_RESULT,
|
||||
RP_STRING_WIDTH,
|
||||
RP_STRING_WIDTH_RESULT,
|
||||
RP_READ_BITMAP,
|
||||
RP_READ_BITMAP_RESULT,
|
||||
|
||||
RP_SET_CURSOR = 200,
|
||||
RP_SET_CURSOR_VISIBLE,
|
||||
RP_MOVE_CURSOR_TO,
|
||||
|
||||
RP_MOUSE_MOVED = 220,
|
||||
RP_MOUSE_DOWN,
|
||||
RP_MOUSE_UP,
|
||||
RP_MOUSE_WHEEL_CHANGED,
|
||||
|
||||
RP_KEY_DOWN = 240,
|
||||
RP_KEY_UP,
|
||||
RP_UNMAPPED_KEY_DOWN,
|
||||
RP_UNMAPPED_KEY_UP,
|
||||
RP_MODIFIERS_CHANGED
|
||||
};
|
||||
|
||||
|
||||
class CanvasMessage {
|
||||
public:
|
||||
CanvasMessage(StreamingRingBuffer* source,
|
||||
StreamingRingBuffer *target);
|
||||
~CanvasMessage();
|
||||
|
||||
void Start(uint16 code);
|
||||
status_t Flush();
|
||||
void Cancel();
|
||||
|
||||
status_t NextMessage(uint16& code);
|
||||
uint16 Code() { return fCode; }
|
||||
uint32 DataLeft() { return fDataLeft; }
|
||||
|
||||
template<typename T>
|
||||
void Add(const T& value);
|
||||
|
||||
void AddString(const char* string, size_t length);
|
||||
void AddRegion(const BRegion& region);
|
||||
void AddGradient(const BGradient& gradient);
|
||||
|
||||
void AddBitmap(const ServerBitmap& bitmap,
|
||||
bool minimal = false);
|
||||
void AddFont(const ServerFont& font);
|
||||
void AddPattern(const Pattern& pattern);
|
||||
void AddDrawState(const DrawState& drawState);
|
||||
void AddArrayLine(const ViewLineArrayInfo& line);
|
||||
void AddCursor(const ServerCursor& cursor);
|
||||
|
||||
template<typename T>
|
||||
void AddList(const T* array, int32 count);
|
||||
|
||||
template<typename T>
|
||||
status_t Read(T& value);
|
||||
|
||||
status_t ReadRegion(BRegion& region);
|
||||
status_t ReadFontState(BFont& font);
|
||||
// sets font state
|
||||
status_t ReadViewState(BView& view, ::pattern& pattern);
|
||||
// sets viewstate and returns pattern
|
||||
|
||||
status_t ReadString(char** _string, size_t& length);
|
||||
status_t ReadBitmap(BBitmap** _bitmap,
|
||||
bool minimal = false,
|
||||
color_space colorSpace = B_RGB32,
|
||||
uint32 flags = 0);
|
||||
status_t ReadGradient(BGradient** _gradient);
|
||||
status_t ReadArrayLine(BPoint& startPoint,
|
||||
BPoint& endPoint, rgb_color& color);
|
||||
|
||||
template<typename T>
|
||||
status_t ReadList(T* array, int32 count);
|
||||
|
||||
private:
|
||||
bool _MakeSpace(size_t size);
|
||||
|
||||
StreamingRingBuffer* fSource;
|
||||
StreamingRingBuffer* fTarget;
|
||||
|
||||
uint8* fBuffer;
|
||||
size_t fAvailable;
|
||||
size_t fWriteIndex;
|
||||
uint32 fDataLeft;
|
||||
uint16 fCode;
|
||||
};
|
||||
|
||||
|
||||
inline
|
||||
CanvasMessage::CanvasMessage(StreamingRingBuffer* source,
|
||||
StreamingRingBuffer* target)
|
||||
:
|
||||
fSource(source),
|
||||
fTarget(target),
|
||||
fBuffer(NULL),
|
||||
fAvailable(0),
|
||||
fWriteIndex(0),
|
||||
fDataLeft(0),
|
||||
fCode(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
CanvasMessage::~CanvasMessage()
|
||||
{
|
||||
if (fWriteIndex > 0)
|
||||
Flush();
|
||||
free(fBuffer);
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
CanvasMessage::Start(uint16 code)
|
||||
{
|
||||
if (fWriteIndex > 0)
|
||||
Flush();
|
||||
|
||||
Add(code);
|
||||
|
||||
// uint32 sizeDummy;
|
||||
// Add(sizeDummy);
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
CanvasMessage::Flush()
|
||||
{
|
||||
if (fWriteIndex == 0)
|
||||
return B_NO_INIT;
|
||||
|
||||
// end by the multipart boundary
|
||||
static const char boundary[] = "--x\r\n\r\n";
|
||||
AddString(boundary, sizeof(boundary) - 1);
|
||||
|
||||
uint32 length = fWriteIndex;
|
||||
fAvailable += fWriteIndex;
|
||||
fWriteIndex = 0;
|
||||
|
||||
// memcpy(fBuffer + sizeof(uint16) * 2, &length, sizeof(uint32));
|
||||
return fTarget->Write(fBuffer, length);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline void
|
||||
CanvasMessage::Add(const T& value)
|
||||
{
|
||||
ssize_t done;
|
||||
|
||||
if (!_MakeSpace(sizeof(T) * 2)) // 4/3 actually
|
||||
return;
|
||||
|
||||
//memcpy(fBuffer + fWriteIndex, &value, sizeof(T));
|
||||
done = encode_base64((char *)fBuffer + fWriteIndex, (const char *)(&value),
|
||||
sizeof(T));
|
||||
fWriteIndex += done;
|
||||
fAvailable -= done;
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
CanvasMessage::AddString(const char* string, size_t length)
|
||||
{
|
||||
Add(length);
|
||||
if (length > fAvailable && !_MakeSpace(length))
|
||||
return;
|
||||
|
||||
memcpy(fBuffer + fWriteIndex, string, length);
|
||||
fWriteIndex += length;
|
||||
fAvailable -= length;
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
CanvasMessage::AddRegion(const BRegion& region)
|
||||
{
|
||||
int32 rectCount = region.CountRects();
|
||||
Add(rectCount);
|
||||
|
||||
for (int32 i = 0; i < rectCount; i++)
|
||||
Add(region.RectAt(i));
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline void
|
||||
CanvasMessage::AddList(const T* array, int32 count)
|
||||
{
|
||||
for (int32 i = 0; i < count; i++)
|
||||
Add(array[i]);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline status_t
|
||||
CanvasMessage::Read(T& value)
|
||||
{
|
||||
//TODO
|
||||
if (fDataLeft < sizeof(T))
|
||||
return B_ERROR;
|
||||
|
||||
int32 readSize = fSource->Read(&value, sizeof(T));
|
||||
if (readSize < 0)
|
||||
return readSize;
|
||||
|
||||
if (readSize != sizeof(T))
|
||||
return B_ERROR;
|
||||
|
||||
fDataLeft -= sizeof(T);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
CanvasMessage::ReadRegion(BRegion& region)
|
||||
{
|
||||
region.MakeEmpty();
|
||||
|
||||
int32 rectCount;
|
||||
Read(rectCount);
|
||||
|
||||
for (int32 i = 0; i < rectCount; i++) {
|
||||
BRect rect;
|
||||
status_t result = Read(rect);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
region.Include(rect);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline status_t
|
||||
CanvasMessage::ReadList(T* array, int32 count)
|
||||
{
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
status_t result = Read(array[i]);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
inline bool
|
||||
CanvasMessage::_MakeSpace(size_t size)
|
||||
{
|
||||
if (fAvailable >= size)
|
||||
return true;
|
||||
|
||||
size_t extraSize = size + 20;
|
||||
uint8 *newBuffer = (uint8*)realloc(fBuffer, fWriteIndex + extraSize);
|
||||
if (newBuffer == NULL)
|
||||
return false;
|
||||
|
||||
fAvailable = extraSize;
|
||||
fBuffer = newBuffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // CANVAS_MESSAGE_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,180 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
* François Revol <revol@free.fr>
|
||||
*/
|
||||
#ifndef HTML5_DRAWING_ENGINE_H
|
||||
#define HTML5_DRAWING_ENGINE_H
|
||||
|
||||
#include "DrawingEngine.h"
|
||||
#include "DrawState.h"
|
||||
#include "HTML5HWInterface.h"
|
||||
#include "ServerFont.h"
|
||||
|
||||
class BPoint;
|
||||
class BRect;
|
||||
class BRegion;
|
||||
|
||||
class BitmapDrawingEngine;
|
||||
class ServerBitmap;
|
||||
|
||||
class HTML5DrawingEngine : public DrawingEngine {
|
||||
public:
|
||||
HTML5DrawingEngine(
|
||||
HTML5HWInterface* interface);
|
||||
virtual ~HTML5DrawingEngine();
|
||||
|
||||
// HWInterfaceListener interface
|
||||
virtual void FrameBufferChanged();
|
||||
|
||||
virtual void SetCopyToFrontEnabled(bool enabled);
|
||||
|
||||
// for screen shots
|
||||
virtual status_t ReadBitmap(ServerBitmap* bitmap,
|
||||
bool drawCursor, BRect bounds);
|
||||
|
||||
// clipping for all drawing functions, passing a NULL region
|
||||
// will remove any clipping (drawing allowed everywhere)
|
||||
virtual void ConstrainClippingRegion(const BRegion* region);
|
||||
|
||||
virtual void SetDrawState(const DrawState* state,
|
||||
int32 xOffset = 0, int32 yOffset = 0);
|
||||
|
||||
virtual void SetHighColor(const rgb_color& color);
|
||||
virtual void SetLowColor(const rgb_color& color);
|
||||
virtual void SetPenSize(float size);
|
||||
virtual void SetStrokeMode(cap_mode lineCap,
|
||||
join_mode joinMode, float miterLimit);
|
||||
virtual void SetPattern(const struct pattern& pattern);
|
||||
virtual void SetDrawingMode(drawing_mode mode);
|
||||
virtual void SetDrawingMode(drawing_mode mode,
|
||||
drawing_mode& oldMode);
|
||||
virtual void SetBlendingMode(source_alpha srcAlpha,
|
||||
alpha_function alphaFunc);
|
||||
virtual void SetFont(const ServerFont& font);
|
||||
virtual void SetFont(const DrawState* state);
|
||||
|
||||
// drawing functions
|
||||
virtual void InvertRect(BRect rect);
|
||||
|
||||
virtual void DrawBitmap(ServerBitmap* bitmap,
|
||||
const BRect& bitmapRect,
|
||||
const BRect& viewRect, uint32 options = 0);
|
||||
|
||||
// drawing primitives
|
||||
virtual void DrawArc(BRect rect, const float& angle,
|
||||
const float& span, bool filled);
|
||||
virtual void FillArc(BRect rect, const float& angle,
|
||||
const float& span,
|
||||
const BGradient& gradient);
|
||||
|
||||
virtual void DrawBezier(BPoint* points, bool filled);
|
||||
virtual void FillBezier(BPoint* points,
|
||||
const BGradient& gradient);
|
||||
|
||||
virtual void DrawEllipse(BRect rect, bool filled);
|
||||
virtual void FillEllipse(BRect rect,
|
||||
const BGradient& gradient);
|
||||
|
||||
virtual void DrawPolygon(BPoint* pointList, int32 numPoints,
|
||||
BRect bounds, bool filled, bool closed);
|
||||
virtual void FillPolygon(BPoint* pointList, int32 numPoints,
|
||||
BRect bounds, const BGradient& gradient,
|
||||
bool closed);
|
||||
|
||||
// these rgb_color versions are used internally by the server
|
||||
virtual void StrokePoint(const BPoint& point,
|
||||
const rgb_color& color);
|
||||
virtual void StrokeRect(BRect rect, const rgb_color &color);
|
||||
virtual void FillRect(BRect rect, const rgb_color &color);
|
||||
virtual void FillRegion(BRegion& region,
|
||||
const rgb_color& color);
|
||||
|
||||
virtual void StrokeRect(BRect rect);
|
||||
virtual void FillRect(BRect rect);
|
||||
virtual void FillRect(BRect rect, const BGradient& gradient);
|
||||
|
||||
virtual void FillRegion(BRegion& region);
|
||||
virtual void FillRegion(BRegion& region,
|
||||
const BGradient& gradient);
|
||||
|
||||
virtual void DrawRoundRect(BRect rect, float xRadius,
|
||||
float yRadius, bool filled);
|
||||
virtual void FillRoundRect(BRect rect, float xRadius,
|
||||
float yRadius, const BGradient& gradient);
|
||||
|
||||
virtual void DrawShape(const BRect& bounds,
|
||||
int32 opCount, const uint32* opList,
|
||||
int32 pointCount, const BPoint* pointList,
|
||||
bool filled,
|
||||
const BPoint& viewToScreenOffset,
|
||||
float viewScale);
|
||||
virtual void FillShape(const BRect& bounds,
|
||||
int32 opCount, const uint32* opList,
|
||||
int32 pointCount, const BPoint* pointList,
|
||||
const BGradient& gradient,
|
||||
const BPoint& viewToScreenOffset,
|
||||
float viewScale);
|
||||
|
||||
virtual void DrawTriangle(BPoint* points,
|
||||
const BRect& bounds, bool filled);
|
||||
virtual void FillTriangle(BPoint* points,
|
||||
const BRect& bounds,
|
||||
const BGradient& gradient);
|
||||
|
||||
// these versions are used by the Decorator
|
||||
virtual void StrokeLine(const BPoint& start,
|
||||
const BPoint& end, const rgb_color& color);
|
||||
virtual void StrokeLine(const BPoint& start,
|
||||
const BPoint& end);
|
||||
virtual void StrokeLineArray(int32 numlines,
|
||||
const ViewLineArrayInfo* data);
|
||||
|
||||
// returns the pen position behind the (virtually) drawn string
|
||||
virtual BPoint DrawString(const char* string, int32 length,
|
||||
const BPoint& point,
|
||||
escapement_delta* delta = NULL);
|
||||
virtual BPoint DrawString(const char* string, int32 length,
|
||||
const BPoint* offsets);
|
||||
|
||||
virtual float StringWidth(const char* string, int32 length,
|
||||
escapement_delta* delta = NULL);
|
||||
|
||||
// software rendering backend invoked by CopyRegion() for the sorted
|
||||
// individual rects
|
||||
virtual BRect CopyRect(BRect rect, int32 xOffset,
|
||||
int32 yOffset) const;
|
||||
|
||||
private:
|
||||
status_t _AddCallback();
|
||||
|
||||
static bool _DrawingEngineResult(void* cookie,
|
||||
CanvasMessage& message);
|
||||
|
||||
BRect _BuildBounds(BPoint* points, int32 pointCount);
|
||||
status_t _ExtractBitmapRegions(ServerBitmap& bitmap,
|
||||
uint32 options, const BRect& bitmapRect,
|
||||
const BRect& viewRect, double xScale,
|
||||
double yScale, BRegion& region,
|
||||
UtilityBitmap**& bitmaps);
|
||||
|
||||
HTML5HWInterface* fHWInterface;
|
||||
addr_t fToken;
|
||||
|
||||
DrawState fState;
|
||||
BRegion fClippingRegion;
|
||||
float fExtendWidth;
|
||||
|
||||
bool fCallbackAdded;
|
||||
sem_id fResultNotify;
|
||||
BPoint fDrawStringResult;
|
||||
float fStringWidthResult;
|
||||
BBitmap* fReadBitmapResult;
|
||||
|
||||
BitmapDrawingEngine* fBitmapDrawingEngine;
|
||||
};
|
||||
|
||||
#endif // HTML5_DRAWING_ENGINE_H
|
||||
@@ -1,639 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
* François Revol <revol@free.fr>
|
||||
*/
|
||||
|
||||
#include "HTML5HWInterface.h"
|
||||
#include "HTML5DrawingEngine.h"
|
||||
#include "CanvasEventStream.h"
|
||||
#include "CanvasMessage.h"
|
||||
|
||||
#include "WebHandler.h"
|
||||
#include "WebServer.h"
|
||||
#include "WebWorker.h"
|
||||
//#include "NetReceiver.h"
|
||||
//#include "NetSender.h"
|
||||
#include "StreamingRingBuffer.h"
|
||||
|
||||
#include "desktop.html.h"
|
||||
#include "haiku.js.h"
|
||||
|
||||
#include <Autolock.h>
|
||||
#include <NetEndpoint.h>
|
||||
|
||||
#include <new>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define TRACE(x...) debug_printf("HTML5HWInterface: " x)
|
||||
#define TRACE_ALWAYS(x...) debug_printf("HTML5HWInterface: "x)
|
||||
#define TRACE_ERROR(x...) debug_printf("HTML5HWInterface: " x)
|
||||
|
||||
|
||||
struct callback_info {
|
||||
uint32 token;
|
||||
HTML5HWInterface::CallbackFunction callback;
|
||||
void* cookie;
|
||||
};
|
||||
|
||||
|
||||
HTML5HWInterface::HTML5HWInterface(const char* target)
|
||||
:
|
||||
HWInterface(),
|
||||
fTarget(target),
|
||||
fRemoteHost(NULL),
|
||||
fRemotePort(10900),
|
||||
fIsConnected(false),
|
||||
fProtocolVersion(100),
|
||||
fConnectionSpeed(0),
|
||||
fListenPort(10901),
|
||||
fReceiveEndpoint(NULL),
|
||||
fSendBuffer(NULL),
|
||||
fReceiveBuffer(NULL),
|
||||
fServer(NULL),
|
||||
// fSender(NULL),
|
||||
// fReceiver(NULL),
|
||||
fEventThread(-1),
|
||||
fEventStream(NULL),
|
||||
fCallbackLocker("callback locker")
|
||||
{
|
||||
fDisplayMode.virtual_width = 640;
|
||||
fDisplayMode.virtual_height = 480;
|
||||
fDisplayMode.space = B_RGB32;
|
||||
fDisplayMode.h_display_start = 0;
|
||||
fDisplayMode.v_display_start = 0;
|
||||
fDisplayMode.flags = 0;
|
||||
|
||||
//TODO: Cleanup; parse host ??
|
||||
fRemoteHost = strdup(fTarget);
|
||||
if (strncmp(fRemoteHost, "html5:", 6) != 0) {
|
||||
fInitStatus = B_BAD_VALUE;
|
||||
return;
|
||||
}
|
||||
char *portStart = fRemoteHost + 5;//strchr(fRemoteHost + 6, ':');
|
||||
if (portStart != NULL) {
|
||||
portStart[0] = 0;
|
||||
portStart++;
|
||||
if (sscanf(portStart, "%" B_PRIu32, &fRemotePort) != 1) {
|
||||
fInitStatus = B_BAD_VALUE;
|
||||
return;
|
||||
}
|
||||
|
||||
fListenPort = fRemotePort;
|
||||
}
|
||||
|
||||
fReceiveEndpoint = new(std::nothrow) BNetEndpoint();
|
||||
if (fReceiveEndpoint == NULL) {
|
||||
fInitStatus = B_NO_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
fInitStatus = fReceiveEndpoint->Bind(fListenPort);
|
||||
if (fInitStatus != B_OK)
|
||||
return;
|
||||
|
||||
fSendBuffer = new(std::nothrow) StreamingRingBuffer(16 * 1024);
|
||||
if (fSendBuffer == NULL) {
|
||||
fInitStatus = B_NO_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
fInitStatus = fSendBuffer->InitCheck();
|
||||
if (fInitStatus != B_OK)
|
||||
return;
|
||||
|
||||
fReceiveBuffer = new(std::nothrow) StreamingRingBuffer(16 * 1024);
|
||||
if (fReceiveBuffer == NULL) {
|
||||
fInitStatus = B_NO_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
fInitStatus = fReceiveBuffer->InitCheck();
|
||||
if (fInitStatus != B_OK)
|
||||
return;
|
||||
|
||||
fServer = new(std::nothrow) WebServer(fReceiveEndpoint);
|
||||
if (fServer == NULL) {
|
||||
fInitStatus = B_NO_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
WebHandler *handler;
|
||||
handler = new(std::nothrow) WebHandler("output", fSendBuffer);
|
||||
if (handler == NULL) {
|
||||
fInitStatus = B_NO_MEMORY;
|
||||
return;
|
||||
}
|
||||
handler->SetMultipart();
|
||||
handler->SetType("multipart/x-mixed-replace;boundary=x");
|
||||
fServer->AddHandler(handler);
|
||||
|
||||
handler = new(std::nothrow) WebHandler("input", fReceiveBuffer);
|
||||
if (handler == NULL) {
|
||||
fInitStatus = B_NO_MEMORY;
|
||||
return;
|
||||
}
|
||||
fServer->AddHandler(handler);
|
||||
|
||||
handler = new(std::nothrow) WebHandler("desktop.html",
|
||||
new(std::nothrow) BMemoryIO(desktop_html, sizeof(desktop_html) - 1));
|
||||
if (handler == NULL) {
|
||||
fInitStatus = B_NO_MEMORY;
|
||||
return;
|
||||
}
|
||||
fServer->AddHandler(handler);
|
||||
|
||||
handler = new(std::nothrow) WebHandler("haiku.js",
|
||||
new(std::nothrow) BMemoryIO(haiku_js, sizeof(haiku_js) - 1));
|
||||
if (handler == NULL) {
|
||||
fInitStatus = B_NO_MEMORY;
|
||||
return;
|
||||
}
|
||||
fServer->AddHandler(handler);
|
||||
|
||||
|
||||
fEventStream = new(std::nothrow) CanvasEventStream();
|
||||
if (fEventStream == NULL) {
|
||||
fInitStatus = B_NO_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
// fInitStatus = _Connect();
|
||||
// if (fInitStatus != B_OK)
|
||||
// return;
|
||||
fDisplayMode.virtual_width = 800;
|
||||
fDisplayMode.virtual_height = 600;
|
||||
|
||||
|
||||
fEventThread = spawn_thread(_EventThreadEntry, "HTML5 event thread",
|
||||
B_NORMAL_PRIORITY, this);
|
||||
if (fEventThread < 0) {
|
||||
fInitStatus = fEventThread;
|
||||
return;
|
||||
}
|
||||
|
||||
resume_thread(fEventThread);
|
||||
}
|
||||
|
||||
|
||||
HTML5HWInterface::~HTML5HWInterface()
|
||||
{
|
||||
// delete fReceiver;
|
||||
delete fReceiveBuffer;
|
||||
|
||||
delete fSendBuffer;
|
||||
// delete fSender;
|
||||
|
||||
delete fReceiveEndpoint;
|
||||
// delete fSendEndpoint;
|
||||
delete fServer;
|
||||
|
||||
delete fEventStream;
|
||||
|
||||
free(fRemoteHost);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::Initialize()
|
||||
{
|
||||
return fInitStatus;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::Shutdown()
|
||||
{
|
||||
_Disconnect();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
DrawingEngine*
|
||||
HTML5HWInterface::CreateDrawingEngine()
|
||||
{
|
||||
return new(std::nothrow) HTML5DrawingEngine(this);
|
||||
}
|
||||
|
||||
|
||||
EventStream*
|
||||
HTML5HWInterface::CreateEventStream()
|
||||
{
|
||||
return fEventStream;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::AddCallback(uint32 token, CallbackFunction callback,
|
||||
void* cookie)
|
||||
{
|
||||
BAutolock lock(fCallbackLocker);
|
||||
int32 index = fCallbacks.BinarySearchIndexByKey(token, &_CallbackCompare);
|
||||
if (index >= 0)
|
||||
return B_NAME_IN_USE;
|
||||
|
||||
callback_info* info = new(std::nothrow) callback_info;
|
||||
if (info == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
info->token = token;
|
||||
info->callback = callback;
|
||||
info->cookie = cookie;
|
||||
|
||||
fCallbacks.AddItem(info, -index - 1);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
HTML5HWInterface::RemoveCallback(uint32 token)
|
||||
{
|
||||
BAutolock lock(fCallbackLocker);
|
||||
int32 index = fCallbacks.BinarySearchIndexByKey(token, &_CallbackCompare);
|
||||
if (index < 0)
|
||||
return false;
|
||||
|
||||
delete fCallbacks.RemoveItemAt(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
callback_info*
|
||||
HTML5HWInterface::_FindCallback(uint32 token)
|
||||
{
|
||||
BAutolock lock(fCallbackLocker);
|
||||
return fCallbacks.BinarySearchByKey(token, &_CallbackCompare);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
HTML5HWInterface::_CallbackCompare(const uint32* key,
|
||||
const callback_info* info)
|
||||
{
|
||||
if (info->token == *key)
|
||||
return 0;
|
||||
|
||||
if (info->token < *key)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
HTML5HWInterface::_EventThreadEntry(void* data)
|
||||
{
|
||||
return ((HTML5HWInterface*)data)->_EventThread();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::_EventThread()
|
||||
{
|
||||
CanvasMessage message(fReceiveBuffer, fSendBuffer);
|
||||
while (true) {
|
||||
uint16 code;
|
||||
status_t result = message.NextMessage(code);
|
||||
if (result != B_OK) {
|
||||
TRACE_ERROR("failed to read message from receiver: %s\n",
|
||||
strerror(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
TRACE("got message code %" B_PRIu16 " with %" B_PRIu32 " bytes\n", code,
|
||||
message.DataLeft());
|
||||
|
||||
if (code >= RP_MOUSE_MOVED && code <= RP_MODIFIERS_CHANGED) {
|
||||
// an input event, dispatch to the event stream
|
||||
if (fEventStream->EventReceived(message))
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
case RP_UPDATE_DISPLAY_MODE:
|
||||
{
|
||||
// TODO: implement, we only handle it in the context of the
|
||||
// initial mode setup on connect
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
uint32 token;
|
||||
if (message.Read(token) == B_OK) {
|
||||
callback_info* info = _FindCallback(token);
|
||||
if (info != NULL && info->callback(info->cookie, message))
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE_ERROR("unhandled HTML5 event code %u\n", code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::_Connect()
|
||||
{
|
||||
#if 0
|
||||
TRACE("connecting to host \"%s\" port %lu\n", fRemoteHost, fRemotePort);
|
||||
status_t result = fSendEndpoint->Connect(fRemoteHost, (uint16)fRemotePort);
|
||||
if (result != B_OK) {
|
||||
TRACE_ERROR("failed to connect to host \"%s\" port %lu\n", fRemoteHost,
|
||||
fRemotePort);
|
||||
return result;
|
||||
}
|
||||
|
||||
CanvasMessage message(fReceiveBuffer, fSendBuffer);
|
||||
message.Start(RP_INIT_CONNECTION);
|
||||
message.Add(fListenPort);
|
||||
result = message.Flush();
|
||||
if (result != B_OK) {
|
||||
TRACE_ERROR("failed to send init connection message\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16 code;
|
||||
result = message.NextMessage(code);
|
||||
if (result != B_OK) {
|
||||
TRACE_ERROR("failed to read message from receiver: %s\n",
|
||||
strerror(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
TRACE("code %u with %lu bytes of data\n", code, message.DataLeft());
|
||||
if (code != RP_UPDATE_DISPLAY_MODE) {
|
||||
TRACE_ERROR("invalid connection init code %u\n", code);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
int32 width, height;
|
||||
message.Read(width);
|
||||
result = message.Read(height);
|
||||
if (result != B_OK) {
|
||||
TRACE_ERROR("failed to get initial display mode\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
fDisplayMode.virtual_width = width;
|
||||
fDisplayMode.virtual_height = height;
|
||||
#endif
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HTML5HWInterface::_Disconnect()
|
||||
{
|
||||
if (fIsConnected) {
|
||||
CanvasMessage message(NULL, fSendBuffer);
|
||||
message.Start(RP_CLOSE_CONNECTION);
|
||||
message.Flush();
|
||||
fIsConnected = false;
|
||||
}
|
||||
|
||||
if (fReceiveEndpoint != NULL)
|
||||
fReceiveEndpoint->Close();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::SetMode(const display_mode& mode)
|
||||
{
|
||||
// The display mode depends on the screen resolution of the client, we
|
||||
// don't allow to change it.
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HTML5HWInterface::GetMode(display_mode* mode)
|
||||
{
|
||||
if (mode == NULL || !ReadLock())
|
||||
return;
|
||||
|
||||
*mode = fDisplayMode;
|
||||
ReadUnlock();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::GetDeviceInfo(accelerant_device_info* info)
|
||||
{
|
||||
if (!ReadLock())
|
||||
return B_ERROR;
|
||||
|
||||
info->version = fProtocolVersion;
|
||||
info->dac_speed = fConnectionSpeed;
|
||||
info->memory = 33554432; // 32MB
|
||||
snprintf(info->name, sizeof(info->name), "Haiku, Inc. HTML5HWInterface");
|
||||
snprintf(info->chipset, sizeof(info->chipset), "Haiku, Inc. Chipset");
|
||||
snprintf(info->serial_no, sizeof(info->serial_no), fTarget);
|
||||
|
||||
ReadUnlock();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::GetFrameBufferConfig(frame_buffer_config& config)
|
||||
{
|
||||
// We don't actually have a frame buffer.
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::GetModeList(display_mode** _modes, uint32* _count)
|
||||
{
|
||||
AutoReadLocker _(this);
|
||||
|
||||
display_mode* modes = new(std::nothrow) display_mode[1];
|
||||
if (modes == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
modes[0] = fDisplayMode;
|
||||
*_modes = modes;
|
||||
*_count = 1;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::GetPixelClockLimits(display_mode* mode, uint32* low,
|
||||
uint32* high)
|
||||
{
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::GetTimingConstraints(display_timing_constraints* constraints)
|
||||
{
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::ProposeMode(display_mode* candidate, const display_mode* low,
|
||||
const display_mode* high)
|
||||
{
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::SetDPMSMode(uint32 state)
|
||||
{
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
HTML5HWInterface::DPMSMode()
|
||||
{
|
||||
return (IsConnected() ? B_DPMS_ON : B_DPMS_SUSPEND);
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
HTML5HWInterface::DPMSCapabilities()
|
||||
{
|
||||
return B_DPMS_ON | B_DPMS_SUSPEND;
|
||||
}
|
||||
|
||||
|
||||
sem_id
|
||||
HTML5HWInterface::RetraceSemaphore()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::SetBrightness(float)
|
||||
{
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::GetBrightness(float*)
|
||||
{
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::WaitForRetrace(bigtime_t timeout)
|
||||
{
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HTML5HWInterface::SetCursor(ServerCursor* cursor)
|
||||
{
|
||||
HWInterface::SetCursor(cursor);
|
||||
if (!IsConnected())
|
||||
return;
|
||||
CanvasMessage message(NULL, fSendBuffer);
|
||||
message.Start(RP_SET_CURSOR);
|
||||
message.AddCursor(Cursor().Get());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HTML5HWInterface::SetCursorVisible(bool visible)
|
||||
{
|
||||
HWInterface::SetCursorVisible(visible);
|
||||
if (!IsConnected())
|
||||
return;
|
||||
CanvasMessage message(NULL, fSendBuffer);
|
||||
message.Start(RP_SET_CURSOR_VISIBLE);
|
||||
message.Add(visible);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HTML5HWInterface::MoveCursorTo(float x, float y)
|
||||
{
|
||||
HWInterface::MoveCursorTo(x, y);
|
||||
if (!IsConnected())
|
||||
return;
|
||||
CanvasMessage message(NULL, fSendBuffer);
|
||||
message.Start(RP_MOVE_CURSOR_TO);
|
||||
message.Add(x);
|
||||
message.Add(y);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HTML5HWInterface::SetDragBitmap(const ServerBitmap* bitmap,
|
||||
const BPoint& offsetFromCursor)
|
||||
{
|
||||
HWInterface::SetDragBitmap(bitmap, offsetFromCursor);
|
||||
if (!IsConnected())
|
||||
return;
|
||||
CanvasMessage message(NULL, fSendBuffer);
|
||||
message.Start(RP_SET_CURSOR);
|
||||
message.AddCursor(CursorAndDragBitmap().Get());
|
||||
}
|
||||
|
||||
|
||||
RenderingBuffer*
|
||||
HTML5HWInterface::FrontBuffer() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
RenderingBuffer*
|
||||
HTML5HWInterface::BackBuffer() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
HTML5HWInterface::IsDoubleBuffered() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::InvalidateRegion(BRegion& region)
|
||||
{
|
||||
CanvasMessage message(NULL, fSendBuffer);
|
||||
if (!IsConnected())
|
||||
return B_OK;
|
||||
message.Start(RP_INVALIDATE_REGION);
|
||||
message.AddRegion(region);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::Invalidate(const BRect& frame)
|
||||
{
|
||||
CanvasMessage message(NULL, fSendBuffer);
|
||||
if (!IsConnected())
|
||||
return B_OK;
|
||||
message.Start(RP_INVALIDATE_RECT);
|
||||
message.Add(frame);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HTML5HWInterface::CopyBackToFront(const BRect& frame)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
* François Revol <revol@free.fr>
|
||||
*/
|
||||
#ifndef HTML5_HW_INTERFACE_H
|
||||
#define HTML5_HW_INTERFACE_H
|
||||
|
||||
#include "HWInterface.h"
|
||||
|
||||
#include <Locker.h>
|
||||
#include <ObjectList.h>
|
||||
|
||||
class BNetEndpoint;
|
||||
class StreamingRingBuffer;
|
||||
class NetSender;
|
||||
class NetReceiver;
|
||||
class CanvasEventStream;
|
||||
class CanvasMessage;
|
||||
class WebServer;
|
||||
|
||||
struct callback_info;
|
||||
|
||||
|
||||
//XXX: CanvasHWInterface ??
|
||||
class HTML5HWInterface : public HWInterface {
|
||||
public:
|
||||
HTML5HWInterface(const char* target);
|
||||
virtual ~HTML5HWInterface();
|
||||
|
||||
virtual status_t Initialize();
|
||||
virtual status_t Shutdown();
|
||||
|
||||
virtual DrawingEngine* CreateDrawingEngine();
|
||||
virtual EventStream* CreateEventStream();
|
||||
|
||||
virtual status_t SetMode(const display_mode& mode);
|
||||
virtual void GetMode(display_mode* mode);
|
||||
|
||||
virtual status_t GetDeviceInfo(accelerant_device_info* info);
|
||||
virtual status_t GetFrameBufferConfig(
|
||||
frame_buffer_config& config);
|
||||
|
||||
virtual status_t GetModeList(display_mode** _modeList,
|
||||
uint32* _count);
|
||||
virtual status_t GetPixelClockLimits(display_mode* mode,
|
||||
uint32* _low, uint32* _high);
|
||||
virtual status_t GetTimingConstraints(
|
||||
display_timing_constraints* constraints);
|
||||
virtual status_t ProposeMode(display_mode* candidate,
|
||||
const display_mode* low,
|
||||
const display_mode* high);
|
||||
|
||||
virtual sem_id RetraceSemaphore();
|
||||
virtual status_t WaitForRetrace(
|
||||
bigtime_t timeout = B_INFINITE_TIMEOUT);
|
||||
|
||||
virtual status_t SetDPMSMode(uint32 state);
|
||||
virtual uint32 DPMSMode();
|
||||
virtual uint32 DPMSCapabilities();
|
||||
|
||||
virtual status_t SetBrightness(float);
|
||||
virtual status_t GetBrightness(float*);
|
||||
|
||||
// cursor handling
|
||||
virtual void SetCursor(ServerCursor* cursor);
|
||||
virtual void SetCursorVisible(bool visible);
|
||||
virtual void MoveCursorTo(float x, float y);
|
||||
virtual void SetDragBitmap(const ServerBitmap* bitmap,
|
||||
const BPoint& offsetFormCursor);
|
||||
|
||||
// frame buffer access
|
||||
virtual RenderingBuffer* FrontBuffer() const;
|
||||
virtual RenderingBuffer* BackBuffer() const;
|
||||
virtual bool IsDoubleBuffered() const;
|
||||
|
||||
virtual status_t InvalidateRegion(BRegion& region);
|
||||
virtual status_t Invalidate(const BRect& frame);
|
||||
virtual status_t CopyBackToFront(const BRect& frame);
|
||||
|
||||
// drawing engine interface
|
||||
StreamingRingBuffer* ReceiveBuffer() { return fReceiveBuffer; }
|
||||
StreamingRingBuffer* SendBuffer() { return fSendBuffer; }
|
||||
|
||||
typedef bool (*CallbackFunction)(void* cookie, CanvasMessage& message);
|
||||
|
||||
status_t AddCallback(uint32 token,
|
||||
CallbackFunction callback,
|
||||
void* cookie);
|
||||
bool RemoveCallback(uint32 token);
|
||||
|
||||
bool IsConnected() { return fIsConnected; }
|
||||
|
||||
private:
|
||||
callback_info* _FindCallback(uint32 token);
|
||||
static int _CallbackCompare(const uint32* key,
|
||||
const callback_info* info);
|
||||
|
||||
static int32 _EventThreadEntry(void* data);
|
||||
status_t _EventThread();
|
||||
|
||||
status_t _Connect();
|
||||
void _Disconnect();
|
||||
|
||||
const char* fTarget;
|
||||
char* fRemoteHost;
|
||||
uint32 fRemotePort;
|
||||
|
||||
status_t fInitStatus;
|
||||
bool fIsConnected;
|
||||
uint32 fProtocolVersion;
|
||||
uint32 fConnectionSpeed;
|
||||
display_mode fDisplayMode;
|
||||
uint16 fListenPort;
|
||||
|
||||
// BNetEndpoint* fSendEndpoint;
|
||||
BNetEndpoint* fReceiveEndpoint;
|
||||
|
||||
StreamingRingBuffer* fSendBuffer;
|
||||
StreamingRingBuffer* fReceiveBuffer;
|
||||
|
||||
WebServer* fServer;
|
||||
// NetSender* fSender;
|
||||
// NetReceiver* fReceiver;
|
||||
|
||||
thread_id fEventThread;
|
||||
CanvasEventStream* fEventStream;
|
||||
|
||||
BLocker fCallbackLocker;
|
||||
BObjectList<callback_info> fCallbacks;
|
||||
};
|
||||
|
||||
#endif // HTML5_HW_INTERFACE_H
|
||||
@@ -1,36 +0,0 @@
|
||||
SubDir HAIKU_TOP src servers app drawing interface html5 ;
|
||||
|
||||
UseLibraryHeaders agg ;
|
||||
UsePrivateHeaders app graphics interface kernel shared ;
|
||||
UsePrivateHeaders [ FDirName graphics common ] ;
|
||||
UsePrivateSystemHeaders ;
|
||||
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src servers app ] ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src servers app font ] ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing ] ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter drawing_modes ] ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter font_support ] ;
|
||||
UseBuildFeatureHeaders freetype ;
|
||||
|
||||
Includes [ FGristFiles HTML5HWInterface.cpp HTML5DrawingEngine.cpp
|
||||
CanvasMessage.cpp ]
|
||||
: [ BuildFeatureAttribute freetype : headers ] ;
|
||||
|
||||
StaticLibrary libashtml5.a :
|
||||
base64.cpp
|
||||
|
||||
#NetReceiver.cpp
|
||||
#NetSender.cpp
|
||||
|
||||
HTML5DrawingEngine.cpp
|
||||
CanvasEventStream.cpp
|
||||
HTML5HWInterface.cpp
|
||||
CanvasMessage.cpp
|
||||
|
||||
StreamingRingBuffer.cpp
|
||||
|
||||
WebHandler.cpp
|
||||
WebServer.cpp
|
||||
WebWorker.cpp
|
||||
;
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
*/
|
||||
|
||||
#include "NetSender.h"
|
||||
|
||||
#include "StreamingRingBuffer.h"
|
||||
|
||||
#include <NetEndpoint.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TRACE(x...) /*debug_printf("NetSender: "x)*/
|
||||
#define TRACE_ERROR(x...) debug_printf("NetSender: "x)
|
||||
|
||||
|
||||
NetSender::NetSender(BNetEndpoint *endpoint, StreamingRingBuffer *source)
|
||||
:
|
||||
fEndpoint(endpoint),
|
||||
fSource(source),
|
||||
fSenderThread(-1),
|
||||
fStopThread(false)
|
||||
{
|
||||
fSenderThread = spawn_thread(_NetworkSenderEntry, "network sender",
|
||||
B_NORMAL_PRIORITY, this);
|
||||
resume_thread(fSenderThread);
|
||||
}
|
||||
|
||||
|
||||
NetSender::~NetSender()
|
||||
{
|
||||
fStopThread = true;
|
||||
int32 result;
|
||||
wait_for_thread(fSenderThread, &result);
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
NetSender::_NetworkSenderEntry(void *data)
|
||||
{
|
||||
return ((NetSender *)data)->_NetworkSender();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NetSender::_NetworkSender()
|
||||
{
|
||||
while (!fStopThread) {
|
||||
uint8 buffer[4096];
|
||||
int32 readSize = fSource->Read(buffer, sizeof(buffer), true);
|
||||
if (readSize < 0) {
|
||||
TRACE_ERROR("read failed, stopping sender thread: %s\n",
|
||||
strerror(readSize));
|
||||
return readSize;
|
||||
}
|
||||
|
||||
while (readSize > 0) {
|
||||
int32 sendSize = fEndpoint->Send(buffer, readSize);
|
||||
if (sendSize < 0) {
|
||||
TRACE_ERROR("sending data failed: %s\n", strerror(sendSize));
|
||||
return sendSize;
|
||||
}
|
||||
|
||||
readSize -= sendSize;
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
*/
|
||||
#ifndef NET_SENDER_H
|
||||
#define NET_SENDER_H
|
||||
|
||||
#include <OS.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
class BNetEndpoint;
|
||||
class StreamingRingBuffer;
|
||||
|
||||
class NetSender {
|
||||
public:
|
||||
NetSender(BNetEndpoint *endpoint,
|
||||
StreamingRingBuffer *source);
|
||||
~NetSender();
|
||||
|
||||
private:
|
||||
static int32 _NetworkSenderEntry(void *data);
|
||||
status_t _NetworkSender();
|
||||
|
||||
BNetEndpoint * fEndpoint;
|
||||
StreamingRingBuffer * fSource;
|
||||
|
||||
thread_id fSenderThread;
|
||||
bool fStopThread;
|
||||
};
|
||||
|
||||
#endif // NET_SENDER_H
|
||||
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
*/
|
||||
|
||||
#include "StreamingRingBuffer.h"
|
||||
|
||||
#include <Autolock.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TRACE(x...) /*debug_printf("StreamingRingBuffer: "x)*/
|
||||
#define TRACE_ERROR(x...) debug_printf("StreamingRingBuffer: "x)
|
||||
|
||||
|
||||
StreamingRingBuffer::StreamingRingBuffer(size_t bufferSize)
|
||||
:
|
||||
fReaderWaiting(false),
|
||||
fWriterWaiting(false),
|
||||
fReaderNotifier(-1),
|
||||
fWriterNotifier(-1),
|
||||
fReaderLocker("StreamingRingBuffer reader"),
|
||||
fWriterLocker("StreamingRingBuffer writer"),
|
||||
fDataLocker("StreamingRingBuffer data"),
|
||||
fBuffer(NULL),
|
||||
fBufferSize(bufferSize),
|
||||
fReadable(0),
|
||||
fReadPosition(0),
|
||||
fWritePosition(0)
|
||||
{
|
||||
fReaderNotifier = create_sem(0, "StreamingRingBuffer read notify");
|
||||
fWriterNotifier = create_sem(0, "StreamingRingBuffer write notify");
|
||||
|
||||
fBuffer = (uint8 *)malloc(fBufferSize);
|
||||
if (fBuffer == NULL)
|
||||
fBufferSize = 0;
|
||||
}
|
||||
|
||||
|
||||
StreamingRingBuffer::~StreamingRingBuffer()
|
||||
{
|
||||
delete_sem(fReaderNotifier);
|
||||
delete_sem(fWriterNotifier);
|
||||
free(fBuffer);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
StreamingRingBuffer::InitCheck()
|
||||
{
|
||||
if (fReaderNotifier < 0)
|
||||
return fReaderNotifier;
|
||||
if (fWriterNotifier < 0)
|
||||
return fWriterNotifier;
|
||||
if (fBuffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
StreamingRingBuffer::Read(void *buffer, size_t length, bool onlyBlockOnNoData)
|
||||
{
|
||||
BAutolock readerLock(fReaderLocker);
|
||||
if (!readerLock.IsLocked())
|
||||
return B_ERROR;
|
||||
|
||||
BAutolock dataLock(fDataLocker);
|
||||
if (!dataLock.IsLocked())
|
||||
return B_ERROR;
|
||||
|
||||
int32 readSize = 0;
|
||||
while (length > 0) {
|
||||
size_t copyLength = min_c(length, fBufferSize - fReadPosition);
|
||||
copyLength = min_c(copyLength, fReadable);
|
||||
|
||||
if (copyLength == 0) {
|
||||
if (onlyBlockOnNoData && readSize > 0)
|
||||
return readSize;
|
||||
|
||||
fReaderWaiting = true;
|
||||
dataLock.Unlock();
|
||||
|
||||
status_t result;
|
||||
do {
|
||||
TRACE("waiting in reader\n");
|
||||
result = acquire_sem(fReaderNotifier);
|
||||
TRACE("done waiting in reader with status: 0x%08lx\n", result);
|
||||
} while (result == B_INTERRUPTED);
|
||||
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
if (!dataLock.Lock())
|
||||
return B_ERROR;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// support discarding input
|
||||
if (buffer != NULL) {
|
||||
memcpy(buffer, fBuffer + fReadPosition, copyLength);
|
||||
buffer = (uint8 *)buffer + copyLength;
|
||||
}
|
||||
|
||||
fReadPosition = (fReadPosition + copyLength) % fBufferSize;
|
||||
fReadable -= copyLength;
|
||||
readSize += copyLength;
|
||||
length -= copyLength;
|
||||
|
||||
if (fWriterWaiting) {
|
||||
release_sem_etc(fWriterNotifier, 1, B_DO_NOT_RESCHEDULE);
|
||||
fWriterWaiting = false;
|
||||
}
|
||||
}
|
||||
|
||||
return readSize;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
StreamingRingBuffer::Write(const void *buffer, size_t length)
|
||||
{
|
||||
BAutolock writerLock(fWriterLocker);
|
||||
if (!writerLock.IsLocked())
|
||||
return B_ERROR;
|
||||
|
||||
BAutolock dataLock(fDataLocker);
|
||||
if (!dataLock.IsLocked())
|
||||
return B_ERROR;
|
||||
|
||||
while (length > 0) {
|
||||
size_t copyLength = min_c(length, fBufferSize - fWritePosition);
|
||||
copyLength = min_c(copyLength, fBufferSize - fReadable);
|
||||
|
||||
if (copyLength == 0) {
|
||||
fWriterWaiting = true;
|
||||
dataLock.Unlock();
|
||||
|
||||
status_t result;
|
||||
do {
|
||||
TRACE("waiting in writer\n");
|
||||
result = acquire_sem(fWriterNotifier);
|
||||
TRACE("done waiting in writer with status: 0x%08lx\n", result);
|
||||
} while (result == B_INTERRUPTED);
|
||||
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
if (!dataLock.Lock())
|
||||
return B_ERROR;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(fBuffer + fWritePosition, buffer, copyLength);
|
||||
fWritePosition = (fWritePosition + copyLength) % fBufferSize;
|
||||
fReadable += copyLength;
|
||||
|
||||
buffer = (uint8 *)buffer + copyLength;
|
||||
length -= copyLength;
|
||||
|
||||
if (fReaderWaiting) {
|
||||
release_sem_etc(fReaderNotifier, 1, B_DO_NOT_RESCHEDULE);
|
||||
fReaderWaiting = false;
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
*/
|
||||
#ifndef STREAMING_RING_BUFFER_H
|
||||
#define STREAMING_RING_BUFFER_H
|
||||
|
||||
#include <OS.h>
|
||||
#include <SupportDefs.h>
|
||||
#include <Locker.h>
|
||||
|
||||
class StreamingRingBuffer {
|
||||
public:
|
||||
StreamingRingBuffer(size_t bufferSize);
|
||||
~StreamingRingBuffer();
|
||||
|
||||
status_t InitCheck();
|
||||
|
||||
// blocking read and write
|
||||
int32 Read(void *buffer, size_t length,
|
||||
bool onlyBlockOnNoData = false);
|
||||
status_t Write(const void *buffer, size_t length);
|
||||
|
||||
private:
|
||||
bool _Lock();
|
||||
void _Unlock();
|
||||
|
||||
bool fReaderWaiting;
|
||||
bool fWriterWaiting;
|
||||
sem_id fReaderNotifier;
|
||||
sem_id fWriterNotifier;
|
||||
|
||||
BLocker fReaderLocker;
|
||||
BLocker fWriterLocker;
|
||||
BLocker fDataLocker;
|
||||
|
||||
uint8 * fBuffer;
|
||||
size_t fBufferSize;
|
||||
size_t fReadable;
|
||||
int32 fReadPosition;
|
||||
int32 fWritePosition;
|
||||
};
|
||||
|
||||
#endif // STREAMING_RING_BUFFER_H
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
* François Revol <revol@free.fr>
|
||||
*/
|
||||
|
||||
#include "WebHandler.h"
|
||||
|
||||
#include "StreamingRingBuffer.h"
|
||||
|
||||
#include <NetEndpoint.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TRACE(x...) debug_printf("WebHandler: " x)
|
||||
#define TRACE_ERROR(x...) debug_printf("WebHandler: "x)
|
||||
|
||||
|
||||
WebHandler::WebHandler(const char *path, BDataIO *data)
|
||||
:
|
||||
fPath(path),
|
||||
fMultipart(false),
|
||||
fType(""),
|
||||
fData(data),
|
||||
fTarget(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
WebHandler::WebHandler(const char *path, StreamingRingBuffer *target)
|
||||
:
|
||||
fPath(path),
|
||||
fMultipart(false),
|
||||
fType(""),
|
||||
fData(NULL),
|
||||
fTarget(target)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
WebHandler::~WebHandler()
|
||||
{
|
||||
delete fData;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
WebHandler::HandleRequest(WebWorker *worker, BString &path)
|
||||
{
|
||||
// off_t offset = 0LL;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WebHandler::_CallbackCompare(const BString* key,
|
||||
const WebHandler* info)
|
||||
{
|
||||
int diff = strcmp(*key, info->fPath.String());
|
||||
TRACE("'%s' <> '%s' %d\n", key->String(), info->fPath.String(), diff);
|
||||
if (diff == 0)
|
||||
return 0;
|
||||
if (diff < 0)
|
||||
return -1;
|
||||
return 1;
|
||||
// return strcmp(*key, info->fPath.String());
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WebHandler::_CallbackCompare(const WebHandler* a, const WebHandler* b)
|
||||
{
|
||||
int diff = strcmp(a->fPath.String(), b->fPath.String());
|
||||
return diff;
|
||||
// return strcmp(*key, info->fPath.String());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
* François Revol <revol@free.fr>
|
||||
*/
|
||||
#ifndef WEB_HANDLER_H
|
||||
#define WEB_HANDLER_H
|
||||
|
||||
#include <OS.h>
|
||||
#include <String.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
class BNetEndpoint;
|
||||
class StreamingRingBuffer;
|
||||
class BDataIO;
|
||||
class WebWorker;
|
||||
|
||||
class WebHandler {
|
||||
public:
|
||||
WebHandler(const char *path,
|
||||
BDataIO *data=NULL);
|
||||
WebHandler(const char *path,
|
||||
StreamingRingBuffer *target);
|
||||
virtual ~WebHandler();
|
||||
|
||||
void SetMultipart(bool multipart=true) {
|
||||
fMultipart = true; }
|
||||
bool IsMultipart() { return fMultipart; }
|
||||
void SetType(const char *type) { fType = type; }
|
||||
|
||||
|
||||
BString & Name() { return fPath; }
|
||||
// BNetEndpoint * Endpoint() { return fEndpoint; }
|
||||
virtual status_t HandleRequest(WebWorker *worker,
|
||||
BString &path);
|
||||
|
||||
static int _CallbackCompare(const BString* key,
|
||||
const WebHandler* info);
|
||||
static int _CallbackCompare(const WebHandler* a,
|
||||
const WebHandler* b);
|
||||
|
||||
private:
|
||||
friend class WebWorker;
|
||||
BString fPath;
|
||||
|
||||
bool fMultipart;
|
||||
BString fType; // MIME
|
||||
BDataIO * fData;
|
||||
StreamingRingBuffer * fTarget;
|
||||
};
|
||||
|
||||
#endif // WEB_HANDLER_H
|
||||
@@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
* François Revol <revol@free.fr>
|
||||
*/
|
||||
|
||||
#include "WebHandler.h"
|
||||
#include "WebServer.h"
|
||||
#include "WebWorker.h"
|
||||
|
||||
#include "StreamingRingBuffer.h"
|
||||
|
||||
#include <NetEndpoint.h>
|
||||
#include <Autolock.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TRACE(x...) debug_printf("WebServer: " x)
|
||||
#define TRACE_ERROR(x...) debug_printf("WebServer: " x)
|
||||
|
||||
|
||||
WebServer::WebServer(BNetEndpoint *listener)
|
||||
:
|
||||
fListener(listener),
|
||||
fReceiverThread(-1),
|
||||
fStopThread(false),
|
||||
fLocker("WebServer locker")
|
||||
{
|
||||
fReceiverThread = spawn_thread(_NetworkReceiverEntry, "html5 server",
|
||||
B_NORMAL_PRIORITY, this);
|
||||
resume_thread(fReceiverThread);
|
||||
}
|
||||
|
||||
|
||||
WebServer::~WebServer()
|
||||
{
|
||||
fStopThread = true;
|
||||
|
||||
if (fListener != NULL)
|
||||
fListener->Close();
|
||||
|
||||
//int32 result;
|
||||
//wait_for_thread(fReceiverThread, &result);
|
||||
// TODO: find out why closing the endpoint doesn't notify the waiter
|
||||
|
||||
kill_thread(fReceiverThread);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WebServer::AddHandler(WebHandler *handler)
|
||||
{
|
||||
BAutolock lock(fLocker);
|
||||
fHandlers.AddItem(handler);
|
||||
}
|
||||
|
||||
int32
|
||||
WebServer::_NetworkReceiverEntry(void *data)
|
||||
{
|
||||
return ((WebServer *)data)->_NetworkReceiver();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
WebServer::_NetworkReceiver()
|
||||
{
|
||||
status_t result = fListener->Listen();
|
||||
if (result != B_OK) {
|
||||
TRACE_ERROR("failed to listen on port: %s\n", strerror(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
fHandlers.SortItems(&WebHandler::_CallbackCompare);
|
||||
|
||||
while (!fStopThread) {
|
||||
BNetEndpoint *endpoint = fListener->Accept(1000);
|
||||
if (endpoint == NULL)
|
||||
continue;
|
||||
|
||||
TRACE("new endpoint connection: %p\n", endpoint);
|
||||
while (!fStopThread) {
|
||||
int32 errorCount = 0;
|
||||
uint8 buffer[4096];
|
||||
int32 readSize = endpoint->Receive(buffer, sizeof(buffer) - 1);
|
||||
if (readSize < 0) {
|
||||
TRACE_ERROR("read failed, closing connection: %s\n",
|
||||
strerror(readSize));
|
||||
delete endpoint;
|
||||
break;
|
||||
}
|
||||
|
||||
if (readSize == 0) {
|
||||
TRACE("read 0 bytes, retrying\n");
|
||||
snooze(100 * 1000);
|
||||
errorCount++;
|
||||
if (errorCount == 5) {
|
||||
TRACE_ERROR("failed to read, assuming disconnect\n");
|
||||
delete endpoint;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
buffer[readSize] = '\0';
|
||||
|
||||
const char err404[] = "HTTP/1.1 404 Not found\r\n\r\n";
|
||||
|
||||
// XXX: HACK HACK HACK
|
||||
const char *p = (const char *)buffer;
|
||||
if (strncmp(p, "GET ", 4) == 0) {
|
||||
p += 4;
|
||||
const char *s = strchr(p, ' ');
|
||||
if (s && strncmp(s, " HTTP/", 6) == 0) {
|
||||
if (*p == '/')
|
||||
p++;
|
||||
BString path(p, s - p);
|
||||
if (p == s)
|
||||
path = "desktop.html";
|
||||
TRACE("searching handler for '%s'\n", path.String());
|
||||
WebHandler *handler = fHandlers.BinarySearchByKey(
|
||||
path, &WebHandler::_CallbackCompare);
|
||||
if (handler) {
|
||||
TRACE("found handler '%s'\n", handler->Name().String());
|
||||
WebWorker *worker =
|
||||
new (std::nothrow) WebWorker(endpoint, handler);
|
||||
if (worker) {
|
||||
fWorkers.AddItem(worker);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// some error
|
||||
endpoint->Send(err404, sizeof(err404) - 1);
|
||||
delete endpoint;
|
||||
break;
|
||||
|
||||
#if 0
|
||||
status_t result = fTarget->Write(buffer, readSize);
|
||||
if (result != B_OK) {
|
||||
TRACE_ERROR("writing to ring buffer failed: %s\n",
|
||||
strerror(result));
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
* François Revol <revol@free.fr>
|
||||
*/
|
||||
#ifndef WEB_SERVER_H
|
||||
#define WEB_SERVER_H
|
||||
|
||||
//#include "WebWorker.h"
|
||||
|
||||
#include <Locker.h>
|
||||
#include <ObjectList.h>
|
||||
#include <OS.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
class BNetEndpoint;
|
||||
class WebHandler;
|
||||
class WebWorker;
|
||||
|
||||
class WebServer {
|
||||
public:
|
||||
WebServer(BNetEndpoint *listener);
|
||||
~WebServer();
|
||||
|
||||
// BNetEndpoint * Endpoint() { return fEndpoint; }
|
||||
|
||||
void AddHandler(WebHandler *handler);
|
||||
|
||||
private:
|
||||
static int32 _NetworkReceiverEntry(void *data);
|
||||
status_t _NetworkReceiver();
|
||||
|
||||
BNetEndpoint * fListener;
|
||||
|
||||
thread_id fReceiverThread;
|
||||
bool fStopThread;
|
||||
|
||||
BLocker fLocker;
|
||||
BObjectList<WebHandler> fHandlers;
|
||||
BObjectList<WebWorker> fWorkers;
|
||||
// BNetEndpoint * fEndpoint;
|
||||
};
|
||||
|
||||
#endif // WEB_SERVER_H
|
||||
@@ -1,152 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
* François Revol <revol@free.fr>
|
||||
*/
|
||||
|
||||
#include "WebHandler.h"
|
||||
#include "WebWorker.h"
|
||||
|
||||
#include "StreamingRingBuffer.h"
|
||||
|
||||
#include <NetEndpoint.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TRACE(x...) debug_printf("WebWorker: " x)
|
||||
#define TRACE_ERROR(x...) debug_printf("WebWorker: " x)
|
||||
|
||||
|
||||
WebWorker::WebWorker(BNetEndpoint *endpoint, WebHandler *handler)
|
||||
:
|
||||
fHandler(handler),
|
||||
fWorkThread(-1),
|
||||
fStopThread(false),
|
||||
fEndpoint(endpoint)
|
||||
{
|
||||
fWorkThread = spawn_thread(_WorkEntry, "html5 http worker",
|
||||
B_NORMAL_PRIORITY, this);
|
||||
resume_thread(fWorkThread);
|
||||
}
|
||||
|
||||
|
||||
WebWorker::~WebWorker()
|
||||
{
|
||||
fStopThread = true;
|
||||
|
||||
if (fEndpoint != NULL)
|
||||
fEndpoint->Close();
|
||||
|
||||
//int32 result;
|
||||
//wait_for_thread(fWorkThread, &result);
|
||||
// TODO: find out why closing the endpoint doesn't notify the waiter
|
||||
|
||||
kill_thread(fWorkThread);
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
WebWorker::_WorkEntry(void *data)
|
||||
{
|
||||
return ((WebWorker *)data)->_Work();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
WebWorker::_Work()
|
||||
{
|
||||
off_t pos = 0LL, contentSize = -1LL;
|
||||
int32 errorCount = 0;
|
||||
status_t result;
|
||||
TRACE("new endpoint connection: %p\n", fEndpoint);
|
||||
|
||||
BDataIO *io = fHandler->fData;
|
||||
BPositionIO *pio = dynamic_cast<BPositionIO *>(io);
|
||||
StreamingRingBuffer *rb = fHandler->fTarget;
|
||||
|
||||
if (pio)
|
||||
pio->GetSize(&contentSize);
|
||||
|
||||
BString headers("HTTP/1.1 200 OK\r\n");
|
||||
headers << "Server: app_server(Haiku)\r\n";
|
||||
headers << "Accept-Ranges: bytes\r\n";
|
||||
headers << "Connection: ";
|
||||
if (fHandler->IsMultipart())
|
||||
headers << "close";
|
||||
else
|
||||
headers << "keep-alive";
|
||||
headers << "\r\n";
|
||||
if (fHandler->fType.Length())
|
||||
headers << "Content-Type: " << fHandler->fType << "\r\n";
|
||||
if (contentSize > 0)
|
||||
headers << "Content-Length: " << contentSize << "\r\n";
|
||||
headers << "\r\n";
|
||||
|
||||
result = fEndpoint->Send(headers.String(), headers.Length());
|
||||
if (result < headers.Length()) {
|
||||
TRACE_ERROR("sending headers failed: %s\n",
|
||||
strerror(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
// send initial multipart boundary
|
||||
// XXX: this is messy!
|
||||
if (fHandler->IsMultipart()) {
|
||||
static const char boundary[] = "--x\r\n\r\n";
|
||||
result = fEndpoint->Send(boundary, sizeof(boundary) - 1);
|
||||
if (result < (signed)sizeof(boundary) - 1) {
|
||||
TRACE_ERROR("writing to peer failed: %s\n",
|
||||
strerror(result));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
while (!fStopThread) {
|
||||
uint8 buffer[4096];
|
||||
int32 readSize = 0;
|
||||
if (pio)
|
||||
readSize = pio->ReadAt(pos, buffer, sizeof(buffer));
|
||||
else if (io)
|
||||
readSize = io->Read(buffer, sizeof(buffer));
|
||||
else if (rb)
|
||||
readSize = rb->Read(buffer, sizeof(buffer));
|
||||
TRACE("readSize %" B_PRId32 "\n", readSize);
|
||||
|
||||
if (readSize < 0) {
|
||||
TRACE_ERROR("read failed, closing connection: %s\n",
|
||||
strerror(readSize));
|
||||
return readSize;
|
||||
}
|
||||
|
||||
if (readSize == 0) {
|
||||
//XXX:should just break;
|
||||
// TRACE("read 0 bytes, retrying\n");
|
||||
snooze(100 * 1000);
|
||||
errorCount++;
|
||||
if (errorCount == 5) {
|
||||
TRACE_ERROR("failed to read, assuming disconnect\n");
|
||||
fEndpoint->Close();
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
pos += readSize;
|
||||
|
||||
errorCount = 0;
|
||||
result = fEndpoint->Send(buffer, readSize);
|
||||
// TRACE("writeSize %ld\n", result);
|
||||
if (result < readSize) {
|
||||
TRACE_ERROR("writing to peer failed: %s\n",
|
||||
strerror(result));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
* François Revol <revol@free.fr>
|
||||
*/
|
||||
#ifndef WEB_WORKER_H
|
||||
#define WEB_WORKER_H
|
||||
|
||||
#include <OS.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
class BNetEndpoint;
|
||||
class StreamingRingBuffer;
|
||||
class WebHandler;
|
||||
|
||||
class WebWorker {
|
||||
public:
|
||||
WebWorker(BNetEndpoint *endpoint,
|
||||
WebHandler *handler);
|
||||
~WebWorker();
|
||||
|
||||
BNetEndpoint * Endpoint() { return fEndpoint; }
|
||||
|
||||
private:
|
||||
static int32 _WorkEntry(void *data);
|
||||
status_t _Work();
|
||||
|
||||
WebHandler * fHandler;
|
||||
|
||||
thread_id fWorkThread;
|
||||
bool fStopThread;
|
||||
|
||||
BNetEndpoint * fEndpoint;
|
||||
};
|
||||
|
||||
#endif // WEB_WORKER_H
|
||||
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011, Haiku, Inc. All rights reserved.
|
||||
* Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <mail_encoding.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
static const char kBase64Alphabet[64] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
|
||||
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
||||
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'+',
|
||||
'/'
|
||||
};
|
||||
|
||||
static const char kHexAlphabet[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8','9','A','B','C','D','E','F'};
|
||||
|
||||
|
||||
ssize_t
|
||||
encode_base64(char *out, const char *in, off_t length, bool packed)
|
||||
{
|
||||
uint32 concat;
|
||||
int i = 0;
|
||||
int k = 0;
|
||||
|
||||
while (i < length) {
|
||||
concat = ((in[i] & 0xff) << 16);
|
||||
|
||||
if ((i+1) < length)
|
||||
concat |= ((in[i+1] & 0xff) << 8);
|
||||
if ((i+2) < length)
|
||||
concat |= (in[i+2] & 0xff);
|
||||
|
||||
i += 3;
|
||||
|
||||
out[k++] = kBase64Alphabet[(concat >> 18) & 63];
|
||||
out[k++] = kBase64Alphabet[(concat >> 12) & 63];
|
||||
if ((i+1) < length)
|
||||
out[k++] = kBase64Alphabet[(concat >> 6) & 63];
|
||||
else if (!packed)
|
||||
out[k++] = '=';
|
||||
if ((i+2) < length)
|
||||
out[k++] = kBase64Alphabet[concat & 63];
|
||||
else if (!packed)
|
||||
out[k++] = '=';
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
decode_base64(char *out, const char *in, off_t length)
|
||||
{
|
||||
uint32 concat, value;
|
||||
int lastOutLine = 0;
|
||||
int i, j;
|
||||
int outIndex = 0;
|
||||
|
||||
for (i = 0; i < length; i += 4) {
|
||||
concat = 0;
|
||||
|
||||
for (j = 0; j < 4 && (i + j) < length; j++) {
|
||||
value = in[i + j];
|
||||
|
||||
if (value == '\n' || value == '\r') {
|
||||
// jump over line breaks
|
||||
lastOutLine = outIndex;
|
||||
i++;
|
||||
j--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((value >= 'A') && (value <= 'Z'))
|
||||
value -= 'A';
|
||||
else if ((value >= 'a') && (value <= 'z'))
|
||||
value = value - 'a' + 26;
|
||||
else if ((value >= '0') && (value <= '9'))
|
||||
value = value - '0' + 52;
|
||||
else if (value == '+')
|
||||
value = 62;
|
||||
else if (value == '/')
|
||||
value = 63;
|
||||
else if (value == '=')
|
||||
break;
|
||||
else {
|
||||
// there is an invalid character in this line - we will
|
||||
// ignore the whole line and go to the next
|
||||
outIndex = lastOutLine;
|
||||
while (i < length && in[i] != '\n' && in[i] != '\r')
|
||||
i++;
|
||||
concat = 0;
|
||||
}
|
||||
|
||||
value = value << ((3-j)*6);
|
||||
|
||||
concat |= value;
|
||||
}
|
||||
|
||||
if (j > 1)
|
||||
out[outIndex++] = (concat & 0x00ff0000) >> 16;
|
||||
if (j > 2)
|
||||
out[outIndex++] = (concat & 0x0000ff00) >> 8;
|
||||
if (j > 3)
|
||||
out[outIndex++] = (concat & 0x000000ff);
|
||||
}
|
||||
|
||||
return outIndex;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011, Haiku, Inc. All rights reserved.
|
||||
* Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
|
||||
*/
|
||||
#ifndef BASE64_H
|
||||
#define BASE64_H
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
extern ssize_t encode_base64(char *out, const char *in, off_t length,
|
||||
bool packed=false);
|
||||
extern ssize_t decode_base64(char *out, const char *in, off_t length);
|
||||
|
||||
|
||||
#endif // BASE64_H
|
||||
@@ -1,29 +0,0 @@
|
||||
<html>
|
||||
<!-- Haiku HTML5 desktop -->
|
||||
<!-- Loosely inspired by the Broadway GDK backend, just done differently -->
|
||||
<head>
|
||||
<title>Haiku</title>
|
||||
<meta name="robots" content="noindex, nofollow, noarchive" />
|
||||
<style type="text/css">
|
||||
<!--
|
||||
/* basic style */
|
||||
body { background-color: #336698; }
|
||||
a:link { color:orange; }
|
||||
a:visited { color:darkorange; }
|
||||
a:hover { color:pink; }
|
||||
.haiku_online_form { color: white; }
|
||||
.haiku_online_disabled { color: grey; }
|
||||
.haiku_online_out { color: white; }
|
||||
.haiku_online_debug { color: orange; }
|
||||
.haiku_online_error { color: red; font-weight: bold; }
|
||||
-->
|
||||
</style>
|
||||
<script type="text/javascript" src="/haiku.js"></script>
|
||||
<link rel="shortcut icon" href="http://haiku-os.org/sites/haiku-os.org/themes/shijin/favicon.ico" type="image/x-icon" />
|
||||
</head>
|
||||
<body onload="onPageLoad()" onunload="onPageUnload()">
|
||||
<canvas id="desktop">Your browser does not support the <canvas> element, which is required.</canvas>
|
||||
<noscript>Your browser does not support javascript or javascript is disabled.</noscript>
|
||||
<div id="log"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,30 +0,0 @@
|
||||
static const char desktop_html[] =
|
||||
"<html>\n"
|
||||
"<!-- Haiku HTML5 desktop -->\n"
|
||||
"<!-- Loosely inspired by the Broadway GDK backend, just done differently -->\n"
|
||||
"<head>\n"
|
||||
"<title>Haiku</title>\n"
|
||||
"<meta name=\"robots\" content=\"noindex, nofollow, noarchive\" />\n"
|
||||
"<style type=\"text/css\">\n"
|
||||
"<!--\n"
|
||||
"/* basic style */\n"
|
||||
"body { background-color: #336698; }\n"
|
||||
"a:link { color:orange; }\n"
|
||||
"a:visited { color:darkorange; }\n"
|
||||
"a:hover { color:pink; }\n"
|
||||
".haiku_online_form { color: white; }\n"
|
||||
".haiku_online_disabled { color: grey; }\n"
|
||||
".haiku_online_out { color: white; }\n"
|
||||
".haiku_online_debug { color: orange; }\n"
|
||||
".haiku_online_error { color: red; font-weight: bold; }\n"
|
||||
"-->\n"
|
||||
"</style>\n"
|
||||
"<script type=\"text/javascript\" src=\"/haiku.js\"></script>\n"
|
||||
"<link rel=\"shortcut icon\" href=\"http://haiku-os.org/sites/haiku-os.org/themes/shijin/favicon.ico\" type=\"image/x-icon\" />\n"
|
||||
"</head>\n"
|
||||
"<body onload=\"onPageLoad()\" onunload=\"onPageUnload()\">\n"
|
||||
"<canvas id=\"desktop\">Your browser does not support the <canvas> element, which is required.</canvas>\n"
|
||||
"<noscript>Your browser does not support javascript or javascript is disabled.</noscript>\n"
|
||||
"<div id=\"log\"></div>\n"
|
||||
"</body>\n"
|
||||
"</html>\n";
|
||||
@@ -1,229 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* François Revol <revol@free.fr>
|
||||
*
|
||||
* Loosely inspired by
|
||||
* http://git.gnome.org/browse/gtk+/tree/gdk/broadway/broadway.js?h=broadway
|
||||
*/
|
||||
|
||||
var logDiv;
|
||||
var desktop; // the canvas
|
||||
|
||||
var b64Values = new Array(
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
|
||||
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
|
||||
|
||||
//DEBUG
|
||||
var stream={s:"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==",i:0};
|
||||
var stream2={s:"YWJjZAYWIYQVQqgqlUVaoVaqqVQqlVVqg",i:0};
|
||||
|
||||
|
||||
function b64_get_u32_(t, i)
|
||||
{
|
||||
var v = 0;
|
||||
if (b64Values[t.charCodeAt(i)] < 0) return v;
|
||||
v += b64Values[t.charCodeAt(i++)] << 26;
|
||||
if (b64Values[t.charCodeAt(i)] < 0) return v;
|
||||
v += b64Values[t.charCodeAt(i++)] << 20;
|
||||
if (b64Values[t.charCodeAt(i)] < 0) return v;
|
||||
v += b64Values[t.charCodeAt(i++)] << 14;
|
||||
if (b64Values[t.charCodeAt(i)] < 0) return v;
|
||||
v += b64Values[t.charCodeAt(i++)] << 8;
|
||||
if (b64Values[t.charCodeAt(i)] < 0) return v;
|
||||
v += b64Values[t.charCodeAt(i++)] << 2;
|
||||
if (b64Values[t.charCodeAt(i)] < 0) return v;
|
||||
v += b64Values[t.charCodeAt(i++)] >> 4;
|
||||
if (b64Values[t.charCodeAt(i)] < 0) i++;
|
||||
if (b64Values[t.charCodeAt(i)] < 0) i++;
|
||||
dbg("u32:" + v + " 0x" + v.toString(16));
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
function b64_get_u8(s)
|
||||
{
|
||||
var v = 0;
|
||||
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
|
||||
v += b64Values[s.s.charCodeAt(s.i++)] << 2;
|
||||
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
|
||||
v += b64Values[s.s.charCodeAt(s.i++)] >> 4;
|
||||
if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;
|
||||
if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;
|
||||
dbg(" u8:" + v + " 0x" + v.toString(16));
|
||||
return v;
|
||||
}
|
||||
|
||||
function b64_get_u16(s)
|
||||
{
|
||||
var v = 0;
|
||||
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
|
||||
v += b64Values[s.s.charCodeAt(s.i++)] << 10;
|
||||
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
|
||||
v += b64Values[s.s.charCodeAt(s.i++)] << 4;
|
||||
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
|
||||
v += b64Values[s.s.charCodeAt(s.i++)] >> 2;
|
||||
if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;
|
||||
dbg("u16:" + v + " 0x" + v.toString(16));
|
||||
return v;
|
||||
}
|
||||
|
||||
function b64_get_u32(s)
|
||||
{
|
||||
var v = 0;
|
||||
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
|
||||
v += b64Values[s.s.charCodeAt(s.i++)] << 26;
|
||||
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
|
||||
v += b64Values[s.s.charCodeAt(s.i++)] << 20;
|
||||
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
|
||||
v += b64Values[s.s.charCodeAt(s.i++)] << 14;
|
||||
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
|
||||
v += b64Values[s.s.charCodeAt(s.i++)] << 8;
|
||||
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
|
||||
v += b64Values[s.s.charCodeAt(s.i++)] << 2;
|
||||
if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;
|
||||
v += b64Values[s.s.charCodeAt(s.i++)] >> 4;
|
||||
//v &= 0x0ffffffff;
|
||||
if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;
|
||||
if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;
|
||||
dbg("u32:" + v + " 0x" + v.toString(16));
|
||||
return v;
|
||||
}
|
||||
|
||||
function dbg(str)
|
||||
{
|
||||
var div = document.createElement("div");
|
||||
div.className = "haiku_online_debug";
|
||||
div.appendChild(document.createTextNode(str));
|
||||
logDiv.appendChild(div);
|
||||
}
|
||||
|
||||
function err(str)
|
||||
{
|
||||
var div = document.createElement("div");
|
||||
div.className = "haiku_online_error";
|
||||
div.appendChild(document.createTextNode(str));
|
||||
logDiv.appendChild(div);
|
||||
}
|
||||
|
||||
function createXHR()
|
||||
{
|
||||
try {
|
||||
return new XMLHttpRequest();
|
||||
} catch(e) {
|
||||
err("Failed to create XHR: " + e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function onMessage(message)
|
||||
{
|
||||
dbg("onMessage: ");
|
||||
window.popup("plop");
|
||||
dbg(message.target.responseText);
|
||||
}
|
||||
|
||||
function decodeCanvasMessage(msg)
|
||||
{
|
||||
dbg("decodeCanvasMessage()");
|
||||
var code = b64_get_u16(msg);
|
||||
dbg("code: " + code);
|
||||
/* switch (code) {
|
||||
//case 1:
|
||||
//break;
|
||||
default:
|
||||
dbg("unhandled code " + code);
|
||||
return;
|
||||
}*/
|
||||
}
|
||||
|
||||
function onReadyStateChange()
|
||||
{
|
||||
dbg("readystate changed: " + this.readyState);
|
||||
if (this.readyState != 4)
|
||||
return;
|
||||
dbg("status: " + this.status);
|
||||
dbg("resonseType: " + this.responseType);
|
||||
dbg("response: " + this.responseText);
|
||||
//dbg("headers: " + this.getAllResponseHeaders());
|
||||
//var stream={s:"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==",i:0};
|
||||
var msg = {s:(this.responseText),i:0};
|
||||
decodeCanvasMessage(msg);
|
||||
}
|
||||
|
||||
//DEBUG
|
||||
function testB64(stream)
|
||||
{
|
||||
var i = 0;
|
||||
b64_get_u32(stream);
|
||||
b64_get_u16(stream);
|
||||
b64_get_u8(stream);
|
||||
b64_get_u8(stream);
|
||||
b64_get_u8(stream);
|
||||
b64_get_u16(stream);
|
||||
b64_get_u16(stream);
|
||||
b64_get_u32(stream);
|
||||
b64_get_u32(stream);
|
||||
dbg("s.i:"+stream.i);
|
||||
}
|
||||
|
||||
function initDesktop()
|
||||
{
|
||||
dbg("initDesktop()");
|
||||
|
||||
//testB64(stream);
|
||||
//testB64(stream2);
|
||||
|
||||
//var stream={s:"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==",i:0};
|
||||
var msg = {s:"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==",i:0};
|
||||
decodeCanvasMessage(stream);
|
||||
|
||||
desktop = document.getElementById("desktop");
|
||||
var xhr = createXHR();
|
||||
if (xhr) {
|
||||
if (typeof xhr.multipart != "undefined")
|
||||
xhr.multipart = true;
|
||||
else {
|
||||
err("XHR has no multipart field!");
|
||||
return;
|
||||
}
|
||||
if (typeof xhr.async != "undefined")
|
||||
xhr.async = true;
|
||||
else {
|
||||
dbg("XHR has no async field!");
|
||||
}
|
||||
dbg("multipart: " + xhr.multipart);
|
||||
xhr.open("GET", "http://127.0.0.1:8080/output", true);
|
||||
//xhr.onload = onMessage;
|
||||
xhr.onreadystatechange = onReadyStateChange;
|
||||
//xhr.responseType = "arraybuffer";
|
||||
//dbg("xhr.onload:" + xhr.onload);
|
||||
//dbg("xhr.send:" + xhr.send);
|
||||
//xhr.overrideMimeType("multipart/x-mixed-replace;boundary=x");
|
||||
xhr.send(null);
|
||||
//dbg("headers: " + xhr.getAllResponseHeaders());
|
||||
} else
|
||||
err("No XHR");
|
||||
dbg("done");
|
||||
}
|
||||
|
||||
|
||||
function onPageLoad() {
|
||||
logDiv = document.getElementById("log");
|
||||
dbg("onPageLoad()");
|
||||
initDesktop();
|
||||
}
|
||||
|
||||
function onPageUnload() {
|
||||
dbg("onPageUnload()");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,230 +0,0 @@
|
||||
static const char haiku_js[] =
|
||||
"/*\n"
|
||||
" * Copyright 2012, Haiku, Inc.\n"
|
||||
" * Distributed under the terms of the MIT License.\n"
|
||||
" *\n"
|
||||
" * Authors:\n"
|
||||
" * François Revol <[email protected]>\n"
|
||||
" *\n"
|
||||
" * Loosely inspired by\n"
|
||||
" * http://git.gnome.org/browse/gtk+/tree/gdk/broadway/broadway.js?h=broadway\n"
|
||||
" */\n"
|
||||
"\n"
|
||||
"var logDiv;\n"
|
||||
"var desktop; // the canvas\n"
|
||||
"\n"
|
||||
"var b64Values = new Array(\n"
|
||||
" -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n"
|
||||
" -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n"
|
||||
" -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,\n"
|
||||
" 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,\n"
|
||||
" -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,\n"
|
||||
" 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,\n"
|
||||
" -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,\n"
|
||||
" 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);\n"
|
||||
"\n"
|
||||
"//DEBUG\n"
|
||||
"var stream={s:\"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==\",i:0};\n"
|
||||
"var stream2={s:\"YWJjZAYWIYQVQqgqlUVaoVaqqVQqlVVqg\",i:0};\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"function b64_get_u32_(t, i)\n"
|
||||
"{\n"
|
||||
" var v = 0;\n"
|
||||
" if (b64Values[t.charCodeAt(i)] < 0) return v;\n"
|
||||
" v += b64Values[t.charCodeAt(i++)] << 26;\n"
|
||||
" if (b64Values[t.charCodeAt(i)] < 0) return v;\n"
|
||||
" v += b64Values[t.charCodeAt(i++)] << 20;\n"
|
||||
" if (b64Values[t.charCodeAt(i)] < 0) return v;\n"
|
||||
" v += b64Values[t.charCodeAt(i++)] << 14;\n"
|
||||
" if (b64Values[t.charCodeAt(i)] < 0) return v;\n"
|
||||
" v += b64Values[t.charCodeAt(i++)] << 8;\n"
|
||||
" if (b64Values[t.charCodeAt(i)] < 0) return v;\n"
|
||||
" v += b64Values[t.charCodeAt(i++)] << 2;\n"
|
||||
" if (b64Values[t.charCodeAt(i)] < 0) return v;\n"
|
||||
" v += b64Values[t.charCodeAt(i++)] >> 4;\n"
|
||||
" if (b64Values[t.charCodeAt(i)] < 0) i++;\n"
|
||||
" if (b64Values[t.charCodeAt(i)] < 0) i++;\n"
|
||||
" dbg(\"u32:\" + v + \" 0x\" + v.toString(16));\n"
|
||||
" return v;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"function b64_get_u8(s)\n"
|
||||
"{\n"
|
||||
" var v = 0;\n"
|
||||
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
|
||||
" v += b64Values[s.s.charCodeAt(s.i++)] << 2;\n"
|
||||
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
|
||||
" v += b64Values[s.s.charCodeAt(s.i++)] >> 4;\n"
|
||||
" if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;\n"
|
||||
" if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;\n"
|
||||
" dbg(\" u8:\" + v + \" 0x\" + v.toString(16));\n"
|
||||
" return v;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function b64_get_u16(s)\n"
|
||||
"{\n"
|
||||
" var v = 0;\n"
|
||||
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
|
||||
" v += b64Values[s.s.charCodeAt(s.i++)] << 10;\n"
|
||||
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
|
||||
" v += b64Values[s.s.charCodeAt(s.i++)] << 4;\n"
|
||||
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
|
||||
" v += b64Values[s.s.charCodeAt(s.i++)] >> 2;\n"
|
||||
" if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;\n"
|
||||
" dbg(\"u16:\" + v + \" 0x\" + v.toString(16));\n"
|
||||
" return v;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function b64_get_u32(s)\n"
|
||||
"{\n"
|
||||
" var v = 0;\n"
|
||||
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
|
||||
" v += b64Values[s.s.charCodeAt(s.i++)] << 26;\n"
|
||||
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
|
||||
" v += b64Values[s.s.charCodeAt(s.i++)] << 20;\n"
|
||||
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
|
||||
" v += b64Values[s.s.charCodeAt(s.i++)] << 14;\n"
|
||||
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
|
||||
" v += b64Values[s.s.charCodeAt(s.i++)] << 8;\n"
|
||||
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
|
||||
" v += b64Values[s.s.charCodeAt(s.i++)] << 2;\n"
|
||||
" if (b64Values[s.s.charCodeAt(s.i)] < 0) return v;\n"
|
||||
" v += b64Values[s.s.charCodeAt(s.i++)] >> 4;\n"
|
||||
" //v &= 0x0ffffffff;\n"
|
||||
" if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;\n"
|
||||
" if (b64Values[s.s.charCodeAt(s.i)] < 0) s.i++;\n"
|
||||
" dbg(\"u32:\" + v + \" 0x\" + v.toString(16));\n"
|
||||
" return v;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function dbg(str)\n"
|
||||
"{\n"
|
||||
" var div = document.createElement(\"div\");\n"
|
||||
" div.className = \"haiku_online_debug\";\n"
|
||||
" div.appendChild(document.createTextNode(str));\n"
|
||||
" logDiv.appendChild(div);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function err(str)\n"
|
||||
"{\n"
|
||||
" var div = document.createElement(\"div\");\n"
|
||||
" div.className = \"haiku_online_error\";\n"
|
||||
" div.appendChild(document.createTextNode(str));\n"
|
||||
" logDiv.appendChild(div);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function createXHR()\n"
|
||||
"{\n"
|
||||
" try {\n"
|
||||
" return new XMLHttpRequest();\n"
|
||||
" } catch(e) {\n"
|
||||
" err(\"Failed to create XHR: \" + e);\n"
|
||||
" }\n"
|
||||
" return null;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function onMessage(message)\n"
|
||||
"{\n"
|
||||
" dbg(\"onMessage: \");\n"
|
||||
"window.popup(\"plop\");\n"
|
||||
" dbg(message.target.responseText);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function decodeCanvasMessage(msg)\n"
|
||||
"{\n"
|
||||
" dbg(\"decodeCanvasMessage()\");\n"
|
||||
" var code = b64_get_u16(msg);\n"
|
||||
" dbg(\"code: \" + code);\n"
|
||||
"/* switch (code) {\n"
|
||||
" //case 1:\n"
|
||||
" //break;\n"
|
||||
" default:\n"
|
||||
" dbg(\"unhandled code \" + code);\n"
|
||||
" return;\n"
|
||||
" }*/\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function onReadyStateChange()\n"
|
||||
"{\n"
|
||||
" dbg(\"readystate changed: \" + this.readyState);\n"
|
||||
" if (this.readyState != 4)\n"
|
||||
" return;\n"
|
||||
" dbg(\"status: \" + this.status);\n"
|
||||
" dbg(\"resonseType: \" + this.responseType);\n"
|
||||
" dbg(\"response: \" + this.responseText);\n"
|
||||
" //dbg(\"headers: \" + this.getAllResponseHeaders());\n"
|
||||
"//var stream={s:\"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==\",i:0};\n"
|
||||
" var msg = {s:(this.responseText),i:0};\n"
|
||||
" decodeCanvasMessage(msg);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"//DEBUG\n"
|
||||
"function testB64(stream)\n"
|
||||
"{\n"
|
||||
" var i = 0;\n"
|
||||
" b64_get_u32(stream);\n"
|
||||
" b64_get_u16(stream);\n"
|
||||
" b64_get_u8(stream);\n"
|
||||
" b64_get_u8(stream);\n"
|
||||
" b64_get_u8(stream);\n"
|
||||
" b64_get_u16(stream);\n"
|
||||
" b64_get_u16(stream);\n"
|
||||
" b64_get_u32(stream);\n"
|
||||
" b64_get_u32(stream);\n"
|
||||
" dbg(\"s.i:\"+stream.i);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function initDesktop()\n"
|
||||
"{\n"
|
||||
" dbg(\"initDesktop()\");\n"
|
||||
"\n"
|
||||
" //testB64(stream);\n"
|
||||
" //testB64(stream2);\n"
|
||||
"\n"
|
||||
"//var stream={s:\"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==\",i:0};\n"
|
||||
" var msg = {s:\"YWJjZA==YWI=YQ==VQ==qg==qlU=Vao=VaqqVQ==qlVVqg==\",i:0};\n"
|
||||
" decodeCanvasMessage(stream);\n"
|
||||
"\n"
|
||||
" desktop = document.getElementById(\"desktop\");\n"
|
||||
" var xhr = createXHR();\n"
|
||||
" if (xhr) {\n"
|
||||
" if (typeof xhr.multipart != \"undefined\")\n"
|
||||
" xhr.multipart = true;\n"
|
||||
" else {\n"
|
||||
" err(\"XHR has no multipart field!\");\n"
|
||||
" return;\n"
|
||||
" }\n"
|
||||
" if (typeof xhr.async != \"undefined\")\n"
|
||||
" xhr.async = true;\n"
|
||||
" else {\n"
|
||||
" dbg(\"XHR has no async field!\");\n"
|
||||
" }\n"
|
||||
" dbg(\"multipart: \" + xhr.multipart);\n"
|
||||
" xhr.open(\"GET\", \"http://127.0.0.1:8080/output\", true);\n"
|
||||
" //xhr.onload = onMessage;\n"
|
||||
" xhr.onreadystatechange = onReadyStateChange;\n"
|
||||
" //xhr.responseType = \"arraybuffer\";\n"
|
||||
" //dbg(\"xhr.onload:\" + xhr.onload);\n"
|
||||
" //dbg(\"xhr.send:\" + xhr.send);\n"
|
||||
" //xhr.overrideMimeType(\"multipart/x-mixed-replace;boundary=x\");\n"
|
||||
" xhr.send(null);\n"
|
||||
" //dbg(\"headers: \" + xhr.getAllResponseHeaders());\n"
|
||||
" } else\n"
|
||||
" err(\"No XHR\");\n"
|
||||
" dbg(\"done\");\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"function onPageLoad() {\n"
|
||||
" logDiv = document.getElementById(\"log\");\n"
|
||||
" dbg(\"onPageLoad()\");\n"
|
||||
" initDesktop();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"function onPageUnload() {\n"
|
||||
" dbg(\"onPageUnload()\");\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n";
|
||||
Reference in New Issue
Block a user