Creating child window for rendering#285
Creating child window for rendering#285highperformancecoder merged 9 commits intohighperformancecoder:RESTService-branchfrom
Conversation
model/renderNativeWindow.cc
Outdated
| inline cairo::SurfacePtr nativeWindowSurface(unsigned long window) | ||
|
|
||
| inline cairo::SurfacePtr createNativeWindowSurface(WindowInformation *wi) |
There was a problem hiding this comment.
There's no good reason to pass this as a pointer. Better to use a reference.
model/renderNativeWindow.h
Outdated
| { | ||
| public: | ||
| void renderToNativeWindow(unsigned long window); | ||
| /* Perhaps needs to be public for some auto-binding code */ |
There was a problem hiding this comment.
Definitely not. If you're managing raw pointers in this way (new in constructor/delete in destructor), then the actual pointer must be private, and the copy operations must be deleted. But most classes in Minsky need to be DCAS (default constructible, copy constructible, assignable and serialisable), so you won't get very far with this strategy.
If you do need pointers (I'm not sure you really need them here, mind you), then using smart pointers is the smart thing to do, as all these issues have been thought out for you. For example, std::shared_ptr is DCAS, and std::unique_ptr is nearly so.
model/renderNativeWindow.cc
Outdated
| cout << "Delete called for window information" << endl; | ||
| } | ||
|
|
||
| void WindowInformation::initialize(unsigned long parentWin, int left, int top, int cWidth, int cHeight) |
There was a problem hiding this comment.
This should really be implemented in the constructor (RAII and all that).
model/renderNativeWindow.cc
Outdated
| void WindowInformation::copy(WindowInformation *winInfo) | ||
| { | ||
| this->parentWindowId = winInfo->parentWindowId; | ||
| this->childWindowId = winInfo->childWindowId; |
There was a problem hiding this comment.
childWindowId is managing resources in just the same way as a pointer does, so this line leaks resources. The proper way to solve this is to apply RAII.
model/renderNativeWindow.h
Outdated
| int offsetTop; | ||
| Display* display; | ||
| XWindowAttributes wAttr; | ||
| ecolab::cairo::SurfacePtr *childSurface; // TODO:: Review right way to store surface ptr |
There was a problem hiding this comment.
A SurfacePtr is a smart pointer - basically a std::shared_ptr IIRC. Taking a pointer to it will almost invariably lead to resource leaks and object lifetime problems.
model/renderNativeWindow.h
Outdated
| int childHeight; | ||
| int offsetLeft; | ||
| int offsetTop; | ||
| Display* display; |
There was a problem hiding this comment.
Because of the problems pointers create, it is worthwhile noting that this is a weak pointer, ie ownership of the display object remains with the X11 system.
| { | ||
| auto tmp = createNativeWindowSurface(winInfo); | ||
|
|
||
| //TODO:: Review if this paint (below 3 lines) is really needed with each frame |
There was a problem hiding this comment.
My intuition is that painting the background canvas is not necessary for X11, but might be for Windows. I guess we should suck it and see.
Why not check whether windowInfo is initialised in renderNativeWindow, and initialise if not at that time? Lazy initialisation.
Yes - the SurfacePtr needs to have a shorter lifetime (only just shorter) than the child Window. So it should probably be declared after the WindowInfo to ensure it is destroyed before the child window.
Yes - lots of problems, as I identified in the comments. Please review RAII principles.
There is no need to distinguish these (it would be a mistake to do so). |
model/renderNativeWindow.cc
Outdated
| if (this->winInfo) | ||
| { | ||
| delete this->winInfo; | ||
| } |
There was a problem hiding this comment.
This still won't do. RenderNativeWindow needs to be DCAS, for Classdesc reflection reasons.
model/renderNativeWindow.cc
Outdated
| auto tmp=nativeWindowSurface(window); | ||
| //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)); |
There was a problem hiding this comment.
In C++, just because a pointer is const, doesn't mean the target of the pointer is const. It's a little counterintuitive, but you have to add extra qualifiers to the type to ensure the target is const,
Nevertheless, it is is bad form to go changing the RHS of an assignment statement - it would be totally surprising to most C++ programmers.
model/renderNativeWindow.h
Outdated
| private: | ||
| CLASSDESC_ACCESS(RenderNativeWindow); | ||
| // std::shared_ptr<WindowInformation> winInfoPtr; // TODO:: cannot get things to work with this | ||
| WindowInformation* winInfo; |
There was a problem hiding this comment.
As mentioned, RenderNativeWindow should be DCAS, in particular have valid copy and assignment operators. Best to arrange all members of RenderNativeWindow be DCAS, and then take the compiler generated copy and assignment operators - this is more scalable.
I think we have two options for making the winInfo member DCAS - the shared_ptr approach I outlined, and the no-op copy operations: both have their own set of issues and implications. Maybe other methods will work, but I can't think of any.
As for the 'S' part, a simple Exclude wrapper is sufficient.
model/windowInformation.cc
Outdated
| // 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 |
There was a problem hiding this comment.
Why wouldn't you arrange for parentWindow to be a dedicated childWindow within electron, that way there will be no scrollbars or padding involved?
model/windowInformation.h
Outdated
|
|
||
| ecolab::cairo::SurfacePtr getSurface(); | ||
|
|
||
| void copyFrom(const WindowInformation &other); |
There was a problem hiding this comment.
I don't see the implementation of this method here, but I'm concerned you're trying to introduce a copy operator in by the back door, and no correctly handling resource lifetime (like the initialize() example above).
| void renderToNativeWindow(unsigned long window); | ||
| private: | ||
| CLASSDESC_ACCESS(RenderNativeWindow); | ||
| std::shared_ptr<WindowInformation> winInfoPtr; |
There was a problem hiding this comment.
I think you will probably have to classdesc::Exclude this member.
|
Visually, the code now passes muster. You also need to for the code to pass continuous integration. Looking at the errors Travis flags, I'd say this can be dealt with by wrapping winInfoPtr in a classdesc::Exclude construct. I'll try checking out this PR branch and seeing if that does the trick. |
ac55587
into
highperformancecoder:RESTService-branch
We have created a struct
WindowInformationthat stores thechildWindowIdalong with other details like display and window attributes. This information is reused across multiple calls torenderFrame.The flow for code will be -- when minsky starts:
A call to
/minsky/canvas/initializeNativeWindowwill 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/renderFrameAs of now, we create a cairo surface with each call to
renderFrame, though I think the surface can also be reused. I tried having pointer to cairo::SurfacePtr (not sure we should have pointer to pointer) but it didn't work as expected (maybe syntax related usage issue), so for now I reverted to recreating the surface in the call torenderFramePlease especially review the lifecycle (constructors, desctructors and copy constructors) that I have defined in
renderNativeWindow.cc. I think theWindowInformationobject that is destroyed in the destructor forRenderNativeWindowcan also be reused (perhaps it can be made a static object?).Also - am not sure how to distinguish between destructor for
RenderNativeWindowthat will be called with each call to load model (or undo/redo as you mentioned), and the final call when minsky is closed.This change is