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