Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!purdue!bu-cs!dartvax!eleazar.dartmouth.edu!earleh From: earleh@eleazar.dartmouth.edu (Earle R. Horton) Newsgroups: comp.sys.mac.programmer Subject: Re: WaitNextEvent Message-ID: <14798@dartvax.Dartmouth.EDU> Date: 2 Aug 89 19:51:12 GMT References: <11875@orstcs.CS.ORST.EDU> <227700022@uxa.cso.uiuc.edu> <8211@hoptoad.uucp> Sender: news@dartvax.Dartmouth.EDU Reply-To: earleh@eleazar.dartmouth.edu (Earle R. Horton) Organization: Thayer School of Engineering Lines: 188 In article <8211@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes: >Does anyone have any example code which illustrates the use of the >mouse region argument to WaitNextEvent? Yes, this example is from the main event parsing area of my pulsar simulation program. It is based on examples in Apple Sample Code, but it is a little more involved, I like to think, because it handles multiple application window types. The code which I based this on is in TESample.c, which is part of Sample Code number 2. The mouse region argument is used by MultiFinder to wake up your application when it is in front, and the cursor moves out of this region. This lets you wake up, change the cursor, and go back to sleep again. Disclaimer: This source code works. It is, I think, thoroughly debugged. Your mileage may differ. Earle R. Horton /* * The ww_pwindow data type is a pointer to a structure which has * first a WindowRecord, a DialogRecord, or a TPrPort at byte * offset zero. Then, there are all kinds of goodies like * cursor Handles, TextEdit Handles, ProcPtrs, Print Record * Handles, and an endless variety of pointers to specialized * data structures for the manipulation of window and document * contents. The cursor modification routine knows enough about * the contents of the various windows I have in my program to be * able to make an educated guess as to which cursor should be * used. */ RgnHandle cursorRgn; /* * The routine for getting events from the event queue. Returns what * kind of event was received, in case it gets called from a background * procedure. */ short doevents() { EventRecord myEvent; register ww_pwindow activeWindow; short result; /* * See if there's an event. Toss {Wait|Get}NextEvent's return value, 'cause * a false is the same as getting a nullEvent, and a true any other * event. */ if(WNEExists){ activeWindow = (ww_pwindow) FrontWindow(); if (wwmine(activeWindow)) { SetPort(activeWindow); SetupCursor(activeWindow,cursorRgn); } (void)WaitNextEvent(everyEvent,&myEvent,sleeptime(),cursorRgn); }else{ SystemTask(); (void)GetNextEvent(everyEvent, &myEvent); } /* * Make sure we have the right cursor before handling the event. */ activeWindow = (ww_pwindow) FrontWindow(); if (wwmine(activeWindow)) { SetPort(activeWindow); SetupCursor(activeWindow,cursorRgn); } /* * Stash result, 'cause eventparser() just might change it. */ result = myEvent.what; /* * Pass the event to the event parser. */ eventparser(&myEvent); return result; } /* * Set up the cursor if one of our windows is frontmost. Also calculate * the mouse-moved region for WaitNextEvent(). Three possibilities exist * for the mouse region. These are a region containing our window's visRgn, * a region containing active text, and a region which is everything but * one of the first two. * Caller has to do a SetPort() to the target window first. * * A major shortcoming of this approach is that this routine has to know * something about the structure of the window contents, and allows for * only one cursor to be defined per window. An improvement would be * to have a special routine like this for each window type, with most * windows using the default. Then, one could have a real fancy window * with lots of logical regions and a different cursor for each. * * Implementation is left as an exercise for the reader. */ SetupCursor(wptr,region) ww_pwindow wptr; RgnHandle region; { RgnHandle arrowRgn,windowRgn; /* Scratch regions. */ Rect cursRect; /* Active Rect. */ Point mouse; /* Mouse location in global coordinates. */ Boolean useSpecialCursor; /* We have a special cursor for use in this window. */ Point originPt; /* TopLeft of our portRect in global coordinates. */ useSpecialCursor = false; /* * Allocate scratch regions. */ arrowRgn = NewRgn(); windowRgn = NewRgn(); /* * Make a real big region for outside of our window. */ RectRgn(arrowRgn,&hugerect); /* * If the front window is ours, and if it has a special cursor * associated with it, then we will want to keep track of where * the mouse is in relation to the region where this cursor is * supposed to be active. */ if ( wptr->ww_cursor != nil ) { /* * Find out where the mouse is, globally speaking. */ GetMouse(&mouse); LocalToGlobal(&mouse); /* * A window with text. Use the TextEdit Record's viewRect. */ if( wptr->ww_text != nil ){ cursRect = (*wptr->ww_text)->viewRect; } /* * If it's a modeless dialog, try to find out if the mouse is in * an active editText item. If you are of the Maroney persuasion, * then you use FindDItem() here to determine if the mouse is in * ANY editText item. */ else if( wptr->textH != nil ){ cursRect = (*wptr->textH)->viewRect; } /* * If it's some other kind of window, assume the portRect. Subtract * width of standard scroll bars if present. */ else{ cursRect = wptr->ww_rec.port.portRect; if(wptr->ww_vScrollBar != nil){ cursRect.bottom -= SCROLLBARWIDTH - 1; } if(wptr->ww_hScrollBar != nil){ cursRect.right -= SCROLLBARWIDTH - 1; } } /* * Make a region corresponding to the visible part of our cursRect, * in global coordinates. */ RectRgn(windowRgn,&cursRect); SectRgn(windowRgn,wptr->ww_rec.port.visRgn,windowRgn); SetPt(&originPt,0,0); LocalToGlobal(&originPt); OffsetRgn(windowRgn,originPt.h,originPt.v); /* * Subtract our window region from the everything else region. */ DiffRgn(arrowRgn,windowRgn,arrowRgn); /* * Region parameter is the region the mouse is in. Special * cursor if it is our window region. */ useSpecialCursor = PtInRgn(mouse,windowRgn); } if(useSpecialCursor == true){ CopyRgn(windowRgn,region); SetCursor(*wptr->ww_cursor); }else{ CopyRgn(arrowRgn,region); SetCursor(&qd.arrow); } /* * Kill scratch regions. */ DisposeRgn(arrowRgn); DisposeRgn(windowRgn); }