Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit 93ab703

Browse files
Merge pull request #7528 from livecodeian/bugfix-23085
[[ Bug 23085 ]] Fix Macos Big Sur visual effect rendering
2 parents 2c07ea3 + c5a4759 commit 93ab703

File tree

4 files changed

+86
-6
lines changed

4 files changed

+86
-6
lines changed

docs/notes/bugfix-23085.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Fix visual effect rendering on Macos Big Sur

engine/src/mac-core.mm

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
{
4949
kMCMacPlatformBreakEvent = 0,
5050
kMCMacPlatformMouseSyncEvent = 1,
51+
kMCMacPlatformDrawSyncEvent = 2,
5152
};
5253

5354
////////////////////////////////////////////////////////////////////////////////
@@ -73,6 +74,13 @@ bool MCMacPlatformApplicationSendEvent(NSEvent *p_event)
7374
return true;
7475
}
7576

77+
if ([p_event type] == NSApplicationDefined &&
78+
[p_event subtype] == kMCMacPlatformDrawSyncEvent)
79+
{
80+
MCMacPlatformHandleDrawSync([p_event window]);
81+
return true;
82+
}
83+
7684
// MW-2014-08-14: [[ Bug 13016 ]] Whilst the windowserver moves a window
7785
// we intercept mouseDragged events so we can keep script informed.
7886
NSWindow *t_window;
@@ -1982,6 +1990,21 @@ void MCMacPlatformSyncMouseBeforeDragging(void)
19821990
}
19831991
}
19841992

1993+
void MCMacPlatformSyncUpdateAfterDraw(NSInteger windowNumber)
1994+
{
1995+
NSEvent *t_event;
1996+
t_event = [NSEvent otherEventWithType:NSApplicationDefined
1997+
location:NSMakePoint(0,0)
1998+
modifierFlags:0
1999+
timestamp:0
2000+
windowNumber:windowNumber
2001+
context:NULL
2002+
subtype:kMCMacPlatformDrawSyncEvent
2003+
data1:0
2004+
data2:0];
2005+
[NSApp postEvent:t_event atStart:YES];
2006+
}
2007+
19852008
void MCMacPlatformSyncMouseAfterTracking(void)
19862009
{
19872010
NSEvent *t_event;

engine/src/mac-internal.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,8 @@ class MCMacPlatformWindow: public MCPlatformWindow
505505
// IM-2015-01-30: [[ Bug 14140 ]] Locking the frame will prevent the window from being moved or resized
506506
void SetFrameLocked(bool p_locked);
507507

508+
void DrawSync(void);
509+
508510
protected:
509511
virtual void DoRealize(void);
510512
virtual void DoSynchronize(void);
@@ -542,7 +544,7 @@ class MCMacPlatformWindow: public MCPlatformWindow
542544

543545
// The window's content view.
544546
MCWindowView *m_view;
545-
547+
546548
struct
547549
{
548550
// When the mask changes and the window has a shadow we have to
@@ -559,6 +561,10 @@ class MCMacPlatformWindow: public MCPlatformWindow
559561

560562
// When the frame is locked, any changes to the window rect will be prevented.
561563
bool m_frame_locked : 1;
564+
565+
// This is used to signal to DoUpdate that a redraw has been performed
566+
// in response to an update request.
567+
bool m_waiting_for_draw : 1;
562568
};
563569

564570
// A window might map to one of several different classes, so we use a
@@ -578,6 +584,7 @@ class MCMacPlatformWindow: public MCPlatformWindow
578584
static bool s_hiding;
579585
static MCMacPlatformWindow *s_hiding_focused;
580586
static MCMacPlatformWindow *s_hiding_unfocused;
587+
static bool s_showing_sheet;
581588
};
582589

583590
////////////////////////////////////////////////////////////////////////////////
@@ -592,6 +599,7 @@ void MCMacPlatformHandleMousePress(uint32_t p_button, bool p_is_down);
592599
void MCMacPlatformHandleMouseMove(MCPoint p_screen_location);
593600
void MCMacPlatformHandleMouseScroll(CGFloat dx, CGFloat dy);
594601
void MCMacPlatformHandleMouseSync(void);
602+
void MCMacPlatformHandleDrawSync(NSWindow *window);
595603
void MCMacPlatformHandleMouseAfterWindowHidden(void);
596604

597605
void MCMacPlatformHandleMouseForResizeStart(void);
@@ -600,6 +608,8 @@ void MCMacPlatformHandleMouseForResizeEnd(void);
600608
void MCMacPlatformSyncMouseBeforeDragging(void);
601609
void MCMacPlatformSyncMouseAfterTracking(void);
602610

611+
void MCMacPlatformSyncUpdateAfterDraw(NSInteger windowNumber);
612+
603613
void MCMacPlatformHandleModifiersChanged(MCPlatformModifiers modifiers);
604614

605615
bool MCMacPlatformMapKeyCode(uint32_t mac_key_code, uint32_t modifier_flags, MCPlatformKeyCode& r_key_code);

engine/src/mac-window.mm

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "region.h"
2323
#include "graphics.h"
2424
#include "unicode.h"
25+
#include "globals.h"
2526

