]> git.eshelyaron.com Git - emacs.git/commitdiff
Also fetch shapes via XCB for drag and drop
authorPo Lu <luangruo@yahoo.com>
Sat, 26 Mar 2022 09:10:42 +0000 (17:10 +0800)
committerPo Lu <luangruo@yahoo.com>
Sat, 26 Mar 2022 09:14:38 +0000 (17:14 +0800)
* configure.ac: Also look for xcb-shape.
* src/xterm.c (HAVE_XCB_SHAPE_INPUT_RECTS): New define.
(x_dnd_compute_toplevels): Use XCB for input shapes if possible.

configure.ac
src/xterm.c

index 4ac8c143e53b11c840660476ea6f84bdf489d96d..35ebbb2db0ece3331b8c72d817362928f3731a3b 100644 (file)
@@ -4540,6 +4540,7 @@ AC_SUBST(XDBE_LIBS)
 
 ### Use the Nonrectangular Window Shape extension if available.
 HAVE_XSHAPE=no
+HAVE_XCB_SHAPE=no
 if test "${HAVE_X11}" = "yes"; then
   AC_CHECK_HEADER(X11/extensions/shape.h,
     [AC_CHECK_LIB(Xext, XShapeQueryVersion, HAVE_XSHAPE=yes)],
@@ -4548,6 +4549,14 @@ if test "${HAVE_X11}" = "yes"; then
     ])
   if test $HAVE_XSHAPE = yes; then
     XSHAPE_LIBS=-lXext
