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