Commit 2744c0195a29637d3401929e2fd011b14fd3a093

Damian Kaczmarek 2014-05-27T14:41:16

Initial work on X11 implementation of SDL_SetWindowDragAreas().

diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c
index 50e7394..db6a301 100644
--- a/src/video/x11/SDL_x11events.c
+++ b/src/video/x11/SDL_x11events.c
@@ -273,6 +273,51 @@ X11_DispatchUnmapNotify(SDL_WindowData *data)
 }
 
 static void
+InitiateWindowMove(SDL_Window *window)
+{
+    SDL_SysWMinfo info;
+    SDL_VERSION(&info.version);
+    SDL_GetWindowWMInfo(window, &info);
+    Display *display = info.info.x11.display;
+
+    int bx, by, dx, dy;
+    SDL_GetWindowPosition(window, &bx, &by);
+    SDL_GetMouseState(&dx, &dy);
+    X11_XUngrabPointer(display, 0L);
+    X11_XFlush(display);
+
+    XEvent evt;
+    evt.xclient.type = ClientMessage;
+    evt.xclient.window = info.info.x11.window;
+    evt.xclient.message_type = X11_XInternAtom(display, "_NET_WM_MOVERESIZE", False);
+    evt.xclient.format = 32;
+    evt.xclient.data.l[0] = bx + dx;
+    evt.xclient.data.l[1] = by + dy;
+    evt.xclient.data.l[2] = 8; /* _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
+ProcessDragArea(SDL_WindowData* data)
+{
+    SDL_Window* window = data->window;
+    SDL_Mouse* mouse = SDL_GetMouse();
+    int i;
+    const int num_areas = window->num_drag_areas;
+    const SDL_Point point = {mouse->x, mouse->y};
+    const SDL_Rect *areas = window->drag_areas;
+    for(i = 0;i < num_areas;++i) {
+        if (SDL_PointInRect(&point, &areas[i])) {
+            InitiateWindowMove(window);
+        }
+    }
+}
+
+static void
 X11_DispatchEvent(_THIS)
 {
     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
@@ -709,6 +754,9 @@ X11_DispatchEvent(_THIS)
             if (X11_IsWheelEvent(display,&xevent,&ticks)) {
                 SDL_SendMouseWheel(data->window, 0, 0, ticks);
             } else {
+                if(xevent.xbutton.button == SDL_BUTTON_LEFT) {
+                    ProcessDragArea(data);
+                }
                 SDL_SendMouseButton(data->window, 0, SDL_PRESSED, xevent.xbutton.button);
             }
         }
diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c
index ca9faee..4cece01 100644
--- a/src/video/x11/SDL_x11video.c
+++ b/src/video/x11/SDL_x11video.c
@@ -457,6 +457,7 @@ X11_CreateDevice(int devindex)
     device->UpdateWindowFramebuffer = X11_UpdateWindowFramebuffer;
     device->DestroyWindowFramebuffer = X11_DestroyWindowFramebuffer;
     device->GetWindowWMInfo = X11_GetWindowWMInfo;
+    device->SetWindowDragAreas = X11_SetWindowDragAreas;
 
     device->shape_driver.CreateShaper = X11_CreateShaper;
     device->shape_driver.SetWindowShape = X11_SetWindowShape;
diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c
index b4de15b..2c0c9e4 100644
--- a/src/video/x11/SDL_x11window.c
+++ b/src/video/x11/SDL_x11window.c
@@ -1444,6 +1444,12 @@ X11_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
     }
 }
 
+int
+X11_SetWindowDragAreas(SDL_Window *window, const SDL_Rect *areas, int num_areas)
+{
+    return 0; // nothing to do, will be handled in event handler
+}
+
 #endif /* SDL_VIDEO_DRIVER_X11 */
 
 /* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h
index cf0d7f7..6a00c1a 100644
--- a/src/video/x11/SDL_x11window.h
+++ b/src/video/x11/SDL_x11window.h
@@ -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_SetWindowDragAreas(SDL_Window *window, const SDL_Rect *areas, int num_areas);
 
 #endif /* _SDL_x11window_h */