From 32cb203c086163e40ecc040e61e5d304e101b602 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Tue, 19 Jan 2016 18:11:04 +0200 Subject: Unbreak the Cygwin-w32 build * src/w32fns.c (globals_of_w32fns): Move the initialization of resetstkoflw into a part that isn't compiled on Cygwin. (Bug#22403) --- src/w32fns.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/w32fns.c b/src/w32fns.c index 01f5d6f3ae0..a5018ae9d30 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -9921,6 +9921,7 @@ globals_of_w32fns (void) except_addr = 0; #ifndef CYGWIN prev_exception_handler = SetUnhandledExceptionFilter (my_exception_handler); + resetstkoflw = NULL; #endif DEFVAR_INT ("w32-ansi-code-page", @@ -9935,8 +9936,6 @@ globals_of_w32fns (void) after_deadkey = -1; - resetstkoflw = NULL; - /* MessageBox does not work without this when linked to comctl32.dll 6.0. */ InitCommonControls (); -- cgit v1.2.1 From 7c1f66a94bf236a427606ef537b4629a48a1665b Mon Sep 17 00:00:00 2001 From: Joakim Verona Date: Tue, 19 Jan 2016 20:27:12 +0100 Subject: 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 Various improvements to the Xwidget feature. * xwidgets.c: * emacsgtkfixed.c: * xwidget.el: --- src/Makefile.in | 11 + src/buffer.c | 6 + src/dispextern.h | 28 ++ src/dispnew.c | 12 + src/emacs.c | 6 + src/emacsgtkfixed.c | 105 +++- src/emacsgtkfixed.h | 28 ++ src/keyboard.c | 19 + src/lisp.h | 6 + src/print.c | 16 + src/termhooks.h | 5 + src/window.c | 6 + src/xdisp.c | 248 +++++++++- src/xterm.c | 14 + src/xwidget.c | 1332 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/xwidget.h | 135 ++++++ 16 files changed, 1954 insertions(+), 23 deletions(-) create mode 100644 src/xwidget.c create mode 100644 src/xwidget.h (limited to 'src') 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@ ## dbusbind.o if HAVE_DBUS, else empty. DBUS_OBJ = @DBUS_OBJ@ +## xwidgets.o if HAVE_XWIDGETS, else empty. +XWIDGETS_OBJ = @XWIDGETS_OBJ@ + LIB_EXECINFO=@LIB_EXECINFO@ SETTINGS_CFLAGS = @SETTINGS_CFLAGS@ @@ -219,6 +222,11 @@ CFLAGS_SOUND= @CFLAGS_SOUND@ RSVG_LIBS= @RSVG_LIBS@ RSVG_CFLAGS= @RSVG_CFLAGS@ +WEBKIT_LIBS= @WEBKIT_LIBS@ +WEBKIT_CFLAGS= @WEBKIT_CFLAGS@ + +GIR_LIBS= @GIR_LIBS@ +GIR_CFLAGS= @GIR_CFLAGS@ CAIRO_LIBS= @CAIRO_LIBS@ CAIRO_CFLAGS= @CAIRO_CFLAGS@ @@ -358,6 +366,7 @@ ALL_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \ $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \ $(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \ $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \ + $(WEBKIT_CFLAGS) $(GIR_CFLAGS) \ $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \ $(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 \ process.o gnutls.o callproc.o \ region-cache.o sound.o atimer.o \ doprnt.o intervals.o textprop.o composite.o xml.o $(NOTIFY_OBJ) \ + $(XWIDGETS_OBJ) \ profiler.o decompress.o \ $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \ $(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ) @@ -467,6 +477,7 @@ lisp = $(addprefix ${lispsource}/,${shortlisp}) LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ $(LIBX_OTHER) $(LIBSOUND) \ $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \ + $(WEBKIT_LIBS) $(GIR_LIBS) \ $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \ $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \ $(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 . */ #include "keymap.h" #include "frame.h" +#ifdef HAVE_XWIDGETS +# include "xwidget.h" +#endif #ifdef WINDOWSNT #include "w32heap.h" /* for mmap_* */ #endif @@ -1747,6 +1750,9 @@ cleaning up all windows currently displaying the buffer to be killed. */) kill_buffer_processes (buffer); +#ifdef HAVE_XWIDGETS + kill_buffer_xwidgets (buffer); +#endif /* Killing buffer processes may run sentinels which may have killed our buffer. */ 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 /* Glyph is a space of fractional width and/or height. */ STRETCH_GLYPH +#ifdef HAVE_XWIDGETS + /* Glyph is an external widget drawn by the GUI toolkit. */ + ,XWIDGET_GLYPH +#endif }; @@ -499,6 +503,9 @@ struct glyph /* Image ID for image glyphs (type == IMAGE_GLYPH). */ int img_id; +#ifdef HAVE_XWIDGETS + struct xwidget *xwidget; +#endif /* Sub-structure for type == STRETCH_GLYPH. */ struct { @@ -1350,6 +1357,9 @@ struct glyph_string /* Image, if any. */ struct image *img; +#ifdef HAVE_XWIDGETS + struct xwidget *xwidget; +#endif /* Slice */ struct glyph_slice slice; @@ -2102,6 +2112,10 @@ enum display_element_type /* Continuation glyphs. See the comment for IT_TRUNCATION. */ IT_CONTINUATION + +#ifdef HAVE_XWIDGETS + ,IT_XWIDGET +#endif }; @@ -2165,6 +2179,9 @@ enum it_method { GET_FROM_C_STRING, GET_FROM_IMAGE, GET_FROM_STRETCH, +#ifdef HAVE_XWIDGETS + GET_FROM_XWIDGET, +#endif NUM_IT_METHODS }; @@ -2382,6 +2399,12 @@ struct it struct { Lisp_Object object; } stretch; +#ifdef HAVE_XWIDGETS + /* method == GET_FROM_XWIDGET */ + struct { + Lisp_Object object; + } xwidget; +#endif } u; /* Current text and display positions. */ @@ -2506,6 +2529,11 @@ struct it /* If what == IT_IMAGE, the id of the image to display. */ ptrdiff_t image_id; +#ifdef HAVE_XWIDGETS + /* If what == IT_XWIDGET. */ + struct xwidget *xwidget; +#endif + /* Values from `slice' property. */ struct it_slice slice; 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 . */ #include TERM_HEADER #endif /* HAVE_WINDOW_SYSTEM */ +#ifdef HAVE_XWIDGETS +# include "xwidget.h" +#endif + #include #include @@ -3545,6 +3549,9 @@ update_window (struct window *w, bool force_p) add_window_display_history (w, w->current_matrix->method, paused_p); #endif +#ifdef HAVE_XWIDGETS + xwidget_end_redisplay (w, w->current_matrix); +#endif clear_glyph_matrix (desired_matrix); return paused_p; @@ -4118,6 +4125,11 @@ scrolling_window (struct window *w, bool header_line_p) break; } +#ifdef HAVE_XWIDGETS + /* Currently this seems needed to detect xwidget movement reliably. */ + return 0; +#endif + /* Give up if some rows in the desired matrix are not enabled. */ if (! MATRIX_ROW_ENABLED_P (desired_matrix, i)) 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 . */ #include "buffer.h" #include "window.h" +#ifdef HAVE_XWIDGETS +# include "xwidget.h" +#endif #include "atimer.h" #include "blockinput.h" #include "syssignal.h" @@ -1485,6 +1488,9 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem syms_of_xfns (); syms_of_xmenu (); syms_of_fontset (); +#ifdef HAVE_XWIDGETS + syms_of_xwidget (); +#endif syms_of_xsettings (); #ifdef HAVE_X_SM 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 . */ #include "lisp.h" #include "frame.h" #include "xterm.h" +#ifdef HAVE_XWIDGETS +# include "xwidget.h" +#endif #include "emacsgtkfixed.h" /* Silence a bogus diagnostic; see GNOME bug 683906. */ @@ -31,27 +34,10 @@ along with GNU Emacs. If not, see . */ # pragma GCC diagnostic ignored "-Wunused-local-typedefs" #endif -#define EMACS_TYPE_FIXED emacs_fixed_get_type () -#define EMACS_FIXED(obj) \ - G_TYPE_CHECK_INSTANCE_CAST (obj, EMACS_TYPE_FIXED, EmacsFixed) - typedef struct _EmacsFixed EmacsFixed; typedef struct _EmacsFixedPrivate EmacsFixedPrivate; typedef struct _EmacsFixedClass EmacsFixedClass; -struct _EmacsFixed -{ - GtkFixed container; - - /*< private >*/ - EmacsFixedPrivate *priv; -}; - -struct _EmacsFixedClass -{ - GtkFixedClass parent_class; -}; - struct _EmacsFixedPrivate { struct frame *f; @@ -64,9 +50,87 @@ static void emacs_fixed_get_preferred_width (GtkWidget *widget, static void emacs_fixed_get_preferred_height (GtkWidget *widget, gint *minimum, gint *natural); -static GType emacs_fixed_get_type (void); G_DEFINE_TYPE (EmacsFixed, emacs_fixed, GTK_TYPE_FIXED) +#ifdef HAVE_XWIDGETS + +struct GtkFixedPrivateL +{ + GList *children; +}; + +static void emacs_fixed_gtk_widget_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + // For xwidgets. + + // This basically re-implements the base class method and adds an + // additional case for an xwidget view. + + // It would be nicer if the bse class method could be called first, + // and the the xview modification only would remain here. It wasn't + // possible to solve it that way yet. + EmacsFixedClass *klass; + GtkWidgetClass *parent_class; + struct GtkFixedPrivateL* priv; + + klass = EMACS_FIXED_GET_CLASS (widget); + parent_class = g_type_class_peek_parent (klass); + parent_class->size_allocate (widget, allocation); + + priv = G_TYPE_INSTANCE_GET_PRIVATE (widget, + GTK_TYPE_FIXED, + struct GtkFixedPrivateL); + + gtk_widget_set_allocation (widget, allocation); + + if (gtk_widget_get_has_window (widget)) + { + if (gtk_widget_get_realized (widget)) + gdk_window_move_resize (gtk_widget_get_window (widget), + allocation->x, + allocation->y, + allocation->width, + allocation->height); + } + + for (GList *children = priv->children; children; children = children->next) + { + GtkFixedChild *child = children->data; + + if (!gtk_widget_get_visible (child->widget)) + continue; + + GtkRequisition child_requisition; + gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL); + + GtkAllocation child_allocation; + child_allocation.x = child->x; + child_allocation.y = child->y; + + if (!gtk_widget_get_has_window (widget)) + { + child_allocation.x += allocation->x; + child_allocation.y += allocation->y; + } + + child_allocation.width = child_requisition.width; + child_allocation.height = child_requisition.height; + + struct xwidget_view *xv + = g_object_get_data (G_OBJECT (child->widget), XG_XWIDGET_VIEW); + if (xv) + { + child_allocation.width = xv->clip_right; + child_allocation.height = xv->clip_bottom - xv->clip_top; + } + + gtk_widget_size_allocate (child->widget, &child_allocation); + } +} + +#endif /* HAVE_XWIDGETS */ + static void emacs_fixed_class_init (EmacsFixedClass *klass) { @@ -74,11 +138,16 @@ emacs_fixed_class_init (EmacsFixedClass *klass) widget_class = (GtkWidgetClass*) klass; + widget_class->get_preferred_width = emacs_fixed_get_preferred_width; widget_class->get_preferred_height = emacs_fixed_get_preferred_height; +#ifdef HAVE_XWIDGETS + widget_class->size_allocate = emacs_fixed_gtk_widget_size_allocate; +#endif g_type_class_add_private (klass, sizeof (EmacsFixedPrivate)); } + static void emacs_fixed_init (EmacsFixed *fixed) { 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; G_BEGIN_DECLS +struct frame; + +#define EMACS_TYPE_FIXED (emacs_fixed_get_type ()) +#define EMACS_FIXED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMACS_TYPE_FIXED, EmacsFixed)) +#define EMACS_FIXED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EMACS_TYPE_FIXED, EmacsFixedClass)) +#define EMACS_IS_FIXED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMACS_TYPE_FIXED)) +#define EMACS_IS_FIXED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EMACS_TYPE_FIXED)) +#define EMACS_FIXED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EMACS_TYPE_FIXED, EmacsFixedClass)) + +//typedef struct _EmacsFixed EmacsFixed; +typedef struct _EmacsFixedPrivate EmacsFixedPrivate; +typedef struct _EmacsFixedClass EmacsFixedClass; + +struct _EmacsFixed +{ + GtkFixed container; + + /*< private >*/ + EmacsFixedPrivate *priv; +}; + + +struct _EmacsFixedClass +{ + GtkFixedClass parent_class; +}; + extern GtkWidget *emacs_fixed_new (struct frame *f); +extern GType emacs_fixed_get_type (void); G_END_DECLS diff --git a/src/keyboard.c b/src/keyboard.c index 6bdfc1aa084..58831f548ca 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -4013,6 +4013,13 @@ kbd_buffer_get_event (KBOARD **kbp, obj = make_lispy_event (&event->ie); kbd_fetch_ptr = event + 1; } +#endif +#ifdef HAVE_XWIDGETS + else if (event->kind == XWIDGET_EVENT) + { + obj = make_lispy_event (&event->ie); + kbd_fetch_ptr = event + 1; + } #endif else if (event->kind == CONFIG_CHANGED_EVENT) { @@ -5950,6 +5957,14 @@ make_lispy_event (struct input_event *event) } #endif /* HAVE_DBUS */ +#ifdef HAVE_XWIDGETS + case XWIDGET_EVENT: + { + return Fcons (Qxwidget_event,event->arg); + } +#endif + + #if defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY case FILE_NOTIFY_EVENT: { @@ -10956,6 +10971,10 @@ syms_of_keyboard (void) DEFSYM (Qdbus_event, "dbus-event"); #endif +#ifdef HAVE_XWIDGETS + DEFSYM (Qxwidget_event,"xwidget-event"); +#endif + #ifdef USE_FILE_NOTIFY DEFSYM (Qfile_notify, "file-notify"); #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 PVEC_WINDOW_CONFIGURATION, PVEC_SUBR, PVEC_OTHER, + +#ifdef HAVE_XWIDGETS + PVEC_XWIDGET, + PVEC_XWIDGET_VIEW, +#endif + /* These should be last, check internal_equal to see why. */ PVEC_COMPILED, 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 . */ #include "intervals.h" #include "blockinput.h" +#ifdef HAVE_XWIDGETS +# include "xwidget.h" +#endif + #include #include #include @@ -1736,6 +1740,18 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) print_c_string (XSUBR (obj)->symbol_name, printcharfun); printchar ('>', printcharfun); } +#ifdef HAVE_XWIDGETS + else if (XWIDGETP (obj)) + { + print_c_string ("#', printcharfun); + } + else if (XWIDGET_VIEW_P (obj)) + { + print_c_string ("#', printcharfun); + } +#endif else if (WINDOWP (obj)) { int len = sprintf (buf, "#. */ #ifdef MSDOS #include "msdos.h" #endif +#ifdef HAVE_XWIDGETS +# include "xwidget.h" +#endif static ptrdiff_t count_windows (struct window *); static 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. */) /* Block input. */ block_input (); +#ifdef HAVE_XWIDGETS + xwidget_view_delete_all_in_window (w); +#endif window_resize_apply (p, horflag); /* If this window is referred to by the dpyinfo's mouse 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 . */ #include TERM_HEADER #endif /* HAVE_WINDOW_SYSTEM */ +#ifdef HAVE_XWIDGETS +# include "xwidget.h" +#endif #ifndef FRAME_X_OUTPUT #define FRAME_X_OUTPUT(f) ((f)->output_data.x) #endif @@ -854,6 +857,9 @@ static bool next_element_from_buffer (struct it *); static bool next_element_from_composition (struct it *); static bool next_element_from_image (struct it *); static bool next_element_from_stretch (struct it *); +#ifdef HAVE_XWIDGETS +static bool next_element_from_xwidget (struct it *); +#endif static void load_overlay_strings (struct it *, ptrdiff_t); static bool get_next_display_element (struct it *); static enum move_it_result @@ -4690,6 +4696,9 @@ handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, if (CONSP (spec) /* Simple specifications. */ && !EQ (XCAR (spec), Qimage) +#ifdef HAVE_XWIDGETS + && !EQ (XCAR (spec), Qxwidget) +#endif && !EQ (XCAR (spec), Qspace) && !EQ (XCAR (spec), Qwhen) && !EQ (XCAR (spec), Qslice) @@ -5137,7 +5146,12 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p) && valid_image_p (value)) #endif /* not HAVE_WINDOW_SYSTEM */ - || (CONSP (value) && EQ (XCAR (value), Qspace))); + || (CONSP (value) && EQ (XCAR (value), Qspace)) +#ifdef HAVE_XWIDGETS + || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p) + && valid_xwidget_spec_p (value)) +#endif + ); if (valid_p && display_replaced == 0) { @@ -5212,6 +5226,17 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, *position = it->position = start_pos; retval = 1 + (it->area == TEXT_AREA); } +#ifdef HAVE_XWIDGETS + else if (valid_xwidget_spec_p(value)) + { + it->what = IT_XWIDGET; + it->method = GET_FROM_XWIDGET; + it->position = start_pos; + it->object = NILP (object) ? it->w->contents : object; + *position = start_pos; + it->xwidget = lookup_xwidget(value); + } +#endif #ifdef HAVE_WINDOW_SYSTEM else { @@ -5964,6 +5989,11 @@ push_it (struct it *it, struct text_pos *position) case GET_FROM_STRETCH: p->u.stretch.object = it->object; break; +#ifdef HAVE_XWIDGETS + case GET_FROM_XWIDGET: + p->u.xwidget.object = it->object; + break; +#endif case GET_FROM_BUFFER: case GET_FROM_DISPLAY_VECTOR: case GET_FROM_STRING: @@ -6065,6 +6095,11 @@ pop_it (struct it *it) it->object = p->u.image.object; it->slice = p->u.image.slice; break; +#ifdef HAVE_XWIDGETS + case GET_FROM_XWIDGET: + it->object = p->u.xwidget.object; + break; +#endif case GET_FROM_STRETCH: it->object = p->u.stretch.object; break; @@ -6739,7 +6774,10 @@ static next_element_function const get_next_element[NUM_IT_METHODS] = next_element_from_string, next_element_from_c_string, next_element_from_image, - next_element_from_stretch + next_element_from_stretch, +#ifdef HAVE_XWIDGETS + next_element_from_xwidget, +#endif }; #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) case GET_FROM_IMAGE: case GET_FROM_STRETCH: +#ifdef HAVE_XWIDGETS + case GET_FROM_XWIDGET: +#endif + /* The position etc with which we have to proceed are on the stack. The position may be at the end of a string, if the `display' property takes up the whole string. */ @@ -8061,6 +8103,15 @@ next_element_from_image (struct it *it) return true; } +#ifdef HAVE_XWIDGETS +static bool +next_element_from_xwidget (struct it *it) +{ + it->what = IT_XWIDGET; + return true; +} +#endif + /* Fill iterator IT with next display element from a stretch glyph 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) glyph->left_box_line_p, glyph->right_box_line_p); } +#ifdef HAVE_XWIDGETS + else if (glyph->type == XWIDGET_GLYPH) + { + fprintf (stderr, + " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n", + glyph - row->glyphs[TEXT_AREA], + 'X', + glyph->charpos, + (BUFFERP (glyph->object) + ? 'B' + : (STRINGP (glyph->object) + ? 'S' + : '-')), + glyph->pixel_width, + glyph->u.xwidget, + '.', + glyph->face_id, + glyph->left_box_line_p, + glyph->right_box_line_p); + + } +#endif } @@ -24291,6 +24364,13 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, return OK_PIXELS (width_p ? img->width : img->height); } +# ifdef HAVE_XWIDGETS + if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop)) + { + // TODO: Don't return dummy size. + return OK_PIXELS (100); + } +# endif #endif if (EQ (car, Qplus) || EQ (car, Qminus)) { @@ -24796,6 +24876,18 @@ fill_image_glyph_string (struct glyph_string *s) } +#ifdef HAVE_XWIDGETS +static void +fill_xwidget_glyph_string (struct glyph_string *s) +{ + eassert (s->first_glyph->type == XWIDGET_GLYPH); + s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id); + s->font = s->face->font; + s->width = s->first_glyph->pixel_width; + s->ybase += s->first_glyph->voffset; + s->xwidget = s->first_glyph->u.xwidget; +} +#endif /* Fill glyph string S from a sequence of stretch glyphs. 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) } \ while (false) +#ifdef HAVE_XWIDGETS +#define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \ + do \ + { \ + s = alloca (sizeof *s); \ + INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \ + fill_xwidget_glyph_string (s); \ + append_glyph_string (&(HEAD), &(TAIL), s); \ + ++(START); \ + s->x = (X); \ + } \ + while (false) +#endif + /* Add a glyph string for a sequence of character glyphs to the list 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) to allocate glyph strings (because draw_glyphs can be called asynchronously). */ -#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \ +#define BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \ do \ { \ HEAD = TAIL = NULL; \ @@ -25333,8 +25439,17 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p) case IMAGE_GLYPH: \ BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \ HL, X, LAST_X); \ - break; \ - \ + break; + +#ifdef HAVE_XWIDGETS +# define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \ + case XWIDGET_GLYPH: \ + BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL, \ + HL, X, LAST_X); \ + break; +#endif + +#define BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) \ case GLYPHLESS_GLYPH: \ BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \ HL, X, LAST_X); \ @@ -25353,6 +25468,18 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p) } while (false) +#ifdef HAVE_XWIDGETS +# define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \ + BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \ + BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \ + BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) +#else +# define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \ + BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \ + BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) +#endif + + /* Draw glyphs between START and END in AREA of ROW on window W, starting at x-position X. X is relative to AREA in W. HL is a face-override with the following meaning: @@ -25991,6 +26118,109 @@ produce_image_glyph (struct it *it) } } +#ifdef HAVE_XWIDGETS +static void +produce_xwidget_glyph (struct it *it) +{ + struct xwidget *xw; + int glyph_ascent, crop; + eassert (it->what == IT_XWIDGET); + + struct face *face = FACE_FROM_ID (it->f, it->face_id); + eassert (face); + /* Make sure X resources of the face is loaded. */ + prepare_face_for_display (it->f, face); + + xw = it->xwidget; + it->ascent = it->phys_ascent = glyph_ascent = xw->height/2; + it->descent = xw->height/2; + it->phys_descent = it->descent; + it->pixel_width = xw->width; + /* It's quite possible for images to have an ascent greater than + their height, so don't get confused in that case. */ + if (it->descent < 0) + it->descent = 0; + + it->nglyphs = 1; + + if (face->box != FACE_NO_BOX) + { + if (face->box_line_width > 0) + { + it->ascent += face->box_line_width; + it->descent += face->box_line_width; + } + + if (it->start_of_box_run_p) + it->pixel_width += eabs (face->box_line_width); + it->pixel_width += eabs (face->box_line_width); + } + + take_vertical_position_into_account (it); + + /* Automatically crop wide image glyphs at right edge so we can + draw the cursor on same display row. */ + crop = it->pixel_width - (it->last_visible_x - it->current_x); + if (crop > 0 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4)) + it->pixel_width -= crop; + + if (it->glyph_row) + { + enum glyph_row_area area = it->area; + struct glyph *glyph + = it->glyph_row->glyphs[area] + it->glyph_row->used[area]; + + if (it->glyph_row->reversed_p) + { + struct glyph *g; + + /* Make room for the new glyph. */ + for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--) + g[1] = *g; + glyph = it->glyph_row->glyphs[it->area]; + } + if (glyph < it->glyph_row->glyphs[area + 1]) + { + glyph->charpos = CHARPOS (it->position); + glyph->object = it->object; + glyph->pixel_width = it->pixel_width; + glyph->ascent = glyph_ascent; + glyph->descent = it->descent; + glyph->voffset = it->voffset; + glyph->type = XWIDGET_GLYPH; + glyph->avoid_cursor_p = it->avoid_cursor_p; + glyph->multibyte_p = it->multibyte_p; + if (it->glyph_row->reversed_p && area == TEXT_AREA) + { + /* In R2L rows, the left and the right box edges need to be + drawn in reverse direction. */ + glyph->right_box_line_p = it->start_of_box_run_p; + glyph->left_box_line_p = it->end_of_box_run_p; + } + else + { + glyph->left_box_line_p = it->start_of_box_run_p; + glyph->right_box_line_p = it->end_of_box_run_p; + } + glyph->overlaps_vertically_p = 0; + glyph->padding_p = 0; + glyph->glyph_not_available_p = 0; + glyph->face_id = it->face_id; + glyph->u.xwidget = it->xwidget; + glyph->font_type = FONT_TYPE_UNKNOWN; + if (it->bidi_p) + { + glyph->resolved_level = it->bidi_it.resolved_level; + eassert ((it->bidi_it.type & 7) == it->bidi_it.type); + glyph->bidi_type = it->bidi_it.type; + } + ++it->glyph_row->used[area]; + } + else + IT_EXPAND_MATRIX_WIDTH (it, area); + } +} +#endif /* Append a stretch glyph to IT->glyph_row. OBJECT is the source of the glyph, WIDTH and HEIGHT are the width and height of the @@ -27401,6 +27631,10 @@ x_produce_glyphs (struct it *it) produce_image_glyph (it); else if (it->what == IT_STRETCH) produce_stretch_glyph (it); +#ifdef HAVE_XWIDGETS + else if (it->what == IT_XWIDGET) + produce_xwidget_glyph (it); +#endif done: /* 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, /* Use normal cursor if not blinked off. */ if (!w->cursor_off_p) { +#ifdef HAVE_XWIDGETS + if (glyph != NULL && glyph->type == XWIDGET_GLYPH) + return NO_CURSOR; +#endif if (glyph != NULL && glyph->type == IMAGE_GLYPH) { 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 . */ #include "composite.h" #include "frame.h" #include "dispextern.h" +#ifdef HAVE_XWIDGETS +# include "xwidget.h" +#endif #include "fontset.h" #include "termhooks.h" #include "termopts.h" @@ -3511,6 +3514,12 @@ x_draw_glyph_string (struct glyph_string *s) x_draw_image_glyph_string (s); break; +#ifdef HAVE_XWIDGETS + case XWIDGET_GLYPH: + x_draw_xwidget_glyph_string (s); + break; +#endif + case STRETCH_GLYPH: x_draw_stretch_glyph_string (s); break; @@ -8920,6 +8929,11 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text if (cursor_glyph == NULL) return; +#ifdef HAVE_XWIDGETS + if (cursor_glyph->type == XWIDGET_GLYPH) + return; // Experimental avoidance of cursor on xwidget. +#endif + /* If on an image, draw like a normal cursor. That's usually better visible than drawing a bar, esp. if the image is large so that 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 @@ +/* Support for embedding graphical components in a buffer. + +Copyright (C) 2011-2015 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Emacs. If not, see . */ + +#include + + +#include + +#include +#include +#ifdef HAVE_X_WINDOWS + +#include "lisp.h" +#include "blockinput.h" +#include "syssignal.h" + +#include "xterm.h" +#include + +#ifndef makedev +# include +#endif + +#ifdef BSD_SYSTEM +# include +#endif + +#include "systime.h" + +#ifndef INCLUDED_FCNTL +# include +#endif +#include +#include +#include +#include + +#include "charset.h" +#include "character.h" +#include "coding.h" +#include "ccl.h" +#include "frame.h" +#include "dispextern.h" +#include "fontset.h" +#include "termhooks.h" +#include "termopts.h" +#include "termchar.h" +#include "disptab.h" +#include "buffer.h" +#include "window.h" +#include "keyboard.h" +#include "intervals.h" +#include "process.h" +#include "atimer.h" +#include "keymap.h" + + +#ifdef USE_X_TOOLKIT +#include +#endif +#include +#include +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "gtkutil.h" +#include "font.h" +#endif /* HAVE_X_WINDOWS */ + +#include +#include + +#include + +#include "emacsgtkfixed.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "xwidget.h" + +static struct xwidget * +allocate_xwidget (void) +{ + return ALLOCATE_PSEUDOVECTOR (struct xwidget, height, PVEC_XWIDGET); +} + +static struct xwidget_view * +allocate_xwidget_view (void) +{ + return ALLOCATE_PSEUDOVECTOR (struct xwidget_view, redisplayed, + PVEC_XWIDGET_VIEW); +} + +#define XSETXWIDGET(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET)) +#define XSETXWIDGET_VIEW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET_VIEW)) + +struct xwidget_view *xwidget_view_lookup (struct xwidget *, struct window *); +Lisp_Object xwidget_spec_value (Lisp_Object , Lisp_Object , int *); +gboolean offscreen_damage_event (GtkWidget * , GdkEvent * , gpointer ); +void webkit_document_load_finished_cb (WebKitWebView *, WebKitWebFrame *, + gpointer ); +gboolean webkit_download_cb (WebKitWebView *, WebKitDownload *, gpointer); + +gboolean +webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *, + WebKitWebFrame *, + WebKitNetworkRequest *, + gchar *, + WebKitWebPolicyDecision *, + gpointer); + +gboolean +webkit_new_window_policy_decision_requested_cb (WebKitWebView *, + WebKitWebFrame *, + WebKitNetworkRequest *, + WebKitWebNavigationAction *, + WebKitWebPolicyDecision *, + gpointer); + +gboolean +webkit_navigation_policy_decision_requested_cb (WebKitWebView *, + WebKitWebFrame *, + WebKitNetworkRequest *, + WebKitWebNavigationAction *, + WebKitWebPolicyDecision *, + gpointer); + + + +DEFUN ("make-xwidget", + Fmake_xwidget, Smake_xwidget, + 7, 8, 0, + doc: /* Make an xwidget from BEG to END of TYPE. + +If BUFFER is nil it uses the current +buffer. If BUFFER is a string and no such +buffer exists, it is created. + +TYPE is a symbol which can take one of the +following values: + +- webkit_osr + +Returns the newly constructed xwidget, or nil if construction +fails. */) + (Lisp_Object beg, Lisp_Object end, + Lisp_Object type, + Lisp_Object title, + Lisp_Object width, Lisp_Object height, + Lisp_Object arguments, Lisp_Object buffer) +{ + //should work a bit like "make-button"(make-button BEG END &rest PROPERTIES) + // arg "type" and fwd should be keyword args eventually + //(make-xwidget 3 3 'button "oei" 31 31 nil) + //(xwidget-info (car xwidget-list)) + struct xwidget *xw = allocate_xwidget (); + Lisp_Object val; + xw->type = type; + xw->title = title; + if (NILP (buffer)) + buffer = Fcurrent_buffer (); // no need to gcpro because + // Fcurrent_buffer doesn't + // call Feval/eval_sub. + else + buffer = Fget_buffer_create (buffer); + xw->buffer = buffer; + + xw->height = XFASTINT (height); + xw->width = XFASTINT (width); + xw->kill_without_query = 0; + XSETXWIDGET (val, xw); // set the vectorlike_header of VAL + // with the correct value + Vxwidget_list = Fcons (val, Vxwidget_list); + xw->widgetwindow_osr = NULL; + xw->widget_osr = NULL; + xw->plist = Qnil; + + + if (EQ (xw->type, Qwebkit_osr)) + { + block_input (); + xw->widgetwindow_osr = gtk_offscreen_window_new (); + gtk_window_resize (GTK_WINDOW (xw->widgetwindow_osr), xw->width, + xw->height); + xw->widgetscrolledwindow_osr = NULL; //webkit osr is the + //only scrolled + //component atm + + if (EQ (xw->type, Qwebkit_osr)) + { + xw->widgetscrolledwindow_osr = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW + (xw-> + widgetscrolledwindow_osr), + xw->height); + gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW + (xw-> + widgetscrolledwindow_osr), + xw->width); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW + (xw->widgetscrolledwindow_osr), + GTK_POLICY_ALWAYS, + GTK_POLICY_ALWAYS); + + xw->widget_osr = webkit_web_view_new (); + gtk_container_add (GTK_CONTAINER (xw->widgetscrolledwindow_osr), + GTK_WIDGET (WEBKIT_WEB_VIEW (xw->widget_osr))); + } + + gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, + xw->height); + + if (EQ (xw->type, Qwebkit_osr)) + { + gtk_container_add (GTK_CONTAINER (xw->widgetwindow_osr), + xw->widgetscrolledwindow_osr); + } + else + { + gtk_container_add (GTK_CONTAINER (xw->widgetwindow_osr), + xw->widget_osr); + } + + gtk_widget_show (xw->widget_osr); + gtk_widget_show (xw->widgetwindow_osr); + gtk_widget_show (xw->widgetscrolledwindow_osr); + + /* store some xwidget data in the gtk widgets for convenient + retrieval in the event handlers. */ + g_object_set_data (G_OBJECT (xw->widget_osr), XG_XWIDGET, + (gpointer) (xw)); + g_object_set_data (G_OBJECT (xw->widgetwindow_osr), XG_XWIDGET, + (gpointer) (xw)); + + /* signals */ + if (EQ (xw->type, Qwebkit_osr)) + { + g_signal_connect (G_OBJECT (xw->widget_osr), + "document-load-finished", + G_CALLBACK + (webkit_document_load_finished_cb), xw); + + g_signal_connect (G_OBJECT (xw->widget_osr), + "download-requested", + G_CALLBACK (webkit_download_cb), xw); + + g_signal_connect (G_OBJECT (xw->widget_osr), + "mime-type-policy-decision-requested", + G_CALLBACK + (webkit_mime_type_policy_typedecision_requested_cb), + xw); + + g_signal_connect (G_OBJECT (xw->widget_osr), + "new-window-policy-decision-requested", + G_CALLBACK + (webkit_new_window_policy_decision_requested_cb), + xw); + + g_signal_connect (G_OBJECT (xw->widget_osr), + "navigation-policy-decision-requested", + G_CALLBACK + (webkit_navigation_policy_decision_requested_cb), + xw); + } + + unblock_input (); + + } + + return val; +} + +DEFUN ("get-buffer-xwidgets", Fget_buffer_xwidgets, Sget_buffer_xwidgets, + 1, 1, 0, + doc: /* Return a list of xwidgets associated with BUFFER. +BUFFER may be a buffer or the name of one. */) + (Lisp_Object buffer) +{ + Lisp_Object xw, tail, xw_list; + + if (NILP (buffer)) + return Qnil; + buffer = Fget_buffer (buffer); + if (NILP (buffer)) + return Qnil; + + xw_list = Qnil; + + for (tail = Vxwidget_list; CONSP (tail); tail = XCDR (tail)) + { + xw = XCAR (tail); + if (XWIDGETP (xw) && EQ (Fxwidget_buffer (xw), buffer)) + xw_list = Fcons (xw, xw_list); + } + return xw_list; +} + +static int +xwidget_hidden (struct xwidget_view *xv) +{ + return xv->hidden; +} + + + +static void +xwidget_show_view (struct xwidget_view *xv) +{ + xv->hidden = 0; + gtk_widget_show (xv->widgetwindow); + gtk_fixed_move (GTK_FIXED (xv->emacswindow), + xv->widgetwindow, + xv->x + xv->clip_left, + xv->y + xv->clip_top); +} + + +/* Hide an xvidget view. */ +static void +xwidget_hide_view (struct xwidget_view *xv) +{ + xv->hidden = 1; + gtk_fixed_move (GTK_FIXED (xv->emacswindow), xv->widgetwindow, + 10000, 10000); +} + + + +/* When the off-screen webkit master view changes this signal is called. + It copies the bitmap from the off-screen instance. */ +gboolean +offscreen_damage_event (GtkWidget * widget, GdkEvent * event, + gpointer xv_widget) +{ + // Queue a redraw of onscreen widget. + // There is a guard against receiving an invalid widget, + // which should only happen if we failed to remove the + // specific signal handler for the damage event. + if (GTK_IS_WIDGET (xv_widget)) + gtk_widget_queue_draw (GTK_WIDGET (xv_widget)); + else + printf ("Warning, offscreen_damage_event received invalid xv pointer:%p\n", + (void *) xv_widget); + + return FALSE; +} + +static void +store_xwidget_event_string (struct xwidget *xw, const char *eventname, + const char *eventstr) +{ + struct input_event event; + Lisp_Object xwl; + XSETXWIDGET (xwl, xw); + EVENT_INIT (event); + event.kind = XWIDGET_EVENT; + event.frame_or_window = Qnil; + + event.arg = Qnil; + event.arg = Fcons (build_string (eventstr), event.arg); + event.arg = Fcons (xwl, event.arg); + event.arg = Fcons (intern (eventname), event.arg); + kbd_buffer_store_event (&event); + +} + +//TODO deprecated, use load-status +void +webkit_document_load_finished_cb (WebKitWebView * webkitwebview, + WebKitWebFrame * arg1, + gpointer data) +{ + struct xwidget *xw = + (struct xwidget *) g_object_get_data (G_OBJECT (webkitwebview), + XG_XWIDGET); + + store_xwidget_event_string (xw, "document-load-finished", ""); +} + +gboolean +webkit_download_cb (WebKitWebView * webkitwebview, + WebKitDownload * arg1, + gpointer data) +{ + struct xwidget *xw = + (struct xwidget *) g_object_get_data (G_OBJECT (webkitwebview), + XG_XWIDGET); + store_xwidget_event_string (xw, "download-requested", + webkit_download_get_uri (arg1)); + + return FALSE; +} + +gboolean +webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *webView, + WebKitWebFrame *frame, + WebKitNetworkRequest * request, + gchar * mimetype, + WebKitWebPolicyDecision *policy_decision, + gpointer user_data) +{ + // This function makes webkit send a download signal for all unknown + // mime types. TODO Defer the decision to lisp, so that its possible + // to make Emacs handle teext mime for instance.xs + if (!webkit_web_view_can_show_mime_type (webView, mimetype)) + { + webkit_web_policy_decision_download (policy_decision); + return TRUE; + } + else + { + return FALSE; + } +} + + +gboolean +webkit_new_window_policy_decision_requested_cb (WebKitWebView *webView, + WebKitWebFrame *frame, + WebKitNetworkRequest *request, + WebKitWebNavigationAction *navigation_action, + WebKitWebPolicyDecision *policy_decision, + gpointer user_data) +{ + struct xwidget *xw = + (struct xwidget *) g_object_get_data (G_OBJECT (webView), XG_XWIDGET); + webkit_web_navigation_action_get_original_uri (navigation_action); + + store_xwidget_event_string (xw, "new-window-policy-decision-requested", + webkit_web_navigation_action_get_original_uri + (navigation_action)); + return FALSE; +} + +gboolean +webkit_navigation_policy_decision_requested_cb (WebKitWebView *webView, + WebKitWebFrame *frame, + WebKitNetworkRequest *request, + WebKitWebNavigationAction *navigation_action, + WebKitWebPolicyDecision * policy_decision, + gpointer user_data) +{ + struct xwidget *xw = + (struct xwidget *) g_object_get_data (G_OBJECT (webView), XG_XWIDGET); + store_xwidget_event_string (xw, "navigation-policy-decision-requested", + webkit_web_navigation_action_get_original_uri + (navigation_action)); + return FALSE; +} + +// For gtk3 offscreen rendered widgets. +static gboolean +xwidget_osr_draw_cb (GtkWidget * widget, cairo_t * cr, gpointer data) +{ + struct xwidget *xw = + (struct xwidget *) g_object_get_data (G_OBJECT (widget), XG_XWIDGET); + struct xwidget_view *xv = + (struct xwidget_view *) g_object_get_data (G_OBJECT (widget), + XG_XWIDGET_VIEW); + + cairo_rectangle (cr, 0, 0, xv->clip_right, xv->clip_bottom); + cairo_clip (cr); + + if (xw->widgetscrolledwindow_osr != NULL) + gtk_widget_draw (xw->widgetscrolledwindow_osr, cr); + else + gtk_widget_draw (xw->widget_osr, cr); + return FALSE; +} + +static gboolean +xwidget_osr_event_forward (GtkWidget * widget, + GdkEvent * event, + gpointer user_data) +{ + /* Copy events that arrive at the outer widget to the offscreen widget. */ + struct xwidget *xw = + (struct xwidget *) g_object_get_data (G_OBJECT (widget), XG_XWIDGET); + GdkEvent *eventcopy = gdk_event_copy (event); + eventcopy->any.window = gtk_widget_get_window (xw->widget_osr); + + //TODO This might leak events. They should be deallocated later, + //perhaps in xwgir_event_cb + gtk_main_do_event (eventcopy); + return TRUE; //dont propagate this event furter +} + + +static gboolean +xwidget_osr_event_set_embedder (GtkWidget * widget, + GdkEvent * event, gpointer data) +{ + struct xwidget_view *xv = (struct xwidget_view *) data; + struct xwidget *xww = XXWIDGET (xv->model); + gdk_offscreen_window_set_embedder (gtk_widget_get_window + (xww->widgetwindow_osr), + gtk_widget_get_window (xv->widget)); + return FALSE; +} + + +/* Initializes and does initial placement of an xwidget view on screen. */ +static struct xwidget_view * +xwidget_init_view (struct xwidget *xww, + struct glyph_string *s, + int x, int y) +{ + struct xwidget_view *xv = allocate_xwidget_view (); + Lisp_Object val; + + XSETXWIDGET_VIEW (val, xv); + Vxwidget_view_list = Fcons (val, Vxwidget_view_list); + + XSETWINDOW (xv->w, s->w); + XSETXWIDGET (xv->model, xww); + + if (EQ (xww->type, Qwebkit_osr)) + { + xv->widget = gtk_drawing_area_new (); + // Expose event handling. + gtk_widget_set_app_paintable (xv->widget, TRUE); + gtk_widget_add_events (xv->widget, GDK_ALL_EVENTS_MASK); + + /* Draw the view on damage-event */ + g_signal_connect (G_OBJECT (xww->widgetwindow_osr), "damage-event", + G_CALLBACK (offscreen_damage_event), xv->widget); + + if (EQ (xww->type, Qwebkit_osr)) + { + g_signal_connect (G_OBJECT (xv->widget), "button-press-event", + G_CALLBACK (xwidget_osr_event_forward), NULL); + g_signal_connect (G_OBJECT (xv->widget), "button-release-event", + G_CALLBACK (xwidget_osr_event_forward), NULL); + g_signal_connect (G_OBJECT (xv->widget), "motion-notify-event", + G_CALLBACK (xwidget_osr_event_forward), NULL); + } + else + { + // xwgir debug , orthogonal to forwarding + g_signal_connect (G_OBJECT (xv->widget), "enter-notify-event", + G_CALLBACK (xwidget_osr_event_set_embedder), xv); + } + g_signal_connect (G_OBJECT (xv->widget), "draw", + G_CALLBACK (xwidget_osr_draw_cb), NULL); + } + // Widget realization. + + // Make container widget 1st, and put the actual widget inside the + // container later. Drawing should crop container window if necessary + // to handle case where xwidget is partially obscured by other Emacs + // windows. Other containers than gtk_fixed where explored, but + // gtk_fixed had the most predictable behaviour so far. + xv->emacswindow = FRAME_GTK_WIDGET (s->f); + xv->widgetwindow = gtk_fixed_new (); + gtk_widget_set_has_window (xv->widgetwindow, TRUE); + gtk_container_add (GTK_CONTAINER (xv->widgetwindow), xv->widget); + + // Store some xwidget data in the gtk widgets. + // The emacs frame. + g_object_set_data (G_OBJECT (xv->widget), XG_FRAME_DATA, (gpointer) (s->f)); + // The xwidget. + g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET, (gpointer) (xww)); + // The xwidget. + g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET_VIEW, (gpointer) (xv)); + // The xwidget window. + g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET, (gpointer) (xww)); + // the xwidget view. + g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET_VIEW, + (gpointer) (xv)); + + + gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xww->width, + xww->height); + gtk_widget_set_size_request (xv->widgetwindow, xww->width, xww->height); + gtk_fixed_put (GTK_FIXED (FRAME_GTK_WIDGET (s->f)), xv->widgetwindow, x, y); + xv->x = x; + xv->y = y; + gtk_widget_show_all (xv->widgetwindow); + + + return xv; +} + + +void +x_draw_xwidget_glyph_string (struct glyph_string *s) +{ + /* This method is called by the redisplay engine and places the + xwidget on screen. Moving and clipping is done here. Also view + initialization. + */ + struct xwidget *xww = s->xwidget; + struct xwidget_view *xv = xwidget_view_lookup (xww, s->w); + int clip_right; + int clip_bottom; + int clip_top; + int clip_left; + + int x = s->x; + int y = s->y + (s->height / 2) - (xww->height / 2); + int moved = 0; + + /* We do initialization here in the display loop because there is no + other time to know things like window placement etc. + */ + xv = xwidget_init_view (xww, s, x, y); + + // Calculate clipping, which is used for all manner of onscreen + // xwidget views. Each widget border can get clipped by other emacs + // objects so there are four clipping variables. + clip_right = + min (xww->width, + WINDOW_RIGHT_EDGE_X (s->w) - x - + WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w) - + WINDOW_RIGHT_FRINGE_WIDTH (s->w)); + clip_left = + max (0, + WINDOW_LEFT_EDGE_X (s->w) - x + + WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (s->w) + + WINDOW_LEFT_FRINGE_WIDTH (s->w)); + + clip_bottom = + min (xww->height, + WINDOW_BOTTOM_EDGE_Y (s->w) - WINDOW_MODE_LINE_HEIGHT (s->w) - y); + clip_top = max (0, WINDOW_TOP_EDGE_Y (s->w) - y); + + // We are conserned with movement of the onscreen area. The area + // might sit still when the widget actually moves. This happens + // when an Emacs window border moves across a widget window. So, if + // any corner of the outer widget clipping window moves, that counts + // as movement here, even if it looks like no movement happens + // because the widget sits still inside the clipping area. The + // widget can also move inside the clipping area, which happens + // later + moved = (xv->x + xv->clip_left != x + clip_left) + || ((xv->y + xv->clip_top) != (y + clip_top)); + xv->x = x; + xv->y = y; + if (moved) // Has it moved? + { + gtk_fixed_move (GTK_FIXED (FRAME_GTK_WIDGET (s->f)), + xv->widgetwindow, x + clip_left, y + clip_top); + } + // Clip the widget window if some parts happen to be outside + // drawable area. An Emacs window is not a gtk window. A gtk window + // covers the entire frame. Clipping might have changed even if we + // havent actualy moved, we try figure out when we need to reclip + // for real. + if ((xv->clip_right != clip_right) + || (xv->clip_bottom != clip_bottom) + || (xv->clip_top != clip_top) || (xv->clip_left != clip_left)) + { + gtk_widget_set_size_request (xv->widgetwindow, clip_right + clip_left, + clip_bottom + clip_top); + gtk_fixed_move (GTK_FIXED (xv->widgetwindow), xv->widget, -clip_left, + -clip_top); + + xv->clip_right = clip_right; + xv->clip_bottom = clip_bottom; + xv->clip_top = clip_top; + xv->clip_left = clip_left; + } + // If emacs wants to repaint the area where the widget lives, queue + // a redraw. It seems its possible to get out of sync with emacs + // redraws so emacs background sometimes shows up instead of the + // xwidgets background. It's just a visual glitch though. + if (!xwidget_hidden (xv)) + { + gtk_widget_queue_draw (xv->widgetwindow); + gtk_widget_queue_draw (xv->widget); + } +} + + +// Macro that checks WEBKIT_IS_WEB_VIEW(xw->widget_osr) first +#define WEBKIT_FN_INIT() \ + struct xwidget* xw; \ + CHECK_XWIDGET (xwidget); \ + if (NILP (xwidget)) {printf("ERROR xwidget nil\n"); return Qnil;}; \ + xw = XXWIDGET (xwidget); \ + if (NULL == xw) printf("ERROR xw is 0\n"); \ + if ((NULL == xw->widget_osr) || !WEBKIT_IS_WEB_VIEW(xw->widget_osr)){ \ + printf ("ERROR xw->widget_osr does not hold a webkit instance\n");\ + return Qnil;\ + }; + + +DEFUN ("xwidget-webkit-goto-uri", + Fxwidget_webkit_goto_uri, Sxwidget_webkit_goto_uri, + 2, 2, 0, + doc: /* Make the xwidget webkit instance referenced by XWIDGET +browse URI. */) + (Lisp_Object xwidget, Lisp_Object uri) +{ + WEBKIT_FN_INIT (); + CHECK_STRING (uri); + webkit_web_view_load_uri (WEBKIT_WEB_VIEW (xw->widget_osr), SSDATA (uri)); + return Qnil; +} + + +DEFUN ("xwidget-webkit-execute-script", + Fxwidget_webkit_execute_script, Sxwidget_webkit_execute_script, + 2, 2, 0, + doc: /* Make the Webkit XWIDGET execute javascript SCRIPT. */) + (Lisp_Object xwidget, Lisp_Object script) +{ + WEBKIT_FN_INIT (); + CHECK_STRING (script); + webkit_web_view_execute_script (WEBKIT_WEB_VIEW (xw->widget_osr), + SSDATA (script)); + return Qnil; +} + +DEFUN ("xwidget-webkit-get-title", + Fxwidget_webkit_get_title, Sxwidget_webkit_get_title, + 1, 1, 0, + doc: /* Returns the title from the Webkit instance in XWIDGET. +This can be used to work around the lack of a return value from the +exec method. */ ) + (Lisp_Object xwidget) +{ + // TODO support multibyte strings + WEBKIT_FN_INIT (); + const gchar *str = + webkit_web_view_get_title (WEBKIT_WEB_VIEW (xw->widget_osr)); + if (str == 0) + { + // TODO maybe return Qnil instead. I suppose webkit returns + // nullpointer when doc is not properly loaded or something + return build_string (""); + } + return build_string (str); +} + +DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 3, 3, 0, + doc: /* Resize XWIDGET. NEW_WIDTH NEW_HEIGHT defines the new +size. */ ) + (Lisp_Object xwidget, Lisp_Object new_width, Lisp_Object new_height) +{ + CHECK_XWIDGET (xwidget); + struct xwidget *xw = XXWIDGET (xwidget); + struct xwidget_view *xv; + int w, h; + + CHECK_NUMBER (new_width); + CHECK_NUMBER (new_height); + w = XFASTINT (new_width); + h = XFASTINT (new_height); + + xw->width = w; + xw->height = h; + // If there is a offscreen widget resize it 1st. + if (xw->widget_osr) + { + gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), + xw->width, xw->height); //minimum size + gtk_window_resize (GTK_WINDOW (xw->widgetwindow_osr), xw->width, + xw->height); + gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW + (xw-> + widgetscrolledwindow_osr), + xw->height); + gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW + (xw-> + widgetscrolledwindow_osr), + xw->width); + + gtk_container_resize_children (GTK_CONTAINER (xw->widgetwindow_osr)); + + } + + for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail)) + { + if (XWIDGET_VIEW_P (XCAR (tail))) + { + xv = XXWIDGET_VIEW (XCAR (tail)); + if (XXWIDGET (xv->model) == xw) + gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xw->width, + xw->height); + } + } + + return Qnil; +} + + + +DEFUN ("xwidget-set-adjustment", + Fxwidget_set_adjustment, Sxwidget_set_adjustment, 4, 4, 0, + doc: /* Set native scrolling for XWIDGET. AXIS can be 'vertical or +'horizontal. If RELATIVE is t, scroll relative, otherwise absolutely. +VALUE is the amount to scroll, either relatively or absolutely. */) + (Lisp_Object xwidget, Lisp_Object axis, Lisp_Object relative, + Lisp_Object value) +{ + CHECK_XWIDGET (xwidget); + struct xwidget *xw = XXWIDGET (xwidget); + GtkAdjustment *adjustment; + float final_value = 0.0; + + adjustment = + gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW + (xw->widgetscrolledwindow_osr)); + if (EQ (Qvertical, axis)) + { + adjustment = + gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW + (xw->widgetscrolledwindow_osr)); + } + if (EQ (Qhorizontal, axis)) + { + adjustment = + gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW + (xw->widgetscrolledwindow_osr)); + } + + if (EQ (Qt, relative)) + { + final_value = gtk_adjustment_get_value (adjustment) + XFASTINT (value); + } + else + { + final_value = 0.0 + XFASTINT (value); + } + + gtk_adjustment_set_value (adjustment, final_value); + + return Qnil; +} + + +DEFUN ("xwidget-size-request", + Fxwidget_size_request, Sxwidget_size_request, + 1, 1, 0, + doc: /* Return the desired size of the XWIDGET. + +This can be used to read the xwidget desired size, and resizes the +Emacs allocated area accordingly. */) + (Lisp_Object xwidget) +{ + CHECK_XWIDGET (xwidget); + GtkRequisition requisition; + Lisp_Object rv; + gtk_widget_size_request (XXWIDGET (xwidget)->widget_osr, &requisition); + rv = Qnil; + rv = Fcons (make_number (requisition.height), rv); + rv = Fcons (make_number (requisition.width), rv); + return rv; + +} + +DEFUN ("xwidgetp", + Fxwidgetp, Sxwidgetp, + 1, 1, 0, + doc: /* Return t if OBJECT is a xwidget. */) + (Lisp_Object object) +{ + return XWIDGETP (object) ? Qt : Qnil; +} + +DEFUN ("xwidget-view-p", + Fxwidget_view_p, Sxwidget_view_p, + 1, 1, 0, + doc: /* Return t if OBJECT is a xwidget-view. */) + (Lisp_Object object) +{ + return XWIDGET_VIEW_P (object) ? Qt : Qnil; +} + +DEFUN ("xwidget-info", + Fxwidget_info, Sxwidget_info, + 1, 1, 0, + doc: /* Return XWIDGET properties in a vector. Currently [TYPE +TITLE WIDTH HEIGHT]. */) + (Lisp_Object xwidget) +{ + CHECK_XWIDGET (xwidget); + Lisp_Object info, n; + struct xwidget *xw = XXWIDGET (xwidget); + + info = Fmake_vector (make_number (4), Qnil); + ASET (info, 0, xw->type); + ASET (info, 1, xw->title); + XSETFASTINT (n, xw->width); + ASET (info, 2, n); + XSETFASTINT (n, xw->height); + ASET (info, 3, n); + + return info; +} + +DEFUN ("xwidget-view-info", + Fxwidget_view_info, Sxwidget_view_info, + 1, 1, 0, + doc: /* Return properties of XWIDGET-VIEW in a vector. +Currently [X Y CLIP_RIGHT CLIP_BOTTOM CLIP_TOP CLIP_LEFT] */) + (Lisp_Object xwidget_view) +{ + CHECK_XWIDGET_VIEW (xwidget_view); + struct xwidget_view *xv = XXWIDGET_VIEW (xwidget_view); + Lisp_Object info; + + info = Fmake_vector (make_number (6), Qnil); + ASET (info, 0, make_number (xv->x)); + ASET (info, 1, make_number (xv->y)); + ASET (info, 2, make_number (xv->clip_right)); + ASET (info, 3, make_number (xv->clip_bottom)); + ASET (info, 4, make_number (xv->clip_top)); + ASET (info, 5, make_number (xv->clip_left)); + + return info; +} + +DEFUN ("xwidget-view-model", + Fxwidget_view_model, Sxwidget_view_model, + 1, 1, 0, + doc: /* Return the model associated with XWIDGET-VIEW. */) + (Lisp_Object xwidget_view) +{ + CHECK_XWIDGET_VIEW (xwidget_view); + return XXWIDGET_VIEW (xwidget_view)->model; +} + +DEFUN ("xwidget-view-window", + Fxwidget_view_window, Sxwidget_view_window, + 1, 1, 0, + doc: /* Return the window of XWIDGET-VIEW. */) + (Lisp_Object xwidget_view) +{ + CHECK_XWIDGET_VIEW (xwidget_view); + return XXWIDGET_VIEW (xwidget_view)->w; +} + + +DEFUN ("delete-xwidget-view", + Fdelete_xwidget_view, Sdelete_xwidget_view, + 1, 1, 0, + doc: /* Delete the XWIDGET-VIEW. */) + (Lisp_Object xwidget_view) +{ + CHECK_XWIDGET_VIEW (xwidget_view); + struct xwidget_view *xv = XXWIDGET_VIEW (xwidget_view); + gtk_widget_destroy (xv->widgetwindow); + Vxwidget_view_list = Fdelq (xwidget_view, Vxwidget_view_list); + // xv->model still has signals pointing to the view. There can be + // several views. Find the matching signals and delete them all. + g_signal_handlers_disconnect_matched (XXWIDGET (xv->model)->widgetwindow_osr, + G_SIGNAL_MATCH_DATA, + 0, 0, 0, 0, + xv->widget); + return Qnil; +} + +DEFUN ("xwidget-view-lookup", + Fxwidget_view_lookup, Sxwidget_view_lookup, + 1, 2, 0, + doc: /* Return the xwidget-view associated with XWIDGET in +WINDOW if specified, otherwise it uses the selected window. Return nil +if no association is found. */) + (Lisp_Object xwidget, Lisp_Object window) +{ + CHECK_XWIDGET (xwidget); + + if (NILP (window)) + window = Fselected_window (); + CHECK_WINDOW (window); + + for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); + tail = XCDR (tail)) + { + Lisp_Object xwidget_view = XCAR (tail); + if (EQ (Fxwidget_view_model (xwidget_view), xwidget) + && EQ (Fxwidget_view_window (xwidget_view), window)) + return xwidget_view; + } + + return Qnil; +} + +DEFUN ("xwidget-plist", + Fxwidget_plist, Sxwidget_plist, + 1, 1, 0, + doc: /* Return the plist of XWIDGET. */) + (register Lisp_Object xwidget) +{ + CHECK_XWIDGET (xwidget); + return XXWIDGET (xwidget)->plist; +} + +DEFUN ("xwidget-buffer", + Fxwidget_buffer, Sxwidget_buffer, + 1, 1, 0, + doc: /* Return the buffer of XWIDGET. */) + (register Lisp_Object xwidget) +{ + CHECK_XWIDGET (xwidget); + return XXWIDGET (xwidget)->buffer; +} + +DEFUN ("set-xwidget-plist", + Fset_xwidget_plist, Sset_xwidget_plist, + 2, 2, 0, + doc: /* Replace the plist of XWIDGET with PLIST. +Returns PLIST. */) + (register Lisp_Object xwidget, Lisp_Object plist) +{ + CHECK_XWIDGET (xwidget); + CHECK_LIST (plist); + + XXWIDGET (xwidget)->plist = plist; + return plist; +} + +DEFUN ("set-xwidget-query-on-exit-flag", + Fset_xwidget_query_on_exit_flag, Sset_xwidget_query_on_exit_flag, + 2, 2, 0, + doc: /* Specify if query is needed for XWIDGET when +Emacs is exited. If the second argument FLAG is non-nil, Emacs will +queries the user before exiting or killing a buffer if XWIDGET is +running. This function returns FLAG. */) + (Lisp_Object xwidget, Lisp_Object flag) +{ + CHECK_XWIDGET (xwidget); + XXWIDGET (xwidget)->kill_without_query = NILP (flag); + return flag; +} + +DEFUN ("xwidget-query-on-exit-flag", + Fxwidget_query_on_exit_flag, Sxwidget_query_on_exit_flag, + 1, 1, 0, + doc: /* Return the current value of query-on-exit +flag for XWIDGET. */) + (Lisp_Object xwidget) +{ + CHECK_XWIDGET (xwidget); + return (XXWIDGET (xwidget)->kill_without_query ? Qnil : Qt); +} + +void +syms_of_xwidget (void) +{ + + defsubr (&Smake_xwidget); + defsubr (&Sxwidgetp); + DEFSYM (Qxwidgetp, "xwidgetp"); + defsubr (&Sxwidget_view_p); + DEFSYM (Qxwidget_view_p, "xwidget-view-p"); + defsubr (&Sxwidget_info); + defsubr (&Sxwidget_view_info); + defsubr (&Sxwidget_resize); + defsubr (&Sget_buffer_xwidgets); + defsubr (&Sxwidget_view_model); + defsubr (&Sxwidget_view_window); + defsubr (&Sxwidget_view_lookup); + defsubr (&Sxwidget_query_on_exit_flag); + defsubr (&Sset_xwidget_query_on_exit_flag); + +#ifdef HAVE_WEBKIT_OSR + defsubr (&Sxwidget_webkit_goto_uri); + defsubr (&Sxwidget_webkit_execute_script); + defsubr (&Sxwidget_webkit_get_title); + DEFSYM (Qwebkit_osr, "webkit-osr"); +#endif + + defsubr (&Sxwidget_size_request); + defsubr (&Sdelete_xwidget_view); + + defsubr (&Sxwidget_plist); + defsubr (&Sxwidget_buffer); + defsubr (&Sset_xwidget_plist); + + defsubr (&Sxwidget_set_adjustment); + + DEFSYM (Qxwidget, "xwidget"); + + DEFSYM (QCxwidget, ":xwidget"); + DEFSYM (QCtitle, ":title"); + + /* Do not forget to update the docstring of make-xwidget if you add + new types. */ + + DEFSYM (Qvertical, "vertical"); + DEFSYM (Qhorizontal, "horizontal"); + + DEFSYM (QCplist, ":plist"); + + DEFVAR_LISP ("xwidget-list", Vxwidget_list, + doc: /* xwidgets list. */); + Vxwidget_list = Qnil; + + DEFVAR_LISP ("xwidget-view-list", Vxwidget_view_list, + doc: /* xwidget views list. */); + Vxwidget_view_list = Qnil; + + Fprovide (intern ("xwidget-internal"), Qnil); + +} + + +/* Value is non-zero if OBJECT is a valid Lisp xwidget specification. A + valid xwidget specification is a list whose car is the symbol + `xwidget', and whose rest is a property list. The property list must + contain a value for key `:type'. That value must be the name of a + supported xwidget type. The rest of the property list depends on the + xwidget type. */ + +bool +valid_xwidget_spec_p (Lisp_Object object) +{ + int valid_p = false; + + if (CONSP (object) && EQ (XCAR (object), Qxwidget)) + valid_p = true; + + return valid_p; +} + + + +/* Find a value associated with key in spec. */ +Lisp_Object +xwidget_spec_value (Lisp_Object spec, Lisp_Object key, int *found) +{ + Lisp_Object tail; + + eassert (valid_xwidget_spec_p (spec)); + + for (tail = XCDR (spec); + CONSP (tail) && CONSP (XCDR (tail)); tail = XCDR (XCDR (tail))) + { + if (EQ (XCAR (tail), key)) + { + if (found) + *found = 1; + return XCAR (XCDR (tail)); + } + } + + if (found) + *found = 0; + return Qnil; +} + + +void +xwidget_view_delete_all_in_window (struct window *w) +{ + struct xwidget_view *xv = NULL; + for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); + tail = XCDR (tail)) + { + if (XWIDGET_VIEW_P (XCAR (tail))) + { + xv = XXWIDGET_VIEW (XCAR (tail)); + if (XWINDOW (xv->w) == w) + { + Fdelete_xwidget_view (XCAR (tail)); + } + } + } +} + +struct xwidget_view * +xwidget_view_lookup (struct xwidget *xw, struct window *w) +{ + Lisp_Object xwidget, window, ret; + XSETXWIDGET (xwidget, xw); + XSETWINDOW (window, w); + + ret = Fxwidget_view_lookup (xwidget, window); + + return EQ (ret, Qnil) ? NULL : XXWIDGET_VIEW (ret); +} + +struct xwidget * +lookup_xwidget (Lisp_Object spec) +{ + /* When a xwidget lisp spec is found initialize the C struct that is + used in the C code. This is done by redisplay so values change + if the spec changes. So, take special care of one-shot events. + */ + int found = 0; + Lisp_Object value; + struct xwidget *xw; + + value = xwidget_spec_value (spec, QCxwidget, &found); + xw = XXWIDGET (value); + + return xw; +} + +/* Set up detection of touched xwidget*/ +void +xwidget_start_redisplay (void) +{ + for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); + tail = XCDR (tail)) + { + if (XWIDGET_VIEW_P (XCAR (tail))) + XXWIDGET_VIEW (XCAR (tail))->redisplayed = 0; + } +} + +/* The xwidget was touched during redisplay, so it isn't a candidate + for hiding. */ +void +xwidget_touch (struct xwidget_view *xv) +{ + xv->redisplayed = 1; +} + +static int +xwidget_touched (struct xwidget_view *xv) +{ + return xv->redisplayed; +} + +/* Redisplay has ended, now we should hide untouched xwidgets +*/ +void +xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix) +{ + + int i; + int area; + + xwidget_start_redisplay (); + // Iterate desired glyph matrix of window here, hide gtk widgets + // not in the desired matrix. + + // This only takes care of xwidgets in active windows. if a window + // goes away from screen xwidget views wust be deleted + + // dump_glyph_matrix (matrix, 2); + for (i = 0; i < matrix->nrows; ++i) + { + // dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs); + struct glyph_row *row; + row = MATRIX_ROW (matrix, i); + if (row->enabled_p != 0) + { + for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area) + { + struct glyph *glyph = row->glyphs[area]; + struct glyph *glyph_end = glyph + row->used[area]; + for (; glyph < glyph_end; ++glyph) + { + if (glyph->type == XWIDGET_GLYPH) + { + /* + The only call to xwidget_end_redisplay is in dispnew + xwidget_end_redisplay (w->current_matrix); + */ + xwidget_touch (xwidget_view_lookup (glyph->u.xwidget, + w)); + } + } + } + } + } + + for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); + tail = XCDR (tail)) + { + if (XWIDGET_VIEW_P (XCAR (tail))) + { + struct xwidget_view *xv = XXWIDGET_VIEW (XCAR (tail)); + + // "touched" is only meaningful for the current window, so + // disregard other views. + if (XWINDOW (xv->w) == w) + { + if (xwidget_touched (xv)) + xwidget_show_view (xv); + else + xwidget_hide_view (xv); + } + } + } +} + +/* Kill all xwidget in BUFFER. */ +void +kill_buffer_xwidgets (Lisp_Object buffer) +{ + Lisp_Object tail, xwidget; + for (tail = Fget_buffer_xwidgets (buffer); CONSP (tail); tail = XCDR (tail)) + { + xwidget = XCAR (tail); + Vxwidget_list = Fdelq (xwidget, Vxwidget_list); + /* TODO free the GTK things in xw */ + { + CHECK_XWIDGET (xwidget); + struct xwidget *xw = XXWIDGET (xwidget); + if (xw->widget_osr && xw->widgetwindow_osr) + { + gtk_widget_destroy (xw->widget_osr); + gtk_widget_destroy (xw->widgetwindow_osr); + } + } + } +} 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 @@ +/* Support for embedding graphical components in a buffer. + +Copyright (C) 2011-2015 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Emacs. If not, see . */ + +#ifndef XWIDGET_H_INCLUDED +#define XWIDGET_H_INCLUDED + +void x_draw_xwidget_glyph_string (struct glyph_string *s); +void syms_of_xwidget (void); + +//extern Lisp_Object Qxwidget; + + +bool valid_xwidget_spec_p (Lisp_Object object); + +#include + + +/* +each xwidget instance/model is described by this struct. + +lisp pseudovector. + + + */ +struct xwidget +{ + struct vectorlike_header header; + Lisp_Object plist; //auxilliary data + Lisp_Object type; //the widget type + Lisp_Object buffer; //buffer where xwidget lives + Lisp_Object title; //a title that is used for button labels for instance + + //here ends the lisp part. + //"height" is the marker field + int height; + int width; + + //for offscreen widgets, unused if not osr + GtkWidget *widget_osr; + GtkWidget *widgetwindow_osr; + //this is used if the widget (webkit) is to be wrapped in a scrolled window, + GtkWidget *widgetscrolledwindow_osr; + /* Non-nil means kill silently if Emacs is exited. */ + unsigned int kill_without_query:1; + +}; + + +//struct for each xwidget view +struct xwidget_view +{ + struct vectorlike_header header; + Lisp_Object model; + Lisp_Object w; + + //here ends the lisp part. + //"redisplayed" is the marker field + int redisplayed; //if touched by redisplay + + int hidden; //if the "live" instance isnt drawn + + GtkWidget *widget; + GtkWidget *widgetwindow; + GtkWidget *emacswindow; + int x; + int y; + int clip_right; + int clip_bottom; + int clip_top; + int clip_left; + + + long handler_id; +}; + +/* Test for xwidget pseudovector*/ +#define XWIDGETP(x) PSEUDOVECTORP (x, PVEC_XWIDGET) +#define XXWIDGET(a) (eassert (XWIDGETP(a)), \ + (struct xwidget *) XUNTAG(a, Lisp_Vectorlike)) + +#define CHECK_XWIDGET(x) \ + CHECK_TYPE (XWIDGETP (x), Qxwidgetp, x) + +/* Test for xwidget_view pseudovector */ +#define XWIDGET_VIEW_P(x) PSEUDOVECTORP (x, PVEC_XWIDGET_VIEW) +#define XXWIDGET_VIEW(a) (eassert (XWIDGET_VIEW_P(a)), \ + (struct xwidget_view *) XUNTAG(a, Lisp_Vectorlike)) + +#define CHECK_XWIDGET_VIEW(x) \ + CHECK_TYPE (XWIDGET_VIEW_P (x), Qxwidget_view_p, x) + +struct xwidget_type +{ + /* A symbol uniquely identifying the xwidget type, */ + Lisp_Object *type; + + /* Check that SPEC is a valid image specification for the given + image type. Value is non-zero if SPEC is valid. */ + int (*valid_p) (Lisp_Object spec); + + /* Next in list of all supported image types. */ + struct xwidget_type *next; +}; + + +struct xwidget *xwidget_from_id (int id); + +void xwidget_start_redisplay (void); +void xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix); + +void xwidget_touch (struct xwidget_view *xw); + +struct xwidget *lookup_xwidget (Lisp_Object spec); +#define XG_XWIDGET "emacs_xwidget" +#define XG_XWIDGET_VIEW "emacs_xwidget_view" +void xwidget_view_delete_all_in_window (struct window *w); + +void kill_buffer_xwidgets (Lisp_Object buffer); +#endif /* XWIDGET_H_INCLUDED */ -- cgit v1.2.1 From c7441cd7d8befe1f79ed3509c4a2202a01314336 Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Tue, 19 Jan 2016 16:00:34 -0500 Subject: ; Add 2016 to copyright years of new files. --- src/xwidget.c | 2 +- src/xwidget.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/xwidget.c b/src/xwidget.c index 74319e1667d..1ed7eaae2a7 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -1,6 +1,6 @@ /* Support for embedding graphical components in a buffer. -Copyright (C) 2011-2015 Free Software Foundation, Inc. +Copyright (C) 2011-2016 Free Software Foundation, Inc. This file is part of GNU Emacs. diff --git a/src/xwidget.h b/src/xwidget.h index 493000c34fd..4dffaa4750d 100644 --- a/src/xwidget.h +++ b/src/xwidget.h @@ -1,6 +1,6 @@ /* Support for embedding graphical components in a buffer. -Copyright (C) 2011-2015 Free Software Foundation, Inc. +Copyright (C) 2011-2016 Free Software Foundation, Inc. This file is part of GNU Emacs. -- cgit v1.2.1 From ea415382786305179ec9bd2ca88d7caccd09f63a Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Tue, 19 Jan 2016 18:42:47 -0500 Subject: Trivial doc copyedits. * src/xwidget.c (Fmake_xwidget, Fget_buffer_xwidgets) (Fxwidget_webkit_get_title, Fxwidget_resize) (Fxwidget_set_adjustment, Fxwidgetp, Fxwidget_view_p) (Fxwidget_info, Fxwidget_view_lookup) (Fset_xwidget_query_on_exit_flag): Trivial doc copyedits. --- src/xwidget.c | 98 +++++++++++++++++++++++++++-------------------------------- 1 file changed, 45 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/xwidget.c b/src/xwidget.c index 1ed7eaae2a7..88cdb941c4c 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -160,18 +160,13 @@ DEFUN ("make-xwidget", Fmake_xwidget, Smake_xwidget, 7, 8, 0, doc: /* Make an xwidget from BEG to END of TYPE. - -If BUFFER is nil it uses the current -buffer. If BUFFER is a string and no such -buffer exists, it is created. - -TYPE is a symbol which can take one of the -following values: +If BUFFER is nil, use the current buffer. +If BUFFER is a string and no such buffer exists, create it. +TYPE is a symbol which can take one of the following values: - webkit_osr -Returns the newly constructed xwidget, or nil if construction -fails. */) +Returns the newly constructed xwidget, or nil if construction fails. */) (Lisp_Object beg, Lisp_Object end, Lisp_Object type, Lisp_Object title, @@ -255,7 +250,7 @@ fails. */) gtk_widget_show (xw->widgetscrolledwindow_osr); /* store some xwidget data in the gtk widgets for convenient - retrieval in the event handlers. */ + retrieval in the event handlers. */ g_object_set_data (G_OBJECT (xw->widget_osr), XG_XWIDGET, (gpointer) (xw)); g_object_set_data (G_OBJECT (xw->widgetwindow_osr), XG_XWIDGET, @@ -302,7 +297,7 @@ fails. */) DEFUN ("get-buffer-xwidgets", Fget_buffer_xwidgets, Sget_buffer_xwidgets, 1, 1, 0, doc: /* Return a list of xwidgets associated with BUFFER. -BUFFER may be a buffer or the name of one. */) +BUFFER may be a buffer or the name of one. */) (Lisp_Object buffer) { Lisp_Object xw, tail, xw_list; @@ -429,7 +424,7 @@ webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *webView, gpointer user_data) { // This function makes webkit send a download signal for all unknown - // mime types. TODO Defer the decision to lisp, so that its possible + // mime types. TODO Defer the decision to lisp, so that its possible // to make Emacs handle teext mime for instance.xs if (!webkit_web_view_can_show_mime_type (webView, mimetype)) { @@ -502,13 +497,13 @@ xwidget_osr_event_forward (GtkWidget * widget, GdkEvent * event, gpointer user_data) { - /* Copy events that arrive at the outer widget to the offscreen widget. */ + /* Copy events that arrive at the outer widget to the offscreen widget. */ struct xwidget *xw = (struct xwidget *) g_object_get_data (G_OBJECT (widget), XG_XWIDGET); GdkEvent *eventcopy = gdk_event_copy (event); eventcopy->any.window = gtk_widget_get_window (xw->widget_osr); - //TODO This might leak events. They should be deallocated later, + //TODO This might leak events. They should be deallocated later, //perhaps in xwgir_event_cb gtk_main_do_event (eventcopy); return TRUE; //dont propagate this event furter @@ -528,7 +523,7 @@ xwidget_osr_event_set_embedder (GtkWidget * widget, } -/* Initializes and does initial placement of an xwidget view on screen. */ +/* Initializes and does initial placement of an xwidget view on screen. */ static struct xwidget_view * xwidget_init_view (struct xwidget *xww, struct glyph_string *s, @@ -653,9 +648,9 @@ x_draw_xwidget_glyph_string (struct glyph_string *s) WINDOW_BOTTOM_EDGE_Y (s->w) - WINDOW_MODE_LINE_HEIGHT (s->w) - y); clip_top = max (0, WINDOW_TOP_EDGE_Y (s->w) - y); - // We are conserned with movement of the onscreen area. The area + // We are conserned with movement of the onscreen area. The area // might sit still when the widget actually moves. This happens - // when an Emacs window border moves across a widget window. So, if + // when an Emacs window border moves across a widget window. So, if // any corner of the outer widget clipping window moves, that counts // as movement here, even if it looks like no movement happens // because the widget sits still inside the clipping area. The @@ -671,8 +666,8 @@ x_draw_xwidget_glyph_string (struct glyph_string *s) xv->widgetwindow, x + clip_left, y + clip_top); } // Clip the widget window if some parts happen to be outside - // drawable area. An Emacs window is not a gtk window. A gtk window - // covers the entire frame. Clipping might have changed even if we + // drawable area. An Emacs window is not a gtk window. A gtk window + // covers the entire frame. Clipping might have changed even if we // havent actualy moved, we try figure out when we need to reclip // for real. if ((xv->clip_right != clip_right) @@ -690,9 +685,9 @@ x_draw_xwidget_glyph_string (struct glyph_string *s) xv->clip_left = clip_left; } // If emacs wants to repaint the area where the widget lives, queue - // a redraw. It seems its possible to get out of sync with emacs + // a redraw. It seems its possible to get out of sync with emacs // redraws so emacs background sometimes shows up instead of the - // xwidgets background. It's just a visual glitch though. + // xwidgets background. It's just a visual glitch though. if (!xwidget_hidden (xv)) { gtk_widget_queue_draw (xv->widgetwindow); @@ -717,8 +712,7 @@ x_draw_xwidget_glyph_string (struct glyph_string *s) DEFUN ("xwidget-webkit-goto-uri", Fxwidget_webkit_goto_uri, Sxwidget_webkit_goto_uri, 2, 2, 0, - doc: /* Make the xwidget webkit instance referenced by XWIDGET -browse URI. */) + doc: /* Make the xwidget webkit instance referenced by XWIDGET browse URI. */) (Lisp_Object xwidget, Lisp_Object uri) { WEBKIT_FN_INIT (); @@ -744,7 +738,7 @@ DEFUN ("xwidget-webkit-execute-script", DEFUN ("xwidget-webkit-get-title", Fxwidget_webkit_get_title, Sxwidget_webkit_get_title, 1, 1, 0, - doc: /* Returns the title from the Webkit instance in XWIDGET. + doc: /* Return the title from the Webkit instance in XWIDGET. This can be used to work around the lack of a return value from the exec method. */ ) (Lisp_Object xwidget) @@ -755,7 +749,7 @@ exec method. */ ) webkit_web_view_get_title (WEBKIT_WEB_VIEW (xw->widget_osr)); if (str == 0) { - // TODO maybe return Qnil instead. I suppose webkit returns + // TODO maybe return Qnil instead. I suppose webkit returns // nullpointer when doc is not properly loaded or something return build_string (""); } @@ -763,8 +757,7 @@ exec method. */ ) } DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 3, 3, 0, - doc: /* Resize XWIDGET. NEW_WIDTH NEW_HEIGHT defines the new -size. */ ) + doc: /* Resize XWIDGET. NEW_WIDTH, NEW_HEIGHT define the new size. */ ) (Lisp_Object xwidget, Lisp_Object new_width, Lisp_Object new_height) { CHECK_XWIDGET (xwidget); @@ -817,8 +810,9 @@ size. */ ) DEFUN ("xwidget-set-adjustment", Fxwidget_set_adjustment, Sxwidget_set_adjustment, 4, 4, 0, - doc: /* Set native scrolling for XWIDGET. AXIS can be 'vertical or -'horizontal. If RELATIVE is t, scroll relative, otherwise absolutely. + doc: /* Set native scrolling for XWIDGET. +AXIS can be 'vertical or 'horizontal. +If RELATIVE is t, scroll relative, otherwise absolutely. VALUE is the amount to scroll, either relatively or absolutely. */) (Lisp_Object xwidget, Lisp_Object axis, Lisp_Object relative, Lisp_Object value) @@ -863,7 +857,6 @@ DEFUN ("xwidget-size-request", Fxwidget_size_request, Sxwidget_size_request, 1, 1, 0, doc: /* Return the desired size of the XWIDGET. - This can be used to read the xwidget desired size, and resizes the Emacs allocated area accordingly. */) (Lisp_Object xwidget) @@ -882,7 +875,7 @@ Emacs allocated area accordingly. */) DEFUN ("xwidgetp", Fxwidgetp, Sxwidgetp, 1, 1, 0, - doc: /* Return t if OBJECT is a xwidget. */) + doc: /* Return t if OBJECT is an xwidget. */) (Lisp_Object object) { return XWIDGETP (object) ? Qt : Qnil; @@ -891,7 +884,7 @@ DEFUN ("xwidgetp", DEFUN ("xwidget-view-p", Fxwidget_view_p, Sxwidget_view_p, 1, 1, 0, - doc: /* Return t if OBJECT is a xwidget-view. */) + doc: /* Return t if OBJECT is an xwidget-view. */) (Lisp_Object object) { return XWIDGET_VIEW_P (object) ? Qt : Qnil; @@ -900,8 +893,8 @@ DEFUN ("xwidget-view-p", DEFUN ("xwidget-info", Fxwidget_info, Sxwidget_info, 1, 1, 0, - doc: /* Return XWIDGET properties in a vector. Currently [TYPE -TITLE WIDTH HEIGHT]. */) + doc: /* Return XWIDGET properties in a vector. +Currently [TYPE TITLE WIDTH HEIGHT]. */) (Lisp_Object xwidget) { CHECK_XWIDGET (xwidget); @@ -923,7 +916,7 @@ DEFUN ("xwidget-view-info", Fxwidget_view_info, Sxwidget_view_info, 1, 1, 0, doc: /* Return properties of XWIDGET-VIEW in a vector. -Currently [X Y CLIP_RIGHT CLIP_BOTTOM CLIP_TOP CLIP_LEFT] */) +Currently [X Y CLIP_RIGHT CLIP_BOTTOM CLIP_TOP CLIP_LEFT]. */) (Lisp_Object xwidget_view) { CHECK_XWIDGET_VIEW (xwidget_view); @@ -944,7 +937,7 @@ Currently [X Y CLIP_RIGHT CLIP_BOTTOM CLIP_TOP CLIP_LEFT] */) DEFUN ("xwidget-view-model", Fxwidget_view_model, Sxwidget_view_model, 1, 1, 0, - doc: /* Return the model associated with XWIDGET-VIEW. */) + doc: /* Return the model associated with XWIDGET-VIEW. */) (Lisp_Object xwidget_view) { CHECK_XWIDGET_VIEW (xwidget_view); @@ -954,7 +947,7 @@ DEFUN ("xwidget-view-model", DEFUN ("xwidget-view-window", Fxwidget_view_window, Sxwidget_view_window, 1, 1, 0, - doc: /* Return the window of XWIDGET-VIEW. */) + doc: /* Return the window of XWIDGET-VIEW. */) (Lisp_Object xwidget_view) { CHECK_XWIDGET_VIEW (xwidget_view); @@ -965,15 +958,15 @@ DEFUN ("xwidget-view-window", DEFUN ("delete-xwidget-view", Fdelete_xwidget_view, Sdelete_xwidget_view, 1, 1, 0, - doc: /* Delete the XWIDGET-VIEW. */) + doc: /* Delete the XWIDGET-VIEW. */) (Lisp_Object xwidget_view) { CHECK_XWIDGET_VIEW (xwidget_view); struct xwidget_view *xv = XXWIDGET_VIEW (xwidget_view); gtk_widget_destroy (xv->widgetwindow); Vxwidget_view_list = Fdelq (xwidget_view, Vxwidget_view_list); - // xv->model still has signals pointing to the view. There can be - // several views. Find the matching signals and delete them all. + // xv->model still has signals pointing to the view. There can be + // several views. Find the matching signals and delete them all. g_signal_handlers_disconnect_matched (XXWIDGET (xv->model)->widgetwindow_osr, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, @@ -984,9 +977,9 @@ DEFUN ("delete-xwidget-view", DEFUN ("xwidget-view-lookup", Fxwidget_view_lookup, Sxwidget_view_lookup, 1, 2, 0, - doc: /* Return the xwidget-view associated with XWIDGET in -WINDOW if specified, otherwise it uses the selected window. Return nil -if no association is found. */) + doc: /* Return the xwidget-view associated with XWIDGET in WINDOW. +If WINDOW is unspecified or nil, use the selected window. +Return nil if no association is found. */) (Lisp_Object xwidget, Lisp_Object window) { CHECK_XWIDGET (xwidget); @@ -1044,10 +1037,10 @@ Returns PLIST. */) DEFUN ("set-xwidget-query-on-exit-flag", Fset_xwidget_query_on_exit_flag, Sset_xwidget_query_on_exit_flag, 2, 2, 0, - doc: /* Specify if query is needed for XWIDGET when -Emacs is exited. If the second argument FLAG is non-nil, Emacs will -queries the user before exiting or killing a buffer if XWIDGET is -running. This function returns FLAG. */) + doc: /* Specify if query is needed for XWIDGET when Emacs is exited. +If the second argument FLAG is non-nil, Emacs will query the user before +exiting or killing a buffer if XWIDGET is running. +This function returns FLAG. */) (Lisp_Object xwidget, Lisp_Object flag) { CHECK_XWIDGET (xwidget); @@ -1058,8 +1051,7 @@ running. This function returns FLAG. */) DEFUN ("xwidget-query-on-exit-flag", Fxwidget_query_on_exit_flag, Sxwidget_query_on_exit_flag, 1, 1, 0, - doc: /* Return the current value of query-on-exit -flag for XWIDGET. */) + doc: /* Return the current value of the query-on-exit flag for XWIDGET. */) (Lisp_Object xwidget) { CHECK_XWIDGET (xwidget); @@ -1107,7 +1099,7 @@ syms_of_xwidget (void) DEFSYM (QCtitle, ":title"); /* Do not forget to update the docstring of make-xwidget if you add - new types. */ + new types. */ DEFSYM (Qvertical, "vertical"); DEFSYM (Qhorizontal, "horizontal"); @@ -1219,7 +1211,7 @@ lookup_xwidget (Lisp_Object spec) return xw; } -/* Set up detection of touched xwidget*/ +/* Set up detection of touched xwidget */ void xwidget_start_redisplay (void) { @@ -1258,7 +1250,7 @@ xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix) // Iterate desired glyph matrix of window here, hide gtk widgets // not in the desired matrix. - // This only takes care of xwidgets in active windows. if a window + // This only takes care of xwidgets in active windows. If a window // goes away from screen xwidget views wust be deleted // dump_glyph_matrix (matrix, 2); @@ -1309,7 +1301,7 @@ xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix) } } -/* Kill all xwidget in BUFFER. */ +/* Kill all xwidget in BUFFER. */ void kill_buffer_xwidgets (Lisp_Object buffer) { -- cgit v1.2.1 From 2388fa74982a9146e4bcefc75004ec9d7241c505 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 20 Jan 2016 11:06:01 -0800 Subject: Port to platforms with gtk3 but not webkitgtk3 I ran into this problem on my Fedora 23 installation; Emacs configured but did not build when --with-xwidgets was specified. * configure.ac (HAVE_WEBKIT, HAVE_GIR): Omit unnecessary initializations. (DOES_XWIDGETS_USE_GIR): New var. If --with-xwidgets is specified, report an error if not doable, to be consistent with the other --with options. Require webkitgtk3 to use Xwidgets, as the Xwidgets code does not work at all without webkitgtk3. Simplify use of EMACS_CHECK_MODULES. Output message about gobject introspection only if xwidgets are used. * etc/NEWS: Users need webkitgtk3, not merely webkit. * src/xwidget.c (syms_of_xwidget): Don’t worry about HAVE_WEBKIT_OSR, since this file is no longer compiled if webkitgtk3 is not available. --- src/xwidget.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/xwidget.c b/src/xwidget.c index 88cdb941c4c..f8e13cd4522 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -1077,12 +1077,10 @@ syms_of_xwidget (void) defsubr (&Sxwidget_query_on_exit_flag); defsubr (&Sset_xwidget_query_on_exit_flag); -#ifdef HAVE_WEBKIT_OSR defsubr (&Sxwidget_webkit_goto_uri); defsubr (&Sxwidget_webkit_execute_script); defsubr (&Sxwidget_webkit_get_title); DEFSYM (Qwebkit_osr, "webkit-osr"); -#endif defsubr (&Sxwidget_size_request); defsubr (&Sdelete_xwidget_view); -- cgit v1.2.1 From 9d7265ba1a3f93e107a88c3fc4b76557e36192b5 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 20 Jan 2016 14:55:09 -0800 Subject: Don’t export C symbols not used elsewhere These were recently added, mostly as part of xwidget code. * src/emacsgtkfixed.c (emacs_fixed_get_type): Now static. (EMACS_FIXED, EMACS_FIXED_GET_CLASS): Now static functions here, not macros in emacsgtkfixed.h. * src/emacsgtkfixed.h (EMACS_TYPE_FIXED): Remove. All uses replaced by definiens. (EMACS_FIXED, EMACS_FIXED_GET_CLASS): Remove; these are now static functions in emacsgtkfixed.c. (EMACS_FIXED_CLASS, EMACS_IS_FIXED, EMACS_IS_FIXED_CLASS): Remove; unused. (emacs_fixed_get_type): Remove decl; no longer extern. * src/xwidget.c (offscreen_damage_event) (webkit_mime_type_policy_typedecision_requested_cb) (webkit_new_window_policy_decision_requested_cb) (webkit_navigation_policy_decision_requested_cb) (xwidget_spec_value, xwidget_view_lookup) (xwidget_start_redisplay, xwidget_touch): Now static. * src/xwidget.h (xwidget_start_redisplay, xwidget_touch): Remove decls. --- src/emacsgtkfixed.c | 20 ++++++++++++++++++-- src/emacsgtkfixed.h | 8 -------- src/xwidget.c | 36 +++++++++++++++++------------------- src/xwidget.h | 3 --- 4 files changed, 35 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c index da1017df2ae..08b840389c5 100644 --- a/src/emacsgtkfixed.c +++ b/src/emacsgtkfixed.c @@ -50,10 +50,26 @@ static void emacs_fixed_get_preferred_width (GtkWidget *widget, static void emacs_fixed_get_preferred_height (GtkWidget *widget, gint *minimum, gint *natural); + +static GType emacs_fixed_get_type (void); G_DEFINE_TYPE (EmacsFixed, emacs_fixed, GTK_TYPE_FIXED) +static EmacsFixed * +EMACS_FIXED (GtkWidget *widget) +{ + return G_TYPE_CHECK_INSTANCE_CAST (widget, emacs_fixed_get_type (), + EmacsFixed); +} + #ifdef HAVE_XWIDGETS +static EmacsFixedClass * +EMACS_FIXED_GET_CLASS (GtkWidget *widget) +{ + return G_TYPE_INSTANCE_GET_CLASS (widget, emacs_fixed_get_type (), + EmacsFixedClass); +} + struct GtkFixedPrivateL { GList *children; @@ -151,7 +167,7 @@ emacs_fixed_class_init (EmacsFixedClass *klass) static void emacs_fixed_init (EmacsFixed *fixed) { - fixed->priv = G_TYPE_INSTANCE_GET_PRIVATE (fixed, EMACS_TYPE_FIXED, + fixed->priv = G_TYPE_INSTANCE_GET_PRIVATE (fixed, emacs_fixed_get_type (), EmacsFixedPrivate); fixed->priv->f = 0; } @@ -166,7 +182,7 @@ emacs_fixed_init (EmacsFixed *fixed) GtkWidget* emacs_fixed_new (struct frame *f) { - EmacsFixed *fixed = g_object_new (EMACS_TYPE_FIXED, NULL); + EmacsFixed *fixed = g_object_new (emacs_fixed_get_type (), NULL); EmacsFixedPrivate *priv = fixed->priv; priv->f = f; return GTK_WIDGET (fixed); diff --git a/src/emacsgtkfixed.h b/src/emacsgtkfixed.h index 5b2fa566785..378bd2b828c 100644 --- a/src/emacsgtkfixed.h +++ b/src/emacsgtkfixed.h @@ -29,13 +29,6 @@ G_BEGIN_DECLS struct frame; -#define EMACS_TYPE_FIXED (emacs_fixed_get_type ()) -#define EMACS_FIXED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMACS_TYPE_FIXED, EmacsFixed)) -#define EMACS_FIXED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EMACS_TYPE_FIXED, EmacsFixedClass)) -#define EMACS_IS_FIXED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMACS_TYPE_FIXED)) -#define EMACS_IS_FIXED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EMACS_TYPE_FIXED)) -#define EMACS_FIXED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EMACS_TYPE_FIXED, EmacsFixedClass)) - //typedef struct _EmacsFixed EmacsFixed; typedef struct _EmacsFixedPrivate EmacsFixedPrivate; typedef struct _EmacsFixedClass EmacsFixedClass; @@ -55,7 +48,6 @@ struct _EmacsFixedClass }; extern GtkWidget *emacs_fixed_new (struct frame *f); -extern GType emacs_fixed_get_type (void); G_END_DECLS diff --git a/src/xwidget.c b/src/xwidget.c index f8e13cd4522..ea5dea0f9fe 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -123,14 +123,13 @@ allocate_xwidget_view (void) #define XSETXWIDGET(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET)) #define XSETXWIDGET_VIEW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET_VIEW)) -struct xwidget_view *xwidget_view_lookup (struct xwidget *, struct window *); -Lisp_Object xwidget_spec_value (Lisp_Object , Lisp_Object , int *); -gboolean offscreen_damage_event (GtkWidget * , GdkEvent * , gpointer ); -void webkit_document_load_finished_cb (WebKitWebView *, WebKitWebFrame *, - gpointer ); -gboolean webkit_download_cb (WebKitWebView *, WebKitDownload *, gpointer); +static struct xwidget_view *xwidget_view_lookup (struct xwidget *, + struct window *); +static void webkit_document_load_finished_cb (WebKitWebView *, WebKitWebFrame *, + gpointer); +static gboolean webkit_download_cb (WebKitWebView *, WebKitDownload *, gpointer); -gboolean +static gboolean webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *, WebKitWebFrame *, WebKitNetworkRequest *, @@ -138,7 +137,7 @@ webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *, WebKitWebPolicyDecision *, gpointer); -gboolean +static gboolean webkit_new_window_policy_decision_requested_cb (WebKitWebView *, WebKitWebFrame *, WebKitNetworkRequest *, @@ -146,7 +145,7 @@ webkit_new_window_policy_decision_requested_cb (WebKitWebView *, WebKitWebPolicyDecision *, gpointer); -gboolean +static gboolean webkit_navigation_policy_decision_requested_cb (WebKitWebView *, WebKitWebFrame *, WebKitNetworkRequest *, @@ -261,8 +260,7 @@ Returns the newly constructed xwidget, or nil if construction fails. */) { g_signal_connect (G_OBJECT (xw->widget_osr), "document-load-finished", - G_CALLBACK - (webkit_document_load_finished_cb), xw); + G_CALLBACK (webkit_document_load_finished_cb), xw); g_signal_connect (G_OBJECT (xw->widget_osr), "download-requested", @@ -352,7 +350,7 @@ xwidget_hide_view (struct xwidget_view *xv) /* When the off-screen webkit master view changes this signal is called. It copies the bitmap from the off-screen instance. */ -gboolean +static gboolean offscreen_damage_event (GtkWidget * widget, GdkEvent * event, gpointer xv_widget) { @@ -415,7 +413,7 @@ webkit_download_cb (WebKitWebView * webkitwebview, return FALSE; } -gboolean +static gboolean webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *webView, WebKitWebFrame *frame, WebKitNetworkRequest * request, @@ -438,7 +436,7 @@ webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *webView, } -gboolean +static gboolean webkit_new_window_policy_decision_requested_cb (WebKitWebView *webView, WebKitWebFrame *frame, WebKitNetworkRequest *request, @@ -456,7 +454,7 @@ webkit_new_window_policy_decision_requested_cb (WebKitWebView *webView, return FALSE; } -gboolean +static gboolean webkit_navigation_policy_decision_requested_cb (WebKitWebView *webView, WebKitWebFrame *frame, WebKitNetworkRequest *request, @@ -1138,7 +1136,7 @@ valid_xwidget_spec_p (Lisp_Object object) /* Find a value associated with key in spec. */ -Lisp_Object +static Lisp_Object xwidget_spec_value (Lisp_Object spec, Lisp_Object key, int *found) { Lisp_Object tail; @@ -1180,7 +1178,7 @@ xwidget_view_delete_all_in_window (struct window *w) } } -struct xwidget_view * +static struct xwidget_view * xwidget_view_lookup (struct xwidget *xw, struct window *w) { Lisp_Object xwidget, window, ret; @@ -1210,7 +1208,7 @@ lookup_xwidget (Lisp_Object spec) } /* Set up detection of touched xwidget */ -void +static void xwidget_start_redisplay (void) { for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); @@ -1223,7 +1221,7 @@ xwidget_start_redisplay (void) /* The xwidget was touched during redisplay, so it isn't a candidate for hiding. */ -void +static void xwidget_touch (struct xwidget_view *xv) { xv->redisplayed = 1; diff --git a/src/xwidget.h b/src/xwidget.h index 4dffaa4750d..fdcf40d8cbb 100644 --- a/src/xwidget.h +++ b/src/xwidget.h @@ -121,11 +121,8 @@ struct xwidget_type struct xwidget *xwidget_from_id (int id); -void xwidget_start_redisplay (void); void xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix); -void xwidget_touch (struct xwidget_view *xw); - struct xwidget *lookup_xwidget (Lisp_Object spec); #define XG_XWIDGET "emacs_xwidget" #define XG_XWIDGET_VIEW "emacs_xwidget_view" -- cgit v1.2.1 From 871c8b1b96c1cffb84d30dddd484663a0c94818f Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 20 Jan 2016 15:28:30 -0800 Subject: No need to configure gobject-introspection It wasn’t needed for the recently-installed xwidget_mvp code; see: http://lists.gnu.org/archive/html/emacs-devel/2016-01/msg01154.html * configure.ac (DOES_XWIDGETS_USE_GIR, GIR_REQUIRED, GIR_MODULES): (HAVE_GIR): * src/Makefile.in (GIR_LIBS, GIR_CFLAGS): Remove. All uses removed. * configure.ac (emacs_config_features): Don’t worry about GIR. --- src/Makefile.in | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/Makefile.in b/src/Makefile.in index 2b5ae30a704..4a52757fec6 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -225,8 +225,6 @@ RSVG_CFLAGS= @RSVG_CFLAGS@ WEBKIT_LIBS= @WEBKIT_LIBS@ WEBKIT_CFLAGS= @WEBKIT_CFLAGS@ -GIR_LIBS= @GIR_LIBS@ -GIR_CFLAGS= @GIR_CFLAGS@ CAIRO_LIBS= @CAIRO_LIBS@ CAIRO_CFLAGS= @CAIRO_CFLAGS@ @@ -366,7 +364,7 @@ ALL_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \ $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \ $(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \ $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \ - $(WEBKIT_CFLAGS) $(GIR_CFLAGS) \ + $(WEBKIT_CFLAGS) \ $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \ $(LIBGNUTLS_CFLAGS) $(GFILENOTIFY_CFLAGS) $(CAIRO_CFLAGS) \ @@ -477,7 +475,7 @@ lisp = $(addprefix ${lispsource}/,${shortlisp}) LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ $(LIBX_OTHER) $(LIBSOUND) \ $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \ - $(WEBKIT_LIBS) $(GIR_LIBS) \ + $(WEBKIT_LIBS) \ $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \ $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \ $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) $(CAIRO_LIBS) \ -- cgit v1.2.1