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 Painter ] ;
|
||||||
UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing interface local ] ;
|
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 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 stackandtile ] ;
|
||||||
|
|
||||||
UseHeaders [ FDirName $(HAIKU_TOP) src servers app decorator ] ;
|
UseHeaders [ FDirName $(HAIKU_TOP) src servers app decorator ] ;
|
||||||
@@ -107,7 +106,7 @@ Server app_server :
|
|||||||
# libraries
|
# libraries
|
||||||
:
|
:
|
||||||
libtranslation.so libbe.so libbnetapi.so
|
libtranslation.so libbe.so libbnetapi.so
|
||||||
libaslocal.a libasremote.a libashtml5.a
|
libaslocal.a libasremote.a
|
||||||
libasdrawing.a libpainter.a libagg.a
|
libasdrawing.a libpainter.a libagg.a
|
||||||
[ BuildFeatureAttribute freetype : library ]
|
[ BuildFeatureAttribute freetype : library ]
|
||||||
[ BuildFeatureAttribute fontconfig : library ]
|
[ BuildFeatureAttribute fontconfig : library ]
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#include "ServerConfig.h"
|
#include "ServerConfig.h"
|
||||||
|
|
||||||
#include "RemoteHWInterface.h"
|
#include "RemoteHWInterface.h"
|
||||||
#include "HTML5HWInterface.h"
|
|
||||||
|
|
||||||
#include <Autolock.h>
|
#include <Autolock.h>
|
||||||
#include <Entry.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
|
// TODO: right now we only support remote screens, but we could
|
||||||
// also target specific accelerants to support other graphics cards
|
// also target specific accelerants to support other graphics cards
|
||||||
HWInterface* interface;
|
HWInterface* interface;
|
||||||
/*
|
/*if (strncmp(target, "vnc:", 4) == 0)
|
||||||
if (strncmp(target, "vnc:", 4) == 0)
|
|
||||||
interface = new(nothrow) VNCHWInterface(target);
|
interface = new(nothrow) VNCHWInterface(target);
|
||||||
else*/
|
else*/
|
||||||
if (strncmp(target, "html5:", 6) == 0)
|
|
||||||
interface = new(nothrow) HTML5HWInterface(target);
|
|
||||||
else
|
|
||||||
interface = new(nothrow) RemoteHWInterface(target);
|
interface = new(nothrow) RemoteHWInterface(target);
|
||||||
if (interface != NULL) {
|
if (interface != NULL) {
|
||||||
screen_item* item = _AddHWInterface(interface);
|
screen_item* item = _AddHWInterface(interface);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
SubDir HAIKU_TOP src servers app drawing interface ;
|
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 local ;
|
||||||
SubInclude HAIKU_TOP src servers app drawing interface remote ;
|
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 <[email protected]>
|
|
||||||
* François Revol <[email protected]>
|
|
||||||
*/
|
|
||||||
#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 <[email protected]>
|
|
||||||
* François Revol <[email protected]>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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 <[email protected]>
|
|
||||||
* François Revol <[email protected]>
|
|
||||||
*/
|
|
||||||
#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 <[email protected]>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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 <[email protected]>
|
|
||||||
*/
|
|
||||||
#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 <[email protected]>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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 <[email protected]>
|
|
||||||
*/
|
|
||||||
#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 <[email protected]>
|
|
||||||
* François Revol <[email protected]>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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 <[email protected]>
|
|
||||||
* François Revol <[email protected]>
|
|
||||||
*/
|
|
||||||
#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 <[email protected]>
|
|
||||||
* François Revol <[email protected]>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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 <[email protected]>
|
|
||||||
* François Revol <[email protected]>
|
|
||||||
*/
|
|
||||||
#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 <[email protected]>
|
|
||||||
* François Revol <[email protected]>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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 <[email protected]>
|
|
||||||
* François Revol <[email protected]>
|
|
||||||
*/
|
|
||||||
#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 <[email protected]>
|
|
||||||
*
|
|
||||||
* 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