aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJoakim Verona2016-01-19 20:27:12 +0100
committerJoakim Verona2016-01-19 20:58:22 +0100
commit7c1f66a94bf236a427606ef537b4629a48a1665b (patch)
tree8661f512f7bcf35bfb1e7d915e5b6ef8df6229d8 /src
parent663d379bbc2fde5e9bded157365e9d48ea01c027 (diff)
downloademacs-7c1f66a94bf236a427606ef537b4629a48a1665b.tar.gz
emacs-7c1f66a94bf236a427606ef537b4629a48a1665b.zip
Support for the new Xwidget feature.
* configure.ac: (HAVE_XWIDGETS, WIDGET_OBJ, EMACS_CONFIG_FEATURES): * xterm.c (x_draw_glyph_string, x_draw_bar_cursor): * xdisp.c: (handle_display_spec, handle_single_display_spec, push_it) (pop_it, set_iterator_to_next, dump_glyph) (calc_pixel_width_or_height, fill_xwidget_glyph_string) (BUILD_XWIDGET_GLYPH_STRING, BUILD_GLYPH_STRINGS) (produce_xwidget_glyph, x_produce_glyphs) (get_window_cursor_type): * window.c (Fdelete_window_internal): * termhooks.h (e): * print.c (print_object): * lisp.h (ptrdiff_t): * keyboard.c (kbd_buffer_get_event, make_lispy_event) (syms_of_keyboard): * emacs.c (main): * dispnew.c (update_window, scrolling_window): * dispextern.h (g, i): * Makefile.in (XWIDGETS_OBJ, WEBKIT_CFLAGS, WEBKIT_LIBS) (GIR_LIBS, ALL_CFLAGS, base_obj, LIBES): * keyboard.c (kbd_buffer_get_event): * emacsgtkfixed.c (emacs_fixed_gtk_widget_size_allocate) (emacs_fixed_class_init): Add case for an xwidget view. * xwidget.c, xwidget.h, xwidget.el: New files for xwidgets Co-authored-by: Grégoire Jadi <daimrod@gmail.com> Various improvements to the Xwidget feature. * xwidgets.c: * emacsgtkfixed.c: * xwidget.el:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.in11
-rw-r--r--src/buffer.c6
-rw-r--r--src/dispextern.h28
-rw-r--r--src/dispnew.c12
-rw-r--r--src/emacs.c6
-rw-r--r--src/emacsgtkfixed.c105
-rw-r--r--src/emacsgtkfixed.h28
-rw-r--r--src/keyboard.c19
-rw-r--r--src/lisp.h6
-rw-r--r--src/print.c16
-rw-r--r--src/termhooks.h5
-rw-r--r--src/window.c6
-rw-r--r--src/xdisp.c248
-rw-r--r--src/xterm.c14
-rw-r--r--src/xwidget.c1332
-rw-r--r--src/xwidget.h135
16 files changed, 1954 insertions, 23 deletions
diff --git a/src/Makefile.in b/src/Makefile.in
index 74c0e4eeda5..2b5ae30a704 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -152,6 +152,9 @@ DBUS_LIBS = @DBUS_LIBS@
152## dbusbind.o if HAVE_DBUS, else empty. 152## dbusbind.o if HAVE_DBUS, else empty.
153DBUS_OBJ = @DBUS_OBJ@ 153DBUS_OBJ = @DBUS_OBJ@
154 154
155## xwidgets.o if HAVE_XWIDGETS, else empty.
156XWIDGETS_OBJ = @XWIDGETS_OBJ@
157
155LIB_EXECINFO=@LIB_EXECINFO@ 158LIB_EXECINFO=@LIB_EXECINFO@
156 159
157SETTINGS_CFLAGS = @SETTINGS_CFLAGS@ 160SETTINGS_CFLAGS = @SETTINGS_CFLAGS@
@@ -219,6 +222,11 @@ CFLAGS_SOUND= @CFLAGS_SOUND@
219RSVG_LIBS= @RSVG_LIBS@ 222RSVG_LIBS= @RSVG_LIBS@
220RSVG_CFLAGS= @RSVG_CFLAGS@ 223RSVG_CFLAGS= @RSVG_CFLAGS@
221 224
225WEBKIT_LIBS= @WEBKIT_LIBS@
226WEBKIT_CFLAGS= @WEBKIT_CFLAGS@
227
228GIR_LIBS= @GIR_LIBS@
229GIR_CFLAGS= @GIR_CFLAGS@
222CAIRO_LIBS= @CAIRO_LIBS@ 230CAIRO_LIBS= @CAIRO_LIBS@
223CAIRO_CFLAGS= @CAIRO_CFLAGS@ 231CAIRO_CFLAGS= @CAIRO_CFLAGS@
224 232
@@ -358,6 +366,7 @@ ALL_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \
358 $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \ 366 $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \
359 $(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \ 367 $(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \
360 $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \ 368 $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \
369 $(WEBKIT_CFLAGS) $(GIR_CFLAGS) \
361 $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ 370 $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
362 $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \ 371 $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
363 $(LIBGNUTLS_CFLAGS) $(GFILENOTIFY_CFLAGS) $(CAIRO_CFLAGS) \ 372 $(LIBGNUTLS_CFLAGS) $(GFILENOTIFY_CFLAGS) $(CAIRO_CFLAGS) \
@@ -387,6 +396,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
387 process.o gnutls.o callproc.o \ 396 process.o gnutls.o callproc.o \
388 region-cache.o sound.o atimer.o \ 397 region-cache.o sound.o atimer.o \
389 doprnt.o intervals.o textprop.o composite.o xml.o $(NOTIFY_OBJ) \ 398 doprnt.o intervals.o textprop.o composite.o xml.o $(NOTIFY_OBJ) \
399 $(XWIDGETS_OBJ) \
390 profiler.o decompress.o \ 400 profiler.o decompress.o \
391 $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \ 401 $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \
392 $(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ) 402 $(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ)
@@ -467,6 +477,7 @@ lisp = $(addprefix ${lispsource}/,${shortlisp})
467LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ 477LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
468 $(LIBX_OTHER) $(LIBSOUND) \ 478 $(LIBX_OTHER) $(LIBSOUND) \
469 $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \ 479 $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \
480 $(WEBKIT_LIBS) $(GIR_LIBS) \
470 $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \ 481 $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
471 $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \ 482 $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \
472 $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) $(CAIRO_LIBS) \ 483 $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) $(CAIRO_LIBS) \
diff --git a/src/buffer.c b/src/buffer.c
index b02135cef87..a2981c90f66 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -43,6 +43,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
43#include "keymap.h" 43#include "keymap.h"
44#include "frame.h" 44#include "frame.h"
45 45
46#ifdef HAVE_XWIDGETS
47# include "xwidget.h"
48#endif
46#ifdef WINDOWSNT 49#ifdef WINDOWSNT
47#include "w32heap.h" /* for mmap_* */ 50#include "w32heap.h" /* for mmap_* */
48#endif 51#endif
@@ -1747,6 +1750,9 @@ cleaning up all windows currently displaying the buffer to be killed. */)
1747 1750
1748 kill_buffer_processes (buffer); 1751 kill_buffer_processes (buffer);
1749 1752
1753#ifdef HAVE_XWIDGETS
1754 kill_buffer_xwidgets (buffer);
1755#endif
1750 /* Killing buffer processes may run sentinels which may have killed 1756 /* Killing buffer processes may run sentinels which may have killed
1751 our buffer. */ 1757 our buffer. */
1752 if (!BUFFER_LIVE_P (b)) 1758 if (!BUFFER_LIVE_P (b))
diff --git a/src/dispextern.h b/src/dispextern.h
index bb876f5af70..fad5bfd6f2f 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -348,6 +348,10 @@ enum glyph_type
348 348
349 /* Glyph is a space of fractional width and/or height. */ 349 /* Glyph is a space of fractional width and/or height. */
350 STRETCH_GLYPH 350 STRETCH_GLYPH
351#ifdef HAVE_XWIDGETS
352 /* Glyph is an external widget drawn by the GUI toolkit. */
353 ,XWIDGET_GLYPH
354#endif
351}; 355};
352 356
353 357
@@ -499,6 +503,9 @@ struct glyph
499 /* Image ID for image glyphs (type == IMAGE_GLYPH). */ 503 /* Image ID for image glyphs (type == IMAGE_GLYPH). */
500 int img_id; 504 int img_id;
501 505
506#ifdef HAVE_XWIDGETS
507 struct xwidget *xwidget;
508#endif
502 /* Sub-structure for type == STRETCH_GLYPH. */ 509 /* Sub-structure for type == STRETCH_GLYPH. */
503 struct 510 struct
504 { 511 {
@@ -1350,6 +1357,9 @@ struct glyph_string
1350 /* Image, if any. */ 1357 /* Image, if any. */
1351 struct image *img; 1358 struct image *img;
1352 1359
1360#ifdef HAVE_XWIDGETS
1361 struct xwidget *xwidget;
1362#endif
1353 /* Slice */ 1363 /* Slice */
1354 struct glyph_slice slice; 1364 struct glyph_slice slice;
1355 1365
@@ -2102,6 +2112,10 @@ enum display_element_type
2102 2112
2103 /* Continuation glyphs. See the comment for IT_TRUNCATION. */ 2113 /* Continuation glyphs. See the comment for IT_TRUNCATION. */
2104 IT_CONTINUATION 2114 IT_CONTINUATION
2115
2116#ifdef HAVE_XWIDGETS
2117 ,IT_XWIDGET
2118#endif
2105}; 2119};
2106 2120
2107 2121
@@ -2165,6 +2179,9 @@ enum it_method {
2165 GET_FROM_C_STRING, 2179 GET_FROM_C_STRING,
2166 GET_FROM_IMAGE, 2180 GET_FROM_IMAGE,
2167 GET_FROM_STRETCH, 2181 GET_FROM_STRETCH,
2182#ifdef HAVE_XWIDGETS
2183 GET_FROM_XWIDGET,
2184#endif
2168 NUM_IT_METHODS 2185 NUM_IT_METHODS
2169}; 2186};
2170 2187
@@ -2382,6 +2399,12 @@ struct it
2382 struct { 2399 struct {
2383 Lisp_Object object; 2400 Lisp_Object object;
2384 } stretch; 2401 } stretch;
2402#ifdef HAVE_XWIDGETS
2403 /* method == GET_FROM_XWIDGET */
2404 struct {
2405 Lisp_Object object;
2406 } xwidget;
2407#endif
2385 } u; 2408 } u;
2386 2409
2387 /* Current text and display positions. */ 2410 /* Current text and display positions. */
@@ -2506,6 +2529,11 @@ struct it
2506 /* If what == IT_IMAGE, the id of the image to display. */ 2529 /* If what == IT_IMAGE, the id of the image to display. */
2507 ptrdiff_t image_id; 2530 ptrdiff_t image_id;
2508 2531
2532#ifdef HAVE_XWIDGETS
2533 /* If what == IT_XWIDGET. */
2534 struct xwidget *xwidget;
2535#endif
2536
2509 /* Values from `slice' property. */ 2537 /* Values from `slice' property. */
2510 struct it_slice slice; 2538 struct it_slice slice;
2511 2539
diff --git a/src/dispnew.c b/src/dispnew.c
index 3e1557fa3b9..571ed5f851f 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -44,6 +44,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
44#include TERM_HEADER 44#include TERM_HEADER
45#endif /* HAVE_WINDOW_SYSTEM */ 45#endif /* HAVE_WINDOW_SYSTEM */
46 46
47#ifdef HAVE_XWIDGETS
48# include "xwidget.h"
49#endif
50
47#include <errno.h> 51#include <errno.h>
48 52
49#include <fpending.h> 53#include <fpending.h>
@@ -3545,6 +3549,9 @@ update_window (struct window *w, bool force_p)
3545 add_window_display_history (w, w->current_matrix->method, paused_p); 3549 add_window_display_history (w, w->current_matrix->method, paused_p);
3546#endif 3550#endif
3547 3551
3552#ifdef HAVE_XWIDGETS
3553 xwidget_end_redisplay (w, w->current_matrix);
3554#endif
3548 clear_glyph_matrix (desired_matrix); 3555 clear_glyph_matrix (desired_matrix);
3549 3556
3550 return paused_p; 3557 return paused_p;
@@ -4118,6 +4125,11 @@ scrolling_window (struct window *w, bool header_line_p)
4118 break; 4125 break;
4119 } 4126 }
4120 4127
4128#ifdef HAVE_XWIDGETS
4129 /* Currently this seems needed to detect xwidget movement reliably. */
4130 return 0;
4131#endif
4132
4121 /* Give up if some rows in the desired matrix are not enabled. */ 4133 /* Give up if some rows in the desired matrix are not enabled. */
4122 if (! MATRIX_ROW_ENABLED_P (desired_matrix, i)) 4134 if (! MATRIX_ROW_ENABLED_P (desired_matrix, i))
4123 return -1; 4135 return -1;
diff --git a/src/emacs.c b/src/emacs.c
index b1b2170a028..6de0fffb904 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -66,6 +66,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
66#include "buffer.h" 66#include "buffer.h"
67#include "window.h" 67#include "window.h"
68 68
69#ifdef HAVE_XWIDGETS
70# include "xwidget.h"
71#endif
69#include "atimer.h" 72#include "atimer.h"
70#include "blockinput.h" 73#include "blockinput.h"
71#include "syssignal.h" 74#include "syssignal.h"
@@ -1485,6 +1488,9 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1485 syms_of_xfns (); 1488 syms_of_xfns ();
1486 syms_of_xmenu (); 1489 syms_of_xmenu ();
1487 syms_of_fontset (); 1490 syms_of_fontset ();
1491#ifdef HAVE_XWIDGETS
1492 syms_of_xwidget ();
1493#endif
1488 syms_of_xsettings (); 1494 syms_of_xsettings ();
1489#ifdef HAVE_X_SM 1495#ifdef HAVE_X_SM
1490 syms_of_xsmfns (); 1496 syms_of_xsmfns ();
diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c
index cdcaf803ba5..da1017df2ae 100644
--- a/src/emacsgtkfixed.c
+++ b/src/emacsgtkfixed.c
@@ -23,6 +23,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
23#include "lisp.h" 23#include "lisp.h"
24#include "frame.h" 24#include "frame.h"
25#include "xterm.h" 25#include "xterm.h"
26#ifdef HAVE_XWIDGETS
27# include "xwidget.h"
28#endif
26#include "emacsgtkfixed.h" 29#include "emacsgtkfixed.h"
27 30
28/* Silence a bogus diagnostic; see GNOME bug 683906. */ 31/* Silence a bogus diagnostic; see GNOME bug 683906. */
@@ -31,27 +34,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
31# pragma GCC diagnostic ignored "-Wunused-local-typedefs" 34# pragma GCC diagnostic ignored "-Wunused-local-typedefs"
32#endif 35#endif
33 36
34#define EMACS_TYPE_FIXED emacs_fixed_get_type ()
35#define EMACS_FIXED(obj) \
36 G_TYPE_CHECK_INSTANCE_CAST (obj, EMACS_TYPE_FIXED, EmacsFixed)
37
38typedef struct _EmacsFixed EmacsFixed; 37typedef struct _EmacsFixed EmacsFixed;
39typedef struct _EmacsFixedPrivate EmacsFixedPrivate; 38typedef struct _EmacsFixedPrivate EmacsFixedPrivate;
40typedef struct _EmacsFixedClass EmacsFixedClass; 39typedef struct _EmacsFixedClass EmacsFixedClass;
41 40
42struct _EmacsFixed
43{
44 GtkFixed container;
45
46 /*< private >*/
47 EmacsFixedPrivate *priv;
48};
49
50struct _EmacsFixedClass
51{
52 GtkFixedClass parent_class;
53};
54
55struct _EmacsFixedPrivate 41struct _EmacsFixedPrivate
56{ 42{
57 struct frame *f; 43 struct frame *f;
@@ -64,9 +50,87 @@ static void emacs_fixed_get_preferred_width (GtkWidget *widget,
64static void emacs_fixed_get_preferred_height (GtkWidget *widget, 50static void emacs_fixed_get_preferred_height (GtkWidget *widget,
65 gint *minimum, 51 gint *minimum,
66 gint *natural); 52 gint *natural);
67static GType emacs_fixed_get_type (void);
68G_DEFINE_TYPE (EmacsFixed, emacs_fixed, GTK_TYPE_FIXED) 53G_DEFINE_TYPE (EmacsFixed, emacs_fixed, GTK_TYPE_FIXED)
69 54
55#ifdef HAVE_XWIDGETS
56
57struct GtkFixedPrivateL
58{
59 GList *children;
60};
61
62static void emacs_fixed_gtk_widget_size_allocate (GtkWidget *widget,
63 GtkAllocation *allocation)
64{
65 // For xwidgets.
66
67 // This basically re-implements the base class method and adds an
68 // additional case for an xwidget view.
69
70 // It would be nicer if the bse class method could be called first,
71 // and the the xview modification only would remain here. It wasn't
72 // possible to solve it that way yet.
73 EmacsFixedClass *klass;
74 GtkWidgetClass *parent_class;
75 struct GtkFixedPrivateL* priv;
76
77 klass = EMACS_FIXED_GET_CLASS (widget);
78 parent_class = g_type_class_peek_parent (klass);
79 parent_class->size_allocate (widget, allocation);
80
81 priv = G_TYPE_INSTANCE_GET_PRIVATE (widget,
82 GTK_TYPE_FIXED,
83 struct GtkFixedPrivateL);
84
85 gtk_widget_set_allocation (widget, allocation);
86
87 if (gtk_widget_get_has_window (widget))
88 {
89 if (gtk_widget_get_realized (widget))
90 gdk_window_move_resize (gtk_widget_get_window (widget),
91 allocation->x,
92 allocation->y,
93 allocation->width,
94 allocation->height);
95 }
96
97 for (GList *children = priv->children; children; children = children->next)
98 {
99 GtkFixedChild *child = children->data;
100
101 if (!gtk_widget_get_visible (child->widget))
102 continue;
103
104 GtkRequisition child_requisition;
105 gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL);
106
107 GtkAllocation child_allocation;
108 child_allocation.x = child->x;
109 child_allocation.y = child->y;
110
111 if (!gtk_widget_get_has_window (widget))
112 {
113 child_allocation.x += allocation->x;
114 child_allocation.y += allocation->y;
115 }
116
117 child_allocation.width = child_requisition.width;
118 child_allocation.height = child_requisition.height;
119
120 struct xwidget_view *xv
121 = g_object_get_data (G_OBJECT (child->widget), XG_XWIDGET_VIEW);
122 if (xv)
123 {
124 child_allocation.width = xv->clip_right;
125 child_allocation.height = xv->clip_bottom - xv->clip_top;
126 }
127
128 gtk_widget_size_allocate (child->widget, &child_allocation);
129 }
130}
131
132#endif /* HAVE_XWIDGETS */
133
70static void 134static void
71emacs_fixed_class_init (EmacsFixedClass *klass) 135emacs_fixed_class_init (EmacsFixedClass *klass)
72{ 136{
@@ -74,11 +138,16 @@ emacs_fixed_class_init (EmacsFixedClass *klass)
74 138
75 widget_class = (GtkWidgetClass*) klass; 139 widget_class = (GtkWidgetClass*) klass;
76 140
141
77 widget_class->get_preferred_width = emacs_fixed_get_preferred_width; 142 widget_class->get_preferred_width = emacs_fixed_get_preferred_width;
78 widget_class->get_preferred_height = emacs_fixed_get_preferred_height; 143 widget_class->get_preferred_height = emacs_fixed_get_preferred_height;
144#ifdef HAVE_XWIDGETS
145 widget_class->size_allocate = emacs_fixed_gtk_widget_size_allocate;
146#endif
79 g_type_class_add_private (klass, sizeof (EmacsFixedPrivate)); 147 g_type_class_add_private (klass, sizeof (EmacsFixedPrivate));
80} 148}
81 149
150
82static void 151static void
83emacs_fixed_init (EmacsFixed *fixed) 152emacs_fixed_init (EmacsFixed *fixed)
84{ 153{
diff --git a/src/emacsgtkfixed.h b/src/emacsgtkfixed.h
index 73280b83e57..5b2fa566785 100644
--- a/src/emacsgtkfixed.h
+++ b/src/emacsgtkfixed.h
@@ -27,7 +27,35 @@ struct frame;
27 27
28G_BEGIN_DECLS 28G_BEGIN_DECLS
29 29
30struct frame;
31
32#define EMACS_TYPE_FIXED (emacs_fixed_get_type ())
33#define EMACS_FIXED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMACS_TYPE_FIXED, EmacsFixed))
34#define EMACS_FIXED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EMACS_TYPE_FIXED, EmacsFixedClass))
35#define EMACS_IS_FIXED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMACS_TYPE_FIXED))
36#define EMACS_IS_FIXED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EMACS_TYPE_FIXED))
37#define EMACS_FIXED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EMACS_TYPE_FIXED, EmacsFixedClass))
38
39//typedef struct _EmacsFixed EmacsFixed;
40typedef struct _EmacsFixedPrivate EmacsFixedPrivate;
41typedef struct _EmacsFixedClass EmacsFixedClass;
42
43struct _EmacsFixed
44{
45 GtkFixed container;
46
47 /*< private >*/
48 EmacsFixedPrivate *priv;
49};
50
51
52struct _EmacsFixedClass
53{
54 GtkFixedClass parent_class;
55};
56
30extern GtkWidget *emacs_fixed_new (struct frame *f); 57extern GtkWidget *emacs_fixed_new (struct frame *f);
58extern GType emacs_fixed_get_type (void);
31 59
32G_END_DECLS 60G_END_DECLS
33 61
diff --git a/src/keyboard.c b/src/keyboard.c
index 6bdfc1aa084..58831f548ca 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -4014,6 +4014,13 @@ kbd_buffer_get_event (KBOARD **kbp,
4014 kbd_fetch_ptr = event + 1; 4014 kbd_fetch_ptr = event + 1;
4015 } 4015 }
4016#endif 4016#endif
4017#ifdef HAVE_XWIDGETS
4018 else if (event->kind == XWIDGET_EVENT)
4019 {
4020 obj = make_lispy_event (&event->ie);
4021 kbd_fetch_ptr = event + 1;
4022 }
4023#endif
4017 else if (event->kind == CONFIG_CHANGED_EVENT) 4024 else if (event->kind == CONFIG_CHANGED_EVENT)
4018 { 4025 {
4019 obj = make_lispy_event (&event->ie); 4026 obj = make_lispy_event (&event->ie);
@@ -5950,6 +5957,14 @@ make_lispy_event (struct input_event *event)
5950 } 5957 }
5951#endif /* HAVE_DBUS */ 5958#endif /* HAVE_DBUS */
5952 5959
5960#ifdef HAVE_XWIDGETS
5961 case XWIDGET_EVENT:
5962 {
5963 return Fcons (Qxwidget_event,event->arg);
5964 }
5965#endif
5966
5967
5953#if defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY 5968#if defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY
5954 case FILE_NOTIFY_EVENT: 5969 case FILE_NOTIFY_EVENT:
5955 { 5970 {
@@ -10956,6 +10971,10 @@ syms_of_keyboard (void)
10956 DEFSYM (Qdbus_event, "dbus-event"); 10971 DEFSYM (Qdbus_event, "dbus-event");
10957#endif 10972#endif
10958 10973
10974#ifdef HAVE_XWIDGETS
10975 DEFSYM (Qxwidget_event,"xwidget-event");
10976#endif
10977
10959#ifdef USE_FILE_NOTIFY 10978#ifdef USE_FILE_NOTIFY
10960 DEFSYM (Qfile_notify, "file-notify"); 10979 DEFSYM (Qfile_notify, "file-notify");
10961#endif /* USE_FILE_NOTIFY */ 10980#endif /* USE_FILE_NOTIFY */
diff --git a/src/lisp.h b/src/lisp.h
index f33a8f2494e..b0a8d75c439 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -799,6 +799,12 @@ enum pvec_type
799 PVEC_WINDOW_CONFIGURATION, 799 PVEC_WINDOW_CONFIGURATION,
800 PVEC_SUBR, 800 PVEC_SUBR,
801 PVEC_OTHER, 801 PVEC_OTHER,
802
803#ifdef HAVE_XWIDGETS
804 PVEC_XWIDGET,
805 PVEC_XWIDGET_VIEW,
806#endif
807
802 /* These should be last, check internal_equal to see why. */ 808 /* These should be last, check internal_equal to see why. */
803 PVEC_COMPILED, 809 PVEC_COMPILED,
804 PVEC_CHAR_TABLE, 810 PVEC_CHAR_TABLE,
diff --git a/src/print.c b/src/print.c
index 269d8f250e2..4dd4e963093 100644
--- a/src/print.c
+++ b/src/print.c
@@ -33,6 +33,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
33#include "intervals.h" 33#include "intervals.h"
34#include "blockinput.h" 34#include "blockinput.h"
35 35
36#ifdef HAVE_XWIDGETS
37# include "xwidget.h"
38#endif
39
36#include <c-ctype.h> 40#include <c-ctype.h>
37#include <float.h> 41#include <float.h>
38#include <ftoastr.h> 42#include <ftoastr.h>
@@ -1736,6 +1740,18 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1736 print_c_string (XSUBR (obj)->symbol_name, printcharfun); 1740 print_c_string (XSUBR (obj)->symbol_name, printcharfun);
1737 printchar ('>', printcharfun); 1741 printchar ('>', printcharfun);
1738 } 1742 }
1743#ifdef HAVE_XWIDGETS
1744 else if (XWIDGETP (obj))
1745 {
1746 print_c_string ("#<xwidget ", printcharfun);
1747 printchar ('>', printcharfun);
1748 }
1749 else if (XWIDGET_VIEW_P (obj))
1750 {
1751 print_c_string ("#<xwidget ", printcharfun);
1752 printchar ('>', printcharfun);
1753 }
1754#endif
1739 else if (WINDOWP (obj)) 1755 else if (WINDOWP (obj))
1740 { 1756 {
1741 int len = sprintf (buf, "#<window %"pI"d", 1757 int len = sprintf (buf, "#<window %"pI"d",
diff --git a/src/termhooks.h b/src/termhooks.h
index 29223757621..c183528ee84 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -239,6 +239,11 @@ enum event_kind
239 , NS_NONKEY_EVENT 239 , NS_NONKEY_EVENT
240#endif 240#endif
241 241
242#ifdef HAVE_XWIDGETS
243 /* events generated by xwidgets*/
244 , XWIDGET_EVENT
245#endif
246
242#ifdef USE_FILE_NOTIFY 247#ifdef USE_FILE_NOTIFY
243 /* File or directory was changed. */ 248 /* File or directory was changed. */
244 , FILE_NOTIFY_EVENT 249 , FILE_NOTIFY_EVENT
diff --git a/src/window.c b/src/window.c
index 2eacc3a2647..880ca4a46bb 100644
--- a/src/window.c
+++ b/src/window.c
@@ -41,6 +41,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
41#ifdef MSDOS 41#ifdef MSDOS
42#include "msdos.h" 42#include "msdos.h"
43#endif 43#endif
44#ifdef HAVE_XWIDGETS
45# include "xwidget.h"
46#endif
44 47
45static ptrdiff_t count_windows (struct window *); 48static ptrdiff_t count_windows (struct window *);
46static ptrdiff_t get_leaf_windows (struct window *, struct window **, 49static ptrdiff_t get_leaf_windows (struct window *, struct window **,
@@ -4370,6 +4373,9 @@ Signal an error when WINDOW is the only window on its frame. */)
4370 4373
4371 /* Block input. */ 4374 /* Block input. */
4372 block_input (); 4375 block_input ();
4376#ifdef HAVE_XWIDGETS
4377 xwidget_view_delete_all_in_window (w);
4378#endif
4373 window_resize_apply (p, horflag); 4379 window_resize_apply (p, horflag);
4374 /* If this window is referred to by the dpyinfo's mouse 4380 /* If this window is referred to by the dpyinfo's mouse
4375 highlight, invalidate that slot to be safe (Bug#9904). */ 4381 highlight, invalidate that slot to be safe (Bug#9904). */
diff --git a/src/xdisp.c b/src/xdisp.c
index d730a0bf1b6..89385c0e172 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -318,6 +318,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
318#include TERM_HEADER 318#include TERM_HEADER
319#endif /* HAVE_WINDOW_SYSTEM */ 319#endif /* HAVE_WINDOW_SYSTEM */
320 320
321#ifdef HAVE_XWIDGETS
322# include "xwidget.h"
323#endif
321#ifndef FRAME_X_OUTPUT 324#ifndef FRAME_X_OUTPUT
322#define FRAME_X_OUTPUT(f) ((f)->output_data.x) 325#define FRAME_X_OUTPUT(f) ((f)->output_data.x)
323#endif 326#endif
@@ -854,6 +857,9 @@ static bool next_element_from_buffer (struct it *);
854static bool next_element_from_composition (struct it *); 857static bool next_element_from_composition (struct it *);
855static bool next_element_from_image (struct it *); 858static bool next_element_from_image (struct it *);
856static bool next_element_from_stretch (struct it *); 859static bool next_element_from_stretch (struct it *);
860#ifdef HAVE_XWIDGETS
861static bool next_element_from_xwidget (struct it *);
862#endif
857static void load_overlay_strings (struct it *, ptrdiff_t); 863static void load_overlay_strings (struct it *, ptrdiff_t);
858static bool get_next_display_element (struct it *); 864static bool get_next_display_element (struct it *);
859static enum move_it_result 865static enum move_it_result
@@ -4690,6 +4696,9 @@ handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
4690 if (CONSP (spec) 4696 if (CONSP (spec)
4691 /* Simple specifications. */ 4697 /* Simple specifications. */
4692 && !EQ (XCAR (spec), Qimage) 4698 && !EQ (XCAR (spec), Qimage)
4699#ifdef HAVE_XWIDGETS
4700 && !EQ (XCAR (spec), Qxwidget)
4701#endif
4693 && !EQ (XCAR (spec), Qspace) 4702 && !EQ (XCAR (spec), Qspace)
4694 && !EQ (XCAR (spec), Qwhen) 4703 && !EQ (XCAR (spec), Qwhen)
4695 && !EQ (XCAR (spec), Qslice) 4704 && !EQ (XCAR (spec), Qslice)
@@ -5137,7 +5146,12 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5137 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p) 5146 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
5138 && valid_image_p (value)) 5147 && valid_image_p (value))
5139#endif /* not HAVE_WINDOW_SYSTEM */ 5148#endif /* not HAVE_WINDOW_SYSTEM */
5140 || (CONSP (value) && EQ (XCAR (value), Qspace))); 5149 || (CONSP (value) && EQ (XCAR (value), Qspace))
5150#ifdef HAVE_XWIDGETS
5151 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
5152 && valid_xwidget_spec_p (value))
5153#endif
5154 );
5141 5155
5142 if (valid_p && display_replaced == 0) 5156 if (valid_p && display_replaced == 0)
5143 { 5157 {
@@ -5212,6 +5226,17 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5212 *position = it->position = start_pos; 5226 *position = it->position = start_pos;
5213 retval = 1 + (it->area == TEXT_AREA); 5227 retval = 1 + (it->area == TEXT_AREA);
5214 } 5228 }
5229#ifdef HAVE_XWIDGETS
5230 else if (valid_xwidget_spec_p(value))
5231 {
5232 it->what = IT_XWIDGET;
5233 it->method = GET_FROM_XWIDGET;
5234 it->position = start_pos;
5235 it->object = NILP (object) ? it->w->contents : object;
5236 *position = start_pos;
5237 it->xwidget = lookup_xwidget(value);
5238 }
5239#endif
5215#ifdef HAVE_WINDOW_SYSTEM 5240#ifdef HAVE_WINDOW_SYSTEM
5216 else 5241 else
5217 { 5242 {
@@ -5964,6 +5989,11 @@ push_it (struct it *it, struct text_pos *position)
5964 case GET_FROM_STRETCH: 5989 case GET_FROM_STRETCH:
5965 p->u.stretch.object = it->object; 5990 p->u.stretch.object = it->object;
5966 break; 5991 break;
5992#ifdef HAVE_XWIDGETS
5993 case GET_FROM_XWIDGET:
5994 p->u.xwidget.object = it->object;
5995 break;
5996#endif
5967 case GET_FROM_BUFFER: 5997 case GET_FROM_BUFFER:
5968 case GET_FROM_DISPLAY_VECTOR: 5998 case GET_FROM_DISPLAY_VECTOR:
5969 case GET_FROM_STRING: 5999 case GET_FROM_STRING:
@@ -6065,6 +6095,11 @@ pop_it (struct it *it)
6065 it->object = p->u.image.object; 6095 it->object = p->u.image.object;
6066 it->slice = p->u.image.slice; 6096 it->slice = p->u.image.slice;
6067 break; 6097 break;
6098#ifdef HAVE_XWIDGETS
6099 case GET_FROM_XWIDGET:
6100 it->object = p->u.xwidget.object;
6101 break;
6102#endif
6068 case GET_FROM_STRETCH: 6103 case GET_FROM_STRETCH:
6069 it->object = p->u.stretch.object; 6104 it->object = p->u.stretch.object;
6070 break; 6105 break;
@@ -6739,7 +6774,10 @@ static next_element_function const get_next_element[NUM_IT_METHODS] =
6739 next_element_from_string, 6774 next_element_from_string,
6740 next_element_from_c_string, 6775 next_element_from_c_string,
6741 next_element_from_image, 6776 next_element_from_image,
6742 next_element_from_stretch 6777 next_element_from_stretch,
6778#ifdef HAVE_XWIDGETS
6779 next_element_from_xwidget,
6780#endif
6743}; 6781};
6744 6782
6745#define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it) 6783#define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it)
@@ -7600,6 +7638,10 @@ set_iterator_to_next (struct it *it, bool reseat_p)
7600 7638
7601 case GET_FROM_IMAGE: 7639 case GET_FROM_IMAGE:
7602 case GET_FROM_STRETCH: 7640 case GET_FROM_STRETCH:
7641#ifdef HAVE_XWIDGETS
7642 case GET_FROM_XWIDGET:
7643#endif
7644
7603 /* The position etc with which we have to proceed are on 7645 /* The position etc with which we have to proceed are on
7604 the stack. The position may be at the end of a string, 7646 the stack. The position may be at the end of a string,
7605 if the `display' property takes up the whole string. */ 7647 if the `display' property takes up the whole string. */
@@ -8061,6 +8103,15 @@ next_element_from_image (struct it *it)
8061 return true; 8103 return true;
8062} 8104}
8063 8105
8106#ifdef HAVE_XWIDGETS
8107static bool
8108next_element_from_xwidget (struct it *it)
8109{
8110 it->what = IT_XWIDGET;
8111 return true;
8112}
8113#endif
8114
8064 8115
8065/* Fill iterator IT with next display element from a stretch glyph 8116/* Fill iterator IT with next display element from a stretch glyph
8066 property. IT->object is the value of the text property. Value is 8117 property. IT->object is the value of the text property. Value is
@@ -18793,6 +18844,28 @@ dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
18793 glyph->left_box_line_p, 18844 glyph->left_box_line_p,
18794 glyph->right_box_line_p); 18845 glyph->right_box_line_p);
18795 } 18846 }
18847#ifdef HAVE_XWIDGETS
18848 else if (glyph->type == XWIDGET_GLYPH)
18849 {
18850 fprintf (stderr,
18851 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
18852 glyph - row->glyphs[TEXT_AREA],
18853 'X',
18854 glyph->charpos,
18855 (BUFFERP (glyph->object)
18856 ? 'B'
18857 : (STRINGP (glyph->object)
18858 ? 'S'
18859 : '-')),
18860 glyph->pixel_width,
18861 glyph->u.xwidget,
18862 '.',
18863 glyph->face_id,
18864 glyph->left_box_line_p,
18865 glyph->right_box_line_p);
18866
18867 }
18868#endif
18796} 18869}
18797 18870
18798 18871
@@ -24291,6 +24364,13 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
24291 24364
24292 return OK_PIXELS (width_p ? img->width : img->height); 24365 return OK_PIXELS (width_p ? img->width : img->height);
24293 } 24366 }
24367# ifdef HAVE_XWIDGETS
24368 if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop))
24369 {
24370 // TODO: Don't return dummy size.
24371 return OK_PIXELS (100);
24372 }
24373# endif
24294#endif 24374#endif
24295 if (EQ (car, Qplus) || EQ (car, Qminus)) 24375 if (EQ (car, Qplus) || EQ (car, Qminus))
24296 { 24376 {
@@ -24796,6 +24876,18 @@ fill_image_glyph_string (struct glyph_string *s)
24796} 24876}
24797 24877
24798 24878
24879#ifdef HAVE_XWIDGETS
24880static void
24881fill_xwidget_glyph_string (struct glyph_string *s)
24882{
24883 eassert (s->first_glyph->type == XWIDGET_GLYPH);
24884 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
24885 s->font = s->face->font;
24886 s->width = s->first_glyph->pixel_width;
24887 s->ybase += s->first_glyph->voffset;
24888 s->xwidget = s->first_glyph->u.xwidget;
24889}
24890#endif
24799/* Fill glyph string S from a sequence of stretch glyphs. 24891/* Fill glyph string S from a sequence of stretch glyphs.
24800 24892
24801 START is the index of the first glyph to consider, 24893 START is the index of the first glyph to consider,
@@ -25181,6 +25273,20 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
25181 } \ 25273 } \
25182 while (false) 25274 while (false)
25183 25275
25276#ifdef HAVE_XWIDGETS
25277#define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
25278 do \
25279 { \
25280 s = alloca (sizeof *s); \
25281 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
25282 fill_xwidget_glyph_string (s); \
25283 append_glyph_string (&(HEAD), &(TAIL), s); \
25284 ++(START); \
25285 s->x = (X); \
25286 } \
25287 while (false)
25288#endif
25289
25184 25290
25185/* Add a glyph string for a sequence of character glyphs to the list 25291/* Add a glyph string for a sequence of character glyphs to the list
25186 of strings between HEAD and TAIL. START is the index of the first 25292 of strings between HEAD and TAIL. START is the index of the first
@@ -25302,7 +25408,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
25302 to allocate glyph strings (because draw_glyphs can be called 25408 to allocate glyph strings (because draw_glyphs can be called
25303 asynchronously). */ 25409 asynchronously). */
25304 25410
25305#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \ 25411#define BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
25306 do \ 25412 do \
25307 { \ 25413 { \
25308 HEAD = TAIL = NULL; \ 25414 HEAD = TAIL = NULL; \
@@ -25333,8 +25439,17 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
25333 case IMAGE_GLYPH: \ 25439 case IMAGE_GLYPH: \
25334 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \ 25440 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \
25335 HL, X, LAST_X); \ 25441 HL, X, LAST_X); \
25336 break; \ 25442 break;
25337 \ 25443
25444#ifdef HAVE_XWIDGETS
25445# define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
25446 case XWIDGET_GLYPH: \
25447 BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL, \
25448 HL, X, LAST_X); \
25449 break;
25450#endif
25451
25452#define BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) \
25338 case GLYPHLESS_GLYPH: \ 25453 case GLYPHLESS_GLYPH: \
25339 BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \ 25454 BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \
25340 HL, X, LAST_X); \ 25455 HL, X, LAST_X); \
@@ -25353,6 +25468,18 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
25353 } while (false) 25468 } while (false)
25354 25469
25355 25470
25471#ifdef HAVE_XWIDGETS
25472# define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
25473 BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
25474 BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
25475 BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
25476#else
25477# define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
25478 BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
25479 BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
25480#endif
25481
25482
25356/* Draw glyphs between START and END in AREA of ROW on window W, 25483/* Draw glyphs between START and END in AREA of ROW on window W,
25357 starting at x-position X. X is relative to AREA in W. HL is a 25484 starting at x-position X. X is relative to AREA in W. HL is a
25358 face-override with the following meaning: 25485 face-override with the following meaning:
@@ -25991,6 +26118,109 @@ produce_image_glyph (struct it *it)
25991 } 26118 }
25992} 26119}
25993 26120
26121#ifdef HAVE_XWIDGETS
26122static void
26123produce_xwidget_glyph (struct it *it)
26124{
26125 struct xwidget *xw;
26126 int glyph_ascent, crop;
26127 eassert (it->what == IT_XWIDGET);
26128
26129 struct face *face = FACE_FROM_ID (it->f, it->face_id);
26130 eassert (face);
26131 /* Make sure X resources of the face is loaded. */
26132 prepare_face_for_display (it->f, face);
26133
26134 xw = it->xwidget;
26135 it->ascent = it->phys_ascent = glyph_ascent = xw->height/2;
26136 it->descent = xw->height/2;
26137 it->phys_descent = it->descent;
26138 it->pixel_width = xw->width;
26139 /* It's quite possible for images to have an ascent greater than
26140 their height, so don't get confused in that case. */
26141 if (it->descent < 0)
26142 it->descent = 0;
26143
26144 it->nglyphs = 1;
26145
26146 if (face->box != FACE_NO_BOX)
26147 {
26148 if (face->box_line_width > 0)
26149 {
26150 it->ascent += face->box_line_width;
26151 it->descent += face->box_line_width;
26152 }
26153
26154 if (it->start_of_box_run_p)
26155 it->pixel_width += eabs (face->box_line_width);
26156 it->pixel_width += eabs (face->box_line_width);
26157 }
26158
26159 take_vertical_position_into_account (it);
26160
26161 /* Automatically crop wide image glyphs at right edge so we can
26162 draw the cursor on same display row. */
26163 crop = it->pixel_width - (it->last_visible_x - it->current_x);
26164 if (crop > 0 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
26165 it->pixel_width -= crop;
26166
26167 if (it->glyph_row)
26168 {
26169 enum glyph_row_area area = it->area;
26170 struct glyph *glyph
26171 = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
26172
26173 if (it->glyph_row->reversed_p)
26174 {
26175 struct glyph *g;
26176
26177 /* Make room for the new glyph. */
26178 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
26179 g[1] = *g;
26180 glyph = it->glyph_row->glyphs[it->area];
26181 }
26182 if (glyph < it->glyph_row->glyphs[area + 1])
26183 {
26184 glyph->charpos = CHARPOS (it->position);
26185 glyph->object = it->object;
26186 glyph->pixel_width = it->pixel_width;
26187 glyph->ascent = glyph_ascent;
26188 glyph->descent = it->descent;
26189 glyph->voffset = it->voffset;
26190 glyph->type = XWIDGET_GLYPH;
26191 glyph->avoid_cursor_p = it->avoid_cursor_p;
26192 glyph->multibyte_p = it->multibyte_p;
26193 if (it->glyph_row->reversed_p && area == TEXT_AREA)
26194 {
26195 /* In R2L rows, the left and the right box edges need to be
26196 drawn in reverse direction. */
26197 glyph->right_box_line_p = it->start_of_box_run_p;
26198 glyph->left_box_line_p = it->end_of_box_run_p;
26199 }
26200 else
26201 {
26202 glyph->left_box_line_p = it->start_of_box_run_p;
26203 glyph->right_box_line_p = it->end_of_box_run_p;
26204 }
26205 glyph->overlaps_vertically_p = 0;
26206 glyph->padding_p = 0;
26207 glyph->glyph_not_available_p = 0;
26208 glyph->face_id = it->face_id;
26209 glyph->u.xwidget = it->xwidget;
26210 glyph->font_type = FONT_TYPE_UNKNOWN;
26211 if (it->bidi_p)
26212 {
26213 glyph->resolved_level = it->bidi_it.resolved_level;
26214 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
26215 glyph->bidi_type = it->bidi_it.type;
26216 }
26217 ++it->glyph_row->used[area];
26218 }
26219 else
26220 IT_EXPAND_MATRIX_WIDTH (it, area);
26221 }
26222}
26223#endif
25994 26224
25995/* Append a stretch glyph to IT->glyph_row. OBJECT is the source 26225/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
25996 of the glyph, WIDTH and HEIGHT are the width and height of the 26226 of the glyph, WIDTH and HEIGHT are the width and height of the
@@ -27401,6 +27631,10 @@ x_produce_glyphs (struct it *it)
27401 produce_image_glyph (it); 27631 produce_image_glyph (it);
27402 else if (it->what == IT_STRETCH) 27632 else if (it->what == IT_STRETCH)
27403 produce_stretch_glyph (it); 27633 produce_stretch_glyph (it);
27634#ifdef HAVE_XWIDGETS
27635 else if (it->what == IT_XWIDGET)
27636 produce_xwidget_glyph (it);
27637#endif
27404 27638
27405 done: 27639 done:
27406 /* Accumulate dimensions. Note: can't assume that it->descent > 0 27640 /* Accumulate dimensions. Note: can't assume that it->descent > 0
@@ -27770,6 +28004,10 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
27770 /* Use normal cursor if not blinked off. */ 28004 /* Use normal cursor if not blinked off. */
27771 if (!w->cursor_off_p) 28005 if (!w->cursor_off_p)
27772 { 28006 {
28007#ifdef HAVE_XWIDGETS
28008 if (glyph != NULL && glyph->type == XWIDGET_GLYPH)
28009 return NO_CURSOR;
28010#endif
27773 if (glyph != NULL && glyph->type == IMAGE_GLYPH) 28011 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
27774 { 28012 {
27775 if (cursor_type == FILLED_BOX_CURSOR) 28013 if (cursor_type == FILLED_BOX_CURSOR)
diff --git a/src/xterm.c b/src/xterm.c
index 5a6d643bad4..44eed22d2ec 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -62,6 +62,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
62#include "composite.h" 62#include "composite.h"
63#include "frame.h" 63#include "frame.h"
64#include "dispextern.h" 64#include "dispextern.h"
65#ifdef HAVE_XWIDGETS
66# include "xwidget.h"
67#endif
65#include "fontset.h" 68#include "fontset.h"
66#include "termhooks.h" 69#include "termhooks.h"
67#include "termopts.h" 70#include "termopts.h"
@@ -3511,6 +3514,12 @@ x_draw_glyph_string (struct glyph_string *s)
3511 x_draw_image_glyph_string (s); 3514 x_draw_image_glyph_string (s);
3512 break; 3515 break;
3513 3516
3517#ifdef HAVE_XWIDGETS
3518 case XWIDGET_GLYPH:
3519 x_draw_xwidget_glyph_string (s);
3520 break;
3521#endif
3522
3514 case STRETCH_GLYPH: 3523 case STRETCH_GLYPH:
3515 x_draw_stretch_glyph_string (s); 3524 x_draw_stretch_glyph_string (s);
3516 break; 3525 break;
@@ -8920,6 +8929,11 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
8920 if (cursor_glyph == NULL) 8929 if (cursor_glyph == NULL)
8921 return; 8930 return;
8922 8931
8932#ifdef HAVE_XWIDGETS
8933 if (cursor_glyph->type == XWIDGET_GLYPH)
8934 return; // Experimental avoidance of cursor on xwidget.
8935#endif
8936
8923 /* If on an image, draw like a normal cursor. That's usually better 8937 /* If on an image, draw like a normal cursor. That's usually better
8924 visible than drawing a bar, esp. if the image is large so that 8938 visible than drawing a bar, esp. if the image is large so that
8925 the bar might not be in the window. */ 8939 the bar might not be in the window. */
diff --git a/src/xwidget.c b/src/xwidget.c
new file mode 100644
index 00000000000..74319e1667d
--- /dev/null
+++ b/src/xwidget.c
@@ -0,0 +1,1332 @@
1/* Support for embedding graphical components in a buffer.
2
3Copyright (C) 2011-2015 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19
20#include <config.h>
21
22
23#include <signal.h>
24
25#include <stdio.h>
26#include <setjmp.h>
27#ifdef HAVE_X_WINDOWS
28
29#include "lisp.h"
30#include "blockinput.h"
31#include "syssignal.h"
32
33#include "xterm.h"
34#include <X11/cursorfont.h>
35
36#ifndef makedev
37# include <sys/types.h>
38#endif
39
40#ifdef BSD_SYSTEM
41# include <sys/ioctl.h>
42#endif
43
44#include "systime.h"
45
46#ifndef INCLUDED_FCNTL
47# include <fcntl.h>
48#endif
49#include <ctype.h>
50#include <errno.h>
51#include <setjmp.h>
52#include <sys/stat.h>
53
54#include "charset.h"
55#include "character.h"
56#include "coding.h"
57#include "ccl.h"
58#include "frame.h"
59#include "dispextern.h"
60#include "fontset.h"
61#include "termhooks.h"
62#include "termopts.h"
63#include "termchar.h"
64#include "disptab.h"
65#include "buffer.h"
66#include "window.h"
67#include "keyboard.h"
68#include "intervals.h"
69#include "process.h"
70#include "atimer.h"
71#include "keymap.h"
72
73
74#ifdef USE_X_TOOLKIT
75#include <X11/Shell.h>
76#endif
77#include <X11/extensions/Xcomposite.h>
78#include <X11/extensions/Xrender.h>
79#include <cairo.h>
80#ifdef HAVE_SYS_TIME_H
81#include <sys/time.h>
82#endif
83#ifdef HAVE_UNISTD_H
84#include <unistd.h>
85#endif
86
87#include "gtkutil.h"
88#include "font.h"
89#endif /* HAVE_X_WINDOWS */
90
91#include <gtk/gtk.h>
92#include <gdk/gdk.h>
93
94#include <gtk/gtkx.h>
95
96#include "emacsgtkfixed.h"
97
98#include <wchar.h>
99
100#include <webkit/webkitwebview.h>
101#include <webkit/webkitwebplugindatabase.h>
102#include <webkit/webkitwebplugin.h>
103#include <webkit/webkitglobals.h>
104#include <webkit/webkitwebnavigationaction.h>
105#include <webkit/webkitdownload.h>
106#include <webkit/webkitwebpolicydecision.h>
107
108#include "xwidget.h"
109
110static struct xwidget *
111allocate_xwidget (void)
112{
113 return ALLOCATE_PSEUDOVECTOR (struct xwidget, height, PVEC_XWIDGET);
114}
115
116static struct xwidget_view *
117allocate_xwidget_view (void)
118{
119 return ALLOCATE_PSEUDOVECTOR (struct xwidget_view, redisplayed,
120 PVEC_XWIDGET_VIEW);
121}
122
123#define XSETXWIDGET(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET))
124#define XSETXWIDGET_VIEW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET_VIEW))
125
126struct xwidget_view *xwidget_view_lookup (struct xwidget *, struct window *);
127Lisp_Object xwidget_spec_value (Lisp_Object , Lisp_Object , int *);
128gboolean offscreen_damage_event (GtkWidget * , GdkEvent * , gpointer );
129void webkit_document_load_finished_cb (WebKitWebView *, WebKitWebFrame *,
130 gpointer );
131gboolean webkit_download_cb (WebKitWebView *, WebKitDownload *, gpointer);
132
133gboolean
134webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *,
135 WebKitWebFrame *,
136 WebKitNetworkRequest *,
137 gchar *,
138 WebKitWebPolicyDecision *,
139 gpointer);
140
141gboolean
142webkit_new_window_policy_decision_requested_cb (WebKitWebView *,
143 WebKitWebFrame *,
144 WebKitNetworkRequest *,
145 WebKitWebNavigationAction *,
146 WebKitWebPolicyDecision *,
147 gpointer);
148
149gboolean
150webkit_navigation_policy_decision_requested_cb (WebKitWebView *,
151 WebKitWebFrame *,
152 WebKitNetworkRequest *,
153 WebKitWebNavigationAction *,
154 WebKitWebPolicyDecision *,
155 gpointer);
156
157
158
159DEFUN ("make-xwidget",
160 Fmake_xwidget, Smake_xwidget,
161 7, 8, 0,
162 doc: /* Make an xwidget from BEG to END of TYPE.
163
164If BUFFER is nil it uses the current
165buffer. If BUFFER is a string and no such
166buffer exists, it is created.
167
168TYPE is a symbol which can take one of the
169following values:
170
171- webkit_osr
172
173Returns the newly constructed xwidget, or nil if construction
174fails. */)
175 (Lisp_Object beg, Lisp_Object end,
176 Lisp_Object type,
177 Lisp_Object title,
178 Lisp_Object width, Lisp_Object height,
179 Lisp_Object arguments, Lisp_Object buffer)
180{
181 //should work a bit like "make-button"(make-button BEG END &rest PROPERTIES)
182 // arg "type" and fwd should be keyword args eventually
183 //(make-xwidget 3 3 'button "oei" 31 31 nil)
184 //(xwidget-info (car xwidget-list))
185 struct xwidget *xw = allocate_xwidget ();
186 Lisp_Object val;
187 xw->type = type;
188 xw->title = title;
189 if (NILP (buffer))
190 buffer = Fcurrent_buffer (); // no need to gcpro because
191 // Fcurrent_buffer doesn't
192 // call Feval/eval_sub.
193 else
194 buffer = Fget_buffer_create (buffer);
195 xw->buffer = buffer;
196
197 xw->height = XFASTINT (height);
198 xw->width = XFASTINT (width);
199 xw->kill_without_query = 0;
200 XSETXWIDGET (val, xw); // set the vectorlike_header of VAL
201 // with the correct value
202 Vxwidget_list = Fcons (val, Vxwidget_list);
203 xw->widgetwindow_osr = NULL;
204 xw->widget_osr = NULL;
205 xw->plist = Qnil;
206
207
208 if (EQ (xw->type, Qwebkit_osr))
209 {
210 block_input ();
211 xw->widgetwindow_osr = gtk_offscreen_window_new ();
212 gtk_window_resize (GTK_WINDOW (xw->widgetwindow_osr), xw->width,
213 xw->height);
214 xw->widgetscrolledwindow_osr = NULL; //webkit osr is the
215 //only scrolled
216 //component atm
217
218 if (EQ (xw->type, Qwebkit_osr))
219 {
220 xw->widgetscrolledwindow_osr = gtk_scrolled_window_new (NULL, NULL);
221 gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW
222 (xw->
223 widgetscrolledwindow_osr),
224 xw->height);
225 gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW
226 (xw->
227 widgetscrolledwindow_osr),
228 xw->width);
229 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW
230 (xw->widgetscrolledwindow_osr),
231 GTK_POLICY_ALWAYS,
232 GTK_POLICY_ALWAYS);
233
234 xw->widget_osr = webkit_web_view_new ();
235 gtk_container_add (GTK_CONTAINER (xw->widgetscrolledwindow_osr),
236 GTK_WIDGET (WEBKIT_WEB_VIEW (xw->widget_osr)));
237 }
238
239 gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width,
240 xw->height);
241
242 if (EQ (xw->type, Qwebkit_osr))
243 {
244 gtk_container_add (GTK_CONTAINER (xw->widgetwindow_osr),
245 xw->widgetscrolledwindow_osr);
246 }
247 else
248 {
249 gtk_container_add (GTK_CONTAINER (xw->widgetwindow_osr),
250 xw->widget_osr);
251 }
252
253 gtk_widget_show (xw->widget_osr);
254 gtk_widget_show (xw->widgetwindow_osr);
255 gtk_widget_show (xw->widgetscrolledwindow_osr);
256
257 /* store some xwidget data in the gtk widgets for convenient
258 retrieval in the event handlers. */
259 g_object_set_data (G_OBJECT (xw->widget_osr), XG_XWIDGET,
260 (gpointer) (xw));
261 g_object_set_data (G_OBJECT (xw->widgetwindow_osr), XG_XWIDGET,
262 (gpointer) (xw));
263
264 /* signals */
265 if (EQ (xw->type, Qwebkit_osr))
266 {
267 g_signal_connect (G_OBJECT (xw->widget_osr),
268 "document-load-finished",
269 G_CALLBACK
270 (webkit_document_load_finished_cb), xw);
271
272 g_signal_connect (G_OBJECT (xw->widget_osr),
273 "download-requested",
274 G_CALLBACK (webkit_download_cb), xw);
275
276 g_signal_connect (G_OBJECT (xw->widget_osr),
277 "mime-type-policy-decision-requested",
278 G_CALLBACK
279 (webkit_mime_type_policy_typedecision_requested_cb),
280 xw);
281
282 g_signal_connect (G_OBJECT (xw->widget_osr),
283 "new-window-policy-decision-requested",
284 G_CALLBACK
285 (webkit_new_window_policy_decision_requested_cb),
286 xw);
287
288 g_signal_connect (G_OBJECT (xw->widget_osr),
289 "navigation-policy-decision-requested",
290 G_CALLBACK
291 (webkit_navigation_policy_decision_requested_cb),
292 xw);
293 }
294
295 unblock_input ();
296
297 }
298
299 return val;
300}
301
302DEFUN ("get-buffer-xwidgets", Fget_buffer_xwidgets, Sget_buffer_xwidgets,
303 1, 1, 0,
304 doc: /* Return a list of xwidgets associated with BUFFER.
305BUFFER may be a buffer or the name of one. */)
306 (Lisp_Object buffer)
307{
308 Lisp_Object xw, tail, xw_list;
309
310 if (NILP (buffer))
311 return Qnil;
312 buffer = Fget_buffer (buffer);
313 if (NILP (buffer))
314 return Qnil;
315
316 xw_list = Qnil;
317
318 for (tail = Vxwidget_list; CONSP (tail); tail = XCDR (tail))
319 {
320 xw = XCAR (tail);
321 if (XWIDGETP (xw) && EQ (Fxwidget_buffer (xw), buffer))
322 xw_list = Fcons (xw, xw_list);
323 }
324 return xw_list;
325}
326
327static int
328xwidget_hidden (struct xwidget_view *xv)
329{
330 return xv->hidden;
331}
332
333
334
335static void
336xwidget_show_view (struct xwidget_view *xv)
337{
338 xv->hidden = 0;
339 gtk_widget_show (xv->widgetwindow);
340 gtk_fixed_move (GTK_FIXED (xv->emacswindow),
341 xv->widgetwindow,
342 xv->x + xv->clip_left,
343 xv->y + xv->clip_top);
344}
345
346
347/* Hide an xvidget view. */
348static void
349xwidget_hide_view (struct xwidget_view *xv)
350{
351 xv->hidden = 1;
352 gtk_fixed_move (GTK_FIXED (xv->emacswindow), xv->widgetwindow,
353 10000, 10000);
354}
355
356
357
358/* When the off-screen webkit master view changes this signal is called.
359 It copies the bitmap from the off-screen instance. */
360gboolean
361offscreen_damage_event (GtkWidget * widget, GdkEvent * event,
362 gpointer xv_widget)
363{
364 // Queue a redraw of onscreen widget.
365 // There is a guard against receiving an invalid widget,
366 // which should only happen if we failed to remove the
367 // specific signal handler for the damage event.
368 if (GTK_IS_WIDGET (xv_widget))
369 gtk_widget_queue_draw (GTK_WIDGET (xv_widget));
370 else
371 printf ("Warning, offscreen_damage_event received invalid xv pointer:%p\n",
372 (void *) xv_widget);
373
374 return FALSE;
375}
376
377static void
378store_xwidget_event_string (struct xwidget *xw, const char *eventname,
379 const char *eventstr)
380{
381 struct input_event event;
382 Lisp_Object xwl;
383 XSETXWIDGET (xwl, xw);
384 EVENT_INIT (event);
385 event.kind = XWIDGET_EVENT;
386 event.frame_or_window = Qnil;
387
388 event.arg = Qnil;
389 event.arg = Fcons (build_string (eventstr), event.arg);
390 event.arg = Fcons (xwl, event.arg);
391 event.arg = Fcons (intern (eventname), event.arg);
392 kbd_buffer_store_event (&event);
393
394}
395
396//TODO deprecated, use load-status
397void
398webkit_document_load_finished_cb (WebKitWebView * webkitwebview,
399 WebKitWebFrame * arg1,
400 gpointer data)
401{
402 struct xwidget *xw =
403 (struct xwidget *) g_object_get_data (G_OBJECT (webkitwebview),
404 XG_XWIDGET);
405
406 store_xwidget_event_string (xw, "document-load-finished", "");
407}
408
409gboolean
410webkit_download_cb (WebKitWebView * webkitwebview,
411 WebKitDownload * arg1,
412 gpointer data)
413{
414 struct xwidget *xw =
415 (struct xwidget *) g_object_get_data (G_OBJECT (webkitwebview),
416 XG_XWIDGET);
417 store_xwidget_event_string (xw, "download-requested",
418 webkit_download_get_uri (arg1));
419
420 return FALSE;
421}
422
423gboolean
424webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *webView,
425 WebKitWebFrame *frame,
426 WebKitNetworkRequest * request,
427 gchar * mimetype,
428 WebKitWebPolicyDecision *policy_decision,
429 gpointer user_data)
430{
431 // This function makes webkit send a download signal for all unknown
432 // mime types. TODO Defer the decision to lisp, so that its possible
433 // to make Emacs handle teext mime for instance.xs
434 if (!webkit_web_view_can_show_mime_type (webView, mimetype))
435 {
436 webkit_web_policy_decision_download (policy_decision);
437 return TRUE;
438 }
439 else
440 {
441 return FALSE;
442 }
443}
444
445
446gboolean
447webkit_new_window_policy_decision_requested_cb (WebKitWebView *webView,
448 WebKitWebFrame *frame,
449 WebKitNetworkRequest *request,
450 WebKitWebNavigationAction *navigation_action,
451 WebKitWebPolicyDecision *policy_decision,
452 gpointer user_data)
453{
454 struct xwidget *xw =
455 (struct xwidget *) g_object_get_data (G_OBJECT (webView), XG_XWIDGET);
456 webkit_web_navigation_action_get_original_uri (navigation_action);
457
458 store_xwidget_event_string (xw, "new-window-policy-decision-requested",
459 webkit_web_navigation_action_get_original_uri
460 (navigation_action));
461 return FALSE;
462}
463
464gboolean
465webkit_navigation_policy_decision_requested_cb (WebKitWebView *webView,
466 WebKitWebFrame *frame,
467 WebKitNetworkRequest *request,
468 WebKitWebNavigationAction *navigation_action,
469 WebKitWebPolicyDecision * policy_decision,
470 gpointer user_data)
471{
472 struct xwidget *xw =
473 (struct xwidget *) g_object_get_data (G_OBJECT (webView), XG_XWIDGET);
474 store_xwidget_event_string (xw, "navigation-policy-decision-requested",
475 webkit_web_navigation_action_get_original_uri
476 (navigation_action));
477 return FALSE;
478}
479
480// For gtk3 offscreen rendered widgets.
481static gboolean
482xwidget_osr_draw_cb (GtkWidget * widget, cairo_t * cr, gpointer data)
483{
484 struct xwidget *xw =
485 (struct xwidget *) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
486 struct xwidget_view *xv =
487 (struct xwidget_view *) g_object_get_data (G_OBJECT (widget),
488 XG_XWIDGET_VIEW);
489
490 cairo_rectangle (cr, 0, 0, xv->clip_right, xv->clip_bottom);
491 cairo_clip (cr);
492
493 if (xw->widgetscrolledwindow_osr != NULL)
494 gtk_widget_draw (xw->widgetscrolledwindow_osr, cr);
495 else
496 gtk_widget_draw (xw->widget_osr, cr);
497 return FALSE;
498}
499
500static gboolean
501xwidget_osr_event_forward (GtkWidget * widget,
502 GdkEvent * event,
503 gpointer user_data)
504{
505 /* Copy events that arrive at the outer widget to the offscreen widget. */
506 struct xwidget *xw =
507 (struct xwidget *) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
508 GdkEvent *eventcopy = gdk_event_copy (event);
509 eventcopy->any.window = gtk_widget_get_window (xw->widget_osr);
510
511 //TODO This might leak events. They should be deallocated later,
512 //perhaps in xwgir_event_cb
513 gtk_main_do_event (eventcopy);
514 return TRUE; //dont propagate this event furter
515}
516
517
518static gboolean
519xwidget_osr_event_set_embedder (GtkWidget * widget,
520 GdkEvent * event, gpointer data)
521{
522 struct xwidget_view *xv = (struct xwidget_view *) data;
523 struct xwidget *xww = XXWIDGET (xv->model);
524 gdk_offscreen_window_set_embedder (gtk_widget_get_window
525 (xww->widgetwindow_osr),
526 gtk_widget_get_window (xv->widget));
527 return FALSE;
528}
529
530
531/* Initializes and does initial placement of an xwidget view on screen. */
532static struct xwidget_view *
533xwidget_init_view (struct xwidget *xww,
534 struct glyph_string *s,
535 int x, int y)
536{
537 struct xwidget_view *xv = allocate_xwidget_view ();
538 Lisp_Object val;
539
540 XSETXWIDGET_VIEW (val, xv);
541 Vxwidget_view_list = Fcons (val, Vxwidget_view_list);
542
543 XSETWINDOW (xv->w, s->w);
544 XSETXWIDGET (xv->model, xww);
545
546 if (EQ (xww->type, Qwebkit_osr))
547 {
548 xv->widget = gtk_drawing_area_new ();
549 // Expose event handling.
550 gtk_widget_set_app_paintable (xv->widget, TRUE);
551 gtk_widget_add_events (xv->widget, GDK_ALL_EVENTS_MASK);
552
553 /* Draw the view on damage-event */
554 g_signal_connect (G_OBJECT (xww->widgetwindow_osr), "damage-event",
555 G_CALLBACK (offscreen_damage_event), xv->widget);
556
557 if (EQ (xww->type, Qwebkit_osr))
558 {
559 g_signal_connect (G_OBJECT (xv->widget), "button-press-event",
560 G_CALLBACK (xwidget_osr_event_forward), NULL);
561 g_signal_connect (G_OBJECT (xv->widget), "button-release-event",
562 G_CALLBACK (xwidget_osr_event_forward), NULL);
563 g_signal_connect (G_OBJECT (xv->widget), "motion-notify-event",
564 G_CALLBACK (xwidget_osr_event_forward), NULL);
565 }
566 else
567 {
568 // xwgir debug , orthogonal to forwarding
569 g_signal_connect (G_OBJECT (xv->widget), "enter-notify-event",
570 G_CALLBACK (xwidget_osr_event_set_embedder), xv);
571 }
572 g_signal_connect (G_OBJECT (xv->widget), "draw",
573 G_CALLBACK (xwidget_osr_draw_cb), NULL);
574 }
575 // Widget realization.
576
577 // Make container widget 1st, and put the actual widget inside the
578 // container later. Drawing should crop container window if necessary
579 // to handle case where xwidget is partially obscured by other Emacs
580 // windows. Other containers than gtk_fixed where explored, but
581 // gtk_fixed had the most predictable behaviour so far.
582 xv->emacswindow = FRAME_GTK_WIDGET (s->f);
583 xv->widgetwindow = gtk_fixed_new ();
584 gtk_widget_set_has_window (xv->widgetwindow, TRUE);
585 gtk_container_add (GTK_CONTAINER (xv->widgetwindow), xv->widget);
586
587 // Store some xwidget data in the gtk widgets.
588 // The emacs frame.
589 g_object_set_data (G_OBJECT (xv->widget), XG_FRAME_DATA, (gpointer) (s->f));
590 // The xwidget.
591 g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET, (gpointer) (xww));
592 // The xwidget.
593 g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET_VIEW, (gpointer) (xv));
594 // The xwidget window.
595 g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET, (gpointer) (xww));
596 // the xwidget view.
597 g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET_VIEW,
598 (gpointer) (xv));
599
600
601 gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xww->width,
602 xww->height);
603 gtk_widget_set_size_request (xv->widgetwindow, xww->width, xww->height);
604 gtk_fixed_put (GTK_FIXED (FRAME_GTK_WIDGET (s->f)), xv->widgetwindow, x, y);
605 xv->x = x;
606 xv->y = y;
607 gtk_widget_show_all (xv->widgetwindow);
608
609
610 return xv;
611}
612
613
614void
615x_draw_xwidget_glyph_string (struct glyph_string *s)
616{
617 /* This method is called by the redisplay engine and places the
618 xwidget on screen. Moving and clipping is done here. Also view
619 initialization.
620 */
621 struct xwidget *xww = s->xwidget;
622 struct xwidget_view *xv = xwidget_view_lookup (xww, s->w);
623 int clip_right;
624 int clip_bottom;
625 int clip_top;
626 int clip_left;
627
628 int x = s->x;
629 int y = s->y + (s->height / 2) - (xww->height / 2);
630 int moved = 0;
631
632 /* We do initialization here in the display loop because there is no
633 other time to know things like window placement etc.
634 */
635 xv = xwidget_init_view (xww, s, x, y);
636
637 // Calculate clipping, which is used for all manner of onscreen
638 // xwidget views. Each widget border can get clipped by other emacs
639 // objects so there are four clipping variables.
640 clip_right =
641 min (xww->width,
642 WINDOW_RIGHT_EDGE_X (s->w) - x -
643 WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w) -
644 WINDOW_RIGHT_FRINGE_WIDTH (s->w));
645 clip_left =
646 max (0,
647 WINDOW_LEFT_EDGE_X (s->w) - x +
648 WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (s->w) +
649 WINDOW_LEFT_FRINGE_WIDTH (s->w));
650
651 clip_bottom =
652 min (xww->height,
653 WINDOW_BOTTOM_EDGE_Y (s->w) - WINDOW_MODE_LINE_HEIGHT (s->w) - y);
654 clip_top = max (0, WINDOW_TOP_EDGE_Y (s->w) - y);
655
656 // We are conserned with movement of the onscreen area. The area
657 // might sit still when the widget actually moves. This happens
658 // when an Emacs window border moves across a widget window. So, if
659 // any corner of the outer widget clipping window moves, that counts
660 // as movement here, even if it looks like no movement happens
661 // because the widget sits still inside the clipping area. The
662 // widget can also move inside the clipping area, which happens
663 // later
664 moved = (xv->x + xv->clip_left != x + clip_left)
665 || ((xv->y + xv->clip_top) != (y + clip_top));
666 xv->x = x;
667 xv->y = y;
668 if (moved) // Has it moved?
669 {
670 gtk_fixed_move (GTK_FIXED (FRAME_GTK_WIDGET (s->f)),
671 xv->widgetwindow, x + clip_left, y + clip_top);
672 }
673 // Clip the widget window if some parts happen to be outside
674 // drawable area. An Emacs window is not a gtk window. A gtk window
675 // covers the entire frame. Clipping might have changed even if we
676 // havent actualy moved, we try figure out when we need to reclip
677 // for real.
678 if ((xv->clip_right != clip_right)
679 || (xv->clip_bottom != clip_bottom)
680 || (xv->clip_top != clip_top) || (xv->clip_left != clip_left))
681 {
682 gtk_widget_set_size_request (xv->widgetwindow, clip_right + clip_left,
683 clip_bottom + clip_top);
684 gtk_fixed_move (GTK_FIXED (xv->widgetwindow), xv->widget, -clip_left,
685 -clip_top);
686
687 xv->clip_right = clip_right;
688 xv->clip_bottom = clip_bottom;
689 xv->clip_top = clip_top;
690 xv->clip_left = clip_left;
691 }
692 // If emacs wants to repaint the area where the widget lives, queue
693 // a redraw. It seems its possible to get out of sync with emacs
694 // redraws so emacs background sometimes shows up instead of the
695 // xwidgets background. It's just a visual glitch though.
696 if (!xwidget_hidden (xv))
697 {
698 gtk_widget_queue_draw (xv->widgetwindow);
699 gtk_widget_queue_draw (xv->widget);
700 }
701}
702
703
704// Macro that checks WEBKIT_IS_WEB_VIEW(xw->widget_osr) first
705#define WEBKIT_FN_INIT() \
706 struct xwidget* xw; \
707 CHECK_XWIDGET (xwidget); \
708 if (NILP (xwidget)) {printf("ERROR xwidget nil\n"); return Qnil;}; \
709 xw = XXWIDGET (xwidget); \
710 if (NULL == xw) printf("ERROR xw is 0\n"); \
711 if ((NULL == xw->widget_osr) || !WEBKIT_IS_WEB_VIEW(xw->widget_osr)){ \
712 printf ("ERROR xw->widget_osr does not hold a webkit instance\n");\
713 return Qnil;\
714 };
715
716
717DEFUN ("xwidget-webkit-goto-uri",
718 Fxwidget_webkit_goto_uri, Sxwidget_webkit_goto_uri,
719 2, 2, 0,
720 doc: /* Make the xwidget webkit instance referenced by XWIDGET
721browse URI. */)
722 (Lisp_Object xwidget, Lisp_Object uri)
723{
724 WEBKIT_FN_INIT ();
725 CHECK_STRING (uri);
726 webkit_web_view_load_uri (WEBKIT_WEB_VIEW (xw->widget_osr), SSDATA (uri));
727 return Qnil;
728}
729
730
731DEFUN ("xwidget-webkit-execute-script",
732 Fxwidget_webkit_execute_script, Sxwidget_webkit_execute_script,
733 2, 2, 0,
734 doc: /* Make the Webkit XWIDGET execute javascript SCRIPT. */)
735 (Lisp_Object xwidget, Lisp_Object script)
736{
737 WEBKIT_FN_INIT ();
738 CHECK_STRING (script);
739 webkit_web_view_execute_script (WEBKIT_WEB_VIEW (xw->widget_osr),
740 SSDATA (script));
741 return Qnil;
742}
743
744DEFUN ("xwidget-webkit-get-title",
745 Fxwidget_webkit_get_title, Sxwidget_webkit_get_title,
746 1, 1, 0,
747 doc: /* Returns the title from the Webkit instance in XWIDGET.
748This can be used to work around the lack of a return value from the
749exec method. */ )
750 (Lisp_Object xwidget)
751{
752 // TODO support multibyte strings
753 WEBKIT_FN_INIT ();
754 const gchar *str =
755 webkit_web_view_get_title (WEBKIT_WEB_VIEW (xw->widget_osr));
756 if (str == 0)
757 {
758 // TODO maybe return Qnil instead. I suppose webkit returns
759 // nullpointer when doc is not properly loaded or something
760 return build_string ("");
761 }
762 return build_string (str);
763}
764
765DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 3, 3, 0,
766 doc: /* Resize XWIDGET. NEW_WIDTH NEW_HEIGHT defines the new
767size. */ )
768 (Lisp_Object xwidget, Lisp_Object new_width, Lisp_Object new_height)
769{
770 CHECK_XWIDGET (xwidget);
771 struct xwidget *xw = XXWIDGET (xwidget);
772 struct xwidget_view *xv;
773 int w, h;
774
775 CHECK_NUMBER (new_width);
776 CHECK_NUMBER (new_height);
777 w = XFASTINT (new_width);
778 h = XFASTINT (new_height);
779
780 xw->width = w;
781 xw->height = h;
782 // If there is a offscreen widget resize it 1st.
783 if (xw->widget_osr)
784 {
785 gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr),
786 xw->width, xw->height); //minimum size
787 gtk_window_resize (GTK_WINDOW (xw->widgetwindow_osr), xw->width,
788 xw->height);
789 gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW
790 (xw->
791 widgetscrolledwindow_osr),
792 xw->height);
793 gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW
794 (xw->
795 widgetscrolledwindow_osr),
796 xw->width);
797
798 gtk_container_resize_children (GTK_CONTAINER (xw->widgetwindow_osr));
799
800 }
801
802 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail))
803 {
804 if (XWIDGET_VIEW_P (XCAR (tail)))
805 {
806 xv = XXWIDGET_VIEW (XCAR (tail));
807 if (XXWIDGET (xv->model) == xw)
808 gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xw->width,
809 xw->height);
810 }
811 }
812
813 return Qnil;
814}
815
816
817
818DEFUN ("xwidget-set-adjustment",
819 Fxwidget_set_adjustment, Sxwidget_set_adjustment, 4, 4, 0,
820 doc: /* Set native scrolling for XWIDGET. AXIS can be 'vertical or
821'horizontal. If RELATIVE is t, scroll relative, otherwise absolutely.
822VALUE is the amount to scroll, either relatively or absolutely. */)
823 (Lisp_Object xwidget, Lisp_Object axis, Lisp_Object relative,
824 Lisp_Object value)
825{
826 CHECK_XWIDGET (xwidget);
827 struct xwidget *xw = XXWIDGET (xwidget);
828 GtkAdjustment *adjustment;
829 float final_value = 0.0;
830
831 adjustment =
832 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW
833 (xw->widgetscrolledwindow_osr));
834 if (EQ (Qvertical, axis))
835 {
836 adjustment =
837 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW
838 (xw->widgetscrolledwindow_osr));
839 }
840 if (EQ (Qhorizontal, axis))
841 {
842 adjustment =
843 gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW
844 (xw->widgetscrolledwindow_osr));
845 }
846
847 if (EQ (Qt, relative))
848 {
849 final_value = gtk_adjustment_get_value (adjustment) + XFASTINT (value);
850 }
851 else
852 {
853 final_value = 0.0 + XFASTINT (value);
854 }
855
856 gtk_adjustment_set_value (adjustment, final_value);
857
858 return Qnil;
859}
860
861
862DEFUN ("xwidget-size-request",
863 Fxwidget_size_request, Sxwidget_size_request,
864 1, 1, 0,
865 doc: /* Return the desired size of the XWIDGET.
866
867This can be used to read the xwidget desired size, and resizes the
868Emacs allocated area accordingly. */)
869 (Lisp_Object xwidget)
870{
871 CHECK_XWIDGET (xwidget);
872 GtkRequisition requisition;
873 Lisp_Object rv;
874 gtk_widget_size_request (XXWIDGET (xwidget)->widget_osr, &requisition);
875 rv = Qnil;
876 rv = Fcons (make_number (requisition.height), rv);
877 rv = Fcons (make_number (requisition.width), rv);
878 return rv;
879
880}
881
882DEFUN ("xwidgetp",
883 Fxwidgetp, Sxwidgetp,
884 1, 1, 0,
885 doc: /* Return t if OBJECT is a xwidget. */)
886 (Lisp_Object object)
887{
888 return XWIDGETP (object) ? Qt : Qnil;
889}
890
891DEFUN ("xwidget-view-p",
892 Fxwidget_view_p, Sxwidget_view_p,
893 1, 1, 0,
894 doc: /* Return t if OBJECT is a xwidget-view. */)
895 (Lisp_Object object)
896{
897 return XWIDGET_VIEW_P (object) ? Qt : Qnil;
898}
899
900DEFUN ("xwidget-info",
901 Fxwidget_info, Sxwidget_info,
902 1, 1, 0,
903 doc: /* Return XWIDGET properties in a vector. Currently [TYPE
904TITLE WIDTH HEIGHT]. */)
905 (Lisp_Object xwidget)
906{
907 CHECK_XWIDGET (xwidget);
908 Lisp_Object info, n;
909 struct xwidget *xw = XXWIDGET (xwidget);
910
911 info = Fmake_vector (make_number (4), Qnil);
912 ASET (info, 0, xw->type);
913 ASET (info, 1, xw->title);
914 XSETFASTINT (n, xw->width);
915 ASET (info, 2, n);
916 XSETFASTINT (n, xw->height);
917 ASET (info, 3, n);
918
919 return info;
920}
921
922DEFUN ("xwidget-view-info",
923 Fxwidget_view_info, Sxwidget_view_info,
924 1, 1, 0,
925 doc: /* Return properties of XWIDGET-VIEW in a vector.
926Currently [X Y CLIP_RIGHT CLIP_BOTTOM CLIP_TOP CLIP_LEFT] */)
927 (Lisp_Object xwidget_view)
928{
929 CHECK_XWIDGET_VIEW (xwidget_view);
930 struct xwidget_view *xv = XXWIDGET_VIEW (xwidget_view);
931 Lisp_Object info;
932
933 info = Fmake_vector (make_number (6), Qnil);
934 ASET (info, 0, make_number (xv->x));
935 ASET (info, 1, make_number (xv->y));
936 ASET (info, 2, make_number (xv->clip_right));
937 ASET (info, 3, make_number (xv->clip_bottom));
938 ASET (info, 4, make_number (xv->clip_top));
939 ASET (info, 5, make_number (xv->clip_left));
940
941 return info;
942}
943
944DEFUN ("xwidget-view-model",
945 Fxwidget_view_model, Sxwidget_view_model,
946 1, 1, 0,
947 doc: /* Return the model associated with XWIDGET-VIEW. */)
948 (Lisp_Object xwidget_view)
949{
950 CHECK_XWIDGET_VIEW (xwidget_view);
951 return XXWIDGET_VIEW (xwidget_view)->model;
952}
953
954DEFUN ("xwidget-view-window",
955 Fxwidget_view_window, Sxwidget_view_window,
956 1, 1, 0,
957 doc: /* Return the window of XWIDGET-VIEW. */)
958 (Lisp_Object xwidget_view)
959{
960 CHECK_XWIDGET_VIEW (xwidget_view);
961 return XXWIDGET_VIEW (xwidget_view)->w;
962}
963
964
965DEFUN ("delete-xwidget-view",
966 Fdelete_xwidget_view, Sdelete_xwidget_view,
967 1, 1, 0,
968 doc: /* Delete the XWIDGET-VIEW. */)
969 (Lisp_Object xwidget_view)
970{
971 CHECK_XWIDGET_VIEW (xwidget_view);
972 struct xwidget_view *xv = XXWIDGET_VIEW (xwidget_view);
973 gtk_widget_destroy (xv->widgetwindow);
974 Vxwidget_view_list = Fdelq (xwidget_view, Vxwidget_view_list);
975 // xv->model still has signals pointing to the view. There can be
976 // several views. Find the matching signals and delete them all.
977 g_signal_handlers_disconnect_matched (XXWIDGET (xv->model)->widgetwindow_osr,
978 G_SIGNAL_MATCH_DATA,
979 0, 0, 0, 0,
980 xv->widget);
981 return Qnil;
982}
983
984DEFUN ("xwidget-view-lookup",
985 Fxwidget_view_lookup, Sxwidget_view_lookup,
986 1, 2, 0,
987 doc: /* Return the xwidget-view associated with XWIDGET in
988WINDOW if specified, otherwise it uses the selected window. Return nil
989if no association is found. */)
990 (Lisp_Object xwidget, Lisp_Object window)
991{
992 CHECK_XWIDGET (xwidget);
993
994 if (NILP (window))
995 window = Fselected_window ();
996 CHECK_WINDOW (window);
997
998 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail);
999 tail = XCDR (tail))
1000 {
1001 Lisp_Object xwidget_view = XCAR (tail);
1002 if (EQ (Fxwidget_view_model (xwidget_view), xwidget)
1003 && EQ (Fxwidget_view_window (xwidget_view), window))
1004 return xwidget_view;
1005 }
1006
1007 return Qnil;
1008}
1009
1010DEFUN ("xwidget-plist",
1011 Fxwidget_plist, Sxwidget_plist,
1012 1, 1, 0,
1013 doc: /* Return the plist of XWIDGET. */)
1014 (register Lisp_Object xwidget)
1015{
1016 CHECK_XWIDGET (xwidget);
1017 return XXWIDGET (xwidget)->plist;
1018}
1019
1020DEFUN ("xwidget-buffer",
1021 Fxwidget_buffer, Sxwidget_buffer,
1022 1, 1, 0,
1023 doc: /* Return the buffer of XWIDGET. */)
1024 (register Lisp_Object xwidget)
1025{
1026 CHECK_XWIDGET (xwidget);
1027 return XXWIDGET (xwidget)->buffer;
1028}
1029
1030DEFUN ("set-xwidget-plist",
1031 Fset_xwidget_plist, Sset_xwidget_plist,
1032 2, 2, 0,
1033 doc: /* Replace the plist of XWIDGET with PLIST.
1034Returns PLIST. */)
1035 (register Lisp_Object xwidget, Lisp_Object plist)
1036{
1037 CHECK_XWIDGET (xwidget);
1038 CHECK_LIST (plist);
1039
1040 XXWIDGET (xwidget)->plist = plist;
1041 return plist;
1042}
1043
1044DEFUN ("set-xwidget-query-on-exit-flag",
1045 Fset_xwidget_query_on_exit_flag, Sset_xwidget_query_on_exit_flag,
1046 2, 2, 0,
1047 doc: /* Specify if query is needed for XWIDGET when
1048Emacs is exited. If the second argument FLAG is non-nil, Emacs will
1049queries the user before exiting or killing a buffer if XWIDGET is
1050running. This function returns FLAG. */)
1051 (Lisp_Object xwidget, Lisp_Object flag)
1052{
1053 CHECK_XWIDGET (xwidget);
1054 XXWIDGET (xwidget)->kill_without_query = NILP (flag);
1055 return flag;
1056}
1057
1058DEFUN ("xwidget-query-on-exit-flag",
1059 Fxwidget_query_on_exit_flag, Sxwidget_query_on_exit_flag,
1060 1, 1, 0,
1061 doc: /* Return the current value of query-on-exit
1062flag for XWIDGET. */)
1063 (Lisp_Object xwidget)
1064{
1065 CHECK_XWIDGET (xwidget);
1066 return (XXWIDGET (xwidget)->kill_without_query ? Qnil : Qt);
1067}
1068
1069void
1070syms_of_xwidget (void)
1071{
1072
1073 defsubr (&Smake_xwidget);
1074 defsubr (&Sxwidgetp);
1075 DEFSYM (Qxwidgetp, "xwidgetp");
1076 defsubr (&Sxwidget_view_p);
1077 DEFSYM (Qxwidget_view_p, "xwidget-view-p");
1078 defsubr (&Sxwidget_info);
1079 defsubr (&Sxwidget_view_info);
1080 defsubr (&Sxwidget_resize);
1081 defsubr (&Sget_buffer_xwidgets);
1082 defsubr (&Sxwidget_view_model);
1083 defsubr (&Sxwidget_view_window);
1084 defsubr (&Sxwidget_view_lookup);
1085 defsubr (&Sxwidget_query_on_exit_flag);
1086 defsubr (&Sset_xwidget_query_on_exit_flag);
1087
1088#ifdef HAVE_WEBKIT_OSR
1089 defsubr (&Sxwidget_webkit_goto_uri);
1090 defsubr (&Sxwidget_webkit_execute_script);
1091 defsubr (&Sxwidget_webkit_get_title);
1092 DEFSYM (Qwebkit_osr, "webkit-osr");
1093#endif
1094
1095 defsubr (&Sxwidget_size_request);
1096 defsubr (&Sdelete_xwidget_view);
1097
1098 defsubr (&Sxwidget_plist);
1099 defsubr (&Sxwidget_buffer);
1100 defsubr (&Sset_xwidget_plist);
1101
1102 defsubr (&Sxwidget_set_adjustment);
1103
1104 DEFSYM (Qxwidget, "xwidget");
1105
1106 DEFSYM (QCxwidget, ":xwidget");
1107 DEFSYM (QCtitle, ":title");
1108
1109 /* Do not forget to update the docstring of make-xwidget if you add
1110 new types. */
1111
1112 DEFSYM (Qvertical, "vertical");
1113 DEFSYM (Qhorizontal, "horizontal");
1114
1115 DEFSYM (QCplist, ":plist");
1116
1117 DEFVAR_LISP ("xwidget-list", Vxwidget_list,
1118 doc: /* xwidgets list. */);
1119 Vxwidget_list = Qnil;
1120
1121 DEFVAR_LISP ("xwidget-view-list", Vxwidget_view_list,
1122 doc: /* xwidget views list. */);
1123 Vxwidget_view_list = Qnil;
1124
1125 Fprovide (intern ("xwidget-internal"), Qnil);
1126
1127}
1128
1129
1130/* Value is non-zero if OBJECT is a valid Lisp xwidget specification. A
1131 valid xwidget specification is a list whose car is the symbol
1132 `xwidget', and whose rest is a property list. The property list must
1133 contain a value for key `:type'. That value must be the name of a
1134 supported xwidget type. The rest of the property list depends on the
1135 xwidget type. */
1136
1137bool
1138valid_xwidget_spec_p (Lisp_Object object)
1139{
1140 int valid_p = false;
1141
1142 if (CONSP (object) && EQ (XCAR (object), Qxwidget))
1143 valid_p = true;
1144
1145 return valid_p;
1146}
1147
1148
1149
1150/* Find a value associated with key in spec. */
1151Lisp_Object
1152xwidget_spec_value (Lisp_Object spec, Lisp_Object key, int *found)
1153{
1154 Lisp_Object tail;
1155
1156 eassert (valid_xwidget_spec_p (spec));
1157
1158 for (tail = XCDR (spec);
1159 CONSP (tail) && CONSP (XCDR (tail)); tail = XCDR (XCDR (tail)))
1160 {
1161 if (EQ (XCAR (tail), key))
1162 {
1163 if (found)
1164 *found = 1;
1165 return XCAR (XCDR (tail));
1166 }
1167 }
1168
1169 if (found)
1170 *found = 0;
1171 return Qnil;
1172}
1173
1174
1175void
1176xwidget_view_delete_all_in_window (struct window *w)
1177{
1178 struct xwidget_view *xv = NULL;
1179 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail);
1180 tail = XCDR (tail))
1181 {
1182 if (XWIDGET_VIEW_P (XCAR (tail)))
1183 {
1184 xv = XXWIDGET_VIEW (XCAR (tail));
1185 if (XWINDOW (xv->w) == w)
1186 {
1187 Fdelete_xwidget_view (XCAR (tail));
1188 }
1189 }
1190 }
1191}
1192
1193struct xwidget_view *
1194xwidget_view_lookup (struct xwidget *xw, struct window *w)
1195{
1196 Lisp_Object xwidget, window, ret;
1197 XSETXWIDGET (xwidget, xw);
1198 XSETWINDOW (window, w);
1199
1200 ret = Fxwidget_view_lookup (xwidget, window);
1201
1202 return EQ (ret, Qnil) ? NULL : XXWIDGET_VIEW (ret);
1203}
1204
1205struct xwidget *
1206lookup_xwidget (Lisp_Object spec)
1207{
1208 /* When a xwidget lisp spec is found initialize the C struct that is
1209 used in the C code. This is done by redisplay so values change
1210 if the spec changes. So, take special care of one-shot events.
1211 */
1212 int found = 0;
1213 Lisp_Object value;
1214 struct xwidget *xw;
1215
1216 value = xwidget_spec_value (spec, QCxwidget, &found);
1217 xw = XXWIDGET (value);
1218
1219 return xw;
1220}
1221
1222/* Set up detection of touched xwidget*/
1223void
1224xwidget_start_redisplay (void)
1225{
1226 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail);
1227 tail = XCDR (tail))
1228 {
1229 if (XWIDGET_VIEW_P (XCAR (tail)))
1230 XXWIDGET_VIEW (XCAR (tail))->redisplayed = 0;
1231 }
1232}
1233
1234/* The xwidget was touched during redisplay, so it isn't a candidate
1235 for hiding. */
1236void
1237xwidget_touch (struct xwidget_view *xv)
1238{
1239 xv->redisplayed = 1;
1240}
1241
1242static int
1243xwidget_touched (struct xwidget_view *xv)
1244{
1245 return xv->redisplayed;
1246}
1247
1248/* Redisplay has ended, now we should hide untouched xwidgets
1249*/
1250void
1251xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix)
1252{
1253
1254 int i;
1255 int area;
1256
1257 xwidget_start_redisplay ();
1258 // Iterate desired glyph matrix of window here, hide gtk widgets
1259 // not in the desired matrix.
1260
1261 // This only takes care of xwidgets in active windows. if a window
1262 // goes away from screen xwidget views wust be deleted
1263
1264 // dump_glyph_matrix (matrix, 2);
1265 for (i = 0; i < matrix->nrows; ++i)
1266 {
1267 // dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
1268 struct glyph_row *row;
1269 row = MATRIX_ROW (matrix, i);
1270 if (row->enabled_p != 0)
1271 {
1272 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
1273 {
1274 struct glyph *glyph = row->glyphs[area];
1275 struct glyph *glyph_end = glyph + row->used[area];
1276 for (; glyph < glyph_end; ++glyph)
1277 {
1278 if (glyph->type == XWIDGET_GLYPH)
1279 {
1280 /*
1281 The only call to xwidget_end_redisplay is in dispnew
1282 xwidget_end_redisplay (w->current_matrix);
1283 */
1284 xwidget_touch (xwidget_view_lookup (glyph->u.xwidget,
1285 w));
1286 }
1287 }
1288 }
1289 }
1290 }
1291
1292 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail);
1293 tail = XCDR (tail))
1294 {
1295 if (XWIDGET_VIEW_P (XCAR (tail)))
1296 {
1297 struct xwidget_view *xv = XXWIDGET_VIEW (XCAR (tail));
1298
1299 // "touched" is only meaningful for the current window, so
1300 // disregard other views.
1301 if (XWINDOW (xv->w) == w)
1302 {
1303 if (xwidget_touched (xv))
1304 xwidget_show_view (xv);
1305 else
1306 xwidget_hide_view (xv);
1307 }
1308 }
1309 }
1310}
1311
1312/* Kill all xwidget in BUFFER. */
1313void
1314kill_buffer_xwidgets (Lisp_Object buffer)
1315{
1316 Lisp_Object tail, xwidget;
1317 for (tail = Fget_buffer_xwidgets (buffer); CONSP (tail); tail = XCDR (tail))
1318 {
1319 xwidget = XCAR (tail);
1320 Vxwidget_list = Fdelq (xwidget, Vxwidget_list);
1321 /* TODO free the GTK things in xw */
1322 {
1323 CHECK_XWIDGET (xwidget);
1324 struct xwidget *xw = XXWIDGET (xwidget);
1325 if (xw->widget_osr && xw->widgetwindow_osr)
1326 {
1327 gtk_widget_destroy (xw->widget_osr);
1328 gtk_widget_destroy (xw->widgetwindow_osr);
1329 }
1330 }
1331 }
1332}
diff --git a/src/xwidget.h b/src/xwidget.h
new file mode 100644
index 00000000000..493000c34fd
--- /dev/null
+++ b/src/xwidget.h
@@ -0,0 +1,135 @@
1/* Support for embedding graphical components in a buffer.
2
3Copyright (C) 2011-2015 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19
20#ifndef XWIDGET_H_INCLUDED
21#define XWIDGET_H_INCLUDED
22
23void x_draw_xwidget_glyph_string (struct glyph_string *s);
24void syms_of_xwidget (void);
25
26//extern Lisp_Object Qxwidget;
27
28
29bool valid_xwidget_spec_p (Lisp_Object object);
30
31#include <gtk/gtk.h>
32
33
34/*
35each xwidget instance/model is described by this struct.
36
37lisp pseudovector.
38
39
40 */
41struct xwidget
42{
43 struct vectorlike_header header;
44 Lisp_Object plist; //auxilliary data
45 Lisp_Object type; //the widget type
46 Lisp_Object buffer; //buffer where xwidget lives
47 Lisp_Object title; //a title that is used for button labels for instance
48
49 //here ends the lisp part.
50 //"height" is the marker field
51 int height;
52 int width;
53
54 //for offscreen widgets, unused if not osr
55 GtkWidget *widget_osr;
56 GtkWidget *widgetwindow_osr;
57 //this is used if the widget (webkit) is to be wrapped in a scrolled window,
58 GtkWidget *widgetscrolledwindow_osr;
59 /* Non-nil means kill silently if Emacs is exited. */
60 unsigned int kill_without_query:1;
61
62};
63
64
65//struct for each xwidget view
66struct xwidget_view
67{
68 struct vectorlike_header header;
69 Lisp_Object model;
70 Lisp_Object w;
71
72 //here ends the lisp part.
73 //"redisplayed" is the marker field
74 int redisplayed; //if touched by redisplay
75
76 int hidden; //if the "live" instance isnt drawn
77
78 GtkWidget *widget;
79 GtkWidget *widgetwindow;
80 GtkWidget *emacswindow;
81 int x;
82 int y;
83 int clip_right;
84 int clip_bottom;
85 int clip_top;
86 int clip_left;
87
88
89 long handler_id;
90};
91
92/* Test for xwidget pseudovector*/
93#define XWIDGETP(x) PSEUDOVECTORP (x, PVEC_XWIDGET)
94#define XXWIDGET(a) (eassert (XWIDGETP(a)), \
95 (struct xwidget *) XUNTAG(a, Lisp_Vectorlike))
96
97#define CHECK_XWIDGET(x) \
98 CHECK_TYPE (XWIDGETP (x), Qxwidgetp, x)
99
100/* Test for xwidget_view pseudovector */
101#define XWIDGET_VIEW_P(x) PSEUDOVECTORP (x, PVEC_XWIDGET_VIEW)
102#define XXWIDGET_VIEW(a) (eassert (XWIDGET_VIEW_P(a)), \
103 (struct xwidget_view *) XUNTAG(a, Lisp_Vectorlike))
104
105#define CHECK_XWIDGET_VIEW(x) \
106 CHECK_TYPE (XWIDGET_VIEW_P (x), Qxwidget_view_p, x)
107
108struct xwidget_type
109{
110 /* A symbol uniquely identifying the xwidget type, */
111 Lisp_Object *type;
112
113 /* Check that SPEC is a valid image specification for the given
114 image type. Value is non-zero if SPEC is valid. */
115 int (*valid_p) (Lisp_Object spec);
116
117 /* Next in list of all supported image types. */
118 struct xwidget_type *next;
119};
120
121
122struct xwidget *xwidget_from_id (int id);
123
124void xwidget_start_redisplay (void);
125void xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix);
126
127void xwidget_touch (struct xwidget_view *xw);
128
129struct xwidget *lookup_xwidget (Lisp_Object spec);
130#define XG_XWIDGET "emacs_xwidget"
131#define XG_XWIDGET_VIEW "emacs_xwidget_view"
132void xwidget_view_delete_all_in_window (struct window *w);
133
134void kill_buffer_xwidgets (Lisp_Object buffer);
135#endif /* XWIDGET_H_INCLUDED */