.developing Turtle

git-svn-id: svn://ultimatepp.org/upp/trunk@6812 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2014-01-26 21:32:54 +00:00
parent 184ec3274a
commit c364742944
15 changed files with 596 additions and 320 deletions

View file

@ -2,11 +2,9 @@
private:
static Ptr<Ctrl> desktop;
static Vector<Ctrl *> topctrl;
static bool invalid;
static Point fbCursorPos;
static Image fbCursorImage;
static bool sdlMouseIsIn;
static Rect fbCaretRect;
static int fbCaretTm;
@ -15,7 +13,28 @@ private:
static int64 fbEventLoop;
static int64 fbEndSessionLoop;
static void CursorSync();
static Ctrl& Desktop();
static void TimerAndPaint();
static bool ProcessEvent(const String& event);
static bool quit;
static int main_pid;
static Vector<int> pid;
static TcpSocket socket;
static WebSocket websocket;
static int64 update_serial;
static int64 recieved_update_serial;
static Vector<Rect> invalid;
static BiVector<String> event_queue;
static Size DesktopSize;
static void AddInvalid(const Rect& r);
void AddInvalid() { AddInvalid(GetScreenRect()); }
static void InvalidateDesktop();
int FindTopCtrl() const;
static Rect GetClipBound(const Vector<Rect>& inv, const Rect& r);
@ -49,21 +68,17 @@ private:
void SetOpen(bool b) { isopen = b; }
protected:
static Ctrl& Desktop();
static void TimerAndPaint();
static bool ProcessEvent(const String& event);
static bool quit;
static int main_pid;
static Vector<int> pid;
static TcpSocket socket;
static WebSocket websocket;
static void Signal(int signal);
static void Broadcast(int signal);
static void Put8(int x) { turtle_stream.Put(x); }
static void Put16(int x);
static void Put32(int x);
static void Put(Point p);
static void Put(Size sz);
static void Put(const Rect& r);
static void Put(const String& s);
public:
static bool DoKeyFB(dword key, int cnt);
@ -72,6 +87,9 @@ public:
static bool debugmode;
static String ip;
static Time stat_started;
static int64 stat_data_send;
static bool StartSession();
static Callback WhenDisconnect;
static void EndSession();
@ -80,21 +98,12 @@ public:
static Ctrl *GetDesktop() { return desktop; }
static void SetDesktopSize(Size sz);
static void Invalidate() { invalid = true; }
void DragRectDraw(const Rect& rect1, const Rect& rect2, const Rect& clip, int n,
Color color, int type, int animation);
static Ctrl *FindMouseTopCtrl();
static void PaintScene(SystemDraw& draw);
static void PaintCaretCursor(SystemDraw& draw);
static bool SystemCursor;
enum { DRAWDRAGRECT_SCREEN = 0x8000 };
_TODO_
static bool ProcessEventQueue(const String& event_queue);
//$ };

View file

