]> code.delx.au - gnu-emacs/commitdiff
mostly upstream
authorJoakim Verona <joakim@verona.se>
Sun, 7 Aug 2011 12:24:24 +0000 (14:24 +0200)
committerJoakim Verona <joakim@verona.se>
Sun, 7 Aug 2011 12:24:24 +0000 (14:24 +0200)
13 files changed:
1  2 
README.xwidget
autogen/configure
configure.in
lisp/xwidget.el
src/Makefile.in
src/dispextern.h
src/dispnew.c
src/emacs.c
src/keyboard.c
src/window.c
src/xdisp.c
src/xterm.c
src/xwidget.c

diff --cc README.xwidget
index f457b5cd10e0bd99cabce7b2832fd9a69e3811ae,0000000000000000000000000000000000000000..710c10ed7f3e868f8cd2cafd7f0adc6e977c7bb9
mode 100644,000000..100644
--- /dev/null
@@@ -1,1073 -1,0 +1,1076 @@@
 +* Xwidgets
 +
 +This is an experimental branch to enable embedding of GTK widgets
 +inside an Emacs window. The Emacs abstraction is called an Xwidget,
 +for eXternal widget, and also in reference to the Xembed protocoll.
 +
 +There is a demo file called xwidget-test.el which shows some of the
 +possibilities. There are some screnshots at the emacswiki.
 +
 +Currently its possible to insert buttons, sliders, xembed widgets, and
 +webkit in the buffer. It works similar to the support for images in
 +Emacs.  Adding more types of widgets should be fairly straightforward,
 +but will require adapter code for each type.
 +
 +A difference from images is that xwidgets live their own life. You
 +create them with an api, get a reference, and tie them to a particular
 +buffer with a display spec. 
 +
 +Each xwidget can have several views. In MVC terms, an xwidget is the
 +model, and an xwidget-view is a view of the xwidget in a particular
 +Emacs window.
 +
 +The xwidget code attempts to keep the visual appearance of the views
 +in sync with through an Observer pattern implementation. This is
 +necessary to support the Emacs window paradigm.
 +
 +** building
 +bzr co bzr+ssh://bzr.savannah.gnu.org/emacs/xwidget/
 +#the below compiler flags shouldn't be strictly necessary
 +export CFLAGS=" -g -DGLYPH_DEBUG=1"
 +./configure   --with-x-toolkit=gtk3 --with-xwidgets
 +make -j4
 +gdb -ex run src/emacs
 +
 +** try it out
 +If you have GTK3 and gtk-webkit installed, you should be able to
 +start the embedded webkit browser now:
 +
 +M-X xwidget-webkit-browse-url
 +
 +If that didnt work out try the minimal demonstration instead:
 +
 +(load-library "xwidget-test")
 +(xwidget-demo-a-button)
 +
 +It looks unimpressive, but it's a gtk button inside an Emacs buffer!
 +*** webkit hints
 +If you got webkit working, great! Please note, though, that the
 +current support is far from a full fledged browser. My focus is on
 +delivering a component that can be used to build a full emacs based
 +browser on. Since I implement a browse-url function you can get quite
 +far just by:
 +
 +(setq browse-url-browser-function 'xwidget-webkit-browse-url)
 +
 +then all Emacs browser interface systems work to a degree.
 +heres stuff I use currenly
 +
 +- m-x anything-surfraw interfaces to search engines
 +- C-o in org mode opens links inside org
 +- m-x ffap opens links anywhere in a buffer
 +- m-x gtk-lookup-symbol searches gtk docs
 +- m-x bookmark-jump
 +etc..
 +
 +I'll add more examples as I go along.
 +
 +However theres lots of support missing, see TODO list for
 +information. Briefly:
 +- download handling
 +- keyboard field navigation
 +- isearch
 +- history
 +- sites that use flash. I dont really care about this issue so its
 +unlikely to be fixed. Just a heads up.
 +
 +** Stability
 +Beginning with Summer 2011 I am now able to use Xwidget Emacs as my
 +primary Emacs. That is good for the project and the stability of the
 +code.
 +
 +At the time of writing I have 24 hour Emacs uptime with several
 +embedded webkit browsers, Gnus, org-mode, tramp, etc. etc.
 +
 +That said, there are still many improvements that needs to be done,
 +particularily in memory management. Expect xwidget emacs to leak
 +heavily for now.
 +
 +** timeline for inclusion in trunk
 +The Emacs 24 feature freeze is passed, so xwidgets won't probably be merged
 +until Emacs 25. OTOH since I now use xwidget emacs as my primary
 +emacs, I will merge from trunk much more often than in the past.
 +
 +** Thanks
 +emacs-devel@gnu.org. There are very helpful people there. When I
 +started the xwidget project I had no clue about the Emacs internals. 
 +
 +* Brief overview of how xwidgets work
 +Xwidgets work in one way like images in Emacs. You bind a display spec very
 +similar to an image display spec to buffer contents. The display engine will
 +notice the display spec and try to display the xwidget there. The display engine
 +prepares space at the right place for the xwidget and so on for free, as long as
 +we provide proper sizes and so on back to the redisplay engine.
 +
 +** Issues
 +The problem is that Emacs cant actually draw the widgets, as it can with
 +images. Emacs must notify GTK about where the widgets should be, and how they
 +should be clipped and so on, and this information must be given to GTK
 +synchonous with Emacs display changes. Ok, so why is that difficult then?
 +
 +- How do we know when a widget is NOT to be drawn? The only way I found so far
 +  is having a flag for each xwdiget, that is reset before a redisplay. When an
 +  xwidget is encountered during display, the flag is set. After redisplay,
 +  iterate all xwidgets and hide those which hasnt been displayed. 
 +
 +- The gtk socket type for embedding external applications is desirable
 +  but presents a lot of difficulties of its own. One difficulty is
 +  deciding which input events to forward, and when and how to do it.
 +
 +** placement and clipping
 +the entire emacs frame is a gtk window. we use the fixed layout
 +manager to place xwidgets on the frame. coordinates are supplied by
 +the emacs display engine. widgets are placed inside an intermediate
 +window, called the widgetwindow. the widgetwindows are placed on the
 +emacs frame.
 +
 +this way was chosen to simplify clipping of the widgets against emacs
 +window borders.
 +
 +
 +** different strategies
 +Integrating toolkit widgets(gtk in this case) and the emacs display
 +engine is more difficult than your plain average gui application, and
 +different strategies has been tested and will continue to be tested.
 +
 +There was a distinction between live xwidgets and
 +phantom xwidgets, previous to the change to MVC.
 +
 +- the first aproach was to have the live xwidget on-screen, and move
 +  them about. the phantoms were generated by snapshoting the live
 +  xwidget. 
 +
 +the drawback of that aproach was that the gtk toolkit is admirably
 +lazy and doesnt draw the widget if its not actualy shown, meaning that
 +the snapshots for the phantoms will show garbage.
 +
 +- the second aproach was to use composition support. that tells gtk
 +  that the widget should be drawn in an off-screen buffer and drawn on
 +  screen by the application.
 +
 +this has the primary advantage that the snapshot is always
 +available, and enables the possibility of more eye-candy like drawing
 +live and phantom widgets in different colors.
 +
 +the drawback is that its our own responsibility to handle drawing,
 +which puts more of the display optimization burden on us.
 +
 +this is aproach worked so-so.
 +
 +- another aproach is to have both live and phantom widgets drawn
 +  on-screen by proxy gtk objects. the live xwidget will be entirely
 +  handled in an off-screen window, and the proxy objects will redirect
 +  events there.
 +
 +- combine on-screen and off-screen aproaches. maybe composition is the
 +  way to go for most cases, but on-screen xembeding is the way to go
 +  for particular special cases, like showing video in a
 +  window. off-screen rendering and whatnot, is not efficient in that
 +  particular case, and the user will simply have to accept that the
 +  phantom of a video widget isnt particularily beautiful.
 +
 +- The current and seemingly sanest aproach implements a MVC pattern.
 +
 +** Testing
 +;;test like:
 +;; cd /path/to/xwidgets-emacs-dir
 +;; make   all&&  src/emacs -q --eval "(progn (load \"`pwd`/lisp/xwidget-test.el\") (xwidget-demo-basic))"
 +
 +** MVC and Xembedd
 +The MVC approach appears to be at least in principle robust for plain gtk
 +widgets. For the interesting case of gtk sockets which implements an
 +xembed host widget that allows for embedding other applications inside
 +an Emacs window, the story gets more complex.
 +
 +The problem is that xembed is designed to plug an application window
 +inside a a secket and thats it. You can't move a plug between
 +sockets. I tried numerous hacks to get around this but there is
 +nothing that works realy well.
 +
 +Therefore the Emacs part of the code will only expose well-defined
 +interfaces. cooperating applications will be able to use the interface
 +in a well defined manner. The problem is that there is no known xembeddable
 +application that implement the needed type of functionality, which is
 +allowing for creating new windows on the fly that plug into new
 +sockets.
 +
 +Therefore I will attempt to provide an external application that wraps
 +another application and through hacks attempts to provide the needed
 +multi view xembed function. That way Emacs is sane and the insanity
 +contained.
 +
 +This app will work by providing a socket that an app plugs into. The
 +socket window is copied efficientlp by means of composition to a
 +number of other windows, that then are plugged into the different
 +Emacs sockets. 
 +* ToDo:s
 +** DONE allow xwidgets to report their size
 +   CLOSED: [2011-07-19 Tue 14:26]
 +now we just hard code sizes. but webkit widgets for instance can
 +report sizes that suit the content. support that.
 +** TODO BUG xwidget view ghosts
 +- xwidget-webkit-browse-url somewhere
 +- split window.
 +now theres 2 webkit views
 +- c-x 1
 +now theres 2 views but one is a ghost!
 +one should have been deleted when its window died but that didnt work
 +for some reason here.
 +
 +- m-x xwidget-cleanup
 +
 +the ghost goes away because we killed explicitly but this is just a workaround.
 +
 +xwidget_view_delete_all_in_window(w); in delete-window-internal is not sufficient.
 +delete-other-windows-internal
 +delete_all_subwindows
 +unshow_buffer
 +
 +** DONE BUG annoying backtrace
 +   CLOSED: [2011-07-19 Tue 14:28]
 +(this no longer seems to happen even under heavy usage. seems merging
 +from trunk helped. lots were happening in redisplay at this time in trunk.)
 +
 +sadly happens a lot.
 +- happens even with no initialized xwidgets
 +-                  + row->glyphs[area][i].face_id
 +or similar code, so row is invalid for some reason.
 +xwidgets currently disable some redisplay opimizations so it might be
 +an actual emacs bug manifesting without optimizations.
 +
 +*** bt 1
 +      /* Compute the width of this line.  */
 +      row->pixel_width = row->x;
 +      for (i = 0; i < row->used[TEXT_AREA]; ++i)
 +      row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
 +
 +(gdb) bt
 +#0  0x000000000045c340 in compute_line_metrics (it=0x7fffffff8a20)
 +    at xdisp.c:17549
 +#1  0x00000000004603da in display_line (it=0x7fffffff8a20) at xdisp.c:18792
 +#2  0x0000000000457646 in try_window (window=23403045, pos=..., flags=1)
 +    at xdisp.c:15399
 +#3  0x00000000004559c9 in redisplay_window (window=23403045, just_this_one_p=0)
 +    at xdisp.c:14944
 +#4  0x0000000000450247 in redisplay_window_0 (window=23403045) at xdisp.c:13152
 +#5  0x00000000005fdcd9 in internal_condition_case_1 (bfun=
 +    0x450208 <redisplay_window_0>, arg=23403045, handlers=12691046, hfun=
 +    0x4501d9 <redisplay_window_error>) at eval.c:1538
 +#6  0x00000000004501ba in redisplay_windows (window=23403045) at xdisp.c:13132
 +#7  0x000000000044f19c in redisplay_internal () at xdisp.c:12706
 +#8  0x000000000044f9f2 in redisplay_preserve_echo_area (from_where=7)
 +    at xdisp.c:12964
 +#9  0x0000000000568525 in swallow_events (do_display=1) at keyboard.c:4197
 +#10 0x0000000000422554 in sit_for (timeout=40, reading=1, do_display=1)
 +    at dispnew.c:5963
 +#11 0x000000000056512c in read_char (commandflag=1, nmaps=8, maps=
 +    0x7fffffffd3f0, prev_event=12720514, used_mouse_menu=0x7fffffffd604, 
 +    end_time=0x0) at keyboard.c:2689
 +#12 0x0000000000572c59 in read_key_sequence (keybuf=0x7fffffffd850, bufsize=
 +    30, prompt=12720514, dont_downcase_last=0, can_return_switch_frame=1, 
 +---Type <return> to continue, or q <return> to quit---
 +    fix_current_buffer=1) at keyboard.c:9291
 +#13 0x0000000000562897 in command_loop_1 () at keyboard.c:1446
 +#14 0x00000000005fdb52 in internal_condition_case (bfun=
 +    0x5624b4 <command_loop_1>, handlers=12772898, hfun=0x561dab <cmd_error>)
 +    at eval.c:1493
 +#15 0x00000000005621ab in command_loop_2 (ignore=12720514) at keyboard.c:1157
 +#16 0x00000000005fd4ce in internal_catch (tag=12768770, func=
 +    0x562185 <command_loop_2>, arg=12720514) at eval.c:1247
 +#17 0x000000000056215e in command_loop () at keyboard.c:1136
 +#18 0x00000000005618f9 in recursive_edit_1 () at keyboard.c:757
 +#19 0x0000000000561a95 in Frecursive_edit () at keyboard.c:821
 +#20 0x000000000055fba2 in main (argc=1, argv=0x7fffffffe188) at emacs.c:1704
 +
 +
 +*** bt 2
 +
 +** DONE Examine using XComposite rather than GTK off-screen
 +  rendering. This would make xembed widgets work much better. This
 +  would probably be rathter difficult, but could open up other
 +  interesting possibilities for Emacs. There is an early attempt in
 +  xwidget.c, but the X call to redirect to offscreen rendering fails
 +  for unknown reasons.
 +
 +  the attempt was further worked on, and the xlib calls replaced with
 +  gdk calls, this works better.
 +
 +  In the end I abandoned this aproach. Xwidget-osr is the new aproach.
 +
 +** TODO  make the keyboard event code propagation code work. 
 +There is an attempt to provide an api to send keyboard events to an
 +xwidget, but it doesnt currently work very well.
 +
 +*** TODO try gtk event creation instead 
 +since that works fine in the webkit osr code. 
 +but, oh no, that didn't work for some reason.
 +the event seems to receive the event but then the embedded widgets
 +hangs.
 +
 +
 +*** TODO examine some library to synthesise events
 +xdotool
 +xte xautomation
 +crikey
 +libxdo
 +** DONE remove the special-case for when the minibuffer is
 +  active.  I added some code to reduce the annoying problem display artefacts
 +  when making the minibuffer the selected window. This made xwidgets in the
 +  buffer go grey or black whenever one did m-x to activate the minibuffer. The
 +  coded tried to handle the minibuffer as a special case. That simply wasnt a
 +  good idea. Special-casing will never work properly. It is much better to spend
 +  time finding solutions that work acceptably in the general case.
 +
 +** DONE disable emacs cursor drawing on top of an active xwidget. 
 +  This ought to be rather simple and should improve the visuals a lot.
 +
 +** TODO  improve the xwidgets programming interface 
 +so its less of hand-waving affair. This shouldnt be too hard, but I
 +  have deliberatley not spent any time on it, since getting the
 +  visuals right is much harder. Anyway, I sort of think the interface
 +  should be somewhat like it is, except symbols is used instead of
 +  integers.
 +*** DONE use symbols for xwidget types rather than ints
 +    CLOSED: [2011-06-27 Mon 12:52]
 +
 +
 +*** TODO better lisp based structure for xwidgets
 +the lisp interface woud be like this:
 +- make-xwidget returns an xwidget object, similar to a process
 +  object. this object is used when creating the display spec(instead of
 +  the user defined id now used)
 +
 +the data structure would be something like this:
 +- a "process" like aproach to create the xwidgets. xwidgets are
 +  coupled to buffers, somewhat like processes, except a buffer can
 +  hold several xwidgets
 +- an xwidget has a plist to hold the model, like a process
 +- an xwidget has an assoc list of xwidget views
 +
 +there are some things that arent clear:
 +- an xwidget doesnt necessarily need to be coupled to a buffer but it
 +  seems to be the clearest model. xwidgets would be buffer local
 +- xwidget-views are by necessity coupled to a emacs window so it might
 +  be better to store them window locally rather than in an assoc
 +  coupled to the xwidget model
 +- for some gtk widgets that resist an mvc approach, like the webkit
 +  widgets, special operations are needed, similar to the old phantom
 +  widgets aproach. so we need to differentiate live and phantom
 +  instances for these troublesome widgets and let lisp manage all the trickery.
 +
 +stuff that needs to work:
 +- do something for all views of a xwidget(resize, value change)
 +- do something for all xw-views in an emacs window(deletion etc)
 +- lookup xw-view for xwidget in emacs window(during redisplay)
 +(- do something for all siblings of a xw-view. not atm)
 +
 +*** DONE xwidget creation interface
 +    CLOSED: [2011-07-18 Mon 01:59]
 +xwidgets are a little bit like emacs processes but also a little bit
 +like emacs images. Therefore its not perfectly obvious how to handle
 +creation. Currently I just use hardcoded identifiers. the real scheme
 +needs to be something else.
 +
 +Heres a tentative approach:
 +- xwidget-create returns a xwidget object, like process creation
 +  functions. the xwidget will be largely uninitialized until
 +  discovered by redisplay. an xw belongs to a buffer
 +- xwidget-insert inserts the xwidget in a buffer. when discovered by
 +  redisplay it will be initialized and a xwidget-view allocated
 +- an event will be emitted when initialization is finished when
 +  relevant like for sockets
 +
 +the problem with this aproach is that its not really legal to reuse
 +xwidget objects by writing several display specs who reference the
 +same xwidget. It could presumably be done but it would just become
 +weird for no real benefit. the big preblem is that the display spec
 +decides the on-screen size, and its not sane to have xwidget views
 +with different sizes. therefore such display specs would need to be
 +catched and dissallowed. Except it is hard because AFAIK the specs
 +don't have an identity as such. A flag in the structure could be set
 +by lookup so the first display attempt would win. but then you can't
 +rewrite the spec to change the size. hmmm. A third approach would be
 +to just allow the 1st spec refering an xw during a redisplay to take
 +effect, the rest are signaled as errors. this wouldnt be too bad.
 +
 +the other aproach would be to work more like images:
 +
 +- write the display spec with all information needed to create the
 +  xwidget.
 +- retrieve the xwidget objet from the spec with an xwidget-at-point function. It
 +  can be uninitalized which client code must handle. Unlike
 +  assynchronous process creation we dont get back a handle, because
 +  there is none yet.
 +- emitted event on initialization, when needed. Many widgets don't
 +  need this. for instance, a button sends an event when pressed. but
 +  you can't press it unless its on screen, and then its initialized
 +  properly. 
 +
 +This approach seemed good, but how do I know which instance
 +generates an event if I cant set the id beforehand?
 +
 +so, therefore, the first two aproach is used. 
 +
 +
 +*** DONE xwidget creation interface actually
 +    CLOSED: [2011-07-18 Mon 01:59]
 +conclusion of above ramblings:
 +- should be similar to make-text-button
 +- don't init from display spec, instead during make-xwidget call
 +*** TODO callbacks would be nice 
 +but they need to be handled initially with events for technical
 +reasons. C code can't call Lisp easily. The event handler can call the
 +callback though.
 +
 +** TODO  more documentation
 +There should be user docs, and xwidget contributor docs. The current README
 +is all contributor docs there is now, apart from the code.
 +
 +
 +
 +** CANCELLED look into more ways of displaying xwidgets, like binding them to a
 +   CLOSED: [2011-07-05 Tue 11:34]
 +window rather than a point in a buffer. This was suggested by Chidong.
 +This would be a useful addition to Emacs in itself, and would avoid nearly all 
 +display issues. I still think the general case is more interesting, but this
 +special case should also be added. The xwidget would then be bound to
 +replace the view of a particular window, and it would only show in
 +that window.
 +
 +I got the webkit xwidget to work well enough so I dont see the need
 +for this now, except for sockets and I think it can better be dealt
 +with at the lisp level.
 +
 +** DONE MVC mode for xwidgets
 +   CLOSED: [2011-06-27 Mon 12:53]
 +It appears unfruitful to chase using the same display mode for all
 +types of xwidgets. Composition is fun but not robust the way I'm
 +tried to do it.
 +
 +Instead there should be a set of MVC xwidgets. Each on-screen instance
 +of an MVC widget would be a real GTK widget. The instances would
 +communciate state using signals. 
 +
 +There are drawbacks. There is no inbuilt support for MVC in GTK, so we
 +have to roll our own, which is tedious if not much work for the few
 +cases.
 +
 +MVC for xembedded application will need support from the applications
 +themselves. Inkscape supports multiple views to the same document,
 +other programs don't. In practice it might not be a big drawback.
 +
 +
 +*** DONE figure out what to do with the multiple frames case. 
 +    CLOSED: [2011-06-27 Mon 12:52]
 +This should be easier to solve with MVC.
 +Surprisingly, this just worked!
 +*** DONE how to propagate changes in views to other views?
 +    CLOSED: [2011-06-27 Mon 12:53]
 +I used gtk signals, the implementation for sliders works well!
 +
 +** TODO canvas support
 +heres an interesting comparision of gtk canvases
 +http://live.gnome.org/ProjectRidley/CanvasOverview
 +*** goocanvas
 +goocanvas is a gtk canvas implemented using cairo. investigate.
 +
 +pros:
 +- it has a MVC model aproach out of the box which is nice.
 +
 +http://developer.gnome.org/goocanvas/unstable/goocanvas-model-view-canvas.html
 +
 +export CFLAGS="`pkg-config --cflags goocanvas` -DHAVE_GOOCANVAS"
 +export LDFLAGS=`pkg-config --libs goocanvas`
 +./configure
 +make
 +
 +I made a hello goo world xwidget so seems doable.
 +I wanted to load a SVG which wasnt immediately straightforward, so I
 +tried clutter. but it turns out the exact same strategy could be used
 +with goocanvas.
 +
 +*** clutter
 +maybe clutter can be used as a canvas? 
 +pros:
 +- seems to have a lot of traction atm. many examples
 +- potentialy fast and cool vector graphics
 +cons:
 +- no out of the box MVC support, but seems doable. no worse than the
 +  other home brew mvc support I have in xwidgets
 +(media-explorer in an application that employes the MVC pattern)
 +
 +http://www.openismus.com/documents/clutter_tutorial/0.9/docs/tutorial/html/sec-stage-widget.html
 +
 +there is also cool stuff like this:
 +http://gitorious.org/webkit-clutter/webkit-clutter which is an webkit actor for
 +clutter! hmmmmm.
 +
 +I want to render svg. aparently:
 +  librsvg rsvg_handle_render_cairo(h, cr);
 +  ClutterCairoTexture
 +  Clutter
 +
 +export CFLAGS="`pkg-config --cflags clutter-gtk-1.0` -DHAVE_CLUTTER"
 +export LDFLAGS=`pkg-config --libs clutter-gtk-1.0`
 +./configure
 +make
 +
 +compiles but I get:
 +Gtk-ERROR **: GTK+ 2.x symbols detected. Using GTK+ 2.x and GTK+ 3 in
 +the same process is not supported
 +
 +export CFLAGS="`pkg-config --cflags clutter-gtk-0.10` -DHAVE_CLUTTER"
 +export LDFLAGS=`pkg-config --libs clutter-gtk-0.10`
 +./configure
 +make
 +
 +
 +*** webkit html 5
 +expose the DOM to lisp or something
 +** DONE mvc code crashes after a while
 +   CLOSED: [2011-07-12 Tue 18:52]
 +seemingly only when compiling with optimizations.
 +I have no idea why.
 +
 +Doesn't seem to happen after some code cleanups.
 +** DONE xwidget-resize-at
 +   CLOSED: [2011-07-19 Tue 14:28]
 +reimplement so display spec is not involved
 +** DONE display spec validation
 +   CLOSED: [2011-07-19 Tue 14:44]
 +it is an error to reuse xwidgets in several buffers or in the same
 +buffer. how do we catch these errors? 
 +- showing the same xwidget twice in a buffer is no more wrong than
 +  showing in several emacs windows, just conceptually wrong, so ignore
 +  this case for now
 +- xwidgets now store a reference to the buffer they were created in,
 +  so use that to invalidate xwidget references in oher buffers. but
 +  thats not really an error either
 +- xwidgets should now be proper lisp objects so you dont delete them
 +  you await their garbage collection. so therefore there can never be
 +  invalid disploy specs
 +
 +so turned out this got solved by using proper lisp objects for
 +xwidgets. yay!
 +
 +** DONE clipping of controllers
 +   CLOSED: [2011-07-05 Tue 11:33]
 +
 +Emacs uses a big GTK window and does its own clipping against Emacs
 +windows inside this area. So, in order to layout gtk widgets in emacs
 +windows we must clip thim ourselves. 
 +
 +The following method worked well for a long time:
 +- make a gtk widget, say a button, xw
 +- make a clipping area, of type gtkfixed(many types have been tested)
 +- put the clip area in the main emacs gtk window
 +- figure out clip area changes during emacs redisplay
 +
 +the only weirdness was that one has to tell gtk the clip area has a
 +window in order to get clipping. This is weird because all gtkwidgets
 +are windows in a sense and a window is almost by definition also a
 +clipping area.
 +
 +Anyway, in GTK3 the   gtk_widget_set_has_window(GTK_WIDGET (
 +xv->widgetwindow), TRUE); call is ignored. 
 +
 +The gtkeventbox which is documented to have its own window doesnt work
 +either.
 +
 +http://www.lanedo.com/~carlos/gtk3-doc/chap-drawing-model.html
 +
 +anyway clipping is rather complicated but seems to finally work okay.
 +
 +*** DONE subclass my own clipping widget
 +    CLOSED: [2011-07-04 Mon 16:55]
 +http://www.lanedo.com/~carlos/gtk3-doc/GtkWidget.html#gtk-widget-set-has-window
 +mentions that it has_window can only be called inside a widget
 +impementation.
 +
 +this wasnt really the issue. allocation was the problem
 +*** DONE try scrolled window
 +    CLOSED: [2011-07-01 Fri 10:56]
 +clipping does in fact work with
 +gtk_scrolled_window_add_with_viewport (xv->widgetwindow, xv->widget);
 +!!
 +
 +I get unwanted scrollbars in the widget though.
 +
 +  gtk_scrolled_window_set_policy      (  xv->widgetwindow,
 +  GTK_POLICY_NEVER, GTK_POLICY_NEVER); 
 +
 +stops clipping from working! 
 +
 +
 +*** DONE try viewport
 +    CLOSED: [2011-07-01 Fri 10:56]
 +gtkviewport is used in scrolled window so in order to remove
 +scrollbars it should be possible to use viewport directly. however, 
 +viewport ignores size requests. or rather the container does.
 +
 +
 +*** DONE debug allocation
 +    CLOSED: [2011-07-04 Mon 16:56]
 +the container determines how much size to allocate to child widgets.
 +
 +        GtkAllocation galloc;
 +        gtk_widget_get_allocation(GTK_WIDGET (xv->widgetwindow), &galloc);
 +        printf("allocation %d %d , %d %d\n", galloc.x,galloc.y,galloc.width,galloc.height);
 +
 +after my clipping attemp shows that my size request is ignored! this
 +might be logical, since the container provided by emacs is a
 +gtkfixed. gtkfixed might choose to heed the widgets size desires and
 +allocate the entire widget size. but we want clipping!
 +
 +since i cant reasonably expect to change the emacs main container, i
 +can maybe overide the setallocation method in gwfixed, and adjust
 +allocation to clipping if its an xwidget asking for allocation.
 +
 +**** DONE subclass gtkfixed
 +     CLOSED: [2011-07-04 Mon 16:56]
 +possibly i need to subclass gtkfixed and override
 +
 +void                gtk_widget_size_allocate            (GtkWidget *widget,
 +                                                         GtkAllocation *allocation);
 +
 +http://developer.gnome.org/gobject/stable/howto-gobject.html
 +
 +turns out emacs already does this for gtk3 according to jan D:
 +>>For GTK3, Emacs already subclasses GtkFixed, see emacsgtkfixed.[ch].
 +
 +- widgets may not be underallocated, aparently
 +http://mail.gnome.org/archives/commits-list/2011-April/msg10950.html
 +
 +- how to call base class method/chain up
 +http://developer.gnome.org/gobject/stable/howto-gobject-chainup.html
 +
 +- the allocation modification could happen in the container or the
 +  child. it feels more apropiate in the container
 +
 +it is however unexpectedy inconvenient to modify allocation because
 +the needed data is private to the base class. to overcome this:
 +
 + - run base class method 1st. 
 + - then, iterate all children, and modify allocation  for xwidget
 +   children only. x y will then be set.
 +
 +JanD pointed out the GTK3 port already has its own subclass, so I
 +modified that one.
 +
 +*** DONE clip top
 +    CLOSED: [2011-07-05 Tue 11:30]
 +there are four controller edges that potentialy need clipping. I begun
 +with right and bottom edges. clipping them is just a matter of setting
 +the right size of the widgetwindow and also ensure it gets the right
 +allocation from the container.
 +
 +clipping top (and left) is not equally straightforward. I'm using a
 +viewport now and scroll it the amount that needs to be clipped.
 +however, the viewport is sensitive to changes in allocation, which
 +makes it harder to use the allocation workarounds.
 +
 +see:
 +- gtk_widget_set_size_request
 +- gtkscrolledwindow
 +
 +I returned to using a simple gtkfixed for the widgetwindow. with
 +allocation hack and set_has_window it works. Idea prefer not to have
 +the allocatien hack and it wasnt needed it gtk3 only gtk2. needs
 +furthi investigation,
 +
 +** various code cleanups
 +There are many cleanups necessary before any hope of inclusion in
 +Emacs trunk. To begin with, the part of the patch that touches other
 +parts of emacs must be very clean. 
 +*** DONE use FRAME_GTK_WIDGET (f)
 +    CLOSED: [2011-07-20 Wed 20:02]
 +rather than gwfixed.
 +
 +*** DONE support configure
 +    CLOSED: [2011-07-12 Tue 18:48]
 +*** TODO ifdef all xwidget code
 +so you can reliably disable the code at compiletime
 +** DONE translate clicks 
 +   CLOSED: [2011-07-03 Sun 22:12]
 +on onscreen webkit peer to offscreen
 +
 +maybe
 +http://developer.gnome.org/gdk/stable/gdk-Windows.html#GdkWindow-from-embedder
 +
 +turned out to be not so hard, captured events, copied them and
 +forwarded them offscreen!
 +
 +** TODO investigate gdk_window_redirect_to_drawable
 +http://developer.gnome.org/gdk/stable/gdk-Windows.html#gdk-offscreen-window-set-embedder
 +maybe could be used in place of my own copy hacks? to work it must
 +support a chain of redirects, which seems unlikely. the benefit would
 +be that I dont have to spend time optimizing redrawing.
 +
 +
 +** DONE remove xwidget_views when emacs window is deleted
 +   CLOSED: [2011-07-05 Tue 11:29]
 +removing xwidget views when an Emacs window closes is not reliable.
 +
 +- switching buffers in a window seems to hide the corresponding
 +  xwidget-views properly, but they might as well be deleted.
 +
 +-  patching delete-window-internal could be used to delete the xwidget-views
 +this seems to work
 +
 +
 +** browser xwidget
 +although embedding a browser is not my primary concern many are
 +interested in this. some suitable browser component needs to be found
 +supporting gtk.
 +
 +*** DONE webkit
 +    CLOSED: [2011-07-03 Sun 22:13]
 +there is a webkit gtk port. there is no obvious mvc support.
 +http://live.gnome.org/WebKitGtk
 +http://webkitgtk.org/
 +
 +it might be possible to keep a set of webxits in artificial
 +synchronisation by recursive deep copy of the DOM from one webkit to
 +another. This will be error prone at best though. Another way might be
 +to just use bitmap copy of the "live"instance to the "phantom"
 +instances. the problem of transfering the live view remains though.
 +
 +export CFLAGS="`pkg-config --cflags webkit-1.0` -DHAVE_WEBKIT -g"
 +export LDFLAGS=`pkg-config --libs webkit-1.0`
 +./configure
 +make
 +
 +**** off screen rendering
 +export CFLAGS="`pkg-config --cflags webkit-1.0` -DHAVE_WEBKIT_OSR -g"
 +export LDFLAGS=`pkg-config --libs webkit-1.0`
 +./configure
 +make
 +
 +works a little bit  but i get errors like:
 +
 +(emacs:8362): GLib-GObject-WARNING **: invalid cast from `GdkOffscreenWindow' to `GdkDrawableImplX11'
 +
 +set a breakpoint in g_log, backtrace seems to indicate
 +webkitViewportAttributesRecompute is the offender. 
 +
 +maybe try gtk3 variants?
 +
 +export CFLAGS="`pkg-config --cflags webkitgtk-3.0 ` -DHAVE_WEBKIT_OSR "
 +export LDFLAGS=`pkg-config --libs webkitgtk-3.0 `
 +./configure   --with-x-toolkit=gtk3
 +make
 +
 +crash in gtk_window_get_size instead. great.
 +
 +http://gtkplus-p3.0.sourcearchive.com/documentation/2.91.5-0ubuntu1/testoffscreenwindow_8c-source.html
 +
 +after many atempts, the basic issue remains. for some reason the
 +offscreen widget isnt ok when I want to snapshot it, so i simply get
 +emptiness. the surface is only ok someimes. 
 +
 +here is a useful debugging snippets:
 +  // debugging redraw:
 +  //  - the bg colors always change, so theres no error in signal handling
 +  //  - i get this error now and then:
 +  //(emacs:7109): GLib-GObject-WARNING **: invalid cast from `GdkOffscreenWindow' to `GdkDrawableImplX11'
 +  // seems to happen in webkit actually. see README
 +  
 +  if(0){ //redraw debug hack. helped a lot in fact. use the with alpha painter below also
 +    cairo_set_source_rgb(cr, osr_dbg_color, 1.0, 0.2);
 +    cairo_rectangle(cr, 0,0, xw->width, xw->height);
 +    cairo_fill(cr);
 +    osr_dbg_color+=0.1;
 +    if(osr_dbg_color>1.0)
 +      osr_dbg_color=0.0;
 +    
 +  }
 +
 +you need to terminate drawing like this:
 +  
 +  //cairo_set_source_surface (cr, src_pixmap, 0,0); 
 +  //cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
 +
 +  //cairo_paint_with_alpha (cr, 1.0);
 +  //cairo_paint(cr);
 +
 +the snippets change background color on oach redraw. 
 +
 +**** on-screen rendering to separate window
 +an alternative might be to open a separate window and snapshot it. the
 +idea is that whatever oddness webkit does so that offscreen rendering
 +doesnt work, doesnt happen on-screen. the window could be opened
 +somewhere not in the way.
 +
 +*** CANCELLED firefox
 +    CLOSED: [2011-07-03 Sun 22:13]
 +http://www-archive.mozilla.org/unix/gtk-embedding.html
 +seems to be severly bitrotted
 +
 +heres a newer aproach
 +http://hg.mozilla.org/incubator/embedding/file/29ac0fe51754/gtk/tests/test.cpp
 +
 +while webkit clearly has the best traction as an embeddee, the
 +offscreen rendering issues makes it interesting to see what ff brings
 +to the table. 
 +
 +turned out webkit has as good offscreen support as anyone, see I went
 +with that in the end.
 +
 +
 +*** DONE text field support
 +    CLOSED: [2011-07-20 Wed 20:05]
 +Emacs captures all keyboard events so text field support isn't super
 +straightforward. 
 +
 +**** propagate keyboard events
 +I have some old hacks for this and they are not good.
 +**** use the DOM model
 +expose document.activeElement to lisp. This is potentially more
 +interesting than just forwarding keyboard events.
 +
 +webkit_web_view_get_dom_document ()
 +
 +this is hard it seems. an idea might be to hack elisp support for swig
 +to machine generate the bindings. 
 +**** DONE inject javascript
 +     CLOSED: [2011-07-03 Sun 22:50]
 +webkit_web_view_execute_script ()
 +
 +this works now:
 +(xwidget-webkit-execute-script 5 "document.activeElement.value='test'")
 +
 +so it should be possible to do some interesting stuff.
 +execute-script does however not return anything at the interface level
 +so satisfaction is not total:
 +
 +http://markmail.org/message/4yowmdgras73z3x5
 +
 +maybe
 +https://launchpad.net/gnome-seed
 +
 +or this funny hack:
 +<jave> im trying to understanh how to interact via javascript to an embedded
 +       webkit gtk instance  [23:38]
 +<jave> i use webkit_web_view_execute_script() which is nice but doesnt return
 +       a value, by design aparently  [23:39]
 +<jave> any hints?
 +<lucian> jave: afaik, webkit still doesn't have full gobject bindings  [23:48]
 +<lucian> jave: you can hack it up by making the JS modify the title, and read
 +         the title from gtk-side
 +<jave> lucian: that was a pretty cool idea!
 +
 +
 +*** webkit_web_view_load_string ()
 +I would like preview of html in a buffer rather than from uri.
 +
 +
 +
 +*** DONE simple xwidget-webkit wrapper
 +    CLOSED: [2011-07-22 Fri 11:01]
 +so that it could be used for actual browsing :)
 +I dont want to reinvent too many wheels so i'd like to use existing
 +emacs facilities here possible. use bindings similar to w3m(or info)
 +
 +- m-x xwidget-webkit starts a session
 +- 'g' goes to a url
 +- use bookmark-jump i suppose. I mostly use org for bookmarks myself
 +- browse-url support so webkit can be the default browser
 +- some way of getting around the quirky keyboard interaction since
 +  xwidgets dont receive keyboard events because I hawe no idea how to
 +  do that in a sane way
 +
 +... and one can of course go on bikeshedding forever. lets keep it
 +simple and extensible, and compatible with other Emacs packages.
 +
 +the really cool ideas would need Emacs DOM integration, which is not
 +easy. 
 +
 +** webkit related
 +*** TODO webkit support webkit signals
 +
 +**** DONE particularily document-load-finished
 +     CLOSED: [2011-08-01 Mon 22:34]
 +http://webkitgtk.org/reference/webkitgtk-webkitwebview.html#WebKitWebView-document-load-finished
 +because one might need tell set a title and sizes and things when it loads.
 +**** TODO event bug
 +Debugger entered--Lisp error: (error "Two bases given in one event")
 +
 +for some reason hapens sometimes with xwidget events.
 +
