[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master 5c387ad 02/35: Enable scrolling optimization for xwidgets
From: |
Lars Ingebrigtsen |
Subject: |
master 5c387ad 02/35: Enable scrolling optimization for xwidgets |
Date: |
Sat, 6 Nov 2021 22:01:54 -0400 (EDT) |
branch: master
commit 5c387ad437872c6e95599710ba5dcdfaa470c5ea
Author: Po Lu <luangruo@yahoo.com>
Commit: Lars Ingebrigtsen <larsi@gnus.org>
Enable scrolling optimization for xwidgets
* src/dispextern.h (struct glyph): Store xwidget ID instead of a
reference.
* src/dispnew.c (scrolling_window): Enable scrolling optimization on
xwidget builds.
* src/xdisp.c (fill_xwidget_glyph_string, produce_xwidget_glyph):
Obtain xwidget from ID.
* src/xterm.c (x_scroll_run): Scroll xwidget windows.
* src/xwidget.c (id_to_xwidget_map, xwidget_counter): New xwidget
variables.
(Fmake_xwidget): Assign each xwidget a unique ID, and keep track of
that ID.
(xwidget_from_id): New function.
(syms_of_xwidget): Initialize id_to_xwidget_map.
(xwidget_end_redisplay): Lookup xwidgets via ID.
* src/xwidget.h (struct xwidget): Add ID field.
(xwidget_from_id): New function.
---
src/dispextern.h | 4 +--
src/dispnew.c | 10 -------
src/xdisp.c | 4 +--
src/xterm.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/xwidget.c | 24 ++++++++++++++++-
src/xwidget.h | 3 +++
6 files changed, 112 insertions(+), 15 deletions(-)
diff --git a/src/dispextern.h b/src/dispextern.h
index 5b28fe7..f17f095 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -536,8 +536,8 @@ struct glyph
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. */
diff --git a/src/dispnew.c b/src/dispnew.c
index 4a73244..632eec2 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -4449,16 +4449,6 @@ scrolling_window (struct window *w, int tab_line_p)
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. */
diff --git a/src/xdisp.c b/src/xdisp.c
index 86c4e70..d7ad548 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -28429,7 +28429,7 @@ fill_xwidget_glyph_string (struct glyph_string *s)
}
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.
@@ -29832,7 +29832,7 @@ produce_xwidget_glyph (struct it *it)
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)
{
diff --git a/src/xterm.c b/src/xterm.c
index 54bfb65..b12c15c 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -4390,6 +4390,88 @@ x_scroll_run (struct window *w, struct run *run)
/* 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))
{
diff --git a/src/xwidget.c b/src/xwidget.c
index 62b30a0..68188eb 100644
--- a/src/xwidget.c
+++ b/src/xwidget.c
@@ -41,6 +41,9 @@ along with GNU Emacs. If not, see
<https://www.gnu.org/licenses/>. */
#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
@@ -114,6 +117,9 @@ Returns the newly constructed xwidget, or nil if
construction fails. */)
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;
@@ -227,6 +233,18 @@ xwidget_hidden (struct xwidget_view *xv)
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 *
@@ -1242,6 +1260,9 @@ syms_of_xwidget (void)
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);
@@ -1385,7 +1406,7 @@ xwidget_end_redisplay (struct window *w, struct
glyph_matrix *matrix)
/* 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.
@@ -1448,6 +1469,7 @@ kill_buffer_xwidgets (Lisp_Object buffer)
{
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)
{
diff --git a/src/xwidget.h b/src/xwidget.h
index fc68b52..28098c0 100644
--- a/src/xwidget.h
+++ b/src/xwidget.h
@@ -60,6 +60,7 @@ struct xwidget
int height;
int width;
+ uint32_t xwidget_id;
#if defined (USE_GTK)
/* For offscreen widgets, unused if not osr. */
@@ -168,6 +169,8 @@ void store_xwidget_js_callback_event (struct xwidget *xw,
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) {}
- master updated (d69b5a9 -> 5b7ab89), Lars Ingebrigtsen, 2021/11/06
- master 61d049a 01/35: Use an X window to display xwidgets on X11, Lars Ingebrigtsen, 2021/11/06
- master 5c387ad 02/35: Enable scrolling optimization for xwidgets,
Lars Ingebrigtsen <=
- master 9c9e15a 03/35: Destroy xwidgets when destroying frames, Lars Ingebrigtsen, 2021/11/06
- master 1e16fc2 05/35: Prefer XMoveResizeWindow to XMoveWindow for resizing xwidgets, Lars Ingebrigtsen, 2021/11/06
- master b39f1f1 07/35: Implement function for sending events to widgets, Lars Ingebrigtsen, 2021/11/06
- master f52f772 04/35: Allow xwidgets to accept motion and button events, Lars Ingebrigtsen, 2021/11/06
- master c9c1b43 06/35: Use gtk_widget_queue_draw instead of xv_do_draw, Lars Ingebrigtsen, 2021/11/06
- master b48a89f 11/35: Fix special events in xwidgets, Lars Ingebrigtsen, 2021/11/06
- master 32b9df6 10/35: Fix drag on xwidget motion events, Lars Ingebrigtsen, 2021/11/06
- master 6ed7454 12/35: Add xwidget-webkit-edit-mode to make using the WebKit browser easier, Lars Ingebrigtsen, 2021/11/06
- master 8ddeebb 13/35: Allow enabling xwidget-webkit-edit-mode via a binding, Lars Ingebrigtsen, 2021/11/06
- master 74711c0 22/35: Display page titles in xwidget webkit header line, Lars Ingebrigtsen, 2021/11/06