@ -2,43 +2,10 @@
#ifdef GUI_TURTLE
#define LLOG(x) // LOG(x)
NAMESPACE_UPP
void SystemDraw::Put16(int x)
{
Put8(LOBYTE(x));
Put8(HIBYTE(x));
}
void SystemDraw::Put32(int x)
{
Put16(LOWORD(x));
Put16(HIWORD(x));
}
void SystemDraw::Put(Point p)
{// TODO: Clamp?
Put16(p.x);
Put16(p.y);
}
void SystemDraw::Put(Size sz)
{
Put((Point)sz);
}
void SystemDraw::Put(const Rect& r)
{
Put(r.TopLeft());
Put(r.GetSize());
}
void SystemDraw::Put(const String& s)
{
Put32(s.GetLength());
turtle_stream.Put(s);
}
Index<int64> SystemDraw::img_index[3];
int SystemDraw::GetImageI(int from, Index<int64>& img_index, int maxcount, const Image& img)
@ -54,15 +21,16 @@ int SystemDraw::GetImageI(int from, Index<int64>& img_index, int maxcount, const
q = Random(maxcount);
img_index.Set(q, id);
}
Put8(SETIMAGE);
Put16(q + from);
Put(img.GetSize());
LLOG("SetImage " << q + from << ", size: " << img.GetLength());
Ctrl::Put8(SETIMAGE);
Ctrl::Put16(q + from);
Ctrl::Put(img.GetSize());
const RGBA *end = ~img + img.GetLength();
for(const RGBA *s = ~img; s < end; s++) {
Put8(s->r);
Put8(s->g);
Put8(s->b);
Put8(s->a);
Ctrl::Put8(s->r);
Ctrl::Put8(s->g);
Ctrl::Put8(s->b);
Ctrl::Put8(s->a);
}
}
return q + from;
@ -78,26 +46,53 @@ int SystemDraw::GetImageI(const Image& img)
void SystemDraw::PutImage(Point p, const Image& img, const Rect& src)
{
LLOG("Ctrl::PutImage " << p << ", size: " << img.GetSize() << ", src: " << src << ", id: " << img.GetSerialId());
int i = GetImageI(img);
Put8(IMAGE);
Put16(i);
Put(p);
Put(src);
if(Rect(img.GetSize()) == src) {
Point dp = p - pos;
if(abs(dp.x) < 256 && abs(dp.y) < 256) {
Ctrl::Put8(dp.x < 0 ? dp.y < 0 ? IMAGENN : IMAGENP : dp.y < 0 ? IMAGEPN : IMAGEPP);
Ctrl::Put8(abs(dp.x));
Ctrl::Put8(abs(dp.y));
Ctrl::Put16(i);
pos = p;
return;
}
}
Ctrl::Put8(IMAGE);
Ctrl::Put16(i);
Ctrl::Put(p);
Ctrl::Put(src);
pos = p;
}
void SystemDraw::PutRect(const Rect& r, Color color)
{ // TODO: Support InvertColor
{
LLOG("Ctrl::PutRect " << r << ", color " << color);
Point p = r.TopLeft();
if(color == InvertColor()) {
Put8(INVERTRECT);
Put(r);
Ctrl::Put8(INVERTRECT);
Ctrl::Put(r);
}
else {
Put8(RECT);
Put(r);
Put8(color.GetR());
Put8(color.GetG());
Put8(color.GetB());
Size sz = r.GetSize();
Point dp = p - pos;
if(abs(dp.x) < 256 && abs(dp.y) < 256 && sz.cx < 256 && sz.cy < 256 && 0) {
Ctrl::Put8(dp.x < 0 ? dp.y < 0 ? RECTNN : RECTNP : dp.y < 0 ? RECTPN : RECTPP);
Ctrl::Put8(abs(dp.x));
Ctrl::Put8(abs(dp.y));
Ctrl::Put8(sz.cx);
Ctrl::Put8(sz.cy);
}
else {
Ctrl::Put8(RECT);
Ctrl::Put(r);
}
Ctrl::Put8(color.GetR());
Ctrl::Put8(color.GetG());
Ctrl::Put8(color.GetB());
}
pos = p;
}
END_UPP_NAMESPACE

View file

@ -63,7 +63,7 @@ void DrawDragRect(Ctrl& q, const DrawDragRectInfo& f)
DrawDragFrame(w, f.rect1, f.n, dash, f.animation);
DrawDragFrame(w, f.rect2, f.n, dash, f.animation);
// w.End();
Ctrl::PaintCaretCursor(w);
// Ctrl::PaintCaretCursor(w);
// SDL_GL_SwapWindow(screen.win);
}
@ -88,7 +88,7 @@ void FinishDragRect(Ctrl& q)
{
SystemDraw w;
Ctrl::PaintScene(w);
Ctrl::PaintCaretCursor(w);
// Ctrl::PaintCaretCursor(w);
_TODO_
//SDL_GL_SwapWindow(screen.win);
}

View file

