1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-02-08 16:52:40 -08:00

minor cleanups and doc

This commit is contained in:
Joakim Verona 2011-07-10 23:47:48 +02:00
parent d812bba65d
commit e098c552cc
4 changed files with 400 additions and 33 deletions

View file

@ -198,13 +198,62 @@ stuff that needs to work:
- lookup xw-view for xwidget in emacs window(during redisplay)
(- do something for all siblings of a xw-view. not atm)
*** TODO xwidget creation interface
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.
** 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.
** TODO look into more ways of displaying xwidgets, like binding them to a
** 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
@ -212,6 +261,9 @@ 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]
@ -298,10 +350,9 @@ make
** TODO mvc code crashes after a while
seemingly only when compiling with optimizations
seemingly only when compiling with optimizations.
I have no idea why.
** TODO delete xwidgets belonging to an emacs window
when it closes
** TODO xwidget-resize-at
currently it rewrites the display spec. then it resizes the xwidget
views. maybe rewriting the spec should be sufficient, and changes to
@ -349,7 +400,7 @@ webkitViewportAttributesRecompute is the offender.
maybe try gtk3 variants?
export CFLAGS="`pkg-config --cflags webkitgtk-3.0 ` -DHAVE_WEBKIT_OSR -g"
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
@ -420,6 +471,8 @@ 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 ()
@ -448,12 +501,32 @@ or this funny hack:
<jave> lucian: that was a pretty cool idea!
**** webkit_web_view_load_string ()
*** webkit_web_view_load_string ()
I would like preview of html in a buffer rather than from uri.
** TODO clipping of controllers
*** TODO simple xwidget-webkit wrapper
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.
** 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
@ -478,6 +551,7 @@ 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]
@ -555,7 +629,8 @@ the needed data is private to the base class. to overcome this:
JanD pointed out the GTK3 port already has its own subclass, so I
modified that one.
*** TODO clip top
*** 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
@ -569,9 +644,20 @@ makes it harder to use the allocation workarounds.
see:
- gtk_widget_set_size_request
- gtkscrolledwindow
** TODO use FRAME_GTK_WIDGET (f)
rather than gwfixed
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,
** TODO 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.
*** TODO use FRAME_GTK_WIDGET (f)
rather than gwfixed.
*** TODO support configure
** DONE translate clicks
CLOSED: [2011-07-03 Sun 22:12]
on onscreen webkit peer to offscreen
@ -584,18 +670,21 @@ 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 control be used in place of my own copy hacks?
maybe control 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.
** TODO remove xwidget_views when emacs window is deleted
** 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
** notes from x_draw_xwidget_glyph_string

View file

