Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Window animations still flicker at random #2129

Closed
koekeishiya opened this issue Feb 28, 2024 · 6 comments
Closed

Window animations still flicker at random #2129

koekeishiya opened this issue Feb 28, 2024 · 6 comments
Labels
bug Something isn't working

Comments

@koekeishiya
Copy link
Owner

I have a solution for this, but it breaks integration with JankyBorders FelixKratz/JankyBorders#62 (comment)

@koekeishiya koekeishiya added the bug Something isn't working label Feb 28, 2024
@koekeishiya koekeishiya added the addressed on master; not released Fixed upstream, but not yet released label Feb 28, 2024
@koekeishiya
Copy link
Owner Author

Added commit that eliminates flicker, but it also breaks JankyBorders inregration. Hopefully I can work out a solution together with Felix that makes both of these compatible in the end.

The flicker is very noticable and distracting, so I will prioritize this over the border integration if I can only have one.

koekeishiya added a commit that referenced this issue Feb 28, 2024
koekeishiya added a commit that referenced this issue Feb 28, 2024
@koekeishiya
Copy link
Owner Author

I put together some debug code; you can apply this patch to yabai when you want to investigate further.
I basically retrieve the WMDelegate instance and inspect it. It has three methods. The window animations and SLSOrderWindow all pass through performWindowManagementBridgeTransactionUsingBlock, which is why that is the swizzle target so far. When I swizzle this function and just return, it stops everything basically making it a NOOP. This is not really what we want though, as we want the fallback logic in some cases, but not all -- not just NOPing the bridged work.

diff --git a/src/yabai.c b/src/yabai.c
index 0afe9ed..83baab0 100644
--- a/src/yabai.c
+++ b/src/yabai.c
@@ -24,6 +24,7 @@
 #define MINOR  0
 #define PATCH 15
 
+static id (* SLSWMBridgeDelegate)(void);
 struct signal *g_signal_event[SIGNAL_TYPE_COUNT];
 struct process_manager g_process_manager;
 struct display_manager g_display_manager;
@@ -51,6 +52,50 @@ int g_connection;
 bool g_verbose;
 pid_t g_pid;
 
+static void dump_class_info(Class c)
+{
+    const char *name = class_getName(c);
+    NSLog(@"DUMP::%s\n", name);
+
+    unsigned int count = 0;
+
+    Ivar *ivar_list = class_copyIvarList(c, &count);
+    for (int i = 0; i < count; i++) {
+        Ivar ivar = ivar_list[i];
+        const char *ivar_name = ivar_getName(ivar);
+        NSLog(@"%s ivar: %s", name, ivar_name);
+    }
+    if (ivar_list) free(ivar_list);
+
+    objc_property_t *property_list = class_copyPropertyList(c, &count);
+    for (int i = 0; i < count; i++) {
+        objc_property_t property = property_list[i];
+        const char *prop_name = property_getName(property);
+        NSLog(@"%s property: %s", name, prop_name);
+    }
+    if (property_list) free(property_list);
+
+    Method *method_list = class_copyMethodList(c, &count);
+    for (int i = 0; i < count; i++) {
+        Method method = method_list[i];
+        const char *method_name = sel_getName(method_getName(method));
+        NSLog(@"%s method: %s", name, method_name);
+    }
+    if (method_list) free(method_list);
+}
+
+static inline id get_ivar_value(id instance, const char *name)
+{
+    id result = nil;
+    object_getInstanceVariable(instance, name, (void **) &result);
+    return result;
+}
+
+static inline void set_ivar_value(id instance, const char *name, id value)
+{
+    object_setInstanceVariable(instance, name, value);
+}
+
 static int client_send_message(int argc, char **argv)
 {
     if (argc <= 1) {
@@ -167,6 +212,84 @@ static void exec_config_file(void)
     }
 }
 
