Bug 459075 - "Unnecessary nsCommonWidget class in GTK code" [r+sr=roc]

This commit is contained in:
John Daniels 2008-10-18 20:13:27 -05:00
parent 4c1097b866
commit c8a2fb249f
6 changed files with 472 additions and 587 deletions

View File

@ -94,7 +94,6 @@ CPPSRCS = \
nsWidgetFactory.cpp \
nsToolkit.cpp \
nsBidiKeyboard.cpp \
nsCommonWidget.cpp \
nsLookAndFeel.cpp \
nsGtkKeyUtils.cpp \
nsFilePicker.cpp \

View File

@ -41,7 +41,6 @@
#include <fcntl.h>
#include <errno.h>
#include <gdk/gdkwindow.h>
#include "nsCommonWidget.h"
#include "nsAppShell.h"
#include "prlog.h"
#include "prenv.h"

View File

@ -1,402 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:expandtab:shiftwidth=4:tabstop=4:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Christopher Blizzard
* <blizzard@mozilla.org>. Portions created by the Initial Developer
* are Copyright (C) 2001 the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsCommonWidget.h"
#include "nsGtkKeyUtils.h"
nsCommonWidget::nsCommonWidget()
{
mIsTopLevel = PR_FALSE;
mIsDestroyed = PR_FALSE;
mNeedsResize = PR_FALSE;
mNeedsMove = PR_FALSE;
mListenForResizes = PR_FALSE;
mIsShown = PR_FALSE;
mNeedsShow = PR_FALSE;
mEnabled = PR_TRUE;
mCreated = PR_FALSE;
mPlaced = PR_FALSE;
mPreferredWidth = 0;
mPreferredHeight = 0;
}
nsCommonWidget::~nsCommonWidget()
{
}
nsIWidget *
nsCommonWidget::GetParent(void)
{
return mParent;
}
void
nsCommonWidget::CommonCreate(nsIWidget *aParent, PRBool aListenForResizes)
{
mParent = aParent;
mListenForResizes = aListenForResizes;
mCreated = PR_TRUE;
}
void
nsCommonWidget::InitKeyEvent(nsKeyEvent &aEvent, GdkEventKey *aGdkEvent)
{
aEvent.keyCode = GdkKeyCodeToDOMKeyCode(aGdkEvent->keyval);
aEvent.isShift = (aGdkEvent->state & GDK_SHIFT_MASK)
? PR_TRUE : PR_FALSE;
aEvent.isControl = (aGdkEvent->state & GDK_CONTROL_MASK)
? PR_TRUE : PR_FALSE;
aEvent.isAlt = (aGdkEvent->state & GDK_MOD1_MASK)
? PR_TRUE : PR_FALSE;
aEvent.isMeta = (aGdkEvent->state & GDK_MOD4_MASK)
? PR_TRUE : PR_FALSE;
// The transformations above and in gdk for the keyval are not invertible
// so link to the GdkEvent (which will vanish soon after return from the
// event callback) to give plugins access to hardware_keycode and state.
// (An XEvent would be nice but the GdkEvent is good enough.)
aEvent.nativeMsg = (void *)aGdkEvent;
aEvent.time = aGdkEvent->time;
}
void
nsCommonWidget::DispatchGotFocusEvent(void)
{
nsGUIEvent event(PR_TRUE, NS_GOTFOCUS, this);
nsEventStatus status;
DispatchEvent(&event, status);
}
void
nsCommonWidget::DispatchLostFocusEvent(void)
{
nsGUIEvent event(PR_TRUE, NS_LOSTFOCUS, this);
nsEventStatus status;
DispatchEvent(&event, status);
}
void
nsCommonWidget::DispatchActivateEvent(void)
{
nsGUIEvent event(PR_TRUE, NS_ACTIVATE, this);
nsEventStatus status;
DispatchEvent(&event, status);
}
void
nsCommonWidget::DispatchDeactivateEvent(void)
{
nsGUIEvent event(PR_TRUE, NS_DEACTIVATE, this);
nsEventStatus status;
DispatchEvent(&event, status);
}
void
nsCommonWidget::DispatchResizeEvent(nsRect &aRect, nsEventStatus &aStatus)
{
nsSizeEvent event(PR_TRUE, NS_SIZE, this);
event.windowSize = &aRect;
event.refPoint.x = aRect.x;
event.refPoint.y = aRect.y;
event.mWinWidth = aRect.width;
event.mWinHeight = aRect.height;
nsEventStatus status;
DispatchEvent(&event, status);
}
NS_IMETHODIMP
nsCommonWidget::DispatchEvent(nsGUIEvent *aEvent,
nsEventStatus &aStatus)
{
#ifdef DEBUG
debug_DumpEvent(stdout, aEvent->widget, aEvent,
nsCAutoString("something"), 0);
#endif
aStatus = nsEventStatus_eIgnore;
// send it to the standard callback
if (mEventCallback)
aStatus = (* mEventCallback)(aEvent);
// dispatch to event listener if event was not consumed
if ((aStatus != nsEventStatus_eIgnore) && mEventListener)
aStatus = mEventListener->ProcessEvent(*aEvent);
return NS_OK;
}
NS_IMETHODIMP
nsCommonWidget::Show(PRBool aState)
{
mIsShown = aState;
LOG(("nsCommonWidget::Show [%p] state %d\n", (void *)this, aState));
// Ok, someone called show on a window that isn't sized to a sane
// value. Mark this window as needing to have Show() called on it
// and return.
if ((aState && !AreBoundsSane()) || !mCreated) {
LOG(("\tbounds are insane or window hasn't been created yet\n"));
mNeedsShow = PR_TRUE;
return NS_OK;
}
// If someone is hiding this widget, clear any needing show flag.
if (!aState)
mNeedsShow = PR_FALSE;
// If someone is showing this window and it needs a resize then
// resize the widget.
if (aState) {
if (mNeedsMove) {
LOG(("\tresizing\n"));
NativeResize(mBounds.x, mBounds.y, mBounds.width, mBounds.height,
PR_FALSE);
} else if (mNeedsResize) {
NativeResize(mBounds.width, mBounds.height, PR_FALSE);
}
}
NativeShow(aState);
return NS_OK;
}
NS_IMETHODIMP
nsCommonWidget::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
{
mBounds.SizeTo(GetSafeWindowSize(nsSize(aWidth, aHeight)));
if (!mCreated)
return NS_OK;
// There are several cases here that we need to handle, based on a
// matrix of the visibility of the widget, the sanity of this resize
// and whether or not the widget was previously sane.
// Has this widget been set to visible?
if (mIsShown) {
// Are the bounds sane?
if (AreBoundsSane()) {
// Yep? Resize the window
//Maybe, the toplevel has moved
// Note that if the widget needs to be shown because it
// was previously insane in Resize(x,y,w,h), then we need
// to set the x and y here too, because the widget wasn't
// moved back then
if (mIsTopLevel || mNeedsShow)
NativeResize(mBounds.x, mBounds.y,
mBounds.width, mBounds.height, aRepaint);
else
NativeResize(mBounds.width, mBounds.height, aRepaint);
// Does it need to be shown because it was previously insane?
if (mNeedsShow)
NativeShow(PR_TRUE);
}
else {
// If someone has set this so that the needs show flag is false
// and it needs to be hidden, update the flag and hide the
// window. This flag will be cleared the next time someone
// hides the window or shows it. It also prevents us from
// calling NativeShow(PR_FALSE) excessively on the window which
// causes unneeded X traffic.
if (!mNeedsShow) {
mNeedsShow = PR_TRUE;
NativeShow(PR_FALSE);
}
}
}
// If the widget hasn't been shown, mark the widget as needing to be
// resized before it is shown.
else {
if (AreBoundsSane() && mListenForResizes) {
// For widgets that we listen for resizes for (widgets created
// with native parents) we apparently _always_ have to resize. I
// dunno why, but apparently we're lame like that.
NativeResize(aWidth, aHeight, aRepaint);
}
else {
mNeedsResize = PR_TRUE;
}
}
// synthesize a resize event if this isn't a toplevel
if (mIsTopLevel || mListenForResizes) {
nsRect rect(mBounds.x, mBounds.y, aWidth, aHeight);
nsEventStatus status;
DispatchResizeEvent(rect, status);
}
return NS_OK;
}
NS_IMETHODIMP
nsCommonWidget::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,
PRBool aRepaint)
{
mBounds.x = aX;
mBounds.y = aY;
mBounds.SizeTo(GetSafeWindowSize(nsSize(aWidth, aHeight)));
mPlaced = PR_TRUE;
if (!mCreated)
return NS_OK;
// There are several cases here that we need to handle, based on a
// matrix of the visibility of the widget, the sanity of this resize
// and whether or not the widget was previously sane.
// Has this widget been set to visible?
if (mIsShown) {
// Are the bounds sane?
if (AreBoundsSane()) {
// Yep? Resize the window
NativeResize(aX, aY, aWidth, aHeight, aRepaint);
// Does it need to be shown because it was previously insane?
if (mNeedsShow)
NativeShow(PR_TRUE);
}
else {
// If someone has set this so that the needs show flag is false
// and it needs to be hidden, update the flag and hide the
// window. This flag will be cleared the next time someone
// hides the window or shows it. It also prevents us from
// calling NativeShow(PR_FALSE) excessively on the window which
// causes unneeded X traffic.
if (!mNeedsShow) {
mNeedsShow = PR_TRUE;
NativeShow(PR_FALSE);
}
}
}
// If the widget hasn't been shown, mark the widget as needing to be
// resized before it is shown
else {
if (AreBoundsSane() && mListenForResizes){
// For widgets that we listen for resizes for (widgets created
// with native parents) we apparently _always_ have to resize. I
// dunno why, but apparently we're lame like that.
NativeResize(aX, aY, aWidth, aHeight, aRepaint);
}
else {
mNeedsResize = PR_TRUE;
mNeedsMove = PR_TRUE;
}
}
if (mIsTopLevel || mListenForResizes) {
// synthesize a resize event
nsRect rect(aX, aY, aWidth, aHeight);
nsEventStatus status;
DispatchResizeEvent(rect, status);
}
return NS_OK;
}
NS_IMETHODIMP
nsCommonWidget::GetPreferredSize(PRInt32 &aWidth,
PRInt32 &aHeight)
{
aWidth = mPreferredWidth;
aHeight = mPreferredHeight;
return (mPreferredWidth != 0 && mPreferredHeight != 0) ?
NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsCommonWidget::SetPreferredSize(PRInt32 aWidth,
PRInt32 aHeight)
{
mPreferredWidth = aWidth;
mPreferredHeight = aHeight;
return NS_OK;
}
NS_IMETHODIMP
nsCommonWidget::Enable(PRBool aState)
{
mEnabled = aState;
return NS_OK;
}
NS_IMETHODIMP
nsCommonWidget::IsEnabled(PRBool *aState)
{
*aState = mEnabled;
return NS_OK;
}
void
nsCommonWidget::OnDestroy(void)
{
if (mOnDestroyCalled)
return;
mOnDestroyCalled = PR_TRUE;
// release references to children, device context, toolkit + app shell
nsBaseWidget::OnDestroy();
// let go of our parent
mParent = nsnull;
nsCOMPtr<nsIWidget> kungFuDeathGrip = this;
nsGUIEvent event(PR_TRUE, NS_DESTROY, this);
nsEventStatus status;
DispatchEvent(&event, status);
}
PRBool
nsCommonWidget::AreBoundsSane(void)
{
if (mBounds.width > 0 && mBounds.height > 0)
return PR_TRUE;
return PR_FALSE;
}

View File

@ -1,161 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:expandtab:shiftwidth=4:tabstop=4:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Christopher Blizzard
* <blizzard@mozilla.org>. Portions created by the Initial Developer
* are Copyright (C) 2001 the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __nsCommonWidget_h__
#define __nsCommonWidget_h__
#include "nsBaseWidget.h"
#include "nsGUIEvent.h"
#include <gdk/gdkevents.h>
#ifdef MOZ_LOGGING
// make sure that logging is enabled before including prlog.h
#define FORCE_PR_LOG
#include "prlog.h"
extern PRLogModuleInfo *gWidgetLog;
extern PRLogModuleInfo *gWidgetFocusLog;
extern PRLogModuleInfo *gWidgetIMLog;
extern PRLogModuleInfo *gWidgetDrawLog;
#define LOG(args) PR_LOG(gWidgetLog, 4, args)
#define LOGFOCUS(args) PR_LOG(gWidgetFocusLog, 4, args)
#define LOGIM(args) PR_LOG(gWidgetIMLog, 4, args)
#define LOGDRAW(args) PR_LOG(gWidgetDrawLog, 4, args)
#else
#define LOG(args)
#define LOGFOCUS(args)
#define LOGIM(args)
#define LOGDRAW(args)
#endif /* MOZ_LOGGING */
class nsCommonWidget : public nsBaseWidget {
public:
nsCommonWidget();
virtual ~nsCommonWidget();
virtual nsIWidget *GetParent(void);
void CommonCreate(nsIWidget *aParent, PRBool aListenForResizes);
// event handling code
void InitKeyEvent(nsKeyEvent &aEvent, GdkEventKey *aGdkEvent);
void DispatchGotFocusEvent(void);
void DispatchLostFocusEvent(void);
void DispatchActivateEvent(void);
void DispatchDeactivateEvent(void);
void DispatchResizeEvent(nsRect &aRect, nsEventStatus &aStatus);
NS_IMETHOD DispatchEvent(nsGUIEvent *aEvent, nsEventStatus &aStatus);
// virtual interfaces for some nsIWidget methods
virtual void NativeResize(PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint) = 0;
virtual void NativeResize(PRInt32 aX,
PRInt32 aY,
PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint) = 0;
virtual void NativeShow (PRBool aAction) = 0;
virtual nsSize GetSafeWindowSize(nsSize aSize) = 0;
// Some of the nsIWidget methods
NS_IMETHOD Show (PRBool aState);
NS_IMETHOD Resize (PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint);
NS_IMETHOD Resize (PRInt32 aX,
PRInt32 aY,
PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint);
NS_IMETHOD GetPreferredSize (PRInt32 &aWidth,
PRInt32 &aHeight);
NS_IMETHOD SetPreferredSize (PRInt32 aWidth,
PRInt32 aHeight);
NS_IMETHOD Enable (PRBool aState);
NS_IMETHOD IsEnabled (PRBool *aState);
// called when we are destroyed
void OnDestroy(void);
// called to check and see if a widget's dimensions are sane
PRBool AreBoundsSane(void);
protected:
nsCOMPtr<nsIWidget> mParent;
// Is this a toplevel window?
PRPackedBool mIsTopLevel;
// Has this widget been destroyed yet?
PRPackedBool mIsDestroyed;
// This is a flag that tracks if we need to resize a widget or
// window when we show it.
PRPackedBool mNeedsResize;
// This is a flag that tracks if we need to move a widget or
// window when we show it.
PRPackedBool mNeedsMove;
// Should we send resize events on all resizes?
PRPackedBool mListenForResizes;
// This flag tracks if we're hidden or shown.
PRPackedBool mIsShown;
PRPackedBool mNeedsShow;
// is this widget enabled?
PRBool mEnabled;
// has the native window for this been created yet?
PRBool mCreated;
// Has anyone set an x/y location for this widget yet? Toplevels
// shouldn't be automatically set to 0,0 for first show.
PRBool mPlaced;
// Preferred sizes
PRUint32 mPreferredWidth;
PRUint32 mPreferredHeight;
};
#endif /* __nsCommonWidget_h__ */

View File

@ -350,6 +350,19 @@ static PRBool gForce24bpp = PR_FALSE;
nsWindow::nsWindow()
{
mIsTopLevel = PR_FALSE;
mIsDestroyed = PR_FALSE;
mNeedsResize = PR_FALSE;
mNeedsMove = PR_FALSE;
mListenForResizes = PR_FALSE;
mIsShown = PR_FALSE;
mNeedsShow = PR_FALSE;
mEnabled = PR_TRUE;
mCreated = PR_FALSE;
mPlaced = PR_FALSE;
mPreferredWidth = 0;
mPreferredHeight = 0;
mContainer = nsnull;
mDrawingarea = nsnull;
mShell = nsnull;
@ -455,9 +468,147 @@ nsWindow::ReleaseGlobals()
}
}
NS_IMPL_ISUPPORTS_INHERITED1(nsWindow, nsCommonWidget,
NS_IMPL_ISUPPORTS_INHERITED1(nsWindow, nsBaseWidget,
nsISupportsWeakReference)
void
nsWindow::CommonCreate(nsIWidget *aParent, PRBool aListenForResizes)
{
mParent = aParent;
mListenForResizes = aListenForResizes;
mCreated = PR_TRUE;
}
void
nsWindow::InitKeyEvent(nsKeyEvent &aEvent, GdkEventKey *aGdkEvent)
{
aEvent.keyCode = GdkKeyCodeToDOMKeyCode(aGdkEvent->keyval);
aEvent.isShift = (aGdkEvent->state & GDK_SHIFT_MASK)
? PR_TRUE : PR_FALSE;
aEvent.isControl = (aGdkEvent->state & GDK_CONTROL_MASK)
? PR_TRUE : PR_FALSE;
aEvent.isAlt = (aGdkEvent->state & GDK_MOD1_MASK)
? PR_TRUE : PR_FALSE;
aEvent.isMeta = (aGdkEvent->state & GDK_MOD4_MASK)
? PR_TRUE : PR_FALSE;
// The transformations above and in gdk for the keyval are not invertible
// so link to the GdkEvent (which will vanish soon after return from the
// event callback) to give plugins access to hardware_keycode and state.
// (An XEvent would be nice but the GdkEvent is good enough.)
aEvent.nativeMsg = (void *)aGdkEvent;
aEvent.time = aGdkEvent->time;
}
void
nsWindow::DispatchGotFocusEvent(void)
{
nsGUIEvent event(PR_TRUE, NS_GOTFOCUS, this);
nsEventStatus status;
DispatchEvent(&event, status);
}
void
nsWindow::DispatchLostFocusEvent(void)
{
nsGUIEvent event(PR_TRUE, NS_LOSTFOCUS, this);
nsEventStatus status;
DispatchEvent(&event, status);
}
void
nsWindow::DispatchResizeEvent(nsRect &aRect, nsEventStatus &aStatus)
{
nsSizeEvent event(PR_TRUE, NS_SIZE, this);
event.windowSize = &aRect;
event.refPoint.x = aRect.x;
event.refPoint.y = aRect.y;
event.mWinWidth = aRect.width;
event.mWinHeight = aRect.height;
nsEventStatus status;
DispatchEvent(&event, status);
}
void
nsWindow::DispatchActivateEvent(void)
{
#ifdef ACCESSIBILITY
DispatchActivateEventAccessible();
#endif //ACCESSIBILITY
nsGUIEvent event(PR_TRUE, NS_ACTIVATE, this);
nsEventStatus status;
DispatchEvent(&event, status);
}
void
nsWindow::DispatchDeactivateEvent(void)
{
nsGUIEvent event(PR_TRUE, NS_DEACTIVATE, this);
nsEventStatus status;
DispatchEvent(&event, status);
#ifdef ACCESSIBILITY
DispatchDeactivateEventAccessible();
#endif //ACCESSIBILITY
}
nsresult
nsWindow::DispatchEvent(nsGUIEvent *aEvent,
nsEventStatus &aStatus)
{
#ifdef DEBUG
debug_DumpEvent(stdout, aEvent->widget, aEvent,
nsCAutoString("something"), 0);
#endif
aStatus = nsEventStatus_eIgnore;
// send it to the standard callback
if (mEventCallback)
aStatus = (* mEventCallback)(aEvent);
// dispatch to event listener if event was not consumed
if ((aStatus != nsEventStatus_eIgnore) && mEventListener)
aStatus = mEventListener->ProcessEvent(*aEvent);
return NS_OK;
}
void
nsWindow::OnDestroy(void)
{
if (mOnDestroyCalled)
return;
mOnDestroyCalled = PR_TRUE;
// release references to children, device context, toolkit + app shell
nsBaseWidget::OnDestroy();
// let go of our parent
mParent = nsnull;
nsCOMPtr<nsIWidget> kungFuDeathGrip = this;
nsGUIEvent event(PR_TRUE, NS_DESTROY, this);
nsEventStatus status;
DispatchEvent(&event, status);
}
PRBool
nsWindow::AreBoundsSane(void)
{
if (mBounds.width > 0 && mBounds.height > 0)
return PR_TRUE;
return PR_FALSE;
}
NS_IMETHODIMP
nsWindow::Create(nsIWidget *aParent,
const nsRect &aRect,
@ -599,6 +750,12 @@ nsWindow::Destroy(void)
return NS_OK;
}
nsIWidget *
nsWindow::GetParent(void)
{
return mParent;
}
NS_IMETHODIMP
nsWindow::SetParent(nsIWidget *aNewParent)
{
@ -698,6 +855,215 @@ nsWindow::ConstrainPosition(PRBool aAllowSlop, PRInt32 *aX, PRInt32 *aY)
return NS_OK;
}
NS_IMETHODIMP
nsWindow::Show(PRBool aState)
{
mIsShown = aState;
LOG(("nsWindow::Show [%p] state %d\n", (void *)this, aState));
// Ok, someone called show on a window that isn't sized to a sane
// value. Mark this window as needing to have Show() called on it
// and return.
if ((aState && !AreBoundsSane()) || !mCreated) {
LOG(("\tbounds are insane or window hasn't been created yet\n"));
mNeedsShow = PR_TRUE;
return NS_OK;
}
// If someone is hiding this widget, clear any needing show flag.
if (!aState)
mNeedsShow = PR_FALSE;
// If someone is showing this window and it needs a resize then
// resize the widget.
if (aState) {
if (mNeedsMove) {
LOG(("\tresizing\n"));
NativeResize(mBounds.x, mBounds.y, mBounds.width, mBounds.height,
PR_FALSE);
} else if (mNeedsResize) {
NativeResize(mBounds.width, mBounds.height, PR_FALSE);
}
}
NativeShow(aState);
return NS_OK;
}
NS_IMETHODIMP
nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
{
mBounds.SizeTo(GetSafeWindowSize(nsSize(aWidth, aHeight)));
if (!mCreated)
return NS_OK;
// There are several cases here that we need to handle, based on a
// matrix of the visibility of the widget, the sanity of this resize
// and whether or not the widget was previously sane.
// Has this widget been set to visible?
if (mIsShown) {
// Are the bounds sane?
if (AreBoundsSane()) {
// Yep? Resize the window
//Maybe, the toplevel has moved
// Note that if the widget needs to be shown because it
// was previously insane in Resize(x,y,w,h), then we need
// to set the x and y here too, because the widget wasn't
// moved back then
if (mIsTopLevel || mNeedsShow)
NativeResize(mBounds.x, mBounds.y,
mBounds.width, mBounds.height, aRepaint);
else
NativeResize(mBounds.width, mBounds.height, aRepaint);
// Does it need to be shown because it was previously insane?
if (mNeedsShow)
NativeShow(PR_TRUE);
}
else {
// If someone has set this so that the needs show flag is false
// and it needs to be hidden, update the flag and hide the
// window. This flag will be cleared the next time someone
// hides the window or shows it. It also prevents us from
// calling NativeShow(PR_FALSE) excessively on the window which
// causes unneeded X traffic.
if (!mNeedsShow) {
mNeedsShow = PR_TRUE;
NativeShow(PR_FALSE);
}
}
}
// If the widget hasn't been shown, mark the widget as needing to be
// resized before it is shown.
else {
if (AreBoundsSane() && mListenForResizes) {
// For widgets that we listen for resizes for (widgets created
// with native parents) we apparently _always_ have to resize. I
// dunno why, but apparently we're lame like that.
NativeResize(aWidth, aHeight, aRepaint);
}
else {
mNeedsResize = PR_TRUE;
}
}
// synthesize a resize event if this isn't a toplevel
if (mIsTopLevel || mListenForResizes) {
nsRect rect(mBounds.x, mBounds.y, aWidth, aHeight);
nsEventStatus status;
DispatchResizeEvent(rect, status);
}
return NS_OK;
}
NS_IMETHODIMP
nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,
PRBool aRepaint)
{
mBounds.x = aX;
mBounds.y = aY;
mBounds.SizeTo(GetSafeWindowSize(nsSize(aWidth, aHeight)));
mPlaced = PR_TRUE;
if (!mCreated)
return NS_OK;
// There are several cases here that we need to handle, based on a
// matrix of the visibility of the widget, the sanity of this resize
// and whether or not the widget was previously sane.
// Has this widget been set to visible?
if (mIsShown) {
// Are the bounds sane?
if (AreBoundsSane()) {
// Yep? Resize the window
NativeResize(aX, aY, aWidth, aHeight, aRepaint);
// Does it need to be shown because it was previously insane?
if (mNeedsShow)
NativeShow(PR_TRUE);
}
else {
// If someone has set this so that the needs show flag is false
// and it needs to be hidden, update the flag and hide the
// window. This flag will be cleared the next time someone
// hides the window or shows it. It also prevents us from
// calling NativeShow(PR_FALSE) excessively on the window which
// causes unneeded X traffic.
if (!mNeedsShow) {
mNeedsShow = PR_TRUE;
NativeShow(PR_FALSE);
}
}
}
// If the widget hasn't been shown, mark the widget as needing to be
// resized before it is shown
else {
if (AreBoundsSane() && mListenForResizes){
// For widgets that we listen for resizes for (widgets created
// with native parents) we apparently _always_ have to resize. I
// dunno why, but apparently we're lame like that.
NativeResize(aX, aY, aWidth, aHeight, aRepaint);
}
else {
mNeedsResize = PR_TRUE;
mNeedsMove = PR_TRUE;
}
}
if (mIsTopLevel || mListenForResizes) {
// synthesize a resize event
nsRect rect(aX, aY, aWidth, aHeight);
nsEventStatus status;
DispatchResizeEvent(rect, status);
}
return NS_OK;
}
NS_IMETHODIMP
nsWindow::GetPreferredSize(PRInt32 &aWidth,
PRInt32 &aHeight)
{
aWidth = mPreferredWidth;
aHeight = mPreferredHeight;
return (mPreferredWidth != 0 && mPreferredHeight != 0) ?
NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsWindow::SetPreferredSize(PRInt32 aWidth,
PRInt32 aHeight)
{
mPreferredWidth = aWidth;
mPreferredHeight = aHeight;
return NS_OK;
}
NS_IMETHODIMP
nsWindow::Enable(PRBool aState)
{
mEnabled = aState;
return NS_OK;
}
NS_IMETHODIMP
nsWindow::IsEnabled(PRBool *aState)
{
*aState = mEnabled;
return NS_OK;
}
NS_IMETHODIMP
nsWindow::Move(PRInt32 aX, PRInt32 aY)
{
@ -807,12 +1173,6 @@ nsWindow::SetSizeMode(PRInt32 aMode)
return rv;
}
NS_IMETHODIMP
nsWindow::Enable(PRBool aState)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
typedef void (* SetUserTimeFunc)(GdkWindow* aWindow, guint32 aTimestamp);
// This will become obsolete when new GTK APIs are widely supported,
@ -5634,7 +5994,7 @@ nsWindow::DispatchAccessibleEvent(nsIAccessible** aAccessible)
}
void
nsWindow::DispatchActivateEvent(void)
nsWindow::DispatchActivateEventAccessible(void)
{
if (sAccessibilityEnabled) {
nsCOMPtr<nsIAccessible> rootAcc;
@ -5646,15 +6006,11 @@ nsWindow::DispatchActivateEvent(void)
rootAcc);
}
}
nsCommonWidget::DispatchActivateEvent();
}
void
nsWindow::DispatchDeactivateEvent(void)
nsWindow::DispatchDeactivateEventAccessible(void)
{
nsCommonWidget::DispatchDeactivateEvent();
if (sAccessibilityEnabled) {
nsCOMPtr<nsIAccessible> rootAcc;
GetRootAccessible(getter_AddRefs(rootAcc));
@ -5666,6 +6022,7 @@ nsWindow::DispatchDeactivateEvent(void)
}
}
}
#endif /* #ifdef ACCESSIBILITY */
// nsChildWindow class

