Files
darling-lol/tools/riot-client-resize-check.m
T
lucannez64 e94c3ce40f Fix League client resizing and runtime compatibility
Fix X11 presentation handoff after resizing, preserve NSView size callbacks, and correct content and backing-layer geometry. Add CoreText font enumeration for the language dropdown and rebuild/install the matching runtime overlays.

Correct CarbonCore Gestalt version queries and roll back proc_listpids for Vanguard testing. Document that VAN -101 can still recur. Include accumulated CoreAudio stream and AudioUnit corrections.

Add standalone font, version, resize and publisher-handoff regressions. Record manual confirmation of the language dropdown and window resizing; all 29 pinned patches and the source/script audit validate.
2026-10-15 18:44:43 +02:00

148 lines
6.8 KiB
Objective-C

#import <AppKit/AppKit.h>
#import <QuartzCore/CALayer.h>
#import <QuartzCore/CATransaction.h>
#import <IOSurface/IOSurface.h>
#import <X11/Xlib.h>
#import <X11/Xutil.h>
#import <OpenGL/OpenGL.h>
#import <OpenGL/gl.h>
#include <stdio.h>
#include <dlfcn.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <fcntl.h>
@interface NSObject (NativeWindowID)
- (unsigned long)windowHandle;
@end
static void pump(double seconds) {
NSDate *end=[NSDate dateWithTimeIntervalSinceNow:seconds];
while([end timeIntervalSinceNow]>0) {
NSEvent *e=[NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES];
if(e)[NSApp sendEvent:e];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.005]];
}
}
static IOSurfaceRef surface(int width,int height,int generation) {
int dims[]={width,height,4,width*4,0x42475241};
const void *keys[]={kIOSurfaceWidth,kIOSurfaceHeight,kIOSurfaceBytesPerElement,kIOSurfaceBytesPerRow,kIOSurfacePixelFormat},*values[5];
for(int i=0;i<5;i++)values[i]=CFNumberCreate(NULL,kCFNumberIntType,&dims[i]);
CFDictionaryRef options=CFDictionaryCreate(NULL,keys,values,5,&kCFTypeDictionaryKeyCallBacks,&kCFTypeDictionaryValueCallBacks);
IOSurfaceRef s=IOSurfaceCreate(options);CFRelease(options);for(int i=0;i<5;i++)CFRelease(values[i]);
if(!s)return NULL;
unsigned char *pixels=IOSurfaceGetBaseAddress(s);size_t stride=IOSurfaceGetBytesPerRow(s);
for(int y=0;y<height;y++)for(int x=0;x<width;x++){unsigned char *p=pixels+y*stride+x*4;p[0]=x<width/2?0:255;p[1]=y<height/2?255:0;p[2]=40+generation*40;p[3]=255;}
return s;
}
/* Exercise the transport protocol with two owned fixture publishers. The
* software owner changes to a popup while readback supplies the resized main
* window, as happens when a browser GPU process serves multiple windows. */
typedef struct {
uint32_t magic, sequence, width, height, stride, format;
uint64_t size;
} FixtureFrame;
static BOOL writeFixture(const char *path,int width,int height,int generation,BOOL software) {
IOSurfaceRef s=surface(width,height,generation);if(!s)return NO;
size_t stride=IOSurfaceGetBytesPerRow(s),bytes=stride*height;
int fd=open(path,O_CREAT|O_RDWR,0600);
BOOL ok=fd>=0 && ftruncate(fd,32+64u*1024u*1024u)==0;
static uint32_t sequence=0;sequence+=2;
FixtureFrame head={0x43414652u,sequence|1,width,height,(uint32_t)stride,
0x42475241u|(software?0x80000000u:0),bytes};
if(ok)ok=pwrite(fd,&head,sizeof(head),0)==sizeof(head) &&
pwrite(fd,IOSurfaceGetBaseAddress(s),bytes,sizeof(head))==(ssize_t)bytes;
head.sequence=sequence;
if(ok)ok=pwrite(fd,&head,sizeof(head),0)==sizeof(head);
if(fd>=0)close(fd);CFRelease(s);return ok;
}
static int checkPublisherHandoff(void) {
char owner[128],readback[128];
snprintf(owner,sizeof(owner),"/dev/shm/darling-ca-frame-%u-%d",getuid(),getpid());
snprintf(readback,sizeof(readback),"/dev/shm/darling-ca-frame-%u-%d",getuid(),getpid()+100000000);
NSWindow *w=[[NSWindow alloc] initWithContentRect:NSMakeRect(0,0,1280,720)
styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
[w setTitle:@"Darling standalone publisher handoff"];
[w makeKeyAndOrderFront:nil];
Display *d=XOpenDisplay(NULL);Window xid=[(id)[w platformWindow] windowHandle];
BOOL pass=d!=NULL;
int sizes[][2]={{1280,720},{1600,900},{1024,576},{1280,720}};
for(int n=0;pass && n<4;n++) {
int width=sizes[n][0],height=sizes[n][1];
[w setContentSize:NSMakeSize(width,height)];
if(n==0)pass=writeFixture(owner,width,height,n,YES);
else pass=writeFixture(owner,262,131,0,YES) &&
writeFixture(readback,width,height,n,NO);
BOOL ok=NO;unsigned long pixel=0;
NSDate *deadline=[NSDate dateWithTimeIntervalSinceNow:3.0];
while(pass && !ok && [deadline timeIntervalSinceNow]>0) {
pump(.05);XSync(d,False);
XImage *im=XGetImage(d,xid,0,0,width,height,AllPlanes,ZPixmap);
if(im){pixel=XGetPixel(im,width-8,height-8)&0xffffff;
ok=pixel==(((unsigned long)(40+n*40)<<16)|0xff);XDestroyImage(im);}
}
printf("PUBLISHER_HANDOFF size=%dx%d bottom_right=%06lx pass=%d\n",width,height,pixel,ok);
pass &=ok;
}
[w orderOut:nil];[w release];if(d)XCloseDisplay(d);
unlink(owner);unlink(readback);return pass?0:1;
}
int main(int argc, const char **argv) {
@autoreleasepool {
[NSApplication sharedApplication];
if(argc>1 && strcmp(argv[1],"--handoff")==0)return checkPublisherHandoff();
NSWindow *w=[[NSWindow alloc] initWithContentRect:NSMakeRect(0,0,1280,720) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
[w setTitle:@"Darling standalone resize pixels"];
NSView *view=[w contentView];[view setWantsLayer:YES];
[w makeKeyAndOrderFront:nil];pump(.15);
Display *d=XOpenDisplay(NULL);Window xid=[(id)[w platformWindow] windowHandle];
void (*publish)(IOSurfaceRef)=dlsym(RTLD_DEFAULT,"DarlingCAPublishIOSurfacePixels");
if(!d||!publish)return 2;
BOOL useGPU = argc > 1 && strcmp(argv[1], "--gpu") == 0;
IOSurfaceRef bootstrap=surface(1280,720,0);
[view.layer setContents:(id)bootstrap];publish(bootstrap);pump(.5);CFRelease(bootstrap);
CGLPixelFormatAttribute attrs[]={0};CGLPixelFormatObj format;GLint screens;CGLContextObj gpu;
GLuint texture=0;
if(useGPU) {
if(CGLChoosePixelFormat(attrs,&format,&screens)||CGLCreateContext(format,NULL,&gpu))return 4;
CGLSetCurrentContext(gpu);glGenTextures(1,&texture);
}
BOOL pass=YES;
int sizes[][2]={{1280,720},{1600,900},{1024,576},{1280,720}};
for(int n=0;n<4;n++) {
int width=sizes[n][0],height=sizes[n][1];
[w setContentSize:NSMakeSize(width,height)];
IOSurfaceRef s=surface(width,height,n);if(!s)return 3;
if(useGPU) {
CGLSetCurrentContext(gpu);glBindTexture(GL_TEXTURE_RECTANGLE,texture);
if(CGLTexImageIOSurface2D(gpu,GL_TEXTURE_RECTANGLE,GL_RGBA8,width,height,GL_BGRA,GL_UNSIGNED_INT_8_8_8_8_REV,s,0))return 5;
}
for(int f=0;f<8;f++) {
if(useGPU)CGLSetCurrentContext(gpu);
[view.layer setContents:(id)s];
if(!useGPU)publish(s);
[CATransaction flush];pump(.1);
}
BOOL ok=NO;
unsigned long pixel=0;
NSDate *deadline=[NSDate dateWithTimeIntervalSinceNow:2.5];
do {
XSync(d,False);
XImage *im=XGetImage(d,xid,0,0,width,height,AllPlanes,ZPixmap);
if(im) {
pixel=XGetPixel(im,width-8,height-8)&0xffffff;
ok=pixel==(((unsigned long)(40+n*40)<<16)|0xff);
XDestroyImage(im);
}
if(!ok)pump(.05);
} while(!ok && [deadline timeIntervalSinceNow]>0);
printf("RESIZE_PIXEL mode=%s size=%dx%d view=%.0fx%.0f bottom_right=%06lx pass=%d\n",
useGPU?"gpu":"software",width,height,view.frame.size.width,view.frame.size.height,pixel,ok);
pass &=ok;CFRelease(s);
}
if(useGPU){CGLSetCurrentContext(gpu);glDeleteTextures(1,&texture);CGLSetCurrentContext(NULL);CGLReleaseContext(gpu);CGLReleasePixelFormat(format);}
[w orderOut:nil];[w release];XCloseDisplay(d);
return pass?0:1;
}
}