]> code.delx.au - gnu-emacs/blob - src/xwidget.c
merge from trunk
[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 DEFUN( "xwgir-require-namespace",Fxwgir_require_namespace, Sxwgir_require_namespace, 2,2,0,
610 doc: /*require a namespace. must be done for all namespaces we want to use, before using other xwgir functions.*/)
611 (Lisp_Object lnamespace, Lisp_Object lnamespace_version)
612 {
613 char* namespace = SDATA(lnamespace);
614 char* namespace_version = SDATA(lnamespace_version);
615 GError *error = NULL;
616
617 girepository = g_irepository_get_default();
618 g_irepository_require(girepository, namespace, namespace_version, 0, &error);
619 if (error) {
620 g_error("ERROR: %s\n", error->message);
621 return Qnil;
622 }
623 return Qt;
624 }
625
626 GtkWidget* xwgir_create(char* class, char* namespace){
627 //TODO this is more or less the same as xwgir-call-method, so should be refactored
628 //create a gtk widget, given its name
629 //find the constructor
630 //call it
631 //also figure out how to pass args
632
633 GError *error = NULL;
634 GIArgument return_value;
635
636 GIObjectInfo* obj_info = g_irepository_find_by_name(girepository, namespace, class);
637 GIFunctionInfo* f_info = g_object_info_find_method (obj_info, "new");
638 g_function_info_invoke(f_info,
639 NULL, 0,
640 NULL, 0,
641 &return_value,
642 NULL);
643 xwgir_create_debug = return_value.v_pointer;
644 return return_value.v_pointer;
645
646 }
647
648 int
649 xwgir_convert_lisp_to_gir_arg(GIArgument* giarg,
650 GIArgInfo* arginfo,
651 Lisp_Object lisparg )
652 {
653
654 GITypeTag tag;
655 gboolean is_pointer;
656 gboolean is_enum;
657 tag = g_type_info_get_tag (g_arg_info_get_type (arginfo));
658
659 switch (tag)
660 {
661 case GI_TYPE_TAG_BOOLEAN:
662 giarg->v_boolean = XFASTINT(lisparg);
663 break;
664 case GI_TYPE_TAG_INT8:
665 giarg->v_int8 = XFASTINT(lisparg);
666 break;
667 case GI_TYPE_TAG_UINT8:
668 giarg->v_uint8 = XFASTINT(lisparg);
669 break;
670 case GI_TYPE_TAG_INT16:
671 giarg->v_int16 = XFASTINT(lisparg);
672 break;
673 case GI_TYPE_TAG_UINT16:
674 giarg->v_uint16 = XFASTINT(lisparg);
675 break;
676 case GI_TYPE_TAG_INT32:
677 giarg->v_int32 = XFASTINT(lisparg);
678 break;
679 case GI_TYPE_TAG_UINT32:
680 giarg->v_uint32 = XFASTINT(lisparg);
681 break;
682
683 case GI_TYPE_TAG_INT64:
684 giarg->v_int64 = XFASTINT(lisparg);
685 break;
686 case GI_TYPE_TAG_UINT64:
687 giarg->v_uint64 = XFASTINT(lisparg);
688 break;
689
690
691 case GI_TYPE_TAG_FLOAT:
692 giarg->v_float = XFLOAT_DATA(lisparg);
693 break;
694
695 case GI_TYPE_TAG_DOUBLE:
696 giarg->v_double = XFLOAT_DATA(lisparg);
697 break;
698
699 case GI_TYPE_TAG_UTF8:
700 case GI_TYPE_TAG_FILENAME:
701 //giarg->v_string = SDATA(lisparg);
702 giarg->v_pointer = SDATA(lisparg);
703 break;
704
705 case GI_TYPE_TAG_ARRAY:
706 case GI_TYPE_TAG_GLIST:
707 case GI_TYPE_TAG_GSLIST:
708 case GI_TYPE_TAG_GHASH:
709 case GI_TYPE_TAG_ERROR:
710 case GI_TYPE_TAG_INTERFACE:
711 case GI_TYPE_TAG_VOID:
712 case GI_TYPE_TAG_UNICHAR:
713 case GI_TYPE_TAG_GTYPE:
714 //?? i dont know how to handle these yet TODO
715 printf("failed in my lisp to gir arg conversion duties. sob!\n");
716 return -1;
717 break;
718 }
719 return 0;
720 }
721
722 #if 0
723 void
724 refactor_attempt(){
725 //this methhod should be called from xwgir-xwidget-call-method and from xwgir xwidget construction
726 char* class = SDATA(Fcar(Fcdr(Fget(xw->type, QCxwgir_class))));
727
728 GIObjectInfo* obj_info = g_irepository_find_by_name(girepository, namespace, class);
729 GIFunctionInfo* f_info = g_object_info_find_method (obj_info, SDATA(method));
730
731 //loop over args, convert from lisp to primitive type, given arg introspection data
732 //TODO g_callable_info_get_n_args(f_info) should match
733 int argscount = XFASTINT(Flength(arguments));
734 if(argscount != g_callable_info_get_n_args(f_info)){
735 printf("xwgir call method arg count doesn match! \n");
736 return Qnil;
737 }
738 int i;
739 for (i = 1; i < argscount + 1; ++i)
740 {
741 xwgir_convert_lisp_to_gir_arg(&in_args[i], g_callable_info_get_arg(f_info, i - 1), Fnth(i - 1, arguments));
742 }
743
744 in_args[0].v_pointer = widget;
745 if(g_function_info_invoke(f_info,
746 in_args, argscount + 1,
747 NULL, 0,
748 &return_value,
749 &error)) {
750 //g_error("ERROR: %s\n", error->message);
751 printf("invokation error\n");
752 return Qnil;
753 }
754 return Qt;
755 }
756 #endif /* 0 */
757
758 DEFUN ("xwgir-xwidget-call-method", Fxwgir_xwidget_call_method, Sxwgir_xwidget_call_method, 3, 3, 0,
759 doc: /* call xwidget object method.*/)
760 (Lisp_Object xwidget, Lisp_Object method, Lisp_Object arguments)
761 {
762 CHECK_XWIDGET (xwidget);
763 GError *error = NULL;
764 GIArgument return_value;
765 GIArgument in_args[20];
766
767
768 struct xwidget* xw;
769 if (NILP (xwidget)) { printf("ERROR xwidget nil\n"); return Qnil; };
770 xw = XXWIDGET(xwidget);
771 if(NULL == xw) printf("ERROR xw is 0\n");
772 char* namespace = SDATA(Fcar(Fget(xw->type, QCxwgir_class)));
773 //we need the concrete widget, which happens in 2 ways depending on OSR or not TODO
774 GtkWidget* widget = NULL;
775 if(NULL == xw->widget_osr) {
776 widget = xwidget_view_lookup (xw, XWINDOW(FRAME_SELECTED_WINDOW (SELECTED_FRAME ()))) -> widget;
777 } else {
778 widget = xw->widget_osr;
779 }
780
781 //char* class = SDATA(SYMBOL_NAME(xw->type)); //this works but is unflexible
782 //figure out the class from the widget instead
783 /* printf("type class: %s %s\n", G_OBJECT_TYPE_NAME(widget), G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(widget))); */
784 /* char* class = G_OBJECT_TYPE_NAME(widget); //gives "GtkButton"(I want "Button") */
785 /* class += strlen(namespace); //TODO check for corresponding api method. but this seems to work. */
786
787 char* class = SDATA(Fcar(Fcdr(Fget(xw->type, QCxwgir_class))));
788
789 GIObjectInfo* obj_info = g_irepository_find_by_name(girepository, namespace, class);
790 GIFunctionInfo* f_info = g_object_info_find_method (obj_info, SDATA(method));
791
792 //loop over args, convert from lisp to primitive type, given arg introspection data
793 //TODO g_callable_info_get_n_args(f_info) should match
794 int argscount = XFASTINT(Flength(arguments));
795 if(argscount != g_callable_info_get_n_args(f_info)){
796 printf("xwgir call method arg count doesn match! \n");
797 return Qnil;
798 }
799 int i;
800 Lisp_Object n;
801 for (i = 1; i < argscount + 1; ++i)
802 {
803 XSETFASTINT (n, i - 1);
804 xwgir_convert_lisp_to_gir_arg(&in_args[i], g_callable_info_get_arg(f_info, i - 1), Fnth(n, arguments));
805 }
806
807 in_args[0].v_pointer = widget;
808 if(g_function_info_invoke(f_info,
809 in_args, argscount + 1,
810 NULL, 0,
811 &return_value,
812 &error)) {
813 //g_error("ERROR: %s\n", error->message);
814 printf("invokation error\n");
815 return Qnil;
816 }
817 return Qt;
818 }
819
820 void
821 to_child (GtkWidget *bin,
822 double widget_x,
823 double widget_y,
824 double *x_out,
825 double *y_out)
826 {
827 *x_out = widget_x;
828 *y_out = widget_y;
829 }
830
831
832 GdkWindow *
833 offscreen_pick_embedded_child (GdkWindow *window,
834 double x,
835 double y,
836 gpointer *data)
837 {
838 //in this simple case we assume the window contains a single widget. easy.
839 //but then we get the problem that the widget cant be embedded in several windows
840 return gtk_widget_get_window (GTK_WIDGET (data));
841 }
842
843 void
844 offscreen_to_embedder (GdkWindow *window,
845 gdouble offscreen_x,
846 gdouble offscreen_y,
847 gpointer embedder_x,
848 gpointer embedder_y,
849 gpointer data)
850 {
851 * (gdouble *) embedder_x = offscreen_x;
852 * (gdouble *) embedder_y = offscreen_y;
853 }
854
855 void
856 offscreen_from_embedder (GdkWindow *window,
857 gdouble embedder_x,
858 gdouble embedder_y,
859 gpointer offscreen_x,
860 gpointer offscreen_y,
861 gpointer user_data)
862 {
863 * (gdouble *) offscreen_x = embedder_x;
864 * (gdouble *) offscreen_y = embedder_y;
865 }
866
867 gboolean
868 xwidget_osr_event_set_embedder (GtkWidget *widget,
869 GdkEvent *event,
870 gpointer data)
871 {
872 struct xwidget_view *xv = (struct xwidget_view *) data;
873 struct xwidget *xww = XXWIDGET (xv->model);
874 printf("gdk_offscreen_window_set_embedder %d %d\n",
875 GDK_IS_WINDOW(gtk_widget_get_window (xww->widget_osr)),
876 GDK_IS_WINDOW(gtk_widget_get_window (GTK_WIDGET (xv->widget))));
877 gdk_offscreen_window_set_embedder (gtk_widget_get_window (xww->widgetwindow_osr),
878 gtk_widget_get_window (xv->widget));
879 }
880
881
882 /* initializes and does initial placement of an xwidget view on screen */
883 struct xwidget_view*
884 xwidget_init_view (struct xwidget *xww,
885 struct glyph_string *s,
886 int x, int y)
887 {
888 struct xwidget_view *xv = allocate_xwidget_view();
889 Lisp_Object val;
890 GdkColor color;
891
892 XSETXWIDGET_VIEW (val, xv) ;
893 Vxwidget_view_list = Fcons (val, Vxwidget_view_list);
894
895 XSETWINDOW(xv->w, s->w);
896 XSETXWIDGET(xv->model, xww);
897
898 //widget creation
899 if(EQ(xww->type, Qbutton))
900 {
901 xv->widget = gtk_button_new_with_label (XSTRING(xww->title)->data);
902 g_signal_connect (G_OBJECT (xv->widget), "clicked",
903 G_CALLBACK (buttonclick_handler), xv); // the view rather than the model
904 } else if (EQ(xww->type, Qtoggle)) {
905 xv->widget = gtk_toggle_button_new_with_label (XSTRING(xww->title)->data);
906 //xv->widget = gtk_entry_new ();//temp hack to experiment with key propagation TODO entry widget is useful for testing
907 } else if (EQ(xww->type, Qsocket)) {
908 xv->widget = gtk_socket_new ();
909 g_signal_connect_after(xv->widget, "plug-added", G_CALLBACK(xwidget_plug_added), "plug added");
910 g_signal_connect_after(xv->widget, "plug-removed", G_CALLBACK(xwidget_plug_removed), "plug removed");
911 //TODO these doesnt help
912 gtk_widget_add_events(xv->widget, GDK_KEY_PRESS);
913 gtk_widget_add_events(xv->widget, GDK_KEY_RELEASE);
914 } else if (EQ(xww->type, Qslider)) {
915 xv->widget =
916 //gtk_hscale_new (GTK_ADJUSTMENT(gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 10.0, 10.0)));
917 gtk_hscale_new_with_range ( 0.0, 100.0, 10.0);
918 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
919 xv->handler_id = g_signal_connect_after(xv->widget, "value-changed", G_CALLBACK(xwidget_slider_changed), "slider changed");
920 } else if (EQ(xww->type, Qcairo)) {
921 //Cairo view
922 //uhm cairo is differentish in gtk 3.
923 //gdk_cairo_create (gtk_widget_get_window (FRAME_GTK_WIDGET (s->f)));
924 xv->widget = gtk_drawing_area_new();
925 g_signal_connect (G_OBJECT ( xv->widget), "draw",
926 G_CALLBACK (xwidget_osr_draw_callback), NULL);
927
928 } else if (EQ(xww->type, Qwebkit_osr)||
929 EQ(xww->type, Qsocket_osr)||
930 (!NILP (Fget(xww->type, QCxwgir_class))))//xwgir widgets are OSR
931 {
932 printf("osr init:%s\n",SDATA(SYMBOL_NAME(xww->type)));
933 xv->widget = gtk_drawing_area_new();
934 gtk_widget_set_app_paintable ( xv->widget, TRUE); //because expose event handling
935 gtk_widget_add_events(xv->widget, GDK_ALL_EVENTS_MASK);
936
937 /* Draw the view on damage-event */
938 g_signal_connect (G_OBJECT (xww->widgetwindow_osr), "damage-event",
939 G_CALLBACK (offscreen_damage_event), xv->widget);
940
941 if (EQ(xww->type, Qwebkit_osr)){
942 /* ///xwgir debug */
943 /* //forward events. this isnt compatible with the set_embedded strategy */
944 g_signal_connect (G_OBJECT ( xv->widget), "button-press-event",
945 G_CALLBACK (xwidget_osr_event_forward), NULL);
946 g_signal_connect (G_OBJECT ( xv->widget), "button-release-event",
947 G_CALLBACK (xwidget_osr_event_forward), NULL);
948 g_signal_connect (G_OBJECT ( xv->widget), "motion-notify-event",
949 G_CALLBACK (xwidget_osr_event_forward), NULL);
950 }else{
951 //xwgir debug , orthogonal to forwarding
952 g_signal_connect (G_OBJECT (xv->widget), "enter-notify-event",
953 G_CALLBACK (xwidget_osr_event_set_embedder), xv);
954 }
955
956 //draw
957 g_signal_connect (G_OBJECT (xv->widget), "draw",
958 G_CALLBACK (xwidget_osr_draw_callback), NULL);
959
960 }
961 //else return NULL;
962
963 //widget realization
964 //make container widget 1st, and put the actual widget inside the container
965 //later, drawing should crop container window if necessary to handle case where xwidget
966 //is partially obscured by other emacs windows
967 //other containers than gtk_fixed where explored, but gtk_fixed had the most predictable behaviour so far.
968 xv->emacswindow = FRAME_GTK_WIDGET (s->f);
969 xv->widgetwindow = gtk_fixed_new ();
970 gtk_widget_set_has_window(xv->widgetwindow, TRUE);
971 gtk_container_add (GTK_CONTAINER (xv->widgetwindow), xv->widget);
972
973 //store some xwidget data in the gtk widgets
974 g_object_set_data (G_OBJECT (xv->widget), XG_FRAME_DATA, (gpointer) (s->f)); //the emacs frame
975 g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET, (gpointer) (xww)); //the xwidget
976 g_object_set_data (G_OBJECT (xv->widget), XG_XWIDGET_VIEW, (gpointer) (xv)); //the xwidget
977 g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET, (gpointer) (xww)); //the xwidget window
978 g_object_set_data (G_OBJECT (xv->widgetwindow), XG_XWIDGET_VIEW, (gpointer) (xv)); //the xwidget window
979
980
981 gtk_widget_set_size_request (GTK_WIDGET (xv->widget), xww->width, xww->height);
982 gtk_widget_set_size_request (xv->widgetwindow, xww->width, xww->height);
983 gtk_fixed_put (GTK_FIXED (FRAME_GTK_WIDGET (s->f)), xv->widgetwindow, x, y);
984 xv->x = x; xv->y = y;
985 gtk_widget_show_all (xv->widgetwindow);
986
987
988
989 //widgettype specific initialization only possible after realization
990 if (EQ(xww->type, Qsocket)) {
991 printf ("xwid:%d socket id:%x %d\n",
992 xww,
993 gtk_socket_get_id (GTK_SOCKET (xv->widget)),
994 gtk_socket_get_id (GTK_SOCKET (xv->widget)));
995 send_xembed_ready_event (xww,
996 gtk_socket_get_id (GTK_SOCKET (xv->widget)));
997 //gtk_widget_realize(xw->widget);
998 }
999
1000 //////////////////////////////////////////////////////////////
1001 // xwgir debug
1002 if (//EQ(xww->type, Qwebkit_osr)|| //TODO should be able to choose compile time which method to use with webkit
1003 EQ(xww->type, Qsocket_osr)||
1004 (!NILP (Fget(xww->type, QCxwgir_class))))//xwgir widgets are OSR
1005 {
1006 printf("gdk_offscreen_window_set_embedder %d %d\n",
1007 GDK_IS_WINDOW(gtk_widget_get_window (xww->widget_osr)),
1008 GDK_IS_WINDOW(gtk_widget_get_window (GTK_WIDGET (xv->widget))));
1009 // set_embedder needs to be called after xv->widget realization
1010 gdk_offscreen_window_set_embedder (gtk_widget_get_window (xww->widgetwindow_osr),
1011 gtk_widget_get_window (xv->widget));
1012 g_signal_connect (gtk_widget_get_window (xv->widget), "pick-embedded-child",
1013 G_CALLBACK (offscreen_pick_embedded_child), xww->widgetwindow_osr);
1014
1015 g_signal_connect (gtk_widget_get_window (xww->widgetwindow_osr), "from-embedder",
1016 G_CALLBACK (offscreen_from_embedder), NULL);
1017 g_signal_connect (gtk_widget_get_window (xww->widgetwindow_osr), "to-embedder",
1018 G_CALLBACK (offscreen_to_embedder), NULL);
1019 }
1020 ////////////////////////////////////////
1021
1022 return xv;
1023 }
1024
1025
1026 void
1027 x_draw_xwidget_glyph_string (struct glyph_string *s)
1028 {
1029 /*
1030 this method is called by the redisplay engine and places the xwidget on screen.
1031 moving and clipping is done here. also view init.
1032
1033 */
1034 int box_line_hwidth = eabs (s->face->box_line_width);
1035 int box_line_vwidth = max (s->face->box_line_width, 0);
1036 int height = s->height;
1037 struct xwidget *xww = s->xwidget;
1038 struct xwidget_view *xv = xwidget_view_lookup(xww, s->w);
1039 int clip_right; int clip_bottom; int clip_top; int clip_left;
1040
1041 int x = s->x;
1042 int y = s->y + (s->height / 2) - (xww->height / 2);
1043 int moved=0;
1044
1045 /* We do it here in the display loop because there is no other
1046 time to know things like window placement etc.
1047 */
1048 printf ("xv init for xw %d\n", xww);
1049 xv = xwidget_init_view (xww, s, x, y);
1050
1051 //calculate clipping, which is used for all manner of onscreen xwidget views
1052 //each widget border can get clipped by other emacs objects so there are four clipping variables
1053 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));
1054 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));
1055
1056 clip_bottom = min (xww->height, WINDOW_BOTTOM_EDGE_Y (s->w) - WINDOW_MODE_LINE_HEIGHT (s->w) - y);
1057 clip_top = max(0, WINDOW_TOP_EDGE_Y(s->w) -y );
1058
1059 //we are conserned with movement of the onscreen area. the area might sit still when the widget actually moves
1060 //this happens when an emacs window border moves across a widget window
1061 //so, if any corner of the outer widget clippng window moves, that counts as movement here, even
1062 //if it looks like no movement happens because the widget sits still inside the clipping area.
1063 //the widget can also move inside the clipping area, which happens later
1064 moved = (xv->x + xv->clip_left != x+clip_left)
1065 || ((xv->y + xv->clip_top)!= (y+clip_top));
1066 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);
1067 else
1068 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);
1069 xv->x = x;
1070 xv->y = y;
1071 if (moved) //has it moved?
1072 {
1073 if (1)//!xwidget_hidden(xv)) //hidden equals not being seen during redisplay
1074 {
1075 //TODO should be possible to use xwidget_show_view here
1076 gtk_fixed_move (GTK_FIXED (FRAME_GTK_WIDGET (s->f)),
1077 xv->widgetwindow,
1078 x + clip_left, y + clip_top);
1079 }
1080 }
1081 //clip the widget window if some parts happen to be outside drawable area
1082 //an emacs window is not a gtk window, a gtk window covers the entire frame
1083 //cliping might have changed even if we havent actualy moved, we try figure out when we need to reclip for real
1084 if((xv->clip_right != clip_right)
1085 || (xv->clip_bottom != clip_bottom)
1086 || (xv->clip_top != clip_top)
1087 || (xv->clip_left != clip_left)){
1088 gtk_widget_set_size_request (xv->widgetwindow, clip_right + clip_left, clip_bottom + clip_top);
1089 gtk_fixed_move(GTK_FIXED(xv->widgetwindow), xv->widget, -clip_left, -clip_top);
1090 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);
1091
1092
1093 xv->clip_right = clip_right; xv->clip_bottom = clip_bottom; xv->clip_top = clip_top;xv->clip_left = clip_left;
1094 }
1095 //if emacs wants to repaint the area where the widget lives, queue a redraw
1096 //TODO it seems its possible to get out of sync with emacs redraws so emacs bg sometimes shows up instead of xwidget
1097 //its just a visual glitch though
1098 if (!xwidget_hidden(xv)){
1099 gtk_widget_queue_draw (xv->widgetwindow);
1100 gtk_widget_queue_draw (xv->widget);
1101 }
1102 }
1103
1104
1105 #ifdef HAVE_WEBKIT_OSR
1106
1107 //FUGLY macro that checks WEBKIT_IS_WEB_VIEW(xw->widget_osr) first
1108 #define WEBKIT_FN_INIT() \
1109 struct xwidget* xw; \
1110 CHECK_XWIDGET (xwidget); \
1111 if(NILP (xwidget)) {printf("ERROR xwidget nil\n"); return Qnil;}; \
1112 xw = XXWIDGET(xwidget); \
1113 if(NULL == xw) printf("ERROR xw is 0\n"); \
1114 if((NULL == xw->widget_osr) || !WEBKIT_IS_WEB_VIEW(xw->widget_osr)){ \
1115 printf("ERROR xw->widget_osr does not hold a webkit instance\n");\
1116 return Qnil;\
1117 };
1118
1119
1120 DEFUN ("xwidget-webkit-goto-uri", Fxwidget_webkit_goto_uri, Sxwidget_webkit_goto_uri,
1121 2, 2, 0,
1122 doc: /* webkit goto uri.*/)
1123 (Lisp_Object xwidget, Lisp_Object uri)
1124 {
1125 WEBKIT_FN_INIT();
1126 webkit_web_view_load_uri ( WEBKIT_WEB_VIEW(xw->widget_osr), SDATA(uri));
1127 return Qnil;
1128 }
1129
1130
1131 DEFUN ("xwidget-webkit-execute-script", Fxwidget_webkit_execute_script, Sxwidget_webkit_execute_script,
1132 2, 2, 0,
1133 doc: /* webkit exec js.*/)
1134 (Lisp_Object xwidget, Lisp_Object script)
1135 {
1136 WEBKIT_FN_INIT();
1137 webkit_web_view_execute_script( WEBKIT_WEB_VIEW(xw->widget_osr), SDATA(script));
1138 return Qnil;
1139 }
1140
1141 DEFUN ("xwidget-webkit-get-title", Fxwidget_webkit_get_title, Sxwidget_webkit_get_title,
1142 1, 1, 0,
1143 doc: /* webkit get title. can be used to work around exec method lacks return val*/)
1144 (Lisp_Object xwidget)
1145 {
1146 //TODO support multibyte strings
1147 WEBKIT_FN_INIT();
1148 const gchar* str=webkit_web_view_get_title( WEBKIT_WEB_VIEW(xw->widget_osr));
1149 //return make_string_from_bytes(str, wcslen((const wchar_t *)str), strlen(str));
1150 if(str == 0){
1151 //TODO maybe return Qnil instead. I suppose webkit returns nullpointer when doc is not properly loaded or something
1152 printf("xwidget-webkit-get-title null webkit title\n");
1153 return build_string("");
1154 }
1155 return build_string(str);
1156 }
1157
1158 //TODO missnamed
1159 DEFUN("xwidget-disable-plugin-for-mime", Fxwidget_disable_plugin_for_mime , Sxwidget_disable_plugin_for_mime,
1160 1,1,0, doc: /* */)
1161 (Lisp_Object mime)
1162 {
1163 WebKitWebPlugin *wp = webkit_web_plugin_database_get_plugin_for_mimetype
1164 (webkit_get_web_plugin_database(), SDATA(mime));
1165 if(wp == NULL) return Qnil;
1166 if(webkit_web_plugin_get_enabled (wp)){
1167 webkit_web_plugin_set_enabled (wp, FALSE);
1168 return Qt;
1169 }
1170 return Qnil;
1171 }
1172
1173
1174 void
1175 xwidget_webkit_dom_dump(WebKitDOMNode* parent)
1176 {
1177 WebKitDOMNodeList* list;
1178 int i;
1179 int length;
1180 WebKitDOMNode* attribute;
1181 WebKitDOMNamedNodeMap* attrs;
1182 WebKitDOMNode* child;
1183 printf("node:%d type:%d name:%s content:%s\n",
1184 parent,
1185 webkit_dom_node_get_node_type(parent),//1 element 3 text 8 comment 2 attribute
1186 webkit_dom_node_get_local_name(parent),
1187 webkit_dom_node_get_text_content(parent));
1188
1189 if(webkit_dom_node_has_attributes(parent)){
1190 attrs = webkit_dom_node_get_attributes(parent);
1191
1192 length = webkit_dom_named_node_map_get_length(attrs);
1193 for (int i = 0; i < length; i++) {
1194 attribute = webkit_dom_named_node_map_item(attrs,i);
1195 printf(" attr node:%d type:%d name:%s content:%s\n",
1196 attribute,
1197 webkit_dom_node_get_node_type(attribute),//1 element 3 text 8 comment
1198 webkit_dom_node_get_local_name(attribute),
1199 webkit_dom_node_get_text_content(attribute));
1200 }
1201 }
1202 list = webkit_dom_node_get_child_nodes(parent);
1203 length = webkit_dom_node_list_get_length(list);
1204
1205 for (int i = 0; i < length; i++) {
1206 child = webkit_dom_node_list_item(list, i);
1207 //if(webkit_dom_node_has_child_nodes(child))
1208 xwidget_webkit_dom_dump(child);
1209 }
1210 }
1211
1212
1213 DEFUN ("xwidget-webkit-dom-dump", Fxwidget_webkit_dom_dump, Sxwidget_webkit_dom_dump,
1214 1, 1, 0,
1215 doc: /* webkit dom dump*/)
1216 (Lisp_Object xwidget)
1217 {
1218 WEBKIT_FN_INIT();
1219 xwidget_webkit_dom_dump(WEBKIT_DOM_NODE(webkit_web_view_get_dom_document( WEBKIT_WEB_VIEW(xw->widget_osr))));
1220 return Qnil;
1221 }
1222
1223
1224
1225 #endif /* HAVE_WEBKIT_OSR */
1226
1227
1228
1229
1230
1231 DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 3, 3, 0, doc:
1232 /* resize xwidgets*/)
1233 (Lisp_Object xwidget, Lisp_Object new_width, Lisp_Object new_height)
1234 {
1235 CHECK_XWIDGET (xwidget);
1236 struct xwidget* xw = XXWIDGET(xwidget);
1237 struct xwidget_view *xv;
1238 int w, h;
1239
1240 CHECK_NUMBER (new_width);
1241 CHECK_NUMBER (new_height);
1242 w = XFASTINT (new_width);
1243 h = XFASTINT (new_height);
1244
1245
1246 printf("resize xwidget %d (%d,%d)->(%d,%d)\n",xw, xw->width,xw->height,w,h);
1247 xw->width=w;
1248 xw->height=h;
1249 //if theres a osr resize it 1st
1250 if(xw->widget_osr){
1251 printf("resize xwidget_osr\n");
1252 //gtk_container_set_resize_mode ( GTK_WINDOW(xw->widgetwindow_osr), GTK_RESIZE_QUEUE);
1253 //gtk_container_set_resize_mode ( GTK_WINDOW(xw->widget_osr), GTK_RESIZE_QUEUE);
1254
1255
1256 //gtk_layout_set_size (GTK_LAYOUT (xw->widgetwindow_osr), xw->width, xw->height);
1257 gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, xw->height); //minimum size
1258 //gtk_window_resize( GTK_WINDOW(xw->widget_osr), xw->width, xw->height);
1259 gtk_window_resize( GTK_WINDOW(xw->widgetwindow_osr), xw->width, xw->height);
1260 //gtk_container_resize_children ( GTK_WINDOW(xw->widgetwindow_osr));
1261 gtk_container_resize_children (GTK_CONTAINER(xw->widgetwindow_osr));
1262
1263 }
1264
1265 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail)) //TODO MVC refactor lazy linear search
1266 {
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);
1272 }
1273 }
1274 }
1275
1276 return Qnil;
1277 }
1278
1279 DEFUN ("xwidget-size-request", Fxwidget_size_request, Sxwidget_size_request, 1, 1, 0, doc:
1280 /* desired size (TODO crashes if arg not osr widget)*/)
1281 (Lisp_Object xwidget)
1282 {
1283 CHECK_XWIDGET (xwidget);
1284 GtkRequisition requisition;
1285 Lisp_Object rv;
1286 gtk_widget_size_request(XXWIDGET(xwidget)->widget_osr, &requisition);
1287 rv = Qnil;
1288 rv = Fcons (make_number(requisition.height), rv);
1289 rv = Fcons (make_number(requisition.width), rv);
1290 return rv;
1291
1292 }
1293
1294 DEFUN ("xwidgetp", Fxwidgetp, Sxwidgetp, 1, 1, 0,
1295 doc: /* Return t if OBJECT is a xwidget. */)
1296 (Lisp_Object object)
1297 {
1298 return XWIDGETP (object) ? Qt : Qnil;
1299 }
1300
1301 DEFUN ("xwidget-view-p", Fxwidget_view_p, Sxwidget_view_p, 1, 1, 0,
1302 doc: /* Return t if OBJECT is a xwidget-view. */)
1303 (Lisp_Object object)
1304 {
1305 return XWIDGET_VIEW_P (object) ? Qt : Qnil;
1306 }
1307
1308 DEFUN ("xwidget-info", Fxwidget_info , Sxwidget_info, 1,1,0, doc: /* get xwidget props */)
1309 (Lisp_Object xwidget)
1310 {
1311 CHECK_XWIDGET (xwidget);
1312 Lisp_Object info, n;
1313 struct xwidget* xw = XXWIDGET(xwidget);
1314
1315 info = Fmake_vector (make_number (4), Qnil);
1316 ASET (info, 0, xw->type);
1317 ASET (info, 1, xw->title);
1318 XSETFASTINT(n, xw->width);
1319 ASET (info, 2, n);
1320 XSETFASTINT(n, xw->height);
1321 ASET (info, 3, n);
1322
1323 return info;
1324 }
1325
1326 DEFUN ("xwidget-view-info", Fxwidget_view_info , Sxwidget_view_info, 1, 1, 0, doc: /* get xwidget view props */)
1327 (Lisp_Object xwidget_view)
1328 {
1329 CHECK_XWIDGET_VIEW (xwidget_view);
1330 struct xwidget_view *xv = XXWIDGET_VIEW (xwidget_view);
1331 Lisp_Object info;
1332
1333 info = Fmake_vector (make_number (6), Qnil);
1334 ASET (info, 0, make_number(xv->x));
1335 ASET (info, 1, make_number(xv->y));
1336 ASET (info, 2, make_number(xv->clip_right));
1337 ASET (info, 3, make_number(xv->clip_bottom));
1338 ASET (info, 4, make_number(xv->clip_top));
1339 ASET (info, 5, make_number(xv->clip_left));
1340
1341 return info;
1342 }
1343
1344 DEFUN ("xwidget-view-model", Fxwidget_view_model, Sxwidget_view_model,
1345 1, 1, 0,
1346 doc: /* get xwidget view model */)
1347 (Lisp_Object xwidget_view)
1348 {
1349 CHECK_XWIDGET_VIEW (xwidget_view);
1350 return XXWIDGET_VIEW (xwidget_view)->model;
1351 }
1352
1353 DEFUN ("xwidget-view-window", Fxwidget_view_window, Sxwidget_view_window,
1354 1, 1, 0,
1355 doc: /* get xwidget view window */)
1356 (Lisp_Object xwidget_view)
1357 {
1358 CHECK_XWIDGET_VIEW (xwidget_view);
1359 return XXWIDGET_VIEW (xwidget_view)->w;
1360 }
1361
1362 DEFUN ("xwidget-send-keyboard-event", Fxwidget_send_keyboard_event, Sxwidget_send_keyboard_event, 2, 2, 0, doc:/* synthesize a kbd event for a xwidget. */
1363 )
1364 (Lisp_Object xwidget, Lisp_Object keydescriptor)
1365 {
1366 //TODO this code crashes for offscreen widgets and ive tried many different strategies
1367 //int keyval = 0x058; //X
1368 int keyval = XFASTINT(keydescriptor); //X
1369 char *keystring = "";
1370 GdkKeymapKey* keys;
1371 gint n_keys;
1372 GdkDeviceManager* manager;
1373 struct xwidget *xw;
1374 GtkWidget* widget;
1375 GdkEventKey* ev;
1376 Lisp_Object window;
1377 //popup_activated_flag = 1; //TODO just a hack
1378 gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), keyval, &keys, &n_keys);
1379
1380 xw = XXWIDGET(xwidget);
1381
1382 ev = (GdkEventKey*)gdk_event_new(GDK_KEY_PRESS);
1383
1384
1385 //todo what about windowless widgets?
1386
1387 window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1388
1389
1390 //TODO maybe we also need to special case sockets by picking up the plug rather than the socket
1391 if(xw->widget_osr)
1392 widget = xw->widget_osr;
1393 else
1394 widget = xwidget_view_lookup(xw, XWINDOW(window))->widget;
1395
1396 ev->window = gtk_widget_get_window(widget);
1397 gtk_widget_grab_focus(widget);
1398 ev->send_event = FALSE;
1399
1400 ev->hardware_keycode = keys[0].keycode;
1401 ev->group = keys[0].group;
1402
1403 ev->keyval = keyval;
1404 ev->time = GDK_CURRENT_TIME;
1405
1406 //ev->device = gdk_device_get_core_pointer();
1407 manager = gdk_display_get_device_manager(gdk_window_get_display(ev->window));
1408 gdk_event_set_device ((GdkEvent*)ev, gdk_device_manager_get_client_pointer(manager));
1409 gdk_event_put((GdkEvent*)ev);
1410 //g_signal_emit_by_name(ev->window,"key-press-event", ev);
1411
1412 ev->type = GDK_KEY_RELEASE;
1413 gdk_event_put((GdkEvent*)ev);
1414 //g_signal_emit_by_name(ev->window,"key-release-event", ev);
1415 //gtk_main_do_event(ev);
1416
1417 //TODO
1418 //if I delete the event the receiving component eventually crashes.
1419 //it ough TDTRT since event_put is supposed to copy the event
1420 //so probably this leaks events now
1421 //gdk_event_free((GdkEvent*)ev);
1422
1423 return Qnil;
1424 }
1425
1426 DEFUN ("delete-xwidget-view", Fdelete_xwidget_view, Sdelete_xwidget_view,
1427 1, 1, 0,
1428 doc: /* Delete the XWIDGET-VIEW. */)
1429 (Lisp_Object xwidget_view)
1430 {
1431 CHECK_XWIDGET_VIEW (xwidget_view);
1432 struct xwidget_view *xv = XXWIDGET_VIEW (xwidget_view);
1433 gtk_widget_destroy(xv->widgetwindow);
1434 Vxwidget_view_list = Fdelq (xwidget_view, Vxwidget_view_list);
1435 }
1436
1437 DEFUN ("xwidget-view-lookup", Fxwidget_view_lookup, Sxwidget_view_lookup,
1438 1, 2, 0,
1439 doc: /* Return the xwidget-view associated to XWIDGET in
1440 WINDOW if specified, otherwise it uses the selected window. */)
1441 (Lisp_Object xwidget, Lisp_Object window)
1442 {
1443 CHECK_XWIDGET (xwidget);
1444
1445 if (NILP (window))
1446 window = Fselected_window();
1447 CHECK_WINDOW (window);
1448
1449 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail))
1450 {
1451 Lisp_Object xwidget_view = XCAR (tail);
1452 if (EQ (Fxwidget_view_model (xwidget_view), xwidget)
1453 && EQ (Fxwidget_view_window (xwidget_view), window))
1454 return xwidget_view;
1455 }
1456
1457 return Qnil;
1458 }
1459
1460 DEFUN ("set-frame-visible", Fset_frame_visible, Sset_frame_visible,
1461 2, 2, 0,
1462 doc: /* HACKY */)
1463 (Lisp_Object frame, Lisp_Object flag)
1464 {
1465 CHECK_FRAME (frame);
1466 struct frame *f = XFRAME (frame);
1467 SET_FRAME_VISIBLE (f, !NILP (flag));
1468 return flag;
1469 }
1470
1471 DEFUN ("xwidget-plist", Fxwidget_plist, Sxwidget_plist,
1472 1, 1, 0,
1473 doc: /* Return the plist of XWIDGET. */)
1474 (register Lisp_Object xwidget)
1475 {
1476 CHECK_XWIDGET (xwidget);
1477 return XXWIDGET (xwidget)->plist;
1478 }
1479
1480 DEFUN ("xwidget-buffer", Fxwidget_buffer, Sxwidget_buffer,
1481 1, 1, 0,
1482 doc: /* Return the buffer of XWIDGET. */)
1483 (register Lisp_Object xwidget)
1484 {
1485 CHECK_XWIDGET (xwidget);
1486 return XXWIDGET (xwidget)->buffer;
1487 }
1488
1489 DEFUN ("set-xwidget-plist", Fset_xwidget_plist, Sset_xwidget_plist,
1490 2, 2, 0,
1491 doc: /* Replace the plist of XWIDGET with PLIST. Returns PLIST. */)
1492 (register Lisp_Object xwidget, Lisp_Object plist)
1493 {
1494 CHECK_XWIDGET (xwidget);
1495 CHECK_LIST (plist);
1496
1497 XXWIDGET (xwidget)->plist = plist;
1498 return plist;
1499 }
1500
1501 DEFUN ("set-xwidget-query-on-exit-flag",
1502 Fset_xwidget_query_on_exit_flag, Sset_xwidget_query_on_exit_flag,
1503 2, 2, 0,
1504 doc: /* Specify if query is needed for XWIDGET when Emacs is
1505 exited. If the second argument FLAG is non-nil, Emacs will query the
1506 user before exiting or killing a buffer if XWIDGET is running. This
1507 function returns FLAG. */)
1508 (Lisp_Object xwidget, Lisp_Object flag)
1509 {
1510 CHECK_XWIDGET (xwidget);
1511 XXWIDGET (xwidget)->kill_without_query = NILP (flag);
1512 return flag;
1513 }
1514
1515 DEFUN ("xwidget-query-on-exit-flag",
1516 Fxwidget_query_on_exit_flag, Sxwidget_query_on_exit_flag,
1517 1, 1, 0,
1518 doc: /* Return the current value of query-on-exit flag for XWIDGET. */)
1519 (Lisp_Object xwidget)
1520 {
1521 CHECK_XWIDGET (xwidget);
1522 return (XXWIDGET (xwidget)->kill_without_query ? Qnil : Qt);
1523 }
1524
1525 void
1526 syms_of_xwidget (void)
1527 {
1528 int i;
1529
1530 defsubr (&Smake_xwidget);
1531 defsubr (&Sxwidgetp);
1532 DEFSYM (Qxwidgetp, "xwidgetp");
1533 defsubr (&Sxwidget_view_p);
1534 DEFSYM (Qxwidget_view_p, "xwidget-view-p");
1535 defsubr (&Sxwidget_info);
1536 defsubr (&Sxwidget_view_info);
1537 defsubr (&Sxwidget_resize);
1538 defsubr (&Sget_buffer_xwidgets);
1539 defsubr (&Sxwidget_view_model);
1540 defsubr (&Sxwidget_view_window);
1541 defsubr (&Sxwidget_view_lookup);
1542 defsubr (&Sxwidget_query_on_exit_flag);
1543 defsubr (&Sset_xwidget_query_on_exit_flag);
1544 defsubr (&Sset_frame_visible);
1545
1546 #ifdef HAVE_WEBKIT_OSR
1547 defsubr (&Sxwidget_webkit_goto_uri);
1548 defsubr (&Sxwidget_webkit_execute_script);
1549 defsubr (&Sxwidget_webkit_get_title);
1550 DEFSYM (Qwebkit_osr ,"webkit-osr");
1551 #endif
1552
1553 defsubr (&Sxwgir_xwidget_call_method );
1554 defsubr (&Sxwgir_require_namespace);
1555 defsubr (&Sxwidget_size_request );
1556 defsubr (&Sdelete_xwidget_view);
1557 defsubr (&Sxwidget_disable_plugin_for_mime);
1558
1559 defsubr (&Sxwidget_send_keyboard_event);
1560 defsubr (&Sxwidget_webkit_dom_dump);
1561 defsubr (&Sxwidget_plist);
1562 defsubr (&Sxwidget_buffer);
1563 defsubr (&Sset_xwidget_plist);
1564
1565 DEFSYM (Qxwidget, "xwidget");
1566
1567 DEFSYM (QCxwidget, ":xwidget");
1568 DEFSYM (QCxwgir_class, ":xwgir-class");
1569 DEFSYM (QCtitle, ":title");
1570
1571 /* Do not forget to update the docstring of make-xwidget if you add
1572 new types. */
1573 DEFSYM (Qbutton, "Button"); //changed to match the gtk class because xwgir(experimental and not really needed)
1574 DEFSYM (Qtoggle, "ToggleButton");
1575 DEFSYM (Qslider, "slider");
1576 DEFSYM (Qsocket, "socket");
1577 DEFSYM (Qsocket_osr, "socket-osr");
1578 DEFSYM (Qcairo, "cairo");
1579
1580 DEFSYM (QCplist, ":plist");
1581
1582 DEFVAR_LISP ("xwidget-list", Vxwidget_list, doc: /*xwidgets list*/);
1583 Vxwidget_list = Qnil;
1584
1585 DEFVAR_LISP ("xwidget-view-list", Vxwidget_view_list, doc: /*xwidget views list*/);
1586 Vxwidget_view_list = Qnil;
1587
1588 Fprovide (intern ("xwidget-internal"), Qnil);
1589
1590 }
1591
1592
1593 /* Value is non-zero if OBJECT is a valid Lisp xwidget specification. A
1594 valid xwidget specification is a list whose car is the symbol
1595 `xwidget', and whose rest is a property list. The property list must
1596 contain a value for key `:type'. That value must be the name of a
1597 supported xwidget type. The rest of the property list depends on the
1598 xwidget type. */
1599
1600 int
1601 valid_xwidget_spec_p (Lisp_Object object)
1602 {
1603 int valid_p = 0;
1604
1605 if (CONSP (object) && EQ (XCAR (object), Qxwidget))
1606 {
1607 /* Lisp_Object tem; */
1608
1609 /* for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem)) */
1610 /* if (EQ (XCAR (tem), QCtype)) */
1611 /* { */
1612 /* tem = XCDR (tem); */
1613 /* if (CONSP (tem) && SYMBOLP (XCAR (tem))) */
1614 /* { */
1615 /* struct xwidget_type *type; */
1616 /* type = lookup_xwidget_type (XCAR (tem)); */
1617 /* if (type) */
1618 /* valid_p = type->valid_p (object); */
1619 /* } */
1620
1621 /* break; */
1622 /* } */
1623 //never mind type support for now
1624 valid_p = 1;
1625 }
1626
1627 return valid_p;
1628 }
1629
1630
1631
1632 /* find a value associated with key in spec */
1633 Lisp_Object
1634 xwidget_spec_value ( Lisp_Object spec, Lisp_Object key,
1635 int *found)
1636 {
1637 Lisp_Object tail;
1638
1639 eassert (valid_xwidget_spec_p (spec));
1640
1641 for (tail = XCDR (spec);
1642 CONSP (tail) && CONSP (XCDR (tail)); tail = XCDR (XCDR (tail)))
1643 {
1644 if (EQ (XCAR (tail), key))
1645 {
1646 if (found)
1647 *found = 1;
1648 return XCAR (XCDR (tail));
1649 }
1650 }
1651
1652 if (found)
1653 *found = 0;
1654 return Qnil;
1655 }
1656
1657
1658 void
1659 xwidget_view_delete_all_in_window (struct window *w)
1660 {
1661 struct xwidget_view* xv = NULL;
1662 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail))
1663 {
1664 if (XWIDGET_VIEW_P (XCAR (tail))) {
1665 xv = XXWIDGET_VIEW (XCAR (tail));
1666 if(XWINDOW (xv->w) == w) {
1667 gtk_widget_destroy(xv->widgetwindow);
1668 Vxwidget_view_list = Fdelq (XCAR (tail), Vxwidget_view_list);
1669 }
1670 }
1671 }
1672 }
1673
1674 struct xwidget_view*
1675 xwidget_view_lookup (struct xwidget* xw, struct window *w)
1676 {
1677 Lisp_Object xwidget, window, ret;
1678 XSETXWIDGET (xwidget, xw);
1679 XSETWINDOW (window, w);
1680
1681 ret = Fxwidget_view_lookup (xwidget, window);
1682
1683 return EQ (ret, Qnil) ? NULL : XXWIDGET_VIEW (ret);
1684 }
1685
1686 struct xwidget*
1687 lookup_xwidget (Lisp_Object spec)
1688 {
1689 /* When a xwidget lisp spec is found initialize the C struct that is used in the C code.
1690 This is done by redisplay so values change if the spec changes.
1691 So, take special care of one-shot events
1692
1693 TODO remove xwidget init from display spec. simply store an xwidget reference only and set
1694 size etc when creating the xwidget, which should happen before insertion into buffer
1695 */
1696 int found = 0, found1 = 0, found2 = 0;
1697 Lisp_Object value;
1698 struct xwidget *xw;
1699
1700 value = xwidget_spec_value (spec, QCxwidget, &found1);
1701 xw = XXWIDGET(value);
1702
1703 /* value = xwidget_spec_value (spec, QCtype, &found); */
1704 /* xw->type = SYMBOLP (value) ? value : Qbutton; //default to button */
1705 /* value = xwidget_spec_value (spec, QCtitle, &found2); */
1706 /* xw->title = STRINGP (value) ? (char *) SDATA (value) : "?"; //funky cast FIXME TODO */
1707
1708 /* value = xwidget_spec_value (spec, QCheight, NULL); */
1709 /* xw->height = INTEGERP (value) ? XFASTINT (value) : 50; */
1710 /* value = xwidget_spec_value (spec, QCwidth, NULL); */
1711 /* xw->width = INTEGERP (value) ? XFASTINT (value) : 50; */
1712
1713 /* value = xwidget_spec_value (spec, QCplist, NULL); */
1714 /* xw->plist = value; */
1715 /* coordinates are not known here */
1716 printf ("lookup_xwidget xwidget_id:%d type:%d found:%d %d %d title:'%s' (%d,%d)\n", xw,
1717 xw->type, found, found1, found2, xw->title, xw->height, xw->width);
1718
1719 //assert_valid_xwidget_id (id, "lookup_xwidget");
1720 return xw;
1721 }
1722
1723 /*set up detection of touched xwidget*/
1724 void
1725 xwidget_start_redisplay (void)
1726 {
1727 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail))
1728 {
1729 if (XWIDGET_VIEW_P (XCAR (tail)))
1730 XXWIDGET_VIEW (XCAR (tail))->redisplayed = 0;
1731 }
1732 }
1733
1734 /* the xwidget was touched during redisplay, so it isnt a candidate for hiding*/
1735 void
1736 xwidget_touch (struct xwidget_view *xv)
1737 {
1738 xv->redisplayed = 1;
1739 }
1740
1741 int
1742 xwidget_touched (struct xwidget_view *xv)
1743 {
1744 return xv->redisplayed;
1745 }
1746
1747 /* redisplay has ended, now we should hide untouched xwidgets
1748 */
1749 void
1750 xwidget_end_redisplay (struct window *w, struct glyph_matrix *matrix)
1751 {
1752
1753 int i;
1754 struct xwidget *xw;
1755 int area;
1756
1757
1758 xwidget_start_redisplay ();
1759 //iterate desired glyph matrix of window here, hide gtk widgets
1760 //not in the desired matrix.
1761
1762 //this only takes care of xwidgets in active windows.
1763 //if a window goes away from screen xwidget views wust be deleted
1764
1765 // dump_glyph_matrix(matrix, 2);
1766 for (i = 0; i < matrix->nrows; ++i)
1767 {
1768 // dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
1769 struct glyph_row *row;
1770 row = MATRIX_ROW (matrix, i);
1771 if (row->enabled_p != 0)
1772 {
1773 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
1774 {
1775 struct glyph *glyph = row->glyphs[area];
1776 struct glyph *glyph_end = glyph + row->used[area];
1777 for (; glyph < glyph_end; ++glyph)
1778 {
1779 if (glyph->type == XWIDGET_GLYPH)
1780 {
1781 /*
1782 the only call to xwidget_end_redisplay is in dispnew
1783 xwidget_end_redisplay(w->current_matrix);
1784 */
1785 xwidget_touch (xwidget_view_lookup(glyph->u.xwidget,
1786 w));
1787 }
1788 }
1789 }
1790 }
1791 }
1792
1793 for (Lisp_Object tail = Vxwidget_view_list; CONSP (tail); tail = XCDR (tail))
1794 {
1795 if (XWIDGET_VIEW_P (XCAR (tail))) {
1796 struct xwidget_view* xv = XXWIDGET_VIEW (XCAR (tail));
1797
1798 //"touched" is only meaningful for the current window, so disregard other views
1799 if (XWINDOW (xv->w) == w) {
1800 if (xwidget_touched(xv))
1801 xwidget_show_view (xv);
1802 else
1803 xwidget_hide_view (xv);
1804 }
1805 }
1806 }
1807 }
1808
1809 /* Kill all xwidget in BUFFER. */
1810 void
1811 kill_buffer_xwidgets (Lisp_Object buffer)
1812 {
1813 Lisp_Object tail, xwidget;
1814 for (tail = Fget_buffer_xwidgets (buffer); CONSP (tail); tail = XCDR (tail))
1815 {
1816 xwidget = XCAR (tail);
1817 Vxwidget_list = Fdelq (xwidget, Vxwidget_list);
1818 /* TODO free the GTK things in xw */
1819 {
1820 CHECK_XWIDGET (xwidget);
1821 struct xwidget *xw = XXWIDGET (xwidget);
1822 if (xw->widget_osr && xw->widgetwindow_osr)
1823 {
1824 gtk_widget_destroy(xw->widget_osr);
1825 gtk_widget_destroy(xw->widgetwindow_osr);
1826 }
1827 }
1828 }
1829 }
1830
1831 #endif /* HAVE_XWIDGETS */