]> code.delx.au - gnu-emacs/blob - README.xwidget
notes
[gnu-emacs] / README.xwidget
1 * Xwidgets
2
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.
6
7 There is a demo file called xwidget-test.el which shows some of the
8 possibilities. There are some screnshots at the emacswiki.
9
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.
14
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.
18
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
21 Emacs window.
22
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.
26
27 ** building
28 bzr co bzr+ssh://bzr.savannah.gnu.org/emacs/xwidget/
29 export CFLAGS=" -g -DGLYPH_DEBUG=1"
30 ./configure --with-x-toolkit=gtk3 --with-xwidgets
31 make -j4
32
33 ** try it out
34 If you have GTK3 and gtk-webkit installed, you should be able to
35 started the embedded webkit browser now:
36
37 M-X xwidget-webkit-browse-url
38
39 If that didnt work out try the minimal demonstration instead:
40
41 (load-library "xwidget-test")
42 (xwidget-demo-a-button)
43
44 It looks unimpressive, but it's a gtk button inside an Emars buffer!
45
46 ** Stability
47 Beginning with Summer 2011 I am now able to use Xwidget Emacs as my
48 primary Emacs. That is good for the project and the stability of the
49 code.
50
51 At the time of writing I have 24 hour Emacs uptime with several
52 embedded webkit browsers, Gnus, org-mode, tramp, etc. etc.
53
54 That said, there are still many improvements that needs to be done,
55 particularily in memory management. Expect xwidget emacs to leak
56 heavily for now.
57
58 ** timeline for inclusion in trunk
59 The Emacs 24 feature freeze is passed, so xwidgets won't probably be merged
60 until Emacs 25. OTOH since I now use xwidget emacs as my primary
61 emacs, I will merge from trunk much more often than in the past.
62
63 ** Thanks
64 emacs-devel@gnu.org. There are very helpful people there. When I
65 started the xwidget project I had no clue about the Emacs internals.
66
67 * Brief overview of how xwidgets work
68 Xwidgets work in one way like images in Emacs. You bind a display spec very
69 similar to an image display spec to buffer contents. The display engine will
70 notice the display spec and try to display the xwidget there. The display engine
71 prepares space at the right place for the xwidget and so on for free, as long as
72 we provide proper sizes and so on back to the redisplay engine.
73
74 ** Issues
75 The problem is that Emacs cant actually draw the widgets, as it can with
76 images. Emacs must notify GTK about where the widgets should be, and how they
77 should be clipped and so on, and this information must be given to GTK
78 synchonous with Emacs display changes. Ok, so why is that difficult then?
79
80 - How do we know when a widget is NOT to be drawn? The only way I found so far
81 is having a flag for each xwdiget, that is reset before a redisplay. When an
82 xwidget is encountered during display, the flag is set. After redisplay,
83 iterate all xwidgets and hide those which hasnt been displayed.
84
85 - The gtk socket type for embedding external applications is desirable
86 but presents a lot of difficulties of its own. One difficulty is
87 deciding which input events to forward, and when and how to do it.
88
89 ** placement and clipping
90 the entire emacs frame is a gtk window. we use the fixed layout
91 manager to place xwidgets on the frame. coordinates are supplied by
92 the emacs display engine. widgets are placed inside an intermediate
93 window, called the widgetwindow. the widgetwindows are placed on the
94 emacs frame.
95
96 this way was chosen to simplify clipping of the widgets against emacs
97 window borders.
98
99
100 ** different strategies
101 Integrating toolkit widgets(gtk in this case) and the emacs display
102 engine is more difficult than your plain average gui application, and
103 different strategies has been tested and will continue to be tested.
104
105 There was a distinction between live xwidgets and
106 phantom xwidgets, previous to the change to MVC.
107
108 - the first aproach was to have the live xwidget on-screen, and move
109 them about. the phantoms were generated by snapshoting the live
110 xwidget.
111
112 the drawback of that aproach was that the gtk toolkit is admirably
113 lazy and doesnt draw the widget if its not actualy shown, meaning that
114 the snapshots for the phantoms will show garbage.
115
116 - the second aproach was to use composition support. that tells gtk
117 that the widget should be drawn in an off-screen buffer and drawn on
118 screen by the application.
119
120 this has the primary advantage that the snapshot is always
121 available, and enables the possibility of more eye-candy like drawing
122 live and phantom widgets in different colors.
123
124 the drawback is that its our own responsibility to handle drawing,
125 which puts more of the display optimization burden on us.
126
127 this is aproach worked so-so.
128
129 - another aproach is to have both live and phantom widgets drawn
130 on-screen by proxy gtk objects. the live xwidget will be entirely
131 handled in an off-screen window, and the proxy objects will redirect
132 events there.
133
134 - combine on-screen and off-screen aproaches. maybe composition is the
135 way to go for most cases, but on-screen xembeding is the way to go
136 for particular special cases, like showing video in a
137 window. off-screen rendering and whatnot, is not efficient in that
138 particular case, and the user will simply have to accept that the
139 phantom of a video widget isnt particularily beautiful.
140
141 - The current and seemingly sanest aproach implements a MVC pattern.
142
143 ** Testing
144 ;;test like:
145 ;; cd /path/to/xwidgets-emacs-dir
146 ;; make all&& src/emacs -q --eval "(progn (load \"`pwd`/lisp/xwidget-test.el\") (xwidget-demo-basic))"
147
148 ** MVC and Xembedd
149 The MVC approach appears to be at least in principle robust for plain gtk
150 widgets. For the interesting case of gtk sockets which implements an
151 xembed host widget that allows for embedding other applications inside
152 an Emacs window, the story gets more complex.
153
154 The problem is that xembed is designed to plug an application window
155 inside a a secket and thats it. You can't move a plug between
156 sockets. I tried numerous hacks to get around this but there is
157 nothing that works realy well.
158
159 Therefore the Emacs part of the code will only expose well-defined
160 interfaces. cooperating applications will be able to use the interface
161 in a well defined manner. The problem is that there is no known xembeddable
162 application that implement the needed type of functionality, which is
163 allowing for creating new windows on the fly that plug into new
164 sockets.
165
166 Therefore I will attempt to provide an external application that wraps
167 another application and through hacks attempts to provide the needed
168 multi view xembed function. That way Emacs is sane and the insanity
169 contained.
170
171 This app will work by providing a socket that an app plugs into. The
172 socket window is copied efficientlp by means of composition to a
173 number of other windows, that then are plugged into the different
174 Emacs sockets.
175 * ToDo:s
176 ** DONE webkit flashkiller by default
177 CLOSED: [2011-07-19 Tue 14:27]
178 while its possible to support plugins in the webkit xwidget, flash has
179 issues on 64 bit, and slows down emacs to a halt with off screen
180 rendering, and of course is not free software. its in the way for real
181 world usage even if its interesting to watch flash animations inside
182 emacs. which should be achieved with Gnash or other free software
183 instead.
184
185 http://stackoverflow.com/questions/4885513/prevent-flash-in-cocoa-webview
186
187 simply use this api:
188 http://webkitgtk.org/reference/WebKitWebPluginDatabase.html
189
190 ** DONE allow xwidgets to report thoir size
191 CLOSED: [2011-07-19 Tue 14:26]
192 now we just hard code sizes. but webkit widgets for instance can
193 report sizes that suit the content. support that.
194 ** TODO BUG xwidget view ghosts
195 - xwidget-webkit-browse-url somewhere
196 - split window.
197 now theres 2 webkit views
198 - c-x 1
199 now theres 2 views but one is a ghost!
200 one should have been deleted when its window died but that didnt work
201 for some reason here.
202
203 - m-x xwidget-cleanup
204
205 the ghost goes away because we killed explicitly but this is just a workaround.
206
207 xwidget_view_delete_all_in_window(w); in delete-window-internal is not sufficient.
208 delete-other-windows-internal
209 delete_all_subwindows
210 unshow_buffer
211
212 ** DONE BUG annoying backtrace
213 CLOSED: [2011-07-19 Tue 14:28]
214 (this no longer seems to happen even under heavy usage. seems merging
215 from trunk helped. lots were happening in redisplay at this time in trunk.)
216
217 sadly happens a lot.
218 - happens even with no initialized xwidgets
219 - + row->glyphs[area][i].face_id
220 or similar code, so row is invalid for some reason.
221 xwidgets currently disable some redisplay opimizations so it might be
222 an actual emacs bug manifesting without optimizations.
223
224 *** bt 1
225 /* Compute the width of this line. */
226 row->pixel_width = row->x;
227 for (i = 0; i < row->used[TEXT_AREA]; ++i)
228 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
229
230 (gdb) bt
231 #0 0x000000000045c340 in compute_line_metrics (it=0x7fffffff8a20)
232 at xdisp.c:17549
233 #1 0x00000000004603da in display_line (it=0x7fffffff8a20) at xdisp.c:18792
234 #2 0x0000000000457646 in try_window (window=23403045, pos=..., flags=1)
235 at xdisp.c:15399
236 #3 0x00000000004559c9 in redisplay_window (window=23403045, just_this_one_p=0)
237 at xdisp.c:14944
238 #4 0x0000000000450247 in redisplay_window_0 (window=23403045) at xdisp.c:13152
239 #5 0x00000000005fdcd9 in internal_condition_case_1 (bfun=
240 0x450208 <redisplay_window_0>, arg=23403045, handlers=12691046, hfun=
241 0x4501d9 <redisplay_window_error>) at eval.c:1538
242 #6 0x00000000004501ba in redisplay_windows (window=23403045) at xdisp.c:13132
243 #7 0x000000000044f19c in redisplay_internal () at xdisp.c:12706
244 #8 0x000000000044f9f2 in redisplay_preserve_echo_area (from_where=7)
245 at xdisp.c:12964
246 #9 0x0000000000568525 in swallow_events (do_display=1) at keyboard.c:4197
247 #10 0x0000000000422554 in sit_for (timeout=40, reading=1, do_display=1)
248 at dispnew.c:5963
249 #11 0x000000000056512c in read_char (commandflag=1, nmaps=8, maps=
250 0x7fffffffd3f0, prev_event=12720514, used_mouse_menu=0x7fffffffd604,
251 end_time=0x0) at keyboard.c:2689
252 #12 0x0000000000572c59 in read_key_sequence (keybuf=0x7fffffffd850, bufsize=
253 30, prompt=12720514, dont_downcase_last=0, can_return_switch_frame=1,
254 ---Type <return> to continue, or q <return> to quit---
255 fix_current_buffer=1) at keyboard.c:9291
256 #13 0x0000000000562897 in command_loop_1 () at keyboard.c:1446
257 #14 0x00000000005fdb52 in internal_condition_case (bfun=
258 0x5624b4 <command_loop_1>, handlers=12772898, hfun=0x561dab <cmd_error>)
259 at eval.c:1493
260 #15 0x00000000005621ab in command_loop_2 (ignore=12720514) at keyboard.c:1157
261 #16 0x00000000005fd4ce in internal_catch (tag=12768770, func=
262 0x562185 <command_loop_2>, arg=12720514) at eval.c:1247
263 #17 0x000000000056215e in command_loop () at keyboard.c:1136
264 #18 0x00000000005618f9 in recursive_edit_1 () at keyboard.c:757
265 #19 0x0000000000561a95 in Frecursive_edit () at keyboard.c:821
266 #20 0x000000000055fba2 in main (argc=1, argv=0x7fffffffe188) at emacs.c:1704
267
268
269 *** bt 2
270
271 ** DONE Examine using XComposite rather than GTK off-screen
272 rendering. This would make xembed widgets work much better. This
273 would probably be rathter difficult, but could open up other
274 interesting possibilities for Emacs. There is an early attempt in
275 xwidget.c, but the X call to redirect to offscreen rendering fails
276 for unknown reasons.
277
278 the attempt was further worked on, and the xlib calls replaced with
279 gdk calls, this works better.
280
281 ** TODO make the keyboard event code propagation code work.
282 There is an attempt to provide an api to send keyboard events to an
283 xwidget, but it doesnt currently work very well.
284
285 try gtk event creation instead since that works fine in the webkit osr code.
286
287 ** DONE remove the special-case for when the minibuffer is
288 active. I added some code to reduce the annoying problem display artefacts
289 when making the minibuffer the selected window. This made xwidgets in the
290 buffer go grey or black whenever one did m-x to activate the minibuffer. The
291 coded tried to handle the minibuffer as a special case. That simply wasnt a
292 good idea. Special-casing will never work properly. It is much better to spend
293 time finding solutions that work acceptably in the general case.
294
295 ** DONE disable emacs cursor drawing on top of an active xwidget.
296 This ought to be rather simple and should improve the visuals a lot.
297
298 ** TODO improve the xwidgets programming interface
299 so its less of hand-waving affair. This shouldnt be too hard, but I
300 have deliberatley not spent any time on it, since getting the
301 visuals right is much harder. Anyway, I sort of think the interface
302 should be somewhat like it is, except symbols is used instead of
303 integers.
304 *** DONE use symbols for xwidget types rather than ints
305 CLOSED: [2011-06-27 Mon 12:52]
306
307
308 *** TODO better lisp based structure for xwidgets
309 the lisp interface woud be like this:
310 - make-xwidget returns an xwidget object, similar to a process
311 object. this object is used when creating the display spec(instead of
312 the user defined id now used)
313
314 the data structure would be something like this:
315 - a "process" like aproach to create the xwidgets. xwidgets are
316 coupled to buffers, somewhat like processes, except a buffer can
317 hold several xwidgets
318 - an xwidget has a plist to hold the model, like a process
319 - an xwidget has an assoc list of xwidget views
320
321 there are some things that arent clear:
322 - an xwidget doesnt necessarily need to be coupled to a buffer but it
323 seems to be the clearest model. xwidgets would be buffer local
324 - xwidget-views are by necessity coupled to a emacs window so it might
325 be better to store them window locally rather than in an assoc
326 coupled to the xwidget model
327 - for some gtk widgets that resist an mvc approach, like the webkit
328 widgets, special operations are needed, similar to the old phantom
329 widgets aproach. so we need to differentiate live and phantom
330 instances for these troublesome widgets and let lisp manage all the trickery.
331
332 stuff that needs to work:
333 - do something for all views of a xwidget(resize, value change)
334 - do something for all xw-views in an emacs window(deletion etc)
335 - lookup xw-view for xwidget in emacs window(during redisplay)
336 (- do something for all siblings of a xw-view. not atm)
337
338 *** DONE xwidget creation interface
339 CLOSED: [2011-07-18 Mon 01:59]
340 xwidgets are a little bit like emacs processes but also a little bit
341 like emacs images. Therefore its not perfectly obvious how to handle
342 creation. Currently I just use hardcoded identifiers. the real scheme
343 needs to be something else.
344
345 Heres a tentative approach:
346 - xwidget-create returns a xwidget object, like process creation
347 functions. the xwidget will be largely uninitialized until
348 discovered by redisplay. an xw belongs to a buffer
349 - xwidget-insert inserts the xwidget in a buffer. when discovered by
350 redisplay it will be initialized and a xwidget-view allocated
351 - an event will be emitted when initialization is finished when
352 relevant like for sockets
353
354 the problem with this aproach is that its not really legal to reuse
355 xwidget objects by writing several display specs who reference the
356 same xwidget. It could presumably be done but it would just become
357 weird for no real benefit. the big preblem is that the display spec
358 decides the on-screen size, and its not sane to have xwidget views
359 with different sizes. therefore such display specs would need to be
360 catched and dissallowed. Except it is hard because AFAIK the specs
361 don't have an identity as such. A flag in the structure could be set
362 by lookup so the first display attempt would win. but then you can't
363 rewrite the spec to change the size. hmmm. A third approach would be
364 to just allow the 1st spec refering an xw during a redisplay to take
365 effect, the rest are signaled as errors. this wouldnt be too bad.
366
367 the other aproach would be to work more like images:
368
369 - write the display spec with all information needed to create the
370 xwidget.
371 - retrieve the xwidget objet from the spec with an xwidget-at-point function. It
372 can be uninitalized which client code must handle. Unlike
373 assynchronous process creation we dont get back a handle, because
374 there is none yet.
375 - emitted event on initialization, when needed. Many widgets don't
376 need this. for instance, a button sends an event when pressed. but
377 you can't press it unless its on screen, and then its initialized
378 properly.
379
380 This approach seemed good, but how do I know which instance
381 generates an event if I cant set the id beforehand?
382
383 so, therefore, the first two aproach is used.
384
385
386 *** DONE xwidget creation interface actually
387 CLOSED: [2011-07-18 Mon 01:59]
388 conclusion of above ramblings:
389 - should be similar to make-text-button
390 - don't init from display spec, instead during make-xwidget call
391 *** TODO callbacks would be nice
392 but they need to be handled initially with events for technical
393 reasons. C code can't call Lisp easily. The event handler can call the
394 callback though.
395
396 ** TODO more documentation
397 There should be user docs, and xwidget contributor docs. The current README
398 is all contributor docs there is now, apart from the code.
399
400
401
402 ** CANCELLED look into more ways of displaying xwidgets, like binding them to a
403 CLOSED: [2011-07-05 Tue 11:34]
404 window rather than a point in a buffer. This was suggested by Chidong.
405 This would be a useful addition to Emacs in itself, and would avoid nearly all
406 display issues. I still think the general case is more interesting, but this
407 special case should also be added. The xwidget would then be bound to
408 replace the view of a particular window, and it would only show in
409 that window.
410
411 I got the webkit xwidget to work well enough so I dont see the need
412 for this now, except for sockets and I think it can better be dealt
413 with at the lisp level.
414
415 ** DONE MVC mode for xwidgets
416 CLOSED: [2011-06-27 Mon 12:53]
417 It appears unfruitful to chase using the same display mode for all
418 types of xwidgets. Composition is fun but not robust the way I'm
419 tried to do it.
420
421 Instead there should be a set of MVC xwidgets. Each on-screen instance
422 of an MVC widget would be a real GTK widget. The instances would
423 communciate state using signals.
424
425 There are drawbacks. There is no inbuilt support for MVC in GTK, so we
426 have to roll our own, which is tedious if not much work for the few
427 cases.
428
429 MVC for xembedded application will need support from the applications
430 themselves. Inkscape supports multiple views to the same document,
431 other programs don't. In practice it might not be a big drawback.
432
433
434 *** DONE figure out what to do with the multiple frames case.
435 CLOSED: [2011-06-27 Mon 12:52]
436 This should be easier to solve with MVC.
437 Surprisingly, this just worked!
438 *** DONE how to propagate changes in views to other views?
439 CLOSED: [2011-06-27 Mon 12:53]
440 I used gtk signals, the implementation for sliders works well!
441
442 ** TODO canvas support
443 heres an interesting comparision of gtk canvases
444 http://live.gnome.org/ProjectRidley/CanvasOverview
445 *** goocanvas
446 goocanvas is a gtk canvas implemented using cairo. investigate.
447
448 pros:
449 - it has a MVC model aproach out of the box which is nice.
450
451 http://developer.gnome.org/goocanvas/unstable/goocanvas-model-view-canvas.html
452
453 export CFLAGS="`pkg-config --cflags goocanvas` -DHAVE_GOOCANVAS"
454 export LDFLAGS=`pkg-config --libs goocanvas`
455 ./configure
456 make
457
458 I made a hello goo world xwidget so seems doable.
459 I wanted to load a SVG which wasnt immediately straightforward, so I
460 tried clutter. but it turns out the exact same strategy could be used
461 with goocanvas.
462
463 *** clutter
464 maybe clutter can be used as a canvas?
465 pros:
466 - seems to have a lot of traction atm. many examples
467 - potentialy fast and cool vector graphics
468 cons:
469 - no out of the box MVC support, but seems doable. no worse than the
470 other home brew mvc support I have in xwidgets
471 (media-explorer in an application that employes the MVC pattern)
472
473 http://www.openismus.com/documents/clutter_tutorial/0.9/docs/tutorial/html/sec-stage-widget.html
474
475 there is also cool stuff like this:
476 http://gitorious.org/webkit-clutter/webkit-clutter which is an webkit actor for
477 clutter! hmmmmm.
478
479 I want to render svg. aparently:
480 librsvg rsvg_handle_render_cairo(h, cr);
481 ClutterCairoTexture
482 Clutter
483
484 export CFLAGS="`pkg-config --cflags clutter-gtk-1.0` -DHAVE_CLUTTER"
485 export LDFLAGS=`pkg-config --libs clutter-gtk-1.0`
486 ./configure
487 make
488
489 compiles but I get:
490 Gtk-ERROR **: GTK+ 2.x symbols detected. Using GTK+ 2.x and GTK+ 3 in
491 the same process is not supported
492
493 export CFLAGS="`pkg-config --cflags clutter-gtk-0.10` -DHAVE_CLUTTER"
494 export LDFLAGS=`pkg-config --libs clutter-gtk-0.10`
495 ./configure
496 make
497
498
499 ** DONE mvc code crashes after a while
500 CLOSED: [2011-07-12 Tue 18:52]
501 seemingly only when compiling with optimizations.
502 I have no idea why.
503
504 Doesn't seem to happen after some code cleanups.
505 ** DONE xwidget-resize-at
506 CLOSED: [2011-07-19 Tue 14:28]
507 reimplement so display spec is not involved
508 ** DONE display spec validation
509 CLOSED: [2011-07-19 Tue 14:44]
510 it is an error to reuse xwidgets in several buffers or in the same
511 buffer. how do we catch these errors?
512 - showing the same xwidget twice in a buffer is no more wrong than
513 showing in several emacs windows, just conceptually wrong, so ignore
514 this case for now
515 - xwidgets now store a reference to the buffer they were created in,
516 so use that to invalidate xwidget references in oher buffers. but
517 thats not really an error either
518 - xwidgets should now be proper lisp objects so you dont delete them
519 you await their garbage collection. so therefore there can never be
520 invalid disploy specs
521
522 so turned out this got solved by using proper lisp objects for
523 xwidgets. yay!
524
525
526 ** DONE browser xwidget
527 CLOSED: [2011-07-20 Wed 20:05]
528 although embedding a browser is not my primary concern many are
529 interested in this. some suitable browser component needs to be found
530 supporting gtk.
531
532 *** DONE webkit
533 CLOSED: [2011-07-03 Sun 22:13]
534 there is a webkit gtk port. there is no obvious mvc support.
535 http://live.gnome.org/WebKitGtk
536 http://webkitgtk.org/
537
538 it might be possible to keep a set of webxits in artificial
539 synchronisation by recursive deep copy of the DOM from one webkit to
540 another. This will be error prone at best though. Another way might be
541 to just use bitmap copy of the "live"instance to the "phantom"
542 instances. the problem of transfering the live view remains though.
543
544 export CFLAGS="`pkg-config --cflags webkit-1.0` -DHAVE_WEBKIT -g"
545 export LDFLAGS=`pkg-config --libs webkit-1.0`
546 ./configure
547 make
548
549 **** off screen rendering
550 export CFLAGS="`pkg-config --cflags webkit-1.0` -DHAVE_WEBKIT_OSR -g"
551 export LDFLAGS=`pkg-config --libs webkit-1.0`
552 ./configure
553 make
554
555 works a little bit but i get errors like:
556
557 (emacs:8362): GLib-GObject-WARNING **: invalid cast from `GdkOffscreenWindow' to `GdkDrawableImplX11'
558
559 set a breakpoint in g_log, backtrace seems to indicate
560 webkitViewportAttributesRecompute is the offender.
561
562 maybe try gtk3 variants?
563
564 export CFLAGS="`pkg-config --cflags webkitgtk-3.0 ` -DHAVE_WEBKIT_OSR "
565 export LDFLAGS=`pkg-config --libs webkitgtk-3.0 `
566 ./configure --with-x-toolkit=gtk3
567 make
568
569 crash in gtk_window_get_size instead. great.
570
571 http://gtkplus-p3.0.sourcearchive.com/documentation/2.91.5-0ubuntu1/testoffscreenwindow_8c-source.html
572
573 after many atempts, the basic issue remains. for some reason the
574 offscreen widget isnt ok when I want to snapshot it, so i simply get
575 emptiness. the surface is only ok someimes.
576
577 here is a useful debugging snippets:
578 // debugging redraw:
579 // - the bg colors always change, so theres no error in signal handling
580 // - i get this error now and then:
581 //(emacs:7109): GLib-GObject-WARNING **: invalid cast from `GdkOffscreenWindow' to `GdkDrawableImplX11'
582 // seems to happen in webkit actually. see README
583
584 if(0){ //redraw debug hack. helped a lot in fact. use the with alpha painter below also
585 cairo_set_source_rgb(cr, osr_dbg_color, 1.0, 0.2);
586 cairo_rectangle(cr, 0,0, xw->width, xw->height);
587 cairo_fill(cr);
588 osr_dbg_color+=0.1;
589 if(osr_dbg_color>1.0)
590 osr_dbg_color=0.0;
591
592 }
593
594 you need to terminate drawing like this:
595
596 //cairo_set_source_surface (cr, src_pixmap, 0,0);
597 //cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
598
599 //cairo_paint_with_alpha (cr, 1.0);
600 //cairo_paint(cr);
601
602 the snippets change background color on oach redraw.
603
604 **** on-screen rendering to separate window
605 an alternative might be to open a separate window and snapshot it. the
606 idea is that whatever oddness webkit does so that offscreen rendering
607 doesnt work, doesnt happen on-screen. the window could be opened
608 somewhere not in the way.
609
610 *** CANCELLED firefox
611 CLOSED: [2011-07-03 Sun 22:13]
612 http://www-archive.mozilla.org/unix/gtk-embedding.html
613 seems to be severly bitrotted
614
615 heres a newer aproach
616 http://hg.mozilla.org/incubator/embedding/file/29ac0fe51754/gtk/tests/test.cpp
617
618 while webkit clearly has the best traction as an embeddee, the
619 offscreen rendering issues makes it interesting to see what ff brings
620 to the table. turns out webkit has as good offscreen support as anyone.
621
622
623 *** DONE text field support
624 CLOSED: [2011-07-20 Wed 20:05]
625 Emacs captures all keyboard events so text field support isn't super
626 straightforward.
627
628 **** propagate keyboard events
629 I have some old hacks for this and they are not good.
630 **** use the DOM model
631 expose document.activeElement to lisp. This is potentially more
632 interesting than just forwarding keyboard events.
633
634 webkit_web_view_get_dom_document ()
635
636 this is hard it seems. an idea might be to hack elisp support for swig
637 to machine generate the bindings.
638 **** DONE inject javascript
639 CLOSED: [2011-07-03 Sun 22:50]
640 webkit_web_view_execute_script ()
641
642 this works now:
643 (xwidget-webkit-execute-script 5 "document.activeElement.value='test'")
644
645 so it should be possible to do some interesting stuff.
646 execute-script does however not return anything at the interface level
647 so satisfaction is not total:
648
649 http://markmail.org/message/4yowmdgras73z3x5
650
651 maybe
652 https://launchpad.net/gnome-seed
653
654 or this funny hack:
655 <jave> im trying to understanh how to interact via javascript to an embedded
656 webkit gtk instance [23:38]
657 <jave> i use webkit_web_view_execute_script() which is nice but doesnt return
658 a value, by design aparently [23:39]
659 <jave> any hints?
660 <lucian> jave: afaik, webkit still doesn't have full gobject bindings [23:48]
661 <lucian> jave: you can hack it up by making the JS modify the title, and read
662 the title from gtk-side
663 <jave> lucian: that was a pretty cool idea!
664
665
666 *** webkit_web_view_load_string ()
667 I would like preview of html in a buffer rather than from uri.
668
669
670
671 *** TODO simple xwidget-webkit wrapper
672 so that it could be used for actual browsing :)
673 I dont want to reinvent too many wheels so i'd like to use existing
674 emacs facilities here possible. use bindings similar to w3m(or info)
675
676 - m-x xwidget-webkit starts a session
677 - 'g' goes to a url
678 - use bookmark-jump i suppose. I mostly use org for bookmarks myself
679 - browse-url support so webkit can be the default browser
680 - some way of getting around the quirky keyboard interaction since
681 xwidgets dont receive keyboard events because I hawe no idea how to
682 do that in a sane way
683
684 ... and one can of course go on bikeshedding forever. lets keep it
685 simple and extensible, and compatible with other Emacs packages.
686
687 the really cool ideas would need Emacs DOM integration, which is not
688 easy.
689
690 ** DONE clipping of controllers
691 CLOSED: [2011-07-05 Tue 11:33]
692
693 Emacs uses a big GTK window and does its own clipping against Emacs
694 windows inside this area. So, in order to layout gtk widgets in emacs
695 windows we must clip thim ourselves.
696
697 The following method worked well for a long time:
698 - make a gtk widget, say a button, xw
699 - make a clipping area, of type gtkfixed(many types have been tested)
700 - put the clip area in the main emacs gtk window
701 - figure out clip area changes during emacs redisplay
702
703 the only weirdness was that one has to tell gtk the clip area has a
704 window in order to get clipping. This is weird because all gtkwidgets
705 are windows in a sense and a window is almost by definition also a
706 clipping area.
707
708 Anyway, in GTK3 the gtk_widget_set_has_window(GTK_WIDGET (
709 xv->widgetwindow), TRUE); call is ignored.
710
711 The gtkeventbox which is documented to have its own window doesnt work
712 either.
713
714 http://www.lanedo.com/~carlos/gtk3-doc/chap-drawing-model.html
715
716 anyway clipping is rather complicated but seems to finally work okay.
717
718 *** DONE subclass my own clipping widget
719 CLOSED: [2011-07-04 Mon 16:55]
720 http://www.lanedo.com/~carlos/gtk3-doc/GtkWidget.html#gtk-widget-set-has-window
721 mentions that it has_window can only be called inside a widget
722 impementation.
723
724 this wasnt really the issue. allocation was the problem
725 *** DONE try scrolled window
726 CLOSED: [2011-07-01 Fri 10:56]
727 clipping does in fact work with
728 gtk_scrolled_window_add_with_viewport (xv->widgetwindow, xv->widget);
729 !!
730
731 I get unwanted scrollbars in the widget though.
732
733 gtk_scrolled_window_set_policy ( xv->widgetwindow,
734 GTK_POLICY_NEVER, GTK_POLICY_NEVER);
735
736 stops clipping from working!
737
738
739 *** DONE try viewport
740 CLOSED: [2011-07-01 Fri 10:56]
741 gtkviewport is used in scrolled window so in order to remove
742 scrollbars it should be possible to use viewport directly. however,
743 viewport ignores size requests. or rather the container does.
744
745
746 *** DONE debug allocation
747 CLOSED: [2011-07-04 Mon 16:56]
748 the container determines how much size to allocate to child widgets.
749
750 GtkAllocation galloc;
751 gtk_widget_get_allocation(GTK_WIDGET (xv->widgetwindow), &galloc);
752 printf("allocation %d %d , %d %d\n", galloc.x,galloc.y,galloc.width,galloc.height);
753
754 after my clipping attemp shows that my size request is ignored! this
755 might be logical, since the container provided by emacs is a
756 gtkfixed. gtkfixed might choose to heed the widgets size desires and
757 allocate the entire widget size. but we want clipping!
758
759 since i cant reasonably expect to change the emacs main container, i
760 can maybe overide the setallocation method in gwfixed, and adjust
761 allocation to clipping if its an xwidget asking for allocation.
762
763 **** DONE subclass gtkfixed
764 CLOSED: [2011-07-04 Mon 16:56]
765 possibly i need to subclass gtkfixed and override
766
767 void gtk_widget_size_allocate (GtkWidget *widget,
768 GtkAllocation *allocation);
769
770 http://developer.gnome.org/gobject/stable/howto-gobject.html
771
772 turns out emacs already does this for gtk3 according to jan D:
773 >>For GTK3, Emacs already subclasses GtkFixed, see emacsgtkfixed.[ch].
774
775 - widgets may not be underallocated, aparently
776 http://mail.gnome.org/archives/commits-list/2011-April/msg10950.html
777
778 - how to call base class method/chain up
779 http://developer.gnome.org/gobject/stable/howto-gobject-chainup.html
780
781 - the allocation modification could happen in the container or the
782 child. it feels more apropiate in the container
783
784 it is however unexpectedy inconvenient to modify allocation because
785 the needed data is private to the base class. to overcome this:
786
787 - run base class method 1st.
788 - then, iterate all children, and modify allocation for xwidget
789 children only. x y will then be set.
790
791 JanD pointed out the GTK3 port already has its own subclass, so I
792 modified that one.
793
794 *** DONE clip top
795 CLOSED: [2011-07-05 Tue 11:30]
796 there are four controller edges that potentialy need clipping. I begun
797 with right and bottom edges. clipping them is just a matter of setting
798 the right size of the widgetwindow and also ensure it gets the right
799 allocation from the container.
800
801 clipping top (and left) is not equally straightforward. I'm using a
802 viewport now and scroll it the amount that needs to be clipped.
803 however, the viewport is sensitive to changes in allocation, which
804 makes it harder to use the allocation workarounds.
805
806 see:
807 - gtk_widget_set_size_request
808 - gtkscrolledwindow
809
810 I returned to using a simple gtkfixed for the widgetwindow. with
811 allocation hack and set_has_window it works. Idea prefer not to have
812 the allocatien hack and it wasnt needed it gtk3 only gtk2. needs
813 furthi investigation,
814
815 ** DONE various code cleanups
816 CLOSED: [2011-07-20 Wed 20:05]
817 There are many cleanups necessary before any hope of inclusion in
818 Emacs trunk. To begin with, the part of the patch that touches other
819 parts of emacs must be very clean.
820 *** DONE use FRAME_GTK_WIDGET (f)
821 CLOSED: [2011-07-20 Wed 20:02]
822 rather than gwfixed.
823
824 *** DONE support configure
825 CLOSED: [2011-07-12 Tue 18:48]
826 ** DONE translate clicks
827 CLOSED: [2011-07-03 Sun 22:12]
828 on onscreen webkit peer to offscreen
829
830 maybe
831 http://developer.gnome.org/gdk/stable/gdk-Windows.html#GdkWindow-from-embedder
832
833 turned out to be not so hard, captured events, copied them and
834 forwarded them offscreen!
835
836 ** TODO investigate gdk_window_redirect_to_drawable
837 http://developer.gnome.org/gdk/stable/gdk-Windows.html#gdk-offscreen-window-set-embedder
838 maybe control be used in place of my own copy hacks? to work it must
839 support a chain of redirects, which seems unlikely. the benefit would
840 be that I dont have to spend time optimizing redrawing.
841
842
843
844 ** DONE remove xwidget_views when emacs window is deleted
845 CLOSED: [2011-07-05 Tue 11:29]
846 removing xwidget views when an Emacs window closes is not reliable.
847
848 - switching buffers in a window seems to hide the corresponding
849 xwidget-views properly, but they might as well be deleted.
850
851 - patching delete-window-internal could be used to delete the xwidget-views
852 this seems to work
853
854
855 ** TODO support webkit signals
856 *** TODO particularily document-load-finished
857 http://webkitgtk.org/reference/webkitgtk-webkitwebview.html#WebKitWebView-document-load-finished
858 *** TODO console messages
859 http://webkitgtk.org/reference/webkitgtk-webkitwebview.html#WebKitWebView-console-message
860 http://getfirebug.com/wiki/index.php/Console_API#console.count.28.5Btitle.5D.29
861 because maybe we can make a simple JS REPL that way.
862 (xwidget-webkit-execute-script ( xwidget-webkit-last-session)
863 "console.log('hello')")
864 prints hello to stdout but theres no way to catch stdout from webkit I
865 think other than receiving the signal.
866
867
868
869 ** TODO webkit downloads
870 when clicking a download link in Webkit Emacs should take over and handle it
871 from there. Probably need signals.
872
873 ** TODO webkit alt-text not handled
874 XKCD use image-title to display a cartoon comment. These mysteriously
875 don't work ATM. Other mouseovers work though. Maybe webkit tries to
876 open a new window or something, which wont work.
877
878 ** TODO isearch in webkit buffers
879 have a look at how docview solves it
880 webkit_web_view_search_text ()
881 ** TODO webkit relative references doesn't work
882 probably because we handle scrolling in a non-standard way
883 * old notes from x_draw_xwidget_glyph_string
884
885 BUG it seems this method for some reason is called with bad s->x and s->y sometimes.
886 When this happens the xwidget doesnt move on screen as it should.
887 This mightbe because of x_scroll_run. Emacs decides to scroll the screen by blitting sometimes.
888 then emacs doesnt try to actualy call the paint routines, which means this here code will never
889 run so the xwidget wont know it has been moved.
890
891 Solved temporarily by never optimizing in try_window_reusing_current_matrix().
892
893 BUG the phantoming code doesnt work very well when the live xwidget is off screen.
894 you will get weirdo display artefacts. Composition ought to solve this, since that means the live window is
895 always available in an off-screen buffer. My current attempt at composition doesnt work properly however.
896
897 //allocation debugging. the correct values cant be expected to show upp immediately, but eventually they should get to be ok
898 // this is because we dont know when the container gets around to doing layout
899 //GtkAllocation galloc;
900 //gtk_widget_get_allocation(GTK_WIDGET (xv->widgetwindow), &galloc);
901 //printf("allocation %d %d , %d %d\n", galloc.x,galloc.y,galloc.width,galloc.height);
902
903
904 *** old notes about the old live/phantom scheme
905
906 //TODO:
907 // 1) always draw live xwidget in slected window
908 // (2) if there were no live instances of the xwidget in selected window, also draw it live)
909 // 3) if there was a live xwidget previously, now phantom it.
910
911 else
912 {
913 //ok, we are painting the xwidgets in non-selected window, so draw a phantom
914 //printf("draw phantom xwidget at:%d %d\n",x,y);
915 //xwidget_composite_draw_phantom (xw, x, y, clipx, clipy); //TODO MVC there will be very few cases of phantoming
916 }
917
918
919 atm this works as follows: only check if xwidgets are displayed in the
920 "selected window". if not, hide them or phantom them.
921
922 this means valid cases like xwidgets being displayed only once in
923 non-selected windows, does not work well. they should also be visible
924 in that case not phantomed.