From 5b135ba1b6df353b7cd05cfba51f37663fd87278 Mon Sep 17 00:00:00 2001 From: "quy%igelaus.com.au" Date: Thu, 5 Oct 2000 00:29:55 +0000 Subject: [PATCH] Updating xlib toolkit. r=a=blizzard. Not part of build. Bug # 54132 --- widget/src/xlib/nsAppShell.cpp | 79 ++++++++++-- widget/src/xlib/nsClipboard.cpp | 11 +- widget/src/xlib/nsWidget.cpp | 6 +- widget/src/xlib/nsWindow.cpp | 120 ++++++++++++------ widget/src/xlib/nsWindow.h | 14 +- .../window_service/nsIXlibWindowService.h | 3 +- 6 files changed, 179 insertions(+), 54 deletions(-) diff --git a/widget/src/xlib/nsAppShell.cpp b/widget/src/xlib/nsAppShell.cpp index 33c605cdf42f..cbb06d11dc1c 100644 --- a/widget/src/xlib/nsAppShell.cpp +++ b/widget/src/xlib/nsAppShell.cpp @@ -20,6 +20,8 @@ * Contributor(s): * Peter Hartshorn * Ken Faulkner + * Tony Tsui + * Caspian Maclean */ #include @@ -214,7 +216,7 @@ static int CallTimeToNextTimeoutFunc(struct timeval * aTimeval) #endif /* MOZ_MONOLITHIC_TOOLKIT */ } -static void CallProcessTimeoutsProc(void) +static void CallProcessTimeoutsProc(Display *aDisplay) { #ifdef MOZ_MONOLITHIC_TOOLKIT NS_ProcessTimeouts(); @@ -223,7 +225,7 @@ static void CallProcessTimeoutsProc(void) if (proc) { - (*proc)(); + (*proc)(aDisplay); } #endif /* MOZ_MONOLITHIC_TOOLKIT */ } @@ -447,7 +449,7 @@ nsresult nsAppShell::Run() } if (please_run_timer_queue) { - CallProcessTimeoutsProc(); + CallProcessTimeoutsProc(mDisplay); } // Flush the nsWindow's drawing queue @@ -533,7 +535,7 @@ nsresult nsAppShell::DispatchNativeEvent(PRBool aRealEvent, void *aEvent) free(event); } - CallProcessTimeoutsProc(); + CallProcessTimeoutsProc(mDisplay); nsWindow::UpdateIdle(nsnull); return rv; @@ -655,6 +657,11 @@ nsAppShell::HandleMotionNotifyEvent(XEvent *event, nsWidget *aWidget) mevent.point.x = event->xmotion.x; mevent.point.y = event->xmotion.y; + mevent.isShift = mShiftDown; + mevent.isControl = mCtrlDown; + mevent.isAlt = mAltDown; + mevent.isMeta = mMetaDown; + Display * dpy = (Display *)aWidget->GetNativeData(NS_NATIVE_DISPLAY); Window win = (Window)aWidget->GetNativeData(NS_NATIVE_WINDOW); // We are only interested in the LAST (newest) location of the pointer @@ -868,6 +875,38 @@ nsAppShell::HandleConfigureNotifyEvent(XEvent *event, nsWidget *aWidget) delete sevent.windowSize; } +PRUint32 nsConvertCharCodeToUnicode(XKeyEvent* xkey) +{ + // The only Unicode specific at the moment is casting to PRUint32. + + // For control characters convert from the event ascii code (e.g. 1 for + // control-a) to the ascii code for the key, e.g., 'a' for + // control-a. + + KeySym keysym; + XComposeStatus compose; + unsigned char string_buf[CHAR_BUF_SIZE]; + int len = 0; + + len = XLookupString(xkey, (char *)string_buf, CHAR_BUF_SIZE, &keysym, &compose); + if (0 == len) return 0; + + if (xkey->state & ControlMask) { + if (xkey->state & ShiftMask) { + return (PRUint32)(string_buf[0] + 'A' - 1); + } + else { + return (PRUint32)(string_buf[0] + 'a' - 1); + } + } + if (!isprint(string_buf[0])) { + return 0; + } + else { + return (PRUint32)(string_buf[0]); + } +} + void nsAppShell::HandleKeyPressEvent(XEvent *event, nsWidget *aWidget) { @@ -931,7 +970,7 @@ nsAppShell::HandleKeyPressEvent(XEvent *event, nsWidget *aWidget) keyEvent.keyCode = nsKeyCode::ConvertKeySymToVirtualKey(keysym); keyEvent.charCode = 0; keyEvent.time = event->xkey.time; - keyEvent.isShift = event->xkey.state & ShiftMask; + keyEvent.isShift = (event->xkey.state & ShiftMask) ? PR_TRUE : PR_FALSE; keyEvent.isControl = (event->xkey.state & ControlMask) ? 1 : 0; keyEvent.isAlt = (event->xkey.state & Mod1Mask) ? 1 : 0; // I think 'meta' is the same as 'alt' in X11. Is this OK for other systems? @@ -950,9 +989,9 @@ nsAppShell::HandleKeyPressEvent(XEvent *event, nsWidget *aWidget) focusWidget->DispatchKeyEvent(keyEvent); keyEvent.keyCode = nsKeyCode::ConvertKeySymToVirtualKey(keysym); - keyEvent.charCode = isprint(string_buf[0]) ? string_buf[0] : 0; + keyEvent.charCode = nsConvertCharCodeToUnicode(&event->xkey); keyEvent.time = event->xkey.time; - keyEvent.isShift = event->xkey.state & ShiftMask; + keyEvent.isShift = (event->xkey.state & ShiftMask) ? PR_TRUE : PR_FALSE; keyEvent.isControl = (event->xkey.state & ControlMask) ? 1 : 0; keyEvent.isAlt = (event->xkey.state & Mod1Mask) ? 1 : 0; keyEvent.isMeta = (event->xkey.state & Mod1Mask) ? 1 : 0; @@ -962,6 +1001,20 @@ nsAppShell::HandleKeyPressEvent(XEvent *event, nsWidget *aWidget) keyEvent.widget = focusWidget; keyEvent.eventStructType = NS_KEY_EVENT; + if (keyEvent.charCode) + { + /* This is the comment from the GTK code. Hope it makes more sense to you + * than it did for me. + * + * if the control, meta, or alt key is down, then we should leave + * the isShift flag alone (probably not a printable character) + * if none of the other modifier keys are pressed then we need to + * clear isShift so the character can be inserted in the editor + */ + if (!keyEvent.isControl && !keyEvent.isAlt && !keyEvent.isMeta) + keyEvent.isShift = PR_FALSE; + } + focusWidget->DispatchKeyEvent(keyEvent); } @@ -1090,7 +1143,11 @@ nsAppShell::HandleEnterEvent(XEvent *event, nsWidget *aWidget) enterEvent.message = NS_MOUSE_ENTER; enterEvent.eventStructType = NS_MOUSE_EVENT; - + + // make sure this is in focus. This will do until I rewrite all the + // focus routines. KenF + aWidget->SetFocus(); + NS_ADDREF(aWidget); aWidget->DispatchWindowEvent(enterEvent); NS_RELEASE(aWidget); @@ -1249,6 +1306,8 @@ void nsAppShell::HandleDragLeaveEvent(XEvent *event, nsWidget *aWidget) { nsresult rv = nsServiceManager::GetService(kCDragServiceCID, nsIDragService::GetIID(), (nsISupports**)&dragService); + + // FIXME: Not sure if currentlyDragging is required. KenF if (NS_SUCCEEDED(rv)) { nsCOMPtr dragServiceXlib; dragServiceXlib = do_QueryInterface(dragService); @@ -1280,6 +1339,8 @@ void nsAppShell::HandleDragDropEvent(XEvent *event, nsWidget *aWidget) { nsresult rv = nsServiceManager::GetService(kCDragServiceCID, nsIDragService::GetIID(), (nsISupports**)&dragService); + + // FIXME: Dont think the currentlyDragging check is required. KenF if (NS_SUCCEEDED(rv)) { nsCOMPtr dragServiceXlib; dragServiceXlib = do_QueryInterface(dragService); @@ -1299,6 +1360,8 @@ void nsAppShell::HandleDragDropEvent(XEvent *event, nsWidget *aWidget) { NS_IF_ADDREF(aWidget); aWidget->DispatchMouseEvent(mevent); NS_IF_RELEASE(aWidget); + + dragService->EndDragSession(); } } diff --git a/widget/src/xlib/nsClipboard.cpp b/widget/src/xlib/nsClipboard.cpp index 025b1f704d71..42089dc5c743 100644 --- a/widget/src/xlib/nsClipboard.cpp +++ b/widget/src/xlib/nsClipboard.cpp @@ -20,7 +20,7 @@ * Contributor(s): * Pierre Phaneuf * Peter Hartshorn - * Ken Faulkner > + * Ken Faulkner */ /* TODO: @@ -97,7 +97,8 @@ void nsClipboard::Init() { // This is the callback function for our nsWidget. It is given the // XEvent from nsAppShell. - +// FIXME: We _should_ assign mTransferable here depending on if its a +// selectionrequest nsEventStatus PR_CALLBACK nsClipboard::Callback(nsGUIEvent *event) { XEvent *ev = (XEvent *)event->nativeMsg; @@ -192,6 +193,12 @@ NS_IMETHODIMP nsClipboard::SetNativeClipboardData(PRInt32 aWhichClipboard) nsCOMPtr flavorList; nsCOMPtr transferable(getter_AddRefs(GetTransferable(aWhichClipboard))); + // FIXME Need to make sure mTransferable has reference to selectionclipboard. + // This solves the problem with copying to an external app. + // but cannot be sure if its fully correct until menu copy/paste is working. + if (aWhichClipboard == kSelectionClipboard) + mTransferable = transferable; + // make sure we have a good transferable if (nsnull == transferable) { #ifdef DEBUG_faulkner diff --git a/widget/src/xlib/nsWidget.cpp b/widget/src/xlib/nsWidget.cpp index 4faebfcc1212..bf50b85fa6ce 100644 --- a/widget/src/xlib/nsWidget.cpp +++ b/widget/src/xlib/nsWidget.cpp @@ -22,6 +22,7 @@ * Ken Faulkner * Quy Tonthat * B.J. Rossiter + * Tony Tsui */ #include "nsWidget.h" @@ -606,6 +607,8 @@ NS_IMETHODIMP nsWidget::Show(PRBool bState) } if (mParentWidget) { ((nsWidget *)mParentWidget)->WidgetShow(this); + // Fix Popups appearing behind mozilla window. TonyT + XRaiseWindow(mDisplay, mBaseWindow); } else { if (mBaseWindow) { @@ -808,7 +811,8 @@ nsWidget::GetEventMask() PointerMotionMask | StructureNotifyMask | VisibilityChangeMask | - FocusChangeMask; + FocusChangeMask | + OwnerGrabButtonMask; return event_mask; } diff --git a/widget/src/xlib/nsWindow.cpp b/widget/src/xlib/nsWindow.cpp index d4690e4caaa9..d18ef39f4e67 100644 --- a/widget/src/xlib/nsWindow.cpp +++ b/widget/src/xlib/nsWindow.cpp @@ -21,6 +21,7 @@ * Peter Hartshorn * Ken Faulkner * B.J. Rossiter + * Tony Tsui */ #include "nsWindow.h" @@ -31,6 +32,10 @@ #define ABS(i) ( i<0 ? 0-i : i ) +// Variables for grabbing +PRBool nsWindow::sIsGrabbing = PR_FALSE; +nsWindow *nsWindow::sGrabWindow = NULL; + // Routines implementing an update queue. // We keep a single queue for all widgets because it is // (most likely) more efficient and better looking to handle @@ -195,6 +200,13 @@ nsWindow::nsWindow() : nsWidget() nsWindow::~nsWindow() { + // Release grab + if (sGrabWindow == this) + { + sIsGrabbing = PR_FALSE; + sGrabWindow = NULL; + } + // Should get called from ~nsWidget() anyway. KenF // if (mBaseWindow) //Destroy(); @@ -222,11 +234,80 @@ PRBool nsWindow::OnExpose(nsPaintEvent &event) return result; } +// Function that does native grab. +void nsWindow::NativeGrab(PRBool aGrab) +{ + Cursor newCursor = XCreateFontCursor(mDisplay, XC_right_ptr); + if (aGrab) + { + int retval; + retval = XGrabPointer(mDisplay, mBaseWindow, PR_TRUE, (ButtonPressMask | + ButtonReleaseMask | EnterWindowMask | LeaveWindowMask + | PointerMotionMask), GrabModeAsync, GrabModeAsync, + (Window*)NULL, newCursor, CurrentTime); + if (retval != GrabSuccess) + fprintf(stderr, "Grab pointer failed!\n"); + retval = XGrabKeyboard(mDisplay, mBaseWindow, PR_TRUE, GrabModeAsync, + GrabModeAsync, CurrentTime); + if (retval != GrabSuccess) + fprintf(stderr, "Grab keyboard failed!\n"); + + } + else + { + XUngrabPointer(mDisplay, CurrentTime); + XUngrabKeyboard(mDisplay, CurrentTime); + } +} + +/* This called when a popup is generated so that if a mouse down event occurs, + * the passed listener can be informed (see nsWidget::HandlePopup). It is also + * called with aDoCapture == PR_FALSE when a popup is no longer visible + */ +NS_IMETHODIMP nsWindow::CaptureRollupEvents(nsIRollupListener * aListener, + PRBool aDoCapture, + PRBool aConsumeRollupEvent) +{ + if (aDoCapture) + { + NativeGrab(PR_TRUE); + + sIsGrabbing = PR_TRUE; + sGrabWindow = this; + + //fprintf(stderr, "Received listener from generated popup\n"); + gRollupListener = aListener; + + // Get assertion error: + // ###!!! ASSERTION: Did you know you were calling |NS_GetWeakReference()| on + // something that doesn't support weak references?: 'factoryPtr', file + // nsWeakReference.cpp, line 55 + //gRollupWidget = getter_AddRefs(NS_GetWeakReference(NS_STATIC_CAST(nsIWidget*,this))); + gRollupWidget = NS_STATIC_CAST(nsIWidget*,this); + + // GTK does not seem to use this but other window toolkits do + gRollupConsumeRollupEvent = PR_TRUE; + //} + }else{ + + // Release Grab + if (sGrabWindow == this) + sGrabWindow = NULL; + + sIsGrabbing = PR_FALSE; + + NativeGrab(PR_FALSE); + + gRollupListener = nsnull; + gRollupWidget = nsnull; + } + return NS_OK; +} NS_IMETHODIMP nsWindow::InvalidateRegion(const nsIRegion* aRegion, PRBool aIsSynchronous) { @@ -453,7 +534,8 @@ nsWindow::GetEventMask() PointerMotionMask | StructureNotifyMask | VisibilityChangeMask | - FocusChangeMask; + FocusChangeMask | + OwnerGrabButtonMask; return event_mask; } @@ -564,42 +646,6 @@ NS_IMETHODIMP nsWindow::Update() return NS_OK; } - -/* This called when a popup is generated so that if a mouse down event occurs, - * the passed listener can be informed (see nsWidget::HandlePopup). It is also - * called with aDoCapture == PR_FALSE when a popup is no longer visible - */ -NS_IMETHODIMP nsWindow::CaptureRollupEvents(nsIRollupListener * aListener, - PRBool aDoCapture, - PRBool aConsumeRollupEvent) -{ - if (aDoCapture) { - /*if (mSuperWin) {*/ - - // Gtk also has functionality to handle "grabbing" - - //fprintf(stderr, "Received listener from generated popup\n"); - gRollupListener = aListener; - - // Get assertion error: - // ###!!! ASSERTION: Did you know you were calling |NS_GetWeakReference()| on - // something that doesn't support weak references?: 'factoryPtr', file - // nsWeakReference.cpp, line 55 - //gRollupWidget = getter_AddRefs(NS_GetWeakReference(NS_STATIC_CAST(nsIWidget*,this))); - gRollupWidget = NS_STATIC_CAST(nsIWidget*,this); - - // GTK does not seem to use this but other window toolkits do - gRollupConsumeRollupEvent = PR_TRUE; - //} - }else{ - // Gtk also has functionality to handle "ungrabbing" - - gRollupListener = nsnull; - gRollupWidget = nsnull; - } - return NS_OK; -} - NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect) { PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("nsWindow::Scroll()\n")); diff --git a/widget/src/xlib/nsWindow.h b/widget/src/xlib/nsWindow.h index bdce8472a0e4..adb710240cbd 100644 --- a/widget/src/xlib/nsWindow.h +++ b/widget/src/xlib/nsWindow.h @@ -21,12 +21,14 @@ * Peter Hartshorn * Ken Faulkner * B.J. Rossiter + * Tony Tsui */ #ifndef nsWindow_h__ #define nsWindow_h__ #include "nsWidget.h" +#include #include "nsString.h" @@ -69,9 +71,9 @@ class nsWindow : public nsWidget nsWindow(); ~nsWindow(); static void UpdateIdle (void *data); - NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener, - PRBool aDoCapture, - PRBool aConsumeRollupEvent); + NS_IMETHOD CaptureRollupEvents(nsIRollupListener *aListener, + PRBool aDoCapture, + PRBool aConsumeRollupEvent); NS_IMETHOD Invalidate(PRBool aIsSynchronous); NS_IMETHOD Invalidate(const nsRect & aRect, PRBool aIsSynchronous); NS_IMETHOD InvalidateRegion(const nsIRegion* aRegion, PRBool aIsSynchronous); @@ -102,14 +104,16 @@ protected: virtual long GetEventMask(); - + // Keyboard and Pointer Grabbing + void NativeGrab(PRBool aGrab); void QueueDraw(); void UnqueueDraw(); PRBool mIsUpdating; PRBool mBlockFocusEvents; - + static PRBool sIsGrabbing; + static nsWindow *sGrabWindow; #if 0 virtual void CreateNative(Window aParent, nsRect aRect); diff --git a/widget/src/xlib/window_service/nsIXlibWindowService.h b/widget/src/xlib/window_service/nsIXlibWindowService.h index 77cd31940ca2..a583cad05207 100644 --- a/widget/src/xlib/window_service/nsIXlibWindowService.h +++ b/widget/src/xlib/window_service/nsIXlibWindowService.h @@ -26,6 +26,7 @@ #include "nsISupports.h" #include +#include // Interface id for the XlibWindow service // { bd39ccb0-3f08-11d3-b419-00805f6d4c2a } @@ -53,7 +54,7 @@ typedef void (*nsXlibEventDispatcher)(nsXlibNativeEvent aNativeEvent); typedef int (*nsXlibTimeToNextTimeoutFunc)(struct timeval *aTimer); -typedef void (*nsXlibProcessTimeoutsProc)(void); +typedef void (*nsXlibProcessTimeoutsProc)(Display *aDisplay); class nsIXlibWindowService : public nsISupports {