aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2016-01-30 11:27:34 -0800
committerPaul Eggert2016-01-30 11:27:34 -0800
commit82b089783e71b2aeef950eaecfe4cbc0735e64a2 (patch)
treea826c20768071bda95a69b2632718c1641c6d0cc
parentd27c8078ef766dae3587bc82b70128a70efaa223 (diff)
parentf7dc6d8b5bb318e02a4016d93f8b34de0716f4dc (diff)
downloademacs-82b089783e71b2aeef950eaecfe4cbc0735e64a2.tar.gz
emacs-82b089783e71b2aeef950eaecfe4cbc0735e64a2.zip
-
-rw-r--r--configure.ac32
-rw-r--r--doc/emacs/anti.texi249
-rw-r--r--doc/emacs/emacs.texi2
-rw-r--r--doc/emacs/maintaining.texi33
-rw-r--r--doc/lispref/variables.texi4
-rw-r--r--etc/NEWS15
-rw-r--r--lisp/calendar/todo-mode.el10
-rw-r--r--lisp/doc-view.el7
-rw-r--r--lisp/emacs-lisp/pcase.el47
-rw-r--r--lisp/gnus/nnir.el6
-rw-r--r--lisp/htmlfontify.el14
-rw-r--r--lisp/image-mode.el43
-rw-r--r--lisp/international/mule-cmds.el2
-rw-r--r--lisp/international/quail.el2
-rw-r--r--lisp/isearch.el13
-rw-r--r--lisp/net/shr.el2
-rw-r--r--lisp/progmodes/ruby-mode.el2
-rw-r--r--lisp/progmodes/xref.el8
-rw-r--r--lisp/xwidget.el580
-rw-r--r--src/Makefile.in9
-rw-r--r--src/buffer.c6
-rw-r--r--src/dispextern.h28
-rw-r--r--src/dispnew.c12
-rw-r--r--src/emacs.c6
-rw-r--r--src/emacsgtkfixed.c123
-rw-r--r--src/emacsgtkfixed.h20
-rw-r--r--src/keyboard.c18
-rw-r--r--src/lisp.h6
-rw-r--r--src/print.c16
-rw-r--r--src/termhooks.h5
-rw-r--r--src/window.c6
-rw-r--r--src/xdisp.c248
-rw-r--r--src/xterm.c14
-rw-r--r--src/xwidget.c1320
-rw-r--r--src/xwidget.h132
-rw-r--r--test/manual/indent/ruby.rb4
36 files changed, 2873 insertions, 171 deletions
diff --git a/configure.ac b/configure.ac
index d3b518366ef..50bc04b4c87 100644
--- a/configure.ac
+++ b/configure.ac
@@ -374,6 +374,9 @@ otherwise for the first of 'inotify', 'kqueue' or 'gfile' that is usable.])
374 ], 374 ],
375 [with_file_notification=$with_features]) 375 [with_file_notification=$with_features])
376 376
377OPTION_DEFAULT_OFF([xwidgets],
378 [enable use of some gtk widgets in Emacs buffers (requires gtk3)])
379
377## For the times when you want to build Emacs but don't have 380## For the times when you want to build Emacs but don't have
378## a suitable makeinfo, and can live without the manuals. 381## a suitable makeinfo, and can live without the manuals.
379dnl http://lists.gnu.org/archive/html/emacs-devel/2008-04/msg01844.html 382dnl http://lists.gnu.org/archive/html/emacs-devel/2008-04/msg01844.html
@@ -2563,6 +2566,26 @@ if test "${HAVE_GTK}" = "yes"; then
2563 term_header=gtkutil.h 2566 term_header=gtkutil.h
2564fi 2567fi
2565 2568
2569
2570dnl Enable xwidgets if GTK3 and WebKitGTK+ are available.
2571HAVE_XWIDGETS=no
2572XWIDGETS_OBJ=
2573if test "$with_xwidgets" != "no"; then
2574 test "$USE_GTK_TOOLKIT" = "GTK3" && test "$window_system" != "none" ||
2575 AC_MSG_ERROR([xwidgets requested but gtk3 not used.])
2576
2577 WEBKIT_REQUIRED=1.4.0
2578 WEBKIT_MODULES="webkitgtk-3.0 >= $WEBKIT_REQUIRED"
2579 EMACS_CHECK_MODULES([WEBKIT], [$WEBKIT_MODULES])
2580 HAVE_XWIDGETS=$HAVE_WEBKIT
2581 test $HAVE_XWIDGETS = yes ||
2582 AC_MSG_ERROR([xwidgets requested but WebKitGTK+ not found.])
2583
2584 XWIDGETS_OBJ=xwidget.o
2585 AC_DEFINE([HAVE_XWIDGETS], 1, [Define to 1 if you have xwidgets support.])
2586fi
2587AC_SUBST(XWIDGETS_OBJ)
2588
2566CFLAGS=$OLD_CFLAGS 2589CFLAGS=$OLD_CFLAGS
2567LIBS=$OLD_LIBS 2590LIBS=$OLD_LIBS
2568 2591
@@ -3123,7 +3146,7 @@ if test "${HAVE_X11}" = "yes"; then
3123 if test "${with_cairo}" != "no"; then 3146 if test "${with_cairo}" != "no"; then
3124 CAIRO_REQUIRED=1.12.0 3147 CAIRO_REQUIRED=1.12.0
3125 CAIRO_MODULE="cairo >= $CAIRO_REQUIRED" 3148 CAIRO_MODULE="cairo >= $CAIRO_REQUIRED"
3126 PKG_CHECK_MODULES(CAIRO, $CAIRO_MODULE, USE_CAIRO=yes, :) 3149 EMACS_CHECK_MODULES(CAIRO, $CAIRO_MODULE, USE_CAIRO=yes, :)
3127 if test $USE_CAIRO = yes; then 3150 if test $USE_CAIRO = yes; then
3128 AC_DEFINE(USE_CAIRO, 1, [Define to 1 if using cairo.]) 3151 AC_DEFINE(USE_CAIRO, 1, [Define to 1 if using cairo.])
3129 else 3152 else
@@ -4948,6 +4971,9 @@ case "$USE_X_TOOLKIT" in
4948 LUCID) TOOLKIT_LIBW="$LUCID_LIBW" ;; 4971 LUCID) TOOLKIT_LIBW="$LUCID_LIBW" ;;
4949 none) test "x$HAVE_GTK" = "xyes" && TOOLKIT_LIBW="$GTK_LIBS" ;; 4972 none) test "x$HAVE_GTK" = "xyes" && TOOLKIT_LIBW="$GTK_LIBS" ;;
4950esac 4973esac
4974if test "$HAVE_XWIDGETS" = "yes"; then
4975 TOOLKIT_LIBW="$TOOLKIT_LIBW -lXcomposite"
4976fi
4951AC_SUBST(TOOLKIT_LIBW) 4977AC_SUBST(TOOLKIT_LIBW)
4952 4978
4953if test "${opsys}" != "mingw32"; then 4979if test "${opsys}" != "mingw32"; then
@@ -5237,7 +5263,8 @@ optsep=
5237emacs_config_features= 5263emacs_config_features=
5238for opt in XAW3D XPM JPEG TIFF GIF PNG RSVG CAIRO IMAGEMAGICK SOUND GPM DBUS \ 5264for opt in XAW3D XPM JPEG TIFF GIF PNG RSVG CAIRO IMAGEMAGICK SOUND GPM DBUS \
5239 GCONF GSETTINGS NOTIFY ACL LIBSELINUX GNUTLS LIBXML2 FREETYPE M17N_FLT \ 5265 GCONF GSETTINGS NOTIFY ACL LIBSELINUX GNUTLS LIBXML2 FREETYPE M17N_FLT \
5240 LIBOTF XFT ZLIB TOOLKIT_SCROLL_BARS X_TOOLKIT X11 NS MODULES; do 5266 LIBOTF XFT ZLIB TOOLKIT_SCROLL_BARS X_TOOLKIT X11 NS MODULES \
5267 XWIDGETS; do
5241 5268
5242 case $opt in 5269 case $opt in
5243 NOTIFY|ACL) eval val=\${${opt}_SUMMARY} ;; 5270 NOTIFY|ACL) eval val=\${${opt}_SUMMARY} ;;
@@ -5287,6 +5314,7 @@ AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D
5287 Does Emacs directly use zlib? ${HAVE_ZLIB} 5314 Does Emacs directly use zlib? ${HAVE_ZLIB}
5288 Does Emacs have dynamic modules support? ${HAVE_MODULES} 5315 Does Emacs have dynamic modules support? ${HAVE_MODULES}
5289 Does Emacs use toolkit scroll bars? ${USE_TOOLKIT_SCROLL_BARS} 5316 Does Emacs use toolkit scroll bars? ${USE_TOOLKIT_SCROLL_BARS}
5317 Does Emacs support Xwidgets (requires gtk3)? ${HAVE_XWIDGETS}
5290"]) 5318"])
5291 5319
5292if test -n "${EMACSDATA}"; then 5320if test -n "${EMACSDATA}"; then
diff --git a/doc/emacs/anti.texi b/doc/emacs/anti.texi
index 26e3d2e337f..ae13ae09a04 100644
--- a/doc/emacs/anti.texi
+++ b/doc/emacs/anti.texi
@@ -1,113 +1,218 @@
1@c -*- coding: utf-8 -*-
1@c This is part of the Emacs manual. 2@c This is part of the Emacs manual.
2@c Copyright (C) 2005-2016 Free Software Foundation, Inc. 3@c Copyright (C) 2005-2016 Free Software Foundation, Inc.
3@c See file emacs.texi for copying conditions. 4@c See file emacs.texi for copying conditions.
4 5
5@node Antinews 6@node Antinews
6@appendix Emacs 23 Antinews 7@appendix Emacs 24 Antinews
7@c Update the emacs.texi Antinews menu entry with the above version number. 8@c Update the emacs.texi Antinews menu entry with the above version number.
8 9
9 For those users who live backwards in time, here is information 10 For those users who live backwards in time, here is information
10about downgrading to Emacs version 23.4. We hope you will enjoy the 11about downgrading to Emacs version 24.5. We hope you will enjoy the
11greater simplicity that results from the absence of many Emacs 12greater simplicity that results from the absence of many Emacs
12@value{EMACSVER} features. 13@value{EMACSVER} features.
13 14
14@itemize @bullet 15@itemize @bullet
15@item 16@item
16Support for displaying and editing ``bidirectional'' text has been 17Support for Cairo drawing has been removed. On GNU and Unix systems,
17removed. Text is now always displayed on the screen in a single 18you now have only one drawing engine---the venerable X Window system.
18consistent direction---left to right---regardless of the underlying 19No need to procrastinate on the dilemma whether you do or don't want
19script. Similarly, @kbd{C-f} and @kbd{C-b} always move the text 20the new shiny Cairo thing. Hail, simplicity!
20cursor to the right and left respectively. Also, @key{RIGHT} and
21@key{LEFT} are now equivalent to @kbd{C-f} and @kbd{C-b}, as you might
22expect, rather than moving forward or backward based on the underlying
23``paragraph direction''.
24 21
25Users of right-to-left languages, like Arabic and Hebrew, may 22@item
26adapt by reading and/or editing text in left-to-right order. 23Emacs still works on SGI IRIX systems. if you live backwards in time,
24this is actually a bonus, as IRIX systems will become more and more
25popular as you move farther back in time.
26
27@item
28Support for dynamically loaded modules has been removed. You get to
29use only the trusted Emacs codebase, with no additions. Those
30external modules written by some J.R. Hacker cannot be trusted anyway.
31Good riddance!
32
33@item
34We have greatly simplified the Emacs features which access the network
35by removing the Network Security Manager. No more annoying prompts
36about trusting this or that site or page---you asked for it, you get
37it, no questions asked! You, the user, are now in charge of any
38security issues related to sites whose certificates expired or didn't
39exist in the first place. Giving the user the utmost freedom was and
40always will be the most important goal of Emacs development. We keep
41that goal even as we develop Emacs back in time.
42
43@item
44We made the output of @kbd{C-h l} much simpler and easier to grasp by
45removing the names of commands run by the recorded keystrokes. True
46Emacs lovers know their bindings by heart anyway, so why waste
47precious screen estate on that which is well known?
48
49@item
50Selection- and clipboard-related commands and variables got their
51historical names back. It's now the definitive
52@code{x-select-enable-clipboard} again instead of the vague
53@code{select-enable-clipboard}, and all those @code{gui-select-text},
54@code{gui-get-primary-selection}, etc.@: got their @code{x-*} names
55back. (What's a ``GUI'', anyway?) The only true window system with
56selections is the X Window system, so we stopped pretending that other
57platforms have anything similar to that. You now know when you invoke
58a command that accesses X.
59
60@item
61Passwords are no longer hidden when typed in @code{-batch} mode. It
62was a misfeature to have it not shown in the first place: who can type
63without seeing what they type? We couldn't convince the users of GUI
64sessions to give up hiding the password, so we at least made it
65visible in batch mode, which is something every veteran Emacs user
66uses all the time. Stay tuned for un-hiding the password in GUI
67sessions as well as we downgrade progressively to previous Emacs
68versions.
27 69
28@item 70@item
29The Emacs Lisp package manager has been removed. Instead of using a 71The nuisance with Unicode characters popping up all over the place has
30user interface (@kbd{M-x list-packages}), additional Lisp packages 72been amply dealt with. We've removed @kbd{C-x 8} shorthands for
31must now be installed by hand, which is the most flexible and 73characters such as ‘, ’, “, ”, €, ≤, and many others; as a nice
32``Lispy'' method anyway. Typically, this just involves editing your 74benefit, this removes many useless entries at the beginning of the
33init file to add the package installation directory to the load path 75@kbd{C-h b} output. The @code{electric-quote-mode} has been deleted,
34and defining some autoloads; see each package's commentary section 76so there's only the one true quoting method now---using the
35and/or README file for details. 77plain-@acronym{ASCII} quote characters. And if that's not enough, the
78doc strings and other messages show text quoted `like this' and "like
79this" as they were written, instead of arbitrarily replacing them
80with Unicode ``curved quote'' characters. The
81@code{text-quoting-style} variable becomes therefore unneeded and was
82removed. As result, text produced by Emacs can be sent to those
83venerable teletypes again, yeah!
84
85For the same reasons, the character classes @code{[:alpha:]} and
86@code{[:alnum:]} again match any word-constituent character, and
87@code{[:graph:]} and @code{[:print:]} match every multibyte character.
88Confusing use of Unicode character properties is gone.
36 89
37@item 90@item
38The option @code{delete-active-region} has been deleted. When the 91I-search and query-replace no longer try to confuse you by using the
39region is active, typing @key{DEL} or @key{Delete} no longer deletes 92``character-folding'' magic. They will no longer find any characters
40the text in the region; it deletes a single character instead. 93you didn't actually type, like find @kbd{ⓐ} when you actually typed
94@kbd{a}. Users who want to find some fancy character will have to
95type it explicitly.
41 96
42@item 97@item
43We have reworked how Emacs handles the clipboard and the X primary 98The @file{desktop.el} package no longer records window and frame
44selection. Commands for killing and yanking, like @kbd{C-w} and 99configuration, and doesn't attempt to restore them. You now have back
45@kbd{C-y}, use the primary selection and not the clipboard, so you can 100your freedom of re-arranging your windows and frames anew each time
46use these commands without interfering with ``cutting'' or ``pasting'' 101you restore a session. This made the new backward-incompatible format
47in other programs. The @samp{Cut}/@samp{Copy}/@samp{Paste} menu items 102of the @file{.emacs.desktop} file unnecessary, so the format was
48are bound to separate clipboard commands, not to the same commands as 103reverted back to what it was before Emacs 25. You can now again use
49@kbd{C-w}/@kbd{M-w}/@kbd{C-y}. 104the desktop file with all the previous versions of Emacs.
50 105
51Selecting text by dragging with the mouse now puts the text in the 106@item
52kill ring, in addition to the primary selection. But note that 107We have reworked the Prettify Symbols mode to support only the default
53selecting an active region with @kbd{C-@key{SPC}} does @emph{not} 108@code{prettify-symbols-compose-predicate}. No need to consider
54alter the kill ring nor the primary selection, even though the text 109whether your major or minor mode needs its own prettifications; just
55highlighting is visually identical. 110use what came with Emacs. We also removed the
111@code{prettify-symbols-unprettify-at-point} option: once prettified,
112always prettified! These changes make the Prettify Symbols mode quite
113a lot simpler and easier to use.
114
115@item
116Support for nifty new features of xterm, such as access to the X
117selection and the clipboard, the ``bracketed paste mode'', and other
118advanced capabilities has been removed. When you kill text in an
119xterm Emacs session, that text is only saved in the Emacs kill ring,
120without letting other applications have any way of accessing it. An
121xterm is just a text terminal, nothing more, nothing less. There
122should be no feature we support on xterm that isn't supported on bare
123console terminals. For the same reasons, support for mouse-tracking
124on xterm was removed. We will continue this line of simplifications
125as we downgrade to previous versions of Emacs; stay tuned.
126
127@item
128Various features in @file{package.el} have been simplified. The
129``external'' package status is no longer available. A package present
130on multiple archives will now be listed as many times as it is found:
131we don't believe in concealing any information from the users. This
132and other similar simplifications made
133@code{package-menu-toggle-hiding} unnecessary, since there's nothing
134to unhide now.
135
136@item
137The @kbd{@key{UP}} and @kbd{@key{DOWN}} keys in the minibuffer have
138been simplified to move by history items. No need to wonder whether
139you have moved to the next/previous item or to another line within the
140same item. Well-written commands shouldn't allow too long history
141entries anyway; be sure to report any that do as bugs, so that we
142could fix them in past versions of Emacs.
143
144@item
145The VC mode was simplified by removing the support for ``push''
146commands. Moving back in time means you will have less and less need
147to use modern version control systems such as Git, Bazaar, and
148Mercurial, so the necessity of using ``push'' commands will gradually
149disappear. We removed it from Emacs in advance, so that you won't
150need to un-learn it when this command disappears, as it should.
151
152@item
153The support for full C/C++ expressions in macros has been removed from
154Hide-Ifdef mode. It now supports only the basic literal macros. As
155result, the user interface was simplified, and a number of useless
156commands have been removed from Hide-Ifdef mode. Further
157simplifications were made possible by removing support for some fancy
158new preprocessor directives, such as @code{#if defined}, @code{#elif},
159etc.
56 160
57@item 161@item
58In Isearch, @kbd{C-y} and @kbd{M-y} are no longer bound to 162We have reverted to Etags for looking up definitions of functions,
59@code{isearch-yank-kill} and @code{isearch-yank-pop} respectively. 163variables, etc. Commands such as @kbd{M-.} use tags tables, as they
60Instead, @kbd{C-y} yanks the rest of the current line into the search 164always have. This allowed the removal of the entire @file{xref.el}
61string (@code{isearch-yank-line}), whereas @kbd{M-y} does 165package and its many metastases in the other Emacs packages and
62@code{isearch-yank-kill}. The mismatch with the usual meanings of 166commands, significantly simplifying those. No more complexities with
63@kbd{C-y} and @kbd{M-y} is unintended. 167the various ``backends'' that provide incoherent behavior that is hard
168to explain and remember; either the symbol is in TAGS or it isn't. No
169more new user interfaces we never before saw in Emacs, either; if you
170want the next definition for the symbol you typed, just invoke
171@kbd{C-u M-.}---what could be simpler? As a nice side effect, you get
172to use your beloved @code{tags-loop-continue} and @code{pop-tag-mark}
173commands and their memorable bindings. The @file{package.el} package
174has been removed for similar reasons.
64 175
65@item 176@item
66Various completion features have been simplified. The option 177@code{(/ @var{n})} once again yields just @var{n}. Emacs Lisp is not
67@code{completion-category-overrides} has been removed, so Emacs uses a 178Common Lisp, so compatibility with CL just complicates Emacs here.
68single consistent scheme to generate completions, instead of using a
69separate scheme for (say) buffer name completion. Several major
70modes, such as Shell mode, now implement their own inline completion
71commands instead of using @code{completion-at-point}.
72 179
73@item 180@item
74We have removed several options for controlling how windows are used, 181The functions @code{filepos-to-bufferpos} and
75such as @code{display-buffer-base-action}, 182@code{bufferpos-to-filepos} have been removed. Code that needs to
76@code{display-buffer-alist}, @code{window-combination-limit}, and 183find a file position by a buffer position or vice versa should adapt
77@code{window-combination-resize}. 184by reading the file with no conversions and counting bytes while
185comparing text. How hard can that be?
78 186
79@item 187@item
80The command @kbd{M-x customize-themes} has been removed. Emacs no 188We saw no need for the @code{make-process} primitive, so we removed
81longer comes with pre-defined themes (you can write your own). 189it. The @code{start-process} primitive provides all the functionality
190one needs, so adding more APIs just confuses users.
82 191
83@item 192@item
84Emacs no longer adapts various aspects of its display to GTK+ 193The functions @code{bidi-find-overridden-directionality} and
85settings, opting instead for a uniform toolkit-independent look. GTK+ 194@code{buffer-substring-with-bidi-context} were removed, in preparation
86scroll bars are placed on the left, the same position as non-GTK+ X 195for removing the whole bidi support when downgrading to Emacs 23.
87scroll bars. Emacs no longer refers to GTK+ to set the default
88@code{region} face, nor for drawing tooltips.
89 196
90@item 197@item
91Setting the option @code{delete-by-moving-to-trash} to a 198Horizontal scroll bars are no longer supported. Enlarge your windows
92non-@code{nil} value now causes all file deletions to use the system trash, 199and frames instead, or use @code{truncate-lines} and the automatic
93even temporary files created by Lisp programs; furthermore, the 200horizontal scrolling of text that Emacs had since time immemoriam.
94@kbd{M-x delete-file} and @kbd{M-x delete-directory} commands no
95longer accept prefix arguments to force true deletion.
96 201
97@item 202@item
98On GNU/Linux and Unix, the default method for sending mail (as 203Emacs is again counting the height of a frame's menu and its tool bar
99specified by @code{send-mail-function}) is to use the 204in the frame's text height calculations. This makes Emacs invocation
100@command{sendmail} program. Emacs no longer asks for a delivery 205on different platforms and with different toolkits less predictable
101method the first time you try to send mail, trusting instead that the 206when frame geometry parameters are given on the Emacs command line,
102system is configured for mail delivery, as it ought to be. 207thus making Emacs more adventurous and less boring to use.
103 208
104@item 209@item
105Several VC features have been removed, including the @kbd{C-x v +} and 210The @command{etags} program no longer supports Ruby and Go languages.
106@kbd{C-x v m} commands for pulling and merging on distributed version 211You won't need that as you progressively travel back in time towards
107control systems, and the ability to view inline log entries in the log 212the time before these languages were invented. We removed support for
108buffers made by @kbd{C-x v L}. 213them in anticipation for that time.
109 214
110@item 215@item
111To keep up with decreasing computer memory capacity and disk space, many 216To keep up with decreasing computer memory capacity and disk space, many
112other functions and files have been eliminated in Emacs 23.4. 217other functions and files have been eliminated in Emacs 24.5.
113@end itemize 218@end itemize
diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi
index 5ef938566de..ac8988b4020 100644
--- a/doc/emacs/emacs.texi
+++ b/doc/emacs/emacs.texi
@@ -221,7 +221,7 @@ Appendices
221* GNU Free Documentation License:: The license for this documentation. 221* GNU Free Documentation License:: The license for this documentation.
222* Emacs Invocation:: Hairy startup options. 222* Emacs Invocation:: Hairy startup options.
223* X Resources:: X resources for customizing Emacs. 223* X Resources:: X resources for customizing Emacs.
224* Antinews:: Information about Emacs version 23. 224* Antinews:: Information about Emacs version 24.
225* Mac OS / GNUstep:: Using Emacs under Mac OS and GNUstep. 225* Mac OS / GNUstep:: Using Emacs under Mac OS and GNUstep.
226* Microsoft Windows:: Using Emacs on Microsoft Windows and MS-DOS. 226* Microsoft Windows:: Using Emacs on Microsoft Windows and MS-DOS.
227* Manifesto:: What's GNU? Gnu's Not Unix! 227* Manifesto:: What's GNU? Gnu's Not Unix!
diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi
index 989d8ff7485..90af5c8b17d 100644
--- a/doc/emacs/maintaining.texi
+++ b/doc/emacs/maintaining.texi
@@ -1990,8 +1990,8 @@ Searching}.
1990@table @kbd 1990@table @kbd
1991@item C-M-i 1991@item C-M-i
1992@itemx M-@key{TAB} 1992@itemx M-@key{TAB}
1993Perform completion on the text around point, using the selected tags 1993Perform completion on the text around point, possibly using the
1994table if one is loaded (@code{completion-at-point}). 1994selected tags table if one is loaded (@code{completion-at-point}).
1995@item M-x xref-find-apropos @key{RET} @var{regexp} @key{RET} 1995@item M-x xref-find-apropos @key{RET} @var{regexp} @key{RET}
1996Display a list of all known identifiers matching @var{regexp}. 1996Display a list of all known identifiers matching @var{regexp}.
1997@item M-x list-tags @key{RET} @var{file} @key{RET} 1997@item M-x list-tags @key{RET} @var{file} @key{RET}
@@ -2004,9 +2004,10 @@ Visit files recorded in the selected tags table.
2004@cindex completion (symbol names) 2004@cindex completion (symbol names)
2005 In most programming language modes, you can type @kbd{C-M-i} or 2005 In most programming language modes, you can type @kbd{C-M-i} or
2006@kbd{M-@key{TAB}} (@code{completion-at-point}) to complete the symbol 2006@kbd{M-@key{TAB}} (@code{completion-at-point}) to complete the symbol
2007at point. If there is a tags table loaded, this command can use it to 2007at point. Some modes provide specialized completion for this command
2008generate completion candidates more intelligently. @xref{Symbol 2008tailored to the mode; for those that don't, if there is a tags table
2009Completion}. 2009loaded, this command can use it to generate completion candidates.
2010@xref{Symbol Completion}.
2010 2011
2011@findex list-tags 2012@findex list-tags
2012 @kbd{M-x list-tags} reads the name of one of the files covered by 2013 @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.
2047@subsection Tags Tables 2048@subsection Tags Tables
2048@cindex tags and tag tables 2049@cindex tags and tag tables
2049 2050
2050@cindex tag 2051 A @dfn{tags table} records the tags@footnote{
2051 A @dfn{tag} is a synonym for identifier reference. @xref{Xref}. 2052A @dfn{tag} is a synonym for identifier reference. Commands and
2052 2053features based on the @code{etags} package traditionally use ``tag''
2053 A @dfn{tags table} records the tags extracted by scanning the source 2054with this meaning, and this subsection follows that tradition.
2054code of a certain program or a certain document. Tags extracted from 2055} extracted by scanning the source code of a certain program or a
2055generated files reference the original files, rather than the 2056certain document. Tags extracted from generated files reference the
2056generated files that were scanned during tag extraction. Examples of 2057original files, rather than the generated files that were scanned
2057generated files include C files generated from Cweb source files, from 2058during tag extraction. Examples of generated files include C files
2058a Yacc parser, or from Lex scanner definitions; @file{.i} preprocessed 2059generated from Cweb source files, from a Yacc parser, or from Lex
2059C files; and Fortran files produced by preprocessing @file{.fpp} 2060scanner definitions; @file{.i} preprocessed C files; and Fortran files
2060source files. 2061produced by preprocessing @file{.fpp} source files.
2061 2062
2062@cindex etags 2063@cindex etags
2063 To produce a tags table, you run the @command{etags} shell command 2064 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 c48af9a40c0..42701614365 100644
--- a/doc/lispref/variables.texi
+++ b/doc/lispref/variables.texi
@@ -2068,7 +2068,7 @@ cdar nthcdr
2068A call to any of the following Emacs-specific functions: 2068A call to any of the following Emacs-specific functions:
2069 2069
2070@smallexample 2070@smallexample
2071default-value process-get 2071alist-get process-get
2072frame-parameter process-sentinel 2072frame-parameter process-sentinel
2073terminal-parameter window-buffer 2073terminal-parameter window-buffer
2074keymap-parent window-display-table 2074keymap-parent window-display-table
@@ -2077,7 +2077,7 @@ overlay-get window-hscroll
2077overlay-start window-parameter 2077overlay-start window-parameter
2078overlay-end window-point 2078overlay-end window-point
2079process-buffer window-start 2079process-buffer window-start
2080process-filter 2080process-filter default-value
2081@end smallexample 2081@end smallexample
2082@end itemize 2082@end itemize
2083 2083
diff --git a/etc/NEWS b/etc/NEWS
index 68e4aac6752..4a370a9c809 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -179,6 +179,20 @@ and can contain escape sequences for command keys, quotes, and the like.
179 179
180* Changes in Emacs 25.1 180* Changes in Emacs 25.1
181 181
182** Xwidgets: a new feature for embedding native widgets inside Emacs buffers.
183If you have gtk3 and webkitgtk3 installed, you can access the
184embedded webkit browser with `M-x xwidget-webkit-browse-url'. This
185opens a new buffer with the embedded browser. The buffer will
186have a new mode, `xwidget-webkit-mode' (similar to `image-mode'),
187which supports the webkit widget.
188
189*** New functions for xwidget-webkit mode `xwidget-webkit-insert-string',
190`xwidget-webkit-adjust-size-dispatch', `xwidget-webkit-back',
191`xwidget-webkit-browse-url', `xwidget-webkit-reload',
192`xwidget-webkit-current-url', `xwidget-webkit-scroll-backward',
193`xwidget-webkit-scroll-forward', `xwidget-webkit-scroll-down',
194`xwidget-webkit-scroll-up'.
195
182+++ 196+++
183** Emacs can now load shared/dynamic libraries (modules). 197** Emacs can now load shared/dynamic libraries (modules).
184A dynamic Emacs module is a shared library that provides additional 198A 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).
1596+++ 1610+++
1597** Function `sort' can deal with vectors. 1611** Function `sort' can deal with vectors.
1598 1612
1613---
1599** Function `system-name' now returns an updated value if the current 1614** Function `system-name' now returns an updated value if the current
1600system's name has changed or if the Emacs process has changed systems, 1615system's name has changed or if the Emacs process has changed systems,
1601and to avoid long waits it no longer consults DNS to canonicalize the 1616and 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 353ca69a1ba..29d8dfcfb7f 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
4654 (goto-char (match-beginning 0)) 4654 (goto-char (match-beginning 0))
4655 (goto-char (point-max))) 4655 (goto-char (point-max)))
4656 (backward-char) 4656 (backward-char)
4657 (when (looking-back "\\[\\([^][]+\\)\\]") 4657 (when (looking-back "\\[\\([^][]+\\)\\]"
4658 (line-beginning-position))
4658 (setq cat (match-string 1)) 4659 (setq cat (match-string 1))
4659 (goto-char (match-beginning 0)) 4660 (goto-char (match-beginning 0))
4660 (replace-match "")) 4661 (replace-match ""))
4661 ;; If the item ends with a non-comment parenthesis not 4662 ;; If the item ends with a non-comment parenthesis not
4662 ;; followed by a period, we lose (but we inherit that 4663 ;; followed by a period, we lose (but we inherit that
4663 ;; problem from the legacy code). 4664 ;; problem from the legacy code).
4665 ;; FIXME: fails on multiline comment
4664 (when (looking-back "(\\(.*\\)) " (line-beginning-position)) 4666 (when (looking-back "(\\(.*\\)) " (line-beginning-position))
4665 (setq comment (match-string 1)) 4667 (setq comment (match-string 1))
4666 (replace-match "") 4668 (replace-match "")
@@ -5230,7 +5232,8 @@ Also preserve category display, if applicable."
5230 (with-current-buffer buffer 5232 (with-current-buffer buffer
5231 (widen) 5233 (widen)
5232 (let ((todo-category-number (cdr (assq 'catnum misc)))) 5234 (let ((todo-category-number (cdr (assq 'catnum misc))))
5233 (todo-category-select)))) 5235 (todo-category-select)
5236 (current-buffer))))
5234 5237
5235(add-to-list 'desktop-buffer-mode-handlers 5238(add-to-list 'desktop-buffer-mode-handlers
5236 '(todo-mode . todo-restore-desktop-buffer)) 5239 '(todo-mode . todo-restore-desktop-buffer))
@@ -6579,8 +6582,7 @@ Added to `window-configuration-change-hook' in Todo mode."
6579 "Make some settings that apply to multiple Todo modes." 6582 "Make some settings that apply to multiple Todo modes."
6580 (add-to-invisibility-spec 'todo) 6583 (add-to-invisibility-spec 'todo)
6581 (setq buffer-read-only t) 6584 (setq buffer-read-only t)
6582 (when (and (boundp 'desktop-save-mode) desktop-save-mode) 6585 (setq-local desktop-save-buffer 'todo-desktop-save-buffer)
6583 (setq-local desktop-save-buffer 'todo-desktop-save-buffer))
6584 (when (boundp 'hl-line-range-function) 6586 (when (boundp 'hl-line-range-function)
6585 (setq-local hl-line-range-function 6587 (setq-local hl-line-range-function
6586 (lambda() (save-excursion 6588 (lambda() (save-excursion
diff --git a/lisp/doc-view.el b/lisp/doc-view.el
index 286811358fb..06cf8dcef3a 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."
1714 ;; window-parameters in the window-state(s) and then restoring this 1714 ;; window-parameters in the window-state(s) and then restoring this
1715 ;; window-state should call us back (to interpret/use those parameters). 1715 ;; window-state should call us back (to interpret/use those parameters).
1716 (doc-view-goto-page page) 1716 (doc-view-goto-page page)
1717 (when slice (apply 'doc-view-set-slice slice))))) 1717 (when slice (apply 'doc-view-set-slice slice))
1718 (current-buffer))))
1718 1719
1719(add-to-list 'desktop-buffer-mode-handlers 1720(add-to-list 'desktop-buffer-mode-handlers
1720 '(doc-view-mode . doc-view-restore-desktop-buffer)) 1721 '(doc-view-mode . doc-view-restore-desktop-buffer))
@@ -1788,9 +1789,7 @@ toggle between displaying the document or editing it as text.
1788 nil t) 1789 nil t)
1789 (add-hook 'clone-indirect-buffer-hook 'doc-view-clone-buffer-hook nil t) 1790 (add-hook 'clone-indirect-buffer-hook 'doc-view-clone-buffer-hook nil t)
1790 (add-hook 'kill-buffer-hook 'doc-view-kill-proc nil t) 1791 (add-hook 'kill-buffer-hook 'doc-view-kill-proc nil t)
1791 (when (and (boundp 'desktop-save-mode) 1792 (setq-local desktop-save-buffer 'doc-view-desktop-save-buffer)
1792 desktop-save-mode)
1793 (setq-local desktop-save-buffer 'doc-view-desktop-save-buffer))
1794 1793
1795 (remove-overlays (point-min) (point-max) 'doc-view t) ;Just in case. 1794 (remove-overlays (point-min) (point-max) 'doc-view t) ;Just in case.
1796 ;; Keep track of display info ([vh]scroll, page number, overlay, 1795 ;; 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 3b224814e9e..549ee96dd5f 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -107,12 +107,36 @@
107 107
108;;;###autoload 108;;;###autoload
109(defmacro pcase (exp &rest cases) 109(defmacro pcase (exp &rest cases)
110 "Eval EXP and perform ML-style pattern matching on that value. 110 "Evaluate EXP and attempt to match it against structural patterns.
111CASES is a list of elements of the form (PATTERN CODE...). 111CASES is a list of elements of the form (PATTERN CODE...).
112 112
113Patterns can take the following forms: 113A structural PATTERN describes a template that identifies a class
114of values. For example, the pattern `(,foo ,bar) matches any
115two element list, binding its elements to symbols named `foo' and
116`bar' -- in much the same way that `cl-destructuring-bind' would.
117
118A significant difference from `cl-destructuring-bind' is that, if
119a pattern match fails, the next case is tried until either a
120succesful match is found or there are no more cases.
121
122Another difference is that pattern elements may be backquoted,
123meaning they must match exactly: The pattern \\='(foo bar)
124matches only against two element lists containing the symbols
125`foo' and `bar' in that order. (As a short-hand, atoms always
126match themselves, such as numbers or strings, and need not be
127quoted).
128
129Lastly, a pattern can be logical, such as (pred numberp), that
130matches any number-like element; or the symbol `_', that matches
131anything. Also, when patterns are backquoted, a comma may be
132used to introduce logical patterns inside backquoted patterns.
133
134The complete list of standard patterns is as follows:
135
114 _ matches anything. 136 _ matches anything.
115 SYMBOL matches anything and binds it to SYMBOL. 137 SYMBOL matches anything and binds it to SYMBOL.
138 If a SYMBOL is used twice in the same pattern
139 the second occurrence becomes an `eq'uality test.
116 (or PAT...) matches if any of the patterns matches. 140 (or PAT...) matches if any of the patterns matches.
117 (and PAT...) matches if all the patterns match. 141 (and PAT...) matches if all the patterns match.
118 \\='VAL matches if the object is `equal' to VAL. 142 \\='VAL matches if the object is `equal' to VAL.
@@ -122,23 +146,18 @@ Patterns can take the following forms:
122 (guard BOOLEXP) matches if BOOLEXP evaluates to non-nil. 146 (guard BOOLEXP) matches if BOOLEXP evaluates to non-nil.
123 (let PAT EXP) matches if EXP matches PAT. 147 (let PAT EXP) matches if EXP matches PAT.
124 (app FUN PAT) matches if FUN applied to the object matches PAT. 148 (app FUN PAT) matches if FUN applied to the object matches PAT.
125If a SYMBOL is used twice in the same pattern (i.e. the pattern is
126\"non-linear\"), then the second occurrence is turned into an `eq'uality test.
127 149
128FUN can take the form 150Additional patterns can be defined using `pcase-defmacro'.
151
152The FUN argument in the `app' pattern may have the following forms:
129 SYMBOL or (lambda ARGS BODY) in which case it's called with one argument. 153 SYMBOL or (lambda ARGS BODY) in which case it's called with one argument.
130 (F ARG1 .. ARGn) in which case F gets called with an n+1'th argument 154 (F ARG1 .. ARGn) in which case F gets called with an n+1'th argument
131 which is the value being matched. 155 which is the value being matched.
132So a FUN of the form SYMBOL is equivalent to one of the form (FUN). 156So a FUN of the form SYMBOL is equivalent to (FUN).
133FUN can refer to variables bound earlier in the pattern. 157FUN can refer to variables bound earlier in the pattern.
134E.g. you can match pairs where the cdr is larger than the car with a pattern 158
135like \\=`(,a . ,(pred (< a))) or, with more checks: 159See Info node `(elisp) Pattern matching case statement' in the
136\\=`(,(and a (pred numberp)) . ,(and (pred numberp) (pred (< a)))) 160Emacs Lisp manual for more information and examples."
137FUN is assumed to be pure, i.e. it can be dropped if its result is not used,
138and two identical calls can be merged into one.
139
140Additional patterns can be defined via `pcase-defmacro'.
141Currently, the following patterns are provided this way:"
142 (declare (indent 1) (debug (form &rest (pcase-PAT body)))) 161 (declare (indent 1) (debug (form &rest (pcase-PAT body))))
143 ;; We want to use a weak hash table as a cache, but the key will unavoidably 162 ;; We want to use a weak hash table as a cache, but the key will unavoidably
144 ;; be based on `exp' and `cases', yet `cases' is a fresh new list each time 163 ;; 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 183e1443dac..560ba8ad2e5 100644
--- a/lisp/gnus/nnir.el
+++ b/lisp/gnus/nnir.el
@@ -822,8 +822,10 @@ skips all prompting."
822(deffoo nnir-request-update-mark (group article mark) 822(deffoo nnir-request-update-mark (group article mark)
823 (let ((artgroup (nnir-article-group article)) 823 (let ((artgroup (nnir-article-group article))
824 (artnumber (nnir-article-number article))) 824 (artnumber (nnir-article-number article)))
825 (when (and artgroup artnumber) 825 (or (and artgroup
826 (gnus-request-update-mark artgroup artnumber mark)))) 826 artnumber
827 (gnus-request-update-mark artgroup artnumber mark))
828 mark)))
827 829
828(deffoo nnir-request-set-mark (group actions &optional server) 830(deffoo nnir-request-set-mark (group actions &optional server)
829 (nnir-possibly-change-group group server) 831 (nnir-possibly-change-group group server)
diff --git a/lisp/htmlfontify.el b/lisp/htmlfontify.el
index 964d7440332..431300c81c2 100644
--- a/lisp/htmlfontify.el
+++ b/lisp/htmlfontify.el
@@ -1001,7 +1001,7 @@ merged by the user - `hfy-flatten-style' should do this."
1001 (append 1001 (append
1002 parent 1002 parent
1003 (hfy-face-to-style-i 1003 (hfy-face-to-style-i
1004 (hfy-face-attr-for-class v hfy-display-class)) )))) 1004 (hfy-face-attr-for-class v hfy-display-class))))))
1005 (setq this 1005 (setq this
1006 (if val (case key 1006 (if val (case key
1007 (:family (hfy-family val)) 1007 (:family (hfy-family val))
@@ -1020,7 +1020,7 @@ merged by the user - `hfy-flatten-style' should do this."
1020 (:italic (hfy-slant 'italic)))))) 1020 (:italic (hfy-slant 'italic))))))
1021 (setq that (hfy-face-to-style-i next)) 1021 (setq that (hfy-face-to-style-i next))
1022 ;;(lwarn t :warning "%S => %S" fn (nconc this that parent)) 1022 ;;(lwarn t :warning "%S => %S" fn (nconc this that parent))
1023 (nconc this that parent))) ) 1023 (nconc this parent that))) )
1024 1024
1025(defun hfy-size-to-int (spec) 1025(defun hfy-size-to-int (spec)
1026 "Convert SPEC, a CSS font-size specifier, to an Emacs :height attribute value. 1026 "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'."
1058 (nconc r (hfy-size (if x (round n) (* n 1.0)))) )) 1058 (nconc r (hfy-size (if x (round n) (* n 1.0)))) ))
1059 1059
1060(defun hfy-face-resolve-face (fn) 1060(defun hfy-face-resolve-face (fn)
1061 "For FN return a face specification.
1062FN may be either a face or a face specification. If the latter,
1063then the specification is returned unchanged."
1061 (cond 1064 (cond
1062 ((facep fn) 1065 ((facep fn)
1063 (hfy-face-attr-for-class fn hfy-display-class)) 1066 (hfy-face-attr-for-class fn hfy-display-class))
1067 ;; FIXME: is this necessary? Faces can be symbols, but
1068 ;; not symbols refering to other symbols?
1064 ((and (symbolp fn) 1069 ((and (symbolp fn)
1065 (facep (symbol-value fn))) 1070 (facep (symbol-value fn)))
1066 (hfy-face-attr-for-class (symbol-value fn) hfy-display-class)) 1071 (hfy-face-attr-for-class
1067 (t nil))) 1072 (symbol-value fn) hfy-display-class))
1073 (t fn)))
1068 1074
1069 1075
1070(defun hfy-face-to-style (fn) 1076(defun hfy-face-to-style (fn)
diff --git a/lisp/image-mode.el b/lisp/image-mode.el
index e677dd0d0e7..e549b49001e 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."
153 (selected-window)))) 153 (selected-window))))
154 154
155(declare-function image-size "image.c" (spec &optional pixels frame)) 155(declare-function image-size "image.c" (spec &optional pixels frame))
156(declare-function xwidget-info "xwidget.c" (xwidget))
157(declare-function xwidget-at "xwidget.el" (pos))
156 158
157(defun image-display-size (spec &optional pixels frame) 159(defun image-display-size (spec &optional pixels frame)
158 "Wrapper around `image-size', handling slice display properties. 160 "Wrapper around `image-size', handling slice display properties.
@@ -160,24 +162,29 @@ Like `image-size', the return value is (WIDTH . HEIGHT).
160WIDTH and HEIGHT are in canonical character units if PIXELS is 162WIDTH and HEIGHT are in canonical character units if PIXELS is
161nil, and in pixel units if PIXELS is non-nil. 163nil, and in pixel units if PIXELS is non-nil.
162 164
163If SPEC is an image display property, this function is equivalent 165If SPEC is an image display property, this function is equivalent to
164to `image-size'. If SPEC is a list of properties containing 166`image-size'. If SPEC represents an xwidget object, defer to `xwidget-info'.
165`image' and `slice' properties, return the display size taking 167If SPEC is a list of properties containing `image' and `slice' properties,
166the slice property into account. If the list contains `image' 168return the display size taking the slice property into account. If the list
167but not `slice', return the `image-size' of the specified image." 169contains `image' but not `slice', return the `image-size' of the specified
168 (if (eq (car spec) 'image) 170image."
169 (image-size spec pixels frame) 171 (cond ((eq (car spec) 'xwidget)
170 (let ((image (assoc 'image spec)) 172 (let ((xwi (xwidget-info (xwidget-at (point-min)))))
171 (slice (assoc 'slice spec))) 173 (cons (aref xwi 2) (aref xwi 3))))
172 (cond ((and image slice) 174 ((eq (car spec) 'image)
173 (if pixels 175 (image-size spec pixels frame))
174 (cons (nth 3 slice) (nth 4 slice)) 176 (t (let ((image (assoc 'image spec))
175 (cons (/ (float (nth 3 slice)) (frame-char-width frame)) 177 (slice (assoc 'slice spec)))
176 (/ (float (nth 4 slice)) (frame-char-height frame))))) 178 (cond ((and image slice)
177 (image 179 (if pixels
178 (image-size image pixels frame)) 180 (cons (nth 3 slice) (nth 4 slice))
179 (t 181 (cons (/ (float (nth 3 slice)) (frame-char-width frame))
180 (error "Invalid image specification: %s" spec)))))) 182 (/ (float (nth 4 slice))
183 (frame-char-height frame)))))
184 (image
185 (image-size image pixels frame))
186 (t
187 (error "Invalid image specification: %s" spec)))))))
181 188
182(defun image-forward-hscroll (&optional n) 189(defun image-forward-hscroll (&optional n)
183 "Scroll image in current window to the left by N character widths. 190 "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 79e9c7b4adc..2df847acc25 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."
2119 (with-current-buffer standard-output 2119 (with-current-buffer standard-output
2120 (insert language-name " language environment\n\n") 2120 (insert language-name " language environment\n\n")
2121 (if (stringp doc) 2121 (if (stringp doc)
2122 (insert doc "\n\n")) 2122 (insert (substitute-command-keys doc) "\n\n"))
2123 (condition-case nil 2123 (condition-case nil
2124 (let ((str (eval (get-language-info language-name 'sample-text)))) 2124 (let ((str (eval (get-language-info language-name 'sample-text))))
2125 (if (stringp str) 2125 (if (stringp str)
diff --git a/lisp/international/quail.el b/lisp/international/quail.el
index 75cb7f787df..f5e390278ca 100644
--- a/lisp/international/quail.el
+++ b/lisp/international/quail.el
@@ -2516,7 +2516,7 @@ package to describe."
2516 ")\n\n") 2516 ")\n\n")
2517 (save-restriction 2517 (save-restriction
2518 (narrow-to-region (point) (point)) 2518 (narrow-to-region (point) (point))
2519 (insert (quail-docstring)) 2519 (insert (substitute-command-keys (quail-docstring)))
2520 (goto-char (point-min)) 2520 (goto-char (point-min))
2521 (with-syntax-table emacs-lisp-mode-syntax-table 2521 (with-syntax-table emacs-lisp-mode-syntax-table
2522 (while (re-search-forward "\\\\<\\sw\\(\\sw\\|\\s_\\)+>" nil t) 2522 (while (re-search-forward "\\\\<\\sw\\(\\sw\\|\\s_\\)+>" nil t)
diff --git a/lisp/isearch.el b/lisp/isearch.el
index e636ccc0d22..c36f4631549 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -2647,10 +2647,11 @@ the word mode."
2647 "Non-default value overrides the behavior of `isearch-search-fun-default'. 2647 "Non-default value overrides the behavior of `isearch-search-fun-default'.
2648This variable's value should be a function, which will be called 2648This variable's value should be a function, which will be called
2649with no arguments, and should return a function that takes three 2649with no arguments, and should return a function that takes three
2650arguments: STRING, BOUND, and NOERROR. 2650arguments: STRING, BOUND, and NOERROR. See `re-search-forward'
2651for the meaning of BOUND and NOERROR arguments.
2651 2652
2652This returned function will be used by `isearch-search-string' to 2653This returned function will be used by `isearch-search-string' to
2653search for the first occurrence of STRING or its translation.") 2654search for the first occurrence of STRING.")
2654 2655
2655(defun isearch-search-fun () 2656(defun isearch-search-fun ()
2656 "Return the function to use for the search. 2657 "Return the function to use for the search.
@@ -2695,8 +2696,14 @@ Can be changed via `isearch-search-fun-function' for special needs."
2695 2696
2696(defun isearch-search-string (string bound noerror) 2697(defun isearch-search-string (string bound noerror)
2697 "Search for the first occurrence of STRING or its translation. 2698 "Search for the first occurrence of STRING or its translation.
2699STRING's characters are translated using `translation-table-for-input'
2700if that is non-nil.
2698If found, move point to the end of the occurrence, 2701If found, move point to the end of the occurrence,
2699update the match data, and return point." 2702update the match data, and return point.
2703An optional second argument bounds the search; it is a buffer position.
2704The match found must not extend after that position.
2705Optional third argument, if t, means if fail just return nil (no error).
2706 If not nil and not t, move to limit of search and return nil."
2700 (let* ((func (isearch-search-fun)) 2707 (let* ((func (isearch-search-fun))
2701 (pos1 (save-excursion (funcall func string bound noerror))) 2708 (pos1 (save-excursion (funcall func string bound noerror)))
2702 pos2) 2709 pos2)
diff --git a/lisp/net/shr.el b/lisp/net/shr.el
index 290a6422bd7..ab416146595 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'."
1619(defun shr-table-body (dom) 1619(defun shr-table-body (dom)
1620 (let ((tbodies (seq-filter (lambda (child) 1620 (let ((tbodies (seq-filter (lambda (child)
1621 (eq (dom-tag child) 'tbody)) 1621 (eq (dom-tag child) 'tbody))
1622 (dom-children dom)))) 1622 (dom-non-text-children dom))))
1623 (cond 1623 (cond
1624 ((null tbodies) 1624 ((null tbodies)
1625 dom) 1625 dom)
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index 53f8a6bb4c0..e3fe315f3bd 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -102,7 +102,7 @@
102 102
103(eval-and-compile 103(eval-and-compile
104 (defconst ruby-here-doc-beg-re 104 (defconst ruby-here-doc-beg-re
105 "\\(<\\)<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)" 105 "\\(<\\)<\\([~-]\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)"
106 "Regexp to match the beginning of a heredoc.") 106 "Regexp to match the beginning of a heredoc.")
107 107
108 (defconst ruby-expression-expansion-re 108 (defconst ruby-expression-expansion-re
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index 2bccd857576..d32da371771 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -861,7 +861,13 @@ tools are used, and when."
861 (cl-assert (directory-name-p dir)) 861 (cl-assert (directory-name-p dir))
862 (require 'semantic/symref) 862 (require 'semantic/symref)
863 (defvar semantic-symref-tool) 863 (defvar semantic-symref-tool)
864 (let* ((default-directory dir) 864
865 ;; Some symref backends use `ede-project-root-directory' as the root
866 ;; directory for the search, rather than `default-directory'. Since
867 ;; the caller has specified `dir', we bind `ede-minor-mode' to nil
868 ;; to force the backend to use `default-directory'.
869 (let* ((ede-minor-mode nil)
870 (default-directory dir)
865 (semantic-symref-tool 'detect) 871 (semantic-symref-tool 'detect)
866 (res (semantic-symref-find-references-by-name symbol 'subdirs)) 872 (res (semantic-symref-find-references-by-name symbol 'subdirs))
867 (hits (and res (oref res hit-lines))) 873 (hits (and res (oref res hit-lines)))
diff --git a/lisp/xwidget.el b/lisp/xwidget.el
new file mode 100644
index 00000000000..f184eb31dbb
--- /dev/null
+++ b/lisp/xwidget.el
@@ -0,0 +1,580 @@
1;;; xwidget.el --- api functions for xwidgets -*- lexical-binding: t -*-
2;;
3;; Copyright (C) 2011-2016 Free Software Foundation, Inc.
4;;
5;; Author: Joakim Verona (joakim@verona.se)
6;;
7;; This file is part of GNU Emacs.
8;;
9;; GNU Emacs is free software: you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
21;;
22;; --------------------------------------------------------------------
23
24;;; Commentary:
25;;
26;; See xwidget.c for more api functions.
27
28;; TODO this breaks compilation when we don't have xwidgets.
29;;(require 'xwidget-internal)
30
31;;; Code:
32
33(require 'cl-lib)
34(require 'bookmark)
35
36(defcustom xwidget-webkit-scroll-behaviour 'native
37 "Scroll behaviour of the webkit instance.
38'native or 'image."
39 :version "25.1"
40 :group 'frames ; TODO add xwidgets group if more options are added
41 :type '(choice (const native) (const image)))
42
43(declare-function make-xwidget "xwidget.c"
44 (beg end type title width height arguments &optional buffer))
45(declare-function xwidget-set-adjustment "xwidget.c"
46 (xwidget axis relative value))
47(declare-function xwidget-buffer "xwidget.c" (xwidget))
48(declare-function xwidget-webkit-get-title "xwidget.c" (xwidget))
49(declare-function xwidget-size-request "xwidget.c" (xwidget))
50(declare-function xwidget-resize "xwidget.c" (xwidget new-width new-height))
51(declare-function xwidget-webkit-execute-script "xwidget.c" (xwidget script))
52(declare-function xwidget-webkit-goto-uri "xwidget.c" (xwidget uri))
53(declare-function xwidget-plist "xwidget.c" (xwidget))
54(declare-function set-xwidget-plist "xwidget.c" (xwidget plist))
55(declare-function xwidget-view-window "xwidget.c" (xwidget-view))
56(declare-function xwidget-view-model "xwidget.c" (xwidget-view))
57(declare-function delete-xwidget-view "xwidget.c" (xwidget-view))
58(declare-function get-buffer-xwidgets "xwidget.c" (buffer))
59
60(defun xwidget-insert (pos type title width height &optional args)
61 "Insert an xwidget at POS.
62given ID, TYPE, TITLE WIDTH and
63HEIGHT in the current buffer.
64
65Return ID
66
67see `make-xwidget' for types suitable for TYPE.
68Optional argument ARGS usage depends on the xwidget."
69 (goto-char pos)
70 (let ((id (make-xwidget (point) (point)
71 type title width height args)))
72 (put-text-property (point) (+ 1 (point))
73 'display (list 'xwidget ':xwidget id))
74 id))
75
76(defun xwidget-at (pos)
77 "Return xwidget at POS."
78 ;; TODO this function is a bit tedious because the C layer isn't well
79 ;; protected yet and xwidgetp apparently doesn't work yet.
80 (let* ((disp (get-text-property pos 'display))
81 (xw (car (cdr (cdr disp)))))
82 ;;(if (xwidgetp xw) xw nil)
83 (if (equal 'xwidget (car disp)) xw)))
84
85
86
87;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
88;;; webkit support
89(require 'browse-url)
90(require 'image-mode);;for some image-mode alike functionality
91
92;;;###autoload
93(defun xwidget-webkit-browse-url (url &optional new-session)
94 "Ask xwidget-webkit to browse URL.
95NEW-SESSION specifies whether to create a new xwidget-webkit session. URL
96defaults to the string looking like a url around the cursor position."
97 (interactive (progn
98 (require 'browse-url)
99 (browse-url-interactive-arg "xwidget-webkit URL: "
100 ;;(xwidget-webkit-current-url)
101 )))
102 (when (stringp url)
103 (if new-session
104 (xwidget-webkit-new-session url)
105 (xwidget-webkit-goto-url url))))
106
107;;todo.
108;; - check that the webkit support is compiled in
109(defvar xwidget-webkit-mode-map
110 (let ((map (make-sparse-keymap)))
111 (define-key map "g" 'xwidget-webkit-browse-url)
112 (define-key map "a" 'xwidget-webkit-adjust-size-dispatch)
113 (define-key map "b" 'xwidget-webkit-back)
114 (define-key map "r" 'xwidget-webkit-reload)
115 (define-key map "t" (lambda () (interactive) (message "o"))) ;FIXME: ?!?
116 (define-key map "\C-m" 'xwidget-webkit-insert-string)
117 (define-key map "w" 'xwidget-webkit-current-url)
118
119 ;;similar to image mode bindings
120 (define-key map (kbd "SPC") 'xwidget-webkit-scroll-up)
121 (define-key map (kbd "DEL") 'xwidget-webkit-scroll-down)
122
123 (define-key map [remap scroll-up] 'xwidget-webkit-scroll-up)
124 (define-key map [remap scroll-up-command] 'xwidget-webkit-scroll-up)
125
126 (define-key map [remap scroll-down] 'xwidget-webkit-scroll-down)
127 (define-key map [remap scroll-down-command] 'xwidget-webkit-scroll-down)
128
129 (define-key map [remap forward-char] 'xwidget-webkit-scroll-forward)
130 (define-key map [remap backward-char] 'xwidget-webkit-scroll-backward)
131 (define-key map [remap right-char] 'xwidget-webkit-scroll-forward)
132 (define-key map [remap left-char] 'xwidget-webkit-scroll-backward)
133 ;; (define-key map [remap previous-line] 'image-previous-line)
134 ;; (define-key map [remap next-line] 'image-next-line)
135
136 ;; (define-key map [remap move-beginning-of-line] 'image-bol)
137 ;; (define-key map [remap move-end-of-line] 'image-eol)
138 ;; (define-key map [remap beginning-of-buffer] 'image-bob)
139 ;; (define-key map [remap end-of-buffer] 'image-eob)
140 map)
141 "Keymap for `xwidget-webkit-mode'.")
142
143(defun xwidget-webkit-scroll-up ()
144 "Scroll webkit up,either native or like image mode."
145 (interactive)
146 (if (eq xwidget-webkit-scroll-behaviour 'native)
147 (xwidget-set-adjustment (xwidget-webkit-last-session) 'vertical t 50)
148 (image-scroll-up)))
149
150(defun xwidget-webkit-scroll-down ()
151 "Scroll webkit down,either native or like image mode."
152 (interactive)
153 (if (eq xwidget-webkit-scroll-behaviour 'native)
154 (xwidget-set-adjustment (xwidget-webkit-last-session) 'vertical t -50)
155 (image-scroll-down)))
156
157(defun xwidget-webkit-scroll-forward ()
158 "Scroll webkit forward,either native or like image mode."
159 (interactive)
160 (if (eq xwidget-webkit-scroll-behaviour 'native)
161 (xwidget-set-adjustment (xwidget-webkit-last-session) 'horizontal t 50)
162 (xwidget-webkit-scroll-forward)))
163
164(defun xwidget-webkit-scroll-backward ()
165 "Scroll webkit backward,either native or like image mode."
166 (interactive)
167 (if (eq xwidget-webkit-scroll-behaviour 'native)
168 (xwidget-set-adjustment (xwidget-webkit-last-session) 'horizontal t -50)
169 (xwidget-webkit-scroll-backward)))
170
171
172;; The xwidget event needs to go into a higher level handler
173;; since the xwidget can generate an event even if it's offscreen.
174;; TODO this needs to use callbacks and consider different xwidget event types.
175(define-key (current-global-map) [xwidget-event] #'xwidget-event-handler)
176(defun xwidget-log (&rest msg)
177 "Log MSG to a buffer."
178 (let ((buf (get-buffer-create " *xwidget-log*")))
179 (with-current-buffer buf
180 (insert (apply #'format msg))
181 (insert "\n"))))
182
183(defun xwidget-event-handler ()
184 "Receive xwidget event."
185 (interactive)
186 (xwidget-log "stuff happened to xwidget %S" last-input-event)
187 (let*
188 ((xwidget-event-type (nth 1 last-input-event))
189 (xwidget (nth 2 last-input-event))
190 ;;(xwidget-callback (xwidget-get xwidget 'callback))
191 ;;TODO stopped working for some reason
192 )
193 ;;(funcall xwidget-callback xwidget xwidget-event-type)
194 (message "xw callback %s" xwidget)
195 (funcall 'xwidget-webkit-callback xwidget xwidget-event-type)))
196
197(defun xwidget-webkit-callback (xwidget xwidget-event-type)
198 "Callback for xwidgets.
199XWIDGET instance, XWIDGET-EVENT-TYPE depends on the originating xwidget."
200 (if (not (buffer-live-p (xwidget-buffer xwidget)))
201 (xwidget-log
202 "error: callback called for xwidget with dead buffer")
203 (with-current-buffer (xwidget-buffer xwidget)
204 (let* ((strarg (nth 3 last-input-event)))
205 (cond ((eq xwidget-event-type 'document-load-finished)
206 (xwidget-log "webkit finished loading: '%s'"
207 (xwidget-webkit-get-title xwidget))
208 ;;TODO - check the native/internal scroll
209 ;;(xwidget-adjust-size-to-content xwidget)
210 (xwidget-webkit-adjust-size-dispatch) ;;TODO xwidget arg
211 (rename-buffer (format "*xwidget webkit: %s *"
212 (xwidget-webkit-get-title xwidget)))
213 (pop-to-buffer (current-buffer)))
214 ((eq xwidget-event-type
215 'navigation-policy-decision-requested)
216 (if (string-match ".*#\\(.*\\)" strarg)
217 (xwidget-webkit-show-id-or-named-element
218 xwidget
219 (match-string 1 strarg))))
220 (t (xwidget-log "unhandled event:%s" xwidget-event-type)))))))
221
222(defvar bookmark-make-record-function)
223(define-derived-mode xwidget-webkit-mode
224 special-mode "xwidget-webkit" "Xwidget webkit view mode."
225 (setq buffer-read-only t)
226 (setq-local bookmark-make-record-function
227 #'xwidget-webkit-bookmark-make-record)
228 ;; Keep track of [vh]scroll when switching buffers
229 (image-mode-setup-winprops))
230
231(defun xwidget-webkit-bookmark-make-record ()
232 "Integrate Emacs bookmarks with the webkit xwidget."
233 (nconc (bookmark-make-record-default t t)
234 `((page . ,(xwidget-webkit-current-url))
235 (handler . (lambda (bmk) (browse-url
236 (bookmark-prop-get bmk 'page)))))))
237
238
239(defvar xwidget-webkit-last-session-buffer nil)
240
241(defun xwidget-webkit-last-session ()
242 "Last active webkit, or nil."
243 (if (buffer-live-p xwidget-webkit-last-session-buffer)
244 (with-current-buffer xwidget-webkit-last-session-buffer
245 (xwidget-at (point-min)))
246 nil))
247
248(defun xwidget-webkit-current-session ()
249 "Either the webkit in the current buffer, or the last one used.
250The latter might be nil."
251 (or (xwidget-at (point-min)) (xwidget-webkit-last-session)))
252
253(defun xwidget-adjust-size-to-content (xw)
254 "Resize XW to content."
255 ;; xwidgets doesn't support widgets that have their own opinions about
256 ;; size well, yet this reads the desired size and resizes the Emacs
257 ;; allocated area accordingly.
258 (let ((size (xwidget-size-request xw)))
259 (xwidget-resize xw (car size) (cadr size))))
260
261
262(defvar xwidget-webkit-activeelement-js"
263function findactiveelement(doc){
264//alert(doc.activeElement.value);
265 if(doc.activeElement.value != undefined){
266 return doc.activeElement;
267 }else{
268 // recurse over the child documents:
269 var frames = doc.getElementsByTagName('frame');
270 for (var i = 0; i < frames.length; i++)
271 {
272 var d = frames[i].contentDocument;
273 var rv = findactiveelement(d);
274 if(rv != undefined){
275 return rv;
276 }
277 }
278 }
279 return undefined;
280};
281
282
283"
284
285 "javascript that finds the active element."
286 ;; Yes it's ugly, because:
287 ;; - there is apparently no way to find the active frame other than recursion
288 ;; - the js "for each" construct misbehaved on the "frames" collection
289 ;; - a window with no frameset still has frames.length == 1, but
290 ;; frames[0].document.activeElement != document.activeElement
291 ;;TODO the activeelement type needs to be examined, for iframe, etc.
292 )
293
294(defun xwidget-webkit-insert-string (xw str)
295 "Insert string in the active field in the webkit.
296Argument XW webkit.
297Argument STR string."
298 ;; Read out the string in the field first and provide for edit.
299 (interactive
300 (let* ((xww (xwidget-webkit-current-session))
301
302 (field-value
303 (progn
304 (xwidget-webkit-execute-script xww xwidget-webkit-activeelement-js)
305 (xwidget-webkit-execute-script-rv
306 xww
307 "findactiveelement(document).value;")))
308 (field-type (xwidget-webkit-execute-script-rv
309 xww
310 "findactiveelement(document).type;")))
311 (list xww
312 (cond ((equal "text" field-type)
313 (read-string "text:" field-value))
314 ((equal "password" field-type)
315 (read-passwd "password:" nil field-value))
316 ((equal "textarea" field-type)
317 (xwidget-webkit-begin-edit-textarea xww field-value))))))
318 (xwidget-webkit-execute-script
319 xw
320 (format "findactiveelement(document).value='%s'" str)))
321
322(defvar xwidget-xwbl)
323(defun xwidget-webkit-begin-edit-textarea (xw text)
324 "Start editing of a webkit text area.
325XW is the xwidget identifier, TEXT is retrieved from the webkit."
326 (switch-to-buffer
327 (generate-new-buffer "textarea"))
328
329 (set (make-local-variable 'xwidget-xwbl) xw)
330 (insert text))
331
332(defun xwidget-webkit-end-edit-textarea ()
333 "End editing of a webkit text area."
334 (interactive)
335 (goto-char (point-min))
336 (while (search-forward "\n" nil t)
337 (replace-match "\\n" nil t))
338 (xwidget-webkit-execute-script
339 xwidget-xwbl
340 (format "findactiveelement(document).value='%s'"
341 (buffer-substring (point-min) (point-max))))
342 ;;TODO convert linefeed to \n
343 )
344
345(defun xwidget-webkit-show-named-element (xw element-name)
346 "Make named-element show. for instance an anchor.
347Argument XW is the xwidget.
348Argument ELEMENT-NAME is the element name to display in the webkit xwidget."
349 (interactive (list (xwidget-webkit-current-session)
350 (read-string "element name:")))
351 ;;TODO since an xwidget is an Emacs object, it is not trivial to do
352 ;; some things that are taken for granted in a normal browser.
353 ;; scrolling an anchor/named-element into view is one such thing.
354 ;; This function implements a proof-of-concept for this. Problems
355 ;; remaining: - The selected window is scrolled but this is not
356 ;; always correct - This needs to be interfaced into browse-url
357 ;; somehow. The tricky part is that we need to do this in two steps:
358 ;; A: load the base url, wait for load signal to arrive B: navigate
359 ;; to the anchor when the base url is finished rendering
360
361 ;; This part figures out the Y coordinate of the element
362 (let ((y (string-to-number
363 (xwidget-webkit-execute-script-rv
364 xw
365 (format
366 "document.getElementsByName('%s')[0].getBoundingClientRect().top"
367 element-name)
368 0))))
369 ;; Now we need to tell Emacs to scroll the element into view.
370 (xwidget-log "scroll: %d" y)
371 (set-window-vscroll (selected-window) y t)))
372
373(defun xwidget-webkit-show-id-element (xw element-id)
374 "Make id-element show. for instance an anchor.
375Argument XW is the webkit xwidget.
376Argument ELEMENT-ID is the id of the element to show."
377 (interactive (list (xwidget-webkit-current-session)
378 (read-string "element id:")))
379 (let ((y (string-to-number
380 (xwidget-webkit-execute-script-rv
381 xw
382 (format "document.getElementById('%s').getBoundingClientRect().top"
383 element-id)
384 0))))
385 ;; Now we need to tell Emacs to scroll the element into view.
386 (xwidget-log "scroll: %d" y)
387 (set-window-vscroll (selected-window) y t)))
388
389(defun xwidget-webkit-show-id-or-named-element (xw element-id)
390 "Make id-element show. for instance an anchor.
391Argument XW is the webkit xwidget.
392Argument ELEMENT-ID is either a name or an element id."
393 (interactive (list (xwidget-webkit-current-session)
394 (read-string "element id:")))
395 (let* ((y1 (string-to-number
396 (xwidget-webkit-execute-script-rv
397 xw
398 (format "document.getElementsByName('%s')[0].getBoundingClientRect().top" element-id)
399 "0")))
400 (y2 (string-to-number
401 (xwidget-webkit-execute-script-rv
402 xw
403 (format "document.getElementById('%s').getBoundingClientRect().top" element-id)
404 "0")))
405 (y3 (max y1 y2)))
406 ;; Now we need to tell Emacs to scroll the element into view.
407 (xwidget-log "scroll: %d" y3)
408 (set-window-vscroll (selected-window) y3 t)))
409
410(defun xwidget-webkit-adjust-size-to-content ()
411 "Adjust webkit to content size."
412 (interactive)
413 (xwidget-adjust-size-to-content (xwidget-webkit-current-session)))
414
415(defun xwidget-webkit-adjust-size-dispatch ()
416 "Adjust size according to mode."
417 (interactive)
418 (if (eq xwidget-webkit-scroll-behaviour 'native)
419 (xwidget-webkit-adjust-size-to-window)
420 (xwidget-webkit-adjust-size-to-content))
421 ;; The recenter is intended to correct a visual glitch.
422 ;; It errors out if the buffer isn't visible, but then we don't get
423 ;; the glitch, so silence errors.
424 (ignore-errors
425 (recenter-top-bottom))
426 )
427
428(defun xwidget-webkit-adjust-size-to-window ()
429 "Adjust webkit to window."
430 (interactive)
431 (xwidget-resize (xwidget-webkit-current-session) (window-pixel-width)
432 (window-pixel-height)))
433
434(defun xwidget-webkit-adjust-size (w h)
435 "Manually set webkit size.
436Argument W width.
437Argument H height."
438 ;; TODO shouldn't be tied to the webkit xwidget
439 (interactive "nWidth:\nnHeight:\n")
440 (xwidget-resize (xwidget-webkit-current-session) w h))
441
442(defun xwidget-webkit-fit-width ()
443 "Adjust width of webkit to window width."
444 (interactive)
445 (xwidget-webkit-adjust-size (- (nth 2 (window-inside-pixel-edges))
446 (car (window-inside-pixel-edges)))
447 1000))
448
449(defun xwidget-webkit-new-session (url)
450 "Create a new webkit session buffer with URL."
451 (let*
452 ((bufname (generate-new-buffer-name "*xwidget-webkit*"))
453 xw)
454 (setq xwidget-webkit-last-session-buffer (switch-to-buffer
455 (get-buffer-create bufname)))
456 (insert " 'a' adjusts the xwidget size.")
457 (setq xw (xwidget-insert 1 'webkit-osr bufname 1000 1000))
458 (xwidget-put xw 'callback 'xwidget-webkit-callback)
459 (xwidget-webkit-mode)
460 (xwidget-webkit-goto-uri (xwidget-webkit-last-session) url)))
461
462
463(defun xwidget-webkit-goto-url (url)
464 "Goto URL."
465 (if (xwidget-webkit-current-session)
466 (progn
467 (xwidget-webkit-goto-uri (xwidget-webkit-current-session) url))
468 (xwidget-webkit-new-session url)))
469
470(defun xwidget-webkit-back ()
471 "Back in history."
472 (interactive)
473 (xwidget-webkit-execute-script (xwidget-webkit-current-session)
474 "history.go(-1);"))
475
476(defun xwidget-webkit-reload ()
477 "Reload current url."
478 (interactive)
479 (xwidget-webkit-execute-script (xwidget-webkit-current-session)
480 "history.go(0);"))
481
482(defun xwidget-webkit-current-url ()
483 "Get the webkit url. place it on kill ring."
484 (interactive)
485 (let* ((rv (xwidget-webkit-execute-script-rv (xwidget-webkit-current-session)
486 "document.URL"))
487 (url (kill-new (or rv ""))))
488 (message "url: %s" url)
489 url))
490
491(defun xwidget-webkit-execute-script-rv (xw script &optional default)
492 "Same as 'xwidget-webkit-execute-script' but but with return value.
493XW is the webkit instance. SCRIPT is the script to execute.
494DEFAULT is the defaultreturn value."
495 ;; Notice the ugly "title" hack. It is needed because the Webkit
496 ;; API at the time of writing didn't support returning values. This
497 ;; is a wrapper for the title hack so it's easy to remove should
498 ;; Webkit someday support JS return values or we find some other way
499 ;; to access the DOM.
500
501 ;; Reset webkit title. Not very nice.
502 (let* ((emptytag "titlecantbewhitespaceohthehorror")
503 title)
504 (xwidget-webkit-execute-script xw (format "document.title=\"%s\";"
505 (or default emptytag)))
506 (xwidget-webkit-execute-script xw (format "document.title=%s;" script))
507 (setq title (xwidget-webkit-get-title xw))
508 (if (equal emptytag title)
509 (setq title ""))
510 (unless title
511 (setq title default))
512 title))
513
514;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
515(defun xwidget-webkit-get-selection ()
516 "Get the webkit selection."
517 (xwidget-webkit-execute-script-rv (xwidget-webkit-current-session)
518 "window.getSelection().toString();"))
519
520(defun xwidget-webkit-copy-selection-as-kill ()
521 "Get the webkit selection and put it on the kill ring."
522 (interactive)
523 (kill-new (xwidget-webkit-get-selection)))
524
525
526;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
527;; Xwidget plist management (similar to the process plist functions)
528
529(defun xwidget-get (xwidget propname)
530 "Return the value of XWIDGET' PROPNAME property.
531This is the last value stored with `(xwidget-put XWIDGET PROPNAME VALUE)'."
532 (plist-get (xwidget-plist xwidget) propname))
533
534(defun xwidget-put (xwidget propname value)
535 "Change XWIDGET' PROPNAME property to VALUE.
536It can be retrieved with `(xwidget-get XWIDGET PROPNAME)'."
537 (set-xwidget-plist xwidget
538 (plist-put (xwidget-plist xwidget) propname value)))
539
540
541;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
542
543(defvar xwidget-view-list) ; xwidget.c
544(defvar xwidget-list) ; xwidget.c
545
546(defun xwidget-delete-zombies ()
547 "Helper for `xwidget-cleanup'."
548 (dolist (xwidget-view xwidget-view-list)
549 (when (or (not (window-live-p (xwidget-view-window xwidget-view)))
550 (not (memq (xwidget-view-model xwidget-view)
551 xwidget-list)))
552 (delete-xwidget-view xwidget-view))))
553
554(defun xwidget-cleanup ()
555 "Delete zombie xwidgets."
556 ;; During development it was sometimes easy to wind up with zombie
557 ;; xwidget instances.
558 ;; This function tries to implement a workaround should it occur again.
559 (interactive)
560 ;; Kill xviews that should have been deleted but still linger.
561 (xwidget-delete-zombies)
562 ;; Redraw display otherwise ghost of zombies will remain to haunt the screen
563 (redraw-display))
564
565(defun xwidget-kill-buffer-query-function ()
566 "Ask before killing a buffer that has xwidgets."
567 (let ((xwidgets (get-buffer-xwidgets (current-buffer))))
568 (or (not xwidgets)
569 (not (memq t (mapcar #'xwidget-query-on-exit-flag xwidgets)))
570 (yes-or-no-p
571 (format "Buffer %S has xwidgets; kill it? " (buffer-name))))))
572
573(when (featurep 'xwidget-internal)
574 (add-hook 'kill-buffer-query-functions #'xwidget-kill-buffer-query-function)
575 ;; This would have felt better in C, but this seems to work well in
576 ;; practice though.
577 (add-hook 'window-configuration-change-hook #'xwidget-delete-zombies))
578
579(provide 'xwidget)
580;;; xwidget.el ends here
diff --git a/src/Makefile.in b/src/Makefile.in
index defce62c529..b38e7d558b8 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -152,6 +152,9 @@ DBUS_LIBS = @DBUS_LIBS@
152## dbusbind.o if HAVE_DBUS, else empty. 152## dbusbind.o if HAVE_DBUS, else empty.
153DBUS_OBJ = @DBUS_OBJ@ 153DBUS_OBJ = @DBUS_OBJ@
154 154
155## xwidgets.o if HAVE_XWIDGETS, else empty.
156XWIDGETS_OBJ = @XWIDGETS_OBJ@
157
155LIB_EXECINFO=@LIB_EXECINFO@ 158LIB_EXECINFO=@LIB_EXECINFO@
156 159
157SETTINGS_CFLAGS = @SETTINGS_CFLAGS@ 160SETTINGS_CFLAGS = @SETTINGS_CFLAGS@
@@ -220,6 +223,9 @@ CFLAGS_SOUND= @CFLAGS_SOUND@
220RSVG_LIBS= @RSVG_LIBS@ 223RSVG_LIBS= @RSVG_LIBS@
221RSVG_CFLAGS= @RSVG_CFLAGS@ 224RSVG_CFLAGS= @RSVG_CFLAGS@
222 225
226WEBKIT_LIBS= @WEBKIT_LIBS@
227WEBKIT_CFLAGS= @WEBKIT_CFLAGS@
228
223CAIRO_LIBS= @CAIRO_LIBS@ 229CAIRO_LIBS= @CAIRO_LIBS@
224CAIRO_CFLAGS= @CAIRO_CFLAGS@ 230CAIRO_CFLAGS= @CAIRO_CFLAGS@
225 231
@@ -359,6 +365,7 @@ ALL_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \
359 $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \ 365 $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \
360 $(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \ 366 $(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \
361 $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \ 367 $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \
368 $(WEBKIT_CFLAGS) \
362 $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ 369 $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
363 $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \ 370 $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
364 $(LIBGNUTLS_CFLAGS) $(NOTIFY_CFLAGS) $(CAIRO_CFLAGS) \ 371 $(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 \
388 process.o gnutls.o callproc.o \ 395 process.o gnutls.o callproc.o \
389 region-cache.o sound.o atimer.o \ 396 region-cache.o sound.o atimer.o \
390 doprnt.o intervals.o textprop.o composite.o xml.o $(NOTIFY_OBJ) \ 397 doprnt.o intervals.o textprop.o composite.o xml.o $(NOTIFY_OBJ) \
398 $(XWIDGETS_OBJ) \
391 profiler.o decompress.o \ 399 profiler.o decompress.o \
392 $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \ 400 $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \
393 $(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ) 401 $(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ)
@@ -468,6 +476,7 @@ lisp = $(addprefix ${lispsource}/,${shortlisp})
468LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ 476LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
469 $(LIBX_OTHER) $(LIBSOUND) \ 477 $(LIBX_OTHER) $(LIBSOUND) \
470 $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \ 478 $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \
479 $(WEBKIT_LIBS) \
471 $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \ 480 $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
472 $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \ 481 $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \
473 $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) $(CAIRO_LIBS) \ 482 $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) $(CAIRO_LIBS) \
diff --git a/src/buffer.c b/src/buffer.c
index 4df77a181d6..51bbad78bbc 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -43,6 +43,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
43#include "keymap.h" 43#include "keymap.h"
44#include "frame.h" 44#include "frame.h"
45 45
46#ifdef HAVE_XWIDGETS
47# include "xwidget.h"
48#endif
46#ifdef WINDOWSNT 49#ifdef WINDOWSNT
47#include "w32heap.h" /* for mmap_* */ 50#include "w32heap.h" /* for mmap_* */
48#endif 51#endif
@@ -1747,6 +1750,9 @@ cleaning up all windows currently displaying the buffer to be killed. */)
1747 1750
1748 kill_buffer_processes (buffer); 1751 kill_buffer_processes (buffer);
1749 1752
1753#ifdef HAVE_XWIDGETS
1754 kill_buffer_xwidgets (buffer);
1755#endif
1750 /* Killing buffer processes may run sentinels which may have killed 1756 /* Killing buffer processes may run sentinels which may have killed
1751 our buffer. */ 1757 our buffer. */
1752 if (!BUFFER_LIVE_P (b)) 1758 if (!BUFFER_LIVE_P (b))
diff --git a/src/dispextern.h b/src/dispextern.h
index bb876f5af70..fad5bfd6f2f 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -348,6 +348,10 @@ enum glyph_type
348 348
349 /* Glyph is a space of fractional width and/or height. */ 349 /* Glyph is a space of fractional width and/or height. */
350 STRETCH_GLYPH 350 STRETCH_GLYPH
351#ifdef HAVE_XWIDGETS
352 /* Glyph is an external widget drawn by the GUI toolkit. */
353 ,XWIDGET_GLYPH
354#endif
351}; 355};
352 356
353 357
@@ -499,6 +503,9 @@ struct glyph
499 /* Image ID for image glyphs (type == IMAGE_GLYPH). */ 503 /* Image ID for image glyphs (type == IMAGE_GLYPH). */
500 int img_id; 504 int img_id;
501 505
506#ifdef HAVE_XWIDGETS
507 struct xwidget *xwidget;
508#endif
502 /* Sub-structure for type == STRETCH_GLYPH. */ 509 /* Sub-structure for type == STRETCH_GLYPH. */
503 struct 510 struct
504 { 511 {
@@ -1350,6 +1357,9 @@ struct glyph_string
1350 /* Image, if any. */ 1357 /* Image, if any. */
1351 struct image *img; 1358 struct image *img;
1352 1359
1360#ifdef HAVE_XWIDGETS
1361 struct xwidget *xwidget;
1362#endif
1353 /* Slice */ 1363 /* Slice */
1354 struct glyph_slice slice; 1364 struct glyph_slice slice;
1355 1365
@@ -2102,6 +2112,10 @@ enum display_element_type
2102 2112
2103 /* Continuation glyphs. See the comment for IT_TRUNCATION. */ 2113 /* Continuation glyphs. See the comment for IT_TRUNCATION. */
2104 IT_CONTINUATION 2114 IT_CONTINUATION
2115
2116#ifdef HAVE_XWIDGETS
2117 ,IT_XWIDGET
2118#endif
2105}; 2119};
2106 2120
2107 2121
@@ -2165,6 +2179,9 @@ enum it_method {
2165 GET_FROM_C_STRING, 2179 GET_FROM_C_STRING,
2166 GET_FROM_IMAGE, 2180 GET_FROM_IMAGE,
2167 GET_FROM_STRETCH, 2181 GET_FROM_STRETCH,
2182#ifdef HAVE_XWIDGETS
2183 GET_FROM_XWIDGET,
2184#endif
2168 NUM_IT_METHODS 2185 NUM_IT_METHODS
2169}; 2186};
2170 2187
@@ -2382,6 +2399,12 @@ struct it
2382 struct { 2399 struct {
2383 Lisp_Object object; 2400 Lisp_Object object;
2384 } stretch; 2401 } stretch;
2402#ifdef HAVE_XWIDGETS
2403 /* method == GET_FROM_XWIDGET */
2404 struct {
2405 Lisp_Object object;
2406 } xwidget;
2407#endif
2385 } u; 2408 } u;
2386 2409
2387 /* Current text and display positions. */ 2410 /* Current text and display positions. */
@@ -2506,6 +2529,11 @@ struct it
2506 /* If what == IT_IMAGE, the id of the image to display. */ 2529 /* If what == IT_IMAGE, the id of the image to display. */
2507 ptrdiff_t image_id; 2530 ptrdiff_t image_id;
2508 2531
2532#ifdef HAVE_XWIDGETS
2533 /* If what == IT_XWIDGET. */
2534 struct xwidget *xwidget;
2535#endif
2536
2509 /* Values from `slice' property. */ 2537 /* Values from `slice' property. */
2510 struct it_slice slice; 2538 struct it_slice slice;
2511 2539
diff --git a/src/dispnew.c b/src/dispnew.c
index 8d671f82e47..32c0dff9b92 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -44,6 +44,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
44#include TERM_HEADER 44#include TERM_HEADER
45#endif /* HAVE_WINDOW_SYSTEM */ 45#endif /* HAVE_WINDOW_SYSTEM */
46 46
47#ifdef HAVE_XWIDGETS
48# include "xwidget.h"
49#endif
50
47#include <errno.h> 51#include <errno.h>
48 52
49#include <fpending.h> 53#include <fpending.h>
@@ -3543,6 +3547,9 @@ update_window (struct window *w, bool force_p)
3543 add_window_display_history (w, w->current_matrix->method, paused_p); 3547 add_window_display_history (w, w->current_matrix->method, paused_p);
3544#endif 3548#endif
3545 3549
3550#ifdef HAVE_XWIDGETS
3551 xwidget_end_redisplay (w, w->current_matrix);
3552#endif
3546 clear_glyph_matrix (desired_matrix); 3553 clear_glyph_matrix (desired_matrix);
3547 3554
3548 return paused_p; 3555 return paused_p;
@@ -4116,6 +4123,11 @@ scrolling_window (struct window *w, bool header_line_p)
4116 break; 4123 break;
4117 } 4124 }
4118 4125
4126#ifdef HAVE_XWIDGETS
4127 /* Currently this seems needed to detect xwidget movement reliably. */
4128 return 0;
4129#endif
4130
4119 /* Give up if some rows in the desired matrix are not enabled. */ 4131 /* Give up if some rows in the desired matrix are not enabled. */
4120 if (! MATRIX_ROW_ENABLED_P (desired_matrix, i)) 4132 if (! MATRIX_ROW_ENABLED_P (desired_matrix, i))
4121 return -1; 4133 return -1;
diff --git a/src/emacs.c b/src/emacs.c
index aaf058e4a80..fcf048ca84b 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -66,6 +66,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
66#include "buffer.h" 66#include "buffer.h"
67#include "window.h" 67#include "window.h"
68 68
69#ifdef HAVE_XWIDGETS
70# include "xwidget.h"
71#endif
69#include "atimer.h" 72#include "atimer.h"
70#include "blockinput.h" 73#include "blockinput.h"
71#include "syssignal.h" 74#include "syssignal.h"
@@ -1492,6 +1495,9 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1492 syms_of_xfns (); 1495 syms_of_xfns ();
1493 syms_of_xmenu (); 1496 syms_of_xmenu ();
1494 syms_of_fontset (); 1497 syms_of_fontset ();
1498#ifdef HAVE_XWIDGETS
1499 syms_of_xwidget ();
1500#endif
1495 syms_of_xsettings (); 1501 syms_of_xsettings ();
1496#ifdef HAVE_X_SM 1502#ifdef HAVE_X_SM
1497 syms_of_xsmfns (); 1503 syms_of_xsmfns ();
diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c
index cdcaf803ba5..08b840389c5 100644
--- a/src/emacsgtkfixed.c
+++ b/src/emacsgtkfixed.c
@@ -23,6 +23,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
23#include "lisp.h" 23#include "lisp.h"
24#include "frame.h" 24#include "frame.h"
25#include "xterm.h" 25#include "xterm.h"
26#ifdef HAVE_XWIDGETS
27# include "xwidget.h"
28#endif
26#include "emacsgtkfixed.h" 29#include "emacsgtkfixed.h"
27 30
28/* Silence a bogus diagnostic; see GNOME bug 683906. */ 31/* Silence a bogus diagnostic; see GNOME bug 683906. */
@@ -31,27 +34,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
31# pragma GCC diagnostic ignored "-Wunused-local-typedefs" 34# pragma GCC diagnostic ignored "-Wunused-local-typedefs"
32#endif 35#endif
33 36
34#define EMACS_TYPE_FIXED emacs_fixed_get_type ()
35#define EMACS_FIXED(obj) \
36 G_TYPE_CHECK_INSTANCE_CAST (obj, EMACS_TYPE_FIXED, EmacsFixed)
37
38typedef struct _EmacsFixed EmacsFixed; 37typedef struct _EmacsFixed EmacsFixed;
39typedef struct _EmacsFixedPrivate EmacsFixedPrivate; 38typedef struct _EmacsFixedPrivate EmacsFixedPrivate;
40typedef struct _EmacsFixedClass EmacsFixedClass; 39typedef struct _EmacsFixedClass EmacsFixedClass;
41 40
42struct _EmacsFixed
43{
44 GtkFixed container;
45
46 /*< private >*/
47 EmacsFixedPrivate *priv;
48};
49
50struct _EmacsFixedClass
51{
52 GtkFixedClass parent_class;
53};
54
55struct _EmacsFixedPrivate 41struct _EmacsFixedPrivate
56{ 42{
57 struct frame *f; 43 struct frame *f;
@@ -64,9 +50,103 @@ static void emacs_fixed_get_preferred_width (GtkWidget *widget,
64static void emacs_fixed_get_preferred_height (GtkWidget *widget, 50static void emacs_fixed_get_preferred_height (GtkWidget *widget,
65 gint *minimum, 51 gint *minimum,
66 gint *natural); 52 gint *natural);
53
67static GType emacs_fixed_get_type (void); 54static GType emacs_fixed_get_type (void);
68G_DEFINE_TYPE (EmacsFixed, emacs_fixed, GTK_TYPE_FIXED) 55G_DEFINE_TYPE (EmacsFixed, emacs_fixed, GTK_TYPE_FIXED)
69 56
57static EmacsFixed *
58EMACS_FIXED (GtkWidget *widget)
59{
60 return G_TYPE_CHECK_INSTANCE_CAST (widget, emacs_fixed_get_type (),
61 EmacsFixed);
62}
63
64#ifdef HAVE_XWIDGETS
65
66static EmacsFixedClass *
67EMACS_FIXED_GET_CLASS (GtkWidget *widget)
68{
69 return G_TYPE_INSTANCE_GET_CLASS (widget, emacs_fixed_get_type (),
70 EmacsFixedClass);
71}
72
73struct GtkFixedPrivateL
74{
75 GList *children;
76};
77
78static void emacs_fixed_gtk_widget_size_allocate (GtkWidget *widget,
79 GtkAllocation *allocation)
80{
81 // For xwidgets.
82
83 // This basically re-implements the base class method and adds an
84 // additional case for an xwidget view.
85
86 // It would be nicer if the bse class method could be called first,
87 // and the the xview modification only would remain here. It wasn't
88 // possible to solve it that way yet.
89 EmacsFixedClass *klass;
90 GtkWidgetClass *parent_class;
91 struct GtkFixedPrivateL* priv;
92
93 klass = EMACS_FIXED_GET_CLASS (widget);
94 parent_class = g_type_class_peek_parent (klass);
95 parent_class->size_allocate (widget, allocation);
96
97 priv = G_TYPE_INSTANCE_GET_PRIVATE (widget,
98 GTK_TYPE_FIXED,
99 struct GtkFixedPrivateL);
100
101 gtk_widget_set_allocation (widget, allocation);
102
103 if (gtk_widget_get_has_window (widget))
104 {
105 if (gtk_widget_get_realized (widget))
106 gdk_window_move_resize (gtk_widget_get_window (widget),
107 allocation->x,
108 allocation->y,
109 allocation->width,
110 allocation->height);
111 }
112
113 for (GList *children = priv->children; children; children = children->next)
114 {
115 GtkFixedChild *child = children->data;
116
117 if (!gtk_widget_get_visible (child->widget))
118 continue;
119
120 GtkRequisition child_requisition;
121 gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL);
122
123 GtkAllocation child_allocation;
124 child_allocation.x = child->x;
125 child_allocation.y = child->y;
126
127 if (!gtk_widget_get_has_window (widget))
128 {
129 child_allocation.x += allocation->x;
130 child_allocation.y += allocation->y;
131 }
132
133 child_allocation.width = child_requisition.width;
134 child_allocation.height = child_requisition.height;
135
136 struct xwidget_view *xv
137 = g_object_get_data (G_OBJECT (child->widget), XG_XWIDGET_VIEW);
138 if (xv)
139 {
140 child_allocation.width = xv->clip_right;
141 child_allocation.height = xv->clip_bottom - xv->clip_top;
142 }
143
144 gtk_widget_size_allocate (child->widget, &child_allocation);
145 }
146}
147
148#endif /* HAVE_XWIDGETS */
149
70static void 150static void
71emacs_fixed_class_init (EmacsFixedClass *klass) 151emacs_fixed_class_init (EmacsFixedClass *klass)
72{ 152{
@@ -74,15 +154,20 @@ emacs_fixed_class_init (EmacsFixedClass *klass)
74 154
75 widget_class = (GtkWidgetClass*) klass; 155 widget_class = (GtkWidgetClass*) klass;
76 156
157
77 widget_class->get_preferred_width = emacs_fixed_get_preferred_width; 158 widget_class->get_preferred_width = emacs_fixed_get_preferred_width;
78 widget_class->get_preferred_height = emacs_fixed_get_preferred_height; 159 widget_class->get_preferred_height = emacs_fixed_get_preferred_height;
160#ifdef HAVE_XWIDGETS
161 widget_class->size_allocate = emacs_fixed_gtk_widget_size_allocate;
162#endif
79 g_type_class_add_private (klass, sizeof (EmacsFixedPrivate)); 163 g_type_class_add_private (klass, sizeof (EmacsFixedPrivate));
80} 164}
81 165
166
82static void 167static void
83emacs_fixed_init (EmacsFixed *fixed) 168emacs_fixed_init (EmacsFixed *fixed)
84{ 169{
85 fixed->priv = G_TYPE_INSTANCE_GET_PRIVATE (fixed, EMACS_TYPE_FIXED, 170 fixed->priv = G_TYPE_INSTANCE_GET_PRIVATE (fixed, emacs_fixed_get_type (),
86 EmacsFixedPrivate); 171 EmacsFixedPrivate);
87 fixed->priv->f = 0; 172 fixed->priv->f = 0;
88} 173}
@@ -97,7 +182,7 @@ emacs_fixed_init (EmacsFixed *fixed)
97GtkWidget* 182GtkWidget*
98emacs_fixed_new (struct frame *f) 183emacs_fixed_new (struct frame *f)
99{ 184{
100 EmacsFixed *fixed = g_object_new (EMACS_TYPE_FIXED, NULL); 185 EmacsFixed *fixed = g_object_new (emacs_fixed_get_type (), NULL);
101 EmacsFixedPrivate *priv = fixed->priv; 186 EmacsFixedPrivate *priv = fixed->priv;
102 priv->f = f; 187 priv->f = f;
103 return GTK_WIDGET (fixed); 188 return GTK_WIDGET (fixed);
diff --git a/src/emacsgtkfixed.h b/src/emacsgtkfixed.h
index 73280b83e57..378bd2b828c 100644
--- a/src/emacsgtkfixed.h
+++ b/src/emacsgtkfixed.h
@@ -27,6 +27,26 @@ struct frame;
27 27
28G_BEGIN_DECLS 28G_BEGIN_DECLS
29 29
30struct frame;
31
32//typedef struct _EmacsFixed EmacsFixed;
33typedef struct _EmacsFixedPrivate EmacsFixedPrivate;
34typedef struct _EmacsFixedClass EmacsFixedClass;
35
36struct _EmacsFixed
37{
38 GtkFixed container;
39
40 /*< private >*/
41 EmacsFixedPrivate *priv;
42};
43
44
45struct _EmacsFixedClass
46{
47 GtkFixedClass parent_class;
48};
49
30extern GtkWidget *emacs_fixed_new (struct frame *f); 50extern GtkWidget *emacs_fixed_new (struct frame *f);
31 51
32G_END_DECLS 52G_END_DECLS
diff --git a/src/keyboard.c b/src/keyboard.c
index c8a9728e896..fe503b8ce56 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -4014,6 +4014,13 @@ kbd_buffer_get_event (KBOARD **kbp,
4014 kbd_fetch_ptr = event + 1; 4014 kbd_fetch_ptr = event + 1;
4015 } 4015 }
4016#endif 4016#endif
4017#ifdef HAVE_XWIDGETS
4018 else if (event->kind == XWIDGET_EVENT)
4019 {
4020 obj = make_lispy_event (&event->ie);
4021 kbd_fetch_ptr = event + 1;
4022 }
4023#endif
4017 else if (event->kind == CONFIG_CHANGED_EVENT) 4024 else if (event->kind == CONFIG_CHANGED_EVENT)
4018 { 4025 {
4019 obj = make_lispy_event (&event->ie); 4026 obj = make_lispy_event (&event->ie);
@@ -5950,6 +5957,13 @@ make_lispy_event (struct input_event *event)
5950 } 5957 }
5951#endif /* HAVE_DBUS */ 5958#endif /* HAVE_DBUS */
5952 5959
5960#ifdef HAVE_XWIDGETS
5961 case XWIDGET_EVENT:
5962 {
5963 return Fcons (Qxwidget_event,event->arg);
5964 }
5965#endif
5966
5953#if defined HAVE_INOTIFY || defined HAVE_KQUEUE || defined HAVE_GFILENOTIFY 5967#if defined HAVE_INOTIFY || defined HAVE_KQUEUE || defined HAVE_GFILENOTIFY
5954 case FILE_NOTIFY_EVENT: 5968 case FILE_NOTIFY_EVENT:
5955 { 5969 {
@@ -10956,6 +10970,10 @@ syms_of_keyboard (void)
10956 DEFSYM (Qdbus_event, "dbus-event"); 10970 DEFSYM (Qdbus_event, "dbus-event");
10957#endif 10971#endif
10958 10972
10973#ifdef HAVE_XWIDGETS
10974 DEFSYM (Qxwidget_event,"xwidget-event");
10975#endif
10976
10959#ifdef USE_FILE_NOTIFY 10977#ifdef USE_FILE_NOTIFY
10960 DEFSYM (Qfile_notify, "file-notify"); 10978 DEFSYM (Qfile_notify, "file-notify");
10961#endif /* USE_FILE_NOTIFY */ 10979#endif /* USE_FILE_NOTIFY */
diff --git a/src/lisp.h b/src/lisp.h
index 02b8078a9fd..8aa034e9e57 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -799,6 +799,12 @@ enum pvec_type
799 PVEC_WINDOW_CONFIGURATION, 799 PVEC_WINDOW_CONFIGURATION,
800 PVEC_SUBR, 800 PVEC_SUBR,
801 PVEC_OTHER, 801 PVEC_OTHER,
802
803#ifdef HAVE_XWIDGETS
804 PVEC_XWIDGET,
805 PVEC_XWIDGET_VIEW,
806#endif
807
802 /* These should be last, check internal_equal to see why. */ 808 /* These should be last, check internal_equal to see why. */
803 PVEC_COMPILED, 809 PVEC_COMPILED,
804 PVEC_CHAR_TABLE, 810 PVEC_CHAR_TABLE,
diff --git a/src/print.c b/src/print.c
index 269d8f250e2..4dd4e963093 100644
--- a/src/print.c
+++ b/src/print.c
@@ -33,6 +33,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
33#include "intervals.h" 33#include "intervals.h"
34#include "blockinput.h" 34#include "blockinput.h"
35 35
36#ifdef HAVE_XWIDGETS
37# include "xwidget.h"
38#endif
39
36#include <c-ctype.h> 40#include <c-ctype.h>
37#include <float.h> 41#include <float.h>
38#include <ftoastr.h> 42#include <ftoastr.h>
@@ -1736,6 +1740,18 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1736 print_c_string (XSUBR (obj)->symbol_name, printcharfun); 1740 print_c_string (XSUBR (obj)->symbol_name, printcharfun);
1737 printchar ('>', printcharfun); 1741 printchar ('>', printcharfun);
1738 } 1742 }
1743#ifdef HAVE_XWIDGETS
1744 else if (XWIDGETP (obj))
1745 {
1746 print_c_string ("#<xwidget ", printcharfun);
1747 printchar ('>', printcharfun);
1748 }
1749 else if (XWIDGET_VIEW_P (obj))
1750 {
1751 print_c_string ("#<xwidget ", printcharfun);
1752 printchar ('>', printcharfun);
1753 }
1754#endif
1739 else if (WINDOWP (obj)) 1755 else if (WINDOWP (obj))
1740 { 1756 {
1741 int len = sprintf (buf, "#<window %"pI"d", 1757 int len = sprintf (buf, "#<window %"pI"d",
diff --git a/src/termhooks.h b/src/termhooks.h
index 29223757621..c183528ee84 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -239,6 +239,11 @@ enum event_kind
239 , NS_NONKEY_EVENT 239 , NS_NONKEY_EVENT
240#endif 240#endif
241 241
242#ifdef HAVE_XWIDGETS
243 /* events generated by xwidgets*/
244 , XWIDGET_EVENT
245#endif
246
242#ifdef USE_FILE_NOTIFY 247#ifdef USE_FILE_NOTIFY
243 /* File or directory was changed. */ 248 /* File or directory was changed. */
244 , FILE_NOTIFY_EVENT 249 , FILE_NOTIFY_EVENT
diff --git a/src/window.c b/src/window.c
index 4aeb8b39a70..add2de38d18 100644
--- a/src/window.c
+++ b/src/window.c
@@ -41,6 +41,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
41#ifdef MSDOS 41#ifdef MSDOS
42#include "msdos.h" 42#include "msdos.h"
43#endif 43#endif
44#ifdef HAVE_XWIDGETS
45# include "xwidget.h"
46#endif
44 47
45static ptrdiff_t count_windows (struct window *); 48static ptrdiff_t count_windows (struct window *);
46static ptrdiff_t get_leaf_windows (struct window *, struct window **, 49static ptrdiff_t get_leaf_windows (struct window *, struct window **,
@@ -4368,6 +4371,9 @@ Signal an error when WINDOW is the only window on its frame. */)
4368 4371
4369 /* Block input. */ 4372 /* Block input. */
4370 block_input (); 4373 block_input ();
4374#ifdef HAVE_XWIDGETS
4375 xwidget_view_delete_all_in_window (w);
4376#endif
4371 window_resize_apply (p, horflag); 4377 window_resize_apply (p, horflag);
4372 /* If this window is referred to by the dpyinfo's mouse 4378 /* If this window is referred to by the dpyinfo's mouse
4373 highlight, invalidate that slot to be safe (Bug#9904). */ 4379 highlight, invalidate that slot to be safe (Bug#9904). */
diff --git a/src/xdisp.c b/src/xdisp.c
index d730a0bf1b6..89385c0e172 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -318,6 +318,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
318#include TERM_HEADER 318#include TERM_HEADER
319#endif /* HAVE_WINDOW_SYSTEM */ 319#endif /* HAVE_WINDOW_SYSTEM */
320 320
321#ifdef HAVE_XWIDGETS
322# include "xwidget.h"
323#endif
321#ifndef FRAME_X_OUTPUT 324#ifndef FRAME_X_OUTPUT
322#define FRAME_X_OUTPUT(f) ((f)->output_data.x) 325#define FRAME_X_OUTPUT(f) ((f)->output_data.x)
323#endif 326#endif
@@ -854,6 +857,9 @@ static bool next_element_from_buffer (struct it *);
854static bool next_element_from_composition (struct it *); 857static bool next_element_from_composition (struct it *);
855static bool next_element_from_image (struct it *); 858static bool next_element_from_image (struct it *);
856static bool next_element_from_stretch (struct it *); 859static bool next_element_from_stretch (struct it *);
860#ifdef HAVE_XWIDGETS
861static bool next_element_from_xwidget (struct it *);
862#endif
857static void load_overlay_strings (struct it *, ptrdiff_t); 863static void load_overlay_strings (struct it *, ptrdiff_t);
858static bool get_next_display_element (struct it *); 864static bool get_next_display_element (struct it *);
859static enum move_it_result 865static enum move_it_result
@@ -4690,6 +4696,9 @@ handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
4690 if (CONSP (spec) 4696 if (CONSP (spec)
4691 /* Simple specifications. */ 4697 /* Simple specifications. */
4692 && !EQ (XCAR (spec), Qimage) 4698 && !EQ (XCAR (spec), Qimage)
4699#ifdef HAVE_XWIDGETS
4700 && !EQ (XCAR (spec), Qxwidget)
4701#endif
4693 && !EQ (XCAR (spec), Qspace) 4702 && !EQ (XCAR (spec), Qspace)
4694 && !EQ (XCAR (spec), Qwhen) 4703 && !EQ (XCAR (spec), Qwhen)
4695 && !EQ (XCAR (spec), Qslice) 4704 && !EQ (XCAR (spec), Qslice)
@@ -5137,7 +5146,12 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5137 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p) 5146 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
5138 && valid_image_p (value)) 5147 && valid_image_p (value))
5139#endif /* not HAVE_WINDOW_SYSTEM */ 5148#endif /* not HAVE_WINDOW_SYSTEM */
5140 || (CONSP (value) && EQ (XCAR (value), Qspace))); 5149 || (CONSP (value) && EQ (XCAR (value), Qspace))
5150#ifdef HAVE_XWIDGETS
5151 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
5152 && valid_xwidget_spec_p (value))
5153#endif
5154 );
5141 5155
5142 if (valid_p && display_replaced == 0) 5156 if (valid_p && display_replaced == 0)
5143 { 5157 {
@@ -5212,6 +5226,17 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5212 *position = it->position = start_pos; 5226 *position = it->position = start_pos;
5213 retval = 1 + (it->area == TEXT_AREA); 5227 retval = 1 + (it->area == TEXT_AREA);
5214 } 5228 }
5229#ifdef HAVE_XWIDGETS
5230 else if (valid_xwidget_spec_p(value))
5231 {
5232 it->what = IT_XWIDGET;
5233 it->method = GET_FROM_XWIDGET;
5234 it->position = start_pos;
5235 it->object = NILP (object) ? it->w->contents : object;
5236 *position = start_pos;
5237 it->xwidget = lookup_xwidget(value);
5238 }
5239#endif
5215#ifdef HAVE_WINDOW_SYSTEM 5240#ifdef HAVE_WINDOW_SYSTEM
5216 else 5241 else
5217 { 5242 {
@@ -5964,6 +5989,11 @@ push_it (struct it *it, struct text_pos *position)
5964 case GET_FROM_STRETCH: 5989 case GET_FROM_STRETCH:
5965 p->u.stretch.object = it->object; 5990 p->u.stretch.object = it->object;
5966 break; 5991 break;
5992#ifdef HAVE_XWIDGETS
5993 case GET_FROM_XWIDGET:
5994 p->u.xwidget.object = it->object;
5995 break;
5996#endif
5967 case GET_FROM_BUFFER: 5997 case GET_FROM_BUFFER:
5968 case GET_FROM_DISPLAY_VECTOR: 5998 case GET_FROM_DISPLAY_VECTOR:
5969 case GET_FROM_STRING: 5999 case GET_FROM_STRING:
@@ -6065,6 +6095,11 @@ pop_it (struct it *it)
6065 it->object = p->u.image.object; 6095 it->object = p->u.image.object;
6066 it->slice = p->u.image.slice; 6096 it->slice = p->u.image.slice;
6067 break; 6097 break;
6098#ifdef HAVE_XWIDGETS
6099 case GET_FROM_XWIDGET:
6100 it->object = p->u.xwidget.object;
6101 break;
6102#endif
6068 case GET_FROM_STRETCH: 6103 case GET_FROM_STRETCH:
6069 it->object = p->u.stretch.object; 6104 it->object = p->u.stretch.object;
6070 break; 6105 break;
@@ -6739,7 +6774,10 @@ static next_element_function const get_next_element[NUM_IT_METHODS] =
6739 next_element_from_string, 6774 next_element_from_string,
6740 next_element_from_c_string, 6775 next_element_from_c_string,
6741 next_element_from_image, 6776 next_element_from_image,
6742 next_element_from_stretch 6777 next_element_from_stretch,
6778#ifdef HAVE_XWIDGETS
6779 next_element_from_xwidget,
6780#endif
6743}; 6781};
6744 6782
6745#define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it) 6783#define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it)
@@ -7600,6 +7638,10 @@ set_iterator_to_next (struct it *it, bool reseat_p)
7600 7638
7601 case GET_FROM_IMAGE: 7639 case GET_FROM_IMAGE:
7602 case GET_FROM_STRETCH: 7640 case GET_FROM_STRETCH:
7641#ifdef HAVE_XWIDGETS
7642 case GET_FROM_XWIDGET:
7643#endif
7644
7603 /* The position etc with which we have to proceed are on 7645 /* The position etc with which we have to proceed are on
7604 the stack. The position may be at the end of a string, 7646 the stack. The position may be at the end of a string,
7605 if the `display' property takes up the whole string. */ 7647 if the `display' property takes up the whole string. */
@@ -8061,6 +8103,15 @@ next_element_from_image (struct it *it)
8061 return true; 8103 return true;
8062} 8104}
8063 8105
8106#ifdef HAVE_XWIDGETS
8107static bool
8108next_element_from_xwidget (struct it *it)
8109{
8110 it->what = IT_XWIDGET;
8111 return true;
8112}
8113#endif
8114
8064 8115
8065/* Fill iterator IT with next display element from a stretch glyph 8116/* Fill iterator IT with next display element from a stretch glyph
8066 property. IT->object is the value of the text property. Value is 8117 property. IT->object is the value of the text property. Value is
@@ -18793,6 +18844,28 @@ dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
18793 glyph->left_box_line_p, 18844 glyph->left_box_line_p,
18794 glyph->right_box_line_p); 18845 glyph->right_box_line_p);
18795 } 18846 }
18847#ifdef HAVE_XWIDGETS
18848 else if (glyph->type == XWIDGET_GLYPH)
18849 {
18850 fprintf (stderr,
18851 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
18852 glyph - row->glyphs[TEXT_AREA],
18853 'X',
18854 glyph->charpos,
18855 (BUFFERP (glyph->object)
18856 ? 'B'
18857 : (STRINGP (glyph->object)
18858 ? 'S'
18859 : '-')),
18860 glyph->pixel_width,
18861 glyph->u.xwidget,
18862 '.',
18863 glyph->face_id,
18864 glyph->left_box_line_p,
18865 glyph->right_box_line_p);
18866
18867 }
18868#endif
18796} 18869}
18797 18870
18798 18871
@@ -24291,6 +24364,13 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
24291 24364
24292 return OK_PIXELS (width_p ? img->width : img->height); 24365 return OK_PIXELS (width_p ? img->width : img->height);
24293 } 24366 }
24367# ifdef HAVE_XWIDGETS
24368 if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop))
24369 {
24370 // TODO: Don't return dummy size.
24371 return OK_PIXELS (100);
24372 }
24373# endif
24294#endif 24374#endif
24295 if (EQ (car, Qplus) || EQ (car, Qminus)) 24375 if (EQ (car, Qplus) || EQ (car, Qminus))
24296 { 24376 {
@@ -24796,6 +24876,18 @@ fill_image_glyph_string (struct glyph_string *s)
24796} 24876}
24797 24877
24798 24878
24879#ifdef HAVE_XWIDGETS
24880static void
24881fill_xwidget_glyph_string (struct glyph_string *s)
24882{
24883 eassert (s->first_glyph->type == XWIDGET_GLYPH);
24884 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
24885 s->font = s->face->font;
24886 s->width = s->first_glyph->pixel_width;
24887 s->ybase += s->first_glyph->voffset;
24888 s->xwidget = s->first_glyph->u.xwidget;
24889}
24890#endif
24799/* Fill glyph string S from a sequence of stretch glyphs. 24891/* Fill glyph string S from a sequence of stretch glyphs.
24800 24892
24801 START is the index of the first glyph to consider, 24893 START is the index of the first glyph to consider,
@@ -25181,6 +25273,20 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
25181 } \ 25273 } \
25182 while (false) 25274 while (false)
25183 25275
25276#ifdef HAVE_XWIDGETS
25277#define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
25278 do \
25279 { \
25280 s = alloca (sizeof *s); \
25281 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
25282 fill_xwidget_glyph_string (s); \
25283 append_glyph_string (&(HEAD), &(TAIL), s); \
25284 ++(START); \
25285 s->x = (X); \
25286 } \
25287 while (false)
25288#endif
25289
25184 25290
25185/* Add a glyph string for a sequence of character glyphs to the list 25291/* Add a glyph string for a sequence of character glyphs to the list
25186 of strings between HEAD and TAIL. START is the index of the first 25292 of strings between HEAD and TAIL. START is the index of the first
@@ -25302,7 +25408,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
25302 to allocate glyph strings (because draw_glyphs can be called 25408 to allocate glyph strings (because draw_glyphs can be called
25303 asynchronously). */ 25409 asynchronously). */
25304 25410
25305#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \ 25411#define BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
25306 do \ 25412 do \
25307 { \ 25413 { \
25308 HEAD = TAIL = NULL; \ 25414 HEAD = TAIL = NULL; \
@@ -25333,8 +25439,17 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
25333 case IMAGE_GLYPH: \ 25439 case IMAGE_GLYPH: \
25334 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \ 25440 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \
25335 HL, X, LAST_X); \ 25441 HL, X, LAST_X); \
25336 break; \ 25442 break;
25337 \ 25443
25444#ifdef HAVE_XWIDGETS
25445# define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
25446 case XWIDGET_GLYPH: \
25447 BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL, \
25448 HL, X, LAST_X); \
25449 break;
25450#endif
25451
25452#define BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) \
25338 case GLYPHLESS_GLYPH: \ 25453 case GLYPHLESS_GLYPH: \
25339 BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \ 25454 BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \
25340 HL, X, LAST_X); \ 25455 HL, X, LAST_X); \
@@ -25353,6 +25468,18 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
25353 } while (false) 25468 } while (false)
25354 25469
25355 25470
25471#ifdef HAVE_XWIDGETS
25472# define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
25473 BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
25474 BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
25475 BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
25476#else
25477# define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
25478 BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
25479 BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
25480#endif
25481
25482
25356/* Draw glyphs between START and END in AREA of ROW on window W, 25483/* Draw glyphs between START and END in AREA of ROW on window W,
25357 starting at x-position X. X is relative to AREA in W. HL is a 25484 starting at x-position X. X is relative to AREA in W. HL is a
25358 face-override with the following meaning: 25485 face-override with the following meaning:
@@ -25991,6 +26118,109 @@ produce_image_glyph (struct it *it)
25991 } 26118 }
25992} 26119}
25993 26120
26121#ifdef HAVE_XWIDGETS
26122static void
26123produce_xwidget_glyph (struct it *it)
26124{
26125 struct xwidget *xw;
26126 int glyph_ascent, crop;
26127 eassert (it->what == IT_XWIDGET);
26128
26129 struct face *face = FACE_FROM_ID (it->f, it->face_id);
26130 eassert (face);
26131 /* Make sure X resources of the face is loaded. */
26132 prepare_face_for_display (it->f, face);
26133
26134 xw = it->xwidget;
26135 it->ascent = it->phys_ascent = glyph_ascent = xw->height/2;
26136 it->descent = xw->height/2;
26137 it->phys_descent = it->descent;
26138 it->pixel_width = xw->width;
26139 /* It's quite possible for images to have an ascent greater than
26140 their height, so don't get confused in that case. */
26141 if (it->descent < 0)
26142 it->descent = 0;
26143
26144 it->nglyphs = 1;
26145
26146 if (face->box != FACE_NO_BOX)
26147 {
26148 if (face->box_line_width > 0)
26149 {
26150 it->ascent += face->box_line_width;
26151 it->descent += face->box_line_width;
26152 }
26153
26154 if (it->start_of_box_run_p)
26155 it->pixel_width += eabs (face->box_line_width);
26156 it->pixel_width += eabs (face->box_line_width);
26157 }
26158
26159 take_vertical_position_into_account (it);
26160
26161 /* Automatically crop wide image glyphs at right edge so we can
26162 draw the cursor on same display row. */
26163 crop = it->pixel_width - (it->last_visible_x - it->current_x);
26164 if (crop > 0 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
26165 it->pixel_width -= crop;
26166
26167 if (it->glyph_row)
26168 {
26169 enum glyph_row_area area = it->area;
26170 struct glyph *glyph
26171 = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
26172
26173 if (it->glyph_row->reversed_p)
26174 {
26175 struct glyph *g;
26176
26177 /* Make room for the new glyph. */
26178 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
26179 g[1] = *g;
26180 glyph = it->glyph_row->glyphs[it->area];
26181 }
26182 if (glyph < it->glyph_row->glyphs[area + 1])
26183 {
26184 glyph->charpos = CHARPOS (it->position);
26185 glyph->object = it->object;
26186 glyph->pixel_width = it->pixel_width;
26187 glyph->ascent = glyph_ascent;
26188 glyph->descent = it->descent;
26189 glyph->voffset = it->voffset;
26190 glyph->type = XWIDGET_GLYPH;
26191 glyph->avoid_cursor_p = it->avoid_cursor_p;
26192 glyph->multibyte_p = it->multibyte_p;
26193 if (it->glyph_row->reversed_p && area == TEXT_AREA)
26194 {
26195 /* In R2L rows, the left and the right box edges need to be
26196 drawn in reverse direction. */
26197 glyph->right_box_line_p = it->start_of_box_run_p;
26198 glyph->left_box_line_p = it->end_of_box_run_p;
26199 }
26200 else
26201 {
26202 glyph->left_box_line_p = it->start_of_box_run_p;
26203 glyph->right_box_line_p = it->end_of_box_run_p;
26204 }
26205 glyph->overlaps_vertically_p = 0;
26206 glyph->padding_p = 0;
26207 glyph->glyph_not_available_p = 0;
26208 glyph->face_id = it->face_id;
26209 glyph->u.xwidget = it->xwidget;
26210 glyph->font_type = FONT_TYPE_UNKNOWN;
26211 if (it->bidi_p)
26212 {
26213 glyph->resolved_level = it->bidi_it.resolved_level;
26214 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
26215 glyph->bidi_type = it->bidi_it.type;
26216 }
26217 ++it->glyph_row->used[area];
26218 }
26219 else
26220 IT_EXPAND_MATRIX_WIDTH (it, area);
26221 }
26222}
26223#endif
25994 26224
25995/* Append a stretch glyph to IT->glyph_row. OBJECT is the source 26225/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
25996 of the glyph, WIDTH and HEIGHT are the width and height of the 26226 of the glyph, WIDTH and HEIGHT are the width and height of the
@@ -27401,6 +27631,10 @@ x_produce_glyphs (struct it *it)
27401 produce_image_glyph (it); 27631 produce_image_glyph (it);
27402 else if (it->what == IT_STRETCH) 27632 else if (it->what == IT_STRETCH)
27403 produce_stretch_glyph (it); 27633 produce_stretch_glyph (it);
27634#ifdef HAVE_XWIDGETS
27635 else if (it->what == IT_XWIDGET)
27636 produce_xwidget_glyph (it);
27637#endif
27404 27638
27405 done: 27639 done:
27406 /* Accumulate dimensions. Note: can't assume that it->descent > 0 27640 /* Accumulate dimensions. Note: can't assume that it->descent > 0
@@ -27770,6 +28004,10 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
27770 /* Use normal cursor if not blinked off. */ 28004 /* Use normal cursor if not blinked off. */
27771 if (!w->cursor_off_p) 28005 if (!w->cursor_off_p)
27772 { 28006 {
28007#ifdef HAVE_XWIDGETS
28008 if (glyph != NULL && glyph->type == XWIDGET_GLYPH)
28009 return NO_CURSOR;
28010#endif
27773 if (glyph != NULL && glyph->type == IMAGE_GLYPH) 28011 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
27774 { 28012 {
27775 if (cursor_type == FILLED_BOX_CURSOR) 28013 if (cursor_type == FILLED_BOX_CURSOR)
diff --git a/src/xterm.c b/src/xterm.c
index 5a6d643bad4..44eed22d2ec 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -62,6 +62,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
62#include "composite.h" 62#include "composite.h"
63#include "frame.h" 63#include "frame.h"
64#include "dispextern.h" 64#include "dispextern.h"
65#ifdef HAVE_XWIDGETS
66# include "xwidget.h"
67#endif
65#include "fontset.h" 68#include "fontset.h"
66#include "termhooks.h" 69#include "termhooks.h"
67#include "termopts.h" 70#include "termopts.h"
@@ -3511,6 +3514,12 @@ x_draw_glyph_string (struct glyph_string *s)
3511 x_draw_image_glyph_string (s); 3514 x_draw_image_glyph_string (s);
3512 break; 3515 break;
3513 3516
3517#ifdef HAVE_XWIDGETS
3518 case XWIDGET_GLYPH:
3519 x_draw_xwidget_glyph_string (s);
3520 break;
3521#endif
3522
3514 case STRETCH_GLYPH: 3523 case STRETCH_GLYPH:
3515 x_draw_stretch_glyph_string (s); 3524 x_draw_stretch_glyph_string (s);
3516 break; 3525 break;
@@ -8920,6 +8929,11 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
8920 if (cursor_glyph == NULL) 8929 if (cursor_glyph == NULL)
8921 return; 8930 return;
8922 8931
8932#ifdef HAVE_XWIDGETS
8933 if (cursor_glyph->type == XWIDGET_GLYPH)
8934 return; // Experimental avoidance of cursor on xwidget.
8935#endif
8936
8923 /* If on an image, draw like a normal cursor. That's usually better 8937 /* If on an image, draw like a normal cursor. That's usually better
8924 visible than drawing a bar, esp. if the image is large so that 8938 visible than drawing a bar, esp. if the image is large so that
8925 the bar might not be in the window. */ 8939 the bar might not be in the window. */
diff --git a/src/xwidget.c b/src/xwidget.c
new file mode 100644
index 00000000000..ea5dea0f9fe
--- /dev/null
+++ b/src/xwidget.c
@@ -0,0 +1,1320 @@
1/* Support for embedding graphical components in a buffer.
2
3Copyright (C) 2011-2016 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19
20#include <config.h>
21
22
23#include <signal.h>
24
25#include <stdio.h>
26#include <setjmp.h>
27#ifdef HAVE_X_WINDOWS
28
29#include "lisp.h"
30#include "blockinput.h"
31#include "syssignal.h"
32
33#include "xterm.h"
34#include <X11/cursorfont.h>
35
36#ifndef makedev
37# include <sys/types.h>
38#endif
39
40#ifdef BSD_SYSTEM
41# include <sys/ioctl.h>
42#endif
43
44#include "systime.h"
45
46#ifndef INCLUDED_FCNTL
47# include <fcntl.h>
48#endif
49#include <ctype.h>
50#include <errno.h>
51#include <setjmp.h>
52#include <sys/stat.h>
53
54#include "charset.h"
55#include "character.h"
56#include "coding.h"
57#include "ccl.h"
58#include "frame.h"
59#include "dispextern.h"
60#include "fontset.h"
61#include "termhooks.h"
62#include "termopts.h"
63#include "termchar.h"
64#include "disptab.h"
65#include "buffer.h"
66#include "window.h"
67#include "keyboard.h"
68#include "intervals.h"
69#include "process.h"
70#include "atimer.h"
71#include "keymap.h"
72
73
74#ifdef USE_X_TOOLKIT
75#include <X11/Shell.h>
76#endif
77#include <X11/extensions/Xcomposite.h>
78#include <X11/extensions/Xrender.h>
79#include <cairo.h>
80#ifdef HAVE_SYS_TIME_H
81#include <sys/time.h>
82#endif
83#ifdef HAVE_UNISTD_H
84#include <unistd.h>
85#endif
86
87#include "gtkutil.h"
88#include "font.h"
89#endif /* HAVE_X_WINDOWS */
90
91#include <gtk/gtk.h>
92#include <gdk/gdk.h>
93
94#include <gtk/gtkx.h>
95
96#include "emacsgtkfixed.h"
97
98#include <wchar.h>
99
100#include <webkit/webkitwebview.h>
101#include <webkit/webkitwebplugindatabase.h>
102#include <webkit/webkitwebplugin.h>
103#include <webkit/webkitglobals.h>
104#include <webkit/webkitwebnavigationaction.h>
105#include <webkit/webkitdownload.h>
106#include <webkit/webkitwebpolicydecision.h>
107
108#include "xwidget.h"
109
110static struct xwidget *
111allocate_xwidget (void)
112{
113 return ALLOCATE_PSEUDOVECTOR (struct xwidget, height, PVEC_XWIDGET);
114}
115
116static struct xwidget_view *
117allocate_xwidget_view (void)
118{
119 return ALLOCATE_PSEUDOVECTOR (struct xwidget_view, redisplayed,
120 PVEC_XWIDGET_VIEW);
121}
122
123#define XSETXWIDGET(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET))
124#define XSETXWIDGET_VIEW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET_VIEW))
125
126static struct xwidget_view *xwidget_view_lookup (struct xwidget *,
127 struct window *);
128static void webkit_document_load_finished_cb (WebKitWebView *, WebKitWebFrame *,
129 gpointer);
130static gboolean webkit_download_cb (WebKitWebView *, WebKitDownload *, gpointer);
131
132static gboolean
133webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *,
134 WebKitWebFrame *,
135 WebKitNetworkRequest *,
136 gchar *,
137 WebKitWebPolicyDecision *,
138 gpointer);
139
140static gboolean
141webkit_new_window_policy_decision_requested_cb (WebKitWebView *,
142 WebKitWebFrame *,
143 WebKitNetworkRequest *,
144 WebKitWebNavigationAction *,
145 WebKitWebPolicyDecision *,
146 gpointer);
147
148static gboolean
149webkit_navigation_policy_decision_requested_cb (WebKitWebView *,
150 WebKitWebFrame *,
151 WebKitNetworkRequest *,
152 WebKitWebNavigationAction *,
153 WebKitWebPolicyDecision *,
154 gpointer);
155
156
157
158DEFUN ("make-xwidget",
159 Fmake_xwidget, Smake_xwidget,
160 7, 8, 0,
161 doc: /* Make an xwidget from BEG to END of TYPE.
162If BUFFER is nil, use the current buffer.
163If BUFFER is a string and no such buffer exists, create it.
164TYPE is a symbol which can take one of the following values:
165
166- webkit_osr
167
168Returns the newly constructed xwidget, or nil if construction fails. */)
169 (Lisp_Object beg, Lisp_Object end,
170 Lisp_Object type,
171 Lisp_Object title,
172 Lisp_Object width, Lisp_Object height,
173 Lisp_Object arguments, Lisp_Object buffer)
174{
175 //should work a bit like "make-button"(make-button BEG END &rest PROPERTIES)
176 // arg "type" and fwd should be keyword args eventually
177 //(make-xwidget 3 3 'button "oei" 31 31 nil)
178 //(xwidget-info (car xwidget-list))
179 struct xwidget *xw = allocate_xwidget ();
180 Lisp_Object val;
181 xw->type = type;
182 xw->title = title;
183 if (NILP (buffer))
184 buffer = Fcurrent_buffer (); // no need to gcpro because
185 // Fcurrent_buffer doesn't
186 // call Feval/eval_sub.
187 else
188 buffer = Fget_buffer_create (buffer);
189 xw->buffer = buffer;
190
191 xw->height = XFASTINT (height);
192 xw->width = XFASTINT (width);
193 xw->kill_without_query = 0;
194 XSETXWIDGET (val, xw); // set the vectorlike_header of VAL
195 // with the correct value
196 Vxwidget_list = Fcons (val, Vxwidget_list);
197 xw->widgetwindow_osr = NULL;
198 xw->widget_osr = NULL;
199 xw->plist = Qnil;
200
201
202 if (EQ (xw->type, Qwebkit_osr))
203 {
204 block_input ();
205 xw->widgetwindow_osr = gtk_offscreen_window_new ();
206 gtk_window_resize (GTK_WINDOW (xw->widgetwindow_osr), xw->width,
207 xw->height);
208 xw->widgetscrolledwindow_osr = NULL; //webkit osr is the
209 //only scrolled
210 //component atm
211
212 if (EQ (xw->type, Qwebkit_osr))
213 {
214 xw->widgetscrolledwindow_osr = gtk_scrolled_window_new (NULL, NULL);
215 gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW
216 (xw->
217 widgetscrolledwindow_osr),
218 xw->height);
219 gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW
220 (xw->
221 widgetscrolledwindow_osr),
222 xw->width);
223 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW
224 (xw->widgetscrolledwindow_osr),
225 GTK_POLICY_ALWAYS,
226 GTK_POLICY_ALWAYS);
227
228 xw->widget_osr = webkit_web_view_new ();
229 gtk_container_add (GTK_CONTAINER (xw->widgetscrolledwindow_osr),
230 GTK_WIDGET (WEBKIT_WEB_VIEW (xw->widget_osr)));
231 }
232
233 gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width,
234 xw->height);
235
236 if (EQ (xw->type, Qwebkit_osr))
237 {
238 gtk_container_add (GTK_CONTAINER (xw->widgetwindow_osr),
239 xw->widgetscrolledwindow_osr);
240 }
241 else
242 {
243 gtk_container_add (GTK_CONTAINER (xw->widgetwindow_osr),
244 xw->widget_osr);
245 }
246
247 gtk_widget_show (xw->widget_osr);
248 gtk_widget_show (xw->widgetwindow_osr);
249 gtk_widget_show (xw->widgetscrolledwindow_osr);
250
251 /* store some xwidget data in the gtk widgets for convenient
252 retrieval in the event handlers. */
253 g_object_set_data (G_OBJECT (xw->widget_osr), XG_XWIDGET,
254 (gpointer) (xw));
255 g_object_set_data (G_OBJECT (xw->widgetwindow_osr), XG_XWIDGET,
256 (gpointer) (xw));
257
258 /* signals */
259 if (EQ (xw->type, Qwebkit_osr))
260 {
261 g_signal_connect (G_OBJECT (xw->widget_osr),
262 "document-load-finished",
263 G_CALLBACK (webkit_document_load_finished_cb), xw);
264
265 g_signal_connect (G_OBJECT (xw->widget_osr),
266 "download-requested",
267 G_CALLBACK (webkit_download_cb), xw);
268
269 g_signal_connect (G_OBJECT (xw->widget_osr),
270 "mime-type-policy-decision-requested",
271 G_CALLBACK
272 (webkit_mime_type_policy_typedecision_requested_cb),
273 xw);
274
275 g_signal_connect (G_OBJECT (xw->widget_osr),
276 "new-window-policy-decision-requested",
277 G_CALLBACK
278 (webkit_new_window_policy_decision_requested_cb),
279 xw);
280
281 g_signal_connect (G_OBJECT (xw->widget_osr),
282 "navigation-policy-decision-requested",
283 G_CALLBACK
284 (webkit_navigation_policy_decision_requested_cb),
285 xw);
286 }
287
288 unblock_input ();
289
290 }
291
292 return val;
293}
294
295DEFUN ("get-buffer-xwidgets", Fget_buffer_xwidgets, Sget_buffer_xwidgets,
296 1, 1, 0,
297 doc: /* Return a list of xwidgets associated with BUFFER.
298BUFFER may be a buffer or the name of one. */)
299 (Lisp_Object buffer)
300{
301 Lisp_Object xw, tail, xw_list;
302
303 if (NILP (buffer))
304 return Qnil;
305 buffer = Fget_buffer (buffer);
306 if (NILP (buffer))
307 return Qnil;
308
309 xw_list = Qnil;
310
311 for (tail = Vxwidget_list; CONSP (tail); tail = XCDR (tail))
312 {
313 xw = XCAR (tail);
314 if (XWIDGETP (xw) && EQ (Fxwidget_buffer (xw), buffer))
315 xw_list = Fcons (xw, xw_list);
316 }
317 return xw_list;
318}
319
320static int
321xwidget_hidden (struct xwidget_view *xv)
322{
323 return xv->hidden;
324}
325
326
327
328static void
329xwidget_show_view (struct xwidget_view *xv)
330{
331 xv->hidden = 0;
332 gtk_widget_show (xv->widgetwindow);
333 gtk_fixed_move (GTK_FIXED (xv->emacswindow),
334 xv->widgetwindow,
335 xv->x + xv->clip_left,
336 xv->y + xv->clip_top);
337}
338
339
340/* Hide an xvidget view. */
341static void
342xwidget_hide_view (struct xwidget_view *xv)
343{
344 xv->hidden = 1;
345 gtk_fixed_move (GTK_FIXED (xv->emacswindow), xv->widgetwindow,
346 10000, 10000);
347}
348
349
350
351/* When the off-screen webkit master view changes this signal is called.
352 It copies the bitmap from the off-screen instance. */
353static gboolean
354offscreen_damage_event (GtkWidget * widget, GdkEvent * event,
355 gpointer xv_widget)
356{
357 // Queue a redraw of onscreen widget.
358 // There is a guard against receiving an invalid widget,
359 // which should only happen if we failed to remove the
360 // specific signal handler for the damage event.
361 if (GTK_IS_WIDGET (xv_widget))
362 gtk_widget_queue_draw (GTK_WIDGET (xv_widget));
363 else
364 printf ("Warning, offscreen_damage_event received invalid xv pointer:%p\n",
365 (void *) xv_widget);
366
367 return FALSE;
368}
369
370static void
371store_xwidget_event_string (struct xwidget *xw, const char *eventname,
372 const char *eventstr)
373{
374 struct input_event event;
375 Lisp_Object xwl;
376 XSETXWIDGET (xwl, xw);
377 EVENT_INIT (event);
378 event.kind = XWIDGET_EVENT;
379 event.frame_or_window = Qnil;
380
381 event.arg = Qnil;
382 event.arg = Fcons (build_string (eventstr), event.arg);
383 event.arg = Fcons (xwl, event.arg);
384 event.arg = Fcons (intern (eventname), event.arg);
385 kbd_buffer_store_event (&event);
386
387}
388
389//TODO deprecated, use load-status
390void
391webkit_document_load_finished_cb (WebKitWebView * webkitwebview,
392 WebKitWebFrame * arg1,
393 gpointer data)
394{
395 struct xwidget *xw =
396 (struct xwidget *) g_object_get_data (G_OBJECT (webkitwebview),
397 XG_XWIDGET);
398
399 store_xwidget_event_string (xw, "document-load-finished", "");
400}
401
402gboolean
403webkit_download_cb (WebKitWebView * webkitwebview,
404 WebKitDownload * arg1,
405 gpointer data)
406{
407 struct xwidget *xw =
408 (struct xwidget *) g_object_get_data (G_OBJECT (webkitwebview),
409 XG_XWIDGET);
410 store_xwidget_event_string (xw, "download-requested",
411 webkit_download_get_uri (arg1));
412
413 return FALSE;
414}
415
416static gboolean
417webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *webView,
418 WebKitWebFrame *frame,
419 WebKitNetworkRequest * request,
420 gchar * mimetype,
421 WebKitWebPolicyDecision *policy_decision,
422 gpointer user_data)
423{
424 // This function makes webkit send a download signal for all unknown
425 // mime types. TODO Defer the decision to lisp, so that its possible
426 // to make Emacs handle teext mime for instance.xs
427 if (!webkit_web_view_can_show_mime_type (webView, mimetype))
428 {
429 webkit_web_policy_decision_download (policy_decision);
430 return TRUE;
431 }
432 else
433 {
434 return FALSE;
435 }
436}
437
438
439static gboolean
440webkit_new_window_policy_decision_requested_cb (WebKitWebView *webView,
441 WebKitWebFrame *frame,
442 WebKitNetworkRequest *request,
443 WebKitWebNavigationAction *navigation_action,
444 WebKitWebPolicyDecision *policy_decision,
445 gpointer user_data)
446{
447 struct xwidget *xw =
448 (struct xwidget *) g_object_get_data (G_OBJECT (webView), XG_XWIDGET);
449 webkit_web_navigation_action_get_original_uri (navigation_action);
450
451 store_xwidget_event_string (xw, "new-window-policy-decision-requested",
452 webkit_web_navigation_action_get_original_uri
453 (navigation_action));
454 return FALSE;
455}
456
457static gboolean
458webkit_navigation_policy_decision_requested_cb (WebKitWebView *webView,
459 WebKitWebFrame *frame,
460 WebKitNetworkRequest *request,
461 WebKitWebNavigationAction *navigation_action,
462 WebKitWebPolicyDecision * policy_decision,
463 gpointer user_data)
464{
465 struct xwidget *xw =
466 (struct xwidget *) g_object_get_data (G_OBJECT (webView), XG_XWIDGET);
467 store_xwidget_event_string (xw, "navigation-policy-decision-requested",
468 webkit_web_navigation_action_get_original_uri
469 (navigation_action));
470 return FALSE;
471}
472
473// For gtk3 offscreen rendered widgets.
474static gboolean
475xwidget_osr_draw_cb (GtkWidget * widget, cairo_t * cr, gpointer data)
476{
477 struct xwidget *xw =
478 (struct xwidget *) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
479 struct xwidget_view *xv =
480 (struct xwidget_view *) g_object_get_data (G_OBJECT (widget),
481 XG_XWIDGET_VIEW);
482
483 cairo_rectangle (cr, 0, 0, xv->clip_right, xv->clip_bottom);
484 cairo_clip (cr);
485
486 if (xw->widgetscrolledwindow_osr != NULL)
487 gtk_widget_draw (xw->widgetscrolledwindow_osr, cr);
488 else
489 gtk_widget_draw (xw->widget_osr, cr);
490 return FALSE;
491}
492
493static gboolean
494xwidget_osr_event_forward (GtkWidget * widget,
495 GdkEvent * event,
496 gpointer user_data)
497{
498 /* Copy events that arrive at the outer widget to the offscreen widget. */
499 struct xwidget *xw =
500 (struct xwidget *) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
501 GdkEvent *eventcopy = gdk_event_copy (event);
502 eventcopy->any.window = gtk_widget_get_window (xw->widget_osr);
503
504 //TODO This might leak events. They should be deallocated later,
505 //perhaps in xwgir_event_cb
506 gtk_main_do_event (eventcopy);
507 return TRUE; //dont propagate this event furter
508}
509
510
511static gboolean
512xwidget_osr_event_set_embedder (GtkWidget * widget,
513 GdkEvent * event, gpointer data)
514{
515 struct xwidget_view *xv = (struct xwidget_view *) data;
516 struct xwidget *xww = XXWIDGET (xv->model);
517 gdk_offscreen_window_set_embedder (gtk_widget_get_window
518 (xww->widgetwindow_osr),
519 gtk_widget_get_window (xv->widget));
520 return FALSE;
521}
522
523
524/* Initializes and does initial placement of an xwidget view on screen. */
525static struct xwidget_view *
526xwidget_init_view (struct xwidget *xww,
527 struct glyph_string *s,
528 int x, int y)
529{
530 struct xwidget_view *xv = allocate_xwidget_view ();
531 Lisp_Object val;
532
533 XSETXWIDGET_VIEW (val, xv);
534 Vxwidget_view_list = Fcons (val, Vxwidget_view_list);
535
536 XSETWINDOW (xv->w, s->w);
537 XSETXWIDGET (xv->model, xww);
538
539 if (EQ (xww->type, Qwebkit_osr))
540 {
541 xv->widget = gtk_drawing_area_new ();
542 // Expose event handling.
543 gtk_widget_set_app_paintable (xv->widget, TRUE);
544 gtk_widget_add_events (xv->widget, GDK_ALL_EVENTS_MASK);
545
546 /* Draw the view on damage-event */
547 g_signal_connect (G_OBJECT (xww->widgetwindow_osr), "damage-event",
548 G_CALLBACK (offscreen_damage_event), xv->widget);
549
550 if (EQ (xww->type, Qwebkit_osr))
551 {
552 g_signal_connect (G_OBJECT (xv->widget), "button-press-event",
553 G_CALLBACK (xwidget_osr_event_forward), NULL);
554 g_signal_connect (G_OBJECT (xv->widget), "button-release-event",
555 G_CALLBACK (xwidget_osr_event_forward), NULL);
556 g_signal_connect (G_OBJECT (xv->widget), "motion-notify-event",
557 G_CALLBACK (xwidget_osr_event_forward), NULL);
558 }
559 else
560 {
561 // xwgir debug , orthogonal to forwarding
562 g_signal_connect (G_OBJECT (xv->widget), "enter-notify-event",
563 G_CALLBACK (xwidget_osr_event_set_embedder), xv);
564 }
565 g_signal_connect (G_OBJECT (xv->widget), "draw",
566 G_CALLBACK (xwidget_osr_draw_cb), NULL);
567 }
568 // Widget realization.
569
570 // Make container widget 1st, and put the actual widget inside the
571 // container later. Drawing should crop container window if necessary
572 // to handle case where xwidget is partially obscured by other Emacs
573 // windows. Other containers than gtk_fixed where explored, but
574 // gtk_fixed had the most predictable behaviour so far.
575 xv->emacswindow = FRAME_GTK_WIDGET (s->f);
576 xv->widgetwindow = gtk_fixed_new ();
577 gtk_widget_set_has_window (xv->widgetwindow, TRUE);
578 gtk_container_add (GTK_CONTAINER (xv->widgetwindow), xv->widget);
579
580 // Store some xwidget data in the gtk widgets.
581 // The emacs frame.
582 g_object_set_data (G_OBJECT (xv->widget), XG_FRAME_DATA, (gpointer) (s->f));
583 // The xwidget.
584 g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET, (gpointer) (xww));
585 // The xwidget.
586 g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET_VIEW, (gpointer) (xv));
587 // The xwidget window.
588 g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET, (gpointer) (xww));
589 // the xwidget view.
590 g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET_VIEW,
591 (gpointer) (xv));
592
593
594 gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xww->width,
595 xww->height);
596 gtk_widget_set_size_request (xv->widgetwindow, xww->width, xww->height);
597 gtk_fixed_put (GTK_FIXED (FRAME_GTK_WIDGET (s->f)), xv->widgetwindow, x, y);
598 xv->x = x;
599 xv->y = y;
600 gtk_widget_show_all (xv->widgetwindow);
601
602
603 return xv;
604}
605
606
607void
608x_draw_xwidget_glyph_string (struct glyph_string *s)
609{
610 /* This method is called by the redisplay engine and places the
611 xwidget on screen. Moving and clipping is done here. Also view
612 initialization.
613 */
614 struct xwidget *xww = s->xwidget;
615 struct xwidget_view *xv = xwidget_view_lookup (xww, s->w);
616 int clip_right;
617 int clip_bottom;
618 int clip_top;
619 int clip_left;
620
621 int x = s->x;
622 int y = s->y + (s->height / 2) - (xww->height / 2);
623 int moved = 0;
624
625 /* We do initialization here in the display loop because there is no
626 other time to know things like window placement etc.
627 */
628 xv = xwidget_init_view (xww, s, x, y);
629
630 // Calculate clipping, which is used for all manner of onscreen
631 // xwidget views. Each widget border can get clipped by other emacs
632 // objects so there are four clipping variables.
633 clip_right =
634 min (xww->width,
635 WINDOW_RIGHT_EDGE_X (s->w) - x -
636 WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w) -
637 WINDOW_RIGHT_FRINGE_WIDTH (s->w));
638 clip_left =
639 max (0,
640 WINDOW_LEFT_EDGE_X (s->w) - x +
641 WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (s->w) +
642 WINDOW_LEFT_FRINGE_WIDTH (s->w));
643
644 clip_bottom =
645 min (xww->height,
646 WINDOW_BOTTOM_EDGE_Y (s->w) - WINDOW_MODE_LINE_HEIGHT (s->w) - y);
647 clip_top = max (0, WINDOW_TOP_EDGE_Y (s->w) - y);
648
649 // We are conserned with movement of the onscreen area. The area
650 // might sit still when the widget actually moves. This happens
651 // when an Emacs window border moves across a widget window. So, if
652 // any corner of the outer widget clipping window moves, that counts
653 // as movement here, even if it looks like no movement happens
654 // because the widget sits still inside the clipping area. The
655 // widget can also move inside the clipping area, which happens
656 // later
657 moved = (xv->x + xv->clip_left != x + clip_left)
658 || ((xv->y + xv->clip_top) != (y + clip_top));
659 xv->x = x;
660 xv->y = y;
661 if (moved) // Has it moved?
662 {
663 gtk_fixed_move (GTK_FIXED (FRAME_GTK_WIDGET (s->f)),
664 xv->widgetwindow, x + clip_left, y + clip_top);
665 }
666 // Clip the widget window if some parts happen to be outside
667 // drawable area. An Emacs window is not a gtk window. A gtk window
668 // covers the entire frame. Clipping might have changed even if we
669 // havent actualy moved, we try figure out when we need to reclip
670 // for real.
671 if ((xv->clip_right != clip_right)
672 || (xv->clip_bottom != clip_bottom)
673 || (xv->clip_top != clip_top) || (xv->clip_left != clip_left))
674 {
675 gtk_widget_set_size_request (xv->widgetwindow, clip_right + clip_left,
676 clip_bottom + clip_top);
677 gtk_fixed_move (GTK_FIXED (xv->widgetwindow), xv->widget, -clip_left,
678 -clip_top);
679
680 xv->clip_right = clip_right;
681 xv->clip_bottom = clip_bottom;
682 xv->clip_top = clip_top;
683 xv->clip_left = clip_left;
684 }
685 // If emacs wants to repaint the area where the widget lives, queue
686 // a redraw. It seems its possible to get out of sync with emacs
687 // redraws so emacs background sometimes shows up instead of the
688 // xwidgets background. It's just a visual glitch though.
689 if (!xwidget_hidden (xv))
690 {
691 gtk_widget_queue_draw (xv->widgetwindow);
692 gtk_widget_queue_draw (xv->widget);
693 }
694}
695
696
697// Macro that checks WEBKIT_IS_WEB_VIEW(xw->widget_osr) first
698#define WEBKIT_FN_INIT() \
699 struct xwidget* xw; \
700 CHECK_XWIDGET (xwidget); \
701 if (NILP (xwidget)) {printf("ERROR xwidget nil\n"); return Qnil;}; \
702 xw = XXWIDGET (xwidget); \
703 if (NULL == xw) printf("ERROR xw is 0\n"); \
704 if ((NULL == xw->widget_osr) || !WEBKIT_IS_WEB_VIEW(xw->widget_osr)){ \
705 printf ("ERROR xw->widget_osr does not hold a webkit instance\n");\
706 return Qnil;\
707 };
708
709
710DEFUN ("xwidget-webkit-goto-uri",
711 Fxwidget_webkit_goto_uri, Sxwidget_webkit_goto_uri,
712 2, 2, 0,
713 doc: /* Make the xwidget webkit instance referenced by XWIDGET browse URI. */)
714 (Lisp_Object xwidget, Lisp_Object uri)
715{
716 WEBKIT_FN_INIT ();
717 CHECK_STRING (uri);
718 webkit_web_view_load_uri (WEBKIT_WEB_VIEW (xw->widget_osr), SSDATA (uri));
719 return Qnil;
720}
721
722
723DEFUN ("xwidget-webkit-execute-script",
724 Fxwidget_webkit_execute_script, Sxwidget_webkit_execute_script,
725 2, 2, 0,
726 doc: /* Make the Webkit XWIDGET execute javascript SCRIPT. */)
727 (Lisp_Object xwidget, Lisp_Object script)
728{
729 WEBKIT_FN_INIT ();
730 CHECK_STRING (script);
731 webkit_web_view_execute_script (WEBKIT_WEB_VIEW (xw->widget_osr),
732 SSDATA (script));
733 return Qnil;
734}
735
736DEFUN ("xwidget-webkit-get-title",
737 Fxwidget_webkit_get_title, Sxwidget_webkit_get_title,
738 1, 1, 0,
739 doc: /* Return the title from the Webkit instance in XWIDGET.
740This can be used to work around the lack of a return value from the
741exec method. */ )
742 (Lisp_Object xwidget)
743{
744 // TODO support multibyte strings
745 WEBKIT_FN_INIT ();
746 const gchar *str =
747 webkit_web_view_get_title (WEBKIT_WEB_VIEW (xw->widget_osr));
748 if (str == 0)
749 {
750 // TODO maybe return Qnil instead. I suppose webkit returns
751 // nullpointer when doc is not properly loaded or something
752 return build_string ("");
753 }
754 return build_string (str);
755}
756
757DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 3, 3, 0,
758 doc: /* Resize XWIDGET. NEW_WIDTH, NEW_HEIGHT define the new size. */ )
759 (Lisp_Object xwidget, Lisp_Object new_width, Lisp_Object new_height)
760{
761 CHECK_XWIDGET (xwidget);
762 struct xwidget *xw = XXWIDGET (xwidget);
763 struct xwidget_view *xv;
764 int w, h;
765
766 CHECK_NUMBER (new_width);
767 CHECK_NUMBER (new_height);
768 w = XFASTINT (new_width);
769 h = XFASTINT (new_height);
770
771 xw->width = w;
772 xw->height = h;
773 // If there is a offscreen widget resize it 1st.
774 if (xw->widget_osr)
775 {
776 gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr),
777 xw->width, xw->height); //minimum size
778 gtk_window_resize (GTK_WINDOW (xw->widgetwindow_osr), xw->width,
779 xw->height);
780 gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW
781 (xw->
782 widgetscrolledwindow_osr),
783 xw->height);
784 gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW
785 (xw->
786 widgetscrolledwindow_osr),
787 xw->width);
788
789 gtk_container_resize_children (GTK_CONTAINER (xw->widgetwindow_osr));
790
791 }
792
793 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail))
794 {
795 if (XWIDGET_VIEW_P (XCAR (tail)))
796 {
797 xv = XXWIDGET_VIEW (XCAR (tail));
798 if (XXWIDGET (xv->model) == xw)
799 gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xw->width,
800 xw->height);
801 }
802 }
803
804 return Qnil;
805}
806
807
808
809DEFUN ("xwidget-set-adjustment",
810 Fxwidget_set_adjustment, Sxwidget_set_adjustment, 4, 4, 0,
811 doc: /* Set native scrolling for XWIDGET.
812AXIS can be 'vertical or 'horizontal.
813If RELATIVE is t, scroll relative, otherwise absolutely.
814VALUE is the amount to scroll, either relatively or absolutely. */)
815 (Lisp_Object xwidget, Lisp_Object axis, Lisp_Object relative,
816 Lisp_Object value)
817{
818 CHECK_XWIDGET (xwidget);
819 struct xwidget *xw = XXWIDGET (xwidget);
820 GtkAdjustment *adjustment;
821 float final_value = 0.0;
822
823 adjustment =
824 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW
825 (xw->widgetscrolledwindow_osr));
826 if (EQ (Qvertical, axis))
827 {
828 adjustment =
829 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW
830 (xw->widgetscrolledwindow_osr));
831 }
832 if (EQ (Qhorizontal, axis))
833 {
834 adjustment =
835 gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW
836 (xw->widgetscrolledwindow_osr));
837 }
838
839 if (EQ (Qt, relative))
840 {
841 final_value = gtk_adjustment_get_value (adjustment) + XFASTINT (value);
842 }
843 else
844 {
845 final_value = 0.0 + XFASTINT (value);
846 }
847
848 gtk_adjustment_set_value (adjustment, final_value);
849
850 return Qnil;
851}
852
853
854DEFUN ("xwidget-size-request",
855 Fxwidget_size_request, Sxwidget_size_request,
856 1, 1, 0,
857 doc: /* Return the desired size of the XWIDGET.
858This can be used to read the xwidget desired size, and resizes the
859Emacs allocated area accordingly. */)
860 (Lisp_Object xwidget)
861{
862 CHECK_XWIDGET (xwidget);
863 GtkRequisition requisition;
864 Lisp_Object rv;
865 gtk_widget_size_request (XXWIDGET (xwidget)->widget_osr, &requisition);
866 rv = Qnil;
867 rv = Fcons (make_number (requisition.height), rv);
868 rv = Fcons (make_number (requisition.width), rv);
869 return rv;
870
871}
872
873DEFUN ("xwidgetp",
874 Fxwidgetp, Sxwidgetp,
875 1, 1, 0,
876 doc: /* Return t if OBJECT is an xwidget. */)
877 (Lisp_Object object)
878{
879 return XWIDGETP (object) ? Qt : Qnil;
880}
881
882DEFUN ("xwidget-view-p",
883 Fxwidget_view_p, Sxwidget_view_p,
884 1, 1, 0,
885 doc: /* Return t if OBJECT is an xwidget-view. */)
886 (Lisp_Object object)
887{
888 return XWIDGET_VIEW_P (object) ? Qt : Qnil;
889}
890
891DEFUN ("xwidget-info",
892 Fxwidget_info, Sxwidget_info,
893 1, 1, 0,
894 doc: /* Return XWIDGET properties in a vector.
895Currently [TYPE TITLE WIDTH HEIGHT]. */)
896 (Lisp_Object xwidget)
897{
898 CHECK_XWIDGET (xwidget);
899 Lisp_Object info, n;
900 struct xwidget *xw = XXWIDGET (xwidget);
901
902 info = Fmake_vector (make_number (4), Qnil);
903 ASET (info, 0, xw->type);
904 ASET (info, 1, xw->title);
905 XSETFASTINT (n, xw->width);
906 ASET (info, 2, n);
907 XSETFASTINT (n, xw->height);
908 ASET (info, 3, n);
909
910 return info;
911}
912
913DEFUN ("xwidget-view-info",
914 Fxwidget_view_info, Sxwidget_view_info,
915 1, 1, 0,
916 doc: /* Return properties of XWIDGET-VIEW in a vector.
917Currently [X Y CLIP_RIGHT CLIP_BOTTOM CLIP_TOP CLIP_LEFT]. */)
918 (Lisp_Object xwidget_view)
919{
920 CHECK_XWIDGET_VIEW (xwidget_view);
921 struct xwidget_view *xv = XXWIDGET_VIEW (xwidget_view);
922 Lisp_Object info;
923
924 info = Fmake_vector (make_number (6), Qnil);
925 ASET (info, 0, make_number (xv->x));
926 ASET (info, 1, make_number (xv->y));
927 ASET (info, 2, make_number (xv->clip_right));
928 ASET (info, 3, make_number (xv->clip_bottom));
929 ASET (info, 4, make_number (xv->clip_top));
930 ASET (info, 5, make_number (xv->clip_left));
931
932 return info;
933}
934
935DEFUN ("xwidget-view-model",
936 Fxwidget_view_model, Sxwidget_view_model,
937 1, 1, 0,
938 doc: /* Return the model associated with XWIDGET-VIEW. */)
939 (Lisp_Object xwidget_view)
940{
941 CHECK_XWIDGET_VIEW (xwidget_view);
942 return XXWIDGET_VIEW (xwidget_view)->model;
943}
944
945DEFUN ("xwidget-view-window",
946 Fxwidget_view_window, Sxwidget_view_window,
947 1, 1, 0,
948 doc: /* Return the window of XWIDGET-VIEW. */)
949 (Lisp_Object xwidget_view)
950{
951 CHECK_XWIDGET_VIEW (xwidget_view);
952 return XXWIDGET_VIEW (xwidget_view)->w;
953}
954
955
956DEFUN ("delete-xwidget-view",
957 Fdelete_xwidget_view, Sdelete_xwidget_view,
958 1, 1, 0,
959 doc: /* Delete the XWIDGET-VIEW. */)
960 (Lisp_Object xwidget_view)
961{
962 CHECK_XWIDGET_VIEW (xwidget_view);
963 struct xwidget_view *xv = XXWIDGET_VIEW (xwidget_view);
964 gtk_widget_destroy (xv->widgetwindow);
965 Vxwidget_view_list = Fdelq (xwidget_view, Vxwidget_view_list);
966 // xv->model still has signals pointing to the view. There can be
967 // several views. Find the matching signals and delete them all.
968 g_signal_handlers_disconnect_matched (XXWIDGET (xv->model)->widgetwindow_osr,
969 G_SIGNAL_MATCH_DATA,
970 0, 0, 0, 0,
971 xv->widget);
972 return Qnil;
973}
974
975DEFUN ("xwidget-view-lookup",
976 Fxwidget_view_lookup, Sxwidget_view_lookup,
977 1, 2, 0,
978 doc: /* Return the xwidget-view associated with XWIDGET in WINDOW.
979If WINDOW is unspecified or nil, use the selected window.
980Return nil if no association is found. */)
981 (Lisp_Object xwidget, Lisp_Object window)
982{
983 CHECK_XWIDGET (xwidget);
984
985 if (NILP (window))
986 window = Fselected_window ();
987 CHECK_WINDOW (window);
988
989 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail);
990 tail = XCDR (tail))
991 {
992 Lisp_Object xwidget_view = XCAR (tail);
993 if (EQ (Fxwidget_view_model (xwidget_view), xwidget)
994 && EQ (Fxwidget_view_window (xwidget_view), window))
995 return xwidget_view;
996 }
997
998 return Qnil;
999}
1000
1001DEFUN ("xwidget-plist",
1002 Fxwidget_plist, Sxwidget_plist,
1003 1, 1, 0,
1004 doc: /* Return the plist of XWIDGET. */)
1005 (register Lisp_Object xwidget)
1006{
1007 CHECK_XWIDGET (xwidget);
1008 return XXWIDGET (xwidget)->plist;
1009}
1010
1011DEFUN ("xwidget-buffer",
1012 Fxwidget_buffer, Sxwidget_buffer,
1013 1, 1, 0,
1014 doc: /* Return the buffer of XWIDGET. */)
1015 (register Lisp_Object xwidget)
1016{
1017 CHECK_XWIDGET (xwidget);
1018 return XXWIDGET (xwidget)->buffer;
1019}
1020
1021DEFUN ("set-xwidget-plist",
1022 Fset_xwidget_plist, Sset_xwidget_plist,
1023 2, 2, 0,
1024 doc: /* Replace the plist of XWIDGET with PLIST.
1025Returns PLIST. */)
1026 (register Lisp_Object xwidget, Lisp_Object plist)
1027{
1028 CHECK_XWIDGET (xwidget);
1029 CHECK_LIST (plist);
1030
1031 XXWIDGET (xwidget)->plist = plist;
1032 return plist;
1033}
1034
1035DEFUN ("set-xwidget-query-on-exit-flag",
1036 Fset_xwidget_query_on_exit_flag, Sset_xwidget_query_on_exit_flag,
1037 2, 2, 0,
1038 doc: /* Specify if query is needed for XWIDGET when Emacs is exited.
1039If the second argument FLAG is non-nil, Emacs will query the user before
1040exiting or killing a buffer if XWIDGET is running.
1041This function returns FLAG. */)
1042 (Lisp_Object xwidget, Lisp_Object flag)
1043{
1044 CHECK_XWIDGET (xwidget);
1045 XXWIDGET (xwidget)->kill_without_query = NILP (flag);
1046 return flag;
1047}
1048
1049DEFUN ("xwidget-query-on-exit-flag",
1050 Fxwidget_query_on_exit_flag, Sxwidget_query_on_exit_flag,
1051 1, 1, 0,
1052 doc: /* Return the current value of the query-on-exit flag for XWIDGET. */)
1053 (Lisp_Object xwidget)
1054{
1055 CHECK_XWIDGET (xwidget);
1056 return (XXWIDGET (xwidget)->kill_without_query ? Qnil : Qt);
1057}
1058
1059void
1060syms_of_xwidget (void)
1061{
1062
1063 defsubr (&Smake_xwidget);
1064 defsubr (&Sxwidgetp);
1065 DEFSYM (Qxwidgetp, "xwidgetp");
1066 defsubr (&Sxwidget_view_p);
1067 DEFSYM (Qxwidget_view_p, "xwidget-view-p");
1068 defsubr (&Sxwidget_info);
1069 defsubr (&Sxwidget_view_info);
1070 defsubr (&Sxwidget_resize);
1071 defsubr (&Sget_buffer_xwidgets);
1072 defsubr (&Sxwidget_view_model);
1073 defsubr (&Sxwidget_view_window);
1074 defsubr (&Sxwidget_view_lookup);
1075 defsubr (&Sxwidget_query_on_exit_flag);
1076 defsubr (&Sset_xwidget_query_on_exit_flag);
1077
1078 defsubr (&Sxwidget_webkit_goto_uri);
1079 defsubr (&Sxwidget_webkit_execute_script);
1080 defsubr (&Sxwidget_webkit_get_title);
1081 DEFSYM (Qwebkit_osr, "webkit-osr");
1082
1083 defsubr (&Sxwidget_size_request);
1084 defsubr (&Sdelete_xwidget_view);
1085
1086 defsubr (&Sxwidget_plist);
1087 defsubr (&Sxwidget_buffer);
1088 defsubr (&Sset_xwidget_plist);
1089
1090 defsubr (&Sxwidget_set_adjustment);
1091
1092 DEFSYM (Qxwidget, "xwidget");
1093
1094 DEFSYM (QCxwidget, ":xwidget");
1095 DEFSYM (QCtitle, ":title");
1096
1097 /* Do not forget to update the docstring of make-xwidget if you add
1098 new types. */
1099
1100 DEFSYM (Qvertical, "vertical");
1101 DEFSYM (Qhorizontal, "horizontal");
1102
1103 DEFSYM (QCplist, ":plist");
1104
1105 DEFVAR_LISP ("xwidget-list", Vxwidget_list,
1106 doc: /* xwidgets list. */);
1107 Vxwidget_list = Qnil;
1108
1109 DEFVAR_LISP ("xwidget-view-list", Vxwidget_view_list,
1110 doc: /* xwidget views list. */);
1111 Vxwidget_view_list = Qnil;
1112
1113 Fprovide (intern ("xwidget-internal"), Qnil);
1114
1115}
1116
1117
1118/* Value is non-zero if OBJECT is a valid Lisp xwidget specification. A
1119 valid xwidget specification is a list whose car is the symbol
1120 `xwidget', and whose rest is a property list. The property list must
1121 contain a value for key `:type'. That value must be the name of a
1122 supported xwidget type. The rest of the property list depends on the
1123 xwidget type. */
1124
1125bool
1126valid_xwidget_spec_p (Lisp_Object object)
1127{
1128 int valid_p = false;
1129
1130 if (CONSP (object) && EQ (XCAR (object), Qxwidget))
1131 valid_p = true;
1132
1133 return valid_p;
1134}
1135
1136
1137
1138/* Find a value associated with key in spec. */
1139static Lisp_Object
1140xwidget_spec_value (Lisp_Object spec, Lisp_Object key, int *found)
1141{
1142 Lisp_Object tail;
1143
1144 eassert (valid_xwidget_spec_p (spec));
1145
1146 for (tail = XCDR (spec);
1147 CONSP (tail) && CONSP (XCDR (tail)); tail = XCDR (XCDR (tail)))
1148 {
1149 if (EQ (XCAR (tail), key))
1150 {
1151 if (found)
1152 *found = 1;
1153 return XCAR (XCDR (tail));
1154 }
1155 }
1156
1157 if (found)
1158 *found = 0;
1159 return Qnil;
1160}
1161
1162
1163void
1164xwidget_view_delete_all_in_window (struct window *w)
1165{
1166 struct xwidget_view *xv = NULL;
1167 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail);
1168 tail = XCDR (tail))
1169 {
1170 if (XWIDGET_VIEW_P (XCAR (tail)))
1171 {
1172 xv = XXWIDGET_VIEW (XCAR (tail));
1173 if (XWINDOW (xv->w) == w)
1174 {
1175 Fdelete_xwidget_view (XCAR (tail));
1176 }
1177 }
1178 }
1179}
1180
1181static struct xwidget_view *
1182xwidget_view_lookup (struct xwidget *xw, struct window *w)
1183{
1184 Lisp_Object xwidget, window, ret;
1185 XSETXWIDGET (xwidget, xw);
1186 XSETWINDOW (window, w);
1187
1188 ret = Fxwidget_view_lookup (xwidget, window);
1189
1190 return EQ (ret, Qnil) ? NULL : XXWIDGET_VIEW (ret);
1191}
1192
1193struct xwidget *
1194lookup_xwidget (Lisp_Object spec)
1195{
1196 /* When a xwidget lisp spec is found initialize the C struct that is
1197 used in the C code. This is done by redisplay so values change
1198 if the spec changes. So, take special care of one-shot events.
1199 */
1200 int found = 0;
1201 Lisp_Object value;
1202 struct xwidget *xw;
1203
1204 value = xwidget_spec_value (spec, QCxwidget, &found);
1205 xw = XXWIDGET (value);
1206
1207 return xw;
1208}
1209
1210/* Set up detection of touched xwidget */
1211static void
1212xwidget_start_redisplay (void)
1213{
1214 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail);
1215 tail = XCDR (tail))
1216 {
1217 if (XWIDGET_VIEW_P (XCAR (tail)))
1218 XXWIDGET_VIEW (XCAR (tail))->redisplayed = 0;
1219 }
1220}
1221
1222/* The xwidget was touched during redisplay, so it isn't a candidate
1223 for hiding. */
1224static void
1225xwidget_touch (struct xwidget_view *xv)
1226{
1227 xv->redisplayed = 1;
1228}
1229
1230static int
1231xwidget_touched (struct xwidget_view *xv)
1232{
1233 return xv->redisplayed;
1234}
1235
1236/* Redisplay has ended, now we should hide untouched xwidgets
1237*/
1238void
1239xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix)
1240{
1241
1242 int i;
1243 int area;
1244
1245 xwidget_start_redisplay ();
1246 // Iterate desired glyph matrix of window here, hide gtk widgets
1247 // not in the desired matrix.
1248
1249 // This only takes care of xwidgets in active windows. If a window
1250 // goes away from screen xwidget views wust be deleted
1251
1252 // dump_glyph_matrix (matrix, 2);
1253 for (i = 0; i < matrix->nrows; ++i)
1254 {
1255 // dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
1256 struct glyph_row *row;
1257 row = MATRIX_ROW (matrix, i);
1258 if (row->enabled_p != 0)
1259 {
1260 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
1261 {
1262 struct glyph *glyph = row->glyphs[area];
1263 struct glyph *glyph_end = glyph + row->used[area];
1264 for (; glyph < glyph_end; ++glyph)
1265 {
1266 if (glyph->type == XWIDGET_GLYPH)
1267 {
1268 /*
1269 The only call to xwidget_end_redisplay is in dispnew
1270 xwidget_end_redisplay (w->current_matrix);
1271 */
1272 xwidget_touch (xwidget_view_lookup (glyph->u.xwidget,
1273 w));
1274 }
1275 }
1276 }
1277 }
1278 }
1279
1280 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail);
1281 tail = XCDR (tail))
1282 {
1283 if (XWIDGET_VIEW_P (XCAR (tail)))
1284 {
1285 struct xwidget_view *xv = XXWIDGET_VIEW (XCAR (tail));
1286
1287 // "touched" is only meaningful for the current window, so
1288 // disregard other views.
1289 if (XWINDOW (xv->w) == w)
1290 {
1291 if (xwidget_touched (xv))
1292 xwidget_show_view (xv);
1293 else
1294 xwidget_hide_view (xv);
1295 }
1296 }
1297 }
1298}
1299
1300/* Kill all xwidget in BUFFER. */
1301void
1302kill_buffer_xwidgets (Lisp_Object buffer)
1303{
1304 Lisp_Object tail, xwidget;
1305 for (tail = Fget_buffer_xwidgets (buffer); CONSP (tail); tail = XCDR (tail))
1306 {
1307 xwidget = XCAR (tail);
1308 Vxwidget_list = Fdelq (xwidget, Vxwidget_list);
1309 /* TODO free the GTK things in xw */
1310 {
1311 CHECK_XWIDGET (xwidget);
1312 struct xwidget *xw = XXWIDGET (xwidget);
1313 if (xw->widget_osr && xw->widgetwindow_osr)
1314 {
1315 gtk_widget_destroy (xw->widget_osr);
1316 gtk_widget_destroy (xw->widgetwindow_osr);
1317 }
1318 }
1319 }
1320}
diff --git a/src/xwidget.h b/src/xwidget.h
new file mode 100644
index 00000000000..fdcf40d8cbb
--- /dev/null
+++ b/src/xwidget.h
@@ -0,0 +1,132 @@
1/* Support for embedding graphical components in a buffer.
2
3Copyright (C) 2011-2016 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19
20#ifndef XWIDGET_H_INCLUDED
21#define XWIDGET_H_INCLUDED
22
23void x_draw_xwidget_glyph_string (struct glyph_string *s);
24void syms_of_xwidget (void);
25
26//extern Lisp_Object Qxwidget;
27
28
29bool valid_xwidget_spec_p (Lisp_Object object);
30
31#include <gtk/gtk.h>
32
33
34/*
35each xwidget instance/model is described by this struct.
36
37lisp pseudovector.
38
39
40 */
41struct xwidget
42{
43 struct vectorlike_header header;
44 Lisp_Object plist; //auxilliary data
45 Lisp_Object type; //the widget type
46 Lisp_Object buffer; //buffer where xwidget lives
47 Lisp_Object title; //a title that is used for button labels for instance
48
49 //here ends the lisp part.
50 //"height" is the marker field
51 int height;
52 int width;
53
54 //for offscreen widgets, unused if not osr
55 GtkWidget *widget_osr;
56 GtkWidget *widgetwindow_osr;
57 //this is used if the widget (webkit) is to be wrapped in a scrolled window,
58 GtkWidget *widgetscrolledwindow_osr;
59 /* Non-nil means kill silently if Emacs is exited. */
60 unsigned int kill_without_query:1;
61
62};
63
64
65//struct for each xwidget view
66struct xwidget_view
67{
68 struct vectorlike_header header;
69 Lisp_Object model;
70 Lisp_Object w;
71
72 //here ends the lisp part.
73 //"redisplayed" is the marker field
74 int redisplayed; //if touched by redisplay
75
76 int hidden; //if the "live" instance isnt drawn
77
78 GtkWidget *widget;
79 GtkWidget *widgetwindow;
80 GtkWidget *emacswindow;
81 int x;
82 int y;
83 int clip_right;
84 int clip_bottom;
85 int clip_top;
86 int clip_left;
87
88
89 long handler_id;
90};
91
92/* Test for xwidget pseudovector*/
93#define XWIDGETP(x) PSEUDOVECTORP (x, PVEC_XWIDGET)
94#define XXWIDGET(a) (eassert (XWIDGETP(a)), \
95 (struct xwidget *) XUNTAG(a, Lisp_Vectorlike))
96
97#define CHECK_XWIDGET(x) \
98 CHECK_TYPE (XWIDGETP (x), Qxwidgetp, x)
99
100/* Test for xwidget_view pseudovector */
101#define XWIDGET_VIEW_P(x) PSEUDOVECTORP (x, PVEC_XWIDGET_VIEW)
102#define XXWIDGET_VIEW(a) (eassert (XWIDGET_VIEW_P(a)), \
103 (struct xwidget_view *) XUNTAG(a, Lisp_Vectorlike))
104
105#define CHECK_XWIDGET_VIEW(x) \
106 CHECK_TYPE (XWIDGET_VIEW_P (x), Qxwidget_view_p, x)
107
108struct xwidget_type
109{
110 /* A symbol uniquely identifying the xwidget type, */
111 Lisp_Object *type;
112
113 /* Check that SPEC is a valid image specification for the given
114 image type. Value is non-zero if SPEC is valid. */
115 int (*valid_p) (Lisp_Object spec);
116
117 /* Next in list of all supported image types. */
118 struct xwidget_type *next;
119};
120
121
122struct xwidget *xwidget_from_id (int id);
123
124void xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix);
125
126struct xwidget *lookup_xwidget (Lisp_Object spec);
127#define XG_XWIDGET "emacs_xwidget"
128#define XG_XWIDGET_VIEW "emacs_xwidget_view"
129void xwidget_view_delete_all_in_window (struct window *w);
130
131void kill_buffer_xwidgets (Lisp_Object buffer);
132#endif /* XWIDGET_H_INCLUDED */
diff --git a/test/manual/indent/ruby.rb b/test/manual/indent/ruby.rb
index dec6de98605..dfd1c75a679 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
4 end 4 end
5 eowarn 5 eowarn
6 foo 6 foo
7
8 foo(<<~squiggly)
9 end
10 squiggly
7end 11end
8 12
9def foo 13def foo