widget/qt/nsWindow.cpp

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

mercurial