Changed drag area API to a hit-testing API.
authorRyan C. Gordon <icculus@icculus.org>
Wed, 28 May 2014 01:22:47 -0400
changeset 89359d2f0236322b
parent 8934 57fe4bf1b84b
child 8936 59cbb9959346
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.
.hgignore
include/SDL_video.h
src/dynapi/SDL_dynapi_overrides.h
src/dynapi/SDL_dynapi_procs.h
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/cocoa/SDL_cocoavideo.m
src/video/cocoa/SDL_cocoawindow.h
src/video/cocoa/SDL_cocoawindow.m
src/video/x11/SDL_x11events.c
src/video/x11/SDL_x11video.c
src/video/x11/SDL_x11window.c
src/video/x11/SDL_x11window.h
test/Makefile.in
test/testdragareas.c
test/testhittesting.c
     1.1 --- a/.hgignore	Tue May 27 15:47:25 2014 -0400
     1.2 +++ b/.hgignore	Wed May 28 01:22:47 2014 -0400
     1.3 @@ -55,7 +55,6 @@
     1.4  test/testatomic
     1.5  test/testaudioinfo
     1.6  test/testautomation
     1.7 -test/testdragareas
     1.8  test/testdraw2
     1.9  test/testerror
    1.10  test/testfile
    1.11 @@ -64,6 +63,7 @@
    1.12  test/testgl2
    1.13  test/testgles
    1.14  test/testhaptic
    1.15 +test/testhittesting
    1.16  test/testiconv
    1.17  test/testime
    1.18  test/testintersections
     2.1 --- a/include/SDL_video.h	Tue May 27 15:47:25 2014 -0400
     2.2 +++ b/include/SDL_video.h	Wed May 28 01:22:47 2014 -0400
     2.3 @@ -791,43 +791,51 @@
     2.4                                                     Uint16 * green,
     2.5                                                     Uint16 * blue);
     2.6  
     2.7 +typedef enum
     2.8 +{
     2.9 +    SDL_HITTEST_NORMAL,  /**< Region is normal. No special properties. */
    2.10 +    SDL_HITTEST_DRAGGABLE,  /**< Region can drag entire window. */
    2.11 +    /* !!! FIXME: resize enums here. */
    2.12 +} SDL_HitTestResult;
    2.13 +
    2.14 +typedef SDL_HitTestResult (SDLCALL *SDL_HitTest)(SDL_Window *win,
    2.15 +                                                 const SDL_Point *area,
    2.16 +                                                 void *data);
    2.17 +
    2.18  /**
    2.19 - *  \brief Define regions of a window that can be used to drag it.
    2.20 + *  \brief Provide a callback that decides if a window region has special properties.
    2.21   *
    2.22 - *  Normally windows are dragged by decorations provided by the system
    2.23 - *  window manager (usually, a title bar), but for some apps, it makes sense
    2.24 - *  to drag them from somewhere else inside the window itself; for example,
    2.25 - *  one might have a borderless window that wants to be draggable from any
    2.26 - *  part, or simulate its own title bar, etc.
    2.27 + *  Normally windows are dragged and resized by decorations provided by the
    2.28 + *  system window manager (a title bar, borders, etc), but for some apps, it
    2.29 + *  makes sense to drag them from somewhere else inside the window itself; for
    2.30 + *  example, one might have a borderless window that wants to be draggable
    2.31 + *  from any part, or simulate its own title bar, etc.
    2.32   *
    2.33 - *  This method designates pieces of a given window as "drag areas," which
    2.34 - *  will move the window when the user drags with his mouse, as if she had
    2.35 - *  used the titlebar.
    2.36 - *
    2.37 - *  You may specify multiple drag areas, disconnected or overlapping. This
    2.38 - *  function accepts an array of rectangles. Each call to this function will
    2.39 - *  replace any previously-defined drag areas. To disable drag areas on a
    2.40 - *  window, call this function with a NULL array of zero elements.
    2.41 - *
    2.42 - *  Drag areas do not automatically resize. If your window changes dimensions
    2.43 - *  you should plan to re-call this function with new drag areas if
    2.44 - *  appropriate.
    2.45 + *  This function lets the app provide a callback that designates pieces of
    2.46 + *  a given window as special. This callback is run during event processing
    2.47 + *  if we need to tell the OS to treat a region of the window specially; the
    2.48 + *  use of this callback is known as "hit testing."
    2.49   *
    2.50   *  Mouse input may not be delivered to your application if it is within
    2.51 - *  a drag area; the OS will often apply that input to moving the window and
    2.52 - *  not deliver it to the application.
    2.53 + *  a special area; the OS will often apply that input to moving the window or
    2.54 + *  resizing the window and not deliver it to the application.
    2.55 + *
    2.56 + *  Specifying NULL for a callback disables hit-testing. Hit-testing is
    2.57 + *  disabled by default.
    2.58   *
    2.59   *  Platforms that don't support this functionality will return -1
    2.60 - *  unconditionally, even if you're attempting to disable drag areas.
    2.61 + *  unconditionally, even if you're attempting to disable hit-testing.
    2.62   *
    2.63 - *  \param window The window to set drag areas on.
    2.64 - *  \param areas An array of SDL_Rects containing num_areas elements.
    2.65 - *  \param num_areas The number of elements in the areas parameter.
    2.66 + *  Your callback may fire at any time.
    2.67 + *
    2.68 + *  \param window The window to set hit-testing on.
    2.69 + *  \param callback The callback to call when doing a hit-test.
    2.70 + *  \param callback_data An app-defined void pointer passed to the callback.
    2.71   *  \return 0 on success, -1 on error (including unsupported).
    2.72   */
    2.73 -extern DECLSPEC int SDLCALL SDL_SetWindowDragAreas(SDL_Window * window,
    2.74 -                                                   const SDL_Rect *areas,
    2.75 -                                                   int num_areas);
    2.76 +extern DECLSPEC int SDLCALL SDL_SetWindowHitTest(SDL_Window * window,
    2.77 +                                                 SDL_HitTest callback,
    2.78 +                                                 void *callback_data);
    2.79  
    2.80  /**
    2.81   *  \brief Destroy a window.
     3.1 --- a/src/dynapi/SDL_dynapi_overrides.h	Tue May 27 15:47:25 2014 -0400
     3.2 +++ b/src/dynapi/SDL_dynapi_overrides.h	Wed May 28 01:22:47 2014 -0400
     3.3 @@ -580,4 +580,4 @@
     3.4  #define SDL_WinRTGetFSPathUTF8 SDL_WinRTGetFSPathUTF8_REAL
     3.5  #define SDL_WinRTRunApp SDL_WinRTRunApp_REAL
     3.6  #define SDL_CaptureMouse SDL_CaptureMouse_REAL
     3.7 -#define SDL_SetWindowDragAreas SDL_SetWindowDragAreas_REAL
     3.8 +#define SDL_SetWindowHitTest SDL_SetWindowHitTest_REAL
     4.1 --- a/src/dynapi/SDL_dynapi_procs.h	Tue May 27 15:47:25 2014 -0400
     4.2 +++ b/src/dynapi/SDL_dynapi_procs.h	Wed May 28 01:22:47 2014 -0400
     4.3 @@ -613,4 +613,4 @@
     4.4  SDL_DYNAPI_PROC(int,SDL_WinRTRunApp,(int a, char **b, void *c),(a,b,c),return)
     4.5  #endif
     4.6  SDL_DYNAPI_PROC(int,SDL_CaptureMouse,(SDL_bool a),(a),return)
     4.7 -SDL_DYNAPI_PROC(int,SDL_SetWindowDragAreas,(SDL_Window *a, const SDL_Rect *b, int c),(a,b,c),return)
     4.8 +SDL_DYNAPI_PROC(int,SDL_SetWindowHitTest,(SDL_Window *a, SDL_HitTest b, void *c),(a,b,c),return)
     5.1 --- a/src/video/SDL_sysvideo.h	Tue May 27 15:47:25 2014 -0400
     5.2 +++ b/src/video/SDL_sysvideo.h	Wed May 28 01:22:47 2014 -0400
     5.3 @@ -97,8 +97,8 @@
     5.4  
     5.5      SDL_WindowShaper *shaper;
     5.6  
     5.7 -    int num_drag_areas;
     5.8 -    SDL_Rect *drag_areas;
     5.9 +    SDL_HitTest hit_test;
    5.10 +    void *hit_test_data;
    5.11  
    5.12      SDL_WindowUserData *data;
    5.13  
    5.14 @@ -264,8 +264,8 @@
    5.15      /* MessageBox */
    5.16      int (*ShowMessageBox) (_THIS, const SDL_MessageBoxData *messageboxdata, int *buttonid);
    5.17  
    5.18 -    /* Drag areas. Note that (areas) and (num_areas) are also copied to the SDL_Window for you after this call. */
    5.19 -    int (*SetWindowDragAreas)(SDL_Window * window, const SDL_Rect *areas, int num_areas);
    5.20 +    /* Hit-testing */
    5.21 +    int (*SetWindowHitTest)(SDL_Window * window, SDL_bool enabled);
    5.22  
    5.23      /* * * */
    5.24      /* Data common to all drivers */
     6.1 --- a/src/video/SDL_video.c	Tue May 27 15:47:25 2014 -0400
     6.2 +++ b/src/video/SDL_video.c	Wed May 28 01:22:47 2014 -0400
     6.3 @@ -1411,8 +1411,8 @@
     6.4          SDL_FreeSurface(icon);
     6.5      }
     6.6  
     6.7 -    if (window->num_drag_areas > 0) {
     6.8 -        _this->SetWindowDragAreas(window, window->drag_areas, window->num_drag_areas);
     6.9 +    if (window->hit_test > 0) {
    6.10 +        _this->SetWindowHitTest(window, SDL_TRUE);
    6.11      }
    6.12  
    6.13      SDL_FinishWindowCreation(window, flags);
    6.14 @@ -2310,8 +2310,6 @@
    6.15          _this->windows = window->next;
    6.16      }
    6.17  
    6.18 -    SDL_free(window->drag_areas);
    6.19 -
    6.20      SDL_free(window);
    6.21  }
    6.22  
    6.23 @@ -3388,33 +3386,20 @@
    6.24  }
    6.25  
    6.26  int
    6.27 -SDL_SetWindowDragAreas(SDL_Window * window, const SDL_Rect *_areas, int num_areas)
    6.28 +SDL_SetWindowHitTest(SDL_Window * window, SDL_HitTest callback, void *userdata)
    6.29  {
    6.30 -    SDL_Rect *areas = NULL;
    6.31 -
    6.32      CHECK_WINDOW_MAGIC(window, -1);
    6.33  
    6.34 -    if (!_this->SetWindowDragAreas) {
    6.35 +    if (!_this->SetWindowHitTest) {
    6.36          return SDL_Unsupported();
    6.37 -    }
    6.38 -
    6.39 -    if (num_areas > 0) {
    6.40 -        const size_t len = sizeof (SDL_Rect) * num_areas;
    6.41 -        areas = (SDL_Rect *) SDL_malloc(len);
    6.42 -        if (!areas) {
    6.43 -            return SDL_OutOfMemory();
    6.44 -        }
    6.45 -        SDL_memcpy(areas, _areas, len);
    6.46 -    }
    6.47 -
    6.48 -    if (_this->SetWindowDragAreas(window, areas, num_areas) == -1) {
    6.49 -        SDL_free(areas);
    6.50 +    } else if (_this->SetWindowHitTest(window, callback != NULL) == -1) {
    6.51          return -1;
    6.52      }
    6.53  
    6.54 -    SDL_free(window->drag_areas);
    6.55 -    window->drag_areas = areas;
    6.56 -    window->num_drag_areas = num_areas;
    6.57 +    window->hit_test = callback;
    6.58 +    window->hit_test_data = userdata;
    6.59 +
    6.60 +    return 0;
    6.61  }
    6.62  
    6.63  /* vi: set ts=4 sw=4 expandtab: */
     7.1 --- a/src/video/cocoa/SDL_cocoavideo.m	Tue May 27 15:47:25 2014 -0400
     7.2 +++ b/src/video/cocoa/SDL_cocoavideo.m	Wed May 28 01:22:47 2014 -0400
     7.3 @@ -108,7 +108,7 @@
     7.4      device->SetWindowGrab = Cocoa_SetWindowGrab;
     7.5      device->DestroyWindow = Cocoa_DestroyWindow;
     7.6      device->GetWindowWMInfo = Cocoa_GetWindowWMInfo;
     7.7 -    device->SetWindowDragAreas = Cocoa_SetWindowDragAreas;
     7.8 +    device->SetWindowHitTest = Cocoa_SetWindowHitTest;
     7.9  
    7.10      device->shape_driver.CreateShaper = Cocoa_CreateShaper;
    7.11      device->shape_driver.SetWindowShape = Cocoa_SetWindowShape;
     8.1 --- a/src/video/cocoa/SDL_cocoawindow.h	Tue May 27 15:47:25 2014 -0400
     8.2 +++ b/src/video/cocoa/SDL_cocoawindow.h	Wed May 28 01:22:47 2014 -0400
     8.3 @@ -77,7 +77,7 @@
     8.4  -(NSApplicationPresentationOptions)window:(NSWindow *)window willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions;
     8.5  
     8.6  /* See if event is in a drag area, toggle on window dragging. */
     8.7 --(BOOL) processDragArea:(NSEvent *)theEvent;
     8.8 +-(BOOL) processHitTest:(NSEvent *)theEvent;
     8.9  
    8.10  /* Window event handling */
    8.11  -(void) mouseDown:(NSEvent *) theEvent;
    8.12 @@ -119,7 +119,6 @@
    8.13      SDL_bool inWindowMove;
    8.14      Cocoa_WindowListener *listener;
    8.15      struct SDL_VideoData *videodata;
    8.16 -    NSView *dragarea;
    8.17  };
    8.18  
    8.19  extern int Cocoa_CreateWindow(_THIS, SDL_Window * window);
    8.20 @@ -144,7 +143,7 @@
    8.21  extern void Cocoa_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
    8.22  extern void Cocoa_DestroyWindow(_THIS, SDL_Window * window);
    8.23  extern SDL_bool Cocoa_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info);
    8.24 -extern int Cocoa_SetWindowDragAreas(SDL_Window *window, const SDL_Rect *areas, int num_areas);
    8.25 +extern int Cocoa_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
    8.26  
    8.27  #endif /* _SDL_cocoawindow_h */
    8.28  
     9.1 --- a/src/video/cocoa/SDL_cocoawindow.m	Tue May 27 15:47:25 2014 -0400
     9.2 +++ b/src/video/cocoa/SDL_cocoawindow.m	Wed May 28 01:22:47 2014 -0400
     9.3 @@ -657,26 +657,20 @@
     9.4      /*NSLog(@"doCommandBySelector: %@\n", NSStringFromSelector(aSelector));*/
     9.5  }
     9.6  
     9.7 -- (BOOL)processDragArea:(NSEvent *)theEvent
     9.8 +- (BOOL)processHitTest:(NSEvent *)theEvent
     9.9  {
    9.10 -    const int num_areas = _data->window->num_drag_areas;
    9.11 +    SDL_assert(isDragAreaRunning == [_data->nswindow isMovableByWindowBackground]);
    9.12  
    9.13 -    SDL_assert(isDragAreaRunning == [_data->nswindow isMovableByWindowBackground]);
    9.14 -    SDL_assert((num_areas > 0) || !isDragAreaRunning);
    9.15 -
    9.16 -    if (num_areas > 0) {  /* if no drag areas, skip this. */
    9.17 -        int i;
    9.18 +    if (_data->window->hit_test) {  /* if no hit-test, skip this. */
    9.19          const NSPoint location = [theEvent locationInWindow];
    9.20          const SDL_Point point = { (int) location.x, _data->window->h - (((int) location.y)-1) };
    9.21 -        const SDL_Rect *areas = _data->window->drag_areas;
    9.22 -        for (i = 0; i < num_areas; i++) {
    9.23 -            if (SDL_PointInRect(&point, &areas[i])) {
    9.24 -                if (!isDragAreaRunning) {
    9.25 -                    isDragAreaRunning = YES;
    9.26 -                    [_data->nswindow setMovableByWindowBackground:YES];
    9.27 -                }
    9.28 -                return YES;  /* started a new drag! */
    9.29 +        const SDL_HitTestResult rc = _data->window->hit_test(_data->window, &point, _data->window->hit_test_data);
    9.30 +        if (rc == SDL_HITTEST_DRAGGABLE) {
    9.31 +            if (!isDragAreaRunning) {
    9.32 +                isDragAreaRunning = YES;
    9.33 +                [_data->nswindow setMovableByWindowBackground:YES];
    9.34              }
    9.35 +            return YES;  /* dragging! */
    9.36          }
    9.37      }
    9.38  
    9.39 @@ -686,14 +680,14 @@
    9.40          return YES;  /* was dragging, drop event. */
    9.41      }
    9.42  
    9.43 -    return NO;  /* not a drag area, carry on. */
    9.44 +    return NO;  /* not a special area, carry on. */
    9.45  }
    9.46  
    9.47  - (void)mouseDown:(NSEvent *)theEvent
    9.48  {
    9.49      int button;
    9.50  
    9.51 -    if ([self processDragArea:theEvent]) {
    9.52 +    if ([self processHitTest:theEvent]) {
    9.53          return;  /* dragging, drop event. */
    9.54      }
    9.55  
    9.56 @@ -735,7 +729,7 @@
    9.57  {
    9.58      int button;
    9.59  
    9.60 -    if ([self processDragArea:theEvent]) {
    9.61 +    if ([self processHitTest:theEvent]) {
    9.62          return;  /* stopped dragging, drop event. */
    9.63      }
    9.64  
    9.65 @@ -778,7 +772,7 @@
    9.66      NSPoint point;
    9.67      int x, y;
    9.68  
    9.69 -    if ([self processDragArea:theEvent]) {
    9.70 +    if ([self processHitTest:theEvent]) {
    9.71          return;  /* dragging, drop event. */
    9.72      }
    9.73  
    9.74 @@ -1599,7 +1593,7 @@
    9.75  }
    9.76  
    9.77  int
    9.78 -Cocoa_SetWindowDragAreas(SDL_Window * window, const SDL_Rect *areas, int num_areas)
    9.79 +Cocoa_SetWindowHitTest(SDL_Window * window, SDL_bool enabled)
    9.80  {
    9.81      return 0;  /* just succeed, the real work is done elsewhere. */
    9.82  }
    10.1 --- a/src/video/x11/SDL_x11events.c	Tue May 27 15:47:25 2014 -0400
    10.2 +++ b/src/video/x11/SDL_x11events.c	Wed May 28 01:22:47 2014 -0400
    10.3 @@ -303,21 +303,16 @@
    10.4  }
    10.5  
    10.6  static SDL_bool
    10.7 -ProcessDragArea(_THIS, const SDL_WindowData *data, const XEvent *xev)
    10.8 +ProcessHitTest(_THIS, const SDL_WindowData *data, const XEvent *xev)
    10.9  {
   10.10 -    const SDL_Window *window = data->window;
   10.11 -    const int num_areas = window->num_drag_areas;
   10.12 +    SDL_Window *window = data->window;
   10.13  
   10.14 -    if (num_areas > 0) {
   10.15 +    if (window->hit_test) {
   10.16          const SDL_Point point = { xev->xbutton.x, xev->xbutton.y };
   10.17 -        const SDL_Rect *areas = window->drag_areas;
   10.18 -        int i;
   10.19 -
   10.20 -        for (i = 0; i < num_areas; i++) {
   10.21 -            if (SDL_PointInRect(&point, &areas[i])) {
   10.22 -                InitiateWindowMove(_this, data, &point);
   10.23 -                return SDL_TRUE;  /* dragging, drop this event. */
   10.24 -            }
   10.25 +        const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
   10.26 +        if (rc == SDL_HITTEST_DRAGGABLE) {
   10.27 +            InitiateWindowMove(_this, data, &point);
   10.28 +            return SDL_TRUE;  /* dragging, drop this event. */
   10.29          }
   10.30      }
   10.31  
   10.32 @@ -762,7 +757,7 @@
   10.33                  SDL_SendMouseWheel(data->window, 0, 0, ticks);
   10.34              } else {
   10.35                  if(xevent.xbutton.button == Button1) {
   10.36 -                    if (ProcessDragArea(_this, data, &xevent)) {
   10.37 +                    if (ProcessHitTest(_this, data, &xevent)) {
   10.38                          break;  /* don't pass this event on to app. */
   10.39                      }
   10.40                  }
    11.1 --- a/src/video/x11/SDL_x11video.c	Tue May 27 15:47:25 2014 -0400
    11.2 +++ b/src/video/x11/SDL_x11video.c	Wed May 28 01:22:47 2014 -0400
    11.3 @@ -457,7 +457,7 @@
    11.4      device->UpdateWindowFramebuffer = X11_UpdateWindowFramebuffer;
    11.5      device->DestroyWindowFramebuffer = X11_DestroyWindowFramebuffer;
    11.6      device->GetWindowWMInfo = X11_GetWindowWMInfo;
    11.7 -    device->SetWindowDragAreas = X11_SetWindowDragAreas;
    11.8 +    device->SetWindowHitTest = X11_SetWindowHitTest;
    11.9  
   11.10      device->shape_driver.CreateShaper = X11_CreateShaper;
   11.11      device->shape_driver.SetWindowShape = X11_SetWindowShape;
    12.1 --- a/src/video/x11/SDL_x11window.c	Tue May 27 15:47:25 2014 -0400
    12.2 +++ b/src/video/x11/SDL_x11window.c	Wed May 28 01:22:47 2014 -0400
    12.3 @@ -1445,9 +1445,9 @@
    12.4  }
    12.5  
    12.6  int
    12.7 -X11_SetWindowDragAreas(SDL_Window *window, const SDL_Rect *areas, int num_areas)
    12.8 +X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
    12.9  {
   12.10 -    return 0; // nothing to do, will be handled in event handler
   12.11 +    return 0;  /* just succeed, the real work is done elsewhere. */
   12.12  }
   12.13  
   12.14  #endif /* SDL_VIDEO_DRIVER_X11 */
    13.1 --- a/src/video/x11/SDL_x11window.h	Tue May 27 15:47:25 2014 -0400
    13.2 +++ b/src/video/x11/SDL_x11window.h	Wed May 28 01:22:47 2014 -0400
    13.3 @@ -93,7 +93,7 @@
    13.4  extern void X11_DestroyWindow(_THIS, SDL_Window * window);
    13.5  extern SDL_bool X11_GetWindowWMInfo(_THIS, SDL_Window * window,
    13.6                                      struct SDL_SysWMinfo *info);
    13.7 -extern int X11_SetWindowDragAreas(SDL_Window *window, const SDL_Rect *areas, int num_areas);
    13.8 +extern int X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
    13.9  
   13.10  #endif /* _SDL_x11window_h */
   13.11  
    14.1 --- a/test/Makefile.in	Tue May 27 15:47:25 2014 -0400
    14.2 +++ b/test/Makefile.in	Wed May 28 01:22:47 2014 -0400
    14.3 @@ -12,7 +12,6 @@
    14.4  	loopwave$(EXE) \
    14.5  	testaudioinfo$(EXE) \
    14.6  	testautomation$(EXE) \
    14.7 -	testdragareas$(EXE) \
    14.8  	testdraw2$(EXE) \
    14.9  	testdrawchessboard$(EXE) \
   14.10  	testdropfile$(EXE) \
   14.11 @@ -24,6 +23,7 @@
   14.12  	testgles$(EXE) \
   14.13  	testgles2$(EXE) \
   14.14  	testhaptic$(EXE) \
   14.15 +	testhittesting$(EXE) \
   14.16  	testrumble$(EXE) \
   14.17  	testhotplug$(EXE) \
   14.18  	testthread$(EXE) \
   14.19 @@ -109,7 +109,7 @@
   14.20  testrelative$(EXE): $(srcdir)/testrelative.c
   14.21  	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
   14.22  
   14.23 -testdragareas$(EXE): $(srcdir)/testdragareas.c
   14.24 +testhittesting$(EXE): $(srcdir)/testhittesting.c
   14.25  	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
   14.26  
   14.27  testdraw2$(EXE): $(srcdir)/testdraw2.c
    15.1 --- a/test/testdragareas.c	Tue May 27 15:47:25 2014 -0400
    15.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.3 @@ -1,93 +0,0 @@
    15.4 -#include <stdio.h>
    15.5 -#include "SDL.h"
    15.6 -
    15.7 -/* !!! FIXME: rewrite this to be wired in to test framework. */
    15.8 -
    15.9 -int main(int argc, char **argv)
   15.10 -{
   15.11 -    int done = 0;
   15.12 -    SDL_Window *window;
   15.13 -    SDL_Renderer *renderer;
   15.14 -
   15.15 -    const SDL_Rect drag_areas[] = {
   15.16 -        { 20, 20, 100, 100 },
   15.17 -        { 200, 70, 100, 100 },
   15.18 -        { 400, 90, 100, 100 }
   15.19 -    };
   15.20 -
   15.21 -    const SDL_Rect *areas = drag_areas;
   15.22 -    int numareas = SDL_arraysize(drag_areas);
   15.23 -
   15.24 -    /* !!! FIXME: check for errors. */
   15.25 -    SDL_Init(SDL_INIT_VIDEO);
   15.26 -    window = SDL_CreateWindow("Drag the red boxes", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_BORDERLESS);
   15.27 -    renderer = SDL_CreateRenderer(window, -1, 0);
   15.28 -
   15.29 -    if (SDL_SetWindowDragAreas(window, areas, numareas) == -1) {
   15.30 -        fprintf(stderr, "Setting drag areas failed!\n");
   15.31 -        SDL_Quit();
   15.32 -        return 1;
   15.33 -    }
   15.34 -
   15.35 -    while (!done)
   15.36 -    {
   15.37 -        SDL_SetRenderDrawColor(renderer, 0, 0, 127, 255);
   15.38 -        SDL_RenderClear(renderer);
   15.39 -        SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
   15.40 -        SDL_RenderFillRects(renderer, areas, SDL_arraysize(drag_areas));
   15.41 -        SDL_RenderPresent(renderer);
   15.42 -
   15.43 -        SDL_Event e;
   15.44 -        int nothing_to_do = 1;
   15.45 -        while (SDL_PollEvent(&e)) {
   15.46 -            nothing_to_do = 0;
   15.47 -
   15.48 -            switch (e.type)
   15.49 -            {
   15.50 -                case SDL_MOUSEBUTTONDOWN:
   15.51 -                    printf("button down!\n");
   15.52 -                    break;
   15.53 -
   15.54 -                case SDL_MOUSEBUTTONUP:
   15.55 -                    printf("button up!\n");
   15.56 -                    break;
   15.57 -
   15.58 -                case SDL_WINDOWEVENT:
   15.59 -                    if (e.window.event == SDL_WINDOWEVENT_MOVED) {
   15.60 -                        printf("Window event moved to (%d, %d)!\n", (int) e.window.data1, (int) e.window.data2);
   15.61 -                    }
   15.62 -                    break;
   15.63 -
   15.64 -                case SDL_KEYDOWN:
   15.65 -                    if (e.key.keysym.sym == SDLK_ESCAPE) {
   15.66 -                        done = 1;
   15.67 -                    } else if (e.key.keysym.sym == SDLK_x) {
   15.68 -                        if (!areas) {
   15.69 -                            areas = drag_areas;
   15.70 -                            numareas = SDL_arraysize(drag_areas);
   15.71 -                        } else {
   15.72 -                            areas = NULL;
   15.73 -                            numareas = 0;
   15.74 -                        }
   15.75 -                        if (SDL_SetWindowDragAreas(window, areas, numareas) == -1) {
   15.76 -                            fprintf(stderr, "Setting drag areas failed!\n");
   15.77 -                            SDL_Quit();
   15.78 -                            return 1;
   15.79 -                        }
   15.80 -                    }
   15.81 -                    break;
   15.82 -
   15.83 -                case SDL_QUIT:
   15.84 -                    done = 1;
   15.85 -                    break;
   15.86 -            }
   15.87 -        }
   15.88 -
   15.89 -        if (nothing_to_do) {
   15.90 -            SDL_Delay(50);
   15.91 -        }
   15.92 -    }
   15.93 -
   15.94 -    SDL_Quit();
   15.95 -    return 0;
   15.96 -}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/test/testhittesting.c	Wed May 28 01:22:47 2014 -0400
    16.3 @@ -0,0 +1,102 @@
    16.4 +#include <stdio.h>
    16.5 +#include "SDL.h"
    16.6 +
    16.7 +/* !!! FIXME: rewrite this to be wired in to test framework. */
    16.8 +
    16.9 +const SDL_Rect drag_areas[] = {
   16.10 +    { 20, 20, 100, 100 },
   16.11 +    { 200, 70, 100, 100 },
   16.12 +    { 400, 90, 100, 100 }
   16.13 +};
   16.14 +
   16.15 +static const SDL_Rect *areas = drag_areas;
   16.16 +static int numareas = SDL_arraysize(drag_areas);
   16.17 +
   16.18 +static SDL_HitTestResult
   16.19 +hitTest(SDL_Window *window, const SDL_Point *pt, void *data)
   16.20 +{
   16.21 +    int i;
   16.22 +    for (i = 0; i < numareas; i++) {
   16.23 +        if (SDL_PointInRect(pt, &areas[i])) {
   16.24 +            return SDL_HITTEST_DRAGGABLE;
   16.25 +        }
   16.26 +    }
   16.27 +
   16.28 +    return SDL_HITTEST_NORMAL;
   16.29 +}
   16.30 +
   16.31 +
   16.32 +int main(int argc, char **argv)
   16.33 +{
   16.34 +    int done = 0;
   16.35 +    SDL_Window *window;
   16.36 +    SDL_Renderer *renderer;
   16.37 +
   16.38 +    /* !!! FIXME: check for errors. */
   16.39 +    SDL_Init(SDL_INIT_VIDEO);
   16.40 +    window = SDL_CreateWindow("Drag the red boxes", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_BORDERLESS);
   16.41 +    renderer = SDL_CreateRenderer(window, -1, 0);
   16.42 +
   16.43 +    if (SDL_SetWindowHitTest(window, hitTest, NULL) == -1) {
   16.44 +        fprintf(stderr, "Enabling hit-testing failed!\n");
   16.45 +        SDL_Quit();
   16.46 +        return 1;
   16.47 +    }
   16.48 +
   16.49 +    while (!done)
   16.50 +    {
   16.51 +        SDL_SetRenderDrawColor(renderer, 0, 0, 127, 255);
   16.52 +        SDL_RenderClear(renderer);
   16.53 +        SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
   16.54 +        SDL_RenderFillRects(renderer, areas, SDL_arraysize(drag_areas));
   16.55 +        SDL_RenderPresent(renderer);
   16.56 +
   16.57 +        SDL_Event e;
   16.58 +        int nothing_to_do = 1;
   16.59 +        while (SDL_PollEvent(&e)) {
   16.60 +            nothing_to_do = 0;
   16.61 +
   16.62 +            switch (e.type)
   16.63 +            {
   16.64 +                case SDL_MOUSEBUTTONDOWN:
   16.65 +                    printf("button down!\n");
   16.66 +                    break;
   16.67 +
   16.68 +                case SDL_MOUSEBUTTONUP:
   16.69 +                    printf("button up!\n");
   16.70 +                    break;
   16.71 +
   16.72 +                case SDL_WINDOWEVENT:
   16.73 +                    if (e.window.event == SDL_WINDOWEVENT_MOVED) {
   16.74 +                        printf("Window event moved to (%d, %d)!\n", (int) e.window.data1, (int) e.window.data2);
   16.75 +                    }
   16.76 +                    break;
   16.77 +
   16.78 +                case SDL_KEYDOWN:
   16.79 +                    if (e.key.keysym.sym == SDLK_ESCAPE) {
   16.80 +                        done = 1;
   16.81 +                    } else if (e.key.keysym.sym == SDLK_x) {
   16.82 +                        if (!areas) {
   16.83 +                            areas = drag_areas;
   16.84 +                            numareas = SDL_arraysize(drag_areas);
   16.85 +                        } else {
   16.86 +                            areas = NULL;
   16.87 +                            numareas = 0;
   16.88 +                        }
   16.89 +                    }
   16.90 +                    break;
   16.91 +
   16.92 +                case SDL_QUIT:
   16.93 +                    done = 1;
   16.94 +                    break;
   16.95 +            }
   16.96 +        }
   16.97 +
   16.98 +        if (nothing_to_do) {
   16.99 +            SDL_Delay(50);
  16.100 +        }
  16.101 +    }
  16.102 +
  16.103 +    SDL_Quit();
  16.104 +    return 0;
  16.105 +}