Skip to content

Commit

Permalink
improve proxy begin latency
Browse files Browse the repository at this point in the history
..

..
  • Loading branch information
FelixKratz committed Mar 11, 2024
1 parent bdccecf commit 5fef2e5
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 50 deletions.
2 changes: 1 addition & 1 deletion makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FILES = src/main.c src/parse.c src/mach.c src/hashtable.c src/events.c src/windows.c src/border.c
FILES = src/main.c src/parse.c src/mach.c src/hashtable.c src/events.c src/windows.c src/border.c src/animation.c
LIBS = -framework AppKit -framework CoreVideo -F/System/Library/PrivateFrameworks/ -framework SkyLight

all: | bin
Expand Down
29 changes: 29 additions & 0 deletions src/animation.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include "animation.h"

void animation_init(struct animation* animation) {
memset(animation, 0, sizeof(struct animation));
}

void animation_start(struct animation* animation, void* proc, void* context) {
assert(animation->link == NULL);
assert(animation->context == NULL);
CVDisplayLinkCreateWithActiveCGDisplays(&animation->link);
CVTime refresh_period
= CVDisplayLinkGetNominalOutputVideoRefreshPeriod(animation->link);
animation->frame_time = 1e6 * (double)refresh_period.timeValue
/ (double)refresh_period.timeScale;

animation->context = context;
CVDisplayLinkSetOutputCallback(animation->link, proc, animation);
CVDisplayLinkStart(animation->link);
}

void animation_stop(struct animation* animation) {
if (animation->link) {
CVDisplayLinkStop(animation->link);
CVDisplayLinkRelease(animation->link);
animation->link = NULL;
}
if (animation->context) free(animation->context);
animation->context = NULL;
}
13 changes: 13 additions & 0 deletions src/animation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once
#include <CoreVideo/CoreVideo.h>
#include <pthread.h>

struct animation {
void* context;
double frame_time;
CVDisplayLinkRef link;
};

void animation_init(struct animation* animation);
void animation_start(struct animation* animation, void* proc, void* context);
void animation_stop(struct animation* animation);
18 changes: 14 additions & 4 deletions src/border.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ void border_init(struct border* border) {
pthread_mutexattr_init(&mattr);
pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&border->mutex, &mattr);
animation_init(&border->animation);
border->cid = SLSMainConnectionID();
}

Expand Down Expand Up @@ -245,10 +246,18 @@ void border_update_internal(struct border* border, struct settings* settings) {
transaction = SLSTransactionCreate(cid);
if(!transaction) return;
}
CGAffineTransform transform = CGAffineTransformIdentity;
transform.tx = -border->origin.x;
transform.ty = -border->origin.y;
SLSTransactionSetWindowTransform(transaction, border->wid, 0, 0, transform);

if (!border->is_proxy) {
CGAffineTransform transform = CGAffineTransformIdentity;
transform.tx = -border->origin.x;
transform.ty = -border->origin.y;
SLSTransactionSetWindowTransform(transaction,
border->wid,
0,
0,
transform );
}

