]> code.delx.au - gnu-emacs/blob - lisp/xwidget.el
Fix visual glitch during webkit resizing
[gnu-emacs] / lisp / xwidget.el
1 ;;; xwidget.el --- api functions for xwidgets
2 ;; see xwidget.c for more api functions
3
4
5 ;;; Commentary:
6 ;;
7
8 ;;TODO this breaks compilation when we dont have xwidgets
9 ;;(require 'xwidget-internal)
10
11 ;;TODO model after make-text-button instead!
12 ;;; Code:
13
14 (eval-when-compile (require 'cl))
15 (require 'reporter)
16
17 (defcustom xwidget-webkit-scroll-behaviour 'native
18 "Scroll behaviour of the webkit instance.
19 'native or 'image."
20 :group 'xwidgets)
21
22 (defun xwidget-insert (pos type title width height)
23 "Insert an xwidget at POS.
24 given ID, TYPE, TITLE WIDTH and
25 HEIGHT in the current buffer.
26
27 Return ID
28
29 see `make-xwidget' for types suitable for TYPE."
30 (goto-char pos)
31 (let ((id (make-xwidget (point) (point)
32 type title width height nil)))
33 (put-text-property (point) (+ 1 (point))
34 'display (list 'xwidget ':xwidget id))
35 id))
36
37 (defun xwidget-at (pos)
38 "Return xwidget at POS."
39 ;;TODO this function is a bit tedious because the C layer isnt well protected yet and
40 ;;xwidgetp aparently doesnt work yet
41 (let* ((disp (get-text-property pos 'display))
42 (xw (car (cdr (cdr disp)))))
43 ;;(if ( xwidgetp xw) xw nil)
44 (if (equal 'xwidget (car disp)) xw)))
45
46
47 ;; (defun xwidget-socket-handler ()
48 ;; "Create plug for socket. TODO."
49 ;; (interactive)
50 ;; (message "socket handler xwidget %S" last-input-event)
51 ;; (let*
52 ;; ((xwidget-event-type (nth 2 last-input-event))
53 ;; (xwidget-id (nth 1 last-input-event)))
54 ;; (cond ( (eq xwidget-event-type 'xembed-ready)
55 ;; (let*
56 ;; ((xembed-id (nth 3 last-input-event)))
57 ;; (message "xembed ready event: %S xw-id:%s" xembed-id xwidget-id)
58 ;; ;;TODO fetch process data from the xwidget. create it, store process info
59 ;; ;;will start emacs/uzbl in a xembed socket when its ready
60 ;; ;; (cond
61 ;; ;; ((eq 3 xwidget-id)
62 ;; ;; (start-process "xembed" "*xembed*" (format "%ssrc/emacs" default-directory) "-q" "--parent-id" (number-to-string xembed-id) ) )
63 ;; ;; ((eq 5 xwidget-id)
64 ;; ;; (start-process "xembed2" "*xembed2*" "uzbl-core" "-s" (number-to-string xembed-id) "http://www.fsf.org" ) )
65 ;; )))))
66
67 (defun xwidget-display (xwidget)
68 "Force XWIDGET to be displayed to create a xwidget_view.
69 Return the window displaying XWIDGET."
70 (let* ((buffer (xwidget-buffer xwidget))
71 (window (display-buffer buffer))
72 (frame (window-frame window)))
73 (set-frame-visible frame t)
74 (redisplay t)
75 window))
76
77
78 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
79 ;;; webkit support
80 (require 'browse-url)
81 (require 'image-mode);;for some image-mode alike functionality
82 (require 'cl-macs);;for flet
83
84 ;;;###autoload
85 (defun xwidget-webkit-browse-url (url &optional new-session)
86 "Ask xwidget-webkit to browse URL.
87 NEW-SESSION specifies whether to create a new xwidget-webkit session. URL
88 defaults to the string looking like a url around the cursor position."
89 (interactive (progn
90 (require 'browse-url)
91 (browse-url-interactive-arg "xwidget-webkit URL: "
92 ;;( xwidget-webkit-current-url)
93 )))
94 (when (stringp url)
95 (setq url (url-tidy url))
96 (if new-session
97 (xwidget-webkit-new-session url)
98 (xwidget-webkit-goto-url url))))
99
100
101 ;;shims for adapting image mode code to the webkit browser window
102 (defun xwidget-image-display-size (spec &optional pixels frame)
103 "Image code adaptor. SPEC PIXELS FRAME like the corresponding `image-mode' fn."
104 (let ((xwi (xwidget-info (xwidget-at 1))))
105 (cons (aref xwi 2)
106 (aref xwi 3))))
107
108 (defadvice image-display-size (around image-display-size-for-xwidget
109 (spec &optional pixels frame)
110 activate)
111 "Advice for re-using image mode for xwidget."
112 (if (eq (car spec) 'xwidget)
113 (setq ad-return-value (xwidget-image-display-size spec pixels frame))
114 ad-do-it))
115
116 ;;todo.
117 ;; - check that the webkit support is compiled in
118 (defvar xwidget-webkit-mode-map
119 (let ((map (make-sparse-keymap)))
120 (define-key map "g" 'xwidget-webkit-browse-url)
121 (define-key map "a" 'xwidget-webkit-adjust-size-dispatch)
122 (define-key map "b" 'xwidget-webkit-back )
123 (define-key map "r" 'xwidget-webkit-reload )
124 (define-key map "t" (lambda () (interactive) (message "o")) )
125 (define-key map "\C-m" 'xwidget-webkit-insert-string)
126 (define-key map "w" 'xwidget-webkit-current-url)
127
128 ;;similar to image mode bindings
129 (define-key map (kbd "SPC") 'xwidget-webkit-scroll-up)
130 (define-key map (kbd "DEL") 'xwidget-webkit-scroll-down)
131
132 (define-key map [remap scroll-up] 'xwidget-webkit-scroll-up)
133 (define-key map [remap scroll-up-command] 'xwidget-webkit-scroll-up)
134
135 (define-key map [remap scroll-down] 'xwidget-webkit-scroll-down)
136 (define-key map [remap scroll-down-command] 'xwidget-webkit-scroll-down)
137
138 (define-key map [remap forward-char] 'xwidget-webkit-scroll-forward)
139 (define-key map [remap backward-char] 'xwidget-webkit-scroll-backward)
140 (define-key map [remap right-char] 'xwidget-webkit-scroll-forward)
141 (define-key map [remap left-char] 'xwidget-webkit-scroll-backward)
142 ;; (define-key map [remap previous-line] 'image-previous-line)
143 ;; (define-key map [remap next-line] 'image-next-line)
144
145 ;; (define-key map [remap move-beginning-of-line] 'image-bol)
146 ;; (define-key map [remap move-end-of-line] 'image-eol)
147 ;; (define-key map [remap beginning-of-buffer] 'image-bob)
148 ;; (define-key map [remap end-of-buffer] 'image-eob)
149 map)
150 "Keymap for `xwidget-webkit-mode'.")
151
152 (defun xwidget-webkit-scroll-up ()
153 "Scroll webkit up,either native or like image mode."
154 (interactive)
155 (if (eq xwidget-webkit-scroll-behaviour 'native)
156 (xwidget-set-adjustment (xwidget-webkit-last-session) 'vertical t 50)
157 (image-scroll-up)))
158
159 (defun xwidget-webkit-scroll-down ()
160 "Scroll webkit down,either native or like image mode."
161 (interactive)
162 (if (eq xwidget-webkit-scroll-behaviour 'native)
163 (xwidget-set-adjustment (xwidget-webkit-last-session) 'vertical t -50)
164 (image-scroll-down)))
165
166 (defun xwidget-webkit-scroll-forward ()
167 (interactive)
168 (if (eq xwidget-webkit-scroll-behaviour 'native)
169 (xwidget-set-adjustment (xwidget-webkit-last-session) 'horizontal t 50)
170 (xwidget-webkit-scroll-forward)))
171
172 (defun xwidget-webkit-scroll-backward ()
173 (interactive)
174 (if (eq xwidget-webkit-scroll-behaviour 'native)
175 (xwidget-set-adjustment (xwidget-webkit-last-session) 'horizontal t -50)
176 (xwidget-webkit-scroll-backward)))
177
178
179 ;;the xwidget event needs to go into a higher level handler
180 ;;since the xwidget can generate an event even if its offscreen
181 ;;TODO this needs to use callbacks and consider different xw ev types
182 (define-key (current-global-map) [xwidget-event] 'xwidget-event-handler)
183 (defun xwidget-log ( &rest msg)
184 "Log MSG to a buffer."
185 (let ( (buf (get-buffer-create "*xwidget-log*")))
186 (save-excursion
187 (buffer-disable-undo buf)
188 (set-buffer buf)
189 (insert (apply 'format msg))
190 (insert "\n"))))
191
192 (defun xwidget-event-handler ()
193 "Receive xwidget event."
194 (interactive)
195 (xwidget-log "stuff happened to xwidget %S" last-input-event)
196 (let*
197 ((xwidget-event-type (nth 1 last-input-event))
198 (xwidget (nth 2 last-input-event))
199 ;(xwidget-callback (xwidget-get xwidget 'callback));;TODO stopped working for some reason
200 )
201 ;(funcall xwidget-callback xwidget xwidget-event-type)
202 (message "xw callback %s" xwidget)
203 (funcall 'xwidget-webkit-callback xwidget xwidget-event-type)))
204
205 (defun xwidget-webkit-callback (xwidget xwidget-event-type)
206 "Callback for xwidgets.
207 XWIDGET instance, XWIDGET-EVENT-TYPE depends on the originating xwidget."
208 (save-excursion
209 (cond ((buffer-live-p (xwidget-buffer xwidget))
210 (set-buffer (xwidget-buffer xwidget))
211 (let* ((strarg (nth 3 last-input-event)))
212 (cond ((eq xwidget-event-type 'document-load-finished)
213 (xwidget-log "webkit finished loading: '%s'" (xwidget-webkit-get-title xwidget))
214 ;;TODO - check the native/internal scroll
215 ;;(xwidget-adjust-size-to-content xwidget)
216 (xwidget-webkit-adjust-size-dispatch) ;;TODO send xwidget here
217 (rename-buffer (format "*xwidget webkit: %s *" (xwidget-webkit-get-title xwidget)))
218 (pop-to-buffer (current-buffer)))
219 ((eq xwidget-event-type 'navigation-policy-decision-requested)
220 (if (string-match ".*#\\(.*\\)" strarg)
221 (xwidget-webkit-show-id-or-named-element xwidget (match-string 1 strarg))))
222 (t (xwidget-log "unhandled event:%s" xwidget-event-type)))))
223 (t (xwidget-log "error: callback called for xwidget with dead buffer")))))
224
225 (define-derived-mode xwidget-webkit-mode
226 special-mode "xwidget-webkit" "xwidget webkit view mode"
227 (setq buffer-read-only t)
228 ;; Keep track of [vh]scroll when switching buffers
229 (image-mode-setup-winprops))
230
231 (defvar xwidget-webkit-last-session-buffer nil)
232
233 (defun xwidget-webkit-last-session ()
234 "Last active webkit, or nil."
235 (if (buffer-live-p xwidget-webkit-last-session-buffer)
236 (with-current-buffer xwidget-webkit-last-session-buffer
237 (xwidget-at 1))
238 nil))
239
240 (defun xwidget-webkit-current-session ()
241 "Either the webkit in the current buffer, or the last one used, which might be nil."
242 (if (xwidget-at 1)
243 (xwidget-at 1)
244 (xwidget-webkit-last-session)))
245
246 (defun xwidget-adjust-size-to-content (xw)
247 "Resize XW to content."
248 ;;xwidgets doesnt support widgets that have their own opinions about size well yet
249 ;;this reads the desired size and resizes the emacs allocated area accordingly
250 (let ((size (xwidget-size-request xw)))
251 (xwidget-resize xw (car size) (cadr size))))
252
253
254 (defvar xwidget-webkit-activeelement-js"
255 function findactiveelement(doc){
256 //alert(doc.activeElement.value);
257 if(doc.activeElement.value != undefined){
258 return doc.activeElement;
259 }else{
260 // recurse over the child documents:
261 var frames = doc.getElementsByTagName('frame');
262 for (var i = 0; i < frames.length; i++)
263 {
264 var d = frames[i].contentDocument;
265 var rv = findactiveelement(d);
266 if(rv != undefined){
267 return rv;
268 }
269 }
270 }
271 return undefined;
272 };
273
274
275 "
276
277 "javascript that finds the active element."
278 ;;yes its ugly. because:
279 ;; - there is aparently no way to find the active frame other than recursion
280 ;; - the js "for each" construct missbehaved on the "frames" collection
281 ;; - a window with no frameset still has frames.length == 1, but frames[0].document.activeElement != document.activeElement
282 ;;TODO the activeelement type needs to be examined, for iframe, etc. sucks.
283 )
284
285 (defun xwidget-webkit-insert-string (xw str)
286 "Insert string in the active field in the webkit.
287 Argument XW webkit.
288 Argument STR string."
289 ;;read out the string in the field first and provide for edit
290 (interactive
291 (let* ((xww (xwidget-webkit-current-session))
292
293 (field-value
294 (progn
295 (xwidget-webkit-execute-script xww xwidget-webkit-activeelement-js)
296 (xwidget-webkit-execute-script-rv xww "findactiveelement(document).value;" )))
297 (field-type (xwidget-webkit-execute-script-rv xww "findactiveelement(document).type;" )))
298 (list xww
299 (cond ((equal "text" field-type)
300 (read-string "text:" field-value))
301 ((equal "password" field-type)
302 (read-passwd "password:" nil field-value))
303 ((equal "textarea" field-type)
304 (xwidget-webkit-begin-edit-textarea xww field-value))))))
305 (xwidget-webkit-execute-script xw (format "findactiveelement(document).value='%s'" str)))
306
307
308 (defun xwidget-webkit-begin-edit-textarea (xw text)
309 (switch-to-buffer
310 (generate-new-buffer "textarea"))
311
312 (set (make-local-variable 'xwbl) xw)
313 (insert text))
314
315 (defun xwidget-webkit-end-edit-textarea ()
316 (interactive)
317 (goto-char (point-min))
318 (while (search-forward "\n" nil t)
319 (replace-match "\\n" nil t))
320 (xwidget-webkit-execute-script xwbl (format "findactiveelement(document).value='%s'"
321 (buffer-substring (point-min) (point-max))))
322 ;;TODO convert linefeed to \n
323 )
324
325 (defun xwidget-webkit-show-named-element (xw element-name)
326 "make named-element show. for instance an anchor."
327 (interactive (list (xwidget-webkit-current-session) (read-string "element name:")))
328 ;;TODO
329 ;; since an xwidget is an Emacs object, it is not trivial to do some things that are taken for granted in a normal browser.
330 ;; scrolling an anchor/named-element into view is one such thing.
331 ;; this function implements a proof-of-concept for this.
332 ;; problems remaining:
333 ;; - the selected window is scrolled but this is not always correct
334 ;; - this needs to be interfaced into browse-url somehow. the tricky part is that we need to do this in two steps:
335 ;; A: load the base url, wait for load signal to arrive B: navigate to the anchor when the base url is finished rendering
336
337 ;;this part figures out the Y coordinate of the element
338 (let ((y (string-to-number
339 (xwidget-webkit-execute-script-rv xw
340 (format "document.getElementsByName('%s')[0].getBoundingClientRect().top" element-name)
341 0))))
342 ;;now we need to tell emacs to scroll the element into view.
343 (xwidget-log "scroll: %d" y)
344 (set-window-vscroll (selected-window) y t)))
345
346 (defun xwidget-webkit-show-id-element (xw element-id)
347 "make id-element show. for instance an anchor."
348 (interactive (list (xwidget-webkit-current-session)
349 (read-string "element id:")))
350 (let ((y (string-to-number
351 (xwidget-webkit-execute-script-rv xw
352 (format "document.getElementById('%s').getBoundingClientRect().top" element-id)
353 0))))
354 ;;now we need to tell emacs to scroll the element into view.
355 (xwidget-log "scroll: %d" y)
356 (set-window-vscroll (selected-window) y t)))
357
358 (defun xwidget-webkit-show-id-or-named-element (xw element-id)
359 "make id-element show. for instance an anchor."
360 (interactive (list (xwidget-webkit-current-session)
361 (read-string "element id:")))
362 (let* ((y1 (string-to-number
363 (xwidget-webkit-execute-script-rv xw
364 (format "document.getElementsByName('%s')[0].getBoundingClientRect().top" element-id)
365 "0")))
366 (y2 (string-to-number
367 (xwidget-webkit-execute-script-rv xw
368 (format "document.getElementById('%s').getBoundingClientRect().top" element-id)
369 "0")))
370 (y3 (max y1 y2)))
371 ;;now we need to tell emacs to scroll the element into view.
372 (xwidget-log "scroll: %d" y3)
373 (set-window-vscroll (selected-window) y3 t)))
374
375 (defun xwidget-webkit-adjust-size-to-content ()
376 "Adjust webkit to content size."
377 (interactive)
378 (xwidget-adjust-size-to-content (xwidget-webkit-current-session)))
379
380 (defun xwidget-webkit-adjust-size-dispatch ()
381 "Adjust size according to mode."
382 (interactive)
383 (if (eq xwidget-webkit-scroll-behaviour 'native)
384 (xwidget-webkit-adjust-size-to-window)
385 (xwidget-webkit-adjust-size-to-content))
386 (recenter-top-bottom)
387 )
388
389 (defun xwidget-webkit-adjust-size-to-window ()
390 "Adjust webkit to window."
391 (interactive)
392 (xwidget-resize ( xwidget-webkit-current-session) (window-pixel-width) (window-pixel-height)))
393
394 (defun xwidget-webkit-adjust-size (w h)
395 "Manualy set webkit size.
396 Argument W width.
397 Argument H height."
398 ;;TODO shouldnt be tied to the webkit xwidget
399 (interactive "nWidth:\nnHeight:\n")
400 (xwidget-resize ( xwidget-webkit-current-session) w h))
401
402 (defun xwidget-webkit-fit-width ()
403 "Adjust width of webkit to window width."
404 (interactive)
405 (xwidget-webkit-adjust-size (- (caddr (window-inside-pixel-edges))
406 (car (window-inside-pixel-edges)))
407 1000))
408
409 (defun xwidget-webkit-new-session (url)
410 "Create a new webkit session buffer with URL."
411 (let*
412 ((bufname (generate-new-buffer-name "*xwidget-webkit*"))
413 xw)
414 (setq xwidget-webkit-last-session-buffer (switch-to-buffer (get-buffer-create bufname)))
415 (insert " ")
416 (setq xw (xwidget-insert 1 'webkit-osr bufname 1000 1000))
417 (xwidget-put xw 'callback 'xwidget-webkit-callback)
418 (xwidget-webkit-mode)
419 (xwidget-webkit-goto-uri (xwidget-webkit-last-session) url )))
420
421
422 (defun xwidget-webkit-goto-url (url)
423 "Goto URL."
424 (if (xwidget-webkit-current-session)
425 (progn
426 (xwidget-webkit-goto-uri (xwidget-webkit-current-session) url))
427 (xwidget-webkit-new-session url)))
428
429 (defun xwidget-webkit-back ()
430 "Back in history."
431 (interactive)
432 (xwidget-webkit-execute-script (xwidget-webkit-current-session) "history.go(-1);"))
433
434 (defun xwidget-webkit-reload ()
435 "Reload current url."
436 (interactive)
437 (xwidget-webkit-execute-script (xwidget-webkit-current-session) "history.go(0);"))
438
439 (defun xwidget-webkit-current-url ()
440 "Get the webkit url. place it on kill ring."
441 (interactive)
442 (let* ((rv (xwidget-webkit-execute-script-rv (xwidget-webkit-current-session)
443 "document.URL"))
444 (url (kill-new (or rv ""))))
445 (message "url: %s" url )
446 url))
447
448 (defun xwidget-webkit-execute-script-rv (xw script &optional default)
449 "Same as 'xwidget-webkit-execute-script' but but with return value.
450 XW is the webkit instance. SCRIPT is the script to execut.
451 DEFAULT is the defaultreturn value."
452 ;;notice the fugly "title" hack. it is needed because the webkit api
453 ;;doesnt support returning values. this is a wrapper for the title
454 ;;hack so its easy to remove should webkit someday support JS return
455 ;;values or we find some other way to access the DOM
456
457 ;;reset webkit title. fugly.
458 (let* ((emptytag "titlecantbewhitespaceohthehorror")
459 title)
460 (xwidget-webkit-execute-script xw (format "document.title=\"%s\";" (or default emptytag)))
461 (xwidget-webkit-execute-script xw (format "document.title=%s;" script))
462 (setq title (xwidget-webkit-get-title xw))
463 (if (equal emptytag title)
464 (setq title ""))
465 (unless title
466 (setq title default))
467 title))
468
469
470 ;; use declare here?
471 ;; (declare-function xwidget-resize-internal "xwidget.c" )
472 ;; check-declare-function?
473
474 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
475 (defun xwidget-webkit-get-selection ()
476 "Get the webkit selection."
477 (xwidget-webkit-execute-script-rv (xwidget-webkit-current-session)
478 "window.getSelection().toString();"))
479
480 (defun xwidget-webkit-copy-selection-as-kill ()
481 "Get the webkit selection and put it on the kill ring."
482 (interactive)
483 (kill-new (xwidget-webkit-get-selection)))
484
485
486 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
487 ;; xwidget plist management(similar to the process plist functions)
488
489 (defun xwidget-get (xwidget propname)
490 "Return the value of XWIDGET' PROPNAME property.
491 This is the last value stored with `(xwidget-put XWIDGET PROPNAME VALUE)'."
492 (plist-get (xwidget-plist xwidget) propname))
493
494 (defun xwidget-put (xwidget propname value)
495 "Change XWIDGET' PROPNAME property to VALUE.
496 It can be retrieved with `(xwidget-get XWIDGET PROPNAME)'."
497 (set-xwidget-plist xwidget
498 (plist-put (xwidget-plist xwidget) propname value)))
499
500
501 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
502
503 (defun xwidget-delete-zombies ()
504 "Helper for xwidget-cleanup."
505 (dolist (xwidget-view xwidget-view-list)
506 (when (or (not (window-live-p (xwidget-view-window xwidget-view)))
507 (not (memq (xwidget-view-model xwidget-view)
508 xwidget-list)))
509 (delete-xwidget-view xwidget-view))))
510
511 (defun xwidget-cleanup ()
512 "Delete zombie xwidgets."
513 ;;its still pretty easy to trigger bugs with xwidgets.
514 ;;this function tries to implement a workaround
515 (interactive)
516 ;; kill xviews who should have been deleted but stull linger
517 (xwidget-delete-zombies)
518 ;; redraw display otherwise ghost of zombies will remain to haunt the screen
519 (redraw-display))
520
521 ;;this is a workaround because I cant find the right place to put it in C
522 ;;seems to work well in practice though
523 ;;(add-hook 'window-configuration-change-hook 'xwidget-cleanup)
524 (add-hook 'window-configuration-change-hook 'xwidget-delete-zombies)
525
526 (defun xwidget-kill-buffer-query-function ()
527 "Ask beforek illing a buffer that has xwidgets."
528 (let ((xwidgets (get-buffer-xwidgets (current-buffer))))
529 (or (not xwidgets)
530 (not (memq t (mapcar 'xwidget-query-on-exit-flag xwidgets)))
531 (yes-or-no-p
532 (format "Buffer %S has xwidgets; kill it? "
533 (buffer-name (current-buffer)))))))
534
535 (add-hook 'kill-buffer-query-functions 'xwidget-kill-buffer-query-function)
536
537 ;;killflash is sadly not reliable yet.
538 (defvar xwidget-webkit-kill-flash-oneshot t)
539 (defun xwidget-webkit-kill-flash ()
540 "Disable the flash plugin in webkit.
541 This is needed because Flash is non-free and doesnt work reliably
542 on 64 bit systems and offscreen rendering. Sadly not reliable
543 yet, so deinstall Flash instead for now."
544 ;;you can only call this once or webkit crashes and takes emacs with it. odd.
545 (unless xwidget-webkit-kill-flash-oneshot
546 (xwidget-disable-plugin-for-mime "application/x-shockwave-flash")
547 (setq xwidget-webkit-kill-flash-oneshot t)))
548
549 (xwidget-webkit-kill-flash)
550
551 (defun report-xwidget-bug ()
552 "Report a bug in GNU Emacs about the XWidget branch.
553 Prompts for bug subject. Leaves you in a mail buffer."
554 (interactive)
555 (let ((reporter-prompt-for-summary-p t))
556 (reporter-submit-bug-report "submit@debbugs.gnu.org" nil nil nil nil
557 (format "Package: emacs-xwidgets
558
559 Please describee xactly whata ctions triggered the bug, and the
560 precise symptoms of the bug. If you can, give a recipe starting
561 from `emacs -Q'.
562
563 If Emacs crashed, and you have the Emacs process in the gdb
564 deubbger, please include the output from the following gdb
565 commands:
566 `bt full' and `xbacktrace'.
567
568 For information about debugging Emacs, please read the file
569 %s" (expand-file-name "DEBUG" data-directory)))))
570
571 (provide 'xwidget)
572
573 ;;; xwidget.el ends here