int img_id;
#ifdef HAVE_XWIDGETS
- /* Xwidget reference (type == XWIDGET_GLYPH). */
- struct xwidget *xwidget;
+ /* Xwidget ID. */
+ uint32_t xwidget;
#endif
/* Sub-structure for type == STRETCH_GLYPH. */
break;
}
-#ifdef HAVE_XWIDGETS
- /* Currently this seems needed to detect xwidget movement reliably.
- This is most probably because an xwidget glyph is represented in
- struct glyph's 'union u' by a pointer to a struct, which takes 8
- bytes in 64-bit builds, and thus the comparison of u.val values
- done by GLYPH_EQUAL_P doesn't work reliably, since it assumes the
- size of the union is 4 bytes. FIXME. */
- return 0;
-#endif
-
/* Can't scroll the display of w32 GUI frames when position of point
is indicated by the system caret, because scrolling the display
will then "copy" the pixels used by the caret. */
}
s->width = s->first_glyph->pixel_width;
s->ybase += s->first_glyph->voffset;
- s->xwidget = s->first_glyph->u.xwidget;
+ s->xwidget = xwidget_from_id (s->first_glyph->u.xwidget);
}
#endif
/* Fill glyph string S from a sequence of stretch glyphs.
glyph->padding_p = 0;
glyph->glyph_not_available_p = 0;
glyph->face_id = it->face_id;
- glyph->u.xwidget = it->xwidget;
+ glyph->u.xwidget = it->xwidget->xwidget_id;
glyph->font_type = FONT_TYPE_UNKNOWN;
if (it->bidi_p)
{
/* Cursor off. Will be switched on again in gui_update_window_end. */
gui_clear_cursor (w);
+#ifdef HAVE_XWIDGETS
+ /* "Copy" xwidget windows in the area that will be scrolled. */
+ Display *dpy = FRAME_X_DISPLAY (f);
+ Window window = FRAME_X_WINDOW (f);
+
+ Window root, parent, *children;
+ unsigned int nchildren;
+
+ if (XQueryTree (dpy, window, &root, &parent, &children, &nchildren))
+ {
+ /* Now find xwidget views situated between from_y and to_y, and
+ attached to w. */
+ for (unsigned int i = 0; i < nchildren; ++i)
+ {
+ Window child = children[i];
+ struct xwidget_view *view = xwidget_view_from_window (child);
+
+ if (view)
+ {
+ int window_y = view->y + view->clip_top;
+ int window_height = view->clip_bottom - view->clip_top;
+ int min_y = min (from_y, to_y);
+ int max_y = max (from_y, to_y);
+
+ Emacs_Rectangle r1, r2, result;
+ r1.x = w->pixel_left;
+ r1.y = min_y;
+ r1.width = w->pixel_width;
+ r1.height = max_y - min_y;
+ r2 = r1;
+ r2.y = window_y;
+ r2.height = window_height;
+
+ /* The window is offscreen, just unmap it. */
+ if (window_height == 0)
+ {
+ view->hidden = true;
+ XUnmapWindow (dpy, child);
+ continue;
+ }
+
+ bool intersects_p =
+ gui_intersect_rectangles (&r1, &r2, &result);
+
+ if (XWINDOW (view->w) == w && intersects_p)
+ {
+ int y = view->y + (to_y - from_y);
+ int text_area_x, text_area_y, text_area_width, text_area_height;
+ int clip_top, clip_bottom;
+
+ window_box (w, TEXT_AREA, &text_area_x, &text_area_y,
+ &text_area_width, &text_area_height);
+
+ clip_top = max (0, text_area_y - y);
+ clip_bottom = max (clip_top,
+ min (XXWIDGET (view->model)->height,
+ text_area_y + text_area_height - y));
+
+ view->y = y;
+ view->clip_top = clip_top;
+ view->clip_bottom = clip_bottom;
+
+ /* This means the view has moved offscreen. Unmap
+ it and hide it here. */
+ if ((view->clip_top - view->clip_bottom) <= 0)
+ {
+ view->hidden = true;
+ XUnmapWindow (dpy, child);
+ }
+ else
+ XMoveResizeWindow (dpy, child, view->x + view->clip_left,
+ view->y + view->clip_top,
+ view->clip_right - view->clip_left,
+ view->clip_top - view->clip_bottom);
+ XFlush (dpy);
+ }
+ }
+ }
+ XFree (children);
+ }
+#endif
+
#ifdef USE_CAIRO
if (FRAME_CR_CONTEXT (f))
{
#include "nsxwidget.h"
#endif
+static Lisp_Object id_to_xwidget_map;
+static uint32_t xwidget_counter = 0;
+
#ifdef USE_GTK
static Lisp_Object x_window_to_xwv_map;
#endif
XSETXWIDGET (val, xw);
Vxwidget_list = Fcons (val, Vxwidget_list);
xw->plist = Qnil;
+ xw->xwidget_id = ++xwidget_counter;
+
+ Fputhash (make_fixnum (xw->xwidget_id), val, id_to_xwidget_map);
#ifdef USE_GTK
xw->widgetwindow_osr = NULL;
return xv->hidden;
}
+struct xwidget *
+xwidget_from_id (uint32_t id)
+{
+ Lisp_Object key = make_fixnum (id);
+ Lisp_Object xwidget = Fgethash (key, id_to_xwidget_map, Qnil);
+
+ if (NILP (xwidget))
+ emacs_abort ();
+
+ return XXWIDGET (xwidget);
+}
+
#ifdef USE_GTK
struct xwidget_view *
Fprovide (intern ("xwidget-internal"), Qnil);
+ id_to_xwidget_map = CALLN (Fmake_hash_table, QCtest, Qeq);
+ staticpro (&id_to_xwidget_map);
+
#ifdef USE_GTK
x_window_to_xwv_map = CALLN (Fmake_hash_table, QCtest, Qeq);
/* The only call to xwidget_end_redisplay is in dispnew.
xwidget_end_redisplay (w->current_matrix); */
struct xwidget_view *xv
- = xwidget_view_lookup (glyph->u.xwidget, w);
+ = xwidget_view_lookup (xwidget_from_id (glyph->u.xwidget), w);
#ifdef USE_GTK
/* FIXME: Is it safe to assume xwidget_view_lookup
always succeeds here? If so, this comment can be removed.
{
CHECK_XWIDGET (xwidget);
struct xwidget *xw = XXWIDGET (xwidget);
+ Fremhash (make_fixnum (xw->xwidget_id), id_to_xwidget_map);
#ifdef USE_GTK
if (xw->widget_osr && xw->widgetwindow_osr)
{
int height;
int width;
+ uint32_t xwidget_id;
#if defined (USE_GTK)
/* For offscreen widgets, unused if not osr. */
Lisp_Object argument);
struct xwidget_view *xwidget_view_from_window (Window wdesc);
void xwidget_expose (struct xwidget_view *xv);
+
+extern struct xwidget *xwidget_from_id (uint32_t id);
#else
INLINE_HEADER_BEGIN
INLINE void syms_of_xwidget (void) {}