++maybe I need to set the originating window?
++  event.frame_or_window = Qnil;       //frame; //how to get the frame here? //TODO i store it in the xwidget now
++
 +*** TODO console messages
 +http://webkitgtk.org/reference/webkitgtk-webkitwebview.html#WebKitWebView-console-message
 +http://getfirebug.com/wiki/index.php/Console_API#console.count.28.5Btitle.5D.29
 +because maybe we can make a simple JS REPL that way.
 +  (xwidget-webkit-execute-script ( xwidget-webkit-last-session)
 +  "console.log('hello')")
 +prints hello to stdout but theres no way to catch stdout from webkit I
 +think other than receiving the signal.
 +
 +*** TODO webkit flashkiller by default
 +while its possible to support plugins in the webkit xwidget, flash has
 +issues on 64 bit, and slows down emacs to a halt with off screen
 +rendering, and of course is not free software. its in the way for real
 +world usage even if its interesting to watch flash animations inside
 +emacs. which should be achieved with Gnash or other free software
 +instead.
 +
 +http://stackoverflow.com/questions/4885513/prevent-flash-in-cocoa-webview
 +
 +simply use this api:
 +http://webkitgtk.org/reference/WebKitWebPluginDatabase.html
 +
 +theres an implementation now but it's not robust enough webkit often
 +crashes taking emacs with it.
 +
 +*** TODO webkit downloads
 +when clicking a download link in Webkit Emacs should take over and handle it
 +from there. Probably need signals. There are Emacs libraries to
 +download things, with wget etc.
 +"download-requested"
 +*** TODO webkit alt-text not handled
 +XKCD use image-title to display a cartoon comment. These mysteriously
 +don't work ATM. Other mouseovers work though. Maybe webkit tries to
 +open a new window or something, which wont work.
 +
 +*** TODO webkit isearch in webkit buffers
 +have a look at how docview solves it
 +webkit_web_view_search_text ()
 +*** TODO webkit relative references doesn't work
 +probably because we handle scrolling in a non-standard way. It does
 +work sort of when theres a html frameset and webkit scrols by itself.
 +*** TODO webkit width adjustment handling issue
 +since there are so many levels of clipping and whatnot in xwidgets
 +sizing issues are difficult.
 +
 +- an xwidget is told how large it can be by emacs. thats the end of
 +  it. if the xwidget thinks otherwise it will be clipped.
 +- but emacs can ask the xwudget how large it wants to be. it can then
 +  resize the reserved area and inform the xwidget thusly. 
 +
 +That should have been enough. but webkit never reports less than what
 +it already has. So currently a webkit view will only growth and not
 +adjust to smaller sizes. 
 +
 +This is not a big problem in practice but is still annoying.
 +
 +to see the problem surface to http://www.slashdot.org
 +- xwidget-webkit-adjust-size
 +- xwidget-webkit-adjust-size-to-content
 +
 +and then compare by resizing in Epiphany, which is also webkit based.
 +
 +*** TODO xwidget webkit allow loading from string from emacs
 +*** DONE xwidget-webkit-last-session
 +    CLOSED: [2011-08-01 Mon 22:38]
 +was rather hurried. end result is that the lisp layer only really
 +allows for one webkit session.
 +*** TODO C-X b in other buffer from webkit
 +bafflingly resets the webkit view to the top. Maybe the window
 +reconfiguration hook code? further mystification is added because it
 +only seems to happen with ido mode enabled.
 +
 +in comparison with image-mode which does the right thing, I discovered
 +that image-mode has special code to handle scrolling. the browser mode
 +and image mode has some similarities.
 +
 +** TODO xwidget image display  spec compatibility
 +some history: the first version of the xwidget display spec was
 +the same as an image spec. This turned out not to be fantastic because
 +an xwidget is both like a process and like an image. it has a separate
 +existence from display. So now the xwidget display spec is just a
 +pointer to a xwidget. But then some useful functionality in Emacs
 +can't be reused for xwidget, in particular image-mode.
 +
 +Maybe a new image type could be added that was a wraper on an
 +xwidget. Then image mode could be reused for webkit mode. 
 +
 +** socket related
 +*** TODO some flickering during redisplay of sockets
 +with gtk3 an size allocation workaround is used.
 +this seems maybe to result in flickering sizewize y-axis with the
 +xwidget socket type. The webkit xwidget doesn't seem similarily
 +afflicted.
 +
 +the size allocation workaround works by 1st running the ordinary
 +allocation then modifying the results. its done this way to minimise
 +the copy paste index from the base class. it might be that the
 +original allocation has a brief time window to show itself.
 +
 +tried to modify the allocation hack so it doesn't call allocate
 +twice. this doesn't seem to help flicker at all aparently so the
 +hypothesis falls. Maybe then a socket simply doesn't lke being clipped
 +by gtkfixed. 
 +
 +*** TODO xwidget view reaping too agressive
 +hide an emacs window for a while and return to it. the xwidget might
 +get reaped and a new socket thus created.
 +*** DONE try out OSR for sockets
 +    CLOSED: [2011-07-25 Mon 21:30]
 +
 +didn't work too well in the inkscape case. it might be that some other
 +bitmap copy method works better though.
 +
 +** TODO synchronise emacs background with xwidget color
 +fine-tuning to reduce flicker.
 +
 +
 +
 +** DONE xwidgets doesn't work during bootstrap all of a sudden
 +   CLOSED: [2011-08-01 Mon 22:33]
 +might be some annoying local issues with my install because it is not
 +reliably reproducible. (went away during merges)
 +
 +** TODO low impact xwidget based image viewer
 +for instance to render SVG using webkit, or some other canvas.
 +that way it would be possible to merge to trunk in stages.
 +
 +so, webkit could be used to display the SVG. the display spec for
 +images would be used. multiple webkits would be used rather than
 +offscreen rendering, so it would be GTK2 compatible. 
 +** 
 +* old notes from x_draw_xwidget_glyph_string
 +
 +    BUG it seems this method for some reason is called with bad s->x and s->y sometimes.
 +    When this happens the xwidget doesnt move on screen as it should.
 +    This mightbe because of x_scroll_run. Emacs decides to scroll the screen by blitting sometimes.
 +    then emacs doesnt try to actualy call the paint routines, which means this here code will never
 +    run so the xwidget wont know it has been moved.
 +
 +    Solved temporarily by never optimizing in try_window_reusing_current_matrix().
 +
 +    BUG the phantoming code doesnt work very well when the live xwidget is off screen.
 +    you will get weirdo display artefacts. Composition ought to solve this, since that means the live window is
 +    always available in an off-screen buffer. My current attempt at composition doesnt work properly however.
 +
 +    //allocation debugging. the correct values cant be expected to show upp immediately, but eventually they should get to be ok
 +    // this is because we dont know when the container gets around to doing layout
 +    //GtkAllocation galloc;
 +    //gtk_widget_get_allocation(GTK_WIDGET (xv->widgetwindow), &galloc);
 +    //printf("allocation %d %d , %d %d\n", galloc.x,galloc.y,galloc.width,galloc.height);
 +
 +
 +*** old notes about the old live/phantom scheme
 +
 +   //TODO:
 +   // 1) always draw live xwidget in slected window
 +   // (2) if there were no live instances of the xwidget in selected window, also draw it live)
 +   // 3) if there was a live xwidget previously, now phantom it.
 +
 +   else
 +     {
 +       //ok, we are painting the xwidgets in non-selected window, so draw a phantom
 +       //printf("draw phantom xwidget at:%d %d\n",x,y);
 +       //xwidget_composite_draw_phantom (xw, x, y, clipx, clipy); //TODO MVC there will be very few cases of phantoming
 +     }
 +
 +
 +   atm this works as follows: only check if xwidgets are displayed in the
 +   "selected window". if not, hide them or phantom them.
 +
 +   this means valid cases like xwidgets being displayed only once in
 +   non-selected windows, does not work well. they should also be visible
 +   in that case not phantomed.
 +
