widget/qt/nsWindow.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/widget/qt/nsWindow.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2256 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +/* vim:expandtab:shiftwidth=4:tabstop=4:
     1.6 + */
     1.7 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    1.10 +
    1.11 +#include "mozilla/ArrayUtils.h"
    1.12 +#include "mozilla/MiscEvents.h"
    1.13 +#include "mozilla/MouseEvents.h"
    1.14 +#include "mozilla/TextEvents.h"
    1.15 +#include "mozilla/TouchEvents.h"
    1.16 +
    1.17 +#include <QGuiApplication>
    1.18 +#include <QtGui/QCursor>
    1.19 +#include <QIcon>
    1.20 +#include <QMouseEvent>
    1.21 +#include <QWheelEvent>
    1.22 +#include <QResizeEvent>
    1.23 +#include <QPaintEngine>
    1.24 +#include <QMimeData>
    1.25 +#include <QScreen>
    1.26 +
    1.27 +#include <QtCore/QDebug>
    1.28 +#include <QtCore/QEvent>
    1.29 +#include <QtCore/QVariant>
    1.30 +#include <algorithm>
    1.31 +
    1.32 +#ifdef MOZ_X11
    1.33 +#include <X11/Xlib.h>
    1.34 +#include <X11/Xutil.h>
    1.35 +#endif //MOZ_X11
    1.36 +
    1.37 +#include "nsXULAppAPI.h"
    1.38 +
    1.39 +#include "prlink.h"
    1.40 +
    1.41 +#include "nsWindow.h"
    1.42 +#include "mozqwidget.h"
    1.43 +
    1.44 +#include "nsIdleService.h"
    1.45 +#include "nsRenderingContext.h"
    1.46 +#include "nsIRollupListener.h"
    1.47 +#include "nsWidgetsCID.h"
    1.48 +#include "nsQtKeyUtils.h"
    1.49 +#include "mozilla/Services.h"
    1.50 +#include "mozilla/Preferences.h"
    1.51 +#include "mozilla/Likely.h"
    1.52 +#include "mozilla/layers/LayersTypes.h"
    1.53 +#include "nsIWidgetListener.h"
    1.54 +#include "ClientLayerManager.h"
    1.55 +#include "BasicLayers.h"
    1.56 +
    1.57 +#include "nsIStringBundle.h"
    1.58 +#include "nsGfxCIID.h"
    1.59 +
    1.60 +#include "imgIContainer.h"
    1.61 +#include "nsGfxCIID.h"
    1.62 +#include "nsIInterfaceRequestorUtils.h"
    1.63 +#include "nsAutoPtr.h"
    1.64 +
    1.65 +#include "gfxQtPlatform.h"
    1.66 +
    1.67 +#include "nsIDOMWheelEvent.h"
    1.68 +
    1.69 +#include "GLContext.h"
    1.70 +
    1.71 +#ifdef MOZ_X11
    1.72 +#include "keysym2ucs.h"
    1.73 +#endif
    1.74 +
    1.75 +#include "Layers.h"
    1.76 +#include "GLContextProvider.h"
    1.77 +
    1.78 +using namespace mozilla;
    1.79 +using namespace mozilla::gl;
    1.80 +using namespace mozilla::widget;
    1.81 +using namespace mozilla::gfx;
    1.82 +using namespace mozilla::layers;
    1.83 +using mozilla::gl::GLContext;
    1.84 +
    1.85 +#define kWindowPositionSlop 20
    1.86 +
    1.87 +// Qt
    1.88 +static const int WHEEL_DELTA = 120;
    1.89 +static bool gGlobalsInitialized = false;
    1.90 +static bool sAltGrModifier = false;
    1.91 +
    1.92 +static void find_first_visible_parent(QWindow* aItem, QWindow*& aVisibleItem);
    1.93 +static bool is_mouse_in_window (MozQWidget* aWindow, double aMouseX, double aMouseY);
    1.94 +static bool isContextMenuKeyEvent(const QKeyEvent *qe);
    1.95 +static void InitKeyEvent(WidgetKeyboardEvent &aEvent, QKeyEvent *aQEvent);
    1.96 +
    1.97 +nsWindow::nsWindow()
    1.98 +{
    1.99 +    LOG(("%s [%p]\n", __PRETTY_FUNCTION__, (void *)this));
   1.100 +
   1.101 +    mIsTopLevel       = false;
   1.102 +    mIsDestroyed      = false;
   1.103 +    mIsShown          = false;
   1.104 +    mEnabled          = true;
   1.105 +    mWidget              = nullptr;
   1.106 +    mVisible           = false;
   1.107 +    mActivatePending     = false;
   1.108 +    mWindowType          = eWindowType_child;
   1.109 +    mSizeState           = nsSizeMode_Normal;
   1.110 +    mLastSizeMode        = nsSizeMode_Normal;
   1.111 +    mQCursor             = Qt::ArrowCursor;
   1.112 +    mNeedsResize         = false;
   1.113 +    mNeedsMove           = false;
   1.114 +    mListenForResizes    = false;
   1.115 +    mNeedsShow           = false;
   1.116 +    mTimerStarted        = false;
   1.117 +    mMoveEvent.needDispatch = false;
   1.118 +
   1.119 +    if (!gGlobalsInitialized) {
   1.120 +        gfxPlatform::GetPlatform();
   1.121 +        gGlobalsInitialized = true;
   1.122 +    }
   1.123 +
   1.124 +    memset(mKeyDownFlags, 0, sizeof(mKeyDownFlags));
   1.125 +
   1.126 +    mIsTransparent = false;
   1.127 +
   1.128 +    mCursor = eCursor_standard;
   1.129 +}
   1.130 +
   1.131 +nsWindow::~nsWindow()
   1.132 +{
   1.133 +    LOG(("%s [%p]\n", __PRETTY_FUNCTION__, (void *)this));
   1.134 +
   1.135 +    Destroy();
   1.136 +}
   1.137 +
   1.138 +nsresult
   1.139 +nsWindow::Create(nsIWidget        *aParent,
   1.140 +                 nsNativeWidget    aNativeParent,
   1.141 +                 const nsIntRect  &aRect,
   1.142 +                 nsDeviceContext *aContext,
   1.143 +                 nsWidgetInitData *aInitData)
   1.144 +{
   1.145 +    // only set the base parent if we're not going to be a dialog or a
   1.146 +    // toplevel
   1.147 +    nsIWidget *baseParent = aParent;
   1.148 +
   1.149 +    // initialize all the common bits of this class
   1.150 +    BaseCreate(baseParent, aRect, aContext, aInitData);
   1.151 +
   1.152 +    mVisible = true;
   1.153 +
   1.154 +    // and do our common creation
   1.155 +    mParent = (nsWindow *)aParent;
   1.156 +
   1.157 +    // save our bounds
   1.158 +    mBounds = aRect;
   1.159 +
   1.160 +    // find native parent
   1.161 +    MozQWidget *parent = nullptr;
   1.162 +
   1.163 +    if (aParent != nullptr) {
   1.164 +        parent = static_cast<MozQWidget*>(aParent->GetNativeData(NS_NATIVE_WIDGET));
   1.165 +    } else if (aNativeParent != nullptr) {
   1.166 +        parent = static_cast<MozQWidget*>(aNativeParent);
   1.167 +        if (parent && mParent == nullptr) {
   1.168 +            mParent = parent->getReceiver();
   1.169 +        }
   1.170 +    }
   1.171 +
   1.172 +    LOG(("Create: nsWindow [%p] mWidget:[%p] parent:[%p], natPar:[%p] mParent:%p\n", (void *)this, (void*)mWidget, parent, aNativeParent, mParent));
   1.173 +
   1.174 +    // ok, create our QGraphicsWidget
   1.175 +    mWidget = createQWidget(parent, aInitData);
   1.176 +
   1.177 +    if (!mWidget) {
   1.178 +        return NS_ERROR_OUT_OF_MEMORY;
   1.179 +    }
   1.180 +
   1.181 +
   1.182 +    // resize so that everything is set to the right dimensions
   1.183 +    Resize(mBounds.x, mBounds.y, mBounds.width, mBounds.height, false);
   1.184 +
   1.185 +    // check if we should listen for resizes
   1.186 +    mListenForResizes = (aNativeParent ||
   1.187 +                         (aInitData && aInitData->mListenForResizes));
   1.188 +
   1.189 +    return NS_OK;
   1.190 +}
   1.191 +
   1.192 +MozQWidget*
   1.193 +nsWindow::createQWidget(MozQWidget* parent,
   1.194 +                        nsWidgetInitData* aInitData)
   1.195 +{
   1.196 +    const char *windowName = nullptr;
   1.197 +    Qt::WindowFlags flags = Qt::Widget;
   1.198 +
   1.199 +    // ok, create our windows
   1.200 +    switch (mWindowType) {
   1.201 +    case eWindowType_dialog:
   1.202 +        windowName = "topLevelDialog";
   1.203 +        flags = Qt::Dialog;
   1.204 +        break;
   1.205 +    case eWindowType_popup:
   1.206 +        windowName = "topLevelPopup";
   1.207 +        flags = Qt::Popup;
   1.208 +        break;
   1.209 +    case eWindowType_toplevel:
   1.210 +        windowName = "topLevelWindow";
   1.211 +        flags = Qt::Window;
   1.212 +        break;
   1.213 +    case eWindowType_invisible:
   1.214 +        windowName = "topLevelInvisible";
   1.215 +        break;
   1.216 +    case eWindowType_child:
   1.217 +    case eWindowType_plugin:
   1.218 +    default: // sheet
   1.219 +        windowName = "paintArea";
   1.220 +        break;
   1.221 +    }
   1.222 +
   1.223 +    MozQWidget* widget = new MozQWidget(this, parent);
   1.224 +    if (!widget) {
   1.225 +        return nullptr;
   1.226 +    }
   1.227 +
   1.228 +    widget->setObjectName(QString(windowName));
   1.229 +    if (mWindowType == eWindowType_invisible) {
   1.230 +        widget->setVisibility(QWindow::Hidden);
   1.231 +    }
   1.232 +    if (mWindowType == eWindowType_dialog) {
   1.233 +        widget->setModality(Qt::WindowModal);
   1.234 +    }
   1.235 +
   1.236 +    widget->create();
   1.237 +
   1.238 +    // create a QGraphicsView if this is a new toplevel window
   1.239 +    LOG(("nsWindow::%s [%p] Created Window: %s, widget:%p, par:%p\n", __FUNCTION__, (void *)this, windowName, widget, parent));
   1.240 +
   1.241 +    return widget;
   1.242 +}
   1.243 +
   1.244 +NS_IMETHODIMP
   1.245 +nsWindow::Destroy(void)
   1.246 +{
   1.247 +    if (mIsDestroyed || !mWidget) {
   1.248 +        return NS_OK;
   1.249 +    }
   1.250 +
   1.251 +    LOG(("nsWindow::Destroy [%p]\n", (void *)this));
   1.252 +    mIsDestroyed = true;
   1.253 +
   1.254 +    /** Need to clean our LayerManager up while still alive */
   1.255 +    if (mLayerManager) {
   1.256 +        mLayerManager->Destroy();
   1.257 +    }
   1.258 +    mLayerManager = nullptr;
   1.259 +
   1.260 +    // It is safe to call DestroyeCompositor several times (here and 
   1.261 +    // in the parent class) since it will take effect only once.
   1.262 +    // The reason we call it here is because on gtk platforms we need 
   1.263 +    // to destroy the compositor before we destroy the gdk window (which
   1.264 +    // destroys the the gl context attached to it).
   1.265 +    DestroyCompositor();
   1.266 +
   1.267 +    ClearCachedResources();
   1.268 +
   1.269 +    nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener();
   1.270 +    if (rollupListener) {
   1.271 +        nsCOMPtr<nsIWidget> rollupWidget = rollupListener->GetRollupWidget();
   1.272 +        if (static_cast<nsIWidget *>(this) == rollupWidget) {
   1.273 +            rollupListener->Rollup(0, nullptr, nullptr);
   1.274 +        }
   1.275 +    }
   1.276 +
   1.277 +    Show(false);
   1.278 +
   1.279 +    // walk the list of children and call destroy on them.  Have to be
   1.280 +    // careful, though -- calling destroy on a kid may actually remove
   1.281 +    // it from our child list, losing its sibling links.
   1.282 +    for (nsIWidget* kid = mFirstChild; kid; ) {
   1.283 +        nsIWidget* next = kid->GetNextSibling();
   1.284 +        kid->Destroy();
   1.285 +        kid = next;
   1.286 +    }
   1.287 +
   1.288 +    // Destroy thebes surface now. Badness can happen if we destroy
   1.289 +    // the surface after its X Window.
   1.290 +    if (mWidget) {
   1.291 +        mWidget->dropReceiver();
   1.292 +
   1.293 +        // Call deleteLater instead of delete; Qt still needs the object
   1.294 +        // to be valid even after sending it a Close event.  We could
   1.295 +        // also set WA_DeleteOnClose, but this gives us more control.
   1.296 +        mWidget->deleteLater();
   1.297 +    }
   1.298 +    mWidget = nullptr;
   1.299 +
   1.300 +    OnDestroy();
   1.301 +
   1.302 +    return NS_OK;
   1.303 +}
   1.304 +
   1.305 +NS_IMETHODIMP
   1.306 +nsWindow::Show(bool aState)
   1.307 +{
   1.308 +    LOG(("nsWindow::Show [%p] state %d\n", (void *)this, aState));
   1.309 +    if (aState == mIsShown) {
   1.310 +        return NS_OK;
   1.311 +    }
   1.312 +
   1.313 +    // Clear our cached resources when the window is hidden.
   1.314 +    if (mIsShown && !aState) {
   1.315 +        ClearCachedResources();
   1.316 +    }
   1.317 +
   1.318 +    mIsShown = aState;
   1.319 +
   1.320 +    if ((aState && !AreBoundsSane()) || !mWidget) {
   1.321 +        LOG(("\tbounds are insane or window hasn't been created yet\n"));
   1.322 +        mNeedsShow = true;
   1.323 +        return NS_OK;
   1.324 +    }
   1.325 +
   1.326 +    if (aState) {
   1.327 +        if (mNeedsMove) {
   1.328 +            NativeResize(mBounds.x, mBounds.y, mBounds.width, mBounds.height,
   1.329 +                         false);
   1.330 +        } else if (mNeedsResize) {
   1.331 +            NativeResize(mBounds.width, mBounds.height, false);
   1.332 +        }
   1.333 +    }
   1.334 +    else {
   1.335 +        // If someone is hiding this widget, clear any needing show flag.
   1.336 +        mNeedsShow = false;
   1.337 +    }
   1.338 +
   1.339 +    NativeShow(aState);
   1.340 +
   1.341 +    return NS_OK;
   1.342 +}
   1.343 +
   1.344 +bool
   1.345 +nsWindow::IsVisible() const
   1.346 +{
   1.347 +    return mIsShown;
   1.348 +}
   1.349 +
   1.350 +NS_IMETHODIMP
   1.351 +nsWindow::ConstrainPosition(bool aAllowSlop, int32_t *aX, int32_t *aY)
   1.352 +{
   1.353 +    if (!mWidget) {
   1.354 +        return NS_ERROR_FAILURE;
   1.355 +    }
   1.356 +
   1.357 +    int32_t screenWidth  = qApp->primaryScreen()->size().width();
   1.358 +    int32_t screenHeight = qApp->primaryScreen()->size().height();
   1.359 +
   1.360 +    if (aAllowSlop) {
   1.361 +        if (*aX < (kWindowPositionSlop - mBounds.width))
   1.362 +            *aX = kWindowPositionSlop - mBounds.width;
   1.363 +        if (*aX > (screenWidth - kWindowPositionSlop))
   1.364 +            *aX = screenWidth - kWindowPositionSlop;
   1.365 +        if (*aY < (kWindowPositionSlop - mBounds.height))
   1.366 +            *aY = kWindowPositionSlop - mBounds.height;
   1.367 +        if (*aY > (screenHeight - kWindowPositionSlop))
   1.368 +            *aY = screenHeight - kWindowPositionSlop;
   1.369 +    } else {
   1.370 +        if (*aX < 0)
   1.371 +            *aX = 0;
   1.372 +        if (*aX > (screenWidth - mBounds.width))
   1.373 +            *aX = screenWidth - mBounds.width;
   1.374 +        if (*aY < 0)
   1.375 +            *aY = 0;
   1.376 +        if (*aY > (screenHeight - mBounds.height))
   1.377 +            *aY = screenHeight - mBounds.height;
   1.378 +    }
   1.379 +
   1.380 +    return NS_OK;
   1.381 +}
   1.382 +
   1.383 +NS_IMETHODIMP
   1.384 +nsWindow::Move(double aX, double aY)
   1.385 +{
   1.386 +    LOG(("nsWindow::Move [%p] %f %f\n", (void *)this,
   1.387 +         aX, aY));
   1.388 +
   1.389 +    int32_t x = NSToIntRound(aX);
   1.390 +    int32_t y = NSToIntRound(aY);
   1.391 +
   1.392 +    if (mIsTopLevel) {
   1.393 +        SetSizeMode(nsSizeMode_Normal);
   1.394 +    }
   1.395 +
   1.396 +    if (x == mBounds.x && y == mBounds.y) {
   1.397 +        return NS_OK;
   1.398 +    }
   1.399 +
   1.400 +    mNeedsMove = false;
   1.401 +
   1.402 +    // update the bounds
   1.403 +    QPoint pos(x, y);
   1.404 +    if (mIsTopLevel) {
   1.405 +        mWidget->setPosition(x, y);
   1.406 +    }
   1.407 +    else if (mWidget) {
   1.408 +        // the position of the widget is set relative to the parent
   1.409 +        // so we map the coordinates accordingly
   1.410 +        pos = mWidget->mapToGlobal(pos);
   1.411 +        mWidget->setPosition(pos);
   1.412 +    }
   1.413 +
   1.414 +    mBounds.x = pos.x();
   1.415 +    mBounds.y = pos.y();
   1.416 +
   1.417 +    NotifyRollupGeometryChange();
   1.418 +    return NS_OK;
   1.419 +}
   1.420 +
   1.421 +NS_IMETHODIMP
   1.422 +nsWindow::Resize(double aWidth, double aHeight, bool aRepaint)
   1.423 +{
   1.424 +    mBounds.width = NSToIntRound(aWidth);
   1.425 +    mBounds.height = NSToIntRound(aHeight);
   1.426 +
   1.427 +    if (!mWidget)
   1.428 +        return NS_OK;
   1.429 +
   1.430 +    if (mIsShown) {
   1.431 +        if (AreBoundsSane()) {
   1.432 +            if (mIsTopLevel || mNeedsShow)
   1.433 +                NativeResize(mBounds.x, mBounds.y,
   1.434 +                             mBounds.width, mBounds.height, aRepaint);
   1.435 +            else
   1.436 +                NativeResize(mBounds.width, mBounds.height, aRepaint);
   1.437 +
   1.438 +            // Does it need to be shown because it was previously insane?
   1.439 +            if (mNeedsShow) {
   1.440 +                NativeShow(true);
   1.441 +            }
   1.442 +        }
   1.443 +        else {
   1.444 +            // If someone has set this so that the needs show flag is false
   1.445 +            // and it needs to be hidden, update the flag and hide the
   1.446 +            // window.  This flag will be cleared the next time someone
   1.447 +            // hides the window or shows it.  It also prevents us from
   1.448 +            // calling NativeShow(false) excessively on the window which
   1.449 +            // causes unneeded X traffic.
   1.450 +            if (!mNeedsShow) {
   1.451 +                mNeedsShow = true;
   1.452 +                NativeShow(false);
   1.453 +            }
   1.454 +        }
   1.455 +    }
   1.456 +    else if (AreBoundsSane() && mListenForResizes) {
   1.457 +        // For widgets that we listen for resizes for (widgets created
   1.458 +        // with native parents) we apparently _always_ have to resize.  I
   1.459 +        // dunno why, but apparently we're lame like that.
   1.460 +        NativeResize(mBounds.width, mBounds.height, aRepaint);
   1.461 +    }
   1.462 +    else {
   1.463 +        mNeedsResize = true;
   1.464 +    }
   1.465 +
   1.466 +    // synthesize a resize event if this isn't a toplevel
   1.467 +    if (mIsTopLevel || mListenForResizes) {
   1.468 +        nsEventStatus status;
   1.469 +        DispatchResizeEvent(mBounds, status);
   1.470 +    }
   1.471 +
   1.472 +    NotifyRollupGeometryChange();
   1.473 +    return NS_OK;
   1.474 +}
   1.475 +
   1.476 +NS_IMETHODIMP
   1.477 +nsWindow::Resize(double aX, double aY, double aWidth, double aHeight,
   1.478 +                 bool aRepaint)
   1.479 +{
   1.480 +    mBounds.x = NSToIntRound(aX);
   1.481 +    mBounds.y = NSToIntRound(aY);
   1.482 +    mBounds.width = NSToIntRound(aWidth);
   1.483 +    mBounds.height = NSToIntRound(aHeight);
   1.484 +
   1.485 +    mPlaced = true;
   1.486 +
   1.487 +    if (!mWidget) {
   1.488 +        return NS_OK;
   1.489 +    }
   1.490 +
   1.491 +    // Has this widget been set to visible?
   1.492 +    if (mIsShown) {
   1.493 +        // Are the bounds sane?
   1.494 +        if (AreBoundsSane()) {
   1.495 +            // Yep?  Resize the window
   1.496 +            NativeResize(mBounds.x, mBounds.y, mBounds.width, mBounds.height,
   1.497 +                         aRepaint);
   1.498 +            // Does it need to be shown because it was previously insane?
   1.499 +            if (mNeedsShow)
   1.500 +                NativeShow(true);
   1.501 +        }
   1.502 +        else {
   1.503 +            // If someone has set this so that the needs show flag is false
   1.504 +            // and it needs to be hidden, update the flag and hide the
   1.505 +            // window.  This flag will be cleared the next time someone
   1.506 +            // hides the window or shows it.  It also prevents us from
   1.507 +            // calling NativeShow(false) excessively on the window which
   1.508 +            // causes unneeded X traffic.
   1.509 +            if (!mNeedsShow) {
   1.510 +                mNeedsShow = true;
   1.511 +                NativeShow(false);
   1.512 +            }
   1.513 +        }
   1.514 +    }
   1.515 +    // If the widget hasn't been shown, mark the widget as needing to be
   1.516 +    // resized before it is shown
   1.517 +    else if (AreBoundsSane() && mListenForResizes) {
   1.518 +        // For widgets that we listen for resizes for (widgets created
   1.519 +        // with native parents) we apparently _always_ have to resize.  I
   1.520 +        // dunno why, but apparently we're lame like that.
   1.521 +        NativeResize(mBounds.x, mBounds.y, mBounds.width, mBounds.height,
   1.522 +                     aRepaint);
   1.523 +    }
   1.524 +    else {
   1.525 +        mNeedsResize = true;
   1.526 +        mNeedsMove = true;
   1.527 +    }
   1.528 +
   1.529 +    if (mIsTopLevel || mListenForResizes) {
   1.530 +        // synthesize a resize event
   1.531 +        nsEventStatus status;
   1.532 +        DispatchResizeEvent(mBounds, status);
   1.533 +    }
   1.534 +
   1.535 +    if (aRepaint) {
   1.536 +        mWidget->renderLater();
   1.537 +    }
   1.538 +
   1.539 +    NotifyRollupGeometryChange();
   1.540 +    return NS_OK;
   1.541 +}
   1.542 +
   1.543 +NS_IMETHODIMP
   1.544 +nsWindow::Enable(bool aState)
   1.545 +{
   1.546 +    mEnabled = aState;
   1.547 +
   1.548 +    return NS_OK;
   1.549 +}
   1.550 +
   1.551 +bool
   1.552 +nsWindow::IsEnabled() const
   1.553 +{
   1.554 +    return mEnabled;
   1.555 +}
   1.556 +
   1.557 +NS_IMETHODIMP
   1.558 +nsWindow::SetFocus(bool aRaise)
   1.559 +{
   1.560 +    // Make sure that our owning widget has focus.  If it doesn't try to
   1.561 +    // grab it.  Note that we don't set our focus flag in this case.
   1.562 +    LOGFOCUS(("  SetFocus [%p]\n", (void *)this));
   1.563 +
   1.564 +    if (!mWidget) {
   1.565 +        return NS_ERROR_FAILURE;
   1.566 +    }
   1.567 +
   1.568 +    if (mWidget->focusObject()) {
   1.569 +        return NS_OK;
   1.570 +    }
   1.571 +
   1.572 +    // Because QGraphicsItem cannot get the focus if they are
   1.573 +    // invisible, we look up the chain, for the lowest visible
   1.574 +    // parent and focus that one
   1.575 +    QWindow* realFocusItem = nullptr;
   1.576 +    find_first_visible_parent(mWidget, realFocusItem);
   1.577 +
   1.578 +    if (!realFocusItem || realFocusItem->focusObject()) {
   1.579 +        return NS_OK;
   1.580 +    }
   1.581 +
   1.582 +    if (aRaise && mWidget) {
   1.583 +        // the raising has to happen on the view widget
   1.584 +        mWidget->raise();
   1.585 +    }
   1.586 +
   1.587 +    // XXXndeakin why is this here? It should dispatch only when the OS
   1.588 +    // notifies us.
   1.589 +    DispatchActivateEvent();
   1.590 +
   1.591 +    return NS_OK;
   1.592 +}
   1.593 +
   1.594 +NS_IMETHODIMP
   1.595 +nsWindow::ConfigureChildren(const nsTArray<nsIWidget::Configuration>& aConfigurations)
   1.596 +{
   1.597 +    for (uint32_t i = 0; i < aConfigurations.Length(); ++i) {
   1.598 +        const Configuration& configuration = aConfigurations[i];
   1.599 +
   1.600 +        nsWindow* w = static_cast<nsWindow*>(configuration.mChild);
   1.601 +        NS_ASSERTION(w->GetParent() == this,
   1.602 +                     "Configured widget is not a child");
   1.603 +
   1.604 +        if (w->mBounds.Size() != configuration.mBounds.Size()) {
   1.605 +            w->Resize(configuration.mBounds.x, configuration.mBounds.y,
   1.606 +                      configuration.mBounds.width, configuration.mBounds.height,
   1.607 +                      true);
   1.608 +        } else if (w->mBounds.TopLeft() != configuration.mBounds.TopLeft()) {
   1.609 +            w->Move(configuration.mBounds.x, configuration.mBounds.y);
   1.610 +        }
   1.611 +    }
   1.612 +    return NS_OK;
   1.613 +}
   1.614 +
   1.615 +NS_IMETHODIMP
   1.616 +nsWindow::Invalidate(const nsIntRect &aRect)
   1.617 +{
   1.618 +    LOGDRAW(("Invalidate (rect) [%p,%p]: %d %d %d %d\n", (void *)this,
   1.619 +             (void*)mWidget,aRect.x, aRect.y, aRect.width, aRect.height));
   1.620 +
   1.621 +    if (!mWidget) {
   1.622 +        return NS_OK;
   1.623 +    }
   1.624 +
   1.625 +    mWidget->renderLater();
   1.626 +
   1.627 +    return NS_OK;
   1.628 +}
   1.629 +
   1.630 +nsIntPoint
   1.631 +nsWindow::WidgetToScreenOffset()
   1.632 +{
   1.633 +    NS_ENSURE_TRUE(mWidget, nsIntPoint(0,0));
   1.634 +
   1.635 +    QPoint origin(0, 0);
   1.636 +    origin = mWidget->mapToGlobal(origin);
   1.637 +
   1.638 +    return nsIntPoint(origin.x(), origin.y());
   1.639 +}
   1.640 +
   1.641 +void*
   1.642 +nsWindow::GetNativeData(uint32_t aDataType)
   1.643 +{
   1.644 +    switch (aDataType) {
   1.645 +    case NS_NATIVE_WINDOW:
   1.646 +    case NS_NATIVE_WIDGET: {
   1.647 +        return mWidget;
   1.648 +    }
   1.649 +    case NS_NATIVE_SHAREABLE_WINDOW: {
   1.650 +        return mWidget ? (void*)mWidget->winId() : nullptr;
   1.651 +    }
   1.652 +    case NS_NATIVE_DISPLAY: {
   1.653 +#ifdef MOZ_X11
   1.654 +        return gfxQtPlatform::GetXDisplay(mWidget);
   1.655 +#endif
   1.656 +        break;
   1.657 +    }
   1.658 +    case NS_NATIVE_PLUGIN_PORT:
   1.659 +    case NS_NATIVE_GRAPHIC:
   1.660 +    case NS_NATIVE_SHELLWIDGET: {
   1.661 +        break;
   1.662 +    }
   1.663 +    default:
   1.664 +        NS_WARNING("nsWindow::GetNativeData called with bad value");
   1.665 +        return nullptr;
   1.666 +    }
   1.667 +    LOG(("nsWindow::%s [%p] aDataType:%i\n", __FUNCTION__, (void *)this, aDataType));
   1.668 +    return nullptr;
   1.669 +}
   1.670 +
   1.671 +NS_IMETHODIMP
   1.672 +nsWindow::DispatchEvent(WidgetGUIEvent* aEvent, nsEventStatus& aStatus)
   1.673 +{
   1.674 +#ifdef DEBUG
   1.675 +    debug_DumpEvent(stdout, aEvent->widget, aEvent,
   1.676 +                    nsAutoCString("something"), 0);
   1.677 +#endif
   1.678 +
   1.679 +    aStatus = nsEventStatus_eIgnore;
   1.680 +
   1.681 +    // send it to the standard callback
   1.682 +    if (mWidgetListener) {
   1.683 +        aStatus = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents);
   1.684 +    }
   1.685 +
   1.686 +    return NS_OK;
   1.687 +}
   1.688 +
   1.689 +NS_IMETHODIMP_(void)
   1.690 +nsWindow::SetInputContext(const InputContext& aContext,
   1.691 +                          const InputContextAction& aAction)
   1.692 +{
   1.693 +    NS_ENSURE_TRUE_VOID(mWidget);
   1.694 +
   1.695 +    // SetSoftwareKeyboardState uses mInputContext,
   1.696 +    // so, before calling that, record aContext in mInputContext.
   1.697 +    mInputContext = aContext;
   1.698 +
   1.699 +    switch (mInputContext.mIMEState.mEnabled) {
   1.700 +        case IMEState::ENABLED:
   1.701 +        case IMEState::PASSWORD:
   1.702 +        case IMEState::PLUGIN:
   1.703 +            SetSoftwareKeyboardState(true, aAction);
   1.704 +            break;
   1.705 +        default:
   1.706 +            SetSoftwareKeyboardState(false, aAction);
   1.707 +            break;
   1.708 +    }
   1.709 +}
   1.710 +
   1.711 +NS_IMETHODIMP_(InputContext)
   1.712 +nsWindow::GetInputContext()
   1.713 +{
   1.714 +    mInputContext.mIMEState.mOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
   1.715 +    // Our qt widget looks like using only one context per process.
   1.716 +    // However, it's better to set the context's pointer.
   1.717 +    mInputContext.mNativeIMEContext = qApp->inputMethod();
   1.718 +
   1.719 +    return mInputContext;
   1.720 +}
   1.721 +
   1.722 +NS_IMETHODIMP
   1.723 +nsWindow::ReparentNativeWidget(nsIWidget *aNewParent)
   1.724 +{
   1.725 +    NS_PRECONDITION(aNewParent, "");
   1.726 +
   1.727 +    MozQWidget* newParent = static_cast<MozQWidget*>(aNewParent->GetNativeData(NS_NATIVE_WINDOW));
   1.728 +    NS_ASSERTION(newParent, "Parent widget has a null native window handle");
   1.729 +    if (mWidget) {
   1.730 +        mWidget->setParent(newParent);
   1.731 +    }
   1.732 +    return NS_OK;
   1.733 +}
   1.734 +
   1.735 +NS_IMETHODIMP
   1.736 +nsWindow::MakeFullScreen(bool aFullScreen)
   1.737 +{
   1.738 +    NS_ENSURE_TRUE(mWidget, NS_ERROR_FAILURE);
   1.739 +
   1.740 +    if (aFullScreen) {
   1.741 +        if (mSizeMode != nsSizeMode_Fullscreen) {
   1.742 +            mLastSizeMode = mSizeMode;
   1.743 +        }
   1.744 +
   1.745 +        mSizeMode = nsSizeMode_Fullscreen;
   1.746 +        mWidget->showFullScreen();
   1.747 +    }
   1.748 +    else {
   1.749 +        mSizeMode = mLastSizeMode;
   1.750 +
   1.751 +        switch (mSizeMode) {
   1.752 +        case nsSizeMode_Maximized:
   1.753 +            mWidget->showMaximized();
   1.754 +            break;
   1.755 +        case nsSizeMode_Minimized:
   1.756 +            mWidget->showMinimized();
   1.757 +            break;
   1.758 +        case nsSizeMode_Normal:
   1.759 +            mWidget->showNormal();
   1.760 +            break;
   1.761 +        default:
   1.762 +            mWidget->showNormal();
   1.763 +            break;
   1.764 +        }
   1.765 +    }
   1.766 +
   1.767 +    NS_ASSERTION(mLastSizeMode != nsSizeMode_Fullscreen,
   1.768 +                 "mLastSizeMode should never be fullscreen");
   1.769 +    return nsBaseWidget::MakeFullScreen(aFullScreen);
   1.770 +}
   1.771 +
   1.772 +LayerManager*
   1.773 +nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
   1.774 +                          LayersBackend aBackendHint,
   1.775 +                          LayerManagerPersistence aPersistence,
   1.776 +                          bool* aAllowRetaining)
   1.777 +{
   1.778 +    if (!mLayerManager && eTransparencyTransparent == GetTransparencyMode()) {
   1.779 +        mLayerManager = CreateBasicLayerManager();
   1.780 +    }
   1.781 +
   1.782 +    return nsBaseWidget::GetLayerManager(aShadowManager, aBackendHint,
   1.783 +                                         aPersistence, aAllowRetaining);
   1.784 +}
   1.785 +
   1.786 +void
   1.787 +nsWindow::UserActivity()
   1.788 +{
   1.789 +    if (!mIdleService) {
   1.790 +        mIdleService = do_GetService("@mozilla.org/widget/idleservice;1");
   1.791 +    }
   1.792 +
   1.793 +    if (mIdleService) {
   1.794 +        mIdleService->ResetIdleTimeOut(0);
   1.795 +    }
   1.796 +}
   1.797 +
   1.798 +uint32_t
   1.799 +nsWindow::GetGLFrameBufferFormat()
   1.800 +{
   1.801 +    if (mLayerManager &&
   1.802 +        mLayerManager->GetBackendType() == mozilla::layers::LayersBackend::LAYERS_OPENGL) {
   1.803 +        return LOCAL_GL_RGB;
   1.804 +    }
   1.805 +    return LOCAL_GL_NONE;
   1.806 +}
   1.807 +
   1.808 +NS_IMETHODIMP
   1.809 +nsWindow::SetCursor(nsCursor aCursor)
   1.810 +{
   1.811 +    if (mCursor == aCursor) {
   1.812 +        return NS_OK;
   1.813 +    }
   1.814 +
   1.815 +    mCursor = aCursor;
   1.816 +    if (mWidget) {
   1.817 +        mWidget->SetCursor(mCursor);
   1.818 +    }
   1.819 +    return NS_OK;
   1.820 +}
   1.821 +
   1.822 +NS_IMETHODIMP
   1.823 +nsWindow::SetTitle(const nsAString& aTitle)
   1.824 +{
   1.825 +    QString qStr(QString::fromUtf16((const ushort*)aTitle.BeginReading(), aTitle.Length()));
   1.826 +
   1.827 +    mWidget->setTitle(qStr);
   1.828 +
   1.829 +    return NS_OK;
   1.830 +}
   1.831 +
   1.832 +// EVENTS
   1.833 +
   1.834 +void
   1.835 +nsWindow::OnPaint()
   1.836 +{
   1.837 +    LOGDRAW(("nsWindow::%s [%p]\n", __FUNCTION__, (void *)this));
   1.838 +    nsIWidgetListener* listener =
   1.839 +        mAttachedWidgetListener ? mAttachedWidgetListener : mWidgetListener;
   1.840 +    if (!listener) {
   1.841 +        return;
   1.842 +    }
   1.843 +
   1.844 +    listener->WillPaintWindow(this);
   1.845 +
   1.846 +    switch (GetLayerManager()->GetBackendType()) {
   1.847 +        case mozilla::layers::LayersBackend::LAYERS_CLIENT: {
   1.848 +            nsIntRegion region(nsIntRect(0, 0, mWidget->width(), mWidget->height()));
   1.849 +            listener->PaintWindow(this, region);
   1.850 +            break;
   1.851 +        }
   1.852 +        default:
   1.853 +            NS_ERROR("Invalid layer manager");
   1.854 +    }
   1.855 +
   1.856 +    listener->DidPaintWindow();
   1.857 +}
   1.858 +
   1.859 +nsEventStatus
   1.860 +nsWindow::moveEvent(QMoveEvent* aEvent)
   1.861 +{
   1.862 +    LOG(("configure event [%p] %d %d\n", (void *)this,
   1.863 +        aEvent->pos().x(),  aEvent->pos().y()));
   1.864 +
   1.865 +    // can we shortcut?
   1.866 +    if (!mWidget || !mWidgetListener)
   1.867 +        return nsEventStatus_eIgnore;
   1.868 +
   1.869 +    if ((mBounds.x == aEvent->pos().x() &&
   1.870 +         mBounds.y == aEvent->pos().y()))
   1.871 +    {
   1.872 +        return nsEventStatus_eIgnore;
   1.873 +    }
   1.874 +
   1.875 +    NotifyWindowMoved(aEvent->pos().x(), aEvent->pos().y());
   1.876 +    return nsEventStatus_eConsumeNoDefault;
   1.877 +}
   1.878 +
   1.879 +nsEventStatus
   1.880 +nsWindow::resizeEvent(QResizeEvent* aEvent)
   1.881 +{
   1.882 +    nsIntRect rect;
   1.883 +
   1.884 +    // Generate XPFE resize event
   1.885 +    GetBounds(rect);
   1.886 +
   1.887 +    rect.width = aEvent->size().width();
   1.888 +    rect.height = aEvent->size().height();
   1.889 +
   1.890 +    mBounds.width = rect.width;
   1.891 +    mBounds.height = rect.height;
   1.892 +
   1.893 +    nsEventStatus status;
   1.894 +    DispatchResizeEvent(rect, status);
   1.895 +    return status;
   1.896 +}
   1.897 +
   1.898 +nsEventStatus
   1.899 +nsWindow::mouseMoveEvent(QMouseEvent* aEvent)
   1.900 +{
   1.901 +    UserActivity();
   1.902 +
   1.903 +    mMoveEvent.pos = aEvent->pos();
   1.904 +    mMoveEvent.modifiers = aEvent->modifiers();
   1.905 +    mMoveEvent.needDispatch = true;
   1.906 +    DispatchMotionToMainThread();
   1.907 +
   1.908 +    return nsEventStatus_eIgnore;
   1.909 +}
   1.910 +
   1.911 +nsEventStatus
   1.912 +nsWindow::mousePressEvent(QMouseEvent* aEvent)
   1.913 +{
   1.914 +    // The user has done something.
   1.915 +    UserActivity();
   1.916 +
   1.917 +    QPoint pos = aEvent->pos();
   1.918 +
   1.919 +    // we check against the widgets geometry, so use parent coordinates
   1.920 +    // for the check
   1.921 +    if (mWidget)
   1.922 +        pos = mWidget->mapToGlobal(pos);
   1.923 +
   1.924 +    if (CheckForRollup( pos.x(), pos.y(), false))
   1.925 +        return nsEventStatus_eIgnore;
   1.926 +
   1.927 +    uint16_t      domButton;
   1.928 +    switch (aEvent->button()) {
   1.929 +    case Qt::MidButton:
   1.930 +        domButton = WidgetMouseEvent::eMiddleButton;
   1.931 +        break;
   1.932 +    case Qt::RightButton:
   1.933 +        domButton = WidgetMouseEvent::eRightButton;
   1.934 +        break;
   1.935 +    default:
   1.936 +        domButton = WidgetMouseEvent::eLeftButton;
   1.937 +        break;
   1.938 +    }
   1.939 +
   1.940 +    WidgetMouseEvent event(true, NS_MOUSE_BUTTON_DOWN, this,
   1.941 +                           WidgetMouseEvent::eReal);
   1.942 +    event.button = domButton;
   1.943 +    InitButtonEvent(event, aEvent, 1);
   1.944 +
   1.945 +    LOG(("%s [%p] button: %d\n", __PRETTY_FUNCTION__, (void*)this, domButton));
   1.946 +
   1.947 +    nsEventStatus status = DispatchEvent(&event);
   1.948 +
   1.949 +    // right menu click on linux should also pop up a context menu
   1.950 +    if (domButton == WidgetMouseEvent::eRightButton &&
   1.951 +        MOZ_LIKELY(!mIsDestroyed)) {
   1.952 +        WidgetMouseEvent contextMenuEvent(true, NS_CONTEXTMENU, this,
   1.953 +                                          WidgetMouseEvent::eReal);
   1.954 +        InitButtonEvent(contextMenuEvent, aEvent, 1);
   1.955 +        DispatchEvent(&contextMenuEvent, status);
   1.956 +    }
   1.957 +
   1.958 +    return status;
   1.959 +}
   1.960 +
   1.961 +nsEventStatus
   1.962 +nsWindow::mouseReleaseEvent(QMouseEvent* aEvent)
   1.963 +{
   1.964 +    // The user has done something.
   1.965 +    UserActivity();
   1.966 +
   1.967 +    uint16_t domButton;
   1.968 +
   1.969 +    switch (aEvent->button()) {
   1.970 +    case Qt::MidButton:
   1.971 +        domButton = WidgetMouseEvent::eMiddleButton;
   1.972 +        break;
   1.973 +    case Qt::RightButton:
   1.974 +        domButton = WidgetMouseEvent::eRightButton;
   1.975 +        break;
   1.976 +    default:
   1.977 +        domButton = WidgetMouseEvent::eLeftButton;
   1.978 +        break;
   1.979 +    }
   1.980 +
   1.981 +    LOG(("%s [%p] button: %d\n", __PRETTY_FUNCTION__, (void*)this, domButton));
   1.982 +
   1.983 +    WidgetMouseEvent event(true, NS_MOUSE_BUTTON_UP, this,
   1.984 +                           WidgetMouseEvent::eReal);
   1.985 +    event.button = domButton;
   1.986 +    InitButtonEvent(event, aEvent, 1);
   1.987 +
   1.988 +    nsEventStatus status = DispatchEvent(&event);
   1.989 +
   1.990 +    return status;
   1.991 +}
   1.992 +
   1.993 +nsEventStatus
   1.994 +nsWindow::mouseDoubleClickEvent(QMouseEvent* aEvent)
   1.995 +{
   1.996 +    uint32_t eventType;
   1.997 +
   1.998 +    switch (aEvent->button()) {
   1.999 +    case Qt::MidButton:
  1.1000 +        eventType = WidgetMouseEvent::eMiddleButton;
  1.1001 +        break;
  1.1002 +    case Qt::RightButton:
  1.1003 +        eventType = WidgetMouseEvent::eRightButton;
  1.1004 +        break;
  1.1005 +    default:
  1.1006 +        eventType = WidgetMouseEvent::eLeftButton;
  1.1007 +        break;
  1.1008 +    }
  1.1009 +
  1.1010 +    WidgetMouseEvent event(true, NS_MOUSE_DOUBLECLICK, this,
  1.1011 +                           WidgetMouseEvent::eReal);
  1.1012 +    event.button = eventType;
  1.1013 +
  1.1014 +    InitButtonEvent(event, aEvent, 2);
  1.1015 +    //pressed
  1.1016 +    return DispatchEvent(&event);
  1.1017 +}
  1.1018 +
  1.1019 +nsEventStatus
  1.1020 +nsWindow::focusInEvent(QFocusEvent* aEvent)
  1.1021 +{
  1.1022 +    LOGFOCUS(("OnFocusInEvent [%p]\n", (void *)this));
  1.1023 +
  1.1024 +    if (!mWidget) {
  1.1025 +        return nsEventStatus_eIgnore;
  1.1026 +    }
  1.1027 +
  1.1028 +    DispatchActivateEventOnTopLevelWindow();
  1.1029 +
  1.1030 +    LOGFOCUS(("Events sent from focus in event [%p]\n", (void *)this));
  1.1031 +    return nsEventStatus_eIgnore;
  1.1032 +}
  1.1033 +
  1.1034 +nsEventStatus
  1.1035 +nsWindow::focusOutEvent(QFocusEvent* aEvent)
  1.1036 +{
  1.1037 +    LOGFOCUS(("OnFocusOutEvent [%p]\n", (void *)this));
  1.1038 +
  1.1039 +    if (!mWidget) {
  1.1040 +        return nsEventStatus_eIgnore;
  1.1041 +    }
  1.1042 +
  1.1043 +    DispatchDeactivateEventOnTopLevelWindow();
  1.1044 +
  1.1045 +    LOGFOCUS(("Done with container focus out [%p]\n", (void *)this));
  1.1046 +    return nsEventStatus_eIgnore;
  1.1047 +}
  1.1048 +
  1.1049 +nsEventStatus
  1.1050 +nsWindow::keyPressEvent(QKeyEvent* aEvent)
  1.1051 +{
  1.1052 +    LOGFOCUS(("OnKeyPressEvent [%p]\n", (void *)this));
  1.1053 +
  1.1054 +    // The user has done something.
  1.1055 +    UserActivity();
  1.1056 +
  1.1057 +    if (aEvent->key() == Qt::Key_AltGr) {
  1.1058 +        sAltGrModifier = true;
  1.1059 +    }
  1.1060 +
  1.1061 +#ifdef MOZ_X11
  1.1062 +    // before we dispatch a key, check if it's the context menu key.
  1.1063 +    // If so, send a context menu key event instead.
  1.1064 +    if (isContextMenuKeyEvent(aEvent)) {
  1.1065 +        WidgetMouseEvent contextMenuEvent(true, NS_CONTEXTMENU, this,
  1.1066 +                                          WidgetMouseEvent::eReal,
  1.1067 +                                          WidgetMouseEvent::eContextMenuKey);
  1.1068 +        //keyEventToContextMenuEvent(&event, &contextMenuEvent);
  1.1069 +        return DispatchEvent(&contextMenuEvent);
  1.1070 +    }
  1.1071 +
  1.1072 +    uint32_t domCharCode = 0;
  1.1073 +    uint32_t domKeyCode = QtKeyCodeToDOMKeyCode(aEvent->key());
  1.1074 +
  1.1075 +    // get keymap and modifier map from the Xserver
  1.1076 +    Display *display = gfxQtPlatform::GetXDisplay(mWidget);
  1.1077 +    int x_min_keycode = 0, x_max_keycode = 0, xkeysyms_per_keycode;
  1.1078 +    XDisplayKeycodes(display, &x_min_keycode, &x_max_keycode);
  1.1079 +    XModifierKeymap *xmodmap = XGetModifierMapping(display);
  1.1080 +    if (!xmodmap)
  1.1081 +        return nsEventStatus_eIgnore;
  1.1082 +
  1.1083 +    KeySym *xkeymap = XGetKeyboardMapping(display, x_min_keycode, x_max_keycode - x_min_keycode,
  1.1084 +                                          &xkeysyms_per_keycode);
  1.1085 +    if (!xkeymap) {
  1.1086 +        XFreeModifiermap(xmodmap);
  1.1087 +        return nsEventStatus_eIgnore;
  1.1088 +    }
  1.1089 +
  1.1090 +    // create modifier masks
  1.1091 +    qint32 shift_mask = 0, shift_lock_mask = 0, caps_lock_mask = 0, num_lock_mask = 0;
  1.1092 +
  1.1093 +    for (int i = 0; i < 8 * xmodmap->max_keypermod; ++i) {
  1.1094 +        qint32 maskbit = 1 << (i / xmodmap->max_keypermod);
  1.1095 +        KeyCode modkeycode = xmodmap->modifiermap[i];
  1.1096 +        if (modkeycode == NoSymbol) {
  1.1097 +            continue;
  1.1098 +        }
  1.1099 +
  1.1100 +        quint32 mapindex = (modkeycode - x_min_keycode) * xkeysyms_per_keycode;
  1.1101 +        for (int j = 0; j < xkeysyms_per_keycode; ++j) {
  1.1102 +            KeySym modkeysym = xkeymap[mapindex + j];
  1.1103 +            switch (modkeysym) {
  1.1104 +                case XK_Num_Lock:
  1.1105 +                    num_lock_mask |= maskbit;
  1.1106 +                    break;
  1.1107 +                case XK_Caps_Lock:
  1.1108 +                    caps_lock_mask |= maskbit;
  1.1109 +                    break;
  1.1110 +                case XK_Shift_Lock:
  1.1111 +                    shift_lock_mask |= maskbit;
  1.1112 +                    break;
  1.1113 +                case XK_Shift_L:
  1.1114 +                case XK_Shift_R:
  1.1115 +                    shift_mask |= maskbit;
  1.1116 +                    break;
  1.1117 +            }
  1.1118 +        }
  1.1119 +    }
  1.1120 +    // indicate whether is down or not
  1.1121 +    bool shift_state = ((shift_mask & aEvent->nativeModifiers()) != 0) ^
  1.1122 +                          (bool)(shift_lock_mask & aEvent->nativeModifiers());
  1.1123 +    bool capslock_state = (bool)(caps_lock_mask & aEvent->nativeModifiers());
  1.1124 +
  1.1125 +    // try to find a keysym that we can translate to a DOMKeyCode
  1.1126 +    // this is needed because some of Qt's keycodes cannot be translated
  1.1127 +    // TODO: use US keyboard keymap instead of localised keymap
  1.1128 +    if (!domKeyCode &&
  1.1129 +        aEvent->nativeScanCode() >= (quint32)x_min_keycode &&
  1.1130 +        aEvent->nativeScanCode() <= (quint32)x_max_keycode) {
  1.1131 +        int index = (aEvent->nativeScanCode() - x_min_keycode) * xkeysyms_per_keycode;
  1.1132 +        for(int i = 0; (i < xkeysyms_per_keycode) && (domKeyCode == (quint32)NoSymbol); ++i) {
  1.1133 +            domKeyCode = QtKeyCodeToDOMKeyCode(xkeymap[index + i]);
  1.1134 +        }
  1.1135 +    }
  1.1136 +
  1.1137 +    // store character in domCharCode
  1.1138 +    if (aEvent->text().length() && aEvent->text()[0].isPrint())
  1.1139 +        domCharCode = (int32_t) aEvent->text()[0].unicode();
  1.1140 +
  1.1141 +    KeyNameIndex keyNameIndex =
  1.1142 +        domCharCode ? KEY_NAME_INDEX_PrintableKey :
  1.1143 +                      QtKeyCodeToDOMKeyNameIndex(aEvent->key());
  1.1144 +
  1.1145 +    // If the key isn't autorepeat, we need to send the initial down event
  1.1146 +    if (!aEvent->isAutoRepeat() && !IsKeyDown(domKeyCode)) {
  1.1147 +        // send the key down event
  1.1148 +
  1.1149 +        SetKeyDownFlag(domKeyCode);
  1.1150 +
  1.1151 +        WidgetKeyboardEvent downEvent(true, NS_KEY_DOWN, this);
  1.1152 +        InitKeyEvent(downEvent, aEvent);
  1.1153 +
  1.1154 +        downEvent.keyCode = domKeyCode;
  1.1155 +        downEvent.mKeyNameIndex = keyNameIndex;
  1.1156 +
  1.1157 +        nsEventStatus status = DispatchEvent(&downEvent);
  1.1158 +
  1.1159 +        // DispatchEvent can Destroy us (bug 378273)
  1.1160 +        if (MOZ_UNLIKELY(mIsDestroyed)) {
  1.1161 +            qWarning() << "Returning[" << __LINE__ << "]: " << "Window destroyed";
  1.1162 +            return status;
  1.1163 +        }
  1.1164 +
  1.1165 +        // If prevent default on keydown, don't dispatch keypress event
  1.1166 +        if (status == nsEventStatus_eConsumeNoDefault) {
  1.1167 +            return nsEventStatus_eConsumeNoDefault;
  1.1168 +        }
  1.1169 +    }
  1.1170 +
  1.1171 +    // Don't pass modifiers as NS_KEY_PRESS events.
  1.1172 +    // Instead of selectively excluding some keys from NS_KEY_PRESS events,
  1.1173 +    // we instead selectively include (as per MSDN spec
  1.1174 +    // ( http://msdn.microsoft.com/en-us/library/system.windows.forms.control.keypress%28VS.71%29.aspx );
  1.1175 +    // no official spec covers KeyPress events).
  1.1176 +    if (aEvent->key() == Qt::Key_Shift   ||
  1.1177 +        aEvent->key() == Qt::Key_Control ||
  1.1178 +        aEvent->key() == Qt::Key_Meta    ||
  1.1179 +        aEvent->key() == Qt::Key_Alt     ||
  1.1180 +        aEvent->key() == Qt::Key_AltGr) {
  1.1181 +
  1.1182 +        return nsEventStatus_eIgnore;
  1.1183 +    }
  1.1184 +
  1.1185 +    // Look for specialized app-command keys
  1.1186 +    switch (aEvent->key()) {
  1.1187 +        case Qt::Key_Back:
  1.1188 +            return DispatchCommandEvent(nsGkAtoms::Back);
  1.1189 +        case Qt::Key_Forward:
  1.1190 +            return DispatchCommandEvent(nsGkAtoms::Forward);
  1.1191 +        case Qt::Key_Refresh:
  1.1192 +            return DispatchCommandEvent(nsGkAtoms::Reload);
  1.1193 +        case Qt::Key_Stop:
  1.1194 +            return DispatchCommandEvent(nsGkAtoms::Stop);
  1.1195 +        case Qt::Key_Search:
  1.1196 +            return DispatchCommandEvent(nsGkAtoms::Search);
  1.1197 +        case Qt::Key_Favorites:
  1.1198 +            return DispatchCommandEvent(nsGkAtoms::Bookmarks);
  1.1199 +        case Qt::Key_HomePage:
  1.1200 +            return DispatchCommandEvent(nsGkAtoms::Home);
  1.1201 +        case Qt::Key_Copy:
  1.1202 +        case Qt::Key_F16: // F16, F20, F18, F14 are old keysyms for Copy Cut Paste Undo
  1.1203 +            return DispatchContentCommandEvent(NS_CONTENT_COMMAND_COPY);
  1.1204 +        case Qt::Key_Cut:
  1.1205 +        case Qt::Key_F20:
  1.1206 +            return DispatchContentCommandEvent(NS_CONTENT_COMMAND_CUT);
  1.1207 +        case Qt::Key_Paste:
  1.1208 +        case Qt::Key_F18:
  1.1209 +        case Qt::Key_F9:
  1.1210 +            return DispatchContentCommandEvent(NS_CONTENT_COMMAND_PASTE);
  1.1211 +        case Qt::Key_F14:
  1.1212 +            return DispatchContentCommandEvent(NS_CONTENT_COMMAND_UNDO);
  1.1213 +    }
  1.1214 +
  1.1215 +    // Qt::Key_Redo and Qt::Key_Undo are not available yet.
  1.1216 +    if (aEvent->nativeVirtualKey() == 0xff66) {
  1.1217 +        return DispatchContentCommandEvent(NS_CONTENT_COMMAND_REDO);
  1.1218 +    }
  1.1219 +    if (aEvent->nativeVirtualKey() == 0xff65) {
  1.1220 +        return DispatchContentCommandEvent(NS_CONTENT_COMMAND_UNDO);
  1.1221 +    }
  1.1222 +
  1.1223 +    WidgetKeyboardEvent event(true, NS_KEY_PRESS, this);
  1.1224 +    InitKeyEvent(event, aEvent);
  1.1225 +
  1.1226 +    // If there is no charcode attainable from the text, try to
  1.1227 +    // generate it from the keycode. Check shift state for case
  1.1228 +    // Also replace the charcode if ControlModifier is the only
  1.1229 +    // pressed Modifier
  1.1230 +    if ((!domCharCode) &&
  1.1231 +        (QGuiApplication::keyboardModifiers() &
  1.1232 +        (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier))) {
  1.1233 +
  1.1234 +        // get a character from X11 key map
  1.1235 +        KeySym keysym = aEvent->nativeVirtualKey();
  1.1236 +        if (keysym) {
  1.1237 +            domCharCode = (uint32_t) keysym2ucs(keysym);
  1.1238 +            if (domCharCode == -1 || !QChar((quint32)domCharCode).isPrint()) {
  1.1239 +                domCharCode = 0;
  1.1240 +            }
  1.1241 +        }
  1.1242 +
  1.1243 +        // if Ctrl is pressed and domCharCode is not a ASCII character
  1.1244 +        if (domCharCode > 0xFF && (QGuiApplication::keyboardModifiers() & Qt::ControlModifier)) {
  1.1245 +            // replace Unicode character
  1.1246 +            int index = (aEvent->nativeScanCode() - x_min_keycode) * xkeysyms_per_keycode;
  1.1247 +            for (int i = 0; i < xkeysyms_per_keycode; ++i) {
  1.1248 +                if (xkeymap[index + i] <= 0xFF && !shift_state) {
  1.1249 +                    domCharCode = (uint32_t) QChar::toLower((uint) xkeymap[index + i]);
  1.1250 +                    break;
  1.1251 +                }
  1.1252 +            }
  1.1253 +        }
  1.1254 +
  1.1255 +    } else { // The key event should cause a character input.
  1.1256 +             // At that time, we need to reset the modifiers
  1.1257 +             // because nsEditor will not accept a key event
  1.1258 +             // for text input if one or more modifiers are set.
  1.1259 +        event.modifiers &= ~(MODIFIER_CONTROL |
  1.1260 +                             MODIFIER_ALT |
  1.1261 +                             MODIFIER_META);
  1.1262 +    }
  1.1263 +
  1.1264 +    KeySym keysym = NoSymbol;
  1.1265 +    int index = (aEvent->nativeScanCode() - x_min_keycode) * xkeysyms_per_keycode;
  1.1266 +    for (int i = 0; i < xkeysyms_per_keycode; ++i) {
  1.1267 +        if (xkeymap[index + i] == aEvent->nativeVirtualKey()) {
  1.1268 +            if ((i % 2) == 0) { // shifted char
  1.1269 +                keysym = xkeymap[index + i + 1];
  1.1270 +                break;
  1.1271 +            } else { // unshifted char
  1.1272 +                keysym = xkeymap[index + i - 1];
  1.1273 +                break;
  1.1274 +            }
  1.1275 +        }
  1.1276 +        if (xkeysyms_per_keycode - 1 == i) {
  1.1277 +            qWarning() << "Symbol '" << aEvent->nativeVirtualKey() << "' not found";
  1.1278 +        }
  1.1279 +    }
  1.1280 +    QChar unshiftedChar(domCharCode);
  1.1281 +    long ucs = keysym2ucs(keysym);
  1.1282 +    ucs = ucs == -1 ? 0 : ucs;
  1.1283 +    QChar shiftedChar((uint)ucs);
  1.1284 +
  1.1285 +    // append alternativeCharCodes if modifier is pressed
  1.1286 +    // append an additional alternativeCharCodes if domCharCode is not a Latin character
  1.1287 +    // and if one of these modifiers is pressed (i.e. Ctrl, Alt, Meta)
  1.1288 +    if (domCharCode &&
  1.1289 +        (QGuiApplication::keyboardModifiers() &
  1.1290 +        (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier))) {
  1.1291 +
  1.1292 +        event.charCode = domCharCode;
  1.1293 +        event.keyCode = 0;
  1.1294 +        AlternativeCharCode altCharCode(0, 0);
  1.1295 +        // if character has a lower and upper representation
  1.1296 +        if ((unshiftedChar.isUpper() || unshiftedChar.isLower()) &&
  1.1297 +            unshiftedChar.toLower() == shiftedChar.toLower()) {
  1.1298 +            if (shift_state ^ capslock_state) {
  1.1299 +                altCharCode.mUnshiftedCharCode = (uint32_t) QChar::toUpper((uint)domCharCode);
  1.1300 +                altCharCode.mShiftedCharCode = (uint32_t) QChar::toLower((uint)domCharCode);
  1.1301 +            } else {
  1.1302 +                altCharCode.mUnshiftedCharCode = (uint32_t) QChar::toLower((uint)domCharCode);
  1.1303 +                altCharCode.mShiftedCharCode = (uint32_t) QChar::toUpper((uint)domCharCode);
  1.1304 +            }
  1.1305 +        } else {
  1.1306 +            altCharCode.mUnshiftedCharCode = (uint32_t) unshiftedChar.unicode();
  1.1307 +            altCharCode.mShiftedCharCode = (uint32_t) shiftedChar.unicode();
  1.1308 +        }
  1.1309 +
  1.1310 +        // append alternative char code to event
  1.1311 +        if ((altCharCode.mUnshiftedCharCode && altCharCode.mUnshiftedCharCode != domCharCode) ||
  1.1312 +            (altCharCode.mShiftedCharCode && altCharCode.mShiftedCharCode != domCharCode)) {
  1.1313 +            event.alternativeCharCodes.AppendElement(altCharCode);
  1.1314 +        }
  1.1315 +
  1.1316 +        // check if the alternative char codes are latin-1
  1.1317 +        if (altCharCode.mUnshiftedCharCode > 0xFF || altCharCode.mShiftedCharCode > 0xFF) {
  1.1318 +            altCharCode.mUnshiftedCharCode = altCharCode.mShiftedCharCode = 0;
  1.1319 +
  1.1320 +            // find latin char for keycode
  1.1321 +            KeySym keysym = NoSymbol;
  1.1322 +            int index = (aEvent->nativeScanCode() - x_min_keycode) * xkeysyms_per_keycode;
  1.1323 +            // find first shifted and unshifted Latin-Char in XKeyMap
  1.1324 +            for (int i = 0; i < xkeysyms_per_keycode; ++i) {
  1.1325 +                keysym = xkeymap[index + i];
  1.1326 +                if (keysym && keysym <= 0xFF) {
  1.1327 +                    if ((shift_state && (i % 2 == 1)) ||
  1.1328 +                        (!shift_state && (i % 2 == 0))) {
  1.1329 +                        altCharCode.mUnshiftedCharCode = altCharCode.mUnshiftedCharCode ?
  1.1330 +                            altCharCode.mUnshiftedCharCode :
  1.1331 +                            keysym;
  1.1332 +                    } else {
  1.1333 +                        altCharCode.mShiftedCharCode = altCharCode.mShiftedCharCode ?
  1.1334 +                            altCharCode.mShiftedCharCode :
  1.1335 +                            keysym;
  1.1336 +                    }
  1.1337 +                    if (altCharCode.mUnshiftedCharCode && altCharCode.mShiftedCharCode) {
  1.1338 +                        break;
  1.1339 +                    }
  1.1340 +                }
  1.1341 +            }
  1.1342 +
  1.1343 +            if (altCharCode.mUnshiftedCharCode || altCharCode.mShiftedCharCode) {
  1.1344 +                event.alternativeCharCodes.AppendElement(altCharCode);
  1.1345 +            }
  1.1346 +        }
  1.1347 +    } else {
  1.1348 +        event.charCode = domCharCode;
  1.1349 +    }
  1.1350 +
  1.1351 +    if (xmodmap) {
  1.1352 +        XFreeModifiermap(xmodmap);
  1.1353 +    }
  1.1354 +    if (xkeymap) {
  1.1355 +        XFree(xkeymap);
  1.1356 +    }
  1.1357 +
  1.1358 +    event.keyCode = domCharCode ? 0 : domKeyCode;
  1.1359 +    event.mKeyNameIndex = keyNameIndex;
  1.1360 +    // send the key press event
  1.1361 +    return DispatchEvent(&event);
  1.1362 +#else
  1.1363 +
  1.1364 +    //:TODO: fix shortcuts hebrew for non X11,
  1.1365 +    //see Bug 562195##51
  1.1366 +
  1.1367 +    // before we dispatch a key, check if it's the context menu key.
  1.1368 +    // If so, send a context menu key event instead.
  1.1369 +    if (isContextMenuKeyEvent(aEvent)) {
  1.1370 +        WidgetMouseEvent contextMenuEvent(true, NS_CONTEXTMENU, this,
  1.1371 +                                          WidgetMouseEvent::eReal,
  1.1372 +                                          WidgetMouseEvent::eContextMenuKey);
  1.1373 +        //keyEventToContextMenuEvent(&event, &contextMenuEvent);
  1.1374 +        return DispatchEvent(&contextMenuEvent);
  1.1375 +    }
  1.1376 +
  1.1377 +    uint32_t domCharCode = 0;
  1.1378 +    uint32_t domKeyCode = QtKeyCodeToDOMKeyCode(aEvent->key());
  1.1379 +
  1.1380 +    if (aEvent->text().length() && aEvent->text()[0].isPrint()) {
  1.1381 +        domCharCode = (int32_t) aEvent->text()[0].unicode();
  1.1382 +    }
  1.1383 +
  1.1384 +    KeyNameIndex keyNameIndex =
  1.1385 +        domCharCode ? KEY_NAME_INDEX_PrintableKey :
  1.1386 +                      QtKeyCodeToDOMKeyNameIndex(aEvent->key());
  1.1387 +
  1.1388 +    // If the key isn't autorepeat, we need to send the initial down event
  1.1389 +    if (!aEvent->isAutoRepeat() && !IsKeyDown(domKeyCode)) {
  1.1390 +        // send the key down event
  1.1391 +
  1.1392 +        SetKeyDownFlag(domKeyCode);
  1.1393 +
  1.1394 +        WidgetKeyboardEvent downEvent(true, NS_KEY_DOWN, this);
  1.1395 +        InitKeyEvent(downEvent, aEvent);
  1.1396 +
  1.1397 +        downEvent.keyCode = domKeyCode;
  1.1398 +        downEvent.mKeyNameIndex = keyNameIndex;
  1.1399 +
  1.1400 +        nsEventStatus status = DispatchEvent(&downEvent);
  1.1401 +
  1.1402 +        // If prevent default on keydown, don't dispatch keypress event
  1.1403 +        if (status == nsEventStatus_eConsumeNoDefault) {
  1.1404 +            return nsEventStatus_eConsumeNoDefault;
  1.1405 +        }
  1.1406 +    }
  1.1407 +
  1.1408 +    WidgetKeyboardEvent event(true, NS_KEY_PRESS, this);
  1.1409 +    InitKeyEvent(event, aEvent);
  1.1410 +
  1.1411 +    event.charCode = domCharCode;
  1.1412 +
  1.1413 +    event.keyCode = domCharCode ? 0 : domKeyCode;
  1.1414 +    event.mKeyNameIndex = keyNameIndex;
  1.1415 +
  1.1416 +    // send the key press event
  1.1417 +    return DispatchEvent(&event);
  1.1418 +#endif
  1.1419 +}
  1.1420 +
  1.1421 +nsEventStatus
  1.1422 +nsWindow::keyReleaseEvent(QKeyEvent* aEvent)
  1.1423 +{
  1.1424 +    LOGFOCUS(("OnKeyReleaseEvent [%p]\n", (void *)this));
  1.1425 +
  1.1426 +    // The user has done something.
  1.1427 +    UserActivity();
  1.1428 +
  1.1429 +    if (isContextMenuKeyEvent(aEvent)) {
  1.1430 +        // er, what do we do here? DoDefault or NoDefault?
  1.1431 +        return nsEventStatus_eConsumeDoDefault;
  1.1432 +    }
  1.1433 +
  1.1434 +    uint32_t domKeyCode = QtKeyCodeToDOMKeyCode(aEvent->key());
  1.1435 +
  1.1436 +#ifdef MOZ_X11
  1.1437 +    if (!domKeyCode) {
  1.1438 +        // get keymap from the Xserver
  1.1439 +        Display *display = gfxQtPlatform::GetXDisplay(mWidget);
  1.1440 +        int x_min_keycode = 0, x_max_keycode = 0, xkeysyms_per_keycode;
  1.1441 +        XDisplayKeycodes(display, &x_min_keycode, &x_max_keycode);
  1.1442 +        KeySym *xkeymap = XGetKeyboardMapping(display, x_min_keycode, x_max_keycode - x_min_keycode,
  1.1443 +                                              &xkeysyms_per_keycode);
  1.1444 +
  1.1445 +        if (aEvent->nativeScanCode() >= (quint32)x_min_keycode &&
  1.1446 +            aEvent->nativeScanCode() <= (quint32)x_max_keycode) {
  1.1447 +            int index = (aEvent->nativeScanCode() - x_min_keycode) * xkeysyms_per_keycode;
  1.1448 +            for(int i = 0; (i < xkeysyms_per_keycode) && (domKeyCode == (quint32)NoSymbol); ++i) {
  1.1449 +                domKeyCode = QtKeyCodeToDOMKeyCode(xkeymap[index + i]);
  1.1450 +            }
  1.1451 +        }
  1.1452 +
  1.1453 +        if (xkeymap) {
  1.1454 +            XFree(xkeymap);
  1.1455 +        }
  1.1456 +    }
  1.1457 +#endif // MOZ_X11
  1.1458 +
  1.1459 +    // send the key event as a key up event
  1.1460 +    WidgetKeyboardEvent event(true, NS_KEY_UP, this);
  1.1461 +    InitKeyEvent(event, aEvent);
  1.1462 +
  1.1463 +    if (aEvent->key() == Qt::Key_AltGr) {
  1.1464 +        sAltGrModifier = false;
  1.1465 +    }
  1.1466 +
  1.1467 +    event.keyCode = domKeyCode;
  1.1468 +    event.mKeyNameIndex =
  1.1469 +        (aEvent->text().length() && aEvent->text()[0].isPrint()) ?
  1.1470 +            KEY_NAME_INDEX_PrintableKey :
  1.1471 +            QtKeyCodeToDOMKeyNameIndex(aEvent->key());
  1.1472 +
  1.1473 +    // unset the key down flag
  1.1474 +    ClearKeyDownFlag(event.keyCode);
  1.1475 +
  1.1476 +    return DispatchEvent(&event);
  1.1477 +}
  1.1478 +
  1.1479 +nsEventStatus
  1.1480 +nsWindow::wheelEvent(QWheelEvent* aEvent)
  1.1481 +{
  1.1482 +    // check to see if we should rollup
  1.1483 +    WidgetWheelEvent wheelEvent(true, NS_WHEEL_WHEEL, this);
  1.1484 +    wheelEvent.deltaMode = nsIDOMWheelEvent::DOM_DELTA_LINE;
  1.1485 +
  1.1486 +    // negative values for aEvent->delta indicate downward scrolling;
  1.1487 +    // this is opposite Gecko usage.
  1.1488 +    // TODO: Store the unused delta values due to fraction round and add it
  1.1489 +    //       to next event.  The stored values should be reset by other
  1.1490 +    //       direction scroll event.
  1.1491 +    int32_t delta = (int)(aEvent->delta() / WHEEL_DELTA) * -3;
  1.1492 +
  1.1493 +    switch (aEvent->orientation()) {
  1.1494 +    case Qt::Vertical:
  1.1495 +        wheelEvent.deltaY = wheelEvent.lineOrPageDeltaY = delta;
  1.1496 +        break;
  1.1497 +    case Qt::Horizontal:
  1.1498 +        wheelEvent.deltaX = wheelEvent.lineOrPageDeltaX = delta;
  1.1499 +        break;
  1.1500 +    default:
  1.1501 +        Q_ASSERT(0);
  1.1502 +        break;
  1.1503 +    }
  1.1504 +
  1.1505 +    wheelEvent.refPoint.x = nscoord(aEvent->pos().x());
  1.1506 +    wheelEvent.refPoint.y = nscoord(aEvent->pos().y());
  1.1507 +
  1.1508 +    wheelEvent.InitBasicModifiers(aEvent->modifiers() & Qt::ControlModifier,
  1.1509 +                                  aEvent->modifiers() & Qt::AltModifier,
  1.1510 +                                  aEvent->modifiers() & Qt::ShiftModifier,
  1.1511 +                                  aEvent->modifiers() & Qt::MetaModifier);
  1.1512 +    wheelEvent.time = 0;
  1.1513 +
  1.1514 +    return DispatchEvent(&wheelEvent);
  1.1515 +}
  1.1516 +
  1.1517 +nsEventStatus
  1.1518 +nsWindow::showEvent(QShowEvent *)
  1.1519 +{
  1.1520 +    LOG(("%s [%p]\n", __PRETTY_FUNCTION__,(void *)this));
  1.1521 +    mVisible = true;
  1.1522 +    return nsEventStatus_eConsumeDoDefault;
  1.1523 +}
  1.1524 +
  1.1525 +nsEventStatus
  1.1526 +nsWindow::hideEvent(QHideEvent *)
  1.1527 +{
  1.1528 +    LOG(("%s [%p]\n", __PRETTY_FUNCTION__,(void *)this));
  1.1529 +    mVisible = false;
  1.1530 +    return nsEventStatus_eConsumeDoDefault;
  1.1531 +}
  1.1532 +
  1.1533 +nsEventStatus nsWindow::touchEvent(QTouchEvent* aEvent)
  1.1534 +{
  1.1535 +    return nsEventStatus_eIgnore;
  1.1536 +}
  1.1537 +
  1.1538 +nsEventStatus
  1.1539 +nsWindow::tabletEvent(QTabletEvent* aEvent)
  1.1540 +{
  1.1541 +    LOGFOCUS(("nsWindow::%s [%p]\n", __FUNCTION__, (void *)this));
  1.1542 +    return nsEventStatus_eIgnore;
  1.1543 +}
  1.1544 +
  1.1545 +//  Helpers
  1.1546 +
  1.1547 +void
  1.1548 +nsWindow::InitButtonEvent(WidgetMouseEvent& aMoveEvent,
  1.1549 +                          QMouseEvent* aEvent,
  1.1550 +                          int aClickCount)
  1.1551 +{
  1.1552 +    aMoveEvent.refPoint.x = nscoord(aEvent->pos().x());
  1.1553 +    aMoveEvent.refPoint.y = nscoord(aEvent->pos().y());
  1.1554 +
  1.1555 +    aMoveEvent.InitBasicModifiers(aEvent->modifiers() & Qt::ControlModifier,
  1.1556 +                                  aEvent->modifiers() & Qt::AltModifier,
  1.1557 +                                  aEvent->modifiers() & Qt::ShiftModifier,
  1.1558 +                                  aEvent->modifiers() & Qt::MetaModifier);
  1.1559 +    aMoveEvent.clickCount      = aClickCount;
  1.1560 +}
  1.1561 +
  1.1562 +nsEventStatus
  1.1563 +nsWindow::DispatchEvent(WidgetGUIEvent* aEvent)
  1.1564 +{
  1.1565 +    nsEventStatus status;
  1.1566 +    DispatchEvent(aEvent, status);
  1.1567 +    return status;
  1.1568 +}
  1.1569 +
  1.1570 +void
  1.1571 +nsWindow::DispatchActivateEvent(void)
  1.1572 +{
  1.1573 +    if (mWidgetListener) {
  1.1574 +        mWidgetListener->WindowActivated();
  1.1575 +    }
  1.1576 +}
  1.1577 +
  1.1578 +void
  1.1579 +nsWindow::DispatchDeactivateEvent(void)
  1.1580 +{
  1.1581 +    if (mWidgetListener) {
  1.1582 +        mWidgetListener->WindowDeactivated();
  1.1583 +    }
  1.1584 +}
  1.1585 +
  1.1586 +void
  1.1587 +nsWindow::DispatchActivateEventOnTopLevelWindow(void)
  1.1588 +{
  1.1589 +    nsWindow* topLevelWindow = static_cast<nsWindow*>(GetTopLevelWidget());
  1.1590 +    if (topLevelWindow != nullptr) {
  1.1591 +        topLevelWindow->DispatchActivateEvent();
  1.1592 +    }
  1.1593 +}
  1.1594 +
  1.1595 +void
  1.1596 +nsWindow::DispatchDeactivateEventOnTopLevelWindow(void)
  1.1597 +{
  1.1598 +    nsWindow* topLevelWindow = static_cast<nsWindow*>(GetTopLevelWidget());
  1.1599 +    if (topLevelWindow != nullptr) {
  1.1600 +        topLevelWindow->DispatchDeactivateEvent();
  1.1601 +    }
  1.1602 +}
  1.1603 +
  1.1604 +void
  1.1605 +nsWindow::DispatchResizeEvent(nsIntRect &aRect, nsEventStatus &aStatus)
  1.1606 +{
  1.1607 +    aStatus = nsEventStatus_eIgnore;
  1.1608 +    if (mWidgetListener &&
  1.1609 +        mWidgetListener->WindowResized(this, aRect.width, aRect.height)) {
  1.1610 +        aStatus = nsEventStatus_eConsumeNoDefault;
  1.1611 +    }
  1.1612 +}
  1.1613 +
  1.1614 +///////////////////////////////////// OLD GECKO ECENTS need to Sort ///////////////////
  1.1615 +
  1.1616 +/* static */ bool
  1.1617 +isContextMenuKeyEvent(const QKeyEvent *qe)
  1.1618 +{
  1.1619 +    uint32_t kc = QtKeyCodeToDOMKeyCode(qe->key());
  1.1620 +    if (qe->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)) {
  1.1621 +        return false;
  1.1622 +    }
  1.1623 +
  1.1624 +    bool isShift = qe->modifiers() & Qt::ShiftModifier;
  1.1625 +    return (kc == NS_VK_F10 && isShift) ||
  1.1626 +        (kc == NS_VK_CONTEXT_MENU && !isShift);
  1.1627 +}
  1.1628 +
  1.1629 +/* static */void
  1.1630 +InitKeyEvent(WidgetKeyboardEvent &aEvent, QKeyEvent *aQEvent)
  1.1631 +{
  1.1632 +    aEvent.InitBasicModifiers(aQEvent->modifiers() & Qt::ControlModifier,
  1.1633 +                              aQEvent->modifiers() & Qt::AltModifier,
  1.1634 +                              aQEvent->modifiers() & Qt::ShiftModifier,
  1.1635 +                              aQEvent->modifiers() & Qt::MetaModifier);
  1.1636 +    aEvent.mIsRepeat =
  1.1637 +        (aEvent.message == NS_KEY_DOWN || aEvent.message == NS_KEY_PRESS) &&
  1.1638 +        aQEvent->isAutoRepeat();
  1.1639 +    aEvent.time = 0;
  1.1640 +
  1.1641 +    if (sAltGrModifier) {
  1.1642 +        aEvent.modifiers |= (MODIFIER_CONTROL | MODIFIER_ALT);
  1.1643 +    }
  1.1644 +
  1.1645 +    // The transformations above and in qt for the keyval are not invertible
  1.1646 +    // so link to the QKeyEvent (which will vanish soon after return from the
  1.1647 +    // event callback) to give plugins access to hardware_keycode and state.
  1.1648 +    // (An XEvent would be nice but the QKeyEvent is good enough.)
  1.1649 +    aEvent.pluginEvent = (void *)aQEvent;
  1.1650 +}
  1.1651 +
  1.1652 +NS_IMPL_ISUPPORTS_INHERITED(nsWindow, nsBaseWidget, nsISupportsWeakReference)
  1.1653 +
  1.1654 +
  1.1655 +
  1.1656 +void
  1.1657 +nsWindow::ClearCachedResources()
  1.1658 +{
  1.1659 +    if (mLayerManager &&
  1.1660 +        mLayerManager->GetBackendType() == mozilla::layers::LayersBackend::LAYERS_BASIC) {
  1.1661 +        mLayerManager->ClearCachedResources();
  1.1662 +    }
  1.1663 +    for (nsIWidget* kid = mFirstChild; kid; ) {
  1.1664 +        nsIWidget* next = kid->GetNextSibling();
  1.1665 +        static_cast<nsWindow*>(kid)->ClearCachedResources();
  1.1666 +        kid = next;
  1.1667 +    }
  1.1668 +}
  1.1669 +
  1.1670 +NS_IMETHODIMP
  1.1671 +nsWindow::SetParent(nsIWidget *aNewParent)
  1.1672 +{
  1.1673 +    NS_ENSURE_ARG_POINTER(aNewParent);
  1.1674 +
  1.1675 +    nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
  1.1676 +    nsIWidget* parent = GetParent();
  1.1677 +    if (parent) {
  1.1678 +        parent->RemoveChild(this);
  1.1679 +    }
  1.1680 +    ReparentNativeWidget(aNewParent);
  1.1681 +    aNewParent->AddChild(this);
  1.1682 +    return NS_OK;
  1.1683 +}
  1.1684 +
  1.1685 +NS_IMETHODIMP
  1.1686 +nsWindow::SetModal(bool aModal)
  1.1687 +{
  1.1688 +    LOG(("nsWindow::SetModal [%p] %d, widget[%p]\n", (void *)this, aModal, mWidget));
  1.1689 +    if (mWidget) {
  1.1690 +        mWidget->setModality(aModal ? Qt::WindowModal : Qt::NonModal);
  1.1691 +    }
  1.1692 +
  1.1693 +    return NS_OK;
  1.1694 +}
  1.1695 +
  1.1696 +
  1.1697 +NS_IMETHODIMP
  1.1698 +nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement  aPlacement,
  1.1699 +                      nsIWidget                  *aWidget,
  1.1700 +                      bool                        aActivate)
  1.1701 +{
  1.1702 +    return NS_ERROR_NOT_IMPLEMENTED;
  1.1703 +}
  1.1704 +
  1.1705 +NS_IMETHODIMP
  1.1706 +nsWindow::SetSizeMode(int32_t aMode)
  1.1707 +{
  1.1708 +    nsresult rv;
  1.1709 +
  1.1710 +    LOG(("nsWindow::SetSizeMode [%p] %d\n", (void *)this, aMode));
  1.1711 +    if (aMode != nsSizeMode_Minimized) {
  1.1712 +        mWidget->requestActivate();
  1.1713 +    }
  1.1714 +
  1.1715 +    // Save the requested state.
  1.1716 +    rv = nsBaseWidget::SetSizeMode(aMode);
  1.1717 +
  1.1718 +    // return if there's no shell or our current state is the same as
  1.1719 +    // the mode we were just set to.
  1.1720 +    if (!mWidget || mSizeState == mSizeMode) {
  1.1721 +        return rv;
  1.1722 +    }
  1.1723 +
  1.1724 +    switch (aMode) {
  1.1725 +    case nsSizeMode_Maximized:
  1.1726 +        mWidget->showMaximized();
  1.1727 +        break;
  1.1728 +    case nsSizeMode_Minimized:
  1.1729 +        mWidget->showMinimized();
  1.1730 +        break;
  1.1731 +    case nsSizeMode_Fullscreen:
  1.1732 +        mWidget->showFullScreen();
  1.1733 +        break;
  1.1734 +
  1.1735 +    default:
  1.1736 +        // nsSizeMode_Normal, really.
  1.1737 +        mWidget->show();
  1.1738 +        break;
  1.1739 +    }
  1.1740 +
  1.1741 +    mSizeState = mSizeMode;
  1.1742 +
  1.1743 +    return rv;
  1.1744 +}
  1.1745 +
  1.1746 +// Helper function to recursively find the first parent item that
  1.1747 +// is still visible (QGraphicsItem can be hidden even if they are
  1.1748 +// set to visible if one of their ancestors is invisible)
  1.1749 +/* static */
  1.1750 +void find_first_visible_parent(QWindow* aItem, QWindow*& aVisibleItem)
  1.1751 +{
  1.1752 +    NS_ENSURE_TRUE_VOID(aItem);
  1.1753 +
  1.1754 +    aVisibleItem = nullptr;
  1.1755 +    QWindow* parItem = nullptr;
  1.1756 +    while (!aVisibleItem) {
  1.1757 +        if (aItem->isVisible()) {
  1.1758 +            aVisibleItem = aItem;
  1.1759 +        }
  1.1760 +        else {
  1.1761 +            parItem = aItem->parent();
  1.1762 +            if (parItem) {
  1.1763 +                aItem = parItem;
  1.1764 +            }
  1.1765 +            else {
  1.1766 +                aItem->setVisible(true);
  1.1767 +                aVisibleItem = aItem;
  1.1768 +            }
  1.1769 +        }
  1.1770 +    }
  1.1771 +}
  1.1772 +
  1.1773 +NS_IMETHODIMP
  1.1774 +nsWindow::GetScreenBounds(nsIntRect &aRect)
  1.1775 +{
  1.1776 +    aRect = nsIntRect(nsIntPoint(0, 0), mBounds.Size());
  1.1777 +    if (mIsTopLevel) {
  1.1778 +        QPoint pos = mWidget->position();
  1.1779 +        aRect.MoveTo(pos.x(), pos.y());
  1.1780 +    }
  1.1781 +    else {
  1.1782 +        aRect.MoveTo(WidgetToScreenOffset());
  1.1783 +    }
  1.1784 +    LOG(("GetScreenBounds %d %d | %d %d | %d %d\n",
  1.1785 +         aRect.x, aRect.y,
  1.1786 +         mBounds.width, mBounds.height,
  1.1787 +         aRect.width, aRect.height));
  1.1788 +    return NS_OK;
  1.1789 +}
  1.1790 +
  1.1791 +NS_IMETHODIMP
  1.1792 +nsWindow::SetIcon(const nsAString& aIconSpec)
  1.1793 +{
  1.1794 +    if (!mWidget)
  1.1795 +        return NS_OK;
  1.1796 +
  1.1797 +    nsCOMPtr<nsIFile> iconFile;
  1.1798 +    nsAutoCString path;
  1.1799 +    nsTArray<nsCString> iconList;
  1.1800 +
  1.1801 +    // Look for icons with the following suffixes appended to the base name.
  1.1802 +    // The last two entries (for the old XPM format) will be ignored unless
  1.1803 +    // no icons are found using the other suffixes. XPM icons are depricated.
  1.1804 +
  1.1805 +    const char extensions[6][7] = { ".png", "16.png", "32.png", "48.png",
  1.1806 +                                    ".xpm", "16.xpm" };
  1.1807 +
  1.1808 +    for (uint32_t i = 0; i < ArrayLength(extensions); i++) {
  1.1809 +        // Don't bother looking for XPM versions if we found a PNG.
  1.1810 +        if (i == ArrayLength(extensions) - 2 && iconList.Length())
  1.1811 +            break;
  1.1812 +
  1.1813 +        nsAutoString extension;
  1.1814 +        extension.AppendASCII(extensions[i]);
  1.1815 +
  1.1816 +        ResolveIconName(aIconSpec, extension, getter_AddRefs(iconFile));
  1.1817 +        if (iconFile) {
  1.1818 +            iconFile->GetNativePath(path);
  1.1819 +            iconList.AppendElement(path);
  1.1820 +        }
  1.1821 +    }
  1.1822 +
  1.1823 +    // leave the default icon intact if no matching icons were found
  1.1824 +    if (iconList.Length() == 0)
  1.1825 +        return NS_OK;
  1.1826 +
  1.1827 +    return SetWindowIconList(iconList);
  1.1828 +}
  1.1829 +
  1.1830 +NS_IMETHODIMP
  1.1831 +nsWindow::CaptureMouse(bool aCapture)
  1.1832 +{
  1.1833 +    LOG(("CaptureMouse %p\n", (void *)this));
  1.1834 +
  1.1835 +    if (!mWidget)
  1.1836 +        return NS_OK;
  1.1837 +
  1.1838 +    mWidget->setMouseGrabEnabled(aCapture);
  1.1839 +
  1.1840 +    return NS_OK;
  1.1841 +}
  1.1842 +
  1.1843 +bool
  1.1844 +nsWindow::CheckForRollup(double aMouseX, double aMouseY,
  1.1845 +                         bool aIsWheel)
  1.1846 +{
  1.1847 +    nsIRollupListener* rollupListener = GetActiveRollupListener();
  1.1848 +    nsCOMPtr<nsIWidget> rollupWidget;
  1.1849 +    if (rollupListener) {
  1.1850 +        rollupWidget = rollupListener->GetRollupWidget();
  1.1851 +    }
  1.1852 +    if (!rollupWidget) {
  1.1853 +        nsBaseWidget::gRollupListener = nullptr;
  1.1854 +        return false;
  1.1855 +    }
  1.1856 +
  1.1857 +    bool retVal = false;
  1.1858 +    MozQWidget *currentPopup =
  1.1859 +        (MozQWidget *)rollupWidget->GetNativeData(NS_NATIVE_WINDOW);
  1.1860 +    if (!is_mouse_in_window(currentPopup, aMouseX, aMouseY)) {
  1.1861 +        bool rollup = true;
  1.1862 +        if (aIsWheel) {
  1.1863 +            rollup = rollupListener->ShouldRollupOnMouseWheelEvent();
  1.1864 +            retVal = true;
  1.1865 +        }
  1.1866 +        // if we're dealing with menus, we probably have submenus and
  1.1867 +        // we don't want to rollup if the clickis in a parent menu of
  1.1868 +        // the current submenu
  1.1869 +        uint32_t popupsToRollup = UINT32_MAX;
  1.1870 +        if (rollupListener) {
  1.1871 +            nsAutoTArray<nsIWidget*, 5> widgetChain;
  1.1872 +            uint32_t sameTypeCount = rollupListener->GetSubmenuWidgetChain(&widgetChain);
  1.1873 +            for (uint32_t i=0; i<widgetChain.Length(); ++i) {
  1.1874 +                nsIWidget* widget =  widgetChain[i];
  1.1875 +                MozQWidget* currWindow =
  1.1876 +                    (MozQWidget*) widget->GetNativeData(NS_NATIVE_WINDOW);
  1.1877 +                if (is_mouse_in_window(currWindow, aMouseX, aMouseY)) {
  1.1878 +                  if (i < sameTypeCount) {
  1.1879 +                    rollup = false;
  1.1880 +                  }
  1.1881 +                  else {
  1.1882 +                    popupsToRollup = sameTypeCount;
  1.1883 +                  }
  1.1884 +                  break;
  1.1885 +                }
  1.1886 +            } // foreach parent menu widget
  1.1887 +        } // if rollup listener knows about menus
  1.1888 +
  1.1889 +        // if we've determined that we should still rollup, do it.
  1.1890 +        if (rollup) {
  1.1891 +            nsIntPoint pos(aMouseX, aMouseY);
  1.1892 +            retVal = rollupListener->Rollup(popupsToRollup, &pos, nullptr);
  1.1893 +        }
  1.1894 +    }
  1.1895 +
  1.1896 +    return retVal;
  1.1897 +}
  1.1898 +
  1.1899 +/* static */
  1.1900 +bool
  1.1901 +is_mouse_in_window (MozQWidget* aWindow, double aMouseX, double aMouseY)
  1.1902 +{
  1.1903 +    return aWindow->geometry().contains(aMouseX, aMouseY);
  1.1904 +}
  1.1905 +
  1.1906 +NS_IMETHODIMP
  1.1907 +nsWindow::GetAttention(int32_t aCycleCount)
  1.1908 +{
  1.1909 +    LOG(("nsWindow::GetAttention [%p]\n", (void *)this));
  1.1910 +    return NS_ERROR_NOT_IMPLEMENTED;
  1.1911 +}
  1.1912 +
  1.1913 +
  1.1914 +
  1.1915 +nsEventStatus
  1.1916 +nsWindow::OnCloseEvent(QCloseEvent *aEvent)
  1.1917 +{
  1.1918 +    if (!mWidgetListener)
  1.1919 +        return nsEventStatus_eIgnore;
  1.1920 +    mWidgetListener->RequestWindowClose(this);
  1.1921 +    return nsEventStatus_eConsumeNoDefault;
  1.1922 +}
  1.1923 +
  1.1924 +
  1.1925 +inline bool
  1.1926 +is_latin_shortcut_key(quint32 aKeyval)
  1.1927 +{
  1.1928 +    return ((Qt::Key_0 <= aKeyval && aKeyval <= Qt::Key_9) ||
  1.1929 +            (Qt::Key_A <= aKeyval && aKeyval <= Qt::Key_Z));
  1.1930 +}
  1.1931 +
  1.1932 +nsEventStatus
  1.1933 +nsWindow::DispatchCommandEvent(nsIAtom* aCommand)
  1.1934 +{
  1.1935 +    WidgetCommandEvent event(true, nsGkAtoms::onAppCommand, aCommand, this);
  1.1936 +
  1.1937 +    nsEventStatus status;
  1.1938 +    DispatchEvent(&event, status);
  1.1939 +
  1.1940 +    return status;
  1.1941 +}
  1.1942 +
  1.1943 +nsEventStatus
  1.1944 +nsWindow::DispatchContentCommandEvent(int32_t aMsg)
  1.1945 +{
  1.1946 +    WidgetContentCommandEvent event(true, aMsg, this);
  1.1947 +
  1.1948 +    nsEventStatus status;
  1.1949 +    DispatchEvent(&event, status);
  1.1950 +
  1.1951 +    return status;
  1.1952 +}
  1.1953 +
  1.1954 +
  1.1955 +static void
  1.1956 +GetBrandName(nsXPIDLString& brandName)
  1.1957 +{
  1.1958 +    nsCOMPtr<nsIStringBundleService> bundleService =
  1.1959 +        mozilla::services::GetStringBundleService();
  1.1960 +
  1.1961 +    nsCOMPtr<nsIStringBundle> bundle;
  1.1962 +    if (bundleService) {
  1.1963 +        bundleService->CreateBundle(
  1.1964 +            "chrome://branding/locale/brand.properties",
  1.1965 +            getter_AddRefs(bundle));
  1.1966 +    }
  1.1967 +
  1.1968 +    if (bundle) {
  1.1969 +        bundle->GetStringFromName(
  1.1970 +            MOZ_UTF16("brandShortName"),
  1.1971 +            getter_Copies(brandName));
  1.1972 +    }
  1.1973 +
  1.1974 +    if (brandName.IsEmpty()) {
  1.1975 +        brandName.Assign(NS_LITERAL_STRING("Mozilla"));
  1.1976 +    }
  1.1977 +}
  1.1978 +
  1.1979 +NS_IMETHODIMP
  1.1980 +nsWindow::SetWindowClass(const nsAString &xulWinType)
  1.1981 +{
  1.1982 +    if (!mWidget) {
  1.1983 +        return NS_ERROR_FAILURE;
  1.1984 +    }
  1.1985 +
  1.1986 +    nsXPIDLString brandName;
  1.1987 +    GetBrandName(brandName);
  1.1988 +
  1.1989 +#ifdef MOZ_X11
  1.1990 +    XClassHint *class_hint = XAllocClassHint();
  1.1991 +    if (!class_hint) {
  1.1992 +        return NS_ERROR_OUT_OF_MEMORY;
  1.1993 +    }
  1.1994 +    const char *role = nullptr;
  1.1995 +    class_hint->res_name = ToNewCString(xulWinType);
  1.1996 +    if (!class_hint->res_name) {
  1.1997 +        XFree(class_hint);
  1.1998 +        return NS_ERROR_OUT_OF_MEMORY;
  1.1999 +    }
  1.2000 +    class_hint->res_class = ToNewCString(brandName);
  1.2001 +    if (!class_hint->res_class) {
  1.2002 +        nsMemory::Free(class_hint->res_name);
  1.2003 +        XFree(class_hint);
  1.2004 +        return NS_ERROR_OUT_OF_MEMORY;
  1.2005 +    }
  1.2006 +
  1.2007 +    // Parse res_name into a name and role. Characters other than
  1.2008 +    // [A-Za-z0-9_-] are converted to '_'. Anything after the first
  1.2009 +    // colon is assigned to role; if there's no colon, assign the
  1.2010 +    // whole thing to both role and res_name.
  1.2011 +    for (char *c = class_hint->res_name; *c; c++) {
  1.2012 +        if (':' == *c) {
  1.2013 +            *c = 0;
  1.2014 +            role = c + 1;
  1.2015 +        }
  1.2016 +        else if (!isascii(*c) || (!isalnum(*c) && ('_' != *c) && ('-' != *c)))
  1.2017 +            *c = '_';
  1.2018 +    }
  1.2019 +    class_hint->res_name[0] = toupper(class_hint->res_name[0]);
  1.2020 +    if (!role) role = class_hint->res_name;
  1.2021 +
  1.2022 +    QWindow *widget = mWidget;
  1.2023 +    // If widget not show, handle might be null
  1.2024 +    if (widget && widget->winId()) {
  1.2025 +        XSetClassHint(gfxQtPlatform::GetXDisplay(widget),
  1.2026 +                      widget->winId(),
  1.2027 +                      class_hint);
  1.2028 +    }
  1.2029 +
  1.2030 +    nsMemory::Free(class_hint->res_class);
  1.2031 +    nsMemory::Free(class_hint->res_name);
  1.2032 +    XFree(class_hint);
  1.2033 +#endif
  1.2034 +
  1.2035 +    return NS_OK;
  1.2036 +}
  1.2037 +
  1.2038 +void
  1.2039 +nsWindow::NativeResize(int32_t aWidth, int32_t aHeight, bool    aRepaint)
  1.2040 +{
  1.2041 +    LOG(("nsWindow::NativeResize [%p] %d %d\n", (void *)this,
  1.2042 +         aWidth, aHeight));
  1.2043 +
  1.2044 +    mNeedsResize = false;
  1.2045 +
  1.2046 +    mWidget->resize(aWidth, aHeight);
  1.2047 +
  1.2048 +    if (aRepaint) {
  1.2049 +        mWidget->renderLater();
  1.2050 +    }
  1.2051 +}
  1.2052 +
  1.2053 +void
  1.2054 +nsWindow::NativeResize(int32_t aX, int32_t aY,
  1.2055 +                       int32_t aWidth, int32_t aHeight,
  1.2056 +                       bool    aRepaint)
  1.2057 +{
  1.2058 +    LOG(("nsWindow::NativeResize [%p] %d %d %d %d\n", (void *)this,
  1.2059 +         aX, aY, aWidth, aHeight));
  1.2060 +
  1.2061 +    mNeedsResize = false;
  1.2062 +    mNeedsMove = false;
  1.2063 +
  1.2064 +    mWidget->setGeometry(aX, aY, aWidth, aHeight);
  1.2065 +
  1.2066 +    if (aRepaint) {
  1.2067 +        mWidget->renderLater();
  1.2068 +    }
  1.2069 +}
  1.2070 +
  1.2071 +void
  1.2072 +nsWindow::NativeShow(bool aAction)
  1.2073 +{
  1.2074 +    if (aAction) {
  1.2075 +        // On e10s, we never want the child process or plugin process
  1.2076 +        // to go fullscreen because if we do the window because visible
  1.2077 +        // do to disabled Qt-Xembed
  1.2078 +        mWidget->show();
  1.2079 +        // unset our flag now that our window has been shown
  1.2080 +        mNeedsShow = false;
  1.2081 +    }
  1.2082 +    else {
  1.2083 +        mWidget->hide();
  1.2084 +    }
  1.2085 +}
  1.2086 +
  1.2087 +NS_IMETHODIMP
  1.2088 +nsWindow::SetHasTransparentBackground(bool aTransparent)
  1.2089 +{
  1.2090 +    return NS_ERROR_NOT_IMPLEMENTED;
  1.2091 +}
  1.2092 +
  1.2093 +NS_IMETHODIMP
  1.2094 +nsWindow::GetHasTransparentBackground(bool& aTransparent)
  1.2095 +{
  1.2096 +    aTransparent = mIsTransparent;
  1.2097 +    return NS_OK;
  1.2098 +}
  1.2099 +
  1.2100 +void *
  1.2101 +nsWindow::SetupPluginPort(void)
  1.2102 +{
  1.2103 +    NS_WARNING("Not implemented");
  1.2104 +    return nullptr;
  1.2105 +}
  1.2106 +
  1.2107 +nsresult
  1.2108 +nsWindow::SetWindowIconList(const nsTArray<nsCString> &aIconList)
  1.2109 +{
  1.2110 +    QIcon icon;
  1.2111 +
  1.2112 +    for (uint32_t i = 0; i < aIconList.Length(); ++i) {
  1.2113 +        const char *path = aIconList[i].get();
  1.2114 +        LOG(("window [%p] Loading icon from %s\n", (void *)this, path));
  1.2115 +        icon.addFile(path);
  1.2116 +    }
  1.2117 +
  1.2118 +    mWidget->setIcon(icon);
  1.2119 +
  1.2120 +    return NS_OK;
  1.2121 +}
  1.2122 +
  1.2123 +void
  1.2124 +nsWindow::SetDefaultIcon(void)
  1.2125 +{
  1.2126 +    SetIcon(NS_LITERAL_STRING("default"));
  1.2127 +}
  1.2128 +
  1.2129 +void nsWindow::QWidgetDestroyed()
  1.2130 +{
  1.2131 +    mWidget = nullptr;
  1.2132 +}
  1.2133 +
  1.2134 +
  1.2135 +NS_IMETHODIMP
  1.2136 +nsWindow::HideWindowChrome(bool aShouldHide)
  1.2137 +{
  1.2138 +    if (!mWidget) {
  1.2139 +        // Nothing to hide
  1.2140 +        return NS_ERROR_FAILURE;
  1.2141 +    }
  1.2142 +
  1.2143 +    // Sawfish, metacity, and presumably other window managers get
  1.2144 +    // confused if we change the window decorations while the window
  1.2145 +    // is visible.
  1.2146 +    bool wasVisible = false;
  1.2147 +    if (mWidget->isVisible()) {
  1.2148 +        NativeShow(false);
  1.2149 +        wasVisible = true;
  1.2150 +    }
  1.2151 +
  1.2152 +    if (wasVisible) {
  1.2153 +        NativeShow(true);
  1.2154 +    }
  1.2155 +
  1.2156 +    return NS_OK;
  1.2157 +}
  1.2158 +
  1.2159 +//////////////////////////////////////////////////////////////////////
  1.2160 +
  1.2161 +NS_IMETHODIMP_(bool)
  1.2162 +nsWindow::HasGLContext()
  1.2163 +{
  1.2164 +    return false;
  1.2165 +}
  1.2166 +
  1.2167 +
  1.2168 +nsIWidget*
  1.2169 +nsWindow::GetParent(void)
  1.2170 +{
  1.2171 +    return mParent;
  1.2172 +}
  1.2173 +
  1.2174 +float
  1.2175 +nsWindow::GetDPI()
  1.2176 +{
  1.2177 +    return qApp->primaryScreen()->logicalDotsPerInch();
  1.2178 +}
  1.2179 +
  1.2180 +void
  1.2181 +nsWindow::OnDestroy(void)
  1.2182 +{
  1.2183 +    if (mOnDestroyCalled) {
  1.2184 +        return;
  1.2185 +    }
  1.2186 +
  1.2187 +    mOnDestroyCalled = true;
  1.2188 +
  1.2189 +    // release references to children and device context
  1.2190 +    nsBaseWidget::OnDestroy();
  1.2191 +
  1.2192 +    // let go of our parent
  1.2193 +    mParent = nullptr;
  1.2194 +
  1.2195 +    nsCOMPtr<nsIWidget> kungFuDeathGrip = this;
  1.2196 +    NotifyWindowDestroyed();
  1.2197 +}
  1.2198 +
  1.2199 +bool
  1.2200 +nsWindow::AreBoundsSane(void)
  1.2201 +{
  1.2202 +    if (mBounds.width > 0 && mBounds.height > 0) {
  1.2203 +        return true;
  1.2204 +    }
  1.2205 +
  1.2206 +    return false;
  1.2207 +}
  1.2208 +
  1.2209 +void
  1.2210 +nsWindow::SetSoftwareKeyboardState(bool aOpen,
  1.2211 +                                   const InputContextAction& aAction)
  1.2212 +{
  1.2213 +    if (aOpen) {
  1.2214 +        NS_ENSURE_TRUE_VOID(mInputContext.mIMEState.mEnabled !=
  1.2215 +                            IMEState::DISABLED);
  1.2216 +
  1.2217 +        // Ensure that opening the virtual keyboard is allowed for this specific
  1.2218 +        // InputContext depending on the content.ime.strict.policy pref
  1.2219 +        if (mInputContext.mIMEState.mEnabled != IMEState::PLUGIN &&
  1.2220 +            Preferences::GetBool("content.ime.strict_policy", false) &&
  1.2221 +            !aAction.ContentGotFocusByTrustedCause() &&
  1.2222 +            !aAction.UserMightRequestOpenVKB()) {
  1.2223 +            return;
  1.2224 +        }
  1.2225 +    }
  1.2226 +
  1.2227 +    if (aOpen) {
  1.2228 +        qApp->inputMethod()->show();
  1.2229 +    } else {
  1.2230 +        qApp->inputMethod()->hide();
  1.2231 +    }
  1.2232 +
  1.2233 +    return;
  1.2234 +}
  1.2235 +
  1.2236 +
  1.2237 +void
  1.2238 +nsWindow::ProcessMotionEvent()
  1.2239 +{
  1.2240 +    if (mMoveEvent.needDispatch) {
  1.2241 +        WidgetMouseEvent event(true, NS_MOUSE_MOVE, this,
  1.2242 +                               WidgetMouseEvent::eReal);
  1.2243 +
  1.2244 +        event.refPoint.x = nscoord(mMoveEvent.pos.x());
  1.2245 +        event.refPoint.y = nscoord(mMoveEvent.pos.y());
  1.2246 +
  1.2247 +        event.InitBasicModifiers(mMoveEvent.modifiers & Qt::ControlModifier,
  1.2248 +                                 mMoveEvent.modifiers & Qt::AltModifier,
  1.2249 +                                 mMoveEvent.modifiers & Qt::ShiftModifier,
  1.2250 +                                 mMoveEvent.modifiers & Qt::MetaModifier);
  1.2251 +        event.clickCount      = 0;
  1.2252 +
  1.2253 +        DispatchEvent(&event);
  1.2254 +        mMoveEvent.needDispatch = false;
  1.2255 +    }
  1.2256 +
  1.2257 +    mTimerStarted = false;
  1.2258 +}
  1.2259 +

mercurial