LCOV - app.info - widget/gtk2/nsWindow.cpp

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-07-07 | 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