1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim:expandtab:shiftwidth=4:tabstop=4:
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "mozilla/Util.h"
10 #include <QApplication>
11 #include <QDesktopWidget>
12 #include <QtGui/QCursor>
14 #include <QGraphicsScene>
15 #include <QGraphicsView>
16 #include <QGraphicsSceneContextMenuEvent>
17 #include <QGraphicsSceneDragDropEvent>
18 #include <QGraphicsSceneMouseEvent>
19 #include <QGraphicsSceneHoverEvent>
20 #include <QGraphicsSceneWheelEvent>
21 #include <QGraphicsSceneResizeEvent>
22 #include <QStyleOptionGraphicsItem>
23 #include <QPaintEngine>
25 #include "mozqglwidgetwrapper.h"
27 #include <QtCore/QDebug>
28 #include <QtCore/QEvent>
29 #include <QtCore/QVariant>
31 #if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 0))
32 #include <QPinchGesture>
33 #include <QGestureRecognizer>
34 #include "mozSwipeGesture.h"
35 static Qt::GestureType gSwipeGestureId
= Qt::CustomGesture
;
37 // How many milliseconds mouseevents are blocked after receiving
39 static const float GESTURES_BLOCK_MOUSE_FOR
= 200;
40 #ifdef MOZ_ENABLE_QTMOBILITY
41 #include <QtSensors/QOrientationSensor>
42 using namespace QtMobility
;
43 #endif // MOZ_ENABLE_QTMOBILITY
44 #endif // QT version check 4.6
50 #include "nsXULAppAPI.h"
55 #include "mozqwidget.h"
57 #ifdef MOZ_ENABLE_QTMOBILITY
58 #include "mozqorientationsensorfilter.h"
61 #include "nsIdleService.h"
62 #include "nsRenderingContext.h"
63 #include "nsIRollupListener.h"
64 #include "nsWidgetsCID.h"
65 #include "nsQtKeyUtils.h"
66 #include "mozilla/Services.h"
67 #include "mozilla/Preferences.h"
68 #include "mozilla/Likely.h"
69 #include "mozilla/layers/LayersTypes.h"
70 #include "nsIWidgetListener.h"
72 #include "nsIStringBundle.h"
73 #include "nsGfxCIID.h"
75 #include "imgIContainer.h"
76 #include "nsGfxCIID.h"
77 #include "nsIInterfaceRequestorUtils.h"
78 #include "nsAutoPtr.h"
80 #include "gfxQtPlatform.h"
82 #include "gfxXlibSurface.h"
84 #include "gfxQPainterSurface.h"
85 #include "gfxContext.h"
86 #include "gfxImageSurface.h"
88 #include "nsIDOMSimpleGestureEvent.h" //Gesture support
89 #include "nsIDOMWheelEvent.h"
92 #include "keysym2ucs.h"
97 #include "GLContextProvider.h"
98 #include "LayerManagerOGL.h"
99 #include "nsFastStartupQt.h"
101 // If embedding clients want to create widget without real parent window
102 // then nsIBaseWindow->Init() should have parent argument equal to PARENTLESS_WIDGET
103 #define PARENTLESS_WIDGET (void*)0x13579
105 #include "nsShmImage.h"
107 #define PIXMAN_DONT_DEFINE_STDINT
111 using namespace mozilla
;
112 using namespace mozilla::widget
;
113 using mozilla::gl::GLContext
;
114 using mozilla::layers::LayerManagerOGL
;
116 // Cached offscreen surface
117 static nsRefPtr
<gfxASurface
> gBufferSurface
;
118 #ifdef MOZ_HAVE_SHMIMAGE
119 // If we're using xshm rendering, mThebesSurface wraps gShmImage
120 nsRefPtr
<nsShmImage
> gShmImage
;
123 static int gBufferPixmapUsageCount
= 0;
124 static gfxIntSize
gBufferMaxSize(0, 0);
126 // initialization static functions
127 static nsresult
initialize_prefs (void);
129 static NS_DEFINE_IID(kCDragServiceCID
, NS_DRAGSERVICE_CID
);
131 #define NS_WINDOW_TITLE_MAX_LENGTH 4095
133 #define kWindowPositionSlop 20
136 static const int WHEEL_DELTA
= 120;
137 static bool gGlobalsInitialized
= false;
140 is_mouse_in_window (MozQWidget
* aWindow
, double aMouseX
, double aMouseY
);
142 static bool sAltGrModifier
= false;
144 #ifdef MOZ_ENABLE_QTMOBILITY
145 static QOrientationSensor
*gOrientation
= nullptr;
146 static MozQOrientationSensorFilter gOrientationFilter
;
150 isContextMenuKeyEvent(const QKeyEvent
*qe
)
152 uint32_t kc
= QtKeyCodeToDOMKeyCode(qe
->key());
153 if (qe
->modifiers() & (Qt::ControlModifier
| Qt::AltModifier
| Qt::MetaModifier
))
156 bool isShift
= qe
->modifiers() & Qt::ShiftModifier
;
157 return (kc
== NS_VK_F10
&& isShift
) ||
158 (kc
== NS_VK_CONTEXT_MENU
&& !isShift
);
162 InitKeyEvent(nsKeyEvent
&aEvent
, QKeyEvent
*aQEvent
)
164 aEvent
.InitBasicModifiers(aQEvent
->modifiers() & Qt::ControlModifier
,
165 aQEvent
->modifiers() & Qt::AltModifier
,
166 aQEvent
->modifiers() & Qt::ShiftModifier
,
167 aQEvent
->modifiers() & Qt::MetaModifier
);
170 if (sAltGrModifier
) {
171 aEvent
.modifiers
|= (widget::MODIFIER_CONTROL
| widget::MODIFIER_ALT
);
174 // The transformations above and in qt for the keyval are not invertible
175 // so link to the QKeyEvent (which will vanish soon after return from the
176 // event callback) to give plugins access to hardware_keycode and state.
177 // (An XEvent would be nice but the QKeyEvent is good enough.)
178 aEvent
.pluginEvent
= (void *)aQEvent
;
183 LOG(("%s [%p]\n", __PRETTY_FUNCTION__
, (void *)this));
186 mIsDestroyed
= false;
191 mActivatePending
= false;
192 mWindowType
= eWindowType_child
;
193 mSizeState
= nsSizeMode_Normal
;
194 mLastSizeMode
= nsSizeMode_Normal
;
195 mPluginType
= PluginType_NONE
;
196 mQCursor
= Qt::ArrowCursor
;
197 mNeedsResize
= false;
199 mListenForResizes
= false;
201 mGesturesCancelled
= false;
202 mTimerStarted
= false;
203 mPinchEvent
.needDispatch
= false;
204 mMoveEvent
.needDispatch
= false;
206 if (!gGlobalsInitialized
) {
207 gfxPlatform::GetPlatform();
208 gGlobalsInitialized
= true;
210 // It's OK if either of these fail, but it may not be one day.
214 memset(mKeyDownFlags
, 0, sizeof(mKeyDownFlags
));
216 mIsTransparent
= false;
218 mCursor
= eCursor_standard
;
220 gBufferPixmapUsageCount
++;
222 #if (QT_VERSION > QT_VERSION_CHECK(4,6,0))
223 if (gSwipeGestureId
== Qt::CustomGesture
) {
224 // QGestureRecognizer takes ownership
225 MozSwipeGestureRecognizer
* swipeRecognizer
= new MozSwipeGestureRecognizer
;
226 gSwipeGestureId
= QGestureRecognizer::registerRecognizer(swipeRecognizer
);
231 static inline gfxASurface::gfxImageFormat
232 _depth_to_gfximage_format(int32_t aDepth
)
236 return gfxASurface::ImageFormatARGB32
;
238 return gfxASurface::ImageFormatRGB24
;
240 return gfxASurface::ImageFormatRGB16_565
;
242 return gfxASurface::ImageFormatUnknown
;
246 static inline QImage::Format
247 _gfximage_to_qformat(gfxASurface::gfxImageFormat aFormat
)
250 case gfxASurface::ImageFormatARGB32
:
251 return QImage::Format_ARGB32_Premultiplied
;
252 case gfxASurface::ImageFormatRGB24
:
253 return QImage::Format_ARGB32
;
254 case gfxASurface::ImageFormatRGB16_565
:
255 return QImage::Format_RGB16
;
257 return QImage::Format_Invalid
;
262 UpdateOffScreenBuffers(int aDepth
, QSize aSize
, QWidget
* aWidget
= nullptr)
264 gfxIntSize
size(aSize
.width(), aSize
.height());
265 if (gBufferSurface
) {
266 if (gBufferMaxSize
.width
< size
.width
||
267 gBufferMaxSize
.height
< size
.height
) {
268 gBufferSurface
= nullptr;
273 gBufferMaxSize
.width
= std::max(gBufferMaxSize
.width
, size
.width
);
274 gBufferMaxSize
.height
= std::max(gBufferMaxSize
.height
, size
.height
);
276 // Check if system depth has related gfxImage format
277 gfxASurface::gfxImageFormat format
=
278 _depth_to_gfximage_format(aDepth
);
280 // Use fallback RGB24 format, Qt will do conversion for us
281 if (format
== gfxASurface::ImageFormatUnknown
)
282 format
= gfxASurface::ImageFormatRGB24
;
284 #ifdef MOZ_HAVE_SHMIMAGE
286 if (gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType() ==
287 gfxASurface::SurfaceTypeImage
) {
288 gShmImage
= nsShmImage::Create(gBufferMaxSize
,
289 DefaultVisualOfScreen(gfxQtPlatform::GetXScreen(aWidget
)),
291 gBufferSurface
= gShmImage
->AsSurface();
297 gBufferSurface
= gfxPlatform::GetPlatform()->
298 CreateOffscreenSurface(gBufferMaxSize
, gfxASurface::ContentFromFormat(format
));
303 nsWindow::~nsWindow()
305 LOG(("%s [%p]\n", __PRETTY_FUNCTION__
, (void *)this));
311 nsWindow::ReleaseGlobals()
315 NS_IMPL_ISUPPORTS_INHERITED1(nsWindow
, nsBaseWidget
, nsISupportsWeakReference
)
318 nsWindow::ConfigureChildren(const nsTArray
<nsIWidget::Configuration
>& aConfigurations
)
320 for (uint32_t i
= 0; i
< aConfigurations
.Length(); ++i
) {
321 const Configuration
& configuration
= aConfigurations
[i
];
323 nsWindow
* w
= static_cast<nsWindow
*>(configuration
.mChild
);
324 NS_ASSERTION(w
->GetParent() == this,
325 "Configured widget is not a child");
327 if (w
->mBounds
.Size() != configuration
.mBounds
.Size()) {
328 w
->Resize(configuration
.mBounds
.x
, configuration
.mBounds
.y
,
329 configuration
.mBounds
.width
, configuration
.mBounds
.height
,
331 } else if (w
->mBounds
.TopLeft() != configuration
.mBounds
.TopLeft()) {
332 w
->Move(configuration
.mBounds
.x
, configuration
.mBounds
.y
);
339 nsWindow::Destroy(void)
341 if (mIsDestroyed
|| !mWidget
)
344 LOG(("nsWindow::Destroy [%p]\n", (void *)this));
347 if (gBufferPixmapUsageCount
&&
348 --gBufferPixmapUsageCount
== 0) {
350 gBufferSurface
= nullptr;
351 #ifdef MOZ_HAVE_SHMIMAGE
354 #ifdef MOZ_ENABLE_QTMOBILITY
356 gOrientation
->removeFilter(&gOrientationFilter
);
357 gOrientation
->stop();
359 gOrientation
= nullptr;
364 /** Need to clean our LayerManager up while still alive */
366 nsRefPtr
<GLContext
> gl
= nullptr;
367 if (mLayerManager
->GetBackendType() == mozilla::layers::LAYERS_OPENGL
) {
368 LayerManagerOGL
*ogllm
= static_cast<LayerManagerOGL
*>(mLayerManager
.get());
372 mLayerManager
->Destroy();
378 mLayerManager
= nullptr;
380 // It is safe to call DestroyeCompositor several times (here and
381 // in the parent class) since it will take effect only once.
382 // The reason we call it here is because on gtk platforms we need
383 // to destroy the compositor before we destroy the gdk window (which
384 // destroys the the gl context attached to it).
387 ClearCachedResources();
389 nsIRollupListener
* rollupListener
= nsBaseWidget::GetActiveRollupListener();
390 if (rollupListener
) {
391 nsCOMPtr
<nsIWidget
> rollupWidget
= rollupListener
->GetRollupWidget();
392 if (static_cast<nsIWidget
*>(this) == rollupWidget
) {
393 rollupListener
->Rollup(0, nullptr);
399 // walk the list of children and call destroy on them. Have to be
400 // careful, though -- calling destroy on a kid may actually remove
401 // it from our child list, losing its sibling links.
402 for (nsIWidget
* kid
= mFirstChild
; kid
; ) {
403 nsIWidget
* next
= kid
->GetNextSibling();
408 // Destroy thebes surface now. Badness can happen if we destroy
409 // the surface after its X Window.
410 mThebesSurface
= nullptr;
412 QWidget
*view
= nullptr;
413 QGraphicsScene
*scene
= nullptr;
416 view
= GetViewWidget();
417 scene
= mWidget
->scene();
420 mWidget
->dropReceiver();
422 // Call deleteLater instead of delete; Qt still needs the object
423 // to be valid even after sending it a Close event. We could
424 // also set WA_DeleteOnClose, but this gives us more control.
425 mWidget
->deleteLater();
431 // tear down some infrastructure after all event handling is finished
439 nsWindow::ClearCachedResources()
442 mLayerManager
->GetBackendType() == mozilla::layers::LAYERS_BASIC
) {
443 statimLayerManager
->ClearCachedResources();
445 for (nsIWidget
* kid
= mFirstChild
; kid
; ) {
446 nsIWidget
* next
= kid
->GetNextSibling();
447 static_cast<nsWindow
*>(kid
)->ClearCachedResources();
453 nsWindow::SetParent(nsIWidget
*aNewParent
)
455 NS_ENSURE_ARG_POINTER(aNewParent
);
456 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
457 nsIWidget
* parent
= GetParent();
459 parent
->RemoveChild(this);
461 ReparentNativeWidget(aNewParent
);
462 aNewParent
->AddChild(this);
467 nsWindow::ReparentNativeWidget(nsIWidget
*aNewParent
)
469 NS_PRECONDITION(aNewParent
, "");
471 MozQWidget
* newParent
= static_cast<MozQWidget
*>(aNewParent
->GetNativeData(NS_NATIVE_WINDOW
));
472 NS_ASSERTION(newParent
, "Parent widget has a null native window handle");
474 mWidget
->setParentItem(newParent
);
480 nsWindow::SetModal(bool aModal
)
482 LOG(("nsWindow::SetModal [%p] %d, widget[%p]\n", (void *)this, aModal
, mWidget
));
484 mWidget
->setModal(aModal
);
490 nsWindow::IsVisible() const
496 nsWindow::ConstrainPosition(bool aAllowSlop
, int32_t *aX
, int32_t *aY
)
499 int32_t screenWidth
= QApplication::desktop()->width();
500 int32_t screenHeight
= QApplication::desktop()->height();
503 if (*aX
< (kWindowPositionSlop
- mBounds
.width
))
504 *aX
= kWindowPositionSlop
- mBounds
.width
;
505 if (*aX
> (screenWidth
- kWindowPositionSlop
))
506 *aX
= screenWidth
- kWindowPositionSlop
;
507 if (*aY
< (kWindowPositionSlop
- mBounds
.height
))
508 *aY
= kWindowPositionSlop
- mBounds
.height
;
509 if (*aY
> (screenHeight
- kWindowPositionSlop
))
510 *aY
= screenHeight
- kWindowPositionSlop
;
514 if (*aX
> (screenWidth
- mBounds
.width
))
515 *aX
= screenWidth
- mBounds
.width
;
518 if (*aY
> (screenHeight
- mBounds
.height
))
519 *aY
= screenHeight
- mBounds
.height
;
527 nsWindow::Move(double aX
, double aY
)
529 LOG(("nsWindow::Move [%p] %f %f\n", (void *)this,
532 int32_t x
= NSToIntRound(aX
);
533 int32_t y
= NSToIntRound(aY
);
536 SetSizeMode(nsSizeMode_Normal
);
539 if (x
== mBounds
.x
&& y
== mBounds
.y
)
547 QWidget
*widget
= GetViewWidget();
548 NS_ENSURE_TRUE(widget
, NS_OK
);
552 // the position of the widget is set relative to the parent
553 // so we map the coordinates accordingly
554 pos
= mWidget
->mapFromScene(pos
);
555 pos
= mWidget
->mapToParent(pos
);
556 mWidget
->setPos(pos
);
562 NotifyRollupGeometryChange();
567 nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement
,
571 return NS_ERROR_NOT_IMPLEMENTED
;
575 nsWindow::SetSizeMode(int32_t aMode
)
579 LOG(("nsWindow::SetSizeMode [%p] %d\n", (void *)this, aMode
));
580 if (aMode
!= nsSizeMode_Minimized
) {
581 GetViewWidget()->activateWindow();
584 // Save the requested state.
585 rv
= nsBaseWidget::SetSizeMode(aMode
);
587 // return if there's no shell or our current state is the same as
588 // the mode we were just set to.
589 if (!mWidget
|| mSizeState
== mSizeMode
) {
593 QWidget
*widget
= GetViewWidget();
594 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
597 case nsSizeMode_Maximized
:
598 widget
->showMaximized();
600 case nsSizeMode_Minimized
:
601 widget
->showMinimized();
603 case nsSizeMode_Fullscreen
:
604 widget
->showFullScreen();
608 // nsSizeMode_Normal, really.
609 widget
->showNormal();
613 mSizeState
= mSizeMode
;
618 // Helper function to recursively find the first parent item that
619 // is still visible (QGraphicsItem can be hidden even if they are
620 // set to visible if one of their ancestors is invisible)
621 static void find_first_visible_parent(QGraphicsItem
* aItem
, QGraphicsItem
*& aVisibleItem
)
623 NS_ENSURE_TRUE_VOID(aItem
);
625 aVisibleItem
= nullptr;
626 QGraphicsItem
* parItem
= nullptr;
627 while (!aVisibleItem
) {
628 if (aItem
->isVisible())
629 aVisibleItem
= aItem
;
631 parItem
= aItem
->parentItem();
635 aItem
->setVisible(true);
636 aVisibleItem
= aItem
;
643 nsWindow::SetFocus(bool aRaise
)
645 // Make sure that our owning widget has focus. If it doesn't try to
646 // grab it. Note that we don't set our focus flag in this case.
647 LOGFOCUS((" SetFocus [%p]\n", (void *)this));
650 return NS_ERROR_FAILURE
;
652 if (mWidget
->hasFocus())
655 // Because QGraphicsItem cannot get the focus if they are
656 // invisible, we look up the chain, for the lowest visible
657 // parent and focus that one
658 QGraphicsItem
* realFocusItem
= nullptr;
659 find_first_visible_parent(mWidget
, realFocusItem
);
661 if (!realFocusItem
|| realFocusItem
->hasFocus())
665 // the raising has to happen on the view widget
666 QWidget
*widget
= GetViewWidget();
669 realFocusItem
->setFocus(Qt::ActiveWindowFocusReason
);
672 realFocusItem
->setFocus(Qt::OtherFocusReason
);
674 // XXXndeakin why is this here? It should dispatch only when the OS
676 DispatchActivateEvent();
682 nsWindow::GetScreenBounds(nsIntRect
&aRect
)
684 aRect
= nsIntRect(nsIntPoint(0, 0), mBounds
.Size());
686 QWidget
*widget
= GetViewWidget();
687 NS_ENSURE_TRUE(widget
, NS_OK
);
688 QPoint pos
= widget
->pos();
689 aRect
.MoveTo(pos
.x(), pos
.y());
692 aRect
.MoveTo(WidgetToScreenOffset());
694 LOG(("GetScreenBounds %d %d | %d %d | %d %d\n",
696 mBounds
.width
, mBounds
.height
,
697 aRect
.width
, aRect
.height
));
702 nsWindow::SetForegroundColor(const nscolor
&aColor
)
704 return NS_ERROR_NOT_IMPLEMENTED
;
708 nsWindow::SetBackgroundColor(const nscolor
&aColor
)
710 return NS_ERROR_NOT_IMPLEMENTED
;
714 nsWindow::SetCursor(nsCursor aCursor
)
716 if (mCursor
== aCursor
)
721 mWidget
->SetCursor(mCursor
);
726 nsWindow::SetCursor(imgIContainer
* aCursor
,
727 uint32_t aHotspotX
, uint32_t aHotspotY
)
729 return NS_ERROR_NOT_AVAILABLE
;
733 nsWindow::Invalidate(const nsIntRect
&aRect
)
735 LOGDRAW(("Invalidate (rect) [%p,%p]: %d %d %d %d\n", (void *)this,
736 (void*)mWidget
,aRect
.x
, aRect
.y
, aRect
.width
, aRect
.height
));
741 mDirtyScrollArea
= mDirtyScrollArea
.united(QRect(aRect
.x
, aRect
.y
, aRect
.width
, aRect
.height
));
743 mWidget
->update(aRect
.x
, aRect
.y
, aRect
.width
, aRect
.height
);
748 // Returns the graphics view widget for this nsWindow by iterating
749 // the chain of parents until a toplevel window with a view/scene is found.
750 // (This function always returns something or asserts if the precondition
752 QWidget
* nsWindow::GetViewWidget()
754 NS_ASSERTION(mWidget
, "Calling GetViewWidget without mWidget created");
755 if (!mWidget
|| !mWidget
->scene() || !mWidget
->scene()->views().size())
758 NS_ASSERTION(mWidget
->scene()->views().size() == 1, "Not exactly one view for our scene!");
759 return mWidget
->scene()->views()[0];
763 nsWindow::GetNativeData(uint32_t aDataType
)
766 case NS_NATIVE_WINDOW
:
767 case NS_NATIVE_WIDGET
: {
775 case NS_NATIVE_PLUGIN_PORT
:
776 return SetupPluginPort();
779 case NS_NATIVE_DISPLAY
:
782 return gfxQtPlatform::GetXDisplay(GetViewWidget());
789 case NS_NATIVE_GRAPHIC
: {
794 case NS_NATIVE_SHELLWIDGET
: {
795 QWidget
* widget
= nullptr;
796 if (mWidget
&& mWidget
->scene())
797 widget
= mWidget
->scene()->views()[0]->viewport();
798 return (void *) widget
;
801 case NS_NATIVE_SHAREABLE_WINDOW
: {
802 QWidget
*widget
= GetViewWidget();
803 return widget
? (void*)widget
->winId() : nullptr;
807 NS_WARNING("nsWindow::GetNativeData called with bad value");
813 nsWindow::SetTitle(const nsAString
& aTitle
)
815 QString
qStr(QString::fromUtf16(aTitle
.BeginReading(), aTitle
.Length()));
817 QWidget
*widget
= GetViewWidget();
819 widget
->setWindowTitle(qStr
);
822 mWidget
->setWindowTitle(qStr
);
828 nsWindow::SetIcon(const nsAString
& aIconSpec
)
833 nsCOMPtr
<nsIFile
> iconFile
;
835 nsTArray
<nsCString
> iconList
;
837 // Look for icons with the following suffixes appended to the base name.
838 // The last two entries (for the old XPM format) will be ignored unless
839 // no icons are found using the other suffixes. XPM icons are depricated.
841 const char extensions
[6][7] = { ".png", "16.png", "32.png", "48.png",
844 for (uint32_t i
= 0; i
< ArrayLength(extensions
); i
++) {
845 // Don't bother looking for XPM versions if we found a PNG.
846 if (i
== ArrayLength(extensions
) - 2 && iconList
.Length())
849 nsAutoString extension
;
850 extension
.AppendASCII(extensions
[i
]);
852 ResolveIconName(aIconSpec
, extension
, getter_AddRefs(iconFile
));
854 iconFile
->GetNativePath(path
);
855 iconList
.AppendElement(path
);
859 // leave the default icon intact if no matching icons were found
860 if (iconList
.Length() == 0)
863 return SetWindowIconList(iconList
);
867 nsWindow::WidgetToScreenOffset()
869 NS_ENSURE_TRUE(mWidget
, nsIntPoint(0,0));
871 QPointF
origin(0, 0);
872 origin
= mWidget
->mapToScene(origin
);
874 return nsIntPoint(origin
.x(), origin
.y());
878 nsWindow::EnableDragDrop(bool aEnable
)
880 mWidget
->setAcceptDrops(aEnable
);
885 nsWindow::CaptureMouse(bool aCapture
)
887 LOG(("CaptureMouse %p\n", (void *)this));
892 QWidget
*widget
= GetViewWidget();
893 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
898 widget
->releaseMouse();
904 nsWindow::CaptureRollupEvents(nsIRollupListener
*aListener
,
910 LOG(("CaptureRollupEvents %p\n", (void *)this));
912 gRollupListener
= aDoCapture
? aListener
: nullptr;
917 nsWindow::CheckForRollup(double aMouseX
, double aMouseY
,
920 nsIRollupListener
* rollupListener
= GetActiveRollupListener();
921 nsCOMPtr
<nsIWidget
> rollupWidget
;
922 if (rollupListener
) {
923 rollupWidget
= rollupListener
->GetRollupWidget();
926 nsBaseWidget::gRollupListener
= nullptr;
931 MozQWidget
*currentPopup
=
932 (MozQWidget
*)rollupWidget
->GetNativeData(NS_NATIVE_WINDOW
);
933 if (!is_mouse_in_window(currentPopup
, aMouseX
, aMouseY
)) {
936 rollup
= rollupListener
->ShouldRollupOnMouseWheelEvent();
939 // if we're dealing with menus, we probably have submenus and
940 // we don't want to rollup if the clickis in a parent menu of
941 // the current submenu
942 uint32_t popupsToRollup
= UINT32_MAX
;
943 if (rollupListener
) {
944 nsAutoTArray
<nsIWidget
*, 5> widgetChain
;
945 uint32_t sameTypeCount
= rollupListener
->GetSubmenuWidgetChain(&widgetChain
);
946 for (uint32_t i
=0; i
<widgetChain
.Length(); ++i
) {
947 nsIWidget
* widget
= widgetChain
[i
];
948 MozQWidget
* currWindow
=
949 (MozQWidget
*) widget
->GetNativeData(NS_NATIVE_WINDOW
);
950 if (is_mouse_in_window(currWindow
, aMouseX
, aMouseY
)) {
951 if (i
< sameTypeCount
) {
955 popupsToRollup
= sameTypeCount
;
959 } // foreach parent menu widget
960 } // if rollup listener knows about menus
962 // if we've determined that we should still rollup, do it.
964 retVal
= rollupListener
->Rollup(popupsToRollup
, nullptr);
973 is_mouse_in_window (MozQWidget
* aWindow
, double aMouseX
, double aMouseY
)
975 return aWindow
->geometry().contains( aMouseX
, aMouseY
);
979 nsWindow::GetAttention(int32_t aCycleCount
)
981 LOG(("nsWindow::GetAttention [%p]\n", (void *)this));
982 return NS_ERROR_NOT_IMPLEMENTED
;
986 static already_AddRefed
<gfxASurface
>
987 GetSurfaceForQWidget(QWidget
* aDrawable
)
989 nsRefPtr
<gfxASurface
> result
=
990 new gfxXlibSurface(gfxQtPlatform::GetXDisplay(aDrawable
),
992 DefaultVisualOfScreen(gfxQtPlatform::GetXScreen(aDrawable
)),
993 gfxIntSize(aDrawable
->size().width(),
994 aDrawable
->size().height()));
995 return result
.forget();
1000 nsWindow::DoPaint(QPainter
* aPainter
, const QStyleOptionGraphicsItem
* aOption
, QWidget
* aWidget
)
1003 LOG(("Expose event on destroyed window [%p] window %p\n",
1004 (void *)this, mWidget
));
1008 // Call WillPaintWindow to allow scripts etc. to run before we paint
1010 if (mWidgetListener
)
1011 mWidgetListener
->WillPaintWindow(this);
1019 r
= aOption
->exposedRect
;
1021 r
= mWidget
->boundingRect();
1024 return nsEventStatus_eIgnore
;
1026 if (!mDirtyScrollArea
.isEmpty())
1027 mDirtyScrollArea
= QRegion();
1029 bool painted
= false;
1030 nsIntRect
rect(r
.x(), r
.y(), r
.width(), r
.height());
1032 nsFastStartup
* startup
= nsFastStartup::GetSingleton();
1034 startup
->RemoveFakeLayout();
1037 if (GetLayerManager(nullptr)->GetBackendType() == mozilla::layers::LAYERS_OPENGL
) {
1038 aPainter
->beginNativePainting();
1039 nsIntRegion
region(rect
);
1040 static_cast<mozilla::layers::LayerManagerOGL
*>(GetLayerManager(nullptr))->
1041 SetClippingRegion(region
);
1044 matr
.Translate(gfxPoint(aPainter
->transform().dx(), aPainter
->transform().dy()));
1045 #ifdef MOZ_ENABLE_QTMOBILITY
1046 // This is needed for rotate transformation on MeeGo
1047 // This will work very slow if pixman does not handle rotation very well
1048 matr
.Rotate((M_PI
/180) * gOrientationFilter
.GetWindowRotationAngle());
1049 static_cast<mozilla::layers::LayerManagerOGL
*>(GetLayerManager(nullptr))->
1050 SetWorldTransform(matr
);
1051 #endif //MOZ_ENABLE_QTMOBILITY
1053 if (mWidgetListener
)
1054 painted
= mWidgetListener
->PaintWindow(this, region
);
1055 aPainter
->endNativePainting();
1056 if (mWidgetListener
)
1057 mWidgetListener
->DidPaintWindow();
1061 gfxQtPlatform::RenderMode renderMode
= gfxQtPlatform::GetPlatform()->GetRenderMode();
1062 int depth
= aPainter
->device()->depth();
1064 nsRefPtr
<gfxASurface
> targetSurface
= nullptr;
1065 if (renderMode
== gfxQtPlatform::RENDER_BUFFERED
) {
1066 // Prepare offscreen buffers iamge or xlib, depends from paintEngineType
1067 if (!UpdateOffScreenBuffers(depth
, QSize(r
.width(), r
.height())))
1070 targetSurface
= gBufferSurface
;
1072 #ifdef CAIRO_HAS_QT_SURFACE
1073 } else if (renderMode
== gfxQtPlatform::RENDER_QPAINTER
) {
1074 targetSurface
= new gfxQPainterSurface(aPainter
);
1076 } else if (renderMode
== gfxQtPlatform::RENDER_DIRECT
) {
1077 if (!UpdateOffScreenBuffers(depth
, aWidget
->size(), aWidget
)) {
1080 targetSurface
= gBufferSurface
;
1083 if (MOZ_UNLIKELY(!targetSurface
))
1086 nsRefPtr
<gfxContext
> ctx
= new gfxContext(targetSurface
);
1088 // We will paint to 0, 0 position in offscrenn buffer
1089 if (renderMode
== gfxQtPlatform::RENDER_BUFFERED
) {
1090 ctx
->Translate(gfxPoint(-r
.x(), -r
.y()));
1092 else if (renderMode
== gfxQtPlatform::RENDER_DIRECT
) {
1094 matr
.Translate(gfxPoint(aPainter
->transform().dx(), aPainter
->transform().dy()));
1095 #ifdef MOZ_ENABLE_QTMOBILITY
1096 // This is needed for rotate transformation on MeeGo
1097 // This will work very slow if pixman does not handle rotation very well
1098 matr
.Rotate((M_PI
/180) * gOrientationFilter
.GetWindowRotationAngle());
1099 NS_ASSERTION(PIXMAN_VERSION
> PIXMAN_VERSION_ENCODE(0, 21, 2) ||
1100 !gOrientationFilter
.GetWindowRotationAngle(),
1101 "Old pixman and rotate transform, it is going to be slow");
1102 #endif //MOZ_ENABLE_QTMOBILITY
1104 ctx
->SetMatrix(matr
);
1108 AutoLayerManagerSetup
1109 setupLayerManager(this, ctx
, mozilla::layers::BUFFER_NONE
);
1110 if (mWidgetListener
) {
1111 nsIntRegion
region(rect
);
1112 painted
= mWidgetListener
->PaintWindow(this, region
);
1116 // DispatchEvent can Destroy us (bug 378273), avoid doing any paint
1117 // operations below if that happened - it will lead to XError and exit().
1118 if (MOZ_UNLIKELY(mIsDestroyed
))
1124 LOGDRAW(("[%p] draw done\n", this));
1126 // Handle buffered painting mode
1127 if (renderMode
== gfxQtPlatform::RENDER_BUFFERED
) {
1128 #if defined(MOZ_X11) && defined(Q_WS_X11)
1129 if (gBufferSurface
->GetType() == gfxASurface::SurfaceTypeXlib
) {
1130 // Paint offscreen pixmap to QPainter
1131 static QPixmap gBufferPixmap
;
1132 Drawable draw
= static_cast<gfxXlibSurface
*>(gBufferSurface
.get())->XDrawable();
1133 if (gBufferPixmap
.handle() != draw
)
1134 gBufferPixmap
= QPixmap::fromX11Pixmap(draw
, QPixmap::ExplicitlyShared
);
1135 XSync(static_cast<gfxXlibSurface
*>(gBufferSurface
.get())->XDisplay(), False
);
1136 aPainter
->drawPixmap(QPoint(rect
.x
, rect
.y
), gBufferPixmap
,
1137 QRect(0, 0, rect
.width
, rect
.height
));
1141 if (gBufferSurface
->GetType() == gfxASurface::SurfaceTypeImage
) {
1142 // in raster mode we can just wrap gBufferImage as QImage and paint directly
1143 gfxImageSurface
*imgs
= static_cast<gfxImageSurface
*>(gBufferSurface
.get());
1144 QImage
img(imgs
->Data(),
1148 _gfximage_to_qformat(imgs
->Format()));
1149 aPainter
->drawImage(QPoint(rect
.x
, rect
.y
), img
,
1150 QRect(0, 0, rect
.width
, rect
.height
));
1152 } else if (renderMode
== gfxQtPlatform::RENDER_DIRECT
) {
1153 QRect trans
= aPainter
->transform().mapRect(r
).toRect();
1155 if (gBufferSurface
->GetType() == gfxASurface::SurfaceTypeXlib
) {
1156 nsRefPtr
<gfxASurface
> widgetSurface
= GetSurfaceForQWidget(aWidget
);
1157 nsRefPtr
<gfxContext
> ctx
= new gfxContext(widgetSurface
);
1158 ctx
->SetSource(gBufferSurface
);
1159 ctx
->Rectangle(gfxRect(trans
.x(), trans
.y(), trans
.width(), trans
.height()), true);
1164 if (gBufferSurface
->GetType() == gfxASurface::SurfaceTypeImage
) {
1165 #ifdef MOZ_HAVE_SHMIMAGE
1167 gShmImage
->Put(aWidget
, trans
);
1171 // Qt should take care about optimized rendering on QImage into painter device (gl/fb/image et.c.)
1172 gfxImageSurface
*imgs
= static_cast<gfxImageSurface
*>(gBufferSurface
.get());
1173 QImage
img(imgs
->Data(),
1177 _gfximage_to_qformat(imgs
->Format()));
1178 aPainter
->drawImage(trans
, img
, trans
);
1184 targetSurface
= nullptr;
1185 if (mWidgetListener
)
1186 mWidgetListener
->DidPaintWindow();
1188 // check the return value!
1193 nsWindow::OnMoveEvent(QGraphicsSceneHoverEvent
*aEvent
)
1195 LOG(("configure event [%p] %d %d\n", (void *)this,
1196 aEvent
->pos().x(), aEvent
->pos().y()));
1199 if (!mWidget
|| !mWidgetListener
)
1200 return nsEventStatus_eIgnore
;
1202 if ((mBounds
.x
== aEvent
->pos().x() &&
1203 mBounds
.y
== aEvent
->pos().y()))
1205 return nsEventStatus_eIgnore
;
1208 bool moved
= mWidgetListener
->WindowMoved(this, aEvent
->pos().x(), aEvent
->pos().y());
1209 return moved
? nsEventStatus_eConsumeNoDefault
: nsEventStatus_eIgnore
;
1213 nsWindow::OnResizeEvent(QGraphicsSceneResizeEvent
*aEvent
)
1217 // Generate XPFE resize event
1220 rect
.width
= aEvent
->newSize().width();
1221 rect
.height
= aEvent
->newSize().height();
1223 mBounds
.width
= rect
.width
;
1224 mBounds
.height
= rect
.height
;
1226 nsEventStatus status
;
1227 DispatchResizeEvent(rect
, status
);
1232 nsWindow::OnCloseEvent(QCloseEvent
*aEvent
)
1234 if (!mWidgetListener
)
1235 return nsEventStatus_eIgnore
;
1236 mWidgetListener
->RequestWindowClose(this);
1237 return nsEventStatus_eConsumeNoDefault
;
1241 nsWindow::OnEnterNotifyEvent(QGraphicsSceneHoverEvent
*aEvent
)
1243 nsMouseEvent
event(true, NS_MOUSE_ENTER
, this, nsMouseEvent::eReal
);
1245 event
.refPoint
.x
= nscoord(aEvent
->pos().x());
1246 event
.refPoint
.y
= nscoord(aEvent
->pos().y());
1248 LOG(("OnEnterNotify: %p\n", (void *)this));
1250 return DispatchEvent(&event
);
1254 nsWindow::OnLeaveNotifyEvent(QGraphicsSceneHoverEvent
*aEvent
)
1256 nsMouseEvent
event(true, NS_MOUSE_EXIT
, this, nsMouseEvent::eReal
);
1258 event
.refPoint
.x
= nscoord(aEvent
->pos().x());
1259 event
.refPoint
.y
= nscoord(aEvent
->pos().y());
1261 LOG(("OnLeaveNotify: %p\n", (void *)this));
1263 return DispatchEvent(&event
);
1266 // Block the mouse events if user was recently executing gestures;
1267 // otherwise there will be also some panning during/after gesture
1268 #if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 0))
1269 #define CHECK_MOUSE_BLOCKED { \
1270 if (mLastMultiTouchTime.isValid()) { \
1271 if (mLastMultiTouchTime.elapsed() < GESTURES_BLOCK_MOUSE_FOR) \
1272 return nsEventStatus_eIgnore; \
1274 mLastMultiTouchTime = QTime(); \
1278 define CHECK_MOUSE_BLOCKED
{}
1282 nsWindow::OnMotionNotifyEvent(QPointF aPos
, Qt::KeyboardModifiers aModifiers
)
1288 mMoveEvent
.pos
= aPos
;
1289 mMoveEvent
.modifiers
= aModifiers
;
1290 mMoveEvent
.needDispatch
= true;
1291 DispatchMotionToMainThread();
1293 return nsEventStatus_eIgnore
;
1297 nsWindow::InitButtonEvent(nsMouseEvent
&aMoveEvent
,
1298 QGraphicsSceneMouseEvent
*aEvent
, int aClickCount
)
1300 aMoveEvent
.refPoint
.x
= nscoord(aEvent
->pos().x());
1301 aMoveEvent
.refPoint
.y
= nscoord(aEvent
->pos().y());
1303 aMoveEvent
.InitBasicModifiers(aEvent
->modifiers() & Qt::ControlModifier
,
1304 aEvent
->modifiers() & Qt::AltModifier
,
1305 aEvent
->modifiers() & Qt::ShiftModifier
,
1306 aEvent
->modifiers() & Qt::MetaModifier
);
1307 aMoveEvent
.clickCount
= aClickCount
;
1311 nsWindow::OnButtonPressEvent(QGraphicsSceneMouseEvent
*aEvent
)
1313 // The user has done something.
1318 QPointF pos
= aEvent
->pos();
1320 // we check against the widgets geometry, so use parent coordinates
1323 pos
= mWidget
->mapToParent(pos
);
1325 if (CheckForRollup( pos
.x(), pos
.y(), false))
1326 return nsEventStatus_eIgnore
;
1329 switch (aEvent
->button()) {
1331 domButton
= nsMouseEvent::eMiddleButton
;
1333 case Qt::RightButton
:
1334 domButton
= nsMouseEvent::eRightButton
;
1337 domButton
= nsMouseEvent::eLeftButton
;
1341 nsMouseEvent
event(true, NS_MOUSE_BUTTON_DOWN
, this, nsMouseEvent::eReal
);
1342 event
.button
= domButton
;
1343 InitButtonEvent(event
, aEvent
, 1);
1345 LOG(("%s [%p] button: %d\n", __PRETTY_FUNCTION__
, (void*)this, domButton
));
1347 nsEventStatus status
= DispatchEvent(&event
);
1349 // right menu click on linux should also pop up a context menu
1350 if (domButton
== nsMouseEvent::eRightButton
&&
1351 MOZ_LIKELY(!mIsDestroyed
)) {
1352 nsMouseEvent
contextMenuEvent(true, NS_CONTEXTMENU
, this,
1353 nsMouseEvent::eReal
);
1354 InitButtonEvent(contextMenuEvent
, aEvent
, 1);
1355 DispatchEvent(&contextMenuEvent
, status
);
1362 nsWindow::OnButtonReleaseEvent(QGraphicsSceneMouseEvent
*aEvent
)
1367 // The user has done something.
1372 switch (aEvent
->button()) {
1374 domButton
= nsMouseEvent::eMiddleButton
;
1376 case Qt::RightButton
:
1377 domButton
= nsMouseEvent::eRightButton
;
1380 domButton
= nsMouseEvent::eLeftButton
;
1384 LOG(("%s [%p] button: %d\n", __PRETTY_FUNCTION__
, (void*)this, domButton
));
1386 nsMouseEvent
event(true, NS_MOUSE_BUTTON_UP
, this, nsMouseEvent::eReal
);
1387 event
.button
= domButton
;
1388 InitButtonEvent(event
, aEvent
, 1);
1390 nsEventStatus status
= DispatchEvent(&event
);
1396 nsWindow::OnMouseDoubleClickEvent(QGraphicsSceneMouseEvent
*aEvent
)
1400 switch (aEvent
->button()) {
1402 eventType
= nsMouseEvent::eMiddleButton
;
1404 case Qt::RightButton
:
1405 eventType
= nsMouseEvent::eRightButton
;
1408 eventType
= nsMouseEvent::eLeftButton
;
1412 nsMouseEvent
event(true, NS_MOUSE_DOUBLECLICK
, this, nsMouseEvent::eReal
);
1413 event
.button
= eventType
;
1415 InitButtonEvent(event
, aEvent
, 2);
1417 return DispatchEvent(&event
);
1421 nsWindow::OnFocusInEvent(QEvent
*aEvent
)
1423 LOGFOCUS(("OnFocusInEvent [%p]\n", (void *)this));
1426 return nsEventStatus_eIgnore
;
1428 DispatchActivateEventOnTopLevelWindow();
1430 LOGFOCUS(("Events sent from focus in event [%p]\n", (void *)this));
1431 return nsEventStatus_eIgnore
;
1435 nsWindow::OnFocusOutEvent(QEvent
*aEvent
)
1437 LOGFOCUS(("OnFocusOutEvent [%p]\n", (void *)this));
1440 return nsEventStatus_eIgnore
;
1442 DispatchDeactivateEventOnTopLevelWindow();
1444 LOGFOCUS(("Done with container focus out [%p]\n", (void *)this));
1445 return nsEventStatus_eIgnore
;
1449 is_latin_shortcut_key(quint32 aKeyval
)
1451 return ((Qt::Key_0
<= aKeyval
&& aKeyval
<= Qt::Key_9
) ||
1452 (Qt::Key_A
<= aKeyval
&& aKeyval
<= Qt::Key_Z
));
1456 nsWindow::DispatchCommandEvent(nsIAtom
* aCommand
)
1458 nsCommandEvent
event(true, nsGkAtoms::onAppCommand
, aCommand
, this);
1460 nsEventStatus status
;
1461 DispatchEvent(&event
, status
);
1467 nsWindow::DispatchContentCommandEvent(int32_t aMsg
)
1469 nsContentCommandEvent
event(true, aMsg
, this);
1471 nsEventStatus status
;
1472 DispatchEvent(&event
, status
);
1478 nsWindow::OnKeyPressEvent(QKeyEvent
*aEvent
)
1480 LOGFOCUS(("OnKeyPressEvent [%p]\n", (void *)this));
1482 // The user has done something.
1485 if (aEvent
->key() == Qt::Key_AltGr
) {
1486 sAltGrModifier
= true;
1490 // before we dispatch a key, check if it's the context menu key.
1491 // If so, send a context menu key event instead.
1492 if (isContextMenuKeyEvent(aEvent
)) {
1493 nsMouseEvent
contextMenuEvent(true, NS_CONTEXTMENU
, this,
1494 nsMouseEvent::eReal
,
1495 nsMouseEvent::eContextMenuKey
);
1496 //keyEventToContextMenuEvent(&event, &contextMenuEvent);
1497 return DispatchEvent(&contextMenuEvent
);
1500 uint32_t domCharCode
= 0;
1501 uint32_t domKeyCode
= QtKeyCodeToDOMKeyCode(aEvent
->key());
1503 // get keymap and modifier map from the Xserver
1504 Display
*display
= mozilla::DefaultXDisplay();
1505 int x_min_keycode
= 0, x_max_keycode
= 0, xkeysyms_per_keycode
;
1506 XDisplayKeycodes(display
, &x_min_keycode
, &x_max_keycode
);
1507 XModifierKeymap
*xmodmap
= XGetModifierMapping(display
);
1509 return nsEventStatus_eIgnore
;
1511 KeySym
*xkeymap
= XGetKeyboardMapping(display
, x_min_keycode
, x_max_keycode
- x_min_keycode
,
1512 &xkeysyms_per_keycode
);
1514 XFreeModifiermap(xmodmap
);
1515 return nsEventStatus_eIgnore
;
1518 // create modifier masks
1519 qint32 shift_mask
= 0, shift_lock_mask
= 0, caps_lock_mask
= 0, num_lock_mask
= 0;
1521 for (int i
= 0; i
< 8 * xmodmap
->max_keypermod
; ++i
) {
1522 qint32 maskbit
= 1 << (i
/ xmodmap
->max_keypermod
);
1523 KeyCode modkeycode
= xmodmap
->modifiermap
[i
];
1524 if (modkeycode
== NoSymbol
) {
1528 quint32 mapindex
= (modkeycode
- x_min_keycode
) * xkeysyms_per_keycode
;
1529 for (int j
= 0; j
< xkeysyms_per_keycode
; ++j
) {
1530 KeySym modkeysym
= xkeymap
[mapindex
+ j
];
1531 switch (modkeysym
) {
1533 num_lock_mask
|= maskbit
;
1536 caps_lock_mask
|= maskbit
;
1539 shift_lock_mask
|= maskbit
;
1543 shift_mask
|= maskbit
;
1548 // indicate whether is down or not
1549 bool shift_state
= ((shift_mask
& aEvent
->nativeModifiers()) != 0) ^
1550 (bool)(shift_lock_mask
& aEvent
->nativeModifiers());
1551 bool capslock_state
= (bool)(caps_lock_mask
& aEvent
->nativeModifiers());
1553 // try to find a keysym that we can translate to a DOMKeyCode
1554 // this is needed because some of Qt's keycodes cannot be translated
1555 // TODO: use US keyboard keymap instead of localised keymap
1557 aEvent
->nativeScanCode() >= (quint32
)x_min_keycode
&&
1558 aEvent
->nativeScanCode() <= (quint32
)x_max_keycode
) {
1559 int index
= (aEvent
->nativeScanCode() - x_min_keycode
) * xkeysyms_per_keycode
;
1560 for(int i
= 0; (i
< xkeysyms_per_keycode
) && (domKeyCode
== (quint32
)NoSymbol
); ++i
) {
1561 domKeyCode
= QtKeyCodeToDOMKeyCode(xkeymap
[index
+ i
]);
1565 // store character in domCharCode
1566 if (aEvent
->text().length() && aEvent
->text()[0].isPrint())
1567 domCharCode
= (int32_t) aEvent
->text()[0].unicode();
1569 KeyNameIndex keyNameIndex
=
1570 domCharCode
? KEY_NAME_INDEX_PrintableKey
:
1571 QtKeyCodeToDOMKeyNameIndex(aEvent
->key());
1573 // If the key isn't autorepeat, we need to send the initial down event
1574 if (!aEvent
->isAutoRepeat() && !IsKeyDown(domKeyCode
)) {
1575 // send the key down event
1577 SetKeyDownFlag(domKeyCode
);
1579 nsKeyEvent
downEvent(true, NS_KEY_DOWN
, this);
1580 InitKeyEvent(downEvent
, aEvent
);
1582 downEvent
.keyCode
= domKeyCode
;
1583 downEvent
.mKeyNameIndex
= keyNameIndex
;
1585 nsEventStatus status
= DispatchEvent(&downEvent
);
1587 // DispatchEvent can Destroy us (bug 378273)
1588 if (MOZ_UNLIKELY(mIsDestroyed
)) {
1589 qWarning() << "Returning[" << __LINE__
<< "]: " << "Window destroyed";
1593 // If prevent default on keydown, don't dispatch keypress event
1594 if (status
== nsEventStatus_eConsumeNoDefault
) {
1595 return nsEventStatus_eConsumeNoDefault
;
1599 // Don't pass modifiers as NS_KEY_PRESS events.
1600 // Instead of selectively excluding some keys from NS_KEY_PRESS events,
1601 // we instead selectively include (as per MSDN spec
1602 // ( http://msdn.microsoft.com/en-us/library/system.windows.forms.control.keypress%28VS.71%29.aspx );
1603 // no official spec covers KeyPress events).
1604 if (aEvent
->key() == Qt::Key_Shift
||
1605 aEvent
->key() == Qt::Key_Control
||
1606 aEvent
->key() == Qt::Key_Meta
||
1607 aEvent
->key() == Qt::Key_Alt
||
1608 aEvent
->key() == Qt::Key_AltGr
) {
1610 return nsEventStatus_eIgnore
;
1613 // Look for specialized app-command keys
1614 switch (aEvent
->key()) {
1616 return DispatchCommandEvent(nsGkAtoms::Back
);
1617 case Qt::Key_Forward
:
1618 return DispatchCommandEvent(nsGkAtoms::Forward
);
1619 case Qt::Key_Refresh
:
1620 return DispatchCommandEvent(nsGkAtoms::Reload
);
1622 return DispatchCommandEvent(nsGkAtoms::Stop
);
1623 case Qt::Key_Search
:
1624 return DispatchCommandEvent(nsGkAtoms::Search
);
1625 case Qt::Key_Favorites
:
1626 return DispatchCommandEvent(nsGkAtoms::Bookmarks
);
1627 case Qt::Key_HomePage
:
1628 return DispatchCommandEvent(nsGkAtoms::Home
);
1630 case Qt::Key_F16
: // F16, F20, F18, F14 are old keysyms for Copy Cut Paste Undo
1631 return DispatchContentCommandEvent(NS_CONTENT_COMMAND_COPY
);
1634 return DispatchContentCommandEvent(NS_CONTENT_COMMAND_CUT
);
1638 return DispatchContentCommandEvent(NS_CONTENT_COMMAND_PASTE
);
1640 return DispatchContentCommandEvent(NS_CONTENT_COMMAND_UNDO
);
1643 // Qt::Key_Redo and Qt::Key_Undo are not available yet.
1644 if (aEvent
->nativeVirtualKey() == 0xff66) {
1645 return DispatchContentCommandEvent(NS_CONTENT_COMMAND_REDO
);
1647 if (aEvent
->nativeVirtualKey() == 0xff65) {
1648 return DispatchContentCommandEvent(NS_CONTENT_COMMAND_UNDO
);
1651 nsKeyEvent
event(true, NS_KEY_PRESS
, this);
1652 InitKeyEvent(event
, aEvent
);
1654 // If there is no charcode attainable from the text, try to
1655 // generate it from the keycode. Check shift state for case
1656 // Also replace the charcode if ControlModifier is the only
1658 if ((!domCharCode
) &&
1659 (QApplication::keyboardModifiers() &
1660 (Qt::ControlModifier
| Qt::AltModifier
| Qt::MetaModifier
))) {
1662 // get a character from X11 key map
1663 KeySym keysym
= aEvent
->nativeVirtualKey();
1665 domCharCode
= (uint32_t) keysym2ucs(keysym
);
1666 if (domCharCode
== -1 || !QChar((quint32
)domCharCode
).isPrint()) {
1671 // if Ctrl is pressed and domCharCode is not a ASCII character
1672 if (domCharCode
> 0xFF && (QApplication::keyboardModifiers() & Qt::ControlModifier
)) {
1673 // replace Unicode character
1674 int index
= (aEvent
->nativeScanCode() - x_min_keycode
) * xkeysyms_per_keycode
;
1675 for (int i
= 0; i
< xkeysyms_per_keycode
; ++i
) {
1676 if (xkeymap
[index
+ i
] <= 0xFF && !shift_state
) {
1677 domCharCode
= (uint32_t) QChar::toLower((uint
) xkeymap
[index
+ i
]);
1683 } else { // The key event should cause a character input.
1684 // At that time, we need to reset the modifiers
1685 // because nsEditor will not accept a key event
1686 // for text input if one or more modifiers are set.
1687 event
.modifiers
&= ~(widget::MODIFIER_CONTROL
|
1688 widget::MODIFIER_ALT
|
1689 widget::MODIFIER_META
);
1692 KeySym keysym
= NoSymbol
;
1693 int index
= (aEvent
->nativeScanCode() - x_min_keycode
) * xkeysyms_per_keycode
;
1694 for (int i
= 0; i
< xkeysyms_per_keycode
; ++i
) {
1695 if (xkeymap
[index
+ i
] == aEvent
->nativeVirtualKey()) {
1696 if ((i
% 2) == 0) { // shifted char
1697 keysym
= xkeymap
[index
+ i
+ 1];
1699 } else { // unshifted char
1700 keysym
= xkeymap
[index
+ i
- 1];
1704 if (xkeysyms_per_keycode
- 1 == i
) {
1705 qWarning() << "Symbol '" << aEvent
->nativeVirtualKey() << "' not found";
1708 QChar
unshiftedChar(domCharCode
);
1709 long ucs
= keysym2ucs(keysym
);
1710 ucs
= ucs
== -1 ? 0 : ucs
;
1711 QChar
shiftedChar((uint
)ucs
);
1713 // append alternativeCharCodes if modifier is pressed
1714 // append an additional alternativeCharCodes if domCharCode is not a Latin character
1715 // and if one of these modifiers is pressed (i.e. Ctrl, Alt, Meta)
1717 (QApplication::keyboardModifiers() &
1718 (Qt::ControlModifier
| Qt::AltModifier
| Qt::MetaModifier
))) {
1720 event
.charCode
= domCharCode
;
1722 nsAlternativeCharCode
altCharCode(0, 0);
1723 // if character has a lower and upper representation
1724 if ((unshiftedChar
.isUpper() || unshiftedChar
.isLower()) &&
1725 unshiftedChar
.toLower() == shiftedChar
.toLower()) {
1726 if (shift_state
^ capslock_state
) {
1727 altCharCode
.mUnshiftedCharCode
= (uint32_t) QChar::toUpper((uint
)domCharCode
);
1728 altCharCode
.mShiftedCharCode
= (uint32_t) QChar::toLower((uint
)domCharCode
);
1730 altCharCode
.mUnshiftedCharCode
= (uint32_t) QChar::toLower((uint
)domCharCode
);
1731 altCharCode
.mShiftedCharCode
= (uint32_t) QChar::toUpper((uint
)domCharCode
);
1734 altCharCode
.mUnshiftedCharCode
= (uint32_t) unshiftedChar
.unicode();
1735 altCharCode
.mShiftedCharCode
= (uint32_t) shiftedChar
.unicode();
1738 // append alternative char code to event
1739 if ((altCharCode
.mUnshiftedCharCode
&& altCharCode
.mUnshiftedCharCode
!= domCharCode
) ||
1740 (altCharCode
.mShiftedCharCode
&& altCharCode
.mShiftedCharCode
!= domCharCode
)) {
1741 event
.alternativeCharCodes
.AppendElement(altCharCode
);
1744 // check if the alternative char codes are latin-1
1745 if (altCharCode
.mUnshiftedCharCode
> 0xFF || altCharCode
.mShiftedCharCode
> 0xFF) {
1746 altCharCode
.mUnshiftedCharCode
= altCharCode
.mShiftedCharCode
= 0;
1748 // find latin char for keycode
1749 KeySym keysym
= NoSymbol
;
1750 int index
= (aEvent
->nativeScanCode() - x_min_keycode
) * xkeysyms_per_keycode
;
1751 // find first shifted and unshifted Latin-Char in XKeyMap
1752 for (int i
= 0; i
< xkeysyms_per_keycode
; ++i
) {
1753 keysym
= xkeymap
[index
+ i
];
1754 if (keysym
&& keysym
<= 0xFF) {
1755 if ((shift_state
&& (i
% 2 == 1)) ||
1756 (!shift_state
&& (i
% 2 == 0))) {
1757 altCharCode
.mUnshiftedCharCode
= altCharCode
.mUnshiftedCharCode
?
1758 altCharCode
.mUnshiftedCharCode
:
1761 altCharCode
.mShiftedCharCode
= altCharCode
.mShiftedCharCode
?
1762 altCharCode
.mShiftedCharCode
:
1765 if (altCharCode
.mUnshiftedCharCode
&& altCharCode
.mShiftedCharCode
) {
1771 if (altCharCode
.mUnshiftedCharCode
|| altCharCode
.mShiftedCharCode
) {
1772 event
.alternativeCharCodes
.AppendElement(altCharCode
);
1776 event
.charCode
= domCharCode
;
1780 XFreeModifiermap(xmodmap
);
1786 event
.keyCode
= domCharCode
? 0 : domKeyCode
;
1787 event
.mKeyNameIndex
= keyNameIndex
;
1788 // send the key press event
1789 return DispatchEvent(&event
);
1792 //:TODO: fix shortcuts hebrew for non X11,
1793 //see Bug 562195##51
1795 // before we dispatch a key, check if it's the context menu key.
1796 // If so, send a context menu key event instead.
1797 if (isContextMenuKeyEvent(aEvent
)) {
1798 nsMouseEvent
contextMenuEvent(true, NS_CONTEXTMENU
, this,
1799 nsMouseEvent::eReal
,
1800 nsMouseEvent::eContextMenuKey
);
1801 //keyEventToContextMenuEvent(&event, &contextMenuEvent);
1802 return DispatchEvent(&contextMenuEvent
);
1805 uint32_t domCharCode
= 0;
1806 uint32_t domKeyCode
= QtKeyCodeToDOMKeyCode(aEvent
->key());
1808 if (aEvent
->text().length() && aEvent
->text()[0].isPrint())
1809 domCharCode
= (int32_t) aEvent
->text()[0].unicode();
1811 KeyNameIndex keyNameIndex
=
1812 domCharCode
? KEY_NAME_INDEX_PrintableKey
:
1813 QtKeyCodeToDOMKeyNameIndex(aEvent
->key());
1815 // If the key isn't autorepeat, we need to send the initial down event
1816 if (!aEvent
->isAutoRepeat() && !IsKeyDown(domKeyCode
)) {
1817 // send the key down event
1819 SetKeyDownFlag(domKeyCode
);
1821 nsKeyEvent
downEvent(true, NS_KEY_DOWN
, this);
1822 InitKeyEvent(downEvent
, aEvent
);
1824 downEvent
.keyCode
= domKeyCode
;
1825 downEvent
.mKeyNameIndex
= keyNameIndex
;
1827 nsEventStatus status
= DispatchEvent(&downEvent
);
1829 // If prevent default on keydown, don't dispatch keypress event
1830 if (status
== nsEventStatus_eConsumeNoDefault
) {
1831 return nsEventStatus_eConsumeNoDefault
;
1835 nsKeyEvent
event(true, NS_KEY_PRESS
, this);
1836 InitKeyEvent(event
, aEvent
);
1838 event
.charCode
= domCharCode
;
1840 event
.keyCode
= domCharCode
? 0 : domKeyCode
;
1841 event
.mKeyNameIndex
= keyNameIndex
;
1843 // send the key press event
1844 return DispatchEvent(&event
);
1849 nsWindow::OnKeyReleaseEvent(QKeyEvent
*aEvent
)
1851 LOGFOCUS(("OnKeyReleaseEvent [%p]\n", (void *)this));
1853 // The user has done something.
1856 if (isContextMenuKeyEvent(aEvent
)) {
1857 // er, what do we do here? DoDefault or NoDefault?
1858 return nsEventStatus_eConsumeDoDefault
;
1861 uint32_t domKeyCode
= QtKeyCodeToDOMKeyCode(aEvent
->key());
1865 // get keymap from the Xserver
1866 Display
*display
= mozilla::DefaultXDisplay();
1867 int x_min_keycode
= 0, x_max_keycode
= 0, xkeysyms_per_keycode
;
1868 XDisplayKeycodes(display
, &x_min_keycode
, &x_max_keycode
);
1869 KeySym
*xkeymap
= XGetKeyboardMapping(display
, x_min_keycode
, x_max_keycode
- x_min_keycode
,
1870 &xkeysyms_per_keycode
);
1872 if (aEvent
->nativeScanCode() >= (quint32
)x_min_keycode
&&
1873 aEvent
->nativeScanCode() <= (quint32
)x_max_keycode
) {
1874 int index
= (aEvent
->nativeScanCode() - x_min_keycode
) * xkeysyms_per_keycode
;
1875 for(int i
= 0; (i
< xkeysyms_per_keycode
) && (domKeyCode
== (quint32
)NoSymbol
); ++i
) {
1876 domKeyCode
= QtKeyCodeToDOMKeyCode(xkeymap
[index
+ i
]);
1886 // send the key event as a key up event
1887 nsKeyEvent
event(true, NS_KEY_UP
, this);
1888 InitKeyEvent(event
, aEvent
);
1890 if (aEvent
->key() == Qt::Key_AltGr
) {
1891 sAltGrModifier
= false;
1894 event
.keyCode
= domKeyCode
;
1895 event
.mKeyNameIndex
=
1896 (aEvent
->text().length() && aEvent
->text()[0].isPrint()) ?
1897 KEY_NAME_INDEX_PrintableKey
:
1898 QtKeyCodeToDOMKeyNameIndex(aEvent
->key());
1900 // unset the key down flag
1901 ClearKeyDownFlag(event
.keyCode
);
1903 return DispatchEvent(&event
);
1907 nsWindow::OnScrollEvent(QGraphicsSceneWheelEvent
*aEvent
)
1909 // check to see if we should rollup
1910 WheelEvent
wheelEvent(true, NS_WHEEL_WHEEL
, this);
1911 wheelEvent
.deltaMode
= nsIDOMWheelEvent::DOM_DELTA_LINE
;
1913 // negative values for aEvent->delta indicate downward scrolling;
1914 // this is opposite Gecko usage.
1915 // TODO: Store the unused delta values due to fraction round and add it
1916 // to next event. The stored values should be reset by other
1917 // direction scroll event.
1918 int32_t delta
= (int)(aEvent
->delta() / WHEEL_DELTA
) * -3;
1920 switch (aEvent
->orientation()) {
1922 wheelEvent
.deltaY
= wheelEvent
.lineOrPageDeltaY
= delta
;
1924 case Qt::Horizontal
:
1925 wheelEvent
.deltaX
= wheelEvent
.lineOrPageDeltaX
= delta
;
1932 wheelEvent
.refPoint
.x
= nscoord(aEvent
->scenePos().x());
1933 wheelEvent
.refPoint
.y
= nscoord(aEvent
->scenePos().y());
1935 wheelEvent
.InitBasicModifiers(aEvent
->modifiers() & Qt::ControlModifier
,
1936 aEvent
->modifiers() & Qt::AltModifier
,
1937 aEvent
->modifiers() & Qt::ShiftModifier
,
1938 aEvent
->modifiers() & Qt::MetaModifier
);
1939 wheelEvent
.time
= 0;
1941 return DispatchEvent(&wheelEvent
);
1946 nsWindow::showEvent(QShowEvent
*)
1948 LOG(("%s [%p]\n", __PRETTY_FUNCTION__
,(void *)this));
1950 return nsEventStatus_eConsumeDoDefault
;
1954 nsWindow::hideEvent(QHideEvent
*)
1956 LOG(("%s [%p]\n", __PRETTY_FUNCTION__
,(void *)this));
1958 return nsEventStatus_eConsumeDoDefault
;
1961 //Gestures are only supported in 4.6.0 >
1962 #if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 0))
1963 nsEventStatus
nsWindow::OnTouchEvent(QTouchEvent
*event
, bool &handled
)
1966 const QList
<QTouchEvent::TouchPoint
> &touchPoints
= event
->touchPoints();
1968 if (event
->type() == QEvent::TouchBegin
) {
1970 for (int i
= touchPoints
.count() -1; i
>= 0; i
--) {
1971 QPointF fpos
= touchPoints
[i
].pos();
1972 nsGestureNotifyEvent
gestureNotifyEvent(true, NS_GESTURENOTIFY_EVENT_START
, this);
1973 gestureNotifyEvent
.refPoint
= LayoutDeviceIntPoint(fpos
.x(), fpos
.y());
1974 DispatchEvent(&gestureNotifyEvent
);
1977 else if (event
->type() == QEvent::TouchEnd
) {
1978 mGesturesCancelled
= false;
1979 mPinchEvent
.needDispatch
= false;
1982 if (touchPoints
.count() > 0) {
1983 // Remember start touch point in order to use it for
1984 // distance calculation in NS_SIMPLE_GESTURE_MAGNIFY_UPDATE
1985 mPinchEvent
.touchPoint
= touchPoints
.at(0).pos();
1988 return nsEventStatus_eIgnore
;
1992 nsWindow::OnGestureEvent(QGestureEvent
* event
, bool &handled
) {
1995 if (mGesturesCancelled
) {
1996 return nsEventStatus_eIgnore
;
1999 nsEventStatus result
= nsEventStatus_eIgnore
;
2001 QGesture
* gesture
= event
->gesture(Qt::PinchGesture
);
2004 QPinchGesture
* pinch
= static_cast<QPinchGesture
*>(gesture
);
2007 mPinchEvent
.centerPoint
=
2008 mWidget
->mapFromScene(event
->mapToGraphicsScene(pinch
->centerPoint()));
2009 nsIntPoint
centerPoint(mPinchEvent
.centerPoint
.x(),
2010 mPinchEvent
.centerPoint
.y());
2012 if (pinch
->state() == Qt::GestureStarted
) {
2014 mPinchEvent
.startDistance
= DistanceBetweenPoints(mPinchEvent
.centerPoint
, mPinchEvent
.touchPoint
) * 2;
2015 mPinchEvent
.prevDistance
= mPinchEvent
.startDistance
;
2016 result
= DispatchGestureEvent(NS_SIMPLE_GESTURE_MAGNIFY_START
,
2019 else if (pinch
->state() == Qt::GestureUpdated
) {
2020 mPinchEvent
.needDispatch
= true;
2021 mPinchEvent
.delta
= 0;
2022 DispatchMotionToMainThread();
2024 else if (pinch
->state() == Qt::GestureFinished
) {
2025 double distance
= DistanceBetweenPoints(mPinchEvent
.centerPoint
, mPinchEvent
.touchPoint
) * 2;
2026 double delta
= distance
- mPinchEvent
.startDistance
;
2027 result
= DispatchGestureEvent(NS_SIMPLE_GESTURE_MAGNIFY
,
2028 0, delta
, centerPoint
);
2029 mPinchEvent
.needDispatch
= false;
2035 //Disable mouse events when gestures are used, because they cause problems with
2037 mLastMultiTouchTime
.start();
2040 gesture
= event
->gesture(gSwipeGestureId
);
2042 if (gesture
->state() == Qt::GestureStarted
) {
2045 if (gesture
->state() == Qt::GestureFinished
) {
2049 MozSwipeGesture
* swipe
= static_cast<MozSwipeGesture
*>(gesture
);
2051 hotspot
.x
= swipe
->hotSpot().x();
2052 hotspot
.y
= swipe
->hotSpot().y();
2054 // Cancel pinch gesture
2055 mGesturesCancelled
= true;
2056 mPinchEvent
.needDispatch
= false;
2058 double distance
= DistanceBetweenPoints(swipe
->hotSpot(), mPinchEvent
.touchPoint
) * 2;
2059 double delta
= distance
- mPinchEvent
.startDistance
;
2061 DispatchGestureEvent(NS_SIMPLE_GESTURE_MAGNIFY
, 0, delta
/ 2, hotspot
);
2063 result
= DispatchGestureEvent(NS_SIMPLE_GESTURE_SWIPE
,
2064 swipe
->Direction(), 0, hotspot
);
2066 mLastMultiTouchTime
.start();
2073 nsWindow::DispatchGestureEvent(uint32_t aMsg
, uint32_t aDirection
,
2074 double aDelta
, const nsIntPoint
& aRefPoint
)
2076 nsSimpleGestureEvent
mozGesture(true, aMsg
, this, 0, 0.0);
2077 mozGesture
.direction
= aDirection
;
2078 mozGesture
.delta
= aDelta
;
2079 mozGesture
.refPoint
= LayoutDeviceIntPoint::FromUntyped(aRefPoint
);
2081 Qt::KeyboardModifiers modifiers
= QApplication::keyboardModifiers();
2083 mozGesture
.InitBasicModifiers(modifiers
& Qt::ControlModifier
,
2084 modifiers
& Qt::AltModifier
,
2085 modifiers
& Qt::ShiftModifier
,
2087 mozGesture
.button
= 0;
2088 mozGesture
.time
= 0;
2090 return DispatchEvent(&mozGesture
);
2095 nsWindow::DistanceBetweenPoints(const QPointF
&aFirstPoint
, const QPointF
&aSecondPoint
)
2098 double deltaX
= abs(aFirstPoint
.x() - aSecondPoint
.x());
2099 double deltaY
= abs(aFirstPoint
.y() - aSecondPoint
.y());
2100 result
= sqrt(deltaX
*deltaX
+ deltaY
*deltaY
);
2104 #endif //qt version check
2107 nsWindow::ThemeChanged()
2109 NotifyThemeChanged();
2113 nsWindow::OnDragMotionEvent(QGraphicsSceneDragDropEvent
*aEvent
)
2115 LOG(("nsWindow::OnDragMotionSignal\n"));
2117 nsMouseEvent
event(true, NS_DRAGDROP_OVER
, 0,
2118 nsMouseEvent::eReal
);
2119 return nsEventStatus_eIgnore
;
2123 nsWindow::OnDragLeaveEvent(QGraphicsSceneDragDropEvent
*aEvent
)
2125 // XXX Do we want to pass this on only if the event's subwindow is null?
2126 LOG(("nsWindow::OnDragLeaveSignal(%p)\n", this));
2127 nsMouseEvent
event(true, NS_DRAGDROP_EXIT
, this, nsMouseEvent::eReal
);
2129 return DispatchEvent(&event
);
2133 nsWindow::OnDragDropEvent(QGraphicsSceneDragDropEvent
*aDropEvent
)
2135 if (aDropEvent
->proposedAction() == Qt::CopyAction
)
2137 printf("text version of the data: %s\n", aDropEvent
->mimeData()->text().toUtf8().data());
2138 aDropEvent
->acceptProposedAction();
2141 LOG(("nsWindow::OnDragDropSignal\n"));
2142 nsMouseEvent
event(true, NS_DRAGDROP_OVER
, 0,
2143 nsMouseEvent::eReal
);
2144 return nsEventStatus_eIgnore
;
2148 nsWindow::OnDragEnter(QGraphicsSceneDragDropEvent
*aDragEvent
)
2150 // Is it some format we think we can support?
2151 if ( aDragEvent
->mimeData()->hasFormat(kURLMime
)
2152 || aDragEvent
->mimeData()->hasFormat(kURLDataMime
)
2153 || aDragEvent
->mimeData()->hasFormat(kURLDescriptionMime
)
2154 || aDragEvent
->mimeData()->hasFormat(kHTMLMime
)
2155 || aDragEvent
->mimeData()->hasFormat(kUnicodeMime
)
2156 || aDragEvent
->mimeData()->hasFormat(kTextMime
)
2159 aDragEvent
->acceptProposedAction();
2162 // XXX Do we want to pass this on only if the event's subwindow is null?
2164 LOG(("nsWindow::OnDragEnter(%p)\n", this));
2166 nsMouseEvent
event(true, NS_DRAGDROP_ENTER
, this, nsMouseEvent::eReal
);
2167 return DispatchEvent(&event
);
2171 GetBrandName(nsXPIDLString
& brandName
)
2173 nsCOMPtr
<nsIStringBundleService
> bundleService
=
2174 mozilla::services::GetStringBundleService();
2176 nsCOMPtr
<nsIStringBundle
> bundle
;
2178 bundleService
->CreateBundle(
2179 "chrome://branding/locale/brand.properties",
2180 getter_AddRefs(bundle
));
2183 bundle
->GetStringFromName(
2184 NS_LITERAL_STRING("brandShortName").get(),
2185 getter_Copies(brandName
));
2187 if (brandName
.IsEmpty())
2188 brandName
.Assign(NS_LITERAL_STRING("Mozilla"));
2193 nsWindow::Create(nsIWidget
*aParent
,
2194 nsNativeWidget aNativeParent
,
2195 const nsIntRect
&aRect
,
2196 nsDeviceContext
*aContext
,
2197 nsWidgetInitData
*aInitData
)
2199 // only set the base parent if we're not going to be a dialog or a
2201 nsIWidget
*baseParent
= aParent
;
2204 (aInitData
->mWindowType
== eWindowType_dialog
||
2205 aInitData
->mWindowType
== eWindowType_toplevel
||
2206 aInitData
->mWindowType
== eWindowType_invisible
)) {
2208 baseParent
= nullptr;
2209 // also drop native parent for toplevel windows
2210 aNativeParent
= nullptr;
2213 // initialize all the common bits of this class
2214 BaseCreate(baseParent
, aRect
, aContext
, aInitData
);
2216 // and do our common creation
2222 // find native parent
2223 MozQWidget
*parent
= nullptr;
2225 if (aParent
!= nullptr)
2226 parent
= static_cast<MozQWidget
*>(aParent
->GetNativeData(NS_NATIVE_WIDGET
));
2228 // ok, create our QGraphicsWidget
2229 mWidget
= createQWidget(parent
, aNativeParent
, aInitData
);
2232 return NS_ERROR_OUT_OF_MEMORY
;
2234 LOG(("Create: nsWindow [%p] [%p]\n", (void *)this, (void *)mWidget
));
2236 // resize so that everything is set to the right dimensions
2237 Resize(mBounds
.x
, mBounds
.y
, mBounds
.width
, mBounds
.height
, false);
2239 // check if we should listen for resizes
2240 mListenForResizes
= (aNativeParent
||
2241 (aInitData
&& aInitData
->mListenForResizes
));
2246 already_AddRefed
<nsIWidget
>
2247 nsWindow::CreateChild(const nsIntRect
& aRect
,
2248 nsDeviceContext
* aContext
,
2249 nsWidgetInitData
* aInitData
,
2250 bool /*aForceUseIWidgetParent*/)
2252 //We need to force parent widget, otherwise GetTopLevelWindow doesn't work
2253 return nsBaseWidget::CreateChild(aRect
,
2256 true); // Force parent
2261 nsWindow::SetWindowClass(const nsAString
&xulWinType
)
2264 return NS_ERROR_FAILURE
;
2266 nsXPIDLString brandName
;
2267 GetBrandName(brandName
);
2270 XClassHint
*class_hint
= XAllocClassHint();
2272 return NS_ERROR_OUT_OF_MEMORY
;
2273 const char *role
= NULL
;
2274 class_hint
->res_name
= ToNewCString(xulWinType
);
2275 if (!class_hint
->res_name
) {
2277 return NS_ERROR_OUT_OF_MEMORY
;
2279 class_hint
->res_class
= ToNewCString(brandName
);
2280 if (!class_hint
->res_class
) {
2281 nsMemory::Free(class_hint
->res_name
);
2283 return NS_ERROR_OUT_OF_MEMORY
;
2286 // Parse res_name into a name and role. Characters other than
2287 // [A-Za-z0-9_-] are converted to '_'. Anything after the first
2288 // colon is assigned to role; if there's no colon, assign the
2289 // whole thing to both role and res_name.
2290 for (char *c
= class_hint
->res_name
; *c
; c
++) {
2295 else if (!isascii(*c
) || (!isalnum(*c
) && ('_' != *c
) && ('-' != *c
)))
2298 class_hint
->res_name
[0] = toupper(class_hint
->res_name
[0]);
2299 if (!role
) role
= class_hint
->res_name
;
2301 QWidget
*widget
= GetViewWidget();
2302 // If widget not show, handle might be null
2303 if (widget
&& widget
->winId())
2304 XSetClassHint(gfxQtPlatform::GetXDisplay(widget
),
2308 nsMemory::Free(class_hint
->res_class
);
2309 nsMemory::Free(class_hint
->res_name
);
2317 nsWindow::NativeResize(int32_t aWidth
, int32_t aHeight
, bool aRepaint
)
2319 LOG(("nsWindow::NativeResize [%p] %d %d\n", (void *)this,
2322 mNeedsResize
= false;
2325 QGraphicsView
*widget
= qobject_cast
<QGraphicsView
*>(GetViewWidget());
2326 NS_ENSURE_TRUE_VOID(widget
);
2327 // map from in-scene widget to scene, from scene to view.
2328 QRect r
= widget
->mapFromScene(mWidget
->mapToScene(QRect(0, 0, aWidth
, aHeight
))).boundingRect();
2329 // going from QPolygon to QRect includes the points, adding one to width and height
2330 r
.adjust(0, 0, -1, -1);
2331 widget
->resize(r
.width(), r
.height());
2334 mWidget
->resize(aWidth
, aHeight
);
2342 nsWindow::NativeResize(int32_t aX
, int32_t aY
,
2343 int32_t aWidth
, int32_t aHeight
,
2346 LOG(("nsWindow::NativeResize [%p] %d %d %d %d\n", (void *)this,
2347 aX
, aY
, aWidth
, aHeight
));
2349 mNeedsResize
= false;
2353 QGraphicsView
*widget
= qobject_cast
<QGraphicsView
*>(GetViewWidget());
2354 NS_ENSURE_TRUE_VOID(widget
);
2355 // map from in-scene widget to scene, from scene to view.
2356 QRect r
= widget
->mapFromScene(mWidget
->mapToScene(QRect(aX
, aY
, aWidth
, aHeight
))).boundingRect();
2357 // going from QPolygon to QRect includes the points, adding one to width and height
2358 r
.adjust(0, 0, -1, -1);
2359 widget
->setGeometry(r
.x(), r
.y(), r
.width(), r
.height());
2362 mWidget
->setGeometry(aX
, aY
, aWidth
, aHeight
);
2370 nsWindow::NativeShow(bool aAction
)
2373 QWidget
*widget
= GetViewWidget();
2374 // On e10s, we never want the child process or plugin process
2375 // to go fullscreen because if we do the window because visible
2376 // do to disabled Qt-Xembed
2378 !widget
->isVisible())
2379 MakeFullScreen(mSizeMode
== nsSizeMode_Fullscreen
);
2382 // unset our flag now that our window has been shown
2390 nsWindow::SetHasTransparentBackground(bool aTransparent
)
2392 return NS_ERROR_NOT_IMPLEMENTED
;
2396 nsWindow::GetHasTransparentBackground(bool& aTransparent
)
2398 aTransparent
= mIsTransparent
;
2403 nsWindow::SetupPluginPort(void)
2405 NS_WARNING("Not implemented");
2410 nsWindow::SetWindowIconList(const nsTArray
<nsCString
> &aIconList
)
2414 for (uint32_t i
= 0; i
< aIconList
.Length(); ++i
) {
2415 const char *path
= aIconList
[i
].get();
2416 LOG(("window [%p] Loading icon from %s\n", (void *)this, path
));
2420 QWidget
*widget
= GetViewWidget();
2421 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
2422 widget
->setWindowIcon(icon
);
2428 nsWindow::SetDefaultIcon(void)
2430 SetIcon(NS_LITERAL_STRING("default"));
2433 void nsWindow::QWidgetDestroyed()
2439 nsWindow::MakeFullScreen(bool aFullScreen
)
2441 QWidget
*widget
= GetViewWidget();
2442 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
2444 if (mSizeMode
!= nsSizeMode_Fullscreen
)
2445 mLastSizeMode
= mSizeMode
;
2447 mSizeMode
= nsSizeMode_Fullscreen
;
2448 widget
->showFullScreen();
2451 mSizeMode
= mLastSizeMode
;
2453 switch (mSizeMode
) {
2454 case nsSizeMode_Maximized
:
2455 widget
->showMaximized();
2457 case nsSizeMode_Minimized
:
2458 widget
->showMinimized();
2460 case nsSizeMode_Normal
:
2461 widget
->showNormal();
2464 widget
->showNormal();
2469 NS_ASSERTION(mLastSizeMode
!= nsSizeMode_Fullscreen
,
2470 "mLastSizeMode should never be fullscreen");
2471 return nsBaseWidget::MakeFullScreen(aFullScreen
);
2475 nsWindow::HideWindowChrome(bool aShouldHide
)
2479 return NS_ERROR_FAILURE
;
2482 // Sawfish, metacity, and presumably other window managers get
2483 // confused if we change the window decorations while the window
2485 bool wasVisible
= false;
2486 if (mWidget
->isVisible()) {
2495 // For some window managers, adding or removing window decorations
2496 // requires unmapping and remapping our toplevel window. Go ahead
2497 // and flush the queue here so that we don't end up with a BadWindow
2498 // error later when this happens (when the persistence timer fires
2499 // and GetWindowPos is called)
2500 QWidget
*widget
= GetViewWidget();
2501 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
2503 XSync(gfxQtPlatform::GetXDisplay(widget
), False
);
2509 //////////////////////////////////////////////////////////////////////
2510 // These are all of our drag and drop operations
2513 nsWindow::InitDragEvent(nsMouseEvent
&aEvent
)
2515 // set the keyboard modifiers
2518 // This will update the drag action based on the information in the
2523 initialize_prefs(void)
2525 // check to see if we should set our raise pref
2530 is_context_menu_key(const nsKeyEvent
& aKeyEvent
)
2532 return ((aKeyEvent
.keyCode
== NS_VK_F10
&& aKeyEvent
.IsShift() &&
2533 !aKeyEvent
.IsControl() && !aKeyEvent
.IsMeta() &&
2534 !aKeyEvent
.IsAlt()) ||
2535 (aKeyEvent
.keyCode
== NS_VK_CONTEXT_MENU
&& !aKeyEvent
.IsShift() &&
2536 !aKeyEvent
.IsControl() && !aKeyEvent
.IsMeta() &&
2537 !aKeyEvent
.IsAlt()));
2541 key_event_to_context_menu_event(nsMouseEvent
&aEvent
,
2542 QKeyEvent
*aGdkEvent
)
2544 aEvent
.refPoint
= LayoutDeviceIntPoint(0, 0);
2545 aEvent
.modifiers
= 0;
2547 aEvent
.clickCount
= 1;
2550 // nsChildWindow class
2552 nsChildWindow::nsChildWindow()
2556 nsChildWindow::~nsChildWindow()
2560 nsPopupWindow::nsPopupWindow()
2562 #ifdef DEBUG_WIDGETS
2563 qDebug("===================== popup!");
2567 nsPopupWindow::~nsPopupWindow()
2571 NS_IMETHODIMP_(bool)
2572 nsWindow::HasGLContext()
2574 return MozQGLWidgetWrapper::hasGLContext(qobject_cast
<QGraphicsView
*>(GetViewWidget()));
2578 nsWindow::createQWidget(MozQWidget
*parent
,
2579 nsNativeWidget nativeParent
,
2580 nsWidgetInitData
*aInitData
)
2582 const char *windowName
= NULL
;
2583 Qt::WindowFlags flags
= Qt::Widget
;
2584 QWidget
*parentWidget
= (parent
&& parent
->getReceiver()) ?
2585 parent
->getReceiver()->GetViewWidget() : nullptr;
2587 #ifdef DEBUG_WIDGETS
2588 qDebug("NEW WIDGET\n\tparent is %p (%s)", (void*)parent
,
2589 parent
? qPrintable(parent
->objectName()) : "null");
2592 // ok, create our windows
2593 switch (mWindowType
) {
2594 case eWindowType_dialog
:
2595 windowName
= "topLevelDialog";
2597 flags
|= Qt::Dialog
;
2599 case eWindowType_popup
:
2600 windowName
= "topLevelPopup";
2602 case eWindowType_toplevel
:
2603 windowName
= "topLevelWindow";
2606 case eWindowType_invisible
:
2607 windowName
= "topLevelInvisible";
2609 case eWindowType_child
:
2610 case eWindowType_plugin
:
2612 windowName
= "paintArea";
2616 MozQWidget
* parentQWidget
= nullptr;
2618 parentQWidget
= parent
;
2619 } else if (nativeParent
&& nativeParent
!= PARENTLESS_WIDGET
) {
2620 parentQWidget
= static_cast<MozQWidget
*>(nativeParent
);
2622 MozQWidget
* widget
= new MozQWidget(this, parentQWidget
);
2625 widget
->setObjectName(QString(windowName
));
2627 // make only child and plugin windows focusable
2628 if (eWindowType_child
== mWindowType
|| eWindowType_plugin
== mWindowType
) {
2629 widget
->setFlag(QGraphicsItem::ItemIsFocusable
);
2630 widget
->setFocusPolicy(Qt::WheelFocus
);
2633 // create a QGraphicsView if this is a new toplevel window
2636 QGraphicsView
* newView
=
2637 nsFastStartup::GetStartupGraphicsView(parentWidget
, widget
);
2639 if (mWindowType
== eWindowType_dialog
) {
2640 newView
->setWindowModality(Qt::WindowModal
);
2643 if (gfxQtPlatform::GetPlatform()->GetRenderMode() == gfxQtPlatform::RENDER_DIRECT
) {
2644 // Disable double buffer and system background rendering
2645 #if defined(MOZ_X11) && (QT_VERSION < QT_VERSION_CHECK(5,0,0))
2646 newView
->viewport()->setAttribute(Qt::WA_PaintOnScreen
, true);
2648 newView
->viewport()->setAttribute(Qt::WA_NoSystemBackground
, true);
2651 #if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 0))
2652 #if defined MOZ_ENABLE_MEEGOTOUCH
2653 // Disable default Gesture filters (speedup filtering)
2654 newView
->viewport()->ungrabGesture(Qt::PanGesture
);
2655 newView
->viewport()->ungrabGesture(Qt::TapGesture
);
2656 newView
->viewport()->ungrabGesture(Qt::TapAndHoldGesture
);
2657 newView
->viewport()->ungrabGesture(Qt::SwipeGesture
);
2660 // Enable required filters
2661 newView
->viewport()->grabGesture(Qt::PinchGesture
);
2662 newView
->viewport()->grabGesture(gSwipeGestureId
);
2664 newView
->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
2665 newView
->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
2667 #if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 0))
2668 // Top level widget is just container, and should not be painted
2669 widget
->setFlag(QGraphicsItem::ItemHasNoContents
);
2673 if (newView
->effectiveWinId()) {
2674 XSetWindowBackgroundPixmap(mozilla::DefaultXDisplay(),
2675 newView
->effectiveWinId(), None
);
2680 if (mWindowType
== eWindowType_popup
) {
2681 widget
->setZValue(100);
2683 // XXX is this needed for Qt?
2684 // gdk does not automatically set the cursor for "temporary"
2685 // windows, which are what gtk uses for popups.
2686 SetCursor(eCursor_standard
);
2687 } else if (mIsTopLevel
) {
2690 #if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 0))
2691 #if defined MOZ_ENABLE_MEEGOTOUCH
2692 // Disable default Gesture filters (speedup filtering)
2693 widget
->ungrabGesture(Qt::PanGesture
);
2694 widget
->ungrabGesture(Qt::TapGesture
);
2695 widget
->ungrabGesture(Qt::TapAndHoldGesture
);
2696 widget
->ungrabGesture(Qt::SwipeGesture
);
2698 widget
->grabGesture(Qt::PinchGesture
);
2699 widget
->grabGesture(gSwipeGestureId
);
2705 // return the gfxASurface for rendering to this widget
2707 nsWindow::GetThebesSurface()
2709 /* This is really a dummy surface; this is only used when doing reflow, because
2710 * we need a RenderingContext to measure text against.
2713 return mThebesSurface
;
2715 #ifdef CAIRO_HAS_QT_SURFACE
2716 gfxQtPlatform::RenderMode renderMode
= gfxQtPlatform::GetPlatform()->GetRenderMode();
2717 if (renderMode
== gfxQtPlatform::RENDER_QPAINTER
) {
2718 mThebesSurface
= new gfxQPainterSurface(gfxIntSize(1, 1), gfxASurface::CONTENT_COLOR
);
2721 if (!mThebesSurface
) {
2722 gfxASurface::gfxImageFormat imageFormat
= gfxASurface::ImageFormatRGB24
;
2723 mThebesSurface
= new gfxImageSurface(gfxIntSize(1, 1), imageFormat
);
2726 return mThebesSurface
;
2730 nsWindow::BeginResizeDrag(nsGUIEvent
* aEvent
, int32_t aHorizontal
, int32_t aVertical
)
2732 NS_ENSURE_ARG_POINTER(aEvent
);
2734 if (aEvent
->eventStructType
!= NS_MOUSE_EVENT
) {
2735 // you can only begin a resize drag with a mouse event
2736 return NS_ERROR_INVALID_ARG
;
2739 nsMouseEvent
* mouse_event
= static_cast<nsMouseEvent
*>(aEvent
);
2741 if (mouse_event
->button
!= nsMouseEvent::eLeftButton
) {
2742 // you can only begin a resize drag with the left mouse button
2743 return NS_ERROR_INVALID_ARG
;
2750 nsWindow::contextMenuEvent(QGraphicsSceneContextMenuEvent
*)
2752 return nsEventStatus_eIgnore
;
2756 nsWindow::imComposeEvent(QInputMethodEvent
*event
, bool &handled
)
2758 // XXX Needs to check whether this widget has been destroyed or not after
2759 // each DispatchEvent().
2761 nsCompositionEvent
start(true, NS_COMPOSITION_START
, this);
2762 DispatchEvent(&start
);
2764 nsAutoString
compositionStr(event
->commitString().utf16());
2766 if (!compositionStr
.IsEmpty()) {
2767 nsCompositionEvent
update(true, NS_COMPOSITION_UPDATE
, this);
2768 update
.data
= compositionStr
;
2769 DispatchEvent(&update
);
2772 nsTextEvent
text(true, NS_TEXT_TEXT
, this);
2773 text
.theText
= compositionStr
;
2774 DispatchEvent(&text
);
2776 nsCompositionEvent
end(true, NS_COMPOSITION_END
, this);
2777 end
.data
= compositionStr
;
2778 DispatchEvent(&end
);
2780 return nsEventStatus_eIgnore
;
2784 nsWindow::GetParent(void)
2792 QDesktopWidget
* rootWindow
= QApplication::desktop();
2793 double heightInches
= rootWindow
->heightMM()/25.4;
2794 if (heightInches
< 0.25) {
2795 // Something's broken, but we'd better not crash.
2799 return float(rootWindow
->height()/heightInches
);
2803 nsWindow::DispatchActivateEvent(void)
2805 if (mWidgetListener
)
2806 mWidgetListener
->WindowActivated();
2810 nsWindow::DispatchDeactivateEvent(void)
2812 if (mWidgetListener
)
2813 mWidgetListener
->WindowDeactivated();
2817 nsWindow::DispatchActivateEventOnTopLevelWindow(void)
2819 nsWindow
* topLevelWindow
= static_cast<nsWindow
*>(GetTopLevelWidget());
2820 if (topLevelWindow
!= nullptr)
2821 topLevelWindow
->DispatchActivateEvent();
2825 nsWindow::DispatchDeactivateEventOnTopLevelWindow(void)
2827 nsWindow
* topLevelWindow
= static_cast<nsWindow
*>(GetTopLevelWidget());
2828 if (topLevelWindow
!= nullptr)
2829 topLevelWindow
->DispatchDeactivateEvent();
2833 nsWindow::DispatchResizeEvent(nsIntRect
&aRect
, nsEventStatus
&aStatus
)
2835 aStatus
= nsEventStatus_eIgnore
;
2836 if (mWidgetListener
&&
2837 mWidgetListener
->WindowResized(this, aRect
.width
, aRect
.height
))
2838 aStatus
= nsEventStatus_eConsumeNoDefault
;
2842 nsWindow::DispatchEvent(nsGUIEvent
*aEvent
, nsEventStatus
&aStatus
)
2845 debug_DumpEvent(stdout
, aEvent
->widget
, aEvent
,
2846 nsAutoCString("something"), 0);
2849 aStatus
= nsEventStatus_eIgnore
;
2851 // send it to the standard callback
2852 if (mWidgetListener
)
2853 aStatus
= mWidgetListener
->HandleEvent(aEvent
, mUseAttachedEvents
);
2859 nsWindow::Show(bool aState
)
2861 LOG(("nsWindow::Show [%p] state %d\n", (void *)this, aState
));
2862 if (aState
== mIsShown
)
2865 // Clear our cached resources when the window is hidden.
2866 if (mIsShown
&& !aState
) {
2867 ClearCachedResources();
2872 #ifdef MOZ_ENABLE_QTMOBILITY
2874 (mWindowType
== eWindowType_toplevel
||
2875 mWindowType
== eWindowType_dialog
||
2876 mWindowType
== eWindowType_popup
))
2878 if (!gOrientation
) {
2879 gOrientation
= new QOrientationSensor();
2880 gOrientation
->addFilter(&gOrientationFilter
);
2881 gOrientation
->start();
2882 if (!gOrientation
->isActive()) {
2883 qWarning("Orientationsensor didn't start!");
2885 gOrientationFilter
.filter(gOrientation
->reading());
2887 QObject::connect((QObject
*) &gOrientationFilter
, SIGNAL(orientationChanged()),
2888 mWidget
, SLOT(orientationChanged()));
2893 if ((aState
&& !AreBoundsSane()) || !mWidget
) {
2894 LOG(("\tbounds are insane or window hasn't been created yet\n"));
2901 NativeResize(mBounds
.x
, mBounds
.y
, mBounds
.width
, mBounds
.height
,
2903 } else if (mNeedsResize
) {
2904 NativeResize(mBounds
.width
, mBounds
.height
, false);
2908 // If someone is hiding this widget, clear any needing show flag.
2917 nsWindow::Resize(double aWidth
, double aHeight
, bool aRepaint
)
2919 mBounds
.width
= NSToIntRound(aWidth
);
2920 mBounds
.height
= NSToIntRound(aHeight
);
2926 if (AreBoundsSane()) {
2927 if (mIsTopLevel
|| mNeedsShow
)
2928 NativeResize(mBounds
.x
, mBounds
.y
,
2929 mBounds
.width
, mBounds
.height
, aRepaint
);
2931 NativeResize(mBounds
.width
, mBounds
.height
, aRepaint
);
2933 // Does it need to be shown because it was previously insane?
2938 // If someone has set this so that the needs show flag is false
2939 // and it needs to be hidden, update the flag and hide the
2940 // window. This flag will be cleared the next time someone
2941 // hides the window or shows it. It also prevents us from
2942 // calling NativeShow(false) excessively on the window which
2943 // causes unneeded X traffic.
2950 else if (AreBoundsSane() && mListenForResizes
) {
2951 // For widgets that we listen for resizes for (widgets created
2952 // with native parents) we apparently _always_ have to resize. I
2953 // dunno why, but apparently we're lame like that.
2954 NativeResize(mBounds
.width
, mBounds
.height
, aRepaint
);
2957 mNeedsResize
= true;
2960 // synthesize a resize event if this isn't a toplevel
2961 if (mIsTopLevel
|| mListenForResizes
) {
2962 nsEventStatus status
;
2963 DispatchResizeEvent(mBounds
, status
);
2966 NotifyRollupGeometryChange();
2971 nsWindow::Resize(double aX
, double aY
, double aWidth
, double aHeight
,
2974 mBounds
.x
= NSToIntRound(aX
);
2975 mBounds
.y
= NSToIntRound(aY
);
2976 mBounds
.width
= NSToIntRound(aWidth
);
2977 mBounds
.height
= NSToIntRound(aHeight
);
2984 // Has this widget been set to visible?
2986 // Are the bounds sane?
2987 if (AreBoundsSane()) {
2988 // Yep? Resize the window
2989 NativeResize(mBounds
.x
, mBounds
.y
, mBounds
.width
, mBounds
.height
,
2991 // Does it need to be shown because it was previously insane?
2996 // If someone has set this so that the needs show flag is false
2997 // and it needs to be hidden, update the flag and hide the
2998 // window. This flag will be cleared the next time someone
2999 // hides the window or shows it. It also prevents us from
3000 // calling NativeShow(false) excessively on the window which
3001 // causes unneeded X traffic.
3008 // If the widget hasn't been shown, mark the widget as needing to be
3009 // resized before it is shown
3010 else if (AreBoundsSane() && mListenForResizes
) {
3011 // For widgets that we listen for resizes for (widgets created
3012 // with native parents) we apparently _always_ have to resize. I
3013 // dunno why, but apparently we're lame like that.
3014 NativeResize(mBounds
.x
, mBounds
.y
, mBounds
.width
, mBounds
.height
,
3018 mNeedsResize
= true;
3022 if (mIsTopLevel
|| mListenForResizes
) {
3023 // synthesize a resize event
3024 nsEventStatus status
;
3025 DispatchResizeEvent(mBounds
, status
);
3031 NotifyRollupGeometryChange();
3036 nsWindow::Enable(bool aState
)
3044 nsWindow::IsEnabled() const
3050 nsWindow::OnDestroy(void)
3052 if (mOnDestroyCalled
)
3055 mOnDestroyCalled
= true;
3057 // release references to children and device context
3058 nsBaseWidget::OnDestroy();
3060 // let go of our parent
3063 nsCOMPtr
<nsIWidget
> kungFuDeathGrip
= this;
3064 NotifyWindowDestroyed();
3068 nsWindow::AreBoundsSane(void)
3070 if (mBounds
.width
> 0 && mBounds
.height
> 0)
3076 NS_IMETHODIMP_(void)
3077 nsWindow::SetInputContext(const InputContext
& aContext
,
3078 const InputContextAction
& aAction
)
3080 NS_ENSURE_TRUE_VOID(mWidget
);
3082 // SetSoftwareKeyboardState uses mInputContext,
3083 // so, before calling that, record aContext in mInputContext.
3084 mInputContext
= aContext
;
3086 switch (mInputContext
.mIMEState
.mEnabled
) {
3087 case IMEState::ENABLED
:
3088 case IMEState::PASSWORD
:
3089 case IMEState::PLUGIN
:
3090 SetSoftwareKeyboardState(true, aAction
);
3093 SetSoftwareKeyboardState(false, aAction
);
3098 NS_IMETHODIMP_(InputContext
)
3099 nsWindow::GetInputContext()
3101 mInputContext
.mIMEState
.mOpen
= IMEState::OPEN_STATE_NOT_SUPPORTED
;
3102 // Our qt widget looks like using only one context per process.
3103 // However, it's better to set the context's pointer.
3104 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
3105 mInputContext
.mNativeIMEContext
= qApp
->inputContext();
3107 mInputContext
.mNativeIMEContext
= qApp
->inputMethod();
3109 return mInputContext
;
3113 nsWindow::SetSoftwareKeyboardState(bool aOpen
,
3114 const InputContextAction
& aAction
)
3117 NS_ENSURE_TRUE_VOID(mInputContext
.mIMEState
.mEnabled
!=
3118 IMEState::DISABLED
);
3120 // Ensure that opening the virtual keyboard is allowed for this specific
3121 // InputContext depending on the content.ime.strict.policy pref
3122 if (mInputContext
.mIMEState
.mEnabled
!= IMEState::PLUGIN
&&
3123 Preferences::GetBool("content.ime.strict_policy", false) &&
3124 !aAction
.ContentGotFocusByTrustedCause() &&
3125 !aAction
.UserMightRequestOpenVKB()) {
3131 // VKB open need to be delayed in order to give
3132 // to plugins chance prevent VKB from opening
3134 Preferences::GetInt("ui.vkb.open.delay", 200);
3135 MozQWidget::requestVKB(openDelay
, mWidget
);
3137 MozQWidget::hideVKB();
3143 nsWindow::UserActivity()
3145 if (!mIdleService
) {
3146 mIdleService
= do_GetService("@mozilla.org/widget/idleservice;1");
3150 mIdleService
->ResetIdleTimeOut(0);
3155 nsWindow::GetGLFrameBufferFormat()
3157 if (mLayerManager
&&
3158 mLayerManager
->GetBackendType() == mozilla::layers::LAYERS_OPENGL
) {
3159 return MozQGLWidgetWrapper::isRGBAContext() ? LOCAL_GL_RGBA
: LOCAL_GL_RGB
;
3161 return LOCAL_GL_NONE
;