View File

@ -42,8 +42,6 @@
#include "nsAutoPtr.h"
#include "nsCommonWidget.h"
#include "mozcontainer.h"
#include "mozdrawingarea.h"
#include "nsWeakReference.h"
@ -54,6 +52,9 @@
#include "gfxASurface.h"
#include "nsBaseWidget.h"
#include "nsGUIEvent.h"
#include <gdk/gdkevents.h>
#include <gtk/gtk.h>
#ifdef MOZ_DFB
@ -75,7 +76,34 @@
#include "pldhash.h"
#endif
class nsWindow : public nsCommonWidget, public nsSupportsWeakReference
#ifdef MOZ_LOGGING
// make sure that logging is enabled before including prlog.h
#define FORCE_PR_LOG
#include "prlog.h"
extern PRLogModuleInfo *gWidgetLog;
extern PRLogModuleInfo *gWidgetFocusLog;
extern PRLogModuleInfo *gWidgetIMLog;
extern PRLogModuleInfo *gWidgetDrawLog;
#define LOG(args) PR_LOG(gWidgetLog, 4, args)
#define LOGFOCUS(args) PR_LOG(gWidgetFocusLog, 4, args)
#define LOGIM(args) PR_LOG(gWidgetIMLog, 4, args)
#define LOGDRAW(args) PR_LOG(gWidgetDrawLog, 4, args)
#else
#define LOG(args)
#define LOGFOCUS(args)
#define LOGIM(args)
#define LOGDRAW(args)
#endif /* MOZ_LOGGING */
class nsWindow : public nsBaseWidget, public nsSupportsWeakReference
{
public:
nsWindow();
@ -84,6 +112,25 @@ public:
static void ReleaseGlobals();
NS_DECL_ISUPPORTS_INHERITED
void CommonCreate(nsIWidget *aParent, PRBool aListenForResizes);
// event handling code
void InitKeyEvent(nsKeyEvent &aEvent, GdkEventKey *aGdkEvent);
void DispatchGotFocusEvent(void);
void DispatchLostFocusEvent(void);
void DispatchActivateEvent(void);
void DispatchDeactivateEvent(void);
void DispatchResizeEvent(nsRect &aRect, nsEventStatus &aStatus);
virtual nsresult DispatchEvent(nsGUIEvent *aEvent, nsEventStatus &aStatus);
// called when we are destroyed
void OnDestroy(void);
// called to check and see if a widget's dimensions are sane
PRBool AreBoundsSane(void);
// nsIWidget
NS_IMETHOD Create(nsIWidget *aParent,
@ -101,7 +148,8 @@ public:
nsIToolkit *aToolkit,
nsWidgetInitData *aInitData);
NS_IMETHOD Destroy(void);
NS_IMETHOD SetParent(nsIWidget* aNewParent);
virtual nsIWidget *GetParent();
virtual nsresult SetParent(nsIWidget* aNewParent);
NS_IMETHOD SetModal(PRBool aModal);
NS_IMETHOD IsVisible(PRBool & aState);
NS_IMETHOD ConstrainPosition(PRBool aAllowSlop,
@ -109,6 +157,22 @@ public:
PRInt32 *aY);
NS_IMETHOD Move(PRInt32 aX,
PRInt32 aY);
NS_IMETHOD Show (PRBool aState);
NS_IMETHOD Resize (PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint);
NS_IMETHOD Resize (PRInt32 aX,
PRInt32 aY,
PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint);
NS_IMETHOD GetPreferredSize (PRInt32 &aWidth,
PRInt32 &aHeight);
NS_IMETHOD SetPreferredSize (PRInt32 aWidth,
PRInt32 aHeight);
NS_IMETHOD IsEnabled (PRBool *aState);
NS_IMETHOD PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
nsIWidget *aWidget,
PRBool aActivate);
@ -237,17 +301,17 @@ public:
nsIToolkit *aToolkit,
nsWidgetInitData *aInitData);
void NativeResize(PRInt32 aWidth,
virtual void NativeResize(PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint);
void NativeResize(PRInt32 aX,
virtual void NativeResize(PRInt32 aX,
PRInt32 aY,
PRInt32 aWidth,
PRInt32 aHeight,
PRBool aRepaint);
void NativeShow (PRBool aAction);
virtual void NativeShow (PRBool aAction);
virtual nsSize GetSafeWindowSize(nsSize aSize);
void EnsureGrabs (void);
@ -379,6 +443,35 @@ public:
#ifdef ACCESSIBILITY
static PRBool sAccessibilityEnabled;
#endif
protected:
nsCOMPtr<nsIWidget> mParent;
// Is this a toplevel window?
PRPackedBool mIsTopLevel;
// Has this widget been destroyed yet?
PRPackedBool mIsDestroyed;
// This is a flag that tracks if we need to resize a widget or
// window when we show it.
PRPackedBool mNeedsResize;
// This is a flag that tracks if we need to move a widget or
// window when we show it.
PRPackedBool mNeedsMove;
// Should we send resize events on all resizes?
PRPackedBool mListenForResizes;
// This flag tracks if we're hidden or shown.
PRPackedBool mIsShown;
PRPackedBool mNeedsShow;
// is this widget enabled?
PRPackedBool mEnabled;
// has the native window for this been created yet?
PRPackedBool mCreated;
// Has anyone set an x/y location for this widget yet? Toplevels
// shouldn't be automatically set to 0,0 for first show.
PRPackedBool mPlaced;
// Preferred sizes
PRUint32 mPreferredWidth;
PRUint32 mPreferredHeight;
private:
void GetToplevelWidget(GtkWidget **aWidget);
@ -425,8 +518,8 @@ private:
nsCOMPtr<nsIAccessible> mRootAccessible;
void CreateRootAccessible();
void GetRootAccessible(nsIAccessible** aAccessible);
void DispatchActivateEvent(void);
void DispatchDeactivateEvent(void);
void DispatchActivateEventAccessible();
void DispatchDeactivateEventAccessible();
NS_IMETHOD_(PRBool) DispatchAccessibleEvent(nsIAccessible** aAccessible);
#endif