Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / widget / src / qt / nsWindow.cpp
blob58e8327ca36fb450e8e685389044bd064197c855
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim:expandtab:shiftwidth=4:tabstop=4:
3 */
4 /* ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
17 * The Original Code is mozilla.org code.
19 * The Initial Developer of the Original Code is Christopher Blizzard
20 * <blizzard@mozilla.org>. Portions created by the Initial Developer
21 * are Copyright (C) 2001 the Initial Developer. All Rights Reserved.
23 * Contributor(s):
24 * Mats Palmgren <mats.palmgren@bredband.net>
25 * Masayuki Nakano <masayuki@d-toybox.com>
26 * Romashin Oleg <romaxa@gmail.com>
27 * Vladimir Vukicevic <vladimir@pobox.com>
29 * Alternatively, the contents of this file may be used under the terms of
30 * either the GNU General Public License Version 2 or later (the "GPL"), or
31 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
32 * in which case the provisions of the GPL or the LGPL are applicable instead
33 * of those above. If you wish to allow use of your version of this file only
34 * under the terms of either the GPL or the LGPL, and not to allow others to
35 * use your version of this file under the terms of the MPL, indicate your
36 * decision by deleting the provisions above and replace them with the notice
37 * and other provisions required by the GPL or the LGPL. If you do not delete
38 * the provisions above, a recipient may use your version of this file under
39 * the terms of any one of the MPL, the GPL or the LGPL.
41 * ***** END LICENSE BLOCK ***** */
43 #include "prlink.h"
45 #include <qevent.h> //XXX switch for forward-decl
46 #include <QtGui>
47 #include <qcursor.h>
49 #include "nsWindow.h"
50 #include "nsToolkit.h"
51 #include "nsIDeviceContext.h"
52 #include "nsIRenderingContext.h"
53 #include "nsIRegion.h"
54 #include "nsIRollupListener.h"
55 #include "nsIMenuRollup.h"
56 #include "nsIDOMNode.h"
58 #include "nsWidgetsCID.h"
59 #include "nsIDragService.h"
61 #include "nsQtKeyUtils.h"
63 #ifdef Q_WS_X11
64 #include <X11/XF86keysym.h>
65 #endif
67 #include "nsWidgetAtoms.h"
69 #ifdef MOZ_ENABLE_STARTUP_NOTIFICATION
70 #define SN_API_NOT_YET_FROZEN
71 #include <startup-notification-1.0/libsn/sn.h>
72 #endif
74 #include "nsIPrefService.h"
75 #include "nsIPrefBranch.h"
76 #include "nsIServiceManager.h"
77 #include "nsIStringBundle.h"
78 #include "nsGfxCIID.h"
80 /* For SetIcon */
81 #include "nsAppDirectoryServiceDefs.h"
82 #include "nsXPIDLString.h"
83 #include "nsIFile.h"
84 #include "nsILocalFile.h"
86 /* SetCursor(imgIContainer*) */
87 #include "imgIContainer.h"
88 #include "gfxIImageFrame.h"
89 #include "nsGfxCIID.h"
90 #include "nsIImage.h"
91 #include "nsIInterfaceRequestorUtils.h"
92 #include "nsAutoPtr.h"
94 #include "gfxQtPlatform.h"
95 #include "gfxXlibSurface.h"
96 #include "gfxQPainterSurface.h"
97 #include "gfxContext.h"
98 #include "gfxImageSurface.h"
100 #include <qapplication.h>
101 #include <qdesktopwidget.h>
102 #include <qwidget.h>
103 #include <qcursor.h>
104 #include <qobject.h>
105 #include <execinfo.h>
106 #include <stdlib.h>
108 #ifdef Q_WS_X11
109 #include "qx11info_x11.h"
110 #endif
112 #include <execinfo.h>
114 #include "mozqwidget.h"
116 /* For PrepareNativeWidget */
117 static NS_DEFINE_IID(kDeviceContextCID, NS_DEVICE_CONTEXT_CID);
119 // initialization static functions
120 static nsresult initialize_prefs (void);
122 static NS_DEFINE_IID(kCDragServiceCID, NS_DRAGSERVICE_CID);
124 #define NS_WINDOW_TITLE_MAX_LENGTH 4095
126 #define kWindowPositionSlop 20
128 // QT
129 static const int WHEEL_DELTA = 120;
130 static PRBool gGlobalsInitialized = PR_FALSE;
132 static nsCOMPtr<nsIRollupListener> gRollupListener;
133 static nsWeakPtr gRollupWindow;
134 static PRBool gConsumeRollupEvent;
136 //static nsWindow * get_window_for_qt_widget(QWidget *widget);
138 static PRBool check_for_rollup(double aMouseX, double aMouseY,
139 PRBool aIsWheel);
140 static PRBool
141 is_mouse_in_window (QWidget* aWindow, double aMouseX, double aMouseY);
143 static PRBool
144 isContextMenuKeyEvent(const QKeyEvent *qe)
146 PRUint32 kc = QtKeyCodeToDOMKeyCode(qe->key());
147 if (qe->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier))
148 return PR_FALSE;
150 PRBool isShift = qe->modifiers() & Qt::ShiftModifier;
151 return (kc == NS_VK_F10 && isShift) ||
152 (kc == NS_VK_CONTEXT_MENU && !isShift);
155 static void
156 InitKeyEvent(nsKeyEvent &aEvent, QKeyEvent *aQEvent)
158 aEvent.isShift = aQEvent->modifiers() & Qt::ShiftModifier;
159 aEvent.isControl = aQEvent->modifiers() & Qt::ControlModifier;
160 aEvent.isAlt = aQEvent->modifiers() & Qt::AltModifier;
161 aEvent.isMeta = aQEvent->modifiers() & Qt::MetaModifier;
162 aEvent.time = 0;
164 // The transformations above and in gdk for the keyval are not invertible
165 // so link to the GdkEvent (which will vanish soon after return from the
166 // event callback) to give plugins access to hardware_keycode and state.
167 // (An XEvent would be nice but the GdkEvent is good enough.)
168 aEvent.nativeMsg = (void *)aQEvent;
171 static void
172 keyEventToContextMenuEvent(const nsKeyEvent* aKeyEvent,
173 nsMouseEvent* aCMEvent)
175 memcpy(aCMEvent, aKeyEvent, sizeof(nsInputEvent));
176 // aCMEvent->message = NS_CONTEXTMENU_KEY;
177 aCMEvent->isShift = aCMEvent->isControl = PR_FALSE;
178 aCMEvent->isControl = PR_FALSE;
179 aCMEvent->isAlt = aCMEvent->isMeta = PR_FALSE;
180 aCMEvent->isMeta = PR_FALSE;
181 aCMEvent->clickCount = 0;
182 aCMEvent->acceptActivation = PR_FALSE;
185 nsWindow::nsWindow()
187 LOG(("%s [%p]\n", __PRETTY_FUNCTION__, (void *)this));
189 mIsTopLevel = PR_FALSE;
190 mIsDestroyed = PR_FALSE;
191 mIsShown = PR_FALSE;
192 mEnabled = PR_TRUE;
194 mPreferredWidth = 0;
195 mPreferredHeight = 0;
197 mDrawingArea = nsnull;
198 mIsVisible = PR_FALSE;
199 mActivatePending = PR_FALSE;
200 mWindowType = eWindowType_child;
201 mSizeState = nsSizeMode_Normal;
202 mPluginType = PluginType_NONE;
203 mQCursor = Qt::ArrowCursor;
205 if (!gGlobalsInitialized) {
206 gGlobalsInitialized = PR_TRUE;
208 // It's OK if either of these fail, but it may not be one day.
209 initialize_prefs();
212 memset(mKeyDownFlags, 0, sizeof(mKeyDownFlags));
214 mIsTransparent = PR_FALSE;
216 mCursor = eCursor_standard;
219 nsWindow::~nsWindow()
221 LOG(("%s [%p]\n", __PRETTY_FUNCTION__, (void *)this));
223 Destroy();
226 /* XXX - this gets called right after CreateQWidget, which also
227 * sets mDrawingArea. We probably want to always pass a MozQWidget
228 * here; things won't really work at all with any generic widget.
230 void
231 nsWindow::Initialize(QWidget *widget)
233 LOG(("%s [%p]\n", __PRETTY_FUNCTION__, (void *)this));
235 Q_ASSERT(widget);
237 mDrawingArea = widget;
238 mDrawingArea->setMouseTracking(PR_TRUE);
239 mDrawingArea->setFocusPolicy(Qt::WheelFocus);
242 /* static */ void
243 nsWindow::ReleaseGlobals()
247 NS_IMPL_ISUPPORTS_INHERITED1(nsWindow, nsBaseWidget, nsISupportsWeakReference)
249 NS_IMETHODIMP
250 nsWindow::Create(nsIWidget *aParent,
251 const nsRect &aRect,
252 EVENT_CALLBACK aHandleEventFunction,
253 nsIDeviceContext *aContext,
254 nsIAppShell *aAppShell,
255 nsIToolkit *aToolkit,
256 nsWidgetInitData *aInitData)
258 LOG(("%s [%p]\n", __PRETTY_FUNCTION__, (void *)this));
260 nsresult rv = NativeCreate(aParent, nsnull, aRect, aHandleEventFunction,
261 aContext, aAppShell, aToolkit, aInitData);
262 return rv;
265 NS_IMETHODIMP
266 nsWindow::Create(nsNativeWidget aParent,
267 const nsRect &aRect,
268 EVENT_CALLBACK aHandleEventFunction,
269 nsIDeviceContext *aContext,
270 nsIAppShell *aAppShell,
271 nsIToolkit *aToolkit,
272 nsWidgetInitData *aInitData)
274 LOG(("%s [%p]\n", __PRETTY_FUNCTION__, (void *)this));
276 nsresult rv = NativeCreate(nsnull, aParent, aRect, aHandleEventFunction,
277 aContext, aAppShell, aToolkit, aInitData);
278 return rv;
281 NS_IMETHODIMP
282 nsWindow::Destroy(void)
284 if (mIsDestroyed || !mDrawingArea)
285 return NS_OK;
287 LOG(("nsWindow::Destroy [%p]\n", (void *)this));
288 mIsDestroyed = PR_TRUE;
290 nsCOMPtr<nsIWidget> rollupWidget = do_QueryReferent(gRollupWindow);
291 if (static_cast<nsIWidget *>(this) == rollupWidget.get()) {
292 if (gRollupListener)
293 gRollupListener->Rollup(nsnull);
294 gRollupWindow = nsnull;
295 gRollupListener = nsnull;
298 Show(PR_FALSE);
300 // walk the list of children and call destroy on them. Have to be
301 // careful, though -- calling destroy on a kid may actually remove
302 // it from our child list, losing its sibling links.
303 for (nsIWidget* kid = mFirstChild; kid; ) {
304 nsIWidget* next = kid->GetNextSibling();
305 kid->Destroy();
306 kid = next;
309 // Destroy thebes surface now. Badness can happen if we destroy
310 // the surface after its X Window.
311 mThebesSurface = nsnull;
313 if (mMozQWidget) {
314 mMozQWidget->dropReceiver();
316 // Call deleteLater instead of delete; Qt still needs the object
317 // to be valid even after sending it a Close event. We could
318 // also set WA_DeleteOnClose, but this gives us more control.
319 mMozQWidget->deleteLater();
322 mDrawingArea = nsnull;
324 OnDestroy();
326 return NS_OK;
329 NS_IMETHODIMP
330 nsWindow::SetParent(nsIWidget *aNewParent)
332 NS_ENSURE_ARG_POINTER(aNewParent);
334 QWidget* newParentWindow =
335 static_cast<QWidget*>(aNewParent->GetNativeData(NS_NATIVE_WINDOW));
336 NS_ASSERTION(newParentWindow, "Parent widget has a null native window handle");
338 if (mDrawingArea) {
339 qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
340 // moz_drawingarea_reparent(mDrawingArea, newParentWindow);
341 } else {
342 NS_NOTREACHED("nsWindow::SetParent - reparenting a non-child window");
344 return NS_OK;
347 NS_IMETHODIMP
348 nsWindow::SetModal(PRBool aModal)
350 LOG(("nsWindow::SetModal [%p] %d, widget[%p]\n", (void *)this, aModal, mDrawingArea));
352 MozQWidget *mozWidget = static_cast<MozQWidget*>(mDrawingArea);
353 if (mozWidget)
354 mozWidget->setModal(aModal);
356 return NS_OK;
359 NS_IMETHODIMP
360 nsWindow::IsVisible(PRBool & aState)
362 aState = mDrawingArea?mDrawingArea->isVisible():PR_FALSE;
363 return NS_OK;
366 NS_IMETHODIMP
367 nsWindow::ConstrainPosition(PRBool aAllowSlop, PRInt32 *aX, PRInt32 *aY)
369 if (mDrawingArea) {
370 PRInt32 screenWidth = QApplication::desktop()->width();
371 PRInt32 screenHeight = QApplication::desktop()->height();
372 if (aAllowSlop) {
373 if (*aX < (kWindowPositionSlop - mBounds.width))
374 *aX = kWindowPositionSlop - mBounds.width;
375 if (*aX > (screenWidth - kWindowPositionSlop))
376 *aX = screenWidth - kWindowPositionSlop;
377 if (*aY < (kWindowPositionSlop - mBounds.height))
378 *aY = kWindowPositionSlop - mBounds.height;
379 if (*aY > (screenHeight - kWindowPositionSlop))
380 *aY = screenHeight - kWindowPositionSlop;
381 } else {
382 if (*aX < 0)
383 *aX = 0;
384 if (*aX > (screenWidth - mBounds.width))
385 *aX = screenWidth - mBounds.width;
386 if (*aY < 0)
387 *aY = 0;
388 if (*aY > (screenHeight - mBounds.height))
389 *aY = screenHeight - mBounds.height;
393 return NS_OK;
396 NS_IMETHODIMP
397 nsWindow::Move(PRInt32 aX, PRInt32 aY)
399 LOG(("nsWindow::Move [%p] %d %d\n", (void *)this,
400 aX, aY));
402 // Since a popup window's x/y coordinates are in relation to to
403 // the parent, the parent might have moved so we always move a
404 // popup window.
405 //bool popup = mDrawingArea ? mDrawingArea->windowType() == Qt::Popup : false;
406 if (aX == mBounds.x && aY == mBounds.y &&
407 mWindowType != eWindowType_popup)
408 return NS_OK;
410 // XXX Should we do some AreBoundsSane check here?
413 if (!mDrawingArea)
414 return NS_OK;
416 QPoint pos(aX, aY);
417 if (mDrawingArea) {
418 if (mParent && mDrawingArea->windowType() == Qt::Popup) {
419 nsRect oldrect, newrect;
420 oldrect.x = aX;
421 oldrect.y = aY;
423 mParent->WidgetToScreen(oldrect, newrect);
425 pos = QPoint(newrect.x, newrect.y);
426 #ifdef DEBUG_WIDGETS
427 qDebug("pos is [%d,%d]", pos.x(), pos.y());
428 #endif
429 } else {
430 qDebug("Widget within another? (%p)", (void*)mDrawingArea);
434 mBounds.x = pos.x();
435 mBounds.y = pos.y();
437 mDrawingArea->move(pos);
439 return NS_OK;
442 NS_IMETHODIMP
443 nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
444 nsIWidget *aWidget,
445 PRBool aActivate)
447 return NS_ERROR_NOT_IMPLEMENTED;
450 NS_IMETHODIMP
451 nsWindow::SetZIndex(PRInt32 aZIndex)
453 nsIWidget* oldPrev = GetPrevSibling();
455 nsBaseWidget::SetZIndex(aZIndex);
457 if (GetPrevSibling() == oldPrev) {
458 return NS_OK;
461 NS_ASSERTION(!mDrawingArea, "Expected Mozilla child widget");
463 // We skip the nsWindows that don't have mDrawingAreas.
464 // These are probably in the process of being destroyed.
466 if (!GetNextSibling()) {
467 // We're to be on top.
468 if (mDrawingArea) {
469 qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
470 // gdk_window_raise(mDrawingArea->clip_window);
472 } else {
473 // All the siblings before us need to be below our widget.
474 for (nsWindow* w = this; w;
475 w = static_cast<nsWindow*>(w->GetPrevSibling())) {
476 if (w->mDrawingArea) {
477 qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
478 // gdk_window_lower(w->mDrawingArea->clip_window);
482 return NS_OK;
485 NS_IMETHODIMP
486 nsWindow::SetSizeMode(PRInt32 aMode)
488 nsresult rv;
490 LOG(("nsWindow::SetSizeMode [%p] %d\n", (void *)this, aMode));
492 // Save the requested state.
493 rv = nsBaseWidget::SetSizeMode(aMode);
495 // return if there's no shell or our current state is the same as
496 // the mode we were just set to.
497 if (!mDrawingArea || mSizeState == mSizeMode) {
498 return rv;
501 switch (aMode) {
502 case nsSizeMode_Maximized:
503 mDrawingArea->showMaximized();
504 break;
505 case nsSizeMode_Minimized:
506 mDrawingArea->showMinimized();
507 break;
508 default:
509 // nsSizeMode_Normal, really.
510 mDrawingArea->showNormal ();
511 // KILLME
512 //if (mSizeState == nsSizeMode_Minimized)
513 // gtk_window_deiconify(GTK_WINDOW(mDrawingArea));
514 //else if (mSizeState == nsSizeMode_Maximized)
515 // gtk_window_unmaximize(GTK_WINDOW(mDrawingArea));
516 break;
519 mSizeState = mSizeMode;
521 return rv;
524 typedef void (* SetUserTimeFunc)(QWidget* aWindow, quint32 aTimestamp);
526 // This will become obsolete when new GTK APIs are widely supported,
527 // as described here: http://bugzilla.gnome.org/show_bug.cgi?id=347375
529 static void
530 SetUserTimeAndStartupIDForActivatedWindow(QWidget* aWindow)
532 nsCOMPtr<nsIToolkit> toolkit;
533 NS_GetCurrentToolkit(getter_AddRefs(toolkit));
534 if (!toolkit)
535 return;
537 nsToolkit* QTToolkit = static_cast<nsToolkit*>
538 (static_cast<nsIToolkit*>(toolkit));
539 nsCAutoString desktopStartupID;
540 QTToolkit->GetDesktopStartupID(&desktopStartupID);
541 if (desktopStartupID.IsEmpty()) {
542 // We don't have the data we need. Fall back to an
543 // approximation ... using the timestamp of the remote command
544 // being received as a guess for the timestamp of the user event
545 // that triggered it.
546 PRUint32 timestamp = QTToolkit->GetFocusTimestamp();
547 if (timestamp) {
548 aWindow->focusWidget ();
549 // gdk_window_focus(aWindow->window, timestamp);
550 QTToolkit->SetFocusTimestamp(0);
552 return;
555 QTToolkit->SetDesktopStartupID(EmptyCString());
559 NS_IMETHODIMP
560 nsWindow::SetFocus(PRBool aRaise)
562 // Make sure that our owning widget has focus. If it doesn't try to
563 // grab it. Note that we don't set our focus flag in this case.
565 LOGFOCUS((" SetFocus [%p]\n", (void *)this));
567 if (!mDrawingArea)
568 return NS_ERROR_FAILURE;
570 if (aRaise)
571 mDrawingArea->raise();
572 mDrawingArea->setFocus();
574 // If there is already a focused child window, dispatch a LOSTFOCUS
575 // event from that widget and unset its got focus flag.
577 LOGFOCUS((" widget now has focus - dispatching events [%p]\n",
578 (void *)this));
580 DispatchGotFocusEvent();
582 LOGFOCUS((" done dispatching events in SetFocus() [%p]\n",
583 (void *)this));
585 return NS_OK;
588 NS_IMETHODIMP
589 nsWindow::GetScreenBounds(nsRect &aRect)
591 nsRect origin(0, 0, mBounds.width, mBounds.height);
592 WidgetToScreen(origin, aRect);
593 LOG(("GetScreenBounds %d %d | %d %d | %d %d\n",
594 aRect.x, aRect.y,
595 mBounds.width, mBounds.height,
596 aRect.width, aRect.height));
597 return NS_OK;
600 NS_IMETHODIMP
601 nsWindow::SetForegroundColor(const nscolor &aColor)
603 return NS_ERROR_NOT_IMPLEMENTED;
606 NS_IMETHODIMP
607 nsWindow::SetBackgroundColor(const nscolor &aColor)
609 return NS_ERROR_NOT_IMPLEMENTED;
612 NS_IMETHODIMP
613 nsWindow::SetCursor(nsCursor aCursor)
615 mCursor = aCursor;
616 if (mMozQWidget)
617 mMozQWidget->SetCursor(mCursor);
618 return NS_OK;
622 static
623 PRUint8* Data32BitTo1Bit(PRUint8* aImageData,
624 PRUint32 aImageBytesPerRow,
625 PRUint32 aWidth, PRUint32 aHeight)
627 PRUint32 outBpr = (aWidth + 7) / 8;
629 PRUint8* outData = new PRUint8[outBpr * aHeight];
630 if (!outData)
631 return NULL;
633 PRUint8 *outRow = outData,
634 *imageRow = aImageData;
636 for (PRUint32 curRow = 0; curRow < aHeight; curRow++) {
637 PRUint8 *irow = imageRow;
638 PRUint8 *orow = outRow;
639 PRUint8 imagePixels = 0;
640 PRUint8 offset = 0;
642 for (PRUint32 curCol = 0; curCol < aWidth; curCol++) {
643 PRUint8 r = *imageRow++,
644 g = *imageRow++,
645 b = *imageRow++;
646 imageRow++;
648 if ((r + b + g) < 3 * 128)
649 imagePixels |= (1 << offset);
651 if (offset == 7) {
652 *outRow++ = imagePixels;
653 offset = 0;
654 imagePixels = 0;
655 } else {
656 offset++;
659 if (offset != 0)
660 *outRow++ = imagePixels;
662 imageRow = irow + aImageBytesPerRow;
663 outRow = orow + outBpr;
666 return outData;
671 NS_IMETHODIMP
672 nsWindow::SetCursor(imgIContainer* aCursor,
673 PRUint32 aHotspotX, PRUint32 aHotspotY)
675 nsresult rv = NS_ERROR_OUT_OF_MEMORY;
676 qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
677 return rv;
681 NS_IMETHODIMP
682 nsWindow::Validate()
684 // Get the update for this window and, well, just drop it on the
685 // floor.
686 if (!mDrawingArea)
687 return NS_OK;
689 qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
691 return NS_OK;
694 NS_IMETHODIMP
695 nsWindow::Invalidate(PRBool aIsSynchronous)
697 LOGDRAW(("Invalidate (all) [%p]: \n", (void *)this));
699 if (!mDrawingArea)
700 return NS_OK;
702 if (aIsSynchronous && !mDrawingArea->paintingActive())
703 mDrawingArea->repaint();
704 else
705 mDrawingArea->update();
707 return NS_OK;
710 NS_IMETHODIMP
711 nsWindow::Invalidate(const nsRect &aRect,
712 PRBool aIsSynchronous)
714 LOGDRAW(("Invalidate (rect) [%p,%p]: %d %d %d %d (sync: %d)\n", (void *)this,
715 (void*)mDrawingArea,aRect.x, aRect.y, aRect.width, aRect.height, aIsSynchronous));
717 if (!mDrawingArea)
718 return NS_OK;
720 if (aIsSynchronous)
721 mDrawingArea->repaint(aRect.x, aRect.y, aRect.width, aRect.height);
722 else {
723 mDrawingArea->update(aRect.x, aRect.y, aRect.width, aRect.height);
726 return NS_OK;
729 NS_IMETHODIMP
730 nsWindow::InvalidateRegion(const nsIRegion* aRegion,
731 PRBool aIsSynchronous)
734 QRegion *region = nsnull;
735 aRegion->GetNativeRegion((void *&)region);
737 if (region && mDrawingArea) {
738 QRect rect = region->boundingRect();
740 // LOGDRAW(("Invalidate (region) [%p]: %d %d %d %d (sync: %d)\n",
741 // (void *)this,
742 // rect.x, rect.y, rect.width, rect.height, aIsSynchronous));
744 if (aIsSynchronous && !mDrawingArea->paintingActive())
745 mDrawingArea->repaint(*region);
746 else
747 mDrawingArea->update(*region);
749 else {
750 qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
751 LOGDRAW(("Invalidate (region) [%p] with empty region\n",
752 (void *)this));
755 return NS_OK;
758 NS_IMETHODIMP
759 nsWindow::Update()
761 if (!mDrawingArea)
762 return NS_OK;
764 // mDrawingArea->update(); // FIXME This call cause update for whole window on each scroll event
765 return NS_OK;
768 NS_IMETHODIMP
769 nsWindow::SetColorMap(nsColorMap *aColorMap)
771 return NS_ERROR_NOT_IMPLEMENTED;
774 NS_IMETHODIMP
775 nsWindow::Scroll(PRInt32 aDx,
776 PRInt32 aDy,
777 nsRect *aClipRect)
779 if (!mDrawingArea)
780 return NS_OK;
782 mDrawingArea->scroll(aDx, aDy);
784 // Update bounds on our child windows
785 for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
786 nsRect bounds;
787 kid->GetBounds(bounds);
788 bounds.x += aDx;
789 bounds.y += aDy;
790 static_cast<nsBaseWidget*>(kid)->SetBounds(bounds);
793 return NS_OK;
796 NS_IMETHODIMP
797 nsWindow::ScrollWidgets(PRInt32 aDx,
798 PRInt32 aDy)
800 if (!mDrawingArea)
801 return NS_OK;
803 mDrawingArea->scroll(aDx, aDy);
805 return NS_OK;
808 NS_IMETHODIMP
809 nsWindow::ScrollRect(nsRect &aSrcRect,
810 PRInt32 aDx,
811 PRInt32 aDy)
813 return NS_ERROR_NOT_IMPLEMENTED;
816 void*
817 nsWindow::GetNativeData(PRUint32 aDataType)
819 switch (aDataType) {
820 case NS_NATIVE_WINDOW:
821 case NS_NATIVE_WIDGET: {
822 if (!mDrawingArea)
823 return nsnull;
825 return mDrawingArea;
826 break;
829 case NS_NATIVE_PLUGIN_PORT:
830 return SetupPluginPort();
831 break;
833 #ifdef Q_WS_X11
834 case NS_NATIVE_DISPLAY:
835 return mDrawingArea->x11Info().display();
836 break;
837 #endif
839 case NS_NATIVE_GRAPHIC: {
840 NS_ASSERTION(nsnull != mToolkit, "NULL toolkit, unable to get a GC");
841 return (void *)static_cast<nsToolkit *>(mToolkit)->GetSharedGC();
842 break;
845 case NS_NATIVE_SHELLWIDGET:
846 return (void *) mDrawingArea;
848 default:
849 NS_WARNING("nsWindow::GetNativeData called with bad value");
850 return nsnull;
854 NS_IMETHODIMP
855 nsWindow::SetBorderStyle(nsBorderStyle aBorderStyle)
857 return NS_ERROR_NOT_IMPLEMENTED;
860 NS_IMETHODIMP
861 nsWindow::SetTitle(const nsAString& aTitle)
863 if (mDrawingArea) {
864 QString qStr(QString::fromUtf16(aTitle.BeginReading(), aTitle.Length()));
865 mDrawingArea->setWindowTitle(qStr);
868 return NS_OK;
871 NS_IMETHODIMP
872 nsWindow::SetIcon(const nsAString& aIconSpec)
874 if (!mDrawingArea)
875 return NS_OK;
877 nsCOMPtr<nsILocalFile> iconFile;
878 nsCAutoString path;
879 nsCStringArray iconList;
881 // Look for icons with the following suffixes appended to the base name.
882 // The last two entries (for the old XPM format) will be ignored unless
883 // no icons are found using the other suffixes. XPM icons are depricated.
885 const char extensions[6][7] = { ".png", "16.png", "32.png", "48.png",
886 ".xpm", "16.xpm" };
888 for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(extensions); i++) {
889 // Don't bother looking for XPM versions if we found a PNG.
890 if (i == NS_ARRAY_LENGTH(extensions) - 2 && iconList.Count())
891 break;
893 nsAutoString extension;
894 extension.AppendASCII(extensions[i]);
896 ResolveIconName(aIconSpec, extension, getter_AddRefs(iconFile));
897 if (iconFile) {
898 iconFile->GetNativePath(path);
899 iconList.AppendCString(path);
903 // leave the default icon intact if no matching icons were found
904 if (iconList.Count() == 0)
905 return NS_OK;
907 return SetWindowIconList(iconList);
910 NS_IMETHODIMP
911 nsWindow::ShowMenuBar(PRBool aShow)
913 return NS_ERROR_NOT_IMPLEMENTED;
916 NS_IMETHODIMP
917 nsWindow::WidgetToScreen(const nsRect& aOldRect, nsRect& aNewRect)
919 NS_ENSURE_TRUE(mDrawingArea, NS_OK);
921 QPoint origin(aOldRect.x, aOldRect.y);
922 origin = mDrawingArea->mapToGlobal(origin);
924 aNewRect.x = origin.x();
925 aNewRect.y = origin.y();
926 aNewRect.width = aOldRect.width;
927 aNewRect.height = aOldRect.height;
929 return NS_OK;
932 NS_IMETHODIMP
933 nsWindow::ScreenToWidget(const nsRect& aOldRect, nsRect& aNewRect)
935 NS_ENSURE_TRUE(mDrawingArea, NS_OK);
937 QPoint origin(aOldRect.x, aOldRect.y);
938 origin = mDrawingArea->mapFromGlobal(origin);
940 aNewRect.x = origin.x();
941 aNewRect.y = origin.y();
942 aNewRect.width = aOldRect.width;
943 aNewRect.height = aOldRect.height;
945 return NS_OK;
948 NS_IMETHODIMP
949 nsWindow::BeginResizingChildren(void)
951 return NS_ERROR_NOT_IMPLEMENTED;
954 NS_IMETHODIMP
955 nsWindow::EndResizingChildren(void)
957 return NS_ERROR_NOT_IMPLEMENTED;
960 NS_IMETHODIMP
961 nsWindow::EnableDragDrop(PRBool aEnable)
963 mDrawingArea->setAcceptDrops(aEnable);
964 return NS_OK;
967 void
968 nsWindow::ConvertToDeviceCoordinates(nscoord &aX,
969 nscoord &aY)
973 NS_IMETHODIMP
974 nsWindow::PreCreateWidget(nsWidgetInitData *aWidgetInitData)
976 if (nsnull != aWidgetInitData) {
977 mWindowType = aWidgetInitData->mWindowType;
978 mBorderStyle = aWidgetInitData->mBorderStyle;
979 return NS_OK;
981 return NS_ERROR_FAILURE;
984 NS_IMETHODIMP
985 nsWindow::CaptureMouse(PRBool aCapture)
987 LOG(("CaptureMouse %p\n", (void *)this));
989 if (!mDrawingArea)
990 return NS_OK;
992 if (aCapture)
993 mDrawingArea->grabMouse();
994 else
995 mDrawingArea->releaseMouse();
997 return NS_OK;
1000 NS_IMETHODIMP
1001 nsWindow::CaptureRollupEvents(nsIRollupListener *aListener,
1002 PRBool aDoCapture,
1003 PRBool aConsumeRollupEvent)
1005 if (!mDrawingArea)
1006 return NS_OK;
1008 LOG(("CaptureRollupEvents %p\n", (void *)this));
1010 if (aDoCapture) {
1011 gConsumeRollupEvent = aConsumeRollupEvent;
1012 gRollupListener = aListener;
1013 gRollupWindow = do_GetWeakReference(static_cast<nsIWidget*>(this));
1015 else {
1016 gRollupListener = nsnull;
1017 gRollupWindow = nsnull;
1020 return NS_OK;
1023 PRBool
1024 check_for_rollup(double aMouseX, double aMouseY,
1025 PRBool aIsWheel)
1027 PRBool retVal = PR_FALSE;
1028 nsCOMPtr<nsIWidget> rollupWidget = do_QueryReferent(gRollupWindow);
1030 if (rollupWidget && gRollupListener) {
1031 QWidget *currentPopup =
1032 (QWidget *)rollupWidget->GetNativeData(NS_NATIVE_WINDOW);
1034 if (!is_mouse_in_window(currentPopup, aMouseX, aMouseY)) {
1035 PRBool rollup = PR_TRUE;
1036 if (aIsWheel) {
1037 gRollupListener->ShouldRollupOnMouseWheelEvent(&rollup);
1038 retVal = PR_TRUE;
1040 // if we're dealing with menus, we probably have submenus and
1041 // we don't want to rollup if the clickis in a parent menu of
1042 // the current submenu
1043 nsCOMPtr<nsIMenuRollup> menuRollup;
1044 menuRollup = (do_QueryInterface(gRollupListener));
1045 if (menuRollup) {
1046 nsAutoTArray<nsIWidget*, 5> widgetChain;
1047 menuRollup->GetSubmenuWidgetChain(&widgetChain);
1048 for (PRUint32 i=0; i<widgetChain.Length(); ++i) {
1049 nsIWidget* widget = widgetChain[i];
1050 QWidget* currWindow =
1051 (QWidget*) widget->GetNativeData(NS_NATIVE_WINDOW);
1052 if (is_mouse_in_window(currWindow, aMouseX, aMouseY)) {
1053 rollup = PR_FALSE;
1054 break;
1056 } // foreach parent menu widget
1057 } // if rollup listener knows about menus
1059 // if we've determined that we should still rollup, do it.
1060 if (rollup) {
1061 gRollupListener->Rollup(nsnull);
1062 retVal = PR_TRUE;
1065 } else {
1066 gRollupWindow = nsnull;
1067 gRollupListener = nsnull;
1070 return retVal;
1073 /* static */
1074 PRBool
1075 is_mouse_in_window (QWidget* aWindow, double aMouseX, double aMouseY)
1077 int x = 0;
1078 int y = 0;
1079 int w, h;
1081 x = aWindow->pos().x();
1082 y = aWindow->pos().y();
1083 w = aWindow->size().width();
1084 h = aWindow->size().height();
1086 if (aMouseX > x && aMouseX < x + w &&
1087 aMouseY > y && aMouseY < y + h)
1088 return PR_TRUE;
1090 return PR_FALSE;
1093 NS_IMETHODIMP
1094 nsWindow::GetAttention(PRInt32 aCycleCount)
1096 LOG(("nsWindow::GetAttention [%p]\n", (void *)this));
1098 SetUrgencyHint(mDrawingArea, PR_TRUE);
1100 return NS_OK;
1103 void
1104 nsWindow::LoseFocus(void)
1106 // make sure that we reset our key down counter so the next keypress
1107 // for this widget will get the down event
1108 memset(mKeyDownFlags, 0, sizeof(mKeyDownFlags));
1110 // Dispatch a lostfocus event
1111 DispatchLostFocusEvent();
1113 LOGFOCUS((" widget lost focus [%p]\n", (void *)this));
1116 static int gDoubleBuffering = -1;
1118 nsEventStatus
1119 nsWindow::OnPaintEvent(QPaintEvent *aEvent)
1121 //fprintf (stderr, "===== Expose start\n");
1123 if (mIsDestroyed) {
1124 LOG(("Expose event on destroyed window [%p] window %p\n",
1125 (void *)this, mDrawingArea));
1126 return nsEventStatus_eIgnore;
1129 if (!mDrawingArea)
1130 return nsEventStatus_eIgnore;
1132 static NS_DEFINE_CID(kRegionCID, NS_REGION_CID);
1134 nsCOMPtr<nsIRegion> updateRegion = do_CreateInstance(kRegionCID);
1135 if (!updateRegion)
1136 return nsEventStatus_eIgnore;
1138 updateRegion->Init();
1140 QVector<QRect> rects = aEvent->region().rects();
1142 LOGDRAW(("[%p] sending expose event %p 0x%lx (rects follow):\n",
1143 (void *)this, (void *)aEvent, 0));
1145 for (int i = 0; i < rects.size(); ++i) {
1146 QRect r = rects.at(i);
1147 updateRegion->Union(r.x(), r.y(), r.width(), r.height());
1148 LOGDRAW(("\t%d %d %d %d\n", r.x(), r.y(), r.width(), r.height()));
1151 QPainter painter;
1153 if (!painter.begin(mDrawingArea)) {
1154 fprintf (stderr, "*********** Failed to begin painting!\n");
1155 return nsEventStatus_eConsumeNoDefault;
1158 nsRefPtr<gfxQPainterSurface> targetSurface = new gfxQPainterSurface(&painter);
1159 nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
1161 nsCOMPtr<nsIRenderingContext> rc;
1162 GetDeviceContext()->CreateRenderingContextInstance(*getter_AddRefs(rc));
1163 if (NS_UNLIKELY(!rc))
1164 return nsEventStatus_eIgnore;
1166 rc->Init(GetDeviceContext(), ctx);
1168 nsIntRect boundsRect;
1170 updateRegion->GetBoundingBox(&boundsRect.x, &boundsRect.y,
1171 &boundsRect.width, &boundsRect.height);
1173 nsPaintEvent event(PR_TRUE, NS_PAINT, this);
1174 QRect r = aEvent->rect();
1175 if (!r.isValid())
1176 r = mDrawingArea->rect();
1177 nsRect rect(r.x(), r.y(), r.width(), r.height());
1178 event.refPoint.x = aEvent->rect().x();
1179 event.refPoint.y = aEvent->rect().y();
1180 event.rect = &rect; // was null FIXME
1181 event.region = updateRegion;
1182 event.renderingContext = rc;
1184 nsEventStatus status = DispatchEvent(&event);
1185 //nsEventStatus status = nsEventStatus_eConsumeNoDefault;
1187 // DispatchEvent can Destroy us (bug 378273), avoid doing any paint
1188 // operations below if that happened - it will lead to XError and exit().
1189 if (NS_UNLIKELY(mIsDestroyed))
1190 return status;
1192 if (status == nsEventStatus_eIgnore)
1193 return status;
1195 LOGDRAW(("[%p] draw done\n", this));
1197 ctx = nsnull;
1198 targetSurface = nsnull;
1200 //fprintf (stderr, "===== Expose end\n");
1202 // check the return value!
1203 return status;
1206 nsEventStatus
1207 nsWindow::OnMoveEvent(QMoveEvent *aEvent)
1209 LOG(("configure event [%p] %d %d\n", (void *)this,
1210 aEvent->pos().x(), aEvent->pos().y()));
1212 // can we shortcut?
1213 if (!mDrawingArea)
1214 return nsEventStatus_eIgnore;
1216 if ((mBounds.x == aEvent->pos().x() &&
1217 mBounds.y == aEvent->pos().y()))
1219 return nsEventStatus_eIgnore;
1222 // Toplevel windows need to have their bounds set so that we can
1223 // keep track of our location. It's not often that the x,y is set
1224 // by the layout engine. Width and height are set elsewhere.
1225 QPoint pos = aEvent->pos();
1226 if (mIsTopLevel) {
1227 // Need to translate this into the right coordinates
1228 nsRect oldrect, newrect;
1229 WidgetToScreen(oldrect, newrect);
1230 mBounds.x = newrect.x;
1231 mBounds.y = newrect.y;
1234 nsGUIEvent event(PR_TRUE, NS_MOVE, this);
1236 event.refPoint.x = pos.x();
1237 event.refPoint.y = pos.y();
1239 // XXX mozilla will invalidate the entire window after this move
1240 // complete. wtf?
1241 return DispatchEvent(&event);
1244 nsEventStatus
1245 nsWindow::OnResizeEvent(QResizeEvent *e)
1247 nsRect rect;
1249 // Generate XPFE resize event
1250 GetBounds(rect);
1252 rect.width = e->size().width();
1253 rect.height = e->size().height();
1255 LOG(("size_allocate [%p] %d %d\n",
1256 (void *)this, rect.width, rect.height));
1258 mBounds.width = rect.width;
1259 mBounds.height = rect.height;
1261 #ifdef DEBUG_WIDGETS
1262 qDebug("resizeEvent: mDrawingArea=%p, aWidth=%d, aHeight=%d, aX = %d, aY = %d", (void*)mDrawingArea,
1263 rect.width, rect.height, rect.x, rect.y);
1264 #endif
1266 if (mDrawingArea)
1267 mDrawingArea->resize(rect.width, rect.height);
1269 nsEventStatus status;
1270 DispatchResizeEvent(rect, status);
1271 return status;
1274 nsEventStatus
1275 nsWindow::OnCloseEvent(QCloseEvent *aEvent)
1277 nsGUIEvent event(PR_TRUE, NS_XUL_CLOSE, this);
1279 event.refPoint.x = 0;
1280 event.refPoint.y = 0;
1282 return DispatchEvent(&event);
1285 nsEventStatus
1286 nsWindow::OnEnterNotifyEvent(QEvent *aEvent)
1288 nsMouseEvent event(PR_TRUE, NS_MOUSE_ENTER, this, nsMouseEvent::eReal);
1290 QPoint pt = QCursor::pos();
1292 event.refPoint.x = nscoord(pt.x());
1293 event.refPoint.y = nscoord(pt.y());
1295 LOG(("OnEnterNotify: %p\n", (void *)this));
1297 return DispatchEvent(&event);
1300 nsEventStatus
1301 nsWindow::OnLeaveNotifyEvent(QEvent *aEvent)
1303 nsMouseEvent event(PR_TRUE, NS_MOUSE_EXIT, this, nsMouseEvent::eReal);
1305 QPoint pt = QCursor::pos();
1307 event.refPoint.x = nscoord(pt.x());
1308 event.refPoint.y = nscoord(pt.y());
1310 LOG(("OnLeaveNotify: %p\n", (void *)this));
1312 return DispatchEvent(&event);
1315 nsEventStatus
1316 nsWindow::OnMotionNotifyEvent(QMouseEvent *aEvent)
1318 // when we receive this, it must be that the gtk dragging is over,
1319 // it is dropped either in or out of mozilla, clear the flag
1320 //mDrawingArea->setCursor(mQCursor);
1322 nsMouseEvent event(PR_TRUE, NS_MOUSE_MOVE, this, nsMouseEvent::eReal);
1325 event.refPoint.x = nscoord(aEvent->x());
1326 event.refPoint.y = nscoord(aEvent->y());
1328 event.isShift = aEvent->modifiers() & Qt::ShiftModifier;
1329 event.isControl = aEvent->modifiers() & Qt::ControlModifier;
1330 event.isAlt = aEvent->modifiers() & Qt::AltModifier;
1331 event.isMeta = aEvent->modifiers() & Qt::MetaModifier;
1332 event.clickCount = 0;
1334 nsEventStatus status = DispatchEvent(&event);
1336 //fprintf (stderr, "[%p] %p MotionNotify -> %d\n", this, mDrawingArea, status);
1338 return status;
1341 void
1342 nsWindow::InitButtonEvent(nsMouseEvent &event,
1343 QMouseEvent *aEvent, int aClickCount)
1345 event.refPoint.x = nscoord(aEvent->x());
1346 event.refPoint.y = nscoord(aEvent->y());
1348 event.isShift = aEvent->modifiers() & Qt::ShiftModifier;
1349 event.isControl = aEvent->modifiers() & Qt::ControlModifier;
1350 event.isAlt = aEvent->modifiers() & Qt::AltModifier;
1351 event.isMeta = aEvent->modifiers() & Qt::MetaModifier;
1352 event.clickCount = aClickCount;
1355 nsEventStatus
1356 nsWindow::OnButtonPressEvent(QMouseEvent *aEvent)
1358 PRBool rolledUp = check_for_rollup(aEvent->globalX(),
1359 aEvent->globalY(), PR_FALSE);
1360 if (gConsumeRollupEvent && rolledUp)
1361 return nsEventStatus_eIgnore;
1363 PRUint16 domButton;
1364 switch (aEvent->button()) {
1365 case Qt::MidButton:
1366 domButton = nsMouseEvent::eMiddleButton;
1367 break;
1368 case Qt::RightButton:
1369 domButton = nsMouseEvent::eRightButton;
1370 break;
1371 default:
1372 domButton = nsMouseEvent::eLeftButton;
1373 break;
1376 nsMouseEvent event(PR_TRUE, NS_MOUSE_BUTTON_DOWN, this, nsMouseEvent::eReal);
1377 event.button = domButton;
1378 InitButtonEvent(event, aEvent, 1);
1380 LOG(("%s [%p] button: %d\n", __PRETTY_FUNCTION__, (void*)this, domButton));
1382 nsEventStatus status = DispatchEvent(&event);
1384 // right menu click on linux should also pop up a context menu
1385 if (domButton == nsMouseEvent::eRightButton &&
1386 NS_LIKELY(!mIsDestroyed)) {
1387 nsMouseEvent contextMenuEvent(PR_TRUE, NS_CONTEXTMENU, this,
1388 nsMouseEvent::eReal);
1389 InitButtonEvent(contextMenuEvent, aEvent, 1);
1390 DispatchEvent(&contextMenuEvent, status);
1393 //fprintf (stderr, "[%p] %p ButtonPress -> %d\n", this, mDrawingArea, status);
1395 return status;
1398 nsEventStatus
1399 nsWindow::OnButtonReleaseEvent(QMouseEvent *aEvent)
1401 PRUint16 domButton;
1402 // mLastButtonReleaseTime = aEvent->time;
1404 switch (aEvent->button()) {
1405 case Qt::MidButton:
1406 domButton = nsMouseEvent::eMiddleButton;
1407 break;
1408 case Qt::RightButton:
1409 domButton = nsMouseEvent::eRightButton;
1410 break;
1411 default:
1412 domButton = nsMouseEvent::eLeftButton;
1413 break;
1416 LOG(("%s [%p] button: %d\n", __PRETTY_FUNCTION__, (void*)this, domButton));
1418 nsMouseEvent event(PR_TRUE, NS_MOUSE_BUTTON_UP, this, nsMouseEvent::eReal);
1419 event.button = domButton;
1420 InitButtonEvent(event, aEvent, 1);
1422 nsEventStatus status = DispatchEvent(&event);
1424 //fprintf (stderr, "[%p] %p ButtonRelease -> %d\n", this, mDrawingArea, status);
1426 return status;
1429 nsEventStatus
1430 nsWindow::mouseDoubleClickEvent(QMouseEvent *e)
1432 PRUint32 eventType;
1434 switch (e->button()) {
1435 case Qt::MidButton:
1436 eventType = nsMouseEvent::eMiddleButton;
1437 break;
1438 case Qt::RightButton:
1439 eventType = nsMouseEvent::eRightButton;
1440 break;
1441 default:
1442 eventType = nsMouseEvent::eLeftButton;
1443 break;
1446 nsMouseEvent event(PR_TRUE, NS_MOUSE_DOUBLECLICK, this, nsMouseEvent::eReal);
1447 event.button = eventType;
1449 InitButtonEvent(event, e, 2);
1450 //pressed
1451 return DispatchEvent(&event);
1454 nsEventStatus
1455 nsWindow::OnFocusInEvent(QFocusEvent *aEvent)
1457 LOGFOCUS(("OnFocusInEvent [%p]\n", (void *)this));
1458 // Return if someone has blocked events for this widget. This will
1459 // happen if someone has called gtk_widget_grab_focus() from
1460 // nsWindow::SetFocus() and will prevent recursion.
1462 if (!mDrawingArea)
1463 return nsEventStatus_eIgnore;
1465 // Unset the urgency hint, if possible
1466 // SetUrgencyHint(top_window, PR_FALSE);
1468 // dispatch a got focus event
1469 DispatchGotFocusEvent();
1471 // send the activate event if it wasn't already sent via any
1472 // SetFocus() calls that were the result of the GOTFOCUS event
1473 // above.
1474 DispatchActivateEvent();
1476 LOGFOCUS(("Events sent from focus in event [%p]\n", (void *)this));
1477 return nsEventStatus_eIgnore;
1480 nsEventStatus
1481 nsWindow::OnFocusOutEvent(QFocusEvent *aEvent)
1483 LOGFOCUS(("OnFocusOutEvent [%p]\n", (void *)this));
1485 DispatchLostFocusEvent();
1486 if (mDrawingArea)
1487 DispatchDeactivateEvent();
1489 LOGFOCUS(("Done with container focus out [%p]\n", (void *)this));
1490 return nsEventStatus_eIgnore;
1493 inline PRBool
1494 is_latin_shortcut_key(quint32 aKeyval)
1496 return ((Qt::Key_0 <= aKeyval && aKeyval <= Qt::Key_9) ||
1497 (Qt::Key_A <= aKeyval && aKeyval <= Qt::Key_Z));
1500 PRBool
1501 nsWindow::DispatchCommandEvent(nsIAtom* aCommand)
1503 nsCommandEvent event(PR_TRUE, nsWidgetAtoms::onAppCommand, aCommand, this);
1505 DispatchEvent(&event);
1507 return TRUE;
1510 nsEventStatus
1511 nsWindow::OnKeyPressEvent(QKeyEvent *aEvent)
1513 LOGFOCUS(("OnKeyPressEvent [%p]\n", (void *)this));
1515 PRBool setNoDefault = PR_FALSE;
1517 // before we dispatch a key, check if it's the context menu key.
1518 // If so, send a context menu key event instead.
1519 if (isContextMenuKeyEvent(aEvent)) {
1520 nsMouseEvent contextMenuEvent(PR_TRUE, NS_CONTEXTMENU, this,
1521 nsMouseEvent::eReal,
1522 nsMouseEvent::eContextMenuKey);
1523 //keyEventToContextMenuEvent(&event, &contextMenuEvent);
1524 return DispatchEvent(&contextMenuEvent);
1527 PRUint32 domCharCode = 0;
1528 PRUint32 domKeyCode = QtKeyCodeToDOMKeyCode(aEvent->key());
1530 if (aEvent->text().length() && aEvent->text()[0].isPrint())
1531 domCharCode = (PRInt32) aEvent->text()[0].unicode();
1533 // If the key isn't autorepeat, we need to send the initial down event
1534 if (!aEvent->isAutoRepeat() && !IsKeyDown(domKeyCode)) {
1535 // send the key down event
1537 SetKeyDownFlag(domKeyCode);
1539 nsKeyEvent downEvent(PR_TRUE, NS_KEY_DOWN, this);
1540 InitKeyEvent(downEvent, aEvent);
1542 downEvent.charCode = domCharCode;
1543 downEvent.keyCode = domCharCode ? 0 : domKeyCode;
1545 nsEventStatus status = DispatchEvent(&downEvent);
1547 // If prevent default on keydown, do same for keypress
1548 if (status == nsEventStatus_eConsumeNoDefault)
1549 setNoDefault = PR_TRUE;
1552 nsKeyEvent event(PR_TRUE, NS_KEY_PRESS, this);
1553 InitKeyEvent(event, aEvent);
1555 event.charCode = domCharCode;
1556 event.keyCode = domCharCode ? 0 : domKeyCode;
1558 if (setNoDefault)
1559 event.flags |= NS_EVENT_FLAG_NO_DEFAULT;
1561 // send the key press event
1562 return DispatchEvent(&event);
1565 nsEventStatus
1566 nsWindow::OnKeyReleaseEvent(QKeyEvent *aEvent)
1568 LOGFOCUS(("OnKeyReleaseEvent [%p]\n", (void *)this));
1570 if (isContextMenuKeyEvent(aEvent)) {
1571 // er, what do we do here? DoDefault or NoDefault?
1572 return nsEventStatus_eConsumeDoDefault;
1575 PRUint32 domCharCode = 0;
1576 PRUint32 domKeyCode = QtKeyCodeToDOMKeyCode(aEvent->key());
1578 if (aEvent->text().length() && aEvent->text()[0].isPrint())
1579 domCharCode = (PRInt32) aEvent->text()[0].unicode();
1581 // send the key event as a key up event
1582 nsKeyEvent event(PR_TRUE, NS_KEY_UP, this);
1583 InitKeyEvent(event, aEvent);
1585 event.charCode = domCharCode;
1586 event.keyCode = domCharCode ? 0 : domKeyCode;
1588 // unset the key down flag
1589 ClearKeyDownFlag(event.keyCode);
1591 return DispatchEvent(&event);
1594 nsEventStatus
1595 nsWindow::OnScrollEvent(QWheelEvent *aEvent)
1597 // check to see if we should rollup
1598 nsMouseScrollEvent event(PR_TRUE, NS_MOUSE_SCROLL, this);
1600 switch (aEvent->orientation()) {
1601 case Qt::Vertical:
1602 event.scrollFlags = nsMouseScrollEvent::kIsVertical;
1603 break;
1604 case Qt::Horizontal:
1605 event.scrollFlags = nsMouseScrollEvent::kIsHorizontal;
1606 break;
1607 default:
1608 Q_ASSERT(0);
1609 break;
1612 // negative values for aEvent->delta indicate downward scrolling;
1613 // this is opposite Gecko usage.
1615 event.delta = (int)(aEvent->delta() / WHEEL_DELTA) * -3;
1617 event.refPoint.x = nscoord(aEvent->x());
1618 event.refPoint.y = nscoord(aEvent->y());
1620 event.isShift = aEvent->modifiers() & Qt::ShiftModifier;
1621 event.isControl = aEvent->modifiers() & Qt::ControlModifier;
1622 event.isAlt = aEvent->modifiers() & Qt::AltModifier;
1623 event.isMeta = aEvent->modifiers() & Qt::MetaModifier;
1624 event.time = 0;
1626 return DispatchEvent(&event);
1630 nsEventStatus
1631 nsWindow::showEvent(QShowEvent *)
1633 LOG(("%s [%p]\n", __PRETTY_FUNCTION__,(void *)this));
1634 // qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
1636 QRect r = mDrawingArea->rect();
1637 nsRect rect(r.x(), r.y(), r.width(), r.height());
1639 nsCOMPtr<nsIRenderingContext> rc = getter_AddRefs(GetRenderingContext());
1640 // Generate XPFE paint event
1641 nsPaintEvent event(PR_TRUE, NS_PAINT, this);
1642 event.refPoint.x = 0;
1643 event.refPoint.y = 0;
1644 event.rect = &rect;
1645 // XXX fix this!
1646 event.region = nsnull;
1647 // XXX fix this!
1648 event.renderingContext = rc;
1650 return DispatchEvent(&event);
1652 mIsVisible = PR_TRUE;
1653 return nsEventStatus_eConsumeDoDefault;
1656 nsEventStatus
1657 nsWindow::hideEvent(QHideEvent *)
1659 LOG(("%s [%p]\n", __PRETTY_FUNCTION__,(void *)this));
1660 mIsVisible = PR_FALSE;
1661 return nsEventStatus_eConsumeDoDefault;
1664 nsEventStatus
1665 nsWindow::OnWindowStateEvent(QEvent *aEvent)
1667 qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
1668 nsSizeModeEvent event(PR_TRUE, NS_SIZEMODE, this);
1669 return DispatchEvent(&event);
1672 void
1673 nsWindow::ThemeChanged()
1675 nsGUIEvent event(PR_TRUE, NS_THEMECHANGED, this);
1677 DispatchEvent(&event);
1679 if (!mDrawingArea || NS_UNLIKELY(mIsDestroyed))
1680 return;
1681 qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
1682 return;
1685 nsEventStatus
1686 nsWindow::OnDragMotionEvent(QDragMoveEvent *e)
1688 LOG(("nsWindow::OnDragMotionSignal\n"));
1690 nsMouseEvent event(PR_TRUE, NS_DRAGDROP_OVER, 0,
1691 nsMouseEvent::eReal);
1692 return nsEventStatus_eIgnore;
1695 nsEventStatus
1696 nsWindow::OnDragLeaveEvent(QDragLeaveEvent *e)
1698 // XXX Do we want to pass this on only if the event's subwindow is null?
1699 LOG(("nsWindow::OnDragLeaveSignal(%p)\n", this));
1700 nsMouseEvent event(PR_TRUE, NS_DRAGDROP_EXIT, this, nsMouseEvent::eReal);
1702 return DispatchEvent(&event);
1705 nsEventStatus
1706 nsWindow::OnDragDropEvent(QDropEvent *aDropEvent)
1708 if (aDropEvent->proposedAction() == Qt::CopyAction)
1710 printf("text version of the data: %s\n", aDropEvent->mimeData()->text().toAscii().data());
1711 aDropEvent->acceptProposedAction();
1714 LOG(("nsWindow::OnDragDropSignal\n"));
1715 nsMouseEvent event(PR_TRUE, NS_DRAGDROP_OVER, 0,
1716 nsMouseEvent::eReal);
1717 return nsEventStatus_eIgnore;
1720 nsEventStatus
1721 nsWindow::OnDragEnter(QDragEnterEvent *aDragEvent)
1723 #if 0
1724 // TODO: Remove debugging prints
1725 QStringList strings = aDragEvent->mimeData()->formats();
1726 for (int i=0; i<strings.size(); ++i)
1728 printf("%i: %s\n", i, strings.at(i).toLocal8Bit().constData());
1730 #endif
1732 // Is it some format we think we can support?
1733 if ( aDragEvent->mimeData()->hasFormat(kURLMime)
1734 || aDragEvent->mimeData()->hasFormat(kURLDataMime)
1735 || aDragEvent->mimeData()->hasFormat(kURLDescriptionMime)
1736 || aDragEvent->mimeData()->hasFormat(kHTMLMime)
1737 || aDragEvent->mimeData()->hasFormat(kUnicodeMime)
1738 || aDragEvent->mimeData()->hasFormat(kTextMime)
1741 aDragEvent->acceptProposedAction();
1744 // XXX Do we want to pass this on only if the event's subwindow is null?
1746 LOG(("nsWindow::OnDragEnter(%p)\n", this));
1748 nsMouseEvent event(PR_TRUE, NS_DRAGDROP_ENTER, this, nsMouseEvent::eReal);
1749 return DispatchEvent(&event);
1752 static void
1753 GetBrandName(nsXPIDLString& brandName)
1755 nsCOMPtr<nsIStringBundleService> bundleService =
1756 do_GetService(NS_STRINGBUNDLE_CONTRACTID);
1758 nsCOMPtr<nsIStringBundle> bundle;
1759 if (bundleService)
1760 bundleService->CreateBundle(
1761 "chrome://branding/locale/brand.properties",
1762 getter_AddRefs(bundle));
1764 if (bundle)
1765 bundle->GetStringFromName(
1766 NS_LITERAL_STRING("brandShortName").get(),
1767 getter_Copies(brandName));
1769 if (brandName.IsEmpty())
1770 brandName.Assign(NS_LITERAL_STRING("Mozilla"));
1774 nsresult
1775 nsWindow::NativeCreate(nsIWidget *aParent,
1776 nsNativeWidget aNativeParent,
1777 const nsRect &aRect,
1778 EVENT_CALLBACK aHandleEventFunction,
1779 nsIDeviceContext *aContext,
1780 nsIAppShell *aAppShell,
1781 nsIToolkit *aToolkit,
1782 nsWidgetInitData *aInitData)
1784 // only set the base parent if we're going to be a dialog or a
1785 // toplevel
1786 nsIWidget *baseParent = aInitData &&
1787 (aInitData->mWindowType == eWindowType_dialog ||
1788 aInitData->mWindowType == eWindowType_toplevel ||
1789 aInitData->mWindowType == eWindowType_invisible) ?
1790 nsnull : aParent;
1792 // initialize all the common bits of this class
1793 BaseCreate(baseParent, aRect, aHandleEventFunction, aContext,
1794 aAppShell, aToolkit, aInitData);
1796 // and do our common creation
1797 mParent = aParent;
1799 // save our bounds
1800 mBounds = aRect;
1802 // figure out our parent window
1803 QWidget *parent = nsnull;
1804 if (aParent != nsnull)
1805 parent = (QWidget*)aParent->GetNativeData(NS_NATIVE_WIDGET);
1806 else
1807 parent = (QWidget*)aNativeParent;
1809 // ok, create our windows
1810 mDrawingArea = createQWidget(parent, aInitData);
1812 Initialize(mDrawingArea);
1814 LOG(("Create: nsWindow [%p] [%p]\n", (void *)this, (void *)mDrawingArea));
1816 // resize so that everything is set to the right dimensions
1817 Resize(mBounds.x, mBounds.y, mBounds.width, mBounds.height, PR_FALSE);
1819 return NS_OK;
1822 NS_IMETHODIMP
1823 nsWindow::SetWindowClass(const nsAString &xulWinType)
1825 if (!mDrawingArea)
1826 return NS_ERROR_FAILURE;
1828 nsXPIDLString brandName;
1829 GetBrandName(brandName);
1831 #ifdef Q_WS_X11
1832 XClassHint *class_hint = XAllocClassHint();
1833 if (!class_hint)
1834 return NS_ERROR_OUT_OF_MEMORY;
1835 const char *role = NULL;
1836 class_hint->res_name = ToNewCString(xulWinType);
1837 if (!class_hint->res_name) {
1838 XFree(class_hint);
1839 return NS_ERROR_OUT_OF_MEMORY;
1841 class_hint->res_class = ToNewCString(brandName);
1842 if (!class_hint->res_class) {
1843 nsMemory::Free(class_hint->res_name);
1844 XFree(class_hint);
1845 return NS_ERROR_OUT_OF_MEMORY;
1848 // Parse res_name into a name and role. Characters other than
1849 // [A-Za-z0-9_-] are converted to '_'. Anything after the first
1850 // colon is assigned to role; if there's no colon, assign the
1851 // whole thing to both role and res_name.
1852 for (char *c = class_hint->res_name; *c; c++) {
1853 if (':' == *c) {
1854 *c = 0;
1855 role = c + 1;
1857 else if (!isascii(*c) || (!isalnum(*c) && ('_' != *c) && ('-' != *c)))
1858 *c = '_';
1860 class_hint->res_name[0] = toupper(class_hint->res_name[0]);
1861 if (!role) role = class_hint->res_name;
1863 // gdk_window_set_role(GTK_WIDGET(mDrawingArea)->window, role);
1864 qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
1865 // Can't use gtk_window_set_wmclass() for this; it prints
1866 // a warning & refuses to make the change.
1867 XSetClassHint(mDrawingArea->x11Info().display(),
1868 mDrawingArea->handle(),
1869 class_hint);
1870 nsMemory::Free(class_hint->res_class);
1871 nsMemory::Free(class_hint->res_name);
1872 XFree(class_hint);
1873 #endif
1875 return NS_OK;
1878 void
1879 nsWindow::NativeResize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
1881 LOG(("nsWindow::NativeResize [%p] %d %d\n", (void *)this,
1882 aWidth, aHeight));
1884 mDrawingArea->resize( aWidth, aHeight);
1886 if (aRepaint)
1887 mDrawingArea->update();
1890 void
1891 nsWindow::NativeResize(PRInt32 aX, PRInt32 aY,
1892 PRInt32 aWidth, PRInt32 aHeight,
1893 PRBool aRepaint)
1895 LOG(("nsWindow::NativeResize [%p] %d %d %d %d\n", (void *)this,
1896 aX, aY, aWidth, aHeight));
1898 QPoint pos(aX, aY);
1899 if (mDrawingArea)
1901 if (mParent && mDrawingArea->windowType() == Qt::Popup) {
1902 nsRect oldrect, newrect;
1903 oldrect.x = aX;
1904 oldrect.y = aY;
1906 mParent->WidgetToScreen(oldrect, newrect);
1908 pos = QPoint(newrect.x, newrect.y);
1909 #ifdef DEBUG_WIDGETS
1910 qDebug("pos is [%d,%d]", pos.x(), pos.y());
1911 #endif
1912 } else {
1913 #ifdef DEBUG_WIDGETS
1914 qDebug("Widget with original position? (%p)", mDrawingArea);
1915 #endif
1919 mDrawingArea->setGeometry(pos.x(), pos.y(), aWidth, aHeight);
1921 if (aRepaint)
1922 mDrawingArea->update();
1925 NS_IMETHODIMP
1926 nsWindow::SetHasTransparentBackground(PRBool aTransparent)
1928 return NS_ERROR_NOT_IMPLEMENTED;
1931 NS_IMETHODIMP
1932 nsWindow::GetHasTransparentBackground(PRBool& aTransparent)
1934 aTransparent = mIsTransparent;
1935 return NS_OK;
1938 void
1939 nsWindow::GetToplevelWidget(QWidget **aWidget)
1941 *aWidget = nsnull;
1943 if (mDrawingArea) {
1944 *aWidget = mDrawingArea;
1945 return;
1949 void
1950 nsWindow::SetUrgencyHint(QWidget *top_window, PRBool state)
1952 if (!top_window)
1953 return;
1954 qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
1956 // Try to get a pointer to gdk_window_set_urgency_hint
1957 PRLibrary* lib;
1958 _gdk_window_set_urgency_hint_fn _gdk_window_set_urgency_hint = nsnull;
1959 _gdk_window_set_urgency_hint = (_gdk_window_set_urgency_hint_fn)
1960 PR_FindFunctionSymbolAndLibrary("gdk_window_set_urgency_hint", &lib);
1962 if (_gdk_window_set_urgency_hint) {
1963 _gdk_window_set_urgency_hint(top_window->window, state);
1964 PR_UnloadLibrary(lib);
1966 else if (state) {
1967 gdk_window_show_unraised(top_window->window);
1972 void *
1973 nsWindow::SetupPluginPort(void)
1975 if (!mDrawingArea)
1976 return nsnull;
1978 qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
1981 // we have to flush the X queue here so that any plugins that
1982 // might be running on separate X connections will be able to use
1983 // this window in case it was just created
1984 XWindowAttributes xattrs;
1985 XGetWindowAttributes(Qt::Key_DISPLAY (),
1986 Qt::Key_WINDOW_XWINDOW(mDrawingArea->inner_window),
1987 &xattrs);
1988 XSelectInput (Qt::Key_DISPLAY (),
1989 Qt::Key_WINDOW_XWINDOW(mDrawingArea->inner_window),
1990 xattrs.your_event_mask |
1991 SubstructureNotifyMask);
1993 gdk_window_add_filter(mDrawingArea->inner_window,
1994 plugin_window_filter_func,
1995 this);
1997 XSync(Qt::Key_DISPLAY(), False);
1999 return (void *)Qt::Key_WINDOW_XWINDOW(mDrawingArea->inner_window);
2001 return nsnull;
2004 nsresult
2005 nsWindow::SetWindowIconList(const nsCStringArray &aIconList)
2007 qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
2008 return NS_OK;
2011 void
2012 nsWindow::SetDefaultIcon(void)
2014 SetIcon(NS_LITERAL_STRING("default"));
2017 void
2018 nsWindow::SetPluginType(PluginType aPluginType)
2020 mPluginType = aPluginType;
2023 void
2024 nsWindow::SetNonXEmbedPluginFocus()
2026 qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
2029 void
2030 nsWindow::LoseNonXEmbedPluginFocus()
2032 qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
2033 LOGFOCUS(("nsWindow::LoseNonXEmbedPluginFocus\n"));
2034 LOGFOCUS(("nsWindow::LoseNonXEmbedPluginFocus end\n"));
2038 qint32
2039 nsWindow::ConvertBorderStyles(nsBorderStyle aStyle)
2041 qint32 w = 0;
2043 if (aStyle == eBorderStyle_default)
2044 return -1;
2046 qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
2048 if (aStyle & eBorderStyle_all)
2049 w |= Qt::Key_DECOR_ALL;
2050 if (aStyle & eBorderStyle_border)
2051 w |= Qt::Key_DECOR_BORDER;
2052 if (aStyle & eBorderStyle_resizeh)
2053 w |= Qt::Key_DECOR_RESIZEH;
2054 if (aStyle & eBorderStyle_title)
2055 w |= Qt::Key_DECOR_TITLE;
2056 if (aStyle & eBorderStyle_menu)
2057 w |= Qt::Key_DECOR_MENU;
2058 if (aStyle & eBorderStyle_minimize)
2059 w |= Qt::Key_DECOR_MINIMIZE;
2060 if (aStyle & eBorderStyle_maximize)
2061 w |= Qt::Key_DECOR_MAXIMIZE;
2062 if (aStyle & eBorderStyle_close) {
2063 #ifdef DEBUG
2064 printf("we don't handle eBorderStyle_close yet... please fix me\n");
2065 #endif
2068 return w;
2071 NS_IMETHODIMP
2072 nsWindow::MakeFullScreen(PRBool aFullScreen)
2075 #if GTK_CHECK_VERSION(2,2,0)
2076 if (aFullScreen)
2077 gdk_window_fullscreen (mDrawingArea->window);
2078 else
2079 gdk_window_unfullscreen (mDrawingArea->window);
2080 return NS_OK;
2081 #else
2083 return nsBaseWidget::MakeFullScreen(aFullScreen);
2084 //#endif
2087 NS_IMETHODIMP
2088 nsWindow::HideWindowChrome(PRBool aShouldHide)
2090 if (!mDrawingArea) {
2091 // Pass the request to the toplevel window
2092 QWidget *topWidget = nsnull;
2093 GetToplevelWidget(&topWidget);
2094 // return topWindow->HideWindowChrome(aShouldHide);
2095 return NS_ERROR_FAILURE;
2098 // Sawfish, metacity, and presumably other window managers get
2099 // confused if we change the window decorations while the window
2100 // is visible.
2101 PRBool wasVisible = PR_FALSE;
2102 if (mDrawingArea->isVisible()) {
2103 mDrawingArea->hide();
2104 wasVisible = PR_TRUE;
2107 qint32 wmd;
2108 if (aShouldHide)
2109 wmd = 0;
2110 else
2111 wmd = ConvertBorderStyles(mBorderStyle);
2113 // gdk_window_set_decorations(mDrawingArea->window, (GdkWMDecoration) wmd);
2115 if (wasVisible) {
2116 mDrawingArea->show();
2119 // For some window managers, adding or removing window decorations
2120 // requires unmapping and remapping our toplevel window. Go ahead
2121 // and flush the queue here so that we don't end up with a BadWindow
2122 // error later when this happens (when the persistence timer fires
2123 // and GetWindowPos is called)
2124 #ifdef Q_WS_X11
2125 XSync(mDrawingArea->x11Info().display(), False);
2126 #endif
2128 return NS_OK;
2131 /* static */
2133 nsWindow *
2134 get_window_for_qt_widget(QWidget *widget)
2136 MozQWidget *mozWidget = static_cast<MozQWidget*>(widget);
2137 return mozWidget->getReceiver();
2141 //////////////////////////////////////////////////////////////////////
2142 // These are all of our drag and drop operations
2144 void
2145 nsWindow::InitDragEvent(nsMouseEvent &aEvent)
2147 // set the keyboard modifiers
2149 qint32 x, y;
2151 GdkModifierType state = (GdkModifierType)0;
2152 gdk_window_get_pointer(NULL, &x, &y, &state);
2153 aEvent.isShift = (state & Qt::Key_SHIFT_MASK) ? PR_TRUE : PR_FALSE;
2154 aEvent.isControl = (state & Qt::Key_CONTROL_MASK) ? PR_TRUE : PR_FALSE;
2155 aEvent.isAlt = (state & Qt::Key_MOD1_MASK) ? PR_TRUE : PR_FALSE;
2156 aEvent.isMeta = PR_FALSE; // GTK+ doesn't support the meta key
2160 // This will update the drag action based on the information in the
2161 // drag context. Gtk gets this from a combination of the key settings
2162 // and what the source is offering.
2164 /* static */
2165 nsresult
2166 initialize_prefs(void)
2168 // check to see if we should set our raise pref
2169 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
2170 if (!prefs)
2171 return NS_OK;
2173 PRBool val = PR_TRUE;
2174 nsresult rv;
2175 rv = prefs->GetBoolPref("mozilla.widget.raise-on-setfocus", &val);
2177 return NS_OK;
2180 inline PRBool
2181 is_context_menu_key(const nsKeyEvent& aKeyEvent)
2183 return ((aKeyEvent.keyCode == NS_VK_F10 && aKeyEvent.isShift &&
2184 !aKeyEvent.isControl && !aKeyEvent.isMeta && !aKeyEvent.isAlt) ||
2185 (aKeyEvent.keyCode == NS_VK_CONTEXT_MENU && !aKeyEvent.isShift &&
2186 !aKeyEvent.isControl && !aKeyEvent.isMeta && !aKeyEvent.isAlt));
2189 void
2190 key_event_to_context_menu_event(nsMouseEvent &aEvent,
2191 QKeyEvent *aGdkEvent)
2193 aEvent.refPoint = nsPoint(0, 0);
2194 aEvent.isShift = PR_FALSE;
2195 aEvent.isControl = PR_FALSE;
2196 aEvent.isAlt = PR_FALSE;
2197 aEvent.isMeta = PR_FALSE;
2198 aEvent.time = 0;
2199 aEvent.clickCount = 1;
2203 static PRBool
2204 gdk_keyboard_get_modmap_masks(Display* aDisplay,
2205 PRUint32* aCapsLockMask,
2206 PRUint32* aNumLockMask,
2207 PRUint32* aScrollLockMask)
2209 *aCapsLockMask = 0;
2210 *aNumLockMask = 0;
2211 *aScrollLockMask = 0;
2213 int min_keycode = 0;
2214 int max_keycode = 0;
2215 XDisplayKeycodes(aDisplay, &min_keycode, &max_keycode);
2217 int keysyms_per_keycode = 0;
2218 KeySym* xkeymap = XGetKeyboardMapping(aDisplay, min_keycode,
2219 max_keycode - min_keycode + 1,
2220 &keysyms_per_keycode);
2221 if (!xkeymap) {
2222 return PR_FALSE;
2225 XModifierKeymap* xmodmap = XGetModifierMapping(aDisplay);
2226 if (!xmodmap) {
2227 XFree(xkeymap);
2228 return PR_FALSE;
2231 // The modifiermap member of the XModifierKeymap structure contains 8 sets
2232 // of max_keypermod KeyCodes, one for each modifier in the order Shift,
2233 // Lock, Control, Mod1, Mod2, Mod3, Mod4, and Mod5.
2234 // Only nonzero KeyCodes have meaning in each set, and zero KeyCodes are ignored.
2235 const unsigned int map_size = 8 * xmodmap->max_keypermod;
2236 for (unsigned int i = 0; i < map_size; i++) {
2237 KeyCode keycode = xmodmap->modifiermap[i];
2238 if (!keycode || keycode < min_keycode || keycode > max_keycode)
2239 continue;
2241 const KeySym* syms = xkeymap + (keycode - min_keycode) * keysyms_per_keycode;
2242 const unsigned int mask = 1 << (i / xmodmap->max_keypermod);
2243 for (int j = 0; j < keysyms_per_keycode; j++) {
2244 switch (syms[j]) {
2245 case Qt::Key_CapsLock: *aCapsLockMask |= mask; break;
2246 case Qt::Key_NumLock: *aNumLockMask |= mask; break;
2247 case Qt::Key_ScrollLock: *aScrollLockMask |= mask; break;
2252 XFreeModifiermap(xmodmap);
2253 XFree(xkeymap);
2254 return PR_TRUE;
2258 // nsChildWindow class
2260 nsChildWindow::nsChildWindow()
2264 nsChildWindow::~nsChildWindow()
2268 nsPopupWindow::nsPopupWindow()
2270 qDebug("===================== popup!");
2273 nsPopupWindow::~nsPopupWindow()
2277 QWidget*
2278 nsWindow::createQWidget(QWidget *parent, nsWidgetInitData *aInitData)
2280 Qt::WFlags flags = Qt::Widget;
2281 const char *windowName = NULL;
2283 if (gDoubleBuffering == -1) {
2284 if (getenv("MOZ_NO_DOUBLEBUFFER"))
2285 gDoubleBuffering = 0;
2286 else
2287 gDoubleBuffering = 1;
2290 #ifdef DEBUG_WIDGETS
2291 qDebug("NEW WIDGET\n\tparent is %p (%s)", (void*)parent,
2292 parent ? qPrintable(parent->objectName()) : "null");
2293 #endif
2294 // ok, create our windows
2295 switch (mWindowType) {
2296 case eWindowType_dialog:
2297 flags |= Qt::Dialog;
2298 windowName = "topLevelDialog";
2299 break;
2300 case eWindowType_popup:
2301 flags |= Qt::ToolTip;
2302 windowName = "topLevelPopup";
2303 break;
2304 case eWindowType_toplevel:
2305 flags |= Qt::Window;
2306 windowName = "topLevelWindow";
2307 break;
2308 case eWindowType_invisible:
2309 flags |= Qt::Window;
2310 windowName = "topLevelInvisible";
2311 break;
2312 case eWindowType_child:
2313 default: // plugin, java, sheet
2314 windowName = "paintArea";
2315 break;
2318 mMozQWidget = new MozQWidget(this, parent, windowName, flags);
2319 mDrawingArea = mMozQWidget;
2321 if (mWindowType == eWindowType_popup) {
2322 mMozQWidget->setFocusPolicy(Qt::WheelFocus);
2324 // XXX is this needed for Qt?
2325 // gdk does not automatically set the cursor for "temporary"
2326 // windows, which are what gtk uses for popups.
2327 SetCursor(eCursor_standard);
2328 } else if (mIsTopLevel) {
2329 SetDefaultIcon();
2332 mMozQWidget->setAttribute(Qt::WA_StaticContents);
2333 mMozQWidget->setAttribute(Qt::WA_OpaquePaintEvent); // Transparent Widget Background
2334 mMozQWidget->setAttribute(Qt::WA_NoSystemBackground);
2336 if (!gDoubleBuffering)
2337 mMozQWidget->setAttribute(Qt::WA_PaintOnScreen);
2339 return mDrawingArea;
2342 // return the gfxASurface for rendering to this widget
2343 gfxASurface*
2344 nsWindow::GetThebesSurface()
2346 /* This is really a dummy surface; this is only used when doing reflow, because
2347 * we need a RenderingContext to measure text against.
2349 if (!mThebesSurface)
2350 mThebesSurface = new gfxQPainterSurface(gfxIntSize(5,5), gfxASurface::CONTENT_COLOR);
2352 return mThebesSurface;
2355 NS_IMETHODIMP
2356 nsWindow::BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical)
2358 NS_ENSURE_ARG_POINTER(aEvent);
2361 if (aEvent->eventStructType != NS_MOUSE_EVENT) {
2362 // you can only begin a resize drag with a mouse event
2363 return NS_ERROR_INVALID_ARG;
2366 nsMouseEvent* mouse_event = static_cast<nsMouseEvent*>(aEvent);
2368 if (mouse_event->button != nsMouseEvent::eLeftButton) {
2369 // you can only begin a resize drag with the left mouse button
2370 return NS_ERROR_INVALID_ARG;
2373 qDebug("FIXME:>>>>>>Func:%s::%d\n", __PRETTY_FUNCTION__, __LINE__);
2375 return NS_OK;
2378 nsEventStatus
2379 nsWindow::contextMenuEvent(QContextMenuEvent *)
2381 //qDebug("context menu");
2382 return nsEventStatus_eIgnore;
2385 nsEventStatus
2386 nsWindow::imStartEvent(QEvent *)
2388 qWarning("XXX imStartEvent");
2389 return nsEventStatus_eIgnore;
2392 nsEventStatus
2393 nsWindow::imComposeEvent(QEvent *)
2395 qWarning("XXX imComposeEvent");
2396 return nsEventStatus_eIgnore;
2399 nsEventStatus
2400 nsWindow::imEndEvent(QEvent * )
2402 qWarning("XXX imComposeEvent");
2403 return nsEventStatus_eIgnore;
2406 nsIWidget *
2407 nsWindow::GetParent(void)
2409 return mParent;
2412 void
2413 nsWindow::DispatchGotFocusEvent(void)
2415 nsGUIEvent event(PR_TRUE, NS_GOTFOCUS, this);
2416 nsEventStatus status;
2417 DispatchEvent(&event, status);
2420 void
2421 nsWindow::DispatchLostFocusEvent(void)
2423 nsGUIEvent event(PR_TRUE, NS_LOSTFOCUS, this);
2424 nsEventStatus status;
2425 DispatchEvent(&event, status);
2428 void
2429 nsWindow::DispatchActivateEvent(void)
2431 nsGUIEvent event(PR_TRUE, NS_ACTIVATE, this);
2432 nsEventStatus status;
2433 DispatchEvent(&event, status);
2436 void
2437 nsWindow::DispatchDeactivateEvent(void)
2439 nsGUIEvent event(PR_TRUE, NS_DEACTIVATE, this);
2440 nsEventStatus status;
2441 DispatchEvent(&event, status);
2444 void
2445 nsWindow::DispatchResizeEvent(nsRect &aRect, nsEventStatus &aStatus)
2447 nsSizeEvent event(PR_TRUE, NS_SIZE, this);
2449 event.windowSize = &aRect;
2450 event.refPoint.x = aRect.x;
2451 event.refPoint.y = aRect.y;
2452 event.mWinWidth = aRect.width;
2453 event.mWinHeight = aRect.height;
2455 nsEventStatus status;
2456 DispatchEvent(&event, status);
2459 NS_IMETHODIMP
2460 nsWindow::DispatchEvent(nsGUIEvent *aEvent,
2461 nsEventStatus &aStatus)
2463 #ifdef DEBUG
2464 debug_DumpEvent(stdout, aEvent->widget, aEvent,
2465 nsCAutoString("something"), 0);
2466 #endif
2468 aStatus = nsEventStatus_eIgnore;
2470 // send it to the standard callback
2471 if (mEventCallback)
2472 aStatus = (* mEventCallback)(aEvent);
2474 // dispatch to event listener if event was not consumed
2475 if ((aStatus != nsEventStatus_eIgnore) && mEventListener)
2476 aStatus = mEventListener->ProcessEvent(*aEvent);
2478 return NS_OK;
2481 NS_IMETHODIMP
2482 nsWindow::Show(PRBool aState)
2484 LOG(("nsWindow::Show [%p] state %d\n", (void *)this, aState));
2486 mIsShown = aState;
2488 if (!mDrawingArea)
2489 return NS_OK;
2491 mDrawingArea->setVisible(aState);
2492 if (mWindowType == eWindowType_popup && aState)
2493 Resize(mBounds.x, mBounds.y, mBounds.width, mBounds.height, PR_FALSE);
2495 return NS_OK;
2498 NS_IMETHODIMP
2499 nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
2501 mBounds.width = aWidth;
2502 mBounds.height = aHeight;
2504 if (!mDrawingArea)
2505 return NS_OK;
2507 mDrawingArea->resize(aWidth, aHeight);
2509 if (aRepaint)
2510 mDrawingArea->update();
2512 return NS_OK;
2515 NS_IMETHODIMP
2516 nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,
2517 PRBool aRepaint)
2519 mBounds.x = aX;
2520 mBounds.y = aY;
2521 mBounds.width = aWidth;
2522 mBounds.height = aHeight;
2524 mPlaced = PR_TRUE;
2526 if (!mDrawingArea)
2527 return NS_OK;
2529 QPoint pos(aX, aY);
2531 // XXXvlad what?
2532 #if 0
2533 if (mParent && mDrawingArea->windowType() == Qt::Popup) {
2534 nsRect oldrect, newrect;
2535 oldrect.x = aX;
2536 oldrect.y = aY;
2538 mParent->WidgetToScreen(oldrect, newrect);
2540 pos = QPoint(newrect.x, newrect.y);
2541 #ifdef DEBUG_WIDGETS
2542 qDebug("pos is [%d,%d]", pos.x(), pos.y());
2543 #endif
2544 } else {
2545 #ifdef DEBUG_WIDGETS
2546 qDebug("Widget with original position? (%p)", mDrawingArea);
2547 #endif
2549 #endif
2551 mDrawingArea->setGeometry(pos.x(), pos.y(), aWidth, aHeight);
2553 if (aRepaint)
2554 mDrawingArea->update();
2556 return NS_OK;
2559 NS_IMETHODIMP
2560 nsWindow::GetPreferredSize(PRInt32 &aWidth,
2561 PRInt32 &aHeight)
2563 aWidth = mPreferredWidth;
2564 aHeight = mPreferredHeight;
2565 return (mPreferredWidth != 0 && mPreferredHeight != 0) ?
2566 NS_OK : NS_ERROR_FAILURE;
2569 NS_IMETHODIMP
2570 nsWindow::SetPreferredSize(PRInt32 aWidth,
2571 PRInt32 aHeight)
2573 mPreferredWidth = aWidth;
2574 mPreferredHeight = aHeight;
2575 return NS_OK;
2578 NS_IMETHODIMP
2579 nsWindow::Enable(PRBool aState)
2581 mEnabled = aState;
2583 return NS_OK;
2586 NS_IMETHODIMP
2587 nsWindow::IsEnabled(PRBool *aState)
2589 *aState = mEnabled;
2591 return NS_OK;
2594 void
2595 nsWindow::OnDestroy(void)
2597 if (mOnDestroyCalled)
2598 return;
2600 mOnDestroyCalled = PR_TRUE;
2602 // release references to children, device context, toolkit + app shell
2603 nsBaseWidget::OnDestroy();
2605 // let go of our parent
2606 mParent = nsnull;
2608 nsCOMPtr<nsIWidget> kungFuDeathGrip = this;
2610 nsGUIEvent event(PR_TRUE, NS_DESTROY, this);
2611 nsEventStatus status;
2612 DispatchEvent(&event, status);
2615 PRBool
2616 nsWindow::AreBoundsSane(void)
2618 if (mBounds.width > 0 && mBounds.height > 0)
2619 return PR_TRUE;
2621 return PR_FALSE;