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"
91 #if MOZ_PLATFORM_MAEMO > 5
92 #include "nsIDOMWindow.h"
93 #include "nsIDOMElement.h"
94 #include "nsIFocusManager.h"
98 #include "keysym2ucs.h"
99 #if MOZ_PLATFORM_MAEMO == 6
100 #include <X11/Xatom.h>
101 static Atom sPluginIMEAtom
= nullptr;
102 #define PLUGIN_VKB_REQUEST_PROP "_NPAPI_PLUGIN_REQUEST_VKB"
107 #include "gfxUtils.h"
109 #include "GLContextProvider.h"
110 #include "BasicLayers.h"
111 #include "LayerManagerOGL.h"
112 #include "nsFastStartupQt.h"
114 // If embedding clients want to create widget without real parent window
115 // then nsIBaseWindow->Init() should have parent argument equal to PARENTLESS_WIDGET
116 #define PARENTLESS_WIDGET (void*)0x13579
118 #include "nsShmImage.h"
120 #define PIXMAN_DONT_DEFINE_STDINT
124 using namespace mozilla
;
125 using namespace mozilla::widget
;
126 using mozilla::gl::GLContext
;
127 using mozilla::layers::LayerManagerOGL
;
129 // Cached offscreen surface
130 static nsRefPtr
<gfxASurface
> gBufferSurface
;
131 #ifdef MOZ_HAVE_SHMIMAGE
132 // If we're using xshm rendering, mThebesSurface wraps gShmImage
133 nsRefPtr
<nsShmImage
> gShmImage
;
136 static int gBufferPixmapUsageCount
= 0;
137 static gfxIntSize
gBufferMaxSize(0, 0);
139 // initialization static functions
140 static nsresult
initialize_prefs (void);
142 static NS_DEFINE_IID(kCDragServiceCID
, NS_DRAGSERVICE_CID
);
144 #define NS_WINDOW_TITLE_MAX_LENGTH 4095
146 #define kWindowPositionSlop 20
149 static const int WHEEL_DELTA
= 120;
150 static bool gGlobalsInitialized
= false;
153 is_mouse_in_window (MozQWidget
* aWindow
, double aMouseX
, double aMouseY
);
155 static bool sAltGrModifier
= false;
157 #ifdef MOZ_ENABLE_QTMOBILITY
158 static QOrientationSensor
*gOrientation
= nullptr;
159 static MozQOrientationSensorFilter gOrientationFilter
;
163 isContextMenuKeyEvent(const QKeyEvent
*qe
)
165 uint32_t kc
= QtKeyCodeToDOMKeyCode(qe
->key());
166 if (qe
->modifiers() & (Qt::ControlModifier
| Qt::AltModifier
| Qt::MetaModifier
))
169 bool isShift
= qe
->modifiers() & Qt::ShiftModifier
;
170 return (kc
== NS_VK_F10
&& isShift
) ||
171 (kc
== NS_VK_CONTEXT_MENU
&& !isShift
);
175 InitKeyEvent(nsKeyEvent
&aEvent
, QKeyEvent
*aQEvent
)
177 aEvent
.InitBasicModifiers(aQEvent
->modifiers() & Qt::ControlModifier
,
178 aQEvent
->modifiers() & Qt::AltModifier
,
179 aQEvent
->modifiers() & Qt::ShiftModifier
,
180 aQEvent
->modifiers() & Qt::MetaModifier
);
182 // TODO: Needs to set .location for desktop Qt build.
183 #ifdef MOZ_PLATFORM_MAEMO
184 aEvent
.location
= nsIDOMKeyEvent::DOM_KEY_LOCATION_MOBILE
;
188 if (sAltGrModifier
) {
189 aEvent
.modifiers
|= (widget::MODIFIER_CONTROL
| widget::MODIFIER_ALT
);
192 // The transformations above and in qt for the keyval are not invertible
193 // so link to the QKeyEvent (which will vanish soon after return from the
194 // event callback) to give plugins access to hardware_keycode and state.
195 // (An XEvent would be nice but the QKeyEvent is good enough.)
196 aEvent
.pluginEvent
= (void *)aQEvent
;
201 LOG(("%s [%p]\n", __PRETTY_FUNCTION__
, (void *)this));
204 mIsDestroyed
= false;
209 mActivatePending
= false;
210 mWindowType
= eWindowType_child
;
211 mSizeState
= nsSizeMode_Normal
;
212 mLastSizeMode
= nsSizeMode_Normal
;
213 mPluginType
= PluginType_NONE
;
214 mQCursor
= Qt::ArrowCursor
;
215 mNeedsResize
= false;
217 mListenForResizes
= false;
219 mGesturesCancelled
= false;
220 mTimerStarted
= false;
221 mPinchEvent
.needDispatch
= false;
222 mMoveEvent
.needDispatch
= false;
224 if (!gGlobalsInitialized
) {
225 gfxPlatform::GetPlatform();
226 gGlobalsInitialized
= true;
228 #if defined(MOZ_X11) && (MOZ_PLATFORM_MAEMO == 6)
229 // This cannot be called on non-main thread
230 if (QThread::currentThread() == qApp
->thread()) {
231 sPluginIMEAtom
= XInternAtom(mozilla::DefaultXDisplay(), PLUGIN_VKB_REQUEST_PROP
, False
);
234 // It's OK if either of these fail, but it may not be one day.
238 memset(mKeyDownFlags
, 0, sizeof(mKeyDownFlags
));
240 mIsTransparent
= false;
242 mCursor
= eCursor_standard
;
244 gBufferPixmapUsageCount
++;
246 #if (QT_VERSION > QT_VERSION_CHECK(4,6,0))
247 if (gSwipeGestureId
== Qt::CustomGesture
) {
248 // QGestureRecognizer takes ownership
249 MozSwipeGestureRecognizer
* swipeRecognizer
= new MozSwipeGestureRecognizer
;
250 gSwipeGestureId
= QGestureRecognizer::registerRecognizer(swipeRecognizer
);
255 static inline gfxASurface::gfxImageFormat
256 _depth_to_gfximage_format(int32_t aDepth
)
260 return gfxASurface::ImageFormatARGB32
;
262 return gfxASurface::ImageFormatRGB24
;
264 return gfxASurface::ImageFormatRGB16_565
;
266 return gfxASurface::ImageFormatUnknown
;
270 static inline QImage::Format
271 _gfximage_to_qformat(gfxASurface::gfxImageFormat aFormat
)
274 case gfxASurface::ImageFormatARGB32
:
275 return QImage::Format_ARGB32_Premultiplied
;
276 case gfxASurface::ImageFormatRGB24
:
277 return QImage::Format_ARGB32
;
278 case gfxASurface::ImageFormatRGB16_565
:
279 return QImage::Format_RGB16
;
281 return QImage::Format_Invalid
;
286 UpdateOffScreenBuffers(int aDepth
, QSize aSize
, QWidget
* aWidget
= nullptr)
288 gfxIntSize
size(aSize
.width(), aSize
.height());
289 if (gBufferSurface
) {
290 if (gBufferMaxSize
.width
< size
.width
||
291 gBufferMaxSize
.height
< size
.height
) {
292 gBufferSurface
= nullptr;
297 gBufferMaxSize
.width
= std::max(gBufferMaxSize
.width
, size
.width
);
298 gBufferMaxSize
.height
= std::max(gBufferMaxSize
.height
, size
.height
);
300 // Check if system depth has related gfxImage format
301 gfxASurface::gfxImageFormat format
=
302 _depth_to_gfximage_format(aDepth
);
304 // Use fallback RGB24 format, Qt will do conversion for us
305 if (format
== gfxASurface::ImageFormatUnknown
)
306 format
= gfxASurface::ImageFormatRGB24
;
308 #ifdef MOZ_HAVE_SHMIMAGE
310 if (gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType() ==
311 gfxASurface::SurfaceTypeImage
) {
312 gShmImage
= nsShmImage::Create(gBufferMaxSize
,
313 DefaultVisualOfScreen(gfxQtPlatform::GetXScreen(aWidget
)),
315 gBufferSurface
= gShmImage
->AsSurface();
321 gBufferSurface
= gfxPlatform::GetPlatform()->
322 CreateOffscreenSurface(gBufferMaxSize
, gfxASurface::ContentFromFormat(format
));
327 nsWindow::~nsWindow()
329 LOG(("%s [%p]\n", __PRETTY_FUNCTION__
, (void *)this));
335 nsWindow::ReleaseGlobals()
339 NS_IMPL_ISUPPORTS_INHERITED1(nsWindow
, nsBaseWidget
, nsISupportsWeakReference
)
342 nsWindow::ConfigureChildren(const nsTArray
<nsIWidget::Configuration
>& aConfigurations
)
344 for (uint32_t i
= 0; i
< aConfigurations
.Length(); ++i
) {
345 const Configuration
& configuration
= aConfigurations
[i
];
347 nsWindow
* w
= static_cast<nsWindow
*>(configuration
.mChild
);
348 NS_ASSERTION(w
->GetParent() == this,
349 "Configured widget is not a child");
351 if (w
->mBounds
.Size() != configuration
.mBounds
.Size()) {
352 w
->Resize(configuration
.mBounds
.x
, configuration
.mBounds
.y
,
353 configuration
.mBounds
.width
, configuration
.mBounds
.height
,
355 } else if (w
->mBounds
.TopLeft() != configuration
.mBounds
.TopLeft()) {
356 w
->Move(configuration
.mBounds
.x
, configuration
.mBounds
.y
);
363 nsWindow::Destroy(void)
365 if (mIsDestroyed
|| !mWidget
)
368 LOG(("nsWindow::Destroy [%p]\n", (void *)this));
371 if (gBufferPixmapUsageCount
&&
372 --gBufferPixmapUsageCount
== 0) {
374 gBufferSurface
= nullptr;
375 #ifdef MOZ_HAVE_SHMIMAGE
378 #ifdef MOZ_ENABLE_QTMOBILITY
380 gOrientation
->removeFilter(&gOrientationFilter
);
381 gOrientation
->stop();
383 gOrientation
= nullptr;
388 /** Need to clean our LayerManager up while still alive */
390 nsRefPtr
<GLContext
> gl
= nullptr;
391 if (mLayerManager
->GetBackendType() == mozilla::layers::LAYERS_OPENGL
) {
392 LayerManagerOGL
*ogllm
= static_cast<LayerManagerOGL
*>(mLayerManager
.get());
396 mLayerManager
->Destroy();
402 mLayerManager
= nullptr;
404 // It is safe to call DestroyeCompositor several times (here and
405 // in the parent class) since it will take effect only once.
406 // The reason we call it here is because on gtk platforms we need
407 // to destroy the compositor before we destroy the gdk window (which
408 // destroys the the gl context attached to it).
411 ClearCachedResources();
413 nsIRollupListener
* rollupListener
= nsBaseWidget::GetActiveRollupListener();
414 if (rollupListener
) {
415 nsCOMPtr
<nsIWidget
> rollupWidget
= rollupListener
->GetRollupWidget();
416 if (static_cast<nsIWidget
*>(this) == rollupWidget
) {
417 rollupListener
->Rollup(0, nullptr);
423 // walk the list of children and call destroy on them. Have to be
424 // careful, though -- calling destroy on a kid may actually remove
425 // it from our child list, losing its sibling links.
426 for (nsIWidget
* kid
= mFirstChild
; kid
; ) {
427 nsIWidget
* next
= kid
->GetNextSibling();
432 // Destroy thebes surface now. Badness can happen if we destroy
433 // the surface after its X Window.
434 mThebesSurface
= nullptr;
436 QWidget
*view
= nullptr;
437 QGraphicsScene
*scene
= nullptr;
440 view
= GetViewWidget();
441 scene
= mWidget
->scene();
444 mWidget
->dropReceiver();
446 // Call deleteLater instead of delete; Qt still needs the object
447 // to be valid even after sending it a Close event. We could
448 // also set WA_DeleteOnClose, but this gives us more control.
449 mWidget
->deleteLater();
455 // tear down some infrastructure after all event handling is finished
463 nsWindow::ClearCachedResources()
466 mLayerManager
->GetBackendType() == mozilla::layers::LAYERS_BASIC
) {
467 static_cast<mozilla::layers::BasicLayerManager
*> (mLayerManager
.get())->
468 ClearCachedResources();
470 for (nsIWidget
* kid
= mFirstChild
; kid
; ) {
471 nsIWidget
* next
= kid
->GetNextSibling();
472 static_cast<nsWindow
*>(kid
)->ClearCachedResources();
478 nsWindow::SetParent(nsIWidget
*aNewParent
)
480 NS_ENSURE_ARG_POINTER(aNewParent
);
481 nsCOMPtr
<nsIWidget
> kungFuDeathGrip(this);
482 nsIWidget
* parent
= GetParent();
484 parent
->RemoveChild(this);
486 ReparentNativeWidget(aNewParent
);
487 aNewParent
->AddChild(this);
492 nsWindow::ReparentNativeWidget(nsIWidget
*aNewParent
)
494 NS_PRECONDITION(aNewParent
, "");
496 MozQWidget
* newParent
= static_cast<MozQWidget
*>(aNewParent
->GetNativeData(NS_NATIVE_WINDOW
));
497 NS_ASSERTION(newParent
, "Parent widget has a null native window handle");
499 mWidget
->setParentItem(newParent
);
505 nsWindow::SetModal(bool aModal
)
507 LOG(("nsWindow::SetModal [%p] %d, widget[%p]\n", (void *)this, aModal
, mWidget
));
509 mWidget
->setModal(aModal
);
515 nsWindow::IsVisible() const
521 nsWindow::ConstrainPosition(bool aAllowSlop
, int32_t *aX
, int32_t *aY
)
524 int32_t screenWidth
= QApplication::desktop()->width();
525 int32_t screenHeight
= QApplication::desktop()->height();
528 if (*aX
< (kWindowPositionSlop
- mBounds
.width
))
529 *aX
= kWindowPositionSlop
- mBounds
.width
;
530 if (*aX
> (screenWidth
- kWindowPositionSlop
))
531 *aX
= screenWidth
- kWindowPositionSlop
;
532 if (*aY
< (kWindowPositionSlop
- mBounds
.height
))
533 *aY
= kWindowPositionSlop
- mBounds
.height
;
534 if (*aY
> (screenHeight
- kWindowPositionSlop
))
535 *aY
= screenHeight
- kWindowPositionSlop
;
539 if (*aX
> (screenWidth
- mBounds
.width
))
540 *aX
= screenWidth
- mBounds
.width
;
543 if (*aY
> (screenHeight
- mBounds
.height
))
544 *aY
= screenHeight
- mBounds
.height
;
552 nsWindow::Move(double aX
, double aY
)
554 LOG(("nsWindow::Move [%p] %f %f\n", (void *)this,
557 int32_t x
= NSToIntRound(aX
);
558 int32_t y
= NSToIntRound(aY
);
561 SetSizeMode(nsSizeMode_Normal
);
564 if (x
== mBounds
.x
&& y
== mBounds
.y
)
572 QWidget
*widget
= GetViewWidget();
573 NS_ENSURE_TRUE(widget
, NS_OK
);
577 // the position of the widget is set relative to the parent
578 // so we map the coordinates accordingly
579 pos
= mWidget
->mapFromScene(pos
);
580 pos
= mWidget
->mapToParent(pos
);
581 mWidget
->setPos(pos
);
587 NotifyRollupGeometryChange();
592 nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement
,
596 return NS_ERROR_NOT_IMPLEMENTED
;
600 nsWindow::SetSizeMode(int32_t aMode
)
604 LOG(("nsWindow::SetSizeMode [%p] %d\n", (void *)this, aMode
));
605 if (aMode
!= nsSizeMode_Minimized
) {
606 GetViewWidget()->activateWindow();
609 // Save the requested state.
610 rv
= nsBaseWidget::SetSizeMode(aMode
);
612 // return if there's no shell or our current state is the same as
613 // the mode we were just set to.
614 if (!mWidget
|| mSizeState
== mSizeMode
) {
618 QWidget
*widget
= GetViewWidget();
619 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
622 case nsSizeMode_Maximized
:
623 widget
->showMaximized();
625 case nsSizeMode_Minimized
:
626 widget
->showMinimized();
628 case nsSizeMode_Fullscreen
:
629 widget
->showFullScreen();
633 // nsSizeMode_Normal, really.
634 widget
->showNormal();
638 mSizeState
= mSizeMode
;
643 // Helper function to recursively find the first parent item that
644 // is still visible (QGraphicsItem can be hidden even if they are
645 // set to visible if one of their ancestors is invisible)
646 static void find_first_visible_parent(QGraphicsItem
* aItem
, QGraphicsItem
*& aVisibleItem
)
648 NS_ENSURE_TRUE_VOID(aItem
);
650 aVisibleItem
= nullptr;
651 QGraphicsItem
* parItem
= nullptr;
652 while (!aVisibleItem
) {
653 if (aItem
->isVisible())
654 aVisibleItem
= aItem
;
656 parItem
= aItem
->parentItem();
660 aItem
->setVisible(true);
661 aVisibleItem
= aItem
;
668 nsWindow::SetFocus(bool aRaise
)
670 // Make sure that our owning widget has focus. If it doesn't try to
671 // grab it. Note that we don't set our focus flag in this case.
672 LOGFOCUS((" SetFocus [%p]\n", (void *)this));
675 return NS_ERROR_FAILURE
;
677 if (mWidget
->hasFocus())
680 // Because QGraphicsItem cannot get the focus if they are
681 // invisible, we look up the chain, for the lowest visible
682 // parent and focus that one
683 QGraphicsItem
* realFocusItem
= nullptr;
684 find_first_visible_parent(mWidget
, realFocusItem
);
686 if (!realFocusItem
|| realFocusItem
->hasFocus())
690 // the raising has to happen on the view widget
691 QWidget
*widget
= GetViewWidget();
694 realFocusItem
->setFocus(Qt::ActiveWindowFocusReason
);
697 realFocusItem
->setFocus(Qt::OtherFocusReason
);
699 // XXXndeakin why is this here? It should dispatch only when the OS
701 DispatchActivateEvent();
707 nsWindow::GetScreenBounds(nsIntRect
&aRect
)
709 aRect
= nsIntRect(nsIntPoint(0, 0), mBounds
.Size());
711 QWidget
*widget
= GetViewWidget();
712 NS_ENSURE_TRUE(widget
, NS_OK
);
713 QPoint pos
= widget
->pos();
714 aRect
.MoveTo(pos
.x(), pos
.y());
717 aRect
.MoveTo(WidgetToScreenOffset());
719 LOG(("GetScreenBounds %d %d | %d %d | %d %d\n",
721 mBounds
.width
, mBounds
.height
,
722 aRect
.width
, aRect
.height
));
727 nsWindow::SetForegroundColor(const nscolor
&aColor
)
729 return NS_ERROR_NOT_IMPLEMENTED
;
733 nsWindow::SetBackgroundColor(const nscolor
&aColor
)
735 return NS_ERROR_NOT_IMPLEMENTED
;
739 nsWindow::SetCursor(nsCursor aCursor
)
741 if (mCursor
== aCursor
)
746 mWidget
->SetCursor(mCursor
);
751 nsWindow::SetCursor(imgIContainer
* aCursor
,
752 uint32_t aHotspotX
, uint32_t aHotspotY
)
754 return NS_ERROR_NOT_AVAILABLE
;
758 nsWindow::Invalidate(const nsIntRect
&aRect
)
760 LOGDRAW(("Invalidate (rect) [%p,%p]: %d %d %d %d\n", (void *)this,
761 (void*)mWidget
,aRect
.x
, aRect
.y
, aRect
.width
, aRect
.height
));
766 mDirtyScrollArea
= mDirtyScrollArea
.united(QRect(aRect
.x
, aRect
.y
, aRect
.width
, aRect
.height
));
768 mWidget
->update(aRect
.x
, aRect
.y
, aRect
.width
, aRect
.height
);
773 // Returns the graphics view widget for this nsWindow by iterating
774 // the chain of parents until a toplevel window with a view/scene is found.
775 // (This function always returns something or asserts if the precondition
777 QWidget
* nsWindow::GetViewWidget()
779 NS_ASSERTION(mWidget
, "Calling GetViewWidget without mWidget created");
780 if (!mWidget
|| !mWidget
->scene() || !mWidget
->scene()->views().size())
783 NS_ASSERTION(mWidget
->scene()->views().size() == 1, "Not exactly one view for our scene!");
784 return mWidget
->scene()->views()[0];
788 nsWindow::GetNativeData(uint32_t aDataType
)
791 case NS_NATIVE_WINDOW
:
792 case NS_NATIVE_WIDGET
: {
800 case NS_NATIVE_PLUGIN_PORT
:
801 return SetupPluginPort();
804 case NS_NATIVE_DISPLAY
:
807 return gfxQtPlatform::GetXDisplay(GetViewWidget());
814 case NS_NATIVE_GRAPHIC
: {
819 case NS_NATIVE_SHELLWIDGET
: {
820 QWidget
* widget
= nullptr;
821 if (mWidget
&& mWidget
->scene())
822 widget
= mWidget
->scene()->views()[0]->viewport();
823 return (void *) widget
;
826 case NS_NATIVE_SHAREABLE_WINDOW
: {
827 QWidget
*widget
= GetViewWidget();
828 return widget
? (void*)widget
->winId() : nullptr;
832 NS_WARNING("nsWindow::GetNativeData called with bad value");
838 nsWindow::SetTitle(const nsAString
& aTitle
)
840 QString
qStr(QString::fromUtf16(aTitle
.BeginReading(), aTitle
.Length()));
842 QWidget
*widget
= GetViewWidget();
844 widget
->setWindowTitle(qStr
);
847 mWidget
->setWindowTitle(qStr
);
853 nsWindow::SetIcon(const nsAString
& aIconSpec
)
858 nsCOMPtr
<nsIFile
> iconFile
;
860 nsTArray
<nsCString
> iconList
;
862 // Look for icons with the following suffixes appended to the base name.
863 // The last two entries (for the old XPM format) will be ignored unless
864 // no icons are found using the other suffixes. XPM icons are depricated.
866 const char extensions
[6][7] = { ".png", "16.png", "32.png", "48.png",
869 for (uint32_t i
= 0; i
< ArrayLength(extensions
); i
++) {
870 // Don't bother looking for XPM versions if we found a PNG.
871 if (i
== ArrayLength(extensions
) - 2 && iconList
.Length())
874 nsAutoString extension
;
875 extension
.AppendASCII(extensions
[i
]);
877 ResolveIconName(aIconSpec
, extension
, getter_AddRefs(iconFile
));
879 iconFile
->GetNativePath(path
);
880 iconList
.AppendElement(path
);
884 // leave the default icon intact if no matching icons were found
885 if (iconList
.Length() == 0)
888 return SetWindowIconList(iconList
);
892 nsWindow::WidgetToScreenOffset()
894 NS_ENSURE_TRUE(mWidget
, nsIntPoint(0,0));
896 QPointF
origin(0, 0);
897 origin
= mWidget
->mapToScene(origin
);
899 return nsIntPoint(origin
.x(), origin
.y());
903 nsWindow::EnableDragDrop(bool aEnable
)
905 mWidget
->setAcceptDrops(aEnable
);
910 nsWindow::CaptureMouse(bool aCapture
)
912 LOG(("CaptureMouse %p\n", (void *)this));
917 QWidget
*widget
= GetViewWidget();
918 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
923 widget
->releaseMouse();
929 nsWindow::CaptureRollupEvents(nsIRollupListener
*aListener
,
935 LOG(("CaptureRollupEvents %p\n", (void *)this));
937 gRollupListener
= aDoCapture
? aListener
: nullptr;
942 nsWindow::CheckForRollup(double aMouseX
, double aMouseY
,
945 nsIRollupListener
* rollupListener
= GetActiveRollupListener();
946 nsCOMPtr
<nsIWidget
> rollupWidget
;
947 if (rollupListener
) {
948 rollupWidget
= rollupListener
->GetRollupWidget();
951 nsBaseWidget::gRollupListener
= nullptr;
956 MozQWidget
*currentPopup
=
957 (MozQWidget
*)rollupWidget
->GetNativeData(NS_NATIVE_WINDOW
);
958 if (!is_mouse_in_window(currentPopup
, aMouseX
, aMouseY
)) {
961 rollup
= rollupListener
->ShouldRollupOnMouseWheelEvent();
964 // if we're dealing with menus, we probably have submenus and
965 // we don't want to rollup if the clickis in a parent menu of
966 // the current submenu
967 uint32_t popupsToRollup
= UINT32_MAX
;
968 if (rollupListener
) {
969 nsAutoTArray
<nsIWidget
*, 5> widgetChain
;
970 uint32_t sameTypeCount
= rollupListener
->GetSubmenuWidgetChain(&widgetChain
);
971 for (uint32_t i
=0; i
<widgetChain
.Length(); ++i
) {
972 nsIWidget
* widget
= widgetChain
[i
];
973 MozQWidget
* currWindow
=
974 (MozQWidget
*) widget
->GetNativeData(NS_NATIVE_WINDOW
);
975 if (is_mouse_in_window(currWindow
, aMouseX
, aMouseY
)) {
976 if (i
< sameTypeCount
) {
980 popupsToRollup
= sameTypeCount
;
984 } // foreach parent menu widget
985 } // if rollup listener knows about menus
987 // if we've determined that we should still rollup, do it.
989 retVal
= rollupListener
->Rollup(popupsToRollup
, nullptr);
998 is_mouse_in_window (MozQWidget
* aWindow
, double aMouseX
, double aMouseY
)
1000 return aWindow
->geometry().contains( aMouseX
, aMouseY
);
1004 nsWindow::GetAttention(int32_t aCycleCount
)
1006 LOG(("nsWindow::GetAttention [%p]\n", (void *)this));
1007 return NS_ERROR_NOT_IMPLEMENTED
;
1011 static already_AddRefed
<gfxASurface
>
1012 GetSurfaceForQWidget(QWidget
* aDrawable
)
1014 gfxASurface
* result
=
1015 new gfxXlibSurface(gfxQtPlatform::GetXDisplay(aDrawable
),
1017 DefaultVisualOfScreen(gfxQtPlatform::GetXScreen(aDrawable
)),
1018 gfxIntSize(aDrawable
->size().width(),
1019 aDrawable
->size().height()));
1020 NS_IF_ADDREF(result
);
1026 nsWindow::DoPaint(QPainter
* aPainter
, const QStyleOptionGraphicsItem
* aOption
, QWidget
* aWidget
)
1029 LOG(("Expose event on destroyed window [%p] window %p\n",
1030 (void *)this, mWidget
));
1034 // Call WillPaintWindow to allow scripts etc. to run before we paint
1036 if (mWidgetListener
)
1037 mWidgetListener
->WillPaintWindow(this);
1045 r
= aOption
->exposedRect
;
1047 r
= mWidget
->boundingRect();
1050 return nsEventStatus_eIgnore
;
1052 if (!mDirtyScrollArea
.isEmpty())
1053 mDirtyScrollArea
= QRegion();
1055 bool painted
= false;
1056 nsIntRect
rect(r
.x(), r
.y(), r
.width(), r
.height());
1058 nsFastStartup
* startup
= nsFastStartup::GetSingleton();
1060 startup
->RemoveFakeLayout();
1063 if (GetLayerManager(nullptr)->GetBackendType() == mozilla::layers::LAYERS_OPENGL
) {
1064 aPainter
->beginNativePainting();
1065 nsIntRegion
region(rect
);
1066 static_cast<mozilla::layers::LayerManagerOGL
*>(GetLayerManager(nullptr))->
1067 SetClippingRegion(region
);
1070 matr
.Translate(gfxPoint(aPainter
->transform().dx(), aPainter
->transform().dy()));
1071 #ifdef MOZ_ENABLE_QTMOBILITY
1072 // This is needed for rotate transformation on MeeGo
1073 // This will work very slow if pixman does not handle rotation very well
1074 matr
.Rotate((M_PI
/180) * gOrientationFilter
.GetWindowRotationAngle());
1075 static_cast<mozilla::layers::LayerManagerOGL
*>(GetLayerManager(nullptr))->
1076 SetWorldTransform(matr
);
1077 #endif //MOZ_ENABLE_QTMOBILITY
1079 if (mWidgetListener
)
1080 painted
= mWidgetListener
->PaintWindow(this, region
, 0);
1081 aPainter
->endNativePainting();
1082 if (mWidgetListener
)
1083 mWidgetListener
->DidPaintWindow();
1087 gfxQtPlatform::RenderMode renderMode
= gfxQtPlatform::GetPlatform()->GetRenderMode();
1088 int depth
= aPainter
->device()->depth();
1090 nsRefPtr
<gfxASurface
> targetSurface
= nullptr;
1091 if (renderMode
== gfxQtPlatform::RENDER_BUFFERED
) {
1092 // Prepare offscreen buffers iamge or xlib, depends from paintEngineType
1093 if (!UpdateOffScreenBuffers(depth
, QSize(r
.width(), r
.height())))
1096 targetSurface
= gBufferSurface
;
1098 #ifdef CAIRO_HAS_QT_SURFACE
1099 } else if (renderMode
== gfxQtPlatform::RENDER_QPAINTER
) {
1100 targetSurface
= new gfxQPainterSurface(aPainter
);
1102 } else if (renderMode
== gfxQtPlatform::RENDER_DIRECT
) {
1103 if (!UpdateOffScreenBuffers(depth
, aWidget
->size(), aWidget
)) {
1106 targetSurface
= gBufferSurface
;
1109 if (MOZ_UNLIKELY(!targetSurface
))
1112 nsRefPtr
<gfxContext
> ctx
= new gfxContext(targetSurface
);
1114 // We will paint to 0, 0 position in offscrenn buffer
1115 if (renderMode
== gfxQtPlatform::RENDER_BUFFERED
) {
1116 ctx
->Translate(gfxPoint(-r
.x(), -r
.y()));
1118 else if (renderMode
== gfxQtPlatform::RENDER_DIRECT
) {
1120 matr
.Translate(gfxPoint(aPainter
->transform().dx(), aPainter
->transform().dy()));
1121 #ifdef MOZ_ENABLE_QTMOBILITY
1122 // This is needed for rotate transformation on MeeGo
1123 // This will work very slow if pixman does not handle rotation very well
1124 matr
.Rotate((M_PI
/180) * gOrientationFilter
.GetWindowRotationAngle());
1125 NS_ASSERTION(PIXMAN_VERSION
> PIXMAN_VERSION_ENCODE(0, 21, 2) ||
1126 !gOrientationFilter
.GetWindowRotationAngle(),
1127 "Old pixman and rotate transform, it is going to be slow");
1128 #endif //MOZ_ENABLE_QTMOBILITY
1130 ctx
->SetMatrix(matr
);
1134 AutoLayerManagerSetup
1135 setupLayerManager(this, ctx
, mozilla::layers::BUFFER_NONE
);
1136 if (mWidgetListener
) {
1137 nsIntRegion
region(rect
);
1138 painted
= mWidgetListener
->PaintWindow(this, region
, 0);
1142 // DispatchEvent can Destroy us (bug 378273), avoid doing any paint
1143 // operations below if that happened - it will lead to XError and exit().
1144 if (MOZ_UNLIKELY(mIsDestroyed
))
1150 LOGDRAW(("[%p] draw done\n", this));
1152 // Handle buffered painting mode
1153 if (renderMode
== gfxQtPlatform::RENDER_BUFFERED
) {
1154 #if defined(MOZ_X11) && defined(Q_WS_X11)
1155 if (gBufferSurface
->GetType() == gfxASurface::SurfaceTypeXlib
) {
1156 // Paint offscreen pixmap to QPainter
1157 static QPixmap gBufferPixmap
;
1158 Drawable draw
= static_cast<gfxXlibSurface
*>(gBufferSurface
.get())->XDrawable();
1159 if (gBufferPixmap
.handle() != draw
)
1160 gBufferPixmap
= QPixmap::fromX11Pixmap(draw
, QPixmap::ExplicitlyShared
);
1161 XSync(static_cast<gfxXlibSurface
*>(gBufferSurface
.get())->XDisplay(), False
);
1162 aPainter
->drawPixmap(QPoint(rect
.x
, rect
.y
), gBufferPixmap
,
1163 QRect(0, 0, rect
.width
, rect
.height
));
1167 if (gBufferSurface
->GetType() == gfxASurface::SurfaceTypeImage
) {
1168 // in raster mode we can just wrap gBufferImage as QImage and paint directly
1169 gfxImageSurface
*imgs
= static_cast<gfxImageSurface
*>(gBufferSurface
.get());
1170 QImage
img(imgs
->Data(),
1174 _gfximage_to_qformat(imgs
->Format()));
1175 aPainter
->drawImage(QPoint(rect
.x
, rect
.y
), img
,
1176 QRect(0, 0, rect
.width
, rect
.height
));
1178 } else if (renderMode
== gfxQtPlatform::RENDER_DIRECT
) {
1179 QRect trans
= aPainter
->transform().mapRect(r
).toRect();
1181 if (gBufferSurface
->GetType() == gfxASurface::SurfaceTypeXlib
) {
1182 nsRefPtr
<gfxASurface
> widgetSurface
= GetSurfaceForQWidget(aWidget
);
1183 nsRefPtr
<gfxContext
> ctx
= new gfxContext(widgetSurface
);
1184 ctx
->SetSource(gBufferSurface
);
1185 ctx
->Rectangle(gfxRect(trans
.x(), trans
.y(), trans
.width(), trans
.height()), true);
1190 if (gBufferSurface
->GetType() == gfxASurface::SurfaceTypeImage
) {
1191 #ifdef MOZ_HAVE_SHMIMAGE
1193 gShmImage
->Put(aWidget
, trans
);
1197 // Qt should take care about optimized rendering on QImage into painter device (gl/fb/image et.c.)
1198 gfxImageSurface
*imgs
= static_cast<gfxImageSurface
*>(gBufferSurface
.get());
1199 QImage
img(imgs
->Data(),
1203 _gfximage_to_qformat(imgs
->Format()));
1204 aPainter
->drawImage(trans
, img
, trans
);
1210 targetSurface
= nullptr;
1211 if (mWidgetListener
)
1212 mWidgetListener
->DidPaintWindow();
1214 // check the return value!
1219 nsWindow::OnMoveEvent(QGraphicsSceneHoverEvent
*aEvent
)
1221 LOG(("configure event [%p] %d %d\n", (void *)this,
1222 aEvent
->pos().x(), aEvent
->pos().y()));
1225 if (!mWidget
|| !mWidgetListener
)
1226 return nsEventStatus_eIgnore
;
1228 if ((mBounds
.x
== aEvent
->pos().x() &&
1229 mBounds
.y
== aEvent
->pos().y()))
1231 return nsEventStatus_eIgnore
;
1234 bool moved
= mWidgetListener
->WindowMoved(this, aEvent
->pos().x(), aEvent
->pos().y());
1235 return moved
? nsEventStatus_eConsumeNoDefault
: nsEventStatus_eIgnore
;
1239 nsWindow::OnResizeEvent(QGraphicsSceneResizeEvent
*aEvent
)
1243 // Generate XPFE resize event
1246 rect
.width
= aEvent
->newSize().width();
1247 rect
.height
= aEvent
->newSize().height();
1249 mBounds
.width
= rect
.width
;
1250 mBounds
.height
= rect
.height
;
1252 nsEventStatus status
;
1253 DispatchResizeEvent(rect
, status
);
1258 nsWindow::OnCloseEvent(QCloseEvent
*aEvent
)
1260 if (!mWidgetListener
)
1261 return nsEventStatus_eIgnore
;
1262 mWidgetListener
->RequestWindowClose(this);
1263 return nsEventStatus_eConsumeNoDefault
;
1267 nsWindow::OnEnterNotifyEvent(QGraphicsSceneHoverEvent
*aEvent
)
1269 nsMouseEvent
event(true, NS_MOUSE_ENTER
, this, nsMouseEvent::eReal
);
1271 event
.refPoint
.x
= nscoord(aEvent
->pos().x());
1272 event
.refPoint
.y
= nscoord(aEvent
->pos().y());
1274 LOG(("OnEnterNotify: %p\n", (void *)this));
1276 return DispatchEvent(&event
);
1280 nsWindow::OnLeaveNotifyEvent(QGraphicsSceneHoverEvent
*aEvent
)
1282 nsMouseEvent
event(true, NS_MOUSE_EXIT
, this, nsMouseEvent::eReal
);
1284 event
.refPoint
.x
= nscoord(aEvent
->pos().x());
1285 event
.refPoint
.y
= nscoord(aEvent
->pos().y());
1287 LOG(("OnLeaveNotify: %p\n", (void *)this));
1289 return DispatchEvent(&event
);
1292 // Block the mouse events if user was recently executing gestures;
1293 // otherwise there will be also some panning during/after gesture
1294 #if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 0))
1295 #define CHECK_MOUSE_BLOCKED { \
1296 if (mLastMultiTouchTime.isValid()) { \
1297 if (mLastMultiTouchTime.elapsed() < GESTURES_BLOCK_MOUSE_FOR) \
1298 return nsEventStatus_eIgnore; \
1300 mLastMultiTouchTime = QTime(); \
1304 define CHECK_MOUSE_BLOCKED
{}
1308 nsWindow::OnMotionNotifyEvent(QPointF aPos
, Qt::KeyboardModifiers aModifiers
)
1314 mMoveEvent
.pos
= aPos
;
1315 mMoveEvent
.modifiers
= aModifiers
;
1316 mMoveEvent
.needDispatch
= true;
1317 DispatchMotionToMainThread();
1319 return nsEventStatus_eIgnore
;
1323 nsWindow::InitButtonEvent(nsMouseEvent
&aMoveEvent
,
1324 QGraphicsSceneMouseEvent
*aEvent
, int aClickCount
)
1326 aMoveEvent
.refPoint
.x
= nscoord(aEvent
->pos().x());
1327 aMoveEvent
.refPoint
.y
= nscoord(aEvent
->pos().y());
1329 aMoveEvent
.InitBasicModifiers(aEvent
->modifiers() & Qt::ControlModifier
,
1330 aEvent
->modifiers() & Qt::AltModifier
,
1331 aEvent
->modifiers() & Qt::ShiftModifier
,
1332 aEvent
->modifiers() & Qt::MetaModifier
);
1333 aMoveEvent
.clickCount
= aClickCount
;
1337 nsWindow::OnButtonPressEvent(QGraphicsSceneMouseEvent
*aEvent
)
1339 // The user has done something.
1344 QPointF pos
= aEvent
->pos();
1346 // we check against the widgets geometry, so use parent coordinates
1349 pos
= mWidget
->mapToParent(pos
);
1351 if (CheckForRollup( pos
.x(), pos
.y(), false))
1352 return nsEventStatus_eIgnore
;
1355 switch (aEvent
->button()) {
1357 domButton
= nsMouseEvent::eMiddleButton
;
1359 case Qt::RightButton
:
1360 domButton
= nsMouseEvent::eRightButton
;
1363 domButton
= nsMouseEvent::eLeftButton
;
1367 nsMouseEvent
event(true, NS_MOUSE_BUTTON_DOWN
, this, nsMouseEvent::eReal
);
1368 event
.button
= domButton
;
1369 InitButtonEvent(event
, aEvent
, 1);
1371 LOG(("%s [%p] button: %d\n", __PRETTY_FUNCTION__
, (void*)this, domButton
));
1373 nsEventStatus status
= DispatchEvent(&event
);
1375 // right menu click on linux should also pop up a context menu
1376 if (domButton
== nsMouseEvent::eRightButton
&&
1377 MOZ_LIKELY(!mIsDestroyed
)) {
1378 nsMouseEvent
contextMenuEvent(true, NS_CONTEXTMENU
, this,
1379 nsMouseEvent::eReal
);
1380 InitButtonEvent(contextMenuEvent
, aEvent
, 1);
1381 DispatchEvent(&contextMenuEvent
, status
);
1388 nsWindow::OnButtonReleaseEvent(QGraphicsSceneMouseEvent
*aEvent
)
1393 // The user has done something.
1398 switch (aEvent
->button()) {
1400 domButton
= nsMouseEvent::eMiddleButton
;
1402 case Qt::RightButton
:
1403 domButton
= nsMouseEvent::eRightButton
;
1406 domButton
= nsMouseEvent::eLeftButton
;
1410 LOG(("%s [%p] button: %d\n", __PRETTY_FUNCTION__
, (void*)this, domButton
));
1412 nsMouseEvent
event(true, NS_MOUSE_BUTTON_UP
, this, nsMouseEvent::eReal
);
1413 event
.button
= domButton
;
1414 InitButtonEvent(event
, aEvent
, 1);
1416 nsEventStatus status
= DispatchEvent(&event
);
1422 nsWindow::OnMouseDoubleClickEvent(QGraphicsSceneMouseEvent
*aEvent
)
1426 switch (aEvent
->button()) {
1428 eventType
= nsMouseEvent::eMiddleButton
;
1430 case Qt::RightButton
:
1431 eventType
= nsMouseEvent::eRightButton
;
1434 eventType
= nsMouseEvent::eLeftButton
;
1438 nsMouseEvent
event(true, NS_MOUSE_DOUBLECLICK
, this, nsMouseEvent::eReal
);
1439 event
.button
= eventType
;
1441 InitButtonEvent(event
, aEvent
, 2);
1443 return DispatchEvent(&event
);
1447 nsWindow::OnFocusInEvent(QEvent
*aEvent
)
1449 LOGFOCUS(("OnFocusInEvent [%p]\n", (void *)this));
1452 return nsEventStatus_eIgnore
;
1454 DispatchActivateEventOnTopLevelWindow();
1456 LOGFOCUS(("Events sent from focus in event [%p]\n", (void *)this));
1457 return nsEventStatus_eIgnore
;
1461 nsWindow::OnFocusOutEvent(QEvent
*aEvent
)
1463 LOGFOCUS(("OnFocusOutEvent [%p]\n", (void *)this));
1466 return nsEventStatus_eIgnore
;
1468 #if MOZ_PLATFORM_MAEMO > 5
1469 if (((QFocusEvent
*)aEvent
)->reason() == Qt::OtherFocusReason
1470 && mWidget
->isVKBOpen()) {
1471 // We assume that the VKB was open in this case, because of the focus
1472 // reason and clear the focus in the active window.
1473 nsCOMPtr
<nsIFocusManager
> fm
= do_GetService("@mozilla.org/focus-manager;1");
1475 nsCOMPtr
<nsIDOMWindow
> domWindow
;
1476 fm
->GetActiveWindow(getter_AddRefs(domWindow
));
1477 fm
->ClearFocus(domWindow
);
1480 return nsEventStatus_eIgnore
;
1484 DispatchDeactivateEventOnTopLevelWindow();
1486 LOGFOCUS(("Done with container focus out [%p]\n", (void *)this));
1487 return nsEventStatus_eIgnore
;
1491 is_latin_shortcut_key(quint32 aKeyval
)
1493 return ((Qt::Key_0
<= aKeyval
&& aKeyval
<= Qt::Key_9
) ||
1494 (Qt::Key_A
<= aKeyval
&& aKeyval
<= Qt::Key_Z
));
1498 nsWindow::DispatchCommandEvent(nsIAtom
* aCommand
)
1500 nsCommandEvent
event(true, nsGkAtoms::onAppCommand
, aCommand
, this);
1502 nsEventStatus status
;
1503 DispatchEvent(&event
, status
);
1509 nsWindow::DispatchContentCommandEvent(int32_t aMsg
)
1511 nsContentCommandEvent
event(true, aMsg
, this);
1513 nsEventStatus status
;
1514 DispatchEvent(&event
, status
);
1520 nsWindow::OnKeyPressEvent(QKeyEvent
*aEvent
)
1522 LOGFOCUS(("OnKeyPressEvent [%p]\n", (void *)this));
1524 // The user has done something.
1527 bool setNoDefault
= false;
1529 if (aEvent
->key() == Qt::Key_AltGr
) {
1530 sAltGrModifier
= true;
1534 // before we dispatch a key, check if it's the context menu key.
1535 // If so, send a context menu key event instead.
1536 if (isContextMenuKeyEvent(aEvent
)) {
1537 nsMouseEvent
contextMenuEvent(true, NS_CONTEXTMENU
, this,
1538 nsMouseEvent::eReal
,
1539 nsMouseEvent::eContextMenuKey
);
1540 //keyEventToContextMenuEvent(&event, &contextMenuEvent);
1541 return DispatchEvent(&contextMenuEvent
);
1544 uint32_t domCharCode
= 0;
1545 uint32_t domKeyCode
= QtKeyCodeToDOMKeyCode(aEvent
->key());
1547 // get keymap and modifier map from the Xserver
1548 Display
*display
= mozilla::DefaultXDisplay();
1549 int x_min_keycode
= 0, x_max_keycode
= 0, xkeysyms_per_keycode
;
1550 XDisplayKeycodes(display
, &x_min_keycode
, &x_max_keycode
);
1551 XModifierKeymap
*xmodmap
= XGetModifierMapping(display
);
1553 return nsEventStatus_eIgnore
;
1555 KeySym
*xkeymap
= XGetKeyboardMapping(display
, x_min_keycode
, x_max_keycode
- x_min_keycode
,
1556 &xkeysyms_per_keycode
);
1558 XFreeModifiermap(xmodmap
);
1559 return nsEventStatus_eIgnore
;
1562 // create modifier masks
1563 qint32 shift_mask
= 0, shift_lock_mask
= 0, caps_lock_mask
= 0, num_lock_mask
= 0;
1565 for (int i
= 0; i
< 8 * xmodmap
->max_keypermod
; ++i
) {
1566 qint32 maskbit
= 1 << (i
/ xmodmap
->max_keypermod
);
1567 KeyCode modkeycode
= xmodmap
->modifiermap
[i
];
1568 if (modkeycode
== NoSymbol
) {
1572 quint32 mapindex
= (modkeycode
- x_min_keycode
) * xkeysyms_per_keycode
;
1573 for (int j
= 0; j
< xkeysyms_per_keycode
; ++j
) {
1574 KeySym modkeysym
= xkeymap
[mapindex
+ j
];
1575 switch (modkeysym
) {
1577 num_lock_mask
|= maskbit
;
1580 caps_lock_mask
|= maskbit
;
1583 shift_lock_mask
|= maskbit
;
1587 shift_mask
|= maskbit
;
1592 // indicate whether is down or not
1593 bool shift_state
= ((shift_mask
& aEvent
->nativeModifiers()) != 0) ^
1594 (bool)(shift_lock_mask
& aEvent
->nativeModifiers());
1595 bool capslock_state
= (bool)(caps_lock_mask
& aEvent
->nativeModifiers());
1597 // try to find a keysym that we can translate to a DOMKeyCode
1598 // this is needed because some of Qt's keycodes cannot be translated
1599 // TODO: use US keyboard keymap instead of localised keymap
1601 aEvent
->nativeScanCode() >= (quint32
)x_min_keycode
&&
1602 aEvent
->nativeScanCode() <= (quint32
)x_max_keycode
) {
1603 int index
= (aEvent
->nativeScanCode() - x_min_keycode
) * xkeysyms_per_keycode
;
1604 for(int i
= 0; (i
< xkeysyms_per_keycode
) && (domKeyCode
== (quint32
)NoSymbol
); ++i
) {
1605 domKeyCode
= QtKeyCodeToDOMKeyCode(xkeymap
[index
+ i
]);
1609 // store character in domCharCode
1610 if (aEvent
->text().length() && aEvent
->text()[0].isPrint())
1611 domCharCode
= (int32_t) aEvent
->text()[0].unicode();
1613 KeyNameIndex keyNameIndex
=
1614 domCharCode
? KEY_NAME_INDEX_PrintableKey
:
1615 QtKeyCodeToDOMKeyNameIndex(aEvent
->key());
1617 // If the key isn't autorepeat, we need to send the initial down event
1618 if (!aEvent
->isAutoRepeat() && !IsKeyDown(domKeyCode
)) {
1619 // send the key down event
1621 SetKeyDownFlag(domKeyCode
);
1623 nsKeyEvent
downEvent(true, NS_KEY_DOWN
, this);
1624 InitKeyEvent(downEvent
, aEvent
);
1626 downEvent
.keyCode
= domKeyCode
;
1627 downEvent
.mKeyNameIndex
= keyNameIndex
;
1629 nsEventStatus status
= DispatchEvent(&downEvent
);
1631 // DispatchEvent can Destroy us (bug 378273)
1632 if (MOZ_UNLIKELY(mIsDestroyed
)) {
1633 qWarning() << "Returning[" << __LINE__
<< "]: " << "Window destroyed";
1637 // If prevent default on keydown, do same for keypress
1638 if (status
== nsEventStatus_eConsumeNoDefault
)
1639 setNoDefault
= true;
1642 // Don't pass modifiers as NS_KEY_PRESS events.
1643 // Instead of selectively excluding some keys from NS_KEY_PRESS events,
1644 // we instead selectively include (as per MSDN spec
1645 // ( http://msdn.microsoft.com/en-us/library/system.windows.forms.control.keypress%28VS.71%29.aspx );
1646 // no official spec covers KeyPress events).
1647 if (aEvent
->key() == Qt::Key_Shift
||
1648 aEvent
->key() == Qt::Key_Control
||
1649 aEvent
->key() == Qt::Key_Meta
||
1650 aEvent
->key() == Qt::Key_Alt
||
1651 aEvent
->key() == Qt::Key_AltGr
) {
1653 return setNoDefault
?
1654 nsEventStatus_eConsumeNoDefault
:
1655 nsEventStatus_eIgnore
;
1658 // Look for specialized app-command keys
1659 switch (aEvent
->key()) {
1661 return DispatchCommandEvent(nsGkAtoms::Back
);
1662 case Qt::Key_Forward
:
1663 return DispatchCommandEvent(nsGkAtoms::Forward
);
1664 case Qt::Key_Refresh
:
1665 return DispatchCommandEvent(nsGkAtoms::Reload
);
1667 return DispatchCommandEvent(nsGkAtoms::Stop
);
1668 case Qt::Key_Search
:
1669 return DispatchCommandEvent(nsGkAtoms::Search
);
1670 case Qt::Key_Favorites
:
1671 return DispatchCommandEvent(nsGkAtoms::Bookmarks
);
1672 case Qt::Key_HomePage
:
1673 return DispatchCommandEvent(nsGkAtoms::Home
);
1675 case Qt::Key_F16
: // F16, F20, F18, F14 are old keysyms for Copy Cut Paste Undo
1676 return DispatchContentCommandEvent(NS_CONTENT_COMMAND_COPY
);
1679 return DispatchContentCommandEvent(NS_CONTENT_COMMAND_CUT
);
1683 return DispatchContentCommandEvent(NS_CONTENT_COMMAND_PASTE
);
1685 return DispatchContentCommandEvent(NS_CONTENT_COMMAND_UNDO
);
1688 // Qt::Key_Redo and Qt::Key_Undo are not available yet.
1689 if (aEvent
->nativeVirtualKey() == 0xff66) {
1690 return DispatchContentCommandEvent(NS_CONTENT_COMMAND_REDO
);
1692 if (aEvent
->nativeVirtualKey() == 0xff65) {
1693 return DispatchContentCommandEvent(NS_CONTENT_COMMAND_UNDO
);
1696 nsKeyEvent
event(true, NS_KEY_PRESS
, this);
1697 InitKeyEvent(event
, aEvent
);
1699 // If prevent default on keydown, do same for keypress
1701 event
.mFlags
.mDefaultPrevented
= true;
1704 // If there is no charcode attainable from the text, try to
1705 // generate it from the keycode. Check shift state for case
1706 // Also replace the charcode if ControlModifier is the only
1708 if ((!domCharCode
) &&
1709 (QApplication::keyboardModifiers() &
1710 (Qt::ControlModifier
| Qt::AltModifier
| Qt::MetaModifier
))) {
1712 // get a character from X11 key map
1713 KeySym keysym
= aEvent
->nativeVirtualKey();
1715 domCharCode
= (uint32_t) keysym2ucs(keysym
);
1716 if (domCharCode
== -1 || !QChar((quint32
)domCharCode
).isPrint()) {
1721 // if Ctrl is pressed and domCharCode is not a ASCII character
1722 if (domCharCode
> 0xFF && (QApplication::keyboardModifiers() & Qt::ControlModifier
)) {
1723 // replace Unicode character
1724 int index
= (aEvent
->nativeScanCode() - x_min_keycode
) * xkeysyms_per_keycode
;
1725 for (int i
= 0; i
< xkeysyms_per_keycode
; ++i
) {
1726 if (xkeymap
[index
+ i
] <= 0xFF && !shift_state
) {
1727 domCharCode
= (uint32_t) QChar::toLower((uint
) xkeymap
[index
+ i
]);
1733 } else { // The key event should cause a character input.
1734 // At that time, we need to reset the modifiers
1735 // because nsEditor will not accept a key event
1736 // for text input if one or more modifiers are set.
1737 event
.modifiers
&= ~(widget::MODIFIER_CONTROL
|
1738 widget::MODIFIER_ALT
|
1739 widget::MODIFIER_META
);
1742 KeySym keysym
= NoSymbol
;
1743 int index
= (aEvent
->nativeScanCode() - x_min_keycode
) * xkeysyms_per_keycode
;
1744 for (int i
= 0; i
< xkeysyms_per_keycode
; ++i
) {
1745 if (xkeymap
[index
+ i
] == aEvent
->nativeVirtualKey()) {
1746 if ((i
% 2) == 0) { // shifted char
1747 keysym
= xkeymap
[index
+ i
+ 1];
1749 } else { // unshifted char
1750 keysym
= xkeymap
[index
+ i
- 1];
1754 if (xkeysyms_per_keycode
- 1 == i
) {
1755 qWarning() << "Symbol '" << aEvent
->nativeVirtualKey() << "' not found";
1758 QChar
unshiftedChar(domCharCode
);
1759 long ucs
= keysym2ucs(keysym
);
1760 ucs
= ucs
== -1 ? 0 : ucs
;
1761 QChar
shiftedChar((uint
)ucs
);
1763 // append alternativeCharCodes if modifier is pressed
1764 // append an additional alternativeCharCodes if domCharCode is not a Latin character
1765 // and if one of these modifiers is pressed (i.e. Ctrl, Alt, Meta)
1767 (QApplication::keyboardModifiers() &
1768 (Qt::ControlModifier
| Qt::AltModifier
| Qt::MetaModifier
))) {
1770 event
.charCode
= domCharCode
;
1772 nsAlternativeCharCode
altCharCode(0, 0);
1773 // if character has a lower and upper representation
1774 if ((unshiftedChar
.isUpper() || unshiftedChar
.isLower()) &&
1775 unshiftedChar
.toLower() == shiftedChar
.toLower()) {
1776 if (shift_state
^ capslock_state
) {
1777 altCharCode
.mUnshiftedCharCode
= (uint32_t) QChar::toUpper((uint
)domCharCode
);
1778 altCharCode
.mShiftedCharCode
= (uint32_t) QChar::toLower((uint
)domCharCode
);
1780 altCharCode
.mUnshiftedCharCode
= (uint32_t) QChar::toLower((uint
)domCharCode
);
1781 altCharCode
.mShiftedCharCode
= (uint32_t) QChar::toUpper((uint
)domCharCode
);
1784 altCharCode
.mUnshiftedCharCode
= (uint32_t) unshiftedChar
.unicode();
1785 altCharCode
.mShiftedCharCode
= (uint32_t) shiftedChar
.unicode();
1788 // append alternative char code to event
1789 if ((altCharCode
.mUnshiftedCharCode
&& altCharCode
.mUnshiftedCharCode
!= domCharCode
) ||
1790 (altCharCode
.mShiftedCharCode
&& altCharCode
.mShiftedCharCode
!= domCharCode
)) {
1791 event
.alternativeCharCodes
.AppendElement(altCharCode
);
1794 // check if the alternative char codes are latin-1
1795 if (altCharCode
.mUnshiftedCharCode
> 0xFF || altCharCode
.mShiftedCharCode
> 0xFF) {
1796 altCharCode
.mUnshiftedCharCode
= altCharCode
.mShiftedCharCode
= 0;
1798 // find latin char for keycode
1799 KeySym keysym
= NoSymbol
;
1800 int index
= (aEvent
->nativeScanCode() - x_min_keycode
) * xkeysyms_per_keycode
;
1801 // find first shifted and unshifted Latin-Char in XKeyMap
1802 for (int i
= 0; i
< xkeysyms_per_keycode
; ++i
) {
1803 keysym
= xkeymap
[index
+ i
];
1804 if (keysym
&& keysym
<= 0xFF) {
1805 if ((shift_state
&& (i
% 2 == 1)) ||
1806 (!shift_state
&& (i
% 2 == 0))) {
1807 altCharCode
.mUnshiftedCharCode
= altCharCode
.mUnshiftedCharCode
?
1808 altCharCode
.mUnshiftedCharCode
:
1811 altCharCode
.mShiftedCharCode
= altCharCode
.mShiftedCharCode
?
1812 altCharCode
.mShiftedCharCode
:
1815 if (altCharCode
.mUnshiftedCharCode
&& altCharCode
.mShiftedCharCode
) {
1821 if (altCharCode
.mUnshiftedCharCode
|| altCharCode
.mShiftedCharCode
) {
1822 event
.alternativeCharCodes
.AppendElement(altCharCode
);
1826 event
.charCode
= domCharCode
;
1830 XFreeModifiermap(xmodmap
);
1836 event
.keyCode
= domCharCode
? 0 : domKeyCode
;
1837 event
.mKeyNameIndex
= keyNameIndex
;
1838 // send the key press event
1839 return DispatchEvent(&event
);
1842 //:TODO: fix shortcuts hebrew for non X11,
1843 //see Bug 562195##51
1845 // before we dispatch a key, check if it's the context menu key.
1846 // If so, send a context menu key event instead.
1847 if (isContextMenuKeyEvent(aEvent
)) {
1848 nsMouseEvent
contextMenuEvent(true, NS_CONTEXTMENU
, this,
1849 nsMouseEvent::eReal
,
1850 nsMouseEvent::eContextMenuKey
);
1851 //keyEventToContextMenuEvent(&event, &contextMenuEvent);
1852 return DispatchEvent(&contextMenuEvent
);
1855 uint32_t domCharCode
= 0;
1856 uint32_t domKeyCode
= QtKeyCodeToDOMKeyCode(aEvent
->key());
1858 if (aEvent
->text().length() && aEvent
->text()[0].isPrint())
1859 domCharCode
= (int32_t) aEvent
->text()[0].unicode();
1861 KeyNameIndex keyNameIndex
=
1862 domCharCode
? KEY_NAME_INDEX_PrintableKey
:
1863 QtKeyCodeToDOMKeyNameIndex(aEvent
->key());
1865 // If the key isn't autorepeat, we need to send the initial down event
1866 if (!aEvent
->isAutoRepeat() && !IsKeyDown(domKeyCode
)) {
1867 // send the key down event
1869 SetKeyDownFlag(domKeyCode
);
1871 nsKeyEvent
downEvent(true, NS_KEY_DOWN
, this);
1872 InitKeyEvent(downEvent
, aEvent
);
1874 downEvent
.keyCode
= domKeyCode
;
1875 downEvent
.mKeyNameIndex
= keyNameIndex
;
1877 nsEventStatus status
= DispatchEvent(&downEvent
);
1879 // If prevent default on keydown, do same for keypress
1880 if (status
== nsEventStatus_eConsumeNoDefault
)
1881 setNoDefault
= true;
1884 nsKeyEvent
event(true, NS_KEY_PRESS
, this);
1885 InitKeyEvent(event
, aEvent
);
1887 event
.charCode
= domCharCode
;
1889 event
.keyCode
= domCharCode
? 0 : domKeyCode
;
1890 event
.mKeyNameIndex
= keyNameIndex
;
1893 event
.mFlags
.mDefaultPrevented
= true;
1895 // send the key press event
1896 return DispatchEvent(&event
);
1901 nsWindow::OnKeyReleaseEvent(QKeyEvent
*aEvent
)
1903 LOGFOCUS(("OnKeyReleaseEvent [%p]\n", (void *)this));
1905 // The user has done something.
1908 if (isContextMenuKeyEvent(aEvent
)) {
1909 // er, what do we do here? DoDefault or NoDefault?
1910 return nsEventStatus_eConsumeDoDefault
;
1913 uint32_t domKeyCode
= QtKeyCodeToDOMKeyCode(aEvent
->key());
1917 // get keymap from the Xserver
1918 Display
*display
= mozilla::DefaultXDisplay();
1919 int x_min_keycode
= 0, x_max_keycode
= 0, xkeysyms_per_keycode
;
1920 XDisplayKeycodes(display
, &x_min_keycode
, &x_max_keycode
);
1921 KeySym
*xkeymap
= XGetKeyboardMapping(display
, x_min_keycode
, x_max_keycode
- x_min_keycode
,
1922 &xkeysyms_per_keycode
);
1924 if (aEvent
->nativeScanCode() >= (quint32
)x_min_keycode
&&
1925 aEvent
->nativeScanCode() <= (quint32
)x_max_keycode
) {
1926 int index
= (aEvent
->nativeScanCode() - x_min_keycode
) * xkeysyms_per_keycode
;
1927 for(int i
= 0; (i
< xkeysyms_per_keycode
) && (domKeyCode
== (quint32
)NoSymbol
); ++i
) {
1928 domKeyCode
= QtKeyCodeToDOMKeyCode(xkeymap
[index
+ i
]);
1938 // send the key event as a key up event
1939 nsKeyEvent
event(true, NS_KEY_UP
, this);
1940 InitKeyEvent(event
, aEvent
);
1942 if (aEvent
->key() == Qt::Key_AltGr
) {
1943 sAltGrModifier
= false;
1946 event
.keyCode
= domKeyCode
;
1947 event
.mKeyNameIndex
=
1948 (aEvent
->text().length() && aEvent
->text()[0].isPrint()) ?
1949 KEY_NAME_INDEX_PrintableKey
:
1950 QtKeyCodeToDOMKeyNameIndex(aEvent
->key());
1952 // unset the key down flag
1953 ClearKeyDownFlag(event
.keyCode
);
1955 return DispatchEvent(&event
);
1959 nsWindow::OnScrollEvent(QGraphicsSceneWheelEvent
*aEvent
)
1961 // check to see if we should rollup
1962 WheelEvent
wheelEvent(true, NS_WHEEL_WHEEL
, this);
1963 wheelEvent
.deltaMode
= nsIDOMWheelEvent::DOM_DELTA_LINE
;
1965 // negative values for aEvent->delta indicate downward scrolling;
1966 // this is opposite Gecko usage.
1967 // TODO: Store the unused delta values due to fraction round and add it
1968 // to next event. The stored values should be reset by other
1969 // direction scroll event.
1970 int32_t delta
= (int)(aEvent
->delta() / WHEEL_DELTA
) * -3;
1972 switch (aEvent
->orientation()) {
1974 wheelEvent
.deltaY
= wheelEvent
.lineOrPageDeltaY
= delta
;
1976 case Qt::Horizontal
:
1977 wheelEvent
.deltaX
= wheelEvent
.lineOrPageDeltaX
= delta
;
1984 wheelEvent
.refPoint
.x
= nscoord(aEvent
->scenePos().x());
1985 wheelEvent
.refPoint
.y
= nscoord(aEvent
->scenePos().y());
1987 wheelEvent
.InitBasicModifiers(aEvent
->modifiers() & Qt::ControlModifier
,
1988 aEvent
->modifiers() & Qt::AltModifier
,
1989 aEvent
->modifiers() & Qt::ShiftModifier
,
1990 aEvent
->modifiers() & Qt::MetaModifier
);
1991 wheelEvent
.time
= 0;
1993 return DispatchEvent(&wheelEvent
);
1998 nsWindow::showEvent(QShowEvent
*)
2000 LOG(("%s [%p]\n", __PRETTY_FUNCTION__
,(void *)this));
2002 return nsEventStatus_eConsumeDoDefault
;
2006 nsWindow::hideEvent(QHideEvent
*)
2008 LOG(("%s [%p]\n", __PRETTY_FUNCTION__
,(void *)this));
2010 return nsEventStatus_eConsumeDoDefault
;
2013 //Gestures are only supported in 4.6.0 >
2014 #if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 0))
2015 nsEventStatus
nsWindow::OnTouchEvent(QTouchEvent
*event
, bool &handled
)
2018 const QList
<QTouchEvent::TouchPoint
> &touchPoints
= event
->touchPoints();
2020 if (event
->type() == QEvent::TouchBegin
) {
2022 for (int i
= touchPoints
.count() -1; i
>= 0; i
--) {
2023 QPointF fpos
= touchPoints
[i
].pos();
2024 nsGestureNotifyEvent
gestureNotifyEvent(true, NS_GESTURENOTIFY_EVENT_START
, this);
2025 gestureNotifyEvent
.refPoint
= nsIntPoint(fpos
.x(), fpos
.y());
2026 DispatchEvent(&gestureNotifyEvent
);
2029 else if (event
->type() == QEvent::TouchEnd
) {
2030 mGesturesCancelled
= false;
2031 mPinchEvent
.needDispatch
= false;
2034 if (touchPoints
.count() > 0) {
2035 // Remember start touch point in order to use it for
2036 // distance calculation in NS_SIMPLE_GESTURE_MAGNIFY_UPDATE
2037 mPinchEvent
.touchPoint
= touchPoints
.at(0).pos();
2040 return nsEventStatus_eIgnore
;
2044 nsWindow::OnGestureEvent(QGestureEvent
* event
, bool &handled
) {
2047 if (mGesturesCancelled
) {
2048 return nsEventStatus_eIgnore
;
2051 nsEventStatus result
= nsEventStatus_eIgnore
;
2053 QGesture
* gesture
= event
->gesture(Qt::PinchGesture
);
2056 QPinchGesture
* pinch
= static_cast<QPinchGesture
*>(gesture
);
2059 mPinchEvent
.centerPoint
=
2060 mWidget
->mapFromScene(event
->mapToGraphicsScene(pinch
->centerPoint()));
2061 nsIntPoint
centerPoint(mPinchEvent
.centerPoint
.x(),
2062 mPinchEvent
.centerPoint
.y());
2064 if (pinch
->state() == Qt::GestureStarted
) {
2066 mPinchEvent
.startDistance
= DistanceBetweenPoints(mPinchEvent
.centerPoint
, mPinchEvent
.touchPoint
) * 2;
2067 mPinchEvent
.prevDistance
= mPinchEvent
.startDistance
;
2068 result
= DispatchGestureEvent(NS_SIMPLE_GESTURE_MAGNIFY_START
,
2071 else if (pinch
->state() == Qt::GestureUpdated
) {
2072 mPinchEvent
.needDispatch
= true;
2073 mPinchEvent
.delta
= 0;
2074 DispatchMotionToMainThread();
2076 else if (pinch
->state() == Qt::GestureFinished
) {
2077 double distance
= DistanceBetweenPoints(mPinchEvent
.centerPoint
, mPinchEvent
.touchPoint
) * 2;
2078 double delta
= distance
- mPinchEvent
.startDistance
;
2079 result
= DispatchGestureEvent(NS_SIMPLE_GESTURE_MAGNIFY
,
2080 0, delta
, centerPoint
);
2081 mPinchEvent
.needDispatch
= false;
2087 //Disable mouse events when gestures are used, because they cause problems with
2089 mLastMultiTouchTime
.start();
2092 gesture
= event
->gesture(gSwipeGestureId
);
2094 if (gesture
->state() == Qt::GestureStarted
) {
2097 if (gesture
->state() == Qt::GestureFinished
) {
2101 MozSwipeGesture
* swipe
= static_cast<MozSwipeGesture
*>(gesture
);
2103 hotspot
.x
= swipe
->hotSpot().x();
2104 hotspot
.y
= swipe
->hotSpot().y();
2106 // Cancel pinch gesture
2107 mGesturesCancelled
= true;
2108 mPinchEvent
.needDispatch
= false;
2110 double distance
= DistanceBetweenPoints(swipe
->hotSpot(), mPinchEvent
.touchPoint
) * 2;
2111 double delta
= distance
- mPinchEvent
.startDistance
;
2113 DispatchGestureEvent(NS_SIMPLE_GESTURE_MAGNIFY
, 0, delta
/ 2, hotspot
);
2115 result
= DispatchGestureEvent(NS_SIMPLE_GESTURE_SWIPE
,
2116 swipe
->Direction(), 0, hotspot
);
2118 mLastMultiTouchTime
.start();
2125 nsWindow::DispatchGestureEvent(uint32_t aMsg
, uint32_t aDirection
,
2126 double aDelta
, const nsIntPoint
& aRefPoint
)
2128 nsSimpleGestureEvent
mozGesture(true, aMsg
, this, 0, 0.0);
2129 mozGesture
.direction
= aDirection
;
2130 mozGesture
.delta
= aDelta
;
2131 mozGesture
.refPoint
= aRefPoint
;
2133 Qt::KeyboardModifiers modifiers
= QApplication::keyboardModifiers();
2135 mozGesture
.InitBasicModifiers(modifiers
& Qt::ControlModifier
,
2136 modifiers
& Qt::AltModifier
,
2137 modifiers
& Qt::ShiftModifier
,
2139 mozGesture
.button
= 0;
2140 mozGesture
.time
= 0;
2142 return DispatchEvent(&mozGesture
);
2147 nsWindow::DistanceBetweenPoints(const QPointF
&aFirstPoint
, const QPointF
&aSecondPoint
)
2150 double deltaX
= abs(aFirstPoint
.x() - aSecondPoint
.x());
2151 double deltaY
= abs(aFirstPoint
.y() - aSecondPoint
.y());
2152 result
= sqrt(deltaX
*deltaX
+ deltaY
*deltaY
);
2156 #endif //qt version check
2159 nsWindow::ThemeChanged()
2161 NotifyThemeChanged();
2165 nsWindow::OnDragMotionEvent(QGraphicsSceneDragDropEvent
*aEvent
)
2167 LOG(("nsWindow::OnDragMotionSignal\n"));
2169 nsMouseEvent
event(true, NS_DRAGDROP_OVER
, 0,
2170 nsMouseEvent::eReal
);
2171 return nsEventStatus_eIgnore
;
2175 nsWindow::OnDragLeaveEvent(QGraphicsSceneDragDropEvent
*aEvent
)
2177 // XXX Do we want to pass this on only if the event's subwindow is null?
2178 LOG(("nsWindow::OnDragLeaveSignal(%p)\n", this));
2179 nsMouseEvent
event(true, NS_DRAGDROP_EXIT
, this, nsMouseEvent::eReal
);
2181 return DispatchEvent(&event
);
2185 nsWindow::OnDragDropEvent(QGraphicsSceneDragDropEvent
*aDropEvent
)
2187 if (aDropEvent
->proposedAction() == Qt::CopyAction
)
2189 printf("text version of the data: %s\n", aDropEvent
->mimeData()->text().toUtf8().data());
2190 aDropEvent
->acceptProposedAction();
2193 LOG(("nsWindow::OnDragDropSignal\n"));
2194 nsMouseEvent
event(true, NS_DRAGDROP_OVER
, 0,
2195 nsMouseEvent::eReal
);
2196 return nsEventStatus_eIgnore
;
2200 nsWindow::OnDragEnter(QGraphicsSceneDragDropEvent
*aDragEvent
)
2202 // Is it some format we think we can support?
2203 if ( aDragEvent
->mimeData()->hasFormat(kURLMime
)
2204 || aDragEvent
->mimeData()->hasFormat(kURLDataMime
)
2205 || aDragEvent
->mimeData()->hasFormat(kURLDescriptionMime
)
2206 || aDragEvent
->mimeData()->hasFormat(kHTMLMime
)
2207 || aDragEvent
->mimeData()->hasFormat(kUnicodeMime
)
2208 || aDragEvent
->mimeData()->hasFormat(kTextMime
)
2211 aDragEvent
->acceptProposedAction();
2214 // XXX Do we want to pass this on only if the event's subwindow is null?
2216 LOG(("nsWindow::OnDragEnter(%p)\n", this));
2218 nsMouseEvent
event(true, NS_DRAGDROP_ENTER
, this, nsMouseEvent::eReal
);
2219 return DispatchEvent(&event
);
2223 GetBrandName(nsXPIDLString
& brandName
)
2225 nsCOMPtr
<nsIStringBundleService
> bundleService
=
2226 mozilla::services::GetStringBundleService();
2228 nsCOMPtr
<nsIStringBundle
> bundle
;
2230 bundleService
->CreateBundle(
2231 "chrome://branding/locale/brand.properties",
2232 getter_AddRefs(bundle
));
2235 bundle
->GetStringFromName(
2236 NS_LITERAL_STRING("brandShortName").get(),
2237 getter_Copies(brandName
));
2239 if (brandName
.IsEmpty())
2240 brandName
.Assign(NS_LITERAL_STRING("Mozilla"));
2245 nsWindow::Create(nsIWidget
*aParent
,
2246 nsNativeWidget aNativeParent
,
2247 const nsIntRect
&aRect
,
2248 nsDeviceContext
*aContext
,
2249 nsWidgetInitData
*aInitData
)
2251 // only set the base parent if we're not going to be a dialog or a
2253 nsIWidget
*baseParent
= aParent
;
2256 (aInitData
->mWindowType
== eWindowType_dialog
||
2257 aInitData
->mWindowType
== eWindowType_toplevel
||
2258 aInitData
->mWindowType
== eWindowType_invisible
)) {
2260 baseParent
= nullptr;
2261 // also drop native parent for toplevel windows
2262 aNativeParent
= nullptr;
2265 // initialize all the common bits of this class
2266 BaseCreate(baseParent
, aRect
, aContext
, aInitData
);
2268 // and do our common creation
2274 // find native parent
2275 MozQWidget
*parent
= nullptr;
2277 if (aParent
!= nullptr)
2278 parent
= static_cast<MozQWidget
*>(aParent
->GetNativeData(NS_NATIVE_WIDGET
));
2280 // ok, create our QGraphicsWidget
2281 mWidget
= createQWidget(parent
, aNativeParent
, aInitData
);
2284 return NS_ERROR_OUT_OF_MEMORY
;
2286 LOG(("Create: nsWindow [%p] [%p]\n", (void *)this, (void *)mWidget
));
2288 // resize so that everything is set to the right dimensions
2289 Resize(mBounds
.x
, mBounds
.y
, mBounds
.width
, mBounds
.height
, false);
2291 // check if we should listen for resizes
2292 mListenForResizes
= (aNativeParent
||
2293 (aInitData
&& aInitData
->mListenForResizes
));
2298 already_AddRefed
<nsIWidget
>
2299 nsWindow::CreateChild(const nsIntRect
& aRect
,
2300 nsDeviceContext
* aContext
,
2301 nsWidgetInitData
* aInitData
,
2302 bool /*aForceUseIWidgetParent*/)
2304 //We need to force parent widget, otherwise GetTopLevelWindow doesn't work
2305 return nsBaseWidget::CreateChild(aRect
,
2308 true); // Force parent
2313 nsWindow::SetWindowClass(const nsAString
&xulWinType
)
2316 return NS_ERROR_FAILURE
;
2318 nsXPIDLString brandName
;
2319 GetBrandName(brandName
);
2322 XClassHint
*class_hint
= XAllocClassHint();
2324 return NS_ERROR_OUT_OF_MEMORY
;
2325 const char *role
= NULL
;
2326 class_hint
->res_name
= ToNewCString(xulWinType
);
2327 if (!class_hint
->res_name
) {
2329 return NS_ERROR_OUT_OF_MEMORY
;
2331 class_hint
->res_class
= ToNewCString(brandName
);
2332 if (!class_hint
->res_class
) {
2333 nsMemory::Free(class_hint
->res_name
);
2335 return NS_ERROR_OUT_OF_MEMORY
;
2338 // Parse res_name into a name and role. Characters other than
2339 // [A-Za-z0-9_-] are converted to '_'. Anything after the first
2340 // colon is assigned to role; if there's no colon, assign the
2341 // whole thing to both role and res_name.
2342 for (char *c
= class_hint
->res_name
; *c
; c
++) {
2347 else if (!isascii(*c
) || (!isalnum(*c
) && ('_' != *c
) && ('-' != *c
)))
2350 class_hint
->res_name
[0] = toupper(class_hint
->res_name
[0]);
2351 if (!role
) role
= class_hint
->res_name
;
2353 QWidget
*widget
= GetViewWidget();
2354 // If widget not show, handle might be null
2355 if (widget
&& widget
->winId())
2356 XSetClassHint(gfxQtPlatform::GetXDisplay(widget
),
2360 nsMemory::Free(class_hint
->res_class
);
2361 nsMemory::Free(class_hint
->res_name
);
2369 nsWindow::NativeResize(int32_t aWidth
, int32_t aHeight
, bool aRepaint
)
2371 LOG(("nsWindow::NativeResize [%p] %d %d\n", (void *)this,
2374 mNeedsResize
= false;
2377 QGraphicsView
*widget
= qobject_cast
<QGraphicsView
*>(GetViewWidget());
2378 NS_ENSURE_TRUE_VOID(widget
);
2379 // map from in-scene widget to scene, from scene to view.
2380 QRect r
= widget
->mapFromScene(mWidget
->mapToScene(QRect(0, 0, aWidth
, aHeight
))).boundingRect();
2381 // going from QPolygon to QRect includes the points, adding one to width and height
2382 r
.adjust(0, 0, -1, -1);
2383 widget
->resize(r
.width(), r
.height());
2386 mWidget
->resize(aWidth
, aHeight
);
2394 nsWindow::NativeResize(int32_t aX
, int32_t aY
,
2395 int32_t aWidth
, int32_t aHeight
,
2398 LOG(("nsWindow::NativeResize [%p] %d %d %d %d\n", (void *)this,
2399 aX
, aY
, aWidth
, aHeight
));
2401 mNeedsResize
= false;
2405 QGraphicsView
*widget
= qobject_cast
<QGraphicsView
*>(GetViewWidget());
2406 NS_ENSURE_TRUE_VOID(widget
);
2407 // map from in-scene widget to scene, from scene to view.
2408 QRect r
= widget
->mapFromScene(mWidget
->mapToScene(QRect(aX
, aY
, aWidth
, aHeight
))).boundingRect();
2409 // going from QPolygon to QRect includes the points, adding one to width and height
2410 r
.adjust(0, 0, -1, -1);
2411 widget
->setGeometry(r
.x(), r
.y(), r
.width(), r
.height());
2414 mWidget
->setGeometry(aX
, aY
, aWidth
, aHeight
);
2422 nsWindow::NativeShow(bool aAction
)
2425 QWidget
*widget
= GetViewWidget();
2426 // On e10s, we never want the child process or plugin process
2427 // to go fullscreen because if we do the window because visible
2428 // do to disabled Qt-Xembed
2430 !widget
->isVisible())
2431 MakeFullScreen(mSizeMode
== nsSizeMode_Fullscreen
);
2434 // unset our flag now that our window has been shown
2442 nsWindow::SetHasTransparentBackground(bool aTransparent
)
2444 return NS_ERROR_NOT_IMPLEMENTED
;
2448 nsWindow::GetHasTransparentBackground(bool& aTransparent
)
2450 aTransparent
= mIsTransparent
;
2455 nsWindow::SetupPluginPort(void)
2457 NS_WARNING("Not implemented");
2462 nsWindow::SetWindowIconList(const nsTArray
<nsCString
> &aIconList
)
2466 for (uint32_t i
= 0; i
< aIconList
.Length(); ++i
) {
2467 const char *path
= aIconList
[i
].get();
2468 LOG(("window [%p] Loading icon from %s\n", (void *)this, path
));
2472 QWidget
*widget
= GetViewWidget();
2473 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
2474 widget
->setWindowIcon(icon
);
2480 nsWindow::SetDefaultIcon(void)
2482 SetIcon(NS_LITERAL_STRING("default"));
2485 void nsWindow::QWidgetDestroyed()
2491 nsWindow::MakeFullScreen(bool aFullScreen
)
2493 QWidget
*widget
= GetViewWidget();
2494 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
2496 if (mSizeMode
!= nsSizeMode_Fullscreen
)
2497 mLastSizeMode
= mSizeMode
;
2499 mSizeMode
= nsSizeMode_Fullscreen
;
2500 widget
->showFullScreen();
2503 mSizeMode
= mLastSizeMode
;
2505 switch (mSizeMode
) {
2506 case nsSizeMode_Maximized
:
2507 widget
->showMaximized();
2509 case nsSizeMode_Minimized
:
2510 widget
->showMinimized();
2512 case nsSizeMode_Normal
:
2513 widget
->showNormal();
2516 widget
->showNormal();
2521 NS_ASSERTION(mLastSizeMode
!= nsSizeMode_Fullscreen
,
2522 "mLastSizeMode should never be fullscreen");
2523 return nsBaseWidget::MakeFullScreen(aFullScreen
);
2527 nsWindow::HideWindowChrome(bool aShouldHide
)
2531 return NS_ERROR_FAILURE
;
2534 // Sawfish, metacity, and presumably other window managers get
2535 // confused if we change the window decorations while the window
2537 bool wasVisible
= false;
2538 if (mWidget
->isVisible()) {
2547 // For some window managers, adding or removing window decorations
2548 // requires unmapping and remapping our toplevel window. Go ahead
2549 // and flush the queue here so that we don't end up with a BadWindow
2550 // error later when this happens (when the persistence timer fires
2551 // and GetWindowPos is called)
2552 QWidget
*widget
= GetViewWidget();
2553 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
2555 XSync(gfxQtPlatform::GetXDisplay(widget
), False
);
2561 //////////////////////////////////////////////////////////////////////
2562 // These are all of our drag and drop operations
2565 nsWindow::InitDragEvent(nsMouseEvent
&aEvent
)
2567 // set the keyboard modifiers
2570 // This will update the drag action based on the information in the
2575 initialize_prefs(void)
2577 // check to see if we should set our raise pref
2582 is_context_menu_key(const nsKeyEvent
& aKeyEvent
)
2584 return ((aKeyEvent
.keyCode
== NS_VK_F10
&& aKeyEvent
.IsShift() &&
2585 !aKeyEvent
.IsControl() && !aKeyEvent
.IsMeta() &&
2586 !aKeyEvent
.IsAlt()) ||
2587 (aKeyEvent
.keyCode
== NS_VK_CONTEXT_MENU
&& !aKeyEvent
.IsShift() &&
2588 !aKeyEvent
.IsControl() && !aKeyEvent
.IsMeta() &&
2589 !aKeyEvent
.IsAlt()));
2593 key_event_to_context_menu_event(nsMouseEvent
&aEvent
,
2594 QKeyEvent
*aGdkEvent
)
2596 aEvent
.refPoint
= nsIntPoint(0, 0);
2597 aEvent
.modifiers
= 0;
2599 aEvent
.clickCount
= 1;
2602 // nsChildWindow class
2604 nsChildWindow::nsChildWindow()
2608 nsChildWindow::~nsChildWindow()
2612 nsPopupWindow::nsPopupWindow()
2614 #ifdef DEBUG_WIDGETS
2615 qDebug("===================== popup!");
2619 nsPopupWindow::~nsPopupWindow()
2623 NS_IMETHODIMP_(bool)
2624 nsWindow::HasGLContext()
2626 return MozQGLWidgetWrapper::hasGLContext(qobject_cast
<QGraphicsView
*>(GetViewWidget()));
2630 nsWindow::createQWidget(MozQWidget
*parent
,
2631 nsNativeWidget nativeParent
,
2632 nsWidgetInitData
*aInitData
)
2634 const char *windowName
= NULL
;
2635 Qt::WindowFlags flags
= Qt::Widget
;
2636 QWidget
*parentWidget
= (parent
&& parent
->getReceiver()) ?
2637 parent
->getReceiver()->GetViewWidget() : nullptr;
2639 #ifdef DEBUG_WIDGETS
2640 qDebug("NEW WIDGET\n\tparent is %p (%s)", (void*)parent
,
2641 parent
? qPrintable(parent
->objectName()) : "null");
2644 // ok, create our windows
2645 switch (mWindowType
) {
2646 case eWindowType_dialog
:
2647 windowName
= "topLevelDialog";
2649 flags
|= Qt::Dialog
;
2651 case eWindowType_popup
:
2652 windowName
= "topLevelPopup";
2654 case eWindowType_toplevel
:
2655 windowName
= "topLevelWindow";
2658 case eWindowType_invisible
:
2659 windowName
= "topLevelInvisible";
2661 case eWindowType_child
:
2662 case eWindowType_plugin
:
2664 windowName
= "paintArea";
2668 MozQWidget
* parentQWidget
= nullptr;
2670 parentQWidget
= parent
;
2671 } else if (nativeParent
&& nativeParent
!= PARENTLESS_WIDGET
) {
2672 parentQWidget
= static_cast<MozQWidget
*>(nativeParent
);
2674 MozQWidget
* widget
= new MozQWidget(this, parentQWidget
);
2677 widget
->setObjectName(QString(windowName
));
2679 // make only child and plugin windows focusable
2680 if (eWindowType_child
== mWindowType
|| eWindowType_plugin
== mWindowType
) {
2681 widget
->setFlag(QGraphicsItem::ItemIsFocusable
);
2682 widget
->setFocusPolicy(Qt::WheelFocus
);
2685 // create a QGraphicsView if this is a new toplevel window
2688 QGraphicsView
* newView
=
2689 nsFastStartup::GetStartupGraphicsView(parentWidget
, widget
);
2691 if (mWindowType
== eWindowType_dialog
) {
2692 newView
->setWindowModality(Qt::WindowModal
);
2695 #if defined(MOZ_PLATFORM_MAEMO) || defined(MOZ_GL_PROVIDER)
2696 if (ComputeShouldAccelerate(mUseLayersAcceleration
)) {
2697 // Only create new OGL widget if it is not yet installed
2698 if (!HasGLContext()) {
2699 MozQGraphicsView
*qview
= qobject_cast
<MozQGraphicsView
*>(newView
);
2701 qview
->setGLWidgetEnabled(true);
2707 if (gfxQtPlatform::GetPlatform()->GetRenderMode() == gfxQtPlatform::RENDER_DIRECT
) {
2708 // Disable double buffer and system background rendering
2709 #if defined(MOZ_X11) && (QT_VERSION < QT_VERSION_CHECK(5,0,0))
2710 newView
->viewport()->setAttribute(Qt::WA_PaintOnScreen
, true);
2712 newView
->viewport()->setAttribute(Qt::WA_NoSystemBackground
, true);
2715 #if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 0))
2716 #if defined MOZ_ENABLE_MEEGOTOUCH
2717 // Disable default Gesture filters (speedup filtering)
2718 newView
->viewport()->ungrabGesture(Qt::PanGesture
);
2719 newView
->viewport()->ungrabGesture(Qt::TapGesture
);
2720 newView
->viewport()->ungrabGesture(Qt::TapAndHoldGesture
);
2721 newView
->viewport()->ungrabGesture(Qt::SwipeGesture
);
2724 // Enable required filters
2725 newView
->viewport()->grabGesture(Qt::PinchGesture
);
2726 newView
->viewport()->grabGesture(gSwipeGestureId
);
2728 newView
->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
2729 newView
->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
2731 #if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 0))
2732 // Top level widget is just container, and should not be painted
2733 widget
->setFlag(QGraphicsItem::ItemHasNoContents
);
2737 if (newView
->effectiveWinId()) {
2738 XSetWindowBackgroundPixmap(mozilla::DefaultXDisplay(),
2739 newView
->effectiveWinId(), None
);
2744 if (mWindowType
== eWindowType_popup
) {
2745 widget
->setZValue(100);
2747 // XXX is this needed for Qt?
2748 // gdk does not automatically set the cursor for "temporary"
2749 // windows, which are what gtk uses for popups.
2750 SetCursor(eCursor_standard
);
2751 } else if (mIsTopLevel
) {
2754 #if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 0))
2755 #if defined MOZ_ENABLE_MEEGOTOUCH
2756 // Disable default Gesture filters (speedup filtering)
2757 widget
->ungrabGesture(Qt::PanGesture
);
2758 widget
->ungrabGesture(Qt::TapGesture
);
2759 widget
->ungrabGesture(Qt::TapAndHoldGesture
);
2760 widget
->ungrabGesture(Qt::SwipeGesture
);
2762 widget
->grabGesture(Qt::PinchGesture
);
2763 widget
->grabGesture(gSwipeGestureId
);
2769 // return the gfxASurface for rendering to this widget
2771 nsWindow::GetThebesSurface()
2773 /* This is really a dummy surface; this is only used when doing reflow, because
2774 * we need a RenderingContext to measure text against.
2777 return mThebesSurface
;
2779 #ifdef CAIRO_HAS_QT_SURFACE
2780 gfxQtPlatform::RenderMode renderMode
= gfxQtPlatform::GetPlatform()->GetRenderMode();
2781 if (renderMode
== gfxQtPlatform::RENDER_QPAINTER
) {
2782 mThebesSurface
= new gfxQPainterSurface(gfxIntSize(1, 1), gfxASurface::CONTENT_COLOR
);
2785 if (!mThebesSurface
) {
2786 gfxASurface::gfxImageFormat imageFormat
= gfxASurface::ImageFormatRGB24
;
2787 mThebesSurface
= new gfxImageSurface(gfxIntSize(1, 1), imageFormat
);
2790 return mThebesSurface
;
2794 nsWindow::BeginResizeDrag(nsGUIEvent
* aEvent
, int32_t aHorizontal
, int32_t aVertical
)
2796 NS_ENSURE_ARG_POINTER(aEvent
);
2798 if (aEvent
->eventStructType
!= NS_MOUSE_EVENT
) {
2799 // you can only begin a resize drag with a mouse event
2800 return NS_ERROR_INVALID_ARG
;
2803 nsMouseEvent
* mouse_event
= static_cast<nsMouseEvent
*>(aEvent
);
2805 if (mouse_event
->button
!= nsMouseEvent::eLeftButton
) {
2806 // you can only begin a resize drag with the left mouse button
2807 return NS_ERROR_INVALID_ARG
;
2814 nsWindow::contextMenuEvent(QGraphicsSceneContextMenuEvent
*)
2816 return nsEventStatus_eIgnore
;
2820 nsWindow::imComposeEvent(QInputMethodEvent
*event
, bool &handled
)
2822 // XXX Needs to check whether this widget has been destroyed or not after
2823 // each DispatchEvent().
2825 nsCompositionEvent
start(true, NS_COMPOSITION_START
, this);
2826 DispatchEvent(&start
);
2828 nsAutoString
compositionStr(event
->commitString().utf16());
2830 if (!compositionStr
.IsEmpty()) {
2831 nsCompositionEvent
update(true, NS_COMPOSITION_UPDATE
, this);
2832 update
.data
= compositionStr
;
2833 DispatchEvent(&update
);
2836 nsTextEvent
text(true, NS_TEXT_TEXT
, this);
2837 text
.theText
= compositionStr
;
2838 DispatchEvent(&text
);
2840 nsCompositionEvent
end(true, NS_COMPOSITION_END
, this);
2841 end
.data
= compositionStr
;
2842 DispatchEvent(&end
);
2844 return nsEventStatus_eIgnore
;
2848 nsWindow::GetParent(void)
2856 QDesktopWidget
* rootWindow
= QApplication::desktop();
2857 double heightInches
= rootWindow
->heightMM()/25.4;
2858 if (heightInches
< 0.25) {
2859 // Something's broken, but we'd better not crash.
2863 return float(rootWindow
->height()/heightInches
);
2867 nsWindow::DispatchActivateEvent(void)
2869 if (mWidgetListener
)
2870 mWidgetListener
->WindowActivated();
2874 nsWindow::DispatchDeactivateEvent(void)
2876 if (mWidgetListener
)
2877 mWidgetListener
->WindowDeactivated();
2881 nsWindow::DispatchActivateEventOnTopLevelWindow(void)
2883 nsWindow
* topLevelWindow
= static_cast<nsWindow
*>(GetTopLevelWidget());
2884 if (topLevelWindow
!= nullptr)
2885 topLevelWindow
->DispatchActivateEvent();
2889 nsWindow::DispatchDeactivateEventOnTopLevelWindow(void)
2891 nsWindow
* topLevelWindow
= static_cast<nsWindow
*>(GetTopLevelWidget());
2892 if (topLevelWindow
!= nullptr)
2893 topLevelWindow
->DispatchDeactivateEvent();
2897 nsWindow::DispatchResizeEvent(nsIntRect
&aRect
, nsEventStatus
&aStatus
)
2899 aStatus
= nsEventStatus_eIgnore
;
2900 if (mWidgetListener
&&
2901 mWidgetListener
->WindowResized(this, aRect
.width
, aRect
.height
))
2902 aStatus
= nsEventStatus_eConsumeNoDefault
;
2906 nsWindow::DispatchEvent(nsGUIEvent
*aEvent
, nsEventStatus
&aStatus
)
2909 debug_DumpEvent(stdout
, aEvent
->widget
, aEvent
,
2910 nsAutoCString("something"), 0);
2913 aStatus
= nsEventStatus_eIgnore
;
2915 // send it to the standard callback
2916 if (mWidgetListener
)
2917 aStatus
= mWidgetListener
->HandleEvent(aEvent
, mUseAttachedEvents
);
2923 nsWindow::Show(bool aState
)
2925 LOG(("nsWindow::Show [%p] state %d\n", (void *)this, aState
));
2926 if (aState
== mIsShown
)
2929 // Clear our cached resources when the window is hidden.
2930 if (mIsShown
&& !aState
) {
2931 ClearCachedResources();
2936 #ifdef MOZ_ENABLE_QTMOBILITY
2938 (mWindowType
== eWindowType_toplevel
||
2939 mWindowType
== eWindowType_dialog
||
2940 mWindowType
== eWindowType_popup
))
2942 if (!gOrientation
) {
2943 gOrientation
= new QOrientationSensor();
2944 gOrientation
->addFilter(&gOrientationFilter
);
2945 gOrientation
->start();
2946 if (!gOrientation
->isActive()) {
2947 qWarning("Orientationsensor didn't start!");
2949 gOrientationFilter
.filter(gOrientation
->reading());
2951 QObject::connect((QObject
*) &gOrientationFilter
, SIGNAL(orientationChanged()),
2952 mWidget
, SLOT(orientationChanged()));
2957 if ((aState
&& !AreBoundsSane()) || !mWidget
) {
2958 LOG(("\tbounds are insane or window hasn't been created yet\n"));
2965 NativeResize(mBounds
.x
, mBounds
.y
, mBounds
.width
, mBounds
.height
,
2967 } else if (mNeedsResize
) {
2968 NativeResize(mBounds
.width
, mBounds
.height
, false);
2972 // If someone is hiding this widget, clear any needing show flag.
2981 nsWindow::Resize(double aWidth
, double aHeight
, bool aRepaint
)
2983 mBounds
.width
= NSToIntRound(aWidth
);
2984 mBounds
.height
= NSToIntRound(aHeight
);
2990 if (AreBoundsSane()) {
2991 if (mIsTopLevel
|| mNeedsShow
)
2992 NativeResize(mBounds
.x
, mBounds
.y
,
2993 mBounds
.width
, mBounds
.height
, aRepaint
);
2995 NativeResize(mBounds
.width
, mBounds
.height
, aRepaint
);
2997 // Does it need to be shown because it was previously insane?
3002 // If someone has set this so that the needs show flag is false
3003 // and it needs to be hidden, update the flag and hide the
3004 // window. This flag will be cleared the next time someone
3005 // hides the window or shows it. It also prevents us from
3006 // calling NativeShow(false) excessively on the window which
3007 // causes unneeded X traffic.
3014 else if (AreBoundsSane() && mListenForResizes
) {
3015 // For widgets that we listen for resizes for (widgets created
3016 // with native parents) we apparently _always_ have to resize. I
3017 // dunno why, but apparently we're lame like that.
3018 NativeResize(mBounds
.width
, mBounds
.height
, aRepaint
);
3021 mNeedsResize
= true;
3024 // synthesize a resize event if this isn't a toplevel
3025 if (mIsTopLevel
|| mListenForResizes
) {
3026 nsEventStatus status
;
3027 DispatchResizeEvent(mBounds
, status
);
3030 NotifyRollupGeometryChange();
3035 nsWindow::Resize(double aX
, double aY
, double aWidth
, double aHeight
,
3038 mBounds
.x
= NSToIntRound(aX
);
3039 mBounds
.y
= NSToIntRound(aY
);
3040 mBounds
.width
= NSToIntRound(aWidth
);
3041 mBounds
.height
= NSToIntRound(aHeight
);
3048 // Has this widget been set to visible?
3050 // Are the bounds sane?
3051 if (AreBoundsSane()) {
3052 // Yep? Resize the window
3053 NativeResize(mBounds
.x
, mBounds
.y
, mBounds
.width
, mBounds
.height
,
3055 // Does it need to be shown because it was previously insane?
3060 // If someone has set this so that the needs show flag is false
3061 // and it needs to be hidden, update the flag and hide the
3062 // window. This flag will be cleared the next time someone
3063 // hides the window or shows it. It also prevents us from
3064 // calling NativeShow(false) excessively on the window which
3065 // causes unneeded X traffic.
3072 // If the widget hasn't been shown, mark the widget as needing to be
3073 // resized before it is shown
3074 else if (AreBoundsSane() && mListenForResizes
) {
3075 // For widgets that we listen for resizes for (widgets created
3076 // with native parents) we apparently _always_ have to resize. I
3077 // dunno why, but apparently we're lame like that.
3078 NativeResize(mBounds
.x
, mBounds
.y
, mBounds
.width
, mBounds
.height
,
3082 mNeedsResize
= true;
3086 if (mIsTopLevel
|| mListenForResizes
) {
3087 // synthesize a resize event
3088 nsEventStatus status
;
3089 DispatchResizeEvent(mBounds
, status
);
3095 NotifyRollupGeometryChange();
3100 nsWindow::Enable(bool aState
)
3108 nsWindow::IsEnabled() const
3114 nsWindow::OnDestroy(void)
3116 if (mOnDestroyCalled
)
3119 mOnDestroyCalled
= true;
3121 // release references to children and device context
3122 nsBaseWidget::OnDestroy();
3124 // let go of our parent
3127 nsCOMPtr
<nsIWidget
> kungFuDeathGrip
= this;
3128 NotifyWindowDestroyed();
3132 nsWindow::AreBoundsSane(void)
3134 if (mBounds
.width
> 0 && mBounds
.height
> 0)
3140 #if defined(MOZ_X11) && (MOZ_PLATFORM_MAEMO == 6)
3147 static QCoreApplication::EventFilter previousEventFilter
= NULL
;
3149 static PluginVKBState
3150 GetPluginVKBState(Window aWinId
)
3152 // Set default value as unexpected error
3153 PluginVKBState imeState
= VKBUndefined
;
3154 Display
*display
= mozilla::DefaultXDisplay();
3158 unsigned long nitems
;
3159 unsigned long bytes
;
3161 unsigned char* asUChar
;
3162 unsigned long* asLong
;
3164 int status
= XGetWindowProperty(display
, aWinId
, sPluginIMEAtom
,
3165 0, 1, False
, AnyPropertyType
,
3166 &actualType
, &actualFormat
, &nitems
,
3167 &bytes
, &data
.asUChar
);
3169 if (status
== Success
&& actualType
== XA_CARDINAL
&& actualFormat
== 32 && nitems
== 1) {
3170 // Assume that plugin set value false - close VKB, true - open VKB
3171 imeState
= data
.asLong
[0] ? VKBOpen
: VKBClose
;
3174 if (status
== Success
) {
3175 XFree(data
.asUChar
);
3182 SetVKBState(Window aWinId
, PluginVKBState aState
)
3184 Display
*display
= mozilla::DefaultXDisplay();
3185 if (aState
!= VKBUndefined
) {
3186 unsigned long isOpen
= aState
== VKBOpen
? 1 : 0;
3187 XChangeProperty(display
, aWinId
, sPluginIMEAtom
, XA_CARDINAL
, 32,
3188 PropModeReplace
, (unsigned char *) &isOpen
, 1);
3190 XDeleteProperty(display
, aWinId
, sPluginIMEAtom
);
3192 XSync(display
, False
);
3196 x11EventFilter(void* message
, long* result
)
3198 XEvent
* event
= static_cast<XEvent
*>(message
);
3199 if (event
->type
== PropertyNotify
) {
3200 if (event
->xproperty
.atom
== sPluginIMEAtom
) {
3201 PluginVKBState state
= GetPluginVKBState(event
->xproperty
.window
);
3202 if (state
== VKBOpen
) {
3203 MozQWidget::requestVKB();
3204 } else if (state
== VKBClose
) {
3205 MozQWidget::hideVKB();
3210 if (previousEventFilter
) {
3211 return previousEventFilter(message
, result
);
3218 NS_IMETHODIMP_(void)
3219 nsWindow::SetInputContext(const InputContext
& aContext
,
3220 const InputContextAction
& aAction
)
3222 NS_ENSURE_TRUE_VOID(mWidget
);
3224 // SetSoftwareKeyboardState uses mInputContext,
3225 // so, before calling that, record aContext in mInputContext.
3226 mInputContext
= aContext
;
3228 #if defined(MOZ_X11) && (MOZ_PLATFORM_MAEMO == 6)
3229 if (sPluginIMEAtom
) {
3230 static QCoreApplication::EventFilter currentEventFilter
= NULL
;
3231 if (mInputContext
.mIMEState
.mEnabled
== IMEState::PLUGIN
&&
3232 currentEventFilter
!= x11EventFilter
) {
3233 // Install event filter for listening Plugin IME state changes
3234 previousEventFilter
= QCoreApplication::instance()->setEventFilter(x11EventFilter
);
3235 currentEventFilter
= x11EventFilter
;
3236 } else if (mInputContext
.mIMEState
.mEnabled
!= IMEState::PLUGIN
&&
3237 currentEventFilter
== x11EventFilter
) {
3238 // Remove event filter
3239 QCoreApplication::instance()->setEventFilter(previousEventFilter
);
3240 currentEventFilter
= previousEventFilter
;
3241 previousEventFilter
= NULL
;
3242 QWidget
* view
= GetViewWidget();
3244 SetVKBState(view
->winId(), VKBUndefined
);
3250 switch (mInputContext
.mIMEState
.mEnabled
) {
3251 case IMEState::ENABLED
:
3252 case IMEState::PASSWORD
:
3253 case IMEState::PLUGIN
:
3254 SetSoftwareKeyboardState(true, aAction
);
3257 SetSoftwareKeyboardState(false, aAction
);
3262 NS_IMETHODIMP_(InputContext
)
3263 nsWindow::GetInputContext()
3265 mInputContext
.mIMEState
.mOpen
= IMEState::OPEN_STATE_NOT_SUPPORTED
;
3266 // Our qt widget looks like using only one context per process.
3267 // However, it's better to set the context's pointer.
3268 #if (QT_VERSION <= QT_VERSION_CHECK(5, 0, 0))
3269 mInputContext
.mNativeIMEContext
= qApp
->inputContext();
3271 mInputContext
.mNativeIMEContext
= nullptr;
3273 return mInputContext
;
3277 nsWindow::SetSoftwareKeyboardState(bool aOpen
,
3278 const InputContextAction
& aAction
)
3281 NS_ENSURE_TRUE_VOID(mInputContext
.mIMEState
.mEnabled
!=
3282 IMEState::DISABLED
);
3284 // Ensure that opening the virtual keyboard is allowed for this specific
3285 // InputContext depending on the content.ime.strict.policy pref
3286 if (mInputContext
.mIMEState
.mEnabled
!= IMEState::PLUGIN
&&
3287 Preferences::GetBool("content.ime.strict_policy", false) &&
3288 !aAction
.ContentGotFocusByTrustedCause() &&
3289 !aAction
.UserMightRequestOpenVKB()) {
3292 #if defined(MOZ_X11) && (MOZ_PLATFORM_MAEMO == 6)
3293 // doen't open VKB if plugin did set closed state
3294 else if (sPluginIMEAtom
) {
3295 QWidget
* view
= GetViewWidget();
3296 if (view
&& GetPluginVKBState(view
->winId()) == VKBClose
) {
3304 // VKB open need to be delayed in order to give
3305 // to plugins chance prevent VKB from opening
3307 Preferences::GetInt("ui.vkb.open.delay", 200);
3308 MozQWidget::requestVKB(openDelay
, mWidget
);
3310 MozQWidget::hideVKB();
3316 nsWindow::UserActivity()
3318 if (!mIdleService
) {
3319 mIdleService
= do_GetService("@mozilla.org/widget/idleservice;1");
3323 mIdleService
->ResetIdleTimeOut(0);
3328 nsWindow::GetGLFrameBufferFormat()
3330 if (mLayerManager
&&
3331 mLayerManager
->GetBackendType() == mozilla::layers::LAYERS_OPENGL
) {
3332 return MozQGLWidgetWrapper::isRGBAContext() ? LOCAL_GL_RGBA
: LOCAL_GL_RGB
;
3334 return LOCAL_GL_NONE
;