Bug #129591. nsWindow::Enabled is a no-op on GTK. Also fixes bug #65521. linux modal dialogs should only freeze parent window (not all windows.) This code is a big cleanup of the event dispatching code, too. r=bryner,sr=jst

This commit is contained in:
blizzard%redhat.com 2002-04-27 13:50:21 +00:00
parent a9d5116705
commit 413ebca0d9
5 changed files with 242 additions and 417 deletions

View File

@ -50,7 +50,8 @@
#include <stdio.h>
#include "gtk/gtk.h"
#include <gtk/gtk.h>
#include <gtk/gtkprivate.h>
#include "nsGtkEventHandler.h"
#include <gdk/gdkkeysyms.h>
@ -755,11 +756,21 @@ handle_gdk_event (GdkEvent *event, gpointer data)
if (!window)
goto end;
// Get the grabbing widget, if there is one. We will need this
// later.
GtkWidget *grabWidget;
grabWidget = gtk_grab_get_current();
PRBool grabIsRegularWidget = (grabWidget && !GTK_IS_MOZAREA(grabWidget));
// Find out if there's a grabbing widget. If there is and it's a
// regular gtk widget, and our current event window is not the
// child of that grab widget, we need to rewrite the event to that
// gtk grabbing widget.
PRBool rewriteEvent = PR_FALSE;
GtkWidget *grabWidget = gtk_grab_get_current();
GtkWidget *owningWidget = window->GetOwningWidget();
if (grabWidget &&
!GTK_IS_MOZAREA(grabWidget) &&
!gdk_window_child_of_gdk_window(owningWidget->window,
grabWidget->window)) {
rewriteEvent = PR_TRUE;
}
// There are a lot of events that are always dispatched to our
// internal handler, no matter if there is a grab or not.
@ -790,69 +801,44 @@ handle_gdk_event (GdkEvent *event, gpointer data)
case GDK_3BUTTON_PRESS:
case GDK_KEY_PRESS:
case GDK_KEY_RELEASE:
// Always rewrite the event to the grab widget. If it's a
// MozArea widget, the handler will get called as normal.
if (grabWidget &&
!gdk_window_child_of_gdk_window(window->GetOwningWidget()->window,
grabWidget->window)) {
// If we need to rewrite this to the nearest real gtk widget,
// do it here.
if (rewriteEvent) {
gdk_window_unref(event->any.window);
event->any.window = grabWidget->window;
event->any.window = owningWidget->window;
gdk_window_ref(event->any.window);
gtk_main_do_event(event);
break;
}
// Otherwise, just send it to our event handler
dispatch_superwin_event(event, window);
if (GTK_WIDGET_IS_SENSITIVE(owningWidget))
dispatch_superwin_event(event, window);
break;
case GDK_MOTION_NOTIFY:
case GDK_BUTTON_RELEASE:
case GDK_PROXIMITY_IN:
case GDK_PROXIMITY_OUT:
// We only rewrite these events if the grab happens on a
// non-mozilla window. Menus get really sad if we don't do it
// this way since they expect to get events on their native
// windows, no matter if there is a grab in effect or not.
if (grabIsRegularWidget &&
!gdk_window_child_of_gdk_window(window->GetOwningWidget()->window,
grabWidget->window)) {
// We rewrite the event to the nearest "real" widget so that
// the gtk mainloop doesn't get confuse-ed.
// See above.
if (rewriteEvent) {
gdk_window_unref(event->any.window);
event->any.window = window->GetOwningWidget()->window;
event->any.window = owningWidget->window;
gdk_window_ref(event->any.window);
gtk_propagate_event(grabWidget, event);
if (event->type == GDK_BUTTON_RELEASE) {
// Always clear the button motion target when sending a
// button release event to a real gtk widget, otherwise
// mozilla will still think it has the grab. This happens
// when there's a native gtk widget popup over a Mozilla
// area.
nsWidget::DropMotionTarget();
}
break;
}
dispatch_superwin_event(event, window);
if (GTK_WIDGET_IS_SENSITIVE(owningWidget))
dispatch_superwin_event(event, window);
break;
case GDK_ENTER_NOTIFY:
case GDK_LEAVE_NOTIFY:
// We rewrite the event to the nearest "real" widget so that
// the gtk mainloop doesn't get confuse-ed.
if (grabWidget &&
gdk_window_child_of_gdk_window(window->GetOwningWidget()->window,
grabWidget->window)) {
gdk_window_unref(event->any.window);
event->any.window = window->GetOwningWidget()->window;
gdk_window_ref(event->any.window);
gtk_widget_event(grabWidget, event);
break;
}
// XXX these should track sensitivity!
// Always dispatch enter and leave notify events to the
// windows that they happened on so that state can be properly
// tracked. The code that handles the enter and leave events
// tracks sensitivity as well.
dispatch_superwin_event(event, window);
break;

View File

@ -69,25 +69,6 @@ static NS_DEFINE_CID(kRegionCID, NS_REGION_CID);
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
static NS_DEFINE_IID(kCDragServiceCID, NS_DRAGSERVICE_CID);
// keeping track of a list of simultaneously modal widgets
class ModalWidgetList {
public:
ModalWidgetList(nsWidget *aWidget);
~ModalWidgetList();
static PRBool Find(nsWidget *aWidget);
static void Append(nsWidget *aWidget);
static void Remove(nsWidget *aWidget);
static void RemoveLast(void);
static void Suppress(PRBool aSuppress);
private:
nsWidget *mWidget;
ModalWidgetList *mNext,
*mPrev,
*mLast; // valid only for head of list
};
PRUint32 nsWidget::sWidgetCount = 0;
// this is the nsWindow with the focus
@ -301,7 +282,6 @@ nsWidget::~nsWidget()
// to be called once
Destroy();
NS_ASSERTION(!ModalWidgetList::Find(this), "destroying widget without first clearing modality.");
}
@ -435,13 +415,6 @@ nsWidget::DestroySignal(GtkWidget* aGtkWidget, nsWidget* aWidget)
return PR_TRUE;
}
void
nsWidget::SuppressModality(PRBool aSuppress)
{
ModalWidgetList::Suppress(aSuppress);
}
void
nsWidget::OnDestroySignal(GtkWidget* aGtkWidget)
{
@ -493,30 +466,6 @@ NS_IMETHODIMP nsWidget::CaptureRollupEvents(nsIRollupListener * aListener, PRBoo
return NS_OK;
}
NS_IMETHODIMP nsWidget::SetModal(PRBool aModal)
{
GtkWindow *topWindow;
topWindow = GetTopLevelWindow();
if (!topWindow) {
if (!aModal) {
ModalWidgetList::RemoveLast();
}
return NS_ERROR_FAILURE;
}
if (aModal) {
ModalWidgetList::Append(this);
gtk_window_set_modal(topWindow, TRUE);
} else {
ModalWidgetList::Remove(this);
gtk_window_set_modal(topWindow, FALSE);
}
return NS_OK;
}
NS_IMETHODIMP nsWidget::IsVisible(PRBool &aState)
{
if (mWidget)
@ -1820,90 +1769,6 @@ nsWidget::OnLeaveNotifySignal(GdkEventCrossing * aGdkCrossingEvent)
}
//
// IsMouseInWindow
//
// Check if the mouse x/y is within the given window
//
PRBool
nsWidget :: IsMouseInWindow ( GdkWindow* inWindow, PRInt32 inMouseX, PRInt32 inMouseY )
{
gint x, y;
gint w, h;
// XXX this causes a round trip to the ever lovely X server. fix me.
gdk_window_get_origin(inWindow, &x, &y);
// this doesn't... it just pokes GdkWindowPrivate :-)
gdk_window_get_size(inWindow, &w, &h);
if ( inMouseX > x && inMouseX < x + w &&
inMouseY > y && inMouseY < y + h )
return PR_TRUE;
return PR_FALSE;
} // IsMouseInWindow
//
// HandlePopup
//
// Deal with rollup of popups (xpmenus, etc)
//
PRBool
nsWidget::HandlePopup(PRInt32 inMouseX, PRInt32 inMouseY, PRBool isWheel)
{
PRBool retVal = PR_FALSE;
nsCOMPtr<nsIWidget> rollupWidget = do_QueryReferent(gRollupWidget);
if (rollupWidget && gRollupListener)
{
GdkWindow *currentPopup = (GdkWindow *)rollupWidget->GetNativeData(NS_NATIVE_WINDOW);
if ( !IsMouseInWindow(currentPopup, inMouseX, inMouseY) ) {
PRBool rollup = PR_TRUE;
if (isWheel) {
gRollupListener->ShouldRollupOnMouseWheelEvent(&rollup);
retVal = PR_TRUE;
}
// if we're dealing with menus, we probably have submenus and we don't
// want to rollup if the clickis in a parent menu of the current submenu
nsCOMPtr<nsIMenuRollup> menuRollup ( do_QueryInterface(gRollupListener) );
if ( menuRollup ) {
nsCOMPtr<nsISupportsArray> widgetChain;
menuRollup->GetSubmenuWidgetChain ( getter_AddRefs(widgetChain) );
if ( widgetChain ) {
PRUint32 count = 0;
widgetChain->Count ( &count );
for ( PRUint32 i = 0; i < count; ++i ) {
nsCOMPtr<nsISupports> genericWidget;
widgetChain->GetElementAt ( i, getter_AddRefs(genericWidget) );
nsCOMPtr<nsIWidget> widget ( do_QueryInterface(genericWidget) );
if ( widget ) {
GdkWindow* currWindow = (GdkWindow*) widget->GetNativeData(NS_NATIVE_WINDOW);
if ( IsMouseInWindow(currWindow, inMouseX, inMouseY) ) {
rollup = PR_FALSE;
break;
}
}
} // foreach parent menu widget
}
} // if rollup listener knows about menus
// if we've determined that we should still rollup, do it.
if ( rollup ) {
gRollupListener->Rollup();
retVal = PR_TRUE;
}
}
} else {
gRollupWidget = nsnull;
gRollupListener = nsnull;
}
return retVal;
} // HandlePopup
//////////////////////////////////////////////////////////////////////
/* virtual */ void
nsWidget::OnButtonPressSignal(GdkEventButton * aGdkButtonEvent)
@ -1912,11 +1777,6 @@ nsWidget::OnButtonPressSignal(GdkEventButton * aGdkButtonEvent)
nsMouseScrollEvent scrollEvent;
PRUint32 eventType = 0;
PRBool isWheel = (aGdkButtonEvent->button == 4 ||
aGdkButtonEvent->button == 5);
if (HandlePopup(aGdkButtonEvent->x_root, aGdkButtonEvent->y_root, isWheel))
return;
// Switch on single, double, triple click.
switch (aGdkButtonEvent->type)
{
@ -2197,61 +2057,6 @@ nsWidget::InitMouseEvent(GdkEventButton * aGdkButtonEvent,
}
}
//////////////////////////////////////////////////////////////////
PRBool
nsWidget::DropEvent(GtkWidget * aWidget,
GdkWindow * aEventWindow)
{
NS_ASSERTION( nsnull != aWidget, "widget is null");
NS_ASSERTION( nsnull != aEventWindow, "event window is null");
#if 0
static int count = 0;
if (GTK_IS_LAYOUT(aWidget))
{
GtkLayout * layout = GTK_LAYOUT(aWidget);
printf("%4d DropEvent(this=%p,widget=%p,event_win=%p,wid_win=%p,bin_win=%p)\n",
count++,
this,
aWidget,
aEventWindow,
aWidget->window,
layout->bin_window);
}
else
{
printf("%4d DropEvent(this=%p,widget=%p,event_win=%p,wid_win=%p)\n",
count++,
this,
aWidget,
aEventWindow,
aWidget->window);
}
#endif
// For gtklayout widgets, we dont want to handle events
// that occur in the sub windows. Check the window member
// of the GdkEvent, if it is not the gtklayout's bin_window,
// drop the event.
if (GTK_IS_LAYOUT(aWidget))
{
GtkLayout * layout = GTK_LAYOUT(aWidget);
if (aEventWindow != layout->bin_window)
{
#ifdef DEBUG_pavlov
printf("dropping event!!!!!!!\n");
#endif
return PR_TRUE;
}
}
return PR_FALSE;
}
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//
@ -2270,11 +2075,6 @@ nsWidget::MotionNotifySignal(GtkWidget * aWidget,
NS_ASSERTION( nsnull != widget, "instance pointer is null");
if (widget->DropEvent(aWidget, aGdkMotionEvent->window))
{
return PR_TRUE;
}
widget->OnMotionNotifySignal(aGdkMotionEvent);
return PR_TRUE;
@ -2293,11 +2093,6 @@ nsWidget::EnterNotifySignal(GtkWidget * aWidget,
NS_ASSERTION( nsnull != widget, "instance pointer is null");
if (widget->DropEvent(aWidget, aGdkCrossingEvent->window))
{
return PR_TRUE;
}
widget->OnEnterNotifySignal(aGdkCrossingEvent);
return PR_TRUE;
@ -2315,11 +2110,6 @@ nsWidget::LeaveNotifySignal(GtkWidget * aWidget,
NS_ASSERTION( nsnull != widget, "instance pointer is null");
if (widget->DropEvent(aWidget, aGdkCrossingEvent->window))
{
return PR_TRUE;
}
widget->OnLeaveNotifySignal(aGdkCrossingEvent);
return PR_TRUE;
@ -2339,11 +2129,6 @@ nsWidget::ButtonPressSignal(GtkWidget * aWidget,
NS_ASSERTION( nsnull != widget, "instance pointer is null");
if (widget->DropEvent(aWidget, aGdkButtonEvent->window))
{
return PR_TRUE;
}
widget->OnButtonPressSignal(aGdkButtonEvent);
return PR_TRUE;
@ -2363,11 +2148,6 @@ nsWidget::ButtonReleaseSignal(GtkWidget * aWidget,
NS_ASSERTION( nsnull != widget, "instance pointer is null");
if (widget->DropEvent(aWidget, aGdkButtonEvent->window))
{
return PR_TRUE;
}
widget->OnButtonReleaseSignal(aGdkButtonEvent);
return PR_TRUE;
@ -2402,11 +2182,6 @@ nsWidget::FocusInSignal(GtkWidget * aWidget,
NS_ASSERTION( nsnull != widget, "instance pointer is null");
// if (widget->DropEvent(aWidget, aGdkFocusEvent->window))
// {
// return PR_TRUE;
// }
widget->OnFocusInSignal(aGdkFocusEvent);
if (GTK_IS_WINDOW(aWidget))
@ -2429,11 +2204,6 @@ nsWidget::FocusOutSignal(GtkWidget * aWidget,
NS_ASSERTION( nsnull != widget, "instance pointer is null");
// if (widget->DropEvent(aWidget, aGdkFocusEvent->window))
// {
// return PR_TRUE;
// }
widget->OnFocusOutSignal(aGdkFocusEvent);
if (GTK_IS_WINDOW(aWidget))
@ -2535,95 +2305,6 @@ NS_IMETHODIMP nsWidget::ResetInputState()
return NS_OK;
}
/********************** class ModalWidgetList ***********************/
/* This silly little thing is a linked list of widgets that have been
declared modal, in the order of their declaration. We do this only
so clients can stack modal dialogs on top of each other, as they
are wont to do. Yes, glib keeps its own list, but we need our own copy
so we can temporarily disable them all when a popup control window
makes an appearance within a modal dialog.
*/
static ModalWidgetList *gModalWidgets = nsnull;
ModalWidgetList::ModalWidgetList(nsWidget *aWidget) {
mWidget = aWidget;
mNext = 0;
mPrev = 0;
mLast = 0;
}
ModalWidgetList::~ModalWidgetList() {
}
PRBool ModalWidgetList::Find(nsWidget *aWidget) {
ModalWidgetList *next;
for (next = gModalWidgets; next && next->mWidget != aWidget; next = next->mNext)
;
return next ? PR_TRUE : PR_FALSE;
}
void ModalWidgetList::Append(nsWidget *aWidget) {
ModalWidgetList *newElement = new ModalWidgetList(aWidget);
NS_ASSERTION(newElement, "out of memory in modal widget list creation");
if (!newElement)
return;
if (gModalWidgets) {
newElement->mPrev = gModalWidgets->mLast;
gModalWidgets->mLast->mNext = newElement;
gModalWidgets->mLast = newElement;
} else {
newElement->mLast = newElement;
gModalWidgets = newElement;
}
}
void ModalWidgetList::Remove(nsWidget *aWidget) {
NS_ASSERTION(gModalWidgets && gModalWidgets->mLast->mWidget == aWidget,
"removing modal widgets out of order");
if (gModalWidgets && gModalWidgets->mLast->mWidget == aWidget)
ModalWidgetList::RemoveLast();
}
void ModalWidgetList::RemoveLast() {
NS_ASSERTION(gModalWidgets, "removing modal widgets from empty list");
if (!gModalWidgets)
return;
ModalWidgetList *deadElement = gModalWidgets->mLast;
if (deadElement->mPrev) {
deadElement->mPrev->mNext = 0;
gModalWidgets->mLast = deadElement->mPrev;
} else
gModalWidgets = 0;
delete deadElement;
}
void ModalWidgetList::Suppress(PRBool aSuppress) {
if (!gModalWidgets)
return;
GtkWindow *window;
ModalWidgetList *widget;
if (aSuppress)
for (widget = gModalWidgets->mLast; widget; widget = widget->mPrev) {
window = widget->mWidget->GetTopLevelWindow();
NS_ASSERTION(window, "non-window in modality suppression list");
gtk_window_set_modal(window, FALSE);
}
else
for (widget = gModalWidgets; widget; widget = widget->mNext) {
window = widget->mWidget->GetTopLevelWindow();
NS_ASSERTION(window, "non-window in modality suppression list");
gtk_window_set_modal(window, TRUE);
}
}
/* virtual */
GtkWindow *nsWidget::GetTopLevelWindow(void)
{

View File

@ -108,7 +108,6 @@ public:
nsIWidget* GetParent(void);
virtual void OnDestroy();
NS_IMETHOD SetModal(PRBool aModal);
NS_IMETHOD Show(PRBool state);
NS_IMETHOD CaptureRollupEvents(nsIRollupListener *aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent);
NS_IMETHOD IsVisible(PRBool &aState);
@ -311,12 +310,6 @@ protected:
static gint DestroySignal(GtkWidget * aGtkWidget,
nsWidget* aWidget);
static void SuppressModality(PRBool aSuppress);
// Deal with rollup for popups
PRBool HandlePopup(PRInt32 inMouseX, PRInt32 inMouseY, PRBool isWheel);
PRBool IsMouseInWindow ( GdkWindow* inWindow, PRInt32 inMouseX, PRInt32 inMouseY ) ;
public:
virtual void IMECommitEvent(GdkEventKey *aEvent);
@ -371,9 +364,6 @@ protected:
gchar * aSignalName,
GtkSignalFunc aSignalFunction);
PRBool DropEvent(GtkWidget * aWidget,
GdkWindow * aEventWindow);
void InitMouseEvent(GdkEventButton * aGdkButtonEvent,
nsMouseEvent & anEvent,
PRUint32 aEventType);
@ -423,6 +413,7 @@ private:
//
// Keep track of the last widget being "dragged"
//
public:
static nsWidget *sButtonMotionTarget;
static gint sButtonMotionRootX;
static gint sButtonMotionRootY;

View File

@ -169,6 +169,26 @@ static void printDepth(int depth) {
}
#endif
// This function will check if a button event falls inside of a
// window's bounds.
static PRBool
ButtonEventInsideWindow (GdkWindow *window, GdkEventButton *aGdkButtonEvent)
{
gint x, y;
gint width, height;
gdk_window_get_position(window, &x, &y);
gdk_window_get_size(window, &width, &height);
// This event is measured from the origin of the window itself, not
// from the origin of the screen.
if (aGdkButtonEvent->x >= x && aGdkButtonEvent->y >= y &&
aGdkButtonEvent->x <= width + x && aGdkButtonEvent->y <= height + y)
return TRUE;
return FALSE;
}
NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, nsWidget)
//-------------------------------------------------------------------------
@ -222,6 +242,9 @@ nsWindow::nsWindow()
}
#endif // USE_XIM
mLeavePending = PR_FALSE;
mRestoreFocus = PR_FALSE;
// initialize globals
if (!gGlobalsInitialized) {
gGlobalsInitialized = PR_TRUE;
@ -858,8 +881,6 @@ NS_IMETHODIMP nsWindow::CaptureRollupEvents(nsIRollupListener * aListener,
sIsGrabbing = PR_TRUE;
sGrabWindow = this;
SuppressModality(PR_TRUE);
}
gRollupConsumeRollupEvent = PR_TRUE;
@ -876,7 +897,6 @@ NS_IMETHODIMP nsWindow::CaptureRollupEvents(nsIRollupListener * aListener,
gRollupListener = nsnull;
gRollupWidget = nsnull;
SuppressModality(PR_FALSE);
}
return NS_OK;
@ -1177,6 +1197,48 @@ GdkCursor *nsWindow::GtkCreateCursor(nsCursor aCursorType)
return gdkcursor;
}
NS_IMETHODIMP
nsWindow::Enable(PRBool aState)
{
GtkWidget *top_mozarea = GetOwningWidget();
GtkWindow *top_window = GTK_WINDOW(gtk_widget_get_toplevel(top_mozarea));
if (aState) {
gtk_widget_set_sensitive(top_mozarea, TRUE);
// See if now that we're sensitive again check to see if we need
// to reset ourselves the default focus widget for the toplevel
// window. We should only do that if there is no focus widget
// since someone else might have taken the focus while we were
// disabled, and stealing focus is rude!
if (mRestoreFocus && !top_window->focus_widget) {
gtk_window_set_focus(top_window, top_mozarea);
}
mRestoreFocus = PR_FALSE;
}
else {
// Setting the window insensitive below will remove the window
// focus widget so we will have to restore it when we are
// reenabled. Of course, because of embedding, we might not
// actually _be_ the widget with focus, so keep that in mind.
if (top_window->focus_widget == top_mozarea) {
mRestoreFocus = PR_TRUE;
}
gtk_widget_set_sensitive(top_mozarea, FALSE);
}
return NS_OK;
}
NS_IMETHODIMP
nsWindow::IsEnabled(PRBool *aState)
{
NS_ENSURE_ARG_POINTER(aState);
*aState = !mMozArea || GTK_WIDGET_IS_SENSITIVE(mMozArea);
return NS_OK;
}
NS_IMETHODIMP
nsWindow::SetFocus(PRBool aRaise)
{
@ -1401,7 +1463,7 @@ void nsWindow::HandleMozAreaFocusIn(void)
// otherwise, dispatch our focus events
#ifdef DEBUG_FOCUS
printf("nsWindow::HandleMozAreaFocusIn %p\n", NS_STATIC_CAST(void *, this));
#endif /* DEBUG_FOCUS */
#endif
// we only set the gJustGotActivate signal if we're the toplevel
// window. embedding handles activate semantics for us.
if (mIsToplevel)
@ -1422,7 +1484,7 @@ void nsWindow::HandleMozAreaFocusOut(void)
// otherwise handle our focus out here.
#ifdef DEBUG_FOCUS
printf("nsWindow::HandleMozAreaFocusOut %p\n", NS_STATIC_CAST(void *, this));
#endif /* DEBUG_FOCUS */
#endif
// if there's a window with focus, send a focus out event for that
// window.
if (sFocusWindow)
@ -1464,6 +1526,107 @@ void nsWindow::HandleMozAreaFocusOut(void)
}
}
//////////////////////////////////////////////////////////////////////
/* virtual */ void
nsWindow::OnMotionNotifySignal(GdkEventMotion *aGdkMotionEvent)
{
// If there's a rollup widget and this window is not a popup window,
// drop the event.
if (gRollupWidget && GetOwningWindowType() != eWindowType_popup) {
return;
}
XEvent xevent;
GdkEvent gdk_event;
PRBool synthEvent = PR_FALSE;
while (XCheckWindowEvent(GDK_DISPLAY(),
GDK_WINDOW_XWINDOW(mSuperWin->bin_window),
ButtonMotionMask, &xevent)) {
synthEvent = PR_TRUE;
}
if (synthEvent) {
gdk_event.type = GDK_MOTION_NOTIFY;
gdk_event.motion.window = aGdkMotionEvent->window;
gdk_event.motion.send_event = aGdkMotionEvent->send_event;
gdk_event.motion.time = xevent.xmotion.time;
gdk_event.motion.x = xevent.xmotion.x;
gdk_event.motion.y = xevent.xmotion.y;
gdk_event.motion.pressure = aGdkMotionEvent->pressure;
gdk_event.motion.xtilt = aGdkMotionEvent->xtilt;
gdk_event.motion.ytilt = aGdkMotionEvent->ytilt;
gdk_event.motion.state = aGdkMotionEvent->state;
gdk_event.motion.is_hint = xevent.xmotion.is_hint;
gdk_event.motion.source = aGdkMotionEvent->source;
gdk_event.motion.deviceid = aGdkMotionEvent->deviceid;
gdk_event.motion.x_root = xevent.xmotion.x_root;
gdk_event.motion.y_root = xevent.xmotion.y_root;
nsWidget::OnMotionNotifySignal(&gdk_event.motion);
}
else {
nsWidget::OnMotionNotifySignal(aGdkMotionEvent);
}
}
//////////////////////////////////////////////////////////////////////
/* virtual */ void
nsWindow::OnEnterNotifySignal(GdkEventCrossing *aGdkCrossingEvent)
{
if (GTK_WIDGET_SENSITIVE(GetOwningWidget())) {
nsWidget::OnEnterNotifySignal(aGdkCrossingEvent);
if (mMozArea)
GTK_PRIVATE_SET_FLAG(mMozArea, GTK_LEAVE_PENDING);
mLeavePending = PR_TRUE;
}
}
//////////////////////////////////////////////////////////////////////
/* virtual */ void
nsWindow::OnLeaveNotifySignal(GdkEventCrossing *aGdkCrossingEvent)
{
if (mLeavePending) {
if (mMozArea)
GTK_PRIVATE_UNSET_FLAG(mMozArea, GTK_LEAVE_PENDING);
mLeavePending = PR_FALSE;
nsWidget::OnLeaveNotifySignal(aGdkCrossingEvent);
}
}
//////////////////////////////////////////////////////////////////////
/* virtual */ void
nsWindow::OnButtonPressSignal(GdkEventButton *aGdkButtonEvent)
{
// This widget has gotten a button press event. If there's a rollup
// widget and we're not inside of a popup window we should pop up
// the rollup widget. Also, if the event is our event but it
// happens outside of the bounds of the window we should roll up as
// well.
if (gRollupWidget && ((GetOwningWindowType() != eWindowType_popup) ||
(mSuperWin->bin_window == aGdkButtonEvent->window &&
!ButtonEventInsideWindow(aGdkButtonEvent->window,
aGdkButtonEvent)))) {
gRollupListener->Rollup();
gRollupWidget = nsnull;
gRollupListener = nsnull;
return;
}
nsWidget::OnButtonPressSignal(aGdkButtonEvent);
}
//////////////////////////////////////////////////////////////////////
/* virtual */ void
nsWindow::OnButtonReleaseSignal(GdkEventButton *aGdkButtonEvent)
{
// we only dispatch this event if there's a button motion target or
// if it's happening inside of a popup window while there is a
// rollup widget
if (!sButtonMotionTarget &&
(gRollupWidget && GetOwningWindowType() != eWindowType_popup)) {
return;
}
nsWidget::OnButtonReleaseSignal(aGdkButtonEvent);
}
//////////////////////////////////////////////////////////////////////
/* virtual */ void
nsWindow::OnFocusInSignal(GdkEventFocus * aGdkFocusEvent)
@ -1549,38 +1712,8 @@ nsWindow::HandleGDKEvent(GdkEvent *event)
switch (event->any.type)
{
case GDK_MOTION_NOTIFY:
{
XEvent xevent;
GdkEvent gdk_event;
PRBool synthEvent = PR_FALSE;
while (XCheckWindowEvent(GDK_DISPLAY(),
GDK_WINDOW_XWINDOW(mSuperWin->bin_window),
ButtonMotionMask, &xevent)) {
synthEvent = PR_TRUE;
}
if (synthEvent) {
gdk_event.type = GDK_MOTION_NOTIFY;
gdk_event.motion.window = event->motion.window;
gdk_event.motion.send_event = event->motion.send_event;
gdk_event.motion.time = xevent.xmotion.time;
gdk_event.motion.x = xevent.xmotion.x;
gdk_event.motion.y = xevent.xmotion.y;
gdk_event.motion.pressure = event->motion.pressure;
gdk_event.motion.xtilt = event->motion.xtilt;
gdk_event.motion.ytilt = event->motion.ytilt;
gdk_event.motion.state = event->motion.state;
gdk_event.motion.is_hint = xevent.xmotion.is_hint;
gdk_event.motion.source = event->motion.source;
gdk_event.motion.deviceid = event->motion.deviceid;
gdk_event.motion.x_root = xevent.xmotion.x_root;
gdk_event.motion.y_root = xevent.xmotion.y_root;
OnMotionNotifySignal (&gdk_event.motion);
}
else {
OnMotionNotifySignal (&event->motion);
}
}
break;
OnMotionNotifySignal (&event->motion);
break;
case GDK_BUTTON_PRESS:
case GDK_2BUTTON_PRESS:
case GDK_3BUTTON_PRESS:
@ -1589,12 +1722,13 @@ nsWindow::HandleGDKEvent(GdkEvent *event)
case GDK_BUTTON_RELEASE:
OnButtonReleaseSignal (&event->button);
break;
case GDK_ENTER_NOTIFY:
OnEnterNotifySignal (&event->crossing);
break;
case GDK_LEAVE_NOTIFY:
OnLeaveNotifySignal (&event->crossing);
break;
case GDK_ENTER_NOTIFY:
OnEnterNotifySignal ( &event->crossing );
break;
default:
break;
}
@ -1611,6 +1745,13 @@ nsWindow::OnDestroySignal(GtkWidget* aGtkWidget)
gint handle_delete_event(GtkWidget *w, GdkEventAny *e, nsWindow *win)
{
PRBool isEnabled;
// If this window is disabled, don't dispatch the delete event
win->IsEnabled(&isEnabled);
if (!isEnabled)
return TRUE;
NS_ADDREF(win);
// dispatch an "onclose" event. to delete immediately, call win->Destroy()
@ -2754,6 +2895,21 @@ nsWindow::GetOwningWidget()
return (GtkWidget *)mMozAreaClosestParent;
}
nsWindowType
nsWindow::GetOwningWindowType(void)
{
GtkWidget *widget = GetOwningWidget();
nsWindow *owningWindow;
owningWindow = (nsWindow *)gtk_object_get_data(GTK_OBJECT(widget),
"nsWindow");
nsWindowType retval;
owningWindow->GetWindowType(retval);
return retval;
}
PRBool
nsWindow::GrabInProgress(void)
{
@ -2765,9 +2921,7 @@ nsWindow *
nsWindow::GetGrabWindow(void)
{
if (nsWindow::sIsGrabbing)
{
return sGrabWindow;
}
else
return nsnull;
}

View File

@ -108,6 +108,8 @@ public:
NS_IMETHOD InvalidateRegion(const nsIRegion* aRegion, PRBool aIsSynchronous);
NS_IMETHOD SetBackgroundColor(const nscolor &aColor);
NS_IMETHOD SetCursor(nsCursor aCursor);
NS_IMETHOD Enable (PRBool aState);
NS_IMETHOD IsEnabled (PRBool *aState);
NS_IMETHOD SetFocus(PRBool aRaise);
NS_IMETHOD GetAttention(void);
NS_IMETHOD Destroy();
@ -126,6 +128,11 @@ public:
// get the toplevel window for this widget
virtual GtkWindow *GetTopLevelWindow(void);
NS_IMETHOD Update(void);
virtual void OnMotionNotifySignal(GdkEventMotion *aGdkMotionEvent);
virtual void OnEnterNotifySignal(GdkEventCrossing *aGdkCrossingEvent);
virtual void OnLeaveNotifySignal(GdkEventCrossing *aGdkCrossingEvent);
virtual void OnButtonPressSignal(GdkEventButton *aGdkButtonEvent);
virtual void OnButtonReleaseSignal(GdkEventButton *aGdkButtonEvent);
virtual void OnFocusInSignal(GdkEventFocus * aGdkFocusEvent);
virtual void OnFocusOutSignal(GdkEventFocus * aGdkFocusEvent);
virtual void InstallFocusInSignal(GtkWidget * aWidget);
@ -146,6 +153,10 @@ public:
// Return the GtkMozArea that is the nearest parent of this widget
virtual GtkWidget *GetOwningWidget();
// Return the type of the window that is the toplevel mozilla window
// for this (possibly) inner window
nsWindowType GetOwningWindowType();
// Return the Gdk window used for rendering
virtual GdkWindow * GetRenderWindow(GtkObject * aGtkWidget);
@ -366,6 +377,8 @@ private:
GtkWindow *mTransientParent;
PRBool mLeavePending;
PRBool mRestoreFocus;
};
//