void wxModalEventLoop::DoRun() { wxWindowDisabler disabler(m_modalWindow); wxMacAutoreleasePool autoreleasepool; bool resetGroupParent = false; WindowGroupRef windowGroup = NULL; WindowGroupRef formerParentGroup = NULL; // make sure modal dialogs are in the right layer so that they are not covered if ( m_modalWindow != NULL ) { if ( m_modalWindow->GetParent() == NULL ) { windowGroup = GetWindowGroup(m_modalNativeWindow) ; if ( windowGroup != GetWindowGroupOfClass( kMovableModalWindowClass ) ) { formerParentGroup = GetWindowGroupParent( windowGroup ); SetWindowGroupParent( windowGroup, GetWindowGroupOfClass( kMovableModalWindowClass ) ); resetGroupParent = true; } } } m_modalWindow->SetFocus(); RunAppModalLoopForWindow(m_modalNativeWindow); if ( resetGroupParent ) { SetWindowGroupParent( windowGroup , formerParentGroup ); } }
OSStatus wxOverlayImpl::CreateOverlayWindow() { OSStatus err; WindowAttributes overlayAttributes = kWindowIgnoreClicksAttribute; if ( m_window ) { m_overlayParentWindow =(WindowRef) m_window->MacGetTopLevelWindowRef(); Rect bounds ; MacGetBounds(&bounds); err = CreateNewWindow( kOverlayWindowClass, overlayAttributes, &bounds, &m_overlayWindow ); if ( err == noErr ) { SetWindowGroup( m_overlayWindow, GetWindowGroup(m_overlayParentWindow)); // Put them in the same group so that their window layers are consistent } } else { m_overlayParentWindow = NULL ; CGRect cgbounds ; cgbounds = CGDisplayBounds(CGMainDisplayID()); Rect bounds; bounds.top = (short)cgbounds.origin.y; bounds.left = (short)cgbounds.origin.x; bounds.bottom = (short)(bounds.top + cgbounds.size.height); bounds.right = (short)(bounds.left + cgbounds.size.width); err = CreateNewWindow( kOverlayWindowClass, overlayAttributes, &bounds, &m_overlayWindow ); } ShowWindow(m_overlayWindow); return err; }
// Creates an overlay window which will move with its parent. This technique is typical for doing things like drawing on top of movies, // creating selection rectangles, drawing on top of GL windows, etc. static void CreateOverlayWindow( WindowRef window ) { OSStatus err; Rect windowRect; WindowStorage *windowStorage = (WindowStorage*) GetWRefCon( window ); WindowAttributes overlayAttributes = kWindowNoShadowAttribute | kWindowIgnoreClicksAttribute | kWindowNoActivatesAttribute | kWindowStandardHandlerAttribute; static EventHandlerUPP overlayWindowEventHandlerUPP; const EventTypeSpec windowEvents[] = { { kEventClassWindow, kEventWindowBoundsChanged }, { kEventClassWindow, kEventWindowShown }, { kEventClassWindow, kEventWindowClose } }; SetPortWindowPort( window ); GetWindowPortBounds( window, &windowRect ); LocalToGlobalRect( &windowRect ); // Window to be size of window it lies on err = CreateNewWindow( kOverlayWindowClass, overlayAttributes, &windowRect, &windowStorage->overlayWindow ); if ( err != noErr ) goto Bail; SetWindowGroup( windowStorage->overlayWindow, GetWindowGroup(window) ); // Put them in the same group so that their window layers are consistent if ( overlayWindowEventHandlerUPP == NULL ) overlayWindowEventHandlerUPP = NewEventHandlerUPP( OverlayWindowEventHandlerProc ); err = InstallWindowEventHandler( windowStorage->overlayWindow, overlayWindowEventHandlerUPP, GetEventTypeCount(windowEvents), windowEvents, windowStorage, NULL ); ShowWindow( windowStorage->overlayWindow ); Bail: return; }
void LineTool( WindowRef window ) { OSStatus err; Point endPt; MouseTrackingResult trackingResult; Point beginPt; Rect windowRect; WindowRef overlayWindow; CGRect cgRect; CGContextRef cgContext; Boolean isStillDown = true; SetThemeCursor( kThemeCrossCursor ); SetPortWindowPort( window ); GetWindowPortBounds( window, &windowRect ); LocalToGlobalRect( &windowRect ); (void) CreateNewWindow( kOverlayWindowClass, kWindowHideOnSuspendAttribute | kWindowIgnoreClicksAttribute, &windowRect, &overlayWindow ); SetPortWindowPort( overlayWindow ); SetWindowGroup( overlayWindow, GetWindowGroup(window) ); // This assures we draw into the same layer as the window ShowWindow( overlayWindow ); GetMouse( &beginPt ); cgRect = CGRectMake( 0, 0, windowRect.right - windowRect.left+1, windowRect.bottom - windowRect.top+1 ); CreateCGContextForPort( GetWindowPort(overlayWindow), &cgContext ); CGContextSetLineWidth( cgContext, 3 ); // Line is 3 pixels wide CGContextSetRGBStrokeColor( cgContext, 1.0, .45, .3, .4 ); // Make it orange with alpha = 0.4 SyncCGContextOriginWithPort( cgContext, GetWindowPort(overlayWindow) ); CGContextTranslateCTM( cgContext, 0, windowRect.bottom - windowRect.top ); // Flip & rotate the context to use QD coordinates CGContextScaleCTM( cgContext, 1.0, -1.0 ); do { err = TrackMouseLocation( GetWindowPort(window), &endPt, &trackingResult ); switch ( trackingResult ) { case kMouseTrackingMouseDragged: CGContextClearRect( cgContext, cgRect ); // "Erase" the window #if ( 1 ) CGContextMoveToPoint( cgContext, beginPt.h, beginPt.v ); // Draw the line CGContextAddLineToPoint( cgContext, endPt.h, endPt.v ); CGContextStrokePath( cgContext ); #else MoveTo( beginPt.h, beginPt.v ); // We could use QuickDraw and draw opaque lines LineTo( endPt.h, endPt.v ); #endif CGContextFlush( cgContext ); // Flush our drawing to the screen break; case kMouseTrackingMouseDown: break; case kMouseTrackingMouseUp: case kMouseTrackingUserCancelled: isStillDown = false; break; } } while( isStillDown == true ); CGContextRelease( cgContext ); DisposeWindow( overlayWindow ); SetThemeCursor( kThemeArrowCursor ); return; }
static pascal OSStatus SimpleWindowEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ) { #pragma unused ( inCallRef ) HICommand command; Point pt; SInt16 value; Rect r; WindowGroupRef windowGroup; WindowGroupAttributes windowGroupAttributes; UInt32 eventKind = GetEventKind( inEvent ); UInt32 eventClass = GetEventClass( inEvent ); WindowRef window = (WindowRef) inUserData; OSStatus err = eventNotHandledErr; WindowStorage *windowStorage = (WindowStorage*) GetWRefCon( window ); switch ( eventClass ) { case kEventClassWindow: if ( eventKind == kEventWindowClose ) // Dispose extra window storage here { if ( windowStorage->overlayWindow != NULL ) SendWindowCloseEvent( windowStorage->overlayWindow ); DisposePtr( (Ptr) windowStorage ); } else if ( eventKind == kEventWindowClickContentRgn ) { if ( GetControlValueByID( window, 'Butn', 0 ) == 1 ) // If the "Line Tool" button is depressed { LineTool( window ); SetControlValueByID( window, 'Butn', 0, 0 ); // Pop the button back up err = noErr; } } else if ( (eventKind == kEventWindowBoundsChanging) || (eventKind == kEventWindowBoundsChanged) ) { if ( windowStorage->overlayWindow != NULL ) // Resize the overlay window as well { (void) GetEventParameter( inEvent, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &r ); SizeWindow( windowStorage->overlayWindow, r.right-r.left, r.bottom-r.top, false ); } } break; case kEventClassCommand: if ( eventKind == kEventCommandProcess ) { GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &command ); if ( command.commandID == kHICommandOK ) // Change the window layering and attributes { value = GetControlValueByID( window, 'Rdio', 0 ); // Which group was chosen windowGroupAttributes = 0; // Now set the attributes for the parent group if ( GetControlValueByID( window, 'Chek', 0 ) == 1 ) windowGroupAttributes |= kWindowGroupAttrMoveTogether; ChangeWindowGroupAttributes( g.windowGroups[value-1], windowGroupAttributes, ~windowGroupAttributes ); windowGroupAttributes = kWindowGroupAttrMoveTogether | kWindowGroupAttrLayerTogether | kWindowGroupAttrHideOnCollapse; err = CreateWindowGroup( windowGroupAttributes, &windowGroup ); // We can only call SetWindowGroupParent() on an empty group, so create a new one if ( err == noErr ) err = SetWindowGroupParent( windowGroup, g.windowGroups[value-1] ); // Set the new parent if ( (err == noErr) && (windowStorage->overlayWindow != NULL) ) err = SetWindowGroup( windowStorage->overlayWindow, windowGroup ); // FIRST add the overlay window so that it is on top of the "normal" window if ( err == noErr ) { ReleaseWindowGroup( GetWindowGroup(window) ); // Release the old group err = SetWindowGroup( window, windowGroup ); // Add the window to the new group } } else if ( command.commandID == 'GAtr' ) // Get the window attributes { windowGroup = GetWindowGroupParent( GetWindowGroup(window) ); GetWindowGroupAttributes( windowGroup, &windowGroupAttributes ); SetControlValueByID( window, 'Chek', 0, ((windowGroupAttributes & kWindowGroupAttrMoveTogether) != 0) ); if ( windowGroup == g.windowGroups[0] ) SetControlValueByID( window, 'Rdio', 0, 1 ); else if ( windowGroup == g.windowGroups[1] ) SetControlValueByID( window, 'Rdio', 0, 2 ); else SetControlValueByID( window, 'Rdio', 0, 3 ); } else if ( command.commandID == 'Poof' ) { SetPortWindowPort( window ); GetMouse( &pt ); LocalToGlobal( &pt ); pt.v -= 50; // Draw the Poof 50 pixels above the mouse PoofItGood( pt ); } else if ( command.commandID == 'Over' ) { if ( windowStorage->overlayWindow == NULL ) { CreateOverlayWindow( window ); } else { SendWindowCloseEvent( windowStorage->overlayWindow ); } } } break; } return( err ); }