SLSTransactionSetWindowLevel(transaction, border->wid, level);
SLSTransactionSetWindowSubLevel(transaction, border->wid, sub_level);
SLSTransactionOrderWindow(transaction,
Expand Down Expand Up @@ -304,6 +313,7 @@ void border_destroy(struct border* border) {
pthread_mutex_lock(&border->mutex);
border_destroy_window(border);
if (border->proxy) border_destroy(border->proxy);
animation_stop(&border->animation);
pthread_mutex_unlock(&border->mutex);
free(border);
}
Expand Down
3 changes: 3 additions & 0 deletions src/border.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "misc/helpers.h"
#include "misc/window.h"
#include "misc/drawing.h"
#include "animation.h"
#include "hashtable.h"

#define BORDER_ORDER_ABOVE 1
Expand Down Expand Up @@ -64,6 +65,8 @@ struct border {
CGRect drawing_bounds;
CGContextRef context;

struct animation animation;

bool disable_coalescing;
volatile bool is_coalescing;
int64_t last_coalesce_attempt;
Expand Down
77 changes: 32 additions & 45 deletions src/misc/yabai.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ struct track_transform_payload {
uint32_t border_wid;
uint32_t proxy_wid;
uint32_t target_wid;
uint64_t frame_delay;
CGAffineTransform initial_transform;
};

Expand All @@ -26,57 +25,36 @@ struct yabai_proxy_payload {
uint32_t external_proxy_wid;
};

static CVReturn frame_callback(CVDisplayLinkRef display_link, const CVTimeStamp* now, const CVTimeStamp* output_time, CVOptionFlags flags, CVOptionFlags* flags_out, void* context) {
struct track_transform_payload* payload = context;
CGAffineTransform target_transform, border_transform;
static CVReturn track_transform(CVDisplayLinkRef display_link, const CVTimeStamp* now, const CVTimeStamp* output_time, CVOptionFlags flags, CVOptionFlags* flags_out, void* context) {
struct animation* animation = context;
usleep(0.25*animation->frame_time);

usleep(payload->frame_delay);
struct track_transform_payload* payload = animation->context;
CGAffineTransform target_transform, border_transform;
CGError error = SLSGetWindowTransform(payload->cid,
payload->target_wid,
&target_transform );

if (error != kCGErrorSuccess) {
CVDisplayLinkStop(display_link);
CVDisplayLinkRelease(display_link);
free(payload);
return kCVReturnSuccess;
}
if (error != kCGErrorSuccess) return kCVReturnSuccess;

border_transform = CGAffineTransformConcat(target_transform,
payload->initial_transform);

SLSSetWindowTransform(payload->cid, payload->proxy_wid, border_transform);
CFTypeRef transaction = SLSTransactionCreate(payload->cid);
if (transaction) {
SLSTransactionSetWindowTransform(transaction, payload->proxy_wid, 0, 0, border_transform);
SLSTransactionSetWindowTransform(transaction, payload->border_wid, 0, 0, border_transform);
SLSTransactionCommit(transaction, 1);
CFRelease(transaction);
}
return kCVReturnSuccess;
}

static inline void border_track_transform(struct track_transform_payload* payload) {
CVDisplayLinkRef link;
CVDisplayLinkCreateWithActiveCGDisplays(&link);
CVTime refresh_period = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
payload->frame_delay = 0.25e6 * (double)refresh_period.timeValue
/ (double)refresh_period.timeScale;

CVDisplayLinkSetOutputCallback(link, frame_callback, payload);
CVDisplayLinkStart(link);
}

static void* yabai_proxy_begin_proc(void* context) {
struct yabai_proxy_payload* info = context;
struct border* proxy = info->proxy;
pthread_mutex_lock(&proxy->mutex);

if (!proxy->is_proxy) {
proxy->is_proxy = true;
border_update_internal(proxy, &info->settings);

CFTypeRef transaction = SLSTransactionCreate(proxy->cid);
if (transaction) {
SLSTransactionSetWindowAlpha(transaction, info->border_wid, 0.f);
SLSTransactionSetWindowAlpha(transaction, proxy->wid, 1.f);
SLSTransactionCommit(transaction, 1);
CFRelease(transaction);
}
}
struct track_transform_payload* payload
= malloc(sizeof(struct track_transform_payload));

Expand All @@ -98,8 +76,23 @@ static void* yabai_proxy_begin_proc(void* context) {
payload->initial_transform.ty = 0.5*(proxy->frame.size.height
- proxy->target_bounds.size.height);

animation_stop(&proxy->animation);
animation_start(&proxy->animation, track_transform, payload);

if (!proxy->is_proxy) {
proxy->is_proxy = true;
proxy->frame = CGRectNull;
border_update_internal(proxy, &info->settings);

CFTypeRef transaction = SLSTransactionCreate(proxy->cid);
if (transaction) {
SLSTransactionSetWindowAlpha(transaction, info->border_wid, 0.f);
SLSTransactionSetWindowAlpha(transaction, proxy->wid, 1.f);
SLSTransactionCommit(transaction, 1);
CFRelease(transaction);
}
}
pthread_mutex_unlock(&proxy->mutex);
border_track_transform(payload);
free(context);
return NULL;
}
Expand All @@ -118,7 +111,7 @@ static void* yabai_proxy_end_proc(void* context) {
}

static inline void yabai_proxy_begin(struct table* windows, uint32_t wid, uint32_t real_wid) {
if (!real_wid) return;
if (!real_wid || !wid) return;
struct border* border = table_find(windows, &real_wid);

if (border) {
Expand All @@ -129,6 +122,7 @@ static inline void yabai_proxy_begin(struct table* windows, uint32_t wid, uint32
border_init(border->proxy);
border_create_window(border->proxy, CGRectNull, true, false);
border->proxy->target_bounds = border->target_bounds;
border->proxy->frame = border->frame;
border->proxy->focused = border->focused;
border->proxy->target_wid = border->target_wid;
border->proxy->sid = border->sid;
Expand All @@ -150,22 +144,15 @@ static inline void yabai_proxy_begin(struct table* windows, uint32_t wid, uint32
}

static inline void yabai_proxy_end(struct table* windows, uint32_t wid, uint32_t real_wid) {
if (!real_wid || !wid) return;
struct border* border = (struct border*)table_find(windows, &real_wid);
if (border) pthread_mutex_lock(&border->mutex);
if (border && border->proxy && border->external_proxy_wid == wid) {
struct border* proxy = border->proxy;
border->proxy = NULL;

CGAffineTransform transform;
SLSGetWindowTransform(border->cid, proxy->wid, &transform);
CFTypeRef transaction = SLSTransactionCreate(border->cid);
if (transaction) {
SLSTransactionSetWindowTransform(transaction,
border->wid,
0,
0,
transform );

SLSTransactionSetWindowAlpha(transaction, proxy->wid, 0.f);
SLSTransactionSetWindowAlpha(transaction, border->wid, 1.f);
SLSTransactionCommit(transaction, 1);
Expand Down

0 comments on commit 5fef2e5

Please sign in to comment.