Skip to content

Commit 5d4dc61

Browse files
authored
Merge pull request #806 from gree/update/osx_impl
refined osx implementation (about events, synchronization, offscreen rendering).
2 parents 02f9d65 + 4bbb052 commit 5d4dc61

File tree

2 files changed

+142
-166
lines changed

2 files changed

+142
-166
lines changed

plugins/Mac/Sources/WebView.mm

Lines changed: 114 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ @interface CWebViewPlugin : NSObject<WKUIDelegate, WKNavigationDelegate, WKScrip
3737
WKWebView *webView;
3838
NSString *gameObject;
3939
NSBitmapImageRep *bitmap;
40+
NSBitmapImageRep *bitmaps[2];
4041
BOOL needsDisplay;
4142
NSMutableDictionary *customRequestHeader;
4243
NSMutableArray *messages;
@@ -217,6 +218,8 @@ - (void)dispose
217218
[window close];
218219
}
219220
gameObject = nil;
221+
bitmaps[1] = nil;
222+
bitmaps[0] = nil;
220223
bitmap = nil;
221224
window = nil;
222225
windowController = nil;
@@ -417,17 +420,15 @@ - (void)observeValueForKeyPath:(NSString *)keyPath
417420

418421
- (void)addMessage:(NSString*)msg
419422
{
420-
@synchronized(messages)
421-
{
423+
@synchronized(messages) {
422424
[messages addObject:msg];
423425
}
424426
}
425427

426428
- (NSString *)getMessage
427429
{
428430
NSString *ret = nil;
429-
@synchronized(messages)
430-
{
431+
@synchronized(messages) {
431432
if ([messages count] > 0) {
432433
ret = [messages[0] copy];
433434
[messages removeObjectAtIndex:0];
@@ -446,9 +447,9 @@ - (void)setRect:(int)width height:(int)height
446447
frame.origin.x = 0;
447448
frame.origin.y = 0;
448449
webView.frame = frame;
449-
if (bitmap != nil) {
450-
bitmap = nil;
451-
}
450+
bitmaps[1] = nil;
451+
bitmaps[0] = nil;
452+
bitmap = nil;
452453
if (window != nil) {
453454
frame.origin = window.frame.origin;
454455
[window setFrame:frame display:YES];
@@ -601,9 +602,7 @@ - (void)sendMouseEvent:(int)x y:(int)y deltaY:(float)deltaY mouseState:(int)mous
601602
return;
602603
NSView *view = webView;
603604
NSGraphicsContext *context = [NSGraphicsContext currentContext];
604-
dispatch_async(
605-
dispatch_get_main_queue(),
606-
^{
605+
[self runBlock:^{
607606
NSEvent *event;
608607
switch (mouseState) {
609608
case 1:
@@ -636,7 +635,7 @@ - (void)sendMouseEvent:(int)x y:(int)y deltaY:(float)deltaY mouseState:(int)mous
636635
CFRelease(cgEvent);
637636
[view scrollWheel:scrollEvent];
638637
}
639-
});
638+
}];
640639
}
641640

642641
- (void)sendKeyEvent:(int)x y:(int)y keyChars:(char *)keyChars keyCode:(unsigned short)keyCode keyState:(int)keyState
@@ -650,51 +649,58 @@ - (void)sendKeyEvent:(int)x y:(int)y keyChars:(char *)keyChars keyCode:(unsigned
650649
if (0xf700 <= keyCode && keyCode <= 0xf8ff
651650
&& _nskey2cgkey.find(keyCode) != _nskey2cgkey.end())
652651
cgKeyCode = _nskey2cgkey.at(keyCode);
653-
dispatch_async(
654-
dispatch_get_main_queue(),
655-
^{
652+
[self runBlock:^{
656653
NSEvent *event;
657654
switch (keyState) {
658655
case 1:
659-
if (cgKeyCode == 0 || CGEventSourceKeyState(kCGEventSourceStateCombinedSessionState, cgKeyCode)) {
660-
event = [NSEvent keyEventWithType:NSEventTypeKeyDown
661-
location:NSMakePoint(x, y) modifierFlags:0
662-
timestamp:GetCurrentEventTime() windowNumber:0
663-
context:context
664-
characters:characters
665-
charactersIgnoringModifiers:characters
666-
isARepeat:NO keyCode:0];
667-
[view keyDown:event];
668-
}
656+
event = [NSEvent keyEventWithType:NSEventTypeKeyDown
657+
location:NSMakePoint(x, y) modifierFlags:0
658+
timestamp:GetCurrentEventTime() windowNumber:0
659+
context:context
660+
characters:characters
661+
charactersIgnoringModifiers:characters
662+
isARepeat:NO keyCode:keyCode];
663+
[view interpretKeyEvents:[NSArray arrayWithObject:event]];
664+
// if (CGEventSourceKeyState(kCGEventSourceStateCombinedSessionState, cgKeyCode)) {
665+
// [view keyDown:event];
666+
// } else {
667+
// [view interpretKeyEvents:[NSArray arrayWithObject:event]];
668+
// }
669669
break;
670670
case 2:
671-
if (cgKeyCode == 0 || CGEventSourceKeyState(kCGEventSourceStateCombinedSessionState, cgKeyCode)) {
672-
event = [NSEvent keyEventWithType:NSEventTypeKeyDown
673-
location:NSMakePoint(x, y) modifierFlags:0
674-
timestamp:GetCurrentEventTime() windowNumber:0
675-
context:context
676-
characters:characters
677-
charactersIgnoringModifiers:characters
678-
isARepeat:YES keyCode:0];
679-
[view keyDown:event];
680-
}
671+
event = [NSEvent keyEventWithType:NSEventTypeKeyDown
672+
location:NSMakePoint(x, y) modifierFlags:0
673+
timestamp:GetCurrentEventTime() windowNumber:0
674+
context:context
675+
characters:characters
676+
charactersIgnoringModifiers:characters
677+
isARepeat:YES keyCode:keyCode];
678+
[view interpretKeyEvents:[NSArray arrayWithObject:event]];
679+
// if (CGEventSourceKeyState(kCGEventSourceStateCombinedSessionState, cgKeyCode)) {
680+
// [view keyDown:event];
681+
// } else {
682+
// [view interpretKeyEvents:[NSArray arrayWithObject:event]];
683+
// }
681684
break;
682685
case 3:
683-
if (cgKeyCode == 0 || !CGEventSourceKeyState(kCGEventSourceStateCombinedSessionState, cgKeyCode)) {
684-
event = [NSEvent keyEventWithType:NSEventTypeKeyUp
685-
location:NSMakePoint(x, y) modifierFlags:0
686-
timestamp:GetCurrentEventTime() windowNumber:0
687-
context:context
688-
characters:characters
689-
charactersIgnoringModifiers:characters
690-
isARepeat:NO keyCode:0];
691-
[view keyUp:event];
692-
}
686+
event = [NSEvent keyEventWithType:NSEventTypeKeyUp
687+
location:NSMakePoint(x, y) modifierFlags:0
688+
timestamp:GetCurrentEventTime() windowNumber:0
689+
context:context
690+
characters:characters
691+
charactersIgnoringModifiers:characters
692+
isARepeat:NO keyCode:keyCode];
693+
[view interpretKeyEvents:[NSArray arrayWithObject:event]];
694+
// if (CGEventSourceKeyState(kCGEventSourceStateCombinedSessionState, cgKeyCode)) {
695+
// [view keyDown:event];
696+
// } else {
697+
// [view interpretKeyEvents:[NSArray arrayWithObject:event]];
698+
// }
693699
break;
694700
default:
695701
break;
696702
}
697-
});
703+
}];
698704
}
699705

700706
- (void)update:(BOOL)refreshBitmap
@@ -704,11 +710,15 @@ - (void)update:(BOOL)refreshBitmap
704710
@synchronized(self) {
705711
if (inRendering)
706712
return;
707-
if (refreshBitmap) {
708-
// [webView cacheDisplayInRect:webView.frame toBitmapImageRep:bitmap];
709-
NSRect rect = webView.frame;
710-
if (bitmap == nil) {
711-
bitmap
713+
inRendering = YES;
714+
}
715+
if (refreshBitmap) {
716+
// [webView cacheDisplayInRect:webView.frame toBitmapImageRep:bitmap];
717+
// bitmap = [webView bitmapImageRepForCachingDisplayInRect:webView.frame];
718+
NSRect rect = webView.frame;
719+
if (bitmaps[0] == nil || bitmaps[1] == nil) {
720+
for (int i = 0; i < 2; i++) {
721+
bitmaps[i]
712722
= [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
713723
pixelsWide:rect.size.width
714724
pixelsHigh:rect.size.height
@@ -720,42 +730,53 @@ - (void)update:(BOOL)refreshBitmap
720730
bitmapFormat:0
721731
bytesPerRow:(4 * rect.size.width)
722732
bitsPerPixel:32];
723-
// bitmap = [webView bitmapImageRepForCachingDisplayInRect:webView.frame];
724-
needsDisplay = true;
725733
}
726-
inRendering = YES;
727-
if (window != nil) {
728-
memset([bitmap bitmapData], 128, [bitmap bytesPerRow] * [bitmap pixelsHigh]);
729-
needsDisplay = true;
734+
bitmap = bitmaps[0];
735+
}
736+
NSBitmapImageRep *bitmap1 = (bitmap == bitmaps[0]) ? bitmaps[1] : bitmaps[0];
737+
if (window != nil) {
738+
memset([bitmap1 bitmapData], 128, [bitmap1 bytesPerRow] * [bitmap1 pixelsHigh]);
739+
@synchronized(self) {
740+
bitmap = bitmap1;
741+
needsDisplay = YES;
730742
inRendering = NO;
731-
} else {
732-
[webView takeSnapshotWithConfiguration:[WKSnapshotConfiguration new]
733-
completionHandler:^(NSImage *nsImg, NSError *err) {
734-
dispatch_async(
735-
dispatch_get_main_queue(),
736-
^{
743+
}
744+
} else {
745+
[self runBlock:^{
746+
[self->webView takeSnapshotWithConfiguration:[WKSnapshotConfiguration new]
747+
completionHandler:^(NSImage *nsImg, NSError *err) {
748+
if (err == nil) {
749+
NSGraphicsContext *ctx = [NSGraphicsContext graphicsContextWithBitmapImageRep:bitmap1];
750+
[NSGraphicsContext saveGraphicsState];
751+
[NSGraphicsContext setCurrentContext:ctx];
752+
[nsImg drawAtPoint:CGPointZero
753+
fromRect:CGRectMake(0, 0, [bitmap1 pixelsWide], [bitmap1 pixelsHigh])
754+
operation:NSCompositingOperationCopy
755+
fraction:1.0];
756+
[[NSGraphicsContext currentContext] flushGraphics];
757+
[NSGraphicsContext restoreGraphicsState];
758+
}
737759
@synchronized(self) {
738-
if (err == nil && self->bitmap != nil) {
739-
NSGraphicsContext *ctx = [NSGraphicsContext graphicsContextWithBitmapImageRep:self->bitmap];
740-
[NSGraphicsContext saveGraphicsState];
741-
[NSGraphicsContext setCurrentContext:ctx];
742-
[nsImg drawAtPoint:CGPointZero
743-
fromRect:CGRectMake(0, 0, [self->bitmap pixelsWide], [self->bitmap pixelsHigh])
744-
operation:NSCompositingOperationCopy
745-
fraction:1.0];
746-
[[NSGraphicsContext currentContext] flushGraphics];
747-
[NSGraphicsContext restoreGraphicsState];
748-
}
749-
self->needsDisplay = true;
760+
self->bitmap = bitmap1;
761+
self->needsDisplay = YES;
750762
self->inRendering = NO;
751763
}
752-
});
764+
}];
753765
}];
754-
}
755766
}
756767
}
757768
}
758769

770+
- (void)runBlock:(void (^)())block
771+
{
772+
block();
773+
// if ([NSThread isMainThread]) {
774+
// block();
775+
// } else {
776+
// dispatch_sync(dispatch_get_main_queue(), block);
777+
// }
778+
}
779+
759780
- (int)bitmapWide
760781
{
761782
@synchronized(self) {
@@ -772,44 +793,29 @@ - (int)bitmapHigh
772793

773794
- (void)render:(void *)textureBuffer
774795
{
796+
if (webView == nil)
797+
return;
798+
NSBitmapImageRep *bitmap0;
775799
@synchronized(self) {
776-
if (webView == nil)
777-
return;
778800
if (!needsDisplay)
779801
return;
780802
if (bitmap == nil)
781803
return;
782-
int w = (int)[bitmap pixelsWide];
783-
int h = (int)[bitmap pixelsHigh];
784-
int p = (int)[bitmap samplesPerPixel];
785-
int r = (int)[bitmap bytesPerRow];
786-
uint8_t *s0 = (uint8_t *)[bitmap bitmapData];
787-
uint32_t *d0 = (uint32_t *)textureBuffer;
788-
if (p == 3) {
789-
for (int y = 0; y < h; y++) {
790-
uint8_t *s = s0 + y * r;
791-
uint32_t *d = d0 + y * w;
792-
for (int x = 0; x < w; x++) {
793-
uint32_t r = *s++;
794-
uint32_t g = *s++;
795-
uint32_t b = *s++;
796-
*d++ = (0xff << 24) | (b << 16) | (g << 8) | r;
797-
}
798-
}
799-
} else if (p == 4) {
800-
for (int y = 0; y < h; y++) {
801-
uint8_t *s = s0 + y * r;
802-
uint32_t *d = d0 + y * w;
803-
for (int x = 0; x < w; x++) {
804-
uint32_t r = *s++;
805-
uint32_t g = *s++;
806-
uint32_t b = *s++;
807-
uint32_t a = *s++;
808-
*d++ = (a << 24) | (b << 16) | (g << 8) | r;
809-
}
810-
}
804+
needsDisplay = NO;
805+
bitmap0 = bitmap;
806+
}
807+
int w = (int)[bitmap0 pixelsWide];
808+
int h = (int)[bitmap0 pixelsHigh];
809+
//int p = (int)[bitmap0 samplesPerPixel]; // should be 4.
810+
int r = (int)[bitmap0 bytesPerRow];
811+
uint32_t *s0 = (uint32_t *)[bitmap0 bitmapData];
812+
uint32_t *d0 = (uint32_t *)textureBuffer;
813+
for (int y = 0; y < h; y++) {
814+
uint32_t *s = (uint32_t *)((uint8_t *)s0 + y * r);
815+
uint32_t *d = d0 + y * w;
816+
for (int x = 0; x < w; x++) {
817+
*d++ = *s++;
811818
}
812-
needsDisplay = false;
813819
}
814820
}
815821

0 commit comments

Comments
 (0)