@ -8,9 +8,12 @@ NAMESPACE_UPP
#define LDUMP(x) // RDUMP(x)
#define LTIMING(x)
Time Ctrl::stat_started;
int64 Ctrl::stat_data_send;
static Point MousePos;
Size DesktopSize = Size(1000, 1000);
Size Ctrl::DesktopSize = Size(1000, 1000);
StaticRect& DesktopRect()
{
@ -23,24 +26,7 @@ Ctrl& Ctrl::Desktop()
return DesktopRect();
}
BiVector<String> event_queue;
void Ctrl::TimerAndPaint()
{
LLOG("TimerAndPaint " << msecs());
TimerProc(GetTickCount());
DefferedFocusSync();
SyncCaret();
SyncTopWindows();
SweepMkImageCache();
DoPaint();
socket.Timeout(20000);
websocket.SendBinary(ZCompress(String(SystemDraw::DISABLESENDING, 1))); // Do not send events until data transfered and processed
String s = turtle_stream.FlushStream();
if(s.GetCount() > 10)
LLOG("Sending " << s.GetLength());
websocket.SendBinary(s);
}
BiVector<String> Ctrl::event_queue;
void Ctrl::EndSession()
{
@ -66,8 +52,20 @@ bool Ctrl::IsWaitingEvent()
}
LLOG("Recieved data " << s);
StringStream ss(s);
while(!ss.IsEof())
event_queue.AddTail(ss.GetLine());
while(!ss.IsEof()) {
String s = ss.GetLine();
CParser p(s);
try {
if(p.Id("S")) {
uint32 l = p.ReadNumber();
uint32 h = p.ReadNumber();
recieved_update_serial = MAKEQWORD(l, h);
}
else
event_queue.AddTail(s);
}
catch(CParser::Error) {}
}
}
socket.Timeout(20000);
if(socket.IsError())
@ -148,86 +146,6 @@ void Ctrl::SetCaret(int x, int y, int cx, int cy)
SyncCaret();
}
void Ctrl::SyncCaret()
{
CursorSync();
}
void Ctrl::CursorSync()
{
// LLOG("@ CursorSync");
Point p = GetMousePos() - fbCursorImage.GetHotSpot();
Rect cr = Null;
if(focusCtrl && (((GetTickCount() - fbCaretTm) / 500) & 1) == 0)
cr = (RectC(focusCtrl->caretx, focusCtrl->carety, focusCtrl->caretcx, focusCtrl->caretcy)
+ focusCtrl->GetScreenView().TopLeft()) & focusCtrl->GetScreenView();
if(fbCursorPos != p && !SystemCursor || cr != fbCaretRect) {
fbCaretRect = cr;
fbCursorPos = p;
Invalidate();
}
}
void Ctrl::PaintScene(SystemDraw& draw)
{
if(!desktop)
return;
LLOG("@ DoPaint");
LTIMING("DoPaint paint");
draw.Init(DesktopSize);
draw.Begin();
Vector<Rect> invalid;
invalid.Add(DesktopSize); _TODO_
for(int i = topctrl.GetCount() - 1; i >= 0; i--) {
Rect r = topctrl[i]->GetRect();
Rect ri = GetClipBound(invalid, r);
if(!IsNull(ri)) {
draw.Clipoff(r);
topctrl[i]->UpdateArea(draw, ri - r.TopLeft());
draw.End();
Subtract(invalid, r);
draw.ExcludeClip(r);
}
}
Rect ri = GetClipBound(invalid, desktop->GetRect().GetSize());
if(!IsNull(ri))
desktop->UpdateArea(draw, ri);
draw.End();
}
void Ctrl::PaintCaretCursor(SystemDraw& draw)
{
if(!IsNull(fbCaretRect))
draw.DrawRect(fbCaretRect, InvertColor);
int64 q = fbCursorImage.GetAuxData();
if(q) {
draw.Put8(SystemDraw::STD_CURSORIMAGE);
draw.Put8(clamp((int)q, 1, 16));
}
else {
String h;
Point p = fbCursorImage.GetHotSpot();
h << "url('data:image/png;base64,"
<< Base64Encode(PNGEncoder().SaveString(fbCursorImage))
<< "') " << p.x << ' ' << p.y << ", default";
draw.Put8(SystemDraw::SETCURSORIMAGE);
draw.Put16(0); // _TODO_ Cursor cache
draw.Put(h);
draw.Put8(SystemDraw::CURSORIMAGE);
draw.Put16(0); // _TODO_ Cursor cache
}
}
void Ctrl::DoPaint()
{
if(invalid && desktop) {
invalid = false;
SystemDraw draw;
PaintScene(draw);
PaintCaretCursor(draw);
}
}
bool keyShift;
bool keyCtrl;
bool keyAlt;
@ -238,6 +156,7 @@ bool GetAlt() { return keyAlt; }
bool GetCapsLock() { return false; } // Impossible to implement
dword fbKEYtoK(dword chr) {
if(findarg(chr, 9, 0xd) < 0)
chr = chr + K_DELTA;
if(chr == K_ALT_KEY || chr == K_CTRL_KEY || chr == K_SHIFT_KEY)
return chr;
@ -409,7 +328,7 @@ bool Ctrl::ProcessEvent(const String& event)
int code = p.ReadInt();
int which = p.ReadInt();
ReadKeyMods(p);
if(which && !keyAlt && !keyCtrl)
if(which && !keyAlt && !keyCtrl && findarg(which, 9, 0xd) < 0)
DoKeyFB(which, 1);
}
}

146
rainbow/Turtle/Output.cpp Normal file
View file