@ -0,0 +1,32 @@
;;(require 'screencast)
(require 'xwidget)
(defconst xwidget-screencast-webkit '("Hello, and welcome to a
short demo of the Emacs xwidget branch, and the Webkit
integration it provides." n
"Xwidgets are toolkit widgets that behave like images in an
Emacs buffer. Except they are actual widgets, so you can
interact with them." n
"There are several, but people seem to fancy the webkit the most so lets have a look!"
(insert "some text")
(xwidget-insert (point-min) 'webkit-osr "webkit-osr" 500 1000 5)
n
"Okay so thats an actual webkit instance in an Emacs buffer! " n
"Mouse-overs work" n
"Mouse-clicks work" n
(split-window-vertically)
"You can split the buffer and scroll the windows separately, as
usual in Emacs. This is however not so usual in the browser
world for some reason." n
"So, can you use the xwidget branch as your main Emacs instance?"n
"Not yet, its still not mature. There are many tricky issues
left. That being said, there are many simple tasks to help out
with also if you like!" ))
(defun xwidget-screencast(&optional arg)
"Displays the screencast for xwidgets."
(interactive "P")
(apply (if arg
'screencast-record
'screencast)
xwidget-screencast-webkit "xvidgets" 1 ()))

229
src/xwidget-attic.c Normal file
View file

@ -0,0 +1,229 @@
static int once = 0;
int
xwidget_has_composition(void){ //unused
int event_base, error_base;
Display* dpy = GDK_DISPLAY ();
int i;
if(xwidget_query_composition_called)
return hasNamePixmap;
xwidget_query_composition_called = 1;
//do this once in an emacs session
if(gdk_display_supports_composite(gdk_display_get_default ())){
hasNamePixmap = 1;
}else{
return 0;
}
return 1;
}
void
xwidget_end_composition(struct xwidget* w){ //unused
//XCompositeUnredirectWindow(); stop redirecting, should be called when the socket is destroyed
}
static gboolean
xwidget_composite_draw_phantom(struct xwidget* xw,
int x, int y,
int clipx, int clipy)
{
FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (xw->widget), XG_FRAME_DATA);
////////////////////////////////////////////////////////////////
//Example 7. Composited windows
GdkRegion *region;
GtkWidget *child;
cairo_t *cr;
printf("xwidget_composite_draw_2 at:%d %d\n", x,y);
/* get our child (in this case, the event box) */
child = xw->widget; //gtk_bin_get_child (GTK_BIN (widget));
/* create a cairo context to draw to the emacs window */
// cr = gdk_cairo_create (gtk_widget_get_window (f->gwfixed));//GTK_WIDGET(xw->emacswindow));//xw->widgetwindow));//widget->window);
cr = gdk_cairo_create (gtk_widget_get_window (f->gwfixed));//GTK_WIDGET(xw->emacswindow));//));//widget->window);
/* the source data is the (composited) xwidget */
//cairo_move_to(cr, xw->x, xw->y);
cairo_rectangle(cr, x,y, clipx, clipy);
cairo_clip(cr);
cairo_set_source_rgb(cr,1.0,0,0);
cairo_rectangle(cr,x,y,xw->width,xw->height);
cairo_fill(cr);
gdk_cairo_set_source_pixmap (cr, child->window,
x,//child->allocation.x,
y//child->allocation.y
);
/* draw no more than our expose event intersects our child */
/* region = gdk_region_rectangle (&child->allocation);
gdk_region_intersect (region, event->region);
gdk_cairo_region (cr, region);
cairo_clip (cr); */
/* composite, with a 50% opacity */
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
//cairo_paint_with_alpha (cr, phantom ? 0.5 : 0);
cairo_paint_with_alpha (cr, 0.9);
//cairo_paint(cr);//transparency);
/* we're done */
cairo_destroy (cr);
return FALSE;
}
/*
static gboolean
xwidget_composite_draw(GtkWidget *widget,
GdkEventExpose *event,
gpointer data)
{
struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
printf("xwidget_composite_draw %s\n", data);
xwidget_composite_draw_2(widget,
event,
data,
xw->x, xw->y, 0);
return FALSE;
}
*/
static gboolean
xwidget_composite_draw_widgetwindow(GtkWidget *widget,
GdkEventExpose *event,
gpointer data)
{
struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
cairo_t *cr;
GdkPixmap *pixmap;
pixmap=xw->widget->window;
printf("xwidget_composite_draw_widgetwindow xw.id:%d xw.type:%d window:%d\n", xw->id,xw->type, gtk_widget_get_window (widget));
//if(xw->type!=3)//TODO this is just trial and terror to see if i can draw the live socket anywhere at all
cr = gdk_cairo_create (gtk_widget_get_window (widget));//GTK_LAYOUT (xw->widgetwindow)->bin_window);//
//else cr = gdk_cairo_create (gtk_widget_get_window (xw->emacswindow));
cairo_rectangle(cr, 0,0, xw->width, xw->height);
cairo_clip(cr);
cairo_set_source_rgb(cr,0,1.0,0);
cairo_rectangle(cr, 0,0, xw->width, xw->height);
cairo_fill(cr);
gdk_cairo_set_source_pixmap (cr, pixmap,
0,0);
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
cairo_paint_with_alpha (cr, 0.9);
//cairo_paint(cr);
cairo_destroy (cr);
return FALSE;
}
//type support nevermind for now
/* /\* List of supported image types. Use define_image_type to add new */
/* types. Use lookup_image_type to find a type for a given symbol. *\/ */
/* static struct wxidget_type *wxidget_types; */
/* /\* Look up xwidget type SYMBOL, and return a pointer to its xwidget_type */
/* structure. Value is null if SYMBOL is not a known image type. *\/ */
/* static INLINE struct xwidget_type *lookup_xwidget_type (Lisp_Object symbol) */
/* { */
/* struct xwidget_type *type; */
/* for (type = xwidget_types; type; type = type->next) */
/* if (EQ (symbol, *type->type)) */
/* break; */
/* return type; */
/* } */
////////////////////////////////////////////////////////////////
/* delete the xwidget and its native widget peer(unused) */
void xwidget_delete(struct xwidget* xw);
void
xwidget_delete (struct xwidget *xw)
{
printf ("xwidget %d deleted\n", xw->id);
xw->initialized = 0;
gtk_widget_destroy (xw->widget);
}
/* redraw all xwidgets(unused) */
void
xwidget_invalidate (void)
{
int i;
struct xwidget *xw;
printf ("invalidate ");
for (i = 0; i < MAX_XWIDGETS; i++)
{
xw = &xwidgets[i];
if (xw->initialized)
{
printf ("%d,", i);
gtk_widget_queue_draw_area (xw->widget, 0, 0, xw->width,
xw->height);
}
}
printf ("\n");
}
/* initializes the xwidget model */
void
xwidget_init_model (struct xwidget *xw,
struct glyph_string *s,
int x, int y)
{
xw->id = s->xwidget_id;
xw->initialized = 1;
}
DEFUN ("xwidget-replug", Fxwidget_replug, Sxwidget_replug, 2, 2, 0,
doc: /* unplug from socket1 plug into socket2.*/
)
(Lisp_Object old_parent, Lisp_Object new_parent)
{
struct xwidget *xw1;
struct xwidget *xw2;
GtkWidget* widget;
CHECK_NUMBER (old_parent);
CHECK_NUMBER (new_parent);
xw1 = &xwidgets[XFASTINT (old_parent)];
xw2 = &xwidgets[XFASTINT (new_parent)];
///this wasnt thought through. we need the views rather than the model.
//so we need to map xw+w to xv
widget = xw1->widget->gtk_socket_get_plug_window ();
//the plug...
gtk_widget_ref(widget);//...gets an xtra ref to prevent garb, then it ...
gtk_container_remove(GTK_CONTAINER(xw1->widget), widget);//...is uplugged from old socket and...
gtk_container_add(GTK_CONTAINER(xw2->widget), widget);//...replugged in new socket...
gtk_widget_unref(widget);//...and lastly remove the ref
return Qnil;
}

View file

@ -90,8 +90,11 @@
#endif
#include <wchar.h>
#ifdef HAVE_WEBKIT
#include <webkitgtk.h>
#endif
@ -412,15 +415,10 @@ xwidget_osr_button_callback ( GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
{
gdouble x, y;
struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
GdkEventButton* eventcopy = gdk_event_copy(event);
x = ((GdkEventButton*)event)->x;
y = ((GdkEventButton*)event)->y;
printf ("button callback %d %d\n",x,y);
GdkEvent* eventcopy = gdk_event_copy(event);
eventcopy->window = gtk_widget_get_window(xw->widget_osr);
((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
}
@ -620,7 +618,7 @@ 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 clpping
moving and clipping is done here. also view init.
*/
int box_line_hwidth = eabs (s->face->box_line_width);
@ -676,7 +674,7 @@ x_draw_xwidget_glyph_string (struct glyph_string *s)
|| (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_put(GTK_FIXED(xv->widgetwindow), xv->widget, -clip_left, -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);
@ -684,7 +682,7 @@ x_draw_xwidget_glyph_string (struct glyph_string *s)
}
//if emacs wants to repaint the area where the widget lives, queue a redraw
if (!xwidget_hidden(xv)){
gtk_widget_queue_draw (xv->widgetwindow);
gtk_widget_queue_draw (GTK_WIDGET(xv->widgetwindow));
gtk_widget_queue_draw (xv->widget);
}
}
@ -730,7 +728,7 @@ DEFUN ("xwidget-webkit-get-title", Fxwidget_webkit_get_title, Sxwidget_webkit_g
{
//TODO support multibyte strings
const gchar* str=webkit_web_view_get_title( WEBKIT_WEB_VIEW(xid2xw(xwidget_id)->widget_osr));
return make_string_from_bytes(str, wcslen(str), strlen(str));
return make_string_from_bytes(str, wcslen((const wchar_t *)str), strlen(str));
}
@ -798,18 +796,37 @@ DEFUN("xwidget-info", Fxwidget_info , Sxwidget_info, 1,1,0, doc: /* get xwidget
struct xwidget *xw = xid2xw(xwidget_id);
Lisp_Object info;
info = Fmake_vector (make_number (7), Qnil);
info = Fmake_vector (make_number (4), Qnil);
XVECTOR (info)->contents[0] = make_number(xw->id);
XVECTOR (info)->contents[1] = make_number(xw->type);
XVECTOR (info)->contents[2] = Qnil; //make_number(xw->x);
XVECTOR (info)->contents[3] = Qnil;//make_number(xw->y);
XVECTOR (info)->contents[4] = make_number(xw->width);
XVECTOR (info)->contents[5] = make_number(xw->height);
XVECTOR (info)->contents[6] = Qnil;//make_number(xw->hidden);
XVECTOR (info)->contents[1] = xw->type;
XVECTOR (info)->contents[2] = make_number(xw->width);
XVECTOR (info)->contents[3] = make_number(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_id, Lisp_Object window)
{
struct xwidget *xw = xid2xw(xwidget_id);
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;
}
//xterm.c listens to xwidget_owns_kbd and tries to not eat events when its set
int xwidget_owns_kbd = 0;
DEFUN ("xwidget-set-keyboard-grab", Fxwidget_set_keyboard_grab, Sxwidget_set_keyboard_grab, 2, 2, 0, doc: /* set unset kbd grab for xwidget. */
@ -938,6 +955,7 @@ syms_of_xwidget (void)
defsubr (&Sxwidget_send_keyboard_event);
defsubr (&Sxwidget_embed_steal_window);
defsubr (&Sxwidget_info);
defsubr (&Sxwidget_view_info);
defsubr (&Sxwidget_resize_internal);
defsubr (&Sxwidget_embed_steal_window);
@ -1050,12 +1068,11 @@ xwidget_from_id (int id)
void xwidget_view_delete_all_in_window( struct window *w )
{
//xxx
struct xwidget_view* xv = NULL;
for (int i = 0; i < MAX_XWIDGETS; i++){
xv = &xwidget_views[i];
if(xv->w == w){
gtk_widget_destroy(xv->widgetwindow);
gtk_widget_destroy(GTK_WIDGET(xv->widgetwindow));
}
}
}