+struct BlockDescriptor {
+    unsigned long reserved;
+    unsigned long size;
+    void *rest[1];
+};
+
+struct Block {
+    void *isa;
+    int flags;
+    int reserved;
+    void *invoke;
+    struct BlockDescriptor *descriptor;
+};
+
+static const char *BlockSig(id blockObj)
+{
+    struct Block *block = (void *)blockObj;
+    struct BlockDescriptor *descriptor = block->descriptor;
+
+    int copyDisposeFlag = 1 << 25;
+    int signatureFlag = 1 << 30;
+
+    assert(block->flags & signatureFlag);
+
+    int index = 0;
+    if(block->flags & copyDisposeFlag)
+        index += 2;
+
+    return descriptor->rest[index];
+}
+
+static void *BlockHandler(id blockObj)
+{
+    struct Block *block = (void *)blockObj;
+    return block->invoke;
+}
+
+@implementation NSObject(swizzle)
+- (void)fake_performAsynchronousBridgedWindowManagementOperation:(id)instance
+{
+    printf("%s\n", __FUNCTION__);
+    return;
+}
+- (void)fake_performSynchronousBridgedWindowManagementOperation:(id)instance
+{
+    printf("%s\n", __FUNCTION__);
+    return;
+}
+- (void)fake_performWindowManagementBridgeTransactionUsingBlock:(id)arg1
+{
+    uint64_t address = (uint64_t)arg1;
+    printf("\n");
+    printf("FUNC: %s\n", __FUNCTION__);
+    printf("ARG1: %p\n", arg1);
+    printf("ARG1 class: %s\n", [NSStringFromClass([arg1 class]) UTF8String]);
+    printf("ARG1 description: %s\n", [[arg1 description] UTF8String]);
+    printf("ARG1 signature: %s\n", BlockSig(arg1));
+    printf("ARG1 handler: %p\n", BlockHandler(arg1));
+    printf("\n");
+
+    void *addr[40];
+    int frame_count = backtrace(addr, sizeof(addr)/sizeof(*addr));
+    if (frame_count > 1) {
+        char **syms = backtrace_symbols(addr, frame_count);
+        for (int f = 0; f < frame_count; ++f) {
+            printf("%s\n", syms[f]);
+        }
+        printf("\n");
+        free(syms);
+    } else {
+        printf("*** Failed to generate backtrace.");
+    }
+
+    [self fake_performWindowManagementBridgeTransactionUsingBlock:arg1];
+    return;
+}
+@end
+
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
 static inline bool configure_settings_and_acquire_lock(void)
@@ -180,6 +303,12 @@ static inline bool configure_settings_and_acquire_lock(void)
     snprintf(g_socket_file, sizeof(g_socket_file), SOCKET_PATH_FMT, user);
     snprintf(g_lock_file, sizeof(g_lock_file), LCFILE_PATH_FMT, user);
 
+    CGSGetConnectionPortById             = macho_find_symbol("/System/Library/PrivateFrameworks/SkyLight.framework/Versions/A/SkyLight", "_CGSGetConnectionPortById");
+    SLSWMBridgeDelegate                  = macho_find_symbol("/System/Library/PrivateFrameworks/SkyLight.framework/Versions/A/SkyLight", "__ZL19SLSWMBridgeDelegatev");
+    SLSWindowManagementBridgeSetDelegate = macho_find_symbol("/System/Library/PrivateFrameworks/SkyLight.framework/Versions/A/SkyLight", "_SLSWindowManagementBridgeSetDelegate");
+    // if (SLSWindowManagementBridgeSetDelegate) SLSWindowManagementBridgeSetDelegate(NULL);
+    id delegate = SLSWMBridgeDelegate ? SLSWMBridgeDelegate() : NULL;
+
     NSApplicationLoad();
     g_pid = getpid();
     g_event_bytes = malloc(0xf8);
@@ -189,10 +318,6 @@ static inline bool configure_settings_and_acquire_lock(void)
     g_layer_below_window_level  = CGWindowLevelForKey(LAYER_BELOW);
     g_layer_above_window_level  = CGWindowLevelForKey(LAYER_ABOVE);
 
-    CGSGetConnectionPortById             = macho_find_symbol("/System/Library/PrivateFrameworks/SkyLight.framework/Versions/A/SkyLight", "_CGSGetConnectionPortById");
-    SLSWindowManagementBridgeSetDelegate = macho_find_symbol("/System/Library/PrivateFrameworks/SkyLight.framework/Versions/A/SkyLight", "_SLSWindowManagementBridgeSetDelegate");
-    if (SLSWindowManagementBridgeSetDelegate) SLSWindowManagementBridgeSetDelegate(NULL);
-
     signal(SIGCHLD, SIG_IGN);
     signal(SIGPIPE, SIG_IGN);
     CGSetLocalEventsSuppressionInterval(0.0f);
@@ -200,6 +325,60 @@ static inline bool configure_settings_and_acquire_lock(void)
     mouse_state_init(&g_mouse_state);
     task_get_special_port(mach_task_self(), TASK_BOOTSTRAP_PORT, &g_bs_port);
 
