aboutsummaryrefslogtreecommitdiffstats
path: root/embed/xulrunner/src/EmbedWindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'embed/xulrunner/src/EmbedWindow.cpp')
-rw-r--r--embed/xulrunner/src/EmbedWindow.cpp467
1 files changed, 467 insertions, 0 deletions
diff --git a/embed/xulrunner/src/EmbedWindow.cpp b/embed/xulrunner/src/EmbedWindow.cpp
new file mode 100644
index 000000000..15c098f28
--- /dev/null
+++ b/embed/xulrunner/src/EmbedWindow.cpp
@@ -0,0 +1,467 @@
+/*
+ * Copyright © Christopher Blizzard
+ * Copyright © 2006 Christian Persch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------------------------
+ * Derived from Mozilla.org code, which had the following attributions:
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright © Christopher Blizzard. All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright © 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Christopher Blizzard <blizzard@mozilla.org>
+ * ---------------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#include <mozilla-config.h>
+#include <config.h>
+
+#include <nsCWebBrowser.h>
+#include <nsIComponentManager.h>
+#include <nsComponentManagerUtils.h>
+#include <nsIDocShellTreeItem.h>
+#include "nsIWidget.h"
+
+#include "EmbedWindow.h"
+#include "GeckoBrowser.h"
+
+#include "gecko-embed-signals.h"
+
+GtkWidget *EmbedWindow::sTipWindow = nsnull;
+
+EmbedWindow::EmbedWindow(void)
+{
+ mOwner = nsnull;
+ mVisibility = PR_FALSE;
+ mIsModal = PR_FALSE;
+}
+
+EmbedWindow::~EmbedWindow(void)
+{
+ ExitModalEventLoop(PR_FALSE);
+}
+
+nsresult
+EmbedWindow::Init(GeckoBrowser *aOwner)
+{
+ // save our owner for later
+ mOwner = aOwner;
+
+ // create our nsIWebBrowser object and set up some basic defaults.
+ mWebBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID);
+ if (!mWebBrowser)
+ return NS_ERROR_FAILURE;
+
+ mWebBrowser->SetContainerWindow(static_cast<nsIWebBrowserChrome *>(this));
+
+ nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(mWebBrowser);
+ item->SetItemType(nsIDocShellTreeItem::typeContentWrapper);
+
+ return NS_OK;
+}
+
+nsresult
+EmbedWindow::CreateWindow(void)
+{
+ nsresult rv;
+ GtkWidget *ownerAsWidget = GTK_WIDGET(mOwner->mOwningWidget);
+
+ // Get the base window interface for the web browser object and
+ // create the window.
+ mBaseWindow = do_QueryInterface(mWebBrowser);
+ rv = mBaseWindow->InitWindow(GTK_WIDGET(mOwner->mOwningWidget),
+ nsnull,
+ 0, 0,
+ ownerAsWidget->allocation.width,
+ ownerAsWidget->allocation.height);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = mBaseWindow->Create();
+ if (NS_FAILED(rv))
+ return rv;
+
+ return NS_OK;
+}
+
+void
+EmbedWindow::ReleaseChildren(void)
+{
+ ExitModalEventLoop(PR_FALSE);
+
+ mBaseWindow->Destroy();
+ mBaseWindow = 0;
+ mWebBrowser = 0;
+}
+
+// nsISupports
+
+NS_IMPL_ADDREF(EmbedWindow)
+NS_IMPL_RELEASE(EmbedWindow)
+
+NS_INTERFACE_MAP_BEGIN(EmbedWindow)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome)
+ NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
+ NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus)
+ NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
+ NS_INTERFACE_MAP_ENTRY(nsITooltipListener)
+ NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
+NS_INTERFACE_MAP_END
+
+// nsIWebBrowserChrome
+
+NS_IMETHODIMP
+EmbedWindow::SetStatus(PRUint32 aStatusType, const PRUnichar *aStatus)
+{
+ switch (aStatusType) {
+ case STATUS_SCRIPT:
+ {
+ mJSStatus = aStatus;
+ g_signal_emit (mOwner->mOwningWidget, gecko_embed_signals[JS_STATUS], 0);
+ }
+ break;
+ case STATUS_SCRIPT_DEFAULT:
+ // Gee, that's nice.
+ break;
+ case STATUS_LINK:
+ {
+ mLinkMessage = aStatus;
+ g_signal_emit (mOwner->mOwningWidget, gecko_embed_signals[LINK_MESSAGE], 0);
+ }
+ break;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::GetWebBrowser(nsIWebBrowser **aWebBrowser)
+{
+ *aWebBrowser = mWebBrowser;
+ NS_IF_ADDREF(*aWebBrowser);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::SetWebBrowser(nsIWebBrowser *aWebBrowser)
+{
+ mWebBrowser = aWebBrowser;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::GetChromeFlags(PRUint32 *aChromeFlags)
+{
+ *aChromeFlags = mOwner->mChromeMask;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::SetChromeFlags(PRUint32 aChromeFlags)
+{
+ mOwner->SetChromeMask(aChromeFlags);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::DestroyBrowserWindow(void)
+{
+ // mark the owner as destroyed so it won't emit events anymore.
+ mOwner->mIsDestroyed = PR_TRUE;
+
+ g_signal_emit (mOwner->mOwningWidget, gecko_embed_signals[DESTROY_BROWSER], 0);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::SizeBrowserTo(PRInt32 aCX, PRInt32 aCY)
+{
+ g_signal_emit (mOwner->mOwningWidget, gecko_embed_signals[SIZE_TO], 0, aCX, aCY);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::ShowAsModal(void)
+{
+ mIsModal = PR_TRUE;
+ GtkWidget *toplevel;
+ toplevel = gtk_widget_get_toplevel(GTK_WIDGET(mOwner->mOwningWidget));
+ gtk_grab_add(toplevel);
+ gtk_main();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::IsWindowModal(PRBool *_retval)
+{
+ *_retval = mIsModal;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::ExitModalEventLoop(nsresult aStatus)
+{
+ if (mIsModal) {
+ GtkWidget *toplevel;
+ toplevel = gtk_widget_get_toplevel(GTK_WIDGET(mOwner->mOwningWidget));
+ gtk_grab_remove(toplevel);
+ mIsModal = PR_FALSE;
+ gtk_main_quit();
+ }
+ return NS_OK;
+}
+
+// nsIWebBrowserChromeFocus
+
+NS_IMETHODIMP
+EmbedWindow::FocusNextElement()
+{
+ GtkWidget *toplevel;
+ toplevel = gtk_widget_get_toplevel(GTK_WIDGET(mOwner->mOwningWidget));
+ if (!GTK_WIDGET_TOPLEVEL(toplevel))
+ return NS_OK;
+
+ g_signal_emit_by_name (toplevel, "move_focus", GTK_DIR_TAB_FORWARD);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::FocusPrevElement()
+{
+ GtkWidget *toplevel;
+ toplevel = gtk_widget_get_toplevel(GTK_WIDGET(mOwner->mOwningWidget));
+ if (!GTK_WIDGET_TOPLEVEL(toplevel))
+ return NS_OK;
+
+ g_signal_emit_by_name (toplevel, "move_focus", GTK_DIR_TAB_BACKWARD);
+
+ return NS_OK;
+}
+
+// nsIEmbeddingSiteWindow
+
+NS_IMETHODIMP
+EmbedWindow::SetDimensions(PRUint32 aFlags, PRInt32 aX, PRInt32 aY,
+ PRInt32 aCX, PRInt32 aCY)
+{
+ if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION &&
+ (aFlags & (nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER |
+ nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER))) {
+ return mBaseWindow->SetPositionAndSize(aX, aY, aCX, aCY, PR_TRUE);
+ }
+ else if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) {
+ return mBaseWindow->SetPosition(aX, aY);
+ }
+ else if (aFlags & (nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER |
+ nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER)) {
+ return mBaseWindow->SetSize(aCX, aCY, PR_TRUE);
+ }
+ return NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
+EmbedWindow::GetDimensions(PRUint32 aFlags, PRInt32 *aX,
+ PRInt32 *aY, PRInt32 *aCX, PRInt32 *aCY)
+{
+ if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION &&
+ (aFlags & (nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER |
+ nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER))) {
+ return mBaseWindow->GetPositionAndSize(aX, aY, aCX, aCY);
+ }
+ else if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) {
+ return mBaseWindow->GetPosition(aX, aY);
+ }
+ else if (aFlags & (nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER |
+ nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER)) {
+ return mBaseWindow->GetSize(aCX, aCY);
+ }
+ return NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
+EmbedWindow::SetFocus(void)
+{
+ // XXX might have to do more here.
+ return mBaseWindow->SetFocus();
+}
+
+NS_IMETHODIMP
+EmbedWindow::GetTitle(PRUnichar **aTitle)
+{
+ *aTitle = NS_StringCloneData(mTitle);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::SetTitle(const PRUnichar *aTitle)
+{
+ mTitle = aTitle;
+ g_signal_emit (mOwner->mOwningWidget, gecko_embed_signals[TITLE], 0);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::GetSiteWindow(void **aSiteWindow)
+{
+ GtkWidget *ownerAsWidget (GTK_WIDGET(mOwner->mOwningWidget));
+ *aSiteWindow = static_cast<void *>(ownerAsWidget);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::GetVisibility(PRBool *aVisibility)
+{
+ // Work around the problem that sometimes the window
+ // is already visible even though mVisibility isn't true
+ // yet.
+ *aVisibility = mVisibility ||
+ (!mOwner->mIsChrome &&
+ mOwner->mOwningWidget &&
+ GTK_WIDGET_MAPPED(mOwner->mOwningWidget));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::SetVisibility(PRBool aVisibility)
+{
+ // We always set the visibility so that if it's chrome and we finish
+ // the load we know that we have to show the window.
+ mVisibility = aVisibility;
+
+ // if this is a chrome window and the chrome hasn't finished loading
+ // yet then don't show the window yet.
+ if (mOwner->mIsChrome && !mOwner->mChromeLoaded)
+ return NS_OK;
+
+ g_signal_emit (mOwner->mOwningWidget, gecko_embed_signals[VISIBILITY], 0,
+ aVisibility);
+ return NS_OK;
+}
+
+// nsITooltipListener
+
+static gboolean
+tooltips_paint_window (GtkWidget *window)
+{
+ // draw tooltip style border around the text
+ gtk_paint_flat_box (window->style, window->window,
+ GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+ NULL, window, "tooltip",
+ 0, 0,
+ window->allocation.width, window->allocation.height);
+
+ return FALSE;
+}
+
+NS_IMETHODIMP
+EmbedWindow::OnShowTooltip(PRInt32 aXCoords, PRInt32 aYCoords,
+ const PRUnichar *aTipText)
+{
+ nsEmbedCString tipText;
+
+ NS_UTF16ToCString(nsEmbedString(aTipText),
+ NS_CSTRING_ENCODING_UTF8, tipText);
+
+ if (sTipWindow)
+ gtk_widget_destroy(sTipWindow);
+
+ // get the root origin for this content window
+ nsCOMPtr<nsIWidget> mainWidget;
+ mBaseWindow->GetMainWidget(getter_AddRefs(mainWidget));
+ GdkWindow *window;
+ window = static_cast<GdkWindow *>
+ (mainWidget->GetNativeData(NS_NATIVE_WINDOW));
+ gint root_x, root_y;
+ gdk_window_get_origin(window, &root_x, &root_y);
+
+ // XXX work around until I can get pink to figure out why
+ // tooltips vanish if they show up right at the origin of the
+ // cursor.
+ root_y += 10;
+
+ sTipWindow = gtk_window_new(GTK_WINDOW_POPUP);
+ gtk_widget_set_app_paintable(sTipWindow, TRUE);
+ gtk_window_set_policy(GTK_WINDOW(sTipWindow), FALSE, FALSE, TRUE);
+ // needed to get colors + fonts etc correctly
+ gtk_widget_set_name(sTipWindow, "gtk-tooltips");
+
+ // set up the popup window as a transient of the widget.
+ GtkWidget *toplevel_window;
+ toplevel_window = gtk_widget_get_toplevel(GTK_WIDGET(mOwner->mOwningWidget));
+ if (!GTK_WINDOW(toplevel_window)) {
+ NS_ERROR("no gtk window in hierarchy!\n");
+ return NS_ERROR_FAILURE;
+ }
+ gtk_window_set_transient_for(GTK_WINDOW(sTipWindow),
+ GTK_WINDOW(toplevel_window));
+
+ // realize the widget
+ gtk_widget_realize(sTipWindow);
+
+ g_signal_connect (G_OBJECT(sTipWindow), "expose-event",
+ G_CALLBACK(tooltips_paint_window), NULL);
+
+ // set up the label for the tooltip
+ GtkWidget *label = gtk_label_new(tipText.get());
+ // wrap automatically
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+ gtk_container_add(GTK_CONTAINER(sTipWindow), label);
+ gtk_container_set_border_width(GTK_CONTAINER(sTipWindow), 4);
+ // set the coords for the widget
+ gtk_widget_set_uposition(sTipWindow, aXCoords + root_x,
+ aYCoords + root_y);
+
+ // and show it.
+ gtk_widget_show_all(sTipWindow);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::OnHideTooltip(void)
+{
+ if (sTipWindow)
+ gtk_widget_destroy(sTipWindow);
+ sTipWindow = NULL;
+ return NS_OK;
+}
+
+// nsIInterfaceRequestor
+
+NS_IMETHODIMP
+EmbedWindow::GetInterface(const nsIID &aIID, void** aInstancePtr)
+{
+ nsresult rv;
+
+ rv = QueryInterface(aIID, aInstancePtr);
+
+ // pass it up to the web browser object
+ if (NS_FAILED(rv) || !*aInstancePtr) {
+ nsCOMPtr<nsIInterfaceRequestor> ir = do_QueryInterface(mWebBrowser);
+ return ir->GetInterface(aIID, aInstancePtr);
+ }
+
+ return rv;
+}