mirror of
https://github.com/gnustep/libs-back.git
synced 2025-02-23 03:41:04 +00:00
wayland backend: refactor code, split into categories
This commit is contained in:
parent
7b87b268e3
commit
30ceacc90d
9 changed files with 1001 additions and 928 deletions
5
Headers/wayland/WaylandServer.h
Normal file → Executable file
5
Headers/wayland/WaylandServer.h
Normal file → Executable file
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
446
Source/wayland/WaylandServer+Cursor.m
Executable file
446
Source/wayland/WaylandServer+Cursor.m
Executable file
|
@ -0,0 +1,446 @@
|
|||
#include "wayland/WaylandServer.h"
|
||||
#include <AppKit/NSEvent.h>
|
||||
#include <AppKit/NSApplication.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
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
|
192
Source/wayland/WaylandServer+Keyboard.m
Executable file
192
Source/wayland/WaylandServer+Keyboard.m
Executable file
|
@ -0,0 +1,192 @@
|
|||
#include "wayland/WaylandServer.h"
|
||||
#include <AppKit/NSEvent.h>
|
||||
#include <AppKit/NSApplication.h>
|
||||
#include <linux/input.h>
|
||||
#include <AppKit/NSText.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
||||
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
|
||||
|
38
Source/wayland/WaylandServer+Layershell.m
Executable file
38
Source/wayland/WaylandServer+Layershell.m
Executable file
|
@ -0,0 +1,38 @@
|
|||
#include "wayland/WaylandServer.h"
|
||||
#include <AppKit/NSEvent.h>
|
||||
#include <AppKit/NSApplication.h>
|
||||
|
||||
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,
|
||||
};
|
||||
|
96
Source/wayland/WaylandServer+Output.m
Executable file
96
Source/wayland/WaylandServer+Output.m
Executable file
|
@ -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
|
||||
};
|
64
Source/wayland/WaylandServer+Seat.m
Executable file
64
Source/wayland/WaylandServer+Seat.m
Executable file
|
@ -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
|
||||
|
129
Source/wayland/WaylandServer+Xdgshell.m
Executable file
129
Source/wayland/WaylandServer+Xdgshell.m
Executable file
|
@ -0,0 +1,129 @@
|
|||
#include "wayland/WaylandServer.h"
|
||||
#include <AppKit/NSEvent.h>
|
||||
#include <AppKit/NSApplication.h>
|
||||
|
||||
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,
|
||||
};
|
953
Source/wayland/WaylandServer.m
Normal file → Executable file
953
Source/wayland/WaylandServer.m
Normal file → Executable file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue