mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-05 16:46:26 +00:00
309 lines
8.7 KiB
C++
309 lines
8.7 KiB
C++
|
|
//
|
|
// What follows is a hacked version the the sample hello
|
|
// world gtk app found: http://www.gtk.org/tutorial/gtk_tut-2.html
|
|
//
|
|
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "gtkEmbed.h"
|
|
|
|
#include "nsCOMPtr.h"
|
|
#include "nsEmbedAPI.h"
|
|
#include "WebBrowserChrome.h"
|
|
#include "WindowCreator.h"
|
|
|
|
#include "nsIEventQueueService.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "nsIWindowWatcher.h"
|
|
|
|
#ifdef NS_TRACE_MALLOC
|
|
#include "nsTraceMalloc.h"
|
|
#endif
|
|
|
|
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
|
|
|
static gint io_identifier = 0;
|
|
static char *sWatcherContractID = "@mozilla.org/embedcomp/window-watcher;1";
|
|
|
|
typedef struct
|
|
{
|
|
GtkWidget *window;
|
|
GtkWidget *urlEntry;
|
|
GtkWidget *box;
|
|
GtkWidget *view;
|
|
GtkWidget *memUsageDumpBtn;
|
|
nsIWebBrowserChrome *chrome;
|
|
} MyBrowser;
|
|
|
|
|
|
void destroy( GtkWidget *widget, MyBrowser* data )
|
|
{
|
|
PRBool dontQuit;
|
|
|
|
printf("Destroying created widgets\n");
|
|
gtk_widget_destroy( data->window );
|
|
gtk_widget_destroy( data->urlEntry );
|
|
gtk_widget_destroy( data->box );
|
|
gtk_widget_destroy( data->memUsageDumpBtn );
|
|
// gtk_widget_destroy( data->view );
|
|
free (data);
|
|
|
|
dontQuit = PR_FALSE;
|
|
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(sWatcherContractID));
|
|
if (wwatch) {
|
|
nsCOMPtr<nsISimpleEnumerator> list;
|
|
wwatch->GetWindowEnumerator(getter_AddRefs(list));
|
|
if (list)
|
|
list->HasMoreElements(&dontQuit);
|
|
}
|
|
if (!dontQuit)
|
|
gtk_main_quit();
|
|
}
|
|
|
|
gint delete_event( GtkWidget *widget, GdkEvent *event, MyBrowser* data )
|
|
{
|
|
printf("Releasing chrome...");
|
|
NS_RELEASE(data->chrome);
|
|
printf("done.\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
void
|
|
dump_mem_clicked_cb(GtkButton *button, nsIWebBrowserChrome *browser)
|
|
{
|
|
g_print("dumping memory usage:\n");
|
|
system("ps -eo \"%c %z\" | grep gtkEmbed");
|
|
|
|
#ifdef NS_TRACE_MALLOC
|
|
// dump detailed information, too
|
|
NS_TraceMallocDumpAllocations("allocations.log");
|
|
#endif
|
|
}
|
|
|
|
|
|
void
|
|
url_activate_cb( GtkEditable *widget, nsIWebBrowserChrome *browser)
|
|
{
|
|
gchar *text = gtk_editable_get_chars(widget, 0, -1);
|
|
g_print("loading url %s\n", text);
|
|
if (browser)
|
|
{
|
|
nsCOMPtr<nsIWebBrowser> webBrowser;
|
|
browser->GetWebBrowser(getter_AddRefs(webBrowser));
|
|
nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(webBrowser));
|
|
if (webNav)
|
|
webNav->LoadURI(NS_ConvertASCIItoUCS2(text).GetUnicode(), nsIWebNavigation::LOAD_FLAGS_NONE);
|
|
|
|
}
|
|
g_free(text);
|
|
}
|
|
|
|
static void
|
|
handle_event_queue(gpointer data, gint source, GdkInputCondition condition)
|
|
{
|
|
nsIEventQueue *eventQueue = (nsIEventQueue *)data;
|
|
eventQueue->ProcessPendingEvents();
|
|
}
|
|
|
|
|
|
/* InitializeWindowCreator creates and hands off an object with a callback
|
|
to a window creation function. This will be used by Gecko C++ code
|
|
(never JS) to create new windows when no previous window is handy
|
|
to begin with. This is done in a few exceptional cases, like PSM code.
|
|
Failure to set this callback will only disable the ability to create
|
|
new windows under these circumstances. */
|
|
nsresult InitializeWindowCreator()
|
|
{
|
|
// create an nsWindowCreator and give it to the WindowWatcher service
|
|
WindowCreator *creatorCallback = new WindowCreator();
|
|
if (creatorCallback) {
|
|
nsCOMPtr<nsIWindowCreator> windowCreator(dont_QueryInterface(NS_STATIC_CAST(nsIWindowCreator *, creatorCallback)));
|
|
if (windowCreator) {
|
|
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(sWatcherContractID));
|
|
if (wwatch) {
|
|
wwatch->SetWindowCreator(windowCreator);
|
|
return NS_OK;
|
|
}
|
|
}
|
|
}
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
nsresult CreateBrowserWindow(PRUint32 aChromeFlags,
|
|
nsIWebBrowserChrome *aParent,
|
|
nsIWebBrowserChrome **aNewWindow)
|
|
{
|
|
WebBrowserChrome * chrome = new WebBrowserChrome();
|
|
if (!chrome)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
CallQueryInterface(NS_STATIC_CAST(nsIWebBrowserChrome *, chrome), aNewWindow);
|
|
|
|
// chrome->SetChromeFlags(aChromeFlags);
|
|
|
|
nsCOMPtr<nsIWebBrowser> newBrowser;
|
|
chrome->CreateBrowser(-1, -1, -1, -1, getter_AddRefs(newBrowser));
|
|
if (!newBrowser)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(newBrowser);
|
|
|
|
baseWindow->SetPositionAndSize(0,
|
|
0,
|
|
430,
|
|
430,
|
|
PR_TRUE);
|
|
|
|
baseWindow->SetVisibility(PR_TRUE);
|
|
|
|
GtkWidget *widget;
|
|
baseWindow->GetParentNativeWindow((void**)&widget);
|
|
|
|
gtk_widget_show (widget); // should this function do this?
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
nsresult OpenWebPage(char* url)
|
|
{
|
|
nsresult rv;
|
|
nsCOMPtr<nsIWebBrowserChrome> chrome;
|
|
|
|
rv = CreateBrowserWindow(nsIWebBrowserChrome::CHROME_ALL, nsnull,
|
|
getter_AddRefs(chrome));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
// Start loading a page
|
|
nsCOMPtr<nsIWebBrowser> newBrowser;
|
|
chrome->GetWebBrowser(getter_AddRefs(newBrowser));
|
|
nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(newBrowser));
|
|
return webNav->LoadURI(NS_ConvertASCIItoUCS2(url).GetUnicode(), nsIWebNavigation::LOAD_FLAGS_NONE);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
|
|
nativeWindow CreateNativeWindow(nsIWebBrowserChrome* chrome)
|
|
{
|
|
MyBrowser* browser = (MyBrowser*) malloc (sizeof(MyBrowser) );
|
|
if (!browser)
|
|
return nsnull;
|
|
|
|
browser->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
|
browser->urlEntry = gtk_entry_new();
|
|
browser->box = gtk_vbox_new(FALSE, 0);
|
|
browser->view = gtk_event_box_new();
|
|
browser->memUsageDumpBtn = gtk_button_new_with_label("Dump Memory Usage");
|
|
browser->chrome = chrome; // take ownership!
|
|
NS_ADDREF(chrome); // no, really take it! (released in delete_event)
|
|
|
|
if (!browser->window || !browser->urlEntry || !browser->box ||
|
|
!browser->view || !browser->memUsageDumpBtn)
|
|
return nsnull;
|
|
|
|
/* Put the box into the main window. */
|
|
gtk_container_add (GTK_CONTAINER (browser->window),browser->box);
|
|
|
|
gtk_box_pack_start(GTK_BOX(browser->box), browser->urlEntry, FALSE, FALSE, 5);
|
|
gtk_box_pack_start(GTK_BOX(browser->box), browser->view, FALSE, FALSE, 5);
|
|
gtk_box_pack_start(GTK_BOX(browser->box), browser->memUsageDumpBtn, FALSE, FALSE, 5);
|
|
|
|
gtk_signal_connect (GTK_OBJECT (browser->window),
|
|
"destroy",
|
|
GTK_SIGNAL_FUNC (destroy),
|
|
browser);
|
|
|
|
gtk_signal_connect (GTK_OBJECT (browser->window),
|
|
"delete_event",
|
|
GTK_SIGNAL_FUNC (delete_event),
|
|
browser);
|
|
|
|
gtk_signal_connect(GTK_OBJECT(browser->urlEntry),
|
|
"activate",
|
|
GTK_SIGNAL_FUNC(url_activate_cb),
|
|
chrome);
|
|
|
|
gtk_signal_connect(GTK_OBJECT(browser->memUsageDumpBtn),
|
|
"clicked",
|
|
GTK_SIGNAL_FUNC(dump_mem_clicked_cb),
|
|
chrome);
|
|
|
|
gtk_widget_set_usize(browser->view, 430, 430);
|
|
|
|
gtk_window_set_title (GTK_WINDOW (browser->window), "Embedding is Fun!");
|
|
gtk_window_set_default_size (GTK_WINDOW(browser->window), 450, 450);
|
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (browser->window), 10);
|
|
|
|
gtk_widget_realize (browser->window);
|
|
|
|
gtk_widget_show (browser->memUsageDumpBtn);
|
|
gtk_widget_show (browser->urlEntry);
|
|
gtk_widget_show (browser->box);
|
|
gtk_widget_show (browser->view);
|
|
gtk_widget_show (browser->window);
|
|
|
|
return browser->view;
|
|
}
|
|
|
|
|
|
|
|
int main( int argc, char *argv[] )
|
|
{
|
|
#ifdef NS_TRACE_MALLOC
|
|
argc = NS_TraceMallocStartupArgs(argc, argv);
|
|
#endif
|
|
|
|
char *loadURLStr;
|
|
if (argc > 1)
|
|
loadURLStr = argv[1];
|
|
else
|
|
loadURLStr = "http://www.mozilla.org/projects/embedding";
|
|
|
|
NS_InitEmbedding(nsnull, nsnull);
|
|
|
|
InitializeWindowCreator();
|
|
|
|
// set up the thread event queue
|
|
nsCOMPtr<nsIEventQueueService> eventQService = do_GetService(kEventQueueServiceCID);
|
|
if (!eventQService) return (-1);
|
|
|
|
nsCOMPtr< nsIEventQueue> eventQueue;
|
|
eventQService->GetThreadEventQueue( NS_CURRENT_THREAD, getter_AddRefs(eventQueue));
|
|
if (!eventQueue) return (-1);
|
|
|
|
io_identifier = gdk_input_add( eventQueue->GetEventQueueSelectFD(),
|
|
GDK_INPUT_READ,
|
|
handle_event_queue,
|
|
eventQueue);
|
|
|
|
/* This is called in all GTK applications. Arguments are parsed
|
|
* from the command line and are returned to the application. */
|
|
gtk_init(&argc, &argv);
|
|
|
|
|
|
if ( NS_FAILED( OpenWebPage(loadURLStr) ))
|
|
return (-1);
|
|
|
|
|
|
/* All GTK applications must have a gtk_main(). Control ends here
|
|
* and waits for an event to occur (like a key press or
|
|
* mouse event). */
|
|
gtk_main ();
|
|
|
|
gtk_input_remove(io_identifier);
|
|
|
|
printf("Cleaning up embedding\n");
|
|
NS_TermEmbedding();
|
|
|
|
#ifdef NS_TRACE_MALLOC
|
|
NS_TraceMallocShutdown();
|
|
#endif
|
|
|
|
return(0);
|
|
}
|
|
|