LCOV - code coverage report
Current view: directory - widget/gtk2 - nsWindow.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 2647 6 0.2 %
Date: 2012-06-02 Functions: 205 3 1.5 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* vim:expandtab:shiftwidth=4:tabstop=4:
       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 Christopher Blizzard
      20                 :  * <blizzard@mozilla.org>.  Portions created by the Initial Developer
      21                 :  * are Copyright (C) 2001 the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Mats Palmgren <matspal@gmail.com>
      25                 :  *   Masayuki Nakano <masayuki@d-toybox.com>
      26                 :  *   Martin Stransky <stransky@redhat.com>
      27                 :  *   Jan Horak <jhorak@redhat.com>
      28                 :  *
      29                 :  * Alternatively, the contents of this file may be used under the terms of
      30                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      31                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      32                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      33                 :  * of those above. If you wish to allow use of your version of this file only
      34                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      35                 :  * use your version of this file under the terms of the MPL, indicate your
      36                 :  * decision by deleting the provisions above and replace them with the notice
      37                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      38                 :  * the provisions above, a recipient may use your version of this file under
      39                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      40                 :  *
      41                 :  * ***** END LICENSE BLOCK ***** */
      42                 : 
      43                 : #include "mozilla/Util.h"
      44                 : 
      45                 : #ifdef MOZ_PLATFORM_MAEMO
      46                 : // needed to include hildon parts in gtk.h
      47                 : #define MAEMO_CHANGES
      48                 : #endif
      49                 : 
      50                 : #include "prlink.h"
      51                 : #include "nsWindow.h"
      52                 : #include "nsGTKToolkit.h"
      53                 : #include "nsIRollupListener.h"
      54                 : #include "nsIDOMNode.h"
      55                 : 
      56                 : #include "nsWidgetsCID.h"
      57                 : #include "nsDragService.h"
      58                 : #include "nsIDragSessionGTK.h"
      59                 : 
      60                 : #include "nsGtkKeyUtils.h"
      61                 : #include "nsGtkCursors.h"
      62                 : 
      63                 : #include <gtk/gtk.h>
      64                 : #if defined(MOZ_WIDGET_GTK3)
      65                 : #include <gtk/gtkx.h>
      66                 : #endif
      67                 : #ifdef MOZ_X11
      68                 : #include <gdk/gdkx.h>
      69                 : #include <X11/Xatom.h>
      70                 : #include <X11/extensions/XShm.h>
      71                 : #include <X11/extensions/shape.h>
      72                 : #if defined(MOZ_WIDGET_GTK3)
      73                 : #include <gdk/gdkkeysyms-compat.h>
      74                 : #endif
      75                 : 
      76                 : #ifdef AIX
      77                 : #include <X11/keysym.h>
      78                 : #else
      79                 : #include <X11/XF86keysym.h>
      80                 : #endif
      81                 : 
      82                 : #include "gtk2xtbin.h"
      83                 : #endif /* MOZ_X11 */
      84                 : #include <gdk/gdkkeysyms.h>
      85                 : #if defined(MOZ_WIDGET_GTK2)
      86                 : #include <gtk/gtkprivate.h>
      87                 : #endif
      88                 : 
      89                 : #if defined(MOZ_WIDGET_GTK2)
      90                 : #include "gtk2compat.h"
      91                 : #endif
      92                 : 
      93                 : #include "nsGkAtoms.h"
      94                 : 
      95                 : #ifdef MOZ_ENABLE_STARTUP_NOTIFICATION
      96                 : #define SN_API_NOT_YET_FROZEN
      97                 : #include <startup-notification-1.0/libsn/sn.h>
      98                 : #endif
      99                 : 
     100                 : #include "mozilla/Preferences.h"
     101                 : #include "nsIPrefService.h"
     102                 : #include "nsIGConfService.h"
     103                 : #include "nsIServiceManager.h"
     104                 : #include "nsIStringBundle.h"
     105                 : #include "nsGfxCIID.h"
     106                 : #include "nsIObserverService.h"
     107                 : 
     108                 : #include "nsIdleService.h"
     109                 : #include "nsIPropertyBag2.h"
     110                 : 
     111                 : #ifdef ACCESSIBILITY
     112                 : #include "nsAccessibilityService.h"
     113                 : #include "nsIAccessibleDocument.h"
     114                 : 
     115                 : using namespace mozilla;
     116                 : using namespace mozilla::widget;
     117                 : #endif
     118                 : 
     119                 : /* For SetIcon */
     120                 : #include "nsAppDirectoryServiceDefs.h"
     121                 : #include "nsXPIDLString.h"
     122                 : #include "nsIFile.h"
     123                 : #include "nsILocalFile.h"
     124                 : 
     125                 : /* SetCursor(imgIContainer*) */
     126                 : #include <gdk/gdk.h>
     127                 : #include <wchar.h>
     128                 : #include "imgIContainer.h"
     129                 : #include "nsGfxCIID.h"
     130                 : #include "nsImageToPixbuf.h"
     131                 : #include "nsIInterfaceRequestorUtils.h"
     132                 : #include "nsAutoPtr.h"
     133                 : 
     134                 : extern "C" {
     135                 : #define PIXMAN_DONT_DEFINE_STDINT
     136                 : #include "pixman.h"
     137                 : }
     138                 : #include "gfxPlatformGtk.h"
     139                 : #include "gfxContext.h"
     140                 : #include "gfxImageSurface.h"
     141                 : #include "gfxUtils.h"
     142                 : #include "Layers.h"
     143                 : #include "LayerManagerOGL.h"
     144                 : #include "GLContextProvider.h"
     145                 : 
     146                 : #ifdef MOZ_X11
     147                 : #include "gfxXlibSurface.h"
     148                 : #include "cairo-xlib.h"
     149                 : #endif
     150                 : 
     151                 : #include "nsShmImage.h"
     152                 : 
     153                 : using namespace mozilla;
     154                 : using namespace mozilla::widget;
     155                 : using mozilla::gl::GLContext;
     156                 : using mozilla::layers::LayerManagerOGL;
     157                 : 
     158                 : // Don't put more than this many rects in the dirty region, just fluff
     159                 : // out to the bounding-box if there are more
     160                 : #define MAX_RECTS_IN_REGION 100
     161                 : 
     162                 : /* utility functions */
     163                 : static bool       check_for_rollup(gdouble aMouseX, gdouble aMouseY,
     164                 :                                    bool aIsWheel, bool aAlwaysRollup);
     165                 : static bool       is_mouse_in_window(GdkWindow* aWindow,
     166                 :                                      gdouble aMouseX, gdouble aMouseY);
     167                 : static nsWindow  *get_window_for_gtk_widget(GtkWidget *widget);
     168                 : static nsWindow  *get_window_for_gdk_window(GdkWindow *window);
     169                 : static GtkWidget *get_gtk_widget_for_gdk_window(GdkWindow *window);
     170                 : static GdkCursor *get_gtk_cursor(nsCursor aCursor);
     171                 : 
     172                 : static GdkWindow *get_inner_gdk_window (GdkWindow *aWindow,
     173                 :                                         gint x, gint y,
     174                 :                                         gint *retx, gint *rety);
     175                 : 
     176                 : static inline bool is_context_menu_key(const nsKeyEvent& inKeyEvent);
     177                 : 
     178                 : static int    is_parent_ungrab_enter(GdkEventCrossing *aEvent);
     179                 : static int    is_parent_grab_leave(GdkEventCrossing *aEvent);
     180                 : 
     181                 : static void GetBrandName(nsXPIDLString& brandName);
     182                 : 
     183                 : /* callbacks from widgets */
     184                 : #if defined(MOZ_WIDGET_GTK2)
     185                 : static gboolean expose_event_cb           (GtkWidget *widget,
     186                 :                                            GdkEventExpose *event);
     187                 : #else
     188                 : static gboolean expose_event_cb           (GtkWidget *widget,
     189                 :                                            cairo_t *rect);
     190                 : #endif
     191                 : static gboolean configure_event_cb        (GtkWidget *widget,
     192                 :                                            GdkEventConfigure *event);
     193                 : static void     container_unrealize_cb    (GtkWidget *widget);
     194                 : static void     size_allocate_cb          (GtkWidget *widget,
     195                 :                                            GtkAllocation *allocation);
     196                 : static gboolean delete_event_cb           (GtkWidget *widget,
     197                 :                                            GdkEventAny *event);
     198                 : static gboolean enter_notify_event_cb     (GtkWidget *widget,
     199                 :                                            GdkEventCrossing *event);
     200                 : static gboolean leave_notify_event_cb     (GtkWidget *widget,
     201                 :                                            GdkEventCrossing *event);
     202                 : static gboolean motion_notify_event_cb    (GtkWidget *widget,
     203                 :                                            GdkEventMotion *event);
     204                 : static gboolean button_press_event_cb     (GtkWidget *widget,
     205                 :                                            GdkEventButton *event);
     206                 : static gboolean button_release_event_cb   (GtkWidget *widget,
     207                 :                                            GdkEventButton *event);
     208                 : static gboolean focus_in_event_cb         (GtkWidget *widget,
     209                 :                                            GdkEventFocus *event);
     210                 : static gboolean focus_out_event_cb        (GtkWidget *widget,
     211                 :                                            GdkEventFocus *event);
     212                 : static gboolean key_press_event_cb        (GtkWidget *widget,
     213                 :                                            GdkEventKey *event);
     214                 : static gboolean key_release_event_cb      (GtkWidget *widget,
     215                 :                                            GdkEventKey *event);
     216                 : static gboolean scroll_event_cb           (GtkWidget *widget,
     217                 :                                            GdkEventScroll *event);
     218                 : static gboolean visibility_notify_event_cb(GtkWidget *widget,
     219                 :                                            GdkEventVisibility *event);
     220                 : static void     hierarchy_changed_cb      (GtkWidget *widget,
     221                 :                                            GtkWidget *previous_toplevel);
     222                 : static gboolean window_state_event_cb     (GtkWidget *widget,
     223                 :                                            GdkEventWindowState *event);
     224                 : static void     theme_changed_cb          (GtkSettings *settings,
     225                 :                                            GParamSpec *pspec,
     226                 :                                            nsWindow *data);
     227                 : static nsWindow* GetFirstNSWindowForGDKWindow (GdkWindow *aGdkWindow);
     228                 : 
     229                 : #ifdef __cplusplus
     230                 : extern "C" {
     231                 : #endif /* __cplusplus */
     232                 : #ifdef MOZ_X11
     233                 : static GdkFilterReturn popup_take_focus_filter (GdkXEvent *gdk_xevent,
     234                 :                                                 GdkEvent *event,
     235                 :                                                 gpointer data);
     236                 : static GdkFilterReturn plugin_window_filter_func (GdkXEvent *gdk_xevent,
     237                 :                                                   GdkEvent *event,
     238                 :                                                   gpointer data);
     239                 : static GdkFilterReturn plugin_client_message_filter (GdkXEvent *xevent,
     240                 :                                                      GdkEvent *event,
     241                 :                                                      gpointer data);
     242                 : #endif /* MOZ_X11 */
     243                 : #ifdef __cplusplus
     244                 : }
     245                 : #endif /* __cplusplus */
     246                 : 
     247                 : static gboolean drag_motion_event_cb      (GtkWidget *aWidget,
     248                 :                                            GdkDragContext *aDragContext,
     249                 :                                            gint aX,
     250                 :                                            gint aY,
     251                 :                                            guint aTime,
     252                 :                                            gpointer aData);
     253                 : static void     drag_leave_event_cb       (GtkWidget *aWidget,
     254                 :                                            GdkDragContext *aDragContext,
     255                 :                                            guint aTime,
     256                 :                                            gpointer aData);
     257                 : static gboolean drag_drop_event_cb        (GtkWidget *aWidget,
     258                 :                                            GdkDragContext *aDragContext,
     259                 :                                            gint aX,
     260                 :                                            gint aY,
     261                 :                                            guint aTime,
     262                 :                                            gpointer aData);
     263                 : static void    drag_data_received_event_cb(GtkWidget *aWidget,
     264                 :                                            GdkDragContext *aDragContext,
     265                 :                                            gint aX,
     266                 :                                            gint aY,
     267                 :                                            GtkSelectionData  *aSelectionData,
     268                 :                                            guint aInfo,
     269                 :                                            guint32 aTime,
     270                 :                                            gpointer aData);
     271                 : 
     272                 : /* initialization static functions */
     273                 : static nsresult    initialize_prefs        (void);
     274                 : 
     275                 : // this is the last window that had a drag event happen on it.
     276                 : nsWindow *nsWindow::sLastDragMotionWindow = NULL;
     277                 : bool nsWindow::sIsDraggingOutOf = false;
     278                 : 
     279                 : // Time of the last button release event. We use it to detect when the
     280                 : // drag ended before we could properly setup drag and drop.
     281                 : guint32   nsWindow::sLastButtonReleaseTime = 0;
     282                 : static guint32 sLastUserInputTime = GDK_CURRENT_TIME;
     283                 : static guint32 sRetryGrabTime;
     284                 : 
     285                 : static NS_DEFINE_IID(kCDragServiceCID,  NS_DRAGSERVICE_CID);
     286                 : 
     287                 : // The window from which the focus manager asks us to dispatch key events.
     288                 : static nsWindow         *gFocusWindow          = NULL;
     289                 : static bool              gBlockActivateEvent   = false;
     290                 : static bool              gGlobalsInitialized   = false;
     291                 : static bool              gRaiseWindows         = true;
     292                 : static nsWindow         *gPluginFocusWindow    = NULL;
     293                 : 
     294                 : static nsIRollupListener*          gRollupListener;
     295            1464 : static nsWeakPtr                   gRollupWindow;
     296                 : static bool                        gConsumeRollupEvent;
     297                 : 
     298                 : 
     299                 : #define NS_WINDOW_TITLE_MAX_LENGTH 4095
     300                 : 
     301                 : // If after selecting profile window, the startup fail, please refer to
     302                 : // http://bugzilla.gnome.org/show_bug.cgi?id=88940
     303                 : 
     304                 : // needed for imgIContainer cursors
     305                 : // GdkDisplay* was added in 2.2
     306                 : typedef struct _GdkDisplay GdkDisplay;
     307                 : 
     308                 : #define kWindowPositionSlop 20
     309                 : 
     310                 : // cursor cache
     311                 : static GdkCursor *gCursorCache[eCursorCount];
     312                 : 
     313                 : // imported in nsWidgetFactory.cpp
     314                 : bool gDisableNativeTheme = false;
     315                 : 
     316                 : static GtkWidget *gInvisibleContainer = NULL;
     317                 : 
     318                 : // Sometimes this actually also includes the state of the modifier keys, but
     319                 : // only the button state bits are used.
     320                 : static guint gButtonState;
     321                 : 
     322                 : // Some gobject functions expect functions for gpointer arguments.
     323                 : // gpointer is void* but C++ doesn't like casting functions to void*.
     324                 : template<class T> static inline gpointer
     325               0 : FuncToGpointer(T aFunction)
     326                 : {
     327                 :     return reinterpret_cast<gpointer>
     328                 :         (reinterpret_cast<uintptr_t>
     329                 :          // This cast just provides a warning if T is not a function.
     330               0 :          (reinterpret_cast<void (*)()>(aFunction)));
     331                 : }
     332                 : 
     333                 : // nsAutoRef<pixman_region32> uses nsSimpleRef<> to know how to automatically
     334                 : // destroy regions.
     335                 : template <>
     336                 : class nsSimpleRef<pixman_region32> : public pixman_region32 {
     337                 : protected:
     338                 :     typedef pixman_region32 RawRef;
     339                 : 
     340               0 :     nsSimpleRef() { data = nsnull; }
     341                 :     nsSimpleRef(const RawRef &aRawRef) : pixman_region32(aRawRef) { }
     342                 : 
     343               0 :     static void Release(pixman_region32& region) {
     344               0 :         pixman_region32_fini(&region);
     345               0 :     }
     346                 :     // Whether this needs to be released:
     347               0 :     bool HaveResource() const { return data != nsnull; }
     348                 : 
     349               0 :     pixman_region32& get() { return *this; }
     350                 : };
     351                 : 
     352                 : static inline PRInt32
     353               0 : GetBitmapStride(PRInt32 width)
     354                 : {
     355                 : #if defined(MOZ_X11) || defined(MOZ_WIDGET_GTK2)
     356               0 :   return (width+7)/8;
     357                 : #else
     358                 :   return cairo_format_stride_for_width(CAIRO_FORMAT_A1, width);
     359                 : #endif
     360                 : }
     361                 : 
     362               0 : static inline bool TimestampIsNewerThan(guint32 a, guint32 b)
     363                 : {
     364                 :     // Timestamps are just the least significant bits of a monotonically
     365                 :     // increasing function, and so the use of unsigned overflow arithmetic.
     366               0 :     return a - b <= G_MAXUINT32/2;
     367                 : }
     368                 : 
     369                 : static void
     370               0 : UpdateLastInputEventTime(void *aGdkEvent)
     371                 : {
     372                 :     nsCOMPtr<nsIdleService> idleService =
     373               0 :         do_GetService("@mozilla.org/widget/idleservice;1");
     374               0 :     if (idleService) {
     375               0 :         idleService->ResetIdleTimeOut();
     376                 :     }
     377                 : 
     378               0 :     guint timestamp = gdk_event_get_time(static_cast<GdkEvent*>(aGdkEvent));
     379               0 :     if (timestamp == GDK_CURRENT_TIME)
     380                 :         return;
     381                 : 
     382               0 :     sLastUserInputTime = timestamp;
     383                 : }
     384                 : 
     385               0 : nsWindow::nsWindow()
     386                 : {
     387               0 :     mIsTopLevel       = false;
     388               0 :     mIsDestroyed      = false;
     389               0 :     mNeedsResize      = false;
     390               0 :     mNeedsMove        = false;
     391               0 :     mListenForResizes = false;
     392               0 :     mIsShown          = false;
     393               0 :     mNeedsShow        = false;
     394               0 :     mEnabled          = true;
     395               0 :     mCreated          = false;
     396                 : 
     397               0 :     mContainer           = nsnull;
     398               0 :     mGdkWindow           = nsnull;
     399               0 :     mShell               = nsnull;
     400               0 :     mWindowGroup         = nsnull;
     401               0 :     mHasMappedToplevel   = false;
     402               0 :     mIsFullyObscured     = false;
     403               0 :     mRetryPointerGrab    = false;
     404               0 :     mTransientParent     = nsnull;
     405               0 :     mWindowType          = eWindowType_child;
     406               0 :     mSizeState           = nsSizeMode_Normal;
     407               0 :     mLastSizeMode        = nsSizeMode_Normal;
     408                 : 
     409                 : #ifdef MOZ_X11
     410               0 :     mOldFocusWindow      = 0;
     411                 : #endif /* MOZ_X11 */
     412               0 :     mPluginType          = PluginType_NONE;
     413                 : 
     414               0 :     if (!gGlobalsInitialized) {
     415               0 :         gGlobalsInitialized = true;
     416                 : 
     417                 :         // It's OK if either of these fail, but it may not be one day.
     418               0 :         initialize_prefs();
     419                 :     }
     420                 : 
     421               0 :     mLastMotionPressure = 0;
     422                 : 
     423                 : #ifdef ACCESSIBILITY
     424               0 :     mRootAccessible  = nsnull;
     425                 : #endif
     426                 : 
     427               0 :     mIsTransparent = false;
     428               0 :     mTransparencyBitmap = nsnull;
     429                 : 
     430               0 :     mTransparencyBitmapWidth  = 0;
     431               0 :     mTransparencyBitmapHeight = 0;
     432               0 : }
     433                 : 
     434               0 : nsWindow::~nsWindow()
     435                 : {
     436               0 :     LOG(("nsWindow::~nsWindow() [%p]\n", (void *)this));
     437               0 :     if (sLastDragMotionWindow == this) {
     438               0 :         sLastDragMotionWindow = NULL;
     439                 :     }
     440                 : 
     441               0 :     delete[] mTransparencyBitmap;
     442               0 :     mTransparencyBitmap = nsnull;
     443                 : 
     444               0 :     Destroy();
     445               0 : }
     446                 : 
     447                 : /* static */ void
     448            1387 : nsWindow::ReleaseGlobals()
     449                 : {
     450           49932 :   for (PRUint32 i = 0; i < ArrayLength(gCursorCache); ++i) {
     451           48545 :     if (gCursorCache[i]) {
     452               0 :       gdk_cursor_unref(gCursorCache[i]);
     453               0 :       gCursorCache[i] = nsnull;
     454                 :     }
     455                 :   }
     456            1387 : }
     457                 : 
     458               0 : NS_IMPL_ISUPPORTS_INHERITED1(nsWindow, nsBaseWidget,
     459                 :                              nsISupportsWeakReference)
     460                 : 
     461                 : void
     462               0 : nsWindow::CommonCreate(nsIWidget *aParent, bool aListenForResizes)
     463                 : {
     464               0 :     mParent = aParent;
     465               0 :     mListenForResizes = aListenForResizes;
     466               0 :     mCreated = true;
     467               0 : }
     468                 : 
     469                 : void
     470               0 : nsWindow::DispatchResizeEvent(nsIntRect &aRect, nsEventStatus &aStatus)
     471                 : {
     472               0 :     nsSizeEvent event(true, NS_SIZE, this);
     473                 : 
     474               0 :     event.windowSize = &aRect;
     475               0 :     event.refPoint.x = aRect.x;
     476               0 :     event.refPoint.y = aRect.y;
     477               0 :     event.mWinWidth = aRect.width;
     478               0 :     event.mWinHeight = aRect.height;
     479                 : 
     480                 :     nsEventStatus status;
     481               0 :     DispatchEvent(&event, status);
     482               0 : }
     483                 : 
     484                 : void
     485               0 : nsWindow::DispatchActivateEvent(void)
     486                 : {
     487               0 :     NS_ASSERTION(mContainer || mIsDestroyed,
     488                 :                  "DispatchActivateEvent only intended for container windows");
     489                 : 
     490                 : #ifdef ACCESSIBILITY
     491               0 :     DispatchActivateEventAccessible();
     492                 : #endif //ACCESSIBILITY
     493               0 :     nsGUIEvent event(true, NS_ACTIVATE, this);
     494                 :     nsEventStatus status;
     495               0 :     DispatchEvent(&event, status);
     496               0 : }
     497                 : 
     498                 : void
     499               0 : nsWindow::DispatchDeactivateEvent(void)
     500                 : {
     501               0 :     nsGUIEvent event(true, NS_DEACTIVATE, this);
     502                 :     nsEventStatus status;
     503               0 :     DispatchEvent(&event, status);
     504                 : 
     505                 : #ifdef ACCESSIBILITY
     506               0 :     DispatchDeactivateEventAccessible();
     507                 : #endif //ACCESSIBILITY
     508               0 : }
     509                 : 
     510                 : 
     511                 : 
     512                 : nsresult
     513               0 : nsWindow::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus &aStatus)
     514                 : {
     515                 : #ifdef DEBUG
     516                 :     debug_DumpEvent(stdout, aEvent->widget, aEvent,
     517               0 :                     nsCAutoString("something"), 0);
     518                 : #endif
     519                 : 
     520               0 :     aStatus = nsEventStatus_eIgnore;
     521                 : 
     522                 :     // send it to the standard callback
     523               0 :     if (mEventCallback)
     524               0 :         aStatus = (* mEventCallback)(aEvent);
     525                 : 
     526               0 :     return NS_OK;
     527                 : }
     528                 : 
     529                 : void
     530               0 : nsWindow::OnDestroy(void)
     531                 : {
     532               0 :     if (mOnDestroyCalled)
     533               0 :         return;
     534                 : 
     535               0 :     mOnDestroyCalled = true;
     536                 :     
     537                 :     // Prevent deletion.
     538               0 :     nsCOMPtr<nsIWidget> kungFuDeathGrip = this;
     539                 : 
     540                 :     // release references to children, device context, toolkit + app shell
     541               0 :     nsBaseWidget::OnDestroy(); 
     542                 :     
     543                 :     // Remove association between this object and its parent and siblings.
     544               0 :     nsBaseWidget::Destroy();
     545               0 :     mParent = nsnull;
     546                 : 
     547               0 :     nsGUIEvent event(true, NS_DESTROY, this);
     548                 :     nsEventStatus status;
     549               0 :     DispatchEvent(&event, status);
     550                 : }
     551                 : 
     552                 : bool
     553               0 : nsWindow::AreBoundsSane(void)
     554                 : {
     555               0 :     if (mBounds.width > 0 && mBounds.height > 0)
     556               0 :         return true;
     557                 : 
     558               0 :     return false;
     559                 : }
     560                 : 
     561                 : static GtkWidget*
     562               0 : EnsureInvisibleContainer()
     563                 : {
     564               0 :     if (!gInvisibleContainer) {
     565                 :         // GtkWidgets need to be anchored to a GtkWindow to be realized (to
     566                 :         // have a window).  Using GTK_WINDOW_POPUP rather than
     567                 :         // GTK_WINDOW_TOPLEVEL in the hope that POPUP results in less
     568                 :         // initialization and window manager interaction.
     569               0 :         GtkWidget* window = gtk_window_new(GTK_WINDOW_POPUP);
     570               0 :         gInvisibleContainer = moz_container_new();
     571               0 :         gtk_container_add(GTK_CONTAINER(window), gInvisibleContainer);
     572               0 :         gtk_widget_realize(gInvisibleContainer);
     573                 : 
     574                 :     }
     575               0 :     return gInvisibleContainer;
     576                 : }
     577                 : 
     578                 : static void
     579               0 : CheckDestroyInvisibleContainer()
     580                 : {
     581               0 :     NS_PRECONDITION(gInvisibleContainer, "oh, no");
     582                 : 
     583               0 :     if (!gdk_window_peek_children(gtk_widget_get_window(gInvisibleContainer))) {
     584                 :         // No children, so not in use.
     585                 :         // Make sure to destroy the GtkWindow also.
     586               0 :         gtk_widget_destroy(gtk_widget_get_parent(gInvisibleContainer));
     587               0 :         gInvisibleContainer = NULL;
     588                 :     }
     589               0 : }
     590                 : 
     591                 : // Change the containing GtkWidget on a sub-hierarchy of GdkWindows belonging
     592                 : // to aOldWidget and rooted at aWindow, and reparent any child GtkWidgets of
     593                 : // the GdkWindow hierarchy to aNewWidget.
     594                 : static void
     595               0 : SetWidgetForHierarchy(GdkWindow *aWindow,
     596                 :                       GtkWidget *aOldWidget,
     597                 :                       GtkWidget *aNewWidget)
     598                 : {
     599                 :     gpointer data;
     600               0 :     gdk_window_get_user_data(aWindow, &data);
     601                 : 
     602               0 :     if (data != aOldWidget) {
     603               0 :         if (!GTK_IS_WIDGET(data))
     604               0 :             return;
     605                 : 
     606               0 :         GtkWidget* widget = static_cast<GtkWidget*>(data);
     607               0 :         if (gtk_widget_get_parent(widget) != aOldWidget)
     608               0 :             return;
     609                 : 
     610                 :         // This window belongs to a child widget, which will no longer be a
     611                 :         // child of aOldWidget.
     612               0 :         gtk_widget_reparent(widget, aNewWidget);
     613                 : 
     614               0 :         return;
     615                 :     }
     616                 : 
     617               0 :     GList *children = gdk_window_get_children(aWindow);
     618               0 :     for(GList *list = children; list; list = list->next) {
     619               0 :         SetWidgetForHierarchy(GDK_WINDOW(list->data), aOldWidget, aNewWidget);
     620                 :     }
     621               0 :     g_list_free(children);
     622                 : 
     623               0 :     gdk_window_set_user_data(aWindow, aNewWidget);
     624                 : }
     625                 : 
     626                 : // Walk the list of child windows and call destroy on them.
     627                 : void
     628               0 : nsWindow::DestroyChildWindows()
     629                 : {
     630               0 :     if (!mGdkWindow)
     631               0 :         return;
     632                 : 
     633               0 :     while (GList *children = gdk_window_peek_children(mGdkWindow)) {
     634               0 :         GdkWindow *child = GDK_WINDOW(children->data);
     635               0 :         nsWindow *kid = get_window_for_gdk_window(child);
     636               0 :         if (kid) {
     637               0 :             kid->Destroy();
     638                 :         } else {
     639                 :             // This child is not an nsWindow.
     640                 :             // Destroy the child GtkWidget.
     641                 :             gpointer data;
     642               0 :             gdk_window_get_user_data(child, &data);
     643               0 :             if (GTK_IS_WIDGET(data)) {
     644               0 :                 gtk_widget_destroy(static_cast<GtkWidget*>(data));
     645                 :             }
     646                 :         }
     647                 :     }
     648                 : }
     649                 : 
     650                 : NS_IMETHODIMP
     651               0 : nsWindow::Destroy(void)
     652                 : {
     653               0 :     if (mIsDestroyed || !mCreated)
     654               0 :         return NS_OK;
     655                 : 
     656               0 :     LOG(("nsWindow::Destroy [%p]\n", (void *)this));
     657               0 :     mIsDestroyed = true;
     658               0 :     mCreated = false;
     659                 : 
     660                 :     /** Need to clean our LayerManager up while still alive */
     661               0 :     if (mLayerManager) {
     662               0 :         nsRefPtr<GLContext> gl = nsnull;
     663               0 :         if (mLayerManager->GetBackendType() == LayerManager::LAYERS_OPENGL) {
     664               0 :             LayerManagerOGL *ogllm = static_cast<LayerManagerOGL*>(mLayerManager.get());
     665               0 :             gl = ogllm->gl();
     666                 :         }
     667                 : 
     668               0 :         mLayerManager->Destroy();
     669                 : 
     670               0 :         if (gl) {
     671               0 :             gl->MarkDestroyed();
     672                 :         }
     673                 :     }
     674               0 :     mLayerManager = nsnull;
     675                 : 
     676               0 :     ClearCachedResources();
     677                 : 
     678               0 :     g_signal_handlers_disconnect_by_func(gtk_settings_get_default(),
     679                 :                                          FuncToGpointer(theme_changed_cb),
     680               0 :                                          this);
     681                 : 
     682                 :     // ungrab if required
     683               0 :     nsCOMPtr<nsIWidget> rollupWidget = do_QueryReferent(gRollupWindow);
     684               0 :     if (static_cast<nsIWidget *>(this) == rollupWidget.get()) {
     685               0 :         if (gRollupListener)
     686               0 :             gRollupListener->Rollup(0);
     687               0 :         gRollupWindow = nsnull;
     688               0 :         gRollupListener = nsnull;
     689                 :     }
     690                 : 
     691               0 :     NativeShow(false);
     692                 : 
     693               0 :     if (mIMModule) {
     694               0 :         mIMModule->OnDestroyWindow(this);
     695                 :     }
     696                 : 
     697                 :     // make sure that we remove ourself as the focus window
     698               0 :     if (gFocusWindow == this) {
     699               0 :         LOGFOCUS(("automatically losing focus...\n"));
     700               0 :         gFocusWindow = nsnull;
     701                 :     }
     702                 : 
     703                 : #if defined(MOZ_WIDGET_GTK2) && defined(MOZ_X11)
     704                 :     // make sure that we remove ourself as the plugin focus window
     705               0 :     if (gPluginFocusWindow == this) {
     706               0 :         gPluginFocusWindow->LoseNonXEmbedPluginFocus();
     707                 :     }
     708                 : #endif /* MOZ_X11 && MOZ_WIDGET_GTK2 */
     709                 :   
     710               0 :     if (mWindowGroup) {
     711               0 :         g_object_unref(mWindowGroup);
     712               0 :         mWindowGroup = nsnull;
     713                 :     }
     714                 : 
     715                 :     // Destroy thebes surface now. Badness can happen if we destroy
     716                 :     // the surface after its X Window.
     717               0 :     mThebesSurface = nsnull;
     718                 : 
     719               0 :     if (mDragLeaveTimer) {
     720               0 :         mDragLeaveTimer->Cancel();
     721               0 :         mDragLeaveTimer = nsnull;
     722                 :     }
     723                 : 
     724               0 :     GtkWidget *owningWidget = GetMozContainerWidget();
     725               0 :     if (mShell) {
     726               0 :         gtk_widget_destroy(mShell);
     727               0 :         mShell = nsnull;
     728               0 :         mContainer = nsnull;
     729               0 :         NS_ABORT_IF_FALSE(!mGdkWindow,
     730                 :                           "mGdkWindow should be NULL when mContainer is destroyed");
     731                 :     }
     732               0 :     else if (mContainer) {
     733               0 :         gtk_widget_destroy(GTK_WIDGET(mContainer));
     734               0 :         mContainer = nsnull;
     735               0 :         NS_ABORT_IF_FALSE(!mGdkWindow,
     736                 :                           "mGdkWindow should be NULL when mContainer is destroyed");
     737                 :     }
     738               0 :     else if (mGdkWindow) {
     739                 :         // Destroy child windows to ensure that their mThebesSurfaces are
     740                 :         // released and to remove references from GdkWindows back to their
     741                 :         // container widget.  (OnContainerUnrealize() does this when the
     742                 :         // MozContainer widget is destroyed.)
     743               0 :         DestroyChildWindows();
     744                 : 
     745               0 :         gdk_window_set_user_data(mGdkWindow, NULL);
     746               0 :         g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", NULL);
     747               0 :         gdk_window_destroy(mGdkWindow);
     748               0 :         mGdkWindow = nsnull;
     749                 :     }
     750                 : 
     751               0 :     if (gInvisibleContainer && owningWidget == gInvisibleContainer) {
     752               0 :         CheckDestroyInvisibleContainer();
     753                 :     }
     754                 : 
     755                 : #ifdef ACCESSIBILITY
     756               0 :      if (mRootAccessible) {
     757               0 :          mRootAccessible = nsnull;
     758                 :      }
     759                 : #endif
     760                 : 
     761                 :     // Save until last because OnDestroy() may cause us to be deleted.
     762               0 :     OnDestroy();
     763                 : 
     764               0 :     return NS_OK;
     765                 : }
     766                 : 
     767                 : nsIWidget *
     768               0 : nsWindow::GetParent(void)
     769                 : {
     770               0 :     return mParent;
     771                 : }
     772                 : 
     773                 : float
     774               0 : nsWindow::GetDPI()
     775                 : {
     776                 : 
     777                 : #ifdef MOZ_PLATFORM_MAEMO
     778                 :     static float sDPI = 0;
     779                 : 
     780                 :     if (!sDPI) {
     781                 :         // X on Maemo does not report true DPI: https://bugs.maemo.org/show_bug.cgi?id=4825
     782                 :         nsCOMPtr<nsIPropertyBag2> infoService = do_GetService("@mozilla.org/system-info;1");
     783                 :         NS_ASSERTION(infoService, "Could not find a system info service");
     784                 : 
     785                 :         nsCString deviceType;
     786                 :         infoService->GetPropertyAsACString(NS_LITERAL_STRING("device"), deviceType);
     787                 :         if (deviceType.EqualsLiteral("Nokia N900")) {
     788                 :             sDPI = 265.0f;
     789                 :         } else if (deviceType.EqualsLiteral("Nokia N8xx")) {
     790                 :             sDPI = 225.0f;
     791                 :         } else {
     792                 :             // Fall back to something sane.
     793                 :             NS_WARNING("Unknown device - using default DPI");
     794                 :             sDPI = 96.0f;
     795                 :         }
     796                 :     }
     797                 :     return sDPI;
     798                 : #else
     799               0 :     Display *dpy = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
     800               0 :     int defaultScreen = DefaultScreen(dpy);
     801               0 :     double heightInches = DisplayHeightMM(dpy, defaultScreen)/MM_PER_INCH_FLOAT;
     802               0 :     if (heightInches < 0.25) {
     803                 :         // Something's broken, but we'd better not crash.
     804               0 :         return 96.0f;
     805                 :     }
     806               0 :     return float(DisplayHeight(dpy, defaultScreen)/heightInches);
     807                 : #endif
     808                 : }
     809                 : 
     810                 : NS_IMETHODIMP
     811               0 : nsWindow::SetParent(nsIWidget *aNewParent)
     812                 : {
     813               0 :     if (mContainer || !mGdkWindow) {
     814               0 :         NS_NOTREACHED("nsWindow::SetParent called illegally");
     815               0 :         return NS_ERROR_NOT_IMPLEMENTED;
     816                 :     }
     817                 : 
     818               0 :     NS_ASSERTION(!mTransientParent, "child widget with transient parent");
     819                 : 
     820               0 :     nsCOMPtr<nsIWidget> kungFuDeathGrip = this;
     821               0 :     if (mParent) {
     822               0 :         mParent->RemoveChild(this);
     823                 :     }
     824                 : 
     825               0 :     mParent = aNewParent;
     826                 : 
     827               0 :     GtkWidget* oldContainer = GetMozContainerWidget();
     828               0 :     if (!oldContainer) {
     829                 :         // The GdkWindows have been destroyed so there is nothing else to
     830                 :         // reparent.
     831               0 :         NS_ABORT_IF_FALSE(gdk_window_is_destroyed(mGdkWindow),
     832                 :                           "live GdkWindow with no widget");
     833               0 :         return NS_OK;
     834                 :     }
     835                 : 
     836               0 :     if (aNewParent) {
     837               0 :         aNewParent->AddChild(this);
     838               0 :         ReparentNativeWidget(aNewParent);
     839                 :     } else {
     840                 :         // aNewParent is NULL, but reparent to a hidden window to avoid
     841                 :         // destroying the GdkWindow and its descendants.
     842                 :         // An invisible container widget is needed to hold descendant
     843                 :         // GtkWidgets.
     844               0 :         GtkWidget* newContainer = EnsureInvisibleContainer();
     845               0 :         GdkWindow* newParentWindow = gtk_widget_get_window(newContainer);
     846                 :         ReparentNativeWidgetInternal(aNewParent, newContainer, newParentWindow,
     847               0 :                                      oldContainer);
     848                 :     }
     849               0 :     return NS_OK;
     850                 : }
     851                 : 
     852                 : NS_IMETHODIMP
     853               0 : nsWindow::ReparentNativeWidget(nsIWidget* aNewParent)
     854                 : {
     855               0 :     NS_PRECONDITION(aNewParent, "");
     856               0 :     NS_ASSERTION(!mIsDestroyed, "");
     857               0 :     NS_ASSERTION(!static_cast<nsWindow*>(aNewParent)->mIsDestroyed, "");
     858                 : 
     859               0 :     GtkWidget* oldContainer = GetMozContainerWidget();
     860               0 :     if (!oldContainer) {
     861                 :         // The GdkWindows have been destroyed so there is nothing else to
     862                 :         // reparent.
     863               0 :         NS_ABORT_IF_FALSE(gdk_window_is_destroyed(mGdkWindow),
     864                 :                           "live GdkWindow with no widget");
     865               0 :         return NS_OK;
     866                 :     }
     867               0 :     NS_ABORT_IF_FALSE(!gdk_window_is_destroyed(mGdkWindow),
     868                 :                       "destroyed GdkWindow with widget");
     869                 :     
     870               0 :     nsWindow* newParent = static_cast<nsWindow*>(aNewParent);
     871               0 :     GdkWindow* newParentWindow = newParent->mGdkWindow;
     872               0 :     GtkWidget* newContainer = NULL;
     873               0 :     if (newParentWindow) {
     874               0 :         newContainer = get_gtk_widget_for_gdk_window(newParentWindow);
     875                 :     }
     876                 : 
     877               0 :     if (mTransientParent) {
     878                 :       GtkWindow* topLevelParent =
     879               0 :           GTK_WINDOW(gtk_widget_get_toplevel(newContainer));
     880               0 :       gtk_window_set_transient_for(GTK_WINDOW(mShell), topLevelParent);
     881               0 :       mTransientParent = topLevelParent;
     882               0 :       if (mWindowGroup) {
     883               0 :           g_object_unref(mWindowGroup);
     884               0 :           mWindowGroup = NULL;
     885                 :       }
     886               0 :       if (gtk_window_get_group(mTransientParent)) {
     887                 :           gtk_window_group_add_window(gtk_window_get_group(mTransientParent),
     888               0 :                                       GTK_WINDOW(mShell));
     889               0 :           mWindowGroup = gtk_window_get_group(mTransientParent);
     890               0 :           g_object_ref(mWindowGroup);
     891                 :       }
     892               0 :       else if (gtk_window_get_group(GTK_WINDOW(mShell))) {
     893               0 :           gtk_window_group_remove_window(gtk_window_get_group(GTK_WINDOW(mShell)),
     894               0 :                                          GTK_WINDOW(mShell));
     895                 :       }
     896                 :     }
     897                 : 
     898                 :     ReparentNativeWidgetInternal(aNewParent, newContainer, newParentWindow,
     899               0 :                                  oldContainer);
     900               0 :     return NS_OK;
     901                 : }
     902                 : 
     903                 : void
     904               0 : nsWindow::ReparentNativeWidgetInternal(nsIWidget* aNewParent,
     905                 :                                        GtkWidget* aNewContainer,
     906                 :                                        GdkWindow* aNewParentWindow,
     907                 :                                        GtkWidget* aOldContainer)
     908                 : {
     909               0 :     if (!aNewContainer) {
     910                 :         // The new parent GdkWindow has been destroyed.
     911               0 :         NS_ABORT_IF_FALSE(!aNewParentWindow ||
     912                 :                           gdk_window_is_destroyed(aNewParentWindow),
     913                 :                           "live GdkWindow with no widget");
     914               0 :         Destroy();
     915                 :     } else {
     916               0 :         if (aNewContainer != aOldContainer) {
     917               0 :             NS_ABORT_IF_FALSE(!gdk_window_is_destroyed(aNewParentWindow),
     918                 :                               "destroyed GdkWindow with widget");
     919               0 :             SetWidgetForHierarchy(mGdkWindow, aOldContainer, aNewContainer);
     920                 : 
     921               0 :             if (aOldContainer == gInvisibleContainer) {
     922               0 :                 CheckDestroyInvisibleContainer();
     923                 :             }
     924                 :         }
     925                 : 
     926               0 :         if (!mIsTopLevel) {
     927                 :             gdk_window_reparent(mGdkWindow, aNewParentWindow, mBounds.x,
     928               0 :                                 mBounds.y);
     929                 :         }
     930                 :     }
     931                 : 
     932               0 :     nsWindow* newParent = static_cast<nsWindow*>(aNewParent);
     933                 :     bool parentHasMappedToplevel =
     934               0 :         newParent && newParent->mHasMappedToplevel;
     935               0 :     if (mHasMappedToplevel != parentHasMappedToplevel) {
     936               0 :         SetHasMappedToplevel(parentHasMappedToplevel);
     937                 :     }
     938               0 : }
     939                 : 
     940                 : NS_IMETHODIMP
     941               0 : nsWindow::SetModal(bool aModal)
     942                 : {
     943               0 :     LOG(("nsWindow::SetModal [%p] %d\n", (void *)this, aModal));
     944               0 :     if (mIsDestroyed)
     945               0 :         return aModal ? NS_ERROR_NOT_AVAILABLE : NS_OK;
     946               0 :     if (!mIsTopLevel || !mShell)
     947               0 :         return NS_ERROR_FAILURE;
     948               0 :     gtk_window_set_modal(GTK_WINDOW(mShell), aModal ? TRUE : FALSE);
     949               0 :     return NS_OK;
     950                 : }
     951                 : 
     952                 : // nsIWidget method, which means IsShown.
     953                 : NS_IMETHODIMP
     954               0 : nsWindow::IsVisible(bool& aState)
     955                 : {
     956               0 :     aState = mIsShown;
     957               0 :     return NS_OK;
     958                 : }
     959                 : 
     960                 : NS_IMETHODIMP
     961               0 : nsWindow::ConstrainPosition(bool aAllowSlop, PRInt32 *aX, PRInt32 *aY)
     962                 : {
     963               0 :     if (mIsTopLevel && mShell) {
     964               0 :         PRInt32 screenWidth = gdk_screen_width();
     965               0 :         PRInt32 screenHeight = gdk_screen_height();
     966               0 :         if (aAllowSlop) {
     967               0 :             if (*aX < (kWindowPositionSlop - mBounds.width))
     968               0 :                 *aX = kWindowPositionSlop - mBounds.width;
     969               0 :             if (*aX > (screenWidth - kWindowPositionSlop))
     970               0 :                 *aX = screenWidth - kWindowPositionSlop;
     971               0 :             if (*aY < (kWindowPositionSlop - mBounds.height))
     972               0 :                 *aY = kWindowPositionSlop - mBounds.height;
     973               0 :             if (*aY > (screenHeight - kWindowPositionSlop))
     974               0 :                 *aY = screenHeight - kWindowPositionSlop;
     975                 :         } else {
     976               0 :             if (*aX < 0)
     977               0 :                 *aX = 0;
     978               0 :             if (*aX > (screenWidth - mBounds.width))
     979               0 :                 *aX = screenWidth - mBounds.width;
     980               0 :             if (*aY < 0)
     981               0 :                 *aY = 0;
     982               0 :             if (*aY > (screenHeight - mBounds.height))
     983               0 :                 *aY = screenHeight - mBounds.height;
     984                 :         }
     985                 :     }
     986               0 :     return NS_OK;
     987                 : }
     988                 : 
     989                 : NS_IMETHODIMP
     990               0 : nsWindow::Show(bool aState)
     991                 : {
     992               0 :     if (aState == mIsShown)
     993               0 :         return NS_OK;
     994                 : 
     995                 :     // Clear our cached resources when the window is hidden.
     996               0 :     if (mIsShown && !aState) {
     997               0 :         ClearCachedResources();
     998                 :     }
     999                 : 
    1000               0 :     mIsShown = aState;
    1001                 : 
    1002               0 :     LOG(("nsWindow::Show [%p] state %d\n", (void *)this, aState));
    1003                 : 
    1004               0 :     if (aState) {
    1005                 :         // Now that this window is shown, mHasMappedToplevel needs to be
    1006                 :         // tracked on viewable descendants.
    1007               0 :         SetHasMappedToplevel(mHasMappedToplevel);
    1008                 :     }
    1009                 : 
    1010                 :     // Ok, someone called show on a window that isn't sized to a sane
    1011                 :     // value.  Mark this window as needing to have Show() called on it
    1012                 :     // and return.
    1013               0 :     if ((aState && !AreBoundsSane()) || !mCreated) {
    1014               0 :         LOG(("\tbounds are insane or window hasn't been created yet\n"));
    1015               0 :         mNeedsShow = true;
    1016               0 :         return NS_OK;
    1017                 :     }
    1018                 : 
    1019                 :     // If someone is hiding this widget, clear any needing show flag.
    1020               0 :     if (!aState)
    1021               0 :         mNeedsShow = false;
    1022                 : 
    1023                 :     // If someone is showing this window and it needs a resize then
    1024                 :     // resize the widget.
    1025               0 :     if (aState) {
    1026               0 :         if (mNeedsMove) {
    1027                 :             NativeResize(mBounds.x, mBounds.y, mBounds.width, mBounds.height,
    1028               0 :                          false);
    1029               0 :         } else if (mNeedsResize) {
    1030               0 :             NativeResize(mBounds.width, mBounds.height, false);
    1031                 :         }
    1032                 :     }
    1033                 : 
    1034                 : #ifdef ACCESSIBILITY
    1035               0 :     if (aState && a11y::ShouldA11yBeEnabled())
    1036               0 :         CreateRootAccessible();
    1037                 : #endif
    1038                 : 
    1039               0 :     NativeShow(aState);
    1040                 : 
    1041               0 :     return NS_OK;
    1042                 : }
    1043                 : 
    1044                 : NS_IMETHODIMP
    1045               0 : nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, bool aRepaint)
    1046                 : {
    1047                 :     // For top-level windows, aWidth and aHeight should possibly be
    1048                 :     // interpreted as frame bounds, but NativeResize treats these as window
    1049                 :     // bounds (Bug 581866).
    1050                 : 
    1051               0 :     mBounds.SizeTo(GetSafeWindowSize(nsIntSize(aWidth, aHeight)));
    1052                 : 
    1053               0 :     if (!mCreated)
    1054               0 :         return NS_OK;
    1055                 : 
    1056                 :     // There are several cases here that we need to handle, based on a
    1057                 :     // matrix of the visibility of the widget, the sanity of this resize
    1058                 :     // and whether or not the widget was previously sane.
    1059                 : 
    1060                 :     // Has this widget been set to visible?
    1061               0 :     if (mIsShown) {
    1062                 :         // Are the bounds sane?
    1063               0 :         if (AreBoundsSane()) {
    1064                 :             // Yep?  Resize the window
    1065                 :             //Maybe, the toplevel has moved
    1066                 : 
    1067                 :             // Note that if the widget needs to be positioned because its
    1068                 :             // size was previously insane in Resize(x,y,w,h), then we need
    1069                 :             // to set the x and y here too, because the widget wasn't
    1070                 :             // moved back then
    1071               0 :             if (mNeedsMove)
    1072                 :                 NativeResize(mBounds.x, mBounds.y,
    1073               0 :                              mBounds.width, mBounds.height, aRepaint);
    1074                 :             else
    1075               0 :                 NativeResize(mBounds.width, mBounds.height, aRepaint);
    1076                 : 
    1077                 :             // Does it need to be shown because it was previously insane?
    1078               0 :             if (mNeedsShow)
    1079               0 :                 NativeShow(true);
    1080                 :         }
    1081                 :         else {
    1082                 :             // If someone has set this so that the needs show flag is false
    1083                 :             // and it needs to be hidden, update the flag and hide the
    1084                 :             // window.  This flag will be cleared the next time someone
    1085                 :             // hides the window or shows it.  It also prevents us from
    1086                 :             // calling NativeShow(false) excessively on the window which
    1087                 :             // causes unneeded X traffic.
    1088               0 :             if (!mNeedsShow) {
    1089               0 :                 mNeedsShow = true;
    1090               0 :                 NativeShow(false);
    1091                 :             }
    1092                 :         }
    1093                 :     }
    1094                 :     // If the widget hasn't been shown, mark the widget as needing to be
    1095                 :     // resized before it is shown.
    1096                 :     else {
    1097               0 :         if (AreBoundsSane() && mListenForResizes) {
    1098                 :             // For widgets that we listen for resizes for (widgets created
    1099                 :             // with native parents) we apparently _always_ have to resize.  I
    1100                 :             // dunno why, but apparently we're lame like that.
    1101               0 :             NativeResize(aWidth, aHeight, aRepaint);
    1102                 :         }
    1103                 :         else {
    1104               0 :             mNeedsResize = true;
    1105                 :         }
    1106                 :     }
    1107                 : 
    1108                 :     // synthesize a resize event if this isn't a toplevel
    1109               0 :     if (mIsTopLevel || mListenForResizes) {
    1110               0 :         nsIntRect rect(mBounds.x, mBounds.y, aWidth, aHeight);
    1111                 :         nsEventStatus status;
    1112               0 :         DispatchResizeEvent(rect, status);
    1113                 :     }
    1114                 : 
    1115               0 :     return NS_OK;
    1116                 : }
    1117                 : 
    1118                 : NS_IMETHODIMP
    1119               0 : nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,
    1120                 :                        bool aRepaint)
    1121                 : {
    1122               0 :     mBounds.x = aX;
    1123               0 :     mBounds.y = aY;
    1124               0 :     mBounds.SizeTo(GetSafeWindowSize(nsIntSize(aWidth, aHeight)));
    1125                 : 
    1126               0 :     mNeedsMove = true;
    1127                 : 
    1128               0 :     if (!mCreated)
    1129               0 :         return NS_OK;
    1130                 : 
    1131                 :     // There are several cases here that we need to handle, based on a
    1132                 :     // matrix of the visibility of the widget, the sanity of this resize
    1133                 :     // and whether or not the widget was previously sane.
    1134                 : 
    1135                 :     // Has this widget been set to visible?
    1136               0 :     if (mIsShown) {
    1137                 :         // Are the bounds sane?
    1138               0 :         if (AreBoundsSane()) {
    1139                 :             // Yep?  Resize the window
    1140               0 :             NativeResize(aX, aY, aWidth, aHeight, aRepaint);
    1141                 :             // Does it need to be shown because it was previously insane?
    1142               0 :             if (mNeedsShow)
    1143               0 :                 NativeShow(true);
    1144                 :         }
    1145                 :         else {
    1146                 :             // If someone has set this so that the needs show flag is false
    1147                 :             // and it needs to be hidden, update the flag and hide the
    1148                 :             // window.  This flag will be cleared the next time someone
    1149                 :             // hides the window or shows it.  It also prevents us from
    1150                 :             // calling NativeShow(false) excessively on the window which
    1151                 :             // causes unneeded X traffic.
    1152               0 :             if (!mNeedsShow) {
    1153               0 :                 mNeedsShow = true;
    1154               0 :                 NativeShow(false);
    1155                 :             }
    1156                 :         }
    1157                 :     }
    1158                 :     // If the widget hasn't been shown, mark the widget as needing to be
    1159                 :     // resized before it is shown
    1160                 :     else {
    1161               0 :         if (AreBoundsSane() && mListenForResizes){
    1162                 :             // For widgets that we listen for resizes for (widgets created
    1163                 :             // with native parents) we apparently _always_ have to resize.  I
    1164                 :             // dunno why, but apparently we're lame like that.
    1165               0 :             NativeResize(aX, aY, aWidth, aHeight, aRepaint);
    1166                 :         }
    1167                 :         else {
    1168               0 :             mNeedsResize = true;
    1169                 :         }
    1170                 :     }
    1171                 : 
    1172               0 :     if (mIsTopLevel || mListenForResizes) {
    1173                 :         // synthesize a resize event
    1174               0 :         nsIntRect rect(aX, aY, aWidth, aHeight);
    1175                 :         nsEventStatus status;
    1176               0 :         DispatchResizeEvent(rect, status);
    1177                 :     }
    1178                 : 
    1179               0 :     return NS_OK;
    1180                 : }
    1181                 : 
    1182                 : NS_IMETHODIMP
    1183               0 : nsWindow::Enable(bool aState)
    1184                 : {
    1185               0 :     mEnabled = aState;
    1186                 : 
    1187               0 :     return NS_OK;
    1188                 : }
    1189                 : 
    1190                 : NS_IMETHODIMP
    1191               0 : nsWindow::IsEnabled(bool *aState)
    1192                 : {
    1193               0 :     *aState = mEnabled;
    1194                 : 
    1195               0 :     return NS_OK;
    1196                 : }
    1197                 : 
    1198                 : 
    1199                 : 
    1200                 : NS_IMETHODIMP
    1201               0 : nsWindow::Move(PRInt32 aX, PRInt32 aY)
    1202                 : {
    1203               0 :     LOG(("nsWindow::Move [%p] %d %d\n", (void *)this,
    1204                 :          aX, aY));
    1205                 : 
    1206               0 :     if (mWindowType == eWindowType_toplevel ||
    1207                 :         mWindowType == eWindowType_dialog) {
    1208               0 :         SetSizeMode(nsSizeMode_Normal);
    1209                 :     }
    1210                 : 
    1211                 :     // Since a popup window's x/y coordinates are in relation to to
    1212                 :     // the parent, the parent might have moved so we always move a
    1213                 :     // popup window.
    1214               0 :     if (aX == mBounds.x && aY == mBounds.y &&
    1215                 :         mWindowType != eWindowType_popup)
    1216               0 :         return NS_OK;
    1217                 : 
    1218                 :     // XXX Should we do some AreBoundsSane check here?
    1219                 : 
    1220               0 :     mBounds.x = aX;
    1221               0 :     mBounds.y = aY;
    1222                 : 
    1223               0 :     if (!mCreated)
    1224               0 :         return NS_OK;
    1225                 : 
    1226               0 :     mNeedsMove = false;
    1227                 : 
    1228               0 :     if (mIsTopLevel) {
    1229               0 :         gtk_window_move(GTK_WINDOW(mShell), aX, aY);
    1230                 :     }
    1231               0 :     else if (mGdkWindow) {
    1232               0 :         gdk_window_move(mGdkWindow, aX, aY);
    1233                 :     }
    1234                 : 
    1235               0 :     return NS_OK;
    1236                 : }
    1237                 : 
    1238                 : NS_IMETHODIMP
    1239               0 : nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement  aPlacement,
    1240                 :                       nsIWidget                  *aWidget,
    1241                 :                       bool                        aActivate)
    1242                 : {
    1243               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1244                 : }
    1245                 : 
    1246                 : NS_IMETHODIMP
    1247               0 : nsWindow::SetZIndex(PRInt32 aZIndex)
    1248                 : {
    1249               0 :     nsIWidget* oldPrev = GetPrevSibling();
    1250                 : 
    1251               0 :     nsBaseWidget::SetZIndex(aZIndex);
    1252                 : 
    1253               0 :     if (GetPrevSibling() == oldPrev) {
    1254               0 :         return NS_OK;
    1255                 :     }
    1256                 : 
    1257               0 :     NS_ASSERTION(!mContainer, "Expected Mozilla child widget");
    1258                 : 
    1259                 :     // We skip the nsWindows that don't have mGdkWindows.
    1260                 :     // These are probably in the process of being destroyed.
    1261                 : 
    1262               0 :     if (!GetNextSibling()) {
    1263                 :         // We're to be on top.
    1264               0 :         if (mGdkWindow)
    1265               0 :             gdk_window_raise(mGdkWindow);
    1266                 :     } else {
    1267                 :         // All the siblings before us need to be below our widget.
    1268               0 :         for (nsWindow* w = this; w;
    1269               0 :              w = static_cast<nsWindow*>(w->GetPrevSibling())) {
    1270               0 :             if (w->mGdkWindow)
    1271               0 :                 gdk_window_lower(w->mGdkWindow);
    1272                 :         }
    1273                 :     }
    1274               0 :     return NS_OK;
    1275                 : }
    1276                 : 
    1277                 : NS_IMETHODIMP
    1278               0 : nsWindow::SetSizeMode(PRInt32 aMode)
    1279                 : {
    1280                 :     nsresult rv;
    1281                 : 
    1282               0 :     LOG(("nsWindow::SetSizeMode [%p] %d\n", (void *)this, aMode));
    1283                 : 
    1284                 :     // Save the requested state.
    1285               0 :     rv = nsBaseWidget::SetSizeMode(aMode);
    1286                 : 
    1287                 :     // return if there's no shell or our current state is the same as
    1288                 :     // the mode we were just set to.
    1289               0 :     if (!mShell || mSizeState == mSizeMode) {
    1290               0 :         return rv;
    1291                 :     }
    1292                 : 
    1293               0 :     switch (aMode) {
    1294                 :     case nsSizeMode_Maximized:
    1295               0 :         gtk_window_maximize(GTK_WINDOW(mShell));
    1296               0 :         break;
    1297                 :     case nsSizeMode_Minimized:
    1298               0 :         gtk_window_iconify(GTK_WINDOW(mShell));
    1299               0 :         break;
    1300                 :     case nsSizeMode_Fullscreen:
    1301               0 :         MakeFullScreen(true);
    1302               0 :         break;
    1303                 : 
    1304                 :     default:
    1305                 :         // nsSizeMode_Normal, really.
    1306               0 :         if (mSizeState == nsSizeMode_Minimized)
    1307               0 :             gtk_window_deiconify(GTK_WINDOW(mShell));
    1308               0 :         else if (mSizeState == nsSizeMode_Maximized)
    1309               0 :             gtk_window_unmaximize(GTK_WINDOW(mShell));
    1310               0 :         break;
    1311                 :     }
    1312                 : 
    1313               0 :     mSizeState = mSizeMode;
    1314                 : 
    1315               0 :     return rv;
    1316                 : }
    1317                 : 
    1318                 : typedef void (* SetUserTimeFunc)(GdkWindow* aWindow, guint32 aTimestamp);
    1319                 : 
    1320                 : // This will become obsolete when new GTK APIs are widely supported,
    1321                 : // as described here: http://bugzilla.gnome.org/show_bug.cgi?id=347375
    1322                 : static void
    1323               0 : SetUserTimeAndStartupIDForActivatedWindow(GtkWidget* aWindow)
    1324                 : {
    1325               0 :     nsGTKToolkit* GTKToolkit = nsGTKToolkit::GetToolkit();
    1326               0 :     if (!GTKToolkit)
    1327               0 :         return;
    1328                 : 
    1329               0 :     nsCAutoString desktopStartupID;
    1330               0 :     GTKToolkit->GetDesktopStartupID(&desktopStartupID);
    1331               0 :     if (desktopStartupID.IsEmpty()) {
    1332                 :         // We don't have the data we need. Fall back to an
    1333                 :         // approximation ... using the timestamp of the remote command
    1334                 :         // being received as a guess for the timestamp of the user event
    1335                 :         // that triggered it.
    1336               0 :         PRUint32 timestamp = GTKToolkit->GetFocusTimestamp();
    1337               0 :         if (timestamp) {
    1338               0 :             gdk_window_focus(gtk_widget_get_window(aWindow), timestamp);
    1339               0 :             GTKToolkit->SetFocusTimestamp(0);
    1340                 :         }
    1341                 :         return;
    1342                 :     }
    1343                 : 
    1344                 : #if defined(MOZ_ENABLE_STARTUP_NOTIFICATION)
    1345                 :     GdkWindow* gdkWindow = gtk_widget_get_window(aWindow);
    1346                 :   
    1347                 :     GdkScreen* screen = gdk_window_get_screen(gdkWindow);
    1348                 :     SnDisplay* snd =
    1349                 :         sn_display_new(gdk_x11_display_get_xdisplay(gdk_window_get_display(gdkWindow)), 
    1350                 :                        nsnull, nsnull);
    1351                 :     if (!snd)
    1352                 :         return;
    1353                 :     SnLauncheeContext* ctx =
    1354                 :         sn_launchee_context_new(snd, gdk_screen_get_number(screen),
    1355                 :                                 desktopStartupID.get());
    1356                 :     if (!ctx) {
    1357                 :         sn_display_unref(snd);
    1358                 :         return;
    1359                 :     }
    1360                 : 
    1361                 :     if (sn_launchee_context_get_id_has_timestamp(ctx)) {
    1362                 :         PRLibrary* gtkLibrary;
    1363                 :         SetUserTimeFunc setUserTimeFunc = (SetUserTimeFunc)
    1364                 :             PR_FindFunctionSymbolAndLibrary("gdk_x11_window_set_user_time", &gtkLibrary);
    1365                 :         if (setUserTimeFunc) {
    1366                 :             setUserTimeFunc(gdkWindow, sn_launchee_context_get_timestamp(ctx));
    1367                 :             PR_UnloadLibrary(gtkLibrary);
    1368                 :         }
    1369                 :     }
    1370                 : 
    1371                 :     sn_launchee_context_setup_window(ctx, gdk_x11_window_get_xid(gdkWindow));
    1372                 :     sn_launchee_context_complete(ctx);
    1373                 : 
    1374                 :     sn_launchee_context_unref(ctx);
    1375                 :     sn_display_unref(snd);
    1376                 : #endif
    1377                 : 
    1378                 :     // If we used the startup ID, that already contains the focus timestamp;
    1379                 :     // we don't want to reuse the timestamp next time we raise the window
    1380               0 :     GTKToolkit->SetFocusTimestamp(0);
    1381               0 :     GTKToolkit->SetDesktopStartupID(EmptyCString());
    1382                 : }
    1383                 : 
    1384                 : /* static */ guint32
    1385               0 : nsWindow::GetLastUserInputTime()
    1386                 : {
    1387                 :     // gdk_x11_display_get_user_time tracks button and key presses,
    1388                 :     // DESKTOP_STARTUP_ID used to start the app, drop events from external
    1389                 :     // drags, WM_DELETE_WINDOW delete events, but not usually mouse motion nor
    1390                 :     // button and key releases.  Therefore use the most recent of
    1391                 :     // gdk_x11_display_get_user_time and the last time that we have seen.
    1392                 :     guint32 timestamp =
    1393               0 :             gdk_x11_display_get_user_time(gdk_display_get_default());
    1394               0 :     if (sLastUserInputTime != GDK_CURRENT_TIME &&
    1395               0 :         TimestampIsNewerThan(sLastUserInputTime, timestamp)) {
    1396               0 :         return sLastUserInputTime;
    1397                 :     }       
    1398                 : 
    1399               0 :     return timestamp;
    1400                 : }
    1401                 : 
    1402                 : NS_IMETHODIMP
    1403               0 : nsWindow::SetFocus(bool aRaise)
    1404                 : {
    1405                 :     // Make sure that our owning widget has focus.  If it doesn't try to
    1406                 :     // grab it.  Note that we don't set our focus flag in this case.
    1407                 : 
    1408               0 :     LOGFOCUS(("  SetFocus %d [%p]\n", aRaise, (void *)this));
    1409                 : 
    1410               0 :     GtkWidget *owningWidget = GetMozContainerWidget();
    1411               0 :     if (!owningWidget)
    1412               0 :         return NS_ERROR_FAILURE;
    1413                 : 
    1414                 :     // Raise the window if someone passed in true and the prefs are
    1415                 :     // set properly.
    1416               0 :     GtkWidget *toplevelWidget = gtk_widget_get_toplevel(owningWidget);
    1417                 : 
    1418               0 :     if (gRaiseWindows && aRaise && toplevelWidget &&
    1419               0 :         !gtk_widget_has_focus(owningWidget) &&
    1420               0 :         !gtk_widget_has_focus(toplevelWidget)) {
    1421               0 :         GtkWidget* top_window = nsnull;
    1422               0 :         GetToplevelWidget(&top_window);
    1423               0 :         if (top_window && (gtk_widget_get_visible(top_window)))
    1424                 :         {
    1425               0 :             gdk_window_show_unraised(gtk_widget_get_window(top_window));
    1426                 :             // Unset the urgency hint if possible.
    1427               0 :             SetUrgencyHint(top_window, false);
    1428                 :         }
    1429                 :     }
    1430                 : 
    1431               0 :     nsRefPtr<nsWindow> owningWindow = get_window_for_gtk_widget(owningWidget);
    1432               0 :     if (!owningWindow)
    1433               0 :         return NS_ERROR_FAILURE;
    1434                 : 
    1435               0 :     if (aRaise) {
    1436                 :         // aRaise == true means request toplevel activation.
    1437                 : 
    1438                 :         // This is asynchronous.
    1439                 :         // If and when the window manager accepts the request, then the focus
    1440                 :         // widget will get a focus-in-event signal.
    1441               0 :         if (gRaiseWindows && owningWindow->mIsShown && owningWindow->mShell &&
    1442               0 :             !gtk_window_is_active(GTK_WINDOW(owningWindow->mShell))) {
    1443                 : 
    1444               0 :             PRUint32 timestamp = GDK_CURRENT_TIME;
    1445                 : 
    1446               0 :             nsGTKToolkit* GTKToolkit = nsGTKToolkit::GetToolkit();
    1447               0 :             if (GTKToolkit)
    1448               0 :                 timestamp = GTKToolkit->GetFocusTimestamp();
    1449                 : 
    1450               0 :             LOGFOCUS(("  requesting toplevel activation [%p]\n", (void *)this));
    1451               0 :             NS_ASSERTION(owningWindow->mWindowType != eWindowType_popup
    1452                 :                          || mParent,
    1453                 :                          "Presenting an override-redirect window");
    1454               0 :             gtk_window_present_with_time(GTK_WINDOW(owningWindow->mShell), timestamp);
    1455                 : 
    1456               0 :             if (GTKToolkit)
    1457               0 :                 GTKToolkit->SetFocusTimestamp(0);
    1458                 :         }
    1459                 : 
    1460               0 :         return NS_OK;
    1461                 :     }
    1462                 : 
    1463                 :     // aRaise == false means that keyboard events should be dispatched
    1464                 :     // from this widget.
    1465                 : 
    1466                 :     // Ensure owningWidget is the focused GtkWidget within its toplevel window.
    1467                 :     //
    1468                 :     // For eWindowType_popup, this GtkWidget may not actually be the one that
    1469                 :     // receives the key events as it may be the parent window that is active.
    1470               0 :     if (!gtk_widget_is_focus(owningWidget)) {
    1471                 :         // This is synchronous.  It takes focus from a plugin or from a widget
    1472                 :         // in an embedder.  The focus manager already knows that this window
    1473                 :         // is active so gBlockActivateEvent avoids another (unnecessary)
    1474                 :         // NS_ACTIVATE event.
    1475               0 :         gBlockActivateEvent = true;
    1476               0 :         gtk_widget_grab_focus(owningWidget);
    1477               0 :         gBlockActivateEvent = false;
    1478                 :     }
    1479                 : 
    1480                 :     // If this is the widget that already has focus, return.
    1481               0 :     if (gFocusWindow == this) {
    1482               0 :         LOGFOCUS(("  already have focus [%p]\n", (void *)this));
    1483               0 :         return NS_OK;
    1484                 :     }
    1485                 : 
    1486                 :     // Set this window to be the focused child window
    1487               0 :     gFocusWindow = this;
    1488                 : 
    1489               0 :     if (mIMModule) {
    1490               0 :         mIMModule->OnFocusWindow(this);
    1491                 :     }
    1492                 : 
    1493               0 :     LOGFOCUS(("  widget now has focus in SetFocus() [%p]\n",
    1494                 :               (void *)this));
    1495                 : 
    1496               0 :     return NS_OK;
    1497                 : }
    1498                 : 
    1499                 : NS_IMETHODIMP
    1500               0 : nsWindow::GetScreenBounds(nsIntRect &aRect)
    1501                 : {
    1502               0 :     if (mIsTopLevel && mContainer) {
    1503                 :         // use the point including window decorations
    1504                 :         gint x, y;
    1505               0 :         gdk_window_get_root_origin(gtk_widget_get_window(GTK_WIDGET(mContainer)), &x, &y);
    1506               0 :         aRect.MoveTo(x, y);
    1507                 :     }
    1508                 :     else {
    1509               0 :         aRect.MoveTo(WidgetToScreenOffset());
    1510                 :     }
    1511                 :     // mBounds.Size() is the window bounds, not the window-manager frame
    1512                 :     // bounds (bug 581863).  gdk_window_get_frame_extents would give the
    1513                 :     // frame bounds, but mBounds.Size() is returned here for consistency
    1514                 :     // with Resize.
    1515               0 :     aRect.SizeTo(mBounds.Size());
    1516               0 :     LOG(("GetScreenBounds %d,%d | %dx%d\n",
    1517                 :          aRect.x, aRect.y, aRect.width, aRect.height));
    1518               0 :     return NS_OK;
    1519                 : }
    1520                 : 
    1521                 : NS_IMETHODIMP
    1522               0 : nsWindow::GetClientBounds(nsIntRect &aRect)
    1523                 : {
    1524                 :     // GetBounds returns a rect whose top left represents the top left of the
    1525                 :     // outer bounds, but whose width/height represent the size of the inner
    1526                 :     // bounds (which is messed up).
    1527               0 :     GetBounds(aRect);
    1528               0 :     aRect.MoveBy(GetClientOffset());
    1529                 : 
    1530               0 :     return NS_OK;
    1531                 : }
    1532                 : 
    1533                 : nsIntPoint
    1534               0 : nsWindow::GetClientOffset()
    1535                 : {
    1536               0 :     if (!mIsTopLevel) {
    1537               0 :         return nsIntPoint(0, 0);
    1538                 :     }
    1539                 : 
    1540               0 :     GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL);
    1541                 : 
    1542                 :     GdkAtom type_returned;
    1543                 :     int format_returned;
    1544                 :     int length_returned;
    1545                 :     long *frame_extents;
    1546                 : 
    1547               0 :     if (!mShell || !mShell->window ||
    1548                 :         !gdk_property_get(mShell->window,
    1549                 :                           gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE),
    1550                 :                           cardinal_atom,
    1551                 :                           0, // offset
    1552                 :                           4*4, // length
    1553                 :                           FALSE, // delete
    1554                 :                           &type_returned,
    1555                 :                           &format_returned,
    1556                 :                           &length_returned,
    1557               0 :                           (guchar **) &frame_extents) ||
    1558                 :         length_returned/sizeof(glong) != 4) {
    1559                 : 
    1560               0 :         return nsIntPoint(0, 0);
    1561                 :     }
    1562                 : 
    1563                 :     // data returned is in the order left, right, top, bottom
    1564               0 :     PRInt32 left = PRInt32(frame_extents[0]);
    1565               0 :     PRInt32 top = PRInt32(frame_extents[2]);
    1566                 : 
    1567               0 :     g_free(frame_extents);
    1568                 : 
    1569               0 :     return nsIntPoint(left, top);
    1570                 : }
    1571                 : 
    1572                 : NS_IMETHODIMP
    1573               0 : nsWindow::SetForegroundColor(const nscolor &aColor)
    1574                 : {
    1575               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1576                 : }
    1577                 : 
    1578                 : NS_IMETHODIMP
    1579               0 : nsWindow::SetBackgroundColor(const nscolor &aColor)
    1580                 : {
    1581               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    1582                 : }
    1583                 : 
    1584                 : NS_IMETHODIMP
    1585               0 : nsWindow::SetCursor(nsCursor aCursor)
    1586                 : {
    1587                 :     // if we're not the toplevel window pass up the cursor request to
    1588                 :     // the toplevel window to handle it.
    1589               0 :     if (!mContainer && mGdkWindow) {
    1590               0 :         nsWindow *window = GetContainerWindow();
    1591               0 :         if (!window)
    1592               0 :             return NS_ERROR_FAILURE;
    1593                 : 
    1594               0 :         return window->SetCursor(aCursor);
    1595                 :     }
    1596                 : 
    1597                 :     // Only change cursor if it's actually been changed
    1598               0 :     if (aCursor != mCursor) {
    1599               0 :         GdkCursor *newCursor = NULL;
    1600                 : 
    1601               0 :         newCursor = get_gtk_cursor(aCursor);
    1602                 : 
    1603               0 :         if (nsnull != newCursor) {
    1604               0 :             mCursor = aCursor;
    1605                 : 
    1606               0 :             if (!mContainer)
    1607               0 :                 return NS_OK;
    1608                 : 
    1609               0 :             gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(mContainer)), newCursor);
    1610                 :         }
    1611                 :     }
    1612                 : 
    1613               0 :     return NS_OK;
    1614                 : }
    1615                 : 
    1616                 : NS_IMETHODIMP
    1617               0 : nsWindow::SetCursor(imgIContainer* aCursor,
    1618                 :                     PRUint32 aHotspotX, PRUint32 aHotspotY)
    1619                 : {
    1620                 :     // if we're not the toplevel window pass up the cursor request to
    1621                 :     // the toplevel window to handle it.
    1622               0 :     if (!mContainer && mGdkWindow) {
    1623               0 :         nsWindow *window = GetContainerWindow();
    1624               0 :         if (!window)
    1625               0 :             return NS_ERROR_FAILURE;
    1626                 : 
    1627               0 :         return window->SetCursor(aCursor, aHotspotX, aHotspotY);
    1628                 :     }
    1629                 : 
    1630               0 :     mCursor = nsCursor(-1);
    1631                 : 
    1632                 :     // Get the image's current frame
    1633               0 :     GdkPixbuf* pixbuf = nsImageToPixbuf::ImageToPixbuf(aCursor);
    1634               0 :     if (!pixbuf)
    1635               0 :         return NS_ERROR_NOT_AVAILABLE;
    1636                 : 
    1637               0 :     int width = gdk_pixbuf_get_width(pixbuf);
    1638               0 :     int height = gdk_pixbuf_get_height(pixbuf);
    1639                 :     // Reject cursors greater than 128 pixels in some direction, to prevent
    1640                 :     // spoofing.
    1641                 :     // XXX ideally we should rescale. Also, we could modify the API to
    1642                 :     // allow trusted content to set larger cursors.
    1643               0 :     if (width > 128 || height > 128) {
    1644               0 :         g_object_unref(pixbuf);
    1645               0 :         return NS_ERROR_NOT_AVAILABLE;
    1646                 :     }
    1647                 : 
    1648                 :     // Looks like all cursors need an alpha channel (tested on Gtk 2.4.4). This
    1649                 :     // is of course not documented anywhere...
    1650                 :     // So add one if there isn't one yet
    1651               0 :     if (!gdk_pixbuf_get_has_alpha(pixbuf)) {
    1652               0 :         GdkPixbuf* alphaBuf = gdk_pixbuf_add_alpha(pixbuf, FALSE, 0, 0, 0);
    1653               0 :         g_object_unref(pixbuf);
    1654               0 :         if (!alphaBuf) {
    1655               0 :             return NS_ERROR_OUT_OF_MEMORY;
    1656                 :         }
    1657               0 :         pixbuf = alphaBuf;
    1658                 :     }
    1659                 : 
    1660                 :     GdkCursor* cursor = gdk_cursor_new_from_pixbuf(gdk_display_get_default(),
    1661                 :                                                    pixbuf,
    1662               0 :                                                    aHotspotX, aHotspotY);
    1663               0 :     g_object_unref(pixbuf);
    1664               0 :     nsresult rv = NS_ERROR_OUT_OF_MEMORY;
    1665               0 :     if (cursor) {
    1666               0 :         if (mContainer) {
    1667               0 :             gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(mContainer)), cursor);
    1668               0 :             rv = NS_OK;
    1669                 :         }
    1670               0 :         gdk_cursor_unref(cursor);
    1671                 :     }
    1672                 : 
    1673               0 :     return rv;
    1674                 : }
    1675                 : 
    1676                 : NS_IMETHODIMP
    1677               0 : nsWindow::Invalidate(const nsIntRect &aRect)
    1678                 : {
    1679               0 :     if (!mGdkWindow)
    1680               0 :         return NS_OK;
    1681                 : 
    1682                 :     GdkRectangle rect;
    1683               0 :     rect.x = aRect.x;
    1684               0 :     rect.y = aRect.y;
    1685               0 :     rect.width = aRect.width;
    1686               0 :     rect.height = aRect.height;
    1687                 : 
    1688               0 :     LOGDRAW(("Invalidate (rect) [%p]: %d %d %d %d\n", (void *)this,
    1689                 :              rect.x, rect.y, rect.width, rect.height));
    1690                 : 
    1691               0 :     gdk_window_invalidate_rect(mGdkWindow, &rect, FALSE);
    1692                 : 
    1693               0 :     return NS_OK;
    1694                 : }
    1695                 : 
    1696                 : void*
    1697               0 : nsWindow::GetNativeData(PRUint32 aDataType)
    1698                 : {
    1699               0 :     switch (aDataType) {
    1700                 :     case NS_NATIVE_WINDOW:
    1701                 :     case NS_NATIVE_WIDGET: {
    1702               0 :         if (!mGdkWindow)
    1703               0 :             return nsnull;
    1704                 : 
    1705               0 :         return mGdkWindow;
    1706                 :         break;
    1707                 :     }
    1708                 : 
    1709                 :     case NS_NATIVE_PLUGIN_PORT:
    1710               0 :         return SetupPluginPort();
    1711                 :         break;
    1712                 : 
    1713                 :     case NS_NATIVE_DISPLAY:
    1714                 : #ifdef MOZ_X11
    1715               0 :         return GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
    1716                 : #else
    1717                 :         return nsnull;
    1718                 : #endif /* MOZ_X11 */
    1719                 :         break;
    1720                 : 
    1721                 :     case NS_NATIVE_GRAPHIC: {
    1722                 : #if defined(MOZ_WIDGET_GTK2)
    1723               0 :         nsGTKToolkit* toolkit = nsGTKToolkit::GetToolkit();
    1724               0 :         NS_ASSERTION(nsnull != toolkit, "NULL toolkit, unable to get a GC");    
    1725               0 :         return toolkit->GetSharedGC();
    1726                 : #else
    1727                 :         return nsnull;
    1728                 : #endif
    1729                 :         break;
    1730                 :     }
    1731                 : 
    1732                 :     case NS_NATIVE_SHELLWIDGET:
    1733               0 :         return (void *) mShell;
    1734                 : 
    1735                 :     case NS_NATIVE_SHAREABLE_WINDOW:
    1736               0 :         return (void *) GDK_WINDOW_XID(gdk_window_get_toplevel(mGdkWindow));
    1737                 : 
    1738                 :     default:
    1739               0 :         NS_WARNING("nsWindow::GetNativeData called with bad value");
    1740               0 :         return nsnull;
    1741                 :     }
    1742                 : }
    1743                 : 
    1744                 : NS_IMETHODIMP
    1745               0 : nsWindow::SetTitle(const nsAString& aTitle)
    1746                 : {
    1747               0 :     if (!mShell)
    1748               0 :         return NS_OK;
    1749                 : 
    1750                 :     // convert the string into utf8 and set the title.
    1751                 : #define UTF8_FOLLOWBYTE(ch) (((ch) & 0xC0) == 0x80)
    1752               0 :     NS_ConvertUTF16toUTF8 titleUTF8(aTitle);
    1753               0 :     if (titleUTF8.Length() > NS_WINDOW_TITLE_MAX_LENGTH) {
    1754                 :         // Truncate overlong titles (bug 167315). Make sure we chop after a
    1755                 :         // complete sequence by making sure the next char isn't a follow-byte.
    1756               0 :         PRUint32 len = NS_WINDOW_TITLE_MAX_LENGTH;
    1757               0 :         while(UTF8_FOLLOWBYTE(titleUTF8[len]))
    1758               0 :             --len;
    1759               0 :         titleUTF8.Truncate(len);
    1760                 :     }
    1761               0 :     gtk_window_set_title(GTK_WINDOW(mShell), (const char *)titleUTF8.get());
    1762                 : 
    1763               0 :     return NS_OK;
    1764                 : }
    1765                 : 
    1766                 : NS_IMETHODIMP
    1767               0 : nsWindow::SetIcon(const nsAString& aIconSpec)
    1768                 : {
    1769               0 :     if (!mShell)
    1770               0 :         return NS_OK;
    1771                 : 
    1772               0 :     nsCAutoString iconName;
    1773                 :     
    1774               0 :     if (aIconSpec.EqualsLiteral("default")) {
    1775               0 :         nsXPIDLString brandName;
    1776               0 :         GetBrandName(brandName);
    1777               0 :         AppendUTF16toUTF8(brandName, iconName);
    1778               0 :         ToLowerCase(iconName);
    1779                 :     } else {
    1780               0 :         AppendUTF16toUTF8(aIconSpec, iconName);
    1781                 :     }
    1782                 :     
    1783               0 :     nsCOMPtr<nsILocalFile> iconFile;
    1784               0 :     nsCAutoString path;
    1785                 : 
    1786                 :     gint *iconSizes =
    1787                 :         gtk_icon_theme_get_icon_sizes(gtk_icon_theme_get_default(),
    1788               0 :                                       iconName.get());
    1789               0 :     bool foundIcon = (iconSizes[0] != 0);
    1790               0 :     g_free(iconSizes);
    1791                 : 
    1792               0 :     if (!foundIcon) {
    1793                 :         // Look for icons with the following suffixes appended to the base name
    1794                 :         // The last two entries (for the old XPM format) will be ignored unless
    1795                 :         // no icons are found using other suffixes. XPM icons are deprecated.
    1796                 : 
    1797                 :         const char extensions[6][7] = { ".png", "16.png", "32.png", "48.png",
    1798               0 :                                     ".xpm", "16.xpm" };
    1799                 : 
    1800               0 :         for (PRUint32 i = 0; i < ArrayLength(extensions); i++) {
    1801                 :             // Don't bother looking for XPM versions if we found a PNG.
    1802               0 :             if (i == ArrayLength(extensions) - 2 && foundIcon)
    1803               0 :                 break;
    1804                 : 
    1805               0 :             nsAutoString extension;
    1806               0 :             extension.AppendASCII(extensions[i]);
    1807                 : 
    1808               0 :             ResolveIconName(aIconSpec, extension, getter_AddRefs(iconFile));
    1809               0 :             if (iconFile) {
    1810               0 :                 iconFile->GetNativePath(path);
    1811               0 :                 GdkPixbuf *icon = gdk_pixbuf_new_from_file(path.get(), NULL);
    1812               0 :                 if (icon){
    1813                 :                     gtk_icon_theme_add_builtin_icon(iconName.get(),
    1814                 :                                                     gdk_pixbuf_get_height(icon),
    1815               0 :                                                     icon);
    1816               0 :                     g_object_unref(icon);
    1817               0 :                     foundIcon = true;
    1818                 :                 }
    1819                 :             }
    1820                 :         }
    1821                 :     }
    1822                 : 
    1823                 :     // leave the default icon intact if no matching icons were found
    1824               0 :     if (foundIcon) {
    1825               0 :         gtk_window_set_icon_name(GTK_WINDOW(mShell), iconName.get());
    1826                 :     }
    1827                 : 
    1828               0 :     return NS_OK;
    1829                 : }
    1830                 : 
    1831                 : 
    1832                 : nsIntPoint
    1833               0 : nsWindow::WidgetToScreenOffset()
    1834                 : {
    1835               0 :     gint x = 0, y = 0;
    1836                 : 
    1837               0 :     if (mGdkWindow) {
    1838               0 :         gdk_window_get_origin(mGdkWindow, &x, &y);
    1839                 :     }
    1840                 : 
    1841               0 :     return nsIntPoint(x, y);
    1842                 : }
    1843                 : 
    1844                 : NS_IMETHODIMP
    1845               0 : nsWindow::EnableDragDrop(bool aEnable)
    1846                 : {
    1847               0 :     return NS_OK;
    1848                 : }
    1849                 : 
    1850                 : NS_IMETHODIMP
    1851               0 : nsWindow::CaptureMouse(bool aCapture)
    1852                 : {
    1853               0 :     LOG(("CaptureMouse %p\n", (void *)this));
    1854                 : 
    1855               0 :     if (!mGdkWindow)
    1856               0 :         return NS_OK;
    1857                 : 
    1858               0 :     GtkWidget *widget = GetMozContainerWidget();
    1859               0 :     if (!widget)
    1860               0 :         return NS_ERROR_FAILURE;
    1861                 : 
    1862               0 :     if (aCapture) {
    1863               0 :         gtk_grab_add(widget);
    1864               0 :         GrabPointer(GetLastUserInputTime());
    1865                 :     }
    1866                 :     else {
    1867               0 :         ReleaseGrabs();
    1868               0 :         gtk_grab_remove(widget);
    1869                 :     }
    1870                 : 
    1871               0 :     return NS_OK;
    1872                 : }
    1873                 : 
    1874                 : NS_IMETHODIMP
    1875               0 : nsWindow::CaptureRollupEvents(nsIRollupListener *aListener,
    1876                 :                               bool               aDoCapture,
    1877                 :                               bool               aConsumeRollupEvent)
    1878                 : {
    1879               0 :     if (!mGdkWindow)
    1880               0 :         return NS_OK;
    1881                 : 
    1882               0 :     GtkWidget *widget = GetMozContainerWidget();
    1883               0 :     if (!widget)
    1884               0 :         return NS_ERROR_FAILURE;
    1885                 : 
    1886               0 :     LOG(("CaptureRollupEvents %p\n", (void *)this));
    1887                 : 
    1888               0 :     if (aDoCapture) {
    1889               0 :         gConsumeRollupEvent = aConsumeRollupEvent;
    1890               0 :         gRollupListener = aListener;
    1891                 :         gRollupWindow = do_GetWeakReference(static_cast<nsIWidget*>
    1892               0 :                                                        (this));
    1893                 :         // real grab is only done when there is no dragging
    1894               0 :         if (!nsWindow::DragInProgress()) {
    1895               0 :             gtk_grab_add(widget);
    1896               0 :             GrabPointer(GetLastUserInputTime());
    1897                 :         }
    1898                 :     }
    1899                 :     else {
    1900               0 :         if (!nsWindow::DragInProgress()) {
    1901               0 :             ReleaseGrabs();
    1902                 :         }
    1903                 :         // There may not have been a drag in process when aDoCapture was set,
    1904                 :         // so make sure to remove any added grab.  This is a no-op if the grab
    1905                 :         // was not added to this widget.
    1906               0 :         gtk_grab_remove(widget);
    1907               0 :         gRollupListener = nsnull;
    1908               0 :         gRollupWindow = nsnull;
    1909                 :     }
    1910                 : 
    1911               0 :     return NS_OK;
    1912                 : }
    1913                 : 
    1914                 : NS_IMETHODIMP
    1915               0 : nsWindow::GetAttention(PRInt32 aCycleCount)
    1916                 : {
    1917               0 :     LOG(("nsWindow::GetAttention [%p]\n", (void *)this));
    1918                 : 
    1919               0 :     GtkWidget* top_window = nsnull;
    1920               0 :     GtkWidget* top_focused_window = nsnull;
    1921               0 :     GetToplevelWidget(&top_window);
    1922               0 :     if (gFocusWindow)
    1923               0 :         gFocusWindow->GetToplevelWidget(&top_focused_window);
    1924                 : 
    1925                 :     // Don't get attention if the window is focused anyway.
    1926               0 :     if (top_window && (gtk_widget_get_visible(top_window)) &&
    1927                 :         top_window != top_focused_window) {
    1928               0 :         SetUrgencyHint(top_window, true);
    1929                 :     }
    1930                 : 
    1931               0 :     return NS_OK;
    1932                 : }
    1933                 : 
    1934                 : bool
    1935               0 : nsWindow::HasPendingInputEvent()
    1936                 : {
    1937                 :     // This sucks, but gtk/gdk has no way to answer the question we want while
    1938                 :     // excluding paint events, and there's no X API that will let us peek
    1939                 :     // without blocking or removing.  To prevent event reordering, peek
    1940                 :     // anything except expose events.  Reordering expose and others should be
    1941                 :     // ok, hopefully.
    1942                 :     bool haveEvent;
    1943                 : #ifdef MOZ_X11
    1944                 :     XEvent ev;
    1945               0 :     Display *display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
    1946                 :     haveEvent =
    1947                 :         XCheckMaskEvent(display,
    1948                 :                         KeyPressMask | KeyReleaseMask | ButtonPressMask |
    1949                 :                         ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
    1950                 :                         PointerMotionMask | PointerMotionHintMask |
    1951                 :                         Button1MotionMask | Button2MotionMask |
    1952                 :                         Button3MotionMask | Button4MotionMask |
    1953                 :                         Button5MotionMask | ButtonMotionMask | KeymapStateMask |
    1954                 :                         VisibilityChangeMask | StructureNotifyMask |
    1955                 :                         ResizeRedirectMask | SubstructureNotifyMask |
    1956                 :                         SubstructureRedirectMask | FocusChangeMask |
    1957                 :                         PropertyChangeMask | ColormapChangeMask |
    1958               0 :                         OwnerGrabButtonMask, &ev);
    1959               0 :     if (haveEvent) {
    1960               0 :         XPutBackEvent(display, &ev);
    1961                 :     }
    1962                 : #else
    1963                 :     haveEvent = false;
    1964                 : #endif
    1965               0 :     return haveEvent;
    1966                 : }
    1967                 : 
    1968                 : #if 0
    1969                 : #ifdef DEBUG
    1970                 : // Paint flashing code (disabled for cairo - see below)
    1971                 : 
    1972                 : #define CAPS_LOCK_IS_ON \
    1973                 : (KeymapWrapper::AreModifiersCurrentlyActive(KeymapWrapper::CAPS_LOCK))
    1974                 : 
    1975                 : #define WANT_PAINT_FLASHING \
    1976                 : (debug_WantPaintFlashing() && CAPS_LOCK_IS_ON)
    1977                 : 
    1978                 : #ifdef MOZ_X11
    1979                 : static void
    1980                 : gdk_window_flash(GdkWindow *    aGdkWindow,
    1981                 :                  unsigned int   aTimes,
    1982                 :                  unsigned int   aInterval,  // Milliseconds
    1983                 :                  GdkRegion *    aRegion)
    1984                 : {
    1985                 :   gint         x;
    1986                 :   gint         y;
    1987                 :   gint         width;
    1988                 :   gint         height;
    1989                 :   guint        i;
    1990                 :   GdkGC *      gc = 0;
    1991                 :   GdkColor     white;
    1992                 : 
    1993                 : #if defined(MOZ_WIDGET_GTK2)
    1994                 :   gdk_window_get_geometry(aGdkWindow,NULL,NULL,&width,&height,NULL);
    1995                 : #else
    1996                 :   gdk_window_get_geometry(aGdkWindow,NULL,NULL,&width,&height);
    1997                 : #endif
    1998                 : 
    1999                 :   gdk_window_get_origin (aGdkWindow,
    2000                 :                          &x,
    2001                 :                          &y);
    2002                 : 
    2003                 :   gc = gdk_gc_new(GDK_ROOT_PARENT());
    2004                 : 
    2005                 :   white.pixel = WhitePixel(gdk_display,DefaultScreen(gdk_display));
    2006                 : 
    2007                 :   gdk_gc_set_foreground(gc,&white);
    2008                 :   gdk_gc_set_function(gc,GDK_XOR);
    2009                 :   gdk_gc_set_subwindow(gc,GDK_INCLUDE_INFERIORS);
    2010                 : 
    2011                 :   gdk_region_offset(aRegion, x, y);
    2012                 :   gdk_gc_set_clip_region(gc, aRegion);
    2013                 : 
    2014                 :   /*
    2015                 :    * Need to do this twice so that the XOR effect can replace
    2016                 :    * the original window contents.
    2017                 :    */
    2018                 :   for (i = 0; i < aTimes * 2; i++)
    2019                 :   {
    2020                 :     gdk_draw_rectangle(GDK_ROOT_PARENT(),
    2021                 :                        gc,
    2022                 :                        TRUE,
    2023                 :                        x,
    2024                 :                        y,
    2025                 :                        width,
    2026                 :                        height);
    2027                 : 
    2028                 :     gdk_flush();
    2029                 : 
    2030                 :     PR_Sleep(PR_MillisecondsToInterval(aInterval));
    2031                 :   }
    2032                 : 
    2033                 :   gdk_gc_destroy(gc);
    2034                 : 
    2035                 :   gdk_region_offset(aRegion, -x, -y);
    2036                 : }
    2037                 : #endif /* MOZ_X11 */
    2038                 : #endif // DEBUG
    2039                 : #endif
    2040                 : 
    2041                 : static void
    2042               0 : DispatchDidPaint(nsIWidget* aWidget)
    2043                 : {
    2044                 :     nsEventStatus status;
    2045               0 :     nsPaintEvent didPaintEvent(true, NS_DID_PAINT, aWidget);
    2046               0 :     aWidget->DispatchEvent(&didPaintEvent, status);
    2047               0 : }
    2048                 : 
    2049                 : #if defined(MOZ_WIDGET_GTK2)
    2050                 : gboolean
    2051               0 : nsWindow::OnExposeEvent(GdkEventExpose *aEvent)
    2052                 : #else
    2053                 : gboolean
    2054                 : nsWindow::OnExposeEvent(cairo_t *cr)
    2055                 : #endif
    2056                 : {
    2057               0 :     if (mIsDestroyed) {
    2058               0 :         return FALSE;
    2059                 :     }
    2060                 : 
    2061                 :     // Windows that are not visible will be painted after they become visible.
    2062               0 :     if (!mGdkWindow || mIsFullyObscured || !mHasMappedToplevel)
    2063               0 :         return FALSE;
    2064                 : 
    2065                 :     // Dispatch WILL_PAINT to allow scripts etc. to run before we
    2066                 :     // dispatch PAINT
    2067                 :     {
    2068                 :         nsEventStatus status;
    2069               0 :         nsPaintEvent willPaintEvent(true, NS_WILL_PAINT, this);
    2070               0 :         willPaintEvent.willSendDidPaint = true;
    2071               0 :         DispatchEvent(&willPaintEvent, status);
    2072                 : 
    2073                 :         // If the window has been destroyed during WILL_PAINT, there is
    2074                 :         // nothing left to do.
    2075               0 :         if (!mGdkWindow)
    2076               0 :             return TRUE;
    2077                 :     }
    2078                 : 
    2079               0 :     nsPaintEvent event(true, NS_PAINT, this);
    2080               0 :     event.willSendDidPaint = true;
    2081                 : 
    2082                 : #if defined(MOZ_WIDGET_GTK2)
    2083                 :     GdkRectangle *rects;
    2084                 :     gint nrects;
    2085               0 :     gdk_region_get_rectangles(aEvent->region, &rects, &nrects);
    2086               0 :     if (NS_UNLIKELY(!rects)) // OOM
    2087               0 :         return FALSE;
    2088                 : #else
    2089                 : #ifdef cairo_copy_clip_rectangle_list
    2090                 : #error "Looks like we're including Mozilla's cairo instead of system cairo"
    2091                 : #else
    2092                 :     cairo_rectangle_list_t *rects;
    2093                 :     rects = cairo_copy_clip_rectangle_list(cr);  
    2094                 :     if (NS_UNLIKELY(rects->status != CAIRO_STATUS_SUCCESS)) {
    2095                 :        NS_WARNING("Failed to obtain cairo rectangle list.");
    2096                 :        return FALSE;
    2097                 :     }
    2098                 : #endif
    2099                 : #endif
    2100                 : 
    2101                 : // GTK3 TODO?
    2102                 : #if defined(MOZ_WIDGET_GTK2)
    2103               0 :     if (nrects > MAX_RECTS_IN_REGION) {
    2104                 :         // Just use the bounding box
    2105               0 :         rects[0] = aEvent->area;
    2106               0 :         nrects = 1;
    2107                 :     }
    2108                 : #endif
    2109                 : 
    2110               0 :     LOGDRAW(("sending expose event [%p] %p 0x%lx (rects follow):\n",
    2111                 :              (void *)this, (void *)mGdkWindow,
    2112                 :              gdk_x11_window_get_xid(mGdkWindow)));
    2113                 :   
    2114                 : #if defined(MOZ_WIDGET_GTK2)
    2115               0 :     GdkRectangle *r = rects;
    2116               0 :     GdkRectangle *r_end = rects + nrects;
    2117                 : #else
    2118                 :     cairo_rectangle_t *r = rects->rectangles;
    2119                 :     cairo_rectangle_t *r_end = r + rects->num_rectangles;
    2120                 : #endif
    2121               0 :     for (; r < r_end; ++r) {
    2122               0 :         event.region.Or(event.region, nsIntRect(r->x, r->y, r->width, r->height));
    2123               0 :         LOGDRAW(("\t%d %d %d %d\n", r->x, r->y, r->width, r->height));
    2124                 :     }
    2125                 : 
    2126                 :     // Our bounds may have changed after dispatching WILL_PAINT.  Clip
    2127                 :     // to the new bounds here.  The event region is relative to this
    2128                 :     // window.
    2129                 :     event.region.And(event.region,
    2130               0 :                      nsIntRect(0, 0, mBounds.width, mBounds.height));
    2131                 : 
    2132               0 :     bool translucent = eTransparencyTransparent == GetTransparencyMode();
    2133               0 :     if (!translucent) {
    2134                 :         GList *children =
    2135               0 :             gdk_window_peek_children(mGdkWindow);
    2136               0 :         while (children) {
    2137               0 :             GdkWindow *gdkWin = GDK_WINDOW(children->data);
    2138               0 :             nsWindow *kid = get_window_for_gdk_window(gdkWin);
    2139               0 :             if (kid && gdk_window_is_visible(gdkWin)) {
    2140               0 :                 nsAutoTArray<nsIntRect,1> clipRects;
    2141               0 :                 kid->GetWindowClipRegion(&clipRects);
    2142               0 :                 nsIntRect bounds;
    2143               0 :                 kid->GetBounds(bounds);
    2144               0 :                 for (PRUint32 i = 0; i < clipRects.Length(); ++i) {
    2145               0 :                     nsIntRect r = clipRects[i] + bounds.TopLeft();
    2146               0 :                     event.region.Sub(event.region, r);
    2147                 :                 }
    2148                 :             }
    2149               0 :             children = children->next;
    2150                 :         }
    2151                 :     }
    2152                 : 
    2153               0 :     if (event.region.IsEmpty()) {
    2154                 : #if defined(MOZ_WIDGET_GTK2)
    2155               0 :         g_free(rects);
    2156                 : #else
    2157                 :         cairo_rectangle_list_destroy(rects);
    2158                 : #endif
    2159               0 :         return TRUE;
    2160                 :     }
    2161                 : 
    2162               0 :     if (GetLayerManager()->GetBackendType() == LayerManager::LAYERS_OPENGL)
    2163                 :     {
    2164               0 :         LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(GetLayerManager());
    2165               0 :         manager->SetClippingRegion(event.region);
    2166                 : 
    2167                 :         nsEventStatus status;
    2168               0 :         DispatchEvent(&event, status);
    2169                 : 
    2170               0 :         g_free(rects);
    2171                 : 
    2172               0 :         DispatchDidPaint(this);
    2173                 : 
    2174               0 :         return TRUE;
    2175                 :     }
    2176                 :             
    2177                 : #if defined(MOZ_WIDGET_GTK2)
    2178               0 :     nsRefPtr<gfxContext> ctx = new gfxContext(GetThebesSurface());
    2179                 : #else
    2180                 :     nsRefPtr<gfxContext> ctx = new gfxContext(GetThebesSurface(cr));
    2181                 : #endif
    2182                 : 
    2183                 : #ifdef MOZ_X11
    2184               0 :     nsIntRect boundsRect; // for translucent only
    2185                 : 
    2186               0 :     ctx->NewPath();
    2187               0 :     if (translucent) {
    2188                 :         // Collapse update area to the bounding box. This is so we only have to
    2189                 :         // call UpdateTranslucentWindowAlpha once. After we have dropped
    2190                 :         // support for non-Thebes graphics, UpdateTranslucentWindowAlpha will be
    2191                 :         // our private interface so we can rework things to avoid this.
    2192               0 :         boundsRect = event.region.GetBounds();
    2193                 :         ctx->Rectangle(gfxRect(boundsRect.x, boundsRect.y,
    2194               0 :                                boundsRect.width, boundsRect.height));
    2195                 :     } else {
    2196               0 :         gfxUtils::PathFromRegion(ctx, event.region);
    2197                 :     }
    2198               0 :     ctx->Clip();
    2199                 : 
    2200                 :     BasicLayerManager::BufferMode layerBuffering;
    2201               0 :     if (translucent) {
    2202                 :         // The double buffering is done here to extract the shape mask.
    2203                 :         // (The shape mask won't be necessary when a visual with an alpha
    2204                 :         // channel is used on compositing window managers.)
    2205               0 :         layerBuffering = BasicLayerManager::BUFFER_NONE;
    2206               0 :         ctx->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
    2207                 : #ifdef MOZ_HAVE_SHMIMAGE
    2208               0 :     } else if (nsShmImage::UseShm()) {
    2209                 :         // We're using an xshm mapping as a back buffer.
    2210               0 :         layerBuffering = BasicLayerManager::BUFFER_NONE;
    2211                 : #endif // MOZ_HAVE_SHMIMAGE
    2212                 :     } else {
    2213                 :         // Get the layer manager to do double buffering (if necessary).
    2214               0 :         layerBuffering = BasicLayerManager::BUFFER_BUFFERED;
    2215                 :     }
    2216                 : 
    2217                 : #if 0
    2218                 :     // NOTE: Paint flashing region would be wrong for cairo, since
    2219                 :     // cairo inflates the update region, etc.  So don't paint flash
    2220                 :     // for cairo.
    2221                 : #ifdef DEBUG
    2222                 :     // XXX aEvent->region may refer to a newly-invalid area.  FIXME
    2223                 :     if (0 && WANT_PAINT_FLASHING && gtk_widget_get_window(aEvent))
    2224                 :         gdk_window_flash(mGdkWindow, 1, 100, aEvent->region);
    2225                 : #endif
    2226                 : #endif
    2227                 : 
    2228                 : #endif // MOZ_X11
    2229                 : 
    2230                 :     nsEventStatus status;
    2231                 :     {
    2232               0 :       AutoLayerManagerSetup setupLayerManager(this, ctx, layerBuffering);
    2233               0 :       DispatchEvent(&event, status);
    2234                 :     }
    2235                 : 
    2236                 : #ifdef MOZ_X11
    2237                 :     // DispatchEvent can Destroy us (bug 378273), avoid doing any paint
    2238                 :     // operations below if that happened - it will lead to XError and exit().
    2239               0 :     if (translucent) {
    2240               0 :         if (NS_LIKELY(!mIsDestroyed)) {
    2241               0 :             if (status != nsEventStatus_eIgnore) {
    2242               0 :                 nsRefPtr<gfxPattern> pattern = ctx->PopGroup();
    2243                 : 
    2244                 :                 nsRefPtr<gfxImageSurface> img =
    2245                 :                     new gfxImageSurface(gfxIntSize(boundsRect.width, boundsRect.height),
    2246               0 :                                         gfxImageSurface::ImageFormatA8);
    2247               0 :                 if (img && !img->CairoStatus()) {
    2248               0 :                     img->SetDeviceOffset(gfxPoint(-boundsRect.x, -boundsRect.y));
    2249                 : 
    2250               0 :                     nsRefPtr<gfxContext> imgCtx = new gfxContext(img);
    2251               0 :                     if (imgCtx) {
    2252               0 :                         imgCtx->SetPattern(pattern);
    2253               0 :                         imgCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
    2254               0 :                         imgCtx->Paint();
    2255                 :                     }
    2256                 : 
    2257                 :                     UpdateTranslucentWindowAlphaInternal(nsIntRect(boundsRect.x, boundsRect.y,
    2258                 :                                                                    boundsRect.width, boundsRect.height),
    2259               0 :                                                          img->Data(), img->Stride());
    2260                 :                 }
    2261                 : 
    2262               0 :                 ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
    2263               0 :                 ctx->SetPattern(pattern);
    2264               0 :                 ctx->Paint();
    2265                 :             }
    2266                 :         }
    2267                 :     }
    2268                 : #  ifdef MOZ_HAVE_SHMIMAGE
    2269               0 :     if (nsShmImage::UseShm() && NS_LIKELY(!mIsDestroyed)) {
    2270                 : #if defined(MOZ_WIDGET_GTK2)
    2271               0 :         mShmImage->Put(mGdkWindow, rects, r_end);
    2272                 : #else
    2273                 :         mShmImage->Put(mGdkWindow, rects);
    2274                 : #endif
    2275                 :     }
    2276                 : #  endif  // MOZ_HAVE_SHMIMAGE
    2277                 : #endif // MOZ_X11
    2278                 : 
    2279                 : #if defined(MOZ_WIDGET_GTK2)
    2280               0 :     g_free(rects);
    2281                 : #else
    2282                 :     cairo_rectangle_list_destroy(rects);
    2283                 : #endif
    2284                 : 
    2285               0 :     DispatchDidPaint(this);
    2286                 : 
    2287                 :     // Synchronously flush any new dirty areas
    2288                 : #if defined(MOZ_WIDGET_GTK2)
    2289               0 :     GdkRegion* dirtyArea = gdk_window_get_update_area(mGdkWindow);
    2290                 : #else
    2291                 :     cairo_region_t* dirtyArea = gdk_window_get_update_area(mGdkWindow);
    2292                 : #endif
    2293                 : 
    2294               0 :     if (dirtyArea) {
    2295               0 :         gdk_window_invalidate_region(mGdkWindow, dirtyArea, false);
    2296                 : #if defined(MOZ_WIDGET_GTK2)
    2297               0 :         gdk_region_destroy(dirtyArea);
    2298                 : #else
    2299                 :         cairo_region_destroy(dirtyArea);
    2300                 : #endif
    2301               0 :         gdk_window_process_updates(mGdkWindow, false);
    2302                 :     }
    2303                 : 
    2304                 :     // check the return value!
    2305               0 :     return TRUE;
    2306                 : }
    2307                 : 
    2308                 : gboolean
    2309               0 : nsWindow::OnConfigureEvent(GtkWidget *aWidget, GdkEventConfigure *aEvent)
    2310                 : {
    2311                 :     // These events are only received on toplevel windows.
    2312                 :     //
    2313                 :     // GDK ensures that the coordinates are the client window top-left wrt the
    2314                 :     // root window.
    2315                 :     //
    2316                 :     //   GDK calculates the cordinates for real ConfigureNotify events on
    2317                 :     //   managed windows (that would normally be relative to the parent
    2318                 :     //   window).
    2319                 :     //
    2320                 :     //   Synthetic ConfigureNotify events are from the window manager and
    2321                 :     //   already relative to the root window.  GDK creates all X windows with
    2322                 :     //   border_width = 0, so synthetic events also indicate the top-left of
    2323                 :     //   the client window.
    2324                 :     //
    2325                 :     //   Override-redirect windows are children of the root window so parent
    2326                 :     //   coordinates are root coordinates.
    2327                 : 
    2328               0 :     LOG(("configure event [%p] %d %d %d %d\n", (void *)this,
    2329                 :          aEvent->x, aEvent->y, aEvent->width, aEvent->height));
    2330                 : 
    2331               0 :     nsIntRect screenBounds;
    2332               0 :     GetScreenBounds(screenBounds);
    2333                 : 
    2334               0 :     if (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog) {
    2335                 :         // This check avoids unwanted rollup on spurious configure events from
    2336                 :         // Cygwin/X (bug 672103).
    2337               0 :         if (mBounds.x != screenBounds.x ||
    2338                 :             mBounds.y != screenBounds.y) {
    2339               0 :             check_for_rollup(0, 0, false, true);
    2340                 :         }
    2341                 :     }
    2342                 : 
    2343                 :     // This event indicates that the window position may have changed.
    2344                 :     // mBounds.Size() is updated in OnSizeAllocate().
    2345                 : 
    2346                 :     // (The gtk_window_get_window_type() function is only available from
    2347                 :     // version 2.20.)
    2348               0 :     NS_ASSERTION(GTK_IS_WINDOW(aWidget),
    2349                 :                  "Configure event on widget that is not a GtkWindow");
    2350                 :     gint type;
    2351               0 :     g_object_get(aWidget, "type", &type, NULL);
    2352               0 :     if (type == GTK_WINDOW_POPUP) {
    2353                 :         // Override-redirect window
    2354                 :         //
    2355                 :         // These windows should not be moved by the window manager, and so any
    2356                 :         // change in position is a result of our direction.  mBounds has
    2357                 :         // already been set in Move() or Resize(), and that is more
    2358                 :         // up-to-date than the position in the ConfigureNotify event if the
    2359                 :         // event is from an earlier window move.
    2360                 :         //
    2361                 :         // Skipping the NS_MOVE dispatch saves context menus from an infinite
    2362                 :         // loop when nsXULPopupManager::PopupMoved moves the window to the new
    2363                 :         // position and nsMenuPopupFrame::SetPopupPosition adds
    2364                 :         // offsetForContextMenu on each iteration.
    2365               0 :         return FALSE;
    2366                 :     }
    2367                 : 
    2368               0 :     mBounds.MoveTo(screenBounds.TopLeft());
    2369                 : 
    2370               0 :     nsGUIEvent event(true, NS_MOVE, this);
    2371                 : 
    2372               0 :     event.refPoint = mBounds.TopLeft();
    2373                 : 
    2374                 :     // XXX mozilla will invalidate the entire window after this move
    2375                 :     // complete.  wtf?
    2376                 :     nsEventStatus status;
    2377               0 :     DispatchEvent(&event, status);
    2378                 : 
    2379               0 :     return FALSE;
    2380                 : }
    2381                 : 
    2382                 : void
    2383               0 : nsWindow::OnContainerUnrealize(GtkWidget *aWidget)
    2384                 : {
    2385                 :     // The GdkWindows are about to be destroyed (but not deleted), so remove
    2386                 :     // their references back to their container widget while the GdkWindow
    2387                 :     // hierarchy is still available.
    2388                 : 
    2389               0 :     NS_ASSERTION(mContainer == MOZ_CONTAINER(aWidget),
    2390                 :                  "unexpected \"unrealize\" signal");
    2391                 : 
    2392               0 :     if (mGdkWindow) {
    2393               0 :         DestroyChildWindows();
    2394                 : 
    2395               0 :         g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", NULL);
    2396               0 :         mGdkWindow = NULL;
    2397                 :     }
    2398               0 : }
    2399                 : 
    2400                 : void
    2401               0 : nsWindow::OnSizeAllocate(GtkWidget *aWidget, GtkAllocation *aAllocation)
    2402                 : {
    2403               0 :     LOG(("size_allocate [%p] %d %d %d %d\n",
    2404                 :          (void *)this, aAllocation->x, aAllocation->y,
    2405                 :          aAllocation->width, aAllocation->height));
    2406                 : 
    2407                 :     nsIntRect rect(aAllocation->x, aAllocation->y,
    2408               0 :                    aAllocation->width, aAllocation->height);
    2409                 : 
    2410               0 :     ResizeTransparencyBitmap(rect.width, rect.height);
    2411                 : 
    2412               0 :     mBounds.width = rect.width;
    2413               0 :     mBounds.height = rect.height;
    2414                 : 
    2415               0 :     if (!mGdkWindow)
    2416               0 :         return;
    2417                 : 
    2418               0 :     if (mTransparencyBitmap) {
    2419               0 :       ApplyTransparencyBitmap();
    2420                 :     }
    2421                 : 
    2422                 :     nsEventStatus status;
    2423               0 :     DispatchResizeEvent (rect, status);
    2424                 : }
    2425                 : 
    2426                 : void
    2427               0 : nsWindow::OnDeleteEvent(GtkWidget *aWidget, GdkEventAny *aEvent)
    2428                 : {
    2429               0 :     nsGUIEvent event(true, NS_XUL_CLOSE, this);
    2430                 : 
    2431               0 :     event.refPoint.x = 0;
    2432               0 :     event.refPoint.y = 0;
    2433                 : 
    2434                 :     nsEventStatus status;
    2435               0 :     DispatchEvent(&event, status);
    2436               0 : }
    2437                 : 
    2438                 : void
    2439               0 : nsWindow::OnEnterNotifyEvent(GtkWidget *aWidget, GdkEventCrossing *aEvent)
    2440                 : {
    2441                 :     // This skips NotifyVirtual and NotifyNonlinearVirtual enter notify events
    2442                 :     // when the pointer enters a child window.  If the destination window is a
    2443                 :     // Gecko window then we'll catch the corresponding event on that window,
    2444                 :     // but we won't notice when the pointer directly enters a foreign (plugin)
    2445                 :     // child window without passing over a visible portion of a Gecko window.
    2446               0 :     if (aEvent->subwindow != NULL)
    2447               0 :         return;
    2448                 : 
    2449                 :     // Check before is_parent_ungrab_enter() as the button state may have
    2450                 :     // changed while a non-Gecko ancestor window had a pointer grab.
    2451               0 :     DispatchMissedButtonReleases(aEvent);
    2452                 : 
    2453               0 :     if (is_parent_ungrab_enter(aEvent))
    2454               0 :         return;
    2455                 : 
    2456               0 :     nsMouseEvent event(true, NS_MOUSE_ENTER, this, nsMouseEvent::eReal);
    2457                 : 
    2458               0 :     event.refPoint.x = nscoord(aEvent->x);
    2459               0 :     event.refPoint.y = nscoord(aEvent->y);
    2460                 : 
    2461               0 :     event.time = aEvent->time;
    2462                 : 
    2463               0 :     LOG(("OnEnterNotify: %p\n", (void *)this));
    2464                 : 
    2465                 :     nsEventStatus status;
    2466               0 :     DispatchEvent(&event, status);
    2467                 : }
    2468                 : 
    2469                 : // XXX Is this the right test for embedding cases?
    2470                 : static bool
    2471               0 : is_top_level_mouse_exit(GdkWindow* aWindow, GdkEventCrossing *aEvent)
    2472                 : {
    2473               0 :     gint x = gint(aEvent->x_root);
    2474               0 :     gint y = gint(aEvent->y_root);
    2475               0 :     GdkDisplay* display = gdk_window_get_display(aWindow);
    2476               0 :     GdkWindow* winAtPt = gdk_display_get_window_at_pointer(display, &x, &y);
    2477               0 :     if (!winAtPt)
    2478               0 :         return true;
    2479               0 :     GdkWindow* topLevelAtPt = gdk_window_get_toplevel(winAtPt);
    2480               0 :     GdkWindow* topLevelWidget = gdk_window_get_toplevel(aWindow);
    2481               0 :     return topLevelAtPt != topLevelWidget;
    2482                 : }
    2483                 : 
    2484                 : void
    2485               0 : nsWindow::OnLeaveNotifyEvent(GtkWidget *aWidget, GdkEventCrossing *aEvent)
    2486                 : {
    2487                 :     // This ignores NotifyVirtual and NotifyNonlinearVirtual leave notify
    2488                 :     // events when the pointer leaves a child window.  If the destination
    2489                 :     // window is a Gecko window then we'll catch the corresponding event on
    2490                 :     // that window.
    2491                 :     //
    2492                 :     // XXXkt However, we will miss toplevel exits when the pointer directly
    2493                 :     // leaves a foreign (plugin) child window without passing over a visible
    2494                 :     // portion of a Gecko window.
    2495               0 :     if (aEvent->subwindow != NULL)
    2496               0 :         return;
    2497                 : 
    2498               0 :     nsMouseEvent event(true, NS_MOUSE_EXIT, this, nsMouseEvent::eReal);
    2499                 : 
    2500               0 :     event.refPoint.x = nscoord(aEvent->x);
    2501               0 :     event.refPoint.y = nscoord(aEvent->y);
    2502                 : 
    2503               0 :     event.time = aEvent->time;
    2504                 : 
    2505               0 :     event.exit = is_top_level_mouse_exit(mGdkWindow, aEvent)
    2506               0 :         ? nsMouseEvent::eTopLevel : nsMouseEvent::eChild;
    2507                 : 
    2508               0 :     LOG(("OnLeaveNotify: %p\n", (void *)this));
    2509                 : 
    2510                 :     nsEventStatus status;
    2511               0 :     DispatchEvent(&event, status);
    2512                 : }
    2513                 : 
    2514                 : void
    2515               0 : nsWindow::OnMotionNotifyEvent(GtkWidget *aWidget, GdkEventMotion *aEvent)
    2516                 : {
    2517                 :     // when we receive this, it must be that the gtk dragging is over,
    2518                 :     // it is dropped either in or out of mozilla, clear the flag
    2519               0 :     sIsDraggingOutOf = false;
    2520                 : 
    2521                 :     // see if we can compress this event
    2522                 :     // XXXldb Why skip every other motion event when we have multiple,
    2523                 :     // but not more than that?
    2524               0 :     bool synthEvent = false;
    2525                 : #ifdef MOZ_X11
    2526                 :     XEvent xevent;
    2527                 : 
    2528               0 :     while (XPending (GDK_WINDOW_XDISPLAY(aEvent->window))) {
    2529                 :         XEvent peeked;
    2530               0 :         XPeekEvent (GDK_WINDOW_XDISPLAY(aEvent->window), &peeked);
    2531               0 :         if (peeked.xany.window != gdk_x11_window_get_xid(aEvent->window)
    2532                 :             || peeked.type != MotionNotify)
    2533               0 :             break;
    2534                 : 
    2535               0 :         synthEvent = true;
    2536               0 :         XNextEvent (GDK_WINDOW_XDISPLAY(aEvent->window), &xevent);
    2537                 :     }
    2538                 : #if defined(MOZ_WIDGET_GTK2)
    2539                 :     // if plugins still keeps the focus, get it back
    2540               0 :     if (gPluginFocusWindow && gPluginFocusWindow != this) {
    2541               0 :         nsRefPtr<nsWindow> kungFuDeathGrip = gPluginFocusWindow;
    2542               0 :         gPluginFocusWindow->LoseNonXEmbedPluginFocus();
    2543                 :     }
    2544                 : #endif /* MOZ_WIDGET_GTK2 */
    2545                 : #endif /* MOZ_X11 */
    2546                 : 
    2547               0 :     nsMouseEvent event(true, NS_MOUSE_MOVE, this, nsMouseEvent::eReal);
    2548                 : 
    2549               0 :     gdouble pressure = 0;
    2550               0 :     gdk_event_get_axis ((GdkEvent*)aEvent, GDK_AXIS_PRESSURE, &pressure);
    2551                 :     // Sometime gdk generate 0 pressure value between normal values
    2552                 :     // We have to ignore that and use last valid value
    2553               0 :     if (pressure)
    2554               0 :       mLastMotionPressure = pressure;
    2555               0 :     event.pressure = mLastMotionPressure;
    2556                 : 
    2557                 :     guint modifierState;
    2558               0 :     if (synthEvent) {
    2559                 : #ifdef MOZ_X11
    2560               0 :         event.refPoint.x = nscoord(xevent.xmotion.x);
    2561               0 :         event.refPoint.y = nscoord(xevent.xmotion.y);
    2562                 : 
    2563               0 :         modifierState = xevent.xmotion.state;
    2564                 : 
    2565               0 :         event.time = xevent.xmotion.time;
    2566                 : #else
    2567                 :         event.refPoint.x = nscoord(aEvent->x);
    2568                 :         event.refPoint.y = nscoord(aEvent->y);
    2569                 : 
    2570                 :         modifierState = aEvent->state;
    2571                 : 
    2572                 :         event.time = aEvent->time;
    2573                 : #endif /* MOZ_X11 */
    2574                 :     }
    2575                 :     else {
    2576                 :         // XXX see OnScrollEvent()
    2577               0 :         if (aEvent->window == mGdkWindow) {
    2578               0 :             event.refPoint.x = nscoord(aEvent->x);
    2579               0 :             event.refPoint.y = nscoord(aEvent->y);
    2580                 :         } else {
    2581               0 :             nsIntPoint point(NSToIntFloor(aEvent->x_root), NSToIntFloor(aEvent->y_root));
    2582               0 :             event.refPoint = point - WidgetToScreenOffset();
    2583                 :         }
    2584                 : 
    2585               0 :         modifierState = aEvent->state;
    2586                 : 
    2587               0 :         event.time = aEvent->time;
    2588                 :     }
    2589                 : 
    2590               0 :     KeymapWrapper::InitInputEvent(event, modifierState);
    2591                 : 
    2592                 :     nsEventStatus status;
    2593               0 :     DispatchEvent(&event, status);
    2594               0 : }
    2595                 : 
    2596                 : // If the automatic pointer grab on ButtonPress has deactivated before
    2597                 : // ButtonRelease, and the mouse button is released while the pointer is not
    2598                 : // over any a Gecko window, then the ButtonRelease event will not be received.
    2599                 : // (A similar situation exists when the pointer is grabbed with owner_events
    2600                 : // True as the ButtonRelease may be received on a foreign [plugin] window).
    2601                 : // Use this method to check for released buttons when the pointer returns to a
    2602                 : // Gecko window.
    2603                 : void
    2604               0 : nsWindow::DispatchMissedButtonReleases(GdkEventCrossing *aGdkEvent)
    2605                 : {
    2606               0 :     guint changed = aGdkEvent->state ^ gButtonState;
    2607                 :     // Only consider button releases.
    2608                 :     // (Ignore button presses that occurred outside Gecko.)
    2609               0 :     guint released = changed & gButtonState;
    2610               0 :     gButtonState = aGdkEvent->state;
    2611                 : 
    2612                 :     // Loop over each button, excluding mouse wheel buttons 4 and 5 for which
    2613                 :     // GDK ignores releases.
    2614               0 :     for (guint buttonMask = GDK_BUTTON1_MASK;
    2615                 :          buttonMask <= GDK_BUTTON3_MASK;
    2616                 :          buttonMask <<= 1) {
    2617                 : 
    2618               0 :         if (released & buttonMask) {
    2619                 :             PRInt16 buttonType;
    2620               0 :             switch (buttonMask) {
    2621                 :             case GDK_BUTTON1_MASK:
    2622               0 :                 buttonType = nsMouseEvent::eLeftButton;
    2623               0 :                 break;
    2624                 :             case GDK_BUTTON2_MASK:
    2625               0 :                 buttonType = nsMouseEvent::eMiddleButton;
    2626               0 :                 break;
    2627                 :             default:
    2628               0 :                 NS_ASSERTION(buttonMask == GDK_BUTTON3_MASK,
    2629                 :                              "Unexpected button mask");
    2630               0 :                 buttonType = nsMouseEvent::eRightButton;
    2631                 :             }
    2632                 : 
    2633               0 :             LOG(("Synthesized button %u release on %p\n",
    2634                 :                  guint(buttonType + 1), (void *)this));
    2635                 : 
    2636                 :             // Dispatch a synthesized button up event to tell Gecko about the
    2637                 :             // change in state.  This event is marked as synthesized so that
    2638                 :             // it is not dispatched as a DOM event, because we don't know the
    2639                 :             // position, widget, modifiers, or time/order.
    2640                 :             nsMouseEvent synthEvent(true, NS_MOUSE_BUTTON_UP, this,
    2641               0 :                                     nsMouseEvent::eSynthesized);
    2642               0 :             synthEvent.button = buttonType;
    2643                 :             nsEventStatus status;
    2644               0 :             DispatchEvent(&synthEvent, status);
    2645                 : 
    2646               0 :             sLastButtonReleaseTime = aGdkEvent->time;
    2647                 :         }
    2648                 :     }
    2649               0 : }
    2650                 : 
    2651                 : void
    2652               0 : nsWindow::InitButtonEvent(nsMouseEvent &aEvent,
    2653                 :                           GdkEventButton *aGdkEvent)
    2654                 : {
    2655                 :     // XXX see OnScrollEvent()
    2656               0 :     if (aGdkEvent->window == mGdkWindow) {
    2657               0 :         aEvent.refPoint.x = nscoord(aGdkEvent->x);
    2658               0 :         aEvent.refPoint.y = nscoord(aGdkEvent->y);
    2659                 :     } else {
    2660               0 :         nsIntPoint point(NSToIntFloor(aGdkEvent->x_root), NSToIntFloor(aGdkEvent->y_root));
    2661               0 :         aEvent.refPoint = point - WidgetToScreenOffset();
    2662                 :     }
    2663                 : 
    2664               0 :     KeymapWrapper::InitInputEvent(aEvent, aGdkEvent->state);
    2665                 : 
    2666               0 :     aEvent.time = aGdkEvent->time;
    2667                 : 
    2668               0 :     switch (aGdkEvent->type) {
    2669                 :     case GDK_2BUTTON_PRESS:
    2670               0 :         aEvent.clickCount = 2;
    2671               0 :         break;
    2672                 :     case GDK_3BUTTON_PRESS:
    2673               0 :         aEvent.clickCount = 3;
    2674               0 :         break;
    2675                 :         // default is one click
    2676                 :     default:
    2677               0 :         aEvent.clickCount = 1;
    2678                 :     }
    2679               0 : }
    2680                 : 
    2681               0 : static guint ButtonMaskFromGDKButton(guint button)
    2682                 : {
    2683               0 :     return GDK_BUTTON1_MASK << (button - 1);
    2684                 : }
    2685                 : 
    2686                 : void
    2687               0 : nsWindow::OnButtonPressEvent(GtkWidget *aWidget, GdkEventButton *aEvent)
    2688                 : {
    2689               0 :     LOG(("Button %u press on %p\n", aEvent->button, (void *)this));
    2690                 : 
    2691                 :     nsEventStatus status;
    2692                 : 
    2693                 :     // If you double click in GDK, it will actually generate a second
    2694                 :     // GDK_BUTTON_PRESS before sending the GDK_2BUTTON_PRESS, and this is
    2695                 :     // different than the DOM spec.  GDK puts this in the queue
    2696                 :     // programatically, so it's safe to assume that if there's a
    2697                 :     // double click in the queue, it was generated so we can just drop
    2698                 :     // this click.
    2699               0 :     GdkEvent *peekedEvent = gdk_event_peek();
    2700               0 :     if (peekedEvent) {
    2701               0 :         GdkEventType type = peekedEvent->any.type;
    2702               0 :         gdk_event_free(peekedEvent);
    2703               0 :         if (type == GDK_2BUTTON_PRESS || type == GDK_3BUTTON_PRESS)
    2704               0 :             return;
    2705                 :     }
    2706                 : 
    2707                 :     // We haven't received the corresponding release event yet.
    2708               0 :     sLastButtonReleaseTime = 0;
    2709                 : 
    2710               0 :     nsWindow *containerWindow = GetContainerWindow();
    2711               0 :     if (!gFocusWindow && containerWindow) {
    2712               0 :         containerWindow->DispatchActivateEvent();
    2713                 :     }
    2714                 : 
    2715                 :     // check to see if we should rollup
    2716                 :     bool rolledUp =
    2717               0 :         check_for_rollup(aEvent->x_root, aEvent->y_root, false, false);
    2718               0 :     if (gConsumeRollupEvent && rolledUp)
    2719               0 :         return;
    2720                 : 
    2721               0 :     gdouble pressure = 0;
    2722               0 :     gdk_event_get_axis ((GdkEvent*)aEvent, GDK_AXIS_PRESSURE, &pressure);
    2723               0 :     mLastMotionPressure = pressure;
    2724                 : 
    2725                 :     PRUint16 domButton;
    2726               0 :     switch (aEvent->button) {
    2727                 :     case 1:
    2728               0 :         domButton = nsMouseEvent::eLeftButton;
    2729               0 :         break;
    2730                 :     case 2:
    2731               0 :         domButton = nsMouseEvent::eMiddleButton;
    2732               0 :         break;
    2733                 :     case 3:
    2734               0 :         domButton = nsMouseEvent::eRightButton;
    2735               0 :         break;
    2736                 :     // These are mapped to horizontal scroll
    2737                 :     case 6:
    2738                 :     case 7:
    2739                 :         {
    2740               0 :             nsMouseScrollEvent event(true, NS_MOUSE_SCROLL, this);
    2741               0 :             event.pressure = mLastMotionPressure;
    2742               0 :             event.scrollFlags = nsMouseScrollEvent::kIsHorizontal;
    2743               0 :             event.refPoint.x = nscoord(aEvent->x);
    2744               0 :             event.refPoint.y = nscoord(aEvent->y);
    2745                 :             // XXX Why is this delta value different from the scroll event?
    2746               0 :             event.delta = (aEvent->button == 6) ? -2 : 2;
    2747                 : 
    2748               0 :             KeymapWrapper::InitInputEvent(event, aEvent->state);
    2749                 : 
    2750               0 :             event.time = aEvent->time;
    2751                 : 
    2752                 :             nsEventStatus status;
    2753               0 :             DispatchEvent(&event, status);
    2754                 :             return;
    2755                 :         }
    2756                 :     // Map buttons 8-9 to back/forward
    2757                 :     case 8:
    2758               0 :         DispatchCommandEvent(nsGkAtoms::Back);
    2759               0 :         return;
    2760                 :     case 9:
    2761               0 :         DispatchCommandEvent(nsGkAtoms::Forward);
    2762               0 :         return;
    2763                 :     default:
    2764               0 :         return;
    2765                 :     }
    2766                 : 
    2767               0 :     gButtonState |= ButtonMaskFromGDKButton(aEvent->button);
    2768                 : 
    2769               0 :     nsMouseEvent event(true, NS_MOUSE_BUTTON_DOWN, this, nsMouseEvent::eReal);
    2770               0 :     event.button = domButton;
    2771               0 :     InitButtonEvent(event, aEvent);
    2772               0 :     event.pressure = mLastMotionPressure;
    2773                 : 
    2774               0 :     DispatchEvent(&event, status);
    2775                 : 
    2776                 :     // right menu click on linux should also pop up a context menu
    2777               0 :     if (domButton == nsMouseEvent::eRightButton &&
    2778               0 :         NS_LIKELY(!mIsDestroyed)) {
    2779                 :         nsMouseEvent contextMenuEvent(true, NS_CONTEXTMENU, this,
    2780               0 :                                       nsMouseEvent::eReal);
    2781               0 :         InitButtonEvent(contextMenuEvent, aEvent);
    2782               0 :         contextMenuEvent.pressure = mLastMotionPressure;
    2783               0 :         DispatchEvent(&contextMenuEvent, status);
    2784                 :     }
    2785                 : }
    2786                 : 
    2787                 : void
    2788               0 : nsWindow::OnButtonReleaseEvent(GtkWidget *aWidget, GdkEventButton *aEvent)
    2789                 : {
    2790               0 :     LOG(("Button %u release on %p\n", aEvent->button, (void *)this));
    2791                 : 
    2792                 :     PRUint16 domButton;
    2793               0 :     sLastButtonReleaseTime = aEvent->time;
    2794                 : 
    2795               0 :     switch (aEvent->button) {
    2796                 :     case 1:
    2797               0 :         domButton = nsMouseEvent::eLeftButton;
    2798               0 :         break;
    2799                 :     case 2:
    2800               0 :         domButton = nsMouseEvent::eMiddleButton;
    2801               0 :         break;
    2802                 :     case 3:
    2803               0 :         domButton = nsMouseEvent::eRightButton;
    2804               0 :         break;
    2805                 :     default:
    2806               0 :         return;
    2807                 :     }
    2808                 : 
    2809               0 :     gButtonState &= ~ButtonMaskFromGDKButton(aEvent->button);
    2810                 : 
    2811               0 :     nsMouseEvent event(true, NS_MOUSE_BUTTON_UP, this, nsMouseEvent::eReal);
    2812               0 :     event.button = domButton;
    2813               0 :     InitButtonEvent(event, aEvent);
    2814               0 :     gdouble pressure = 0;
    2815               0 :     gdk_event_get_axis ((GdkEvent*)aEvent, GDK_AXIS_PRESSURE, &pressure);
    2816               0 :     event.pressure = pressure ? pressure : mLastMotionPressure;
    2817                 : 
    2818                 :     nsEventStatus status;
    2819               0 :     DispatchEvent(&event, status);
    2820               0 :     mLastMotionPressure = pressure;
    2821                 : }
    2822                 : 
    2823                 : void
    2824               0 : nsWindow::OnContainerFocusInEvent(GtkWidget *aWidget, GdkEventFocus *aEvent)
    2825                 : {
    2826               0 :     NS_ASSERTION(mWindowType != eWindowType_popup,
    2827                 :                  "Unexpected focus on a popup window");
    2828                 : 
    2829               0 :     LOGFOCUS(("OnContainerFocusInEvent [%p]\n", (void *)this));
    2830                 : 
    2831                 :     // Unset the urgency hint, if possible
    2832               0 :     GtkWidget* top_window = nsnull;
    2833               0 :     GetToplevelWidget(&top_window);
    2834               0 :     if (top_window && (gtk_widget_get_visible(top_window)))
    2835               0 :         SetUrgencyHint(top_window, false);
    2836                 : 
    2837                 :     // Return if being called within SetFocus because the focus manager
    2838                 :     // already knows that the window is active.
    2839               0 :     if (gBlockActivateEvent) {
    2840               0 :         LOGFOCUS(("NS_ACTIVATE event is blocked [%p]\n", (void *)this));
    2841               0 :         return;
    2842                 :     }
    2843                 : 
    2844                 :     // This is not usually the correct window for dispatching key events,
    2845                 :     // but the focus manager will call SetFocus to set the correct window if
    2846                 :     // keyboard input will be accepted.  Setting a non-NULL value here
    2847                 :     // prevents OnButtonPressEvent() from dispatching NS_ACTIVATE if the
    2848                 :     // widget is already active.
    2849               0 :     gFocusWindow = this;
    2850                 : 
    2851               0 :     DispatchActivateEvent();
    2852                 : 
    2853               0 :     LOGFOCUS(("Events sent from focus in event [%p]\n", (void *)this));
    2854                 : }
    2855                 : 
    2856                 : void
    2857               0 : nsWindow::OnContainerFocusOutEvent(GtkWidget *aWidget, GdkEventFocus *aEvent)
    2858                 : {
    2859               0 :     LOGFOCUS(("OnContainerFocusOutEvent [%p]\n", (void *)this));
    2860                 : 
    2861               0 :     if (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog) {
    2862               0 :         nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
    2863               0 :         nsCOMPtr<nsIDragSession> dragSession;
    2864               0 :         dragService->GetCurrentSession(getter_AddRefs(dragSession));
    2865                 : 
    2866                 :         // Rollup popups when a window is focused out unless a drag is occurring.
    2867                 :         // This check is because drags grab the keyboard and cause a focus out on
    2868                 :         // versions of GTK before 2.18.
    2869               0 :         bool shouldRollup = !dragSession;
    2870               0 :         if (!shouldRollup) {
    2871                 :             // we also roll up when a drag is from a different application
    2872               0 :             nsCOMPtr<nsIDOMNode> sourceNode;
    2873               0 :             dragSession->GetSourceNode(getter_AddRefs(sourceNode));
    2874               0 :             shouldRollup = (sourceNode == nsnull);
    2875                 :         }
    2876                 : 
    2877               0 :         if (shouldRollup) {
    2878               0 :             check_for_rollup(0, 0, false, true);
    2879                 :         }
    2880                 :     }
    2881                 : 
    2882                 : #if defined(MOZ_WIDGET_GTK2) && defined(MOZ_X11)
    2883                 :     // plugin lose focus
    2884               0 :     if (gPluginFocusWindow) {
    2885               0 :         nsRefPtr<nsWindow> kungFuDeathGrip = gPluginFocusWindow;
    2886               0 :         gPluginFocusWindow->LoseNonXEmbedPluginFocus();
    2887                 :     }
    2888                 : #endif /* MOZ_X11 && MOZ_WIDGET_GTK2 */
    2889                 : 
    2890               0 :     if (gFocusWindow) {
    2891               0 :         nsRefPtr<nsWindow> kungFuDeathGrip = gFocusWindow;
    2892               0 :         if (gFocusWindow->mIMModule) {
    2893               0 :             gFocusWindow->mIMModule->OnBlurWindow(gFocusWindow);
    2894                 :         }
    2895               0 :         gFocusWindow = nsnull;
    2896                 :     }
    2897                 : 
    2898               0 :     DispatchDeactivateEvent();
    2899                 : 
    2900               0 :     LOGFOCUS(("Done with container focus out [%p]\n", (void *)this));
    2901               0 : }
    2902                 : 
    2903                 : bool
    2904               0 : nsWindow::DispatchCommandEvent(nsIAtom* aCommand)
    2905                 : {
    2906                 :     nsEventStatus status;
    2907               0 :     nsCommandEvent event(true, nsGkAtoms::onAppCommand, aCommand, this);
    2908               0 :     DispatchEvent(&event, status);
    2909               0 :     return TRUE;
    2910                 : }
    2911                 : 
    2912                 : bool
    2913               0 : nsWindow::DispatchContentCommandEvent(PRInt32 aMsg)
    2914                 : {
    2915                 :   nsEventStatus status;
    2916               0 :   nsContentCommandEvent event(true, aMsg, this);
    2917               0 :   DispatchEvent(&event, status);
    2918               0 :   return TRUE;
    2919                 : }
    2920                 : 
    2921                 : static bool
    2922               0 : IsCtrlAltTab(GdkEventKey *aEvent)
    2923                 : {
    2924                 :     return aEvent->keyval == GDK_Tab &&
    2925                 :         KeymapWrapper::AreModifiersActive(
    2926               0 :             KeymapWrapper::CTRL | KeymapWrapper::ALT, aEvent->state);
    2927                 : }
    2928                 : 
    2929                 : bool
    2930               0 : nsWindow::DispatchKeyDownEvent(GdkEventKey *aEvent, bool *aCancelled)
    2931                 : {
    2932               0 :     NS_PRECONDITION(aCancelled, "aCancelled must not be null");
    2933                 : 
    2934               0 :     *aCancelled = false;
    2935                 : 
    2936               0 :     if (IsCtrlAltTab(aEvent)) {
    2937               0 :         return false;
    2938                 :     }
    2939                 : 
    2940                 :     // send the key down event
    2941                 :     nsEventStatus status;
    2942               0 :     nsKeyEvent downEvent(true, NS_KEY_DOWN, this);
    2943               0 :     KeymapWrapper::InitKeyEvent(downEvent, aEvent);
    2944               0 :     DispatchEvent(&downEvent, status);
    2945               0 :     *aCancelled = (status == nsEventStatus_eConsumeNoDefault);
    2946               0 :     return true;
    2947                 : }
    2948                 : 
    2949                 : gboolean
    2950               0 : nsWindow::OnKeyPressEvent(GtkWidget *aWidget, GdkEventKey *aEvent)
    2951                 : {
    2952               0 :     LOGFOCUS(("OnKeyPressEvent [%p]\n", (void *)this));
    2953                 : 
    2954                 :     // if we are in the middle of composing text, XIM gets to see it
    2955                 :     // before mozilla does.
    2956               0 :     bool IMEWasEnabled = false;
    2957               0 :     if (mIMModule) {
    2958               0 :         IMEWasEnabled = mIMModule->IsEnabled();
    2959               0 :         if (mIMModule->OnKeyEvent(this, aEvent)) {
    2960               0 :             return TRUE;
    2961                 :         }
    2962                 :     }
    2963                 : 
    2964                 :     nsEventStatus status;
    2965                 : 
    2966                 :     // work around for annoying things.
    2967               0 :     if (IsCtrlAltTab(aEvent)) {
    2968               0 :         return TRUE;
    2969                 :     }
    2970                 : 
    2971               0 :     nsCOMPtr<nsIWidget> kungFuDeathGrip = this;
    2972                 : 
    2973                 :     // Dispatch keydown event always.  At auto repeating, we should send
    2974                 :     // KEYDOWN -> KEYPRESS -> KEYDOWN -> KEYPRESS ... -> KEYUP
    2975                 :     // However, old distributions (e.g., Ubuntu 9.10) sent native key
    2976                 :     // release event, so, on such platform, the DOM events will be:
    2977                 :     // KEYDOWN -> KEYPRESS -> KEYUP -> KEYDOWN -> KEYPRESS -> KEYUP...
    2978                 : 
    2979               0 :     bool isKeyDownCancelled = false;
    2980               0 :     if (DispatchKeyDownEvent(aEvent, &isKeyDownCancelled) &&
    2981               0 :         NS_UNLIKELY(mIsDestroyed)) {
    2982               0 :         return TRUE;
    2983                 :     }
    2984                 : 
    2985                 :     // If a keydown event handler causes to enable IME, i.e., it moves
    2986                 :     // focus from IME unusable content to IME usable editor, we should
    2987                 :     // send the native key event to IME for the first input on the editor.
    2988               0 :     if (!IMEWasEnabled && mIMModule && mIMModule->IsEnabled()) {
    2989                 :         // Notice our keydown event was already dispatched.  This prevents
    2990                 :         // unnecessary DOM keydown event in the editor.
    2991               0 :         if (mIMModule->OnKeyEvent(this, aEvent, true)) {
    2992               0 :             return TRUE;
    2993                 :         }
    2994                 :     }
    2995                 : 
    2996                 :     // Don't pass modifiers as NS_KEY_PRESS events.
    2997                 :     // TODO: Instead of selectively excluding some keys from NS_KEY_PRESS events,
    2998                 :     //       we should instead selectively include (as per MSDN spec; no official
    2999                 :     //       spec covers KeyPress events).
    3000               0 :     if (!KeymapWrapper::IsKeyPressEventNecessary(aEvent)) {
    3001               0 :         return TRUE;
    3002                 :     }
    3003                 : 
    3004                 : #ifdef MOZ_X11
    3005                 : #if ! defined AIX // no XFree86 on AIX 5L
    3006                 :     // Look for specialized app-command keys
    3007               0 :     switch (aEvent->keyval) {
    3008                 :         case XF86XK_Back:
    3009               0 :             return DispatchCommandEvent(nsGkAtoms::Back);
    3010                 :         case XF86XK_Forward:
    3011               0 :             return DispatchCommandEvent(nsGkAtoms::Forward);
    3012                 :         case XF86XK_Refresh:
    3013               0 :             return DispatchCommandEvent(nsGkAtoms::Reload);
    3014                 :         case XF86XK_Stop:
    3015               0 :             return DispatchCommandEvent(nsGkAtoms::Stop);
    3016                 :         case XF86XK_Search:
    3017               0 :             return DispatchCommandEvent(nsGkAtoms::Search);
    3018                 :         case XF86XK_Favorites:
    3019               0 :             return DispatchCommandEvent(nsGkAtoms::Bookmarks);
    3020                 :         case XF86XK_HomePage:
    3021               0 :             return DispatchCommandEvent(nsGkAtoms::Home);
    3022                 :         case XF86XK_Copy:
    3023                 :         case GDK_F16:  // F16, F20, F18, F14 are old keysyms for Copy Cut Paste Undo
    3024               0 :             return DispatchContentCommandEvent(NS_CONTENT_COMMAND_COPY);
    3025                 :         case XF86XK_Cut:
    3026                 :         case GDK_F20:
    3027               0 :             return DispatchContentCommandEvent(NS_CONTENT_COMMAND_CUT);
    3028                 :         case XF86XK_Paste:
    3029                 :         case GDK_F18:
    3030               0 :             return DispatchContentCommandEvent(NS_CONTENT_COMMAND_PASTE);
    3031                 :         case GDK_Redo:
    3032               0 :             return DispatchContentCommandEvent(NS_CONTENT_COMMAND_REDO);
    3033                 :         case GDK_Undo:
    3034                 :         case GDK_F14:
    3035               0 :             return DispatchContentCommandEvent(NS_CONTENT_COMMAND_UNDO);
    3036                 :     }
    3037                 : #endif /* ! AIX */
    3038                 : #endif /* MOZ_X11 */
    3039                 : 
    3040               0 :     nsKeyEvent event(true, NS_KEY_PRESS, this);
    3041               0 :     KeymapWrapper::InitKeyEvent(event, aEvent);
    3042               0 :     if (isKeyDownCancelled) {
    3043                 :       // If prevent default set for onkeydown, do the same for onkeypress
    3044               0 :       event.flags |= NS_EVENT_FLAG_NO_DEFAULT;
    3045                 :     }
    3046                 : 
    3047                 :     // before we dispatch a key, check if it's the context menu key.
    3048                 :     // If so, send a context menu key event instead.
    3049               0 :     if (is_context_menu_key(event)) {
    3050                 :         nsMouseEvent contextMenuEvent(true, NS_CONTEXTMENU, this,
    3051                 :                                       nsMouseEvent::eReal,
    3052               0 :                                       nsMouseEvent::eContextMenuKey);
    3053                 : 
    3054               0 :         contextMenuEvent.refPoint = nsIntPoint(0, 0);
    3055               0 :         contextMenuEvent.time = aEvent->time;
    3056               0 :         contextMenuEvent.clickCount = 1;
    3057               0 :         KeymapWrapper::InitInputEvent(contextMenuEvent, aEvent->state);
    3058               0 :         DispatchEvent(&contextMenuEvent, status);
    3059                 :     }
    3060                 :     else {
    3061                 :         // If the character code is in the BMP, send the key press event.
    3062                 :         // Otherwise, send a text event with the equivalent UTF-16 string.
    3063               0 :         if (IS_IN_BMP(event.charCode)) {
    3064               0 :             DispatchEvent(&event, status);
    3065                 :         }
    3066                 :         else {
    3067               0 :             nsTextEvent textEvent(true, NS_TEXT_TEXT, this);
    3068                 :             PRUnichar textString[3];
    3069               0 :             textString[0] = H_SURROGATE(event.charCode);
    3070               0 :             textString[1] = L_SURROGATE(event.charCode);
    3071               0 :             textString[2] = 0;
    3072               0 :             textEvent.theText = textString;
    3073               0 :             textEvent.time = event.time;
    3074               0 :             DispatchEvent(&textEvent, status);
    3075                 :         }
    3076                 :     }
    3077                 : 
    3078                 :     // If the event was consumed, return.
    3079               0 :     if (status == nsEventStatus_eConsumeNoDefault) {
    3080               0 :         return TRUE;
    3081                 :     }
    3082                 : 
    3083               0 :     return FALSE;
    3084                 : }
    3085                 : 
    3086                 : gboolean
    3087               0 : nsWindow::OnKeyReleaseEvent(GtkWidget *aWidget, GdkEventKey *aEvent)
    3088                 : {
    3089               0 :     LOGFOCUS(("OnKeyReleaseEvent [%p]\n", (void *)this));
    3090                 : 
    3091               0 :     if (mIMModule && mIMModule->OnKeyEvent(this, aEvent)) {
    3092               0 :         return TRUE;
    3093                 :     }
    3094                 : 
    3095                 :     // send the key event as a key up event
    3096               0 :     nsKeyEvent event(true, NS_KEY_UP, this);
    3097               0 :     KeymapWrapper::InitKeyEvent(event, aEvent);
    3098                 : 
    3099                 :     nsEventStatus status;
    3100               0 :     DispatchEvent(&event, status);
    3101                 : 
    3102                 :     // If the event was consumed, return.
    3103               0 :     if (status == nsEventStatus_eConsumeNoDefault) {
    3104               0 :         return TRUE;
    3105                 :     }
    3106                 : 
    3107               0 :     return FALSE;
    3108                 : }
    3109                 : 
    3110                 : void
    3111               0 : nsWindow::OnScrollEvent(GtkWidget *aWidget, GdkEventScroll *aEvent)
    3112                 : {
    3113                 :     // check to see if we should rollup
    3114                 :     bool rolledUp =
    3115               0 :         check_for_rollup(aEvent->x_root, aEvent->y_root, true, false);
    3116               0 :     if (gConsumeRollupEvent && rolledUp)
    3117               0 :         return;
    3118                 : 
    3119               0 :     nsMouseScrollEvent event(true, NS_MOUSE_SCROLL, this);
    3120               0 :     switch (aEvent->direction) {
    3121                 :     case GDK_SCROLL_UP:
    3122               0 :         event.scrollFlags = nsMouseScrollEvent::kIsVertical;
    3123               0 :         event.delta = -3;
    3124               0 :         break;
    3125                 :     case GDK_SCROLL_DOWN:
    3126               0 :         event.scrollFlags = nsMouseScrollEvent::kIsVertical;
    3127               0 :         event.delta = 3;
    3128               0 :         break;
    3129                 :     case GDK_SCROLL_LEFT:
    3130               0 :         event.scrollFlags = nsMouseScrollEvent::kIsHorizontal;
    3131               0 :         event.delta = -1;
    3132               0 :         break;
    3133                 :     case GDK_SCROLL_RIGHT:
    3134               0 :         event.scrollFlags = nsMouseScrollEvent::kIsHorizontal;
    3135               0 :         event.delta = 1;
    3136               0 :         break;
    3137                 :     }
    3138                 : 
    3139               0 :     if (aEvent->window == mGdkWindow) {
    3140                 :         // we are the window that the event happened on so no need for expensive WidgetToScreenOffset
    3141               0 :         event.refPoint.x = nscoord(aEvent->x);
    3142               0 :         event.refPoint.y = nscoord(aEvent->y);
    3143                 :     } else {
    3144                 :         // XXX we're never quite sure which GdkWindow the event came from due to our custom bubbling
    3145                 :         // in scroll_event_cb(), so use ScreenToWidget to translate the screen root coordinates into
    3146                 :         // coordinates relative to this widget.
    3147               0 :         nsIntPoint point(NSToIntFloor(aEvent->x_root), NSToIntFloor(aEvent->y_root));
    3148               0 :         event.refPoint = point - WidgetToScreenOffset();
    3149                 :     }
    3150                 : 
    3151               0 :     KeymapWrapper::InitInputEvent(event, aEvent->state);
    3152                 : 
    3153               0 :     event.time = aEvent->time;
    3154                 : 
    3155                 :     nsEventStatus status;
    3156               0 :     DispatchEvent(&event, status);
    3157                 : }
    3158                 : 
    3159                 : void
    3160               0 : nsWindow::OnVisibilityNotifyEvent(GtkWidget *aWidget,
    3161                 :                                   GdkEventVisibility *aEvent)
    3162                 : {
    3163               0 :     LOGDRAW(("Visibility event %i on [%p] %p\n",
    3164                 :              aEvent->state, this, aEvent->window));
    3165                 : 
    3166               0 :     if (!mGdkWindow)
    3167               0 :         return;
    3168                 : 
    3169               0 :     switch (aEvent->state) {
    3170                 :     case GDK_VISIBILITY_UNOBSCURED:
    3171                 :     case GDK_VISIBILITY_PARTIAL:
    3172               0 :         if (mIsFullyObscured && mHasMappedToplevel) {
    3173                 :             // GDK_EXPOSE events have been ignored, so make sure GDK
    3174                 :             // doesn't think that the window has already been painted.
    3175               0 :             gdk_window_invalidate_rect(mGdkWindow, NULL, FALSE);
    3176                 :         }
    3177                 : 
    3178               0 :         mIsFullyObscured = false;
    3179                 : 
    3180                 :         // In Hildon/Maemo, a browser window will get into 'patially visible' state wheneven an
    3181                 :         // autocomplete feature is dropped down (from urlbar or from an entry form completion),
    3182                 :         // and there are no much further ways for that to happen in the plaftorm. In such cases, if hildon
    3183                 :         // virtual keyboard is up, we can not grab focus to any dropdown list. Reason: nsWindow::EnsureGrabs()
    3184                 :         // calls gdk_pointer_grab() which grabs the pointer (usually a mouse) so that all events are passed
    3185                 :         // to this it until the pointer is ungrabbed.
    3186               0 :         if (!nsGtkIMModule::IsVirtualKeyboardOpened()) {
    3187                 :             // if we have to retry the grab, retry it.
    3188               0 :             EnsureGrabs();
    3189                 :         }
    3190               0 :         break;
    3191                 :     default: // includes GDK_VISIBILITY_FULLY_OBSCURED
    3192               0 :         mIsFullyObscured = true;
    3193               0 :         break;
    3194                 :     }
    3195                 : }
    3196                 : 
    3197                 : void
    3198               0 : nsWindow::OnWindowStateEvent(GtkWidget *aWidget, GdkEventWindowState *aEvent)
    3199                 : {
    3200               0 :     LOG(("nsWindow::OnWindowStateEvent [%p] changed %d new_window_state %d\n",
    3201                 :          (void *)this, aEvent->changed_mask, aEvent->new_window_state));
    3202                 : 
    3203               0 :     if (IS_MOZ_CONTAINER(aWidget)) {
    3204                 :         // This event is notifying the container widget of changes to the
    3205                 :         // toplevel window.  Just detect changes affecting whether windows are
    3206                 :         // viewable.
    3207                 :         //
    3208                 :         // (A visibility notify event is sent to each window that becomes
    3209                 :         // viewable when the toplevel is mapped, but we can't rely on that for
    3210                 :         // setting mHasMappedToplevel because these toplevel window state
    3211                 :         // events are asynchronous.  The windows in the hierarchy now may not
    3212                 :         // be the same windows as when the toplevel was mapped, so they may
    3213                 :         // not get VisibilityNotify events.)
    3214                 :         bool mapped =
    3215                 :             !(aEvent->new_window_state &
    3216               0 :               (GDK_WINDOW_STATE_ICONIFIED|GDK_WINDOW_STATE_WITHDRAWN));
    3217               0 :         if (mHasMappedToplevel != mapped) {
    3218               0 :             SetHasMappedToplevel(mapped);
    3219                 :         }
    3220               0 :         return;
    3221                 :     }
    3222                 :     // else the widget is a shell widget.
    3223                 : 
    3224               0 :     nsSizeModeEvent event(true, NS_SIZEMODE, this);
    3225                 : 
    3226                 :     // We don't care about anything but changes in the maximized/icon/fullscreen
    3227                 :     // states
    3228               0 :     if ((aEvent->changed_mask
    3229                 :          & (GDK_WINDOW_STATE_ICONIFIED |
    3230                 :             GDK_WINDOW_STATE_MAXIMIZED |
    3231                 :             GDK_WINDOW_STATE_FULLSCREEN)) == 0) {
    3232                 :         return;
    3233                 :     }
    3234                 : 
    3235               0 :     if (aEvent->new_window_state & GDK_WINDOW_STATE_ICONIFIED) {
    3236               0 :         LOG(("\tIconified\n"));
    3237               0 :         event.mSizeMode = nsSizeMode_Minimized;
    3238               0 :         mSizeState = nsSizeMode_Minimized;
    3239                 : #ifdef ACCESSIBILITY
    3240               0 :         DispatchMinimizeEventAccessible();
    3241                 : #endif //ACCESSIBILITY
    3242                 :     }
    3243               0 :     else if (aEvent->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) {
    3244               0 :         LOG(("\tFullscreen\n"));
    3245               0 :         event.mSizeMode = nsSizeMode_Fullscreen;
    3246               0 :         mSizeState = nsSizeMode_Fullscreen;
    3247                 :     }
    3248               0 :     else if (aEvent->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) {
    3249               0 :         LOG(("\tMaximized\n"));
    3250               0 :         event.mSizeMode = nsSizeMode_Maximized;
    3251               0 :         mSizeState = nsSizeMode_Maximized;
    3252                 : #ifdef ACCESSIBILITY
    3253               0 :         DispatchMaximizeEventAccessible();
    3254                 : #endif //ACCESSIBILITY
    3255                 :     }
    3256                 :     else {
    3257               0 :         LOG(("\tNormal\n"));
    3258               0 :         event.mSizeMode = nsSizeMode_Normal;
    3259               0 :         mSizeState = nsSizeMode_Normal;
    3260                 : #ifdef ACCESSIBILITY
    3261               0 :         DispatchRestoreEventAccessible();
    3262                 : #endif //ACCESSIBILITY
    3263                 :     }
    3264                 : 
    3265                 :     nsEventStatus status;
    3266               0 :     DispatchEvent(&event, status);
    3267                 : }
    3268                 : 
    3269                 : void
    3270               0 : nsWindow::ThemeChanged()
    3271                 : {
    3272               0 :     nsGUIEvent event(true, NS_THEMECHANGED, this);
    3273               0 :     nsEventStatus status = nsEventStatus_eIgnore;
    3274               0 :     DispatchEvent(&event, status);
    3275                 : 
    3276               0 :     if (!mGdkWindow || NS_UNLIKELY(mIsDestroyed))
    3277                 :         return;
    3278                 : 
    3279                 :     // Dispatch NS_THEMECHANGED to all child windows
    3280                 :     GList *children =
    3281               0 :         gdk_window_peek_children(mGdkWindow);
    3282               0 :     while (children) {
    3283               0 :         GdkWindow *gdkWin = GDK_WINDOW(children->data);
    3284                 : 
    3285               0 :         nsWindow *win = (nsWindow*) g_object_get_data(G_OBJECT(gdkWin),
    3286               0 :                                                       "nsWindow");
    3287                 : 
    3288               0 :         if (win && win != this) { // guard against infinite recursion
    3289               0 :             nsRefPtr<nsWindow> kungFuDeathGrip = win;
    3290               0 :             win->ThemeChanged();
    3291                 :         }
    3292                 : 
    3293               0 :         children = children->next;
    3294                 :     }
    3295                 : }
    3296                 : 
    3297                 : void
    3298               0 : nsWindow::CheckNeedDragLeaveEnter(nsWindow* aInnerMostWidget,
    3299                 :                                   nsIDragService* aDragService,
    3300                 :                                   GdkDragContext *aDragContext,
    3301                 :                                   nscoord aX, nscoord aY)
    3302                 : {
    3303                 :     // check to see if there was a drag motion window already in place
    3304               0 :     if (sLastDragMotionWindow) {
    3305                 :         // same as the last window so no need for dragenter and dragleave events
    3306               0 :         if (sLastDragMotionWindow == aInnerMostWidget) {
    3307               0 :             UpdateDragStatus(aDragContext, aDragService);
    3308               0 :             return;
    3309                 :         }
    3310                 : 
    3311                 :         // send a dragleave event to the last window that got a motion event
    3312               0 :         nsRefPtr<nsWindow> kungFuDeathGrip = sLastDragMotionWindow;
    3313               0 :         sLastDragMotionWindow->OnDragLeave();
    3314                 :     }
    3315                 : 
    3316                 :     // Make sure that the drag service knows we're now dragging
    3317               0 :     aDragService->StartDragSession();
    3318                 : 
    3319                 :     // update our drag status and send a dragenter event to the window
    3320               0 :     UpdateDragStatus(aDragContext, aDragService);
    3321               0 :     aInnerMostWidget->OnDragEnter(aX, aY);
    3322                 : 
    3323                 :     // set the last window to the innerMostWidget
    3324               0 :     sLastDragMotionWindow = aInnerMostWidget;
    3325                 : }
    3326                 : 
    3327                 : gboolean
    3328               0 : nsWindow::OnDragMotionEvent(GtkWidget *aWidget,
    3329                 :                             GdkDragContext *aDragContext,
    3330                 :                             gint aX,
    3331                 :                             gint aY,
    3332                 :                             guint aTime,
    3333                 :                             gpointer aData)
    3334                 : {
    3335               0 :     LOGDRAG(("nsWindow::OnDragMotionSignal\n"));
    3336                 : 
    3337               0 :     if (sLastButtonReleaseTime) {
    3338                 :       // The drag ended before it was even setup to handle the end of the drag
    3339                 :       // So, we fake the button getting released again to release the drag
    3340               0 :       GtkWidget *widget = gtk_grab_get_current();
    3341                 :       GdkEvent event;
    3342                 :       gboolean retval;
    3343               0 :       memset(&event, 0, sizeof(event));
    3344               0 :       event.type = GDK_BUTTON_RELEASE;
    3345               0 :       event.button.time = sLastButtonReleaseTime;
    3346               0 :       event.button.button = 1;
    3347               0 :       sLastButtonReleaseTime = 0;
    3348               0 :       if (widget) {
    3349               0 :         g_signal_emit_by_name(widget, "button_release_event", &event, &retval);
    3350               0 :         return TRUE;
    3351                 :       }
    3352                 :     }
    3353                 : 
    3354               0 :     sIsDraggingOutOf = false;
    3355                 : 
    3356                 :     // get our drag context
    3357               0 :     nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
    3358               0 :     nsCOMPtr<nsIDragSessionGTK> dragSessionGTK = do_QueryInterface(dragService);
    3359                 : 
    3360                 :     // first, figure out which internal widget this drag motion actually
    3361                 :     // happened on
    3362               0 :     nscoord retx = 0;
    3363               0 :     nscoord rety = 0;
    3364                 : 
    3365                 :     GdkWindow *innerWindow = get_inner_gdk_window(gtk_widget_get_window(aWidget), aX, aY,
    3366               0 :                                                   &retx, &rety);
    3367               0 :     nsRefPtr<nsWindow> innerMostWidget = get_window_for_gdk_window(innerWindow);
    3368                 : 
    3369               0 :     if (!innerMostWidget)
    3370               0 :         innerMostWidget = this;
    3371                 : 
    3372                 :     // update the drag context
    3373               0 :     dragSessionGTK->TargetSetLastContext(aWidget, aDragContext, aTime);
    3374                 : 
    3375                 :     // clear any drag leave timer that might be pending so that it
    3376                 :     // doesn't get processed when we actually go out to get data.
    3377               0 :     if (mDragLeaveTimer) {
    3378               0 :         mDragLeaveTimer->Cancel();
    3379               0 :         mDragLeaveTimer = nsnull;
    3380                 :     }
    3381                 : 
    3382               0 :     CheckNeedDragLeaveEnter(innerMostWidget, dragService, aDragContext, retx, rety);
    3383                 : 
    3384                 :     // notify the drag service that we are starting a drag motion.
    3385               0 :     dragSessionGTK->TargetStartDragMotion();
    3386                 : 
    3387               0 :     dragService->FireDragEventAtSource(NS_DRAGDROP_DRAG);
    3388                 : 
    3389               0 :     nsDragEvent event(true, NS_DRAGDROP_OVER, innerMostWidget);
    3390                 : 
    3391               0 :     InitDragEvent(event);
    3392                 : 
    3393               0 :     event.refPoint.x = retx;
    3394               0 :     event.refPoint.y = rety;
    3395               0 :     event.time = aTime;
    3396                 : 
    3397                 :     nsEventStatus status;
    3398               0 :     innerMostWidget->DispatchEvent(&event, status);
    3399                 : 
    3400                 :     // we're done with the drag motion event.  notify the drag service.
    3401               0 :     dragSessionGTK->TargetEndDragMotion(aWidget, aDragContext, aTime);
    3402                 : 
    3403                 :     // and unset our context
    3404               0 :     dragSessionGTK->TargetSetLastContext(0, 0, 0);
    3405                 : 
    3406               0 :     return TRUE;
    3407                 : }
    3408                 : 
    3409                 : void
    3410               0 : nsWindow::OnDragLeaveEvent(GtkWidget *aWidget,
    3411                 :                            GdkDragContext *aDragContext,
    3412                 :                            guint aTime,
    3413                 :                            gpointer aData)
    3414                 : {
    3415                 :     // XXX Do we want to pass this on only if the event's subwindow is null?
    3416                 : 
    3417               0 :     LOGDRAG(("nsWindow::OnDragLeaveSignal(%p)\n", (void*)this));
    3418                 : 
    3419               0 :     sIsDraggingOutOf = true;
    3420                 : 
    3421               0 :     if (mDragLeaveTimer) {
    3422               0 :         return;
    3423                 :     }
    3424                 : 
    3425                 :     // create a fast timer - we're delaying the drag leave until the
    3426                 :     // next mainloop in hopes that we might be able to get a drag drop
    3427                 :     // signal
    3428               0 :     mDragLeaveTimer = do_CreateInstance("@mozilla.org/timer;1");
    3429               0 :     NS_ASSERTION(mDragLeaveTimer, "Failed to create drag leave timer!");
    3430                 :     // fire this baby asafp, but not too quickly... see bug 216800 ;-)
    3431               0 :     mDragLeaveTimer->InitWithFuncCallback(DragLeaveTimerCallback,
    3432                 :                                           (void *)this,
    3433               0 :                                           20, nsITimer::TYPE_ONE_SHOT);
    3434                 : }
    3435                 : 
    3436                 : gboolean
    3437               0 : nsWindow::OnDragDropEvent(GtkWidget *aWidget,
    3438                 :                           GdkDragContext *aDragContext,
    3439                 :                           gint aX,
    3440                 :                           gint aY,
    3441                 :                           guint aTime,
    3442                 :                           gpointer aData)
    3443                 : 
    3444                 : {
    3445               0 :     LOGDRAG(("nsWindow::OnDragDropSignal\n"));
    3446                 : 
    3447                 :     // get our drag context
    3448               0 :     nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
    3449               0 :     nsCOMPtr<nsIDragSessionGTK> dragSessionGTK = do_QueryInterface(dragService);
    3450                 : 
    3451               0 :     nscoord retx = 0;
    3452               0 :     nscoord rety = 0;
    3453                 : 
    3454                 :     GdkWindow *innerWindow = get_inner_gdk_window(gtk_widget_get_window(aWidget), aX, aY,
    3455               0 :                                                   &retx, &rety);
    3456               0 :     nsRefPtr<nsWindow> innerMostWidget = get_window_for_gdk_window(innerWindow);
    3457                 : 
    3458               0 :     if (!innerMostWidget)
    3459               0 :         innerMostWidget = this;
    3460                 : 
    3461                 :     // set this now before any of the drag enter or leave events happen
    3462               0 :     dragSessionGTK->TargetSetLastContext(aWidget, aDragContext, aTime);
    3463                 : 
    3464                 :     // clear any drag leave timer that might be pending so that it
    3465                 :     // doesn't get processed when we actually go out to get data.
    3466               0 :     if (mDragLeaveTimer) {
    3467               0 :         mDragLeaveTimer->Cancel();
    3468               0 :         mDragLeaveTimer = nsnull;
    3469                 :     }
    3470                 : 
    3471               0 :     CheckNeedDragLeaveEnter(innerMostWidget, dragService, aDragContext, retx, rety);
    3472                 : 
    3473                 :     // What we do here is dispatch a new drag motion event to
    3474                 :     // re-validate the drag target and then we do the drop.  The events
    3475                 :     // look the same except for the type.
    3476                 : 
    3477               0 :     nsDragEvent event(true, NS_DRAGDROP_OVER, innerMostWidget);
    3478                 : 
    3479               0 :     InitDragEvent(event);
    3480                 : 
    3481               0 :     event.refPoint.x = retx;
    3482               0 :     event.refPoint.y = rety;
    3483               0 :     event.time = aTime;
    3484                 : 
    3485                 :     nsEventStatus status;
    3486               0 :     innerMostWidget->DispatchEvent(&event, status);
    3487                 : 
    3488                 :     // We need to check innerMostWidget->mIsDestroyed here because the nsRefPtr
    3489                 :     // only protects innerMostWidget from being deleted, it does NOT protect
    3490                 :     // against nsView::~nsView() calling Destroy() on it, bug 378670.
    3491               0 :     if (!innerMostWidget->mIsDestroyed) {
    3492               0 :         nsDragEvent event(true, NS_DRAGDROP_DROP, innerMostWidget);
    3493               0 :         event.refPoint.x = retx;
    3494               0 :         event.refPoint.y = rety;
    3495                 : 
    3496               0 :         nsEventStatus status = nsEventStatus_eIgnore;
    3497               0 :         innerMostWidget->DispatchEvent(&event, status);
    3498                 :     }
    3499                 : 
    3500                 :     // before we unset the context we need to do a drop_finish
    3501                 : 
    3502               0 :     gdk_drop_finish(aDragContext, TRUE, aTime);
    3503                 : 
    3504                 :     // after a drop takes place we need to make sure that the drag
    3505                 :     // service doesn't think that it still has a context.  if the other
    3506                 :     // way ( besides the drop ) to end a drag event is during the leave
    3507                 :     // event and and that case is handled in that handler.
    3508               0 :     dragSessionGTK->TargetSetLastContext(0, 0, 0);
    3509                 : 
    3510                 :     // clear the sLastDragMotion window
    3511               0 :     sLastDragMotionWindow = 0;
    3512                 : 
    3513                 :     // Make sure to end the drag session. If this drag started in a
    3514                 :     // different app, we won't get a drag_end signal to end it from.
    3515                 :     gint x, y;
    3516               0 :     GdkDisplay* display = gdk_display_get_default();
    3517               0 :     if (display) {
    3518                 :       // get the current cursor position
    3519               0 :       gdk_display_get_pointer(display, NULL, &x, &y, NULL);
    3520               0 :       ((nsDragService *)dragService.get())->SetDragEndPoint(nsIntPoint(x, y));
    3521                 :     }
    3522               0 :     dragService->EndDragSession(true);
    3523                 : 
    3524               0 :     return TRUE;
    3525                 : }
    3526                 : 
    3527                 : void
    3528               0 : nsWindow::OnDragDataReceivedEvent(GtkWidget *aWidget,
    3529                 :                                   GdkDragContext *aDragContext,
    3530                 :                                   gint aX,
    3531                 :                                   gint aY,
    3532                 :                                   GtkSelectionData  *aSelectionData,
    3533                 :                                   guint aInfo,
    3534                 :                                   guint aTime,
    3535                 :                                   gpointer aData)
    3536                 : {
    3537               0 :     LOGDRAG(("nsWindow::OnDragDataReceived(%p)\n", (void*)this));
    3538                 : 
    3539                 :     // get our drag context
    3540               0 :     nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
    3541               0 :     nsCOMPtr<nsIDragSessionGTK> dragSessionGTK = do_QueryInterface(dragService);
    3542                 : 
    3543               0 :     dragSessionGTK->TargetDataReceived(aWidget, aDragContext, aX, aY,
    3544               0 :                                        aSelectionData, aInfo, aTime);
    3545               0 : }
    3546                 : 
    3547                 : void
    3548               0 : nsWindow::OnDragLeave(void)
    3549                 : {
    3550               0 :     LOGDRAG(("nsWindow::OnDragLeave(%p)\n", (void*)this));
    3551                 : 
    3552               0 :     nsDragEvent event(true, NS_DRAGDROP_EXIT, this);
    3553                 : 
    3554                 :     nsEventStatus status;
    3555               0 :     DispatchEvent(&event, status);
    3556                 : 
    3557               0 :     nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
    3558                 : 
    3559               0 :     if (dragService) {
    3560               0 :         nsCOMPtr<nsIDragSession> currentDragSession;
    3561               0 :         dragService->GetCurrentSession(getter_AddRefs(currentDragSession));
    3562                 : 
    3563               0 :         if (currentDragSession) {
    3564               0 :             nsCOMPtr<nsIDOMNode> sourceNode;
    3565               0 :             currentDragSession->GetSourceNode(getter_AddRefs(sourceNode));
    3566                 : 
    3567               0 :             if (!sourceNode) {
    3568                 :                 // We're leaving a window while doing a drag that was
    3569                 :                 // initiated in a different app. End the drag session,
    3570                 :                 // since we're done with it for now (until the user
    3571                 :                 // drags back into mozilla).
    3572               0 :                 dragService->EndDragSession(false);
    3573                 :             }
    3574                 :         }
    3575                 :     }
    3576               0 : }
    3577                 : 
    3578                 : void
    3579               0 : nsWindow::OnDragEnter(nscoord aX, nscoord aY)
    3580                 : {
    3581                 :     // XXX Do we want to pass this on only if the event's subwindow is null?
    3582                 : 
    3583               0 :     LOGDRAG(("nsWindow::OnDragEnter(%p)\n", (void*)this));
    3584                 : 
    3585               0 :     nsDragEvent event(true, NS_DRAGDROP_ENTER, this);
    3586                 : 
    3587               0 :     event.refPoint.x = aX;
    3588               0 :     event.refPoint.y = aY;
    3589                 : 
    3590                 :     nsEventStatus status;
    3591               0 :     DispatchEvent(&event, status);
    3592               0 : }
    3593                 : 
    3594                 : static void
    3595               0 : GetBrandName(nsXPIDLString& brandName)
    3596                 : {
    3597                 :     nsCOMPtr<nsIStringBundleService> bundleService =
    3598               0 :         do_GetService(NS_STRINGBUNDLE_CONTRACTID);
    3599                 : 
    3600               0 :     nsCOMPtr<nsIStringBundle> bundle;
    3601               0 :     if (bundleService)
    3602               0 :         bundleService->CreateBundle(
    3603                 :             "chrome://branding/locale/brand.properties",
    3604               0 :             getter_AddRefs(bundle));
    3605                 : 
    3606               0 :     if (bundle)
    3607               0 :         bundle->GetStringFromName(
    3608               0 :             NS_LITERAL_STRING("brandShortName").get(),
    3609               0 :             getter_Copies(brandName));
    3610                 : 
    3611               0 :     if (brandName.IsEmpty())
    3612               0 :         brandName.Assign(NS_LITERAL_STRING("Mozilla"));
    3613               0 : }
    3614                 : 
    3615                 : static GdkWindow *
    3616               0 : CreateGdkWindow(GdkWindow *parent, GtkWidget *widget)
    3617                 : {
    3618                 :     GdkWindowAttr attributes;
    3619               0 :     gint          attributes_mask = GDK_WA_VISUAL;
    3620                 : 
    3621                 :     attributes.event_mask = (GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK |
    3622                 :                              GDK_VISIBILITY_NOTIFY_MASK |
    3623                 :                              GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
    3624                 :                              GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
    3625                 : #ifdef HAVE_GTK_MOTION_HINTS
    3626                 :                              GDK_POINTER_MOTION_HINT_MASK |
    3627                 : #endif
    3628               0 :                              GDK_POINTER_MOTION_MASK);
    3629                 : 
    3630               0 :     attributes.width = 1;
    3631               0 :     attributes.height = 1;
    3632               0 :     attributes.wclass = GDK_INPUT_OUTPUT;
    3633               0 :     attributes.visual = gtk_widget_get_visual(widget);
    3634               0 :     attributes.window_type = GDK_WINDOW_CHILD;
    3635                 : 
    3636                 : #if defined(MOZ_WIDGET_GTK2)
    3637               0 :     attributes_mask |= GDK_WA_COLORMAP;
    3638               0 :     attributes.colormap = gtk_widget_get_colormap(widget);
    3639                 : #endif
    3640                 : 
    3641               0 :     GdkWindow *window = gdk_window_new(parent, &attributes, attributes_mask);
    3642               0 :     gdk_window_set_user_data(window, widget);
    3643                 : 
    3644                 : // GTK3 TODO?
    3645                 : #if defined(MOZ_WIDGET_GTK2)
    3646                 :     /* set the default pixmap to None so that you don't end up with the
    3647                 :        gtk default which is BlackPixel. */
    3648               0 :     gdk_window_set_back_pixmap(window, NULL, FALSE);
    3649                 : #endif
    3650                 : 
    3651               0 :     return window;
    3652                 : }
    3653                 : 
    3654                 : nsresult
    3655               0 : nsWindow::Create(nsIWidget        *aParent,
    3656                 :                  nsNativeWidget    aNativeParent,
    3657                 :                  const nsIntRect  &aRect,
    3658                 :                  EVENT_CALLBACK    aHandleEventFunction,
    3659                 :                  nsDeviceContext *aContext,
    3660                 :                  nsWidgetInitData *aInitData)
    3661                 : {
    3662                 :     // only set the base parent if we're going to be a dialog or a
    3663                 :     // toplevel
    3664                 :     nsIWidget *baseParent = aInitData &&
    3665                 :         (aInitData->mWindowType == eWindowType_dialog ||
    3666                 :          aInitData->mWindowType == eWindowType_toplevel ||
    3667                 :          aInitData->mWindowType == eWindowType_invisible) ?
    3668               0 :         nsnull : aParent;
    3669                 : 
    3670               0 :     NS_ASSERTION(!mWindowGroup, "already have window group (leaking it)");
    3671                 : 
    3672                 : #ifdef ACCESSIBILITY
    3673                 :     // Send a DBus message to check whether a11y is enabled
    3674               0 :     a11y::PreInit();
    3675                 : #endif
    3676                 : 
    3677                 :     // Ensure that the toolkit is created.
    3678               0 :     nsGTKToolkit::GetToolkit();
    3679                 : 
    3680                 :     // initialize all the common bits of this class
    3681               0 :     BaseCreate(baseParent, aRect, aHandleEventFunction, aContext, aInitData);
    3682                 : 
    3683                 :     // Do we need to listen for resizes?
    3684               0 :     bool listenForResizes = false;;
    3685               0 :     if (aNativeParent || (aInitData && aInitData->mListenForResizes))
    3686               0 :         listenForResizes = true;
    3687                 : 
    3688                 :     // and do our common creation
    3689               0 :     CommonCreate(aParent, listenForResizes);
    3690                 : 
    3691                 :     // save our bounds
    3692               0 :     mBounds = aRect;
    3693                 : 
    3694                 :     // figure out our parent window
    3695               0 :     GtkWidget      *parentMozContainer = nsnull;
    3696               0 :     GtkContainer   *parentGtkContainer = nsnull;
    3697               0 :     GdkWindow      *parentGdkWindow = nsnull;
    3698               0 :     GtkWindow      *topLevelParent = nsnull;
    3699                 : 
    3700               0 :     if (aParent)
    3701               0 :         parentGdkWindow = GDK_WINDOW(aParent->GetNativeData(NS_NATIVE_WINDOW));
    3702               0 :     else if (aNativeParent && GDK_IS_WINDOW(aNativeParent))
    3703               0 :         parentGdkWindow = GDK_WINDOW(aNativeParent);
    3704               0 :     else if (aNativeParent && GTK_IS_CONTAINER(aNativeParent))
    3705               0 :         parentGtkContainer = GTK_CONTAINER(aNativeParent);
    3706                 : 
    3707               0 :     if (parentGdkWindow) {
    3708                 :         // get the widget for the window - it should be a moz container
    3709               0 :         parentMozContainer = get_gtk_widget_for_gdk_window(parentGdkWindow);
    3710                 : 
    3711               0 :         if (!IS_MOZ_CONTAINER(parentMozContainer))
    3712               0 :             return NS_ERROR_FAILURE;
    3713                 : 
    3714                 :         // get the toplevel window just in case someone needs to use it
    3715                 :         // for setting transients or whatever.
    3716                 :         topLevelParent =
    3717               0 :             GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(parentMozContainer)));
    3718                 :     }
    3719                 : 
    3720                 :     // ok, create our windows
    3721               0 :     switch (mWindowType) {
    3722                 :     case eWindowType_dialog:
    3723                 :     case eWindowType_popup:
    3724                 :     case eWindowType_toplevel:
    3725                 :     case eWindowType_invisible: {
    3726               0 :         mIsTopLevel = true;
    3727                 : 
    3728                 :         // We only move a general managed toplevel window if someone has
    3729                 :         // actually placed the window somewhere.  If no placement has taken
    3730                 :         // place, we just let the window manager Do The Right Thing.
    3731                 :         //
    3732                 :         // Indicate that if we're shown, we at least need to have our size set.
    3733                 :         // If we get explicitly moved, the position will also be set.
    3734               0 :         mNeedsResize = true;
    3735                 : 
    3736               0 :         nsXPIDLString brandName;
    3737               0 :         GetBrandName(brandName);
    3738               0 :         NS_ConvertUTF16toUTF8 cBrand(brandName);
    3739                 : 
    3740               0 :         if (mWindowType == eWindowType_dialog) {
    3741               0 :             mShell = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    3742               0 :             SetDefaultIcon();
    3743               0 :             gtk_window_set_wmclass(GTK_WINDOW(mShell), "Dialog", cBrand.get());
    3744               0 :             gtk_window_set_type_hint(GTK_WINDOW(mShell),
    3745               0 :                                      GDK_WINDOW_TYPE_HINT_DIALOG);
    3746               0 :             gtk_window_set_transient_for(GTK_WINDOW(mShell),
    3747               0 :                                          topLevelParent);
    3748               0 :             mTransientParent = topLevelParent;
    3749                 :             // add ourselves to the parent window's window group
    3750               0 :             if (!topLevelParent) {
    3751               0 :                 gtk_widget_realize(mShell);
    3752               0 :                 GdkWindow* dialoglead = gtk_widget_get_window(mShell);
    3753               0 :                 gdk_window_set_group(dialoglead, dialoglead);
    3754                 :             }
    3755               0 :             if (parentGdkWindow) {
    3756                 :                 nsWindow *parentnsWindow =
    3757               0 :                     get_window_for_gdk_window(parentGdkWindow);
    3758               0 :                 NS_ASSERTION(parentnsWindow,
    3759                 :                              "no nsWindow for parentGdkWindow!");
    3760               0 :                 if (parentnsWindow && parentnsWindow->mWindowGroup) {
    3761                 :                     gtk_window_group_add_window(parentnsWindow->mWindowGroup,
    3762               0 :                                                 GTK_WINDOW(mShell));
    3763                 :                     // store this in case any children are created
    3764               0 :                     mWindowGroup = parentnsWindow->mWindowGroup;
    3765               0 :                     g_object_ref(mWindowGroup);
    3766               0 :                     LOG(("adding window %p to group %p\n",
    3767                 :                          (void *)mShell, (void *)mWindowGroup));
    3768                 :                 }
    3769                 :             }
    3770                 :         }
    3771               0 :         else if (mWindowType == eWindowType_popup) {
    3772                 :             // With popup windows, we want to control their position, so don't
    3773                 :             // wait for the window manager to place them (which wouldn't
    3774                 :             // happen with override-redirect windows anyway).
    3775               0 :             mNeedsMove = true;
    3776                 : 
    3777                 :             // Popups that are not noautohide are only temporary. The are used
    3778                 :             // for menus and the like and disappear when another window is used.
    3779               0 :             if (!aInitData->mNoAutoHide) {
    3780                 :                 // For most popups, use the standard GtkWindowType
    3781                 :                 // GTK_WINDOW_POPUP, which will use a Window with the
    3782                 :                 // override-redirect attribute (for temporary windows).
    3783               0 :                 mShell = gtk_window_new(GTK_WINDOW_POPUP);
    3784               0 :                 gtk_window_set_wmclass(GTK_WINDOW(mShell), "Popup", cBrand.get());
    3785                 :             } else {
    3786                 :                 // For long-lived windows, their stacking order is managed by
    3787                 :                 // the window manager, as indicated by GTK_WINDOW_TOPLEVEL ...
    3788               0 :                 mShell = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    3789               0 :                 gtk_window_set_wmclass(GTK_WINDOW(mShell), "Popup", cBrand.get());
    3790                 :                 // ... but the window manager does not decorate this window,
    3791                 :                 // nor provide a separate taskbar icon.
    3792               0 :                 if (mBorderStyle == eBorderStyle_default) {
    3793               0 :                   gtk_window_set_decorated(GTK_WINDOW(mShell), FALSE);
    3794                 :                 }
    3795                 :                 else {
    3796               0 :                   bool decorate = mBorderStyle & eBorderStyle_title;
    3797               0 :                   gtk_window_set_decorated(GTK_WINDOW(mShell), decorate);
    3798               0 :                   if (decorate) {
    3799               0 :                     gtk_window_set_deletable(GTK_WINDOW(mShell), mBorderStyle & eBorderStyle_close);
    3800                 :                   }
    3801                 :                 }
    3802               0 :                 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(mShell), TRUE);
    3803                 :                 // Element focus is managed by the parent window so the
    3804                 :                 // WM_HINTS input field is set to False to tell the window
    3805                 :                 // manager not to set input focus to this window ...
    3806               0 :                 gtk_window_set_accept_focus(GTK_WINDOW(mShell), FALSE);
    3807                 : #ifdef MOZ_X11
    3808                 :                 // ... but when the window manager offers focus through
    3809                 :                 // WM_TAKE_FOCUS, focus is requested on the parent window.
    3810               0 :                 gtk_widget_realize(mShell);
    3811                 :                 gdk_window_add_filter(gtk_widget_get_window(mShell),
    3812               0 :                                       popup_take_focus_filter, NULL); 
    3813                 : #endif
    3814                 :             }
    3815                 : 
    3816                 :             GdkWindowTypeHint gtkTypeHint;
    3817               0 :             if (aInitData->mIsDragPopup) {
    3818               0 :                 gtkTypeHint = GDK_WINDOW_TYPE_HINT_DND;
    3819                 :             }
    3820                 :             else {
    3821               0 :                 switch (aInitData->mPopupHint) {
    3822                 :                     case ePopupTypeMenu:
    3823               0 :                         gtkTypeHint = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
    3824               0 :                         break;
    3825                 :                     case ePopupTypeTooltip:
    3826               0 :                         gtkTypeHint = GDK_WINDOW_TYPE_HINT_TOOLTIP;
    3827               0 :                         break;
    3828                 :                     default:
    3829               0 :                         gtkTypeHint = GDK_WINDOW_TYPE_HINT_UTILITY;
    3830               0 :                         break;
    3831                 :                 }
    3832                 :             }
    3833               0 :             gtk_window_set_type_hint(GTK_WINDOW(mShell), gtkTypeHint);
    3834                 : 
    3835               0 :             if (topLevelParent) {
    3836               0 :                 gtk_window_set_transient_for(GTK_WINDOW(mShell),
    3837               0 :                                             topLevelParent);
    3838               0 :                 mTransientParent = topLevelParent;
    3839                 : 
    3840               0 :                 GtkWindowGroup *groupParent = gtk_window_get_group(topLevelParent);
    3841               0 :                 if (groupParent) {
    3842               0 :                     gtk_window_group_add_window(groupParent, GTK_WINDOW(mShell));
    3843               0 :                     mWindowGroup = groupParent;
    3844               0 :                     g_object_ref(mWindowGroup);
    3845                 :                 }
    3846                 :             }
    3847                 :         }
    3848                 :         else { // must be eWindowType_toplevel
    3849               0 :             mShell = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    3850               0 :             SetDefaultIcon();
    3851               0 :             gtk_window_set_wmclass(GTK_WINDOW(mShell), "Toplevel", cBrand.get());
    3852                 : 
    3853                 :             // each toplevel window gets its own window group
    3854               0 :             mWindowGroup = gtk_window_group_new();
    3855                 : 
    3856                 :             // and add ourselves to the window group
    3857               0 :             LOG(("adding window %p to new group %p\n",
    3858                 :                  (void *)mShell, (void *)mWindowGroup));
    3859               0 :             gtk_window_group_add_window(mWindowGroup, GTK_WINDOW(mShell));
    3860                 :         }
    3861                 : 
    3862                 :         // create our container
    3863               0 :         GtkWidget *container = moz_container_new();
    3864               0 :         mContainer = MOZ_CONTAINER(container);
    3865               0 :         gtk_container_add(GTK_CONTAINER(mShell), container);
    3866               0 :         gtk_widget_realize(container);
    3867                 : 
    3868                 : #if defined(MOZ_WIDGET_GTK2)
    3869                 :         // Don't let GTK mess with the shapes of our GdkWindows
    3870               0 :         GTK_PRIVATE_SET_FLAG(container, GTK_HAS_SHAPE_MASK);
    3871                 : #endif
    3872                 : 
    3873                 :         // make sure this is the focus widget in the container
    3874               0 :         gtk_window_set_focus(GTK_WINDOW(mShell), container);
    3875                 : 
    3876                 :         // the drawing window
    3877               0 :         mGdkWindow = gtk_widget_get_window(container);
    3878                 : 
    3879               0 :         if (mWindowType == eWindowType_popup) {
    3880                 :             // gdk does not automatically set the cursor for "temporary"
    3881                 :             // windows, which are what gtk uses for popups.
    3882                 : 
    3883               0 :             mCursor = eCursor_wait; // force SetCursor to actually set the
    3884                 :                                     // cursor, even though our internal state
    3885                 :                                     // indicates that we already have the
    3886                 :                                     // standard cursor.
    3887               0 :             SetCursor(eCursor_standard);
    3888                 : 
    3889               0 :             if (aInitData->mNoAutoHide) {
    3890               0 :                 gint wmd = ConvertBorderStyles(mBorderStyle);
    3891               0 :                 if (wmd != -1)
    3892               0 :                   gdk_window_set_decorations(gtk_widget_get_window(mShell), (GdkWMDecoration) wmd);
    3893                 :             }
    3894                 :         }
    3895                 :     }
    3896               0 :         break;
    3897                 :     case eWindowType_plugin:
    3898                 :     case eWindowType_child: {
    3899               0 :         if (parentMozContainer) {
    3900               0 :             mGdkWindow = CreateGdkWindow(parentGdkWindow, parentMozContainer);
    3901                 :             nsWindow *parentnsWindow =
    3902               0 :                 get_window_for_gdk_window(parentGdkWindow);
    3903               0 :             if (parentnsWindow)
    3904               0 :                 mHasMappedToplevel = parentnsWindow->mHasMappedToplevel;
    3905                 :         }
    3906               0 :         else if (parentGtkContainer) {
    3907               0 :             GtkWidget *container = moz_container_new();
    3908               0 :             mContainer = MOZ_CONTAINER(container);
    3909               0 :             gtk_container_add(parentGtkContainer, container);
    3910               0 :             gtk_widget_realize(container);
    3911                 : 
    3912                 : #if defined(MOZ_WIDGET_GTK2)
    3913                 :             // Don't let GTK mess with the shapes of our GdkWindows
    3914               0 :             GTK_PRIVATE_SET_FLAG(container, GTK_HAS_SHAPE_MASK);
    3915                 : #endif
    3916                 : 
    3917               0 :             mGdkWindow = gtk_widget_get_window(container);
    3918                 :         }
    3919                 :         else {
    3920               0 :             NS_WARNING("Warning: tried to create a new child widget with no parent!");
    3921               0 :             return NS_ERROR_FAILURE;
    3922                 :         }
    3923                 :     }
    3924               0 :         break;
    3925                 :     default:
    3926               0 :         break;
    3927                 :     }
    3928                 :     // Disable the double buffer because it will make the caret crazy
    3929                 :     // For bug#153805 (Gtk2 double buffer makes carets misbehave)
    3930                 :     // DirectFB's expose code depends on gtk double buffering
    3931                 :     // XXX - I think this bug is probably dead, we can just use gtk's
    3932                 :     // double-buffering everywhere
    3933                 : #ifdef MOZ_X11
    3934               0 :     if (mContainer)
    3935               0 :         gtk_widget_set_double_buffered (GTK_WIDGET(mContainer),FALSE);
    3936                 : #endif
    3937                 : 
    3938                 :     // label the drawing window with this object so we can find our way home
    3939               0 :     g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", this);
    3940                 : 
    3941               0 :     if (mContainer)
    3942               0 :         g_object_set_data(G_OBJECT(mContainer), "nsWindow", this);
    3943                 : 
    3944               0 :     if (mShell)
    3945               0 :         g_object_set_data(G_OBJECT(mShell), "nsWindow", this);
    3946                 : 
    3947                 :     // attach listeners for events
    3948               0 :     if (mShell) {
    3949               0 :         g_signal_connect(mShell, "configure_event",
    3950               0 :                          G_CALLBACK(configure_event_cb), NULL);
    3951               0 :         g_signal_connect(mShell, "delete_event",
    3952               0 :                          G_CALLBACK(delete_event_cb), NULL);
    3953               0 :         g_signal_connect(mShell, "window_state_event",
    3954               0 :                          G_CALLBACK(window_state_event_cb), NULL);
    3955                 : 
    3956               0 :         GtkSettings* default_settings = gtk_settings_get_default();
    3957               0 :         g_signal_connect_after(default_settings,
    3958                 :                                "notify::gtk-theme-name",
    3959               0 :                                G_CALLBACK(theme_changed_cb), this);
    3960               0 :         g_signal_connect_after(default_settings,
    3961                 :                                "notify::gtk-font-name",
    3962               0 :                                G_CALLBACK(theme_changed_cb), this);
    3963                 : 
    3964                 : #ifdef MOZ_PLATFORM_MAEMO
    3965                 :         if (mWindowType == eWindowType_toplevel) {
    3966                 :             GdkWindow *gdkwin = gtk_widget_get_window(mShell);
    3967                 : 
    3968                 :             // Tell the Hildon desktop that we support being rotated
    3969                 :             gulong portrait_set = 1;
    3970                 :             GdkAtom support = gdk_atom_intern("_HILDON_PORTRAIT_MODE_SUPPORT", FALSE);
    3971                 :             gdk_property_change(gdkwin, support, gdk_x11_xatom_to_atom(XA_CARDINAL),
    3972                 :                                 32, GDK_PROP_MODE_REPLACE,
    3973                 :                                 (const guchar *) &portrait_set, 1);
    3974                 : 
    3975                 :             // Tell maemo-status-volume daemon to ungrab keys
    3976                 :             gulong volume_set = 1;
    3977                 :             GdkAtom keys = gdk_atom_intern("_HILDON_ZOOM_KEY_ATOM", FALSE);
    3978                 :             gdk_property_change(gdkwin, keys, gdk_x11_xatom_to_atom(XA_INTEGER),
    3979                 :                                 32, GDK_PROP_MODE_REPLACE, (const guchar *) &volume_set, 1);
    3980                 :         }
    3981                 : #endif
    3982                 :     }
    3983                 : 
    3984               0 :     if (mContainer) {
    3985               0 :         g_signal_connect(mContainer, "unrealize",
    3986               0 :                          G_CALLBACK(container_unrealize_cb), NULL);
    3987               0 :         g_signal_connect_after(mContainer, "size_allocate",
    3988               0 :                                G_CALLBACK(size_allocate_cb), NULL);
    3989                 : #if defined(MOZ_WIDGET_GTK2)
    3990               0 :         g_signal_connect(mContainer, "expose_event",
    3991               0 :                          G_CALLBACK(expose_event_cb), NULL);
    3992                 : #else
    3993                 :         g_signal_connect(G_OBJECT(mContainer), "draw",
    3994                 :                          G_CALLBACK(expose_event_cb), NULL);
    3995                 : #endif
    3996               0 :         g_signal_connect(mContainer, "enter_notify_event",
    3997               0 :                          G_CALLBACK(enter_notify_event_cb), NULL);
    3998               0 :         g_signal_connect(mContainer, "leave_notify_event",
    3999               0 :                          G_CALLBACK(leave_notify_event_cb), NULL);
    4000               0 :         g_signal_connect(mContainer, "motion_notify_event",
    4001               0 :                          G_CALLBACK(motion_notify_event_cb), NULL);
    4002               0 :         g_signal_connect(mContainer, "button_press_event",
    4003               0 :                          G_CALLBACK(button_press_event_cb), NULL);
    4004               0 :         g_signal_connect(mContainer, "button_release_event",
    4005               0 :                          G_CALLBACK(button_release_event_cb), NULL);
    4006               0 :         g_signal_connect(mContainer, "focus_in_event",
    4007               0 :                          G_CALLBACK(focus_in_event_cb), NULL);
    4008               0 :         g_signal_connect(mContainer, "focus_out_event",
    4009               0 :                          G_CALLBACK(focus_out_event_cb), NULL);
    4010               0 :         g_signal_connect(mContainer, "key_press_event",
    4011               0 :                          G_CALLBACK(key_press_event_cb), NULL);
    4012               0 :         g_signal_connect(mContainer, "key_release_event",
    4013               0 :                          G_CALLBACK(key_release_event_cb), NULL);
    4014               0 :         g_signal_connect(mContainer, "scroll_event",
    4015               0 :                          G_CALLBACK(scroll_event_cb), NULL);
    4016               0 :         g_signal_connect(mContainer, "visibility_notify_event",
    4017               0 :                          G_CALLBACK(visibility_notify_event_cb), NULL);
    4018               0 :         g_signal_connect(mContainer, "hierarchy_changed",
    4019               0 :                          G_CALLBACK(hierarchy_changed_cb), NULL);
    4020                 :         // Initialize mHasMappedToplevel.
    4021               0 :         hierarchy_changed_cb(GTK_WIDGET(mContainer), NULL);
    4022                 : 
    4023                 :         gtk_drag_dest_set((GtkWidget *)mContainer,
    4024                 :                           (GtkDestDefaults)0,
    4025                 :                           NULL,
    4026                 :                           0,
    4027               0 :                           (GdkDragAction)0);
    4028                 : 
    4029               0 :         g_signal_connect(mContainer, "drag_motion",
    4030               0 :                          G_CALLBACK(drag_motion_event_cb), NULL);
    4031               0 :         g_signal_connect(mContainer, "drag_leave",
    4032               0 :                          G_CALLBACK(drag_leave_event_cb), NULL);
    4033               0 :         g_signal_connect(mContainer, "drag_drop",
    4034               0 :                          G_CALLBACK(drag_drop_event_cb), NULL);
    4035               0 :         g_signal_connect(mContainer, "drag_data_received",
    4036               0 :                          G_CALLBACK(drag_data_received_event_cb), NULL);
    4037                 : 
    4038                 :         // We create input contexts for all containers, except for
    4039                 :         // toplevel popup windows
    4040               0 :         if (mWindowType != eWindowType_popup) {
    4041               0 :             mIMModule = new nsGtkIMModule(this);
    4042                 :         }
    4043               0 :     } else if (!mIMModule) {
    4044               0 :         nsWindow *container = GetContainerWindow();
    4045               0 :         if (container) {
    4046               0 :             mIMModule = container->mIMModule;
    4047                 :         }
    4048                 :     }
    4049                 : 
    4050               0 :     LOG(("nsWindow [%p]\n", (void *)this));
    4051               0 :     if (mShell) {
    4052               0 :         LOG(("\tmShell %p %p %lx\n", (void *)mShell, (void *)gtk_widget_get_window(mShell),
    4053                 :              gdk_x11_window_get_xid(gtk_widget_get_window(mShell))));
    4054                 :     }
    4055                 : 
    4056               0 :     if (mContainer) {
    4057               0 :         LOG(("\tmContainer %p %p %lx\n", (void *)mContainer,
    4058                 :              (void *)gtk_widget_get_window(GTK_WIDGET(mContainer)),
    4059                 :              gdk_x11_window_get_xid(gtk_widget_get_window(GTK_WIDGET(mContainer)))));
    4060                 :     }
    4061               0 :     else if (mGdkWindow) {
    4062               0 :         LOG(("\tmGdkWindow %p %lx\n", (void *)mGdkWindow,
    4063                 :              gdk_x11_window_get_xid(mGdkWindow)));
    4064                 :     }
    4065                 : 
    4066                 :     // resize so that everything is set to the right dimensions
    4067               0 :     if (!mIsTopLevel)
    4068               0 :         Resize(mBounds.x, mBounds.y, mBounds.width, mBounds.height, false);
    4069                 : 
    4070               0 :     return NS_OK;
    4071                 : }
    4072                 : 
    4073                 : NS_IMETHODIMP
    4074               0 : nsWindow::SetWindowClass(const nsAString &xulWinType)
    4075                 : {
    4076               0 :   if (!mShell)
    4077               0 :     return NS_ERROR_FAILURE;
    4078                 : 
    4079                 : #ifdef MOZ_X11
    4080               0 :   nsXPIDLString brandName;
    4081               0 :   GetBrandName(brandName);
    4082                 : 
    4083               0 :   XClassHint *class_hint = XAllocClassHint();
    4084               0 :   if (!class_hint)
    4085               0 :     return NS_ERROR_OUT_OF_MEMORY;
    4086               0 :   const char *role = NULL;
    4087               0 :   class_hint->res_name = ToNewCString(xulWinType);
    4088               0 :   if (!class_hint->res_name) {
    4089               0 :     XFree(class_hint);
    4090               0 :     return NS_ERROR_OUT_OF_MEMORY;
    4091                 :   }
    4092               0 :   class_hint->res_class = ToNewCString(brandName);
    4093               0 :   if (!class_hint->res_class) {
    4094               0 :     nsMemory::Free(class_hint->res_name);
    4095               0 :     XFree(class_hint);
    4096               0 :     return NS_ERROR_OUT_OF_MEMORY;
    4097                 :   }
    4098                 : 
    4099                 :   // Parse res_name into a name and role. Characters other than
    4100                 :   // [A-Za-z0-9_-] are converted to '_'. Anything after the first
    4101                 :   // colon is assigned to role; if there's no colon, assign the
    4102                 :   // whole thing to both role and res_name.
    4103               0 :   for (char *c = class_hint->res_name; *c; c++) {
    4104               0 :     if (':' == *c) {
    4105               0 :       *c = 0;
    4106               0 :       role = c + 1;
    4107                 :     }
    4108               0 :     else if (!isascii(*c) || (!isalnum(*c) && ('_' != *c) && ('-' != *c)))
    4109               0 :       *c = '_';
    4110                 :   }
    4111               0 :   class_hint->res_name[0] = toupper(class_hint->res_name[0]);
    4112               0 :   if (!role) role = class_hint->res_name;
    4113                 : 
    4114               0 :   GdkWindow *shellWindow = gtk_widget_get_window(GTK_WIDGET(mShell));
    4115               0 :   gdk_window_set_role(shellWindow, role);
    4116                 :   // Can't use gtk_window_set_wmclass() for this; it prints
    4117                 :   // a warning & refuses to make the change.
    4118                 :   XSetClassHint(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()),
    4119                 :                 gdk_x11_window_get_xid(shellWindow),
    4120               0 :                 class_hint);
    4121               0 :   nsMemory::Free(class_hint->res_class);
    4122               0 :   nsMemory::Free(class_hint->res_name);
    4123               0 :   XFree(class_hint);
    4124                 : #else /* MOZ_X11 */
    4125                 : 
    4126                 :   char *res_name;
    4127                 : 
    4128                 :   res_name = ToNewCString(xulWinType);
    4129                 :   if (!res_name)
    4130                 :     return NS_ERROR_OUT_OF_MEMORY;
    4131                 : 
    4132                 :   printf("WARN: res_name = '%s'\n", res_name);
    4133                 : 
    4134                 : 
    4135                 :   const char *role = NULL;
    4136                 : 
    4137                 :   // Parse res_name into a name and role. Characters other than
    4138                 :   // [A-Za-z0-9_-] are converted to '_'. Anything after the first
    4139                 :   // colon is assigned to role; if there's no colon, assign the
    4140                 :   // whole thing to both role and res_name.
    4141                 :   for (char *c = res_name; *c; c++) {
    4142                 :     if (':' == *c) {
    4143                 :       *c = 0;
    4144                 :       role = c + 1;
    4145                 :     }
    4146                 :     else if (!isascii(*c) || (!isalnum(*c) && ('_' != *c) && ('-' != *c)))
    4147                 :       *c = '_';
    4148                 :   }
    4149                 :   res_name[0] = toupper(res_name[0]);
    4150                 :   if (!role) role = res_name;
    4151                 : 
    4152                 :   gdk_window_set_role(gtk_widget_get_window(GTK_WIDGET(mShell)), role);
    4153                 : 
    4154                 :   nsMemory::Free(res_name);
    4155                 : 
    4156                 : #endif /* MOZ_X11 */
    4157               0 :   return NS_OK;
    4158                 : }
    4159                 : 
    4160                 : void
    4161               0 : nsWindow::NativeResize(PRInt32 aWidth, PRInt32 aHeight, bool    aRepaint)
    4162                 : {
    4163               0 :     LOG(("nsWindow::NativeResize [%p] %d %d\n", (void *)this,
    4164                 :          aWidth, aHeight));
    4165                 : 
    4166               0 :     ResizeTransparencyBitmap(aWidth, aHeight);
    4167                 : 
    4168                 :     // clear our resize flag
    4169               0 :     mNeedsResize = false;
    4170                 : 
    4171               0 :     if (mIsTopLevel) {
    4172               0 :         gtk_window_resize(GTK_WINDOW(mShell), aWidth, aHeight);
    4173                 :     }
    4174               0 :     else if (mContainer) {
    4175               0 :         GtkWidget *widget = GTK_WIDGET(mContainer);
    4176                 :         GtkAllocation allocation, prev_allocation;
    4177               0 :         gtk_widget_get_allocation(widget, &prev_allocation);
    4178               0 :         allocation.x = prev_allocation.x;
    4179               0 :         allocation.y = prev_allocation.y;
    4180               0 :         allocation.width = aWidth;
    4181               0 :         allocation.height = aHeight;
    4182               0 :         gtk_widget_size_allocate(widget, &allocation);
    4183                 :     }
    4184               0 :     else if (mGdkWindow) {
    4185               0 :         gdk_window_resize(mGdkWindow, aWidth, aHeight);
    4186                 :     }
    4187               0 : }
    4188                 : 
    4189                 : void
    4190               0 : nsWindow::NativeResize(PRInt32 aX, PRInt32 aY,
    4191                 :                        PRInt32 aWidth, PRInt32 aHeight,
    4192                 :                        bool    aRepaint)
    4193                 : {
    4194               0 :     mNeedsResize = false;
    4195               0 :     mNeedsMove = false;
    4196                 : 
    4197               0 :     LOG(("nsWindow::NativeResize [%p] %d %d %d %d\n", (void *)this,
    4198                 :          aX, aY, aWidth, aHeight));
    4199                 : 
    4200               0 :     ResizeTransparencyBitmap(aWidth, aHeight);
    4201                 : 
    4202               0 :     if (mIsTopLevel) {
    4203                 :         // aX and aY give the position of the window manager frame top-left.
    4204               0 :         gtk_window_move(GTK_WINDOW(mShell), aX, aY);
    4205                 :         // This sets the client window size.
    4206               0 :         gtk_window_resize(GTK_WINDOW(mShell), aWidth, aHeight);
    4207                 :     }
    4208               0 :     else if (mContainer) {
    4209                 :         GtkAllocation allocation;
    4210               0 :         allocation.x = aX;
    4211               0 :         allocation.y = aY;
    4212               0 :         allocation.width = aWidth;
    4213               0 :         allocation.height = aHeight;
    4214               0 :         gtk_widget_size_allocate(GTK_WIDGET(mContainer), &allocation);
    4215                 :     }
    4216               0 :     else if (mGdkWindow) {
    4217               0 :         gdk_window_move_resize(mGdkWindow, aX, aY, aWidth, aHeight);
    4218                 :     }
    4219               0 : }
    4220                 : 
    4221                 : void
    4222               0 : nsWindow::NativeShow (bool    aAction)
    4223                 : {
    4224               0 :     if (aAction) {
    4225                 :         // GTK wants us to set the window mask before we show the window
    4226                 :         // for the first time, or setting the mask later won't work.
    4227                 :         // GTK also wants us to NOT set the window mask if we're not really
    4228                 :         // going to need it, because GTK won't let us unset the mask properly
    4229                 :         // later.
    4230                 :         // So, we delay setting the mask until the last moment: when the window
    4231                 :         // is shown.
    4232                 :         // XXX that may or may not be true for GTK+ 2.x
    4233               0 :         if (mTransparencyBitmap) {
    4234               0 :             ApplyTransparencyBitmap();
    4235                 :         }
    4236                 : 
    4237                 :         // unset our flag now that our window has been shown
    4238               0 :         mNeedsShow = false;
    4239                 : 
    4240               0 :         if (mIsTopLevel) {
    4241                 :             // Set up usertime/startupID metadata for the created window.
    4242               0 :             if (mWindowType != eWindowType_invisible) {
    4243               0 :                 SetUserTimeAndStartupIDForActivatedWindow(mShell);
    4244                 :             }
    4245                 : 
    4246               0 :             gtk_widget_show(GTK_WIDGET(mContainer));
    4247               0 :             gtk_widget_show(mShell);
    4248                 :         }
    4249               0 :         else if (mContainer) {
    4250               0 :             gtk_widget_show(GTK_WIDGET(mContainer));
    4251                 :         }
    4252               0 :         else if (mGdkWindow) {
    4253               0 :             gdk_window_show_unraised(mGdkWindow);
    4254                 :         }
    4255                 :     }
    4256                 :     else {
    4257               0 :         if (mIsTopLevel) {
    4258               0 :             gtk_widget_hide(GTK_WIDGET(mShell));
    4259               0 :             gtk_widget_hide(GTK_WIDGET(mContainer));
    4260                 :         }
    4261               0 :         else if (mContainer) {
    4262               0 :             gtk_widget_hide(GTK_WIDGET(mContainer));
    4263                 :         }
    4264               0 :         else if (mGdkWindow) {
    4265               0 :             gdk_window_hide(mGdkWindow);
    4266                 :         }
    4267                 :     }
    4268               0 : }
    4269                 : 
    4270                 : void
    4271               0 : nsWindow::SetHasMappedToplevel(bool aState)
    4272                 : {
    4273                 :     // Even when aState == mHasMappedToplevel (as when this method is called
    4274                 :     // from Show()), child windows need to have their state checked, so don't
    4275                 :     // return early.
    4276               0 :     bool oldState = mHasMappedToplevel;
    4277               0 :     mHasMappedToplevel = aState;
    4278                 : 
    4279                 :     // mHasMappedToplevel is not updated for children of windows that are
    4280                 :     // hidden; GDK knows not to send expose events for these windows.  The
    4281                 :     // state is recorded on the hidden window itself, but, for child trees of
    4282                 :     // hidden windows, their state essentially becomes disconnected from their
    4283                 :     // hidden parent.  When the hidden parent gets shown, the child trees are
    4284                 :     // reconnected, and the state of the window being shown can be easily
    4285                 :     // propagated.
    4286               0 :     if (!mIsShown || !mGdkWindow)
    4287               0 :         return;
    4288                 : 
    4289               0 :     if (aState && !oldState && !mIsFullyObscured) {
    4290                 :         // GDK_EXPOSE events have been ignored but the window is now visible,
    4291                 :         // so make sure GDK doesn't think that the window has already been
    4292                 :         // painted.
    4293               0 :         gdk_window_invalidate_rect(mGdkWindow, NULL, FALSE);
    4294                 : 
    4295                 :         // Check that a grab didn't fail due to the window not being
    4296                 :         // viewable.
    4297               0 :         EnsureGrabs();
    4298                 :     }
    4299                 : 
    4300               0 :     for (GList *children = gdk_window_peek_children(mGdkWindow);
    4301                 :          children;
    4302                 :          children = children->next) {
    4303               0 :         GdkWindow *gdkWin = GDK_WINDOW(children->data);
    4304               0 :         nsWindow *child = get_window_for_gdk_window(gdkWin);
    4305                 : 
    4306               0 :         if (child && child->mHasMappedToplevel != aState) {
    4307               0 :             child->SetHasMappedToplevel(aState);
    4308                 :         }
    4309                 :     }
    4310                 : }
    4311                 : 
    4312                 : nsIntSize
    4313               0 : nsWindow::GetSafeWindowSize(nsIntSize aSize)
    4314                 : {
    4315               0 :     nsIntSize result = aSize;
    4316               0 :     const PRInt32 kInt16Max = 32767;
    4317               0 :     if (result.width > kInt16Max) {
    4318               0 :         NS_WARNING("Clamping huge window width");
    4319               0 :         result.width = kInt16Max;
    4320                 :     }
    4321               0 :     if (result.height > kInt16Max) {
    4322               0 :         NS_WARNING("Clamping huge window height");
    4323               0 :         result.height = kInt16Max;
    4324                 :     }
    4325                 :     return result;
    4326                 : }
    4327                 : 
    4328                 : void
    4329               0 : nsWindow::EnsureGrabs(void)
    4330                 : {
    4331               0 :     if (mRetryPointerGrab)
    4332               0 :         GrabPointer(sRetryGrabTime);
    4333               0 : }
    4334                 : 
    4335                 : void
    4336               0 : nsWindow::SetTransparencyMode(nsTransparencyMode aMode)
    4337                 : {
    4338               0 :     if (!mShell) {
    4339                 :         // Pass the request to the toplevel window
    4340               0 :         GtkWidget *topWidget = nsnull;
    4341               0 :         GetToplevelWidget(&topWidget);
    4342               0 :         if (!topWidget)
    4343               0 :             return;
    4344                 : 
    4345               0 :         nsWindow *topWindow = get_window_for_gtk_widget(topWidget);
    4346               0 :         if (!topWindow)
    4347               0 :             return;
    4348                 : 
    4349               0 :         topWindow->SetTransparencyMode(aMode);
    4350               0 :         return;
    4351                 :     }
    4352               0 :     bool isTransparent = aMode == eTransparencyTransparent;
    4353                 : 
    4354               0 :     if (mIsTransparent == isTransparent)
    4355               0 :         return;
    4356                 : 
    4357               0 :     if (!isTransparent) {
    4358               0 :         if (mTransparencyBitmap) {
    4359               0 :             delete[] mTransparencyBitmap;
    4360               0 :             mTransparencyBitmap = nsnull;
    4361               0 :             mTransparencyBitmapWidth = 0;
    4362               0 :             mTransparencyBitmapHeight = 0;
    4363                 : #if defined(MOZ_WIDGET_GTK2)
    4364               0 :             gtk_widget_reset_shapes(mShell);
    4365                 : #else
    4366                 :             // GTK3 TODO
    4367                 : #endif
    4368                 :         }
    4369                 :     } // else the new default alpha values are "all 1", so we don't
    4370                 :     // need to change anything yet
    4371                 : 
    4372               0 :     mIsTransparent = isTransparent;
    4373                 : }
    4374                 : 
    4375                 : nsTransparencyMode
    4376               0 : nsWindow::GetTransparencyMode()
    4377                 : {
    4378               0 :     if (!mShell) {
    4379                 :         // Pass the request to the toplevel window
    4380               0 :         GtkWidget *topWidget = nsnull;
    4381               0 :         GetToplevelWidget(&topWidget);
    4382               0 :         if (!topWidget) {
    4383               0 :             return eTransparencyOpaque;
    4384                 :         }
    4385                 : 
    4386               0 :         nsWindow *topWindow = get_window_for_gtk_widget(topWidget);
    4387               0 :         if (!topWindow) {
    4388               0 :             return eTransparencyOpaque;
    4389                 :         }
    4390                 : 
    4391               0 :         return topWindow->GetTransparencyMode();
    4392                 :     }
    4393                 : 
    4394               0 :     return mIsTransparent ? eTransparencyTransparent : eTransparencyOpaque;
    4395                 : }
    4396                 : 
    4397                 : nsresult
    4398               0 : nsWindow::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
    4399                 : {
    4400               0 :     for (PRUint32 i = 0; i < aConfigurations.Length(); ++i) {
    4401               0 :         const Configuration& configuration = aConfigurations[i];
    4402               0 :         nsWindow* w = static_cast<nsWindow*>(configuration.mChild);
    4403               0 :         NS_ASSERTION(w->GetParent() == this,
    4404                 :                      "Configured widget is not a child");
    4405               0 :         w->SetWindowClipRegion(configuration.mClipRegion, true);
    4406               0 :         if (w->mBounds.Size() != configuration.mBounds.Size()) {
    4407                 :             w->Resize(configuration.mBounds.x, configuration.mBounds.y,
    4408                 :                       configuration.mBounds.width, configuration.mBounds.height,
    4409               0 :                       true);
    4410               0 :         } else if (w->mBounds.TopLeft() != configuration.mBounds.TopLeft()) {
    4411               0 :             w->Move(configuration.mBounds.x, configuration.mBounds.y);
    4412                 :         } 
    4413               0 :         w->SetWindowClipRegion(configuration.mClipRegion, false);
    4414                 :     }
    4415               0 :     return NS_OK;
    4416                 : }
    4417                 : 
    4418                 : static pixman_box32
    4419               0 : ToPixmanBox(const nsIntRect& aRect)
    4420                 : {
    4421                 :     pixman_box32_t result;
    4422               0 :     result.x1 = aRect.x;
    4423               0 :     result.y1 = aRect.y;
    4424               0 :     result.x2 = aRect.XMost();
    4425               0 :     result.y2 = aRect.YMost();
    4426                 :     return result;
    4427                 : }
    4428                 : 
    4429                 : static nsIntRect
    4430               0 : ToIntRect(const pixman_box32& aBox)
    4431                 : {
    4432               0 :     nsIntRect result;
    4433               0 :     result.x = aBox.x1;
    4434               0 :     result.y = aBox.y1;
    4435               0 :     result.width = aBox.x2 - aBox.x1;
    4436               0 :     result.height = aBox.y2 - aBox.y1;
    4437                 :     return result;
    4438                 : }
    4439                 : 
    4440                 : static void
    4441               0 : InitRegion(pixman_region32* aRegion,
    4442                 :            const nsTArray<nsIntRect>& aRects)
    4443                 : {
    4444               0 :     nsAutoTArray<pixman_box32,10> rects;
    4445               0 :     rects.SetCapacity(aRects.Length());
    4446               0 :     for (PRUint32 i = 0; i < aRects.Length (); ++i) {
    4447               0 :         if (!aRects[i].IsEmpty()) {
    4448               0 :             rects.AppendElement(ToPixmanBox(aRects[i]));
    4449                 :         }
    4450                 :     }
    4451                 : 
    4452                 :     pixman_region32_init_rects(aRegion,
    4453               0 :                                rects.Elements(), rects.Length());
    4454               0 : }
    4455                 : 
    4456                 : static void
    4457               0 : GetIntRects(pixman_region32& aRegion, nsTArray<nsIntRect>* aRects)
    4458                 : {
    4459                 :     int nRects;
    4460               0 :     pixman_box32* boxes = pixman_region32_rectangles(&aRegion, &nRects);
    4461               0 :     aRects->SetCapacity(aRects->Length() + nRects);
    4462               0 :     for (int i = 0; i < nRects; ++i) {
    4463               0 :         aRects->AppendElement(ToIntRect(boxes[i]));
    4464                 :     }
    4465               0 : }
    4466                 : 
    4467                 : void
    4468               0 : nsWindow::SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
    4469                 :                               bool aIntersectWithExisting)
    4470                 : {
    4471               0 :     const nsTArray<nsIntRect>* newRects = &aRects;
    4472                 : 
    4473               0 :     nsAutoTArray<nsIntRect,1> intersectRects;
    4474               0 :     if (aIntersectWithExisting) {
    4475               0 :         nsAutoTArray<nsIntRect,1> existingRects;
    4476               0 :         GetWindowClipRegion(&existingRects);
    4477                 : 
    4478               0 :         nsAutoRef<pixman_region32> existingRegion;
    4479               0 :         InitRegion(&existingRegion, existingRects);
    4480               0 :         nsAutoRef<pixman_region32> newRegion;
    4481               0 :         InitRegion(&newRegion, aRects);
    4482               0 :         nsAutoRef<pixman_region32> intersectRegion;
    4483               0 :         pixman_region32_init(&intersectRegion);
    4484                 :         pixman_region32_intersect(&intersectRegion,
    4485               0 :                                   &newRegion, &existingRegion);
    4486                 : 
    4487                 :         // If mClipRects is null we haven't set a clip rect yet, so we
    4488                 :         // need to set the clip even if it is equal.
    4489               0 :         if (mClipRects &&
    4490               0 :             pixman_region32_equal(&intersectRegion, &existingRegion)) {
    4491                 :             return;
    4492                 :         }
    4493                 : 
    4494               0 :         if (!pixman_region32_equal(&intersectRegion, &newRegion)) {
    4495               0 :             GetIntRects(intersectRegion, &intersectRects);
    4496               0 :             newRects = &intersectRects;
    4497                 :         }
    4498                 :     }
    4499                 : 
    4500               0 :     if (!StoreWindowClipRegion(*newRects))
    4501                 :         return;
    4502                 : 
    4503               0 :     if (!mGdkWindow)
    4504                 :         return;
    4505                 : 
    4506                 : #if defined(MOZ_WIDGET_GTK2)
    4507               0 :     GdkRegion *region = gdk_region_new(); // aborts on OOM
    4508               0 :     for (PRUint32 i = 0; i < newRects->Length(); ++i) {
    4509               0 :         const nsIntRect& r = newRects->ElementAt(i);
    4510               0 :         GdkRectangle rect = { r.x, r.y, r.width, r.height };
    4511               0 :         gdk_region_union_with_rect(region, &rect);
    4512                 :     }
    4513                 : 
    4514               0 :     gdk_window_shape_combine_region(mGdkWindow, region, 0, 0);
    4515               0 :     gdk_region_destroy(region);
    4516                 : #else
    4517                 :     cairo_region_t *region = cairo_region_create();
    4518                 :     for (PRUint32 i = 0; i < newRects->Length(); ++i) {
    4519                 :         const nsIntRect& r = newRects->ElementAt(i);
    4520                 :         cairo_rectangle_int_t rect = { r.x, r.y, r.width, r.height };
    4521                 :         cairo_region_union_rectangle(region, &rect);
    4522                 :     }
    4523                 : 
    4524                 :     gdk_window_shape_combine_region(mGdkWindow, region, 0, 0);
    4525                 :     cairo_region_destroy(region);
    4526                 : #endif
    4527                 :   
    4528                 :     return;
    4529                 : }
    4530                 : 
    4531                 : void
    4532               0 : nsWindow::ResizeTransparencyBitmap(PRInt32 aNewWidth, PRInt32 aNewHeight)
    4533                 : {
    4534               0 :     if (!mTransparencyBitmap)
    4535               0 :         return;
    4536                 : 
    4537               0 :     if (aNewWidth == mTransparencyBitmapWidth &&
    4538                 :         aNewHeight == mTransparencyBitmapHeight)
    4539               0 :         return;
    4540                 : 
    4541               0 :     PRInt32 newSize = GetBitmapStride(aNewWidth)*aNewHeight;
    4542               0 :     gchar* newBits = new gchar[newSize];
    4543               0 :     if (!newBits) {
    4544               0 :         delete[] mTransparencyBitmap;
    4545               0 :         mTransparencyBitmap = nsnull;
    4546               0 :         mTransparencyBitmapWidth = 0;
    4547               0 :         mTransparencyBitmapHeight = 0;
    4548               0 :         return;
    4549                 :     }
    4550                 :     // fill new mask with "opaque", first
    4551               0 :     memset(newBits, 255, newSize);
    4552                 : 
    4553                 :     // Now copy the intersection of the old and new areas into the new mask
    4554               0 :     PRInt32 copyWidth = NS_MIN(aNewWidth, mTransparencyBitmapWidth);
    4555               0 :     PRInt32 copyHeight = NS_MIN(aNewHeight, mTransparencyBitmapHeight);
    4556               0 :     PRInt32 oldRowBytes = GetBitmapStride(mTransparencyBitmapWidth);
    4557               0 :     PRInt32 newRowBytes = GetBitmapStride(aNewWidth);
    4558               0 :     PRInt32 copyBytes = GetBitmapStride(copyWidth);
    4559                 : 
    4560                 :     PRInt32 i;
    4561               0 :     gchar* fromPtr = mTransparencyBitmap;
    4562               0 :     gchar* toPtr = newBits;
    4563               0 :     for (i = 0; i < copyHeight; i++) {
    4564               0 :         memcpy(toPtr, fromPtr, copyBytes);
    4565               0 :         fromPtr += oldRowBytes;
    4566               0 :         toPtr += newRowBytes;
    4567                 :     }
    4568                 : 
    4569               0 :     delete[] mTransparencyBitmap;
    4570               0 :     mTransparencyBitmap = newBits;
    4571               0 :     mTransparencyBitmapWidth = aNewWidth;
    4572               0 :     mTransparencyBitmapHeight = aNewHeight;
    4573                 : }
    4574                 : 
    4575                 : static bool
    4576               0 : ChangedMaskBits(gchar* aMaskBits, PRInt32 aMaskWidth, PRInt32 aMaskHeight,
    4577                 :         const nsIntRect& aRect, PRUint8* aAlphas, PRInt32 aStride)
    4578                 : {
    4579               0 :     PRInt32 x, y, xMax = aRect.XMost(), yMax = aRect.YMost();
    4580               0 :     PRInt32 maskBytesPerRow = GetBitmapStride(aMaskWidth);
    4581               0 :     for (y = aRect.y; y < yMax; y++) {
    4582               0 :         gchar* maskBytes = aMaskBits + y*maskBytesPerRow;
    4583               0 :         PRUint8* alphas = aAlphas;
    4584               0 :         for (x = aRect.x; x < xMax; x++) {
    4585               0 :             bool newBit = *alphas > 0;
    4586               0 :             alphas++;
    4587                 : 
    4588               0 :             gchar maskByte = maskBytes[x >> 3];
    4589               0 :             bool maskBit = (maskByte & (1 << (x & 7))) != 0;
    4590                 : 
    4591               0 :             if (maskBit != newBit) {
    4592               0 :                 return true;
    4593                 :             }
    4594                 :         }
    4595               0 :         aAlphas += aStride;
    4596                 :     }
    4597                 : 
    4598               0 :     return false;
    4599                 : }
    4600                 : 
    4601                 : static
    4602               0 : void UpdateMaskBits(gchar* aMaskBits, PRInt32 aMaskWidth, PRInt32 aMaskHeight,
    4603                 :         const nsIntRect& aRect, PRUint8* aAlphas, PRInt32 aStride)
    4604                 : {
    4605               0 :     PRInt32 x, y, xMax = aRect.XMost(), yMax = aRect.YMost();
    4606               0 :     PRInt32 maskBytesPerRow = GetBitmapStride(aMaskWidth);
    4607               0 :     for (y = aRect.y; y < yMax; y++) {
    4608               0 :         gchar* maskBytes = aMaskBits + y*maskBytesPerRow;
    4609               0 :         PRUint8* alphas = aAlphas;
    4610               0 :         for (x = aRect.x; x < xMax; x++) {
    4611               0 :             bool newBit = *alphas > 0;
    4612               0 :             alphas++;
    4613                 : 
    4614               0 :             gchar mask = 1 << (x & 7);
    4615               0 :             gchar maskByte = maskBytes[x >> 3];
    4616                 :             // Note: '-newBit' turns 0 into 00...00 and 1 into 11...11
    4617               0 :             maskBytes[x >> 3] = (maskByte & ~mask) | (-newBit & mask);
    4618                 :         }
    4619               0 :         aAlphas += aStride;
    4620                 :     }
    4621               0 : }
    4622                 : 
    4623                 : void
    4624               0 : nsWindow::ApplyTransparencyBitmap()
    4625                 : {
    4626                 : #ifdef MOZ_X11
    4627                 :     // We use X11 calls where possible, because GDK handles expose events
    4628                 :     // for shaped windows in a way that's incompatible with us (Bug 635903).
    4629                 :     // It doesn't occur when the shapes are set through X.
    4630               0 :     GdkWindow *shellWindow = gtk_widget_get_window(mShell);
    4631               0 :     Display* xDisplay = GDK_WINDOW_XDISPLAY(shellWindow);
    4632               0 :     Window xDrawable = GDK_WINDOW_XID(shellWindow);
    4633                 :     Pixmap maskPixmap = XCreateBitmapFromData(xDisplay,
    4634                 :                                               xDrawable,
    4635                 :                                               mTransparencyBitmap,
    4636                 :                                               mTransparencyBitmapWidth,
    4637               0 :                                               mTransparencyBitmapHeight);
    4638                 :     XShapeCombineMask(xDisplay, xDrawable,
    4639                 :                       ShapeBounding, 0, 0,
    4640               0 :                       maskPixmap, ShapeSet);
    4641               0 :     XFreePixmap(xDisplay, maskPixmap);
    4642                 : #else
    4643                 : #if defined(MOZ_WIDGET_GTK2)
    4644                 :     gtk_widget_reset_shapes(mShell);
    4645                 :     GdkBitmap* maskBitmap = gdk_bitmap_create_from_data(gtk_widget_get_window(mShell),
    4646                 :             mTransparencyBitmap,
    4647                 :             mTransparencyBitmapWidth, mTransparencyBitmapHeight);
    4648                 :     if (!maskBitmap)
    4649                 :         return;
    4650                 : 
    4651                 :     gtk_widget_shape_combine_mask(mShell, maskBitmap, 0, 0);
    4652                 :     g_object_unref(maskBitmap);
    4653                 : #else
    4654                 :     cairo_surface_t *maskBitmap;
    4655                 :     maskBitmap = cairo_image_surface_create_for_data((unsigned char*)mTransparencyBitmap, 
    4656                 :                                                      CAIRO_FORMAT_A1, 
    4657                 :                                                      mTransparencyBitmapWidth, 
    4658                 :                                                      mTransparencyBitmapHeight,
    4659                 :                                                      GetBitmapStride(mTransparencyBitmapWidth));
    4660                 :     if (!maskBitmap)
    4661                 :         return;
    4662                 : 
    4663                 :     cairo_region_t * maskRegion = gdk_cairo_region_create_from_surface(maskBitmap);
    4664                 :     gtk_widget_shape_combine_region(mShell, maskRegion);
    4665                 :     cairo_region_destroy(maskRegion);
    4666                 :     cairo_surface_destroy(maskBitmap);
    4667                 : #endif // MOZ_WIDGET_GTK2
    4668                 : #endif // MOZ_X11
    4669               0 : }
    4670                 : 
    4671                 : nsresult
    4672               0 : nsWindow::UpdateTranslucentWindowAlphaInternal(const nsIntRect& aRect,
    4673                 :                                                PRUint8* aAlphas, PRInt32 aStride)
    4674                 : {
    4675               0 :     if (!mShell) {
    4676                 :         // Pass the request to the toplevel window
    4677               0 :         GtkWidget *topWidget = nsnull;
    4678               0 :         GetToplevelWidget(&topWidget);
    4679               0 :         if (!topWidget)
    4680               0 :             return NS_ERROR_FAILURE;
    4681                 : 
    4682               0 :         nsWindow *topWindow = get_window_for_gtk_widget(topWidget);
    4683               0 :         if (!topWindow)
    4684               0 :             return NS_ERROR_FAILURE;
    4685                 : 
    4686               0 :         return topWindow->UpdateTranslucentWindowAlphaInternal(aRect, aAlphas, aStride);
    4687                 :     }
    4688                 : 
    4689               0 :     NS_ASSERTION(mIsTransparent, "Window is not transparent");
    4690                 : 
    4691               0 :     if (mTransparencyBitmap == nsnull) {
    4692               0 :         PRInt32 size = GetBitmapStride(mBounds.width)*mBounds.height;
    4693               0 :         mTransparencyBitmap = new gchar[size];
    4694               0 :         if (mTransparencyBitmap == nsnull)
    4695               0 :             return NS_ERROR_FAILURE;
    4696               0 :         memset(mTransparencyBitmap, 255, size);
    4697               0 :         mTransparencyBitmapWidth = mBounds.width;
    4698               0 :         mTransparencyBitmapHeight = mBounds.height;
    4699                 :     }
    4700                 : 
    4701               0 :     NS_ASSERTION(aRect.x >= 0 && aRect.y >= 0
    4702                 :             && aRect.XMost() <= mBounds.width && aRect.YMost() <= mBounds.height,
    4703                 :             "Rect is out of window bounds");
    4704                 : 
    4705               0 :     if (!ChangedMaskBits(mTransparencyBitmap, mBounds.width, mBounds.height,
    4706               0 :                          aRect, aAlphas, aStride))
    4707                 :         // skip the expensive stuff if the mask bits haven't changed; hopefully
    4708                 :         // this is the common case
    4709               0 :         return NS_OK;
    4710                 : 
    4711                 :     UpdateMaskBits(mTransparencyBitmap, mBounds.width, mBounds.height,
    4712               0 :                    aRect, aAlphas, aStride);
    4713                 : 
    4714               0 :     if (!mNeedsShow) {
    4715               0 :         ApplyTransparencyBitmap();
    4716                 :     }
    4717               0 :     return NS_OK;
    4718                 : }
    4719                 : 
    4720                 : void
    4721               0 : nsWindow::GrabPointer(guint32 aTime)
    4722                 : {
    4723               0 :     LOG(("GrabPointer time=0x%08x retry=%d\n",
    4724                 :          (unsigned int)aTime, mRetryPointerGrab));
    4725                 : 
    4726               0 :     mRetryPointerGrab = false;
    4727               0 :     sRetryGrabTime = aTime;
    4728                 : 
    4729                 :     // If the window isn't visible, just set the flag to retry the
    4730                 :     // grab.  When this window becomes visible, the grab will be
    4731                 :     // retried.
    4732               0 :     if (!mHasMappedToplevel || mIsFullyObscured) {
    4733               0 :         LOG(("GrabPointer: window not visible\n"));
    4734               0 :         mRetryPointerGrab = true;
    4735               0 :         return;
    4736                 :     }
    4737                 : 
    4738               0 :     if (!mGdkWindow)
    4739               0 :         return;
    4740                 : 
    4741                 :     gint retval;
    4742                 :     retval = gdk_pointer_grab(mGdkWindow, TRUE,
    4743                 :                               (GdkEventMask)(GDK_BUTTON_PRESS_MASK |
    4744                 :                                              GDK_BUTTON_RELEASE_MASK |
    4745                 :                                              GDK_ENTER_NOTIFY_MASK |
    4746                 :                                              GDK_LEAVE_NOTIFY_MASK |
    4747                 : #ifdef HAVE_GTK_MOTION_HINTS
    4748                 :                                              GDK_POINTER_MOTION_HINT_MASK |
    4749                 : #endif
    4750                 :                                              GDK_POINTER_MOTION_MASK),
    4751               0 :                               (GdkWindow *)NULL, NULL, aTime);
    4752                 : 
    4753               0 :     if (retval == GDK_GRAB_NOT_VIEWABLE) {
    4754               0 :         LOG(("GrabPointer: window not viewable; will retry\n"));
    4755               0 :         mRetryPointerGrab = true;
    4756               0 :     } else if (retval != GDK_GRAB_SUCCESS) {
    4757               0 :         LOG(("GrabPointer: pointer grab failed: %i\n", retval));
    4758                 :         // A failed grab indicates that another app has grabbed the pointer.
    4759                 :         // Check for rollup now, because, without the grab, we likely won't
    4760                 :         // get subsequent button press events.
    4761               0 :         check_for_rollup(0, 0, false, true);
    4762                 :     }
    4763                 : }
    4764                 : 
    4765                 : void
    4766               0 : nsWindow::ReleaseGrabs(void)
    4767                 : {
    4768               0 :     LOG(("ReleaseGrabs\n"));
    4769                 : 
    4770               0 :     mRetryPointerGrab = false;
    4771               0 :     gdk_pointer_ungrab(GDK_CURRENT_TIME);
    4772               0 : }
    4773                 : 
    4774                 : void
    4775               0 : nsWindow::GetToplevelWidget(GtkWidget **aWidget)
    4776                 : {
    4777               0 :     *aWidget = nsnull;
    4778                 : 
    4779               0 :     if (mShell) {
    4780               0 :         *aWidget = mShell;
    4781               0 :         return;
    4782                 :     }
    4783                 : 
    4784               0 :     GtkWidget *widget = GetMozContainerWidget();
    4785               0 :     if (!widget)
    4786               0 :         return;
    4787                 : 
    4788               0 :     *aWidget = gtk_widget_get_toplevel(widget);
    4789                 : }
    4790                 : 
    4791                 : GtkWidget *
    4792               0 : nsWindow::GetMozContainerWidget()
    4793                 : {
    4794               0 :     if (!mGdkWindow)
    4795               0 :         return NULL;
    4796                 : 
    4797                 :     GtkWidget *owningWidget =
    4798               0 :         get_gtk_widget_for_gdk_window(mGdkWindow);
    4799               0 :     return owningWidget;
    4800                 : }
    4801                 : 
    4802                 : nsWindow *
    4803               0 : nsWindow::GetContainerWindow()
    4804                 : {
    4805               0 :     GtkWidget *owningWidget = GetMozContainerWidget();
    4806               0 :     if (!owningWidget)
    4807               0 :         return nsnull;
    4808                 : 
    4809               0 :     nsWindow *window = get_window_for_gtk_widget(owningWidget);
    4810               0 :     NS_ASSERTION(window, "No nsWindow for container widget");
    4811               0 :     return window;
    4812                 : }
    4813                 : 
    4814                 : void
    4815               0 : nsWindow::SetUrgencyHint(GtkWidget *top_window, bool state)
    4816                 : {
    4817               0 :     if (!top_window)
    4818               0 :         return;
    4819                 :         
    4820               0 :     gdk_window_set_urgency_hint(gtk_widget_get_window(top_window), state);
    4821                 : }
    4822                 : 
    4823                 : void *
    4824               0 : nsWindow::SetupPluginPort(void)
    4825                 : {
    4826               0 :     if (!mGdkWindow)
    4827               0 :         return nsnull;
    4828                 : 
    4829               0 :     if (gdk_window_is_destroyed(mGdkWindow) == TRUE)
    4830               0 :         return nsnull;
    4831                 : 
    4832               0 :     Window window = gdk_x11_window_get_xid(mGdkWindow);
    4833                 :     
    4834                 :     // we have to flush the X queue here so that any plugins that
    4835                 :     // might be running on separate X connections will be able to use
    4836                 :     // this window in case it was just created
    4837                 : #ifdef MOZ_X11
    4838                 :     XWindowAttributes xattrs;    
    4839               0 :     Display *display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
    4840               0 :     XGetWindowAttributes(display, window, &xattrs);
    4841                 :     XSelectInput (display, window,
    4842                 :                   xattrs.your_event_mask |
    4843               0 :                   SubstructureNotifyMask);
    4844                 : 
    4845               0 :     gdk_window_add_filter(mGdkWindow, plugin_window_filter_func, this);
    4846                 : 
    4847               0 :     XSync(display, False);
    4848                 : #endif /* MOZ_X11 */
    4849                 :     
    4850               0 :     return (void *)window;
    4851                 : }
    4852                 : 
    4853                 : void
    4854               0 : nsWindow::SetDefaultIcon(void)
    4855                 : {
    4856               0 :     SetIcon(NS_LITERAL_STRING("default"));
    4857               0 : }
    4858                 : 
    4859                 : void
    4860               0 : nsWindow::SetPluginType(PluginType aPluginType)
    4861                 : {
    4862               0 :     mPluginType = aPluginType;
    4863               0 : }
    4864                 : 
    4865                 : #ifdef MOZ_X11
    4866                 : void
    4867               0 : nsWindow::SetNonXEmbedPluginFocus()
    4868                 : {
    4869               0 :     if (gPluginFocusWindow == this || mPluginType!=PluginType_NONXEMBED) {
    4870               0 :         return;
    4871                 :     }
    4872                 : 
    4873               0 :     if (gPluginFocusWindow) {
    4874               0 :         nsRefPtr<nsWindow> kungFuDeathGrip = gPluginFocusWindow;
    4875               0 :         gPluginFocusWindow->LoseNonXEmbedPluginFocus();
    4876                 :     }
    4877                 : 
    4878               0 :     LOGFOCUS(("nsWindow::SetNonXEmbedPluginFocus\n"));
    4879                 : 
    4880                 :     Window curFocusWindow;
    4881                 :     int focusState;
    4882                 :     
    4883               0 :     GdkDisplay *gdkDisplay = gdk_window_get_display(mGdkWindow);
    4884                 :     XGetInputFocus(gdk_x11_display_get_xdisplay(gdkDisplay),
    4885                 :                    &curFocusWindow,
    4886               0 :                    &focusState);
    4887                 : 
    4888               0 :     LOGFOCUS(("\t curFocusWindow=%p\n", curFocusWindow));
    4889                 : 
    4890               0 :     GdkWindow* toplevel = gdk_window_get_toplevel(mGdkWindow);
    4891                 : #if defined(MOZ_WIDGET_GTK2)
    4892               0 :     GdkWindow *gdkfocuswin = gdk_window_lookup(curFocusWindow);
    4893                 : #else
    4894                 :     GdkWindow *gdkfocuswin = gdk_x11_window_lookup_for_display(gdkDisplay,
    4895                 :                                                                curFocusWindow);
    4896                 : #endif
    4897                 : 
    4898                 :     // lookup with the focus proxy window is supposed to get the
    4899                 :     // same GdkWindow as toplevel. If the current focused window
    4900                 :     // is not the focus proxy, we return without any change.
    4901               0 :     if (gdkfocuswin != toplevel) {
    4902               0 :         return;
    4903                 :     }
    4904                 : 
    4905                 :     // switch the focus from the focus proxy to the plugin window
    4906               0 :     mOldFocusWindow = curFocusWindow;
    4907                 :     XRaiseWindow(GDK_WINDOW_XDISPLAY(mGdkWindow),
    4908               0 :                  gdk_x11_window_get_xid(mGdkWindow));
    4909               0 :     gdk_error_trap_push();
    4910                 :     XSetInputFocus(GDK_WINDOW_XDISPLAY(mGdkWindow),
    4911                 :                    gdk_x11_window_get_xid(mGdkWindow),
    4912                 :                    RevertToNone,
    4913               0 :                    CurrentTime);
    4914               0 :     gdk_flush();
    4915               0 :     gdk_error_trap_pop();
    4916               0 :     gPluginFocusWindow = this;
    4917               0 :     gdk_window_add_filter(NULL, plugin_client_message_filter, this);
    4918                 : 
    4919               0 :     LOGFOCUS(("nsWindow::SetNonXEmbedPluginFocus oldfocus=%p new=%p\n",
    4920                 :               mOldFocusWindow, gdk_x11_window_get_xid(mGdkWindow)));
    4921                 : }
    4922                 : 
    4923                 : void
    4924               0 : nsWindow::LoseNonXEmbedPluginFocus()
    4925                 : {
    4926               0 :     LOGFOCUS(("nsWindow::LoseNonXEmbedPluginFocus\n"));
    4927                 : 
    4928                 :     // This method is only for the nsWindow which contains a
    4929                 :     // Non-XEmbed plugin, for example, JAVA plugin.
    4930               0 :     if (gPluginFocusWindow != this || mPluginType!=PluginType_NONXEMBED) {
    4931               0 :         return;
    4932                 :     }
    4933                 : 
    4934                 :     Window curFocusWindow;
    4935                 :     int focusState;
    4936                 : 
    4937                 :     XGetInputFocus(GDK_WINDOW_XDISPLAY(mGdkWindow),
    4938                 :                    &curFocusWindow,
    4939               0 :                    &focusState);
    4940                 : 
    4941                 :     // we only switch focus between plugin window and focus proxy. If the
    4942                 :     // current focused window is not the plugin window, just removing the
    4943                 :     // event filter that blocks the WM_TAKE_FOCUS is enough. WM and gtk2
    4944                 :     // will take care of the focus later.
    4945               0 :     if (!curFocusWindow ||
    4946               0 :         curFocusWindow == gdk_x11_window_get_xid(mGdkWindow)) {
    4947                 : 
    4948               0 :         gdk_error_trap_push();
    4949                 :         XRaiseWindow(GDK_WINDOW_XDISPLAY(mGdkWindow),
    4950               0 :                      mOldFocusWindow);
    4951                 :         XSetInputFocus(GDK_WINDOW_XDISPLAY(mGdkWindow),
    4952                 :                        mOldFocusWindow,
    4953                 :                        RevertToParent,
    4954               0 :                        CurrentTime);
    4955               0 :         gdk_flush();
    4956               0 :         gdk_error_trap_pop();
    4957                 :     }
    4958               0 :     gPluginFocusWindow = NULL;
    4959               0 :     mOldFocusWindow = 0;
    4960               0 :     gdk_window_remove_filter(NULL, plugin_client_message_filter, this);
    4961                 : 
    4962               0 :     LOGFOCUS(("nsWindow::LoseNonXEmbedPluginFocus end\n"));
    4963                 : }
    4964                 : #endif /* MOZ_X11 */
    4965                 : 
    4966                 : gint
    4967               0 : nsWindow::ConvertBorderStyles(nsBorderStyle aStyle)
    4968                 : {
    4969               0 :     gint w = 0;
    4970                 : 
    4971               0 :     if (aStyle == eBorderStyle_default)
    4972               0 :         return -1;
    4973                 : 
    4974                 :     // note that we don't handle eBorderStyle_close yet
    4975               0 :     if (aStyle & eBorderStyle_all)
    4976               0 :         w |= GDK_DECOR_ALL;
    4977               0 :     if (aStyle & eBorderStyle_border)
    4978               0 :         w |= GDK_DECOR_BORDER;
    4979               0 :     if (aStyle & eBorderStyle_resizeh)
    4980               0 :         w |= GDK_DECOR_RESIZEH;
    4981               0 :     if (aStyle & eBorderStyle_title)
    4982               0 :         w |= GDK_DECOR_TITLE;
    4983               0 :     if (aStyle & eBorderStyle_menu)
    4984               0 :         w |= GDK_DECOR_MENU;
    4985               0 :     if (aStyle & eBorderStyle_minimize)
    4986               0 :         w |= GDK_DECOR_MINIMIZE;
    4987               0 :     if (aStyle & eBorderStyle_maximize)
    4988               0 :         w |= GDK_DECOR_MAXIMIZE;
    4989                 : 
    4990               0 :     return w;
    4991                 : }
    4992                 : 
    4993                 : NS_IMETHODIMP
    4994               0 : nsWindow::MakeFullScreen(bool aFullScreen)
    4995                 : {
    4996               0 :     LOG(("nsWindow::MakeFullScreen [%p] aFullScreen %d\n",
    4997                 :          (void *)this, aFullScreen));
    4998                 : 
    4999               0 :     if (aFullScreen) {
    5000               0 :         if (mSizeMode != nsSizeMode_Fullscreen)
    5001               0 :             mLastSizeMode = mSizeMode;
    5002                 : 
    5003               0 :         mSizeMode = nsSizeMode_Fullscreen;
    5004               0 :         gtk_window_fullscreen(GTK_WINDOW(mShell));
    5005                 :     }
    5006                 :     else {
    5007               0 :         mSizeMode = mLastSizeMode;
    5008               0 :         gtk_window_unfullscreen(GTK_WINDOW(mShell));
    5009                 :     }
    5010                 : 
    5011               0 :     NS_ASSERTION(mLastSizeMode != nsSizeMode_Fullscreen,
    5012                 :                  "mLastSizeMode should never be fullscreen");
    5013               0 :     return NS_OK;
    5014                 : }
    5015                 : 
    5016                 : NS_IMETHODIMP
    5017               0 : nsWindow::HideWindowChrome(bool aShouldHide)
    5018                 : {
    5019               0 :     if (!mShell) {
    5020                 :         // Pass the request to the toplevel window
    5021               0 :         GtkWidget *topWidget = nsnull;
    5022               0 :         GetToplevelWidget(&topWidget);
    5023               0 :         if (!topWidget)
    5024               0 :             return NS_ERROR_FAILURE;
    5025                 : 
    5026               0 :         nsWindow *topWindow = get_window_for_gtk_widget(topWidget);
    5027               0 :         if (!topWindow)
    5028               0 :             return NS_ERROR_FAILURE;
    5029                 : 
    5030               0 :         return topWindow->HideWindowChrome(aShouldHide);
    5031                 :     }
    5032                 : 
    5033                 :     // Sawfish, metacity, and presumably other window managers get
    5034                 :     // confused if we change the window decorations while the window
    5035                 :     // is visible.
    5036               0 :     bool wasVisible = false;
    5037               0 :     GdkWindow *shellWindow = gtk_widget_get_window(mShell);
    5038               0 :     if (gdk_window_is_visible(shellWindow)) {
    5039               0 :         gdk_window_hide(shellWindow);
    5040               0 :         wasVisible = true;
    5041                 :     }
    5042                 : 
    5043                 :     gint wmd;
    5044               0 :     if (aShouldHide)
    5045               0 :         wmd = 0;
    5046                 :     else
    5047               0 :         wmd = ConvertBorderStyles(mBorderStyle);
    5048                 : 
    5049               0 :     if (wmd != -1)
    5050               0 :       gdk_window_set_decorations(shellWindow, (GdkWMDecoration) wmd);
    5051                 : 
    5052               0 :     if (wasVisible)
    5053               0 :         gdk_window_show(shellWindow);
    5054                 : 
    5055                 :     // For some window managers, adding or removing window decorations
    5056                 :     // requires unmapping and remapping our toplevel window.  Go ahead
    5057                 :     // and flush the queue here so that we don't end up with a BadWindow
    5058                 :     // error later when this happens (when the persistence timer fires
    5059                 :     // and GetWindowPos is called)
    5060                 : #ifdef MOZ_X11
    5061               0 :     XSync(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()) , False);
    5062                 : #else
    5063                 :     gdk_flush ();
    5064                 : #endif /* MOZ_X11 */
    5065                 : 
    5066               0 :     return NS_OK;
    5067                 : }
    5068                 : 
    5069                 : static bool
    5070               0 : check_for_rollup(gdouble aMouseX, gdouble aMouseY,
    5071                 :                  bool aIsWheel, bool aAlwaysRollup)
    5072                 : {
    5073               0 :     bool retVal = false;
    5074               0 :     nsCOMPtr<nsIWidget> rollupWidget = do_QueryReferent(gRollupWindow);
    5075                 : 
    5076               0 :     if (rollupWidget && gRollupListener) {
    5077                 :         GdkWindow *currentPopup =
    5078               0 :             (GdkWindow *)rollupWidget->GetNativeData(NS_NATIVE_WINDOW);
    5079               0 :         if (aAlwaysRollup || !is_mouse_in_window(currentPopup, aMouseX, aMouseY)) {
    5080               0 :             bool rollup = true;
    5081               0 :             if (aIsWheel) {
    5082               0 :                 rollup = gRollupListener->ShouldRollupOnMouseWheelEvent();
    5083               0 :                 retVal = true;
    5084                 :             }
    5085                 :             // if we're dealing with menus, we probably have submenus and
    5086                 :             // we don't want to rollup if the click is in a parent menu of
    5087                 :             // the current submenu
    5088               0 :             PRUint32 popupsToRollup = PR_UINT32_MAX;
    5089               0 :             if (!aAlwaysRollup) {
    5090               0 :                 nsAutoTArray<nsIWidget*, 5> widgetChain;
    5091               0 :                 PRUint32 sameTypeCount = gRollupListener->GetSubmenuWidgetChain(&widgetChain);
    5092               0 :                 for (PRUint32 i=0; i<widgetChain.Length(); ++i) {
    5093               0 :                     nsIWidget* widget = widgetChain[i];
    5094                 :                     GdkWindow* currWindow =
    5095               0 :                         (GdkWindow*) widget->GetNativeData(NS_NATIVE_WINDOW);
    5096               0 :                     if (is_mouse_in_window(currWindow, aMouseX, aMouseY)) {
    5097                 :                       // don't roll up if the mouse event occurred within a
    5098                 :                       // menu of the same type. If the mouse event occurred
    5099                 :                       // in a menu higher than that, roll up, but pass the
    5100                 :                       // number of popups to Rollup so that only those of the
    5101                 :                       // same type close up.
    5102               0 :                       if (i < sameTypeCount) {
    5103               0 :                         rollup = false;
    5104                 :                       }
    5105                 :                       else {
    5106               0 :                         popupsToRollup = sameTypeCount;
    5107                 :                       }
    5108               0 :                       break;
    5109                 :                     }
    5110                 :                 } // foreach parent menu widget
    5111                 :             } // if rollup listener knows about menus
    5112                 : 
    5113                 :             // if we've determined that we should still rollup, do it.
    5114               0 :             if (rollup) {
    5115               0 :                 gRollupListener->Rollup(popupsToRollup);
    5116               0 :                 if (popupsToRollup == PR_UINT32_MAX) {
    5117               0 :                     retVal = true;
    5118                 :                 }
    5119                 :             }
    5120                 :         }
    5121                 :     } else {
    5122               0 :         gRollupWindow = nsnull;
    5123               0 :         gRollupListener = nsnull;
    5124                 :     }
    5125                 : 
    5126               0 :     return retVal;
    5127                 : }
    5128                 : 
    5129                 : /* static */
    5130                 : bool
    5131               0 : nsWindow::DragInProgress(void)
    5132                 : {
    5133                 :     // sLastDragMotionWindow means the drag arrow is over mozilla
    5134                 :     // sIsDraggingOutOf means the drag arrow is out of mozilla
    5135                 :     // both cases mean the dragging is happenning.
    5136               0 :     return (sLastDragMotionWindow || sIsDraggingOutOf);
    5137                 : }
    5138                 : 
    5139                 : static bool
    5140               0 : is_mouse_in_window (GdkWindow* aWindow, gdouble aMouseX, gdouble aMouseY)
    5141                 : {
    5142               0 :     gint x = 0;
    5143               0 :     gint y = 0;
    5144                 :     gint w, h;
    5145                 : 
    5146               0 :     gint offsetX = 0;
    5147               0 :     gint offsetY = 0;
    5148                 : 
    5149               0 :     GdkWindow *window = aWindow;
    5150                 : 
    5151               0 :     while (window) {
    5152               0 :         gint tmpX = 0;
    5153               0 :         gint tmpY = 0;
    5154                 : 
    5155               0 :         gdk_window_get_position(window, &tmpX, &tmpY);
    5156               0 :         GtkWidget *widget = get_gtk_widget_for_gdk_window(window);
    5157                 : 
    5158                 :         // if this is a window, compute x and y given its origin and our
    5159                 :         // offset
    5160               0 :         if (GTK_IS_WINDOW(widget)) {
    5161               0 :             x = tmpX + offsetX;
    5162               0 :             y = tmpY + offsetY;
    5163               0 :             break;
    5164                 :         }
    5165                 : 
    5166               0 :         offsetX += tmpX;
    5167               0 :         offsetY += tmpY;
    5168               0 :         window = gdk_window_get_parent(window);
    5169                 :     }
    5170                 : 
    5171                 : #if defined(MOZ_WIDGET_GTK2)
    5172               0 :     gdk_drawable_get_size(aWindow, &w, &h);
    5173                 : #else
    5174                 :     w = gdk_window_get_width(aWindow);
    5175                 :     h = gdk_window_get_height(aWindow);
    5176                 : #endif
    5177                 : 
    5178               0 :     if (aMouseX > x && aMouseX < x + w &&
    5179                 :         aMouseY > y && aMouseY < y + h)
    5180               0 :         return true;
    5181                 : 
    5182               0 :     return false;
    5183                 : }
    5184                 : 
    5185                 : static nsWindow *
    5186               0 : get_window_for_gtk_widget(GtkWidget *widget)
    5187                 : {
    5188               0 :     gpointer user_data = g_object_get_data(G_OBJECT(widget), "nsWindow");
    5189                 : 
    5190               0 :     return static_cast<nsWindow *>(user_data);
    5191                 : }
    5192                 : 
    5193                 : static nsWindow *
    5194               0 : get_window_for_gdk_window(GdkWindow *window)
    5195                 : {
    5196               0 :     gpointer user_data = g_object_get_data(G_OBJECT(window), "nsWindow");
    5197                 : 
    5198               0 :     return static_cast<nsWindow *>(user_data);
    5199                 : }
    5200                 : 
    5201                 : static GtkWidget *
    5202               0 : get_gtk_widget_for_gdk_window(GdkWindow *window)
    5203                 : {
    5204               0 :     gpointer user_data = NULL;
    5205               0 :     gdk_window_get_user_data(window, &user_data);
    5206                 : 
    5207               0 :     return GTK_WIDGET(user_data);
    5208                 : }
    5209                 : 
    5210                 : static GdkCursor *
    5211               0 : get_gtk_cursor(nsCursor aCursor)
    5212                 : {
    5213               0 :     GdkCursor *gdkcursor = nsnull;
    5214               0 :     PRUint8 newType = 0xff;
    5215                 : 
    5216               0 :     if ((gdkcursor = gCursorCache[aCursor])) {
    5217               0 :         return gdkcursor;
    5218                 :     }
    5219                 : 
    5220               0 :     switch (aCursor) {
    5221                 :     case eCursor_standard:
    5222               0 :         gdkcursor = gdk_cursor_new(GDK_LEFT_PTR);
    5223               0 :         break;
    5224                 :     case eCursor_wait:
    5225               0 :         gdkcursor = gdk_cursor_new(GDK_WATCH);
    5226               0 :         break;
    5227                 :     case eCursor_select:
    5228               0 :         gdkcursor = gdk_cursor_new(GDK_XTERM);
    5229               0 :         break;
    5230                 :     case eCursor_hyperlink:
    5231               0 :         gdkcursor = gdk_cursor_new(GDK_HAND2);
    5232               0 :         break;
    5233                 :     case eCursor_n_resize:
    5234               0 :         gdkcursor = gdk_cursor_new(GDK_TOP_SIDE);
    5235               0 :         break;
    5236                 :     case eCursor_s_resize:
    5237               0 :         gdkcursor = gdk_cursor_new(GDK_BOTTOM_SIDE);
    5238               0 :         break;
    5239                 :     case eCursor_w_resize:
    5240               0 :         gdkcursor = gdk_cursor_new(GDK_LEFT_SIDE);
    5241               0 :         break;
    5242                 :     case eCursor_e_resize:
    5243               0 :         gdkcursor = gdk_cursor_new(GDK_RIGHT_SIDE);
    5244               0 :         break;
    5245                 :     case eCursor_nw_resize:
    5246               0 :         gdkcursor = gdk_cursor_new(GDK_TOP_LEFT_CORNER);
    5247               0 :         break;
    5248                 :     case eCursor_se_resize:
    5249               0 :         gdkcursor = gdk_cursor_new(GDK_BOTTOM_RIGHT_CORNER);
    5250               0 :         break;
    5251                 :     case eCursor_ne_resize:
    5252               0 :         gdkcursor = gdk_cursor_new(GDK_TOP_RIGHT_CORNER);
    5253               0 :         break;
    5254                 :     case eCursor_sw_resize:
    5255               0 :         gdkcursor = gdk_cursor_new(GDK_BOTTOM_LEFT_CORNER);
    5256               0 :         break;
    5257                 :     case eCursor_crosshair:
    5258               0 :         gdkcursor = gdk_cursor_new(GDK_CROSSHAIR);
    5259               0 :         break;
    5260                 :     case eCursor_move:
    5261               0 :         gdkcursor = gdk_cursor_new(GDK_FLEUR);
    5262               0 :         break;
    5263                 :     case eCursor_help:
    5264               0 :         gdkcursor = gdk_cursor_new(GDK_QUESTION_ARROW);
    5265               0 :         break;
    5266                 :     case eCursor_copy: // CSS3
    5267               0 :         newType = MOZ_CURSOR_COPY;
    5268               0 :         break;
    5269                 :     case eCursor_alias:
    5270               0 :         newType = MOZ_CURSOR_ALIAS;
    5271               0 :         break;
    5272                 :     case eCursor_context_menu:
    5273               0 :         newType = MOZ_CURSOR_CONTEXT_MENU;
    5274               0 :         break;
    5275                 :     case eCursor_cell:
    5276               0 :         gdkcursor = gdk_cursor_new(GDK_PLUS);
    5277               0 :         break;
    5278                 :     case eCursor_grab:
    5279               0 :         newType = MOZ_CURSOR_HAND_GRAB;
    5280               0 :         break;
    5281                 :     case eCursor_grabbing:
    5282               0 :         newType = MOZ_CURSOR_HAND_GRABBING;
    5283               0 :         break;
    5284                 :     case eCursor_spinning:
    5285               0 :         newType = MOZ_CURSOR_SPINNING;
    5286               0 :         break;
    5287                 :     case eCursor_zoom_in:
    5288               0 :         newType = MOZ_CURSOR_ZOOM_IN;
    5289               0 :         break;
    5290                 :     case eCursor_zoom_out:
    5291               0 :         newType = MOZ_CURSOR_ZOOM_OUT;
    5292               0 :         break;
    5293                 :     case eCursor_not_allowed:
    5294                 :     case eCursor_no_drop:
    5295               0 :         newType = MOZ_CURSOR_NOT_ALLOWED;
    5296               0 :         break;
    5297                 :     case eCursor_vertical_text:
    5298               0 :         newType = MOZ_CURSOR_VERTICAL_TEXT;
    5299               0 :         break;
    5300                 :     case eCursor_all_scroll:
    5301               0 :         gdkcursor = gdk_cursor_new(GDK_FLEUR);
    5302               0 :         break;
    5303                 :     case eCursor_nesw_resize:
    5304               0 :         newType = MOZ_CURSOR_NESW_RESIZE;
    5305               0 :         break;
    5306                 :     case eCursor_nwse_resize:
    5307               0 :         newType = MOZ_CURSOR_NWSE_RESIZE;
    5308               0 :         break;
    5309                 :     case eCursor_ns_resize:
    5310                 :     case eCursor_row_resize:
    5311               0 :         gdkcursor = gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW);
    5312               0 :         break;
    5313                 :     case eCursor_ew_resize:
    5314                 :     case eCursor_col_resize:
    5315               0 :         gdkcursor = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
    5316               0 :         break;
    5317                 :     case eCursor_none:
    5318               0 :         newType = MOZ_CURSOR_NONE;
    5319               0 :         break;
    5320                 :     default:
    5321               0 :         NS_ASSERTION(aCursor, "Invalid cursor type");
    5322               0 :         gdkcursor = gdk_cursor_new(GDK_LEFT_PTR);
    5323               0 :         break;
    5324                 :     }
    5325                 : 
    5326                 :     // If by now we don't have a xcursor, this means we have to make a custom
    5327                 :     // one. First, we try creating a named cursor based on the hash of our
    5328                 :     // custom bitmap, as libXcursor has some magic to convert bitmapped cursors
    5329                 :     // to themed cursors
    5330               0 :     if (newType != 0xFF && GtkCursors[newType].hash) {
    5331                 :         gdkcursor = gdk_cursor_new_from_name(gdk_display_get_default(),
    5332               0 :                                              GtkCursors[newType].hash);
    5333                 :     }
    5334                 : 
    5335                 :     // If we still don't have a xcursor, we now really create a bitmap cursor
    5336               0 :     if (newType != 0xff && !gdkcursor) {
    5337               0 :         GdkPixbuf * cursor_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 32, 32);
    5338               0 :         if (!cursor_pixbuf)
    5339               0 :             return NULL;
    5340                 :       
    5341               0 :         guchar *data = gdk_pixbuf_get_pixels(cursor_pixbuf);
    5342                 :         
    5343                 :         // Read data from GtkCursors and compose RGBA surface from 1bit bitmap and mask
    5344                 :         // GtkCursors bits and mask are 32x32 monochrome bitmaps (1 bit for each pixel)
    5345                 :         // so it's 128 byte array (4 bytes for are one bitmap row and there are 32 rows here).
    5346               0 :         const unsigned char *bits = GtkCursors[newType].bits;
    5347               0 :         const unsigned char *mask_bits = GtkCursors[newType].mask_bits;
    5348                 :         
    5349               0 :         for (int i = 0; i < 128; i++) {
    5350               0 :             char bit = *bits++;
    5351               0 :             char mask = *mask_bits++;
    5352               0 :             for (int j = 0; j < 8; j++) {
    5353               0 :                 unsigned char pix = ~(((bit >> j) & 0x01) * 0xff);
    5354               0 :                 *data++ = pix;
    5355               0 :                 *data++ = pix;
    5356               0 :                 *data++ = pix;
    5357               0 :                 *data++ = (((mask >> j) & 0x01) * 0xff);
    5358                 :             }
    5359                 :         }
    5360                 :       
    5361                 :         gdkcursor = gdk_cursor_new_from_pixbuf(gdk_display_get_default(), cursor_pixbuf,
    5362                 :                                                GtkCursors[newType].hot_x,
    5363               0 :                                                GtkCursors[newType].hot_y);
    5364                 :         
    5365               0 :         g_object_unref(cursor_pixbuf);
    5366                 :     }
    5367                 : 
    5368               0 :     gCursorCache[aCursor] = gdkcursor;
    5369                 : 
    5370               0 :     return gdkcursor;
    5371                 : }
    5372                 : 
    5373                 : // gtk callbacks
    5374                 : 
    5375                 : #if defined(MOZ_WIDGET_GTK2)
    5376                 : static gboolean
    5377               0 : expose_event_cb(GtkWidget *widget, GdkEventExpose *event)
    5378                 : {
    5379               0 :     nsRefPtr<nsWindow> window = get_window_for_gdk_window(event->window);
    5380               0 :     if (!window)
    5381               0 :         return FALSE;
    5382                 : 
    5383                 :     // XXX We are so getting lucky here.  We are doing all of
    5384                 :     // mozilla's painting and then allowing default processing to occur.
    5385                 :     // This means that Mozilla paints in all of it's stuff and then
    5386                 :     // NO_WINDOW widgets (like scrollbars, for example) are painted by
    5387                 :     // Gtk on top of what we painted.
    5388                 : 
    5389                 :     // This return window->OnExposeEvent(widget, event); */
    5390                 : 
    5391               0 :     window->OnExposeEvent(event);
    5392               0 :     return FALSE;
    5393                 : }
    5394                 : #else
    5395                 : void
    5396                 : draw_window_of_widget(GtkWidget *widget, GdkWindow *aWindow, cairo_t *cr)
    5397                 : {
    5398                 :     gpointer windowWidget;
    5399                 :     gdk_window_get_user_data(aWindow, &windowWidget);
    5400                 : 
    5401                 :     // aWindow is in another widget
    5402                 :     if (windowWidget != widget)
    5403                 :         return;
    5404                 :     
    5405                 :     if (gtk_cairo_should_draw_window(cr, aWindow)) {
    5406                 :         nsRefPtr<nsWindow> window = get_window_for_gdk_window(aWindow);
    5407                 :         if (!window) {
    5408                 :             NS_WARNING("Cannot get nsWindow from GtkWidget");
    5409                 :         }
    5410                 :         else {      
    5411                 :             cairo_save(cr);      
    5412                 :             gtk_cairo_transform_to_window(cr, widget, aWindow);  
    5413                 :             // TODO - window->OnExposeEvent() can destroy this or other windows,
    5414                 :             // do we need to handle it somehow?
    5415                 :             window->OnExposeEvent(cr);
    5416                 :             cairo_restore(cr);
    5417                 :         }
    5418                 :     }
    5419                 :     
    5420                 :     GList *children = gdk_window_get_children(aWindow);
    5421                 :     GList *child = children;
    5422                 :     while (child) {
    5423                 :         draw_window_of_widget(widget, GDK_WINDOW(child->data), cr);
    5424                 :         child = g_list_next(child);
    5425                 :     }  
    5426                 :     g_list_free(children);
    5427                 : 
    5428                 : }
    5429                 : 
    5430                 : /* static */
    5431                 : gboolean
    5432                 : expose_event_cb(GtkWidget *widget, cairo_t *cr)
    5433                 : {
    5434                 :     draw_window_of_widget(widget, gtk_widget_get_window(widget), cr);
    5435                 :     return FALSE;
    5436                 : }
    5437                 : #endif //MOZ_WIDGET_GTK2
    5438                 : 
    5439                 : static gboolean
    5440               0 : configure_event_cb(GtkWidget *widget,
    5441                 :                    GdkEventConfigure *event)
    5442                 : {
    5443               0 :     nsRefPtr<nsWindow> window = get_window_for_gtk_widget(widget);
    5444               0 :     if (!window)
    5445               0 :         return FALSE;
    5446                 : 
    5447               0 :     return window->OnConfigureEvent(widget, event);
    5448                 : }
    5449                 : 
    5450                 : static void
    5451               0 : container_unrealize_cb (GtkWidget *widget)
    5452                 : {
    5453               0 :     nsRefPtr<nsWindow> window = get_window_for_gtk_widget(widget);
    5454               0 :     if (!window)
    5455                 :         return;
    5456                 : 
    5457               0 :     window->OnContainerUnrealize(widget);
    5458                 : }
    5459                 : 
    5460                 : static void
    5461               0 : size_allocate_cb (GtkWidget *widget, GtkAllocation *allocation)
    5462                 : {
    5463               0 :     nsRefPtr<nsWindow> window = get_window_for_gtk_widget(widget);
    5464               0 :     if (!window)
    5465                 :         return;
    5466                 : 
    5467               0 :     window->OnSizeAllocate(widget, allocation);
    5468                 : }
    5469                 : 
    5470                 : static gboolean
    5471               0 : delete_event_cb(GtkWidget *widget, GdkEventAny *event)
    5472                 : {
    5473               0 :     nsRefPtr<nsWindow> window = get_window_for_gtk_widget(widget);
    5474               0 :     if (!window)
    5475               0 :         return FALSE;
    5476                 : 
    5477               0 :     window->OnDeleteEvent(widget, event);
    5478                 : 
    5479               0 :     return TRUE;
    5480                 : }
    5481                 : 
    5482                 : static gboolean
    5483               0 : enter_notify_event_cb(GtkWidget *widget,
    5484                 :                       GdkEventCrossing *event)
    5485                 : {
    5486               0 :     nsRefPtr<nsWindow> window = get_window_for_gdk_window(event->window);
    5487               0 :     if (!window)
    5488               0 :         return TRUE;
    5489                 : 
    5490               0 :     window->OnEnterNotifyEvent(widget, event);
    5491                 : 
    5492               0 :     return TRUE;
    5493                 : }
    5494                 : 
    5495                 : static gboolean
    5496               0 : leave_notify_event_cb(GtkWidget *widget,
    5497                 :                       GdkEventCrossing *event)
    5498                 : {
    5499               0 :     if (is_parent_grab_leave(event)) {
    5500               0 :         return TRUE;
    5501                 :     }
    5502                 : 
    5503                 :     // bug 369599: Suppress LeaveNotify events caused by pointer grabs to
    5504                 :     // avoid generating spurious mouse exit events.
    5505               0 :     gint x = gint(event->x_root);
    5506               0 :     gint y = gint(event->y_root);
    5507               0 :     GdkDisplay* display = gtk_widget_get_display(widget);
    5508               0 :     GdkWindow* winAtPt = gdk_display_get_window_at_pointer(display, &x, &y);
    5509               0 :     if (winAtPt == event->window) {
    5510               0 :         return TRUE;
    5511                 :     }
    5512                 : 
    5513               0 :     nsRefPtr<nsWindow> window = get_window_for_gdk_window(event->window);
    5514               0 :     if (!window)
    5515               0 :         return TRUE;
    5516                 : 
    5517               0 :     window->OnLeaveNotifyEvent(widget, event);
    5518                 : 
    5519               0 :     return TRUE;
    5520                 : }
    5521                 : 
    5522                 : static nsWindow*
    5523               0 : GetFirstNSWindowForGDKWindow(GdkWindow *aGdkWindow)
    5524                 : {
    5525                 :     nsWindow* window;
    5526               0 :     while (!(window = get_window_for_gdk_window(aGdkWindow))) {
    5527                 :         // The event has bubbled to the moz_container widget as passed into each caller's *widget parameter,
    5528                 :         // but its corresponding nsWindow is an ancestor of the window that we need.  Instead, look at
    5529                 :         // event->window and find the first ancestor nsWindow of it because event->window may be in a plugin.
    5530               0 :         aGdkWindow = gdk_window_get_parent(aGdkWindow);
    5531               0 :         if (!aGdkWindow) {
    5532               0 :             window = nsnull;
    5533               0 :             break;
    5534                 :         }
    5535                 :     }
    5536               0 :     return window;
    5537                 : }
    5538                 : 
    5539                 : static gboolean
    5540               0 : motion_notify_event_cb(GtkWidget *widget, GdkEventMotion *event)
    5541                 : {
    5542               0 :     UpdateLastInputEventTime(event);
    5543                 : 
    5544               0 :     nsWindow *window = GetFirstNSWindowForGDKWindow(event->window);
    5545               0 :     if (!window)
    5546               0 :         return FALSE;
    5547                 : 
    5548               0 :     window->OnMotionNotifyEvent(widget, event);
    5549                 : 
    5550                 : #ifdef HAVE_GTK_MOTION_HINTS
    5551                 :     gdk_event_request_motions(event);
    5552                 : #endif
    5553               0 :     return TRUE;
    5554                 : }
    5555                 : 
    5556                 : static gboolean
    5557               0 : button_press_event_cb(GtkWidget *widget, GdkEventButton *event)
    5558                 : {
    5559               0 :     UpdateLastInputEventTime(event);
    5560                 : 
    5561               0 :     nsWindow *window = GetFirstNSWindowForGDKWindow(event->window);
    5562               0 :     if (!window)
    5563               0 :         return FALSE;
    5564                 : 
    5565               0 :     window->OnButtonPressEvent(widget, event);
    5566                 : 
    5567               0 :     return TRUE;
    5568                 : }
    5569                 : 
    5570                 : static gboolean
    5571               0 : button_release_event_cb(GtkWidget *widget, GdkEventButton *event)
    5572                 : {
    5573               0 :     UpdateLastInputEventTime(event);
    5574                 : 
    5575               0 :     nsWindow *window = GetFirstNSWindowForGDKWindow(event->window);
    5576               0 :     if (!window)
    5577               0 :         return FALSE;
    5578                 : 
    5579               0 :     window->OnButtonReleaseEvent(widget, event);
    5580                 : 
    5581               0 :     return TRUE;
    5582                 : }
    5583                 : 
    5584                 : static gboolean
    5585               0 : focus_in_event_cb(GtkWidget *widget, GdkEventFocus *event)
    5586                 : {
    5587               0 :     nsRefPtr<nsWindow> window = get_window_for_gtk_widget(widget);
    5588               0 :     if (!window)
    5589               0 :         return FALSE;
    5590                 : 
    5591               0 :     window->OnContainerFocusInEvent(widget, event);
    5592                 : 
    5593               0 :     return FALSE;
    5594                 : }
    5595                 : 
    5596                 : static gboolean
    5597               0 : focus_out_event_cb(GtkWidget *widget, GdkEventFocus *event)
    5598                 : {
    5599               0 :     nsRefPtr<nsWindow> window = get_window_for_gtk_widget(widget);
    5600               0 :     if (!window)
    5601               0 :         return FALSE;
    5602                 : 
    5603               0 :     window->OnContainerFocusOutEvent(widget, event);
    5604                 : 
    5605               0 :     return FALSE;
    5606                 : }
    5607                 : 
    5608                 : #ifdef MOZ_X11
    5609                 : // For long-lived popup windows that don't really take focus themselves but
    5610                 : // may have elements that accept keyboard input when the parent window is
    5611                 : // active, focus is handled specially.  These windows include noautohide
    5612                 : // panels.  (This special handling is not necessary for temporary popups where
    5613                 : // the keyboard is grabbed.)
    5614                 : //
    5615                 : // Mousing over or clicking on these windows should not cause them to steal
    5616                 : // focus from their parent windows, so, the input field of WM_HINTS is set to
    5617                 : // False to request that the window manager not set the input focus to this
    5618                 : // window.  http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.7
    5619                 : //
    5620                 : // However, these windows can still receive WM_TAKE_FOCUS messages from the
    5621                 : // window manager, so they can still detect when the user has indicated that
    5622                 : // they wish to direct keyboard input at these windows.  When the window
    5623                 : // manager offers focus to these windows (after a mouse over or click, for
    5624                 : // example), a request to make the parent window active is issued.  When the
    5625                 : // parent window becomes active, keyboard events will be received.
    5626                 : 
    5627                 : static GdkFilterReturn
    5628               0 : popup_take_focus_filter(GdkXEvent *gdk_xevent,
    5629                 :                         GdkEvent *event,
    5630                 :                         gpointer data)
    5631                 : {
    5632               0 :     XEvent* xevent = static_cast<XEvent*>(gdk_xevent);
    5633               0 :     if (xevent->type != ClientMessage)
    5634               0 :         return GDK_FILTER_CONTINUE;
    5635                 : 
    5636               0 :     XClientMessageEvent& xclient = xevent->xclient;
    5637               0 :     if (xclient.message_type != gdk_x11_get_xatom_by_name("WM_PROTOCOLS"))
    5638               0 :         return GDK_FILTER_CONTINUE;
    5639                 : 
    5640               0 :     Atom atom = xclient.data.l[0];
    5641               0 :     if (atom != gdk_x11_get_xatom_by_name("WM_TAKE_FOCUS"))
    5642               0 :         return GDK_FILTER_CONTINUE;
    5643                 : 
    5644               0 :     guint32 timestamp = xclient.data.l[1];
    5645                 : 
    5646               0 :     GtkWidget* widget = get_gtk_widget_for_gdk_window(event->any.window);
    5647               0 :     if (!widget)
    5648               0 :         return GDK_FILTER_CONTINUE;
    5649                 : 
    5650               0 :     GtkWindow* parent = gtk_window_get_transient_for(GTK_WINDOW(widget));
    5651               0 :     if (!parent)
    5652               0 :         return GDK_FILTER_CONTINUE;
    5653                 : 
    5654               0 :     if (gtk_window_is_active(parent))
    5655               0 :         return GDK_FILTER_REMOVE; // leave input focus on the parent
    5656                 : 
    5657               0 :     GdkWindow* parent_window = gtk_widget_get_window(GTK_WIDGET(parent));
    5658               0 :     if (!parent_window)
    5659               0 :         return GDK_FILTER_CONTINUE;
    5660                 : 
    5661                 :     // In case the parent has not been deconified.
    5662               0 :     gdk_window_show_unraised(parent_window);
    5663                 : 
    5664                 :     // Request focus on the parent window.
    5665                 :     // Use gdk_window_focus rather than gtk_window_present to avoid
    5666                 :     // raising the parent window.
    5667               0 :     gdk_window_focus(parent_window, timestamp);
    5668               0 :     return GDK_FILTER_REMOVE;
    5669                 : }
    5670                 : 
    5671                 : static GdkFilterReturn
    5672               0 : plugin_window_filter_func(GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
    5673                 : {
    5674                 :     GdkWindow  *plugin_window;
    5675                 :     XEvent     *xevent;
    5676                 :     Window      xeventWindow;
    5677                 : 
    5678               0 :     nsRefPtr<nsWindow> nswindow = (nsWindow*)data;
    5679                 :     GdkFilterReturn return_val;
    5680                 : 
    5681               0 :     xevent = (XEvent *)gdk_xevent;
    5682               0 :     return_val = GDK_FILTER_CONTINUE;
    5683                 : 
    5684               0 :     switch (xevent->type)
    5685                 :     {
    5686                 :         case CreateNotify:
    5687                 :         case ReparentNotify:
    5688               0 :             if (xevent->type==CreateNotify) {
    5689               0 :                 xeventWindow = xevent->xcreatewindow.window;
    5690                 :             }
    5691                 :             else {
    5692               0 :                 if (xevent->xreparent.event != xevent->xreparent.parent)
    5693               0 :                     break;
    5694               0 :                 xeventWindow = xevent->xreparent.window;
    5695                 :             }
    5696                 : #if defined(MOZ_WIDGET_GTK2)
    5697               0 :             plugin_window = gdk_window_lookup(xeventWindow);
    5698                 : #else
    5699                 :             plugin_window = gdk_x11_window_lookup_for_display(
    5700                 :                                   gdk_x11_lookup_xdisplay(xevent->xcreatewindow.display), xeventWindow);
    5701                 : #endif        
    5702               0 :             if (plugin_window) {
    5703                 :                 GtkWidget *widget =
    5704               0 :                     get_gtk_widget_for_gdk_window(plugin_window);
    5705                 : 
    5706                 : // TODO GTK3
    5707                 : #if defined(MOZ_WIDGET_GTK2)
    5708               0 :                 if (GTK_IS_XTBIN(widget)) {
    5709               0 :                     nswindow->SetPluginType(nsWindow::PluginType_NONXEMBED);
    5710               0 :                     break;
    5711                 :                 }
    5712                 :                 else 
    5713                 : #endif
    5714               0 :                 if(GTK_IS_SOCKET(widget)) {
    5715               0 :                     nswindow->SetPluginType(nsWindow::PluginType_XEMBED);
    5716               0 :                     break;
    5717                 :                 }
    5718                 :             }
    5719               0 :             nswindow->SetPluginType(nsWindow::PluginType_NONXEMBED);
    5720               0 :             return_val = GDK_FILTER_REMOVE;
    5721               0 :             break;
    5722                 :         case EnterNotify:
    5723               0 :             nswindow->SetNonXEmbedPluginFocus();
    5724               0 :             break;
    5725                 :         case DestroyNotify:
    5726                 :             gdk_window_remove_filter
    5727               0 :                 ((GdkWindow*)(nswindow->GetNativeData(NS_NATIVE_WINDOW)),
    5728                 :                  plugin_window_filter_func,
    5729               0 :                  nswindow);
    5730                 :             // Currently we consider all plugins are non-xembed and calls
    5731                 :             // LoseNonXEmbedPluginFocus without any checking.
    5732               0 :             nswindow->LoseNonXEmbedPluginFocus();
    5733               0 :             break;
    5734                 :         default:
    5735               0 :             break;
    5736                 :     }
    5737               0 :     return return_val;
    5738                 : }
    5739                 : 
    5740                 : static GdkFilterReturn
    5741               0 : plugin_client_message_filter(GdkXEvent *gdk_xevent,
    5742                 :                              GdkEvent *event,
    5743                 :                              gpointer data)
    5744                 : {
    5745                 :     XEvent    *xevent;
    5746               0 :     xevent = (XEvent *)gdk_xevent;
    5747                 : 
    5748                 :     GdkFilterReturn return_val;
    5749               0 :     return_val = GDK_FILTER_CONTINUE;
    5750                 : 
    5751               0 :     if (!gPluginFocusWindow || xevent->type!=ClientMessage) {
    5752               0 :         return return_val;
    5753                 :     }
    5754                 : 
    5755                 :     // When WM sends out WM_TAKE_FOCUS, gtk2 will use XSetInputFocus
    5756                 :     // to set the focus to the focus proxy. To prevent this happen
    5757                 :     // while the focus is on the plugin, we filter the WM_TAKE_FOCUS
    5758                 :     // out.
    5759               0 :     if (gdk_x11_get_xatom_by_name("WM_PROTOCOLS")
    5760                 :             != xevent->xclient.message_type) {
    5761               0 :         return return_val;
    5762                 :     }
    5763                 : 
    5764               0 :     if ((Atom) xevent->xclient.data.l[0] ==
    5765               0 :             gdk_x11_get_xatom_by_name("WM_TAKE_FOCUS")) {
    5766                 :         // block it from gtk2.0 focus proxy
    5767               0 :         return_val = GDK_FILTER_REMOVE;
    5768                 :     }
    5769                 : 
    5770               0 :     return return_val;
    5771                 : }
    5772                 : #endif /* MOZ_X11 */
    5773                 : 
    5774                 : static gboolean
    5775               0 : key_press_event_cb(GtkWidget *widget, GdkEventKey *event)
    5776                 : {
    5777               0 :     LOG(("key_press_event_cb\n"));
    5778                 : 
    5779               0 :     UpdateLastInputEventTime(event);
    5780                 : 
    5781                 :     // find the window with focus and dispatch this event to that widget
    5782               0 :     nsWindow *window = get_window_for_gtk_widget(widget);
    5783               0 :     if (!window)
    5784               0 :         return FALSE;
    5785                 : 
    5786               0 :     nsRefPtr<nsWindow> focusWindow = gFocusWindow ? gFocusWindow : window;
    5787                 : 
    5788                 : #ifdef MOZ_X11
    5789                 :     // Keyboard repeat can cause key press events to queue up when there are
    5790                 :     // slow event handlers (bug 301029).  Throttle these events by removing
    5791                 :     // consecutive pending duplicate KeyPress events to the same window.
    5792                 :     // We use the event time of the last one.
    5793                 :     // Note: GDK calls XkbSetDetectableAutorepeat so that KeyRelease events
    5794                 :     // are generated only when the key is physically released.
    5795                 : #define NS_GDKEVENT_MATCH_MASK 0x1FFF /* GDK_SHIFT_MASK .. GDK_BUTTON5_MASK */
    5796               0 :     GdkDisplay* gdkDisplay = gtk_widget_get_display(widget);
    5797               0 :     Display* dpy = GDK_DISPLAY_XDISPLAY(gdkDisplay);
    5798               0 :     while (XPending(dpy)) {
    5799                 :         XEvent next_event;
    5800               0 :         XPeekEvent(dpy, &next_event);
    5801                 :         GdkWindow* nextGdkWindow =
    5802               0 :             gdk_x11_window_lookup_for_display(gdkDisplay, next_event.xany.window);
    5803               0 :         if (nextGdkWindow != event->window ||
    5804                 :             next_event.type != KeyPress ||
    5805                 :             next_event.xkey.keycode != event->hardware_keycode ||
    5806                 :             next_event.xkey.state != (event->state & NS_GDKEVENT_MATCH_MASK)) {
    5807               0 :             break;
    5808                 :         }
    5809               0 :         XNextEvent(dpy, &next_event);
    5810               0 :         event->time = next_event.xkey.time;
    5811                 :     }
    5812                 : #endif
    5813                 : 
    5814               0 :     return focusWindow->OnKeyPressEvent(widget, event);
    5815                 : }
    5816                 : 
    5817                 : static gboolean
    5818               0 : key_release_event_cb(GtkWidget *widget, GdkEventKey *event)
    5819                 : {
    5820               0 :     LOG(("key_release_event_cb\n"));
    5821                 : 
    5822               0 :     UpdateLastInputEventTime(event);
    5823                 : 
    5824                 :     // find the window with focus and dispatch this event to that widget
    5825               0 :     nsWindow *window = get_window_for_gtk_widget(widget);
    5826               0 :     if (!window)
    5827               0 :         return FALSE;
    5828                 : 
    5829               0 :     nsRefPtr<nsWindow> focusWindow = gFocusWindow ? gFocusWindow : window;
    5830                 : 
    5831               0 :     return focusWindow->OnKeyReleaseEvent(widget, event);
    5832                 : }
    5833                 : 
    5834                 : static gboolean
    5835               0 : scroll_event_cb(GtkWidget *widget, GdkEventScroll *event)
    5836                 : {
    5837               0 :     nsWindow *window = GetFirstNSWindowForGDKWindow(event->window);
    5838               0 :     if (!window)
    5839               0 :         return FALSE;
    5840                 : 
    5841               0 :     window->OnScrollEvent(widget, event);
    5842                 : 
    5843               0 :     return TRUE;
    5844                 : }
    5845                 : 
    5846                 : static gboolean
    5847               0 : visibility_notify_event_cb (GtkWidget *widget, GdkEventVisibility *event)
    5848                 : {
    5849               0 :     nsRefPtr<nsWindow> window = get_window_for_gdk_window(event->window);
    5850               0 :     if (!window)
    5851               0 :         return FALSE;
    5852                 : 
    5853               0 :     window->OnVisibilityNotifyEvent(widget, event);
    5854                 : 
    5855               0 :     return TRUE;
    5856                 : }
    5857                 : 
    5858                 : static void
    5859               0 : hierarchy_changed_cb (GtkWidget *widget,
    5860                 :                       GtkWidget *previous_toplevel)
    5861                 : {
    5862               0 :     GtkWidget *toplevel = gtk_widget_get_toplevel(widget);
    5863               0 :     GdkWindowState old_window_state = GDK_WINDOW_STATE_WITHDRAWN;
    5864                 :     GdkEventWindowState event;
    5865                 : 
    5866               0 :     event.new_window_state = GDK_WINDOW_STATE_WITHDRAWN;
    5867                 : 
    5868               0 :     if (GTK_IS_WINDOW(previous_toplevel)) {
    5869               0 :         g_signal_handlers_disconnect_by_func(previous_toplevel,
    5870                 :                                              FuncToGpointer(window_state_event_cb),
    5871               0 :                                              widget);
    5872               0 :         GdkWindow *win = gtk_widget_get_window(previous_toplevel);
    5873               0 :         if (win) {
    5874               0 :             old_window_state = gdk_window_get_state(win);
    5875                 :         }
    5876                 :     }
    5877                 : 
    5878               0 :     if (GTK_IS_WINDOW(toplevel)) {
    5879               0 :         g_signal_connect_swapped(toplevel, "window-state-event",
    5880               0 :                                  G_CALLBACK(window_state_event_cb), widget);
    5881               0 :         GdkWindow *win = gtk_widget_get_window(toplevel);
    5882               0 :         if (win) {
    5883               0 :             event.new_window_state = gdk_window_get_state(win);
    5884                 :         }
    5885                 :     }
    5886                 : 
    5887                 :     event.changed_mask = static_cast<GdkWindowState>
    5888               0 :         (old_window_state ^ event.new_window_state);
    5889                 : 
    5890               0 :     if (event.changed_mask) {
    5891               0 :         event.type = GDK_WINDOW_STATE;
    5892               0 :         event.window = NULL;
    5893               0 :         event.send_event = TRUE;
    5894               0 :         window_state_event_cb(widget, &event);
    5895                 :     }
    5896               0 : }
    5897                 : 
    5898                 : static gboolean
    5899               0 : window_state_event_cb (GtkWidget *widget, GdkEventWindowState *event)
    5900                 : {
    5901               0 :     nsRefPtr<nsWindow> window = get_window_for_gtk_widget(widget);
    5902               0 :     if (!window)
    5903               0 :         return FALSE;
    5904                 : 
    5905               0 :     window->OnWindowStateEvent(widget, event);
    5906                 : 
    5907               0 :     return FALSE;
    5908                 : }
    5909                 : 
    5910                 : static void
    5911               0 : theme_changed_cb (GtkSettings *settings, GParamSpec *pspec, nsWindow *data)
    5912                 : {
    5913               0 :     nsRefPtr<nsWindow> window = data;
    5914               0 :     window->ThemeChanged();
    5915               0 : }
    5916                 : 
    5917                 : //////////////////////////////////////////////////////////////////////
    5918                 : // These are all of our drag and drop operations
    5919                 : 
    5920                 : void
    5921               0 : nsWindow::InitDragEvent(nsDragEvent &aEvent)
    5922                 : {
    5923                 :     // set the keyboard modifiers
    5924               0 :     guint modifierState = KeymapWrapper::GetCurrentModifierState();
    5925               0 :     KeymapWrapper::InitInputEvent(aEvent, modifierState);
    5926               0 : }
    5927                 : 
    5928                 : // This will update the drag action based on the information in the
    5929                 : // drag context.  Gtk gets this from a combination of the key settings
    5930                 : // and what the source is offering.
    5931                 : 
    5932                 : void
    5933               0 : nsWindow::UpdateDragStatus(GdkDragContext *aDragContext,
    5934                 :                            nsIDragService *aDragService)
    5935                 : {
    5936                 :     // default is to do nothing
    5937               0 :     int action = nsIDragService::DRAGDROP_ACTION_NONE;
    5938               0 :     GdkDragAction gdkAction = gdk_drag_context_get_actions(aDragContext);
    5939                 : 
    5940                 :     // set the default just in case nothing matches below
    5941               0 :     if (gdkAction & GDK_ACTION_DEFAULT)
    5942               0 :         action = nsIDragService::DRAGDROP_ACTION_MOVE;
    5943                 : 
    5944                 :     // first check to see if move is set
    5945               0 :     if (gdkAction & GDK_ACTION_MOVE)
    5946               0 :         action = nsIDragService::DRAGDROP_ACTION_MOVE;
    5947                 : 
    5948                 :     // then fall to the others
    5949               0 :     else if (gdkAction & GDK_ACTION_LINK)
    5950               0 :         action = nsIDragService::DRAGDROP_ACTION_LINK;
    5951                 : 
    5952                 :     // copy is ctrl
    5953               0 :     else if (gdkAction & GDK_ACTION_COPY)
    5954               0 :         action = nsIDragService::DRAGDROP_ACTION_COPY;
    5955                 : 
    5956                 :     // update the drag information
    5957               0 :     nsCOMPtr<nsIDragSession> session;
    5958               0 :     aDragService->GetCurrentSession(getter_AddRefs(session));
    5959                 : 
    5960               0 :     if (session)
    5961               0 :         session->SetDragAction(action);
    5962               0 : }
    5963                 : 
    5964                 : 
    5965                 : static gboolean
    5966               0 : drag_motion_event_cb(GtkWidget *aWidget,
    5967                 :                      GdkDragContext *aDragContext,
    5968                 :                      gint aX,
    5969                 :                      gint aY,
    5970                 :                      guint aTime,
    5971                 :                      gpointer aData)
    5972                 : {
    5973               0 :     nsRefPtr<nsWindow> window = get_window_for_gtk_widget(aWidget);
    5974               0 :     if (!window)
    5975               0 :         return FALSE;
    5976                 : 
    5977                 :     return window->OnDragMotionEvent(aWidget,
    5978                 :                                      aDragContext,
    5979               0 :                                      aX, aY, aTime, aData);
    5980                 : }
    5981                 : 
    5982                 : static void
    5983               0 : drag_leave_event_cb(GtkWidget *aWidget,
    5984                 :                     GdkDragContext *aDragContext,
    5985                 :                     guint aTime,
    5986                 :                     gpointer aData)
    5987                 : {
    5988               0 :     nsRefPtr<nsWindow> window = get_window_for_gtk_widget(aWidget);
    5989               0 :     if (!window)
    5990                 :         return;
    5991                 : 
    5992               0 :     window->OnDragLeaveEvent(aWidget, aDragContext, aTime, aData);
    5993                 : }
    5994                 : 
    5995                 : 
    5996                 : static gboolean
    5997               0 : drag_drop_event_cb(GtkWidget *aWidget,
    5998                 :                    GdkDragContext *aDragContext,
    5999                 :                    gint aX,
    6000                 :                    gint aY,
    6001                 :                    guint aTime,
    6002                 :                    gpointer aData)
    6003                 : {
    6004               0 :     nsRefPtr<nsWindow> window = get_window_for_gtk_widget(aWidget);
    6005               0 :     if (!window)
    6006               0 :         return FALSE;
    6007                 : 
    6008                 :     return window->OnDragDropEvent(aWidget,
    6009                 :                                    aDragContext,
    6010               0 :                                    aX, aY, aTime, aData);
    6011                 : }
    6012                 : 
    6013                 : static void
    6014               0 : drag_data_received_event_cb(GtkWidget *aWidget,
    6015                 :                             GdkDragContext *aDragContext,
    6016                 :                             gint aX,
    6017                 :                             gint aY,
    6018                 :                             GtkSelectionData  *aSelectionData,
    6019                 :                             guint aInfo,
    6020                 :                             guint aTime,
    6021                 :                             gpointer aData)
    6022                 : {
    6023               0 :     nsRefPtr<nsWindow> window = get_window_for_gtk_widget(aWidget);
    6024               0 :     if (!window)
    6025                 :         return;
    6026                 : 
    6027                 :     window->OnDragDataReceivedEvent(aWidget,
    6028                 :                                     aDragContext,
    6029                 :                                     aX, aY,
    6030                 :                                     aSelectionData,
    6031               0 :                                     aInfo, aTime, aData);
    6032                 : }
    6033                 : 
    6034                 : static nsresult
    6035               0 : initialize_prefs(void)
    6036                 : {
    6037                 :     gRaiseWindows =
    6038               0 :         Preferences::GetBool("mozilla.widget.raise-on-setfocus", true);
    6039                 :     gDisableNativeTheme =
    6040               0 :         Preferences::GetBool("mozilla.widget.disable-native-theme", false);
    6041                 : 
    6042               0 :     return NS_OK;
    6043                 : }
    6044                 : 
    6045                 : void
    6046               0 : nsWindow::FireDragLeaveTimer(void)
    6047                 : {
    6048               0 :     LOGDRAG(("nsWindow::FireDragLeaveTimer(%p)\n", (void*)this));
    6049                 : 
    6050               0 :     mDragLeaveTimer = nsnull;
    6051                 : 
    6052                 :     // clean up any pending drag motion window info
    6053               0 :     if (sLastDragMotionWindow) {
    6054               0 :         nsRefPtr<nsWindow> kungFuDeathGrip = sLastDragMotionWindow;
    6055                 :         // send our leave signal
    6056               0 :         sLastDragMotionWindow->OnDragLeave();
    6057               0 :         sLastDragMotionWindow = 0;
    6058                 :     }
    6059               0 : }
    6060                 : 
    6061                 : /* static */
    6062                 : void
    6063               0 : nsWindow::DragLeaveTimerCallback(nsITimer *aTimer, void *aClosure)
    6064                 : {
    6065               0 :     nsRefPtr<nsWindow> window = static_cast<nsWindow *>(aClosure);
    6066               0 :     window->FireDragLeaveTimer();
    6067               0 : }
    6068                 : 
    6069                 : static GdkWindow *
    6070               0 : get_inner_gdk_window (GdkWindow *aWindow,
    6071                 :                       gint x, gint y,
    6072                 :                       gint *retx, gint *rety)
    6073                 : {
    6074                 :     gint cx, cy, cw, ch;
    6075               0 :     GList *children = gdk_window_peek_children(aWindow);
    6076               0 :     for (GList *child = g_list_last(children);
    6077                 :          child;
    6078                 :          child = g_list_previous(child)) {
    6079               0 :         GdkWindow *childWindow = (GdkWindow *) child->data;
    6080               0 :         if (get_window_for_gdk_window(childWindow)) {
    6081                 : #if defined(MOZ_WIDGET_GTK2)
    6082               0 :             gdk_window_get_geometry(childWindow, &cx, &cy, &cw, &ch, NULL);
    6083                 : #else
    6084                 :             gdk_window_get_geometry(childWindow, &cx, &cy, &cw, &ch);
    6085                 : #endif
    6086               0 :             if ((cx < x) && (x < (cx + cw)) &&
    6087                 :                 (cy < y) && (y < (cy + ch)) &&
    6088               0 :                 gdk_window_is_visible(childWindow)) {
    6089                 :                 return get_inner_gdk_window(childWindow,
    6090                 :                                             x - cx, y - cy,
    6091               0 :                                             retx, rety);
    6092                 :             }
    6093                 :         }
    6094                 :     }
    6095               0 :     *retx = x;
    6096               0 :     *rety = y;
    6097               0 :     return aWindow;
    6098                 : }
    6099                 : 
    6100                 : static inline bool
    6101               0 : is_context_menu_key(const nsKeyEvent& aKeyEvent)
    6102                 : {
    6103                 :     return ((aKeyEvent.keyCode == NS_VK_F10 && aKeyEvent.isShift &&
    6104               0 :              !aKeyEvent.isControl && !aKeyEvent.isMeta && !aKeyEvent.isAlt) ||
    6105               0 :             (aKeyEvent.keyCode == NS_VK_CONTEXT_MENU && !aKeyEvent.isShift &&
    6106               0 :              !aKeyEvent.isControl && !aKeyEvent.isMeta && !aKeyEvent.isAlt));
    6107                 : }
    6108                 : 
    6109                 : static int
    6110               0 : is_parent_ungrab_enter(GdkEventCrossing *aEvent)
    6111                 : {
    6112                 :     return (GDK_CROSSING_UNGRAB == aEvent->mode) &&
    6113                 :         ((GDK_NOTIFY_ANCESTOR == aEvent->detail) ||
    6114               0 :          (GDK_NOTIFY_VIRTUAL == aEvent->detail));
    6115                 : 
    6116                 : }
    6117                 : 
    6118                 : static int
    6119               0 : is_parent_grab_leave(GdkEventCrossing *aEvent)
    6120                 : {
    6121                 :     return (GDK_CROSSING_GRAB == aEvent->mode) &&
    6122                 :         ((GDK_NOTIFY_ANCESTOR == aEvent->detail) ||
    6123               0 :             (GDK_NOTIFY_VIRTUAL == aEvent->detail));
    6124                 : }
    6125                 : 
    6126                 : #ifdef ACCESSIBILITY
    6127                 : void
    6128               0 : nsWindow::CreateRootAccessible()
    6129                 : {
    6130               0 :     if (mIsTopLevel && !mRootAccessible) {
    6131               0 :         LOG(("nsWindow:: Create Toplevel Accessibility\n"));
    6132               0 :         nsAccessible *acc = DispatchAccessibleEvent();
    6133                 : 
    6134               0 :         if (acc) {
    6135               0 :             mRootAccessible = acc;
    6136                 :         }
    6137                 :     }
    6138               0 : }
    6139                 : 
    6140                 : nsAccessible*
    6141               0 : nsWindow::DispatchAccessibleEvent()
    6142                 : {
    6143               0 :     nsAccessibleEvent event(true, NS_GETACCESSIBLE, this);
    6144                 : 
    6145                 :     nsEventStatus status;
    6146               0 :     DispatchEvent(&event, status);
    6147                 : 
    6148               0 :     return event.mAccessible;
    6149                 : }
    6150                 : 
    6151                 : void
    6152               0 : nsWindow::DispatchEventToRootAccessible(PRUint32 aEventType)
    6153                 : {
    6154               0 :     if (!a11y::ShouldA11yBeEnabled()) {
    6155               0 :         return;
    6156                 :     }
    6157                 : 
    6158                 :     nsCOMPtr<nsIAccessibilityService> accService =
    6159               0 :         do_GetService("@mozilla.org/accessibilityService;1");
    6160               0 :     if (!accService) {
    6161                 :         return;
    6162                 :     }
    6163                 : 
    6164                 :     // Get the root document accessible and fire event to it.
    6165               0 :     nsAccessible *acc = DispatchAccessibleEvent();
    6166               0 :     if (acc) {
    6167               0 :         accService->FireAccessibleEvent(aEventType, acc);
    6168                 :     }
    6169                 : }
    6170                 : 
    6171                 : void
    6172               0 : nsWindow::DispatchActivateEventAccessible(void)
    6173                 : {
    6174               0 :     DispatchEventToRootAccessible(nsIAccessibleEvent::EVENT_WINDOW_ACTIVATE);
    6175               0 : }
    6176                 : 
    6177                 : void
    6178               0 : nsWindow::DispatchDeactivateEventAccessible(void)
    6179                 : {
    6180               0 :     DispatchEventToRootAccessible(nsIAccessibleEvent::EVENT_WINDOW_DEACTIVATE);
    6181               0 : }
    6182                 : 
    6183                 : void
    6184               0 : nsWindow::DispatchMaximizeEventAccessible(void)
    6185                 : {
    6186               0 :     DispatchEventToRootAccessible(nsIAccessibleEvent::EVENT_WINDOW_MAXIMIZE);
    6187               0 : }
    6188                 : 
    6189                 : void
    6190               0 : nsWindow::DispatchMinimizeEventAccessible(void)
    6191                 : {
    6192               0 :     DispatchEventToRootAccessible(nsIAccessibleEvent::EVENT_WINDOW_MINIMIZE);
    6193               0 : }
    6194                 : 
    6195                 : void
    6196               0 : nsWindow::DispatchRestoreEventAccessible(void)
    6197                 : {
    6198               0 :     DispatchEventToRootAccessible(nsIAccessibleEvent::EVENT_WINDOW_RESTORE);
    6199               0 : }
    6200                 : 
    6201                 : #endif /* #ifdef ACCESSIBILITY */
    6202                 : 
    6203                 : // nsChildWindow class
    6204                 : 
    6205               0 : nsChildWindow::nsChildWindow()
    6206                 : {
    6207               0 : }
    6208                 : 
    6209               0 : nsChildWindow::~nsChildWindow()
    6210                 : {
    6211               0 : }
    6212                 : 
    6213                 : NS_IMETHODIMP
    6214               0 : nsWindow::ResetInputState()
    6215                 : {
    6216               0 :     return mIMModule ? mIMModule->ResetInputState(this) : NS_OK;
    6217                 : }
    6218                 : 
    6219                 : NS_IMETHODIMP_(void)
    6220               0 : nsWindow::SetInputContext(const InputContext& aContext,
    6221                 :                           const InputContextAction& aAction)
    6222                 : {
    6223               0 :     if (!mIMModule) {
    6224               0 :         return;
    6225                 :     }
    6226               0 :     mIMModule->SetInputContext(this, &aContext, &aAction);
    6227                 : }
    6228                 : 
    6229                 : NS_IMETHODIMP_(InputContext)
    6230               0 : nsWindow::GetInputContext()
    6231                 : {
    6232               0 :   InputContext context;
    6233               0 :   if (!mIMModule) {
    6234               0 :       context.mIMEState.mEnabled = IMEState::DISABLED;
    6235               0 :       context.mIMEState.mOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
    6236                 :   } else {
    6237               0 :       context = mIMModule->GetInputContext();
    6238                 :   }
    6239                 :   return context;
    6240                 : }
    6241                 : 
    6242                 : NS_IMETHODIMP
    6243               0 : nsWindow::CancelIMEComposition()
    6244                 : {
    6245               0 :     return mIMModule ? mIMModule->CancelIMEComposition(this) : NS_OK;
    6246                 : }
    6247                 : 
    6248                 : NS_IMETHODIMP
    6249               0 : nsWindow::OnIMEFocusChange(bool aFocus)
    6250                 : {
    6251               0 :     if (mIMModule) {
    6252               0 :       mIMModule->OnFocusChangeInGecko(aFocus);
    6253                 :     }
    6254                 :     // XXX Return NS_ERROR_NOT_IMPLEMENTED, see bug 496360.
    6255               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    6256                 : }
    6257                 : 
    6258                 : NS_IMETHODIMP
    6259               0 : nsWindow::GetToggledKeyState(PRUint32 aKeyCode, bool* aLEDState)
    6260                 : {
    6261               0 :     NS_ENSURE_ARG_POINTER(aLEDState);
    6262                 : 
    6263                 :     KeymapWrapper::Modifiers modifier;
    6264               0 :     switch (aKeyCode) {
    6265               0 :         case NS_VK_CAPS_LOCK:   modifier = KeymapWrapper::CAPS_LOCK;   break;
    6266               0 :         case NS_VK_NUM_LOCK:    modifier = KeymapWrapper::NUM_LOCK;    break;
    6267               0 :         case NS_VK_SCROLL_LOCK: modifier = KeymapWrapper::SCROLL_LOCK; break;
    6268               0 :         default: return NS_ERROR_INVALID_ARG;
    6269                 :     }
    6270                 : 
    6271                 :     *aLEDState =
    6272               0 :         KeymapWrapper::AreModifiersCurrentlyActive(modifier);
    6273               0 :     return NS_OK;
    6274                 : }
    6275                 : 
    6276                 : #if defined(MOZ_X11) && defined(MOZ_WIDGET_GTK2)
    6277                 : /* static */ already_AddRefed<gfxASurface>
    6278               0 : nsWindow::GetSurfaceForGdkDrawable(GdkDrawable* aDrawable,
    6279                 :                                    const nsIntSize& aSize)
    6280                 : {
    6281               0 :     GdkVisual* visual = gdk_drawable_get_visual(aDrawable);
    6282                 :     Screen* xScreen =
    6283               0 :         gdk_x11_screen_get_xscreen(gdk_drawable_get_screen(aDrawable));
    6284               0 :     Display* xDisplay = DisplayOfScreen(xScreen);
    6285               0 :     Drawable xDrawable = gdk_x11_drawable_get_xid(aDrawable);
    6286                 : 
    6287               0 :     gfxASurface* result = nsnull;
    6288                 : 
    6289               0 :     if (visual) {
    6290               0 :         Visual* xVisual = gdk_x11_visual_get_xvisual(visual);
    6291                 : 
    6292                 :         result = new gfxXlibSurface(xDisplay, xDrawable, xVisual,
    6293               0 :                                     gfxIntSize(aSize.width, aSize.height));
    6294                 :     } else {
    6295                 :         // no visual? we must be using an xrender format.  Find a format
    6296                 :         // for this depth.
    6297               0 :         XRenderPictFormat *pf = NULL;
    6298               0 :         switch (gdk_drawable_get_depth(aDrawable)) {
    6299                 :             case 32:
    6300               0 :                 pf = XRenderFindStandardFormat(xDisplay, PictStandardARGB32);
    6301               0 :                 break;
    6302                 :             case 24:
    6303               0 :                 pf = XRenderFindStandardFormat(xDisplay, PictStandardRGB24);
    6304               0 :                 break;
    6305                 :             default:
    6306               0 :                 NS_ERROR("Don't know how to handle the given depth!");
    6307               0 :                 break;
    6308                 :         }
    6309                 : 
    6310                 :         result = new gfxXlibSurface(xScreen, xDrawable, pf,
    6311               0 :                                     gfxIntSize(aSize.width, aSize.height));
    6312                 :     }
    6313                 : 
    6314               0 :     NS_IF_ADDREF(result);
    6315               0 :     return result;
    6316                 : }
    6317                 : #endif
    6318                 : 
    6319                 : // return the gfxASurface for rendering to this widget
    6320                 : gfxASurface*
    6321                 : #if defined(MOZ_WIDGET_GTK2)
    6322               0 : nsWindow::GetThebesSurface()
    6323                 : #else
    6324                 : nsWindow::GetThebesSurface(cairo_t *cr)
    6325                 : #endif
    6326                 : {
    6327               0 :     if (!mGdkWindow)
    6328               0 :         return nsnull;
    6329                 : 
    6330                 : #if !defined(MOZ_WIDGET_GTK2)
    6331                 :     cairo_surface_t *surf = cairo_get_target(cr);
    6332                 :     if (cairo_surface_status(surf) != CAIRO_STATUS_SUCCESS) {
    6333                 :       NS_NOTREACHED("Missing cairo target?");
    6334                 :       return NULL;
    6335                 :     }
    6336                 : #endif // MOZ_WIDGET_GTK2
    6337                 : 
    6338                 : #ifdef MOZ_X11
    6339                 :     gint width, height;
    6340                 : 
    6341                 : #if defined(MOZ_WIDGET_GTK2)
    6342               0 :     gdk_drawable_get_size(GDK_DRAWABLE(mGdkWindow), &width, &height);
    6343                 : #else
    6344                 :     width = gdk_window_get_width(mGdkWindow);
    6345                 :     height = gdk_window_get_height(mGdkWindow);
    6346                 : #endif
    6347                 : 
    6348                 :     // Owen Taylor says this is the right thing to do!
    6349               0 :     width = NS_MIN(32767, width);
    6350               0 :     height = NS_MIN(32767, height);
    6351               0 :     gfxIntSize size(width, height);
    6352                 : 
    6353               0 :     GdkVisual *gdkVisual = gdk_window_get_visual(mGdkWindow);
    6354               0 :     Visual* visual = gdk_x11_visual_get_xvisual(gdkVisual);
    6355                 : 
    6356                 : #  ifdef MOZ_HAVE_SHMIMAGE
    6357               0 :     bool usingShm = false;
    6358               0 :     if (nsShmImage::UseShm()) {
    6359                 :         // EnsureShmImage() is a dangerous interface, but we guarantee
    6360                 :         // that the thebes surface and the shmimage have the same
    6361                 :         // lifetime
    6362                 :         mThebesSurface =
    6363                 :             nsShmImage::EnsureShmImage(size,
    6364               0 :                                        visual, gdk_visual_get_depth(gdkVisual),
    6365               0 :                                        mShmImage);
    6366               0 :         usingShm = mThebesSurface != nsnull;
    6367                 :     }
    6368               0 :     if (!usingShm)
    6369                 : #  endif  // MOZ_HAVE_SHMIMAGE
    6370                 : 
    6371                 : #if defined(MOZ_WIDGET_GTK2)
    6372                 :     mThebesSurface = new gfxXlibSurface
    6373               0 :         (GDK_WINDOW_XDISPLAY(mGdkWindow),
    6374               0 :          gdk_x11_window_get_xid(mGdkWindow),
    6375                 :          visual,
    6376               0 :          size);
    6377                 : #else
    6378                 : #if MOZ_TREE_CAIRO
    6379                 : #error "cairo-gtk3 target must be built with --enable-system-cairo"
    6380                 : #else
    6381                 :     mThebesSurface = gfxASurface::Wrap(surf);
    6382                 : #endif
    6383                 : #endif
    6384                 : 
    6385                 : #endif
    6386                 : 
    6387                 :     // if the surface creation is reporting an error, then
    6388                 :     // we don't have a surface to give back
    6389               0 :     if (mThebesSurface && mThebesSurface->CairoStatus() != 0) {
    6390               0 :         mThebesSurface = nsnull;
    6391                 :     }
    6392                 : 
    6393               0 :     return mThebesSurface;
    6394                 : }
    6395                 : 
    6396                 : // Code shared begin BeginMoveDrag and BeginResizeDrag
    6397                 : bool
    6398               0 : nsWindow::GetDragInfo(nsMouseEvent* aMouseEvent,
    6399                 :                       GdkWindow** aWindow, gint* aButton,
    6400                 :                       gint* aRootX, gint* aRootY)
    6401                 : {
    6402               0 :     if (aMouseEvent->button != nsMouseEvent::eLeftButton) {
    6403                 :         // we can only begin a move drag with the left mouse button
    6404               0 :         return false;
    6405                 :     }
    6406               0 :     *aButton = 1;
    6407                 : 
    6408                 :     // get the gdk window for this widget
    6409               0 :     GdkWindow* gdk_window = mGdkWindow;
    6410               0 :     if (!gdk_window) {
    6411               0 :         return false;
    6412                 :     }
    6413               0 :     NS_ABORT_IF_FALSE(GDK_IS_WINDOW(gdk_window), "must really be window");
    6414                 : 
    6415                 :     // find the top-level window
    6416               0 :     gdk_window = gdk_window_get_toplevel(gdk_window);
    6417               0 :     NS_ABORT_IF_FALSE(gdk_window,
    6418                 :                       "gdk_window_get_toplevel should not return null");
    6419               0 :     *aWindow = gdk_window;
    6420                 : 
    6421               0 :     if (!aMouseEvent->widget) {
    6422               0 :         return false;
    6423                 :     }
    6424                 : 
    6425                 :     // FIXME: It would be nice to have the widget position at the time
    6426                 :     // of the event, but it's relatively unlikely that the widget has
    6427                 :     // moved since the mousedown.  (On the other hand, it's quite likely
    6428                 :     // that the mouse has moved, which is why we use the mouse position
    6429                 :     // from the event.)
    6430               0 :     nsIntPoint offset = aMouseEvent->widget->WidgetToScreenOffset();
    6431               0 :     *aRootX = aMouseEvent->refPoint.x + offset.x;
    6432               0 :     *aRootY = aMouseEvent->refPoint.y + offset.y;
    6433                 : 
    6434               0 :     return true;
    6435                 : }
    6436                 : 
    6437                 : NS_IMETHODIMP
    6438               0 : nsWindow::BeginMoveDrag(nsMouseEvent* aEvent)
    6439                 : {
    6440               0 :     NS_ABORT_IF_FALSE(aEvent, "must have event");
    6441               0 :     NS_ABORT_IF_FALSE(aEvent->eventStructType == NS_MOUSE_EVENT,
    6442                 :                       "event must have correct struct type");
    6443                 : 
    6444                 :     GdkWindow *gdk_window;
    6445                 :     gint button, screenX, screenY;
    6446               0 :     if (!GetDragInfo(aEvent, &gdk_window, &button, &screenX, &screenY)) {
    6447               0 :         return NS_ERROR_FAILURE;
    6448                 :     }
    6449                 : 
    6450                 :     // tell the window manager to start the move
    6451                 :     gdk_window_begin_move_drag(gdk_window, button, screenX, screenY,
    6452               0 :                                aEvent->time);
    6453                 : 
    6454               0 :     return NS_OK;
    6455                 : }
    6456                 : 
    6457                 : NS_IMETHODIMP
    6458               0 : nsWindow::BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical)
    6459                 : {
    6460               0 :     NS_ENSURE_ARG_POINTER(aEvent);
    6461                 : 
    6462               0 :     if (aEvent->eventStructType != NS_MOUSE_EVENT) {
    6463                 :         // you can only begin a resize drag with a mouse event
    6464               0 :         return NS_ERROR_INVALID_ARG;
    6465                 :     }
    6466                 : 
    6467               0 :     nsMouseEvent* mouse_event = static_cast<nsMouseEvent*>(aEvent);
    6468                 : 
    6469                 :     GdkWindow *gdk_window;
    6470                 :     gint button, screenX, screenY;
    6471               0 :     if (!GetDragInfo(mouse_event, &gdk_window, &button, &screenX, &screenY)) {
    6472               0 :         return NS_ERROR_FAILURE;
    6473                 :     }
    6474                 : 
    6475                 :     // work out what GdkWindowEdge we're talking about
    6476                 :     GdkWindowEdge window_edge;
    6477               0 :     if (aVertical < 0) {
    6478               0 :         if (aHorizontal < 0) {
    6479               0 :             window_edge = GDK_WINDOW_EDGE_NORTH_WEST;
    6480               0 :         } else if (aHorizontal == 0) {
    6481               0 :             window_edge = GDK_WINDOW_EDGE_NORTH;
    6482                 :         } else {
    6483               0 :             window_edge = GDK_WINDOW_EDGE_NORTH_EAST;
    6484                 :         }
    6485               0 :     } else if (aVertical == 0) {
    6486               0 :         if (aHorizontal < 0) {
    6487               0 :             window_edge = GDK_WINDOW_EDGE_WEST;
    6488               0 :         } else if (aHorizontal == 0) {
    6489               0 :             return NS_ERROR_INVALID_ARG;
    6490                 :         } else {
    6491               0 :             window_edge = GDK_WINDOW_EDGE_EAST;
    6492                 :         }
    6493                 :     } else {
    6494               0 :         if (aHorizontal < 0) {
    6495               0 :             window_edge = GDK_WINDOW_EDGE_SOUTH_WEST;
    6496               0 :         } else if (aHorizontal == 0) {
    6497               0 :             window_edge = GDK_WINDOW_EDGE_SOUTH;
    6498                 :         } else {
    6499               0 :             window_edge = GDK_WINDOW_EDGE_SOUTH_EAST;
    6500                 :         }
    6501                 :     }
    6502                 : 
    6503                 :     // tell the window manager to start the resize
    6504                 :     gdk_window_begin_resize_drag(gdk_window, window_edge, button,
    6505               0 :                                  screenX, screenY, aEvent->time);
    6506                 : 
    6507               0 :     return NS_OK;
    6508                 : }
    6509                 : 
    6510                 : void
    6511               0 : nsWindow::ClearCachedResources()
    6512                 : {
    6513               0 :     if (mLayerManager &&
    6514               0 :         mLayerManager->GetBackendType() == LayerManager::LAYERS_BASIC) {
    6515               0 :         static_cast<BasicLayerManager*> (mLayerManager.get())->
    6516               0 :             ClearCachedResources();
    6517                 :     }
    6518                 : 
    6519               0 :     GList* children = gdk_window_peek_children(mGdkWindow);
    6520               0 :     for (GList* list = children; list; list = list->next) {
    6521               0 :         nsWindow* window = get_window_for_gdk_window(GDK_WINDOW(list->data));
    6522               0 :         if (window) {
    6523               0 :             window->ClearCachedResources();
    6524                 :         }
    6525                 :     }
    6526            4392 : }

Generated by: LCOV version 1.7