Understanding WNT_Window, minimal working example in windows using IUP or GTK+ 3

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

sander boer's picture

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.