widget/qt/nsWindow.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* vim:expandtab:shiftwidth=4:tabstop=4:
     3  */
     4 /* This Source Code Form is subject to the terms of the Mozilla Public
     5  * License, v. 2.0. If a copy of the MPL was not distributed with this
     6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     8 #include "mozilla/ArrayUtils.h"
     9 #include "mozilla/MiscEvents.h"
    10 #include "mozilla/MouseEvents.h"
    11 #include "mozilla/TextEvents.h"
    12 #include "mozilla/TouchEvents.h"
    14 #include <QGuiApplication>
    15 #include <QtGui/QCursor>
    16 #include <QIcon>
    17 #include <QMouseEvent>
    18 #include <QWheelEvent>
    19 #include <QResizeEvent>
    20 #include <QPaintEngine>
    21 #include <QMimeData>
    22 #include <QScreen>
    24 #include <QtCore/QDebug>
    25 #include <QtCore/QEvent>
    26 #include <QtCore/QVariant>
    27 #include <algorithm>
    29 #ifdef MOZ_X11
    30 #include <X11/Xlib.h>
    31 #include <X11/Xutil.h>
    32 #endif //MOZ_X11
    34 #include "nsXULAppAPI.h"
    36 #include "prlink.h"
    38 #include "nsWindow.h"
    39 #include "mozqwidget.h"
    41 #include "nsIdleService.h"
    42 #include "nsRenderingContext.h"
    43 #include "nsIRollupListener.h"
    44 #include "nsWidgetsCID.h"
    45 #include "nsQtKeyUtils.h"
    46 #include "mozilla/Services.h"
    47 #include "mozilla/Preferences.h"
    48 #include "mozilla/Likely.h"
    49 #include "mozilla/layers/LayersTypes.h"
    50 #include "nsIWidgetListener.h"
    51 #include "ClientLayerManager.h"
    52 #include "BasicLayers.h"
    54 #include "nsIStringBundle.h"
    55 #include "nsGfxCIID.h"
    57 #include "imgIContainer.h"
    58 #include "nsGfxCIID.h"
    59 #include "nsIInterfaceRequestorUtils.h"
    60 #include "nsAutoPtr.h"
    62 #include "gfxQtPlatform.h"
    64 #include "nsIDOMWheelEvent.h"
    66 #include "GLContext.h"
    68 #ifdef MOZ_X11
    69 #include "keysym2ucs.h"
    70 #endif
    72 #include "Layers.h"
    73 #include "GLContextProvider.h"
    75 using namespace mozilla;
    76 using namespace mozilla::gl;
    77 using namespace mozilla::widget;
    78 using namespace mozilla::gfx;
    79 using namespace mozilla::layers;
    80 using mozilla::gl::GLContext;
    82 #define kWindowPositionSlop 20
    84 // Qt
    85 static const int WHEEL_DELTA = 120;
    86 static bool gGlobalsInitialized = false;
    87 static bool sAltGrModifier = false;
    89 static void find_first_visible_parent(QWindow* aItem, QWindow*& aVisibleItem);
    90 static bool is_mouse_in_window (MozQWidget* aWindow, double aMouseX, double aMouseY);
    91 static bool isContextMenuKeyEvent(const QKeyEvent *qe);
    92 static void InitKeyEvent(WidgetKeyboardEvent &aEvent, QKeyEvent *aQEvent);
    94 nsWindow::nsWindow()
    95 {
    96     LOG(("%s [%p]\n", __PRETTY_FUNCTION__, (void *)this));
    98     mIsTopLevel       = false;
    99     mIsDestroyed      = false;
   100     mIsShown          = false;
   101     mEnabled          = true;
   102     mWidget              = nullptr;
   103     mVisible           = false;
   104     mActivatePending     = false;
   105     mWindowType          = eWindowType_child;
   106     mSizeState           = nsSizeMode_Normal;
   107     mLastSizeMode        = nsSizeMode_Normal;
   108     mQCursor             = Qt::ArrowCursor;
   109     mNeedsResize         = false;
   110     mNeedsMove           = false;
   111     mListenForResizes    = false;
   112     mNeedsShow           = false;
   113     mTimerStarted        = false;
   114     mMoveEvent.needDispatch = false;
   116     if (!gGlobalsInitialized) {
   117         gfxPlatform::GetPlatform();
   118         gGlobalsInitialized = true;
   119     }
   121     memset(mKeyDownFlags, 0, sizeof(mKeyDownFlags));
   123     mIsTransparent = false;
   125     mCursor = eCursor_standard;
   126 }
   128 nsWindow::~nsWindow()
   129 {
   130     LOG(("%s [%p]\n", __PRETTY_FUNCTION__, (void *)this));
   132     Destroy();
   133 }
   135 nsresult
   136 nsWindow::Create(nsIWidget        *aParent,
   137                  nsNativeWidget    aNativeParent,
   138                  const nsIntRect  &aRect,
   139                  nsDeviceContext *aContext,
   140                  nsWidgetInitData *aInitData)
   141 {
   142     // only set the base parent if we're not going to be a dialog or a
   143     // toplevel
   144     nsIWidget *baseParent = aParent;
   146     // initialize all the common bits of this class
   147     BaseCreate(baseParent, aRect, aContext, aInitData);
   149     mVisible = true;
   151     // and do our common creation
   152     mParent = (nsWindow *)aParent;
   154     // save our bounds
   155     mBounds = aRect;
   157     // find native parent
   158     MozQWidget *parent = nullptr;
   160     if (aParent != nullptr) {
   161         parent = static_cast<MozQWidget*>(aParent->GetNativeData(NS_NATIVE_WIDGET));
   162     } else if (aNativeParent != nullptr) {
   163         parent = static_cast<MozQWidget*>(aNativeParent);
   164         if (parent && mParent == nullptr) {
   165             mParent = parent->getReceiver();
   166         }
   167     }
   169     LOG(("Create: nsWindow [%p] mWidget:[%p] parent:[%p], natPar:[%p] mParent:%p\n", (void *)this, (void*)mWidget, parent, aNativeParent, mParent));
   171     // ok, create our QGraphicsWidget
   172     mWidget = createQWidget(parent, aInitData);
   174     if (!mWidget) {
   175         return NS_ERROR_OUT_OF_MEMORY;
   176     }
   179     // resize so that everything is set to the right dimensions
   180     Resize(mBounds.x, mBounds.y, mBounds.width, mBounds.height, false);
   182     // check if we should listen for resizes
   183     mListenForResizes = (aNativeParent ||
   184                          (aInitData && aInitData->mListenForResizes));
   186     return NS_OK;
   187 }
   189 MozQWidget*
   190 nsWindow::createQWidget(MozQWidget* parent,
   191                         nsWidgetInitData* aInitData)
   192 {
   193     const char *windowName = nullptr;
   194     Qt::WindowFlags flags = Qt::Widget;
   196     // ok, create our windows
   197     switch (mWindowType) {
   198     case eWindowType_dialog:
   199         windowName = "topLevelDialog";
   200         flags = Qt::Dialog;
   201         break;
   202     case eWindowType_popup:
   203         windowName = "topLevelPopup";
   204         flags = Qt::Popup;
   205         break;
   206     case eWindowType_toplevel:
   207         windowName = "topLevelWindow";
   208         flags = Qt::Window;
   209         break;
   210     case eWindowType_invisible:
   211         windowName = "topLevelInvisible";
   212         break;
   213     case eWindowType_child:
   214     case eWindowType_plugin:
   215     default: // sheet
   216         windowName = "paintArea";
   217         break;
   218     }
   220     MozQWidget* widget = new MozQWidget(this, parent);
   221     if (!widget) {
   222         return nullptr;
   223     }
   225     widget->setObjectName(QString(windowName));
   226     if (mWindowType == eWindowType_invisible) {
   227         widget->setVisibility(QWindow::Hidden);
   228     }
   229     if (mWindowType == eWindowType_dialog) {
   230         widget->setModality(Qt::WindowModal);
   231     }
   233     widget->create();
   235     // create a QGraphicsView if this is a new toplevel window
   236     LOG(("nsWindow::%s [%p] Created Window: %s, widget:%p, par:%p\n", __FUNCTION__, (void *)this, windowName, widget, parent));
   238     return widget;
   239 }
   241 NS_IMETHODIMP
   242 nsWindow::Destroy(void)
   243 {
   244     if (mIsDestroyed || !mWidget) {
   245         return NS_OK;
   246     }
   248     LOG(("nsWindow::Destroy [%p]\n", (void *)this));
   249     mIsDestroyed = true;
   251     /** Need to clean our LayerManager up while still alive */
   252     if (mLayerManager) {
   253         mLayerManager->Destroy();
   254     }
   255     mLayerManager = nullptr;
   257     // It is safe to call DestroyeCompositor several times (here and 
   258     // in the parent class) since it will take effect only once.
   259     // The reason we call it here is because on gtk platforms we need 
   260     // to destroy the compositor before we destroy the gdk window (which
   261     // destroys the the gl context attached to it).
   262     DestroyCompositor();
   264     ClearCachedResources();
   266     nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener();
   267     if (rollupListener) {
   268         nsCOMPtr<nsIWidget> rollupWidget = rollupListener->GetRollupWidget();
   269         if (static_cast<nsIWidget *>(this) == rollupWidget) {
   270             rollupListener->Rollup(0, nullptr, nullptr);
   271         }
   272     }
   274     Show(false);
   276     // walk the list of children and call destroy on them.  Have to be
   277     // careful, though -- calling destroy on a kid may actually remove
   278     // it from our child list, losing its sibling links.
   279     for (nsIWidget* kid = mFirstChild; kid; ) {
   280         nsIWidget* next = kid->GetNextSibling();
   281         kid->Destroy();
   282         kid = next;
   283     }
   285     // Destroy thebes surface now. Badness can happen if we destroy
   286     // the surface after its X Window.
   287     if (mWidget) {
   288         mWidget->dropReceiver();
   290         // Call deleteLater instead of delete; Qt still needs the object
   291         // to be valid even after sending it a Close event.  We could
   292         // also set WA_DeleteOnClose, but this gives us more control.
   293         mWidget->deleteLater();
   294     }
   295     mWidget = nullptr;
   297     OnDestroy();
   299     return NS_OK;
   300 }
   302 NS_IMETHODIMP
   303 nsWindow::Show(bool aState)
   304 {
   305     LOG(("nsWindow::Show [%p] state %d\n", (void *)this, aState));
   306     if (aState == mIsShown) {
   307         return NS_OK;
   308     }
   310     // Clear our cached resources when the window is hidden.
   311     if (mIsShown && !aState) {
   312         ClearCachedResources();
   313     }
   315     mIsShown = aState;
   317     if ((aState && !AreBoundsSane()) || !mWidget) {
   318         LOG(("\tbounds are insane or window hasn't been created yet\n"));
   319         mNeedsShow = true;
   320         return NS_OK;
   321     }
   323     if (aState) {
   324         if (mNeedsMove) {
   325             NativeResize(mBounds.x, mBounds.y, mBounds.width, mBounds.height,
   326                          false);
   327         } else if (mNeedsResize) {
   328             NativeResize(mBounds.width, mBounds.height, false);
   329         }
   330     }
   331     else {
   332         // If someone is hiding this widget, clear any needing show flag.
   333         mNeedsShow = false;
   334     }
   336     NativeShow(aState);
   338     return NS_OK;
   339 }
   341 bool
   342 nsWindow::IsVisible() const
   343 {
   344     return mIsShown;
   345 }
   347 NS_IMETHODIMP
   348 nsWindow::ConstrainPosition(bool aAllowSlop, int32_t *aX, int32_t *aY)
   349 {
   350     if (!mWidget) {
   351         return NS_ERROR_FAILURE;
   352     }
   354     int32_t screenWidth  = qApp->primaryScreen()->size().width();
   355     int32_t screenHeight = qApp->primaryScreen()->size().height();
   357     if (aAllowSlop) {
   358         if (*aX < (kWindowPositionSlop - mBounds.width))
   359             *aX = kWindowPositionSlop - mBounds.width;
   360         if (*aX > (screenWidth - kWindowPositionSlop))
   361             *aX = screenWidth - kWindowPositionSlop;
   362         if (*aY < (kWindowPositionSlop - mBounds.height))
   363             *aY = kWindowPositionSlop - mBounds.height;
   364         if (*aY > (screenHeight - kWindowPositionSlop))
   365             *aY = screenHeight - kWindowPositionSlop;
   366     } else {
   367         if (*aX < 0)
   368             *aX = 0;
   369         if (*aX > (screenWidth - mBounds.width))
   370             *aX = screenWidth - mBounds.width;
   371         if (*aY < 0)
   372             *aY = 0;
   373         if (*aY > (screenHeight - mBounds.height))
   374             *aY = screenHeight - mBounds.height;
   375     }
   377     return NS_OK;
   378 }
   380 NS_IMETHODIMP
   381 nsWindow::Move(double aX, double aY)
   382 {
   383     LOG(("nsWindow::Move [%p] %f %f\n", (void *)this,
   384          aX, aY));
   386     int32_t x = NSToIntRound(aX);
   387     int32_t y = NSToIntRound(aY);
   389     if (mIsTopLevel) {
   390         SetSizeMode(nsSizeMode_Normal);
   391     }
   393     if (x == mBounds.x && y == mBounds.y) {
   394         return NS_OK;
   395     }
   397     mNeedsMove = false;
   399     // update the bounds
   400     QPoint pos(x, y);
   401     if (mIsTopLevel) {
   402         mWidget->setPosition(x, y);
   403     }
   404     else if (mWidget) {
   405         // the position of the widget is set relative to the parent
   406         // so we map the coordinates accordingly
   407         pos = mWidget->mapToGlobal(pos);
   408         mWidget->setPosition(pos);
   409     }
   411     mBounds.x = pos.x();
   412     mBounds.y = pos.y();
   414     NotifyRollupGeometryChange();
   415     return NS_OK;
   416 }
   418 NS_IMETHODIMP
   419 nsWindow::Resize(double aWidth, double aHeight, bool aRepaint)
   420 {
   421     mBounds.width = NSToIntRound(aWidth);
   422     mBounds.height = NSToIntRound(aHeight);
   424     if (!mWidget)
   425         return NS_OK;
   427     if (mIsShown) {
   428         if (AreBoundsSane()) {
   429             if (mIsTopLevel || mNeedsShow)
   430                 NativeResize(mBounds.x, mBounds.y,
   431                              mBounds.width, mBounds.height, aRepaint);
   432             else
   433                 NativeResize(mBounds.width, mBounds.height, aRepaint);
   435             // Does it need to be shown because it was previously insane?
   436             if (mNeedsShow) {
   437                 NativeShow(true);
   438             }
   439         }
   440         else {
   441             // If someone has set this so that the needs show flag is false
   442             // and it needs to be hidden, update the flag and hide the
   443             // window.  This flag will be cleared the next time someone
   444             // hides the window or shows it.  It also prevents us from
   445             // calling NativeShow(false) excessively on the window which
   446             // causes unneeded X traffic.
   447             if (!mNeedsShow) {
   448                 mNeedsShow = true;
   449                 NativeShow(false);
   450             }
   451         }
   452     }
   453     else if (AreBoundsSane() && mListenForResizes) {
   454         // For widgets that we listen for resizes for (widgets created
   455         // with native parents) we apparently _always_ have to resize.  I
   456         // dunno why, but apparently we're lame like that.
   457         NativeResize(mBounds.width, mBounds.height, aRepaint);
   458     }
   459     else {
   460         mNeedsResize = true;
   461     }
   463     // synthesize a resize event if this isn't a toplevel
   464     if (mIsTopLevel || mListenForResizes) {
   465         nsEventStatus status;
   466         DispatchResizeEvent(mBounds, status);
   467     }
   469     NotifyRollupGeometryChange();
   470     return NS_OK;
   471 }
   473 NS_IMETHODIMP
   474 nsWindow::Resize(double aX, double aY, double aWidth, double aHeight,
   475                  bool aRepaint)
   476 {
   477     mBounds.x = NSToIntRound(aX);
   478     mBounds.y = NSToIntRound(aY);
   479     mBounds.width = NSToIntRound(aWidth);
   480     mBounds.height = NSToIntRound(aHeight);
   482     mPlaced = true;
   484     if (!mWidget) {
   485         return NS_OK;
   486     }
   488     // Has this widget been set to visible?
   489     if (mIsShown) {
   490         // Are the bounds sane?
   491         if (AreBoundsSane()) {
   492             // Yep?  Resize the window
   493             NativeResize(mBounds.x, mBounds.y, mBounds.width, mBounds.height,
   494                          aRepaint);
   495             // Does it need to be shown because it was previously insane?
   496             if (mNeedsShow)
   497                 NativeShow(true);
   498         }
   499         else {
   500             // If someone has set this so that the needs show flag is false
   501             // and it needs to be hidden, update the flag and hide the
   502             // window.  This flag will be cleared the next time someone
   503             // hides the window or shows it.  It also prevents us from
   504             // calling NativeShow(false) excessively on the window which
   505             // causes unneeded X traffic.
   506             if (!mNeedsShow) {
   507                 mNeedsShow = true;
   508                 NativeShow(false);
   509             }
   510         }
   511     }
   512     // If the widget hasn't been shown, mark the widget as needing to be
   513     // resized before it is shown
   514     else if (AreBoundsSane() && mListenForResizes) {
   515         // For widgets that we listen for resizes for (widgets created
   516         // with native parents) we apparently _always_ have to resize.  I
   517         // dunno why, but apparently we're lame like that.
   518         NativeResize(mBounds.x, mBounds.y, mBounds.width, mBounds.height,
   519                      aRepaint);
   520     }
   521     else {
   522         mNeedsResize = true;
   523         mNeedsMove = true;
   524     }
   526     if (mIsTopLevel || mListenForResizes) {
   527         // synthesize a resize event
   528         nsEventStatus status;
   529         DispatchResizeEvent(mBounds, status);
   530     }
   532     if (aRepaint) {
   533         mWidget->renderLater();
   534     }
   536     NotifyRollupGeometryChange();
   537     return NS_OK;
   538 }
   540 NS_IMETHODIMP
   541 nsWindow::Enable(bool aState)
   542 {
   543     mEnabled = aState;
   545     return NS_OK;
   546 }
   548 bool
   549 nsWindow::IsEnabled() const
   550 {
   551     return mEnabled;
   552 }
   554 NS_IMETHODIMP
   555 nsWindow::SetFocus(bool aRaise)
   556 {
   557     // Make sure that our owning widget has focus.  If it doesn't try to
   558     // grab it.  Note that we don't set our focus flag in this case.
   559     LOGFOCUS(("  SetFocus [%p]\n", (void *)this));
   561     if (!mWidget) {
   562         return NS_ERROR_FAILURE;
   563     }
   565     if (mWidget->focusObject()) {
   566         return NS_OK;
   567     }
   569     // Because QGraphicsItem cannot get the focus if they are
   570     // invisible, we look up the chain, for the lowest visible
   571     // parent and focus that one
   572     QWindow* realFocusItem = nullptr;
   573     find_first_visible_parent(mWidget, realFocusItem);
   575     if (!realFocusItem || realFocusItem->focusObject()) {
   576         return NS_OK;
   577     }
   579     if (aRaise && mWidget) {
   580         // the raising has to happen on the view widget
   581         mWidget->raise();
   582     }
   584     // XXXndeakin why is this here? It should dispatch only when the OS
   585     // notifies us.
   586     DispatchActivateEvent();
   588     return NS_OK;
   589 }
   591 NS_IMETHODIMP
   592 nsWindow::ConfigureChildren(const nsTArray<nsIWidget::Configuration>& aConfigurations)
   593 {
   594     for (uint32_t i = 0; i < aConfigurations.Length(); ++i) {
   595         const Configuration& configuration = aConfigurations[i];
   597         nsWindow* w = static_cast<nsWindow*>(configuration.mChild);
   598         NS_ASSERTION(w->GetParent() == this,
   599                      "Configured widget is not a child");
   601         if (w->mBounds.Size() != configuration.mBounds.Size()) {
   602             w->Resize(configuration.mBounds.x, configuration.mBounds.y,
   603                       configuration.mBounds.width, configuration.mBounds.height,
   604                       true);
   605         } else if (w->mBounds.TopLeft() != configuration.mBounds.TopLeft()) {
   606             w->Move(configuration.mBounds.x, configuration.mBounds.y);
   607         }
   608     }
   609     return NS_OK;
   610 }
   612 NS_IMETHODIMP
   613 nsWindow::Invalidate(const nsIntRect &aRect)
   614 {
   615     LOGDRAW(("Invalidate (rect) [%p,%p]: %d %d %d %d\n", (void *)this,
   616              (void*)mWidget,aRect.x, aRect.y, aRect.width, aRect.height));
   618     if (!mWidget) {
   619         return NS_OK;
   620     }
   622     mWidget->renderLater();
   624     return NS_OK;
   625 }
   627 nsIntPoint
   628 nsWindow::WidgetToScreenOffset()
   629 {
   630     NS_ENSURE_TRUE(mWidget, nsIntPoint(0,0));
   632     QPoint origin(0, 0);
   633     origin = mWidget->mapToGlobal(origin);
   635     return nsIntPoint(origin.x(), origin.y());
   636 }
   638 void*
   639 nsWindow::GetNativeData(uint32_t aDataType)
   640 {
   641     switch (aDataType) {
   642     case NS_NATIVE_WINDOW:
   643     case NS_NATIVE_WIDGET: {
   644         return mWidget;
   645     }
   646     case NS_NATIVE_SHAREABLE_WINDOW: {
   647         return mWidget ? (void*)mWidget->winId() : nullptr;
   648     }
   649     case NS_NATIVE_DISPLAY: {
   650 #ifdef MOZ_X11
   651         return gfxQtPlatform::GetXDisplay(mWidget);
   652 #endif
   653         break;
   654     }
   655     case NS_NATIVE_PLUGIN_PORT:
   656     case NS_NATIVE_GRAPHIC:
   657     case NS_NATIVE_SHELLWIDGET: {
   658         break;
   659     }
   660     default:
   661         NS_WARNING("nsWindow::GetNativeData called with bad value");
   662         return nullptr;
   663     }
   664     LOG(("nsWindow::%s [%p] aDataType:%i\n", __FUNCTION__, (void *)this, aDataType));
   665     return nullptr;
   666 }
   668 NS_IMETHODIMP
   669 nsWindow::DispatchEvent(WidgetGUIEvent* aEvent, nsEventStatus& aStatus)
   670 {
   671 #ifdef DEBUG
   672     debug_DumpEvent(stdout, aEvent->widget, aEvent,
   673                     nsAutoCString("something"), 0);
   674 #endif
   676     aStatus = nsEventStatus_eIgnore;
   678     // send it to the standard callback
   679     if (mWidgetListener) {
   680         aStatus = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents);
   681     }
   683     return NS_OK;
   684 }
   686 NS_IMETHODIMP_(void)
   687 nsWindow::SetInputContext(const InputContext& aContext,
   688                           const InputContextAction& aAction)
   689 {
   690     NS_ENSURE_TRUE_VOID(mWidget);
   692     // SetSoftwareKeyboardState uses mInputContext,
   693     // so, before calling that, record aContext in mInputContext.
   694     mInputContext = aContext;
   696     switch (mInputContext.mIMEState.mEnabled) {
   697         case IMEState::ENABLED:
   698         case IMEState::PASSWORD:
   699         case IMEState::PLUGIN:
   700             SetSoftwareKeyboardState(true, aAction);
   701             break;
   702         default:
   703             SetSoftwareKeyboardState(false, aAction);
   704             break;
   705     }
   706 }
   708 NS_IMETHODIMP_(InputContext)
   709 nsWindow::GetInputContext()
   710 {
   711     mInputContext.mIMEState.mOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
   712     // Our qt widget looks like using only one context per process.
   713     // However, it's better to set the context's pointer.
   714     mInputContext.mNativeIMEContext = qApp->inputMethod();
   716     return mInputContext;
   717 }
   719 NS_IMETHODIMP
   720 nsWindow::ReparentNativeWidget(nsIWidget *aNewParent)
   721 {
   722     NS_PRECONDITION(aNewParent, "");
   724     MozQWidget* newParent = static_cast<MozQWidget*>(aNewParent->GetNativeData(NS_NATIVE_WINDOW));
   725     NS_ASSERTION(newParent, "Parent widget has a null native window handle");
   726     if (mWidget) {
   727         mWidget->setParent(newParent);
   728     }
   729     return NS_OK;
   730 }
   732 NS_IMETHODIMP
   733 nsWindow::MakeFullScreen(bool aFullScreen)
   734 {
   735     NS_ENSURE_TRUE(mWidget, NS_ERROR_FAILURE);
   737     if (aFullScreen) {
   738         if (mSizeMode != nsSizeMode_Fullscreen) {
   739             mLastSizeMode = mSizeMode;
   740         }
   742         mSizeMode = nsSizeMode_Fullscreen;
   743         mWidget->showFullScreen();
   744     }
   745     else {
   746         mSizeMode = mLastSizeMode;
   748         switch (mSizeMode) {
   749         case nsSizeMode_Maximized:
   750             mWidget->showMaximized();
   751             break;
   752         case nsSizeMode_Minimized:
   753             mWidget->showMinimized();
   754             break;
   755         case nsSizeMode_Normal:
   756             mWidget->showNormal();
   757             break;
   758         default:
   759             mWidget->showNormal();
   760             break;
   761         }
   762     }
   764     NS_ASSERTION(mLastSizeMode != nsSizeMode_Fullscreen,
   765                  "mLastSizeMode should never be fullscreen");
   766     return nsBaseWidget::MakeFullScreen(aFullScreen);
   767 }
   769 LayerManager*
   770 nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
   771                           LayersBackend aBackendHint,
   772                           LayerManagerPersistence aPersistence,
   773                           bool* aAllowRetaining)
   774 {
   775     if (!mLayerManager && eTransparencyTransparent == GetTransparencyMode()) {
   776         mLayerManager = CreateBasicLayerManager();
   777     }
   779     return nsBaseWidget::GetLayerManager(aShadowManager, aBackendHint,
   780                                          aPersistence, aAllowRetaining);
   781 }
   783 void
   784 nsWindow::UserActivity()
   785 {
   786     if (!mIdleService) {
   787         mIdleService = do_GetService("@mozilla.org/widget/idleservice;1");
   788     }
   790     if (mIdleService) {
   791         mIdleService->ResetIdleTimeOut(0);
   792     }
   793 }
   795 uint32_t
   796 nsWindow::GetGLFrameBufferFormat()
   797 {
   798     if (mLayerManager &&
   799         mLayerManager->GetBackendType() == mozilla::layers::LayersBackend::LAYERS_OPENGL) {
   800         return LOCAL_GL_RGB;
   801     }
   802     return LOCAL_GL_NONE;
   803 }
   805 NS_IMETHODIMP
   806 nsWindow::SetCursor(nsCursor aCursor)
   807 {
   808     if (mCursor == aCursor) {
   809         return NS_OK;
   810     }
   812     mCursor = aCursor;
   813     if (mWidget) {
   814         mWidget->SetCursor(mCursor);
   815     }
   816     return NS_OK;
   817 }
   819 NS_IMETHODIMP
   820 nsWindow::SetTitle(const nsAString& aTitle)
   821 {
   822     QString qStr(QString::fromUtf16((const ushort*)aTitle.BeginReading(), aTitle.Length()));
   824     mWidget->setTitle(qStr);
   826     return NS_OK;
   827 }
   829 // EVENTS
   831 void
   832 nsWindow::OnPaint()
   833 {
   834     LOGDRAW(("nsWindow::%s [%p]\n", __FUNCTION__, (void *)this));
   835     nsIWidgetListener* listener =
   836         mAttachedWidgetListener ? mAttachedWidgetListener : mWidgetListener;
   837     if (!listener) {
   838         return;
   839     }
   841     listener->WillPaintWindow(this);
   843     switch (GetLayerManager()->GetBackendType()) {
   844         case mozilla::layers::LayersBackend::LAYERS_CLIENT: {
   845             nsIntRegion region(nsIntRect(0, 0, mWidget->width(), mWidget->height()));
   846             listener->PaintWindow(this, region);
   847             break;
   848         }
   849         default:
   850             NS_ERROR("Invalid layer manager");
   851     }
   853     listener->DidPaintWindow();
   854 }
   856 nsEventStatus
   857 nsWindow::moveEvent(QMoveEvent* aEvent)
   858 {
   859     LOG(("configure event [%p] %d %d\n", (void *)this,
   860         aEvent->pos().x(),  aEvent->pos().y()));
   862     // can we shortcut?
   863     if (!mWidget || !mWidgetListener)
   864         return nsEventStatus_eIgnore;
   866     if ((mBounds.x == aEvent->pos().x() &&
   867          mBounds.y == aEvent->pos().y()))
   868     {
   869         return nsEventStatus_eIgnore;
   870     }
   872     NotifyWindowMoved(aEvent->pos().x(), aEvent->pos().y());
   873     return nsEventStatus_eConsumeNoDefault;
   874 }
   876 nsEventStatus
   877 nsWindow::resizeEvent(QResizeEvent* aEvent)
   878 {
   879     nsIntRect rect;
   881     // Generate XPFE resize event
   882     GetBounds(rect);
   884     rect.width = aEvent->size().width();
   885     rect.height = aEvent->size().height();
   887     mBounds.width = rect.width;
   888     mBounds.height = rect.height;
   890     nsEventStatus status;
   891     DispatchResizeEvent(rect, status);
   892     return status;
   893 }
   895 nsEventStatus
   896 nsWindow::mouseMoveEvent(QMouseEvent* aEvent)
   897 {
   898     UserActivity();
   900     mMoveEvent.pos = aEvent->pos();
   901     mMoveEvent.modifiers = aEvent->modifiers();
   902     mMoveEvent.needDispatch = true;
   903     DispatchMotionToMainThread();
   905     return nsEventStatus_eIgnore;
   906 }
   908 nsEventStatus
   909 nsWindow::mousePressEvent(QMouseEvent* aEvent)
   910 {
   911     // The user has done something.
   912     UserActivity();
   914     QPoint pos = aEvent->pos();
   916     // we check against the widgets geometry, so use parent coordinates
   917     // for the check
   918     if (mWidget)
   919         pos = mWidget->mapToGlobal(pos);
   921     if (CheckForRollup( pos.x(), pos.y(), false))
   922         return nsEventStatus_eIgnore;
   924     uint16_t      domButton;
   925     switch (aEvent->button()) {
   926     case Qt::MidButton:
   927         domButton = WidgetMouseEvent::eMiddleButton;
   928         break;
   929     case Qt::RightButton:
   930         domButton = WidgetMouseEvent::eRightButton;
   931         break;
   932     default:
   933         domButton = WidgetMouseEvent::eLeftButton;
   934         break;
   935     }
   937     WidgetMouseEvent event(true, NS_MOUSE_BUTTON_DOWN, this,
   938                            WidgetMouseEvent::eReal);
   939     event.button = domButton;
   940     InitButtonEvent(event, aEvent, 1);
   942     LOG(("%s [%p] button: %d\n", __PRETTY_FUNCTION__, (void*)this, domButton));
   944     nsEventStatus status = DispatchEvent(&event);
   946     // right menu click on linux should also pop up a context menu
   947     if (domButton == WidgetMouseEvent::eRightButton &&
   948         MOZ_LIKELY(!mIsDestroyed)) {
   949         WidgetMouseEvent contextMenuEvent(true, NS_CONTEXTMENU, this,
   950                                           WidgetMouseEvent::eReal);
   951         InitButtonEvent(contextMenuEvent, aEvent, 1);
   952         DispatchEvent(&contextMenuEvent, status);
   953     }
   955     return status;
   956 }
   958 nsEventStatus
   959 nsWindow::mouseReleaseEvent(QMouseEvent* aEvent)
   960 {
   961     // The user has done something.
   962     UserActivity();
   964     uint16_t domButton;
   966     switch (aEvent->button()) {
   967     case Qt::MidButton:
   968         domButton = WidgetMouseEvent::eMiddleButton;
   969         break;
   970     case Qt::RightButton:
   971         domButton = WidgetMouseEvent::eRightButton;
   972         break;
   973     default:
   974         domButton = WidgetMouseEvent::eLeftButton;
   975         break;
   976     }
   978     LOG(("%s [%p] button: %d\n", __PRETTY_FUNCTION__, (void*)this, domButton));
   980     WidgetMouseEvent event(true, NS_MOUSE_BUTTON_UP, this,
   981                            WidgetMouseEvent::eReal);
   982     event.button = domButton;
   983     InitButtonEvent(event, aEvent, 1);
   985     nsEventStatus status = DispatchEvent(&event);
   987     return status;
   988 }
   990 nsEventStatus
   991 nsWindow::mouseDoubleClickEvent(QMouseEvent* aEvent)
   992 {
   993     uint32_t eventType;
   995     switch (aEvent->button()) {
   996     case Qt::MidButton:
   997         eventType = WidgetMouseEvent::eMiddleButton;
   998         break;
   999     case Qt::RightButton:
  1000         eventType = WidgetMouseEvent::eRightButton;
  1001         break;
  1002     default:
  1003         eventType = WidgetMouseEvent::eLeftButton;
  1004         break;
  1007     WidgetMouseEvent event(true, NS_MOUSE_DOUBLECLICK, this,
  1008                            WidgetMouseEvent::eReal);
  1009     event.button = eventType;
  1011     InitButtonEvent(event, aEvent, 2);
  1012     //pressed
  1013     return DispatchEvent(&event);
  1016 nsEventStatus
  1017 nsWindow::focusInEvent(QFocusEvent* aEvent)
  1019     LOGFOCUS(("OnFocusInEvent [%p]\n", (void *)this));
  1021     if (!mWidget) {
  1022         return nsEventStatus_eIgnore;
  1025     DispatchActivateEventOnTopLevelWindow();
  1027     LOGFOCUS(("Events sent from focus in event [%p]\n", (void *)this));
  1028     return nsEventStatus_eIgnore;
  1031 nsEventStatus
  1032 nsWindow::focusOutEvent(QFocusEvent* aEvent)
  1034     LOGFOCUS(("OnFocusOutEvent [%p]\n", (void *)this));
  1036     if (!mWidget) {
  1037         return nsEventStatus_eIgnore;
  1040     DispatchDeactivateEventOnTopLevelWindow();
  1042     LOGFOCUS(("Done with container focus out [%p]\n", (void *)this));
  1043     return nsEventStatus_eIgnore;
  1046 nsEventStatus
  1047 nsWindow::keyPressEvent(QKeyEvent* aEvent)
  1049     LOGFOCUS(("OnKeyPressEvent [%p]\n", (void *)this));
  1051     // The user has done something.
  1052     UserActivity();
  1054     if (aEvent->key() == Qt::Key_AltGr) {
  1055         sAltGrModifier = true;
  1058 #ifdef MOZ_X11
  1059     // before we dispatch a key, check if it's the context menu key.
  1060     // If so, send a context menu key event instead.
  1061     if (isContextMenuKeyEvent(aEvent)) {
  1062         WidgetMouseEvent contextMenuEvent(true, NS_CONTEXTMENU, this,
  1063                                           WidgetMouseEvent::eReal,
  1064                                           WidgetMouseEvent::eContextMenuKey);
  1065         //keyEventToContextMenuEvent(&event, &contextMenuEvent);
  1066         return DispatchEvent(&contextMenuEvent);
  1069     uint32_t domCharCode = 0;
  1070     uint32_t domKeyCode = QtKeyCodeToDOMKeyCode(aEvent->key());
  1072     // get keymap and modifier map from the Xserver
  1073     Display *display = gfxQtPlatform::GetXDisplay(mWidget);
  1074     int x_min_keycode = 0, x_max_keycode = 0, xkeysyms_per_keycode;
  1075     XDisplayKeycodes(display, &x_min_keycode, &x_max_keycode);
  1076     XModifierKeymap *xmodmap = XGetModifierMapping(display);
  1077     if (!xmodmap)
  1078         return nsEventStatus_eIgnore;
  1080     KeySym *xkeymap = XGetKeyboardMapping(display, x_min_keycode, x_max_keycode - x_min_keycode,
  1081                                           &xkeysyms_per_keycode);
  1082     if (!xkeymap) {
  1083         XFreeModifiermap(xmodmap);
  1084         return nsEventStatus_eIgnore;
  1087     // create modifier masks
  1088     qint32 shift_mask = 0, shift_lock_mask = 0, caps_lock_mask = 0, num_lock_mask = 0;
  1090     for (int i = 0; i < 8 * xmodmap->max_keypermod; ++i) {
  1091         qint32 maskbit = 1 << (i / xmodmap->max_keypermod);
  1092         KeyCode modkeycode = xmodmap->modifiermap[i];
  1093         if (modkeycode == NoSymbol) {
  1094             continue;
  1097         quint32 mapindex = (modkeycode - x_min_keycode) * xkeysyms_per_keycode;
  1098         for (int j = 0; j < xkeysyms_per_keycode; ++j) {
  1099             KeySym modkeysym = xkeymap[mapindex + j];
  1100             switch (modkeysym) {
  1101                 case XK_Num_Lock:
  1102                     num_lock_mask |= maskbit;
  1103                     break;
  1104                 case XK_Caps_Lock:
  1105                     caps_lock_mask |= maskbit;
  1106                     break;
  1107                 case XK_Shift_Lock:
  1108                     shift_lock_mask |= maskbit;
  1109                     break;
  1110                 case XK_Shift_L:
  1111                 case XK_Shift_R:
  1112                     shift_mask |= maskbit;
  1113                     break;
  1117     // indicate whether is down or not
  1118     bool shift_state = ((shift_mask & aEvent->nativeModifiers()) != 0) ^
  1119                           (bool)(shift_lock_mask & aEvent->nativeModifiers());
  1120     bool capslock_state = (bool)(caps_lock_mask & aEvent->nativeModifiers());
  1122     // try to find a keysym that we can translate to a DOMKeyCode
  1123     // this is needed because some of Qt's keycodes cannot be translated
  1124     // TODO: use US keyboard keymap instead of localised keymap
  1125     if (!domKeyCode &&
  1126         aEvent->nativeScanCode() >= (quint32)x_min_keycode &&
  1127         aEvent->nativeScanCode() <= (quint32)x_max_keycode) {
  1128         int index = (aEvent->nativeScanCode() - x_min_keycode) * xkeysyms_per_keycode;
  1129         for(int i = 0; (i < xkeysyms_per_keycode) && (domKeyCode == (quint32)NoSymbol); ++i) {
  1130             domKeyCode = QtKeyCodeToDOMKeyCode(xkeymap[index + i]);
  1134     // store character in domCharCode
  1135     if (aEvent->text().length() && aEvent->text()[0].isPrint())
  1136         domCharCode = (int32_t) aEvent->text()[0].unicode();
  1138     KeyNameIndex keyNameIndex =
  1139         domCharCode ? KEY_NAME_INDEX_PrintableKey :
  1140                       QtKeyCodeToDOMKeyNameIndex(aEvent->key());
  1142     // If the key isn't autorepeat, we need to send the initial down event
  1143     if (!aEvent->isAutoRepeat() && !IsKeyDown(domKeyCode)) {
  1144         // send the key down event
  1146         SetKeyDownFlag(domKeyCode);
  1148         WidgetKeyboardEvent downEvent(true, NS_KEY_DOWN, this);
  1149         InitKeyEvent(downEvent, aEvent);
  1151         downEvent.keyCode = domKeyCode;
  1152         downEvent.mKeyNameIndex = keyNameIndex;
  1154         nsEventStatus status = DispatchEvent(&downEvent);
  1156         // DispatchEvent can Destroy us (bug 378273)
  1157         if (MOZ_UNLIKELY(mIsDestroyed)) {
  1158             qWarning() << "Returning[" << __LINE__ << "]: " << "Window destroyed";
  1159             return status;
  1162         // If prevent default on keydown, don't dispatch keypress event
  1163         if (status == nsEventStatus_eConsumeNoDefault) {
  1164             return nsEventStatus_eConsumeNoDefault;
  1168     // Don't pass modifiers as NS_KEY_PRESS events.
  1169     // Instead of selectively excluding some keys from NS_KEY_PRESS events,
  1170     // we instead selectively include (as per MSDN spec
  1171     // ( http://msdn.microsoft.com/en-us/library/system.windows.forms.control.keypress%28VS.71%29.aspx );
  1172     // no official spec covers KeyPress events).
  1173     if (aEvent->key() == Qt::Key_Shift   ||
  1174         aEvent->key() == Qt::Key_Control ||
  1175         aEvent->key() == Qt::Key_Meta    ||
  1176         aEvent->key() == Qt::Key_Alt     ||
  1177         aEvent->key() == Qt::Key_AltGr) {
  1179         return nsEventStatus_eIgnore;
  1182     // Look for specialized app-command keys
  1183     switch (aEvent->key()) {
  1184         case Qt::Key_Back:
  1185             return DispatchCommandEvent(nsGkAtoms::Back);
  1186         case Qt::Key_Forward:
  1187             return DispatchCommandEvent(nsGkAtoms::Forward);
  1188         case Qt::Key_Refresh:
  1189             return DispatchCommandEvent(nsGkAtoms::Reload);
  1190         case Qt::Key_Stop:
  1191             return DispatchCommandEvent(nsGkAtoms::Stop);
  1192         case Qt::Key_Search:
  1193             return DispatchCommandEvent(nsGkAtoms::Search);
  1194         case Qt::Key_Favorites:
  1195             return DispatchCommandEvent(nsGkAtoms::Bookmarks);
  1196         case Qt::Key_HomePage:
  1197             return DispatchCommandEvent(nsGkAtoms::Home);
  1198         case Qt::Key_Copy:
  1199         case Qt::Key_F16: // F16, F20, F18, F14 are old keysyms for Copy Cut Paste Undo
  1200             return DispatchContentCommandEvent(NS_CONTENT_COMMAND_COPY);
  1201         case Qt::Key_Cut:
  1202         case Qt::Key_F20:
  1203             return DispatchContentCommandEvent(NS_CONTENT_COMMAND_CUT);
  1204         case Qt::Key_Paste:
  1205         case Qt::Key_F18:
  1206         case Qt::Key_F9:
  1207             return DispatchContentCommandEvent(NS_CONTENT_COMMAND_PASTE);
  1208         case Qt::Key_F14:
  1209             return DispatchContentCommandEvent(NS_CONTENT_COMMAND_UNDO);
  1212     // Qt::Key_Redo and Qt::Key_Undo are not available yet.
  1213     if (aEvent->nativeVirtualKey() == 0xff66) {
  1214         return DispatchContentCommandEvent(NS_CONTENT_COMMAND_REDO);
  1216     if (aEvent->nativeVirtualKey() == 0xff65) {
  1217         return DispatchContentCommandEvent(NS_CONTENT_COMMAND_UNDO);
  1220     WidgetKeyboardEvent event(true, NS_KEY_PRESS, this);
  1221     InitKeyEvent(event, aEvent);
  1223     // If there is no charcode attainable from the text, try to
  1224     // generate it from the keycode. Check shift state for case
  1225     // Also replace the charcode if ControlModifier is the only
  1226     // pressed Modifier
  1227     if ((!domCharCode) &&
  1228         (QGuiApplication::keyboardModifiers() &
  1229         (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier))) {
  1231         // get a character from X11 key map
  1232         KeySym keysym = aEvent->nativeVirtualKey();
  1233         if (keysym) {
  1234             domCharCode = (uint32_t) keysym2ucs(keysym);
  1235             if (domCharCode == -1 || !QChar((quint32)domCharCode).isPrint()) {
  1236                 domCharCode = 0;
  1240         // if Ctrl is pressed and domCharCode is not a ASCII character
  1241         if (domCharCode > 0xFF && (QGuiApplication::keyboardModifiers() & Qt::ControlModifier)) {
  1242             // replace Unicode character
  1243             int index = (aEvent->nativeScanCode() - x_min_keycode) * xkeysyms_per_keycode;
  1244             for (int i = 0; i < xkeysyms_per_keycode; ++i) {
  1245                 if (xkeymap[index + i] <= 0xFF && !shift_state) {
  1246                     domCharCode = (uint32_t) QChar::toLower((uint) xkeymap[index + i]);
  1247                     break;
  1252     } else { // The key event should cause a character input.
  1253              // At that time, we need to reset the modifiers
  1254              // because nsEditor will not accept a key event
  1255              // for text input if one or more modifiers are set.
  1256         event.modifiers &= ~(MODIFIER_CONTROL |
  1257                              MODIFIER_ALT |
  1258                              MODIFIER_META);
  1261     KeySym keysym = NoSymbol;
  1262     int index = (aEvent->nativeScanCode() - x_min_keycode) * xkeysyms_per_keycode;
  1263     for (int i = 0; i < xkeysyms_per_keycode; ++i) {
  1264         if (xkeymap[index + i] == aEvent->nativeVirtualKey()) {
  1265             if ((i % 2) == 0) { // shifted char
  1266                 keysym = xkeymap[index + i + 1];
  1267                 break;
  1268             } else { // unshifted char
  1269                 keysym = xkeymap[index + i - 1];
  1270                 break;
  1273         if (xkeysyms_per_keycode - 1 == i) {
  1274             qWarning() << "Symbol '" << aEvent->nativeVirtualKey() << "' not found";
  1277     QChar unshiftedChar(domCharCode);
  1278     long ucs = keysym2ucs(keysym);
  1279     ucs = ucs == -1 ? 0 : ucs;
  1280     QChar shiftedChar((uint)ucs);
  1282     // append alternativeCharCodes if modifier is pressed
  1283     // append an additional alternativeCharCodes if domCharCode is not a Latin character
  1284     // and if one of these modifiers is pressed (i.e. Ctrl, Alt, Meta)
  1285     if (domCharCode &&
  1286         (QGuiApplication::keyboardModifiers() &
  1287         (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier))) {
  1289         event.charCode = domCharCode;
  1290         event.keyCode = 0;
  1291         AlternativeCharCode altCharCode(0, 0);
  1292         // if character has a lower and upper representation
  1293         if ((unshiftedChar.isUpper() || unshiftedChar.isLower()) &&
  1294             unshiftedChar.toLower() == shiftedChar.toLower()) {
  1295             if (shift_state ^ capslock_state) {
  1296                 altCharCode.mUnshiftedCharCode = (uint32_t) QChar::toUpper((uint)domCharCode);
  1297                 altCharCode.mShiftedCharCode = (uint32_t) QChar::toLower((uint)domCharCode);
  1298             } else {
  1299                 altCharCode.mUnshiftedCharCode = (uint32_t) QChar::toLower((uint)domCharCode);
  1300                 altCharCode.mShiftedCharCode = (uint32_t) QChar::toUpper((uint)domCharCode);
  1302         } else {
  1303             altCharCode.mUnshiftedCharCode = (uint32_t) unshiftedChar.unicode();
  1304             altCharCode.mShiftedCharCode = (uint32_t) shiftedChar.unicode();
  1307         // append alternative char code to event
  1308         if ((altCharCode.mUnshiftedCharCode && altCharCode.mUnshiftedCharCode != domCharCode) ||
  1309             (altCharCode.mShiftedCharCode && altCharCode.mShiftedCharCode != domCharCode)) {
  1310             event.alternativeCharCodes.AppendElement(altCharCode);
  1313         // check if the alternative char codes are latin-1
  1314         if (altCharCode.mUnshiftedCharCode > 0xFF || altCharCode.mShiftedCharCode > 0xFF) {
  1315             altCharCode.mUnshiftedCharCode = altCharCode.mShiftedCharCode = 0;
  1317             // find latin char for keycode
  1318             KeySym keysym = NoSymbol;
  1319             int index = (aEvent->nativeScanCode() - x_min_keycode) * xkeysyms_per_keycode;
  1320             // find first shifted and unshifted Latin-Char in XKeyMap
  1321             for (int i = 0; i < xkeysyms_per_keycode; ++i) {
  1322                 keysym = xkeymap[index + i];
  1323                 if (keysym && keysym <= 0xFF) {
  1324                     if ((shift_state && (i % 2 == 1)) ||
  1325                         (!shift_state && (i % 2 == 0))) {
  1326                         altCharCode.mUnshiftedCharCode = altCharCode.mUnshiftedCharCode ?
  1327                             altCharCode.mUnshiftedCharCode :
  1328                             keysym;
  1329                     } else {
  1330                         altCharCode.mShiftedCharCode = altCharCode.mShiftedCharCode ?
  1331                             altCharCode.mShiftedCharCode :
  1332                             keysym;
  1334                     if (altCharCode.mUnshiftedCharCode && altCharCode.mShiftedCharCode) {
  1335                         break;
  1340             if (altCharCode.mUnshiftedCharCode || altCharCode.mShiftedCharCode) {
  1341                 event.alternativeCharCodes.AppendElement(altCharCode);
  1344     } else {
  1345         event.charCode = domCharCode;
  1348     if (xmodmap) {
  1349         XFreeModifiermap(xmodmap);
  1351     if (xkeymap) {
  1352         XFree(xkeymap);
  1355     event.keyCode = domCharCode ? 0 : domKeyCode;
  1356     event.mKeyNameIndex = keyNameIndex;
  1357     // send the key press event
  1358     return DispatchEvent(&event);
  1359 #else
  1361     //:TODO: fix shortcuts hebrew for non X11,
  1362     //see Bug 562195##51
  1364     // before we dispatch a key, check if it's the context menu key.
  1365     // If so, send a context menu key event instead.
  1366     if (isContextMenuKeyEvent(aEvent)) {
  1367         WidgetMouseEvent contextMenuEvent(true, NS_CONTEXTMENU, this,
  1368                                           WidgetMouseEvent::eReal,
  1369                                           WidgetMouseEvent::eContextMenuKey);
  1370         //keyEventToContextMenuEvent(&event, &contextMenuEvent);
  1371         return DispatchEvent(&contextMenuEvent);
  1374     uint32_t domCharCode = 0;
  1375     uint32_t domKeyCode = QtKeyCodeToDOMKeyCode(aEvent->key());
  1377     if (aEvent->text().length() && aEvent->text()[0].isPrint()) {
  1378         domCharCode = (int32_t) aEvent->text()[0].unicode();
  1381     KeyNameIndex keyNameIndex =
  1382         domCharCode ? KEY_NAME_INDEX_PrintableKey :
  1383                       QtKeyCodeToDOMKeyNameIndex(aEvent->key());
  1385     // If the key isn't autorepeat, we need to send the initial down event
  1386     if (!aEvent->isAutoRepeat() && !IsKeyDown(domKeyCode)) {
  1387         // send the key down event
  1389         SetKeyDownFlag(domKeyCode);
  1391         WidgetKeyboardEvent downEvent(true, NS_KEY_DOWN, this);
  1392         InitKeyEvent(downEvent, aEvent);
  1394         downEvent.keyCode = domKeyCode;
  1395         downEvent.mKeyNameIndex = keyNameIndex;
  1397         nsEventStatus status = DispatchEvent(&downEvent);
  1399         // If prevent default on keydown, don't dispatch keypress event
  1400         if (status == nsEventStatus_eConsumeNoDefault) {
  1401             return nsEventStatus_eConsumeNoDefault;
  1405     WidgetKeyboardEvent event(true, NS_KEY_PRESS, this);
  1406     InitKeyEvent(event, aEvent);
  1408     event.charCode = domCharCode;
  1410     event.keyCode = domCharCode ? 0 : domKeyCode;
  1411     event.mKeyNameIndex = keyNameIndex;
  1413     // send the key press event
  1414     return DispatchEvent(&event);
  1415 #endif
  1418 nsEventStatus
  1419 nsWindow::keyReleaseEvent(QKeyEvent* aEvent)
  1421     LOGFOCUS(("OnKeyReleaseEvent [%p]\n", (void *)this));
  1423     // The user has done something.
  1424     UserActivity();
  1426     if (isContextMenuKeyEvent(aEvent)) {
  1427         // er, what do we do here? DoDefault or NoDefault?
  1428         return nsEventStatus_eConsumeDoDefault;
  1431     uint32_t domKeyCode = QtKeyCodeToDOMKeyCode(aEvent->key());
  1433 #ifdef MOZ_X11
  1434     if (!domKeyCode) {
  1435         // get keymap from the Xserver
  1436         Display *display = gfxQtPlatform::GetXDisplay(mWidget);
  1437         int x_min_keycode = 0, x_max_keycode = 0, xkeysyms_per_keycode;
  1438         XDisplayKeycodes(display, &x_min_keycode, &x_max_keycode);
  1439         KeySym *xkeymap = XGetKeyboardMapping(display, x_min_keycode, x_max_keycode - x_min_keycode,
  1440                                               &xkeysyms_per_keycode);
  1442         if (aEvent->nativeScanCode() >= (quint32)x_min_keycode &&
  1443             aEvent->nativeScanCode() <= (quint32)x_max_keycode) {
  1444             int index = (aEvent->nativeScanCode() - x_min_keycode) * xkeysyms_per_keycode;
  1445             for(int i = 0; (i < xkeysyms_per_keycode) && (domKeyCode == (quint32)NoSymbol); ++i) {
  1446                 domKeyCode = QtKeyCodeToDOMKeyCode(xkeymap[index + i]);
  1450         if (xkeymap) {
  1451             XFree(xkeymap);
  1454 #endif // MOZ_X11
  1456     // send the key event as a key up event
  1457     WidgetKeyboardEvent event(true, NS_KEY_UP, this);
  1458     InitKeyEvent(event, aEvent);
  1460     if (aEvent->key() == Qt::Key_AltGr) {
  1461         sAltGrModifier = false;
  1464     event.keyCode = domKeyCode;
  1465     event.mKeyNameIndex =
  1466         (aEvent->text().length() && aEvent->text()[0].isPrint()) ?
  1467             KEY_NAME_INDEX_PrintableKey :
  1468             QtKeyCodeToDOMKeyNameIndex(aEvent->key());
  1470     // unset the key down flag
  1471     ClearKeyDownFlag(event.keyCode);
  1473     return DispatchEvent(&event);
  1476 nsEventStatus
  1477 nsWindow::wheelEvent(QWheelEvent* aEvent)
  1479     // check to see if we should rollup
  1480     WidgetWheelEvent wheelEvent(true, NS_WHEEL_WHEEL, this);
  1481     wheelEvent.deltaMode = nsIDOMWheelEvent::DOM_DELTA_LINE;
  1483     // negative values for aEvent->delta indicate downward scrolling;
  1484     // this is opposite Gecko usage.
  1485     // TODO: Store the unused delta values due to fraction round and add it
  1486     //       to next event.  The stored values should be reset by other
  1487     //       direction scroll event.
  1488     int32_t delta = (int)(aEvent->delta() / WHEEL_DELTA) * -3;
  1490     switch (aEvent->orientation()) {
  1491     case Qt::Vertical:
  1492         wheelEvent.deltaY = wheelEvent.lineOrPageDeltaY = delta;
  1493         break;
  1494     case Qt::Horizontal:
  1495         wheelEvent.deltaX = wheelEvent.lineOrPageDeltaX = delta;
  1496         break;
  1497     default:
  1498         Q_ASSERT(0);
  1499         break;
  1502     wheelEvent.refPoint.x = nscoord(aEvent->pos().x());
  1503     wheelEvent.refPoint.y = nscoord(aEvent->pos().y());
  1505     wheelEvent.InitBasicModifiers(aEvent->modifiers() & Qt::ControlModifier,
  1506                                   aEvent->modifiers() & Qt::AltModifier,
  1507                                   aEvent->modifiers() & Qt::ShiftModifier,
  1508                                   aEvent->modifiers() & Qt::MetaModifier);
  1509     wheelEvent.time = 0;
  1511     return DispatchEvent(&wheelEvent);
  1514 nsEventStatus
  1515 nsWindow::showEvent(QShowEvent *)
  1517     LOG(("%s [%p]\n", __PRETTY_FUNCTION__,(void *)this));
  1518     mVisible = true;
  1519     return nsEventStatus_eConsumeDoDefault;
  1522 nsEventStatus
  1523 nsWindow::hideEvent(QHideEvent *)
  1525     LOG(("%s [%p]\n", __PRETTY_FUNCTION__,(void *)this));
  1526     mVisible = false;
  1527     return nsEventStatus_eConsumeDoDefault;
  1530 nsEventStatus nsWindow::touchEvent(QTouchEvent* aEvent)
  1532     return nsEventStatus_eIgnore;
  1535 nsEventStatus
  1536 nsWindow::tabletEvent(QTabletEvent* aEvent)
  1538     LOGFOCUS(("nsWindow::%s [%p]\n", __FUNCTION__, (void *)this));
  1539     return nsEventStatus_eIgnore;
  1542 //  Helpers
  1544 void
  1545 nsWindow::InitButtonEvent(WidgetMouseEvent& aMoveEvent,
  1546                           QMouseEvent* aEvent,
  1547                           int aClickCount)
  1549     aMoveEvent.refPoint.x = nscoord(aEvent->pos().x());
  1550     aMoveEvent.refPoint.y = nscoord(aEvent->pos().y());
  1552     aMoveEvent.InitBasicModifiers(aEvent->modifiers() & Qt::ControlModifier,
  1553                                   aEvent->modifiers() & Qt::AltModifier,
  1554                                   aEvent->modifiers() & Qt::ShiftModifier,
  1555                                   aEvent->modifiers() & Qt::MetaModifier);
  1556     aMoveEvent.clickCount      = aClickCount;
  1559 nsEventStatus
  1560 nsWindow::DispatchEvent(WidgetGUIEvent* aEvent)
  1562     nsEventStatus status;
  1563     DispatchEvent(aEvent, status);
  1564     return status;
  1567 void
  1568 nsWindow::DispatchActivateEvent(void)
  1570     if (mWidgetListener) {
  1571         mWidgetListener->WindowActivated();
  1575 void
  1576 nsWindow::DispatchDeactivateEvent(void)
  1578     if (mWidgetListener) {
  1579         mWidgetListener->WindowDeactivated();
  1583 void
  1584 nsWindow::DispatchActivateEventOnTopLevelWindow(void)
  1586     nsWindow* topLevelWindow = static_cast<nsWindow*>(GetTopLevelWidget());
  1587     if (topLevelWindow != nullptr) {
  1588         topLevelWindow->DispatchActivateEvent();
  1592 void
  1593 nsWindow::DispatchDeactivateEventOnTopLevelWindow(void)
  1595     nsWindow* topLevelWindow = static_cast<nsWindow*>(GetTopLevelWidget());
  1596     if (topLevelWindow != nullptr) {
  1597         topLevelWindow->DispatchDeactivateEvent();
  1601 void
  1602 nsWindow::DispatchResizeEvent(nsIntRect &aRect, nsEventStatus &aStatus)
  1604     aStatus = nsEventStatus_eIgnore;
  1605     if (mWidgetListener &&
  1606         mWidgetListener->WindowResized(this, aRect.width, aRect.height)) {
  1607         aStatus = nsEventStatus_eConsumeNoDefault;
  1611 ///////////////////////////////////// OLD GECKO ECENTS need to Sort ///////////////////
  1613 /* static */ bool
  1614 isContextMenuKeyEvent(const QKeyEvent *qe)
  1616     uint32_t kc = QtKeyCodeToDOMKeyCode(qe->key());
  1617     if (qe->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)) {
  1618         return false;
  1621     bool isShift = qe->modifiers() & Qt::ShiftModifier;
  1622     return (kc == NS_VK_F10 && isShift) ||
  1623         (kc == NS_VK_CONTEXT_MENU && !isShift);
  1626 /* static */void
  1627 InitKeyEvent(WidgetKeyboardEvent &aEvent, QKeyEvent *aQEvent)
  1629     aEvent.InitBasicModifiers(aQEvent->modifiers() & Qt::ControlModifier,
  1630                               aQEvent->modifiers() & Qt::AltModifier,
  1631                               aQEvent->modifiers() & Qt::ShiftModifier,
  1632                               aQEvent->modifiers() & Qt::MetaModifier);
  1633     aEvent.mIsRepeat =
  1634         (aEvent.message == NS_KEY_DOWN || aEvent.message == NS_KEY_PRESS) &&
  1635         aQEvent->isAutoRepeat();
  1636     aEvent.time = 0;
  1638     if (sAltGrModifier) {
  1639         aEvent.modifiers |= (MODIFIER_CONTROL | MODIFIER_ALT);
  1642     // The transformations above and in qt for the keyval are not invertible
  1643     // so link to the QKeyEvent (which will vanish soon after return from the
  1644     // event callback) to give plugins access to hardware_keycode and state.
  1645     // (An XEvent would be nice but the QKeyEvent is good enough.)
  1646     aEvent.pluginEvent = (void *)aQEvent;
  1649 NS_IMPL_ISUPPORTS_INHERITED(nsWindow, nsBaseWidget, nsISupportsWeakReference)
  1653 void
  1654 nsWindow::ClearCachedResources()
  1656     if (mLayerManager &&
  1657         mLayerManager->GetBackendType() == mozilla::layers::LayersBackend::LAYERS_BASIC) {
  1658         mLayerManager->ClearCachedResources();
  1660     for (nsIWidget* kid = mFirstChild; kid; ) {
  1661         nsIWidget* next = kid->GetNextSibling();
  1662         static_cast<nsWindow*>(kid)->ClearCachedResources();
  1663         kid = next;
  1667 NS_IMETHODIMP
  1668 nsWindow::SetParent(nsIWidget *aNewParent)
  1670     NS_ENSURE_ARG_POINTER(aNewParent);
  1672     nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
  1673     nsIWidget* parent = GetParent();
  1674     if (parent) {
  1675         parent->RemoveChild(this);
  1677     ReparentNativeWidget(aNewParent);
  1678     aNewParent->AddChild(this);
  1679     return NS_OK;
  1682 NS_IMETHODIMP
  1683 nsWindow::SetModal(bool aModal)
  1685     LOG(("nsWindow::SetModal [%p] %d, widget[%p]\n", (void *)this, aModal, mWidget));
  1686     if (mWidget) {
  1687         mWidget->setModality(aModal ? Qt::WindowModal : Qt::NonModal);
  1690     return NS_OK;
  1694 NS_IMETHODIMP
  1695 nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement  aPlacement,
  1696                       nsIWidget                  *aWidget,
  1697                       bool                        aActivate)
  1699     return NS_ERROR_NOT_IMPLEMENTED;
  1702 NS_IMETHODIMP
  1703 nsWindow::SetSizeMode(int32_t aMode)
  1705     nsresult rv;
  1707     LOG(("nsWindow::SetSizeMode [%p] %d\n", (void *)this, aMode));
  1708     if (aMode != nsSizeMode_Minimized) {
  1709         mWidget->requestActivate();
  1712     // Save the requested state.
  1713     rv = nsBaseWidget::SetSizeMode(aMode);
  1715     // return if there's no shell or our current state is the same as
  1716     // the mode we were just set to.
  1717     if (!mWidget || mSizeState == mSizeMode) {
  1718         return rv;
  1721     switch (aMode) {
  1722     case nsSizeMode_Maximized:
  1723         mWidget->showMaximized();
  1724         break;
  1725     case nsSizeMode_Minimized:
  1726         mWidget->showMinimized();
  1727         break;
  1728     case nsSizeMode_Fullscreen:
  1729         mWidget->showFullScreen();
  1730         break;
  1732     default:
  1733         // nsSizeMode_Normal, really.
  1734         mWidget->show();
  1735         break;
  1738     mSizeState = mSizeMode;
  1740     return rv;
  1743 // Helper function to recursively find the first parent item that
  1744 // is still visible (QGraphicsItem can be hidden even if they are
  1745 // set to visible if one of their ancestors is invisible)
  1746 /* static */
  1747 void find_first_visible_parent(QWindow* aItem, QWindow*& aVisibleItem)
  1749     NS_ENSURE_TRUE_VOID(aItem);
  1751     aVisibleItem = nullptr;
  1752     QWindow* parItem = nullptr;
  1753     while (!aVisibleItem) {
  1754         if (aItem->isVisible()) {
  1755             aVisibleItem = aItem;
  1757         else {
  1758             parItem = aItem->parent();
  1759             if (parItem) {
  1760                 aItem = parItem;
  1762             else {
  1763                 aItem->setVisible(true);
  1764                 aVisibleItem = aItem;
  1770 NS_IMETHODIMP
  1771 nsWindow::GetScreenBounds(nsIntRect &aRect)
  1773     aRect = nsIntRect(nsIntPoint(0, 0), mBounds.Size());
  1774     if (mIsTopLevel) {
  1775         QPoint pos = mWidget->position();
  1776         aRect.MoveTo(pos.x(), pos.y());
  1778     else {
  1779         aRect.MoveTo(WidgetToScreenOffset());
  1781     LOG(("GetScreenBounds %d %d | %d %d | %d %d\n",
  1782          aRect.x, aRect.y,
  1783          mBounds.width, mBounds.height,
  1784          aRect.width, aRect.height));
  1785     return NS_OK;
  1788 NS_IMETHODIMP
  1789 nsWindow::SetIcon(const nsAString& aIconSpec)
  1791     if (!mWidget)
  1792         return NS_OK;
  1794     nsCOMPtr<nsIFile> iconFile;
  1795     nsAutoCString path;
  1796     nsTArray<nsCString> iconList;
  1798     // Look for icons with the following suffixes appended to the base name.
  1799     // The last two entries (for the old XPM format) will be ignored unless
  1800     // no icons are found using the other suffixes. XPM icons are depricated.
  1802     const char extensions[6][7] = { ".png", "16.png", "32.png", "48.png",
  1803                                     ".xpm", "16.xpm" };
  1805     for (uint32_t i = 0; i < ArrayLength(extensions); i++) {
  1806         // Don't bother looking for XPM versions if we found a PNG.
  1807         if (i == ArrayLength(extensions) - 2 && iconList.Length())
  1808             break;
  1810         nsAutoString extension;
  1811         extension.AppendASCII(extensions[i]);
  1813         ResolveIconName(aIconSpec, extension, getter_AddRefs(iconFile));
  1814         if (iconFile) {
  1815             iconFile->GetNativePath(path);
  1816             iconList.AppendElement(path);
  1820     // leave the default icon intact if no matching icons were found
  1821     if (iconList.Length() == 0)
  1822         return NS_OK;
  1824     return SetWindowIconList(iconList);
  1827 NS_IMETHODIMP
  1828 nsWindow::CaptureMouse(bool aCapture)
  1830     LOG(("CaptureMouse %p\n", (void *)this));
  1832     if (!mWidget)
  1833         return NS_OK;
  1835     mWidget->setMouseGrabEnabled(aCapture);
  1837     return NS_OK;
  1840 bool
  1841 nsWindow::CheckForRollup(double aMouseX, double aMouseY,
  1842                          bool aIsWheel)
  1844     nsIRollupListener* rollupListener = GetActiveRollupListener();
  1845     nsCOMPtr<nsIWidget> rollupWidget;
  1846     if (rollupListener) {
  1847         rollupWidget = rollupListener->GetRollupWidget();
  1849     if (!rollupWidget) {
  1850         nsBaseWidget::gRollupListener = nullptr;
  1851         return false;
  1854     bool retVal = false;
  1855     MozQWidget *currentPopup =
  1856         (MozQWidget *)rollupWidget->GetNativeData(NS_NATIVE_WINDOW);
  1857     if (!is_mouse_in_window(currentPopup, aMouseX, aMouseY)) {
  1858         bool rollup = true;
  1859         if (aIsWheel) {
  1860             rollup = rollupListener->ShouldRollupOnMouseWheelEvent();
  1861             retVal = true;
  1863         // if we're dealing with menus, we probably have submenus and
  1864         // we don't want to rollup if the clickis in a parent menu of
  1865         // the current submenu
  1866         uint32_t popupsToRollup = UINT32_MAX;
  1867         if (rollupListener) {
  1868             nsAutoTArray<nsIWidget*, 5> widgetChain;
  1869             uint32_t sameTypeCount = rollupListener->GetSubmenuWidgetChain(&widgetChain);
  1870             for (uint32_t i=0; i<widgetChain.Length(); ++i) {
  1871                 nsIWidget* widget =  widgetChain[i];
  1872                 MozQWidget* currWindow =
  1873                     (MozQWidget*) widget->GetNativeData(NS_NATIVE_WINDOW);
  1874                 if (is_mouse_in_window(currWindow, aMouseX, aMouseY)) {
  1875                   if (i < sameTypeCount) {
  1876                     rollup = false;
  1878                   else {
  1879                     popupsToRollup = sameTypeCount;
  1881                   break;
  1883             } // foreach parent menu widget
  1884         } // if rollup listener knows about menus
  1886         // if we've determined that we should still rollup, do it.
  1887         if (rollup) {
  1888             nsIntPoint pos(aMouseX, aMouseY);
  1889             retVal = rollupListener->Rollup(popupsToRollup, &pos, nullptr);
  1893     return retVal;
  1896 /* static */
  1897 bool
  1898 is_mouse_in_window (MozQWidget* aWindow, double aMouseX, double aMouseY)
  1900     return aWindow->geometry().contains(aMouseX, aMouseY);
  1903 NS_IMETHODIMP
  1904 nsWindow::GetAttention(int32_t aCycleCount)
  1906     LOG(("nsWindow::GetAttention [%p]\n", (void *)this));
  1907     return NS_ERROR_NOT_IMPLEMENTED;
  1912 nsEventStatus
  1913 nsWindow::OnCloseEvent(QCloseEvent *aEvent)
  1915     if (!mWidgetListener)
  1916         return nsEventStatus_eIgnore;
  1917     mWidgetListener->RequestWindowClose(this);
  1918     return nsEventStatus_eConsumeNoDefault;
  1922 inline bool
  1923 is_latin_shortcut_key(quint32 aKeyval)
  1925     return ((Qt::Key_0 <= aKeyval && aKeyval <= Qt::Key_9) ||
  1926             (Qt::Key_A <= aKeyval && aKeyval <= Qt::Key_Z));
  1929 nsEventStatus
  1930 nsWindow::DispatchCommandEvent(nsIAtom* aCommand)
  1932     WidgetCommandEvent event(true, nsGkAtoms::onAppCommand, aCommand, this);
  1934     nsEventStatus status;
  1935     DispatchEvent(&event, status);
  1937     return status;
  1940 nsEventStatus
  1941 nsWindow::DispatchContentCommandEvent(int32_t aMsg)
  1943     WidgetContentCommandEvent event(true, aMsg, this);
  1945     nsEventStatus status;
  1946     DispatchEvent(&event, status);
  1948     return status;
  1952 static void
  1953 GetBrandName(nsXPIDLString& brandName)
  1955     nsCOMPtr<nsIStringBundleService> bundleService =
  1956         mozilla::services::GetStringBundleService();
  1958     nsCOMPtr<nsIStringBundle> bundle;
  1959     if (bundleService) {
  1960         bundleService->CreateBundle(
  1961             "chrome://branding/locale/brand.properties",
  1962             getter_AddRefs(bundle));
  1965     if (bundle) {
  1966         bundle->GetStringFromName(
  1967             MOZ_UTF16("brandShortName"),
  1968             getter_Copies(brandName));
  1971     if (brandName.IsEmpty()) {
  1972         brandName.Assign(NS_LITERAL_STRING("Mozilla"));
  1976 NS_IMETHODIMP
  1977 nsWindow::SetWindowClass(const nsAString &xulWinType)
  1979     if (!mWidget) {
  1980         return NS_ERROR_FAILURE;
  1983     nsXPIDLString brandName;
  1984     GetBrandName(brandName);
  1986 #ifdef MOZ_X11
  1987     XClassHint *class_hint = XAllocClassHint();
  1988     if (!class_hint) {
  1989         return NS_ERROR_OUT_OF_MEMORY;
  1991     const char *role = nullptr;
  1992     class_hint->res_name = ToNewCString(xulWinType);
  1993     if (!class_hint->res_name) {
  1994         XFree(class_hint);
  1995         return NS_ERROR_OUT_OF_MEMORY;
  1997     class_hint->res_class = ToNewCString(brandName);
  1998     if (!class_hint->res_class) {
  1999         nsMemory::Free(class_hint->res_name);
  2000         XFree(class_hint);
  2001         return NS_ERROR_OUT_OF_MEMORY;
  2004     // Parse res_name into a name and role. Characters other than
  2005     // [A-Za-z0-9_-] are converted to '_'. Anything after the first
  2006     // colon is assigned to role; if there's no colon, assign the
  2007     // whole thing to both role and res_name.
  2008     for (char *c = class_hint->res_name; *c; c++) {
  2009         if (':' == *c) {
  2010             *c = 0;
  2011             role = c + 1;
  2013         else if (!isascii(*c) || (!isalnum(*c) && ('_' != *c) && ('-' != *c)))
  2014             *c = '_';
  2016     class_hint->res_name[0] = toupper(class_hint->res_name[0]);
  2017     if (!role) role = class_hint->res_name;
  2019     QWindow *widget = mWidget;
  2020     // If widget not show, handle might be null
  2021     if (widget && widget->winId()) {
  2022         XSetClassHint(gfxQtPlatform::GetXDisplay(widget),
  2023                       widget->winId(),
  2024                       class_hint);
  2027     nsMemory::Free(class_hint->res_class);
  2028     nsMemory::Free(class_hint->res_name);
  2029     XFree(class_hint);
  2030 #endif
  2032     return NS_OK;
  2035 void
  2036 nsWindow::NativeResize(int32_t aWidth, int32_t aHeight, bool    aRepaint)
  2038     LOG(("nsWindow::NativeResize [%p] %d %d\n", (void *)this,
  2039          aWidth, aHeight));
  2041     mNeedsResize = false;
  2043     mWidget->resize(aWidth, aHeight);
  2045     if (aRepaint) {
  2046         mWidget->renderLater();
  2050 void
  2051 nsWindow::NativeResize(int32_t aX, int32_t aY,
  2052                        int32_t aWidth, int32_t aHeight,
  2053                        bool    aRepaint)
  2055     LOG(("nsWindow::NativeResize [%p] %d %d %d %d\n", (void *)this,
  2056          aX, aY, aWidth, aHeight));
  2058     mNeedsResize = false;
  2059     mNeedsMove = false;
  2061     mWidget->setGeometry(aX, aY, aWidth, aHeight);
  2063     if (aRepaint) {
  2064         mWidget->renderLater();
  2068 void
  2069 nsWindow::NativeShow(bool aAction)
  2071     if (aAction) {
  2072         // On e10s, we never want the child process or plugin process
  2073         // to go fullscreen because if we do the window because visible
  2074         // do to disabled Qt-Xembed
  2075         mWidget->show();
  2076         // unset our flag now that our window has been shown
  2077         mNeedsShow = false;
  2079     else {
  2080         mWidget->hide();
  2084 NS_IMETHODIMP
  2085 nsWindow::SetHasTransparentBackground(bool aTransparent)
  2087     return NS_ERROR_NOT_IMPLEMENTED;
  2090 NS_IMETHODIMP
  2091 nsWindow::GetHasTransparentBackground(bool& aTransparent)
  2093     aTransparent = mIsTransparent;
  2094     return NS_OK;
  2097 void *
  2098 nsWindow::SetupPluginPort(void)
  2100     NS_WARNING("Not implemented");
  2101     return nullptr;
  2104 nsresult
  2105 nsWindow::SetWindowIconList(const nsTArray<nsCString> &aIconList)
  2107     QIcon icon;
  2109     for (uint32_t i = 0; i < aIconList.Length(); ++i) {
  2110         const char *path = aIconList[i].get();
  2111         LOG(("window [%p] Loading icon from %s\n", (void *)this, path));
  2112         icon.addFile(path);
  2115     mWidget->setIcon(icon);
  2117     return NS_OK;
  2120 void
  2121 nsWindow::SetDefaultIcon(void)
  2123     SetIcon(NS_LITERAL_STRING("default"));
  2126 void nsWindow::QWidgetDestroyed()
  2128     mWidget = nullptr;
  2132 NS_IMETHODIMP
  2133 nsWindow::HideWindowChrome(bool aShouldHide)
  2135     if (!mWidget) {
  2136         // Nothing to hide
  2137         return NS_ERROR_FAILURE;
  2140     // Sawfish, metacity, and presumably other window managers get
  2141     // confused if we change the window decorations while the window
  2142     // is visible.
  2143     bool wasVisible = false;
  2144     if (mWidget->isVisible()) {
  2145         NativeShow(false);
  2146         wasVisible = true;
  2149     if (wasVisible) {
  2150         NativeShow(true);
  2153     return NS_OK;
  2156 //////////////////////////////////////////////////////////////////////
  2158 NS_IMETHODIMP_(bool)
  2159 nsWindow::HasGLContext()
  2161     return false;
  2165 nsIWidget*
  2166 nsWindow::GetParent(void)
  2168     return mParent;
  2171 float
  2172 nsWindow::GetDPI()
  2174     return qApp->primaryScreen()->logicalDotsPerInch();
  2177 void
  2178 nsWindow::OnDestroy(void)
  2180     if (mOnDestroyCalled) {
  2181         return;
  2184     mOnDestroyCalled = true;
  2186     // release references to children and device context
  2187     nsBaseWidget::OnDestroy();
  2189     // let go of our parent
  2190     mParent = nullptr;
  2192     nsCOMPtr<nsIWidget> kungFuDeathGrip = this;
  2193     NotifyWindowDestroyed();
  2196 bool
  2197 nsWindow::AreBoundsSane(void)
  2199     if (mBounds.width > 0 && mBounds.height > 0) {
  2200         return true;
  2203     return false;
  2206 void
  2207 nsWindow::SetSoftwareKeyboardState(bool aOpen,
  2208                                    const InputContextAction& aAction)
  2210     if (aOpen) {
  2211         NS_ENSURE_TRUE_VOID(mInputContext.mIMEState.mEnabled !=
  2212                             IMEState::DISABLED);
  2214         // Ensure that opening the virtual keyboard is allowed for this specific
  2215         // InputContext depending on the content.ime.strict.policy pref
  2216         if (mInputContext.mIMEState.mEnabled != IMEState::PLUGIN &&
  2217             Preferences::GetBool("content.ime.strict_policy", false) &&
  2218             !aAction.ContentGotFocusByTrustedCause() &&
  2219             !aAction.UserMightRequestOpenVKB()) {
  2220             return;
  2224     if (aOpen) {
  2225         qApp->inputMethod()->show();
  2226     } else {
  2227         qApp->inputMethod()->hide();
  2230     return;
  2234 void
  2235 nsWindow::ProcessMotionEvent()
  2237     if (mMoveEvent.needDispatch) {
  2238         WidgetMouseEvent event(true, NS_MOUSE_MOVE, this,
  2239                                WidgetMouseEvent::eReal);
  2241         event.refPoint.x = nscoord(mMoveEvent.pos.x());
  2242         event.refPoint.y = nscoord(mMoveEvent.pos.y());
  2244         event.InitBasicModifiers(mMoveEvent.modifiers & Qt::ControlModifier,
  2245                                  mMoveEvent.modifiers & Qt::AltModifier,
  2246                                  mMoveEvent.modifiers & Qt::ShiftModifier,
  2247                                  mMoveEvent.modifiers & Qt::MetaModifier);
  2248         event.clickCount      = 0;
  2250         DispatchEvent(&event);
  2251         mMoveEvent.needDispatch = false;
  2254     mTimerStarted = false;

mercurial