emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 82b0897 01/13: -


From: Paul Eggert
Subject: [Emacs-diffs] master 82b0897 01/13: -
Date: Sat, 30 Jan 2016 22:12:14 +0000

branch: master
commit 82b089783e71b2aeef950eaecfe4cbc0735e64a2
Merge: d27c807 f7dc6d8
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    -
---
 configure.ac                    |   32 +-
 doc/emacs/anti.texi             |  249 ++++++---
 doc/emacs/emacs.texi            |    2 +-
 doc/emacs/maintaining.texi      |   33 +-
 doc/lispref/variables.texi      |    4 +-
 etc/NEWS                        |   15 +
 lisp/calendar/todo-mode.el      |   10 +-
 lisp/doc-view.el                |    7 +-
 lisp/emacs-lisp/pcase.el        |   47 +-
 lisp/gnus/nnir.el               |    6 +-
 lisp/htmlfontify.el             |   14 +-
 lisp/image-mode.el              |   43 +-
 lisp/international/mule-cmds.el |    2 +-
 lisp/international/quail.el     |    2 +-
 lisp/isearch.el                 |   13 +-
 lisp/net/shr.el                 |    2 +-
 lisp/progmodes/ruby-mode.el     |    2 +-
 lisp/progmodes/xref.el          |    8 +-
 lisp/xwidget.el                 |  580 +++++++++++++++++
 src/Makefile.in                 |    9 +
 src/buffer.c                    |    6 +
 src/dispextern.h                |   28 +
 src/dispnew.c                   |   12 +
 src/emacs.c                     |    6 +
 src/emacsgtkfixed.c             |  123 +++-
 src/emacsgtkfixed.h             |   20 +
 src/keyboard.c                  |   18 +
 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                   | 1320 +++++++++++++++++++++++++++++++++++++++
 src/xwidget.h                   |  132 ++++
 test/manual/indent/ruby.rb      |    4 +
 36 files changed, 2873 insertions(+), 171 deletions(-)

diff --git a/configure.ac b/configure.ac
index d3b5183..50bc04b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -374,6 +374,9 @@ otherwise for the first of 'inotify', 'kqueue' or 'gfile' 
that is usable.])
  ],
  [with_file_notification=$with_features])
 
+OPTION_DEFAULT_OFF([xwidgets],
+  [enable use of some gtk widgets in Emacs buffers (requires gtk3)])
+
 ## For the times when you want to build Emacs but don't have
 ## a suitable makeinfo, and can live without the manuals.
 dnl http://lists.gnu.org/archive/html/emacs-devel/2008-04/msg01844.html
@@ -2563,6 +2566,26 @@ if test "${HAVE_GTK}" = "yes"; then
  term_header=gtkutil.h
 fi
 
+
+dnl Enable xwidgets if GTK3 and WebKitGTK+ are available.
+HAVE_XWIDGETS=no
+XWIDGETS_OBJ=
+if test "$with_xwidgets" != "no"; then
+  test "$USE_GTK_TOOLKIT" = "GTK3" && test "$window_system" != "none" ||
+    AC_MSG_ERROR([xwidgets requested but gtk3 not used.])
+
+  WEBKIT_REQUIRED=1.4.0
+  WEBKIT_MODULES="webkitgtk-3.0 >= $WEBKIT_REQUIRED"
+  EMACS_CHECK_MODULES([WEBKIT], [$WEBKIT_MODULES])
+  HAVE_XWIDGETS=$HAVE_WEBKIT
+  test $HAVE_XWIDGETS = yes ||
+    AC_MSG_ERROR([xwidgets requested but WebKitGTK+ not found.])
+
+  XWIDGETS_OBJ=xwidget.o
+  AC_DEFINE([HAVE_XWIDGETS], 1, [Define to 1 if you have xwidgets support.])
+fi
+AC_SUBST(XWIDGETS_OBJ)
+
 CFLAGS=$OLD_CFLAGS
 LIBS=$OLD_LIBS
 
@@ -3123,7 +3146,7 @@ if test "${HAVE_X11}" = "yes"; then
   if test "${with_cairo}" != "no"; then
     CAIRO_REQUIRED=1.12.0
     CAIRO_MODULE="cairo >= $CAIRO_REQUIRED"
-    PKG_CHECK_MODULES(CAIRO, $CAIRO_MODULE, USE_CAIRO=yes, :)
+    EMACS_CHECK_MODULES(CAIRO, $CAIRO_MODULE, USE_CAIRO=yes, :)
     if test $USE_CAIRO = yes; then
       AC_DEFINE(USE_CAIRO, 1, [Define to 1 if using cairo.])
     else
@@ -4948,6 +4971,9 @@ case "$USE_X_TOOLKIT" in
   LUCID) TOOLKIT_LIBW="$LUCID_LIBW" ;;
   none) test "x$HAVE_GTK" = "xyes" && TOOLKIT_LIBW="$GTK_LIBS" ;;
 esac
+if test "$HAVE_XWIDGETS" = "yes"; then
+  TOOLKIT_LIBW="$TOOLKIT_LIBW -lXcomposite"
+fi
 AC_SUBST(TOOLKIT_LIBW)
 
 if test "${opsys}" != "mingw32"; then
@@ -5237,7 +5263,8 @@ optsep=
 emacs_config_features=
 for opt in XAW3D XPM JPEG TIFF GIF PNG RSVG CAIRO IMAGEMAGICK SOUND GPM DBUS \
   GCONF GSETTINGS NOTIFY ACL LIBSELINUX GNUTLS LIBXML2 FREETYPE M17N_FLT \
-  LIBOTF XFT ZLIB TOOLKIT_SCROLL_BARS X_TOOLKIT X11 NS MODULES; do
+  LIBOTF XFT ZLIB TOOLKIT_SCROLL_BARS X_TOOLKIT X11 NS MODULES \
+  XWIDGETS; do
 
     case $opt in
       NOTIFY|ACL) eval val=\${${opt}_SUMMARY} ;;
