From 3d7408bc93c280683cc482e98be670c0e2786dcb Mon Sep 17 00:00:00 2001 From: Janak Porwal Date: Tue, 16 Feb 2021 16:19:01 +0530 Subject: [PATCH 1/9] Initial rendering code commit --- model/renderNativeWindow.cc | 30 ++++++++++++++++++++++++++++-- model/renderNativeWindow.h | 3 +++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/model/renderNativeWindow.cc b/model/renderNativeWindow.cc index 873cbd6bf..a4057459f 100644 --- a/model/renderNativeWindow.cc +++ b/model/renderNativeWindow.cc @@ -77,12 +77,38 @@ namespace minsky int err=XGetWindowAttributes(display, window, &wAttr); if (err>1) throw runtime_error("Invalid window: "+to_string(window)); - cairo::SurfacePtr r(new cairo::Surface(cairo_xlib_surface_create(display,window,wAttr.visual,wAttr.width,wAttr.height),wAttr.width,wAttr.height)); + + + int padding = 10; + int yOffset = 150; + int childWindowWidth = wAttr.width - 2*padding; + int childWindowHeight = wAttr.height - yOffset - padding; + + unsigned long childWindow = XCreateSimpleWindow(display, window, padding, yOffset, childWindowWidth, childWindowHeight, 0, 0, 0); + XMapWindow(display, childWindow); + + cout << "Child Window ID ::"<< childWindow << endl; + //XSelectInput(d, da, ButtonPressMask | KeyPressMask); + cout << "wAttr(x, y)::" << wAttr.x << "," << wAttr.y << endl; + + cairo::SurfacePtr r(new cairo::Surface(cairo_xlib_surface_create(display, childWindow,wAttr.visual, childWindowWidth, childWindowHeight), childWindowWidth, childWindowHeight)); cairo_surface_set_device_offset(r->surface(), -wAttr.x, -wAttr.y); + + cairo_move_to(r->cairo(), 0, 0); + cairo_set_source_rgb(r->cairo(), 1, 1, 1); + cairo_paint(r->cairo()); return r; } #endif - + + + void RenderNativeWindow::initializeNativeWindow(unsigned long window) { + + } + + void RenderNativeWindow::renderFrame() { + + } void RenderNativeWindow::renderToNativeWindow(unsigned long window) { diff --git a/model/renderNativeWindow.h b/model/renderNativeWindow.h index 85ca8ed41..726ef34cd 100644 --- a/model/renderNativeWindow.h +++ b/model/renderNativeWindow.h @@ -27,6 +27,9 @@ namespace minsky class RenderNativeWindow: public ecolab::CairoSurface { public: + void initializeNativeWindow(unsigned long window); + void renderFrame(); + void renderToNativeWindow(unsigned long window); }; } From 1733fe1f9e125741203862d4232f84532d61fa10 Mon Sep 17 00:00:00 2001 From: Janak Porwal Date: Wed, 17 Feb 2021 15:45:08 +0530 Subject: [PATCH 2/9] Struct for WindowInformation and reusing the child window across repaints --- model/renderNativeWindow.cc | 125 ++++++++++++++++++++++++------------ model/renderNativeWindow.h | 35 ++++++++-- 2 files changed, 114 insertions(+), 46 deletions(-) diff --git a/model/renderNativeWindow.cc b/model/renderNativeWindow.cc index a4057459f..ec34fef5a 100644 --- a/model/renderNativeWindow.cc +++ b/model/renderNativeWindow.cc @@ -54,67 +54,110 @@ using namespace ecolab; namespace minsky { #ifdef USE_WIN32_SURFACE - inline cairo::SurfacePtr nativeWindowSurface(unsigned long window) - {/* TODO */} + inline cairo::SurfacePtr createNativeWindowSurface(WindowInformation *winInfo) + { /* TODO */ + } #elif defined(MAC_OSX_TK) - inline cairo::SurfacePtr nativeWindowSurface(unsigned long window) - {/* TODO */} + inline cairo::SurfacePtr createNativeWindowSurface(WindowInformation *winInfo) + { /* TODO */ + } #else - int throwOnXError(Display*, XErrorEvent* ev) + int throwOnXError(Display *, XErrorEvent *ev) { char errorMessage[256]; XGetErrorText(ev->display, ev->error_code, errorMessage, sizeof(errorMessage)); throw runtime_error(errorMessage); } - - inline cairo::SurfacePtr nativeWindowSurface(unsigned long window) + + inline cairo::SurfacePtr createNativeWindowSurface(WindowInformation *wi) { - // ensure errors are thrown, rather than exit() being called - static bool errorHandlingSet=(XSetErrorHandler(throwOnXError), true); - XWindowAttributes wAttr; - auto display=XOpenDisplay(nullptr); - int err=XGetWindowAttributes(display, window, &wAttr); - if (err>1) - throw runtime_error("Invalid window: "+to_string(window)); - - - int padding = 10; - int yOffset = 150; - int childWindowWidth = wAttr.width - 2*padding; - int childWindowHeight = wAttr.height - yOffset - padding; - - unsigned long childWindow = XCreateSimpleWindow(display, window, padding, yOffset, childWindowWidth, childWindowHeight, 0, 0, 0); - XMapWindow(display, childWindow); - - cout << "Child Window ID ::"<< childWindow << endl; - //XSelectInput(d, da, ButtonPressMask | KeyPressMask); - cout << "wAttr(x, y)::" << wAttr.x << "," << wAttr.y << endl; - - cairo::SurfacePtr r(new cairo::Surface(cairo_xlib_surface_create(display, childWindow,wAttr.visual, childWindowWidth, childWindowHeight), childWindowWidth, childWindowHeight)); - cairo_surface_set_device_offset(r->surface(), -wAttr.x, -wAttr.y); - - cairo_move_to(r->cairo(), 0, 0); - cairo_set_source_rgb(r->cairo(), 1, 1, 1); - cairo_paint(r->cairo()); - return r; + cairo::SurfacePtr childSurface(new cairo::Surface(cairo_xlib_surface_create(wi->display, wi->childWindowId, wi->wAttr.visual, wi->childWidth, wi->childHeight), wi->childWidth, wi->childHeight)); + cairo_surface_set_device_offset(childSurface->surface(), -wi->wAttr.x, -wi->wAttr.y); + return childSurface; } #endif + WindowInformation::WindowInformation() + { + } + WindowInformation::~WindowInformation() { + cout << "Delete called for window information" << endl; + } + + void WindowInformation::initialize(unsigned long parentWin, int left, int top) + { + parentWindowId = parentWin; + offsetLeft = left; + offsetTop = top; + + static bool errorHandlingSet = (XSetErrorHandler(throwOnXError), true); + display = XOpenDisplay(nullptr); + int err = XGetWindowAttributes(display, parentWin, &wAttr); + if (err > 1) + throw runtime_error("Invalid window: " + to_string(parentWin)); + + int padding = offsetLeft; + int yOffset = offsetTop; - void RenderNativeWindow::initializeNativeWindow(unsigned long window) { + childWidth = wAttr.width - 2 * padding; + childHeight = wAttr.height - yOffset - padding; + childWindowId = XCreateSimpleWindow(display, parentWin, offsetTop, offsetLeft, childWidth, childHeight, 0, 0, 0); + XMapWindow(display, childWindowId); } - void RenderNativeWindow::renderFrame() { + void WindowInformation::copy(WindowInformation *winInfo) + { + this->parentWindowId = winInfo->parentWindowId; + this->childWindowId = winInfo->childWindowId; + this->offsetLeft = winInfo->offsetLeft; + this->offsetTop = winInfo->offsetTop; + this->display = winInfo->display; + this->wAttr = winInfo->wAttr; + // this->childSurface = winInfo->childSurface;// TODO:: Later, try reusing the surface also in winInfo + } + RenderNativeWindow::RenderNativeWindow() + { + winInfo = new WindowInformation(); // TODO:: Try to reuse the WindowInformation object instead of creating a new one.... perhaps it should be a static data member? } - void RenderNativeWindow::renderToNativeWindow(unsigned long window) + RenderNativeWindow::~RenderNativeWindow() { - auto tmp=nativeWindowSurface(window); + delete winInfo; + } + + RenderNativeWindow &RenderNativeWindow::operator=(const RenderNativeWindow &a) + { + cout << "Calling assignment on renderNativeWindow" << endl; + a.winInfo->copy(this->winInfo); + return *this; + } + + RenderNativeWindow::RenderNativeWindow(const RenderNativeWindow &a) + { + cout << "Copy constructor for RenderNativeWindow called... TODO:: implement this" << endl; + //a.winInfo->copy(this->winInfo); // reverse? + }; + + void RenderNativeWindow::renderFrame() + { + auto tmp = createNativeWindowSurface(winInfo); + + //TODO:: Review if this paint (below 3 lines) is really needed with each frame + cairo_move_to(tmp->cairo(), 0, 0); + cairo_set_source_rgb(tmp->cairo(), 1, 1, 1); + cairo_paint(tmp->cairo()); + tmp.swap(surface); - redraw(0,0,surface->width(),surface->height()); + redraw(0, 0, surface->width(), surface->height()); tmp.swap(surface); } -} + + void RenderNativeWindow::initializeNativeWindow(unsigned long parentWindowId) + { + this->winInfo->initialize(parentWindowId, 15, 150); + } + +} // namespace minsky diff --git a/model/renderNativeWindow.h b/model/renderNativeWindow.h index 726ef34cd..4d67afe49 100644 --- a/model/renderNativeWindow.h +++ b/model/renderNativeWindow.h @@ -24,15 +24,40 @@ namespace minsky { - class RenderNativeWindow: public ecolab::CairoSurface + struct WindowInformation { + unsigned long parentWindowId; + unsigned long childWindowId; + int childWidth; + int childHeight; + int offsetLeft; + int offsetTop; + Display* display; + XWindowAttributes wAttr; + ecolab::cairo::SurfacePtr *childSurface; // TODO:: Review right way to store surface ptr + + WindowInformation(); + ~WindowInformation(); + void initialize(unsigned long parentWin, int offsetLeft, int offsetTop); + void copy(WindowInformation *winInfo); + }; + + class RenderNativeWindow : public ecolab::CairoSurface + { + private: + WindowInformation *winInfo; + public: - void initializeNativeWindow(unsigned long window); - void renderFrame(); + RenderNativeWindow(); + ~RenderNativeWindow(); + RenderNativeWindow& operator=(const RenderNativeWindow &a); + RenderNativeWindow(const RenderNativeWindow &a); - void renderToNativeWindow(unsigned long window); + public: + void initializeNativeWindow(unsigned long parentWindowId); + void renderFrame(); }; -} +} // namespace minsky #include "renderNativeWindow.cd" #endif From c119dd7e20f070f4e4db3c9d689128d2d6e242d5 Mon Sep 17 00:00:00 2001 From: Janak Porwal Date: Wed, 17 Feb 2021 15:54:56 +0530 Subject: [PATCH 3/9] offset reversal fixed --- model/renderNativeWindow.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/model/renderNativeWindow.cc b/model/renderNativeWindow.cc index ec34fef5a..73929660b 100644 --- a/model/renderNativeWindow.cc +++ b/model/renderNativeWindow.cc @@ -103,7 +103,7 @@ namespace minsky childWidth = wAttr.width - 2 * padding; childHeight = wAttr.height - yOffset - padding; - childWindowId = XCreateSimpleWindow(display, parentWin, offsetTop, offsetLeft, childWidth, childHeight, 0, 0, 0); + childWindowId = XCreateSimpleWindow(display, parentWin, offsetLeft, offsetTop, childWidth, childHeight, 0, 0, 0); //TODO:: Should we pass visual and attributes at the end? XMapWindow(display, childWindowId); } From d14090c7cfbac0bcc6313acb08339a6eb03e4ea9 Mon Sep 17 00:00:00 2001 From: Janak Porwal Date: Wed, 17 Feb 2021 17:15:58 +0530 Subject: [PATCH 4/9] Added processing of offset arguments, though they don't work --- model/renderNativeWindow.cc | 45 +++++++++++++++++++++++++++---------- model/renderNativeWindow.h | 7 ++++-- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/model/renderNativeWindow.cc b/model/renderNativeWindow.cc index 73929660b..1df5c87ed 100644 --- a/model/renderNativeWindow.cc +++ b/model/renderNativeWindow.cc @@ -17,6 +17,15 @@ along with Minsky. If not, see . */ +/* We have created a struct `WindowInformation` that stores the `childWindowId` along with other details like display and window attributes. This information is reused across multiple calls to `renderFrame`. + +The flow for code will be -- when minsky starts, a call to /minsky/canvas/initializeNativeWindow will be made, with parentWindowId (and offsets) as the parameters (creating child window in electron did not work as expected, so we need to work with offsets). Subsequent repaints can be requested with /minsky/canvas/renderFrame + +As of now, we create the cairo surface with each call to `renderFrame`, though I think the surface can also be reused. I have a placeholder for pointer to cairo::SurfacePtr (not sure we should have pointer to pointer) but it didn't work as expected, so for now I am recreating the surface in `renderFrame` + +Please especially review the lifecycle (constructors, desctructors and copy constructors) that I have defined in `renderNativeWindow.cc `. I think the WindowInformation object that is destroyed in the destructor for RenderNativeWindow can be reused (perhaps it can be made a static object?). Also - am not sure how to distinguish between destructor for RenderNativeWindow that will be called with each call to load model (or undo/redo as you mentioned), and the final call when minsky is closed. + */ + #include "renderNativeWindow.h" #include "minsky_epilogue.h" @@ -81,11 +90,12 @@ namespace minsky WindowInformation::WindowInformation() { } - WindowInformation::~WindowInformation() { + WindowInformation::~WindowInformation() + { cout << "Delete called for window information" << endl; } - void WindowInformation::initialize(unsigned long parentWin, int left, int top) + void WindowInformation::initialize(unsigned long parentWin, int left, int top, int cWidth, int cHeight) { parentWindowId = parentWin; offsetLeft = left; @@ -97,12 +107,20 @@ namespace minsky if (err > 1) throw runtime_error("Invalid window: " + to_string(parentWin)); - int padding = offsetLeft; - int yOffset = offsetTop; - - childWidth = wAttr.width - 2 * padding; - childHeight = wAttr.height - yOffset - padding; - + childWidth = wAttr.width - offsetLeft; + childHeight = wAttr.height - offsetTop; + + // Todo:: currently width, height parameters are not getting passed properly + // Eventually, we need those in order to ensure we don't need to worry about + // paddings, scrollbars etc + if(cWidth > 0) { + childWidth = min(childWidth, cWidth); + } + if(cHeight > 0) { + childHeight = min(childHeight, cHeight); + } + + cout << childWidth << "::" << childHeight << "::" << offsetLeft << "::" << offsetTop << endl; childWindowId = XCreateSimpleWindow(display, parentWin, offsetLeft, offsetTop, childWidth, childHeight, 0, 0, 0); //TODO:: Should we pass visual and attributes at the end? XMapWindow(display, childWindowId); } @@ -144,7 +162,7 @@ namespace minsky void RenderNativeWindow::renderFrame() { auto tmp = createNativeWindowSurface(winInfo); - + //TODO:: Review if this paint (below 3 lines) is really needed with each frame cairo_move_to(tmp->cairo(), 0, 0); cairo_set_source_rgb(tmp->cairo(), 1, 1, 1); @@ -155,9 +173,12 @@ namespace minsky tmp.swap(surface); } - void RenderNativeWindow::initializeNativeWindow(unsigned long parentWindowId) + void RenderNativeWindow::initializeNativeWindow(unsigned long parentWindowId, int offsetLeft, int offsetTop, int childWidth, int childHeight) { - this->winInfo->initialize(parentWindowId, 15, 150); + cout << parentWindowId << "::" << offsetLeft << "::" << offsetTop << "::" << childWidth << "::" << childHeight << endl; + // TODO:: Only the first argument is getting passed here, rest values are 0s + offsetLeft = max(20, offsetLeft); + offsetTop = max(180, offsetTop); + this->winInfo->initialize(parentWindowId, offsetLeft, offsetTop, childWidth, childHeight); } - } // namespace minsky diff --git a/model/renderNativeWindow.h b/model/renderNativeWindow.h index 4d67afe49..02d5bc055 100644 --- a/model/renderNativeWindow.h +++ b/model/renderNativeWindow.h @@ -38,7 +38,7 @@ namespace minsky WindowInformation(); ~WindowInformation(); - void initialize(unsigned long parentWin, int offsetLeft, int offsetTop); + void initialize(unsigned long parentWin, int offsetLeft, int offsetTop, int childWidth, int childHeight); void copy(WindowInformation *winInfo); }; @@ -54,7 +54,10 @@ namespace minsky RenderNativeWindow(const RenderNativeWindow &a); public: - void initializeNativeWindow(unsigned long parentWindowId); + void initializeNativeWindow(unsigned long parentWindowId, int offsetLeft, int offsetTop, int childWidth, int childHeight); + + void resizeWindow(int offsetLeft, int offsetTop, int childWidth, int childHeight); + void renderFrame(); }; } // namespace minsky From 01eeda14a72c78ca87fac13e108efc93aed2611b Mon Sep 17 00:00:00 2001 From: Janak Porwal Date: Wed, 17 Feb 2021 17:18:52 +0530 Subject: [PATCH 5/9] winInfo made public --- model/renderNativeWindow.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/model/renderNativeWindow.h b/model/renderNativeWindow.h index 02d5bc055..b347f7b69 100644 --- a/model/renderNativeWindow.h +++ b/model/renderNativeWindow.h @@ -44,7 +44,8 @@ namespace minsky class RenderNativeWindow : public ecolab::CairoSurface { - private: + public: + /* Perhaps needs to be public for some auto-binding code */ WindowInformation *winInfo; public: From 9131626dade7d2ffb368fc91627e1a9c4da87b4e Mon Sep 17 00:00:00 2001 From: Janak Porwal Date: Wed, 17 Feb 2021 17:37:47 +0530 Subject: [PATCH 6/9] function placeholder --- model/renderNativeWindow.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/model/renderNativeWindow.cc b/model/renderNativeWindow.cc index 1df5c87ed..4cfc1d2aa 100644 --- a/model/renderNativeWindow.cc +++ b/model/renderNativeWindow.cc @@ -181,4 +181,9 @@ namespace minsky offsetTop = max(180, offsetTop); this->winInfo->initialize(parentWindowId, offsetLeft, offsetTop, childWidth, childHeight); } + + + void RenderNativeWindow::resizeWindow(int offsetLeft, int offsetTop, int childWidth, int childHeight) { + // TODO:: To be implemented... need to recreate child window + } } // namespace minsky From 446d6e3acb2d14c0f0b1481526a21f4ecd5d441d Mon Sep 17 00:00:00 2001 From: Janak Porwal Date: Mon, 22 Feb 2021 17:45:09 +0530 Subject: [PATCH 7/9] WindowInformation in separate file --- model/renderNativeWindow.cc | 104 ++++++++-------------------------- model/renderNativeWindow.h | 33 +++-------- model/windowInformation.cc | 110 ++++++++++++++++++++++++++++++++++++ model/windowInformation.h | 63 +++++++++++++++++++++ 4 files changed, 204 insertions(+), 106 deletions(-) create mode 100644 model/windowInformation.cc create mode 100644 model/windowInformation.h diff --git a/model/renderNativeWindow.cc b/model/renderNativeWindow.cc index 4cfc1d2aa..6a3c4b0f1 100644 --- a/model/renderNativeWindow.cc +++ b/model/renderNativeWindow.cc @@ -27,11 +27,11 @@ Please especially review the lifecycle (constructors, desctructors and copy cons */ #include "renderNativeWindow.h" +#include "windowInformation.h" #include "minsky_epilogue.h" #if defined(CAIRO_HAS_XLIB_SURFACE) && !defined(MAC_OSX_TK) #include -#include #include #endif @@ -63,105 +63,50 @@ using namespace ecolab; namespace minsky { #ifdef USE_WIN32_SURFACE - inline cairo::SurfacePtr createNativeWindowSurface(WindowInformation *winInfo) + inline cairo::SurfacePtr createNativeWindowSurface(WindowInformation &winInfo) { /* TODO */ } #elif defined(MAC_OSX_TK) - inline cairo::SurfacePtr createNativeWindowSurface(WindowInformation *winInfo) + inline cairo::SurfacePtr createNativeWindowSurface(WindowInformation &winInfo) { /* TODO */ } #else - - int throwOnXError(Display *, XErrorEvent *ev) - { - char errorMessage[256]; - XGetErrorText(ev->display, ev->error_code, errorMessage, sizeof(errorMessage)); - throw runtime_error(errorMessage); - } - - inline cairo::SurfacePtr createNativeWindowSurface(WindowInformation *wi) + inline cairo::SurfacePtr createNativeWindowSurface(WindowInformation &wi) { - cairo::SurfacePtr childSurface(new cairo::Surface(cairo_xlib_surface_create(wi->display, wi->childWindowId, wi->wAttr.visual, wi->childWidth, wi->childHeight), wi->childWidth, wi->childHeight)); - cairo_surface_set_device_offset(childSurface->surface(), -wi->wAttr.x, -wi->wAttr.y); + cairo::SurfacePtr childSurface(new cairo::Surface(cairo_xlib_surface_create(wi.getDisplay(), wi.getChildWindowId(), wi.wAttr.visual, wi.childWidth, wi.childHeight), wi.childWidth, wi.childHeight)); + cairo_surface_set_device_offset(childSurface->surface(), -wi.wAttr.x, -wi.wAttr.y); return childSurface; } #endif - WindowInformation::WindowInformation() - { - } - WindowInformation::~WindowInformation() - { - cout << "Delete called for window information" << endl; - } - - void WindowInformation::initialize(unsigned long parentWin, int left, int top, int cWidth, int cHeight) + RenderNativeWindow::~RenderNativeWindow() { - parentWindowId = parentWin; - offsetLeft = left; - offsetTop = top; - - static bool errorHandlingSet = (XSetErrorHandler(throwOnXError), true); - display = XOpenDisplay(nullptr); - int err = XGetWindowAttributes(display, parentWin, &wAttr); - if (err > 1) - throw runtime_error("Invalid window: " + to_string(parentWin)); - - childWidth = wAttr.width - offsetLeft; - childHeight = wAttr.height - offsetTop; - - // Todo:: currently width, height parameters are not getting passed properly - // Eventually, we need those in order to ensure we don't need to worry about - // paddings, scrollbars etc - if(cWidth > 0) { - childWidth = min(childWidth, cWidth); - } - if(cHeight > 0) { - childHeight = min(childHeight, cHeight); + if (this->winInfo) + { + delete this->winInfo; } - - cout << childWidth << "::" << childHeight << "::" << offsetLeft << "::" << offsetTop << endl; - childWindowId = XCreateSimpleWindow(display, parentWin, offsetLeft, offsetTop, childWidth, childHeight, 0, 0, 0); //TODO:: Should we pass visual and attributes at the end? - XMapWindow(display, childWindowId); - } - - void WindowInformation::copy(WindowInformation *winInfo) - { - this->parentWindowId = winInfo->parentWindowId; - this->childWindowId = winInfo->childWindowId; - this->offsetLeft = winInfo->offsetLeft; - this->offsetTop = winInfo->offsetTop; - this->display = winInfo->display; - this->wAttr = winInfo->wAttr; - // this->childSurface = winInfo->childSurface;// TODO:: Later, try reusing the surface also in winInfo } RenderNativeWindow::RenderNativeWindow() { - winInfo = new WindowInformation(); // TODO:: Try to reuse the WindowInformation object instead of creating a new one.... perhaps it should be a static data member? - } - - RenderNativeWindow::~RenderNativeWindow() - { - delete winInfo; + this->winInfo = new WindowInformation(); } RenderNativeWindow &RenderNativeWindow::operator=(const RenderNativeWindow &a) { - cout << "Calling assignment on renderNativeWindow" << endl; - a.winInfo->copy(this->winInfo); - return *this; + //TODO:: I expected this to be the "new" instance with uninitialized winInfo and a to have the previous winInfo. + // However, it seems to be the other way round in practice --- Janak + a.winInfo->initialize(*(this->winInfo)); } RenderNativeWindow::RenderNativeWindow(const RenderNativeWindow &a) { - cout << "Copy constructor for RenderNativeWindow called... TODO:: implement this" << endl; - //a.winInfo->copy(this->winInfo); // reverse? - }; + // cout << "Copy constructor was called" << endl; + } void RenderNativeWindow::renderFrame() { - auto tmp = createNativeWindowSurface(winInfo); + auto tmp = createNativeWindowSurface(*winInfo); //TODO:: Review if this paint (below 3 lines) is really needed with each frame cairo_move_to(tmp->cairo(), 0, 0); @@ -173,17 +118,14 @@ namespace minsky tmp.swap(surface); } - void RenderNativeWindow::initializeNativeWindow(unsigned long parentWindowId, int offsetLeft, int offsetTop, int childWidth, int childHeight) - { - cout << parentWindowId << "::" << offsetLeft << "::" << offsetTop << "::" << childWidth << "::" << childHeight << endl; - // TODO:: Only the first argument is getting passed here, rest values are 0s - offsetLeft = max(20, offsetLeft); - offsetTop = max(180, offsetTop); - this->winInfo->initialize(parentWindowId, offsetLeft, offsetTop, childWidth, childHeight); + void RenderNativeWindow::initializeNativeWindow(unsigned long parentWindowId, int offsetLeft, int offsetTop, int childWidth, int childHeight) { + //std::cout << parentWindowId << "::" << offsetLeft << "::" << offsetTop << "::" << childWidth << "::" << childHeight << std::endl; + winInfo->initialize(parentWindowId, offsetLeft, offsetTop, childWidth, childHeight); + //std::cout << "Child window id:: " << winInfo->getChildWindowId() << std::endl; } - - void RenderNativeWindow::resizeWindow(int offsetLeft, int offsetTop, int childWidth, int childHeight) { + void RenderNativeWindow::resizeWindow(int offsetLeft, int offsetTop, int childWidth, int childHeight) + { // TODO:: To be implemented... need to recreate child window } } // namespace minsky diff --git a/model/renderNativeWindow.h b/model/renderNativeWindow.h index b347f7b69..1106678b7 100644 --- a/model/renderNativeWindow.h +++ b/model/renderNativeWindow.h @@ -23,42 +23,25 @@ #include namespace minsky -{ - struct WindowInformation - { - unsigned long parentWindowId; - unsigned long childWindowId; - int childWidth; - int childHeight; - int offsetLeft; - int offsetTop; - Display* display; - XWindowAttributes wAttr; - ecolab::cairo::SurfacePtr *childSurface; // TODO:: Review right way to store surface ptr - - WindowInformation(); - ~WindowInformation(); - void initialize(unsigned long parentWin, int offsetLeft, int offsetTop, int childWidth, int childHeight); - void copy(WindowInformation *winInfo); - }; - +{ + class WindowInformation; class RenderNativeWindow : public ecolab::CairoSurface { - public: - /* Perhaps needs to be public for some auto-binding code */ - WindowInformation *winInfo; + private: + CLASSDESC_ACCESS(RenderNativeWindow); + // std::shared_ptr winInfoPtr; // TODO:: cannot get things to work with this + WindowInformation* winInfo; public: + RenderNativeWindow(); ~RenderNativeWindow(); RenderNativeWindow& operator=(const RenderNativeWindow &a); RenderNativeWindow(const RenderNativeWindow &a); - public: + void initializeNativeWindow(unsigned long parentWindowId, int offsetLeft, int offsetTop, int childWidth, int childHeight); - void resizeWindow(int offsetLeft, int offsetTop, int childWidth, int childHeight); - void renderFrame(); }; } // namespace minsky diff --git a/model/windowInformation.cc b/model/windowInformation.cc new file mode 100644 index 000000000..63a87dd3d --- /dev/null +++ b/model/windowInformation.cc @@ -0,0 +1,110 @@ +/* + @copyright Steve Keen 2021 + @author Janak Porwal + This file is part of Minsky. + + Minsky is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Minsky is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Minsky. If not, see . +*/ + +#include "windowInformation.h" +#include "minsky_epilogue.h" + +#include +#include + +using namespace std; +using namespace ecolab; + +namespace minsky +{ +#ifdef USE_WIN32_SURFACE +#elif defined(MAC_OSX_TK) +#else + int throwOnXError(Display *, XErrorEvent *ev) + { + char errorMessage[256]; + XGetErrorText(ev->display, ev->error_code, errorMessage, sizeof(errorMessage)); + throw runtime_error(errorMessage); + } +#endif + + WindowInformation::WindowInformation() + { + } + + unsigned long WindowInformation::getChildWindowId() + { + return childWindowId; + } + + Display *WindowInformation::getDisplay() + { + return display; + } + + WindowInformation::~WindowInformation() + { + childSurface.reset(); + XDestroyWindow(display, childWindowId); + } + + void WindowInformation::initialize(const WindowInformation &other) + { + this->initialize(other.parentWindowId, other.offsetLeft, other.offsetTop, other.childWidth, other.childHeight); + } + + void WindowInformation::initialize(unsigned long parentWin, int left, int top, int cWidth, int cHeight) + { + parentWindowId = parentWin; + offsetLeft = left; + offsetTop = top; + + static bool errorHandlingSet = (XSetErrorHandler(throwOnXError), true); + display = XOpenDisplay(nullptr); + int err = XGetWindowAttributes(display, parentWin, &wAttr); + if (err > 1) + throw runtime_error("Invalid window: " + to_string(parentWin)); + + childWidth = wAttr.width - offsetLeft; + childHeight = wAttr.height - offsetTop; + + // Todo:: currently width, height parameters are not getting passed properly + // Eventually, we need those in order to ensure we don't need to worry about + // paddings, scrollbars etc + if (cWidth > 0) + { + childWidth = min(childWidth, cWidth); + } + if (cHeight > 0) + { + childHeight = min(childHeight, cHeight); + } + + // std::cout << childWidth << "::" << childHeight << "::" << offsetLeft << "::" << offsetTop << std::endl; + childWindowId = XCreateSimpleWindow(display, parentWin, offsetLeft, offsetTop, childWidth, childHeight, 0, 0, 0); //TODO:: Should we pass visual and attributes at the end? + XMapWindow(display, childWindowId); + // std::cout << "We got child window id = " << childWindowId << std::endl; + } + + ecolab::cairo::SurfacePtr WindowInformation::getSurface() + { + return childSurface; + } + + WindowInformation::WindowInformation(unsigned long parentWin, int left, int top, int cWidth, int cHeight) + { + this->initialize(parentWin, left, top, cWidth, cHeight); + } + +} // namespace minsky diff --git a/model/windowInformation.h b/model/windowInformation.h new file mode 100644 index 000000000..3105b5886 --- /dev/null +++ b/model/windowInformation.h @@ -0,0 +1,63 @@ +/* + @copyright Steve Keen 2021 + @author Janak Porwal + This file is part of Minsky. + + Minsky is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Minsky is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Minsky. If not, see . +*/ + +#ifndef WINDOW_INFORMATION_H +#define WINDOW_INFORMATION_H + +#include +#include + +namespace minsky +{ + class WindowInformation + { + unsigned long parentWindowId; + unsigned long childWindowId; + + Display* display; // Weak reference, returned by system + ecolab::cairo::SurfacePtr childSurface; + + public: + int childWidth; + int childHeight; + int offsetLeft; + int offsetTop; + + XWindowAttributes wAttr; + unsigned long getChildWindowId(); + Display* getDisplay(); + + public: + + + WindowInformation(); + ~WindowInformation(); + WindowInformation(unsigned long parentWin, int left, int top, int cWidth, int cHeight); + void initialize(unsigned long parentWin, int left, int top, int cWidth, int cHeight); + void initialize(const WindowInformation &other); + + ecolab::cairo::SurfacePtr getSurface(); + + void copyFrom(const WindowInformation &other); + WindowInformation(const WindowInformation&)=delete; + void operator=(const WindowInformation&)=delete; + }; +} // namespace minsky + +#endif From 2be7a381f94fb3df3c56d777212217e5359115ba Mon Sep 17 00:00:00 2001 From: Janak Porwal Date: Tue, 23 Feb 2021 15:36:45 +0530 Subject: [PATCH 8/9] Pass parentWindowId and offsets etc with each call to renderFrame --- model/renderNativeWindow.cc | 36 ++++-------------------------------- model/renderNativeWindow.h | 15 +++------------ model/windowInformation.cc | 22 +++------------------- model/windowInformation.h | 8 +------- 4 files changed, 11 insertions(+), 70 deletions(-) diff --git a/model/renderNativeWindow.cc b/model/renderNativeWindow.cc index 6a3c4b0f1..8b38928d1 100644 --- a/model/renderNativeWindow.cc +++ b/model/renderNativeWindow.cc @@ -79,34 +79,12 @@ namespace minsky } #endif - RenderNativeWindow::~RenderNativeWindow() + void RenderNativeWindow::renderFrame(unsigned long parentWindowId, int offsetLeft, int offsetTop, int childWidth, int childHeight) { - if (this->winInfo) - { - delete this->winInfo; - } - } + if (!winInfoPtr) + winInfoPtr=std::make_shared(parentWindowId, offsetLeft, offsetTop, childWidth, childHeight); - RenderNativeWindow::RenderNativeWindow() - { - this->winInfo = new WindowInformation(); - } - - RenderNativeWindow &RenderNativeWindow::operator=(const RenderNativeWindow &a) - { - //TODO:: I expected this to be the "new" instance with uninitialized winInfo and a to have the previous winInfo. - // However, it seems to be the other way round in practice --- Janak - a.winInfo->initialize(*(this->winInfo)); - } - - RenderNativeWindow::RenderNativeWindow(const RenderNativeWindow &a) - { - // cout << "Copy constructor was called" << endl; - } - - void RenderNativeWindow::renderFrame() - { - auto tmp = createNativeWindowSurface(*winInfo); + auto tmp = createNativeWindowSurface(*winInfoPtr); //TODO:: Review if this paint (below 3 lines) is really needed with each frame cairo_move_to(tmp->cairo(), 0, 0); @@ -118,12 +96,6 @@ namespace minsky tmp.swap(surface); } - void RenderNativeWindow::initializeNativeWindow(unsigned long parentWindowId, int offsetLeft, int offsetTop, int childWidth, int childHeight) { - //std::cout << parentWindowId << "::" << offsetLeft << "::" << offsetTop << "::" << childWidth << "::" << childHeight << std::endl; - winInfo->initialize(parentWindowId, offsetLeft, offsetTop, childWidth, childHeight); - //std::cout << "Child window id:: " << winInfo->getChildWindowId() << std::endl; - } - void RenderNativeWindow::resizeWindow(int offsetLeft, int offsetTop, int childWidth, int childHeight) { // TODO:: To be implemented... need to recreate child window diff --git a/model/renderNativeWindow.h b/model/renderNativeWindow.h index 1106678b7..979996b66 100644 --- a/model/renderNativeWindow.h +++ b/model/renderNativeWindow.h @@ -29,20 +29,11 @@ namespace minsky { private: CLASSDESC_ACCESS(RenderNativeWindow); - // std::shared_ptr winInfoPtr; // TODO:: cannot get things to work with this - WindowInformation* winInfo; + std::shared_ptr winInfoPtr; - public: - - RenderNativeWindow(); - ~RenderNativeWindow(); - RenderNativeWindow& operator=(const RenderNativeWindow &a); - RenderNativeWindow(const RenderNativeWindow &a); - - - void initializeNativeWindow(unsigned long parentWindowId, int offsetLeft, int offsetTop, int childWidth, int childHeight); + public: void resizeWindow(int offsetLeft, int offsetTop, int childWidth, int childHeight); - void renderFrame(); + void renderFrame(unsigned long parentWindowId, int offsetLeft, int offsetTop, int childWidth, int childHeight); }; } // namespace minsky diff --git a/model/windowInformation.cc b/model/windowInformation.cc index 63a87dd3d..ae2061627 100644 --- a/model/windowInformation.cc +++ b/model/windowInformation.cc @@ -38,11 +38,6 @@ namespace minsky throw runtime_error(errorMessage); } #endif - - WindowInformation::WindowInformation() - { - } - unsigned long WindowInformation::getChildWindowId() { return childWindowId; @@ -59,12 +54,12 @@ namespace minsky XDestroyWindow(display, childWindowId); } - void WindowInformation::initialize(const WindowInformation &other) + ecolab::cairo::SurfacePtr WindowInformation::getSurface() { - this->initialize(other.parentWindowId, other.offsetLeft, other.offsetTop, other.childWidth, other.childHeight); + return childSurface; } - void WindowInformation::initialize(unsigned long parentWin, int left, int top, int cWidth, int cHeight) + WindowInformation::WindowInformation(unsigned long parentWin, int left, int top, int cWidth, int cHeight) { parentWindowId = parentWin; offsetLeft = left; @@ -96,15 +91,4 @@ namespace minsky XMapWindow(display, childWindowId); // std::cout << "We got child window id = " << childWindowId << std::endl; } - - ecolab::cairo::SurfacePtr WindowInformation::getSurface() - { - return childSurface; - } - - WindowInformation::WindowInformation(unsigned long parentWin, int left, int top, int cWidth, int cHeight) - { - this->initialize(parentWin, left, top, cWidth, cHeight); - } - } // namespace minsky diff --git a/model/windowInformation.h b/model/windowInformation.h index 3105b5886..e3757a6bc 100644 --- a/model/windowInformation.h +++ b/model/windowInformation.h @@ -44,17 +44,11 @@ namespace minsky Display* getDisplay(); public: - - - WindowInformation(); ~WindowInformation(); WindowInformation(unsigned long parentWin, int left, int top, int cWidth, int cHeight); - void initialize(unsigned long parentWin, int left, int top, int cWidth, int cHeight); - void initialize(const WindowInformation &other); - + ecolab::cairo::SurfacePtr getSurface(); - void copyFrom(const WindowInformation &other); WindowInformation(const WindowInformation&)=delete; void operator=(const WindowInformation&)=delete; }; From ac555875ebe2f9f750ad647850525bafea9b5273 Mon Sep 17 00:00:00 2001 From: Janak Porwal Date: Tue, 23 Feb 2021 15:56:31 +0530 Subject: [PATCH 9/9] Moved surface and all window bookkeeping logic to WindowInformation --- model/renderNativeWindow.cc | 44 ++--------------------- model/windowInformation.cc | 72 +++++++++++++++++++++++++++---------- model/windowInformation.h | 2 ++ 3 files changed, 59 insertions(+), 59 deletions(-) diff --git a/model/renderNativeWindow.cc b/model/renderNativeWindow.cc index 8b38928d1..5d557bb1f 100644 --- a/model/renderNativeWindow.cc +++ b/model/renderNativeWindow.cc @@ -30,29 +30,6 @@ Please especially review the lifecycle (constructors, desctructors and copy cons #include "windowInformation.h" #include "minsky_epilogue.h" -#if defined(CAIRO_HAS_XLIB_SURFACE) && !defined(MAC_OSX_TK) -#include -#include -#endif - -#if defined(CAIRO_HAS_WIN32_SURFACE) && !defined(__CYGWIN__) -#define USE_WIN32_SURFACE -#endif - -#ifdef _WIN32 -#undef Realloc -#include -#include -#ifdef USE_WIN32_SURFACE -#include -#endif -#endif - -#if defined(MAC_OSX_TK) -#include -#include -#include "getContext.h" -#endif #include #include @@ -62,29 +39,14 @@ using namespace ecolab; namespace minsky { -#ifdef USE_WIN32_SURFACE - inline cairo::SurfacePtr createNativeWindowSurface(WindowInformation &winInfo) - { /* TODO */ - } -#elif defined(MAC_OSX_TK) - inline cairo::SurfacePtr createNativeWindowSurface(WindowInformation &winInfo) - { /* TODO */ - } -#else - inline cairo::SurfacePtr createNativeWindowSurface(WindowInformation &wi) - { - cairo::SurfacePtr childSurface(new cairo::Surface(cairo_xlib_surface_create(wi.getDisplay(), wi.getChildWindowId(), wi.wAttr.visual, wi.childWidth, wi.childHeight), wi.childWidth, wi.childHeight)); - cairo_surface_set_device_offset(childSurface->surface(), -wi.wAttr.x, -wi.wAttr.y); - return childSurface; - } -#endif - void RenderNativeWindow::renderFrame(unsigned long parentWindowId, int offsetLeft, int offsetTop, int childWidth, int childHeight) { if (!winInfoPtr) winInfoPtr=std::make_shared(parentWindowId, offsetLeft, offsetTop, childWidth, childHeight); - auto tmp = createNativeWindowSurface(*winInfoPtr); + auto tmp = winInfoPtr->getSurface(); + + //auto tmp = createNativeWindowSurface(*winInfoPtr); //TODO:: Review if this paint (below 3 lines) is really needed with each frame cairo_move_to(tmp->cairo(), 0, 0); diff --git a/model/windowInformation.cc b/model/windowInformation.cc index ae2061627..0963884dc 100644 --- a/model/windowInformation.cc +++ b/model/windowInformation.cc @@ -23,11 +23,36 @@ #include #include +#if defined(CAIRO_HAS_XLIB_SURFACE) && !defined(MAC_OSX_TK) +#include +#include +#endif + +#if defined(CAIRO_HAS_WIN32_SURFACE) && !defined(__CYGWIN__) +#define USE_WIN32_SURFACE +#endif + +#ifdef _WIN32 +#undef Realloc +#include +#include +#ifdef USE_WIN32_SURFACE +#include +#endif +#endif + +#if defined(MAC_OSX_TK) +#include +#include +#include "getContext.h" +#endif + using namespace std; using namespace ecolab; namespace minsky { + #ifdef USE_WIN32_SURFACE #elif defined(MAC_OSX_TK) #else @@ -38,27 +63,41 @@ namespace minsky throw runtime_error(errorMessage); } #endif - unsigned long WindowInformation::getChildWindowId() - { + + unsigned long WindowInformation::getChildWindowId() { return childWindowId; } - Display *WindowInformation::getDisplay() - { + Display *WindowInformation::getDisplay() { return display; } - WindowInformation::~WindowInformation() - { + WindowInformation::~WindowInformation() { childSurface.reset(); XDestroyWindow(display, childWindowId); } - ecolab::cairo::SurfacePtr WindowInformation::getSurface() - { + ecolab::cairo::SurfacePtr WindowInformation::getSurface() { return childSurface; } + void WindowInformation::createSurface(){ +#ifdef USE_WIN32_SURFACE + { + /* TODO */ + } +#elif defined(MAC_OSX_TK) + + { + /* TODO */ + } +#else + {childSurface.reset(new cairo::Surface(cairo_xlib_surface_create(getDisplay(), getChildWindowId(), wAttr.visual, childWidth, childHeight), childWidth, childHeight)); + cairo_surface_set_device_offset(childSurface->surface(), -wAttr.x, -wAttr.y); +} +#endif + } + WindowInformation::WindowInformation(unsigned long parentWin, int left, int top, int cWidth, int cHeight) { parentWindowId = parentWin; @@ -74,21 +113,18 @@ namespace minsky childWidth = wAttr.width - offsetLeft; childHeight = wAttr.height - offsetTop; - // Todo:: currently width, height parameters are not getting passed properly - // Eventually, we need those in order to ensure we don't need to worry about - // paddings, scrollbars etc - if (cWidth > 0) - { + // TODO:: Take care of scrollbars + + if (cWidth > 0) { childWidth = min(childWidth, cWidth); } - if (cHeight > 0) - { + + if (cHeight > 0) { childHeight = min(childHeight, cHeight); } - // std::cout << childWidth << "::" << childHeight << "::" << offsetLeft << "::" << offsetTop << std::endl; childWindowId = XCreateSimpleWindow(display, parentWin, offsetLeft, offsetTop, childWidth, childHeight, 0, 0, 0); //TODO:: Should we pass visual and attributes at the end? XMapWindow(display, childWindowId); - // std::cout << "We got child window id = " << childWindowId << std::endl; + createSurface(); } -} // namespace minsky +} // namespace minsky \ No newline at end of file diff --git a/model/windowInformation.h b/model/windowInformation.h index e3757a6bc..fa9b8c784 100644 --- a/model/windowInformation.h +++ b/model/windowInformation.h @@ -33,6 +33,8 @@ namespace minsky Display* display; // Weak reference, returned by system ecolab::cairo::SurfacePtr childSurface; + private: + void createSurface(); public: int childWidth; int childHeight;