From 17e31781b71464b33270dd15240baaadf83cf65b Mon Sep 17 00:00:00 2001 From: cxl Date: Mon, 16 Sep 2013 12:55:26 +0000 Subject: [PATCH] .rainbow: Developing SDL20GL git-svn-id: svn://ultimatepp.org/upp/trunk@6358 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- rainbow/SDL20GL/After.h | 51 ++ rainbow/SDL20GL/ChSysInit.cpp | 21 + rainbow/SDL20GL/Clip.cpp | 238 +++++++++ rainbow/SDL20GL/Ctrl.cpp | 81 ++++ rainbow/SDL20GL/Ctrl.h | 86 ++++ rainbow/SDL20GL/DnD.cpp | 150 ++++++ rainbow/SDL20GL/Draw.cpp | 109 +++++ rainbow/SDL20GL/Event.cpp | 189 ++++++++ rainbow/SDL20GL/FB.iml | 59 +++ rainbow/SDL20GL/Gui.h | 358 ++++++++++++++ rainbow/SDL20GL/Image.cpp | 44 ++ rainbow/SDL20GL/Keys.h | 110 +++++ rainbow/SDL20GL/Local.h | 69 +++ rainbow/SDL20GL/SDL.cpp | 162 +++++++ rainbow/SDL20GL/SDL20.h | 135 ++++++ rainbow/SDL20GL/SDL20GL.upp | 32 ++ rainbow/SDL20GL/SDLProc.cpp | 208 ++++++++ rainbow/SDL20GL/Top.cpp | 150 ++++++ rainbow/SDL20GL/Top.h | 16 + rainbow/SDL20GL/TopFrame.cpp | 259 ++++++++++ rainbow/SDL20GL/Util.cpp | 77 +++ rainbow/SDL20GL/Window.cpp | 58 +++ rainbow/SDL20GL/Wnd.cpp | 767 ++++++++++++++++++++++++++++++ rainbow/SDL20GL/init | 6 + rainbow/SDL20Uword/SDL20Uword.upp | 4 +- rainbow/SDL20Uword/init | 2 +- 26 files changed, 3438 insertions(+), 3 deletions(-) create mode 100644 rainbow/SDL20GL/After.h create mode 100644 rainbow/SDL20GL/ChSysInit.cpp create mode 100644 rainbow/SDL20GL/Clip.cpp create mode 100644 rainbow/SDL20GL/Ctrl.cpp create mode 100644 rainbow/SDL20GL/Ctrl.h create mode 100644 rainbow/SDL20GL/DnD.cpp create mode 100644 rainbow/SDL20GL/Draw.cpp create mode 100644 rainbow/SDL20GL/Event.cpp create mode 100644 rainbow/SDL20GL/FB.iml create mode 100644 rainbow/SDL20GL/Gui.h create mode 100644 rainbow/SDL20GL/Image.cpp create mode 100644 rainbow/SDL20GL/Keys.h create mode 100644 rainbow/SDL20GL/Local.h create mode 100644 rainbow/SDL20GL/SDL.cpp create mode 100644 rainbow/SDL20GL/SDL20.h create mode 100644 rainbow/SDL20GL/SDL20GL.upp create mode 100644 rainbow/SDL20GL/SDLProc.cpp create mode 100644 rainbow/SDL20GL/Top.cpp create mode 100644 rainbow/SDL20GL/Top.h create mode 100644 rainbow/SDL20GL/TopFrame.cpp create mode 100644 rainbow/SDL20GL/Util.cpp create mode 100644 rainbow/SDL20GL/Window.cpp create mode 100644 rainbow/SDL20GL/Wnd.cpp create mode 100644 rainbow/SDL20GL/init diff --git a/rainbow/SDL20GL/After.h b/rainbow/SDL20GL/After.h new file mode 100644 index 000000000..8f241c17e --- /dev/null +++ b/rainbow/SDL20GL/After.h @@ -0,0 +1,51 @@ +class ViewDraw : public SystemDraw { +public: + ViewDraw(Ctrl *ctrl); + ~ViewDraw(); +}; + + +/* +class ViewDraw : public SystemDraw { + Vector dummy; +public: + ViewDraw(Ctrl *) : SystemDraw(Ctrl::framebuffer, dummy) { dummy.Add(Rect(10, 10, 100, 100)); } +}; +*/ +class DHCtrl : Ctrl {}; + +void FBInit(); +void FBDeInit(); + +#ifdef PLATFORM_WIN32 +#define GUI_APP_MAIN \ +void GuiMainFn_(); \ +\ +extern "C" int main(int argc, char *argv[]) { \ + UPP::AppInit__(argc, (const char **)argv); \ + FBInit(); \ + GuiMainFn_(); \ + UPP::Ctrl::CloseTopCtrls(); \ + FBDeInit(); \ + return UPP::GetExitCode(); \ +} \ +\ +void GuiMainFn_() + +#endif + +#ifdef PLATFORM_POSIX +#define GUI_APP_MAIN \ +void GuiMainFn_(); \ +\ +extern "C" int main(int argc, const char **argv, const char **envptr) { \ + UPP::AppInit__(argc, argv, envptr); \ + FBInit(); \ + GuiMainFn_(); \ + UPP::Ctrl::CloseTopCtrls(); \ + FBDeInit(); \ + return UPP::GetExitCode(); \ +} \ +\ +void GuiMainFn_() +#endif diff --git a/rainbow/SDL20GL/ChSysInit.cpp b/rainbow/SDL20GL/ChSysInit.cpp new file mode 100644 index 000000000..052fa9b32 --- /dev/null +++ b/rainbow/SDL20GL/ChSysInit.cpp @@ -0,0 +1,21 @@ +#include "Local.h" + +#ifdef GUI_SDL20 + +NAMESPACE_UPP + +void ChSysInit() +{ + CtrlImg::Reset(); + CtrlsImg::Reset(); + ChReset(); +} + +void ChHostSkin() +{ + ChSysInit(); +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/SDL20GL/Clip.cpp b/rainbow/SDL20GL/Clip.cpp new file mode 100644 index 000000000..cfde63045 --- /dev/null +++ b/rainbow/SDL20GL/Clip.cpp @@ -0,0 +1,238 @@ +#include "Local.h" + +#ifdef GUI_SDL20 + +NAMESPACE_UPP + +#define LLOG(x) // LOG(x) + +static VectorMap fbClipboard; + +void ClearClipboard() +{ + GuiLock __; + fbClipboard.Clear(); +} + +void AppendClipboard(const char *format, const Value& data, String (*render)(const Value&)) +{ + GuiLock __; + ClipData& cd = fbClipboard.GetAdd(format); + cd.data = data; + cd.render = render; +} + +static String sRawRender(const Value& v) +{ + return v; +} + +void AppendClipboard(const char *format, const String& data) +{ + GuiLock __; + AppendClipboard(format, data, sRawRender); +} + +void AppendClipboard(const char *format, const byte *data, int length) +{ + GuiLock __; + AppendClipboard(format, String(data, length)); +} + +String ReadClipboard(const char *format) +{ + GuiLock __; + int q = fbClipboard.Find(format); + return q >= 0 ? (*fbClipboard[q].render)(fbClipboard[q].data) : String(); +} + +void AppendClipboardText(const String& s) +{ + AppendClipboard("text", ToSystemCharset(s)); +} + +void AppendClipboardUnicodeText(const WString& s) +{ + AppendClipboard("wtext", (byte *)~s, 2 * s.GetLength()); +} + +const char *ClipFmtsText() +{ + return "wtext;text"; +} + +String GetString(PasteClip& clip) +{ + GuiLock __; + if(clip.Accept("wtext")) { + String s = ~clip; + return WString((const wchar *)~s, wstrlen((const wchar *)~s)).ToString(); + } + if(clip.IsAvailable("text")) + return ~clip; + return Null; +} + +WString GetWString(PasteClip& clip) +{ + GuiLock __; + if(clip.Accept("wtext")) { + String s = ~clip; + return WString((const wchar *)~s, wstrlen((const wchar *)~s)); + } + if(clip.IsAvailable("text")) + return (~clip).ToWString(); + return Null; +} + + +bool AcceptText(PasteClip& clip) +{ + return clip.Accept(ClipFmtsText()); +} + +static String sText(const Value& data) +{ + return data; +} + +static String sWText(const Value& data) +{ + return Unicode__(WString(data)); +} + +void Append(VectorMap& data, const String& text) +{ + data.GetAdd("text", ClipData(text, sText)); + data.GetAdd("wtext", ClipData(text, sWText)); +} + +void Append(VectorMap& data, const WString& text) +{ + data.GetAdd("text", ClipData(text, sText)); + data.GetAdd("wtext", ClipData(text, sWText)); +} + +String GetTextClip(const WString& text, const String& fmt) +{ + if(fmt == "text") + return text.ToString(); + if(fmt == "wtext") + return Unicode__(text); + return Null; +} + +String GetTextClip(const String& text, const String& fmt) +{ + if(fmt == "text") + return text; + if(fmt == "wtext") + return Unicode__(text.ToWString()); + return Null; +} + +String ReadClipboardText() +{ + String w = ReadClipboard("text"); + return w.GetCount() ? w : ReadClipboardUnicodeText().ToString(); +} + +WString ReadClipboardUnicodeText() +{ + String w = ReadClipboard("wtext"); + if(w.GetCount()) + return WString((const wchar *)~w, w.GetLength() / 2); + return ReadClipboard("text").ToWString(); +} + +bool IsClipboardAvailable(const char *id) +{ + return fbClipboard.Find(id) >= 0; +} + +bool IsClipboardAvailableText() +{ + return IsClipboardAvailable("text") || IsClipboardAvailable("wtext"); +} + +const char *ClipFmtsImage() +{ + static const char *q; + ONCELOCK { + static String s = "dib;" + ClipFmt(); + q = s; + } + return q; +} + +bool AcceptImage(PasteClip& clip) +{ + GuiLock __; + return clip.Accept(ClipFmtsImage()); +} + +Image GetImage(PasteClip& clip) +{ + GuiLock __; + Image m; + if(Accept(clip)) { + LoadFromString(m, ~clip); + if(!m.IsEmpty()) + return m; + } + return Null; +} + +Image ReadClipboardImage() +{ + GuiLock __; + PasteClip d = Ctrl::Clipboard(); + return GetImage(d); +} + +String sImage(const Value& image) +{ + Image img = image; + return StoreAsString(const_cast(img)); +} + +String GetImageClip(const Image& img, const String& fmt) +{ + GuiLock __; + if(img.IsEmpty()) return Null; + if(fmt == ClipFmt()) + return sImage(img); + return Null; +} + +void AppendClipboardImage(const Image& img) +{ + GuiLock __; + if(img.IsEmpty()) return; + AppendClipboard(ClipFmt(), img, sImage); +} + +bool AcceptFiles(PasteClip& clip) +{ + if(clip.Accept("files")) { + clip.SetAction(DND_COPY); + return true; + } + return false; +} + +bool IsAvailableFiles(PasteClip& clip) +{ + return clip.IsAvailable("files"); +} + +Vector GetFiles(PasteClip& clip) +{ + GuiLock __; + Vector f; + return f; +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/SDL20GL/Ctrl.cpp b/rainbow/SDL20GL/Ctrl.cpp new file mode 100644 index 000000000..a0b35c0e5 --- /dev/null +++ b/rainbow/SDL20GL/Ctrl.cpp @@ -0,0 +1,81 @@ +#include "Local.h" + +#ifdef GUI_SDL20 + +#define LLOG(x) // DLOG(x) + +NAMESPACE_UPP + +void Ctrl::GuiPlatformConstruct() +{ +} + +void Ctrl::GuiPlatformRemove() +{ +} + +void Ctrl::GuiPlatformGetTopRect(Rect& r) const +{ +} + +bool Ctrl::GuiPlatformRefreshFrameSpecial(const Rect& r) +{ + return false; +} + +bool Ctrl::GuiPlatformSetFullRefreshSpecial() +{ + return false; +} + +void Ctrl::PaintCaret(SystemDraw& w) +{ +} + +String GuiPlatformGetKeyDesc(dword key) +{ + return Null; +} + +void Ctrl::GuiPlatformSelection(PasteClip&) +{ +} + +void GuiPlatformAdjustDragImage(ImageBuffer&) +{ +} + +bool GuiPlatformHasSizeGrip() +{ + return true; +} + +void GuiPlatformGripResize(TopWindow *q) +{ + q->GripResize(); +} + +Color GuiPlatformGetScreenPixel(int x, int y) +{ + return Ctrl::GetFrameBuffer()[y][x]; +} + +void GuiPlatformAfterMenuPopUp() +{ +} + +String Ctrl::Name() const { + GuiLock __; +#ifdef CPU_64 + String s = String(typeid(*this).name()) + " : 0x" + FormatIntHex(this); +#else + String s = String(typeid(*this).name()) + " : " + Format("0x%x", (int) this); +#endif + if(IsChild()) + s << "(parent " << String(typeid(*parent).name()) << ")"; + return s; +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/SDL20GL/Ctrl.h b/rainbow/SDL20GL/Ctrl.h new file mode 100644 index 000000000..ac2f22117 --- /dev/null +++ b/rainbow/SDL20GL/Ctrl.h @@ -0,0 +1,86 @@ +//$ class Ctrl { +private: + static Ptr desktop; + static Vector topctrl; + static ImageBuffer framebuffer; + static Vector invalid, update; + + static Point fbCursorPos; + static Image fbCursorImage; + + static Point fbCursorBakPos; + static Image fbCursorBak; + + static Rect fbCaretRect; + static Image fbCaretBak; + static int fbCaretTm; + + static int renderingMode; + + static bool fbEndSession; + static int64 fbEventLoop; + static int64 fbEndSessionLoop; + + static Image GetBak(Rect& tr); + static void RemoveCursor(); + static void RemoveCaret(); + static void CursorSync(); + + int FindTopCtrl() const; + static Rect GetClipBound(const Vector& inv, const Rect& r); + static void DoPaint(); + static void DoUpdate(); + static void SyncTopWindows(); + + static void AddInvalid(const Rect& rect); + + void DestroyWnd(); + + void NewTop() { top = new Top; top->owner_window = NULL; } + void PutForeground(); + static void MouseEventFB(Ptr t, int event, Point p, int zdelta); + Vector GetPaintRects(); + + static void DrawLine(const Vector& clip, int x, int y, int cx, int cy, bool horz, + const byte *pattern, int animation); + static void DragRectDraw0(const Vector& clip, const Rect& rect, int n, + const byte *pattern, int animation); + + friend struct PaintProxy__; + friend class TopWindowFrame; + friend class SystemDraw; + friend struct DnDLoop; + + void SetOpen(bool b) { isopen = b; } + +protected: + static int PaintLock; + +public: + static void DoMouseFB(int event, Point p, int zdelta = 0); + static bool DoKeyFB(dword key, int cnt); + + static void InitFB(); + static void ExitFB(); + static void EndSession(); + + static void SetDesktop(Ctrl& q); + static Ctrl *GetDesktop() { return desktop; } + static void SetFramebufferSize(Size sz); + + static const ImageBuffer& GetFrameBuffer() { return framebuffer; } + + static void SetRenderingMode(int mode); + + static void AddUpdate(const Rect& rect); + + void DragRectDraw(const Rect& rect1, const Rect& rect2, const Rect& clip, int n, + Color color, int type, int animation); + + static Ctrl *FindMouseTopCtrl(); + + static bool FullWindowDrag; + + enum { DRAWDRAGRECT_SCREEN = 0x8000 }; + +//$ }; diff --git a/rainbow/SDL20GL/DnD.cpp b/rainbow/SDL20GL/DnD.cpp new file mode 100644 index 000000000..46ba7de16 --- /dev/null +++ b/rainbow/SDL20GL/DnD.cpp @@ -0,0 +1,150 @@ +#include "Local.h" + +#ifdef GUI_SDL20 + +NAMESPACE_UPP + +#define LLOG(x) // DLOG(x) + +// -------------------------------------------------------------------------------------------- + +Ptr sDnDSource; + +Ctrl * Ctrl::GetDragAndDropSource() +{ + return sDnDSource; +} + +struct DnDLoop : LocalLoop { + const VectorMap *data; + Vector fmts; + + Image move, copy, reject; + Ptr target; + int action; + byte actions; + + void Sync(); + String GetData(const String& f); + void DnD(bool paste); + + virtual void LeftUp(Point, dword); + virtual bool Key(dword, int); + virtual void MouseMove(Point p, dword); + virtual Image CursorImage(Point, dword); +}; + +Ptr dndloop; + +bool PasteClip::IsAvailable(const char *fmt) const +{ + GuiLock __; + return dnd ? dndloop && FindIndex(dndloop->fmts, fmt) >= 0 + : IsClipboardAvailable(fmt); +} + +String DnDLoop::GetData(const String& f) +{ + GuiLock __; + int i = data->Find(f); + String d; + if(i >= 0) + d = (*data)[i].Render(); + else + if(sDnDSource) + d = sDnDSource->GetDropData(f); + return d; +} + +String PasteClip::Get(const char *fmt) const +{ + return dnd ? dndloop ? dndloop->GetData(fmt) : String() : ReadClipboard(fmt); +} + +void PasteClip::GuiPlatformConstruct() +{ + dnd = false; +} + +void DnDLoop::DnD(bool paste) +{ + PasteClip d; + d.paste = paste; + d.accepted = false; + d.allowed = (byte)actions; + d.action = GetCtrl() ? DND_COPY : DND_MOVE; + d.dnd = true; + if(target) + target->DnD(GetMousePos(), d); + action = d.IsAccepted() ? d.GetAction() : DND_NONE; +} + +void DnDLoop::Sync() +{ + GuiLock __; + Ptr t = FindMouseTopCtrl(); + if(t != target) + if(target) + target->DnDLeave(); + target = t; + DnD(false); +} + +void DnDLoop::LeftUp(Point, dword) +{ + GuiLock __; + LLOG("DnDLoop::LeftUp"); + DnD(true); + EndLoop(); +} + +void DnDLoop::MouseMove(Point p, dword) +{ + GuiLock __; + LLOG("DnDLoop::MouseMove"); + Sync(); +} + +bool DnDLoop::Key(dword, int) +{ + GuiLock __; + LLOG("DnDLoop::Key"); + Sync(); + return false; +} + +Image DnDLoop::CursorImage(Point, dword) +{ + GuiLock __; + return action == DND_MOVE ? move : action == DND_COPY ? copy : reject; +} + +int Ctrl::DoDragAndDrop(const char *fmts, const Image& sample, dword actions, + const VectorMap& data) +{ + GuiLock __; + DnDLoop d; + d.actions = (byte)actions; + d.reject = actions & DND_EXACTIMAGE ? CtrlCoreImg::DndNone() : MakeDragImage(CtrlCoreImg::DndNone(), sample); + if(actions & DND_COPY) + d.copy = actions & DND_EXACTIMAGE ? sample : MakeDragImage(CtrlCoreImg::DndCopy(), sample); + if(actions & DND_MOVE) + d.move = actions & DND_EXACTIMAGE ? sample : MakeDragImage(CtrlCoreImg::DndMoveX11(), sample); + d.SetMaster(*this); + d.data = &data; + d.action = DND_NONE; + d.fmts = Split(fmts, ';'); + dndloop = &d; + sDnDSource = this; + d.Run(); + sDnDSource = NULL; + SyncCaret(); + LLOG("DoDragAndDrop finished"); + return d.action; +} + +void Ctrl::SetSelectionSource(const char *fmts) {} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/SDL20GL/Draw.cpp b/rainbow/SDL20GL/Draw.cpp new file mode 100644 index 000000000..6e241fdd8 --- /dev/null +++ b/rainbow/SDL20GL/Draw.cpp @@ -0,0 +1,109 @@ +#include "Local.h" + +#ifdef GUI_SDL20 + +NAMESPACE_UPP + +#define LLOG(x) // LOG(x) +#define LTIMING(x) // RTIMING(x) + +struct RectSDL { + SDL_Rect sr; + + operator SDL_Rect *() { return &sr; } + + RectSDL(const Rect& r) + { + sr.x = r.left; + sr.y = r.top; + sr.w = r.GetWidth(); + sr.h = r.GetHeight(); + } +}; + +SDL_Texture *TextureFromImage(SDL_Renderer *renderer, const Image& m) +{ + Size isz = m.GetSize(); + SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STATIC, isz.cx, isz.cy); + if(texture) { + SDL_UpdateTexture(texture, RectSDL(isz), ~m, isz.cx * sizeof(RGBA)); + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); + } + return texture; +} + +struct ImageSysData { + Image img; + SDL_Texture *texture; + + void Init(SDL_Renderer *renderer, const Image& img); + ~ImageSysData(); +}; + +void ImageSysData::Init(SDL_Renderer *renderer, const Image& m) +{ + img = m; + texture = TextureFromImage(renderer, img); + SysImageRealized(img); +} + +ImageSysData::~ImageSysData() +{ + SysImageReleased(img); + SDL_DestroyTexture(texture); +} + +struct ImageSysDataMaker : LRUCache::Maker { + Image img; + int64 wserial; + SDL_Renderer *renderer; + + virtual int64 Key() const { return img.GetSerialId(); } // TODO! add ren_serial + virtual int Make(ImageSysData& object) const { object.Init(renderer, img); return img.GetLength(); } +}; + +void SystemDraw::PutImage(Point p, const Image& img, const Rect& src) +{ + if(img.GetLength() == 0 || !win) + return; + LLOG("SysDrawImageOp " << img.GetSerialId() << ' ' << p.x << ", " << p.y << ", "<< img.GetSize()); + ImageSysDataMaker m; + static LRUCache cache; + LLOG("SysImage cache pixels " << cache.GetSize() << ", count " << cache.GetCount()); + m.img = img; + m.renderer = win->ren; + m.wserial = win->serial; + ImageSysData& sd = cache.Get(m); + { + RTIMING("SDL_RenderCopy"); + SDL_RenderCopy(win->ren, sd.texture, RectSDL(src), RectSDL(Rect(p, src.GetSize()))); + } + cache.Shrink(4 * 1024 * 768, 1000); // Cache shrink must be after Paint because of PaintOnly! +} + +void SystemDraw::PutRect(const Rect& r, Color color) +{ + if(win && !IsNull(color)) { + SDL_SetRenderDrawColor(win->ren, color.GetR(), color.GetG(), color.GetB(), 255); // Optimize? + SDL_RenderFillRect(win->ren, RectSDL(r)); + } +} + +void SystemDraw::Set(SDLWindow& win_) +{ + win = win_.ren ? &win_ : NULL; +} + +SystemDraw::SystemDraw() +{ + win = NULL; +} + +SystemDraw::~SystemDraw() +{ +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/SDL20GL/Event.cpp b/rainbow/SDL20GL/Event.cpp new file mode 100644 index 000000000..d2aaf625a --- /dev/null +++ b/rainbow/SDL20GL/Event.cpp @@ -0,0 +1,189 @@ +#include "Local.h" + +#ifdef GUI_SDL20 + +NAMESPACE_UPP + +#define LLOG(x) //DLOG(x) +#define LDUMP(x) //DDUMP(x) + +static Point fbmousepos; + +Point GetMousePos() { + return fbmousepos; +} + +void Ctrl::MouseEventFB(Ptr t, int event, Point p, int zdelta) +{ + if(!t->IsEnabled()) + return; + Rect rr = t->GetRect(); + if((event & Ctrl::ACTION) == DOWN) { + Ptr q = t; + TopWindowFrame *wf = dynamic_cast(~t); + if(wf) + q = wf->window; + if(q) q->ClickActivateWnd(); + if(q) q->SetForeground(); + if(ignoreclick) + return; + } + if(t) + t->DispatchMouse(event, p - rr.TopLeft(), zdelta); + if(t) + t->PostInput(); +} + +Ctrl *Ctrl::FindMouseTopCtrl() +{ + for(int i = topctrl.GetCount() - 1; i >= 0; i--) { + Ctrl *t = topctrl[i]; + if(t->GetRect().Contains(fbmousepos)) + return t->IsEnabled() ? t : NULL; + } + return desktop->IsEnabled() ? desktop : NULL; +} + +void Ctrl::DoMouseFB(int event, Point p, int zdelta) +{ + fbmousepos = p; + int a = event & Ctrl::ACTION; + if(a == Ctrl::UP && Ctrl::ignoreclick) { + EndIgnore(); + return; + } + else + if(a == Ctrl::DOWN && ignoreclick) + return; + LLOG("### Mouse event: " << event << " position " << p << " zdelta " << zdelta << ", capture " << Upp::Name(captureCtrl)); + if(captureCtrl) + MouseEventFB(captureCtrl->GetTopCtrl(), event, p, zdelta); + else + for(int i = topctrl.GetCount() - 1; i >= 0; i--) { + Ptr t = topctrl[i]; + Rect rr = t->GetRect(); + if(rr.Contains(p)) { + MouseEventFB(t, event, p, zdelta); + return; + } + } + Ctrl *desktop = GetDesktop(); + if(desktop) { + desktop->DispatchMouse(event, p, zdelta); + desktop->PostInput(); + } +} + +bool Ctrl::DoKeyFB(dword key, int cnt) +{ + bool b = DispatchKey(key, cnt); + SyncCaret(); + Ctrl *desktop = GetDesktop(); + if(desktop) + desktop->PostInput(); + return b; +} + +Image Ctrl::GetBak(Rect& tr) +{ + Image bak; + tr.Intersect(framebuffer.GetSize()); + if(!tr.IsEmpty()) { + Image h = framebuffer; + bak = CreateImage(tr.GetSize(), Black); + Copy(bak, Point(0, 0), h, tr); + framebuffer = h; + } + return bak; +} + +void Ctrl::RemoveCursor() +{ + if(!IsNull(fbCursorBakPos)) { + Copy(framebuffer, fbCursorBakPos, fbCursorBak, fbCursorBak.GetSize()); + AddUpdate(Rect(fbCursorBakPos, fbCursorBak.GetSize())); + } + fbCursorPos = fbCursorBakPos = Null; + fbCursorBak = Null; +} + +void Ctrl::RemoveCaret() +{ + if(!IsNull(fbCaretRect)) { + Copy(framebuffer, fbCaretRect.TopLeft(), fbCaretBak, fbCaretBak.GetSize()); + AddUpdate(fbCaretRect); + } + fbCaretRect = Null; + fbCaretBak = Null; +} + +void Ctrl::SetCaret(int x, int y, int cx, int cy) +{ + GuiLock __; + caretx = x; + carety = y; + caretcx = cx; + caretcy = cy; + fbCaretTm = GetTickCount(); + SyncCaret(); +} + +void Ctrl::SyncCaret() +{ + GuiLock __; +} + +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(); + LDUMP(GetTickCount()); + if(fbCursorPos != p || cr != fbCaretRect) { + LDUMP(fbCaretRect); + RemoveCursor(); + RemoveCaret(); + + fbCursorPos = p; + Size sz = fbCursorImage.GetSize(); + Rect tr(p, sz); + fbCursorBak = GetBak(tr); + fbCursorBakPos = tr.TopLeft(); + + fbCaretRect = cr; + if(!cr.IsEmpty()) { + fbCaretBak = GetBak(cr); + for(int y = cr.top; y < cr.bottom; y++) { + RGBA *s = framebuffer[y] + cr.left; + const RGBA *e = framebuffer[y] + cr.right; + while(s < e) { + s->r = ~s->r; + s->g = ~s->g; + s->b = ~s->b; + s++; + } + } + AddUpdate(fbCaretRect); + } + + Over(framebuffer, p, fbCursorImage, sz); + LLOG("Cursor: " << p << ", rect " << tr); + AddUpdate(tr); + } +} + +void Ctrl::SetMouseCursor(const Image& image) +{ + GuiLock __; + if(image.GetSerialId() != fbCursorImage.GetSerialId()) { + fbCursorImage = image; + fbCursorPos = Null; + } +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/SDL20GL/FB.iml b/rainbow/SDL20GL/FB.iml new file mode 100644 index 000000000..08f565033 --- /dev/null +++ b/rainbow/SDL20GL/FB.iml @@ -0,0 +1,59 @@ +PREMULTIPLIED +IMAGE_ID(arrow) +IMAGE_ID(ibeam) +IMAGE_ID(wait) +IMAGE_ID(no) +IMAGE_ID(sizeall) +IMAGE_ID(sizehorz) +IMAGE_ID(sizeright) +IMAGE_ID(sizeleft) +IMAGE_ID(sizevert) +IMAGE_ID(sizetopleft) +IMAGE_ID(sizetop) +IMAGE_ID(sizetopright) +IMAGE_ID(sizebottomleft) +IMAGE_ID(sizebottom) +IMAGE_ID(sizebottomright) +IMAGE_ID(overlap) +IMAGE_ID(maximize) +IMAGE_ID(close) +IMAGE_ID(bgtitle) +IMAGE_ID(title) +IMAGE_ID(border) +IMAGE_ID(hand) + +IMAGE_BEGIN_DATA +IMAGE_DATA(120,156,237,90,205,75,84,81,20,191,101,163,6,74,72,180,115,209,166,77,127,66,4,109,91,6,22,4,209,38,23,209) +IMAGE_DATA(162,93,45,162,204,9,34,130,8,13,178,36,44,45,11,212,172,197,108,68,84,212,133,31,8,126,224,7,12,162,8,34) +IMAGE_DATA(136,136,160,43,221,157,238,140,51,227,245,188,251,206,61,231,206,27,43,120,231,113,208,247,238,239,119,238,57,191,115,222) +IMAGE_DATA(123,227,135,170,82,23,84,198,202,213,169,204,23,80,50,3,33,7,0,68,28,56,56,184,8,251,251,151,184,28,216,219) +IMAGE_DATA(187,2,187,187,215,96,103,231,58,135,3,219,219,55,96,107,235,38,108,110,222,129,245,245,122,23,7,54,54,234,53,238) +IMAGE_DATA(62,172,173,61,132,213,213,71,144,78,63,165,56,176,178,242,24,150,151,159,104,92,35,44,46,190,130,249,249,183,48,59) +IMAGE_DATA(219,28,198,129,165,165,151,176,176,240,26,230,230,154,96,102,166,21,166,166,58,97,114,242,59,76,76,180,219,56,26,211) +IMAGE_DATA(12,211,211,239,53,174,13,198,199,187,97,100,100,36,231,191,96,120,184,19,115,116,172,86,141,107,131,177,177,78,24,29) +IMAGE_DATA(253,93,192,171,163,94,154,28,141,249,172,189,3,134,134,126,192,224,224,79,232,239,79,145,245,14,12,180,67,95,223,215) +IMAGE_DATA(66,156,84,170,155,196,167,82,95,2,57,118,117,125,11,213,199,166,65,71,199,39,10,111,221,183,165,229,157,104,14,155) +IMAGE_DATA(154,222,136,103,61,153,124,46,218,163,161,225,153,120,15,1,54,104,9,117,78,157,86,21,89,87,168,241,42,123,179,30) +IMAGE_DATA(26,250,190,176,57,58,255,239,175,133,212,27,208,69,85,105,225,18,90,180,196,113,225,184,158,229,212,246,124,32,221,192) +IMAGE_DATA(158,4,158,228,88,176,161,28,2,27,224,48,176,5,142,4,235,147,139,79,173,62,90,254,133,254,202,230,179,70,31,149) +IMAGE_DATA(185,131,18,206,226,92,227,222,36,28,126,49,235,146,60,139,229,7,26,200,136,97,127,250,248,243,195,242,146,242,185,49) +IMAGE_DATA(36,235,174,61,56,57,82,117,82,230,210,88,194,183,229,36,153,21,219,53,95,62,55,142,207,125,231,115,223,186,98,217) +IMAGE_DATA(141,249,64,58,140,26,124,189,139,204,124,253,23,195,207,187,52,14,230,251,196,1,195,208,169,51,6,198,217,244,160,98) +IMAGE_DATA(133,225,57,215,204,235,56,111,91,45,24,139,249,62,110,139,227,147,71,84,122,68,213,23,91,44,91,45,46,46,222,31) +IMAGE_DATA(187,36,134,45,142,148,143,227,248,242,81,28,218,106,244,199,254,74,85,150,117,76,118,5,160,48,220,34,194,112,212,208) +IMAGE_DATA(218,76,169,147,191,121,56,121,68,165,135,185,238,213,151,184,209,113,163,253,2,50,19,118,225,138,21,216,188,230,227,182) +IMAGE_DATA(56,62,121,68,165,135,185,238,213,151,10,221,234,178,92,171,45,27,178,19,193,194,186,4,183,9,132,206,157,133,255,235) +IMAGE_DATA(107,84,125,148,46,148,158,156,92,140,245,35,171,214,71,121,238,8,100,130,68,39,2,146,73,185,56,46,124,177,28,44) +IMAGE_DATA(182,139,131,155,197,221,47,108,239,98,121,146,62,72,106,53,121,170,132,189,240,157,17,235,44,198,79,166,210,173,81,245) +IMAGE_DATA(81,186,80,122,114,114,49,214,143,204,124,50,81,22,200,18,53,132,216,236,68,159,66,92,14,22,223,197,161,26,201,197) +IMAGE_DATA(227,117,28,75,146,3,7,111,114,212,9,235,207,205,77,58,83,241,192,198,3,91,18,14,55,55,241,192,198,175,210,210) +IMAGE_DATA(173,81,245,81,186,80,122,114,114,49,214,143,44,254,144,31,228,224,102,113,247,11,219,187,88,158,164,15,146,90,77,158) +IMAGE_DATA(42,97,47,124,103,196,58,139,85,250,136,200,172,119,154,225,54,60,21,203,23,207,201,3,227,93,123,70,133,231,232,83) +IMAGE_DATA(42,93,204,107,146,62,241,45,130,97,114,37,39,17,203,134,137,241,209,227,37,253,226,91,20,79,166,171,213,213,161,155) +IMAGE_DATA(227,181,204,121,222,109,88,219,154,237,58,21,7,175,187,176,97,28,10,43,197,75,242,145,212,235,171,39,149,39,85,7) +IMAGE_DATA(105,103,244,145,183,186,186,86,184,253,160,23,238,190,232,133,123,31,123,65,122,94,8,86,150,253,219,76,18,206,94,238) +IMAGE_DATA(129,243,183,150,160,182,49,243,18,22,158,103,198,60,161,143,220,207,178,220,251,233,216,155,223,101,230,255,83,231,207,41) +IMAGE_DATA(79,38,147,49,190,68,248,252,185,203,125,102,33,59,76,142,95,140,80,159,94,48,14,210,233,244,177,175,97,88,140,51) +IMAGE_DATA(240,214,79,32,97,120,180,79,33,6,23,239,194,217,240,121,151,226,195,28,213,44,197,59,57,148,166,76,44,11,255,7) +IMAGE_DATA(113,204,146,74,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) +IMAGE_END_DATA(1056, 22) diff --git a/rainbow/SDL20GL/Gui.h b/rainbow/SDL20GL/Gui.h new file mode 100644 index 000000000..925e1b3fd --- /dev/null +++ b/rainbow/SDL20GL/Gui.h @@ -0,0 +1,358 @@ +#define GUI_SDL20 + +NAMESPACE_UPP + +class SystemDraw : public Draw { +public: + virtual dword GetInfo() const; + virtual Size GetPageSize() const; + + virtual void BeginOp(); + virtual void EndOp(); + virtual void OffsetOp(Point p); + virtual bool ClipOp(const Rect& r); + virtual bool ClipoffOp(const Rect& r); + virtual bool ExcludeClipOp(const Rect& r); + virtual bool IntersectClipOp(const Rect& r); + virtual bool IsPaintingOp(const Rect& r) const; + virtual Rect GetPaintRect() const; + + virtual void DrawRectOp(int x, int y, int cx, int cy, Color color); + virtual void DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color); + virtual void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color); + + virtual void DrawPolyPolylineOp(const Point *vertices, int vertex_count, + const int *counts, int count_count, + int width, Color color, Color doxor); + virtual void DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count, + const int *subpolygon_counts, int scc, + const int *disjunct_polygon_counts, int dpcc, + Color color, int width, Color outline, + uint64 pattern, Color doxor); + virtual void DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color); + + virtual void DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor); + virtual void DrawTextOp(int x, int y, int angle, const wchar *text, Font font, + Color ink, int n, const int *dx); + + virtual Size GetNativeDpi() const; + virtual void BeginNative(); + virtual void EndNative(); + + virtual int GetCloffLevel() const; + +private: + Size pageSize; + Size nativeSize; + Size nativeDpi; + bool palette:1; + bool color16:1; + bool is_mono:1; + int native; + + friend class ImageDraw; + friend class FontInfo; + friend class Font; + + friend void StaticExitDraw_(); + + Point actual_offset_bak; + + struct Cloff : Moveable { + Point org; + HRGN hrgn; + Rect drawingclip; + }; + + Array cloff; + Rect drawingclip; + + COLORREF lastTextColor; + Color lastColor; + HBRUSH orgBrush; + HBRUSH actBrush; + HPEN orgPen; + HPEN actPen; + int lastPen; + Color lastPenColor; + + void Unselect0(); + void Cinit(); + + void LoadCaps(); + void SetPrinterMode(); + void Reset(); + void SetOrg(); + friend HPALETTE GetQlibPalette(); + void DotsMode(); + + static void InitColors(); + + friend class BackDraw; + friend class ScreenDraw; + friend class PrintDraw; + +protected: + dword style; + HDC handle; + Point actual_offset; + + SystemDraw(); + void Init(); + void InitClip(const Rect& clip); + +public: + static Rect GetVirtualScreenArea(); + + static void SetAutoPalette(bool ap); + static bool AutoPalette(); + bool PaletteMode() { return palette; } + + static void Flush() { GdiFlush(); } + + COLORREF GetColor(Color color) const; + + Point GetOffset() const { return actual_offset; } + +#ifndef PLATFORM_WINCE + Point LPtoDP(Point p) const; + Point DPtoLP(Point p) const; + Rect LPtoDP(const Rect& r) const; + Rect DPtoLP(const Rect& r) const; +#endif + + void SetColor(Color color); + void SetDrawPen(int width, Color color); + + Size GetSizeCaps(int i, int j) const; + HDC BeginGdi(); + void EndGdi(); + HDC GetHandle() { return handle; } + operator HDC() const { return handle; } + void Unselect(); + void Attach(HDC ahandle) { handle = ahandle; Init(); } + HDC Detach() { Unselect(); HDC h = handle; handle = NULL; return h; } + + SystemDraw(HDC hdc); + virtual ~SystemDraw(); + + bool CanSetSurface() { return IsGui() && IsWinNT(); } +}; + +#ifndef PLATFORM_WINCE +class WinMetaFile { + Size size; + HENHMETAFILE hemf; + + void Init(); + +public: + void Attach(HENHMETAFILE emf); + HENHMETAFILE Detach(); + + void Set(const void *data, dword len); + void Set(const String& data) { Set(~data, data.GetCount()); } + + String Get() const; + + operator bool() const { return hemf; } + void SetSize(const Size& sz) { size = sz; } + Size GetSize() const { return hemf ? size : Size(0, 0); } + + void Clear(); + + void Paint(Draw& w, const Rect& r) const; + void Paint(Draw& w, int x, int y, int cx, int cy) const; + + void Serialize(Stream& s); + + void ReadClipboard(); + void WriteClipboard() const; + void Load(const char *file) { Set(LoadFile(file)); } + + WinMetaFile() { Init(); } + WinMetaFile(HENHMETAFILE hemf); + WinMetaFile(HENHMETAFILE hemf, Size sz); + WinMetaFile(const char *file); + WinMetaFile(void *data, int len); + WinMetaFile(const String& data); + + ~WinMetaFile() { Clear(); } + + HENHMETAFILE GetHEMF() const { return hemf; } +}; + +class WinMetaFileDraw : public SystemDraw { + Size size; + +public: + bool Create(HDC hdc, int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL); + bool Create(int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL); + WinMetaFile Close(); + + WinMetaFileDraw() {} + WinMetaFileDraw(HDC hdc, int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL); + WinMetaFileDraw(int cx, int cy, const char *app = NULL, const char *name = NULL, const char *file = NULL); + ~WinMetaFileDraw(); +}; + +void DrawWMF(Draw& w, int x, int y, int cx, int cy, const String& wmf); +void DrawWMF(Draw& w, int x, int y, const String& wmf); +Drawing LoadWMF(const char *path, int cx, int cy); +Drawing LoadWMF(const char *path); + +String AsWMF(const Drawing& iw); + +#endif + +class ScreenDraw : public SystemDraw { +public: + ScreenDraw(bool ic = false); + ~ScreenDraw(); +}; + +#ifndef PLATFORM_WINCE +class PrintDraw : public SystemDraw { +public: + virtual void StartPage(); + virtual void EndPage(); + +private: + bool aborted; + + void InitPrinter(); +public: + PrintDraw(HDC hdc, const char *jobname); + ~PrintDraw(); +}; +#endif + +inline bool BitBlt(HDC ddc, Point d, HDC sdc, const Rect& s, dword rop = SRCCOPY) +{ return BitBlt(ddc, d.x, d.y, s.Width(), s.Height(), sdc, s.left, s.top, rop); } + +inline bool StretchBlt(HDC ddc, const Rect& r, HDC sdc, const Rect& s, dword rop = SRCCOPY) +{ return StretchBlt(ddc, r.left, r.top, r.Width(), r.Height(), sdc, s.left, s.top, s.Width(), s.Height(), rop); } + +inline bool PatBlt(HDC dc, const Rect& r, dword rop = PATCOPY) +{ return PatBlt(dc, r.left, r.top, r.Width(), r.Height(), rop); } + +inline void MoveTo(HDC hdc, Point pt) { MoveToEx(hdc, pt.x, pt.y, 0); } +inline void LineTo(HDC hdc, Point pt) { LineTo(hdc, pt.x, pt.y); } + +inline void DrawLine(HDC hdc, Point p, Point q) { MoveTo(hdc, p); LineTo(hdc, q); } +inline void DrawLine(HDC hdc, int px, int py, int qx, int qy) { MoveToEx(hdc, px, py, 0); LineTo(hdc, qx, qy); } + +#ifndef PLATFORM_WINCE +inline void DrawArc(HDC hdc, const Rect& rc, Point p, Point q){ Arc(hdc, rc.left, rc.top, rc.right, rc.bottom, p.x, p.y, q.x, q.y); } +#endif +inline void DrawCircle(HDC hdc, int x, int y, int radius) { Ellipse(hdc, x - radius, y - radius, x + radius + 1, y + radius + 1); } +inline void DrawCircle(HDC hdc, Point centre, int radius) { DrawCircle(hdc, centre.x, centre.y, radius); } +inline void DrawEllipse(HDC hdc, const Rect& rc) { Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom); } + +inline void DrawRect(HDC hdc, const Rect& rc) { Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom); } + +HDC ScreenHDC(); +HPALETTE GetQlibPalette(); + +Image Win32Icon(LPCSTR id, int iconsize = 0); +Image Win32Icon(int id, int iconsize = 0); +Image Win32Cursor(LPCSTR id); +Image Win32Cursor(int id); +HICON IconWin32(const Image& img, bool cursor = false); +Image Win32DllIcon(const char *dll, int ii, bool large); + +class BackDraw : public SystemDraw { +public: + virtual bool IsPaintingOp(const Rect& r) const; + +protected: + HBITMAP hbmpold; + HBITMAP hbmp; + + Size size; + Draw *painting; + Point painting_offset; + +public: + void Put(SystemDraw& w, int x, int y); + void Put(SystemDraw& w, Point p) { Put(w, p.x, p.y); } + + void Create(SystemDraw& w, int cx, int cy); + void Create(SystemDraw& w, Size sz) { Create(w, sz.cx, sz.cy); } + void Destroy(); + + void SetPaintingDraw(Draw& w, Point off) { painting = &w; painting_offset = off; } + + BackDraw(); + ~BackDraw(); +}; + +class ImageDraw : public SystemDraw { + Size size; + + struct Section { + HDC dc; + HBITMAP hbmp, hbmpOld; + RGBA *pixels; + + void Init(int cx, int cy); + ~Section(); + }; + + Section rgb; + Section a; + SystemDraw alpha; + + + bool has_alpha; + + void Init(); + Image Get(bool pm) const; + +public: + Draw& Alpha(); + + operator Image() const; + + Image GetStraight() const; + + ImageDraw(Size sz); + ImageDraw(int cx, int cy); + ~ImageDraw(); +}; + +END_UPP_NAMESPACE + +#define GUIPLATFORM_KEYCODES_INCLUDE "Win32Keys.h" + + +#define GUIPLATFORM_CTRL_TOP_DECLS \ + HWND hwnd; \ + UDropTarget *dndtgt; \ + + +#define GUIPLATFORM_CTRL_DECLS_INCLUDE "Win32Ctrl.h" + + +#define GUIPLATFORM_PASTECLIP_DECLS \ + UDropTarget *dt; \ + +#define GUIPLATFORM_TOPWINDOW_DECLS_INCLUDE "Win32Top.h" + +NAMESPACE_UPP + +inline unsigned GetHashValue(const HWND& hwnd) +{ + return (unsigned)(intptr_t)hwnd; +} +END_UPP_NAMESPACE + +#ifdef PLATFORM_WIN32 +#ifndef PLATFORM_WINCE + +#include + +#endif +#endif + +#define GUIPLATFORM_INCLUDE_AFTER "Win32GuiA.h" diff --git a/rainbow/SDL20GL/Image.cpp b/rainbow/SDL20GL/Image.cpp new file mode 100644 index 000000000..66c01b1a1 --- /dev/null +++ b/rainbow/SDL20GL/Image.cpp @@ -0,0 +1,44 @@ +#include + +#ifdef GUI_SDL20 + +NAMESPACE_UPP + +#define LTIMING(x) // RTIMING(x) + +void SetSurface(SystemDraw& w, int x, int y, int cx, int cy, const RGBA *pixels) +{ + GuiLock __; + // Empty as CanSetSurface is false +} + +void SetSurface(SystemDraw& w, const Rect& dest, const RGBA *pixels, Size psz, Point poff) +{ + GuiLock __; + // Empty as CanSetSurface is false +} + +#define IMAGECLASS FBImg +#define IMAGEFILE +#include + +Image Image::Arrow() { return FBImg::arrow(); } +Image Image::Wait() { return FBImg::wait(); } +Image Image::IBeam() { return FBImg::ibeam(); } +Image Image::No() { return FBImg::no(); } +Image Image::SizeAll() { return FBImg::sizeall(); } +Image Image::SizeHorz() { return FBImg::sizehorz(); } +Image Image::SizeVert() { return FBImg::sizevert(); } +Image Image::SizeTopLeft() { return FBImg::sizetopleft(); } +Image Image::SizeTop() { return FBImg::sizetop(); } +Image Image::SizeTopRight() { return FBImg::sizetopright(); } +Image Image::SizeLeft() { return FBImg::sizeleft(); } +Image Image::SizeRight() { return FBImg::sizeright(); } +Image Image::SizeBottomLeft() { return FBImg::sizebottomleft(); } +Image Image::SizeBottom() { return FBImg::sizebottom(); } +Image Image::SizeBottomRight() { return FBImg::sizebottomright(); } +Image Image::Hand() { return FBImg::hand(); } + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/SDL20GL/Keys.h b/rainbow/SDL20GL/Keys.h new file mode 100644 index 000000000..893da7085 --- /dev/null +++ b/rainbow/SDL20GL/Keys.h @@ -0,0 +1,110 @@ +K_BACK = SDLK_BACKSPACE + K_DELTA, +K_BACKSPACE = SDLK_BACKSPACE + K_DELTA, + +//handled extra in fbKEYtoK +K_TAB = 9, //SDLK_TAB, + +K_SPACE = 32, //SDLK_SPACE, + +K_RETURN = 13, //SDLK_RETURN, +K_ENTER = K_RETURN, + +K_SHIFT_KEY = SDLK_LSHIFT + K_DELTA, +K_CTRL_KEY = SDLK_LCTRL + K_DELTA, +K_ALT_KEY = SDLK_LALT + K_DELTA, +K_CAPSLOCK = SDLK_CAPSLOCK + K_DELTA, +K_ESCAPE = SDLK_ESCAPE + K_DELTA, +K_PRIOR = SDLK_PAGEUP + K_DELTA, +K_PAGEUP = SDLK_PAGEUP + K_DELTA, +K_NEXT = SDLK_PAGEDOWN + K_DELTA, +K_PAGEDOWN = SDLK_PAGEDOWN + K_DELTA, +K_END = SDLK_END + K_DELTA, +K_HOME = SDLK_HOME + K_DELTA, +K_LEFT = SDLK_LEFT + K_DELTA, +K_UP = SDLK_UP + K_DELTA, +K_RIGHT = SDLK_RIGHT + K_DELTA, +K_DOWN = SDLK_DOWN + K_DELTA, +K_INSERT = SDLK_INSERT + K_DELTA, +K_DELETE = SDLK_DELETE + K_DELTA, + +K_NUMPAD0 = SDLK_KP_0 + K_DELTA, +K_NUMPAD1 = SDLK_KP_1 + K_DELTA, +K_NUMPAD2 = SDLK_KP_2 + K_DELTA, +K_NUMPAD3 = SDLK_KP_3 + K_DELTA, +K_NUMPAD4 = SDLK_KP_4 + K_DELTA, +K_NUMPAD5 = SDLK_KP_5 + K_DELTA, +K_NUMPAD6 = SDLK_KP_6 + K_DELTA, +K_NUMPAD7 = SDLK_KP_7 + K_DELTA, +K_NUMPAD8 = SDLK_KP_8 + K_DELTA, +K_NUMPAD9 = SDLK_KP_9 + K_DELTA, +K_MULTIPLY = SDLK_KP_MULTIPLY + K_DELTA, +K_ADD = SDLK_KP_PLUS + K_DELTA, +K_SEPARATOR = SDLK_KP_PERIOD + K_DELTA, +K_SUBTRACT = SDLK_KP_MINUS + K_DELTA, +K_DECIMAL = SDLK_KP_PERIOD + K_DELTA, +K_DIVIDE = SDLK_KP_DIVIDE + K_DELTA, +K_SCROLL = SDLK_SCROLLLOCK + K_DELTA, + +K_F1 = SDLK_F1 + K_DELTA, +K_F2 = SDLK_F2 + K_DELTA, +K_F3 = SDLK_F3 + K_DELTA, +K_F4 = SDLK_F4 + K_DELTA, +K_F5 = SDLK_F5 + K_DELTA, +K_F6 = SDLK_F6 + K_DELTA, +K_F7 = SDLK_F7 + K_DELTA, +K_F8 = SDLK_F8 + K_DELTA, +K_F9 = SDLK_F9 + K_DELTA, +K_F10 = SDLK_F10 + K_DELTA, +K_F11 = SDLK_F11 + K_DELTA, +K_F12 = SDLK_F12 + K_DELTA, + +K_A = SDLK_a + K_DELTA, +K_B = SDLK_b + K_DELTA, +K_C = SDLK_c + K_DELTA, +K_D = SDLK_d + K_DELTA, +K_E = SDLK_e + K_DELTA, +K_F = SDLK_f + K_DELTA, +K_G = SDLK_g + K_DELTA, +K_H = SDLK_h + K_DELTA, +K_I = SDLK_i + K_DELTA, +K_J = SDLK_j + K_DELTA, +K_K = SDLK_k + K_DELTA, +K_L = SDLK_l + K_DELTA, +K_M = SDLK_m + K_DELTA, +K_N = SDLK_n + K_DELTA, +K_O = SDLK_o + K_DELTA, +K_P = SDLK_p + K_DELTA, +K_Q = SDLK_q + K_DELTA, +K_R = SDLK_r + K_DELTA, +K_S = SDLK_s + K_DELTA, +K_T = SDLK_t + K_DELTA, +K_U = SDLK_u + K_DELTA, +K_V = SDLK_v + K_DELTA, +K_W = SDLK_w + K_DELTA, +K_X = SDLK_x + K_DELTA, +K_Y = SDLK_y + K_DELTA, +K_Z = SDLK_z + K_DELTA, +K_0 = SDLK_0 + K_DELTA, +K_1 = SDLK_1 + K_DELTA, +K_2 = SDLK_2 + K_DELTA, +K_3 = SDLK_3 + K_DELTA, +K_4 = SDLK_4 + K_DELTA, +K_5 = SDLK_5 + K_DELTA, +K_6 = SDLK_6 + K_DELTA, +K_7 = SDLK_7 + K_DELTA, +K_8 = SDLK_8 + K_DELTA, +K_9 = SDLK_9 + K_DELTA, + +K_CTRL_LBRACKET = K_CTRL|219|K_DELTA, +K_CTRL_RBRACKET = K_CTRL|221|K_DELTA, +K_CTRL_MINUS = K_CTRL|0xbd|K_DELTA, +K_CTRL_GRAVE = K_CTRL|0xc0|K_DELTA, +K_CTRL_SLASH = K_CTRL|0xbf|K_DELTA, +K_CTRL_BACKSLASH = K_CTRL|0xdc|K_DELTA, +K_CTRL_COMMA = K_CTRL|0xbc|K_DELTA, +K_CTRL_PERIOD = K_CTRL|0xbe|K_DELTA, +K_CTRL_SEMICOLON = K_CTRL|0xbe|K_DELTA, +K_CTRL_EQUAL = K_CTRL|0xbb|K_DELTA, +K_CTRL_APOSTROPHE= K_CTRL|0xde|K_DELTA, + +K_BREAK = SDLK_PAUSE + K_DELTA, // Is it really? diff --git a/rainbow/SDL20GL/Local.h b/rainbow/SDL20GL/Local.h new file mode 100644 index 000000000..ad85d7871 --- /dev/null +++ b/rainbow/SDL20GL/Local.h @@ -0,0 +1,69 @@ +#include + +#ifdef GUI_SDL20 + +NAMESPACE_UPP + +class TopWindowFrame : public Ctrl { +public: + virtual void Layout(); + virtual void Paint(Draw& w); + virtual Image CursorImage(Point p, dword keyflags); + virtual void LeftDown(Point p, dword keyflags); + virtual void LeftHold(Point p, dword keyflags); + virtual void LeftDouble(Point p, dword keyflags); + virtual void MouseMove(Point p, dword keyflags); + virtual void CancelMode(); + virtual void LeftUp(Point p, dword keyflags); + +private: + Point dir; + Point startpos; + Rect startrect; + + bool maximized; + Rect overlapped; + + bool holding; + TimeCallback hold; + + Point GetDragMode(Point p); + Image GetDragImage(Point dragmode); + void StartDrag(); + Rect Margins() const; + Rect ComputeClient(Rect r); + void Hold(); + + typedef TopWindowFrame CLASSNAME; + +public: + String title; + Button close, maximize; + Image icon; + Size minsize; + bool sizeable; + TopWindow *window; + + void SetTitle(const String& s) { title = s; Refresh(); } + Rect GetClient() const; + void SetClient(Rect r); + void GripResize(); + + void Maximize(); + void Overlap(); + void ToggleMaximize(); + bool IsMaximized() const { return maximized; } + void SyncRect(); + + TopWindowFrame(); +}; + +void HandleSDLEvent(SDL_Event* event); +void HandleUserEvent(SDL_Event* event); + +extern Size screen_size; +extern SDLWindow screen; + +END_UPP_NAMESPACE + +#endif \ No newline at end of file diff --git a/rainbow/SDL20GL/SDL.cpp b/rainbow/SDL20GL/SDL.cpp new file mode 100644 index 000000000..fe1519131 --- /dev/null +++ b/rainbow/SDL20GL/SDL.cpp @@ -0,0 +1,162 @@ +#include "Local.h" + +#ifdef GUI_SDL20 + +NAMESPACE_UPP + +#define LLOG(x) //LOG(x) + +Size screen_size; +SDLWindow screen; + +SDL_TimerID waketimer_id = 0; +Uint32 WakeCb(Uint32 interval, void *param) +{ + //wake up message que, FIXME maybe it can be done better? + SDL_Event event; + event.type=SDL_USEREVENT; + SDL_PushEvent(&event); + return 0; +} +void ScheduleWakup() +{ + waketimer_id = SDL_AddTimer(20, WakeCb, NULL); +} + +void FBQuitSession() +{ + SDL_Event event; + event.type=SDL_QUIT; + SDL_PushEvent(&event); +} + +bool FBIsWaitingEvent() +{ + SDL_PumpEvents(); + SDL_Event events; + int tc = SDL_PeepEvents(&events, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT); + return (tc>0); +} + +bool FBProcessEvent(bool *quit) +{ + DLOG("FBProcessEvent"); + SDL_Event event; + if(SDL_PollEvent(&event)) { + if(event.type == SDL_QUIT && quit) + *quit = true; + HandleSDLEvent(&event); + return true; + } + return false; +} + +void FBSleep(int ms) +{ + DLOG("FBSleep " << ms); + SDL_Delay(ms); //sleep should be wakeable with input + //ProcessEvents needs to process sth from queue each now and then. + //if no input is generated, no TimerProc call is performed, because queue ws empty. + //win32 backend has WM_TIMER message, that gets posted automatically into queue each 10ms. + //we dont have means to define a 'background' timer in an efficient way + //which could wakeup queue with smaller intervall (10ms) than sleep (20ms). + //we could go long way with a rescheduled timer (expensive) + //or the short way, keeping queue busy after each sleep + WakeCb(0,0); +} + +void FBInitUpdate() +{ + DLOG("FBInitUpdate"); +// TODO +// if(SDL_MUSTLOCK(screen)) +// SDL_LockSurface(screen); +} + +void FBUpdate(const Rect& inv) +{ + DLOG("FBUpdate"); +// TODO +#if 0 + //The invalidated areas accumulate in the update region until the region is processed when the next WM_PAINT message occurs + const ImageBuffer& framebuffer = Ctrl::GetFrameBuffer(); + +#if 1 + memcpy(screen->pixels, ~framebuffer, framebuffer.GetLength() * sizeof(RGBA)); +#endif + +#if 0 + ASSERT(Size(screen->w,screen->h) == framebuffer.GetSize()); + + Size ssz = inv.GetSize(); + Size dsz = framebuffer.GetSize(); + + ASSERT(Rect(dsz).Contains(inv)); + + for(int i = inv.top; i < inv.bottom; i++) + { + uint32 o = i * dsz.cx + inv.left; + memcpy(((RGBA*)screen->pixels) + o, (~framebuffer) + o, ssz.cx * sizeof(RGBA)); + } +#endif +#endif +} + +void FBFlush() +{ +} + +void FBInit() +{ + GuiLock __; + + SDL_Init(SDL_INIT_EVERYTHING); + + Ctrl::InitFB(); + +#if 0 + if(SDL_Init(SDL_INIT_VIDEO/* | SDL_INIT_TIMER*/) < 0) //timer not needed, we post to queue directly + { + Cout() << Format("Couldn't initialize SDL: %s\n", SDL_GetError()); + return; + } +#endif + +// TODO +// SDL_EnableUNICODE(1); //for unicode keycode availability +// SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL/2); +// SDL_ShowCursor(0); + +#if 0 + const SDL_VideoInfo* vi = SDL_GetVideoInfo(); + //ASSERT(vi->hw_available); + + width = vi->current_w; + height = vi->current_h; + bpp = vi->vfmt->BitsPerPixel; + ASSERT(bpp == 32); + + //FIXME adjustable + videoflags = SDL_HWSURFACE | SDL_HWACCEL | SDL_DOUBLEBUF | SDL_RESIZABLE;// | SDL_NOFRAME | SDL_FULLSCREEN; +#endif + + screen_size = Size(1024, 768); + screen.Create(screen_size, "First test"); + + Ctrl::SetFramebufferSize(screen_size); + + DLOG("INIT!"); +} + +void FBDeInit() +{ + SDL_RemoveTimer(waketimer_id); + Ctrl::ExitFB(); + screen.Destroy(); + SDL_Quit(); + DLOG("EXIT!"); +} + +END_UPP_NAMESPACE + +#endif \ No newline at end of file diff --git a/rainbow/SDL20GL/SDL20.h b/rainbow/SDL20GL/SDL20.h new file mode 100644 index 000000000..7d264c78d --- /dev/null +++ b/rainbow/SDL20GL/SDL20.h @@ -0,0 +1,135 @@ +#define GUI_SDL20 + +#include + +#include + +#ifdef PLATFORM_POSIX +#include +#endif + +NAMESPACE_UPP + +#define IMAGECLASS FBImg +#define IMAGEFILE +#include + +struct SDLWindow { + SDL_Window *win; + SDL_GLContext glcontext; + int64 serial; + + bool Create(const Rect& rect, const char *title); + void Destroy(); + + void Present(); + + operator bool() const { return win; } + + SDLWindow(); + ~SDLWindow(); +}; + +class SystemDraw : public SDraw { +public: + SDLWindow *win; + + virtual void PutImage(Point p, const Image& m, const Rect& src); + virtual void PutRect(const Rect& r, Color color); + + void Set(SDLWindow& win_); + + bool CanSetSurface() { return false; } + + static void Flush() {} + + SystemDraw(); + ~SystemDraw(); +}; + +struct BackDraw__ : public SystemDraw { + BackDraw__() : SystemDraw() {} +}; + +class BackDraw : public BackDraw__ { // Dummy only, as we are running in GlobalBackBuffer mode + Size size; + Draw *painting; + Point painting_offset; + ImageBuffer ib; + +public: + virtual bool IsPaintingOp(const Rect& r) const; + +public: + void Put(SystemDraw& w, int x, int y) {} + void Put(SystemDraw& w, Point p) { Put(w, p.x, p.y); } + + void Create(SystemDraw& w, int cx, int cy) {} + void Create(SystemDraw& w, Size sz) { Create(w, sz.cx, sz.cy); } + void Destroy() {} + + void SetPaintingDraw(Draw& w, Point off) { painting = &w; painting_offset = off; } + + BackDraw(); + ~BackDraw(); +}; + +class ImageDraw : public SImageDraw { +public: + ImageDraw(Size sz) : SImageDraw(sz) {} + ImageDraw(int cx, int cy) : SImageDraw(cx, cy) {} +}; + +void DrawDragRect(SystemDraw& w, const Rect& rect1, const Rect& rect2, const Rect& clip, int n, + Color color, uint64 pattern); + +class TopWindowFrame; + +#define GUIPLATFORM_CTRL_TOP_DECLS Ctrl *owner_window; + +#define GUIPLATFORM_CTRL_DECLS_INCLUDE + +#define GUIPLATFORM_PASTECLIP_DECLS \ + bool dnd; \ + friend struct DnDLoop; \ + +#define GUIPLATFORM_TOPWINDOW_DECLS_INCLUDE + +// to be implemented by final FB { + +bool FBIsWaitingEvent(); +bool FBProcessEvent(bool *quit); +void FBSleep(int ms); +void FBInitUpdate(); +void FBUpdate(const Rect& area); +void FBFlush(); +void FBQuitSession(); + +// } + +class PrinterJob { // Dummy only... + NilDraw nil; + Vector pages; + +public: + Draw& GetDraw() { return nil; } + operator Draw&() { return GetDraw(); } + const Vector& GetPages() const { return pages; } + int operator[](int i) const { return 0; } + int GetPageCount() const { return 0; } + + bool Execute() { return false; } + + PrinterJob& Landscape(bool b = true) { return *this; } + PrinterJob& MinMaxPage(int minpage, int maxpage) { return *this; } + PrinterJob& PageCount(int n) { return *this; } + PrinterJob& CurrentPage(int currentpage) { return *this; } + PrinterJob& Name(const char *_name) { return *this; } + + PrinterJob(const char *name = NULL) {} + ~PrinterJob() {} +}; + +END_UPP_NAMESPACE + +#define GUIPLATFORM_INCLUDE_AFTER diff --git a/rainbow/SDL20GL/SDL20GL.upp b/rainbow/SDL20GL/SDL20GL.upp new file mode 100644 index 000000000..b025f7019 --- /dev/null +++ b/rainbow/SDL20GL/SDL20GL.upp @@ -0,0 +1,32 @@ +description "SDL20 U++ backend\377"; + +uses + Painter, + CtrlLib, + GLDraw; + +library(POSIX) "SDL2 SDL2main"; + +file + SDL20.h, + Keys.h, + After.h, + Local.h, + Window.cpp, + Draw.cpp, + Image.cpp, + Util.cpp, + FB.iml, + Ctrl.h, + Ctrl.cpp, + Wnd.cpp, + Event.cpp, + Top.h, + TopFrame.cpp, + Top.cpp, + Clip.cpp, + DnD.cpp, + ChSysInit.cpp, + SDL.cpp, + SDLProc.cpp; + diff --git a/rainbow/SDL20GL/SDLProc.cpp b/rainbow/SDL20GL/SDLProc.cpp new file mode 100644 index 000000000..798e60686 --- /dev/null +++ b/rainbow/SDL20GL/SDLProc.cpp @@ -0,0 +1,208 @@ +#include "Local.h" + +#ifdef GUI_SDL20 + +NAMESPACE_UPP + +#define LLOG(x) //LOG(x) + +dword mouseb = 0; +dword modkeys = 0; + +enum KM { + KM_NONE = 0x00, + + KM_LSHIFT= 0x01, + KM_RSHIFT= 0x02, + KM_LCTRL = 0x04, + KM_RCTRL = 0x08, + KM_LALT = 0x10, + KM_RALT = 0x20, + + KM_CAPS = 0x40, + KM_NUM = 0x80, + + KM_CTRL = KM_LCTRL | KM_RCTRL, + KM_SHIFT = KM_LSHIFT | KM_RSHIFT, + KM_ALT = KM_LALT | KM_RALT, +}; + +bool GetMouseLeft() { return mouseb & (1<<0); } +bool GetMouseRight() { return mouseb & (1<<1); } +bool GetMouseMiddle() { return mouseb & (1<<2); } +bool GetShift() { return modkeys & KM_SHIFT; } +bool GetCtrl() { return modkeys & KM_CTRL; } +bool GetAlt() { return modkeys & KM_ALT; } +bool GetCapsLock() { return modkeys & KM_CAPS; } + +dword fbKEYtoK(dword chr) { + if(chr == SDLK_TAB) + chr = K_TAB; + else + if(chr == SDLK_SPACE) + chr = K_SPACE; + else + if(chr == SDLK_RETURN) + chr = K_RETURN; + else + chr = chr + K_DELTA; + if(chr == K_ALT_KEY || chr == K_CTRL_KEY || chr == K_SHIFT_KEY) + return chr; + if(GetCtrl()) chr |= K_CTRL; + if(GetAlt()) chr |= K_ALT; + if(GetShift()) chr |= K_SHIFT; + return chr; +} + +dword lastbdowntime[8] = {0}; +dword isdblclick[8] = {0}; +void HandleSDLEvent(SDL_Event* event) +{ + DLOG("HandleSDLEvent " << event->type); + switch(event->type) { +// case SDL_ACTIVEEVENT: //SDL_ActiveEvent +// break; + case SDL_KEYDOWN: + case SDL_KEYUP: //SDL_KeyboardEvent + { +// bool b = false; + dword keycode = 0; + if(event->type == SDL_KEYDOWN) { + switch(event->key.keysym.sym) + { + case SDLK_LSHIFT: modkeys |= KM_LSHIFT; break; + case SDLK_RSHIFT: modkeys |= KM_RSHIFT; break; + case SDLK_LCTRL: modkeys |= KM_LCTRL; break; + case SDLK_RCTRL: modkeys |= KM_RCTRL; break; + case SDLK_LALT: modkeys |= KM_LALT; break; + case SDLK_RALT: modkeys |= KM_RALT; break; + default:; + } + + keycode = fbKEYtoK((dword)event->key.keysym.sym); + if(keycode != K_SPACE) //dont send space on keydown + /*b = */Ctrl::DoKeyFB(keycode, 1); + + //send respective keyup things as char events as well + keycode = (dword)event->key.keysym.unicode; + if((keycode != 127 && keycode >= 32 && keycode < 255)) + /*b = */Ctrl::DoKeyFB(keycode, 1); + } + else + if(event->type == SDL_KEYUP) + { + switch(event->key.keysym.sym) + { + case SDLK_LSHIFT: modkeys &= ~KM_LSHIFT; break; + case SDLK_RSHIFT: modkeys &= ~KM_RSHIFT; break; + case SDLK_LCTRL: modkeys &= ~KM_LCTRL; break; + case SDLK_RCTRL: modkeys &= ~KM_RCTRL; break; + case SDLK_LALT: modkeys &= ~KM_LALT; break; + case SDLK_RALT: modkeys &= ~KM_RALT; break; + default:; + } + + keycode = fbKEYtoK((dword)event->key.keysym.sym) | K_KEYUP; + /*b = */Ctrl::DoKeyFB(keycode, 1); + } + } + break; + case SDL_MOUSEMOTION: //SDL_MouseMotionEvent + Ctrl::DoMouseFB(Ctrl::MOUSEMOVE, Point(event->motion.x, event->motion.y)); + break; + case SDL_MOUSEWHEEL: Ctrl::DoMouseFB(Ctrl::MOUSEWHEEL, GetMousePos(), sgn(event->wheel.y) * 120); break; + case SDL_MOUSEBUTTONDOWN: //SDL_MouseButtonEvent, FIXME DoubleClick + { + Point p(event->button.x, event->button.y); + int bi = event->button.button; + dword ct = SDL_GetTicks(); + if(isdblclick[bi] && (abs(int(ct) - int(lastbdowntime[bi])) < 400)) + { + switch(bi) + { + case SDL_BUTTON_LEFT: Ctrl::DoMouseFB(Ctrl::LEFTDOUBLE, p); break; + case SDL_BUTTON_RIGHT: Ctrl::DoMouseFB(Ctrl::RIGHTDOUBLE, p); break; + case SDL_BUTTON_MIDDLE: Ctrl::DoMouseFB(Ctrl::MIDDLEDOUBLE, p); break; + } + isdblclick[bi] = 0; //reset, to go ahead sending repeats + } + else + { + lastbdowntime[bi] = ct; + isdblclick[bi] = 0; //prepare for repeat + switch(bi) + { + case SDL_BUTTON_LEFT: mouseb |= (1<<0); Ctrl::DoMouseFB(Ctrl::LEFTDOWN, p); break; + case SDL_BUTTON_RIGHT: mouseb |= (1<<1); Ctrl::DoMouseFB(Ctrl::RIGHTDOWN, p); break; + case SDL_BUTTON_MIDDLE: mouseb |= (1<<2); Ctrl::DoMouseFB(Ctrl::MIDDLEDOWN, p); break; + } + } + } + break; + case SDL_MOUSEBUTTONUP: + { + int bi = event->button.button; + isdblclick[bi] = 1; //indicate maybe a dblclick + + Point p(event->button.x, event->button.y); + switch(bi) + { + case SDL_BUTTON_LEFT: mouseb &= ~(1<<0); Ctrl::DoMouseFB(Ctrl::LEFTUP, p); break; + case SDL_BUTTON_RIGHT: mouseb &= ~(1<<1); Ctrl::DoMouseFB(Ctrl::RIGHTUP, p); break; + case SDL_BUTTON_MIDDLE: mouseb &= ~(1<<2); Ctrl::DoMouseFB(Ctrl::MIDDLEUP, p); break; + } + } + break; + case SDL_JOYAXISMOTION: //SDL_JoyAxisEvent + break; + case SDL_JOYBALLMOTION: //SDL_JoyBallEvent + break; + case SDL_JOYHATMOTION: //SDL_JoyHatEvent + break; + case SDL_JOYBUTTONDOWN: + case SDL_JOYBUTTONUP: //SDL_JoyButtonEvent + break; +/* case SDL_VIDEORESIZE: //SDL_ResizeEvent + { + width = event->resize.w; + height = event->resize.h; + + SDL_FreeSurface(screen); + screen = CreateScreen(width, height, bpp, videoflags); + ASSERT(screen); + Ctrl::SetFramebufferSize(Size(width, height)); + } + break; + case SDL_VIDEOEXPOSE: //SDL_ExposeEvent + break; +*/ case SDL_QUIT: //SDL_QuitEvent + Ctrl::EndSession(); + break; + case SDL_USEREVENT: //SDL_UserEvent + HandleUserEvent(event); + break; + case SDL_SYSWMEVENT: //SDL_SysWMEvent + break; + + default: + break; + } // End switch +} + +void HandleUserEvent(SDL_Event* event) +{ +/* + switch (event->user.code) { + case RUN_GAME_LOOP: + GameLoop(); + break; + + default: + break; + } +*/ +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/SDL20GL/Top.cpp b/rainbow/SDL20GL/Top.cpp new file mode 100644 index 000000000..992e009d7 --- /dev/null +++ b/rainbow/SDL20GL/Top.cpp @@ -0,0 +1,150 @@ +#include "Local.h" + +#ifdef GUI_SDL20 + +NAMESPACE_UPP + +#define LLOG(x) // LOG(x) + +void TopWindow::SyncFrameRect(const Rect& r) +{ + frame->SetClient(r); +} + +void TopWindow::DestroyFrame() +{ + if(frame->IsOpen()) + frame->DestroyWnd(); +} + +void TopWindow::GripResize() +{ + frame->GripResize(); +} + +void TopWindow::SyncSizeHints() +{ + SyncCaption(); +} + +void TopWindow::SyncTitle() +{ + SyncCaption(); +} + +void TopWindow::SyncCaption() +{ + GuiLock __; + frame->title = title.ToString(); + frame->minsize = minsize; + frame->close.Show(!noclosebox); + frame->maximize.Show(maximizebox); + frame->sizeable = sizeable; + frame->RefreshLayout(); + frame->Refresh(); + frame->close <<= Proxy(WhenClose); + frame->icon = icon; + frame->Enable(IsEnabled()); +} + +void TopWindow::State(int reason) +{ + SyncCaption(); +} + +void TopWindow::SyncRect() +{ + frame->SyncRect(); + Rect r = frame->GetClient(); + if(r != GetRect()) { + SetRect(r); + } +} + +void TopWindow::Open(Ctrl *owner) +{ + GuiLock __; + LLOG("Open " << Upp::Name(owner)); + Rect r = GetRect(); + if(r.IsEmpty()) + SetRect(GetDefaultWindowRect()); + else + if(r.left == 0 && r.top == 0) + if(owner && center == 1) + SetRect(owner->GetRect().CenterRect(r.GetSize())); + else + if(center) + SetRect(GetWorkArea().CenterRect(r.GetSize())); + frame->SetClient(GetRect()); + frame->window = this; + frame->PopUp(owner, false, true); + PopUp(frame, false, true); + popup = false; + SetRect(frame->GetClient()); + SyncCaption(); + if(state == MAXIMIZED) + frame->Maximize(); +} + +void TopWindow::Open() +{ + Open(GetActiveCtrl()); +} + +void TopWindow::OpenMain() +{ + Open(NULL); +} + +void TopWindow::Minimize(bool effect) +{ +// state = MINIMIZED; +} + +TopWindow& TopWindow::FullScreen(bool b) +{ + return *this; +} + +void TopWindow::Maximize(bool effect) +{ + state = MAXIMIZED; + frame->Maximize(); +} + +void TopWindow::Overlap(bool effect) +{ + GuiLock __; + state = OVERLAPPED; + frame->Overlap(); +} + +TopWindow& TopWindow::TopMost(bool b, bool stay_top) +{ + GuiLock __; + return *this; +} + +bool TopWindow::IsTopMost() const +{ + return true; +} + +void TopWindow::GuiPlatformConstruct() +{ + frame = new TopWindowFrame; +} + +void TopWindow::GuiPlatformDestruct() +{ + delete frame; +} + +void TopWindow::SerializePlacement(Stream& s, bool reminimize) +{ + GuiLock __; +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/SDL20GL/Top.h b/rainbow/SDL20GL/Top.h new file mode 100644 index 000000000..2e9b12c16 --- /dev/null +++ b/rainbow/SDL20GL/Top.h @@ -0,0 +1,16 @@ +//$ class TopWindow { +public: + virtual void State(int reason); + +private: + TopWindowFrame *frame; + + void SyncRect(); + void SyncFrameRect(const Rect& r); + void DestroyFrame(); + + friend class Ctrl; + +public: + void GripResize(); +//$ }; diff --git a/rainbow/SDL20GL/TopFrame.cpp b/rainbow/SDL20GL/TopFrame.cpp new file mode 100644 index 000000000..12f5c34c9 --- /dev/null +++ b/rainbow/SDL20GL/TopFrame.cpp @@ -0,0 +1,259 @@ +#include "Local.h" + +#ifdef GUI_SDL20 + +NAMESPACE_UPP + +#define LLOG(x) // LOG(x) +#define LDUMP(x) //DDUMP(x) + +TopWindowFrame::TopWindowFrame() +{ + close.SetImage(FBImg::close()); + close.EdgeStyle(); + Add(close); + maximize.SetImage(FBImg::maximize()); + maximize.EdgeStyle(); + Add(maximize); + maximize <<= THISBACK(ToggleMaximize); + maximized = false; + sizeable = false; + holding = false; +} + +void TopWindowFrame::SyncRect() +{ + if(maximized) { + Size sz = framebuffer.GetSize(); + if(GetRect().GetSize() != sz) + SetRect(sz); + } +} + +void TopWindowFrame::Maximize() +{ + if(!maximized && maximize.IsShown()) { + maximized = true; + overlapped = GetRect(); + SetRect(framebuffer.GetSize()); + maximize.SetImage(FBImg::overlap()); + } +} + +void TopWindowFrame::Overlap() +{ + if(maximized && maximize.IsShown()) { + maximized = false; + SetRect(overlapped); + maximize.SetImage(FBImg::maximize()); + } +} + +void TopWindowFrame::ToggleMaximize() +{ + if(maximized) + Overlap(); + else + Maximize(); +} + +Rect TopWindowFrame::Margins() const +{ + return maximized ? Rect(0, 0, 0, 0) : ChMargins(FBImg::border()); +} + +void TopWindowFrame::Paint(Draw& w) +{ + Size sz = GetSize(); + Rect m = Margins(); + int c = GetStdFontCy() + 4; + ChPaintEdge(w, sz, FBImg::border()); + ChPaint(w, m.left, m.top, sz.cx - m.left - m.right, GetStdFontCy() + 4, + window->IsForeground() ? FBImg::title() : FBImg::bgtitle()); + int tx = m.left + 2; + int tcx = sz.cx - m.left - m.right - 4 - c * (close.IsShown() + maximize.IsShown()); + if(!IsNull(icon)) { + Image h = icon; + if(h.GetWidth() > c || h.GetHeight() > c) + h = Rescale(h, GetFitSize(h.GetSize(), Size(c))); + w.DrawImage(tx, m.top + 2, h); + tx += c; + tcx -= c; + } + DrawTextEllipsis(w, tx, m.top + 2, tcx, title, "..", StdFont(), SColorHighlightText()); +} + +void TopWindowFrame::Layout() +{ + Size sz = GetSize(); + Rect m = Margins(); + int c = GetStdFontCy() + 4; + int x = sz.cx - m.right; + if(close.IsShown()) + close.SetRect(x -= c, m.top, c, c); + if(maximize.IsShown()) + maximize.SetRect(x -= c, m.top, c, c); +} + +Rect TopWindowFrame::GetClient() const +{ + Rect r = GetRect(); + Rect m = Margins(); + r.left += m.left; + r.right -= m.right; + r.top += m.top; + r.bottom -= m.bottom; + r.top += GetStdFontCy() + 4; + return r; +} + +Rect TopWindowFrame::ComputeClient(Rect r) +{ + Rect m = Margins(); + r.left -= m.left; + r.right += m.right; + r.top -= m.top; + r.bottom += m.bottom; + r.top -= GetStdFontCy() + 4; + return r; +} + +void TopWindowFrame::SetClient(Rect r) +{ + SetRect(ComputeClient(r)); +} + +Point TopWindowFrame::GetDragMode(Point p) +{ + Size sz = GetSize(); + Rect m = ChMargins(FBImg::border()); + Point dir; + dir.y = p.y < m.top ? -1 : p.y > sz.cy - m.top ? 1 : 0; + dir.x = p.x < m.left ? -1 : p.x > sz.cx - m.right ? 1 : 0; + return dir; +} + +void TopWindowFrame::StartDrag() +{ + if(maximized) + return; + if(!sizeable && (dir.x || dir.y)) + return; + if(FullWindowDrag) { + SetCapture(); + startrect = GetRect(); + startpos = GetMousePos(); + } + else { + Rect r = GetScreenRect(); + RectTracker tr(*this); + tr.SetCursorImage(GetDragImage(dir)) + .MaxRect(framebuffer.GetSize()) + .MinSize(ComputeClient(minsize).GetSize()) + .Pattern(DRAWDRAGRECT_DASHED | DRAWDRAGRECT_SCREEN) + .Width(2) + .Animation(); + PaintLock++; + r = tr.Track(r, dir.x < 0 ? ALIGN_LEFT : dir.x > 0 ? ALIGN_RIGHT : ALIGN_CENTER, + dir.y < 0 ? ALIGN_TOP : dir.y > 0 ? ALIGN_BOTTOM : ALIGN_CENTER); + PaintLock--; + SetRect(r); + } + LLOG("START DRAG ---------------"); +} + +void TopWindowFrame::GripResize() +{ + dir = Point(1, 1); + StartDrag(); +} + +void TopWindowFrame::LeftDown(Point p, dword keyflags) +{ + dir = GetDragMode(p); + if(dir.x || dir.y || FullWindowDrag) + StartDrag(); + else { + SetCapture(); + holding = true; + hold.Set(GetKbdDelay() / 3, THISBACK(Hold)); + } +} + +void TopWindowFrame::CancelMode() +{ + holding = false; +} + +void TopWindowFrame::LeftUp(Point p, dword keyflags) +{ + holding = false; +} + +void TopWindowFrame::Hold() +{ + if(HasCapture()) { + if(HasMouse() && GetMouseLeft() && holding) + StartDrag(); + ReleaseCapture(); + holding = false; + } +} + +void TopWindowFrame::LeftHold(Point p, dword keyflags) +{ + if(HasCapture() || FullWindowDrag) + return; + dir = GetDragMode(p); + if(!dir.x && !dir.y) + StartDrag(); +} + +void TopWindowFrame::LeftDouble(Point p, dword keyflags) +{ + ToggleMaximize(); + IgnoreMouseUp(); +} + +void TopWindowFrame::MouseMove(Point, dword) +{ + LDUMP(HasWndCapture()); + LDUMP(HasCapture()); + if(!HasCapture() || holding) + return; + Size msz = ComputeClient(minsize).GetSize(); + Point p = GetMousePos() - startpos; + Rect r = startrect; + if(dir.x == -1) + r.left = min(r.left + p.x, startrect.right - msz.cx); + if(dir.x == 1) + r.right = max(r.right + p.x, startrect.left + msz.cx); + if(dir.y == -1) + r.top = min(r.top + p.y, startrect.bottom - msz.cy); + if(dir.y == 1) + r.bottom = max(r.bottom + p.y, startrect.top + msz.cy); + if(dir.y == 0 && dir.x == 0) + r.Offset(p); + SetRect(r); +} + +Image TopWindowFrame::GetDragImage(Point dir) +{ + static Image (*im[9])() = { + Image::SizeTopLeft, Image::SizeLeft, Image::SizeBottomLeft, + Image::SizeTop, Image::Arrow, Image::SizeBottom, + Image::SizeTopRight, Image::SizeRight, Image::SizeBottomRight, + }; + return (*im[(dir.x + 1) * 3 + (dir.y + 1)])(); +} + +Image TopWindowFrame::CursorImage(Point p, dword) +{ + if(!sizeable) + return Image::Arrow(); + return GetDragImage(HasCapture() ? dir : GetDragMode(p)); +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/SDL20GL/Util.cpp b/rainbow/SDL20GL/Util.cpp new file mode 100644 index 000000000..4430a5a3e --- /dev/null +++ b/rainbow/SDL20GL/Util.cpp @@ -0,0 +1,77 @@ +#include + +#ifdef GUI_SDL20 + +NAMESPACE_UPP + +/* +static void sRenderLine(SystemDraw& w, int x, int y, int dx, int dy, int cx, int cy, int len, byte pattern) +{ + DLOG(len); + for(int i = 0; i < len; i++) + if((128 >> (i & 7)) & pattern) + w.DrawRect(x + dx * i, y + dy * i, cx, cy, Black); + DDUMP("~sRenderLine"); +} + +static void sRenderRect(SystemDraw& w, const Rect& r, int n, byte pattern) +{ + sRenderLine(w, r.left, r.top, 1, 0, 1, n, r.GetWidth(), pattern); + sRenderLine(w, r.left, r.bottom - 1, 1, 0, 1, n, r.GetWidth(), pattern); + sRenderLine(w, r.left, r.top, 0, 1, n, 1, r.GetHeight(), pattern); + sRenderLine(w, r.right - 1, r.top, 0, 1, n, 1, r.GetHeight(), pattern); +} + +void DrawDragRect(SystemDraw& w, const Rect& rect1, const Rect& rect2, + const Rect& clip, int n, Color color, uint64 pattern) +{ + DLOG("@ DrawDragRect " << rect1 << " " << rect2 << ", clip: " << clip << ", pattern: " << pattern); + TIMING("DrawDrawRect"); + w.Clip(clip); + w.Invert(); + sRenderRect(w, rect1, n, (byte)pattern); + sRenderRect(w, rect2, n, (byte)pattern); + Ctrl::AddUpdate((rect1 | rect2).Offseted(w.GetOffset())); +// MemoryProfile mem; +// DDUMP(mem); + w.End(); +} + + + + +static uint64 sGetAniPat(uint64 src, int pos) +{ + uint64 out = 0; + pos &= 7; + for(int i = 8; --i >= 0;) { + byte sr = (byte)(src >> (8 * ((7 - i - pos) & 7))); + out = (out << 8) | (byte)((sr | (sr << 8)) >> pos); + } + return out; +} +*/ + + +/* +Size GetScreenSize() +{ + return ScreenInfo().GetPageSize(); +} +*/ + +void DrawDragRect(Ctrl& q, const Rect& rect1, const Rect& rect2, const Rect& clip, int n, + Color color, int type, int animation) +{ + // q.DragRectDraw(rect1, rect2, clip, n, color, type, animation); + _DBG_ + // TODO: Implement +} + +void FinishDragRect(Ctrl& q) +{ +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/SDL20GL/Window.cpp b/rainbow/SDL20GL/Window.cpp new file mode 100644 index 000000000..b016caf9d --- /dev/null +++ b/rainbow/SDL20GL/Window.cpp @@ -0,0 +1,58 @@ +#include "Local.h" + +#ifdef GUI_SDL20 + +NAMESPACE_UPP + +bool SDLWindow::Create(const Rect& rect, const char *title) +{ + win = SDL_CreateWindow(title, rect.left, rect.top, rect.GetWidth(), rect.GetHeight(), + SDL_WINDOW_SHOWN|SDL_WINDOW_OPENGL); + if(!win) + return false; + MemoryIgnoreLeaksBegin(); + glcontext = SDL_GL_CreateContext(window) + MemoryIgnoreLeaksEnd(); + if(!glcontext) { + Destroy(); + return false; + } + INTERLOCKED { + static int64 h; + serial = h++; + } + return true; +} + +void SDLWindow::Destroy() +{ + if(glcontext) { + SDL_GL_DeleteContext(glcontext); + glcontext = NULL; + GLDraw::ResetCache(); // TODO: Consider not reseting ALL cache data, only specific context + } + if(win) { + SDL_DestroyWindow(win); + win = NULL; + } +} + +void SDLWindow::Present() +{ + SDL_GL_SwapWindow(window); +} + +SDLWindow::SDLWindow() +{ + glcontext = NULL; + win = NULL; +} + +SDLWindow::~SDLWindow() +{ + Destroy(); +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/SDL20GL/Wnd.cpp b/rainbow/SDL20GL/Wnd.cpp new file mode 100644 index 000000000..93bfdfa26 --- /dev/null +++ b/rainbow/SDL20GL/Wnd.cpp @@ -0,0 +1,767 @@ +#include "Local.h" + +#ifdef GUI_SDL20 + +NAMESPACE_UPP + +#define LLOG(x) //DLOG(x) +#define LDUMP(x) //DDUMP(x) +#define LDUMPC(x) //DDUMPC(x) + +ImageBuffer Ctrl::framebuffer; +Vector Ctrl::invalid; +Vector Ctrl::update; + +Ptr Ctrl::desktop; +Vector Ctrl::topctrl; + +Point Ctrl::fbCursorPos = Null; +Image Ctrl::fbCursorImage; +Point Ctrl::fbCursorBakPos = Null; +Image Ctrl::fbCursorBak; +Rect Ctrl::fbCaretRect; +Image Ctrl::fbCaretBak; +int Ctrl::fbCaretTm; +int Ctrl::renderingMode = MODE_ANTIALIASED; +bool Ctrl::fbEndSession; +bool Ctrl::FullWindowDrag; +int Ctrl::PaintLock; + +void Ctrl::SetDesktop(Ctrl& q) +{ + desktop = &q; + desktop->SetRect(framebuffer.GetSize()); + desktop->SetOpen(true); + desktop->NewTop(); + invalid.Add(framebuffer.GetSize()); +} + +void Ctrl::SetRenderingMode(int mode) +{ + renderingMode = mode; + invalid.Add(framebuffer.GetSize()); +} + +void Ctrl::InitFB() +{ + Ctrl::GlobalBackBuffer(); + Ctrl::InitTimer(); + framebuffer.Create(1, 1); + +#ifdef PLATFORM_POSIX + SetStdFont(ScreenSans(12)); //FIXME general handling +#endif + ChStdSkin(); + + static StaticRect x; + x.Color(Cyan()); + SetDesktop(x); +} + +void Ctrl::EndSession() +{ + GuiLock __; + LLOG("Ctrl::EndSession"); + fbEndSession = true; + EndSessionLoopNo = EventLoopNo; +} + +void Ctrl::ExitFB() +{ + TopWindow::ShutdownWindows(); + Ctrl::CloseTopCtrls(); + if(fbEndSession) + FBQuitSession(); +} + +void Ctrl::SetFramebufferSize(Size sz) +{ + framebuffer.Create(sz); + if(desktop) + desktop->SetRect(sz); + invalid.Add(sz); + SyncTopWindows(); +} + +int Ctrl::FindTopCtrl() const +{ + for(int i = 0; i < topctrl.GetCount(); i++) + if(this == topctrl[i]) + return i; + return -1; +} + +bool Ctrl::IsAlphaSupported() +{ + return false; +} + +bool Ctrl::IsCompositedGui() +{ + return false; +} + +Vector Ctrl::GetTopCtrls() +{ + Vector ctrl; + if(desktop) + ctrl.Add(desktop); + for(int i = 0; i < topctrl.GetCount(); i++) + if(!dynamic_cast(topctrl[i])) + ctrl.Add(topctrl[i]); + return ctrl; +} + +Ctrl *Ctrl::GetOwner() +{ + GuiLock __; + int q = FindTopCtrl(); + if(q > 0 && topctrl[q]->top) { + Ctrl *x = topctrl[q]->top->owner_window; + LDUMP(Upp::Name(x)); + return dynamic_cast(x) ? x->GetOwner() : x; + } + return NULL; +} + +Ctrl *Ctrl::GetActiveCtrl() +{ + GuiLock __; + return focusCtrl ? focusCtrl->GetTopCtrl() : NULL; +} + +// Vector Ctrl::hotkey; + +int Ctrl::RegisterSystemHotKey(dword key, Callback cb) +{ +/* ASSERT(key >= K_DELTA); + int q = hotkey.GetCount(); + for(int i = 0; i < hotkey.GetCount(); i++) + if(!hotkey[i]) { + q = i; + break; + } + hotkey.At(q) = cb; + dword mod = 0; + if(key & K_ALT) + mod |= MOD_ALT; + if(key & K_SHIFT) + mod |= MOD_SHIFT; + if(key & K_CTRL) + mod |= MOD_CONTROL; + + return RegisterHotKey(NULL, q, mod, key & 0xffff) ? q : -1;*/ + return -1; +} + +void Ctrl::UnregisterSystemHotKey(int id) +{ +/* if(id >= 0 && id < hotkey.GetCount()) { + UnregisterHotKey(NULL, id); + hotkey[id].Clear(); + }*/ +} + +bool Ctrl::IsWaitingEvent() +{ + return FBIsWaitingEvent(); +} + +void Ctrl::AddUpdate(const Rect& rect) +{ + LLOG("@AddUpdate " << rect); + AddRefreshRect(update, rect); +} + +void Ctrl::AddInvalid(const Rect& rect) +{ + LLOG("@AddInvalid " << rect); + AddRefreshRect(invalid, rect); +} + +void Ctrl::SyncTopWindows() +{ + for(int i = 0; i < topctrl.GetCount(); i++) { + TopWindow *w = dynamic_cast(topctrl[i]); + if(w) + w->SyncRect(); + } +} + +bool Ctrl::ProcessEvent(bool *quit) +{ + LLOG("@ ProcessEvent"); + ASSERT(IsMainThread()); + if(!GetMouseLeft() && !GetMouseRight() && !GetMouseMiddle()) + ReleaseCtrlCapture(); + if(FBProcessEvent(quit)) { + LLOG("FBProcesEvent returned true"); + SyncTopWindows(); + DefferedFocusSync(); + SyncCaret(); + return true; + } + return false; +} + +Rect Ctrl::GetClipBound(const Vector& inv, const Rect& r) +{ + Rect ri = Null; + for(int j = 0; j < inv.GetCount(); j++) { + Rect rr = inv[j] & r; + if(!rr.IsEmpty()) + ri = IsNull(ri) ? rr : rr | ri; + } + return ri; +} + + +ViewDraw::ViewDraw(Ctrl *ctrl) +{ + if(Ctrl::invalid.GetCount()) + Ctrl::DoPaint(); + Ctrl::invalid.Clear(); + Ctrl::RemoveCursor(); + Ctrl::RemoveCaret(); + Rect r = ctrl->GetScreenView(); + Ctrl::invalid.Add(r); + Ctrl::AddUpdate(r); + for(int i = max(ctrl->GetTopCtrl()->FindTopCtrl() + 1, 0); i < Ctrl::topctrl.GetCount(); i++) { + Rect rr = Ctrl::topctrl[i]->GetScreenRect(); + ExcludeClip(rr); + Subtract(Ctrl::invalid, rr); + } + Offset(r.TopLeft()); +} + +ViewDraw::~ViewDraw() +{ + FBInitUpdate(); + Ctrl::DoUpdate(); + FBFlush(); +// Ctrl::invalid.Clear(); +} + +void Ctrl::DoUpdate() +{ + LLOG("DoUpdate"); + invalid.Clear(); + CursorSync(); + LDUMPC(update); + screen.Present(); +#if 0 + FBUpdate(framebuffer.GetSize()); +#else + for(int i = 0; i < update.GetCount(); i++) { + LDUMP(update[i]); + FBUpdate(update[i]); + } +#endif + update.Clear(); +// Sleep(1000); +} + +Vector Ctrl::GetPaintRects() +{ + Vector r; + r.Add(GetScreenRect()); + for(int i = max(FindTopCtrl() + 1, 0); i < topctrl.GetCount(); i++) + Subtract(r, topctrl[i]->GetScreenRect()); + return r; +} + + +void DDRect(RGBA *t, int dir, const byte *pattern, int pos, int count) +{ + while(count-- > 0) { + byte p = pattern[7 & pos++]; + t->r ^= p; + t->g ^= p; + t->b ^= p; + t += dir; + } +} + +void Ctrl::DrawLine(const Vector& clip, int x, int y, int cx, int cy, bool horz, const byte *pattern, int animation) +{ + if(cx <= 0 || cy <= 0) + return; + Vector rr = Intersection(clip, RectC(x, y, cx, cy)); + for(int i = 0; i < rr.GetCount(); i++) { + Rect r = rr[i]; + AddUpdate(r); + if(horz) + for(int y = r.top; y < r.bottom; y++) + DDRect(framebuffer[y] + r.left, 1, pattern, r.left + animation, r.GetWidth()); + else + for(int x = r.left; x < r.right; x++) + DDRect(framebuffer[r.top] + x, framebuffer.GetWidth(), pattern, r.top + animation, r.GetHeight()); + } +} + +void Ctrl::DragRectDraw0(const Vector& clip, const Rect& rect, int n, const byte *pattern, int animation) +{ + int hn = min(rect.GetHeight(), n); + int vn = min(rect.GetWidth(), n); + DrawLine(clip, rect.left, rect.top, rect.GetWidth(), hn, true, pattern, animation); + DrawLine(clip, rect.left, rect.top + hn, vn, rect.GetHeight() - hn, false, pattern, animation); + DrawLine(clip, rect.right - vn, rect.top + hn, vn, rect.GetHeight() - hn, false, pattern, animation); + DrawLine(clip, rect.left + vn, rect.bottom - hn, rect.GetWidth() - 2 * vn, hn, true, pattern, animation); +} + +void Ctrl::DragRectDraw(const Rect& rect1, const Rect& rect2, const Rect& clip, int n, + Color color, int type, int animation) +{ + static byte solid[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + static byte normal[] = { 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00 }; + static byte dashed[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }; + Point p = GetScreenView().TopLeft(); + Vector pr; + if(type & DRAWDRAGRECT_SCREEN) { + pr.Add(Rect(framebuffer.GetSize())); + type &= ~DRAWDRAGRECT_SCREEN; + p = Point(0, 0); + } + else + pr = Intersection(GetPaintRects(), clip.Offseted(p)); + const byte *pattern = type == DRAWDRAGRECT_DASHED ? dashed : + type == DRAWDRAGRECT_NORMAL ? normal : solid; + RemoveCursor(); + RemoveCaret(); + DragRectDraw0(pr, rect1.Offseted(p), n, pattern, animation); + DragRectDraw0(pr, rect2.Offseted(p), n, pattern, animation); +} + +void Ctrl::DoPaint() +{ + LLOG("@ DoPaint"); + if(!PaintLock) { + bool scroll = false; + if(desktop) + desktop->SyncScroll(); + for(int i = 0; i < topctrl.GetCount(); i++) + topctrl[i]->SyncScroll(); + if((invalid.GetCount() || scroll) && desktop) { + RemoveCursor(); + RemoveCaret(); + for(int phase = 0; phase < 2; phase++) { + LLOG("DoPaint invalid phase " << phase); + LDUMPC(invalid); + SystemDraw draw; + draw.Set(screen); + draw.Init(screen_size); + for(int i = 0; i < invalid.GetCount(); i++) { + draw.Clip(invalid[i]); + AddUpdate(invalid[i]); + } + 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, framebuffer.GetSize()); + if(!IsNull(ri)) + desktop->UpdateArea(draw, ri); + } + } + } + DoUpdate(); +} + +void Ctrl::WndUpdate(const Rect& r) +{ + GuiLock __; + Rect rr = r + GetRect().TopLeft(); + bool dummy; + Vector h; + h <<= invalid; + invalid = Intersect(invalid, rr, dummy); + FBInitUpdate(); + DoPaint(); + invalid <<= h; + Subtract(invalid, rr); + FBFlush(); +} + +bool Ctrl::ProcessEvents(bool *quit) +{ + //LOGBLOCK("@ ProcessEvents"); +// MemoryCheckDebug(); + if(!ProcessEvent(quit)) + return false; + while(ProcessEvent(quit) && (!LoopCtrl || LoopCtrl->InLoop())); + TimeStop tm; + TimerProc(GetTickCount()); + LLOG("TimerProc elapsed: " << tm); + SweepMkImageCache(); + FBInitUpdate(); + DoPaint(); + FBFlush(); + return true; +} + +void Ctrl::EventLoop(Ctrl *ctrl) +{ + GuiLock __; + ASSERT(IsMainThread()); + ASSERT(LoopLevel == 0 || ctrl); + LoopLevel++; + LLOG("Entering event loop at level " << LoopLevel << LOG_BEGIN); + Ptr ploop; + if(ctrl) { + ploop = LoopCtrl; + LoopCtrl = ctrl; + ctrl->inloop = true; + } + + bool quit = false; + int64 loopno = ++EventLoopNo; + ProcessEvents(&quit); + while(loopno > EndSessionLoopNo && !quit && (ctrl ? ctrl->IsOpen() && ctrl->InLoop() : GetTopCtrls().GetCount())) + { +// LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / GuiSleep"); + SyncCaret(); + GuiSleep(20); +// LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / ProcessEvents"); + ProcessEvents(&quit); +// LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / after ProcessEvents"); + LDUMP(loopno); + LDUMP(fbEndSessionLoop); + } + + if(ctrl) + LoopCtrl = ploop; + LoopLevel--; + LLOG(LOG_END << "Leaving event loop "); +} + +void Ctrl::GuiSleep(int ms) +{ + GuiLock __; + ASSERT(IsMainThread()); + LLOG("GuiSleep"); + int level = LeaveGuiMutexAll(); + FBSleep(ms); + EnterGuiMutex(level); +} + +Rect Ctrl::GetWndScreenRect() const +{ + GuiLock __; + return GetRect(); +} + +void Ctrl::WndShow(bool b) +{ + GuiLock __; +} + +void Ctrl::WndUpdate() +{ + GuiLock __; +} + +bool Ctrl::IsWndOpen() const { + GuiLock __; + return FindTopCtrl() >= 0 || this == desktop; +} + +void Ctrl::SetAlpha(byte alpha) +{ + GuiLock __; +} + +Rect Ctrl::GetWorkArea() const +{ + GuiLock __; + return framebuffer.GetSize(); +} + +void Ctrl::GetWorkArea(Array& rc) +{ + GuiLock __; + Array r; + r.Add(framebuffer.GetSize()); +} + +Rect Ctrl::GetVirtualWorkArea() +{ + return framebuffer.GetSize(); +} + +Rect Ctrl::GetWorkArea(Point pt) +{ + return framebuffer.GetSize(); +} + +Rect Ctrl::GetVirtualScreenArea() +{ + GuiLock __; + return framebuffer.GetSize(); +} + +Rect Ctrl::GetPrimaryWorkArea() +{ + Rect r; + return framebuffer.GetSize(); +} + +Rect Ctrl::GetPrimaryScreenArea() +{ + return framebuffer.GetSize(); +} + +int Ctrl::GetKbdDelay() +{ + GuiLock __; + return 500; +} + +int Ctrl::GetKbdSpeed() +{ + GuiLock __; + return 1000 / 32; +} + +void Ctrl::DestroyWnd() +{ + for(int i = 0; i < topctrl.GetCount(); i++) + if(topctrl[i]->top && topctrl[i]->top->owner_window == this) + topctrl[i]->WndDestroy(); + int q = FindTopCtrl(); + if(q >= 0) { + AddInvalid(GetRect()); + topctrl.Remove(q); + } + if(top) { + delete top; + top = NULL; + } + isopen = false; + TopWindow *win = dynamic_cast(this); + if(win) + win->DestroyFrame(); +} + +void Ctrl::WndDestroy() +{ + DestroyWnd(); + if(topctrl.GetCount()) + topctrl.Top()->ActivateWnd(); +} + +void Ctrl::PutForeground() +{ + int q = FindTopCtrl(); + if(q >= 0) { + AddInvalid(GetRect()); + topctrl.Remove(q); + topctrl.Add(this); + } + Vector< Ptr > fw; + for(int i = 0; i < topctrl.GetCount(); i++) + if(topctrl[i] && topctrl[i]->top && topctrl[i]->top->owner_window == this && topctrl[i] != this) + fw.Add(topctrl[i]); + for(int i = 0; i < fw.GetCount(); i++) + if(fw[i]) + fw[i]->PutForeground(); +} + +void Ctrl::SetWndForeground() +{ + GuiLock __; + ASSERT(IsOpen()); + if(IsWndForeground()) + return; + Ctrl *to = this; + while(to->top && to->top->owner_window) + to = to->top->owner_window; + to->PutForeground(); + if(this != focusCtrl) + ActivateWnd(); +} + +bool Ctrl::IsWndForeground() const +{ + GuiLock __; + bool b = false; + for(int i = 0; i < topctrl.GetCount(); i++) { + const TopWindow *tw = dynamic_cast(topctrl[i]); + if(tw) + b = tw == this; + } + return b; +} + +void Ctrl::WndEnable(bool) +{ + GuiLock __; +} + +bool Ctrl::SetWndFocus() +{ + GuiLock __; + return true; +} + +bool Ctrl::HasWndFocus() const +{ + GuiLock __; + return focusCtrl && focusCtrl->GetTopCtrl() == this; +} + +bool Ctrl::SetWndCapture() +{ + GuiLock __; + ASSERT(IsMainThread()); + return true; +} + +bool Ctrl::ReleaseWndCapture() +{ + GuiLock __; + ASSERT(IsMainThread()); + return true; +} + +bool Ctrl::HasWndCapture() const +{ + GuiLock __; + return captureCtrl && captureCtrl->GetTopCtrl() == this; +} + +void Ctrl::WndInvalidateRect(const Rect& r) +{ + GuiLock __; + int q = FindTopCtrl(); + if(q >= 0) + AddInvalid(r + topctrl[q]->GetRect().TopLeft()); + else + AddInvalid(r); +} + +void Ctrl::WndSetPos(const Rect& rect) +{ + GuiLock __; + TopWindow *w = dynamic_cast(this); + if(w) + w->SyncFrameRect(rect); + invalid.Add(GetRect()); + SetWndRect(rect); + invalid.Add(rect); +} + +void Ctrl::WndScrollView(const Rect& r, int dx, int dy) +{ + GuiLock __; + if(dx == 0 && dy == 0) + return; + if(dx && dy) { + Refresh(r); + return; + } + RemoveCursor(); + RemoveCaret(); + Rect sr = r.Offseted(GetScreenRect().TopLeft()); + Vector pr = Intersection(GetPaintRects(), sr); + for(int i = 0; i < pr.GetCount(); i++) { + Rect r = pr[i]; + if(dx) { + int n = r.GetWidth() - abs(dx); + if(n > 0) { + int to = r.left + dx * (dx > 0); + int from = r.left - dx * (dx < 0); + for(int y = r.top; y < r.bottom; y++) + memmove(framebuffer[y] + to, framebuffer[y] + from, n * sizeof(RGBA)); + } + n = min(abs(dx), r.GetWidth()); + Refresh(dx < 0 ? r.left : r.right - n, r.top, n, r.GetHeight()); + } + else { + int n = r.GetHeight() - abs(dy); + for(int y = 0; y < n; y++) + memmove(framebuffer[dy < 0 ? r.top + y : r.bottom - 1 - y] + r.left, + framebuffer[dy < 0 ? r.top + y - dy : r.bottom - 1 - y - dy] + r.left, + r.GetWidth() * sizeof(RGBA)); + n = min(abs(dy), r.GetHeight()); + Refresh(r.left, dy < 0 ? r.bottom - n : r.top, r.GetWidth(), n); + } + } + + Vector ur; + for(int i = 0; i < invalid.GetCount(); i++) + if(invalid[i].Intersects(sr)) + ur.Add(invalid[i]); + for(int i = 0; i < ur.GetCount(); i++) + AddInvalid(ur[i].Offseted(dx, dy)); +} + +void Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow, bool topmost) +{ + ASSERT(!IsChild() && !IsOpen() && FindTopCtrl() < 0); + NewTop(); + if(owner) { + Ctrl *owner_window = owner->GetTopWindow(); + if(!owner_window) + owner_window = owner->GetTopCtrl(); + ASSERT(owner_window->IsOpen()); + if(owner_window != desktop) { + owner_window->SetForeground(); + top->owner_window = owner_window; + } + } + topctrl.Add(this); + popup = isopen = true; + RefreshLayoutDeep(); + if(activate) SetFocusWnd(); + AddInvalid(GetRect()); +} + +Rect Ctrl::GetDefaultWindowRect() { + GuiLock __; + static int ii = 0; + Size sz = framebuffer.GetSize(); + Rect rect = framebuffer.GetSize(); + rect.Deflate(sz / 10); + rect.Offset(Size(GetStdFontCy(), 2 * GetStdFontCy()) * (++ii % 8)); + return rect; +} + +Vector SplitCmdLine__(const char *cmd) +{ + Vector out; + while(*cmd) + if((byte)*cmd <= ' ') + cmd++; + else if(*cmd == '\"') { + WString quoted; + while(*++cmd && (*cmd != '\"' || *++cmd == '\"')) + quoted.Cat(FromSystemCharset(String(cmd, 1)).ToWString()); + out.Add(quoted); + } + else { + const char *begin = cmd; + while((byte)*cmd > ' ') + cmd++; + out.Add(String(begin, cmd).ToWString()); + } + return out; +} + +void Ctrl::InstallPanicBox() +{ +} + +void Ctrl::SysEndLoop() +{ +} + +END_UPP_NAMESPACE + +#endif diff --git a/rainbow/SDL20GL/init b/rainbow/SDL20GL/init new file mode 100644 index 000000000..f98f13489 --- /dev/null +++ b/rainbow/SDL20GL/init @@ -0,0 +1,6 @@ +#ifndef _SDL20_icpp_init_stub +#define _SDL20_icpp_init_stub +#include "Painter/init" +#include "CtrlLib/init" +#include "GLDraw/init" +#endif diff --git a/rainbow/SDL20Uword/SDL20Uword.upp b/rainbow/SDL20Uword/SDL20Uword.upp index 432a04688..dee328209 100644 --- a/rainbow/SDL20Uword/SDL20Uword.upp +++ b/rainbow/SDL20Uword/SDL20Uword.upp @@ -1,7 +1,7 @@ uses CtrlLib, - SDL20, - RichEdit; + RichEdit, + SDL20GL; file main.cpp; diff --git a/rainbow/SDL20Uword/init b/rainbow/SDL20Uword/init index 11b71eee9..2325fefba 100644 --- a/rainbow/SDL20Uword/init +++ b/rainbow/SDL20Uword/init @@ -1,6 +1,6 @@ #ifndef _SDL20Uword_icpp_init_stub #define _SDL20Uword_icpp_init_stub #include "CtrlLib/init" -#include "SDL20/init" #include "RichEdit/init" +#include "SDL20GL/init" #endif