From 30ceacc90ded84ed2b2c2861742c335cf9c0915c Mon Sep 17 00:00:00 2001 From: Riccardo Canalicchio Date: Mon, 25 Oct 2021 07:16:22 -0400 Subject: [PATCH] wayland backend: refactor code, split into categories --- Headers/wayland/WaylandServer.h | 5 +- Source/wayland/GNUmakefile | 6 + Source/wayland/WaylandServer+Cursor.m | 446 ++++++++++ Source/wayland/WaylandServer+Keyboard.m | 192 +++++ Source/wayland/WaylandServer+Layershell.m | 38 + Source/wayland/WaylandServer+Output.m | 96 +++ Source/wayland/WaylandServer+Seat.m | 64 ++ Source/wayland/WaylandServer+Xdgshell.m | 129 +++ Source/wayland/WaylandServer.m | 953 +--------------------- 9 files changed, 1001 insertions(+), 928 deletions(-) mode change 100644 => 100755 Headers/wayland/WaylandServer.h create mode 100755 Source/wayland/WaylandServer+Cursor.m create mode 100755 Source/wayland/WaylandServer+Keyboard.m create mode 100755 Source/wayland/WaylandServer+Layershell.m create mode 100755 Source/wayland/WaylandServer+Output.m create mode 100755 Source/wayland/WaylandServer+Seat.m create mode 100755 Source/wayland/WaylandServer+Xdgshell.m mode change 100644 => 100755 Source/wayland/WaylandServer.m diff --git a/Headers/wayland/WaylandServer.h b/Headers/wayland/WaylandServer.h old mode 100644 new mode 100755 index a74eb4b..4fafd0d --- a/Headers/wayland/WaylandServer.h +++ b/Headers/wayland/WaylandServer.h @@ -109,7 +109,8 @@ struct window { int window_id; struct wl_list link; BOOL configured; // surface has been configured once - BOOL buffer_needs_attach; // surface has been configured once + BOOL buffer_needs_attach; // there is a new buffer avaialble for the surface + BOOL terminated; // there is a new buffer avaialble for the surface float pos_x; float pos_y; @@ -140,5 +141,7 @@ struct window { BOOL _mouseInitialized; } @end +@interface WaylandServer(Cursor) +@end #endif /* _XGServer_h_INCLUDE */ diff --git a/Source/wayland/GNUmakefile b/Source/wayland/GNUmakefile index b84fd24..a106b5e 100644 --- a/Source/wayland/GNUmakefile +++ b/Source/wayland/GNUmakefile @@ -45,6 +45,12 @@ wlr-layer-shell-protocol.c \ # The Objective-C source files to be compiled wayland_OBJC_FILES = \ WaylandServer.m \ +WaylandServer+Output.m \ +WaylandServer+Cursor.m \ +WaylandServer+Keyboard.m \ +WaylandServer+Seat.m \ +WaylandServer+Xdgshell.m \ +WaylandServer+Layershell.m \ -include GNUmakefile.preamble diff --git a/Source/wayland/WaylandServer+Cursor.m b/Source/wayland/WaylandServer+Cursor.m new file mode 100755 index 0000000..ea43d09 --- /dev/null +++ b/Source/wayland/WaylandServer+Cursor.m @@ -0,0 +1,446 @@ +#include "wayland/WaylandServer.h" +#include +#include +#include + +static void +pointer_handle_enter(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface, + wl_fixed_t sx_w, wl_fixed_t sy_w) +{ + NSDebugLog(@"pointer_handle_enter"); + if (!surface) { + NSDebugLog(@"no surface"); + return; + } + + WaylandConfig *wlconfig = data; + struct window *window = wl_surface_get_user_data(surface); + float sx = wl_fixed_to_double(sx_w); + float sy = wl_fixed_to_double(sy_w); + [GSCurrentServer() initializeMouseIfRequired]; + + wlconfig->pointer.x = sx; + wlconfig->pointer.y = sy; + wlconfig->pointer.focus = window; + + // FIXME: Send NSMouseEntered event. +} + +static void +pointer_handle_leave(void *data, struct wl_pointer *pointer, + uint32_t serial, struct wl_surface *surface) +{ + NSDebugLog(@"pointer_handle_leave"); + if (!surface) { + NSDebugLog(@"no surface"); + return; + } + + WaylandConfig *wlconfig = data; + struct window *window = wl_surface_get_user_data(surface); + [GSCurrentServer() initializeMouseIfRequired]; + + if (wlconfig->pointer.focus->window_id == window->window_id) { + wlconfig->pointer.focus = NULL; + wlconfig->pointer.serial = 0; + } + + // FIXME: Send NSMouseExited event. +} + +// triggered when the cursor is over a surface +static void +pointer_handle_motion(void *data, struct wl_pointer *pointer, + uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w) +{ + WaylandConfig *wlconfig = data; + struct window *window; + float sx = wl_fixed_to_double(sx_w); + float sy = wl_fixed_to_double(sy_w); + NSDebugLog(@"pointer_handle_motion: %fx%f", sx, sy); + + [GSCurrentServer() initializeMouseIfRequired]; + + if (wlconfig->pointer.focus && wlconfig->pointer.serial) { + window = wlconfig->pointer.focus; + NSEvent *event; + NSEventType eventType; + NSPoint eventLocation; + NSGraphicsContext *gcontext; + unsigned int eventFlags; + float deltaX = sx - window->wlconfig->pointer.x; + float deltaY = sy - window->wlconfig->pointer.y; + +// NSDebugLog(@"obtaining locations: wayland=%fx%f pointer=%fx%f", +// sx, sy, window->wlconfig->pointer.x, window->wlconfig->pointer.y); + + gcontext = GSCurrentContext(); + eventLocation = NSMakePoint(sx, + window->height - sy); + + eventFlags = 0; + eventType = NSLeftMouseDragged; + +// NSDebugLog(@"sending pointer delta: %fx%f, window=%d", deltaX, deltaY, window->window_id); + + event = [NSEvent mouseEventWithType: eventType + location: eventLocation + modifierFlags: eventFlags + timestamp: (NSTimeInterval) time / 1000.0 + windowNumber: (int)window->window_id + context: gcontext + eventNumber: time + clickCount: 1 + pressure: 1.0 + buttonNumber: 0 /* FIXME */ + deltaX: deltaX + deltaY: deltaY + deltaZ: 0.]; + + [GSCurrentServer() postEvent: event atStart: NO]; + } + + wlconfig->pointer.x = sx; + wlconfig->pointer.y = sy; +} + +static void +pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial, + uint32_t time, uint32_t button, uint32_t state_w) +{ + NSDebugLog(@"pointer_handle_button: button=%d", button); + WaylandConfig *wlconfig = data; + NSEvent *event; + NSEventType eventType; + NSPoint eventLocation; + NSGraphicsContext *gcontext; + unsigned int eventFlags; + float deltaX = 0.0; + float deltaY = 0.0; + int clickCount = 1; + int tick; + int buttonNumber; + enum wl_pointer_button_state state = state_w; + struct window *window = wlconfig->pointer.focus; + + [GSCurrentServer() initializeMouseIfRequired]; + + gcontext = GSCurrentContext(); + eventLocation = NSMakePoint(wlconfig->pointer.x, + window->height - wlconfig->pointer.y); + eventFlags = 0; + + if (state == WL_POINTER_BUTTON_STATE_PRESSED) { + if (button == wlconfig->pointer.last_click_button && + time - wlconfig->pointer.last_click_time < 300 && + abs(wlconfig->pointer.x - wlconfig->pointer.last_click_x) < 3 && + abs(wlconfig->pointer.y - wlconfig->pointer.last_click_y) < 3) { + NSDebugLog(@"handle_button HIT: b=%d t=%d x=%f y=%f", button, time, wlconfig->pointer.x, wlconfig->pointer.y); + wlconfig->pointer.last_click_time = 0; + clickCount++; + } else { + NSDebugLog(@"handle_button MISS: b=%d t=%d x=%f y=%f", button, time, wlconfig->pointer.x, wlconfig->pointer.y); + wlconfig->pointer.last_click_button = button; + wlconfig->pointer.last_click_time = time; + wlconfig->pointer.last_click_x = wlconfig->pointer.x; + wlconfig->pointer.last_click_y = wlconfig->pointer.y; + } + + switch (button) { + case BTN_LEFT: + eventType = NSLeftMouseDown; + break; + case BTN_RIGHT: + eventType = NSRightMouseDown; + break; + case BTN_MIDDLE: + eventType = NSOtherMouseDown; + break; + // TODO: handle BTN_SIDE, BTN_EXTRA, BTN_FORWARD, BTN_BACK and other + // constants in libinput. + // We may just want to send NSOtherMouseDown and populate buttonNumber + // with the libinput constant? + } + wlconfig->pointer.serial = serial; + } else if (state == WL_POINTER_BUTTON_STATE_RELEASED) { + switch (button) { + case BTN_LEFT: + eventType = NSLeftMouseUp; + break; + case BTN_RIGHT: + eventType = NSRightMouseUp; + break; + case BTN_MIDDLE: + eventType = NSOtherMouseUp; + break; + } + wlconfig->pointer.serial = 0; + } else { + NSDebugLog(@"unhandled wayland pointer state 0x%02x", state); + return; + } + + /* FIXME: unlike in _motion and _axis handlers, the argument used in _button + is the "serial" of the event, not passed and unavailable in _motion and + _axis handlers. Is it allowed to pass "serial" as the eventNumber: in + _button handler, but "time" as the eventNumber: in the _motion and _axis + handlers? */ + tick = serial; + + NSDebugLog(@"sending pointer event at: %fx%f, window=%d", wlconfig->pointer.x, wlconfig->pointer.y, window->window_id); + + /* FIXME: X11 backend uses the XGetPointerMapping()-returned values from + its map_return argument as constants for buttonNumber. As the variant + with buttonNumber: seems to be a GNUstep extension, and the value + internal, it might be ok to just provide libinput constant as we're doing + here. If this is truly correct, please update this comment to document + the correctness of doing so. */ + buttonNumber = button; + + event = [NSEvent mouseEventWithType: eventType + location: eventLocation + modifierFlags: eventFlags + timestamp: (NSTimeInterval) time / 1000.0 + windowNumber: (int)window->window_id + context: gcontext + eventNumber: tick + clickCount: clickCount + pressure: 1.0 + buttonNumber: buttonNumber + deltaX: deltaX /* FIXME unused */ + deltaY: deltaY /* FIXME unused */ + deltaZ: 0.]; + + [GSCurrentServer() postEvent: event atStart: NO]; +} + +static void +pointer_handle_axis(void *data, struct wl_pointer *pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) +{ + NSDebugLog(@"pointer_handle_axis: axis=%d value=%g", axis, wl_fixed_to_double(value)); + WaylandConfig *wlconfig = data; + NSEvent *event; + NSEventType eventType; + NSPoint eventLocation; + NSGraphicsContext *gcontext; + unsigned int eventFlags; + float deltaX = 0.0; + float deltaY = 0.0; + int clickCount = 1; + int buttonNumber; + + struct window *window = wlconfig->pointer.focus; + + [GSCurrentServer() initializeMouseIfRequired]; + + gcontext = GSCurrentContext(); + eventLocation = NSMakePoint(wlconfig->pointer.x, + window->height - wlconfig->pointer.y); + eventFlags = 0; + + /* FIXME: we should get axis_source out of wl_pointer; however, the wl_pointer + is not defined in wayland-client.h. How does one get the axis_source out of + it to confirm the source is the physical mouse wheel? */ +#if 0 + if (pointer->axis_source != WL_POINTER_AXIS_SOURCE_WHEEL) + return; +#endif + + float mouse_scroll_multiplier = wlconfig->mouse_scroll_multiplier; + /* For smooth-scroll events, we're not doing any cross-event or delta + calculations, as is done in button event handling. */ + switch(axis) + { + case WL_POINTER_AXIS_VERTICAL_SCROLL: + eventType = NSScrollWheel; + deltaY = wl_fixed_to_double(value) * wlconfig->mouse_scroll_multiplier; + case WL_POINTER_AXIS_HORIZONTAL_SCROLL: + eventType = NSScrollWheel; + deltaX = wl_fixed_to_double(value) * wlconfig->mouse_scroll_multiplier; + } + + NSDebugLog(@"sending pointer scroll at: %fx%f, value %fx%f, window=%d", wlconfig->pointer.x, wlconfig->pointer.y, deltaX, deltaY, window->window_id); + + /* FIXME: X11 backend uses the XGetPointerMapping()-returned values from + its map_return argument as constants for buttonNumber. As the variant + with buttonNumber: seems to be a GNUstep extension, and the value + internal, it might be ok to just not provide any value here. + If this is truly correct, please update this comment to document + the correctness of doing so. */ + buttonNumber = 0; + + event = [NSEvent mouseEventWithType: eventType + location: eventLocation + modifierFlags: eventFlags + timestamp: (NSTimeInterval) time / 1000.0 + windowNumber: (int)window->window_id + context: gcontext + eventNumber: time + clickCount: clickCount + pressure: 1.0 + buttonNumber: buttonNumber + deltaX: deltaX + deltaY: deltaY + deltaZ: 0.]; + + [GSCurrentServer() postEvent: event atStart: NO]; +} + +const struct wl_pointer_listener pointer_listener = { + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, +}; + +@implementation WaylandServer(Cursor) +- (NSPoint) mouselocation +{ + int aScreen = -1; + struct output *output; + + NSDebugLog(@"mouselocation"); + + // FIXME: find a cleaner way to get the first element of a wl_list + wl_list_for_each(output, &wlconfig->output_list, link) { + aScreen = output->server_output_id; + break; + } + if (aScreen < 0) + // No outputs in the wl_list. + return NSZeroPoint; + + return [self mouseLocationOnScreen: aScreen window: NULL]; +} + +- (NSPoint) mouseLocationOnScreen: (int)aScreen window: (int *)win +{ +// NSDebugLog(@"mouseLocationOnScreen: %d %fx%f", win, +// wlconfig->pointer.x, wlconfig->pointer.y); + struct window *window = wlconfig->pointer.focus; + struct output *output; + float x; + float y; + + /*if (wlconfig->pointer.serial) { + NSDebugLog(@"captured"); + x = wlconfig->pointer.captured_x; + y = wlconfig->pointer.captured_y; + } else*/ { + //NSDebugLog(@"NOT captured"); + x = wlconfig->pointer.x; + y = wlconfig->pointer.y; + + if (window) { + x += window->pos_x; + y += window->pos_y; + if (win) { + *win = &window->window_id; + } + } + } + + wl_list_for_each(output, &wlconfig->output_list, link) { + if (output->server_output_id == aScreen) { + y = output->height - y; + break; + } + } + +// NSDebugLog(@"mouseLocationOnScreen: returning %fx%f", x, y); + + return NSMakePoint(x, y); +} + +- (BOOL) capturemouse: (int) win +{ + NSDebugLog(@"capturemouse: %d", win); + return NO; +} + +- (void) releasemouse +{ + NSDebugLog(@"releasemouse"); +} + +- (void) setMouseLocation: (NSPoint)mouseLocation onScreen: (int)aScreen +{ + NSDebugLog(@"setMouseLocation"); +} + +- (void) hidecursor +{ + NSDebugLog(@"hidecursor"); +} + +- (void) showcursor +{ + NSDebugLog(@"showcursor"); +} + +- (void) standardcursor: (int) style : (void**) cid +{ + NSDebugLog(@"standardcursor"); +} + +- (void) imagecursor: (NSPoint)hotp : (NSImage *) image : (void**) cid +{ + NSDebugLog(@"imagecursor"); +} + +- (void) setcursorcolor: (NSColor *)fg : (NSColor *)bg : (void*) cid +{ + NSLog(@"Call to obsolete method -setcursorcolor:::"); + [self recolorcursor: fg : bg : cid]; + [self setcursor: cid]; +} + +- (void) recolorcursor: (NSColor *)fg : (NSColor *)bg : (void*) cid +{ + NSDebugLog(@"recolorcursor"); +} + +- (void) setcursor: (void*) cid +{ + NSDebugLog(@"setcursor"); +} + +- (void) freecursor: (void*) cid +{ + NSDebugLog(@"freecursor"); +} +- (void) setIgnoreMouse: (BOOL)ignoreMouse : (int)win +{ + NSDebugLog(@"setIgnoreMouse"); +} + +- (void) initializeMouseIfRequired +{ + if (!_mouseInitialized) + [self initializeMouse]; +} + +- (void) initializeMouse +{ + _mouseInitialized = YES; + + [self mouseOptionsChanged: nil]; + [[NSDistributedNotificationCenter defaultCenter] + addObserver: self + selector: @selector(mouseOptionsChanged:) + name: NSUserDefaultsDidChangeNotification + object: nil]; +} + +- (void) mouseOptionsChanged: (NSNotification *)aNotif +{ + NSUserDefaults *defs = [NSUserDefaults standardUserDefaults]; + + wlconfig->mouse_scroll_multiplier = [defs integerForKey:@"GSMouseScrollMultiplier"]; + if (wlconfig->mouse_scroll_multiplier < 0.0001f) + wlconfig->mouse_scroll_multiplier = 1.0f; +} +@end diff --git a/Source/wayland/WaylandServer+Keyboard.m b/Source/wayland/WaylandServer+Keyboard.m new file mode 100755 index 0000000..a144ae7 --- /dev/null +++ b/Source/wayland/WaylandServer+Keyboard.m @@ -0,0 +1,192 @@ +#include "wayland/WaylandServer.h" +#include +#include +#include +#include +#include + + +static void +keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, + uint32_t format, int fd, uint32_t size) +{ + NSDebugLog(@"keyboard_handle_keymap"); + WaylandConfig *wlconfig = data; + struct xkb_keymap *keymap; + struct xkb_state *state; + char *map_str; + + if (!data) { + close(fd); + return; + } + + if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { + close(fd); + return; + } + + map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (map_str == MAP_FAILED) { + close(fd); + return; + } + + wlconfig->xkb_context = xkb_context_new(0); + if (wlconfig->xkb_context == NULL) { + fprintf(stderr, "Failed to create XKB context\n"); + return; + } + + keymap = xkb_keymap_new_from_string(wlconfig->xkb_context, + map_str, + XKB_KEYMAP_FORMAT_TEXT_V1, + 0); + munmap(map_str, size); + close(fd); + + if (!keymap) { + fprintf(stderr, "failed to compile keymap\n"); + return; + } + + state = xkb_state_new(keymap); + if (!state) { + fprintf(stderr, "failed to create XKB state\n"); + xkb_keymap_unref(keymap); + return; + } + + xkb_keymap_unref(wlconfig->xkb.keymap); + xkb_state_unref(wlconfig->xkb.state); + wlconfig->xkb.keymap = keymap; + wlconfig->xkb.state = state; + + wlconfig->xkb.control_mask = + 1 << xkb_keymap_mod_get_index(wlconfig->xkb.keymap, "Control"); + wlconfig->xkb.alt_mask = + 1 << xkb_keymap_mod_get_index(wlconfig->xkb.keymap, "Mod1"); + wlconfig->xkb.shift_mask = + 1 << xkb_keymap_mod_get_index(wlconfig->xkb.keymap, "Shift"); +} + +static void +keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, + uint32_t serial, struct wl_surface *surface, + struct wl_array *keys) +{ + NSDebugLog(@"keyboard_handle_enter"); +} + +static void +keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, + uint32_t serial, struct wl_surface *surface) +{ + NSDebugLog(@"keyboard_handle_leave"); +} + +static void +keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, + uint32_t serial, uint32_t mods_depressed, + uint32_t mods_latched, uint32_t mods_locked, + uint32_t group) +{ + NSDebugLog(@"keyboard_handle_modifiers"); + WaylandConfig *wlconfig = data; + xkb_mod_mask_t mask; + + /* If we're not using a keymap, then we don't handle PC-style modifiers */ + if (!wlconfig->xkb.keymap) + return; + + xkb_state_update_mask(wlconfig->xkb.state, mods_depressed, mods_latched, + mods_locked, 0, 0, group); + mask = xkb_state_serialize_mods(wlconfig->xkb.state, + XKB_STATE_MODS_DEPRESSED | + XKB_STATE_MODS_LATCHED); + wlconfig->modifiers = 0; + if (mask & wlconfig->xkb.control_mask) + wlconfig->modifiers |= NSCommandKeyMask; + if (mask & wlconfig->xkb.alt_mask) + wlconfig->modifiers |= NSAlternateKeyMask; + if (mask & wlconfig->xkb.shift_mask) + wlconfig->modifiers |= NSShiftKeyMask; +} + +static void +keyboard_handle_key(void *data, struct wl_keyboard *keyboard, + uint32_t serial, uint32_t time, uint32_t key, + uint32_t state_w) +{ + NSDebugLog(@"keyboard_handle_key: %d", key); + WaylandConfig *wlconfig = data; + uint32_t code, num_syms; + enum wl_keyboard_key_state state = state_w; + const xkb_keysym_t *syms; + xkb_keysym_t sym; + struct window *window = wlconfig->pointer.focus; + + if (!window) + return; + + code = 0; + if (key == 28) { + sym = NSCarriageReturnCharacter; + } else if (key == 14) { + sym = NSDeleteCharacter; + } else { + code = key + 8; + + num_syms = xkb_state_key_get_syms(wlconfig->xkb.state, code, &syms); + + sym = XKB_KEY_NoSymbol; + if (num_syms == 1) + sym = syms[0]; + } + + NSString *s = [NSString stringWithUTF8String: &sym]; + NSEventType eventType; + + if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { + eventType = NSKeyDown; + } else { + eventType = NSKeyUp; + } + + NSEvent *ev = [NSEvent keyEventWithType: eventType + location: NSZeroPoint + modifierFlags: wlconfig->modifiers + timestamp: time / 1000.0 + windowNumber: window->window_id + context: GSCurrentContext() + characters: s + charactersIgnoringModifiers: s + isARepeat: NO + keyCode: code]; + + [GSCurrentServer() postEvent: ev atStart: NO]; + + NSDebugLog(@"keyboard_handle_key: %@", s); +} + +static void +keyboard_handle_repeat_info(void *data, struct wl_keyboard *keyboard, + int32_t rate, int32_t delay) +{ + NSDebugLog(@"keyboard_handle_repeat_info"); +} + +const struct wl_keyboard_listener keyboard_listener = { + keyboard_handle_keymap, + keyboard_handle_enter, + keyboard_handle_leave, + keyboard_handle_key, + keyboard_handle_modifiers, + keyboard_handle_repeat_info +}; + + +@implementation WaylandServer (KeyboardOps) + +@end + diff --git a/Source/wayland/WaylandServer+Layershell.m b/Source/wayland/WaylandServer+Layershell.m new file mode 100755 index 0000000..dfecf5c --- /dev/null +++ b/Source/wayland/WaylandServer+Layershell.m @@ -0,0 +1,38 @@ +#include "wayland/WaylandServer.h" +#include +#include + +static void layer_surface_configure(void *data, + struct zwlr_layer_surface_v1 *surface, + uint32_t serial, uint32_t w, uint32_t h) { + + NSDebugLog(@"configure layer"); + struct window *window = data; + WaylandConfig *wlconfig = window->wlconfig; + zwlr_layer_surface_v1_ack_configure(surface, serial); + window->configured = YES; + if(window->buffer_needs_attach) { + NSDebugLog(@"attach: win=%d layer", window->window_id); + wl_surface_attach(window->surface, window->buffer, 0, 0); + wl_surface_commit(window->surface); + } + +} + +static void layer_surface_closed(void *data, + struct zwlr_layer_surface_v1 *surface) { + struct window *window = data; + WaylandConfig *wlconfig = window->wlconfig; + NSDebugLog(@"layer_surface_closed %d", window->window_id); + //zwlr_layer_surface_v1_destroy(surface); + wl_surface_destroy(window->surface); + window->surface = NULL; + window->configured = NO; + window->layer_surface = NULL; +} + +const struct zwlr_layer_surface_v1_listener layer_surface_listener = { + .configure = layer_surface_configure, + .closed = layer_surface_closed, +}; + diff --git a/Source/wayland/WaylandServer+Output.m b/Source/wayland/WaylandServer+Output.m new file mode 100755 index 0000000..a4d5cf5 --- /dev/null +++ b/Source/wayland/WaylandServer+Output.m @@ -0,0 +1,96 @@ +#include "wayland/WaylandServer.h" + +static void +handle_geometry(void *data, + struct wl_output *wl_output, + int x, int y, + int physical_width, + int physical_height, + int subpixel, + const char *make, + const char *model, + int transform) +{ + NSDebugLog(@"handle_geometry"); + struct output *output = data; + + output->alloc_x = x; + output->alloc_y = y; + output->transform = transform; + + if (output->make) + free(output->make); + output->make = strdup(make); + + if (output->model) + free(output->model); + output->model = strdup(model); +} + +static void +handle_done(void *data, + struct wl_output *wl_output) +{ + NSDebugLog(@"handle_done"); +} + +static void +handle_scale(void *data, + struct wl_output *wl_output, + int32_t scale) +{ + NSDebugLog(@"handle_scale"); + struct output *output = data; + + output->scale = scale; +} + +static void +handle_mode(void *data, + struct wl_output *wl_output, + uint32_t flags, + int width, + int height, + int refresh) +{ + NSDebugLog(@"handle_mode"); + struct output *output = data; + + if (flags & WL_OUTPUT_MODE_CURRENT) { + output->width = width; + output->height = height /*- 30*/; + NSDebugLog(@"handle_mode output=%dx%d", width, height); + +// XXX - Should we implement this? +// if (display->output_configure_handler) +// (*display->output_configure_handler) +// (output, display->user_data); +// + } + +} + +/* +static void +destroy_output(WaylandConfig *wlconfig, uint32_t id) +{ + struct output *output; + + wl_list_for_each(output, &wlconfig->output_list, link) { + if (output->server_output_id == id) { + wl_output_destroy(output->output); + wl_list_remove(&output->link); + free(output); + wlconfig->output_count--; + break; + } + } +} +*/ + +const struct wl_output_listener output_listener = { + handle_geometry, + handle_mode, + handle_done, + handle_scale +}; diff --git a/Source/wayland/WaylandServer+Seat.m b/Source/wayland/WaylandServer+Seat.m new file mode 100755 index 0000000..1187f2c --- /dev/null +++ b/Source/wayland/WaylandServer+Seat.m @@ -0,0 +1,64 @@ +#include "wayland/WaylandServer.h" + +extern const struct wl_keyboard_listener keyboard_listener; + +extern const struct wl_pointer_listener pointer_listener; + +static void +seat_handle_capabilities(void *data, struct wl_seat *seat, + enum wl_seat_capability caps) +{ + WaylandConfig *wlconfig = data; + + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !wlconfig->pointer.wlpointer) { + wlconfig->pointer.wlpointer = wl_seat_get_pointer(seat); + wl_pointer_set_user_data(wlconfig->pointer.wlpointer, wlconfig); + wl_pointer_add_listener(wlconfig->pointer.wlpointer, &pointer_listener, + wlconfig); + } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && wlconfig->pointer.wlpointer) { + if (wlconfig->seat_version >= WL_POINTER_RELEASE_SINCE_VERSION) + wl_pointer_release(wlconfig->pointer.wlpointer); + else + wl_pointer_destroy(wlconfig->pointer.wlpointer); + wlconfig->pointer.wlpointer = NULL; + } + + wl_display_dispatch_pending(wlconfig->display); + wl_display_flush(wlconfig->display); + + if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !wlconfig->keyboard) { + wlconfig->keyboard = wl_seat_get_keyboard(seat); + wl_keyboard_set_user_data(wlconfig->keyboard, wlconfig); + wl_keyboard_add_listener(wlconfig->keyboard, &keyboard_listener, + wlconfig); + } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && wlconfig->keyboard) { + if (wlconfig->seat_version >= WL_KEYBOARD_RELEASE_SINCE_VERSION) + wl_keyboard_release(wlconfig->keyboard); + else + wl_keyboard_destroy(wlconfig->keyboard); + wlconfig->keyboard = NULL; + } + +#if 0 + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->touch) { + input->touch = wl_seat_get_touch(seat); + wl_touch_set_user_data(input->touch, input); + wl_touch_add_listener(input->touch, &touch_listener, input); + } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->touch) { + if (input->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION) + wl_touch_release(input->touch); + else + wl_touch_destroy(input->touch); + input->touch = NULL; + } +#endif +} + +const struct wl_seat_listener seat_listener = { + seat_handle_capabilities, +}; + +@implementation WaylandServer (Seat) + +@end + diff --git a/Source/wayland/WaylandServer+Xdgshell.m b/Source/wayland/WaylandServer+Xdgshell.m new file mode 100755 index 0000000..1a9e806 --- /dev/null +++ b/Source/wayland/WaylandServer+Xdgshell.m @@ -0,0 +1,129 @@ +#include "wayland/WaylandServer.h" +#include +#include + +static void +xdg_surface_on_configure(void *data, struct xdg_surface *xdg_surface, + uint32_t serial) +{ + struct window *window = data; + + NSDebugLog(@"xdg_surface_on_configure: win=%d", window->window_id); + + if(window->terminated == YES) { + NSDebugLog(@"deleting window win=%d", window->window_id); + free(window); + return; + } + WaylandConfig *wlconfig = window->wlconfig; + + NSEvent *ev = nil; + NSWindow *nswindow = GSWindowWithNumber(window->window_id); + + NSDebugLog(@"Acknowledging surface configure %p %d (window_id=%d)", xdg_surface, serial, window->window_id); + xdg_surface_ack_configure(xdg_surface, serial); + window->configured = YES; + + + if(window->buffer_needs_attach) { + NSDebugLog(@"attach: win=%d toplevel", window->window_id); + wl_surface_attach(window->surface, window->buffer, 0, 0); + wl_surface_commit(window->surface); + } + + + if (wlconfig->pointer.focus && + wlconfig->pointer.focus->window_id == window->window_id) { + ev = [NSEvent otherEventWithType: NSAppKitDefined + location: NSZeroPoint + modifierFlags: 0 + timestamp: 0 + windowNumber: (int)window->window_id + context: GSCurrentContext() + subtype: GSAppKitWindowFocusIn + data1: 0 + data2: 0]; + + [nswindow sendEvent: ev]; + } + +#if 0 + struct window *window = data; + int moved = 0; + NSDebugLog(@"configure window=%d pos=%dx%d size=%dx%d", + window->window_id, x, y, width, height); + NSDebugLog(@"current values pos=%dx%d size=%dx%d", + window->pos_x, window->pos_y, window->width, window->height); + + if (!window->is_out && (window->pos_x != x || window->pos_y != y)) { + window->pos_x = x; + window->pos_y = y; + moved = 1; + } + + xdg_surface_ack_configure(window->xdg_surface, serial); + NSRect rect = NSMakeRect(0, 0, + window->width, window->height); + [window->instance flushwindowrect:rect :window->window_id]; + + wl_display_dispatch_pending(window->wlconfig->display); + wl_display_flush(window->wlconfig->display); + + if (moved) { + NSDebugLog(@"window moved, notifying AppKit"); + NSEvent *ev = nil; + NSWindow *nswindow = GSWindowWithNumber(window->window_id); + + ev = [NSEvent otherEventWithType: NSAppKitDefined + location: NSZeroPoint + modifierFlags: 0 + timestamp: 0 + windowNumber: (int)window->window_id + context: GSCurrentContext() + subtype: GSAppKitWindowMoved + data1: window->pos_x + data2: WaylandToNS(window, window->pos_y)]; + + [nswindow sendEvent: ev]; + } +#endif +} + +static void xdg_popup_configure(void *data, struct xdg_popup *xdg_popup, + int32_t x, int32_t y, int32_t width, int32_t height) { + struct window *window = data; + WaylandConfig *wlconfig = window->wlconfig; + + window->width = width; + window->height = height; + + +} + +static void xdg_popup_done(void *data, struct xdg_popup *xdg_popup) { + struct window *window = data; + WaylandConfig *wlconfig = window->wlconfig; + xdg_popup_destroy(xdg_popup); + + wl_surface_destroy(window->surface); +} + +static void wm_base_handle_ping(void *data, struct xdg_wm_base *xdg_wm_base, + uint32_t serial) +{ + xdg_wm_base_pong(xdg_wm_base, serial); +} + + +const struct xdg_surface_listener xdg_surface_listener = { + xdg_surface_on_configure, +}; + +const struct xdg_wm_base_listener wm_base_listener = { + .ping = wm_base_handle_ping, +}; + +const struct xdg_popup_listener xdg_popup_listener = { + .configure = xdg_popup_configure, + .popup_done = xdg_popup_done, +}; diff --git a/Source/wayland/WaylandServer.m b/Source/wayland/WaylandServer.m old mode 100644 new mode 100755 index a5ce15e..1285b69 --- a/Source/wayland/WaylandServer.m +++ b/Source/wayland/WaylandServer.m @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include #include @@ -46,622 +48,10 @@ #include "wayland/WaylandServer.h" -static void -handle_geometry(void *data, - struct wl_output *wl_output, - int x, int y, - int physical_width, - int physical_height, - int subpixel, - const char *make, - const char *model, - int transform) -{ - NSDebugLog(@"handle_geometry"); - struct output *output = data; - output->alloc_x = x; - output->alloc_y = y; - output->transform = transform; +extern const struct wl_output_listener output_listener; - if (output->make) - free(output->make); - output->make = strdup(make); - - if (output->model) - free(output->model); - output->model = strdup(model); -} - -static void -handle_done(void *data, - struct wl_output *wl_output) -{ - NSDebugLog(@"handle_done"); -} - -static void -handle_scale(void *data, - struct wl_output *wl_output, - int32_t scale) -{ - NSDebugLog(@"handle_scale"); - struct output *output = data; - - output->scale = scale; -} - -static void -handle_mode(void *data, - struct wl_output *wl_output, - uint32_t flags, - int width, - int height, - int refresh) -{ - NSDebugLog(@"handle_mode"); - struct output *output = data; - - if (flags & WL_OUTPUT_MODE_CURRENT) { - output->width = width; - output->height = height /*- 30*/; - NSDebugLog(@"handle_mode output=%dx%d", width, height); - /* XXX - Should we implement this? - if (display->output_configure_handler) - (*display->output_configure_handler) - (output, display->user_data); - */ - } -} - -static const struct wl_output_listener output_listener = { - handle_geometry, - handle_mode, - handle_done, - handle_scale -}; -/* -static void -destroy_output(WaylandConfig *wlconfig, uint32_t id) -{ - struct output *output; - - wl_list_for_each(output, &wlconfig->output_list, link) { - if (output->server_output_id == id) { - wl_output_destroy(output->output); - wl_list_remove(&output->link); - free(output); - wlconfig->output_count--; - break; - } - } -} -*/ -static void -pointer_handle_enter(void *data, struct wl_pointer *pointer, - uint32_t serial, struct wl_surface *surface, - wl_fixed_t sx_w, wl_fixed_t sy_w) -{ - NSDebugLog(@"pointer_handle_enter"); - if (!surface) { - NSDebugLog(@"no surface"); - return; - } - - WaylandConfig *wlconfig = data; - struct window *window = wl_surface_get_user_data(surface); - float sx = wl_fixed_to_double(sx_w); - float sy = wl_fixed_to_double(sy_w); - [GSCurrentServer() initializeMouseIfRequired]; - - wlconfig->pointer.x = sx; - wlconfig->pointer.y = sy; - wlconfig->pointer.focus = window; - - // FIXME: Send NSMouseEntered event. -} - -static void -pointer_handle_leave(void *data, struct wl_pointer *pointer, - uint32_t serial, struct wl_surface *surface) -{ - NSDebugLog(@"pointer_handle_leave"); - if (!surface) { - NSDebugLog(@"no surface"); - return; - } - - WaylandConfig *wlconfig = data; - struct window *window = wl_surface_get_user_data(surface); - [GSCurrentServer() initializeMouseIfRequired]; - - if (wlconfig->pointer.focus->window_id == window->window_id) { - wlconfig->pointer.focus = NULL; - wlconfig->pointer.serial = 0; - } - - // FIXME: Send NSMouseExited event. -} - -// triggered when the cursor is over a surface -static void -pointer_handle_motion(void *data, struct wl_pointer *pointer, - uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w) -{ - WaylandConfig *wlconfig = data; - struct window *window; - float sx = wl_fixed_to_double(sx_w); - float sy = wl_fixed_to_double(sy_w); - NSDebugLog(@"pointer_handle_motion: %fx%f", sx, sy); - - [GSCurrentServer() initializeMouseIfRequired]; - - if (wlconfig->pointer.focus && wlconfig->pointer.serial) { - window = wlconfig->pointer.focus; - NSEvent *event; - NSEventType eventType; - NSPoint eventLocation; - NSGraphicsContext *gcontext; - unsigned int eventFlags; - float deltaX = sx - window->wlconfig->pointer.x; - float deltaY = sy - window->wlconfig->pointer.y; - - NSDebugLog(@"obtaining locations: wayland=%fx%f pointer=%fx%f", - sx, sy, window->wlconfig->pointer.x, window->wlconfig->pointer.y); - - gcontext = GSCurrentContext(); - eventLocation = NSMakePoint(sx, - window->height - sy); - - eventFlags = 0; - eventType = NSLeftMouseDragged; - - NSDebugLog(@"sending pointer delta: %fx%f, window=%d", deltaX, deltaY, window->window_id); - - event = [NSEvent mouseEventWithType: eventType - location: eventLocation - modifierFlags: eventFlags - timestamp: (NSTimeInterval) time / 1000.0 - windowNumber: (int)window->window_id - context: gcontext - eventNumber: time - clickCount: 1 - pressure: 1.0 - buttonNumber: 0 /* FIXME */ - deltaX: deltaX - deltaY: deltaY - deltaZ: 0.]; - - [GSCurrentServer() postEvent: event atStart: NO]; - } - - wlconfig->pointer.x = sx; - wlconfig->pointer.y = sy; -} - -static void -pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial, - uint32_t time, uint32_t button, uint32_t state_w) -{ - NSDebugLog(@"pointer_handle_button: button=%d", button); - WaylandConfig *wlconfig = data; - NSEvent *event; - NSEventType eventType; - NSPoint eventLocation; - NSGraphicsContext *gcontext; - unsigned int eventFlags; - float deltaX = 0.0; - float deltaY = 0.0; - int clickCount = 1; - int tick; - int buttonNumber; - enum wl_pointer_button_state state = state_w; - struct window *window = wlconfig->pointer.focus; - - [GSCurrentServer() initializeMouseIfRequired]; - - gcontext = GSCurrentContext(); - eventLocation = NSMakePoint(wlconfig->pointer.x, - window->height - wlconfig->pointer.y); - eventFlags = 0; - - if (state == WL_POINTER_BUTTON_STATE_PRESSED) { - if (button == wlconfig->pointer.last_click_button && - time - wlconfig->pointer.last_click_time < 300 && - abs(wlconfig->pointer.x - wlconfig->pointer.last_click_x) < 3 && - abs(wlconfig->pointer.y - wlconfig->pointer.last_click_y) < 3) { - NSDebugLog(@"handle_button HIT: b=%d t=%d x=%f y=%f", button, time, wlconfig->pointer.x, wlconfig->pointer.y); - wlconfig->pointer.last_click_time = 0; - clickCount++; - } else { - NSDebugLog(@"handle_button MISS: b=%d t=%d x=%f y=%f", button, time, wlconfig->pointer.x, wlconfig->pointer.y); - wlconfig->pointer.last_click_button = button; - wlconfig->pointer.last_click_time = time; - wlconfig->pointer.last_click_x = wlconfig->pointer.x; - wlconfig->pointer.last_click_y = wlconfig->pointer.y; - } - - switch (button) { - case BTN_LEFT: - eventType = NSLeftMouseDown; - break; - case BTN_RIGHT: - eventType = NSRightMouseDown; - break; - case BTN_MIDDLE: - eventType = NSOtherMouseDown; - break; - // TODO: handle BTN_SIDE, BTN_EXTRA, BTN_FORWARD, BTN_BACK and other - // constants in libinput. - // We may just want to send NSOtherMouseDown and populate buttonNumber - // with the libinput constant? - } - wlconfig->pointer.serial = serial; - } else if (state == WL_POINTER_BUTTON_STATE_RELEASED) { - switch (button) { - case BTN_LEFT: - eventType = NSLeftMouseUp; - break; - case BTN_RIGHT: - eventType = NSRightMouseUp; - break; - case BTN_MIDDLE: - eventType = NSOtherMouseUp; - break; - } - wlconfig->pointer.serial = 0; - } else { - NSDebugLog(@"unhandled wayland pointer state 0x%02x", state); - return; - } - - /* FIXME: unlike in _motion and _axis handlers, the argument used in _button - is the "serial" of the event, not passed and unavailable in _motion and - _axis handlers. Is it allowed to pass "serial" as the eventNumber: in - _button handler, but "time" as the eventNumber: in the _motion and _axis - handlers? */ - tick = serial; - - NSDebugLog(@"sending pointer event at: %fx%f, window=%d", wlconfig->pointer.x, wlconfig->pointer.y, window->window_id); - - /* FIXME: X11 backend uses the XGetPointerMapping()-returned values from - its map_return argument as constants for buttonNumber. As the variant - with buttonNumber: seems to be a GNUstep extension, and the value - internal, it might be ok to just provide libinput constant as we're doing - here. If this is truly correct, please update this comment to document - the correctness of doing so. */ - buttonNumber = button; - - event = [NSEvent mouseEventWithType: eventType - location: eventLocation - modifierFlags: eventFlags - timestamp: (NSTimeInterval) time / 1000.0 - windowNumber: (int)window->window_id - context: gcontext - eventNumber: tick - clickCount: clickCount - pressure: 1.0 - buttonNumber: buttonNumber - deltaX: deltaX /* FIXME unused */ - deltaY: deltaY /* FIXME unused */ - deltaZ: 0.]; - - [GSCurrentServer() postEvent: event atStart: NO]; -} - -static void -pointer_handle_axis(void *data, struct wl_pointer *pointer, - uint32_t time, uint32_t axis, wl_fixed_t value) -{ - NSDebugLog(@"pointer_handle_axis: axis=%d value=%g", axis, wl_fixed_to_double(value)); - WaylandConfig *wlconfig = data; - NSEvent *event; - NSEventType eventType; - NSPoint eventLocation; - NSGraphicsContext *gcontext; - unsigned int eventFlags; - float deltaX = 0.0; - float deltaY = 0.0; - int clickCount = 1; - int buttonNumber; - - struct window *window = wlconfig->pointer.focus; - - [GSCurrentServer() initializeMouseIfRequired]; - - gcontext = GSCurrentContext(); - eventLocation = NSMakePoint(wlconfig->pointer.x, - window->height - wlconfig->pointer.y); - eventFlags = 0; - - /* FIXME: we should get axis_source out of wl_pointer; however, the wl_pointer - is not defined in wayland-client.h. How does one get the axis_source out of - it to confirm the source is the physical mouse wheel? */ -#if 0 - if (pointer->axis_source != WL_POINTER_AXIS_SOURCE_WHEEL) - return; -#endif - - float mouse_scroll_multiplier = wlconfig->mouse_scroll_multiplier; - /* For smooth-scroll events, we're not doing any cross-event or delta - calculations, as is done in button event handling. */ - switch(axis) - { - case WL_POINTER_AXIS_VERTICAL_SCROLL: - eventType = NSScrollWheel; - deltaY = wl_fixed_to_double(value) * wlconfig->mouse_scroll_multiplier; - case WL_POINTER_AXIS_HORIZONTAL_SCROLL: - eventType = NSScrollWheel; - deltaX = wl_fixed_to_double(value) * wlconfig->mouse_scroll_multiplier; - } - - NSDebugLog(@"sending pointer scroll at: %fx%f, value %fx%f, window=%d", wlconfig->pointer.x, wlconfig->pointer.y, deltaX, deltaY, window->window_id); - - /* FIXME: X11 backend uses the XGetPointerMapping()-returned values from - its map_return argument as constants for buttonNumber. As the variant - with buttonNumber: seems to be a GNUstep extension, and the value - internal, it might be ok to just not provide any value here. - If this is truly correct, please update this comment to document - the correctness of doing so. */ - buttonNumber = 0; - - event = [NSEvent mouseEventWithType: eventType - location: eventLocation - modifierFlags: eventFlags - timestamp: (NSTimeInterval) time / 1000.0 - windowNumber: (int)window->window_id - context: gcontext - eventNumber: time - clickCount: clickCount - pressure: 1.0 - buttonNumber: buttonNumber - deltaX: deltaX - deltaY: deltaY - deltaZ: 0.]; - - [GSCurrentServer() postEvent: event atStart: NO]; -} - -static const struct wl_pointer_listener pointer_listener = { - pointer_handle_enter, - pointer_handle_leave, - pointer_handle_motion, - pointer_handle_button, - pointer_handle_axis, -}; - -static void -keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, - uint32_t format, int fd, uint32_t size) -{ - NSDebugLog(@"keyboard_handle_keymap"); - WaylandConfig *wlconfig = data; - struct xkb_keymap *keymap; - struct xkb_state *state; - char *map_str; - - if (!data) { - close(fd); - return; - } - - if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { - close(fd); - return; - } - - map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); - if (map_str == MAP_FAILED) { - close(fd); - return; - } - - wlconfig->xkb_context = xkb_context_new(0); - if (wlconfig->xkb_context == NULL) { - fprintf(stderr, "Failed to create XKB context\n"); - return; - } - - keymap = xkb_keymap_new_from_string(wlconfig->xkb_context, - map_str, - XKB_KEYMAP_FORMAT_TEXT_V1, - 0); - munmap(map_str, size); - close(fd); - - if (!keymap) { - fprintf(stderr, "failed to compile keymap\n"); - return; - } - - state = xkb_state_new(keymap); - if (!state) { - fprintf(stderr, "failed to create XKB state\n"); - xkb_keymap_unref(keymap); - return; - } - - xkb_keymap_unref(wlconfig->xkb.keymap); - xkb_state_unref(wlconfig->xkb.state); - wlconfig->xkb.keymap = keymap; - wlconfig->xkb.state = state; - - wlconfig->xkb.control_mask = - 1 << xkb_keymap_mod_get_index(wlconfig->xkb.keymap, "Control"); - wlconfig->xkb.alt_mask = - 1 << xkb_keymap_mod_get_index(wlconfig->xkb.keymap, "Mod1"); - wlconfig->xkb.shift_mask = - 1 << xkb_keymap_mod_get_index(wlconfig->xkb.keymap, "Shift"); -} - -static void -keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, - uint32_t serial, struct wl_surface *surface, - struct wl_array *keys) -{ - NSDebugLog(@"keyboard_handle_enter"); -} - -static void -keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, - uint32_t serial, struct wl_surface *surface) -{ - NSDebugLog(@"keyboard_handle_leave"); -} - -static void -keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, - uint32_t serial, uint32_t mods_depressed, - uint32_t mods_latched, uint32_t mods_locked, - uint32_t group) -{ - NSDebugLog(@"keyboard_handle_modifiers"); - WaylandConfig *wlconfig = data; - xkb_mod_mask_t mask; - - /* If we're not using a keymap, then we don't handle PC-style modifiers */ - if (!wlconfig->xkb.keymap) - return; - - xkb_state_update_mask(wlconfig->xkb.state, mods_depressed, mods_latched, - mods_locked, 0, 0, group); - mask = xkb_state_serialize_mods(wlconfig->xkb.state, - XKB_STATE_MODS_DEPRESSED | - XKB_STATE_MODS_LATCHED); - wlconfig->modifiers = 0; - if (mask & wlconfig->xkb.control_mask) - wlconfig->modifiers |= NSCommandKeyMask; - if (mask & wlconfig->xkb.alt_mask) - wlconfig->modifiers |= NSAlternateKeyMask; - if (mask & wlconfig->xkb.shift_mask) - wlconfig->modifiers |= NSShiftKeyMask; -} - -static void -keyboard_handle_key(void *data, struct wl_keyboard *keyboard, - uint32_t serial, uint32_t time, uint32_t key, - uint32_t state_w) -{ - NSDebugLog(@"keyboard_handle_key: %d", key); - WaylandConfig *wlconfig = data; - uint32_t code, num_syms; - enum wl_keyboard_key_state state = state_w; - const xkb_keysym_t *syms; - xkb_keysym_t sym; - struct window *window = wlconfig->pointer.focus; - - if (!window) - return; - - code = 0; - if (key == 28) { - sym = NSCarriageReturnCharacter; - } else if (key == 14) { - sym = NSDeleteCharacter; - } else { - code = key + 8; - - num_syms = xkb_state_key_get_syms(wlconfig->xkb.state, code, &syms); - - sym = XKB_KEY_NoSymbol; - if (num_syms == 1) - sym = syms[0]; - } - - NSString *s = [NSString stringWithUTF8String: &sym]; - NSEventType eventType; - - if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { - eventType = NSKeyDown; - } else { - eventType = NSKeyUp; - } - - NSEvent *ev = [NSEvent keyEventWithType: eventType - location: NSZeroPoint - modifierFlags: wlconfig->modifiers - timestamp: time / 1000.0 - windowNumber: window->window_id - context: GSCurrentContext() - characters: s - charactersIgnoringModifiers: s - isARepeat: NO - keyCode: code]; - - [GSCurrentServer() postEvent: ev atStart: NO]; - - NSDebugLog(@"keyboard_handle_key: %@", s); -} - -static void -keyboard_handle_repeat_info(void *data, struct wl_keyboard *keyboard, - int32_t rate, int32_t delay) -{ - NSDebugLog(@"keyboard_handle_repeat_info"); -} - -static const struct wl_keyboard_listener keyboard_listener = { - keyboard_handle_keymap, - keyboard_handle_enter, - keyboard_handle_leave, - keyboard_handle_key, - keyboard_handle_modifiers, - keyboard_handle_repeat_info -}; - -static void -seat_handle_capabilities(void *data, struct wl_seat *seat, - enum wl_seat_capability caps) -{ - WaylandConfig *wlconfig = data; - - if ((caps & WL_SEAT_CAPABILITY_POINTER) && !wlconfig->pointer.wlpointer) { - wlconfig->pointer.wlpointer = wl_seat_get_pointer(seat); - wl_pointer_set_user_data(wlconfig->pointer.wlpointer, wlconfig); - wl_pointer_add_listener(wlconfig->pointer.wlpointer, &pointer_listener, - wlconfig); - } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && wlconfig->pointer.wlpointer) { - if (wlconfig->seat_version >= WL_POINTER_RELEASE_SINCE_VERSION) - wl_pointer_release(wlconfig->pointer.wlpointer); - else - wl_pointer_destroy(wlconfig->pointer.wlpointer); - wlconfig->pointer.wlpointer = NULL; - } - - wl_display_dispatch_pending(wlconfig->display); - wl_display_flush(wlconfig->display); - - if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !wlconfig->keyboard) { - wlconfig->keyboard = wl_seat_get_keyboard(seat); - wl_keyboard_set_user_data(wlconfig->keyboard, wlconfig); - wl_keyboard_add_listener(wlconfig->keyboard, &keyboard_listener, - wlconfig); - } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && wlconfig->keyboard) { - if (wlconfig->seat_version >= WL_KEYBOARD_RELEASE_SINCE_VERSION) - wl_keyboard_release(wlconfig->keyboard); - else - wl_keyboard_destroy(wlconfig->keyboard); - wlconfig->keyboard = NULL; - } - -#if 0 - if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->touch) { - input->touch = wl_seat_get_touch(seat); - wl_touch_set_user_data(input->touch, input); - wl_touch_add_listener(input->touch, &touch_listener, input); - } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->touch) { - if (input->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION) - wl_touch_release(input->touch); - else - wl_touch_destroy(input->touch); - input->touch = NULL; - } -#endif -} - -static const struct wl_seat_listener seat_listener = { - seat_handle_capabilities, -}; +extern const struct wl_seat_listener seat_listener; static void shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) @@ -672,158 +62,14 @@ struct wl_shm_listener shm_listener = { shm_format }; -#define XDG_SHELL -static void -xdg_surface_on_configure(void *data, struct xdg_surface *xdg_surface, - uint32_t serial) -{ - struct window *window = data; - WaylandConfig *wlconfig = window->wlconfig; - NSDebugLog(@"xdg_surface_on_configure: win=%d", window->window_id); +extern const struct xdg_surface_listener xdg_surface_listener; - NSEvent *ev = nil; - NSWindow *nswindow = GSWindowWithNumber(window->window_id); +extern const struct xdg_wm_base_listener wm_base_listener; - NSDebugLog(@"Acknowledging surface configure %p %d (window_id=%d)", xdg_surface, serial, window->window_id); - xdg_surface_ack_configure(xdg_surface, serial); - window->configured = YES; +extern const struct zwlr_layer_surface_v1_listener layer_surface_listener; - - if(window->buffer_needs_attach) { - NSDebugLog(@"attach: win=%d toplevel", window->window_id); - wl_surface_attach(window->surface, window->buffer, 0, 0); - wl_surface_commit(window->surface); - } - - - if (wlconfig->pointer.focus && - wlconfig->pointer.focus->window_id == window->window_id) { - ev = [NSEvent otherEventWithType: NSAppKitDefined - location: NSZeroPoint - modifierFlags: 0 - timestamp: 0 - windowNumber: (int)window->window_id - context: GSCurrentContext() - subtype: GSAppKitWindowFocusIn - data1: 0 - data2: 0]; - - [nswindow sendEvent: ev]; - } - -#if 0 - struct window *window = data; - int moved = 0; - NSDebugLog(@"configure window=%d pos=%dx%d size=%dx%d", - window->window_id, x, y, width, height); - NSDebugLog(@"current values pos=%dx%d size=%dx%d", - window->pos_x, window->pos_y, window->width, window->height); - - if (!window->is_out && (window->pos_x != x || window->pos_y != y)) { - window->pos_x = x; - window->pos_y = y; - moved = 1; - } - - xdg_surface_ack_configure(window->xdg_surface, serial); - NSRect rect = NSMakeRect(0, 0, - window->width, window->height); - [window->instance flushwindowrect:rect :window->window_id]; - - wl_display_dispatch_pending(window->wlconfig->display); - wl_display_flush(window->wlconfig->display); - - if (moved) { - NSDebugLog(@"window moved, notifying AppKit"); - NSEvent *ev = nil; - NSWindow *nswindow = GSWindowWithNumber(window->window_id); - - ev = [NSEvent otherEventWithType: NSAppKitDefined - location: NSZeroPoint - modifierFlags: 0 - timestamp: 0 - windowNumber: (int)window->window_id - context: GSCurrentContext() - subtype: GSAppKitWindowMoved - data1: window->pos_x - data2: WaylandToNS(window, window->pos_y)]; - - [nswindow sendEvent: ev]; - } -#endif -} - -static const struct xdg_surface_listener xdg_surface_listener = { - xdg_surface_on_configure, -}; -static void wm_base_handle_ping(void *data, struct xdg_wm_base *xdg_wm_base, - uint32_t serial) -{ - xdg_wm_base_pong(xdg_wm_base, serial); -} - -static const struct xdg_wm_base_listener wm_base_listener = { - .ping = wm_base_handle_ping, -}; - -static void layer_surface_configure(void *data, - struct zwlr_layer_surface_v1 *surface, - uint32_t serial, uint32_t w, uint32_t h) { - - NSDebugLog(@"configure layer"); - struct window *window = data; - WaylandConfig *wlconfig = window->wlconfig; - zwlr_layer_surface_v1_ack_configure(surface, serial); - window->configured = YES; - if(window->buffer_needs_attach) { - NSDebugLog(@"attach: win=%d layer", window->window_id); - wl_surface_attach(window->surface, window->buffer, 0, 0); - wl_surface_commit(window->surface); - } - -} - -static void layer_surface_closed(void *data, - struct zwlr_layer_surface_v1 *surface) { - struct window *window = data; - WaylandConfig *wlconfig = window->wlconfig; - NSDebugLog(@"layer_surface_closed %d", window->window_id); - //zwlr_layer_surface_v1_destroy(surface); - wl_surface_destroy(window->surface); - window->surface = NULL; - window->configured = NO; - window->layer_surface = NULL; -} - -struct zwlr_layer_surface_v1_listener layer_surface_listener = { - .configure = layer_surface_configure, - .closed = layer_surface_closed, -}; - -static void xdg_popup_configure(void *data, struct xdg_popup *xdg_popup, - int32_t x, int32_t y, int32_t width, int32_t height) { - struct window *window = data; - WaylandConfig *wlconfig = window->wlconfig; - - window->width = width; - window->height = height; - - -} - -static void xdg_popup_done(void *data, struct xdg_popup *xdg_popup) { - struct window *window = data; - WaylandConfig *wlconfig = window->wlconfig; - xdg_popup_destroy(xdg_popup); - - wl_surface_destroy(window->surface); -} - -static const struct xdg_popup_listener xdg_popup_listener = { - .configure = xdg_popup_configure, - .popup_done = xdg_popup_done, -}; +extern const struct xdg_popup_listener xdg_popup_listener; static void @@ -968,7 +214,7 @@ int NSToWayland(struct window *window, int ns_y) forMode: (NSString*)mode { if (type == ET_RDESC){ - NSDebugLog(@"receivedEvent ET_RDESC"); +// NSDebugLog(@"receivedEvent ET_RDESC"); if (wl_display_dispatch(wlconfig->display) == -1) { [NSException raise: NSWindowServerCommunicationException format: @"Connection to Wayland Server lost"]; @@ -1128,30 +374,26 @@ int NSToWayland(struct window *window, int ns_y) window->toplevel = NULL; window->configured = NO; window->buffer_needs_attach = NO; + window->terminated = NO; #if 0 if (style & NSMiniWindowMask) { - NSDebugLog(@"window id=%d will be a NSMiniWindowMask", window->window_id); + NSDebugLog(@"----> window id=%d will be a NSMiniWindowMask", window->window_id); } else if (style & NSIconWindowMask) { - NSDebugLog(@"window id=%d will be a NSIconWindowMask", window->window_id); + NSDebugLog(@"----> window id=%d will be a NSIconWindowMask", window->window_id); } else if (style & NSBorderlessWindowMask) { - NSDebugLog(@"window id=%d will be a NSBorderlessWindowMask", window->window_id); + NSDebugLog(@"----> window id=%d will be a NSBorderlessWindowMask", window->window_id); } else { - NSDebugLog(@"window id=%d will be ordinary", window->window_id); + NSDebugLog(@"----> window id=%d will be ordinary", window->window_id); } #endif + // FIXME is this needed? if (window->pos_x < 0) { window->pos_x = 0; altered = 1; } -#if 0 - if (window->pos_y < 31) { - window->pos_y = 31; - altered = 1; - } -#endif NSDebugLog(@"creating new window with id=%d: pos=%fx%f, size=%fx%f", window->window_id, window->pos_x, window->pos_y, @@ -1165,6 +407,7 @@ int NSToWayland(struct window *window, int ns_y) // creates a buffer for the window [self _setWindowOwnedByServer: (int)window->window_id]; + if (altered) { NSEvent *ev = [NSEvent otherEventWithType: NSAppKitDefined location: NSZeroPoint @@ -1184,8 +427,9 @@ int NSToWayland(struct window *window, int ns_y) } - (void) makeWindowTopLevelIfNeeded: (int) win { - NSDebugLog(@"makeWindowTopLevelIfNeeded"); + NSDebugLog(@"makeWindowTopLevelIfNeeded %d", win); struct window *window = get_window_with_id(wlconfig, win); + if(window->toplevel != NULL || window->layer_surface != NULL) { return; } @@ -1229,8 +473,7 @@ int NSToWayland(struct window *window, int ns_y) wl_surface_destroy(window->surface); wl_buffer_destroy(window->buffer); wl_list_remove(&window->link); - - free(window); + window->terminated = YES; } - (int) nativeWindow: (void *)winref @@ -1271,7 +514,8 @@ int NSToWayland(struct window *window, int ns_y) - (void) miniwindow: (int) win { NSDebugLog(@"miniwindow"); - [self orderwindow: NSWindowOut :0 :win]; +// xdg_toplevel_set_minimized(window->toplevel); +// [self orderwindow: NSWindowOut :0 :win]; } - (void) setWindowdevice: (int) winId forContext: (NSGraphicsContext *)ctxt @@ -1362,7 +606,7 @@ int NSToWayland(struct window *window, int ns_y) WaylandConfig *config = window->wlconfig; if(window->toplevel == NULL && !window->layer_surface) { - [self makeWindowTopLevelIfNeeded: win]; + [self makeWindowShell: win]; } NSDebugLog(@"placewindow: oldpos=%fx%f", window->pos_x, window->pos_y); NSDebugLog(@"placewindow: oldsize=%fx%f", window->width, window->height); @@ -1440,7 +684,6 @@ int NSToWayland(struct window *window, int ns_y) NSDebugLog(@"placewindow: newpos=%fx%f", window->pos_x, window->pos_y); NSDebugLog(@"placewindow: newsize=%fx%f", window->width, window->height); - } } - (NSRect) windowbounds: (int) win @@ -1524,6 +767,7 @@ int NSToWayland(struct window *window, int ns_y) - (void) makeWindowShell: (int) win { + NSLog(@"makeWindowShell %d", win); struct window *window = get_window_with_id(wlconfig, win); switch(window->level) { case NSMainMenuWindowLevel: @@ -1570,7 +814,8 @@ int NSToWayland(struct window *window, int ns_y) - (int) windowlevel: (int) win { NSDebugLog(@"windowlevel: %d", win); - return 0; + struct window *window = get_window_with_id(wlconfig, win); + return window->level; } - (int) windowdepth: (int) win @@ -1596,7 +841,7 @@ int NSToWayland(struct window *window, int ns_y) - (void) flushwindowrect: (NSRect)rect : (int) win { - NSDebugLog(@"flushwindowrect: %d %fx%f", win, NSWidth(rect), NSHeight(rect)); +// NSDebugLog(@"flushwindowrect: %d %fx%f", win, NSWidth(rect), NSHeight(rect)); struct window *window = get_window_with_id(wlconfig, win); [[GSCurrentContext() class] handleExposeRect: rect forDriver: window->wcs]; @@ -1636,122 +881,6 @@ int NSToWayland(struct window *window, int ns_y) NSDebugLog(@"setshadow"); } -- (NSPoint) mouselocation -{ - int aScreen = -1; - struct output *output; - - NSDebugLog(@"mouselocation"); - - // FIXME: find a cleaner way to get the first element of a wl_list - wl_list_for_each(output, &wlconfig->output_list, link) { - aScreen = output->server_output_id; - break; - } - if (aScreen < 0) - // No outputs in the wl_list. - return NSZeroPoint; - - return [self mouseLocationOnScreen: aScreen window: NULL]; -} - -- (NSPoint) mouseLocationOnScreen: (int)aScreen window: (int *)win -{ - NSDebugLog(@"mouseLocationOnScreen: %d %fx%f", win, - wlconfig->pointer.x, wlconfig->pointer.y); - struct window *window = wlconfig->pointer.focus; - struct output *output; - float x; - float y; - - /*if (wlconfig->pointer.serial) { - NSDebugLog(@"captured"); - x = wlconfig->pointer.captured_x; - y = wlconfig->pointer.captured_y; - } else*/ { - NSDebugLog(@"NOT captured"); - x = wlconfig->pointer.x; - y = wlconfig->pointer.y; - - if (window) { - x += window->pos_x; - y += window->pos_y; - if (win) { - *win = &window->window_id; - } - } - } - - wl_list_for_each(output, &wlconfig->output_list, link) { - if (output->server_output_id == aScreen) { - y = output->height - y; - break; - } - } - - NSDebugLog(@"mouseLocationOnScreen: returning %fx%f", x, y); - - return NSMakePoint(x, y); -} - -- (BOOL) capturemouse: (int) win -{ - NSDebugLog(@"capturemouse: %d", win); - return NO; -} - -- (void) releasemouse -{ - NSDebugLog(@"releasemouse"); -} - -- (void) setMouseLocation: (NSPoint)mouseLocation onScreen: (int)aScreen -{ - NSDebugLog(@"setMouseLocation"); -} - -- (void) hidecursor -{ - NSDebugLog(@"hidecursor"); -} - -- (void) showcursor -{ - NSDebugLog(@"showcursor"); -} - -- (void) standardcursor: (int) style : (void**) cid -{ - NSDebugLog(@"standardcursor"); -} - -- (void) imagecursor: (NSPoint)hotp : (NSImage *) image : (void**) cid -{ - NSDebugLog(@"imagecursor"); -} - -- (void) setcursorcolor: (NSColor *)fg : (NSColor *)bg : (void*) cid -{ - NSLog(@"Call to obsolete method -setcursorcolor:::"); - [self recolorcursor: fg : bg : cid]; - [self setcursor: cid]; -} - -- (void) recolorcursor: (NSColor *)fg : (NSColor *)bg : (void*) cid -{ - NSDebugLog(@"recolorcursor"); -} - -- (void) setcursor: (void*) cid -{ - NSDebugLog(@"setcursor"); -} - -- (void) freecursor: (void*) cid -{ - NSDebugLog(@"freecursor"); -} - - (void) setParentWindow: (int)parentWin forChildWindow: (int)childWin { @@ -1775,37 +904,7 @@ int NSToWayland(struct window *window, int ns_y) wl_display_flush(wlconfig->display); } -- (void) setIgnoreMouse: (BOOL)ignoreMouse : (int)win -{ - NSDebugLog(@"setIgnoreMouse"); -} -- (void) initializeMouseIfRequired -{ - if (!_mouseInitialized) - [self initializeMouse]; -} - -- (void) initializeMouse -{ - _mouseInitialized = YES; - - [self mouseOptionsChanged: nil]; - [[NSDistributedNotificationCenter defaultCenter] - addObserver: self - selector: @selector(mouseOptionsChanged:) - name: NSUserDefaultsDidChangeNotification - object: nil]; -} - -- (void) mouseOptionsChanged: (NSNotification *)aNotif -{ - NSUserDefaults *defs = [NSUserDefaults standardUserDefaults]; - - wlconfig->mouse_scroll_multiplier = [defs integerForKey:@"GSMouseScrollMultiplier"]; - if (wlconfig->mouse_scroll_multiplier < 0.0001f) - wlconfig->mouse_scroll_multiplier = 1.0f; -} @end