summaryrefslogtreecommitdiff
path: root/tests/cocoa
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-12 10:53:22 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-12 10:53:22 +0300
commit5206933399775e5ff46baefbbb3a776c2a9bb84c (patch)
treee7549216ac626c1f3ac22345f79fbf80cc5a90fb /tests/cocoa
parent881fb6cb1d64868132287bd9637f4ae1cbc3504c (diff)
feat: add type-safe native platform headers and portable drag support
- Add include/yasl/native/{wayland,cocoa,x11}.h with type-safe handle accessors. - Unify drag-and-drop and window carry support across Wayland, X11, and Cocoa. - Preserve full ABI compatibility for capability flags. - Install native headers conditionally based on enabled backend. - Include missing tablet example and backend test suites.
Diffstat (limited to 'tests/cocoa')
-rw-r--r--tests/cocoa/test_cursor.m53
-rw-r--r--tests/cocoa/test_ownership.m4
-rw-r--r--tests/cocoa/test_tablet.m123
3 files changed, 180 insertions, 0 deletions
diff --git a/tests/cocoa/test_cursor.m b/tests/cocoa/test_cursor.m
new file mode 100644
index 0000000..0f3ba06
--- /dev/null
+++ b/tests/cocoa/test_cursor.m
@@ -0,0 +1,53 @@
+#import <AppKit/AppKit.h>
+#include <yasl/native.h>
+#include <assert.h>
+
+static void assert_transparent(NSCursor *cursor)
+{
+ assert(cursor);
+ NSBitmapImageRep *bitmap = [NSBitmapImageRep imageRepWithData:cursor.image.TIFFRepresentation];
+ assert(bitmap && bitmap.hasAlpha);
+ for (NSInteger y = 0; y < bitmap.pixelsHigh; y++)
+ for (NSInteger x = 0; x < bitmap.pixelsWide; x++)
+ assert([bitmap colorAtX:x y:y].alphaComponent == 0);
+}
+
+int main(void)
+{
+ @autoreleasepool {
+ struct yasl_display *display = yasl_display_open(NULL, NULL);
+ assert(display);
+ struct yasl_surface_spec spec = {.title = "Cursor test", .size = {320, 240}};
+ struct yasl_surface *surface = yasl_surface_create_toplevel(display, &spec);
+ assert(surface);
+ NSWindow *window = (NSWindow *)yasl_surface_get_native_handle(surface);
+ NSView *view = window.contentView;
+ yasl_surface_set_cursor(surface, YASL_CURSOR_HIDDEN);
+ [view cursorUpdate:nil];
+ NSCursor *hidden = [NSCursor currentCursor];
+ assert_transparent(hidden);
+
+ NSEvent *motion = [NSEvent mouseEventWithType:NSEventTypeMouseMoved
+ location:NSMakePoint(100, 120) modifierFlags:0 timestamp:0
+ windowNumber:window.windowNumber context:nil eventNumber:0 clickCount:0 pressure:0];
+ [view mouseMoved:motion];
+ [view cursorUpdate:nil];
+ assert([NSCursor currentCursor] == hidden);
+ struct yasl_input_event event;
+ bool moved = false;
+ while (yasl_surface_input_poll(surface, &event))
+ if (event.kind == YASL_INPUT_MOUSE && event.mouse.kind == YASL_PTR_MOTION)
+ moved = true;
+ assert(moved);
+
+ [[NSCursor arrowCursor] set]; /* Simulate leaving and re-entering. */
+ [view cursorUpdate:nil];
+ assert([NSCursor currentCursor] == hidden);
+ yasl_surface_set_cursor(surface, YASL_CURSOR_ARROW);
+ [view cursorUpdate:nil];
+ assert([NSCursor currentCursor] == [NSCursor arrowCursor]);
+ yasl_surface_destroy(surface);
+ yasl_display_close(display);
+ }
+ return 0;
+}
diff --git a/tests/cocoa/test_ownership.m b/tests/cocoa/test_ownership.m
index 168a47b..2b2f52d 100644
--- a/tests/cocoa/test_ownership.m
+++ b/tests/cocoa/test_ownership.m
@@ -1,4 +1,5 @@
#include "yasl/native.h"
+#include "yasl/native/cocoa.h"
#import <AppKit/AppKit.h>
#include "yasl/yasl.h"
#include <assert.h>
@@ -13,7 +14,10 @@ int main(void)
struct yasl_surface *s = yasl_surface_create_toplevel(d, &spec);
assert(s);
assert(yasl_display_get_native_handle(d) == (void *)NSApp);
+ assert(yasl_cocoa_display_get_application(d) == NSApp);
NSWindow *window = (NSWindow *)yasl_surface_get_native_handle(s);
+ assert(yasl_cocoa_surface_get_window(s) == window);
+ assert(yasl_cocoa_surface_get_view(s) == window.contentView);
assert([window isKindOfClass:[NSWindow class]] && window.contentView);
struct yasl_input_event event;
while (yasl_surface_input_poll(s, &event)) {}
diff --git a/tests/cocoa/test_tablet.m b/tests/cocoa/test_tablet.m
new file mode 100644
index 0000000..f1489a1
--- /dev/null
+++ b/tests/cocoa/test_tablet.m
@@ -0,0 +1,123 @@
+#import <AppKit/AppKit.h>
+#include <yasl/native.h>
+#include <assert.h>
+
+/* A strict event double catches querying tablet-only properties on ordinary
+ * mouse events, and proximity-only properties on tablet point events. */
+@interface TabletSample : NSObject
+@property NSEventType type;
+@property NSEventSubtype subtype;
+@property NSEventModifierFlags modifierFlags;
+@property NSPoint locationInWindow;
+@property NSInteger buttonNumber;
+@property NSUInteger buttonMask;
+@property(getter=isEnteringProximity) BOOL enteringProximity;
+@property NSPointingDeviceType tool;
+@property float samplePressure;
+@property NSPoint sampleTilt;
+@end
+
+@implementation TabletSample
+- (float)pressure
+{
+ assert(self.type == NSEventTypeTabletPoint || self.subtype == NSEventSubtypeTabletPoint);
+ return self.samplePressure;
+}
+- (NSPoint)tilt
+{
+ assert(self.type == NSEventTypeTabletPoint || self.subtype == NSEventSubtypeTabletPoint);
+ return self.sampleTilt;
+}
+- (NSPointingDeviceType)pointingDeviceType
+{
+ assert(self.type == NSEventTypeTabletProximity || self.subtype == NSEventSubtypeTabletProximity);
+ return self.tool;
+}
+@end
+
+static struct yasl_mouse_event next(struct yasl_surface *surface)
+{
+ struct yasl_input_event event;
+ while (yasl_surface_input_poll(surface, &event))
+ if (event.kind == YASL_INPUT_MOUSE) return event.mouse;
+ assert(!"Expected a pointer event");
+ return (struct yasl_mouse_event){0};
+}
+
+int main(void)
+{
+ @autoreleasepool {
+ struct yasl_display *display = yasl_display_open(NULL, NULL);
+ assert(display && (yasl_display_caps(display) & YASL_CAP_TABLET));
+ struct yasl_surface_spec spec = {.title = "Tablet test", .size = {320, 240}};
+ struct yasl_surface *surface = yasl_surface_create_toplevel(display, &spec);
+ assert(surface);
+ NSWindow *window = (NSWindow *)yasl_surface_get_native_handle(surface);
+ NSView *view = window.contentView;
+ struct yasl_input_event event;
+ while (yasl_surface_input_poll(surface, &event)) {}
+ TabletSample *sample = [TabletSample new];
+ NSEvent *native = (NSEvent *)sample;
+ sample.type = NSEventTypeTabletProximity;
+ sample.enteringProximity = YES;
+ sample.tool = NSPointingDeviceTypePen;
+ [view tabletProximity:native];
+ sample.type = NSEventTypeMouseMoved;
+ sample.subtype = NSEventSubtypeTabletPoint;
+ sample.locationInWindow = NSMakePoint(100, 120);
+ sample.sampleTilt = NSMakePoint(-0.5, 0.5);
+ [view mouseMoved:native];
+ struct yasl_mouse_event ev = next(surface);
+ assert(ev.device == YASL_PTR_DEV_PEN && ev.kind == YASL_PTR_MOTION && !ev.pen.pressure);
+ assert(ev.pen.tilt_x == -45 && ev.pen.tilt_y == -45);
+ sample.type = NSEventTypeLeftMouseDown;
+ sample.samplePressure = 0.5;
+ [view mouseDown:native];
+ ev = next(surface);
+ assert(ev.device == YASL_PTR_DEV_PEN && ev.kind == YASL_PTR_PRESS && ev.button == 0);
+ assert(ev.pen.pressure == 32767);
+ struct yasl_vector2i position = ev.pos;
+ /* Native tablet events cover stationary pressure changes. */
+ sample.type = NSEventTypeTabletPoint;
+ sample.subtype = NSEventSubtypeMouseEvent;
+ sample.buttonMask = NSEventButtonMaskPenTip;
+ sample.samplePressure = 1.5;
+ [view tabletPoint:native];
+ ev = next(surface);
+ assert(ev.kind == YASL_PTR_MOTION && ev.pen.pressure == 65535);
+ assert(ev.pos.x == position.x && ev.pos.y == position.y);
+ sample.samplePressure = 0; /* Zero does not release a held tip button. */
+ [view tabletPoint:native];
+ assert(next(surface).kind == YASL_PTR_MOTION);
+ sample.buttonMask = 0;
+ [view tabletPoint:native];
+ ev = next(surface);
+ assert(ev.kind == YASL_PTR_RELEASE && !ev.pen.pressure && ev.device == YASL_PTR_DEV_PEN);
+ sample.type = NSEventTypeTabletProximity;
+ sample.enteringProximity = NO;
+ [view tabletProximity:native];
+ assert(next(surface).kind == YASL_PTR_LEAVE);
+ sample.enteringProximity = YES;
+ sample.tool = NSPointingDeviceTypeEraser;
+ [view tabletProximity:native];
+ sample.type = NSEventTypeTabletPoint;
+ sample.samplePressure = 0.75;
+ sample.buttonMask = NSEventButtonMaskPenTip;
+ [view tabletPoint:native];
+ ev = next(surface);
+ assert(ev.device == YASL_PTR_DEV_ERASER && ev.kind == YASL_PTR_PRESS && ev.pen.pressure > 0);
+ sample.type = NSEventTypeTabletProximity;
+ sample.enteringProximity = NO;
+ [view tabletProximity:native];
+ ev = next(surface);
+ assert(ev.device == YASL_PTR_DEV_ERASER && ev.kind == YASL_PTR_LEAVE && !ev.pen.pressure);
+ sample.type = NSEventTypeMouseMoved;
+ [view mouseMoved:native];
+ ev = next(surface);
+ assert(ev.device == YASL_PTR_DEV_MOUSE && !ev.pen.pressure);
+ [sample release];
+ yasl_surface_destroy(surface);
+ yasl_display_close(display);
+ }
+ return 0;
+}