typo
[emacs.git] / src / xwidget.c
blobeb6c5345a1f0a99526d11de06e656f9ad8623d28
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 //TODO these were just a test hack
203 /* g_signal_connect (G_OBJECT ( xw->widget_osr), "key-press-event", G_CALLBACK (webkit_osr_key_event_callback), NULL); */
204 /* g_signal_connect (G_OBJECT ( xw->widget_osr), "key-release-event", G_CALLBACK (webkit_osr_key_event_callback), NULL); */
206 g_signal_connect (G_OBJECT ( xw->widget_osr),
207 "document-load-finished",
208 G_CALLBACK (webkit_osr_document_load_finished_callback),
209 xw);
211 webkit_web_view_load_uri(WEBKIT_WEB_VIEW(xw->widget_osr), "http://www.fsf.org");
212 UNBLOCK_INPUT;
215 #endif
216 if (EQ(xw->type, Qsocket_osr)){
217 printf("init socket osr\n");
218 BLOCK_INPUT;
219 xw->widgetwindow_osr = GTK_CONTAINER (gtk_offscreen_window_new ());
220 gtk_window_resize( GTK_WINDOW(xw->widgetwindow_osr), xw->width, xw->height);
222 ////////////////////
223 //xw->widget_osr = webkit_web_view_new();
224 xw->widget_osr = gtk_socket_new();
225 //g_signal_connect_after(xv->widget, "plug-added", G_CALLBACK(xwidget_plug_added), "plug added");
226 //g_signal_connect_after(xv->widget, "plug-removed", G_CALLBACK(xwidget_plug_removed), "plug removed");
227 ///////////////////
229 gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, xw->height);
230 gtk_container_add (xw->widgetwindow_osr, xw->widget_osr);
232 gtk_widget_show_all (GTK_WIDGET (xw->widgetwindow_osr));
234 /* store some xwidget data in the gtk widgets for convenient retrieval in the event handlers. */
235 g_object_set_data (G_OBJECT (xw->widget_osr), XG_XWIDGET, (gpointer) (xw));
236 g_object_set_data (G_OBJECT (xw->widgetwindow_osr), XG_XWIDGET, (gpointer) (xw));
237 g_signal_connect (G_OBJECT ( xw->widgetwindow_osr), "damage-event", G_CALLBACK (webkit_osr_damage_event_callback), NULL);
239 //webkit_web_view_load_uri(WEBKIT_WEB_VIEW(xw->widget_osr), "http://www.fsf.org");
240 UNBLOCK_INPUT;
244 UNGCPRO;
245 return val;
249 xwidget_hidden(struct xwidget_view *xv)
251 return xv->hidden;
255 static void
256 buttonclick_handler (GtkWidget * widget, gpointer data)
258 struct xwidget *xw = (struct xwidget *) data;
259 struct input_event event;
260 Lisp_Object frame;
261 FRAME_PTR f = NULL;//(FRAME_PTR) g_object_get_data (G_OBJECT (xw->widget), XG_FRAME_DATA); //TODO
262 printf ("button clicked xw:%d '%s'\n", xw, xw->title);
264 EVENT_INIT (event);
265 event.kind = XWIDGET_EVENT;
267 XSETFRAME (frame, f);
269 event.frame_or_window = Qnil; //frame; //how to get the frame here?
272 event.arg = Qnil;
273 event.arg = Fcons (xw, event.arg); //TODO send the actual xwidget object now instead
274 event.arg = Fcons (intern ("buttonclick"), event.arg);
276 kbd_buffer_store_event (&event);
282 static void
283 send_xembed_ready_event (struct xwidget* xw, int xembedid)
285 struct input_event event;
286 EVENT_INIT (event);
287 event.kind = XWIDGET_EVENT;
288 event.frame_or_window = Qnil; //frame; //how to get the frame here? //TODO i store it in the xwidget now
290 event.arg = Qnil;
291 event.arg = Fcons (make_number (xembedid), event.arg);
292 event.arg = Fcons (intern ("xembed-ready"), event.arg);
293 event.arg = Fcons (xw, event.arg); //TODO
296 kbd_buffer_store_event (&event);
300 void
301 xwidget_show_view (struct xwidget_view *xv)
303 xv->hidden = 0;
304 gtk_widget_show(GTK_WIDGET(xv->widgetwindow));
305 gtk_fixed_move (GTK_FIXED (xv->emacswindow), GTK_WIDGET (xv->widgetwindow), xv->x + xv->clip_left, xv->y + xv->clip_top); //TODO refactor
309 /* hide an xvidget view */
310 void
311 xwidget_hide_view (struct xwidget_view *xv)
313 xv->hidden = 1;
314 //gtk_widget_hide(GTK_WIDGET(xw->widgetwindow));
315 gtk_fixed_move (GTK_FIXED (xv->emacswindow), GTK_WIDGET (xv->widgetwindow),
316 10000, 10000);
320 void xwidget_plug_added(GtkSocket *socket,
321 gpointer user_data)
323 //hmm this doesnt seem to get called for foreign windows
324 printf("xwidget_plug_added\n");
327 gboolean xwidget_plug_removed(GtkSocket *socket,
328 gpointer user_data)
330 printf("xwidget_plug_removed\n");
331 return TRUE; /* dont run the default handler because that kills the socket and we want to reuse it*/
335 void xwidget_slider_changed (GtkRange *range,
336 gpointer user_data)
338 //slider value changed. change value of siblings
339 //correspondingly. but remember that changing value will again
340 //trigger signal
342 //TODO MVC view storage wont be an array futureish so the loop needs to change eventually
343 //TODO MVC it would be nice if this code could be reusable but, alas, C is not a functional language
344 //issues are:
345 // - the type of the controllers value (double, boolean etc)
346 // - the getter and setter (but they can be func pointers)
347 // a behemoth macro is always an option.
348 double v=gtk_range_get_value(range);
349 struct xwidget_view* xvp = g_object_get_data (G_OBJECT (range), XG_XWIDGET_VIEW);
350 struct xwidget_view* xv;
352 printf("slider changed val:%f\n", v);
355 //block sibling views signal handlers
356 for (int i = 0; i < MAX_XWIDGETS; i++)
358 xv = &xwidget_views[i];
359 if(xv->initialized && xvp->model == xv->model){
360 g_signal_handler_block( xv->widget,xv->handler_id);
363 //set values of sibling views and unblock
364 for (int i = 0; i < MAX_XWIDGETS; i++)
366 xv = &xwidget_views[i];
367 if(xv->initialized && xvp->model == xv->model){
368 gtk_range_set_value(GTK_RANGE(xv->widget), v);
369 g_signal_handler_unblock( xv->widget,xv->handler_id);
376 /* when the off-screen webkit master view changes this signal is called.
377 it copies the bitmap from the off-screen webkit instance */
378 gboolean webkit_osr_damage_event_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data)
380 //TODO this is wrong! should just oueu a redraw of onscreen widget
381 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
382 struct xwidget_view* xv;
383 //webkit_osr_redraw_child(xw, widget);
384 printf ("damage\n");
385 for (int i = 0; i < MAX_XWIDGETS; i++)//todo mvc refactor
387 xv = &xwidget_views[i];
388 if(xv->initialized && xv->model == xw){
389 gtk_widget_queue_draw (xv->widget); //redraw all views, the master has changed
393 return FALSE;
398 gboolean webkit_osr_key_event_callback (GtkWidget *widget, GdkEventKey *event, gpointer data)
400 printf("terminating a webkit osr keypress\n");
401 //TRUE terminate the event here. no paren handlers will be called. but webkit then doesng get the event and it still crashes
402 //FALSE paren handlers will be called. webkit then gets the event and it still crashes
403 return TRUE;
407 void webkit_osr_document_load_finished_callback (WebKitWebView *webkitwebview,
408 WebKitWebFrame *arg1,
409 gpointer data)
411 //TODO this event sending code should be refactored
412 struct input_event event;
413 // struct xwidget *xw = (struct xwidget *) data;
414 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (webkitwebview), XG_XWIDGET);
415 printf("webkit finished loading\n");
417 EVENT_INIT (event);
418 event.kind = XWIDGET_EVENT;
419 event.frame_or_window = Qnil; //frame; //how to get the frame here? //TODO i store it in the xwidget now
421 event.arg = Qnil;
422 event.arg = Fcons (xw, event.arg); //TODO
423 event.arg = Fcons (intern ("document-load-finished"), event.arg);
426 kbd_buffer_store_event (&event);
430 //for gtk3 webkit_osr
431 gboolean
432 xwidget_osr_draw_callback (GtkWidget *widget, cairo_t *cr, gpointer data)
434 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
435 struct xwidget_view* xv = (struct xwidget_view*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET_VIEW);
437 // printf("xwidget_osr_draw_callback gtk3 xw.id:%d xw.type:%d window:%d vis:%d\n",
438 // xw,xw->type, gtk_widget_get_window (widget), gtk_widget_get_visible (xw->widget_osr));
440 cairo_rectangle(cr, 0,0, xv->clip_right, xv->clip_bottom);//xw->width, xw->height);
441 cairo_clip(cr);
443 gtk_widget_draw (xw->widget_osr, cr);
446 return FALSE;
450 gboolean
451 xwidget_osr_button_callback ( GtkWidget *widget,
452 GdkEvent *event,
453 gpointer user_data)
455 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
456 GdkEvent* eventcopy = gdk_event_copy(event);
458 ((GdkEventButton*)eventcopy)->window = gtk_widget_get_window(xw->widget_osr);
459 gtk_main_do_event(eventcopy); //TODO this will leak events. they should be deallocated later
460 return TRUE; //dont propagate this event furter
463 int xwidget_view_index=0;
465 /* initializes and does initial placement of an xwidget view on screen */
466 struct xwidget_view*
467 xwidget_init_view (
468 struct xwidget *xww,
469 struct glyph_string *s,
470 int x, int y)
472 //TODO temp code replace with lisp list
473 struct xwidget_view *xv;
474 GdkColor color;
477 if(xwidget_view_index < MAX_XWIDGETS)
478 xwidget_view_index++;
479 else
480 xwidget_view_index=0;
482 xv = &xwidget_views[xwidget_view_index];
483 }while( xv->initialized == 1); //TODO yeah this can infloop if there are MAX_WIDGETS on-screen
485 xv->initialized = 1;
486 xv->w = s->w;
487 xv->model = xww;
489 //widget creation
490 if(EQ(xww->type, Qbutton))
492 xv->widget = gtk_button_new_with_label (XSTRING(xww->title)->data);
493 g_signal_connect (G_OBJECT (xv->widget), "clicked",
494 G_CALLBACK (buttonclick_handler), xww); //the model rather than the view
495 } else if (EQ(xww->type, Qtoggle)) {
496 xv->widget = gtk_toggle_button_new_with_label (XSTRING(xww->title)->data);
497 //xv->widget = gtk_entry_new ();//temp hack to experiment with key propagation TODO entry widget is useful for testing
498 } else if (EQ(xww->type, Qsocket)) {
499 xv->widget = gtk_socket_new ();
500 g_signal_connect_after(xv->widget, "plug-added", G_CALLBACK(xwidget_plug_added), "plug added");
501 g_signal_connect_after(xv->widget, "plug-removed", G_CALLBACK(xwidget_plug_removed), "plug removed");
502 //TODO these doesnt help
503 gtk_widget_add_events(xv->widget, GDK_KEY_PRESS);
504 gtk_widget_add_events(xv->widget, GDK_KEY_RELEASE);
505 } else if (EQ(xww->type, Qslider)) {
506 xv->widget =
507 //gtk_hscale_new (GTK_ADJUSTMENT(gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 10.0, 10.0)));
508 gtk_hscale_new_with_range ( 0.0, 100.0, 10.0);
509 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
510 xv->handler_id = g_signal_connect_after(xv->widget, "value-changed", G_CALLBACK(xwidget_slider_changed), "slider changed");
511 } else if (EQ(xww->type, Qcairo)) {
512 //Cairo view
513 //uhm cairo is differentish in gtk 3.
514 //gdk_cairo_create (gtk_widget_get_window (FRAME_GTK_WIDGET (s->f)));
515 #ifdef HAVE_GOOCANVAS
516 xv->widget = goo_canvas_new();
517 GooCanvasItem *root, *rect_item, *text_item;
518 goo_canvas_set_bounds (GOO_CANVAS (xv->widget), 0, 0, 1000, 1000);
519 root = goo_canvas_get_root_item (GOO_CANVAS (xv->widget));
520 rect_item = goo_canvas_rect_new (root, 100, 100, 400, 400,
521 "line-width", 10.0,
522 "radius-x", 20.0,
523 "radius-y", 10.0,
524 "stroke-color", "yellow",
525 "fill-color", "red",
526 NULL);
528 text_item = goo_canvas_text_new (root, "Hello World", 300, 300, -1,
529 GTK_ANCHOR_CENTER,
530 "font", "Sans 24",
531 NULL);
532 goo_canvas_item_rotate (text_item, 45, 300, 300);
534 #endif
535 #ifdef HAVE_CLUTTER
536 xv->widget = gtk_clutter_embed_new ();;
537 ClutterActor *stage = NULL;
538 stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED ( xv->widget));
539 ClutterColor stage_color = { 0xaa, 0xaa, 0xaa, 0xff }; /* Black */
540 clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
542 ClutterActor * texture = clutter_cairo_texture_new (1000, 1000);
543 clutter_container_add_actor(stage, texture);
544 clutter_actor_set_position(texture, 0,0);
545 clutter_actor_show(texture);
547 cairo_t *cr;
548 cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (texture));
550 /* draw on the context */
551 RsvgHandle *h = rsvg_handle_new_from_file ("/tmp/tst.svg",
552 NULL);
554 rsvg_handle_render_cairo(h, cr);
555 cairo_destroy (cr);
557 /* Show the stage: */
558 clutter_actor_show (stage);
559 #endif
560 } else if (EQ(xww->type, Qwebkit_osr)||EQ(xww->type, Qsocket_osr)) {
561 #ifdef HAVE_WEBKIT_OSR
562 xv->widget = gtk_drawing_area_new();
563 gtk_widget_set_app_paintable ( xv->widget, TRUE); //because expose event handling
564 gtk_widget_add_events(xv->widget,
565 GDK_BUTTON_PRESS_MASK
566 | GDK_BUTTON_RELEASE_MASK
567 | GDK_POINTER_MOTION_MASK);
568 g_signal_connect (G_OBJECT ( xv->widget), "draw",
569 G_CALLBACK (xwidget_osr_draw_callback), NULL);
570 g_signal_connect (G_OBJECT ( xv->widget), "button-press-event",
571 G_CALLBACK (xwidget_osr_button_callback), NULL);
572 g_signal_connect (G_OBJECT ( xv->widget), "button-release-event",
573 G_CALLBACK (xwidget_osr_button_callback), NULL);
574 g_signal_connect (G_OBJECT ( xv->widget), "motion-notify-event",
575 G_CALLBACK (xwidget_osr_button_callback), NULL);
576 /* g_signal_connect (G_OBJECT ( xv->widget), "key-press-event", */
577 /* G_CALLBACK (xwidget_osr_button_callback), NULL); */
578 /* g_signal_connect (G_OBJECT ( xv->widget), "key-release-event", */
579 /* G_CALLBACK (xwidget_osr_button_callback), NULL); */
581 #endif
584 } else return NULL;
586 //widget realization
587 //make container widget 1st, and put the actual widget inside the container
588 //later, drawing should crop container window if necessary to handle case where xwidget
589 //is partially obscured by other emacs windows
590 //other containers than gtk_fixed where explored, but gtk_fixed had the most predictable behaviour so far.
591 xv->emacswindow = GTK_CONTAINER (FRAME_GTK_WIDGET (s->f));
592 xv->widgetwindow = GTK_CONTAINER (gtk_fixed_new ());
593 gtk_widget_set_has_window(GTK_WIDGET ( xv->widgetwindow), TRUE);
594 gtk_container_add (xv->widgetwindow, xv->widget);
596 //store some xwidget data in the gtk widgets
597 g_object_set_data (G_OBJECT (xv->widget), XG_FRAME_DATA, (gpointer) (s->f)); //the emacs frame
598 g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET, (gpointer) (xww)); //the xwidget
599 g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET_VIEW, (gpointer) (xv)); //the xwidget
600 g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET, (gpointer) (xww)); //the xwidget window
601 g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET_VIEW, (gpointer) (xv)); //the xwidget window
604 gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xww->width, xww->height);
605 gtk_widget_set_size_request (GTK_WIDGET (xv->widgetwindow), xww->width, xww->height);
606 gtk_fixed_put (GTK_FIXED (FRAME_GTK_WIDGET (s->f)), GTK_WIDGET (xv->widgetwindow), x, y);
607 xv->x = x; xv->y = y;
608 gtk_widget_show_all (GTK_WIDGET (xv->widgetwindow));
610 //widgettype specific initialization only possible after realization
611 if (EQ(xww->type, Qsocket)) {
612 printf ("xwid:%d socket id:%x %d\n",
613 xww,
614 gtk_socket_get_id (GTK_SOCKET (xv->widget)),
615 gtk_socket_get_id (GTK_SOCKET (xv->widget)));
616 send_xembed_ready_event (xww,
617 gtk_socket_get_id (GTK_SOCKET (xv->widget)));
618 //gtk_widget_realize(xw->widget);
620 return xv;
624 void
625 x_draw_xwidget_glyph_string (struct glyph_string *s)
628 this method is called by the redisplay engine and places the xwidget on screen.
629 moving and clipping is done here. also view init.
632 int box_line_hwidth = eabs (s->face->box_line_width);
633 int box_line_vwidth = max (s->face->box_line_width, 0);
634 int height = s->height;
635 struct xwidget *xww = s->xwidget;
636 struct xwidget_view *xv = xwidget_view_lookup(xww, (s->w));
637 int clip_right; int clip_bottom; int clip_top; int clip_left;
639 int x = s->x;
640 int y = s->y + (s->height / 2) - (xww->height / 2);
641 int moved=0;
643 if (xv == NULL || xv->initialized == 0){
644 /* Views must be initialized once(only once).
645 We do it here in the display loop because there is no other time to know things like
646 window placement etc.
648 printf ("xv init for xw %d\n", xww);
649 xv = xwidget_init_view (xww, s, x, y);
652 //calculate clipping, which is used for all manner of onscreen xwidget views
653 //each widget border can get clipped by other emacs objects so there are four clipping variables
654 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));
655 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));
657 clip_bottom = min (xww->height, WINDOW_BOTTOM_EDGE_Y (s->w) - WINDOW_MODE_LINE_HEIGHT (s->w) - y);
658 clip_top = max(0, WINDOW_TOP_EDGE_Y(s->w) -y );
660 //we are conserned with movement of the onscreen area. the area might sit still when the widget actually moves
661 //this happens when an emacs window border moves across a widget window
662 //so, if any corner of the outer widget clippng window moves, that counts as movement here, even
663 //if it looks like no movement happens because the widget sits still inside the clipping area.
664 //the widget can also move inside the clipping area, which happens later
665 moved = (xv->x + xv->clip_left != x+clip_left)
666 || ((xv->y + xv->clip_top)!= (y+clip_top));
667 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);
668 else
669 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);
670 xv->x = x;
671 xv->y = y;
672 if (moved) //has it moved?
674 if (1)//!xwidget_hidden(xv)) //hidden equals not being seen during redisplay
676 //TODO should be possible to use xwidget_show_view here
677 gtk_fixed_move (GTK_FIXED (FRAME_GTK_WIDGET (s->f)),
678 GTK_WIDGET (xv->widgetwindow),
679 x + clip_left, y + clip_top);
682 //clip the widget window if some parts happen to be outside drawable area
683 //an emacs window is not a gtk window, a gtk window covers the entire frame
684 //cliping might have changed even if we havent actualy moved, we try figure out when we need to reclip for real
685 if((xv->clip_right != clip_right)
686 || (xv->clip_bottom != clip_bottom)
687 || (xv->clip_top != clip_top)
688 || (xv->clip_left != clip_left)){
689 gtk_widget_set_size_request (GTK_WIDGET (xv->widgetwindow), clip_right + clip_left, clip_bottom + clip_top);
690 gtk_fixed_move(GTK_FIXED(xv->widgetwindow), xv->widget, -clip_left, -clip_top);
691 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);
694 xv->clip_right = clip_right; xv->clip_bottom = clip_bottom; xv->clip_top = clip_top;xv->clip_left = clip_left;
696 //if emacs wants to repaint the area where the widget lives, queue a redraw
697 //TODO it seems its possible to get out of sync with emacs redraws so emacs bg sometimes shows up instead of xwidget
698 //its just a visual glitch though
699 if (!xwidget_hidden(xv)){
700 gtk_widget_queue_draw (GTK_WIDGET(xv->widgetwindow));
701 gtk_widget_queue_draw (xv->widget);
706 #ifdef HAVE_WEBKIT_OSR
707 DEFUN ("xwidget-webkit-goto-uri", Fxwidget_webkit_goto_uri, Sxwidget_webkit_goto_uri, 2, 2, 0,
708 doc: /* webkit goto uri.*/
710 (Lisp_Object xwidget, Lisp_Object uri)
712 struct xwidget* xw = XXWIDGET(xwidget);
713 webkit_web_view_load_uri ( WEBKIT_WEB_VIEW(xw->widget_osr), SDATA(uri));
714 return Qnil;
717 DEFUN ("xwidget-webkit-execute-script", Fxwidget_webkit_execute_script, Sxwidget_webkit_execute_script, 2, 2, 0,
718 doc: /* webkit exec js.*/
720 (Lisp_Object xwidget, Lisp_Object script)
722 struct xwidget* xw = XXWIDGET(xwidget);
723 webkit_web_view_execute_script( WEBKIT_WEB_VIEW(xw->widget_osr), SDATA(script));
724 return Qnil;
727 DEFUN ("xwidget-webkit-get-title", Fxwidget_webkit_get_title, Sxwidget_webkit_get_title, 1, 1, 0,
728 doc: /* webkit get title. can be used to work around exec method lacks return val*/
730 (Lisp_Object xwidget)
732 //TODO support multibyte strings
733 struct xwidget* xw = XXWIDGET(xwidget);
734 const gchar* str=webkit_web_view_get_title( WEBKIT_WEB_VIEW(xw->widget_osr));
735 //return make_string_from_bytes(str, wcslen((const wchar_t *)str), strlen(str));
736 if(str == 0){
737 //TODO maybe return Qnil instead. I suppose webkit returns nullpointer when doc is not properly loaded or something
738 printf("xwidget-webkit-get-title null webkit title\n");
739 return build_string("");
741 return build_string(str);
744 //TODO missnamed
745 DEFUN("xwidget-disable-plugin-for-mime", Fxwidget_disable_plugin_for_mime , Sxwidget_disable_plugin_for_mime, 1,1,0, doc: /* */)
746 (Lisp_Object mime)
748 WebKitWebPlugin *wp = webkit_web_plugin_database_get_plugin_for_mimetype
749 (webkit_get_web_plugin_database(), SDATA(mime));
750 if(wp == NULL) return Qnil;
751 if(webkit_web_plugin_get_enabled (wp)){
752 webkit_web_plugin_set_enabled (wp, FALSE);
753 return Qt;
755 return Qnil;
759 //attempting a workaround for a webkit offscreen bug
760 //TODO verify its still needed
761 void gtk_window_get_position (GtkWindow *window,
762 gint *root_x,
763 gint *root_y){
764 printf("my getsize\n");
765 *root_x = 0;
766 *root_y = 0;
769 DEFUN ("xwidget-webkit-dom-dump", Fxwidget_webkit_dom_dump, Sxwidget_webkit_dom_dump, 1, 1, 0,
770 doc: /* webkit dom dump*/
772 (Lisp_Object xwidget)
774 struct xwidget* xw = XXWIDGET(xwidget);
775 xwidget_webkit_dom_dump(webkit_web_view_get_dom_document(xw->widget_osr));
776 return Qnil;
779 void
780 xwidget_webkit_dom_dump(WebKitDOMNode* parent){
781 WebKitDOMNodeList* list;
782 int i;
783 int length;
784 WebKitDOMNode* attribute;
785 WebKitDOMNamedNodeMap* attrs;
786 printf("node:%d type:%d name:%s content:%s\n",
787 parent,
788 webkit_dom_node_get_node_type(parent),//1 element 3 text 8 comment 2 attribute
789 webkit_dom_node_get_local_name(parent),
790 webkit_dom_node_get_text_content(parent));
792 if(webkit_dom_node_has_attributes(parent)){
793 attrs = webkit_dom_node_get_attributes(parent);
795 length = webkit_dom_named_node_map_get_length(attrs);
796 for (int i = 0; i < length; i++) {
797 attribute = webkit_dom_named_node_map_item(attrs,i);
798 printf(" attr node:%d type:%d name:%s content:%s\n",
799 attribute,
800 webkit_dom_node_get_node_type(attribute),//1 element 3 text 8 comment
801 webkit_dom_node_get_local_name(attribute),
802 webkit_dom_node_get_text_content(attribute));
805 list = webkit_dom_node_get_child_nodes(parent);
806 length = webkit_dom_node_list_get_length(list);
807 WebKitDOMNode* child;
808 for (int i = 0; i < length; i++) {
809 child = webkit_dom_node_list_item(list, i);
810 //if(webkit_dom_node_has_child_nodes(child))
811 xwidget_webkit_dom_dump(child);
816 #endif
822 DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 3, 3, 0, doc:
823 /* resize xwidgets*/)
824 (Lisp_Object xwidget, Lisp_Object new_width, Lisp_Object new_height)
826 struct xwidget* xw = XXWIDGET(xwidget);
827 struct xwidget_view *xv;
828 int w, h;
830 CHECK_NUMBER (new_width);
831 CHECK_NUMBER (new_height);
832 w = XFASTINT (new_width);
833 h = XFASTINT (new_height);
836 printf("resize xwidget %d (%d,%d)->(%d,%d)",xw, xw->width,xw->height,w,h);
837 xw->width=w;
838 xw->height=h;
839 //if theres a osr resize it 1st
840 if(xw->widget_osr){
841 gtk_layout_set_size (GTK_LAYOUT (xw->widgetwindow_osr), xw->width, xw->height);
842 gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, xw->height);
845 for (int i = 0; i < MAX_XWIDGETS; i++) //TODO MVC refactor lazy linear search
847 xv = &xwidget_views[i];
848 if(xv->initialized && xv->model == xw){
849 gtk_layout_set_size (GTK_LAYOUT (xv->widgetwindow), xw->width, xw->height);
850 gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xw->width, xw->height);
854 return Qnil;
857 DEFUN ("xwidget-size-request", Fxwidget_size_request, Sxwidget_size_request, 1, 1, 0, doc:
858 /* desired size (TODO crashes if arg not osr widget)*/)
859 (Lisp_Object xwidget)
861 GtkRequisition requisition;
862 Lisp_Object rv;
863 gtk_widget_size_request(XXWIDGET(xwidget)->widget_osr, &requisition);
864 rv = Qnil;
865 rv = Fcons (make_number(requisition.height), rv);
866 rv = Fcons (make_number(requisition.width), rv);
867 return rv;
871 DEFUN ("xwidgetp", Fxwidgetp, Sxwidgetp, 1, 1, 0,
872 doc: /* Return t if OBJECT is a xwidget. */)
873 (Lisp_Object object)
875 return XWIDGETP (object) ? Qt : Qnil;
878 DEFUN("xwidget-info", Fxwidget_info , Sxwidget_info, 1,1,0, doc: /* get xwidget props */)
879 (Lisp_Object xwidget)
881 Lisp_Object info;
882 struct xwidget* xw = XXWIDGET(xwidget);
884 info = Fmake_vector (make_number (4), Qnil);
885 XSETSYMBOL (XVECTOR (info)->contents[0], xw->type);
886 XSETSTRING (XVECTOR (info)->contents[1], xw->title);
887 XSETINT (XVECTOR (info)->contents[2], xw->width);
888 XSETINT (XVECTOR (info)->contents[3], xw->height);
891 return info;
895 DEFUN("xwidget-view-info", Fxwidget_view_info , Sxwidget_view_info, 2,2,0, doc: /* get xwidget view props */)
896 (Lisp_Object xwidget, Lisp_Object window)
898 struct xwidget* xw = XXWIDGET(xwidget);
899 struct xwidget_view* xv = xwidget_view_lookup(xw, XWINDOW(window));
901 Lisp_Object info;
903 info = Fmake_vector (make_number (6), Qnil);
904 XVECTOR (info)->contents[0] = make_number(xv->x);
905 XVECTOR (info)->contents[1] = make_number(xv->y);
906 XVECTOR (info)->contents[2] = make_number(xv->clip_right);
907 XVECTOR (info)->contents[3] = make_number(xv->clip_bottom);
908 XVECTOR (info)->contents[4] = make_number(xv->clip_top);
909 XVECTOR (info)->contents[5] = make_number(xv->clip_left);
911 return info;
914 DEFUN ("xwidget-send-keyboard-event", Fxwidget_send_keyboard_event, Sxwidget_send_keyboard_event, 2, 2, 0, doc:/* synthesize a kbd event for a xwidget. */
916 (Lisp_Object xwidget, Lisp_Object keydescriptor)
918 //TODO this code crashes for offscreen widgets and ive tried many different strategies
919 //int keyval = 0x058; //X
920 int keyval = XFASTINT(keydescriptor); //X
921 char *keystring = "";
922 GdkKeymapKey* keys;
923 gint n_keys;
924 //popup_activated_flag = 1; //TODO just a hack
925 gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), keyval, &keys, &n_keys);
927 struct xwidget *xw = XXWIDGET(xwidget);
929 GdkEventKey* ev = (GdkEventKey*)gdk_event_new(GDK_KEY_PRESS);
932 //todo what about windowless widgets?
933 Lisp_Object window;
934 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
935 GtkWidget* widget;
937 //TODO maybe we also need to special case sockets by picking up the plug rather than the socket
938 if(xw->widget_osr)
939 widget = xw->widget_osr;
940 else
941 widget = xwidget_view_lookup(xw, XWINDOW(window))->widget;
943 ev->window = gtk_widget_get_window(widget);
944 gtk_widget_grab_focus(widget);
945 ev->send_event = FALSE;
947 ev->hardware_keycode = keys[0].keycode;
948 ev->group = keys[0].group;
950 ev->keyval = keyval;
951 ev->time = GDK_CURRENT_TIME;
953 //ev->device = gdk_device_get_core_pointer();
954 GdkDeviceManager* manager = gdk_display_get_device_manager(gdk_window_get_display(ev->window));
955 gdk_event_set_device ((GdkEvent*)ev, gdk_device_manager_get_client_pointer(manager));
956 gdk_event_put((GdkEvent*)ev);
957 //g_signal_emit_by_name(ev->window,"key-press-event", ev);
959 ev->type = GDK_KEY_RELEASE;
960 gdk_event_put((GdkEvent*)ev);
961 //g_signal_emit_by_name(ev->window,"key-release-event", ev);
962 //gtk_main_do_event(ev);
964 //TODO
965 //if I delete the event the receiving component eventually crashes.
966 //it ough TDTRT since event_put is supposed to copy the event
967 //so probably this leaks events now
968 //gdk_event_free((GdkEvent*)ev);
970 return Qnil;
975 DEFUN("xwidget-delete-zombies", Fxwidget_delete_zombies , Sxwidget_delete_zombies, 0,0,0, doc: /* */)
976 (void)
979 - remove all views with window gone
981 TODO
982 - remove all xwidgets with buffer gone
983 - remove all views with xw gone
986 struct xwidget_view* xv = NULL;
987 Lisp_Object w;
988 for (int i = 0; i < MAX_XWIDGETS; i++){
989 xv = &xwidget_views[i];
990 XSETWINDOW(w, xv->w);
991 if(xv->initialized && (! (WINDOW_LIVE_P(w)))){
993 gtk_widget_destroy(GTK_WIDGET(xv->widgetwindow));
994 xv->initialized = 0;
1000 DEFUN ("xwidget-plist", Fxwidget_plist, Sxwidget_plist,
1001 1, 1, 0,
1002 doc: /* Return the plist of XWIDGET. */)
1003 (register Lisp_Object xwidget)
1005 //CHECK_XWIDGET (xwidget); //todo
1006 return XXWIDGET (xwidget)->plist;
1009 DEFUN ("xwidget-buffer", Fxwidget_buffer, Sxwidget_buffer,
1010 1, 1, 0,
1011 doc: /* Return the buffer of XWIDGET. */)
1012 (register Lisp_Object xwidget)
1014 //CHECK_XWIDGET (xwidget); //todo
1015 return XXWIDGET (xwidget)->buffer;
1018 DEFUN ("set-xwidget-plist", Fset_xwidget_plist, Sset_xwidget_plist,
1019 2, 2, 0,
1020 doc: /* Replace the plist of XWIDGET with PLIST. Returns PLIST. */)
1021 (register Lisp_Object xwidget, Lisp_Object plist)
1023 //CHECK_XWIDGET (xwidget); //todo
1024 CHECK_LIST (plist);
1026 XXWIDGET (xwidget)->plist = plist;
1027 return plist;
1032 void
1033 syms_of_xwidget (void)
1035 int i;
1037 defsubr (&Smake_xwidget);
1038 defsubr (&Sxwidgetp);
1039 defsubr (&Sxwidget_info);
1040 defsubr (&Sxwidget_view_info);
1041 defsubr (&Sxwidget_resize);
1043 #ifdef HAVE_WEBKIT_OSR
1044 defsubr (&Sxwidget_webkit_goto_uri);
1045 defsubr (&Sxwidget_webkit_execute_script);
1046 defsubr (&Sxwidget_webkit_get_title);
1047 DEFSYM (Qwebkit_osr ,"webkit-osr");
1048 #endif
1050 defsubr (&Sxwidget_size_request );
1051 defsubr (&Sxwidget_delete_zombies);
1052 defsubr (&Sxwidget_disable_plugin_for_mime);
1054 defsubr (&Sxwidget_send_keyboard_event);
1055 defsubr (&Sxwidget_webkit_dom_dump);
1056 defsubr (&Sxwidget_plist);
1057 defsubr (&Sxwidget_buffer);
1058 defsubr (&Sset_xwidget_plist);
1060 DEFSYM (Qxwidget ,"xwidget");
1062 DEFSYM (Qcxwidget ,":xwidget");
1063 DEFSYM (Qtitle ,":title");
1065 DEFSYM (Qbutton, "button");
1066 DEFSYM (Qtoggle, "toggle");
1067 DEFSYM (Qslider, "slider");
1068 DEFSYM (Qsocket, "socket");
1069 DEFSYM (Qsocket_osr, "socket-osr");
1070 DEFSYM (Qcairo, "cairo");
1072 DEFSYM (QCplist, ":plist");
1074 DEFVAR_LISP ("xwidget-alist", Vxwidget_alist, doc: /*xwidgets list*/);
1075 Vxwidget_alist = Qnil;
1076 DEFVAR_LISP ("xwidget-view-alist", Vxwidget_view_alist, doc: /*xwidget views list*/);
1077 Vxwidget_alist = Qnil;
1079 Fprovide (intern ("xwidget-internal"), Qnil);
1081 // for (i = 0; i < MAX_XWIDGETS; i++)
1082 //xwidgets[i].initialized = 0;
1086 /* Value is non-zero if OBJECT is a valid Lisp xwidget specification. A
1087 valid xwidget specification is a list whose car is the symbol
1088 `xwidget', and whose rest is a property list. The property list must
1089 contain a value for key `:type'. That value must be the name of a
1090 supported xwidget type. The rest of the property list depends on the
1091 xwidget type. */
1094 valid_xwidget_p (Lisp_Object object)
1096 int valid_p = 0;
1098 if (XWIDGETP (object))
1100 /* Lisp_Object tem; */
1102 /* for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem)) */
1103 /* if (EQ (XCAR (tem), QCtype)) */
1104 /* { */
1105 /* tem = XCDR (tem); */
1106 /* if (CONSP (tem) && SYMBOLP (XCAR (tem))) */
1107 /* { */
1108 /* struct xwidget_type *type; */
1109 /* type = lookup_xwidget_type (XCAR (tem)); */
1110 /* if (type) */
1111 /* valid_p = type->valid_p (object); */
1112 /* } */
1114 /* break; */
1115 /* } */
1116 //never mind type support for now
1117 valid_p = 1;
1120 return valid_p;
1125 /* find a value associated with key in spec */
1126 Lisp_Object
1127 xwidget_spec_value ( Lisp_Object spec, Lisp_Object key,
1128 int *found)
1130 Lisp_Object tail;
1132 xassert (valid_xwidget_p (spec));
1134 for (tail = XCDR (spec);
1135 CONSP (tail) && CONSP (XCDR (tail)); tail = XCDR (XCDR (tail)))
1137 if (EQ (XCAR (tail), key))
1139 if (found)
1140 *found = 1;
1141 return XCAR (XCDR (tail));
1145 if (found)
1146 *found = 0;
1147 return Qnil;
1151 void xwidget_view_delete_all_in_window( struct window *w )
1153 struct xwidget_view* xv = NULL;
1154 for (int i = 0; i < MAX_XWIDGETS; i++){
1155 xv = &xwidget_views[i];
1156 if(xv->initialized && xv->w == w){
1157 gtk_widget_destroy(GTK_WIDGET(xv->widgetwindow));
1158 xv->initialized = 0;
1165 struct xwidget_view* xwidget_view_lookup(struct xwidget* xw, struct window *w){
1166 struct xwidget_view* xv = NULL;
1167 for (int i = 0; i < MAX_XWIDGETS; i++){
1168 xv = &xwidget_views[i];
1169 if (xv->initialized && (xv->model == xw) && (xv->w == w))
1170 return xv;
1174 struct xwidget*
1175 lookup_xwidget (Lisp_Object spec)
1177 /* When a xwidget lisp spec is found initialize the C struct that is used in the C code.
1178 This is done by redisplay so values change if the spec changes.
1179 So, take special care of one-shot events
1181 TODO remove xwidget init from display spec. simply store an xwidget reference only and set
1182 size etc when creating the xwidget, which should happen before insertion into buffer
1184 int found = 0, found1 = 0, found2 = 0;
1185 Lisp_Object value;
1186 struct xwidget *xw;
1188 value = xwidget_spec_value (spec, Qcxwidget, &found1);
1189 xw = XXWIDGET(value);
1191 /* value = xwidget_spec_value (spec, QCtype, &found); */
1192 /* xw->type = SYMBOLP (value) ? value : Qbutton; //default to button */
1193 /* value = xwidget_spec_value (spec, Qtitle, &found2); */
1194 /* xw->title = STRINGP (value) ? (char *) SDATA (value) : "?"; //funky cast FIXME TODO */
1196 /* value = xwidget_spec_value (spec, QCheight, NULL); */
1197 /* xw->height = INTEGERP (value) ? XFASTINT (value) : 50; */
1198 /* value = xwidget_spec_value (spec, QCwidth, NULL); */
1199 /* xw->width = INTEGERP (value) ? XFASTINT (value) : 50; */
1201 /* value = xwidget_spec_value (spec, QCplist, NULL); */
1202 /* xw->plist = value; */
1203 /* coordinates are not known here */
1204 printf ("lookup_xwidget xwidget_id:%d type:%d found:%d %d %d title:'%s' (%d,%d)\n", xw,
1205 xw->type, found, found1, found2, xw->title, xw->height, xw->width);
1207 //assert_valid_xwidget_id (id, "lookup_xwidget");
1208 return xw;
1211 /*set up detection of touched xwidget*/
1212 void
1213 xwidget_start_redisplay (void)
1215 int i;
1216 for (i = 0; i < MAX_XWIDGETS; i++)
1217 xwidget_views[i].redisplayed = 0;
1221 /* the xwidget was touched during redisplay, so it isnt a candidate for hiding*/
1222 void
1223 xwidget_touch (struct xwidget_view *xv)
1225 xv->redisplayed = 1;
1229 xwidget_touched (struct xwidget_view *xv)
1231 return xv->redisplayed;
1234 /* redisplay has ended, now we should hide untouched xwidgets
1236 void
1237 xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix)
1240 int i;
1241 struct xwidget *xw;
1242 int area;
1245 xwidget_start_redisplay ();
1246 //iterate desired glyph matrix of window here, hide gtk widgets
1247 //not in the desired matrix.
1249 //this only takes care of xwidgets in active windows.
1250 //if a window goes away from screen xwidget views wust be deleted
1252 // dump_glyph_matrix(matrix, 2);
1253 for (i = 0; i < matrix->nrows; ++i)
1255 // dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
1256 struct glyph_row *row;
1257 row = MATRIX_ROW (matrix, i);
1258 if (row->enabled_p != 0)
1260 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
1262 struct glyph *glyph = row->glyphs[area];
1263 struct glyph *glyph_end = glyph + row->used[area];
1264 for (; glyph < glyph_end; ++glyph)
1266 if (glyph->type == XWIDGET_GLYPH)
1269 the only call to xwidget_end_redisplay is in dispnew
1270 xwidget_end_redisplay(w->current_matrix);
1272 xwidget_touch (xwidget_view_lookup(glyph->u.xwidget,
1273 w));
1280 for (i = 0; i < MAX_XWIDGETS; i++)
1282 struct xwidget_view* xv = &xwidget_views[i];
1284 //"touched" is only meaningful for the current window, so disregard other views
1285 if (xv->initialized && ( xv->w == w))
1287 if (xwidget_touched(xv))
1288 xwidget_show_view (xv);
1289 else
1290 xwidget_hide_view (xv);