]> code.delx.au - gnu-emacs/blob - src/xwidget.c
Merge branch 'master' into xwidget
[gnu-emacs] / src / xwidget.c
1 #include <config.h>
2 #ifdef HAVE_XWIDGETS
3
4 #include <signal.h>
5
6 #include <stdio.h>
7 #include <setjmp.h>
8 #ifdef HAVE_X_WINDOWS
9
10 #include "lisp.h"
11 #include "blockinput.h"
12 #include "syssignal.h"
13
14 #include "xterm.h"
15 #include <X11/cursorfont.h>
16
17 #ifndef makedev
18 #include <sys/types.h>
19 #endif /* makedev */
20
21 #ifdef BSD_SYSTEM
22 #include <sys/ioctl.h>
23 #endif /* ! defined (BSD_SYSTEM) */
24
25 #include "systime.h"
26
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>
34
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"
54
55
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
68
69 #include "gtkutil.h"
70 #include "font.h"
71 #endif /* HAVE_X_WINDOWS */
72
73 #include <gtk/gtk.h>
74 #include <gdk/gdk.h>
75
76 #ifdef HAVE_GTK3
77 //for gtk3; sockets and plugs
78 #include <gtk/gtkx.h>
79 #include "emacsgtkfixed.h"
80 #endif
81
82 #include <wchar.h>
83
84 #ifdef HAVE_WEBKIT_OSR
85 #include <webkit/webkitwebview.h>
86 #include <webkit/webkitwebplugindatabase.h>
87 #include <webkit/webkitwebplugin.h>
88 #include <webkit/webkitglobals.h>
89 #include <webkit/webkitwebnavigationaction.h>
90 #include <webkit/webkitdownload.h>
91 #include <webkit/webkitwebpolicydecision.h>
92 #endif
93
94 //for GIR
95 #include <girepository.h>
96
97 #include "xwidget.h"
98
99 //TODO embryo of lisp allocators for xwidgets
100 //TODO xwidget* should be Lisp_xwidget*
101 struct xwidget*
102 allocate_xwidget (void)
103 {
104 return ALLOCATE_PSEUDOVECTOR (struct xwidget, height, PVEC_XWIDGET);
105 }
106
107 //TODO xwidget_view* should be Lisp_xwidget_view*
108 struct xwidget_view*
109 allocate_xwidget_view (void)
110 {
111 return ALLOCATE_PSEUDOVECTOR (struct xwidget_view, redisplayed, PVEC_XWIDGET_VIEW);
112 }
113 #define XSETXWIDGET(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET))
114 #define XSETXWIDGET_VIEW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET_VIEW))
115
116 Lisp_Object Qxwidget;
117 Lisp_Object QCxwidget;
118 Lisp_Object QCtitle;
119 Lisp_Object Qxwidget_set_keyboard_grab;
120 Lisp_Object Qxwidget_embed_steal_window;
121 Lisp_Object Qxwidget_info;
122 Lisp_Object Qxwidget_resize;
123 Lisp_Object Qxwidget_send_keyboard_event;
124 Lisp_Object QCxwgir_class;
125 Lisp_Object Qbutton, Qtoggle, Qslider, Qsocket, Qsocket_osr, Qcairo, Qxwgir,
126 Qwebkit_osr, QCplist;
127 Lisp_Object Qxwidgetp, Qxwidget_view_p;
128
129
130 extern Lisp_Object QCtype;
131 extern Lisp_Object QCwidth, QCheight;
132
133 struct xwidget_view* xwidget_view_lookup(struct xwidget* xw, struct window *w);
134 Lisp_Object xwidget_spec_value ( Lisp_Object spec, Lisp_Object key, int *found);
135 gboolean offscreen_damage_event (GtkWidget *widget, GdkEvent *event, gpointer data);
136 void webkit_osr_document_load_finished_callback (WebKitWebView *webkitwebview,
137 WebKitWebFrame *arg1,
138 gpointer user_data);
139 gboolean webkit_osr_download_callback (WebKitWebView *webkitwebview,
140 WebKitDownload *arg1,
141 gpointer data);
142
143 gboolean webkit_osr_mime_type_policy_typedecision_requested_callback(WebKitWebView *webView,
144 WebKitWebFrame *frame,
145 WebKitNetworkRequest *request,
146 gchar *mimetype,
147 WebKitWebPolicyDecision *policy_decision,
148 gpointer user_data);
149
150 gboolean webkit_osr_new_window_policy_decision_requested_callback(WebKitWebView *webView,
151 WebKitWebFrame *frame,
152 WebKitNetworkRequest *request,
153 WebKitWebNavigationAction *navigation_action,
154 WebKitWebPolicyDecision *policy_decision,
155 gpointer user_data);
156
157
158 gboolean webkit_osr_navigation_policy_decision_requested_callback(WebKitWebView *webView,
159 WebKitWebFrame *frame,
160 WebKitNetworkRequest *request,
161 WebKitWebNavigationAction *navigation_action,
162 WebKitWebPolicyDecision *policy_decision,
163 gpointer user_data);
164
165 GtkWidget* xwgir_create(char* class, char* namespace);
166 static void
167 send_xembed_ready_event (struct xwidget* xw, int xembedid);
168 DEFUN ("make-xwidget", Fmake_xwidget, Smake_xwidget, 7, 8, 0,
169 doc: /* Make an xwidget from BEG to END of TYPE.
170
171 If BUFFER is nil it uses the current buffer. If BUFFER is a string and
172 no such buffer exists, it is created.
173
174 TYPE is a symbol which can take one of the following values:
175 - Button
176 - ToggleButton
177 - slider
178 - socket
179 - socket-osr
180 - cairo
181 */
182 )
183 (Lisp_Object beg, Lisp_Object end,
184 Lisp_Object type,
185 Lisp_Object title,
186 Lisp_Object width, Lisp_Object height,
187 Lisp_Object data,
188 Lisp_Object buffer)
189 {
190 //should work a bit like "make-button"(make-button BEG END &rest PROPERTIES)
191 // arg "type" and fwd should be keyword args eventually
192 //(make-xwidget 3 3 'button "oei" 31 31 nil)
193 //(xwidget-info (car xwidget-list))
194 struct xwidget* xw = allocate_xwidget();
195 Lisp_Object val;
196 xw->type = type;
197 xw->title = title;
198 if (NILP (buffer))
199 buffer = Fcurrent_buffer(); // no need to gcpro because Fcurrent_buffer doesn't call Feval/eval_sub.
200 else
201 buffer = Fget_buffer_create (buffer);
202 xw->buffer = buffer;
203
204 xw->height = XFASTINT(height);
205 xw->width = XFASTINT(width);
206 xw->kill_without_query = 0;
207 XSETXWIDGET (val, xw); // set the vectorlike_header of VAL with the correct value
208 Vxwidget_list = Fcons (val, Vxwidget_list);
209 xw->widgetwindow_osr = NULL;
210 xw->widget_osr = NULL;
211 xw->plist = Qnil;
212
213
214 #ifdef HAVE_WEBKIT_OSR
215 /* DIY mvc. widget is rendered offscreen,
216 later bitmap copied to the views.
217 */
218 if (EQ(xw->type, Qwebkit_osr)||
219 EQ(xw->type, Qsocket_osr)||
220 (!NILP (Fget(xw->type, QCxwgir_class)))) {
221 block_input();
222 xw->widgetwindow_osr = gtk_offscreen_window_new ();
223 gtk_window_resize(GTK_WINDOW(xw->widgetwindow_osr), xw->width, xw->height);
224
225 if (EQ(xw->type, Qwebkit_osr))
226 xw->widget_osr = webkit_web_view_new();
227 if(EQ(xw->type, Qsocket_osr))
228 xw->widget_osr = gtk_socket_new();
229 if(!NILP (Fget(xw->type, QCxwgir_class)))
230 xw->widget_osr = xwgir_create(SDATA(Fcar(Fcdr(Fget(xw->type, QCxwgir_class)))),
231 SDATA(Fcar(Fget(xw->type, QCxwgir_class))));
232
233 gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, xw->height);
234 gtk_container_add (GTK_CONTAINER (xw->widgetwindow_osr), xw->widget_osr);
235
236 gtk_widget_show (xw->widget_osr);
237 gtk_widget_show (xw->widgetwindow_osr);
238
239 /* store some xwidget data in the gtk widgets for convenient retrieval in the event handlers. */
240 g_object_set_data (G_OBJECT (xw->widget_osr), XG_XWIDGET, (gpointer) (xw));
241 g_object_set_data (G_OBJECT (xw->widgetwindow_osr), XG_XWIDGET, (gpointer) (xw));
242
243 /* signals */
244 if (EQ(xw->type, Qwebkit_osr)) {
245 g_signal_connect (G_OBJECT (xw->widget_osr),
246 "document-load-finished",
247 G_CALLBACK (webkit_osr_document_load_finished_callback),
248 xw);
249
250 g_signal_connect (G_OBJECT (xw->widget_osr),
251 "download-requested",
252 G_CALLBACK (webkit_osr_download_callback),
253 xw);
254
255 g_signal_connect (G_OBJECT (xw->widget_osr),
256 "mime-type-policy-decision-requested",
257 G_CALLBACK (webkit_osr_mime_type_policy_typedecision_requested_callback),
258 xw);
259
260 g_signal_connect (G_OBJECT (xw->widget_osr),
261 "new-window-policy-decision-requested",
262 G_CALLBACK (webkit_osr_new_window_policy_decision_requested_callback),
263 xw);
264
265 g_signal_connect (G_OBJECT (xw->widget_osr),
266 "navigation-policy-decision-requested",
267 G_CALLBACK (webkit_osr_navigation_policy_decision_requested_callback),
268 xw);
269 }
270
271 if (EQ(xw->type, Qsocket_osr)) {
272 send_xembed_ready_event (xw, gtk_socket_get_id (GTK_SOCKET (xw->widget_osr)));
273 //gtk_widget_realize(xw->widget);
274 }
275
276
277 unblock_input();
278
279 }
280 #endif /* HAVE_WEBKIT_OSR */
281
282 return val;
283 }
284
285 DEFUN ("get-buffer-xwidgets", Fget_buffer_xwidgets, Sget_buffer_xwidgets, 1, 1, 0,
286 doc: /* Return the xwidgets associated with BUFFER.
287 BUFFER may be a buffer or the name of one.
288 */
289 )
290 (Lisp_Object buffer)
291 {
292 Lisp_Object xw, tail, xw_list;
293
294 if (NILP (buffer)) return Qnil;
295 buffer = Fget_buffer (buffer);
296 if (NILP (buffer)) return Qnil;
297
298 xw_list = Qnil;
299
300 for (tail = Vxwidget_list; CONSP (tail); tail = XCDR (tail))
301 {
302 xw = XCAR (tail);
303 if (XWIDGETP (xw) && EQ (Fxwidget_buffer (xw), buffer))
304 xw_list = Fcons (xw, xw_list);
305 }
306 return xw_list;
307 }
308
309 int
310 xwidget_hidden(struct xwidget_view *xv)
311 {
312 return xv->hidden;
313 }
314
315
316 static void
317 buttonclick_handler (GtkWidget * widget, gpointer data)
318 {
319 Lisp_Object xwidget_view, xwidget;
320 XSETXWIDGET_VIEW (xwidget_view, (struct xwidget_view *) data);
321 xwidget = Fxwidget_view_model (xwidget_view);
322
323 struct input_event event;
324 Lisp_Object frame = Fwindow_frame (Fxwidget_view_window (xwidget_view));
325 struct frame *f = XFRAME (frame);
326 printf ("button clicked xw:%d '%s'\n", XXWIDGET (xwidget), XXWIDGET (xwidget)->title);
327
328 EVENT_INIT (event);
329 event.kind = XWIDGET_EVENT;
330
331 event.frame_or_window = frame;
332
333 event.arg = Qnil;
334 event.arg = Fcons (xwidget, event.arg);
335 event.arg = Fcons (intern ("buttonclick"), event.arg);
336
337 kbd_buffer_store_event (&event);
338 }
339
340
341 static void
342 send_xembed_ready_event (struct xwidget* xw, int xembedid)
343 {
344 Lisp_Object xw_lo;
345 XSETXWIDGET(xw_lo, xw);
346 struct input_event event;
347 EVENT_INIT (event);
348 event.kind = XWIDGET_EVENT;
349 event.frame_or_window = Qnil; //frame; //how to get the frame here? //TODO i store it in the xwidget now
350
351 event.arg = Qnil;
352 event.arg = Fcons (make_number (xembedid), event.arg);
353 event.arg = Fcons (xw_lo, event.arg);
354 event.arg = Fcons (intern ("xembed-ready"), event.arg);
355
356
357 kbd_buffer_store_event (&event);
358
359 }
360
361 void
362 xwidget_show_view (struct xwidget_view *xv)
363 {
364 xv->hidden = 0;
365 gtk_widget_show(xv->widgetwindow);
366 gtk_fixed_move (GTK_FIXED (xv->emacswindow), xv->widgetwindow, xv->x + xv->clip_left, xv->y + xv->clip_top); //TODO refactor
367 }
368
369
370 /* hide an xvidget view */
371 void
372 xwidget_hide_view (struct xwidget_view *xv)
373 {
374 xv->hidden = 1;
375 //gtk_widget_hide(xw->widgetwindow);
376 gtk_fixed_move (GTK_FIXED (xv->emacswindow), xv->widgetwindow,
377 10000, 10000);
378 }
379
380
381 void
382 xwidget_plug_added(GtkSocket *socket,
383 gpointer user_data)
384 {
385 //hmm this doesnt seem to get called for foreign windows
386 printf("xwidget_plug_added\n");
387 }
388
389 gboolean
390 xwidget_plug_removed(GtkSocket *socket,
391 gpointer user_data)
392 {
393 printf("xwidget_plug_removed\n");
394 return TRUE; /* dont run the default handler because that kills the socket and we want to reuse it*/
395 }
396
397
398 void
399 xwidget_slider_changed (GtkRange *range,
400 gpointer user_data)
401 {
402 //slider value changed. change value of siblings
403 //correspondingly. but remember that changing value will again
404 //trigger signal
405
406 //TODO MVC view storage wont be an array futureish so the loop needs to change eventually
407 //TODO MVC it would be nice if this code could be reusable but, alas, C is not a functional language
408 //issues are:
409 // - the type of the controllers value (double, boolean etc)
410 // - the getter and setter (but they can be func pointers)
411 // a behemoth macro is always an option.
412 double v=gtk_range_get_value(range);
413 struct xwidget_view* xvp = g_object_get_data (G_OBJECT (range), XG_XWIDGET_VIEW);
414 struct xwidget_view* xv;
415
416 printf("slider changed val:%f\n", v);
417
418 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail))
419 {
420 if (XWIDGET_VIEW_P (XCAR (tail))) {
421 xv = XXWIDGET_VIEW (XCAR (tail));
422 if (EQ (xvp->model, xv->model)) {
423 //block sibling views signal handlers
424 g_signal_handler_block(xv->widget, xv->handler_id);
425
426 //set values of sibling views and unblock
427 gtk_range_set_value(GTK_RANGE(xv->widget), v);
428 g_signal_handler_unblock(xv->widget,xv->handler_id);
429 }
430 }
431 }
432 }
433
434
435 /* when the off-screen webkit master view changes this signal is called.
436 it copies the bitmap from the off-screen webkit instance */
437 gboolean
438 offscreen_damage_event (GtkWidget *widget, GdkEvent *event, gpointer data)
439 {
440 //TODO this is wrong! should just queu a redraw of onscreen widget
441 gtk_widget_queue_draw (GTK_WIDGET (data));
442 return FALSE;
443 }
444
445 void
446 store_xwidget_event_string(struct xwidget* xw, char* eventname, const char* eventstr)
447 {
448 //refactor attempt
449 struct input_event event;
450 Lisp_Object xwl;
451 XSETXWIDGET(xwl,xw);
452 EVENT_INIT (event);
453 event.kind = XWIDGET_EVENT;
454 event.frame_or_window = Qnil; //frame; //how to get the frame here? //TODO i store it in the xwidget now
455
456 event.arg = Qnil;
457 event.arg = Fcons (build_string(eventstr), event.arg); //string so dont intern
458 event.arg = Fcons (xwl, event.arg); //TODO
459 event.arg = Fcons (intern (eventname), event.arg);//interning should be ok
460 kbd_buffer_store_event (&event);
461
462 }
463
464 //TODO deprecated, use load-status
465 void
466 webkit_osr_document_load_finished_callback (WebKitWebView *webkitwebview,
467 WebKitWebFrame *arg1,
468 gpointer data)
469 {
470 //TODO this event sending code should be refactored
471 // struct xwidget *xw = (struct xwidget *) data;
472 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (webkitwebview), XG_XWIDGET);
473 printf("webkit finished loading\n");
474
475 store_xwidget_event_string(xw,
476 "document-load-finished", "");
477 }
478
479 gboolean
480 webkit_osr_download_callback (WebKitWebView *webkitwebview,
481 WebKitDownload *arg1,
482 gpointer data)
483 {
484 //TODO this event sending code should be refactored
485 struct input_event event;
486 // struct xwidget *xw = (struct xwidget *) data;
487 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (webkitwebview), XG_XWIDGET);
488 printf("download requested %s\n", webkit_download_get_uri (arg1));
489
490
491 printf("webkit finished loading\n");
492
493 store_xwidget_event_string(xw, "download-requested", webkit_download_get_uri (arg1));
494
495 return FALSE;
496 }
497
498 gboolean
499 webkit_osr_mime_type_policy_typedecision_requested_callback(WebKitWebView *webView,
500 WebKitWebFrame *frame,
501 WebKitNetworkRequest *request,
502 gchar *mimetype,
503 WebKitWebPolicyDecision *policy_decision,
504 gpointer user_data)
505 {
506 printf("mime policy requested\n");
507 // this function makes webkit send a download signal for all unknown mime types
508 // TODO defer the decision to lisp, so that its possible to make Emacs handle text mime for instance
509 if(!webkit_web_view_can_show_mime_type(webView, mimetype)){
510 webkit_web_policy_decision_download (policy_decision);
511 return TRUE;
512 }else{
513 return FALSE;
514 }
515 }
516
517
518 gboolean
519 webkit_osr_new_window_policy_decision_requested_callback(WebKitWebView *webView,
520 WebKitWebFrame *frame,
521 WebKitNetworkRequest *request,
522 WebKitWebNavigationAction *navigation_action,
523 WebKitWebPolicyDecision *policy_decision,
524 gpointer user_data)
525 {
526 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (webView), XG_XWIDGET);
527 printf("webkit_osr_new_window_policy_decision_requested_callback %s\n",
528 webkit_web_navigation_action_get_original_uri (navigation_action));
529
530 store_xwidget_event_string(xw, "new-window-policy-decision-requested", webkit_web_navigation_action_get_original_uri (navigation_action)
531 );
532 return FALSE;
533 }
534
535 gboolean
536 webkit_osr_navigation_policy_decision_requested_callback(WebKitWebView *webView,
537 WebKitWebFrame *frame,
538 WebKitNetworkRequest *request,
539 WebKitWebNavigationAction *navigation_action,
540 WebKitWebPolicyDecision *policy_decision,
541 gpointer user_data)
542 {
543 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (webView), XG_XWIDGET);
544 printf("webkit_osr_navigation_policy_decision_requested_callback %s\n",
545 webkit_web_navigation_action_get_original_uri (navigation_action));
546 store_xwidget_event_string(xw, "navigation-policy-decision-requested", webkit_web_navigation_action_get_original_uri (navigation_action)
547 );
548 return FALSE;
549 }
550
551 //for gtk3 offscreen rendered widgets
552 gboolean
553 xwidget_osr_draw_callback (GtkWidget *widget, cairo_t *cr, gpointer data)
554 {
555 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
556 struct xwidget_view* xv = (struct xwidget_view*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET_VIEW);
557
558 cairo_rectangle(cr, 0,0, xv->clip_right, xv->clip_bottom);//xw->width, xw->height);
559 cairo_clip(cr);
560
561 gtk_widget_draw (xw->widget_osr, cr);
562
563 return FALSE;
564 }
565
566 GtkWidget* xwgir_create_debug;
567
568
569
570 gboolean
571 xwidget_osr_event_forward (GtkWidget *widget,
572 GdkEvent *event,
573 gpointer user_data)
574 {
575 /* copy events that arrive at the outer widget to the offscreen widget */
576 struct xwidget* xw = (struct xwidget*) g_object_get_data (G_OBJECT (widget), XG_XWIDGET);
577 GdkEvent* eventcopy = gdk_event_copy(event);
578 //GdkEvent* eventcopy = gdk_event_new(GDK_BUTTON_PRESS);
579
580
581 //((GdkEventAny*)eventcopy)->window = gtk_widget_get_window(xw->widget_osr);
582 //eventcopy->any.window = gtk_widget_get_window(GTK_WIDGET (xw->widgetwindow_osr));
583 //((GdkEventAny*)eventcopy)->window = gtk_widget_get_window(xwgir_create_debug);
584 eventcopy->any.window = gtk_widget_get_window(xw->widget_osr);//gtk_widget_get_window(xwgir_create_debug);
585 //eventcopy->any.window = gtk_button_get_event_window(GTK_BUTTON(xw->widget_osr));//gtk_widget_get_window(xwgir_create_debug);
586 //eventcopy->button.x=200; eventcopy->button.y=200;
587 //event->button.button = GDK_BUTTON_PRIMARY; //debug
588
589 //eventcopy->any.window = xw->widgetwindow_osr;//gtk_widget_get_window(xwgir_create_debug);
590 /* eventcopy->any.send_event = TRUE; */
591 /* eventcopy->button.time = GDK_CURRENT_TIME; */
592 /* eventcopy->button.device = event->button.device; */
593
594
595 printf("xwidget_osr_event_forward redirect event to window:%d\n", ((GdkEventAny*)eventcopy)->window);
596 printf("A type:%d x:%f y:%f \n", event->type, event->button.x, event->button.y);
597 printf("B type:%d x:%f y:%f \n", eventcopy->type, eventcopy->button.x, eventcopy->button.y);
598 //gtk_button_get_event_window(xwgir_create_debug);
599 gtk_main_do_event(eventcopy); //TODO this will leak events. they should be deallocated later, perhaps in xwgir_event_callback
600 //printf("gtk_widget_event:%d\n",gtk_widget_event(xw->widget_osr, eventcopy));
601 //gdk_event_put(eventcopy);
602 //gdk_event_queue_append(eventcopy);
603 //gdk_event_free(eventcopy);
604 return TRUE; //dont propagate this event furter
605 //return FALSE; //dont propagate this event furter
606 }
607
608 GIRepository *girepository ;
609
610 DEFUN ("xwgir-require-namespace", Fxwgir_require_namespace, Sxwgir_require_namespace, 2,2,0,
611 doc: /*require a namespace. must be done for all namespaces we want to use, before using other xwgir functions.*/)
612 (Lisp_Object lnamespace, Lisp_Object lnamespace_version)
613 {
614 char* namespace = SDATA(lnamespace);
615 char* namespace_version = SDATA(lnamespace_version);
616 GError *error = NULL;
617
618 girepository = g_irepository_get_default();
619 g_irepository_require(girepository, namespace, namespace_version, 0, &error);
620 if (error) {
621 g_error("ERROR: %s\n", error->message);
622 return Qnil;
623 }
624 return Qt;
625 }
626
627 GtkWidget* xwgir_create(char* class, char* namespace){
628 //TODO this is more or less the same as xwgir-call-method, so should be refactored
629 //create a gtk widget, given its name
630 //find the constructor
631 //call it
632 //also figure out how to pass args
633
634 GError *error = NULL;
635 GIArgument return_value;
636
637 GIObjectInfo* obj_info = g_irepository_find_by_name(girepository, namespace, class);
638 GIFunctionInfo* f_info = g_object_info_find_method (obj_info, "new");
639 g_function_info_invoke(f_info,
640 NULL, 0,
641 NULL, 0,
642 &return_value,
643 NULL);
644 xwgir_create_debug = return_value.v_pointer;
645 return return_value.v_pointer;
646
647 }
648
649 int
650 xwgir_convert_lisp_to_gir_arg(GIArgument* giarg,
651 GIArgInfo* arginfo,
652 Lisp_Object lisparg )
653 {
654
655 GITypeTag tag;
656 gboolean is_pointer;
657 gboolean is_enum;
658 tag = g_type_info_get_tag (g_arg_info_get_type (arginfo));
659
660 switch (tag)
661 {
662 case GI_TYPE_TAG_BOOLEAN:
663 giarg->v_boolean = XFASTINT(lisparg);
664 break;
665 case GI_TYPE_TAG_INT8:
666 giarg->v_int8 = XFASTINT(lisparg);
667 break;
668 case GI_TYPE_TAG_UINT8:
669 giarg->v_uint8 = XFASTINT(lisparg);
670 break;
671 case GI_TYPE_TAG_INT16:
672 giarg->v_int16 = XFASTINT(lisparg);
673 break;
674 case GI_TYPE_TAG_UINT16:
675 giarg->v_uint16 = XFASTINT(lisparg);
676 break;
677 case GI_TYPE_TAG_INT32:
678 giarg->v_int32 = XFASTINT(lisparg);
679 break;
680 case GI_TYPE_TAG_UINT32:
681 giarg->v_uint32 = XFASTINT(lisparg);
682 break;
683
684 case GI_TYPE_TAG_INT64:
685 giarg->v_int64 = XFASTINT(lisparg);
686 break;
687 case GI_TYPE_TAG_UINT64:
688 giarg->v_uint64 = XFASTINT(lisparg);
689 break;
690
691
692 case GI_TYPE_TAG_FLOAT:
693 giarg->v_float = XFLOAT_DATA(lisparg);
694 break;
695
696 case GI_TYPE_TAG_DOUBLE:
697 giarg->v_double = XFLOAT_DATA(lisparg);
698 break;
699
700 case GI_TYPE_TAG_UTF8:
701 case GI_TYPE_TAG_FILENAME:
702 //giarg->v_string = SDATA(lisparg);
703 giarg->v_pointer = SDATA(lisparg);
704 break;
705
706 case GI_TYPE_TAG_ARRAY:
707 case GI_TYPE_TAG_GLIST:
708 case GI_TYPE_TAG_GSLIST:
709 case GI_TYPE_TAG_GHASH:
710 case GI_TYPE_TAG_ERROR:
711 case GI_TYPE_TAG_INTERFACE:
712 case GI_TYPE_TAG_VOID:
713 case GI_TYPE_TAG_UNICHAR:
714 case GI_TYPE_TAG_GTYPE:
715 //?? i dont know how to handle these yet TODO
716 printf("failed in my lisp to gir arg conversion duties. sob!\n");
717 return -1;
718 break;
719 }
720 return 0;
721 }
722
723 #if 0
724 void
725 refactor_attempt(){
726 //this methhod should be called from xwgir-xwidget-call-method and from xwgir xwidget construction
727 char* class = SDATA(Fcar(Fcdr(Fget(xw->type, QCxwgir_class))));
728
729 GIObjectInfo* obj_info = g_irepository_find_by_name(girepository, namespace, class);
730 GIFunctionInfo* f_info = g_object_info_find_method (obj_info, SDATA(method));
731
732 //loop over args, convert from lisp to primitive type, given arg introspection data
733 //TODO g_callable_info_get_n_args(f_info) should match
734 int argscount = XFASTINT(Flength(arguments));
735 if(argscount != g_callable_info_get_n_args(f_info)){
736 printf("xwgir call method arg count doesn match! \n");
737 return Qnil;
738 }
739 int i;
740 for (i = 1; i < argscount + 1; ++i)
741 {
742 xwgir_convert_lisp_to_gir_arg(&in_args[i], g_callable_info_get_arg(f_info, i - 1), Fnth(i - 1, arguments));
743 }
744
745 in_args[0].v_pointer = widget;
746 if(g_function_info_invoke(f_info,
747 in_args, argscount + 1,
748 NULL, 0,
749 &return_value,
750 &error)) {
751 //g_error("ERROR: %s\n", error->message);
752 printf("invokation error\n");
753 return Qnil;
754 }
755 return Qt;
756 }
757 #endif /* 0 */
758
759 DEFUN ("xwgir-xwidget-call-method", Fxwgir_xwidget_call_method, Sxwgir_xwidget_call_method, 3, 3, 0,
760 doc: /* call xwidget object method.*/)
761 (Lisp_Object xwidget, Lisp_Object method, Lisp_Object arguments)
762 {
763 CHECK_XWIDGET (xwidget);
764 GError *error = NULL;
765 GIArgument return_value;
766 GIArgument in_args[20];
767
768
769 struct xwidget* xw;
770 if (NILP (xwidget)) { printf("ERROR xwidget nil\n"); return Qnil; };
771 xw = XXWIDGET(xwidget);
772 if(NULL == xw) printf("ERROR xw is 0\n");
773 char* namespace = SDATA(Fcar(Fget(xw->type, QCxwgir_class)));
774 //we need the concrete widget, which happens in 2 ways depending on OSR or not TODO
775 GtkWidget* widget = NULL;
776 if(NULL == xw->widget_osr) {
777 widget = xwidget_view_lookup (xw, XWINDOW(FRAME_SELECTED_WINDOW (SELECTED_FRAME ()))) -> widget;
778 } else {
779 widget = xw->widget_osr;
780 }
781
782 //char* class = SDATA(SYMBOL_NAME(xw->type)); //this works but is unflexible
783 //figure out the class from the widget instead
784 /* printf("type class: %s %s\n", G_OBJECT_TYPE_NAME(widget), G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(widget))); */
785 /* char* class = G_OBJECT_TYPE_NAME(widget); //gives "GtkButton"(I want "Button") */
786 /* class += strlen(namespace); //TODO check for corresponding api method. but this seems to work. */
787
788 char* class = SDATA(Fcar(Fcdr(Fget(xw->type, QCxwgir_class))));
789
790 GIObjectInfo* obj_info = g_irepository_find_by_name(girepository, namespace, class);
791 GIFunctionInfo* f_info = g_object_info_find_method (obj_info, SDATA(method));
792
793 //loop over args, convert from lisp to primitive type, given arg introspection data
794 //TODO g_callable_info_get_n_args(f_info) should match
795 int argscount = XFASTINT(Flength(arguments));
796 if(argscount != g_callable_info_get_n_args(f_info)){
797 printf("xwgir call method arg count doesn match! \n");
798 return Qnil;
799 }
800 int i;
801 Lisp_Object n;
802 for (i = 1; i < argscount + 1; ++i)
803 {
804 XSETFASTINT (n, i - 1);
805 xwgir_convert_lisp_to_gir_arg(&in_args[i], g_callable_info_get_arg(f_info, i - 1), Fnth(n, arguments));
806 }
807
808 in_args[0].v_pointer = widget;
809 if(g_function_info_invoke(f_info,
810 in_args, argscount + 1,
811 NULL, 0,
812 &return_value,
813 &error)) {
814 //g_error("ERROR: %s\n", error->message);
815 printf("invokation error\n");
816 return Qnil;
817 }
818 return Qt;
819 }
820
821 void
822 to_child (GtkWidget *bin,
823 double widget_x,
824 double widget_y,
825 double *x_out,
826 double *y_out)
827 {
828 *x_out = widget_x;
829 *y_out = widget_y;
830 }
831
832
833 GdkWindow *
834 offscreen_pick_embedded_child (GdkWindow *window,
835 double x,
836 double y,
837 gpointer *data)
838 {
839 //in this simple case we assume the window contains a single widget. easy.
840 //but then we get the problem that the widget cant be embedded in several windows
841 return gtk_widget_get_window (GTK_WIDGET (data));
842 }
843
844 void
845 offscreen_to_embedder (GdkWindow *window,
846 gdouble offscreen_x,
847 gdouble offscreen_y,
848 gpointer embedder_x,
849 gpointer embedder_y,
850 gpointer data)
851 {
852 * (gdouble *) embedder_x = offscreen_x;
853 * (gdouble *) embedder_y = offscreen_y;
854 }
855
856 void
857 offscreen_from_embedder (GdkWindow *window,
858 gdouble embedder_x,
859 gdouble embedder_y,
860 gpointer offscreen_x,
861 gpointer offscreen_y,
862 gpointer user_data)
863 {
864 * (gdouble *) offscreen_x = embedder_x;
865 * (gdouble *) offscreen_y = embedder_y;
866 }
867
868 gboolean
869 xwidget_osr_event_set_embedder (GtkWidget *widget,
870 GdkEvent *event,
871 gpointer data)
872 {
873 struct xwidget_view *xv = (struct xwidget_view *) data;
874 struct xwidget *xww = XXWIDGET (xv->model);
875 printf("gdk_offscreen_window_set_embedder %d %d\n",
876 GDK_IS_WINDOW(gtk_widget_get_window (xww->widget_osr)),
877 GDK_IS_WINDOW(gtk_widget_get_window (GTK_WIDGET (xv->widget))));
878 gdk_offscreen_window_set_embedder (gtk_widget_get_window (xww->widgetwindow_osr),
879 gtk_widget_get_window (xv->widget));
880 }
881
882
883 /* initializes and does initial placement of an xwidget view on screen */
884 struct xwidget_view*
885 xwidget_init_view (struct xwidget *xww,
886 struct glyph_string *s,
887 int x, int y)
888 {
889 struct xwidget_view *xv = allocate_xwidget_view();
890 Lisp_Object val;
891 GdkColor color;
892
893 XSETXWIDGET_VIEW (val, xv) ;
894 Vxwidget_view_list = Fcons (val, Vxwidget_view_list);
895
896 XSETWINDOW(xv->w, s->w);
897 XSETXWIDGET(xv->model, xww);
898
899 //widget creation
900 if(EQ(xww->type, Qbutton))
901 {
902 xv->widget = gtk_button_new_with_label (XSTRING(xww->title)->data);
903 g_signal_connect (G_OBJECT (xv->widget), "clicked",
904 G_CALLBACK (buttonclick_handler), xv); // the view rather than the model
905 } else if (EQ(xww->type, Qtoggle)) {
906 xv->widget = gtk_toggle_button_new_with_label (XSTRING(xww->title)->data);
907 //xv->widget = gtk_entry_new ();//temp hack to experiment with key propagation TODO entry widget is useful for testing
908 } else if (EQ(xww->type, Qsocket)) {
909 xv->widget = gtk_socket_new ();
910 g_signal_connect_after(xv->widget, "plug-added", G_CALLBACK(xwidget_plug_added), "plug added");
911 g_signal_connect_after(xv->widget, "plug-removed", G_CALLBACK(xwidget_plug_removed), "plug removed");
912 //TODO these doesnt help
913 gtk_widget_add_events(xv->widget, GDK_KEY_PRESS);
914 gtk_widget_add_events(xv->widget, GDK_KEY_RELEASE);
915 } else if (EQ(xww->type, Qslider)) {
916 xv->widget =
917 //gtk_hscale_new (GTK_ADJUSTMENT(gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 10.0, 10.0)));
918 gtk_hscale_new_with_range ( 0.0, 100.0, 10.0);
919 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
920 xv->handler_id = g_signal_connect_after(xv->widget, "value-changed", G_CALLBACK(xwidget_slider_changed), "slider changed");
921 } else if (EQ(xww->type, Qcairo)) {
922 //Cairo view
923 //uhm cairo is differentish in gtk 3.
924 //gdk_cairo_create (gtk_widget_get_window (FRAME_GTK_WIDGET (s->f)));
925 xv->widget = gtk_drawing_area_new();
926 g_signal_connect (G_OBJECT ( xv->widget), "draw",
927 G_CALLBACK (xwidget_osr_draw_callback), NULL);
928
929 } else if (EQ(xww->type, Qwebkit_osr)||
930 EQ(xww->type, Qsocket_osr)||
931 (!NILP (Fget(xww->type, QCxwgir_class))))//xwgir widgets are OSR
932 {
933 printf("osr init:%s\n",SDATA(SYMBOL_NAME(xww->type)));
934 xv->widget = gtk_drawing_area_new();
935 gtk_widget_set_app_paintable ( xv->widget, TRUE); //because expose event handling
936 gtk_widget_add_events(xv->widget, GDK_ALL_EVENTS_MASK);
937
938 /* Draw the view on damage-event */
939 g_signal_connect (G_OBJECT (xww->widgetwindow_osr), "damage-event",
940 G_CALLBACK (offscreen_damage_event), xv->widget);
941
942 if (EQ(xww->type, Qwebkit_osr)){
943 /* ///xwgir debug */
944 /* //forward events. this isnt compatible with the set_embedded strategy */
945 g_signal_connect (G_OBJECT ( xv->widget), "button-press-event",
946 G_CALLBACK (xwidget_osr_event_forward), NULL);
947 g_signal_connect (G_OBJECT ( xv->widget), "button-release-event",
948 G_CALLBACK (xwidget_osr_event_forward), NULL);
949 g_signal_connect (G_OBJECT ( xv->widget), "motion-notify-event",
950 G_CALLBACK (xwidget_osr_event_forward), NULL);
951 }else{
952 //xwgir debug , orthogonal to forwarding
953 g_signal_connect (G_OBJECT (xv->widget), "enter-notify-event",
954 G_CALLBACK (xwidget_osr_event_set_embedder), xv);
955 }
956
957 //draw
958 g_signal_connect (G_OBJECT (xv->widget), "draw",
959 G_CALLBACK (xwidget_osr_draw_callback), NULL);
960
961 }
962 //else return NULL;
963
964 //widget realization
965 //make container widget 1st, and put the actual widget inside the container
966 //later, drawing should crop container window if necessary to handle case where xwidget
967 //is partially obscured by other emacs windows
968 //other containers than gtk_fixed where explored, but gtk_fixed had the most predictable behaviour so far.
969 xv->emacswindow = FRAME_GTK_WIDGET (s->f);
970 xv->widgetwindow = gtk_fixed_new ();
971 gtk_widget_set_has_window(xv->widgetwindow, TRUE);
972 gtk_container_add (GTK_CONTAINER (xv->widgetwindow), xv->widget);
973
974 //store some xwidget data in the gtk widgets
975 g_object_set_data (G_OBJECT (xv->widget), XG_FRAME_DATA, (gpointer) (s->f)); //the emacs frame
976 g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET, (gpointer) (xww)); //the xwidget
977 g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET_VIEW, (gpointer) (xv)); //the xwidget
978 g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET, (gpointer) (xww)); //the xwidget window
979 g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET_VIEW, (gpointer) (xv)); //the xwidget window
980
981
982 gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xww->width, xww->height);
983 gtk_widget_set_size_request (xv->widgetwindow, xww->width, xww->height);
984 gtk_fixed_put (GTK_FIXED (FRAME_GTK_WIDGET (s->f)), xv->widgetwindow, x, y);
985 xv->x = x; xv->y = y;
986 gtk_widget_show_all (xv->widgetwindow);
987
988
989
990 //widgettype specific initialization only possible after realization
991 if (EQ(xww->type, Qsocket)) {
992 printf ("xwid:%d socket id:%x %d\n",
993 xww,
994 gtk_socket_get_id (GTK_SOCKET (xv->widget)),
995 gtk_socket_get_id (GTK_SOCKET (xv->widget)));
996 send_xembed_ready_event (xww,
997 gtk_socket_get_id (GTK_SOCKET (xv->widget)));
998 //gtk_widget_realize(xw->widget);
999 }
1000
1001 //////////////////////////////////////////////////////////////
1002 // xwgir debug
1003 if (//EQ(xww->type, Qwebkit_osr)|| //TODO should be able to choose compile time which method to use with webkit
1004 EQ(xww->type, Qsocket_osr)||
1005 (!NILP (Fget(xww->type, QCxwgir_class))))//xwgir widgets are OSR
1006 {
1007 printf("gdk_offscreen_window_set_embedder %d %d\n",
1008 GDK_IS_WINDOW(gtk_widget_get_window (xww->widget_osr)),
1009 GDK_IS_WINDOW(gtk_widget_get_window (GTK_WIDGET (xv->widget))));
1010 // set_embedder needs to be called after xv->widget realization
1011 gdk_offscreen_window_set_embedder (gtk_widget_get_window (xww->widgetwindow_osr),
1012 gtk_widget_get_window (xv->widget));
1013 g_signal_connect (gtk_widget_get_window (xv->widget), "pick-embedded-child",
1014 G_CALLBACK (offscreen_pick_embedded_child), xww->widgetwindow_osr);
1015
1016 g_signal_connect (gtk_widget_get_window (xww->widgetwindow_osr), "from-embedder",
1017 G_CALLBACK (offscreen_from_embedder), NULL);
1018 g_signal_connect (gtk_widget_get_window (xww->widgetwindow_osr), "to-embedder",
1019 G_CALLBACK (offscreen_to_embedder), NULL);
1020 }
1021 ////////////////////////////////////////
1022
1023 return xv;
1024 }
1025
1026
1027 void
1028 x_draw_xwidget_glyph_string (struct glyph_string *s)
1029 {
1030 /*
1031 this method is called by the redisplay engine and places the xwidget on screen.
1032 moving and clipping is done here. also view init.
1033
1034 */
1035 int box_line_hwidth = eabs (s->face->box_line_width);
1036 int box_line_vwidth = max (s->face->box_line_width, 0);
1037 int height = s->height;
1038 struct xwidget *xww = s->xwidget;
1039 struct xwidget_view *xv = xwidget_view_lookup(xww, s->w);
1040 int clip_right; int clip_bottom; int clip_top; int clip_left;
1041
1042 int x = s->x;
1043 int y = s->y + (s->height / 2) - (xww->height / 2);
1044 int moved=0;
1045
1046 /* We do it here in the display loop because there is no other
1047 time to know things like window placement etc.
1048 */
1049 printf ("xv init for xw %d\n", xww);
1050 xv = xwidget_init_view (xww, s, x, y);
1051
1052 //calculate clipping, which is used for all manner of onscreen xwidget views
1053 //each widget border can get clipped by other emacs objects so there are four clipping variables
1054 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));
1055 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));
1056
1057 clip_bottom = min (xww->height, WINDOW_BOTTOM_EDGE_Y (s->w) - WINDOW_MODE_LINE_HEIGHT (s->w) - y);
1058 clip_top = max(0, WINDOW_TOP_EDGE_Y(s->w) -y );
1059
1060 //we are conserned with movement of the onscreen area. the area might sit still when the widget actually moves
1061 //this happens when an emacs window border moves across a widget window
1062 //so, if any corner of the outer widget clippng window moves, that counts as movement here, even
1063 //if it looks like no movement happens because the widget sits still inside the clipping area.
1064 //the widget can also move inside the clipping area, which happens later
1065 moved = (xv->x + xv->clip_left != x+clip_left)
1066 || ((xv->y + xv->clip_top)!= (y+clip_top));
1067 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);
1068 else
1069 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);
1070 xv->x = x;
1071 xv->y = y;
1072 if (moved) //has it moved?
1073 {
1074 if (1)//!xwidget_hidden(xv)) //hidden equals not being seen during redisplay
1075 {
1076 //TODO should be possible to use xwidget_show_view here
1077 gtk_fixed_move (GTK_FIXED (FRAME_GTK_WIDGET (s->f)),
1078 xv->widgetwindow,
1079 x + clip_left, y + clip_top);
1080 }
1081 }
1082 //clip the widget window if some parts happen to be outside drawable area
1083 //an emacs window is not a gtk window, a gtk window covers the entire frame
1084 //cliping might have changed even if we havent actualy moved, we try figure out when we need to reclip for real
1085 if((xv->clip_right != clip_right)
1086 || (xv->clip_bottom != clip_bottom)
1087 || (xv->clip_top != clip_top)
1088 || (xv->clip_left != clip_left)){
1089 gtk_widget_set_size_request (xv->widgetwindow, clip_right + clip_left, clip_bottom + clip_top);
1090 gtk_fixed_move(GTK_FIXED(xv->widgetwindow), xv->widget, -clip_left, -clip_top);
1091 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);
1092
1093
1094 xv->clip_right = clip_right; xv->clip_bottom = clip_bottom; xv->clip_top = clip_top;xv->clip_left = clip_left;
1095 }
1096 //if emacs wants to repaint the area where the widget lives, queue a redraw
1097 //TODO it seems its possible to get out of sync with emacs redraws so emacs bg sometimes shows up instead of xwidget
1098 //its just a visual glitch though
1099 if (!xwidget_hidden(xv)){
1100 gtk_widget_queue_draw (xv->widgetwindow);
1101 gtk_widget_queue_draw (xv->widget);
1102 }
1103 }
1104
1105
1106 #ifdef HAVE_WEBKIT_OSR
1107
1108 //FUGLY macro that checks WEBKIT_IS_WEB_VIEW(xw->widget_osr) first
1109 #define WEBKIT_FN_INIT() \
1110 struct xwidget* xw; \
1111 CHECK_XWIDGET (xwidget); \
1112 if(NILP (xwidget)) {printf("ERROR xwidget nil\n"); return Qnil;}; \
1113 xw = XXWIDGET(xwidget); \
1114 if(NULL == xw) printf("ERROR xw is 0\n"); \
1115 if((NULL == xw->widget_osr) || !WEBKIT_IS_WEB_VIEW(xw->widget_osr)){ \
1116 printf("ERROR xw->widget_osr does not hold a webkit instance\n");\
1117 return Qnil;\
1118 };
1119
1120
1121 DEFUN ("xwidget-webkit-goto-uri", Fxwidget_webkit_goto_uri, Sxwidget_webkit_goto_uri,
1122 2, 2, 0,
1123 doc: /* webkit goto uri.*/)
1124 (Lisp_Object xwidget, Lisp_Object uri)
1125 {
1126 WEBKIT_FN_INIT();
1127 webkit_web_view_load_uri ( WEBKIT_WEB_VIEW(xw->widget_osr), SDATA(uri));
1128 return Qnil;
1129 }
1130
1131
1132 DEFUN ("xwidget-webkit-execute-script", Fxwidget_webkit_execute_script, Sxwidget_webkit_execute_script,
1133 2, 2, 0,
1134 doc: /* webkit exec js.*/)
1135 (Lisp_Object xwidget, Lisp_Object script)
1136 {
1137 WEBKIT_FN_INIT();
1138 webkit_web_view_execute_script( WEBKIT_WEB_VIEW(xw->widget_osr), SDATA(script));
1139 return Qnil;
1140 }
1141
1142 DEFUN ("xwidget-webkit-get-title", Fxwidget_webkit_get_title, Sxwidget_webkit_get_title,
1143 1, 1, 0,
1144 doc: /* webkit get title. can be used to work around exec method lacks return val*/)
1145 (Lisp_Object xwidget)
1146 {
1147 //TODO support multibyte strings
1148 WEBKIT_FN_INIT();
1149 const gchar* str=webkit_web_view_get_title( WEBKIT_WEB_VIEW(xw->widget_osr));
1150 //return make_string_from_bytes(str, wcslen((const wchar_t *)str), strlen(str));
1151 if(str == 0){
1152 //TODO maybe return Qnil instead. I suppose webkit returns nullpointer when doc is not properly loaded or something
1153 printf("xwidget-webkit-get-title null webkit title\n");
1154 return build_string("");
1155 }
1156 return build_string(str);
1157 }
1158
1159 //TODO missnamed
1160 DEFUN("xwidget-disable-plugin-for-mime", Fxwidget_disable_plugin_for_mime , Sxwidget_disable_plugin_for_mime,
1161 1,1,0, doc: /* */)
1162 (Lisp_Object mime)
1163 {
1164 WebKitWebPlugin *wp = webkit_web_plugin_database_get_plugin_for_mimetype
1165 (webkit_get_web_plugin_database(), SDATA(mime));
1166 if(wp == NULL) return Qnil;
1167 if(webkit_web_plugin_get_enabled (wp)){
1168 webkit_web_plugin_set_enabled (wp, FALSE);
1169 return Qt;
1170 }
1171 return Qnil;
1172 }
1173
1174
1175 void
1176 xwidget_webkit_dom_dump(WebKitDOMNode* parent)
1177 {
1178 WebKitDOMNodeList* list;
1179 int i;
1180 int length;
1181 WebKitDOMNode* attribute;
1182 WebKitDOMNamedNodeMap* attrs;
1183 WebKitDOMNode* child;
1184 printf("node:%d type:%d name:%s content:%s\n",
1185 parent,
1186 webkit_dom_node_get_node_type(parent),//1 element 3 text 8 comment 2 attribute
1187 webkit_dom_node_get_local_name(parent),
1188 webkit_dom_node_get_text_content(parent));
1189
1190 if(webkit_dom_node_has_attributes(parent)){
1191 attrs = webkit_dom_node_get_attributes(parent);
1192
1193 length = webkit_dom_named_node_map_get_length(attrs);
1194 for (int i = 0; i < length; i++) {
1195 attribute = webkit_dom_named_node_map_item(attrs,i);
1196 printf(" attr node:%d type:%d name:%s content:%s\n",
1197 attribute,
1198 webkit_dom_node_get_node_type(attribute),//1 element 3 text 8 comment
1199 webkit_dom_node_get_local_name(attribute),
1200 webkit_dom_node_get_text_content(attribute));
1201 }
1202 }
1203 list = webkit_dom_node_get_child_nodes(parent);
1204 length = webkit_dom_node_list_get_length(list);
1205
1206 for (int i = 0; i < length; i++) {
1207 child = webkit_dom_node_list_item(list, i);
1208 //if(webkit_dom_node_has_child_nodes(child))
1209 xwidget_webkit_dom_dump(child);
1210 }
1211 }
1212
1213
1214 DEFUN ("xwidget-webkit-dom-dump", Fxwidget_webkit_dom_dump, Sxwidget_webkit_dom_dump,
1215 1, 1, 0,
1216 doc: /* webkit dom dump*/)
1217 (Lisp_Object xwidget)
1218 {
1219 WEBKIT_FN_INIT();
1220 xwidget_webkit_dom_dump(WEBKIT_DOM_NODE(webkit_web_view_get_dom_document( WEBKIT_WEB_VIEW(xw->widget_osr))));
1221 return Qnil;
1222 }
1223
1224
1225
1226 #endif /* HAVE_WEBKIT_OSR */
1227
1228
1229
1230
1231
1232 DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 3, 3, 0, doc:
1233 /* resize xwidgets*/)
1234 (Lisp_Object xwidget, Lisp_Object new_width, Lisp_Object new_height)
1235 {
1236 CHECK_XWIDGET (xwidget);
1237 struct xwidget* xw = XXWIDGET(xwidget);
1238 struct xwidget_view *xv;
1239 int w, h;
1240
1241 CHECK_NUMBER (new_width);
1242 CHECK_NUMBER (new_height);
1243 w = XFASTINT (new_width);
1244 h = XFASTINT (new_height);
1245
1246
1247 printf("resize xwidget %d (%d,%d)->(%d,%d)\n",xw, xw->width,xw->height,w,h);
1248 xw->width=w;
1249 xw->height=h;
1250 //if theres a osr resize it 1st
1251 if(xw->widget_osr){
1252 printf("resize xwidget_osr\n");
1253 //gtk_container_set_resize_mode ( GTK_WINDOW(xw->widgetwindow_osr), GTK_RESIZE_QUEUE);
1254 //gtk_container_set_resize_mode ( GTK_WINDOW(xw->widget_osr), GTK_RESIZE_QUEUE);
1255
1256
1257 //gtk_layout_set_size (GTK_LAYOUT (xw->widgetwindow_osr), xw->width, xw->height);
1258 gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, xw->height); //minimum size
1259 //gtk_window_resize( GTK_WINDOW(xw->widget_osr), xw->width, xw->height);
1260 gtk_window_resize( GTK_WINDOW(xw->widgetwindow_osr), xw->width, xw->height);
1261 //gtk_container_resize_children ( GTK_WINDOW(xw->widgetwindow_osr));
1262 gtk_container_resize_children (GTK_CONTAINER(xw->widgetwindow_osr));
1263
1264 }
1265
1266 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail)) //TODO MVC refactor lazy linear search
1267 {
1268 if (XWIDGET_VIEW_P (XCAR (tail))) {
1269 xv = XXWIDGET_VIEW (XCAR (tail));
1270 if(XXWIDGET (xv->model) == xw) {
1271 gtk_layout_set_size (GTK_LAYOUT (xv->widgetwindow), xw->width, xw->height);
1272 gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xw->width, xw->height);
1273 }
1274 }
1275 }
1276
1277 return Qnil;
1278 }
1279
1280 DEFUN ("xwidget-size-request", Fxwidget_size_request, Sxwidget_size_request, 1, 1, 0, doc:
1281 /* desired size (TODO crashes if arg not osr widget)*/)
1282 (Lisp_Object xwidget)
1283 {
1284 CHECK_XWIDGET (xwidget);
1285 GtkRequisition requisition;
1286 Lisp_Object rv;
1287 gtk_widget_size_request(XXWIDGET(xwidget)->widget_osr, &requisition);
1288 rv = Qnil;
1289 rv = Fcons (make_number(requisition.height), rv);
1290 rv = Fcons (make_number(requisition.width), rv);
1291 return rv;
1292
1293 }
1294
1295 DEFUN ("xwidgetp", Fxwidgetp, Sxwidgetp, 1, 1, 0,
1296 doc: /* Return t if OBJECT is a xwidget. */)
1297 (Lisp_Object object)
1298 {
1299 return XWIDGETP (object) ? Qt : Qnil;
1300 }
1301
1302 DEFUN ("xwidget-view-p", Fxwidget_view_p, Sxwidget_view_p, 1, 1, 0,
1303 doc: /* Return t if OBJECT is a xwidget-view. */)
1304 (Lisp_Object object)
1305 {
1306 return XWIDGET_VIEW_P (object) ? Qt : Qnil;
1307 }
1308
1309 DEFUN ("xwidget-info", Fxwidget_info , Sxwidget_info, 1,1,0, doc: /* get xwidget props */)
1310 (Lisp_Object xwidget)
1311 {
1312 CHECK_XWIDGET (xwidget);
1313 Lisp_Object info, n;
1314 struct xwidget* xw = XXWIDGET(xwidget);
1315
1316 info = Fmake_vector (make_number (4), Qnil);
1317 ASET (info, 0, xw->type);
1318 ASET (info, 1, xw->title);
1319 XSETFASTINT(n, xw->width);
1320 ASET (info, 2, n);
1321 XSETFASTINT(n, xw->height);
1322 ASET (info, 3, n);
1323
1324 return info;
1325 }
1326
1327 DEFUN ("xwidget-view-info", Fxwidget_view_info , Sxwidget_view_info, 1, 1, 0, doc: /* get xwidget view props */)
1328 (Lisp_Object xwidget_view)
1329 {
1330 CHECK_XWIDGET_VIEW (xwidget_view);
1331 struct xwidget_view *xv = XXWIDGET_VIEW (xwidget_view);
1332 Lisp_Object info;
1333
1334 info = Fmake_vector (make_number (6), Qnil);
1335 ASET (info, 0, make_number(xv->x));
1336 ASET (info, 1, make_number(xv->y));
1337 ASET (info, 2, make_number(xv->clip_right));
1338 ASET (info, 3, make_number(xv->clip_bottom));
1339 ASET (info, 4, make_number(xv->clip_top));
1340 ASET (info, 5, make_number(xv->clip_left));
1341
1342 return info;
1343 }
1344
1345 DEFUN ("xwidget-view-model", Fxwidget_view_model, Sxwidget_view_model,
1346 1, 1, 0,
1347 doc: /* get xwidget view model */)
1348 (Lisp_Object xwidget_view)
1349 {
1350 CHECK_XWIDGET_VIEW (xwidget_view);
1351 return XXWIDGET_VIEW (xwidget_view)->model;
1352 }
1353
1354 DEFUN ("xwidget-view-window", Fxwidget_view_window, Sxwidget_view_window,
1355 1, 1, 0,
1356 doc: /* get xwidget view window */)
1357 (Lisp_Object xwidget_view)
1358 {
1359 CHECK_XWIDGET_VIEW (xwidget_view);
1360 return XXWIDGET_VIEW (xwidget_view)->w;
1361 }
1362
1363 DEFUN ("xwidget-send-keyboard-event", Fxwidget_send_keyboard_event, Sxwidget_send_keyboard_event, 2, 2, 0, doc:/* synthesize a kbd event for a xwidget. */
1364 )
1365 (Lisp_Object xwidget, Lisp_Object keydescriptor)
1366 {
1367 //TODO this code crashes for offscreen widgets and ive tried many different strategies
1368 //int keyval = 0x058; //X
1369 int keyval = XFASTINT(keydescriptor); //X
1370 char *keystring = "";
1371 GdkKeymapKey* keys;
1372 gint n_keys;
1373 GdkDeviceManager* manager;
1374 struct xwidget *xw;
1375 GtkWidget* widget;
1376 GdkEventKey* ev;
1377 Lisp_Object window;
1378 //popup_activated_flag = 1; //TODO just a hack
1379 gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), keyval, &keys, &n_keys);
1380
1381 xw = XXWIDGET(xwidget);
1382
1383 ev = (GdkEventKey*)gdk_event_new(GDK_KEY_PRESS);
1384
1385
1386 //todo what about windowless widgets?
1387
1388 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1389
1390
1391 //TODO maybe we also need to special case sockets by picking up the plug rather than the socket
1392 if(xw->widget_osr)
1393 widget = xw->widget_osr;
1394 else
1395 widget = xwidget_view_lookup(xw, XWINDOW(window))->widget;
1396
1397 ev->window = gtk_widget_get_window(widget);
1398 gtk_widget_grab_focus(widget);
1399 ev->send_event = FALSE;
1400
1401 ev->hardware_keycode = keys[0].keycode;
1402 ev->group = keys[0].group;
1403
1404 ev->keyval = keyval;
1405 ev->time = GDK_CURRENT_TIME;
1406
1407 //ev->device = gdk_device_get_core_pointer();
1408 manager = gdk_display_get_device_manager(gdk_window_get_display(ev->window));
1409 gdk_event_set_device ((GdkEvent*)ev, gdk_device_manager_get_client_pointer(manager));
1410 gdk_event_put((GdkEvent*)ev);
1411 //g_signal_emit_by_name(ev->window,"key-press-event", ev);
1412
1413 ev->type = GDK_KEY_RELEASE;
1414 gdk_event_put((GdkEvent*)ev);
1415 //g_signal_emit_by_name(ev->window,"key-release-event", ev);
1416 //gtk_main_do_event(ev);
1417
1418 //TODO
1419 //if I delete the event the receiving component eventually crashes.
1420 //it ough TDTRT since event_put is supposed to copy the event
1421 //so probably this leaks events now
1422 //gdk_event_free((GdkEvent*)ev);
1423
1424 return Qnil;
1425 }
1426
1427 DEFUN ("delete-xwidget-view", Fdelete_xwidget_view, Sdelete_xwidget_view,
1428 1, 1, 0,
1429 doc: /* Delete the XWIDGET-VIEW. */)
1430 (Lisp_Object xwidget_view)
1431 {
1432 CHECK_XWIDGET_VIEW (xwidget_view);
1433 struct xwidget_view *xv = XXWIDGET_VIEW (xwidget_view);
1434 gtk_widget_destroy(xv->widgetwindow);
1435 Vxwidget_view_list = Fdelq (xwidget_view, Vxwidget_view_list);
1436 }
1437
1438 DEFUN ("xwidget-view-lookup", Fxwidget_view_lookup, Sxwidget_view_lookup,
1439 1, 2, 0,
1440 doc: /* Return the xwidget-view associated to XWIDGET in
1441 WINDOW if specified, otherwise it uses the selected window. */)
1442 (Lisp_Object xwidget, Lisp_Object window)
1443 {
1444 CHECK_XWIDGET (xwidget);
1445
1446 if (NILP (window))
1447 window = Fselected_window();
1448 CHECK_WINDOW (window);
1449
1450 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail))
1451 {
1452 Lisp_Object xwidget_view = XCAR (tail);
1453 if (EQ (Fxwidget_view_model (xwidget_view), xwidget)
1454 && EQ (Fxwidget_view_window (xwidget_view), window))
1455 return xwidget_view;
1456 }
1457
1458 return Qnil;
1459 }
1460
1461 DEFUN ("set-frame-visible", Fset_frame_visible, Sset_frame_visible,
1462 2, 2, 0,
1463 doc: /* HACKY */)
1464 (Lisp_Object frame, Lisp_Object flag)
1465 {
1466 CHECK_FRAME (frame);
1467 struct frame *f = XFRAME (frame);
1468 SET_FRAME_VISIBLE (f, !NILP (flag));
1469 return flag;
1470 }
1471
1472 DEFUN ("xwidget-plist", Fxwidget_plist, Sxwidget_plist,
1473 1, 1, 0,
1474 doc: /* Return the plist of XWIDGET. */)
1475 (register Lisp_Object xwidget)
1476 {
1477 CHECK_XWIDGET (xwidget);
1478 return XXWIDGET (xwidget)->plist;
1479 }
1480
1481 DEFUN ("xwidget-buffer", Fxwidget_buffer, Sxwidget_buffer,
1482 1, 1, 0,
1483 doc: /* Return the buffer of XWIDGET. */)
1484 (register Lisp_Object xwidget)
1485 {
1486 CHECK_XWIDGET (xwidget);
1487 return XXWIDGET (xwidget)->buffer;
1488 }
1489
1490 DEFUN ("set-xwidget-plist", Fset_xwidget_plist, Sset_xwidget_plist,
1491 2, 2, 0,
1492 doc: /* Replace the plist of XWIDGET with PLIST. Returns PLIST. */)
1493 (register Lisp_Object xwidget, Lisp_Object plist)
1494 {
1495 CHECK_XWIDGET (xwidget);
1496 CHECK_LIST (plist);
1497
1498 XXWIDGET (xwidget)->plist = plist;
1499 return plist;
1500 }
1501
1502 DEFUN ("set-xwidget-query-on-exit-flag",
1503 Fset_xwidget_query_on_exit_flag, Sset_xwidget_query_on_exit_flag,
1504 2, 2, 0,
1505 doc: /* Specify if query is needed for XWIDGET when Emacs is
1506 exited. If the second argument FLAG is non-nil, Emacs will query the
1507 user before exiting or killing a buffer if XWIDGET is running. This
1508 function returns FLAG. */)
1509 (Lisp_Object xwidget, Lisp_Object flag)
1510 {
1511 CHECK_XWIDGET (xwidget);
1512 XXWIDGET (xwidget)->kill_without_query = NILP (flag);
1513 return flag;
1514 }
1515
1516 DEFUN ("xwidget-query-on-exit-flag",
1517 Fxwidget_query_on_exit_flag, Sxwidget_query_on_exit_flag,
1518 1, 1, 0,
1519 doc: /* Return the current value of query-on-exit flag for XWIDGET. */)
1520 (Lisp_Object xwidget)
1521 {
1522 CHECK_XWIDGET (xwidget);
1523 return (XXWIDGET (xwidget)->kill_without_query ? Qnil : Qt);
1524 }
1525
1526 void
1527 syms_of_xwidget (void)
1528 {
1529 int i;
1530
1531 defsubr (&Smake_xwidget);
1532 defsubr (&Sxwidgetp);
1533 DEFSYM (Qxwidgetp, "xwidgetp");
1534 defsubr (&Sxwidget_view_p);
1535 DEFSYM (Qxwidget_view_p, "xwidget-view-p");
1536 defsubr (&Sxwidget_info);
1537 defsubr (&Sxwidget_view_info);
1538 defsubr (&Sxwidget_resize);
1539 defsubr (&Sget_buffer_xwidgets);
1540 defsubr (&Sxwidget_view_model);
1541 defsubr (&Sxwidget_view_window);
1542 defsubr (&Sxwidget_view_lookup);
1543 defsubr (&Sxwidget_query_on_exit_flag);
1544 defsubr (&Sset_xwidget_query_on_exit_flag);
1545 defsubr (&Sset_frame_visible);
1546
1547 #ifdef HAVE_WEBKIT_OSR
1548 defsubr (&Sxwidget_webkit_goto_uri);
1549 defsubr (&Sxwidget_webkit_execute_script);
1550 defsubr (&Sxwidget_webkit_get_title);
1551 DEFSYM (Qwebkit_osr ,"webkit-osr");
1552 #endif
1553
1554 defsubr (&Sxwgir_xwidget_call_method );
1555 defsubr (&Sxwgir_require_namespace);
1556 defsubr (&Sxwidget_size_request );
1557 defsubr (&Sdelete_xwidget_view);
1558 defsubr (&Sxwidget_disable_plugin_for_mime);
1559
1560 defsubr (&Sxwidget_send_keyboard_event);
1561 defsubr (&Sxwidget_webkit_dom_dump);
1562 defsubr (&Sxwidget_plist);
1563 defsubr (&Sxwidget_buffer);
1564 defsubr (&Sset_xwidget_plist);
1565
1566 DEFSYM (Qxwidget, "xwidget");
1567
1568 DEFSYM (QCxwidget, ":xwidget");
1569 DEFSYM (QCxwgir_class, ":xwgir-class");
1570 DEFSYM (QCtitle, ":title");
1571
1572 /* Do not forget to update the docstring of make-xwidget if you add
1573 new types. */
1574 DEFSYM (Qbutton, "Button"); //changed to match the gtk class because xwgir(experimental and not really needed)
1575 DEFSYM (Qtoggle, "ToggleButton");
1576 DEFSYM (Qslider, "slider");
1577 DEFSYM (Qsocket, "socket");
1578 DEFSYM (Qsocket_osr, "socket-osr");
1579 DEFSYM (Qcairo, "cairo");
1580
1581 DEFSYM (QCplist, ":plist");
1582
1583 DEFVAR_LISP ("xwidget-list", Vxwidget_list, doc: /*xwidgets list*/);
1584 Vxwidget_list = Qnil;
1585
1586 DEFVAR_LISP ("xwidget-view-list", Vxwidget_view_list, doc: /*xwidget views list*/);
1587 Vxwidget_view_list = Qnil;
1588
1589 Fprovide (intern ("xwidget-internal"), Qnil);
1590
1591 }
1592
1593
1594 /* Value is non-zero if OBJECT is a valid Lisp xwidget specification. A
1595 valid xwidget specification is a list whose car is the symbol
1596 `xwidget', and whose rest is a property list. The property list must
1597 contain a value for key `:type'. That value must be the name of a
1598 supported xwidget type. The rest of the property list depends on the
1599 xwidget type. */
1600
1601 int
1602 valid_xwidget_spec_p (Lisp_Object object)
1603 {
1604 int valid_p = 0;
1605
1606 if (CONSP (object) && EQ (XCAR (object), Qxwidget))
1607 {
1608 /* Lisp_Object tem; */
1609
1610 /* for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem)) */
1611 /* if (EQ (XCAR (tem), QCtype)) */
1612 /* { */
1613 /* tem = XCDR (tem); */
1614 /* if (CONSP (tem) && SYMBOLP (XCAR (tem))) */
1615 /* { */
1616 /* struct xwidget_type *type; */
1617 /* type = lookup_xwidget_type (XCAR (tem)); */
1618 /* if (type) */
1619 /* valid_p = type->valid_p (object); */
1620 /* } */
1621
1622 /* break; */
1623 /* } */
1624 //never mind type support for now
1625 valid_p = 1;
1626 }
1627
1628 return valid_p;
1629 }
1630
1631
1632
1633 /* find a value associated with key in spec */
1634 Lisp_Object
1635 xwidget_spec_value ( Lisp_Object spec, Lisp_Object key,
1636 int *found)
1637 {
1638 Lisp_Object tail;
1639
1640 eassert (valid_xwidget_spec_p (spec));
1641
1642 for (tail = XCDR (spec);
1643 CONSP (tail) && CONSP (XCDR (tail)); tail = XCDR (XCDR (tail)))
1644 {
1645 if (EQ (XCAR (tail), key))
1646 {
1647 if (found)
1648 *found = 1;
1649 return XCAR (XCDR (tail));
1650 }
1651 }
1652
1653 if (found)
1654 *found = 0;
1655 return Qnil;
1656 }
1657
1658
1659 void
1660 xwidget_view_delete_all_in_window (struct window *w)
1661 {
1662 struct xwidget_view* xv = NULL;
1663 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail))
1664 {
1665 if (XWIDGET_VIEW_P (XCAR (tail))) {
1666 xv = XXWIDGET_VIEW (XCAR (tail));
1667 if(XWINDOW (xv->w) == w) {
1668 gtk_widget_destroy(xv->widgetwindow);
1669 Vxwidget_view_list = Fdelq (XCAR (tail), Vxwidget_view_list);
1670 }
1671 }
1672 }
1673 }
1674
1675 struct xwidget_view*
1676 xwidget_view_lookup (struct xwidget* xw, struct window *w)
1677 {
1678 Lisp_Object xwidget, window, ret;
1679 XSETXWIDGET (xwidget, xw);
1680 XSETWINDOW (window, w);
1681
1682 ret = Fxwidget_view_lookup (xwidget, window);
1683
1684 return EQ (ret, Qnil) ? NULL : XXWIDGET_VIEW (ret);
1685 }
1686
1687 struct xwidget*
1688 lookup_xwidget (Lisp_Object spec)
1689 {
1690 /* When a xwidget lisp spec is found initialize the C struct that is used in the C code.
1691 This is done by redisplay so values change if the spec changes.
1692 So, take special care of one-shot events
1693
1694 TODO remove xwidget init from display spec. simply store an xwidget reference only and set
1695 size etc when creating the xwidget, which should happen before insertion into buffer
1696 */
1697 int found = 0, found1 = 0, found2 = 0;
1698 Lisp_Object value;
1699 struct xwidget *xw;
1700
1701 value = xwidget_spec_value (spec, QCxwidget, &found1);
1702 xw = XXWIDGET(value);
1703
1704 /* value = xwidget_spec_value (spec, QCtype, &found); */
1705 /* xw->type = SYMBOLP (value) ? value : Qbutton; //default to button */
1706 /* value = xwidget_spec_value (spec, QCtitle, &found2); */
1707 /* xw->title = STRINGP (value) ? (char *) SDATA (value) : "?"; //funky cast FIXME TODO */
1708
1709 /* value = xwidget_spec_value (spec, QCheight, NULL); */
1710 /* xw->height = INTEGERP (value) ? XFASTINT (value) : 50; */
1711 /* value = xwidget_spec_value (spec, QCwidth, NULL); */
1712 /* xw->width = INTEGERP (value) ? XFASTINT (value) : 50; */
1713
1714 /* value = xwidget_spec_value (spec, QCplist, NULL); */
1715 /* xw->plist = value; */
1716 /* coordinates are not known here */
1717 printf ("lookup_xwidget xwidget_id:%d type:%d found:%d %d %d title:'%s' (%d,%d)\n", xw,
1718 xw->type, found, found1, found2, xw->title, xw->height, xw->width);
1719
1720 //assert_valid_xwidget_id (id, "lookup_xwidget");
1721 return xw;
1722 }
1723
1724 /*set up detection of touched xwidget*/
1725 void
1726 xwidget_start_redisplay (void)
1727 {
1728 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail))
1729 {
1730 if (XWIDGET_VIEW_P (XCAR (tail)))
1731 XXWIDGET_VIEW (XCAR (tail))->redisplayed = 0;
1732 }
1733 }
1734
1735 /* the xwidget was touched during redisplay, so it isnt a candidate for hiding*/
1736 void
1737 xwidget_touch (struct xwidget_view *xv)
1738 {
1739 xv->redisplayed = 1;
1740 }
1741
1742 int
1743 xwidget_touched (struct xwidget_view *xv)
1744 {
1745 return xv->redisplayed;
1746 }
1747
1748 /* redisplay has ended, now we should hide untouched xwidgets
1749 */
1750 void
1751 xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix)
1752 {
1753
1754 int i;
1755 struct xwidget *xw;
1756 int area;
1757
1758
1759 xwidget_start_redisplay ();
1760 //iterate desired glyph matrix of window here, hide gtk widgets
1761 //not in the desired matrix.
1762
1763 //this only takes care of xwidgets in active windows.
1764 //if a window goes away from screen xwidget views wust be deleted
1765
1766 // dump_glyph_matrix(matrix, 2);
1767 for (i = 0; i < matrix->nrows; ++i)
1768 {
1769 // dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
1770 struct glyph_row *row;
1771 row = MATRIX_ROW (matrix, i);
1772 if (row->enabled_p != 0)
1773 {
1774 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
1775 {
1776 struct glyph *glyph = row->glyphs[area];
1777 struct glyph *glyph_end = glyph + row->used[area];
1778 for (; glyph < glyph_end; ++glyph)
1779 {
1780 if (glyph->type == XWIDGET_GLYPH)
1781 {
1782 /*
1783 the only call to xwidget_end_redisplay is in dispnew
1784 xwidget_end_redisplay(w->current_matrix);
1785 */
1786 xwidget_touch (xwidget_view_lookup(glyph->u.xwidget,
1787 w));
1788 }
1789 }
1790 }
1791 }
1792 }
1793
1794 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail))
1795 {
1796 if (XWIDGET_VIEW_P (XCAR (tail))) {
1797 struct xwidget_view* xv = XXWIDGET_VIEW (XCAR (tail));
1798
1799 //"touched" is only meaningful for the current window, so disregard other views
1800 if (XWINDOW (xv->w) == w) {
1801 if (xwidget_touched(xv))
1802 xwidget_show_view (xv);
1803 else
1804 xwidget_hide_view (xv);
1805 }
1806 }
1807 }
1808 }
1809
1810 /* Kill all xwidget in BUFFER. */
1811 void
1812 kill_buffer_xwidgets (Lisp_Object buffer)
1813 {
1814 Lisp_Object tail, xwidget;
1815 for (tail = Fget_buffer_xwidgets (buffer); CONSP (tail); tail = XCDR (tail))
1816 {
1817 xwidget = XCAR (tail);
1818 Vxwidget_list = Fdelq (xwidget, Vxwidget_list);
1819 /* TODO free the GTK things in xw */
1820 {
1821 CHECK_XWIDGET (xwidget);
1822 struct xwidget *xw = XXWIDGET (xwidget);
1823 if (xw->widget_osr && xw->widgetwindow_osr)
1824 {
1825 gtk_widget_destroy(xw->widget_osr);
1826 gtk_widget_destroy(xw->widgetwindow_osr);
1827 }
1828 }
1829 }
1830 }
1831
1832 #endif /* HAVE_XWIDGETS */