Bugs #121252,#122120. Get grabs finished on Linux and implement nsWindow::CaptureMouse(). Not part of the build.

git-svn-id: svn://10.0.0.236/trunk@113021 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
blizzard%redhat.com 2002-01-28 06:23:27 +00:00
parent 9416759610
commit ed6985c02f
2 changed files with 113 additions and 69 deletions

View File

@ -106,7 +106,8 @@ nsWindow::nsWindow()
mHasFocus = PR_FALSE;
mInKeyRepeat = PR_FALSE;
mIsVisible = PR_FALSE;
mRetryGrab = PR_FALSE;
mRetryPointerGrab = PR_FALSE;
mRetryKeyboardGrab = PR_FALSE;
mTransientParent = nsnull;
mWindowType = eWindowType_child;
}
@ -664,8 +665,21 @@ nsWindow::PreCreateWidget(nsWidgetInitData *aWidgetInitData)
NS_IMETHODIMP
nsWindow::CaptureMouse(PRBool aCapture)
{
printf("nsWindow::CaptureMouse called!\n");
return NS_ERROR_NOT_IMPLEMENTED;
LOG(("CaptureMouse %p\n", (void *)this));
GtkWidget *widget =
get_gtk_widget_for_gdk_window(mDrawingarea->inner_window);
if (aCapture) {
gtk_grab_add(widget);
GrabPointer();
}
else {
ReleaseGrabs();
gtk_grab_remove(widget);
}
return NS_OK;
}
NS_IMETHODIMP
@ -676,15 +690,18 @@ nsWindow::CaptureRollupEvents(nsIRollupListener *aListener,
GtkWidget *widget =
get_gtk_widget_for_gdk_window(mDrawingarea->inner_window);
LOG(("CaptureRollupEvents %p\n", (void *)this));
if (aDoCapture) {
gRollupListener = aListener;
gRollupWindow =
getter_AddRefs(NS_GetWeakReference(NS_STATIC_CAST(nsIWidget*,this)));
gtk_grab_add(widget);
NativeGrab(PR_TRUE);
GrabPointer();
GrabKeyboard();
}
else {
NativeGrab(PR_FALSE);
ReleaseGrabs();
gtk_grab_remove(widget);
gRollupListener = nsnull;
gRollupWindow = nsnull;
@ -1080,8 +1097,7 @@ nsWindow::OnVisibilityNotifyEvent(GtkWidget *aWidget,
case GDK_VISIBILITY_PARTIAL:
mIsVisible = PR_TRUE;
// if we have to retry the grab, retry it.
if (mRetryGrab)
NativeGrab(PR_TRUE);
EnsureGrabs();
break;
default: // includes GDK_VISIBILITY_FULLY_OBSCURED
mIsVisible = PR_FALSE;
@ -1371,71 +1387,97 @@ nsWindow::NativeShow (PRBool aAction)
}
void
nsWindow::NativeGrab(PRBool aGrab)
nsWindow::EnsureGrabs(void)
{
LOG(("NativeGrab aGrab %d mRetryGrab %d\n", aGrab, mRetryGrab));
if (mRetryPointerGrab)
GrabPointer();
if (mRetryKeyboardGrab)
GrabKeyboard();
}
// Clear the retry flag. It doesn't matter if it's being released
// or grabbed.
mRetryGrab = PR_FALSE;
void
nsWindow::GrabPointer(void)
{
LOG(("GrabPointer %d\n", mRetryPointerGrab));
if (aGrab) {
// If the window isn't visible, just set the flag to retry the
// grab. When this window becomes visible, the grab will be
// retried.
PRBool visibility = PR_TRUE;
IsVisible(visibility);
if (!visibility) {
LOG(("window not visible\n"));
mRetryGrab = PR_TRUE;
return;
}
mRetryPointerGrab = PR_FALSE;
GdkCursor *cursor = gdk_cursor_new(GDK_ARROW);
gint retval;
retval = gdk_pointer_grab(mDrawingarea->inner_window, TRUE,
(GdkEventMask)(GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_ENTER_NOTIFY_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_POINTER_MOTION_MASK),
(GdkWindow *)NULL, cursor, GDK_CURRENT_TIME);
// now that we're done with the cursor, destroy it
gdk_cursor_destroy(cursor);
if (retval != GDK_GRAB_SUCCESS) {
LOG(("pointer grab failed\n"));
mRetryGrab = PR_TRUE;
return;
}
GdkWindow *grabWindow;
// we need to grab the keyboard on the transient parent so that we
// don't end up with any focus events that end up on the parent
// window that will cause the popup to go away
if (mTransientParent)
grabWindow = GTK_WIDGET(mTransientParent)->window;
else
grabWindow = mDrawingarea->inner_window;
retval = gdk_keyboard_grab(grabWindow, TRUE, GDK_CURRENT_TIME);
if (retval != GDK_GRAB_SUCCESS) {
LOG(("keyboard grab failed %d\n", retval));
gdk_pointer_ungrab(GDK_CURRENT_TIME);
mRetryGrab = PR_TRUE;
return;
}
// If the window isn't visible, just set the flag to retry the
// grab. When this window becomes visible, the grab will be
// retried.
PRBool visibility = PR_TRUE;
IsVisible(visibility);
if (!visibility) {
LOG(("GrabPointer: window not visible\n"));
mRetryPointerGrab = PR_TRUE;
return;
}
else {
gint retval;
retval = gdk_pointer_grab(mDrawingarea->inner_window, FALSE,
(GdkEventMask)(GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_ENTER_NOTIFY_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_POINTER_MOTION_MASK),
(GdkWindow *)NULL, NULL, GDK_CURRENT_TIME);
if (retval != GDK_GRAB_SUCCESS) {
LOG(("GrabPointer: pointer grab failed\n"));
mRetryPointerGrab = PR_TRUE;
}
}
void
nsWindow::GrabKeyboard(void)
{
LOG(("GrabKeyboard %d\n", mRetryKeyboardGrab));
mRetryKeyboardGrab = PR_FALSE;
// If the window isn't visible, just set the flag to retry the
// grab. When this window becomes visible, the grab will be
// retried.
PRBool visibility = PR_TRUE;
IsVisible(visibility);
if (!visibility) {
LOG(("GrabKeyboard: window not visible\n"));
mRetryKeyboardGrab = PR_TRUE;
return;
}
// we need to grab the keyboard on the transient parent so that we
// don't end up with any focus events that end up on the parent
// window that will cause the popup to go away
GdkWindow *grabWindow;
if (mTransientParent)
grabWindow = GTK_WIDGET(mTransientParent)->window;
else
grabWindow = mDrawingarea->inner_window;
gint retval;
retval = gdk_keyboard_grab(grabWindow, TRUE, GDK_CURRENT_TIME);
if (retval != GDK_GRAB_SUCCESS) {
LOG(("GrabKeyboard: keyboard grab failed %d\n", retval));
gdk_pointer_ungrab(GDK_CURRENT_TIME);
gdk_keyboard_ungrab(GDK_CURRENT_TIME);
mRetryKeyboardGrab = PR_TRUE;
}
}
void
nsWindow::ReleaseGrabs(void)
{
LOG(("ReleaseGrabs\n"));
mRetryPointerGrab = PR_FALSE;
mRetryKeyboardGrab = PR_FALSE;
gdk_pointer_ungrab(GDK_CURRENT_TIME);
gdk_keyboard_ungrab(GDK_CURRENT_TIME);
}
void
nsWindow::GetToplevelWidget(GtkWidget **aWidget)
{
@ -1515,15 +1557,13 @@ check_for_rollup(GdkWindow *aWindow, gdouble aMouseX, gdouble aMouseY,
PRBool
is_mouse_in_window (GdkWindow* aWindow, gdouble aMouseX, gdouble aMouseY)
{
gint x, y;
gint x = 0;
gint y = y;
gint w, h;
gint offsetX = 0;
gint offsetY = 0;
// XXX this causes a round trip to the ever lovely X server. fix me.
// gdk_window_get_origin(aWindow, &x, &y);
// use get_position
GtkWidget *widget;
GdkWindow *window;

View File

@ -175,7 +175,10 @@ class nsWindow : public nsCommonWidget, public nsSupportsWeakReference {
void NativeShow (PRBool aAction);
void NativeGrab (PRBool aGrab);
void EnsureGrabs (void);
void GrabPointer (void);
void GrabKeyboard (void);
void ReleaseGrabs (void);
nsWindow *mFocusChild;
@ -197,7 +200,8 @@ class nsWindow : public nsCommonWidget, public nsSupportsWeakReference {
PRPackedBool mInKeyRepeat;
PRPackedBool mIsVisible;
PRPackedBool mRetryGrab;
PRPackedBool mRetryPointerGrab;
PRPackedBool mRetryKeyboardGrab;
GtkWindow *mTransientParent;
};