Bug 672857 - Make IM work for IPC plugins in remote browser. r=karlt
authorOleg Romashin <romaxa@gmail.com>
Mon, 29 Aug 2011 17:26:24 +0100
changeset 76187 4fc1f5dd41054e92e62fc3f34899a5c21ec5d46e
parent 76186 bc4b2d84f80aeb4ebb2b19d67cd1f2a56e139c5f
child 76188 9f7ccdc68e3f087a805d21afd67ac6c981deb67e
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewerskarlt
bugs672857
milestone9.0a1
Bug 672857 - Make IM work for IPC plugins in remote browser. r=karlt
dom/plugins/base/PluginPRLibrary.cpp
dom/plugins/base/PluginPRLibrary.h
dom/plugins/base/nsNPAPIPluginInstance.cpp
dom/plugins/base/nsNPAPIPluginInstance.h
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/plugins/base/nsPluginInstanceOwner.h
dom/plugins/ipc/PPluginInstance.ipdl
dom/plugins/ipc/PluginInstanceChild.cpp
dom/plugins/ipc/PluginInstanceChild.h
dom/plugins/ipc/PluginInstanceParent.cpp
dom/plugins/ipc/PluginInstanceParent.h
dom/plugins/ipc/PluginLibrary.h
dom/plugins/ipc/PluginModuleParent.cpp
dom/plugins/ipc/PluginModuleParent.h
widget/public/nsGUIEvent.h
widget/src/qt/Makefile.in
--- a/dom/plugins/base/PluginPRLibrary.cpp
+++ b/dom/plugins/base/PluginPRLibrary.cpp
@@ -241,16 +241,27 @@ PluginPRLibrary::NPP_GetSitesWithData(In
 nsresult
 PluginPRLibrary::AsyncSetWindow(NPP instance, NPWindow* window)
 {
   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
   NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+nsresult
+PluginPRLibrary::HandleGUIEvent(NPP instance, const nsGUIEvent& anEvent,
+                                bool* handled)
+{
+  nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
+  NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+#endif
+
 nsresult
 PluginPRLibrary::GetImage(NPP instance, ImageContainer* aContainer, Image** aImage)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 #if defined(XP_MACOSX)
 nsresult
--- a/dom/plugins/base/PluginPRLibrary.h
+++ b/dom/plugins/base/PluginPRLibrary.h
@@ -149,16 +149,20 @@ public:
     NS_OVERRIDE
     virtual nsresult SetBackgroundUnknown(NPP instance);
     NS_OVERRIDE
     virtual nsresult BeginUpdateBackground(NPP instance,
                                            const nsIntRect&, gfxContext** aCtx);
     NS_OVERRIDE
     virtual nsresult EndUpdateBackground(NPP instance,
                                          gfxContext* aCtx, const nsIntRect&);
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+    virtual nsresult HandleGUIEvent(NPP instance,
+                                    const nsGUIEvent& anEvent, bool* handled);
+#endif
 
 private:
     NP_InitializeFunc mNP_Initialize;
     NP_ShutdownFunc mNP_Shutdown;
     NP_GetMIMEDescriptionFunc mNP_GetMIMEDescription;
 #if defined(XP_UNIX) && !defined(XP_MACOSX)
     NP_GetValueFunc mNP_GetValue;
 #endif
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -837,16 +837,33 @@ nsNPAPIPluginInstance::AsyncSetWindow(NP
 
   AutoPluginLibraryCall library(this);
   if (!library)
     return NS_ERROR_FAILURE;
 
   return library->AsyncSetWindow(&mNPP, window);
 }
 
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+nsresult
+nsNPAPIPluginInstance::HandleGUIEvent(const nsGUIEvent& anEvent, bool* handled)
+{
+  if (RUNNING != mRunning) {
+    *handled = false;
+    return NS_OK;
+  }
+
+  AutoPluginLibraryCall library(this);
+  if (!library)
+    return NS_ERROR_FAILURE;
+
+  return library->HandleGUIEvent(&mNPP, anEvent, handled);
+}
+#endif
+
 nsresult
 nsNPAPIPluginInstance::GetImage(ImageContainer* aContainer, Image** aImage)
 {
   *aImage = nsnull;
 
   if (RUNNING != mRunning)
     return NS_OK;
 
--- a/dom/plugins/base/nsNPAPIPluginInstance.h
+++ b/dom/plugins/base/nsNPAPIPluginInstance.h
@@ -109,16 +109,19 @@ public:
   nsresult InvalidateRegion(NPRegion invalidRegion);
   nsresult ForceRedraw();
   nsresult GetMIMEType(const char* *result);
   nsresult GetJSContext(JSContext* *outContext);
   nsresult GetOwner(nsIPluginInstanceOwner **aOwner);
   nsresult SetOwner(nsIPluginInstanceOwner *aOwner);
   nsresult ShowStatus(const char* message);
   nsresult InvalidateOwner();
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+  nsresult HandleGUIEvent(const nsGUIEvent& anEvent, bool* handled);
+#endif
 
   nsNPAPIPlugin* GetPlugin();
 
   nsresult GetNPP(NPP * aNPP);
 
   void SetURI(nsIURI* uri);
   nsIURI* GetURI();
 
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -1683,16 +1683,39 @@ nsresult nsPluginInstanceOwner::Dispatch
     }
     else NS_ASSERTION(PR_FALSE, "nsPluginInstanceOwner::DispatchFocusToPlugin failed, focusEvent null");   
   }
   else NS_ASSERTION(PR_FALSE, "nsPluginInstanceOwner::DispatchFocusToPlugin failed, privateEvent null");   
   
   return NS_OK;
 }    
 
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+nsresult nsPluginInstanceOwner::Text(nsIDOMEvent* aTextEvent)
+{
+  if (mInstance) {
+    nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aTextEvent));
+    if (privateEvent) {
+      nsEvent *event = privateEvent->GetInternalNSEvent();
+      if (event && event->eventStructType == NS_TEXT_EVENT) {
+        nsEventStatus rv = ProcessEvent(*static_cast<nsGUIEvent*>(event));
+        if (nsEventStatus_eConsumeNoDefault == rv) {
+          aTextEvent->PreventDefault();
+          aTextEvent->StopPropagation();
+        }
+      }
+      else NS_ASSERTION(PR_FALSE, "nsPluginInstanceOwner::DispatchTextToPlugin failed, textEvent null");
+    }
+    else NS_ASSERTION(PR_FALSE, "nsPluginInstanceOwner::DispatchTextToPlugin failed, privateEvent null");
+  }
+
+  return NS_OK;
+}
+#endif
+
 nsresult nsPluginInstanceOwner::KeyPress(nsIDOMEvent* aKeyEvent)
 {
 #ifdef XP_MACOSX
 #ifndef NP_NO_CARBON
   if (GetEventModel() == NPEventModelCarbon) {
     // KeyPress events are really synthesized keyDown events.
     // Here we check the native message of the event so that
     // we won't send the plugin two keyDown events.
@@ -1866,16 +1889,21 @@ nsPluginInstanceOwner::HandleEvent(nsIDO
   }
   if (eventType.EqualsLiteral("keydown") ||
       eventType.EqualsLiteral("keyup")) {
     return DispatchKeyToPlugin(aEvent);
   }
   if (eventType.EqualsLiteral("keypress")) {
     return KeyPress(aEvent);
   }
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+  if (eventType.EqualsLiteral("text")) {
+    return Text(aEvent);
+  }
+#endif
 
   nsCOMPtr<nsIDOMDragEvent> dragEvent(do_QueryInterface(aEvent));
   if (dragEvent && mInstance) {
     nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aEvent));
     if (privateEvent) {
       nsEvent* ievent = privateEvent->GetInternalNSEvent();
       if ((ievent && NS_IS_TRUSTED_EVENT(ievent)) &&
            ievent->message != NS_DRAGDROP_ENTER && ievent->message != NS_DRAGDROP_OVER) {
@@ -2363,20 +2391,39 @@ nsEventStatus nsPluginInstanceOwner::Pro
           event.same_screen = False;
         }
       else
         {
           // If we need to send synthesized key events, then
           // DOMKeyCodeToGdkKeyCode(keyEvent.keyCode) and
           // gdk_keymap_get_entries_for_keyval will be useful, but the
           // mappings will not be unique.
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+          bool handled;
+          if (NS_SUCCEEDED(mInstance->HandleGUIEvent(anEvent, &handled)) &&
+              handled) {
+            rv = nsEventStatus_eConsumeNoDefault;
+          }
+#else
           NS_WARNING("Synthesized key event not sent to plugin");
+#endif
         }
       break;
 
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+   case NS_TEXT_EVENT:
+        {
+          bool handled;
+          if (NS_SUCCEEDED(mInstance->HandleGUIEvent(anEvent, &handled)) &&
+              handled) {
+            rv = nsEventStatus_eConsumeNoDefault;
+          }
+        }
+      break;
+#endif
     default: 
       switch (anEvent.message)
         {
         case NS_FOCUS_CONTENT:
         case NS_BLUR_CONTENT:
           {
             XFocusChangeEvent &event = pluginEvent.xfocus;
             event.type =
@@ -2447,16 +2494,19 @@ nsPluginInstanceOwner::Destroy()
   mContent->RemoveEventListener(NS_LITERAL_STRING("drag"), this, PR_TRUE);
   mContent->RemoveEventListener(NS_LITERAL_STRING("dragenter"), this, PR_TRUE);
   mContent->RemoveEventListener(NS_LITERAL_STRING("dragover"), this, PR_TRUE);
   mContent->RemoveEventListener(NS_LITERAL_STRING("dragleave"), this, PR_TRUE);
   mContent->RemoveEventListener(NS_LITERAL_STRING("dragexit"), this, PR_TRUE);
   mContent->RemoveEventListener(NS_LITERAL_STRING("dragstart"), this, PR_TRUE);
   mContent->RemoveEventListener(NS_LITERAL_STRING("draggesture"), this, PR_TRUE);
   mContent->RemoveEventListener(NS_LITERAL_STRING("dragend"), this, PR_TRUE);
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+  mContent->RemoveEventListener(NS_LITERAL_STRING("text"), this, PR_TRUE);
+#endif
 
   if (mWidget) {
     nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
     if (pluginWidget)
       pluginWidget->SetPluginInstanceOwner(nsnull);
 
     if (mDestroyWidget)
       mWidget->Destroy();
@@ -2907,16 +2957,19 @@ nsresult nsPluginInstanceOwner::Init(nsP
   mContent->AddEventListener(NS_LITERAL_STRING("drag"), this, PR_TRUE);
   mContent->AddEventListener(NS_LITERAL_STRING("dragenter"), this, PR_TRUE);
   mContent->AddEventListener(NS_LITERAL_STRING("dragover"), this, PR_TRUE);
   mContent->AddEventListener(NS_LITERAL_STRING("dragleave"), this, PR_TRUE);
   mContent->AddEventListener(NS_LITERAL_STRING("dragexit"), this, PR_TRUE);
   mContent->AddEventListener(NS_LITERAL_STRING("dragstart"), this, PR_TRUE);
   mContent->AddEventListener(NS_LITERAL_STRING("draggesture"), this, PR_TRUE);
   mContent->AddEventListener(NS_LITERAL_STRING("dragend"), this, PR_TRUE);
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+  mContent->AddEventListener(NS_LITERAL_STRING("text"), this, PR_TRUE);
+#endif
   
   // Register scroll position listeners
   // We need to register a scroll position listener on every scrollable
   // frame up to the top
   for (nsIFrame* f = mObjectFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
     nsIScrollableFrame* sf = do_QueryFrame(f);
     if (sf) {
       sf->AddScrollPositionListener(this);
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -125,16 +125,19 @@ public:
   //nsIPluginTagInfo interface
   NS_DECL_NSIPLUGINTAGINFO
   
   // nsIDOMEventListener interfaces 
   NS_DECL_NSIDOMEVENTLISTENER
   
   nsresult MouseDown(nsIDOMEvent* aKeyEvent);
   nsresult KeyPress(nsIDOMEvent* aKeyEvent);
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+  nsresult Text(nsIDOMEvent* aTextEvent);
+#endif
 
   nsresult Destroy();  
   
   void PrepareToStop(PRBool aDelayedStop);
   
 #ifdef XP_WIN
   void Paint(const RECT& aDirty, HDC aDC);
 #elif defined(XP_MACOSX)
--- a/dom/plugins/ipc/PPluginInstance.ipdl
+++ b/dom/plugins/ipc/PPluginInstance.ipdl
@@ -41,29 +41,32 @@ include protocol PPluginBackgroundDestro
 include protocol PPluginModule;
 include protocol PPluginScriptableObject;
 include protocol PBrowserStream;
 include protocol PPluginStream;
 include protocol PStreamNotify;
 include protocol PPluginSurface;
 
 include "mozilla/plugins/PluginMessageUtils.h";
+include "IPC/nsGUIEventIPC.h";
 
 using NPError;
 using NPRemoteWindow;
 using NPRemoteEvent;
 using NPRect;
 using NPNURLVariable;
 using NPCoordinateSpace;
 using mozilla::plugins::NativeWindowHandle;
 using mozilla::gfxSurfaceType;
 using gfxIntSize;
 using mozilla::null_t;
 using mozilla::plugins::WindowsSharedMemoryHandle;
 using nsIntRect;
+using nsTextEvent;
+using nsKeyEvent;
 
 namespace mozilla {
 namespace plugins {
 
 struct SurfaceDescriptorX11 {
   int XID;
   int xrenderPictID;
   gfxIntSize size;
@@ -142,16 +145,21 @@ child:
 
   // There is now an opaque background behind this instance (or the
   // background was updated).  The changed area is |rect|.  The
   // browser owns the background surface, and it's read-only from
   // within the plugin process.  |background| is either null_t to
   // refer to the existing background or a fresh descriptor.
   async UpdateBackground(SurfaceDescriptor background, nsIntRect rect);
 
+  rpc HandleTextEvent(nsTextEvent event)
+    returns (bool handled);
+  rpc HandleKeyEvent(nsKeyEvent event)
+    returns (bool handled);
+
   rpc NPP_Destroy()
     returns (NPError rv);
 
 parent:
   rpc NPN_GetValue_NPNVjavascriptEnabledBool()
     returns (bool value, NPError result);
   rpc NPN_GetValue_NPNVisOfflineBool()
     returns (bool value, NPError result);
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -32,16 +32,24 @@
  * 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 ***** */
 
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+#include <QEvent>
+#include <QKeyEvent>
+#include <QApplication>
+#include <QInputMethodEvent>
+#include "nsQtKeyUtils.h"
+#endif
+
 #include "PluginBackgroundDestroyer.h"
 #include "PluginInstanceChild.h"
 #include "PluginModuleChild.h"
 #include "BrowserStreamChild.h"
 #include "PluginStreamChild.h"
 #include "StreamNotifyChild.h"
 #include "PluginProcessChild.h"
 #include "gfxASurface.h"
@@ -69,16 +77,18 @@ using namespace mozilla::plugins;
 
 #include <gtk/gtk.h>
 #include <gdk/gdkx.h>
 #include <gdk/gdk.h>
 #include "gtk2xtbin.h"
 
 #elif defined(MOZ_WIDGET_QT)
 #include <QX11Info>
+#undef KeyPress
+#undef KeyRelease
 #elif defined(OS_WIN)
 #ifndef WM_MOUSEHWHEEL
 #define WM_MOUSEHWHEEL     0x020E
 #endif
 
 #include "nsWindowsDllInterceptor.h"
 
 typedef BOOL (WINAPI *User32TrackPopupMenu)(HMENU hMenu,
@@ -2312,16 +2322,67 @@ PluginInstanceChild::RecvAsyncSetWindow(
         MessageLoop::current()->PostTask(FROM_HERE, mCurrentAsyncSetWindowTask);
     } else {
         DoAsyncSetWindow(aSurfaceType, aWindow, false);
     }
 
     return true;
 }
 
+bool
+PluginInstanceChild::AnswerHandleKeyEvent(const nsKeyEvent& aKeyEvent,
+                                          bool* handled)
+{
+    AssertPluginThread();
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+    Qt::KeyboardModifiers modifier;
+    if (aKeyEvent.isShift)
+        modifier |= Qt::ShiftModifier;
+    if (aKeyEvent.isControl)
+        modifier |= Qt::ControlModifier;
+    if (aKeyEvent.isAlt)
+        modifier |= Qt::AltModifier;
+    if (aKeyEvent.isMeta)
+        modifier |= Qt::MetaModifier;
+
+    QEvent::Type type;
+    if (aKeyEvent.message == NS_KEY_DOWN) {
+        type = QEvent::KeyPress;
+    } else if (aKeyEvent.message == NS_KEY_UP) {
+        type = QEvent::KeyRelease;
+    } else {
+        *handled = false;
+        return true;
+    }
+    QKeyEvent keyEv(type, DOMKeyCodeToQtKeyCode(aKeyEvent.keyCode), modifier);
+    *handled = QApplication::sendEvent(qApp, &keyEv);
+#else
+    NS_ERROR("Not implemented");
+#endif
+
+    return true;
+}
+
+bool
+PluginInstanceChild::AnswerHandleTextEvent(const nsTextEvent& aEvent,
+                                           bool* handled)
+{
+    AssertPluginThread();
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+    QInputMethodEvent event;
+    event.setCommitString(QString((const QChar*)aEvent.theText.get(),
+                          aEvent.theText.Length()));
+    *handled = QApplication::sendEvent(qApp, &event);
+#else
+    NS_ERROR("Not implemented");
+#endif
+
+    return true;
+}
+
 void
 PluginInstanceChild::DoAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
                                       const NPRemoteWindow& aWindow,
                                       bool aIsAsync)
 {
     PLUGIN_LOG_DEBUG(
         ("[InstanceChild][%p] AsyncSetWindow to <x=%d,y=%d, w=%d,h=%d>",
          this, aWindow.x, aWindow.y, aWindow.width, aWindow.height));
--- a/dom/plugins/ipc/PluginInstanceChild.h
+++ b/dom/plugins/ipc/PluginInstanceChild.h
@@ -115,16 +115,21 @@ protected:
     RecvAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
                        const NPRemoteWindow& aWindow);
 
     virtual void
     DoAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
                      const NPRemoteWindow& aWindow,
                      bool aIsAsync);
 
+    virtual bool
+    AnswerHandleKeyEvent(const nsKeyEvent& aEvent, bool* handled);
+    virtual bool
+    AnswerHandleTextEvent(const nsTextEvent& aEvent, bool* handled);
+
     virtual PPluginSurfaceChild* AllocPPluginSurface(const WindowsSharedMemoryHandle&,
                                                      const gfxIntSize&, const bool&) {
         return new PPluginSurfaceChild();
     }
 
     virtual bool DeallocPPluginSurface(PPluginSurfaceChild* s) {
         delete s;
         return true;
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -613,16 +613,41 @@ PluginInstanceParent::AsyncSetWindow(NPW
     window.type = aWindow->type;
     if (!SendAsyncSetWindow(gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType(),
                             window))
         return NS_ERROR_FAILURE;
 
     return NS_OK;
 }
 
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+nsresult
+PluginInstanceParent::HandleGUIEvent(const nsGUIEvent& anEvent, bool* handled)
+{
+    switch (anEvent.eventStructType) {
+    case NS_KEY_EVENT:
+        if (!CallHandleKeyEvent(static_cast<const nsKeyEvent&>(anEvent),
+                                handled)) {
+            return NS_ERROR_FAILURE;
+        }
+        break;
+    case NS_TEXT_EVENT:
+        if (!CallHandleTextEvent(static_cast<const nsTextEvent&>(anEvent),
+                                 handled)) {
+            return NS_ERROR_FAILURE;
+        }
+        break;
+    default:
+        NS_ERROR("Not implemented for this event type");
+        return NS_ERROR_FAILURE;
+    }
+    return NS_OK;
+}
+#endif
+
 nsresult
 PluginInstanceParent::GetImage(ImageContainer* aContainer, Image** aImage)
 {
 #ifdef XP_MACOSX
     nsIOSurface* ioSurface = NULL;
   
     if (mFrontIOSurface) {
       ioSurface = mFrontIOSurface;
--- a/dom/plugins/ipc/PluginInstanceParent.h
+++ b/dom/plugins/ipc/PluginInstanceParent.h
@@ -52,16 +52,17 @@
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsRect.h"
 #include "gfxASurface.h"
 #include "ImageLayers.h"
 #ifdef MOZ_X11
 class gfxXlibSurface;
 #endif
+#include "nsGUIEvent.h"
 
 namespace mozilla {
 namespace plugins {
 
 class PBrowserStreamParent;
 class PluginModuleParent;
 
 class PluginInstanceParent : public PPluginInstanceParent
@@ -285,16 +286,19 @@ public:
 #ifdef XP_MACOSX
     nsresult IsRemoteDrawingCoreAnimation(PRBool *aDrawing);
 #endif
     nsresult SetBackgroundUnknown();
     nsresult BeginUpdateBackground(const nsIntRect& aRect,
                                    gfxContext** aCtx);
     nsresult EndUpdateBackground(gfxContext* aCtx,
                                  const nsIntRect& aRect);
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+    nsresult HandleGUIEvent(const nsGUIEvent& anEvent, bool* handled);
+#endif
 
 private:
     // Create an appropriate platform surface for a background of size
     // |aSize|.  Return true if successful.
     bool CreateBackground(const nsIntSize& aSize);
     void DestroyBackground();
     SurfaceDescriptor BackgroundDescriptor() /*const*/;
 
--- a/dom/plugins/ipc/PluginLibrary.h
+++ b/dom/plugins/ipc/PluginLibrary.h
@@ -47,16 +47,17 @@
 #include "nsPluginError.h"
 
 class gfxASurface;
 class gfxContext;
 class nsCString;
 struct nsIntRect;
 struct nsIntSize;
 class nsNPAPIPlugin;
+class nsGUIEvent;
 
 namespace mozilla {
 namespace layers {
 class Image;
 class ImageContainer;
 }
 }
 
@@ -111,14 +112,17 @@ public:
    * PluginInstanceParent.  They approximately follow the ReadbackSink
    * API.
    */
   virtual nsresult SetBackgroundUnknown(NPP instance) = 0;
   virtual nsresult BeginUpdateBackground(NPP instance,
                                          const nsIntRect&, gfxContext**) = 0;
   virtual nsresult EndUpdateBackground(NPP instance,
                                        gfxContext*, const nsIntRect&) = 0;
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+  virtual nsresult HandleGUIEvent(NPP instance, const nsGUIEvent&, bool*) = 0;
+#endif
 };
 
 
 } // namespace mozilla
 
 #endif  // ifndef mozilla_PluginLibrary_h
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -698,16 +698,30 @@ PluginModuleParent::AsyncSetWindow(NPP i
 {
     PluginInstanceParent* i = InstCast(instance);
     if (!i)
         return NS_ERROR_FAILURE;
 
     return i->AsyncSetWindow(window);
 }
 
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+nsresult
+PluginModuleParent::HandleGUIEvent(NPP instance,
+                                   const nsGUIEvent& anEvent,
+                                   bool* handled)
+{
+    PluginInstanceParent* i = InstCast(instance);
+    if (!i)
+        return NS_ERROR_FAILURE;
+
+    return i->HandleGUIEvent(anEvent, handled);
+}
+#endif
+
 nsresult
 PluginModuleParent::GetImage(NPP instance,
                              mozilla::layers::ImageContainer* aContainer,
                              mozilla::layers::Image** aImage)
 {
     PluginInstanceParent* i = InstCast(instance);
     return !i ? NS_ERROR_FAILURE : i->GetImage(aContainer, aImage);
 }
--- a/dom/plugins/ipc/PluginModuleParent.h
+++ b/dom/plugins/ipc/PluginModuleParent.h
@@ -291,16 +291,20 @@ private:
                              NPError* error);
     virtual nsresult NPP_ClearSiteData(const char* site, uint64_t flags,
                                        uint64_t maxAge);
     virtual nsresult NPP_GetSitesWithData(InfallibleTArray<nsCString>& result);
 
 #if defined(XP_MACOSX)
     virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, PRBool *aDrawing);
 #endif
+#if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
+    virtual nsresult HandleGUIEvent(NPP instance, const nsGUIEvent& anEvent,
+                                    bool* handled);
+#endif
 
 private:
     void WritePluginExtraDataForMinidump(const nsAString& id);
     void WriteExtraDataForHang();
     void CleanupFromTimeout();
     static int TimeoutChanged(const char* aPref, void* aModule);
     void NotifyPluginCrashed();
 
--- a/widget/public/nsGUIEvent.h
+++ b/widget/public/nsGUIEvent.h
@@ -61,16 +61,19 @@
 #include "nsIVariant.h"
 #include "nsStyleConsts.h"
 
 namespace mozilla {
 namespace dom {
   class PBrowserParent;
   class PBrowserChild;
 }
+namespace plugins {
+  class PPluginInstanceChild;
+}
 }
 
 #ifdef ACCESSIBILITY
 class nsAccessible;
 #endif
 class nsRenderingContext;
 class nsIMenuItem;
 class nsIContent;
@@ -1117,16 +1120,17 @@ struct nsTextRange
 
 typedef nsTextRange* nsTextRangeArray;
 
 class nsTextEvent : public nsInputEvent
 {
 private:
   friend class mozilla::dom::PBrowserParent;
   friend class mozilla::dom::PBrowserChild;
+  friend class mozilla::plugins::PPluginInstanceChild;
 
   nsTextEvent()
   {
   }
 
 public:
   PRUint32 seqno;
 
--- a/widget/src/qt/Makefile.in
+++ b/widget/src/qt/Makefile.in
@@ -77,16 +77,20 @@ CPPSRCS	= \
 		nsSound.cpp \
 		nsFilePicker.cpp \
 		nsPrintOptionsQt.cpp \
 		nsPrintSettingsQt.cpp \
 		nsPrintDialogQt.cpp \
 		nsDeviceContextSpecQt.cpp \
 		$(NULL)
 
+EXPORTS		= \
+		nsQtKeyUtils.h \
+		$(NULL)
+
 ifdef MOZ_ENABLE_QTMOBILITY
 MOCSRCS += moc_mozqorientationsensorfilter.cpp
 CPPSRCS += mozqorientationsensorfilter.cpp
 endif
 
 SHARED_LIBRARY_LIBS = ../xpwidgets/libxpwidgets_s.a
 
 # If not primary toolkit, install in secondary path