11 #include "blockinput.h"
12 #include "syssignal.h"
15 #include <X11/cursorfont.h>
18 #include <sys/types.h>
22 #include <sys/ioctl.h>
23 #endif /* ! defined (BSD_SYSTEM) */
27 #ifndef INCLUDED_FCNTL
36 #include "character.h"
40 #include "dispextern.h"
42 #include "termhooks.h"
45 #include "emacs-icon.h"
50 #include "intervals.h"
57 #include <X11/Shell.h>
59 #include <X11/extensions/Xcomposite.h>
60 #include <X11/extensions/Xrender.h>
62 #ifdef HAVE_SYS_TIME_H
71 #endif /* HAVE_X_WINDOWS */
77 //for gtk3; sockets and plugs
79 #include <gtk/gtkscrolledwindow.h>
80 #include "emacsgtkfixed.h"
85 #ifdef HAVE_WEBKIT_OSR
86 #include <webkit/webkitwebview.h>
87 #include <webkit/webkitwebplugindatabase.h>
88 #include <webkit/webkitwebplugin.h>
89 #include <webkit/webkitglobals.h>
90 #include <webkit/webkitwebnavigationaction.h>
91 #include <webkit/webkitdownload.h>
92 #include <webkit/webkitwebpolicydecision.h>
96 #include <girepository.h>
100 //TODO embryo of lisp allocators for xwidgets
101 //TODO xwidget* should be Lisp_xwidget*
103 allocate_xwidget (void)
105 return ALLOCATE_PSEUDOVECTOR (struct xwidget
, height
, PVEC_XWIDGET
);
108 //TODO xwidget_view* should be Lisp_xwidget_view*
110 allocate_xwidget_view (void)
112 return ALLOCATE_PSEUDOVECTOR (struct xwidget_view
, redisplayed
, PVEC_XWIDGET_VIEW
);
114 #define XSETXWIDGET(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET))
115 #define XSETXWIDGET_VIEW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET_VIEW))
117 struct xwidget_view
* xwidget_view_lookup(struct xwidget
* xw
, struct window
*w
);
118 Lisp_Object
xwidget_spec_value ( Lisp_Object spec
, Lisp_Object key
, int *found
);
119 gboolean
offscreen_damage_event (GtkWidget
*widget
, GdkEvent
*event
, gpointer data
);
120 void webkit_osr_document_load_finished_callback (WebKitWebView
*webkitwebview
,
121 WebKitWebFrame
*arg1
,
123 gboolean
webkit_osr_download_callback (WebKitWebView
*webkitwebview
,
124 WebKitDownload
*arg1
,
127 gboolean
webkit_osr_mime_type_policy_typedecision_requested_callback(WebKitWebView
*webView
,
128 WebKitWebFrame
*frame
,
129 WebKitNetworkRequest
*request
,
131 WebKitWebPolicyDecision
*policy_decision
,
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
,
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
,
149 GtkWidget
* xwgir_create(char* class, char* namespace);
154 send_xembed_ready_event (struct xwidget
* xw
, int xembedid
);
155 DEFUN ("make-xwidget", Fmake_xwidget
, Smake_xwidget
, 7, 8, 0,
156 doc
: /* Make an xwidget from BEG to END of TYPE.
158 If BUFFER is nil it uses the current buffer. If BUFFER is a string and
159 no such buffer exists, it is created.
161 TYPE is a symbol which can take one of the following values:
170 (Lisp_Object beg
, Lisp_Object end
,
173 Lisp_Object width
, Lisp_Object height
,
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();
186 buffer
= Fcurrent_buffer(); // no need to gcpro because Fcurrent_buffer doesn't call Feval/eval_sub.
188 buffer
= Fget_buffer_create (buffer
);
191 xw
->height
= XFASTINT(height
);
192 xw
->width
= XFASTINT(width
);
193 xw
->kill_without_query
= 0;
194 XSETXWIDGET (val
, xw
); // set the vectorlike_header of VAL with the correct value
195 Vxwidget_list
= Fcons (val
, Vxwidget_list
);
196 xw
->widgetwindow_osr
= NULL
;
197 xw
->widget_osr
= NULL
;
203 #ifdef HAVE_WEBKIT_OSR
204 /* DIY mvc. widget is rendered offscreen,
205 later bitmap copied to the views.
207 if (EQ(xw
->type
, Qwebkit_osr
)||
208 EQ(xw
->type
, Qsocket_osr
)||
209 (!NILP (Fget(xw
->type
, QCxwgir_class
)))) {
211 xw
->widgetwindow_osr
= gtk_offscreen_window_new ();
212 gtk_window_resize(GTK_WINDOW(xw
->widgetwindow_osr
), xw
->width
, xw
->height
);
213 xw
->widgetscrolledwindow_osr
= NULL
; //webkit osr is the only scrolled component atm
215 if (EQ(xw
->type
, Qwebkit_osr
)){
216 xw
->widgetscrolledwindow_osr
= gtk_scrolled_window_new(NULL
, NULL
);
217 gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(xw
->widgetscrolledwindow_osr
),xw
->height
);
218 gtk_scrolled_window_set_min_content_width(GTK_SCROLLED_WINDOW(xw
->widgetscrolledwindow_osr
),xw
->width
);
219 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(xw
->widgetscrolledwindow_osr
), GTK_POLICY_ALWAYS
, GTK_POLICY_ALWAYS
);
221 xw
->widget_osr
=webkit_web_view_new();
222 gtk_container_add(GTK_CONTAINER(xw
->widgetscrolledwindow_osr
), GTK_WIDGET( WEBKIT_WEB_VIEW(xw
->widget_osr
)));
224 if(EQ(xw
->type
, Qsocket_osr
))
225 xw
->widget_osr
= gtk_socket_new();
226 if(!NILP (Fget(xw
->type
, QCxwgir_class
)))
227 xw
->widget_osr
= xwgir_create(SDATA(Fcar(Fcdr(Fget(xw
->type
, QCxwgir_class
)))),
228 SDATA(Fcar(Fget(xw
->type
, QCxwgir_class
))));
230 gtk_widget_set_size_request (GTK_WIDGET (xw
->widget_osr
), xw
->width
, xw
->height
);
232 if (EQ(xw
->type
, Qwebkit_osr
)){
233 gtk_container_add (GTK_CONTAINER (xw
->widgetwindow_osr
), xw
->widgetscrolledwindow_osr
);
235 gtk_container_add (GTK_CONTAINER (xw
->widgetwindow_osr
), xw
->widget_osr
);
238 gtk_widget_show (xw
->widget_osr
);
239 gtk_widget_show (xw
->widgetwindow_osr
);
240 gtk_widget_show (xw
->widgetscrolledwindow_osr
);
242 /* store some xwidget data in the gtk widgets for convenient retrieval in the event handlers. */
243 g_object_set_data (G_OBJECT (xw
->widget_osr
), XG_XWIDGET
, (gpointer
) (xw
));
244 g_object_set_data (G_OBJECT (xw
->widgetwindow_osr
), XG_XWIDGET
, (gpointer
) (xw
));
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
),
253 g_signal_connect (G_OBJECT (xw
->widget_osr
),
254 "download-requested",
255 G_CALLBACK (webkit_osr_download_callback
),
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
),
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
),
268 g_signal_connect (G_OBJECT (xw
->widget_osr
),
269 "navigation-policy-decision-requested",
270 G_CALLBACK (webkit_osr_navigation_policy_decision_requested_callback
),
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);
283 #endif /* HAVE_WEBKIT_OSR */
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.
295 Lisp_Object xw
, tail
, xw_list
;
297 if (NILP (buffer
)) return Qnil
;
298 buffer
= Fget_buffer (buffer
);
299 if (NILP (buffer
)) return Qnil
;
303 for (tail
= Vxwidget_list
; CONSP (tail
); tail
= XCDR (tail
))
306 if (XWIDGETP (xw
) && EQ (Fxwidget_buffer (xw
), buffer
))
307 xw_list
= Fcons (xw
, xw_list
);
313 xwidget_hidden(struct xwidget_view
*xv
)
320 buttonclick_handler (GtkWidget
* widget
, gpointer data
)
322 Lisp_Object xwidget_view
, xwidget
;
323 XSETXWIDGET_VIEW (xwidget_view
, (struct xwidget_view
*) data
);
324 xwidget
= Fxwidget_view_model (xwidget_view
);
326 struct input_event event
;
327 Lisp_Object frame
= Fwindow_frame (Fxwidget_view_window (xwidget_view
));
328 struct frame
*f
= XFRAME (frame
);
329 printf ("button clicked xw:%d '%s'\n", XXWIDGET (xwidget
), XXWIDGET (xwidget
)->title
);
332 event
.kind
= XWIDGET_EVENT
;
334 event
.frame_or_window
= frame
;
337 event
.arg
= Fcons (xwidget
, event
.arg
);
338 event
.arg
= Fcons (intern ("buttonclick"), event
.arg
);
340 kbd_buffer_store_event (&event
);
345 send_xembed_ready_event (struct xwidget
* xw
, int xembedid
)
348 XSETXWIDGET(xw_lo
, xw
);
349 struct input_event 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
355 event
.arg
= Fcons (make_number (xembedid
), event
.arg
);
356 event
.arg
= Fcons (xw_lo
, event
.arg
);
357 event
.arg
= Fcons (intern ("xembed-ready"), event
.arg
);
360 kbd_buffer_store_event (&event
);
365 xwidget_show_view (struct xwidget_view
*xv
)
368 gtk_widget_show(xv
->widgetwindow
);
369 gtk_fixed_move (GTK_FIXED (xv
->emacswindow
), xv
->widgetwindow
, xv
->x
+ xv
->clip_left
, xv
->y
+ xv
->clip_top
); //TODO refactor
373 /* hide an xvidget view */
375 xwidget_hide_view (struct xwidget_view
*xv
)
378 //gtk_widget_hide(xw->widgetwindow);
379 gtk_fixed_move (GTK_FIXED (xv
->emacswindow
), xv
->widgetwindow
,
385 xwidget_plug_added(GtkSocket
*socket
,
388 //hmm this doesnt seem to get called for foreign windows
389 printf("xwidget_plug_added\n");
393 xwidget_plug_removed(GtkSocket
*socket
,
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*/
402 xwidget_slider_changed (GtkRange
*range
,
405 //slider value changed. change value of siblings
406 //correspondingly. but remember that changing value will again
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
412 // - the type of the controllers value (double, boolean etc)
413 // - the getter and setter (but they can be func pointers)
414 // a behemoth macro is always an option.
415 double v
=gtk_range_get_value(range
);
416 struct xwidget_view
* xvp
= g_object_get_data (G_OBJECT (range
), XG_XWIDGET_VIEW
);
417 struct xwidget_view
* xv
;
419 printf("slider changed val:%f\n", v
);
421 for (Lisp_Object tail
= Vxwidget_view_list
; CONSP (tail
); tail
= XCDR (tail
))
423 if (XWIDGET_VIEW_P (XCAR (tail
))) {
424 xv
= XXWIDGET_VIEW (XCAR (tail
));
425 if (EQ (xvp
->model
, xv
->model
)) {
426 //block sibling views signal handlers
427 g_signal_handler_block(xv
->widget
, xv
->handler_id
);
429 //set values of sibling views and unblock
430 gtk_range_set_value(GTK_RANGE(xv
->widget
), v
);
431 g_signal_handler_unblock(xv
->widget
,xv
->handler_id
);
438 /* when the off-screen webkit master view changes this signal is called.
439 it copies the bitmap from the off-screen webkit instance */
441 offscreen_damage_event (GtkWidget
*widget
, GdkEvent
*event
, gpointer data
)
443 //TODO this is wrong! should just queu a redraw of onscreen widget
444 gtk_widget_queue_draw (GTK_WIDGET (data
));
449 store_xwidget_event_string(struct xwidget
* xw
, char* eventname
, const char* eventstr
)
452 struct input_event 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
460 event
.arg
= Fcons (build_string(eventstr
), event
.arg
); //string so dont intern
461 event
.arg
= Fcons (xwl
, event
.arg
); //TODO
462 event
.arg
= Fcons (intern (eventname
), event
.arg
);//interning should be ok
463 kbd_buffer_store_event (&event
);
467 //TODO deprecated, use load-status
469 webkit_osr_document_load_finished_callback (WebKitWebView
*webkitwebview
,
470 WebKitWebFrame
*arg1
,
473 //TODO this event sending code should be refactored
474 // struct xwidget *xw = (struct xwidget *) data;
475 struct xwidget
* xw
= (struct xwidget
*) g_object_get_data (G_OBJECT (webkitwebview
), XG_XWIDGET
);
476 printf("webkit finished loading\n");
478 store_xwidget_event_string(xw
,
479 "document-load-finished", "");
483 webkit_osr_download_callback (WebKitWebView
*webkitwebview
,
484 WebKitDownload
*arg1
,
487 //TODO this event sending code should be refactored
488 struct input_event event
;
489 // struct xwidget *xw = (struct xwidget *) data;
490 struct xwidget
* xw
= (struct xwidget
*) g_object_get_data (G_OBJECT (webkitwebview
), XG_XWIDGET
);
491 printf("download requested %s\n", webkit_download_get_uri (arg1
));
494 printf("webkit finished loading\n");
496 store_xwidget_event_string(xw
, "download-requested", webkit_download_get_uri (arg1
));
502 webkit_osr_mime_type_policy_typedecision_requested_callback(WebKitWebView
*webView
,
503 WebKitWebFrame
*frame
,
504 WebKitNetworkRequest
*request
,
506 WebKitWebPolicyDecision
*policy_decision
,
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
);
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
,
529 struct xwidget
* xw
= (struct xwidget
*) g_object_get_data (G_OBJECT (webView
), XG_XWIDGET
);
530 printf("webkit_osr_new_window_policy_decision_requested_callback %s\n",
531 webkit_web_navigation_action_get_original_uri (navigation_action
));
533 store_xwidget_event_string(xw
, "new-window-policy-decision-requested", webkit_web_navigation_action_get_original_uri (navigation_action
)
539 webkit_osr_navigation_policy_decision_requested_callback(WebKitWebView
*webView
,
540 WebKitWebFrame
*frame
,
541 WebKitNetworkRequest
*request
,
542 WebKitWebNavigationAction
*navigation_action
,
543 WebKitWebPolicyDecision
*policy_decision
,
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
)
554 //for gtk3 offscreen rendered widgets
556 xwidget_osr_draw_callback (GtkWidget
*widget
, cairo_t
*cr
, gpointer data
)
558 struct xwidget
* xw
= (struct xwidget
*) g_object_get_data (G_OBJECT (widget
), XG_XWIDGET
);
559 struct xwidget_view
* xv
= (struct xwidget_view
*) g_object_get_data (G_OBJECT (widget
), XG_XWIDGET_VIEW
);
561 cairo_rectangle(cr
, 0,0, xv
->clip_right
, xv
->clip_bottom
);//xw->width, xw->height);
565 if(xw
->widgetscrolledwindow_osr
!= NULL
)
566 gtk_widget_draw (xw
->widgetscrolledwindow_osr
, cr
);
568 gtk_widget_draw (xw
->widget_osr
, cr
);
572 GtkWidget
* xwgir_create_debug
;
577 xwidget_osr_event_forward (GtkWidget
*widget
,
581 /* copy events that arrive at the outer widget to the offscreen widget */
582 struct xwidget
* xw
= (struct xwidget
*) g_object_get_data (G_OBJECT (widget
), XG_XWIDGET
);
583 GdkEvent
* eventcopy
= gdk_event_copy(event
);
584 eventcopy
->any
.window
= gtk_widget_get_window(xw
->widget_osr
);// works
586 /* printf("xwidget_osr_event_forward redirect event to window:%d\n", ((GdkEventAny*)eventcopy)->window); */
587 /* printf("A type:%d x:%f y:%f \n", event->type, event->button.x, event->button.y); */
588 /* printf("B type:%d x:%f y:%f \n", eventcopy->type, eventcopy->button.x, eventcopy->button.y); */
589 //gtk_button_get_event_window(xwgir_create_debug);
590 gtk_main_do_event(eventcopy
); //TODO this will leak events. they should be deallocated later, perhaps in xwgir_event_callback
591 return TRUE
; //dont propagate this event furter
594 GIRepository
*girepository
;
596 DEFUN ("xwgir-require-namespace", Fxwgir_require_namespace
, Sxwgir_require_namespace
, 2,2,0,
597 doc
: /* Require a GObject Introspection namespace.
598 This must be done for all namespaces we want to use, before using other xwgir functions.*/)
599 (Lisp_Object lnamespace
, Lisp_Object lnamespace_version
)
601 char* namespace = SDATA(lnamespace
);
602 char* namespace_version
= SDATA(lnamespace_version
);
603 GError
*error
= NULL
;
605 girepository
= g_irepository_get_default();
606 g_irepository_require(girepository
, namespace, namespace_version
, 0, &error
);
608 g_error("ERROR: %s\n", error
->message
);
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
619 //also figure out how to pass args
621 GError
*error
= NULL
;
622 GIArgument return_value
;
624 GIObjectInfo
* obj_info
= g_irepository_find_by_name(girepository
, namespace, class);
625 GIFunctionInfo
* f_info
= g_object_info_find_method (obj_info
, "new");
626 g_function_info_invoke(f_info
,
631 xwgir_create_debug
= return_value
.v_pointer
;
632 return return_value
.v_pointer
;
637 xwgir_convert_lisp_to_gir_arg(GIArgument
* giarg
,
639 Lisp_Object lisparg
)
645 tag
= g_type_info_get_tag (g_arg_info_get_type (arginfo
));
649 case GI_TYPE_TAG_BOOLEAN
:
650 giarg
->v_boolean
= XFASTINT(lisparg
);
652 case GI_TYPE_TAG_INT8
:
653 giarg
->v_int8
= XFASTINT(lisparg
);
655 case GI_TYPE_TAG_UINT8
:
656 giarg
->v_uint8
= XFASTINT(lisparg
);
658 case GI_TYPE_TAG_INT16
:
659 giarg
->v_int16
= XFASTINT(lisparg
);
661 case GI_TYPE_TAG_UINT16
:
662 giarg
->v_uint16
= XFASTINT(lisparg
);
664 case GI_TYPE_TAG_INT32
:
665 giarg
->v_int32
= XFASTINT(lisparg
);
667 case GI_TYPE_TAG_UINT32
:
668 giarg
->v_uint32
= XFASTINT(lisparg
);
671 case GI_TYPE_TAG_INT64
:
672 giarg
->v_int64
= XFASTINT(lisparg
);
674 case GI_TYPE_TAG_UINT64
:
675 giarg
->v_uint64
= XFASTINT(lisparg
);
679 case GI_TYPE_TAG_FLOAT
:
680 giarg
->v_float
= XFLOAT_DATA(lisparg
);
683 case GI_TYPE_TAG_DOUBLE
:
684 giarg
->v_double
= XFLOAT_DATA(lisparg
);
687 case GI_TYPE_TAG_UTF8
:
688 case GI_TYPE_TAG_FILENAME
:
689 //giarg->v_string = SDATA(lisparg);
690 giarg
->v_pointer
= SDATA(lisparg
);
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");
713 //this methhod should be called from xwgir-xwidget-call-method and from xwgir xwidget construction
714 char* class = SDATA(Fcar(Fcdr(Fget(xw
->type
, QCxwgir_class
))));
716 GIObjectInfo
* obj_info
= g_irepository_find_by_name(girepository
, namespace, class);
717 GIFunctionInfo
* f_info
= g_object_info_find_method (obj_info
, SDATA(method
));
719 //loop over args, convert from lisp to primitive type, given arg introspection data
720 //TODO g_callable_info_get_n_args(f_info) should match
721 int argscount
= XFASTINT(Flength(arguments
));
722 if(argscount
!= g_callable_info_get_n_args(f_info
)){
723 printf("xwgir call method arg count doesn match! \n");
727 for (i
= 1; i
< argscount
+ 1; ++i
)
729 xwgir_convert_lisp_to_gir_arg(&in_args
[i
], g_callable_info_get_arg(f_info
, i
- 1), Fnth(i
- 1, arguments
));
732 in_args
[0].v_pointer
= widget
;
733 if(g_function_info_invoke(f_info
,
734 in_args
, argscount
+ 1,
738 //g_error("ERROR: %s\n", error->message);
739 printf("invokation error\n");
746 DEFUN ("xwgir-xwidget-call-method", Fxwgir_xwidget_call_method
, Sxwgir_xwidget_call_method
, 3, 3, 0,
747 doc
: /* Call Xwidget object method using GObject Introspection.
748 XWIDGET is the xwidget instance to act upon.
749 METHOD is the Gobject intrsopsection method name.
750 ARGUMENTS is a list of arguments for the call. They will be converted to GObject types from Lisp types.
752 (Lisp_Object xwidget
, Lisp_Object method
, Lisp_Object arguments
)
754 CHECK_XWIDGET (xwidget
);
755 GError
*error
= NULL
;
756 GIArgument return_value
;
757 GIArgument in_args
[20];
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
;
770 widget
= xw
->widget_osr
;
773 //char* class = SDATA(SYMBOL_NAME(xw->type)); //this works but is unflexible
774 //figure out the class from the widget instead
775 /* printf("type class: %s %s\n", G_OBJECT_TYPE_NAME(widget), G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(widget))); */
776 /* char* class = G_OBJECT_TYPE_NAME(widget); //gives "GtkButton"(I want "Button") */
777 /* class += strlen(namespace); //TODO check for corresponding api method. but this seems to work. */
779 char* class = SDATA(Fcar(Fcdr(Fget(xw
->type
, QCxwgir_class
))));
781 GIObjectInfo
* obj_info
= g_irepository_find_by_name(girepository
, namespace, class);
782 GIFunctionInfo
* f_info
= g_object_info_find_method (obj_info
, SDATA(method
));
784 //loop over args, convert from lisp to primitive type, given arg introspection data
785 //TODO g_callable_info_get_n_args(f_info) should match
786 int argscount
= XFASTINT(Flength(arguments
));
787 if(argscount
!= g_callable_info_get_n_args(f_info
)){
788 printf("xwgir call method arg count doesn match! \n");
793 for (i
= 1; i
< argscount
+ 1; ++i
)
795 XSETFASTINT (n
, i
- 1);
796 xwgir_convert_lisp_to_gir_arg(&in_args
[i
], g_callable_info_get_arg(f_info
, i
- 1), Fnth(n
, arguments
));
799 in_args
[0].v_pointer
= widget
;
800 if(g_function_info_invoke(f_info
,
801 in_args
, argscount
+ 1,
805 //g_error("ERROR: %s\n", error->message);
806 printf("invokation error\n");
813 to_child (GtkWidget
*bin
,
825 offscreen_pick_embedded_child (GdkWindow
*window
,
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
));
836 offscreen_to_embedder (GdkWindow
*window
,
843 * (gdouble
*) embedder_x
= offscreen_x
;
844 * (gdouble
*) embedder_y
= offscreen_y
;
848 offscreen_from_embedder (GdkWindow
*window
,
851 gpointer offscreen_x
,
852 gpointer offscreen_y
,
855 * (gdouble
*) offscreen_x
= embedder_x
;
856 * (gdouble
*) offscreen_y
= embedder_y
;
860 xwidget_osr_event_set_embedder (GtkWidget
*widget
,
864 struct xwidget_view
*xv
= (struct xwidget_view
*) data
;
865 struct xwidget
*xww
= XXWIDGET (xv
->model
);
866 printf("gdk_offscreen_window_set_embedder %d %d\n",
867 GDK_IS_WINDOW(gtk_widget_get_window (xww
->widget_osr
)),
868 GDK_IS_WINDOW(gtk_widget_get_window (GTK_WIDGET (xv
->widget
))));
869 gdk_offscreen_window_set_embedder (gtk_widget_get_window (xww
->widgetwindow_osr
),
870 gtk_widget_get_window (xv
->widget
));
874 /* initializes and does initial placement of an xwidget view on screen */
876 xwidget_init_view (struct xwidget
*xww
,
877 struct glyph_string
*s
,
880 struct xwidget_view
*xv
= allocate_xwidget_view();
884 XSETXWIDGET_VIEW (val
, xv
) ;
885 Vxwidget_view_list
= Fcons (val
, Vxwidget_view_list
);
887 XSETWINDOW(xv
->w
, s
->w
);
888 XSETXWIDGET(xv
->model
, xww
);
891 if(EQ(xww
->type
, Qbutton
))
893 xv
->widget
= gtk_button_new_with_label (XSTRING(xww
->title
)->data
);
894 g_signal_connect (G_OBJECT (xv
->widget
), "clicked",
895 G_CALLBACK (buttonclick_handler
), xv
); // the view rather than the model
896 } else if (EQ(xww
->type
, Qtoggle
)) {
897 xv
->widget
= gtk_toggle_button_new_with_label (XSTRING(xww
->title
)->data
);
898 //xv->widget = gtk_entry_new ();//temp hack to experiment with key propagation TODO entry widget is useful for testing
899 } else if (EQ(xww
->type
, Qsocket
)) {
900 xv
->widget
= gtk_socket_new ();
901 g_signal_connect_after(xv
->widget
, "plug-added", G_CALLBACK(xwidget_plug_added
), "plug added");
902 g_signal_connect_after(xv
->widget
, "plug-removed", G_CALLBACK(xwidget_plug_removed
), "plug removed");
903 //TODO these doesnt help
904 gtk_widget_add_events(xv
->widget
, GDK_KEY_PRESS
);
905 gtk_widget_add_events(xv
->widget
, GDK_KEY_RELEASE
);
906 } else if (EQ(xww
->type
, Qslider
)) {
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
)) {
914 //uhm cairo is differentish in gtk 3.
915 //gdk_cairo_create (gtk_widget_get_window (FRAME_GTK_WIDGET (s->f)));
916 xv
->widget
= gtk_drawing_area_new();
917 g_signal_connect (G_OBJECT ( xv
->widget
), "draw",
918 G_CALLBACK (xwidget_osr_draw_callback
), NULL
);
920 } else if (EQ(xww
->type
, Qwebkit_osr
)||
921 EQ(xww
->type
, Qsocket_osr
)||
922 (!NILP (Fget(xww
->type
, QCxwgir_class
))))//xwgir widgets are OSR
924 printf("osr init:%s\n",SDATA(SYMBOL_NAME(xww
->type
)));
925 xv
->widget
= gtk_drawing_area_new();
926 gtk_widget_set_app_paintable ( xv
->widget
, TRUE
); //because expose event handling
927 gtk_widget_add_events(xv
->widget
, GDK_ALL_EVENTS_MASK
);
929 /* Draw the view on damage-event */
930 g_signal_connect (G_OBJECT (xww
->widgetwindow_osr
), "damage-event",
931 G_CALLBACK (offscreen_damage_event
), xv
->widget
);
933 if (EQ(xww
->type
, Qwebkit_osr
)){
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
);
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
);
949 g_signal_connect (G_OBJECT (xv
->widget
), "draw",
950 G_CALLBACK (xwidget_osr_draw_callback
), NULL
);
956 //make container widget 1st, and put the actual widget inside the container
957 //later, drawing should crop container window if necessary to handle case where xwidget
958 //is partially obscured by other emacs windows
959 //other containers than gtk_fixed where explored, but gtk_fixed had the most predictable behaviour so far.
960 xv
->emacswindow
= FRAME_GTK_WIDGET (s
->f
);
961 xv
->widgetwindow
= gtk_fixed_new ();
962 gtk_widget_set_has_window(xv
->widgetwindow
, TRUE
);
963 gtk_container_add (GTK_CONTAINER (xv
->widgetwindow
), xv
->widget
);
965 //store some xwidget data in the gtk widgets
966 g_object_set_data (G_OBJECT (xv
->widget
), XG_FRAME_DATA
, (gpointer
) (s
->f
)); //the emacs frame
967 g_object_set_data (G_OBJECT (xv
->widget
), XG_XWIDGET
, (gpointer
) (xww
)); //the xwidget
968 g_object_set_data (G_OBJECT (xv
->widget
), XG_XWIDGET_VIEW
, (gpointer
) (xv
)); //the xwidget
969 g_object_set_data (G_OBJECT (xv
->widgetwindow
), XG_XWIDGET
, (gpointer
) (xww
)); //the xwidget window
970 g_object_set_data (G_OBJECT (xv
->widgetwindow
), XG_XWIDGET_VIEW
, (gpointer
) (xv
)); //the xwidget window
973 gtk_widget_set_size_request (GTK_WIDGET (xv
->widget
), xww
->width
, xww
->height
);
974 gtk_widget_set_size_request (xv
->widgetwindow
, xww
->width
, xww
->height
);
975 gtk_fixed_put (GTK_FIXED (FRAME_GTK_WIDGET (s
->f
)), xv
->widgetwindow
, x
, y
);
976 xv
->x
= x
; xv
->y
= y
;
977 gtk_widget_show_all (xv
->widgetwindow
);
981 //widgettype specific initialization only possible after realization
982 if (EQ(xww
->type
, Qsocket
)) {
983 printf ("xwid:%d socket id:%x %d\n",
985 gtk_socket_get_id (GTK_SOCKET (xv
->widget
)),
986 gtk_socket_get_id (GTK_SOCKET (xv
->widget
)));
987 send_xembed_ready_event (xww
,
988 gtk_socket_get_id (GTK_SOCKET (xv
->widget
)));
989 //gtk_widget_realize(xw->widget);
992 //////////////////////////////////////////////////////////////
994 if (//EQ(xww->type, Qwebkit_osr)|| //TODO should be able to choose compile time which method to use with webkit
995 EQ(xww
->type
, Qsocket_osr
)||
996 (!NILP (Fget(xww
->type
, QCxwgir_class
))))//xwgir widgets are OSR
998 printf("gdk_offscreen_window_set_embedder %d %d\n",
999 GDK_IS_WINDOW(gtk_widget_get_window (xww
->widget_osr
)),
1000 GDK_IS_WINDOW(gtk_widget_get_window (GTK_WIDGET (xv
->widget
))));
1001 // set_embedder needs to be called after xv->widget realization
1002 gdk_offscreen_window_set_embedder (gtk_widget_get_window (xww
->widgetwindow_osr
),
1003 gtk_widget_get_window (xv
->widget
));
1004 g_signal_connect (gtk_widget_get_window (xv
->widget
), "pick-embedded-child",
1005 G_CALLBACK (offscreen_pick_embedded_child
), xww
->widgetwindow_osr
);
1007 g_signal_connect (gtk_widget_get_window (xww
->widgetwindow_osr
), "from-embedder",
1008 G_CALLBACK (offscreen_from_embedder
), NULL
);
1009 g_signal_connect (gtk_widget_get_window (xww
->widgetwindow_osr
), "to-embedder",
1010 G_CALLBACK (offscreen_to_embedder
), NULL
);
1012 ////////////////////////////////////////
1019 x_draw_xwidget_glyph_string (struct glyph_string
*s
)
1022 this method is called by the redisplay engine and places the xwidget on screen.
1023 moving and clipping is done here. also view init.
1026 int box_line_hwidth
= eabs (s
->face
->box_line_width
);
1027 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
1028 int height
= s
->height
;
1029 struct xwidget
*xww
= s
->xwidget
;
1030 struct xwidget_view
*xv
= xwidget_view_lookup(xww
, s
->w
);
1031 int clip_right
; int clip_bottom
; int clip_top
; int clip_left
;
1034 int y
= s
->y
+ (s
->height
/ 2) - (xww
->height
/ 2);
1037 /* We do it here in the display loop because there is no other
1038 time to know things like window placement etc.
1040 printf ("xv init for xw %d\n", xww
);
1041 xv
= xwidget_init_view (xww
, s
, x
, y
);
1043 //calculate clipping, which is used for all manner of onscreen xwidget views
1044 //each widget border can get clipped by other emacs objects so there are four clipping variables
1045 clip_right
= min (xww
->width
, WINDOW_RIGHT_EDGE_X (s
->w
) - x
- WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH(s
->w
) - WINDOW_RIGHT_FRINGE_WIDTH(s
->w
));
1046 clip_left
= max (0, WINDOW_LEFT_EDGE_X (s
->w
) - x
+ WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH(s
->w
) + WINDOW_LEFT_FRINGE_WIDTH(s
->w
));
1048 clip_bottom
= min (xww
->height
, WINDOW_BOTTOM_EDGE_Y (s
->w
) - WINDOW_MODE_LINE_HEIGHT (s
->w
) - y
);
1049 clip_top
= max(0, WINDOW_TOP_EDGE_Y(s
->w
) -y
);
1051 //we are conserned with movement of the onscreen area. the area might sit still when the widget actually moves
1052 //this happens when an emacs window border moves across a widget window
1053 //so, if any corner of the outer widget clippng window moves, that counts as movement here, even
1054 //if it looks like no movement happens because the widget sits still inside the clipping area.
1055 //the widget can also move inside the clipping area, which happens later
1056 moved
= (xv
->x
+ xv
->clip_left
!= x
+clip_left
)
1057 || ((xv
->y
+ xv
->clip_top
)!= (y
+clip_top
));
1058 if(moved
) printf ("lxwidget moved: id:%d (%d,%d)->(%d,%d) y+clip_top:%d\n", xww
, xv
->x
, xv
->y
, x
, y
, y
+ clip_top
);
1060 printf ("lxwidget DIDNT move: id:%d (%d,%d)->(%d,%d) y+clip_top:%d\n", xww
, xv
->x
, xv
->y
, x
, y
, y
+ clip_top
);
1063 if (moved
) //has it moved?
1065 if (1)//!xwidget_hidden(xv)) //hidden equals not being seen during redisplay
1067 //TODO should be possible to use xwidget_show_view here
1068 gtk_fixed_move (GTK_FIXED (FRAME_GTK_WIDGET (s
->f
)),
1070 x
+ clip_left
, y
+ clip_top
);
1073 //clip the widget window if some parts happen to be outside drawable area
1074 //an emacs window is not a gtk window, a gtk window covers the entire frame
1075 //cliping might have changed even if we havent actualy moved, we try figure out when we need to reclip for real
1076 if((xv
->clip_right
!= clip_right
)
1077 || (xv
->clip_bottom
!= clip_bottom
)
1078 || (xv
->clip_top
!= clip_top
)
1079 || (xv
->clip_left
!= clip_left
)){
1080 gtk_widget_set_size_request (xv
->widgetwindow
, clip_right
+ clip_left
, clip_bottom
+ clip_top
);
1081 gtk_fixed_move(GTK_FIXED(xv
->widgetwindow
), xv
->widget
, -clip_left
, -clip_top
);
1082 printf("reclip %d %d -> %d %d clip_top:%d clip_left:%d\n",xv
->clip_right
, xv
->clip_bottom
, clip_right
, clip_bottom
, clip_top
, clip_left
);
1085 xv
->clip_right
= clip_right
; xv
->clip_bottom
= clip_bottom
; xv
->clip_top
= clip_top
;xv
->clip_left
= clip_left
;
1087 //if emacs wants to repaint the area where the widget lives, queue a redraw
1088 //TODO it seems its possible to get out of sync with emacs redraws so emacs bg sometimes shows up instead of xwidget
1089 //its just a visual glitch though
1090 if (!xwidget_hidden(xv
)){
1091 gtk_widget_queue_draw (xv
->widgetwindow
);
1092 gtk_widget_queue_draw (xv
->widget
);
1097 #ifdef HAVE_WEBKIT_OSR
1099 //FUGLY macro that checks WEBKIT_IS_WEB_VIEW(xw->widget_osr) first
1100 #define WEBKIT_FN_INIT() \
1101 struct xwidget* xw; \
1102 CHECK_XWIDGET (xwidget); \
1103 if(NILP (xwidget)) {printf("ERROR xwidget nil\n"); return Qnil;}; \
1104 xw = XXWIDGET(xwidget); \
1105 if(NULL == xw) printf("ERROR xw is 0\n"); \
1106 if((NULL == xw->widget_osr) || !WEBKIT_IS_WEB_VIEW(xw->widget_osr)){ \
1107 printf("ERROR xw->widget_osr does not hold a webkit instance\n");\
1112 DEFUN ("xwidget-webkit-goto-uri", Fxwidget_webkit_goto_uri
, Sxwidget_webkit_goto_uri
,
1114 doc
: /* Make the webkit instance referenced by XWIDGET browse URI. */)
1115 (Lisp_Object xwidget
, Lisp_Object uri
)
1119 webkit_web_view_load_uri ( WEBKIT_WEB_VIEW(xw
->widget_osr
), SDATA(uri
));
1124 DEFUN ("xwidget-webkit-execute-script", Fxwidget_webkit_execute_script
, Sxwidget_webkit_execute_script
,
1126 doc
: /* webkit exec js.*/)
1127 (Lisp_Object xwidget
, Lisp_Object script
)
1130 CHECK_STRING(script
);
1131 webkit_web_view_execute_script( WEBKIT_WEB_VIEW(xw
->widget_osr
), SDATA(script
));
1135 DEFUN ("xwidget-webkit-get-title", Fxwidget_webkit_get_title
, Sxwidget_webkit_get_title
,
1137 doc
: /* Get the title from the Webkit instance in XWIDGET.
1138 This can be used to work around the lack of a return value from the exec method.
1140 (Lisp_Object xwidget
)
1142 //TODO support multibyte strings
1144 const gchar
* str
=webkit_web_view_get_title( WEBKIT_WEB_VIEW(xw
->widget_osr
));
1145 //return make_string_from_bytes(str, wcslen((const wchar_t *)str), strlen(str));
1147 //TODO maybe return Qnil instead. I suppose webkit returns nullpointer when doc is not properly loaded or something
1148 printf("xwidget-webkit-get-title null webkit title\n");
1149 return build_string("");
1151 return build_string(str
);
1155 DEFUN ("xwidget-disable-plugin-for-mime", Fxwidget_disable_plugin_for_mime
, Sxwidget_disable_plugin_for_mime
,
1159 WebKitWebPlugin
*wp
= webkit_web_plugin_database_get_plugin_for_mimetype
1160 (webkit_get_web_plugin_database(), SDATA(mime
));
1161 if(wp
== NULL
) return Qnil
;
1162 if(webkit_web_plugin_get_enabled (wp
)){
1163 webkit_web_plugin_set_enabled (wp
, FALSE
);
1171 xwidget_webkit_dom_dump(WebKitDOMNode
* parent
)
1173 WebKitDOMNodeList
* list
;
1176 WebKitDOMNode
* attribute
;
1177 WebKitDOMNamedNodeMap
* attrs
;
1178 WebKitDOMNode
* child
;
1179 printf("node:%d type:%d name:%s content:%s\n",
1181 webkit_dom_node_get_node_type(parent
),//1 element 3 text 8 comment 2 attribute
1182 webkit_dom_node_get_local_name(parent
),
1183 webkit_dom_node_get_text_content(parent
));
1185 if(webkit_dom_node_has_attributes(parent
)){
1186 attrs
= webkit_dom_node_get_attributes(parent
);
1188 length
= webkit_dom_named_node_map_get_length(attrs
);
1189 for (int i
= 0; i
< length
; i
++) {
1190 attribute
= webkit_dom_named_node_map_item(attrs
,i
);
1191 printf(" attr node:%d type:%d name:%s content:%s\n",
1193 webkit_dom_node_get_node_type(attribute
),//1 element 3 text 8 comment
1194 webkit_dom_node_get_local_name(attribute
),
1195 webkit_dom_node_get_text_content(attribute
));
1198 list
= webkit_dom_node_get_child_nodes(parent
);
1199 length
= webkit_dom_node_list_get_length(list
);
1201 for (int i
= 0; i
< length
; i
++) {
1202 child
= webkit_dom_node_list_item(list
, i
);
1203 //if(webkit_dom_node_has_child_nodes(child))
1204 xwidget_webkit_dom_dump(child
);
1209 DEFUN ("xwidget-webkit-dom-dump", Fxwidget_webkit_dom_dump
, Sxwidget_webkit_dom_dump
,
1211 doc
: /*Dump the DOM contained in the webkit instance in XWIDGET.*/)
1212 (Lisp_Object xwidget
)
1215 xwidget_webkit_dom_dump(WEBKIT_DOM_NODE(webkit_web_view_get_dom_document( WEBKIT_WEB_VIEW(xw
->widget_osr
))));
1221 #endif /* HAVE_WEBKIT_OSR */
1225 DEFUN ("xwidget-resize", Fxwidget_resize
, Sxwidget_resize
, 3, 3, 0, doc
:
1227 NEW_WIDTH NEW_HEIGHT defines the new size.)
1229 (Lisp_Object xwidget
, Lisp_Object new_width
, Lisp_Object new_height
)
1231 CHECK_XWIDGET (xwidget
);
1232 struct xwidget
* xw
= XXWIDGET(xwidget
);
1233 struct xwidget_view
*xv
;
1236 CHECK_NUMBER (new_width
);
1237 CHECK_NUMBER (new_height
);
1238 w
= XFASTINT (new_width
);
1239 h
= XFASTINT (new_height
);
1242 printf("resize xwidget %d (%d,%d)->(%d,%d)\n",xw
, xw
->width
,xw
->height
,w
,h
);
1245 //if theres a osr resize it 1st
1247 printf("resize xwidget_osr\n");
1248 //gtk_container_set_resize_mode ( GTK_WINDOW(xw->widgetwindow_osr), GTK_RESIZE_QUEUE);
1249 //gtk_container_set_resize_mode ( GTK_WINDOW(xw->widget_osr), GTK_RESIZE_QUEUE);
1252 //gtk_layout_set_size (GTK_LAYOUT (xw->widgetwindow_osr), xw->width, xw->height);
1253 gtk_widget_set_size_request (GTK_WIDGET (xw
->widget_osr
), xw
->width
, xw
->height
); //minimum size
1254 //gtk_window_resize( GTK_WINDOW(xw->widget_osr), xw->width, xw->height);
1255 gtk_window_resize( GTK_WINDOW(xw
->widgetwindow_osr
), xw
->width
, xw
->height
);
1256 gtk_window_resize( GTK_WINDOW(xw
->widgetscrolledwindow_osr
), xw
->width
, xw
->height
);
1257 gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(xw
->widgetscrolledwindow_osr
),xw
->height
);
1258 gtk_scrolled_window_set_min_content_width(GTK_SCROLLED_WINDOW(xw
->widgetscrolledwindow_osr
),xw
->width
);
1260 //gtk_container_resize_children ( GTK_WINDOW(xw->widgetwindow_osr));
1261 gtk_container_resize_children (GTK_CONTAINER(xw
->widgetwindow_osr
));
1265 for (Lisp_Object tail
= Vxwidget_view_list
; CONSP (tail
); tail
= XCDR (tail
)) //TODO MVC refactor lazy linear search
1267 if (XWIDGET_VIEW_P (XCAR (tail
))) {
1268 xv
= XXWIDGET_VIEW (XCAR (tail
));
1269 if(XXWIDGET (xv
->model
) == xw
) {
1270 gtk_layout_set_size (GTK_LAYOUT (xv
->widgetwindow
), xw
->width
, xw
->height
);
1271 gtk_widget_set_size_request (GTK_WIDGET (xv
->widget
), xw
->width
, xw
->height
);
1281 DEFUN ("xwidget-set-adjustment", Fxwidget_set_adjustment
, Sxwidget_set_adjustment
, 4, 4, 0, doc
:
1282 /* set scrolling */)
1283 (Lisp_Object xwidget
, Lisp_Object axis
, Lisp_Object relative
, Lisp_Object value
)
1285 CHECK_XWIDGET (xwidget
);
1286 struct xwidget
* xw
= XXWIDGET(xwidget
);
1287 GtkAdjustment
* adjustment
;
1288 float final_value
=0.0;
1290 if(EQ(Qvertical
, axis
)){
1291 adjustment
= gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(xw
->widgetscrolledwindow_osr
));
1293 if(EQ(Qhorizontal
, axis
)){
1294 adjustment
= gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(xw
->widgetscrolledwindow_osr
));
1297 if(EQ(Qt
, relative
)){
1298 final_value
=gtk_adjustment_get_value(adjustment
)+XFASTINT(value
);
1300 final_value
=0.0+XFASTINT(value
);
1303 gtk_adjustment_set_value(adjustment
, final_value
);
1309 DEFUN ("xwidget-size-request", Fxwidget_size_request
, Sxwidget_size_request
, 1, 1, 0, doc
:
1310 /* Desired size of the XWIDGET.
1312 This can be used to read the xwidget desired size, and resizes the Emacs allocated area accordingly.
1314 (TODO crashes if arg not osr widget)*/)
1315 (Lisp_Object xwidget
)
1317 CHECK_XWIDGET (xwidget
);
1318 GtkRequisition requisition
;
1320 gtk_widget_size_request(XXWIDGET(xwidget
)->widget_osr
, &requisition
);
1322 rv
= Fcons (make_number(requisition
.height
), rv
);
1323 rv
= Fcons (make_number(requisition
.width
), rv
);
1328 DEFUN ("xwidgetp", Fxwidgetp
, Sxwidgetp
, 1, 1, 0,
1329 doc
: /* Return t if OBJECT is a xwidget. */)
1330 (Lisp_Object object
)
1332 return XWIDGETP (object
) ? Qt
: Qnil
;
1335 DEFUN ("xwidget-view-p", Fxwidget_view_p
, Sxwidget_view_p
, 1, 1, 0,
1336 doc
: /* Return t if OBJECT is a xwidget-view. */)
1337 (Lisp_Object object
)
1339 return XWIDGET_VIEW_P (object
) ? Qt
: Qnil
;
1342 DEFUN ("xwidget-info", Fxwidget_info
, Sxwidget_info
, 1,1,0,
1343 doc
: /* Get XWIDGET properties.
1344 Currently type, title, width, height.*/)
1345 (Lisp_Object xwidget
)
1347 CHECK_XWIDGET (xwidget
);
1348 Lisp_Object info
, n
;
1349 struct xwidget
* xw
= XXWIDGET(xwidget
);
1351 info
= Fmake_vector (make_number (4), Qnil
);
1352 ASET (info
, 0, xw
->type
);
1353 ASET (info
, 1, xw
->title
);
1354 XSETFASTINT(n
, xw
->width
);
1356 XSETFASTINT(n
, xw
->height
);
1362 DEFUN ("xwidget-view-info", Fxwidget_view_info
, Sxwidget_view_info
, 1, 1, 0, doc
:
1363 /* Get XWIDGET-VIEW properties.
1364 Currently x,y clip right, clip bottom, clip top, clip left*/)
1365 (Lisp_Object xwidget_view
)
1367 CHECK_XWIDGET_VIEW (xwidget_view
);
1368 struct xwidget_view
*xv
= XXWIDGET_VIEW (xwidget_view
);
1371 info
= Fmake_vector (make_number (6), Qnil
);
1372 ASET (info
, 0, make_number(xv
->x
));
1373 ASET (info
, 1, make_number(xv
->y
));
1374 ASET (info
, 2, make_number(xv
->clip_right
));
1375 ASET (info
, 3, make_number(xv
->clip_bottom
));
1376 ASET (info
, 4, make_number(xv
->clip_top
));
1377 ASET (info
, 5, make_number(xv
->clip_left
));
1382 DEFUN ("xwidget-view-model", Fxwidget_view_model
, Sxwidget_view_model
,
1384 doc
: /* Get XWIDGET-VIEW model. */)
1385 (Lisp_Object xwidget_view
)
1387 CHECK_XWIDGET_VIEW (xwidget_view
);
1388 return XXWIDGET_VIEW (xwidget_view
)->model
;
1391 DEFUN ("xwidget-view-window", Fxwidget_view_window
, Sxwidget_view_window
,
1393 doc
: /* Get XWIDGET-VIEW window. */)
1394 (Lisp_Object xwidget_view
)
1396 CHECK_XWIDGET_VIEW (xwidget_view
);
1397 return XXWIDGET_VIEW (xwidget_view
)->w
;
1400 DEFUN ("xwidget-send-keyboard-event", Fxwidget_send_keyboard_event
, Sxwidget_send_keyboard_event
, 2, 2, 0,
1401 doc
:/* Synthesize a kbd event for XWIDGET. TODO crashes atm.. */
1403 (Lisp_Object xwidget
, Lisp_Object keydescriptor
)
1405 //TODO this code crashes for offscreen widgets and ive tried many different strategies
1406 //int keyval = 0x058; //X
1407 int keyval
= XFASTINT(keydescriptor
); //X
1408 char *keystring
= "";
1411 GdkDeviceManager
* manager
;
1416 //popup_activated_flag = 1; //TODO just a hack
1417 gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), keyval
, &keys
, &n_keys
);
1419 xw
= XXWIDGET(xwidget
);
1421 ev
= (GdkEventKey
*)gdk_event_new(GDK_KEY_PRESS
);
1424 //todo what about windowless widgets?
1426 window
= FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1429 //TODO maybe we also need to special case sockets by picking up the plug rather than the socket
1431 widget
= xw
->widget_osr
;
1433 widget
= xwidget_view_lookup(xw
, XWINDOW(window
))->widget
;
1435 ev
->window
= gtk_widget_get_window(widget
);
1436 gtk_widget_grab_focus(widget
);
1437 ev
->send_event
= FALSE
;
1439 ev
->hardware_keycode
= keys
[0].keycode
;
1440 ev
->group
= keys
[0].group
;
1442 ev
->keyval
= keyval
;
1443 ev
->time
= GDK_CURRENT_TIME
;
1445 //ev->device = gdk_device_get_core_pointer();
1446 manager
= gdk_display_get_device_manager(gdk_window_get_display(ev
->window
));
1447 gdk_event_set_device ((GdkEvent
*)ev
, gdk_device_manager_get_client_pointer(manager
));
1448 gdk_event_put((GdkEvent
*)ev
);
1449 //g_signal_emit_by_name(ev->window,"key-press-event", ev);
1451 ev
->type
= GDK_KEY_RELEASE
;
1452 gdk_event_put((GdkEvent
*)ev
);
1453 //g_signal_emit_by_name(ev->window,"key-release-event", ev);
1454 //gtk_main_do_event(ev);
1457 //if I delete the event the receiving component eventually crashes.
1458 //it ough TDTRT since event_put is supposed to copy the event
1459 //so probably this leaks events now
1460 //gdk_event_free((GdkEvent*)ev);
1465 DEFUN ("delete-xwidget-view", Fdelete_xwidget_view
, Sdelete_xwidget_view
,
1467 doc
: /* Delete the XWIDGET-VIEW. */)
1468 (Lisp_Object xwidget_view
)
1470 CHECK_XWIDGET_VIEW (xwidget_view
);
1471 struct xwidget_view
*xv
= XXWIDGET_VIEW (xwidget_view
);
1472 gtk_widget_destroy(xv
->widgetwindow
);
1473 Vxwidget_view_list
= Fdelq (xwidget_view
, Vxwidget_view_list
);
1476 DEFUN ("xwidget-view-lookup", Fxwidget_view_lookup
, Sxwidget_view_lookup
,
1478 doc
: /* Return the xwidget-view associated to XWIDGET in
1479 WINDOW if specified, otherwise it uses the selected window. */)
1480 (Lisp_Object xwidget
, Lisp_Object window
)
1482 CHECK_XWIDGET (xwidget
);
1485 window
= Fselected_window();
1486 CHECK_WINDOW (window
);
1488 for (Lisp_Object tail
= Vxwidget_view_list
; CONSP (tail
); tail
= XCDR (tail
))
1490 Lisp_Object xwidget_view
= XCAR (tail
);
1491 if (EQ (Fxwidget_view_model (xwidget_view
), xwidget
)
1492 && EQ (Fxwidget_view_window (xwidget_view
), window
))
1493 return xwidget_view
;
1499 DEFUN ("set-frame-visible", Fset_frame_visible
, Sset_frame_visible
,
1502 (Lisp_Object frame
, Lisp_Object flag
)
1504 CHECK_FRAME (frame
);
1505 struct frame
*f
= XFRAME (frame
);
1506 SET_FRAME_VISIBLE (f
, !NILP (flag
));
1510 DEFUN ("xwidget-plist", Fxwidget_plist
, Sxwidget_plist
,
1512 doc
: /* Return the plist of XWIDGET. */)
1513 (register Lisp_Object xwidget
)
1515 CHECK_XWIDGET (xwidget
);
1516 return XXWIDGET (xwidget
)->plist
;
1519 DEFUN ("xwidget-buffer", Fxwidget_buffer
, Sxwidget_buffer
,
1521 doc
: /* Return the buffer of XWIDGET. */)
1522 (register Lisp_Object xwidget
)
1524 CHECK_XWIDGET (xwidget
);
1525 return XXWIDGET (xwidget
)->buffer
;
1528 DEFUN ("set-xwidget-plist", Fset_xwidget_plist
, Sset_xwidget_plist
,
1530 doc
: /* Replace the plist of XWIDGET with PLIST. Returns PLIST. */)
1531 (register Lisp_Object xwidget
, Lisp_Object plist
)
1533 CHECK_XWIDGET (xwidget
);
1536 XXWIDGET (xwidget
)->plist
= plist
;
1540 DEFUN ("set-xwidget-query-on-exit-flag",
1541 Fset_xwidget_query_on_exit_flag
, Sset_xwidget_query_on_exit_flag
,
1543 doc
: /* Specify if query is needed for XWIDGET when Emacs is
1544 exited. If the second argument FLAG is non-nil, Emacs will query the
1545 user before exiting or killing a buffer if XWIDGET is running. This
1546 function returns FLAG. */)
1547 (Lisp_Object xwidget
, Lisp_Object flag
)
1549 CHECK_XWIDGET (xwidget
);
1550 XXWIDGET (xwidget
)->kill_without_query
= NILP (flag
);
1554 DEFUN ("xwidget-query-on-exit-flag",
1555 Fxwidget_query_on_exit_flag
, Sxwidget_query_on_exit_flag
,
1557 doc
: /* Return the current value of query-on-exit flag for XWIDGET. */)
1558 (Lisp_Object xwidget
)
1560 CHECK_XWIDGET (xwidget
);
1561 return (XXWIDGET (xwidget
)->kill_without_query
? Qnil
: Qt
);
1565 syms_of_xwidget (void)
1569 defsubr (&Smake_xwidget
);
1570 defsubr (&Sxwidgetp
);
1571 DEFSYM (Qxwidgetp
, "xwidgetp");
1572 defsubr (&Sxwidget_view_p
);
1573 DEFSYM (Qxwidget_view_p
, "xwidget-view-p");
1574 defsubr (&Sxwidget_info
);
1575 defsubr (&Sxwidget_view_info
);
1576 defsubr (&Sxwidget_resize
);
1577 defsubr (&Sget_buffer_xwidgets
);
1578 defsubr (&Sxwidget_view_model
);
1579 defsubr (&Sxwidget_view_window
);
1580 defsubr (&Sxwidget_view_lookup
);
1581 defsubr (&Sxwidget_query_on_exit_flag
);
1582 defsubr (&Sset_xwidget_query_on_exit_flag
);
1583 defsubr (&Sset_frame_visible
);
1585 #ifdef HAVE_WEBKIT_OSR
1586 defsubr (&Sxwidget_webkit_goto_uri
);
1587 defsubr (&Sxwidget_webkit_execute_script
);
1588 defsubr (&Sxwidget_webkit_get_title
);
1589 DEFSYM (Qwebkit_osr
, "webkit-osr");
1592 defsubr (&Sxwgir_xwidget_call_method
);
1593 defsubr (&Sxwgir_require_namespace
);
1594 defsubr (&Sxwidget_size_request
);
1595 defsubr (&Sdelete_xwidget_view
);
1596 defsubr (&Sxwidget_disable_plugin_for_mime
);
1598 defsubr (&Sxwidget_send_keyboard_event
);
1599 defsubr (&Sxwidget_webkit_dom_dump
);
1600 defsubr (&Sxwidget_plist
);
1601 defsubr (&Sxwidget_buffer
);
1602 defsubr (&Sset_xwidget_plist
);
1604 defsubr (&Sxwidget_set_adjustment
);
1606 DEFSYM (Qxwidget
, "xwidget");
1608 DEFSYM (QCxwidget
, ":xwidget");
1609 DEFSYM (QCxwgir_class
, ":xwgir-class");
1610 DEFSYM (QCtitle
, ":title");
1612 /* Do not forget to update the docstring of make-xwidget if you add
1614 DEFSYM (Qbutton
, "Button"); //changed to match the gtk class because xwgir(experimental and not really needed)
1615 DEFSYM (Qtoggle
, "ToggleButton");
1616 DEFSYM (Qslider
, "slider");
1617 DEFSYM (Qsocket
, "socket");
1618 DEFSYM (Qsocket_osr
, "socket-osr");
1619 DEFSYM (Qcairo
, "cairo");
1621 DEFSYM (Qvertical
, "vertical");
1622 DEFSYM (Qhorizontal
, "horizontal");
1624 DEFSYM (QCplist
, ":plist");
1626 DEFVAR_LISP ("xwidget-list", Vxwidget_list
, doc
: /*xwidgets list*/);
1627 Vxwidget_list
= Qnil
;
1629 DEFVAR_LISP ("xwidget-view-list", Vxwidget_view_list
, doc
: /*xwidget views list*/);
1630 Vxwidget_view_list
= Qnil
;
1632 Fprovide (intern ("xwidget-internal"), Qnil
);
1637 /* Value is non-zero if OBJECT is a valid Lisp xwidget specification. A
1638 valid xwidget specification is a list whose car is the symbol
1639 `xwidget', and whose rest is a property list. The property list must
1640 contain a value for key `:type'. That value must be the name of a
1641 supported xwidget type. The rest of the property list depends on the
1645 valid_xwidget_spec_p (Lisp_Object object
)
1649 if (CONSP (object
) && EQ (XCAR (object
), Qxwidget
))
1651 /* Lisp_Object tem; */
1653 /* for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem)) */
1654 /* if (EQ (XCAR (tem), QCtype)) */
1656 /* tem = XCDR (tem); */
1657 /* if (CONSP (tem) && SYMBOLP (XCAR (tem))) */
1659 /* struct xwidget_type *type; */
1660 /* type = lookup_xwidget_type (XCAR (tem)); */
1662 /* valid_p = type->valid_p (object); */
1667 //never mind type support for now
1676 /* find a value associated with key in spec */
1678 xwidget_spec_value ( Lisp_Object spec
, Lisp_Object key
,
1683 eassert (valid_xwidget_spec_p (spec
));
1685 for (tail
= XCDR (spec
);
1686 CONSP (tail
) && CONSP (XCDR (tail
)); tail
= XCDR (XCDR (tail
)))
1688 if (EQ (XCAR (tail
), key
))
1692 return XCAR (XCDR (tail
));
1703 xwidget_view_delete_all_in_window (struct window
*w
)
1705 struct xwidget_view
* xv
= NULL
;
1706 for (Lisp_Object tail
= Vxwidget_view_list
; CONSP (tail
); tail
= XCDR (tail
))
1708 if (XWIDGET_VIEW_P (XCAR (tail
))) {
1709 xv
= XXWIDGET_VIEW (XCAR (tail
));
1710 if(XWINDOW (xv
->w
) == w
) {
1711 gtk_widget_destroy(xv
->widgetwindow
);
1712 Vxwidget_view_list
= Fdelq (XCAR (tail
), Vxwidget_view_list
);
1718 struct xwidget_view
*
1719 xwidget_view_lookup (struct xwidget
* xw
, struct window
*w
)
1721 Lisp_Object xwidget
, window
, ret
;
1722 XSETXWIDGET (xwidget
, xw
);
1723 XSETWINDOW (window
, w
);
1725 ret
= Fxwidget_view_lookup (xwidget
, window
);
1727 return EQ (ret
, Qnil
) ? NULL
: XXWIDGET_VIEW (ret
);
1731 lookup_xwidget (Lisp_Object spec
)
1733 /* When a xwidget lisp spec is found initialize the C struct that is used in the C code.
1734 This is done by redisplay so values change if the spec changes.
1735 So, take special care of one-shot events
1737 TODO remove xwidget init from display spec. simply store an xwidget reference only and set
1738 size etc when creating the xwidget, which should happen before insertion into buffer
1740 int found
= 0, found1
= 0, found2
= 0;
1744 value
= xwidget_spec_value (spec
, QCxwidget
, &found1
);
1745 xw
= XXWIDGET(value
);
1747 /* value = xwidget_spec_value (spec, QCtype, &found); */
1748 /* xw->type = SYMBOLP (value) ? value : Qbutton; //default to button */
1749 /* value = xwidget_spec_value (spec, QCtitle, &found2); */
1750 /* xw->title = STRINGP (value) ? (char *) SDATA (value) : "?"; //funky cast FIXME TODO */
1752 /* value = xwidget_spec_value (spec, QCheight, NULL); */
1753 /* xw->height = INTEGERP (value) ? XFASTINT (value) : 50; */
1754 /* value = xwidget_spec_value (spec, QCwidth, NULL); */
1755 /* xw->width = INTEGERP (value) ? XFASTINT (value) : 50; */
1757 /* value = xwidget_spec_value (spec, QCplist, NULL); */
1758 /* xw->plist = value; */
1759 /* coordinates are not known here */
1760 printf ("lookup_xwidget xwidget_id:%d type:%d found:%d %d %d title:'%s' (%d,%d)\n", xw
,
1761 xw
->type
, found
, found1
, found2
, xw
->title
, xw
->height
, xw
->width
);
1763 //assert_valid_xwidget_id (id, "lookup_xwidget");
1767 /*set up detection of touched xwidget*/
1769 xwidget_start_redisplay (void)
1771 for (Lisp_Object tail
= Vxwidget_view_list
; CONSP (tail
); tail
= XCDR (tail
))
1773 if (XWIDGET_VIEW_P (XCAR (tail
)))
1774 XXWIDGET_VIEW (XCAR (tail
))->redisplayed
= 0;
1778 /* the xwidget was touched during redisplay, so it isnt a candidate for hiding*/
1780 xwidget_touch (struct xwidget_view
*xv
)
1782 xv
->redisplayed
= 1;
1786 xwidget_touched (struct xwidget_view
*xv
)
1788 return xv
->redisplayed
;
1791 /* redisplay has ended, now we should hide untouched xwidgets
1794 xwidget_end_redisplay (struct window
*w
, struct glyph_matrix
*matrix
)
1802 xwidget_start_redisplay ();
1803 //iterate desired glyph matrix of window here, hide gtk widgets
1804 //not in the desired matrix.
1806 //this only takes care of xwidgets in active windows.
1807 //if a window goes away from screen xwidget views wust be deleted
1809 // dump_glyph_matrix(matrix, 2);
1810 for (i
= 0; i
< matrix
->nrows
; ++i
)
1812 // dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
1813 struct glyph_row
*row
;
1814 row
= MATRIX_ROW (matrix
, i
);
1815 if (row
->enabled_p
!= 0)
1817 for (area
= LEFT_MARGIN_AREA
; area
< LAST_AREA
; ++area
)
1819 struct glyph
*glyph
= row
->glyphs
[area
];
1820 struct glyph
*glyph_end
= glyph
+ row
->used
[area
];
1821 for (; glyph
< glyph_end
; ++glyph
)
1823 if (glyph
->type
== XWIDGET_GLYPH
)
1826 the only call to xwidget_end_redisplay is in dispnew
1827 xwidget_end_redisplay(w->current_matrix);
1829 xwidget_touch (xwidget_view_lookup(glyph
->u
.xwidget
,
1837 for (Lisp_Object tail
= Vxwidget_view_list
; CONSP (tail
); tail
= XCDR (tail
))
1839 if (XWIDGET_VIEW_P (XCAR (tail
))) {
1840 struct xwidget_view
* xv
= XXWIDGET_VIEW (XCAR (tail
));
1842 //"touched" is only meaningful for the current window, so disregard other views
1843 if (XWINDOW (xv
->w
) == w
) {
1844 if (xwidget_touched(xv
))
1845 xwidget_show_view (xv
);
1847 xwidget_hide_view (xv
);
1853 /* Kill all xwidget in BUFFER. */
1855 kill_buffer_xwidgets (Lisp_Object buffer
)
1857 Lisp_Object tail
, xwidget
;
1858 for (tail
= Fget_buffer_xwidgets (buffer
); CONSP (tail
); tail
= XCDR (tail
))
1860 xwidget
= XCAR (tail
);
1861 Vxwidget_list
= Fdelq (xwidget
, Vxwidget_list
);
1862 /* TODO free the GTK things in xw */
1864 CHECK_XWIDGET (xwidget
);
1865 struct xwidget
*xw
= XXWIDGET (xwidget
);
1866 if (xw
->widget_osr
&& xw
->widgetwindow_osr
)
1868 gtk_widget_destroy(xw
->widget_osr
);
1869 gtk_widget_destroy(xw
->widgetwindow_osr
);
1875 #endif /* HAVE_XWIDGETS */