+    if (delegate) {
+        dump_class_info([delegate class]);
+
+        id manager = get_ivar_value(delegate, "_manager");
+        dump_class_info([manager class]);
+
+        // set_ivar_value(delegate, "_manager", NULL);
+        // set_ivar_value(manager, "_delegate", NULL);
+        // [manager setDelegate: NULL];
+
+        Class class = [delegate class];
+
+        {
+            SEL originalSelector = @selector(performWindowManagementBridgeTransactionUsingBlock:);
+            SEL swizzledSelector = @selector(fake_performWindowManagementBridgeTransactionUsingBlock:);
+
+            Method originalMethod = class_getInstanceMethod(class, originalSelector);
+            Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
+
+            IMP originalImp = method_getImplementation(originalMethod);
+            IMP swizzledImp = method_getImplementation(swizzledMethod);
+
+            class_replaceMethod(class, swizzledSelector, originalImp, method_getTypeEncoding(originalMethod));
+            class_replaceMethod(class, originalSelector, swizzledImp, method_getTypeEncoding(swizzledMethod));
+        }
+        {
+            SEL originalSelector = @selector(performAsynchronousBridgedWindowManagementOperation:);
+            SEL swizzledSelector = @selector(fake_performAsynchronousBridgedWindowManagementOperation:);
+
+            Method originalMethod = class_getInstanceMethod(class, originalSelector);
+            Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
+
+            IMP originalImp = method_getImplementation(originalMethod);
+            IMP swizzledImp = method_getImplementation(swizzledMethod);
+
+            class_replaceMethod(class, swizzledSelector, originalImp, method_getTypeEncoding(originalMethod));
+            class_replaceMethod(class, originalSelector, swizzledImp, method_getTypeEncoding(swizzledMethod));
+        }
+        {
+            SEL originalSelector = @selector(performSynchronousBridgedWindowManagementOperation:);
+            SEL swizzledSelector = @selector(fake_performSynchronousBridgedWindowManagementOperation:);
+
+            Method originalMethod = class_getInstanceMethod(class, originalSelector);
+            Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
+
+            IMP originalImp = method_getImplementation(originalMethod);
+            IMP swizzledImp = method_getImplementation(swizzledMethod);
+
+            class_replaceMethod(class, swizzledSelector, originalImp, method_getTypeEncoding(originalMethod));
+            class_replaceMethod(class, originalSelector, swizzledImp, method_getTypeEncoding(swizzledMethod));
+        }
+    }
+
+
 #if 0
     hook_nsobject_autorelease();
     hook_autoreleasepool_drain();

@koekeishiya
Copy link
Owner Author

So there are actually multiple things going on. When the program launches. Getting the WMBridge instance and dumping it results in :

2024-03-01 13:22:01.215 yabai[93295:664422] DUMP::SLSWindowManagementFallbackBridge
2024-03-01 13:22:01.215 yabai[93295:664422] SLSWindowManagementFallbackBridge ivar: _manager
2024-03-01 13:22:01.215 yabai[93295:664422] SLSWindowManagementFallbackBridge property: hash
2024-03-01 13:22:01.215 yabai[93295:664422] SLSWindowManagementFallbackBridge property: superclass
2024-03-01 13:22:01.215 yabai[93295:664422] SLSWindowManagementFallbackBridge property: description
2024-03-01 13:22:01.215 yabai[93295:664422] SLSWindowManagementFallbackBridge property: debugDescription
2024-03-01 13:22:01.215 yabai[93295:664422] SLSWindowManagementFallbackBridge method: init
2024-03-01 13:22:01.215 yabai[93295:664422] SLSWindowManagementFallbackBridge method: .cxx_destruct
2024-03-01 13:22:01.215 yabai[93295:664422] SLSWindowManagementFallbackBridge method: performAsynchronousBridgedWindowManagementOperation:
2024-03-01 13:22:01.215 yabai[93295:664422] SLSWindowManagementFallbackBridge method: performSynchronousBridgedWindowManagementOperation:
2024-03-01 13:22:01.215 yabai[93295:664422] SLSWindowManagementFallbackBridge method: performWindowManagementBridgeTransactionUsingBlock:
2024-03-01 13:22:01.215 yabai[93295:664422] DUMP::WMClientWindowManager
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager ivar: _activeWindows
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager ivar: _cachedWindowIdentifierToWindowSnapshot
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager ivar: _xpcConnection
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager ivar: _windowsToMinimizePostTransactionHandling
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager ivar: _serverLaunchNotificationToken
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager ivar: _delegate
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager property: delegate
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager property: hash
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager property: superclass
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager property: description
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager property: debugDescription
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager method: init
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager method: .cxx_destruct
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager method: delegate
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager method: invalidate
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager method: setDelegate:
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager method: _xpcConnection
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager method: notifyClickDidEndOnDesktopBackgroundWindow:
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager method: performAsynchronousBridgedWindowManagementOperation:
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager method: performSynchronousBridgedWindowManagementOperation:
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager method: performWindowTransaction:
2024-03-01 13:22:01.215 yabai[93295:664422] WMClientWindowManager method: proposeKeyWindowWithInfo:
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: proposeMainWindowWithInfo:
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: stages
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: _reconnectIfNecessary
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: _reconnect
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: _createXPCConnection
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: updateStages:displayChangeSeed:
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: _applyLegacyXPCWindowProperties:toSceneSettings:
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: _convertLegacyXPCActionToScenes:
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: _createWindowPropertySnapshotForWindow:properties:
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: _handleInterruptionFromConnection:
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: _handleInvalidationFromConnection:
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: _performXPCTransaction:
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: _registerForLaunchNotification
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: applyAgentPropertySnapshots:
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: hideApplicationResponse:
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: makeKeyWindowWithWindowIdentifier:
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: proposeKeyAndMainApplicationResponse:mainWindow:
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: resignKeyWindowWithWindowIdentifier:
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: stageFrames
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: unhideApplicationResponse:
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: windowDeminiaturizationResponse:
2024-03-01 13:22:01.216 yabai[93295:664422] WMClientWindowManager method: windowMiniaturizationResponse:

