Page 1 of 1

"Embedding" native GTK widget

Posted: Fri May 22, 2009 7:22 am
by upCASE
Hi all!

I do have some trouble for a small personal project I'm working on. I wrote kind of a "yet another image/video/archive/whatever" viewer/player and I want to extend it a little, so that it can play swf files.

For that I tried different things (no probs on Windows, as I could embed Adobes player I guess) on Linux using wxGTK. At first I thought I could use gnash, as it has some option to redirect the output to a give XID, but I couldn't get it working (tried the same with mplayer a while ago and had no problems there). Now I'm using swfdec.

The problem is that I want to have a wxPanel/wxControl as the parent window for a GtkWidget that swfdec creates and uses for output. So far I wasn't able to properly embed it. I create the widget and use it like

Code: Select all

widget = swfdec_gtk_widget_new (NULL);
gtk_container_add (GTK_CONTAINER(m_wxwindow), widget);
gtk_widget_show_all (m_wxwindow); 
Now, the widget is displayed and I can set and play the files, but it doesn't react to size changes and other stuff properly. I have handler for size events and resize it manually, as well as a handler for relaying key events, but I thought this could be easier.

Has anybody ever had success in embedding a GtkWidget to a wxWindow? If yes, how? If no, why not?

I'm open for any suggestion.

Posted: Fri May 22, 2009 1:10 pm
by upCASE
Hi all!
Ok, solved.

I created my own subclass derived from wxControl and set the m_widget pointer to be the newly created one from swfdec. Works charming now.

Re: "Embedding" native GTK widget

Posted: Fri Aug 05, 2011 1:43 pm
by astifter
Terribly sorry, I know this is an old post but is it possible to get the source code for your working example.

I'm pretty much stuck right now with my embedded GtkWidget....

Re: "Embedding" native GTK widget

Posted: Mon Aug 08, 2011 11:41 am
by astifter
Okay, I finally solved this myself by copying the code from wxStaticText and modifying it as appropriate, just to solve this once and for all here is the complete code:

wxWebKitCtrl.h

Code: Select all

#ifndef _WX_WEBKITCTRL_H_
#define _WX_WEBKITCTRL_H_

#include "wx/defs.h"
#include "wx/control.h"
#include <gtk/gtk.h>
#include <webkit/webkit.h>

extern WXDLLEXPORT_DATA(const wxChar) wxWebKitCtrlNameStr[];

class WXDLLEXPORT wxWebKitCtrlBase : public wxControl
{
public:
    wxWebKitCtrlBase() { }

    // overriden base virtuals
    virtual bool AcceptsFocus() const { return false; }
    virtual bool HasTransparentBackground() { return false; }

private:
    DECLARE_NO_COPY_CLASS(wxWebKitCtrlBase)
};

class WXDLLIMPEXP_CORE wxWebKitCtrl : public wxControl
{
public:
    wxWebKitCtrl();
    wxWebKitCtrl(wxWindow *parent,
                 wxWindowID id,
                 const wxString &label,
                 const wxPoint &pos = wxDefaultPosition,
                 const wxSize &size = wxDefaultSize,
                 long style = 0,
                 const wxString &name = wxWebKitCtrlNameStr );

    bool Create(wxWindow *parent,
                wxWindowID id,
                const wxString &label,
                const wxPoint &pos = wxDefaultPosition,
                const wxSize &size = wxDefaultSize,
                long style = 0,
                const wxString &name = wxWebKitCtrlNameStr );

    void SetPageSource( const wxString &label );
    void IncreaseTextSize();
    void DecreaseTextSize();

    static wxVisualAttributes
    GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL);

    // implementation
    // --------------

protected:
    virtual void DoSetSize(int x, int y,
                           int width, int height,
                           int sizeFlags = wxSIZE_AUTO);

    virtual wxSize DoGetBestSize() const;

    WebKitWebView *m_webview;

    DECLARE_DYNAMIC_CLASS(wxWebKitCtrl)
};

#endif // _WX_WEBKITCTRL_H_

wxWebKitCtrl.cpp

Code: Select all

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#include "wxWebKitCtrl.h"
#include "private.h"

#include "gdk/gdk.h"
#include "gtk/gtk.h"