@@ -5287,6 +5314,7 @@ AS_ECHO(["  Does Emacs use -lXaw3d?                       
          ${HAVE_XAW3D
   Does Emacs directly use zlib?                           ${HAVE_ZLIB}
   Does Emacs have dynamic modules support?                ${HAVE_MODULES}
   Does Emacs use toolkit scroll bars?                     
${USE_TOOLKIT_SCROLL_BARS}
+  Does Emacs support Xwidgets (requires gtk3)?            ${HAVE_XWIDGETS}
 "])
 
 if test -n "${EMACSDATA}"; then
diff --git a/doc/emacs/anti.texi b/doc/emacs/anti.texi
index 26e3d2e..ae13ae0 100644
--- a/doc/emacs/anti.texi
+++ b/doc/emacs/anti.texi
@@ -1,113 +1,218 @@
address@hidden -*- coding: utf-8 -*-
 @c This is part of the Emacs manual.
 @c Copyright (C) 2005-2016 Free Software Foundation, Inc.
 @c See file emacs.texi for copying conditions.
 
 @node Antinews
address@hidden Emacs 23 Antinews
address@hidden Emacs 24 Antinews
 @c Update the emacs.texi Antinews menu entry with the above version number.
 
   For those users who live backwards in time, here is information
-about downgrading to Emacs version 23.4.  We hope you will enjoy the
+about downgrading to Emacs version 24.5.  We hope you will enjoy the
 greater simplicity that results from the absence of many Emacs
 @value{EMACSVER} features.
 
 @itemize @bullet
 @item
-Support for displaying and editing ``bidirectional'' text has been
-removed.  Text is now always displayed on the screen in a single
-consistent direction---left to right---regardless of the underlying
-script.  Similarly, @kbd{C-f} and @kbd{C-b} always move the text
-cursor to the right and left respectively.  Also, @key{RIGHT} and
address@hidden are now equivalent to @kbd{C-f} and @kbd{C-b}, as you might
-expect, rather than moving forward or backward based on the underlying
-``paragraph direction''.
+Support for Cairo drawing has been removed.  On GNU and Unix systems,
+you now have only one drawing engine---the venerable X Window system.
+No need to procrastinate on the dilemma whether you do or don't want
+the new shiny Cairo thing.  Hail, simplicity!
 
-Users of right-to-left languages, like Arabic and Hebrew, may
-adapt by reading and/or editing text in left-to-right order.
address@hidden
+Emacs still works on SGI IRIX systems.  if you live backwards in time,
+this is actually a bonus, as IRIX systems will become more and more
+popular as you move farther back in time.
+
address@hidden
+Support for dynamically loaded modules has been removed.  You get to
+use only the trusted Emacs codebase, with no additions.  Those
+external modules written by some J.R. Hacker cannot be trusted anyway.
+Good riddance!
+
address@hidden
+We have greatly simplified the Emacs features which access the network
+by removing the Network Security Manager.  No more annoying prompts
+about trusting this or that site or page---you asked for it, you get
+it, no questions asked!  You, the user, are now in charge of any
+security issues related to sites whose certificates expired or didn't
+exist in the first place.  Giving the user the utmost freedom was and
+always will be the most important goal of Emacs development.  We keep
+that goal even as we develop Emacs back in time.
+
address@hidden
+We made the output of @kbd{C-h l} much simpler and easier to grasp by
+removing the names of commands run by the recorded keystrokes.  True
+Emacs lovers know their bindings by heart anyway, so why waste
+precious screen estate on that which is well known?
+
address@hidden
+Selection- and clipboard-related commands and variables got their
+historical names back.  It's now the definitive
address@hidden again instead of the vague
address@hidden, and all those @code{gui-select-text},
address@hidden, etc.@: got their @code{x-*} names
+back.  (What's a ``GUI'', anyway?)  The only true window system with
+selections is the X Window system, so we stopped pretending that other
+platforms have anything similar to that.  You now know when you invoke
+a command that accesses X.
+
address@hidden
+Passwords are no longer hidden when typed in @code{-batch} mode.  It
+was a misfeature to have it not shown in the first place: who can type
+without seeing what they type?  We couldn't convince the users of GUI
+sessions to give up hiding the password, so we at least made it
+visible in batch mode, which is something every veteran Emacs user
+uses all the time.  Stay tuned for un-hiding the password in GUI
+sessions as well as we downgrade progressively to previous Emacs
+versions.
 
 @item
-The Emacs Lisp package manager has been removed.  Instead of using a
-user interface (@kbd{M-x list-packages}), additional Lisp packages
-must now be installed by hand, which is the most flexible and
-``Lispy'' method anyway.  Typically, this just involves editing your
-init file to add the package installation directory to the load path
-and defining some autoloads; see each package's commentary section
-and/or README file for details.
+The nuisance with Unicode characters popping up all over the place has
+been amply dealt with.  We've removed @kbd{C-x 8} shorthands for
+characters such as ‘, ’, “, ”, €, ≤, and many others; as a nice
+benefit, this removes many useless entries at the beginning of the
address@hidden b} output.  The @code{electric-quote-mode} has been deleted,
+so there's only the one true quoting method now---using the
address@hidden quote characters.  And if that's not enough, the
+doc strings and other messages show text quoted `like this' and "like
+this" as they were written, instead of arbitrarily replacing them
+with Unicode ``curved quote'' characters.  The
address@hidden variable becomes therefore unneeded and was
+removed.  As result, text produced by Emacs can be sent to those
+venerable teletypes again, yeah!
+
+For the same reasons, the character classes @code{[:alpha:]} and
address@hidden:alnum:]} again match any word-constituent character, and
address@hidden:graph:]} and @code{[:print:]} match every multibyte character.
+Confusing use of Unicode character properties is gone.
 
 @item
-The option @code{delete-active-region} has been deleted.  When the
-region is active, typing @key{DEL} or @key{Delete} no longer deletes
-the text in the region; it deletes a single character instead.
+I-search and query-replace no longer try to confuse you by using the
+``character-folding'' magic.  They will no longer find any characters
+you didn't actually type, like find @kbd{ⓐ} when you actually typed
address@hidden  Users who want to find some fancy character will have to
+type it explicitly.
 
 @item
-We have reworked how Emacs handles the clipboard and the X primary
-selection.  Commands for killing and yanking, like @kbd{C-w} and
address@hidden, use the primary selection and not the clipboard, so you can
-use these commands without interfering with ``cutting'' or ``pasting''
-in other programs.  The @samp{Cut}/@samp{Copy}/@samp{Paste} menu items
-are bound to separate clipboard commands, not to the same commands as
address@hidden/@kbd{M-w}/@kbd{C-y}.
+The @file{desktop.el} package no longer records window and frame
+configuration, and doesn't attempt to restore them.  You now have back
+your freedom of re-arranging your windows and frames anew each time
+you restore a session.  This made the new backward-incompatible format
+of the @file{.emacs.desktop} file unnecessary, so the format was
+reverted back to what it was before Emacs 25.  You can now again use
+the desktop file with all the previous versions of Emacs.
 
-Selecting text by dragging with the mouse now puts the text in the
-kill ring, in addition to the primary selection.  But note that
-selecting an active region with @address@hidden does @emph{not}
-alter the kill ring nor the primary selection, even though the text
-highlighting is visually identical.
address@hidden
+We have reworked the Prettify Symbols mode to support only the default
address@hidden  No need to consider
+whether your major or minor mode needs its own prettifications; just
+use what came with Emacs.  We also removed the
address@hidden option: once prettified,
+always prettified!  These changes make the Prettify Symbols mode quite
+a lot simpler and easier to use.
+
address@hidden
+Support for nifty new features of xterm, such as access to the X
+selection and the clipboard, the ``bracketed paste mode'', and other
+advanced capabilities has been removed.  When you kill text in an
+xterm Emacs session, that text is only saved in the Emacs kill ring,
+without letting other applications have any way of accessing it.  An
+xterm is just a text terminal, nothing more, nothing less.  There
+should be no feature we support on xterm that isn't supported on bare
+console terminals.  For the same reasons, support for mouse-tracking
+on xterm was removed.  We will continue this line of simplifications
+as we downgrade to previous versions of Emacs; stay tuned.
+
address@hidden
+Various features in @file{package.el} have been simplified.  The
+``external'' package status is no longer available.  A package present
+on multiple archives will now be listed as many times as it is found:
+we don't believe in concealing any information from the users.  This
+and other similar simplifications made
address@hidden unnecessary, since there's nothing
+to unhide now.
+
address@hidden
+The @address@hidden and @address@hidden keys in the minibuffer have
+been simplified to move by history items.  No need to wonder whether
+you have moved to the next/previous item or to another line within the
+same item.  Well-written commands shouldn't allow too long history
+entries anyway; be sure to report any that do as bugs, so that we
+could fix them in past versions of Emacs.
+
address@hidden
+The VC mode was simplified by removing the support for ``push''
+commands.  Moving back in time means you will have less and less need
+to use modern version control systems such as Git, Bazaar, and
+Mercurial, so the necessity of using ``push'' commands will gradually
+disappear.  We removed it from Emacs in advance, so that you won't
+need to un-learn it when this command disappears, as it should.
+
address@hidden
+The support for full C/C++ expressions in macros has been removed from
+Hide-Ifdef mode.  It now supports only the basic literal macros.  As
+result, the user interface was simplified, and a number of useless
+commands have been removed from Hide-Ifdef mode.  Further
+simplifications were made possible by removing support for some fancy
+new preprocessor directives, such as @code{#if defined}, @code{#elif},
+etc.
 
 @item
-In Isearch, @kbd{C-y} and @kbd{M-y} are no longer bound to
address@hidden and @code{isearch-yank-pop} respectively.
-Instead, @kbd{C-y} yanks the rest of the current line into the search
-string (@code{isearch-yank-line}), whereas @kbd{M-y} does
address@hidden  The mismatch with the usual meanings of
address@hidden and @kbd{M-y} is unintended.
+We have reverted to Etags for looking up definitions of functions,
+variables, etc.  Commands such as @kbd{M-.} use tags tables, as they
+always have.  This allowed the removal of the entire @file{xref.el}
+package and its many metastases in the other Emacs packages and
+commands, significantly simplifying those.  No more complexities with
+the various ``backends'' that provide incoherent behavior that is hard
+to explain and remember; either the symbol is in TAGS or it isn't.  No
+more new user interfaces we never before saw in Emacs, either; if you
+want the next definition for the symbol you typed, just invoke
address@hidden M-.}---what could be simpler?  As a nice side effect, you get
+to use your beloved @code{tags-loop-continue} and @code{pop-tag-mark}
+commands and their memorable bindings.  The @file{package.el} package
+has been removed for similar reasons.
 
 @item
-Various completion features have been simplified.  The option
address@hidden has been removed, so Emacs uses a
-single consistent scheme to generate completions, instead of using a
-separate scheme for (say) buffer name completion.  Several major
-modes, such as Shell mode, now implement their own inline completion
-commands instead of using @code{completion-at-point}.
address@hidden(/ @var{n})} once again yields just @var{n}.  Emacs Lisp is not
+Common Lisp, so compatibility with CL just complicates Emacs here.
 
 @item
-We have removed several options for controlling how windows are used,
-such as @code{display-buffer-base-action},
address@hidden, @code{window-combination-limit}, and
address@hidden
+The functions @code{filepos-to-bufferpos} and
address@hidden have been removed.  Code that needs to
+find a file position by a buffer position or vice versa should adapt
+by reading the file with no conversions and counting bytes while
+comparing text.  How hard can that be?
 
 @item
-The command @kbd{M-x customize-themes} has been removed.  Emacs no
-longer comes with pre-defined themes (you can write your own).
+We saw no need for the @code{make-process} primitive, so we removed
+it.  The @code{start-process} primitive provides all the functionality
+one needs, so adding more APIs just confuses users.
 
 @item
-Emacs no longer adapts various aspects of its display to GTK+
-settings, opting instead for a uniform toolkit-independent look.  GTK+
-scroll bars are placed on the left, the same position as non-GTK+ X
-scroll bars.  Emacs no longer refers to GTK+ to set the default
address@hidden face, nor for drawing tooltips.
+The functions @code{bidi-find-overridden-directionality} and
address@hidden were removed, in preparation
+for removing the whole bidi support when downgrading to Emacs 23.
 
 @item
-Setting the option @code{delete-by-moving-to-trash} to a
address@hidden value now causes all file deletions to use the system trash,
-even temporary files created by Lisp programs; furthermore, the
address@hidden delete-file} and @kbd{M-x delete-directory} commands no
-longer accept prefix arguments to force true deletion.
+Horizontal scroll bars are no longer supported.  Enlarge your windows
+and frames instead, or use @code{truncate-lines} and the automatic
+horizontal scrolling of text that Emacs had since time immemoriam.
 
 @item
-On GNU/Linux and Unix, the default method for sending mail (as
-specified by @code{send-mail-function}) is to use the
address@hidden program.  Emacs no longer asks for a delivery
-method the first time you try to send mail, trusting instead that the
-system is configured for mail delivery, as it ought to be.
+Emacs is again counting the height of a frame's menu and its tool bar
+in the frame's text height calculations.  This makes Emacs invocation
+on different platforms and with different toolkits less predictable
+when frame geometry parameters are given on the Emacs command line,
+thus making Emacs more adventurous and less boring to use.
 
 @item
-Several VC features have been removed, including the @kbd{C-x v +} and
address@hidden v m} commands for pulling and merging on distributed version
-control systems, and the ability to view inline log entries in the log
-buffers made by @kbd{C-x v L}.
+The @command{etags} program no longer supports Ruby and Go languages.
+You won't need that as you progressively travel back in time towards
+the time before these languages were invented.  We removed support for
+them in anticipation for that time.
 
 @item
 To keep up with decreasing computer memory capacity and disk space, many
-other functions and files have been eliminated in Emacs 23.4.
+other functions and files have been eliminated in Emacs 24.5.
 @end itemize
diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi
index 5ef9385..ac8988b 100644
--- a/doc/emacs/emacs.texi
+++ b/doc/emacs/emacs.texi
@@ -221,7 +221,7 @@ Appendices
 * GNU Free Documentation License:: The license for this documentation.
 * Emacs Invocation::    Hairy startup options.
 * X Resources::         X resources for customizing Emacs.
-* Antinews::            Information about Emacs version 23.
+* Antinews::            Information about Emacs version 24.
 * Mac OS / GNUstep::    Using Emacs under Mac OS and GNUstep.
 * Microsoft Windows::   Using Emacs on Microsoft Windows and MS-DOS.
 * Manifesto::           What's GNU?  Gnu's Not Unix!
diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi
index 989d8ff..90af5c8 100644
--- a/doc/emacs/maintaining.texi
+++ b/doc/emacs/maintaining.texi
@@ -1990,8 +1990,8 @@ Searching}.
 @table @kbd
 @item C-M-i
 @itemx address@hidden
-Perform completion on the text around point, using the selected tags
-table if one is loaded (@code{completion-at-point}).
+Perform completion on the text around point, possibly using the
+selected tags table if one is loaded (@code{completion-at-point}).
 @item M-x xref-find-apropos @key{RET} @var{regexp} @key{RET}
 Display a list of all known identifiers matching @var{regexp}.
 @item M-x list-tags @key{RET} @var{file} @key{RET}
@@ -2004,9 +2004,10 @@ Visit files recorded in the selected tags table.
 @cindex completion (symbol names)
   In most programming language modes, you can type @kbd{C-M-i} or
 @address@hidden (@code{completion-at-point}) to complete the symbol
-at point.  If there is a tags table loaded, this command can use it to
-generate completion candidates more intelligently.  @xref{Symbol
-Completion}.
+at point.  Some modes provide specialized completion for this command
+tailored to the mode; for those that don't, if there is a tags table
+loaded, this command can use it to generate completion candidates.
address@hidden Completion}.
 
 @findex list-tags
   @kbd{M-x list-tags} reads the name of one of the files covered by
@@ -2047,17 +2048,17 @@ file.  This command requires a tags table to be 
selected.
 @subsection Tags Tables
 @cindex tags and tag tables
 
address@hidden tag
-  A @dfn{tag} is a synonym for identifier reference.  @xref{Xref}.
-
-  A @dfn{tags table} records the tags extracted by scanning the source
-code of a certain program or a certain document.  Tags extracted from
-generated files reference the original files, rather than the
-generated files that were scanned during tag extraction.  Examples of
-generated files include C files generated from Cweb source files, from
-a Yacc parser, or from Lex scanner definitions; @file{.i} preprocessed
-C files; and Fortran files produced by preprocessing @file{.fpp}
-source files.
+  A @dfn{tags table} records the address@hidden
+A @dfn{tag} is a synonym for identifier reference.  Commands and
+features based on the @code{etags} package traditionally use ``tag''
+with this meaning, and this subsection follows that tradition.
+} extracted by scanning the source code of a certain program or a
+certain document.  Tags extracted from generated files reference the
+original files, rather than the generated files that were scanned
+during tag extraction.  Examples of generated files include C files
+generated from Cweb source files, from a Yacc parser, or from Lex
+scanner definitions; @file{.i} preprocessed C files; and Fortran files
+produced by preprocessing @file{.fpp} source files.
 
 @cindex etags
   To produce a tags table, you run the @command{etags} shell command
diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi
index c48af9a..4270161 100644
--- a/doc/lispref/variables.texi
+++ b/doc/lispref/variables.texi
@@ -2068,7 +2068,7 @@ cdar      nthcdr
 A call to any of the following Emacs-specific functions:
 
 @smallexample
-default-value                 process-get
+alist-get                     process-get
 frame-parameter               process-sentinel
 terminal-parameter            window-buffer
 keymap-parent                 window-display-table
@@ -2077,7 +2077,7 @@ overlay-get                   window-hscroll
 overlay-start                 window-parameter
 overlay-end                   window-point
 process-buffer                window-start
-process-filter
+process-filter                default-value
 @end smallexample
 @end itemize
 
diff --git a/etc/NEWS b/etc/NEWS
index 68e4aac..4a370a9 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -179,6 +179,20 @@ and can contain escape sequences for command keys, quotes, 
and the like.
 
 * Changes in Emacs 25.1
 
+** Xwidgets: a new feature for embedding native widgets inside Emacs buffers.
+If you have gtk3 and webkitgtk3 installed, you can access the
+embedded webkit browser with `M-x xwidget-webkit-browse-url'.  This
+opens a new buffer with the embedded browser.  The buffer will
+have a new mode, `xwidget-webkit-mode' (similar to `image-mode'),
+which supports the webkit widget.
+
+*** New functions for xwidget-webkit mode `xwidget-webkit-insert-string',
+`xwidget-webkit-adjust-size-dispatch', `xwidget-webkit-back',
+`xwidget-webkit-browse-url', `xwidget-webkit-reload',
+`xwidget-webkit-current-url', `xwidget-webkit-scroll-backward',
+`xwidget-webkit-scroll-forward', `xwidget-webkit-scroll-down',
+`xwidget-webkit-scroll-up'.
+
 +++
 ** Emacs can now load shared/dynamic libraries (modules).
 A dynamic Emacs module is a shared library that provides additional
@@ -1596,6 +1610,7 @@ permissions set to temporary values (e.g., for creating 
private files).
 +++
 ** Function `sort' can deal with vectors.
 
+---
 ** Function `system-name' now returns an updated value if the current
 system's name has changed or if the Emacs process has changed systems,
 and to avoid long waits it no longer consults DNS to canonicalize the
diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el
index 353ca69..29d8dfc 100644
--- a/lisp/calendar/todo-mode.el
+++ b/lisp/calendar/todo-mode.el
@@ -4654,13 +4654,15 @@ name in `todo-directory'.  See also the documentation 
string of
                    (goto-char (match-beginning 0))
                  (goto-char (point-max)))
                (backward-char)
-               (when (looking-back "\\[\\([^][]+\\)\\]")
+               (when (looking-back "\\[\\([^][]+\\)\\]"
+                                    (line-beginning-position))
                  (setq cat (match-string 1))
                  (goto-char (match-beginning 0))
                  (replace-match ""))
                ;; If the item ends with a non-comment parenthesis not
                ;; followed by a period, we lose (but we inherit that
                ;; problem from the legacy code).
+                ;; FIXME: fails on multiline comment
                (when (looking-back "(\\(.*\\)) " (line-beginning-position))
                  (setq comment (match-string 1))
                  (replace-match "")
@@ -5230,7 +5232,8 @@ Also preserve category display, if applicable."
   (with-current-buffer buffer
     (widen)
     (let ((todo-category-number (cdr (assq 'catnum misc))))
-      (todo-category-select))))
+      (todo-category-select)
+      (current-buffer))))
 
 (add-to-list 'desktop-buffer-mode-handlers
             '(todo-mode . todo-restore-desktop-buffer))
@@ -6579,8 +6582,7 @@ Added to `window-configuration-change-hook' in Todo mode."
   "Make some settings that apply to multiple Todo modes."
   (add-to-invisibility-spec 'todo)
   (setq buffer-read-only t)
-  (when (and (boundp 'desktop-save-mode) desktop-save-mode)
-    (setq-local desktop-save-buffer 'todo-desktop-save-buffer))
+  (setq-local desktop-save-buffer 'todo-desktop-save-buffer)
   (when (boundp 'hl-line-range-function)
     (setq-local hl-line-range-function
                (lambda() (save-excursion
diff --git a/lisp/doc-view.el b/lisp/doc-view.el
index 2868113..06cf8dc 100644
--- a/lisp/doc-view.el
+++ b/lisp/doc-view.el
@@ -1714,7 +1714,8 @@ If BACKWARD is non-nil, jump to the previous match."
       ;; window-parameters in the window-state(s) and then restoring this
       ;; window-state should call us back (to interpret/use those parameters).
       (doc-view-goto-page page)
-      (when slice (apply 'doc-view-set-slice slice)))))
+      (when slice (apply 'doc-view-set-slice slice))
+      (current-buffer))))
 
 (add-to-list 'desktop-buffer-mode-handlers
             '(doc-view-mode . doc-view-restore-desktop-buffer))
@@ -1788,9 +1789,7 @@ toggle between displaying the document or editing it as 
text.
              nil t)
     (add-hook 'clone-indirect-buffer-hook 'doc-view-clone-buffer-hook nil t)
     (add-hook 'kill-buffer-hook 'doc-view-kill-proc nil t)
-    (when (and (boundp 'desktop-save-mode)
-              desktop-save-mode)
-      (setq-local desktop-save-buffer 'doc-view-desktop-save-buffer))
+    (setq-local desktop-save-buffer 'doc-view-desktop-save-buffer)
 
     (remove-overlays (point-min) (point-max) 'doc-view t) ;Just in case.
     ;; Keep track of display info ([vh]scroll, page number, overlay,
diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index 3b22481..549ee96 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -107,12 +107,36 @@
 
 ;;;###autoload
 (defmacro pcase (exp &rest cases)
-  "Eval EXP and perform ML-style pattern matching on that value.
+  "Evaluate EXP and attempt to match it against structural patterns.
 CASES is a list of elements of the form (PATTERN CODE...).
 
-Patterns can take the following forms:
+A structural PATTERN describes a template that identifies a class
+of values.  For example, the pattern `(,foo ,bar) matches any
+two element list, binding its elements to symbols named `foo' and
+`bar' -- in much the same way that `cl-destructuring-bind' would.
+
+A significant difference from `cl-destructuring-bind' is that, if
+a pattern match fails, the next case is tried until either a
+succesful match is found or there are no more cases.
+
+Another difference is that pattern elements may be backquoted,
+meaning they must match exactly: The pattern \\='(foo bar)
+matches only against two element lists containing the symbols
+`foo' and `bar' in that order.  (As a short-hand, atoms always
+match themselves, such as numbers or strings, and need not be
+quoted).
+
+Lastly, a pattern can be logical, such as (pred numberp), that
+matches any number-like element; or the symbol `_', that matches
+anything.  Also, when patterns are backquoted, a comma may be
+used to introduce logical patterns inside backquoted patterns.
+
+The complete list of standard patterns is as follows:
+
   _            matches anything.
   SYMBOL       matches anything and binds it to SYMBOL.
+                If a SYMBOL is used twice in the same pattern
+                the second occurrence becomes an `eq'uality test.
   (or PAT...)  matches if any of the patterns matches.
   (and PAT...) matches if all the patterns match.
   \\='VAL              matches if the object is `equal' to VAL.
@@ -122,23 +146,18 @@ Patterns can take the following forms:
   (guard BOOLEXP)      matches if BOOLEXP evaluates to non-nil.
   (let PAT EXP)        matches if EXP matches PAT.
   (app FUN PAT)        matches if FUN applied to the object matches PAT.
-If a SYMBOL is used twice in the same pattern (i.e. the pattern is
-\"non-linear\"), then the second occurrence is turned into an `eq'uality test.
 
-FUN can take the form
+Additional patterns can be defined using `pcase-defmacro'.
+
+The FUN argument in the `app' pattern may have the following forms:
   SYMBOL or (lambda ARGS BODY)  in which case it's called with one argument.
   (F ARG1 .. ARGn) in which case F gets called with an n+1'th argument
                         which is the value being matched.
-So a FUN of the form SYMBOL is equivalent to one of the form (FUN).
+So a FUN of the form SYMBOL is equivalent to (FUN).
 FUN can refer to variables bound earlier in the pattern.
-E.g. you can match pairs where the cdr is larger than the car with a pattern
-like \\=`(,a . ,(pred (< a))) or, with more checks:
-\\=`(,(and a (pred numberp)) . ,(and (pred numberp) (pred (< a))))
-FUN is assumed to be pure, i.e. it can be dropped if its result is not used,
-and two identical calls can be merged into one.
-
-Additional patterns can be defined via `pcase-defmacro'.
-Currently, the following patterns are provided this way:"
+
+See Info node `(elisp) Pattern matching case statement' in the
+Emacs Lisp manual for more information and examples."
   (declare (indent 1) (debug (form &rest (pcase-PAT body))))
   ;; We want to use a weak hash table as a cache, but the key will unavoidably
   ;; be based on `exp' and `cases', yet `cases' is a fresh new list each time
diff --git a/lisp/gnus/nnir.el b/lisp/gnus/nnir.el
index 183e144..560ba8a 100644
--- a/lisp/gnus/nnir.el
+++ b/lisp/gnus/nnir.el
@@ -822,8 +822,10 @@ skips all prompting."
 (deffoo nnir-request-update-mark (group article mark)
   (let ((artgroup (nnir-article-group article))
        (artnumber (nnir-article-number article)))
-    (when (and artgroup artnumber)
-      (gnus-request-update-mark artgroup artnumber mark))))
+    (or (and artgroup
+            artnumber
+            (gnus-request-update-mark artgroup artnumber mark))
+       mark)))
 
 (deffoo nnir-request-set-mark (group actions &optional server)
   (nnir-possibly-change-group group server)
diff --git a/lisp/htmlfontify.el b/lisp/htmlfontify.el
index 964d744..431300c 100644
--- a/lisp/htmlfontify.el
+++ b/lisp/htmlfontify.el
@@ -1001,7 +1001,7 @@ merged by the user - `hfy-flatten-style' should do this."
                   (append
                    parent
                    (hfy-face-to-style-i
-                    (hfy-face-attr-for-class v hfy-display-class)) ))))
+                    (hfy-face-attr-for-class v hfy-display-class))))))
         (setq this
               (if val (case key
                        (:family         (hfy-family    val))
@@ -1020,7 +1020,7 @@ merged by the user - `hfy-flatten-style' should do this."
                        (:italic         (hfy-slant 'italic))))))
       (setq that (hfy-face-to-style-i next))
       ;;(lwarn t :warning "%S => %S" fn (nconc this that parent))
-      (nconc this that parent))) )
+      (nconc this parent that))) )
 
 (defun hfy-size-to-int (spec)
   "Convert SPEC, a CSS font-size specifier, to an Emacs :height attribute 
value.
@@ -1058,13 +1058,19 @@ haven't encountered them yet.  Returns a 
`hfy-style-assoc'."
     (nconc r (hfy-size (if x (round n) (* n 1.0)))) ))
 
 (defun hfy-face-resolve-face (fn)
+  "For FN return a face specification.
+FN may be either a face or a face specification. If the latter,
+then the specification is returned unchanged."
   (cond
    ((facep fn)
     (hfy-face-attr-for-class fn hfy-display-class))
+   ;; FIXME: is this necessary? Faces can be symbols, but
+   ;; not symbols refering to other symbols?
    ((and (symbolp fn)
          (facep (symbol-value fn)))
-    (hfy-face-attr-for-class (symbol-value fn) hfy-display-class))
-   (t nil)))
+    (hfy-face-attr-for-class
+     (symbol-value fn) hfy-display-class))
+   (t fn)))
 
 
 (defun hfy-face-to-style (fn)
diff --git a/lisp/image-mode.el b/lisp/image-mode.el
index e677dd0..e549b49 100644
--- a/lisp/image-mode.el
+++ b/lisp/image-mode.el
@@ -153,6 +153,8 @@ otherwise it defaults to t, used for times when the buffer 
is not displayed."
                          (selected-window))))
 
 (declare-function image-size "image.c" (spec &optional pixels frame))
+(declare-function xwidget-info "xwidget.c" (xwidget))
+(declare-function xwidget-at "xwidget.el" (pos))
 
 (defun image-display-size (spec &optional pixels frame)
   "Wrapper around `image-size', handling slice display properties.
@@ -160,24 +162,29 @@ Like `image-size', the return value is (WIDTH . HEIGHT).
 WIDTH and HEIGHT are in canonical character units if PIXELS is
 nil, and in pixel units if PIXELS is non-nil.
 
-If SPEC is an image display property, this function is equivalent
-to `image-size'.  If SPEC is a list of properties containing
-`image' and `slice' properties, return the display size taking
-the slice property into account.  If the list contains `image'
-but not `slice', return the `image-size' of the specified image."
-  (if (eq (car spec) 'image)
-      (image-size spec pixels frame)
-    (let ((image (assoc 'image spec))
-         (slice (assoc 'slice spec)))
-      (cond ((and image slice)
-            (if pixels
-                (cons (nth 3 slice) (nth 4 slice))
-              (cons (/ (float (nth 3 slice)) (frame-char-width frame))
-                    (/ (float (nth 4 slice)) (frame-char-height frame)))))
-           (image
-            (image-size image pixels frame))
-           (t
-            (error "Invalid image specification: %s" spec))))))
+If SPEC is an image display property, this function is equivalent to
+`image-size'.  If SPEC represents an xwidget object, defer to `xwidget-info'.
+If SPEC is a list of properties containing `image' and `slice' properties,
+return the display size taking the slice property into account.  If the list
+contains `image' but not `slice', return the `image-size' of the specified
+image."
+  (cond ((eq (car spec) 'xwidget)
+         (let ((xwi (xwidget-info (xwidget-at (point-min)))))
+           (cons (aref xwi 2) (aref xwi 3))))
+        ((eq (car spec) 'image)
+         (image-size spec pixels frame))
+        (t (let ((image (assoc 'image spec))
+                 (slice (assoc 'slice spec)))
+             (cond ((and image slice)
+                    (if pixels
+                        (cons (nth 3 slice) (nth 4 slice))
+                      (cons (/ (float (nth 3 slice)) (frame-char-width frame))
+                            (/ (float (nth 4 slice))
+                               (frame-char-height frame)))))
+                   (image
+                    (image-size image pixels frame))
+                   (t
+                    (error "Invalid image specification: %s" spec)))))))
 
 (defun image-forward-hscroll (&optional n)
   "Scroll image in current window to the left by N character widths.
diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el
index 79e9c7b..2df847a 100644
--- a/lisp/international/mule-cmds.el
+++ b/lisp/international/mule-cmds.el
@@ -2119,7 +2119,7 @@ See `set-language-info-alist' for use in programs."
       (with-current-buffer standard-output
        (insert language-name " language environment\n\n")
        (if (stringp doc)
-           (insert doc "\n\n"))
+           (insert (substitute-command-keys doc) "\n\n"))
        (condition-case nil
            (let ((str (eval (get-language-info language-name 'sample-text))))
              (if (stringp str)
diff --git a/lisp/international/quail.el b/lisp/international/quail.el
index 75cb7f7..f5e3902 100644
--- a/lisp/international/quail.el
+++ b/lisp/international/quail.el
@@ -2516,7 +2516,7 @@ package to describe."
              ")\n\n")
       (save-restriction
        (narrow-to-region (point) (point))
-       (insert (quail-docstring))
+       (insert (substitute-command-keys (quail-docstring)))
        (goto-char (point-min))
        (with-syntax-table emacs-lisp-mode-syntax-table
          (while (re-search-forward "\\\\<\\sw\\(\\sw\\|\\s_\\)+>" nil t)
diff --git a/lisp/isearch.el b/lisp/isearch.el
index e636ccc..c36f463 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -2647,10 +2647,11 @@ the word mode."
   "Non-default value overrides the behavior of `isearch-search-fun-default'.
 This variable's value should be a function, which will be called
 with no arguments, and should return a function that takes three
-arguments: STRING, BOUND, and NOERROR.
+arguments: STRING, BOUND, and NOERROR.  See `re-search-forward'
+for the meaning of BOUND and NOERROR arguments.
 
 This returned function will be used by `isearch-search-string' to
-search for the first occurrence of STRING or its translation.")
+search for the first occurrence of STRING.")
 
 (defun isearch-search-fun ()
   "Return the function to use for the search.
@@ -2695,8 +2696,14 @@ Can be changed via `isearch-search-fun-function' for 
special needs."
 
 (defun isearch-search-string (string bound noerror)
   "Search for the first occurrence of STRING or its translation.
+STRING's characters are translated using `translation-table-for-input'
+if that is non-nil.
 If found, move point to the end of the occurrence,
-update the match data, and return point."
+update the match data, and return point.
+An optional second argument bounds the search; it is a buffer position.
+The match found must not extend after that position.
+Optional third argument, if t, means if fail just return nil (no error).
+  If not nil and not t, move to limit of search and return nil."
   (let* ((func (isearch-search-fun))
          (pos1 (save-excursion (funcall func string bound noerror)))
          pos2)
diff --git a/lisp/net/shr.el b/lisp/net/shr.el
index 290a642..ab41614 100644
--- a/lisp/net/shr.el
+++ b/lisp/net/shr.el
@@ -1619,7 +1619,7 @@ The preference is a float determined from 
`shr-prefer-media-type'."
 (defun shr-table-body (dom)
   (let ((tbodies (seq-filter (lambda (child)
                                (eq (dom-tag child) 'tbody))
-                             (dom-children dom))))
+                             (dom-non-text-children dom))))
     (cond
      ((null tbodies)
       dom)
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index 53f8a6b..e3fe315 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -102,7 +102,7 @@
 
 (eval-and-compile
   (defconst ruby-here-doc-beg-re
-  
"\\(<\\)<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)"
+  
"\\(<\\)<\\([~-]\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)"
   "Regexp to match the beginning of a heredoc.")
 
   (defconst ruby-expression-expansion-re
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index 2bccd85..d32da37 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -861,7 +861,13 @@ tools are used, and when."
   (cl-assert (directory-name-p dir))
   (require 'semantic/symref)
   (defvar semantic-symref-tool)
-  (let* ((default-directory dir)
+
+  ;; Some symref backends use `ede-project-root-directory' as the root
+  ;; directory for the search, rather than `default-directory'. Since
+  ;; the caller has specified `dir', we bind `ede-minor-mode' to nil
+  ;; to force the backend to use `default-directory'.
+  (let* ((ede-minor-mode nil)
+         (default-directory dir)
          (semantic-symref-tool 'detect)
          (res (semantic-symref-find-references-by-name symbol 'subdirs))
          (hits (and res (oref res hit-lines)))
diff --git a/lisp/xwidget.el b/lisp/xwidget.el
new file mode 100644
index 0000000..f184eb3
--- /dev/null
+++ b/lisp/xwidget.el
@@ -0,0 +1,580 @@
+;;; xwidget.el --- api functions for xwidgets  -*- lexical-binding: t -*-
+;;
+;; Copyright (C) 2011-2016 Free Software Foundation, Inc.
+;;
+;; Author: Joakim Verona (address@hidden)
+;;
+;; 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 <http://www.gnu.org/licenses/>.
+;;
+;; --------------------------------------------------------------------
+
+;;; Commentary:
+;;
+;; See xwidget.c for more api functions.
+
+;; TODO this breaks compilation when we don't have xwidgets.
+;;(require 'xwidget-internal)
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'bookmark)
+
+(defcustom xwidget-webkit-scroll-behaviour 'native
+  "Scroll behaviour of the webkit instance.
+'native or 'image."
+  :version "25.1"
+  :group 'frames   ; TODO add xwidgets group if more options are added
+  :type '(choice (const native) (const image)))
+
+(declare-function make-xwidget "xwidget.c"
+                  (beg end type title width height arguments &optional buffer))
+(declare-function xwidget-set-adjustment "xwidget.c"
+                  (xwidget axis relative value))
+(declare-function xwidget-buffer "xwidget.c" (xwidget))
+(declare-function xwidget-webkit-get-title "xwidget.c" (xwidget))
+(declare-function xwidget-size-request "xwidget.c" (xwidget))
+(declare-function xwidget-resize "xwidget.c" (xwidget new-width new-height))
+(declare-function xwidget-webkit-execute-script "xwidget.c" (xwidget script))
+(declare-function xwidget-webkit-goto-uri "xwidget.c" (xwidget uri))
+(declare-function xwidget-plist "xwidget.c" (xwidget))
+(declare-function set-xwidget-plist "xwidget.c" (xwidget plist))
+(declare-function xwidget-view-window "xwidget.c" (xwidget-view))
+(declare-function xwidget-view-model "xwidget.c" (xwidget-view))
+(declare-function delete-xwidget-view "xwidget.c" (xwidget-view))
+(declare-function get-buffer-xwidgets "xwidget.c" (buffer))
+
+(defun xwidget-insert (pos type title width height &optional args)
+  "Insert an xwidget at POS.
+given ID, TYPE, TITLE WIDTH and
+HEIGHT in the current buffer.
+
+Return ID
+
+see `make-xwidget' for types suitable for TYPE.
+Optional argument ARGS usage depends on the xwidget."
+  (goto-char pos)
+  (let ((id (make-xwidget (point) (point)
+                          type title width height args)))
+    (put-text-property (point) (+ 1 (point))
+                       'display (list 'xwidget ':xwidget id))
+    id))
+
+(defun xwidget-at (pos)
+  "Return xwidget at POS."
+  ;; TODO this function is a bit tedious because the C layer isn't well
+  ;; protected yet and xwidgetp apparently doesn't work yet.
+  (let* ((disp (get-text-property pos 'display))
+         (xw (car (cdr (cdr  disp)))))
+    ;;(if (xwidgetp  xw) xw nil)
+    (if (equal 'xwidget (car disp)) xw)))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; webkit support
+(require 'browse-url)
+(require 'image-mode);;for some image-mode alike functionality
+
+;;;###autoload
+(defun xwidget-webkit-browse-url (url &optional new-session)
+  "Ask xwidget-webkit to browse URL.
+NEW-SESSION specifies whether to create a new xwidget-webkit session.  URL
+defaults to the string looking like a url around the cursor position."
+  (interactive (progn
+                 (require 'browse-url)
+                 (browse-url-interactive-arg "xwidget-webkit URL: "
+                                             ;;(xwidget-webkit-current-url)
+                                             )))
+  (when (stringp url)
+    (if new-session
+        (xwidget-webkit-new-session url)
+      (xwidget-webkit-goto-url url))))
+
+;;todo.
+;; - check that the webkit support is compiled in
+(defvar xwidget-webkit-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "g" 'xwidget-webkit-browse-url)
+    (define-key map "a" 'xwidget-webkit-adjust-size-dispatch)
+    (define-key map "b" 'xwidget-webkit-back)
+    (define-key map "r" 'xwidget-webkit-reload)
+    (define-key map "t" (lambda () (interactive) (message "o"))) ;FIXME: ?!?
+    (define-key map "\C-m" 'xwidget-webkit-insert-string)
+    (define-key map "w" 'xwidget-webkit-current-url)
+
+    ;;similar to image mode bindings
+    (define-key map (kbd "SPC")                 'xwidget-webkit-scroll-up)
+    (define-key map (kbd "DEL")                 'xwidget-webkit-scroll-down)
+
+    (define-key map [remap scroll-up]           'xwidget-webkit-scroll-up)
+    (define-key map [remap scroll-up-command]   'xwidget-webkit-scroll-up)
+
+    (define-key map [remap scroll-down]         'xwidget-webkit-scroll-down)
+    (define-key map [remap scroll-down-command] 'xwidget-webkit-scroll-down)
+
+    (define-key map [remap forward-char]        'xwidget-webkit-scroll-forward)
+    (define-key map [remap backward-char]       
'xwidget-webkit-scroll-backward)
+    (define-key map [remap right-char]          'xwidget-webkit-scroll-forward)
+    (define-key map [remap left-char]           
'xwidget-webkit-scroll-backward)
+    ;; (define-key map [remap previous-line]          'image-previous-line)
+    ;; (define-key map [remap next-line]              'image-next-line)
+
+    ;; (define-key map [remap move-beginning-of-line] 'image-bol)
+    ;; (define-key map [remap move-end-of-line]       'image-eol)
+    ;; (define-key map [remap beginning-of-buffer]    'image-bob)
+    ;; (define-key map [remap end-of-buffer]          'image-eob)
+    map)
+  "Keymap for `xwidget-webkit-mode'.")
+
+(defun xwidget-webkit-scroll-up ()
+  "Scroll webkit up,either native or like image mode."
+  (interactive)
+  (if (eq xwidget-webkit-scroll-behaviour 'native)
+      (xwidget-set-adjustment (xwidget-webkit-last-session) 'vertical t 50)
+    (image-scroll-up)))
+
+(defun xwidget-webkit-scroll-down ()
+  "Scroll webkit down,either native or like image mode."
+  (interactive)
+  (if (eq xwidget-webkit-scroll-behaviour 'native)
+      (xwidget-set-adjustment (xwidget-webkit-last-session) 'vertical t -50)
+    (image-scroll-down)))
+
+(defun xwidget-webkit-scroll-forward ()
+  "Scroll webkit forward,either native or like image mode."
+  (interactive)
+  (if (eq xwidget-webkit-scroll-behaviour 'native)
+      (xwidget-set-adjustment (xwidget-webkit-last-session) 'horizontal t 50)
+    (xwidget-webkit-scroll-forward)))
+
+(defun xwidget-webkit-scroll-backward ()
+  "Scroll webkit backward,either native or like image mode."
+  (interactive)
+  (if (eq xwidget-webkit-scroll-behaviour 'native)
+      (xwidget-set-adjustment (xwidget-webkit-last-session) 'horizontal t -50)
+    (xwidget-webkit-scroll-backward)))
+
+
+;; The xwidget event needs to go into a higher level handler
+;; since the xwidget can generate an event even if it's offscreen.
+;; TODO this needs to use callbacks and consider different xwidget event types.
+(define-key (current-global-map) [xwidget-event] #'xwidget-event-handler)
+(defun xwidget-log (&rest msg)
+  "Log MSG to a buffer."
+  (let ((buf (get-buffer-create " *xwidget-log*")))
+    (with-current-buffer buf
+      (insert (apply #'format msg))
+      (insert "\n"))))
+
+(defun xwidget-event-handler ()
+  "Receive xwidget event."
+  (interactive)
+  (xwidget-log "stuff happened to xwidget %S" last-input-event)
+  (let*
+      ((xwidget-event-type (nth 1 last-input-event))
+       (xwidget (nth 2 last-input-event))
+       ;;(xwidget-callback (xwidget-get xwidget 'callback))
+       ;;TODO stopped working for some reason
+       )
+    ;;(funcall  xwidget-callback xwidget xwidget-event-type)
+    (message "xw callback %s" xwidget)
+    (funcall  'xwidget-webkit-callback xwidget xwidget-event-type)))
+
+(defun xwidget-webkit-callback (xwidget xwidget-event-type)
+  "Callback for xwidgets.
+XWIDGET instance, XWIDGET-EVENT-TYPE depends on the originating xwidget."
+  (if (not (buffer-live-p (xwidget-buffer xwidget)))
+      (xwidget-log
+       "error: callback called for xwidget with dead buffer")
+    (with-current-buffer (xwidget-buffer xwidget)
+      (let* ((strarg  (nth 3 last-input-event)))
+        (cond ((eq xwidget-event-type 'document-load-finished)
+               (xwidget-log "webkit finished loading: '%s'"
+                            (xwidget-webkit-get-title xwidget))
+               ;;TODO - check the native/internal scroll
+               ;;(xwidget-adjust-size-to-content xwidget)
+               (xwidget-webkit-adjust-size-dispatch) ;;TODO xwidget arg
+               (rename-buffer (format "*xwidget webkit: %s *"
+                                      (xwidget-webkit-get-title xwidget)))
+               (pop-to-buffer (current-buffer)))
+              ((eq xwidget-event-type
+                   'navigation-policy-decision-requested)
+               (if (string-match ".*#\\(.*\\)" strarg)
+                   (xwidget-webkit-show-id-or-named-element
+                    xwidget
+                    (match-string 1 strarg))))
+              (t (xwidget-log "unhandled event:%s" xwidget-event-type)))))))
+
+(defvar bookmark-make-record-function)
+(define-derived-mode xwidget-webkit-mode
+    special-mode "xwidget-webkit" "Xwidget webkit view mode."
+    (setq buffer-read-only t)
+    (setq-local bookmark-make-record-function
+                #'xwidget-webkit-bookmark-make-record)
+    ;; Keep track of [vh]scroll when switching buffers
+    (image-mode-setup-winprops))
+
+(defun xwidget-webkit-bookmark-make-record ()
+  "Integrate Emacs bookmarks with the webkit xwidget."
+  (nconc (bookmark-make-record-default t t)
+         `((page     . ,(xwidget-webkit-current-url))
+           (handler  . (lambda (bmk) (browse-url
+                                 (bookmark-prop-get bmk 'page)))))))
+
+
+(defvar xwidget-webkit-last-session-buffer nil)
+
+(defun xwidget-webkit-last-session ()
+  "Last active webkit, or nil."
+  (if (buffer-live-p xwidget-webkit-last-session-buffer)
+      (with-current-buffer xwidget-webkit-last-session-buffer
+        (xwidget-at (point-min)))
+    nil))
+
+(defun xwidget-webkit-current-session ()
+  "Either the webkit in the current buffer, or the last one used.
+The latter might be nil."
+  (or (xwidget-at (point-min)) (xwidget-webkit-last-session)))
+
+(defun xwidget-adjust-size-to-content (xw)
+  "Resize XW to content."
+  ;; xwidgets doesn't support widgets that have their own opinions about
+  ;; size well, yet this reads the desired size and resizes the Emacs
+  ;; allocated area accordingly.
+  (let ((size (xwidget-size-request xw)))
+    (xwidget-resize xw (car size) (cadr size))))
+
+
+(defvar xwidget-webkit-activeelement-js"
+function findactiveelement(doc){
+//alert(doc.activeElement.value);
+   if(doc.activeElement.value != undefined){
+      return doc.activeElement;
+   }else{
+        // recurse over the child documents:
+        var frames = doc.getElementsByTagName('frame');
+        for (var i = 0; i < frames.length; i++)
+        {
+                var d = frames[i].contentDocument;
+                 var rv = findactiveelement(d);
+                 if(rv != undefined){
+                    return rv;
+                 }
+        }
+    }
+    return undefined;
+};
+
+
+"
+
+  "javascript that finds the active element."
+  ;; Yes it's ugly, because:
+  ;; - there is apparently no way to find the active frame other than recursion
+  ;; - the js "for each" construct misbehaved on the "frames" collection
+  ;; - a window with no frameset still has frames.length == 1, but
+  ;; frames[0].document.activeElement != document.activeElement
+  ;;TODO the activeelement type needs to be examined, for iframe, etc.
+  )
+
+(defun xwidget-webkit-insert-string (xw str)
+  "Insert string in the active field in the webkit.
+Argument XW webkit.
+Argument STR string."
+  ;; Read out the string in the field first and provide for edit.
+  (interactive
+   (let* ((xww (xwidget-webkit-current-session))
+
+          (field-value
+           (progn
+             (xwidget-webkit-execute-script xww 
xwidget-webkit-activeelement-js)
+             (xwidget-webkit-execute-script-rv
+              xww
+              "findactiveelement(document).value;")))
+          (field-type (xwidget-webkit-execute-script-rv
+                       xww
+                       "findactiveelement(document).type;")))
+     (list xww
+           (cond ((equal "text" field-type)
+                  (read-string "text:" field-value))
+                 ((equal "password" field-type)
+                  (read-passwd "password:" nil field-value))
+                 ((equal "textarea" field-type)
+                  (xwidget-webkit-begin-edit-textarea xww field-value))))))
+  (xwidget-webkit-execute-script
+   xw
+   (format "findactiveelement(document).value='%s'" str)))
+
+(defvar xwidget-xwbl)
+(defun xwidget-webkit-begin-edit-textarea (xw text)
+  "Start editing of a webkit text area.
+XW is the xwidget identifier, TEXT is retrieved from the webkit."
+  (switch-to-buffer
+   (generate-new-buffer "textarea"))
+
+  (set (make-local-variable 'xwidget-xwbl) xw)
+  (insert text))
+
+(defun xwidget-webkit-end-edit-textarea ()
+  "End editing of a webkit text area."
+  (interactive)
+  (goto-char (point-min))
+  (while (search-forward "\n" nil t)
+    (replace-match "\\n" nil t))
+  (xwidget-webkit-execute-script
+   xwidget-xwbl
+   (format "findactiveelement(document).value='%s'"
+           (buffer-substring (point-min) (point-max))))
+  ;;TODO convert linefeed to \n
+  )
+
+(defun xwidget-webkit-show-named-element (xw element-name)
+  "Make named-element show.  for instance an anchor.
+Argument XW is the xwidget.
+Argument ELEMENT-NAME is the element name to display in the webkit xwidget."
+  (interactive (list (xwidget-webkit-current-session)
+                     (read-string "element name:")))
+  ;;TODO since an xwidget is an Emacs object, it is not trivial to do
+  ;; some things that are taken for granted in a normal browser.
+  ;; scrolling an anchor/named-element into view is one such thing.
+  ;; This function implements a proof-of-concept for this.  Problems
+  ;; remaining: - The selected window is scrolled but this is not
+  ;; always correct - This needs to be interfaced into browse-url
+  ;; somehow.  The tricky part is that we need to do this in two steps:
+  ;; A: load the base url, wait for load signal to arrive B: navigate
+  ;; to the anchor when the base url is finished rendering
+
+  ;; This part figures out the Y coordinate of the element
+  (let ((y (string-to-number
+            (xwidget-webkit-execute-script-rv
+             xw
+             (format
+              "document.getElementsByName('%s')[0].getBoundingClientRect().top"
+              element-name)
+             0))))
+    ;; Now we need to tell Emacs to scroll the element into view.
+    (xwidget-log "scroll: %d" y)
+    (set-window-vscroll (selected-window) y t)))
+
+(defun xwidget-webkit-show-id-element (xw element-id)
+  "Make id-element show.  for instance an anchor.
+Argument XW is the webkit xwidget.
+Argument ELEMENT-ID is the id of the element to show."
+  (interactive (list (xwidget-webkit-current-session)
+                     (read-string "element id:")))
+  (let ((y (string-to-number
+            (xwidget-webkit-execute-script-rv
+             xw
+             (format 
"document.getElementById('%s').getBoundingClientRect().top"
+                     element-id)
+             0))))
+    ;; Now we need to tell Emacs to scroll the element into view.
+    (xwidget-log "scroll: %d" y)
+    (set-window-vscroll (selected-window) y t)))
+
+(defun xwidget-webkit-show-id-or-named-element (xw element-id)
+  "Make id-element show.  for instance an anchor.
+Argument XW is the webkit xwidget.
+Argument ELEMENT-ID is either a name or an element id."
+  (interactive (list (xwidget-webkit-current-session)
+                     (read-string "element id:")))
+  (let* ((y1 (string-to-number
+              (xwidget-webkit-execute-script-rv
+               xw
+               (format 
"document.getElementsByName('%s')[0].getBoundingClientRect().top" element-id)
+               "0")))
+         (y2 (string-to-number
+              (xwidget-webkit-execute-script-rv
+               xw
+               (format 
"document.getElementById('%s').getBoundingClientRect().top" element-id)
+               "0")))
+         (y3 (max y1 y2)))
+    ;; Now we need to tell Emacs to scroll the element into view.
+    (xwidget-log "scroll: %d" y3)
+    (set-window-vscroll (selected-window) y3 t)))
+
+(defun xwidget-webkit-adjust-size-to-content ()
+  "Adjust webkit to content size."
+  (interactive)
+  (xwidget-adjust-size-to-content (xwidget-webkit-current-session)))
+
+(defun xwidget-webkit-adjust-size-dispatch ()
+  "Adjust size according to mode."
+  (interactive)
+  (if (eq xwidget-webkit-scroll-behaviour 'native)
+      (xwidget-webkit-adjust-size-to-window)
+    (xwidget-webkit-adjust-size-to-content))
+  ;; The recenter is intended to correct a visual glitch.
+  ;; It errors out if the buffer isn't visible, but then we don't get
+  ;; the glitch, so silence errors.
+  (ignore-errors
+    (recenter-top-bottom))
+  )
+
+(defun xwidget-webkit-adjust-size-to-window ()
+  "Adjust webkit to window."
+  (interactive)
+  (xwidget-resize (xwidget-webkit-current-session) (window-pixel-width)
+                  (window-pixel-height)))
+
+(defun xwidget-webkit-adjust-size (w h)
+  "Manually set webkit size.
+Argument W width.
+Argument H height."
+  ;; TODO shouldn't be tied to the webkit xwidget
+  (interactive "nWidth:\nnHeight:\n")
+  (xwidget-resize (xwidget-webkit-current-session) w h))
+
+(defun xwidget-webkit-fit-width ()
+  "Adjust width of webkit to window width."
+  (interactive)
+  (xwidget-webkit-adjust-size (- (nth 2 (window-inside-pixel-edges))
+                                 (car (window-inside-pixel-edges)))
+                              1000))
+
+(defun xwidget-webkit-new-session (url)
+  "Create a new webkit session buffer with URL."
+  (let*
+      ((bufname (generate-new-buffer-name "*xwidget-webkit*"))
+       xw)
+    (setq xwidget-webkit-last-session-buffer (switch-to-buffer
+                                              (get-buffer-create bufname)))
+    (insert " 'a' adjusts the xwidget size.")
+    (setq xw (xwidget-insert 1 'webkit-osr  bufname 1000 1000))
+    (xwidget-put xw 'callback 'xwidget-webkit-callback)
+    (xwidget-webkit-mode)
+    (xwidget-webkit-goto-uri (xwidget-webkit-last-session) url)))
+
+
+(defun xwidget-webkit-goto-url (url)
+  "Goto URL."
+  (if (xwidget-webkit-current-session)
+      (progn
+        (xwidget-webkit-goto-uri (xwidget-webkit-current-session) url))
+    (xwidget-webkit-new-session url)))
+
+(defun xwidget-webkit-back ()
+  "Back in history."
+  (interactive)
+  (xwidget-webkit-execute-script (xwidget-webkit-current-session)
+                                 "history.go(-1);"))
+
+(defun xwidget-webkit-reload ()
+  "Reload current url."
+  (interactive)
+  (xwidget-webkit-execute-script (xwidget-webkit-current-session)
+                                 "history.go(0);"))
+
+(defun xwidget-webkit-current-url ()
+  "Get the webkit url.  place it on kill ring."
+  (interactive)
+  (let* ((rv (xwidget-webkit-execute-script-rv (xwidget-webkit-current-session)
+                                               "document.URL"))
+         (url (kill-new (or rv ""))))
+    (message "url: %s" url)
+    url))
+
+(defun xwidget-webkit-execute-script-rv (xw script &optional default)
+  "Same as 'xwidget-webkit-execute-script' but but with return value.
+XW is the webkit instance.  SCRIPT is the script to execute.
+DEFAULT is the defaultreturn value."
+  ;; Notice the ugly "title" hack.  It is needed because the Webkit
+  ;; API at the time of writing didn't support returning values.  This
+  ;; is a wrapper for the title hack so it's easy to remove should
+  ;; Webkit someday support JS return values or we find some other way
+  ;; to access the DOM.
+
+  ;; Reset webkit title.  Not very nice.
+  (let* ((emptytag "titlecantbewhitespaceohthehorror")
+         title)
+    (xwidget-webkit-execute-script xw (format "document.title=\"%s\";"
+                                              (or default emptytag)))
+    (xwidget-webkit-execute-script xw (format "document.title=%s;" script))
+    (setq title (xwidget-webkit-get-title xw))
+    (if (equal emptytag title)
+        (setq title ""))
+    (unless title
+      (setq title default))
+    title))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defun xwidget-webkit-get-selection ()
+  "Get the webkit selection."
+  (xwidget-webkit-execute-script-rv (xwidget-webkit-current-session)
+                                    "window.getSelection().toString();"))
+
+(defun xwidget-webkit-copy-selection-as-kill ()
+  "Get the webkit selection and put it on the kill ring."
+  (interactive)
+  (kill-new (xwidget-webkit-get-selection)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Xwidget plist management (similar to the process plist functions)
+
+(defun xwidget-get (xwidget propname)
+  "Return the value of XWIDGET' PROPNAME property.
+This is the last value stored with `(xwidget-put XWIDGET PROPNAME VALUE)'."
+  (plist-get (xwidget-plist xwidget) propname))
+
+(defun xwidget-put (xwidget propname value)
+  "Change XWIDGET' PROPNAME property to VALUE.
+It can be retrieved with `(xwidget-get XWIDGET PROPNAME)'."
+  (set-xwidget-plist xwidget
+                     (plist-put (xwidget-plist xwidget) propname value)))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar xwidget-view-list)              ; xwidget.c
+(defvar xwidget-list)                   ; xwidget.c
+
+(defun xwidget-delete-zombies ()
+  "Helper for `xwidget-cleanup'."
+  (dolist (xwidget-view xwidget-view-list)
+    (when (or (not (window-live-p (xwidget-view-window xwidget-view)))
+              (not (memq (xwidget-view-model xwidget-view)
+                         xwidget-list)))
+      (delete-xwidget-view xwidget-view))))
+
+(defun xwidget-cleanup ()
+  "Delete zombie xwidgets."
+  ;; During development it was sometimes easy to wind up with zombie
+  ;; xwidget instances.
+  ;; This function tries to implement a workaround should it occur again.
+  (interactive)
+  ;; Kill xviews that should have been deleted but still linger.
+  (xwidget-delete-zombies)
+  ;; Redraw display otherwise ghost of zombies will remain to haunt the screen
+  (redraw-display))
+
+(defun xwidget-kill-buffer-query-function ()
+  "Ask before killing a buffer that has xwidgets."
+  (let ((xwidgets (get-buffer-xwidgets (current-buffer))))
+    (or (not xwidgets)
+        (not (memq t (mapcar #'xwidget-query-on-exit-flag xwidgets)))
+        (yes-or-no-p
+         (format "Buffer %S has xwidgets; kill it? " (buffer-name))))))
+
+(when (featurep 'xwidget-internal)
+  (add-hook 'kill-buffer-query-functions #'xwidget-kill-buffer-query-function)
+  ;; This would have felt better in C, but this seems to work well in
+  ;; practice though.
+  (add-hook 'window-configuration-change-hook #'xwidget-delete-zombies))
+
+(provide 'xwidget)
+;;; xwidget.el ends here
diff --git a/src/Makefile.in b/src/Makefile.in
index defce62..b38e7d5 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@
+
 address@hidden@
 
 SETTINGS_CFLAGS = @SETTINGS_CFLAGS@
@@ -220,6 +223,9 @@ CFLAGS_SOUND= @CFLAGS_SOUND@
 RSVG_LIBS= @RSVG_LIBS@
 RSVG_CFLAGS= @RSVG_CFLAGS@
 
+WEBKIT_LIBS= @WEBKIT_LIBS@
+WEBKIT_CFLAGS= @WEBKIT_CFLAGS@
+
 CAIRO_LIBS= @CAIRO_LIBS@
 CAIRO_CFLAGS= @CAIRO_CFLAGS@
 
@@ -359,6 +365,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) \
   $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
   $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
   $(LIBGNUTLS_CFLAGS) $(NOTIFY_CFLAGS) $(CAIRO_CFLAGS) \
@@ -388,6 +395,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)
@@ -468,6 +476,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) \
    $(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 4df77a1..51bbad7 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -43,6 +43,9 @@ along with GNU Emacs.  If not, see 
<http://www.gnu.org/licenses/>.  */
 #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 bb876f5..fad5bfd 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 8d671f8..32c0dff 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -44,6 +44,10 @@ along with GNU Emacs.  If not, see 
<http://www.gnu.org/licenses/>.  */
 #include TERM_HEADER
 #endif /* HAVE_WINDOW_SYSTEM */
 
+#ifdef HAVE_XWIDGETS
+# include "xwidget.h"
+#endif
+
 #include <errno.h>
 
 #include <fpending.h>
@@ -3543,6 +3547,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;
@@ -4116,6 +4123,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 aaf058e..fcf048c 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -66,6 +66,9 @@ along with GNU Emacs.  If not, see 
<http://www.gnu.org/licenses/>.  */
 #include "buffer.h"
 #include "window.h"
 
+#ifdef HAVE_XWIDGETS
+# include "xwidget.h"
+#endif
 #include "atimer.h"
 #include "blockinput.h"
 #include "syssignal.h"
@@ -1492,6 +1495,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 cdcaf80..08b8403 100644
--- a/src/emacsgtkfixed.c
+++ b/src/emacsgtkfixed.c
@@ -23,6 +23,9 @@ along with GNU Emacs.  If not, see 
<http://www.gnu.org/licenses/>.  */
 #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 
<http://www.gnu.org/licenses/>.  */
 # 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,103 @@ 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;
+};
+
+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,15 +154,20 @@ 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)
 {
-  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;
 }
@@ -97,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 73280b8..378bd2b 100644
--- a/src/emacsgtkfixed.h
+++ b/src/emacsgtkfixed.h
@@ -27,6 +27,26 @@ struct frame;
 
 G_BEGIN_DECLS
 
+struct frame;
+
+//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);
 
 G_END_DECLS
diff --git a/src/keyboard.c b/src/keyboard.c
index c8a9728..fe503b8 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -4014,6 +4014,13 @@ kbd_buffer_get_event (KBOARD **kbp,
          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)
        {
          obj = make_lispy_event (&event->ie);
@@ -5950,6 +5957,13 @@ 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_INOTIFY || defined HAVE_KQUEUE || defined HAVE_GFILENOTIFY
     case FILE_NOTIFY_EVENT:
       {
@@ -10956,6 +10970,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 02b8078..8aa034e9 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 269d8f2..4dd4e96 100644
--- a/src/print.c
+++ b/src/print.c
@@ -33,6 +33,10 @@ along with GNU Emacs.  If not, see 
<http://www.gnu.org/licenses/>.  */
 #include "intervals.h"
 #include "blockinput.h"
 
+#ifdef HAVE_XWIDGETS
+# include "xwidget.h"
+#endif
+
 #include <c-ctype.h>
 #include <float.h>
 #include <ftoastr.h>
@@ -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 ("#<xwidget ", printcharfun);
+         printchar ('>', printcharfun);
+       }
+      else if (XWIDGET_VIEW_P (obj))
+       {
+         print_c_string ("#<xwidget ", printcharfun);
+         printchar ('>', printcharfun);
+       }
+#endif
       else if (WINDOWP (obj))
        {
          int len = sprintf (buf, "#<window %"pI"d",
diff --git a/src/termhooks.h b/src/termhooks.h
index 2922375..c183528 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -239,6 +239,11 @@ enum event_kind
   , NS_NONKEY_EVENT
 #endif
 
+#ifdef HAVE_XWIDGETS
+  /* events generated by xwidgets*/
+   , XWIDGET_EVENT
+#endif
+
 #ifdef USE_FILE_NOTIFY
   /* File or directory was changed.  */
   , FILE_NOTIFY_EVENT
diff --git a/src/window.c b/src/window.c
index 4aeb8b3..add2de3 100644
--- a/src/window.c
+++ b/src/window.c
@@ -41,6 +41,9 @@ along with GNU Emacs.  If not, see 
<http://www.gnu.org/licenses/>.  */
 #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 **,
@@ -4368,6 +4371,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 d730a0b..89385c0 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -318,6 +318,9 @@ along with GNU Emacs.  If not, see 
<http://www.gnu.org/licenses/>.  */
 #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 5a6d643..44eed22 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -62,6 +62,9 @@ along with GNU Emacs.  If not, see 
<http://www.gnu.org/licenses/>.  */
 #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 0000000..ea5dea0
--- /dev/null
+++ b/src/xwidget.c
@@ -0,0 +1,1320 @@
+/* Support for embedding graphical components in a buffer.
+
+Copyright (C) 2011-2016 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 <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+
+#include <signal.h>
+
+#include <stdio.h>
+#include <setjmp.h>
+#ifdef HAVE_X_WINDOWS
+
+#include "lisp.h"
+#include "blockinput.h"
+#include "syssignal.h"
+
+#include "xterm.h"
+#include <X11/cursorfont.h>
+
+#ifndef makedev
+# include <sys/types.h>
+#endif
+
+#ifdef BSD_SYSTEM
+# include <sys/ioctl.h>
+#endif
+
+#include "systime.h"
+
+#ifndef INCLUDED_FCNTL
+# include <fcntl.h>
+#endif
+#include <ctype.h>
+#include <errno.h>
+#include <setjmp.h>
+#include <sys/stat.h>
+
+#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 <X11/Shell.h>
+#endif
+#include <X11/extensions/Xcomposite.h>
+#include <X11/extensions/Xrender.h>
+#include <cairo.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "gtkutil.h"
+#include "font.h"
+#endif /* HAVE_X_WINDOWS */
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include <gtk/gtkx.h>
+
+#include "emacsgtkfixed.h"
+
+#include <wchar.h>
+
+#include <webkit/webkitwebview.h>
+#include <webkit/webkitwebplugindatabase.h>
+#include <webkit/webkitwebplugin.h>
+#include <webkit/webkitglobals.h>
+#include <webkit/webkitwebnavigationaction.h>
+#include <webkit/webkitdownload.h>
+#include <webkit/webkitwebpolicydecision.h>
+
+#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))
+
+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);
+
+static gboolean
+webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *,
+                                                   WebKitWebFrame *,
+                                                   WebKitNetworkRequest *,
+                                                   gchar *,
+                                                   WebKitWebPolicyDecision *,
+                                                   gpointer);
+
+static gboolean
+webkit_new_window_policy_decision_requested_cb (WebKitWebView *,
+                                                WebKitWebFrame *,
+                                                WebKitNetworkRequest *,
+                                                WebKitWebNavigationAction *,
+                                                WebKitWebPolicyDecision *,
+                                                gpointer);
+
+static 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, 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.  */)
+  (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.  */
+static 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;
+}
+
+static 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;
+    }
+}
+
+
+static 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;
+}
+
+static 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: /* 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)
+{
+  // 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 define 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 an 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 an 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 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);
+
+  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 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);
+  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 the 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);
+
+  defsubr (&Sxwidget_webkit_goto_uri);
+  defsubr (&Sxwidget_webkit_execute_script);
+  defsubr (&Sxwidget_webkit_get_title);
+  DEFSYM (Qwebkit_osr, "webkit-osr");
+
+  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.  */
+static 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));
+            }
+        }
+    }
+}
+
+static 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  */
+static 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.  */
+static 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 0000000..fdcf40d
--- /dev/null
+++ b/src/xwidget.h
@@ -0,0 +1,132 @@
+/* Support for embedding graphical components in a buffer.
+
+Copyright (C) 2011-2016 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 <http://www.gnu.org/licenses/>.  */
+
+#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 <gtk/gtk.h>
+
+
+/*
+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_end_redisplay (struct window *w, struct glyph_matrix *matrix);
+
+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 */
diff --git a/test/manual/indent/ruby.rb b/test/manual/indent/ruby.rb
index dec6de9..dfd1c75 100644
--- a/test/manual/indent/ruby.rb
+++ b/test/manual/indent/ruby.rb
@@ -4,6 +4,10 @@ if something_wrong?             # 
ruby-move-to-block-skips-heredoc
   end
   eowarn
   foo
+
+  foo(<<~squiggly)
+  end
+  squiggly
 end
 
 def foo



reply via email to

[Prev in Thread] Current Thread [Next in Thread]