Fix bug #61782. Focus problems with gtk based plugins. This also cleans up a lot of other focus-related code as well. r=bryner, saari sr=scc

This commit is contained in:
blizzard%redhat.com 2000-12-29 19:02:00 +00:00
Родитель 4f21917511
Коммит 4546cb78ec
5 изменённых файлов: 200 добавлений и 188 удалений

Просмотреть файл

@ -642,6 +642,7 @@ gint handle_key_press_event(GtkObject *w, GdkEventKey* event, gpointer p)
nsKeyEvent kevent;
nsWidget *win = (nsWidget*)p;
// if there's a focused window rewrite the event to use that window.
if (win->sFocusWindow)
win = win->sFocusWindow;
@ -870,9 +871,13 @@ handle_gdk_event (GdkEvent *event, gpointer data)
// pass it to the nsWindow to be handled
//
nsWindow *grabbingWindow = nsWindow::GetGrabWindow();
GdkWindow *grabbingGdkWindow = (GdkWindow *)grabbingWindow->GetNativeData(NS_NATIVE_WINDOW);
// the grabbingWindow wasn't addrefed by the getter but we
// want to keep a reference on it.
nsCOMPtr<nsIWidget> grabbingWindowGuard(grabbingWindow);
GdkWindow *grabbingGdkWindow =
NS_STATIC_CAST(GdkWindow *,
grabbingWindow->GetNativeData(NS_NATIVE_WINDOW));
GtkWidget *grabbingMozArea = grabbingWindow->GetMozArea();
NS_RELEASE(grabbingWindow);
if (gtk_widget_child_of_gdk_window(current_grab, grabbingGdkWindow))
{
gdk_window_unref (event->any.window);
@ -894,7 +899,6 @@ handle_gdk_event (GdkEvent *event, gpointer data)
}
else
{
// we need to make sure that if we're doing a gdk_pointer_grab on
// a superwin that we check to make sure that we account for a
// real GtkWidget being inside of it. the grab code in gtk that
@ -906,17 +910,20 @@ handle_gdk_event (GdkEvent *event, gpointer data)
// with a gtk scrollbar in it.
nsWindow *grabbingWindow = nsWindow::GetGrabWindow();
// the grabbingWindow wasn't addrefed by the getter but we
// want to keep a reference on it.
nsCOMPtr<nsIWidget> grabbingWindowGuard(grabbingWindow);
GtkWidget *tempWidget = NULL;
if (grabbingWindow)
{
// get the GdkWindow that we are grabbing on
GdkWindow *grabbingGdkWindow = (GdkWindow *)grabbingWindow->GetNativeData(NS_NATIVE_WINDOW);
// release our nsIWidget
NS_RELEASE(grabbingWindow);
GdkWindow *grabbingGdkWindow =
NS_STATIC_CAST(GdkWindow *,
grabbingWindow->GetNativeData(NS_NATIVE_WINDOW));
// only if this is a GtkWidget object
if (GTK_IS_WIDGET(object))
{
tempWidget = (GtkWidget *)object;
tempWidget = GTK_WIDGET(object);
// check to see if this widget is the child of the GdkWindow
// that we are grabbing on.
if (gtk_widget_child_of_gdk_window(tempWidget, grabbingGdkWindow))
@ -943,6 +950,13 @@ handle_gdk_event (GdkEvent *event, gpointer data)
}
gtk_grab_add(tempWidget);
}
else
{
// if the gtk widget in question wasn't the child of the
// grabbing window then the grabbing window gets it.
dispatch_superwin_event(event, grabbingWindow);
return;
}
}
}
gtk_main_do_event (event);
@ -958,13 +972,17 @@ dispatch_superwin_event(GdkEvent *event, nsWindow *window)
{
// Check to see whether or not we need to send this to the
// toplevel window to get passed to the GtkWidget with focus.
// This happens in the embedding case.
if (!window->sFocusWindow)
// This happens in the embedding case. If there's a superwin grab
// in progress it gets the window events, not the gtk widget.
if (!window->sFocusWindow && !window->GrabInProgress())
{
GtkWidget *mozArea = window->GetMozArea();
NS_ASSERTION(mozArea, "Failed to get GtkMozArea for superwin event!\n");
// get the toplevel window for that widget
GtkWidget *toplevel = gtk_widget_get_toplevel(mozArea);
// pass it off to gtk's event system and return
gtk_propagate_event(mozArea, event);
gboolean handled = gtk_widget_event(toplevel, event);
if (handled)
return;
}
}

