From 66ff8bac8ba389bdabca34e70d08743dae4ecda1 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Mon, 18 Jan 2016 23:09:15 -0800 Subject: [PATCH 01/36] Fix spurious escapes in describe-input-method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem reported by Vincent Belaïche (Bug#22309). * lisp/international/mule-cmds.el (describe-language-environment): * lisp/international/quail.el (quail-help): Apply substitute-command-keys to doc strings before displaying them. --- lisp/international/mule-cmds.el | 2 +- lisp/international/quail.el | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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." (with-current-buffer standard-output (insert language-name " language environment\n\n") (if (stringp doc) - (insert doc "\n\n")) + (insert (substitute-command-keys doc) "\n\n")) (condition-case nil (let ((str (eval (get-language-info language-name 'sample-text)))) (if (stringp str) diff --git a/lisp/international/quail.el b/lisp/international/quail.el index 75cb7f787df..f5e390278ca 100644 --- a/lisp/international/quail.el +++ b/lisp/international/quail.el @@ -2516,7 +2516,7 @@ package to describe." ")\n\n") (save-restriction (narrow-to-region (point) (point)) - (insert (quail-docstring)) + (insert (substitute-command-keys (quail-docstring))) (goto-char (point-min)) (with-syntax-table emacs-lisp-mode-syntax-table (while (re-search-forward "\\\\<\\sw\\(\\sw\\|\\s_\\)+>" nil t) From ef768c790ed83c8fa5c7efb24dc8e94967b5a778 Mon Sep 17 00:00:00 2001 From: Phillip Lord Date: Sun, 17 Jan 2016 22:03:10 +0000 Subject: [PATCH 02/36] Cope with multiple overlapping faces. * lisp/htmlfontify.el (hfy-face-to-style-i): Treat inheritance right to left. (hfy-face-resolve-face): Handle font specification as well as font name. Documentation update. (Bug#21990) --- lisp/htmlfontify.el | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lisp/htmlfontify.el b/lisp/htmlfontify.el index 178f3a00133..fc309bd62ee 100644 --- a/lisp/htmlfontify.el +++ b/lisp/htmlfontify.el @@ -999,7 +999,7 @@ merged by the user - `hfy-flatten-style' should do this." (append parent (hfy-face-to-style-i - (hfy-face-attr-for-class v hfy-display-class)) )))) + (hfy-face-attr-for-class v hfy-display-class)))))) (setq this (if val (case key (:family (hfy-family val)) @@ -1018,7 +1018,7 @@ merged by the user - `hfy-flatten-style' should do this." (:italic (hfy-slant 'italic)))))) (setq that (hfy-face-to-style-i next)) ;;(lwarn t :warning "%S => %S" fn (nconc this that parent)) - (nconc this that parent))) ) + (nconc this parent that))) ) (defun hfy-size-to-int (spec) "Convert SPEC, a CSS font-size specifier, to an Emacs :height attribute value. @@ -1056,13 +1056,19 @@ haven't encountered them yet. Returns a `hfy-style-assoc'." (nconc r (hfy-size (if x (round n) (* n 1.0)))) )) (defun hfy-face-resolve-face (fn) + "For FN return a face specification. +FN may be either a face or a face specification. If the latter, +then the specification is returned unchanged." (cond ((facep fn) (hfy-face-attr-for-class fn hfy-display-class)) + ;; FIXME: is this necessary? Faces can be symbols, but + ;; not symbols refering to other symbols? ((and (symbolp fn) (facep (symbol-value fn))) - (hfy-face-attr-for-class (symbol-value fn) hfy-display-class)) - (t nil))) + (hfy-face-attr-for-class + (symbol-value fn) hfy-display-class)) + (t fn))) (defun hfy-face-to-style (fn) From 116caedbe0da17999a3636e4def329edab2c56ed Mon Sep 17 00:00:00 2001 From: Lars Magne Ingebrigtsen Date: Tue, 19 Jan 2016 14:16:34 +0100 Subject: [PATCH 03/36] * shr.el (shr-table-body): Allow tables to have text children. --- lisp/net/shr.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/net/shr.el b/lisp/net/shr.el index 88041f7e553..746cbb61aae 100644 --- a/lisp/net/shr.el +++ b/lisp/net/shr.el @@ -1602,7 +1602,7 @@ The preference is a float determined from `shr-prefer-media-type'." (defun shr-table-body (dom) (let ((tbodies (seq-filter (lambda (child) (eq (dom-tag child) 'tbody)) - (dom-children dom)))) + (dom-non-text-children dom)))) (cond ((null tbodies) dom) From 32cb203c086163e40ecc040e61e5d304e101b602 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Tue, 19 Jan 2016 18:11:04 +0200 Subject: [PATCH 04/36] Unbreak the Cygwin-w32 build * src/w32fns.c (globals_of_w32fns): Move the initialization of resetstkoflw into a part that isn't compiled on Cygwin. (Bug#22403) --- src/w32fns.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/w32fns.c b/src/w32fns.c index 01f5d6f3ae0..a5018ae9d30 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -9921,6 +9921,7 @@ globals_of_w32fns (void) except_addr = 0; #ifndef CYGWIN prev_exception_handler = SetUnhandledExceptionFilter (my_exception_handler); + resetstkoflw = NULL; #endif DEFVAR_INT ("w32-ansi-code-page", @@ -9935,8 +9936,6 @@ globals_of_w32fns (void) after_deadkey = -1; - resetstkoflw = NULL; - /* MessageBox does not work without this when linked to comctl32.dll 6.0. */ InitCommonControls (); From 156270697deb9895f381faf0de1a23cfb9b217d7 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Tue, 19 Jan 2016 19:31:05 +0200 Subject: [PATCH 05/36] Minor copyedits of doc/emacs/maintaining.texi * doc/emacs/maintaining.texi (List Identifiers): More accurate description of "C-M-i" wrt tags tables. (Tags Tables): Move the definition of "tag" to a footnote. --- doc/emacs/maintaining.texi | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) 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}. @table @kbd @item C-M-i @itemx M-@key{TAB} -Perform completion on the text around point, using the selected tags -table if one is loaded (@code{completion-at-point}). +Perform completion on the text around point, possibly using the +selected tags table if one is loaded (@code{completion-at-point}). @item M-x xref-find-apropos @key{RET} @var{regexp} @key{RET} Display a list of all known identifiers matching @var{regexp}. @item M-x list-tags @key{RET} @var{file} @key{RET} @@ -2004,9 +2004,10 @@ Visit files recorded in the selected tags table. @cindex completion (symbol names) In most programming language modes, you can type @kbd{C-M-i} or @kbd{M-@key{TAB}} (@code{completion-at-point}) to complete the symbol -at point. If there is a tags table loaded, this command can use it to -generate completion candidates more intelligently. @xref{Symbol -Completion}. +at point. Some modes provide specialized completion for this command +tailored to the mode; for those that don't, if there is a tags table +loaded, this command can use it to generate completion candidates. +@xref{Symbol Completion}. @findex list-tags @kbd{M-x list-tags} reads the name of one of the files covered by @@ -2047,17 +2048,17 @@ file. This command requires a tags table to be selected. @subsection Tags Tables @cindex tags and tag tables -@cindex tag - A @dfn{tag} is a synonym for identifier reference. @xref{Xref}. - - A @dfn{tags table} records the tags extracted by scanning the source -code of a certain program or a certain document. Tags extracted from -generated files reference the original files, rather than the -generated files that were scanned during tag extraction. Examples of -generated files include C files generated from Cweb source files, from -a Yacc parser, or from Lex scanner definitions; @file{.i} preprocessed -C files; and Fortran files produced by preprocessing @file{.fpp} -source files. + A @dfn{tags table} records the tags@footnote{ +A @dfn{tag} is a synonym for identifier reference. Commands and +features based on the @code{etags} package traditionally use ``tag'' +with this meaning, and this subsection follows that tradition. +} extracted by scanning the source code of a certain program or a +certain document. Tags extracted from generated files reference the +original files, rather than the generated files that were scanned +during tag extraction. Examples of generated files include C files +generated from Cweb source files, from a Yacc parser, or from Lex +scanner definitions; @file{.i} preprocessed C files; and Fortran files +produced by preprocessing @file{.fpp} source files. @cindex etags To produce a tags table, you run the @command{etags} shell command From 77793f52c51e47e73e08d5c5f7eac204fb4a345c Mon Sep 17 00:00:00 2001 From: Shakthi Kannan Date: Tue, 19 Jan 2016 20:36:33 +0200 Subject: [PATCH 06/36] ; * etc/NEWS: No need to document 'system-name'. --- etc/NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/etc/NEWS b/etc/NEWS index e9b539a3785..4e415a1039a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1520,6 +1520,7 @@ permissions set to temporary values (e.g., for creating private files). +++ ** Function `sort' can deal with vectors. +--- ** Function `system-name' now returns an updated value if the current system's name has changed or if the Emacs process has changed systems, and to avoid long waits it no longer consults DNS to canonicalize the From 663d379bbc2fde5e9bded157365e9d48ea01c027 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Tue, 19 Jan 2016 21:05:27 +0200 Subject: [PATCH 07/36] Improve documentation of 'alist-get' * doc/lispref/variables.texi (Setting Generalized Variables): Add 'alist-get' to the list of functions that can appear in PLACE argument of 'setf'. --- doc/lispref/variables.texi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 A call to any of the following Emacs-specific functions: @smallexample -default-value process-get +alist-get process-get frame-parameter process-sentinel terminal-parameter window-buffer keymap-parent window-display-table @@ -2077,7 +2077,7 @@ overlay-get window-hscroll overlay-start window-parameter overlay-end window-point process-buffer window-start -process-filter +process-filter default-value @end smallexample @end itemize From 7c1f66a94bf236a427606ef537b4629a48a1665b Mon Sep 17 00:00:00 2001 From: Joakim Verona Date: Tue, 19 Jan 2016 20:27:12 +0100 Subject: [PATCH 08/36] Support for the new Xwidget feature. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * configure.ac: (HAVE_XWIDGETS, WIDGET_OBJ, EMACS_CONFIG_FEATURES): * xterm.c (x_draw_glyph_string, x_draw_bar_cursor): * xdisp.c: (handle_display_spec, handle_single_display_spec, push_it) (pop_it, set_iterator_to_next, dump_glyph) (calc_pixel_width_or_height, fill_xwidget_glyph_string) (BUILD_XWIDGET_GLYPH_STRING, BUILD_GLYPH_STRINGS) (produce_xwidget_glyph, x_produce_glyphs) (get_window_cursor_type): * window.c (Fdelete_window_internal): * termhooks.h (e): * print.c (print_object): * lisp.h (ptrdiff_t): * keyboard.c (kbd_buffer_get_event, make_lispy_event) (syms_of_keyboard): * emacs.c (main): * dispnew.c (update_window, scrolling_window): * dispextern.h (g, i): * Makefile.in (XWIDGETS_OBJ, WEBKIT_CFLAGS, WEBKIT_LIBS) (GIR_LIBS, ALL_CFLAGS, base_obj, LIBES): * keyboard.c (kbd_buffer_get_event): * emacsgtkfixed.c (emacs_fixed_gtk_widget_size_allocate) (emacs_fixed_class_init): Add case for an xwidget view. * xwidget.c, xwidget.h, xwidget.el: New files for xwidgets Co-authored-by: Grégoire Jadi Various improvements to the Xwidget feature. * xwidgets.c: * emacsgtkfixed.c: * xwidget.el: --- configure.ac | 45 ++ etc/NEWS | 15 + lisp/xwidget.el | 608 ++++++++++++++++++++ src/Makefile.in | 11 + src/buffer.c | 6 + src/dispextern.h | 28 + src/dispnew.c | 12 + src/emacs.c | 6 + src/emacsgtkfixed.c | 105 +++- src/emacsgtkfixed.h | 28 + src/keyboard.c | 19 + src/lisp.h | 6 + src/print.c | 16 + src/termhooks.h | 5 + src/window.c | 6 + src/xdisp.c | 248 +++++++- src/xterm.c | 14 + src/xwidget.c | 1332 +++++++++++++++++++++++++++++++++++++++++++ src/xwidget.h | 135 +++++ 19 files changed, 2622 insertions(+), 23 deletions(-) create mode 100644 lisp/xwidget.el create mode 100644 src/xwidget.c create mode 100644 src/xwidget.h diff --git a/configure.ac b/configure.ac index 3aeba22ec47..95f79ab8d4f 100644 --- a/configure.ac +++ b/configure.ac @@ -373,6 +373,9 @@ otherwise for the first of 'inotify' or 'gfile' that is usable.]) ], [with_file_notification=$with_features]) +OPTION_DEFAULT_OFF([xwidgets], + [enable use of some gtk widgets in Emacs buffers]) + ## For the times when you want to build Emacs but don't have ## a suitable makeinfo, and can live without the manuals. dnl http://lists.gnu.org/archive/html/emacs-devel/2008-04/msg01844.html @@ -2562,6 +2565,42 @@ if test "${HAVE_GTK}" = "yes"; then term_header=gtkutil.h fi + +HAVE_XWIDGETS=no +HAVE_WEBKIT=no +HAVE_GIR=no +XWIDGETS_OBJ= +if test "$with_xwidgets" != "no" && test "$USE_GTK_TOOLKIT" = "GTK3" && + test "$window_system" != "none" +then + HAVE_XWIDGETS=yes + AC_DEFINE([HAVE_XWIDGETS], 1, [Define to 1 if you have xwidgets support.]) + + dnl xwidgets + dnl - enable only if GTK3 is enabled, and we have a window system + dnl - check for webkit and gobject introspection + dnl webkit version for gtk3. + WEBKIT_REQUIRED=1.4.0 + WEBKIT_MODULES="webkitgtk-3.0 >= $WEBKIT_REQUIRED" + + if test "${with_gtk3}" = "yes"; then + PKG_CHECK_MODULES(WEBKIT, $WEBKIT_MODULES, HAVE_WEBKIT=yes, HAVE_WEBKIT=no) + if test $HAVE_WEBKIT = yes; then + AC_DEFINE([HAVE_WEBKIT_OSR], 1, + [Define to 1 if you have webkit_osr support.]) + fi + fi + + GIR_REQUIRED=1.32.1 + GIR_MODULES="gobject-introspection-1.0 >= $GIR_REQUIRED" + PKG_CHECK_MODULES(GIR, $GIR_MODULES, HAVE_GIR=yes, HAVE_GIR=no) + if test $HAVE_GIR = yes; then + AC_DEFINE([HAVE_GIR], 1, [Define to 1 if you have GIR support.]) + fi + XWIDGETS_OBJ=xwidget.o +fi +AC_SUBST(XWIDGETS_OBJ) + CFLAGS=$OLD_CFLAGS LIBS=$OLD_LIBS @@ -4925,6 +4964,9 @@ case "$USE_X_TOOLKIT" in LUCID) TOOLKIT_LIBW="$LUCID_LIBW" ;; none) test "x$HAVE_GTK" = "xyes" && TOOLKIT_LIBW="$GTK_LIBS" ;; esac +if test "$HAVE_XWIDGETS" = "yes"; then + TOOLKIT_LIBW="$TOOLKIT_LIBW -lXcomposite" +fi AC_SUBST(TOOLKIT_LIBW) if test "${opsys}" != "mingw32"; then @@ -5264,6 +5306,9 @@ AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D Does Emacs directly use zlib? ${HAVE_ZLIB} Does Emacs have dynamic modules support? ${HAVE_MODULES} Does Emacs use toolkit scroll bars? ${USE_TOOLKIT_SCROLL_BARS} + Does Emacs support Xwidgets? ${HAVE_XWIDGETS} + Does xwidgets support webkit(requires gtk3)? ${HAVE_WEBKIT} + Does xwidgets support gobject introspection? ${HAVE_GIR} "]) if test -n "${EMACSDATA}"; then diff --git a/etc/NEWS b/etc/NEWS index 4e415a1039a..db6e51dfd45 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -120,6 +120,21 @@ and can contain escape sequences for command keys, quotes, and the like. * Changes in Emacs 25.1 ++++ +** Xwidgets : A new feature for embedding native widgets +inside Emacs buffers. If you have gtk3 and webkit-devel installed, you +can access the embedded webkit browser with m-x +xwidget-webkit-browse-url. This will open a new buffer with the +embedded browser. The buffer will have a new mode, xwidget-webkit +mode which is similar to image mode, which supports the webkit widget. + +*** New functions for xwidget-webkit mode `xwidget-webkit-insert-string', +`xwidget-webkit-adjust-size-dispatch', `xwidget-webkit-back', +`xwidget-webkit-browse-url', `xwidget-webkit-reload', +`xwidget-webkit-current-url', `xwidget-webkit-scroll-backward', +`xwidget-webkit-scroll-forward', `xwidget-webkit-scroll-down', +`xwidget-webkit-scroll-up', + +++ ** Emacs can now load shared/dynamic libraries (modules). A dynamic Emacs module is a shared library that provides additional diff --git a/lisp/xwidget.el b/lisp/xwidget.el new file mode 100644 index 00000000000..ce6d939dd3b --- /dev/null +++ b/lisp/xwidget.el @@ -0,0 +1,608 @@ +;;; xwidget.el --- api functions for xwidgets -*- lexical-binding: t -*- +;; +;; Copyright (C) 2011-2015 Free Software Foundation, Inc. +;; +;; Author: Joakim Verona (joakim@verona.se) +;; +;; This file is part of GNU Emacs. +;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . +;; +;; -------------------------------------------------------------------- + +;;; Commentary: +;; +;; See xwidget.c for more api functions + +;;TODO this breaks compilation when we dont have xwidgets +;;(require 'xwidget-internal) + +;;; Code: + +(require 'cl-lib) +(require 'reporter) +(require 'bookmark) + +(defcustom xwidget-webkit-scroll-behaviour 'native + "Scroll behaviour of the webkit instance. +'native or 'image." + :group 'xwidgets) + +(defun xwidget-insert (pos type title width height &optional args) + "Insert an xwidget at POS. +given ID, TYPE, TITLE WIDTH and +HEIGHT in the current buffer. + +Return ID + +see `make-xwidget' for types suitable for TYPE. +Optional argument ARGS usage depends on the xwidget." + (goto-char pos) + (let ((id (make-xwidget (point) (point) + type title width height args))) + (put-text-property (point) (+ 1 (point)) + 'display (list 'xwidget ':xwidget id)) + id)) + +(defun xwidget-at (pos) + "Return xwidget at POS." + ;;TODO this function is a bit tedious because the C layer isnt well + ;;protected yet and xwidgetp aparently doesnt work yet + (let* ((disp (get-text-property pos 'display)) + (xw (car (cdr (cdr disp))))) + ;;(if ( xwidgetp xw) xw nil) + (if (equal 'xwidget (car disp)) xw))) + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; webkit support +(require 'browse-url) +(require 'image-mode);;for some image-mode alike functionality + +;;;###autoload +(defun xwidget-webkit-browse-url (url &optional new-session) + "Ask xwidget-webkit to browse URL. +NEW-SESSION specifies whether to create a new xwidget-webkit session. URL +defaults to the string looking like a url around the cursor position." + (interactive (progn + (require 'browse-url) + (browse-url-interactive-arg "xwidget-webkit URL: " + ;;( xwidget-webkit-current-url) + ))) + (when (stringp url) + (if new-session + (xwidget-webkit-new-session url) + (xwidget-webkit-goto-url url)))) + + +;;shims for adapting image mode code to the webkit browser window +(defun xwidget-image-display-size (spec &optional pixels frame) + "Image code adaptor. SPEC PIXELS FRAME like the corresponding +`image-mode' fn." + (let ((xwi (xwidget-info (xwidget-at 1)))) + (cons (aref xwi 2) + (aref xwi 3)))) + +(defadvice image-display-size (around image-display-size-for-xwidget + (spec &optional pixels frame) + activate) + "Advice for re-using image mode for xwidget." + (if (eq (car spec) 'xwidget) + (setq ad-return-value (xwidget-image-display-size spec pixels frame)) + ad-do-it)) + +;;todo. +;; - check that the webkit support is compiled in +(defvar xwidget-webkit-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "g" 'xwidget-webkit-browse-url) + (define-key map "a" 'xwidget-webkit-adjust-size-dispatch) + (define-key map "b" 'xwidget-webkit-back ) + (define-key map "r" 'xwidget-webkit-reload ) + (define-key map "t" (lambda () (interactive) (message "o")) ) + (define-key map "\C-m" 'xwidget-webkit-insert-string) + (define-key map "w" 'xwidget-webkit-current-url) + + ;;similar to image mode bindings + (define-key map (kbd "SPC") 'xwidget-webkit-scroll-up) + (define-key map (kbd "DEL") 'xwidget-webkit-scroll-down) + + (define-key map [remap scroll-up] 'xwidget-webkit-scroll-up) + (define-key map [remap scroll-up-command] 'xwidget-webkit-scroll-up) + + (define-key map [remap scroll-down] 'xwidget-webkit-scroll-down) + (define-key map [remap scroll-down-command] 'xwidget-webkit-scroll-down) + + (define-key map [remap forward-char] 'xwidget-webkit-scroll-forward) + (define-key map [remap backward-char] 'xwidget-webkit-scroll-backward) + (define-key map [remap right-char] 'xwidget-webkit-scroll-forward) + (define-key map [remap left-char] 'xwidget-webkit-scroll-backward) + ;; (define-key map [remap previous-line] 'image-previous-line) + ;; (define-key map [remap next-line] 'image-next-line) + + ;; (define-key map [remap move-beginning-of-line] 'image-bol) + ;; (define-key map [remap move-end-of-line] 'image-eol) + ;; (define-key map [remap beginning-of-buffer] 'image-bob) + ;; (define-key map [remap end-of-buffer] 'image-eob) + map) + "Keymap for `xwidget-webkit-mode'.") + +(defun xwidget-webkit-scroll-up () + "Scroll webkit up,either native or like image mode." + (interactive) + (if (eq xwidget-webkit-scroll-behaviour 'native) + (xwidget-set-adjustment (xwidget-webkit-last-session) 'vertical t 50) + (image-scroll-up))) + +(defun xwidget-webkit-scroll-down () + "Scroll webkit down,either native or like image mode." + (interactive) + (if (eq xwidget-webkit-scroll-behaviour 'native) + (xwidget-set-adjustment (xwidget-webkit-last-session) 'vertical t -50) + (image-scroll-down))) + +(defun xwidget-webkit-scroll-forward () + "Scroll webkit forward,either native or like image mode." + (interactive) + (if (eq xwidget-webkit-scroll-behaviour 'native) + (xwidget-set-adjustment (xwidget-webkit-last-session) 'horizontal t 50) + (xwidget-webkit-scroll-forward))) + +(defun xwidget-webkit-scroll-backward () + "Scroll webkit backward,either native or like image mode." + (interactive) + (if (eq xwidget-webkit-scroll-behaviour 'native) + (xwidget-set-adjustment (xwidget-webkit-last-session) 'horizontal t -50) + (xwidget-webkit-scroll-backward))) + + +;;the xwidget event needs to go into a higher level handler +;;since the xwidget can generate an event even if its offscreen +;;TODO this needs to use callbacks and consider different xw ev types +(define-key (current-global-map) [xwidget-event] 'xwidget-event-handler) +(defun xwidget-log ( &rest msg) + "Log MSG to a buffer." + (let ( (buf (get-buffer-create "*xwidget-log*"))) + (save-excursion + (buffer-disable-undo buf) + (set-buffer buf) + (insert (apply 'format msg)) + (insert "\n")))) + +(defun xwidget-event-handler () + "Receive xwidget event." + (interactive) + (xwidget-log "stuff happened to xwidget %S" last-input-event) + (let* + ((xwidget-event-type (nth 1 last-input-event)) + (xwidget (nth 2 last-input-event)) + ;;(xwidget-callback (xwidget-get xwidget 'callback)) + ;;TODO stopped working for some reason + ) + ;;(funcall xwidget-callback xwidget xwidget-event-type) + (message "xw callback %s" xwidget) + (funcall 'xwidget-webkit-callback xwidget xwidget-event-type))) + +(defun xwidget-webkit-callback (xwidget xwidget-event-type) + "Callback for xwidgets. +XWIDGET instance, XWIDGET-EVENT-TYPE depends on the originating xwidget." + (save-excursion + (cond ((buffer-live-p (xwidget-buffer xwidget)) + (set-buffer (xwidget-buffer xwidget)) + (let* ((strarg (nth 3 last-input-event))) + (cond ((eq xwidget-event-type 'document-load-finished) + (xwidget-log "webkit finished loading: '%s'" + (xwidget-webkit-get-title xwidget)) + ;;TODO - check the native/internal scroll + ;;(xwidget-adjust-size-to-content xwidget) + (xwidget-webkit-adjust-size-dispatch) ;;TODO xwidget arg + (rename-buffer (format "*xwidget webkit: %s *" + (xwidget-webkit-get-title xwidget))) + (pop-to-buffer (current-buffer))) + ((eq xwidget-event-type + 'navigation-policy-decision-requested) + (if (string-match ".*#\\(.*\\)" strarg) + (xwidget-webkit-show-id-or-named-element + xwidget + (match-string 1 strarg)))) + (t (xwidget-log "unhandled event:%s" xwidget-event-type))))) + (t (xwidget-log + "error: callback called for xwidget with dead buffer"))))) + +(defvar bookmark-make-record-function) +(define-derived-mode xwidget-webkit-mode + special-mode "xwidget-webkit" "xwidget webkit view mode" + (setq buffer-read-only t) + (setq-local bookmark-make-record-function + #'xwidget-webkit-bookmark-make-record) + ;; Keep track of [vh]scroll when switching buffers + (image-mode-setup-winprops)) + +(defun xwidget-webkit-bookmark-make-record () +"Integrate Emacs bookmarks with the webkit xwidget." + (nconc (bookmark-make-record-default t t) + `((page . ,(xwidget-webkit-current-url)) + (handler . (lambda (bmk) (browse-url + (bookmark-prop-get bmk 'page))))))) + + +(defvar xwidget-webkit-last-session-buffer nil) + +(defun xwidget-webkit-last-session () + "Last active webkit, or nil." + (if (buffer-live-p xwidget-webkit-last-session-buffer) + (with-current-buffer xwidget-webkit-last-session-buffer + (xwidget-at 1)) + nil)) + +(defun xwidget-webkit-current-session () + "Either the webkit in the current buffer, or the last one used, +which might be nil." + (if (xwidget-at 1) + (xwidget-at 1) + (xwidget-webkit-last-session))) + +(defun xwidget-adjust-size-to-content (xw) + "Resize XW to content." + ;;xwidgets doesnt support widgets that have their own opinions about + ;;size well yet this reads the desired size and resizes the emacs + ;;allocated area accordingly + (let ((size (xwidget-size-request xw))) + (xwidget-resize xw (car size) (cadr size)))) + + +(defvar xwidget-webkit-activeelement-js" +function findactiveelement(doc){ +//alert(doc.activeElement.value); + if(doc.activeElement.value != undefined){ + return doc.activeElement; + }else{ + // recurse over the child documents: + var frames = doc.getElementsByTagName('frame'); + for (var i = 0; i < frames.length; i++) + { + var d = frames[i].contentDocument; + var rv = findactiveelement(d); + if(rv != undefined){ + return rv; + } + } + } + return undefined; +}; + + +" + + "javascript that finds the active element." + ;;yes its ugly. because: + ;; - there is aparently no way to find the active frame other than recursion + ;; - the js "for each" construct missbehaved on the "frames" collection + ;; - a window with no frameset still has frames.length == 1, but + ;; frames[0].document.activeElement != document.activeElement + ;;TODO the activeelement type needs to be examined, for iframe, etc. + ) + +(defun xwidget-webkit-insert-string (xw str) + "Insert string in the active field in the webkit. +Argument XW webkit. +Argument STR string." + ;;read out the string in the field first and provide for edit + (interactive + (let* ((xww (xwidget-webkit-current-session)) + + (field-value + (progn + (xwidget-webkit-execute-script xww xwidget-webkit-activeelement-js) + (xwidget-webkit-execute-script-rv + xww + "findactiveelement(document).value;" ))) + (field-type (xwidget-webkit-execute-script-rv + xww + "findactiveelement(document).type;" ))) + (list xww + (cond ((equal "text" field-type) + (read-string "text:" field-value)) + ((equal "password" field-type) + (read-passwd "password:" nil field-value)) + ((equal "textarea" field-type) + (xwidget-webkit-begin-edit-textarea xww field-value)))))) + (xwidget-webkit-execute-script + xw + (format "findactiveelement(document).value='%s'" str))) + +(defvar xwidget-xwbl) +(defun xwidget-webkit-begin-edit-textarea (xw text) + "Start editing of a webkit text area. +XW is the xwidget identifier, TEXT is retrieved from the webkit." + (switch-to-buffer + (generate-new-buffer "textarea")) + + (set (make-local-variable 'xwidget-xwbl) xw) + (insert text)) + +(defun xwidget-webkit-end-edit-textarea () + "End editing of a webkit text area." + (interactive) + (goto-char (point-min)) + (while (search-forward "\n" nil t) + (replace-match "\\n" nil t)) + (xwidget-webkit-execute-script + xwidget-xwbl + (format "findactiveelement(document).value='%s'" + (buffer-substring (point-min) (point-max)))) + ;;TODO convert linefeed to \n + ) + +(defun xwidget-webkit-show-named-element (xw element-name) + "Make named-element show. for instance an anchor. +Argument XW is the xwidget. +Argument ELEMENT-NAME is the element name to display in the webkit xwidget." + (interactive (list (xwidget-webkit-current-session) + (read-string "element name:"))) + ;;TODO since an xwidget is an Emacs object, it is not trivial to do + ;; some things that are taken for granted in a normal browser. + ;; scrolling an anchor/named-element into view is one such thing. + ;; This function implements a proof-of-concept for this. Problems + ;; remaining: - The selected window is scrolled but this is not + ;; always correct - This needs to be interfaced into browse-url + ;; somehow. the tricky part is that we need to do this in two steps: + ;; A: load the base url, wait for load signal to arrive B: navigate + ;; to the anchor when the base url is finished rendering + + ;; This part figures out the Y coordinate of the element + (let ((y (string-to-number + (xwidget-webkit-execute-script-rv + xw + (format + "document.getElementsByName('%s')[0].getBoundingClientRect().top" + element-name) + 0)))) + ;; Now we need to tell emacs to scroll the element into view. + (xwidget-log "scroll: %d" y) + (set-window-vscroll (selected-window) y t))) + +(defun xwidget-webkit-show-id-element (xw element-id) + "Make id-element show. for instance an anchor. +Argument XW is the webkit xwidget. +Argument ELEMENT-ID is the id of the element to show." + (interactive (list (xwidget-webkit-current-session) + (read-string "element id:"))) + (let ((y (string-to-number + (xwidget-webkit-execute-script-rv + xw + (format "document.getElementById('%s').getBoundingClientRect().top" + element-id) + 0)))) + ;; Now we need to tell emacs to scroll the element into view. + (xwidget-log "scroll: %d" y) + (set-window-vscroll (selected-window) y t))) + +(defun xwidget-webkit-show-id-or-named-element (xw element-id) + "Make id-element show. for instance an anchor. +Argument XW is the webkit xwidget. +Argument ELEMENT-ID is either a name or an element id." + (interactive (list (xwidget-webkit-current-session) + (read-string "element id:"))) + (let* ((y1 (string-to-number + (xwidget-webkit-execute-script-rv + xw + (format "document.getElementsByName('%s')[0].getBoundingClientRect().top" element-id) + "0"))) + (y2 (string-to-number + (xwidget-webkit-execute-script-rv + xw + (format "document.getElementById('%s').getBoundingClientRect().top" element-id) + "0"))) + (y3 (max y1 y2))) + ;; Now we need to tell emacs to scroll the element into view. + (xwidget-log "scroll: %d" y3) + (set-window-vscroll (selected-window) y3 t))) + +(defun xwidget-webkit-adjust-size-to-content () + "Adjust webkit to content size." + (interactive) + (xwidget-adjust-size-to-content (xwidget-webkit-current-session))) + +(defun xwidget-webkit-adjust-size-dispatch () + "Adjust size according to mode." + (interactive) + (if (eq xwidget-webkit-scroll-behaviour 'native) + (xwidget-webkit-adjust-size-to-window) + (xwidget-webkit-adjust-size-to-content)) + ;; The recenter is intended to correct a visual glitch. + ;; It errors out if the buffer isn't visible, but then we dont get the glitch, + ;; so silence errors + (ignore-errors + (recenter-top-bottom)) + ) + +(defun xwidget-webkit-adjust-size-to-window () + "Adjust webkit to window." + (interactive) + (xwidget-resize ( xwidget-webkit-current-session) (window-pixel-width) + (window-pixel-height))) + +(defun xwidget-webkit-adjust-size (w h) + "Manualy set webkit size. +Argument W width. +Argument H height." + ;; TODO shouldn't be tied to the webkit xwidget + (interactive "nWidth:\nnHeight:\n") + (xwidget-resize ( xwidget-webkit-current-session) w h)) + +(defun xwidget-webkit-fit-width () + "Adjust width of webkit to window width." + (interactive) + (xwidget-webkit-adjust-size (- (nth 2 (window-inside-pixel-edges)) + (car (window-inside-pixel-edges))) + 1000)) + +(defun xwidget-webkit-new-session (url) + "Create a new webkit session buffer with URL." + (let* + ((bufname (generate-new-buffer-name "*xwidget-webkit*")) + xw) + (setq xwidget-webkit-last-session-buffer (switch-to-buffer + (get-buffer-create bufname))) + (insert " 'a' adjusts the xwidget size.") + (setq xw (xwidget-insert 1 'webkit-osr bufname 1000 1000)) + (xwidget-put xw 'callback 'xwidget-webkit-callback) + (xwidget-webkit-mode) + (xwidget-webkit-goto-uri (xwidget-webkit-last-session) url ))) + + +(defun xwidget-webkit-goto-url (url) + "Goto URL." + (if (xwidget-webkit-current-session) + (progn + (xwidget-webkit-goto-uri (xwidget-webkit-current-session) url)) + (xwidget-webkit-new-session url))) + +(defun xwidget-webkit-back () + "Back in history." + (interactive) + (xwidget-webkit-execute-script (xwidget-webkit-current-session) + "history.go(-1);")) + +(defun xwidget-webkit-reload () + "Reload current url." + (interactive) + (xwidget-webkit-execute-script (xwidget-webkit-current-session) + "history.go(0);")) + +(defun xwidget-webkit-current-url () + "Get the webkit url. place it on kill ring." + (interactive) + (let* ((rv (xwidget-webkit-execute-script-rv (xwidget-webkit-current-session) + "document.URL")) + (url (kill-new (or rv "")))) + (message "url: %s" url ) + url)) + +(defun xwidget-webkit-execute-script-rv (xw script &optional default) + "Same as 'xwidget-webkit-execute-script' but but with return value. +XW is the webkit instance. SCRIPT is the script to execut. +DEFAULT is the defaultreturn value." + ;; Notice the ugly "title" hack. It is needed because the Webkit + ;; API at the time of writing didn't support returning values. This + ;; is a wrapper for the title hack so its easy to remove should + ;; Webkit someday support JS return values or we find some other way + ;; to access the DOM. + + ;; Reset webkit title. Not very nice. + (let* ((emptytag "titlecantbewhitespaceohthehorror") + title) + (xwidget-webkit-execute-script xw (format "document.title=\"%s\";" + (or default emptytag))) + (xwidget-webkit-execute-script xw (format "document.title=%s;" script)) + (setq title (xwidget-webkit-get-title xw)) + (if (equal emptytag title) + (setq title "")) + (unless title + (setq title default)) + title)) + + +;; Use declare here? +;; (declare-function xwidget-resize-internal "xwidget.c" ) +;; check-declare-function? + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defun xwidget-webkit-get-selection () + "Get the webkit selection." + (xwidget-webkit-execute-script-rv (xwidget-webkit-current-session) + "window.getSelection().toString();")) + +(defun xwidget-webkit-copy-selection-as-kill () + "Get the webkit selection and put it on the kill ring." + (interactive) + (kill-new (xwidget-webkit-get-selection))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Xwidget plist management(similar to the process plist functions) + +(defun xwidget-get (xwidget propname) + "Return the value of XWIDGET' PROPNAME property. +This is the last value stored with `(xwidget-put XWIDGET PROPNAME VALUE)'." + (plist-get (xwidget-plist xwidget) propname)) + +(defun xwidget-put (xwidget propname value) + "Change XWIDGET' PROPNAME property to VALUE. +It can be retrieved with `(xwidget-get XWIDGET PROPNAME)'." + (set-xwidget-plist xwidget + (plist-put (xwidget-plist xwidget) propname value))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun xwidget-delete-zombies () + "Helper for `xwidget-cleanup'." + (dolist (xwidget-view xwidget-view-list) + (when (or (not (window-live-p (xwidget-view-window xwidget-view))) + (not (memq (xwidget-view-model xwidget-view) + xwidget-list))) + (delete-xwidget-view xwidget-view)))) + +(defun xwidget-cleanup () + "Delete zombie xwidgets." + ;; During development it was sometimes easy to wind up with zombie + ;; xwidget instances. + ;; This function tries to implement a workaround should it occur again. + (interactive) + ;; Kill xviews who should have been deleted but stull linger. + (xwidget-delete-zombies) + ;; Redraw display otherwise ghost of zombies will remain to haunt the screen + (redraw-display)) + +;; This would have felt better in C, but this seems to work well in +;; practice though. +(add-hook 'window-configuration-change-hook 'xwidget-delete-zombies) + +(defun xwidget-kill-buffer-query-function () + "Ask beforek illing a buffer that has xwidgets." + (let ((xwidgets (get-buffer-xwidgets (current-buffer)))) + (or (not xwidgets) + (not (memq t (mapcar 'xwidget-query-on-exit-flag xwidgets))) + (yes-or-no-p + (format "Buffer %S has xwidgets; kill it? " + (buffer-name (current-buffer))))))) + +(add-hook 'kill-buffer-query-functions 'xwidget-kill-buffer-query-function) + +(defun report-xwidget-bug () + "Report a bug in GNU Emacs about the XWidget branch. +Prompts for bug subject. Leaves you in a mail buffer." + (interactive) + (let ((reporter-prompt-for-summary-p t)) + (reporter-submit-bug-report "submit@debbugs.gnu.org" nil nil nil nil + (format "Package: emacs-xwidgets + +Please describe exactly what actions triggered the bug, and the +precise symptoms of the bug. If you can, give a recipe starting +from `emacs -Q'. + +If Emacs crashed, and you have the Emacs process in the gdb +deubbger, please include the output from the following gdb +commands: + `bt full' and `xbacktrace'. + +For information about debugging Emacs, please read the file +%s" (expand-file-name "DEBUG" data-directory))))) + +(provide 'xwidget) + +;;; xwidget.el ends here diff --git a/src/Makefile.in b/src/Makefile.in index 74c0e4eeda5..2b5ae30a704 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -152,6 +152,9 @@ DBUS_LIBS = @DBUS_LIBS@ ## dbusbind.o if HAVE_DBUS, else empty. DBUS_OBJ = @DBUS_OBJ@ +## xwidgets.o if HAVE_XWIDGETS, else empty. +XWIDGETS_OBJ = @XWIDGETS_OBJ@ + LIB_EXECINFO=@LIB_EXECINFO@ SETTINGS_CFLAGS = @SETTINGS_CFLAGS@ @@ -219,6 +222,11 @@ CFLAGS_SOUND= @CFLAGS_SOUND@ RSVG_LIBS= @RSVG_LIBS@ RSVG_CFLAGS= @RSVG_CFLAGS@ +WEBKIT_LIBS= @WEBKIT_LIBS@ +WEBKIT_CFLAGS= @WEBKIT_CFLAGS@ + +GIR_LIBS= @GIR_LIBS@ +GIR_CFLAGS= @GIR_CFLAGS@ CAIRO_LIBS= @CAIRO_LIBS@ CAIRO_CFLAGS= @CAIRO_CFLAGS@ @@ -358,6 +366,7 @@ ALL_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \ $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \ $(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \ $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \ + $(WEBKIT_CFLAGS) $(GIR_CFLAGS) \ $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \ $(LIBGNUTLS_CFLAGS) $(GFILENOTIFY_CFLAGS) $(CAIRO_CFLAGS) \ @@ -387,6 +396,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \ process.o gnutls.o callproc.o \ region-cache.o sound.o atimer.o \ doprnt.o intervals.o textprop.o composite.o xml.o $(NOTIFY_OBJ) \ + $(XWIDGETS_OBJ) \ profiler.o decompress.o \ $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \ $(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ) @@ -467,6 +477,7 @@ lisp = $(addprefix ${lispsource}/,${shortlisp}) LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ $(LIBX_OTHER) $(LIBSOUND) \ $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \ + $(WEBKIT_LIBS) $(GIR_LIBS) \ $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \ $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \ $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) $(CAIRO_LIBS) \ diff --git a/src/buffer.c b/src/buffer.c index b02135cef87..a2981c90f66 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -43,6 +43,9 @@ along with GNU Emacs. If not, see . */ #include "keymap.h" #include "frame.h" +#ifdef HAVE_XWIDGETS +# include "xwidget.h" +#endif #ifdef WINDOWSNT #include "w32heap.h" /* for mmap_* */ #endif @@ -1747,6 +1750,9 @@ cleaning up all windows currently displaying the buffer to be killed. */) kill_buffer_processes (buffer); +#ifdef HAVE_XWIDGETS + kill_buffer_xwidgets (buffer); +#endif /* Killing buffer processes may run sentinels which may have killed our buffer. */ if (!BUFFER_LIVE_P (b)) diff --git a/src/dispextern.h b/src/dispextern.h index bb876f5af70..fad5bfd6f2f 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -348,6 +348,10 @@ enum glyph_type /* Glyph is a space of fractional width and/or height. */ STRETCH_GLYPH +#ifdef HAVE_XWIDGETS + /* Glyph is an external widget drawn by the GUI toolkit. */ + ,XWIDGET_GLYPH +#endif }; @@ -499,6 +503,9 @@ struct glyph /* Image ID for image glyphs (type == IMAGE_GLYPH). */ int img_id; +#ifdef HAVE_XWIDGETS + struct xwidget *xwidget; +#endif /* Sub-structure for type == STRETCH_GLYPH. */ struct { @@ -1350,6 +1357,9 @@ struct glyph_string /* Image, if any. */ struct image *img; +#ifdef HAVE_XWIDGETS + struct xwidget *xwidget; +#endif /* Slice */ struct glyph_slice slice; @@ -2102,6 +2112,10 @@ enum display_element_type /* Continuation glyphs. See the comment for IT_TRUNCATION. */ IT_CONTINUATION + +#ifdef HAVE_XWIDGETS + ,IT_XWIDGET +#endif }; @@ -2165,6 +2179,9 @@ enum it_method { GET_FROM_C_STRING, GET_FROM_IMAGE, GET_FROM_STRETCH, +#ifdef HAVE_XWIDGETS + GET_FROM_XWIDGET, +#endif NUM_IT_METHODS }; @@ -2382,6 +2399,12 @@ struct it struct { Lisp_Object object; } stretch; +#ifdef HAVE_XWIDGETS + /* method == GET_FROM_XWIDGET */ + struct { + Lisp_Object object; + } xwidget; +#endif } u; /* Current text and display positions. */ @@ -2506,6 +2529,11 @@ struct it /* If what == IT_IMAGE, the id of the image to display. */ ptrdiff_t image_id; +#ifdef HAVE_XWIDGETS + /* If what == IT_XWIDGET. */ + struct xwidget *xwidget; +#endif + /* Values from `slice' property. */ struct it_slice slice; diff --git a/src/dispnew.c b/src/dispnew.c index 3e1557fa3b9..571ed5f851f 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -44,6 +44,10 @@ along with GNU Emacs. If not, see . */ #include TERM_HEADER #endif /* HAVE_WINDOW_SYSTEM */ +#ifdef HAVE_XWIDGETS +# include "xwidget.h" +#endif + #include #include @@ -3545,6 +3549,9 @@ update_window (struct window *w, bool force_p) add_window_display_history (w, w->current_matrix->method, paused_p); #endif +#ifdef HAVE_XWIDGETS + xwidget_end_redisplay (w, w->current_matrix); +#endif clear_glyph_matrix (desired_matrix); return paused_p; @@ -4118,6 +4125,11 @@ scrolling_window (struct window *w, bool header_line_p) break; } +#ifdef HAVE_XWIDGETS + /* Currently this seems needed to detect xwidget movement reliably. */ + return 0; +#endif + /* Give up if some rows in the desired matrix are not enabled. */ if (! MATRIX_ROW_ENABLED_P (desired_matrix, i)) return -1; diff --git a/src/emacs.c b/src/emacs.c index b1b2170a028..6de0fffb904 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -66,6 +66,9 @@ along with GNU Emacs. If not, see . */ #include "buffer.h" #include "window.h" +#ifdef HAVE_XWIDGETS +# include "xwidget.h" +#endif #include "atimer.h" #include "blockinput.h" #include "syssignal.h" @@ -1485,6 +1488,9 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem syms_of_xfns (); syms_of_xmenu (); syms_of_fontset (); +#ifdef HAVE_XWIDGETS + syms_of_xwidget (); +#endif syms_of_xsettings (); #ifdef HAVE_X_SM syms_of_xsmfns (); diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c index cdcaf803ba5..da1017df2ae 100644 --- a/src/emacsgtkfixed.c +++ b/src/emacsgtkfixed.c @@ -23,6 +23,9 @@ along with GNU Emacs. If not, see . */ #include "lisp.h" #include "frame.h" #include "xterm.h" +#ifdef HAVE_XWIDGETS +# include "xwidget.h" +#endif #include "emacsgtkfixed.h" /* Silence a bogus diagnostic; see GNOME bug 683906. */ @@ -31,27 +34,10 @@ along with GNU Emacs. If not, see . */ # pragma GCC diagnostic ignored "-Wunused-local-typedefs" #endif -#define EMACS_TYPE_FIXED emacs_fixed_get_type () -#define EMACS_FIXED(obj) \ - G_TYPE_CHECK_INSTANCE_CAST (obj, EMACS_TYPE_FIXED, EmacsFixed) - typedef struct _EmacsFixed EmacsFixed; typedef struct _EmacsFixedPrivate EmacsFixedPrivate; typedef struct _EmacsFixedClass EmacsFixedClass; -struct _EmacsFixed -{ - GtkFixed container; - - /*< private >*/ - EmacsFixedPrivate *priv; -}; - -struct _EmacsFixedClass -{ - GtkFixedClass parent_class; -}; - struct _EmacsFixedPrivate { struct frame *f; @@ -64,9 +50,87 @@ static void emacs_fixed_get_preferred_width (GtkWidget *widget, static void emacs_fixed_get_preferred_height (GtkWidget *widget, gint *minimum, gint *natural); -static GType emacs_fixed_get_type (void); G_DEFINE_TYPE (EmacsFixed, emacs_fixed, GTK_TYPE_FIXED) +#ifdef HAVE_XWIDGETS + +struct GtkFixedPrivateL +{ + GList *children; +}; + +static void emacs_fixed_gtk_widget_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + // For xwidgets. + + // This basically re-implements the base class method and adds an + // additional case for an xwidget view. + + // It would be nicer if the bse class method could be called first, + // and the the xview modification only would remain here. It wasn't + // possible to solve it that way yet. + EmacsFixedClass *klass; + GtkWidgetClass *parent_class; + struct GtkFixedPrivateL* priv; + + klass = EMACS_FIXED_GET_CLASS (widget); + parent_class = g_type_class_peek_parent (klass); + parent_class->size_allocate (widget, allocation); + + priv = G_TYPE_INSTANCE_GET_PRIVATE (widget, + GTK_TYPE_FIXED, + struct GtkFixedPrivateL); + + gtk_widget_set_allocation (widget, allocation); + + if (gtk_widget_get_has_window (widget)) + { + if (gtk_widget_get_realized (widget)) + gdk_window_move_resize (gtk_widget_get_window (widget), + allocation->x, + allocation->y, + allocation->width, + allocation->height); + } + + for (GList *children = priv->children; children; children = children->next) + { + GtkFixedChild *child = children->data; + + if (!gtk_widget_get_visible (child->widget)) + continue; + + GtkRequisition child_requisition; + gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL); + + GtkAllocation child_allocation; + child_allocation.x = child->x; + child_allocation.y = child->y; + + if (!gtk_widget_get_has_window (widget)) + { + child_allocation.x += allocation->x; + child_allocation.y += allocation->y; + } + + child_allocation.width = child_requisition.width; + child_allocation.height = child_requisition.height; + + struct xwidget_view *xv + = g_object_get_data (G_OBJECT (child->widget), XG_XWIDGET_VIEW); + if (xv) + { + child_allocation.width = xv->clip_right; + child_allocation.height = xv->clip_bottom - xv->clip_top; + } + + gtk_widget_size_allocate (child->widget, &child_allocation); + } +} + +#endif /* HAVE_XWIDGETS */ + static void emacs_fixed_class_init (EmacsFixedClass *klass) { @@ -74,11 +138,16 @@ emacs_fixed_class_init (EmacsFixedClass *klass) widget_class = (GtkWidgetClass*) klass; + widget_class->get_preferred_width = emacs_fixed_get_preferred_width; widget_class->get_preferred_height = emacs_fixed_get_preferred_height; +#ifdef HAVE_XWIDGETS + widget_class->size_allocate = emacs_fixed_gtk_widget_size_allocate; +#endif g_type_class_add_private (klass, sizeof (EmacsFixedPrivate)); } + static void emacs_fixed_init (EmacsFixed *fixed) { diff --git a/src/emacsgtkfixed.h b/src/emacsgtkfixed.h index 73280b83e57..5b2fa566785 100644 --- a/src/emacsgtkfixed.h +++ b/src/emacsgtkfixed.h @@ -27,7 +27,35 @@ struct frame; G_BEGIN_DECLS +struct frame; + +#define EMACS_TYPE_FIXED (emacs_fixed_get_type ()) +#define EMACS_FIXED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMACS_TYPE_FIXED, EmacsFixed)) +#define EMACS_FIXED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EMACS_TYPE_FIXED, EmacsFixedClass)) +#define EMACS_IS_FIXED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMACS_TYPE_FIXED)) +#define EMACS_IS_FIXED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EMACS_TYPE_FIXED)) +#define EMACS_FIXED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EMACS_TYPE_FIXED, EmacsFixedClass)) + +//typedef struct _EmacsFixed EmacsFixed; +typedef struct _EmacsFixedPrivate EmacsFixedPrivate; +typedef struct _EmacsFixedClass EmacsFixedClass; + +struct _EmacsFixed +{ + GtkFixed container; + + /*< private >*/ + EmacsFixedPrivate *priv; +}; + + +struct _EmacsFixedClass +{ + GtkFixedClass parent_class; +}; + extern GtkWidget *emacs_fixed_new (struct frame *f); +extern GType emacs_fixed_get_type (void); G_END_DECLS diff --git a/src/keyboard.c b/src/keyboard.c index 6bdfc1aa084..58831f548ca 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -4013,6 +4013,13 @@ kbd_buffer_get_event (KBOARD **kbp, obj = make_lispy_event (&event->ie); kbd_fetch_ptr = event + 1; } +#endif +#ifdef HAVE_XWIDGETS + else if (event->kind == XWIDGET_EVENT) + { + obj = make_lispy_event (&event->ie); + kbd_fetch_ptr = event + 1; + } #endif else if (event->kind == CONFIG_CHANGED_EVENT) { @@ -5950,6 +5957,14 @@ make_lispy_event (struct input_event *event) } #endif /* HAVE_DBUS */ +#ifdef HAVE_XWIDGETS + case XWIDGET_EVENT: + { + return Fcons (Qxwidget_event,event->arg); + } +#endif + + #if defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY case FILE_NOTIFY_EVENT: { @@ -10956,6 +10971,10 @@ syms_of_keyboard (void) DEFSYM (Qdbus_event, "dbus-event"); #endif +#ifdef HAVE_XWIDGETS + DEFSYM (Qxwidget_event,"xwidget-event"); +#endif + #ifdef USE_FILE_NOTIFY DEFSYM (Qfile_notify, "file-notify"); #endif /* USE_FILE_NOTIFY */ diff --git a/src/lisp.h b/src/lisp.h index f33a8f2494e..b0a8d75c439 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -799,6 +799,12 @@ enum pvec_type PVEC_WINDOW_CONFIGURATION, PVEC_SUBR, PVEC_OTHER, + +#ifdef HAVE_XWIDGETS + PVEC_XWIDGET, + PVEC_XWIDGET_VIEW, +#endif + /* These should be last, check internal_equal to see why. */ PVEC_COMPILED, PVEC_CHAR_TABLE, diff --git a/src/print.c b/src/print.c index 269d8f250e2..4dd4e963093 100644 --- a/src/print.c +++ b/src/print.c @@ -33,6 +33,10 @@ along with GNU Emacs. If not, see . */ #include "intervals.h" #include "blockinput.h" +#ifdef HAVE_XWIDGETS +# include "xwidget.h" +#endif + #include #include #include @@ -1736,6 +1740,18 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) print_c_string (XSUBR (obj)->symbol_name, printcharfun); printchar ('>', printcharfun); } +#ifdef HAVE_XWIDGETS + else if (XWIDGETP (obj)) + { + print_c_string ("#', printcharfun); + } + else if (XWIDGET_VIEW_P (obj)) + { + print_c_string ("#', printcharfun); + } +#endif else if (WINDOWP (obj)) { int len = sprintf (buf, "#. */ #ifdef MSDOS #include "msdos.h" #endif +#ifdef HAVE_XWIDGETS +# include "xwidget.h" +#endif static ptrdiff_t count_windows (struct window *); static ptrdiff_t get_leaf_windows (struct window *, struct window **, @@ -4370,6 +4373,9 @@ Signal an error when WINDOW is the only window on its frame. */) /* Block input. */ block_input (); +#ifdef HAVE_XWIDGETS + xwidget_view_delete_all_in_window (w); +#endif window_resize_apply (p, horflag); /* If this window is referred to by the dpyinfo's mouse highlight, invalidate that slot to be safe (Bug#9904). */ diff --git a/src/xdisp.c b/src/xdisp.c index d730a0bf1b6..89385c0e172 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -318,6 +318,9 @@ along with GNU Emacs. If not, see . */ #include TERM_HEADER #endif /* HAVE_WINDOW_SYSTEM */ +#ifdef HAVE_XWIDGETS +# include "xwidget.h" +#endif #ifndef FRAME_X_OUTPUT #define FRAME_X_OUTPUT(f) ((f)->output_data.x) #endif @@ -854,6 +857,9 @@ static bool next_element_from_buffer (struct it *); static bool next_element_from_composition (struct it *); static bool next_element_from_image (struct it *); static bool next_element_from_stretch (struct it *); +#ifdef HAVE_XWIDGETS +static bool next_element_from_xwidget (struct it *); +#endif static void load_overlay_strings (struct it *, ptrdiff_t); static bool get_next_display_element (struct it *); static enum move_it_result @@ -4690,6 +4696,9 @@ handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, if (CONSP (spec) /* Simple specifications. */ && !EQ (XCAR (spec), Qimage) +#ifdef HAVE_XWIDGETS + && !EQ (XCAR (spec), Qxwidget) +#endif && !EQ (XCAR (spec), Qspace) && !EQ (XCAR (spec), Qwhen) && !EQ (XCAR (spec), Qslice) @@ -5137,7 +5146,12 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p) && valid_image_p (value)) #endif /* not HAVE_WINDOW_SYSTEM */ - || (CONSP (value) && EQ (XCAR (value), Qspace))); + || (CONSP (value) && EQ (XCAR (value), Qspace)) +#ifdef HAVE_XWIDGETS + || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p) + && valid_xwidget_spec_p (value)) +#endif + ); if (valid_p && display_replaced == 0) { @@ -5212,6 +5226,17 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, *position = it->position = start_pos; retval = 1 + (it->area == TEXT_AREA); } +#ifdef HAVE_XWIDGETS + else if (valid_xwidget_spec_p(value)) + { + it->what = IT_XWIDGET; + it->method = GET_FROM_XWIDGET; + it->position = start_pos; + it->object = NILP (object) ? it->w->contents : object; + *position = start_pos; + it->xwidget = lookup_xwidget(value); + } +#endif #ifdef HAVE_WINDOW_SYSTEM else { @@ -5964,6 +5989,11 @@ push_it (struct it *it, struct text_pos *position) case GET_FROM_STRETCH: p->u.stretch.object = it->object; break; +#ifdef HAVE_XWIDGETS + case GET_FROM_XWIDGET: + p->u.xwidget.object = it->object; + break; +#endif case GET_FROM_BUFFER: case GET_FROM_DISPLAY_VECTOR: case GET_FROM_STRING: @@ -6065,6 +6095,11 @@ pop_it (struct it *it) it->object = p->u.image.object; it->slice = p->u.image.slice; break; +#ifdef HAVE_XWIDGETS + case GET_FROM_XWIDGET: + it->object = p->u.xwidget.object; + break; +#endif case GET_FROM_STRETCH: it->object = p->u.stretch.object; break; @@ -6739,7 +6774,10 @@ static next_element_function const get_next_element[NUM_IT_METHODS] = next_element_from_string, next_element_from_c_string, next_element_from_image, - next_element_from_stretch + next_element_from_stretch, +#ifdef HAVE_XWIDGETS + next_element_from_xwidget, +#endif }; #define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it) @@ -7600,6 +7638,10 @@ set_iterator_to_next (struct it *it, bool reseat_p) case GET_FROM_IMAGE: case GET_FROM_STRETCH: +#ifdef HAVE_XWIDGETS + case GET_FROM_XWIDGET: +#endif + /* The position etc with which we have to proceed are on the stack. The position may be at the end of a string, if the `display' property takes up the whole string. */ @@ -8061,6 +8103,15 @@ next_element_from_image (struct it *it) return true; } +#ifdef HAVE_XWIDGETS +static bool +next_element_from_xwidget (struct it *it) +{ + it->what = IT_XWIDGET; + return true; +} +#endif + /* Fill iterator IT with next display element from a stretch glyph property. IT->object is the value of the text property. Value is @@ -18793,6 +18844,28 @@ dump_glyph (struct glyph_row *row, struct glyph *glyph, int area) glyph->left_box_line_p, glyph->right_box_line_p); } +#ifdef HAVE_XWIDGETS + else if (glyph->type == XWIDGET_GLYPH) + { + fprintf (stderr, + " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n", + glyph - row->glyphs[TEXT_AREA], + 'X', + glyph->charpos, + (BUFFERP (glyph->object) + ? 'B' + : (STRINGP (glyph->object) + ? 'S' + : '-')), + glyph->pixel_width, + glyph->u.xwidget, + '.', + glyph->face_id, + glyph->left_box_line_p, + glyph->right_box_line_p); + + } +#endif } @@ -24291,6 +24364,13 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, return OK_PIXELS (width_p ? img->width : img->height); } +# ifdef HAVE_XWIDGETS + if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop)) + { + // TODO: Don't return dummy size. + return OK_PIXELS (100); + } +# endif #endif if (EQ (car, Qplus) || EQ (car, Qminus)) { @@ -24796,6 +24876,18 @@ fill_image_glyph_string (struct glyph_string *s) } +#ifdef HAVE_XWIDGETS +static void +fill_xwidget_glyph_string (struct glyph_string *s) +{ + eassert (s->first_glyph->type == XWIDGET_GLYPH); + s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id); + s->font = s->face->font; + s->width = s->first_glyph->pixel_width; + s->ybase += s->first_glyph->voffset; + s->xwidget = s->first_glyph->u.xwidget; +} +#endif /* Fill glyph string S from a sequence of stretch glyphs. START is the index of the first glyph to consider, @@ -25181,6 +25273,20 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p) } \ while (false) +#ifdef HAVE_XWIDGETS +#define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \ + do \ + { \ + s = alloca (sizeof *s); \ + INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \ + fill_xwidget_glyph_string (s); \ + append_glyph_string (&(HEAD), &(TAIL), s); \ + ++(START); \ + s->x = (X); \ + } \ + while (false) +#endif + /* Add a glyph string for a sequence of character glyphs to the list of strings between HEAD and TAIL. START is the index of the first @@ -25302,7 +25408,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p) to allocate glyph strings (because draw_glyphs can be called asynchronously). */ -#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \ +#define BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \ do \ { \ HEAD = TAIL = NULL; \ @@ -25333,8 +25439,17 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p) case IMAGE_GLYPH: \ BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \ HL, X, LAST_X); \ - break; \ - \ + break; + +#ifdef HAVE_XWIDGETS +# define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \ + case XWIDGET_GLYPH: \ + BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL, \ + HL, X, LAST_X); \ + break; +#endif + +#define BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) \ case GLYPHLESS_GLYPH: \ BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \ HL, X, LAST_X); \ @@ -25353,6 +25468,18 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p) } while (false) +#ifdef HAVE_XWIDGETS +# define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \ + BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \ + BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \ + BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) +#else +# define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \ + BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \ + BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) +#endif + + /* Draw glyphs between START and END in AREA of ROW on window W, starting at x-position X. X is relative to AREA in W. HL is a face-override with the following meaning: @@ -25991,6 +26118,109 @@ produce_image_glyph (struct it *it) } } +#ifdef HAVE_XWIDGETS +static void +produce_xwidget_glyph (struct it *it) +{ + struct xwidget *xw; + int glyph_ascent, crop; + eassert (it->what == IT_XWIDGET); + + struct face *face = FACE_FROM_ID (it->f, it->face_id); + eassert (face); + /* Make sure X resources of the face is loaded. */ + prepare_face_for_display (it->f, face); + + xw = it->xwidget; + it->ascent = it->phys_ascent = glyph_ascent = xw->height/2; + it->descent = xw->height/2; + it->phys_descent = it->descent; + it->pixel_width = xw->width; + /* It's quite possible for images to have an ascent greater than + their height, so don't get confused in that case. */ + if (it->descent < 0) + it->descent = 0; + + it->nglyphs = 1; + + if (face->box != FACE_NO_BOX) + { + if (face->box_line_width > 0) + { + it->ascent += face->box_line_width; + it->descent += face->box_line_width; + } + + if (it->start_of_box_run_p) + it->pixel_width += eabs (face->box_line_width); + it->pixel_width += eabs (face->box_line_width); + } + + take_vertical_position_into_account (it); + + /* Automatically crop wide image glyphs at right edge so we can + draw the cursor on same display row. */ + crop = it->pixel_width - (it->last_visible_x - it->current_x); + if (crop > 0 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4)) + it->pixel_width -= crop; + + if (it->glyph_row) + { + enum glyph_row_area area = it->area; + struct glyph *glyph + = it->glyph_row->glyphs[area] + it->glyph_row->used[area]; + + if (it->glyph_row->reversed_p) + { + struct glyph *g; + + /* Make room for the new glyph. */ + for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--) + g[1] = *g; + glyph = it->glyph_row->glyphs[it->area]; + } + if (glyph < it->glyph_row->glyphs[area + 1]) + { + glyph->charpos = CHARPOS (it->position); + glyph->object = it->object; + glyph->pixel_width = it->pixel_width; + glyph->ascent = glyph_ascent; + glyph->descent = it->descent; + glyph->voffset = it->voffset; + glyph->type = XWIDGET_GLYPH; + glyph->avoid_cursor_p = it->avoid_cursor_p; + glyph->multibyte_p = it->multibyte_p; + if (it->glyph_row->reversed_p && area == TEXT_AREA) + { + /* In R2L rows, the left and the right box edges need to be + drawn in reverse direction. */ + glyph->right_box_line_p = it->start_of_box_run_p; + glyph->left_box_line_p = it->end_of_box_run_p; + } + else + { + glyph->left_box_line_p = it->start_of_box_run_p; + glyph->right_box_line_p = it->end_of_box_run_p; + } + glyph->overlaps_vertically_p = 0; + glyph->padding_p = 0; + glyph->glyph_not_available_p = 0; + glyph->face_id = it->face_id; + glyph->u.xwidget = it->xwidget; + glyph->font_type = FONT_TYPE_UNKNOWN; + if (it->bidi_p) + { + glyph->resolved_level = it->bidi_it.resolved_level; + eassert ((it->bidi_it.type & 7) == it->bidi_it.type); + glyph->bidi_type = it->bidi_it.type; + } + ++it->glyph_row->used[area]; + } + else + IT_EXPAND_MATRIX_WIDTH (it, area); + } +} +#endif /* Append a stretch glyph to IT->glyph_row. OBJECT is the source of the glyph, WIDTH and HEIGHT are the width and height of the @@ -27401,6 +27631,10 @@ x_produce_glyphs (struct it *it) produce_image_glyph (it); else if (it->what == IT_STRETCH) produce_stretch_glyph (it); +#ifdef HAVE_XWIDGETS + else if (it->what == IT_XWIDGET) + produce_xwidget_glyph (it); +#endif done: /* Accumulate dimensions. Note: can't assume that it->descent > 0 @@ -27770,6 +28004,10 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width, /* Use normal cursor if not blinked off. */ if (!w->cursor_off_p) { +#ifdef HAVE_XWIDGETS + if (glyph != NULL && glyph->type == XWIDGET_GLYPH) + return NO_CURSOR; +#endif if (glyph != NULL && glyph->type == IMAGE_GLYPH) { if (cursor_type == FILLED_BOX_CURSOR) diff --git a/src/xterm.c b/src/xterm.c index 5a6d643bad4..44eed22d2ec 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -62,6 +62,9 @@ along with GNU Emacs. If not, see . */ #include "composite.h" #include "frame.h" #include "dispextern.h" +#ifdef HAVE_XWIDGETS +# include "xwidget.h" +#endif #include "fontset.h" #include "termhooks.h" #include "termopts.h" @@ -3511,6 +3514,12 @@ x_draw_glyph_string (struct glyph_string *s) x_draw_image_glyph_string (s); break; +#ifdef HAVE_XWIDGETS + case XWIDGET_GLYPH: + x_draw_xwidget_glyph_string (s); + break; +#endif + case STRETCH_GLYPH: x_draw_stretch_glyph_string (s); break; @@ -8920,6 +8929,11 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text if (cursor_glyph == NULL) return; +#ifdef HAVE_XWIDGETS + if (cursor_glyph->type == XWIDGET_GLYPH) + return; // Experimental avoidance of cursor on xwidget. +#endif + /* If on an image, draw like a normal cursor. That's usually better visible than drawing a bar, esp. if the image is large so that the bar might not be in the window. */ diff --git a/src/xwidget.c b/src/xwidget.c new file mode 100644 index 00000000000..74319e1667d --- /dev/null +++ b/src/xwidget.c @@ -0,0 +1,1332 @@ +/* Support for embedding graphical components in a buffer. + +Copyright (C) 2011-2015 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Emacs. If not, see . */ + +#include + + +#include + +#include +#include +#ifdef HAVE_X_WINDOWS + +#include "lisp.h" +#include "blockinput.h" +#include "syssignal.h" + +#include "xterm.h" +#include + +#ifndef makedev +# include +#endif + +#ifdef BSD_SYSTEM +# include +#endif + +#include "systime.h" + +#ifndef INCLUDED_FCNTL +# include +#endif +#include +#include +#include +#include + +#include "charset.h" +#include "character.h" +#include "coding.h" +#include "ccl.h" +#include "frame.h" +#include "dispextern.h" +#include "fontset.h" +#include "termhooks.h" +#include "termopts.h" +#include "termchar.h" +#include "disptab.h" +#include "buffer.h" +#include "window.h" +#include "keyboard.h" +#include "intervals.h" +#include "process.h" +#include "atimer.h" +#include "keymap.h" + + +#ifdef USE_X_TOOLKIT +#include +#endif +#include +#include +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "gtkutil.h" +#include "font.h" +#endif /* HAVE_X_WINDOWS */ + +#include +#include + +#include + +#include "emacsgtkfixed.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "xwidget.h" + +static struct xwidget * +allocate_xwidget (void) +{ + return ALLOCATE_PSEUDOVECTOR (struct xwidget, height, PVEC_XWIDGET); +} + +static struct xwidget_view * +allocate_xwidget_view (void) +{ + return ALLOCATE_PSEUDOVECTOR (struct xwidget_view, redisplayed, + PVEC_XWIDGET_VIEW); +} + +#define XSETXWIDGET(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET)) +#define XSETXWIDGET_VIEW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET_VIEW)) + +struct xwidget_view *xwidget_view_lookup (struct xwidget *, struct window *); +Lisp_Object xwidget_spec_value (Lisp_Object , Lisp_Object , int *); +gboolean offscreen_damage_event (GtkWidget * , GdkEvent * , gpointer ); +void webkit_document_load_finished_cb (WebKitWebView *, WebKitWebFrame *, + gpointer ); +gboolean webkit_download_cb (WebKitWebView *, WebKitDownload *, gpointer); + +gboolean +webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *, + WebKitWebFrame *, + WebKitNetworkRequest *, + gchar *, + WebKitWebPolicyDecision *, + gpointer); + +gboolean +webkit_new_window_policy_decision_requested_cb (WebKitWebView *, + WebKitWebFrame *, + WebKitNetworkRequest *, + WebKitWebNavigationAction *, + WebKitWebPolicyDecision *, + gpointer); + +gboolean +webkit_navigation_policy_decision_requested_cb (WebKitWebView *, + WebKitWebFrame *, + WebKitNetworkRequest *, + WebKitWebNavigationAction *, + WebKitWebPolicyDecision *, + gpointer); + + + +DEFUN ("make-xwidget", + Fmake_xwidget, Smake_xwidget, + 7, 8, 0, + doc: /* Make an xwidget from BEG to END of TYPE. + +If BUFFER is nil it uses the current +buffer. If BUFFER is a string and no such +buffer exists, it is created. + +TYPE is a symbol which can take one of the +following values: + +- webkit_osr + +Returns the newly constructed xwidget, or nil if construction +fails. */) + (Lisp_Object beg, Lisp_Object end, + Lisp_Object type, + Lisp_Object title, + Lisp_Object width, Lisp_Object height, + Lisp_Object arguments, Lisp_Object buffer) +{ + //should work a bit like "make-button"(make-button BEG END &rest PROPERTIES) + // arg "type" and fwd should be keyword args eventually + //(make-xwidget 3 3 'button "oei" 31 31 nil) + //(xwidget-info (car xwidget-list)) + struct xwidget *xw = allocate_xwidget (); + Lisp_Object val; + xw->type = type; + xw->title = title; + if (NILP (buffer)) + buffer = Fcurrent_buffer (); // no need to gcpro because + // Fcurrent_buffer doesn't + // call Feval/eval_sub. + else + buffer = Fget_buffer_create (buffer); + xw->buffer = buffer; + + xw->height = XFASTINT (height); + xw->width = XFASTINT (width); + xw->kill_without_query = 0; + XSETXWIDGET (val, xw); // set the vectorlike_header of VAL + // with the correct value + Vxwidget_list = Fcons (val, Vxwidget_list); + xw->widgetwindow_osr = NULL; + xw->widget_osr = NULL; + xw->plist = Qnil; + + + if (EQ (xw->type, Qwebkit_osr)) + { + block_input (); + xw->widgetwindow_osr = gtk_offscreen_window_new (); + gtk_window_resize (GTK_WINDOW (xw->widgetwindow_osr), xw->width, + xw->height); + xw->widgetscrolledwindow_osr = NULL; //webkit osr is the + //only scrolled + //component atm + + if (EQ (xw->type, Qwebkit_osr)) + { + xw->widgetscrolledwindow_osr = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW + (xw-> + widgetscrolledwindow_osr), + xw->height); + gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW + (xw-> + widgetscrolledwindow_osr), + xw->width); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW + (xw->widgetscrolledwindow_osr), + GTK_POLICY_ALWAYS, + GTK_POLICY_ALWAYS); + + xw->widget_osr = webkit_web_view_new (); + gtk_container_add (GTK_CONTAINER (xw->widgetscrolledwindow_osr), + GTK_WIDGET (WEBKIT_WEB_VIEW (xw->widget_osr))); + } + + gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, + xw->height); + + if (EQ (xw->type, Qwebkit_osr)) + { + gtk_container_add (GTK_CONTAINER (xw->widgetwindow_osr), + xw->widgetscrolledwindow_osr); + } + else + { + gtk_container_add (GTK_CONTAINER (xw->widgetwindow_osr), + xw->widget_osr); + } + + gtk_widget_show (xw->widget_osr); + gtk_widget_show (xw->widgetwindow_osr); + gtk_widget_show (xw->widgetscrolledwindow_osr); + + /* store some xwidget data in the gtk widgets for convenient + retrieval in the event handlers. */ + g_object_set_data (G_OBJECT (xw->widget_osr), XG_XWIDGET, + (gpointer) (xw)); + g_object_set_data (G_OBJECT (xw->widgetwindow_osr), XG_XWIDGET, + (gpointer) (xw)); + + /* signals */ + if (EQ (xw->type, Qwebkit_osr)) + { + g_signal_connect (G_OBJECT (xw->widget_osr), + "document-load-finished", + G_CALLBACK + (webkit_document_load_finished_cb), xw); + + g_signal_connect (G_OBJECT (xw->widget_osr), + "download-requested", + G_CALLBACK (webkit_download_cb), xw); + + g_signal_connect (G_OBJECT (xw->widget_osr), + "mime-type-policy-decision-requested", + G_CALLBACK + (webkit_mime_type_policy_typedecision_requested_cb), + xw); + + g_signal_connect (G_OBJECT (xw->widget_osr), + "new-window-policy-decision-requested", + G_CALLBACK + (webkit_new_window_policy_decision_requested_cb), + xw); + + g_signal_connect (G_OBJECT (xw->widget_osr), + "navigation-policy-decision-requested", + G_CALLBACK + (webkit_navigation_policy_decision_requested_cb), + xw); + } + + unblock_input (); + + } + + return val; +} + +DEFUN ("get-buffer-xwidgets", Fget_buffer_xwidgets, Sget_buffer_xwidgets, + 1, 1, 0, + doc: /* Return a list of xwidgets associated with BUFFER. +BUFFER may be a buffer or the name of one. */) + (Lisp_Object buffer) +{ + Lisp_Object xw, tail, xw_list; + + if (NILP (buffer)) + return Qnil; + buffer = Fget_buffer (buffer); + if (NILP (buffer)) + return Qnil; + + xw_list = Qnil; + + for (tail = Vxwidget_list; CONSP (tail); tail = XCDR (tail)) + { + xw = XCAR (tail); + if (XWIDGETP (xw) && EQ (Fxwidget_buffer (xw), buffer)) + xw_list = Fcons (xw, xw_list); + } + return xw_list; +} + +static int +xwidget_hidden (struct xwidget_view *xv) +{ + return xv->hidden; +} + + + +static void +xwidget_show_view (struct xwidget_view *xv) +{ + xv->hidden = 0; + gtk_widget_show (xv->widgetwindow); + gtk_fixed_move (GTK_FIXED (xv->emacswindow), + xv->widgetwindow, + xv->x + xv->clip_left, + xv->y + xv->clip_top); +} + + +/* Hide an xvidget view. */ +static void +xwidget_hide_view (struct xwidget_view *xv) +{ + xv->hidden = 1; + gtk_fixed_move (GTK_FIXED (xv->emacswindow), xv->widgetwindow, + 10000, 10000); +} + + + +/* When the off-screen webkit master view changes this signal is called. + It copies the bitmap from the off-screen instance. */ +gboolean +offscreen_damage_event (GtkWidget * widget, GdkEvent * event, + gpointer xv_widget) +{ + // Queue a redraw of onscreen widget. + // There is a guard against receiving an invalid widget, + // which should only happen if we failed to remove the + // specific signal handler for the damage event. + if (GTK_IS_WIDGET (xv_widget)) + gtk_widget_queue_draw (GTK_WIDGET (xv_widget)); + else + printf ("Warning, offscreen_damage_event received invalid xv pointer:%p\n", + (void *) xv_widget); + + return FALSE; +} + +static void +store_xwidget_event_string (struct xwidget *xw, const char *eventname, + const char *eventstr) +{ + struct input_event event; + Lisp_Object xwl; + XSETXWIDGET (xwl, xw); + EVENT_INIT (event); + event.kind = XWIDGET_EVENT; + event.frame_or_window = Qnil; + + event.arg = Qnil; + event.arg = Fcons (build_string (eventstr), event.arg); + event.arg = Fcons (xwl, event.arg); + event.arg = Fcons (intern (eventname), event.arg); + kbd_buffer_store_event (&event); + +} + +//TODO deprecated, use load-status +void +webkit_document_load_finished_cb (WebKitWebView * webkitwebview, + WebKitWebFrame * arg1, + gpointer data) +{ + struct xwidget *xw = + (struct xwidget *) g_object_get_data (G_OBJECT (webkitwebview), + XG_XWIDGET); + + store_xwidget_event_string (xw, "document-load-finished", ""); +} + +gboolean +webkit_download_cb (WebKitWebView * webkitwebview, + WebKitDownload * arg1, + gpointer data) +{ + struct xwidget *xw = + (struct xwidget *) g_object_get_data (G_OBJECT (webkitwebview), + XG_XWIDGET); + store_xwidget_event_string (xw, "download-requested", + webkit_download_get_uri (arg1)); + + return FALSE; +} + +gboolean +webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *webView, + WebKitWebFrame *frame, + WebKitNetworkRequest * request, + gchar * mimetype, + WebKitWebPolicyDecision *policy_decision, + gpointer user_data) +{ + // This function makes webkit send a download signal for all unknown + // mime types. TODO Defer the decision to lisp, so that its possible + // to make Emacs handle teext mime for instance.xs + if (!webkit_web_view_can_show_mime_type (webView, mimetype)) + { + webkit_web_policy_decision_download (policy_decision); + return TRUE; + } + else + { + return FALSE; + } +} + + +gboolean +webkit_new_window_policy_decision_requested_cb (WebKitWebView *webView, + WebKitWebFrame *frame, + WebKitNetworkRequest *request, + WebKitWebNavigationAction *navigation_action, + WebKitWebPolicyDecision *policy_decision, + gpointer user_data) +{ + struct xwidget *xw = + (struct xwidget *) g_object_get_data (G_OBJECT (webView), XG_XWIDGET); + webkit_web_navigation_action_get_original_uri (navigation_action); + + store_xwidget_event_string (xw, "new-window-policy-decision-requested", + webkit_web_navigation_action_get_original_uri + (navigation_action)); + return FALSE; +} + +gboolean +webkit_navigation_policy_decision_requested_cb (WebKitWebView *webView, + WebKitWebFrame *frame, + WebKitNetworkRequest *request, + WebKitWebNavigationAction *navigation_action, + WebKitWebPolicyDecision * policy_decision, + gpointer user_data) +{ + struct xwidget *xw = + (struct xwidget *) g_object_get_data (G_OBJECT (webView), XG_XWIDGET); + store_xwidget_event_string (xw, "navigation-policy-decision-requested", + webkit_web_navigation_action_get_original_uri + (navigation_action)); + return FALSE; +} + +// For gtk3 offscreen rendered widgets. +static gboolean +xwidget_osr_draw_cb (GtkWidget * widget, cairo_t * cr, gpointer data) +{ + struct xwidget *xw = + (struct xwidget *) g_object_get_data (G_OBJECT (widget), XG_XWIDGET); + struct xwidget_view *xv = + (struct xwidget_view *) g_object_get_data (G_OBJECT (widget), + XG_XWIDGET_VIEW); + + cairo_rectangle (cr, 0, 0, xv->clip_right, xv->clip_bottom); + cairo_clip (cr); + + if (xw->widgetscrolledwindow_osr != NULL) + gtk_widget_draw (xw->widgetscrolledwindow_osr, cr); + else + gtk_widget_draw (xw->widget_osr, cr); + return FALSE; +} + +static gboolean +xwidget_osr_event_forward (GtkWidget * widget, + GdkEvent * event, + gpointer user_data) +{ + /* Copy events that arrive at the outer widget to the offscreen widget. */ + struct xwidget *xw = + (struct xwidget *) g_object_get_data (G_OBJECT (widget), XG_XWIDGET); + GdkEvent *eventcopy = gdk_event_copy (event); + eventcopy->any.window = gtk_widget_get_window (xw->widget_osr); + + //TODO This might leak events. They should be deallocated later, + //perhaps in xwgir_event_cb + gtk_main_do_event (eventcopy); + return TRUE; //dont propagate this event furter +} + + +static gboolean +xwidget_osr_event_set_embedder (GtkWidget * widget, + GdkEvent * event, gpointer data) +{ + struct xwidget_view *xv = (struct xwidget_view *) data; + struct xwidget *xww = XXWIDGET (xv->model); + gdk_offscreen_window_set_embedder (gtk_widget_get_window + (xww->widgetwindow_osr), + gtk_widget_get_window (xv->widget)); + return FALSE; +} + + +/* Initializes and does initial placement of an xwidget view on screen. */ +static struct xwidget_view * +xwidget_init_view (struct xwidget *xww, + struct glyph_string *s, + int x, int y) +{ + struct xwidget_view *xv = allocate_xwidget_view (); + Lisp_Object val; + + XSETXWIDGET_VIEW (val, xv); + Vxwidget_view_list = Fcons (val, Vxwidget_view_list); + + XSETWINDOW (xv->w, s->w); + XSETXWIDGET (xv->model, xww); + + if (EQ (xww->type, Qwebkit_osr)) + { + xv->widget = gtk_drawing_area_new (); + // Expose event handling. + gtk_widget_set_app_paintable (xv->widget, TRUE); + gtk_widget_add_events (xv->widget, GDK_ALL_EVENTS_MASK); + + /* Draw the view on damage-event */ + g_signal_connect (G_OBJECT (xww->widgetwindow_osr), "damage-event", + G_CALLBACK (offscreen_damage_event), xv->widget); + + if (EQ (xww->type, Qwebkit_osr)) + { + g_signal_connect (G_OBJECT (xv->widget), "button-press-event", + G_CALLBACK (xwidget_osr_event_forward), NULL); + g_signal_connect (G_OBJECT (xv->widget), "button-release-event", + G_CALLBACK (xwidget_osr_event_forward), NULL); + g_signal_connect (G_OBJECT (xv->widget), "motion-notify-event", + G_CALLBACK (xwidget_osr_event_forward), NULL); + } + else + { + // xwgir debug , orthogonal to forwarding + g_signal_connect (G_OBJECT (xv->widget), "enter-notify-event", + G_CALLBACK (xwidget_osr_event_set_embedder), xv); + } + g_signal_connect (G_OBJECT (xv->widget), "draw", + G_CALLBACK (xwidget_osr_draw_cb), NULL); + } + // Widget realization. + + // Make container widget 1st, and put the actual widget inside the + // container later. Drawing should crop container window if necessary + // to handle case where xwidget is partially obscured by other Emacs + // windows. Other containers than gtk_fixed where explored, but + // gtk_fixed had the most predictable behaviour so far. + xv->emacswindow = FRAME_GTK_WIDGET (s->f); + xv->widgetwindow = gtk_fixed_new (); + gtk_widget_set_has_window (xv->widgetwindow, TRUE); + gtk_container_add (GTK_CONTAINER (xv->widgetwindow), xv->widget); + + // Store some xwidget data in the gtk widgets. + // The emacs frame. + g_object_set_data (G_OBJECT (xv->widget), XG_FRAME_DATA, (gpointer) (s->f)); + // The xwidget. + g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET, (gpointer) (xww)); + // The xwidget. + g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET_VIEW, (gpointer) (xv)); + // The xwidget window. + g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET, (gpointer) (xww)); + // the xwidget view. + g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET_VIEW, + (gpointer) (xv)); + + + gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xww->width, + xww->height); + gtk_widget_set_size_request (xv->widgetwindow, xww->width, xww->height); + gtk_fixed_put (GTK_FIXED (FRAME_GTK_WIDGET (s->f)), xv->widgetwindow, x, y); + xv->x = x; + xv->y = y; + gtk_widget_show_all (xv->widgetwindow); + + + return xv; +} + + +void +x_draw_xwidget_glyph_string (struct glyph_string *s) +{ + /* This method is called by the redisplay engine and places the + xwidget on screen. Moving and clipping is done here. Also view + initialization. + */ + struct xwidget *xww = s->xwidget; + struct xwidget_view *xv = xwidget_view_lookup (xww, s->w); + int clip_right; + int clip_bottom; + int clip_top; + int clip_left; + + int x = s->x; + int y = s->y + (s->height / 2) - (xww->height / 2); + int moved = 0; + + /* We do initialization here in the display loop because there is no + other time to know things like window placement etc. + */ + xv = xwidget_init_view (xww, s, x, y); + + // Calculate clipping, which is used for all manner of onscreen + // xwidget views. Each widget border can get clipped by other emacs + // objects so there are four clipping variables. + clip_right = + min (xww->width, + WINDOW_RIGHT_EDGE_X (s->w) - x - + WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w) - + WINDOW_RIGHT_FRINGE_WIDTH (s->w)); + clip_left = + max (0, + WINDOW_LEFT_EDGE_X (s->w) - x + + WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (s->w) + + WINDOW_LEFT_FRINGE_WIDTH (s->w)); + + clip_bottom = + min (xww->height, + WINDOW_BOTTOM_EDGE_Y (s->w) - WINDOW_MODE_LINE_HEIGHT (s->w) - y); + clip_top = max (0, WINDOW_TOP_EDGE_Y (s->w) - y); + + // We are conserned with movement of the onscreen area. The area + // might sit still when the widget actually moves. This happens + // when an Emacs window border moves across a widget window. So, if + // any corner of the outer widget clipping window moves, that counts + // as movement here, even if it looks like no movement happens + // because the widget sits still inside the clipping area. The + // widget can also move inside the clipping area, which happens + // later + moved = (xv->x + xv->clip_left != x + clip_left) + || ((xv->y + xv->clip_top) != (y + clip_top)); + xv->x = x; + xv->y = y; + if (moved) // Has it moved? + { + gtk_fixed_move (GTK_FIXED (FRAME_GTK_WIDGET (s->f)), + xv->widgetwindow, x + clip_left, y + clip_top); + } + // Clip the widget window if some parts happen to be outside + // drawable area. An Emacs window is not a gtk window. A gtk window + // covers the entire frame. Clipping might have changed even if we + // havent actualy moved, we try figure out when we need to reclip + // for real. + if ((xv->clip_right != clip_right) + || (xv->clip_bottom != clip_bottom) + || (xv->clip_top != clip_top) || (xv->clip_left != clip_left)) + { + gtk_widget_set_size_request (xv->widgetwindow, clip_right + clip_left, + clip_bottom + clip_top); + gtk_fixed_move (GTK_FIXED (xv->widgetwindow), xv->widget, -clip_left, + -clip_top); + + xv->clip_right = clip_right; + xv->clip_bottom = clip_bottom; + xv->clip_top = clip_top; + xv->clip_left = clip_left; + } + // If emacs wants to repaint the area where the widget lives, queue + // a redraw. It seems its possible to get out of sync with emacs + // redraws so emacs background sometimes shows up instead of the + // xwidgets background. It's just a visual glitch though. + if (!xwidget_hidden (xv)) + { + gtk_widget_queue_draw (xv->widgetwindow); + gtk_widget_queue_draw (xv->widget); + } +} + + +// Macro that checks WEBKIT_IS_WEB_VIEW(xw->widget_osr) first +#define WEBKIT_FN_INIT() \ + struct xwidget* xw; \ + CHECK_XWIDGET (xwidget); \ + if (NILP (xwidget)) {printf("ERROR xwidget nil\n"); return Qnil;}; \ + xw = XXWIDGET (xwidget); \ + if (NULL == xw) printf("ERROR xw is 0\n"); \ + if ((NULL == xw->widget_osr) || !WEBKIT_IS_WEB_VIEW(xw->widget_osr)){ \ + printf ("ERROR xw->widget_osr does not hold a webkit instance\n");\ + return Qnil;\ + }; + + +DEFUN ("xwidget-webkit-goto-uri", + Fxwidget_webkit_goto_uri, Sxwidget_webkit_goto_uri, + 2, 2, 0, + doc: /* Make the xwidget webkit instance referenced by XWIDGET +browse URI. */) + (Lisp_Object xwidget, Lisp_Object uri) +{ + WEBKIT_FN_INIT (); + CHECK_STRING (uri); + webkit_web_view_load_uri (WEBKIT_WEB_VIEW (xw->widget_osr), SSDATA (uri)); + return Qnil; +} + + +DEFUN ("xwidget-webkit-execute-script", + Fxwidget_webkit_execute_script, Sxwidget_webkit_execute_script, + 2, 2, 0, + doc: /* Make the Webkit XWIDGET execute javascript SCRIPT. */) + (Lisp_Object xwidget, Lisp_Object script) +{ + WEBKIT_FN_INIT (); + CHECK_STRING (script); + webkit_web_view_execute_script (WEBKIT_WEB_VIEW (xw->widget_osr), + SSDATA (script)); + return Qnil; +} + +DEFUN ("xwidget-webkit-get-title", + Fxwidget_webkit_get_title, Sxwidget_webkit_get_title, + 1, 1, 0, + doc: /* Returns the title from the Webkit instance in XWIDGET. +This can be used to work around the lack of a return value from the +exec method. */ ) + (Lisp_Object xwidget) +{ + // TODO support multibyte strings + WEBKIT_FN_INIT (); + const gchar *str = + webkit_web_view_get_title (WEBKIT_WEB_VIEW (xw->widget_osr)); + if (str == 0) + { + // TODO maybe return Qnil instead. I suppose webkit returns + // nullpointer when doc is not properly loaded or something + return build_string (""); + } + return build_string (str); +} + +DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 3, 3, 0, + doc: /* Resize XWIDGET. NEW_WIDTH NEW_HEIGHT defines the new +size. */ ) + (Lisp_Object xwidget, Lisp_Object new_width, Lisp_Object new_height) +{ + CHECK_XWIDGET (xwidget); + struct xwidget *xw = XXWIDGET (xwidget); + struct xwidget_view *xv; + int w, h; + + CHECK_NUMBER (new_width); + CHECK_NUMBER (new_height); + w = XFASTINT (new_width); + h = XFASTINT (new_height); + + xw->width = w; + xw->height = h; + // If there is a offscreen widget resize it 1st. + if (xw->widget_osr) + { + gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), + xw->width, xw->height); //minimum size + gtk_window_resize (GTK_WINDOW (xw->widgetwindow_osr), xw->width, + xw->height); + gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW + (xw-> + widgetscrolledwindow_osr), + xw->height); + gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW + (xw-> + widgetscrolledwindow_osr), + xw->width); + + gtk_container_resize_children (GTK_CONTAINER (xw->widgetwindow_osr)); + + } + + for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail)) + { + if (XWIDGET_VIEW_P (XCAR (tail))) + { + xv = XXWIDGET_VIEW (XCAR (tail)); + if (XXWIDGET (xv->model) == xw) + gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xw->width, + xw->height); + } + } + + return Qnil; +} + + + +DEFUN ("xwidget-set-adjustment", + Fxwidget_set_adjustment, Sxwidget_set_adjustment, 4, 4, 0, + doc: /* Set native scrolling for XWIDGET. AXIS can be 'vertical or +'horizontal. If RELATIVE is t, scroll relative, otherwise absolutely. +VALUE is the amount to scroll, either relatively or absolutely. */) + (Lisp_Object xwidget, Lisp_Object axis, Lisp_Object relative, + Lisp_Object value) +{ + CHECK_XWIDGET (xwidget); + struct xwidget *xw = XXWIDGET (xwidget); + GtkAdjustment *adjustment; + float final_value = 0.0; + + adjustment = + gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW + (xw->widgetscrolledwindow_osr)); + if (EQ (Qvertical, axis)) + { + adjustment = + gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW + (xw->widgetscrolledwindow_osr)); + } + if (EQ (Qhorizontal, axis)) + { + adjustment = + gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW + (xw->widgetscrolledwindow_osr)); + } + + if (EQ (Qt, relative)) + { + final_value = gtk_adjustment_get_value (adjustment) + XFASTINT (value); + } + else + { + final_value = 0.0 + XFASTINT (value); + } + + gtk_adjustment_set_value (adjustment, final_value); + + return Qnil; +} + + +DEFUN ("xwidget-size-request", + Fxwidget_size_request, Sxwidget_size_request, + 1, 1, 0, + doc: /* Return the desired size of the XWIDGET. + +This can be used to read the xwidget desired size, and resizes the +Emacs allocated area accordingly. */) + (Lisp_Object xwidget) +{ + CHECK_XWIDGET (xwidget); + GtkRequisition requisition; + Lisp_Object rv; + gtk_widget_size_request (XXWIDGET (xwidget)->widget_osr, &requisition); + rv = Qnil; + rv = Fcons (make_number (requisition.height), rv); + rv = Fcons (make_number (requisition.width), rv); + return rv; + +} + +DEFUN ("xwidgetp", + Fxwidgetp, Sxwidgetp, + 1, 1, 0, + doc: /* Return t if OBJECT is a xwidget. */) + (Lisp_Object object) +{ + return XWIDGETP (object) ? Qt : Qnil; +} + +DEFUN ("xwidget-view-p", + Fxwidget_view_p, Sxwidget_view_p, + 1, 1, 0, + doc: /* Return t if OBJECT is a xwidget-view. */) + (Lisp_Object object) +{ + return XWIDGET_VIEW_P (object) ? Qt : Qnil; +} + +DEFUN ("xwidget-info", + Fxwidget_info, Sxwidget_info, + 1, 1, 0, + doc: /* Return XWIDGET properties in a vector. Currently [TYPE +TITLE WIDTH HEIGHT]. */) + (Lisp_Object xwidget) +{ + CHECK_XWIDGET (xwidget); + Lisp_Object info, n; + struct xwidget *xw = XXWIDGET (xwidget); + + info = Fmake_vector (make_number (4), Qnil); + ASET (info, 0, xw->type); + ASET (info, 1, xw->title); + XSETFASTINT (n, xw->width); + ASET (info, 2, n); + XSETFASTINT (n, xw->height); + ASET (info, 3, n); + + return info; +} + +DEFUN ("xwidget-view-info", + Fxwidget_view_info, Sxwidget_view_info, + 1, 1, 0, + doc: /* Return properties of XWIDGET-VIEW in a vector. +Currently [X Y CLIP_RIGHT CLIP_BOTTOM CLIP_TOP CLIP_LEFT] */) + (Lisp_Object xwidget_view) +{ + CHECK_XWIDGET_VIEW (xwidget_view); + struct xwidget_view *xv = XXWIDGET_VIEW (xwidget_view); + Lisp_Object info; + + info = Fmake_vector (make_number (6), Qnil); + ASET (info, 0, make_number (xv->x)); + ASET (info, 1, make_number (xv->y)); + ASET (info, 2, make_number (xv->clip_right)); + ASET (info, 3, make_number (xv->clip_bottom)); + ASET (info, 4, make_number (xv->clip_top)); + ASET (info, 5, make_number (xv->clip_left)); + + return info; +} + +DEFUN ("xwidget-view-model", + Fxwidget_view_model, Sxwidget_view_model, + 1, 1, 0, + doc: /* Return the model associated with XWIDGET-VIEW. */) + (Lisp_Object xwidget_view) +{ + CHECK_XWIDGET_VIEW (xwidget_view); + return XXWIDGET_VIEW (xwidget_view)->model; +} + +DEFUN ("xwidget-view-window", + Fxwidget_view_window, Sxwidget_view_window, + 1, 1, 0, + doc: /* Return the window of XWIDGET-VIEW. */) + (Lisp_Object xwidget_view) +{ + CHECK_XWIDGET_VIEW (xwidget_view); + return XXWIDGET_VIEW (xwidget_view)->w; +} + + +DEFUN ("delete-xwidget-view", + Fdelete_xwidget_view, Sdelete_xwidget_view, + 1, 1, 0, + doc: /* Delete the XWIDGET-VIEW. */) + (Lisp_Object xwidget_view) +{ + CHECK_XWIDGET_VIEW (xwidget_view); + struct xwidget_view *xv = XXWIDGET_VIEW (xwidget_view); + gtk_widget_destroy (xv->widgetwindow); + Vxwidget_view_list = Fdelq (xwidget_view, Vxwidget_view_list); + // xv->model still has signals pointing to the view. There can be + // several views. Find the matching signals and delete them all. + g_signal_handlers_disconnect_matched (XXWIDGET (xv->model)->widgetwindow_osr, + G_SIGNAL_MATCH_DATA, + 0, 0, 0, 0, + xv->widget); + return Qnil; +} + +DEFUN ("xwidget-view-lookup", + Fxwidget_view_lookup, Sxwidget_view_lookup, + 1, 2, 0, + doc: /* Return the xwidget-view associated with XWIDGET in +WINDOW if specified, otherwise it uses the selected window. Return nil +if no association is found. */) + (Lisp_Object xwidget, Lisp_Object window) +{ + CHECK_XWIDGET (xwidget); + + if (NILP (window)) + window = Fselected_window (); + CHECK_WINDOW (window); + + for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); + tail = XCDR (tail)) + { + Lisp_Object xwidget_view = XCAR (tail); + if (EQ (Fxwidget_view_model (xwidget_view), xwidget) + && EQ (Fxwidget_view_window (xwidget_view), window)) + return xwidget_view; + } + + return Qnil; +} + +DEFUN ("xwidget-plist", + Fxwidget_plist, Sxwidget_plist, + 1, 1, 0, + doc: /* Return the plist of XWIDGET. */) + (register Lisp_Object xwidget) +{ + CHECK_XWIDGET (xwidget); + return XXWIDGET (xwidget)->plist; +} + +DEFUN ("xwidget-buffer", + Fxwidget_buffer, Sxwidget_buffer, + 1, 1, 0, + doc: /* Return the buffer of XWIDGET. */) + (register Lisp_Object xwidget) +{ + CHECK_XWIDGET (xwidget); + return XXWIDGET (xwidget)->buffer; +} + +DEFUN ("set-xwidget-plist", + Fset_xwidget_plist, Sset_xwidget_plist, + 2, 2, 0, + doc: /* Replace the plist of XWIDGET with PLIST. +Returns PLIST. */) + (register Lisp_Object xwidget, Lisp_Object plist) +{ + CHECK_XWIDGET (xwidget); + CHECK_LIST (plist); + + XXWIDGET (xwidget)->plist = plist; + return plist; +} + +DEFUN ("set-xwidget-query-on-exit-flag", + Fset_xwidget_query_on_exit_flag, Sset_xwidget_query_on_exit_flag, + 2, 2, 0, + doc: /* Specify if query is needed for XWIDGET when +Emacs is exited. If the second argument FLAG is non-nil, Emacs will +queries the user before exiting or killing a buffer if XWIDGET is +running. This function returns FLAG. */) + (Lisp_Object xwidget, Lisp_Object flag) +{ + CHECK_XWIDGET (xwidget); + XXWIDGET (xwidget)->kill_without_query = NILP (flag); + return flag; +} + +DEFUN ("xwidget-query-on-exit-flag", + Fxwidget_query_on_exit_flag, Sxwidget_query_on_exit_flag, + 1, 1, 0, + doc: /* Return the current value of query-on-exit +flag for XWIDGET. */) + (Lisp_Object xwidget) +{ + CHECK_XWIDGET (xwidget); + return (XXWIDGET (xwidget)->kill_without_query ? Qnil : Qt); +} + +void +syms_of_xwidget (void) +{ + + defsubr (&Smake_xwidget); + defsubr (&Sxwidgetp); + DEFSYM (Qxwidgetp, "xwidgetp"); + defsubr (&Sxwidget_view_p); + DEFSYM (Qxwidget_view_p, "xwidget-view-p"); + defsubr (&Sxwidget_info); + defsubr (&Sxwidget_view_info); + defsubr (&Sxwidget_resize); + defsubr (&Sget_buffer_xwidgets); + defsubr (&Sxwidget_view_model); + defsubr (&Sxwidget_view_window); + defsubr (&Sxwidget_view_lookup); + defsubr (&Sxwidget_query_on_exit_flag); + defsubr (&Sset_xwidget_query_on_exit_flag); + +#ifdef HAVE_WEBKIT_OSR + defsubr (&Sxwidget_webkit_goto_uri); + defsubr (&Sxwidget_webkit_execute_script); + defsubr (&Sxwidget_webkit_get_title); + DEFSYM (Qwebkit_osr, "webkit-osr"); +#endif + + defsubr (&Sxwidget_size_request); + defsubr (&Sdelete_xwidget_view); + + defsubr (&Sxwidget_plist); + defsubr (&Sxwidget_buffer); + defsubr (&Sset_xwidget_plist); + + defsubr (&Sxwidget_set_adjustment); + + DEFSYM (Qxwidget, "xwidget"); + + DEFSYM (QCxwidget, ":xwidget"); + DEFSYM (QCtitle, ":title"); + + /* Do not forget to update the docstring of make-xwidget if you add + new types. */ + + DEFSYM (Qvertical, "vertical"); + DEFSYM (Qhorizontal, "horizontal"); + + DEFSYM (QCplist, ":plist"); + + DEFVAR_LISP ("xwidget-list", Vxwidget_list, + doc: /* xwidgets list. */); + Vxwidget_list = Qnil; + + DEFVAR_LISP ("xwidget-view-list", Vxwidget_view_list, + doc: /* xwidget views list. */); + Vxwidget_view_list = Qnil; + + Fprovide (intern ("xwidget-internal"), Qnil); + +} + + +/* Value is non-zero if OBJECT is a valid Lisp xwidget specification. A + valid xwidget specification is a list whose car is the symbol + `xwidget', and whose rest is a property list. The property list must + contain a value for key `:type'. That value must be the name of a + supported xwidget type. The rest of the property list depends on the + xwidget type. */ + +bool +valid_xwidget_spec_p (Lisp_Object object) +{ + int valid_p = false; + + if (CONSP (object) && EQ (XCAR (object), Qxwidget)) + valid_p = true; + + return valid_p; +} + + + +/* Find a value associated with key in spec. */ +Lisp_Object +xwidget_spec_value (Lisp_Object spec, Lisp_Object key, int *found) +{ + Lisp_Object tail; + + eassert (valid_xwidget_spec_p (spec)); + + for (tail = XCDR (spec); + CONSP (tail) && CONSP (XCDR (tail)); tail = XCDR (XCDR (tail))) + { + if (EQ (XCAR (tail), key)) + { + if (found) + *found = 1; + return XCAR (XCDR (tail)); + } + } + + if (found) + *found = 0; + return Qnil; +} + + +void +xwidget_view_delete_all_in_window (struct window *w) +{ + struct xwidget_view *xv = NULL; + for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); + tail = XCDR (tail)) + { + if (XWIDGET_VIEW_P (XCAR (tail))) + { + xv = XXWIDGET_VIEW (XCAR (tail)); + if (XWINDOW (xv->w) == w) + { + Fdelete_xwidget_view (XCAR (tail)); + } + } + } +} + +struct xwidget_view * +xwidget_view_lookup (struct xwidget *xw, struct window *w) +{ + Lisp_Object xwidget, window, ret; + XSETXWIDGET (xwidget, xw); + XSETWINDOW (window, w); + + ret = Fxwidget_view_lookup (xwidget, window); + + return EQ (ret, Qnil) ? NULL : XXWIDGET_VIEW (ret); +} + +struct xwidget * +lookup_xwidget (Lisp_Object spec) +{ + /* When a xwidget lisp spec is found initialize the C struct that is + used in the C code. This is done by redisplay so values change + if the spec changes. So, take special care of one-shot events. + */ + int found = 0; + Lisp_Object value; + struct xwidget *xw; + + value = xwidget_spec_value (spec, QCxwidget, &found); + xw = XXWIDGET (value); + + return xw; +} + +/* Set up detection of touched xwidget*/ +void +xwidget_start_redisplay (void) +{ + for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); + tail = XCDR (tail)) + { + if (XWIDGET_VIEW_P (XCAR (tail))) + XXWIDGET_VIEW (XCAR (tail))->redisplayed = 0; + } +} + +/* The xwidget was touched during redisplay, so it isn't a candidate + for hiding. */ +void +xwidget_touch (struct xwidget_view *xv) +{ + xv->redisplayed = 1; +} + +static int +xwidget_touched (struct xwidget_view *xv) +{ + return xv->redisplayed; +} + +/* Redisplay has ended, now we should hide untouched xwidgets +*/ +void +xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix) +{ + + int i; + int area; + + xwidget_start_redisplay (); + // Iterate desired glyph matrix of window here, hide gtk widgets + // not in the desired matrix. + + // This only takes care of xwidgets in active windows. if a window + // goes away from screen xwidget views wust be deleted + + // dump_glyph_matrix (matrix, 2); + for (i = 0; i < matrix->nrows; ++i) + { + // dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs); + struct glyph_row *row; + row = MATRIX_ROW (matrix, i); + if (row->enabled_p != 0) + { + for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area) + { + struct glyph *glyph = row->glyphs[area]; + struct glyph *glyph_end = glyph + row->used[area]; + for (; glyph < glyph_end; ++glyph) + { + if (glyph->type == XWIDGET_GLYPH) + { + /* + The only call to xwidget_end_redisplay is in dispnew + xwidget_end_redisplay (w->current_matrix); + */ + xwidget_touch (xwidget_view_lookup (glyph->u.xwidget, + w)); + } + } + } + } + } + + for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); + tail = XCDR (tail)) + { + if (XWIDGET_VIEW_P (XCAR (tail))) + { + struct xwidget_view *xv = XXWIDGET_VIEW (XCAR (tail)); + + // "touched" is only meaningful for the current window, so + // disregard other views. + if (XWINDOW (xv->w) == w) + { + if (xwidget_touched (xv)) + xwidget_show_view (xv); + else + xwidget_hide_view (xv); + } + } + } +} + +/* Kill all xwidget in BUFFER. */ +void +kill_buffer_xwidgets (Lisp_Object buffer) +{ + Lisp_Object tail, xwidget; + for (tail = Fget_buffer_xwidgets (buffer); CONSP (tail); tail = XCDR (tail)) + { + xwidget = XCAR (tail); + Vxwidget_list = Fdelq (xwidget, Vxwidget_list); + /* TODO free the GTK things in xw */ + { + CHECK_XWIDGET (xwidget); + struct xwidget *xw = XXWIDGET (xwidget); + if (xw->widget_osr && xw->widgetwindow_osr) + { + gtk_widget_destroy (xw->widget_osr); + gtk_widget_destroy (xw->widgetwindow_osr); + } + } + } +} diff --git a/src/xwidget.h b/src/xwidget.h new file mode 100644 index 00000000000..493000c34fd --- /dev/null +++ b/src/xwidget.h @@ -0,0 +1,135 @@ +/* Support for embedding graphical components in a buffer. + +Copyright (C) 2011-2015 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Emacs. If not, see . */ + +#ifndef XWIDGET_H_INCLUDED +#define XWIDGET_H_INCLUDED + +void x_draw_xwidget_glyph_string (struct glyph_string *s); +void syms_of_xwidget (void); + +//extern Lisp_Object Qxwidget; + + +bool valid_xwidget_spec_p (Lisp_Object object); + +#include + + +/* +each xwidget instance/model is described by this struct. + +lisp pseudovector. + + + */ +struct xwidget +{ + struct vectorlike_header header; + Lisp_Object plist; //auxilliary data + Lisp_Object type; //the widget type + Lisp_Object buffer; //buffer where xwidget lives + Lisp_Object title; //a title that is used for button labels for instance + + //here ends the lisp part. + //"height" is the marker field + int height; + int width; + + //for offscreen widgets, unused if not osr + GtkWidget *widget_osr; + GtkWidget *widgetwindow_osr; + //this is used if the widget (webkit) is to be wrapped in a scrolled window, + GtkWidget *widgetscrolledwindow_osr; + /* Non-nil means kill silently if Emacs is exited. */ + unsigned int kill_without_query:1; + +}; + + +//struct for each xwidget view +struct xwidget_view +{ + struct vectorlike_header header; + Lisp_Object model; + Lisp_Object w; + + //here ends the lisp part. + //"redisplayed" is the marker field + int redisplayed; //if touched by redisplay + + int hidden; //if the "live" instance isnt drawn + + GtkWidget *widget; + GtkWidget *widgetwindow; + GtkWidget *emacswindow; + int x; + int y; + int clip_right; + int clip_bottom; + int clip_top; + int clip_left; + + + long handler_id; +}; + +/* Test for xwidget pseudovector*/ +#define XWIDGETP(x) PSEUDOVECTORP (x, PVEC_XWIDGET) +#define XXWIDGET(a) (eassert (XWIDGETP(a)), \ + (struct xwidget *) XUNTAG(a, Lisp_Vectorlike)) + +#define CHECK_XWIDGET(x) \ + CHECK_TYPE (XWIDGETP (x), Qxwidgetp, x) + +/* Test for xwidget_view pseudovector */ +#define XWIDGET_VIEW_P(x) PSEUDOVECTORP (x, PVEC_XWIDGET_VIEW) +#define XXWIDGET_VIEW(a) (eassert (XWIDGET_VIEW_P(a)), \ + (struct xwidget_view *) XUNTAG(a, Lisp_Vectorlike)) + +#define CHECK_XWIDGET_VIEW(x) \ + CHECK_TYPE (XWIDGET_VIEW_P (x), Qxwidget_view_p, x) + +struct xwidget_type +{ + /* A symbol uniquely identifying the xwidget type, */ + Lisp_Object *type; + + /* Check that SPEC is a valid image specification for the given + image type. Value is non-zero if SPEC is valid. */ + int (*valid_p) (Lisp_Object spec); + + /* Next in list of all supported image types. */ + struct xwidget_type *next; +}; + + +struct xwidget *xwidget_from_id (int id); + +void xwidget_start_redisplay (void); +void xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix); + +void xwidget_touch (struct xwidget_view *xw); + +struct xwidget *lookup_xwidget (Lisp_Object spec); +#define XG_XWIDGET "emacs_xwidget" +#define XG_XWIDGET_VIEW "emacs_xwidget_view" +void xwidget_view_delete_all_in_window (struct window *w); + +void kill_buffer_xwidgets (Lisp_Object buffer); +#endif /* XWIDGET_H_INCLUDED */ From c7441cd7d8befe1f79ed3509c4a2202a01314336 Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Tue, 19 Jan 2016 16:00:34 -0500 Subject: [PATCH 09/36] ; Add 2016 to copyright years of new files. --- lisp/xwidget.el | 2 +- src/xwidget.c | 2 +- src/xwidget.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lisp/xwidget.el b/lisp/xwidget.el index ce6d939dd3b..9c38c8e84ca 100644 --- a/lisp/xwidget.el +++ b/lisp/xwidget.el @@ -1,6 +1,6 @@ ;;; xwidget.el --- api functions for xwidgets -*- lexical-binding: t -*- ;; -;; Copyright (C) 2011-2015 Free Software Foundation, Inc. +;; Copyright (C) 2011-2016 Free Software Foundation, Inc. ;; ;; Author: Joakim Verona (joakim@verona.se) ;; diff --git a/src/xwidget.c b/src/xwidget.c index 74319e1667d..1ed7eaae2a7 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -1,6 +1,6 @@ /* Support for embedding graphical components in a buffer. -Copyright (C) 2011-2015 Free Software Foundation, Inc. +Copyright (C) 2011-2016 Free Software Foundation, Inc. This file is part of GNU Emacs. diff --git a/src/xwidget.h b/src/xwidget.h index 493000c34fd..4dffaa4750d 100644 --- a/src/xwidget.h +++ b/src/xwidget.h @@ -1,6 +1,6 @@ /* Support for embedding graphical components in a buffer. -Copyright (C) 2011-2015 Free Software Foundation, Inc. +Copyright (C) 2011-2016 Free Software Foundation, Inc. This file is part of GNU Emacs. From 9d00392520abc4421f0a5992298f3cb8077c78b0 Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Tue, 19 Jan 2016 16:02:18 -0500 Subject: [PATCH 10/36] * lisp/xwidget.el (report-xwidget-bug): Remove. (top-level): No longer require reporter. --- lisp/xwidget.el | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/lisp/xwidget.el b/lisp/xwidget.el index 9c38c8e84ca..2472c8db93f 100644 --- a/lisp/xwidget.el +++ b/lisp/xwidget.el @@ -31,7 +31,6 @@ ;;; Code: (require 'cl-lib) -(require 'reporter) (require 'bookmark) (defcustom xwidget-webkit-scroll-behaviour 'native @@ -583,26 +582,6 @@ It can be retrieved with `(xwidget-get XWIDGET PROPNAME)'." (add-hook 'kill-buffer-query-functions 'xwidget-kill-buffer-query-function) -(defun report-xwidget-bug () - "Report a bug in GNU Emacs about the XWidget branch. -Prompts for bug subject. Leaves you in a mail buffer." - (interactive) - (let ((reporter-prompt-for-summary-p t)) - (reporter-submit-bug-report "submit@debbugs.gnu.org" nil nil nil nil - (format "Package: emacs-xwidgets - -Please describe exactly what actions triggered the bug, and the -precise symptoms of the bug. If you can, give a recipe starting -from `emacs -Q'. - -If Emacs crashed, and you have the Emacs process in the gdb -deubbger, please include the output from the following gdb -commands: - `bt full' and `xbacktrace'. - -For information about debugging Emacs, please read the file -%s" (expand-file-name "DEBUG" data-directory))))) - (provide 'xwidget) ;;; xwidget.el ends here From 406887f5ef286270a5b5d00523f2eaf449db4ced Mon Sep 17 00:00:00 2001 From: Katsumi Yamaoka Date: Tue, 19 Jan 2016 22:10:09 +0000 Subject: [PATCH 11/36] * lisp/gnus/nnir.el (nnir-request-update-mark): Default to the original mark. cf. and --- lisp/gnus/nnir.el | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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." (deffoo nnir-request-update-mark (group article mark) (let ((artgroup (nnir-article-group article)) (artnumber (nnir-article-number article))) - (when (and artgroup artnumber) - (gnus-request-update-mark artgroup artnumber mark)))) + (or (and artgroup + artnumber + (gnus-request-update-mark artgroup artnumber mark)) + mark))) (deffoo nnir-request-set-mark (group actions &optional server) (nnir-possibly-change-group group server) From 11a0300d9f48cd6245fdf3f8576cda58c4bafb8a Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Tue, 19 Jan 2016 17:32:23 -0500 Subject: [PATCH 12/36] ; * etc/NEWS: xwidgets isn't documented. --- etc/NEWS | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index db6e51dfd45..934bc3f0859 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -120,20 +120,19 @@ and can contain escape sequences for command keys, quotes, and the like. * Changes in Emacs 25.1 -+++ -** Xwidgets : A new feature for embedding native widgets -inside Emacs buffers. If you have gtk3 and webkit-devel installed, you -can access the embedded webkit browser with m-x -xwidget-webkit-browse-url. This will open a new buffer with the -embedded browser. The buffer will have a new mode, xwidget-webkit -mode which is similar to image mode, which supports the webkit widget. +** Xwidgets: a new feature for embedding native widgets inside Emacs buffers. +If you have gtk3 and webkit-devel installed, you can access the +embedded webkit browser with `M-x xwidget-webkit-browse-url'. This +opens a new buffer with the embedded browser. The buffer will +have a new mode, `xwidget-webkit-mode' (similar to `image-mode'), +which supports the webkit widget. *** New functions for xwidget-webkit mode `xwidget-webkit-insert-string', `xwidget-webkit-adjust-size-dispatch', `xwidget-webkit-back', `xwidget-webkit-browse-url', `xwidget-webkit-reload', `xwidget-webkit-current-url', `xwidget-webkit-scroll-backward', `xwidget-webkit-scroll-forward', `xwidget-webkit-scroll-down', -`xwidget-webkit-scroll-up', +`xwidget-webkit-scroll-up'. +++ ** Emacs can now load shared/dynamic libraries (modules). From 644e2fb73aa3968be573b2b1e0b491618f84d47b Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Tue, 19 Jan 2016 17:48:35 -0500 Subject: [PATCH 13/36] * configure.ac (HAVE_WEBKIT_OSR): Remove broken, duplicated gtk3 test. --- configure.ac | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index 95f79ab8d4f..d3513ff4759 100644 --- a/configure.ac +++ b/configure.ac @@ -374,7 +374,7 @@ otherwise for the first of 'inotify' or 'gfile' that is usable.]) [with_file_notification=$with_features]) OPTION_DEFAULT_OFF([xwidgets], - [enable use of some gtk widgets in Emacs buffers]) + [enable use of some gtk widgets in Emacs buffers (requires gtk3)]) ## For the times when you want to build Emacs but don't have ## a suitable makeinfo, and can live without the manuals. @@ -2583,12 +2583,9 @@ then WEBKIT_REQUIRED=1.4.0 WEBKIT_MODULES="webkitgtk-3.0 >= $WEBKIT_REQUIRED" - if test "${with_gtk3}" = "yes"; then - PKG_CHECK_MODULES(WEBKIT, $WEBKIT_MODULES, HAVE_WEBKIT=yes, HAVE_WEBKIT=no) - if test $HAVE_WEBKIT = yes; then - AC_DEFINE([HAVE_WEBKIT_OSR], 1, - [Define to 1 if you have webkit_osr support.]) - fi + PKG_CHECK_MODULES(WEBKIT, $WEBKIT_MODULES, HAVE_WEBKIT=yes, HAVE_WEBKIT=no) + if test $HAVE_WEBKIT = yes; then + AC_DEFINE([HAVE_WEBKIT_OSR], 1, [Define to 1 if you have webkit_osr support.]) fi GIR_REQUIRED=1.32.1 @@ -5306,8 +5303,8 @@ AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D Does Emacs directly use zlib? ${HAVE_ZLIB} Does Emacs have dynamic modules support? ${HAVE_MODULES} Does Emacs use toolkit scroll bars? ${USE_TOOLKIT_SCROLL_BARS} - Does Emacs support Xwidgets? ${HAVE_XWIDGETS} - Does xwidgets support webkit(requires gtk3)? ${HAVE_WEBKIT} + Does Emacs support Xwidgets (requires gtk3)? ${HAVE_XWIDGETS} + Does xwidgets support webkit? ${HAVE_WEBKIT} Does xwidgets support gobject introspection? ${HAVE_GIR} "]) From 2dbb4deaa97bdd89705d416b0d0cd3d3c444815f Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Tue, 19 Jan 2016 17:49:40 -0500 Subject: [PATCH 14/36] * configure.ac (emacs_config_features): Add XWIDGETS, WEBKIT, GIR. --- configure.ac | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d3513ff4759..bf653adfae1 100644 --- a/configure.ac +++ b/configure.ac @@ -5253,7 +5253,8 @@ optsep= emacs_config_features= for opt in XAW3D XPM JPEG TIFF GIF PNG RSVG CAIRO IMAGEMAGICK SOUND GPM DBUS \ GCONF GSETTINGS NOTIFY ACL LIBSELINUX GNUTLS LIBXML2 FREETYPE M17N_FLT \ - LIBOTF XFT ZLIB TOOLKIT_SCROLL_BARS X_TOOLKIT X11 NS MODULES; do + LIBOTF XFT ZLIB TOOLKIT_SCROLL_BARS X_TOOLKIT X11 NS MODULES \ + XWIDGETS WEBKIT GIR; do case $opt in NOTIFY|ACL) eval val=\${${opt}_SUMMARY} ;; From 1e5eb04c83420bece575cab89b028cf828aaa00e Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Tue, 19 Jan 2016 17:51:32 -0500 Subject: [PATCH 15/36] * configure.ac (WEBKIT, GIR, CAIRO): Use EMACS_CHECK_MODULES, not PKG_. --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index bf653adfae1..3b87fad60b6 100644 --- a/configure.ac +++ b/configure.ac @@ -2583,14 +2583,14 @@ then WEBKIT_REQUIRED=1.4.0 WEBKIT_MODULES="webkitgtk-3.0 >= $WEBKIT_REQUIRED" - PKG_CHECK_MODULES(WEBKIT, $WEBKIT_MODULES, HAVE_WEBKIT=yes, HAVE_WEBKIT=no) + EMACS_CHECK_MODULES(WEBKIT, $WEBKIT_MODULES, HAVE_WEBKIT=yes, HAVE_WEBKIT=no) if test $HAVE_WEBKIT = yes; then AC_DEFINE([HAVE_WEBKIT_OSR], 1, [Define to 1 if you have webkit_osr support.]) fi GIR_REQUIRED=1.32.1 GIR_MODULES="gobject-introspection-1.0 >= $GIR_REQUIRED" - PKG_CHECK_MODULES(GIR, $GIR_MODULES, HAVE_GIR=yes, HAVE_GIR=no) + EMACS_CHECK_MODULES(GIR, $GIR_MODULES, HAVE_GIR=yes, HAVE_GIR=no) if test $HAVE_GIR = yes; then AC_DEFINE([HAVE_GIR], 1, [Define to 1 if you have GIR support.]) fi @@ -3136,7 +3136,7 @@ if test "${HAVE_X11}" = "yes"; then if test "${with_cairo}" != "no"; then CAIRO_REQUIRED=1.12.0 CAIRO_MODULE="cairo >= $CAIRO_REQUIRED" - PKG_CHECK_MODULES(CAIRO, $CAIRO_MODULE, USE_CAIRO=yes, :) + EMACS_CHECK_MODULES(CAIRO, $CAIRO_MODULE, USE_CAIRO=yes, :) if test $USE_CAIRO = yes; then AC_DEFINE(USE_CAIRO, 1, [Define to 1 if using cairo.]) else From 22977b5c51f5c0ffe318fc3cf8a88b7b14983b15 Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Tue, 19 Jan 2016 18:03:37 -0500 Subject: [PATCH 16/36] * lisp/xwidget.el (xwidget-webkit-scroll-behaviour): Fix custom spec. --- lisp/xwidget.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lisp/xwidget.el b/lisp/xwidget.el index 2472c8db93f..17fcf3dae91 100644 --- a/lisp/xwidget.el +++ b/lisp/xwidget.el @@ -36,7 +36,9 @@ (defcustom xwidget-webkit-scroll-behaviour 'native "Scroll behaviour of the webkit instance. 'native or 'image." - :group 'xwidgets) + :version "25.1" + :group 'frames ; TODO add xwidgets group if more options are added + :type '(choice (const native) (const image))) (defun xwidget-insert (pos type title width height &optional args) "Insert an xwidget at POS. From b88f4a2c7624362081aca2bc81cc0c5c72b7245d Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Tue, 19 Jan 2016 18:06:30 -0500 Subject: [PATCH 17/36] Avoid breaking non-xwidget Emacs that happen to load xwidget.el. * lisp/xwidget.el (window-configuration-change-hook) (kill-buffer-query-functions): Only modify these hooks if compiled with xwidget support. --- lisp/xwidget.el | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lisp/xwidget.el b/lisp/xwidget.el index 17fcf3dae91..ff3b977ade5 100644 --- a/lisp/xwidget.el +++ b/lisp/xwidget.el @@ -571,7 +571,8 @@ It can be retrieved with `(xwidget-get XWIDGET PROPNAME)'." ;; This would have felt better in C, but this seems to work well in ;; practice though. -(add-hook 'window-configuration-change-hook 'xwidget-delete-zombies) +(if (featurep 'xwidget-internal) + (add-hook 'window-configuration-change-hook 'xwidget-delete-zombies)) (defun xwidget-kill-buffer-query-function () "Ask beforek illing a buffer that has xwidgets." @@ -582,7 +583,8 @@ It can be retrieved with `(xwidget-get XWIDGET PROPNAME)'." (format "Buffer %S has xwidgets; kill it? " (buffer-name (current-buffer))))))) -(add-hook 'kill-buffer-query-functions 'xwidget-kill-buffer-query-function) +(if (featurep 'xwidget-internal) + (add-hook 'kill-buffer-query-functions 'xwidget-kill-buffer-query-function)) (provide 'xwidget) From 0b356a6aeb7c908e778ac20497bc90fee287af66 Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Tue, 19 Jan 2016 18:13:07 -0500 Subject: [PATCH 18/36] Avoid advising image-display-size for xwidgets. * lisp/xwidget.el (xwidget-image-display-size): Remove. (image-display-size): Remove advice. * lisp/image-mode.el (xwidget-info, xwidget-at): Declare. (image-display-size): Incorporate xwidget code directly. --- lisp/image-mode.el | 43 +++++++++++++++++++++++++------------------ lisp/xwidget.el | 17 ----------------- 2 files changed, 25 insertions(+), 35 deletions(-) diff --git a/lisp/image-mode.el b/lisp/image-mode.el index e677dd0d0e7..38a25d2b7a6 100644 --- a/lisp/image-mode.el +++ b/lisp/image-mode.el @@ -153,6 +153,8 @@ otherwise it defaults to t, used for times when the buffer is not displayed." (selected-window)))) (declare-function image-size "image.c" (spec &optional pixels frame)) +(declare-function xwidget-info "xwidget.c" (xwidget)) +(declare-function xwidget-at "xwidget.el" (pos)) (defun image-display-size (spec &optional pixels frame) "Wrapper around `image-size', handling slice display properties. @@ -160,24 +162,29 @@ Like `image-size', the return value is (WIDTH . HEIGHT). WIDTH and HEIGHT are in canonical character units if PIXELS is nil, and in pixel units if PIXELS is non-nil. -If SPEC is an image display property, this function is equivalent -to `image-size'. If SPEC is a list of properties containing -`image' and `slice' properties, return the display size taking -the slice property into account. If the list contains `image' -but not `slice', return the `image-size' of the specified image." - (if (eq (car spec) 'image) - (image-size spec pixels frame) - (let ((image (assoc 'image spec)) - (slice (assoc 'slice spec))) - (cond ((and image slice) - (if pixels - (cons (nth 3 slice) (nth 4 slice)) - (cons (/ (float (nth 3 slice)) (frame-char-width frame)) - (/ (float (nth 4 slice)) (frame-char-height frame))))) - (image - (image-size image pixels frame)) - (t - (error "Invalid image specification: %s" spec)))))) +If SPEC is an image display property, this function is equivalent to +`image-size'. If SPEC represents an xwidget object, defer to `xwidget-info'. +If SPEC is a list of properties containing `image' and `slice' properties, +return the display size taking the slice property into account. If the list +contains `image' but not `slice', return the `image-size' of the specified +image." + (cond ((eq (car spec) 'xwidget) + (let ((xwi (xwidget-info (xwidget-at 1)))) ; FIXME point-min? + (cons (aref xwi 2) (aref xwi 3)))) + ((eq (car spec) 'image) + (image-size spec pixels frame)) + (t (let ((image (assoc 'image spec)) + (slice (assoc 'slice spec))) + (cond ((and image slice) + (if pixels + (cons (nth 3 slice) (nth 4 slice)) + (cons (/ (float (nth 3 slice)) (frame-char-width frame)) + (/ (float (nth 4 slice)) + (frame-char-height frame))))) + (image + (image-size image pixels frame)) + (t + (error "Invalid image specification: %s" spec))))))) (defun image-forward-hscroll (&optional n) "Scroll image in current window to the left by N character widths. diff --git a/lisp/xwidget.el b/lisp/xwidget.el index ff3b977ade5..41e2c1cef6c 100644 --- a/lisp/xwidget.el +++ b/lisp/xwidget.el @@ -87,23 +87,6 @@ defaults to the string looking like a url around the cursor position." (xwidget-webkit-new-session url) (xwidget-webkit-goto-url url)))) - -;;shims for adapting image mode code to the webkit browser window -(defun xwidget-image-display-size (spec &optional pixels frame) - "Image code adaptor. SPEC PIXELS FRAME like the corresponding -`image-mode' fn." - (let ((xwi (xwidget-info (xwidget-at 1)))) - (cons (aref xwi 2) - (aref xwi 3)))) - -(defadvice image-display-size (around image-display-size-for-xwidget - (spec &optional pixels frame) - activate) - "Advice for re-using image mode for xwidget." - (if (eq (car spec) 'xwidget) - (setq ad-return-value (xwidget-image-display-size spec pixels frame)) - ad-do-it)) - ;;todo. ;; - check that the webkit support is compiled in (defvar xwidget-webkit-mode-map From ea415382786305179ec9bd2ca88d7caccd09f63a Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Tue, 19 Jan 2016 18:42:47 -0500 Subject: [PATCH 19/36] Trivial doc copyedits. * src/xwidget.c (Fmake_xwidget, Fget_buffer_xwidgets) (Fxwidget_webkit_get_title, Fxwidget_resize) (Fxwidget_set_adjustment, Fxwidgetp, Fxwidget_view_p) (Fxwidget_info, Fxwidget_view_lookup) (Fset_xwidget_query_on_exit_flag): Trivial doc copyedits. --- src/xwidget.c | 98 +++++++++++++++++++++++---------------------------- 1 file changed, 45 insertions(+), 53 deletions(-) diff --git a/src/xwidget.c b/src/xwidget.c index 1ed7eaae2a7..88cdb941c4c 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -160,18 +160,13 @@ DEFUN ("make-xwidget", Fmake_xwidget, Smake_xwidget, 7, 8, 0, doc: /* Make an xwidget from BEG to END of TYPE. - -If BUFFER is nil it uses the current -buffer. If BUFFER is a string and no such -buffer exists, it is created. - -TYPE is a symbol which can take one of the -following values: +If BUFFER is nil, use the current buffer. +If BUFFER is a string and no such buffer exists, create it. +TYPE is a symbol which can take one of the following values: - webkit_osr -Returns the newly constructed xwidget, or nil if construction -fails. */) +Returns the newly constructed xwidget, or nil if construction fails. */) (Lisp_Object beg, Lisp_Object end, Lisp_Object type, Lisp_Object title, @@ -255,7 +250,7 @@ fails. */) gtk_widget_show (xw->widgetscrolledwindow_osr); /* store some xwidget data in the gtk widgets for convenient - retrieval in the event handlers. */ + retrieval in the event handlers. */ g_object_set_data (G_OBJECT (xw->widget_osr), XG_XWIDGET, (gpointer) (xw)); g_object_set_data (G_OBJECT (xw->widgetwindow_osr), XG_XWIDGET, @@ -302,7 +297,7 @@ fails. */) DEFUN ("get-buffer-xwidgets", Fget_buffer_xwidgets, Sget_buffer_xwidgets, 1, 1, 0, doc: /* Return a list of xwidgets associated with BUFFER. -BUFFER may be a buffer or the name of one. */) +BUFFER may be a buffer or the name of one. */) (Lisp_Object buffer) { Lisp_Object xw, tail, xw_list; @@ -429,7 +424,7 @@ webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *webView, gpointer user_data) { // This function makes webkit send a download signal for all unknown - // mime types. TODO Defer the decision to lisp, so that its possible + // mime types. TODO Defer the decision to lisp, so that its possible // to make Emacs handle teext mime for instance.xs if (!webkit_web_view_can_show_mime_type (webView, mimetype)) { @@ -502,13 +497,13 @@ xwidget_osr_event_forward (GtkWidget * widget, GdkEvent * event, gpointer user_data) { - /* Copy events that arrive at the outer widget to the offscreen widget. */ + /* Copy events that arrive at the outer widget to the offscreen widget. */ struct xwidget *xw = (struct xwidget *) g_object_get_data (G_OBJECT (widget), XG_XWIDGET); GdkEvent *eventcopy = gdk_event_copy (event); eventcopy->any.window = gtk_widget_get_window (xw->widget_osr); - //TODO This might leak events. They should be deallocated later, + //TODO This might leak events. They should be deallocated later, //perhaps in xwgir_event_cb gtk_main_do_event (eventcopy); return TRUE; //dont propagate this event furter @@ -528,7 +523,7 @@ xwidget_osr_event_set_embedder (GtkWidget * widget, } -/* Initializes and does initial placement of an xwidget view on screen. */ +/* Initializes and does initial placement of an xwidget view on screen. */ static struct xwidget_view * xwidget_init_view (struct xwidget *xww, struct glyph_string *s, @@ -653,9 +648,9 @@ x_draw_xwidget_glyph_string (struct glyph_string *s) WINDOW_BOTTOM_EDGE_Y (s->w) - WINDOW_MODE_LINE_HEIGHT (s->w) - y); clip_top = max (0, WINDOW_TOP_EDGE_Y (s->w) - y); - // We are conserned with movement of the onscreen area. The area + // We are conserned with movement of the onscreen area. The area // might sit still when the widget actually moves. This happens - // when an Emacs window border moves across a widget window. So, if + // when an Emacs window border moves across a widget window. So, if // any corner of the outer widget clipping window moves, that counts // as movement here, even if it looks like no movement happens // because the widget sits still inside the clipping area. The @@ -671,8 +666,8 @@ x_draw_xwidget_glyph_string (struct glyph_string *s) xv->widgetwindow, x + clip_left, y + clip_top); } // Clip the widget window if some parts happen to be outside - // drawable area. An Emacs window is not a gtk window. A gtk window - // covers the entire frame. Clipping might have changed even if we + // drawable area. An Emacs window is not a gtk window. A gtk window + // covers the entire frame. Clipping might have changed even if we // havent actualy moved, we try figure out when we need to reclip // for real. if ((xv->clip_right != clip_right) @@ -690,9 +685,9 @@ x_draw_xwidget_glyph_string (struct glyph_string *s) xv->clip_left = clip_left; } // If emacs wants to repaint the area where the widget lives, queue - // a redraw. It seems its possible to get out of sync with emacs + // a redraw. It seems its possible to get out of sync with emacs // redraws so emacs background sometimes shows up instead of the - // xwidgets background. It's just a visual glitch though. + // xwidgets background. It's just a visual glitch though. if (!xwidget_hidden (xv)) { gtk_widget_queue_draw (xv->widgetwindow); @@ -717,8 +712,7 @@ x_draw_xwidget_glyph_string (struct glyph_string *s) DEFUN ("xwidget-webkit-goto-uri", Fxwidget_webkit_goto_uri, Sxwidget_webkit_goto_uri, 2, 2, 0, - doc: /* Make the xwidget webkit instance referenced by XWIDGET -browse URI. */) + doc: /* Make the xwidget webkit instance referenced by XWIDGET browse URI. */) (Lisp_Object xwidget, Lisp_Object uri) { WEBKIT_FN_INIT (); @@ -744,7 +738,7 @@ DEFUN ("xwidget-webkit-execute-script", DEFUN ("xwidget-webkit-get-title", Fxwidget_webkit_get_title, Sxwidget_webkit_get_title, 1, 1, 0, - doc: /* Returns the title from the Webkit instance in XWIDGET. + doc: /* Return the title from the Webkit instance in XWIDGET. This can be used to work around the lack of a return value from the exec method. */ ) (Lisp_Object xwidget) @@ -755,7 +749,7 @@ exec method. */ ) webkit_web_view_get_title (WEBKIT_WEB_VIEW (xw->widget_osr)); if (str == 0) { - // TODO maybe return Qnil instead. I suppose webkit returns + // TODO maybe return Qnil instead. I suppose webkit returns // nullpointer when doc is not properly loaded or something return build_string (""); } @@ -763,8 +757,7 @@ exec method. */ ) } DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 3, 3, 0, - doc: /* Resize XWIDGET. NEW_WIDTH NEW_HEIGHT defines the new -size. */ ) + doc: /* Resize XWIDGET. NEW_WIDTH, NEW_HEIGHT define the new size. */ ) (Lisp_Object xwidget, Lisp_Object new_width, Lisp_Object new_height) { CHECK_XWIDGET (xwidget); @@ -817,8 +810,9 @@ size. */ ) DEFUN ("xwidget-set-adjustment", Fxwidget_set_adjustment, Sxwidget_set_adjustment, 4, 4, 0, - doc: /* Set native scrolling for XWIDGET. AXIS can be 'vertical or -'horizontal. If RELATIVE is t, scroll relative, otherwise absolutely. + doc: /* Set native scrolling for XWIDGET. +AXIS can be 'vertical or 'horizontal. +If RELATIVE is t, scroll relative, otherwise absolutely. VALUE is the amount to scroll, either relatively or absolutely. */) (Lisp_Object xwidget, Lisp_Object axis, Lisp_Object relative, Lisp_Object value) @@ -863,7 +857,6 @@ DEFUN ("xwidget-size-request", Fxwidget_size_request, Sxwidget_size_request, 1, 1, 0, doc: /* Return the desired size of the XWIDGET. - This can be used to read the xwidget desired size, and resizes the Emacs allocated area accordingly. */) (Lisp_Object xwidget) @@ -882,7 +875,7 @@ Emacs allocated area accordingly. */) DEFUN ("xwidgetp", Fxwidgetp, Sxwidgetp, 1, 1, 0, - doc: /* Return t if OBJECT is a xwidget. */) + doc: /* Return t if OBJECT is an xwidget. */) (Lisp_Object object) { return XWIDGETP (object) ? Qt : Qnil; @@ -891,7 +884,7 @@ DEFUN ("xwidgetp", DEFUN ("xwidget-view-p", Fxwidget_view_p, Sxwidget_view_p, 1, 1, 0, - doc: /* Return t if OBJECT is a xwidget-view. */) + doc: /* Return t if OBJECT is an xwidget-view. */) (Lisp_Object object) { return XWIDGET_VIEW_P (object) ? Qt : Qnil; @@ -900,8 +893,8 @@ DEFUN ("xwidget-view-p", DEFUN ("xwidget-info", Fxwidget_info, Sxwidget_info, 1, 1, 0, - doc: /* Return XWIDGET properties in a vector. Currently [TYPE -TITLE WIDTH HEIGHT]. */) + doc: /* Return XWIDGET properties in a vector. +Currently [TYPE TITLE WIDTH HEIGHT]. */) (Lisp_Object xwidget) { CHECK_XWIDGET (xwidget); @@ -923,7 +916,7 @@ DEFUN ("xwidget-view-info", Fxwidget_view_info, Sxwidget_view_info, 1, 1, 0, doc: /* Return properties of XWIDGET-VIEW in a vector. -Currently [X Y CLIP_RIGHT CLIP_BOTTOM CLIP_TOP CLIP_LEFT] */) +Currently [X Y CLIP_RIGHT CLIP_BOTTOM CLIP_TOP CLIP_LEFT]. */) (Lisp_Object xwidget_view) { CHECK_XWIDGET_VIEW (xwidget_view); @@ -944,7 +937,7 @@ Currently [X Y CLIP_RIGHT CLIP_BOTTOM CLIP_TOP CLIP_LEFT] */) DEFUN ("xwidget-view-model", Fxwidget_view_model, Sxwidget_view_model, 1, 1, 0, - doc: /* Return the model associated with XWIDGET-VIEW. */) + doc: /* Return the model associated with XWIDGET-VIEW. */) (Lisp_Object xwidget_view) { CHECK_XWIDGET_VIEW (xwidget_view); @@ -954,7 +947,7 @@ DEFUN ("xwidget-view-model", DEFUN ("xwidget-view-window", Fxwidget_view_window, Sxwidget_view_window, 1, 1, 0, - doc: /* Return the window of XWIDGET-VIEW. */) + doc: /* Return the window of XWIDGET-VIEW. */) (Lisp_Object xwidget_view) { CHECK_XWIDGET_VIEW (xwidget_view); @@ -965,15 +958,15 @@ DEFUN ("xwidget-view-window", DEFUN ("delete-xwidget-view", Fdelete_xwidget_view, Sdelete_xwidget_view, 1, 1, 0, - doc: /* Delete the XWIDGET-VIEW. */) + doc: /* Delete the XWIDGET-VIEW. */) (Lisp_Object xwidget_view) { CHECK_XWIDGET_VIEW (xwidget_view); struct xwidget_view *xv = XXWIDGET_VIEW (xwidget_view); gtk_widget_destroy (xv->widgetwindow); Vxwidget_view_list = Fdelq (xwidget_view, Vxwidget_view_list); - // xv->model still has signals pointing to the view. There can be - // several views. Find the matching signals and delete them all. + // xv->model still has signals pointing to the view. There can be + // several views. Find the matching signals and delete them all. g_signal_handlers_disconnect_matched (XXWIDGET (xv->model)->widgetwindow_osr, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, @@ -984,9 +977,9 @@ DEFUN ("delete-xwidget-view", DEFUN ("xwidget-view-lookup", Fxwidget_view_lookup, Sxwidget_view_lookup, 1, 2, 0, - doc: /* Return the xwidget-view associated with XWIDGET in -WINDOW if specified, otherwise it uses the selected window. Return nil -if no association is found. */) + doc: /* Return the xwidget-view associated with XWIDGET in WINDOW. +If WINDOW is unspecified or nil, use the selected window. +Return nil if no association is found. */) (Lisp_Object xwidget, Lisp_Object window) { CHECK_XWIDGET (xwidget); @@ -1044,10 +1037,10 @@ Returns PLIST. */) DEFUN ("set-xwidget-query-on-exit-flag", Fset_xwidget_query_on_exit_flag, Sset_xwidget_query_on_exit_flag, 2, 2, 0, - doc: /* Specify if query is needed for XWIDGET when -Emacs is exited. If the second argument FLAG is non-nil, Emacs will -queries the user before exiting or killing a buffer if XWIDGET is -running. This function returns FLAG. */) + doc: /* Specify if query is needed for XWIDGET when Emacs is exited. +If the second argument FLAG is non-nil, Emacs will query the user before +exiting or killing a buffer if XWIDGET is running. +This function returns FLAG. */) (Lisp_Object xwidget, Lisp_Object flag) { CHECK_XWIDGET (xwidget); @@ -1058,8 +1051,7 @@ running. This function returns FLAG. */) DEFUN ("xwidget-query-on-exit-flag", Fxwidget_query_on_exit_flag, Sxwidget_query_on_exit_flag, 1, 1, 0, - doc: /* Return the current value of query-on-exit -flag for XWIDGET. */) + doc: /* Return the current value of the query-on-exit flag for XWIDGET. */) (Lisp_Object xwidget) { CHECK_XWIDGET (xwidget); @@ -1107,7 +1099,7 @@ syms_of_xwidget (void) DEFSYM (QCtitle, ":title"); /* Do not forget to update the docstring of make-xwidget if you add - new types. */ + new types. */ DEFSYM (Qvertical, "vertical"); DEFSYM (Qhorizontal, "horizontal"); @@ -1219,7 +1211,7 @@ lookup_xwidget (Lisp_Object spec) return xw; } -/* Set up detection of touched xwidget*/ +/* Set up detection of touched xwidget */ void xwidget_start_redisplay (void) { @@ -1258,7 +1250,7 @@ xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix) // Iterate desired glyph matrix of window here, hide gtk widgets // not in the desired matrix. - // This only takes care of xwidgets in active windows. if a window + // This only takes care of xwidgets in active windows. If a window // goes away from screen xwidget views wust be deleted // dump_glyph_matrix (matrix, 2); @@ -1309,7 +1301,7 @@ xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix) } } -/* Kill all xwidget in BUFFER. */ +/* Kill all xwidget in BUFFER. */ void kill_buffer_xwidgets (Lisp_Object buffer) { From c9471132c329cffd24db2cedea339e58bea70920 Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Tue, 19 Jan 2016 18:44:29 -0500 Subject: [PATCH 20/36] * lisp/xwidget.el: Add declarations to silence non-xwidget compilation. --- lisp/xwidget.el | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/lisp/xwidget.el b/lisp/xwidget.el index 41e2c1cef6c..f2c79afec03 100644 --- a/lisp/xwidget.el +++ b/lisp/xwidget.el @@ -40,6 +40,23 @@ :group 'frames ; TODO add xwidgets group if more options are added :type '(choice (const native) (const image))) +(declare-function make-xwidget "xwidget.c" + (beg end type title width height arguments &optional buffer)) +(declare-function xwidget-set-adjustment "xwidget.c" + (xwidget axis relative value)) +(declare-function xwidget-buffer "xwidget.c" (xwidget)) +(declare-function xwidget-webkit-get-title "xwidget.c" (xwidget)) +(declare-function xwidget-size-request "xwidget.c" (xwidget)) +(declare-function xwidget-resize "xwidget.c" (xwidget new-width new-height)) +(declare-function xwidget-webkit-execute-script "xwidget.c" (xwidget script)) +(declare-function xwidget-webkit-goto-uri "xwidget.c" (xwidget uri)) +(declare-function xwidget-plist "xwidget.c" (xwidget)) +(declare-function set-xwidget-plist "xwidget.c" (xwidget plist)) +(declare-function xwidget-view-window "xwidget.c" (xwidget-view)) +(declare-function xwidget-view-model "xwidget.c" (xwidget-view)) +(declare-function delete-xwidget-view "xwidget.c" (xwidget-view)) +(declare-function get-buffer-xwidgets "xwidget.c" (buffer)) + (defun xwidget-insert (pos type title width height &optional args) "Insert an xwidget at POS. given ID, TYPE, TITLE WIDTH and @@ -499,11 +516,6 @@ DEFAULT is the defaultreturn value." (setq title default)) title)) - -;; Use declare here? -;; (declare-function xwidget-resize-internal "xwidget.c" ) -;; check-declare-function? - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun xwidget-webkit-get-selection () "Get the webkit selection." @@ -533,6 +545,9 @@ It can be retrieved with `(xwidget-get XWIDGET PROPNAME)'." ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defvar xwidget-view-list) ; xwidget.c +(defvar xwidget-list) ; xwidget.c + (defun xwidget-delete-zombies () "Helper for `xwidget-cleanup'." (dolist (xwidget-view xwidget-view-list) From 833d53b98bb3ea037fb15d2bac855a47fa00639d Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Tue, 19 Jan 2016 19:06:32 -0500 Subject: [PATCH 21/36] ; * lisp/xwidget.el: Spelling fixes. --- lisp/xwidget.el | 54 ++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/lisp/xwidget.el b/lisp/xwidget.el index f2c79afec03..223f4f290b2 100644 --- a/lisp/xwidget.el +++ b/lisp/xwidget.el @@ -23,9 +23,9 @@ ;;; Commentary: ;; -;; See xwidget.c for more api functions +;; See xwidget.c for more api functions. -;;TODO this breaks compilation when we dont have xwidgets +;; TODO this breaks compilation when we don't have xwidgets. ;;(require 'xwidget-internal) ;;; Code: @@ -75,8 +75,8 @@ Optional argument ARGS usage depends on the xwidget." (defun xwidget-at (pos) "Return xwidget at POS." - ;;TODO this function is a bit tedious because the C layer isnt well - ;;protected yet and xwidgetp aparently doesnt work yet + ;; TODO this function is a bit tedious because the C layer isn't well + ;; protected yet and xwidgetp apparently doesn't work yet. (let* ((disp (get-text-property pos 'display)) (xw (car (cdr (cdr disp))))) ;;(if ( xwidgetp xw) xw nil) @@ -169,9 +169,9 @@ defaults to the string looking like a url around the cursor position." (xwidget-webkit-scroll-backward))) -;;the xwidget event needs to go into a higher level handler -;;since the xwidget can generate an event even if its offscreen -;;TODO this needs to use callbacks and consider different xw ev types +;; The xwidget event needs to go into a higher level handler +;; since the xwidget can generate an event even if it's offscreen. +;; TODO this needs to use callbacks and consider different xwidget event types. (define-key (current-global-map) [xwidget-event] 'xwidget-event-handler) (defun xwidget-log ( &rest msg) "Log MSG to a buffer." @@ -241,7 +241,7 @@ XWIDGET instance, XWIDGET-EVENT-TYPE depends on the originating xwidget." (defvar xwidget-webkit-last-session-buffer nil) -(defun xwidget-webkit-last-session () +(defun xwidget-webkit-last-session () "Last active webkit, or nil." (if (buffer-live-p xwidget-webkit-last-session-buffer) (with-current-buffer xwidget-webkit-last-session-buffer @@ -249,17 +249,17 @@ XWIDGET instance, XWIDGET-EVENT-TYPE depends on the originating xwidget." nil)) (defun xwidget-webkit-current-session () - "Either the webkit in the current buffer, or the last one used, -which might be nil." + "Either the webkit in the current buffer, or the last one used. +The latter might be nil." (if (xwidget-at 1) (xwidget-at 1) (xwidget-webkit-last-session))) (defun xwidget-adjust-size-to-content (xw) "Resize XW to content." - ;;xwidgets doesnt support widgets that have their own opinions about - ;;size well yet this reads the desired size and resizes the emacs - ;;allocated area accordingly + ;; xwidgets doesn't support widgets that have their own opinions about + ;; size well, yet this reads the desired size and resizes the emacs + ;; allocated area accordingly. (let ((size (xwidget-size-request xw))) (xwidget-resize xw (car size) (cadr size)))) @@ -288,9 +288,9 @@ function findactiveelement(doc){ " "javascript that finds the active element." - ;;yes its ugly. because: - ;; - there is aparently no way to find the active frame other than recursion - ;; - the js "for each" construct missbehaved on the "frames" collection + ;; Yes it's ugly, because: + ;; - there is apparently no way to find the active frame other than recursion + ;; - the js "for each" construct misbehaved on the "frames" collection ;; - a window with no frameset still has frames.length == 1, but ;; frames[0].document.activeElement != document.activeElement ;;TODO the activeelement type needs to be examined, for iframe, etc. @@ -300,7 +300,7 @@ function findactiveelement(doc){ "Insert string in the active field in the webkit. Argument XW webkit. Argument STR string." - ;;read out the string in the field first and provide for edit + ;; Read out the string in the field first and provide for edit. (interactive (let* ((xww (xwidget-webkit-current-session)) @@ -359,7 +359,7 @@ Argument ELEMENT-NAME is the element name to display in the webkit xwidget." ;; This function implements a proof-of-concept for this. Problems ;; remaining: - The selected window is scrolled but this is not ;; always correct - This needs to be interfaced into browse-url - ;; somehow. the tricky part is that we need to do this in two steps: + ;; somehow. The tricky part is that we need to do this in two steps: ;; A: load the base url, wait for load signal to arrive B: navigate ;; to the anchor when the base url is finished rendering @@ -424,8 +424,8 @@ Argument ELEMENT-ID is either a name or an element id." (xwidget-webkit-adjust-size-to-window) (xwidget-webkit-adjust-size-to-content)) ;; The recenter is intended to correct a visual glitch. - ;; It errors out if the buffer isn't visible, but then we dont get the glitch, - ;; so silence errors + ;; It errors out if the buffer isn't visible, but then we don't get + ;; the glitch, so silence errors. (ignore-errors (recenter-top-bottom)) ) @@ -437,7 +437,7 @@ Argument ELEMENT-ID is either a name or an element id." (window-pixel-height))) (defun xwidget-webkit-adjust-size (w h) - "Manualy set webkit size. + "Manually set webkit size. Argument W width. Argument H height." ;; TODO shouldn't be tied to the webkit xwidget @@ -495,15 +495,15 @@ Argument H height." (defun xwidget-webkit-execute-script-rv (xw script &optional default) "Same as 'xwidget-webkit-execute-script' but but with return value. -XW is the webkit instance. SCRIPT is the script to execut. +XW is the webkit instance. SCRIPT is the script to execute. DEFAULT is the defaultreturn value." ;; Notice the ugly "title" hack. It is needed because the Webkit ;; API at the time of writing didn't support returning values. This - ;; is a wrapper for the title hack so its easy to remove should + ;; is a wrapper for the title hack so it's easy to remove should ;; Webkit someday support JS return values or we find some other way ;; to access the DOM. - ;; Reset webkit title. Not very nice. + ;; Reset webkit title. Not very nice. (let* ((emptytag "titlecantbewhitespaceohthehorror") title) (xwidget-webkit-execute-script xw (format "document.title=\"%s\";" @@ -529,7 +529,7 @@ DEFAULT is the defaultreturn value." ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Xwidget plist management(similar to the process plist functions) +;; Xwidget plist management (similar to the process plist functions) (defun xwidget-get (xwidget propname) "Return the value of XWIDGET' PROPNAME property. @@ -562,7 +562,7 @@ It can be retrieved with `(xwidget-get XWIDGET PROPNAME)'." ;; xwidget instances. ;; This function tries to implement a workaround should it occur again. (interactive) - ;; Kill xviews who should have been deleted but stull linger. + ;; Kill xviews that should have been deleted but still linger. (xwidget-delete-zombies) ;; Redraw display otherwise ghost of zombies will remain to haunt the screen (redraw-display)) @@ -573,7 +573,7 @@ It can be retrieved with `(xwidget-get XWIDGET PROPNAME)'." (add-hook 'window-configuration-change-hook 'xwidget-delete-zombies)) (defun xwidget-kill-buffer-query-function () - "Ask beforek illing a buffer that has xwidgets." + "Ask before killing a buffer that has xwidgets." (let ((xwidgets (get-buffer-xwidgets (current-buffer)))) (or (not xwidgets) (not (memq t (mapcar 'xwidget-query-on-exit-flag xwidgets))) From 96f6cace6bd088c8a49892502354272eb9d1a702 Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Tue, 19 Jan 2016 19:09:45 -0500 Subject: [PATCH 22/36] Don't hard-code 1 as point-min. * lisp/image-mode.el (image-display-size): * lisp/xwidget.el (xwidget-webkit-last-session) (xwidget-webkit-current-session): Don't hard-code 1 as point-min. --- lisp/image-mode.el | 2 +- lisp/xwidget.el | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/lisp/image-mode.el b/lisp/image-mode.el index 38a25d2b7a6..e549b49001e 100644 --- a/lisp/image-mode.el +++ b/lisp/image-mode.el @@ -169,7 +169,7 @@ return the display size taking the slice property into account. If the list contains `image' but not `slice', return the `image-size' of the specified image." (cond ((eq (car spec) 'xwidget) - (let ((xwi (xwidget-info (xwidget-at 1)))) ; FIXME point-min? + (let ((xwi (xwidget-info (xwidget-at (point-min))))) (cons (aref xwi 2) (aref xwi 3)))) ((eq (car spec) 'image) (image-size spec pixels frame)) diff --git a/lisp/xwidget.el b/lisp/xwidget.el index 223f4f290b2..0fb90c4573c 100644 --- a/lisp/xwidget.el +++ b/lisp/xwidget.el @@ -245,15 +245,13 @@ XWIDGET instance, XWIDGET-EVENT-TYPE depends on the originating xwidget." "Last active webkit, or nil." (if (buffer-live-p xwidget-webkit-last-session-buffer) (with-current-buffer xwidget-webkit-last-session-buffer - (xwidget-at 1)) + (xwidget-at (point-min))) nil)) (defun xwidget-webkit-current-session () "Either the webkit in the current buffer, or the last one used. The latter might be nil." - (if (xwidget-at 1) - (xwidget-at 1) - (xwidget-webkit-last-session))) + (or (xwidget-at (point-min)) (xwidget-webkit-last-session))) (defun xwidget-adjust-size-to-content (xw) "Resize XW to content." From c5ee6de21d4bd0562d811129e2ef7c0419a882a1 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Tue, 19 Jan 2016 20:53:10 -0500 Subject: [PATCH 23/36] * lisp/xwidget.el: Nitpicks * lisp/xwidget.el (xwidget-log, xwidget-webkit-callback): Use with-current-buffer rather than save-excursion + set-buffer. --- lisp/xwidget.el | 123 +++++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 65 deletions(-) diff --git a/lisp/xwidget.el b/lisp/xwidget.el index 0fb90c4573c..f184eb31dbb 100644 --- a/lisp/xwidget.el +++ b/lisp/xwidget.el @@ -79,7 +79,7 @@ Optional argument ARGS usage depends on the xwidget." ;; protected yet and xwidgetp apparently doesn't work yet. (let* ((disp (get-text-property pos 'display)) (xw (car (cdr (cdr disp))))) - ;;(if ( xwidgetp xw) xw nil) + ;;(if (xwidgetp xw) xw nil) (if (equal 'xwidget (car disp)) xw))) @@ -97,7 +97,7 @@ defaults to the string looking like a url around the cursor position." (interactive (progn (require 'browse-url) (browse-url-interactive-arg "xwidget-webkit URL: " - ;;( xwidget-webkit-current-url) + ;;(xwidget-webkit-current-url) ))) (when (stringp url) (if new-session @@ -110,9 +110,9 @@ defaults to the string looking like a url around the cursor position." (let ((map (make-sparse-keymap))) (define-key map "g" 'xwidget-webkit-browse-url) (define-key map "a" 'xwidget-webkit-adjust-size-dispatch) - (define-key map "b" 'xwidget-webkit-back ) - (define-key map "r" 'xwidget-webkit-reload ) - (define-key map "t" (lambda () (interactive) (message "o")) ) + (define-key map "b" 'xwidget-webkit-back) + (define-key map "r" 'xwidget-webkit-reload) + (define-key map "t" (lambda () (interactive) (message "o"))) ;FIXME: ?!? (define-key map "\C-m" 'xwidget-webkit-insert-string) (define-key map "w" 'xwidget-webkit-current-url) @@ -172,14 +172,12 @@ defaults to the string looking like a url around the cursor position." ;; The xwidget event needs to go into a higher level handler ;; since the xwidget can generate an event even if it's offscreen. ;; TODO this needs to use callbacks and consider different xwidget event types. -(define-key (current-global-map) [xwidget-event] 'xwidget-event-handler) -(defun xwidget-log ( &rest msg) +(define-key (current-global-map) [xwidget-event] #'xwidget-event-handler) +(defun xwidget-log (&rest msg) "Log MSG to a buffer." - (let ( (buf (get-buffer-create "*xwidget-log*"))) - (save-excursion - (buffer-disable-undo buf) - (set-buffer buf) - (insert (apply 'format msg)) + (let ((buf (get-buffer-create " *xwidget-log*"))) + (with-current-buffer buf + (insert (apply #'format msg)) (insert "\n")))) (defun xwidget-event-handler () @@ -199,44 +197,43 @@ defaults to the string looking like a url around the cursor position." (defun xwidget-webkit-callback (xwidget xwidget-event-type) "Callback for xwidgets. XWIDGET instance, XWIDGET-EVENT-TYPE depends on the originating xwidget." - (save-excursion - (cond ((buffer-live-p (xwidget-buffer xwidget)) - (set-buffer (xwidget-buffer xwidget)) - (let* ((strarg (nth 3 last-input-event))) - (cond ((eq xwidget-event-type 'document-load-finished) - (xwidget-log "webkit finished loading: '%s'" - (xwidget-webkit-get-title xwidget)) - ;;TODO - check the native/internal scroll - ;;(xwidget-adjust-size-to-content xwidget) - (xwidget-webkit-adjust-size-dispatch) ;;TODO xwidget arg - (rename-buffer (format "*xwidget webkit: %s *" - (xwidget-webkit-get-title xwidget))) - (pop-to-buffer (current-buffer))) - ((eq xwidget-event-type - 'navigation-policy-decision-requested) - (if (string-match ".*#\\(.*\\)" strarg) - (xwidget-webkit-show-id-or-named-element - xwidget - (match-string 1 strarg)))) - (t (xwidget-log "unhandled event:%s" xwidget-event-type))))) - (t (xwidget-log - "error: callback called for xwidget with dead buffer"))))) + (if (not (buffer-live-p (xwidget-buffer xwidget))) + (xwidget-log + "error: callback called for xwidget with dead buffer") + (with-current-buffer (xwidget-buffer xwidget) + (let* ((strarg (nth 3 last-input-event))) + (cond ((eq xwidget-event-type 'document-load-finished) + (xwidget-log "webkit finished loading: '%s'" + (xwidget-webkit-get-title xwidget)) + ;;TODO - check the native/internal scroll + ;;(xwidget-adjust-size-to-content xwidget) + (xwidget-webkit-adjust-size-dispatch) ;;TODO xwidget arg + (rename-buffer (format "*xwidget webkit: %s *" + (xwidget-webkit-get-title xwidget))) + (pop-to-buffer (current-buffer))) + ((eq xwidget-event-type + 'navigation-policy-decision-requested) + (if (string-match ".*#\\(.*\\)" strarg) + (xwidget-webkit-show-id-or-named-element + xwidget + (match-string 1 strarg)))) + (t (xwidget-log "unhandled event:%s" xwidget-event-type))))))) (defvar bookmark-make-record-function) (define-derived-mode xwidget-webkit-mode - special-mode "xwidget-webkit" "xwidget webkit view mode" - (setq buffer-read-only t) - (setq-local bookmark-make-record-function - #'xwidget-webkit-bookmark-make-record) - ;; Keep track of [vh]scroll when switching buffers - (image-mode-setup-winprops)) + special-mode "xwidget-webkit" "Xwidget webkit view mode." + (setq buffer-read-only t) + (setq-local bookmark-make-record-function + #'xwidget-webkit-bookmark-make-record) + ;; Keep track of [vh]scroll when switching buffers + (image-mode-setup-winprops)) (defun xwidget-webkit-bookmark-make-record () -"Integrate Emacs bookmarks with the webkit xwidget." + "Integrate Emacs bookmarks with the webkit xwidget." (nconc (bookmark-make-record-default t t) `((page . ,(xwidget-webkit-current-url)) (handler . (lambda (bmk) (browse-url - (bookmark-prop-get bmk 'page))))))) + (bookmark-prop-get bmk 'page))))))) (defvar xwidget-webkit-last-session-buffer nil) @@ -256,7 +253,7 @@ The latter might be nil." (defun xwidget-adjust-size-to-content (xw) "Resize XW to content." ;; xwidgets doesn't support widgets that have their own opinions about - ;; size well, yet this reads the desired size and resizes the emacs + ;; size well, yet this reads the desired size and resizes the Emacs ;; allocated area accordingly. (let ((size (xwidget-size-request xw))) (xwidget-resize xw (car size) (cadr size)))) @@ -307,10 +304,10 @@ Argument STR string." (xwidget-webkit-execute-script xww xwidget-webkit-activeelement-js) (xwidget-webkit-execute-script-rv xww - "findactiveelement(document).value;" ))) + "findactiveelement(document).value;"))) (field-type (xwidget-webkit-execute-script-rv xww - "findactiveelement(document).type;" ))) + "findactiveelement(document).type;"))) (list xww (cond ((equal "text" field-type) (read-string "text:" field-value)) @@ -333,7 +330,7 @@ XW is the xwidget identifier, TEXT is retrieved from the webkit." (insert text)) (defun xwidget-webkit-end-edit-textarea () - "End editing of a webkit text area." + "End editing of a webkit text area." (interactive) (goto-char (point-min)) (while (search-forward "\n" nil t) @@ -369,7 +366,7 @@ Argument ELEMENT-NAME is the element name to display in the webkit xwidget." "document.getElementsByName('%s')[0].getBoundingClientRect().top" element-name) 0)))) - ;; Now we need to tell emacs to scroll the element into view. + ;; Now we need to tell Emacs to scroll the element into view. (xwidget-log "scroll: %d" y) (set-window-vscroll (selected-window) y t))) @@ -385,7 +382,7 @@ Argument ELEMENT-ID is the id of the element to show." (format "document.getElementById('%s').getBoundingClientRect().top" element-id) 0)))) - ;; Now we need to tell emacs to scroll the element into view. + ;; Now we need to tell Emacs to scroll the element into view. (xwidget-log "scroll: %d" y) (set-window-vscroll (selected-window) y t))) @@ -404,9 +401,9 @@ Argument ELEMENT-ID is either a name or an element id." (xwidget-webkit-execute-script-rv xw (format "document.getElementById('%s').getBoundingClientRect().top" element-id) - "0"))) + "0"))) (y3 (max y1 y2))) - ;; Now we need to tell emacs to scroll the element into view. + ;; Now we need to tell Emacs to scroll the element into view. (xwidget-log "scroll: %d" y3) (set-window-vscroll (selected-window) y3 t))) @@ -431,7 +428,7 @@ Argument ELEMENT-ID is either a name or an element id." (defun xwidget-webkit-adjust-size-to-window () "Adjust webkit to window." (interactive) - (xwidget-resize ( xwidget-webkit-current-session) (window-pixel-width) + (xwidget-resize (xwidget-webkit-current-session) (window-pixel-width) (window-pixel-height))) (defun xwidget-webkit-adjust-size (w h) @@ -440,7 +437,7 @@ Argument W width. Argument H height." ;; TODO shouldn't be tied to the webkit xwidget (interactive "nWidth:\nnHeight:\n") - (xwidget-resize ( xwidget-webkit-current-session) w h)) + (xwidget-resize (xwidget-webkit-current-session) w h)) (defun xwidget-webkit-fit-width () "Adjust width of webkit to window width." @@ -460,7 +457,7 @@ Argument H height." (setq xw (xwidget-insert 1 'webkit-osr bufname 1000 1000)) (xwidget-put xw 'callback 'xwidget-webkit-callback) (xwidget-webkit-mode) - (xwidget-webkit-goto-uri (xwidget-webkit-last-session) url ))) + (xwidget-webkit-goto-uri (xwidget-webkit-last-session) url))) (defun xwidget-webkit-goto-url (url) @@ -488,7 +485,7 @@ Argument H height." (let* ((rv (xwidget-webkit-execute-script-rv (xwidget-webkit-current-session) "document.URL")) (url (kill-new (or rv "")))) - (message "url: %s" url ) + (message "url: %s" url) url)) (defun xwidget-webkit-execute-script-rv (xw script &optional default) @@ -565,23 +562,19 @@ It can be retrieved with `(xwidget-get XWIDGET PROPNAME)'." ;; Redraw display otherwise ghost of zombies will remain to haunt the screen (redraw-display)) -;; This would have felt better in C, but this seems to work well in -;; practice though. -(if (featurep 'xwidget-internal) - (add-hook 'window-configuration-change-hook 'xwidget-delete-zombies)) - (defun xwidget-kill-buffer-query-function () "Ask before killing a buffer that has xwidgets." (let ((xwidgets (get-buffer-xwidgets (current-buffer)))) (or (not xwidgets) - (not (memq t (mapcar 'xwidget-query-on-exit-flag xwidgets))) + (not (memq t (mapcar #'xwidget-query-on-exit-flag xwidgets))) (yes-or-no-p - (format "Buffer %S has xwidgets; kill it? " - (buffer-name (current-buffer))))))) + (format "Buffer %S has xwidgets; kill it? " (buffer-name)))))) -(if (featurep 'xwidget-internal) - (add-hook 'kill-buffer-query-functions 'xwidget-kill-buffer-query-function)) +(when (featurep 'xwidget-internal) + (add-hook 'kill-buffer-query-functions #'xwidget-kill-buffer-query-function) + ;; This would have felt better in C, but this seems to work well in + ;; practice though. + (add-hook 'window-configuration-change-hook #'xwidget-delete-zombies)) (provide 'xwidget) - ;;; xwidget.el ends here From 65575c24aaad9bedf6b84cc062cc03fbe4dd1315 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Wed, 20 Jan 2016 15:09:09 +0200 Subject: [PATCH 24/36] Fix doc string of 'isearch-search-fun-function' * lisp/isearch.el (isearch-search-fun-function) (isearch-search-string): Doc fixes. (Bug#22411) --- lisp/isearch.el | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) 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." "Non-default value overrides the behavior of `isearch-search-fun-default'. This variable's value should be a function, which will be called with no arguments, and should return a function that takes three -arguments: STRING, BOUND, and NOERROR. +arguments: STRING, BOUND, and NOERROR. See `re-search-forward' +for the meaning of BOUND and NOERROR arguments. This returned function will be used by `isearch-search-string' to -search for the first occurrence of STRING or its translation.") +search for the first occurrence of STRING.") (defun isearch-search-fun () "Return the function to use for the search. @@ -2695,8 +2696,14 @@ Can be changed via `isearch-search-fun-function' for special needs." (defun isearch-search-string (string bound noerror) "Search for the first occurrence of STRING or its translation. +STRING's characters are translated using `translation-table-for-input' +if that is non-nil. If found, move point to the end of the occurrence, -update the match data, and return point." +update the match data, and return point. +An optional second argument bounds the search; it is a buffer position. +The match found must not extend after that position. +Optional third argument, if t, means if fail just return nil (no error). + If not nil and not t, move to limit of search and return nil." (let* ((func (isearch-search-fun)) (pos1 (save-excursion (funcall func string bound noerror))) pos2) From 2388fa74982a9146e4bcefc75004ec9d7241c505 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 20 Jan 2016 11:06:01 -0800 Subject: [PATCH 25/36] Port to platforms with gtk3 but not webkitgtk3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I ran into this problem on my Fedora 23 installation; Emacs configured but did not build when --with-xwidgets was specified. * configure.ac (HAVE_WEBKIT, HAVE_GIR): Omit unnecessary initializations. (DOES_XWIDGETS_USE_GIR): New var. If --with-xwidgets is specified, report an error if not doable, to be consistent with the other --with options. Require webkitgtk3 to use Xwidgets, as the Xwidgets code does not work at all without webkitgtk3. Simplify use of EMACS_CHECK_MODULES. Output message about gobject introspection only if xwidgets are used. * etc/NEWS: Users need webkitgtk3, not merely webkit. * src/xwidget.c (syms_of_xwidget): Don’t worry about HAVE_WEBKIT_OSR, since this file is no longer compiled if webkitgtk3 is not available. --- configure.ac | 35 +++++++++++++++-------------------- etc/NEWS | 2 +- src/xwidget.c | 2 -- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/configure.ac b/configure.ac index 3b87fad60b6..a344b28c68a 100644 --- a/configure.ac +++ b/configure.ac @@ -2566,35 +2566,32 @@ if test "${HAVE_GTK}" = "yes"; then fi +dnl Enable xwidgets if GTK3 and WebKitGTK+ are available. HAVE_XWIDGETS=no -HAVE_WEBKIT=no -HAVE_GIR=no XWIDGETS_OBJ= -if test "$with_xwidgets" != "no" && test "$USE_GTK_TOOLKIT" = "GTK3" && - test "$window_system" != "none" -then - HAVE_XWIDGETS=yes - AC_DEFINE([HAVE_XWIDGETS], 1, [Define to 1 if you have xwidgets support.]) +DOES_XWIDGETS_USE_GIR= +if test "$with_xwidgets" != "no"; then + test "$USE_GTK_TOOLKIT" = "GTK3" && test "$window_system" != "none" || + AC_MSG_ERROR([xwidgets requested but gtk3 not used.]) - dnl xwidgets - dnl - enable only if GTK3 is enabled, and we have a window system - dnl - check for webkit and gobject introspection - dnl webkit version for gtk3. WEBKIT_REQUIRED=1.4.0 WEBKIT_MODULES="webkitgtk-3.0 >= $WEBKIT_REQUIRED" + EMACS_CHECK_MODULES([WEBKIT], [$WEBKIT_MODULES]) + HAVE_XWIDGETS=$HAVE_WEBKIT + test $HAVE_XWIDGETS = yes || + AC_MSG_ERROR([xwidgets requested but WebKitGTK+ not found.]) - EMACS_CHECK_MODULES(WEBKIT, $WEBKIT_MODULES, HAVE_WEBKIT=yes, HAVE_WEBKIT=no) - if test $HAVE_WEBKIT = yes; then - AC_DEFINE([HAVE_WEBKIT_OSR], 1, [Define to 1 if you have webkit_osr support.]) - fi + XWIDGETS_OBJ=xwidget.o + AC_DEFINE([HAVE_XWIDGETS], 1, [Define to 1 if you have xwidgets support.]) GIR_REQUIRED=1.32.1 GIR_MODULES="gobject-introspection-1.0 >= $GIR_REQUIRED" - EMACS_CHECK_MODULES(GIR, $GIR_MODULES, HAVE_GIR=yes, HAVE_GIR=no) + EMACS_CHECK_MODULES([GIR], [$GIR_MODULES]) if test $HAVE_GIR = yes; then AC_DEFINE([HAVE_GIR], 1, [Define to 1 if you have GIR support.]) fi - XWIDGETS_OBJ=xwidget.o + DOES_XWIDGETS_USE_GIR="\ + Does Xwidgets use gobject introspection? $HAVE_GIR" fi AC_SUBST(XWIDGETS_OBJ) @@ -5305,9 +5302,7 @@ AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D Does Emacs have dynamic modules support? ${HAVE_MODULES} Does Emacs use toolkit scroll bars? ${USE_TOOLKIT_SCROLL_BARS} Does Emacs support Xwidgets (requires gtk3)? ${HAVE_XWIDGETS} - Does xwidgets support webkit? ${HAVE_WEBKIT} - Does xwidgets support gobject introspection? ${HAVE_GIR} -"]) +${DOES_XWIDGETS_USE_GIR}"]) if test -n "${EMACSDATA}"; then AS_ECHO([" Environment variable EMACSDATA set to: $EMACSDATA"]) diff --git a/etc/NEWS b/etc/NEWS index 934bc3f0859..06b32ce9ccc 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -121,7 +121,7 @@ and can contain escape sequences for command keys, quotes, and the like. * Changes in Emacs 25.1 ** Xwidgets: a new feature for embedding native widgets inside Emacs buffers. -If you have gtk3 and webkit-devel installed, you can access the +If you have gtk3 and webkitgtk3 installed, you can access the embedded webkit browser with `M-x xwidget-webkit-browse-url'. This opens a new buffer with the embedded browser. The buffer will have a new mode, `xwidget-webkit-mode' (similar to `image-mode'), diff --git a/src/xwidget.c b/src/xwidget.c index 88cdb941c4c..f8e13cd4522 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -1077,12 +1077,10 @@ syms_of_xwidget (void) defsubr (&Sxwidget_query_on_exit_flag); defsubr (&Sset_xwidget_query_on_exit_flag); -#ifdef HAVE_WEBKIT_OSR defsubr (&Sxwidget_webkit_goto_uri); defsubr (&Sxwidget_webkit_execute_script); defsubr (&Sxwidget_webkit_get_title); DEFSYM (Qwebkit_osr, "webkit-osr"); -#endif defsubr (&Sxwidget_size_request); defsubr (&Sdelete_xwidget_view); From 4db94245d014d12ca2964d4c15c31ec3f8dabb76 Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Wed, 20 Jan 2016 14:50:02 -0500 Subject: [PATCH 26/36] * configure.ac (emacs_config_features): Remove WEBKIT. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index a344b28c68a..aac3cf28099 100644 --- a/configure.ac +++ b/configure.ac @@ -5251,7 +5251,7 @@ emacs_config_features= for opt in XAW3D XPM JPEG TIFF GIF PNG RSVG CAIRO IMAGEMAGICK SOUND GPM DBUS \ GCONF GSETTINGS NOTIFY ACL LIBSELINUX GNUTLS LIBXML2 FREETYPE M17N_FLT \ LIBOTF XFT ZLIB TOOLKIT_SCROLL_BARS X_TOOLKIT X11 NS MODULES \ - XWIDGETS WEBKIT GIR; do + XWIDGETS GIR; do case $opt in NOTIFY|ACL) eval val=\${${opt}_SUMMARY} ;; From 6a9399f7fd3ea6f4eaa0c6ceee92308553fadd39 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Thu, 21 Jan 2016 00:26:05 +0300 Subject: [PATCH 27/36] Support squiggly heredocs in ruby-mode * lisp/progmodes/ruby-mode.el (ruby-here-doc-beg-re): Support squiggly heredocs added in Ruby 2.3. * test/indent/ruby.rb: Add squiggly example. --- lisp/progmodes/ruby-mode.el | 2 +- test/indent/ruby.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) 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 @@ (eval-and-compile (defconst ruby-here-doc-beg-re - "\\(<\\)<\\(-\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)" + "\\(<\\)<\\([~-]\\)?\\(\\([a-zA-Z0-9_]+\\)\\|[\"]\\([^\"]+\\)[\"]\\|[']\\([^']+\\)[']\\)" "Regexp to match the beginning of a heredoc.") (defconst ruby-expression-expansion-re diff --git a/test/indent/ruby.rb b/test/indent/ruby.rb index dec6de98605..dfd1c75a679 100644 --- a/test/indent/ruby.rb +++ b/test/indent/ruby.rb @@ -4,6 +4,10 @@ end eowarn foo + + foo(<<~squiggly) + end + squiggly end def foo From 9d7265ba1a3f93e107a88c3fc4b76557e36192b5 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 20 Jan 2016 14:55:09 -0800 Subject: [PATCH 28/36] =?UTF-8?q?Don=E2=80=99t=20export=20C=20symbols=20no?= =?UTF-8?q?t=20used=20elsewhere?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These were recently added, mostly as part of xwidget code. * src/emacsgtkfixed.c (emacs_fixed_get_type): Now static. (EMACS_FIXED, EMACS_FIXED_GET_CLASS): Now static functions here, not macros in emacsgtkfixed.h. * src/emacsgtkfixed.h (EMACS_TYPE_FIXED): Remove. All uses replaced by definiens. (EMACS_FIXED, EMACS_FIXED_GET_CLASS): Remove; these are now static functions in emacsgtkfixed.c. (EMACS_FIXED_CLASS, EMACS_IS_FIXED, EMACS_IS_FIXED_CLASS): Remove; unused. (emacs_fixed_get_type): Remove decl; no longer extern. * src/xwidget.c (offscreen_damage_event) (webkit_mime_type_policy_typedecision_requested_cb) (webkit_new_window_policy_decision_requested_cb) (webkit_navigation_policy_decision_requested_cb) (xwidget_spec_value, xwidget_view_lookup) (xwidget_start_redisplay, xwidget_touch): Now static. * src/xwidget.h (xwidget_start_redisplay, xwidget_touch): Remove decls. --- src/emacsgtkfixed.c | 20 ++++++++++++++++++-- src/emacsgtkfixed.h | 8 -------- src/xwidget.c | 36 +++++++++++++++++------------------- src/xwidget.h | 3 --- 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c index da1017df2ae..08b840389c5 100644 --- a/src/emacsgtkfixed.c +++ b/src/emacsgtkfixed.c @@ -50,10 +50,26 @@ static void emacs_fixed_get_preferred_width (GtkWidget *widget, static void emacs_fixed_get_preferred_height (GtkWidget *widget, gint *minimum, gint *natural); + +static GType emacs_fixed_get_type (void); G_DEFINE_TYPE (EmacsFixed, emacs_fixed, GTK_TYPE_FIXED) +static EmacsFixed * +EMACS_FIXED (GtkWidget *widget) +{ + return G_TYPE_CHECK_INSTANCE_CAST (widget, emacs_fixed_get_type (), + EmacsFixed); +} + #ifdef HAVE_XWIDGETS +static EmacsFixedClass * +EMACS_FIXED_GET_CLASS (GtkWidget *widget) +{ + return G_TYPE_INSTANCE_GET_CLASS (widget, emacs_fixed_get_type (), + EmacsFixedClass); +} + struct GtkFixedPrivateL { GList *children; @@ -151,7 +167,7 @@ emacs_fixed_class_init (EmacsFixedClass *klass) static void emacs_fixed_init (EmacsFixed *fixed) { - fixed->priv = G_TYPE_INSTANCE_GET_PRIVATE (fixed, EMACS_TYPE_FIXED, + fixed->priv = G_TYPE_INSTANCE_GET_PRIVATE (fixed, emacs_fixed_get_type (), EmacsFixedPrivate); fixed->priv->f = 0; } @@ -166,7 +182,7 @@ emacs_fixed_init (EmacsFixed *fixed) GtkWidget* emacs_fixed_new (struct frame *f) { - EmacsFixed *fixed = g_object_new (EMACS_TYPE_FIXED, NULL); + EmacsFixed *fixed = g_object_new (emacs_fixed_get_type (), NULL); EmacsFixedPrivate *priv = fixed->priv; priv->f = f; return GTK_WIDGET (fixed); diff --git a/src/emacsgtkfixed.h b/src/emacsgtkfixed.h index 5b2fa566785..378bd2b828c 100644 --- a/src/emacsgtkfixed.h +++ b/src/emacsgtkfixed.h @@ -29,13 +29,6 @@ G_BEGIN_DECLS struct frame; -#define EMACS_TYPE_FIXED (emacs_fixed_get_type ()) -#define EMACS_FIXED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMACS_TYPE_FIXED, EmacsFixed)) -#define EMACS_FIXED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EMACS_TYPE_FIXED, EmacsFixedClass)) -#define EMACS_IS_FIXED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMACS_TYPE_FIXED)) -#define EMACS_IS_FIXED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EMACS_TYPE_FIXED)) -#define EMACS_FIXED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EMACS_TYPE_FIXED, EmacsFixedClass)) - //typedef struct _EmacsFixed EmacsFixed; typedef struct _EmacsFixedPrivate EmacsFixedPrivate; typedef struct _EmacsFixedClass EmacsFixedClass; @@ -55,7 +48,6 @@ struct _EmacsFixedClass }; extern GtkWidget *emacs_fixed_new (struct frame *f); -extern GType emacs_fixed_get_type (void); G_END_DECLS diff --git a/src/xwidget.c b/src/xwidget.c index f8e13cd4522..ea5dea0f9fe 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -123,14 +123,13 @@ allocate_xwidget_view (void) #define XSETXWIDGET(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET)) #define XSETXWIDGET_VIEW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET_VIEW)) -struct xwidget_view *xwidget_view_lookup (struct xwidget *, struct window *); -Lisp_Object xwidget_spec_value (Lisp_Object , Lisp_Object , int *); -gboolean offscreen_damage_event (GtkWidget * , GdkEvent * , gpointer ); -void webkit_document_load_finished_cb (WebKitWebView *, WebKitWebFrame *, - gpointer ); -gboolean webkit_download_cb (WebKitWebView *, WebKitDownload *, gpointer); +static struct xwidget_view *xwidget_view_lookup (struct xwidget *, + struct window *); +static void webkit_document_load_finished_cb (WebKitWebView *, WebKitWebFrame *, + gpointer); +static gboolean webkit_download_cb (WebKitWebView *, WebKitDownload *, gpointer); -gboolean +static gboolean webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *, WebKitWebFrame *, WebKitNetworkRequest *, @@ -138,7 +137,7 @@ webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *, WebKitWebPolicyDecision *, gpointer); -gboolean +static gboolean webkit_new_window_policy_decision_requested_cb (WebKitWebView *, WebKitWebFrame *, WebKitNetworkRequest *, @@ -146,7 +145,7 @@ webkit_new_window_policy_decision_requested_cb (WebKitWebView *, WebKitWebPolicyDecision *, gpointer); -gboolean +static gboolean webkit_navigation_policy_decision_requested_cb (WebKitWebView *, WebKitWebFrame *, WebKitNetworkRequest *, @@ -261,8 +260,7 @@ Returns the newly constructed xwidget, or nil if construction fails. */) { g_signal_connect (G_OBJECT (xw->widget_osr), "document-load-finished", - G_CALLBACK - (webkit_document_load_finished_cb), xw); + G_CALLBACK (webkit_document_load_finished_cb), xw); g_signal_connect (G_OBJECT (xw->widget_osr), "download-requested", @@ -352,7 +350,7 @@ xwidget_hide_view (struct xwidget_view *xv) /* When the off-screen webkit master view changes this signal is called. It copies the bitmap from the off-screen instance. */ -gboolean +static gboolean offscreen_damage_event (GtkWidget * widget, GdkEvent * event, gpointer xv_widget) { @@ -415,7 +413,7 @@ webkit_download_cb (WebKitWebView * webkitwebview, return FALSE; } -gboolean +static gboolean webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *webView, WebKitWebFrame *frame, WebKitNetworkRequest * request, @@ -438,7 +436,7 @@ webkit_mime_type_policy_typedecision_requested_cb (WebKitWebView *webView, } -gboolean +static gboolean webkit_new_window_policy_decision_requested_cb (WebKitWebView *webView, WebKitWebFrame *frame, WebKitNetworkRequest *request, @@ -456,7 +454,7 @@ webkit_new_window_policy_decision_requested_cb (WebKitWebView *webView, return FALSE; } -gboolean +static gboolean webkit_navigation_policy_decision_requested_cb (WebKitWebView *webView, WebKitWebFrame *frame, WebKitNetworkRequest *request, @@ -1138,7 +1136,7 @@ valid_xwidget_spec_p (Lisp_Object object) /* Find a value associated with key in spec. */ -Lisp_Object +static Lisp_Object xwidget_spec_value (Lisp_Object spec, Lisp_Object key, int *found) { Lisp_Object tail; @@ -1180,7 +1178,7 @@ xwidget_view_delete_all_in_window (struct window *w) } } -struct xwidget_view * +static struct xwidget_view * xwidget_view_lookup (struct xwidget *xw, struct window *w) { Lisp_Object xwidget, window, ret; @@ -1210,7 +1208,7 @@ lookup_xwidget (Lisp_Object spec) } /* Set up detection of touched xwidget */ -void +static void xwidget_start_redisplay (void) { for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); @@ -1223,7 +1221,7 @@ xwidget_start_redisplay (void) /* The xwidget was touched during redisplay, so it isn't a candidate for hiding. */ -void +static void xwidget_touch (struct xwidget_view *xv) { xv->redisplayed = 1; diff --git a/src/xwidget.h b/src/xwidget.h index 4dffaa4750d..fdcf40d8cbb 100644 --- a/src/xwidget.h +++ b/src/xwidget.h @@ -121,11 +121,8 @@ struct xwidget_type struct xwidget *xwidget_from_id (int id); -void xwidget_start_redisplay (void); void xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix); -void xwidget_touch (struct xwidget_view *xw); - struct xwidget *lookup_xwidget (Lisp_Object spec); #define XG_XWIDGET "emacs_xwidget" #define XG_XWIDGET_VIEW "emacs_xwidget_view" From 871c8b1b96c1cffb84d30dddd484663a0c94818f Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 20 Jan 2016 15:28:30 -0800 Subject: [PATCH 29/36] No need to configure gobject-introspection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It wasn’t needed for the recently-installed xwidget_mvp code; see: http://lists.gnu.org/archive/html/emacs-devel/2016-01/msg01154.html * configure.ac (DOES_XWIDGETS_USE_GIR, GIR_REQUIRED, GIR_MODULES): (HAVE_GIR): * src/Makefile.in (GIR_LIBS, GIR_CFLAGS): Remove. All uses removed. * configure.ac (emacs_config_features): Don’t worry about GIR. --- configure.ac | 14 ++------------ src/Makefile.in | 6 ++---- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index aac3cf28099..b5e6b77c713 100644 --- a/configure.ac +++ b/configure.ac @@ -2569,7 +2569,6 @@ fi dnl Enable xwidgets if GTK3 and WebKitGTK+ are available. HAVE_XWIDGETS=no XWIDGETS_OBJ= -DOES_XWIDGETS_USE_GIR= if test "$with_xwidgets" != "no"; then test "$USE_GTK_TOOLKIT" = "GTK3" && test "$window_system" != "none" || AC_MSG_ERROR([xwidgets requested but gtk3 not used.]) @@ -2583,15 +2582,6 @@ if test "$with_xwidgets" != "no"; then XWIDGETS_OBJ=xwidget.o AC_DEFINE([HAVE_XWIDGETS], 1, [Define to 1 if you have xwidgets support.]) - - GIR_REQUIRED=1.32.1 - GIR_MODULES="gobject-introspection-1.0 >= $GIR_REQUIRED" - EMACS_CHECK_MODULES([GIR], [$GIR_MODULES]) - if test $HAVE_GIR = yes; then - AC_DEFINE([HAVE_GIR], 1, [Define to 1 if you have GIR support.]) - fi - DOES_XWIDGETS_USE_GIR="\ - Does Xwidgets use gobject introspection? $HAVE_GIR" fi AC_SUBST(XWIDGETS_OBJ) @@ -5251,7 +5241,7 @@ emacs_config_features= for opt in XAW3D XPM JPEG TIFF GIF PNG RSVG CAIRO IMAGEMAGICK SOUND GPM DBUS \ GCONF GSETTINGS NOTIFY ACL LIBSELINUX GNUTLS LIBXML2 FREETYPE M17N_FLT \ LIBOTF XFT ZLIB TOOLKIT_SCROLL_BARS X_TOOLKIT X11 NS MODULES \ - XWIDGETS GIR; do + XWIDGETS; do case $opt in NOTIFY|ACL) eval val=\${${opt}_SUMMARY} ;; @@ -5302,7 +5292,7 @@ AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D Does Emacs have dynamic modules support? ${HAVE_MODULES} Does Emacs use toolkit scroll bars? ${USE_TOOLKIT_SCROLL_BARS} Does Emacs support Xwidgets (requires gtk3)? ${HAVE_XWIDGETS} -${DOES_XWIDGETS_USE_GIR}"]) +"]) if test -n "${EMACSDATA}"; then AS_ECHO([" Environment variable EMACSDATA set to: $EMACSDATA"]) diff --git a/src/Makefile.in b/src/Makefile.in index 2b5ae30a704..4a52757fec6 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -225,8 +225,6 @@ RSVG_CFLAGS= @RSVG_CFLAGS@ WEBKIT_LIBS= @WEBKIT_LIBS@ WEBKIT_CFLAGS= @WEBKIT_CFLAGS@ -GIR_LIBS= @GIR_LIBS@ -GIR_CFLAGS= @GIR_CFLAGS@ CAIRO_LIBS= @CAIRO_LIBS@ CAIRO_CFLAGS= @CAIRO_CFLAGS@ @@ -366,7 +364,7 @@ ALL_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \ $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \ $(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \ $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \ - $(WEBKIT_CFLAGS) $(GIR_CFLAGS) \ + $(WEBKIT_CFLAGS) \ $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \ $(LIBGNUTLS_CFLAGS) $(GFILENOTIFY_CFLAGS) $(CAIRO_CFLAGS) \ @@ -477,7 +475,7 @@ lisp = $(addprefix ${lispsource}/,${shortlisp}) LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ $(LIBX_OTHER) $(LIBSOUND) \ $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \ - $(WEBKIT_LIBS) $(GIR_LIBS) \ + $(WEBKIT_LIBS) \ $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \ $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \ $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) $(CAIRO_LIBS) \ From 7bc7fd6058a28cdf7da672dc625c6d3f2e50aa1b Mon Sep 17 00:00:00 2001 From: Stephen Berman Date: Thu, 21 Jan 2016 11:19:21 +0100 Subject: [PATCH 30/36] Fix desktop support in todo-mode and doc-view (bug#22377) * lisp/calendar/todo-mode.el (todo-restore-desktop-buffer): * lisp/doc-view.el (doc-view-restore-desktop-buffer): Return current buffer. * lisp/calendar/todo-mode.el (todo-modes-set-2): * lisp/doc-view.el (doc-view-mode): Set desktop-save-buffer unconditionally. --- lisp/calendar/todo-mode.el | 6 +++--- lisp/doc-view.el | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el index 353ca69a1ba..ebf0a82be0c 100644 --- a/lisp/calendar/todo-mode.el +++ b/lisp/calendar/todo-mode.el @@ -5230,7 +5230,8 @@ Also preserve category display, if applicable." (with-current-buffer buffer (widen) (let ((todo-category-number (cdr (assq 'catnum misc)))) - (todo-category-select)))) + (todo-category-select) + (current-buffer)))) (add-to-list 'desktop-buffer-mode-handlers '(todo-mode . todo-restore-desktop-buffer)) @@ -6579,8 +6580,7 @@ Added to `window-configuration-change-hook' in Todo mode." "Make some settings that apply to multiple Todo modes." (add-to-invisibility-spec 'todo) (setq buffer-read-only t) - (when (and (boundp 'desktop-save-mode) desktop-save-mode) - (setq-local desktop-save-buffer 'todo-desktop-save-buffer)) + (setq-local desktop-save-buffer 'todo-desktop-save-buffer) (when (boundp 'hl-line-range-function) (setq-local hl-line-range-function (lambda() (save-excursion diff --git a/lisp/doc-view.el b/lisp/doc-view.el index 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." ;; window-parameters in the window-state(s) and then restoring this ;; window-state should call us back (to interpret/use those parameters). (doc-view-goto-page page) - (when slice (apply 'doc-view-set-slice slice))))) + (when slice (apply 'doc-view-set-slice slice)) + (current-buffer)))) (add-to-list 'desktop-buffer-mode-handlers '(doc-view-mode . doc-view-restore-desktop-buffer)) @@ -1788,9 +1789,7 @@ toggle between displaying the document or editing it as text. nil t) (add-hook 'clone-indirect-buffer-hook 'doc-view-clone-buffer-hook nil t) (add-hook 'kill-buffer-hook 'doc-view-kill-proc nil t) - (when (and (boundp 'desktop-save-mode) - desktop-save-mode) - (setq-local desktop-save-buffer 'doc-view-desktop-save-buffer)) + (setq-local desktop-save-buffer 'doc-view-desktop-save-buffer) (remove-overlays (point-min) (point-max) 'doc-view t) ;Just in case. ;; Keep track of display info ([vh]scroll, page number, overlay, From 5293d1bdb3e665a565af032a163004c976328cc2 Mon Sep 17 00:00:00 2001 From: Stephen Berman Date: Thu, 21 Jan 2016 12:01:12 +0100 Subject: [PATCH 31/36] Avoid byte-compiler warning in todo-mode (bug#21953) * todo-mode.el (todo-convert-legacy-files): Add limit argument to looking-back to comply with advertised-calling-convention. --- lisp/calendar/todo-mode.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el index ebf0a82be0c..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 (goto-char (match-beginning 0)) (goto-char (point-max))) (backward-char) - (when (looking-back "\\[\\([^][]+\\)\\]") + (when (looking-back "\\[\\([^][]+\\)\\]" + (line-beginning-position)) (setq cat (match-string 1)) (goto-char (match-beginning 0)) (replace-match "")) ;; If the item ends with a non-comment parenthesis not ;; followed by a period, we lose (but we inherit that ;; problem from the legacy code). + ;; FIXME: fails on multiline comment (when (looking-back "(\\(.*\\)) " (line-beginning-position)) (setq comment (match-string 1)) (replace-match "") From 4763c774c31deaab83f65a2499a0e39ca4207eeb Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Thu, 21 Jan 2016 22:07:19 -0800 Subject: [PATCH 32/36] Write a new docstring for the pcase macro * lisp/emacs-lisp/pcase.el (pcase): Write a new docstring. --- lisp/emacs-lisp/pcase.el | 46 ++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el index 3b224814e9e..9d88e87f040 100644 --- a/lisp/emacs-lisp/pcase.el +++ b/lisp/emacs-lisp/pcase.el @@ -107,12 +107,37 @@ ;;;###autoload (defmacro pcase (exp &rest cases) - "Eval EXP and perform ML-style pattern matching on that value. + "Evaluate EXP and attempt to match it against structural patterns. CASES is a list of elements of the form (PATTERN CODE...). -Patterns can take the following forms: +A structural PATTERN describes a template that identifies a class +of values. For example, the pattern (foo bar) matches any two +element list, binding its elements to symbols named `foo' and +`bar' -- in much the same way that `cl-destructuring-bind' would. + +A significant difference from `cl-destructuring-bind' is that, if +a pattern match fails, the next case is tried until either a +succesful match is found or there are no more cases. + +Another difference is that pattern elements may be quoted, +meaning they must match exactly: The pattern (\\='foo \\='bar) +matches only against two element lists containing the symbols +`foo' and `bar' in that order. (As a short-hand, atoms always +match themselves, such as numbers or strings, and need not be +quoted). + +Lastly, a pattern can be logical, such as (pred numberp), that +matches any number-like element; or the symbol `_', that matches +anything. Patterns may also be backquoted (with \\=`), so that +comma (\\=,) can be used to introduce logical patterns inside +quoted patterns. + +The complete list of standard patterns is as follows: + _ matches anything. SYMBOL matches anything and binds it to SYMBOL. + If a SYMBOL is used twice in the same pattern + the second occurrence becomes an `eq'uality test. (or PAT...) matches if any of the patterns matches. (and PAT...) matches if all the patterns match. \\='VAL matches if the object is `equal' to VAL. @@ -122,23 +147,18 @@ Patterns can take the following forms: (guard BOOLEXP) matches if BOOLEXP evaluates to non-nil. (let PAT EXP) matches if EXP matches PAT. (app FUN PAT) matches if FUN applied to the object matches PAT. -If a SYMBOL is used twice in the same pattern (i.e. the pattern is -\"non-linear\"), then the second occurrence is turned into an `eq'uality test. -FUN can take the form +Additional patterns may be defined using `pcase-defmacro'. + +The FUN argument in the `app' pattern may have the following forms: SYMBOL or (lambda ARGS BODY) in which case it's called with one argument. (F ARG1 .. ARGn) in which case F gets called with an n+1'th argument which is the value being matched. -So a FUN of the form SYMBOL is equivalent to one of the form (FUN). +So a FUN of the form SYMBOL is equivalent to (FUN). FUN can refer to variables bound earlier in the pattern. -E.g. you can match pairs where the cdr is larger than the car with a pattern -like \\=`(,a . ,(pred (< a))) or, with more checks: -\\=`(,(and a (pred numberp)) . ,(and (pred numberp) (pred (< a)))) -FUN is assumed to be pure, i.e. it can be dropped if its result is not used, -and two identical calls can be merged into one. -Additional patterns can be defined via `pcase-defmacro'. -Currently, the following patterns are provided this way:" +See Info node `(elisp) Pattern matching case statement' in the +Emacs Lisp manual for more information and examples." (declare (indent 1) (debug (form &rest (pcase-PAT body)))) ;; We want to use a weak hash table as a cache, but the key will unavoidably ;; be based on `exp' and `cases', yet `cases' is a fresh new list each time From fb7c5812fb5e082ac92fb2b50e51a252eea5ef90 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Thu, 21 Jan 2016 23:28:50 -0800 Subject: [PATCH 33/36] Minor correction to pcase docstring --- lisp/emacs-lisp/pcase.el | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el index 9d88e87f040..a2e05245c31 100644 --- a/lisp/emacs-lisp/pcase.el +++ b/lisp/emacs-lisp/pcase.el @@ -119,7 +119,7 @@ A significant difference from `cl-destructuring-bind' is that, if a pattern match fails, the next case is tried until either a succesful match is found or there are no more cases. -Another difference is that pattern elements may be quoted, +Another difference is that pattern elements may be backquoted, meaning they must match exactly: The pattern (\\='foo \\='bar) matches only against two element lists containing the symbols `foo' and `bar' in that order. (As a short-hand, atoms always @@ -128,9 +128,8 @@ quoted). Lastly, a pattern can be logical, such as (pred numberp), that matches any number-like element; or the symbol `_', that matches -anything. Patterns may also be backquoted (with \\=`), so that -comma (\\=,) can be used to introduce logical patterns inside -quoted patterns. +anything. Also, when patterns are backquoted, a comma may be +used to introduce logical patterns inside backquoted patterns. The complete list of standard patterns is as follows: @@ -148,7 +147,7 @@ The complete list of standard patterns is as follows: (let PAT EXP) matches if EXP matches PAT. (app FUN PAT) matches if FUN applied to the object matches PAT. -Additional patterns may be defined using `pcase-defmacro'. +Additional patterns can be defined using `pcase-defmacro'. The FUN argument in the `app' pattern may have the following forms: SYMBOL or (lambda ARGS BODY) in which case it's called with one argument. From 44c7b49d9a8188e8befc85f7e95d074ad4605c6a Mon Sep 17 00:00:00 2001 From: Stephen Leake Date: Fri, 22 Jan 2016 01:53:05 -0600 Subject: [PATCH 34/36] In xref-collect-references, force backends to respect the 'dir' arg * lisp/progmodes/xref.el (xref-collect-references): Force symref backends to use `default-directory'. --- lisp/progmodes/xref.el | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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." (cl-assert (directory-name-p dir)) (require 'semantic/symref) (defvar semantic-symref-tool) - (let* ((default-directory dir) + + ;; Some symref backends use `ede-project-root-directory' as the root + ;; directory for the search, rather than `default-directory'. Since + ;; the caller has specified `dir', we bind `ede-minor-mode' to nil + ;; to force the backend to use `default-directory'. + (let* ((ede-minor-mode nil) + (default-directory dir) (semantic-symref-tool 'detect) (res (semantic-symref-find-references-by-name symbol 'subdirs)) (hits (and res (oref res hit-lines))) From 669d30b2173dfbfe9658320baf79e1b504fb89b1 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 22 Jan 2016 12:20:11 +0200 Subject: [PATCH 35/36] * doc/emacs/anti.texi (Antinews): Rewrite for Emacs 25. --- doc/emacs/anti.texi | 253 ++++++++++++++++++++++++++++++------------- doc/emacs/emacs.texi | 2 +- 2 files changed, 180 insertions(+), 75 deletions(-) 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 @@ +@c -*- coding: utf-8 -*- @c This is part of the Emacs manual. @c Copyright (C) 2005-2016 Free Software Foundation, Inc. @c See file emacs.texi for copying conditions. @node Antinews -@appendix Emacs 23 Antinews +@appendix Emacs 24 Antinews @c Update the emacs.texi Antinews menu entry with the above version number. For those users who live backwards in time, here is information -about downgrading to Emacs version 23.4. We hope you will enjoy the +about downgrading to Emacs version 24.5. We hope you will enjoy the greater simplicity that results from the absence of many Emacs @value{EMACSVER} features. @itemize @bullet @item -Support for displaying and editing ``bidirectional'' text has been -removed. Text is now always displayed on the screen in a single -consistent direction---left to right---regardless of the underlying -script. Similarly, @kbd{C-f} and @kbd{C-b} always move the text -cursor to the right and left respectively. Also, @key{RIGHT} and -@key{LEFT} are now equivalent to @kbd{C-f} and @kbd{C-b}, as you might -expect, rather than moving forward or backward based on the underlying -``paragraph direction''. - -Users of right-to-left languages, like Arabic and Hebrew, may -adapt by reading and/or editing text in left-to-right order. +Support for Cairo drawing has been removed. On GNU and Unix systems, +you now have only one drawing engine---the venerable X Window system. +No need to procrastinate on the dilemma whether you do or don't want +the new shiny Cairo thing. Hail, simplicity! @item -The Emacs Lisp package manager has been removed. Instead of using a -user interface (@kbd{M-x list-packages}), additional Lisp packages -must now be installed by hand, which is the most flexible and -``Lispy'' method anyway. Typically, this just involves editing your -init file to add the package installation directory to the load path -and defining some autoloads; see each package's commentary section -and/or README file for details. +Emacs still works on SGI IRIX systems. if you live backwards in time, +this is actually a bonus, as IRIX systems will become more and more +popular as you move farther back in time. @item -The option @code{delete-active-region} has been deleted. When the -region is active, typing @key{DEL} or @key{Delete} no longer deletes -the text in the region; it deletes a single character instead. +Support for dynamically loaded modules has been removed. You get to +use only the trusted Emacs codebase, with no additions. Those +external modules written by some J.R. Hacker cannot be trusted anyway. +Good riddance! @item -We have reworked how Emacs handles the clipboard and the X primary -selection. Commands for killing and yanking, like @kbd{C-w} and -@kbd{C-y}, use the primary selection and not the clipboard, so you can -use these commands without interfering with ``cutting'' or ``pasting'' -in other programs. The @samp{Cut}/@samp{Copy}/@samp{Paste} menu items -are bound to separate clipboard commands, not to the same commands as -@kbd{C-w}/@kbd{M-w}/@kbd{C-y}. - -Selecting text by dragging with the mouse now puts the text in the -kill ring, in addition to the primary selection. But note that -selecting an active region with @kbd{C-@key{SPC}} does @emph{not} -alter the kill ring nor the primary selection, even though the text -highlighting is visually identical. +We have greatly simplified the Emacs features which access the network +by removing the Network Security Manager. No more annoying prompts +about trusting this or that site or page---you asked for it, you get +it, no questions asked! You, the user, are now in charge of any +security issues related to sites whose certificates expired or didn't +exist in the first place. Giving the user the utmost freedom was and +always will be the most important goal of Emacs development. We keep +that goal even as we develop Emacs back in time. @item -In Isearch, @kbd{C-y} and @kbd{M-y} are no longer bound to -@code{isearch-yank-kill} and @code{isearch-yank-pop} respectively. -Instead, @kbd{C-y} yanks the rest of the current line into the search -string (@code{isearch-yank-line}), whereas @kbd{M-y} does -@code{isearch-yank-kill}. The mismatch with the usual meanings of -@kbd{C-y} and @kbd{M-y} is unintended. +We made the output of @kbd{C-h l} much simpler and easier to grasp by +removing the names of commands run by the recorded keystrokes. True +Emacs lovers know their bindings by heart anyway, so why waste +precious screen estate on that which is well known? @item -Various completion features have been simplified. The option -@code{completion-category-overrides} has been removed, so Emacs uses a -single consistent scheme to generate completions, instead of using a -separate scheme for (say) buffer name completion. Several major -modes, such as Shell mode, now implement their own inline completion -commands instead of using @code{completion-at-point}. +Selection- and clipboard-related commands and variables got their +historical names back. It's now the definitive +@code{x-select-enable-clipboard} again instead of the vague +@code{select-enable-clipboard}, and all those @code{gui-select-text}, +@code{gui-get-primary-selection}, etc.@: got their @code{x-*} names +back. (What's a ``GUI'', anyway?) The only true window system with +selections is the X Window system, so we stopped pretending that other +platforms have anything similar to that. You now know when you invoke +a command that accesses X. @item -We have removed several options for controlling how windows are used, -such as @code{display-buffer-base-action}, -@code{display-buffer-alist}, @code{window-combination-limit}, and -@code{window-combination-resize}. +Passwords are no longer hidden when typed in @code{-batch} mode. It +was a misfeature to have it not shown in the first place: who can type +without seeing what they type? We couldn't convince the users of GUI +sessions to give up hiding the password, so we at least made it +visible in batch mode, which is something every veteran Emacs user +uses all the time. Stay tuned for un-hiding the password in GUI +sessions as well as we downgrade progressively to previous Emacs +versions. @item -The command @kbd{M-x customize-themes} has been removed. Emacs no -longer comes with pre-defined themes (you can write your own). +The nuisance with Unicode characters popping up all over the place has +been amply dealt with. We've removed @kbd{C-x 8} shorthands for +characters such as ‘, ’, “, ”, €, ≤, and many others; as a nice +benefit, this removes many useless entries at the beginning of the +@kbd{C-h b} output. The @code{electric-quote-mode} has been deleted, +so there's only the one true quoting method now---using the +plain-@acronym{ASCII} quote characters. And if that's not enough, the +doc strings and other messages show text quoted `like this' and "like +this" as they were written, instead of arbitrarily replacing them +with Unicode ``curved quote'' characters. The +@code{text-quoting-style} variable becomes therefore unneeded and was +removed. As result, text produced by Emacs can be sent to those +venerable teletypes again, yeah! + +For the same reasons, the character classes @code{[:alpha:]} and +@code{[:alnum:]} again match any word-constituent character, and +@code{[:graph:]} and @code{[:print:]} match every multibyte character. +Confusing use of Unicode character properties is gone. @item -Emacs no longer adapts various aspects of its display to GTK+ -settings, opting instead for a uniform toolkit-independent look. GTK+ -scroll bars are placed on the left, the same position as non-GTK+ X -scroll bars. Emacs no longer refers to GTK+ to set the default -@code{region} face, nor for drawing tooltips. +I-search and query-replace no longer try to confuse you by using the +``character-folding'' magic. They will no longer find any characters +you didn't actually type, like find @kbd{ⓐ} when you actually typed +@kbd{a}. Users who want to find some fancy character will have to +type it explicitly. @item -Setting the option @code{delete-by-moving-to-trash} to a -non-@code{nil} value now causes all file deletions to use the system trash, -even temporary files created by Lisp programs; furthermore, the -@kbd{M-x delete-file} and @kbd{M-x delete-directory} commands no -longer accept prefix arguments to force true deletion. +The @file{desktop.el} package no longer records window and frame +configuration, and doesn't attempt to restore them. You now have back +your freedom of re-arranging your windows and frames anew each time +you restore a session. This made the new backward-incompatible format +of the @file{.emacs.desktop} file unnecessary, so the format was +reverted back to what it was before Emacs 25. You can now again use +the desktop file with all the previous versions of Emacs. @item -On GNU/Linux and Unix, the default method for sending mail (as -specified by @code{send-mail-function}) is to use the -@command{sendmail} program. Emacs no longer asks for a delivery -method the first time you try to send mail, trusting instead that the -system is configured for mail delivery, as it ought to be. +We have reworked the Prettify Symbols mode to support only the default +@code{prettify-symbols-compose-predicate}. No need to consider +whether your major or minor mode needs its own prettifications; just +use what came with Emacs. We also removed the +@code{prettify-symbols-unprettify-at-point} option: once prettified, +always prettified! These changes make the Prettify Symbols mode quite +a lot simpler and easier to use. @item -Several VC features have been removed, including the @kbd{C-x v +} and -@kbd{C-x v m} commands for pulling and merging on distributed version -control systems, and the ability to view inline log entries in the log -buffers made by @kbd{C-x v L}. +Support for nifty new features of xterm, such as access to the X +selection and the clipboard, the ``bracketed paste mode'', and other +advanced capabilities has been removed. When you kill text in an +xterm Emacs session, that text is only saved in the Emacs kill ring, +without letting other applications have any way of accessing it. An +xterm is just a text terminal, nothing more, nothing less. There +should be no feature we support on xterm that isn't supported on bare +console terminals. For the same reasons, support for mouse-tracking +on xterm was removed. We will continue this line of simplifications +as we downgrade to previous versions of Emacs; stay tuned. + +@item +Various features in @file{package.el} have been simplified. The +``external'' package status is no longer available. A package present +on multiple archives will now be listed as many times as it is found: +we don't believe in concealing any information from the users. This +and other similar simplifications made +@code{package-menu-toggle-hiding} unnecessary, since there's nothing +to unhide now. + +@item +The @kbd{@key{UP}} and @kbd{@key{DOWN}} keys in the minibuffer have +been simplified to move by history items. No need to wonder whether +you have moved to the next/previous item or to another line within the +same item. Well-written commands shouldn't allow too long history +entries anyway; be sure to report any that do as bugs, so that we +could fix them in past versions of Emacs. + +@item +The VC mode was simplified by removing the support for ``push'' +commands. Moving back in time means you will have less and less need +to use modern version control systems such as Git, Bazaar, and +Mercurial, so the necessity of using ``push'' commands will gradually +disappear. We removed it from Emacs in advance, so that you won't +need to un-learn it when this command disappears, as it should. + +@item +The support for full C/C++ expressions in macros has been removed from +Hide-Ifdef mode. It now supports only the basic literal macros. As +result, the user interface was simplified, and a number of useless +commands have been removed from Hide-Ifdef mode. Further +simplifications were made possible by removing support for some fancy +new preprocessor directives, such as @code{#if defined}, @code{#elif}, +etc. + +@item +We have reverted to Etags for looking up definitions of functions, +variables, etc. Commands such as @kbd{M-.} use tags tables, as they +always have. This allowed the removal of the entire @file{xref.el} +package and its many metastases in the other Emacs packages and +commands, significantly simplifying those. No more complexities with +the various ``backends'' that provide incoherent behavior that is hard +to explain and remember; either the symbol is in TAGS or it isn't. No +more new user interfaces we never before saw in Emacs, either; if you +want the next definition for the symbol you typed, just invoke +@kbd{C-u M-.}---what could be simpler? As a nice side effect, you get +to use your beloved @code{tags-loop-continue} and @code{pop-tag-mark} +commands and their memorable bindings. The @file{package.el} package +has been removed for similar reasons. + +@item +@code{(/ @var{n})} once again yields just @var{n}. Emacs Lisp is not +Common Lisp, so compatibility with CL just complicates Emacs here. + +@item +The functions @code{filepos-to-bufferpos} and +@code{bufferpos-to-filepos} have been removed. Code that needs to +find a file position by a buffer position or vice versa should adapt +by reading the file with no conversions and counting bytes while +comparing text. How hard can that be? + +@item +We saw no need for the @code{make-process} primitive, so we removed +it. The @code{start-process} primitive provides all the functionality +one needs, so adding more APIs just confuses users. + +@item +The functions @code{bidi-find-overridden-directionality} and +@code{buffer-substring-with-bidi-context} were removed, in preparation +for removing the whole bidi support when downgrading to Emacs 23. + +@item +Horizontal scroll bars are no longer supported. Enlarge your windows +and frames instead, or use @code{truncate-lines} and the automatic +horizontal scrolling of text that Emacs had since time immemoriam. + +@item +Emacs is again counting the height of a frame's menu and its tool bar +in the frame's text height calculations. This makes Emacs invocation +on different platforms and with different toolkits less predictable +when frame geometry parameters are given on the Emacs command line, +thus making Emacs more adventurous and less boring to use. + +@item +The @command{etags} program no longer supports Ruby and Go languages. +You won't need that as you progressively travel back in time towards +the time before these languages were invented. We removed support for +them in anticipation for that time. @item To keep up with decreasing computer memory capacity and disk space, many -other functions and files have been eliminated in Emacs 23.4. +other functions and files have been eliminated in Emacs 24.5. @end itemize diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi index 5ef938566de..ac8988b4020 100644 --- a/doc/emacs/emacs.texi +++ b/doc/emacs/emacs.texi @@ -221,7 +221,7 @@ Appendices * GNU Free Documentation License:: The license for this documentation. * Emacs Invocation:: Hairy startup options. * X Resources:: X resources for customizing Emacs. -* Antinews:: Information about Emacs version 23. +* Antinews:: Information about Emacs version 24. * Mac OS / GNUstep:: Using Emacs under Mac OS and GNUstep. * Microsoft Windows:: Using Emacs on Microsoft Windows and MS-DOS. * Manifesto:: What's GNU? Gnu's Not Unix! From f7dc6d8b5bb318e02a4016d93f8b34de0716f4dc Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Fri, 22 Jan 2016 09:55:52 -0800 Subject: [PATCH 36/36] Further corrections to the pcase docstring --- lisp/emacs-lisp/pcase.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el index a2e05245c31..549ee96dd5f 100644 --- a/lisp/emacs-lisp/pcase.el +++ b/lisp/emacs-lisp/pcase.el @@ -111,8 +111,8 @@ CASES is a list of elements of the form (PATTERN CODE...). A structural PATTERN describes a template that identifies a class -of values. For example, the pattern (foo bar) matches any two -element list, binding its elements to symbols named `foo' and +of values. For example, the pattern `(,foo ,bar) matches any +two element list, binding its elements to symbols named `foo' and `bar' -- in much the same way that `cl-destructuring-bind' would. A significant difference from `cl-destructuring-bind' is that, if @@ -120,7 +120,7 @@ a pattern match fails, the next case is tried until either a succesful match is found or there are no more cases. Another difference is that pattern elements may be backquoted, -meaning they must match exactly: The pattern (\\='foo \\='bar) +meaning they must match exactly: The pattern \\='(foo bar) matches only against two element lists containing the symbols `foo' and `bar' in that order. (As a short-hand, atoms always match themselves, such as numbers or strings, and need not be