diff --git a/src/mred/mred.cxx b/src/mred/mred.cxx index 7742f2cec7..480b0609bb 100644 --- a/src/mred/mred.cxx +++ b/src/mred/mred.cxx @@ -117,6 +117,7 @@ wxFrame *mred_real_main_frame; static Scheme_Thread *user_main_thread; extern void wxMediaIOCheckLSB(void); +extern void wxMouseEventHandled(void); #include "mred.h" @@ -1681,6 +1682,9 @@ Scheme_Object *wxDispatchEventsUntilWaitable(wxDispatch_Check_Fun f, void *data, Scheme_Object *result = scheme_void; c = MrEdGetContext(); +#ifdef wx_mac + wxMouseEventHandled(); +#endif if (c->ready_to_go || (c->handler_running != scheme_current_thread)) { diff --git a/src/mred/mredmac.cxx b/src/mred/mredmac.cxx index cab6de3207..0ec1485555 100644 --- a/src/mred/mredmac.cxx +++ b/src/mred/mredmac.cxx @@ -62,6 +62,7 @@ typedef struct EventFinderClosure { } EventFinderClosure; static int queue_size, max_queue_size; +static int mouse_down_in_flight; Bool wx_ignore_key; /* used in wxItem */ @@ -229,6 +230,11 @@ static void QueueTransferredEvent(EventRecord *e) max_queue_size = queue_size; } + if ((e->what == mouseDown) + || (e->what == mouseMenuDown)) { + mouse_down_in_flight = 1; + } + q->rgn = NULL; if (e->what == updateEvt) { @@ -421,6 +427,39 @@ int WNE(EventRecord *e, double sleep_secs) { int r; + if (mouse_down_in_flight) { + /* Try hard to handle a mouse-down event before calling + WaitNextEvent again. Otherwise, mouse events for tracking + (e.g., menu clicks, close-window clicks, window-drag clicks, + and button clicks) can get lost. We can't wait forever, though; + the target eventspace might be stuck for some reason. If MrEd + is idle enough to sleep, take that as a sign that it's ok to + get new events. Another sign is if there's a new mouse-down or + key-down event. Some other cases, such as a `yield' or waiting + on an AppleEvent, are handled by explicitly turning off + mouse_down_in_flight before we get here. */ + EventRef eref; + EventTypeSpec poll_evts[2]; + + if (!sleep_secs) { + poll_evts[0].eventClass = kEventClassMouse; + poll_evts[0].eventKind = kEventMouseDown; + poll_evts[1].eventClass = kEventClassKeyboard; + poll_evts[1].eventKind = kEventRawKeyDown; + eref = AcquireFirstMatchingEventInQueue(GetCurrentEventQueue(), + 2, + poll_evts, + kEventQueueOptionsNone); + if (eref) { + ReleaseEvent(eref); + } else { + /* Looks like we should wait... */ + return 0; + } + } + } + + wxResetCanvasBackgrounds(); if (!wne_handlersInstalled) { @@ -486,6 +525,8 @@ void WakeUpMrEd() Application queue, sticks them in the MrEd queue, and returns 1, unless it was called less than delay_time ago, in which case do nothing and return 0. */ + +static unsigned long lastTime; static int TransferQueue(int all) { @@ -494,7 +535,6 @@ static int TransferQueue(int all) int delay_time = 0; /* Don't call WaitNextEvent() too often. */ - static unsigned long lastTime; if (TickCount() <= lastTime + delay_time) return 0; @@ -607,6 +647,11 @@ void wxTracking() cont_mouse_context_window = NULL; } +void wxMouseEventHandled(void) +{ + mouse_down_in_flight = 0; +} + #ifdef RECORD_HISTORY FILE *history; #endif @@ -948,7 +993,7 @@ int MrEdGetNextEvent(int check_only, int current_only, if (check_only) return TRUE; - + MrDequeue(osq); return TRUE; @@ -1937,6 +1982,7 @@ static void wait_for_reply(AppleEvent *ae, AppleEvent *reply) AEGetAttributePtr(ae, keyReturnIDAttr, typeLongInteger, &rtype, &id, sizeof(long), &sz); while (1) { + wxMouseEventHandled(); WNE(&e, 1.0); if (e.what == kHighLevelEvent) AEProcessAppleEvent(&e); diff --git a/src/mred/wxme/wx_media.cxx b/src/mred/wxme/wx_media.cxx index c6bee0e954..e6c97af28b 100644 --- a/src/mred/wxme/wx_media.cxx +++ b/src/mred/wxme/wx_media.cxx @@ -466,7 +466,7 @@ void wxMediaEdit::OnEvent(wxMouseEvent *event) snip = NULL; } else snip = NULL; - sequenced = (PTRNE(snip, caretSnip)); + sequenced = 0 && (PTRNE(snip, caretSnip)); if (sequenced) BeginEditSequence(); SetCaretOwner(snip); diff --git a/src/mred/wxme/wx_media.h b/src/mred/wxme/wx_media.h index 9b96e153b5..238e110cd9 100644 --- a/src/mred/wxme/wx_media.h +++ b/src/mred/wxme/wx_media.h @@ -645,6 +645,7 @@ class wxMediaEdit : public wxMediaBuffer void NeedRefresh(long start, long end = -1); void NeedRefresh(double, double, double, double); void RefreshByLineDemand(void); + void ContinueRefresh(void); void RefreshBox(double x, double y, double w, double h); void NeedCaretRefresh(void); diff --git a/src/mred/wxme/wx_mpriv.cxx b/src/mred/wxme/wx_mpriv.cxx index 7dd2886b31..6cb1c81901 100644 --- a/src/mred/wxme/wx_mpriv.cxx +++ b/src/mred/wxme/wx_mpriv.cxx @@ -2394,8 +2394,8 @@ void wxMediaEdit::Redraw() return; if (admin->DelayRefresh()) { - /* Do we know the refresh box already? */ - if (!delayedscroll && !delayedscrollbox && (refreshAll || refreshUnset)) { + /* Does the admin know the refresh box already? */ + if ((delayedscroll != -1) && !delayedscrollbox && (refreshAll || refreshUnset)) { /* Yes ... */ if (!refreshAll && refreshBoxUnset) return; /* Nothing to do */ @@ -2425,8 +2425,11 @@ void wxMediaEdit::Redraw() dc = admin->GetDC(&x, &y); - if (!dc) + if (!dc) { + delayedscroll = -1; + delayedscrollbox = FALSE; return; + } origx = x; origy = y; @@ -2691,10 +2694,7 @@ void wxMediaEdit::NeedRefresh(long start, long end) drawCachedInBitmap = FALSE; - if (!delayRefresh && !printing && (!admin || !admin->DelayRefresh())) - Redraw(); - else if (admin && !admin->standard) - admin->Resized(FALSE); + ContinueRefresh(); } void wxMediaEdit::RefreshByLineDemand(void) @@ -2702,10 +2702,30 @@ void wxMediaEdit::RefreshByLineDemand(void) if (!graphicMaybeInvalid) graphicMaybeInvalid = TRUE; + ContinueRefresh(); +} + +void wxMediaEdit::ContinueRefresh(void) +{ if (!delayRefresh && !printing && (!admin || !admin->DelayRefresh())) Redraw(); - else if (admin && !admin->standard) - admin->Resized(FALSE); + else { + int rs = 1; + if (!delayRefresh && ((delayedscroll != -1) + || delayedscrollbox)) { + if (!printing && admin) { + /* Although the administrator says to delay, + we can't just drop scroll requests. */ + Redraw(); + rs = 0; + } else { + delayedscroll = -1; + delayedscrollbox = NULL; + } + } + if (admin && !admin->standard) + admin->Resized(FALSE); + } } void wxMediaEdit::NeedCaretRefresh(void) diff --git a/src/wxmac/src/mac/wx_app.cc b/src/wxmac/src/mac/wx_app.cc index 44e28e7ce2..caa56aece8 100644 --- a/src/wxmac/src/mac/wx_app.cc +++ b/src/wxmac/src/mac/wx_app.cc @@ -45,6 +45,7 @@ extern WindowPtr MrEdMouseWindow(Point where); extern WindowPtr MrEdKeyWindow(); extern void wxCheckRootFrame(WindowPtr w); +extern void wxMouseEventHandled(void); int wxTranslateRawKey(int key); @@ -329,6 +330,7 @@ void wxApp::doMacMouseDown(void) #endif if (modal) { + wxMouseEventHandled(); SysBeep(0); return; } @@ -336,6 +338,12 @@ void wxApp::doMacMouseDown(void) } } + if (windowPart != inContent) { + /* We've gotten far enough handling the mouse-down event that + mouse-up events are ok to receive again: */ + wxMouseEventHandled(); + } + switch (windowPart) { case inMenuBar: @@ -365,6 +373,7 @@ void wxApp::doMacMouseDown(void) break; case inContent: doMacInContent(window); + wxMouseEventHandled(); break; case inDrag: doMacInDrag(window); @@ -1197,10 +1206,9 @@ void wxApp::doMacInContent(WindowPtr window) { wxFrame* theMacWxFrame; theMacWxFrame = findMacWxFrame(window); - if (theMacWxFrame) - { - doMacContentClick(theMacWxFrame); - } + if (theMacWxFrame) { + doMacContentClick(theMacWxFrame); + } } //----------------------------------------------------------------------------- diff --git a/src/wxmac/src/mac/wx_main.cc b/src/wxmac/src/mac/wx_main.cc index 766f370db1..7cdeaaa660 100644 --- a/src/wxmac/src/mac/wx_main.cc +++ b/src/wxmac/src/mac/wx_main.cc @@ -18,6 +18,7 @@ #include "PSDC.h" void wxCleanUp(void); +extern void wxMouseEventHandled(void); /////////////////////////////////////////////////////////////////////////////// // The procedure CreateApp initializes the whole application. @@ -92,6 +93,8 @@ void wxCleanUp(void) Bool wxYield(void) { // Yield to incoming messages + wxMouseEventHandled(); + while (wxTheApp->Pending()) { wxTheApp->Dispatch(); }