diff options
| author | Berke Güzel <wenekar1@gmail.com> | 2026-10-12 10:17:33 +0300 |
|---|---|---|
| committer | Berke Güzel <wenekar1@gmail.com> | 2026-10-12 10:17:33 +0300 |
| commit | 881fb6cb1d64868132287bd9637f4ae1cbc3504c (patch) | |
| tree | 5688d5f8be69805ccf290178675b522802155e6d /src/cocoa | |
| parent | 3b8af02be94a510e385f44d58c35c86bb89424a6 (diff) | |
cursor hidden and tablet support
Diffstat (limited to 'src/cocoa')
| -rw-r--r-- | src/cocoa/window.m | 78 |
1 files changed, 63 insertions, 15 deletions
diff --git a/src/cocoa/window.m b/src/cocoa/window.m index 6e1e457..6235b77 100644 --- a/src/cocoa/window.m +++ b/src/cocoa/window.m @@ -91,6 +91,8 @@ struct cocoa_surface { uint32_t state; uint32_t mods; enum yasl_cursor cursor; + enum yasl_pointer_device tablet_device; + bool tablet_down; char title[160]; struct yasl_frame_clock clock; @@ -106,6 +108,7 @@ struct cocoa_display { char *app_id; struct yasl_loop *loop; id key_up_monitor; + NSCursor *hidden_cursor; YaslAppDelegate *delegate; NSPoint cascade; struct cocoa_surface *dead; @@ -284,6 +287,18 @@ static void push_pointer(struct cocoa_surface *w, NSEvent *ev, enum yasl_pointer { if (!w || w->closed || button < 0) return; + bool proximity = ev.type == NSEventTypeTabletProximity || + ev.subtype == NSEventSubtypeTabletProximity; + if (proximity) { + if (ev.isEnteringProximity) { + w->tablet_device = ev.pointingDeviceType == NSPointingDeviceTypeEraser ? + YASL_PTR_DEV_ERASER : ev.pointingDeviceType == NSPointingDeviceTypePen ? + YASL_PTR_DEV_PEN : YASL_PTR_DEV_MOUSE; + return; + } + kind = YASL_PTR_LEAVE; + button = 3; + } w->mods = cocoa_mods(ev.modifierFlags); if (kind != YASL_PTR_LEAVE) w->pointer = event_pos(w, ev); @@ -291,20 +306,26 @@ static void push_pointer(struct cocoa_surface *w, NSEvent *ev, enum yasl_pointer enum yasl_pointer_device device = YASL_PTR_DEV_MOUSE; struct yasl_pointer_pen pen = {0}; - float press = (float)ev.pressure; - if (ev.subtype == NSEventSubtypeTabletPoint || press > 0.0f) { - if (ev.pointingDeviceType == NSPointingDeviceTypeEraser) - device = YASL_PTR_DEV_ERASER; - else if (ev.pointingDeviceType == NSPointingDeviceTypePen) - device = YASL_PTR_DEV_PEN; - + if (kind == YASL_PTR_LEAVE && w->tablet_device != YASL_PTR_DEV_MOUSE) { + device = w->tablet_device; + w->tablet_down = false; + } else if (ev.type == NSEventTypeTabletPoint || ev.subtype == NSEventSubtypeTabletPoint) { + /* pointingDeviceType belongs to proximity events. Remember that + * event's tool so erasers and zero-pressure hover stay classified. */ + device = w->tablet_device == YASL_PTR_DEV_ERASER ? YASL_PTR_DEV_ERASER : YASL_PTR_DEV_PEN; + float press = (float)ev.pressure; if (press > 1.0f) press = 1.0f; if (press > 0.0f) pen.pressure = (uint16_t)(press * 65535.0f); NSPoint tilt = ev.tilt; - pen.tilt_x = (int8_t)(tilt.x * 90.0); - pen.tilt_y = (int8_t)(tilt.y * 90.0); + pen.tilt_x = (int8_t)lround(fmax(-1, fmin(1, tilt.x)) * 90.0); + pen.tilt_y = (int8_t)lround(fmax(-1, fmin(1, -tilt.y)) * 90.0); + if (button == 0 && kind == YASL_PTR_PRESS) w->tablet_down = true; + if (button == 0 && kind == YASL_PTR_RELEASE) { + w->tablet_down = false; + pen.pressure = 0; + } } struct yasl_input_event input_ev = { @@ -320,6 +341,10 @@ static void push_pointer(struct cocoa_surface *w, NSEvent *ev, enum yasl_pointer }, }; input_queue_push(&w->input, &input_ev); + if (proximity) { + w->tablet_device = YASL_PTR_DEV_MOUSE; + w->tablet_down = false; + } } static NSCursor *cocoa_cursor(enum yasl_cursor cursor) @@ -328,6 +353,17 @@ static NSCursor *cocoa_cursor(enum yasl_cursor cursor) case YASL_CURSOR_TEXT: return [NSCursor IBeamCursor]; case YASL_CURSOR_LINK: return [NSCursor pointingHandCursor]; case YASL_CURSOR_CROSSHAIR: return [NSCursor crosshairCursor]; + case YASL_CURSOR_HIDDEN: + if (!darwin_ctx.hidden_cursor) { + NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize(1, 1)]; + [image lockFocus]; + [[NSColor clearColor] set]; + NSRectFillUsingOperation(NSMakeRect(0, 0, 1, 1), NSCompositingOperationCopy); + [image unlockFocus]; + darwin_ctx.hidden_cursor = [[NSCursor alloc] initWithImage:image hotSpot:NSZeroPoint]; + [image release]; + } + return darwin_ctx.hidden_cursor; case YASL_CURSOR_ARROW: default: return [NSCursor arrowCursor]; } @@ -566,6 +602,21 @@ static NSCursor *cocoa_cursor(enum yasl_cursor cursor) push_pointer(self.surface, event, YASL_PTR_LEAVE, 3); } +- (void)tabletProximity:(NSEvent *)event +{ + push_pointer(self.surface, event, YASL_PTR_MOTION, 3); +} + +- (void)tabletPoint:(NSEvent *)event +{ + struct cocoa_surface *w = self.surface; + if (!w) return; + bool down = (event.buttonMask & NSEventButtonMaskPenTip) != 0; + enum yasl_pointer_kind kind = down == w->tablet_down ? YASL_PTR_MOTION : + down ? YASL_PTR_PRESS : YASL_PTR_RELEASE; + push_pointer(w, event, kind, 0); +} + - (void)scrollWheel:(NSEvent *)event { struct cocoa_surface *w = self.surface; @@ -1042,6 +1093,7 @@ void cocoa_display_close(struct cocoa_display *d) NSApp.delegate = nil; [d->delegate release]; d->delegate = nil; + [d->hidden_cursor release]; free(d->app_id); free(d->windows); *d = (struct cocoa_display){0}; @@ -1050,7 +1102,7 @@ void cocoa_display_close(struct cocoa_display *d) uint32_t cocoa_display_caps(const struct cocoa_display *d) { return d ? (YASL_CAP_PLACE_WINDOW | YASL_CAP_CSD | YASL_CAP_NATIVE_GRAPHICS | - YASL_CAP_FRAME_PACING) : 0; + YASL_CAP_FRAME_PACING | YASL_CAP_TABLET) : 0; } struct cocoa_surface *cocoa_surface_create_toplevel(struct cocoa_display *d, @@ -1230,12 +1282,8 @@ void cocoa_surface_set_background_color(struct cocoa_surface *w, uint32_t bg) void cocoa_surface_set_cursor(struct cocoa_surface *w, enum yasl_cursor cursor) { - if (!w || w->closed || cursor == w->cursor) return; + if (!w || w->closed || cursor == w->cursor || (unsigned)cursor > YASL_CURSOR_HIDDEN) return; w->cursor = cursor; - if (cursor == YASL_CURSOR_NONE) { - [NSCursor setHiddenUntilMouseMoves:YES]; - return; - } NSPoint p = [w->view convertPoint:w->window.mouseLocationOutsideOfEventStream fromView:nil]; if (w->window.isKeyWindow && NSPointInRect(p, w->view.bounds)) [cocoa_cursor(cursor) set]; |