After calling NSApplicationLoad, getting the WMBridge instance and dumping it results in:

2024-03-01 13:23:53.143 yabai[93467:665277] DUMP::NSWMWindowCoordinator
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator ivar: _transaction
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator ivar: _windowManager
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator property: hash
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator property: superclass
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator property: description
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator property: debugDescription
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: init
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: .cxx_destruct
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: applicationDidCancelTermination
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: applicationDidFinishRestoration
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: applicationWillBeginTermination
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: _finishLoginTransition
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: clientWindowManager:hideApplicationResponse:
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: clientWindowManager:requestMakeKeyWindowWithIdentifier:
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: clientWindowManager:requestResignKeyWindowWithIdentifier:
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: clientWindowManager:unhideApplicationResponse:
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: clientWindowManager:updateStages:
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: clientWindowManager:updateStages:displayChangeSeed:
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: clientWindowManager:windowDeminiaturizationResponse:
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: clientWindowManager:windowMiniaturizationResponse:
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: finishLoginTransitionWithCompletionHandler:
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: handleDesktopBackgroundClickEnd:
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: initializeStageFramesIfNeeded
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: performAsynchronousBridgedWindowManagementOperation:
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: performCycleWindowsReversed:
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: performSynchronousBridgedWindowManagementOperation:
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: performTransactionUsingBlock:
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: performWindowManagementBridgeTransactionUsingBlock:
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: proposeKeyWindow:previousWindow:
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: proposeMainWindow:previousWindow:
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: setWindowTags:onWindow:clear:
2024-03-01 13:23:53.143 yabai[93467:665277] NSWMWindowCoordinator method: startLoginTransition
2024-03-01 13:23:53.143 yabai[93467:665277] DUMP::nil

Calling SLSWindowManagementBridgeSetDelegate(NULL); and then getting the WMBridge again, results in the exact same bridge as before NSApplicationLoad was called. So it probably resets the delegate back to the fallback version, but additionally sets some flag to indicate that the bridge is not to be used.

This flag is then checked internally by the windowserver before it attempts to perform some operation, deciding whether it should use a bridged operation or the "old" way.

@koekeishiya
Copy link
Owner Author

I noticed that there is code inside SLSNewWindow that actually checks whether the specific window to be created should use the WMBridge or not. By default, SLSNewWindow will enable it, but I can actually opt out for specific windows using extern CGError SLSNewWindowWithOpaqueShapeAndContext(int cid, int type, CFTypeRef region, CFTypeRef opaque_shape, int options, uint64_t *tags, float x, float y, int tag_size, uint32_t *wid, void *context); and by making sure that the 18th bit is set in the options argument.

# these are basically equivalent; SLSNewWindow passes the integer value 13 as options instead.
SLSNewWindow(animation_connection, 2, 0, 0, frame_region, &proxy->id);

# same as above; but we also set the 18th bit.
SLSNewWindowWithOpaqueShapeAndContext(animation_connection, 2, frame_region, empty_region, 13|(1 << 18), &tags, 0, 0, 64, &proxy->id, NULL);

This can be used instead of disabling the entire WMBridge, however, the window still won't respond to order-operations from JankyBorders.

Edit: There is also a different code path inside SLSNewWindowWithOpaqueShapeAndContext where it checks some bool result of some CFPreferencesCopyValue, operation, skipping the WMBridge setup in a different way than the 18th bit version I mentioned above. Have not looked further into which kind of preference property this is.

koekeishiya added a commit that referenced this issue Mar 2, 2024
@koekeishiya
Copy link
Owner Author

Fixed in v7.0.0.

@koekeishiya koekeishiya removed the addressed on master; not released Fixed upstream, but not yet released label Mar 13, 2024
@jdknox
Copy link

jdknox commented Apr 22, 2024

I noticed that there is code inside SLSNewWindow that actually checks whether the specific window to be created should use the WMBridge or not.
...
Edit: There is also a different code path inside SLSNewWindowWithOpaqueShapeAndContext where it checks some bool result
...

Where do you find the code for those functions? I'm guessing you're looking at the disassembly, but I wonder how you knew where to look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants