3 This is an experimental branch to enable embedding of GTK widgets
4 inside an Emacs window. The Emacs abstraction is called an Xwidget,
5 for eXternal widget, and also in reference to the Xembed protocoll.
7 There is a demo file called xwidget-test.el which shows some of the
8 possibilities. There are some screnshots at the emacswiki.
10 Currently its possible to insert buttons, sliders, xembed widgets, and
11 webkit in the buffer. It works similar to the support for images in
12 Emacs. Adding more types of widgets should be fairly straightforward,
13 but will require adapter code for each type.
15 A difference from images is that xwidgets live their own life. You
16 create them with an api, get a reference, and tie them to a particular
17 buffer with a display spec.
19 Each xwidget can have several views. In MVC terms, an xwidget is the
20 model, and an xwidget-view is a view of the xwidget in a particular
23 The xwidget code attempts to keep the visual appearance of the views
24 in sync with through an Observer pattern implementation. This is
25 necessary to support the Emacs window paradigm.
28 bzr co bzr+ssh://bzr.savannah.gnu.org/emacs/xwidget/
29 #the below compiler flags shouldn't be strictly necessary
31 ./configure --with-xwidgets --enable-asserts --with-x-toolkit=gtk3
36 If you have GTK3 and gtk-webkit installed, you should be able to
37 start the embedded webkit browser now:
39 M-X xwidget-webkit-browse-url
41 If that didnt work out try the minimal demonstration instead:
43 (load-library "xwidget-test")
44 (xwidget-demo-a-button)
46 It looks unimpressive, but it's a gtk button inside an Emacs buffer!
48 If you got webkit working, great! Please note, though, that the
49 current support is far from a full fledged browser. My focus is on
50 delivering a component that can be used to build a full emacs based
51 browser on. Since I implement a browse-url function you can get quite
54 (setq browse-url-browser-function 'xwidget-webkit-browse-url)
56 then all Emacs browser interface systems work to a degree.
57 heres stuff I use currenly
59 - m-x anything-surfraw interfaces to search engines
60 - C-o in org mode opens links inside org
61 - m-x ffap opens links anywhere in a buffer
62 - m-x gtk-lookup-symbol searches gtk docs
66 I'll add more examples as I go along.
68 However theres lots of support missing, see TODO list for
71 - keyboard field navigation
74 - sites that use flash. I dont really care about this issue so its
75 unlikely to be fixed. Just a heads up.
78 Beginning with Summer 2011 I am now able to use Xwidget Emacs as my
79 primary Emacs. That is good for the project and the stability of the
82 At the time of writing I have 24 hour Emacs uptime with several
83 embedded webkit browsers, Gnus, org-mode, tramp, etc. etc.
85 That said, there are still many improvements that needs to be done,
86 particularily in memory management. Expect xwidget emacs to leak
89 ** timeline for inclusion in trunk
90 The Emacs 24 feature freeze is passed, so xwidgets won't probably be merged
91 until Emacs 25. OTOH since I now use xwidget emacs as my primary
92 emacs, I will merge from trunk much more often than in the past.
95 emacs-devel@gnu.org. There are very helpful people there. When I
96 started the xwidget project I had no clue about the Emacs internals.
98 * Brief overview of how xwidgets work
99 Xwidgets work in one way like images in Emacs. You bind a display spec very
100 similar to an image display spec to buffer contents. The display engine will
101 notice the display spec and try to display the xwidget there. The display engine
102 prepares space at the right place for the xwidget and so on for free, as long as
103 we provide proper sizes and so on back to the redisplay engine.
106 The problem is that Emacs cant actually draw the widgets, as it can with
107 images. Emacs must notify GTK about where the widgets should be, and how they
108 should be clipped and so on, and this information must be given to GTK
109 synchonous with Emacs display changes. Ok, so why is that difficult then?
111 - How do we know when a widget is NOT to be drawn? The only way I found so far
112 is having a flag for each xwdiget, that is reset before a redisplay. When an
113 xwidget is encountered during display, the flag is set. After redisplay,
114 iterate all xwidgets and hide those which hasnt been displayed.
116 - The gtk socket type for embedding external applications is desirable
117 but presents a lot of difficulties of its own. One difficulty is
118 deciding which input events to forward, and when and how to do it.
120 ** placement and clipping
121 the entire emacs frame is a gtk window. we use the fixed layout
122 manager to place xwidgets on the frame. coordinates are supplied by
123 the emacs display engine. widgets are placed inside an intermediate
124 window, called the widgetwindow. the widgetwindows are placed on the
127 this way was chosen to simplify clipping of the widgets against emacs
131 ** different strategies
132 Integrating toolkit widgets(gtk in this case) and the emacs display
133 engine is more difficult than your plain average gui application, and
134 different strategies has been tested and will continue to be tested.
136 There was a distinction between live xwidgets and
137 phantom xwidgets, previous to the change to MVC.
139 - the first aproach was to have the live xwidget on-screen, and move
140 them about. the phantoms were generated by snapshoting the live
143 the drawback of that aproach was that the gtk toolkit is admirably
144 lazy and doesnt draw the widget if its not actualy shown, meaning that
145 the snapshots for the phantoms will show garbage.
147 - the second aproach was to use composition support. that tells gtk
148 that the widget should be drawn in an off-screen buffer and drawn on
149 screen by the application.
151 this has the primary advantage that the snapshot is always
152 available, and enables the possibility of more eye-candy like drawing
153 live and phantom widgets in different colors.
155 the drawback is that its our own responsibility to handle drawing,
156 which puts more of the display optimization burden on us.
158 this is aproach worked so-so.
160 - another aproach is to have both live and phantom widgets drawn
161 on-screen by proxy gtk objects. the live xwidget will be entirely
162 handled in an off-screen window, and the proxy objects will redirect
165 - combine on-screen and off-screen aproaches. maybe composition is the
166 way to go for most cases, but on-screen xembeding is the way to go
167 for particular special cases, like showing video in a
168 window. off-screen rendering and whatnot, is not efficient in that
169 particular case, and the user will simply have to accept that the
170 phantom of a video widget isnt particularily beautiful.
172 - The current and seemingly sanest aproach implements a MVC pattern.
176 ;; cd /path/to/xwidgets-emacs-dir
177 ;; make all&& src/emacs -q --eval "(progn (load \"`pwd`/lisp/xwidget-test.el\") (xwidget-demo-basic))"
180 The MVC approach appears to be at least in principle robust for plain gtk
181 widgets. For the interesting case of gtk sockets which implements an
182 xembed host widget that allows for embedding other applications inside
183 an Emacs window, the story gets more complex.
185 The problem is that xembed is designed to plug an application window
186 inside a a secket and thats it. You can't move a plug between
187 sockets. I tried numerous hacks to get around this but there is
188 nothing that works realy well.
190 Therefore the Emacs part of the code will only expose well-defined
191 interfaces. cooperating applications will be able to use the interface
192 in a well defined manner. The problem is that there is no known xembeddable
193 application that implement the needed type of functionality, which is
194 allowing for creating new windows on the fly that plug into new
197 Therefore I will attempt to provide an external application that wraps
198 another application and through hacks attempts to provide the needed
199 multi view xembed function. That way Emacs is sane and the insanity
202 This app will work by providing a socket that an app plugs into. The
203 socket window is copied efficientlp by means of composition to a
204 number of other windows, that then are plugged into the different
206 ** old notes from x_draw_xwidget_glyph_string
208 BUG it seems this method for some reason is called with bad s->x and s->y sometimes.
209 When this happens the xwidget doesnt move on screen as it should.
210 This mightbe because of x_scroll_run. Emacs decides to scroll the screen by blitting sometimes.
211 then emacs doesnt try to actualy call the paint routines, which means this here code will never
212 run so the xwidget wont know it has been moved.
214 Solved temporarily by never optimizing in try_window_reusing_current_matrix().
216 BUG the phantoming code doesnt work very well when the live xwidget is off screen.
217 you will get weirdo display artefacts. Composition ought to solve this, since that means the live window is
218 always available in an off-screen buffer. My current attempt at composition doesnt work properly however.
220 //allocation debugging. the correct values cant be expected to show upp immediately, but eventually they should get to be ok
221 // this is because we dont know when the container gets around to doing layout
222 //GtkAllocation galloc;
223 //gtk_widget_get_allocation(GTK_WIDGET (xv->widgetwindow), &galloc);
224 //printf("allocation %d %d , %d %d\n", galloc.x,galloc.y,galloc.width,galloc.height);
227 *** old notes about the old live/phantom scheme
230 // 1) always draw live xwidget in slected window
231 // (2) if there were no live instances of the xwidget in selected window, also draw it live)
232 // 3) if there was a live xwidget previously, now phantom it.
236 //ok, we are painting the xwidgets in non-selected window, so draw a phantom
237 //printf("draw phantom xwidget at:%d %d\n",x,y);
238 //xwidget_composite_draw_phantom (xw, x, y, clipx, clipy); //TODO MVC there will be very few cases of phantoming
242 atm this works as follows: only check if xwidgets are displayed in the
243 "selected window". if not, hide them or phantom them.
245 this means valid cases like xwidgets being displayed only once in
246 non-selected windows, does not work well. they should also be visible
247 in that case not phantomed.
250 ** DONE new annoying trace
251 CLOSED: [2011-08-13 Sat 16:16]
252 maybe related to scroll inhibiting or cursor inhibiting code.
253 It appears actually to be related to GLYPH_DEBUG=1. this flag is no
256 Breakpoint 1, abort () at emacs.c:383
257 383 kill (getpid (), SIGABRT);
258 Missing separate debuginfos, use: debuginfo-install hunspell-1.2.15-2.fc15.x86_64 nss-mdns-0.10-9.fc15.x86_64
262 #0 abort () at emacs.c:383
263 #1 0x0000000000418f01 in matrix_row (matrix=0xac29400, row=-1)
265 #2 0x000000000046e113 in draw_glyphs (w=0x18235c0, x=198, row=0xa3af100, area=
266 TEXT_AREA, start=17, end=18, hl=DRAW_CURSOR, overlaps=0) at xdisp.c:22550
267 #3 0x000000000047869f in draw_phys_cursor_glyph (w=0x18235c0, row=0xa3af100,
268 hl=DRAW_CURSOR) at xdisp.c:24882
269 #4 0x00000000005083bb in x_draw_window_cursor (w=0x18235c0, glyph_row=
270 0xa3af100, x=180, y=361, cursor_type=0, cursor_width=1, on_p=1, active_p=1)
272 #5 0x00000000004790cd in display_and_set_cursor (w=0x18235c0, on=1, hpos=17,
273 vpos=19, x=180, y=361) at xdisp.c:25098
274 #6 0x00000000004fa31f in x_update_window_end (w=0x18235c0, cursor_on_p=1,
275 mouse_face_overwritten_p=0) at xterm.c:644
276 #7 0x000000000041ccb9 in update_window (w=0x18235c0, force_p=0)
278 #8 0x000000000041c165 in update_window_tree (w=0x18235c0, force_p=0)
280 #9 0x000000000041beee in update_frame (f=0x1658460, force_p=0,
281 inhibit_hairy_id_p=0) at dispnew.c:3258
282 #10 0x0000000000450a2e in redisplay_internal () at xdisp.c:12983
283 #11 0x000000000044e2a6 in redisplay () at xdisp.c:12099
284 #12 0x000000000056a60d in read_char (commandflag=1, nmaps=6, maps=
286 ** DONE allow xwidgets to report their size
287 CLOSED: [2011-07-19 Tue 14:26]
288 now we just hard code sizes. but webkit widgets for instance can
289 report sizes that suit the content. support that.
290 ** TODO BUG xwidget view ghosts
291 - xwidget-webkit-browse-url somewhere
293 now theres 2 webkit views
295 now theres 2 views but one is a ghost!
296 one should have been deleted when its window died but that didnt work
297 for some reason here.
299 - m-x xwidget-cleanup
301 the ghost goes away because we killed explicitly but this is just a workaround.
303 xwidget_view_delete_all_in_window(w); in delete-window-internal is not sufficient.
304 delete-other-windows-internal
305 delete_all_subwindows
308 Added cleanup those window configuration hook which works in practice
311 ** DONE BUG annoying backtrace
312 CLOSED: [2011-07-19 Tue 14:28]
313 (this no longer seems to happen even under heavy usage. seems merging
314 from trunk helped. lots were happening in redisplay at this time in trunk.)
317 - happens even with no initialized xwidgets
318 - + row->glyphs[area][i].face_id
319 or similar code, so row is invalid for some reason.
320 xwidgets currently disable some redisplay opimizations so it might be
321 an actual emacs bug manifesting without optimizations.
324 /* Compute the width of this line. */
325 row->pixel_width = row->x;
326 for (i = 0; i < row->used[TEXT_AREA]; ++i)
327 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
330 #0 0x000000000045c340 in compute_line_metrics (it=0x7fffffff8a20)
332 #1 0x00000000004603da in display_line (it=0x7fffffff8a20) at xdisp.c:18792
333 #2 0x0000000000457646 in try_window (window=23403045, pos=..., flags=1)
335 #3 0x00000000004559c9 in redisplay_window (window=23403045, just_this_one_p=0)
337 #4 0x0000000000450247 in redisplay_window_0 (window=23403045) at xdisp.c:13152
338 #5 0x00000000005fdcd9 in internal_condition_case_1 (bfun=
339 0x450208 <redisplay_window_0>, arg=23403045, handlers=12691046, hfun=
340 0x4501d9 <redisplay_window_error>) at eval.c:1538
341 #6 0x00000000004501ba in redisplay_windows (window=23403045) at xdisp.c:13132
342 #7 0x000000000044f19c in redisplay_internal () at xdisp.c:12706
343 #8 0x000000000044f9f2 in redisplay_preserve_echo_area (from_where=7)
345 #9 0x0000000000568525 in swallow_events (do_display=1) at keyboard.c:4197
346 #10 0x0000000000422554 in sit_for (timeout=40, reading=1, do_display=1)
348 #11 0x000000000056512c in read_char (commandflag=1, nmaps=8, maps=
349 0x7fffffffd3f0, prev_event=12720514, used_mouse_menu=0x7fffffffd604,
350 end_time=0x0) at keyboard.c:2689
351 #12 0x0000000000572c59 in read_key_sequence (keybuf=0x7fffffffd850, bufsize=
352 30, prompt=12720514, dont_downcase_last=0, can_return_switch_frame=1,
353 ---Type <return> to continue, or q <return> to quit---
354 fix_current_buffer=1) at keyboard.c:9291
355 #13 0x0000000000562897 in command_loop_1 () at keyboard.c:1446
356 #14 0x00000000005fdb52 in internal_condition_case (bfun=
357 0x5624b4 <command_loop_1>, handlers=12772898, hfun=0x561dab <cmd_error>)
359 #15 0x00000000005621ab in command_loop_2 (ignore=12720514) at keyboard.c:1157
360 #16 0x00000000005fd4ce in internal_catch (tag=12768770, func=
361 0x562185 <command_loop_2>, arg=12720514) at eval.c:1247
362 #17 0x000000000056215e in command_loop () at keyboard.c:1136
363 #18 0x00000000005618f9 in recursive_edit_1 () at keyboard.c:757
364 #19 0x0000000000561a95 in Frecursive_edit () at keyboard.c:821
365 #20 0x000000000055fba2 in main (argc=1, argv=0x7fffffffe188) at emacs.c:1704
370 ** DONE Examine using XComposite rather than GTK off-screen
371 rendering. This would make xembed widgets work much better. This
372 would probably be rathter difficult, but could open up other
373 interesting possibilities for Emacs. There is an early attempt in
374 xwidget.c, but the X call to redirect to offscreen rendering fails
377 the attempt was further worked on, and the xlib calls replaced with
378 gdk calls, this works better.
380 In the end I abandoned this aproach. Xwidget-osr is the new aproach.
382 ** TODO make the keyboard event code propagation code work.
383 There is an attempt to provide an api to send keyboard events to an
384 xwidget, but it doesnt currently work very well.
386 *** TODO try gtk event creation instead
387 since that works fine in the webkit osr code.
388 but, oh no, that didn't work for some reason.
389 the widgets seems to receive the event but then the embedded widgets
393 *** TODO examine some library to synthesise events
398 ** DONE remove the special-case for when the minibuffer is
399 active. I added some code to reduce the annoying problem display artefacts
400 when making the minibuffer the selected window. This made xwidgets in the
401 buffer go grey or black whenever one did m-x to activate the minibuffer. The
402 coded tried to handle the minibuffer as a special case. That simply wasnt a
403 good idea. Special-casing will never work properly. It is much better to spend
404 time finding solutions that work acceptably in the general case.
406 ** DONE disable emacs cursor drawing on top of an active xwidget.
407 This ought to be rather simple and should improve the visuals a lot.
409 ** TODO improve the xwidgets programming interface
410 so its less of hand-waving affair. This shouldnt be too hard, but I
411 have deliberatley not spent any time on it, since getting the
412 visuals right is much harder. Anyway, I sort of think the interface
413 should be somewhat like it is, except symbols is used instead of
415 *** DONE use symbols for xwidget types rather than ints
416 CLOSED: [2011-06-27 Mon 12:52]
419 *** TODO better lisp based structure for xwidgets
420 the lisp interface woud be like this:
421 - make-xwidget returns an xwidget object, similar to a process
422 object. this object is used when creating the display spec(instead of
423 the user defined id now used)
425 the data structure would be something like this:
426 - a "process" like aproach to create the xwidgets. xwidgets are
427 coupled to buffers, somewhat like processes, except a buffer can
428 hold several xwidgets
429 - an xwidget has a plist to hold the model, like a process
430 - an xwidget has an assoc list of xwidget views
432 there are some things that arent clear:
433 - an xwidget doesnt necessarily need to be coupled to a buffer but it
434 seems to be the clearest model. xwidgets would be buffer local
435 - xwidget-views are by necessity coupled to a emacs window so it might
436 be better to store them window locally rather than in an assoc
437 coupled to the xwidget model
438 - for some gtk widgets that resist an mvc approach, like the webkit
439 widgets, special operations are needed, similar to the old phantom
440 widgets aproach. so we need to differentiate live and phantom
441 instances for these troublesome widgets and let lisp manage all the trickery.
443 stuff that needs to work:
444 - do something for all views of a xwidget(resize, value change)
445 - do something for all xw-views in an emacs window(deletion etc)
446 - lookup xw-view for xwidget in emacs window(during redisplay)
447 (- do something for all siblings of a xw-view. not atm)
449 *** DONE xwidget creation interface
450 CLOSED: [2011-07-18 Mon 01:59]
451 xwidgets are a little bit like emacs processes but also a little bit
452 like emacs images. Therefore its not perfectly obvious how to handle
453 creation. Currently I just use hardcoded identifiers. the real scheme
454 needs to be something else.
456 Heres a tentative approach:
457 - xwidget-create returns a xwidget object, like process creation
458 functions. the xwidget will be largely uninitialized until
459 discovered by redisplay. an xw belongs to a buffer
460 - xwidget-insert inserts the xwidget in a buffer. when discovered by
461 redisplay it will be initialized and a xwidget-view allocated
462 - an event will be emitted when initialization is finished when
463 relevant like for sockets
465 the problem with this aproach is that its not really legal to reuse
466 xwidget objects by writing several display specs who reference the
467 same xwidget. It could presumably be done but it would just become
468 weird for no real benefit. the big preblem is that the display spec
469 decides the on-screen size, and its not sane to have xwidget views
470 with different sizes. therefore such display specs would need to be
471 catched and dissallowed. Except it is hard because AFAIK the specs
472 don't have an identity as such. A flag in the structure could be set
473 by lookup so the first display attempt would win. but then you can't
474 rewrite the spec to change the size. hmmm. A third approach would be
475 to just allow the 1st spec refering an xw during a redisplay to take
476 effect, the rest are signaled as errors. this wouldnt be too bad.
478 the other aproach would be to work more like images:
480 - write the display spec with all information needed to create the
482 - retrieve the xwidget objet from the spec with an xwidget-at-point function. It
483 can be uninitalized which client code must handle. Unlike
484 assynchronous process creation we dont get back a handle, because
486 - emitted event on initialization, when needed. Many widgets don't
487 need this. for instance, a button sends an event when pressed. but
488 you can't press it unless its on screen, and then its initialized
491 This approach seemed good, but how do I know which instance
492 generates an event if I cant set the id beforehand?
494 so, therefore, the first two aproach is used.
497 *** DONE xwidget creation interface actually
498 CLOSED: [2011-07-18 Mon 01:59]
499 conclusion of above ramblings:
500 - should be similar to make-text-button
501 - don't init from display spec, instead during make-xwidget call
502 *** TODO callbacks would be nice
503 but they need to be handled initially with events for technical
504 reasons. C code can't call Lisp easily. The event handler can call the
507 ** TODO more documentation
508 There should be user docs, and xwidget contributor docs. The current README
509 is all contributor docs there is now, apart from the code.
513 ** CANCELLED look into more ways of displaying xwidgets, like binding them to a
514 CLOSED: [2011-07-05 Tue 11:34]
515 window rather than a point in a buffer. This was suggested by Chidong.
516 This would be a useful addition to Emacs in itself, and would avoid nearly all
517 display issues. I still think the general case is more interesting, but this
518 special case should also be added. The xwidget would then be bound to
519 replace the view of a particular window, and it would only show in
522 I got the webkit xwidget to work well enough so I dont see the need
523 for this now, except for sockets and I think it can better be dealt
524 with at the lisp level.
526 ** DONE MVC mode for xwidgets
527 CLOSED: [2011-06-27 Mon 12:53]
528 It appears unfruitful to chase using the same display mode for all
529 types of xwidgets. Composition is fun but not robust the way I
532 Instead there should be a set of MVC xwidgets. Each on-screen instance
533 of an MVC widget would be a real GTK widget. The instances would
534 communciate state using signals.
536 There are drawbacks. There is no inbuilt support for MVC in GTK, so we
537 have to roll our own, which is tedious if not much work for the few
540 MVC for xembedded application will need support from the applications
541 themselves. Inkscape supports multiple views to the same document,
542 other programs don't. In practice it might not be a big drawback.
545 *** DONE figure out what to do with the multiple frames case.
546 CLOSED: [2011-06-27 Mon 12:52]
547 This should be easier to solve with MVC.
548 Surprisingly, this just worked!
549 *** DONE how to propagate changes in views to other views?
550 CLOSED: [2011-06-27 Mon 12:53]
551 I used gtk signals, the implementation for sliders works well!
553 ** TODO canvas support
554 heres an interesting comparision of gtk canvases
555 http://live.gnome.org/ProjectRidley/CanvasOverview
557 goocanvas is a gtk canvas implemented using cairo. investigate.
560 - it has a MVC model aproach out of the box which is nice.
562 http://developer.gnome.org/goocanvas/unstable/goocanvas-model-view-canvas.html
564 export CFLAGS="`pkg-config --cflags goocanvas` -DHAVE_GOOCANVAS"
565 export LDFLAGS=`pkg-config --libs goocanvas`
569 I made a hello goo world xwidget so seems doable.
570 I wanted to load a SVG which wasnt immediately straightforward, so I
571 tried clutter. but it turns out the exact same strategy could be used
575 maybe clutter can be used as a canvas?
577 - seems to have a lot of traction atm. many examples
578 - potentialy fast and cool vector graphics
580 - no out of the box MVC support, but seems doable. no worse than the
581 other home brew mvc support I have in xwidgets
582 (media-explorer in an application that employes the MVC pattern)
584 http://www.openismus.com/documents/clutter_tutorial/0.9/docs/tutorial/html/sec-stage-widget.html
586 there is also cool stuff like this:
587 http://gitorious.org/webkit-clutter/webkit-clutter which is an webkit actor for
590 I want to render svg. aparently:
591 librsvg rsvg_handle_render_cairo(h, cr);
595 export CFLAGS="`pkg-config --cflags clutter-gtk-1.0` -DHAVE_CLUTTER"
596 export LDFLAGS=`pkg-config --libs clutter-gtk-1.0`
601 Gtk-ERROR **: GTK+ 2.x symbols detected. Using GTK+ 2.x and GTK+ 3 in
602 the same process is not supported
604 export CFLAGS="`pkg-config --cflags clutter-gtk-0.10` -DHAVE_CLUTTER"
605 export LDFLAGS=`pkg-config --libs clutter-gtk-0.10`
611 expose the DOM to lisp or something. The webkit xwidget works pretty
612 well now, so this might be the way ahead.
613 ** DONE mvc code crashes after a while
614 CLOSED: [2011-07-12 Tue 18:52]
615 seemingly only when compiling with optimizations.
618 Doesn't seem to happen after some code cleanups.
619 ** DONE xwidget-resize-at
620 CLOSED: [2011-07-19 Tue 14:28]
621 reimplement so display spec is not involved
622 ** DONE display spec validation
623 CLOSED: [2011-07-19 Tue 14:44]
624 it is an error to reuse xwidgets in several buffers or in the same
625 buffer. how do we catch these errors?
626 - showing the same xwidget twice in a buffer is no more wrong than
627 showing in several emacs windows, just conceptually wrong, so ignore
629 - xwidgets now store a reference to the buffer they were created in,
630 so use that to invalidate xwidget references in oher buffers. but
631 thats not really an error either
632 - xwidgets should now be proper lisp objects so you dont delete them
633 you await their garbage collection. so therefore there can never be
634 invalid disploy specs
636 so turned out this got solved by using proper lisp objects for
639 ** DONE clipping of controllers
640 CLOSED: [2011-07-05 Tue 11:33]
642 Emacs uses a big GTK window and does its own clipping against Emacs
643 windows inside this area. So, in order to layout gtk widgets in emacs
644 windows we must clip thim ourselves.
646 The following method worked well for a long time:
647 - make a gtk widget, say a button, xw
648 - make a clipping area, of type gtkfixed(many types have been tested)
649 - put the clip area in the main emacs gtk window
650 - figure out clip area changes during emacs redisplay
652 the only weirdness was that one has to tell gtk the clip area has a
653 window in order to get clipping. This is weird because all gtkwidgets
654 are windows in a sense and a window is almost by definition also a
657 Anyway, in GTK3 the gtk_widget_set_has_window(GTK_WIDGET (
658 xv->widgetwindow), TRUE); call is ignored.
660 The gtkeventbox which is documented to have its own window doesnt work
663 http://www.lanedo.com/~carlos/gtk3-doc/chap-drawing-model.html
665 anyway clipping is rather complicated but seems to finally work okay.
667 *** DONE subclass my own clipping widget
668 CLOSED: [2011-07-04 Mon 16:55]
669 http://www.lanedo.com/~carlos/gtk3-doc/GtkWidget.html#gtk-widget-set-has-window
670 mentions that it has_window can only be called inside a widget
673 this wasnt really the issue. allocation was the problem
674 *** DONE try scrolled window
675 CLOSED: [2011-07-01 Fri 10:56]
676 clipping does in fact work with
677 gtk_scrolled_window_add_with_viewport (xv->widgetwindow, xv->widget);
680 I get unwanted scrollbars in the widget though.
682 gtk_scrolled_window_set_policy ( xv->widgetwindow,
683 GTK_POLICY_NEVER, GTK_POLICY_NEVER);
685 stops clipping from working!
688 *** DONE try viewport
689 CLOSED: [2011-07-01 Fri 10:56]
690 gtkviewport is used in scrolled window so in order to remove
691 scrollbars it should be possible to use viewport directly. however,
692 viewport ignores size requests. or rather the container does.
695 *** DONE debug allocation
696 CLOSED: [2011-07-04 Mon 16:56]
697 the container determines how much size to allocate to child widgets.
699 GtkAllocation galloc;
700 gtk_widget_get_allocation(GTK_WIDGET (xv->widgetwindow), &galloc);
701 printf("allocation %d %d , %d %d\n", galloc.x,galloc.y,galloc.width,galloc.height);
703 after my clipping attemp shows that my size request is ignored! this
704 might be logical, since the container provided by emacs is a
705 gtkfixed. gtkfixed might choose to heed the widgets size desires and
706 allocate the entire widget size. but we want clipping!
708 since i cant reasonably expect to change the emacs main container, i
709 can maybe overide the setallocation method in gwfixed, and adjust
710 allocation to clipping if its an xwidget asking for allocation.
712 **** DONE subclass gtkfixed
713 CLOSED: [2011-07-04 Mon 16:56]
714 possibly i need to subclass gtkfixed and override
716 void gtk_widget_size_allocate (GtkWidget *widget,
717 GtkAllocation *allocation);
719 http://developer.gnome.org/gobject/stable/howto-gobject.html
721 turns out emacs already does this for gtk3 according to jan D:
722 >>For GTK3, Emacs already subclasses GtkFixed, see emacsgtkfixed.[ch].
724 - widgets may not be underallocated, aparently
725 http://mail.gnome.org/archives/commits-list/2011-April/msg10950.html
727 - how to call base class method/chain up
728 http://developer.gnome.org/gobject/stable/howto-gobject-chainup.html
730 - the allocation modification could happen in the container or the
731 child. it feels more apropiate in the container
733 it is however unexpectedy inconvenient to modify allocation because
734 the needed data is private to the base class. to overcome this:
736 - run base class method 1st.
737 - then, iterate all children, and modify allocation for xwidget
738 children only. x y will then be set.
740 JanD pointed out the GTK3 port already has its own subclass, so I
744 CLOSED: [2011-07-05 Tue 11:30]
745 there are four controller edges that potentialy need clipping. I begun
746 with right and bottom edges. clipping them is just a matter of setting
747 the right size of the widgetwindow and also ensure it gets the right
748 allocation from the container.
750 clipping top (and left) is not equally straightforward. I'm using a
751 viewport now and scroll it the amount that needs to be clipped.
752 however, the viewport is sensitive to changes in allocation, which
753 makes it harder to use the allocation workarounds.
756 - gtk_widget_set_size_request
759 I returned to using a simple gtkfixed for the widgetwindow. with
760 allocation hack and set_has_window it works. Idea prefer not to have
761 the allocatien hack and it wasnt needed it gtk3 only gtk2. needs
762 furthi investigation,
764 ** various code cleanups
765 There are many cleanups necessary before any hope of inclusion in
766 Emacs trunk. To begin with, the part of the patch that touches other
767 parts of emacs must be very clean.
768 *** DONE use FRAME_GTK_WIDGET (f)
769 CLOSED: [2011-07-20 Wed 20:02]
772 *** DONE support configure
773 CLOSED: [2011-07-12 Tue 18:48]
774 *** DONE ifdef all xwidget code
775 CLOSED: [2011-08-13 Sat 16:19]
776 so you can reliably disable the code at compiletime
777 ** DONE translate clicks
778 CLOSED: [2011-07-03 Sun 22:12]
779 on onscreen webkit peer to offscreen
782 http://developer.gnome.org/gdk/stable/gdk-Windows.html#GdkWindow-from-embedder
784 turned out to be not so hard, captured events, copied them and
785 forwarded them offscreen!
787 ** TODO investigate gdk_window_redirect_to_drawable
788 http://developer.gnome.org/gdk/stable/gdk-Windows.html#gdk-offscreen-window-set-embedder
789 maybe could be used in place of my own copy hacks? to work it must
790 support a chain of redirects, which seems unlikely. the benefit would
791 be that I dont have to spend time optimizing redrawing.
794 ** DONE remove xwidget_views when emacs window is deleted
795 CLOSED: [2011-07-05 Tue 11:29]
796 removing xwidget views when an Emacs window closes is not reliable.
798 - switching buffers in a window seems to hide the corresponding
799 xwidget-views properly, but they might as well be deleted.
801 - patching delete-window-internal could be used to delete the xwidget-views
806 although embedding a browser is not my primary concern many are
807 interested in this. some suitable browser component needs to be found
811 CLOSED: [2011-07-03 Sun 22:13]
812 there is a webkit gtk port. there is no obvious mvc support.
813 http://live.gnome.org/WebKitGtk
814 http://webkitgtk.org/
816 it might be possible to keep a set of webxits in artificial
817 synchronisation by recursive deep copy of the DOM from one webkit to
818 another. This will be error prone at best though. Another way might be
819 to just use bitmap copy of the "live"instance to the "phantom"
820 instances. the problem of transfering the live view remains though.
822 export CFLAGS="`pkg-config --cflags webkit-1.0` -DHAVE_WEBKIT -g"
823 export LDFLAGS=`pkg-config --libs webkit-1.0`
827 **** off screen rendering
828 export CFLAGS="`pkg-config --cflags webkit-1.0` -DHAVE_WEBKIT_OSR -g"
829 export LDFLAGS=`pkg-config --libs webkit-1.0`
833 works a little bit but i get errors like:
835 (emacs:8362): GLib-GObject-WARNING **: invalid cast from `GdkOffscreenWindow' to `GdkDrawableImplX11'
837 set a breakpoint in g_log, backtrace seems to indicate
838 webkitViewportAttributesRecompute is the offender.
840 maybe try gtk3 variants?
842 export CFLAGS="`pkg-config --cflags webkitgtk-3.0 ` -DHAVE_WEBKIT_OSR "
843 export LDFLAGS=`pkg-config --libs webkitgtk-3.0 `
844 ./configure --with-x-toolkit=gtk3
847 crash in gtk_window_get_size instead. great.
849 http://gtkplus-p3.0.sourcearchive.com/documentation/2.91.5-0ubuntu1/testoffscreenwindow_8c-source.html
851 after many atempts, the basic issue remains. for some reason the
852 offscreen widget isnt ok when I want to snapshot it, so i simply get
853 emptiness. the surface is only ok someimes.
855 here is a useful debugging snippets:
857 // - the bg colors always change, so theres no error in signal handling
858 // - i get this error now and then:
859 //(emacs:7109): GLib-GObject-WARNING **: invalid cast from `GdkOffscreenWindow' to `GdkDrawableImplX11'
860 // seems to happen in webkit actually. see README
862 if(0){ //redraw debug hack. helped a lot in fact. use the with alpha painter below also
863 cairo_set_source_rgb(cr, osr_dbg_color, 1.0, 0.2);
864 cairo_rectangle(cr, 0,0, xw->width, xw->height);
867 if(osr_dbg_color>1.0)
872 you need to terminate drawing like this:
874 //cairo_set_source_surface (cr, src_pixmap, 0,0);
875 //cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
877 //cairo_paint_with_alpha (cr, 1.0);
880 the snippets change background color on oach redraw.
882 **** on-screen rendering to separate window
883 an alternative might be to open a separate window and snapshot it. the
884 idea is that whatever oddness webkit does so that offscreen rendering
885 doesnt work, doesnt happen on-screen. the window could be opened
886 somewhere not in the way.
888 *** CANCELLED firefox
889 CLOSED: [2011-07-03 Sun 22:13]
890 http://www-archive.mozilla.org/unix/gtk-embedding.html
891 seems to be severly bitrotted
893 heres a newer aproach
894 http://hg.mozilla.org/incubator/embedding/file/29ac0fe51754/gtk/tests/test.cpp
896 while webkit clearly has the best traction as an embeddee, the
897 offscreen rendering issues makes it interesting to see what ff brings
900 turned out webkit has as good offscreen support as anyone, see I went
901 with that in the end.
904 *** DONE text field support
905 CLOSED: [2011-07-20 Wed 20:05]
906 Emacs captures all keyboard events so text field support isn't super
909 **** propagate keyboard events
910 I have some old hacks for this and they are not good.
911 **** use the DOM model
912 expose document.activeElement to lisp. This is potentially more
913 interesting than just forwarding keyboard events.
915 webkit_web_view_get_dom_document ()
917 this is hard it seems. an idea might be to hack elisp support for swig
918 to machine generate the bindings.
919 **** DONE inject javascript
920 CLOSED: [2011-07-03 Sun 22:50]
921 webkit_web_view_execute_script ()
924 (xwidget-webkit-execute-script 5 "document.activeElement.value='test'")
926 so it should be possible to do some interesting stuff.
927 execute-script does however not return anything at the interface level
928 so satisfaction is not total:
930 http://markmail.org/message/4yowmdgras73z3x5
933 https://launchpad.net/gnome-seed
936 <jave> im trying to understanh how to interact via javascript to an embedded
937 webkit gtk instance [23:38]
938 <jave> i use webkit_web_view_execute_script() which is nice but doesnt return
939 a value, by design aparently [23:39]
941 <lucian> jave: afaik, webkit still doesn't have full gobject bindings [23:48]
942 <lucian> jave: you can hack it up by making the JS modify the title, and read
943 the title from gtk-side
944 <jave> lucian: that was a pretty cool idea!
947 *** webkit_web_view_load_string ()
948 I would like preview of html in a buffer rather than from uri.
952 *** DONE simple xwidget-webkit wrapper
953 CLOSED: [2011-07-22 Fri 11:01]
954 so that it could be used for actual browsing :)
955 I dont want to reinvent too many wheels so i'd like to use existing
956 emacs facilities here possible. use bindings similar to w3m(or info)
958 - m-x xwidget-webkit starts a session
960 - use bookmark-jump i suppose. I mostly use org for bookmarks myself
961 - browse-url support so webkit can be the default browser
962 - some way of getting around the quirky keyboard interaction since
963 xwidgets dont receive keyboard events because I hawe no idea how to
964 do that in a sane way
966 ... and one can of course go on bikeshedding forever. lets keep it
967 simple and extensible, and compatible with other Emacs packages.
969 the really cool ideas would need Emacs DOM integration, which is not
973 *** TODO webkit support webkit signals
975 **** DONE particularily document-load-finished
976 CLOSED: [2011-08-01 Mon 22:34]
977 http://webkitgtk.org/reference/webkitgtk-webkitwebview.html#WebKitWebView-document-load-finished
978 because one might need tell set a title and sizes and things when it loads.
980 Debugger entered--Lisp error: (error "Two bases given in one event")
982 hapens sometimes with xwidget events. appears to be when the
983 originating xwidget is offscreen so that the event doesn't get caught
984 by the correct emacs event map.
986 maybe I need to set the originating window in the event structure.
987 event.frame_or_window = Qnil; //frame; //how to get the frame here? //TODO i store it in the xwidget now
989 since its an offscreen xwidget the buffer local keymap isnt the right
990 place for the handler. some global map should be used.
992 onscreen widgets don't have the same issue.
994 anyway, seems it'll turn out like this:
995 - xwidget-osr stores a callback and user data
996 - the event is an implementation detail only and get caught in the
998 - the event map calls the callback in the xw with the right args.
1000 we need the event handler at some level because we can't call lisp
1003 *** TODO console messages
1004 http://webkitgtk.org/reference/webkitgtk-webkitwebview.html#WebKitWebView-console-message
1005 http://getfirebug.com/wiki/index.php/Console_API#console.count.28.5Btitle.5D.29
1006 because maybe we can make a simple JS REPL that way.
1007 (xwidget-webkit-execute-script ( xwidget-webkit-last-session)
1008 "console.log('hello')")
1009 prints hello to stdout but theres no way to catch stdout from webkit I
1010 think other than receiving the signal.
1012 *** TODO webkit flashkiller by default
1013 while its possible to support plugins in the webkit xwidget, flash has
1014 issues on 64 bit, and slows down emacs to a halt with off screen
1015 rendering, and of course is not free software. its in the way for real
1016 world usage even if its interesting to watch flash animations inside
1017 emacs. which should be achieved with Gnash or other free software
1020 http://stackoverflow.com/questions/4885513/prevent-flash-in-cocoa-webview
1022 simply use this api:
1023 http://webkitgtk.org/reference/WebKitWebPluginDatabase.html
1025 theres an implementation now but it's not robust enough webkit often
1026 crashes taking emacs with it.
1028 *** TODO webkit downloads
1029 when clicking a download link in Webkit Emacs should take over and handle it
1030 from there. Probably need signals. There are Emacs libraries to
1031 download things, with wget etc. an url.el facility should be made.
1032 "download-requested"
1033 *** TODO webkit alt-text not handled
1034 XKCD use image-title to display a cartoon comment. These mysteriously
1035 don't work ATM. Other mouseovers work though. Maybe webkit tries to
1036 open a new window or something, which wont work.
1038 *** TODO webkit isearch in webkit buffers
1039 have a look at how docview solves it
1040 webkit_web_view_search_text ()
1041 *** TODO webkit relative references doesn't work
1042 probably because we handle scrolling in a non-standard way. It does
1043 work sort of when theres a html frameset and webkit scrolls by itself.
1045 *** TODO webkit width adjustment handling issue
1046 since there are so many levels of clipping and whatnot in xwidgets
1047 sizing issues are difficult.
1049 - an xwidget is told how large it can be by emacs. thats the end of
1050 it. if the xwidget thinks otherwise it will be clipped.
1051 - but emacs can ask the xwidget how large it wants to be. it can then
1052 resize the reserved area and inform the xwidget thusly.
1054 That should have been enough. but webkit never reports less than what
1055 it already has. So currently a webkit view will only growth and not
1056 adjust to smaller sizes.
1058 This is not a big problem in practice but is still annoying.
1060 to see the problem surface to http://www.slashdot.org
1061 - xwidget-webkit-adjust-size
1062 - xwidget-webkit-adjust-size-to-content
1064 and then compare by resizing in Epiphany, which is also webkit based.
1066 *** TODO xwidget webkit allow loading from string from emacs
1067 *** DONE xwidget-webkit-last-session
1068 CLOSED: [2011-08-01 Mon 22:38]
1069 was rather hurried. end result is that the lisp layer only really
1070 allows for one webkit session.
1071 *** TODO extract DOM to lisp
1072 then the SHR html renderer from Gnus could render the DOM as created
1075 made a simple oxperimental DOM tree traverser. It can be expanded to
1076 return a lisp representation, LDOM.
1078 in order to bring lisp and DOM closer together the LDOM can include a
1079 mapping to the originating DOM node. so, find a node in LDOM, and the
1080 cell maps to the original DOM. but since the LDOM is a copy it can get
1081 out of sync. DOM events might help.
1082 *** DONE C-X b in other buffer from webkit
1083 CLOSED: [2011-08-12 Fri 22:20]
1084 bafflingly resets the webkit view to the top. Maybe the window
1085 reconfiguration hook code? further mystification is added because it
1086 only seems to happen with ido mode enabled.
1088 in comparison with image-mode which does the right thing, I discovered
1089 that image-mode has special code to handle scrolling. the browser mode
1090 and image mode has some similarities.
1092 I made some delegation code frrom webkit mode to image mode.
1093 ** TODO xwidget image display spec compatibility
1094 some history: the first version of the xwidget display spec was
1095 the same as an image spec. This turned out not to be fantastic because
1096 an xwidget is both like a process and like an image. it has a separate
1097 existence from display. So now the xwidget display spec is just a
1098 pointer to a xwidget. But then some useful functionality in Emacs
1099 can't be reused for xwidget, in particular image-mode.
1101 Maybe a new image type could be added that was a wraper on an
1102 xwidget. Then image mode could be reused for webkit mode.
1104 I tried some adaptor code in xwidget.el so webkit mode now delegates
1105 to image mode buh its a kludge.
1108 *** TODO some flickering during redisplay of sockets
1109 with gtk3 an size allocation workaround is used.
1110 this seems maybe to result in flickering sizewize y-axis with the
1111 xwidget socket type. The webkit xwidget doesn't seem similarily
1114 the size allocation workaround works by 1st running the ordinary
1115 allocation then modifying the results. its done this way to minimise
1116 the copy paste index from the base class. it might be that the
1117 original allocation has a brief time window to show itself.
1119 tried to modify the allocation hack so it doesn't call allocate
1120 twice. this doesn't seem to help flicker at all aparently so the
1121 hypothesis falls. Maybe then a socket simply doesn't lke being clipped
1124 *** TODO xwidget view reaping too agressive
1125 hide an emacs window for a while and return to it. the xwidget might
1126 get reaped and a new socket thus created.
1127 *** DONE try out OSR for sockets
1128 CLOSED: [2011-07-25 Mon 21:30]
1130 didn't work too well in the inkscape case. it might be that some other
1131 bitmap copy method works better though.
1133 basically sockets doesn't like to be offscreen because they want their
1136 ** DONE synchronise emacs background with xwidget color
1137 CLOSED: [2011-08-11 Thu 11:04]
1138 fine-tuning to reduce flicker.
1140 isn't needed if emacs bg erase disabled
1142 ** DONE xwidgets doesn't work during bootstrap all of a sudden
1143 CLOSED: [2011-08-01 Mon 22:33]
1144 might be some annoying local issues with my install because it is not
1145 reliably reproducible. (went away during merges)
1147 ** TODO low impact xwidget based image viewer
1148 for instance to render SVG using webkit, or some other canvas.
1149 that way it would be possible to merge to trunk in stages.
1151 so, webkit could be used to display the SVG. the display spec for
1152 images would be used. multiple webkits would be used rather than
1153 offscreen rendering, so it would be GTK2 compatible.
1154 ** DONE xwidget movement doesn't work all of a sudden
1155 CLOSED: [2011-08-11 Thu 11:03]
1156 this used to work great. now it doesn't.
1160 - x_shift_glyphs_for_insert
1161 - x_scroll_run. this is run by the try_window* functions, and
1162 inhibiting them dösnt help. but also callid in scrolling_window.
1165 - try_window_reusing_current_matrix
1166 - I used to enable GLYPH_DEBUG which I currently don't. it disables
1167 many optimisations. this was fixed.
1168 - lookup_xwidget then produce_xwidget_glyph gets called always but not
1169 x_draw_xwidget_glyph_string probably because of scroll optimization.
1170 movement detection could possibly be moved to produce_xwidget_glyph(not)
1173 (setq inhibit-try-window-id t)
1174 (setq inhibit-try-window-reusing t)
1177 (run-with-timer 1 1 'redraw-display)
1180 inhibiting scrolling_window(). and this seem to be enaugh to restore
1181 old behaviour, GLYPH_DEBUG doesn't seem needed.
1184 ** DONE GLYPH_DEBUG doesn't work
1185 CLOSED: [2011-08-08 Mon 17:30]
1186 was stupid accidental line removal that was hard to spot
1187 ** TODO osc xwidget example
1188 a couple of xwidget sliders that control a csound/supercollider song with osc.
1189 so, for that to work we need slider callbacks to work. when a slider
1190 changes send an osc message. use ocssend:
1192 oscsend localhost 7777 /sample/address iTfs 1 3.14 hello
1195 http://delysid.org/emacs/osc.el
1197 sliders could be defined in csound comments or something to illustrate
1198 the point. or if real fanciness is desired parse the csound source
1199 with Semantic and provide a control buffer corresponding to the
1204 Added: [2011-08-11 Thu 10:53]
1208 the SEB site does something funny so I can't insert text in fields