2828
2929// //////////////////////////////////////////////////////////////////////////////
3030
31+ extern MCRectangle MCU_make_rect (int2 x, int2 y, uint2 w, uint2 h);
32+
33+ static CGPoint s_snapshot_start_point, s_snapshot_end_point;
34+ static bool s_snapshot_done = false ;
35+
36+ static float menu_screen_height (void )
37+ {
38+ NSArray *t_screens;
39+ t_screens = [NSScreen screens ];
40+
41+ NSScreen *t_screen;
42+ for (uint32_t i = 0 ; i < [t_screens count ]; i++)
43+ {
44+ t_screen = (NSScreen *)[t_screens objectAtIndex: i];
45+ if (NSPointInRect (NSZeroPoint , [t_screen frame ]))
46+ break ;
47+ }
48+
49+ return NSMaxY ([t_screen frame ]);
50+ }
51+
52+ static NSPoint cocoa_point_from_carbon (CGFloat x, CGFloat y)
53+ {
54+ return NSMakePoint (x, menu_screen_height () - y);
55+ }
56+
57+ static NSRect cocoa_rect_from_carbon (CGRect p_rect)
58+ {
59+ NSPoint t_top_left, t_bottom_right;
60+ t_top_left = cocoa_point_from_carbon (p_rect . origin . x, p_rect . origin . y + p_rect . size . height);
61+ return NSMakeRect (t_top_left . x, t_top_left . y, p_rect . size . width, p_rect . size . height);
62+ }
63+
64+ static CGPoint carbon_point_from_cocoa (NSPoint p_point)
65+ {
66+ return CGPointMake (p_point . x, menu_screen_height () - p_point . y);
67+ }
68+
69+ static CGRect cgrect_from_points (CGPoint x, CGPoint y)
70+ {
71+ CGFloat l, t, r, b;
72+ l = MCMin (x . x, y . x);
73+ r = MCMax (x . x, y . x);
74+ t = MCMin (x . y, y . y);
75+ b = MCMax (x . y, y . y);
76+ return CGRectMake (l, t, r - l, b - t);
77+ }
78+
79+ static MCRectangle mcrect_from_points (CGPoint x, CGPoint y)
80+ {
81+ CGFloat l, t, r, b;
82+ l = MCMin (x . x, y . x);
83+ r = MCMax (x . x, y . x);
84+ t = MCMin (x . y, y . y);
85+ b = MCMax (x . y, y . y);
86+ return MCU_make_rect (l, t, r - l, b - t);
87+ }
88+
89+ static Rect rect_from_points (CGPoint x, CGPoint y)
90+ {
91+ CGFloat l, t, r, b;
92+ l = MCMin (x . x, y . x);
93+ r = MCMax (x . x, y . x);
94+ t = MCMin (x . y, y . y);
95+ b = MCMax (x . y, y . y);
96+
97+ Rect t_rect;
98+ SetRect (&t_rect, l, t, r, b);
99+
100+ return t_rect;
101+ }
102+
103+ @interface MCSnapshotWindow : NSWindow
104+ {
105+ NSBox *m_region;
106+ }
107+
108+ - (id )init ;
109+ - (void )dealloc ;
110+
111+ - (void )mouseDown : (NSEvent *)event ;
112+ - (void )mouseUp : (NSEvent *)event ;
113+ - (void )mouseDragged : (NSEvent *)event ;
114+ @end
115+
116+ @implementation MCSnapshotWindow
117+
118+ - (id )init
119+ {
120+ // Compute the desktop bounds.
121+ NSRect t_bounds;
122+ t_bounds = NSZeroRect ;
123+ NSArray *t_screens;
124+ t_screens = [NSScreen screens ];
125+ for (uint32_t i = 0 ; i < [t_screens count ]; i++)
126+ {
127+ NSScreen *t_screen;
128+ t_screen = (NSScreen *)[t_screens objectAtIndex: i];
129+ t_bounds = NSUnionRect (t_bounds, [t_screen frame ]);
130+ }
131+
132+ // Initialize the window.
133+ self = [super initWithContentRect: t_bounds styleMask: NSBorderlessWindowMask backing: NSBackingStoreBuffered defer: NO ];
134+
135+ // Make sure the window is not opaque to events, and renders everything
136+ // at 50% transparency.
137+ [self setOpaque: NO ];
138+ [self setAlphaValue: 0.5 ];
139+ [self setBackgroundColor: [NSColor clearColor ]];
140+ [self setLevel: NSScreenSaverWindowLevel ];
141+ [self setIgnoresMouseEvents: NO ];
142+
143+ // Setup the region used to display the selected area.
144+ m_region = [[NSBox alloc ] initWithFrame: NSZeroRect ];
145+ [m_region setTitlePosition: NSNoTitle];
146+ [m_region setBorderType: NSLineBorder];
147+ [m_region setBoxType: NSBoxCustom];
148+ [m_region setBorderWidth: 1 ];
149+ [m_region setBorderColor: [NSColor whiteColor ]];
150+ [m_region setFillColor: [NSColor grayColor ]];
151+ [[self contentView ] addSubview: m_region];
152+
153+ // Remember to return the window.
154+ return self;
155+ }
156+
157+ - (void )dealloc
158+ {
159+ [m_region release ];
160+ [super dealloc ];
161+ }
162+
163+ - (void )mouseDown : (NSEvent *)event
164+ {
165+ // Start the snapshot region.
166+ s_snapshot_start_point = carbon_point_from_cocoa ([event locationInWindow ]); // CGEventGetLocation([event CGEvent]);
167+ s_snapshot_end_point = s_snapshot_start_point;
168+ }
169+
170+ - (void )mouseUp : (NSEvent *)event
171+ {
172+ // Finish the snapshot region.
173+ s_snapshot_end_point = carbon_point_from_cocoa ([event locationInWindow ]); // CGEventGetLocation([event CGEvent]);
174+ s_snapshot_done = true ;
175+
176+ // Remove the region from display and force an update to ensure in QD mode, we don't get
177+ // partial grayness over the selected area.
178+ [m_region setHidden: YES ];
179+ [[self contentView ] setNeedsDisplayInRect: [m_region frame ]];
180+ [self displayIfNeeded ];
181+ }
182+
183+ - (void )mouseDragged : (NSEvent *)event
184+ {
185+ // Update the snapshot end point
186+ s_snapshot_end_point = carbon_point_from_cocoa ([event locationInWindow ]); // CGEventGetLocation([event CGEvent]);
187+
188+ // Get the old and new frames.
189+ NSRect t_old_frame, t_new_frame;
190+ t_old_frame = [m_region frame ];
191+ t_new_frame = cocoa_rect_from_carbon (cgrect_from_points (s_snapshot_start_point, s_snapshot_end_point));
192+
193+ // Update the frames
194+ [m_region setFrame: t_new_frame];
195+ [m_region setNeedsDisplay: YES ];
196+
197+ // Make sure the contentview is redrawn in the appropriate places.
198+ [[self contentView ] setNeedsDisplayInRect: t_old_frame];
199+ [[self contentView ] setNeedsDisplayInRect: t_new_frame];
200+ }
201+
202+ @end
203+
204+ // //////////////////////////////////////////////////////////////////////////////
205+
31206static void MCMacPlatformCGImageToMCImageBitmap (CGImageRef p_image, MCImageBitmap*& r_bitmap)
32207{
33208 if (p_image != nil )
@@ -54,8 +229,33 @@ static void MCMacPlatformCGImageToMCImageBitmap(CGImageRef p_image, MCImageBitma
54229
55230void MCPlatformScreenSnapshotOfUserArea (MCImageBitmap*& r_bitmap)
56231{
57- // COCOA-TODO: Screen snapshot of area.
58- r_bitmap = nil ;
232+ // Compute the rectangle to grab in screen co-ords.
233+ MCRectangle t_screen_rect;
234+
235+ // Create a window that covers the whole screen.
236+ MCSnapshotWindow *t_window;
237+ t_window = [[MCSnapshotWindow alloc ] init ];
238+ [t_window orderFront: nil ];
239+
240+ // Set the cursor to cross.
241+ [[NSCursor crosshairCursor ] push ];
242+
243+ // Wait until the mouse has been released.
244+ s_snapshot_done = false ;
245+ while (!s_snapshot_done)
246+ MCPlatformWaitForEvent (60.0 , false );
247+
248+ // Remove the window from display.
249+ [t_window orderOut: nil ];
250+ [t_window release ];
251+
252+ // Return the cursor to arrow.
253+ [NSCursor pop ];
254+
255+ // Compute the selected rectangle.
256+ t_screen_rect = mcrect_from_points (s_snapshot_start_point, s_snapshot_end_point);
257+
258+ MCPlatformScreenSnapshot (t_screen_rect, r_bitmap);
59259}
60260
61261void MCPlatformScreenSnapshotOfWindow (uint32_t p_window_id, MCImageBitmap*& r_bitmap)
0 commit comments