cleanup
[emacs.git] / src / xwidget.c
blob780bc2105dc6e8197a667276b58e322c9fe77bca
1 #include <config.h>
2 #ifdef HAVE_XWIDGETS
4 #include <signal.h>
6 #include <stdio.h>
7 #include <setjmp.h>
8 #ifdef HAVE_X_WINDOWS
10 #include "lisp.h"
11 #include "blockinput.h"
12 #include "syssignal.h"
14 #include "xterm.h"
15 #include <X11/cursorfont.h>
17 #ifndef makedev
18 #include <sys/types.h>
19 #endif /* makedev */
21 #ifdef BSD_SYSTEM
22 #include <sys/ioctl.h>
23 #endif /* ! defined (BSD_SYSTEM) */
25 #include "systime.h"
27 #ifndef INCLUDED_FCNTL
28 #include <fcntl.h>
29 #endif
30 #include <ctype.h>
31 #include <errno.h>
32 #include <setjmp.h>
33 #include <sys/stat.h>
35 #include "charset.h"
36 #include "character.h"
37 #include "coding.h"
38 #include "ccl.h"
39 #include "frame.h"
40 #include "dispextern.h"
41 #include "fontset.h"
42 #include "termhooks.h"
43 #include "termopts.h"
44 #include "termchar.h"
45 #include "emacs-icon.h"
46 #include "disptab.h"
47 #include "buffer.h"
48 #include "window.h"
49 #include "keyboard.h"
50 #include "intervals.h"
51 #include "process.h"
52 #include "atimer.h"
53 #include "keymap.h"
56 #ifdef USE_X_TOOLKIT
57 #include <X11/Shell.h>
58 #endif
59 #include <X11/extensions/Xcomposite.h>
60 #include <X11/extensions/Xrender.h>
61 #include <cairo.h>
62 #ifdef HAVE_SYS_TIME_H
63 #include <sys/time.h>
64 #endif
65 #ifdef HAVE_UNISTD_H
66 #include <unistd.h>
67 #endif
69 #include "gtkutil.h"
70 #include "font.h"
71 #endif /* HAVE_X_WINDOWS */
73 #include <gtk/gtk.h>
74 #include <gdk/gdk.h>
76 #ifdef HAVE_GTK3
77 //for gtk3; sockets and plugs
78 #include <gtk/gtkx.h>
79 #include <gtk/gtkscrolledwindow.h>
80 #include "emacsgtkfixed.h"
81 #endif
83 #include <wchar.h>
85 #ifdef HAVE_WEBKIT_OSR
86 #include <webkit/webkitwebview.h>
87 #include <webkit/webkitwebplugindatabase.h>
88 #include <webkit/webkitwebplugin.h>
89 #include <webkit/webkitglobals.h>
90 #include <webkit/webkitwebnavigationaction.h>
91 #include <webkit/webkitdownload.h>
92 #include <webkit/webkitwebpolicydecision.h>
93 #endif
95 //for GIR
96 #include <girepository.h>
98 #include "xwidget.h"
100 //TODO embryo of lisp allocators for xwidgets
101 //TODO xwidget* should be Lisp_xwidget*
102 struct xwidget*
103 allocate_xwidget (void)
105 return ALLOCATE_PSEUDOVECTOR (struct xwidget, height, PVEC_XWIDGET);
108 //TODO xwidget_view* should be Lisp_xwidget_view*
109 struct xwidget_view*
110 allocate_xwidget_view (void)
112 return ALLOCATE_PSEUDOVECTOR (struct xwidget_view, redisplayed, PVEC_XWIDGET_VIEW);
114 #define XSETXWIDGET(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET))
115 #define XSETXWIDGET_VIEW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET_VIEW))
117 struct xwidget_view* xwidget_view_lookup(struct xwidget* xw, struct window *w);
118 Lisp_Object xwidget_spec_value ( Lisp_Object spec, Lisp_Object key, int *found);
119 gboolean offscreen_damage_event (GtkWidget *widget, GdkEvent *event, gpointer data);
120 void webkit_osr_document_load_finished_callback (WebKitWebView *webkitwebview,
121 WebKitWebFrame *arg1,
122 gpointer user_data);
123 gboolean webkit_osr_download_callback (WebKitWebView *webkitwebview,
124 WebKitDownload *arg1,
125 gpointer data);
127 gboolean webkit_osr_mime_type_policy_typedecision_requested_callback(WebKitWebView *webView,
128 WebKitWebFrame *frame,
129 WebKitNetworkRequest *request,
130 gchar *mimetype,
131 WebKitWebPolicyDecision *policy_decision,
132 gpointer user_data);
134 gboolean webkit_osr_new_window_policy_decision_requested_callback(WebKitWebView *webView,
135 WebKitWebFrame *frame,
136 WebKitNetworkRequest *request,
137 WebKitWebNavigationAction *navigation_action,
138 WebKitWebPolicyDecision *policy_decision,
139 gpointer user_data);
142 gboolean webkit_osr_navigation_policy_decision_requested_callback(WebKitWebView *webView,
143 WebKitWebFrame *frame,
144 WebKitNetworkRequest *request,
145 WebKitWebNavigationAction *navigation_action,
146 WebKitWebPolicyDecision *policy_decision,
147 gpointer user_data);
149 GtkWidget* xwgir_create(char* class, char* namespace);
153 static void
154 send_xembed_ready_event (struct xwidget* xw, int xembedid);
155 DEFUN ("make-xwidget", Fmake_xwidget, Smake_xwidget, 7, 8, 0,
156 doc: /* Make an xwidget from BEG to END of TYPE.
158 If BUFFER is nil it uses the current buffer. If BUFFER is a string and
159 no such buffer exists, it is created.
161 TYPE is a symbol which can take one of the following values:
162 - Button
163 - ToggleButton
164 - slider
165 - socket
166 - socket-osr
167 - cairo
170 (Lisp_Object beg, Lisp_Object end,
171 Lisp_Object type,
172 Lisp_Object title,
173 Lisp_Object width, Lisp_Object height,
174 Lisp_Object data,
175 Lisp_Object buffer)
177 //should work a bit like "make-button"(make-button BEG END &rest PROPERTIES)
178 // arg "type" and fwd should be keyword args eventually
179 //(make-xwidget 3 3 'button "oei" 31 31 nil)
180 //(xwidget-info (car xwidget-list))
181 struct xwidget* xw = allocate_xwidget();
182 Lisp_Object val;
183 xw->type = type;
184 xw->title = title;
185 if (NILP (buffer))
186 buffer = Fcurrent_buffer(); // no need to gcpro because Fcurrent_buffer doesn't call Feval/eval_sub.
187 else
188 buffer = Fget_buffer_create (buffer);
189 xw->buffer = buffer;
191 xw->height = XFASTINT(height);
192 xw->width = XFASTINT(width);
193 xw->kill_without_query = 0;
194 XSETXWIDGET (val, xw); // set the vectorlike_header of VAL with the correct value
195 Vxwidget_list = Fcons (val, Vxwidget_list);
196 xw->widgetwindow_osr = NULL;
197 xw->widget_osr = NULL;
198 xw->plist = Qnil;
203 #ifdef HAVE_WEBKIT_OSR
204 /* DIY mvc. widget is rendered offscreen,
205 later bitmap copied to the views.
207 if (EQ(xw->type, Qwebkit_osr)||
208 EQ(xw->type, Qsocket_osr)||
209 (!NILP (Fget(xw->type, QCxwgir_class)))) {
210 block_input();
211 xw->widgetwindow_osr = gtk_offscreen_window_new ();
212 gtk_window_resize(GTK_WINDOW(xw->widgetwindow_osr), xw->width, xw->height);
213 xw->widgetscrolledwindow_osr = NULL; //webkit osr is the only scrolled component atm
215 if (EQ(xw->type, Qwebkit_osr)){
216 xw->widgetscrolledwindow_osr = gtk_scrolled_window_new(NULL, NULL);
217 gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(xw->widgetscrolledwindow_osr ),xw->height);
218 gtk_scrolled_window_set_min_content_width(GTK_SCROLLED_WINDOW(xw->widgetscrolledwindow_osr ),xw->width);
219 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(xw->widgetscrolledwindow_osr ), GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS);
221 xw->widget_osr=webkit_web_view_new();
222 gtk_container_add(GTK_CONTAINER(xw->widgetscrolledwindow_osr ), GTK_WIDGET( WEBKIT_WEB_VIEW(xw->widget_osr)));
224 if(EQ(xw->type, Qsocket_osr))
225 xw->widget_osr = gtk_socket_new();
226 if(!NILP (Fget(xw->type, QCxwgir_class)))
227 xw->widget_osr = xwgir_create(SDATA(Fcar(Fcdr(Fget(xw->type, QCxwgir_class)))),
228 SDATA(Fcar(Fget(xw->type, QCxwgir_class))));
230 gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, xw->height);
232 if (EQ(xw->type, Qwebkit_osr)){
233 gtk_container_add (GTK_CONTAINER (xw->widgetwindow_osr), xw->widgetscrolledwindow_osr);
234 }else{
235 gtk_container_add (GTK_CONTAINER (xw->widgetwindow_osr), xw->widget_osr);
238 gtk_widget_show (xw->widget_osr);
239 gtk_widget_show (xw->widgetwindow_osr);
240 gtk_widget_show (xw->widgetscrolledwindow_osr);
242 /* store some xwidget data in the gtk widgets for convenient retrieval in the event handlers. */
243 g_object_set_data (G_OBJECT (xw->widget_osr), XG_XWIDGET, (gpointer) (xw));
244 g_object_set_data (G_OBJECT (xw->widgetwindow_osr), XG_XWIDGET, (gpointer) (xw));
246 /* signals */
247 if (EQ(xw->type, Qwebkit_osr)) {
248 g_signal_connect (G_OBJECT (xw->widget_osr),
249 "document-load-finished",
250 G_CALLBACK (webkit_osr_document_load_finished_callback),
251 xw);
253 g_signal_connect (G_OBJECT (xw->widget_osr),
254 "download-requested",
255 G_CALLBACK (webkit_osr_download_callback),
256 xw);
258 g_signal_connect (G_OBJECT (xw->widget_osr),
259 "mime-type-policy-decision-requested",
260 G_CALLBACK (webkit_osr_mime_type_policy_typedecision_requested_callback),
261 xw);
263 g_signal_connect (G_OBJECT (xw->widget_osr),
264 "new-window-policy-decision-requested",
265 G_CALLBACK (webkit_osr_new_window_policy_decision_requested_callback),
266 xw);
268 g_signal_connect (G_OBJECT (xw->widget_osr),
269 "navigation-policy-decision-requested",
270 G_CALLBACK (webkit_osr_navigation_policy_decision_requested_callback),
271 xw);
274 if (EQ(xw->type, Qsocket_osr)) {
275 send_xembed_ready_event (xw, gtk_socket_get_id (GTK_SOCKET (xw->widget_osr)));
276 //gtk_widget_realize(xw->widget);
280 unblock_input();
283 #endif /* HAVE_WEBKIT_OSR */
285 return val;
288 DEFUN ("get-buffer-xwidgets", Fget_buffer_xwidgets, Sget_buffer_xwidgets, 1, 1, 0,
289 doc: /* Return a list of xwidgets associated with BUFFER.
290 BUFFER may be a buffer or the name of one.
293 (Lisp_Object buffer)
295 Lisp_Object xw, tail, xw_list;
297 if (NILP (buffer)) return Qnil;
298 buffer = Fget_buffer (buffer);
299 if (NILP (buffer)) return Qnil;
301 xw_list = Qnil;
303 for (tail = Vxwidget_list; CONSP (tail); tail = XCDR (tail))
305 xw = XCAR (tail);
306 if (XWIDGETP (xw) && EQ (Fxwidget_buffer (xw), buffer))
307 xw_list = Fcons (xw, xw_list);
309 return xw_list;
313 xwidget_hidden(struct xwidget_view *xv)
315 return xv->hidden;
319 static void
320 buttonclick_handler (GtkWidget * widget, gpointer data)
322 Lisp_Object xwidget_view, xwidget;
323 XSETXWIDGET_VIEW (xwidget_view, (struct xwidget_view *) data);
324 xwidget = Fxwidget_view_model (xwidget_view);
326 struct input_event event;
327 Lisp_Object frame = Fwindow_frame (Fxwidget_view_window (xwidget_view));
328 struct frame *f = XFRAME (frame);
329 printf ("button clicked xw:%d '%s'\n", XXWIDGET (xwidget), XXWIDGET (xwidget)->title);
331 EVENT_INIT (event);
332 event.kind = XWIDGET_EVENT;
334 event.frame_or_window = frame;
336 event.arg = Qnil;
337 event.arg = Fcons (xwidget, event.arg);
338 event.arg = Fcons (intern ("buttonclick"), event.arg);
340 kbd_buffer_store_event (&event);
344 static void
345 send_xembed_ready_event (struct xwidget* xw, int xembedid)
347 Lisp_Object xw_lo;
348 XSETXWIDGET(xw_lo, xw);
349 struct input_event event;
350 EVENT_INIT (event);
351 event.kind = XWIDGET_EVENT;
352 event.frame_or_window = Qnil; //frame; //how to get the frame here? //TODO i store it in the xwidget now
354 event.arg = Qnil;
355 event.arg = Fcons (make_number (xembedid), event.arg);
356 event.arg = Fcons (xw_lo, event.arg);
357 event.arg = Fcons (intern ("xembed-ready"), event.arg);
360 kbd_buffer_store_event (&event);
364 void
365 xwidget_show_view (struct xwidget_view *xv)
367 xv->hidden = 0;
368 gtk_widget_show(xv->widgetwindow);
369 gtk_fixed_move (GTK_FIXED (xv->emacswindow), xv->widgetwindow, xv->x + xv->clip_left, xv->y + xv->clip_top); //TODO refactor
373 /* hide an xvidget view */
374 void
375 xwidget_hide_view (struct xwidget_view *xv)
377 xv->hidden = 1;
378 //gtk_widget_hide(xw->widgetwindow);
379 gtk_fixed_move (GTK_FIXED (xv->emacswindow), xv->widgetwindow,
380 10000, 10000);
384 void
385 xwidget_plug_added(GtkSocket *socket,
386 gpointer user_data)
388 //hmm this doesnt seem to get called for foreign windows
389 printf("xwidget_plug_added\n");
392 gboolean
393 xwidget_plug_removed(GtkSocket *socket,
394 gpointer user_data)
396 printf("xwidget_plug_removed\n");
397 return TRUE; /* dont run the default handler because that kills the socket and we want to reuse it*/
401 void
402 xwidget_slider_changed (GtkRange *range,
403 gpointer user_data)
405 //slider value changed. change value of siblings
406 //correspondingly. but remember that changing value will again
407 //trigger signal
409 //TODO MVC view storage wont be an array futureish so the loop needs to change eventually
410 //TODO MVC it would be nice if this code could be reusable but, alas, C is not a functional language
411 //issues are:
412 // - the type of the controllers value (double, boolean etc)
413 // - the getter and setter (but they can be func pointers)
414 // a behemoth macro is always an option.
415 double v=gtk_range_get_value(range);
416 struct xwidget_view* xvp = g_object_get_data (G_OBJECT (range), XG_XWIDGET_VIEW);
417 struct xwidget_view* xv;
419 printf("slider changed val:%f\n", v);
421 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail))
423 if (XWIDGET_VIEW_P (XCAR (tail))) {
424 xv = XXWIDGET_VIEW (XCAR (tail));
425 if (EQ (xvp->model, xv->model)) {
426 //block sibling views signal handlers
427 g_signal_handler_block(xv->widget, xv->handler_id);
429 //set values of sibling views and unblock
430 gtk_range_set_value(GTK_RANGE(xv->widget), v);
431 g_signal_handler_unblock(xv->widget,xv->handler_id);
438 /* when the off-screen webkit master view changes this signal is called.
439 it copies the bitmap from the off-screen webkit instance */
440 gboolean
441 offscreen_damage_event (GtkWidget *widget, GdkEvent *event, gpointer data)
443 //TODO this is wrong! should just queu a redraw of onscreen widget
444 gtk_widget_queue_draw (GTK_WIDGET (data));
445 return FALSE;
448 void
449 store_xwidget_event_string(struct xwidget* xw, char* eventname, const char* eventstr)
451 //refactor attempt
452 struct input_event event;
453 Lisp_Object xwl;
454 XSETXWIDGET(xwl,xw);
455 EVENT_INIT (event);
456 event.kind = XWIDGET_EVENT;
457 event.frame_or_window = Qnil; //frame; //how to get the frame here? //TODO i store it in the xwidget now
459 event.arg = Qnil;
460 event.arg = Fcons (build_string(eventstr), event.arg); //string so dont intern
461 event.arg = Fcons (xwl, event.arg); //TODO
462 event.arg = Fcons (intern (eventname), event.arg);//interning should be ok
463 kbd_buffer_store_event (&event);
467 //TODO deprecated, use load-status
468 void
469 webkit_osr_document_load_finished_callback (WebKitWebView *webkitwebview,
470 WebKitWebFrame *arg1,
471 gpointer data)
473 //TODO this event sending code should be refactored
474 // struct xwidget *xw = (struct xwidget *) data;
475 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (webkitwebview), XG_XWIDGET);
476 printf("webkit finished loading\n");
478 store_xwidget_event_string(xw,
479 "document-load-finished", "");
482 gboolean
483 webkit_osr_download_callback (WebKitWebView *webkitwebview,
484 WebKitDownload *arg1,
485 gpointer data)
487 //TODO this event sending code should be refactored
488 struct input_event event;
489 // struct xwidget *xw = (struct xwidget *) data;
490 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (webkitwebview), XG_XWIDGET);
491 printf("download requested %s\n", webkit_download_get_uri (arg1));
494 printf("webkit finished loading\n");
496 store_xwidget_event_string(xw, "download-requested", webkit_download_get_uri (arg1));
498 return FALSE;
501 gboolean
502 webkit_osr_mime_type_policy_typedecision_requested_callback(WebKitWebView *webView,
503 WebKitWebFrame *frame,
504 WebKitNetworkRequest *request,
505 gchar *mimetype,
506 WebKitWebPolicyDecision *policy_decision,
507 gpointer user_data)
509 printf("mime policy requested\n");
510 // this function makes webkit send a download signal for all unknown mime types
511 // TODO defer the decision to lisp, so that its possible to make Emacs handle text mime for instance
512 if(!webkit_web_view_can_show_mime_type(webView, mimetype)){
513 webkit_web_policy_decision_download (policy_decision);
514 return TRUE;
515 }else{
516 return FALSE;
521 gboolean
522 webkit_osr_new_window_policy_decision_requested_callback(WebKitWebView *webView,
523 WebKitWebFrame *frame,
524 WebKitNetworkRequest *request,
525 WebKitWebNavigationAction *navigation_action,
526 WebKitWebPolicyDecision *policy_decision,
527 gpointer user_data)
529 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (webView), XG_XWIDGET);
530 printf("webkit_osr_new_window_policy_decision_requested_callback %s\n",
531 webkit_web_navigation_action_get_original_uri (navigation_action));
533 store_xwidget_event_string(xw, "new-window-policy-decision-requested", webkit_web_navigation_action_get_original_uri (navigation_action)
535 return FALSE;
538 gboolean
539 webkit_osr_navigation_policy_decision_requested_callback(WebKitWebView *webView,
540 WebKitWebFrame *frame,
541 WebKitNetworkRequest *request,
542 WebKitWebNavigationAction *navigation_action,
543 WebKitWebPolicyDecision *policy_decision,
544 gpointer user_data)
546 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (webView), XG_XWIDGET);
547 printf("webkit_osr_navigation_policy_decision_requested_callback %s\n",
548 webkit_web_navigation_action_get_original_uri (navigation_action));
549 store_xwidget_event_string(xw, "navigation-policy-decision-requested", webkit_web_navigation_action_get_original_uri (navigation_action)
551 return FALSE;
554 //for gtk3 offscreen rendered widgets
555 gboolean
556 xwidget_osr_draw_callback (GtkWidget *widget, cairo_t *cr, gpointer data)
558 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
559 struct xwidget_view* xv = (struct xwidget_view*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET_VIEW);
561 cairo_rectangle(cr, 0,0, xv->clip_right, xv->clip_bottom);//xw->width, xw->height);
562 cairo_clip(cr);
565 if(xw->widgetscrolledwindow_osr != NULL)
566 gtk_widget_draw (xw->widgetscrolledwindow_osr, cr);
567 else
568 gtk_widget_draw (xw->widget_osr, cr);
569 return FALSE;
572 GtkWidget* xwgir_create_debug;
576 gboolean
577 xwidget_osr_event_forward (GtkWidget *widget,
578 GdkEvent *event,
579 gpointer user_data)
581 /* copy events that arrive at the outer widget to the offscreen widget */
582 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
583 GdkEvent* eventcopy = gdk_event_copy(event);
584 eventcopy->any.window = gtk_widget_get_window(xw->widget_osr);// works
586 /* printf("xwidget_osr_event_forward redirect event to window:%d\n", ((GdkEventAny*)eventcopy)->window); */
587 /* printf("A type:%d x:%f y:%f \n", event->type, event->button.x, event->button.y); */
588 /* printf("B type:%d x:%f y:%f \n", eventcopy->type, eventcopy->button.x, eventcopy->button.y); */
589 //gtk_button_get_event_window(xwgir_create_debug);
590 gtk_main_do_event(eventcopy); //TODO this will leak events. they should be deallocated later, perhaps in xwgir_event_callback
591 return TRUE; //dont propagate this event furter
594 GIRepository *girepository ;
596 DEFUN ("xwgir-require-namespace", Fxwgir_require_namespace, Sxwgir_require_namespace, 2,2,0,
597 doc: /* Require a GObject Introspection namespace.
598 This must be done for all namespaces we want to use, before using other xwgir functions.*/)
599 (Lisp_Object lnamespace, Lisp_Object lnamespace_version)
601 char* namespace = SDATA(lnamespace);
602 char* namespace_version = SDATA(lnamespace_version);
603 GError *error = NULL;
605 girepository = g_irepository_get_default();
606 g_irepository_require(girepository, namespace, namespace_version, 0, &error);
607 if (error) {
608 g_error("ERROR: %s\n", error->message);
609 return Qnil;
611 return Qt;
614 GtkWidget* xwgir_create(char* class, char* namespace){
615 //TODO this is more or less the same as xwgir-call-method, so should be refactored
616 //create a gtk widget, given its name
617 //find the constructor
618 //call it
619 //also figure out how to pass args
621 GError *error = NULL;
622 GIArgument return_value;
624 GIObjectInfo* obj_info = g_irepository_find_by_name(girepository, namespace, class);
625 GIFunctionInfo* f_info = g_object_info_find_method (obj_info, "new");
626 g_function_info_invoke(f_info,
627 NULL, 0,
628 NULL, 0,
629 &return_value,
630 NULL);
631 xwgir_create_debug = return_value.v_pointer;
632 return return_value.v_pointer;
637 xwgir_convert_lisp_to_gir_arg(GIArgument* giarg,
638 GIArgInfo* arginfo,
639 Lisp_Object lisparg )
642 GITypeTag tag;
643 gboolean is_pointer;
644 gboolean is_enum;
645 tag = g_type_info_get_tag (g_arg_info_get_type (arginfo));
647 switch (tag)
649 case GI_TYPE_TAG_BOOLEAN:
650 giarg->v_boolean = XFASTINT(lisparg);
651 break;
652 case GI_TYPE_TAG_INT8:
653 giarg->v_int8 = XFASTINT(lisparg);
654 break;
655 case GI_TYPE_TAG_UINT8:
656 giarg->v_uint8 = XFASTINT(lisparg);
657 break;
658 case GI_TYPE_TAG_INT16:
659 giarg->v_int16 = XFASTINT(lisparg);
660 break;
661 case GI_TYPE_TAG_UINT16:
662 giarg->v_uint16 = XFASTINT(lisparg);
663 break;
664 case GI_TYPE_TAG_INT32:
665 giarg->v_int32 = XFASTINT(lisparg);
666 break;
667 case GI_TYPE_TAG_UINT32:
668 giarg->v_uint32 = XFASTINT(lisparg);
669 break;
671 case GI_TYPE_TAG_INT64:
672 giarg->v_int64 = XFASTINT(lisparg);
673 break;
674 case GI_TYPE_TAG_UINT64:
675 giarg->v_uint64 = XFASTINT(lisparg);
676 break;
679 case GI_TYPE_TAG_FLOAT:
680 giarg->v_float = XFLOAT_DATA(lisparg);
681 break;
683 case GI_TYPE_TAG_DOUBLE:
684 giarg->v_double = XFLOAT_DATA(lisparg);
685 break;
687 case GI_TYPE_TAG_UTF8:
688 case GI_TYPE_TAG_FILENAME:
689 //giarg->v_string = SDATA(lisparg);
690 giarg->v_pointer = SDATA(lisparg);
691 break;
693 case GI_TYPE_TAG_ARRAY:
694 case GI_TYPE_TAG_GLIST:
695 case GI_TYPE_TAG_GSLIST:
696 case GI_TYPE_TAG_GHASH:
697 case GI_TYPE_TAG_ERROR:
698 case GI_TYPE_TAG_INTERFACE:
699 case GI_TYPE_TAG_VOID:
700 case GI_TYPE_TAG_UNICHAR:
701 case GI_TYPE_TAG_GTYPE:
702 //?? i dont know how to handle these yet TODO
703 printf("failed in my lisp to gir arg conversion duties. sob!\n");
704 return -1;
705 break;
707 return 0;
710 #if 0
711 void
712 refactor_attempt(){
713 //this methhod should be called from xwgir-xwidget-call-method and from xwgir xwidget construction
714 char* class = SDATA(Fcar(Fcdr(Fget(xw->type, QCxwgir_class))));
716 GIObjectInfo* obj_info = g_irepository_find_by_name(girepository, namespace, class);
717 GIFunctionInfo* f_info = g_object_info_find_method (obj_info, SDATA(method));
719 //loop over args, convert from lisp to primitive type, given arg introspection data
720 //TODO g_callable_info_get_n_args(f_info) should match
721 int argscount = XFASTINT(Flength(arguments));
722 if(argscount != g_callable_info_get_n_args(f_info)){
723 printf("xwgir call method arg count doesn match! \n");
724 return Qnil;
726 int i;
727 for (i = 1; i < argscount + 1; ++i)
729 xwgir_convert_lisp_to_gir_arg(&in_args[i], g_callable_info_get_arg(f_info, i - 1), Fnth(i - 1, arguments));
732 in_args[0].v_pointer = widget;
733 if(g_function_info_invoke(f_info,
734 in_args, argscount + 1,
735 NULL, 0,
736 &return_value,
737 &error)) {
738 //g_error("ERROR: %s\n", error->message);
739 printf("invokation error\n");
740 return Qnil;
742 return Qt;
744 #endif /* 0 */
746 DEFUN ("xwgir-xwidget-call-method", Fxwgir_xwidget_call_method, Sxwgir_xwidget_call_method, 3, 3, 0,
747 doc: /* Call Xwidget object method using GObject Introspection.
748 XWIDGET is the xwidget instance to act upon.
749 METHOD is the Gobject intrsopsection method name.
750 ARGUMENTS is a list of arguments for the call. They will be converted to GObject types from Lisp types.
752 (Lisp_Object xwidget, Lisp_Object method, Lisp_Object arguments)
754 CHECK_XWIDGET (xwidget);
755 GError *error = NULL;
756 GIArgument return_value;
757 GIArgument in_args[20];
760 struct xwidget* xw;
761 if (NILP (xwidget)) { printf("ERROR xwidget nil\n"); return Qnil; };
762 xw = XXWIDGET(xwidget);
763 if(NULL == xw) printf("ERROR xw is 0\n");
764 char* namespace = SDATA(Fcar(Fget(xw->type, QCxwgir_class)));
765 //we need the concrete widget, which happens in 2 ways depending on OSR or not TODO
766 GtkWidget* widget = NULL;
767 if(NULL == xw->widget_osr) {
768 widget = xwidget_view_lookup (xw, XWINDOW(FRAME_SELECTED_WINDOW (SELECTED_FRAME ()))) -> widget;
769 } else {
770 widget = xw->widget_osr;
773 //char* class = SDATA(SYMBOL_NAME(xw->type)); //this works but is unflexible
774 //figure out the class from the widget instead
775 /* printf("type class: %s %s\n", G_OBJECT_TYPE_NAME(widget), G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(widget))); */
776 /* char* class = G_OBJECT_TYPE_NAME(widget); //gives "GtkButton"(I want "Button") */
777 /* class += strlen(namespace); //TODO check for corresponding api method. but this seems to work. */
779 char* class = SDATA(Fcar(Fcdr(Fget(xw->type, QCxwgir_class))));
781 GIObjectInfo* obj_info = g_irepository_find_by_name(girepository, namespace, class);
782 GIFunctionInfo* f_info = g_object_info_find_method (obj_info, SDATA(method));
784 //loop over args, convert from lisp to primitive type, given arg introspection data
785 //TODO g_callable_info_get_n_args(f_info) should match
786 int argscount = XFASTINT(Flength(arguments));
787 if(argscount != g_callable_info_get_n_args(f_info)){
788 printf("xwgir call method arg count doesn match! \n");
789 return Qnil;
791 int i;
792 Lisp_Object n;
793 for (i = 1; i < argscount + 1; ++i)
795 XSETFASTINT (n, i - 1);
796 xwgir_convert_lisp_to_gir_arg(&in_args[i], g_callable_info_get_arg(f_info, i - 1), Fnth(n, arguments));
799 in_args[0].v_pointer = widget;
800 if(g_function_info_invoke(f_info,
801 in_args, argscount + 1,
802 NULL, 0,
803 &return_value,
804 &error)) {
805 //g_error("ERROR: %s\n", error->message);
806 printf("invokation error\n");
807 return Qnil;
809 return Qt;
812 void
813 to_child (GtkWidget *bin,
814 double widget_x,
815 double widget_y,
816 double *x_out,
817 double *y_out)
819 *x_out = widget_x;
820 *y_out = widget_y;
824 GdkWindow *
825 offscreen_pick_embedded_child (GdkWindow *window,
826 double x,
827 double y,
828 gpointer *data)
830 //in this simple case we assume the window contains a single widget. easy.
831 //but then we get the problem that the widget cant be embedded in several windows
832 return gtk_widget_get_window (GTK_WIDGET (data));
835 void
836 offscreen_to_embedder (GdkWindow *window,
837 gdouble offscreen_x,
838 gdouble offscreen_y,
839 gpointer embedder_x,
840 gpointer embedder_y,
841 gpointer data)
843 * (gdouble *) embedder_x = offscreen_x;
844 * (gdouble *) embedder_y = offscreen_y;
847 void
848 offscreen_from_embedder (GdkWindow *window,
849 gdouble embedder_x,
850 gdouble embedder_y,
851 gpointer offscreen_x,
852 gpointer offscreen_y,
853 gpointer user_data)
855 * (gdouble *) offscreen_x = embedder_x;
856 * (gdouble *) offscreen_y = embedder_y;
859 gboolean
860 xwidget_osr_event_set_embedder (GtkWidget *widget,
861 GdkEvent *event,
862 gpointer data)
864 struct xwidget_view *xv = (struct xwidget_view *) data;
865 struct xwidget *xww = XXWIDGET (xv->model);
866 printf("gdk_offscreen_window_set_embedder %d %d\n",
867 GDK_IS_WINDOW(gtk_widget_get_window (xww->widget_osr)),
868 GDK_IS_WINDOW(gtk_widget_get_window (GTK_WIDGET (xv->widget))));
869 gdk_offscreen_window_set_embedder (gtk_widget_get_window (xww->widgetwindow_osr),
870 gtk_widget_get_window (xv->widget));
874 /* initializes and does initial placement of an xwidget view on screen */
875 struct xwidget_view*
876 xwidget_init_view (struct xwidget *xww,
877 struct glyph_string *s,
878 int x, int y)
880 struct xwidget_view *xv = allocate_xwidget_view();
881 Lisp_Object val;
882 GdkColor color;
884 XSETXWIDGET_VIEW (val, xv) ;
885 Vxwidget_view_list = Fcons (val, Vxwidget_view_list);
887 XSETWINDOW(xv->w, s->w);
888 XSETXWIDGET(xv->model, xww);
890 //widget creation
891 if(EQ(xww->type, Qbutton))
893 xv->widget = gtk_button_new_with_label (XSTRING(xww->title)->data);
894 g_signal_connect (G_OBJECT (xv->widget), "clicked",
895 G_CALLBACK (buttonclick_handler), xv); // the view rather than the model
896 } else if (EQ(xww->type, Qtoggle)) {
897 xv->widget = gtk_toggle_button_new_with_label (XSTRING(xww->title)->data);
898 //xv->widget = gtk_entry_new ();//temp hack to experiment with key propagation TODO entry widget is useful for testing
899 } else if (EQ(xww->type, Qsocket)) {
900 xv->widget = gtk_socket_new ();
901 g_signal_connect_after(xv->widget, "plug-added", G_CALLBACK(xwidget_plug_added), "plug added");
902 g_signal_connect_after(xv->widget, "plug-removed", G_CALLBACK(xwidget_plug_removed), "plug removed");
903 //TODO these doesnt help
904 gtk_widget_add_events(xv->widget, GDK_KEY_PRESS);
905 gtk_widget_add_events(xv->widget, GDK_KEY_RELEASE);
906 } else if (EQ(xww->type, Qslider)) {
907 xv->widget =
908 //gtk_hscale_new (GTK_ADJUSTMENT(gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 10.0, 10.0)));
909 gtk_hscale_new_with_range ( 0.0, 100.0, 10.0);
910 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
911 xv->handler_id = g_signal_connect_after(xv->widget, "value-changed", G_CALLBACK(xwidget_slider_changed), "slider changed");
912 } else if (EQ(xww->type, Qcairo)) {
913 //Cairo view
914 //uhm cairo is differentish in gtk 3.
915 //gdk_cairo_create (gtk_widget_get_window (FRAME_GTK_WIDGET (s->f)));
916 xv->widget = gtk_drawing_area_new();
917 g_signal_connect (G_OBJECT ( xv->widget), "draw",
918 G_CALLBACK (xwidget_osr_draw_callback), NULL);
920 } else if (EQ(xww->type, Qwebkit_osr)||
921 EQ(xww->type, Qsocket_osr)||
922 (!NILP (Fget(xww->type, QCxwgir_class))))//xwgir widgets are OSR
924 printf("osr init:%s\n",SDATA(SYMBOL_NAME(xww->type)));
925 xv->widget = gtk_drawing_area_new();
926 gtk_widget_set_app_paintable ( xv->widget, TRUE); //because expose event handling
927 gtk_widget_add_events(xv->widget, GDK_ALL_EVENTS_MASK);
929 /* Draw the view on damage-event */
930 g_signal_connect (G_OBJECT (xww->widgetwindow_osr), "damage-event",
931 G_CALLBACK (offscreen_damage_event), xv->widget);
933 if (EQ(xww->type, Qwebkit_osr)){
934 /* ///xwgir debug */
935 /* //forward events. this isnt compatible with the set_embedded strategy */
936 g_signal_connect (G_OBJECT ( xv->widget), "button-press-event",
937 G_CALLBACK (xwidget_osr_event_forward), NULL);
938 g_signal_connect (G_OBJECT ( xv->widget), "button-release-event",
939 G_CALLBACK (xwidget_osr_event_forward), NULL);
940 g_signal_connect (G_OBJECT ( xv->widget), "motion-notify-event",
941 G_CALLBACK (xwidget_osr_event_forward), NULL);
942 }else{
943 //xwgir debug , orthogonal to forwarding
944 g_signal_connect (G_OBJECT (xv->widget), "enter-notify-event",
945 G_CALLBACK (xwidget_osr_event_set_embedder), xv);
948 //draw
949 g_signal_connect (G_OBJECT (xv->widget), "draw",
950 G_CALLBACK (xwidget_osr_draw_callback), NULL);
953 //else return NULL;
955 //widget realization
956 //make container widget 1st, and put the actual widget inside the container
957 //later, drawing should crop container window if necessary to handle case where xwidget
958 //is partially obscured by other emacs windows
959 //other containers than gtk_fixed where explored, but gtk_fixed had the most predictable behaviour so far.
960 xv->emacswindow = FRAME_GTK_WIDGET (s->f);
961 xv->widgetwindow = gtk_fixed_new ();
962 gtk_widget_set_has_window(xv->widgetwindow, TRUE);
963 gtk_container_add (GTK_CONTAINER (xv->widgetwindow), xv->widget);
965 //store some xwidget data in the gtk widgets
966 g_object_set_data (G_OBJECT (xv->widget), XG_FRAME_DATA, (gpointer) (s->f)); //the emacs frame
967 g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET, (gpointer) (xww)); //the xwidget
968 g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET_VIEW, (gpointer) (xv)); //the xwidget
969 g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET, (gpointer) (xww)); //the xwidget window
970 g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET_VIEW, (gpointer) (xv)); //the xwidget window
973 gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xww->width, xww->height);
974 gtk_widget_set_size_request (xv->widgetwindow, xww->width, xww->height);
975 gtk_fixed_put (GTK_FIXED (FRAME_GTK_WIDGET (s->f)), xv->widgetwindow, x, y);
976 xv->x = x; xv->y = y;
977 gtk_widget_show_all (xv->widgetwindow);
981 //widgettype specific initialization only possible after realization
982 if (EQ(xww->type, Qsocket)) {
983 printf ("xwid:%d socket id:%x %d\n",
984 xww,
985 gtk_socket_get_id (GTK_SOCKET (xv->widget)),
986 gtk_socket_get_id (GTK_SOCKET (xv->widget)));
987 send_xembed_ready_event (xww,
988 gtk_socket_get_id (GTK_SOCKET (xv->widget)));
989 //gtk_widget_realize(xw->widget);
992 //////////////////////////////////////////////////////////////
993 // xwgir debug
994 if (//EQ(xww->type, Qwebkit_osr)|| //TODO should be able to choose compile time which method to use with webkit
995 EQ(xww->type, Qsocket_osr)||
996 (!NILP (Fget(xww->type, QCxwgir_class))))//xwgir widgets are OSR
998 printf("gdk_offscreen_window_set_embedder %d %d\n",
999 GDK_IS_WINDOW(gtk_widget_get_window (xww->widget_osr)),
1000 GDK_IS_WINDOW(gtk_widget_get_window (GTK_WIDGET (xv->widget))));
1001 // set_embedder needs to be called after xv->widget realization
1002 gdk_offscreen_window_set_embedder (gtk_widget_get_window (xww->widgetwindow_osr),
1003 gtk_widget_get_window (xv->widget));
1004 g_signal_connect (gtk_widget_get_window (xv->widget), "pick-embedded-child",
1005 G_CALLBACK (offscreen_pick_embedded_child), xww->widgetwindow_osr);
1007 g_signal_connect (gtk_widget_get_window (xww->widgetwindow_osr), "from-embedder",
1008 G_CALLBACK (offscreen_from_embedder), NULL);
1009 g_signal_connect (gtk_widget_get_window (xww->widgetwindow_osr), "to-embedder",
1010 G_CALLBACK (offscreen_to_embedder), NULL);
1012 ////////////////////////////////////////
1014 return xv;
1018 void
1019 x_draw_xwidget_glyph_string (struct glyph_string *s)
1022 this method is called by the redisplay engine and places the xwidget on screen.
1023 moving and clipping is done here. also view init.
1026 int box_line_hwidth = eabs (s->face->box_line_width);
1027 int box_line_vwidth = max (s->face->box_line_width, 0);
1028 int height = s->height;
1029 struct xwidget *xww = s->xwidget;
1030 struct xwidget_view *xv = xwidget_view_lookup(xww, s->w);
1031 int clip_right; int clip_bottom; int clip_top; int clip_left;
1033 int x = s->x;
1034 int y = s->y + (s->height / 2) - (xww->height / 2);
1035 int moved=0;
1037 /* We do it here in the display loop because there is no other
1038 time to know things like window placement etc.
1040 printf ("xv init for xw %d\n", xww);
1041 xv = xwidget_init_view (xww, s, x, y);
1043 //calculate clipping, which is used for all manner of onscreen xwidget views
1044 //each widget border can get clipped by other emacs objects so there are four clipping variables
1045 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));
1046 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));
1048 clip_bottom = min (xww->height, WINDOW_BOTTOM_EDGE_Y (s->w) - WINDOW_MODE_LINE_HEIGHT (s->w) - y);
1049 clip_top = max(0, WINDOW_TOP_EDGE_Y(s->w) -y );
1051 //we are conserned with movement of the onscreen area. the area might sit still when the widget actually moves
1052 //this happens when an emacs window border moves across a widget window
1053 //so, if any corner of the outer widget clippng window moves, that counts as movement here, even
1054 //if it looks like no movement happens because the widget sits still inside the clipping area.
1055 //the widget can also move inside the clipping area, which happens later
1056 moved = (xv->x + xv->clip_left != x+clip_left)
1057 || ((xv->y + xv->clip_top)!= (y+clip_top));
1058 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);
1059 else
1060 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);
1061 xv->x = x;
1062 xv->y = y;
1063 if (moved) //has it moved?
1065 if (1)//!xwidget_hidden(xv)) //hidden equals not being seen during redisplay
1067 //TODO should be possible to use xwidget_show_view here
1068 gtk_fixed_move (GTK_FIXED (FRAME_GTK_WIDGET (s->f)),
1069 xv->widgetwindow,
1070 x + clip_left, y + clip_top);
1073 //clip the widget window if some parts happen to be outside drawable area
1074 //an emacs window is not a gtk window, a gtk window covers the entire frame
1075 //cliping might have changed even if we havent actualy moved, we try figure out when we need to reclip for real
1076 if((xv->clip_right != clip_right)
1077 || (xv->clip_bottom != clip_bottom)
1078 || (xv->clip_top != clip_top)
1079 || (xv->clip_left != clip_left)){
1080 gtk_widget_set_size_request (xv->widgetwindow, clip_right + clip_left, clip_bottom + clip_top);
1081 gtk_fixed_move(GTK_FIXED(xv->widgetwindow), xv->widget, -clip_left, -clip_top);
1082 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);
1085 xv->clip_right = clip_right; xv->clip_bottom = clip_bottom; xv->clip_top = clip_top;xv->clip_left = clip_left;
1087 //if emacs wants to repaint the area where the widget lives, queue a redraw
1088 //TODO it seems its possible to get out of sync with emacs redraws so emacs bg sometimes shows up instead of xwidget
1089 //its just a visual glitch though
1090 if (!xwidget_hidden(xv)){
1091 gtk_widget_queue_draw (xv->widgetwindow);
1092 gtk_widget_queue_draw (xv->widget);
1097 #ifdef HAVE_WEBKIT_OSR
1099 //FUGLY macro that checks WEBKIT_IS_WEB_VIEW(xw->widget_osr) first
1100 #define WEBKIT_FN_INIT() \
1101 struct xwidget* xw; \
1102 CHECK_XWIDGET (xwidget); \
1103 if(NILP (xwidget)) {printf("ERROR xwidget nil\n"); return Qnil;}; \
1104 xw = XXWIDGET(xwidget); \
1105 if(NULL == xw) printf("ERROR xw is 0\n"); \
1106 if((NULL == xw->widget_osr) || !WEBKIT_IS_WEB_VIEW(xw->widget_osr)){ \
1107 printf("ERROR xw->widget_osr does not hold a webkit instance\n");\
1108 return Qnil;\
1112 DEFUN ("xwidget-webkit-goto-uri", Fxwidget_webkit_goto_uri, Sxwidget_webkit_goto_uri,
1113 2, 2, 0,
1114 doc: /* Make the webkit instance referenced by XWIDGET browse URI. */)
1115 (Lisp_Object xwidget, Lisp_Object uri)
1117 WEBKIT_FN_INIT();
1118 CHECK_STRING(uri);
1119 webkit_web_view_load_uri ( WEBKIT_WEB_VIEW(xw->widget_osr), SDATA(uri));
1120 return Qnil;
1124 DEFUN ("xwidget-webkit-execute-script", Fxwidget_webkit_execute_script, Sxwidget_webkit_execute_script,
1125 2, 2, 0,
1126 doc: /* webkit exec js.*/)
1127 (Lisp_Object xwidget, Lisp_Object script)
1129 WEBKIT_FN_INIT();
1130 CHECK_STRING(script);
1131 webkit_web_view_execute_script( WEBKIT_WEB_VIEW(xw->widget_osr), SDATA(script));
1132 return Qnil;
1135 DEFUN ("xwidget-webkit-get-title", Fxwidget_webkit_get_title, Sxwidget_webkit_get_title,
1136 1, 1, 0,
1137 doc: /* Get the title from the Webkit instance in XWIDGET.
1138 This can be used to work around the lack of a return value from the exec method.
1140 (Lisp_Object xwidget)
1142 //TODO support multibyte strings
1143 WEBKIT_FN_INIT();
1144 const gchar* str=webkit_web_view_get_title( WEBKIT_WEB_VIEW(xw->widget_osr));
1145 //return make_string_from_bytes(str, wcslen((const wchar_t *)str), strlen(str));
1146 if(str == 0){
1147 //TODO maybe return Qnil instead. I suppose webkit returns nullpointer when doc is not properly loaded or something
1148 printf("xwidget-webkit-get-title null webkit title\n");
1149 return build_string("");
1151 return build_string(str);
1154 //TODO missnamed
1155 DEFUN ("xwidget-disable-plugin-for-mime", Fxwidget_disable_plugin_for_mime , Sxwidget_disable_plugin_for_mime,
1156 1,1,0, doc: /* */)
1157 (Lisp_Object mime)
1159 WebKitWebPlugin *wp = webkit_web_plugin_database_get_plugin_for_mimetype
1160 (webkit_get_web_plugin_database(), SDATA(mime));
1161 if(wp == NULL) return Qnil;
1162 if(webkit_web_plugin_get_enabled (wp)){
1163 webkit_web_plugin_set_enabled (wp, FALSE);
1164 return Qt;
1166 return Qnil;
1170 void
1171 xwidget_webkit_dom_dump(WebKitDOMNode* parent)
1173 WebKitDOMNodeList* list;
1174 int i;
1175 int length;
1176 WebKitDOMNode* attribute;
1177 WebKitDOMNamedNodeMap* attrs;
1178 WebKitDOMNode* child;
1179 printf("node:%d type:%d name:%s content:%s\n",
1180 parent,
1181 webkit_dom_node_get_node_type(parent),//1 element 3 text 8 comment 2 attribute
1182 webkit_dom_node_get_local_name(parent),
1183 webkit_dom_node_get_text_content(parent));
1185 if(webkit_dom_node_has_attributes(parent)){
1186 attrs = webkit_dom_node_get_attributes(parent);
1188 length = webkit_dom_named_node_map_get_length(attrs);
1189 for (int i = 0; i < length; i++) {
1190 attribute = webkit_dom_named_node_map_item(attrs,i);
1191 printf(" attr node:%d type:%d name:%s content:%s\n",
1192 attribute,
1193 webkit_dom_node_get_node_type(attribute),//1 element 3 text 8 comment
1194 webkit_dom_node_get_local_name(attribute),
1195 webkit_dom_node_get_text_content(attribute));
1198 list = webkit_dom_node_get_child_nodes(parent);
1199 length = webkit_dom_node_list_get_length(list);
1201 for (int i = 0; i < length; i++) {
1202 child = webkit_dom_node_list_item(list, i);
1203 //if(webkit_dom_node_has_child_nodes(child))
1204 xwidget_webkit_dom_dump(child);
1209 DEFUN ("xwidget-webkit-dom-dump", Fxwidget_webkit_dom_dump, Sxwidget_webkit_dom_dump,
1210 1, 1, 0,
1211 doc: /*Dump the DOM contained in the webkit instance in XWIDGET.*/)
1212 (Lisp_Object xwidget)
1214 WEBKIT_FN_INIT();
1215 xwidget_webkit_dom_dump(WEBKIT_DOM_NODE(webkit_web_view_get_dom_document( WEBKIT_WEB_VIEW(xw->widget_osr))));
1216 return Qnil;
1221 #endif /* HAVE_WEBKIT_OSR */
1225 DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 3, 3, 0, doc:
1226 /* Resize XWIDGET.
1227 NEW_WIDTH NEW_HEIGHT defines the new size.)
1229 (Lisp_Object xwidget, Lisp_Object new_width, Lisp_Object new_height)
1231 CHECK_XWIDGET (xwidget);
1232 struct xwidget* xw = XXWIDGET(xwidget);
1233 struct xwidget_view *xv;
1234 int w, h;
1236 CHECK_NUMBER (new_width);
1237 CHECK_NUMBER (new_height);
1238 w = XFASTINT (new_width);
1239 h = XFASTINT (new_height);
1242 printf("resize xwidget %d (%d,%d)->(%d,%d)\n",xw, xw->width,xw->height,w,h);
1243 xw->width=w;
1244 xw->height=h;
1245 //if theres a osr resize it 1st
1246 if(xw->widget_osr){
1247 printf("resize xwidget_osr\n");
1248 //gtk_container_set_resize_mode ( GTK_WINDOW(xw->widgetwindow_osr), GTK_RESIZE_QUEUE);
1249 //gtk_container_set_resize_mode ( GTK_WINDOW(xw->widget_osr), GTK_RESIZE_QUEUE);
1252 //gtk_layout_set_size (GTK_LAYOUT (xw->widgetwindow_osr), xw->width, xw->height);
1253 gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, xw->height); //minimum size
1254 //gtk_window_resize( GTK_WINDOW(xw->widget_osr), xw->width, xw->height);
1255 gtk_window_resize( GTK_WINDOW(xw->widgetwindow_osr), xw->width, xw->height);
1256 gtk_window_resize( GTK_WINDOW(xw->widgetscrolledwindow_osr), xw->width, xw->height);
1257 gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(xw->widgetscrolledwindow_osr ),xw->height);
1258 gtk_scrolled_window_set_min_content_width(GTK_SCROLLED_WINDOW(xw->widgetscrolledwindow_osr ),xw->width);
1260 //gtk_container_resize_children ( GTK_WINDOW(xw->widgetwindow_osr));
1261 gtk_container_resize_children (GTK_CONTAINER(xw->widgetwindow_osr));
1265 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail)) //TODO MVC refactor lazy linear search
1267 if (XWIDGET_VIEW_P (XCAR (tail))) {
1268 xv = XXWIDGET_VIEW (XCAR (tail));
1269 if(XXWIDGET (xv->model) == xw) {
1270 gtk_layout_set_size (GTK_LAYOUT (xv->widgetwindow), xw->width, xw->height);
1271 gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xw->width, xw->height);
1276 return Qnil;
1281 DEFUN ("xwidget-set-adjustment", Fxwidget_set_adjustment, Sxwidget_set_adjustment, 4, 4, 0, doc:
1282 /* set scrolling */)
1283 (Lisp_Object xwidget, Lisp_Object axis, Lisp_Object relative, Lisp_Object value)
1285 CHECK_XWIDGET (xwidget);
1286 struct xwidget* xw = XXWIDGET(xwidget);
1287 GtkAdjustment* adjustment;
1288 float final_value=0.0;
1290 if(EQ(Qvertical, axis)){
1291 adjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(xw->widgetscrolledwindow_osr));
1293 if(EQ(Qhorizontal, axis)){
1294 adjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(xw->widgetscrolledwindow_osr));
1297 if(EQ(Qt, relative)){
1298 final_value=gtk_adjustment_get_value(adjustment)+XFASTINT(value);
1299 }else{
1300 final_value=0.0+XFASTINT(value);
1303 gtk_adjustment_set_value(adjustment, final_value);
1305 return Qnil;
1309 DEFUN ("xwidget-size-request", Fxwidget_size_request, Sxwidget_size_request, 1, 1, 0, doc:
1310 /* Desired size of the XWIDGET.
1312 This can be used to read the xwidget desired size, and resizes the Emacs allocated area accordingly.
1314 (TODO crashes if arg not osr widget)*/)
1315 (Lisp_Object xwidget)
1317 CHECK_XWIDGET (xwidget);
1318 GtkRequisition requisition;
1319 Lisp_Object rv;
1320 gtk_widget_size_request(XXWIDGET(xwidget)->widget_osr, &requisition);
1321 rv = Qnil;
1322 rv = Fcons (make_number(requisition.height), rv);
1323 rv = Fcons (make_number(requisition.width), rv);
1324 return rv;
1328 DEFUN ("xwidgetp", Fxwidgetp, Sxwidgetp, 1, 1, 0,
1329 doc: /* Return t if OBJECT is a xwidget. */)
1330 (Lisp_Object object)
1332 return XWIDGETP (object) ? Qt : Qnil;
1335 DEFUN ("xwidget-view-p", Fxwidget_view_p, Sxwidget_view_p, 1, 1, 0,
1336 doc: /* Return t if OBJECT is a xwidget-view. */)
1337 (Lisp_Object object)
1339 return XWIDGET_VIEW_P (object) ? Qt : Qnil;
1342 DEFUN ("xwidget-info", Fxwidget_info , Sxwidget_info, 1,1,0,
1343 doc: /* Get XWIDGET properties.
1344 Currently type, title, width, height.*/)
1345 (Lisp_Object xwidget)
1347 CHECK_XWIDGET (xwidget);
1348 Lisp_Object info, n;
1349 struct xwidget* xw = XXWIDGET(xwidget);
1351 info = Fmake_vector (make_number (4), Qnil);
1352 ASET (info, 0, xw->type);
1353 ASET (info, 1, xw->title);
1354 XSETFASTINT(n, xw->width);
1355 ASET (info, 2, n);
1356 XSETFASTINT(n, xw->height);
1357 ASET (info, 3, n);
1359 return info;
1362 DEFUN ("xwidget-view-info", Fxwidget_view_info , Sxwidget_view_info, 1, 1, 0, doc:
1363 /* Get XWIDGET-VIEW properties.
1364 Currently x,y clip right, clip bottom, clip top, clip left*/)
1365 (Lisp_Object xwidget_view)
1367 CHECK_XWIDGET_VIEW (xwidget_view);
1368 struct xwidget_view *xv = XXWIDGET_VIEW (xwidget_view);
1369 Lisp_Object info;
1371 info = Fmake_vector (make_number (6), Qnil);
1372 ASET (info, 0, make_number(xv->x));
1373 ASET (info, 1, make_number(xv->y));
1374 ASET (info, 2, make_number(xv->clip_right));
1375 ASET (info, 3, make_number(xv->clip_bottom));
1376 ASET (info, 4, make_number(xv->clip_top));
1377 ASET (info, 5, make_number(xv->clip_left));
1379 return info;
1382 DEFUN ("xwidget-view-model", Fxwidget_view_model, Sxwidget_view_model,
1383 1, 1, 0,
1384 doc: /* Get XWIDGET-VIEW model. */)
1385 (Lisp_Object xwidget_view)
1387 CHECK_XWIDGET_VIEW (xwidget_view);
1388 return XXWIDGET_VIEW (xwidget_view)->model;
1391 DEFUN ("xwidget-view-window", Fxwidget_view_window, Sxwidget_view_window,
1392 1, 1, 0,
1393 doc: /* Get XWIDGET-VIEW window. */)
1394 (Lisp_Object xwidget_view)
1396 CHECK_XWIDGET_VIEW (xwidget_view);
1397 return XXWIDGET_VIEW (xwidget_view)->w;
1400 DEFUN ("xwidget-send-keyboard-event", Fxwidget_send_keyboard_event, Sxwidget_send_keyboard_event, 2, 2, 0,
1401 doc:/* Synthesize a kbd event for XWIDGET. TODO crashes atm.. */
1403 (Lisp_Object xwidget, Lisp_Object keydescriptor)
1405 //TODO this code crashes for offscreen widgets and ive tried many different strategies
1406 //int keyval = 0x058; //X
1407 int keyval = XFASTINT(keydescriptor); //X
1408 char *keystring = "";
1409 GdkKeymapKey* keys;
1410 gint n_keys;
1411 GdkDeviceManager* manager;
1412 struct xwidget *xw;
1413 GtkWidget* widget;
1414 GdkEventKey* ev;
1415 Lisp_Object window;
1416 //popup_activated_flag = 1; //TODO just a hack
1417 gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), keyval, &keys, &n_keys);
1419 xw = XXWIDGET(xwidget);
1421 ev = (GdkEventKey*)gdk_event_new(GDK_KEY_PRESS);
1424 //todo what about windowless widgets?
1426 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1429 //TODO maybe we also need to special case sockets by picking up the plug rather than the socket
1430 if(xw->widget_osr)
1431 widget = xw->widget_osr;
1432 else
1433 widget = xwidget_view_lookup(xw, XWINDOW(window))->widget;
1435 ev->window = gtk_widget_get_window(widget);
1436 gtk_widget_grab_focus(widget);
1437 ev->send_event = FALSE;
1439 ev->hardware_keycode = keys[0].keycode;
1440 ev->group = keys[0].group;
1442 ev->keyval = keyval;
1443 ev->time = GDK_CURRENT_TIME;
1445 //ev->device = gdk_device_get_core_pointer();
1446 manager = gdk_display_get_device_manager(gdk_window_get_display(ev->window));
1447 gdk_event_set_device ((GdkEvent*)ev, gdk_device_manager_get_client_pointer(manager));
1448 gdk_event_put((GdkEvent*)ev);
1449 //g_signal_emit_by_name(ev->window,"key-press-event", ev);
1451 ev->type = GDK_KEY_RELEASE;
1452 gdk_event_put((GdkEvent*)ev);
1453 //g_signal_emit_by_name(ev->window,"key-release-event", ev);
1454 //gtk_main_do_event(ev);
1456 //TODO
1457 //if I delete the event the receiving component eventually crashes.
1458 //it ough TDTRT since event_put is supposed to copy the event
1459 //so probably this leaks events now
1460 //gdk_event_free((GdkEvent*)ev);
1462 return Qnil;
1465 DEFUN ("delete-xwidget-view", Fdelete_xwidget_view, Sdelete_xwidget_view,
1466 1, 1, 0,
1467 doc: /* Delete the XWIDGET-VIEW. */)
1468 (Lisp_Object xwidget_view)
1470 CHECK_XWIDGET_VIEW (xwidget_view);
1471 struct xwidget_view *xv = XXWIDGET_VIEW (xwidget_view);
1472 gtk_widget_destroy(xv->widgetwindow);
1473 Vxwidget_view_list = Fdelq (xwidget_view, Vxwidget_view_list);
1476 DEFUN ("xwidget-view-lookup", Fxwidget_view_lookup, Sxwidget_view_lookup,
1477 1, 2, 0,
1478 doc: /* Return the xwidget-view associated to XWIDGET in
1479 WINDOW if specified, otherwise it uses the selected window. */)
1480 (Lisp_Object xwidget, Lisp_Object window)
1482 CHECK_XWIDGET (xwidget);
1484 if (NILP (window))
1485 window = Fselected_window();
1486 CHECK_WINDOW (window);
1488 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail))
1490 Lisp_Object xwidget_view = XCAR (tail);
1491 if (EQ (Fxwidget_view_model (xwidget_view), xwidget)
1492 && EQ (Fxwidget_view_window (xwidget_view), window))
1493 return xwidget_view;
1496 return Qnil;
1499 DEFUN ("set-frame-visible", Fset_frame_visible, Sset_frame_visible,
1500 2, 2, 0,
1501 doc: /* HACKY */)
1502 (Lisp_Object frame, Lisp_Object flag)
1504 CHECK_FRAME (frame);
1505 struct frame *f = XFRAME (frame);
1506 SET_FRAME_VISIBLE (f, !NILP (flag));
1507 return flag;
1510 DEFUN ("xwidget-plist", Fxwidget_plist, Sxwidget_plist,
1511 1, 1, 0,
1512 doc: /* Return the plist of XWIDGET. */)
1513 (register Lisp_Object xwidget)
1515 CHECK_XWIDGET (xwidget);
1516 return XXWIDGET (xwidget)->plist;
1519 DEFUN ("xwidget-buffer", Fxwidget_buffer, Sxwidget_buffer,
1520 1, 1, 0,
1521 doc: /* Return the buffer of XWIDGET. */)
1522 (register Lisp_Object xwidget)
1524 CHECK_XWIDGET (xwidget);
1525 return XXWIDGET (xwidget)->buffer;
1528 DEFUN ("set-xwidget-plist", Fset_xwidget_plist, Sset_xwidget_plist,
1529 2, 2, 0,
1530 doc: /* Replace the plist of XWIDGET with PLIST. Returns PLIST. */)
1531 (register Lisp_Object xwidget, Lisp_Object plist)
1533 CHECK_XWIDGET (xwidget);
1534 CHECK_LIST (plist);
1536 XXWIDGET (xwidget)->plist = plist;
1537 return plist;
1540 DEFUN ("set-xwidget-query-on-exit-flag",
1541 Fset_xwidget_query_on_exit_flag, Sset_xwidget_query_on_exit_flag,
1542 2, 2, 0,
1543 doc: /* Specify if query is needed for XWIDGET when Emacs is
1544 exited. If the second argument FLAG is non-nil, Emacs will query the
1545 user before exiting or killing a buffer if XWIDGET is running. This
1546 function returns FLAG. */)
1547 (Lisp_Object xwidget, Lisp_Object flag)
1549 CHECK_XWIDGET (xwidget);
1550 XXWIDGET (xwidget)->kill_without_query = NILP (flag);
1551 return flag;
1554 DEFUN ("xwidget-query-on-exit-flag",
1555 Fxwidget_query_on_exit_flag, Sxwidget_query_on_exit_flag,
1556 1, 1, 0,
1557 doc: /* Return the current value of query-on-exit flag for XWIDGET. */)
1558 (Lisp_Object xwidget)
1560 CHECK_XWIDGET (xwidget);
1561 return (XXWIDGET (xwidget)->kill_without_query ? Qnil : Qt);
1564 void
1565 syms_of_xwidget (void)
1567 int i;
1569 defsubr (&Smake_xwidget);
1570 defsubr (&Sxwidgetp);
1571 DEFSYM (Qxwidgetp, "xwidgetp");
1572 defsubr (&Sxwidget_view_p);
1573 DEFSYM (Qxwidget_view_p, "xwidget-view-p");
1574 defsubr (&Sxwidget_info);
1575 defsubr (&Sxwidget_view_info);
1576 defsubr (&Sxwidget_resize);
1577 defsubr (&Sget_buffer_xwidgets);
1578 defsubr (&Sxwidget_view_model);
1579 defsubr (&Sxwidget_view_window);
1580 defsubr (&Sxwidget_view_lookup);
1581 defsubr (&Sxwidget_query_on_exit_flag);
1582 defsubr (&Sset_xwidget_query_on_exit_flag);
1583 defsubr (&Sset_frame_visible);
1585 #ifdef HAVE_WEBKIT_OSR
1586 defsubr (&Sxwidget_webkit_goto_uri);
1587 defsubr (&Sxwidget_webkit_execute_script);
1588 defsubr (&Sxwidget_webkit_get_title);
1589 DEFSYM (Qwebkit_osr, "webkit-osr");
1590 #endif
1592 defsubr (&Sxwgir_xwidget_call_method );
1593 defsubr (&Sxwgir_require_namespace);
1594 defsubr (&Sxwidget_size_request );
1595 defsubr (&Sdelete_xwidget_view);
1596 defsubr (&Sxwidget_disable_plugin_for_mime);
1598 defsubr (&Sxwidget_send_keyboard_event);
1599 defsubr (&Sxwidget_webkit_dom_dump);
1600 defsubr (&Sxwidget_plist);
1601 defsubr (&Sxwidget_buffer);
1602 defsubr (&Sset_xwidget_plist);
1604 defsubr (&Sxwidget_set_adjustment);
1606 DEFSYM (Qxwidget, "xwidget");
1608 DEFSYM (QCxwidget, ":xwidget");
1609 DEFSYM (QCxwgir_class, ":xwgir-class");
1610 DEFSYM (QCtitle, ":title");
1612 /* Do not forget to update the docstring of make-xwidget if you add
1613 new types. */
1614 DEFSYM (Qbutton, "Button"); //changed to match the gtk class because xwgir(experimental and not really needed)
1615 DEFSYM (Qtoggle, "ToggleButton");
1616 DEFSYM (Qslider, "slider");
1617 DEFSYM (Qsocket, "socket");
1618 DEFSYM (Qsocket_osr, "socket-osr");
1619 DEFSYM (Qcairo, "cairo");
1621 DEFSYM (Qvertical, "vertical");
1622 DEFSYM (Qhorizontal, "horizontal");
1624 DEFSYM (QCplist, ":plist");
1626 DEFVAR_LISP ("xwidget-list", Vxwidget_list, doc: /*xwidgets list*/);
1627 Vxwidget_list = Qnil;
1629 DEFVAR_LISP ("xwidget-view-list", Vxwidget_view_list, doc: /*xwidget views list*/);
1630 Vxwidget_view_list = Qnil;
1632 Fprovide (intern ("xwidget-internal"), Qnil);
1637 /* Value is non-zero if OBJECT is a valid Lisp xwidget specification. A
1638 valid xwidget specification is a list whose car is the symbol
1639 `xwidget', and whose rest is a property list. The property list must
1640 contain a value for key `:type'. That value must be the name of a
1641 supported xwidget type. The rest of the property list depends on the
1642 xwidget type. */
1645 valid_xwidget_spec_p (Lisp_Object object)
1647 int valid_p = 0;
1649 if (CONSP (object) && EQ (XCAR (object), Qxwidget))
1651 /* Lisp_Object tem; */
1653 /* for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem)) */
1654 /* if (EQ (XCAR (tem), QCtype)) */
1655 /* { */
1656 /* tem = XCDR (tem); */
1657 /* if (CONSP (tem) && SYMBOLP (XCAR (tem))) */
1658 /* { */
1659 /* struct xwidget_type *type; */
1660 /* type = lookup_xwidget_type (XCAR (tem)); */
1661 /* if (type) */
1662 /* valid_p = type->valid_p (object); */
1663 /* } */
1665 /* break; */
1666 /* } */
1667 //never mind type support for now
1668 valid_p = 1;
1671 return valid_p;
1676 /* find a value associated with key in spec */
1677 Lisp_Object
1678 xwidget_spec_value ( Lisp_Object spec, Lisp_Object key,
1679 int *found)
1681 Lisp_Object tail;
1683 eassert (valid_xwidget_spec_p (spec));
1685 for (tail = XCDR (spec);
1686 CONSP (tail) && CONSP (XCDR (tail)); tail = XCDR (XCDR (tail)))
1688 if (EQ (XCAR (tail), key))
1690 if (found)
1691 *found = 1;
1692 return XCAR (XCDR (tail));
1696 if (found)
1697 *found = 0;
1698 return Qnil;
1702 void
1703 xwidget_view_delete_all_in_window (struct window *w)
1705 struct xwidget_view* xv = NULL;
1706 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail))
1708 if (XWIDGET_VIEW_P (XCAR (tail))) {
1709 xv = XXWIDGET_VIEW (XCAR (tail));
1710 if(XWINDOW (xv->w) == w) {
1711 gtk_widget_destroy(xv->widgetwindow);
1712 Vxwidget_view_list = Fdelq (XCAR (tail), Vxwidget_view_list);
1718 struct xwidget_view*
1719 xwidget_view_lookup (struct xwidget* xw, struct window *w)
1721 Lisp_Object xwidget, window, ret;
1722 XSETXWIDGET (xwidget, xw);
1723 XSETWINDOW (window, w);
1725 ret = Fxwidget_view_lookup (xwidget, window);
1727 return EQ (ret, Qnil) ? NULL : XXWIDGET_VIEW (ret);
1730 struct xwidget*
1731 lookup_xwidget (Lisp_Object spec)
1733 /* When a xwidget lisp spec is found initialize the C struct that is used in the C code.
1734 This is done by redisplay so values change if the spec changes.
1735 So, take special care of one-shot events
1737 TODO remove xwidget init from display spec. simply store an xwidget reference only and set
1738 size etc when creating the xwidget, which should happen before insertion into buffer
1740 int found = 0, found1 = 0, found2 = 0;
1741 Lisp_Object value;
1742 struct xwidget *xw;
1744 value = xwidget_spec_value (spec, QCxwidget, &found1);
1745 xw = XXWIDGET(value);
1747 /* value = xwidget_spec_value (spec, QCtype, &found); */
1748 /* xw->type = SYMBOLP (value) ? value : Qbutton; //default to button */
1749 /* value = xwidget_spec_value (spec, QCtitle, &found2); */
1750 /* xw->title = STRINGP (value) ? (char *) SDATA (value) : "?"; //funky cast FIXME TODO */
1752 /* value = xwidget_spec_value (spec, QCheight, NULL); */
1753 /* xw->height = INTEGERP (value) ? XFASTINT (value) : 50; */
1754 /* value = xwidget_spec_value (spec, QCwidth, NULL); */
1755 /* xw->width = INTEGERP (value) ? XFASTINT (value) : 50; */
1757 /* value = xwidget_spec_value (spec, QCplist, NULL); */
1758 /* xw->plist = value; */
1759 /* coordinates are not known here */
1760 printf ("lookup_xwidget xwidget_id:%d type:%d found:%d %d %d title:'%s' (%d,%d)\n", xw,
1761 xw->type, found, found1, found2, xw->title, xw->height, xw->width);
1763 //assert_valid_xwidget_id (id, "lookup_xwidget");
1764 return xw;
1767 /*set up detection of touched xwidget*/
1768 void
1769 xwidget_start_redisplay (void)
1771 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail))
1773 if (XWIDGET_VIEW_P (XCAR (tail)))
1774 XXWIDGET_VIEW (XCAR (tail))->redisplayed = 0;
1778 /* the xwidget was touched during redisplay, so it isnt a candidate for hiding*/
1779 void
1780 xwidget_touch (struct xwidget_view *xv)
1782 xv->redisplayed = 1;
1786 xwidget_touched (struct xwidget_view *xv)
1788 return xv->redisplayed;
1791 /* redisplay has ended, now we should hide untouched xwidgets
1793 void
1794 xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix)
1797 int i;
1798 struct xwidget *xw;
1799 int area;
1802 xwidget_start_redisplay ();
1803 //iterate desired glyph matrix of window here, hide gtk widgets
1804 //not in the desired matrix.
1806 //this only takes care of xwidgets in active windows.
1807 //if a window goes away from screen xwidget views wust be deleted
1809 // dump_glyph_matrix(matrix, 2);
1810 for (i = 0; i < matrix->nrows; ++i)
1812 // dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
1813 struct glyph_row *row;
1814 row = MATRIX_ROW (matrix, i);
1815 if (row->enabled_p != 0)
1817 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
1819 struct glyph *glyph = row->glyphs[area];
1820 struct glyph *glyph_end = glyph + row->used[area];
1821 for (; glyph < glyph_end; ++glyph)
1823 if (glyph->type == XWIDGET_GLYPH)
1826 the only call to xwidget_end_redisplay is in dispnew
1827 xwidget_end_redisplay(w->current_matrix);
1829 xwidget_touch (xwidget_view_lookup(glyph->u.xwidget,
1830 w));
1837 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail))
1839 if (XWIDGET_VIEW_P (XCAR (tail))) {
1840 struct xwidget_view* xv = XXWIDGET_VIEW (XCAR (tail));
1842 //"touched" is only meaningful for the current window, so disregard other views
1843 if (XWINDOW (xv->w) == w) {
1844 if (xwidget_touched(xv))
1845 xwidget_show_view (xv);
1846 else
1847 xwidget_hide_view (xv);
1853 /* Kill all xwidget in BUFFER. */
1854 void
1855 kill_buffer_xwidgets (Lisp_Object buffer)
1857 Lisp_Object tail, xwidget;
1858 for (tail = Fget_buffer_xwidgets (buffer); CONSP (tail); tail = XCDR (tail))
1860 xwidget = XCAR (tail);
1861 Vxwidget_list = Fdelq (xwidget, Vxwidget_list);
1862 /* TODO free the GTK things in xw */
1864 CHECK_XWIDGET (xwidget);
1865 struct xwidget *xw = XXWIDGET (xwidget);
1866 if (xw->widget_osr && xw->widgetwindow_osr)
1868 gtk_widget_destroy(xw->widget_osr);
1869 gtk_widget_destroy(xw->widgetwindow_osr);
1875 #endif /* HAVE_XWIDGETS */