mirror of
https://github.com/gnustep/libs-back.git
synced 2025-04-26 01:11:00 +00:00
442 lines
13 KiB
Mathematica
442 lines
13 KiB
Mathematica
|
#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)
|
||
|
{
|
||
|
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)
|
||
|
{
|
||
|
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);
|
||
|
|
||
|
[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)
|
||
|
{
|
||
|
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) {
|
||
|
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
|