chore(vendor): import pi 1.3.0
Imported as a linear vendor commit so forge rebases do not replay the upstream root tree. git-subtree-dir: third_party/pi git-subtree-split: 71023aec1546d6d677a65669c5665c0927ce0dd0
This commit is contained in:
@@ -1,70 +0,0 @@
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#define NAPI_AUTO_LENGTH ((size_t)-1)
|
||||
|
||||
typedef void* napi_env;
|
||||
typedef void* napi_value;
|
||||
typedef void* napi_callback_info;
|
||||
typedef napi_value (*napi_callback)(napi_env, napi_callback_info);
|
||||
typedef int (*napi_create_function_fn)(napi_env, const char*, size_t, napi_callback, void*, napi_value*);
|
||||
typedef int (*napi_set_named_property_fn)(napi_env, napi_value, const char*, napi_value);
|
||||
typedef int (*napi_get_boolean_fn)(napi_env, bool, napi_value*);
|
||||
typedef int (*napi_get_cb_info_fn)(napi_env, napi_callback_info, size_t*, napi_value*, napi_value*, void**);
|
||||
typedef int (*napi_get_value_string_utf8_fn)(napi_env, napi_value, char*, size_t, size_t*);
|
||||
|
||||
static void* node_symbol(const char* name) {
|
||||
return dlsym(RTLD_DEFAULT, name);
|
||||
}
|
||||
|
||||
static CGEventFlags modifier_mask_for_name(const char* name) {
|
||||
if (strcmp(name, "shift") == 0) return kCGEventFlagMaskShift;
|
||||
if (strcmp(name, "command") == 0) return kCGEventFlagMaskCommand;
|
||||
if (strcmp(name, "control") == 0) return kCGEventFlagMaskControl;
|
||||
if (strcmp(name, "option") == 0) return kCGEventFlagMaskAlternate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static napi_value is_modifier_pressed(napi_env env, napi_callback_info info) {
|
||||
napi_get_cb_info_fn napi_get_cb_info = (napi_get_cb_info_fn)node_symbol("napi_get_cb_info");
|
||||
napi_get_value_string_utf8_fn napi_get_value_string_utf8 = (napi_get_value_string_utf8_fn)node_symbol("napi_get_value_string_utf8");
|
||||
napi_get_boolean_fn napi_get_boolean = (napi_get_boolean_fn)node_symbol("napi_get_boolean");
|
||||
|
||||
bool pressed = false;
|
||||
if (napi_get_cb_info && napi_get_value_string_utf8) {
|
||||
size_t argc = 1;
|
||||
napi_value args[1] = {0};
|
||||
if (napi_get_cb_info(env, info, &argc, args, 0, 0) == 0 && argc >= 1 && args[0]) {
|
||||
char name[16] = {0};
|
||||
size_t copied = 0;
|
||||
if (napi_get_value_string_utf8(env, args[0], name, sizeof(name), &copied) == 0) {
|
||||
CGEventFlags mask = modifier_mask_for_name(name);
|
||||
if (mask != 0) {
|
||||
CGEventFlags flags = CGEventSourceFlagsState(kCGEventSourceStateCombinedSessionState);
|
||||
pressed = (flags & mask) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
napi_value result = 0;
|
||||
if (napi_get_boolean) napi_get_boolean(env, pressed, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) napi_value napi_register_module_v1(napi_env env, napi_value exports) {
|
||||
napi_create_function_fn napi_create_function = (napi_create_function_fn)node_symbol("napi_create_function");
|
||||
napi_set_named_property_fn napi_set_named_property = (napi_set_named_property_fn)node_symbol("napi_set_named_property");
|
||||
|
||||
napi_value fn = 0;
|
||||
if (napi_create_function &&
|
||||
napi_set_named_property &&
|
||||
napi_create_function(env, "isModifierPressed", NAPI_AUTO_LENGTH, is_modifier_pressed, 0, &fn) == 0) {
|
||||
napi_set_named_property(env, exports, "isModifierPressed", fn);
|
||||
}
|
||||
|
||||
return exports;
|
||||
}
|
||||
132
third_party/pi/packages/tui/native/darwin/src/darwin-platform.m
vendored
Normal file
132
third_party/pi/packages/tui/native/darwin/src/darwin-platform.m
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
#import <AppKit/AppKit.h>
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define PI_CLIPBOARD_WRITE
|
||||
#include "../../clipboard.h"
|
||||
|
||||
static CGEventFlags modifier_mask_for_name(const char* name) {
|
||||
if (strcmp(name, "shift") == 0) return kCGEventFlagMaskShift;
|
||||
if (strcmp(name, "command") == 0) return kCGEventFlagMaskCommand;
|
||||
if (strcmp(name, "control") == 0) return kCGEventFlagMaskControl;
|
||||
if (strcmp(name, "option") == 0) return kCGEventFlagMaskAlternate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static napi_value is_modifier_pressed(napi_env env, napi_callback_info info) {
|
||||
napi_get_cb_info_fn napi_get_cb_info = (napi_get_cb_info_fn)node_symbol("napi_get_cb_info");
|
||||
napi_get_value_string_utf8_fn napi_get_value_string_utf8 =
|
||||
(napi_get_value_string_utf8_fn)node_symbol("napi_get_value_string_utf8");
|
||||
napi_get_boolean_fn napi_get_boolean = (napi_get_boolean_fn)node_symbol("napi_get_boolean");
|
||||
|
||||
bool pressed = false;
|
||||
if (napi_get_cb_info && napi_get_value_string_utf8) {
|
||||
size_t argc = 1;
|
||||
napi_value args[1] = {0};
|
||||
if (napi_get_cb_info(env, info, &argc, args, 0, 0) == 0 && argc >= 1 && args[0]) {
|
||||
char name[16] = {0};
|
||||
size_t copied = 0;
|
||||
if (napi_get_value_string_utf8(env, args[0], name, sizeof(name), &copied) == 0) {
|
||||
CGEventFlags mask = modifier_mask_for_name(name);
|
||||
if (mask != 0) {
|
||||
CGEventFlags flags = CGEventSourceFlagsState(kCGEventSourceStateCombinedSessionState);
|
||||
pressed = (flags & mask) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
napi_value result = 0;
|
||||
if (!napi_get_boolean || napi_get_boolean(env, pressed, &result) != 0) {
|
||||
return fail(env, "Could not inspect modifier state");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void clipboard_execute(clipboard_job* job) {
|
||||
@autoreleasepool {
|
||||
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
|
||||
if (!pasteboard) {
|
||||
job->error = "Could not open clipboard";
|
||||
} else if (job->operation == CLIPBOARD_WRITE) {
|
||||
NSString* text = [[NSString alloc] initWithBytes:job->data length:job->length encoding:NSUTF8StringEncoding];
|
||||
if (!text) {
|
||||
job->error = "Clipboard text is not valid UTF-8";
|
||||
return;
|
||||
}
|
||||
[pasteboard clearContents];
|
||||
if (![pasteboard setString:text forType:NSPasteboardTypeString]) job->error = "Could not set clipboard text";
|
||||
} else if (job->operation == CLIPBOARD_TEXT) {
|
||||
NSString* text = [pasteboard stringForType:NSPasteboardTypeString];
|
||||
if (!text) {
|
||||
job->format = CLIPBOARD_EMPTY;
|
||||
} else if (!text.UTF8String) {
|
||||
job->error = "Could not encode clipboard text";
|
||||
} else {
|
||||
clipboard_copy(job, text.UTF8String, [text lengthOfBytesUsingEncoding:NSUTF8StringEncoding], CLIPBOARD_UTF8);
|
||||
}
|
||||
} else if (job->operation == CLIPBOARD_FILES) {
|
||||
NSArray* urls = [pasteboard readObjectsForClasses:@[[NSURL class]]
|
||||
options:@{NSPasteboardURLReadingFileURLsOnlyKey: @YES}];
|
||||
size_t total = 0;
|
||||
for (NSURL* url in urls) {
|
||||
const char* path = url.fileSystemRepresentation;
|
||||
if (!path) continue;
|
||||
size_t length = strlen(path);
|
||||
if (length == SIZE_MAX || total > SIZE_MAX - length - 1) {
|
||||
job->error = "Clipboard file paths are too large";
|
||||
return;
|
||||
}
|
||||
total += length + 1;
|
||||
}
|
||||
if (total == 0) {
|
||||
job->format = CLIPBOARD_EMPTY;
|
||||
return;
|
||||
}
|
||||
char* paths = clipboard_alloc(total);
|
||||
if (!paths) {
|
||||
job->error = "Out of memory";
|
||||
return;
|
||||
}
|
||||
char* cursor = paths;
|
||||
for (NSURL* url in urls) {
|
||||
const char* path = url.fileSystemRepresentation;
|
||||
if (!path) continue;
|
||||
size_t length = strlen(path);
|
||||
memcpy(cursor, path, length + 1);
|
||||
cursor += length + 1;
|
||||
}
|
||||
job->data = paths;
|
||||
job->length = total;
|
||||
job->format = CLIPBOARD_PATHS;
|
||||
} else {
|
||||
if (![pasteboard availableTypeFromArray:@[ NSPasteboardTypePNG, NSPasteboardTypeTIFF ]]) {
|
||||
job->format = CLIPBOARD_EMPTY;
|
||||
return;
|
||||
}
|
||||
NSData* png = [pasteboard dataForType:NSPasteboardTypePNG];
|
||||
if (!png) {
|
||||
NSImage* image = [[NSImage alloc] initWithPasteboard:pasteboard];
|
||||
NSData* tiff = image.TIFFRepresentation;
|
||||
NSBitmapImageRep* bitmap = tiff ? [NSBitmapImageRep imageRepWithData:tiff] : nil;
|
||||
png = bitmap ? [bitmap representationUsingType:NSBitmapImageFileTypePNG properties:@{}] : nil;
|
||||
}
|
||||
if (png) clipboard_copy(job, png.bytes, png.length, CLIPBOARD_BUFFER);
|
||||
else job->error = "Clipboard does not contain an image";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static napi_value PI_NAPI_CALL get_clipboard_file_paths(napi_env env, napi_callback_info info) {
|
||||
return queue_clipboard(env, info, CLIPBOARD_FILES);
|
||||
}
|
||||
|
||||
PI_NAPI_EXPORT napi_value napi_register_module_v1(napi_env env, napi_value exports) {
|
||||
set_function_export(env, exports, "isModifierPressed", is_modifier_pressed);
|
||||
set_function_export(env, exports, "getText", get_clipboard_text);
|
||||
set_function_export(env, exports, "setText", set_clipboard_text);
|
||||
set_function_export(env, exports, "getImage", get_clipboard_image);
|
||||
set_function_export(env, exports, "getFilePaths", get_clipboard_file_paths);
|
||||
return exports;
|
||||
}
|
||||
Reference in New Issue
Block a user