
Thu, 02/18/2016 - 14:11
Hi,
I've been doing some research on minimal widget toolkits and I have landed on gtk+ 3.0 and IUP (http://webserver2.tecgraf.puc-rio.br/iup/)
The thing that has me baffled is how exactly opencascade gets to draw in an embedded widget.
According to the docs, setting up a viewer for 6.9.1 goes somthing along these lines:
Handle(Aspect_DisplayConnection) aDisplayConnection = new Aspect_DisplayConnection();
Handle(OpenGl_GraphicDriver) myGraphicDriver = new OpenGl_GraphicDriver(aDisplayConnection);Handle_WNT_Window wind = new WNT_Window((Aspect_Handle) myHWND );
Handle_V3d_Viewer mViewer;
mViewer = new V3d_Viewer(myGraphicDriver, (short* const)"viewer");
Handle_V3d_View mView;
mView = mViewer->CreateView();
mView->SetWindow(wind);
if (!wind->IsMapped()) wind->Map();
The thing that baffles me is the "new WNT_Window((Aspect_Handle) myHWND );"
myHWND refers to a HWND window handle in windows. When I set up a minimal example using oldskool windows.h this is trivial.
However, using IUP, the HWND attribute of an embedded IUP widget is read-only. Hence the "new WNT_Window" call will crash the app.
For now I have abandoned researching IUP, a shame really, it balances looks and minimalism really well. If anyone could give a hint on how to proceed I would appreciate it.
The read-only HWND in IUP is why I looked a little further, gtk+ 3 is less minimal than IUP, but not as macro-heavy as wxwindows so I thought I would give it a go.
Using gtk+3 I can get a hold of a HWND using what feels like a convoluted route:
HWND myHWND = gdk_win32_window_get_impl_hwnd (gtk_widget_get_window (MainWindow));
"gdk_win32_window_get_impl_hwnd" is poorly documented, I only found out about it by grepping through the gdk headers seraching for "hwnd".
It does work, though very briefly. The window starts, I can see the MakeBottle example I added and the viewerwidget turns gray, like gtk draws over it or deletes the opencascade viewer.
Luckily, there is an old GTK+ 2.0 example, but I soon realised gtk+ 2.0 and gtk+ 3.0 are really different.
What I think is strange is that in the gtk+ 2.0 example steps are taken to implement opengl. It sets "gl capability" on the gtk+2.0 widget that will receive the opencascade WNT_Window (if that is the right way to phrase it) :
MainWindow = create_MainWindow ();
GtkWidget* draw = lookup_widget(MainWindow, "drawingarea1");
/* Set OpenGL-capability to the widget. */
gtk_widget_set_gl_capability (draw,
glconfig,
NULL,
TRUE,
GDK_GL_RGBA_TYPE);
In gtk+ 3.0 this behavior is depreciated. But mainly I am confused by why these steps are taken. How are the HWND and gl capability linked ?
Right now the source for my gtk+3.0 minimal working example is:
#include "win32_handmade.h"
#include "MakeBottle.h"
#include <gtk/gtk.h>
#include <gdk/gdkwin32.h>#include <V3d_View.hxx>
#include <Graphic3d_GraphicDriver.hxx>
#include <Handle_Graphic3d_GraphicDriver.hxx>
#include <Aspect_Handle.hxx>
#include <Aspect_DisplayConnection.hxx>
#include <Handle_OpenGl_GraphicDriver.hxx>
#include <OpenGl_GraphicDriver.hxx>
#include <WNT_Window.hxx>
#include <AIS_InteractiveContext.hxx>
#include <TopoDS_Shape.hxx>
#include <AIS_Shape.hxx>int main( int argc,
char *argv[] )
{
gtk_init (&argc, &argv);GtkWidget *MainWindow;
GtkWidget *drawingarea1;
GtkWidget *vbox1;
MainWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect(G_OBJECT(MainWindow), "destroy", G_CALLBACK(gtk_main_quit), 0);
gtk_widget_show(MainWindow);vbox1 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 1);
gtk_widget_set_name (vbox1, "vbox1");
gtk_widget_show (vbox1);
gtk_container_add (GTK_CONTAINER (MainWindow), vbox1);
drawingarea1 = gtk_drawing_area_new ();
gtk_widget_set_name (drawingarea1, "drawingarea1");
gtk_widget_show (drawingarea1);
gtk_box_pack_start (GTK_BOX (vbox1), drawingarea1, TRUE, TRUE, 0);HWND wnd = gdk_win32_window_get_impl_hwnd (gtk_widget_get_window (drawingarea1));
Handle(Aspect_DisplayConnection) aDisplayConnection = new Aspect_DisplayConnection();
Handle(OpenGl_GraphicDriver) myGraphicDriver = new OpenGl_GraphicDriver(aDisplayConnection);
Handle_WNT_Window wind = new WNT_Window((Aspect_Handle) wnd);Handle_V3d_Viewer mViewer;
mViewer = new V3d_Viewer(myGraphicDriver, (short* const)"viewer");
mViewer->SetDefaultLights();
mViewer->SetLightOn();
Handle_V3d_View mView;
mView = mViewer->CreateView();
mView->SetWindow(wind);
if (!wind->IsMapped()) wind->Map();mView->SetBackgroundColor(Quantity_NOC_GRAY12);
mView->MustBeResized();
mView->TriedronDisplay(Aspect_TOTP_LEFT_LOWER, Quantity_NOC_GOLD, 0.08, V3d_ZBUFFER);
// Create AISInteractiveContext
Handle_AIS_InteractiveContext mContext;
mContext = new AIS_InteractiveContext(mViewer);// Set up lights etc
mContext->SetDisplayMode(AIS_Shaded);
TopoDS_Shape aBottle=MakeBottle(50,70,30);
Handle(AIS_Shape) AISBottle=new AIS_Shape(aBottle);
mContext->SetMaterial(AISBottle,Graphic3d_NOM_GOLD);
mContext->SetDisplayMode(AISBottle,1,Standard_False);
mContext->Display(AISBottle, Standard_False);
mContext->SetCurrentObject(AISBottle,Standard_False);mView->Redraw();
gtk_main ();
return 0;
}
Any insight on how to proceed with GTK+3 would be appreciated,
Sander
Sun, 02/21/2016 - 13:45
Turns out, opencascade and GTK+ 3.0 proved to be less than trivial.
GTK+ 3 has a double buffered draw cycle which results in gtk painting over the viewer in every frame. Turning off double buffered used to be possible, but is now depreciated.I'll post a question on the gtk boards, maybe I can interfere in the draw cycle, but like I said, it will be non-trivial.