+    AC_CHECK_HEADER(xcb/shape.h,
+      [AC_CHECK_LIB(xcb-shape, xcb_shape_combine, HAVE_XCB_SHAPE=yes)], [],
+      [#include <xcb/shape.h>])
+
+    if test $HAVE_XCB_SHAPE = yes && test "$XCB_LIBS" != ""; then
+      XSHAPE_LIBS="$XSHAPE_LIBS -lxcb-shape"
+      AC_DEFINE(HAVE_XCB_SHAPE, 1, [Define to 1 if XCB supports the Nonrectangular Window Shape extension.])
+    fi
   fi
   if test $HAVE_XSHAPE = yes; then
     AC_DEFINE(HAVE_XSHAPE, 1, [Define to 1 if you have the Nonrectangular Window Shape extension.])
index 7edec2cd4017347b05fab4c5bdff77b9b034f1da..e448c177c0a014f6662b532555ffcc3980ee3bbd 100644 (file)
@@ -550,6 +550,10 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #include <X11/extensions/shape.h>
 #endif
 
+#ifdef HAVE_XCB_SHAPE
+#include <xcb/shape.h>
+#endif
+
 /* Load sys/types.h if not already loaded.
    In some systems loading it twice is suicidal.  */
 #ifndef makedev
@@ -658,6 +662,12 @@ bool use_xim = true;
 bool use_xim = false;  /* configure --without-xim */
 #endif
 
+#if XCB_SHAPE_MAJOR_VERSION > 1              \
+  || (XCB_SHAPE_MAJOR_VERSION == 1 && \
+      XCB_SHAPE_MINOR_VERSION >= 1)
+#define HAVE_XCB_SHAPE_INPUT_RECTS
+#endif
+
 #ifdef USE_GTK
 /* GTK can't tolerate a call to `handle_interrupt' inside an event
    signal handler, but we have to store input events inside the
@@ -912,8 +922,21 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
   xcb_get_geometry_reply_t *geometry_reply;
   xcb_generic_error_t *error;
 #endif
+
+#ifdef HAVE_XCB_SHAPE
+  xcb_shape_get_rectangles_cookie_t *bounding_rect_cookies;
+  xcb_shape_get_rectangles_reply_t *bounding_rect_reply;
+  xcb_rectangle_iterator_t bounding_rect_iterator;
+#endif
+
+#ifdef HAVE_XCB_SHAPE_INPUT_RECTS
+  xcb_shape_get_rectangles_cookie_t *input_rect_cookies;
+  xcb_shape_get_rectangles_reply_t *input_rect_reply;
+  xcb_rectangle_iterator_t input_rect_iterator;
+#endif
+
   struct x_client_list_window *tem;
-#ifdef HAVE_XSHAPE
+#if defined HAVE_XSHAPE && !defined HAVE_XCB_SHAPE_INPUT_RECTS
   int count, ordering;
   XRectangle *rects;
 #endif
@@ -943,6 +966,13 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
     = alloca (sizeof *get_property_cookies * nitems);
   get_geometry_cookies
     = alloca (sizeof *get_geometry_cookies * nitems);
+  bounding_rect_cookies
+    = alloca (sizeof *bounding_rect_cookies * nitems);
+
+#ifdef HAVE_XCB_SHAPE_INPUT_RECTS
+  input_rect_cookies
+    = alloca (sizeof *input_rect_cookies * nitems);
+#endif
 
   for (i = 0; i < nitems; ++i)
     {
@@ -960,6 +990,23 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
                            0, 2);
       get_geometry_cookies[i]
        = xcb_get_geometry (dpyinfo->xcb_connection, (xcb_window_t) toplevels[i]);
+
+#ifdef HAVE_XCB_SHAPE
+      bounding_rect_cookies[i]
+       = xcb_shape_get_rectangles (dpyinfo->xcb_connection,
+                                   (xcb_window_t) toplevels[i],
+                                   XCB_SHAPE_SK_BOUNDING);
+#endif
+
+#ifdef HAVE_XCB_SHAPE_INPUT_RECTS
+      if (dpyinfo->xshape_major > 1
+         || (dpyinfo->xshape_major == 1
+             && dpyinfo->xshape_minor >= 1))
+       input_rect_cookies[i]
+         = xcb_shape_get_rectangles (dpyinfo->xcb_connection,
+                                     (xcb_window_t) toplevels[i],
+                                     XCB_SHAPE_SK_INPUT);
+#endif
     }
 #endif
 
@@ -1094,6 +1141,7 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
                                 ShapeNotifyMask);
              x_uncatch_errors ();
 
+#ifndef HAVE_XCB_SHAPE
              x_catch_errors (dpyinfo->display);
              rects = XShapeGetRectangles (dpyinfo->display,
                                           toplevels[i],
@@ -1114,7 +1162,78 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
 
                  XFree (rects);
                }
+#else
+             bounding_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
+                                                                   bounding_rect_cookies[i],
+                                                                   &error);
 
+             if (bounding_rect_reply)
+               {
+                 bounding_rect_iterator
+                   = xcb_shape_get_rectangles_rectangles_iterator (bounding_rect_reply);
+                 tem->n_bounding_rects = bounding_rect_iterator.rem + 1;
+                 tem->bounding_rects = xmalloc (tem->n_bounding_rects
+                                                * sizeof *tem->bounding_rects);
+                 tem->n_bounding_rects = 0;
+
+                 for (; bounding_rect_iterator.rem; xcb_rectangle_next (&bounding_rect_iterator))
+                   {
+                     tem->bounding_rects[tem->n_bounding_rects].x
+                       = bounding_rect_iterator.data->x;
+                     tem->bounding_rects[tem->n_bounding_rects].y
+                       = bounding_rect_iterator.data->y;
+                     tem->bounding_rects[tem->n_bounding_rects].width
+                       = bounding_rect_iterator.data->width;
+                     tem->bounding_rects[tem->n_bounding_rects].height
+                       = bounding_rect_iterator.data->height;
+
+                     tem->n_bounding_rects++;
+                   }
+
+                 free (bounding_rect_reply);
+               }
+             else
+               free (error);
+#endif
+
+#ifdef HAVE_XCB_SHAPE_INPUT_RECTS
+             if (dpyinfo->xshape_major > 1
+                 || (dpyinfo->xshape_major == 1
+                     && dpyinfo->xshape_minor >= 1))
+               {
+                 input_rect_reply = xcb_shape_get_rectangles_reply (dpyinfo->xcb_connection,
+                                                                    input_rect_cookies[i],
+                                                                    &error);
+
+                 if (input_rect_reply)
+                   {
+                     input_rect_iterator
+                       = xcb_shape_get_rectangles_rectangles_iterator (input_rect_reply);
+                     tem->n_input_rects = input_rect_iterator.rem + 1;
+                     tem->input_rects = xmalloc (tem->n_input_rects
+                                                 * sizeof *tem->input_rects);
+                     tem->n_input_rects = 0;
+
+                     for (; input_rect_iterator.rem; xcb_rectangle_next (&input_rect_iterator))
+                       {
+                         tem->input_rects[tem->n_input_rects].x
+                           = input_rect_iterator.data->x;
+                         tem->input_rects[tem->n_input_rects].y
+                           = input_rect_iterator.data->y;
+                         tem->input_rects[tem->n_input_rects].width
+                           = input_rect_iterator.data->width;
+                         tem->input_rects[tem->n_input_rects].height
+                           = input_rect_iterator.data->height;
+
+                         tem->n_input_rects++;
+                       }
+
+                     free (input_rect_reply);
+                   }
+                 else
+                   free (error);
+               }
+#else
 #ifdef ShapeInput
              if (dpyinfo->xshape_major > 1
                  || (dpyinfo->xshape_major == 1
@@ -1140,6 +1259,7 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
                      XFree (rects);
                    }
                }
+#endif
 #endif
            }