Merged Ryan's SDL-gui-backend branch.
Adds three APIs, and implements them on X11, Cocoa, and Windows: - SDL_CaptureMouse() - SDL_GetGlobalMouseState() - SDL_SetWindowHitTest()
This commit is contained in:
commit
b273873297
28 changed files with 901 additions and 59 deletions
|
@ -584,3 +584,6 @@
|
|||
#define SDL_sqrtf SDL_sqrtf_REAL
|
||||
#define SDL_tan SDL_tan_REAL
|
||||
#define SDL_tanf SDL_tanf_REAL
|
||||
#define SDL_CaptureMouse SDL_CaptureMouse_REAL
|
||||
#define SDL_SetWindowHitTest SDL_SetWindowHitTest_REAL
|
||||
#define SDL_GetGlobalMouseState SDL_GetGlobalMouseState_REAL
|
||||
|
|
|
@ -616,3 +616,6 @@ SDL_DYNAPI_PROC(void,SDL_WarpMouseGlobal,(int a, int b),(a,b),)
|
|||
SDL_DYNAPI_PROC(float,SDL_sqrtf,(float a),(a),return)
|
||||
SDL_DYNAPI_PROC(double,SDL_tan,(double a),(a),return)
|
||||
SDL_DYNAPI_PROC(float,SDL_tanf,(float a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_CaptureMouse,(SDL_bool a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_SetWindowHitTest,(SDL_Window *a, SDL_HitTest b, void *c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(Uint32,SDL_GetGlobalMouseState,(int *a, int *b),(a,b),return)
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "SDL_timer.h"
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_events_c.h"
|
||||
#include "SDL_assert.h"
|
||||
#include "../video/SDL_sysvideo.h"
|
||||
|
||||
|
||||
|
@ -619,6 +620,16 @@ SDL_SetKeyboardFocus(SDL_Window * window)
|
|||
|
||||
/* See if the current window has lost focus */
|
||||
if (keyboard->focus && keyboard->focus != window) {
|
||||
|
||||
/* new window shouldn't think it has mouse captured. */
|
||||
SDL_assert(!window || !(window->flags & SDL_WINDOW_MOUSE_CAPTURE));
|
||||
|
||||
/* old window must lose an existing mouse capture. */
|
||||
if (keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE) {
|
||||
SDL_CaptureMouse(SDL_FALSE); /* drop the capture. */
|
||||
SDL_assert(!(keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE));
|
||||
}
|
||||
|
||||
SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_LOST,
|
||||
0, 0);
|
||||
|
||||
|
|
|
@ -140,14 +140,14 @@ static SDL_bool
|
|||
SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
int w, h;
|
||||
SDL_bool inWindow;
|
||||
SDL_bool inWindow = SDL_TRUE;
|
||||
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
if (x < 0 || y < 0 || x >= w || y >= h) {
|
||||
inWindow = SDL_FALSE;
|
||||
} else {
|
||||
inWindow = SDL_TRUE;
|
||||
if ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0) {
|
||||
int w, h;
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
if (x < 0 || y < 0 || x >= w || y >= h) {
|
||||
inWindow = SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Linux doesn't give you mouse events outside your window unless you grab
|
||||
|
@ -246,24 +246,29 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ
|
|||
mouse->y += yrel;
|
||||
}
|
||||
|
||||
/* !!! FIXME: shouldn't this be (window) instead of (mouse->focus)? */
|
||||
SDL_GetWindowSize(mouse->focus, &x_max, &y_max);
|
||||
--x_max;
|
||||
--y_max;
|
||||
/* make sure that the pointers find themselves inside the windows,
|
||||
unless we have the mouse captured. */
|
||||
if ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0) {
|
||||
int x_max = 0, y_max = 0;
|
||||
|
||||
/* make sure that the pointers find themselves inside the windows */
|
||||
if (mouse->x > x_max) {
|
||||
mouse->x = x_max;
|
||||
}
|
||||
if (mouse->x < 0) {
|
||||
mouse->x = 0;
|
||||
}
|
||||
// !!! FIXME: shouldn't this be (window) instead of (mouse->focus)?
|
||||
SDL_GetWindowSize(mouse->focus, &x_max, &y_max);
|
||||
--x_max;
|
||||
--y_max;
|
||||
|
||||
if (mouse->y > y_max) {
|
||||
mouse->y = y_max;
|
||||
}
|
||||
if (mouse->y < 0) {
|
||||
mouse->y = 0;
|
||||
if (mouse->x > x_max) {
|
||||
mouse->x = x_max;
|
||||
}
|
||||
if (mouse->x < 0) {
|
||||
mouse->x = 0;
|
||||
}
|
||||
|
||||
if (mouse->y > y_max) {
|
||||
mouse->y = y_max;
|
||||
}
|
||||
if (mouse->y < 0) {
|
||||
mouse->y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
mouse->xdelta += xrel;
|
||||
|
@ -426,6 +431,7 @@ SDL_MouseQuit(void)
|
|||
SDL_Cursor *cursor, *next;
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
SDL_CaptureMouse(SDL_FALSE);
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
SDL_ShowCursor(1);
|
||||
|
||||
|
@ -477,16 +483,42 @@ SDL_GetRelativeMouseState(int *x, int *y)
|
|||
return mouse->buttonstate;
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_GetGlobalMouseState(int *x, int *y)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
int tmpx, tmpy;
|
||||
|
||||
/* make sure these are never NULL for the backend implementations... */
|
||||
if (!x) {
|
||||
x = &tmpx;
|
||||
}
|
||||
if (!y) {
|
||||
y = &tmpy;
|
||||
}
|
||||
|
||||
*x = *y = 0;
|
||||
|
||||
if (!mouse->GetGlobalMouseState) {
|
||||
SDL_assert(0 && "This should really be implemented for every target.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mouse->GetGlobalMouseState(x, y);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_WarpMouseInWindow(SDL_Window * window, int x, int y)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
if (window == NULL)
|
||||
if (window == NULL) {
|
||||
window = mouse->focus;
|
||||
}
|
||||
|
||||
if (window == NULL)
|
||||
if (window == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mouse->WarpMouse) {
|
||||
mouse->WarpMouse(window, x, y);
|
||||
|
|
|
@ -66,6 +66,12 @@ typedef struct
|
|||
/* Set relative mode */
|
||||
int (*SetRelativeMouseMode) (SDL_bool enabled);
|
||||
|
||||
/* Set mouse capture */
|
||||
int (*CaptureMouse) (SDL_Window * window);
|
||||
|
||||
/* Get absolute mouse coordinates. (x) and (y) are never NULL and set to zero before call. */
|
||||
Uint32 (*GetGlobalMouseState) (int *x, int *y);
|
||||
|
||||
/* Data common to all mice */
|
||||
SDL_MouseID mouseID;
|
||||
SDL_Window *focus;
|
||||
|
|
|
@ -1379,6 +1379,14 @@ SDLTest_CommonEvent(SDLTest_CommonState * state, SDL_Event * event, int *done)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (withShift) {
|
||||
SDL_Window *current_win = SDL_GetKeyboardFocus();
|
||||
if (current_win) {
|
||||
const SDL_bool shouldCapture = (SDL_GetWindowFlags(current_win) & SDL_WINDOW_MOUSE_CAPTURE) == 0;
|
||||
const int rc = SDL_CaptureMouse(shouldCapture);
|
||||
SDL_Log("%sapturing mouse %s!\n", shouldCapture ? "C" : "Unc", (rc == 0) ? "succeeded" : "failed");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDLK_v:
|
||||
if (withControl) {
|
||||
|
@ -1478,6 +1486,19 @@ SDLTest_CommonEvent(SDLTest_CommonState * state, SDL_Event * event, int *done)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case SDLK_a:
|
||||
if (withControl) {
|
||||
/* Ctrl-A reports absolute mouse position. */
|
||||
int x, y;
|
||||
const Uint32 mask = SDL_GetGlobalMouseState(&x, &y);
|
||||
SDL_Log("ABSOLUTE MOUSE: (%d, %d)%s%s%s%s%s\n", x, y,
|
||||
(mask & SDL_BUTTON_LMASK) ? " [LBUTTON]" : "",
|
||||
(mask & SDL_BUTTON_MMASK) ? " [MBUTTON]" : "",
|
||||
(mask & SDL_BUTTON_RMASK) ? " [RBUTTON]" : "",
|
||||
(mask & SDL_BUTTON_X1MASK) ? " [X2BUTTON]" : "",
|
||||
(mask & SDL_BUTTON_X2MASK) ? " [X2BUTTON]" : "");
|
||||
}
|
||||
break;
|
||||
case SDLK_0:
|
||||
if (withControl) {
|
||||
SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
|
||||
|
|
|
@ -97,6 +97,9 @@ struct SDL_Window
|
|||
|
||||
SDL_WindowShaper *shaper;
|
||||
|
||||
SDL_HitTest hit_test;
|
||||
void *hit_test_data;
|
||||
|
||||
SDL_WindowUserData *data;
|
||||
|
||||
void *driverdata;
|
||||
|
@ -261,6 +264,9 @@ struct SDL_VideoDevice
|
|||
/* MessageBox */
|
||||
int (*ShowMessageBox) (_THIS, const SDL_MessageBoxData *messageboxdata, int *buttonid);
|
||||
|
||||
/* Hit-testing */
|
||||
int (*SetWindowHitTest)(SDL_Window * window, SDL_bool enabled);
|
||||
|
||||
/* * * */
|
||||
/* Data common to all drivers */
|
||||
SDL_bool suspend_screensaver;
|
||||
|
|
|
@ -1428,6 +1428,11 @@ SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
|
|||
SDL_SetWindowIcon(window, icon);
|
||||
SDL_FreeSurface(icon);
|
||||
}
|
||||
|
||||
if (window->hit_test) {
|
||||
_this->SetWindowHitTest(window, SDL_TRUE);
|
||||
}
|
||||
|
||||
SDL_FinishWindowCreation(window, flags);
|
||||
|
||||
return 0;
|
||||
|
@ -3292,12 +3297,17 @@ SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
|||
int retval = -1;
|
||||
SDL_bool relative_mode;
|
||||
int show_cursor_prev;
|
||||
SDL_bool mouse_captured;
|
||||
SDL_Window *current_window;
|
||||
|
||||
if (!messageboxdata) {
|
||||
return SDL_InvalidParamError("messageboxdata");
|
||||
}
|
||||
|
||||
current_window = SDL_GetKeyboardFocus();
|
||||
mouse_captured = current_window && ((SDL_GetWindowFlags(current_window) & SDL_WINDOW_MOUSE_CAPTURE) != 0);
|
||||
relative_mode = SDL_GetRelativeMouseMode();
|
||||
SDL_CaptureMouse(SDL_FALSE);
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
show_cursor_prev = SDL_ShowCursor(1);
|
||||
|
||||
|
@ -3349,6 +3359,13 @@ SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
|||
SDL_SetError("No message system available");
|
||||
}
|
||||
|
||||
if (current_window) {
|
||||
SDL_RaiseWindow(current_window);
|
||||
if (mouse_captured) {
|
||||
SDL_CaptureMouse(SDL_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_ShowCursor(show_cursor_prev);
|
||||
SDL_SetRelativeMouseMode(relative_mode);
|
||||
|
||||
|
@ -3391,4 +3408,21 @@ SDL_ShouldAllowTopmost(void)
|
|||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SetWindowHitTest(SDL_Window * window, SDL_HitTest callback, void *userdata)
|
||||
{
|
||||
CHECK_WINDOW_MAGIC(window, -1);
|
||||
|
||||
if (!_this->SetWindowHitTest) {
|
||||
return SDL_Unsupported();
|
||||
} else if (_this->SetWindowHitTest(window, callback != NULL) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
window->hit_test = callback;
|
||||
window->hit_test_data = userdata;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
@ -307,6 +307,39 @@ Cocoa_SetRelativeMouseMode(SDL_bool enabled)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
Cocoa_CaptureMouse(SDL_Window *window)
|
||||
{
|
||||
/* our Cocoa event code already tracks the mouse outside the window,
|
||||
so all we have to do here is say "okay" and do what we always do. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Uint32
|
||||
Cocoa_GetGlobalMouseState(int *x, int *y)
|
||||
{
|
||||
const NSUInteger cocoaButtons = [NSEvent pressedMouseButtons];
|
||||
const NSPoint cocoaLocation = [NSEvent mouseLocation];
|
||||
Uint32 retval = 0;
|
||||
|
||||
for (NSScreen *screen in [NSScreen screens]) {
|
||||
NSRect frame = [screen frame];
|
||||
if (NSPointInRect(cocoaLocation, frame)) {
|
||||
*x = (int) cocoaLocation.x;
|
||||
*y = (int) ((frame.origin.y + frame.size.height) - cocoaLocation.y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
retval |= (cocoaButtons & (1 << 0)) ? SDL_BUTTON_LMASK : 0;
|
||||
retval |= (cocoaButtons & (1 << 1)) ? SDL_BUTTON_RMASK : 0;
|
||||
retval |= (cocoaButtons & (1 << 2)) ? SDL_BUTTON_MMASK : 0;
|
||||
retval |= (cocoaButtons & (1 << 3)) ? SDL_BUTTON_X1MASK : 0;
|
||||
retval |= (cocoaButtons & (1 << 4)) ? SDL_BUTTON_X2MASK : 0;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_InitMouse(_THIS)
|
||||
{
|
||||
|
@ -321,6 +354,8 @@ Cocoa_InitMouse(_THIS)
|
|||
mouse->WarpMouse = Cocoa_WarpMouse;
|
||||
mouse->WarpMouseGlobal = Cocoa_WarpMouseGlobal;
|
||||
mouse->SetRelativeMouseMode = Cocoa_SetRelativeMouseMode;
|
||||
mouse->CaptureMouse = Cocoa_CaptureMouse;
|
||||
mouse->GetGlobalMouseState = Cocoa_GetGlobalMouseState;
|
||||
|
||||
SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor());
|
||||
|
||||
|
|
|
@ -108,6 +108,7 @@ Cocoa_CreateDevice(int devindex)
|
|||
device->SetWindowGrab = Cocoa_SetWindowGrab;
|
||||
device->DestroyWindow = Cocoa_DestroyWindow;
|
||||
device->GetWindowWMInfo = Cocoa_GetWindowWMInfo;
|
||||
device->SetWindowHitTest = Cocoa_SetWindowHitTest;
|
||||
|
||||
device->shape_driver.CreateShaper = Cocoa_CreateShaper;
|
||||
device->shape_driver.SetWindowShape = Cocoa_SetWindowShape;
|
||||
|
|
|
@ -45,6 +45,7 @@ typedef enum
|
|||
PendingWindowOperation pendingWindowOperation;
|
||||
BOOL isMoving;
|
||||
int pendingWindowWarpX, pendingWindowWarpY;
|
||||
BOOL isDragAreaRunning;
|
||||
}
|
||||
|
||||
-(void) listen:(SDL_WindowData *) data;
|
||||
|
@ -75,6 +76,9 @@ typedef enum
|
|||
-(void) windowDidExitFullScreen:(NSNotification *) aNotification;
|
||||
-(NSApplicationPresentationOptions)window:(NSWindow *)window willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions;
|
||||
|
||||
/* See if event is in a drag area, toggle on window dragging. */
|
||||
-(BOOL) processHitTest:(NSEvent *)theEvent;
|
||||
|
||||
/* Window event handling */
|
||||
-(void) mouseDown:(NSEvent *) theEvent;
|
||||
-(void) rightMouseDown:(NSEvent *) theEvent;
|
||||
|
@ -138,8 +142,8 @@ extern int Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * r
|
|||
extern int Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp);
|
||||
extern void Cocoa_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
|
||||
extern void Cocoa_DestroyWindow(_THIS, SDL_Window * window);
|
||||
extern SDL_bool Cocoa_GetWindowWMInfo(_THIS, SDL_Window * window,
|
||||
struct SDL_SysWMinfo *info);
|
||||
extern SDL_bool Cocoa_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info);
|
||||
extern int Cocoa_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
|
||||
|
||||
#endif /* _SDL_cocoawindow_h */
|
||||
|
||||
|
|
|
@ -192,6 +192,7 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
|||
inFullscreenTransition = NO;
|
||||
pendingWindowOperation = PENDING_OPERATION_NONE;
|
||||
isMoving = NO;
|
||||
isDragAreaRunning = NO;
|
||||
|
||||
center = [NSNotificationCenter defaultCenter];
|
||||
|
||||
|
@ -663,10 +664,48 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
|||
/*Cocoa_HandleKeyEvent(SDL_GetVideoDevice(), theEvent);*/
|
||||
}
|
||||
|
||||
/* We'll respond to selectors by doing nothing so we don't beep.
|
||||
* The escape key gets converted to a "cancel" selector, etc.
|
||||
*/
|
||||
- (void)doCommandBySelector:(SEL)aSelector
|
||||
{
|
||||
/*NSLog(@"doCommandBySelector: %@\n", NSStringFromSelector(aSelector));*/
|
||||
}
|
||||
|
||||
- (BOOL)processHitTest:(NSEvent *)theEvent
|
||||
{
|
||||
SDL_assert(isDragAreaRunning == [_data->nswindow isMovableByWindowBackground]);
|
||||
|
||||
if (_data->window->hit_test) { /* if no hit-test, skip this. */
|
||||
const NSPoint location = [theEvent locationInWindow];
|
||||
const SDL_Point point = { (int) location.x, _data->window->h - (((int) location.y)-1) };
|
||||
const SDL_HitTestResult rc = _data->window->hit_test(_data->window, &point, _data->window->hit_test_data);
|
||||
if (rc == SDL_HITTEST_DRAGGABLE) {
|
||||
if (!isDragAreaRunning) {
|
||||
isDragAreaRunning = YES;
|
||||
[_data->nswindow setMovableByWindowBackground:YES];
|
||||
}
|
||||
return YES; /* dragging! */
|
||||
}
|
||||
}
|
||||
|
||||
if (isDragAreaRunning) {
|
||||
isDragAreaRunning = NO;
|
||||
[_data->nswindow setMovableByWindowBackground:NO];
|
||||
return YES; /* was dragging, drop event. */
|
||||
}
|
||||
|
||||
return NO; /* not a special area, carry on. */
|
||||
}
|
||||
|
||||
- (void)mouseDown:(NSEvent *)theEvent
|
||||
{
|
||||
int button;
|
||||
|
||||
if ([self processHitTest:theEvent]) {
|
||||
return; /* dragging, drop event. */
|
||||
}
|
||||
|
||||
switch ([theEvent buttonNumber]) {
|
||||
case 0:
|
||||
if (([theEvent modifierFlags] & NSControlKeyMask) &&
|
||||
|
@ -705,6 +744,10 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
|||
{
|
||||
int button;
|
||||
|
||||
if ([self processHitTest:theEvent]) {
|
||||
return; /* stopped dragging, drop event. */
|
||||
}
|
||||
|
||||
switch ([theEvent buttonNumber]) {
|
||||
case 0:
|
||||
if (wasCtrlLeft) {
|
||||
|
@ -744,6 +787,10 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
|||
NSPoint point;
|
||||
int x, y;
|
||||
|
||||
if ([self processHitTest:theEvent]) {
|
||||
return; /* dragging, drop event. */
|
||||
}
|
||||
|
||||
if (mouse->relative_mode) {
|
||||
return;
|
||||
}
|
||||
|
@ -752,8 +799,8 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
|||
x = (int)point.x;
|
||||
y = (int)(window->h - point.y);
|
||||
|
||||
if (x < 0 || x >= window->w || y < 0 || y >= window->h) {
|
||||
if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
|
||||
if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
|
||||
if (x < 0 || x >= window->w || y < 0 || y >= window->h) {
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
} else if (x >= window->w) {
|
||||
|
@ -890,6 +937,7 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
|||
|
||||
/* The default implementation doesn't pass rightMouseDown to responder chain */
|
||||
- (void)rightMouseDown:(NSEvent *)theEvent;
|
||||
- (BOOL)mouseDownCanMoveWindow;
|
||||
@end
|
||||
|
||||
@implementation SDLView
|
||||
|
@ -898,6 +946,14 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
|||
[[self nextResponder] rightMouseDown:theEvent];
|
||||
}
|
||||
|
||||
- (BOOL)mouseDownCanMoveWindow
|
||||
{
|
||||
/* Always say YES, but this doesn't do anything until we call
|
||||
-[NSWindow setMovableByWindowBackground:YES], which we ninja-toggle
|
||||
during mouse events when we're using a drag area. */
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)resetCursorRects
|
||||
{
|
||||
[super resetCursorRects];
|
||||
|
@ -995,6 +1051,7 @@ SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, SDL_bool created
|
|||
|
||||
/* All done! */
|
||||
[pool release];
|
||||
window->driverdata = data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1566,6 +1623,12 @@ Cocoa_SetWindowFullscreenSpace(SDL_Window * window, SDL_bool state)
|
|||
return succeeded;
|
||||
}
|
||||
|
||||
int
|
||||
Cocoa_SetWindowHitTest(SDL_Window * window, SDL_bool enabled)
|
||||
{
|
||||
return 0; /* just succeed, the real work is done elsewhere. */
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "../../events/SDL_events_c.h"
|
||||
#include "../../events/SDL_touch_c.h"
|
||||
#include "../../events/scancodes_windows.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
/* Dropfile support */
|
||||
#include <shellapi.h>
|
||||
|
@ -438,33 +439,55 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
HRAWINPUT hRawInput = (HRAWINPUT)lParam;
|
||||
RAWINPUT inp;
|
||||
UINT size = sizeof(inp);
|
||||
const SDL_bool isRelative = mouse->relative_mode || mouse->relative_mode_warp;
|
||||
const SDL_bool isCapture = ((data->window->flags & SDL_WINDOW_MOUSE_CAPTURE) != 0);
|
||||
|
||||
if (!mouse->relative_mode || mouse->relative_mode_warp || mouse->focus != data->window) {
|
||||
break;
|
||||
if (!isRelative || mouse->focus != data->window) {
|
||||
if (!isCapture) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GetRawInputData(hRawInput, RID_INPUT, &inp, &size, sizeof(RAWINPUTHEADER));
|
||||
|
||||
/* Mouse data */
|
||||
if (inp.header.dwType == RIM_TYPEMOUSE) {
|
||||
RAWMOUSE* mouse = &inp.data.mouse;
|
||||
if (isRelative) {
|
||||
RAWMOUSE* mouse = &inp.data.mouse;
|
||||
|
||||
if ((mouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE) {
|
||||
SDL_SendMouseMotion(data->window, 0, 1, (int)mouse->lLastX, (int)mouse->lLastY);
|
||||
} else {
|
||||
/* synthesize relative moves from the abs position */
|
||||
static SDL_Point initialMousePoint;
|
||||
if (initialMousePoint.x == 0 && initialMousePoint.y == 0) {
|
||||
initialMousePoint.x = mouse->lLastX;
|
||||
initialMousePoint.y = mouse->lLastY;
|
||||
}
|
||||
|
||||
SDL_SendMouseMotion(data->window, 0, 1, (int)(mouse->lLastX-initialMousePoint.x), (int)(mouse->lLastY-initialMousePoint.y) );
|
||||
|
||||
if ((mouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE) {
|
||||
SDL_SendMouseMotion(data->window, 0, 1, (int)mouse->lLastX, (int)mouse->lLastY);
|
||||
} else {
|
||||
/* synthesize relative moves from the abs position */
|
||||
static SDL_Point initialMousePoint;
|
||||
if (initialMousePoint.x == 0 && initialMousePoint.y == 0) {
|
||||
initialMousePoint.x = mouse->lLastX;
|
||||
initialMousePoint.y = mouse->lLastY;
|
||||
}
|
||||
|
||||
SDL_SendMouseMotion(data->window, 0, 1, (int)(mouse->lLastX-initialMousePoint.x), (int)(mouse->lLastY-initialMousePoint.y));
|
||||
|
||||
initialMousePoint.x = mouse->lLastX;
|
||||
initialMousePoint.y = mouse->lLastY;
|
||||
WIN_CheckRawMouseButtons( mouse->usButtonFlags, data );
|
||||
} else if (isCapture) {
|
||||
/* we check for where Windows thinks the system cursor lives in this case, so we don't really lose mouse accel, etc. */
|
||||
POINT pt;
|
||||
HWND hwnd = data->hwnd;
|
||||
GetCursorPos(&pt);
|
||||
if (WindowFromPoint(pt) != hwnd) { /* if in the window, WM_MOUSEMOVE, etc, will cover it. */
|
||||
ScreenToClient(data->hwnd, &pt);
|
||||
SDL_SendMouseMotion(data->window, 0, 0, (int) pt.x, (int) pt.y);
|
||||
SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_LBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_LEFT);
|
||||
SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_RBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_RIGHT);
|
||||
SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_MBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_MIDDLE);
|
||||
SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_XBUTTON1) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X1);
|
||||
SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_XBUTTON2) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X2);
|
||||
}
|
||||
} else {
|
||||
SDL_assert(0 && "Shouldn't happen");
|
||||
}
|
||||
WIN_CheckRawMouseButtons(mouse->usButtonFlags, data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -509,7 +532,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
#ifdef WM_MOUSELEAVE
|
||||
case WM_MOUSELEAVE:
|
||||
if (SDL_GetMouseFocus() == data->window && !SDL_GetMouse()->relative_mode) {
|
||||
if (SDL_GetMouseFocus() == data->window && !SDL_GetMouse()->relative_mode && !(data->window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
|
||||
if (!IsIconic(hwnd)) {
|
||||
POINT cursorPos;
|
||||
GetCursorPos(&cursorPos);
|
||||
|
@ -863,6 +886,32 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_NCHITTEST:
|
||||
{
|
||||
SDL_Window *window = data->window;
|
||||
if (window->hit_test) {
|
||||
POINT winpoint = { (int) LOWORD(lParam), (int) HIWORD(lParam) };
|
||||
if (ScreenToClient(data->hwnd, &winpoint)) {
|
||||
const SDL_Point point = { (int) winpoint.x, (int) winpoint.y };
|
||||
const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
|
||||
switch (rc) {
|
||||
case SDL_HITTEST_DRAGGABLE: return HTCAPTION;
|
||||
case SDL_HITTEST_RESIZE_TOPLEFT: return HTTOPLEFT;
|
||||
case SDL_HITTEST_RESIZE_TOP: return HTTOP;
|
||||
case SDL_HITTEST_RESIZE_TOPRIGHT: return HTTOPRIGHT;
|
||||
case SDL_HITTEST_RESIZE_RIGHT: return HTRIGHT;
|
||||
case SDL_HITTEST_RESIZE_BOTTOMRIGHT: return HTBOTTOMRIGHT;
|
||||
case SDL_HITTEST_RESIZE_BOTTOM: return HTBOTTOM;
|
||||
case SDL_HITTEST_RESIZE_BOTTOMLEFT: return HTBOTTOMLEFT;
|
||||
case SDL_HITTEST_RESIZE_LEFT: return HTLEFT;
|
||||
}
|
||||
}
|
||||
/* If we didn't return, this will call DefWindowProc below. */
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/* If there's a window proc, assume it's going to handle messages */
|
||||
|
|
|
@ -30,6 +30,44 @@
|
|||
|
||||
HCURSOR SDL_cursor = NULL;
|
||||
|
||||
static int rawInputEnableCount = 0;
|
||||
|
||||
static int
|
||||
ToggleRawInput(SDL_bool enabled)
|
||||
{
|
||||
RAWINPUTDEVICE rawMouse = { 0x01, 0x02, 0, NULL }; /* Mouse: UsagePage = 1, Usage = 2 */
|
||||
|
||||
if (enabled) {
|
||||
rawInputEnableCount++;
|
||||
if (rawInputEnableCount > 1) {
|
||||
return 0; /* already done. */
|
||||
}
|
||||
} else {
|
||||
if (rawInputEnableCount == 0) {
|
||||
return 0; /* already done. */
|
||||
}
|
||||
rawInputEnableCount--;
|
||||
if (rawInputEnableCount > 0) {
|
||||
return 0; /* not time to disable yet */
|
||||
}
|
||||
}
|
||||
|
||||
if (!enabled) {
|
||||
rawMouse.dwFlags |= RIDEV_REMOVE;
|
||||
}
|
||||
|
||||
/* (Un)register raw input for mice */
|
||||
if (RegisterRawInputDevices(&rawMouse, 1, sizeof(RAWINPUTDEVICE)) == FALSE) {
|
||||
|
||||
/* Only return an error when registering. If we unregister and fail,
|
||||
then it's probably that we unregistered twice. That's OK. */
|
||||
if (enabled) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static SDL_Cursor *
|
||||
WIN_CreateDefaultCursor()
|
||||
|
@ -211,22 +249,43 @@ WIN_WarpMouseGlobal(int x, int y)
|
|||
static int
|
||||
WIN_SetRelativeMouseMode(SDL_bool enabled)
|
||||
{
|
||||
RAWINPUTDEVICE rawMouse = { 0x01, 0x02, 0, NULL }; /* Mouse: UsagePage = 1, Usage = 2 */
|
||||
return ToggleRawInput(enabled);
|
||||
}
|
||||
|
||||
if (!enabled) {
|
||||
rawMouse.dwFlags |= RIDEV_REMOVE;
|
||||
}
|
||||
|
||||
/* (Un)register raw input for mice */
|
||||
if (RegisterRawInputDevices(&rawMouse, 1, sizeof(RAWINPUTDEVICE)) == FALSE) {
|
||||
|
||||
/* Only return an error when registering. If we unregister and fail,
|
||||
then it's probably that we unregistered twice. That's OK. */
|
||||
if (enabled) {
|
||||
return SDL_Unsupported();
|
||||
static int
|
||||
WIN_CaptureMouse(SDL_Window *window)
|
||||
{
|
||||
if (!window) {
|
||||
SDL_Window *focusWin = SDL_GetKeyboardFocus();
|
||||
if (focusWin) {
|
||||
SDL_WindowData *data = (SDL_WindowData *)focusWin->driverdata;
|
||||
WIN_OnWindowEnter(SDL_GetVideoDevice(), focusWin); /* make sure WM_MOUSELEAVE messages are (re)enabled. */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
/* While we were thinking of SetCapture() when designing this API in SDL,
|
||||
we didn't count on the fact that SetCapture() only tracks while the
|
||||
left mouse button is held down! Instead, we listen for raw mouse input
|
||||
and manually query the mouse when it leaves the window. :/ */
|
||||
return ToggleRawInput(window != NULL);
|
||||
}
|
||||
|
||||
static Uint32
|
||||
WIN_GetGlobalMouseState(int *x, int *y)
|
||||
{
|
||||
Uint32 retval = 0;
|
||||
POINT pt = { 0, 0 };
|
||||
GetCursorPos(&pt);
|
||||
*x = (int) pt.x;
|
||||
*y = (int) pt.y;
|
||||
|
||||
retval |= GetAsyncKeyState(VK_LBUTTON) & 0x8000 ? SDL_BUTTON_LMASK : 0;
|
||||
retval |= GetAsyncKeyState(VK_RBUTTON) & 0x8000 ? SDL_BUTTON_RMASK : 0;
|
||||
retval |= GetAsyncKeyState(VK_MBUTTON) & 0x8000 ? SDL_BUTTON_MMASK : 0;
|
||||
retval |= GetAsyncKeyState(VK_X1BUTTON) & 0x8000 ? SDL_BUTTON_X1MASK : 0;
|
||||
retval |= GetAsyncKeyState(VK_X2BUTTON) & 0x8000 ? SDL_BUTTON_X2MASK : 0;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -241,6 +300,8 @@ WIN_InitMouse(_THIS)
|
|||
mouse->WarpMouse = WIN_WarpMouse;
|
||||
mouse->WarpMouseGlobal = WIN_WarpMouseGlobal;
|
||||
mouse->SetRelativeMouseMode = WIN_SetRelativeMouseMode;
|
||||
mouse->CaptureMouse = WIN_CaptureMouse;
|
||||
mouse->GetGlobalMouseState = WIN_GetGlobalMouseState;
|
||||
|
||||
SDL_SetDefaultCursor(WIN_CreateDefaultCursor());
|
||||
|
||||
|
@ -256,6 +317,11 @@ WIN_QuitMouse(_THIS)
|
|||
mouse->def_cursor = NULL;
|
||||
mouse->cur_cursor = NULL;
|
||||
}
|
||||
|
||||
if (rawInputEnableCount) { /* force RAWINPUT off here. */
|
||||
rawInputEnableCount = 1;
|
||||
ToggleRawInput(SDL_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
|
||||
|
|
|
@ -144,6 +144,7 @@ WIN_CreateDevice(int devindex)
|
|||
device->UpdateWindowFramebuffer = WIN_UpdateWindowFramebuffer;
|
||||
device->DestroyWindowFramebuffer = WIN_DestroyWindowFramebuffer;
|
||||
device->OnWindowEnter = WIN_OnWindowEnter;
|
||||
device->SetWindowHitTest = WIN_SetWindowHitTest;
|
||||
|
||||
device->shape_driver.CreateShaper = Win32_CreateShaper;
|
||||
device->shape_driver.SetWindowShape = Win32_SetWindowShape;
|
||||
|
|
|
@ -785,6 +785,12 @@ WIN_UpdateClipCursor(SDL_Window *window)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
WIN_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
|
||||
{
|
||||
return 0; /* just succeed, the real work is done elsewhere. */
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
@ -69,6 +69,7 @@ extern SDL_bool WIN_GetWindowWMInfo(_THIS, SDL_Window * window,
|
|||
struct SDL_SysWMinfo *info);
|
||||
extern void WIN_OnWindowEnter(_THIS, SDL_Window * window);
|
||||
extern void WIN_UpdateClipCursor(SDL_Window *window);
|
||||
extern int WIN_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
|
||||
|
||||
#endif /* _SDL_windowswindow_h */
|
||||
|
||||
|
|
|
@ -40,6 +40,42 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef _NET_WM_MOVERESIZE_SIZE_TOPLEFT
|
||||
#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
|
||||
#endif
|
||||
|
||||
#ifndef _NET_WM_MOVERESIZE_SIZE_TOP
|
||||
#define _NET_WM_MOVERESIZE_SIZE_TOP 1
|
||||
#endif
|
||||
|
||||
#ifndef _NET_WM_MOVERESIZE_SIZE_TOPRIGHT
|
||||
#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
|
||||
#endif
|
||||
|
||||
#ifndef _NET_WM_MOVERESIZE_SIZE_RIGHT
|
||||
#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
|
||||
#endif
|
||||
|
||||
#ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT
|
||||
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
|
||||
#endif
|
||||
|
||||
#ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOM
|
||||
#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
|
||||
#endif
|
||||
|
||||
#ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT
|
||||
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
|
||||
#endif
|
||||
|
||||
#ifndef _NET_WM_MOVERESIZE_SIZE_LEFT
|
||||
#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
|
||||
#endif
|
||||
|
||||
#ifndef _NET_WM_MOVERESIZE_MOVE
|
||||
#define _NET_WM_MOVERESIZE_MOVE 8
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned char *data;
|
||||
int format, count;
|
||||
|
@ -347,6 +383,124 @@ X11_DispatchUnmapNotify(SDL_WindowData *data)
|
|||
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
InitiateWindowMove(_THIS, const SDL_WindowData *data, const SDL_Point *point)
|
||||
{
|
||||
SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
|
||||
SDL_Window* window = data->window;
|
||||
Display *display = viddata->display;
|
||||
|
||||
/* !!! FIXME: we need to regrab this if necessary when the drag is done. */
|
||||
X11_XUngrabPointer(display, 0L);
|
||||
X11_XFlush(display);
|
||||
|
||||
XEvent evt;
|
||||
evt.xclient.type = ClientMessage;
|
||||
evt.xclient.window = data->xwindow;
|
||||
evt.xclient.message_type = X11_XInternAtom(display, "_NET_WM_MOVERESIZE", True);
|
||||
evt.xclient.format = 32;
|
||||
evt.xclient.data.l[0] = window->x + point->x;
|
||||
evt.xclient.data.l[1] = window->y + point->y;
|
||||
evt.xclient.data.l[2] = _NET_WM_MOVERESIZE_MOVE;
|
||||
evt.xclient.data.l[3] = Button1;
|
||||
evt.xclient.data.l[4] = 0;
|
||||
X11_XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &evt);
|
||||
|
||||
X11_XSync(display, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
InitiateWindowResize(_THIS, const SDL_WindowData *data, const SDL_Point *point, int direction)
|
||||
{
|
||||
SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
|
||||
SDL_Window* window = data->window;
|
||||
Display *display = viddata->display;
|
||||
|
||||
if (direction < _NET_WM_MOVERESIZE_SIZE_TOPLEFT || direction > _NET_WM_MOVERESIZE_SIZE_LEFT)
|
||||
return;
|
||||
|
||||
/* !!! FIXME: we need to regrab this if necessary when the drag is done. */
|
||||
X11_XUngrabPointer(display, 0L);
|
||||
X11_XFlush(display);
|
||||
|
||||
XEvent evt;
|
||||
evt.xclient.type = ClientMessage;
|
||||
evt.xclient.window = data->xwindow;
|
||||
evt.xclient.message_type = X11_XInternAtom(display, "_NET_WM_MOVERESIZE", True);
|
||||
evt.xclient.format = 32;
|
||||
evt.xclient.data.l[0] = window->x + point->x;
|
||||
evt.xclient.data.l[1] = window->y + point->y;
|
||||
evt.xclient.data.l[2] = direction;
|
||||
evt.xclient.data.l[3] = Button1;
|
||||
evt.xclient.data.l[4] = 0;
|
||||
X11_XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &evt);
|
||||
|
||||
X11_XSync(display, 0);
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
ProcessHitTest(_THIS, const SDL_WindowData *data, const XEvent *xev)
|
||||
{
|
||||
SDL_Window *window = data->window;
|
||||
SDL_bool ret = SDL_FALSE;
|
||||
|
||||
if (window->hit_test) {
|
||||
const SDL_Point point = { xev->xbutton.x, xev->xbutton.y };
|
||||
const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
|
||||
switch (rc) {
|
||||
case SDL_HITTEST_DRAGGABLE: {
|
||||
InitiateWindowMove(_this, data, &point);
|
||||
ret = SDL_TRUE;
|
||||
}
|
||||
break;
|
||||
case SDL_HITTEST_RESIZE_TOPLEFT: {
|
||||
InitiateWindowResize(_this, data, &point, _NET_WM_MOVERESIZE_SIZE_TOPLEFT);
|
||||
ret = SDL_TRUE;
|
||||
}
|
||||
break;
|
||||
case SDL_HITTEST_RESIZE_TOP: {
|
||||
InitiateWindowResize(_this, data, &point, _NET_WM_MOVERESIZE_SIZE_TOP);
|
||||
ret = SDL_TRUE;
|
||||
}
|
||||
break;
|
||||
case SDL_HITTEST_RESIZE_TOPRIGHT: {
|
||||
InitiateWindowResize(_this, data, &point, _NET_WM_MOVERESIZE_SIZE_TOPRIGHT);
|
||||
ret = SDL_TRUE;
|
||||
}
|
||||
break;
|
||||
case SDL_HITTEST_RESIZE_RIGHT: {
|
||||
InitiateWindowResize(_this, data, &point, _NET_WM_MOVERESIZE_SIZE_RIGHT);
|
||||
ret = SDL_TRUE;
|
||||
}
|
||||
break;
|
||||
case SDL_HITTEST_RESIZE_BOTTOMRIGHT: {
|
||||
InitiateWindowResize(_this, data, &point, _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT);
|
||||
ret = SDL_TRUE;
|
||||
}
|
||||
break;
|
||||
case SDL_HITTEST_RESIZE_BOTTOM: {
|
||||
InitiateWindowResize(_this, data, &point, _NET_WM_MOVERESIZE_SIZE_BOTTOM);
|
||||
ret = SDL_TRUE;
|
||||
}
|
||||
break;
|
||||
case SDL_HITTEST_RESIZE_BOTTOMLEFT: {
|
||||
InitiateWindowResize(_this, data, &point, _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT);
|
||||
ret = SDL_TRUE;
|
||||
}
|
||||
break;
|
||||
case SDL_HITTEST_RESIZE_LEFT: {
|
||||
InitiateWindowResize(_this, data, &point, _NET_WM_MOVERESIZE_SIZE_LEFT);
|
||||
ret = SDL_TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
X11_DispatchEvent(_THIS)
|
||||
{
|
||||
|
@ -820,6 +974,11 @@ X11_DispatchEvent(_THIS)
|
|||
if (X11_IsWheelEvent(display,&xevent,&ticks)) {
|
||||
SDL_SendMouseWheel(data->window, 0, 0, ticks);
|
||||
} else {
|
||||
if(xevent.xbutton.button == Button1) {
|
||||
if (ProcessHitTest(_this, data, &xevent)) {
|
||||
break; /* don't pass this event on to app. */
|
||||
}
|
||||
}
|
||||
SDL_SendMouseButton(data->window, 0, SDL_PRESSED, xevent.xbutton.button);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -339,6 +339,62 @@ X11_SetRelativeMouseMode(SDL_bool enabled)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
X11_CaptureMouse(SDL_Window *window)
|
||||
{
|
||||
Display *display = GetDisplay();
|
||||
|
||||
if (window) {
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
const unsigned int mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask;
|
||||
const int rc = X11_XGrabPointer(display, data->xwindow, False,
|
||||
mask, GrabModeAsync, GrabModeAsync,
|
||||
None, None, CurrentTime);
|
||||
if (rc != GrabSuccess) {
|
||||
return SDL_SetError("X server refused mouse capture");
|
||||
}
|
||||
} else {
|
||||
X11_XUngrabPointer(display, CurrentTime);
|
||||
}
|
||||
|
||||
X11_XSync(display, False);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Uint32
|
||||
X11_GetGlobalMouseState(int *x, int *y)
|
||||
{
|
||||
Display *display = GetDisplay();
|
||||
const int num_screens = SDL_GetNumVideoDisplays();
|
||||
int i;
|
||||
|
||||
/* !!! FIXME: should we XSync() here first? */
|
||||
|
||||
for (i = 0; i < num_screens; i++) {
|
||||
SDL_DisplayData *data = (SDL_DisplayData *) SDL_GetDisplayDriverData(i);
|
||||
if (data != NULL) {
|
||||
Window root, child;
|
||||
int rootx, rooty, winx, winy;
|
||||
unsigned int mask;
|
||||
if (X11_XQueryPointer(display, RootWindow(display, data->screen), &root, &child, &rootx, &rooty, &winx, &winy, &mask)) {
|
||||
Uint32 retval = 0;
|
||||
retval |= (mask & Button1Mask) ? SDL_BUTTON_LMASK : 0;
|
||||
retval |= (mask & Button2Mask) ? SDL_BUTTON_MMASK : 0;
|
||||
retval |= (mask & Button3Mask) ? SDL_BUTTON_RMASK : 0;
|
||||
*x = data->x + rootx;
|
||||
*y = data->y + rooty;
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(0 && "The pointer wasn't on any X11 screen?!");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
X11_InitMouse(_THIS)
|
||||
{
|
||||
|
@ -351,6 +407,8 @@ X11_InitMouse(_THIS)
|
|||
mouse->WarpMouse = X11_WarpMouse;
|
||||
mouse->WarpMouseGlobal = X11_WarpMouseGlobal;
|
||||
mouse->SetRelativeMouseMode = X11_SetRelativeMouseMode;
|
||||
mouse->CaptureMouse = X11_CaptureMouse;
|
||||
mouse->GetGlobalMouseState = X11_GetGlobalMouseState;
|
||||
|
||||
SDL_SetDefaultCursor(X11_CreateDefaultCursor());
|
||||
}
|
||||
|
|
|
@ -243,6 +243,7 @@ X11_CreateDevice(int devindex)
|
|||
device->UpdateWindowFramebuffer = X11_UpdateWindowFramebuffer;
|
||||
device->DestroyWindowFramebuffer = X11_DestroyWindowFramebuffer;
|
||||
device->GetWindowWMInfo = X11_GetWindowWMInfo;
|
||||
device->SetWindowHitTest = X11_SetWindowHitTest;
|
||||
|
||||
device->shape_driver.CreateShaper = X11_CreateShaper;
|
||||
device->shape_driver.SetWindowShape = X11_SetWindowShape;
|
||||
|
|
|
@ -1445,6 +1445,12 @@ X11_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
|
||||
{
|
||||
return 0; /* just succeed, the real work is done elsewhere. */
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_X11 */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
@ -93,6 +93,7 @@ extern void X11_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
|
|||
extern void X11_DestroyWindow(_THIS, SDL_Window * window);
|
||||
extern SDL_bool X11_GetWindowWMInfo(_THIS, SDL_Window * window,
|
||||
struct SDL_SysWMinfo *info);
|
||||
extern int X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
|
||||
|
||||
#endif /* _SDL_x11window_h */
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue