LCOV - code coverage report
Current view: directory - dom/plugins/base - nsPluginNativeWindowGtk2.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 131 0 0.0 %
Date: 2012-06-02 Functions: 11 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim:expandtab:shiftwidth=2:tabstop=2:
       3                 : */
       4                 : /* ***** BEGIN LICENSE BLOCK *****
       5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       6                 :  *
       7                 :  * The contents of this file are subject to the Mozilla Public License Version
       8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       9                 :  * the License. You may obtain a copy of the License at
      10                 :  * http://www.mozilla.org/MPL/
      11                 :  *
      12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      14                 :  * for the specific language governing rights and limitations under the
      15                 :  * License.
      16                 :  *
      17                 :  * The Original Code is mozilla.org code.
      18                 :  *
      19                 :  * The Initial Developer of the Original Code is
      20                 :  * Sun Microsystems, Inc.
      21                 :  * Portions created by the Initial Developer are Copyright (C) 2003
      22                 :  * the Initial Developer. All Rights Reserved.
      23                 :  *
      24                 :  * Contributor(s):
      25                 :  *   Robin Lu <robin.lu@sun.com>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      29                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : /**
      42                 :  *  This file is the Gtk2 implementation of plugin native window.
      43                 :  */
      44                 : 
      45                 : #include "nsDebug.h"
      46                 : #include "nsPluginNativeWindow.h"
      47                 : #include "npapi.h"
      48                 : #include <gtk/gtk.h>
      49                 : #include <gdk/gdkx.h>
      50                 : #include <gdk/gdk.h>
      51                 : 
      52                 : #include "gtk2xtbin.h"
      53                 : 
      54                 : class nsPluginNativeWindowGtk2 : public nsPluginNativeWindow {
      55                 : public: 
      56                 :   nsPluginNativeWindowGtk2();
      57                 :   virtual ~nsPluginNativeWindowGtk2();
      58                 : 
      59                 :   virtual nsresult CallSetWindow(nsRefPtr<nsNPAPIPluginInstance> &aPluginInstance);
      60                 : private:
      61                 :   NPSetWindowCallbackStruct mWsInfo;
      62                 :   /**
      63                 :    * Either a GtkSocket or a special GtkXtBin widget (derived from GtkSocket)
      64                 :    * that encapsulates the Xt toolkit within a Gtk Application.
      65                 :    */
      66                 :   GtkWidget* mSocketWidget;
      67                 :   nsresult  CreateXEmbedWindow();
      68                 :   nsresult  CreateXtWindow();
      69                 :   void      SetAllocation();
      70                 : };
      71                 : 
      72                 : static gboolean plug_removed_cb   (GtkWidget *widget, gpointer data);
      73                 : static void socket_unrealize_cb   (GtkWidget *widget, gpointer data);
      74                 : 
      75               0 : nsPluginNativeWindowGtk2::nsPluginNativeWindowGtk2() : nsPluginNativeWindow()
      76                 : {
      77                 :   // initialize the struct fields
      78               0 :   window = nsnull; 
      79               0 :   x = 0; 
      80               0 :   y = 0; 
      81               0 :   width = 0; 
      82               0 :   height = 0; 
      83               0 :   memset(&clipRect, 0, sizeof(clipRect));
      84               0 :   ws_info = &mWsInfo;
      85               0 :   type = NPWindowTypeWindow;
      86               0 :   mSocketWidget = 0;
      87               0 :   mWsInfo.type = 0;
      88               0 :   mWsInfo.display = nsnull;
      89               0 :   mWsInfo.visual = nsnull;
      90               0 :   mWsInfo.colormap = 0;
      91               0 :   mWsInfo.depth = 0;
      92               0 : }
      93                 : 
      94               0 : nsPluginNativeWindowGtk2::~nsPluginNativeWindowGtk2() 
      95                 : {
      96               0 :   if(mSocketWidget) {
      97               0 :     gtk_widget_destroy(mSocketWidget);
      98                 :   }
      99               0 : }
     100                 : 
     101               0 : nsresult PLUG_NewPluginNativeWindow(nsPluginNativeWindow ** aPluginNativeWindow)
     102                 : {
     103               0 :   NS_ENSURE_ARG_POINTER(aPluginNativeWindow);
     104               0 :   *aPluginNativeWindow = new nsPluginNativeWindowGtk2();
     105               0 :   return *aPluginNativeWindow ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
     106                 : }
     107                 : 
     108               0 : nsresult PLUG_DeletePluginNativeWindow(nsPluginNativeWindow * aPluginNativeWindow)
     109                 : {
     110               0 :   NS_ENSURE_ARG_POINTER(aPluginNativeWindow);
     111               0 :   nsPluginNativeWindowGtk2 *p = (nsPluginNativeWindowGtk2 *)aPluginNativeWindow;
     112               0 :   delete p;
     113               0 :   return NS_OK;
     114                 : }
     115                 : 
     116               0 : nsresult nsPluginNativeWindowGtk2::CallSetWindow(nsRefPtr<nsNPAPIPluginInstance> &aPluginInstance)
     117                 : {
     118               0 :   if (aPluginInstance) {
     119               0 :     if (type == NPWindowTypeWindow) {
     120               0 :       if (!mSocketWidget) {
     121                 :         nsresult rv;
     122                 : 
     123                 :         // The documentation on the types for many variables in NP(N|P)_GetValue
     124                 :         // is vague.  Often boolean values are NPBool (1 byte), but
     125                 :         // https://developer.mozilla.org/en/XEmbed_Extension_for_Mozilla_Plugins
     126                 :         // treats NPPVpluginNeedsXEmbed as PRBool (int), and
     127                 :         // on x86/32-bit, flash stores to this using |movl 0x1,&needsXEmbed|.
     128                 :         // thus we can't use NPBool for needsXEmbed, or the three bytes above
     129                 :         // it on the stack would get clobbered. so protect with the larger bool.
     130               0 :         int needsXEmbed = 0;
     131               0 :         rv = aPluginInstance->GetValueFromPlugin(NPPVpluginNeedsXEmbed, &needsXEmbed);
     132                 :         // If the call returned an error code make sure we still use our default value.
     133               0 :         if (NS_FAILED(rv)) {
     134               0 :           needsXEmbed = 0;
     135                 :         }
     136                 : #ifdef DEBUG
     137               0 :         printf("nsPluginNativeWindowGtk2: NPPVpluginNeedsXEmbed=%d\n", needsXEmbed);
     138                 : #endif
     139                 : 
     140               0 :         if (needsXEmbed) {
     141               0 :           rv = CreateXEmbedWindow();
     142                 :         }
     143                 :         else {
     144               0 :           rv = CreateXtWindow();
     145                 :         }
     146                 : 
     147               0 :         if (NS_FAILED(rv)) {
     148               0 :           return NS_ERROR_FAILURE;
     149                 :         }
     150                 :       }
     151                 : 
     152               0 :       if (!mSocketWidget) {
     153               0 :         return NS_ERROR_FAILURE;
     154                 :       }
     155                 : 
     156                 :       // Make sure to resize and re-place the window if required.
     157                 :       // Need to reset "window" each time as nsObjectFrame::DidReflow sets it
     158                 :       // to the ancestor window.
     159               0 :       if (GTK_IS_XTBIN(mSocketWidget)) {
     160               0 :         gtk_xtbin_resize(mSocketWidget, width, height);
     161                 :         // Point the NPWindow structures window to the actual X window
     162               0 :         window = (void*)GTK_XTBIN(mSocketWidget)->xtwindow;
     163                 :       }
     164                 :       else { // XEmbed
     165               0 :         SetAllocation();
     166               0 :         window = (void*)gtk_socket_get_id(GTK_SOCKET(mSocketWidget));
     167                 :       }
     168                 : #ifdef DEBUG
     169               0 :       printf("nsPluginNativeWindowGtk2: call SetWindow with xid=%p\n", (void *)window);
     170                 : #endif
     171                 :     } // NPWindowTypeWindow
     172               0 :     aPluginInstance->SetWindow(this);
     173                 :   }
     174               0 :   else if (mPluginInstance)
     175               0 :     mPluginInstance->SetWindow(nsnull);
     176                 : 
     177               0 :   SetPluginInstance(aPluginInstance);
     178               0 :   return NS_OK;
     179                 : }
     180                 : 
     181               0 : nsresult nsPluginNativeWindowGtk2::CreateXEmbedWindow() {
     182               0 :   NS_ASSERTION(!mSocketWidget,"Already created a socket widget!");
     183                 : 
     184               0 :   GdkWindow *parent_win = gdk_window_lookup((XID)window);
     185               0 :   mSocketWidget = gtk_socket_new();
     186                 : 
     187                 :   //attach the socket to the container widget
     188               0 :   gtk_widget_set_parent_window(mSocketWidget, parent_win);
     189                 : 
     190                 :   // Make sure to handle the plug_removed signal.  If we don't the
     191                 :   // socket will automatically be destroyed when the plug is
     192                 :   // removed, which means we're destroying it more than once.
     193                 :   // SYNTAX ERROR.
     194               0 :   g_signal_connect(mSocketWidget, "plug_removed",
     195               0 :                    G_CALLBACK(plug_removed_cb), NULL);
     196                 : 
     197               0 :   g_signal_connect(mSocketWidget, "unrealize",
     198               0 :                    G_CALLBACK(socket_unrealize_cb), NULL);
     199                 : 
     200               0 :   g_signal_connect(mSocketWidget, "destroy",
     201               0 :                    G_CALLBACK(gtk_widget_destroyed), &mSocketWidget);
     202                 : 
     203               0 :   gpointer user_data = NULL;
     204               0 :   gdk_window_get_user_data(parent_win, &user_data);
     205                 : 
     206               0 :   GtkContainer *container = GTK_CONTAINER(user_data);
     207               0 :   gtk_container_add(container, mSocketWidget);
     208               0 :   gtk_widget_realize(mSocketWidget);
     209                 : 
     210                 :   // The GtkSocket has a visible window, but the plugin's XEmbed plug will
     211                 :   // cover this window.  Normally GtkSockets let the X server paint their
     212                 :   // background and this would happen immediately (before the plug is
     213                 :   // created).  Setting the background to None prevents the server from
     214                 :   // painting this window, avoiding flicker.
     215               0 :   gdk_window_set_back_pixmap(mSocketWidget->window, NULL, FALSE);
     216                 : 
     217                 :   // Resize before we show
     218               0 :   SetAllocation();
     219                 : 
     220               0 :   gtk_widget_show(mSocketWidget);
     221                 : 
     222               0 :   gdk_flush();
     223               0 :   window = (void*)gtk_socket_get_id(GTK_SOCKET(mSocketWidget));
     224                 : 
     225                 :   // Fill out the ws_info structure.
     226                 :   // (The windowless case is done in nsObjectFrame.cpp.)
     227               0 :   GdkWindow *gdkWindow = gdk_window_lookup((XID)window);
     228               0 :   if(!gdkWindow)
     229               0 :     return NS_ERROR_FAILURE;
     230                 : 
     231               0 :   mWsInfo.display = GDK_WINDOW_XDISPLAY(gdkWindow);
     232               0 :   mWsInfo.colormap = GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(gdkWindow));
     233               0 :   GdkVisual* gdkVisual = gdk_drawable_get_visual(gdkWindow);
     234               0 :   mWsInfo.visual = GDK_VISUAL_XVISUAL(gdkVisual);
     235               0 :   mWsInfo.depth = gdkVisual->depth;
     236                 : 
     237               0 :   return NS_OK;
     238                 : }
     239                 : 
     240               0 : void nsPluginNativeWindowGtk2::SetAllocation() {
     241               0 :   if (!mSocketWidget)
     242               0 :     return;
     243                 : 
     244                 :   GtkAllocation new_allocation;
     245               0 :   new_allocation.x = 0;
     246               0 :   new_allocation.y = 0;
     247               0 :   new_allocation.width = width;
     248               0 :   new_allocation.height = height;
     249               0 :   gtk_widget_size_allocate(mSocketWidget, &new_allocation);
     250                 : }
     251                 : 
     252               0 : nsresult nsPluginNativeWindowGtk2::CreateXtWindow() {
     253               0 :   NS_ASSERTION(!mSocketWidget,"Already created a socket widget!");
     254                 : 
     255                 : #ifdef NS_DEBUG      
     256                 :   printf("About to create new xtbin of %i X %i from %p...\n",
     257               0 :          width, height, (void*)window);
     258                 : #endif
     259               0 :   GdkWindow *gdkWindow = gdk_window_lookup((XID)window);
     260               0 :   mSocketWidget = gtk_xtbin_new(gdkWindow, 0);
     261                 :   // Check to see if creating the xtbin failed for some reason.
     262                 :   // if it did, we can't go any further.
     263               0 :   if (!mSocketWidget)
     264               0 :     return NS_ERROR_FAILURE;
     265                 : 
     266               0 :   g_signal_connect(mSocketWidget, "destroy",
     267               0 :                    G_CALLBACK(gtk_widget_destroyed), &mSocketWidget);
     268                 : 
     269               0 :   gtk_widget_set_size_request(mSocketWidget, width, height);
     270                 : 
     271                 : #ifdef NS_DEBUG
     272               0 :   printf("About to show xtbin(%p)...\n", (void*)mSocketWidget); fflush(NULL);
     273                 : #endif
     274               0 :   gtk_widget_show(mSocketWidget);
     275                 : #ifdef NS_DEBUG
     276               0 :   printf("completed gtk_widget_show(%p)\n", (void*)mSocketWidget); fflush(NULL);
     277                 : #endif
     278                 : 
     279                 :   // Fill out the ws_info structure.
     280               0 :   GtkXtBin* xtbin = GTK_XTBIN(mSocketWidget);
     281                 :   // The xtbin has its own Display structure.
     282               0 :   mWsInfo.display = xtbin->xtdisplay;
     283               0 :   mWsInfo.colormap = xtbin->xtclient.xtcolormap;
     284               0 :   mWsInfo.visual = xtbin->xtclient.xtvisual;
     285               0 :   mWsInfo.depth = xtbin->xtclient.xtdepth;
     286                 :   // Leave mWsInfo.type = 0 - Who knows what this is meant to be?
     287                 : 
     288               0 :   XFlush(mWsInfo.display);
     289                 : 
     290               0 :   return NS_OK;
     291                 : }
     292                 : 
     293                 : /* static */
     294                 : gboolean
     295               0 : plug_removed_cb (GtkWidget *widget, gpointer data)
     296                 : {
     297                 :   // Gee, thanks for the info!
     298               0 :   return TRUE;
     299                 : }
     300                 : 
     301                 : static void
     302               0 : socket_unrealize_cb(GtkWidget *widget, gpointer data)
     303                 : {
     304                 :   // Unmap and reparent any child windows that GDK does not yet know about.
     305                 :   // (See bug 540114 comment 10.)
     306               0 :   GdkWindow* socket_window = widget->window;
     307               0 :   Display* display = GDK_DISPLAY();
     308                 : 
     309                 :   // Ignore X errors that may happen if windows get destroyed (possibly
     310                 :   // requested by the plugin) between XQueryTree and when we operate on them.
     311               0 :   gdk_error_trap_push();
     312                 : 
     313                 :   Window root, parent;
     314                 :   Window* children;
     315                 :   unsigned int nchildren;
     316               0 :   if (!XQueryTree(display, gdk_x11_drawable_get_xid(socket_window),
     317               0 :                   &root, &parent, &children, &nchildren))
     318               0 :     return;
     319                 : 
     320               0 :   for (unsigned int i = 0; i < nchildren; ++i) {
     321               0 :     Window child = children[i];
     322               0 :     if (!gdk_window_lookup(child)) {
     323                 :       // This window is not known to GDK.
     324               0 :       XUnmapWindow(display, child);
     325               0 :       XReparentWindow(display, child, DefaultRootWindow(display), 0, 0);
     326                 :     }
     327                 :   }
     328                 : 
     329               0 :   if (children) XFree(children);
     330                 : 
     331               0 :   XSync(display, False);
     332               0 :   gdk_error_trap_pop();
     333                 : }

Generated by: LCOV version 1.7