extern "C"
void wxgtk_window_size_request_callback(GtkWidget *widget,
                                        GtkRequisition *requisition,
                                        wxWindow *win);

extern WXDLLEXPORT_DATA(const wxChar) wxWebKitCtrlNameStr[] = wxT("webkitCtrl");

//-----------------------------------------------------------------------------
// wxWebKitCtrl
//-----------------------------------------------------------------------------

IMPLEMENT_DYNAMIC_CLASS(wxWebKitCtrl,wxControl)

wxWebKitCtrl::wxWebKitCtrl()
{
}

wxWebKitCtrl::wxWebKitCtrl(wxWindow *parent,
                           wxWindowID id,
                           const wxString &label,
                           const wxPoint &pos,
                           const wxSize &size,
                           long style,
                           const wxString &name)
{
  Create( parent, id, label, pos, size, style, name );
}

bool wxWebKitCtrl::Create(wxWindow *parent,
                          wxWindowID id,
                          const wxString &label,
                          const wxPoint &pos,
                          const wxSize &size,
                          long style,
                          const wxString &name )
{
    m_needParent = TRUE;

    if (!PreCreation( parent, pos, size ) ||
        !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
    {
        wxFAIL_MSG( wxT("wxWebKitCtrl creation failed") );
        return FALSE;
    }

    m_webview = WEBKIT_WEB_VIEW(webkit_web_view_new());
    m_widget = GTK_WIDGET(m_webview);
    SetPageSource(label);

    m_parent->DoAddChild( this );

    PostCreation(size);

    return TRUE;
}

void wxWebKitCtrl::SetPageSource( const wxString &label )
{
    wxCHECK_RET( m_widget != NULL, wxT("invalid static text") );

    wxCharBuffer wx_charbuffer = label.mb_str();
    char *cstr = wx_charbuffer.data();
    wx_charbuffer.release();

    webkit_web_view_load_string(m_webview, (const gchar *)cstr, NULL, NULL, 0);

    free(cstr);

    // adjust the label size to the new label unless disabled
    if ( !HasFlag(wxST_NO_AUTORESIZE) )
    {
        InvalidateBestSize();
        SetSize( GetBestSize() );
    }
}

void wxWebKitCtrl::IncreaseTextSize()
{
    gfloat newzoom = webkit_web_view_get_zoom_level( m_webview ) * 1.1;
    webkit_web_view_set_zoom_level( m_webview, newzoom );
}

void wxWebKitCtrl::DecreaseTextSize()
{
    gfloat newzoom = webkit_web_view_get_zoom_level( m_webview ) / 1.1;
    webkit_web_view_set_zoom_level( m_webview, newzoom );
}

void wxWebKitCtrl::DoSetSize(int x, int y,
                           int width, int height,
                           int sizeFlags )
{
    wxControl::DoSetSize( x, y, width, height, sizeFlags );
}

wxSize wxWebKitCtrl::DoGetBestSize() const
{
    // Do not return any arbitrary default value...
    wxASSERT_MSG( m_widget, wxT("wxWebKitCtrl::DoGetBestSize called before creation") );

    GtkRequisition req;
    req.width = -1;
    req.height = -1;
    (* GTK_WIDGET_CLASS( GTK_OBJECT_GET_CLASS(m_widget) )->size_request )
        (m_widget, &req );

    // Adding 1 to width to workaround GTK sometimes wrapping the text needlessly
    return wxSize (req.width+1, req.height);
}

// static
wxVisualAttributes
wxWebKitCtrl::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
{
    return GetDefaultAttributesFromGTKWidget(gtk_label_new);
}

Re: "Embedding" native GTK widget

Posted: Mon Aug 08, 2011 12:10 pm
by upCASE
Hi!
Thanks for posting your code.
I'm terribly sorry, but I simply didn't pay attention to your posting, otherwise I would have answered earlier.

Re: "Embedding" native GTK widget

Posted: Mon Aug 08, 2011 12:31 pm
by astifter
No worries, when I started to tackle this problem methodically today it was quite easy. Was too tired on Friday I guess.

I have updated the post slightly since there was still an encoding problem with the HTML output, is there a sort of WIKI to post the code snippets too? I guess this class is currently the easiest way to incooperate a proper HTML view into a wxWidgets application.