mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-11 16:32:59 +00:00
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:
parent
a9d5116705
commit
413ebca0d9
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user