Просмотреть файл

@ -2120,7 +2120,7 @@ nsWidget::OnFocusOutSignal(GdkEventFocus * aGdkFocusEvent)
/* virtual */ void
nsWidget::OnRealize(GtkWidget *aWidget)
{
printf("nsWidget::OnRealize(%p)\n",this);
printf("nsWidget::OnRealize(%p)\n", NS_STATIC_CAST(void *, this));
}
//////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -82,16 +82,6 @@ extern "C" int usleep(unsigned int);
static NS_DEFINE_IID(kCDragServiceCID, NS_DRAGSERVICE_CID);
gint handle_toplevel_focus_in (
GtkWidget * aWidget,
GdkEventFocus * aGdkFocusEvent,
gpointer aData);
gint handle_toplevel_focus_out (
GtkWidget * aWidget,
GdkEventFocus * aGdkFocusEvent,
gpointer aData);
gint handle_mozarea_focus_in (
GtkWidget * aWidget,
GdkEventFocus * aGdkFocusEvent,
@ -120,8 +110,8 @@ nsWindow *nsWindow::mLastDragMotionWindow = NULL;
// we get our drop after the leave.
nsWindow *nsWindow::mLastLeaveWindow = NULL;
PRBool gJustGotDeactivate = PR_FALSE;
PRBool gJustGotActivate = PR_FALSE;
PRBool gJustGotDeactivate = PR_TRUE;
static void printDepth(int depth) {
int i;
@ -1060,37 +1050,43 @@ NS_IMETHODIMP nsWindow::SetCursor(nsCursor aCursor)
NS_IMETHODIMP
nsWindow::SetFocus(void)
{
PRBool sendActivate = gJustGotActivate;
gJustGotActivate = PR_FALSE;
#ifdef DEBUG_FOCUS
printf("nsWindow::SetFocus %p\n", this);
printf("nsWindow::SetFocus %p\n", NS_STATIC_CAST(void *, this));
#endif /* DEBUG_FOCUS */
if (mHasFocus)
{
#ifdef DEBUG_FOCUS
printf("Already have focus.\n");
#endif /* DEBUG_FOCUS */
return NS_OK;
}
GtkWidget *top_mozarea = GetMozArea();
#ifdef DEBUG_FOCUS
printf("top moz area is %p\n", NS_STATIC_CAST(void *, top_mozarea));
#endif
if (top_mozarea)
{
if (!GTK_WIDGET_HAS_FOCUS(top_mozarea))
{
nsWindow *mozAreaWindow = (nsWindow *)gtk_object_get_data(GTK_OBJECT(top_mozarea), "nsWindow");
mozAreaWindow->mBlockMozAreaFocusIn = PR_TRUE;
#ifdef DEBUG_FOCUS
printf("mozarea grabbing focus!\n");
#endif
mozAreaWindow->mBlockMozAreaFocusIn = PR_TRUE;
gtk_widget_grab_focus(top_mozarea);
mozAreaWindow->mBlockMozAreaFocusIn = PR_FALSE;
// this will show the window if it's minimized and bring it to
// the front of the stacking order.
GetAttention();
mozAreaWindow->mBlockMozAreaFocusIn = PR_FALSE;
}
}
if (mHasFocus)
{
#ifdef DEBUG_FOCUS
printf("Returning: Already have focus.\n");
#endif /* DEBUG_FOCUS */
return NS_OK;
}
// check to see if we need to send a focus out event for the old window
if (sFocusWindow)
{
@ -1109,18 +1105,21 @@ nsWindow::SetFocus(void)
#endif // USE_XIM
DispatchSetFocusEvent();
if (/*gJustGotActivate &&*/ gJustGotDeactivate) {
if (sendActivate) {
DispatchActivateEvent();
gJustGotActivate = PR_FALSE;
}
#ifdef DEBUG_FOCUS
printf("Returning:\n");
#endif
return NS_OK;
}
void nsWindow::DispatchSetFocusEvent(void)
{
#ifdef DEBUG_FOCUS
printf("nsWindow::DispatchSetFocusEvent %p\n", this);
printf("nsWindow::DispatchSetFocusEvent %p\n", NS_STATIC_CAST(void *, this));
#endif /* DEBUG_FOCUS */
nsGUIEvent event;
@ -1142,7 +1141,7 @@ void nsWindow::DispatchLostFocusEvent(void)
{
#ifdef DEBUG_FOCUS
printf("nsWindow::DispatchLostFocusEvent %p\n", this);
printf("nsWindow::DispatchLostFocusEvent %p\n", NS_STATIC_CAST(void *, this));
#endif /* DEBUG_FOCUS */
nsGUIEvent event;
@ -1165,12 +1164,9 @@ void nsWindow::DispatchLostFocusEvent(void)
void nsWindow::DispatchActivateEvent(void)
{
#ifdef DEBUG_FOCUS
printf("nsWindow::DispatchActivateEvent %p\n", this);
printf("nsWindow::DispatchActivateEvent %p\n", NS_STATIC_CAST(void *, this));
#endif
if(!gJustGotDeactivate)
return;
#ifdef USE_XIM
IMEBeingActivate(PR_TRUE);
#endif // USE_XIM
@ -1199,14 +1195,13 @@ void nsWindow::DispatchActivateEvent(void)
void nsWindow::DispatchDeactivateEvent(void)
{
#ifdef DEBUG_FOCUS
printf("nsWindow::DispatchDeactivateEvent %p\n", this);
printf("nsWindow::DispatchDeactivateEvent %p\n",
NS_STATIC_CAST(void *, this));
#endif
#ifdef USE_XIM
IMEBeingActivate(PR_TRUE);
#endif // USE_XIM
gJustGotDeactivate = PR_TRUE;
nsGUIEvent event;
event.message = NS_DEACTIVATE;
event.widget = this;
@ -1231,11 +1226,6 @@ void nsWindow::DispatchDeactivateEvent(void)
void nsWindow::HandleMozAreaFocusIn(void)
{
// If there's a shell window then we aren't embedded so all the
// functionality is done in the focus handlers for the toplevel
// window. Do nothing.
if (mShell)
return;
// If we're getting this focus in as a result of a child superwin
// getting called with SetFocus() this flag will be set. We don't
// want to generate extra focus in events so just return.
@ -1243,7 +1233,7 @@ void nsWindow::HandleMozAreaFocusIn(void)
return;
// otherwise, dispatch our focus events
#ifdef DEBUG_FOCUS
printf("nsWindow::HandleMozAreaFocusIn %p\n", this);
printf("nsWindow::HandleMozAreaFocusIn %p\n", NS_STATIC_CAST(void *, this));
#endif /* DEBUG_FOCUS */
gJustGotActivate = PR_TRUE;
DispatchSetFocusEvent();
@ -1254,35 +1244,46 @@ void nsWindow::HandleMozAreaFocusIn(void)
void nsWindow::HandleMozAreaFocusOut(void)
{
// Working around unexplained missing calls to top level focus out
gJustGotDeactivate = PR_TRUE;
// If there's a shell window then we aren't embedded so all the
// functionality is done in the focus handlers for the toplevel
// window. Do nothing.
if (mShell)
return;
// otherwise handle our focus out here.
#ifdef DEBUG_FOCUS
printf("nsWindow::HandleMozAreaFocusOut %p\n", this);
printf("nsWindow::HandleMozAreaFocusOut %p\n", NS_STATIC_CAST(void *, this));
#endif /* DEBUG_FOCUS */
// if there's a window with focus, send a focus out event for that
// window.
if (sFocusWindow)
{
nsWidget *focusWidget = sFocusWindow;
// Figure out of the focus widget is the child of this widget. If
// it isn't then we don't send the event since it was already sent
// earlier.
PRBool isChild = PR_FALSE;
GdkWindow *window;
window = (GdkWindow *)sFocusWindow->GetNativeData(NS_NATIVE_WINDOW);
while (window)
{
gpointer data = NULL;
gdk_window_get_user_data(window, &data);
if (GTK_IS_MOZAREA(data))
{
GtkWidget *tmpMozArea = GTK_WIDGET(data);
if (tmpMozArea == mMozArea)
{
isChild = PR_TRUE;
break;
}
}
window = gdk_window_get_parent(window);
}
NS_ADDREF(focusWidget);
if (isChild)
{
nsWidget *focusWidget = sFocusWindow;
nsCOMPtr<nsIWidget> focusWidgetGuard(focusWidget);
focusWidget->DispatchLostFocusEvent();
focusWidget->DispatchDeactivateEvent();
focusWidget->LoseFocus();
NS_RELEASE(focusWidget);
}
}
}
//////////////////////////////////////////////////////////////////////
@ -1478,7 +1479,7 @@ nsWindow::dumpWindowChildren(Window aWindow, unsigned int depth)
thisWindow);
if (childWindow)
{
g_print("(shell_window for nsWindow %p)\n", childWindow);
g_print("(shell_window for nsWindow %p)\n", NS_STATIC_CAST(void *, childWindow));
}
}
}
@ -1503,12 +1504,12 @@ nsWindow::DumpWindowTree(void)
// see where we are starting
if (mShell)
{
g_print("dumping from shell for %p.\n", this);
g_print("dumping from shell for %p.\n", NS_STATIC_CAST(void *, this));
startWindow = mShell->window;
}
else
{
g_print("dumping from superwin for %p.\n", this);
g_print("dumping from superwin for %p.\n", NS_STATIC_CAST(void *, this));
startWindow = mSuperWin->shell_window;
}
Window window;
@ -1517,7 +1518,7 @@ nsWindow::DumpWindowTree(void)
}
else
{
g_print("no windows for %p.\n", this);
g_print("no windows for %p.\n", NS_STATIC_CAST(void *, this));
}
}
@ -1721,30 +1722,10 @@ NS_METHOD nsWindow::CreateNative(GtkObject *parentWidget)
// set up all the focus handling
if (mShell) {
// Track focus in event for the shell. We only need the focus in
// event so that we can dispatch it to the mMozArea
gtk_signal_connect(GTK_OBJECT(mShell),
"focus_in_event",
GTK_SIGNAL_FUNC(handle_toplevel_focus_in),
this);
gtk_signal_connect(GTK_OBJECT(mShell),
"focus_out_event",
GTK_SIGNAL_FUNC(handle_toplevel_focus_out),
this);
gtk_signal_connect(GTK_OBJECT(mShell),
"property_notify_event",
GTK_SIGNAL_FUNC(handle_toplevel_property_change),
this);
gtk_signal_connect(GTK_OBJECT(mShell),
"key_press_event",
GTK_SIGNAL_FUNC(handle_key_press_event),
this);
gtk_signal_connect(GTK_OBJECT(mShell),
"key_release_event",
GTK_SIGNAL_FUNC(handle_key_release_event),
this);
mask = (GdkEventMask) (GDK_PROPERTY_CHANGE_MASK |
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
@ -1757,7 +1738,7 @@ NS_METHOD nsWindow::CreateNative(GtkObject *parentWidget)
}
if (mMozArea) {
// track focus events for the moz area, too
// track focus events for the moz area
gtk_signal_connect(GTK_OBJECT(mMozArea),
"focus_in_event",
GTK_SIGNAL_FUNC(handle_mozarea_focus_in),
@ -2648,84 +2629,6 @@ nsWindow::OnRealize(GtkWidget *aWidget)
}
}
gint handle_toplevel_focus_in(GtkWidget * aWidget,
GdkEventFocus * aGdkFocusEvent,
gpointer aData)
{
GtkWindow *window = NULL;
GtkBin *bin = NULL;
if (!aWidget)
return PR_TRUE;
if (!aGdkFocusEvent)
return PR_TRUE;
nsWindow *widget = (nsWindow *)aData;
if (!widget)
return PR_TRUE;
#ifdef DEBUG_FOCUS
printf("handle_toplevel_focus_in %p\n", widget);
#endif /* DEBUG_FOCUS */
window = GTK_WINDOW(aWidget);
bin = GTK_BIN(window);
gtk_widget_grab_focus(bin->child);
gJustGotActivate = PR_TRUE;
if(gJustGotDeactivate) {
widget->DispatchSetFocusEvent();
}
return PR_TRUE;
}
gint handle_toplevel_focus_out(GtkWidget * aWidget,
GdkEventFocus * aGdkFocusEvent,
gpointer aData)
{
if (!aWidget)
return PR_TRUE;
if (!aGdkFocusEvent)
return PR_TRUE;
nsWindow *widget = (nsWindow *) aData;
if (!widget)
return PR_TRUE;
#ifdef DEBUG_FOCUS
printf("handle_toplevel_focus_out %p\n", widget);
#endif
// addref the widget here since we might send > 1 event to it.
NS_ADDREF(widget);
// if there's a window with focus, send a focus out event for that
// window.
if (widget->sFocusWindow)
{
nsWidget *focusWidget = widget->sFocusWindow;
NS_ADDREF(focusWidget);
focusWidget->DispatchLostFocusEvent();
focusWidget->DispatchDeactivateEvent();
focusWidget->LoseFocus();
NS_RELEASE(focusWidget);
}
NS_RELEASE(widget);
return PR_TRUE;
}
gint handle_mozarea_focus_in(GtkWidget * aWidget,
GdkEventFocus * aGdkFocusEvent,
gpointer aData)
@ -2748,9 +2651,13 @@ gint handle_mozarea_focus_in(GtkWidget * aWidget,
// make sure that we set our focus flag
GTK_WIDGET_SET_FLAGS(aWidget, GTK_HAS_FOCUS);
#ifdef DEBUG_FOCUS
printf("aWidget is %p\n", NS_STATIC_CAST(void *, aWidget));
#endif
widget->HandleMozAreaFocusIn();
return PR_TRUE;
return TRUE;
}
gint handle_mozarea_focus_out(GtkWidget * aWidget,
@ -2780,7 +2687,7 @@ gint handle_mozarea_focus_out(GtkWidget * aWidget,
widget->HandleMozAreaFocusOut();
return PR_TRUE;
return TRUE;
}
@ -2893,7 +2800,6 @@ nsWindow::GetGrabWindow(void)
{
if (nsWindow::sIsGrabbing)
{
NS_ADDREF(sGrabWindow);
return sGrabWindow;
}
else

Просмотреть файл

@ -139,8 +139,8 @@ public:
// virtual void OnButtonPressSignal(GdkEventButton * aGdkButtonEvent);
void ShowCrossAtLocation(guint x, guint y);
// this will get the nsWindow with the grab. this will AddRef()
// before returning.
// this will get the nsWindow with the grab. The return will not be
// addrefed.
static nsWindow *GetGrabWindow(void);
virtual void DispatchSetFocusEvent(void);

Просмотреть файл

@ -16,14 +16,22 @@
* Owen Taylor and Christopher Blizzard. All Rights Reserved. */
#include "gtkmozbox.h"
#include <gtk/gtkmain.h>
#include <X11/Xlib.h>
static void gtk_mozbox_class_init (GtkMozBoxClass *klass);
static void gtk_mozbox_init (GtkMozBox *mozbox);
static void gtk_mozbox_realize (GtkWidget *widget);
static void gtk_mozbox_set_focus (GtkWindow *window,
GtkWidget *focus);
static gint gtk_mozbox_key_press_event (GtkWidget *widget,
GdkEventKey *event);
static GdkFilterReturn gtk_mozbox_filter (GdkXEvent *xevent,
GdkEvent *event,
gpointer data);
static GtkWindow * gtk_mozbox_get_parent_gtkwindow (GtkMozBox *mozbox);
void (*parent_class_set_focus)(GtkWindow *, GtkWidget *);
GtkType
gtk_mozbox_get_type (void)
@ -54,10 +62,18 @@ static void
gtk_mozbox_class_init (GtkMozBoxClass *klass)
{
GtkWidgetClass *widget_class;
GtkWindowClass *window_class;
widget_class = GTK_WIDGET_CLASS (klass);
window_class = GTK_WINDOW_CLASS (klass);
widget_class->realize = gtk_mozbox_realize;
widget_class->key_press_event = gtk_mozbox_key_press_event;
/* save the parent class' set_focus method */
parent_class_set_focus = window_class->set_focus;
window_class->set_focus = gtk_mozbox_set_focus;
}
static void
@ -111,6 +127,61 @@ gtk_mozbox_realize (GtkWidget *widget)
gdk_window_add_filter (widget->window, gtk_mozbox_filter, mozbox);
}
static void
gtk_mozbox_set_focus (GtkWindow *window,
GtkWidget *focus)
{
GtkMozBox *mozbox;
GdkWindow *tmpWindow;
GtkWindow *parentGtkWindow;
g_return_if_fail(window != NULL);
g_return_if_fail(GTK_IS_MOZBOX(window));
mozbox = GTK_MOZBOX(window);
parentGtkWindow = gtk_mozbox_get_parent_gtkwindow (mozbox);
if (parentGtkWindow) {
parent_class_set_focus(parentGtkWindow, focus);
return;
}
/* as a fall back just hand it off to our parent class */
parent_class_set_focus(window, focus);
}
static gint
gtk_mozbox_key_press_event (GtkWidget *widget,
GdkEventKey *event)
{
GtkWindow *window;
GtkMozBox *mozbox;
GtkWindow *parentWindow;
gboolean handled = FALSE;
window = GTK_WINDOW (widget);
mozbox = GTK_MOZBOX (widget);
parentWindow = gtk_mozbox_get_parent_gtkwindow(mozbox);
/* give the focus window the chance to handle the event first. */
if (parentWindow && parentWindow->focus_widget) {
handled = gtk_widget_event (parentWindow->focus_widget, (GdkEvent*) event);
}
/* pass it off to the parent widget */
if (!handled) {
gdk_window_unref(event->window);
event->window = mozbox->parent_window;
gdk_window_ref(event->window);
gdk_event_put((GdkEvent *)event);
}
return TRUE;
}
static GdkFilterReturn
gtk_mozbox_filter (GdkXEvent *xevent,
GdkEvent *event,
@ -134,6 +205,23 @@ gtk_mozbox_filter (GdkXEvent *xevent,
}
}
static GtkWindow *
gtk_mozbox_get_parent_gtkwindow (GtkMozBox *mozbox)
{
GdkWindow *tmpWindow;
/* look for a parent GtkWindow in the heirarchy */
tmpWindow = mozbox->parent_window;
while (tmpWindow) {
gpointer data = NULL;
gdk_window_get_user_data(tmpWindow, &data);
if (data && GTK_IS_WINDOW(data)) {
return GTK_WINDOW(data);
}
tmpWindow = gdk_window_get_parent(tmpWindow);
}
return NULL;
}
GtkWidget*
gtk_mozbox_new (GdkWindow *parent_window)
{