mirror of
https://github.com/lucannez64/darling-lol.git
synced 2026-10-26 19:47:42 +00:00
165 lines
8.1 KiB
Python
165 lines
8.1 KiB
Python
"""Compile the patched VRR eligibility and drawable ownership methods with inert fixtures."""
|
|
from pathlib import Path
|
|
import shutil
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
import test_runtime_compatibility as sources
|
|
|
|
|
|
def body(source, signature):
|
|
return source.split(signature + ' {', 1)[1].split('\n}', 1)[0]
|
|
|
|
|
|
@unittest.skipUnless(shutil.which('c++'), 'C++ compiler required')
|
|
class VrrChecks(unittest.TestCase):
|
|
patched = sources.CompatibilityChecks.patched
|
|
|
|
def run_cpp(self, source):
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
path = Path(directory)
|
|
(path/'check.cpp').write_text('#include <cstddef>\n' + source)
|
|
result = subprocess.run(['c++', '-std=c++17', str(path/'check.cpp'), '-o', str(path/'check')], capture_output=True, text=True)
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
subprocess.run([str(path/'check')], check=True, timeout=10)
|
|
|
|
def test_hints_only_allow_vrr_for_fullscreen_parent_presentation(self):
|
|
source = self.patched('cocotron', 'AppKit/X11.backend/X11Window.m')
|
|
method = body(source, '- (void) updateLayerPresentationHints: (BOOL) fullscreen')
|
|
getter = body(source, '- (void *) layerDrawableFor: (id) owner')
|
|
acquire = body(source, '- (void) acquireLayerDrawable: (id) owner').replace('[self updateLayerPresentationHints: _fullscreenRequested]', 'hints(_fullscreenRequested)')
|
|
release = body(source, '- (void) releaseLayerDrawable: (id) owner').replace('[self updateLayerPresentationHints: _fullscreenRequested]', 'hints(_fullscreenRequested)')
|
|
self.run_cpp(r'''
|
|
#include <cassert>
|
|
#include <cstring>
|
|
using BOOL=bool;
|
|
constexpr auto nil=nullptr;
|
|
constexpr int False=0, XA_CARDINAL=6, PropModeReplace=0;
|
|
static bool game=true;
|
|
static int adaptive=-1,bypass=-1,calls=0;
|
|
static bool X11IsLeagueGameWindow(int,int,int) { return game; }
|
|
static const char* XInternAtom(int,const char* name,int) { return name; }
|
|
static int XChangeProperty(int,int,const char* name,int type,int bits,int mode,unsigned char* data,int count) {
|
|
assert(type==XA_CARDINAL && bits==32 && mode==PropModeReplace && count==1);
|
|
int value=*(unsigned long*)data; ++calls;
|
|
if(!strcmp(name,"_VARIABLE_REFRESH")) adaptive=value;
|
|
else { assert(!strcmp(name,"_NET_WM_BYPASS_COMPOSITOR")); bypass=value; }
|
|
return 0;
|
|
}
|
|
struct Window {
|
|
int _display=1,_window=1,_delegate=1;
|
|
void* _layerDrawableOwner=nullptr;
|
|
void* _cglWindow=(void*)3; bool _hasAlpha=false,_fullscreenRequested=true;
|
|
void hints(BOOL fullscreen) {
|
|
''' + method + '\n }\n void* drawable(void* owner) {' + getter + '\n}\n void acquire(void* owner) {' + acquire + '\n}\n void release(void* owner) {' + release + r'''
|
|
}
|
|
};
|
|
int main() {
|
|
Window w;
|
|
w.hints(true); assert(adaptive==0 && bypass==2);
|
|
w._layerDrawableOwner=&w;
|
|
w.hints(true); assert(adaptive==1 && bypass==0);
|
|
w.hints(false); assert(adaptive==0 && bypass==0);
|
|
w._layerDrawableOwner=nullptr;
|
|
w.hints(true); assert(adaptive==0 && bypass==2);
|
|
int before=calls; game=false; w.hints(true); assert(calls==before);
|
|
assert(!w.drawable(&w)); game=true;
|
|
int a,b;
|
|
assert(w.drawable(&a)==(void*)3);
|
|
w.acquire(&a); assert(w.drawable(&a)==(void*)3 && !w.drawable(&b));
|
|
w.acquire(&b); assert(w._layerDrawableOwner==&a);
|
|
w.release(&b); assert(w._layerDrawableOwner==&a);
|
|
w.release(&a); assert(!w._layerDrawableOwner && w.drawable(&b)==(void*)3);
|
|
w._hasAlpha=true; assert(!w.drawable(&a));
|
|
}
|
|
''')
|
|
|
|
def test_subwindows_borrow_only_when_visible_borderless_and_covering_parent(self):
|
|
source = self.patched('cocotron', 'AppKit/X11.backend/X11SubWindow.m')
|
|
method = body(source, '- (void *) sharedCGLWindow')
|
|
replacements = {'[_parent frame]':'_parent->frame', '[_parent styleMask]':'_parent->style',
|
|
'[_parent layerDrawableFor: self]':'_parent->drawable(this)',
|
|
'[_parent acquireLayerDrawable: self]':'_parent->acquire(this)',
|
|
'[_parent releaseLayerDrawable: self]':'_parent->release(this)'}
|
|
for old,new in replacements.items():
|
|
method=method.replace(old,new)
|
|
self.run_cpp(r'''
|
|
#include <cassert>
|
|
using BOOL=bool;
|
|
struct CGRect { struct {double x,y;} origin; struct {double width,height;} size; };
|
|
static CGRect CGRectMake(double x,double y,double w,double h) {return {{x,y},{w,h}};}
|
|
static bool CGRectEqualToRect(CGRect a,CGRect b) {return a.origin.x==b.origin.x && a.origin.y==b.origin.y && a.size.width==b.size.width && a.size.height==b.size.height;}
|
|
constexpr int NSTitledWindowMask=1;
|
|
static bool mapped;
|
|
static void XMapWindow(int,int) {mapped=true;}
|
|
static void XUnmapWindow(int,int) {mapped=false;}
|
|
struct Parent {
|
|
CGRect frame=CGRectMake(0,0,800,600); int style=0; bool eligible=true;
|
|
void* owner=nullptr; void* surface=this;
|
|
void* drawable(void* requester) {return eligible && (!owner || owner==requester) ? surface : nullptr;}
|
|
void acquire(void* requester) {assert(!owner); owner=requester;}
|
|
void release(void* requester) {assert(owner==requester); owner=nullptr;}
|
|
};
|
|
struct Child {
|
|
Parent* _parent; CGRect _drawableFrame=CGRectMake(0,0,800,600);
|
|
BOOL _visible=true,_usingParentDrawable=false,_allowsParentDrawable=true; int _display=1,_window=2;
|
|
void* shared() {
|
|
''' + method + r'''
|
|
}
|
|
};
|
|
int main() {
|
|
Parent p; Child a{&p}; Child b{&p};
|
|
assert(a.shared()==p.surface && !mapped && p.owner==&a);
|
|
assert(a.shared()==p.surface); // Repeated lookup does not reacquire.
|
|
assert(b.shared()==nullptr && mapped); // A second view cannot share ownership.
|
|
a._visible=false; assert(!a.shared() && !mapped && !p.owner);
|
|
a._visible=true; assert(a.shared()==p.surface);
|
|
a._drawableFrame.size.width=400;
|
|
assert(!a.shared() && mapped && !p.owner);
|
|
a._drawableFrame=CGRectMake(0,0,800,600); p.style=NSTitledWindowMask;
|
|
assert(!a.shared() && mapped);
|
|
p.style=0; p.eligible=false; assert(!a.shared() && mapped);
|
|
p.eligible=true; a._allowsParentDrawable=false; assert(!a.shared() && mapped);
|
|
a._allowsParentDrawable=true; a._drawableFrame.origin.x=1; assert(!a.shared() && mapped);
|
|
a._drawableFrame.origin.x=0; assert(a.shared()==p.surface && !mapped);
|
|
}
|
|
''')
|
|
|
|
def test_switching_surfaces_destroys_only_owned_child_drawables(self):
|
|
source = self.patched('cocotron', 'QuartzCore/CALayerContext.m')
|
|
method = body(source, '- (void) updateDrawable')
|
|
method=method.replace('[_subwindow setAllowsParentDrawable: hasMetalLayer(_layer)]', '_subwindow->allow(hasMetalLayer(_layer))')
|
|
method=method.replace('[_subwindow sharedCGLWindow]', '_subwindow->shared').replace('[_subwindow nativeWindow]', '_subwindow->native')
|
|
self.run_cpp(r'''
|
|
#include <cassert>
|
|
using BOOL=bool;
|
|
using CGLContextObj=int;
|
|
static int current=0,destroyed=0,created=0;
|
|
static void* destroyedSurface;
|
|
static int CGLGetCurrentContext() {return current;}
|
|
static void CGLSetCurrentContext(int c) {current=c;}
|
|
static void CGLDestroyWindow(void* surface) {assert(surface==(void*)10); destroyedSurface=surface; ++destroyed;}
|
|
static void* CGLGetWindow(void*) {++created; return (void*)10;}
|
|
static void CGLContextMakeCurrentAndAttachToWindow(int c,void*) {current=c;}
|
|
static bool hasMetalLayer(int layer) {return layer!=0;}
|
|
struct Subwindow {void* shared=nullptr; void* native=(void*)2; void allow(bool enabled) {assert(enabled);} };
|
|
struct Context {
|
|
Subwindow* _subwindow; int _layer=1; int _glContext=1; void* _cglWindow=nullptr; bool _ownsCglWindow=false;
|
|
void update() {
|
|
''' + method.replace('CGLSetCurrentContext(NULL)', 'CGLSetCurrentContext(0)') + r'''
|
|
}
|
|
};
|
|
int main() {
|
|
Subwindow sub; Context c{&sub};
|
|
c.update(); assert(created==1 && c._ownsCglWindow); // Ordinary clients still get a child.
|
|
c.update(); assert(created==1 && destroyed==0);
|
|
current=1; sub.shared=(void*)20;
|
|
c.update(); assert(destroyed==1 && destroyedSurface==(void*)10 && !c._ownsCglWindow && current==1);
|
|
c.update(); assert(destroyed==1);
|
|
sub.shared=(void*)30; c.update(); assert(destroyed==1 && c._cglWindow==(void*)30);
|
|
sub.shared=nullptr; c.update(); assert(created==2 && destroyed==1 && c._ownsCglWindow);
|
|
current=2; sub.shared=(void*)20; c.update(); assert(current==2 && destroyed==2);
|
|
c._subwindow=nullptr; c.update(); assert(destroyed==2);
|
|
}
|
|
''')
|