2002-04-27 20:26:10 +04:00
|
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
|
/* vim:expandtab:shiftwidth=4:tabstop=4:
|
|
|
|
|
*/
|
2012-05-21 15:12:37 +04:00
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2001-07-26 02:05:10 +04:00
|
|
|
|
|
2013-12-09 06:52:54 +04:00
|
|
|
|
#include "mozilla/ArrayUtils.h"
|
2015-04-29 23:29:34 +03:00
|
|
|
|
#include "mozilla/EventForwards.h"
|
2013-09-25 15:21:20 +04:00
|
|
|
|
#include "mozilla/MiscEvents.h"
|
2013-09-25 15:21:18 +04:00
|
|
|
|
#include "mozilla/MouseEvents.h"
|
2013-09-25 15:21:19 +04:00
|
|
|
|
#include "mozilla/TextEvents.h"
|
2015-04-29 23:29:34 +03:00
|
|
|
|
#include "mozilla/TouchEvents.h"
|
2015-11-06 00:24:24 +03:00
|
|
|
|
#include "mozilla/UniquePtrExtensions.h"
|
2013-01-15 16:22:03 +04:00
|
|
|
|
#include <algorithm>
|
2011-10-11 09:50:08 +04:00
|
|
|
|
|
2015-02-14 14:37:32 +03:00
|
|
|
|
#include "GeckoProfiler.h"
|
|
|
|
|
|
2005-03-16 01:24:20 +03:00
|
|
|
|
#include "prlink.h"
|
2007-02-09 04:33:26 +03:00
|
|
|
|
#include "nsGTKToolkit.h"
|
2002-01-23 09:39:48 +03:00
|
|
|
|
#include "nsIRollupListener.h"
|
2005-03-16 04:50:15 +03:00
|
|
|
|
#include "nsIDOMNode.h"
|
2001-07-26 02:05:10 +04:00
|
|
|
|
|
2002-08-10 20:18:44 +04:00
|
|
|
|
#include "nsWidgetsCID.h"
|
2009-04-21 04:54:46 +04:00
|
|
|
|
#include "nsDragService.h"
|
2012-08-15 22:52:42 +04:00
|
|
|
|
#include "nsIWidgetListener.h"
|
2015-02-10 10:14:00 +03:00
|
|
|
|
#include "nsIScreenManager.h"
|
2015-08-11 10:40:34 +03:00
|
|
|
|
#include "SystemTimeConverter.h"
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2001-12-12 06:03:05 +03:00
|
|
|
|
#include "nsGtkKeyUtils.h"
|
2002-01-28 09:47:47 +03:00
|
|
|
|
#include "nsGtkCursors.h"
|
2015-07-16 03:26:00 +03:00
|
|
|
|
#include "nsScreenGtk.h"
|
2001-12-12 06:03:05 +03:00
|
|
|
|
|
2009-01-03 10:37:52 +03:00
|
|
|
|
#include <gtk/gtk.h>
|
2012-09-14 05:56:59 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 3)
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#include <gtk/gtkx.h>
|
|
|
|
|
#endif
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#ifdef MOZ_X11
|
2001-12-04 19:58:04 +03:00
|
|
|
|
#include <gdk/gdkx.h>
|
2010-04-01 08:38:51 +04:00
|
|
|
|
#include <X11/Xatom.h>
|
2010-09-24 05:00:06 +04:00
|
|
|
|
#include <X11/extensions/XShm.h>
|
2011-05-11 08:54:12 +04:00
|
|
|
|
#include <X11/extensions/shape.h>
|
2012-09-14 05:56:59 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 3)
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#include <gdk/gdkkeysyms-compat.h>
|
|
|
|
|
#endif
|
2010-03-28 19:50:39 +04:00
|
|
|
|
|
|
|
|
|
#ifdef AIX
|
|
|
|
|
#include <X11/keysym.h>
|
|
|
|
|
#else
|
2008-08-07 03:24:13 +04:00
|
|
|
|
#include <X11/XF86keysym.h>
|
2010-03-28 19:50:39 +04:00
|
|
|
|
#endif
|
|
|
|
|
|
2012-09-14 05:56:59 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#include "gtk2xtbin.h"
|
2012-09-14 05:56:59 +04:00
|
|
|
|
#endif
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#endif /* MOZ_X11 */
|
|
|
|
|
#include <gdk/gdkkeysyms.h>
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2009-07-22 04:44:55 +04:00
|
|
|
|
#include <gtk/gtkprivate.h>
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#endif
|
|
|
|
|
|
2011-10-14 22:11:22 +04:00
|
|
|
|
#include "nsGkAtoms.h"
|
2001-12-04 19:58:04 +03:00
|
|
|
|
|
2007-02-09 04:33:26 +03:00
|
|
|
|
#ifdef MOZ_ENABLE_STARTUP_NOTIFICATION
|
|
|
|
|
#define SN_API_NOT_YET_FROZEN
|
|
|
|
|
#include <startup-notification-1.0/libsn/sn.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2014-09-24 21:43:00 +04:00
|
|
|
|
#include "mozilla/Assertions.h"
|
2012-10-26 17:32:10 +04:00
|
|
|
|
#include "mozilla/Likely.h"
|
2011-05-28 11:03:00 +04:00
|
|
|
|
#include "mozilla/Preferences.h"
|
2005-03-16 01:24:20 +03:00
|
|
|
|
#include "nsIPrefService.h"
|
2011-11-26 23:48:55 +04:00
|
|
|
|
#include "nsIGConfService.h"
|
2002-06-04 15:02:26 +04:00
|
|
|
|
#include "nsIServiceManager.h"
|
2006-07-19 16:56:40 +04:00
|
|
|
|
#include "nsIStringBundle.h"
|
2004-09-23 01:14:56 +04:00
|
|
|
|
#include "nsGfxCIID.h"
|
2013-06-22 17:39:43 +04:00
|
|
|
|
#include "nsGtkUtils.h"
|
2009-09-25 20:52:11 +04:00
|
|
|
|
#include "nsIObserverService.h"
|
Bug 825928: Land layers refactoring. r=jrmuizel,bas,nical,mattwoodrow,roc,nrc,benwa,bjacob,jgilbert,kchen CLOSED TREE
Please contact Bas Schouten <bschouten@mozilla.com>, Nicolas Silva <nsilva@mozilla.com> or Nicholas Cameron <ncameron@mozilla.com> with general questions. Below is a rough list of authors to contact with specific questions.
Authors:
gfx/layers/Compositor.* gfx/layers/Effects.h - Compositor Interface - bas,nrc,nical
gfx/layers/d3d* - D3D9/D3D10 - bas
gfx/layers/ThebesLayer* - ThebesLayers - nrc,bas
gfx/layers/composite/* - CompositeLayers - nrc,nical
gfx/layers/client/* - Client - nrc,nical,bas
gfx/layers/*Image* - nical
gfx/layers/ipc ipc - IPC - nical
gfx/layers/opengl - CompositorOGL - nrc,nical
gfx/2d - bas,nrc
gfx/gl - GLContext - bjacob
dom/* layout/* - DOM - mattwoodrow
2013-04-10 13:20:52 +04:00
|
|
|
|
#include "mozilla/layers/LayersTypes.h"
|
2012-06-29 12:32:21 +04:00
|
|
|
|
#include "nsIIdleServiceInternal.h"
|
2010-04-01 17:58:42 +04:00
|
|
|
|
#include "nsIPropertyBag2.h"
|
2013-09-04 16:14:52 +04:00
|
|
|
|
#include "GLContext.h"
|
2013-10-08 03:15:59 +04:00
|
|
|
|
#include "gfx2DGlue.h"
|
2015-01-29 22:41:57 +03:00
|
|
|
|
#include "nsPluginNativeWindowGtk.h"
|
2009-10-06 22:47:46 +04:00
|
|
|
|
|
2003-04-23 09:28:41 +04:00
|
|
|
|
#ifdef ACCESSIBILITY
|
2012-12-02 04:58:25 +04:00
|
|
|
|
#include "mozilla/a11y/Accessible.h"
|
|
|
|
|
#include "mozilla/a11y/Platform.h"
|
2012-01-05 05:54:17 +04:00
|
|
|
|
#include "nsAccessibilityService.h"
|
2011-05-28 11:03:00 +04:00
|
|
|
|
|
|
|
|
|
using namespace mozilla;
|
2011-11-27 15:51:52 +04:00
|
|
|
|
using namespace mozilla::widget;
|
2003-04-23 09:28:41 +04:00
|
|
|
|
#endif
|
|
|
|
|
|
2002-08-10 22:07:20 +04:00
|
|
|
|
/* For SetIcon */
|
|
|
|
|
#include "nsAppDirectoryServiceDefs.h"
|
|
|
|
|
#include "nsXPIDLString.h"
|
|
|
|
|
#include "nsIFile.h"
|
|
|
|
|
|
2005-03-16 01:24:20 +03:00
|
|
|
|
/* SetCursor(imgIContainer*) */
|
|
|
|
|
#include <gdk/gdk.h>
|
2009-09-25 20:52:11 +04:00
|
|
|
|
#include <wchar.h>
|
2005-03-16 01:24:20 +03:00
|
|
|
|
#include "imgIContainer.h"
|
2005-08-23 06:11:54 +04:00
|
|
|
|
#include "nsGfxCIID.h"
|
2006-06-16 22:38:39 +04:00
|
|
|
|
#include "nsImageToPixbuf.h"
|
2005-03-16 01:24:20 +03:00
|
|
|
|
#include "nsIInterfaceRequestorUtils.h"
|
2005-09-01 02:56:37 +04:00
|
|
|
|
#include "nsAutoPtr.h"
|
2013-05-10 01:10:45 +04:00
|
|
|
|
#include "ClientLayerManager.h"
|
2005-03-16 01:24:20 +03:00
|
|
|
|
|
2005-11-29 23:12:29 +03:00
|
|
|
|
#include "gfxPlatformGtk.h"
|
2006-02-21 01:43:44 +03:00
|
|
|
|
#include "gfxContext.h"
|
|
|
|
|
#include "gfxImageSurface.h"
|
2011-01-26 09:26:37 +03:00
|
|
|
|
#include "gfxUtils.h"
|
2010-06-18 01:23:00 +04:00
|
|
|
|
#include "Layers.h"
|
|
|
|
|
#include "GLContextProvider.h"
|
2013-08-12 03:15:10 +04:00
|
|
|
|
#include "mozilla/gfx/2D.h"
|
2013-09-19 04:17:02 +04:00
|
|
|
|
#include "mozilla/layers/CompositorParent.h"
|
2005-11-29 23:12:29 +03:00
|
|
|
|
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#ifdef MOZ_X11
|
|
|
|
|
#include "gfxXlibSurface.h"
|
|
|
|
|
#endif
|
Bug 825928: Land layers refactoring. r=jrmuizel,bas,nical,mattwoodrow,roc,nrc,benwa,bjacob,jgilbert,kchen CLOSED TREE
Please contact Bas Schouten <bschouten@mozilla.com>, Nicolas Silva <nsilva@mozilla.com> or Nicholas Cameron <ncameron@mozilla.com> with general questions. Below is a rough list of authors to contact with specific questions.
Authors:
gfx/layers/Compositor.* gfx/layers/Effects.h - Compositor Interface - bas,nrc,nical
gfx/layers/d3d* - D3D9/D3D10 - bas
gfx/layers/ThebesLayer* - ThebesLayers - nrc,bas
gfx/layers/composite/* - CompositeLayers - nrc,nical
gfx/layers/client/* - Client - nrc,nical,bas
gfx/layers/*Image* - nical
gfx/layers/ipc ipc - IPC - nical
gfx/layers/opengl - CompositorOGL - nrc,nical
gfx/2d - bas,nrc
gfx/gl - GLContext - bjacob
dom/* layout/* - DOM - mattwoodrow
2013-04-10 13:20:52 +04:00
|
|
|
|
|
2010-10-27 08:56:31 +04:00
|
|
|
|
#include "nsShmImage.h"
|
|
|
|
|
|
2012-08-12 05:42:37 +04:00
|
|
|
|
#include "nsIDOMWheelEvent.h"
|
|
|
|
|
|
2014-03-14 17:13:32 +04:00
|
|
|
|
#include "NativeKeyBindings.h"
|
Bug 825928: Land layers refactoring. r=jrmuizel,bas,nical,mattwoodrow,roc,nrc,benwa,bjacob,jgilbert,kchen CLOSED TREE
Please contact Bas Schouten <bschouten@mozilla.com>, Nicolas Silva <nsilva@mozilla.com> or Nicholas Cameron <ncameron@mozilla.com> with general questions. Below is a rough list of authors to contact with specific questions.
Authors:
gfx/layers/Compositor.* gfx/layers/Effects.h - Compositor Interface - bas,nrc,nical
gfx/layers/d3d* - D3D9/D3D10 - bas
gfx/layers/ThebesLayer* - ThebesLayers - nrc,bas
gfx/layers/composite/* - CompositeLayers - nrc,nical
gfx/layers/client/* - Client - nrc,nical,bas
gfx/layers/*Image* - nical
gfx/layers/ipc ipc - IPC - nical
gfx/layers/opengl - CompositorOGL - nrc,nical
gfx/2d - bas,nrc
gfx/gl - GLContext - bjacob
dom/* layout/* - DOM - mattwoodrow
2013-04-10 13:20:52 +04:00
|
|
|
|
#include "nsWindow.h"
|
|
|
|
|
|
2015-01-21 07:53:00 +03:00
|
|
|
|
#include <dlfcn.h>
|
|
|
|
|
|
2015-01-13 06:45:10 +03:00
|
|
|
|
#include "mozilla/layers/APZCTreeManager.h"
|
|
|
|
|
|
2010-09-24 05:00:06 +04:00
|
|
|
|
using namespace mozilla;
|
2013-08-12 03:15:10 +04:00
|
|
|
|
using namespace mozilla::gfx;
|
2011-11-29 00:35:19 +04:00
|
|
|
|
using namespace mozilla::widget;
|
2013-05-10 01:10:45 +04:00
|
|
|
|
using namespace mozilla::layers;
|
2010-06-24 03:37:00 +04:00
|
|
|
|
using mozilla::gl::GLContext;
|
|
|
|
|
|
2009-02-16 04:10:24 +03:00
|
|
|
|
// Don't put more than this many rects in the dirty region, just fluff
|
|
|
|
|
// out to the bounding-box if there are more
|
|
|
|
|
#define MAX_RECTS_IN_REGION 100
|
|
|
|
|
|
2012-10-23 02:39:59 +04:00
|
|
|
|
const gint kEvents = GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK |
|
|
|
|
|
GDK_VISIBILITY_NOTIFY_MASK |
|
|
|
|
|
GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
|
|
|
|
|
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
|
2015-10-19 14:22:55 +03:00
|
|
|
|
#if GTK_CHECK_VERSION(3,4,0)
|
2014-07-07 13:54:13 +04:00
|
|
|
|
GDK_SMOOTH_SCROLL_MASK |
|
2015-04-29 23:29:34 +03:00
|
|
|
|
GDK_TOUCH_MASK |
|
2015-10-19 14:22:55 +03:00
|
|
|
|
#endif
|
2013-08-06 04:10:59 +04:00
|
|
|
|
GDK_SCROLL_MASK |
|
2015-08-12 04:35:38 +03:00
|
|
|
|
GDK_POINTER_MOTION_MASK |
|
|
|
|
|
GDK_PROPERTY_CHANGE_MASK;
|
2012-10-23 02:39:59 +04:00
|
|
|
|
|
2001-12-12 08:50:47 +03:00
|
|
|
|
/* utility functions */
|
2011-09-29 10:19:26 +04:00
|
|
|
|
static bool is_mouse_in_window(GdkWindow* aWindow,
|
2002-04-27 20:26:10 +04:00
|
|
|
|
gdouble aMouseX, gdouble aMouseY);
|
2002-01-27 23:30:56 +03:00
|
|
|
|
static nsWindow *get_window_for_gtk_widget(GtkWidget *widget);
|
|
|
|
|
static nsWindow *get_window_for_gdk_window(GdkWindow *window);
|
|
|
|
|
static GtkWidget *get_gtk_widget_for_gdk_window(GdkWindow *window);
|
2002-01-28 09:47:47 +03:00
|
|
|
|
static GdkCursor *get_gtk_cursor(nsCursor aCursor);
|
2001-12-12 01:22:48 +03:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
static GdkWindow *get_inner_gdk_window (GdkWindow *aWindow,
|
|
|
|
|
gint x, gint y,
|
|
|
|
|
gint *retx, gint *rety);
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2013-10-01 11:22:58 +04:00
|
|
|
|
static inline bool is_context_menu_key(const WidgetKeyboardEvent& inKeyEvent);
|
2002-12-15 01:23:06 +03:00
|
|
|
|
|
2003-09-30 18:58:39 +04:00
|
|
|
|
static int is_parent_ungrab_enter(GdkEventCrossing *aEvent);
|
|
|
|
|
static int is_parent_grab_leave(GdkEventCrossing *aEvent);
|
|
|
|
|
|
2011-12-14 14:22:15 +04:00
|
|
|
|
static void GetBrandName(nsXPIDLString& brandName);
|
|
|
|
|
|
2001-12-12 08:50:47 +03:00
|
|
|
|
/* callbacks from widgets */
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2001-12-12 01:22:48 +03:00
|
|
|
|
static gboolean expose_event_cb (GtkWidget *widget,
|
2002-04-27 20:26:10 +04:00
|
|
|
|
GdkEventExpose *event);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#else
|
|
|
|
|
static gboolean expose_event_cb (GtkWidget *widget,
|
|
|
|
|
cairo_t *rect);
|
|
|
|
|
#endif
|
2001-12-12 01:22:48 +03:00
|
|
|
|
static gboolean configure_event_cb (GtkWidget *widget,
|
2002-04-27 20:26:10 +04:00
|
|
|
|
GdkEventConfigure *event);
|
2009-05-15 06:14:45 +04:00
|
|
|
|
static void container_unrealize_cb (GtkWidget *widget);
|
2001-12-12 01:22:48 +03:00
|
|
|
|
static void size_allocate_cb (GtkWidget *widget,
|
2002-04-27 20:26:10 +04:00
|
|
|
|
GtkAllocation *allocation);
|
2001-12-12 01:22:48 +03:00
|
|
|
|
static gboolean delete_event_cb (GtkWidget *widget,
|
2002-04-27 20:26:10 +04:00
|
|
|
|
GdkEventAny *event);
|
2001-12-12 01:22:48 +03:00
|
|
|
|
static gboolean enter_notify_event_cb (GtkWidget *widget,
|
2002-04-27 20:26:10 +04:00
|
|
|
|
GdkEventCrossing *event);
|
2001-12-12 01:22:48 +03:00
|
|
|
|
static gboolean leave_notify_event_cb (GtkWidget *widget,
|
2002-04-27 20:26:10 +04:00
|
|
|
|
GdkEventCrossing *event);
|
2001-12-12 01:22:48 +03:00
|
|
|
|
static gboolean motion_notify_event_cb (GtkWidget *widget,
|
2002-04-27 20:26:10 +04:00
|
|
|
|
GdkEventMotion *event);
|
2001-12-12 01:22:48 +03:00
|
|
|
|
static gboolean button_press_event_cb (GtkWidget *widget,
|
2002-04-27 20:26:10 +04:00
|
|
|
|
GdkEventButton *event);
|
2001-12-12 01:22:48 +03:00
|
|
|
|
static gboolean button_release_event_cb (GtkWidget *widget,
|
2002-04-27 20:26:10 +04:00
|
|
|
|
GdkEventButton *event);
|
2001-12-12 06:03:05 +03:00
|
|
|
|
static gboolean focus_in_event_cb (GtkWidget *widget,
|
2002-04-27 20:26:10 +04:00
|
|
|
|
GdkEventFocus *event);
|
2001-12-12 06:03:05 +03:00
|
|
|
|
static gboolean focus_out_event_cb (GtkWidget *widget,
|
2002-04-27 20:26:10 +04:00
|
|
|
|
GdkEventFocus *event);
|
2001-12-12 06:03:05 +03:00
|
|
|
|
static gboolean key_press_event_cb (GtkWidget *widget,
|
2002-04-27 20:26:10 +04:00
|
|
|
|
GdkEventKey *event);
|
2001-12-12 06:03:05 +03:00
|
|
|
|
static gboolean key_release_event_cb (GtkWidget *widget,
|
2002-04-27 20:26:10 +04:00
|
|
|
|
GdkEventKey *event);
|
2015-08-12 04:35:38 +03:00
|
|
|
|
static gboolean property_notify_event_cb (GtkWidget *widget,
|
|
|
|
|
GdkEventProperty *event);
|
2001-12-13 02:56:21 +03:00
|
|
|
|
static gboolean scroll_event_cb (GtkWidget *widget,
|
2002-04-27 20:26:10 +04:00
|
|
|
|
GdkEventScroll *event);
|
2002-01-23 09:39:48 +03:00
|
|
|
|
static gboolean visibility_notify_event_cb(GtkWidget *widget,
|
2002-04-27 20:26:10 +04:00
|
|
|
|
GdkEventVisibility *event);
|
2009-11-02 05:03:12 +03:00
|
|
|
|
static void hierarchy_changed_cb (GtkWidget *widget,
|
|
|
|
|
GtkWidget *previous_toplevel);
|
2002-04-30 23:03:12 +04:00
|
|
|
|
static gboolean window_state_event_cb (GtkWidget *widget,
|
|
|
|
|
GdkEventWindowState *event);
|
2005-11-29 01:44:33 +03:00
|
|
|
|
static void theme_changed_cb (GtkSettings *settings,
|
|
|
|
|
GParamSpec *pspec,
|
|
|
|
|
nsWindow *data);
|
2015-04-29 23:29:34 +03:00
|
|
|
|
#if GTK_CHECK_VERSION(3,4,0)
|
|
|
|
|
static gboolean touch_event_cb (GtkWidget* aWidget,
|
|
|
|
|
GdkEventTouch* aEvent);
|
|
|
|
|
#endif
|
2007-12-14 10:00:44 +03:00
|
|
|
|
static nsWindow* GetFirstNSWindowForGDKWindow (GdkWindow *aGdkWindow);
|
|
|
|
|
|
2003-02-17 18:36:37 +03:00
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
extern "C" {
|
|
|
|
|
#endif /* __cplusplus */
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#ifdef MOZ_X11
|
2010-06-18 05:15:03 +04:00
|
|
|
|
static GdkFilterReturn popup_take_focus_filter (GdkXEvent *gdk_xevent,
|
|
|
|
|
GdkEvent *event,
|
|
|
|
|
gpointer data);
|
2004-10-11 08:01:49 +04:00
|
|
|
|
static GdkFilterReturn plugin_window_filter_func (GdkXEvent *gdk_xevent,
|
|
|
|
|
GdkEvent *event,
|
2002-09-02 09:11:10 +04:00
|
|
|
|
gpointer data);
|
2003-02-17 18:36:37 +03:00
|
|
|
|
static GdkFilterReturn plugin_client_message_filter (GdkXEvent *xevent,
|
|
|
|
|
GdkEvent *event,
|
|
|
|
|
gpointer data);
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#endif /* MOZ_X11 */
|
2003-02-17 18:36:37 +03:00
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
}
|
|
|
|
|
#endif /* __cplusplus */
|
|
|
|
|
|
2002-08-10 20:18:44 +04:00
|
|
|
|
static gboolean drag_motion_event_cb (GtkWidget *aWidget,
|
|
|
|
|
GdkDragContext *aDragContext,
|
|
|
|
|
gint aX,
|
|
|
|
|
gint aY,
|
|
|
|
|
guint aTime,
|
|
|
|
|
gpointer aData);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
static void drag_leave_event_cb (GtkWidget *aWidget,
|
2002-08-10 20:18:44 +04:00
|
|
|
|
GdkDragContext *aDragContext,
|
|
|
|
|
guint aTime,
|
|
|
|
|
gpointer aData);
|
|
|
|
|
static gboolean drag_drop_event_cb (GtkWidget *aWidget,
|
|
|
|
|
GdkDragContext *aDragContext,
|
|
|
|
|
gint aX,
|
|
|
|
|
gint aY,
|
|
|
|
|
guint aTime,
|
2011-05-19 14:51:11 +04:00
|
|
|
|
gpointer aData);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
static void drag_data_received_event_cb(GtkWidget *aWidget,
|
2002-08-10 20:18:44 +04:00
|
|
|
|
GdkDragContext *aDragContext,
|
|
|
|
|
gint aX,
|
|
|
|
|
gint aY,
|
|
|
|
|
GtkSelectionData *aSelectionData,
|
|
|
|
|
guint aInfo,
|
|
|
|
|
guint32 aTime,
|
|
|
|
|
gpointer aData);
|
2002-08-10 22:07:20 +04:00
|
|
|
|
|
|
|
|
|
/* initialization static functions */
|
|
|
|
|
static nsresult initialize_prefs (void);
|
2004-10-11 08:01:49 +04:00
|
|
|
|
|
2012-02-14 00:19:59 +04:00
|
|
|
|
static guint32 sLastUserInputTime = GDK_CURRENT_TIME;
|
2012-02-02 06:12:26 +04:00
|
|
|
|
static guint32 sRetryGrabTime;
|
2003-02-17 21:50:01 +03:00
|
|
|
|
|
2015-08-11 10:40:34 +03:00
|
|
|
|
static SystemTimeConverter<guint32>&
|
|
|
|
|
TimeConverter() {
|
|
|
|
|
static SystemTimeConverter<guint32> sTimeConverterSingleton;
|
|
|
|
|
return sTimeConverterSingleton;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
|
|
2015-08-11 11:13:44 +03:00
|
|
|
|
class CurrentX11TimeGetter
|
2015-08-11 10:40:34 +03:00
|
|
|
|
{
|
|
|
|
|
public:
|
2015-08-24 16:24:42 +03:00
|
|
|
|
explicit CurrentX11TimeGetter(GdkWindow* aWindow)
|
2015-08-12 04:35:38 +03:00
|
|
|
|
: mWindow(aWindow)
|
|
|
|
|
, mAsyncUpdateStart()
|
|
|
|
|
{
|
|
|
|
|
}
|
2015-02-19 08:10:00 +03:00
|
|
|
|
|
|
|
|
|
guint32 GetCurrentTime() const
|
|
|
|
|
{
|
2015-08-11 10:40:34 +03:00
|
|
|
|
return gdk_x11_get_server_time(mWindow);
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-19 08:10:00 +03:00
|
|
|
|
void GetTimeAsyncForPossibleBackwardsSkew(const TimeStamp& aNow)
|
|
|
|
|
{
|
2015-08-12 04:35:38 +03:00
|
|
|
|
// Check for in-flight request
|
|
|
|
|
if (!mAsyncUpdateStart.IsNull()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
mAsyncUpdateStart = aNow;
|
|
|
|
|
|
|
|
|
|
Display* xDisplay = GDK_WINDOW_XDISPLAY(mWindow);
|
|
|
|
|
Window xWindow = GDK_WINDOW_XID(mWindow);
|
|
|
|
|
unsigned char c = 'a';
|
|
|
|
|
Atom timeStampPropAtom = TimeStampPropAtom();
|
|
|
|
|
XChangeProperty(xDisplay, xWindow, timeStampPropAtom,
|
|
|
|
|
timeStampPropAtom, 8, PropModeReplace, &c, 1);
|
|
|
|
|
XFlush(xDisplay);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean PropertyNotifyHandler(GtkWidget* aWidget,
|
|
|
|
|
GdkEventProperty* aEvent)
|
|
|
|
|
{
|
|
|
|
|
if (aEvent->atom !=
|
|
|
|
|
gdk_x11_xatom_to_atom(TimeStampPropAtom())) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
guint32 eventTime = aEvent->time;
|
|
|
|
|
TimeStamp lowerBound = mAsyncUpdateStart;
|
|
|
|
|
|
|
|
|
|
TimeConverter().CompensateForBackwardsSkew(eventTime, lowerBound);
|
|
|
|
|
mAsyncUpdateStart = TimeStamp();
|
|
|
|
|
return TRUE;
|
2015-02-19 08:10:00 +03:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-11 10:40:34 +03:00
|
|
|
|
private:
|
2015-08-12 04:35:38 +03:00
|
|
|
|
static Atom TimeStampPropAtom() {
|
|
|
|
|
return gdk_x11_get_xatom_by_name_for_display(
|
|
|
|
|
gdk_display_get_default(), "GDK_TIMESTAMP_PROP");
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-11 11:13:44 +03:00
|
|
|
|
// This is safe because this class is stored as a member of mWindow and
|
|
|
|
|
// won't outlive it.
|
2015-08-11 10:40:34 +03:00
|
|
|
|
GdkWindow* mWindow;
|
2015-08-12 04:35:38 +03:00
|
|
|
|
TimeStamp mAsyncUpdateStart;
|
2015-08-11 10:40:34 +03:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
2002-08-10 20:18:44 +04:00
|
|
|
|
static NS_DEFINE_IID(kCDragServiceCID, NS_DRAGSERVICE_CID);
|
2001-12-10 20:37:36 +03:00
|
|
|
|
|
2010-06-03 07:50:49 +04:00
|
|
|
|
// The window from which the focus manager asks us to dispatch key events.
|
2013-10-08 22:47:37 +04:00
|
|
|
|
static nsWindow *gFocusWindow = nullptr;
|
2011-09-29 10:19:26 +04:00
|
|
|
|
static bool gBlockActivateEvent = false;
|
|
|
|
|
static bool gGlobalsInitialized = false;
|
|
|
|
|
static bool gRaiseWindows = true;
|
2013-10-08 22:47:37 +04:00
|
|
|
|
static nsWindow *gPluginFocusWindow = nullptr;
|
2002-08-10 22:07:20 +04:00
|
|
|
|
|
2015-04-29 23:29:34 +03:00
|
|
|
|
#if GTK_CHECK_VERSION(3,4,0)
|
|
|
|
|
static uint32_t gLastTouchID = 0;
|
|
|
|
|
#endif
|
2002-01-22 09:21:09 +03:00
|
|
|
|
|
2005-08-18 12:10:28 +04:00
|
|
|
|
#define NS_WINDOW_TITLE_MAX_LENGTH 4095
|
|
|
|
|
|
2002-09-26 10:20:01 +04:00
|
|
|
|
// If after selecting profile window, the startup fail, please refer to
|
|
|
|
|
// http://bugzilla.gnome.org/show_bug.cgi?id=88940
|
|
|
|
|
|
2005-03-16 01:24:20 +03:00
|
|
|
|
// needed for imgIContainer cursors
|
2005-03-16 02:19:01 +03:00
|
|
|
|
// GdkDisplay* was added in 2.2
|
|
|
|
|
typedef struct _GdkDisplay GdkDisplay;
|
2006-12-20 12:05:19 +03:00
|
|
|
|
|
2002-07-05 07:23:59 +04:00
|
|
|
|
#define kWindowPositionSlop 20
|
|
|
|
|
|
2002-01-28 09:47:47 +03:00
|
|
|
|
// cursor cache
|
2004-09-23 01:14:56 +04:00
|
|
|
|
static GdkCursor *gCursorCache[eCursorCount];
|
2002-01-28 09:47:47 +03:00
|
|
|
|
|
2013-10-08 22:47:37 +04:00
|
|
|
|
static GtkWidget *gInvisibleContainer = nullptr;
|
2009-05-15 06:14:45 +04:00
|
|
|
|
|
2010-03-24 06:37:06 +03:00
|
|
|
|
// Sometimes this actually also includes the state of the modifier keys, but
|
|
|
|
|
// only the button state bits are used.
|
|
|
|
|
static guint gButtonState;
|
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
|
static inline int32_t
|
|
|
|
|
GetBitmapStride(int32_t width)
|
2011-09-23 00:58:07 +04:00
|
|
|
|
{
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if defined(MOZ_X11) || (MOZ_WIDGET_GTK == 2)
|
2011-09-23 00:58:07 +04:00
|
|
|
|
return (width+7)/8;
|
|
|
|
|
#else
|
|
|
|
|
return cairo_format_stride_for_width(CAIRO_FORMAT_A1, width);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-14 00:19:59 +04:00
|
|
|
|
static inline bool TimestampIsNewerThan(guint32 a, guint32 b)
|
|
|
|
|
{
|
|
|
|
|
// Timestamps are just the least significant bits of a monotonically
|
|
|
|
|
// increasing function, and so the use of unsigned overflow arithmetic.
|
|
|
|
|
return a - b <= G_MAXUINT32/2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
UpdateLastInputEventTime(void *aGdkEvent)
|
|
|
|
|
{
|
2012-06-29 12:32:21 +04:00
|
|
|
|
nsCOMPtr<nsIIdleServiceInternal> idleService =
|
2012-02-14 00:19:59 +04:00
|
|
|
|
do_GetService("@mozilla.org/widget/idleservice;1");
|
|
|
|
|
if (idleService) {
|
2012-06-29 12:32:21 +04:00
|
|
|
|
idleService->ResetIdleTimeOut(0);
|
2012-02-14 00:19:59 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
guint timestamp = gdk_event_get_time(static_cast<GdkEvent*>(aGdkEvent));
|
|
|
|
|
if (timestamp == GDK_CURRENT_TIME)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
sLastUserInputTime = timestamp;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-18 09:27:53 +03:00
|
|
|
|
NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, nsBaseWidget)
|
|
|
|
|
|
2001-07-26 02:05:10 +04:00
|
|
|
|
nsWindow::nsWindow()
|
|
|
|
|
{
|
2015-09-24 05:50:00 +03:00
|
|
|
|
mIsTopLevel = false;
|
|
|
|
|
mIsDestroyed = false;
|
|
|
|
|
mListenForResizes = false;
|
2015-11-11 03:50:04 +03:00
|
|
|
|
mNeedsDispatchResized = false;
|
2015-09-24 05:50:00 +03:00
|
|
|
|
mIsShown = false;
|
|
|
|
|
mNeedsShow = false;
|
|
|
|
|
mEnabled = true;
|
|
|
|
|
mCreated = false;
|
2015-04-29 23:29:34 +03:00
|
|
|
|
#if GTK_CHECK_VERSION(3,4,0)
|
|
|
|
|
mHandleTouchEvent = false;
|
|
|
|
|
#endif
|
2008-10-19 05:13:27 +04:00
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
|
mContainer = nullptr;
|
|
|
|
|
mGdkWindow = nullptr;
|
|
|
|
|
mShell = nullptr;
|
2015-01-29 22:41:57 +03:00
|
|
|
|
mPluginNativeWindow = nullptr;
|
2011-10-03 11:56:21 +04:00
|
|
|
|
mHasMappedToplevel = false;
|
|
|
|
|
mIsFullyObscured = false;
|
|
|
|
|
mRetryPointerGrab = false;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
mWindowType = eWindowType_child;
|
2002-04-30 23:03:12 +04:00
|
|
|
|
mSizeState = nsSizeMode_Normal;
|
2009-08-27 04:09:47 +04:00
|
|
|
|
mLastSizeMode = nsSizeMode_Normal;
|
2012-11-28 02:07:11 +04:00
|
|
|
|
mSizeConstraints.mMaxSize = GetSafeWindowSize(mSizeConstraints.mMaxSize);
|
2009-08-27 04:09:47 +04:00
|
|
|
|
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#ifdef MOZ_X11
|
2002-09-02 09:11:10 +04:00
|
|
|
|
mOldFocusWindow = 0;
|
2015-09-15 23:46:39 +03:00
|
|
|
|
|
|
|
|
|
mXDisplay = nullptr;
|
|
|
|
|
mXWindow = None;
|
|
|
|
|
mXVisual = nullptr;
|
|
|
|
|
mXDepth = 0;
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#endif /* MOZ_X11 */
|
2003-09-16 05:44:41 +04:00
|
|
|
|
mPluginType = PluginType_NONE;
|
2002-05-08 11:42:34 +04:00
|
|
|
|
|
2002-06-04 15:02:26 +04:00
|
|
|
|
if (!gGlobalsInitialized) {
|
2011-10-03 11:56:21 +04:00
|
|
|
|
gGlobalsInitialized = true;
|
2002-06-04 15:02:26 +04:00
|
|
|
|
|
2002-08-10 22:07:20 +04:00
|
|
|
|
// It's OK if either of these fail, but it may not be one day.
|
|
|
|
|
initialize_prefs();
|
2002-06-04 15:02:26 +04:00
|
|
|
|
}
|
2004-10-11 08:01:49 +04:00
|
|
|
|
|
2008-12-12 02:55:15 +03:00
|
|
|
|
mLastMotionPressure = 0;
|
2002-06-04 15:02:26 +04:00
|
|
|
|
|
2002-05-08 11:42:34 +04:00
|
|
|
|
#ifdef ACCESSIBILITY
|
2012-07-30 18:20:58 +04:00
|
|
|
|
mRootAccessible = nullptr;
|
2002-05-08 11:42:34 +04:00
|
|
|
|
#endif
|
2004-07-24 16:42:32 +04:00
|
|
|
|
|
2011-10-03 11:56:21 +04:00
|
|
|
|
mIsTransparent = false;
|
2012-07-30 18:20:58 +04:00
|
|
|
|
mTransparencyBitmap = nullptr;
|
2006-10-16 16:13:54 +04:00
|
|
|
|
|
|
|
|
|
mTransparencyBitmapWidth = 0;
|
|
|
|
|
mTransparencyBitmapHeight = 0;
|
2014-07-07 13:54:13 +04:00
|
|
|
|
|
2015-10-19 14:22:55 +03:00
|
|
|
|
#if GTK_CHECK_VERSION(3,4,0)
|
2014-07-07 13:54:13 +04:00
|
|
|
|
mLastScrollEventTime = GDK_CURRENT_TIME;
|
2015-10-19 14:22:55 +03:00
|
|
|
|
#endif
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsWindow::~nsWindow()
|
|
|
|
|
{
|
2002-04-27 20:26:10 +04:00
|
|
|
|
LOG(("nsWindow::~nsWindow() [%p]\n", (void *)this));
|
2004-07-24 16:42:32 +04:00
|
|
|
|
|
|
|
|
|
delete[] mTransparencyBitmap;
|
2012-07-30 18:20:58 +04:00
|
|
|
|
mTransparencyBitmap = nullptr;
|
2004-07-24 16:42:32 +04:00
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
Destroy();
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
2003-07-02 23:27:38 +04:00
|
|
|
|
/* static */ void
|
|
|
|
|
nsWindow::ReleaseGlobals()
|
|
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
|
for (uint32_t i = 0; i < ArrayLength(gCursorCache); ++i) {
|
2003-07-02 23:27:38 +04:00
|
|
|
|
if (gCursorCache[i]) {
|
2014-06-25 02:35:00 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 3)
|
|
|
|
|
g_object_unref(gCursorCache[i]);
|
|
|
|
|
#else
|
2003-07-02 23:27:38 +04:00
|
|
|
|
gdk_cursor_unref(gCursorCache[i]);
|
2014-06-25 02:35:00 +04:00
|
|
|
|
#endif
|
2012-07-30 18:20:58 +04:00
|
|
|
|
gCursorCache[i] = nullptr;
|
2003-07-02 23:27:38 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-19 05:13:27 +04:00
|
|
|
|
void
|
2011-09-29 10:19:26 +04:00
|
|
|
|
nsWindow::CommonCreate(nsIWidget *aParent, bool aListenForResizes)
|
2008-10-19 05:13:27 +04:00
|
|
|
|
{
|
|
|
|
|
mParent = aParent;
|
|
|
|
|
mListenForResizes = aListenForResizes;
|
2011-10-03 11:56:21 +04:00
|
|
|
|
mCreated = true;
|
2008-10-19 05:13:27 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nsWindow::DispatchActivateEvent(void)
|
|
|
|
|
{
|
2009-09-16 06:01:09 +04:00
|
|
|
|
NS_ASSERTION(mContainer || mIsDestroyed,
|
|
|
|
|
"DispatchActivateEvent only intended for container windows");
|
|
|
|
|
|
2008-10-19 05:13:27 +04:00
|
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
|
DispatchActivateEventAccessible();
|
|
|
|
|
#endif //ACCESSIBILITY
|
2012-08-15 22:52:42 +04:00
|
|
|
|
|
|
|
|
|
if (mWidgetListener)
|
|
|
|
|
mWidgetListener->WindowActivated();
|
2008-10-19 05:13:27 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nsWindow::DispatchDeactivateEvent(void)
|
|
|
|
|
{
|
2012-08-15 22:52:42 +04:00
|
|
|
|
if (mWidgetListener)
|
|
|
|
|
mWidgetListener->WindowDeactivated();
|
2008-10-19 05:13:27 +04:00
|
|
|
|
|
|
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
|
DispatchDeactivateEventAccessible();
|
|
|
|
|
#endif //ACCESSIBILITY
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-23 02:46:45 +04:00
|
|
|
|
void
|
2015-11-10 05:09:52 +03:00
|
|
|
|
nsWindow::DispatchResized()
|
2012-10-23 02:46:45 +04:00
|
|
|
|
{
|
2015-11-11 03:50:04 +03:00
|
|
|
|
mNeedsDispatchResized = false;
|
2015-09-18 15:51:03 +03:00
|
|
|
|
if (mWidgetListener) {
|
2015-11-10 05:09:52 +03:00
|
|
|
|
mWidgetListener->WindowResized(this, mBounds.width, mBounds.height);
|
2015-09-18 15:51:03 +03:00
|
|
|
|
}
|
|
|
|
|
if (mAttachedWidgetListener) {
|
2015-11-10 05:09:52 +03:00
|
|
|
|
mAttachedWidgetListener->WindowResized(this,
|
|
|
|
|
mBounds.width, mBounds.height);
|
2012-10-23 02:46:45 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
2008-10-19 05:13:27 +04:00
|
|
|
|
|
2015-11-11 03:50:04 +03:00
|
|
|
|
void
|
|
|
|
|
nsWindow::MaybeDispatchResized()
|
|
|
|
|
{
|
|
|
|
|
if (mNeedsDispatchResized && !mIsDestroyed) {
|
|
|
|
|
DispatchResized();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-19 05:13:27 +04:00
|
|
|
|
nsresult
|
2013-10-02 07:46:03 +04:00
|
|
|
|
nsWindow::DispatchEvent(WidgetGUIEvent* aEvent, nsEventStatus& aStatus)
|
2008-10-19 05:13:27 +04:00
|
|
|
|
{
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
debug_DumpEvent(stdout, aEvent->widget, aEvent,
|
2012-09-02 06:35:17 +04:00
|
|
|
|
nsAutoCString("something"), 0);
|
2008-10-19 05:13:27 +04:00
|
|
|
|
#endif
|
|
|
|
|
aStatus = nsEventStatus_eIgnore;
|
2012-10-23 02:46:45 +04:00
|
|
|
|
nsIWidgetListener* listener =
|
|
|
|
|
mAttachedWidgetListener ? mAttachedWidgetListener : mWidgetListener;
|
|
|
|
|
if (listener) {
|
|
|
|
|
aStatus = listener->HandleEvent(aEvent, mUseAttachedEvents);
|
|
|
|
|
}
|
2008-10-19 05:13:27 +04:00
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nsWindow::OnDestroy(void)
|
|
|
|
|
{
|
|
|
|
|
if (mOnDestroyCalled)
|
|
|
|
|
return;
|
|
|
|
|
|
2011-10-03 11:56:21 +04:00
|
|
|
|
mOnDestroyCalled = true;
|
2010-03-25 06:29:14 +03:00
|
|
|
|
|
|
|
|
|
// Prevent deletion.
|
|
|
|
|
nsCOMPtr<nsIWidget> kungFuDeathGrip = this;
|
2008-10-19 05:13:27 +04:00
|
|
|
|
|
|
|
|
|
// release references to children, device context, toolkit + app shell
|
2010-03-25 06:29:14 +03:00
|
|
|
|
nsBaseWidget::OnDestroy();
|
|
|
|
|
|
|
|
|
|
// Remove association between this object and its parent and siblings.
|
|
|
|
|
nsBaseWidget::Destroy();
|
2012-07-30 18:20:58 +04:00
|
|
|
|
mParent = nullptr;
|
2008-10-19 05:13:27 +04:00
|
|
|
|
|
2012-08-15 22:52:41 +04:00
|
|
|
|
NotifyWindowDestroyed();
|
2008-10-19 05:13:27 +04:00
|
|
|
|
}
|
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool
|
2008-10-19 05:13:27 +04:00
|
|
|
|
nsWindow::AreBoundsSane(void)
|
|
|
|
|
{
|
|
|
|
|
if (mBounds.width > 0 && mBounds.height > 0)
|
2011-10-03 11:56:21 +04:00
|
|
|
|
return true;
|
2008-10-19 05:13:27 +04:00
|
|
|
|
|
2011-10-03 11:56:21 +04:00
|
|
|
|
return false;
|
2008-10-19 05:13:27 +04:00
|
|
|
|
}
|
|
|
|
|
|
2009-05-15 06:14:45 +04:00
|
|
|
|
static GtkWidget*
|
|
|
|
|
EnsureInvisibleContainer()
|
|
|
|
|
{
|
|
|
|
|
if (!gInvisibleContainer) {
|
|
|
|
|
// GtkWidgets need to be anchored to a GtkWindow to be realized (to
|
|
|
|
|
// have a window). Using GTK_WINDOW_POPUP rather than
|
|
|
|
|
// GTK_WINDOW_TOPLEVEL in the hope that POPUP results in less
|
|
|
|
|
// initialization and window manager interaction.
|
|
|
|
|
GtkWidget* window = gtk_window_new(GTK_WINDOW_POPUP);
|
|
|
|
|
gInvisibleContainer = moz_container_new();
|
|
|
|
|
gtk_container_add(GTK_CONTAINER(window), gInvisibleContainer);
|
|
|
|
|
gtk_widget_realize(gInvisibleContainer);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return gInvisibleContainer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
CheckDestroyInvisibleContainer()
|
|
|
|
|
{
|
|
|
|
|
NS_PRECONDITION(gInvisibleContainer, "oh, no");
|
|
|
|
|
|
2011-09-23 00:58:07 +04:00
|
|
|
|
if (!gdk_window_peek_children(gtk_widget_get_window(gInvisibleContainer))) {
|
2009-05-15 06:14:45 +04:00
|
|
|
|
// No children, so not in use.
|
|
|
|
|
// Make sure to destroy the GtkWindow also.
|
2011-09-23 00:58:07 +04:00
|
|
|
|
gtk_widget_destroy(gtk_widget_get_parent(gInvisibleContainer));
|
2013-10-08 22:47:37 +04:00
|
|
|
|
gInvisibleContainer = nullptr;
|
2009-05-15 06:14:45 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Change the containing GtkWidget on a sub-hierarchy of GdkWindows belonging
|
|
|
|
|
// to aOldWidget and rooted at aWindow, and reparent any child GtkWidgets of
|
2009-11-11 00:57:25 +03:00
|
|
|
|
// the GdkWindow hierarchy to aNewWidget.
|
2009-05-15 06:14:45 +04:00
|
|
|
|
static void
|
|
|
|
|
SetWidgetForHierarchy(GdkWindow *aWindow,
|
|
|
|
|
GtkWidget *aOldWidget,
|
|
|
|
|
GtkWidget *aNewWidget)
|
|
|
|
|
{
|
|
|
|
|
gpointer data;
|
|
|
|
|
gdk_window_get_user_data(aWindow, &data);
|
|
|
|
|
|
|
|
|
|
if (data != aOldWidget) {
|
|
|
|
|
if (!GTK_IS_WIDGET(data))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
GtkWidget* widget = static_cast<GtkWidget*>(data);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
if (gtk_widget_get_parent(widget) != aOldWidget)
|
2009-05-15 06:14:45 +04:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// This window belongs to a child widget, which will no longer be a
|
|
|
|
|
// child of aOldWidget.
|
2009-11-11 00:57:25 +03:00
|
|
|
|
gtk_widget_reparent(widget, aNewWidget);
|
2009-05-15 06:14:45 +04:00
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2009-05-16 14:20:19 +04:00
|
|
|
|
GList *children = gdk_window_get_children(aWindow);
|
|
|
|
|
for(GList *list = children; list; list = list->next) {
|
2009-05-15 06:14:45 +04:00
|
|
|
|
SetWidgetForHierarchy(GDK_WINDOW(list->data), aOldWidget, aNewWidget);
|
|
|
|
|
}
|
2009-05-16 14:20:19 +04:00
|
|
|
|
g_list_free(children);
|
2009-05-15 06:14:45 +04:00
|
|
|
|
|
|
|
|
|
gdk_window_set_user_data(aWindow, aNewWidget);
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-11 00:57:25 +03:00
|
|
|
|
// Walk the list of child windows and call destroy on them.
|
|
|
|
|
void
|
|
|
|
|
nsWindow::DestroyChildWindows()
|
|
|
|
|
{
|
|
|
|
|
if (!mGdkWindow)
|
|
|
|
|
return;
|
|
|
|
|
|
2009-11-13 07:20:23 +03:00
|
|
|
|
while (GList *children = gdk_window_peek_children(mGdkWindow)) {
|
2009-11-11 00:57:25 +03:00
|
|
|
|
GdkWindow *child = GDK_WINDOW(children->data);
|
|
|
|
|
nsWindow *kid = get_window_for_gdk_window(child);
|
|
|
|
|
if (kid) {
|
|
|
|
|
kid->Destroy();
|
|
|
|
|
} else {
|
|
|
|
|
// This child is not an nsWindow.
|
|
|
|
|
// Destroy the child GtkWidget.
|
|
|
|
|
gpointer data;
|
|
|
|
|
gdk_window_get_user_data(child, &data);
|
|
|
|
|
if (GTK_IS_WIDGET(data)) {
|
|
|
|
|
gtk_widget_destroy(static_cast<GtkWidget*>(data));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-07-26 02:05:10 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
nsWindow::Destroy(void)
|
|
|
|
|
{
|
2002-12-03 22:46:49 +03:00
|
|
|
|
if (mIsDestroyed || !mCreated)
|
2002-04-27 20:26:10 +04:00
|
|
|
|
return NS_OK;
|
2001-07-26 02:05:10 +04:00
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
LOG(("nsWindow::Destroy [%p]\n", (void *)this));
|
2011-10-03 11:56:21 +04:00
|
|
|
|
mIsDestroyed = true;
|
|
|
|
|
mCreated = false;
|
2008-09-18 01:15:52 +04:00
|
|
|
|
|
2010-06-24 03:37:00 +04:00
|
|
|
|
/** Need to clean our LayerManager up while still alive */
|
2010-08-07 09:09:18 +04:00
|
|
|
|
if (mLayerManager) {
|
|
|
|
|
mLayerManager->Destroy();
|
|
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
|
mLayerManager = nullptr;
|
2010-06-24 03:37:00 +04:00
|
|
|
|
|
2012-05-23 18:17:44 +04:00
|
|
|
|
// It is safe to call DestroyeCompositor several times (here and
|
|
|
|
|
// in the parent class) since it will take effect only once.
|
|
|
|
|
// The reason we call it here is because on gtk platforms we need
|
|
|
|
|
// to destroy the compositor before we destroy the gdk window (which
|
|
|
|
|
// destroys the the gl context attached to it).
|
|
|
|
|
DestroyCompositor();
|
|
|
|
|
|
2011-01-22 00:45:23 +03:00
|
|
|
|
ClearCachedResources();
|
|
|
|
|
|
2005-11-29 01:44:33 +03:00
|
|
|
|
g_signal_handlers_disconnect_by_func(gtk_settings_get_default(),
|
2009-11-02 05:03:12 +03:00
|
|
|
|
FuncToGpointer(theme_changed_cb),
|
2005-11-29 01:44:33 +03:00
|
|
|
|
this);
|
|
|
|
|
|
2012-10-26 17:15:22 +04:00
|
|
|
|
nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener();
|
2012-12-31 21:27:04 +04:00
|
|
|
|
if (rollupListener) {
|
|
|
|
|
nsCOMPtr<nsIWidget> rollupWidget = rollupListener->GetRollupWidget();
|
|
|
|
|
if (static_cast<nsIWidget *>(this) == rollupWidget) {
|
2015-01-08 04:52:20 +03:00
|
|
|
|
rollupListener->Rollup(0, false, nullptr, nullptr);
|
2012-12-31 21:27:04 +04:00
|
|
|
|
}
|
2001-12-18 01:05:58 +03:00
|
|
|
|
}
|
|
|
|
|
|
2012-05-04 07:34:50 +04:00
|
|
|
|
// dragService will be null after shutdown of the service manager.
|
2012-04-19 10:18:31 +04:00
|
|
|
|
nsDragService *dragService = nsDragService::GetInstance();
|
2012-05-04 07:34:50 +04:00
|
|
|
|
if (dragService && this == dragService->GetMostRecentDestWindow()) {
|
2012-04-19 10:18:31 +04:00
|
|
|
|
dragService->ScheduleLeaveEvent();
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-03 11:56:21 +04:00
|
|
|
|
NativeShow(false);
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2015-07-27 02:23:04 +03:00
|
|
|
|
if (mIMContext) {
|
|
|
|
|
mIMContext->OnDestroyWindow(this);
|
2010-03-19 07:21:16 +03:00
|
|
|
|
}
|
2002-09-26 10:20:01 +04:00
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
// make sure that we remove ourself as the focus window
|
2002-11-06 06:29:02 +03:00
|
|
|
|
if (gFocusWindow == this) {
|
|
|
|
|
LOGFOCUS(("automatically losing focus...\n"));
|
2012-07-30 18:20:58 +04:00
|
|
|
|
gFocusWindow = nullptr;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2) && defined(MOZ_X11)
|
2003-02-17 18:36:37 +03:00
|
|
|
|
// make sure that we remove ourself as the plugin focus window
|
|
|
|
|
if (gPluginFocusWindow == this) {
|
|
|
|
|
gPluginFocusWindow->LoseNonXEmbedPluginFocus();
|
|
|
|
|
}
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#endif /* MOZ_X11 && MOZ_WIDGET_GTK2 */
|
2006-02-21 01:43:44 +03:00
|
|
|
|
|
2009-05-15 06:14:45 +04:00
|
|
|
|
GtkWidget *owningWidget = GetMozContainerWidget();
|
|
|
|
|
if (mShell) {
|
|
|
|
|
gtk_widget_destroy(mShell);
|
2012-07-30 18:20:58 +04:00
|
|
|
|
mShell = nullptr;
|
|
|
|
|
mContainer = nullptr;
|
2015-02-10 01:34:50 +03:00
|
|
|
|
MOZ_ASSERT(!mGdkWindow,
|
|
|
|
|
"mGdkWindow should be NULL when mContainer is destroyed");
|
2009-05-15 06:14:45 +04:00
|
|
|
|
}
|
|
|
|
|
else if (mContainer) {
|
|
|
|
|
gtk_widget_destroy(GTK_WIDGET(mContainer));
|
2012-07-30 18:20:58 +04:00
|
|
|
|
mContainer = nullptr;
|
2015-02-10 01:34:50 +03:00
|
|
|
|
MOZ_ASSERT(!mGdkWindow,
|
|
|
|
|
"mGdkWindow should be NULL when mContainer is destroyed");
|
2009-05-15 06:14:45 +04:00
|
|
|
|
}
|
2009-07-27 05:40:46 +04:00
|
|
|
|
else if (mGdkWindow) {
|
2009-11-11 00:57:25 +03:00
|
|
|
|
// Destroy child windows to ensure that their mThebesSurfaces are
|
|
|
|
|
// released and to remove references from GdkWindows back to their
|
|
|
|
|
// container widget. (OnContainerUnrealize() does this when the
|
|
|
|
|
// MozContainer widget is destroyed.)
|
|
|
|
|
DestroyChildWindows();
|
2009-05-15 06:14:45 +04:00
|
|
|
|
|
2013-10-08 22:47:37 +04:00
|
|
|
|
gdk_window_set_user_data(mGdkWindow, nullptr);
|
|
|
|
|
g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", nullptr);
|
2009-07-27 05:39:36 +04:00
|
|
|
|
gdk_window_destroy(mGdkWindow);
|
2012-07-30 18:20:58 +04:00
|
|
|
|
mGdkWindow = nullptr;
|
2008-08-28 06:04:06 +04:00
|
|
|
|
}
|
|
|
|
|
|
2009-05-15 06:14:45 +04:00
|
|
|
|
if (gInvisibleContainer && owningWidget == gInvisibleContainer) {
|
|
|
|
|
CheckDestroyInvisibleContainer();
|
2002-04-27 20:26:10 +04:00
|
|
|
|
}
|
2004-10-11 08:01:49 +04:00
|
|
|
|
|
2002-05-08 11:42:34 +04:00
|
|
|
|
#ifdef ACCESSIBILITY
|
2010-03-25 06:29:14 +03:00
|
|
|
|
if (mRootAccessible) {
|
2012-07-30 18:20:58 +04:00
|
|
|
|
mRootAccessible = nullptr;
|
2010-03-25 06:29:14 +03:00
|
|
|
|
}
|
2002-05-08 11:42:34 +04:00
|
|
|
|
#endif
|
|
|
|
|
|
2010-03-25 06:29:14 +03:00
|
|
|
|
// Save until last because OnDestroy() may cause us to be deleted.
|
|
|
|
|
OnDestroy();
|
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
return NS_OK;
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
2008-10-19 05:13:27 +04:00
|
|
|
|
nsIWidget *
|
|
|
|
|
nsWindow::GetParent(void)
|
|
|
|
|
{
|
|
|
|
|
return mParent;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-13 13:57:55 +04:00
|
|
|
|
float
|
|
|
|
|
nsWindow::GetDPI()
|
|
|
|
|
{
|
2015-03-05 05:56:00 +03:00
|
|
|
|
GdkScreen *screen = gdk_display_get_default_screen(gdk_display_get_default());
|
|
|
|
|
double heightInches = gdk_screen_get_height_mm(screen)/MM_PER_INCH_FLOAT;
|
2010-08-13 13:57:55 +04:00
|
|
|
|
if (heightInches < 0.25) {
|
|
|
|
|
// Something's broken, but we'd better not crash.
|
|
|
|
|
return 96.0f;
|
|
|
|
|
}
|
2015-03-05 05:56:00 +03:00
|
|
|
|
return float(gdk_screen_get_height(screen)/heightInches);
|
2010-08-13 13:57:55 +04:00
|
|
|
|
}
|
|
|
|
|
|
2015-01-21 07:53:00 +03:00
|
|
|
|
double
|
|
|
|
|
nsWindow::GetDefaultScaleInternal()
|
|
|
|
|
{
|
2015-06-26 11:19:00 +03:00
|
|
|
|
return GdkScaleFactor() * gfxPlatformGtk::GetDPIScale();
|
2015-01-21 07:53:00 +03:00
|
|
|
|
}
|
|
|
|
|
|
2005-08-09 06:51:42 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
nsWindow::SetParent(nsIWidget *aNewParent)
|
|
|
|
|
{
|
2011-11-22 00:15:38 +04:00
|
|
|
|
if (mContainer || !mGdkWindow) {
|
|
|
|
|
NS_NOTREACHED("nsWindow::SetParent called illegally");
|
2009-05-15 06:14:45 +04:00
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
2005-08-09 06:51:42 +04:00
|
|
|
|
|
2009-05-15 06:14:45 +04:00
|
|
|
|
nsCOMPtr<nsIWidget> kungFuDeathGrip = this;
|
2011-11-22 00:15:38 +04:00
|
|
|
|
if (mParent) {
|
|
|
|
|
mParent->RemoveChild(this);
|
|
|
|
|
}
|
2005-08-09 06:51:42 +04:00
|
|
|
|
|
2009-05-15 06:14:45 +04:00
|
|
|
|
mParent = aNewParent;
|
|
|
|
|
|
|
|
|
|
GtkWidget* oldContainer = GetMozContainerWidget();
|
|
|
|
|
if (!oldContainer) {
|
|
|
|
|
// The GdkWindows have been destroyed so there is nothing else to
|
|
|
|
|
// reparent.
|
2015-02-10 01:34:50 +03:00
|
|
|
|
MOZ_ASSERT(gdk_window_is_destroyed(mGdkWindow),
|
|
|
|
|
"live GdkWindow with no widget");
|
2009-05-15 06:14:45 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (aNewParent) {
|
2010-09-18 15:28:50 +04:00
|
|
|
|
aNewParent->AddChild(this);
|
2010-09-18 15:28:50 +04:00
|
|
|
|
ReparentNativeWidget(aNewParent);
|
2005-08-09 06:51:42 +04:00
|
|
|
|
} else {
|
2013-10-08 22:47:37 +04:00
|
|
|
|
// aNewParent is nullptr, but reparent to a hidden window to avoid
|
2009-05-15 06:14:45 +04:00
|
|
|
|
// destroying the GdkWindow and its descendants.
|
|
|
|
|
// An invisible container widget is needed to hold descendant
|
|
|
|
|
// GtkWidgets.
|
2010-09-18 15:28:50 +04:00
|
|
|
|
GtkWidget* newContainer = EnsureInvisibleContainer();
|
2011-09-23 00:58:07 +04:00
|
|
|
|
GdkWindow* newParentWindow = gtk_widget_get_window(newContainer);
|
2010-09-18 15:28:50 +04:00
|
|
|
|
ReparentNativeWidgetInternal(aNewParent, newContainer, newParentWindow,
|
|
|
|
|
oldContainer);
|
|
|
|
|
}
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
nsWindow::ReparentNativeWidget(nsIWidget* aNewParent)
|
|
|
|
|
{
|
|
|
|
|
NS_PRECONDITION(aNewParent, "");
|
|
|
|
|
NS_ASSERTION(!mIsDestroyed, "");
|
|
|
|
|
NS_ASSERTION(!static_cast<nsWindow*>(aNewParent)->mIsDestroyed, "");
|
|
|
|
|
|
|
|
|
|
GtkWidget* oldContainer = GetMozContainerWidget();
|
|
|
|
|
if (!oldContainer) {
|
|
|
|
|
// The GdkWindows have been destroyed so there is nothing else to
|
|
|
|
|
// reparent.
|
2015-02-10 01:34:50 +03:00
|
|
|
|
MOZ_ASSERT(gdk_window_is_destroyed(mGdkWindow),
|
|
|
|
|
"live GdkWindow with no widget");
|
2010-09-18 15:28:50 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
2015-02-10 01:34:50 +03:00
|
|
|
|
MOZ_ASSERT(!gdk_window_is_destroyed(mGdkWindow),
|
|
|
|
|
"destroyed GdkWindow with widget");
|
2010-09-18 15:28:50 +04:00
|
|
|
|
|
|
|
|
|
nsWindow* newParent = static_cast<nsWindow*>(aNewParent);
|
|
|
|
|
GdkWindow* newParentWindow = newParent->mGdkWindow;
|
2012-10-23 02:39:59 +04:00
|
|
|
|
GtkWidget* newContainer = newParent->GetMozContainerWidget();
|
2013-01-03 00:44:19 +04:00
|
|
|
|
GtkWindow* shell = GTK_WINDOW(mShell);
|
2010-09-18 15:28:50 +04:00
|
|
|
|
|
2013-01-03 00:44:19 +04:00
|
|
|
|
if (shell && gtk_window_get_transient_for(shell)) {
|
2010-09-18 15:28:50 +04:00
|
|
|
|
GtkWindow* topLevelParent =
|
|
|
|
|
GTK_WINDOW(gtk_widget_get_toplevel(newContainer));
|
2013-01-03 00:44:19 +04:00
|
|
|
|
gtk_window_set_transient_for(shell, topLevelParent);
|
2009-05-15 06:14:45 +04:00
|
|
|
|
}
|
|
|
|
|
|
2010-09-18 15:28:50 +04:00
|
|
|
|
ReparentNativeWidgetInternal(aNewParent, newContainer, newParentWindow,
|
|
|
|
|
oldContainer);
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nsWindow::ReparentNativeWidgetInternal(nsIWidget* aNewParent,
|
|
|
|
|
GtkWidget* aNewContainer,
|
|
|
|
|
GdkWindow* aNewParentWindow,
|
|
|
|
|
GtkWidget* aOldContainer)
|
|
|
|
|
{
|
|
|
|
|
if (!aNewContainer) {
|
2009-05-15 06:14:45 +04:00
|
|
|
|
// The new parent GdkWindow has been destroyed.
|
2015-02-10 01:34:50 +03:00
|
|
|
|
MOZ_ASSERT(!aNewParentWindow ||
|
|
|
|
|
gdk_window_is_destroyed(aNewParentWindow),
|
|
|
|
|
"live GdkWindow with no widget");
|
2009-05-15 06:14:45 +04:00
|
|
|
|
Destroy();
|
|
|
|
|
} else {
|
2010-09-18 15:28:50 +04:00
|
|
|
|
if (aNewContainer != aOldContainer) {
|
2015-02-10 01:34:50 +03:00
|
|
|
|
MOZ_ASSERT(!gdk_window_is_destroyed(aNewParentWindow),
|
|
|
|
|
"destroyed GdkWindow with widget");
|
2010-09-18 15:28:50 +04:00
|
|
|
|
SetWidgetForHierarchy(mGdkWindow, aOldContainer, aNewContainer);
|
2011-11-22 00:15:38 +04:00
|
|
|
|
|
|
|
|
|
if (aOldContainer == gInvisibleContainer) {
|
|
|
|
|
CheckDestroyInvisibleContainer();
|
|
|
|
|
}
|
2009-05-15 06:14:45 +04:00
|
|
|
|
}
|
|
|
|
|
|
2010-09-18 15:28:50 +04:00
|
|
|
|
if (!mIsTopLevel) {
|
2015-01-21 07:53:00 +03:00
|
|
|
|
gdk_window_reparent(mGdkWindow, aNewParentWindow,
|
|
|
|
|
DevicePixelsToGdkCoordRoundDown(mBounds.x),
|
|
|
|
|
DevicePixelsToGdkCoordRoundDown(mBounds.y));
|
2010-09-18 15:28:50 +04:00
|
|
|
|
}
|
2005-08-09 06:51:42 +04:00
|
|
|
|
}
|
2009-05-15 06:14:45 +04:00
|
|
|
|
|
2010-09-18 15:28:50 +04:00
|
|
|
|
nsWindow* newParent = static_cast<nsWindow*>(aNewParent);
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool parentHasMappedToplevel =
|
2009-11-02 05:03:12 +03:00
|
|
|
|
newParent && newParent->mHasMappedToplevel;
|
|
|
|
|
if (mHasMappedToplevel != parentHasMappedToplevel) {
|
|
|
|
|
SetHasMappedToplevel(parentHasMappedToplevel);
|
|
|
|
|
}
|
2005-08-09 06:51:42 +04:00
|
|
|
|
}
|
|
|
|
|
|
2001-07-26 02:05:10 +04:00
|
|
|
|
NS_IMETHODIMP
|
2011-09-29 10:19:26 +04:00
|
|
|
|
nsWindow::SetModal(bool aModal)
|
2001-07-26 02:05:10 +04:00
|
|
|
|
{
|
2002-04-27 20:26:10 +04:00
|
|
|
|
LOG(("nsWindow::SetModal [%p] %d\n", (void *)this, aModal));
|
2010-06-02 03:33:28 +04:00
|
|
|
|
if (mIsDestroyed)
|
|
|
|
|
return aModal ? NS_ERROR_NOT_AVAILABLE : NS_OK;
|
|
|
|
|
if (!mIsTopLevel || !mShell)
|
2002-04-27 20:26:10 +04:00
|
|
|
|
return NS_ERROR_FAILURE;
|
2010-06-02 03:33:28 +04:00
|
|
|
|
gtk_window_set_modal(GTK_WINDOW(mShell), aModal ? TRUE : FALSE);
|
2002-04-27 20:26:10 +04:00
|
|
|
|
return NS_OK;
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
2009-07-27 05:28:05 +04:00
|
|
|
|
// nsIWidget method, which means IsShown.
|
2012-07-19 12:57:50 +04:00
|
|
|
|
bool
|
|
|
|
|
nsWindow::IsVisible() const
|
2001-07-26 02:05:10 +04:00
|
|
|
|
{
|
2012-07-19 12:57:50 +04:00
|
|
|
|
return mIsShown;
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
2015-04-29 23:29:34 +03:00
|
|
|
|
void
|
|
|
|
|
nsWindow::RegisterTouchWindow()
|
|
|
|
|
{
|
|
|
|
|
#if GTK_CHECK_VERSION(3,4,0)
|
|
|
|
|
mHandleTouchEvent = true;
|
|
|
|
|
mTouches.Clear();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2001-07-26 02:05:10 +04:00
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 19:56:38 +04:00
|
|
|
|
nsWindow::ConstrainPosition(bool aAllowSlop, int32_t *aX, int32_t *aY)
|
2001-07-26 02:05:10 +04:00
|
|
|
|
{
|
2015-02-10 10:14:00 +03:00
|
|
|
|
if (!mIsTopLevel || !mShell)
|
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
|
|
double dpiScale = GetDefaultScale().scale;
|
|
|
|
|
|
|
|
|
|
// we need to use the window size in logical screen pixels
|
|
|
|
|
int32_t logWidth = std::max(NSToIntRound(mBounds.width / dpiScale), 1);
|
|
|
|
|
int32_t logHeight = std::max(NSToIntRound(mBounds.height / dpiScale), 1);
|
|
|
|
|
|
|
|
|
|
/* get our playing field. use the current screen, or failing that
|
|
|
|
|
for any reason, use device caps for the default screen. */
|
|
|
|
|
nsCOMPtr<nsIScreen> screen;
|
|
|
|
|
nsCOMPtr<nsIScreenManager> screenmgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
|
|
|
|
|
if (screenmgr) {
|
|
|
|
|
screenmgr->ScreenForRect(*aX, *aY, logWidth, logHeight,
|
|
|
|
|
getter_AddRefs(screen));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We don't have any screen so leave the coordinates as is
|
|
|
|
|
if (!screen)
|
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
|
|
nsIntRect screenRect;
|
|
|
|
|
if (mSizeMode != nsSizeMode_Fullscreen) {
|
|
|
|
|
// For normalized windows, use the desktop work area.
|
|
|
|
|
screen->GetAvailRectDisplayPix(&screenRect.x, &screenRect.y,
|
|
|
|
|
&screenRect.width, &screenRect.height);
|
|
|
|
|
} else {
|
|
|
|
|
// For full screen windows, use the desktop.
|
|
|
|
|
screen->GetRectDisplayPix(&screenRect.x, &screenRect.y,
|
|
|
|
|
&screenRect.width, &screenRect.height);
|
2002-07-05 07:23:59 +04:00
|
|
|
|
}
|
2015-02-10 10:14:00 +03:00
|
|
|
|
|
|
|
|
|
if (aAllowSlop) {
|
|
|
|
|
if (*aX < screenRect.x - logWidth + kWindowPositionSlop)
|
|
|
|
|
*aX = screenRect.x - logWidth + kWindowPositionSlop;
|
|
|
|
|
else if (*aX >= screenRect.XMost() - kWindowPositionSlop)
|
|
|
|
|
*aX = screenRect.XMost() - kWindowPositionSlop;
|
|
|
|
|
|
|
|
|
|
if (*aY < screenRect.y - logHeight + kWindowPositionSlop)
|
|
|
|
|
*aY = screenRect.y - logHeight + kWindowPositionSlop;
|
|
|
|
|
else if (*aY >= screenRect.YMost() - kWindowPositionSlop)
|
|
|
|
|
*aY = screenRect.YMost() - kWindowPositionSlop;
|
|
|
|
|
} else {
|
|
|
|
|
if (*aX < screenRect.x)
|
|
|
|
|
*aX = screenRect.x;
|
|
|
|
|
else if (*aX >= screenRect.XMost() - logWidth)
|
|
|
|
|
*aX = screenRect.XMost() - logWidth;
|
|
|
|
|
|
|
|
|
|
if (*aY < screenRect.y)
|
|
|
|
|
*aY = screenRect.y;
|
|
|
|
|
else if (*aY >= screenRect.YMost() - logHeight)
|
|
|
|
|
*aY = screenRect.YMost() - logHeight;
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-05 07:23:59 +04:00
|
|
|
|
return NS_OK;
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-07-31 04:43:29 +04:00
|
|
|
|
void nsWindow::SetSizeConstraints(const SizeConstraints& aConstraints)
|
|
|
|
|
{
|
2012-11-28 02:07:11 +04:00
|
|
|
|
mSizeConstraints.mMinSize = GetSafeWindowSize(aConstraints.mMinSize);
|
|
|
|
|
mSizeConstraints.mMaxSize = GetSafeWindowSize(aConstraints.mMaxSize);
|
2012-07-31 04:43:29 +04:00
|
|
|
|
|
2012-11-28 02:07:11 +04:00
|
|
|
|
if (mShell) {
|
|
|
|
|
GdkGeometry geometry;
|
2015-01-21 07:53:00 +03:00
|
|
|
|
geometry.min_width = DevicePixelsToGdkCoordRoundUp(
|
|
|
|
|
mSizeConstraints.mMinSize.width);
|
|
|
|
|
geometry.min_height = DevicePixelsToGdkCoordRoundUp(
|
|
|
|
|
mSizeConstraints.mMinSize.height);
|
|
|
|
|
geometry.max_width = DevicePixelsToGdkCoordRoundDown(
|
|
|
|
|
mSizeConstraints.mMaxSize.width);
|
|
|
|
|
geometry.max_height = DevicePixelsToGdkCoordRoundDown(
|
|
|
|
|
mSizeConstraints.mMaxSize.height);
|
2012-07-31 04:43:29 +04:00
|
|
|
|
|
2012-11-28 02:07:11 +04:00
|
|
|
|
uint32_t hints = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
|
|
|
|
|
gtk_window_set_geometry_hints(GTK_WINDOW(mShell), nullptr,
|
|
|
|
|
&geometry, GdkWindowHints(hints));
|
|
|
|
|
}
|
2012-07-31 04:43:29 +04:00
|
|
|
|
}
|
|
|
|
|
|
2008-10-19 05:13:27 +04:00
|
|
|
|
NS_IMETHODIMP
|
2011-09-29 10:19:26 +04:00
|
|
|
|
nsWindow::Show(bool aState)
|
2008-10-19 05:13:27 +04:00
|
|
|
|
{
|
2009-11-02 05:03:12 +03:00
|
|
|
|
if (aState == mIsShown)
|
|
|
|
|
return NS_OK;
|
|
|
|
|
|
2011-01-22 00:45:23 +03:00
|
|
|
|
// Clear our cached resources when the window is hidden.
|
|
|
|
|
if (mIsShown && !aState) {
|
|
|
|
|
ClearCachedResources();
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-19 05:13:27 +04:00
|
|
|
|
mIsShown = aState;
|
|
|
|
|
|
|
|
|
|
LOG(("nsWindow::Show [%p] state %d\n", (void *)this, aState));
|
|
|
|
|
|
2009-11-02 05:03:12 +03:00
|
|
|
|
if (aState) {
|
|
|
|
|
// Now that this window is shown, mHasMappedToplevel needs to be
|
|
|
|
|
// tracked on viewable descendants.
|
|
|
|
|
SetHasMappedToplevel(mHasMappedToplevel);
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-19 05:13:27 +04:00
|
|
|
|
// Ok, someone called show on a window that isn't sized to a sane
|
|
|
|
|
// value. Mark this window as needing to have Show() called on it
|
|
|
|
|
// and return.
|
|
|
|
|
if ((aState && !AreBoundsSane()) || !mCreated) {
|
|
|
|
|
LOG(("\tbounds are insane or window hasn't been created yet\n"));
|
2011-10-03 11:56:21 +04:00
|
|
|
|
mNeedsShow = true;
|
2008-10-19 05:13:27 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If someone is hiding this widget, clear any needing show flag.
|
|
|
|
|
if (!aState)
|
2011-10-03 11:56:21 +04:00
|
|
|
|
mNeedsShow = false;
|
2008-10-19 05:13:27 +04:00
|
|
|
|
|
2011-05-28 13:26:56 +04:00
|
|
|
|
#ifdef ACCESSIBILITY
|
2012-01-05 05:54:17 +04:00
|
|
|
|
if (aState && a11y::ShouldA11yBeEnabled())
|
2011-05-28 13:26:56 +04:00
|
|
|
|
CreateRootAccessible();
|
|
|
|
|
#endif
|
|
|
|
|
|
2008-10-19 05:13:27 +04:00
|
|
|
|
NativeShow(aState);
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-12-12 13:57:38 +04:00
|
|
|
|
nsWindow::Resize(double aWidth, double aHeight, bool aRepaint)
|
2008-10-19 05:13:27 +04:00
|
|
|
|
{
|
2013-09-18 04:45:19 +04:00
|
|
|
|
CSSToLayoutDeviceScale scale = BoundsUseDisplayPixels() ? GetDefaultScale()
|
|
|
|
|
: CSSToLayoutDeviceScale(1.0);
|
|
|
|
|
int32_t width = NSToIntRound(scale.scale * aWidth);
|
|
|
|
|
int32_t height = NSToIntRound(scale.scale * aHeight);
|
2012-12-12 13:57:38 +04:00
|
|
|
|
ConstrainSize(&width, &height);
|
2012-07-31 04:43:29 +04:00
|
|
|
|
|
2011-07-08 07:14:27 +04:00
|
|
|
|
// For top-level windows, aWidth and aHeight should possibly be
|
|
|
|
|
// interpreted as frame bounds, but NativeResize treats these as window
|
|
|
|
|
// bounds (Bug 581866).
|
|
|
|
|
|
2012-12-12 13:57:38 +04:00
|
|
|
|
mBounds.SizeTo(width, height);
|
2008-10-19 05:13:27 +04:00
|
|
|
|
|
|
|
|
|
if (!mCreated)
|
|
|
|
|
return NS_OK;
|
|
|
|
|
|
2015-07-14 06:24:56 +03:00
|
|
|
|
NativeResize();
|
2008-10-19 05:13:27 +04:00
|
|
|
|
|
2012-10-26 17:15:22 +04:00
|
|
|
|
NotifyRollupGeometryChange();
|
2015-01-29 22:41:57 +03:00
|
|
|
|
ResizePluginSocketWidget();
|
2012-06-23 05:13:56 +04:00
|
|
|
|
|
2012-08-15 22:52:42 +04:00
|
|
|
|
// send a resize notification if this is a toplevel
|
2008-10-19 05:13:27 +04:00
|
|
|
|
if (mIsTopLevel || mListenForResizes) {
|
2015-11-10 05:09:52 +03:00
|
|
|
|
DispatchResized();
|
2008-10-19 05:13:27 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-12-12 13:57:38 +04:00
|
|
|
|
nsWindow::Resize(double aX, double aY, double aWidth, double aHeight,
|
|
|
|
|
bool aRepaint)
|
2008-10-19 05:13:27 +04:00
|
|
|
|
{
|
2013-09-18 04:45:19 +04:00
|
|
|
|
CSSToLayoutDeviceScale scale = BoundsUseDisplayPixels() ? GetDefaultScale()
|
|
|
|
|
: CSSToLayoutDeviceScale(1.0);
|
|
|
|
|
int32_t width = NSToIntRound(scale.scale * aWidth);
|
|
|
|
|
int32_t height = NSToIntRound(scale.scale * aHeight);
|
2012-12-12 13:57:38 +04:00
|
|
|
|
ConstrainSize(&width, &height);
|
2012-07-31 04:43:29 +04:00
|
|
|
|
|
2013-09-18 04:45:19 +04:00
|
|
|
|
int32_t x = NSToIntRound(scale.scale * aX);
|
|
|
|
|
int32_t y = NSToIntRound(scale.scale * aY);
|
2012-12-12 13:57:38 +04:00
|
|
|
|
mBounds.x = x;
|
|
|
|
|
mBounds.y = y;
|
|
|
|
|
mBounds.SizeTo(width, height);
|
2008-10-19 05:13:27 +04:00
|
|
|
|
|
|
|
|
|
if (!mCreated)
|
|
|
|
|
return NS_OK;
|
|
|
|
|
|
2015-07-14 06:24:56 +03:00
|
|
|
|
NativeMoveResize();
|
2008-10-19 05:13:27 +04:00
|
|
|
|
|
2012-10-26 17:15:22 +04:00
|
|
|
|
NotifyRollupGeometryChange();
|
2015-01-29 22:41:57 +03:00
|
|
|
|
ResizePluginSocketWidget();
|
2012-06-23 05:13:56 +04:00
|
|
|
|
|
2008-10-19 05:13:27 +04:00
|
|
|
|
if (mIsTopLevel || mListenForResizes) {
|
2015-11-10 05:09:52 +03:00
|
|
|
|
DispatchResized();
|
2008-10-19 05:13:27 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-29 22:41:57 +03:00
|
|
|
|
void
|
|
|
|
|
nsWindow::ResizePluginSocketWidget()
|
|
|
|
|
{
|
|
|
|
|
// e10s specific, a eWindowType_plugin_ipc_chrome holds its own
|
|
|
|
|
// nsPluginNativeWindowGtk wrapper. We are responsible for resizing
|
|
|
|
|
// the embedded socket widget.
|
|
|
|
|
if (mWindowType == eWindowType_plugin_ipc_chrome) {
|
|
|
|
|
nsPluginNativeWindowGtk* wrapper = (nsPluginNativeWindowGtk*)
|
|
|
|
|
GetNativeData(NS_NATIVE_PLUGIN_OBJECT_PTR);
|
|
|
|
|
if (wrapper) {
|
|
|
|
|
wrapper->width = mBounds.width;
|
|
|
|
|
wrapper->height = mBounds.height;
|
|
|
|
|
wrapper->SetAllocation();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-19 05:13:27 +04:00
|
|
|
|
NS_IMETHODIMP
|
2011-09-29 10:19:26 +04:00
|
|
|
|
nsWindow::Enable(bool aState)
|
2008-10-19 05:13:27 +04:00
|
|
|
|
{
|
|
|
|
|
mEnabled = aState;
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-23 09:19:08 +04:00
|
|
|
|
bool
|
|
|
|
|
nsWindow::IsEnabled() const
|
2008-10-19 05:13:27 +04:00
|
|
|
|
{
|
2012-07-23 09:19:08 +04:00
|
|
|
|
return mEnabled;
|
2008-10-19 05:13:27 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2001-07-26 02:05:10 +04:00
|
|
|
|
NS_IMETHODIMP
|
2012-12-12 13:57:38 +04:00
|
|
|
|
nsWindow::Move(double aX, double aY)
|
2001-07-26 02:05:10 +04:00
|
|
|
|
{
|
2012-12-12 13:57:38 +04:00
|
|
|
|
LOG(("nsWindow::Move [%p] %f %f\n", (void *)this,
|
2002-04-27 20:26:10 +04:00
|
|
|
|
aX, aY));
|
2001-12-11 09:21:22 +03:00
|
|
|
|
|
2013-09-18 04:45:19 +04:00
|
|
|
|
CSSToLayoutDeviceScale scale = BoundsUseDisplayPixels() ? GetDefaultScale()
|
|
|
|
|
: CSSToLayoutDeviceScale(1.0);
|
|
|
|
|
int32_t x = NSToIntRound(aX * scale.scale);
|
|
|
|
|
int32_t y = NSToIntRound(aY * scale.scale);
|
2012-12-12 13:57:38 +04:00
|
|
|
|
|
2009-11-02 22:10:07 +03:00
|
|
|
|
if (mWindowType == eWindowType_toplevel ||
|
|
|
|
|
mWindowType == eWindowType_dialog) {
|
|
|
|
|
SetSizeMode(nsSizeMode_Normal);
|
|
|
|
|
}
|
|
|
|
|
|
2002-11-26 18:46:55 +03:00
|
|
|
|
// Since a popup window's x/y coordinates are in relation to to
|
|
|
|
|
// the parent, the parent might have moved so we always move a
|
|
|
|
|
// popup window.
|
2012-12-12 13:57:38 +04:00
|
|
|
|
if (x == mBounds.x && y == mBounds.y &&
|
2002-11-26 18:46:55 +03:00
|
|
|
|
mWindowType != eWindowType_popup)
|
|
|
|
|
return NS_OK;
|
|
|
|
|
|
2006-01-21 00:31:29 +03:00
|
|
|
|
// XXX Should we do some AreBoundsSane check here?
|
|
|
|
|
|
2012-12-12 13:57:38 +04:00
|
|
|
|
mBounds.x = x;
|
|
|
|
|
mBounds.y = y;
|
2001-12-04 19:58:04 +03:00
|
|
|
|
|
2002-12-03 22:46:49 +03:00
|
|
|
|
if (!mCreated)
|
|
|
|
|
return NS_OK;
|
|
|
|
|
|
2015-07-13 05:29:05 +03:00
|
|
|
|
NativeMove();
|
|
|
|
|
|
|
|
|
|
NotifyRollupGeometryChange();
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nsWindow::NativeMove()
|
|
|
|
|
{
|
|
|
|
|
GdkPoint point = DevicePixelsToGdkPointRoundDown(mBounds.TopLeft());
|
2015-01-21 07:53:00 +03:00
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
if (mIsTopLevel) {
|
2015-01-21 07:53:00 +03:00
|
|
|
|
gtk_window_move(GTK_WINDOW(mShell), point.x, point.y);
|
2001-12-11 09:21:22 +03:00
|
|
|
|
}
|
2009-07-27 05:39:36 +04:00
|
|
|
|
else if (mGdkWindow) {
|
2015-01-21 07:53:00 +03:00
|
|
|
|
gdk_window_move(mGdkWindow, point.x, point.y);
|
2001-12-11 09:21:22 +03:00
|
|
|
|
}
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2008-05-06 03:44:18 +04:00
|
|
|
|
nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
|
|
|
|
|
nsIWidget *aWidget,
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool aActivate)
|
2001-07-26 02:05:10 +04:00
|
|
|
|
{
|
2004-10-11 08:01:49 +04:00
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
2014-03-19 20:48:08 +04:00
|
|
|
|
void
|
2012-08-22 19:56:38 +04:00
|
|
|
|
nsWindow::SetZIndex(int32_t aZIndex)
|
2005-01-27 23:49:47 +03:00
|
|
|
|
{
|
|
|
|
|
nsIWidget* oldPrev = GetPrevSibling();
|
|
|
|
|
|
|
|
|
|
nsBaseWidget::SetZIndex(aZIndex);
|
|
|
|
|
|
|
|
|
|
if (GetPrevSibling() == oldPrev) {
|
2014-03-19 20:48:08 +04:00
|
|
|
|
return;
|
2005-01-27 23:49:47 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_ASSERTION(!mContainer, "Expected Mozilla child widget");
|
|
|
|
|
|
2009-07-27 05:39:36 +04:00
|
|
|
|
// We skip the nsWindows that don't have mGdkWindows.
|
2005-02-11 02:39:44 +03:00
|
|
|
|
// These are probably in the process of being destroyed.
|
|
|
|
|
|
2005-01-27 23:49:47 +03:00
|
|
|
|
if (!GetNextSibling()) {
|
|
|
|
|
// We're to be on top.
|
2009-07-27 05:39:36 +04:00
|
|
|
|
if (mGdkWindow)
|
|
|
|
|
gdk_window_raise(mGdkWindow);
|
2005-01-27 23:49:47 +03:00
|
|
|
|
} else {
|
2009-02-28 04:47:40 +03:00
|
|
|
|
// All the siblings before us need to be below our widget.
|
2005-01-27 23:49:47 +03:00
|
|
|
|
for (nsWindow* w = this; w;
|
2007-07-08 11:08:04 +04:00
|
|
|
|
w = static_cast<nsWindow*>(w->GetPrevSibling())) {
|
2009-07-27 05:39:36 +04:00
|
|
|
|
if (w->mGdkWindow)
|
|
|
|
|
gdk_window_lower(w->mGdkWindow);
|
2005-01-27 23:49:47 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-30 23:03:12 +04:00
|
|
|
|
NS_IMETHODIMP
|
2015-08-29 04:12:41 +03:00
|
|
|
|
nsWindow::SetSizeMode(nsSizeMode aMode)
|
2002-04-30 23:03:12 +04:00
|
|
|
|
{
|
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
|
|
LOG(("nsWindow::SetSizeMode [%p] %d\n", (void *)this, aMode));
|
|
|
|
|
|
|
|
|
|
// Save the requested state.
|
|
|
|
|
rv = nsBaseWidget::SetSizeMode(aMode);
|
|
|
|
|
|
|
|
|
|
// return if there's no shell or our current state is the same as
|
|
|
|
|
// the mode we were just set to.
|
|
|
|
|
if (!mShell || mSizeState == mSizeMode) {
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (aMode) {
|
|
|
|
|
case nsSizeMode_Maximized:
|
|
|
|
|
gtk_window_maximize(GTK_WINDOW(mShell));
|
|
|
|
|
break;
|
|
|
|
|
case nsSizeMode_Minimized:
|
|
|
|
|
gtk_window_iconify(GTK_WINDOW(mShell));
|
|
|
|
|
break;
|
2009-08-14 23:56:56 +04:00
|
|
|
|
case nsSizeMode_Fullscreen:
|
2011-10-03 11:56:21 +04:00
|
|
|
|
MakeFullScreen(true);
|
2009-08-14 23:56:56 +04:00
|
|
|
|
break;
|
|
|
|
|
|
2002-04-30 23:03:12 +04:00
|
|
|
|
default:
|
|
|
|
|
// nsSizeMode_Normal, really.
|
|
|
|
|
if (mSizeState == nsSizeMode_Minimized)
|
|
|
|
|
gtk_window_deiconify(GTK_WINDOW(mShell));
|
|
|
|
|
else if (mSizeState == nsSizeMode_Maximized)
|
|
|
|
|
gtk_window_unmaximize(GTK_WINDOW(mShell));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mSizeState = mSizeMode;
|
|
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2007-02-09 04:33:26 +03:00
|
|
|
|
typedef void (* SetUserTimeFunc)(GdkWindow* aWindow, guint32 aTimestamp);
|
|
|
|
|
|
|
|
|
|
// This will become obsolete when new GTK APIs are widely supported,
|
|
|
|
|
// as described here: http://bugzilla.gnome.org/show_bug.cgi?id=347375
|
|
|
|
|
static void
|
|
|
|
|
SetUserTimeAndStartupIDForActivatedWindow(GtkWidget* aWindow)
|
|
|
|
|
{
|
2011-10-25 19:05:32 +04:00
|
|
|
|
nsGTKToolkit* GTKToolkit = nsGTKToolkit::GetToolkit();
|
|
|
|
|
if (!GTKToolkit)
|
2007-02-09 04:33:26 +03:00
|
|
|
|
return;
|
|
|
|
|
|
2012-09-02 06:35:17 +04:00
|
|
|
|
nsAutoCString desktopStartupID;
|
2007-02-09 04:33:26 +03:00
|
|
|
|
GTKToolkit->GetDesktopStartupID(&desktopStartupID);
|
|
|
|
|
if (desktopStartupID.IsEmpty()) {
|
|
|
|
|
// We don't have the data we need. Fall back to an
|
|
|
|
|
// approximation ... using the timestamp of the remote command
|
|
|
|
|
// being received as a guess for the timestamp of the user event
|
|
|
|
|
// that triggered it.
|
2012-08-22 19:56:38 +04:00
|
|
|
|
uint32_t timestamp = GTKToolkit->GetFocusTimestamp();
|
2007-02-09 04:33:26 +03:00
|
|
|
|
if (timestamp) {
|
2011-09-23 00:58:07 +04:00
|
|
|
|
gdk_window_focus(gtk_widget_get_window(aWindow), timestamp);
|
2007-02-09 04:33:26 +03:00
|
|
|
|
GTKToolkit->SetFocusTimestamp(0);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
2009-02-28 04:47:40 +03:00
|
|
|
|
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#if defined(MOZ_ENABLE_STARTUP_NOTIFICATION)
|
|
|
|
|
GdkWindow* gdkWindow = gtk_widget_get_window(aWindow);
|
|
|
|
|
|
|
|
|
|
GdkScreen* screen = gdk_window_get_screen(gdkWindow);
|
2007-02-09 04:33:26 +03:00
|
|
|
|
SnDisplay* snd =
|
2011-09-23 00:58:07 +04:00
|
|
|
|
sn_display_new(gdk_x11_display_get_xdisplay(gdk_window_get_display(gdkWindow)),
|
2012-07-30 18:20:58 +04:00
|
|
|
|
nullptr, nullptr);
|
2007-02-09 04:33:26 +03:00
|
|
|
|
if (!snd)
|
|
|
|
|
return;
|
|
|
|
|
SnLauncheeContext* ctx =
|
|
|
|
|
sn_launchee_context_new(snd, gdk_screen_get_number(screen),
|
|
|
|
|
desktopStartupID.get());
|
|
|
|
|
if (!ctx) {
|
|
|
|
|
sn_display_unref(snd);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sn_launchee_context_get_id_has_timestamp(ctx)) {
|
2014-11-14 08:32:00 +03:00
|
|
|
|
gdk_x11_window_set_user_time(gdkWindow, sn_launchee_context_get_timestamp(ctx));
|
2007-02-09 04:33:26 +03:00
|
|
|
|
}
|
|
|
|
|
|
2011-09-23 00:58:07 +04:00
|
|
|
|
sn_launchee_context_setup_window(ctx, gdk_x11_window_get_xid(gdkWindow));
|
2007-02-09 04:33:26 +03:00
|
|
|
|
sn_launchee_context_complete(ctx);
|
|
|
|
|
|
|
|
|
|
sn_launchee_context_unref(ctx);
|
|
|
|
|
sn_display_unref(snd);
|
|
|
|
|
#endif
|
2009-02-28 04:47:40 +03:00
|
|
|
|
|
2012-02-16 14:23:34 +04:00
|
|
|
|
// If we used the startup ID, that already contains the focus timestamp;
|
|
|
|
|
// we don't want to reuse the timestamp next time we raise the window
|
|
|
|
|
GTKToolkit->SetFocusTimestamp(0);
|
2007-02-09 04:33:26 +03:00
|
|
|
|
GTKToolkit->SetDesktopStartupID(EmptyCString());
|
2009-02-28 04:47:40 +03:00
|
|
|
|
}
|
2007-02-09 04:33:26 +03:00
|
|
|
|
|
2012-02-02 06:12:26 +04:00
|
|
|
|
/* static */ guint32
|
2012-02-14 00:19:59 +04:00
|
|
|
|
nsWindow::GetLastUserInputTime()
|
|
|
|
|
{
|
|
|
|
|
// gdk_x11_display_get_user_time tracks button and key presses,
|
|
|
|
|
// DESKTOP_STARTUP_ID used to start the app, drop events from external
|
|
|
|
|
// drags, WM_DELETE_WINDOW delete events, but not usually mouse motion nor
|
|
|
|
|
// button and key releases. Therefore use the most recent of
|
|
|
|
|
// gdk_x11_display_get_user_time and the last time that we have seen.
|
|
|
|
|
guint32 timestamp =
|
|
|
|
|
gdk_x11_display_get_user_time(gdk_display_get_default());
|
|
|
|
|
if (sLastUserInputTime != GDK_CURRENT_TIME &&
|
|
|
|
|
TimestampIsNewerThan(sLastUserInputTime, timestamp)) {
|
|
|
|
|
return sLastUserInputTime;
|
2012-02-02 06:12:26 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return timestamp;
|
|
|
|
|
}
|
|
|
|
|
|
2001-07-26 02:05:10 +04:00
|
|
|
|
NS_IMETHODIMP
|
2011-09-29 10:19:26 +04:00
|
|
|
|
nsWindow::SetFocus(bool aRaise)
|
2001-07-26 02:05:10 +04:00
|
|
|
|
{
|
2002-04-27 20:26:10 +04:00
|
|
|
|
// Make sure that our owning widget has focus. If it doesn't try to
|
|
|
|
|
// grab it. Note that we don't set our focus flag in this case.
|
2002-01-27 23:30:56 +03:00
|
|
|
|
|
2010-06-03 07:50:49 +04:00
|
|
|
|
LOGFOCUS((" SetFocus %d [%p]\n", aRaise, (void *)this));
|
2001-12-12 01:22:48 +03:00
|
|
|
|
|
2008-08-28 06:04:06 +04:00
|
|
|
|
GtkWidget *owningWidget = GetMozContainerWidget();
|
2002-04-27 20:26:10 +04:00
|
|
|
|
if (!owningWidget)
|
|
|
|
|
return NS_ERROR_FAILURE;
|
2001-12-12 01:22:48 +03:00
|
|
|
|
|
2011-10-03 11:56:21 +04:00
|
|
|
|
// Raise the window if someone passed in true and the prefs are
|
2002-06-04 15:02:26 +04:00
|
|
|
|
// set properly.
|
|
|
|
|
GtkWidget *toplevelWidget = gtk_widget_get_toplevel(owningWidget);
|
|
|
|
|
|
|
|
|
|
if (gRaiseWindows && aRaise && toplevelWidget &&
|
2011-09-23 00:58:07 +04:00
|
|
|
|
!gtk_widget_has_focus(owningWidget) &&
|
|
|
|
|
!gtk_widget_has_focus(toplevelWidget)) {
|
2012-11-07 01:50:37 +04:00
|
|
|
|
GtkWidget* top_window = GetToplevelWidget();
|
2011-09-23 00:58:07 +04:00
|
|
|
|
if (top_window && (gtk_widget_get_visible(top_window)))
|
2006-12-20 12:05:19 +03:00
|
|
|
|
{
|
2011-09-23 00:58:07 +04:00
|
|
|
|
gdk_window_show_unraised(gtk_widget_get_window(top_window));
|
2006-12-20 12:05:19 +03:00
|
|
|
|
// Unset the urgency hint if possible.
|
2011-10-03 11:56:21 +04:00
|
|
|
|
SetUrgencyHint(top_window, false);
|
2006-12-20 12:05:19 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
2002-06-04 15:02:26 +04:00
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> owningWindow = get_window_for_gtk_widget(owningWidget);
|
2002-04-27 20:26:10 +04:00
|
|
|
|
if (!owningWindow)
|
|
|
|
|
return NS_ERROR_FAILURE;
|
2002-01-22 09:21:09 +03:00
|
|
|
|
|
2010-06-03 07:50:49 +04:00
|
|
|
|
if (aRaise) {
|
2011-10-03 11:56:21 +04:00
|
|
|
|
// aRaise == true means request toplevel activation.
|
2009-02-28 04:47:40 +03:00
|
|
|
|
|
2010-06-03 07:50:49 +04:00
|
|
|
|
// This is asynchronous.
|
|
|
|
|
// If and when the window manager accepts the request, then the focus
|
|
|
|
|
// widget will get a focus-in-event signal.
|
|
|
|
|
if (gRaiseWindows && owningWindow->mIsShown && owningWindow->mShell &&
|
|
|
|
|
!gtk_window_is_active(GTK_WINDOW(owningWindow->mShell))) {
|
2009-02-28 04:47:40 +03:00
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
|
uint32_t timestamp = GDK_CURRENT_TIME;
|
2012-02-16 14:23:34 +04:00
|
|
|
|
|
|
|
|
|
nsGTKToolkit* GTKToolkit = nsGTKToolkit::GetToolkit();
|
|
|
|
|
if (GTKToolkit)
|
|
|
|
|
timestamp = GTKToolkit->GetFocusTimestamp();
|
|
|
|
|
|
2010-06-03 07:50:49 +04:00
|
|
|
|
LOGFOCUS((" requesting toplevel activation [%p]\n", (void *)this));
|
|
|
|
|
NS_ASSERTION(owningWindow->mWindowType != eWindowType_popup
|
|
|
|
|
|| mParent,
|
|
|
|
|
"Presenting an override-redirect window");
|
2012-02-16 14:23:34 +04:00
|
|
|
|
gtk_window_present_with_time(GTK_WINDOW(owningWindow->mShell), timestamp);
|
|
|
|
|
|
|
|
|
|
if (GTKToolkit)
|
|
|
|
|
GTKToolkit->SetFocusTimestamp(0);
|
2010-06-03 07:50:49 +04:00
|
|
|
|
}
|
2002-01-22 09:21:09 +03:00
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
return NS_OK;
|
2002-01-22 09:21:09 +03:00
|
|
|
|
}
|
|
|
|
|
|
2011-10-03 11:56:21 +04:00
|
|
|
|
// aRaise == false means that keyboard events should be dispatched
|
2010-06-03 07:50:49 +04:00
|
|
|
|
// from this widget.
|
|
|
|
|
|
|
|
|
|
// Ensure owningWidget is the focused GtkWidget within its toplevel window.
|
|
|
|
|
//
|
|
|
|
|
// For eWindowType_popup, this GtkWidget may not actually be the one that
|
|
|
|
|
// receives the key events as it may be the parent window that is active.
|
|
|
|
|
if (!gtk_widget_is_focus(owningWidget)) {
|
|
|
|
|
// This is synchronous. It takes focus from a plugin or from a widget
|
|
|
|
|
// in an embedder. The focus manager already knows that this window
|
|
|
|
|
// is active so gBlockActivateEvent avoids another (unnecessary)
|
2012-08-15 22:52:42 +04:00
|
|
|
|
// activate notification.
|
2011-10-03 11:56:21 +04:00
|
|
|
|
gBlockActivateEvent = true;
|
2010-06-03 07:50:49 +04:00
|
|
|
|
gtk_widget_grab_focus(owningWidget);
|
2011-10-03 11:56:21 +04:00
|
|
|
|
gBlockActivateEvent = false;
|
2010-06-03 07:50:49 +04:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
// If this is the widget that already has focus, return.
|
2002-11-06 06:29:02 +03:00
|
|
|
|
if (gFocusWindow == this) {
|
|
|
|
|
LOGFOCUS((" already have focus [%p]\n", (void *)this));
|
2002-04-27 20:26:10 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
// Set this window to be the focused child window
|
2002-11-06 06:29:02 +03:00
|
|
|
|
gFocusWindow = this;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2015-07-27 02:23:04 +03:00
|
|
|
|
if (mIMContext) {
|
|
|
|
|
mIMContext->OnFocusWindow(this);
|
2010-03-19 07:21:16 +03:00
|
|
|
|
}
|
2001-12-12 01:22:48 +03:00
|
|
|
|
|
2009-07-23 05:18:39 +04:00
|
|
|
|
LOGFOCUS((" widget now has focus in SetFocus() [%p]\n",
|
2002-11-06 06:29:02 +03:00
|
|
|
|
(void *)this));
|
|
|
|
|
|
2001-12-12 01:22:48 +03:00
|
|
|
|
return NS_OK;
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2015-11-13 03:04:52 +03:00
|
|
|
|
nsWindow::GetScreenBounds(LayoutDeviceIntRect& aRect)
|
2001-07-26 02:05:10 +04:00
|
|
|
|
{
|
2010-07-27 17:38:04 +04:00
|
|
|
|
if (mIsTopLevel && mContainer) {
|
|
|
|
|
// use the point including window decorations
|
|
|
|
|
gint x, y;
|
2011-09-23 00:58:07 +04:00
|
|
|
|
gdk_window_get_root_origin(gtk_widget_get_window(GTK_WIDGET(mContainer)), &x, &y);
|
2015-11-13 03:04:52 +03:00
|
|
|
|
aRect.MoveTo(GdkPointToDevicePixels({ x, y }));
|
2015-11-13 02:37:18 +03:00
|
|
|
|
} else {
|
2015-11-13 03:04:52 +03:00
|
|
|
|
aRect.MoveTo(WidgetToScreenOffset());
|
2010-07-27 17:38:04 +04:00
|
|
|
|
}
|
2011-07-08 07:14:27 +04:00
|
|
|
|
// mBounds.Size() is the window bounds, not the window-manager frame
|
|
|
|
|
// bounds (bug 581863). gdk_window_get_frame_extents would give the
|
|
|
|
|
// frame bounds, but mBounds.Size() is returned here for consistency
|
|
|
|
|
// with Resize.
|
2015-11-13 03:04:52 +03:00
|
|
|
|
aRect.SizeTo(LayoutDeviceIntSize::FromUnknownSize(mBounds.Size()));
|
|
|
|
|
LOG(("GetScreenBounds %d,%d | %dx%d\n",
|
2011-07-08 07:14:27 +04:00
|
|
|
|
aRect.x, aRect.y, aRect.width, aRect.height));
|
2002-04-27 20:26:10 +04:00
|
|
|
|
return NS_OK;
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
2015-02-14 14:37:32 +03:00
|
|
|
|
gfx::IntSize
|
|
|
|
|
nsWindow::GetClientSize()
|
|
|
|
|
{
|
|
|
|
|
return gfx::IntSize(mBounds.width, mBounds.height);
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-02 01:35:42 +04:00
|
|
|
|
NS_IMETHODIMP
|
2015-11-13 03:04:52 +03:00
|
|
|
|
nsWindow::GetClientBounds(LayoutDeviceIntRect& aRect)
|
2011-12-02 01:35:42 +04:00
|
|
|
|
{
|
|
|
|
|
// GetBounds returns a rect whose top left represents the top left of the
|
|
|
|
|
// outer bounds, but whose width/height represent the size of the inner
|
|
|
|
|
// bounds (which is messed up).
|
2015-11-13 03:04:52 +03:00
|
|
|
|
GetBounds(aRect);
|
|
|
|
|
aRect.MoveBy(GetClientOffset());
|
2011-12-02 01:35:42 +04:00
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-09 16:24:48 +03:00
|
|
|
|
void
|
|
|
|
|
nsWindow::UpdateClientOffset()
|
2011-12-02 01:35:42 +04:00
|
|
|
|
{
|
2015-10-09 16:24:48 +03:00
|
|
|
|
PROFILER_LABEL("nsWindow", "UpdateClientOffset", js::ProfileEntry::Category::GRAPHICS);
|
2015-02-14 14:37:32 +03:00
|
|
|
|
|
2015-04-21 10:52:00 +03:00
|
|
|
|
if (!mIsTopLevel || !mShell || !mGdkWindow ||
|
|
|
|
|
gtk_window_get_window_type(GTK_WINDOW(mShell)) == GTK_WINDOW_POPUP) {
|
2015-10-09 16:24:48 +03:00
|
|
|
|
mClientOffset = nsIntPoint(0, 0);
|
|
|
|
|
return;
|
2011-12-02 01:35:42 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL);
|
|
|
|
|
|
|
|
|
|
GdkAtom type_returned;
|
|
|
|
|
int format_returned;
|
|
|
|
|
int length_returned;
|
|
|
|
|
long *frame_extents;
|
|
|
|
|
|
2015-04-21 10:06:41 +03:00
|
|
|
|
if (!gdk_property_get(mGdkWindow,
|
2011-12-02 01:35:42 +04:00
|
|
|
|
gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE),
|
|
|
|
|
cardinal_atom,
|
|
|
|
|
0, // offset
|
|
|
|
|
4*4, // length
|
|
|
|
|
FALSE, // delete
|
|
|
|
|
&type_returned,
|
|
|
|
|
&format_returned,
|
|
|
|
|
&length_returned,
|
|
|
|
|
(guchar **) &frame_extents) ||
|
|
|
|
|
length_returned/sizeof(glong) != 4) {
|
2015-10-09 16:24:48 +03:00
|
|
|
|
mClientOffset = nsIntPoint(0, 0);
|
|
|
|
|
return;
|
2011-12-02 01:35:42 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// data returned is in the order left, right, top, bottom
|
2012-08-22 19:56:38 +04:00
|
|
|
|
int32_t left = int32_t(frame_extents[0]);
|
|
|
|
|
int32_t top = int32_t(frame_extents[2]);
|
2011-12-02 01:35:42 +04:00
|
|
|
|
|
|
|
|
|
g_free(frame_extents);
|
|
|
|
|
|
2015-10-09 16:24:48 +03:00
|
|
|
|
mClientOffset = nsIntPoint(left, top);
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-13 12:37:02 +03:00
|
|
|
|
LayoutDeviceIntPoint
|
|
|
|
|
nsWindow::GetClientOffset()
|
2015-10-09 16:24:48 +03:00
|
|
|
|
{
|
2015-11-13 12:37:02 +03:00
|
|
|
|
return LayoutDeviceIntPoint::FromUnknownPoint(mClientOffset);
|
2015-10-09 16:24:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nsWindow::OnPropertyNotifyEvent(GtkWidget* aWidget, GdkEventProperty* aEvent)
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
if (aEvent->atom == gdk_atom_intern("_NET_FRAME_EXTENTS", FALSE)) {
|
|
|
|
|
UpdateClientOffset();
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (GetCurrentTimeGetter()->PropertyNotifyHandler(aWidget, aEvent)) {
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
2011-12-02 01:35:42 +04:00
|
|
|
|
}
|
|
|
|
|
|
2001-07-26 02:05:10 +04:00
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
nsWindow::SetCursor(nsCursor aCursor)
|
|
|
|
|
{
|
2002-04-27 20:26:10 +04:00
|
|
|
|
// if we're not the toplevel window pass up the cursor request to
|
|
|
|
|
// the toplevel window to handle it.
|
2009-07-27 05:39:36 +04:00
|
|
|
|
if (!mContainer && mGdkWindow) {
|
2009-02-20 05:07:08 +03:00
|
|
|
|
nsWindow *window = GetContainerWindow();
|
|
|
|
|
if (!window)
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
return window->SetCursor(aCursor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Only change cursor if it's actually been changed
|
2014-05-28 05:12:29 +04:00
|
|
|
|
if (aCursor != mCursor || mUpdateCursor) {
|
2013-10-08 22:47:37 +04:00
|
|
|
|
GdkCursor *newCursor = nullptr;
|
2014-05-28 05:12:29 +04:00
|
|
|
|
mUpdateCursor = false;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
|
|
|
|
newCursor = get_gtk_cursor(aCursor);
|
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
|
if (nullptr != newCursor) {
|
2002-04-27 20:26:10 +04:00
|
|
|
|
mCursor = aCursor;
|
2003-03-06 02:17:28 +03:00
|
|
|
|
|
|
|
|
|
if (!mContainer)
|
|
|
|
|
return NS_OK;
|
|
|
|
|
|
2011-09-23 00:58:07 +04:00
|
|
|
|
gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(mContainer)), newCursor);
|
2002-04-27 20:26:10 +04:00
|
|
|
|
}
|
2002-01-28 09:47:47 +03:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
return NS_OK;
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
2005-03-16 01:24:20 +03:00
|
|
|
|
NS_IMETHODIMP
|
2005-07-01 08:29:42 +04:00
|
|
|
|
nsWindow::SetCursor(imgIContainer* aCursor,
|
2012-08-22 19:56:38 +04:00
|
|
|
|
uint32_t aHotspotX, uint32_t aHotspotY)
|
2005-03-16 01:24:20 +03:00
|
|
|
|
{
|
|
|
|
|
// if we're not the toplevel window pass up the cursor request to
|
|
|
|
|
// the toplevel window to handle it.
|
2009-07-27 05:39:36 +04:00
|
|
|
|
if (!mContainer && mGdkWindow) {
|
2009-02-20 05:07:08 +03:00
|
|
|
|
nsWindow *window = GetContainerWindow();
|
|
|
|
|
if (!window)
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
2005-07-01 08:29:42 +04:00
|
|
|
|
return window->SetCursor(aCursor, aHotspotX, aHotspotY);
|
2005-03-16 01:24:20 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mCursor = nsCursor(-1);
|
|
|
|
|
|
Bug 753 - Remove nsIImage, gfxIImageFrame, and their implementations, and expose an equivalent api on imgIContainer. r=roc,josh,bz,longsonr,vlad,karlt,jimm,bsmedberg,mfinkle,peterw,peterv sr=vlad,roc
--HG--
rename : gfx/src/shared/gfxImageFrame.cpp => modules/libpr0n/src/imgFrame.cpp
rename : gfx/src/shared/gfxImageFrame.h => modules/libpr0n/src/imgFrame.h
2009-07-21 05:50:15 +04:00
|
|
|
|
// Get the image's current frame
|
|
|
|
|
GdkPixbuf* pixbuf = nsImageToPixbuf::ImageToPixbuf(aCursor);
|
2005-03-16 01:24:20 +03:00
|
|
|
|
if (!pixbuf)
|
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
|
|
2007-01-25 05:17:22 +03:00
|
|
|
|
int width = gdk_pixbuf_get_width(pixbuf);
|
|
|
|
|
int height = gdk_pixbuf_get_height(pixbuf);
|
|
|
|
|
// Reject cursors greater than 128 pixels in some direction, to prevent
|
|
|
|
|
// spoofing.
|
|
|
|
|
// XXX ideally we should rescale. Also, we could modify the API to
|
|
|
|
|
// allow trusted content to set larger cursors.
|
2007-10-10 16:21:29 +04:00
|
|
|
|
if (width > 128 || height > 128) {
|
2009-02-02 20:49:58 +03:00
|
|
|
|
g_object_unref(pixbuf);
|
2007-01-25 05:17:22 +03:00
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
2007-10-10 16:21:29 +04:00
|
|
|
|
}
|
2007-01-25 05:17:22 +03:00
|
|
|
|
|
2005-03-16 01:24:20 +03:00
|
|
|
|
// Looks like all cursors need an alpha channel (tested on Gtk 2.4.4). This
|
|
|
|
|
// is of course not documented anywhere...
|
|
|
|
|
// So add one if there isn't one yet
|
|
|
|
|
if (!gdk_pixbuf_get_has_alpha(pixbuf)) {
|
|
|
|
|
GdkPixbuf* alphaBuf = gdk_pixbuf_add_alpha(pixbuf, FALSE, 0, 0, 0);
|
2009-02-02 20:49:58 +03:00
|
|
|
|
g_object_unref(pixbuf);
|
2005-03-16 01:24:20 +03:00
|
|
|
|
if (!alphaBuf) {
|
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
pixbuf = alphaBuf;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-23 00:58:07 +04:00
|
|
|
|
GdkCursor* cursor = gdk_cursor_new_from_pixbuf(gdk_display_get_default(),
|
|
|
|
|
pixbuf,
|
|
|
|
|
aHotspotX, aHotspotY);
|
2009-02-02 20:49:58 +03:00
|
|
|
|
g_object_unref(pixbuf);
|
2005-03-16 01:24:20 +03:00
|
|
|
|
nsresult rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
if (cursor) {
|
|
|
|
|
if (mContainer) {
|
2011-09-23 00:58:07 +04:00
|
|
|
|
gdk_window_set_cursor(gtk_widget_get_window(GTK_WIDGET(mContainer)), cursor);
|
2005-03-16 01:24:20 +03:00
|
|
|
|
rv = NS_OK;
|
|
|
|
|
}
|
2014-06-25 02:35:00 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 3)
|
|
|
|
|
g_object_unref(cursor);
|
|
|
|
|
#else
|
2005-03-16 01:24:20 +03:00
|
|
|
|
gdk_cursor_unref(cursor);
|
2014-06-25 02:35:00 +04:00
|
|
|
|
#endif
|
2005-03-16 01:24:20 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2001-07-26 02:05:10 +04:00
|
|
|
|
NS_IMETHODIMP
|
2011-12-24 07:52:21 +04:00
|
|
|
|
nsWindow::Invalidate(const nsIntRect &aRect)
|
2001-07-26 02:05:10 +04:00
|
|
|
|
{
|
2009-11-02 05:03:12 +03:00
|
|
|
|
if (!mGdkWindow)
|
2009-07-27 05:28:05 +04:00
|
|
|
|
return NS_OK;
|
2001-12-11 05:38:51 +03:00
|
|
|
|
|
2015-01-21 07:53:00 +03:00
|
|
|
|
GdkRectangle rect = DevicePixelsToGdkRectRoundOut(aRect);
|
|
|
|
|
gdk_window_invalidate_rect(mGdkWindow, &rect, FALSE);
|
2001-12-11 05:38:51 +03:00
|
|
|
|
|
2011-12-24 07:52:21 +04:00
|
|
|
|
LOGDRAW(("Invalidate (rect) [%p]: %d %d %d %d\n", (void *)this,
|
|
|
|
|
rect.x, rect.y, rect.width, rect.height));
|
2002-01-28 11:11:50 +03:00
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
return NS_OK;
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void*
|
2012-08-22 19:56:38 +04:00
|
|
|
|
nsWindow::GetNativeData(uint32_t aDataType)
|
2001-07-26 02:05:10 +04:00
|
|
|
|
{
|
2002-04-27 20:26:10 +04:00
|
|
|
|
switch (aDataType) {
|
|
|
|
|
case NS_NATIVE_WINDOW:
|
2003-02-14 18:11:42 +03:00
|
|
|
|
case NS_NATIVE_WIDGET: {
|
2009-07-27 05:39:36 +04:00
|
|
|
|
if (!mGdkWindow)
|
2012-07-30 18:20:58 +04:00
|
|
|
|
return nullptr;
|
2003-02-14 18:11:42 +03:00
|
|
|
|
|
2009-07-27 05:39:36 +04:00
|
|
|
|
return mGdkWindow;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
break;
|
2003-02-14 18:11:42 +03:00
|
|
|
|
}
|
2001-12-04 19:58:04 +03:00
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
case NS_NATIVE_PLUGIN_PORT:
|
2002-09-02 09:11:10 +04:00
|
|
|
|
return SetupPluginPort();
|
2002-04-27 20:26:10 +04:00
|
|
|
|
break;
|
2001-12-04 19:58:04 +03:00
|
|
|
|
|
2015-01-29 22:41:57 +03:00
|
|
|
|
case NS_NATIVE_PLUGIN_ID:
|
|
|
|
|
if (!mPluginNativeWindow) {
|
|
|
|
|
NS_WARNING("no native plugin instance!");
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
// Return the socket widget XID
|
|
|
|
|
return (void*)mPluginNativeWindow->window;
|
|
|
|
|
break;
|
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
case NS_NATIVE_DISPLAY:
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#ifdef MOZ_X11
|
2011-09-23 00:58:07 +04:00
|
|
|
|
return GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#else
|
2012-07-30 18:20:58 +04:00
|
|
|
|
return nullptr;
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#endif /* MOZ_X11 */
|
2002-04-27 20:26:10 +04:00
|
|
|
|
break;
|
2001-12-04 19:58:04 +03:00
|
|
|
|
|
2005-04-04 23:08:55 +04:00
|
|
|
|
case NS_NATIVE_SHELLWIDGET:
|
2012-11-07 01:50:37 +04:00
|
|
|
|
return GetToplevelWidget();
|
2005-04-04 23:08:55 +04:00
|
|
|
|
|
2011-08-31 23:01:38 +04:00
|
|
|
|
case NS_NATIVE_SHAREABLE_WINDOW:
|
|
|
|
|
return (void *) GDK_WINDOW_XID(gdk_window_get_toplevel(mGdkWindow));
|
2015-01-29 22:41:57 +03:00
|
|
|
|
case NS_NATIVE_PLUGIN_OBJECT_PTR:
|
|
|
|
|
return (void *) mPluginNativeWindow;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
default:
|
|
|
|
|
NS_WARNING("nsWindow::GetNativeData called with bad value");
|
2012-07-30 18:20:58 +04:00
|
|
|
|
return nullptr;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
}
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
2015-01-29 22:41:57 +03:00
|
|
|
|
void
|
|
|
|
|
nsWindow::SetNativeData(uint32_t aDataType, uintptr_t aVal)
|
|
|
|
|
{
|
|
|
|
|
if (aDataType != NS_NATIVE_PLUGIN_OBJECT_PTR) {
|
|
|
|
|
NS_WARNING("nsWindow::SetNativeData called with bad value");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
mPluginNativeWindow = (nsPluginNativeWindowGtk*)aVal;
|
|
|
|
|
}
|
|
|
|
|
|
2001-07-26 02:05:10 +04:00
|
|
|
|
NS_IMETHODIMP
|
2004-04-19 03:18:23 +04:00
|
|
|
|
nsWindow::SetTitle(const nsAString& aTitle)
|
2001-07-26 02:05:10 +04:00
|
|
|
|
{
|
2002-04-27 20:26:10 +04:00
|
|
|
|
if (!mShell)
|
|
|
|
|
return NS_OK;
|
2001-12-10 20:37:36 +03:00
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
// convert the string into utf8 and set the title.
|
2005-08-18 12:10:28 +04:00
|
|
|
|
#define UTF8_FOLLOWBYTE(ch) (((ch) & 0xC0) == 0x80)
|
|
|
|
|
NS_ConvertUTF16toUTF8 titleUTF8(aTitle);
|
|
|
|
|
if (titleUTF8.Length() > NS_WINDOW_TITLE_MAX_LENGTH) {
|
|
|
|
|
// Truncate overlong titles (bug 167315). Make sure we chop after a
|
|
|
|
|
// complete sequence by making sure the next char isn't a follow-byte.
|
2012-08-22 19:56:38 +04:00
|
|
|
|
uint32_t len = NS_WINDOW_TITLE_MAX_LENGTH;
|
2005-08-18 12:10:28 +04:00
|
|
|
|
while(UTF8_FOLLOWBYTE(titleUTF8[len]))
|
|
|
|
|
--len;
|
|
|
|
|
titleUTF8.Truncate(len);
|
|
|
|
|
}
|
|
|
|
|
gtk_window_set_title(GTK_WINDOW(mShell), (const char *)titleUTF8.get());
|
2001-12-10 20:37:36 +03:00
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
return NS_OK;
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2002-11-16 04:22:10 +03:00
|
|
|
|
nsWindow::SetIcon(const nsAString& aIconSpec)
|
2001-07-26 02:05:10 +04:00
|
|
|
|
{
|
2002-08-10 22:07:20 +04:00
|
|
|
|
if (!mShell)
|
|
|
|
|
return NS_OK;
|
|
|
|
|
|
2012-09-02 06:35:17 +04:00
|
|
|
|
nsAutoCString iconName;
|
2011-12-14 14:22:15 +04:00
|
|
|
|
|
|
|
|
|
if (aIconSpec.EqualsLiteral("default")) {
|
|
|
|
|
nsXPIDLString brandName;
|
|
|
|
|
GetBrandName(brandName);
|
|
|
|
|
AppendUTF16toUTF8(brandName, iconName);
|
|
|
|
|
ToLowerCase(iconName);
|
|
|
|
|
} else {
|
|
|
|
|
AppendUTF16toUTF8(aIconSpec, iconName);
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-06 06:08:30 +04:00
|
|
|
|
nsCOMPtr<nsIFile> iconFile;
|
2012-09-02 06:35:17 +04:00
|
|
|
|
nsAutoCString path;
|
2004-01-04 01:57:24 +03:00
|
|
|
|
|
2012-01-11 06:41:28 +04:00
|
|
|
|
gint *iconSizes =
|
|
|
|
|
gtk_icon_theme_get_icon_sizes(gtk_icon_theme_get_default(),
|
|
|
|
|
iconName.get());
|
|
|
|
|
bool foundIcon = (iconSizes[0] != 0);
|
|
|
|
|
g_free(iconSizes);
|
2004-01-04 01:57:24 +03:00
|
|
|
|
|
2011-12-14 14:22:15 +04:00
|
|
|
|
if (!foundIcon) {
|
|
|
|
|
// Look for icons with the following suffixes appended to the base name
|
|
|
|
|
// The last two entries (for the old XPM format) will be ignored unless
|
|
|
|
|
// no icons are found using other suffixes. XPM icons are deprecated.
|
2008-01-10 09:04:51 +03:00
|
|
|
|
|
2011-12-14 14:22:15 +04:00
|
|
|
|
const char extensions[6][7] = { ".png", "16.png", "32.png", "48.png",
|
|
|
|
|
".xpm", "16.xpm" };
|
2008-01-10 09:04:51 +03:00
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
|
for (uint32_t i = 0; i < ArrayLength(extensions); i++) {
|
2011-12-14 14:22:15 +04:00
|
|
|
|
// Don't bother looking for XPM versions if we found a PNG.
|
|
|
|
|
if (i == ArrayLength(extensions) - 2 && foundIcon)
|
|
|
|
|
break;
|
2004-01-04 01:57:24 +03:00
|
|
|
|
|
2011-12-14 14:22:15 +04:00
|
|
|
|
nsAutoString extension;
|
|
|
|
|
extension.AppendASCII(extensions[i]);
|
|
|
|
|
|
|
|
|
|
ResolveIconName(aIconSpec, extension, getter_AddRefs(iconFile));
|
|
|
|
|
if (iconFile) {
|
|
|
|
|
iconFile->GetNativePath(path);
|
2013-10-08 22:47:37 +04:00
|
|
|
|
GdkPixbuf *icon = gdk_pixbuf_new_from_file(path.get(), nullptr);
|
|
|
|
|
if (icon) {
|
2011-12-14 14:22:15 +04:00
|
|
|
|
gtk_icon_theme_add_builtin_icon(iconName.get(),
|
|
|
|
|
gdk_pixbuf_get_height(icon),
|
|
|
|
|
icon);
|
|
|
|
|
g_object_unref(icon);
|
|
|
|
|
foundIcon = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-01-10 09:04:51 +03:00
|
|
|
|
}
|
2004-09-07 22:59:27 +04:00
|
|
|
|
}
|
2004-01-04 01:57:24 +03:00
|
|
|
|
|
2004-09-07 22:59:27 +04:00
|
|
|
|
// leave the default icon intact if no matching icons were found
|
2011-12-14 14:22:15 +04:00
|
|
|
|
if (foundIcon) {
|
|
|
|
|
gtk_window_set_icon_name(GTK_WINDOW(mShell), iconName.get());
|
|
|
|
|
}
|
2004-01-04 01:57:24 +03:00
|
|
|
|
|
2011-12-14 14:22:15 +04:00
|
|
|
|
return NS_OK;
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
2011-12-14 14:22:15 +04:00
|
|
|
|
|
2015-02-04 23:21:03 +03:00
|
|
|
|
LayoutDeviceIntPoint
|
2009-02-19 03:11:49 +03:00
|
|
|
|
nsWindow::WidgetToScreenOffset()
|
2001-07-26 02:05:10 +04:00
|
|
|
|
{
|
2006-09-15 23:55:09 +04:00
|
|
|
|
gint x = 0, y = 0;
|
2001-12-11 09:21:22 +03:00
|
|
|
|
|
2010-07-27 17:38:04 +04:00
|
|
|
|
if (mGdkWindow) {
|
2009-07-27 05:39:36 +04:00
|
|
|
|
gdk_window_get_origin(mGdkWindow, &x, &y);
|
2002-04-27 20:26:10 +04:00
|
|
|
|
}
|
2001-12-11 09:21:22 +03:00
|
|
|
|
|
2015-01-21 07:53:00 +03:00
|
|
|
|
return GdkPointToDevicePixels({ x, y });
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2011-09-29 10:19:26 +04:00
|
|
|
|
nsWindow::EnableDragDrop(bool aEnable)
|
2001-07-26 02:05:10 +04:00
|
|
|
|
{
|
2002-08-10 20:18:44 +04:00
|
|
|
|
return NS_OK;
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2001-07-26 02:05:10 +04:00
|
|
|
|
NS_IMETHODIMP
|
2011-09-29 10:19:26 +04:00
|
|
|
|
nsWindow::CaptureMouse(bool aCapture)
|
2001-07-26 02:05:10 +04:00
|
|
|
|
{
|
2002-04-27 20:26:10 +04:00
|
|
|
|
LOG(("CaptureMouse %p\n", (void *)this));
|
|
|
|
|
|
2009-07-27 05:39:36 +04:00
|
|
|
|
if (!mGdkWindow)
|
2003-02-14 18:11:42 +03:00
|
|
|
|
return NS_OK;
|
|
|
|
|
|
2015-09-24 05:50:00 +03:00
|
|
|
|
if (!mContainer)
|
2009-02-20 05:07:08 +03:00
|
|
|
|
return NS_ERROR_FAILURE;
|
2002-01-28 09:23:27 +03:00
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
if (aCapture) {
|
2015-09-24 05:50:00 +03:00
|
|
|
|
gtk_grab_add(GTK_WIDGET(mContainer));
|
2012-02-14 00:19:59 +04:00
|
|
|
|
GrabPointer(GetLastUserInputTime());
|
2002-04-27 20:26:10 +04:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ReleaseGrabs();
|
2015-09-24 05:50:00 +03:00
|
|
|
|
gtk_grab_remove(GTK_WIDGET(mContainer));
|
2002-04-27 20:26:10 +04:00
|
|
|
|
}
|
2002-01-28 09:23:27 +03:00
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
return NS_OK;
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
|
nsWindow::CaptureRollupEvents(nsIRollupListener *aListener,
|
2012-10-26 17:15:22 +04:00
|
|
|
|
bool aDoCapture)
|
2002-04-27 20:26:10 +04:00
|
|
|
|
{
|
2009-07-27 05:39:36 +04:00
|
|
|
|
if (!mGdkWindow)
|
2003-02-14 18:11:42 +03:00
|
|
|
|
return NS_OK;
|
|
|
|
|
|
2015-09-24 05:50:00 +03:00
|
|
|
|
if (!mContainer)
|
2009-02-20 05:07:08 +03:00
|
|
|
|
return NS_ERROR_FAILURE;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2012-10-31 06:44:46 +04:00
|
|
|
|
LOG(("CaptureRollupEvents %p %i\n", this, int(aDoCapture)));
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
|
|
|
|
if (aDoCapture) {
|
|
|
|
|
gRollupListener = aListener;
|
2003-12-03 04:50:50 +03:00
|
|
|
|
// real grab is only done when there is no dragging
|
|
|
|
|
if (!nsWindow::DragInProgress()) {
|
2015-08-05 14:19:44 +03:00
|
|
|
|
// Maybe the dnd flag is not yet set at this point, but dnd has already started
|
|
|
|
|
// so let's be extra careful and skip this operation for dnd popup panels always
|
|
|
|
|
// (panels with type="drag").
|
|
|
|
|
GdkWindowTypeHint gdkTypeHint = gtk_window_get_type_hint(GTK_WINDOW(mShell));
|
|
|
|
|
if (gdkTypeHint != GDK_WINDOW_TYPE_HINT_DND) {
|
2015-09-24 05:50:00 +03:00
|
|
|
|
gtk_grab_add(GTK_WIDGET(mContainer));
|
2015-08-05 14:19:44 +03:00
|
|
|
|
GrabPointer(GetLastUserInputTime());
|
|
|
|
|
}
|
2003-12-03 04:50:50 +03:00
|
|
|
|
}
|
2002-04-27 20:26:10 +04:00
|
|
|
|
}
|
|
|
|
|
else {
|
2003-12-03 04:50:50 +03:00
|
|
|
|
if (!nsWindow::DragInProgress()) {
|
|
|
|
|
ReleaseGrabs();
|
|
|
|
|
}
|
2011-02-16 23:10:54 +03:00
|
|
|
|
// There may not have been a drag in process when aDoCapture was set,
|
|
|
|
|
// so make sure to remove any added grab. This is a no-op if the grab
|
|
|
|
|
// was not added to this widget.
|
2015-09-24 05:50:00 +03:00
|
|
|
|
gtk_grab_remove(GTK_WIDGET(mContainer));
|
2012-07-30 18:20:58 +04:00
|
|
|
|
gRollupListener = nullptr;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
}
|
2002-01-23 09:39:48 +03:00
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
return NS_OK;
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 19:56:38 +04:00
|
|
|
|
nsWindow::GetAttention(int32_t aCycleCount)
|
2001-07-26 02:05:10 +04:00
|
|
|
|
{
|
2002-04-27 20:26:10 +04:00
|
|
|
|
LOG(("nsWindow::GetAttention [%p]\n", (void *)this));
|
2002-06-04 15:02:26 +04:00
|
|
|
|
|
2012-11-07 01:50:37 +04:00
|
|
|
|
GtkWidget* top_window = GetToplevelWidget();
|
|
|
|
|
GtkWidget* top_focused_window =
|
2012-11-07 09:05:01 +04:00
|
|
|
|
gFocusWindow ? gFocusWindow->GetToplevelWidget() : nullptr;
|
2006-12-20 12:05:19 +03:00
|
|
|
|
|
|
|
|
|
// Don't get attention if the window is focused anyway.
|
2011-09-23 00:58:07 +04:00
|
|
|
|
if (top_window && (gtk_widget_get_visible(top_window)) &&
|
2006-12-20 12:05:19 +03:00
|
|
|
|
top_window != top_focused_window) {
|
2011-10-03 11:56:21 +04:00
|
|
|
|
SetUrgencyHint(top_window, true);
|
2002-06-04 15:02:26 +04:00
|
|
|
|
}
|
2004-10-11 08:01:49 +04:00
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
return NS_OK;
|
2001-07-26 02:05:10 +04:00
|
|
|
|
}
|
2001-12-04 19:58:04 +03:00
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool
|
2009-04-22 03:53:52 +04:00
|
|
|
|
nsWindow::HasPendingInputEvent()
|
|
|
|
|
{
|
|
|
|
|
// This sucks, but gtk/gdk has no way to answer the question we want while
|
|
|
|
|
// excluding paint events, and there's no X API that will let us peek
|
|
|
|
|
// without blocking or removing. To prevent event reordering, peek
|
|
|
|
|
// anything except expose events. Reordering expose and others should be
|
|
|
|
|
// ok, hopefully.
|
2015-06-21 22:27:07 +03:00
|
|
|
|
bool haveEvent = false;
|
2009-04-22 03:53:52 +04:00
|
|
|
|
#ifdef MOZ_X11
|
|
|
|
|
XEvent ev;
|
2015-03-05 05:56:00 +03:00
|
|
|
|
GdkDisplay* gdkDisplay = gdk_display_get_default();
|
|
|
|
|
if (GDK_IS_X11_DISPLAY(gdkDisplay)) {
|
|
|
|
|
Display *display = GDK_DISPLAY_XDISPLAY(gdkDisplay);
|
|
|
|
|
haveEvent =
|
|
|
|
|
XCheckMaskEvent(display,
|
|
|
|
|
KeyPressMask | KeyReleaseMask | ButtonPressMask |
|
|
|
|
|
ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
|
|
|
|
|
PointerMotionMask | PointerMotionHintMask |
|
|
|
|
|
Button1MotionMask | Button2MotionMask |
|
|
|
|
|
Button3MotionMask | Button4MotionMask |
|
|
|
|
|
Button5MotionMask | ButtonMotionMask | KeymapStateMask |
|
|
|
|
|
VisibilityChangeMask | StructureNotifyMask |
|
|
|
|
|
ResizeRedirectMask | SubstructureNotifyMask |
|
|
|
|
|
SubstructureRedirectMask | FocusChangeMask |
|
|
|
|
|
PropertyChangeMask | ColormapChangeMask |
|
|
|
|
|
OwnerGrabButtonMask, &ev);
|
|
|
|
|
if (haveEvent) {
|
|
|
|
|
XPutBackEvent(display, &ev);
|
|
|
|
|
}
|
2009-04-22 03:53:52 +04:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
return haveEvent;
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-28 06:04:06 +04:00
|
|
|
|
#if 0
|
2006-04-18 03:46:10 +04:00
|
|
|
|
#ifdef DEBUG
|
2008-08-28 06:04:06 +04:00
|
|
|
|
// Paint flashing code (disabled for cairo - see below)
|
2006-04-18 03:46:10 +04:00
|
|
|
|
|
|
|
|
|
#define CAPS_LOCK_IS_ON \
|
2012-02-22 11:34:31 +04:00
|
|
|
|
(KeymapWrapper::AreModifiersCurrentlyActive(KeymapWrapper::CAPS_LOCK))
|
2006-04-18 03:46:10 +04:00
|
|
|
|
|
|
|
|
|
#define WANT_PAINT_FLASHING \
|
|
|
|
|
(debug_WantPaintFlashing() && CAPS_LOCK_IS_ON)
|
|
|
|
|
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#ifdef MOZ_X11
|
2006-04-18 03:46:10 +04:00
|
|
|
|
static void
|
|
|
|
|
gdk_window_flash(GdkWindow * aGdkWindow,
|
|
|
|
|
unsigned int aTimes,
|
|
|
|
|
unsigned int aInterval, // Milliseconds
|
|
|
|
|
GdkRegion * aRegion)
|
|
|
|
|
{
|
|
|
|
|
gint x;
|
|
|
|
|
gint y;
|
|
|
|
|
gint width;
|
|
|
|
|
gint height;
|
|
|
|
|
guint i;
|
|
|
|
|
GdkGC * gc = 0;
|
|
|
|
|
GdkColor white;
|
|
|
|
|
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2013-10-08 22:47:37 +04:00
|
|
|
|
gdk_window_get_geometry(aGdkWindow,nullptr,nullptr,&width,&height,nullptr);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#else
|
2013-10-08 22:47:37 +04:00
|
|
|
|
gdk_window_get_geometry(aGdkWindow,nullptr,nullptr,&width,&height);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#endif
|
2006-04-18 03:46:10 +04:00
|
|
|
|
|
|
|
|
|
gdk_window_get_origin (aGdkWindow,
|
|
|
|
|
&x,
|
|
|
|
|
&y);
|
|
|
|
|
|
2013-05-31 19:48:33 +04:00
|
|
|
|
gc = gdk_gc_new(gdk_get_default_root_window());
|
2006-04-18 03:46:10 +04:00
|
|
|
|
|
|
|
|
|
white.pixel = WhitePixel(gdk_display,DefaultScreen(gdk_display));
|
|
|
|
|
|
|
|
|
|
gdk_gc_set_foreground(gc,&white);
|
|
|
|
|
gdk_gc_set_function(gc,GDK_XOR);
|
|
|
|
|
gdk_gc_set_subwindow(gc,GDK_INCLUDE_INFERIORS);
|
2009-02-28 04:47:40 +03:00
|
|
|
|
|
2006-04-18 03:46:10 +04:00
|
|
|
|
gdk_region_offset(aRegion, x, y);
|
|
|
|
|
gdk_gc_set_clip_region(gc, aRegion);
|
|
|
|
|
|
|
|
|
|
/*
|
2009-02-28 04:47:40 +03:00
|
|
|
|
* Need to do this twice so that the XOR effect can replace
|
2006-04-18 03:46:10 +04:00
|
|
|
|
* the original window contents.
|
|
|
|
|
*/
|
|
|
|
|
for (i = 0; i < aTimes * 2; i++)
|
|
|
|
|
{
|
2013-05-31 19:48:33 +04:00
|
|
|
|
gdk_draw_rectangle(gdk_get_default_root_window(),
|
2006-04-18 03:46:10 +04:00
|
|
|
|
gc,
|
|
|
|
|
TRUE,
|
|
|
|
|
x,
|
|
|
|
|
y,
|
|
|
|
|
width,
|
|
|
|
|
height);
|
|
|
|
|
|
|
|
|
|
gdk_flush();
|
2009-02-28 04:47:40 +03:00
|
|
|
|
|
2006-04-18 03:46:10 +04:00
|
|
|
|
PR_Sleep(PR_MillisecondsToInterval(aInterval));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gdk_gc_destroy(gc);
|
|
|
|
|
|
|
|
|
|
gdk_region_offset(aRegion, -x, -y);
|
|
|
|
|
}
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#endif /* MOZ_X11 */
|
2006-04-18 03:46:10 +04:00
|
|
|
|
#endif // DEBUG
|
2008-08-28 06:04:06 +04:00
|
|
|
|
#endif
|
2006-04-18 03:46:10 +04:00
|
|
|
|
|
2013-11-21 23:25:16 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2015-05-01 21:08:04 +03:00
|
|
|
|
static bool
|
|
|
|
|
ExtractExposeRegion(nsIntRegion& aRegion, GdkEventExpose* aEvent)
|
|
|
|
|
{
|
|
|
|
|
GdkRectangle* rects;
|
|
|
|
|
gint nrects;
|
|
|
|
|
gdk_region_get_rectangles(aEvent->region, &rects, &nrects);
|
2013-11-21 23:25:16 +04:00
|
|
|
|
|
2015-05-01 21:08:04 +03:00
|
|
|
|
if (nrects > MAX_RECTS_IN_REGION) {
|
|
|
|
|
// Just use the bounding box
|
|
|
|
|
rects[0] = aEvent->area;
|
|
|
|
|
nrects = 1;
|
|
|
|
|
}
|
2013-11-21 23:25:16 +04:00
|
|
|
|
|
2015-05-01 21:08:04 +03:00
|
|
|
|
for (GdkRectangle* r = rects; r < rects + nrects; r++) {
|
|
|
|
|
aRegion.Or(aRegion, nsIntRect(r->x, r->y, r->width, r->height));
|
|
|
|
|
LOGDRAW(("\t%d %d %d %d\n", r->x, r->y, r->width, r->height));
|
|
|
|
|
}
|
2013-11-21 23:25:16 +04:00
|
|
|
|
|
2015-05-01 21:08:04 +03:00
|
|
|
|
g_free(rects);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2013-11-21 23:25:16 +04:00
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
# ifdef cairo_copy_clip_rectangle_list
|
|
|
|
|
# error "Looks like we're including Mozilla's cairo instead of system cairo"
|
|
|
|
|
# endif
|
2015-05-01 21:08:04 +03:00
|
|
|
|
static bool
|
|
|
|
|
ExtractExposeRegion(nsIntRegion& aRegion, cairo_t* cr)
|
|
|
|
|
{
|
|
|
|
|
cairo_rectangle_list_t* rects = cairo_copy_clip_rectangle_list(cr);
|
|
|
|
|
if (rects->status != CAIRO_STATUS_SUCCESS) {
|
|
|
|
|
NS_WARNING("Failed to obtain cairo rectangle list.");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2013-11-21 23:25:16 +04:00
|
|
|
|
|
2015-05-01 21:08:04 +03:00
|
|
|
|
for (int i = 0; i < rects->num_rectangles; i++) {
|
|
|
|
|
const cairo_rectangle_t& r = rects->rectangles[i];
|
|
|
|
|
aRegion.Or(aRegion, nsIntRect(r.x, r.y, r.width, r.height));
|
|
|
|
|
LOGDRAW(("\t%d %d %d %d\n", r.x, r.y, r.width, r.height));
|
|
|
|
|
}
|
2013-11-21 23:25:16 +04:00
|
|
|
|
|
2015-05-01 21:08:04 +03:00
|
|
|
|
cairo_rectangle_list_destroy(rects);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2013-11-21 23:25:16 +04:00
|
|
|
|
#endif
|
|
|
|
|
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2011-09-23 00:58:07 +04:00
|
|
|
|
gboolean
|
|
|
|
|
nsWindow::OnExposeEvent(GdkEventExpose *aEvent)
|
|
|
|
|
#else
|
2001-12-10 20:37:36 +03:00
|
|
|
|
gboolean
|
2011-09-23 00:58:07 +04:00
|
|
|
|
nsWindow::OnExposeEvent(cairo_t *cr)
|
|
|
|
|
#endif
|
2001-12-10 20:37:36 +03:00
|
|
|
|
{
|
2015-11-11 03:50:04 +03:00
|
|
|
|
// Send any pending resize events so that layout can update.
|
|
|
|
|
// May run event loop.
|
|
|
|
|
MaybeDispatchResized();
|
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
if (mIsDestroyed) {
|
2006-04-18 03:46:10 +04:00
|
|
|
|
return FALSE;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
}
|
2001-12-10 20:37:36 +03:00
|
|
|
|
|
2009-11-02 05:03:12 +03:00
|
|
|
|
// Windows that are not visible will be painted after they become visible.
|
|
|
|
|
if (!mGdkWindow || mIsFullyObscured || !mHasMappedToplevel)
|
2002-04-27 20:26:10 +04:00
|
|
|
|
return FALSE;
|
2001-12-10 20:37:36 +03:00
|
|
|
|
|
2012-10-23 02:46:45 +04:00
|
|
|
|
nsIWidgetListener *listener =
|
|
|
|
|
mAttachedWidgetListener ? mAttachedWidgetListener : mWidgetListener;
|
|
|
|
|
if (!listener)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2015-05-01 21:08:04 +03:00
|
|
|
|
nsIntRegion exposeRegion;
|
2013-11-21 23:25:16 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2015-05-01 21:08:04 +03:00
|
|
|
|
if (!ExtractExposeRegion(exposeRegion, aEvent)) {
|
2013-11-21 23:25:16 +04:00
|
|
|
|
#else
|
2015-05-01 21:08:04 +03:00
|
|
|
|
if (!ExtractExposeRegion(exposeRegion, cr)) {
|
2013-11-21 23:25:16 +04:00
|
|
|
|
#endif
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-21 07:53:00 +03:00
|
|
|
|
gint scale = GdkScaleFactor();
|
2015-05-01 21:08:04 +03:00
|
|
|
|
nsIntRegion region = exposeRegion;
|
2015-01-21 07:53:00 +03:00
|
|
|
|
region.ScaleRoundOut(scale, scale);
|
2013-11-21 23:25:16 +04:00
|
|
|
|
|
2013-10-22 00:14:47 +04:00
|
|
|
|
ClientLayerManager *clientLayers =
|
2014-01-23 22:26:41 +04:00
|
|
|
|
(GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT)
|
2013-10-22 00:14:47 +04:00
|
|
|
|
? static_cast<ClientLayerManager*>(GetLayerManager())
|
|
|
|
|
: nullptr;
|
|
|
|
|
|
2014-03-07 06:25:09 +04:00
|
|
|
|
if (clientLayers && mCompositorParent) {
|
2013-10-22 00:14:47 +04:00
|
|
|
|
// We need to paint to the screen even if nothing changed, since if we
|
|
|
|
|
// don't have a compositing window manager, our pixels could be stale.
|
|
|
|
|
clientLayers->SetNeedsComposite(true);
|
2013-11-21 23:25:16 +04:00
|
|
|
|
clientLayers->SendInvalidRegion(region);
|
2013-09-19 04:17:02 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-08-15 22:52:42 +04:00
|
|
|
|
// Dispatch WillPaintWindow notification to allow scripts etc. to run
|
|
|
|
|
// before we paint
|
2011-01-26 09:26:37 +03:00
|
|
|
|
{
|
2013-01-28 23:34:08 +04:00
|
|
|
|
listener->WillPaintWindow(this);
|
2011-05-02 00:33:16 +04:00
|
|
|
|
|
2012-08-15 22:52:42 +04:00
|
|
|
|
// If the window has been destroyed during the will paint notification,
|
|
|
|
|
// there is nothing left to do.
|
2011-05-02 00:33:16 +04:00
|
|
|
|
if (!mGdkWindow)
|
|
|
|
|
return TRUE;
|
2012-12-13 01:57:08 +04:00
|
|
|
|
|
|
|
|
|
// Re-get the listener since the will paint notification might have
|
|
|
|
|
// killed it.
|
|
|
|
|
listener =
|
|
|
|
|
mAttachedWidgetListener ? mAttachedWidgetListener : mWidgetListener;
|
|
|
|
|
if (!listener)
|
|
|
|
|
return FALSE;
|
2011-01-26 09:26:37 +03:00
|
|
|
|
}
|
|
|
|
|
|
2013-10-22 00:14:47 +04:00
|
|
|
|
if (clientLayers && mCompositorParent && clientLayers->NeedsComposite()) {
|
|
|
|
|
mCompositorParent->ScheduleRenderOnCompositorThread();
|
|
|
|
|
clientLayers->SetNeedsComposite(false);
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-23 01:14:56 +04:00
|
|
|
|
LOGDRAW(("sending expose event [%p] %p 0x%lx (rects follow):\n",
|
2011-09-23 00:58:07 +04:00
|
|
|
|
(void *)this, (void *)mGdkWindow,
|
|
|
|
|
gdk_x11_window_get_xid(mGdkWindow)));
|
2012-08-15 22:52:42 +04:00
|
|
|
|
|
|
|
|
|
// Our bounds may have changed after calling WillPaintWindow. Clip
|
|
|
|
|
// to the new bounds here. The region is relative to this
|
2011-01-26 09:26:37 +03:00
|
|
|
|
// window.
|
2012-08-15 22:52:42 +04:00
|
|
|
|
region.And(region, nsIntRect(0, 0, mBounds.width, mBounds.height));
|
2011-01-26 09:26:37 +03:00
|
|
|
|
|
2012-10-03 10:53:57 +04:00
|
|
|
|
bool shaped = false;
|
|
|
|
|
if (eTransparencyTransparent == GetTransparencyMode()) {
|
|
|
|
|
GdkScreen *screen = gdk_window_get_screen(mGdkWindow);
|
|
|
|
|
if (gdk_screen_is_composited(screen) &&
|
|
|
|
|
gdk_window_get_visual(mGdkWindow) ==
|
|
|
|
|
gdk_screen_get_rgba_visual(screen)) {
|
|
|
|
|
// Remove possible shape mask from when window manger was not
|
|
|
|
|
// previously compositing.
|
|
|
|
|
static_cast<nsWindow*>(GetTopLevelWidget())->
|
|
|
|
|
ClearTransparencyBitmap();
|
|
|
|
|
} else {
|
|
|
|
|
shaped = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!shaped) {
|
2009-07-22 04:44:55 +04:00
|
|
|
|
GList *children =
|
2009-07-27 05:39:36 +04:00
|
|
|
|
gdk_window_peek_children(mGdkWindow);
|
2009-07-22 04:44:55 +04:00
|
|
|
|
while (children) {
|
|
|
|
|
GdkWindow *gdkWin = GDK_WINDOW(children->data);
|
|
|
|
|
nsWindow *kid = get_window_for_gdk_window(gdkWin);
|
2009-07-24 06:08:07 +04:00
|
|
|
|
if (kid && gdk_window_is_visible(gdkWin)) {
|
2009-07-22 04:44:55 +04:00
|
|
|
|
nsAutoTArray<nsIntRect,1> clipRects;
|
|
|
|
|
kid->GetWindowClipRegion(&clipRects);
|
|
|
|
|
nsIntRect bounds;
|
2015-11-10 08:37:32 +03:00
|
|
|
|
kid->GetBoundsUntyped(bounds);
|
2012-08-22 19:56:38 +04:00
|
|
|
|
for (uint32_t i = 0; i < clipRects.Length(); ++i) {
|
2009-07-22 04:44:55 +04:00
|
|
|
|
nsIntRect r = clipRects[i] + bounds.TopLeft();
|
2012-08-15 22:52:42 +04:00
|
|
|
|
region.Sub(region, r);
|
2009-07-22 04:44:55 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
children = children->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-15 22:52:42 +04:00
|
|
|
|
if (region.IsEmpty()) {
|
2009-07-22 04:44:55 +04:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2013-11-21 23:25:16 +04:00
|
|
|
|
|
2012-05-04 21:07:34 +04:00
|
|
|
|
// If this widget uses OMTC...
|
2014-01-23 22:26:41 +04:00
|
|
|
|
if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT) {
|
2013-05-23 18:49:18 +04:00
|
|
|
|
listener->PaintWindow(this, region);
|
2012-10-23 02:46:45 +04:00
|
|
|
|
listener->DidPaintWindow();
|
2010-06-18 01:23:00 +04:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2012-07-31 04:42:26 +04:00
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<DrawTarget> dt = GetDrawTarget(region);
|
2015-05-01 21:08:04 +03:00
|
|
|
|
if(!dt) {
|
|
|
|
|
return FALSE;
|
2013-09-20 06:00:35 +04:00
|
|
|
|
}
|
2015-11-11 18:15:40 +03:00
|
|
|
|
RefPtr<gfxContext> ctx;
|
2013-09-20 06:00:35 +04:00
|
|
|
|
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#ifdef MOZ_X11
|
2012-10-03 10:53:57 +04:00
|
|
|
|
nsIntRect boundsRect; // for shaped only
|
2006-04-13 01:58:14 +04:00
|
|
|
|
|
2012-10-03 10:53:57 +04:00
|
|
|
|
if (shaped) {
|
2006-04-13 01:58:14 +04:00
|
|
|
|
// Collapse update area to the bounding box. This is so we only have to
|
|
|
|
|
// call UpdateTranslucentWindowAlpha once. After we have dropped
|
|
|
|
|
// support for non-Thebes graphics, UpdateTranslucentWindowAlpha will be
|
|
|
|
|
// our private interface so we can rework things to avoid this.
|
2012-08-15 22:52:42 +04:00
|
|
|
|
boundsRect = region.GetBounds();
|
2015-11-11 18:15:40 +03:00
|
|
|
|
dt->PushClipRect(Rect(boundsRect.x, boundsRect.y,
|
|
|
|
|
boundsRect.width, boundsRect.height));
|
2006-02-21 01:43:44 +03:00
|
|
|
|
} else {
|
2015-11-11 18:15:40 +03:00
|
|
|
|
gfxUtils::ClipToRegion(dt, region);
|
2006-02-21 01:43:44 +03:00
|
|
|
|
}
|
2006-04-13 01:58:14 +04:00
|
|
|
|
|
2012-07-31 04:42:26 +04:00
|
|
|
|
BufferMode layerBuffering;
|
2012-10-03 10:53:57 +04:00
|
|
|
|
if (shaped) {
|
2010-07-16 01:08:09 +04:00
|
|
|
|
// The double buffering is done here to extract the shape mask.
|
|
|
|
|
// (The shape mask won't be necessary when a visual with an alpha
|
|
|
|
|
// channel is used on compositing window managers.)
|
2014-01-23 22:26:41 +04:00
|
|
|
|
layerBuffering = mozilla::layers::BufferMode::BUFFER_NONE;
|
2015-11-11 18:15:40 +03:00
|
|
|
|
RefPtr<DrawTarget> destDT = dt->CreateSimilarDrawTarget(IntSize(boundsRect.width, boundsRect.height), SurfaceFormat::B8G8R8A8);
|
|
|
|
|
ctx = new gfxContext(destDT, Point(boundsRect.x, boundsRect.y));
|
2010-09-24 05:00:06 +04:00
|
|
|
|
#ifdef MOZ_HAVE_SHMIMAGE
|
2006-04-13 01:58:14 +04:00
|
|
|
|
} else {
|
2015-11-11 18:15:40 +03:00
|
|
|
|
if (nsShmImage::UseShm()) {
|
|
|
|
|
// We're using an xshm mapping as a back buffer.
|
|
|
|
|
layerBuffering = mozilla::layers::BufferMode::BUFFER_NONE;
|
|
|
|
|
#endif // MOZ_HAVE_SHMIMAGE
|
|
|
|
|
} else {
|
|
|
|
|
// Get the layer manager to do double buffering (if necessary).
|
|
|
|
|
layerBuffering = mozilla::layers::BufferMode::BUFFERED;
|
|
|
|
|
}
|
|
|
|
|
ctx = new gfxContext(dt);
|
2006-04-13 01:58:14 +04:00
|
|
|
|
}
|
2006-04-18 03:46:10 +04:00
|
|
|
|
|
2007-06-16 06:13:52 +04:00
|
|
|
|
#if 0
|
2006-04-18 03:46:10 +04:00
|
|
|
|
// NOTE: Paint flashing region would be wrong for cairo, since
|
|
|
|
|
// cairo inflates the update region, etc. So don't paint flash
|
|
|
|
|
// for cairo.
|
2007-06-16 06:13:52 +04:00
|
|
|
|
#ifdef DEBUG
|
2011-01-26 09:26:37 +03:00
|
|
|
|
// XXX aEvent->region may refer to a newly-invalid area. FIXME
|
2011-09-23 00:58:07 +04:00
|
|
|
|
if (0 && WANT_PAINT_FLASHING && gtk_widget_get_window(aEvent))
|
|
|
|
|
gdk_window_flash(mGdkWindow, 1, 100, aEvent->region);
|
2007-06-16 06:13:52 +04:00
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#endif // MOZ_X11
|
|
|
|
|
|
2012-08-15 22:52:42 +04:00
|
|
|
|
bool painted = false;
|
2010-03-01 11:03:49 +03:00
|
|
|
|
{
|
2014-01-23 22:26:41 +04:00
|
|
|
|
if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC) {
|
2013-05-10 01:02:50 +04:00
|
|
|
|
AutoLayerManagerSetup setupLayerManager(this, ctx, layerBuffering);
|
2013-05-23 18:49:18 +04:00
|
|
|
|
painted = listener->PaintWindow(this, region);
|
2013-05-10 01:02:50 +04:00
|
|
|
|
}
|
2010-03-01 11:03:49 +03:00
|
|
|
|
}
|
2001-12-10 20:37:36 +03:00
|
|
|
|
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#ifdef MOZ_X11
|
2012-08-15 22:52:42 +04:00
|
|
|
|
// PaintWindow can Destroy us (bug 378273), avoid doing any paint
|
2007-04-30 04:46:47 +04:00
|
|
|
|
// operations below if that happened - it will lead to XError and exit().
|
2012-10-03 10:53:57 +04:00
|
|
|
|
if (shaped) {
|
2012-10-26 17:32:10 +04:00
|
|
|
|
if (MOZ_LIKELY(!mIsDestroyed)) {
|
2012-08-15 22:52:42 +04:00
|
|
|
|
if (painted) {
|
2015-11-11 18:15:40 +03:00
|
|
|
|
RefPtr<SourceSurface> surf = ctx->GetDrawTarget()->Snapshot();
|
2007-04-30 04:46:47 +04:00
|
|
|
|
|
2015-11-11 18:15:40 +03:00
|
|
|
|
UpdateAlpha(surf, boundsRect);
|
2011-05-13 04:05:05 +04:00
|
|
|
|
|
2015-11-11 18:15:40 +03:00
|
|
|
|
dt->DrawSurface(surf, Rect(boundsRect.x, boundsRect.y, boundsRect.width, boundsRect.height),
|
|
|
|
|
Rect(0, 0, boundsRect.width, boundsRect.height),
|
|
|
|
|
DrawSurfaceOptions(Filter::POINT), DrawOptions(1.0f, CompositionOp::OP_SOURCE));
|
2007-04-30 04:46:47 +04:00
|
|
|
|
}
|
2006-04-13 01:58:14 +04:00
|
|
|
|
}
|
2007-04-30 04:46:47 +04:00
|
|
|
|
}
|
2015-11-11 18:15:40 +03:00
|
|
|
|
|
|
|
|
|
ctx = nullptr;
|
|
|
|
|
dt->PopClip();
|
|
|
|
|
|
2010-09-24 05:00:06 +04:00
|
|
|
|
# ifdef MOZ_HAVE_SHMIMAGE
|
2014-04-22 07:11:42 +04:00
|
|
|
|
if (mShmImage && MOZ_LIKELY(!mIsDestroyed)) {
|
2015-09-15 23:46:39 +03:00
|
|
|
|
mShmImage->Put(mXDisplay, mXWindow, region);
|
2010-09-24 05:00:06 +04:00
|
|
|
|
}
|
|
|
|
|
# endif // MOZ_HAVE_SHMIMAGE
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#endif // MOZ_X11
|
|
|
|
|
|
2012-10-23 02:46:45 +04:00
|
|
|
|
listener->DidPaintWindow();
|
2010-07-16 01:08:08 +04:00
|
|
|
|
|
|
|
|
|
// Synchronously flush any new dirty areas
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2010-07-16 01:08:08 +04:00
|
|
|
|
GdkRegion* dirtyArea = gdk_window_get_update_area(mGdkWindow);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#else
|
|
|
|
|
cairo_region_t* dirtyArea = gdk_window_get_update_area(mGdkWindow);
|
|
|
|
|
#endif
|
|
|
|
|
|
2010-07-16 01:08:08 +04:00
|
|
|
|
if (dirtyArea) {
|
2011-10-03 11:56:21 +04:00
|
|
|
|
gdk_window_invalidate_region(mGdkWindow, dirtyArea, false);
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2010-07-16 01:08:08 +04:00
|
|
|
|
gdk_region_destroy(dirtyArea);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#else
|
|
|
|
|
cairo_region_destroy(dirtyArea);
|
|
|
|
|
#endif
|
2011-10-03 11:56:21 +04:00
|
|
|
|
gdk_window_process_updates(mGdkWindow, false);
|
2010-07-16 01:08:08 +04:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
// check the return value!
|
|
|
|
|
return TRUE;
|
2001-12-10 20:37:36 +03:00
|
|
|
|
}
|
|
|
|
|
|
2013-09-20 06:00:35 +04:00
|
|
|
|
void
|
2015-11-11 18:46:12 +03:00
|
|
|
|
nsWindow::UpdateAlpha(SourceSurface* aSourceSurface, nsIntRect aBoundsRect)
|
2013-09-20 06:00:35 +04:00
|
|
|
|
{
|
2014-03-19 06:36:58 +04:00
|
|
|
|
// We need to create our own buffer to force the stride to match the
|
|
|
|
|
// expected stride.
|
|
|
|
|
int32_t stride = GetAlignedStride<4>(BytesPerPixel(SurfaceFormat::A8) *
|
|
|
|
|
aBoundsRect.width);
|
|
|
|
|
int32_t bufferSize = stride * aBoundsRect.height;
|
2015-11-06 00:24:24 +03:00
|
|
|
|
auto imageBuffer = MakeUniqueFallible<uint8_t[]>(bufferSize);
|
2015-11-11 18:15:40 +03:00
|
|
|
|
{
|
|
|
|
|
RefPtr<DrawTarget> drawTarget = gfxPlatform::GetPlatform()->
|
2015-11-11 19:09:56 +03:00
|
|
|
|
CreateDrawTargetForData(imageBuffer.get(), aBoundsRect.Size(),
|
2015-11-11 18:15:40 +03:00
|
|
|
|
stride, SurfaceFormat::A8);
|
|
|
|
|
|
|
|
|
|
if (drawTarget) {
|
|
|
|
|
drawTarget->DrawSurface(aSourceSurface, Rect(aBoundsRect.x, aBoundsRect.y, aBoundsRect.width, aBoundsRect.height),
|
|
|
|
|
Rect(0, 0, aSourceSurface->GetSize().width, aSourceSurface->GetSize().height),
|
|
|
|
|
DrawSurfaceOptions(Filter::POINT), DrawOptions(1.0f, CompositionOp::OP_SOURCE));
|
|
|
|
|
}
|
2014-03-19 06:36:58 +04:00
|
|
|
|
}
|
2015-10-30 21:35:28 +03:00
|
|
|
|
UpdateTranslucentWindowAlphaInternal(aBoundsRect, imageBuffer.get(), stride);
|
2013-09-20 06:00:35 +04:00
|
|
|
|
}
|
|
|
|
|
|
2001-12-10 20:37:36 +03:00
|
|
|
|
gboolean
|
|
|
|
|
nsWindow::OnConfigureEvent(GtkWidget *aWidget, GdkEventConfigure *aEvent)
|
|
|
|
|
{
|
2011-07-08 07:14:27 +04:00
|
|
|
|
// These events are only received on toplevel windows.
|
|
|
|
|
//
|
|
|
|
|
// GDK ensures that the coordinates are the client window top-left wrt the
|
|
|
|
|
// root window.
|
|
|
|
|
//
|
|
|
|
|
// GDK calculates the cordinates for real ConfigureNotify events on
|
|
|
|
|
// managed windows (that would normally be relative to the parent
|
|
|
|
|
// window).
|
|
|
|
|
//
|
|
|
|
|
// Synthetic ConfigureNotify events are from the window manager and
|
|
|
|
|
// already relative to the root window. GDK creates all X windows with
|
|
|
|
|
// border_width = 0, so synthetic events also indicate the top-left of
|
|
|
|
|
// the client window.
|
|
|
|
|
//
|
|
|
|
|
// Override-redirect windows are children of the root window so parent
|
|
|
|
|
// coordinates are root coordinates.
|
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
LOG(("configure event [%p] %d %d %d %d\n", (void *)this,
|
|
|
|
|
aEvent->x, aEvent->y, aEvent->width, aEvent->height));
|
2001-12-10 20:37:36 +03:00
|
|
|
|
|
2011-12-02 01:35:42 +04:00
|
|
|
|
nsIntRect screenBounds;
|
2015-11-10 08:37:32 +03:00
|
|
|
|
GetScreenBoundsUntyped(screenBounds);
|
2011-08-08 09:28:06 +04:00
|
|
|
|
|
2010-09-16 15:24:08 +04:00
|
|
|
|
if (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog) {
|
2011-12-02 01:35:42 +04:00
|
|
|
|
// This check avoids unwanted rollup on spurious configure events from
|
|
|
|
|
// Cygwin/X (bug 672103).
|
|
|
|
|
if (mBounds.x != screenBounds.x ||
|
|
|
|
|
mBounds.y != screenBounds.y) {
|
2012-10-26 17:15:22 +04:00
|
|
|
|
CheckForRollup(0, 0, false, true);
|
2011-12-02 01:35:42 +04:00
|
|
|
|
}
|
2010-09-16 15:24:08 +04:00
|
|
|
|
}
|
|
|
|
|
|
2011-07-08 07:14:27 +04:00
|
|
|
|
// This event indicates that the window position may have changed.
|
|
|
|
|
// mBounds.Size() is updated in OnSizeAllocate().
|
|
|
|
|
|
|
|
|
|
NS_ASSERTION(GTK_IS_WINDOW(aWidget),
|
|
|
|
|
"Configure event on widget that is not a GtkWindow");
|
2015-04-21 09:17:24 +03:00
|
|
|
|
if (gtk_window_get_window_type(GTK_WINDOW(aWidget)) == GTK_WINDOW_POPUP) {
|
2011-07-08 07:14:27 +04:00
|
|
|
|
// Override-redirect window
|
|
|
|
|
//
|
|
|
|
|
// These windows should not be moved by the window manager, and so any
|
|
|
|
|
// change in position is a result of our direction. mBounds has
|
|
|
|
|
// already been set in Move() or Resize(), and that is more
|
|
|
|
|
// up-to-date than the position in the ConfigureNotify event if the
|
|
|
|
|
// event is from an earlier window move.
|
|
|
|
|
//
|
2012-08-15 22:52:42 +04:00
|
|
|
|
// Skipping the WindowMoved call saves context menus from an infinite
|
2011-07-08 07:14:27 +04:00
|
|
|
|
// loop when nsXULPopupManager::PopupMoved moves the window to the new
|
|
|
|
|
// position and nsMenuPopupFrame::SetPopupPosition adds
|
|
|
|
|
// offsetForContextMenu on each iteration.
|
|
|
|
|
return FALSE;
|
2004-05-28 00:18:59 +04:00
|
|
|
|
}
|
|
|
|
|
|
2011-12-02 01:35:42 +04:00
|
|
|
|
mBounds.MoveTo(screenBounds.TopLeft());
|
2011-07-08 07:14:27 +04:00
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
// XXX mozilla will invalidate the entire window after this move
|
|
|
|
|
// complete. wtf?
|
2014-02-28 11:45:08 +04:00
|
|
|
|
NotifyWindowMoved(mBounds.x, mBounds.y);
|
2001-12-10 20:37:36 +03:00
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
return FALSE;
|
2001-12-10 20:37:36 +03:00
|
|
|
|
}
|
|
|
|
|
|
2009-05-15 06:14:45 +04:00
|
|
|
|
void
|
2012-10-23 02:33:30 +04:00
|
|
|
|
nsWindow::OnContainerUnrealize()
|
2009-05-15 06:14:45 +04:00
|
|
|
|
{
|
|
|
|
|
// The GdkWindows are about to be destroyed (but not deleted), so remove
|
|
|
|
|
// their references back to their container widget while the GdkWindow
|
|
|
|
|
// hierarchy is still available.
|
|
|
|
|
|
2009-07-27 05:39:36 +04:00
|
|
|
|
if (mGdkWindow) {
|
2009-11-11 00:57:25 +03:00
|
|
|
|
DestroyChildWindows();
|
2009-07-27 05:40:46 +04:00
|
|
|
|
|
2013-10-08 22:47:37 +04:00
|
|
|
|
g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", nullptr);
|
|
|
|
|
mGdkWindow = nullptr;
|
2009-05-15 06:14:45 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-11 10:20:30 +03:00
|
|
|
|
void
|
2012-10-23 02:33:30 +04:00
|
|
|
|
nsWindow::OnSizeAllocate(GtkAllocation *aAllocation)
|
2001-12-11 10:20:30 +03:00
|
|
|
|
{
|
2002-04-27 20:26:10 +04:00
|
|
|
|
LOG(("size_allocate [%p] %d %d %d %d\n",
|
|
|
|
|
(void *)this, aAllocation->x, aAllocation->y,
|
|
|
|
|
aAllocation->width, aAllocation->height));
|
|
|
|
|
|
2015-01-21 07:53:00 +03:00
|
|
|
|
nsIntSize size = GdkRectToDevicePixels(*aAllocation).Size();
|
|
|
|
|
|
2012-10-23 02:40:50 +04:00
|
|
|
|
if (mBounds.Size() == size)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Invalidate the new part of the window now for the pending paint to
|
|
|
|
|
// minimize background flashes (GDK does not do this for external resizes
|
|
|
|
|
// of toplevels.)
|
|
|
|
|
if (mBounds.width < size.width) {
|
2015-01-21 07:53:00 +03:00
|
|
|
|
GdkRectangle rect = DevicePixelsToGdkRectRoundOut(
|
|
|
|
|
{ mBounds.width, 0, size.width - mBounds.width, size.height });
|
2012-10-23 02:40:50 +04:00
|
|
|
|
gdk_window_invalidate_rect(mGdkWindow, &rect, FALSE);
|
|
|
|
|
}
|
|
|
|
|
if (mBounds.height < size.height) {
|
2015-01-21 07:53:00 +03:00
|
|
|
|
GdkRectangle rect = DevicePixelsToGdkRectRoundOut(
|
|
|
|
|
{ 0, mBounds.height, size.width, size.height - mBounds.height });
|
2012-10-23 02:40:50 +04:00
|
|
|
|
gdk_window_invalidate_rect(mGdkWindow, &rect, FALSE);
|
|
|
|
|
}
|
2001-12-11 10:20:30 +03:00
|
|
|
|
|
2012-10-23 02:40:50 +04:00
|
|
|
|
mBounds.SizeTo(size);
|
2001-12-11 10:20:30 +03:00
|
|
|
|
|
2015-11-11 03:50:04 +03:00
|
|
|
|
// Gecko permits running nested event loops during processing of events,
|
|
|
|
|
// GtkWindow callers of gtk_widget_size_allocate expect the signal
|
|
|
|
|
// handlers to return sometime in the near future.
|
|
|
|
|
mNeedsDispatchResized = true;
|
|
|
|
|
nsCOMPtr<nsIRunnable> r =
|
|
|
|
|
NS_NewRunnableMethod(this, &nsWindow::MaybeDispatchResized);
|
|
|
|
|
NS_DispatchToCurrentThread(r.forget());
|
2001-12-11 10:20:30 +03:00
|
|
|
|
}
|
|
|
|
|
|
2001-12-10 20:37:36 +03:00
|
|
|
|
void
|
2012-10-23 02:33:30 +04:00
|
|
|
|
nsWindow::OnDeleteEvent()
|
2001-12-10 20:37:36 +03:00
|
|
|
|
{
|
2012-08-15 22:52:42 +04:00
|
|
|
|
if (mWidgetListener)
|
|
|
|
|
mWidgetListener->RequestWindowClose(this);
|
2001-12-10 20:37:36 +03:00
|
|
|
|
}
|
|
|
|
|
|
2001-12-11 05:38:51 +03:00
|
|
|
|
void
|
2012-10-23 02:33:30 +04:00
|
|
|
|
nsWindow::OnEnterNotifyEvent(GdkEventCrossing *aEvent)
|
2001-12-11 05:38:51 +03:00
|
|
|
|
{
|
2010-03-24 06:37:06 +03:00
|
|
|
|
// This skips NotifyVirtual and NotifyNonlinearVirtual enter notify events
|
|
|
|
|
// when the pointer enters a child window. If the destination window is a
|
|
|
|
|
// Gecko window then we'll catch the corresponding event on that window,
|
|
|
|
|
// but we won't notice when the pointer directly enters a foreign (plugin)
|
|
|
|
|
// child window without passing over a visible portion of a Gecko window.
|
2013-10-08 22:47:37 +04:00
|
|
|
|
if (aEvent->subwindow != nullptr)
|
2004-06-22 08:29:59 +04:00
|
|
|
|
return;
|
|
|
|
|
|
2010-03-24 06:37:06 +03:00
|
|
|
|
// Check before is_parent_ungrab_enter() as the button state may have
|
|
|
|
|
// changed while a non-Gecko ancestor window had a pointer grab.
|
|
|
|
|
DispatchMissedButtonReleases(aEvent);
|
|
|
|
|
|
|
|
|
|
if (is_parent_ungrab_enter(aEvent))
|
|
|
|
|
return;
|
|
|
|
|
|
2015-08-29 02:58:31 +03:00
|
|
|
|
WidgetMouseEvent event(true, eMouseEnterIntoWidget, this,
|
|
|
|
|
WidgetMouseEvent::eReal);
|
2001-12-11 05:38:51 +03:00
|
|
|
|
|
2015-10-13 22:09:40 +03:00
|
|
|
|
event.refPoint = GdkEventCoordsToDevicePixels(aEvent->x, aEvent->y);
|
2007-01-24 01:51:38 +03:00
|
|
|
|
event.time = aEvent->time;
|
2015-08-11 10:40:34 +03:00
|
|
|
|
event.timeStamp = GetEventTimeStamp(aEvent->time);
|
2007-01-24 01:51:38 +03:00
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
LOG(("OnEnterNotify: %p\n", (void *)this));
|
2002-01-28 11:11:50 +03:00
|
|
|
|
|
2015-03-17 02:29:55 +03:00
|
|
|
|
DispatchInputEvent(&event);
|
2001-12-11 05:38:51 +03:00
|
|
|
|
}
|
|
|
|
|
|
2010-03-24 06:37:06 +03:00
|
|
|
|
// XXX Is this the right test for embedding cases?
|
2011-09-29 10:19:26 +04:00
|
|
|
|
static bool
|
2008-03-13 01:44:45 +03:00
|
|
|
|
is_top_level_mouse_exit(GdkWindow* aWindow, GdkEventCrossing *aEvent)
|
|
|
|
|
{
|
|
|
|
|
gint x = gint(aEvent->x_root);
|
|
|
|
|
gint y = gint(aEvent->y_root);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
GdkDisplay* display = gdk_window_get_display(aWindow);
|
2008-03-13 01:44:45 +03:00
|
|
|
|
GdkWindow* winAtPt = gdk_display_get_window_at_pointer(display, &x, &y);
|
|
|
|
|
if (!winAtPt)
|
2011-10-03 11:56:21 +04:00
|
|
|
|
return true;
|
2008-03-13 01:44:45 +03:00
|
|
|
|
GdkWindow* topLevelAtPt = gdk_window_get_toplevel(winAtPt);
|
|
|
|
|
GdkWindow* topLevelWidget = gdk_window_get_toplevel(aWindow);
|
|
|
|
|
return topLevelAtPt != topLevelWidget;
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-11 05:38:51 +03:00
|
|
|
|
void
|
2012-10-23 02:33:30 +04:00
|
|
|
|
nsWindow::OnLeaveNotifyEvent(GdkEventCrossing *aEvent)
|
2001-12-11 05:38:51 +03:00
|
|
|
|
{
|
2010-03-24 06:37:06 +03:00
|
|
|
|
// This ignores NotifyVirtual and NotifyNonlinearVirtual leave notify
|
|
|
|
|
// events when the pointer leaves a child window. If the destination
|
|
|
|
|
// window is a Gecko window then we'll catch the corresponding event on
|
|
|
|
|
// that window.
|
|
|
|
|
//
|
|
|
|
|
// XXXkt However, we will miss toplevel exits when the pointer directly
|
|
|
|
|
// leaves a foreign (plugin) child window without passing over a visible
|
|
|
|
|
// portion of a Gecko window.
|
2013-10-08 22:47:37 +04:00
|
|
|
|
if (aEvent->subwindow != nullptr)
|
2004-06-22 08:29:59 +04:00
|
|
|
|
return;
|
|
|
|
|
|
2015-08-29 02:58:31 +03:00
|
|
|
|
WidgetMouseEvent event(true, eMouseExitFromWidget, this,
|
|
|
|
|
WidgetMouseEvent::eReal);
|
2001-12-11 05:38:51 +03:00
|
|
|
|
|
2015-10-13 22:09:40 +03:00
|
|
|
|
event.refPoint = GdkEventCoordsToDevicePixels(aEvent->x, aEvent->y);
|
2007-01-24 01:51:38 +03:00
|
|
|
|
event.time = aEvent->time;
|
2015-08-11 10:40:34 +03:00
|
|
|
|
event.timeStamp = GetEventTimeStamp(aEvent->time);
|
2007-01-24 01:51:38 +03:00
|
|
|
|
|
2009-07-27 05:39:36 +04:00
|
|
|
|
event.exit = is_top_level_mouse_exit(mGdkWindow, aEvent)
|
2013-10-02 10:38:27 +04:00
|
|
|
|
? WidgetMouseEvent::eTopLevel : WidgetMouseEvent::eChild;
|
2008-03-13 01:44:45 +03:00
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
LOG(("OnLeaveNotify: %p\n", (void *)this));
|
2002-01-28 11:11:50 +03:00
|
|
|
|
|
2015-03-17 02:29:55 +03:00
|
|
|
|
DispatchInputEvent(&event);
|
2001-12-11 05:38:51 +03:00
|
|
|
|
}
|
|
|
|
|
|
2015-10-22 07:06:14 +03:00
|
|
|
|
template <typename Event> static LayoutDeviceIntPoint
|
|
|
|
|
GetRefPoint(nsWindow* aWindow, Event* aEvent)
|
|
|
|
|
{
|
|
|
|
|
if (aEvent->window == aWindow->GetGdkWindow()) {
|
|
|
|
|
// we are the window that the event happened on so no need for expensive WidgetToScreenOffset
|
|
|
|
|
return aWindow->GdkEventCoordsToDevicePixels(aEvent->x, aEvent->y);
|
|
|
|
|
}
|
|
|
|
|
// XXX we're never quite sure which GdkWindow the event came from due to our custom bubbling
|
|
|
|
|
// in scroll_event_cb(), so use ScreenToWidget to translate the screen root coordinates into
|
|
|
|
|
// coordinates relative to this widget.
|
|
|
|
|
return aWindow->GdkEventCoordsToDevicePixels(
|
|
|
|
|
aEvent->x_root, aEvent->y_root) - aWindow->WidgetToScreenOffset();
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-11 05:38:51 +03:00
|
|
|
|
void
|
2012-10-23 02:33:30 +04:00
|
|
|
|
nsWindow::OnMotionNotifyEvent(GdkEventMotion *aEvent)
|
2001-12-11 05:38:51 +03:00
|
|
|
|
{
|
2002-04-27 20:26:10 +04:00
|
|
|
|
// see if we can compress this event
|
2008-10-20 05:25:26 +04:00
|
|
|
|
// XXXldb Why skip every other motion event when we have multiple,
|
|
|
|
|
// but not more than that?
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool synthEvent = false;
|
2008-10-20 05:25:26 +04:00
|
|
|
|
#ifdef MOZ_X11
|
|
|
|
|
XEvent xevent;
|
2008-10-18 02:38:49 +04:00
|
|
|
|
|
2015-03-05 05:56:00 +03:00
|
|
|
|
bool isX11Display = GDK_IS_X11_DISPLAY(gdk_display_get_default());
|
|
|
|
|
if (isX11Display) {
|
|
|
|
|
while (XPending (GDK_WINDOW_XDISPLAY(aEvent->window))) {
|
|
|
|
|
XEvent peeked;
|
|
|
|
|
XPeekEvent (GDK_WINDOW_XDISPLAY(aEvent->window), &peeked);
|
|
|
|
|
if (peeked.xany.window != gdk_x11_window_get_xid(aEvent->window)
|
|
|
|
|
|| peeked.type != MotionNotify)
|
|
|
|
|
break;
|
2008-10-13 06:32:56 +04:00
|
|
|
|
|
2015-03-05 05:56:00 +03:00
|
|
|
|
synthEvent = true;
|
|
|
|
|
XNextEvent (GDK_WINDOW_XDISPLAY(aEvent->window), &xevent);
|
|
|
|
|
}
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2015-03-05 05:56:00 +03:00
|
|
|
|
// if plugins still keeps the focus, get it back
|
|
|
|
|
if (gPluginFocusWindow && gPluginFocusWindow != this) {
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> kungFuDeathGrip = gPluginFocusWindow;
|
2015-03-05 05:56:00 +03:00
|
|
|
|
gPluginFocusWindow->LoseNonXEmbedPluginFocus();
|
|
|
|
|
}
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#endif /* MOZ_WIDGET_GTK2 */
|
2015-03-05 05:56:00 +03:00
|
|
|
|
}
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#endif /* MOZ_X11 */
|
2003-02-17 18:36:37 +03:00
|
|
|
|
|
2015-08-29 02:58:29 +03:00
|
|
|
|
WidgetMouseEvent event(true, eMouseMove, this, WidgetMouseEvent::eReal);
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2008-12-12 02:55:15 +03:00
|
|
|
|
gdouble pressure = 0;
|
|
|
|
|
gdk_event_get_axis ((GdkEvent*)aEvent, GDK_AXIS_PRESSURE, &pressure);
|
|
|
|
|
// Sometime gdk generate 0 pressure value between normal values
|
|
|
|
|
// We have to ignore that and use last valid value
|
|
|
|
|
if (pressure)
|
|
|
|
|
mLastMotionPressure = pressure;
|
|
|
|
|
event.pressure = mLastMotionPressure;
|
|
|
|
|
|
2012-02-22 11:34:31 +04:00
|
|
|
|
guint modifierState;
|
2008-10-20 05:25:26 +04:00
|
|
|
|
if (synthEvent) {
|
|
|
|
|
#ifdef MOZ_X11
|
|
|
|
|
event.refPoint.x = nscoord(xevent.xmotion.x);
|
|
|
|
|
event.refPoint.y = nscoord(xevent.xmotion.y);
|
|
|
|
|
|
2012-02-22 11:34:31 +04:00
|
|
|
|
modifierState = xevent.xmotion.state;
|
2008-10-20 05:25:26 +04:00
|
|
|
|
|
|
|
|
|
event.time = xevent.xmotion.time;
|
2015-08-11 10:40:34 +03:00
|
|
|
|
event.timeStamp = GetEventTimeStamp(xevent.xmotion.time);
|
2008-10-20 05:25:26 +04:00
|
|
|
|
#else
|
2015-10-13 22:09:40 +03:00
|
|
|
|
event.refPoint = GdkEventCoordsToDevicePixels(aEvent->x, aEvent->y);
|
2008-08-07 00:48:55 +04:00
|
|
|
|
|
2012-02-22 11:34:31 +04:00
|
|
|
|
modifierState = aEvent->state;
|
2008-10-20 05:25:26 +04:00
|
|
|
|
|
|
|
|
|
event.time = aEvent->time;
|
2015-08-11 10:40:34 +03:00
|
|
|
|
event.timeStamp = GetEventTimeStamp(aEvent->time);
|
2008-10-20 05:25:26 +04:00
|
|
|
|
#endif /* MOZ_X11 */
|
2015-10-22 07:06:14 +03:00
|
|
|
|
} else {
|
|
|
|
|
event.refPoint = GetRefPoint(this, aEvent);
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2012-02-22 11:34:31 +04:00
|
|
|
|
modifierState = aEvent->state;
|
2007-01-24 01:51:38 +03:00
|
|
|
|
|
2008-10-20 05:25:26 +04:00
|
|
|
|
event.time = aEvent->time;
|
2015-08-11 10:40:34 +03:00
|
|
|
|
event.timeStamp = GetEventTimeStamp(aEvent->time);
|
2008-10-20 05:25:26 +04:00
|
|
|
|
}
|
2001-12-11 05:38:51 +03:00
|
|
|
|
|
2012-02-22 11:34:31 +04:00
|
|
|
|
KeymapWrapper::InitInputEvent(event, modifierState);
|
|
|
|
|
|
2015-03-17 02:29:55 +03:00
|
|
|
|
DispatchInputEvent(&event);
|
2001-12-11 05:38:51 +03:00
|
|
|
|
}
|
|
|
|
|
|
2010-03-24 06:37:06 +03:00
|
|
|
|
// If the automatic pointer grab on ButtonPress has deactivated before
|
|
|
|
|
// ButtonRelease, and the mouse button is released while the pointer is not
|
|
|
|
|
// over any a Gecko window, then the ButtonRelease event will not be received.
|
|
|
|
|
// (A similar situation exists when the pointer is grabbed with owner_events
|
|
|
|
|
// True as the ButtonRelease may be received on a foreign [plugin] window).
|
|
|
|
|
// Use this method to check for released buttons when the pointer returns to a
|
|
|
|
|
// Gecko window.
|
|
|
|
|
void
|
|
|
|
|
nsWindow::DispatchMissedButtonReleases(GdkEventCrossing *aGdkEvent)
|
|
|
|
|
{
|
|
|
|
|
guint changed = aGdkEvent->state ^ gButtonState;
|
|
|
|
|
// Only consider button releases.
|
|
|
|
|
// (Ignore button presses that occurred outside Gecko.)
|
|
|
|
|
guint released = changed & gButtonState;
|
|
|
|
|
gButtonState = aGdkEvent->state;
|
|
|
|
|
|
|
|
|
|
// Loop over each button, excluding mouse wheel buttons 4 and 5 for which
|
|
|
|
|
// GDK ignores releases.
|
|
|
|
|
for (guint buttonMask = GDK_BUTTON1_MASK;
|
|
|
|
|
buttonMask <= GDK_BUTTON3_MASK;
|
|
|
|
|
buttonMask <<= 1) {
|
|
|
|
|
|
|
|
|
|
if (released & buttonMask) {
|
2012-08-22 19:56:38 +04:00
|
|
|
|
int16_t buttonType;
|
2010-03-24 06:37:06 +03:00
|
|
|
|
switch (buttonMask) {
|
|
|
|
|
case GDK_BUTTON1_MASK:
|
2013-10-02 10:38:27 +04:00
|
|
|
|
buttonType = WidgetMouseEvent::eLeftButton;
|
2010-03-24 06:37:06 +03:00
|
|
|
|
break;
|
|
|
|
|
case GDK_BUTTON2_MASK:
|
2013-10-02 10:38:27 +04:00
|
|
|
|
buttonType = WidgetMouseEvent::eMiddleButton;
|
2010-03-24 06:37:06 +03:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
NS_ASSERTION(buttonMask == GDK_BUTTON3_MASK,
|
|
|
|
|
"Unexpected button mask");
|
2013-10-02 10:38:27 +04:00
|
|
|
|
buttonType = WidgetMouseEvent::eRightButton;
|
2010-03-24 06:37:06 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LOG(("Synthesized button %u release on %p\n",
|
|
|
|
|
guint(buttonType + 1), (void *)this));
|
|
|
|
|
|
|
|
|
|
// Dispatch a synthesized button up event to tell Gecko about the
|
|
|
|
|
// change in state. This event is marked as synthesized so that
|
|
|
|
|
// it is not dispatched as a DOM event, because we don't know the
|
|
|
|
|
// position, widget, modifiers, or time/order.
|
2015-08-29 02:58:30 +03:00
|
|
|
|
WidgetMouseEvent synthEvent(true, eMouseUp, this,
|
2013-10-02 10:38:27 +04:00
|
|
|
|
WidgetMouseEvent::eSynthesized);
|
2010-03-24 06:37:06 +03:00
|
|
|
|
synthEvent.button = buttonType;
|
2015-10-26 23:06:49 +03:00
|
|
|
|
DispatchAPZAwareEvent(&synthEvent);
|
2010-03-24 06:37:06 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-14 10:00:44 +03:00
|
|
|
|
void
|
2013-10-02 10:38:27 +04:00
|
|
|
|
nsWindow::InitButtonEvent(WidgetMouseEvent& aEvent,
|
|
|
|
|
GdkEventButton* aGdkEvent)
|
2007-12-14 10:00:44 +03:00
|
|
|
|
{
|
2015-10-22 07:06:14 +03:00
|
|
|
|
aEvent.refPoint = GetRefPoint(this, aGdkEvent);
|
2007-12-14 10:00:44 +03:00
|
|
|
|
|
2012-04-25 07:00:01 +04:00
|
|
|
|
guint modifierState = aGdkEvent->state;
|
|
|
|
|
// aEvent's state doesn't include this event's information. Therefore,
|
|
|
|
|
// if aEvent is mouse button down event, we need to set it manually.
|
2015-08-29 02:58:30 +03:00
|
|
|
|
// Note that we cannot do same thing for eMouseUp because
|
2012-04-25 07:00:01 +04:00
|
|
|
|
// system may have two or more mice and same button of another mouse
|
|
|
|
|
// may be still pressed.
|
|
|
|
|
if (aGdkEvent->type != GDK_BUTTON_RELEASE) {
|
|
|
|
|
switch (aGdkEvent->button) {
|
|
|
|
|
case 1:
|
|
|
|
|
modifierState |= GDK_BUTTON1_MASK;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
modifierState |= GDK_BUTTON2_MASK;
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
modifierState |= GDK_BUTTON3_MASK;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
KeymapWrapper::InitInputEvent(aEvent, modifierState);
|
2007-12-14 10:00:44 +03:00
|
|
|
|
|
|
|
|
|
aEvent.time = aGdkEvent->time;
|
2015-08-11 10:40:34 +03:00
|
|
|
|
aEvent.timeStamp = GetEventTimeStamp(aGdkEvent->time);
|
2007-12-14 10:00:44 +03:00
|
|
|
|
|
|
|
|
|
switch (aGdkEvent->type) {
|
|
|
|
|
case GDK_2BUTTON_PRESS:
|
|
|
|
|
aEvent.clickCount = 2;
|
|
|
|
|
break;
|
|
|
|
|
case GDK_3BUTTON_PRESS:
|
|
|
|
|
aEvent.clickCount = 3;
|
|
|
|
|
break;
|
|
|
|
|
// default is one click
|
|
|
|
|
default:
|
|
|
|
|
aEvent.clickCount = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-24 06:37:06 +03:00
|
|
|
|
static guint ButtonMaskFromGDKButton(guint button)
|
|
|
|
|
{
|
|
|
|
|
return GDK_BUTTON1_MASK << (button - 1);
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-11 05:38:51 +03:00
|
|
|
|
void
|
2012-10-23 02:33:30 +04:00
|
|
|
|
nsWindow::OnButtonPressEvent(GdkEventButton *aEvent)
|
2001-12-11 05:38:51 +03:00
|
|
|
|
{
|
2010-03-24 06:37:06 +03:00
|
|
|
|
LOG(("Button %u press on %p\n", aEvent->button, (void *)this));
|
|
|
|
|
|
|
|
|
|
// If you double click in GDK, it will actually generate a second
|
|
|
|
|
// GDK_BUTTON_PRESS before sending the GDK_2BUTTON_PRESS, and this is
|
2003-12-21 21:54:38 +03:00
|
|
|
|
// different than the DOM spec. GDK puts this in the queue
|
|
|
|
|
// programatically, so it's safe to assume that if there's a
|
|
|
|
|
// double click in the queue, it was generated so we can just drop
|
|
|
|
|
// this click.
|
|
|
|
|
GdkEvent *peekedEvent = gdk_event_peek();
|
|
|
|
|
if (peekedEvent) {
|
|
|
|
|
GdkEventType type = peekedEvent->any.type;
|
|
|
|
|
gdk_event_free(peekedEvent);
|
|
|
|
|
if (type == GDK_2BUTTON_PRESS || type == GDK_3BUTTON_PRESS)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-20 05:07:08 +03:00
|
|
|
|
nsWindow *containerWindow = GetContainerWindow();
|
|
|
|
|
if (!gFocusWindow && containerWindow) {
|
2009-07-23 05:18:39 +04:00
|
|
|
|
containerWindow->DispatchActivateEvent();
|
2002-09-24 05:17:19 +04:00
|
|
|
|
}
|
2008-01-14 12:40:45 +03:00
|
|
|
|
|
2009-07-23 05:18:39 +04:00
|
|
|
|
// check to see if we should rollup
|
2012-10-26 17:15:22 +04:00
|
|
|
|
if (CheckForRollup(aEvent->x_root, aEvent->y_root, false, false))
|
2010-09-16 15:24:08 +04:00
|
|
|
|
return;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2008-12-12 02:55:15 +03:00
|
|
|
|
gdouble pressure = 0;
|
|
|
|
|
gdk_event_get_axis ((GdkEvent*)aEvent, GDK_AXIS_PRESSURE, &pressure);
|
|
|
|
|
mLastMotionPressure = pressure;
|
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
|
uint16_t domButton;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
switch (aEvent->button) {
|
2007-07-26 01:26:16 +04:00
|
|
|
|
case 1:
|
2013-10-02 10:38:27 +04:00
|
|
|
|
domButton = WidgetMouseEvent::eLeftButton;
|
2007-07-26 01:26:16 +04:00
|
|
|
|
break;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
case 2:
|
2013-10-02 10:38:27 +04:00
|
|
|
|
domButton = WidgetMouseEvent::eMiddleButton;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
break;
|
|
|
|
|
case 3:
|
2013-10-02 10:38:27 +04:00
|
|
|
|
domButton = WidgetMouseEvent::eRightButton;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
break;
|
2008-03-18 22:36:09 +03:00
|
|
|
|
// These are mapped to horizontal scroll
|
|
|
|
|
case 6:
|
|
|
|
|
case 7:
|
2012-08-12 05:42:37 +04:00
|
|
|
|
NS_WARNING("We're not supporting legacy horizontal scroll event");
|
|
|
|
|
return;
|
2008-03-18 22:36:09 +03:00
|
|
|
|
// Map buttons 8-9 to back/forward
|
2008-02-20 13:10:08 +03:00
|
|
|
|
case 8:
|
2011-10-14 22:11:22 +04:00
|
|
|
|
DispatchCommandEvent(nsGkAtoms::Back);
|
2008-02-20 13:10:08 +03:00
|
|
|
|
return;
|
|
|
|
|
case 9:
|
2011-10-14 22:11:22 +04:00
|
|
|
|
DispatchCommandEvent(nsGkAtoms::Forward);
|
2008-02-20 13:10:08 +03:00
|
|
|
|
return;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
default:
|
2007-07-26 01:26:16 +04:00
|
|
|
|
return;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
2010-03-24 06:37:06 +03:00
|
|
|
|
gButtonState |= ButtonMaskFromGDKButton(aEvent->button);
|
|
|
|
|
|
2015-08-29 02:58:30 +03:00
|
|
|
|
WidgetMouseEvent event(true, eMouseDown, this, WidgetMouseEvent::eReal);
|
2006-11-17 00:35:39 +03:00
|
|
|
|
event.button = domButton;
|
2004-01-12 11:25:18 +03:00
|
|
|
|
InitButtonEvent(event, aEvent);
|
2008-12-12 02:55:15 +03:00
|
|
|
|
event.pressure = mLastMotionPressure;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2015-10-26 23:06:49 +03:00
|
|
|
|
DispatchAPZAwareEvent(&event);
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
|
|
|
|
// right menu click on linux should also pop up a context menu
|
2013-10-02 10:38:27 +04:00
|
|
|
|
if (domButton == WidgetMouseEvent::eRightButton &&
|
2012-10-26 17:32:10 +04:00
|
|
|
|
MOZ_LIKELY(!mIsDestroyed)) {
|
2015-08-31 18:20:06 +03:00
|
|
|
|
WidgetMouseEvent contextMenuEvent(true, eContextMenu, this,
|
2013-10-02 10:38:27 +04:00
|
|
|
|
WidgetMouseEvent::eReal);
|
2004-01-12 11:25:18 +03:00
|
|
|
|
InitButtonEvent(contextMenuEvent, aEvent);
|
2008-12-12 02:55:15 +03:00
|
|
|
|
contextMenuEvent.pressure = mLastMotionPressure;
|
2015-03-17 02:29:55 +03:00
|
|
|
|
DispatchInputEvent(&contextMenuEvent);
|
2002-04-27 20:26:10 +04:00
|
|
|
|
}
|
2001-12-11 05:38:51 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2012-10-23 02:33:30 +04:00
|
|
|
|
nsWindow::OnButtonReleaseEvent(GdkEventButton *aEvent)
|
2001-12-11 05:38:51 +03:00
|
|
|
|
{
|
2010-03-24 06:37:06 +03:00
|
|
|
|
LOG(("Button %u release on %p\n", aEvent->button, (void *)this));
|
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
|
uint16_t domButton;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
switch (aEvent->button) {
|
2007-07-26 01:26:16 +04:00
|
|
|
|
case 1:
|
2013-10-02 10:38:27 +04:00
|
|
|
|
domButton = WidgetMouseEvent::eLeftButton;
|
2007-07-26 01:26:16 +04:00
|
|
|
|
break;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
case 2:
|
2013-10-02 10:38:27 +04:00
|
|
|
|
domButton = WidgetMouseEvent::eMiddleButton;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
break;
|
|
|
|
|
case 3:
|
2013-10-02 10:38:27 +04:00
|
|
|
|
domButton = WidgetMouseEvent::eRightButton;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2007-07-26 01:26:16 +04:00
|
|
|
|
return;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
2010-03-24 06:37:06 +03:00
|
|
|
|
gButtonState &= ~ButtonMaskFromGDKButton(aEvent->button);
|
|
|
|
|
|
2015-08-29 02:58:30 +03:00
|
|
|
|
WidgetMouseEvent event(true, eMouseUp, this,
|
2013-10-02 10:38:27 +04:00
|
|
|
|
WidgetMouseEvent::eReal);
|
2006-11-17 00:35:39 +03:00
|
|
|
|
event.button = domButton;
|
2004-01-12 11:25:18 +03:00
|
|
|
|
InitButtonEvent(event, aEvent);
|
2008-12-12 02:55:15 +03:00
|
|
|
|
gdouble pressure = 0;
|
|
|
|
|
gdk_event_get_axis ((GdkEvent*)aEvent, GDK_AXIS_PRESSURE, &pressure);
|
|
|
|
|
event.pressure = pressure ? pressure : mLastMotionPressure;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2015-10-26 23:06:49 +03:00
|
|
|
|
DispatchAPZAwareEvent(&event);
|
2008-12-12 02:55:15 +03:00
|
|
|
|
mLastMotionPressure = pressure;
|
2001-12-11 05:38:51 +03:00
|
|
|
|
}
|
|
|
|
|
|
2001-12-12 01:22:48 +03:00
|
|
|
|
void
|
2012-10-23 02:33:30 +04:00
|
|
|
|
nsWindow::OnContainerFocusInEvent(GdkEventFocus *aEvent)
|
2001-12-12 01:22:48 +03:00
|
|
|
|
{
|
2002-11-06 06:29:02 +03:00
|
|
|
|
LOGFOCUS(("OnContainerFocusInEvent [%p]\n", (void *)this));
|
2001-12-12 01:22:48 +03:00
|
|
|
|
|
2006-12-20 12:05:19 +03:00
|
|
|
|
// Unset the urgency hint, if possible
|
2012-11-07 01:50:37 +04:00
|
|
|
|
GtkWidget* top_window = GetToplevelWidget();
|
2011-09-23 00:58:07 +04:00
|
|
|
|
if (top_window && (gtk_widget_get_visible(top_window)))
|
2011-10-03 11:56:21 +04:00
|
|
|
|
SetUrgencyHint(top_window, false);
|
2006-12-20 12:05:19 +03:00
|
|
|
|
|
2010-06-03 07:50:49 +04:00
|
|
|
|
// Return if being called within SetFocus because the focus manager
|
|
|
|
|
// already knows that the window is active.
|
|
|
|
|
if (gBlockActivateEvent) {
|
2012-08-15 22:52:42 +04:00
|
|
|
|
LOGFOCUS(("activated notification is blocked [%p]\n", (void *)this));
|
2010-06-03 07:50:49 +04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-23 02:31:53 +04:00
|
|
|
|
// If keyboard input will be accepted, the focus manager will call
|
|
|
|
|
// SetFocus to set the correct window.
|
|
|
|
|
gFocusWindow = nullptr;
|
2010-06-03 07:50:49 +04:00
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
DispatchActivateEvent();
|
2002-10-25 06:46:17 +04:00
|
|
|
|
|
2012-10-23 02:31:53 +04:00
|
|
|
|
if (!gFocusWindow) {
|
|
|
|
|
// We don't really have a window for dispatching key events, but
|
2013-10-08 22:47:37 +04:00
|
|
|
|
// setting a non-nullptr value here prevents OnButtonPressEvent() from
|
2012-10-23 02:31:53 +04:00
|
|
|
|
// dispatching an activation notification if the widget is already
|
|
|
|
|
// active.
|
|
|
|
|
gFocusWindow = this;
|
|
|
|
|
}
|
|
|
|
|
|
2002-11-06 06:29:02 +03:00
|
|
|
|
LOGFOCUS(("Events sent from focus in event [%p]\n", (void *)this));
|
2001-12-12 01:22:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2012-10-23 02:33:30 +04:00
|
|
|
|
nsWindow::OnContainerFocusOutEvent(GdkEventFocus *aEvent)
|
2001-12-12 01:22:48 +03:00
|
|
|
|
{
|
2002-11-06 06:29:02 +03:00
|
|
|
|
LOGFOCUS(("OnContainerFocusOutEvent [%p]\n", (void *)this));
|
2003-02-17 18:36:37 +03:00
|
|
|
|
|
2010-09-16 15:24:08 +04:00
|
|
|
|
if (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog) {
|
2010-12-31 22:20:00 +03:00
|
|
|
|
nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
|
|
|
|
|
nsCOMPtr<nsIDragSession> dragSession;
|
|
|
|
|
dragService->GetCurrentSession(getter_AddRefs(dragSession));
|
|
|
|
|
|
|
|
|
|
// Rollup popups when a window is focused out unless a drag is occurring.
|
|
|
|
|
// This check is because drags grab the keyboard and cause a focus out on
|
|
|
|
|
// versions of GTK before 2.18.
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool shouldRollup = !dragSession;
|
2010-12-31 22:20:00 +03:00
|
|
|
|
if (!shouldRollup) {
|
|
|
|
|
// we also roll up when a drag is from a different application
|
|
|
|
|
nsCOMPtr<nsIDOMNode> sourceNode;
|
|
|
|
|
dragSession->GetSourceNode(getter_AddRefs(sourceNode));
|
2012-07-30 18:20:58 +04:00
|
|
|
|
shouldRollup = (sourceNode == nullptr);
|
2010-12-31 22:20:00 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (shouldRollup) {
|
2012-10-26 17:15:22 +04:00
|
|
|
|
CheckForRollup(0, 0, false, true);
|
2010-12-31 22:20:00 +03:00
|
|
|
|
}
|
2010-09-16 15:24:08 +04:00
|
|
|
|
}
|
|
|
|
|
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2) && defined(MOZ_X11)
|
2003-02-17 18:36:37 +03:00
|
|
|
|
// plugin lose focus
|
|
|
|
|
if (gPluginFocusWindow) {
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> kungFuDeathGrip = gPluginFocusWindow;
|
2003-02-17 18:36:37 +03:00
|
|
|
|
gPluginFocusWindow->LoseNonXEmbedPluginFocus();
|
|
|
|
|
}
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#endif /* MOZ_X11 && MOZ_WIDGET_GTK2 */
|
2003-02-17 18:36:37 +03:00
|
|
|
|
|
2010-06-18 05:11:08 +04:00
|
|
|
|
if (gFocusWindow) {
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> kungFuDeathGrip = gFocusWindow;
|
2015-07-27 02:23:04 +03:00
|
|
|
|
if (gFocusWindow->mIMContext) {
|
|
|
|
|
gFocusWindow->mIMContext->OnBlurWindow(gFocusWindow);
|
2010-06-18 05:11:08 +04:00
|
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
|
gFocusWindow = nullptr;
|
2010-03-19 07:21:16 +03:00
|
|
|
|
}
|
2003-04-09 07:34:53 +04:00
|
|
|
|
|
2010-06-18 05:11:08 +04:00
|
|
|
|
DispatchDeactivateEvent();
|
2002-11-06 06:29:02 +03:00
|
|
|
|
|
|
|
|
|
LOGFOCUS(("Done with container focus out [%p]\n", (void *)this));
|
2001-12-12 01:22:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool
|
2008-02-20 13:10:08 +03:00
|
|
|
|
nsWindow::DispatchCommandEvent(nsIAtom* aCommand)
|
2008-02-07 00:56:02 +03:00
|
|
|
|
{
|
|
|
|
|
nsEventStatus status;
|
2013-09-27 10:20:54 +04:00
|
|
|
|
WidgetCommandEvent event(true, nsGkAtoms::onAppCommand, aCommand, this);
|
2008-02-07 00:56:02 +03:00
|
|
|
|
DispatchEvent(&event, status);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool
|
2015-08-26 15:56:59 +03:00
|
|
|
|
nsWindow::DispatchContentCommandEvent(EventMessage aMsg)
|
2011-07-14 05:58:07 +04:00
|
|
|
|
{
|
|
|
|
|
nsEventStatus status;
|
2013-09-27 10:20:54 +04:00
|
|
|
|
WidgetContentCommandEvent event(true, aMsg, this);
|
2011-07-14 05:58:07 +04:00
|
|
|
|
DispatchEvent(&event, status);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
|
static bool
|
2010-03-19 07:21:16 +03:00
|
|
|
|
IsCtrlAltTab(GdkEventKey *aEvent)
|
|
|
|
|
{
|
|
|
|
|
return aEvent->keyval == GDK_Tab &&
|
2012-02-22 11:34:31 +04:00
|
|
|
|
KeymapWrapper::AreModifiersActive(
|
|
|
|
|
KeymapWrapper::CTRL | KeymapWrapper::ALT, aEvent->state);
|
2010-03-19 07:21:16 +03:00
|
|
|
|
}
|
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool
|
|
|
|
|
nsWindow::DispatchKeyDownEvent(GdkEventKey *aEvent, bool *aCancelled)
|
2010-03-19 07:21:16 +03:00
|
|
|
|
{
|
|
|
|
|
NS_PRECONDITION(aCancelled, "aCancelled must not be null");
|
|
|
|
|
|
2011-10-03 11:56:21 +04:00
|
|
|
|
*aCancelled = false;
|
2010-03-19 07:21:16 +03:00
|
|
|
|
|
|
|
|
|
if (IsCtrlAltTab(aEvent)) {
|
2011-10-03 11:56:21 +04:00
|
|
|
|
return false;
|
2010-03-19 07:21:16 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// send the key down event
|
2015-08-29 02:58:27 +03:00
|
|
|
|
WidgetKeyboardEvent downEvent(true, eKeyDown, this);
|
2012-02-22 11:34:31 +04:00
|
|
|
|
KeymapWrapper::InitKeyEvent(downEvent, aEvent);
|
2015-03-17 02:29:55 +03:00
|
|
|
|
nsEventStatus status = DispatchInputEvent(&downEvent);
|
2010-03-19 07:21:16 +03:00
|
|
|
|
*aCancelled = (status == nsEventStatus_eConsumeNoDefault);
|
2011-10-03 11:56:21 +04:00
|
|
|
|
return true;
|
2010-03-19 07:21:16 +03:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-11 10:40:34 +03:00
|
|
|
|
TimeStamp
|
|
|
|
|
nsWindow::GetEventTimeStamp(guint32 aEventTime)
|
|
|
|
|
{
|
|
|
|
|
if (MOZ_UNLIKELY(!mGdkWindow)) {
|
|
|
|
|
// nsWindow has been Destroy()ed.
|
|
|
|
|
return TimeStamp::Now();
|
|
|
|
|
}
|
|
|
|
|
if (aEventTime == 0) {
|
|
|
|
|
// Some X11 and GDK events may be received with a time of 0 to indicate
|
|
|
|
|
// that they are synthetic events. Some input method editors do this.
|
|
|
|
|
// In this case too, just return the current timestamp.
|
|
|
|
|
return TimeStamp::Now();
|
|
|
|
|
}
|
2015-08-11 11:13:44 +03:00
|
|
|
|
CurrentX11TimeGetter* getCurrentTime = GetCurrentTimeGetter();
|
|
|
|
|
MOZ_ASSERT(getCurrentTime,
|
|
|
|
|
"Null current time getter despite having a window");
|
2015-08-11 10:40:34 +03:00
|
|
|
|
return TimeConverter().GetTimeStampFromSystemTime(aEventTime,
|
2015-08-11 11:13:44 +03:00
|
|
|
|
*getCurrentTime);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mozilla::CurrentX11TimeGetter*
|
|
|
|
|
nsWindow::GetCurrentTimeGetter() {
|
|
|
|
|
MOZ_ASSERT(mGdkWindow, "Expected mGdkWindow to be set");
|
|
|
|
|
if (MOZ_UNLIKELY(!mCurrentTimeGetter)) {
|
|
|
|
|
mCurrentTimeGetter = new CurrentX11TimeGetter(mGdkWindow);
|
|
|
|
|
}
|
|
|
|
|
return mCurrentTimeGetter;
|
2015-08-11 10:40:34 +03:00
|
|
|
|
}
|
|
|
|
|
|
2001-12-12 06:03:05 +03:00
|
|
|
|
gboolean
|
2012-10-23 02:33:30 +04:00
|
|
|
|
nsWindow::OnKeyPressEvent(GdkEventKey *aEvent)
|
2001-12-12 06:03:05 +03:00
|
|
|
|
{
|
2002-11-06 06:29:02 +03:00
|
|
|
|
LOGFOCUS(("OnKeyPressEvent [%p]\n", (void *)this));
|
2003-04-09 07:34:53 +04:00
|
|
|
|
|
|
|
|
|
// if we are in the middle of composing text, XIM gets to see it
|
|
|
|
|
// before mozilla does.
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool IMEWasEnabled = false;
|
2015-07-27 02:23:04 +03:00
|
|
|
|
if (mIMContext) {
|
|
|
|
|
IMEWasEnabled = mIMContext->IsEnabled();
|
|
|
|
|
if (mIMContext->OnKeyEvent(this, aEvent)) {
|
2011-01-14 16:40:08 +03:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2010-03-19 07:21:16 +03:00
|
|
|
|
}
|
2003-04-09 07:34:53 +04:00
|
|
|
|
|
|
|
|
|
nsEventStatus status;
|
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
// work around for annoying things.
|
2010-03-19 07:21:16 +03:00
|
|
|
|
if (IsCtrlAltTab(aEvent)) {
|
2003-04-09 07:34:53 +04:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2005-02-14 12:51:25 +03:00
|
|
|
|
nsCOMPtr<nsIWidget> kungFuDeathGrip = this;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2010-10-07 09:57:53 +04:00
|
|
|
|
// Dispatch keydown event always. At auto repeating, we should send
|
|
|
|
|
// KEYDOWN -> KEYPRESS -> KEYDOWN -> KEYPRESS ... -> KEYUP
|
|
|
|
|
// However, old distributions (e.g., Ubuntu 9.10) sent native key
|
|
|
|
|
// release event, so, on such platform, the DOM events will be:
|
|
|
|
|
// KEYDOWN -> KEYPRESS -> KEYUP -> KEYDOWN -> KEYPRESS -> KEYUP...
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool isKeyDownCancelled = false;
|
2010-03-19 07:21:16 +03:00
|
|
|
|
if (DispatchKeyDownEvent(aEvent, &isKeyDownCancelled) &&
|
2013-07-25 10:09:28 +04:00
|
|
|
|
(MOZ_UNLIKELY(mIsDestroyed) || isKeyDownCancelled)) {
|
2010-03-19 07:21:16 +03:00
|
|
|
|
return TRUE;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
}
|
2001-12-12 06:03:05 +03:00
|
|
|
|
|
2011-01-14 16:40:08 +03:00
|
|
|
|
// If a keydown event handler causes to enable IME, i.e., it moves
|
|
|
|
|
// focus from IME unusable content to IME usable editor, we should
|
|
|
|
|
// send the native key event to IME for the first input on the editor.
|
2015-07-27 02:23:04 +03:00
|
|
|
|
if (!IMEWasEnabled && mIMContext && mIMContext->IsEnabled()) {
|
2011-01-14 16:40:08 +03:00
|
|
|
|
// Notice our keydown event was already dispatched. This prevents
|
|
|
|
|
// unnecessary DOM keydown event in the editor.
|
2015-07-27 02:23:04 +03:00
|
|
|
|
if (mIMContext->OnKeyEvent(this, aEvent, true)) {
|
2011-01-14 16:40:08 +03:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-29 02:58:27 +03:00
|
|
|
|
// Don't pass modifiers as eKeyPress events.
|
|
|
|
|
// TODO: Instead of selectively excluding some keys from eKeyPress events,
|
2004-07-07 15:22:43 +04:00
|
|
|
|
// we should instead selectively include (as per MSDN spec; no official
|
|
|
|
|
// spec covers KeyPress events).
|
2012-02-22 11:34:31 +04:00
|
|
|
|
if (!KeymapWrapper::IsKeyPressEventNecessary(aEvent)) {
|
2004-07-07 15:22:43 +04:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2008-02-07 00:56:02 +03:00
|
|
|
|
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#ifdef MOZ_X11
|
2010-03-28 19:50:39 +04:00
|
|
|
|
#if ! defined AIX // no XFree86 on AIX 5L
|
2008-02-07 00:56:02 +03:00
|
|
|
|
// Look for specialized app-command keys
|
|
|
|
|
switch (aEvent->keyval) {
|
|
|
|
|
case XF86XK_Back:
|
2011-10-14 22:11:22 +04:00
|
|
|
|
return DispatchCommandEvent(nsGkAtoms::Back);
|
2008-02-07 00:56:02 +03:00
|
|
|
|
case XF86XK_Forward:
|
2011-10-14 22:11:22 +04:00
|
|
|
|
return DispatchCommandEvent(nsGkAtoms::Forward);
|
2008-02-07 00:56:02 +03:00
|
|
|
|
case XF86XK_Refresh:
|
2011-10-14 22:11:22 +04:00
|
|
|
|
return DispatchCommandEvent(nsGkAtoms::Reload);
|
2008-02-07 00:56:02 +03:00
|
|
|
|
case XF86XK_Stop:
|
2011-10-14 22:11:22 +04:00
|
|
|
|
return DispatchCommandEvent(nsGkAtoms::Stop);
|
2008-02-07 00:56:02 +03:00
|
|
|
|
case XF86XK_Search:
|
2011-10-14 22:11:22 +04:00
|
|
|
|
return DispatchCommandEvent(nsGkAtoms::Search);
|
2008-02-07 00:56:02 +03:00
|
|
|
|
case XF86XK_Favorites:
|
2011-10-14 22:11:22 +04:00
|
|
|
|
return DispatchCommandEvent(nsGkAtoms::Bookmarks);
|
2008-02-07 00:56:02 +03:00
|
|
|
|
case XF86XK_HomePage:
|
2011-10-14 22:11:22 +04:00
|
|
|
|
return DispatchCommandEvent(nsGkAtoms::Home);
|
2011-07-14 05:58:07 +04:00
|
|
|
|
case XF86XK_Copy:
|
|
|
|
|
case GDK_F16: // F16, F20, F18, F14 are old keysyms for Copy Cut Paste Undo
|
2015-09-10 19:59:52 +03:00
|
|
|
|
return DispatchContentCommandEvent(eContentCommandCopy);
|
2011-07-14 05:58:07 +04:00
|
|
|
|
case XF86XK_Cut:
|
|
|
|
|
case GDK_F20:
|
2015-09-10 19:59:52 +03:00
|
|
|
|
return DispatchContentCommandEvent(eContentCommandCut);
|
2011-07-14 05:58:07 +04:00
|
|
|
|
case XF86XK_Paste:
|
|
|
|
|
case GDK_F18:
|
2015-09-10 19:59:52 +03:00
|
|
|
|
return DispatchContentCommandEvent(eContentCommandPaste);
|
2011-07-14 05:58:07 +04:00
|
|
|
|
case GDK_Redo:
|
2015-09-10 19:59:53 +03:00
|
|
|
|
return DispatchContentCommandEvent(eContentCommandRedo);
|
2011-07-14 05:58:07 +04:00
|
|
|
|
case GDK_Undo:
|
|
|
|
|
case GDK_F14:
|
2015-09-10 19:59:53 +03:00
|
|
|
|
return DispatchContentCommandEvent(eContentCommandUndo);
|
2008-02-07 00:56:02 +03:00
|
|
|
|
}
|
2010-03-28 19:50:39 +04:00
|
|
|
|
#endif /* ! AIX */
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#endif /* MOZ_X11 */
|
2008-02-07 00:56:02 +03:00
|
|
|
|
|
2015-08-29 02:58:27 +03:00
|
|
|
|
WidgetKeyboardEvent event(true, eKeyPress, this);
|
2012-02-22 11:34:31 +04:00
|
|
|
|
KeymapWrapper::InitKeyEvent(event, aEvent);
|
2001-12-12 06:03:05 +03:00
|
|
|
|
|
2002-12-15 01:23:06 +03:00
|
|
|
|
// before we dispatch a key, check if it's the context menu key.
|
|
|
|
|
// If so, send a context menu key event instead.
|
|
|
|
|
if (is_context_menu_key(event)) {
|
2015-08-31 18:20:06 +03:00
|
|
|
|
WidgetMouseEvent contextMenuEvent(true, eContextMenu, this,
|
2013-10-02 10:38:27 +04:00
|
|
|
|
WidgetMouseEvent::eReal,
|
|
|
|
|
WidgetMouseEvent::eContextMenuKey);
|
2012-02-22 11:34:31 +04:00
|
|
|
|
|
2013-08-02 11:05:16 +04:00
|
|
|
|
contextMenuEvent.refPoint = LayoutDeviceIntPoint(0, 0);
|
2012-02-22 11:34:31 +04:00
|
|
|
|
contextMenuEvent.time = aEvent->time;
|
2015-08-11 10:40:34 +03:00
|
|
|
|
contextMenuEvent.timeStamp = GetEventTimeStamp(aEvent->time);
|
2012-02-22 11:34:31 +04:00
|
|
|
|
contextMenuEvent.clickCount = 1;
|
|
|
|
|
KeymapWrapper::InitInputEvent(contextMenuEvent, aEvent->state);
|
2015-03-17 02:29:55 +03:00
|
|
|
|
status = DispatchInputEvent(&contextMenuEvent);
|
2002-12-15 01:23:06 +03:00
|
|
|
|
}
|
2003-04-09 07:34:53 +04:00
|
|
|
|
else {
|
2010-07-04 16:42:04 +04:00
|
|
|
|
// If the character code is in the BMP, send the key press event.
|
2014-10-07 14:01:47 +04:00
|
|
|
|
// Otherwise, send a compositionchange event with the equivalent UTF-16
|
|
|
|
|
// string.
|
2010-07-04 16:42:04 +04:00
|
|
|
|
if (IS_IN_BMP(event.charCode)) {
|
2015-03-17 02:29:55 +03:00
|
|
|
|
status = DispatchInputEvent(&event);
|
2010-07-04 16:42:04 +04:00
|
|
|
|
}
|
|
|
|
|
else {
|
2014-10-07 14:01:49 +04:00
|
|
|
|
WidgetCompositionEvent compositionChangeEvent(
|
2015-09-11 15:21:27 +03:00
|
|
|
|
true, eCompositionChange, this);
|
2014-01-04 19:02:17 +04:00
|
|
|
|
char16_t textString[3];
|
2010-07-04 16:42:04 +04:00
|
|
|
|
textString[0] = H_SURROGATE(event.charCode);
|
|
|
|
|
textString[1] = L_SURROGATE(event.charCode);
|
|
|
|
|
textString[2] = 0;
|
2014-10-07 14:01:49 +04:00
|
|
|
|
compositionChangeEvent.mData = textString;
|
|
|
|
|
compositionChangeEvent.time = event.time;
|
2015-08-11 10:40:34 +03:00
|
|
|
|
compositionChangeEvent.timeStamp = GetEventTimeStamp(aEvent->time);
|
2014-10-07 14:01:49 +04:00
|
|
|
|
DispatchEvent(&compositionChangeEvent, status);
|
2010-07-04 16:42:04 +04:00
|
|
|
|
}
|
2003-04-09 07:34:53 +04:00
|
|
|
|
}
|
|
|
|
|
|
2015-09-24 05:50:00 +03:00
|
|
|
|
return TRUE;
|
2001-12-12 06:03:05 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2012-10-23 02:33:30 +04:00
|
|
|
|
nsWindow::OnKeyReleaseEvent(GdkEventKey *aEvent)
|
2001-12-12 06:03:05 +03:00
|
|
|
|
{
|
2002-11-06 06:29:02 +03:00
|
|
|
|
LOGFOCUS(("OnKeyReleaseEvent [%p]\n", (void *)this));
|
2003-04-09 07:34:53 +04:00
|
|
|
|
|
2015-07-27 02:23:04 +03:00
|
|
|
|
if (mIMContext && mIMContext->OnKeyEvent(this, aEvent)) {
|
2003-04-09 07:34:53 +04:00
|
|
|
|
return TRUE;
|
2010-03-19 07:21:16 +03:00
|
|
|
|
}
|
2003-04-09 07:34:53 +04:00
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
// send the key event as a key up event
|
2015-08-29 02:58:27 +03:00
|
|
|
|
WidgetKeyboardEvent event(true, eKeyUp, this);
|
2012-02-22 11:34:31 +04:00
|
|
|
|
KeymapWrapper::InitKeyEvent(event, aEvent);
|
2001-12-12 06:03:05 +03:00
|
|
|
|
|
2015-09-24 05:50:00 +03:00
|
|
|
|
(void)DispatchInputEvent(&event);
|
2015-09-23 19:28:51 +03:00
|
|
|
|
|
2015-09-24 05:50:00 +03:00
|
|
|
|
return TRUE;
|
2001-12-12 06:03:05 +03:00
|
|
|
|
}
|
|
|
|
|
|
2001-12-13 02:56:21 +03:00
|
|
|
|
void
|
2012-10-23 02:33:30 +04:00
|
|
|
|
nsWindow::OnScrollEvent(GdkEventScroll *aEvent)
|
2001-12-13 02:56:21 +03:00
|
|
|
|
{
|
2002-04-27 20:26:10 +04:00
|
|
|
|
// check to see if we should rollup
|
2012-10-26 17:15:22 +04:00
|
|
|
|
if (CheckForRollup(aEvent->x_root, aEvent->y_root, true, false))
|
2002-04-27 20:26:10 +04:00
|
|
|
|
return;
|
2015-10-19 14:22:55 +03:00
|
|
|
|
#if GTK_CHECK_VERSION(3,4,0)
|
2014-07-07 13:54:13 +04:00
|
|
|
|
// check for duplicate legacy scroll event, see GNOME bug 726878
|
2015-06-03 14:47:00 +03:00
|
|
|
|
if (aEvent->direction != GDK_SCROLL_SMOOTH &&
|
|
|
|
|
mLastScrollEventTime == aEvent->time)
|
2014-07-07 13:54:13 +04:00
|
|
|
|
return;
|
2015-10-19 14:22:55 +03:00
|
|
|
|
#endif
|
2015-09-10 19:59:54 +03:00
|
|
|
|
WidgetWheelEvent wheelEvent(true, eWheel, this);
|
2012-08-12 05:42:37 +04:00
|
|
|
|
wheelEvent.deltaMode = nsIDOMWheelEvent::DOM_DELTA_LINE;
|
2007-12-11 11:49:46 +03:00
|
|
|
|
switch (aEvent->direction) {
|
2015-10-19 14:22:55 +03:00
|
|
|
|
#if GTK_CHECK_VERSION(3,4,0)
|
2014-07-07 13:54:13 +04:00
|
|
|
|
case GDK_SCROLL_SMOOTH:
|
|
|
|
|
{
|
|
|
|
|
// As of GTK 3.4, all directional scroll events are provided by
|
|
|
|
|
// the GDK_SCROLL_SMOOTH direction on XInput2 devices.
|
|
|
|
|
mLastScrollEventTime = aEvent->time;
|
|
|
|
|
// TODO - use a more appropriate scrolling unit than lines.
|
|
|
|
|
// Multiply event deltas by 3 to emulate legacy behaviour.
|
|
|
|
|
wheelEvent.deltaX = aEvent->delta_x * 3;
|
|
|
|
|
wheelEvent.deltaY = aEvent->delta_y * 3;
|
|
|
|
|
wheelEvent.mIsNoLineOrPageDelta = true;
|
|
|
|
|
// This next step manually unsets smooth scrolling for touch devices
|
|
|
|
|
// that trigger GDK_SCROLL_SMOOTH. We use the slave device, which
|
|
|
|
|
// represents the actual input.
|
|
|
|
|
GdkDevice *device = gdk_event_get_source_device((GdkEvent*)aEvent);
|
|
|
|
|
GdkInputSource source = gdk_device_get_source(device);
|
|
|
|
|
if (source == GDK_SOURCE_TOUCHSCREEN ||
|
|
|
|
|
source == GDK_SOURCE_TOUCHPAD) {
|
|
|
|
|
wheelEvent.scrollType = WidgetWheelEvent::SCROLL_ASYNCHRONOUSELY;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2015-10-19 14:22:55 +03:00
|
|
|
|
#endif
|
2007-12-11 11:49:46 +03:00
|
|
|
|
case GDK_SCROLL_UP:
|
2012-08-12 05:42:37 +04:00
|
|
|
|
wheelEvent.deltaY = wheelEvent.lineOrPageDeltaY = -3;
|
2007-12-11 11:49:46 +03:00
|
|
|
|
break;
|
|
|
|
|
case GDK_SCROLL_DOWN:
|
2012-08-12 05:42:37 +04:00
|
|
|
|
wheelEvent.deltaY = wheelEvent.lineOrPageDeltaY = 3;
|
2007-12-11 11:49:46 +03:00
|
|
|
|
break;
|
|
|
|
|
case GDK_SCROLL_LEFT:
|
2012-08-12 05:42:37 +04:00
|
|
|
|
wheelEvent.deltaX = wheelEvent.lineOrPageDeltaX = -1;
|
2007-12-11 11:49:46 +03:00
|
|
|
|
break;
|
|
|
|
|
case GDK_SCROLL_RIGHT:
|
2012-08-12 05:42:37 +04:00
|
|
|
|
wheelEvent.deltaX = wheelEvent.lineOrPageDeltaX = 1;
|
2007-12-11 11:49:46 +03:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-22 07:06:14 +03:00
|
|
|
|
wheelEvent.refPoint = GetRefPoint(this, aEvent);
|
2007-12-11 11:49:46 +03:00
|
|
|
|
|
2012-08-12 05:42:37 +04:00
|
|
|
|
KeymapWrapper::InitInputEvent(wheelEvent, aEvent->state);
|
2007-12-11 11:49:46 +03:00
|
|
|
|
|
2012-08-12 05:42:37 +04:00
|
|
|
|
wheelEvent.time = aEvent->time;
|
2015-08-11 10:40:34 +03:00
|
|
|
|
wheelEvent.timeStamp = GetEventTimeStamp(aEvent->time);
|
2007-12-11 11:49:46 +03:00
|
|
|
|
|
2015-03-07 01:26:59 +03:00
|
|
|
|
DispatchAPZAwareEvent(&wheelEvent);
|
2001-12-13 02:56:21 +03:00
|
|
|
|
}
|
|
|
|
|
|
2002-01-23 09:39:48 +03:00
|
|
|
|
void
|
2012-10-23 02:33:30 +04:00
|
|
|
|
nsWindow::OnVisibilityNotifyEvent(GdkEventVisibility *aEvent)
|
2002-04-27 20:26:10 +04:00
|
|
|
|
{
|
2009-11-02 05:03:12 +03:00
|
|
|
|
LOGDRAW(("Visibility event %i on [%p] %p\n",
|
|
|
|
|
aEvent->state, this, aEvent->window));
|
|
|
|
|
|
|
|
|
|
if (!mGdkWindow)
|
|
|
|
|
return;
|
|
|
|
|
|
2002-04-27 20:26:10 +04:00
|
|
|
|
switch (aEvent->state) {
|
|
|
|
|
case GDK_VISIBILITY_UNOBSCURED:
|
|
|
|
|
case GDK_VISIBILITY_PARTIAL:
|
2009-11-02 05:03:12 +03:00
|
|
|
|
if (mIsFullyObscured && mHasMappedToplevel) {
|
|
|
|
|
// GDK_EXPOSE events have been ignored, so make sure GDK
|
|
|
|
|
// doesn't think that the window has already been painted.
|
2013-10-08 22:47:37 +04:00
|
|
|
|
gdk_window_invalidate_rect(mGdkWindow, nullptr, FALSE);
|
2009-11-02 05:03:12 +03:00
|
|
|
|
}
|
|
|
|
|
|
2011-10-03 11:56:21 +04:00
|
|
|
|
mIsFullyObscured = false;
|
2009-11-02 05:03:12 +03:00
|
|
|
|
|
2014-11-10 12:07:44 +03:00
|
|
|
|
// if we have to retry the grab, retry it.
|
|
|
|
|
EnsureGrabs();
|
2002-04-27 20:26:10 +04:00
|
|
|
|
break;
|
|
|
|
|
default: // includes GDK_VISIBILITY_FULLY_OBSCURED
|
2011-10-03 11:56:21 +04:00
|
|
|
|
mIsFullyObscured = true;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
break;
|
|
|
|
|
}
|
2002-01-23 09:39:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-30 23:03:12 +04:00
|
|
|
|
void
|
|
|
|
|
nsWindow::OnWindowStateEvent(GtkWidget *aWidget, GdkEventWindowState *aEvent)
|
|
|
|
|
{
|
|
|
|
|
LOG(("nsWindow::OnWindowStateEvent [%p] changed %d new_window_state %d\n",
|
|
|
|
|
(void *)this, aEvent->changed_mask, aEvent->new_window_state));
|
|
|
|
|
|
2009-11-02 05:03:12 +03:00
|
|
|
|
if (IS_MOZ_CONTAINER(aWidget)) {
|
|
|
|
|
// This event is notifying the container widget of changes to the
|
|
|
|
|
// toplevel window. Just detect changes affecting whether windows are
|
|
|
|
|
// viewable.
|
|
|
|
|
//
|
|
|
|
|
// (A visibility notify event is sent to each window that becomes
|
|
|
|
|
// viewable when the toplevel is mapped, but we can't rely on that for
|
|
|
|
|
// setting mHasMappedToplevel because these toplevel window state
|
|
|
|
|
// events are asynchronous. The windows in the hierarchy now may not
|
|
|
|
|
// be the same windows as when the toplevel was mapped, so they may
|
|
|
|
|
// not get VisibilityNotify events.)
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool mapped =
|
2009-11-02 05:03:12 +03:00
|
|
|
|
!(aEvent->new_window_state &
|
|
|
|
|
(GDK_WINDOW_STATE_ICONIFIED|GDK_WINDOW_STATE_WITHDRAWN));
|
|
|
|
|
if (mHasMappedToplevel != mapped) {
|
|
|
|
|
SetHasMappedToplevel(mapped);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// else the widget is a shell widget.
|
|
|
|
|
|
2012-02-06 22:17:32 +04:00
|
|
|
|
// We don't care about anything but changes in the maximized/icon/fullscreen
|
2003-03-20 08:24:25 +03:00
|
|
|
|
// states
|
2007-12-19 14:21:05 +03:00
|
|
|
|
if ((aEvent->changed_mask
|
2012-02-06 22:17:32 +04:00
|
|
|
|
& (GDK_WINDOW_STATE_ICONIFIED |
|
|
|
|
|
GDK_WINDOW_STATE_MAXIMIZED |
|
|
|
|
|
GDK_WINDOW_STATE_FULLSCREEN)) == 0) {
|
2003-03-20 08:24:25 +03:00
|
|
|
|
return;
|
2002-04-30 23:03:12 +04:00
|
|
|
|
}
|
2003-03-20 08:24:25 +03:00
|
|
|
|
|
2015-06-10 14:13:12 +03:00
|
|
|
|
bool wasInFullscreen = mSizeState == nsSizeMode_Fullscreen;
|
2003-03-20 08:24:25 +03:00
|
|
|
|
if (aEvent->new_window_state & GDK_WINDOW_STATE_ICONIFIED) {
|
|
|
|
|
LOG(("\tIconified\n"));
|
2002-04-30 23:03:12 +04:00
|
|
|
|
mSizeState = nsSizeMode_Minimized;
|
2011-03-26 19:06:00 +03:00
|
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
|
DispatchMinimizeEventAccessible();
|
|
|
|
|
#endif //ACCESSIBILITY
|
2002-04-30 23:03:12 +04:00
|
|
|
|
}
|
2012-02-06 22:17:32 +04:00
|
|
|
|
else if (aEvent->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) {
|
|
|
|
|
LOG(("\tFullscreen\n"));
|
|
|
|
|
mSizeState = nsSizeMode_Fullscreen;
|
|
|
|
|
}
|
2003-03-20 08:24:25 +03:00
|
|
|
|
else if (aEvent->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) {
|
|
|
|
|
LOG(("\tMaximized\n"));
|
|
|
|
|
mSizeState = nsSizeMode_Maximized;
|
2011-03-26 19:06:00 +03:00
|
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
|
DispatchMaximizeEventAccessible();
|
|
|
|
|
#endif //ACCESSIBILITY
|
2003-03-20 08:24:25 +03:00
|
|
|
|
}
|
|
|
|
|
else {
|
2002-04-30 23:03:12 +04:00
|
|
|
|
LOG(("\tNormal\n"));
|
|
|
|
|
mSizeState = nsSizeMode_Normal;
|
2011-03-26 19:06:00 +03:00
|
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
|
DispatchRestoreEventAccessible();
|
|
|
|
|
#endif //ACCESSIBILITY
|
2002-04-30 23:03:12 +04:00
|
|
|
|
}
|
|
|
|
|
|
2015-06-10 14:13:12 +03:00
|
|
|
|
if (mWidgetListener) {
|
2012-08-15 22:52:42 +04:00
|
|
|
|
mWidgetListener->SizeModeChanged(mSizeState);
|
2015-06-10 14:13:12 +03:00
|
|
|
|
|
|
|
|
|
bool isInFullscreen = mSizeState == nsSizeMode_Fullscreen;
|
|
|
|
|
if (isInFullscreen != wasInFullscreen) {
|
|
|
|
|
mWidgetListener->FullscreenChanged(isInFullscreen);
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-04-30 23:03:12 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-09-17 10:27:01 +04:00
|
|
|
|
void
|
|
|
|
|
nsWindow::ThemeChanged()
|
|
|
|
|
{
|
2012-08-15 22:52:35 +04:00
|
|
|
|
NotifyThemeChanged();
|
2004-09-17 10:27:01 +04:00
|
|
|
|
|
2012-10-26 17:32:10 +04:00
|
|
|
|
if (!mGdkWindow || MOZ_UNLIKELY(mIsDestroyed))
|
2004-09-17 10:27:01 +04:00
|
|
|
|
return;
|
|
|
|
|
|
2012-08-15 22:52:35 +04:00
|
|
|
|
// Dispatch theme change notification to all child windows
|
2004-10-11 08:01:49 +04:00
|
|
|
|
GList *children =
|
2009-07-27 05:39:36 +04:00
|
|
|
|
gdk_window_peek_children(mGdkWindow);
|
2004-09-17 10:27:01 +04:00
|
|
|
|
while (children) {
|
|
|
|
|
GdkWindow *gdkWin = GDK_WINDOW(children->data);
|
|
|
|
|
|
|
|
|
|
nsWindow *win = (nsWindow*) g_object_get_data(G_OBJECT(gdkWin),
|
|
|
|
|
"nsWindow");
|
|
|
|
|
|
2007-04-30 04:46:47 +04:00
|
|
|
|
if (win && win != this) { // guard against infinite recursion
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> kungFuDeathGrip = win;
|
2004-09-17 10:27:01 +04:00
|
|
|
|
win->ThemeChanged();
|
2007-04-30 04:46:47 +04:00
|
|
|
|
}
|
2004-09-17 10:27:01 +04:00
|
|
|
|
|
|
|
|
|
children = children->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-17 05:00:25 +04:00
|
|
|
|
void
|
2015-10-26 23:33:13 +03:00
|
|
|
|
nsWindow::DispatchDragEvent(EventMessage aMsg, const LayoutDeviceIntPoint& aRefPoint,
|
2012-04-17 05:00:25 +04:00
|
|
|
|
guint aTime)
|
|
|
|
|
{
|
2013-10-01 11:23:02 +04:00
|
|
|
|
WidgetDragEvent event(true, aMsg, this);
|
2012-04-17 05:00:25 +04:00
|
|
|
|
|
2015-09-02 09:08:02 +03:00
|
|
|
|
if (aMsg == eDragOver) {
|
2012-04-17 05:00:25 +04:00
|
|
|
|
InitDragEvent(event);
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-26 23:33:13 +03:00
|
|
|
|
event.refPoint = aRefPoint;
|
2012-04-17 05:00:25 +04:00
|
|
|
|
event.time = aTime;
|
2015-08-11 10:40:34 +03:00
|
|
|
|
event.timeStamp = GetEventTimeStamp(aTime);
|
2012-04-17 05:00:25 +04:00
|
|
|
|
|
2015-03-17 02:29:55 +03:00
|
|
|
|
DispatchInputEvent(&event);
|
2012-04-17 05:00:25 +04:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
void
|
|
|
|
|
nsWindow::OnDragDataReceivedEvent(GtkWidget *aWidget,
|
|
|
|
|
GdkDragContext *aDragContext,
|
|
|
|
|
gint aX,
|
|
|
|
|
gint aY,
|
|
|
|
|
GtkSelectionData *aSelectionData,
|
|
|
|
|
guint aInfo,
|
|
|
|
|
guint aTime,
|
|
|
|
|
gpointer aData)
|
2002-04-27 20:26:10 +04:00
|
|
|
|
{
|
2009-06-15 04:48:52 +04:00
|
|
|
|
LOGDRAG(("nsWindow::OnDragDataReceived(%p)\n", (void*)this));
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2012-04-19 10:18:31 +04:00
|
|
|
|
nsDragService::GetInstance()->
|
|
|
|
|
TargetDataReceived(aWidget, aDragContext, aX, aY,
|
|
|
|
|
aSelectionData, aInfo, aTime);
|
2002-01-27 23:30:56 +03:00
|
|
|
|
}
|
|
|
|
|
|
2015-04-29 23:29:34 +03:00
|
|
|
|
#if GTK_CHECK_VERSION(3,4,0)
|
|
|
|
|
static PLDHashOperator AppendTouchToEvent(GdkEventSequence* aKey,
|
|
|
|
|
dom::Touch* aData,
|
|
|
|
|
void* aArg)
|
|
|
|
|
{
|
|
|
|
|
WidgetTouchEvent* event = reinterpret_cast<WidgetTouchEvent*>(aArg);
|
|
|
|
|
event->touches.AppendElement(new dom::Touch(*aData));
|
|
|
|
|
|
|
|
|
|
return PL_DHASH_NEXT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nsWindow::OnTouchEvent(GdkEventTouch* aEvent)
|
|
|
|
|
{
|
|
|
|
|
if (!mHandleTouchEvent) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EventMessage msg;
|
|
|
|
|
switch (aEvent->type) {
|
|
|
|
|
case GDK_TOUCH_BEGIN:
|
|
|
|
|
msg = eTouchStart;
|
|
|
|
|
break;
|
|
|
|
|
case GDK_TOUCH_UPDATE:
|
|
|
|
|
msg = eTouchMove;
|
|
|
|
|
break;
|
|
|
|
|
case GDK_TOUCH_END:
|
|
|
|
|
msg = eTouchEnd;
|
|
|
|
|
break;
|
|
|
|
|
case GDK_TOUCH_CANCEL:
|
|
|
|
|
msg = eTouchCancel;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-22 07:06:14 +03:00
|
|
|
|
LayoutDeviceIntPoint touchPoint = GetRefPoint(this, aEvent);
|
2015-04-29 23:29:34 +03:00
|
|
|
|
|
|
|
|
|
int32_t id;
|
|
|
|
|
RefPtr<dom::Touch> touch;
|
|
|
|
|
if (mTouches.Remove(aEvent->sequence, getter_AddRefs(touch))) {
|
|
|
|
|
id = touch->mIdentifier;
|
|
|
|
|
} else {
|
|
|
|
|
id = ++gLastTouchID & 0x7FFFFFFF;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-10 08:37:31 +03:00
|
|
|
|
touch = new dom::Touch(id, touchPoint, LayoutDeviceIntPoint(1, 1),
|
|
|
|
|
0.0f, 0.0f);
|
2015-04-29 23:29:34 +03:00
|
|
|
|
|
|
|
|
|
WidgetTouchEvent event(true, msg, this);
|
|
|
|
|
KeymapWrapper::InitInputEvent(event, aEvent->state);
|
|
|
|
|
event.time = aEvent->time;
|
|
|
|
|
|
|
|
|
|
if (aEvent->type == GDK_TOUCH_BEGIN || aEvent->type == GDK_TOUCH_UPDATE) {
|
|
|
|
|
mTouches.Put(aEvent->sequence, touch.forget());
|
|
|
|
|
// add all touch points to event object
|
|
|
|
|
mTouches.EnumerateRead(AppendTouchToEvent, &event);
|
|
|
|
|
} else if (aEvent->type == GDK_TOUCH_END ||
|
|
|
|
|
aEvent->type == GDK_TOUCH_CANCEL) {
|
|
|
|
|
*event.touches.AppendElement() = touch.forget();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DispatchAPZAwareEvent(&event);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2006-07-19 16:56:40 +04:00
|
|
|
|
static void
|
|
|
|
|
GetBrandName(nsXPIDLString& brandName)
|
|
|
|
|
{
|
2009-02-28 04:47:40 +03:00
|
|
|
|
nsCOMPtr<nsIStringBundleService> bundleService =
|
2006-07-19 16:56:40 +04:00
|
|
|
|
do_GetService(NS_STRINGBUNDLE_CONTRACTID);
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIStringBundle> bundle;
|
|
|
|
|
if (bundleService)
|
|
|
|
|
bundleService->CreateBundle(
|
|
|
|
|
"chrome://branding/locale/brand.properties",
|
|
|
|
|
getter_AddRefs(bundle));
|
|
|
|
|
|
|
|
|
|
if (bundle)
|
|
|
|
|
bundle->GetStringFromName(
|
2013-12-13 05:50:01 +04:00
|
|
|
|
MOZ_UTF16("brandShortName"),
|
2006-07-19 16:56:40 +04:00
|
|
|
|
getter_Copies(brandName));
|
|
|
|
|
|
|
|
|
|
if (brandName.IsEmpty())
|
2014-05-26 22:54:10 +04:00
|
|
|
|
brandName.AssignLiteral(MOZ_UTF16("Mozilla"));
|
2006-07-19 16:56:40 +04:00
|
|
|
|
}
|
|
|
|
|
|
2009-07-27 05:39:36 +04:00
|
|
|
|
static GdkWindow *
|
|
|
|
|
CreateGdkWindow(GdkWindow *parent, GtkWidget *widget)
|
|
|
|
|
{
|
|
|
|
|
GdkWindowAttr attributes;
|
2011-09-23 00:58:07 +04:00
|
|
|
|
gint attributes_mask = GDK_WA_VISUAL;
|
2009-07-27 05:39:36 +04:00
|
|
|
|
|
2012-10-23 02:39:59 +04:00
|
|
|
|
attributes.event_mask = kEvents;
|
2009-07-27 05:39:36 +04:00
|
|
|
|
|
|
|
|
|
attributes.width = 1;
|
|
|
|
|
attributes.height = 1;
|
|
|
|
|
attributes.wclass = GDK_INPUT_OUTPUT;
|
|
|
|
|
attributes.visual = gtk_widget_get_visual(widget);
|
|
|
|
|
attributes.window_type = GDK_WINDOW_CHILD;
|
|
|
|
|
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2011-09-23 00:58:07 +04:00
|
|
|
|
attributes_mask |= GDK_WA_COLORMAP;
|
|
|
|
|
attributes.colormap = gtk_widget_get_colormap(widget);
|
|
|
|
|
#endif
|
|
|
|
|
|
2009-07-27 05:39:36 +04:00
|
|
|
|
GdkWindow *window = gdk_window_new(parent, &attributes, attributes_mask);
|
|
|
|
|
gdk_window_set_user_data(window, widget);
|
|
|
|
|
|
2011-09-23 00:58:07 +04:00
|
|
|
|
// GTK3 TODO?
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2009-07-27 05:39:36 +04:00
|
|
|
|
/* set the default pixmap to None so that you don't end up with the
|
|
|
|
|
gtk default which is BlackPixel. */
|
2013-10-08 22:47:37 +04:00
|
|
|
|
gdk_window_set_back_pixmap(window, nullptr, FALSE);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#endif
|
2009-07-27 05:39:36 +04:00
|
|
|
|
|
|
|
|
|
return window;
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
nsresult
|
2009-09-24 10:18:10 +04:00
|
|
|
|
nsWindow::Create(nsIWidget *aParent,
|
|
|
|
|
nsNativeWidget aNativeParent,
|
|
|
|
|
const nsIntRect &aRect,
|
|
|
|
|
nsWidgetInitData *aInitData)
|
2001-12-18 01:05:58 +03:00
|
|
|
|
{
|
2002-08-10 22:21:22 +04:00
|
|
|
|
// only set the base parent if we're going to be a dialog or a
|
|
|
|
|
// toplevel
|
|
|
|
|
nsIWidget *baseParent = aInitData &&
|
|
|
|
|
(aInitData->mWindowType == eWindowType_dialog ||
|
2003-07-25 18:53:37 +04:00
|
|
|
|
aInitData->mWindowType == eWindowType_toplevel ||
|
|
|
|
|
aInitData->mWindowType == eWindowType_invisible) ?
|
2012-07-30 18:20:58 +04:00
|
|
|
|
nullptr : aParent;
|
2001-12-18 01:05:58 +03:00
|
|
|
|
|
2012-01-05 05:54:17 +04:00
|
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
|
// Send a DBus message to check whether a11y is enabled
|
|
|
|
|
a11y::PreInit();
|
|
|
|
|
#endif
|
|
|
|
|
|
2011-10-25 19:05:32 +04:00
|
|
|
|
// Ensure that the toolkit is created.
|
|
|
|
|
nsGTKToolkit::GetToolkit();
|
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
// initialize all the common bits of this class
|
2015-02-05 08:18:30 +03:00
|
|
|
|
BaseCreate(baseParent, aRect, aInitData);
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2002-11-26 18:46:55 +03:00
|
|
|
|
// Do we need to listen for resizes?
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool listenForResizes = false;;
|
2002-11-26 19:01:26 +03:00
|
|
|
|
if (aNativeParent || (aInitData && aInitData->mListenForResizes))
|
2011-10-03 11:56:21 +04:00
|
|
|
|
listenForResizes = true;
|
2002-11-26 18:46:55 +03:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
// and do our common creation
|
2002-11-26 18:46:55 +03:00
|
|
|
|
CommonCreate(aParent, listenForResizes);
|
2001-12-18 01:05:58 +03:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
// save our bounds
|
|
|
|
|
mBounds = aRect;
|
2012-11-28 02:07:11 +04:00
|
|
|
|
ConstrainSize(&mBounds.width, &mBounds.height);
|
2001-12-18 01:05:58 +03:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
// figure out our parent window
|
2012-07-30 18:20:58 +04:00
|
|
|
|
GtkWidget *parentMozContainer = nullptr;
|
|
|
|
|
GtkContainer *parentGtkContainer = nullptr;
|
|
|
|
|
GdkWindow *parentGdkWindow = nullptr;
|
|
|
|
|
GtkWindow *topLevelParent = nullptr;
|
2012-10-23 02:39:59 +04:00
|
|
|
|
nsWindow *parentnsWindow = nullptr;
|
|
|
|
|
GtkWidget *eventWidget = nullptr;
|
2015-10-12 10:56:00 +03:00
|
|
|
|
bool shellHasCSD = false;
|
2002-01-27 23:30:56 +03:00
|
|
|
|
|
2012-10-23 02:39:59 +04:00
|
|
|
|
if (aParent) {
|
|
|
|
|
parentnsWindow = static_cast<nsWindow*>(aParent);
|
|
|
|
|
parentGdkWindow = parentnsWindow->mGdkWindow;
|
|
|
|
|
} else if (aNativeParent && GDK_IS_WINDOW(aNativeParent)) {
|
2002-08-10 22:21:22 +04:00
|
|
|
|
parentGdkWindow = GDK_WINDOW(aNativeParent);
|
2012-10-23 02:39:59 +04:00
|
|
|
|
parentnsWindow = get_window_for_gdk_window(parentGdkWindow);
|
|
|
|
|
if (!parentnsWindow)
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
|
|
} else if (aNativeParent && GTK_IS_CONTAINER(aNativeParent)) {
|
2002-08-10 22:21:22 +04:00
|
|
|
|
parentGtkContainer = GTK_CONTAINER(aNativeParent);
|
2012-10-23 02:39:59 +04:00
|
|
|
|
}
|
2002-01-27 23:30:56 +03:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (parentGdkWindow) {
|
2009-07-27 05:39:36 +04:00
|
|
|
|
// get the widget for the window - it should be a moz container
|
2012-10-23 02:39:59 +04:00
|
|
|
|
parentMozContainer = parentnsWindow->GetMozContainerWidget();
|
|
|
|
|
if (!parentMozContainer)
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return NS_ERROR_FAILURE;
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
// get the toplevel window just in case someone needs to use it
|
|
|
|
|
// for setting transients or whatever.
|
|
|
|
|
topLevelParent =
|
2012-10-23 02:39:59 +04:00
|
|
|
|
GTK_WINDOW(gtk_widget_get_toplevel(parentMozContainer));
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
// ok, create our windows
|
|
|
|
|
switch (mWindowType) {
|
|
|
|
|
case eWindowType_dialog:
|
|
|
|
|
case eWindowType_popup:
|
2003-07-25 18:53:37 +04:00
|
|
|
|
case eWindowType_toplevel:
|
|
|
|
|
case eWindowType_invisible: {
|
2011-10-03 11:56:21 +04:00
|
|
|
|
mIsTopLevel = true;
|
2006-07-19 16:56:40 +04:00
|
|
|
|
|
2015-07-14 06:23:47 +03:00
|
|
|
|
// Popups that are not noautohide are only temporary. The are used
|
|
|
|
|
// for menus and the like and disappear when another window is used.
|
|
|
|
|
// For most popups, use the standard GtkWindowType GTK_WINDOW_POPUP,
|
|
|
|
|
// which will use a Window with the override-redirect attribute
|
|
|
|
|
// (for temporary windows).
|
|
|
|
|
// For long-lived windows, their stacking order is managed by the
|
|
|
|
|
// window manager, as indicated by GTK_WINDOW_TOPLEVEL ...
|
|
|
|
|
GtkWindowType type =
|
|
|
|
|
mWindowType != eWindowType_popup || aInitData->mNoAutoHide ?
|
|
|
|
|
GTK_WINDOW_TOPLEVEL : GTK_WINDOW_POPUP;
|
|
|
|
|
mShell = gtk_window_new(type);
|
|
|
|
|
|
2011-07-08 07:13:52 +04:00
|
|
|
|
// We only move a general managed toplevel window if someone has
|
|
|
|
|
// actually placed the window somewhere. If no placement has taken
|
|
|
|
|
// place, we just let the window manager Do The Right Thing.
|
2015-07-14 06:24:56 +03:00
|
|
|
|
NativeResize();
|
2011-07-08 07:13:52 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (mWindowType == eWindowType_dialog) {
|
2002-11-16 04:22:10 +03:00
|
|
|
|
SetDefaultIcon();
|
2012-03-28 03:17:35 +04:00
|
|
|
|
gtk_window_set_wmclass(GTK_WINDOW(mShell), "Dialog",
|
|
|
|
|
gdk_get_program_class());
|
2002-08-10 22:21:22 +04:00
|
|
|
|
gtk_window_set_type_hint(GTK_WINDOW(mShell),
|
|
|
|
|
GDK_WINDOW_TYPE_HINT_DIALOG);
|
|
|
|
|
gtk_window_set_transient_for(GTK_WINDOW(mShell),
|
|
|
|
|
topLevelParent);
|
|
|
|
|
}
|
|
|
|
|
else if (mWindowType == eWindowType_popup) {
|
2011-07-08 07:13:52 +04:00
|
|
|
|
// With popup windows, we want to control their position, so don't
|
|
|
|
|
// wait for the window manager to place them (which wouldn't
|
|
|
|
|
// happen with override-redirect windows anyway).
|
2015-07-14 06:23:47 +03:00
|
|
|
|
NativeMove();
|
|
|
|
|
|
2012-10-03 10:53:53 +04:00
|
|
|
|
gtk_window_set_wmclass(GTK_WINDOW(mShell), "Popup",
|
|
|
|
|
gdk_get_program_class());
|
2012-11-14 06:04:42 +04:00
|
|
|
|
|
|
|
|
|
if (aInitData->mSupportTranslucency) {
|
|
|
|
|
// We need to select an ARGB visual here instead of in
|
2012-10-03 10:53:53 +04:00
|
|
|
|
// SetTransparencyMode() because it has to be done before the
|
2012-11-14 06:04:42 +04:00
|
|
|
|
// widget is realized. An ARGB visual is only useful if we
|
|
|
|
|
// are on a compositing window manager.
|
|
|
|
|
GdkScreen *screen = gtk_widget_get_screen(mShell);
|
2012-10-03 10:53:53 +04:00
|
|
|
|
if (gdk_screen_is_composited(screen)) {
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2012-10-03 10:53:53 +04:00
|
|
|
|
GdkColormap *colormap =
|
|
|
|
|
gdk_screen_get_rgba_colormap(screen);
|
|
|
|
|
gtk_widget_set_colormap(mShell, colormap);
|
|
|
|
|
#else
|
|
|
|
|
GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
|
|
|
|
|
gtk_widget_set_visual(mShell, visual);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2012-11-14 06:04:42 +04:00
|
|
|
|
}
|
|
|
|
|
if (aInitData->mNoAutoHide) {
|
2010-06-18 05:15:03 +04:00
|
|
|
|
// ... but the window manager does not decorate this window,
|
|
|
|
|
// nor provide a separate taskbar icon.
|
2010-07-27 17:38:04 +04:00
|
|
|
|
if (mBorderStyle == eBorderStyle_default) {
|
|
|
|
|
gtk_window_set_decorated(GTK_WINDOW(mShell), FALSE);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool decorate = mBorderStyle & eBorderStyle_title;
|
2010-07-27 17:38:04 +04:00
|
|
|
|
gtk_window_set_decorated(GTK_WINDOW(mShell), decorate);
|
|
|
|
|
if (decorate) {
|
|
|
|
|
gtk_window_set_deletable(GTK_WINDOW(mShell), mBorderStyle & eBorderStyle_close);
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-09-02 11:23:52 +04:00
|
|
|
|
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(mShell), TRUE);
|
2010-06-18 05:15:03 +04:00
|
|
|
|
// Element focus is managed by the parent window so the
|
|
|
|
|
// WM_HINTS input field is set to False to tell the window
|
|
|
|
|
// manager not to set input focus to this window ...
|
2010-09-02 11:23:52 +04:00
|
|
|
|
gtk_window_set_accept_focus(GTK_WINDOW(mShell), FALSE);
|
2010-06-18 05:15:03 +04:00
|
|
|
|
#ifdef MOZ_X11
|
|
|
|
|
// ... but when the window manager offers focus through
|
|
|
|
|
// WM_TAKE_FOCUS, focus is requested on the parent window.
|
|
|
|
|
gtk_widget_realize(mShell);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
gdk_window_add_filter(gtk_widget_get_window(mShell),
|
2013-10-08 22:47:37 +04:00
|
|
|
|
popup_take_focus_filter, nullptr);
|
2010-06-18 05:15:03 +04:00
|
|
|
|
#endif
|
2008-03-14 19:26:13 +03:00
|
|
|
|
}
|
2008-03-08 14:32:25 +03:00
|
|
|
|
|
|
|
|
|
GdkWindowTypeHint gtkTypeHint;
|
2011-04-26 05:37:20 +04:00
|
|
|
|
if (aInitData->mIsDragPopup) {
|
|
|
|
|
gtkTypeHint = GDK_WINDOW_TYPE_HINT_DND;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
switch (aInitData->mPopupHint) {
|
|
|
|
|
case ePopupTypeMenu:
|
|
|
|
|
gtkTypeHint = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
|
|
|
|
|
break;
|
|
|
|
|
case ePopupTypeTooltip:
|
|
|
|
|
gtkTypeHint = GDK_WINDOW_TYPE_HINT_TOOLTIP;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
gtkTypeHint = GDK_WINDOW_TYPE_HINT_UTILITY;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2007-11-28 23:18:11 +03:00
|
|
|
|
}
|
2008-03-08 14:32:25 +03:00
|
|
|
|
gtk_window_set_type_hint(GTK_WINDOW(mShell), gtkTypeHint);
|
2006-07-19 16:56:40 +04:00
|
|
|
|
|
2003-02-17 18:36:37 +03:00
|
|
|
|
if (topLevelParent) {
|
2004-10-11 08:01:49 +04:00
|
|
|
|
gtk_window_set_transient_for(GTK_WINDOW(mShell),
|
2002-08-10 22:21:22 +04:00
|
|
|
|
topLevelParent);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else { // must be eWindowType_toplevel
|
2002-11-16 04:22:10 +03:00
|
|
|
|
SetDefaultIcon();
|
2012-03-28 03:17:35 +04:00
|
|
|
|
gtk_window_set_wmclass(GTK_WINDOW(mShell), "Toplevel",
|
|
|
|
|
gdk_get_program_class());
|
2003-04-09 07:34:53 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
// each toplevel window gets its own window group
|
2013-01-03 00:44:12 +04:00
|
|
|
|
GtkWindowGroup *group = gtk_window_group_new();
|
|
|
|
|
gtk_window_group_add_window(group, GTK_WINDOW(mShell));
|
|
|
|
|
g_object_unref(group);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2012-10-23 02:39:59 +04:00
|
|
|
|
// Create a container to hold child windows and child GtkWidgets.
|
2009-07-27 05:39:36 +04:00
|
|
|
|
GtkWidget *container = moz_container_new();
|
|
|
|
|
mContainer = MOZ_CONTAINER(container);
|
2015-09-24 05:50:00 +03:00
|
|
|
|
|
2015-10-12 10:56:00 +03:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 3)
|
2015-09-24 05:50:00 +03:00
|
|
|
|
// "csd" style is set when widget is realized so we need to call
|
|
|
|
|
// it explicitly now.
|
|
|
|
|
gtk_widget_realize(mShell);
|
|
|
|
|
|
|
|
|
|
// We can't draw directly to top-level window when client side
|
|
|
|
|
// decorations are enabled. We use container with GdkWindow instead.
|
|
|
|
|
GtkStyleContext* style = gtk_widget_get_style_context(mShell);
|
2015-10-12 10:56:00 +03:00
|
|
|
|
shellHasCSD = gtk_style_context_has_class(style, "csd");
|
2015-09-24 05:50:00 +03:00
|
|
|
|
#endif
|
2015-10-12 10:56:00 +03:00
|
|
|
|
if (!shellHasCSD) {
|
2015-09-24 05:50:00 +03:00
|
|
|
|
// Use mShell's window for drawing and events.
|
|
|
|
|
gtk_widget_set_has_window(container, FALSE);
|
|
|
|
|
// Prevent GtkWindow from painting a background to flicker.
|
|
|
|
|
gtk_widget_set_app_paintable(mShell, TRUE);
|
|
|
|
|
}
|
|
|
|
|
// Set up event widget
|
2015-10-12 10:56:00 +03:00
|
|
|
|
eventWidget = shellHasCSD ? container : mShell;
|
2012-10-23 02:39:59 +04:00
|
|
|
|
gtk_widget_add_events(eventWidget, kEvents);
|
2015-09-24 05:50:00 +03:00
|
|
|
|
|
2009-07-27 05:39:36 +04:00
|
|
|
|
gtk_container_add(GTK_CONTAINER(mShell), container);
|
|
|
|
|
gtk_widget_realize(container);
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
// make sure this is the focus widget in the container
|
2012-11-15 11:22:07 +04:00
|
|
|
|
gtk_widget_show(container);
|
|
|
|
|
gtk_widget_grab_focus(container);
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2009-07-27 05:40:46 +04:00
|
|
|
|
// the drawing window
|
2015-09-24 05:50:00 +03:00
|
|
|
|
mGdkWindow = gtk_widget_get_window(eventWidget);
|
2003-09-11 06:51:21 +04:00
|
|
|
|
|
|
|
|
|
if (mWindowType == eWindowType_popup) {
|
|
|
|
|
// gdk does not automatically set the cursor for "temporary"
|
|
|
|
|
// windows, which are what gtk uses for popups.
|
|
|
|
|
|
|
|
|
|
mCursor = eCursor_wait; // force SetCursor to actually set the
|
|
|
|
|
// cursor, even though our internal state
|
|
|
|
|
// indicates that we already have the
|
|
|
|
|
// standard cursor.
|
|
|
|
|
SetCursor(eCursor_standard);
|
2010-07-27 17:38:03 +04:00
|
|
|
|
|
|
|
|
|
if (aInitData->mNoAutoHide) {
|
|
|
|
|
gint wmd = ConvertBorderStyles(mBorderStyle);
|
|
|
|
|
if (wmd != -1)
|
2015-04-21 10:06:41 +03:00
|
|
|
|
gdk_window_set_decorations(mGdkWindow, (GdkWMDecoration) wmd);
|
2010-07-27 17:38:03 +04:00
|
|
|
|
}
|
2014-01-31 17:27:43 +04:00
|
|
|
|
|
|
|
|
|
// If the popup ignores mouse events, set an empty input shape.
|
|
|
|
|
if (aInitData->mMouseTransparent) {
|
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
|
|
|
|
GdkRectangle rect = { 0, 0, 0, 0 };
|
|
|
|
|
GdkRegion *region = gdk_region_rectangle(&rect);
|
|
|
|
|
|
|
|
|
|
gdk_window_input_shape_combine_region(mGdkWindow, region, 0, 0);
|
|
|
|
|
gdk_region_destroy(region);
|
|
|
|
|
#else
|
|
|
|
|
cairo_rectangle_int_t rect = { 0, 0, 0, 0 };
|
|
|
|
|
cairo_region_t *region = cairo_region_create_rectangle(&rect);
|
|
|
|
|
|
|
|
|
|
gdk_window_input_shape_combine_region(mGdkWindow, region, 0, 0);
|
|
|
|
|
cairo_region_destroy(region);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2003-09-11 06:51:21 +04:00
|
|
|
|
}
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
|
|
|
|
break;
|
2009-09-24 13:32:20 +04:00
|
|
|
|
case eWindowType_plugin:
|
2014-11-12 23:59:19 +03:00
|
|
|
|
case eWindowType_plugin_ipc_chrome:
|
|
|
|
|
case eWindowType_plugin_ipc_content:
|
2002-08-10 22:21:22 +04:00
|
|
|
|
case eWindowType_child: {
|
|
|
|
|
if (parentMozContainer) {
|
2009-07-27 05:39:36 +04:00
|
|
|
|
mGdkWindow = CreateGdkWindow(parentGdkWindow, parentMozContainer);
|
2012-10-23 02:39:59 +04:00
|
|
|
|
mHasMappedToplevel = parentnsWindow->mHasMappedToplevel;
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
2003-02-14 18:11:42 +03:00
|
|
|
|
else if (parentGtkContainer) {
|
2012-10-23 02:39:59 +04:00
|
|
|
|
// This MozContainer has its own window for drawing and receives
|
|
|
|
|
// events because there is no mShell widget (corresponding to this
|
|
|
|
|
// nsWindow).
|
2009-07-27 05:39:36 +04:00
|
|
|
|
GtkWidget *container = moz_container_new();
|
|
|
|
|
mContainer = MOZ_CONTAINER(container);
|
2012-10-23 02:39:59 +04:00
|
|
|
|
eventWidget = container;
|
|
|
|
|
gtk_widget_add_events(eventWidget, kEvents);
|
2009-07-27 05:39:36 +04:00
|
|
|
|
gtk_container_add(parentGtkContainer, container);
|
|
|
|
|
gtk_widget_realize(container);
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2011-09-23 00:58:07 +04:00
|
|
|
|
mGdkWindow = gtk_widget_get_window(container);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
2003-12-10 21:56:07 +03:00
|
|
|
|
else {
|
|
|
|
|
NS_WARNING("Warning: tried to create a new child widget with no parent!");
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
}
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2002-01-28 09:47:47 +03:00
|
|
|
|
|
2009-07-27 05:39:36 +04:00
|
|
|
|
// label the drawing window with this object so we can find our way home
|
|
|
|
|
g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", this);
|
2001-12-10 20:37:36 +03:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (mContainer)
|
|
|
|
|
g_object_set_data(G_OBJECT(mContainer), "nsWindow", this);
|
2001-12-18 01:05:58 +03:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (mShell)
|
|
|
|
|
g_object_set_data(G_OBJECT(mShell), "nsWindow", this);
|
2001-12-18 01:05:58 +03:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
// attach listeners for events
|
|
|
|
|
if (mShell) {
|
2011-05-11 17:10:36 +04:00
|
|
|
|
g_signal_connect(mShell, "configure_event",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(configure_event_cb), nullptr);
|
2011-05-11 17:10:36 +04:00
|
|
|
|
g_signal_connect(mShell, "delete_event",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(delete_event_cb), nullptr);
|
2011-05-11 17:10:36 +04:00
|
|
|
|
g_signal_connect(mShell, "window_state_event",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(window_state_event_cb), nullptr);
|
2005-11-29 01:44:33 +03:00
|
|
|
|
|
|
|
|
|
GtkSettings* default_settings = gtk_settings_get_default();
|
|
|
|
|
g_signal_connect_after(default_settings,
|
|
|
|
|
"notify::gtk-theme-name",
|
|
|
|
|
G_CALLBACK(theme_changed_cb), this);
|
|
|
|
|
g_signal_connect_after(default_settings,
|
|
|
|
|
"notify::gtk-font-name",
|
|
|
|
|
G_CALLBACK(theme_changed_cb), this);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
2001-12-10 20:37:36 +03:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (mContainer) {
|
2012-10-23 02:39:59 +04:00
|
|
|
|
// Widget signals
|
2011-05-11 17:10:36 +04:00
|
|
|
|
g_signal_connect(mContainer, "unrealize",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(container_unrealize_cb), nullptr);
|
2011-05-11 17:10:36 +04:00
|
|
|
|
g_signal_connect_after(mContainer, "size_allocate",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(size_allocate_cb), nullptr);
|
2012-10-23 02:39:59 +04:00
|
|
|
|
g_signal_connect(mContainer, "hierarchy-changed",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(hierarchy_changed_cb), nullptr);
|
2012-10-23 02:39:59 +04:00
|
|
|
|
// Initialize mHasMappedToplevel.
|
2013-10-08 22:47:37 +04:00
|
|
|
|
hierarchy_changed_cb(GTK_WIDGET(mContainer), nullptr);
|
2012-10-23 02:39:59 +04:00
|
|
|
|
// Expose, focus, key, and drag events are sent even to GTK_NO_WINDOW
|
|
|
|
|
// widgets.
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2011-05-11 17:10:36 +04:00
|
|
|
|
g_signal_connect(mContainer, "expose_event",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(expose_event_cb), nullptr);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#else
|
|
|
|
|
g_signal_connect(G_OBJECT(mContainer), "draw",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(expose_event_cb), nullptr);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#endif
|
2011-05-11 17:10:36 +04:00
|
|
|
|
g_signal_connect(mContainer, "focus_in_event",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(focus_in_event_cb), nullptr);
|
2011-05-11 17:10:36 +04:00
|
|
|
|
g_signal_connect(mContainer, "focus_out_event",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(focus_out_event_cb), nullptr);
|
2011-05-11 17:10:36 +04:00
|
|
|
|
g_signal_connect(mContainer, "key_press_event",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(key_press_event_cb), nullptr);
|
2011-05-11 17:10:36 +04:00
|
|
|
|
g_signal_connect(mContainer, "key_release_event",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(key_release_event_cb), nullptr);
|
2004-10-11 08:01:49 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
gtk_drag_dest_set((GtkWidget *)mContainer,
|
|
|
|
|
(GtkDestDefaults)0,
|
2013-10-08 22:47:37 +04:00
|
|
|
|
nullptr,
|
2002-08-10 22:21:22 +04:00
|
|
|
|
0,
|
|
|
|
|
(GdkDragAction)0);
|
2002-04-27 20:26:10 +04:00
|
|
|
|
|
2011-05-11 17:10:36 +04:00
|
|
|
|
g_signal_connect(mContainer, "drag_motion",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(drag_motion_event_cb), nullptr);
|
2011-05-11 17:10:36 +04:00
|
|
|
|
g_signal_connect(mContainer, "drag_leave",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(drag_leave_event_cb), nullptr);
|
2011-05-11 17:10:36 +04:00
|
|
|
|
g_signal_connect(mContainer, "drag_drop",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(drag_drop_event_cb), nullptr);
|
2011-05-11 17:10:36 +04:00
|
|
|
|
g_signal_connect(mContainer, "drag_data_received",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(drag_data_received_event_cb), nullptr);
|
2003-04-09 07:34:53 +04:00
|
|
|
|
|
2015-10-12 10:56:00 +03:00
|
|
|
|
GtkWidget *widgets[] = { GTK_WIDGET(mContainer),
|
|
|
|
|
!shellHasCSD ? mShell : nullptr };
|
2012-10-23 02:39:59 +04:00
|
|
|
|
for (size_t i = 0; i < ArrayLength(widgets) && widgets[i]; ++i) {
|
|
|
|
|
// Visibility events are sent to the owning widget of the relevant
|
|
|
|
|
// window but do not propagate to parent widgets so connect on
|
|
|
|
|
// mShell (if it exists) as well as mContainer.
|
|
|
|
|
g_signal_connect(widgets[i], "visibility-notify-event",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(visibility_notify_event_cb), nullptr);
|
2012-10-23 02:39:59 +04:00
|
|
|
|
// Similarly double buffering is controlled by the window's owning
|
|
|
|
|
// widget. Disable double buffering for painting directly to the
|
|
|
|
|
// X Window.
|
|
|
|
|
gtk_widget_set_double_buffered(widgets[i], FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-09 07:34:53 +04:00
|
|
|
|
// We create input contexts for all containers, except for
|
|
|
|
|
// toplevel popup windows
|
2010-03-19 07:21:16 +03:00
|
|
|
|
if (mWindowType != eWindowType_popup) {
|
2015-07-27 02:23:04 +03:00
|
|
|
|
mIMContext = new IMContextWrapper(this);
|
2010-03-19 07:21:16 +03:00
|
|
|
|
}
|
2015-07-27 02:23:04 +03:00
|
|
|
|
} else if (!mIMContext) {
|
2010-03-19 07:21:16 +03:00
|
|
|
|
nsWindow *container = GetContainerWindow();
|
|
|
|
|
if (container) {
|
2015-07-27 02:23:04 +03:00
|
|
|
|
mIMContext = container->mIMContext;
|
2010-03-19 07:21:16 +03:00
|
|
|
|
}
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
2001-12-10 20:37:36 +03:00
|
|
|
|
|
2012-10-23 02:39:59 +04:00
|
|
|
|
if (eventWidget) {
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2012-10-23 02:39:59 +04:00
|
|
|
|
// Don't let GTK mess with the shapes of our GdkWindows
|
|
|
|
|
GTK_PRIVATE_SET_FLAG(eventWidget, GTK_HAS_SHAPE_MASK);
|
2013-06-04 16:23:29 +04:00
|
|
|
|
#endif
|
2012-10-23 02:39:59 +04:00
|
|
|
|
|
|
|
|
|
// These events are sent to the owning widget of the relevant window
|
|
|
|
|
// and propagate up to the first widget that handles the events, so we
|
|
|
|
|
// need only connect on mShell, if it exists, to catch events on its
|
|
|
|
|
// window and windows of mContainer.
|
|
|
|
|
g_signal_connect(eventWidget, "enter-notify-event",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(enter_notify_event_cb), nullptr);
|
2012-10-23 02:39:59 +04:00
|
|
|
|
g_signal_connect(eventWidget, "leave-notify-event",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(leave_notify_event_cb), nullptr);
|
2012-10-23 02:39:59 +04:00
|
|
|
|
g_signal_connect(eventWidget, "motion-notify-event",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(motion_notify_event_cb), nullptr);
|
2012-10-23 02:39:59 +04:00
|
|
|
|
g_signal_connect(eventWidget, "button-press-event",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(button_press_event_cb), nullptr);
|
2012-10-23 02:39:59 +04:00
|
|
|
|
g_signal_connect(eventWidget, "button-release-event",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(button_release_event_cb), nullptr);
|
2015-08-12 04:35:38 +03:00
|
|
|
|
g_signal_connect(eventWidget, "property-notify-event",
|
|
|
|
|
G_CALLBACK(property_notify_event_cb), nullptr);
|
2012-10-23 02:39:59 +04:00
|
|
|
|
g_signal_connect(eventWidget, "scroll-event",
|
2013-10-08 22:47:37 +04:00
|
|
|
|
G_CALLBACK(scroll_event_cb), nullptr);
|
2015-04-29 23:29:34 +03:00
|
|
|
|
#if GTK_CHECK_VERSION(3,4,0)
|
|
|
|
|
g_signal_connect(eventWidget, "touch-event",
|
|
|
|
|
G_CALLBACK(touch_event_cb), nullptr);
|
|
|
|
|
#endif
|
2012-10-23 02:39:59 +04:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
LOG(("nsWindow [%p]\n", (void *)this));
|
|
|
|
|
if (mShell) {
|
2012-10-23 02:40:24 +04:00
|
|
|
|
LOG(("\tmShell %p mContainer %p mGdkWindow %p 0x%lx\n",
|
|
|
|
|
mShell, mContainer, mGdkWindow,
|
|
|
|
|
gdk_x11_window_get_xid(mGdkWindow)));
|
|
|
|
|
} else if (mContainer) {
|
|
|
|
|
LOG(("\tmContainer %p mGdkWindow %p\n", mContainer, mGdkWindow));
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
2009-07-27 05:40:46 +04:00
|
|
|
|
else if (mGdkWindow) {
|
2012-10-23 02:40:24 +04:00
|
|
|
|
LOG(("\tmGdkWindow %p parent %p\n",
|
|
|
|
|
mGdkWindow, gdk_window_get_parent(mGdkWindow)));
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
2001-12-10 20:37:36 +03:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
// resize so that everything is set to the right dimensions
|
2007-06-05 23:57:38 +04:00
|
|
|
|
if (!mIsTopLevel)
|
2011-10-03 11:56:21 +04:00
|
|
|
|
Resize(mBounds.x, mBounds.y, mBounds.width, mBounds.height, false);
|
2001-12-10 20:37:36 +03:00
|
|
|
|
|
2015-08-26 01:42:40 +03:00
|
|
|
|
#ifdef MOZ_X11
|
|
|
|
|
if (mGdkWindow) {
|
2015-09-15 23:46:39 +03:00
|
|
|
|
mXDisplay = GDK_WINDOW_XDISPLAY(mGdkWindow);
|
|
|
|
|
mXWindow = gdk_x11_window_get_xid(mGdkWindow);
|
|
|
|
|
|
|
|
|
|
GdkVisual* gdkVisual = gdk_window_get_visual(mGdkWindow);
|
|
|
|
|
mXVisual = gdk_x11_visual_get_xvisual(gdkVisual);
|
|
|
|
|
mXDepth = gdk_visual_get_depth(gdkVisual);
|
2015-08-26 01:42:40 +03:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return NS_OK;
|
2001-12-10 20:37:36 +03:00
|
|
|
|
}
|
|
|
|
|
|
2006-04-10 02:45:04 +04:00
|
|
|
|
NS_IMETHODIMP
|
2006-07-19 16:56:40 +04:00
|
|
|
|
nsWindow::SetWindowClass(const nsAString &xulWinType)
|
2006-04-10 02:45:04 +04:00
|
|
|
|
{
|
|
|
|
|
if (!mShell)
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
2012-03-28 03:17:35 +04:00
|
|
|
|
const char *res_class = gdk_get_program_class();
|
|
|
|
|
if (!res_class)
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
|
|
char *res_name = ToNewCString(xulWinType);
|
|
|
|
|
if (!res_name)
|
2006-04-10 02:45:04 +04:00
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2012-03-28 03:17:35 +04:00
|
|
|
|
|
2013-10-08 22:47:37 +04:00
|
|
|
|
const char *role = nullptr;
|
2006-04-10 02:45:04 +04:00
|
|
|
|
|
|
|
|
|
// Parse res_name into a name and role. Characters other than
|
|
|
|
|
// [A-Za-z0-9_-] are converted to '_'. Anything after the first
|
|
|
|
|
// colon is assigned to role; if there's no colon, assign the
|
|
|
|
|
// whole thing to both role and res_name.
|
2012-03-28 03:17:35 +04:00
|
|
|
|
for (char *c = res_name; *c; c++) {
|
2006-04-10 02:45:04 +04:00
|
|
|
|
if (':' == *c) {
|
|
|
|
|
*c = 0;
|
|
|
|
|
role = c + 1;
|
|
|
|
|
}
|
|
|
|
|
else if (!isascii(*c) || (!isalnum(*c) && ('_' != *c) && ('-' != *c)))
|
|
|
|
|
*c = '_';
|
|
|
|
|
}
|
2012-03-28 03:17:35 +04:00
|
|
|
|
res_name[0] = toupper(res_name[0]);
|
|
|
|
|
if (!role) role = res_name;
|
2006-04-10 02:45:04 +04:00
|
|
|
|
|
2015-04-21 10:06:41 +03:00
|
|
|
|
gdk_window_set_role(mGdkWindow, role);
|
2012-03-28 03:17:35 +04:00
|
|
|
|
|
|
|
|
|
#ifdef MOZ_X11
|
2015-03-05 05:56:00 +03:00
|
|
|
|
GdkDisplay *display = gdk_display_get_default();
|
|
|
|
|
if (GDK_IS_X11_DISPLAY(display)) {
|
|
|
|
|
XClassHint *class_hint = XAllocClassHint();
|
|
|
|
|
if (!class_hint) {
|
2015-03-27 03:01:12 +03:00
|
|
|
|
free(res_name);
|
2015-03-05 05:56:00 +03:00
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
class_hint->res_name = res_name;
|
|
|
|
|
class_hint->res_class = const_cast<char*>(res_class);
|
|
|
|
|
|
|
|
|
|
// Can't use gtk_window_set_wmclass() for this; it prints
|
|
|
|
|
// a warning & refuses to make the change.
|
|
|
|
|
XSetClassHint(GDK_DISPLAY_XDISPLAY(display),
|
2015-04-21 10:06:41 +03:00
|
|
|
|
gdk_x11_window_get_xid(mGdkWindow),
|
2015-03-05 05:56:00 +03:00
|
|
|
|
class_hint);
|
|
|
|
|
XFree(class_hint);
|
2012-03-28 03:17:35 +04:00
|
|
|
|
}
|
|
|
|
|
#endif /* MOZ_X11 */
|
2008-08-07 00:48:55 +04:00
|
|
|
|
|
2015-03-27 03:01:12 +03:00
|
|
|
|
free(res_name);
|
2008-08-07 00:48:55 +04:00
|
|
|
|
|
2006-04-10 02:45:04 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
void
|
2015-07-14 06:24:56 +03:00
|
|
|
|
nsWindow::NativeResize()
|
2001-12-11 05:38:51 +03:00
|
|
|
|
{
|
2015-07-14 06:23:47 +03:00
|
|
|
|
if (!AreBoundsSane()) {
|
|
|
|
|
// If someone has set this so that the needs show flag is false
|
|
|
|
|
// and it needs to be hidden, update the flag and hide the
|
|
|
|
|
// window. This flag will be cleared the next time someone
|
|
|
|
|
// hides the window or shows it. It also prevents us from
|
|
|
|
|
// calling NativeShow(false) excessively on the window which
|
|
|
|
|
// causes unneeded X traffic.
|
|
|
|
|
if (!mNeedsShow && mIsShown) {
|
|
|
|
|
mNeedsShow = true;
|
|
|
|
|
NativeShow(false);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-14 06:24:56 +03:00
|
|
|
|
GdkRectangle size = DevicePixelsToGdkSizeRoundUp(mBounds.Size());
|
2015-01-21 07:53:00 +03:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
LOG(("nsWindow::NativeResize [%p] %d %d\n", (void *)this,
|
2015-07-14 06:24:56 +03:00
|
|
|
|
size.width, size.height));
|
2001-12-12 01:22:48 +03:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (mIsTopLevel) {
|
2015-07-14 06:24:56 +03:00
|
|
|
|
gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
|
|
|
|
else if (mContainer) {
|
2009-07-27 05:40:46 +04:00
|
|
|
|
GtkWidget *widget = GTK_WIDGET(mContainer);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
GtkAllocation allocation, prev_allocation;
|
|
|
|
|
gtk_widget_get_allocation(widget, &prev_allocation);
|
|
|
|
|
allocation.x = prev_allocation.x;
|
|
|
|
|
allocation.y = prev_allocation.y;
|
2015-07-14 06:24:56 +03:00
|
|
|
|
allocation.width = size.width;
|
|
|
|
|
allocation.height = size.height;
|
2009-07-27 05:40:46 +04:00
|
|
|
|
gtk_widget_size_allocate(widget, &allocation);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
2009-07-27 05:40:46 +04:00
|
|
|
|
else if (mGdkWindow) {
|
2015-07-14 06:24:56 +03:00
|
|
|
|
gdk_window_resize(mGdkWindow, size.width, size.height);
|
2009-03-31 14:03:43 +04:00
|
|
|
|
}
|
2015-07-14 06:23:47 +03:00
|
|
|
|
|
|
|
|
|
// Does it need to be shown because bounds were previously insane?
|
|
|
|
|
if (mNeedsShow && mIsShown) {
|
|
|
|
|
NativeShow(true);
|
|
|
|
|
}
|
2001-12-11 05:38:51 +03:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
void
|
2015-07-14 06:24:56 +03:00
|
|
|
|
nsWindow::NativeMoveResize()
|
2001-12-11 05:38:51 +03:00
|
|
|
|
{
|
2015-07-14 06:23:47 +03:00
|
|
|
|
if (!AreBoundsSane()) {
|
|
|
|
|
// If someone has set this so that the needs show flag is false
|
|
|
|
|
// and it needs to be hidden, update the flag and hide the
|
|
|
|
|
// window. This flag will be cleared the next time someone
|
|
|
|
|
// hides the window or shows it. It also prevents us from
|
|
|
|
|
// calling NativeShow(false) excessively on the window which
|
|
|
|
|
// causes unneeded X traffic.
|
|
|
|
|
if (!mNeedsShow && mIsShown) {
|
|
|
|
|
mNeedsShow = true;
|
|
|
|
|
NativeShow(false);
|
|
|
|
|
}
|
|
|
|
|
NativeMove();
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-14 06:24:56 +03:00
|
|
|
|
GdkRectangle size = DevicePixelsToGdkSizeRoundUp(mBounds.Size());
|
|
|
|
|
GdkPoint topLeft = DevicePixelsToGdkPointRoundDown(mBounds.TopLeft());
|
2015-01-21 07:53:00 +03:00
|
|
|
|
|
2015-07-14 06:24:56 +03:00
|
|
|
|
LOG(("nsWindow::NativeMoveResize [%p] %d %d %d %d\n", (void *)this,
|
|
|
|
|
topLeft.x, topLeft.y, size.width, size.height));
|
2001-12-11 05:38:51 +03:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (mIsTopLevel) {
|
2015-01-21 07:53:00 +03:00
|
|
|
|
// x and y give the position of the window manager frame top-left.
|
2015-07-14 06:24:56 +03:00
|
|
|
|
gtk_window_move(GTK_WINDOW(mShell), topLeft.x, topLeft.y);
|
2011-07-08 07:14:27 +04:00
|
|
|
|
// This sets the client window size.
|
2015-07-14 06:24:56 +03:00
|
|
|
|
gtk_window_resize(GTK_WINDOW(mShell), size.width, size.height);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
|
|
|
|
else if (mContainer) {
|
|
|
|
|
GtkAllocation allocation;
|
2015-07-14 06:24:56 +03:00
|
|
|
|
allocation.x = topLeft.x;
|
|
|
|
|
allocation.y = topLeft.y;
|
|
|
|
|
allocation.width = size.width;
|
|
|
|
|
allocation.height = size.height;
|
2002-08-10 22:21:22 +04:00
|
|
|
|
gtk_widget_size_allocate(GTK_WIDGET(mContainer), &allocation);
|
|
|
|
|
}
|
2009-07-27 05:39:36 +04:00
|
|
|
|
else if (mGdkWindow) {
|
2015-07-14 06:24:56 +03:00
|
|
|
|
gdk_window_move_resize(mGdkWindow,
|
|
|
|
|
topLeft.x, topLeft.y, size.width, size.height);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
2015-07-14 06:23:47 +03:00
|
|
|
|
|
|
|
|
|
// Does it need to be shown because bounds were previously insane?
|
|
|
|
|
if (mNeedsShow && mIsShown) {
|
|
|
|
|
NativeShow(true);
|
|
|
|
|
}
|
2001-12-11 05:38:51 +03:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
void
|
2012-10-03 02:36:08 +04:00
|
|
|
|
nsWindow::NativeShow(bool aAction)
|
2001-12-11 05:38:51 +03:00
|
|
|
|
{
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (aAction) {
|
|
|
|
|
// unset our flag now that our window has been shown
|
2011-10-03 11:56:21 +04:00
|
|
|
|
mNeedsShow = false;
|
2001-12-11 05:38:51 +03:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (mIsTopLevel) {
|
2007-02-09 04:33:26 +03:00
|
|
|
|
// Set up usertime/startupID metadata for the created window.
|
|
|
|
|
if (mWindowType != eWindowType_invisible) {
|
|
|
|
|
SetUserTimeAndStartupIDForActivatedWindow(mShell);
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
gtk_widget_show(mShell);
|
|
|
|
|
}
|
|
|
|
|
else if (mContainer) {
|
|
|
|
|
gtk_widget_show(GTK_WIDGET(mContainer));
|
|
|
|
|
}
|
2009-07-27 05:39:36 +04:00
|
|
|
|
else if (mGdkWindow) {
|
|
|
|
|
gdk_window_show_unraised(mGdkWindow);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (mIsTopLevel) {
|
|
|
|
|
gtk_widget_hide(GTK_WIDGET(mShell));
|
2012-10-03 02:37:06 +04:00
|
|
|
|
|
|
|
|
|
ClearTransparencyBitmap(); // Release some resources
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
|
|
|
|
else if (mContainer) {
|
|
|
|
|
gtk_widget_hide(GTK_WIDGET(mContainer));
|
|
|
|
|
}
|
2009-07-27 05:40:46 +04:00
|
|
|
|
else if (mGdkWindow) {
|
2009-07-27 05:39:36 +04:00
|
|
|
|
gdk_window_hide(mGdkWindow);
|
2003-02-14 18:11:42 +03:00
|
|
|
|
}
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
2001-12-11 05:38:51 +03:00
|
|
|
|
}
|
|
|
|
|
|
2009-11-02 05:03:12 +03:00
|
|
|
|
void
|
2011-09-29 10:19:26 +04:00
|
|
|
|
nsWindow::SetHasMappedToplevel(bool aState)
|
2009-11-02 05:03:12 +03:00
|
|
|
|
{
|
|
|
|
|
// Even when aState == mHasMappedToplevel (as when this method is called
|
|
|
|
|
// from Show()), child windows need to have their state checked, so don't
|
|
|
|
|
// return early.
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool oldState = mHasMappedToplevel;
|
2009-11-02 05:03:12 +03:00
|
|
|
|
mHasMappedToplevel = aState;
|
|
|
|
|
|
|
|
|
|
// mHasMappedToplevel is not updated for children of windows that are
|
|
|
|
|
// hidden; GDK knows not to send expose events for these windows. The
|
|
|
|
|
// state is recorded on the hidden window itself, but, for child trees of
|
|
|
|
|
// hidden windows, their state essentially becomes disconnected from their
|
|
|
|
|
// hidden parent. When the hidden parent gets shown, the child trees are
|
|
|
|
|
// reconnected, and the state of the window being shown can be easily
|
|
|
|
|
// propagated.
|
|
|
|
|
if (!mIsShown || !mGdkWindow)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (aState && !oldState && !mIsFullyObscured) {
|
|
|
|
|
// GDK_EXPOSE events have been ignored but the window is now visible,
|
|
|
|
|
// so make sure GDK doesn't think that the window has already been
|
|
|
|
|
// painted.
|
2013-10-08 22:47:37 +04:00
|
|
|
|
gdk_window_invalidate_rect(mGdkWindow, nullptr, FALSE);
|
2009-11-02 05:03:12 +03:00
|
|
|
|
|
|
|
|
|
// Check that a grab didn't fail due to the window not being
|
|
|
|
|
// viewable.
|
|
|
|
|
EnsureGrabs();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (GList *children = gdk_window_peek_children(mGdkWindow);
|
|
|
|
|
children;
|
|
|
|
|
children = children->next) {
|
|
|
|
|
GdkWindow *gdkWin = GDK_WINDOW(children->data);
|
|
|
|
|
nsWindow *child = get_window_for_gdk_window(gdkWin);
|
|
|
|
|
|
|
|
|
|
if (child && child->mHasMappedToplevel != aState) {
|
|
|
|
|
child->SetHasMappedToplevel(aState);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-30 18:35:25 +03:00
|
|
|
|
LayoutDeviceIntSize
|
|
|
|
|
nsWindow::GetSafeWindowSize(LayoutDeviceIntSize aSize)
|
2008-07-02 15:09:15 +04:00
|
|
|
|
{
|
2012-11-28 02:07:11 +04:00
|
|
|
|
// The X protocol uses CARD32 for window sizes, but the server (1.11.3)
|
|
|
|
|
// reads it as CARD16. Sizes of pixmaps, used for drawing, are (unsigned)
|
|
|
|
|
// CARD16 in the protocol, but the server's ProcCreatePixmap returns
|
|
|
|
|
// BadAlloc if dimensions cannot be represented by signed shorts.
|
2015-03-30 18:35:25 +03:00
|
|
|
|
LayoutDeviceIntSize result = aSize;
|
2012-08-22 19:56:38 +04:00
|
|
|
|
const int32_t kInt16Max = 32767;
|
2008-09-03 19:39:08 +04:00
|
|
|
|
if (result.width > kInt16Max) {
|
|
|
|
|
result.width = kInt16Max;
|
2008-07-02 15:09:15 +04:00
|
|
|
|
}
|
2008-09-03 19:39:08 +04:00
|
|
|
|
if (result.height > kInt16Max) {
|
|
|
|
|
result.height = kInt16Max;
|
2008-07-02 15:09:15 +04:00
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
void
|
|
|
|
|
nsWindow::EnsureGrabs(void)
|
2001-12-11 05:38:51 +03:00
|
|
|
|
{
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (mRetryPointerGrab)
|
2012-02-02 06:12:26 +04:00
|
|
|
|
GrabPointer(sRetryGrabTime);
|
2001-12-11 05:38:51 +03:00
|
|
|
|
}
|
|
|
|
|
|
2012-09-24 03:22:28 +04:00
|
|
|
|
void
|
|
|
|
|
nsWindow::CleanLayerManagerRecursive(void) {
|
|
|
|
|
if (mLayerManager) {
|
|
|
|
|
mLayerManager->Destroy();
|
|
|
|
|
mLayerManager = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DestroyCompositor();
|
|
|
|
|
|
|
|
|
|
GList* children = gdk_window_peek_children(mGdkWindow);
|
|
|
|
|
for (GList* list = children; list; list = list->next) {
|
|
|
|
|
nsWindow* window = get_window_for_gdk_window(GDK_WINDOW(list->data));
|
|
|
|
|
if (window) {
|
|
|
|
|
window->CleanLayerManagerRecursive();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-13 04:44:14 +04:00
|
|
|
|
void
|
|
|
|
|
nsWindow::SetTransparencyMode(nsTransparencyMode aMode)
|
2004-07-24 16:42:32 +04:00
|
|
|
|
{
|
|
|
|
|
if (!mShell) {
|
|
|
|
|
// Pass the request to the toplevel window
|
2012-11-07 01:50:37 +04:00
|
|
|
|
GtkWidget *topWidget = GetToplevelWidget();
|
2004-07-27 23:16:44 +04:00
|
|
|
|
if (!topWidget)
|
2008-08-13 04:44:14 +04:00
|
|
|
|
return;
|
2004-07-27 23:16:44 +04:00
|
|
|
|
|
2004-07-24 16:42:32 +04:00
|
|
|
|
nsWindow *topWindow = get_window_for_gtk_widget(topWidget);
|
2004-07-27 23:16:44 +04:00
|
|
|
|
if (!topWindow)
|
2008-08-13 04:44:14 +04:00
|
|
|
|
return;
|
2004-07-27 23:16:44 +04:00
|
|
|
|
|
2008-08-13 04:44:14 +04:00
|
|
|
|
topWindow->SetTransparencyMode(aMode);
|
|
|
|
|
return;
|
2004-07-24 16:42:32 +04:00
|
|
|
|
}
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool isTransparent = aMode == eTransparencyTransparent;
|
2004-07-24 16:42:32 +04:00
|
|
|
|
|
2008-08-13 04:44:14 +04:00
|
|
|
|
if (mIsTransparent == isTransparent)
|
|
|
|
|
return;
|
2004-07-24 16:42:32 +04:00
|
|
|
|
|
2008-08-13 04:44:14 +04:00
|
|
|
|
if (!isTransparent) {
|
2012-10-03 02:37:06 +04:00
|
|
|
|
ClearTransparencyBitmap();
|
2004-07-24 16:42:32 +04:00
|
|
|
|
} // else the new default alpha values are "all 1", so we don't
|
|
|
|
|
// need to change anything yet
|
|
|
|
|
|
2008-08-13 04:44:14 +04:00
|
|
|
|
mIsTransparent = isTransparent;
|
2012-09-24 03:22:28 +04:00
|
|
|
|
|
|
|
|
|
// Need to clean our LayerManager up while still alive because
|
|
|
|
|
// we don't want to use layers acceleration on shaped windows
|
|
|
|
|
CleanLayerManagerRecursive();
|
2004-07-24 16:42:32 +04:00
|
|
|
|
}
|
|
|
|
|
|
2008-08-13 04:44:14 +04:00
|
|
|
|
nsTransparencyMode
|
|
|
|
|
nsWindow::GetTransparencyMode()
|
2004-07-24 16:42:32 +04:00
|
|
|
|
{
|
|
|
|
|
if (!mShell) {
|
|
|
|
|
// Pass the request to the toplevel window
|
2012-11-07 01:50:37 +04:00
|
|
|
|
GtkWidget *topWidget = GetToplevelWidget();
|
2004-07-27 23:16:44 +04:00
|
|
|
|
if (!topWidget) {
|
2008-08-13 04:44:14 +04:00
|
|
|
|
return eTransparencyOpaque;
|
2004-07-27 23:16:44 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-07-24 16:42:32 +04:00
|
|
|
|
nsWindow *topWindow = get_window_for_gtk_widget(topWidget);
|
2004-07-27 23:16:44 +04:00
|
|
|
|
if (!topWindow) {
|
2008-08-13 04:44:14 +04:00
|
|
|
|
return eTransparencyOpaque;
|
2004-07-27 23:16:44 +04:00
|
|
|
|
}
|
|
|
|
|
|
2008-08-13 04:44:14 +04:00
|
|
|
|
return topWindow->GetTransparencyMode();
|
2004-07-24 16:42:32 +04:00
|
|
|
|
}
|
|
|
|
|
|
2008-08-13 04:44:14 +04:00
|
|
|
|
return mIsTransparent ? eTransparencyTransparent : eTransparencyOpaque;
|
2004-07-24 16:42:32 +04:00
|
|
|
|
}
|
|
|
|
|
|
2009-07-22 04:44:55 +04:00
|
|
|
|
nsresult
|
|
|
|
|
nsWindow::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
|
|
|
|
|
{
|
2014-11-12 23:59:19 +03:00
|
|
|
|
// If this is a remotely updated widget we receive clipping, position, and
|
|
|
|
|
// size information from a source other than our owner. Don't let our parent
|
|
|
|
|
// update this information.
|
|
|
|
|
if (mWindowType == eWindowType_plugin_ipc_chrome) {
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
|
for (uint32_t i = 0; i < aConfigurations.Length(); ++i) {
|
2009-07-22 04:44:55 +04:00
|
|
|
|
const Configuration& configuration = aConfigurations[i];
|
2015-05-25 21:45:00 +03:00
|
|
|
|
nsWindow* w = static_cast<nsWindow*>(configuration.mChild.get());
|
2009-07-22 04:44:55 +04:00
|
|
|
|
NS_ASSERTION(w->GetParent() == this,
|
|
|
|
|
"Configured widget is not a child");
|
2015-11-11 03:27:26 +03:00
|
|
|
|
LayoutDeviceIntRect wBounds =
|
|
|
|
|
LayoutDeviceIntRect::FromUnknownRect(w->mBounds);
|
2011-10-03 11:56:21 +04:00
|
|
|
|
w->SetWindowClipRegion(configuration.mClipRegion, true);
|
2015-11-11 03:27:26 +03:00
|
|
|
|
if (wBounds.Size() != configuration.mBounds.Size()) {
|
2009-07-22 04:44:55 +04:00
|
|
|
|
w->Resize(configuration.mBounds.x, configuration.mBounds.y,
|
|
|
|
|
configuration.mBounds.width, configuration.mBounds.height,
|
2011-10-03 11:56:21 +04:00
|
|
|
|
true);
|
2015-11-11 03:27:26 +03:00
|
|
|
|
} else if (wBounds.TopLeft() != configuration.mBounds.TopLeft()) {
|
2009-07-22 04:44:55 +04:00
|
|
|
|
w->Move(configuration.mBounds.x, configuration.mBounds.y);
|
2015-11-11 03:27:26 +03:00
|
|
|
|
}
|
2011-10-03 11:56:21 +04:00
|
|
|
|
w->SetWindowClipRegion(configuration.mClipRegion, false);
|
2009-07-22 04:44:55 +04:00
|
|
|
|
}
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-12 23:59:19 +03:00
|
|
|
|
nsresult
|
2009-12-14 00:01:33 +03:00
|
|
|
|
nsWindow::SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool aIntersectWithExisting)
|
2009-07-22 04:44:55 +04:00
|
|
|
|
{
|
2009-12-14 00:01:33 +03:00
|
|
|
|
const nsTArray<nsIntRect>* newRects = &aRects;
|
|
|
|
|
|
|
|
|
|
nsAutoTArray<nsIntRect,1> intersectRects;
|
|
|
|
|
if (aIntersectWithExisting) {
|
|
|
|
|
nsAutoTArray<nsIntRect,1> existingRects;
|
|
|
|
|
GetWindowClipRegion(&existingRects);
|
|
|
|
|
|
2015-05-01 15:57:24 +03:00
|
|
|
|
nsIntRegion existingRegion = RegionFromArray(existingRects);
|
|
|
|
|
nsIntRegion newRegion = RegionFromArray(aRects);
|
|
|
|
|
nsIntRegion intersectRegion;
|
|
|
|
|
intersectRegion.And(newRegion, existingRegion);
|
2009-12-14 00:01:33 +03:00
|
|
|
|
|
2010-12-10 07:33:33 +03:00
|
|
|
|
// If mClipRects is null we haven't set a clip rect yet, so we
|
|
|
|
|
// need to set the clip even if it is equal.
|
2015-05-01 15:57:24 +03:00
|
|
|
|
if (mClipRects && intersectRegion.IsEqual(existingRegion)) {
|
2014-11-12 23:59:19 +03:00
|
|
|
|
return NS_OK;
|
2010-12-10 07:33:33 +03:00
|
|
|
|
}
|
2009-12-14 00:01:33 +03:00
|
|
|
|
|
2015-05-01 15:57:24 +03:00
|
|
|
|
if (!intersectRegion.IsEqual(newRegion)) {
|
|
|
|
|
ArrayFromRegion(intersectRegion, intersectRects);
|
2009-12-14 00:01:33 +03:00
|
|
|
|
newRects = &intersectRects;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-28 18:15:54 +03:00
|
|
|
|
if (IsWindowClipRegionEqual(*newRects))
|
2014-11-12 23:59:19 +03:00
|
|
|
|
return NS_OK;
|
2009-07-22 04:44:55 +04:00
|
|
|
|
|
2015-01-28 18:15:54 +03:00
|
|
|
|
StoreWindowClipRegion(*newRects);
|
|
|
|
|
|
2009-07-27 05:39:36 +04:00
|
|
|
|
if (!mGdkWindow)
|
2014-11-12 23:59:19 +03:00
|
|
|
|
return NS_OK;
|
2009-07-22 04:44:55 +04:00
|
|
|
|
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2009-12-14 00:01:33 +03:00
|
|
|
|
GdkRegion *region = gdk_region_new(); // aborts on OOM
|
2012-08-22 19:56:38 +04:00
|
|
|
|
for (uint32_t i = 0; i < newRects->Length(); ++i) {
|
2009-12-14 00:01:33 +03:00
|
|
|
|
const nsIntRect& r = newRects->ElementAt(i);
|
2009-07-22 04:44:55 +04:00
|
|
|
|
GdkRectangle rect = { r.x, r.y, r.width, r.height };
|
|
|
|
|
gdk_region_union_with_rect(region, &rect);
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-27 05:39:36 +04:00
|
|
|
|
gdk_window_shape_combine_region(mGdkWindow, region, 0, 0);
|
2009-07-22 04:44:55 +04:00
|
|
|
|
gdk_region_destroy(region);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#else
|
|
|
|
|
cairo_region_t *region = cairo_region_create();
|
2012-08-22 19:56:38 +04:00
|
|
|
|
for (uint32_t i = 0; i < newRects->Length(); ++i) {
|
2011-09-23 00:58:07 +04:00
|
|
|
|
const nsIntRect& r = newRects->ElementAt(i);
|
|
|
|
|
cairo_rectangle_int_t rect = { r.x, r.y, r.width, r.height };
|
|
|
|
|
cairo_region_union_rectangle(region, &rect);
|
|
|
|
|
}
|
2009-07-22 04:44:55 +04:00
|
|
|
|
|
2011-09-23 00:58:07 +04:00
|
|
|
|
gdk_window_shape_combine_region(mGdkWindow, region, 0, 0);
|
|
|
|
|
cairo_region_destroy(region);
|
|
|
|
|
#endif
|
2014-11-12 23:59:19 +03:00
|
|
|
|
|
|
|
|
|
return NS_OK;
|
2009-07-22 04:44:55 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-07-24 16:42:32 +04:00
|
|
|
|
void
|
2012-09-24 03:15:48 +04:00
|
|
|
|
nsWindow::ResizeTransparencyBitmap()
|
2004-07-24 16:42:32 +04:00
|
|
|
|
{
|
|
|
|
|
if (!mTransparencyBitmap)
|
|
|
|
|
return;
|
|
|
|
|
|
2012-09-24 03:15:48 +04:00
|
|
|
|
if (mBounds.width == mTransparencyBitmapWidth &&
|
|
|
|
|
mBounds.height == mTransparencyBitmapHeight)
|
2005-03-31 06:22:01 +04:00
|
|
|
|
return;
|
|
|
|
|
|
2012-09-24 03:15:48 +04:00
|
|
|
|
int32_t newRowBytes = GetBitmapStride(mBounds.width);
|
|
|
|
|
int32_t newSize = newRowBytes * mBounds.height;
|
2004-07-24 16:42:32 +04:00
|
|
|
|
gchar* newBits = new gchar[newSize];
|
2012-09-24 03:15:48 +04:00
|
|
|
|
// fill new mask with "transparent", first
|
|
|
|
|
memset(newBits, 0, newSize);
|
2004-07-24 16:42:32 +04:00
|
|
|
|
|
|
|
|
|
// Now copy the intersection of the old and new areas into the new mask
|
2013-01-15 16:22:03 +04:00
|
|
|
|
int32_t copyWidth = std::min(mBounds.width, mTransparencyBitmapWidth);
|
|
|
|
|
int32_t copyHeight = std::min(mBounds.height, mTransparencyBitmapHeight);
|
2012-08-22 19:56:38 +04:00
|
|
|
|
int32_t oldRowBytes = GetBitmapStride(mTransparencyBitmapWidth);
|
|
|
|
|
int32_t copyBytes = GetBitmapStride(copyWidth);
|
2004-07-24 16:42:32 +04:00
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
|
int32_t i;
|
2004-07-24 16:42:32 +04:00
|
|
|
|
gchar* fromPtr = mTransparencyBitmap;
|
|
|
|
|
gchar* toPtr = newBits;
|
|
|
|
|
for (i = 0; i < copyHeight; i++) {
|
|
|
|
|
memcpy(toPtr, fromPtr, copyBytes);
|
|
|
|
|
fromPtr += oldRowBytes;
|
|
|
|
|
toPtr += newRowBytes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete[] mTransparencyBitmap;
|
|
|
|
|
mTransparencyBitmap = newBits;
|
2012-09-24 03:15:48 +04:00
|
|
|
|
mTransparencyBitmapWidth = mBounds.width;
|
|
|
|
|
mTransparencyBitmapHeight = mBounds.height;
|
2004-07-24 16:42:32 +04:00
|
|
|
|
}
|
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
|
static bool
|
2012-08-22 19:56:38 +04:00
|
|
|
|
ChangedMaskBits(gchar* aMaskBits, int32_t aMaskWidth, int32_t aMaskHeight,
|
|
|
|
|
const nsIntRect& aRect, uint8_t* aAlphas, int32_t aStride)
|
2004-07-24 16:42:32 +04:00
|
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
|
int32_t x, y, xMax = aRect.XMost(), yMax = aRect.YMost();
|
|
|
|
|
int32_t maskBytesPerRow = GetBitmapStride(aMaskWidth);
|
2004-07-24 16:42:32 +04:00
|
|
|
|
for (y = aRect.y; y < yMax; y++) {
|
|
|
|
|
gchar* maskBytes = aMaskBits + y*maskBytesPerRow;
|
2012-08-22 19:56:38 +04:00
|
|
|
|
uint8_t* alphas = aAlphas;
|
2004-07-24 16:42:32 +04:00
|
|
|
|
for (x = aRect.x; x < xMax; x++) {
|
2012-10-03 02:35:28 +04:00
|
|
|
|
bool newBit = *alphas > 0x7f;
|
2006-02-21 01:43:44 +03:00
|
|
|
|
alphas++;
|
2004-07-24 16:42:32 +04:00
|
|
|
|
|
|
|
|
|
gchar maskByte = maskBytes[x >> 3];
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool maskBit = (maskByte & (1 << (x & 7))) != 0;
|
2004-07-24 16:42:32 +04:00
|
|
|
|
|
|
|
|
|
if (maskBit != newBit) {
|
2011-10-03 11:56:21 +04:00
|
|
|
|
return true;
|
2004-07-24 16:42:32 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
2006-02-21 01:43:44 +03:00
|
|
|
|
aAlphas += aStride;
|
2004-07-24 16:42:32 +04:00
|
|
|
|
}
|
|
|
|
|
|
2011-10-03 11:56:21 +04:00
|
|
|
|
return false;
|
2004-07-24 16:42:32 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static
|
2012-08-22 19:56:38 +04:00
|
|
|
|
void UpdateMaskBits(gchar* aMaskBits, int32_t aMaskWidth, int32_t aMaskHeight,
|
|
|
|
|
const nsIntRect& aRect, uint8_t* aAlphas, int32_t aStride)
|
2004-07-24 16:42:32 +04:00
|
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
|
int32_t x, y, xMax = aRect.XMost(), yMax = aRect.YMost();
|
|
|
|
|
int32_t maskBytesPerRow = GetBitmapStride(aMaskWidth);
|
2004-07-24 16:42:32 +04:00
|
|
|
|
for (y = aRect.y; y < yMax; y++) {
|
|
|
|
|
gchar* maskBytes = aMaskBits + y*maskBytesPerRow;
|
2012-08-22 19:56:38 +04:00
|
|
|
|
uint8_t* alphas = aAlphas;
|
2004-07-24 16:42:32 +04:00
|
|
|
|
for (x = aRect.x; x < xMax; x++) {
|
2012-10-03 02:35:28 +04:00
|
|
|
|
bool newBit = *alphas > 0x7f;
|
2006-02-21 01:43:44 +03:00
|
|
|
|
alphas++;
|
2004-07-24 16:42:32 +04:00
|
|
|
|
|
|
|
|
|
gchar mask = 1 << (x & 7);
|
|
|
|
|
gchar maskByte = maskBytes[x >> 3];
|
|
|
|
|
// Note: '-newBit' turns 0 into 00...00 and 1 into 11...11
|
|
|
|
|
maskBytes[x >> 3] = (maskByte & ~mask) | (-newBit & mask);
|
|
|
|
|
}
|
2006-02-21 01:43:44 +03:00
|
|
|
|
aAlphas += aStride;
|
2004-07-24 16:42:32 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nsWindow::ApplyTransparencyBitmap()
|
|
|
|
|
{
|
2011-05-11 08:54:12 +04:00
|
|
|
|
#ifdef MOZ_X11
|
|
|
|
|
// We use X11 calls where possible, because GDK handles expose events
|
|
|
|
|
// for shaped windows in a way that's incompatible with us (Bug 635903).
|
|
|
|
|
// It doesn't occur when the shapes are set through X.
|
2015-04-21 10:06:41 +03:00
|
|
|
|
Display* xDisplay = GDK_WINDOW_XDISPLAY(mGdkWindow);
|
|
|
|
|
Window xDrawable = GDK_WINDOW_XID(mGdkWindow);
|
2011-05-11 08:54:12 +04:00
|
|
|
|
Pixmap maskPixmap = XCreateBitmapFromData(xDisplay,
|
|
|
|
|
xDrawable,
|
|
|
|
|
mTransparencyBitmap,
|
|
|
|
|
mTransparencyBitmapWidth,
|
|
|
|
|
mTransparencyBitmapHeight);
|
|
|
|
|
XShapeCombineMask(xDisplay, xDrawable,
|
|
|
|
|
ShapeBounding, 0, 0,
|
|
|
|
|
maskPixmap, ShapeSet);
|
|
|
|
|
XFreePixmap(xDisplay, maskPixmap);
|
|
|
|
|
#else
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2004-07-24 16:42:32 +04:00
|
|
|
|
gtk_widget_reset_shapes(mShell);
|
2015-04-21 10:06:41 +03:00
|
|
|
|
GdkBitmap* maskBitmap = gdk_bitmap_create_from_data(mGdkWindow,
|
2004-07-24 16:42:32 +04:00
|
|
|
|
mTransparencyBitmap,
|
2006-10-16 16:13:54 +04:00
|
|
|
|
mTransparencyBitmapWidth, mTransparencyBitmapHeight);
|
2004-07-24 16:42:32 +04:00
|
|
|
|
if (!maskBitmap)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
gtk_widget_shape_combine_mask(mShell, maskBitmap, 0, 0);
|
2009-02-02 20:49:58 +03:00
|
|
|
|
g_object_unref(maskBitmap);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#else
|
|
|
|
|
cairo_surface_t *maskBitmap;
|
|
|
|
|
maskBitmap = cairo_image_surface_create_for_data((unsigned char*)mTransparencyBitmap,
|
|
|
|
|
CAIRO_FORMAT_A1,
|
|
|
|
|
mTransparencyBitmapWidth,
|
|
|
|
|
mTransparencyBitmapHeight,
|
|
|
|
|
GetBitmapStride(mTransparencyBitmapWidth));
|
|
|
|
|
if (!maskBitmap)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
cairo_region_t * maskRegion = gdk_cairo_region_create_from_surface(maskBitmap);
|
|
|
|
|
gtk_widget_shape_combine_region(mShell, maskRegion);
|
|
|
|
|
cairo_region_destroy(maskRegion);
|
|
|
|
|
cairo_surface_destroy(maskBitmap);
|
|
|
|
|
#endif // MOZ_WIDGET_GTK2
|
|
|
|
|
#endif // MOZ_X11
|
2004-07-24 16:42:32 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-10-03 02:37:06 +04:00
|
|
|
|
void
|
|
|
|
|
nsWindow::ClearTransparencyBitmap()
|
|
|
|
|
{
|
|
|
|
|
if (!mTransparencyBitmap)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
delete[] mTransparencyBitmap;
|
|
|
|
|
mTransparencyBitmap = nullptr;
|
|
|
|
|
mTransparencyBitmapWidth = 0;
|
|
|
|
|
mTransparencyBitmapHeight = 0;
|
|
|
|
|
|
|
|
|
|
if (!mShell)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
#ifdef MOZ_X11
|
2015-04-21 10:06:41 +03:00
|
|
|
|
if (!mGdkWindow)
|
2012-10-03 02:37:06 +04:00
|
|
|
|
return;
|
|
|
|
|
|
2015-04-21 10:06:41 +03:00
|
|
|
|
Display* xDisplay = GDK_WINDOW_XDISPLAY(mGdkWindow);
|
|
|
|
|
Window xWindow = gdk_x11_window_get_xid(mGdkWindow);
|
2012-10-03 02:37:06 +04:00
|
|
|
|
|
|
|
|
|
XShapeCombineMask(xDisplay, xWindow, ShapeBounding, 0, 0, None, ShapeSet);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2006-02-21 01:43:44 +03:00
|
|
|
|
nsresult
|
2009-01-15 06:27:09 +03:00
|
|
|
|
nsWindow::UpdateTranslucentWindowAlphaInternal(const nsIntRect& aRect,
|
2012-08-22 19:56:38 +04:00
|
|
|
|
uint8_t* aAlphas, int32_t aStride)
|
2004-07-24 16:42:32 +04:00
|
|
|
|
{
|
|
|
|
|
if (!mShell) {
|
|
|
|
|
// Pass the request to the toplevel window
|
2012-11-07 01:50:37 +04:00
|
|
|
|
GtkWidget *topWidget = GetToplevelWidget();
|
2004-07-27 23:16:44 +04:00
|
|
|
|
if (!topWidget)
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
2004-07-24 16:42:32 +04:00
|
|
|
|
nsWindow *topWindow = get_window_for_gtk_widget(topWidget);
|
2004-07-27 23:16:44 +04:00
|
|
|
|
if (!topWindow)
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
2006-02-21 01:43:44 +03:00
|
|
|
|
return topWindow->UpdateTranslucentWindowAlphaInternal(aRect, aAlphas, aStride);
|
2004-07-24 16:42:32 +04:00
|
|
|
|
}
|
|
|
|
|
|
2007-12-19 22:40:18 +03:00
|
|
|
|
NS_ASSERTION(mIsTransparent, "Window is not transparent");
|
2004-07-24 16:42:32 +04:00
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
|
if (mTransparencyBitmap == nullptr) {
|
2012-08-22 19:56:38 +04:00
|
|
|
|
int32_t size = GetBitmapStride(mBounds.width)*mBounds.height;
|
2004-07-24 16:42:32 +04:00
|
|
|
|
mTransparencyBitmap = new gchar[size];
|
|
|
|
|
memset(mTransparencyBitmap, 255, size);
|
2006-10-16 16:13:54 +04:00
|
|
|
|
mTransparencyBitmapWidth = mBounds.width;
|
|
|
|
|
mTransparencyBitmapHeight = mBounds.height;
|
2012-09-24 03:15:48 +04:00
|
|
|
|
} else {
|
|
|
|
|
ResizeTransparencyBitmap();
|
2004-07-24 16:42:32 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-09-24 03:17:31 +04:00
|
|
|
|
nsIntRect rect;
|
|
|
|
|
rect.IntersectRect(aRect, nsIntRect(0, 0, mBounds.width, mBounds.height));
|
2004-07-24 16:42:32 +04:00
|
|
|
|
|
2006-02-21 01:43:44 +03:00
|
|
|
|
if (!ChangedMaskBits(mTransparencyBitmap, mBounds.width, mBounds.height,
|
2012-09-24 03:17:31 +04:00
|
|
|
|
rect, aAlphas, aStride))
|
2004-07-24 16:42:32 +04:00
|
|
|
|
// skip the expensive stuff if the mask bits haven't changed; hopefully
|
|
|
|
|
// this is the common case
|
|
|
|
|
return NS_OK;
|
|
|
|
|
|
2006-02-21 01:43:44 +03:00
|
|
|
|
UpdateMaskBits(mTransparencyBitmap, mBounds.width, mBounds.height,
|
2012-09-24 03:17:31 +04:00
|
|
|
|
rect, aAlphas, aStride);
|
2004-07-24 16:42:32 +04:00
|
|
|
|
|
|
|
|
|
if (!mNeedsShow) {
|
|
|
|
|
ApplyTransparencyBitmap();
|
|
|
|
|
}
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
2006-02-21 01:43:44 +03:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
void
|
2012-02-02 06:12:26 +04:00
|
|
|
|
nsWindow::GrabPointer(guint32 aTime)
|
2001-12-12 01:22:48 +03:00
|
|
|
|
{
|
2012-02-08 00:51:15 +04:00
|
|
|
|
LOG(("GrabPointer time=0x%08x retry=%d\n",
|
|
|
|
|
(unsigned int)aTime, mRetryPointerGrab));
|
2001-12-12 01:22:48 +03:00
|
|
|
|
|
2011-10-03 11:56:21 +04:00
|
|
|
|
mRetryPointerGrab = false;
|
2012-02-08 00:51:15 +04:00
|
|
|
|
sRetryGrabTime = aTime;
|
2001-12-12 01:22:48 +03:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
// If the window isn't visible, just set the flag to retry the
|
|
|
|
|
// grab. When this window becomes visible, the grab will be
|
|
|
|
|
// retried.
|
2009-11-02 05:03:12 +03:00
|
|
|
|
if (!mHasMappedToplevel || mIsFullyObscured) {
|
2002-08-10 22:21:22 +04:00
|
|
|
|
LOG(("GrabPointer: window not visible\n"));
|
2011-10-03 11:56:21 +04:00
|
|
|
|
mRetryPointerGrab = true;
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return;
|
|
|
|
|
}
|
2001-12-12 01:22:48 +03:00
|
|
|
|
|
2009-07-27 05:39:36 +04:00
|
|
|
|
if (!mGdkWindow)
|
2003-02-14 18:11:42 +03:00
|
|
|
|
return;
|
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
gint retval;
|
2009-07-27 05:39:36 +04:00
|
|
|
|
retval = gdk_pointer_grab(mGdkWindow, TRUE,
|
2002-08-10 22:21:22 +04:00
|
|
|
|
(GdkEventMask)(GDK_BUTTON_PRESS_MASK |
|
|
|
|
|
GDK_BUTTON_RELEASE_MASK |
|
|
|
|
|
GDK_ENTER_NOTIFY_MASK |
|
|
|
|
|
GDK_LEAVE_NOTIFY_MASK |
|
|
|
|
|
GDK_POINTER_MOTION_MASK),
|
2013-10-08 22:47:37 +04:00
|
|
|
|
(GdkWindow *)nullptr, nullptr, aTime);
|
2001-12-12 01:22:48 +03:00
|
|
|
|
|
2012-02-02 06:11:44 +04:00
|
|
|
|
if (retval == GDK_GRAB_NOT_VIEWABLE) {
|
|
|
|
|
LOG(("GrabPointer: window not viewable; will retry\n"));
|
2011-10-03 11:56:21 +04:00
|
|
|
|
mRetryPointerGrab = true;
|
2012-02-02 06:11:44 +04:00
|
|
|
|
} else if (retval != GDK_GRAB_SUCCESS) {
|
|
|
|
|
LOG(("GrabPointer: pointer grab failed: %i\n", retval));
|
|
|
|
|
// A failed grab indicates that another app has grabbed the pointer.
|
|
|
|
|
// Check for rollup now, because, without the grab, we likely won't
|
|
|
|
|
// get subsequent button press events.
|
2012-10-26 17:15:22 +04:00
|
|
|
|
CheckForRollup(0, 0, false, true);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
2001-12-12 01:22:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
void
|
|
|
|
|
nsWindow::ReleaseGrabs(void)
|
2001-12-13 02:56:21 +03:00
|
|
|
|
{
|
2002-08-10 22:21:22 +04:00
|
|
|
|
LOG(("ReleaseGrabs\n"));
|
2001-12-13 02:56:21 +03:00
|
|
|
|
|
2011-10-03 11:56:21 +04:00
|
|
|
|
mRetryPointerGrab = false;
|
2002-08-10 22:21:22 +04:00
|
|
|
|
gdk_pointer_ungrab(GDK_CURRENT_TIME);
|
2001-12-13 02:56:21 +03:00
|
|
|
|
}
|
|
|
|
|
|
2012-11-07 01:50:37 +04:00
|
|
|
|
GtkWidget *
|
|
|
|
|
nsWindow::GetToplevelWidget()
|
2002-01-23 09:39:48 +03:00
|
|
|
|
{
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (mShell) {
|
2012-11-07 01:50:37 +04:00
|
|
|
|
return mShell;
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
2002-01-23 09:39:48 +03:00
|
|
|
|
|
2008-08-28 06:04:06 +04:00
|
|
|
|
GtkWidget *widget = GetMozContainerWidget();
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (!widget)
|
2012-11-07 01:50:37 +04:00
|
|
|
|
return nullptr;
|
2002-08-10 22:21:22 +04:00
|
|
|
|
|
2012-11-07 01:50:37 +04:00
|
|
|
|
return gtk_widget_get_toplevel(widget);
|
2002-01-23 09:39:48 +03:00
|
|
|
|
}
|
|
|
|
|
|
2008-08-28 06:04:06 +04:00
|
|
|
|
GtkWidget *
|
|
|
|
|
nsWindow::GetMozContainerWidget()
|
|
|
|
|
{
|
2009-07-27 05:39:36 +04:00
|
|
|
|
if (!mGdkWindow)
|
2013-10-08 22:47:37 +04:00
|
|
|
|
return nullptr;
|
2009-02-20 05:07:08 +03:00
|
|
|
|
|
2012-10-23 02:39:59 +04:00
|
|
|
|
if (mContainer)
|
|
|
|
|
return GTK_WIDGET(mContainer);
|
|
|
|
|
|
2008-08-28 06:04:06 +04:00
|
|
|
|
GtkWidget *owningWidget =
|
2009-07-27 05:39:36 +04:00
|
|
|
|
get_gtk_widget_for_gdk_window(mGdkWindow);
|
2008-08-28 06:04:06 +04:00
|
|
|
|
return owningWidget;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-20 05:07:08 +03:00
|
|
|
|
nsWindow *
|
|
|
|
|
nsWindow::GetContainerWindow()
|
2002-11-06 06:29:02 +03:00
|
|
|
|
{
|
2008-08-28 06:04:06 +04:00
|
|
|
|
GtkWidget *owningWidget = GetMozContainerWidget();
|
2009-02-20 05:07:08 +03:00
|
|
|
|
if (!owningWidget)
|
2012-07-30 18:20:58 +04:00
|
|
|
|
return nullptr;
|
2002-11-06 06:29:02 +03:00
|
|
|
|
|
2009-02-20 05:07:08 +03:00
|
|
|
|
nsWindow *window = get_window_for_gtk_widget(owningWidget);
|
|
|
|
|
NS_ASSERTION(window, "No nsWindow for container widget");
|
|
|
|
|
return window;
|
2002-11-06 06:29:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
2006-12-20 12:05:19 +03:00
|
|
|
|
void
|
2011-09-29 10:19:26 +04:00
|
|
|
|
nsWindow::SetUrgencyHint(GtkWidget *top_window, bool state)
|
2006-12-20 12:05:19 +03:00
|
|
|
|
{
|
|
|
|
|
if (!top_window)
|
|
|
|
|
return;
|
2011-09-23 00:58:07 +04:00
|
|
|
|
|
|
|
|
|
gdk_window_set_urgency_hint(gtk_widget_get_window(top_window), state);
|
2006-12-20 12:05:19 +03:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-02 09:11:10 +04:00
|
|
|
|
void *
|
|
|
|
|
nsWindow::SetupPluginPort(void)
|
|
|
|
|
{
|
2009-07-27 05:39:36 +04:00
|
|
|
|
if (!mGdkWindow)
|
2012-07-30 18:20:58 +04:00
|
|
|
|
return nullptr;
|
2002-09-02 09:11:10 +04:00
|
|
|
|
|
2011-09-23 00:58:07 +04:00
|
|
|
|
if (gdk_window_is_destroyed(mGdkWindow) == TRUE)
|
2012-07-30 18:20:58 +04:00
|
|
|
|
return nullptr;
|
2002-09-02 09:11:10 +04:00
|
|
|
|
|
2011-09-23 00:58:07 +04:00
|
|
|
|
Window window = gdk_x11_window_get_xid(mGdkWindow);
|
|
|
|
|
|
2002-09-02 09:11:10 +04:00
|
|
|
|
// we have to flush the X queue here so that any plugins that
|
2003-03-24 07:15:34 +03:00
|
|
|
|
// might be running on separate X connections will be able to use
|
2002-09-02 09:11:10 +04:00
|
|
|
|
// this window in case it was just created
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#ifdef MOZ_X11
|
2011-09-23 00:58:07 +04:00
|
|
|
|
XWindowAttributes xattrs;
|
|
|
|
|
Display *display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
|
|
|
|
|
XGetWindowAttributes(display, window, &xattrs);
|
|
|
|
|
XSelectInput (display, window,
|
2002-09-02 09:11:10 +04:00
|
|
|
|
xattrs.your_event_mask |
|
2003-02-17 18:36:37 +03:00
|
|
|
|
SubstructureNotifyMask);
|
2002-09-02 09:11:10 +04:00
|
|
|
|
|
2009-07-27 05:39:36 +04:00
|
|
|
|
gdk_window_add_filter(mGdkWindow, plugin_window_filter_func, this);
|
2002-09-02 09:11:10 +04:00
|
|
|
|
|
2011-09-23 00:58:07 +04:00
|
|
|
|
XSync(display, False);
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#endif /* MOZ_X11 */
|
2011-09-23 00:58:07 +04:00
|
|
|
|
|
|
|
|
|
return (void *)window;
|
2002-09-02 09:11:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
2002-11-16 04:22:10 +03:00
|
|
|
|
void
|
|
|
|
|
nsWindow::SetDefaultIcon(void)
|
|
|
|
|
{
|
2008-01-10 09:04:51 +03:00
|
|
|
|
SetIcon(NS_LITERAL_STRING("default"));
|
2002-11-16 04:22:10 +03:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-02 09:11:10 +04:00
|
|
|
|
void
|
2003-09-16 05:44:41 +04:00
|
|
|
|
nsWindow::SetPluginType(PluginType aPluginType)
|
2002-09-02 09:11:10 +04:00
|
|
|
|
{
|
2003-09-16 05:44:41 +04:00
|
|
|
|
mPluginType = aPluginType;
|
2002-09-02 09:11:10 +04:00
|
|
|
|
}
|
|
|
|
|
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#ifdef MOZ_X11
|
2003-02-17 18:36:37 +03:00
|
|
|
|
void
|
|
|
|
|
nsWindow::SetNonXEmbedPluginFocus()
|
|
|
|
|
{
|
2003-09-16 05:44:41 +04:00
|
|
|
|
if (gPluginFocusWindow == this || mPluginType!=PluginType_NONXEMBED) {
|
2003-02-17 18:36:37 +03:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (gPluginFocusWindow) {
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> kungFuDeathGrip = gPluginFocusWindow;
|
2003-02-17 18:36:37 +03:00
|
|
|
|
gPluginFocusWindow->LoseNonXEmbedPluginFocus();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LOGFOCUS(("nsWindow::SetNonXEmbedPluginFocus\n"));
|
|
|
|
|
|
|
|
|
|
Window curFocusWindow;
|
|
|
|
|
int focusState;
|
2011-09-23 00:58:07 +04:00
|
|
|
|
|
|
|
|
|
GdkDisplay *gdkDisplay = gdk_window_get_display(mGdkWindow);
|
|
|
|
|
XGetInputFocus(gdk_x11_display_get_xdisplay(gdkDisplay),
|
2003-02-17 18:36:37 +03:00
|
|
|
|
&curFocusWindow,
|
|
|
|
|
&focusState);
|
|
|
|
|
|
|
|
|
|
LOGFOCUS(("\t curFocusWindow=%p\n", curFocusWindow));
|
|
|
|
|
|
2009-07-27 05:39:36 +04:00
|
|
|
|
GdkWindow* toplevel = gdk_window_get_toplevel(mGdkWindow);
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2003-02-17 18:36:37 +03:00
|
|
|
|
GdkWindow *gdkfocuswin = gdk_window_lookup(curFocusWindow);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#else
|
|
|
|
|
GdkWindow *gdkfocuswin = gdk_x11_window_lookup_for_display(gdkDisplay,
|
|
|
|
|
curFocusWindow);
|
|
|
|
|
#endif
|
2003-02-17 18:36:37 +03:00
|
|
|
|
|
|
|
|
|
// lookup with the focus proxy window is supposed to get the
|
|
|
|
|
// same GdkWindow as toplevel. If the current focused window
|
|
|
|
|
// is not the focus proxy, we return without any change.
|
|
|
|
|
if (gdkfocuswin != toplevel) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// switch the focus from the focus proxy to the plugin window
|
|
|
|
|
mOldFocusWindow = curFocusWindow;
|
2009-07-27 05:39:36 +04:00
|
|
|
|
XRaiseWindow(GDK_WINDOW_XDISPLAY(mGdkWindow),
|
2011-09-23 00:58:07 +04:00
|
|
|
|
gdk_x11_window_get_xid(mGdkWindow));
|
2003-02-17 18:36:37 +03:00
|
|
|
|
gdk_error_trap_push();
|
2009-07-27 05:39:36 +04:00
|
|
|
|
XSetInputFocus(GDK_WINDOW_XDISPLAY(mGdkWindow),
|
2011-09-23 00:58:07 +04:00
|
|
|
|
gdk_x11_window_get_xid(mGdkWindow),
|
2003-02-17 18:36:37 +03:00
|
|
|
|
RevertToNone,
|
|
|
|
|
CurrentTime);
|
|
|
|
|
gdk_flush();
|
2014-06-25 02:35:00 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 3)
|
|
|
|
|
gdk_error_trap_pop_ignored();
|
|
|
|
|
#else
|
2003-02-17 18:36:37 +03:00
|
|
|
|
gdk_error_trap_pop();
|
2014-06-25 02:35:00 +04:00
|
|
|
|
#endif
|
2003-02-17 18:36:37 +03:00
|
|
|
|
gPluginFocusWindow = this;
|
2013-10-08 22:47:37 +04:00
|
|
|
|
gdk_window_add_filter(nullptr, plugin_client_message_filter, this);
|
2004-10-11 08:01:49 +04:00
|
|
|
|
|
2003-02-17 18:36:37 +03:00
|
|
|
|
LOGFOCUS(("nsWindow::SetNonXEmbedPluginFocus oldfocus=%p new=%p\n",
|
2011-09-23 00:58:07 +04:00
|
|
|
|
mOldFocusWindow, gdk_x11_window_get_xid(mGdkWindow)));
|
2003-02-17 18:36:37 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nsWindow::LoseNonXEmbedPluginFocus()
|
|
|
|
|
{
|
|
|
|
|
LOGFOCUS(("nsWindow::LoseNonXEmbedPluginFocus\n"));
|
|
|
|
|
|
|
|
|
|
// This method is only for the nsWindow which contains a
|
|
|
|
|
// Non-XEmbed plugin, for example, JAVA plugin.
|
2003-09-16 05:44:41 +04:00
|
|
|
|
if (gPluginFocusWindow != this || mPluginType!=PluginType_NONXEMBED) {
|
2003-02-17 18:36:37 +03:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Window curFocusWindow;
|
|
|
|
|
int focusState;
|
|
|
|
|
|
2009-07-27 05:39:36 +04:00
|
|
|
|
XGetInputFocus(GDK_WINDOW_XDISPLAY(mGdkWindow),
|
2003-02-17 18:36:37 +03:00
|
|
|
|
&curFocusWindow,
|
|
|
|
|
&focusState);
|
|
|
|
|
|
2004-10-11 08:01:49 +04:00
|
|
|
|
// we only switch focus between plugin window and focus proxy. If the
|
|
|
|
|
// current focused window is not the plugin window, just removing the
|
2003-02-17 18:36:37 +03:00
|
|
|
|
// event filter that blocks the WM_TAKE_FOCUS is enough. WM and gtk2
|
|
|
|
|
// will take care of the focus later.
|
2004-10-11 08:01:49 +04:00
|
|
|
|
if (!curFocusWindow ||
|
2011-09-23 00:58:07 +04:00
|
|
|
|
curFocusWindow == gdk_x11_window_get_xid(mGdkWindow)) {
|
2003-02-17 18:36:37 +03:00
|
|
|
|
|
|
|
|
|
gdk_error_trap_push();
|
2009-07-27 05:39:36 +04:00
|
|
|
|
XRaiseWindow(GDK_WINDOW_XDISPLAY(mGdkWindow),
|
2003-02-17 18:36:37 +03:00
|
|
|
|
mOldFocusWindow);
|
2009-07-27 05:39:36 +04:00
|
|
|
|
XSetInputFocus(GDK_WINDOW_XDISPLAY(mGdkWindow),
|
2003-02-17 18:36:37 +03:00
|
|
|
|
mOldFocusWindow,
|
|
|
|
|
RevertToParent,
|
|
|
|
|
CurrentTime);
|
|
|
|
|
gdk_flush();
|
2014-06-25 02:35:00 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 3)
|
|
|
|
|
gdk_error_trap_pop_ignored();
|
|
|
|
|
#else
|
2003-02-17 18:36:37 +03:00
|
|
|
|
gdk_error_trap_pop();
|
2014-06-25 02:35:00 +04:00
|
|
|
|
#endif
|
2003-02-17 18:36:37 +03:00
|
|
|
|
}
|
2013-10-08 22:47:37 +04:00
|
|
|
|
gPluginFocusWindow = nullptr;
|
2003-02-17 18:36:37 +03:00
|
|
|
|
mOldFocusWindow = 0;
|
2013-10-08 22:47:37 +04:00
|
|
|
|
gdk_window_remove_filter(nullptr, plugin_client_message_filter, this);
|
2003-02-17 18:36:37 +03:00
|
|
|
|
|
|
|
|
|
LOGFOCUS(("nsWindow::LoseNonXEmbedPluginFocus end\n"));
|
|
|
|
|
}
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#endif /* MOZ_X11 */
|
2003-02-17 18:36:37 +03:00
|
|
|
|
|
2003-05-01 06:32:24 +04:00
|
|
|
|
gint
|
|
|
|
|
nsWindow::ConvertBorderStyles(nsBorderStyle aStyle)
|
|
|
|
|
{
|
|
|
|
|
gint w = 0;
|
|
|
|
|
|
|
|
|
|
if (aStyle == eBorderStyle_default)
|
|
|
|
|
return -1;
|
|
|
|
|
|
2010-07-27 17:38:03 +04:00
|
|
|
|
// note that we don't handle eBorderStyle_close yet
|
2003-05-01 06:32:24 +04:00
|
|
|
|
if (aStyle & eBorderStyle_all)
|
|
|
|
|
w |= GDK_DECOR_ALL;
|
|
|
|
|
if (aStyle & eBorderStyle_border)
|
|
|
|
|
w |= GDK_DECOR_BORDER;
|
|
|
|
|
if (aStyle & eBorderStyle_resizeh)
|
|
|
|
|
w |= GDK_DECOR_RESIZEH;
|
|
|
|
|
if (aStyle & eBorderStyle_title)
|
|
|
|
|
w |= GDK_DECOR_TITLE;
|
|
|
|
|
if (aStyle & eBorderStyle_menu)
|
|
|
|
|
w |= GDK_DECOR_MENU;
|
|
|
|
|
if (aStyle & eBorderStyle_minimize)
|
|
|
|
|
w |= GDK_DECOR_MINIMIZE;
|
|
|
|
|
if (aStyle & eBorderStyle_maximize)
|
|
|
|
|
w |= GDK_DECOR_MAXIMIZE;
|
|
|
|
|
|
|
|
|
|
return w;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-24 02:45:00 +03:00
|
|
|
|
class FullscreenTransitionWindow final : public nsISupports
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
|
|
explicit FullscreenTransitionWindow(GtkWidget* aWidget);
|
|
|
|
|
|
|
|
|
|
GtkWidget* mWindow;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
~FullscreenTransitionWindow();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
NS_IMPL_ISUPPORTS0(FullscreenTransitionWindow)
|
|
|
|
|
|
|
|
|
|
FullscreenTransitionWindow::FullscreenTransitionWindow(GtkWidget* aWidget)
|
|
|
|
|
{
|
|
|
|
|
mWindow = gtk_window_new(GTK_WINDOW_POPUP);
|
|
|
|
|
GtkWindow* gtkWin = GTK_WINDOW(mWindow);
|
|
|
|
|
|
|
|
|
|
gtk_window_set_type_hint(gtkWin, GDK_WINDOW_TYPE_HINT_SPLASHSCREEN);
|
|
|
|
|
gtk_window_set_transient_for(gtkWin, GTK_WINDOW(aWidget));
|
|
|
|
|
gtk_window_set_decorated(gtkWin, false);
|
|
|
|
|
|
2015-08-13 01:53:53 +03:00
|
|
|
|
GdkWindow* gdkWin = gtk_widget_get_window(aWidget);
|
2015-07-24 02:45:00 +03:00
|
|
|
|
GdkScreen* screen = gtk_widget_get_screen(aWidget);
|
2015-08-13 01:53:53 +03:00
|
|
|
|
gint monitorNum = gdk_screen_get_monitor_at_window(screen, gdkWin);
|
|
|
|
|
GdkRectangle monitorRect;
|
|
|
|
|
gdk_screen_get_monitor_geometry(screen, monitorNum, &monitorRect);
|
2015-07-24 02:45:00 +03:00
|
|
|
|
gtk_window_set_screen(gtkWin, screen);
|
2015-08-13 01:53:53 +03:00
|
|
|
|
gtk_window_move(gtkWin, monitorRect.x, monitorRect.y);
|
|
|
|
|
gtk_window_resize(gtkWin, monitorRect.width, monitorRect.height);
|
2015-07-24 02:45:00 +03:00
|
|
|
|
|
|
|
|
|
GdkColor bgColor;
|
|
|
|
|
bgColor.red = bgColor.green = bgColor.blue = 0;
|
|
|
|
|
gtk_widget_modify_bg(mWindow, GTK_STATE_NORMAL, &bgColor);
|
|
|
|
|
|
|
|
|
|
gtk_window_set_opacity(gtkWin, 0.0);
|
|
|
|
|
gtk_widget_show(mWindow);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FullscreenTransitionWindow::~FullscreenTransitionWindow()
|
|
|
|
|
{
|
|
|
|
|
gtk_widget_destroy(mWindow);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class FullscreenTransitionData
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
FullscreenTransitionData(nsIWidget::FullscreenTransitionStage aStage,
|
|
|
|
|
uint16_t aDuration, nsIRunnable* aCallback,
|
|
|
|
|
FullscreenTransitionWindow* aWindow)
|
|
|
|
|
: mStage(aStage)
|
|
|
|
|
, mStep(0)
|
|
|
|
|
, mTotalSteps(aDuration / sInterval)
|
|
|
|
|
, mCallback(aCallback)
|
|
|
|
|
, mWindow(aWindow) { }
|
|
|
|
|
|
|
|
|
|
static const guint sInterval = 10; // 10ms
|
|
|
|
|
static gboolean TimeoutCallback(gpointer aData);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
nsIWidget::FullscreenTransitionStage mStage;
|
|
|
|
|
uint16_t mStep, mTotalSteps;
|
|
|
|
|
nsCOMPtr<nsIRunnable> mCallback;
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<FullscreenTransitionWindow> mWindow;
|
2015-07-24 02:45:00 +03:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* static */ gboolean
|
|
|
|
|
FullscreenTransitionData::TimeoutCallback(gpointer aData)
|
|
|
|
|
{
|
|
|
|
|
auto data = static_cast<FullscreenTransitionData*>(aData);
|
|
|
|
|
data->mStep++;
|
|
|
|
|
gdouble opacity = data->mStep / gdouble(data->mTotalSteps);
|
|
|
|
|
if (data->mStage == nsIWidget::eAfterFullscreenToggle) {
|
|
|
|
|
opacity = 1.0 - opacity;
|
|
|
|
|
}
|
|
|
|
|
gtk_window_set_opacity(GTK_WINDOW(data->mWindow->mWindow), opacity);
|
|
|
|
|
|
|
|
|
|
if (data->mStep != data->mTotalSteps) {
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
NS_DispatchToMainThread(data->mCallback.forget());
|
|
|
|
|
delete data;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* virtual */ bool
|
|
|
|
|
nsWindow::PrepareForFullscreenTransition(nsISupports** aData)
|
|
|
|
|
{
|
|
|
|
|
GdkScreen* screen = gtk_widget_get_screen(mShell);
|
|
|
|
|
if (!gdk_screen_is_composited(screen)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
*aData = do_AddRef(new FullscreenTransitionWindow(mShell)).take();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* virtual */ void
|
|
|
|
|
nsWindow::PerformFullscreenTransition(FullscreenTransitionStage aStage,
|
|
|
|
|
uint16_t aDuration, nsISupports* aData,
|
|
|
|
|
nsIRunnable* aCallback)
|
|
|
|
|
{
|
|
|
|
|
auto data = static_cast<FullscreenTransitionWindow*>(aData);
|
|
|
|
|
// This will be released at the end of the last timeout callback for it.
|
|
|
|
|
auto transitionData = new FullscreenTransitionData(aStage, aDuration,
|
|
|
|
|
aCallback, data);
|
|
|
|
|
g_timeout_add_full(G_PRIORITY_HIGH,
|
|
|
|
|
FullscreenTransitionData::sInterval,
|
|
|
|
|
FullscreenTransitionData::TimeoutCallback,
|
|
|
|
|
transitionData, nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-21 08:28:40 +04:00
|
|
|
|
NS_IMETHODIMP
|
2014-07-09 23:29:28 +04:00
|
|
|
|
nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen)
|
2005-07-21 08:28:40 +04:00
|
|
|
|
{
|
2009-08-14 23:56:56 +04:00
|
|
|
|
LOG(("nsWindow::MakeFullScreen [%p] aFullScreen %d\n",
|
|
|
|
|
(void *)this, aFullScreen));
|
|
|
|
|
|
|
|
|
|
if (aFullScreen) {
|
2009-08-27 04:09:47 +04:00
|
|
|
|
if (mSizeMode != nsSizeMode_Fullscreen)
|
|
|
|
|
mLastSizeMode = mSizeMode;
|
|
|
|
|
|
2009-08-14 23:56:56 +04:00
|
|
|
|
mSizeMode = nsSizeMode_Fullscreen;
|
2009-11-10 23:46:09 +03:00
|
|
|
|
gtk_window_fullscreen(GTK_WINDOW(mShell));
|
2009-08-14 23:56:56 +04:00
|
|
|
|
}
|
2009-08-27 04:09:47 +04:00
|
|
|
|
else {
|
|
|
|
|
mSizeMode = mLastSizeMode;
|
2009-11-10 23:46:09 +03:00
|
|
|
|
gtk_window_unfullscreen(GTK_WINDOW(mShell));
|
2009-08-27 04:09:47 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_ASSERTION(mLastSizeMode != nsSizeMode_Fullscreen,
|
|
|
|
|
"mLastSizeMode should never be fullscreen");
|
2008-01-05 08:34:00 +03:00
|
|
|
|
return NS_OK;
|
2005-07-21 08:28:40 +04:00
|
|
|
|
}
|
|
|
|
|
|
2003-05-01 06:32:24 +04:00
|
|
|
|
NS_IMETHODIMP
|
2011-09-29 10:19:26 +04:00
|
|
|
|
nsWindow::HideWindowChrome(bool aShouldHide)
|
2003-05-01 06:32:24 +04:00
|
|
|
|
{
|
|
|
|
|
if (!mShell) {
|
|
|
|
|
// Pass the request to the toplevel window
|
2012-11-07 01:50:37 +04:00
|
|
|
|
GtkWidget *topWidget = GetToplevelWidget();
|
2009-02-20 05:07:08 +03:00
|
|
|
|
if (!topWidget)
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
2003-05-01 06:32:24 +04:00
|
|
|
|
nsWindow *topWindow = get_window_for_gtk_widget(topWidget);
|
2009-02-20 05:07:08 +03:00
|
|
|
|
if (!topWindow)
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
2003-05-01 06:32:24 +04:00
|
|
|
|
return topWindow->HideWindowChrome(aShouldHide);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sawfish, metacity, and presumably other window managers get
|
|
|
|
|
// confused if we change the window decorations while the window
|
|
|
|
|
// is visible.
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool wasVisible = false;
|
2015-04-21 10:06:41 +03:00
|
|
|
|
if (gdk_window_is_visible(mGdkWindow)) {
|
|
|
|
|
gdk_window_hide(mGdkWindow);
|
2011-10-03 11:56:21 +04:00
|
|
|
|
wasVisible = true;
|
2008-01-14 12:35:19 +03:00
|
|
|
|
}
|
2003-05-01 06:32:24 +04:00
|
|
|
|
|
|
|
|
|
gint wmd;
|
|
|
|
|
if (aShouldHide)
|
|
|
|
|
wmd = 0;
|
|
|
|
|
else
|
|
|
|
|
wmd = ConvertBorderStyles(mBorderStyle);
|
|
|
|
|
|
2010-07-27 17:38:03 +04:00
|
|
|
|
if (wmd != -1)
|
2015-04-21 10:06:41 +03:00
|
|
|
|
gdk_window_set_decorations(mGdkWindow, (GdkWMDecoration) wmd);
|
2003-05-01 06:32:24 +04:00
|
|
|
|
|
2008-01-14 12:35:19 +03:00
|
|
|
|
if (wasVisible)
|
2015-04-21 10:06:41 +03:00
|
|
|
|
gdk_window_show(mGdkWindow);
|
2003-05-01 06:32:24 +04:00
|
|
|
|
|
|
|
|
|
// For some window managers, adding or removing window decorations
|
|
|
|
|
// requires unmapping and remapping our toplevel window. Go ahead
|
|
|
|
|
// and flush the queue here so that we don't end up with a BadWindow
|
|
|
|
|
// error later when this happens (when the persistence timer fires
|
|
|
|
|
// and GetWindowPos is called)
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#ifdef MOZ_X11
|
2011-09-23 00:58:07 +04:00
|
|
|
|
XSync(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()) , False);
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#else
|
|
|
|
|
gdk_flush ();
|
|
|
|
|
#endif /* MOZ_X11 */
|
2003-05-01 06:32:24 +04:00
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-26 17:15:22 +04:00
|
|
|
|
bool
|
|
|
|
|
nsWindow::CheckForRollup(gdouble aMouseX, gdouble aMouseY,
|
|
|
|
|
bool aIsWheel, bool aAlwaysRollup)
|
2002-04-30 23:03:12 +04:00
|
|
|
|
{
|
2012-10-26 17:15:22 +04:00
|
|
|
|
nsIRollupListener* rollupListener = GetActiveRollupListener();
|
2012-12-31 21:27:04 +04:00
|
|
|
|
nsCOMPtr<nsIWidget> rollupWidget;
|
|
|
|
|
if (rollupListener) {
|
|
|
|
|
rollupWidget = rollupListener->GetRollupWidget();
|
|
|
|
|
}
|
|
|
|
|
if (!rollupWidget) {
|
2012-10-26 17:15:22 +04:00
|
|
|
|
nsBaseWidget::gRollupListener = nullptr;
|
2012-12-31 21:27:04 +04:00
|
|
|
|
return false;
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-12-31 21:27:04 +04:00
|
|
|
|
bool retVal = false;
|
|
|
|
|
GdkWindow *currentPopup =
|
|
|
|
|
(GdkWindow *)rollupWidget->GetNativeData(NS_NATIVE_WINDOW);
|
|
|
|
|
if (aAlwaysRollup || !is_mouse_in_window(currentPopup, aMouseX, aMouseY)) {
|
|
|
|
|
bool rollup = true;
|
|
|
|
|
if (aIsWheel) {
|
|
|
|
|
rollup = rollupListener->ShouldRollupOnMouseWheelEvent();
|
2013-11-29 20:58:26 +04:00
|
|
|
|
retVal = rollupListener->ShouldConsumeOnMouseWheelEvent();
|
2012-12-31 21:27:04 +04:00
|
|
|
|
}
|
|
|
|
|
// if we're dealing with menus, we probably have submenus and
|
|
|
|
|
// we don't want to rollup if the click is in a parent menu of
|
|
|
|
|
// the current submenu
|
|
|
|
|
uint32_t popupsToRollup = UINT32_MAX;
|
|
|
|
|
if (!aAlwaysRollup) {
|
|
|
|
|
nsAutoTArray<nsIWidget*, 5> widgetChain;
|
|
|
|
|
uint32_t sameTypeCount = rollupListener->GetSubmenuWidgetChain(&widgetChain);
|
|
|
|
|
for (uint32_t i=0; i<widgetChain.Length(); ++i) {
|
|
|
|
|
nsIWidget* widget = widgetChain[i];
|
|
|
|
|
GdkWindow* currWindow =
|
|
|
|
|
(GdkWindow*) widget->GetNativeData(NS_NATIVE_WINDOW);
|
|
|
|
|
if (is_mouse_in_window(currWindow, aMouseX, aMouseY)) {
|
|
|
|
|
// don't roll up if the mouse event occurred within a
|
|
|
|
|
// menu of the same type. If the mouse event occurred
|
|
|
|
|
// in a menu higher than that, roll up, but pass the
|
|
|
|
|
// number of popups to Rollup so that only those of the
|
|
|
|
|
// same type close up.
|
|
|
|
|
if (i < sameTypeCount) {
|
|
|
|
|
rollup = false;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
popupsToRollup = sameTypeCount;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} // foreach parent menu widget
|
|
|
|
|
} // if rollup listener knows about menus
|
|
|
|
|
|
|
|
|
|
// if we've determined that we should still rollup, do it.
|
2013-11-04 20:22:24 +04:00
|
|
|
|
bool usePoint = !aIsWheel && !aAlwaysRollup;
|
|
|
|
|
nsIntPoint point(aMouseX, aMouseY);
|
2015-01-08 04:52:20 +03:00
|
|
|
|
if (rollup && rollupListener->Rollup(popupsToRollup, true, usePoint ? &point : nullptr, nullptr)) {
|
2012-12-31 21:27:04 +04:00
|
|
|
|
retVal = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return retVal;
|
2002-04-30 23:03:12 +04:00
|
|
|
|
}
|
|
|
|
|
|
2003-12-03 04:50:50 +03:00
|
|
|
|
/* static */
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool
|
2003-12-03 04:50:50 +03:00
|
|
|
|
nsWindow::DragInProgress(void)
|
|
|
|
|
{
|
2012-04-17 05:00:26 +04:00
|
|
|
|
nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
|
|
|
|
|
|
|
|
|
|
if (!dragService)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDragSession> currentDragSession;
|
|
|
|
|
dragService->GetCurrentSession(getter_AddRefs(currentDragSession));
|
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
|
return currentDragSession != nullptr;
|
2003-12-03 04:50:50 +03:00
|
|
|
|
}
|
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
|
static bool
|
2002-08-10 22:21:22 +04:00
|
|
|
|
is_mouse_in_window (GdkWindow* aWindow, gdouble aMouseX, gdouble aMouseY)
|
2002-05-13 01:03:17 +04:00
|
|
|
|
{
|
2002-08-10 22:21:22 +04:00
|
|
|
|
gint x = 0;
|
2003-04-11 02:11:27 +04:00
|
|
|
|
gint y = 0;
|
2002-08-10 22:21:22 +04:00
|
|
|
|
gint w, h;
|
2002-05-13 01:03:17 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
gint offsetX = 0;
|
|
|
|
|
gint offsetY = 0;
|
2002-05-13 01:03:17 +04:00
|
|
|
|
|
2009-02-20 05:07:08 +03:00
|
|
|
|
GdkWindow *window = aWindow;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
while (window) {
|
|
|
|
|
gint tmpX = 0;
|
|
|
|
|
gint tmpY = 0;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
gdk_window_get_position(window, &tmpX, &tmpY);
|
2009-02-20 05:07:08 +03:00
|
|
|
|
GtkWidget *widget = get_gtk_widget_for_gdk_window(window);
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
// if this is a window, compute x and y given its origin and our
|
|
|
|
|
// offset
|
|
|
|
|
if (GTK_IS_WINDOW(widget)) {
|
|
|
|
|
x = tmpX + offsetX;
|
|
|
|
|
y = tmpY + offsetY;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
offsetX += tmpX;
|
|
|
|
|
offsetY += tmpY;
|
|
|
|
|
window = gdk_window_get_parent(window);
|
|
|
|
|
}
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2009-02-02 20:49:58 +03:00
|
|
|
|
gdk_drawable_get_size(aWindow, &w, &h);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#else
|
|
|
|
|
w = gdk_window_get_width(aWindow);
|
|
|
|
|
h = gdk_window_get_height(aWindow);
|
|
|
|
|
#endif
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2003-02-17 18:36:37 +03:00
|
|
|
|
if (aMouseX > x && aMouseX < x + w &&
|
|
|
|
|
aMouseY > y && aMouseY < y + h)
|
2011-10-03 11:56:21 +04:00
|
|
|
|
return true;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2011-10-03 11:56:21 +04:00
|
|
|
|
return false;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
}
|
2002-08-10 22:21:22 +04:00
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static nsWindow *
|
2002-08-10 22:21:22 +04:00
|
|
|
|
get_window_for_gtk_widget(GtkWidget *widget)
|
2002-08-10 20:18:44 +04:00
|
|
|
|
{
|
2009-02-20 05:07:08 +03:00
|
|
|
|
gpointer user_data = g_object_get_data(G_OBJECT(widget), "nsWindow");
|
2002-08-10 22:21:22 +04:00
|
|
|
|
|
2007-07-08 11:08:04 +04:00
|
|
|
|
return static_cast<nsWindow *>(user_data);
|
2002-08-10 20:18:44 +04:00
|
|
|
|
}
|
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static nsWindow *
|
2002-08-10 22:21:22 +04:00
|
|
|
|
get_window_for_gdk_window(GdkWindow *window)
|
|
|
|
|
{
|
2009-02-20 05:07:08 +03:00
|
|
|
|
gpointer user_data = g_object_get_data(G_OBJECT(window), "nsWindow");
|
2002-08-10 22:21:22 +04:00
|
|
|
|
|
2007-07-08 11:08:04 +04:00
|
|
|
|
return static_cast<nsWindow *>(user_data);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static GtkWidget *
|
2002-08-10 22:21:22 +04:00
|
|
|
|
get_gtk_widget_for_gdk_window(GdkWindow *window)
|
2002-08-10 20:18:44 +04:00
|
|
|
|
{
|
2013-10-08 22:47:37 +04:00
|
|
|
|
gpointer user_data = nullptr;
|
2002-08-10 22:21:22 +04:00
|
|
|
|
gdk_window_get_user_data(window, &user_data);
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return GTK_WIDGET(user_data);
|
2002-08-10 20:18:44 +04:00
|
|
|
|
}
|
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static GdkCursor *
|
2002-08-10 22:21:22 +04:00
|
|
|
|
get_gtk_cursor(nsCursor aCursor)
|
2002-08-10 22:07:20 +04:00
|
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
|
GdkCursor *gdkcursor = nullptr;
|
2012-08-22 19:56:38 +04:00
|
|
|
|
uint8_t newType = 0xff;
|
2002-08-10 22:21:22 +04:00
|
|
|
|
|
|
|
|
|
if ((gdkcursor = gCursorCache[aCursor])) {
|
|
|
|
|
return gdkcursor;
|
2002-08-10 22:07:20 +04:00
|
|
|
|
}
|
2014-02-19 20:30:08 +04:00
|
|
|
|
|
|
|
|
|
GdkDisplay *defaultDisplay = gdk_display_get_default();
|
2002-08-10 22:07:20 +04:00
|
|
|
|
|
2014-02-19 20:30:08 +04:00
|
|
|
|
// The strategy here is to use standard GDK cursors, and, if not available,
|
|
|
|
|
// load by standard name with gdk_cursor_new_from_name.
|
|
|
|
|
// Spec is here: http://www.freedesktop.org/wiki/Specifications/cursor-spec/
|
2002-08-10 22:21:22 +04:00
|
|
|
|
switch (aCursor) {
|
|
|
|
|
case eCursor_standard:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay, GDK_LEFT_PTR);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_wait:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay, GDK_WATCH);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_select:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay, GDK_XTERM);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_hyperlink:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay, GDK_HAND2);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
2004-09-12 03:24:30 +04:00
|
|
|
|
case eCursor_n_resize:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay, GDK_TOP_SIDE);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
2004-09-12 03:24:30 +04:00
|
|
|
|
case eCursor_s_resize:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay, GDK_BOTTOM_SIDE);
|
2004-09-12 03:24:30 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_w_resize:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay, GDK_LEFT_SIDE);
|
2004-09-12 03:24:30 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_e_resize:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay, GDK_RIGHT_SIDE);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
2004-09-12 03:24:30 +04:00
|
|
|
|
case eCursor_nw_resize:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay,
|
|
|
|
|
GDK_TOP_LEFT_CORNER);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
2004-09-12 03:24:30 +04:00
|
|
|
|
case eCursor_se_resize:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay,
|
|
|
|
|
GDK_BOTTOM_RIGHT_CORNER);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
2004-09-12 03:24:30 +04:00
|
|
|
|
case eCursor_ne_resize:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay,
|
|
|
|
|
GDK_TOP_RIGHT_CORNER);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
2004-09-12 03:24:30 +04:00
|
|
|
|
case eCursor_sw_resize:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay,
|
|
|
|
|
GDK_BOTTOM_LEFT_CORNER);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_crosshair:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay, GDK_CROSSHAIR);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_move:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay, GDK_FLEUR);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_help:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay,
|
|
|
|
|
GDK_QUESTION_ARROW);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_copy: // CSS3
|
2014-02-19 20:30:08 +04:00
|
|
|
|
gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "copy");
|
|
|
|
|
if (!gdkcursor)
|
|
|
|
|
newType = MOZ_CURSOR_COPY;
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_alias:
|
2014-02-19 20:30:08 +04:00
|
|
|
|
gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "alias");
|
|
|
|
|
if (!gdkcursor)
|
|
|
|
|
newType = MOZ_CURSOR_ALIAS;
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_context_menu:
|
2014-02-19 20:30:08 +04:00
|
|
|
|
gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "context-menu");
|
|
|
|
|
if (!gdkcursor)
|
|
|
|
|
newType = MOZ_CURSOR_CONTEXT_MENU;
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_cell:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay, GDK_PLUS);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
2014-02-19 20:30:08 +04:00
|
|
|
|
// Those two aren’t standardized. Trying both KDE’s and GNOME’s names
|
2002-08-10 22:21:22 +04:00
|
|
|
|
case eCursor_grab:
|
2014-02-19 20:30:08 +04:00
|
|
|
|
gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "openhand");
|
|
|
|
|
if (!gdkcursor)
|
|
|
|
|
newType = MOZ_CURSOR_HAND_GRAB;
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_grabbing:
|
2014-02-19 20:30:08 +04:00
|
|
|
|
gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "closedhand");
|
|
|
|
|
if (!gdkcursor)
|
|
|
|
|
gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "grabbing");
|
|
|
|
|
if (!gdkcursor)
|
|
|
|
|
newType = MOZ_CURSOR_HAND_GRABBING;
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_spinning:
|
2014-02-19 20:30:08 +04:00
|
|
|
|
gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "progress");
|
|
|
|
|
if (!gdkcursor)
|
|
|
|
|
newType = MOZ_CURSOR_SPINNING;
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
2003-05-03 02:23:55 +04:00
|
|
|
|
case eCursor_zoom_in:
|
|
|
|
|
newType = MOZ_CURSOR_ZOOM_IN;
|
|
|
|
|
break;
|
|
|
|
|
case eCursor_zoom_out:
|
|
|
|
|
newType = MOZ_CURSOR_ZOOM_OUT;
|
|
|
|
|
break;
|
2004-09-12 03:24:30 +04:00
|
|
|
|
case eCursor_not_allowed:
|
2014-02-19 20:30:08 +04:00
|
|
|
|
gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "not-allowed");
|
|
|
|
|
if (!gdkcursor) // nonstandard, yet common
|
|
|
|
|
gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "crossed_circle");
|
|
|
|
|
if (!gdkcursor)
|
|
|
|
|
newType = MOZ_CURSOR_NOT_ALLOWED;
|
|
|
|
|
break;
|
2004-09-12 03:24:30 +04:00
|
|
|
|
case eCursor_no_drop:
|
2014-02-19 20:30:08 +04:00
|
|
|
|
gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "no-drop");
|
|
|
|
|
if (!gdkcursor) // this nonstandard sequence makes it work on KDE and GNOME
|
|
|
|
|
gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "forbidden");
|
|
|
|
|
if (!gdkcursor)
|
|
|
|
|
gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "circle");
|
|
|
|
|
if (!gdkcursor)
|
|
|
|
|
newType = MOZ_CURSOR_NOT_ALLOWED;
|
2004-09-12 03:24:30 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_vertical_text:
|
|
|
|
|
newType = MOZ_CURSOR_VERTICAL_TEXT;
|
|
|
|
|
break;
|
|
|
|
|
case eCursor_all_scroll:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay, GDK_FLEUR);
|
2004-09-12 03:24:30 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_nesw_resize:
|
2014-02-19 20:30:08 +04:00
|
|
|
|
gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "size_bdiag");
|
|
|
|
|
if (!gdkcursor)
|
|
|
|
|
newType = MOZ_CURSOR_NESW_RESIZE;
|
2004-09-12 03:24:30 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_nwse_resize:
|
2014-02-19 20:30:08 +04:00
|
|
|
|
gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "size_fdiag");
|
|
|
|
|
if (!gdkcursor)
|
|
|
|
|
newType = MOZ_CURSOR_NWSE_RESIZE;
|
2004-09-12 03:24:30 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_ns_resize:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay,
|
|
|
|
|
GDK_SB_V_DOUBLE_ARROW);
|
2004-09-12 03:24:30 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_ew_resize:
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay,
|
|
|
|
|
GDK_SB_H_DOUBLE_ARROW);
|
2004-09-12 03:24:30 +04:00
|
|
|
|
break;
|
2014-02-19 20:30:08 +04:00
|
|
|
|
// Here, two better fitting cursors exist in some cursor themes. Try those first
|
|
|
|
|
case eCursor_row_resize:
|
|
|
|
|
gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "split_v");
|
|
|
|
|
if (!gdkcursor)
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay,
|
|
|
|
|
GDK_SB_V_DOUBLE_ARROW);
|
2014-02-19 20:30:08 +04:00
|
|
|
|
break;
|
|
|
|
|
case eCursor_col_resize:
|
|
|
|
|
gdkcursor = gdk_cursor_new_from_name(defaultDisplay, "split_h");
|
|
|
|
|
if (!gdkcursor)
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay,
|
|
|
|
|
GDK_SB_H_DOUBLE_ARROW);
|
2014-02-19 20:30:08 +04:00
|
|
|
|
break;
|
2008-01-18 21:39:49 +03:00
|
|
|
|
case eCursor_none:
|
|
|
|
|
newType = MOZ_CURSOR_NONE;
|
|
|
|
|
break;
|
2002-08-10 22:21:22 +04:00
|
|
|
|
default:
|
|
|
|
|
NS_ASSERTION(aCursor, "Invalid cursor type");
|
2015-06-13 05:38:20 +03:00
|
|
|
|
gdkcursor = gdk_cursor_new_for_display(defaultDisplay, GDK_LEFT_PTR);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-14 14:34:31 +04:00
|
|
|
|
// If by now we don't have a xcursor, this means we have to make a custom
|
|
|
|
|
// one. First, we try creating a named cursor based on the hash of our
|
|
|
|
|
// custom bitmap, as libXcursor has some magic to convert bitmapped cursors
|
|
|
|
|
// to themed cursors
|
|
|
|
|
if (newType != 0xFF && GtkCursors[newType].hash) {
|
2014-02-19 20:30:08 +04:00
|
|
|
|
gdkcursor = gdk_cursor_new_from_name(defaultDisplay, GtkCursors[newType].hash);
|
2011-12-14 14:34:31 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If we still don't have a xcursor, we now really create a bitmap cursor
|
|
|
|
|
if (newType != 0xff && !gdkcursor) {
|
2011-09-23 00:58:07 +04:00
|
|
|
|
GdkPixbuf * cursor_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 32, 32);
|
|
|
|
|
if (!cursor_pixbuf)
|
2013-10-08 22:47:37 +04:00
|
|
|
|
return nullptr;
|
2011-09-23 00:58:07 +04:00
|
|
|
|
|
|
|
|
|
guchar *data = gdk_pixbuf_get_pixels(cursor_pixbuf);
|
|
|
|
|
|
|
|
|
|
// Read data from GtkCursors and compose RGBA surface from 1bit bitmap and mask
|
|
|
|
|
// GtkCursors bits and mask are 32x32 monochrome bitmaps (1 bit for each pixel)
|
|
|
|
|
// so it's 128 byte array (4 bytes for are one bitmap row and there are 32 rows here).
|
|
|
|
|
const unsigned char *bits = GtkCursors[newType].bits;
|
|
|
|
|
const unsigned char *mask_bits = GtkCursors[newType].mask_bits;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 128; i++) {
|
|
|
|
|
char bit = *bits++;
|
|
|
|
|
char mask = *mask_bits++;
|
|
|
|
|
for (int j = 0; j < 8; j++) {
|
|
|
|
|
unsigned char pix = ~(((bit >> j) & 0x01) * 0xff);
|
|
|
|
|
*data++ = pix;
|
|
|
|
|
*data++ = pix;
|
|
|
|
|
*data++ = pix;
|
|
|
|
|
*data++ = (((mask >> j) & 0x01) * 0xff);
|
|
|
|
|
}
|
2007-10-10 16:21:29 +04:00
|
|
|
|
}
|
2011-09-23 00:58:07 +04:00
|
|
|
|
|
|
|
|
|
gdkcursor = gdk_cursor_new_from_pixbuf(gdk_display_get_default(), cursor_pixbuf,
|
2002-08-10 22:21:22 +04:00
|
|
|
|
GtkCursors[newType].hot_x,
|
|
|
|
|
GtkCursors[newType].hot_y);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
|
|
|
|
|
g_object_unref(cursor_pixbuf);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gCursorCache[aCursor] = gdkcursor;
|
|
|
|
|
|
|
|
|
|
return gdkcursor;
|
2002-08-10 22:07:20 +04:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
// gtk callbacks
|
|
|
|
|
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static gboolean
|
2002-08-10 22:21:22 +04:00
|
|
|
|
expose_event_cb(GtkWidget *widget, GdkEventExpose *event)
|
2002-08-10 22:07:20 +04:00
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> window = get_window_for_gdk_window(event->window);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (!window)
|
|
|
|
|
return FALSE;
|
2002-08-10 22:07:20 +04:00
|
|
|
|
|
2011-09-23 00:58:07 +04:00
|
|
|
|
window->OnExposeEvent(event);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
void
|
|
|
|
|
draw_window_of_widget(GtkWidget *widget, GdkWindow *aWindow, cairo_t *cr)
|
|
|
|
|
{
|
|
|
|
|
if (gtk_cairo_should_draw_window(cr, aWindow)) {
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> window = get_window_for_gdk_window(aWindow);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
if (!window) {
|
|
|
|
|
NS_WARNING("Cannot get nsWindow from GtkWidget");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
cairo_save(cr);
|
|
|
|
|
gtk_cairo_transform_to_window(cr, widget, aWindow);
|
|
|
|
|
// TODO - window->OnExposeEvent() can destroy this or other windows,
|
|
|
|
|
// do we need to handle it somehow?
|
|
|
|
|
window->OnExposeEvent(cr);
|
|
|
|
|
cairo_restore(cr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GList *children = gdk_window_get_children(aWindow);
|
|
|
|
|
GList *child = children;
|
|
|
|
|
while (child) {
|
2012-10-23 02:39:59 +04:00
|
|
|
|
GdkWindow *window = GDK_WINDOW(child->data);
|
|
|
|
|
gpointer windowWidget;
|
|
|
|
|
gdk_window_get_user_data(window, &windowWidget);
|
|
|
|
|
if (windowWidget == widget) {
|
|
|
|
|
draw_window_of_widget(widget, window, cr);
|
|
|
|
|
}
|
2011-09-23 00:58:07 +04:00
|
|
|
|
child = g_list_next(child);
|
|
|
|
|
}
|
|
|
|
|
g_list_free(children);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
|
gboolean
|
|
|
|
|
expose_event_cb(GtkWidget *widget, cairo_t *cr)
|
|
|
|
|
{
|
|
|
|
|
draw_window_of_widget(widget, gtk_widget_get_window(widget), cr);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#endif //MOZ_WIDGET_GTK2
|
2002-08-10 22:07:20 +04:00
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static gboolean
|
2002-08-10 22:21:22 +04:00
|
|
|
|
configure_event_cb(GtkWidget *widget,
|
|
|
|
|
GdkEventConfigure *event)
|
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> window = get_window_for_gtk_widget(widget);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (!window)
|
|
|
|
|
return FALSE;
|
2002-08-10 22:07:20 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return window->OnConfigureEvent(widget, event);
|
|
|
|
|
}
|
2002-08-10 22:07:20 +04:00
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static void
|
2009-05-15 06:14:45 +04:00
|
|
|
|
container_unrealize_cb (GtkWidget *widget)
|
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> window = get_window_for_gtk_widget(widget);
|
2009-05-15 06:14:45 +04:00
|
|
|
|
if (!window)
|
|
|
|
|
return;
|
|
|
|
|
|
2012-10-23 02:33:30 +04:00
|
|
|
|
window->OnContainerUnrealize();
|
2009-05-15 06:14:45 +04:00
|
|
|
|
}
|
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static void
|
2002-08-10 22:21:22 +04:00
|
|
|
|
size_allocate_cb (GtkWidget *widget, GtkAllocation *allocation)
|
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> window = get_window_for_gtk_widget(widget);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (!window)
|
|
|
|
|
return;
|
|
|
|
|
|
2012-10-23 02:33:30 +04:00
|
|
|
|
window->OnSizeAllocate(allocation);
|
2002-08-10 22:07:20 +04:00
|
|
|
|
}
|
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static gboolean
|
2002-08-10 22:21:22 +04:00
|
|
|
|
delete_event_cb(GtkWidget *widget, GdkEventAny *event)
|
2002-08-10 20:18:44 +04:00
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> window = get_window_for_gtk_widget(widget);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (!window)
|
|
|
|
|
return FALSE;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2012-10-23 02:33:30 +04:00
|
|
|
|
window->OnDeleteEvent();
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static gboolean
|
2007-04-30 04:46:47 +04:00
|
|
|
|
enter_notify_event_cb(GtkWidget *widget,
|
|
|
|
|
GdkEventCrossing *event)
|
2002-08-10 22:21:22 +04:00
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> window = get_window_for_gdk_window(event->window);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (!window)
|
|
|
|
|
return TRUE;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2012-10-23 02:33:30 +04:00
|
|
|
|
window->OnEnterNotifyEvent(event);
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static gboolean
|
2007-04-30 04:46:47 +04:00
|
|
|
|
leave_notify_event_cb(GtkWidget *widget,
|
|
|
|
|
GdkEventCrossing *event)
|
2002-08-10 22:21:22 +04:00
|
|
|
|
{
|
2003-09-30 18:58:39 +04:00
|
|
|
|
if (is_parent_grab_leave(event)) {
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-19 14:21:05 +03:00
|
|
|
|
// bug 369599: Suppress LeaveNotify events caused by pointer grabs to
|
|
|
|
|
// avoid generating spurious mouse exit events.
|
|
|
|
|
gint x = gint(event->x_root);
|
|
|
|
|
gint y = gint(event->y_root);
|
|
|
|
|
GdkDisplay* display = gtk_widget_get_display(widget);
|
|
|
|
|
GdkWindow* winAtPt = gdk_display_get_window_at_pointer(display, &x, &y);
|
|
|
|
|
if (winAtPt == event->window) {
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> window = get_window_for_gdk_window(event->window);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (!window)
|
|
|
|
|
return TRUE;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2012-10-23 02:33:30 +04:00
|
|
|
|
window->OnLeaveNotifyEvent(event);
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static nsWindow*
|
2007-12-14 10:00:44 +03:00
|
|
|
|
GetFirstNSWindowForGDKWindow(GdkWindow *aGdkWindow)
|
|
|
|
|
{
|
|
|
|
|
nsWindow* window;
|
|
|
|
|
while (!(window = get_window_for_gdk_window(aGdkWindow))) {
|
|
|
|
|
// The event has bubbled to the moz_container widget as passed into each caller's *widget parameter,
|
|
|
|
|
// but its corresponding nsWindow is an ancestor of the window that we need. Instead, look at
|
|
|
|
|
// event->window and find the first ancestor nsWindow of it because event->window may be in a plugin.
|
|
|
|
|
aGdkWindow = gdk_window_get_parent(aGdkWindow);
|
|
|
|
|
if (!aGdkWindow) {
|
2012-07-30 18:20:58 +04:00
|
|
|
|
window = nullptr;
|
2007-12-14 10:00:44 +03:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return window;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static gboolean
|
2007-04-30 04:46:47 +04:00
|
|
|
|
motion_notify_event_cb(GtkWidget *widget, GdkEventMotion *event)
|
2002-08-10 22:21:22 +04:00
|
|
|
|
{
|
2012-02-14 00:19:59 +04:00
|
|
|
|
UpdateLastInputEventTime(event);
|
2009-09-17 21:13:45 +04:00
|
|
|
|
|
2007-12-14 10:00:44 +03:00
|
|
|
|
nsWindow *window = GetFirstNSWindowForGDKWindow(event->window);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (!window)
|
2007-12-14 10:00:44 +03:00
|
|
|
|
return FALSE;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2012-10-23 02:33:30 +04:00
|
|
|
|
window->OnMotionNotifyEvent(event);
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static gboolean
|
2007-04-30 04:46:47 +04:00
|
|
|
|
button_press_event_cb(GtkWidget *widget, GdkEventButton *event)
|
2002-08-10 22:21:22 +04:00
|
|
|
|
{
|
2012-02-14 00:19:59 +04:00
|
|
|
|
UpdateLastInputEventTime(event);
|
2009-09-17 21:13:45 +04:00
|
|
|
|
|
2007-12-14 10:00:44 +03:00
|
|
|
|
nsWindow *window = GetFirstNSWindowForGDKWindow(event->window);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (!window)
|
2007-12-14 10:00:44 +03:00
|
|
|
|
return FALSE;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2012-10-23 02:33:30 +04:00
|
|
|
|
window->OnButtonPressEvent(event);
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static gboolean
|
2007-04-30 04:46:47 +04:00
|
|
|
|
button_release_event_cb(GtkWidget *widget, GdkEventButton *event)
|
2002-08-10 22:21:22 +04:00
|
|
|
|
{
|
2012-02-14 00:19:59 +04:00
|
|
|
|
UpdateLastInputEventTime(event);
|
2009-09-17 21:13:45 +04:00
|
|
|
|
|
2007-12-14 10:00:44 +03:00
|
|
|
|
nsWindow *window = GetFirstNSWindowForGDKWindow(event->window);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (!window)
|
2007-12-14 10:00:44 +03:00
|
|
|
|
return FALSE;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2012-10-23 02:33:30 +04:00
|
|
|
|
window->OnButtonReleaseEvent(event);
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static gboolean
|
2007-04-30 04:46:47 +04:00
|
|
|
|
focus_in_event_cb(GtkWidget *widget, GdkEventFocus *event)
|
2002-08-10 22:21:22 +04:00
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> window = get_window_for_gtk_widget(widget);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (!window)
|
|
|
|
|
return FALSE;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2012-10-23 02:33:30 +04:00
|
|
|
|
window->OnContainerFocusInEvent(event);
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return FALSE;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
}
|
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static gboolean
|
2007-04-30 04:46:47 +04:00
|
|
|
|
focus_out_event_cb(GtkWidget *widget, GdkEventFocus *event)
|
2002-08-10 20:18:44 +04:00
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> window = get_window_for_gtk_widget(widget);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (!window)
|
|
|
|
|
return FALSE;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2012-10-23 02:33:30 +04:00
|
|
|
|
window->OnContainerFocusOutEvent(event);
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return FALSE;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
}
|
|
|
|
|
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#ifdef MOZ_X11
|
2010-06-18 05:15:03 +04:00
|
|
|
|
// For long-lived popup windows that don't really take focus themselves but
|
|
|
|
|
// may have elements that accept keyboard input when the parent window is
|
|
|
|
|
// active, focus is handled specially. These windows include noautohide
|
|
|
|
|
// panels. (This special handling is not necessary for temporary popups where
|
|
|
|
|
// the keyboard is grabbed.)
|
|
|
|
|
//
|
|
|
|
|
// Mousing over or clicking on these windows should not cause them to steal
|
|
|
|
|
// focus from their parent windows, so, the input field of WM_HINTS is set to
|
|
|
|
|
// False to request that the window manager not set the input focus to this
|
|
|
|
|
// window. http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.7
|
|
|
|
|
//
|
|
|
|
|
// However, these windows can still receive WM_TAKE_FOCUS messages from the
|
|
|
|
|
// window manager, so they can still detect when the user has indicated that
|
|
|
|
|
// they wish to direct keyboard input at these windows. When the window
|
|
|
|
|
// manager offers focus to these windows (after a mouse over or click, for
|
|
|
|
|
// example), a request to make the parent window active is issued. When the
|
|
|
|
|
// parent window becomes active, keyboard events will be received.
|
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static GdkFilterReturn
|
2010-06-18 05:15:03 +04:00
|
|
|
|
popup_take_focus_filter(GdkXEvent *gdk_xevent,
|
|
|
|
|
GdkEvent *event,
|
|
|
|
|
gpointer data)
|
|
|
|
|
{
|
|
|
|
|
XEvent* xevent = static_cast<XEvent*>(gdk_xevent);
|
|
|
|
|
if (xevent->type != ClientMessage)
|
|
|
|
|
return GDK_FILTER_CONTINUE;
|
|
|
|
|
|
|
|
|
|
XClientMessageEvent& xclient = xevent->xclient;
|
|
|
|
|
if (xclient.message_type != gdk_x11_get_xatom_by_name("WM_PROTOCOLS"))
|
|
|
|
|
return GDK_FILTER_CONTINUE;
|
|
|
|
|
|
|
|
|
|
Atom atom = xclient.data.l[0];
|
|
|
|
|
if (atom != gdk_x11_get_xatom_by_name("WM_TAKE_FOCUS"))
|
|
|
|
|
return GDK_FILTER_CONTINUE;
|
|
|
|
|
|
|
|
|
|
guint32 timestamp = xclient.data.l[1];
|
|
|
|
|
|
|
|
|
|
GtkWidget* widget = get_gtk_widget_for_gdk_window(event->any.window);
|
|
|
|
|
if (!widget)
|
|
|
|
|
return GDK_FILTER_CONTINUE;
|
|
|
|
|
|
|
|
|
|
GtkWindow* parent = gtk_window_get_transient_for(GTK_WINDOW(widget));
|
|
|
|
|
if (!parent)
|
|
|
|
|
return GDK_FILTER_CONTINUE;
|
|
|
|
|
|
|
|
|
|
if (gtk_window_is_active(parent))
|
|
|
|
|
return GDK_FILTER_REMOVE; // leave input focus on the parent
|
|
|
|
|
|
2011-09-23 00:58:07 +04:00
|
|
|
|
GdkWindow* parent_window = gtk_widget_get_window(GTK_WIDGET(parent));
|
2010-06-18 05:15:03 +04:00
|
|
|
|
if (!parent_window)
|
|
|
|
|
return GDK_FILTER_CONTINUE;
|
|
|
|
|
|
|
|
|
|
// In case the parent has not been deconified.
|
|
|
|
|
gdk_window_show_unraised(parent_window);
|
|
|
|
|
|
|
|
|
|
// Request focus on the parent window.
|
|
|
|
|
// Use gdk_window_focus rather than gtk_window_present to avoid
|
|
|
|
|
// raising the parent window.
|
|
|
|
|
gdk_window_focus(parent_window, timestamp);
|
|
|
|
|
return GDK_FILTER_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static GdkFilterReturn
|
2007-04-30 04:46:47 +04:00
|
|
|
|
plugin_window_filter_func(GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
|
2002-09-02 09:11:10 +04:00
|
|
|
|
{
|
2011-09-23 00:58:07 +04:00
|
|
|
|
GdkWindow *plugin_window;
|
|
|
|
|
XEvent *xevent;
|
|
|
|
|
Window xeventWindow;
|
2002-09-02 09:11:10 +04:00
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> nswindow = (nsWindow*)data;
|
2002-09-02 09:11:10 +04:00
|
|
|
|
GdkFilterReturn return_val;
|
2004-10-11 08:01:49 +04:00
|
|
|
|
|
2002-09-02 09:11:10 +04:00
|
|
|
|
xevent = (XEvent *)gdk_xevent;
|
|
|
|
|
return_val = GDK_FILTER_CONTINUE;
|
|
|
|
|
|
|
|
|
|
switch (xevent->type)
|
|
|
|
|
{
|
|
|
|
|
case CreateNotify:
|
|
|
|
|
case ReparentNotify:
|
2003-02-17 18:36:37 +03:00
|
|
|
|
if (xevent->type==CreateNotify) {
|
2011-09-23 00:58:07 +04:00
|
|
|
|
xeventWindow = xevent->xcreatewindow.window;
|
2002-09-02 09:11:10 +04:00
|
|
|
|
}
|
|
|
|
|
else {
|
2003-02-17 18:36:37 +03:00
|
|
|
|
if (xevent->xreparent.event != xevent->xreparent.parent)
|
2002-09-02 09:11:10 +04:00
|
|
|
|
break;
|
2011-09-23 00:58:07 +04:00
|
|
|
|
xeventWindow = xevent->xreparent.window;
|
2002-09-02 09:11:10 +04:00
|
|
|
|
}
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2011-09-23 00:58:07 +04:00
|
|
|
|
plugin_window = gdk_window_lookup(xeventWindow);
|
|
|
|
|
#else
|
|
|
|
|
plugin_window = gdk_x11_window_lookup_for_display(
|
|
|
|
|
gdk_x11_lookup_xdisplay(xevent->xcreatewindow.display), xeventWindow);
|
|
|
|
|
#endif
|
2003-02-17 18:36:37 +03:00
|
|
|
|
if (plugin_window) {
|
2009-02-20 05:07:08 +03:00
|
|
|
|
GtkWidget *widget =
|
|
|
|
|
get_gtk_widget_for_gdk_window(plugin_window);
|
2003-02-17 18:36:37 +03:00
|
|
|
|
|
2011-09-23 00:58:07 +04:00
|
|
|
|
// TODO GTK3
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2003-09-16 05:44:41 +04:00
|
|
|
|
if (GTK_IS_XTBIN(widget)) {
|
|
|
|
|
nswindow->SetPluginType(nsWindow::PluginType_NONXEMBED);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2011-09-23 00:58:07 +04:00
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
if(GTK_IS_SOCKET(widget)) {
|
2012-08-02 00:34:08 +04:00
|
|
|
|
if (!g_object_get_data(G_OBJECT(widget), "enable-xt-focus")) {
|
|
|
|
|
nswindow->SetPluginType(nsWindow::PluginType_XEMBED);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2002-09-02 09:11:10 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
2003-09-16 05:44:41 +04:00
|
|
|
|
nswindow->SetPluginType(nsWindow::PluginType_NONXEMBED);
|
2002-09-02 09:11:10 +04:00
|
|
|
|
return_val = GDK_FILTER_REMOVE;
|
|
|
|
|
break;
|
2003-02-17 18:36:37 +03:00
|
|
|
|
case EnterNotify:
|
|
|
|
|
nswindow->SetNonXEmbedPluginFocus();
|
|
|
|
|
break;
|
|
|
|
|
case DestroyNotify:
|
|
|
|
|
gdk_window_remove_filter
|
|
|
|
|
((GdkWindow*)(nswindow->GetNativeData(NS_NATIVE_WINDOW)),
|
|
|
|
|
plugin_window_filter_func,
|
|
|
|
|
nswindow);
|
|
|
|
|
// Currently we consider all plugins are non-xembed and calls
|
|
|
|
|
// LoseNonXEmbedPluginFocus without any checking.
|
|
|
|
|
nswindow->LoseNonXEmbedPluginFocus();
|
|
|
|
|
break;
|
2002-09-02 09:11:10 +04:00
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return return_val;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static GdkFilterReturn
|
2007-04-30 04:46:47 +04:00
|
|
|
|
plugin_client_message_filter(GdkXEvent *gdk_xevent,
|
|
|
|
|
GdkEvent *event,
|
|
|
|
|
gpointer data)
|
2003-02-17 18:36:37 +03:00
|
|
|
|
{
|
|
|
|
|
XEvent *xevent;
|
|
|
|
|
xevent = (XEvent *)gdk_xevent;
|
|
|
|
|
|
|
|
|
|
GdkFilterReturn return_val;
|
|
|
|
|
return_val = GDK_FILTER_CONTINUE;
|
|
|
|
|
|
|
|
|
|
if (!gPluginFocusWindow || xevent->type!=ClientMessage) {
|
|
|
|
|
return return_val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// When WM sends out WM_TAKE_FOCUS, gtk2 will use XSetInputFocus
|
|
|
|
|
// to set the focus to the focus proxy. To prevent this happen
|
|
|
|
|
// while the focus is on the plugin, we filter the WM_TAKE_FOCUS
|
|
|
|
|
// out.
|
2004-10-11 08:01:49 +04:00
|
|
|
|
if (gdk_x11_get_xatom_by_name("WM_PROTOCOLS")
|
2003-02-17 18:36:37 +03:00
|
|
|
|
!= xevent->xclient.message_type) {
|
|
|
|
|
return return_val;
|
|
|
|
|
}
|
2004-10-11 08:01:49 +04:00
|
|
|
|
|
|
|
|
|
if ((Atom) xevent->xclient.data.l[0] ==
|
2003-02-17 18:36:37 +03:00
|
|
|
|
gdk_x11_get_xatom_by_name("WM_TAKE_FOCUS")) {
|
|
|
|
|
// block it from gtk2.0 focus proxy
|
|
|
|
|
return_val = GDK_FILTER_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return return_val;
|
|
|
|
|
}
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#endif /* MOZ_X11 */
|
2003-02-17 18:36:37 +03:00
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static gboolean
|
2007-04-30 04:46:47 +04:00
|
|
|
|
key_press_event_cb(GtkWidget *widget, GdkEventKey *event)
|
2002-08-10 20:18:44 +04:00
|
|
|
|
{
|
2002-08-10 22:21:22 +04:00
|
|
|
|
LOG(("key_press_event_cb\n"));
|
2009-09-17 21:13:45 +04:00
|
|
|
|
|
2012-02-14 00:19:59 +04:00
|
|
|
|
UpdateLastInputEventTime(event);
|
2009-09-17 21:13:45 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
// find the window with focus and dispatch this event to that widget
|
|
|
|
|
nsWindow *window = get_window_for_gtk_widget(widget);
|
|
|
|
|
if (!window)
|
|
|
|
|
return FALSE;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> focusWindow = gFocusWindow ? gFocusWindow : window;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2008-12-15 14:34:05 +03:00
|
|
|
|
#ifdef MOZ_X11
|
|
|
|
|
// Keyboard repeat can cause key press events to queue up when there are
|
|
|
|
|
// slow event handlers (bug 301029). Throttle these events by removing
|
|
|
|
|
// consecutive pending duplicate KeyPress events to the same window.
|
|
|
|
|
// We use the event time of the last one.
|
|
|
|
|
// Note: GDK calls XkbSetDetectableAutorepeat so that KeyRelease events
|
|
|
|
|
// are generated only when the key is physically released.
|
|
|
|
|
#define NS_GDKEVENT_MATCH_MASK 0x1FFF /* GDK_SHIFT_MASK .. GDK_BUTTON5_MASK */
|
|
|
|
|
GdkDisplay* gdkDisplay = gtk_widget_get_display(widget);
|
2015-03-05 05:56:00 +03:00
|
|
|
|
if (GDK_IS_X11_DISPLAY(gdkDisplay)) {
|
|
|
|
|
Display* dpy = GDK_DISPLAY_XDISPLAY(gdkDisplay);
|
|
|
|
|
while (XPending(dpy)) {
|
|
|
|
|
XEvent next_event;
|
|
|
|
|
XPeekEvent(dpy, &next_event);
|
|
|
|
|
GdkWindow* nextGdkWindow =
|
|
|
|
|
gdk_x11_window_lookup_for_display(gdkDisplay, next_event.xany.window);
|
|
|
|
|
if (nextGdkWindow != event->window ||
|
|
|
|
|
next_event.type != KeyPress ||
|
|
|
|
|
next_event.xkey.keycode != event->hardware_keycode ||
|
|
|
|
|
next_event.xkey.state != (event->state & NS_GDKEVENT_MATCH_MASK)) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
XNextEvent(dpy, &next_event);
|
|
|
|
|
event->time = next_event.xkey.time;
|
2008-12-15 14:34:05 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-10-23 02:33:30 +04:00
|
|
|
|
return focusWindow->OnKeyPressEvent(event);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static gboolean
|
2007-04-30 04:46:47 +04:00
|
|
|
|
key_release_event_cb(GtkWidget *widget, GdkEventKey *event)
|
2002-08-10 22:21:22 +04:00
|
|
|
|
{
|
|
|
|
|
LOG(("key_release_event_cb\n"));
|
2009-09-17 21:13:45 +04:00
|
|
|
|
|
2012-02-14 00:19:59 +04:00
|
|
|
|
UpdateLastInputEventTime(event);
|
2009-09-17 21:13:45 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
// find the window with focus and dispatch this event to that widget
|
|
|
|
|
nsWindow *window = get_window_for_gtk_widget(widget);
|
|
|
|
|
if (!window)
|
|
|
|
|
return FALSE;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> focusWindow = gFocusWindow ? gFocusWindow : window;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2012-10-23 02:33:30 +04:00
|
|
|
|
return focusWindow->OnKeyReleaseEvent(event);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2015-08-12 04:35:38 +03:00
|
|
|
|
static gboolean
|
|
|
|
|
property_notify_event_cb(GtkWidget* aWidget, GdkEventProperty* aEvent)
|
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> window = get_window_for_gdk_window(aEvent->window);
|
2015-08-12 04:35:38 +03:00
|
|
|
|
if (!window)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2015-10-09 16:24:48 +03:00
|
|
|
|
return window->OnPropertyNotifyEvent(aWidget, aEvent);
|
2015-08-12 04:35:38 +03:00
|
|
|
|
}
|
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static gboolean
|
2007-04-30 04:46:47 +04:00
|
|
|
|
scroll_event_cb(GtkWidget *widget, GdkEventScroll *event)
|
2002-08-10 22:21:22 +04:00
|
|
|
|
{
|
2007-12-14 10:00:44 +03:00
|
|
|
|
nsWindow *window = GetFirstNSWindowForGDKWindow(event->window);
|
|
|
|
|
if (!window)
|
|
|
|
|
return FALSE;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2012-10-23 02:33:30 +04:00
|
|
|
|
window->OnScrollEvent(event);
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static gboolean
|
2002-08-10 22:21:22 +04:00
|
|
|
|
visibility_notify_event_cb (GtkWidget *widget, GdkEventVisibility *event)
|
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> window = get_window_for_gdk_window(event->window);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (!window)
|
|
|
|
|
return FALSE;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2012-10-23 02:33:30 +04:00
|
|
|
|
window->OnVisibilityNotifyEvent(event);
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2009-11-02 05:03:12 +03:00
|
|
|
|
static void
|
|
|
|
|
hierarchy_changed_cb (GtkWidget *widget,
|
|
|
|
|
GtkWidget *previous_toplevel)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *toplevel = gtk_widget_get_toplevel(widget);
|
|
|
|
|
GdkWindowState old_window_state = GDK_WINDOW_STATE_WITHDRAWN;
|
|
|
|
|
GdkEventWindowState event;
|
|
|
|
|
|
|
|
|
|
event.new_window_state = GDK_WINDOW_STATE_WITHDRAWN;
|
|
|
|
|
|
|
|
|
|
if (GTK_IS_WINDOW(previous_toplevel)) {
|
|
|
|
|
g_signal_handlers_disconnect_by_func(previous_toplevel,
|
|
|
|
|
FuncToGpointer(window_state_event_cb),
|
|
|
|
|
widget);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
GdkWindow *win = gtk_widget_get_window(previous_toplevel);
|
|
|
|
|
if (win) {
|
|
|
|
|
old_window_state = gdk_window_get_state(win);
|
2009-11-02 05:03:12 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (GTK_IS_WINDOW(toplevel)) {
|
|
|
|
|
g_signal_connect_swapped(toplevel, "window-state-event",
|
|
|
|
|
G_CALLBACK(window_state_event_cb), widget);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
GdkWindow *win = gtk_widget_get_window(toplevel);
|
|
|
|
|
if (win) {
|
|
|
|
|
event.new_window_state = gdk_window_get_state(win);
|
2009-11-02 05:03:12 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
event.changed_mask = static_cast<GdkWindowState>
|
|
|
|
|
(old_window_state ^ event.new_window_state);
|
|
|
|
|
|
|
|
|
|
if (event.changed_mask) {
|
|
|
|
|
event.type = GDK_WINDOW_STATE;
|
2013-10-08 22:47:37 +04:00
|
|
|
|
event.window = nullptr;
|
2009-11-02 05:03:12 +03:00
|
|
|
|
event.send_event = TRUE;
|
|
|
|
|
window_state_event_cb(widget, &event);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static gboolean
|
2002-08-10 22:21:22 +04:00
|
|
|
|
window_state_event_cb (GtkWidget *widget, GdkEventWindowState *event)
|
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> window = get_window_for_gtk_widget(widget);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (!window)
|
|
|
|
|
return FALSE;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
window->OnWindowStateEvent(widget, event);
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static void
|
2005-11-29 01:44:33 +03:00
|
|
|
|
theme_changed_cb (GtkSettings *settings, GParamSpec *pspec, nsWindow *data)
|
2004-09-17 10:27:01 +04:00
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> window = data;
|
2007-04-30 04:46:47 +04:00
|
|
|
|
window->ThemeChanged();
|
2004-09-17 10:27:01 +04:00
|
|
|
|
}
|
|
|
|
|
|
2015-04-29 23:29:34 +03:00
|
|
|
|
#if GTK_CHECK_VERSION(3,4,0)
|
|
|
|
|
static gboolean
|
|
|
|
|
touch_event_cb(GtkWidget* aWidget, GdkEventTouch* aEvent)
|
|
|
|
|
{
|
|
|
|
|
UpdateLastInputEventTime(aEvent);
|
|
|
|
|
|
|
|
|
|
nsWindow* window = GetFirstNSWindowForGDKWindow(aEvent->window);
|
|
|
|
|
if (!window) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return window->OnTouchEvent(aEvent);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
// These are all of our drag and drop operations
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
void
|
2013-10-01 11:23:02 +04:00
|
|
|
|
nsWindow::InitDragEvent(WidgetDragEvent &aEvent)
|
2002-08-10 22:21:22 +04:00
|
|
|
|
{
|
|
|
|
|
// set the keyboard modifiers
|
2012-02-22 11:34:31 +04:00
|
|
|
|
guint modifierState = KeymapWrapper::GetCurrentModifierState();
|
|
|
|
|
KeymapWrapper::InitInputEvent(aEvent, modifierState);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static gboolean
|
2002-08-10 22:21:22 +04:00
|
|
|
|
drag_motion_event_cb(GtkWidget *aWidget,
|
|
|
|
|
GdkDragContext *aDragContext,
|
|
|
|
|
gint aX,
|
|
|
|
|
gint aY,
|
|
|
|
|
guint aTime,
|
|
|
|
|
gpointer aData)
|
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> window = get_window_for_gtk_widget(aWidget);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (!window)
|
|
|
|
|
return FALSE;
|
2004-10-11 08:01:49 +04:00
|
|
|
|
|
2012-04-19 10:18:31 +04:00
|
|
|
|
// figure out which internal widget this drag motion actually happened on
|
|
|
|
|
nscoord retx = 0;
|
|
|
|
|
nscoord rety = 0;
|
|
|
|
|
|
|
|
|
|
GdkWindow *innerWindow =
|
|
|
|
|
get_inner_gdk_window(gtk_widget_get_window(aWidget), aX, aY,
|
|
|
|
|
&retx, &rety);
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> innerMostWindow = get_window_for_gdk_window(innerWindow);
|
2012-04-19 10:18:31 +04:00
|
|
|
|
|
|
|
|
|
if (!innerMostWindow) {
|
|
|
|
|
innerMostWindow = window;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LOGDRAG(("nsWindow drag-motion signal for %p\n", (void*)innerMostWindow));
|
|
|
|
|
|
2015-10-26 23:33:13 +03:00
|
|
|
|
LayoutDeviceIntPoint point = window->GdkPointToDevicePixels({ retx, rety });
|
|
|
|
|
|
2012-04-19 10:18:31 +04:00
|
|
|
|
return nsDragService::GetInstance()->
|
|
|
|
|
ScheduleMotionEvent(innerMostWindow, aDragContext,
|
2015-10-26 23:33:13 +03:00
|
|
|
|
point, aTime);
|
2002-08-10 20:18:44 +04:00
|
|
|
|
}
|
2011-05-17 17:55:16 +04:00
|
|
|
|
|
|
|
|
|
static void
|
2002-08-10 22:21:22 +04:00
|
|
|
|
drag_leave_event_cb(GtkWidget *aWidget,
|
|
|
|
|
GdkDragContext *aDragContext,
|
|
|
|
|
guint aTime,
|
|
|
|
|
gpointer aData)
|
2002-08-10 20:18:44 +04:00
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> window = get_window_for_gtk_widget(aWidget);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (!window)
|
|
|
|
|
return;
|
2005-03-16 03:40:21 +03:00
|
|
|
|
|
2012-04-19 10:18:31 +04:00
|
|
|
|
nsDragService *dragService = nsDragService::GetInstance();
|
|
|
|
|
|
|
|
|
|
nsWindow *mostRecentDragWindow = dragService->GetMostRecentDestWindow();
|
|
|
|
|
if (!mostRecentDragWindow) {
|
2012-04-19 10:18:31 +04:00
|
|
|
|
// This can happen when the target will not accept a drop. A GTK drag
|
|
|
|
|
// source sends the leave message to the destination before the
|
|
|
|
|
// drag-failed signal on the source widget, but the leave message goes
|
|
|
|
|
// via the X server, and so doesn't get processed at least until the
|
|
|
|
|
// event loop runs again.
|
2012-04-19 10:18:31 +04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GtkWidget *mozContainer = mostRecentDragWindow->GetMozContainerWidget();
|
|
|
|
|
if (aWidget != mozContainer)
|
|
|
|
|
{
|
|
|
|
|
// When the drag moves between widgets, GTK can send leave signal for
|
|
|
|
|
// the old widget after the motion or drop signal for the new widget.
|
|
|
|
|
// We'll send the leave event when the motion or drop event is run.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LOGDRAG(("nsWindow drag-leave signal for %p\n",
|
|
|
|
|
(void*)mostRecentDragWindow));
|
|
|
|
|
|
|
|
|
|
dragService->ScheduleLeaveEvent();
|
2002-08-10 20:18:44 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static gboolean
|
2002-08-10 22:21:22 +04:00
|
|
|
|
drag_drop_event_cb(GtkWidget *aWidget,
|
|
|
|
|
GdkDragContext *aDragContext,
|
|
|
|
|
gint aX,
|
|
|
|
|
gint aY,
|
|
|
|
|
guint aTime,
|
2011-05-19 14:51:11 +04:00
|
|
|
|
gpointer aData)
|
2002-08-10 20:18:44 +04:00
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> window = get_window_for_gtk_widget(aWidget);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (!window)
|
|
|
|
|
return FALSE;
|
2004-10-11 08:01:49 +04:00
|
|
|
|
|
2012-04-19 10:18:31 +04:00
|
|
|
|
// figure out which internal widget this drag motion actually happened on
|
|
|
|
|
nscoord retx = 0;
|
|
|
|
|
nscoord rety = 0;
|
|
|
|
|
|
|
|
|
|
GdkWindow *innerWindow =
|
|
|
|
|
get_inner_gdk_window(gtk_widget_get_window(aWidget), aX, aY,
|
|
|
|
|
&retx, &rety);
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> innerMostWindow = get_window_for_gdk_window(innerWindow);
|
2012-04-19 10:18:31 +04:00
|
|
|
|
|
|
|
|
|
if (!innerMostWindow) {
|
|
|
|
|
innerMostWindow = window;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LOGDRAG(("nsWindow drag-drop signal for %p\n", (void*)innerMostWindow));
|
|
|
|
|
|
2015-10-26 23:33:13 +03:00
|
|
|
|
LayoutDeviceIntPoint point = window->GdkPointToDevicePixels({ retx, rety });
|
|
|
|
|
|
2012-04-19 10:18:31 +04:00
|
|
|
|
return nsDragService::GetInstance()->
|
|
|
|
|
ScheduleDropEvent(innerMostWindow, aDragContext,
|
2015-10-26 23:33:13 +03:00
|
|
|
|
point, aTime);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
}
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static void
|
2007-04-30 04:46:47 +04:00
|
|
|
|
drag_data_received_event_cb(GtkWidget *aWidget,
|
|
|
|
|
GdkDragContext *aDragContext,
|
|
|
|
|
gint aX,
|
|
|
|
|
gint aY,
|
|
|
|
|
GtkSelectionData *aSelectionData,
|
|
|
|
|
guint aInfo,
|
|
|
|
|
guint aTime,
|
|
|
|
|
gpointer aData)
|
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<nsWindow> window = get_window_for_gtk_widget(aWidget);
|
2002-08-10 22:21:22 +04:00
|
|
|
|
if (!window)
|
|
|
|
|
return;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
window->OnDragDataReceivedEvent(aWidget,
|
|
|
|
|
aDragContext,
|
|
|
|
|
aX, aY,
|
|
|
|
|
aSelectionData,
|
|
|
|
|
aInfo, aTime, aData);
|
|
|
|
|
}
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static nsresult
|
2002-08-10 22:21:22 +04:00
|
|
|
|
initialize_prefs(void)
|
|
|
|
|
{
|
2011-05-28 11:03:00 +04:00
|
|
|
|
gRaiseWindows =
|
2011-09-29 10:19:26 +04:00
|
|
|
|
Preferences::GetBool("mozilla.widget.raise-on-setfocus", true);
|
2008-09-18 01:15:52 +04:00
|
|
|
|
|
2002-08-10 22:21:22 +04:00
|
|
|
|
return NS_OK;
|
2002-08-10 20:18:44 +04:00
|
|
|
|
}
|
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static GdkWindow *
|
2002-08-10 22:21:22 +04:00
|
|
|
|
get_inner_gdk_window (GdkWindow *aWindow,
|
|
|
|
|
gint x, gint y,
|
|
|
|
|
gint *retx, gint *rety)
|
2002-08-10 20:18:44 +04:00
|
|
|
|
{
|
2011-09-23 00:58:07 +04:00
|
|
|
|
gint cx, cy, cw, ch;
|
2011-05-11 17:12:15 +04:00
|
|
|
|
GList *children = gdk_window_peek_children(aWindow);
|
|
|
|
|
for (GList *child = g_list_last(children);
|
|
|
|
|
child;
|
|
|
|
|
child = g_list_previous(child)) {
|
|
|
|
|
GdkWindow *childWindow = (GdkWindow *) child->data;
|
|
|
|
|
if (get_window_for_gdk_window(childWindow)) {
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if (MOZ_WIDGET_GTK == 2)
|
2013-10-08 22:47:37 +04:00
|
|
|
|
gdk_window_get_geometry(childWindow, &cx, &cy, &cw, &ch, nullptr);
|
2011-09-23 00:58:07 +04:00
|
|
|
|
#else
|
|
|
|
|
gdk_window_get_geometry(childWindow, &cx, &cy, &cw, &ch);
|
|
|
|
|
#endif
|
2011-05-11 17:12:15 +04:00
|
|
|
|
if ((cx < x) && (x < (cx + cw)) &&
|
|
|
|
|
(cy < y) && (y < (cy + ch)) &&
|
|
|
|
|
gdk_window_is_visible(childWindow)) {
|
|
|
|
|
return get_inner_gdk_window(childWindow,
|
|
|
|
|
x - cx, y - cy,
|
|
|
|
|
retx, rety);
|
2002-08-10 20:18:44 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*retx = x;
|
|
|
|
|
*rety = y;
|
|
|
|
|
return aWindow;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
|
static inline bool
|
2013-10-01 11:22:58 +04:00
|
|
|
|
is_context_menu_key(const WidgetKeyboardEvent& aKeyEvent)
|
2002-12-15 01:23:06 +03:00
|
|
|
|
{
|
2012-04-25 07:00:02 +04:00
|
|
|
|
return ((aKeyEvent.keyCode == NS_VK_F10 && aKeyEvent.IsShift() &&
|
|
|
|
|
!aKeyEvent.IsControl() && !aKeyEvent.IsMeta() &&
|
|
|
|
|
!aKeyEvent.IsAlt()) ||
|
|
|
|
|
(aKeyEvent.keyCode == NS_VK_CONTEXT_MENU && !aKeyEvent.IsShift() &&
|
|
|
|
|
!aKeyEvent.IsControl() && !aKeyEvent.IsMeta() &&
|
|
|
|
|
!aKeyEvent.IsAlt()));
|
2002-12-15 01:23:06 +03:00
|
|
|
|
}
|
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static int
|
2003-09-30 18:58:39 +04:00
|
|
|
|
is_parent_ungrab_enter(GdkEventCrossing *aEvent)
|
|
|
|
|
{
|
|
|
|
|
return (GDK_CROSSING_UNGRAB == aEvent->mode) &&
|
|
|
|
|
((GDK_NOTIFY_ANCESTOR == aEvent->detail) ||
|
|
|
|
|
(GDK_NOTIFY_VIRTUAL == aEvent->detail));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-17 17:55:16 +04:00
|
|
|
|
static int
|
2003-09-30 18:58:39 +04:00
|
|
|
|
is_parent_grab_leave(GdkEventCrossing *aEvent)
|
|
|
|
|
{
|
|
|
|
|
return (GDK_CROSSING_GRAB == aEvent->mode) &&
|
|
|
|
|
((GDK_NOTIFY_ANCESTOR == aEvent->detail) ||
|
|
|
|
|
(GDK_NOTIFY_VIRTUAL == aEvent->detail));
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-08 11:42:34 +04:00
|
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
|
void
|
2003-04-23 09:28:41 +04:00
|
|
|
|
nsWindow::CreateRootAccessible()
|
2002-05-08 11:42:34 +04:00
|
|
|
|
{
|
2003-04-23 09:28:41 +04:00
|
|
|
|
if (mIsTopLevel && !mRootAccessible) {
|
2011-05-28 13:26:56 +04:00
|
|
|
|
LOG(("nsWindow:: Create Toplevel Accessibility\n"));
|
2013-06-27 19:03:58 +04:00
|
|
|
|
mRootAccessible = GetRootAccessible();
|
2002-05-08 11:42:34 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-12 10:47:35 +04:00
|
|
|
|
void
|
2012-08-22 19:56:38 +04:00
|
|
|
|
nsWindow::DispatchEventToRootAccessible(uint32_t aEventType)
|
2002-05-08 11:42:34 +04:00
|
|
|
|
{
|
2012-01-05 05:54:17 +04:00
|
|
|
|
if (!a11y::ShouldA11yBeEnabled()) {
|
2010-05-12 10:47:35 +04:00
|
|
|
|
return;
|
|
|
|
|
}
|
2002-05-08 11:42:34 +04:00
|
|
|
|
|
2010-05-12 10:47:35 +04:00
|
|
|
|
nsCOMPtr<nsIAccessibilityService> accService =
|
2014-07-28 19:43:00 +04:00
|
|
|
|
services::GetAccessibilityService();
|
2010-05-12 10:47:35 +04:00
|
|
|
|
if (!accService) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2010-05-12 13:14:50 +04:00
|
|
|
|
|
2010-09-23 07:35:39 +04:00
|
|
|
|
// Get the root document accessible and fire event to it.
|
2013-06-27 19:03:58 +04:00
|
|
|
|
a11y::Accessible* acc = GetRootAccessible();
|
2010-09-23 07:35:39 +04:00
|
|
|
|
if (acc) {
|
|
|
|
|
accService->FireAccessibleEvent(aEventType, acc);
|
2010-05-12 10:47:35 +04:00
|
|
|
|
}
|
2002-05-08 11:42:34 +04:00
|
|
|
|
}
|
|
|
|
|
|
2004-03-25 21:36:08 +03:00
|
|
|
|
void
|
2008-10-19 05:13:27 +04:00
|
|
|
|
nsWindow::DispatchActivateEventAccessible(void)
|
2004-03-25 21:36:08 +03:00
|
|
|
|
{
|
2010-05-12 10:47:35 +04:00
|
|
|
|
DispatchEventToRootAccessible(nsIAccessibleEvent::EVENT_WINDOW_ACTIVATE);
|
2006-07-13 09:42:32 +04:00
|
|
|
|
}
|
2004-03-25 21:36:08 +03:00
|
|
|
|
|
|
|
|
|
void
|
2008-10-19 05:13:27 +04:00
|
|
|
|
nsWindow::DispatchDeactivateEventAccessible(void)
|
2004-03-25 21:36:08 +03:00
|
|
|
|
{
|
2010-05-12 10:47:35 +04:00
|
|
|
|
DispatchEventToRootAccessible(nsIAccessibleEvent::EVENT_WINDOW_DEACTIVATE);
|
2004-03-25 21:36:08 +03:00
|
|
|
|
}
|
2008-10-19 05:13:27 +04:00
|
|
|
|
|
2011-03-26 19:06:00 +03:00
|
|
|
|
void
|
|
|
|
|
nsWindow::DispatchMaximizeEventAccessible(void)
|
|
|
|
|
{
|
|
|
|
|
DispatchEventToRootAccessible(nsIAccessibleEvent::EVENT_WINDOW_MAXIMIZE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nsWindow::DispatchMinimizeEventAccessible(void)
|
|
|
|
|
{
|
|
|
|
|
DispatchEventToRootAccessible(nsIAccessibleEvent::EVENT_WINDOW_MINIMIZE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nsWindow::DispatchRestoreEventAccessible(void)
|
|
|
|
|
{
|
|
|
|
|
DispatchEventToRootAccessible(nsIAccessibleEvent::EVENT_WINDOW_RESTORE);
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-29 08:51:21 +04:00
|
|
|
|
#endif /* #ifdef ACCESSIBILITY */
|
2002-05-08 11:42:34 +04:00
|
|
|
|
|
2001-12-07 08:23:56 +03:00
|
|
|
|
// nsChildWindow class
|
|
|
|
|
|
|
|
|
|
nsChildWindow::nsChildWindow()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsChildWindow::~nsChildWindow()
|
|
|
|
|
{
|
|
|
|
|
}
|
2002-08-10 20:18:44 +04:00
|
|
|
|
|
2015-01-28 09:27:31 +03:00
|
|
|
|
nsresult
|
|
|
|
|
nsWindow::NotifyIMEInternal(const IMENotification& aIMENotification)
|
2013-03-06 10:14:34 +04:00
|
|
|
|
{
|
2015-07-27 02:23:04 +03:00
|
|
|
|
if (MOZ_UNLIKELY(!mIMContext)) {
|
2014-09-26 04:05:13 +04:00
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
2013-03-06 10:14:34 +04:00
|
|
|
|
}
|
2014-02-18 04:00:15 +04:00
|
|
|
|
switch (aIMENotification.mMessage) {
|
2013-03-06 10:14:34 +04:00
|
|
|
|
case REQUEST_TO_COMMIT_COMPOSITION:
|
|
|
|
|
case REQUEST_TO_CANCEL_COMPOSITION:
|
2015-07-27 02:23:04 +03:00
|
|
|
|
return mIMContext->EndIMEComposition(this);
|
2013-03-06 10:14:34 +04:00
|
|
|
|
case NOTIFY_IME_OF_FOCUS:
|
2015-07-27 02:23:04 +03:00
|
|
|
|
mIMContext->OnFocusChangeInGecko(true);
|
2013-03-06 10:14:34 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
case NOTIFY_IME_OF_BLUR:
|
2015-07-27 02:23:04 +03:00
|
|
|
|
mIMContext->OnFocusChangeInGecko(false);
|
2013-03-06 10:14:34 +04:00
|
|
|
|
return NS_OK;
|
2015-06-11 13:50:15 +03:00
|
|
|
|
case NOTIFY_IME_OF_POSITION_CHANGE:
|
2015-07-27 02:23:04 +03:00
|
|
|
|
mIMContext->OnLayoutChange();
|
2015-06-11 13:50:15 +03:00
|
|
|
|
return NS_OK;
|
2014-01-16 14:04:48 +04:00
|
|
|
|
case NOTIFY_IME_OF_COMPOSITION_UPDATE:
|
2015-07-27 02:23:04 +03:00
|
|
|
|
mIMContext->OnUpdateComposition();
|
2014-01-16 14:04:48 +04:00
|
|
|
|
return NS_OK;
|
2014-09-26 04:05:13 +04:00
|
|
|
|
case NOTIFY_IME_OF_SELECTION_CHANGE:
|
2015-07-27 02:23:04 +03:00
|
|
|
|
mIMContext->OnSelectionChange(this, aIMENotification);
|
2014-09-26 04:05:13 +04:00
|
|
|
|
return NS_OK;
|
2013-03-06 10:14:34 +04:00
|
|
|
|
default:
|
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
2006-03-14 09:07:54 +03:00
|
|
|
|
}
|
|
|
|
|
|
2011-11-27 15:51:52 +04:00
|
|
|
|
NS_IMETHODIMP_(void)
|
|
|
|
|
nsWindow::SetInputContext(const InputContext& aContext,
|
|
|
|
|
const InputContextAction& aAction)
|
2006-03-14 09:07:54 +03:00
|
|
|
|
{
|
2015-07-27 02:23:04 +03:00
|
|
|
|
if (!mIMContext) {
|
2011-11-27 15:51:52 +04:00
|
|
|
|
return;
|
|
|
|
|
}
|
2015-07-27 02:23:04 +03:00
|
|
|
|
mIMContext->SetInputContext(this, &aContext, &aAction);
|
2006-03-14 09:07:54 +03:00
|
|
|
|
}
|
|
|
|
|
|
2011-11-27 15:51:52 +04:00
|
|
|
|
NS_IMETHODIMP_(InputContext)
|
|
|
|
|
nsWindow::GetInputContext()
|
2006-03-14 09:07:54 +03:00
|
|
|
|
{
|
2011-11-27 15:51:52 +04:00
|
|
|
|
InputContext context;
|
2015-07-27 02:23:04 +03:00
|
|
|
|
if (!mIMContext) {
|
2011-11-27 15:51:53 +04:00
|
|
|
|
context.mIMEState.mEnabled = IMEState::DISABLED;
|
|
|
|
|
context.mIMEState.mOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
|
2012-10-27 03:35:21 +04:00
|
|
|
|
// If IME context isn't available on this widget, we should set |this|
|
|
|
|
|
// instead of nullptr since nullptr means that the platform has only one
|
|
|
|
|
// context per process.
|
|
|
|
|
context.mNativeIMEContext = this;
|
2011-11-27 15:51:52 +04:00
|
|
|
|
} else {
|
2015-07-27 02:23:04 +03:00
|
|
|
|
context = mIMContext->GetInputContext();
|
|
|
|
|
context.mNativeIMEContext = mIMContext;
|
2010-03-19 07:21:16 +03:00
|
|
|
|
}
|
2011-11-27 15:51:52 +04:00
|
|
|
|
return context;
|
2006-03-14 09:07:54 +03:00
|
|
|
|
}
|
|
|
|
|
|
2014-09-26 04:05:13 +04:00
|
|
|
|
nsIMEUpdatePreference
|
|
|
|
|
nsWindow::GetIMEUpdatePreference()
|
|
|
|
|
{
|
2015-08-06 09:57:58 +03:00
|
|
|
|
if (!mIMContext) {
|
|
|
|
|
return nsIMEUpdatePreference();
|
|
|
|
|
}
|
|
|
|
|
return mIMContext->GetIMEUpdatePreference();
|
2014-09-26 04:05:13 +04:00
|
|
|
|
}
|
|
|
|
|
|
2014-11-22 17:39:04 +03:00
|
|
|
|
bool
|
|
|
|
|
nsWindow::ExecuteNativeKeyBindingRemapped(NativeKeyBindingsType aType,
|
|
|
|
|
const WidgetKeyboardEvent& aEvent,
|
|
|
|
|
DoCommandCallback aCallback,
|
|
|
|
|
void* aCallbackData,
|
|
|
|
|
uint32_t aGeckoKeyCode,
|
|
|
|
|
uint32_t aNativeKeyCode)
|
|
|
|
|
{
|
|
|
|
|
WidgetKeyboardEvent modifiedEvent(aEvent);
|
|
|
|
|
modifiedEvent.keyCode = aGeckoKeyCode;
|
|
|
|
|
static_cast<GdkEventKey*>(modifiedEvent.mNativeKeyEvent)->keyval =
|
|
|
|
|
aNativeKeyCode;
|
|
|
|
|
|
|
|
|
|
NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType);
|
|
|
|
|
return keyBindings->Execute(modifiedEvent, aCallback, aCallbackData);
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-14 17:13:31 +04:00
|
|
|
|
NS_IMETHODIMP_(bool)
|
|
|
|
|
nsWindow::ExecuteNativeKeyBinding(NativeKeyBindingsType aType,
|
|
|
|
|
const WidgetKeyboardEvent& aEvent,
|
|
|
|
|
DoCommandCallback aCallback,
|
|
|
|
|
void* aCallbackData)
|
|
|
|
|
{
|
2014-11-22 17:39:04 +03:00
|
|
|
|
if (aEvent.keyCode >= nsIDOMKeyEvent::DOM_VK_LEFT &&
|
|
|
|
|
aEvent.keyCode <= nsIDOMKeyEvent::DOM_VK_DOWN) {
|
|
|
|
|
|
|
|
|
|
// Check if we're targeting content with vertical writing mode,
|
|
|
|
|
// and if so remap the arrow keys.
|
2015-09-10 04:40:05 +03:00
|
|
|
|
WidgetQueryContentEvent query(true, eQuerySelectedText, this);
|
2014-11-22 17:39:04 +03:00
|
|
|
|
nsEventStatus status;
|
|
|
|
|
DispatchEvent(&query, status);
|
|
|
|
|
|
|
|
|
|
if (query.mSucceeded && query.mReply.mWritingMode.IsVertical()) {
|
|
|
|
|
uint32_t geckoCode = 0;
|
|
|
|
|
uint32_t gdkCode = 0;
|
|
|
|
|
switch (aEvent.keyCode) {
|
|
|
|
|
case nsIDOMKeyEvent::DOM_VK_LEFT:
|
|
|
|
|
if (query.mReply.mWritingMode.IsVerticalLR()) {
|
|
|
|
|
geckoCode = nsIDOMKeyEvent::DOM_VK_UP;
|
|
|
|
|
gdkCode = GDK_Up;
|
|
|
|
|
} else {
|
|
|
|
|
geckoCode = nsIDOMKeyEvent::DOM_VK_DOWN;
|
|
|
|
|
gdkCode = GDK_Down;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case nsIDOMKeyEvent::DOM_VK_RIGHT:
|
|
|
|
|
if (query.mReply.mWritingMode.IsVerticalLR()) {
|
|
|
|
|
geckoCode = nsIDOMKeyEvent::DOM_VK_DOWN;
|
|
|
|
|
gdkCode = GDK_Down;
|
|
|
|
|
} else {
|
|
|
|
|
geckoCode = nsIDOMKeyEvent::DOM_VK_UP;
|
|
|
|
|
gdkCode = GDK_Up;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case nsIDOMKeyEvent::DOM_VK_UP:
|
|
|
|
|
geckoCode = nsIDOMKeyEvent::DOM_VK_LEFT;
|
|
|
|
|
gdkCode = GDK_Left;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case nsIDOMKeyEvent::DOM_VK_DOWN:
|
|
|
|
|
geckoCode = nsIDOMKeyEvent::DOM_VK_RIGHT;
|
|
|
|
|
gdkCode = GDK_Right;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ExecuteNativeKeyBindingRemapped(aType, aEvent, aCallback,
|
|
|
|
|
aCallbackData,
|
|
|
|
|
geckoCode, gdkCode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-14 17:13:32 +04:00
|
|
|
|
NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType);
|
2014-03-14 17:13:32 +04:00
|
|
|
|
return keyBindings->Execute(aEvent, aCallback, aCallbackData);
|
2014-03-14 17:13:31 +04:00
|
|
|
|
}
|
|
|
|
|
|
2007-06-16 23:19:46 +04:00
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 19:56:38 +04:00
|
|
|
|
nsWindow::GetToggledKeyState(uint32_t aKeyCode, bool* aLEDState)
|
2007-06-16 23:19:46 +04:00
|
|
|
|
{
|
|
|
|
|
NS_ENSURE_ARG_POINTER(aLEDState);
|
|
|
|
|
|
2012-02-22 11:34:31 +04:00
|
|
|
|
KeymapWrapper::Modifiers modifier;
|
2007-06-16 23:19:46 +04:00
|
|
|
|
switch (aKeyCode) {
|
2012-02-22 11:34:31 +04:00
|
|
|
|
case NS_VK_CAPS_LOCK: modifier = KeymapWrapper::CAPS_LOCK; break;
|
|
|
|
|
case NS_VK_NUM_LOCK: modifier = KeymapWrapper::NUM_LOCK; break;
|
|
|
|
|
case NS_VK_SCROLL_LOCK: modifier = KeymapWrapper::SCROLL_LOCK; break;
|
|
|
|
|
default: return NS_ERROR_INVALID_ARG;
|
2007-06-16 23:19:46 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-02-22 11:34:31 +04:00
|
|
|
|
*aLEDState =
|
|
|
|
|
KeymapWrapper::AreModifiersCurrentlyActive(modifier);
|
2007-06-16 23:19:46 +04:00
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-23 17:21:35 +04:00
|
|
|
|
#if defined(MOZ_X11) && (MOZ_WIDGET_GTK == 2)
|
2008-06-18 13:20:29 +04:00
|
|
|
|
/* static */ already_AddRefed<gfxASurface>
|
|
|
|
|
nsWindow::GetSurfaceForGdkDrawable(GdkDrawable* aDrawable,
|
2009-01-15 06:27:09 +03:00
|
|
|
|
const nsIntSize& aSize)
|
2008-06-18 13:20:29 +04:00
|
|
|
|
{
|
|
|
|
|
GdkVisual* visual = gdk_drawable_get_visual(aDrawable);
|
2010-07-02 07:55:24 +04:00
|
|
|
|
Screen* xScreen =
|
|
|
|
|
gdk_x11_screen_get_xscreen(gdk_drawable_get_screen(aDrawable));
|
|
|
|
|
Display* xDisplay = DisplayOfScreen(xScreen);
|
2008-06-18 13:20:29 +04:00
|
|
|
|
Drawable xDrawable = gdk_x11_drawable_get_xid(aDrawable);
|
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<gfxASurface> result;
|
2008-09-18 01:15:52 +04:00
|
|
|
|
|
|
|
|
|
if (visual) {
|
|
|
|
|
Visual* xVisual = gdk_x11_visual_get_xvisual(visual);
|
|
|
|
|
|
|
|
|
|
result = new gfxXlibSurface(xDisplay, xDrawable, xVisual,
|
2015-09-23 21:49:05 +03:00
|
|
|
|
IntSize(aSize.width, aSize.height));
|
2008-09-18 01:15:52 +04:00
|
|
|
|
} else {
|
|
|
|
|
// no visual? we must be using an xrender format. Find a format
|
|
|
|
|
// for this depth.
|
2013-10-08 22:47:37 +04:00
|
|
|
|
XRenderPictFormat *pf = nullptr;
|
2008-09-18 01:15:52 +04:00
|
|
|
|
switch (gdk_drawable_get_depth(aDrawable)) {
|
|
|
|
|
case 32:
|
|
|
|
|
pf = XRenderFindStandardFormat(xDisplay, PictStandardARGB32);
|
|
|
|
|
break;
|
|
|
|
|
case 24:
|
|
|
|
|
pf = XRenderFindStandardFormat(xDisplay, PictStandardRGB24);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
NS_ERROR("Don't know how to handle the given depth!");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-02 07:55:24 +04:00
|
|
|
|
result = new gfxXlibSurface(xScreen, xDrawable, pf,
|
2015-09-23 21:49:05 +03:00
|
|
|
|
IntSize(aSize.width, aSize.height));
|
2008-09-18 01:15:52 +04:00
|
|
|
|
}
|
|
|
|
|
|
2013-04-22 15:15:59 +04:00
|
|
|
|
return result.forget();
|
2008-06-18 13:20:29 +04:00
|
|
|
|
}
|
2008-08-07 00:48:55 +04:00
|
|
|
|
#endif
|
2008-06-18 13:20:29 +04:00
|
|
|
|
|
2015-06-17 17:00:52 +03:00
|
|
|
|
already_AddRefed<DrawTarget>
|
2015-09-15 23:46:39 +03:00
|
|
|
|
nsWindow::GetDrawTarget(const nsIntRegion& aRegion)
|
2013-07-09 08:21:05 +04:00
|
|
|
|
{
|
2015-09-15 23:46:39 +03:00
|
|
|
|
if (!mGdkWindow) {
|
2013-07-09 08:21:05 +04:00
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-15 23:46:39 +03:00
|
|
|
|
nsIntRect bounds = aRegion.GetBounds();
|
|
|
|
|
IntSize size(bounds.XMost(), bounds.YMost());
|
2013-07-09 08:21:05 +04:00
|
|
|
|
if (size.width <= 0 || size.height <= 0) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<DrawTarget> dt;
|
2015-09-15 23:46:39 +03:00
|
|
|
|
|
|
|
|
|
#ifdef MOZ_X11
|
|
|
|
|
# ifdef MOZ_HAVE_SHMIMAGE
|
|
|
|
|
if (nsShmImage::UseShm()) {
|
|
|
|
|
dt = nsShmImage::EnsureShmImage(size,
|
|
|
|
|
mXDisplay, mXVisual, mXDepth,
|
|
|
|
|
mShmImage);
|
|
|
|
|
}
|
|
|
|
|
# endif // MOZ_HAVE_SHMIMAGE
|
|
|
|
|
if (!dt) {
|
2015-10-18 08:24:48 +03:00
|
|
|
|
RefPtr<gfxXlibSurface> surf = new gfxXlibSurface(mXDisplay, mXWindow, mXVisual, size);
|
2015-09-15 23:46:39 +03:00
|
|
|
|
if (!surf->CairoStatus()) {
|
|
|
|
|
dt = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surf.get(), surf->GetSize());
|
|
|
|
|
}
|
2015-05-01 21:08:04 +03:00
|
|
|
|
}
|
2015-09-15 23:46:39 +03:00
|
|
|
|
#endif // MOZ_X11
|
|
|
|
|
|
|
|
|
|
return dt.forget();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
already_AddRefed<DrawTarget>
|
|
|
|
|
nsWindow::StartRemoteDrawingInRegion(nsIntRegion& aInvalidRegion)
|
|
|
|
|
{
|
|
|
|
|
return GetDrawTarget(aInvalidRegion);
|
2013-07-09 08:21:05 +04:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-01 21:08:04 +03:00
|
|
|
|
void
|
|
|
|
|
nsWindow::EndRemoteDrawingInRegion(DrawTarget* aDrawTarget, nsIntRegion& aInvalidRegion)
|
2014-06-02 11:36:00 +04:00
|
|
|
|
{
|
2015-05-01 21:08:04 +03:00
|
|
|
|
#ifdef MOZ_X11
|
|
|
|
|
# ifdef MOZ_HAVE_SHMIMAGE
|
2015-08-06 18:02:03 +03:00
|
|
|
|
if (!mGdkWindow || !mShmImage) {
|
2015-05-01 21:08:04 +03:00
|
|
|
|
return;
|
2015-08-06 18:02:03 +03:00
|
|
|
|
}
|
2015-05-01 21:08:04 +03:00
|
|
|
|
|
2015-09-15 23:46:39 +03:00
|
|
|
|
mShmImage->Put(mXDisplay, mXWindow, aInvalidRegion);
|
2015-05-01 21:08:04 +03:00
|
|
|
|
# endif // MOZ_HAVE_SHMIMAGE
|
|
|
|
|
#endif // MOZ_X11
|
2014-06-02 11:36:00 +04:00
|
|
|
|
}
|
2015-05-01 21:08:04 +03:00
|
|
|
|
|
2010-07-17 12:11:54 +04:00
|
|
|
|
// Code shared begin BeginMoveDrag and BeginResizeDrag
|
2011-09-29 10:19:26 +04:00
|
|
|
|
bool
|
2013-10-02 10:38:27 +04:00
|
|
|
|
nsWindow::GetDragInfo(WidgetMouseEvent* aMouseEvent,
|
2010-07-17 12:11:54 +04:00
|
|
|
|
GdkWindow** aWindow, gint* aButton,
|
|
|
|
|
gint* aRootX, gint* aRootY)
|
|
|
|
|
{
|
2013-10-02 10:38:27 +04:00
|
|
|
|
if (aMouseEvent->button != WidgetMouseEvent::eLeftButton) {
|
2010-07-17 12:11:54 +04:00
|
|
|
|
// we can only begin a move drag with the left mouse button
|
2011-10-03 11:56:21 +04:00
|
|
|
|
return false;
|
2010-07-17 12:11:54 +04:00
|
|
|
|
}
|
|
|
|
|
*aButton = 1;
|
|
|
|
|
|
|
|
|
|
// get the gdk window for this widget
|
|
|
|
|
GdkWindow* gdk_window = mGdkWindow;
|
|
|
|
|
if (!gdk_window) {
|
2011-10-03 11:56:21 +04:00
|
|
|
|
return false;
|
2010-07-17 12:11:54 +04:00
|
|
|
|
}
|
2015-02-10 01:34:50 +03:00
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
// GDK_IS_WINDOW(...) expands to a statement-expression, and
|
|
|
|
|
// statement-expressions are not allowed in template-argument lists. So we
|
|
|
|
|
// have to make the MOZ_ASSERT condition indirect.
|
|
|
|
|
if (!GDK_IS_WINDOW(gdk_window)) {
|
|
|
|
|
MOZ_ASSERT(false, "must really be window");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2010-07-17 12:11:54 +04:00
|
|
|
|
|
|
|
|
|
// find the top-level window
|
|
|
|
|
gdk_window = gdk_window_get_toplevel(gdk_window);
|
2015-02-10 01:34:50 +03:00
|
|
|
|
MOZ_ASSERT(gdk_window,
|
|
|
|
|
"gdk_window_get_toplevel should not return null");
|
2010-07-17 12:11:54 +04:00
|
|
|
|
*aWindow = gdk_window;
|
|
|
|
|
|
|
|
|
|
if (!aMouseEvent->widget) {
|
2011-10-03 11:56:21 +04:00
|
|
|
|
return false;
|
2010-07-17 12:11:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FIXME: It would be nice to have the widget position at the time
|
|
|
|
|
// of the event, but it's relatively unlikely that the widget has
|
|
|
|
|
// moved since the mousedown. (On the other hand, it's quite likely
|
|
|
|
|
// that the mouse has moved, which is why we use the mouse position
|
|
|
|
|
// from the event.)
|
2015-02-04 23:21:03 +03:00
|
|
|
|
LayoutDeviceIntPoint offset = aMouseEvent->widget->WidgetToScreenOffset();
|
2010-07-17 12:11:54 +04:00
|
|
|
|
*aRootX = aMouseEvent->refPoint.x + offset.x;
|
|
|
|
|
*aRootY = aMouseEvent->refPoint.y + offset.y;
|
|
|
|
|
|
2011-10-03 11:56:21 +04:00
|
|
|
|
return true;
|
2010-07-17 12:11:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2013-10-02 10:38:27 +04:00
|
|
|
|
nsWindow::BeginMoveDrag(WidgetMouseEvent* aEvent)
|
2010-07-17 12:11:54 +04:00
|
|
|
|
{
|
2015-02-10 01:34:50 +03:00
|
|
|
|
MOZ_ASSERT(aEvent, "must have event");
|
|
|
|
|
MOZ_ASSERT(aEvent->mClass == eMouseEventClass,
|
|
|
|
|
"event must have correct struct type");
|
2010-07-17 12:11:54 +04:00
|
|
|
|
|
|
|
|
|
GdkWindow *gdk_window;
|
|
|
|
|
gint button, screenX, screenY;
|
|
|
|
|
if (!GetDragInfo(aEvent, &gdk_window, &button, &screenX, &screenY)) {
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// tell the window manager to start the move
|
2015-01-21 07:53:00 +03:00
|
|
|
|
screenX = DevicePixelsToGdkCoordRoundDown(screenX);
|
|
|
|
|
screenY = DevicePixelsToGdkCoordRoundDown(screenY);
|
2010-07-17 12:11:54 +04:00
|
|
|
|
gdk_window_begin_move_drag(gdk_window, button, screenX, screenY,
|
|
|
|
|
aEvent->time);
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-11 13:08:35 +03:00
|
|
|
|
NS_IMETHODIMP
|
2013-10-02 07:46:03 +04:00
|
|
|
|
nsWindow::BeginResizeDrag(WidgetGUIEvent* aEvent,
|
|
|
|
|
int32_t aHorizontal,
|
|
|
|
|
int32_t aVertical)
|
2007-12-11 13:08:35 +03:00
|
|
|
|
{
|
|
|
|
|
NS_ENSURE_ARG_POINTER(aEvent);
|
|
|
|
|
|
2014-08-04 09:28:50 +04:00
|
|
|
|
if (aEvent->mClass != eMouseEventClass) {
|
2010-07-17 12:11:54 +04:00
|
|
|
|
// you can only begin a resize drag with a mouse event
|
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
2007-12-11 13:08:35 +03:00
|
|
|
|
}
|
|
|
|
|
|
2010-07-17 12:11:54 +04:00
|
|
|
|
GdkWindow *gdk_window;
|
|
|
|
|
gint button, screenX, screenY;
|
2013-10-22 12:55:20 +04:00
|
|
|
|
if (!GetDragInfo(aEvent->AsMouseEvent(), &gdk_window, &button,
|
|
|
|
|
&screenX, &screenY)) {
|
2010-07-17 12:11:54 +04:00
|
|
|
|
return NS_ERROR_FAILURE;
|
2007-12-11 13:08:35 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// work out what GdkWindowEdge we're talking about
|
|
|
|
|
GdkWindowEdge window_edge;
|
|
|
|
|
if (aVertical < 0) {
|
|
|
|
|
if (aHorizontal < 0) {
|
|
|
|
|
window_edge = GDK_WINDOW_EDGE_NORTH_WEST;
|
|
|
|
|
} else if (aHorizontal == 0) {
|
|
|
|
|
window_edge = GDK_WINDOW_EDGE_NORTH;
|
|
|
|
|
} else {
|
|
|
|
|
window_edge = GDK_WINDOW_EDGE_NORTH_EAST;
|
|
|
|
|
}
|
|
|
|
|
} else if (aVertical == 0) {
|
|
|
|
|
if (aHorizontal < 0) {
|
|
|
|
|
window_edge = GDK_WINDOW_EDGE_WEST;
|
|
|
|
|
} else if (aHorizontal == 0) {
|
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
|
} else {
|
|
|
|
|
window_edge = GDK_WINDOW_EDGE_EAST;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (aHorizontal < 0) {
|
|
|
|
|
window_edge = GDK_WINDOW_EDGE_SOUTH_WEST;
|
|
|
|
|
} else if (aHorizontal == 0) {
|
|
|
|
|
window_edge = GDK_WINDOW_EDGE_SOUTH;
|
|
|
|
|
} else {
|
|
|
|
|
window_edge = GDK_WINDOW_EDGE_SOUTH_EAST;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// tell the window manager to start the resize
|
2010-07-17 12:11:54 +04:00
|
|
|
|
gdk_window_begin_resize_drag(gdk_window, window_edge, button,
|
|
|
|
|
screenX, screenY, aEvent->time);
|
2007-12-11 13:08:35 +03:00
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
2011-01-22 00:45:23 +03:00
|
|
|
|
|
2012-09-24 03:22:28 +04:00
|
|
|
|
nsIWidget::LayerManager*
|
2013-04-24 22:42:40 +04:00
|
|
|
|
nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
|
2012-09-24 03:22:28 +04:00
|
|
|
|
LayersBackend aBackendHint,
|
|
|
|
|
LayerManagerPersistence aPersistence,
|
|
|
|
|
bool* aAllowRetaining)
|
|
|
|
|
{
|
2015-09-15 18:58:06 +03:00
|
|
|
|
if (mIsDestroyed) {
|
|
|
|
|
// Prevent external code from triggering the re-creation of the LayerManager/Compositor
|
|
|
|
|
// during shutdown. Just return what we currently have, which is most likely null.
|
|
|
|
|
return mLayerManager;
|
|
|
|
|
}
|
2012-09-24 03:22:28 +04:00
|
|
|
|
if (!mLayerManager && eTransparencyTransparent == GetTransparencyMode()) {
|
|
|
|
|
mLayerManager = CreateBasicLayerManager();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nsBaseWidget::GetLayerManager(aShadowManager, aBackendHint,
|
|
|
|
|
aPersistence, aAllowRetaining);
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-22 00:45:23 +03:00
|
|
|
|
void
|
|
|
|
|
nsWindow::ClearCachedResources()
|
|
|
|
|
{
|
|
|
|
|
if (mLayerManager &&
|
2014-01-23 22:26:41 +04:00
|
|
|
|
mLayerManager->GetBackendType() == mozilla::layers::LayersBackend::LAYERS_BASIC) {
|
2013-09-02 02:20:45 +04:00
|
|
|
|
mLayerManager->ClearCachedResources();
|
2011-01-22 00:45:23 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GList* children = gdk_window_peek_children(mGdkWindow);
|
|
|
|
|
for (GList* list = children; list; list = list->next) {
|
|
|
|
|
nsWindow* window = get_window_for_gdk_window(GDK_WINDOW(list->data));
|
|
|
|
|
if (window) {
|
|
|
|
|
window->ClearCachedResources();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-04-12 01:55:21 +04:00
|
|
|
|
|
2015-01-21 07:53:00 +03:00
|
|
|
|
gint
|
|
|
|
|
nsWindow::GdkScaleFactor()
|
|
|
|
|
{
|
|
|
|
|
#if (MOZ_WIDGET_GTK >= 3)
|
|
|
|
|
// Available as of GTK 3.10+
|
|
|
|
|
static auto sGdkWindowGetScaleFactorPtr = (gint (*)(GdkWindow*))
|
|
|
|
|
dlsym(RTLD_DEFAULT, "gdk_window_get_scale_factor");
|
2015-07-16 03:26:00 +03:00
|
|
|
|
if (sGdkWindowGetScaleFactorPtr && mGdkWindow)
|
2015-01-21 07:53:00 +03:00
|
|
|
|
return (*sGdkWindowGetScaleFactorPtr)(mGdkWindow);
|
|
|
|
|
#endif
|
2015-07-16 03:26:00 +03:00
|
|
|
|
return nsScreenGtk::GetGtkMonitorScaleFactor();
|
2015-01-21 07:53:00 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gint
|
|
|
|
|
nsWindow::DevicePixelsToGdkCoordRoundUp(int pixels) {
|
|
|
|
|
gint scale = GdkScaleFactor();
|
|
|
|
|
return (pixels + scale - 1) / scale;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gint
|
|
|
|
|
nsWindow::DevicePixelsToGdkCoordRoundDown(int pixels) {
|
|
|
|
|
gint scale = GdkScaleFactor();
|
|
|
|
|
return pixels / scale;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GdkPoint
|
|
|
|
|
nsWindow::DevicePixelsToGdkPointRoundDown(nsIntPoint point) {
|
|
|
|
|
gint scale = GdkScaleFactor();
|
|
|
|
|
return { point.x / scale, point.y / scale };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GdkRectangle
|
|
|
|
|
nsWindow::DevicePixelsToGdkRectRoundOut(nsIntRect rect) {
|
|
|
|
|
gint scale = GdkScaleFactor();
|
|
|
|
|
int x = rect.x / scale;
|
|
|
|
|
int y = rect.y / scale;
|
|
|
|
|
int right = (rect.x + rect.width + scale - 1) / scale;
|
|
|
|
|
int bottom = (rect.y + rect.height + scale - 1) / scale;
|
|
|
|
|
return { x, y, right - x, bottom - y };
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-14 06:24:56 +03:00
|
|
|
|
GdkRectangle
|
|
|
|
|
nsWindow::DevicePixelsToGdkSizeRoundUp(nsIntSize pixelSize) {
|
|
|
|
|
gint scale = GdkScaleFactor();
|
|
|
|
|
gint width = (pixelSize.width + scale - 1) / scale;
|
|
|
|
|
gint height = (pixelSize.height + scale - 1) / scale;
|
|
|
|
|
return { 0, 0, width, height };
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-21 07:53:00 +03:00
|
|
|
|
int
|
|
|
|
|
nsWindow::GdkCoordToDevicePixels(gint coord) {
|
|
|
|
|
return coord * GdkScaleFactor();
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-13 22:09:40 +03:00
|
|
|
|
LayoutDeviceIntPoint
|
|
|
|
|
nsWindow::GdkEventCoordsToDevicePixels(gdouble x, gdouble y)
|
|
|
|
|
{
|
|
|
|
|
gint scale = GdkScaleFactor();
|
|
|
|
|
return LayoutDeviceIntPoint(floor(x * scale + 0.5), floor(y * scale + 0.5));
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-04 23:21:03 +03:00
|
|
|
|
LayoutDeviceIntPoint
|
2015-01-21 07:53:00 +03:00
|
|
|
|
nsWindow::GdkPointToDevicePixels(GdkPoint point) {
|
|
|
|
|
gint scale = GdkScaleFactor();
|
2015-02-04 23:21:03 +03:00
|
|
|
|
return LayoutDeviceIntPoint(point.x * scale,
|
|
|
|
|
point.y * scale);
|
2015-01-21 07:53:00 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nsIntRect
|
|
|
|
|
nsWindow::GdkRectToDevicePixels(GdkRectangle rect) {
|
|
|
|
|
gint scale = GdkScaleFactor();
|
|
|
|
|
return nsIntRect(rect.x * scale,
|
|
|
|
|
rect.y * scale,
|
|
|
|
|
rect.width * scale,
|
|
|
|
|
rect.height * scale);
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-12 01:55:21 +04:00
|
|
|
|
nsresult
|
2015-02-15 21:52:28 +03:00
|
|
|
|
nsWindow::SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
|
2012-08-22 19:56:38 +04:00
|
|
|
|
uint32_t aNativeMessage,
|
2015-04-14 18:36:36 +03:00
|
|
|
|
uint32_t aModifierFlags,
|
|
|
|
|
nsIObserver* aObserver)
|
2012-04-12 01:55:21 +04:00
|
|
|
|
{
|
2015-04-14 18:36:36 +03:00
|
|
|
|
AutoObserverNotifier notifier(aObserver, "mouseevent");
|
|
|
|
|
|
2012-04-12 01:55:21 +04:00
|
|
|
|
if (!mGdkWindow) {
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GdkDisplay* display = gdk_window_get_display(mGdkWindow);
|
2013-07-24 11:58:50 +04:00
|
|
|
|
|
|
|
|
|
// When a button-release event is requested, create it here and put it in the
|
|
|
|
|
// event queue. This will not emit a motion event - this needs to be done
|
|
|
|
|
// explicitly *before* requesting a button-release. You will also need to wait
|
|
|
|
|
// for the motion event to be dispatched before requesting a button-release
|
|
|
|
|
// event to maintain the desired event order.
|
|
|
|
|
if (aNativeMessage == GDK_BUTTON_RELEASE) {
|
|
|
|
|
GdkEvent event;
|
|
|
|
|
memset(&event, 0, sizeof(GdkEvent));
|
|
|
|
|
event.type = (GdkEventType)aNativeMessage;
|
|
|
|
|
event.button.button = 1;
|
|
|
|
|
event.button.window = mGdkWindow;
|
|
|
|
|
event.button.time = GDK_CURRENT_TIME;
|
|
|
|
|
|
|
|
|
|
#if (MOZ_WIDGET_GTK == 3)
|
|
|
|
|
// Get device for event source
|
|
|
|
|
GdkDeviceManager *device_manager = gdk_display_get_device_manager(display);
|
|
|
|
|
event.button.device = gdk_device_manager_get_client_pointer(device_manager);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
gdk_event_put(&event);
|
|
|
|
|
} else {
|
|
|
|
|
// We don't support specific events other than button-release. In case
|
|
|
|
|
// aNativeMessage != GDK_BUTTON_RELEASE we'll synthesize a motion event
|
|
|
|
|
// that will be emitted by gdk_display_warp_pointer().
|
|
|
|
|
GdkScreen* screen = gdk_window_get_screen(mGdkWindow);
|
|
|
|
|
gdk_display_warp_pointer(display, screen, aPoint.x, aPoint.y);
|
|
|
|
|
}
|
2012-04-12 01:55:21 +04:00
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
2015-05-12 00:21:34 +03:00
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
|
nsWindow::SynthesizeNativeMouseScrollEvent(mozilla::LayoutDeviceIntPoint aPoint,
|
|
|
|
|
uint32_t aNativeMessage,
|
|
|
|
|
double aDeltaX,
|
|
|
|
|
double aDeltaY,
|
|
|
|
|
double aDeltaZ,
|
|
|
|
|
uint32_t aModifierFlags,
|
|
|
|
|
uint32_t aAdditionalFlags,
|
|
|
|
|
nsIObserver* aObserver)
|
|
|
|
|
{
|
|
|
|
|
AutoObserverNotifier notifier(aObserver, "mousescrollevent");
|
|
|
|
|
|
|
|
|
|
if (!mGdkWindow) {
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GdkEvent event;
|
|
|
|
|
memset(&event, 0, sizeof(GdkEvent));
|
|
|
|
|
event.type = GDK_SCROLL;
|
|
|
|
|
event.scroll.window = mGdkWindow;
|
|
|
|
|
event.scroll.time = GDK_CURRENT_TIME;
|
|
|
|
|
#if (MOZ_WIDGET_GTK == 3)
|
|
|
|
|
// Get device for event source
|
|
|
|
|
GdkDisplay* display = gdk_window_get_display(mGdkWindow);
|
|
|
|
|
GdkDeviceManager *device_manager = gdk_display_get_device_manager(display);
|
|
|
|
|
event.scroll.device = gdk_device_manager_get_client_pointer(device_manager);
|
|
|
|
|
#endif
|
|
|
|
|
event.scroll.x_root = aPoint.x;
|
|
|
|
|
event.scroll.y_root = aPoint.y;
|
|
|
|
|
|
|
|
|
|
LayoutDeviceIntPoint pointInWindow = aPoint - WidgetToScreenOffset();
|
|
|
|
|
event.scroll.x = pointInWindow.x;
|
|
|
|
|
event.scroll.y = pointInWindow.y;
|
|
|
|
|
|
|
|
|
|
// The delta values are backwards on Linux compared to Windows and Cocoa,
|
|
|
|
|
// hence the negation.
|
2015-10-19 14:22:55 +03:00
|
|
|
|
#if GTK_CHECK_VERSION(3,4,0)
|
|
|
|
|
// TODO: is this correct? I don't have GTK 3.4+ so I can't check
|
2015-05-12 00:21:34 +03:00
|
|
|
|
event.scroll.direction = GDK_SCROLL_SMOOTH;
|
|
|
|
|
event.scroll.delta_x = -aDeltaX;
|
|
|
|
|
event.scroll.delta_y = -aDeltaY;
|
2015-10-19 14:22:55 +03:00
|
|
|
|
#else
|
2015-05-12 00:21:34 +03:00
|
|
|
|
if (aDeltaX < 0) {
|
|
|
|
|
event.scroll.direction = GDK_SCROLL_RIGHT;
|
|
|
|
|
} else if (aDeltaX > 0) {
|
|
|
|
|
event.scroll.direction = GDK_SCROLL_LEFT;
|
|
|
|
|
} else if (aDeltaY < 0) {
|
|
|
|
|
event.scroll.direction = GDK_SCROLL_DOWN;
|
|
|
|
|
} else if (aDeltaY > 0) {
|
|
|
|
|
event.scroll.direction = GDK_SCROLL_UP;
|
|
|
|
|
} else {
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
2015-10-19 14:22:55 +03:00
|
|
|
|
#endif
|
2015-05-12 00:21:34 +03:00
|
|
|
|
|
|
|
|
|
gdk_event_put(&event);
|
|
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
}
|
2015-06-29 18:50:00 +03:00
|
|
|
|
|
|
|
|
|
int32_t
|
|
|
|
|
nsWindow::RoundsWidgetCoordinatesTo()
|
|
|
|
|
{
|
|
|
|
|
return GdkScaleFactor();
|
|
|
|
|
}
|