2021-11-15 22:05:12 +00:00
|
|
|
/*
|
|
|
|
WaylandServer - Cursor Handling
|
|
|
|
|
|
|
|
Copyright (C) 2020 Free Software Foundation, Inc.
|
|
|
|
|
|
|
|
Author: Riccardo Canalicchio <riccardo.canalicchio(at)gmail.com>
|
|
|
|
Date: November 2021
|
|
|
|
|
|
|
|
This file is part of the GNU Objective C Backend Library.
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Lesser General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
|
|
License along with this library; see the file COPYING.LIB.
|
|
|
|
If not, see <http://www.gnu.org/licenses/> or write to the
|
|
|
|
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
2021-10-25 11:16:22 +00:00
|
|
|
#include "wayland/WaylandServer.h"
|
|
|
|
#include <AppKit/NSEvent.h>
|
2021-11-06 12:09:26 +00:00
|
|
|
#include <AppKit/NSView.h>
|
|
|
|
#include <AppKit/NSWindow.h>
|
|
|
|
#include <AppKit/GSWindowDecorationView.h>
|
|
|
|
#include <AppKit/GSTheme.h>
|
2021-10-25 11:16:22 +00:00
|
|
|
#include <AppKit/NSApplication.h>
|
|
|
|
#include <linux/input.h>
|
|
|
|
|
|
|
|
static void
|
2021-11-15 22:05:12 +00:00
|
|
|
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)
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
if (!surface)
|
|
|
|
{
|
|
|
|
NSDebugLog(@"no surface");
|
|
|
|
return;
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
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];
|
2021-10-25 11:16:22 +00:00
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
wlconfig->pointer.x = sx;
|
|
|
|
wlconfig->pointer.y = sy;
|
|
|
|
wlconfig->pointer.focus = window;
|
2021-10-25 11:16:22 +00:00
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
// FIXME: Send NSMouseEntered event.
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-11-15 22:05:12 +00:00
|
|
|
pointer_handle_leave(void *data, struct wl_pointer *pointer, uint32_t serial,
|
|
|
|
struct wl_surface *surface)
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
if (!surface)
|
|
|
|
{
|
|
|
|
NSDebugLog(@"no surface");
|
|
|
|
return;
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
WaylandConfig *wlconfig = data;
|
|
|
|
struct window *window = wl_surface_get_user_data(surface);
|
|
|
|
[GSCurrentServer() initializeMouseIfRequired];
|
2021-10-25 11:16:22 +00:00
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
if (wlconfig->pointer.focus->window_id == window->window_id)
|
|
|
|
{
|
|
|
|
wlconfig->pointer.focus = NULL;
|
|
|
|
wlconfig->pointer.serial = 0;
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
// FIXME: Send NSMouseExited event.
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// triggered when the cursor is over a surface
|
|
|
|
static void
|
2021-11-15 22:05:12 +00:00
|
|
|
pointer_handle_motion(void *data, struct wl_pointer *pointer, uint32_t time,
|
|
|
|
wl_fixed_t sx_w, wl_fixed_t sy_w)
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
WaylandConfig *wlconfig = data;
|
|
|
|
struct window *window;
|
|
|
|
if (window->moving || window->resizing)
|
|
|
|
{
|
|
|
|
return;
|
2021-11-06 12:09:26 +00:00
|
|
|
}
|
2021-11-15 22:05:12 +00:00
|
|
|
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];
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
wlconfig->pointer.x = sx;
|
|
|
|
wlconfig->pointer.y = sy;
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
|
|
|
|
uint32_t time, uint32_t button, uint32_t state_w)
|
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
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;
|
2021-11-06 12:09:26 +00:00
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
[GSCurrentServer() initializeMouseIfRequired];
|
2021-11-06 12:09:26 +00:00
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
gcontext = GSCurrentContext();
|
|
|
|
eventLocation
|
|
|
|
= NSMakePoint(wlconfig->pointer.x, window->height - wlconfig->pointer.y);
|
|
|
|
eventFlags = 0;
|
|
|
|
|
|
|
|
if (window->toplevel)
|
|
|
|
{
|
|
|
|
// if the window is a toplevel we check if the event is for resizing or
|
|
|
|
// moving the window these actions are delegated to the compositor and
|
|
|
|
// therefore we skip forwarding the events to the NSWindow / NSView
|
|
|
|
|
|
|
|
NSWindow *nswindow = GSWindowWithNumber(window->window_id);
|
|
|
|
if (nswindow != nil)
|
|
|
|
{
|
|
|
|
GSWindowDecorationView *wd = [GSWindowDecorationView windowDecorator];
|
|
|
|
// NSPoint p = [[nswindow contentView] convertPoint:
|
|
|
|
// eventLocation fromView: nil];
|
|
|
|
GSTheme *theme = [GSTheme theme];
|
|
|
|
CGFloat titleHeight = [theme titlebarHeight];
|
|
|
|
CGFloat resizebarHeight = [theme resizebarHeight];
|
|
|
|
NSRect windowframe = [nswindow frame];
|
|
|
|
NSDebugLog(@"[%d] titleHeight: %f", window->window_id, titleHeight);
|
|
|
|
NSDebugLog(@"[%d] resizebarHeight: %f", window->window_id,
|
|
|
|
resizebarHeight);
|
|
|
|
NSDebugLog(@"[%d] windowframe: %f,%f %fx%f", windowframe.origin.x,
|
|
|
|
windowframe.origin.y, windowframe.size.width,
|
|
|
|
windowframe.size.height);
|
|
|
|
NSDebugLog(@"[%d] eventLocation: %f,%f", window->window_id,
|
|
|
|
eventLocation.x, eventLocation.y);
|
|
|
|
|
|
|
|
NSRect titleBarRect = NSZeroRect;
|
|
|
|
NSRect resizeBarRect = NSZeroRect;
|
|
|
|
NSRect closeButtonRect = NSZeroRect;
|
|
|
|
NSRect miniaturizeButtonRect = NSZeroRect;
|
|
|
|
NSUInteger styleMask = [nswindow styleMask];
|
|
|
|
bool hasTitleBar = NO;
|
|
|
|
bool hasResizeBar = NO;
|
|
|
|
bool hasCloseButton = NO;
|
|
|
|
bool hasMiniaturizeButton = NO;
|
|
|
|
|
|
|
|
// wayland controls the window move / resize
|
|
|
|
|
|
|
|
if (styleMask
|
|
|
|
& (NSTitledWindowMask | NSClosableWindowMask
|
|
|
|
| NSMiniaturizableWindowMask))
|
|
|
|
{
|
|
|
|
hasTitleBar = YES;
|
|
|
|
titleBarRect
|
|
|
|
= NSMakeRect(0.0, windowframe.size.height - titleHeight,
|
|
|
|
windowframe.size.width, titleHeight);
|
|
|
|
|
|
|
|
NSDebugLog(@"[%d] titleBarRect: %f,%f %fx%f",
|
|
|
|
titleBarRect.origin.x, titleBarRect.origin.y,
|
|
|
|
titleBarRect.size.width, titleBarRect.size.height);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (styleMask & NSResizableWindowMask)
|
|
|
|
{
|
|
|
|
hasResizeBar = YES;
|
|
|
|
float padding = 10.0;
|
|
|
|
resizeBarRect = NSMakeRect(-padding, -padding,
|
|
|
|
windowframe.size.width + padding * 2,
|
|
|
|
resizebarHeight + padding * 2);
|
|
|
|
|
|
|
|
NSDebugLog(@"[%d] resizeBarRect: %f,%f %fx%f",
|
|
|
|
resizeBarRect.origin.x, resizeBarRect.origin.y,
|
|
|
|
resizeBarRect.size.width, resizeBarRect.size.height);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (styleMask & NSClosableWindowMask)
|
|
|
|
{
|
|
|
|
hasCloseButton = YES;
|
|
|
|
|
|
|
|
closeButtonRect
|
|
|
|
= NSMakeRect(windowframe.size.width - [theme titlebarButtonSize]
|
|
|
|
- [theme titlebarPaddingRight],
|
|
|
|
windowframe.size.height -
|
|
|
|
[theme titlebarButtonSize] -
|
|
|
|
[theme titlebarPaddingTop],
|
|
|
|
[theme titlebarButtonSize],
|
|
|
|
[theme titlebarButtonSize]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (styleMask & NSMiniaturizableWindowMask)
|
|
|
|
{
|
|
|
|
hasMiniaturizeButton = YES;
|
|
|
|
miniaturizeButtonRect = NSMakeRect([theme titlebarPaddingLeft],
|
|
|
|
windowframe.size.height -
|
|
|
|
[theme titlebarButtonSize] -
|
|
|
|
[theme titlebarPaddingTop],
|
|
|
|
[theme titlebarButtonSize],
|
|
|
|
[theme titlebarButtonSize]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hasTitleBar && !NSPointInRect(eventLocation, closeButtonRect)
|
|
|
|
&& !NSPointInRect(eventLocation, miniaturizeButtonRect)
|
|
|
|
&& NSPointInRect(eventLocation, titleBarRect))
|
|
|
|
{
|
|
|
|
NSDebugLog(@"[%d] point in titleBarRect [%f,%f] [%f,%f %fx%f]",
|
|
|
|
window->window_id, eventLocation.x, eventLocation.y,
|
|
|
|
titleBarRect.origin.x, titleBarRect.origin.y,
|
|
|
|
titleBarRect.size.width, titleBarRect.size.height);
|
|
|
|
|
|
|
|
if (state == WL_POINTER_BUTTON_STATE_PRESSED)
|
|
|
|
{
|
|
|
|
xdg_toplevel_move(window->toplevel, wlconfig->seat, serial);
|
|
|
|
window->moving = YES;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
window->moving = NO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (hasResizeBar && NSPointInRect(eventLocation, resizeBarRect))
|
|
|
|
{
|
|
|
|
uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;
|
|
|
|
NSDebugLog(@"[%d] point in resizeBarRect [%f,%f] [%f,%f %fx%f]",
|
|
|
|
window->window_id, eventLocation.x, eventLocation.y,
|
|
|
|
resizeBarRect.origin.x, resizeBarRect.origin.y,
|
|
|
|
resizeBarRect.size.width, resizeBarRect.size.height);
|
|
|
|
|
|
|
|
if (resizeBarRect.size.width < 30 * 2
|
|
|
|
&& eventLocation.x < resizeBarRect.size.width / 2)
|
|
|
|
{
|
|
|
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
|
|
|
|
}
|
|
|
|
else if (eventLocation.x > resizeBarRect.size.width - 30)
|
|
|
|
{
|
|
|
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;
|
|
|
|
}
|
|
|
|
else if (eventLocation.x < 29)
|
|
|
|
{
|
|
|
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state == WL_POINTER_BUTTON_STATE_PRESSED)
|
|
|
|
{
|
|
|
|
xdg_toplevel_resize(window->toplevel, wlconfig->seat, serial,
|
|
|
|
edges);
|
|
|
|
window->resizing = YES;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
window->resizing = NO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // endif window->toplevel
|
|
|
|
|
|
|
|
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;
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
switch (button)
|
|
|
|
{
|
2021-10-25 11:16:22 +00:00
|
|
|
case BTN_LEFT:
|
2021-11-15 22:05:12 +00:00
|
|
|
eventType = NSLeftMouseDown;
|
|
|
|
break;
|
2021-10-25 11:16:22 +00:00
|
|
|
case BTN_RIGHT:
|
2021-11-15 22:05:12 +00:00
|
|
|
eventType = NSRightMouseDown;
|
|
|
|
break;
|
2021-10-25 11:16:22 +00:00
|
|
|
case BTN_MIDDLE:
|
2021-11-15 22:05:12 +00:00
|
|
|
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?
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
2021-11-15 22:05:12 +00:00
|
|
|
wlconfig->pointer.serial = serial;
|
|
|
|
}
|
|
|
|
else if (state == WL_POINTER_BUTTON_STATE_RELEASED)
|
|
|
|
{
|
|
|
|
switch (button)
|
|
|
|
{
|
2021-10-25 11:16:22 +00:00
|
|
|
case BTN_LEFT:
|
2021-11-15 22:05:12 +00:00
|
|
|
eventType = NSLeftMouseUp;
|
|
|
|
break;
|
2021-10-25 11:16:22 +00:00
|
|
|
case BTN_RIGHT:
|
2021-11-15 22:05:12 +00:00
|
|
|
eventType = NSRightMouseUp;
|
|
|
|
break;
|
2021-10-25 11:16:22 +00:00
|
|
|
case BTN_MIDDLE:
|
2021-11-15 22:05:12 +00:00
|
|
|
eventType = NSOtherMouseUp;
|
|
|
|
break;
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
2021-11-15 22:05:12 +00:00
|
|
|
wlconfig->pointer.serial = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-25 11:16:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
/* 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];
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-11-15 22:05:12 +00:00
|
|
|
pointer_handle_axis(void *data, struct wl_pointer *pointer, uint32_t time,
|
|
|
|
uint32_t axis, wl_fixed_t value)
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
NSDebugLog(@"pointer_handle_axis: axis=%d value=%g", axis,
|
|
|
|
wl_fixed_to_double(value));
|
|
|
|
WaylandConfig *wlconfig = data;
|
|
|
|
NSEvent *event;
|
|
|
|
NSEventType eventType;
|
|
|
|
NSPoint eventLocation;
|
2021-10-25 11:16:22 +00:00
|
|
|
NSGraphicsContext *gcontext;
|
2021-11-15 22:05:12 +00:00
|
|
|
unsigned int eventFlags;
|
|
|
|
float deltaX = 0.0;
|
|
|
|
float deltaY = 0.0;
|
|
|
|
int clickCount = 1;
|
|
|
|
int buttonNumber;
|
2021-10-25 11:16:22 +00:00
|
|
|
|
|
|
|
struct window *window = wlconfig->pointer.focus;
|
|
|
|
|
|
|
|
[GSCurrentServer() initializeMouseIfRequired];
|
|
|
|
|
|
|
|
gcontext = GSCurrentContext();
|
2021-11-15 22:05:12 +00:00
|
|
|
eventLocation
|
|
|
|
= NSMakePoint(wlconfig->pointer.x, window->height - wlconfig->pointer.y);
|
2021-10-25 11:16:22 +00:00
|
|
|
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. */
|
2021-11-15 22:05:12 +00:00
|
|
|
switch (axis)
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
NSDebugLog(@"sending pointer scroll at: %fx%f, value %fx%f, window=%d",
|
|
|
|
wlconfig->pointer.x, wlconfig->pointer.y, deltaX, deltaY,
|
|
|
|
window->window_id);
|
2021-10-25 11:16:22 +00:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
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];
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const struct wl_pointer_listener pointer_listener = {
|
2021-11-15 22:05:12 +00:00
|
|
|
pointer_handle_enter, pointer_handle_leave, pointer_handle_motion,
|
|
|
|
pointer_handle_button, pointer_handle_axis,
|
2021-10-25 11:16:22 +00:00
|
|
|
};
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
@implementation
|
|
|
|
WaylandServer (Cursor)
|
|
|
|
- (NSPoint)mouselocation
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
int aScreen = -1;
|
2021-10-25 11:16:22 +00:00
|
|
|
struct output *output;
|
|
|
|
|
|
|
|
NSDebugLog(@"mouselocation");
|
|
|
|
|
|
|
|
// FIXME: find a cleaner way to get the first element of a wl_list
|
2021-11-15 22:05:12 +00:00
|
|
|
wl_list_for_each(output, &wlconfig->output_list, link)
|
|
|
|
{
|
2021-10-25 11:16:22 +00:00
|
|
|
aScreen = output->server_output_id;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (aScreen < 0)
|
|
|
|
// No outputs in the wl_list.
|
|
|
|
return NSZeroPoint;
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
return [self mouseLocationOnScreen:aScreen window:NULL];
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
- (NSPoint)mouseLocationOnScreen:(int)aScreen window:(int *)win
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-10-25 11:16:22 +00:00
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
wl_list_for_each(output, &wlconfig->output_list, link)
|
|
|
|
{
|
|
|
|
if (output->server_output_id == aScreen)
|
|
|
|
{
|
|
|
|
y = output->height - y;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-10-25 11:16:22 +00:00
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
// NSDebugLog(@"mouseLocationOnScreen: returning %fx%f", x, y);
|
2021-10-25 11:16:22 +00:00
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
return NSMakePoint(x, y);
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
- (BOOL)capturemouse:(int)win
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
NSDebugLog(@"capturemouse: %d", win);
|
|
|
|
return NO;
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
- (void)releasemouse
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
NSDebugLog(@"releasemouse");
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
- (void)setMouseLocation:(NSPoint)mouseLocation onScreen:(int)aScreen
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
NSDebugLog(@"setMouseLocation");
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
- (void)hidecursor
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
NSDebugLog(@"hidecursor");
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
- (void)showcursor
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
NSDebugLog(@"showcursor");
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
- (void)standardcursor:(int)style:(void **)cid
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
NSDebugLog(@"standardcursor");
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
- (void)imagecursor:(NSPoint)hotp:(NSImage *)image:(void **)cid
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
NSDebugLog(@"imagecursor");
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
- (void)setcursorcolor:(NSColor *)fg:(NSColor *)bg:(void *)cid
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
NSLog(@"Call to obsolete method -setcursorcolor:::");
|
|
|
|
[self recolorcursor:fg:bg:cid];
|
|
|
|
[self setcursor:cid];
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
- (void)recolorcursor:(NSColor *)fg:(NSColor *)bg:(void *)cid
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
NSDebugLog(@"recolorcursor");
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
- (void)setcursor:(void *)cid
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
NSDebugLog(@"setcursor");
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
- (void)freecursor:(void *)cid
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
NSDebugLog(@"freecursor");
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
2021-11-15 22:05:12 +00:00
|
|
|
- (void)setIgnoreMouse:(BOOL)ignoreMouse:(int)win
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
2021-11-15 22:05:12 +00:00
|
|
|
NSDebugLog(@"setIgnoreMouse");
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
- (void)initializeMouseIfRequired
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
|
|
|
if (!_mouseInitialized)
|
|
|
|
[self initializeMouse];
|
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
- (void)initializeMouse
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
|
|
|
_mouseInitialized = YES;
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
[self mouseOptionsChanged:nil];
|
2021-10-25 11:16:22 +00:00
|
|
|
[[NSDistributedNotificationCenter defaultCenter]
|
2021-11-15 22:05:12 +00:00
|
|
|
addObserver:self
|
|
|
|
selector:@selector(mouseOptionsChanged:)
|
|
|
|
name:NSUserDefaultsDidChangeNotification
|
|
|
|
object:nil];
|
2021-10-25 11:16:22 +00:00
|
|
|
}
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
- (void)mouseOptionsChanged:(NSNotification *)aNotif
|
2021-10-25 11:16:22 +00:00
|
|
|
{
|
|
|
|
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
|
|
|
|
|
2021-11-15 22:05:12 +00:00
|
|
|
wlconfig->mouse_scroll_multiplier =
|
|
|
|
[defs integerForKey:@"GSMouseScrollMultiplier"];
|
2021-10-25 11:16:22 +00:00
|
|
|
if (wlconfig->mouse_scroll_multiplier < 0.0001f)
|
|
|
|
wlconfig->mouse_scroll_multiplier = 1.0f;
|
|
|
|
}
|
|
|
|
@end
|