some keyboard event code but it still crashes and now im more fed up
[emacs.git] / src / xwidget.c
blob6bcf49ebd38146c49ffc2ddc319bf6caafde71a8
1 #include <config.h>
3 #include <signal.h>
5 #include <stdio.h>
6 #include <setjmp.h>
7 #ifdef HAVE_X_WINDOWS
9 #include "lisp.h"
10 #include "blockinput.h"
11 #include "syssignal.h"
13 #include "xterm.h"
14 #include <X11/cursorfont.h>
16 #ifndef makedev
17 #include <sys/types.h>
18 #endif /* makedev */
20 #ifdef BSD_SYSTEM
21 #include <sys/ioctl.h>
22 #endif /* ! defined (BSD_SYSTEM) */
24 #include "systime.h"
26 #ifndef INCLUDED_FCNTL
27 #include <fcntl.h>
28 #endif
29 #include <ctype.h>
30 #include <errno.h>
31 #include <setjmp.h>
32 #include <sys/stat.h>
34 #include "charset.h"
35 #include "character.h"
36 #include "coding.h"
37 #include "ccl.h"
38 #include "frame.h"
39 #include "dispextern.h"
40 #include "fontset.h"
41 #include "termhooks.h"
42 #include "termopts.h"
43 #include "termchar.h"
44 #include "emacs-icon.h"
45 #include "disptab.h"
46 #include "buffer.h"
47 #include "window.h"
48 #include "keyboard.h"
49 #include "intervals.h"
50 #include "process.h"
51 #include "atimer.h"
52 #include "keymap.h"
55 #ifdef USE_X_TOOLKIT
56 #include <X11/Shell.h>
57 #endif
58 #include <X11/extensions/Xcomposite.h>
59 #include <X11/extensions/Xrender.h>
60 #include <cairo.h>
61 #ifdef HAVE_SYS_TIME_H
62 #include <sys/time.h>
63 #endif
64 #ifdef HAVE_UNISTD_H
65 #include <unistd.h>
66 #endif
68 #include "gtkutil.h"
69 #include "font.h"
70 #endif
72 #include <gtk/gtk.h>
73 #include <gdk/gdk.h>
75 #ifdef HAVE_GTK3
76 //for gtk3; sockets and plugs
77 #include <gtk/gtkx.h>
78 #include "emacsgtkfixed.h"
79 #endif
81 #include <librsvg/rsvg.h>
83 #ifdef HAVE_GOOCANVAS
84 #include <goocanvas.h>
85 #endif
87 #ifdef HAVE_CLUTTER
88 #include <clutter/clutter.h>
89 #include <clutter-gtk/clutter-gtk.h>
90 #endif
92 #include <wchar.h>
94 #ifdef HAVE_WEBKIT_OSR
95 #include <webkit/webkitwebview.h>
96 #include <webkit/webkitwebplugindatabase.h>
97 #include <webkit/webkitwebplugin.h>
98 #include <webkit/webkitglobals.h>
99 #endif
101 #include "xwidget.h"
103 //TODO should of course not be a hardcoded array but I can't be bothered atm
104 //just a fixed array of xwidgets for now
105 //would need to be hashtables or something
107 #define MAX_XWIDGETS 100
108 struct xwidget_view xwidget_views[MAX_XWIDGETS];
110 //TODO embryo of lisp allocators for xwidgets
111 //TODO xwidget* should be Lisp_xwidget*
112 struct xwidget*
113 allocate_xwidget (void)
115 return ALLOCATE_PSEUDOVECTOR (struct xwidget, height, PVEC_XWIDGET);
118 //TODO xwidget_view* should be Lisp_xwidget_view*
119 struct xwidget_view*
120 allocate_xwidget_view (void)
122 return ALLOCATE_PSEUDOVECTOR (struct xwidget_view, redisplayed, PVEC_XWIDGET_VIEW);
126 Lisp_Object Qxwidget;
127 Lisp_Object Qcxwidget;
128 Lisp_Object Qtitle;
129 Lisp_Object Qxwidget_set_keyboard_grab;
130 Lisp_Object Qxwidget_embed_steal_window;
131 Lisp_Object Qxwidget_info;
132 Lisp_Object Qxwidget_resize;
133 Lisp_Object Qxwidget_send_keyboard_event;
135 Lisp_Object Qbutton, Qtoggle, Qslider, Qsocket, Qsocket_osr, Qcairo,
136 Qwebkit_osr, QCplist;
139 extern Lisp_Object QCtype;
140 extern Lisp_Object QCwidth, QCheight;
142 struct xwidget_view* xwidget_view_lookup(struct xwidget* xw, struct window *w);
143 Lisp_Object xwidget_spec_value ( Lisp_Object spec, Lisp_Object key, int *found);
144 gboolean webkit_osr_damage_event_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data) ;
145 gboolean webkit_osr_key_event_callback (GtkWidget *widget, GdkEventKey *event, gpointer data) ;
146 void webkit_osr_document_load_finished_callback (WebKitWebView *webkitwebview,
147 WebKitWebFrame *arg1,
148 gpointer user_data);
150 DEFUN ("make-xwidget", Fmake_xwidget, Smake_xwidget, 7, 7, 0,
151 doc: /* xw */
153 (Lisp_Object beg, Lisp_Object end,
154 Lisp_Object type,
155 Lisp_Object title,
156 Lisp_Object width, Lisp_Object height,
157 Lisp_Object data)
159 //should work a bit like "make-button"(make-button BEG END &rest PROPERTIES)
160 // arg "type" and fwd should be keyword args eventually
161 //(make-xwidget 3 3 'button "oei" 31 31 nil)
162 //(xwidget-info (car xwidget-alist))
163 struct xwidget* xw = allocate_xwidget();
164 Lisp_Object val;
165 struct gcpro gcpro1;
166 GCPRO1(xw);
167 XSETSYMBOL(xw->type, type);
168 XSETSTRING(xw->title, title);
169 //TODO buffer should be an optional argument not just assumed to be the current buffer
170 XSETBUFFER(xw->buffer, Fcurrent_buffer()); // conservatively gcpro xw since we call lisp
171 xw->height = XFASTINT(height);
172 xw->width = XFASTINT(width);
173 XSETPSEUDOVECTOR (val, xw, PVEC_XWIDGET); //?? dunno why i need this
174 Vxwidget_alist = Fcons ( val, Vxwidget_alist);
175 xw->widgetwindow_osr = NULL;
176 xw->widget_osr = NULL;
177 xw->plist = Qnil;
180 #ifdef HAVE_WEBKIT_OSR
181 /* DIY mvc. widget is rendered offscreen,
182 later bitmap copied to the views.
184 if (EQ(xw->type, Qwebkit_osr)){
185 printf("init webkit osr\n");
186 BLOCK_INPUT;
187 xw->widgetwindow_osr = GTK_CONTAINER (gtk_offscreen_window_new ());
188 gtk_window_resize( GTK_WINDOW(xw->widgetwindow_osr), xw->width, xw->height);
189 xw->widget_osr = webkit_web_view_new();
191 gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, xw->height);
192 gtk_container_add (xw->widgetwindow_osr, xw->widget_osr);
194 gtk_widget_show_all (GTK_WIDGET (xw->widgetwindow_osr));
196 /* store some xwidget data in the gtk widgets for convenient retrieval in the event handlers. */
197 g_object_set_data (G_OBJECT (xw->widget_osr), XG_XWIDGET, (gpointer) (xw));
198 g_object_set_data (G_OBJECT (xw->widgetwindow_osr), XG_XWIDGET, (gpointer) (xw));
199 /* signals */
200 g_signal_connect (G_OBJECT ( xw->widgetwindow_osr), "damage-event", G_CALLBACK (webkit_osr_damage_event_callback), NULL);
202 g_signal_connect (G_OBJECT ( xw->widget_osr), "key-press-event", G_CALLBACK (webkit_osr_key_event_callback), NULL);
203 g_signal_connect (G_OBJECT ( xw->widget_osr), "key-release-event", G_CALLBACK (webkit_osr_key_event_callback), NULL);
205 g_signal_connect (G_OBJECT ( xw->widget_osr),
206 "document-load-finished",
207 G_CALLBACK (webkit_osr_document_load_finished_callback),
208 xw);
210 webkit_web_view_load_uri(WEBKIT_WEB_VIEW(xw->widget_osr), "http://www.fsf.org");
211 UNBLOCK_INPUT;
214 #endif
215 if (EQ(xw->type, Qsocket_osr)){
216 printf("init socket osr\n");
217 BLOCK_INPUT;
218 xw->widgetwindow_osr = GTK_CONTAINER (gtk_offscreen_window_new ());
219 gtk_window_resize( GTK_WINDOW(xw->widgetwindow_osr), xw->width, xw->height);
221 ////////////////////
222 //xw->widget_osr = webkit_web_view_new();
223 xw->widget_osr = gtk_socket_new();
224 //g_signal_connect_after(xv->widget, "plug-added", G_CALLBACK(xwidget_plug_added), "plug added");
225 //g_signal_connect_after(xv->widget, "plug-removed", G_CALLBACK(xwidget_plug_removed), "plug removed");
226 ///////////////////
228 gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, xw->height);
229 gtk_container_add (xw->widgetwindow_osr, xw->widget_osr);
231 gtk_widget_show_all (GTK_WIDGET (xw->widgetwindow_osr));
233 /* store some xwidget data in the gtk widgets for convenient retrieval in the event handlers. */
234 g_object_set_data (G_OBJECT (xw->widget_osr), XG_XWIDGET, (gpointer) (xw));
235 g_object_set_data (G_OBJECT (xw->widgetwindow_osr), XG_XWIDGET, (gpointer) (xw));
236 g_signal_connect (G_OBJECT ( xw->widgetwindow_osr), "damage-event", G_CALLBACK (webkit_osr_damage_event_callback), NULL);
238 //webkit_web_view_load_uri(WEBKIT_WEB_VIEW(xw->widget_osr), "http://www.fsf.org");
239 UNBLOCK_INPUT;
243 UNGCPRO;
244 return val;
248 xwidget_hidden(struct xwidget_view *xv)
250 return xv->hidden;
254 static void
255 buttonclick_handler (GtkWidget * widget, gpointer data)
257 struct xwidget *xw = (struct xwidget *) data;
258 struct input_event event;
259 Lisp_Object frame;
260 FRAME_PTR f = NULL;//(FRAME_PTR) g_object_get_data (G_OBJECT (xw->widget), XG_FRAME_DATA); //TODO
261 printf ("button clicked xw:%d '%s'\n", xw, xw->title);
263 EVENT_INIT (event);
264 event.kind = XWIDGET_EVENT;
266 XSETFRAME (frame, f);
268 event.frame_or_window = Qnil; //frame; //how to get the frame here?
271 event.arg = Qnil;
272 event.arg = Fcons (xw, event.arg); //TODO send the actual xwidget object now instead
273 event.arg = Fcons (intern ("buttonclick"), event.arg);
275 kbd_buffer_store_event (&event);
281 static void
282 send_xembed_ready_event (struct xwidget* xw, int xembedid)
284 struct input_event event;
285 EVENT_INIT (event);
286 event.kind = XWIDGET_EVENT;
287 event.frame_or_window = Qnil; //frame; //how to get the frame here? //TODO i store it in the xwidget now
289 event.arg = Qnil;
290 event.arg = Fcons (make_number (xembedid), event.arg);
291 event.arg = Fcons (intern ("xembed-ready"), event.arg);
292 event.arg = Fcons (xw, event.arg); //TODO
295 kbd_buffer_store_event (&event);
299 void
300 xwidget_show_view (struct xwidget_view *xv)
302 xv->hidden = 0;
303 gtk_widget_show(GTK_WIDGET(xv->widgetwindow));
304 gtk_fixed_move (GTK_FIXED (xv->emacswindow), GTK_WIDGET (xv->widgetwindow), xv->x + xv->clip_left, xv->y + xv->clip_top); //TODO refactor
308 /* hide an xvidget view */
309 void
310 xwidget_hide_view (struct xwidget_view *xv)
312 xv->hidden = 1;
313 //gtk_widget_hide(GTK_WIDGET(xw->widgetwindow));
314 gtk_fixed_move (GTK_FIXED (xv->emacswindow), GTK_WIDGET (xv->widgetwindow),
315 10000, 10000);
319 void xwidget_plug_added(GtkSocket *socket,
320 gpointer user_data)
322 //hmm this doesnt seem to get called for foreign windows
323 printf("xwidget_plug_added\n");
326 gboolean xwidget_plug_removed(GtkSocket *socket,
327 gpointer user_data)
329 printf("xwidget_plug_removed\n");
330 return TRUE; /* dont run the default handler because that kills the socket and we want to reuse it*/
334 void xwidget_slider_changed (GtkRange *range,
335 gpointer user_data)
337 //slider value changed. change value of siblings
338 //correspondingly. but remember that changing value will again
339 //trigger signal
341 //TODO MVC view storage wont be an array futureish so the loop needs to change eventually
342 //TODO MVC it would be nice if this code could be reusable but, alas, C is not a functional language
343 //issues are:
344 // - the type of the controllers value (double, boolean etc)
345 // - the getter and setter (but they can be func pointers)
346 // a behemoth macro is always an option.
347 double v=gtk_range_get_value(range);
348 struct xwidget_view* xvp = g_object_get_data (G_OBJECT (range), XG_XWIDGET_VIEW);
349 struct xwidget_view* xv;
351 printf("slider changed val:%f\n", v);
354 //block sibling views signal handlers
355 for (int i = 0; i < MAX_XWIDGETS; i++)
357 xv = &xwidget_views[i];
358 if(xv->initialized && xvp->model == xv->model){
359 g_signal_handler_block( xv->widget,xv->handler_id);
362 //set values of sibling views and unblock
363 for (int i = 0; i < MAX_XWIDGETS; i++)
365 xv = &xwidget_views[i];
366 if(xv->initialized && xvp->model == xv->model){
367 gtk_range_set_value(GTK_RANGE(xv->widget), v);
368 g_signal_handler_unblock( xv->widget,xv->handler_id);
375 /* when the off-screen webkit master view changes this signal is called.
376 it copies the bitmap from the off-screen webkit instance */
377 gboolean webkit_osr_damage_event_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data)
379 //TODO this is wrong! should just oueu a redraw of onscreen widget
380 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
381 struct xwidget_view* xv;
382 //webkit_osr_redraw_child(xw, widget);
383 printf ("damage\n");
384 for (int i = 0; i < MAX_XWIDGETS; i++)//todo mvc refactor
386 xv = &xwidget_views[i];
387 if(xv->initialized && xv->model == xw){
388 gtk_widget_queue_draw (xv->widget); //redraw all views, the master has changed
392 return FALSE;
397 gboolean webkit_osr_key_event_callback (GtkWidget *widget, GdkEventKey *event, gpointer data)
399 printf("terminating a webkit osr keypress\n");
400 //TRUE terminate the event here. no paren handlers will be called. but webkit then doesng get the event and it still crashes
401 //FALSE paren handlers will be called. webkit then gets the event and it still crashes
402 return TRUE;
406 void webkit_osr_document_load_finished_callback (WebKitWebView *webkitwebview,
407 WebKitWebFrame *arg1,
408 gpointer data)
410 //TODO this event sending code should be refactored
411 struct input_event event;
412 // struct xwidget *xw = (struct xwidget *) data;
413 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (webkitwebview), XG_XWIDGET);
414 printf("webkit finished loading\n");
416 EVENT_INIT (event);
417 event.kind = XWIDGET_EVENT;
418 event.frame_or_window = Qnil; //frame; //how to get the frame here? //TODO i store it in the xwidget now
420 event.arg = Qnil;
421 event.arg = Fcons (xw, event.arg); //TODO
422 event.arg = Fcons (intern ("document-load-finished"), event.arg);
425 kbd_buffer_store_event (&event);
429 //for gtk3 webkit_osr
430 gboolean
431 xwidget_osr_draw_callback (GtkWidget *widget, cairo_t *cr, gpointer data)
433 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
434 struct xwidget_view* xv = (struct xwidget_view*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET_VIEW);
436 // printf("xwidget_osr_draw_callback gtk3 xw.id:%d xw.type:%d window:%d vis:%d\n",
437 // xw,xw->type, gtk_widget_get_window (widget), gtk_widget_get_visible (xw->widget_osr));
439 cairo_rectangle(cr, 0,0, xv->clip_right, xv->clip_bottom);//xw->width, xw->height);
440 cairo_clip(cr);
442 gtk_widget_draw (xw->widget_osr, cr);
445 return FALSE;
449 gboolean
450 xwidget_osr_button_callback ( GtkWidget *widget,
451 GdkEvent *event,
452 gpointer user_data)
454 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
455 GdkEvent* eventcopy = gdk_event_copy(event);
457 ((GdkEventButton*)eventcopy)->window = gtk_widget_get_window(xw->widget_osr);
458 gtk_main_do_event(eventcopy); //TODO this will leak events. they should be deallocated later
459 return TRUE; //dont propagate this event furter
462 int xwidget_view_index=0;
464 /* initializes and does initial placement of an xwidget view on screen */
465 struct xwidget_view*
466 xwidget_init_view (
467 struct xwidget *xww,
468 struct glyph_string *s,
469 int x, int y)
471 //TODO temp code replace with lisp list
472 struct xwidget_view *xv;
473 GdkColor color;
476 if(xwidget_view_index < MAX_XWIDGETS)
477 xwidget_view_index++;
478 else
479 xwidget_view_index=0;
481 xv = &xwidget_views[xwidget_view_index];
482 }while( xv->initialized == 1); //TODO yeah this can infloop if there are MAX_WIDGETS on-screen
484 xv->initialized = 1;
485 xv->w = s->w;
486 xv->model = xww;
488 //widget creation
489 if(EQ(xww->type, Qbutton))
491 xv->widget = gtk_button_new_with_label (XSTRING(xww->title)->data);
492 g_signal_connect (G_OBJECT (xv->widget), "clicked",
493 G_CALLBACK (buttonclick_handler), xww); //the model rather than the view
494 } else if (EQ(xww->type, Qtoggle)) {
495 xv->widget = gtk_toggle_button_new_with_label (XSTRING(xww->title)->data);
496 } else if (EQ(xww->type, Qsocket)) {
497 xv->widget = gtk_socket_new ();
498 g_signal_connect_after(xv->widget, "plug-added", G_CALLBACK(xwidget_plug_added), "plug added");
499 g_signal_connect_after(xv->widget, "plug-removed", G_CALLBACK(xwidget_plug_removed), "plug removed");
500 //TODO these doesnt help
501 gtk_widget_add_events(xv->widget, GDK_KEY_PRESS);
502 gtk_widget_add_events(xv->widget, GDK_KEY_RELEASE);
503 } else if (EQ(xww->type, Qslider)) {
504 xv->widget =
505 //gtk_hscale_new (GTK_ADJUSTMENT(gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 10.0, 10.0)));
506 gtk_hscale_new_with_range ( 0.0, 100.0, 10.0);
507 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
508 xv->handler_id = g_signal_connect_after(xv->widget, "value-changed", G_CALLBACK(xwidget_slider_changed), "slider changed");
509 } else if (EQ(xww->type, Qcairo)) {
510 //Cairo view
511 //uhm cairo is differentish in gtk 3.
512 //gdk_cairo_create (gtk_widget_get_window (FRAME_GTK_WIDGET (s->f)));
513 #ifdef HAVE_GOOCANVAS
514 xv->widget = goo_canvas_new();
515 GooCanvasItem *root, *rect_item, *text_item;
516 goo_canvas_set_bounds (GOO_CANVAS (xv->widget), 0, 0, 1000, 1000);
517 root = goo_canvas_get_root_item (GOO_CANVAS (xv->widget));
518 rect_item = goo_canvas_rect_new (root, 100, 100, 400, 400,
519 "line-width", 10.0,
520 "radius-x", 20.0,
521 "radius-y", 10.0,
522 "stroke-color", "yellow",
523 "fill-color", "red",
524 NULL);
526 text_item = goo_canvas_text_new (root, "Hello World", 300, 300, -1,
527 GTK_ANCHOR_CENTER,
528 "font", "Sans 24",
529 NULL);
530 goo_canvas_item_rotate (text_item, 45, 300, 300);
532 #endif
533 #ifdef HAVE_CLUTTER
534 xv->widget = gtk_clutter_embed_new ();;
535 ClutterActor *stage = NULL;
536 stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED ( xv->widget));
537 ClutterColor stage_color = { 0xaa, 0xaa, 0xaa, 0xff }; /* Black */
538 clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
540 ClutterActor * texture = clutter_cairo_texture_new (1000, 1000);
541 clutter_container_add_actor(stage, texture);
542 clutter_actor_set_position(texture, 0,0);
543 clutter_actor_show(texture);
545 cairo_t *cr;
546 cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (texture));
548 /* draw on the context */
549 RsvgHandle *h = rsvg_handle_new_from_file ("/tmp/tst.svg",
550 NULL);
552 rsvg_handle_render_cairo(h, cr);
553 cairo_destroy (cr);
555 /* Show the stage: */
556 clutter_actor_show (stage);
557 #endif
558 } else if (EQ(xww->type, Qwebkit_osr)||EQ(xww->type, Qsocket_osr)) {
559 #ifdef HAVE_WEBKIT_OSR
560 xv->widget = gtk_drawing_area_new();
561 gtk_widget_set_app_paintable ( xv->widget, TRUE); //because expose event handling
562 gtk_widget_add_events(xv->widget,
563 GDK_BUTTON_PRESS_MASK
564 | GDK_BUTTON_RELEASE_MASK
565 | GDK_POINTER_MOTION_MASK);
566 g_signal_connect (G_OBJECT ( xv->widget), "draw",
567 G_CALLBACK (xwidget_osr_draw_callback), NULL);
568 g_signal_connect (G_OBJECT ( xv->widget), "button-press-event",
569 G_CALLBACK (xwidget_osr_button_callback), NULL);
570 g_signal_connect (G_OBJECT ( xv->widget), "button-release-event",
571 G_CALLBACK (xwidget_osr_button_callback), NULL);
572 g_signal_connect (G_OBJECT ( xv->widget), "motion-notify-event",
573 G_CALLBACK (xwidget_osr_button_callback), NULL);
574 g_signal_connect (G_OBJECT ( xv->widget), "key-press-event",
575 G_CALLBACK (xwidget_osr_button_callback), NULL);
576 g_signal_connect (G_OBJECT ( xv->widget), "key-release-event",
577 G_CALLBACK (xwidget_osr_button_callback), NULL);
579 #endif
582 } else return NULL;
584 //widget realization
585 //make container widget 1st, and put the actual widget inside the container
586 //later, drawing should crop container window if necessary to handle case where xwidget
587 //is partially obscured by other emacs windows
588 //other containers than gtk_fixed where explored, but gtk_fixed had the most predictable behaviour so far.
589 xv->emacswindow = GTK_CONTAINER (FRAME_GTK_WIDGET (s->f));
590 xv->widgetwindow = GTK_CONTAINER (gtk_fixed_new ());
591 gtk_widget_set_has_window(GTK_WIDGET ( xv->widgetwindow), TRUE);
592 gtk_container_add (xv->widgetwindow, xv->widget);
594 //store some xwidget data in the gtk widgets
595 g_object_set_data (G_OBJECT (xv->widget), XG_FRAME_DATA, (gpointer) (s->f)); //the emacs frame
596 g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET, (gpointer) (xww)); //the xwidget
597 g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET_VIEW, (gpointer) (xv)); //the xwidget
598 g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET, (gpointer) (xww)); //the xwidget window
599 g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET_VIEW, (gpointer) (xv)); //the xwidget window
602 gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xww->width, xww->height);
603 gtk_widget_set_size_request (GTK_WIDGET (xv->widgetwindow), xww->width, xww->height);
604 gtk_fixed_put (GTK_FIXED (FRAME_GTK_WIDGET (s->f)), GTK_WIDGET (xv->widgetwindow), x, y);
605 xv->x = x; xv->y = y;
606 gtk_widget_show_all (GTK_WIDGET (xv->widgetwindow));
608 //widgettype specific initialization only possible after realization
609 if (EQ(xww->type, Qsocket)) {
610 printf ("xwid:%d socket id:%x %d\n",
611 xww,
612 gtk_socket_get_id (GTK_SOCKET (xv->widget)),
613 gtk_socket_get_id (GTK_SOCKET (xv->widget)));
614 send_xembed_ready_event (xww,
615 gtk_socket_get_id (GTK_SOCKET (xv->widget)));
616 //gtk_widget_realize(xw->widget);
618 return xv;
622 void
623 x_draw_xwidget_glyph_string (struct glyph_string *s)
626 this method is called by the redisplay engine and places the xwidget on screen.
627 moving and clipping is done here. also view init.
630 int box_line_hwidth = eabs (s->face->box_line_width);
631 int box_line_vwidth = max (s->face->box_line_width, 0);
632 int height = s->height;
633 struct xwidget *xww = s->xwidget;
634 struct xwidget_view *xv = xwidget_view_lookup(xww, (s->w));
635 int clip_right; int clip_bottom; int clip_top; int clip_left;
637 int x = s->x;
638 int y = s->y + (s->height / 2) - (xww->height / 2);
639 int moved=0;
641 if (xv == NULL || xv->initialized == 0){
642 /* Views must be initialized once(only once).
643 We do it here in the display loop because there is no other time to know things like
644 window placement etc.
646 printf ("xv init for xw %d\n", xww);
647 xv = xwidget_init_view (xww, s, x, y);
650 //calculate clipping, which is used for all manner of onscreen xwidget views
651 //each widget border can get clipped by other emacs objects so there are four clipping variables
652 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));
653 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));
655 clip_bottom = min (xww->height, WINDOW_BOTTOM_EDGE_Y (s->w) - WINDOW_MODE_LINE_HEIGHT (s->w) - y);
656 clip_top = max(0, WINDOW_TOP_EDGE_Y(s->w) -y );
658 //we are conserned with movement of the onscreen area. the area might sit still when the widget actually moves
659 //this happens when an emacs window border moves across a widget window
660 //so, if any corner of the outer widget clippng window moves, that counts as movement here, even
661 //if it looks like no movement happens because the widget sits still inside the clipping area.
662 //the widget can also move inside the clipping area, which happens later
663 moved = (xv->x + xv->clip_left != x+clip_left)
664 || ((xv->y + xv->clip_top)!= (y+clip_top));
665 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);
666 else
667 printf ("lxwidget DIDNT move: id:%d (%d,%d)->(%d,%d) y+clip_top:%d\n", xww, xv->x, xv->y, x, y, y + clip_top);
668 xv->x = x;
669 xv->y = y;
670 if (moved) //has it moved?
672 if (1)//!xwidget_hidden(xv)) //hidden equals not being seen during redisplay
674 //TODO should be possible to use xwidget_show_view here
675 gtk_fixed_move (GTK_FIXED (FRAME_GTK_WIDGET (s->f)),
676 GTK_WIDGET (xv->widgetwindow),
677 x + clip_left, y + clip_top);
680 //clip the widget window if some parts happen to be outside drawable area
681 //an emacs window is not a gtk window, a gtk window covers the entire frame
682 //cliping might have changed even if we havent actualy moved, we try figure out when we need to reclip for real
683 if((xv->clip_right != clip_right)
684 || (xv->clip_bottom != clip_bottom)
685 || (xv->clip_top != clip_top)
686 || (xv->clip_left != clip_left)){
687 gtk_widget_set_size_request (GTK_WIDGET (xv->widgetwindow), clip_right + clip_left, clip_bottom + clip_top);
688 gtk_fixed_move(GTK_FIXED(xv->widgetwindow), xv->widget, -clip_left, -clip_top);
689 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);
692 xv->clip_right = clip_right; xv->clip_bottom = clip_bottom; xv->clip_top = clip_top;xv->clip_left = clip_left;
694 //if emacs wants to repaint the area where the widget lives, queue a redraw
695 //TODO it seems its possible to get out of sync with emacs redraws so emacs bg sometimes shows up instead of xwidget
696 //its just a visual glitch though
697 if (!xwidget_hidden(xv)){
698 gtk_widget_queue_draw (GTK_WIDGET(xv->widgetwindow));
699 gtk_widget_queue_draw (xv->widget);
704 #ifdef HAVE_WEBKIT_OSR
705 DEFUN ("xwidget-webkit-goto-uri", Fxwidget_webkit_goto_uri, Sxwidget_webkit_goto_uri, 2, 2, 0,
706 doc: /* webkit goto uri.*/
708 (Lisp_Object xwidget, Lisp_Object uri)
710 struct xwidget* xw = XXWIDGET(xwidget);
711 webkit_web_view_load_uri ( WEBKIT_WEB_VIEW(xw->widget_osr), SDATA(uri));
712 return Qnil;
715 DEFUN ("xwidget-webkit-execute-script", Fxwidget_webkit_execute_script, Sxwidget_webkit_execute_script, 2, 2, 0,
716 doc: /* webkit exec js.*/
718 (Lisp_Object xwidget, Lisp_Object script)
720 struct xwidget* xw = XXWIDGET(xwidget);
721 webkit_web_view_execute_script( WEBKIT_WEB_VIEW(xw->widget_osr), SDATA(script));
722 return Qnil;
725 DEFUN ("xwidget-webkit-get-title", Fxwidget_webkit_get_title, Sxwidget_webkit_get_title, 1, 1, 0,
726 doc: /* webkit get title. can be used to work around exec method lacks return val*/
728 (Lisp_Object xwidget)
730 //TODO support multibyte strings
731 struct xwidget* xw = XXWIDGET(xwidget);
732 const gchar* str=webkit_web_view_get_title( WEBKIT_WEB_VIEW(xw->widget_osr));
733 //return make_string_from_bytes(str, wcslen((const wchar_t *)str), strlen(str));
734 return build_string(str);
737 //TODO missnamed
738 DEFUN("xwidget-disable-plugin-for-mime", Fxwidget_disable_plugin_for_mime , Sxwidget_disable_plugin_for_mime, 1,1,0, doc: /* */)
739 (Lisp_Object mime)
741 WebKitWebPlugin *wp = webkit_web_plugin_database_get_plugin_for_mimetype
742 (webkit_get_web_plugin_database(), SDATA(mime));
743 if(wp == NULL) return Qnil;
744 if(webkit_web_plugin_get_enabled (wp)){
745 webkit_web_plugin_set_enabled (wp, FALSE);
746 return Qt;
748 return Qnil;
752 //attempting a workaround for a webkit offscreen bug
753 //TODO verify its still needed
754 void gtk_window_get_position (GtkWindow *window,
755 gint *root_x,
756 gint *root_y){
757 printf("my getsize\n");
758 *root_x = 0;
759 *root_y = 0;
762 DEFUN ("xwidget-webkit-dom-dump", Fxwidget_webkit_dom_dump, Sxwidget_webkit_dom_dump, 1, 1, 0,
763 doc: /* webkit dom dump*/
765 (Lisp_Object xwidget)
767 struct xwidget* xw = XXWIDGET(xwidget);
768 xwidget_webkit_dom_dump(webkit_web_view_get_dom_document(xw->widget_osr));
769 return Qnil;
772 void
773 xwidget_webkit_dom_dump(WebKitDOMNode* parent){
774 WebKitDOMNodeList* list;
775 int i;
776 int length;
777 WebKitDOMNode* attribute;
778 WebKitDOMNamedNodeMap* attrs;
779 printf("node:%d type:%d name:%s content:%s\n",
780 parent,
781 webkit_dom_node_get_node_type(parent),//1 element 3 text 8 comment 2 attribute
782 webkit_dom_node_get_local_name(parent),
783 webkit_dom_node_get_text_content(parent));
785 if(webkit_dom_node_has_attributes(parent)){
786 attrs = webkit_dom_node_get_attributes(parent);
788 length = webkit_dom_named_node_map_get_length(attrs);
789 for (int i = 0; i < length; i++) {
790 attribute = webkit_dom_named_node_map_item(attrs,i);
791 printf(" attr node:%d type:%d name:%s content:%s\n",
792 attribute,
793 webkit_dom_node_get_node_type(attribute),//1 element 3 text 8 comment
794 webkit_dom_node_get_local_name(attribute),
795 webkit_dom_node_get_text_content(attribute));
798 list = webkit_dom_node_get_child_nodes(parent);
799 length = webkit_dom_node_list_get_length(list);
800 WebKitDOMNode* child;
801 for (int i = 0; i < length; i++) {
802 child = webkit_dom_node_list_item(list, i);
803 //if(webkit_dom_node_has_child_nodes(child))
804 xwidget_webkit_dom_dump(child);
809 #endif
815 DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 3, 3, 0, doc:
816 /* resize xwidgets*/)
817 (Lisp_Object xwidget, Lisp_Object new_width, Lisp_Object new_height)
819 struct xwidget* xw = XXWIDGET(xwidget);
820 struct xwidget_view *xv;
821 int w, h;
823 CHECK_NUMBER (new_width);
824 CHECK_NUMBER (new_height);
825 w = XFASTINT (new_width);
826 h = XFASTINT (new_height);
829 printf("resize xwidget %d (%d,%d)->(%d,%d)",xw, xw->width,xw->height,w,h);
830 xw->width=w;
831 xw->height=h;
832 //if theres a osr resize it 1st
833 if(xw->widget_osr){
834 gtk_layout_set_size (GTK_LAYOUT (xw->widgetwindow_osr), xw->width, xw->height);
835 gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, xw->height);
838 for (int i = 0; i < MAX_XWIDGETS; i++) //TODO MVC refactor lazy linear search
840 xv = &xwidget_views[i];
841 if(xv->initialized && xv->model == xw){
842 gtk_layout_set_size (GTK_LAYOUT (xv->widgetwindow), xw->width, xw->height);
843 gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xw->width, xw->height);
847 return Qnil;
850 DEFUN ("xwidget-size-request", Fxwidget_size_request, Sxwidget_size_request, 1, 1, 0, doc:
851 /* desired size (TODO crashes if arg not osr widget)*/)
852 (Lisp_Object xwidget)
854 GtkRequisition requisition;
855 Lisp_Object rv;
856 gtk_widget_size_request(XXWIDGET(xwidget)->widget_osr, &requisition);
857 rv = Qnil;
858 rv = Fcons (make_number(requisition.height), rv);
859 rv = Fcons (make_number(requisition.width), rv);
860 return rv;
864 DEFUN ("xwidgetp", Fxwidgetp, Sxwidgetp, 1, 1, 0,
865 doc: /* Return t if OBJECT is a xwidget. */)
866 (Lisp_Object object)
868 return XWIDGETP (object) ? Qt : Qnil;
871 DEFUN("xwidget-info", Fxwidget_info , Sxwidget_info, 1,1,0, doc: /* get xwidget props */)
872 (Lisp_Object xwidget)
874 Lisp_Object info;
875 struct xwidget* xw = XXWIDGET(xwidget);
877 info = Fmake_vector (make_number (4), Qnil);
878 XSETSYMBOL (XVECTOR (info)->contents[0], xw->type);
879 XSETSTRING (XVECTOR (info)->contents[1], xw->title);
880 XSETINT (XVECTOR (info)->contents[2], xw->width);
881 XSETINT (XVECTOR (info)->contents[3], xw->height);
884 return info;
888 DEFUN("xwidget-view-info", Fxwidget_view_info , Sxwidget_view_info, 2,2,0, doc: /* get xwidget view props */)
889 (Lisp_Object xwidget, Lisp_Object window)
891 struct xwidget* xw = XXWIDGET(xwidget);
892 struct xwidget_view* xv = xwidget_view_lookup(xw, XWINDOW(window));
894 Lisp_Object info;
896 info = Fmake_vector (make_number (6), Qnil);
897 XVECTOR (info)->contents[0] = make_number(xv->x);
898 XVECTOR (info)->contents[1] = make_number(xv->y);
899 XVECTOR (info)->contents[2] = make_number(xv->clip_right);
900 XVECTOR (info)->contents[3] = make_number(xv->clip_bottom);
901 XVECTOR (info)->contents[4] = make_number(xv->clip_top);
902 XVECTOR (info)->contents[5] = make_number(xv->clip_left);
904 return info;
907 DEFUN ("xwidget-send-keyboard-event", Fxwidget_send_keyboard_event, Sxwidget_send_keyboard_event, 2, 2, 0, doc:/* synthesize a kbd event for a xwidget. */
909 (Lisp_Object xwidget, Lisp_Object keydescriptor)
911 //TODO this code crashes for offscreen widgets and ive tried many different strategies
912 int keyval = 0x058; //X
913 char *keystring = "";
914 GdkKeymapKey* keys;
915 gint n_keys;
916 gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), keyval, &keys, &n_keys);
918 struct xwidget *xw = XXWIDGET(xwidget);
920 GdkEventKey* ev = (GdkEventKey*)gdk_event_new(GDK_KEY_PRESS);
923 //todo what about windowless widgets?
924 Lisp_Object window;
925 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
926 GtkWidget* widget;
928 if(xw->widget_osr)
929 widget = xw->widget_osr;
930 else
931 widget = xwidget_view_lookup(xw, XWINDOW(window))->widget;
933 ev->window = gtk_widget_get_window(widget);
934 gtk_widget_grab_focus(widget);
935 ev->send_event = FALSE;
937 ev->hardware_keycode = keys[0].keycode;
938 ev->group = keys[0].group;
940 ev->keyval = keyval;
941 ev->time = GDK_CURRENT_TIME;
943 //ev->device = gdk_device_get_core_pointer();
944 GdkDeviceManager* manager = gdk_display_get_device_manager(gdk_window_get_display(ev->window));
945 gdk_event_set_device ((GdkEvent*)ev, gdk_device_manager_get_client_pointer(manager));
946 gdk_event_put((GdkEvent*)ev);
947 //g_signal_emit_by_name(ev->window,"key-press-event", ev);
949 ev->type = GDK_KEY_RELEASE;
950 gdk_event_put((GdkEvent*)ev);
951 //g_signal_emit_by_name(ev->window,"key-release-event", ev);
952 //gtk_main_do_event(ev);
953 gdk_event_free((GdkEvent*)ev);
955 return Qnil;
960 DEFUN("xwidget-delete-zombies", Fxwidget_delete_zombies , Sxwidget_delete_zombies, 0,0,0, doc: /* */)
961 (void)
964 - remove all views with window gone
966 TODO
967 - remove all xwidgets with buffer gone
968 - remove all views with xw gone
971 struct xwidget_view* xv = NULL;
972 Lisp_Object w;
973 for (int i = 0; i < MAX_XWIDGETS; i++){
974 xv = &xwidget_views[i];
975 XSETWINDOW(w, xv->w);
976 if(xv->initialized && (! (WINDOW_LIVE_P(w)))){
978 gtk_widget_destroy(GTK_WIDGET(xv->widgetwindow));
979 xv->initialized = 0;
985 DEFUN ("xwidget-plist", Fxwidget_plist, Sxwidget_plist,
986 1, 1, 0,
987 doc: /* Return the plist of XWIDGET. */)
988 (register Lisp_Object xwidget)
990 //CHECK_XWIDGET (xwidget); //todo
991 return XXWIDGET (xwidget)->plist;
994 DEFUN ("xwidget-buffer", Fxwidget_buffer, Sxwidget_buffer,
995 1, 1, 0,
996 doc: /* Return the buffer of XWIDGET. */)
997 (register Lisp_Object xwidget)
999 //CHECK_XWIDGET (xwidget); //todo
1000 return XXWIDGET (xwidget)->buffer;
1003 DEFUN ("set-xwidget-plist", Fset_xwidget_plist, Sset_xwidget_plist,
1004 2, 2, 0,
1005 doc: /* Replace the plist of XWIDGET with PLIST. Returns PLIST. */)
1006 (register Lisp_Object xwidget, Lisp_Object plist)
1008 //CHECK_XWIDGET (xwidget); //todo
1009 CHECK_LIST (plist);
1011 XXWIDGET (xwidget)->plist = plist;
1012 return plist;
1017 void
1018 syms_of_xwidget (void)
1020 int i;
1022 defsubr (&Smake_xwidget);
1023 defsubr (&Sxwidgetp);
1024 defsubr (&Sxwidget_info);
1025 defsubr (&Sxwidget_view_info);
1026 defsubr (&Sxwidget_resize);
1028 #ifdef HAVE_WEBKIT_OSR
1029 defsubr (&Sxwidget_webkit_goto_uri);
1030 defsubr (&Sxwidget_webkit_execute_script);
1031 defsubr (&Sxwidget_webkit_get_title);
1032 DEFSYM (Qwebkit_osr ,"webkit-osr");
1033 #endif
1035 defsubr (&Sxwidget_size_request );
1036 defsubr (&Sxwidget_delete_zombies);
1037 defsubr (&Sxwidget_disable_plugin_for_mime);
1039 defsubr (&Sxwidget_send_keyboard_event);
1040 defsubr (&Sxwidget_webkit_dom_dump);
1041 defsubr (&Sxwidget_plist);
1042 defsubr (&Sxwidget_buffer);
1043 defsubr (&Sset_xwidget_plist);
1045 DEFSYM (Qxwidget ,"xwidget");
1047 DEFSYM (Qcxwidget ,":xwidget");
1048 DEFSYM (Qtitle ,":title");
1050 DEFSYM (Qbutton, "button");
1051 DEFSYM (Qtoggle, "toggle");
1052 DEFSYM (Qslider, "slider");
1053 DEFSYM (Qsocket, "socket");
1054 DEFSYM (Qsocket_osr, "socket-osr");
1055 DEFSYM (Qcairo, "cairo");
1057 DEFSYM (QCplist, ":plist");
1059 DEFVAR_LISP ("xwidget-alist", Vxwidget_alist, doc: /*xwidgets list*/);
1060 Vxwidget_alist = Qnil;
1061 DEFVAR_LISP ("xwidget-view-alist", Vxwidget_view_alist, doc: /*xwidget views list*/);
1062 Vxwidget_alist = Qnil;
1064 Fprovide (intern ("xwidget-internal"), Qnil);
1066 // for (i = 0; i < MAX_XWIDGETS; i++)
1067 //xwidgets[i].initialized = 0;
1071 /* Value is non-zero if OBJECT is a valid Lisp xwidget specification. A
1072 valid xwidget specification is a list whose car is the symbol
1073 `xwidget', and whose rest is a property list. The property list must
1074 contain a value for key `:type'. That value must be the name of a
1075 supported xwidget type. The rest of the property list depends on the
1076 xwidget type. */
1079 valid_xwidget_p (Lisp_Object object)
1081 int valid_p = 0;
1083 if (XWIDGETP (object))
1085 /* Lisp_Object tem; */
1087 /* for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem)) */
1088 /* if (EQ (XCAR (tem), QCtype)) */
1089 /* { */
1090 /* tem = XCDR (tem); */
1091 /* if (CONSP (tem) && SYMBOLP (XCAR (tem))) */
1092 /* { */
1093 /* struct xwidget_type *type; */
1094 /* type = lookup_xwidget_type (XCAR (tem)); */
1095 /* if (type) */
1096 /* valid_p = type->valid_p (object); */
1097 /* } */
1099 /* break; */
1100 /* } */
1101 //never mind type support for now
1102 valid_p = 1;
1105 return valid_p;
1110 /* find a value associated with key in spec */
1111 Lisp_Object
1112 xwidget_spec_value ( Lisp_Object spec, Lisp_Object key,
1113 int *found)
1115 Lisp_Object tail;
1117 xassert (valid_xwidget_p (spec));
1119 for (tail = XCDR (spec);
1120 CONSP (tail) && CONSP (XCDR (tail)); tail = XCDR (XCDR (tail)))
1122 if (EQ (XCAR (tail), key))
1124 if (found)
1125 *found = 1;
1126 return XCAR (XCDR (tail));
1130 if (found)
1131 *found = 0;
1132 return Qnil;
1136 void xwidget_view_delete_all_in_window( struct window *w )
1138 struct xwidget_view* xv = NULL;
1139 for (int i = 0; i < MAX_XWIDGETS; i++){
1140 xv = &xwidget_views[i];
1141 if(xv->initialized && xv->w == w){
1142 gtk_widget_destroy(GTK_WIDGET(xv->widgetwindow));
1143 xv->initialized = 0;
1150 struct xwidget_view* xwidget_view_lookup(struct xwidget* xw, struct window *w){
1151 struct xwidget_view* xv = NULL;
1152 for (int i = 0; i < MAX_XWIDGETS; i++){
1153 xv = &xwidget_views[i];
1154 if (xv->initialized && (xv->model == xw) && (xv->w == w))
1155 return xv;
1159 struct xwidget*
1160 lookup_xwidget (Lisp_Object spec)
1162 /* When a xwidget lisp spec is found initialize the C struct that is used in the C code.
1163 This is done by redisplay so values change if the spec changes.
1164 So, take special care of one-shot events
1166 TODO remove xwidget init from display spec. simply store an xwidget reference only and set
1167 size etc when creating the xwidget, which should happen before insertion into buffer
1169 int found = 0, found1 = 0, found2 = 0;
1170 Lisp_Object value;
1171 struct xwidget *xw;
1173 value = xwidget_spec_value (spec, Qcxwidget, &found1);
1174 xw = XXWIDGET(value);
1176 /* value = xwidget_spec_value (spec, QCtype, &found); */
1177 /* xw->type = SYMBOLP (value) ? value : Qbutton; //default to button */
1178 /* value = xwidget_spec_value (spec, Qtitle, &found2); */
1179 /* xw->title = STRINGP (value) ? (char *) SDATA (value) : "?"; //funky cast FIXME TODO */
1181 /* value = xwidget_spec_value (spec, QCheight, NULL); */
1182 /* xw->height = INTEGERP (value) ? XFASTINT (value) : 50; */
1183 /* value = xwidget_spec_value (spec, QCwidth, NULL); */
1184 /* xw->width = INTEGERP (value) ? XFASTINT (value) : 50; */
1186 /* value = xwidget_spec_value (spec, QCplist, NULL); */
1187 /* xw->plist = value; */
1188 /* coordinates are not known here */
1189 printf ("lookup_xwidget xwidget_id:%d type:%d found:%d %d %d title:'%s' (%d,%d)\n", xw,
1190 xw->type, found, found1, found2, xw->title, xw->height, xw->width);
1192 //assert_valid_xwidget_id (id, "lookup_xwidget");
1193 return xw;
1196 /*set up detection of touched xwidget*/
1197 void
1198 xwidget_start_redisplay (void)
1200 int i;
1201 for (i = 0; i < MAX_XWIDGETS; i++)
1202 xwidget_views[i].redisplayed = 0;
1206 /* the xwidget was touched during redisplay, so it isnt a candidate for hiding*/
1207 void
1208 xwidget_touch (struct xwidget_view *xv)
1210 xv->redisplayed = 1;
1214 xwidget_touched (struct xwidget_view *xv)
1216 return xv->redisplayed;
1219 /* redisplay has ended, now we should hide untouched xwidgets
1221 void
1222 xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix)
1225 int i;
1226 struct xwidget *xw;
1227 int area;
1230 xwidget_start_redisplay ();
1231 //iterate desired glyph matrix of window here, hide gtk widgets
1232 //not in the desired matrix.
1234 //this only takes care of xwidgets in active windows.
1235 //if a window goes away from screen xwidget views wust be deleted
1237 // dump_glyph_matrix(matrix, 2);
1238 for (i = 0; i < matrix->nrows; ++i)
1240 // dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
1241 struct glyph_row *row;
1242 row = MATRIX_ROW (matrix, i);
1243 if (row->enabled_p != 0)
1245 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
1247 struct glyph *glyph = row->glyphs[area];
1248 struct glyph *glyph_end = glyph + row->used[area];
1249 for (; glyph < glyph_end; ++glyph)
1251 if (glyph->type == XWIDGET_GLYPH)
1254 the only call to xwidget_end_redisplay is in dispnew
1255 xwidget_end_redisplay(w->current_matrix);
1257 xwidget_touch (xwidget_view_lookup(glyph->u.xwidget,
1258 w));
1265 for (i = 0; i < MAX_XWIDGETS; i++)
1267 struct xwidget_view* xv = &xwidget_views[i];
1269 //"touched" is only meaningful for the current window, so disregard other views
1270 if (xv->initialized && ( xv->w == w))
1272 if (xwidget_touched(xv))
1273 xwidget_show_view (xv);
1274 else
1275 xwidget_hide_view (xv);