Added SDL_HITTEST_RESIZE_*, and implemented for X11.
authorIonut Leonte
Thu, 05 Jun 2014 00:45:16 -0400
changeset 8946c9592936dffc
parent 8945 04248c700ada
child 8947 14d3e9f93c16
Added SDL_HITTEST_RESIZE_*, and implemented for X11.
include/SDL_video.h
src/video/x11/SDL_x11events.c
test/testhittesting.c
     1.1 --- a/include/SDL_video.h	Thu Jun 05 00:03:33 2014 -0400
     1.2 +++ b/include/SDL_video.h	Thu Jun 05 00:45:16 2014 -0400
     1.3 @@ -800,7 +800,14 @@
     1.4  {
     1.5      SDL_HITTEST_NORMAL,  /**< Region is normal. No special properties. */
     1.6      SDL_HITTEST_DRAGGABLE,  /**< Region can drag entire window. */
     1.7 -    /* !!! FIXME: resize enums here. */
     1.8 +    SDL_HITTEST_RESIZE_TOPLEFT,
     1.9 +    SDL_HITTEST_RESIZE_TOP,
    1.10 +    SDL_HITTEST_RESIZE_TOPRIGHT,
    1.11 +    SDL_HITTEST_RESIZE_RIGHT,
    1.12 +    SDL_HITTEST_RESIZE_BOTTOMRIGHT,
    1.13 +    SDL_HITTEST_RESIZE_BOTTOM,
    1.14 +    SDL_HITTEST_RESIZE_BOTTOMLEFT,
    1.15 +    SDL_HITTEST_RESIZE_LEFT
    1.16  } SDL_HitTestResult;
    1.17  
    1.18  /**
     2.1 --- a/src/video/x11/SDL_x11events.c	Thu Jun 05 00:03:33 2014 -0400
     2.2 +++ b/src/video/x11/SDL_x11events.c	Thu Jun 05 00:45:16 2014 -0400
     2.3 @@ -40,8 +40,40 @@
     2.4  
     2.5  #include <stdio.h>
     2.6  
     2.7 +#ifndef _NET_WM_MOVERESIZE_SIZE_TOPLEFT
     2.8 +#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT      0
     2.9 +#endif
    2.10 +
    2.11 +#ifndef _NET_WM_MOVERESIZE_SIZE_TOP
    2.12 +#define _NET_WM_MOVERESIZE_SIZE_TOP          1
    2.13 +#endif
    2.14 +
    2.15 +#ifndef _NET_WM_MOVERESIZE_SIZE_TOPRIGHT
    2.16 +#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT     2
    2.17 +#endif
    2.18 +
    2.19 +#ifndef _NET_WM_MOVERESIZE_SIZE_RIGHT
    2.20 +#define _NET_WM_MOVERESIZE_SIZE_RIGHT        3
    2.21 +#endif
    2.22 +
    2.23 +#ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT
    2.24 +#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT  4
    2.25 +#endif
    2.26 +
    2.27 +#ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOM
    2.28 +#define _NET_WM_MOVERESIZE_SIZE_BOTTOM       5
    2.29 +#endif
    2.30 +
    2.31 +#ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT
    2.32 +#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT   6
    2.33 +#endif
    2.34 +
    2.35 +#ifndef _NET_WM_MOVERESIZE_SIZE_LEFT
    2.36 +#define _NET_WM_MOVERESIZE_SIZE_LEFT         7
    2.37 +#endif
    2.38 +
    2.39  #ifndef _NET_WM_MOVERESIZE_MOVE
    2.40 -#define _NET_WM_MOVERESIZE_MOVE 8
    2.41 +#define _NET_WM_MOVERESIZE_MOVE              8
    2.42  #endif
    2.43  
    2.44  typedef struct {
    2.45 @@ -290,7 +322,7 @@
    2.46      XEvent evt;
    2.47      evt.xclient.type = ClientMessage;
    2.48      evt.xclient.window = data->xwindow;
    2.49 -    evt.xclient.message_type = X11_XInternAtom(display, "_NET_WM_MOVERESIZE", False);
    2.50 +    evt.xclient.message_type = X11_XInternAtom(display, "_NET_WM_MOVERESIZE", True);
    2.51      evt.xclient.format = 32;
    2.52      evt.xclient.data.l[0] = window->x + point->x;
    2.53      evt.xclient.data.l[1] = window->y + point->y;
    2.54 @@ -302,21 +334,96 @@
    2.55      X11_XSync(display, 0);
    2.56  }
    2.57  
    2.58 +static void
    2.59 +InitiateWindowResize(_THIS, const SDL_WindowData *data, const SDL_Point *point, int direction)
    2.60 +{
    2.61 +    SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
    2.62 +    SDL_Window* window = data->window;
    2.63 +    Display *display = viddata->display;
    2.64 +
    2.65 +    if (direction < _NET_WM_MOVERESIZE_SIZE_TOPLEFT || direction > _NET_WM_MOVERESIZE_SIZE_LEFT)
    2.66 +        return;
    2.67 +
    2.68 +    /* !!! FIXME: we need to regrab this if necessary when the drag is done. */
    2.69 +    X11_XUngrabPointer(display, 0L);
    2.70 +    X11_XFlush(display);
    2.71 +
    2.72 +    XEvent evt;
    2.73 +    evt.xclient.type = ClientMessage;
    2.74 +    evt.xclient.window = data->xwindow;
    2.75 +    evt.xclient.message_type = X11_XInternAtom(display, "_NET_WM_MOVERESIZE", True);
    2.76 +    evt.xclient.format = 32;
    2.77 +    evt.xclient.data.l[0] = window->x + point->x;
    2.78 +    evt.xclient.data.l[1] = window->y + point->y;
    2.79 +    evt.xclient.data.l[2] = direction;
    2.80 +    evt.xclient.data.l[3] = Button1;
    2.81 +    evt.xclient.data.l[4] = 0;
    2.82 +    X11_XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &evt);
    2.83 +
    2.84 +    X11_XSync(display, 0);
    2.85 +}
    2.86 +
    2.87  static SDL_bool
    2.88  ProcessHitTest(_THIS, const SDL_WindowData *data, const XEvent *xev)
    2.89  {
    2.90      SDL_Window *window = data->window;
    2.91 +    SDL_bool ret = SDL_FALSE;
    2.92  
    2.93      if (window->hit_test) {
    2.94          const SDL_Point point = { xev->xbutton.x, xev->xbutton.y };
    2.95          const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
    2.96 -        if (rc == SDL_HITTEST_DRAGGABLE) {
    2.97 -            InitiateWindowMove(_this, data, &point);
    2.98 -            return SDL_TRUE;  /* dragging, drop this event. */
    2.99 +        switch (rc) {
   2.100 +            case SDL_HITTEST_DRAGGABLE: {
   2.101 +                    InitiateWindowMove(_this, data, &point);
   2.102 +                    ret = SDL_TRUE;
   2.103 +                }
   2.104 +                break;
   2.105 +            case SDL_HITTEST_RESIZE_TOPLEFT: {
   2.106 +                    InitiateWindowResize(_this, data, &point, _NET_WM_MOVERESIZE_SIZE_TOPLEFT);
   2.107 +                    ret = SDL_TRUE;
   2.108 +                }
   2.109 +                break;
   2.110 +            case SDL_HITTEST_RESIZE_TOP: {
   2.111 +                    InitiateWindowResize(_this, data, &point, _NET_WM_MOVERESIZE_SIZE_TOP);
   2.112 +                    ret = SDL_TRUE;
   2.113 +                }
   2.114 +                break;
   2.115 +            case SDL_HITTEST_RESIZE_TOPRIGHT: {
   2.116 +                    InitiateWindowResize(_this, data, &point, _NET_WM_MOVERESIZE_SIZE_TOPRIGHT);
   2.117 +                    ret = SDL_TRUE;
   2.118 +                }
   2.119 +                break;
   2.120 +            case SDL_HITTEST_RESIZE_RIGHT: {
   2.121 +                    InitiateWindowResize(_this, data, &point, _NET_WM_MOVERESIZE_SIZE_RIGHT);
   2.122 +                    ret = SDL_TRUE;
   2.123 +                }
   2.124 +                break;
   2.125 +            case SDL_HITTEST_RESIZE_BOTTOMRIGHT: {
   2.126 +                    InitiateWindowResize(_this, data, &point, _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT);
   2.127 +                    ret = SDL_TRUE;
   2.128 +                }
   2.129 +                break;
   2.130 +            case SDL_HITTEST_RESIZE_BOTTOM: {
   2.131 +                    InitiateWindowResize(_this, data, &point, _NET_WM_MOVERESIZE_SIZE_BOTTOM);
   2.132 +                    ret = SDL_TRUE;
   2.133 +                }
   2.134 +                break;
   2.135 +            case SDL_HITTEST_RESIZE_BOTTOMLEFT: {
   2.136 +                    InitiateWindowResize(_this, data, &point, _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT);
   2.137 +                    ret = SDL_TRUE;
   2.138 +                }
   2.139 +                break;
   2.140 +            case SDL_HITTEST_RESIZE_LEFT: {
   2.141 +                    InitiateWindowResize(_this, data, &point, _NET_WM_MOVERESIZE_SIZE_LEFT);
   2.142 +                    ret = SDL_TRUE;
   2.143 +                }
   2.144 +                break;
   2.145 +            default:
   2.146 +                break;
   2.147          }
   2.148      }
   2.149  
   2.150 -    return SDL_FALSE;  /* not a drag area. */
   2.151 +    return ret;
   2.152  }
   2.153  
   2.154  static void
     3.1 --- a/test/testhittesting.c	Thu Jun 05 00:03:33 2014 -0400
     3.2 +++ b/test/testhittesting.c	Thu Jun 05 00:45:16 2014 -0400
     3.3 @@ -3,6 +3,8 @@
     3.4  
     3.5  /* !!! FIXME: rewrite this to be wired in to test framework. */
     3.6  
     3.7 +#define RESIZE_BORDER 20
     3.8 +
     3.9  const SDL_Rect drag_areas[] = {
    3.10      { 20, 20, 100, 100 },
    3.11      { 200, 70, 100, 100 },
    3.12 @@ -16,6 +18,8 @@
    3.13  hitTest(SDL_Window *window, const SDL_Point *pt, void *data)
    3.14  {
    3.15      int i;
    3.16 +    int w, h;
    3.17 +
    3.18      for (i = 0; i < numareas; i++) {
    3.19          if (SDL_PointInRect(pt, &areas[i])) {
    3.20              SDL_Log("HIT-TEST: DRAGGABLE\n");
    3.21 @@ -23,6 +27,24 @@
    3.22          }
    3.23      }
    3.24  
    3.25 +    SDL_GetWindowSize(window, &w, &h);
    3.26 +    if (pt->x < RESIZE_BORDER && pt->y < RESIZE_BORDER)
    3.27 +        return SDL_HITTEST_RESIZE_TOPLEFT;
    3.28 +    if (pt->x > RESIZE_BORDER && pt->x < w - RESIZE_BORDER && pt->y < RESIZE_BORDER)
    3.29 +        return SDL_HITTEST_RESIZE_TOP;
    3.30 +    if (pt->x > w - RESIZE_BORDER && pt->y < RESIZE_BORDER)
    3.31 +        return SDL_HITTEST_RESIZE_TOPRIGHT;
    3.32 +    if (pt->x > w - RESIZE_BORDER && pt->y > RESIZE_BORDER && pt->y < h - RESIZE_BORDER)
    3.33 +        return SDL_HITTEST_RESIZE_RIGHT;
    3.34 +    if (pt->x > w - RESIZE_BORDER && pt->y > h - RESIZE_BORDER)
    3.35 +        return SDL_HITTEST_RESIZE_BOTTOMRIGHT;
    3.36 +    if (pt->x < w - RESIZE_BORDER && pt->x > RESIZE_BORDER && pt->y > h - RESIZE_BORDER)
    3.37 +        return SDL_HITTEST_RESIZE_BOTTOM;
    3.38 +    if (pt->x < RESIZE_BORDER && pt->y > h - RESIZE_BORDER)
    3.39 +        return SDL_HITTEST_RESIZE_BOTTOMLEFT;
    3.40 +    if (pt->x < RESIZE_BORDER && pt->y < h - RESIZE_BORDER && pt->y > RESIZE_BORDER)
    3.41 +        return SDL_HITTEST_RESIZE_LEFT;
    3.42 +
    3.43      SDL_Log("HIT-TEST: NORMAL\n");
    3.44      return SDL_HITTEST_NORMAL;
    3.45  }
    3.46 @@ -36,7 +58,7 @@
    3.47  
    3.48      /* !!! FIXME: check for errors. */
    3.49      SDL_Init(SDL_INIT_VIDEO);
    3.50 -    window = SDL_CreateWindow("Drag the red boxes", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_BORDERLESS);
    3.51 +    window = SDL_CreateWindow("Drag the red boxes", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE);
    3.52      renderer = SDL_CreateRenderer(window, -1, 0);
    3.53  
    3.54      if (SDL_SetWindowHitTest(window, hitTest, NULL) == -1) {