2627
#include "platform.h"
2728
#include "platform-internal.h"
@@ -1588,6 +1589,13 @@ - (void)drawRect: (NSRect)dirtyRect
15881589
//////////
15891590

15901591
MCGRegionDestroy(t_update_region);
1592+
1593+
if (MCmajorosversion >= MCOSVersionMake(10,16,0))
1594+
{
1595+
// Send event to break wait in NSApp::nextEventMatchingMask in MCMacPlatformWindow::DoUpdate
1596+
t_window->DrawSync();
1597+
MCMacPlatformSyncUpdateAfterDraw(self.window.windowNumber);
1598+
}
15911599
}
15921600

15931601
//////////
@@ -1674,6 +1682,8 @@ - (void)setFrameSize: (NSSize)size
16741682
m_has_sheet = false;
16751683
m_frame_locked = false;
16761684

1685+
m_waiting_for_draw = false;
1686+
16771687
m_parent = nil;
16781688
}
16791689

@@ -1693,6 +1703,7 @@ - (void)setFrameSize: (NSSize)size
16931703
bool MCMacPlatformWindow::s_hiding = false;
16941704
MCMacPlatformWindow *MCMacPlatformWindow::s_hiding_focused = nil;
16951705
MCMacPlatformWindow *MCMacPlatformWindow::s_hiding_unfocused = nil;
1706+
bool MCMacPlatformWindow::s_showing_sheet = false;
16961707

16971708
////////////////////////////////////////////////////////////////////////////////
16981709

@@ -2122,6 +2133,7 @@ - (void)setFrameSize: (NSSize)size
21222133
m_parent -> Retain();
21232134
((MCMacPlatformWindow *)m_parent) -> m_has_sheet = true;
21242135

2136+
s_showing_sheet = true;
21252137
[NSApp beginSheet: m_window_handle modalForWindow: t_parent -> m_window_handle modalDelegate: m_delegate didEndSelector: @selector(didEndSheet:returnCode:contextInfo:) contextInfo: nil];
21262138
}
21272139

@@ -2136,6 +2148,7 @@ - (void)setFrameSize: (NSSize)size
21362148
((MCMacPlatformWindow *)m_parent) -> m_has_sheet = false;
21372149
m_parent -> Release();
21382150
m_parent = nil;
2151+
s_showing_sheet = false;
21392152
}
21402153
else if (m_style == kMCPlatformWindowStyleDialog)
21412154
{
@@ -2198,8 +2211,19 @@ bool MCMacDoUpdateRegionCallback(void *p_context, const MCRectangle &p_rect)
21982211

21992212
return true;
22002213
}
2214+
2215+
void MCMacPlatformHandleDrawSync(NSWindow *window)
2216+
{
2217+
/* NOOP */
2218+
}
2219+
2220+
void MCMacPlatformWindow::DrawSync()
2221+
{
2222+
m_waiting_for_draw = false;
2223+
}
2224+
22012225
void MCMacPlatformWindow::DoUpdate(void)
2202-
{
2226+
{
22032227
// If the shadow has changed (due to the mask changing) we must disable
22042228
// screen updates otherwise we get a flicker.
22052229
// IM-2015-02-23: [[ WidgetPopup ]] Assume shadow changes when redrawing a non-opaque widget
@@ -2214,10 +2238,32 @@ bool MCMacDoUpdateRegionCallback(void *p_context, const MCRectangle &p_rect)
22142238
s_rect_count = 0;
22152239
MCRegionForEachRect(m_dirty_region, MCMacDoUpdateRegionCallback, m_view);
22162240

2217-
// Force a re-display, this will cause drawRect to be invoked on our view
2218-
// which in term will result in a redraw window callback being sent.
2219-
[m_view displayIfNeededInRect: [m_view mapMCRectangleToNSRect:MCRegionGetBoundingBox(m_dirty_region)]];
2220-
2241+
if (MCmajorosversion >= MCOSVersionMake(10,16,0))
2242+
{
2243+
// Frequent redraws with displayIfNeeded causes graphical glitches on Macos Big Sur, so instead
2244+
// we enter the runloop to trigger a redraw. This will cause drawRect to be invoked on our view
2245+
// which in turn will result in a redraw window callback being sent.
2246+
// The timeout value of 0.02ms is specified to avoid hitting the 60hz redraw limit.
2247+
if (!s_inside_focus_event && !s_showing_sheet && ![m_delegate inUserReshape])
2248+
{
2249+
m_waiting_for_draw = true;
2250+
while (m_waiting_for_draw)
2251+
{
2252+
NSEvent *t_event;
2253+
t_event = [NSApp nextEventMatchingMask: NSApplicationDefinedMask
2254+
untilDate: [NSDate dateWithTimeIntervalSinceNow: 0.02]
2255+
inMode: NSEventTrackingRunLoopMode
2256+
dequeue: NO];
2257+
t_event = nil;
2258+
}
2259+
}
2260+
}
2261+
else
2262+
{
2263+
// Use displayIfNeeded to trigger a redraw
2264+
[m_view displayIfNeeded];
2265+
}
2266+
22212267
// Re-enable screen updates if needed.
22222268
if (t_shadow_changed)
22232269
{

0 commit comments

Comments
 (0)