mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
7cd70b33b4
In nsIWidget, GetBoundsUntyped(), GetClientBoundsUntyped() and GetScreenBoundsUntyped() are currently the primary implementations, and the untyped versions are defined on top of them. This patch flips that around.
1988 lines
53 KiB
C++
1988 lines
53 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/* vim:expandtab:shiftwidth=4:tabstop=4:
|
|
*/
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "mozilla/ArrayUtils.h"
|
|
#include "mozilla/MiscEvents.h"
|
|
#include "mozilla/MouseEvents.h"
|
|
#include "mozilla/TextEvents.h"
|
|
#include "mozilla/TouchEvents.h"
|
|
|
|
#include <QGuiApplication>
|
|
#include <QtGui/QCursor>
|
|
#include <QIcon>
|
|
#include <QMouseEvent>
|
|
#include <QWheelEvent>
|
|
#include <QResizeEvent>
|
|
#include <QPaintEngine>
|
|
#include <QMimeData>
|
|
#include <QScreen>
|
|
|
|
#include <QtCore/QDebug>
|
|
#include <QtCore/QEvent>
|
|
#include <QtCore/QVariant>
|
|
#include <algorithm>
|
|
|
|
#ifdef MOZ_X11
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xutil.h>
|
|
#include "gfxXlibSurface.h"
|
|
#endif //MOZ_X11
|
|
|
|
#include "nsXULAppAPI.h"
|
|
|
|
#include "prlink.h"
|
|
|
|
#include "nsWindow.h"
|
|
#include "mozqwidget.h"
|
|
|
|
#include "nsIdleService.h"
|
|
#include "nsIRollupListener.h"
|
|
#include "nsWidgetsCID.h"
|
|
#include "nsQtKeyUtils.h"
|
|
#include "mozilla/Services.h"
|
|
#include "mozilla/Preferences.h"
|
|
#include "mozilla/Likely.h"
|
|
#include "mozilla/layers/LayersTypes.h"
|
|
#include "nsIWidgetListener.h"
|
|
#include "ClientLayerManager.h"
|
|
#include "BasicLayers.h"
|
|
|
|
#include "nsIStringBundle.h"
|
|
#include "nsGfxCIID.h"
|
|
|
|
#include "imgIContainer.h"
|
|
#include "nsGfxCIID.h"
|
|
#include "nsIInterfaceRequestorUtils.h"
|
|
#include "nsAutoPtr.h"
|
|
|
|
#include "gfxQtPlatform.h"
|
|
|
|
#include "nsIDOMWheelEvent.h"
|
|
|
|
#include "GLContext.h"
|
|
|
|
#ifdef MOZ_X11
|
|
#include "keysym2ucs.h"
|
|
#endif
|
|
|
|
#include "Layers.h"
|
|
#include "GLContextProvider.h"
|
|
|
|
using namespace mozilla;
|
|
using namespace mozilla::gl;
|
|
using namespace mozilla::widget;
|
|
using namespace mozilla::gfx;
|
|
using namespace mozilla::layers;
|
|
using mozilla::gl::GLContext;
|
|
|
|
#define kWindowPositionSlop 20
|
|
|
|
// Qt
|
|
static const int WHEEL_DELTA = 120;
|
|
static bool gGlobalsInitialized = false;
|
|
static bool sAltGrModifier = false;
|
|
|
|
static void find_first_visible_parent(QWindow* aItem, QWindow*& aVisibleItem);
|
|
static bool is_mouse_in_window (MozQWidget* aWindow, double aMouseX, double aMouseY);
|
|
|
|
NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, nsBaseWidget)
|
|
|
|
nsWindow::nsWindow()
|
|
{
|
|
LOG(("%s [%p]\n", __PRETTY_FUNCTION__, (void *)this));
|
|
|
|
mIsTopLevel = false;
|
|
mIsDestroyed = false;
|
|
mIsShown = false;
|
|
mEnabled = true;
|
|
mWidget = nullptr;
|
|
mVisible = false;
|
|
mActivatePending = false;
|
|
mWindowType = eWindowType_child;
|
|
mSizeState = nsSizeMode_Normal;
|
|
mLastSizeMode = nsSizeMode_Normal;
|
|
mQCursor = Qt::ArrowCursor;
|
|
mNeedsResize = false;
|
|
mNeedsMove = false;
|
|
mListenForResizes = false;
|
|
mNeedsShow = false;
|
|
mTimerStarted = false;
|
|
mMoveEvent.needDispatch = false;
|
|
|
|
if (!gGlobalsInitialized) {
|
|
gfxPlatform::GetPlatform();
|
|
gGlobalsInitialized = true;
|
|
}
|
|
|
|
memset(mKeyDownFlags, 0, sizeof(mKeyDownFlags));
|
|
|
|
mIsTransparent = false;
|
|
|
|
mCursor = eCursor_standard;
|
|
}
|
|
|
|
nsWindow::~nsWindow()
|
|
{
|
|
LOG(("%s [%p]\n", __PRETTY_FUNCTION__, (void *)this));
|
|
|
|
Destroy();
|
|
}
|
|
|
|
nsresult
|
|
nsWindow::Create(nsIWidget *aParent,
|
|
nsNativeWidget aNativeParent,
|
|
const nsIntRect &aRect,
|
|
nsWidgetInitData *aInitData)
|
|
{
|
|
// only set the base parent if we're not going to be a dialog or a
|
|
// toplevel
|
|
nsIWidget *baseParent = aParent;
|
|
|
|
// initialize all the common bits of this class
|
|
BaseCreate(baseParent, aRect, aInitData);
|
|
|
|
mVisible = true;
|
|
|
|
// and do our common creation
|
|
mParent = (nsWindow *)aParent;
|
|
|
|
// save our bounds
|
|
mBounds = aRect;
|
|
|
|
// find native parent
|
|
MozQWidget *parent = nullptr;
|
|
|
|
if (aParent != nullptr) {
|
|
parent = static_cast<MozQWidget*>(aParent->GetNativeData(NS_NATIVE_WIDGET));
|
|
} else if (aNativeParent != nullptr) {
|
|
parent = static_cast<MozQWidget*>(aNativeParent);
|
|
if (parent && mParent == nullptr) {
|
|
mParent = parent->getReceiver();
|
|
}
|
|
}
|
|
|
|
LOG(("Create: nsWindow [%p] mWidget:[%p] parent:[%p], natPar:[%p] mParent:%p\n", (void *)this, (void*)mWidget, parent, aNativeParent, mParent));
|
|
|
|
// ok, create our QGraphicsWidget
|
|
mWidget = createQWidget(parent, aInitData);
|
|
|
|
if (!mWidget) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
|
|
// resize so that everything is set to the right dimensions
|
|
Resize(mBounds.x, mBounds.y, mBounds.width, mBounds.height, false);
|
|
|
|
// check if we should listen for resizes
|
|
mListenForResizes = (aNativeParent ||
|
|
(aInitData && aInitData->mListenForResizes));
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
MozQWidget*
|
|
nsWindow::createQWidget(MozQWidget* parent,
|
|
nsWidgetInitData* aInitData)
|
|
{
|
|
const char *windowName = nullptr;
|
|
Qt::WindowFlags flags = Qt::Widget;
|
|
|
|
// ok, create our windows
|
|
switch (mWindowType) {
|
|
case eWindowType_dialog:
|
|
windowName = "topLevelDialog";
|
|
flags = Qt::Dialog;
|
|
break;
|
|
case eWindowType_popup:
|
|
windowName = "topLevelPopup";
|
|
flags = Qt::Popup;
|
|
break;
|
|
case eWindowType_toplevel:
|
|
windowName = "topLevelWindow";
|
|
flags = Qt::Window;
|
|
break;
|
|
case eWindowType_invisible:
|
|
windowName = "topLevelInvisible";
|
|
break;
|
|
case eWindowType_child:
|
|
case eWindowType_plugin:
|
|
default: // sheet
|
|
windowName = "paintArea";
|
|
break;
|
|
}
|
|
|
|
MozQWidget* widget = new MozQWidget(this, parent);
|
|
if (!widget) {
|
|
return nullptr;
|
|
}
|
|
|
|
widget->setObjectName(QString(windowName));
|
|
if (mWindowType == eWindowType_invisible) {
|
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 1, 0))
|
|
widget->setVisibility(QWindow::Hidden);
|
|
#else
|
|
widget->hide();
|
|
#endif
|
|
}
|
|
if (mWindowType == eWindowType_dialog) {
|
|
widget->setModality(Qt::WindowModal);
|
|
}
|
|
|
|
widget->create();
|
|
|
|
// create a QGraphicsView if this is a new toplevel window
|
|
LOG(("nsWindow::%s [%p] Created Window: %s, widget:%p, par:%p\n", __FUNCTION__, (void *)this, windowName, widget, parent));
|
|
|
|
return widget;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::Destroy(void)
|
|
{
|
|
if (mIsDestroyed || !mWidget) {
|
|
return NS_OK;
|
|
}
|
|
|
|
LOG(("nsWindow::Destroy [%p]\n", (void *)this));
|
|
mIsDestroyed = true;
|
|
|
|
/** Need to clean our LayerManager up while still alive */
|
|
if (mLayerManager) {
|
|
mLayerManager->Destroy();
|
|
}
|
|
mLayerManager = nullptr;
|
|
|
|
// It is safe to call DestroyeCompositor several times (here and
|
|
// in the parent class) since it will take effect only once.
|
|
// The reason we call it here is because on gtk platforms we need
|
|
// to destroy the compositor before we destroy the gdk window (which
|
|
// destroys the the gl context attached to it).
|
|
DestroyCompositor();
|
|
|
|
ClearCachedResources();
|
|
|
|
nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener();
|
|
if (rollupListener) {
|
|
nsCOMPtr<nsIWidget> rollupWidget = rollupListener->GetRollupWidget();
|
|
if (static_cast<nsIWidget *>(this) == rollupWidget) {
|
|
rollupListener->Rollup(0, false, nullptr, nullptr);
|
|
}
|
|
}
|
|
|
|
Show(false);
|
|
|
|
// walk the list of children and call destroy on them. Have to be
|
|
// careful, though -- calling destroy on a kid may actually remove
|
|
// it from our child list, losing its sibling links.
|
|
for (nsIWidget* kid = mFirstChild; kid; ) {
|
|
nsIWidget* next = kid->GetNextSibling();
|
|
kid->Destroy();
|
|
kid = next;
|
|
}
|
|
|
|
// Destroy thebes surface now. Badness can happen if we destroy
|
|
// the surface after its X Window.
|
|
if (mWidget) {
|
|
mWidget->dropReceiver();
|
|
|
|
// Call deleteLater instead of delete; Qt still needs the object
|
|
// to be valid even after sending it a Close event. We could
|
|
// also set WA_DeleteOnClose, but this gives us more control.
|
|
mWidget->deleteLater();
|
|
}
|
|
mWidget = nullptr;
|
|
|
|
OnDestroy();
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::Show(bool aState)
|
|
{
|
|
LOG(("nsWindow::Show [%p] state %d\n", (void *)this, aState));
|
|
if (aState == mIsShown) {
|
|
return NS_OK;
|
|
}
|
|
|
|
// Clear our cached resources when the window is hidden.
|
|
if (mIsShown && !aState) {
|
|
ClearCachedResources();
|
|
}
|
|
|
|
mIsShown = aState;
|
|
|
|
if ((aState && !AreBoundsSane()) || !mWidget) {
|
|
LOG(("\tbounds are insane or window hasn't been created yet\n"));
|
|
mNeedsShow = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
if (aState) {
|
|
if (mNeedsMove) {
|
|
NativeResize(mBounds.x, mBounds.y, mBounds.width, mBounds.height,
|
|
false);
|
|
} else if (mNeedsResize) {
|
|
NativeResize(mBounds.width, mBounds.height, false);
|
|
}
|
|
}
|
|
else {
|
|
// If someone is hiding this widget, clear any needing show flag.
|
|
mNeedsShow = false;
|
|
}
|
|
|
|
NativeShow(aState);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
bool
|
|
nsWindow::IsVisible() const
|
|
{
|
|
return mIsShown;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::ConstrainPosition(bool aAllowSlop, int32_t *aX, int32_t *aY)
|
|
{
|
|
if (!mWidget) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
int32_t screenWidth = qApp->primaryScreen()->size().width();
|
|
int32_t screenHeight = qApp->primaryScreen()->size().height();
|
|
|
|
if (aAllowSlop) {
|
|
if (*aX < (kWindowPositionSlop - mBounds.width))
|
|
*aX = kWindowPositionSlop - mBounds.width;
|
|
if (*aX > (screenWidth - kWindowPositionSlop))
|
|
*aX = screenWidth - kWindowPositionSlop;
|
|
if (*aY < (kWindowPositionSlop - mBounds.height))
|
|
*aY = kWindowPositionSlop - mBounds.height;
|
|
if (*aY > (screenHeight - kWindowPositionSlop))
|
|
*aY = screenHeight - kWindowPositionSlop;
|
|
} else {
|
|
if (*aX < 0)
|
|
*aX = 0;
|
|
if (*aX > (screenWidth - mBounds.width))
|
|
*aX = screenWidth - mBounds.width;
|
|
if (*aY < 0)
|
|
*aY = 0;
|
|
if (*aY > (screenHeight - mBounds.height))
|
|
*aY = screenHeight - mBounds.height;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::Move(double aX, double aY)
|
|
{
|
|
LOG(("nsWindow::Move [%p] %f %f\n", (void *)this,
|
|
aX, aY));
|
|
|
|
int32_t x = NSToIntRound(aX);
|
|
int32_t y = NSToIntRound(aY);
|
|
|
|
if (mIsTopLevel) {
|
|
SetSizeMode(nsSizeMode_Normal);
|
|
}
|
|
|
|
if (x == mBounds.x && y == mBounds.y) {
|
|
return NS_OK;
|
|
}
|
|
|
|
mNeedsMove = false;
|
|
|
|
// update the bounds
|
|
QPoint pos(x, y);
|
|
if (mIsTopLevel) {
|
|
mWidget->setPosition(x, y);
|
|
}
|
|
else if (mWidget) {
|
|
// the position of the widget is set relative to the parent
|
|
// so we map the coordinates accordingly
|
|
pos = mWidget->mapToGlobal(pos);
|
|
mWidget->setPosition(pos);
|
|
}
|
|
|
|
mBounds.x = pos.x();
|
|
mBounds.y = pos.y();
|
|
|
|
NotifyRollupGeometryChange();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::Resize(double aWidth, double aHeight, bool aRepaint)
|
|
{
|
|
mBounds.width = NSToIntRound(aWidth);
|
|
mBounds.height = NSToIntRound(aHeight);
|
|
|
|
if (!mWidget)
|
|
return NS_OK;
|
|
|
|
if (mIsShown) {
|
|
if (AreBoundsSane()) {
|
|
if (mIsTopLevel || mNeedsShow)
|
|
NativeResize(mBounds.x, mBounds.y,
|
|
mBounds.width, mBounds.height, aRepaint);
|
|
else
|
|
NativeResize(mBounds.width, mBounds.height, aRepaint);
|
|
|
|
// Does it need to be shown because it was previously insane?
|
|
if (mNeedsShow) {
|
|
NativeShow(true);
|
|
}
|
|
}
|
|
else {
|
|
// If someone has set this so that the needs show flag is false
|
|
// and it needs to be hidden, update the flag and hide the
|
|
// window. This flag will be cleared the next time someone
|
|
// hides the window or shows it. It also prevents us from
|
|
// calling NativeShow(false) excessively on the window which
|
|
// causes unneeded X traffic.
|
|
if (!mNeedsShow) {
|
|
mNeedsShow = true;
|
|
NativeShow(false);
|
|
}
|
|
}
|
|
}
|
|
else if (AreBoundsSane() && mListenForResizes) {
|
|
// For widgets that we listen for resizes for (widgets created
|
|
// with native parents) we apparently _always_ have to resize. I
|
|
// dunno why, but apparently we're lame like that.
|
|
NativeResize(mBounds.width, mBounds.height, aRepaint);
|
|
}
|
|
else {
|
|
mNeedsResize = true;
|
|
}
|
|
|
|
// synthesize a resize event if this isn't a toplevel
|
|
if (mIsTopLevel || mListenForResizes) {
|
|
nsEventStatus status;
|
|
DispatchResizeEvent(LayoutDeviceIntRect::FromUnknownRect(mBounds),
|
|
status);
|
|
}
|
|
|
|
NotifyRollupGeometryChange();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::Resize(double aX, double aY, double aWidth, double aHeight,
|
|
bool aRepaint)
|
|
{
|
|
mBounds.x = NSToIntRound(aX);
|
|
mBounds.y = NSToIntRound(aY);
|
|
mBounds.width = NSToIntRound(aWidth);
|
|
mBounds.height = NSToIntRound(aHeight);
|
|
|
|
mPlaced = true;
|
|
|
|
if (!mWidget) {
|
|
return NS_OK;
|
|
}
|
|
|
|
// Has this widget been set to visible?
|
|
if (mIsShown) {
|
|
// Are the bounds sane?
|
|
if (AreBoundsSane()) {
|
|
// Yep? Resize the window
|
|
NativeResize(mBounds.x, mBounds.y, mBounds.width, mBounds.height,
|
|
aRepaint);
|
|
// Does it need to be shown because it was previously insane?
|
|
if (mNeedsShow)
|
|
NativeShow(true);
|
|
}
|
|
else {
|
|
// If someone has set this so that the needs show flag is false
|
|
// and it needs to be hidden, update the flag and hide the
|
|
// window. This flag will be cleared the next time someone
|
|
// hides the window or shows it. It also prevents us from
|
|
// calling NativeShow(false) excessively on the window which
|
|
// causes unneeded X traffic.
|
|
if (!mNeedsShow) {
|
|
mNeedsShow = true;
|
|
NativeShow(false);
|
|
}
|
|
}
|
|
}
|
|
// If the widget hasn't been shown, mark the widget as needing to be
|
|
// resized before it is shown
|
|
else if (AreBoundsSane() && mListenForResizes) {
|
|
// For widgets that we listen for resizes for (widgets created
|
|
// with native parents) we apparently _always_ have to resize. I
|
|
// dunno why, but apparently we're lame like that.
|
|
NativeResize(mBounds.x, mBounds.y, mBounds.width, mBounds.height,
|
|
aRepaint);
|
|
}
|
|
else {
|
|
mNeedsResize = true;
|
|
mNeedsMove = true;
|
|
}
|
|
|
|
if (mIsTopLevel || mListenForResizes) {
|
|
// synthesize a resize event
|
|
nsEventStatus status;
|
|
DispatchResizeEvent(LayoutDeviceIntRect::FromUnknownRect(mBounds),
|
|
status);
|
|
}
|
|
|
|
if (aRepaint) {
|
|
mWidget->renderLater();
|
|
}
|
|
|
|
NotifyRollupGeometryChange();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::Enable(bool aState)
|
|
{
|
|
mEnabled = aState;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
bool
|
|
nsWindow::IsEnabled() const
|
|
{
|
|
return mEnabled;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::SetFocus(bool aRaise)
|
|
{
|
|
// Make sure that our owning widget has focus. If it doesn't try to
|
|
// grab it. Note that we don't set our focus flag in this case.
|
|
LOGFOCUS((" SetFocus [%p]\n", (void *)this));
|
|
|
|
if (!mWidget) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
if (mWidget->focusObject()) {
|
|
return NS_OK;
|
|
}
|
|
|
|
// Because QGraphicsItem cannot get the focus if they are
|
|
// invisible, we look up the chain, for the lowest visible
|
|
// parent and focus that one
|
|
QWindow* realFocusItem = nullptr;
|
|
find_first_visible_parent(mWidget, realFocusItem);
|
|
|
|
if (!realFocusItem || realFocusItem->focusObject()) {
|
|
return NS_OK;
|
|
}
|
|
|
|
if (aRaise && mWidget) {
|
|
// the raising has to happen on the view widget
|
|
mWidget->raise();
|
|
}
|
|
|
|
// XXXndeakin why is this here? It should dispatch only when the OS
|
|
// notifies us.
|
|
DispatchActivateEvent();
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::ConfigureChildren(const nsTArray<nsIWidget::Configuration>& aConfigurations)
|
|
{
|
|
for (uint32_t i = 0; i < aConfigurations.Length(); ++i) {
|
|
const Configuration& configuration = aConfigurations[i];
|
|
|
|
nsWindow* w = static_cast<nsWindow*>(configuration.mChild);
|
|
NS_ASSERTION(w->GetParent() == this,
|
|
"Configured widget is not a child");
|
|
|
|
LayoutDeviceIntRect wBounds =
|
|
LayoutDeviceIntRect::FromUnknownRect(w->mBounds);
|
|
if (wBounds.Size() != configuration.mBounds.Size()) {
|
|
w->Resize(configuration.mBounds.x, configuration.mBounds.y,
|
|
configuration.mBounds.width, configuration.mBounds.height,
|
|
true);
|
|
} else if (wBounds.TopLeft() != configuration.mBounds.TopLeft()) {
|
|
w->Move(configuration.mBounds.x, configuration.mBounds.y);
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::Invalidate(const nsIntRect &aRect)
|
|
{
|
|
LOGDRAW(("Invalidate (rect) [%p,%p]: %d %d %d %d\n", (void *)this,
|
|
(void*)mWidget,aRect.x, aRect.y, aRect.width, aRect.height));
|
|
|
|
if (!mWidget) {
|
|
return NS_OK;
|
|
}
|
|
|
|
mWidget->renderLater();
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
LayoutDeviceIntPoint
|
|
nsWindow::WidgetToScreenOffset()
|
|
{
|
|
NS_ENSURE_TRUE(mWidget, LayoutDeviceIntPoint(0,0));
|
|
|
|
QPoint origin(0, 0);
|
|
origin = mWidget->mapToGlobal(origin);
|
|
|
|
return LayoutDeviceIntPoint(origin.x(), origin.y());
|
|
}
|
|
|
|
void*
|
|
nsWindow::GetNativeData(uint32_t aDataType)
|
|
{
|
|
switch (aDataType) {
|
|
case NS_NATIVE_WINDOW:
|
|
case NS_NATIVE_WIDGET: {
|
|
return mWidget;
|
|
}
|
|
case NS_NATIVE_SHAREABLE_WINDOW: {
|
|
return mWidget ? (void*)mWidget->winId() : nullptr;
|
|
}
|
|
case NS_NATIVE_DISPLAY: {
|
|
#ifdef MOZ_X11
|
|
return gfxQtPlatform::GetXDisplay(mWidget);
|
|
#endif
|
|
break;
|
|
}
|
|
case NS_NATIVE_PLUGIN_PORT:
|
|
case NS_NATIVE_GRAPHIC:
|
|
case NS_NATIVE_SHELLWIDGET: {
|
|
break;
|
|
}
|
|
default:
|
|
NS_WARNING("nsWindow::GetNativeData called with bad value");
|
|
return nullptr;
|
|
}
|
|
LOG(("nsWindow::%s [%p] aDataType:%i\n", __FUNCTION__, (void *)this, aDataType));
|
|
return nullptr;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::DispatchEvent(WidgetGUIEvent* aEvent, nsEventStatus& aStatus)
|
|
{
|
|
#ifdef DEBUG
|
|
debug_DumpEvent(stdout, aEvent->widget, aEvent,
|
|
nsAutoCString("something"), 0);
|
|
#endif
|
|
|
|
aStatus = nsEventStatus_eIgnore;
|
|
|
|
// send it to the standard callback
|
|
if (mWidgetListener) {
|
|
aStatus = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP_(void)
|
|
nsWindow::SetInputContext(const InputContext& aContext,
|
|
const InputContextAction& aAction)
|
|
{
|
|
NS_ENSURE_TRUE_VOID(mWidget);
|
|
|
|
// SetSoftwareKeyboardState uses mInputContext,
|
|
// so, before calling that, record aContext in mInputContext.
|
|
mInputContext = aContext;
|
|
|
|
switch (mInputContext.mIMEState.mEnabled) {
|
|
case IMEState::ENABLED:
|
|
case IMEState::PASSWORD:
|
|
case IMEState::PLUGIN:
|
|
SetSoftwareKeyboardState(true, aAction);
|
|
break;
|
|
default:
|
|
SetSoftwareKeyboardState(false, aAction);
|
|
break;
|
|
}
|
|
}
|
|
|
|
NS_IMETHODIMP_(InputContext)
|
|
nsWindow::GetInputContext()
|
|
{
|
|
mInputContext.mIMEState.mOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
|
|
// Our qt widget looks like using only one context per process.
|
|
// However, it's better to set the context's pointer.
|
|
mInputContext.mNativeIMEContext = qApp->inputMethod();
|
|
|
|
return mInputContext;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::ReparentNativeWidget(nsIWidget *aNewParent)
|
|
{
|
|
NS_PRECONDITION(aNewParent, "");
|
|
|
|
MozQWidget* newParent = static_cast<MozQWidget*>(aNewParent->GetNativeData(NS_NATIVE_WINDOW));
|
|
NS_ASSERTION(newParent, "Parent widget has a null native window handle");
|
|
if (mWidget) {
|
|
mWidget->setParent(newParent);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen*)
|
|
{
|
|
NS_ENSURE_TRUE(mWidget, NS_ERROR_FAILURE);
|
|
|
|
if (aFullScreen) {
|
|
if (mSizeMode != nsSizeMode_Fullscreen) {
|
|
mLastSizeMode = mSizeMode;
|
|
}
|
|
|
|
mSizeMode = nsSizeMode_Fullscreen;
|
|
mWidget->showFullScreen();
|
|
}
|
|
else {
|
|
mSizeMode = mLastSizeMode;
|
|
|
|
switch (mSizeMode) {
|
|
case nsSizeMode_Maximized:
|
|
mWidget->showMaximized();
|
|
break;
|
|
case nsSizeMode_Minimized:
|
|
mWidget->showMinimized();
|
|
break;
|
|
case nsSizeMode_Normal:
|
|
mWidget->showNormal();
|
|
break;
|
|
default:
|
|
mWidget->showNormal();
|
|
break;
|
|
}
|
|
}
|
|
|
|
NS_ASSERTION(mLastSizeMode != nsSizeMode_Fullscreen,
|
|
"mLastSizeMode should never be fullscreen");
|
|
return nsBaseWidget::MakeFullScreen(aFullScreen);
|
|
}
|
|
|
|
LayerManager*
|
|
nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
|
|
LayersBackend aBackendHint,
|
|
LayerManagerPersistence aPersistence,
|
|
bool* aAllowRetaining)
|
|
{
|
|
if (!mLayerManager && eTransparencyTransparent == GetTransparencyMode()) {
|
|
mLayerManager = CreateBasicLayerManager();
|
|
}
|
|
|
|
return nsBaseWidget::GetLayerManager(aShadowManager, aBackendHint,
|
|
aPersistence, aAllowRetaining);
|
|
}
|
|
|
|
void
|
|
nsWindow::UserActivity()
|
|
{
|
|
if (!mIdleService) {
|
|
mIdleService = do_GetService("@mozilla.org/widget/idleservice;1");
|
|
}
|
|
|
|
if (mIdleService) {
|
|
mIdleService->ResetIdleTimeOut(0);
|
|
}
|
|
}
|
|
|
|
uint32_t
|
|
nsWindow::GetGLFrameBufferFormat()
|
|
{
|
|
if (mLayerManager &&
|
|
mLayerManager->GetBackendType() == mozilla::layers::LayersBackend::LAYERS_OPENGL) {
|
|
return LOCAL_GL_RGB;
|
|
}
|
|
return LOCAL_GL_NONE;
|
|
}
|
|
|
|
already_AddRefed<DrawTarget>
|
|
nsWindow::StartRemoteDrawing()
|
|
{
|
|
if (!mWidget) {
|
|
return nullptr;
|
|
}
|
|
|
|
#ifdef MOZ_X11
|
|
Display* dpy = gfxQtPlatform::GetXDisplay(mWidget);
|
|
Screen* screen = DefaultScreenOfDisplay(dpy);
|
|
Visual* defaultVisual = DefaultVisualOfScreen(screen);
|
|
gfxASurface* surf = new gfxXlibSurface(dpy, mWidget->winId(), defaultVisual,
|
|
IntSize(mWidget->width(),
|
|
mWidget->height()));
|
|
|
|
IntSize size(surf->GetSize().width, surf->GetSize().height);
|
|
if (size.width <= 0 || size.height <= 0) {
|
|
return nullptr;
|
|
}
|
|
|
|
return gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surf, size);
|
|
#else
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::SetCursor(nsCursor aCursor)
|
|
{
|
|
if (mCursor == aCursor && !mUpdateCursor) {
|
|
return NS_OK;
|
|
}
|
|
mUpdateCursor = false;
|
|
mCursor = aCursor;
|
|
if (mWidget) {
|
|
mWidget->SetCursor(mCursor);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::SetTitle(const nsAString& aTitle)
|
|
{
|
|
QString qStr(QString::fromUtf16((const ushort*)aTitle.BeginReading(), aTitle.Length()));
|
|
|
|
mWidget->setTitle(qStr);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
// EVENTS
|
|
|
|
void
|
|
nsWindow::OnPaint()
|
|
{
|
|
LOGDRAW(("nsWindow::%s [%p]\n", __FUNCTION__, (void *)this));
|
|
nsIWidgetListener* listener =
|
|
mAttachedWidgetListener ? mAttachedWidgetListener : mWidgetListener;
|
|
if (!listener) {
|
|
return;
|
|
}
|
|
|
|
listener->WillPaintWindow(this);
|
|
|
|
switch (GetLayerManager()->GetBackendType()) {
|
|
case mozilla::layers::LayersBackend::LAYERS_CLIENT: {
|
|
nsIntRegion region(nsIntRect(0, 0, mWidget->width(), mWidget->height()));
|
|
listener->PaintWindow(this, region);
|
|
break;
|
|
}
|
|
default:
|
|
NS_ERROR("Invalid layer manager");
|
|
}
|
|
|
|
listener->DidPaintWindow();
|
|
}
|
|
|
|
nsEventStatus
|
|
nsWindow::moveEvent(QMoveEvent* aEvent)
|
|
{
|
|
LOG(("configure event [%p] %d %d\n", (void *)this,
|
|
aEvent->pos().x(), aEvent->pos().y()));
|
|
|
|
// can we shortcut?
|
|
if (!mWidget || !mWidgetListener)
|
|
return nsEventStatus_eIgnore;
|
|
|
|
if ((mBounds.x == aEvent->pos().x() &&
|
|
mBounds.y == aEvent->pos().y()))
|
|
{
|
|
return nsEventStatus_eIgnore;
|
|
}
|
|
|
|
NotifyWindowMoved(aEvent->pos().x(), aEvent->pos().y());
|
|
return nsEventStatus_eConsumeNoDefault;
|
|
}
|
|
|
|
nsEventStatus
|
|
nsWindow::resizeEvent(QResizeEvent* aEvent)
|
|
{
|
|
LayoutDeviceIntRect rect;
|
|
|
|
// Generate XPFE resize event
|
|
GetBounds(rect);
|
|
|
|
rect.width = aEvent->size().width();
|
|
rect.height = aEvent->size().height();
|
|
|
|
mBounds.width = rect.width;
|
|
mBounds.height = rect.height;
|
|
|
|
nsEventStatus status;
|
|
DispatchResizeEvent(rect, status);
|
|
return status;
|
|
}
|
|
|
|
nsEventStatus
|
|
nsWindow::mouseMoveEvent(QMouseEvent* aEvent)
|
|
{
|
|
UserActivity();
|
|
|
|
mMoveEvent.pos = aEvent->pos();
|
|
mMoveEvent.modifiers = aEvent->modifiers();
|
|
mMoveEvent.needDispatch = true;
|
|
DispatchMotionToMainThread();
|
|
|
|
return nsEventStatus_eIgnore;
|
|
}
|
|
|
|
static void
|
|
InitMouseEvent(WidgetMouseEvent& aMouseEvent, QMouseEvent* aEvent,
|
|
int aClickCount)
|
|
{
|
|
aMouseEvent.refPoint.x = nscoord(aEvent->pos().x());
|
|
aMouseEvent.refPoint.y = nscoord(aEvent->pos().y());
|
|
|
|
aMouseEvent.InitBasicModifiers(aEvent->modifiers() & Qt::ControlModifier,
|
|
aEvent->modifiers() & Qt::AltModifier,
|
|
aEvent->modifiers() & Qt::ShiftModifier,
|
|
aEvent->modifiers() & Qt::MetaModifier);
|
|
aMouseEvent.clickCount = aClickCount;
|
|
|
|
switch (aEvent->button()) {
|
|
case Qt::LeftButton:
|
|
aMouseEvent.button = WidgetMouseEvent::eLeftButton;
|
|
break;
|
|
case Qt::RightButton:
|
|
aMouseEvent.button = WidgetMouseEvent::eRightButton;
|
|
break;
|
|
case Qt::MiddleButton:
|
|
aMouseEvent.button = WidgetMouseEvent::eMiddleButton;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static bool
|
|
IsAcceptedButton(Qt::MouseButton button)
|
|
{
|
|
switch (button) {
|
|
case Qt::LeftButton:
|
|
case Qt::RightButton:
|
|
case Qt::MiddleButton:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
nsEventStatus
|
|
nsWindow::mousePressEvent(QMouseEvent* aEvent)
|
|
{
|
|
// The user has done something.
|
|
UserActivity();
|
|
|
|
QPoint pos = aEvent->pos();
|
|
|
|
// we check against the widgets geometry, so use parent coordinates
|
|
// for the check
|
|
if (mWidget)
|
|
pos = mWidget->mapToGlobal(pos);
|
|
|
|
if (CheckForRollup(pos.x(), pos.y(), false))
|
|
return nsEventStatus_eIgnore;
|
|
|
|
if (!IsAcceptedButton(aEvent->button())) {
|
|
if (aEvent->button() == Qt::BackButton)
|
|
return DispatchCommandEvent(nsGkAtoms::Back);
|
|
if (aEvent->button() == Qt::ForwardButton)
|
|
return DispatchCommandEvent(nsGkAtoms::Forward);
|
|
return nsEventStatus_eIgnore;
|
|
}
|
|
|
|
WidgetMouseEvent event(true, eMouseDown, this, WidgetMouseEvent::eReal);
|
|
InitMouseEvent(event, aEvent, 1);
|
|
nsEventStatus status = DispatchEvent(&event);
|
|
|
|
// Right click on linux should also pop up a context menu.
|
|
if (event.button == WidgetMouseEvent::eRightButton &&
|
|
MOZ_LIKELY(!mIsDestroyed)) {
|
|
WidgetMouseEvent contextMenuEvent(true, eContextMenu, this,
|
|
WidgetMouseEvent::eReal);
|
|
InitMouseEvent(contextMenuEvent, aEvent, 1);
|
|
DispatchEvent(&contextMenuEvent, status);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
nsEventStatus
|
|
nsWindow::mouseReleaseEvent(QMouseEvent* aEvent)
|
|
{
|
|
// The user has done something.
|
|
UserActivity();
|
|
|
|
if (!IsAcceptedButton(aEvent->button()))
|
|
return nsEventStatus_eIgnore;
|
|
|
|
WidgetMouseEvent event(true, eMouseUp, this, WidgetMouseEvent::eReal);
|
|
InitMouseEvent(event, aEvent, 1);
|
|
return DispatchEvent(&event);
|
|
}
|
|
|
|
nsEventStatus
|
|
nsWindow::mouseDoubleClickEvent(QMouseEvent* aEvent)
|
|
{
|
|
// The user has done something.
|
|
UserActivity();
|
|
|
|
if (!IsAcceptedButton(aEvent->button()))
|
|
return nsEventStatus_eIgnore;
|
|
|
|
WidgetMouseEvent event(true, eMouseDoubleClick, this,
|
|
WidgetMouseEvent::eReal);
|
|
InitMouseEvent(event, aEvent, 2);
|
|
return DispatchEvent(&event);
|
|
}
|
|
|
|
nsEventStatus
|
|
nsWindow::focusInEvent(QFocusEvent* aEvent)
|
|
{
|
|
LOGFOCUS(("OnFocusInEvent [%p]\n", (void *)this));
|
|
|
|
if (!mWidget) {
|
|
return nsEventStatus_eIgnore;
|
|
}
|
|
|
|
DispatchActivateEventOnTopLevelWindow();
|
|
|
|
LOGFOCUS(("Events sent from focus in event [%p]\n", (void *)this));
|
|
return nsEventStatus_eIgnore;
|
|
}
|
|
|
|
nsEventStatus
|
|
nsWindow::focusOutEvent(QFocusEvent* aEvent)
|
|
{
|
|
LOGFOCUS(("OnFocusOutEvent [%p]\n", (void *)this));
|
|
|
|
if (!mWidget) {
|
|
return nsEventStatus_eIgnore;
|
|
}
|
|
|
|
DispatchDeactivateEventOnTopLevelWindow();
|
|
|
|
LOGFOCUS(("Done with container focus out [%p]\n", (void *)this));
|
|
return nsEventStatus_eIgnore;
|
|
}
|
|
|
|
static bool
|
|
IsContextMenuKeyEvent(const QKeyEvent* aQEvent)
|
|
{
|
|
if (aQEvent->modifiers() & (Qt::ControlModifier |
|
|
Qt::AltModifier |
|
|
Qt::MetaModifier)) {
|
|
return false;
|
|
}
|
|
|
|
bool isShift = aQEvent->modifiers() & Qt::ShiftModifier;
|
|
uint32_t keyCode = QtKeyCodeToDOMKeyCode(aQEvent->key());
|
|
return (keyCode == NS_VK_F10 && isShift) ||
|
|
(keyCode == NS_VK_CONTEXT_MENU && !isShift);
|
|
}
|
|
|
|
static void
|
|
InitKeyEvent(WidgetKeyboardEvent& aEvent, QKeyEvent* aQEvent)
|
|
{
|
|
aEvent.InitBasicModifiers(aQEvent->modifiers() & Qt::ControlModifier,
|
|
aQEvent->modifiers() & Qt::AltModifier,
|
|
aQEvent->modifiers() & Qt::ShiftModifier,
|
|
aQEvent->modifiers() & Qt::MetaModifier);
|
|
|
|
aEvent.mIsRepeat =
|
|
(aEvent.mMessage == eKeyDown || aEvent.mMessage == eKeyPress) &&
|
|
aQEvent->isAutoRepeat();
|
|
aEvent.time = 0;
|
|
|
|
if (sAltGrModifier) {
|
|
aEvent.modifiers |= (MODIFIER_CONTROL | MODIFIER_ALT);
|
|
}
|
|
|
|
if (aQEvent->text().length() && aQEvent->text()[0].isPrint()) {
|
|
aEvent.charCode = (int32_t) aQEvent->text()[0].unicode();
|
|
aEvent.keyCode = 0;
|
|
aEvent.mKeyNameIndex = KEY_NAME_INDEX_PrintableKey;
|
|
} else {
|
|
aEvent.charCode = 0;
|
|
aEvent.keyCode = QtKeyCodeToDOMKeyCode(aQEvent->key());
|
|
aEvent.mKeyNameIndex = QtKeyCodeToDOMKeyNameIndex(aQEvent->key());
|
|
}
|
|
|
|
aEvent.mCodeNameIndex = ScanCodeToDOMCodeNameIndex(aQEvent->nativeScanCode());
|
|
|
|
// The transformations above and in qt for the keyval are not invertible
|
|
// so link to the QKeyEvent (which will vanish soon after return from the
|
|
// event callback) to give plugins access to hardware_keycode and state.
|
|
// (An XEvent would be nice but the QKeyEvent is good enough.)
|
|
aEvent.mPluginEvent.Copy(*aQEvent);
|
|
}
|
|
|
|
nsEventStatus
|
|
nsWindow::keyPressEvent(QKeyEvent* aEvent)
|
|
{
|
|
LOGFOCUS(("OnKeyPressEvent [%p]\n", (void *)this));
|
|
|
|
// The user has done something.
|
|
UserActivity();
|
|
|
|
if (aEvent->key() == Qt::Key_AltGr) {
|
|
sAltGrModifier = true;
|
|
}
|
|
|
|
// Before we dispatch a key, check if it's the context menu key.
|
|
// If so, send a context menu key event instead.
|
|
if (IsContextMenuKeyEvent(aEvent)) {
|
|
WidgetMouseEvent contextMenuEvent(true, eContextMenu, this,
|
|
WidgetMouseEvent::eReal,
|
|
WidgetMouseEvent::eContextMenuKey);
|
|
return DispatchEvent(&contextMenuEvent);
|
|
}
|
|
|
|
//:TODO: fix shortcuts hebrew for non X11,
|
|
//see Bug 562195##51
|
|
|
|
uint32_t domKeyCode = QtKeyCodeToDOMKeyCode(aEvent->key());
|
|
|
|
if (!aEvent->isAutoRepeat() && !IsKeyDown(domKeyCode)) {
|
|
SetKeyDownFlag(domKeyCode);
|
|
|
|
WidgetKeyboardEvent downEvent(true, eKeyDown, this);
|
|
InitKeyEvent(downEvent, aEvent);
|
|
|
|
nsEventStatus status = DispatchEvent(&downEvent);
|
|
|
|
// DispatchEvent can Destroy us (bug 378273)
|
|
if (MOZ_UNLIKELY(mIsDestroyed)) {
|
|
qWarning() << "Returning[" << __LINE__ << "]: " << "Window destroyed";
|
|
return status;
|
|
}
|
|
|
|
// If prevent default on keydown, don't dispatch keypress event
|
|
if (status == nsEventStatus_eConsumeNoDefault) {
|
|
return nsEventStatus_eConsumeNoDefault;
|
|
}
|
|
}
|
|
|
|
// Don't pass modifiers as eKeyPress events.
|
|
// Instead of selectively excluding some keys from eKeyPress events,
|
|
// we instead selectively include (as per MSDN spec
|
|
// ( http://msdn.microsoft.com/en-us/library/system.windows.forms.control.keypress%28VS.71%29.aspx );
|
|
// no official spec covers KeyPress events).
|
|
if (aEvent->key() == Qt::Key_Shift ||
|
|
aEvent->key() == Qt::Key_Control ||
|
|
aEvent->key() == Qt::Key_Meta ||
|
|
aEvent->key() == Qt::Key_Alt ||
|
|
aEvent->key() == Qt::Key_AltGr) {
|
|
return nsEventStatus_eIgnore;
|
|
}
|
|
|
|
// Look for specialized app-command keys
|
|
switch (aEvent->key()) {
|
|
case Qt::Key_Back:
|
|
return DispatchCommandEvent(nsGkAtoms::Back);
|
|
case Qt::Key_Forward:
|
|
return DispatchCommandEvent(nsGkAtoms::Forward);
|
|
case Qt::Key_Refresh:
|
|
return DispatchCommandEvent(nsGkAtoms::Reload);
|
|
case Qt::Key_Stop:
|
|
return DispatchCommandEvent(nsGkAtoms::Stop);
|
|
case Qt::Key_Search:
|
|
return DispatchCommandEvent(nsGkAtoms::Search);
|
|
case Qt::Key_Favorites:
|
|
return DispatchCommandEvent(nsGkAtoms::Bookmarks);
|
|
case Qt::Key_HomePage:
|
|
return DispatchCommandEvent(nsGkAtoms::Home);
|
|
case Qt::Key_Copy:
|
|
case Qt::Key_F16: // F16, F20, F18, F14 are old keysyms for Copy Cut Paste Undo
|
|
return DispatchContentCommandEvent(eContentCommandCopy);
|
|
case Qt::Key_Cut:
|
|
case Qt::Key_F20:
|
|
return DispatchContentCommandEvent(eContentCommandCut);
|
|
case Qt::Key_Paste:
|
|
case Qt::Key_F18:
|
|
case Qt::Key_F9:
|
|
return DispatchContentCommandEvent(eContentCommandPaste);
|
|
case Qt::Key_F14:
|
|
return DispatchContentCommandEvent(eContentCommandUndo);
|
|
}
|
|
|
|
// Qt::Key_Redo and Qt::Key_Undo are not available yet.
|
|
if (aEvent->nativeVirtualKey() == 0xff66) {
|
|
return DispatchContentCommandEvent(eContentCommandRedo);
|
|
}
|
|
if (aEvent->nativeVirtualKey() == 0xff65) {
|
|
return DispatchContentCommandEvent(eContentCommandUndo);
|
|
}
|
|
|
|
WidgetKeyboardEvent event(true, eKeyPress, this);
|
|
InitKeyEvent(event, aEvent);
|
|
// Seend the key press event
|
|
return DispatchEvent(&event);
|
|
}
|
|
|
|
nsEventStatus
|
|
nsWindow::keyReleaseEvent(QKeyEvent* aEvent)
|
|
{
|
|
LOGFOCUS(("OnKeyReleaseEvent [%p]\n", (void *)this));
|
|
|
|
// The user has done something.
|
|
UserActivity();
|
|
|
|
if (IsContextMenuKeyEvent(aEvent)) {
|
|
// er, what do we do here? DoDefault or NoDefault?
|
|
return nsEventStatus_eConsumeDoDefault;
|
|
}
|
|
|
|
// send the key event as a key up event
|
|
WidgetKeyboardEvent event(true, eKeyUp, this);
|
|
InitKeyEvent(event, aEvent);
|
|
|
|
if (aEvent->key() == Qt::Key_AltGr) {
|
|
sAltGrModifier = false;
|
|
}
|
|
|
|
// unset the key down flag
|
|
ClearKeyDownFlag(event.keyCode);
|
|
|
|
return DispatchEvent(&event);
|
|
}
|
|
|
|
nsEventStatus
|
|
nsWindow::wheelEvent(QWheelEvent* aEvent)
|
|
{
|
|
// check to see if we should rollup
|
|
WidgetWheelEvent wheelEvent(true, eWheel, this);
|
|
wheelEvent.deltaMode = nsIDOMWheelEvent::DOM_DELTA_LINE;
|
|
|
|
// negative values for aEvent->delta indicate downward scrolling;
|
|
// this is opposite Gecko usage.
|
|
// TODO: Store the unused delta values due to fraction round and add it
|
|
// to next event. The stored values should be reset by other
|
|
// direction scroll event.
|
|
int32_t delta = (int)(aEvent->delta() / WHEEL_DELTA) * -3;
|
|
|
|
switch (aEvent->orientation()) {
|
|
case Qt::Vertical:
|
|
wheelEvent.deltaY = wheelEvent.lineOrPageDeltaY = delta;
|
|
break;
|
|
case Qt::Horizontal:
|
|
wheelEvent.deltaX = wheelEvent.lineOrPageDeltaX = delta;
|
|
break;
|
|
default:
|
|
Q_ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
wheelEvent.refPoint.x = nscoord(aEvent->pos().x());
|
|
wheelEvent.refPoint.y = nscoord(aEvent->pos().y());
|
|
|
|
wheelEvent.InitBasicModifiers(aEvent->modifiers() & Qt::ControlModifier,
|
|
aEvent->modifiers() & Qt::AltModifier,
|
|
aEvent->modifiers() & Qt::ShiftModifier,
|
|
aEvent->modifiers() & Qt::MetaModifier);
|
|
wheelEvent.time = 0;
|
|
|
|
return DispatchEvent(&wheelEvent);
|
|
}
|
|
|
|
nsEventStatus
|
|
nsWindow::showEvent(QShowEvent *)
|
|
{
|
|
LOG(("%s [%p]\n", __PRETTY_FUNCTION__,(void *)this));
|
|
mVisible = true;
|
|
return nsEventStatus_eConsumeDoDefault;
|
|
}
|
|
|
|
nsEventStatus
|
|
nsWindow::hideEvent(QHideEvent *)
|
|
{
|
|
LOG(("%s [%p]\n", __PRETTY_FUNCTION__,(void *)this));
|
|
mVisible = false;
|
|
return nsEventStatus_eConsumeDoDefault;
|
|
}
|
|
|
|
nsEventStatus nsWindow::touchEvent(QTouchEvent* aEvent)
|
|
{
|
|
return nsEventStatus_eIgnore;
|
|
}
|
|
|
|
nsEventStatus
|
|
nsWindow::tabletEvent(QTabletEvent* aEvent)
|
|
{
|
|
LOGFOCUS(("nsWindow::%s [%p]\n", __FUNCTION__, (void *)this));
|
|
return nsEventStatus_eIgnore;
|
|
}
|
|
|
|
// Helpers
|
|
|
|
nsEventStatus
|
|
nsWindow::DispatchEvent(WidgetGUIEvent* aEvent)
|
|
{
|
|
nsEventStatus status;
|
|
DispatchEvent(aEvent, status);
|
|
return status;
|
|
}
|
|
|
|
void
|
|
nsWindow::DispatchActivateEvent(void)
|
|
{
|
|
if (mWidgetListener) {
|
|
mWidgetListener->WindowActivated();
|
|
}
|
|
}
|
|
|
|
void
|
|
nsWindow::DispatchDeactivateEvent(void)
|
|
{
|
|
if (mWidgetListener) {
|
|
mWidgetListener->WindowDeactivated();
|
|
}
|
|
}
|
|
|
|
void
|
|
nsWindow::DispatchActivateEventOnTopLevelWindow(void)
|
|
{
|
|
nsWindow* topLevelWindow = static_cast<nsWindow*>(GetTopLevelWidget());
|
|
if (topLevelWindow != nullptr) {
|
|
topLevelWindow->DispatchActivateEvent();
|
|
}
|
|
}
|
|
|
|
void
|
|
nsWindow::DispatchDeactivateEventOnTopLevelWindow(void)
|
|
{
|
|
nsWindow* topLevelWindow = static_cast<nsWindow*>(GetTopLevelWidget());
|
|
if (topLevelWindow != nullptr) {
|
|
topLevelWindow->DispatchDeactivateEvent();
|
|
}
|
|
}
|
|
|
|
void
|
|
nsWindow::DispatchResizeEvent(LayoutDeviceIntRect& aRect,
|
|
nsEventStatus& aStatus)
|
|
{
|
|
aStatus = nsEventStatus_eIgnore;
|
|
if (mWidgetListener &&
|
|
mWidgetListener->WindowResized(this, aRect.width, aRect.height)) {
|
|
aStatus = nsEventStatus_eConsumeNoDefault;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////// OLD GECKO ECENTS need to Sort ///////////////////
|
|
|
|
void
|
|
nsWindow::ClearCachedResources()
|
|
{
|
|
if (mLayerManager &&
|
|
mLayerManager->GetBackendType() == mozilla::layers::LayersBackend::LAYERS_BASIC) {
|
|
mLayerManager->ClearCachedResources();
|
|
}
|
|
for (nsIWidget* kid = mFirstChild; kid; ) {
|
|
nsIWidget* next = kid->GetNextSibling();
|
|
static_cast<nsWindow*>(kid)->ClearCachedResources();
|
|
kid = next;
|
|
}
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::SetParent(nsIWidget *aNewParent)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aNewParent);
|
|
|
|
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
|
|
nsIWidget* parent = GetParent();
|
|
if (parent) {
|
|
parent->RemoveChild(this);
|
|
}
|
|
ReparentNativeWidget(aNewParent);
|
|
aNewParent->AddChild(this);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::SetModal(bool aModal)
|
|
{
|
|
LOG(("nsWindow::SetModal [%p] %d, widget[%p]\n", (void *)this, aModal, mWidget));
|
|
if (mWidget) {
|
|
mWidget->setModality(aModal ? Qt::WindowModal : Qt::NonModal);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
|
|
nsIWidget *aWidget,
|
|
bool aActivate)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::SetSizeMode(nsSizeMode aMode)
|
|
{
|
|
nsresult rv;
|
|
|
|
LOG(("nsWindow::SetSizeMode [%p] %d\n", (void *)this, aMode));
|
|
if (aMode != nsSizeMode_Minimized) {
|
|
mWidget->requestActivate();
|
|
}
|
|
|
|
// Save the requested state.
|
|
rv = nsBaseWidget::SetSizeMode(aMode);
|
|
|
|
// return if there's no shell or our current state is the same as
|
|
// the mode we were just set to.
|
|
if (!mWidget || mSizeState == mSizeMode) {
|
|
return rv;
|
|
}
|
|
|
|
switch (aMode) {
|
|
case nsSizeMode_Maximized:
|
|
mWidget->showMaximized();
|
|
break;
|
|
case nsSizeMode_Minimized:
|
|
mWidget->showMinimized();
|
|
break;
|
|
case nsSizeMode_Fullscreen:
|
|
mWidget->showFullScreen();
|
|
break;
|
|
|
|
default:
|
|
// nsSizeMode_Normal, really.
|
|
mWidget->show();
|
|
break;
|
|
}
|
|
|
|
mSizeState = mSizeMode;
|
|
|
|
return rv;
|
|
}
|
|
|
|
// Helper function to recursively find the first parent item that
|
|
// is still visible (QGraphicsItem can be hidden even if they are
|
|
// set to visible if one of their ancestors is invisible)
|
|
/* static */
|
|
void find_first_visible_parent(QWindow* aItem, QWindow*& aVisibleItem)
|
|
{
|
|
NS_ENSURE_TRUE_VOID(aItem);
|
|
|
|
aVisibleItem = nullptr;
|
|
QWindow* parItem = nullptr;
|
|
while (!aVisibleItem) {
|
|
if (aItem->isVisible()) {
|
|
aVisibleItem = aItem;
|
|
}
|
|
else {
|
|
parItem = aItem->parent();
|
|
if (parItem) {
|
|
aItem = parItem;
|
|
}
|
|
else {
|
|
aItem->setVisible(true);
|
|
aVisibleItem = aItem;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::GetScreenBounds(LayoutDeviceIntRect& aRect)
|
|
{
|
|
aRect = LayoutDeviceIntRect(LayoutDeviceIntPoint(0, 0),
|
|
LayoutDeviceIntSize::FromUnknownSize(mBounds.Size()));
|
|
if (mIsTopLevel) {
|
|
QPoint pos = mWidget->position();
|
|
aRect.MoveTo(pos.x(), pos.y());
|
|
} else {
|
|
aRect.MoveTo(WidgetToScreenOffset());
|
|
}
|
|
LOG(("GetScreenBounds %d %d | %d %d | %d %d\n",
|
|
aRect.x, aRect.y,
|
|
mBounds.width, mBounds.height,
|
|
aRect.width, aRect.height));
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::SetIcon(const nsAString& aIconSpec)
|
|
{
|
|
if (!mWidget)
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsIFile> iconFile;
|
|
nsAutoCString path;
|
|
nsTArray<nsCString> iconList;
|
|
|
|
// Look for icons with the following suffixes appended to the base name.
|
|
// The last two entries (for the old XPM format) will be ignored unless
|
|
// no icons are found using the other suffixes. XPM icons are depricated.
|
|
|
|
const char extensions[6][7] = { ".png", "16.png", "32.png", "48.png",
|
|
".xpm", "16.xpm" };
|
|
|
|
for (uint32_t i = 0; i < ArrayLength(extensions); i++) {
|
|
// Don't bother looking for XPM versions if we found a PNG.
|
|
if (i == ArrayLength(extensions) - 2 && iconList.Length())
|
|
break;
|
|
|
|
nsAutoString extension;
|
|
extension.AppendASCII(extensions[i]);
|
|
|
|
ResolveIconName(aIconSpec, extension, getter_AddRefs(iconFile));
|
|
if (iconFile) {
|
|
iconFile->GetNativePath(path);
|
|
iconList.AppendElement(path);
|
|
}
|
|
}
|
|
|
|
// leave the default icon intact if no matching icons were found
|
|
if (iconList.Length() == 0)
|
|
return NS_OK;
|
|
|
|
return SetWindowIconList(iconList);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::CaptureMouse(bool aCapture)
|
|
{
|
|
LOG(("CaptureMouse %p\n", (void *)this));
|
|
|
|
if (!mWidget)
|
|
return NS_OK;
|
|
|
|
mWidget->setMouseGrabEnabled(aCapture);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
bool
|
|
nsWindow::CheckForRollup(double aMouseX, double aMouseY,
|
|
bool aIsWheel)
|
|
{
|
|
nsIRollupListener* rollupListener = GetActiveRollupListener();
|
|
nsCOMPtr<nsIWidget> rollupWidget;
|
|
if (rollupListener) {
|
|
rollupWidget = rollupListener->GetRollupWidget();
|
|
}
|
|
if (!rollupWidget) {
|
|
nsBaseWidget::gRollupListener = nullptr;
|
|
return false;
|
|
}
|
|
|
|
bool retVal = false;
|
|
MozQWidget *currentPopup =
|
|
(MozQWidget *)rollupWidget->GetNativeData(NS_NATIVE_WINDOW);
|
|
if (!is_mouse_in_window(currentPopup, aMouseX, aMouseY)) {
|
|
bool rollup = true;
|
|
if (aIsWheel) {
|
|
rollup = rollupListener->ShouldRollupOnMouseWheelEvent();
|
|
retVal = true;
|
|
}
|
|
// if we're dealing with menus, we probably have submenus and
|
|
// we don't want to rollup if the clickis in a parent menu of
|
|
// the current submenu
|
|
uint32_t popupsToRollup = UINT32_MAX;
|
|
if (rollupListener) {
|
|
nsAutoTArray<nsIWidget*, 5> widgetChain;
|
|
uint32_t sameTypeCount = rollupListener->GetSubmenuWidgetChain(&widgetChain);
|
|
for (uint32_t i=0; i<widgetChain.Length(); ++i) {
|
|
nsIWidget* widget = widgetChain[i];
|
|
MozQWidget* currWindow =
|
|
(MozQWidget*) widget->GetNativeData(NS_NATIVE_WINDOW);
|
|
if (is_mouse_in_window(currWindow, aMouseX, aMouseY)) {
|
|
if (i < sameTypeCount) {
|
|
rollup = false;
|
|
}
|
|
else {
|
|
popupsToRollup = sameTypeCount;
|
|
}
|
|
break;
|
|
}
|
|
} // foreach parent menu widget
|
|
} // if rollup listener knows about menus
|
|
|
|
// if we've determined that we should still rollup, do it.
|
|
if (rollup) {
|
|
nsIntPoint pos(aMouseX, aMouseY);
|
|
retVal = rollupListener->Rollup(popupsToRollup, true, &pos, nullptr);
|
|
}
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
/* static */
|
|
bool
|
|
is_mouse_in_window (MozQWidget* aWindow, double aMouseX, double aMouseY)
|
|
{
|
|
return aWindow->geometry().contains(aMouseX, aMouseY);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::GetAttention(int32_t aCycleCount)
|
|
{
|
|
LOG(("nsWindow::GetAttention [%p]\n", (void *)this));
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
|
|
|
|
nsEventStatus
|
|
nsWindow::OnCloseEvent(QCloseEvent *aEvent)
|
|
{
|
|
if (!mWidgetListener)
|
|
return nsEventStatus_eIgnore;
|
|
mWidgetListener->RequestWindowClose(this);
|
|
return nsEventStatus_eConsumeNoDefault;
|
|
}
|
|
|
|
|
|
inline bool
|
|
is_latin_shortcut_key(quint32 aKeyval)
|
|
{
|
|
return ((Qt::Key_0 <= aKeyval && aKeyval <= Qt::Key_9) ||
|
|
(Qt::Key_A <= aKeyval && aKeyval <= Qt::Key_Z));
|
|
}
|
|
|
|
nsEventStatus
|
|
nsWindow::DispatchCommandEvent(nsIAtom* aCommand)
|
|
{
|
|
WidgetCommandEvent event(true, nsGkAtoms::onAppCommand, aCommand, this);
|
|
|
|
nsEventStatus status;
|
|
DispatchEvent(&event, status);
|
|
|
|
return status;
|
|
}
|
|
|
|
nsEventStatus
|
|
nsWindow::DispatchContentCommandEvent(EventMessage aMsg)
|
|
{
|
|
WidgetContentCommandEvent event(true, aMsg, this);
|
|
|
|
nsEventStatus status;
|
|
DispatchEvent(&event, status);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
static void
|
|
GetBrandName(nsXPIDLString& brandName)
|
|
{
|
|
nsCOMPtr<nsIStringBundleService> bundleService =
|
|
mozilla::services::GetStringBundleService();
|
|
|
|
nsCOMPtr<nsIStringBundle> bundle;
|
|
if (bundleService) {
|
|
bundleService->CreateBundle(
|
|
"chrome://branding/locale/brand.properties",
|
|
getter_AddRefs(bundle));
|
|
}
|
|
|
|
if (bundle) {
|
|
bundle->GetStringFromName(
|
|
MOZ_UTF16("brandShortName"),
|
|
getter_Copies(brandName));
|
|
}
|
|
|
|
if (brandName.IsEmpty()) {
|
|
brandName.AssignLiteral(MOZ_UTF16("Mozilla"));
|
|
}
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::SetWindowClass(const nsAString &xulWinType)
|
|
{
|
|
if (!mWidget) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
nsXPIDLString brandName;
|
|
GetBrandName(brandName);
|
|
|
|
#ifdef MOZ_X11
|
|
XClassHint *class_hint = XAllocClassHint();
|
|
if (!class_hint) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
const char *role = nullptr;
|
|
class_hint->res_name = ToNewCString(xulWinType);
|
|
if (!class_hint->res_name) {
|
|
XFree(class_hint);
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
class_hint->res_class = ToNewCString(brandName);
|
|
if (!class_hint->res_class) {
|
|
free(class_hint->res_name);
|
|
XFree(class_hint);
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
// Parse res_name into a name and role. Characters other than
|
|
// [A-Za-z0-9_-] are converted to '_'. Anything after the first
|
|
// colon is assigned to role; if there's no colon, assign the
|
|
// whole thing to both role and res_name.
|
|
for (char *c = class_hint->res_name; *c; c++) {
|
|
if (':' == *c) {
|
|
*c = 0;
|
|
role = c + 1;
|
|
}
|
|
else if (!isascii(*c) || (!isalnum(*c) && ('_' != *c) && ('-' != *c)))
|
|
*c = '_';
|
|
}
|
|
class_hint->res_name[0] = toupper(class_hint->res_name[0]);
|
|
if (!role) role = class_hint->res_name;
|
|
|
|
QWindow *widget = mWidget;
|
|
// If widget not show, handle might be null
|
|
if (widget && widget->winId()) {
|
|
XSetClassHint(gfxQtPlatform::GetXDisplay(widget),
|
|
widget->winId(),
|
|
class_hint);
|
|
}
|
|
|
|
free(class_hint->res_class);
|
|
free(class_hint->res_name);
|
|
XFree(class_hint);
|
|
#endif
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsWindow::NativeResize(int32_t aWidth, int32_t aHeight, bool aRepaint)
|
|
{
|
|
LOG(("nsWindow::NativeResize [%p] %d %d\n", (void *)this,
|
|
aWidth, aHeight));
|
|
|
|
mNeedsResize = false;
|
|
|
|
mWidget->resize(aWidth, aHeight);
|
|
|
|
if (aRepaint) {
|
|
mWidget->renderLater();
|
|
}
|
|
}
|
|
|
|
void
|
|
nsWindow::NativeResize(int32_t aX, int32_t aY,
|
|
int32_t aWidth, int32_t aHeight,
|
|
bool aRepaint)
|
|
{
|
|
LOG(("nsWindow::NativeResize [%p] %d %d %d %d\n", (void *)this,
|
|
aX, aY, aWidth, aHeight));
|
|
|
|
mNeedsResize = false;
|
|
mNeedsMove = false;
|
|
|
|
mWidget->setGeometry(aX, aY, aWidth, aHeight);
|
|
|
|
if (aRepaint) {
|
|
mWidget->renderLater();
|
|
}
|
|
}
|
|
|
|
void
|
|
nsWindow::NativeShow(bool aAction)
|
|
{
|
|
if (aAction) {
|
|
// On e10s, we never want the child process or plugin process
|
|
// to go fullscreen because if we do the window because visible
|
|
// do to disabled Qt-Xembed
|
|
mWidget->show();
|
|
// unset our flag now that our window has been shown
|
|
mNeedsShow = false;
|
|
}
|
|
else {
|
|
mWidget->hide();
|
|
}
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::SetHasTransparentBackground(bool aTransparent)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::GetHasTransparentBackground(bool& aTransparent)
|
|
{
|
|
aTransparent = mIsTransparent;
|
|
return NS_OK;
|
|
}
|
|
|
|
void *
|
|
nsWindow::SetupPluginPort(void)
|
|
{
|
|
NS_WARNING("Not implemented");
|
|
return nullptr;
|
|
}
|
|
|
|
nsresult
|
|
nsWindow::SetWindowIconList(const nsTArray<nsCString> &aIconList)
|
|
{
|
|
QIcon icon;
|
|
|
|
for (uint32_t i = 0; i < aIconList.Length(); ++i) {
|
|
const char *path = aIconList[i].get();
|
|
LOG(("window [%p] Loading icon from %s\n", (void *)this, path));
|
|
icon.addFile(path);
|
|
}
|
|
|
|
mWidget->setIcon(icon);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsWindow::SetDefaultIcon(void)
|
|
{
|
|
SetIcon(NS_LITERAL_STRING("default"));
|
|
}
|
|
|
|
void nsWindow::QWidgetDestroyed()
|
|
{
|
|
mWidget = nullptr;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::HideWindowChrome(bool aShouldHide)
|
|
{
|
|
if (!mWidget) {
|
|
// Nothing to hide
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
// Sawfish, metacity, and presumably other window managers get
|
|
// confused if we change the window decorations while the window
|
|
// is visible.
|
|
bool wasVisible = false;
|
|
if (mWidget->isVisible()) {
|
|
NativeShow(false);
|
|
wasVisible = true;
|
|
}
|
|
|
|
if (wasVisible) {
|
|
NativeShow(true);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
NS_IMETHODIMP_(bool)
|
|
nsWindow::HasGLContext()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
nsIWidget*
|
|
nsWindow::GetParent(void)
|
|
{
|
|
return mParent;
|
|
}
|
|
|
|
float
|
|
nsWindow::GetDPI()
|
|
{
|
|
return qApp->primaryScreen()->logicalDotsPerInch();
|
|
}
|
|
|
|
void
|
|
nsWindow::OnDestroy(void)
|
|
{
|
|
if (mOnDestroyCalled) {
|
|
return;
|
|
}
|
|
|
|
mOnDestroyCalled = true;
|
|
|
|
// release references to children and device context
|
|
nsBaseWidget::OnDestroy();
|
|
|
|
// let go of our parent
|
|
mParent = nullptr;
|
|
|
|
nsCOMPtr<nsIWidget> kungFuDeathGrip = this;
|
|
NotifyWindowDestroyed();
|
|
}
|
|
|
|
bool
|
|
nsWindow::AreBoundsSane(void)
|
|
{
|
|
if (mBounds.width > 0 && mBounds.height > 0) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void
|
|
nsWindow::SetSoftwareKeyboardState(bool aOpen,
|
|
const InputContextAction& aAction)
|
|
{
|
|
if (aOpen) {
|
|
NS_ENSURE_TRUE_VOID(mInputContext.mIMEState.mEnabled !=
|
|
IMEState::DISABLED);
|
|
|
|
// Ensure that opening the virtual keyboard is allowed for this specific
|
|
// InputContext depending on the content.ime.strict.policy pref
|
|
if (mInputContext.mIMEState.mEnabled != IMEState::PLUGIN &&
|
|
Preferences::GetBool("content.ime.strict_policy", false) &&
|
|
!aAction.ContentGotFocusByTrustedCause() &&
|
|
!aAction.UserMightRequestOpenVKB()) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (aOpen) {
|
|
qApp->inputMethod()->show();
|
|
} else {
|
|
qApp->inputMethod()->hide();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void
|
|
nsWindow::ProcessMotionEvent()
|
|
{
|
|
if (mMoveEvent.needDispatch) {
|
|
WidgetMouseEvent event(true, eMouseMove, this, WidgetMouseEvent::eReal);
|
|
|
|
event.refPoint.x = nscoord(mMoveEvent.pos.x());
|
|
event.refPoint.y = nscoord(mMoveEvent.pos.y());
|
|
|
|
event.InitBasicModifiers(mMoveEvent.modifiers & Qt::ControlModifier,
|
|
mMoveEvent.modifiers & Qt::AltModifier,
|
|
mMoveEvent.modifiers & Qt::ShiftModifier,
|
|
mMoveEvent.modifiers & Qt::MetaModifier);
|
|
event.clickCount = 0;
|
|
|
|
DispatchEvent(&event);
|
|
mMoveEvent.needDispatch = false;
|
|
}
|
|
|
|
mTimerStarted = false;
|
|
}
|
|
|