Simple merge
diff --cc configure.in
Simple merge
diff --cc lisp/xwidget.el
index 0a1d22b9224fcf4e2b836ea012678e351744f573,0000000000000000000000000000000000000000..df6e77b708b8a1059e91e6bc7d1ca3423a9e86fc
mode 100644,000000..100644
--- /dev/null
@@@ -1,250 -1,0 +1,255 @@@
-        (funcall ,fn))))
 +;; xwidget.el - api functions for xwidgets
 +;;  see xwidget.c for more api functions
 +
 +(require 'xwidget-internal)
 +
 +;;TODO model after make-text-button instead!
 +(defun xwidget-insert (pos type title width height)
 +  "Insert an xwidget at POS, given ID, TYPE, TITLE WIDTH and HEIGHT.
 +Return ID
 +
 +see xwidget.c for types suitable for TYPE.
 +"
 +  (goto-char pos)
 +  (let ((id (make-xwidget (point) (point)  type  title  width  height nil)))
 +    (put-text-property (point)
 +                       (+ 1 (point)) 'display (list 'xwidget ':xwidget id))
 +    
 +    id))
 +
 +
 +(defun xwidget-at (pos)
 +  ;;this function is a bit tedious because the C layer isnt well protected yet and
 +  ;;xwidgetp aparently doesnt work yet
 +  (let* ((disp (get-text-property pos 'display))
 +         (xw (car (cdr (cdr  disp)))))
 +    ;;(if ( xwidgetp  xw) xw nil)
 +    (if (equal 'xwidget (car disp)) xw)
 +    ))
 +
 +
 +
 +
 +(defun xwidget-socket-handler ()
 +  "creates plug for socket. TODO"
 +  (interactive)
 +  (message "socket handler xwidget %S" last-input-event)
 +  (let*
 +      ((xwidget-event-type (nth 2 last-input-event))
 +       (xwidget-id (nth 1 last-input-event)))
 +    (cond ( (eq xwidget-event-type 'xembed-ready)
 +            (let*
 +                ((xembed-id (nth 3 last-input-event)))
 +              (message "xembed ready  event: %S xw-id:%s" xembed-id xwidget-id)
 +              ;;TODO fetch process data from the xwidget. create it, store process info
 +              ;;will start emacs/uzbl in a xembed socket when its ready
 +              ;; (cond
 +              ;;  ((eq 3 xwidget-id)
 +              ;;   (start-process "xembed" "*xembed*" (format "%ssrc/emacs" default-directory) "-q" "--parent-id" (number-to-string xembed-id) ) )
 +              ;;  ((eq 5 xwidget-id)
 +              ;;   (start-process "xembed2" "*xembed2*" "uzbl-core"  "-s" (number-to-string xembed-id)  "http://www.fsf.org" )  )
 +              )))))
 +
 +
 +
 +
 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 +;;; webkit support
 +(require 'browse-url)
 +(require 'image-mode);;for some image-mode alike functinoality
 +(require 'cl);;for flet
 +
 +;;;###autoload
 +(defun xwidget-webkit-browse-url (url &optional new-session)
 +  "Ask xwidget-webkit to browse URL.
 +NEW-SESSION specifies whether to create a new xwidget-webkit session.  URL
 +defaults to the string looking like a url around the cursor position."
 +  (interactive (progn
 +               (require 'browse-url)
 +               (browse-url-interactive-arg "xwidget-webkit URL: ")))
 +  (when (stringp url)
 +    (if new-session
 +      (xwidget-webkit-new-session url)
 +      (xwidget-webkit-goto-url url))))
 +
 +
 +;;shims for adapting image mode code to the webkit browser window
 +(defun xwidget-image-display-size  (spec &optional pixels frame)
 +  (let ((xwi (xwidget-info  (xwidget-at 1))))
 +    (cons (aref xwi 2)
 +          (aref xwi 3))))
 +
 +(defmacro xwidget-image-mode-navigation-adaptor (fn)
 +  `(lambda () (interactive)
 +     (flet ((image-display-size (spec) (xwidget-image-display-size spec)))
-     (define-key map [remap forward-char]       (xwidget-image-mode-navigation-adaptor  'image-forward-hscroll))
-     (define-key map [remap backward-char]       (xwidget-image-mode-navigation-adaptor  'image-backward-hscroll))
-     (define-key map [remap right-char]       (xwidget-image-mode-navigation-adaptor  'image-forward-hscroll))
-     (define-key map [remap left-char]       (xwidget-image-mode-navigation-adaptor  'image-backward-hscroll))
-     (define-key map [remap previous-line]       (xwidget-image-mode-navigation-adaptor  'image-previous-line))
-     (define-key map [remap next-line]       (xwidget-image-mode-navigation-adaptor  'image-next-line))
++       (funcall ,fn ))))
++
++(defmacro xwidget-image-mode-navigation-adaptor-p (fn)
++  `(lambda (n) (interactive "p")
++     (flet ((image-display-size (spec) (xwidget-image-display-size spec)))
++       (funcall ,fn n))))
 +
 +
 +;;todo.
 +;; - check that the webkit support is compiled in
 +(defvar xwidget-webkit-mode-map
 +  (let ((map (make-sparse-keymap)))
 +    (define-key map "g" 'xwidget-webkit-browse-url)
 +    (define-key map "a" 'xwidget-webkit-adjust-size-to-content)
 +    (define-key map "b" 'xwidget-webkit-back )
 +    (define-key map "r" 'xwidget-webkit-reload )
 +    (define-key map "t" (lambda () (interactive) (message "o")) )    
 +    (define-key map "\C-m" 'xwidget-webkit-insert-string)
 +    (define-key map [xwidget-event] 'xwidget-webkit-event-handler)
 +
 +    ;;similar to image mode bindings
 +    ;;TODO theres something wrong with the macro
 +    (define-key map (kbd "SPC")       (xwidget-image-mode-navigation-adaptor   'image-scroll-up))
 +    (define-key map (kbd "DEL")       (xwidget-image-mode-navigation-adaptor   'image-scroll-down))
 +
 +    (define-key map [remap scroll-up]          (xwidget-image-mode-navigation-adaptor 'image-scroll-up))
 +    (define-key map [remap scroll-up-command]  (xwidget-image-mode-navigation-adaptor 'image-scroll-up))
 +    
 +    (define-key map [remap scroll-down]       (xwidget-image-mode-navigation-adaptor  'image-scroll-down))
 +    (define-key map [remap scroll-down-command]       (xwidget-image-mode-navigation-adaptor  'image-scroll-down))
 +
 +    
++    (define-key map [remap forward-char]       (xwidget-image-mode-navigation-adaptor-p  'image-forward-hscroll))
++    (define-key map [remap backward-char]       (xwidget-image-mode-navigation-adaptor-p  'image-backward-hscroll))
++    (define-key map [remap right-char]       (xwidget-image-mode-navigation-adaptor-p  'image-forward-hscroll))
++    (define-key map [remap left-char]       (xwidget-image-mode-navigation-adaptor-p  'image-backward-hscroll))
++    (define-key map [remap previous-line]       (xwidget-image-mode-navigation-adaptor-p  'image-previous-line))
++    (define-key map [remap next-line]       (xwidget-image-mode-navigation-adaptor-p  'image-next-line))
 +
 +
 +    (define-key map [remap move-beginning-of-line]       (xwidget-image-mode-navigation-adaptor  'image-bol))
 +    (define-key map [remap move-end-of-line]       (xwidget-image-mode-navigation-adaptor  'image-eol))
 +    (define-key map [remap beginning-of-buffer]       (xwidget-image-mode-navigation-adaptor  'image-bob))
 +    (define-key map [remap end-of-buffer]       (xwidget-image-mode-navigation-adaptor  'image-eob))
 +
 +    
 +    map)
 +  
 +  "Keymap for `xwidget-webkit-mode'.")
 +
 +
 +(defun xwidget-webkit-event-handler ()
 +  (interactive)
 +  (message "stuff happened to webkit xwidget %S" last-input-event)
 +  (let*
 +      ((xwidget-event-type (nth 2 last-input-event))
 +       (xwidget (nth 1 last-input-event)))
 +    (cond ((eq xwidget-event-type 'document-load-finished)
 +           (message "webkit loaded %s" xwidget)
 +           (xwidget-webkit-adjust-size-to-content))
 +          )))
 +
 +(define-derived-mode xwidget-webkit-mode
 +  special-mode "xwidget-webkit" "xwidget webkit view mode"
 +  (setq buffer-read-only t)
 +  ;; Keep track of [vh]scroll when switching buffers
 +  (image-mode-setup-winprops)
 +
 +  )
 +
 +(defvar xwidget-webkit-last-session-buffer nil)
 +
 +(defun  xwidget-webkit-last-session ()
 +  "last active webkit, or a new one"
 +  (if (buffer-live-p xwidget-webkit-last-session-buffer)
 +      (save-excursion
 +        (set-buffer xwidget-webkit-last-session-buffer)
 +        (xwidget-at 1))
 +    nil))
 +
 +(defun xwidget-webkit-current-session ()
 +  "either the webkit in the current buffer, or the last one used"
 +  (if (xwidget-at 1)
 +      (xwidget-at 1)
 +    (xwidget-webkit-last-session)))
 +
 +(defun xwidget-adjust-size-to-content (xw)
 +  ;;xwidgets doesnt support widgets that have thoir own opinions about size well yet
 +  ;;this reads the size and sets it back
 +  (let ((size (xwidget-size-request xw)))
 +    (xwidget-resize xw (car size) (cadr size))))
 +
 +
 +(defun xwidget-webkit-insert-string (xw str)
 +  (interactive (list (xwidget-webkit-current-session)
 +                     (read-string "string:")))
 +  (xwidget-webkit-execute-script xw (format "document.activeElement.value='%s'" str)))
 +
 +(defun xwidget-webkit-adjust-size-to-content ()
 +  (interactive)
 +  ( xwidget-adjust-size-to-content ( xwidget-webkit-current-session)))
 +
 +(defun xwidget-webkit-adjust-size (w h)
 +  (interactive "nWidth:\nnHeight:\n")
 +  ( xwidget-resize ( xwidget-webkit-current-session) w h))
 +
 +
 +(defun xwidget-webkit-new-session (url)
 +
 +  (let*
 +      ((bufname (generate-new-buffer-name "*xwidget-webkit*"))
 +       )
 +    (setq xwidget-webkit-last-session-buffer (switch-to-buffer (get-buffer-create bufname)))
 +    (insert " ")
 +    (xwidget-insert 1 'webkit-osr  bufname 1000 1000)
 +    (xwidget-webkit-mode)
 +    (xwidget-webkit-goto-uri ( xwidget-webkit-last-session) url )))
 +
 +
 +(defun xwidget-webkit-goto-url (url)
 +  (if ( xwidget-webkit-current-session)
 +      (progn
 +        (xwidget-webkit-goto-uri ( xwidget-webkit-current-session) url))
 +    ( xwidget-webkit-new-session url)))
 +
 +(defun xwidget-webkit-back ()
 +  (interactive)
 +  (xwidget-webkit-execute-script ( xwidget-webkit-current-session)  "history.go(-1);"))
 +
 +(defun xwidget-webkit-reload ()
 +  (interactive)
 +  (xwidget-webkit-execute-script ( xwidget-webkit-current-session)  "history.go(0);"))
 +
 +(defun xwidget-current-url ()
 +  "get the webkit url"
 +  ;;notice the fugly "title" hack. it is needed because the webkit api doesnt support returning values.
 +  ;;TODO make a wrapper for the title hack so its easy to remove should webkit someday support JS return values
 +  (xwidget-webkit-execute-script (xwidget-webkit-current-session) "document.title=document.URL;")
 +  (xwidget-webkit-get-title (xwidget-webkit-current-session)))
 +
 +
 +
 +;; use declare here?
 +;; (declare-function xwidget-resize-internal "xwidget.c" )
 +;; check-declare-function?
 +
 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 +(defun xwidget-cleanup ()
 +  ;;its still pretty easy to trigger bugs with xwidgets.
 +  ;;this function tries to implement a workaround
 +  (interactive)
 +  (xwidget-delete-zombies) ;;kill xviews who should have been deleted but stull linger
 +  (redraw-display);;redraw display otherwise ghost of zombies  will remain to haunt the screen
 +  )
 +
 +
 +
 +;;this is a workaround because I cant find the right place to put it in C
 +(add-hook 'window-configuration-change-hook 'xwidget-cleanup)
 +
 +;;killflash is sadly not reliable yet. 
 +(defvar xwidget-webkit-kill-flash-oneshot t)
 +(defun xwidget-webkit-kill-flash ()
 +  ;;you can only call this once or webkit crashes and takes emacs with it. odd.
 +  (unless xwidget-webkit-kill-flash-oneshot
 +    (xwidget-disable-plugin-for-mime "application/x-shockwave-flash")
 +    (setq xwidget-webkit-kill-flash-oneshot t)))
 +
 +(xwidget-webkit-kill-flash)
 +
 +(provide 'xwidget)
diff --cc src/Makefile.in
Simple merge
Simple merge
diff --cc src/dispnew.c
Simple merge
diff --cc src/emacs.c
Simple merge
diff --cc src/keyboard.c
Simple merge
diff --cc src/window.c
Simple merge
diff --cc src/xdisp.c
Simple merge
diff --cc src/xterm.c
Simple merge
diff --cc src/xwidget.c
index 1a3e76dd4a2065fddf38f409cb05504475c369e1,0000000000000000000000000000000000000000..0a5ce3c6f0c473880ac6557e156e07ad36cf334c
mode 100644,000000..100644
--- /dev/null
@@@ -1,1134 -1,0 +1,1133 @@@
-   //event.arg = Fcons (make_number (xembedid), event.arg);
 +#include <config.h>
 +
 +#include <signal.h>
 +
 +#include <stdio.h>
 +#include <setjmp.h>
 +#ifdef HAVE_X_WINDOWS
 +
 +#include "lisp.h"
 +#include "blockinput.h"
 +#include "syssignal.h"
 +
 +#include "xterm.h"
 +#include <X11/cursorfont.h>
 +
 +#ifndef makedev
 +#include <sys/types.h>
 +#endif /* makedev */
 +
 +#ifdef BSD_SYSTEM
 +#include <sys/ioctl.h>
 +#endif /* ! defined (BSD_SYSTEM) */
 +
 +#include "systime.h"
 +
 +#ifndef INCLUDED_FCNTL
 +#include <fcntl.h>
 +#endif
 +#include <ctype.h>
 +#include <errno.h>
 +#include <setjmp.h>
 +#include <sys/stat.h>
 +
 +#include "charset.h"
 +#include "character.h"
 +#include "coding.h"
 +#include "ccl.h"
 +#include "frame.h"
 +#include "dispextern.h"
 +#include "fontset.h"
 +#include "termhooks.h"
 +#include "termopts.h"
 +#include "termchar.h"
 +#include "emacs-icon.h"
 +#include "disptab.h"
 +#include "buffer.h"
 +#include "window.h"
 +#include "keyboard.h"
 +#include "intervals.h"
 +#include "process.h"
 +#include "atimer.h"
 +#include "keymap.h"
 +
 +
 +#ifdef USE_X_TOOLKIT
 +#include <X11/Shell.h>
 +#endif
 +#include <X11/extensions/Xcomposite.h>
 +#include <X11/extensions/Xrender.h>
 +#include <cairo.h>
 +#ifdef HAVE_SYS_TIME_H
 +#include <sys/time.h>
 +#endif
 +#ifdef HAVE_UNISTD_H
 +#include <unistd.h>
 +#endif
 +
 +#include "gtkutil.h"
 +#include "font.h"
 +#endif
 +
 +#include <gtk/gtk.h>
 +#include <gdk/gdk.h>
 +
 +#ifdef HAVE_GTK3
 +//for gtk3; sockets and plugs
 +#include <gtk/gtkx.h>
 +#include "emacsgtkfixed.h"
 +#endif
 +
 +#include <librsvg/rsvg.h>
 +
 +#ifdef HAVE_GOOCANVAS
 +#include <goocanvas.h>
 +#endif
 +
 +#ifdef HAVE_CLUTTER
 +#include <clutter/clutter.h>
 +#include <clutter-gtk/clutter-gtk.h>
 +#endif
 +
 +#include <wchar.h>
 +
 +#ifdef HAVE_WEBKIT_OSR
 +#include <webkit/webkitwebview.h>
 +#include <webkit/webkitwebplugindatabase.h>
 +#include <webkit/webkitwebplugin.h>
 +#include <webkit/webkitglobals.h>
 +#endif
 +
 +#include "xwidget.h"
 +
 +//TODO should of course not be a hardcoded array but I can't be bothered atm
 +//just a fixed array of xwidgets for now
 +//would need to be hashtables or something
 +
 +#define MAX_XWIDGETS 100
 +struct xwidget_view xwidget_views[MAX_XWIDGETS];
 +
 +//TODO embryo of lisp allocators for xwidgets
 +//TODO xwidget* should be Lisp_xwidget*
 +struct xwidget*
 +allocate_xwidget (void)
 +{
 +  return ALLOCATE_PSEUDOVECTOR (struct xwidget, height, PVEC_XWIDGET);
 +}
 +
 +//TODO xwidget_view* should be Lisp_xwidget_view*
 +struct xwidget_view*
 +allocate_xwidget_view (void)
 +{
 +  return ALLOCATE_PSEUDOVECTOR (struct xwidget_view, redisplayed, PVEC_XWIDGET_VIEW);
 +}
 +
 +
 +Lisp_Object Qxwidget;
 +Lisp_Object Qcxwidget;
 +Lisp_Object Qtitle;
 +Lisp_Object Qxwidget_set_keyboard_grab;
 +Lisp_Object Qxwidget_embed_steal_window;
 +Lisp_Object Qxwidget_info;
 +Lisp_Object Qxwidget_resize;
 +Lisp_Object Qxwidget_send_keyboard_event;
 +
 +Lisp_Object Qbutton, Qtoggle, Qslider, Qsocket, Qsocket_osr, Qcairo,
 +  Qwebkit_osr, QCplist;
 +
 +
 +extern Lisp_Object  QCtype;
 +extern Lisp_Object QCwidth, QCheight;
 +
 +struct xwidget_view* xwidget_view_lookup(struct xwidget* xw,     struct window *w);
 +Lisp_Object xwidget_spec_value ( Lisp_Object spec, Lisp_Object  key,  int *found);
 +gboolean webkit_osr_damage_event_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data) ;
 +void     webkit_osr_document_load_finished_callback (WebKitWebView  *webkitwebview,
 +                                                     WebKitWebFrame *arg1,
 +                                                     gpointer        user_data);
 +
 +DEFUN ("make-xwidget", Fmake_xwidget, Smake_xwidget, 7, 7, 0,
 +         doc: /* xw */
 +         )
 +  (Lisp_Object beg, Lisp_Object end,
 +     Lisp_Object type,
 +     Lisp_Object title,
 +     Lisp_Object width, Lisp_Object height,
 +     Lisp_Object data)
 +{
 +  //should work a bit like "make-button"(make-button BEG END &rest PROPERTIES)
 +  // arg "type" and fwd should be keyword args eventually
 +  //(make-xwidget 3 3 'button "oei" 31 31 nil)
 +  //(xwidget-info (car xwidget-alist))
 +  struct xwidget* xw = allocate_xwidget();
 +  Lisp_Object val;
 +  struct gcpro gcpro1;
 +  GCPRO1(xw);
 +  XSETSYMBOL(xw->type, type);
 +  XSETSTRING(xw->title, title);
 +  XSETBUFFER(xw->buffer,  Fcurrent_buffer()); // conservatively gcpro xw since we call lisp
 +  xw->height = XFASTINT(height);
 +  xw->width = XFASTINT(width);
 +  XSETPSEUDOVECTOR (val, xw, PVEC_XWIDGET); //?? dunno why i need this
 +  Vxwidget_alist = Fcons ( val, Vxwidget_alist);
 +  xw->widgetwindow_osr = NULL;
 +  xw->widget_osr = NULL;
 +
 +
 +
 +#ifdef HAVE_WEBKIT_OSR
 +  /* DIY mvc. widget is rendered offscreen,
 +     later bitmap copied to the views.
 +   */
 +  if (EQ(xw->type, Qwebkit_osr)){
 +    printf("init webkit osr\n");
 +    BLOCK_INPUT;
 +    xw->widgetwindow_osr = GTK_CONTAINER (gtk_offscreen_window_new ());
 +    gtk_window_resize(    GTK_WINDOW(xw->widgetwindow_osr), xw->width, xw->height);
 +    xw->widget_osr = webkit_web_view_new();
 +
 +    gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, xw->height);
 +    gtk_container_add (xw->widgetwindow_osr, xw->widget_osr);
 +
 +    gtk_widget_show_all (GTK_WIDGET (xw->widgetwindow_osr));
 +
 +    /* store some xwidget data in the gtk widgets for convenient retrieval in the event handlers. */
 +    g_object_set_data (G_OBJECT (xw->widget_osr), XG_XWIDGET, (gpointer) (xw));
 +    g_object_set_data (G_OBJECT (xw->widgetwindow_osr), XG_XWIDGET, (gpointer) (xw));
 +    /* signals */
 +    g_signal_connect (G_OBJECT ( xw->widgetwindow_osr), "damage-event",    G_CALLBACK (webkit_osr_damage_event_callback), NULL);
 +    g_signal_connect (G_OBJECT ( xw->widget_osr),
 +                      "document-load-finished",
 +                      G_CALLBACK (webkit_osr_document_load_finished_callback),
 +                      xw);    
 +
 +    webkit_web_view_load_uri(WEBKIT_WEB_VIEW(xw->widget_osr), "http://www.fsf.org");
 +    UNBLOCK_INPUT;
 +
 +  }
 +#endif
 +  if (EQ(xw->type, Qsocket_osr)){
 +    printf("init socket osr\n");
 +    BLOCK_INPUT;
 +    xw->widgetwindow_osr = GTK_CONTAINER (gtk_offscreen_window_new ());
 +    gtk_window_resize(    GTK_WINDOW(xw->widgetwindow_osr), xw->width, xw->height);
 +
 +    ////////////////////
 +    //xw->widget_osr = webkit_web_view_new();
 +    xw->widget_osr = gtk_socket_new();
 +    //g_signal_connect_after(xv->widget, "plug-added", G_CALLBACK(xwidget_plug_added), "plug added");
 +    //g_signal_connect_after(xv->widget, "plug-removed", G_CALLBACK(xwidget_plug_removed), "plug removed");
 +    ///////////////////
 +    
 +    gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, xw->height);
 +    gtk_container_add (xw->widgetwindow_osr, xw->widget_osr);
 +
 +    gtk_widget_show_all (GTK_WIDGET (xw->widgetwindow_osr));
 +
 +    /* store some xwidget data in the gtk widgets for convenient retrieval in the event handlers. */
 +    g_object_set_data (G_OBJECT (xw->widget_osr), XG_XWIDGET, (gpointer) (xw));
 +    g_object_set_data (G_OBJECT (xw->widgetwindow_osr), XG_XWIDGET, (gpointer) (xw));
 +    g_signal_connect (G_OBJECT (    xw->widgetwindow_osr), "damage-event",    G_CALLBACK (webkit_osr_damage_event_callback), NULL);
 +
 +    //webkit_web_view_load_uri(WEBKIT_WEB_VIEW(xw->widget_osr), "http://www.fsf.org");
 +    UNBLOCK_INPUT;
 +
 +  }
 +
 +  UNGCPRO;
 +  return val;
 +}
 +
 +int
 +xwidget_hidden(struct xwidget_view *xv)
 +{
 +  return  xv->hidden;
 +}
 +
 +
 +static void
 +buttonclick_handler (GtkWidget * widget, gpointer data)
 +{
 +  struct xwidget *xw = (struct xwidget *) data;
 +  struct input_event event;
 +  Lisp_Object frame;
 +  FRAME_PTR f = NULL;//(FRAME_PTR) g_object_get_data (G_OBJECT (xw->widget), XG_FRAME_DATA); //TODO
 +  printf ("button clicked xw:%d '%s'\n", xw, xw->title);
 +
 +  EVENT_INIT (event);
 +  event.kind = XWIDGET_EVENT;
 +
 +  XSETFRAME (frame, f);
 +
 +  event.frame_or_window = Qnil;       //frame; //how to get the frame here?
 +
 +
 +  event.arg = Qnil;
 +  event.arg = Fcons (xw, event.arg); //TODO send the actual xwidget object now instead
 +  event.arg = Fcons (intern ("buttonclick"), event.arg);
 +
 +  kbd_buffer_store_event (&event);
 +
 +
 +}
 +
 +
 +static void
 +send_xembed_ready_event (struct xwidget* xw, int xembedid)
 +{
 +  struct input_event event;
 +  EVENT_INIT (event);
 +  event.kind = XWIDGET_EVENT;
 +  event.frame_or_window = Qnil;       //frame; //how to get the frame here? //TODO i store it in the xwidget now
 +
 +  event.arg = Qnil;
 +  event.arg = Fcons (make_number (xembedid), event.arg);
 +  event.arg = Fcons (intern ("xembed-ready"), event.arg);
 +  event.arg = Fcons (xw, event.arg); //TODO
 +
 +
 +  kbd_buffer_store_event (&event);
 +
 +}
 +
 +void
 +xwidget_show_view (struct xwidget_view *xv)
 +{
 +  xv->hidden = 0;
 +  gtk_widget_show(GTK_WIDGET(xv->widgetwindow));
 +  gtk_fixed_move (GTK_FIXED (xv->emacswindow), GTK_WIDGET (xv->widgetwindow),  xv->x  + xv->clip_left, xv->y + xv->clip_top); //TODO refactor
 +}
 +
 +
 +/* hide an xvidget view */
 +void
 +xwidget_hide_view (struct xwidget_view *xv)
 +{
 +  xv->hidden = 1;
 +  //gtk_widget_hide(GTK_WIDGET(xw->widgetwindow));
 +  gtk_fixed_move (GTK_FIXED (xv->emacswindow), GTK_WIDGET (xv->widgetwindow),
 +                  10000, 10000);
 +}
 +
 +
 +void xwidget_plug_added(GtkSocket *socket,
 +                        gpointer   user_data)
 +{
 +  //hmm this doesnt seem to get called for foreign windows
 +  printf("xwidget_plug_added\n");
 +}
 +
 +gboolean xwidget_plug_removed(GtkSocket *socket,
 +                              gpointer   user_data)
 +{
 +  printf("xwidget_plug_removed\n");
 +  return TRUE; /* dont run the default handler because that kills the socket and we want to reuse it*/
 +}
 +
 +
 +void xwidget_slider_changed (GtkRange *range,
 +                             gpointer  user_data)
 +{
 +  //slider value changed. change value of siblings
 +  //correspondingly. but remember that changing value will again
 +  //trigger signal
 +
 +  //TODO MVC view storage wont be an array futureish so the loop needs to change eventually
 +  //TODO MVC it would be nice if this code could be reusable but, alas, C is not a functional language
 +  //issues are:
 +  // - the type of the controllers value (double, boolean etc)
 +  // - the getter and setter (but they can be func pointers)
 +  // a behemoth macro is always an option.
 +  double v=gtk_range_get_value(range);
 +  struct xwidget_view* xvp = g_object_get_data (G_OBJECT (range), XG_XWIDGET_VIEW);
 +  struct xwidget_view* xv;
 +
 +  printf("slider changed val:%f\n", v);
 +
 +
 +  //block sibling views signal handlers
 +  for (int i = 0; i < MAX_XWIDGETS; i++)
 +    {
 +      xv = &xwidget_views[i];
 +      if(xv->initialized && xvp->model == xv->model){
 +        g_signal_handler_block( xv->widget,xv->handler_id);
 +      }
 +    }
 +  //set values of sibling views and unblock
 +  for (int i = 0; i < MAX_XWIDGETS; i++)
 +    {
 +      xv = &xwidget_views[i];
 +      if(xv->initialized && xvp->model == xv->model){
 +        gtk_range_set_value(GTK_RANGE(xv->widget), v);
 +        g_signal_handler_unblock( xv->widget,xv->handler_id);
 +      }
 +    }
 +
 +}
 +
 +
 +/* when the off-screen webkit master view changes this signal is called.
 +   it copies the bitmap from the off-screen webkit instance */
 +gboolean webkit_osr_damage_event_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data)
 +{
 +  //TODO this is wrong! should just oueu a redraw of onscreen widget
 +  struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
 +  struct xwidget_view* xv;
 +  //webkit_osr_redraw_child(xw, widget);
 +  printf ("damage\n");
 +  for (int i = 0; i < MAX_XWIDGETS; i++)//todo mvc refactor
 +    {
 +      xv = &xwidget_views[i];
 +      if(xv->initialized && xv->model == xw){
 +        gtk_widget_queue_draw (xv->widget); //redraw all views, the master has changed
 +      }
 +    }
 +
 +  return FALSE;
 +}
 +
 +
 +void     webkit_osr_document_load_finished_callback (WebKitWebView  *webkitwebview,
 +                                                     WebKitWebFrame *arg1,
 +                                                     gpointer        data)
 +{
 +  //TODO this event sending code should be refactored
 +  struct input_event event;
 +  //  struct xwidget *xw = (struct xwidget *) data;
 +  struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (webkitwebview), XG_XWIDGET);  
 +  printf("webkit finished loading\n");
 +
 +  EVENT_INIT (event);
 +  event.kind = XWIDGET_EVENT;
 +  event.frame_or_window = Qnil;       //frame; //how to get the frame here? //TODO i store it in the xwidget now
 +
 +  event.arg = Qnil;
 +  event.arg = Fcons (xw, event.arg); //TODO
 +  event.arg = Fcons (intern ("document-load-finished"), event.arg);
 +
 +
 +  kbd_buffer_store_event (&event);
 +
 +}
 +
 +//for gtk3 webkit_osr
 +gboolean
 +xwidget_osr_draw_callback (GtkWidget *widget, cairo_t *cr, gpointer data)
 +{
 +  struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
 +  struct xwidget_view* xv = (struct xwidget_view*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET_VIEW);
 +
 +  //  printf("xwidget_osr_draw_callback gtk3 xw.id:%d xw.type:%d window:%d vis:%d\n",
 +  //         xw,xw->type, gtk_widget_get_window (widget),  gtk_widget_get_visible (xw->widget_osr));
 +
 +  cairo_rectangle(cr, 0,0, xv->clip_right, xv->clip_bottom);//xw->width, xw->height);
 +  cairo_clip(cr);
 +
 +  gtk_widget_draw (xw->widget_osr,  cr);
 +
 +
 +  return FALSE;
 +}
 +
 +
 +gboolean
 +xwidget_osr_button_callback ( GtkWidget *widget,
 +                              GdkEvent  *event,
 +                              gpointer   user_data)
 +{
 +  struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
 +  GdkEvent* eventcopy =  gdk_event_copy(event);
 +
 +  ((GdkEventButton*)eventcopy)->window = gtk_widget_get_window(xw->widget_osr);
 +  gtk_main_do_event(eventcopy); //TODO this will leak events. they should be deallocated later
 +}
 +
 +int xwidget_view_index=0;
 +
 +/* initializes and does initial placement of an xwidget view on screen */
 +struct xwidget_view*
 +xwidget_init_view (
 +                   struct xwidget *xww,
 +                   struct glyph_string *s,
 +                   int x, int y)
 +{
 +  //TODO temp code replace with lisp list
 +  struct xwidget_view *xv;
 +  GdkColor color;
 +
 +  do{
 +    if(xwidget_view_index < MAX_XWIDGETS)
 +      xwidget_view_index++;
 +    else
 +      xwidget_view_index=0;
 +
 +    xv = &xwidget_views[xwidget_view_index];
 +  }while(  xv->initialized == 1); //TODO yeah this can infloop if there are MAX_WIDGETS on-screen
 +
 +  xv->initialized = 1;
 +  xv->w = s->w;
 +  xv->model = xww;
 +
 +  //widget creation
 +  if(EQ(xww->type, Qbutton))
 +    {
 +      xv->widget = gtk_button_new_with_label (XSTRING(xww->title)->data);
 +      g_signal_connect (G_OBJECT (xv->widget), "clicked",
 +                        G_CALLBACK (buttonclick_handler), xww); //the model rather than the view
 +    } else if (EQ(xww->type, Qtoggle)) {
 +    xv->widget = gtk_toggle_button_new_with_label (XSTRING(xww->title)->data);
 +  } else if (EQ(xww->type, Qsocket)) {
 +    xv->widget = gtk_socket_new ();
 +    g_signal_connect_after(xv->widget, "plug-added", G_CALLBACK(xwidget_plug_added), "plug added");
 +    g_signal_connect_after(xv->widget, "plug-removed", G_CALLBACK(xwidget_plug_removed), "plug removed");
 +  } else if (EQ(xww->type, Qslider)) {
 +    xv->widget =
 +      //gtk_hscale_new (GTK_ADJUSTMENT(gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 10.0, 10.0)));
 +      gtk_hscale_new_with_range ( 0.0, 100.0, 10.0);
 +    gtk_scale_set_draw_value (GTK_SCALE (xv->widget), FALSE); //i think its emacs role to show text and stuff, so disable the widgets own text
 +    xv->handler_id = g_signal_connect_after(xv->widget, "value-changed", G_CALLBACK(xwidget_slider_changed), "slider changed");
 +  } else if (EQ(xww->type, Qcairo)) {
 +    //Cairo view
 +    //uhm cairo is differentish in gtk 3.
 +    //gdk_cairo_create (gtk_widget_get_window (FRAME_GTK_WIDGET (s->f)));
 +#ifdef HAVE_GOOCANVAS
 +    xv->widget = goo_canvas_new();
 +    GooCanvasItem *root, *rect_item, *text_item;
 +    goo_canvas_set_bounds (GOO_CANVAS (xv->widget), 0, 0, 1000, 1000);
 +    root = goo_canvas_get_root_item (GOO_CANVAS (xv->widget));
 +    rect_item = goo_canvas_rect_new (root, 100, 100, 400, 400,
 +                                     "line-width", 10.0,
 +                                     "radius-x", 20.0,
 +                                     "radius-y", 10.0,
 +                                     "stroke-color", "yellow",
 +                                     "fill-color", "red",
 +                                     NULL);
 +
 +    text_item = goo_canvas_text_new (root, "Hello World", 300, 300, -1,
 +                                     GTK_ANCHOR_CENTER,
 +                                     "font", "Sans 24",
 +                                     NULL);
 +    goo_canvas_item_rotate (text_item, 45, 300, 300);
 +
 +#endif
 +#ifdef HAVE_CLUTTER
 +    xv->widget = gtk_clutter_embed_new ();;
 +    ClutterActor *stage = NULL;
 +    stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (        xv->widget));
 +    ClutterColor stage_color = { 0xaa, 0xaa, 0xaa, 0xff }; /* Black */
 +    clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
 +
 +    ClutterActor *  texture =  clutter_cairo_texture_new (1000, 1000);
 +    clutter_container_add_actor(stage, texture);
 +    clutter_actor_set_position(texture, 0,0);
 +    clutter_actor_show(texture);
 +
 +    cairo_t *cr;
 +    cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (texture));
 +
 +    /* draw on the context */
 +    RsvgHandle *h =  rsvg_handle_new_from_file  ("/tmp/tst.svg",
 +                                                 NULL);
 +
 +    rsvg_handle_render_cairo(h, cr);
 +    cairo_destroy (cr);
 +
 +    /* Show the stage: */
 +    clutter_actor_show (stage);
 +#endif
 +  } else if (EQ(xww->type, Qwebkit_osr)||EQ(xww->type, Qsocket_osr)) {
 +#ifdef HAVE_WEBKIT_OSR
 +    xv->widget = gtk_drawing_area_new();
 +    gtk_widget_set_app_paintable ( xv->widget, TRUE); //because expose event handling
 +    gtk_widget_add_events(xv->widget,
 +                          GDK_BUTTON_PRESS_MASK
 +                          | GDK_BUTTON_RELEASE_MASK
 +                          | GDK_POINTER_MOTION_MASK);
 +    g_signal_connect (G_OBJECT (    xv->widget), "draw",
 +                      G_CALLBACK (xwidget_osr_draw_callback), NULL);
 +    g_signal_connect (G_OBJECT (    xv->widget), "button-press-event",
 +                      G_CALLBACK (xwidget_osr_button_callback), NULL);
 +    g_signal_connect (G_OBJECT (    xv->widget), "button-release-event",
 +                      G_CALLBACK (xwidget_osr_button_callback), NULL);
 +    g_signal_connect (G_OBJECT (    xv->widget), "motion-notify-event",
 +                      G_CALLBACK (xwidget_osr_button_callback), NULL);
 +#endif
 +
 +
 +  } else return NULL;
 +
 +  //widget realization
 +  //make container widget 1st, and put the actual widget inside the container
 +  //later, drawing should crop container window if necessary to handle case where xwidget
 +  //is partially obscured by other emacs windows
 +  //other containers than gtk_fixed where explored, but gtk_fixed had the most predictable behaviour so far.
 +  xv->emacswindow = GTK_CONTAINER (FRAME_GTK_WIDGET (s->f));
 +  xv->widgetwindow = GTK_CONTAINER (gtk_fixed_new ()); 
 +  gtk_widget_set_has_window(GTK_WIDGET (  xv->widgetwindow), TRUE);
 +  gtk_container_add (xv->widgetwindow, xv->widget);
 +
 +  //store some xwidget data in the gtk widgets
 +  g_object_set_data (G_OBJECT (xv->widget), XG_FRAME_DATA, (gpointer) (s->f)); //the emacs frame
 +  g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET, (gpointer) (xww)); //the xwidget
 +  g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET_VIEW, (gpointer) (xv)); //the xwidget
 +  g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET, (gpointer) (xww)); //the xwidget window
 +  g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET_VIEW, (gpointer) (xv)); //the xwidget window
 +
 +
 +  gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xww->width, xww->height);
 +  gtk_widget_set_size_request (GTK_WIDGET (xv->widgetwindow), xww->width, xww->height);
 +  gtk_fixed_put (GTK_FIXED (FRAME_GTK_WIDGET (s->f)), GTK_WIDGET (xv->widgetwindow), x, y);
 +  xv->x = x;  xv->y = y;
 +  gtk_widget_show_all (GTK_WIDGET (xv->widgetwindow));
 +
 +  //widgettype specific initialization only possible after realization
 +  if (EQ(xww->type, Qsocket)) {
 +    printf ("xwid:%d socket id:%x %d\n",
 +            xww,
 +            gtk_socket_get_id (GTK_SOCKET (xv->widget)),
 +            gtk_socket_get_id (GTK_SOCKET (xv->widget)));
 +    send_xembed_ready_event (xww,
 +                             gtk_socket_get_id (GTK_SOCKET (xv->widget)));
 +    //gtk_widget_realize(xw->widget);
 +  }
 +  return xv;
 +}
 +
 +
 +void
 +x_draw_xwidget_glyph_string (struct glyph_string *s)
 +{
 +  /*
 +    this method is called by the redisplay engine and places the xwidget on screen.
 +    moving and clipping is done here. also view init.
 +
 +  */
 +  int box_line_hwidth = eabs (s->face->box_line_width);
 +  int box_line_vwidth = max (s->face->box_line_width, 0);
 +  int height = s->height;
 +  struct xwidget *xww = s->xwidget;
 +  struct xwidget_view *xv = xwidget_view_lookup(xww, (s->w));
 +  int clip_right; int clip_bottom; int clip_top; int clip_left;
 +
 +  int x = s->x;
 +  int y = s->y + (s->height / 2) - (xww->height / 2);
 +  int moved=0;
 +
 +  if (xv == NULL || xv->initialized == 0){
 +    /* Views must be initialized once(only once).
 +       We do it here in the display loop because there is no other time to know things like
 +       window placement etc.
 +    */
 +    printf ("xv init for xw %d\n", xww);
 +    xv = xwidget_init_view (xww, s, x, y);
 +  }
 +
 +  //calculate clipping, which is used for all manner of onscreen xwidget views
 +  //each widget border can get clipped by other emacs objects so there are four clipping variables
 +  clip_right = min (xww->width, WINDOW_RIGHT_EDGE_X (s->w) - x - WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH(s->w) - WINDOW_RIGHT_FRINGE_WIDTH(s->w));
 +  clip_left = max (0, WINDOW_LEFT_EDGE_X (s->w) - x + WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH(s->w) + WINDOW_LEFT_FRINGE_WIDTH(s->w));
 +
 +  clip_bottom = min (xww->height, WINDOW_BOTTOM_EDGE_Y (s->w) - WINDOW_MODE_LINE_HEIGHT (s->w) - y);
 +  clip_top = max(0, WINDOW_TOP_EDGE_Y(s->w) -y );
 +
 +  //we are conserned with movement of the onscreen area. the area might sit still when the widget actually moves
 +  //this happens when an emacs window border moves across a widget winow
 +  moved = (xv->x  + xv->clip_left != x+clip_left)
 +    || ((xv->y + xv->clip_top)!= (y+clip_top));
 +  if(moved)    printf ("lxwidget moved: id:%d (%d,%d)->(%d,%d) y+clip_top:%d\n", xww, xv->x, xv->y, x, y, y + clip_top);
 +  xv->x = x;
 +  xv->y = y;
 +  if (moved)  //has it moved?
 +    {
 +      if (!xwidget_hidden(xv))        //hidden equals not being seen during redisplay
 +        {
 +          //TODO should be possible to use xwidget_show_view here
 +          gtk_fixed_move (GTK_FIXED (FRAME_GTK_WIDGET (s->f)),
 +                          GTK_WIDGET (xv->widgetwindow),
 +                          x + clip_left, y + clip_top);
 +        }
 +    }
 +  //clip the widget window if some parts happen to be outside drawable area
 +  //an emacs window is not a gtk window, a gtk window covers the entire frame
 +  //cliping might have changed even if we havent actualy moved, we try figure out when we need to reclip for real
 +  if((xv->clip_right != clip_right)
 +     || (xv->clip_bottom != clip_bottom)
 +     || (xv->clip_top != clip_top)
 +     || (xv->clip_left != clip_left)){
 +    gtk_widget_set_size_request (GTK_WIDGET (xv->widgetwindow),  clip_right + clip_left, clip_bottom + clip_top);
 +    gtk_fixed_move(GTK_FIXED(xv->widgetwindow), xv->widget, -clip_left, -clip_top);
 +    printf("reclip %d %d -> %d %d  clip_top:%d clip_left:%d\n",xv->clip_right, xv->clip_bottom,  clip_right, clip_bottom, clip_top , clip_left);
 +
 +
 +    xv->clip_right = clip_right; xv->clip_bottom = clip_bottom; xv->clip_top = clip_top;xv->clip_left = clip_left;
 +  }
 +  //if emacs wants to repaint the area where the widget lives, queue a redraw
 +  if (!xwidget_hidden(xv)){
 +    gtk_widget_queue_draw (GTK_WIDGET(xv->widgetwindow));
 +    gtk_widget_queue_draw (xv->widget);
 +  }
 +}
 +
 +
 +#ifdef HAVE_WEBKIT_OSR
 +DEFUN ("xwidget-webkit-goto-uri", Fxwidget_webkit_goto_uri,  Sxwidget_webkit_goto_uri, 2, 2, 0,
 +       doc:   /* webkit goto uri.*/
 +       )
 +  (Lisp_Object xwidget, Lisp_Object uri)
 +{
 +  struct xwidget* xw = XXWIDGET(xwidget);
 +  webkit_web_view_load_uri ( WEBKIT_WEB_VIEW(xw->widget_osr), SDATA(uri));
 +  return Qnil;
 +}
 +
 +DEFUN ("xwidget-webkit-execute-script", Fxwidget_webkit_execute_script,  Sxwidget_webkit_execute_script, 2, 2, 0,
 +       doc:   /* webkit exec js.*/
 +       )
 +  (Lisp_Object xwidget, Lisp_Object script)
 +{
 +  struct xwidget* xw = XXWIDGET(xwidget);
 +  webkit_web_view_execute_script( WEBKIT_WEB_VIEW(xw->widget_osr), SDATA(script));
 +  return Qnil;
 +}
 +
 +DEFUN ("xwidget-webkit-get-title", Fxwidget_webkit_get_title,  Sxwidget_webkit_get_title, 1, 1, 0,
 +       doc:   /* webkit get title. can be used to work around exec method lacks return val*/
 +       )
 +  (Lisp_Object xwidget)
 +{
 +  //TODO support multibyte strings
 +  struct xwidget* xw = XXWIDGET(xwidget);
 +  const gchar* str=webkit_web_view_get_title( WEBKIT_WEB_VIEW(xw->widget_osr));
 +  return make_string_from_bytes(str, wcslen((const wchar_t *)str), strlen(str));
 +}
 +
 +#endif
 +
 +
 +
 +
 +
 +DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 3, 3, 0, doc:
 +       /* resize xwidgets*/)
 +  (Lisp_Object xwidget, Lisp_Object new_width, Lisp_Object new_height)
 +{
 +  struct xwidget* xw = XXWIDGET(xwidget);
 +  struct xwidget_view *xv;
 +  int  w, h;
 +
 +  CHECK_NUMBER (new_width);
 +  CHECK_NUMBER (new_height);
 +  w = XFASTINT (new_width);
 +  h = XFASTINT (new_height);
 +
 +
 +  printf("resize xwidget %d (%d,%d)->(%d,%d)",xw, xw->width,xw->height,w,h);
 +  xw->width=w;
 +  xw->height=h;
 +  //if theres a osr resize it 1st
 +  if(xw->widget_osr){
 +    gtk_layout_set_size (GTK_LAYOUT (xw->widgetwindow_osr), xw->width, xw->height);
 +    gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, xw->height);
 +  }
 +
 +  for (int i = 0; i < MAX_XWIDGETS; i++) //TODO MVC refactor lazy linear search
 +    {
 +      xv = &xwidget_views[i];
 +      if(xv->initialized && xv->model == xw){
 +        gtk_layout_set_size (GTK_LAYOUT (xv->widgetwindow), xw->width, xw->height);
 +        gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xw->width, xw->height);
 +      }
 +    }
 +
 +  return Qnil;
 +}
 +
 +DEFUN ("xwidget-size-request", Fxwidget_size_request, Sxwidget_size_request, 1, 1, 0, doc:
 +       /* desired size (TODO crashes if arg not osr widget)*/)
 +  (Lisp_Object xwidget)
 +{
 +  GtkRequisition requisition;
 +  Lisp_Object rv;
 +  gtk_widget_size_request(XXWIDGET(xwidget)->widget_osr, &requisition);
 +  rv = Qnil;
 +  rv = Fcons (make_number(requisition.height), rv);
 +  rv = Fcons (make_number(requisition.width), rv);
 +  return rv;
 +
 +}
 +
 +DEFUN ("xwidgetp", Fxwidgetp, Sxwidgetp, 1, 1, 0,
 +       doc: /* Return t if OBJECT is a xwidget.  */)
 +  (Lisp_Object object)
 +{
 +  return XWIDGETP (object) ? Qt : Qnil;
 +}
 +
 +DEFUN("xwidget-info", Fxwidget_info , Sxwidget_info, 1,1,0, doc: /* get xwidget props */)
 +  (Lisp_Object xwidget)
 +{
 +  Lisp_Object info;
 +  struct xwidget* xw = XXWIDGET(xwidget);
 +
 +  info = Fmake_vector (make_number (4), Qnil);
 +  XSETSYMBOL (XVECTOR (info)->contents[0], xw->type);
 +  XSETSTRING (XVECTOR (info)->contents[1], xw->title);
 +  XSETINT    (XVECTOR (info)->contents[2], xw->width);
 +  XSETINT    (XVECTOR (info)->contents[3], xw->height);
 +
 +
 +  return info;
 +}
 +
 +
 +DEFUN("xwidget-view-info", Fxwidget_view_info , Sxwidget_view_info, 2,2,0, doc: /* get xwidget view props */)
 +  (Lisp_Object xwidget, Lisp_Object window)
 +{
 +  struct xwidget* xw = XXWIDGET(xwidget);
 +  struct xwidget_view* xv = xwidget_view_lookup(xw, XWINDOW(window));
 +
 +  Lisp_Object info;
 +
 +  info = Fmake_vector (make_number (6), Qnil);
 +  XVECTOR (info)->contents[0] = make_number(xv->x);
 +  XVECTOR (info)->contents[1] = make_number(xv->y);
 +  XVECTOR (info)->contents[2] = make_number(xv->clip_right);
 +  XVECTOR (info)->contents[3] = make_number(xv->clip_bottom);
 +  XVECTOR (info)->contents[4] = make_number(xv->clip_top);
 +  XVECTOR (info)->contents[5] = make_number(xv->clip_left);
 +
 +  return info;
 +}
 +
 +DEFUN ("xwidget-send-keyboard-event", Fxwidget_send_keyboard_event, Sxwidget_send_keyboard_event, 2, 2, 0, doc:/* synthesize a kbd event for a xwidget. */
 +       )
 +  (Lisp_Object  xwidget, Lisp_Object keydescriptor)
 +{
 +  //TODO this code crashes and ive tried many different strategies
 +  int keyval = 0x058; //X
 +  char *keystring = "";
 +
 +  struct xwidget *xw = XXWIDGET(xwidget);
 +
 +  GdkEventKey* ev = (GdkEventKey*)gdk_event_new(GDK_KEY_PRESS);
 +  ev->window = gtk_widget_get_window(xw->widget_osr);
 +  ev->keyval = keyval;
 +  ev->time = 0;
 +  GdkDeviceManager* manager = gdk_display_get_device_manager(gdk_window_get_display(ev->window));
 +  gdk_event_set_device (ev,   gdk_device_manager_get_client_pointer(manager));
 +  //gdk_event_put((GdkEvent*)ev);
 +  g_signal_emit_by_name(ev->window,"key-press-event", ev);
 +  ev->type = GDK_KEY_RELEASE;
 +  //gdk_event_put((GdkEvent*)ev);
 +  g_signal_emit_by_name(ev->window,"key-release-event", ev);
 +  //gtk_main_do_event(ev);
 +  //gdk_event_free((GdkEvent*)ev);
 +
 +  return Qnil;
 +}
 +
 +
 +
 +DEFUN("xwidget-delete-zombies", Fxwidget_delete_zombies , Sxwidget_delete_zombies, 0,0,0, doc: /* */)
 +  (void)
 +{
 +  /*
 +    - remove all views with window gone
 +
 +    TODO
 +    - remove all xwidgets with buffer gone
 +    - remove all views with xw gone
 +
 +   */
 +  struct xwidget_view* xv = NULL;
 +  Lisp_Object w;
 +  for (int i = 0; i < MAX_XWIDGETS; i++){
 +      xv =  &xwidget_views[i];
 +      XSETWINDOW(w,  xv->w);
 +      if(xv->initialized && (! (WINDOW_LIVE_P(w)))){
 +
 +        gtk_widget_destroy(GTK_WIDGET(xv->widgetwindow));
 +        xv->initialized = 0;
 +      }
 +  }
 +}
 +
 +DEFUN("xwidget-disable-plugin-for-mime", Fxwidget_disable_plugin_for_mime , Sxwidget_disable_plugin_for_mime, 1,1,0, doc: /* */)
 +  (Lisp_Object mime)
 +{
 +  WebKitWebPlugin *wp = webkit_web_plugin_database_get_plugin_for_mimetype
 +    (webkit_get_web_plugin_database(),  SDATA(mime));
 +  if(wp == NULL) return Qnil;
 +  if(webkit_web_plugin_get_enabled (wp)){
 +    webkit_web_plugin_set_enabled  (wp, FALSE);
 +    return Qt;
 +  }
 +  return Qnil;
 +}
 +
 +void
 +syms_of_xwidget (void)
 +{
 +  int i;
 +
 +  defsubr (&Smake_xwidget);
 +  defsubr (&Sxwidgetp);
 +  defsubr (&Sxwidget_info);
 +  defsubr (&Sxwidget_view_info);
 +  defsubr (&Sxwidget_resize);
 +
 +
 +  defsubr (&Sxwidget_webkit_goto_uri);
 +  defsubr (&Sxwidget_webkit_execute_script);
 +  defsubr (&Sxwidget_webkit_get_title);
 +  defsubr (&Sxwidget_size_request  );
 +  defsubr (&Sxwidget_delete_zombies);
 +  defsubr (&Sxwidget_disable_plugin_for_mime);
 +
 +  defsubr (&Sxwidget_send_keyboard_event);
 +  DEFSYM (Qxwidget ,"xwidget");
 +
 +  DEFSYM (Qcxwidget ,":xwidget");
 +  DEFSYM (Qtitle ,":title");
 +
 +  DEFSYM (Qbutton, "button");
 +  DEFSYM (Qtoggle, "toggle");
 +  DEFSYM (Qslider, "slider");
 +  DEFSYM (Qsocket, "socket");
 +  DEFSYM (Qsocket_osr, "socket-osr");
 +  DEFSYM (Qcairo, "cairo");
 +  DEFSYM (Qwebkit_osr ,"webkit-osr");
 +  DEFSYM (QCplist, ":plist");
 +
 +   DEFVAR_LISP ("xwidget-alist", Vxwidget_alist, doc: /*xwidgets list*/);
 +   Vxwidget_alist = Qnil;
 +   DEFVAR_LISP ("xwidget-view-alist", Vxwidget_view_alist, doc: /*xwidget views list*/);
 +   Vxwidget_alist = Qnil;
 +
 +  Fprovide (intern ("xwidget-internal"), Qnil);
 +
 +  //  for (i = 0; i < MAX_XWIDGETS; i++)
 +  //xwidgets[i].initialized = 0;
 +}
 +
 +
 +/* Value is non-zero if OBJECT is a valid Lisp xwidget specification.  A
 +   valid xwidget specification is a list whose car is the symbol
 +   `xwidget', and whose rest is a property list.  The property list must
 +   contain a value for key `:type'.  That value must be the name of a
 +   supported xwidget type.  The rest of the property list depends on the
 +   xwidget type.  */
 +
 +int
 +valid_xwidget_p (Lisp_Object object)
 +{
 +  int valid_p = 0;
 +
 +  if (XWIDGETP (object))
 +    {
 +      /* Lisp_Object tem; */
 +
 +      /* for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem)) */
 +      /*   if (EQ (XCAR (tem), QCtype)) */
 +      /*     { */
 +      /*       tem = XCDR (tem); */
 +      /*       if (CONSP (tem) && SYMBOLP (XCAR (tem))) */
 +      /*         { */
 +      /*        struct xwidget_type *type; */
 +      /*        type = lookup_xwidget_type (XCAR (tem)); */
 +      /*        if (type) */
 +      /*          valid_p = type->valid_p (object); */
 +      /*         } */
 +
 +      /*       break; */
 +      /*     } */
 +      //never mind type support for now
 +      valid_p = 1;
 +    }
 +
 +  return valid_p;
 +}
 +
 +
 +
 +
 +/* find a value associated with key in spec */
 +Lisp_Object
 +xwidget_spec_value ( Lisp_Object spec, Lisp_Object  key,
 +                     int *found)
 +{
 +  Lisp_Object tail;
 +
 +  xassert (valid_xwidget_p (spec));
 +
 +  for (tail = XCDR (spec);
 +       CONSP (tail) && CONSP (XCDR (tail)); tail = XCDR (XCDR (tail)))
 +    {
 +      if (EQ (XCAR (tail), key))
 +        {
 +          if (found)
 +            *found = 1;
 +          return XCAR (XCDR (tail));
 +        }
 +    }
 +
 +  if (found)
 +    *found = 0;
 +  return Qnil;
 +}
 +
 +
 +void      xwidget_view_delete_all_in_window(  struct window *w )
 +{
 +  struct xwidget_view* xv = NULL;
 +  for (int i = 0; i < MAX_XWIDGETS; i++){
 +      xv =  &xwidget_views[i];
 +      if(xv->initialized && xv->w == w){
 +        gtk_widget_destroy(GTK_WIDGET(xv->widgetwindow));
 +        xv->initialized = 0;
 +      }
 +  }
 +}
 +
 +
 +
 +struct xwidget_view* xwidget_view_lookup(struct xwidget* xw,     struct window *w){
 +  struct xwidget_view* xv = NULL;
 +  for (int i = 0; i < MAX_XWIDGETS; i++){
 +    xv = &xwidget_views[i];
 +    if (xv->initialized && (xv->model == xw) && (xv->w == w))
 +      return xv;
 +  }
 +}
 +
 +//attempting a workaround for a webkit offscreen bug
 +//TODO verify its still needed
 +void                gtk_window_get_position             (GtkWindow *window,
 +                                                         gint *root_x,
 +                                                         gint *root_y){
 +  printf("my getsize\n");
 +  *root_x = 0;
 +  *root_y = 0;
 +}
 +
 +
 +
 +struct xwidget*
 +lookup_xwidget (Lisp_Object  spec)
 +{
 +  /* When a xwidget lisp spec is found initialize the C struct that is used in the C code.
 +     This is done by redisplay so values change if the spec changes.
 +     So, take special care of one-shot events
 +
 +     TODO remove xwidget init from display spec. simply store an xwidget reference only and set
 +     size etc when creating the xwidget, which should happen before insertion into buffer
 +  */
 +  int found = 0, found1 = 0, found2 = 0;
 +  Lisp_Object value;
 +  struct xwidget *xw;
 +
 +  value = xwidget_spec_value (spec, Qcxwidget, &found1);
 +  xw = XXWIDGET(value);
 +
 +  /* value = xwidget_spec_value (spec, QCtype, &found); */
 +  /* xw->type = SYMBOLP (value) ? value : Qbutton;    //default to button */
 +  /* value = xwidget_spec_value (spec, Qtitle, &found2); */
 +  /* xw->title = STRINGP (value) ? (char *) SDATA (value) : "?";      //funky cast FIXME TODO */
 +
 +  /* value = xwidget_spec_value (spec, QCheight, NULL); */
 +  /* xw->height = INTEGERP (value) ? XFASTINT (value) : 50;  */
 +  /* value = xwidget_spec_value (spec, QCwidth, NULL); */
 +  /* xw->width = INTEGERP (value) ? XFASTINT (value) : 50; */
 +
 +  /* value = xwidget_spec_value (spec, QCplist, NULL); */
 +  /* xw->plist = value; */
 +  printf ("xwidget_id:%d type:%d found:%d %d %d title:%s (%d,%d)\n", xw,
 +          xw->type, found, found1, found2, xw->title, xw->height, xw->width);
 +
 +  //assert_valid_xwidget_id (id, "lookup_xwidget");
 +  return xw;
 +}
 +
 +/*set up detection of touched xwidget*/
 +void
 +xwidget_start_redisplay (void)
 +{
 +  int i;
 +  for (i = 0; i < MAX_XWIDGETS; i++)
 +    xwidget_views[i].redisplayed = 0;
 +
 +}
 +
 +/* the xwidget was touched during redisplay, so it isnt a candidate for hiding*/
 +void
 +xwidget_touch (struct xwidget_view *xv)
 +{
 +  xv->redisplayed = 1;
 +}
 +
 +int
 +xwidget_touched (struct xwidget_view *xv)
 +{
 +  return  xv->redisplayed;
 +}
 +
 +/* redisplay has ended, now we should hide untouched xwidgets
 +*/
 +void
 +xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix)
 +{
 +
 +  int i;
 +  struct xwidget *xw;
 +  int area;
 +
 +
 +  xwidget_start_redisplay ();
 +  //iterate desired glyph matrix of window here, hide gtk widgets
 +  //not in the desired matrix.
 +
 +  //this only takes care of xwidgets in active windows.
 +  //if a window goes away from screen xwidget views wust be deleted
 +  
 +  //  dump_glyph_matrix(matrix, 2);
 +  for (i = 0; i < matrix->nrows; ++i)
 +    {
 +      //    dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
 +      struct glyph_row *row;
 +      row = MATRIX_ROW (matrix, i);
 +      if (row->enabled_p != 0)
 +        {
 +          for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
 +            {
 +              struct glyph *glyph = row->glyphs[area];
 +              struct glyph *glyph_end = glyph + row->used[area];
 +              for (; glyph < glyph_end; ++glyph)
 +                {
 +                  if (glyph->type == XWIDGET_GLYPH)
 +                    {
 +                      /*
 +                        the only call to xwidget_end_redisplay is in dispnew
 +                        xwidget_end_redisplay(w->current_matrix);
 +                      */
 +                      xwidget_touch (xwidget_view_lookup(glyph->u.xwidget,
 +                                                         w));
 +                    }
 +                }
 +            }
 +        }
 +    }
 +
 +  for (i = 0; i < MAX_XWIDGETS; i++)
 +    {
 +      struct xwidget_view* xv = &xwidget_views[i];
 +
 +      //"touched" is only meaningful for the current window, so disregard other views
 +      if (xv->initialized && ( xv->w ==    w))
 +        {
 +          if (xwidget_touched(xv))
 +            xwidget_show_view (xv);
 +          else
 +            xwidget_hide_view (xv);
 +        }
 +    }
 +}