diff options
| author | Steve Block <steveblock@google.com> | 2011-05-06 11:45:16 +0100 |
|---|---|---|
| committer | Steve Block <steveblock@google.com> | 2011-05-12 13:44:10 +0100 |
| commit | cad810f21b803229eb11403f9209855525a25d57 (patch) | |
| tree | 29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/plugins/gtk | |
| parent | 121b0cf4517156d0ac5111caf9830c51b69bae8f (diff) | |
| download | external_webkit-cad810f21b803229eb11403f9209855525a25d57.zip external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2 | |
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/plugins/gtk')
| -rw-r--r-- | Source/WebCore/plugins/gtk/PluginDataGtk.cpp | 65 | ||||
| -rw-r--r-- | Source/WebCore/plugins/gtk/PluginPackageGtk.cpp | 176 | ||||
| -rw-r--r-- | Source/WebCore/plugins/gtk/PluginViewGtk.cpp | 901 | ||||
| -rw-r--r-- | Source/WebCore/plugins/gtk/gtk2xtbin.c | 966 | ||||
| -rw-r--r-- | Source/WebCore/plugins/gtk/gtk2xtbin.h | 158 | ||||
| -rw-r--r-- | Source/WebCore/plugins/gtk/xembed.h | 64 |
6 files changed, 2330 insertions, 0 deletions
diff --git a/Source/WebCore/plugins/gtk/PluginDataGtk.cpp b/Source/WebCore/plugins/gtk/PluginDataGtk.cpp new file mode 100644 index 0000000..705bf9a --- /dev/null +++ b/Source/WebCore/plugins/gtk/PluginDataGtk.cpp @@ -0,0 +1,65 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + Copyright (C) 2008 Collabora Ltd. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "PluginData.h" + +#include "PluginDatabase.h" +#include "PluginPackage.h" +#include <stdio.h> +namespace WebCore { + +void PluginData::initPlugins(const Page*) +{ + PluginDatabase *db = PluginDatabase::installedPlugins(); + const Vector<PluginPackage*> &plugins = db->plugins(); + + for (unsigned int i = 0; i < plugins.size(); ++i) { + PluginInfo info; + PluginPackage* package = plugins[i]; + + info.name = package->name(); + info.file = package->fileName(); + info.desc = package->description(); + + const MIMEToDescriptionsMap& mimeToDescriptions = package->mimeToDescriptions(); + MIMEToDescriptionsMap::const_iterator end = mimeToDescriptions.end(); + for (MIMEToDescriptionsMap::const_iterator it = mimeToDescriptions.begin(); it != end; ++it) { + MimeClassInfo mime; + + mime.type = it->first; + mime.desc = it->second; + mime.extensions = package->mimeToExtensions().get(mime.type); + + info.mimes.append(mime); + } + + m_plugins.append(info); + } +} + +void PluginData::refresh() +{ + PluginDatabase *db = PluginDatabase::installedPlugins(); + db->refresh(); +} + +}; diff --git a/Source/WebCore/plugins/gtk/PluginPackageGtk.cpp b/Source/WebCore/plugins/gtk/PluginPackageGtk.cpp new file mode 100644 index 0000000..a702296 --- /dev/null +++ b/Source/WebCore/plugins/gtk/PluginPackageGtk.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2008 Collabora Ltd. All rights reserved. + * Copyright (C) 2008 Nuanti Ltd. + * Copyright (C) 2008 Novell Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "PluginPackage.h" + +#include <gio/gio.h> +#include <stdio.h> + +#include "GOwnPtr.h" +#include "MIMETypeRegistry.h" +#include "NotImplemented.h" +#include "npruntime_impl.h" +#include "PluginDebug.h" +#include <wtf/text/CString.h> + +namespace WebCore { + +bool PluginPackage::fetchInfo() +{ +#if defined(XP_UNIX) + if (!load()) + return false; + + NP_GetMIMEDescriptionFuncPtr NP_GetMIMEDescription = 0; + NPP_GetValueProcPtr NPP_GetValue = 0; + + g_module_symbol(m_module, "NP_GetMIMEDescription", (void**)&NP_GetMIMEDescription); + g_module_symbol(m_module, "NP_GetValue", (void**)&NPP_GetValue); + + if (!NP_GetMIMEDescription || !NPP_GetValue) + return false; + + char* buffer = 0; + NPError err = NPP_GetValue(0, NPPVpluginNameString, &buffer); + if (err == NPERR_NO_ERROR) + m_name = buffer; + + buffer = 0; + err = NPP_GetValue(0, NPPVpluginDescriptionString, &buffer); + if (err == NPERR_NO_ERROR) { + m_description = buffer; + determineModuleVersionFromDescription(); + } + + const gchar* types = NP_GetMIMEDescription(); + if (!types) + return true; + + gchar** mimeDescs = g_strsplit(types, ";", -1); + for (int i = 0; mimeDescs[i] && mimeDescs[i][0]; i++) { + GOwnPtr<char> mime(g_utf8_strdown(mimeDescs[i], -1)); + gchar** mimeData = g_strsplit(mime.get(), ":", 3); + if (g_strv_length(mimeData) < 3) { + g_strfreev(mimeData); + continue; + } + + String description = String::fromUTF8(mimeData[2]); + gchar** extensions = g_strsplit(mimeData[1], ",", -1); + + Vector<String> extVector; + for (int j = 0; extensions[j]; j++) + extVector.append(String::fromUTF8(extensions[j])); + + determineQuirks(mimeData[0]); + m_mimeToExtensions.add(mimeData[0], extVector); + m_mimeToDescriptions.add(mimeData[0], description); + + g_strfreev(extensions); + g_strfreev(mimeData); + } + g_strfreev(mimeDescs); + + return true; +#else + notImplemented(); + return false; +#endif +} + +bool PluginPackage::load() +{ + if (m_isLoaded) { + m_loadCount++; + return true; + } + + GOwnPtr<gchar> finalPath(g_strdup(m_path.utf8().data())); + while (g_file_test(finalPath.get(), G_FILE_TEST_IS_SYMLINK)) { + GOwnPtr<GFile> file(g_file_new_for_path(finalPath.get())); + GOwnPtr<GFile> dir(g_file_get_parent(file.get())); + GOwnPtr<gchar> linkPath(g_file_read_link(finalPath.get(), 0)); + GOwnPtr<GFile> resolvedFile(g_file_resolve_relative_path(dir.get(), linkPath.get())); + finalPath.set(g_file_get_path(resolvedFile.get())); + } + + // No joke. If there is a netscape component in the path, go back + // to the symlink, as flash breaks otherwise. + // See http://src.chromium.org/viewvc/chrome/trunk/src/webkit/glue/plugins/plugin_list_posix.cc + GOwnPtr<gchar> baseName(g_path_get_basename(finalPath.get())); + if (!g_strcmp0(baseName.get(), "libflashplayer.so") + && g_strstr_len(finalPath.get(), -1, "/netscape/")) + finalPath.set(g_strdup(m_path.utf8().data())); + + m_module = g_module_open(finalPath.get(), G_MODULE_BIND_LOCAL); + + if (!m_module) { + LOG(Plugins,"Module Load Failed :%s, Error:%s\n", (m_path.utf8()).data(), g_module_error()); + return false; + } + + m_isLoaded = true; + + NP_InitializeFuncPtr NP_Initialize = 0; + m_NPP_Shutdown = 0; + + NPError npErr; + + g_module_symbol(m_module, "NP_Initialize", (void**)&NP_Initialize); + g_module_symbol(m_module, "NP_Shutdown", (void**)&m_NPP_Shutdown); + + if (!NP_Initialize || !m_NPP_Shutdown) + goto abort; + + memset(&m_pluginFuncs, 0, sizeof(m_pluginFuncs)); + m_pluginFuncs.size = sizeof(m_pluginFuncs); + + initializeBrowserFuncs(); + +#if defined(XP_UNIX) + npErr = NP_Initialize(&m_browserFuncs, &m_pluginFuncs); +#else + npErr = NP_Initialize(&m_browserFuncs); +#endif + if (npErr != NPERR_NO_ERROR) + goto abort; + + m_loadCount++; + return true; + +abort: + unloadWithoutShutdown(); + return false; +} + +uint16_t PluginPackage::NPVersion() const +{ + return NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL; +} +} diff --git a/Source/WebCore/plugins/gtk/PluginViewGtk.cpp b/Source/WebCore/plugins/gtk/PluginViewGtk.cpp new file mode 100644 index 0000000..ec855a2 --- /dev/null +++ b/Source/WebCore/plugins/gtk/PluginViewGtk.cpp @@ -0,0 +1,901 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2008 Collabora Ltd. All rights reserved. + * Copyright (C) 2009, 2010 Kakai, Inc. <brian@kakai.com> + * Copyright (C) 2010 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "PluginView.h" + +#include "Bridge.h" +#include "Document.h" +#include "DocumentLoader.h" +#include "Element.h" +#include "FocusController.h" +#include "FrameLoader.h" +#include "FrameLoadRequest.h" +#include "FrameTree.h" +#include "Frame.h" +#include "FrameView.h" +#include "GraphicsContext.h" +#include "GtkVersioning.h" +#include "HTMLNames.h" +#include "HTMLPlugInElement.h" +#include "HostWindow.h" +#include "Image.h" +#include "KeyboardEvent.h" +#include "MouseEvent.h" +#include "Page.h" +#include "PlatformKeyboardEvent.h" +#include "PlatformMouseEvent.h" +#include "PluginDebug.h" +#include "PluginMainThreadScheduler.h" +#include "PluginPackage.h" +#include "RenderLayer.h" +#include "Settings.h" +#include "JSDOMBinding.h" +#include "ScriptController.h" +#include "npruntime_impl.h" +#include "runtime_root.h" +#include <runtime/JSLock.h> +#include <runtime/JSValue.h> + +#ifdef GTK_API_VERSION_2 +#include <gdkconfig.h> +#endif +#include <gtk/gtk.h> + +#if defined(XP_UNIX) +#include "RefPtrCairo.h" +#include "gtk2xtbin.h" +#define Bool int // this got undefined somewhere +#define Status int // ditto +#include <X11/extensions/Xrender.h> +#include <cairo/cairo-xlib.h> +#include <gdk/gdkx.h> +#elif defined(GDK_WINDOWING_WIN32) +#include "PluginMessageThrottlerWin.h" +#include <gdk/gdkwin32.h> +#endif + +using JSC::ExecState; +using JSC::Interpreter; +using JSC::JSLock; +using JSC::JSObject; +using JSC::UString; + +using std::min; + +using namespace WTF; + +namespace WebCore { + +using namespace HTMLNames; + +bool PluginView::dispatchNPEvent(NPEvent& event) +{ + // sanity check + if (!m_plugin->pluginFuncs()->event) + return false; + + PluginView::setCurrentPluginView(this); + JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); + setCallingPlugin(true); + + bool accepted = m_plugin->pluginFuncs()->event(m_instance, &event); + + setCallingPlugin(false); + PluginView::setCurrentPluginView(0); + return accepted; +} + +#if defined(XP_UNIX) +static Window getRootWindow(Frame* parentFrame) +{ + GtkWidget* parentWidget = parentFrame->view()->hostWindow()->platformPageClient(); + GdkScreen* gscreen = gtk_widget_get_screen(parentWidget); + return GDK_WINDOW_XWINDOW(gdk_screen_get_root_window(gscreen)); +} +#endif + +void PluginView::updatePluginWidget() +{ + if (!parent()) + return; + + ASSERT(parent()->isFrameView()); + FrameView* frameView = static_cast<FrameView*>(parent()); + + IntRect oldWindowRect = m_windowRect; + IntRect oldClipRect = m_clipRect; + + m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size()); + m_clipRect = windowClipRect(); + m_clipRect.move(-m_windowRect.x(), -m_windowRect.y()); + + if (m_windowRect == oldWindowRect && m_clipRect == oldClipRect) + return; + +#if defined(XP_UNIX) + if (!m_isWindowed) { + Display* display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + if (m_drawable) + XFreePixmap(display, m_drawable); + + m_drawable = XCreatePixmap(display, getRootWindow(m_parentFrame.get()), + m_windowRect.width(), m_windowRect.height(), + ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth); + XSync(display, false); // make sure that the server knows about the Drawable + } +#endif + + setNPWindowIfNeeded(); +} + +void PluginView::setFocus(bool focused) +{ + ASSERT(platformPluginWidget() == platformWidget()); + Widget::setFocus(focused); +} + +void PluginView::show() +{ + ASSERT(platformPluginWidget() == platformWidget()); + Widget::show(); +} + +void PluginView::hide() +{ + ASSERT(platformPluginWidget() == platformWidget()); + Widget::hide(); +} + +void PluginView::paint(GraphicsContext* context, const IntRect& rect) +{ + if (!m_isStarted) { + paintMissingPluginIcon(context, rect); + return; + } + + if (context->paintingDisabled()) + return; + + setNPWindowIfNeeded(); + + if (m_isWindowed) + return; + +#if defined(XP_UNIX) + if (!m_drawable) + return; + + Display* display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + const bool syncX = m_pluginDisplay && m_pluginDisplay != display; + + IntRect exposedRect(rect); + exposedRect.intersect(frameRect()); + exposedRect.move(-frameRect().x(), -frameRect().y()); + + RefPtr<cairo_surface_t> drawableSurface = adoptRef(cairo_xlib_surface_create(display, + m_drawable, + m_visual, + m_windowRect.width(), + m_windowRect.height())); + + if (m_isTransparent) { + // If we have a 32 bit drawable and the plugin wants transparency, + // we'll clear the exposed area to transparent first. Otherwise, + // we'd end up with junk in there from the last paint, or, worse, + // uninitialized data. + RefPtr<cairo_t> cr = adoptRef(cairo_create(drawableSurface.get())); + + if (!(cairo_surface_get_content(drawableSurface.get()) & CAIRO_CONTENT_ALPHA)) { + // Attempt to fake it when we don't have an alpha channel on our + // pixmap. If that's not possible, at least clear the window to + // avoid drawing artifacts. + + // This Would not work without double buffering, but we always use it. + cairo_set_source_surface(cr.get(), cairo_get_group_target(context->platformContext()), + -m_windowRect.x(), -m_windowRect.y()); + cairo_set_operator(cr.get(), CAIRO_OPERATOR_SOURCE); + } else + cairo_set_operator(cr.get(), CAIRO_OPERATOR_CLEAR); + + cairo_rectangle(cr.get(), exposedRect.x(), exposedRect.y(), + exposedRect.width(), exposedRect.height()); + cairo_fill(cr.get()); + } + + XEvent xevent; + memset(&xevent, 0, sizeof(XEvent)); + XGraphicsExposeEvent& exposeEvent = xevent.xgraphicsexpose; + exposeEvent.type = GraphicsExpose; + exposeEvent.display = display; + exposeEvent.drawable = m_drawable; + exposeEvent.x = exposedRect.x(); + exposeEvent.y = exposedRect.y(); + exposeEvent.width = exposedRect.x() + exposedRect.width(); // flash bug? it thinks width is the right in transparent mode + exposeEvent.height = exposedRect.y() + exposedRect.height(); // flash bug? it thinks height is the bottom in transparent mode + + dispatchNPEvent(xevent); + + if (syncX) + XSync(m_pluginDisplay, false); // sync changes by plugin + + cairo_t* cr = context->platformContext(); + cairo_save(cr); + + cairo_set_source_surface(cr, drawableSurface.get(), frameRect().x(), frameRect().y()); + + cairo_rectangle(cr, + frameRect().x() + exposedRect.x(), frameRect().y() + exposedRect.y(), + exposedRect.width(), exposedRect.height()); + cairo_clip(cr); + + if (m_isTransparent) + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + else + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_paint(cr); + + cairo_restore(cr); +#endif // defined(XP_UNIX) +} + +void PluginView::handleKeyboardEvent(KeyboardEvent* event) +{ + JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); + + if (m_isWindowed) + return; + + if (event->type() != eventNames().keydownEvent && event->type() != eventNames().keyupEvent) + return; + + NPEvent xEvent; +#if defined(XP_UNIX) + initXEvent(&xEvent); + GdkEventKey* gdkEvent = event->keyEvent()->gdkEventKey(); + + xEvent.type = (event->type() == eventNames().keydownEvent) ? 2 : 3; // KeyPress/Release get unset somewhere + xEvent.xkey.root = getRootWindow(m_parentFrame.get()); + xEvent.xkey.subwindow = 0; // we have no child window + xEvent.xkey.time = event->timeStamp(); + xEvent.xkey.state = gdkEvent->state; // GdkModifierType mirrors xlib state masks + xEvent.xkey.keycode = gdkEvent->hardware_keycode; + xEvent.xkey.same_screen = true; + + // NOTE: As the XEvents sent to the plug-in are synthesized and there is not a native window + // corresponding to the plug-in rectangle, some of the members of the XEvent structures are not + // set to their normal Xserver values. e.g. Key events don't have a position. + // source: https://developer.mozilla.org/en/NPEvent + xEvent.xkey.x = 0; + xEvent.xkey.y = 0; + xEvent.xkey.x_root = 0; + xEvent.xkey.y_root = 0; +#endif + + if (!dispatchNPEvent(xEvent)) + event->setDefaultHandled(); +} + +#if defined(XP_UNIX) +static unsigned int inputEventState(MouseEvent* event) +{ + unsigned int state = 0; + if (event->ctrlKey()) + state |= ControlMask; + if (event->shiftKey()) + state |= ShiftMask; + if (event->altKey()) + state |= Mod1Mask; + if (event->metaKey()) + state |= Mod4Mask; + return state; +} + +void PluginView::initXEvent(XEvent* xEvent) +{ + memset(xEvent, 0, sizeof(XEvent)); + + xEvent->xany.serial = 0; // we are unaware of the last request processed by X Server + xEvent->xany.send_event = false; + xEvent->xany.display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + // NOTE: event->xany.window doesn't always correspond to the .window property of other XEvent's + // but does in the case of KeyPress, KeyRelease, ButtonPress, ButtonRelease, and MotionNotify + // events; thus, this is right: + GtkWidget* widget = m_parentFrame->view()->hostWindow()->platformPageClient(); + xEvent->xany.window = widget ? GDK_WINDOW_XWINDOW(gtk_widget_get_window(widget)) : 0; +} + +static void setXButtonEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos, Frame* parentFrame) +{ + XButtonEvent& xbutton = xEvent->xbutton; + xbutton.type = event->type() == eventNames().mousedownEvent ? ButtonPress : ButtonRelease; + xbutton.root = getRootWindow(parentFrame); + xbutton.subwindow = 0; + xbutton.time = event->timeStamp(); + xbutton.x = postZoomPos.x(); + xbutton.y = postZoomPos.y(); + xbutton.x_root = event->screenX(); + xbutton.y_root = event->screenY(); + xbutton.state = inputEventState(event); + switch (event->button()) { + case MiddleButton: + xbutton.button = Button2; + break; + case RightButton: + xbutton.button = Button3; + break; + case LeftButton: + default: + xbutton.button = Button1; + break; + } + xbutton.same_screen = true; +} + +static void setXMotionEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos, Frame* parentFrame) +{ + XMotionEvent& xmotion = xEvent->xmotion; + xmotion.type = MotionNotify; + xmotion.root = getRootWindow(parentFrame); + xmotion.subwindow = 0; + xmotion.time = event->timeStamp(); + xmotion.x = postZoomPos.x(); + xmotion.y = postZoomPos.y(); + xmotion.x_root = event->screenX(); + xmotion.y_root = event->screenY(); + xmotion.state = inputEventState(event); + xmotion.is_hint = NotifyNormal; + xmotion.same_screen = true; +} + +static void setXCrossingEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos, Frame* parentFrame) +{ + XCrossingEvent& xcrossing = xEvent->xcrossing; + xcrossing.type = event->type() == eventNames().mouseoverEvent ? EnterNotify : LeaveNotify; + xcrossing.root = getRootWindow(parentFrame); + xcrossing.subwindow = 0; + xcrossing.time = event->timeStamp(); + xcrossing.x = postZoomPos.y(); + xcrossing.y = postZoomPos.x(); + xcrossing.x_root = event->screenX(); + xcrossing.y_root = event->screenY(); + xcrossing.state = inputEventState(event); + xcrossing.mode = NotifyNormal; + xcrossing.detail = NotifyDetailNone; + xcrossing.same_screen = true; + xcrossing.focus = false; +} +#endif + +void PluginView::handleMouseEvent(MouseEvent* event) +{ + JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); + + if (m_isWindowed) + return; + + if (event->type() == eventNames().mousedownEvent) { + if (Page* page = m_parentFrame->page()) + page->focusController()->setActive(true); + focusPluginElement(); + } + + NPEvent xEvent; +#if defined(XP_UNIX) + initXEvent(&xEvent); + + IntPoint postZoomPos = roundedIntPoint(m_element->renderer()->absoluteToLocal(event->absoluteLocation())); + + if (event->type() == eventNames().mousedownEvent || event->type() == eventNames().mouseupEvent) + setXButtonEventSpecificFields(&xEvent, event, postZoomPos, m_parentFrame.get()); + else if (event->type() == eventNames().mousemoveEvent) + setXMotionEventSpecificFields(&xEvent, event, postZoomPos, m_parentFrame.get()); + else if (event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mouseoverEvent) + setXCrossingEventSpecificFields(&xEvent, event, postZoomPos, m_parentFrame.get()); + else + return; +#endif + + if (!dispatchNPEvent(xEvent)) + event->setDefaultHandled(); +} + +#if defined(XP_UNIX) +void PluginView::handleFocusInEvent() +{ + XEvent npEvent; + initXEvent(&npEvent); + + XFocusChangeEvent& event = npEvent.xfocus; + event.type = 9; // FocusIn gets unset somewhere + event.mode = NotifyNormal; + event.detail = NotifyDetailNone; + + dispatchNPEvent(npEvent); +} + +void PluginView::handleFocusOutEvent() +{ + XEvent npEvent; + initXEvent(&npEvent); + + XFocusChangeEvent& event = npEvent.xfocus; + event.type = 10; // FocusOut gets unset somewhere + event.mode = NotifyNormal; + event.detail = NotifyDetailNone; + + dispatchNPEvent(npEvent); +} +#endif + +void PluginView::setParent(ScrollView* parent) +{ + Widget::setParent(parent); + + if (parent) + init(); +} + +void PluginView::setNPWindowRect(const IntRect&) +{ + if (!m_isWindowed) + setNPWindowIfNeeded(); +} + +void PluginView::setNPWindowIfNeeded() +{ + if (!m_isStarted || !parent() || !m_plugin->pluginFuncs()->setwindow) + return; + + // If the plugin didn't load sucessfully, no point in calling setwindow + if (m_status != PluginStatusLoadedSuccessfully) + return; + + // On Unix, only call plugin's setwindow if it's full-page or windowed + if (m_mode != NP_FULL && m_mode != NP_EMBED) + return; + + // Check if the platformPluginWidget still exists + if (m_isWindowed && !platformPluginWidget()) + return; + + if (m_isWindowed) { + m_npWindow.x = m_windowRect.x(); + m_npWindow.y = m_windowRect.y(); + m_npWindow.width = m_windowRect.width(); + m_npWindow.height = m_windowRect.height(); + + m_npWindow.clipRect.left = max(0, m_clipRect.x()); + m_npWindow.clipRect.top = max(0, m_clipRect.y()); + m_npWindow.clipRect.right = m_clipRect.x() + m_clipRect.width(); + m_npWindow.clipRect.bottom = m_clipRect.y() + m_clipRect.height(); + } else { + m_npWindow.x = 0; + m_npWindow.y = 0; + m_npWindow.width = m_windowRect.width(); + m_npWindow.height = m_windowRect.height(); + + m_npWindow.clipRect.left = 0; + m_npWindow.clipRect.top = 0; + m_npWindow.clipRect.right = 0; + m_npWindow.clipRect.bottom = 0; + } + + PluginView::setCurrentPluginView(this); + JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); + setCallingPlugin(true); + m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow); + setCallingPlugin(false); + PluginView::setCurrentPluginView(0); + + if (m_isWindowed) { + GtkAllocation allocation = { m_windowRect.x(), m_windowRect.y(), m_windowRect.width(), m_windowRect.height() }; + gtk_widget_size_allocate(platformPluginWidget(), &allocation); +#if defined(XP_UNIX) + if (!m_needsXEmbed) { + gtk_xtbin_set_position(GTK_XTBIN(platformPluginWidget()), m_windowRect.x(), m_windowRect.y()); + gtk_xtbin_resize(platformPluginWidget(), m_windowRect.width(), m_windowRect.height()); + } +#endif + } +} + +void PluginView::setParentVisible(bool visible) +{ + if (isParentVisible() == visible) + return; + + Widget::setParentVisible(visible); + + if (isSelfVisible() && platformPluginWidget()) { + if (visible) + gtk_widget_show(platformPluginWidget()); + else + gtk_widget_hide(platformPluginWidget()); + } +} + +NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32_t len, const char* buf) +{ + WTF::String filename(buf, len); + + if (filename.startsWith("file:///")) + filename = filename.substring(8); + + // Get file info + if (!g_file_test ((filename.utf8()).data(), (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) + return NPERR_FILE_NOT_FOUND; + + //FIXME - read the file data into buffer + FILE* fileHandle = fopen((filename.utf8()).data(), "r"); + + if (fileHandle == 0) + return NPERR_FILE_NOT_FOUND; + + //buffer.resize(); + + int bytesRead = fread(buffer.data(), 1, 0, fileHandle); + + fclose(fileHandle); + + if (bytesRead <= 0) + return NPERR_FILE_NOT_FOUND; + + return NPERR_NO_ERROR; +} + +bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPError* result) +{ + switch (variable) { + case NPNVToolkit: +#if defined(XP_UNIX) + *static_cast<uint32_t*>(value) = 2; +#else + *static_cast<uint32_t*>(value) = 0; +#endif + *result = NPERR_NO_ERROR; + return true; + + case NPNVSupportsXEmbedBool: +#if defined(XP_UNIX) + *static_cast<NPBool*>(value) = true; +#else + *static_cast<NPBool*>(value) = false; +#endif + *result = NPERR_NO_ERROR; + return true; + + case NPNVjavascriptEnabledBool: + *static_cast<NPBool*>(value) = true; + *result = NPERR_NO_ERROR; + return true; + + case NPNVSupportsWindowless: +#if defined(XP_UNIX) + *static_cast<NPBool*>(value) = true; +#else + *static_cast<NPBool*>(value) = false; +#endif + *result = NPERR_NO_ERROR; + return true; + + default: + return false; + } +} + +bool PluginView::platformGetValue(NPNVariable variable, void* value, NPError* result) +{ + switch (variable) { + case NPNVxDisplay: +#if defined(XP_UNIX) + if (m_needsXEmbed) + *(void **)value = (void *)GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + else + *(void **)value = (void *)GTK_XTBIN(platformPluginWidget())->xtclient.xtdisplay; + *result = NPERR_NO_ERROR; +#else + *result = NPERR_GENERIC_ERROR; +#endif + return true; + +#if defined(XP_UNIX) + case NPNVxtAppContext: + if (!m_needsXEmbed) { + *(void **)value = XtDisplayToApplicationContext (GTK_XTBIN(platformPluginWidget())->xtclient.xtdisplay); + + *result = NPERR_NO_ERROR; + } else + *result = NPERR_GENERIC_ERROR; + return true; +#endif + + case NPNVnetscapeWindow: { +#if defined(XP_UNIX) + void* w = reinterpret_cast<void*>(value); + GtkWidget* widget = m_parentFrame->view()->hostWindow()->platformPageClient(); + *((XID *)w) = GDK_WINDOW_XWINDOW(gtk_widget_get_window(widget)); +#endif +#ifdef GDK_WINDOWING_WIN32 + HGDIOBJ* w = reinterpret_cast<HGDIOBJ*>(value); + GtkWidget* widget = m_parentFrame->view()->hostWindow()->platformPageClient(); + *w = GDK_WINDOW_HWND(gtk_widget_get_window(widget)); +#endif + *result = NPERR_NO_ERROR; + return true; + } + + default: + return false; + } +} + +void PluginView::invalidateRect(const IntRect& rect) +{ + if (m_isWindowed) { + gtk_widget_queue_draw_area(GTK_WIDGET(platformPluginWidget()), rect.x(), rect.y(), rect.width(), rect.height()); + return; + } + + invalidateWindowlessPluginRect(rect); +} + +void PluginView::invalidateRect(NPRect* rect) +{ + if (!rect) { + invalidate(); + return; + } + + IntRect r(rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top); + invalidateWindowlessPluginRect(r); +} + +void PluginView::invalidateRegion(NPRegion) +{ + // TODO: optimize + invalidate(); +} + +void PluginView::forceRedraw() +{ + if (m_isWindowed) + gtk_widget_queue_draw(platformPluginWidget()); + else + gtk_widget_queue_draw(m_parentFrame->view()->hostWindow()->platformPageClient()); +} + +static Display* getPluginDisplay() +{ + // The plugin toolkit might have a different X connection open. Since we're + // a gdk/gtk app, we'll (probably?) have the same X connection as any gdk-based + // plugins, so we can return that. We might want to add other implementations here + // later. + +#if defined(XP_UNIX) + return GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); +#else + return 0; +#endif +} + +#if defined(XP_UNIX) +static void getVisualAndColormap(int depth, Visual** visual, Colormap* colormap) +{ + *visual = 0; + *colormap = 0; + + Display* display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + int rmaj, rmin; + if (depth == 32 && (!XRenderQueryVersion(display, &rmaj, &rmin) || (rmaj == 0 && rmin < 5))) + return; + + XVisualInfo templ; + templ.screen = gdk_screen_get_number(gdk_screen_get_default()); + templ.depth = depth; + templ.c_class = TrueColor; + int nVisuals; + XVisualInfo* visualInfo = XGetVisualInfo(display, VisualScreenMask | VisualDepthMask | VisualClassMask, &templ, &nVisuals); + + if (!nVisuals) + return; + + if (depth == 32) { + for (int idx = 0; idx < nVisuals; ++idx) { + XRenderPictFormat* format = XRenderFindVisualFormat(display, visualInfo[idx].visual); + if (format->type == PictTypeDirect && format->direct.alphaMask) { + *visual = visualInfo[idx].visual; + break; + } + } + } else + *visual = visualInfo[0].visual; + + XFree(visualInfo); + + if (*visual) + *colormap = XCreateColormap(display, GDK_ROOT_WINDOW(), *visual, AllocNone); +} +#endif + +static gboolean plugRemovedCallback(GtkSocket* socket, gpointer) +{ + return TRUE; +} + +static void plugAddedCallback(GtkSocket* socket, PluginView* view) +{ + if (!socket || !view) + return; + + // FIXME: Java Plugins do not seem to draw themselves properly the + // first time unless we do a size-allocate after they have done + // the plug operation on their side, which in general does not + // happen since we do size-allocates before setting the + // NPWindow. Apply this workaround until we figure out a better + // solution, if any. + IntRect rect = view->frameRect(); + GtkAllocation allocation = { rect.x(), rect.y(), rect.width(), rect.height() }; + gtk_widget_size_allocate(GTK_WIDGET(socket), &allocation); +} + +bool PluginView::platformStart() +{ + ASSERT(m_isStarted); + ASSERT(m_status == PluginStatusLoadedSuccessfully); + + if (m_plugin->pluginFuncs()->getvalue) { + PluginView::setCurrentPluginView(this); + JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); + setCallingPlugin(true); + m_plugin->pluginFuncs()->getvalue(m_instance, NPPVpluginNeedsXEmbed, &m_needsXEmbed); + setCallingPlugin(false); + PluginView::setCurrentPluginView(0); + } + + if (m_isWindowed) { +#if defined(XP_UNIX) + GtkWidget* pageClient = m_parentFrame->view()->hostWindow()->platformPageClient(); + + if (m_needsXEmbed) { + // If our parent is not anchored the startup process will + // fail miserably for XEmbed plugins a bit later on when + // we try to get the ID of our window (since realize will + // fail), so let's just abort here. + if (!gtk_widget_get_parent(pageClient)) + return false; + + setPlatformWidget(gtk_socket_new()); + gtk_container_add(GTK_CONTAINER(pageClient), platformPluginWidget()); + g_signal_connect(platformPluginWidget(), "plug-added", G_CALLBACK(plugAddedCallback), this); + g_signal_connect(platformPluginWidget(), "plug-removed", G_CALLBACK(plugRemovedCallback), NULL); + } else + setPlatformWidget(gtk_xtbin_new(pageClient, 0)); +#else + setPlatformWidget(gtk_socket_new()); + gtk_container_add(GTK_CONTAINER(pageClient), platformPluginWidget()); +#endif + } else { + setPlatformWidget(0); + m_pluginDisplay = getPluginDisplay(); + } + + show(); + +#if defined(XP_UNIX) + NPSetWindowCallbackStruct* ws = new NPSetWindowCallbackStruct(); + ws->type = 0; +#endif + + if (m_isWindowed) { + m_npWindow.type = NPWindowTypeWindow; +#if defined(XP_UNIX) + if (m_needsXEmbed) { + GtkWidget* widget = platformPluginWidget(); + gtk_widget_realize(widget); + m_npWindow.window = (void*)gtk_socket_get_id(GTK_SOCKET(platformPluginWidget())); + GdkWindow* window = gtk_widget_get_window(widget); + ws->display = GDK_WINDOW_XDISPLAY(window); + ws->visual = GDK_VISUAL_XVISUAL(gdk_window_get_visual(window)); + ws->depth = gdk_visual_get_depth(gdk_window_get_visual(window)); + ws->colormap = XCreateColormap(ws->display, GDK_ROOT_WINDOW(), ws->visual, AllocNone); + } else { + m_npWindow.window = (void*)GTK_XTBIN(platformPluginWidget())->xtwindow; + ws->display = GTK_XTBIN(platformPluginWidget())->xtdisplay; + ws->visual = GTK_XTBIN(platformPluginWidget())->xtclient.xtvisual; + ws->depth = GTK_XTBIN(platformPluginWidget())->xtclient.xtdepth; + ws->colormap = GTK_XTBIN(platformPluginWidget())->xtclient.xtcolormap; + } + XFlush (ws->display); +#elif defined(GDK_WINDOWING_WIN32) + m_npWindow.window = (void*)GDK_WINDOW_HWND(gtk_widget_get_window(platformPluginWidget())); +#endif + } else { + m_npWindow.type = NPWindowTypeDrawable; + m_npWindow.window = 0; // Not used? + +#if defined(XP_UNIX) + GdkScreen* gscreen = gdk_screen_get_default(); + GdkVisual* gvisual = gdk_screen_get_system_visual(gscreen); + + if (gdk_visual_get_depth(gvisual) == 32 || !m_plugin->quirks().contains(PluginQuirkRequiresDefaultScreenDepth)) { + getVisualAndColormap(32, &m_visual, &m_colormap); + ws->depth = 32; + } + + if (!m_visual) { + getVisualAndColormap(gdk_visual_get_depth(gvisual), &m_visual, &m_colormap); + ws->depth = gdk_visual_get_depth(gvisual); + } + + ws->display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + ws->visual = m_visual; + ws->colormap = m_colormap; + + m_npWindow.x = 0; + m_npWindow.y = 0; + m_npWindow.width = -1; + m_npWindow.height = -1; +#else + notImplemented(); + m_status = PluginStatusCanNotLoadPlugin; + return false; +#endif + } + +#if defined(XP_UNIX) + m_npWindow.ws_info = ws; +#endif + + // TODO remove in favor of null events, like mac port? + if (!(m_plugin->quirks().contains(PluginQuirkDeferFirstSetWindowCall))) + updatePluginWidget(); // was: setNPWindowIfNeeded(), but this doesn't produce 0x0 rects at first go + + return true; +} + +void PluginView::platformDestroy() +{ +#if defined(XP_UNIX) + if (m_drawable) { + XFreePixmap(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), m_drawable); + m_drawable = 0; + } +#endif +} + +void PluginView::halt() +{ +} + +void PluginView::restart() +{ +} + +} // namespace WebCore + diff --git a/Source/WebCore/plugins/gtk/gtk2xtbin.c b/Source/WebCore/plugins/gtk/gtk2xtbin.c new file mode 100644 index 0000000..e03fad3 --- /dev/null +++ b/Source/WebCore/plugins/gtk/gtk2xtbin.c @@ -0,0 +1,966 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim:expandtab:shiftwidth=2:tabstop=2: */ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Gtk2XtBin Widget Implementation. + * + * The Initial Developer of the Original Code is + * Sun Microsystems, Inc. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * The GtkXtBin widget allows for Xt toolkit code to be used + * inside a GTK application. + */ + +#include "GtkVersioning.h" +#include "xembed.h" +#include "gtk2xtbin.h" +#include <gtk/gtk.h> +#include <gdk/gdkx.h> +#include <glib.h> +#include <assert.h> +#include <sys/time.h> +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +/* Xlib/Xt stuff */ +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Shell.h> +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> + +/* uncomment this if you want debugging information about widget + creation and destruction */ +#undef DEBUG_XTBIN + +#define XTBIN_MAX_EVENTS 30 + +static void gtk_xtbin_class_init (GtkXtBinClass *klass); +static void gtk_xtbin_init (GtkXtBin *xtbin); +static void gtk_xtbin_realize (GtkWidget *widget); +static void gtk_xtbin_unrealize (GtkWidget *widget); +static void gtk_xtbin_dispose (GObject *object); + +/* Xt aware XEmbed */ +static void xt_client_init (XtClient * xtclient, + Visual *xtvisual, + Colormap xtcolormap, + int xtdepth); +static void xt_client_create (XtClient * xtclient, + Window embeder, + int height, + int width ); +static void xt_client_unrealize (XtClient* xtclient); +static void xt_client_destroy (XtClient* xtclient); +static void xt_client_set_info (Widget xtplug, + unsigned long flags); +static void xt_client_event_handler (Widget w, + XtPointer client_data, + XEvent *event); +static void xt_client_handle_xembed_message (Widget w, + XtPointer client_data, + XEvent *event); +static void xt_client_focus_listener (Widget w, + XtPointer user_data, + XEvent *event); +static void xt_add_focus_listener( Widget w, XtPointer user_data ); +static void xt_add_focus_listener_tree ( Widget treeroot, XtPointer user_data); +static void xt_remove_focus_listener(Widget w, XtPointer user_data); +static void send_xembed_message (XtClient *xtclient, + long message, + long detail, + long data1, + long data2, + long time); +static int error_handler (Display *display, + XErrorEvent *error); +/* For error trap of XEmbed */ +static void trap_errors(void); +static int untrap_error(void); +static int (*old_error_handler) (Display *, XErrorEvent *); +static int trapped_error_code = 0; + +static GtkWidgetClass *parent_class = NULL; + +static Display *xtdisplay = NULL; +static String *fallback = NULL; +static gboolean xt_is_initialized = FALSE; +static gint num_widgets = 0; + +static GPollFD xt_event_poll_fd; +static gint xt_polling_timer_id = 0; +static guint tag = 0; + +static gboolean +xt_event_prepare (GSource* source_data, + gint *timeout) +{ + int mask; + + GDK_THREADS_ENTER(); + mask = XPending(xtdisplay); + GDK_THREADS_LEAVE(); + + return (gboolean)mask; +} + +static gboolean +xt_event_check (GSource* source_data) +{ + GDK_THREADS_ENTER (); + + if (xt_event_poll_fd.revents & G_IO_IN) { + int mask; + mask = XPending(xtdisplay); + GDK_THREADS_LEAVE (); + return (gboolean)mask; + } + + GDK_THREADS_LEAVE (); + return FALSE; +} + +static gboolean +xt_event_dispatch (GSource* source_data, + GSourceFunc call_back, + gpointer user_data) +{ + XtAppContext ac; + int i = 0; + + ac = XtDisplayToApplicationContext(xtdisplay); + + GDK_THREADS_ENTER (); + + /* Process only real X traffic here. We only look for data on the + * pipe, limit it to XTBIN_MAX_EVENTS and only call + * XtAppProcessEvent so that it will look for X events. There's no + * timer processing here since we already have a timer callback that + * does it. */ + for (i=0; i < XTBIN_MAX_EVENTS && XPending(xtdisplay); i++) { + XtAppProcessEvent(ac, XtIMXEvent); + } + + GDK_THREADS_LEAVE (); + + return TRUE; +} + +typedef void (*GSourceFuncsFinalize) (GSource* source); + +static GSourceFuncs xt_event_funcs = { + xt_event_prepare, + xt_event_check, + xt_event_dispatch, + (GSourceFuncsFinalize)g_free, + (GSourceFunc)NULL, + (GSourceDummyMarshal)NULL +}; + +static gboolean +xt_event_polling_timer_callback(gpointer user_data) +{ + Display * display; + XtAppContext ac; + int eventsToProcess = 20; + + display = (Display *)user_data; + ac = XtDisplayToApplicationContext(display); + + /* We need to process many Xt events here. If we just process + one event we might starve one or more Xt consumers. On the other hand + this could hang the whole app if Xt events come pouring in. So process + up to 20 Xt events right now and save the rest for later. This is a hack, + but it oughta work. We *really* should have out of process plugins. + */ + while (eventsToProcess-- && XtAppPending(ac)) + XtAppProcessEvent(ac, XtIMAll); + return TRUE; +} + +GType +gtk_xtbin_get_type (void) +{ + static GType xtbin_type = 0; + + if (!xtbin_type) { + static const GTypeInfo xtbin_info = + { + sizeof (GtkXtBinClass), + NULL, + NULL, + + (GClassInitFunc)gtk_xtbin_class_init, + NULL, + NULL, + + sizeof (GtkXtBin), + 0, + (GInstanceInitFunc)gtk_xtbin_init, + NULL + }; + xtbin_type = g_type_register_static (GTK_TYPE_SOCKET, + "GtkXtBin", + &xtbin_info, + 0); + } + return xtbin_type; +} + +static void +gtk_xtbin_class_init (GtkXtBinClass *klass) +{ + GtkWidgetClass *widget_class; + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (klass); + + widget_class = GTK_WIDGET_CLASS (klass); + widget_class->realize = gtk_xtbin_realize; + widget_class->unrealize = gtk_xtbin_unrealize; + + object_class = G_OBJECT_CLASS (klass); + object_class->dispose = gtk_xtbin_dispose; +} + +static void +gtk_xtbin_init (GtkXtBin *xtbin) +{ + xtbin->xtdisplay = NULL; + xtbin->parent_window = NULL; + xtbin->xtwindow = 0; + xtbin->x = 0; + xtbin->y = 0; +} + +static void +gtk_xtbin_realize (GtkWidget *widget) +{ + GtkXtBin *xtbin; + GtkAllocation allocation = { 0, 0, 200, 200 }; +#if GTK_CHECK_VERSION(2, 18, 0) + GtkAllocation widget_allocation; +#endif + +#ifdef DEBUG_XTBIN + printf("gtk_xtbin_realize()\n"); +#endif + + g_return_if_fail (GTK_IS_XTBIN (widget)); + + xtbin = GTK_XTBIN (widget); + + /* caculate the allocation before realize */ +#if GTK_CHECK_VERSION(2, 24, 0) + allocation.width = gdk_window_get_width(xtbin->parent_window); + allocation.height = gdk_window_get_height(xtbin->parent_window); +#else + gint x, y, w, h, d; /* geometry of window */ + gdk_window_get_geometry(xtbin->parent_window, &x, &y, &w, &h, &d); + allocation.width = w; + allocation.height = h; +#endif + gtk_widget_size_allocate (widget, &allocation); + +#ifdef DEBUG_XTBIN + printf("initial allocation %d %d %d %d\n", x, y, w, h); +#endif + +#if GTK_CHECK_VERSION(2, 18, 0) + gtk_widget_get_allocation(widget, &widget_allocation); + xtbin->width = widget_allocation.width; + xtbin->height = widget_allocation.height; +#else + xtbin->width = widget->allocation.width; + xtbin->height = widget->allocation.height; +#endif + + /* use GtkSocket's realize */ + (*GTK_WIDGET_CLASS(parent_class)->realize)(widget); + + /* create the Xt client widget */ + xt_client_create(&(xtbin->xtclient), + gtk_socket_get_id(GTK_SOCKET(xtbin)), + xtbin->height, + xtbin->width); + xtbin->xtwindow = XtWindow(xtbin->xtclient.child_widget); + + gdk_flush(); + + /* now that we have created the xt client, add it to the socket. */ + gtk_socket_add_id(GTK_SOCKET(widget), xtbin->xtwindow); +} + + + +GtkWidget* +gtk_xtbin_new (GtkWidget *parent_widget, String *f) +{ + GtkXtBin *xtbin; + gpointer user_data; + GdkScreen *screen; + GdkVisual* visual; + Colormap colormap; + GdkWindow* parent_window = gtk_widget_get_window(parent_widget); + + assert(parent_window != NULL); + xtbin = g_object_new (GTK_TYPE_XTBIN, NULL); + + if (!xtbin) + return (GtkWidget*)NULL; + + if (f) + fallback = f; + + /* Initialize the Xt toolkit */ + xtbin->parent_window = parent_window; + + screen = gtk_widget_get_screen(parent_widget); + visual = gdk_screen_get_system_visual(screen); + colormap = XCreateColormap(GDK_DISPLAY_XDISPLAY(gdk_screen_get_display(screen)), + GDK_WINDOW_XWINDOW(gdk_screen_get_root_window(screen)), + GDK_VISUAL_XVISUAL(visual), AllocNone); + + xt_client_init(&(xtbin->xtclient), + GDK_VISUAL_XVISUAL(visual), + colormap, + gdk_visual_get_depth(visual)); + + if (!xtbin->xtclient.xtdisplay) { + /* If XtOpenDisplay failed, we can't go any further. + * Bail out. + */ +#ifdef DEBUG_XTBIN + printf("gtk_xtbin_init: XtOpenDisplay() returned NULL.\n"); +#endif + g_free (xtbin); + return (GtkWidget *)NULL; + } + + /* If this is the first running widget, hook this display into the + mainloop */ + if (0 == num_widgets) { + int cnumber; + /* + * hook Xt event loop into the glib event loop. + */ + + /* the assumption is that gtk_init has already been called */ + GSource* gs = g_source_new(&xt_event_funcs, sizeof(GSource)); + if (!gs) { + return NULL; + } + + g_source_set_priority(gs, GDK_PRIORITY_EVENTS); + g_source_set_can_recurse(gs, TRUE); + tag = g_source_attach(gs, (GMainContext*)NULL); +#ifdef VMS + cnumber = XConnectionNumber(xtdisplay); +#else + cnumber = ConnectionNumber(xtdisplay); +#endif + xt_event_poll_fd.fd = cnumber; + xt_event_poll_fd.events = G_IO_IN; + xt_event_poll_fd.revents = 0; /* hmm... is this correct? */ + + g_main_context_add_poll ((GMainContext*)NULL, + &xt_event_poll_fd, + G_PRIORITY_LOW); + /* add a timer so that we can poll and process Xt timers */ + xt_polling_timer_id = + g_timeout_add(25, + (GSourceFunc)xt_event_polling_timer_callback, + xtdisplay); + } + + /* Bump up our usage count */ + num_widgets++; + + /* Build the hierachy */ + xtbin->xtdisplay = xtbin->xtclient.xtdisplay; + gtk_widget_set_parent_window(GTK_WIDGET(xtbin), parent_window); + gdk_window_get_user_data(xtbin->parent_window, &user_data); + if (user_data) + gtk_container_add(GTK_CONTAINER(user_data), GTK_WIDGET(xtbin)); + + return GTK_WIDGET (xtbin); +} + +void +gtk_xtbin_set_position (GtkXtBin *xtbin, + gint x, + gint y) +{ + xtbin->x = x; + xtbin->y = y; + + if (gtk_widget_get_realized (GTK_WIDGET(xtbin))) + gdk_window_move (gtk_widget_get_window(GTK_WIDGET (xtbin)), x, y); +} + +void +gtk_xtbin_resize (GtkWidget *widget, + gint width, + gint height) +{ + Arg args[2]; + GtkXtBin *xtbin = GTK_XTBIN (widget); + GtkAllocation allocation; + +#ifdef DEBUG_XTBIN + printf("gtk_xtbin_resize %p %d %d\n", (void *)widget, width, height); +#endif + + xtbin->height = height; + xtbin->width = width; + + // Avoid BadValue errors in XtSetValues + if (height <= 0 || width <=0) { + height = 1; + width = 1; + } + XtSetArg(args[0], XtNheight, height); + XtSetArg(args[1], XtNwidth, width); + XtSetValues(xtbin->xtclient.top_widget, args, 2); + + /* we need to send a size allocate so the socket knows about the + size changes */ + allocation.x = xtbin->x; + allocation.y = xtbin->y; + allocation.width = xtbin->width; + allocation.height = xtbin->height; + + gtk_widget_size_allocate(widget, &allocation); +} + +static void +gtk_xtbin_unrealize (GtkWidget *object) +{ + GtkXtBin *xtbin; + GtkWidget *widget; + +#ifdef DEBUG_XTBIN + printf("gtk_xtbin_unrealize()\n"); +#endif + + /* gtk_object_destroy() will already hold a refcount on object + */ + xtbin = GTK_XTBIN(object); + widget = GTK_WIDGET(object); + + gtk_widget_set_visible(widget, FALSE); + if (gtk_widget_get_realized (widget)) { + xt_client_unrealize(&(xtbin->xtclient)); + } + + (*GTK_WIDGET_CLASS (parent_class)->unrealize)(widget); +} + +static void +gtk_xtbin_dispose (GObject *object) +{ + GtkXtBin *xtbin; + +#ifdef DEBUG_XTBIN + printf("gtk_xtbin_destroy()\n"); +#endif + + g_return_if_fail (object != NULL); + g_return_if_fail (GTK_IS_XTBIN (object)); + + xtbin = GTK_XTBIN (object); + + if(xtbin->xtwindow) { + /* remove the event handler */ + xt_client_destroy(&(xtbin->xtclient)); + xtbin->xtwindow = 0; + + num_widgets--; /* reduce our usage count */ + + /* If this is the last running widget, remove the Xt display + connection from the mainloop */ + if (0 == num_widgets) { +#ifdef DEBUG_XTBIN + printf("removing the Xt connection from the main loop\n"); +#endif + g_main_context_remove_poll((GMainContext*)NULL, &xt_event_poll_fd); + g_source_remove(tag); + + g_source_remove(xt_polling_timer_id); + xt_polling_timer_id = 0; + } + } + + G_OBJECT_CLASS(parent_class)->dispose(object); +} + +/* +* Following is the implementation of Xt XEmbedded for client side +*/ + +/* Initial Xt plugin */ +static void +xt_client_init( XtClient * xtclient, + Visual *xtvisual, + Colormap xtcolormap, + int xtdepth) +{ + XtAppContext app_context; + char *mArgv[1]; + int mArgc = 0; + + /* + * Initialize Xt stuff + */ + xtclient->top_widget = NULL; + xtclient->child_widget = NULL; + xtclient->xtdisplay = NULL; + xtclient->xtvisual = NULL; + xtclient->xtcolormap = 0; + xtclient->xtdepth = 0; + + if (!xt_is_initialized) { +#ifdef DEBUG_XTBIN + printf("starting up Xt stuff\n"); +#endif + XtToolkitInitialize(); + app_context = XtCreateApplicationContext(); + if (fallback) + XtAppSetFallbackResources(app_context, fallback); + + xtdisplay = XtOpenDisplay(app_context, gdk_get_display(), NULL, + "Wrapper", NULL, 0, &mArgc, mArgv); + if (xtdisplay) + xt_is_initialized = TRUE; + } + xtclient->xtdisplay = xtdisplay; + xtclient->xtvisual = xtvisual; + xtclient->xtcolormap = xtcolormap; + xtclient->xtdepth = xtdepth; +} + +/* Create the Xt client widgets +* */ +static void +xt_client_create ( XtClient* xtclient , + Window embedderid, + int height, + int width ) +{ + int n; + Arg args[6]; + Widget child_widget; + Widget top_widget; + +#ifdef DEBUG_XTBIN + printf("xt_client_create() \n"); +#endif + top_widget = XtAppCreateShell("drawingArea", "Wrapper", + applicationShellWidgetClass, + xtclient->xtdisplay, + NULL, 0); + xtclient->top_widget = top_widget; + + /* set size of Xt window */ + n = 0; + XtSetArg(args[n], XtNheight, height);n++; + XtSetArg(args[n], XtNwidth, width);n++; + XtSetValues(top_widget, args, n); + + child_widget = XtVaCreateWidget("form", + compositeWidgetClass, + top_widget, NULL); + + n = 0; + XtSetArg(args[n], XtNheight, height);n++; + XtSetArg(args[n], XtNwidth, width);n++; + XtSetArg(args[n], XtNvisual, xtclient->xtvisual ); n++; + XtSetArg(args[n], XtNdepth, xtclient->xtdepth ); n++; + XtSetArg(args[n], XtNcolormap, xtclient->xtcolormap ); n++; + XtSetArg(args[n], XtNborderWidth, 0); n++; + XtSetValues(child_widget, args, n); + + XSync(xtclient->xtdisplay, FALSE); + xtclient->oldwindow = top_widget->core.window; + top_widget->core.window = embedderid; + + /* this little trick seems to finish initializing the widget */ +#if XlibSpecificationRelease >= 6 + XtRegisterDrawable(xtclient->xtdisplay, + embedderid, + top_widget); +#else + _XtRegisterWindow( embedderid, + top_widget); +#endif + XtRealizeWidget(child_widget); + + /* listen to all Xt events */ + XSelectInput(xtclient->xtdisplay, + XtWindow(top_widget), + 0x0FFFFF); + xt_client_set_info (child_widget, 0); + + XtManageChild(child_widget); + xtclient->child_widget = child_widget; + + /* set the event handler */ + XtAddEventHandler(child_widget, + 0x0FFFFF & ~ResizeRedirectMask, + TRUE, + (XtEventHandler)xt_client_event_handler, xtclient); + XtAddEventHandler(child_widget, + SubstructureNotifyMask | ButtonReleaseMask, + TRUE, + (XtEventHandler)xt_client_focus_listener, + xtclient); + XSync(xtclient->xtdisplay, FALSE); +} + +static void +xt_client_unrealize ( XtClient* xtclient ) +{ +#if XlibSpecificationRelease >= 6 + XtUnregisterDrawable(xtclient->xtdisplay, + xtclient->top_widget->core.window); +#else + _XtUnregisterWindow(xtclient->top_widget->core.window, + xtclient->top_widget); +#endif + + /* flush the queue before we returning origin top_widget->core.window + or we can get X error since the window is gone */ + XSync(xtclient->xtdisplay, False); + + xtclient->top_widget->core.window = xtclient->oldwindow; + XtUnrealizeWidget(xtclient->top_widget); +} + +static void +xt_client_destroy (XtClient* xtclient) +{ + if(xtclient->top_widget) { + XtRemoveEventHandler(xtclient->child_widget, 0x0FFFFF, TRUE, + (XtEventHandler)xt_client_event_handler, xtclient); + XtDestroyWidget(xtclient->top_widget); + xtclient->top_widget = NULL; + } +} + +static void +xt_client_set_info (Widget xtplug, unsigned long flags) +{ + unsigned long buffer[2]; + + Atom infoAtom = XInternAtom(XtDisplay(xtplug), "_XEMBED_INFO", False); + + buffer[1] = 0; /* Protocol version */ + buffer[1] = flags; + + XChangeProperty (XtDisplay(xtplug), XtWindow(xtplug), + infoAtom, infoAtom, 32, + PropModeReplace, + (unsigned char *)buffer, 2); +} + +static void +xt_client_handle_xembed_message(Widget w, XtPointer client_data, XEvent *event) +{ + XtClient *xtplug = (XtClient*)client_data; + switch (event->xclient.data.l[1]) + { + case XEMBED_EMBEDDED_NOTIFY: + break; + case XEMBED_WINDOW_ACTIVATE: +#ifdef DEBUG_XTBIN + printf("Xt client get XEMBED_WINDOW_ACTIVATE\n"); +#endif + break; + case XEMBED_WINDOW_DEACTIVATE: +#ifdef DEBUG_XTBIN + printf("Xt client get XEMBED_WINDOW_DEACTIVATE\n"); +#endif + break; + case XEMBED_MODALITY_ON: +#ifdef DEBUG_XTBIN + printf("Xt client get XEMBED_MODALITY_ON\n"); +#endif + break; + case XEMBED_MODALITY_OFF: +#ifdef DEBUG_XTBIN + printf("Xt client get XEMBED_MODALITY_OFF\n"); +#endif + break; + case XEMBED_FOCUS_IN: + case XEMBED_FOCUS_OUT: + { + XEvent xevent; + memset(&xevent, 0, sizeof(xevent)); + + if(event->xclient.data.l[1] == XEMBED_FOCUS_IN) { +#ifdef DEBUG_XTBIN + printf("XTEMBED got focus in\n"); +#endif + xevent.xfocus.type = FocusIn; + } + else { +#ifdef DEBUG_XTBIN + printf("XTEMBED got focus out\n"); +#endif + xevent.xfocus.type = FocusOut; + } + + xevent.xfocus.window = XtWindow(xtplug->child_widget); + xevent.xfocus.display = XtDisplay(xtplug->child_widget); + XSendEvent(XtDisplay(xtplug->child_widget), + xevent.xfocus.window, + False, NoEventMask, + &xevent ); + XSync( XtDisplay(xtplug->child_widget), False); + } + break; + default: + break; + } /* End of XEmbed Message */ +} + +static void +xt_client_event_handler( Widget w, XtPointer client_data, XEvent *event) +{ + XtClient *xtplug = (XtClient*)client_data; + + switch(event->type) + { + case ClientMessage: + /* Handle xembed message */ + if (event->xclient.message_type== + XInternAtom (XtDisplay(xtplug->child_widget), + "_XEMBED", False)) { + xt_client_handle_xembed_message(w, client_data, event); + } + break; + case ReparentNotify: + break; + case MappingNotify: + xt_client_set_info (w, XEMBED_MAPPED); + break; + case UnmapNotify: + xt_client_set_info (w, 0); + break; + case FocusIn: + send_xembed_message ( xtplug, + XEMBED_REQUEST_FOCUS, 0, 0, 0, 0); + break; + case FocusOut: + break; + case KeyPress: +#ifdef DEBUG_XTBIN + printf("Key Press Got!\n"); +#endif + break; + default: + break; + } /* End of switch(event->type) */ +} + +static void +send_xembed_message (XtClient *xtclient, + long message, + long detail, + long data1, + long data2, + long time) +{ + XEvent xevent; + Window w=XtWindow(xtclient->top_widget); + Display* dpy=xtclient->xtdisplay; + int errorcode; + + memset(&xevent,0,sizeof(xevent)); + xevent.xclient.window = w; + xevent.xclient.type = ClientMessage; + xevent.xclient.message_type = XInternAtom(dpy,"_XEMBED",False); + xevent.xclient.format = 32; + xevent.xclient.data.l[0] = time; + xevent.xclient.data.l[1] = message; + xevent.xclient.data.l[2] = detail; + xevent.xclient.data.l[3] = data1; + xevent.xclient.data.l[4] = data2; + + trap_errors (); + XSendEvent (dpy, w, False, NoEventMask, &xevent); + XSync (dpy,False); + + if((errorcode = untrap_error())) { +#ifdef DEBUG_XTBIN + printf("send_xembed_message error(%d)!!!\n",errorcode); +#endif + } +} + +static int +error_handler(Display *display, XErrorEvent *error) +{ + trapped_error_code = error->error_code; + return 0; +} + +static void +trap_errors(void) +{ + trapped_error_code =0; + old_error_handler = XSetErrorHandler(error_handler); +} + +static int +untrap_error(void) +{ + XSetErrorHandler(old_error_handler); + if(trapped_error_code) { +#ifdef DEBUG_XTBIN + printf("Get X Window Error = %d\n", trapped_error_code); +#endif + } + return trapped_error_code; +} + +static void +xt_client_focus_listener( Widget w, XtPointer user_data, XEvent *event) +{ + Display *dpy = XtDisplay(w); + XtClient *xtclient = user_data; + Window win = XtWindow(w); + + switch(event->type) + { + case CreateNotify: + if(event->xcreatewindow.parent == win) { + Widget child=XtWindowToWidget( dpy, event->xcreatewindow.window); + if (child) + xt_add_focus_listener_tree(child, user_data); + } + break; + case DestroyNotify: + xt_remove_focus_listener( w, user_data); + break; + case ReparentNotify: + if(event->xreparent.parent == win) { + /* I am the new parent */ + Widget child=XtWindowToWidget(dpy, event->xreparent.window); + if (child) + xt_add_focus_listener_tree( child, user_data); + } + else if(event->xreparent.window == win) { + /* I am the new child */ + } + else { + /* I am the old parent */ + } + break; + case ButtonRelease: +#if 0 + XSetInputFocus(dpy, XtWindow(xtclient->child_widget), RevertToParent, event->xbutton.time); +#endif + send_xembed_message ( xtclient, + XEMBED_REQUEST_FOCUS, 0, 0, 0, 0); + break; + default: + break; + } /* End of switch(event->type) */ +} + +static void +xt_add_focus_listener( Widget w, XtPointer user_data) +{ + XWindowAttributes attr; + long eventmask; + XtClient *xtclient = user_data; + + trap_errors (); + XGetWindowAttributes(XtDisplay(w), XtWindow(w), &attr); + eventmask = attr.your_event_mask | SubstructureNotifyMask | ButtonReleaseMask; + XSelectInput(XtDisplay(w), + XtWindow(w), + eventmask); + + XtAddEventHandler(w, + SubstructureNotifyMask | ButtonReleaseMask, + TRUE, + (XtEventHandler)xt_client_focus_listener, + xtclient); + untrap_error(); +} + +static void +xt_remove_focus_listener(Widget w, XtPointer user_data) +{ + trap_errors (); + XtRemoveEventHandler(w, SubstructureNotifyMask | ButtonReleaseMask, TRUE, + (XtEventHandler)xt_client_focus_listener, user_data); + + untrap_error(); +} + +static void +xt_add_focus_listener_tree ( Widget treeroot, XtPointer user_data) +{ + Window win = XtWindow(treeroot); + Window *children; + Window root, parent; + Display *dpy = XtDisplay(treeroot); + unsigned int i, nchildren; + + /* ensure we don't add more than once */ + xt_remove_focus_listener( treeroot, user_data); + xt_add_focus_listener( treeroot, user_data); + trap_errors(); + if(!XQueryTree(dpy, win, &root, &parent, &children, &nchildren)) { + untrap_error(); + return; + } + + if(untrap_error()) + return; + + for(i=0; i<nchildren; ++i) { + Widget child = XtWindowToWidget(dpy, children[i]); + if (child) + xt_add_focus_listener_tree( child, user_data); + } + XFree((void*)children); + + return; +} diff --git a/Source/WebCore/plugins/gtk/gtk2xtbin.h b/Source/WebCore/plugins/gtk/gtk2xtbin.h new file mode 100644 index 0000000..11f6e06 --- /dev/null +++ b/Source/WebCore/plugins/gtk/gtk2xtbin.h @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set expandtab shiftwidth=2 tabstop=2: */ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Gtk2XtBin Widget Implementation. + * + * The Initial Developer of the Original Code is + * Sun Microsystems, Inc. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __GTK_XTBIN_H__ +#define __GTK_XTBIN_H__ + +#include <gtk/gtk.h> +#include <X11/Intrinsic.h> +#include <X11/Xutil.h> +#include <X11/Xlib.h> +#ifdef MOZILLA_CLIENT +#include "nscore.h" +#ifdef _IMPL_GTKXTBIN_API +#define GTKXTBIN_API(type) NS_EXPORT_(type) +#else +#define GTKXTBIN_API(type) NS_IMPORT_(type) +#endif +#else +#define GTKXTBIN_API(type) type +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct _GtkXtBin GtkXtBin; +typedef struct _GtkXtBinClass GtkXtBinClass; + +#define GTK_TYPE_XTBIN (gtk_xtbin_get_type ()) +#define GTK_XTBIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + GTK_TYPE_XTBIN, GtkXtBin)) +#define GTK_XTBIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \ + GTK_TYPE_XTBIN, GtkXtBinClass)) +#define GTK_IS_XTBIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + GTK_TYPE_XTBIN)) +#define GTK_IS_XTBIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + GTK_TYPE_XTBIN)) +typedef struct _XtClient XtClient; + +struct _XtClient { + Display *xtdisplay; + Widget top_widget; /* The toplevel widget */ + Widget child_widget; /* The embedded widget */ + Visual *xtvisual; + int xtdepth; + Colormap xtcolormap; + Window oldwindow; +}; + +struct _GtkXtBin +{ + GtkSocket gsocket; + GdkWindow *parent_window; + Display *xtdisplay; /* Xt Toolkit Display */ + + Window xtwindow; /* Xt Toolkit XWindow */ + gint x, y; + gint width, height; + XtClient xtclient; /* Xt Client for XEmbed */ +}; + +struct _GtkXtBinClass +{ + GtkSocketClass widget_class; +}; + +GTKXTBIN_API(GType) gtk_xtbin_get_type (void); +GTKXTBIN_API(GtkWidget *) gtk_xtbin_new (GtkWidget *parent_widget, String *f); +GTKXTBIN_API(void) gtk_xtbin_set_position (GtkXtBin *xtbin, + gint x, + gint y); +GTKXTBIN_API(void) gtk_xtbin_resize (GtkWidget *widget, + gint width, + gint height); + +typedef struct _XtTMRec { + XtTranslations translations; /* private to Translation Manager */ + XtBoundActions proc_table; /* procedure bindings for actions */ + struct _XtStateRec *current_state; /* Translation Manager state ptr */ + unsigned long lastEventTime; +} XtTMRec, *XtTM; + +typedef struct _CorePart { + Widget self; /* pointer to widget itself */ + WidgetClass widget_class; /* pointer to Widget's ClassRec */ + Widget parent; /* parent widget */ + XrmName xrm_name; /* widget resource name quarkified */ + Boolean being_destroyed; /* marked for destroy */ + XtCallbackList destroy_callbacks; /* who to call when widget destroyed */ + XtPointer constraints; /* constraint record */ + Position x, y; /* window position */ + Dimension width, height; /* window dimensions */ + Dimension border_width; /* window border width */ + Boolean managed; /* is widget geometry managed? */ + Boolean sensitive; /* is widget sensitive to user events*/ + Boolean ancestor_sensitive; /* are all ancestors sensitive? */ + XtEventTable event_table; /* private to event dispatcher */ + XtTMRec tm; /* translation management */ + XtTranslations accelerators; /* accelerator translations */ + Pixel border_pixel; /* window border pixel */ + Pixmap border_pixmap; /* window border pixmap or NULL */ + WidgetList popup_list; /* list of popups */ + Cardinal num_popups; /* how many popups */ + String name; /* widget resource name */ + Screen *screen; /* window's screen */ + Colormap colormap; /* colormap */ + Window window; /* window ID */ + Cardinal depth; /* number of planes in window */ + Pixel background_pixel; /* window background pixel */ + Pixmap background_pixmap; /* window background pixmap or NULL */ + Boolean visible; /* is window mapped and not occluded?*/ + Boolean mapped_when_managed;/* map window if it's managed? */ +} CorePart; + +typedef struct _WidgetRec { + CorePart core; + } WidgetRec, CoreRec; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __GTK_XTBIN_H__ */ diff --git a/Source/WebCore/plugins/gtk/xembed.h b/Source/WebCore/plugins/gtk/xembed.h new file mode 100644 index 0000000..dff7be9 --- /dev/null +++ b/Source/WebCore/plugins/gtk/xembed.h @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim:expandtab:shiftwidth=2:tabstop=2: */ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the XEMBED Declaration. + * + * The Initial Developer of the Original Code is + * Sun Microsystems, Inc. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* XEMBED messages */ +#define XEMBED_EMBEDDED_NOTIFY 0 +#define XEMBED_WINDOW_ACTIVATE 1 +#define XEMBED_WINDOW_DEACTIVATE 2 +#define XEMBED_REQUEST_FOCUS 3 +#define XEMBED_FOCUS_IN 4 +#define XEMBED_FOCUS_OUT 5 +#define XEMBED_FOCUS_NEXT 6 +#define XEMBED_FOCUS_PREV 7 +#define XEMBED_GRAB_KEY 8 +#define XEMBED_UNGRAB_KEY 9 +#define XEMBED_MODALITY_ON 10 +#define XEMBED_MODALITY_OFF 11 + +/* Non standard messages*/ +#define XEMBED_GTK_GRAB_KEY 108 +#define XEMBED_GTK_UNGRAB_KEY 109 + +/* Details for XEMBED_FOCUS_IN: */ +#define XEMBED_FOCUS_CURRENT 0 +#define XEMBED_FOCUS_FIRST 1 +#define XEMBED_FOCUS_LAST 2 + +/* Flags for _XEMBED_INFO */ +#define XEMBED_MAPPED (1 << 0) |