@ -0,0 +1,146 @@
#include "Local.h"
#ifdef GUI_TURTLE
NAMESPACE_UPP
#define LLOG(x) // LLOG(x)
#define LDUMP(x) // RDUMP(x)
#define LTIMING(x)
void Ctrl::Put16(int x)
{
Put8(LOBYTE(x));
Put8(HIBYTE(x));
}
void Ctrl::Put32(int x)
{
Put16(LOWORD(x));
Put16(HIWORD(x));
}
void Ctrl::Put(Point p)
{// TODO: Clamp?
Put16(p.x);
Put16(p.y);
}
void Ctrl::Put(Size sz)
{
Put((Point)sz);
}
void Ctrl::Put(const Rect& r)
{
Put(r.TopLeft());
Put(r.GetSize());
}
void Ctrl::Put(const String& s)
{
Put32(s.GetLength());
turtle_stream.Put(s);
}
void Ctrl::TimerAndPaint()
{
LLOG("TimerAndPaint " << msecs());
TimerProc(GetTickCount());
DefferedFocusSync();
SyncCaret();
SyncTopWindows();
SweepMkImageCache();
DoPaint();
socket.Timeout(20000);
if(turtle_stream.HasData()) {
websocket.SendBinary(ZCompress(String(SystemDraw::DISABLESENDING, 1))); // Do not send events until data transfered and processed
int64 x = ++update_serial;
Put8(SystemDraw::UPDATESERIAL);
Put32(LODWORD(x));
Put32(HIDWORD(x));
String s = turtle_stream.FlushStream();
stat_data_send += s.GetCount();
LLOG("Sending " << s.GetLength());
websocket.SendBinary(s);
}
}
void Ctrl::SyncCaret()
{
Rect cr = Null;
if(focusCtrl)
cr = (RectC(focusCtrl->caretx, focusCtrl->carety, focusCtrl->caretcx, focusCtrl->caretcy)
+ focusCtrl->GetScreenView().TopLeft()) & focusCtrl->GetScreenView();
if(cr != fbCaretRect) { // TODO: SetCaret should perhaps be called on Ctrl::SetCaret
Put8(SystemDraw::SETCARET);
Put(cr);
fbCaretRect = cr;
}
}
void Ctrl::PaintScene(SystemDraw& draw)
{
if(!desktop)
return;
LLOG("@ DoPaint");
LTIMING("DoPaint paint");
draw.Init(invalid, DesktopSize.cy);
// draw.Init(DesktopSize);
draw.Begin();
for(int i = topctrl.GetCount() - 1; i >= 0; i--) {
Rect r = topctrl[i]->GetRect();
Rect ri = GetClipBound(invalid, r);
LLOG(i << " Window " << r << ", bound " << ri);
if(!IsNull(ri)) {
draw.Clipoff(r);
topctrl[i]->UpdateArea(draw, ri - r.TopLeft());
draw.End();
draw.ExcludeClip(r);
Subtract(invalid, r);
}
}
Rect ri = GetClipBound(invalid, DesktopSize);
if(!IsNull(ri))
desktop->UpdateArea(draw, ri);
invalid.Clear();
draw.End();
// DDUMP(turtle_stream.FlushStream().GetCount()); abort();
}
void Ctrl::DoPaint()
{
if(recieved_update_serial >= update_serial - 1) { // Prevent overloading of transfer
if(invalid.GetCount() && desktop) {
SystemDraw draw;
PaintScene(draw);
}
static int64 prev_cursor_id = Null;
int64 id = fbCursorImage.GetSerialId();
if(id != prev_cursor_id) {
prev_cursor_id = id;
int64 q = fbCursorImage.GetAuxData();
if(q) {
Put8(SystemDraw::STD_CURSORIMAGE);
Put8(clamp((int)q, 1, 16));
}
else {
String h;
Point p = fbCursorImage.GetHotSpot();
h << "url('data:image/png;base64,"
<< Base64Encode(PNGEncoder().SaveString(fbCursorImage))
<< "') " << p.x << ' ' << p.y << ", default";
Put8(SystemDraw::SETCURSORIMAGE);
Put16(0); // _TODO_ Cursor cache
Put(h);
Put8(SystemDraw::CURSORIMAGE);
Put16(0); // _TODO_ Cursor cache
}
}
}
}
END_UPP_NAMESPACE
#endif

View file

