Changed drag area API to a hit-testing API.
There were several good arguments for this: it's how Windows works with WM_NCHITTEST, SDL doesn't need to manage a list of rects, it allows more control over the regions (how do you use rects to cleanly surround a circular button?), the callback can be more optimized than a iterating a list of rects, and you don't have to send an updated list of rects whenever the window resizes or layout changes. --HG-- rename : test/testdragareas.c => test/testhittesting.c
This commit is contained in:
parent
51a004c734
commit
9e98d09104
15 changed files with 106 additions and 116 deletions
|
@ -580,4 +580,4 @@
|
|||
#define SDL_WinRTGetFSPathUTF8 SDL_WinRTGetFSPathUTF8_REAL
|
||||
#define SDL_WinRTRunApp SDL_WinRTRunApp_REAL
|
||||
#define SDL_CaptureMouse SDL_CaptureMouse_REAL
|
||||
#define SDL_SetWindowDragAreas SDL_SetWindowDragAreas_REAL
|
||||
#define SDL_SetWindowHitTest SDL_SetWindowHitTest_REAL
|
||||
|
|
|
@ -613,4 +613,4 @@ SDL_DYNAPI_PROC(const char*,SDL_WinRTGetFSPathUTF8,(SDL_WinRT_Path a),(a),return
|
|||
SDL_DYNAPI_PROC(int,SDL_WinRTRunApp,(int a, char **b, void *c),(a,b,c),return)
|
||||
#endif
|
||||
SDL_DYNAPI_PROC(int,SDL_CaptureMouse,(SDL_bool a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_SetWindowDragAreas,(SDL_Window *a, const SDL_Rect *b, int c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_SetWindowHitTest,(SDL_Window *a, SDL_HitTest b, void *c),(a,b,c),return)
|
||||
|
|
|
@ -97,8 +97,8 @@ struct SDL_Window
|
|||
|
||||
SDL_WindowShaper *shaper;
|
||||
|
||||
int num_drag_areas;
|
||||
SDL_Rect *drag_areas;
|
||||
SDL_HitTest hit_test;
|
||||
void *hit_test_data;
|
||||
|
||||
SDL_WindowUserData *data;
|
||||
|
||||
|
@ -264,8 +264,8 @@ struct SDL_VideoDevice
|
|||
/* MessageBox */
|
||||
int (*ShowMessageBox) (_THIS, const SDL_MessageBoxData *messageboxdata, int *buttonid);
|
||||
|
||||
/* Drag areas. Note that (areas) and (num_areas) are also copied to the SDL_Window for you after this call. */
|
||||
int (*SetWindowDragAreas)(SDL_Window * window, const SDL_Rect *areas, int num_areas);
|
||||
/* Hit-testing */
|
||||
int (*SetWindowHitTest)(SDL_Window * window, SDL_bool enabled);
|
||||
|
||||
/* * * */
|
||||
/* Data common to all drivers */
|
||||
|
|
|
@ -1411,8 +1411,8 @@ SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
|
|||
SDL_FreeSurface(icon);
|
||||
}
|
||||
|
||||
if (window->num_drag_areas > 0) {
|
||||
_this->SetWindowDragAreas(window, window->drag_areas, window->num_drag_areas);
|
||||
if (window->hit_test > 0) {
|
||||
_this->SetWindowHitTest(window, SDL_TRUE);
|
||||
}
|
||||
|
||||
SDL_FinishWindowCreation(window, flags);
|
||||
|
@ -2310,8 +2310,6 @@ SDL_DestroyWindow(SDL_Window * window)
|
|||
_this->windows = window->next;
|
||||
}
|
||||
|
||||
SDL_free(window->drag_areas);
|
||||
|
||||
SDL_free(window);
|
||||
}
|
||||
|
||||
|
@ -3388,33 +3386,20 @@ SDL_ShouldAllowTopmost(void)
|
|||
}
|
||||
|
||||
int
|
||||
SDL_SetWindowDragAreas(SDL_Window * window, const SDL_Rect *_areas, int num_areas)
|
||||
SDL_SetWindowHitTest(SDL_Window * window, SDL_HitTest callback, void *userdata)
|
||||
{
|
||||
SDL_Rect *areas = NULL;
|
||||
|
||||
CHECK_WINDOW_MAGIC(window, -1);
|
||||
|
||||
if (!_this->SetWindowDragAreas) {
|
||||
if (!_this->SetWindowHitTest) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
if (num_areas > 0) {
|
||||
const size_t len = sizeof (SDL_Rect) * num_areas;
|
||||
areas = (SDL_Rect *) SDL_malloc(len);
|
||||
if (!areas) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
SDL_memcpy(areas, _areas, len);
|
||||
}
|
||||
|
||||
if (_this->SetWindowDragAreas(window, areas, num_areas) == -1) {
|
||||
SDL_free(areas);
|
||||
} else if (_this->SetWindowHitTest(window, callback != NULL) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_free(window->drag_areas);
|
||||
window->drag_areas = areas;
|
||||
window->num_drag_areas = num_areas;
|
||||
window->hit_test = callback;
|
||||
window->hit_test_data = userdata;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
@ -108,7 +108,7 @@ Cocoa_CreateDevice(int devindex)
|
|||
device->SetWindowGrab = Cocoa_SetWindowGrab;
|
||||
device->DestroyWindow = Cocoa_DestroyWindow;
|
||||
device->GetWindowWMInfo = Cocoa_GetWindowWMInfo;
|
||||
device->SetWindowDragAreas = Cocoa_SetWindowDragAreas;
|
||||
device->SetWindowHitTest = Cocoa_SetWindowHitTest;
|
||||
|
||||
device->shape_driver.CreateShaper = Cocoa_CreateShaper;
|
||||
device->shape_driver.SetWindowShape = Cocoa_SetWindowShape;
|
||||
|
|
|
@ -77,7 +77,7 @@ typedef enum
|
|||
-(NSApplicationPresentationOptions)window:(NSWindow *)window willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions;
|
||||
|
||||
/* See if event is in a drag area, toggle on window dragging. */
|
||||
-(BOOL) processDragArea:(NSEvent *)theEvent;
|
||||
-(BOOL) processHitTest:(NSEvent *)theEvent;
|
||||
|
||||
/* Window event handling */
|
||||
-(void) mouseDown:(NSEvent *) theEvent;
|
||||
|
@ -119,7 +119,6 @@ struct SDL_WindowData
|
|||
SDL_bool inWindowMove;
|
||||
Cocoa_WindowListener *listener;
|
||||
struct SDL_VideoData *videodata;
|
||||
NSView *dragarea;
|
||||
};
|
||||
|
||||
extern int Cocoa_CreateWindow(_THIS, SDL_Window * window);
|
||||
|
@ -144,7 +143,7 @@ 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 int Cocoa_SetWindowDragAreas(SDL_Window *window, const SDL_Rect *areas, int num_areas);
|
||||
extern int Cocoa_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
|
||||
|
||||
#endif /* _SDL_cocoawindow_h */
|
||||
|
||||
|
|
|
@ -657,26 +657,20 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
|||
/*NSLog(@"doCommandBySelector: %@\n", NSStringFromSelector(aSelector));*/
|
||||
}
|
||||
|
||||
- (BOOL)processDragArea:(NSEvent *)theEvent
|
||||
- (BOOL)processHitTest:(NSEvent *)theEvent
|
||||
{
|
||||
const int num_areas = _data->window->num_drag_areas;
|
||||
|
||||
SDL_assert(isDragAreaRunning == [_data->nswindow isMovableByWindowBackground]);
|
||||
SDL_assert((num_areas > 0) || !isDragAreaRunning);
|
||||
|
||||
if (num_areas > 0) { /* if no drag areas, skip this. */
|
||||
int i;
|
||||
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_Rect *areas = _data->window->drag_areas;
|
||||
for (i = 0; i < num_areas; i++) {
|
||||
if (SDL_PointInRect(&point, &areas[i])) {
|
||||
if (!isDragAreaRunning) {
|
||||
isDragAreaRunning = YES;
|
||||
[_data->nswindow setMovableByWindowBackground:YES];
|
||||
}
|
||||
return YES; /* started a new drag! */
|
||||
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! */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -686,14 +680,14 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
|||
return YES; /* was dragging, drop event. */
|
||||
}
|
||||
|
||||
return NO; /* not a drag area, carry on. */
|
||||
return NO; /* not a special area, carry on. */
|
||||
}
|
||||
|
||||
- (void)mouseDown:(NSEvent *)theEvent
|
||||
{
|
||||
int button;
|
||||
|
||||
if ([self processDragArea:theEvent]) {
|
||||
if ([self processHitTest:theEvent]) {
|
||||
return; /* dragging, drop event. */
|
||||
}
|
||||
|
||||
|
@ -735,7 +729,7 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
|||
{
|
||||
int button;
|
||||
|
||||
if ([self processDragArea:theEvent]) {
|
||||
if ([self processHitTest:theEvent]) {
|
||||
return; /* stopped dragging, drop event. */
|
||||
}
|
||||
|
||||
|
@ -778,7 +772,7 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
|
|||
NSPoint point;
|
||||
int x, y;
|
||||
|
||||
if ([self processDragArea:theEvent]) {
|
||||
if ([self processHitTest:theEvent]) {
|
||||
return; /* dragging, drop event. */
|
||||
}
|
||||
|
||||
|
@ -1599,7 +1593,7 @@ Cocoa_SetWindowFullscreenSpace(SDL_Window * window, SDL_bool state)
|
|||
}
|
||||
|
||||
int
|
||||
Cocoa_SetWindowDragAreas(SDL_Window * window, const SDL_Rect *areas, int num_areas)
|
||||
Cocoa_SetWindowHitTest(SDL_Window * window, SDL_bool enabled)
|
||||
{
|
||||
return 0; /* just succeed, the real work is done elsewhere. */
|
||||
}
|
||||
|
|
|
@ -303,21 +303,16 @@ InitiateWindowMove(_THIS, const SDL_WindowData *data, const SDL_Point *point)
|
|||
}
|
||||
|
||||
static SDL_bool
|
||||
ProcessDragArea(_THIS, const SDL_WindowData *data, const XEvent *xev)
|
||||
ProcessHitTest(_THIS, const SDL_WindowData *data, const XEvent *xev)
|
||||
{
|
||||
const SDL_Window *window = data->window;
|
||||
const int num_areas = window->num_drag_areas;
|
||||
SDL_Window *window = data->window;
|
||||
|
||||
if (num_areas > 0) {
|
||||
if (window->hit_test) {
|
||||
const SDL_Point point = { xev->xbutton.x, xev->xbutton.y };
|
||||
const SDL_Rect *areas = window->drag_areas;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_areas; i++) {
|
||||
if (SDL_PointInRect(&point, &areas[i])) {
|
||||
InitiateWindowMove(_this, data, &point);
|
||||
return SDL_TRUE; /* dragging, drop this event. */
|
||||
}
|
||||
const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
|
||||
if (rc == SDL_HITTEST_DRAGGABLE) {
|
||||
InitiateWindowMove(_this, data, &point);
|
||||
return SDL_TRUE; /* dragging, drop this event. */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -762,7 +757,7 @@ X11_DispatchEvent(_THIS)
|
|||
SDL_SendMouseWheel(data->window, 0, 0, ticks);
|
||||
} else {
|
||||
if(xevent.xbutton.button == Button1) {
|
||||
if (ProcessDragArea(_this, data, &xevent)) {
|
||||
if (ProcessHitTest(_this, data, &xevent)) {
|
||||
break; /* don't pass this event on to app. */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -457,7 +457,7 @@ X11_CreateDevice(int devindex)
|
|||
device->UpdateWindowFramebuffer = X11_UpdateWindowFramebuffer;
|
||||
device->DestroyWindowFramebuffer = X11_DestroyWindowFramebuffer;
|
||||
device->GetWindowWMInfo = X11_GetWindowWMInfo;
|
||||
device->SetWindowDragAreas = X11_SetWindowDragAreas;
|
||||
device->SetWindowHitTest = X11_SetWindowHitTest;
|
||||
|
||||
device->shape_driver.CreateShaper = X11_CreateShaper;
|
||||
device->shape_driver.SetWindowShape = X11_SetWindowShape;
|
||||
|
|
|
@ -1445,9 +1445,9 @@ X11_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
|
|||
}
|
||||
|
||||
int
|
||||
X11_SetWindowDragAreas(SDL_Window *window, const SDL_Rect *areas, int num_areas)
|
||||
X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
|
||||
{
|
||||
return 0; // nothing to do, will be handled in event handler
|
||||
return 0; /* just succeed, the real work is done elsewhere. */
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_X11 */
|
||||
|
|
|
@ -93,7 +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_SetWindowDragAreas(SDL_Window *window, const SDL_Rect *areas, int num_areas);
|
||||
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