@ -26,56 +26,20 @@ void Ctrl::Broadcast(int signal) {
#endif
}
void Ctrl::Signal(int signal)
{
#ifdef PLATFORM_POSIX
int i = 0;
while(i < pid.GetCount())
if(pid[i] && waitpid(pid[i], 0, WNOHANG | WUNTRACED) > 0)
pid.Remove(i);
else
i++;
switch(signal) {
case SIGTERM:
case SIGHUP:
quit = true;
Broadcast(signal);
break;
case SIGINT:
Broadcast(signal);
exit(0);
break;
case SIGALRM:
if(getpid() != main_pid) {
// "Timeout - session stoped"
exit(0);
}
break;
}
#endif
}
String Ctrl::host = "localhost";
int Ctrl::port = 8088;
bool Ctrl::debugmode;
String Ctrl::ip = "0.0.0.0";
TcpSocket Ctrl::socket;
WebSocket Ctrl::websocket;
int64 Ctrl::update_serial;
int64 Ctrl::recieved_update_serial;
bool Ctrl::StartSession()
{
LLOG("Connect");
#ifdef PLATFORM_POSIX
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = Signal;
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGALRM, &sa, NULL);
sigaction(SIGCHLD, &sa, NULL);
main_pid = getpid();
#endif
@ -99,11 +63,19 @@ bool Ctrl::StartSession()
}
#endif
RLOG("Starting to listen on 8088");
RLOG("Starting to listen on 8088, pid: " << getpid());
socket.Timeout(2000); // TODO: Not quite ideal way to make quit work..
for(;;) {
if(quit)
return false;
#ifdef PLATFORM_POSIX
int i = 0;
while(i < pid.GetCount())
if(pid[i] && waitpid(pid[i], 0, WNOHANG | WUNTRACED) > 0)
pid.Remove(i);
else
i++;
#endif
if(server.IsError())
server.ClearError();
if(socket.Accept(server)) {
@ -112,8 +84,10 @@ bool Ctrl::StartSession()
RLOG("Accepted, header read");
if(websocket.WebAccept(socket, http)) { // TODO: Connection limit, info
#ifdef PLATFORM_POSIX
if(debugmode)
break;
int newpid = fork();
if(debugmode || newpid == 0)
if(newpid == 0)
break;
else {
pid.Add(newpid);
@ -132,7 +106,7 @@ bool Ctrl::StartSession()
socket.Close();
}
}
RLOG("Connection established with " << socket.GetPeerAddr());
RLOG("Connection established with " << socket.GetPeerAddr() << ", pid: " << getpid());
server.Close();
if(socket.IsError())
RLOG("CONNECT ERROR: " << socket.GetErrorDesc());
@ -145,13 +119,19 @@ bool Ctrl::StartSession()
#endif
ChStdSkin();
extern Size DesktopSize;
extern StaticRect& DesktopRect();
DesktopRect().Color(Cyan());
DesktopRect().SetRect(0, 0, DesktopSize.cx, DesktopSize.cy);
SetDesktop(Desktop());
stat_started = GetSysTime();
while(!IsWaitingEvent())
GuiSleep(10);
ProcessEvents();
return true;
}

View file

@ -14,11 +14,13 @@ void TurtleStream::Reset()
{
zlib.Clear();
zlib.Compress();
hasdata = false;
}
void TurtleStream::Out(const void *data, dword size)
{
zlib.Put(data, (int)size);
hasdata = true;
}
String TurtleStream::FlushStream()

View file

@ -20,11 +20,13 @@ public:
private:
Zlib zlib;
bool hasdata;
void Reset();
public:
String FlushStream();
bool HasData() const { return hasdata; }
TurtleStream() { Reset(); }
};
@ -46,24 +48,33 @@ public:
SETCURSORIMAGE = 5,
CURSORIMAGE = 6,
DISABLESENDING = 7,
UPDATESERIAL = 8,
IMAGEPP = 9,
IMAGENP = 10,
IMAGEPN = 11,
IMAGENN = 12,
RECTPP = 13,
RECTNP = 14,
RECTPN = 15,
RECTNN = 16,
SETCARET = 17,
};
static Index<int64> img_index[3];
Point pos;
int GetImageI(int from, Index<int64>& img_index, int maxcount, const Image& img);
int GetImageI(const Image& img);
static void ResetI() { for(int i = 0; i < 3; i++) img_index[i].Clear(); }
void Put8(int x) { turtle_stream.Put(x); }
void Put16(int x);
void Put32(int x);
void Put(Point p);
void Put(Size sz);
void Put(const Rect& r);
void Put(const String& s);
bool CanSetSurface() { return false; }
static void Flush() {}
SystemDraw() { pos = Point(0, 0); }
};
struct BackDraw__ : public SystemDraw {
@ -114,7 +125,7 @@ class TopWindowFrame;
#define GUIPLATFORM_TOPWINDOW_DECLS_INCLUDE <Turtle/Top.h>
class PrinterJob { // Dummy only...
class PrinterJob { // _TODO_
NilDraw nil;
Vector<int> pages;
@ -137,11 +148,6 @@ public:
~PrinterJob() {}
};
void USDLSetup(dword flags);
void InitTelpp();
END_UPP_NAMESPACE
#define GUIPLATFORM_INCLUDE_AFTER <Turtle/After.h>

View file

@ -40,8 +40,8 @@ U.prototype.k=function(){var b=this.input,d,a;d=this.q.k();this.a=this.q.a;if(th
function Log(msg)
{
// if (window.console && console.log)
// console.log(msg); //for firebug
if (window.console && console.log)
console.log(msg); //for firebug
}
function Char(p, ch)
@ -83,19 +83,94 @@ function GetString(p)
var SendingEnabled = true;
var posx, posy;
var ctx;
var caretx = 0, carety = 0, caretcx = 0, caretcy = 0, caretshown = false;
var caretTimerID;
function InvertRect(x, y, cx, cy)
{
if(cx <= 0 || cy <= 0)
return;
var imageData = ctx.getImageData(x, y, cx, cy);
var data = imageData.data;
for(var i = 0; i < data.length; i += 4) {
data[i] = 255 - data[i];
data[i + 1] = 255 - data[i + 1];
data[i + 2] = 255 - data[i + 2];
}
ctx.putImageData(imageData, x, y);
}
function InvertCaret()
{
// Log("InvertCaret " + caretx + " " + carety + " " + caretcx + " " + caretcy);
if(caretcx >= 0 || caretcy >= 0)
InvertRect(caretx, carety, caretcx, caretcy);
}
function ClearCaretTimer()
{
if(caretTimerID != undefined)
clearTimeout(caretTimerID);
}
function CaretTimer()
{
ClearCaretTimer();
caretTimerID = setTimeout(DoCaret, 500);
}
function DoCaret()
{
if(caretcx || caretcy) {
InvertCaret();
caretshown = !caretshown;
CaretTimer();
}
}
function InvertShownCaret()
{
if(caretshown)
InvertCaret();
}
function HideCaret(x, y, cx, cy)
{
return;
if(caretHidden)
return;
if(Math.max(x, caretx) < Math.min(x + cx, caretx + caretcx) &&
Math.max(y, carety) < Math.min(y + cy, carety + caretcy)) {
Log("Hiding caret");
InvertShownCaret();
caretHidden = true;
}
}
function ProcessDraw(s)
{
// console.clear();
// window.document.title = "Processing draw";
var p = new Object;
p.data = s;
p.pos = 0;
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx = canvas.getContext("2d");
SendingEnabled = true;
posx = 0;
posy = 0;
InvertShownCaret();
while(p.pos < p.data.length) {
// Log(p.pos + ": " + p.data[p.pos]);
if(Char(p, 0)) { // RECT
@ -110,7 +185,10 @@ function ProcessDraw(s)
var c = "rgb(" + r + "," + g + "," + b + ")";
ctx.fillStyle = c;
// Log("color: " + c);
HideCaret(x, y, cx, cy);
ctx.fillRect(x, y, cx, cy);
posx = x;
posy = y;
}
else
if(Char(p, 3)) { // INVERTRECT
@ -119,14 +197,8 @@ function ProcessDraw(s)
var cx = Get16(p);
var cy = Get16(p);
// Log("irect: " + x + ", " + y + ", " + cx + ", " + cy);
var imageData = ctx.getImageData(x, y, cx, cy);
var data = imageData.data;
for(var i = 0; i < data.length; i += 4) {
data[i] = 255 - data[i];
data[i + 1] = 255 - data[i + 1];
data[i + 2] = 255 - data[i + 2];
}
ctx.putImageData(imageData, x, y);
HideCaret(x, y, cx, cy);
InvertRect(x, y, cx, cy);
}
else
if(Char(p, 2)) { // SETIMAGE
@ -161,8 +233,12 @@ function ProcessDraw(s)
// Log("Draw image: " + n);
if(window.img_cache[n] == undefined)
alert("Undefined: " + n);
alert("Undefined image: " + n);
HideCaret(x, y, cx, cy);
ctx.drawImage(window.img_cache[n], x, y, cx, cy, px, py, cx, cy);
posx = px;
posy = py;
}
else
if(Char(p, 4)) { // STD_CURSORIMAGE
@ -201,14 +277,93 @@ function ProcessDraw(s)
if(Char(p, 7)) { // DISABLESENDING
SendingEnabled = true;
}
else
if(Char(p, 8)) { // UPDATESERIAL
update_serial_l = Get32(p);
update_serial_h = Get32(p);
ws.send("S " + update_serial_l + " " + update_serial_h + "\n");
}
else
if(Char(p, 9)) // IMAGEPP
SImage(p, 1, 1);
else
if(Char(p, 10)) // IMAGENP
SImage(p, -1, 1);
else
if(Char(p, 11)) // IMAGEPN
SImage(p, 1, -1);
else
if(Char(p, 12)) // IMAGENN
SImage(p, -1, -1);
else
if(Char(p, 13)) // RECTPP
SRect(p, 1, 1);
else
if(Char(p, 14)) // RECTNP
SRect(p, -1, 1);
else
if(Char(p, 15)) // RECTPN
SRect(p, 1, -1);
else
if(Char(p, 16)) // RECTNN
SRect(p, -1, -1);
else
if(Char(p, 17)) { // SETCARET
caretx = Get16(p);
carety = Get16(p);
caretcx = Get16(p);
caretcy = Get16(p);
caretshown = true;
CaretTimer();
// Log("SET CARET " + caretx + " " + carety + " " + caretcx + " " + caretcy);
}
}
InvertShownCaret();
// window.document.title = "OK";
if(SendingEnabled && event_queue.length)
ScheduleSend();
}
function SImage(p, sx, sy)
{
var px = posx + sx * Get8(p);
var py = posy + sy * Get8(p);
var n = Get16(p);
// Log("Draw opt image: " + px + " " + py + " " + n);
var img = window.img_cache[n];
if(img == undefined)
alert("Undefined image: " + n);
HideCaret(px, py, img.width, img.height);
ctx.drawImage(window.img_cache[n], px, py);
posx = px;
posy = py;
}
function SRect(p, sx, sy)
{
var px = posx + sx * Get8(p);
var py = posy + sy * Get8(p);
var cx = Get8(p);
var cy = Get8(p);
var r = Get8(p);
var g = Get8(p);
var b = Get8(p);
// Log("rect: " + x + ", " + y + ", " + cx + ", " + cy);
var c = "rgb(" + r + "," + g + "," + b + ")";
ctx.fillStyle = c;
// Log("color: " + c);
HideCaret(x, y, cx, cy);
ctx.fillRect(x, y, cx, cy);
posx = px;
posy = py;
}
window.img_cache = {};
window.event_queue = "I\n";
window.cursor_cache = {};
window.update_serial_l = 0;
window.update_serial_h = 0;
var canvas = document.getElementById("myCanvas");
@ -302,9 +457,10 @@ function ScheduleSend()
function SendEvents()
{
if(SendingEnabled) {
if(event_queue.length)
Log("Sending " + event_queue);
if(event_queue.length) {
Log(event_queue);
ws.send(event_queue);
}
event_queue = "";
if(timerID != undefined)
clearTimeout(timerID);
@ -320,7 +476,7 @@ ws.onopen = function()
ws.onmessage = function(event)
{
Log("onmessage");
// Log("onmessage");
if(event.data instanceof ArrayBuffer) {
var inflate = new Zlib.Inflate(new Uint8Array(event.data));
ProcessDraw(inflate.decompress());
@ -329,6 +485,7 @@ ws.onmessage = function(event)
ws.onclose = function(ev)
{
ClearCaretTimer();
alert("Connection closed.");
};

View file

@ -19,6 +19,7 @@ file
Cursor.cpp,
Stream.cpp,
Server.cpp,
Output.cpp,
Event.cpp,
Top.h,
TopFrame.cpp,

View file

@ -12,31 +12,32 @@ NAMESPACE_UPP
Ptr<Ctrl> Ctrl::desktop;
Vector<Ctrl *> Ctrl::topctrl;
bool Ctrl::invalid;
bool Ctrl::sdlMouseIsIn;
Point Ctrl::fbCursorPos = Null;
Image Ctrl::fbCursorImage;
Rect Ctrl::fbCaretRect;
int Ctrl::fbCaretTm;
bool Ctrl::fbEndSession;
bool Ctrl::SystemCursor;
Vector<Rect> Ctrl::invalid;
void Ctrl::InvalidateDesktop()
{
AddInvalid(desktop->GetSize());
}
void Ctrl::SetDesktop(Ctrl& q)
{
desktop = &q;
desktop->SetOpen(true);
desktop->NewTop();
invalid = true;
InvalidateDesktop();
}
void Ctrl::SetDesktopSize(Size sz)
{
if(desktop)
desktop->SetRect(sz);
invalid = true;
InvalidateDesktop();
SyncTopWindows();
}
@ -164,11 +165,11 @@ Rect Ctrl::GetClipBound(const Vector<Rect>& inv, const Rect& r)
return ri;
}
void Ctrl::WndUpdate(const Rect&)
void Ctrl::WndUpdate(const Rect& r)
{
GuiLock __;
Invalidate();
DoPaint();
// WndInvalidateRect(r);
// DoPaint(); // TODO
}
Rect Ctrl::GetWndScreenRect() const
@ -255,7 +256,7 @@ void Ctrl::DestroyWnd()
topctrl[i]->WndDestroy();
int q = FindTopCtrl();
if(q >= 0) {
Invalidate();
AddInvalid();
topctrl.Remove(q);
}
if(top) {
@ -279,7 +280,7 @@ void Ctrl::PutForeground()
{
int q = FindTopCtrl();
if(q >= 0) {
Invalidate();
AddInvalid();
topctrl.Remove(q);
topctrl.Add(this);
}
@ -355,10 +356,21 @@ bool Ctrl::HasWndCapture() const
return captureCtrl && captureCtrl->GetTopCtrl() == this;
}
void Ctrl::WndInvalidateRect(const Rect&)
void Ctrl::AddInvalid(const Rect& r_)
{
Rect r = r_ & Rect(DesktopSize);
if(!IsNull(r))
AddRefreshRect(invalid, r);
}
void Ctrl::WndInvalidateRect(const Rect& r)
{
GuiLock __;
Invalidate();
int q = FindTopCtrl();
if(q >= 0)
AddInvalid(r + topctrl[q]->GetRect().TopLeft());
else
AddInvalid(r);
}
void Ctrl::WndSetPos(const Rect& rect)
@ -367,14 +379,15 @@ void Ctrl::WndSetPos(const Rect& rect)
TopWindow *w = dynamic_cast<TopWindow *>(this);
if(w)
w->SyncFrameRect(rect);
Invalidate();
AddInvalid();
SetWndRect(rect);
AddInvalid(rect);
}
void Ctrl::WndScrollView(const Rect& r, int dx, int dy)
{
GuiLock __;
LLOG("ScrollView " << rect);
LLOG("ScrollView " << r << ", size " << GetSize());
WndInvalidateRect(r);
}
@ -396,7 +409,7 @@ void Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow, boo
popup = isopen = true;
RefreshLayoutDeep();
if(activate) SetFocusWnd();
Invalidate();
AddInvalid();
}
Rect Ctrl::GetDefaultWindowRect() {

View file

@ -1,7 +1,4 @@
#include <RichEdit/RichEdit.h>
#include <PdfDraw/PdfDraw.h>
using namespace Upp;
#include "WebWord.h"
#define IMAGECLASS UWordImg
#define IMAGEFILE <UWord/UWord.iml>
@ -19,46 +16,6 @@ FileSel& PdfFs()
return fs;
}
struct UWord : public TopWindow {
public:
virtual void DragAndDrop(Point, PasteClip& d);
virtual void FrameDragAndDrop(Point, PasteClip& d);
virtual void ShutdownWindow();
RichEdit editor;
MenuBar menubar;
ToolBar toolbar;
StatusBar statusbar;
String filename;
static LRUList& lrufile() { static LRUList l; return l; }
void Load(const String& filename);
void OpenFile(const String& fn);
void New();
void Open();
void Save0();
void Save();
void SaveAs();
void Print();
void Pdf();
void About();
void Destroy(bool shutdown);
void SetBar();
void FileBar(Bar& bar);
void AboutMenu(Bar& bar);
void MainMenu(Bar& bar);
void MainBar(Bar& bar);
public:
typedef UWord CLASSNAME;
static void SerializeApp(Stream& s);
UWord();
};
void UWord::FileBar(Bar& bar)
{
/*
@ -94,6 +51,36 @@ void UWord::AboutMenu(Bar& bar)
bar.Add("About..", THISBACK(About));
}
String FormatSize(int64 n)
{
if(n < 10000)
return Format("%d B", n);
else
if(n < 10000 * 1024)
return Format("%d.%d KB", n >> 10, (n & 1023) / 103);
else
if(n < I64(10000000) * 1024)
return Format("%d.%d MB", n >> 20, (n & 1023) / 103);
else
return Format("%d.%d GB", n >> 30, (n & 1023) / 103);
}
void UWord::ShowInfo()
{
String s;
s << "Mem " << MemoryUsedKb() << " KB";
int secs = GetSysTime() - Ctrl::stat_started;
Time tm = Time(1, 1, 1, 0, 0, 0) + secs;
s << ", uptime " << Format("%d:%0d:%02d:%02d", tm - Date(1, 1, 1), tm.hour, tm.minute, tm.second);
s << ", data sent " << FormatSize(Ctrl::stat_data_send);
if(secs)
s << ", average bandwidth " << FormatSize(Ctrl::stat_data_send / secs) << "/s";
s << ", actual bandwidth " << FormatSize(Ctrl::stat_data_send - sent_prev);
sent_prev = Ctrl::stat_data_send;
statusbar.Set(s);
}
void UWord::MainMenu(Bar& bar)
{
// bar.Add("File", THISBACK(FileBar));
@ -248,6 +235,9 @@ UWord::UWord()
editor.WhenRefreshBar = THISBACK(SetBar);
OpenMain();
ActiveFocus(editor);
SetTimeCallback(-1000, THISBACK(ShowInfo));
sent_prev = 0;
}
void UWord::SerializeApp(Stream& s)
@ -294,7 +284,7 @@ struct EventsWnd : TopWindow {
EventsWnd() {
Add(l.SizePos());
SetTimeCallback(-100, THISBACK(Do));
SetTimeCallback(-1000, THISBACK(Do));
}
};
@ -311,7 +301,8 @@ CONSOLE_APP_MAIN
LOG("Session Started");
#ifdef _DEBUG
MemoryLimitKb(10000);
MemoryLimitKb(5000000);
Ctrl::debugmode = true;
#endif
Ctrl::WhenDisconnect = callback(FinishApp);
@ -325,6 +316,8 @@ CONSOLE_APP_MAIN
SetLanguage(LNG_ENGLISH);
SetDefaultCharset(CHARSET_UTF8);
PromptOK("Session started");
UWordFs().Type("QTF files", "*.qtf")
.AllFilesType()
.DefaultExt("qtf");

53
rainbow/WebWord/WebWord.h Normal file
View file

@ -0,0 +1,53 @@
#ifndef _WebWord_WebWord_h_
#define _WebWord_WebWord_h_
#include <RichEdit/RichEdit.h>
#include <PdfDraw/PdfDraw.h>
using namespace Upp;
struct UWord : public TopWindow {
public:
virtual void DragAndDrop(Point, PasteClip& d);
virtual void FrameDragAndDrop(Point, PasteClip& d);
virtual void ShutdownWindow();
RichEdit editor;
MenuBar menubar;
ToolBar toolbar;
StatusBar statusbar;
String filename;
int64 sent_prev;
static LRUList& lrufile() { static LRUList l; return l; }
void Load(const String& filename);
void OpenFile(const String& fn);
void New();
void Open();
void Save0();
void Save();
void SaveAs();
void Print();
void Pdf();
void About();
void Destroy(bool shutdown);
void SetBar();
void FileBar(Bar& bar);
void AboutMenu(Bar& bar);
void MainMenu(Bar& bar);
void MainBar(Bar& bar);
void ShowInfo();
public:
typedef UWord CLASSNAME;
static void SerializeApp(Stream& s);
UWord();
};
#endif

View file

@ -7,6 +7,7 @@ uses
file
test.qtf,
WebWord.h,
WebWord.cpp;
mainconfig

View file

@ -57,4 +57,5 @@
#define GUIPLATFORM_KEYCODES_INCLUDE <Turtle/Keys.h>
//need to make SDL_keysym.h known before K_ enum
#define GUIPLATFORM_INCLUDE <Turtle/Turtle.h>
#define GUIPLATFORM_NOSCROLL
#endif