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>
99 /* Convert STRING, a string constant, to a type acceptable as glib data.
102 gstr (char const *string
)
104 return (char *) string
;
108 //TODO embryo of lisp allocators for xwidgets
109 //TODO xwidget* should be Lisp_xwidget*
110 static struct xwidget
*
111 allocate_xwidget (void)
113 return ALLOCATE_PSEUDOVECTOR (struct xwidget
, height
, PVEC_XWIDGET
);
116 //TODO xwidget_view* should be Lisp_xwidget_view*
117 static struct xwidget_view
*
118 allocate_xwidget_view (void)
120 return ALLOCATE_PSEUDOVECTOR (struct xwidget_view
, redisplayed
,
124 #define XSETXWIDGET(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET))
125 #define XSETXWIDGET_VIEW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_XWIDGET_VIEW))
127 struct xwidget_view
*xwidget_view_lookup (struct xwidget
*xw
,
129 Lisp_Object
xwidget_spec_value (Lisp_Object spec
, Lisp_Object key
,
131 gboolean
offscreen_damage_event (GtkWidget
* widget
, GdkEvent
* event
,
133 void webkit_osr_document_load_finished_callback (WebKitWebView
*
135 WebKitWebFrame
* arg1
,
137 gboolean
webkit_osr_download_callback (WebKitWebView
* webkitwebview
,
138 WebKitDownload
* arg1
, gpointer data
);
141 webkit_osr_mime_type_policy_typedecision_requested_callback (WebKitWebView
*
148 WebKitWebPolicyDecision
155 webkit_osr_new_window_policy_decision_requested_callback (WebKitWebView
*
161 WebKitWebNavigationAction
163 WebKitWebPolicyDecision
169 webkit_osr_navigation_policy_decision_requested_callback (WebKitWebView
*
175 WebKitWebNavigationAction
177 WebKitWebPolicyDecision
181 static GtkWidget
*xwgir_create (char *, char *);
184 static void send_xembed_ready_event (struct xwidget
*xw
, int xembedid
);
185 DEFUN ("make-xwidget", Fmake_xwidget
, Smake_xwidget
, 7, 8, 0, doc
: /* Make an xwidget from BEG to END of TYPE.
187 If BUFFER is nil it uses the current buffer. If BUFFER is a string and
188 no such buffer exists, it is created.
190 TYPE is a symbol which can take one of the following values:
198 )(Lisp_Object beg
, Lisp_Object end
,
201 Lisp_Object width
, Lisp_Object height
, Lisp_Object data
, Lisp_Object buffer
)
203 //should work a bit like "make-button"(make-button BEG END &rest PROPERTIES)
204 // arg "type" and fwd should be keyword args eventually
205 //(make-xwidget 3 3 'button "oei" 31 31 nil)
206 //(xwidget-info (car xwidget-list))
207 struct xwidget
*xw
= allocate_xwidget ();
212 buffer
= Fcurrent_buffer (); // no need to gcpro because Fcurrent_buffer doesn't call Feval/eval_sub.
214 buffer
= Fget_buffer_create (buffer
);
217 xw
->height
= XFASTINT (height
);
218 xw
->width
= XFASTINT (width
);
219 xw
->kill_without_query
= 0;
220 XSETXWIDGET (val
, xw
); // set the vectorlike_header of VAL with the correct value
221 Vxwidget_list
= Fcons (val
, Vxwidget_list
);
222 xw
->widgetwindow_osr
= NULL
;
223 xw
->widget_osr
= NULL
;
229 #ifdef HAVE_WEBKIT_OSR
230 /* DIY mvc. widget is rendered offscreen,
231 later bitmap copied to the views.
233 if (EQ (xw
->type
, Qwebkit_osr
) ||
234 EQ (xw
->type
, Qsocket_osr
) || (!NILP (Fget (xw
->type
, QCxwgir_class
))))
237 xw
->widgetwindow_osr
= gtk_offscreen_window_new ();
238 gtk_window_resize (GTK_WINDOW (xw
->widgetwindow_osr
), xw
->width
,
240 xw
->widgetscrolledwindow_osr
= NULL
; //webkit osr is the only scrolled component atm
242 if (EQ (xw
->type
, Qwebkit_osr
))
244 xw
->widgetscrolledwindow_osr
= gtk_scrolled_window_new (NULL
, NULL
);
245 gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW
247 widgetscrolledwindow_osr
),
249 gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW
251 widgetscrolledwindow_osr
),
253 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW
254 (xw
->widgetscrolledwindow_osr
),
258 xw
->widget_osr
= webkit_web_view_new ();
259 gtk_container_add (GTK_CONTAINER (xw
->widgetscrolledwindow_osr
),
260 GTK_WIDGET (WEBKIT_WEB_VIEW (xw
->widget_osr
)));
262 if (EQ (xw
->type
, Qsocket_osr
))
263 xw
->widget_osr
= gtk_socket_new ();
264 if (!NILP (Fget (xw
->type
, QCxwgir_class
)))
266 xwgir_create (SSDATA (Fcar (Fcdr (Fget (xw
->type
, QCxwgir_class
)))),
267 SSDATA (Fcar (Fget (xw
->type
, QCxwgir_class
))));
269 gtk_widget_set_size_request (GTK_WIDGET (xw
->widget_osr
), xw
->width
,
272 if (EQ (xw
->type
, Qwebkit_osr
))
274 gtk_container_add (GTK_CONTAINER (xw
->widgetwindow_osr
),
275 xw
->widgetscrolledwindow_osr
);
279 gtk_container_add (GTK_CONTAINER (xw
->widgetwindow_osr
),
283 gtk_widget_show (xw
->widget_osr
);
284 gtk_widget_show (xw
->widgetwindow_osr
);
285 gtk_widget_show (xw
->widgetscrolledwindow_osr
);
287 /* store some xwidget data in the gtk widgets for convenient retrieval in the event handlers. */
288 g_object_set_data (G_OBJECT (xw
->widget_osr
), XG_XWIDGET
,
290 g_object_set_data (G_OBJECT (xw
->widgetwindow_osr
), XG_XWIDGET
,
294 if (EQ (xw
->type
, Qwebkit_osr
))
296 g_signal_connect (G_OBJECT (xw
->widget_osr
),
297 "document-load-finished",
299 (webkit_osr_document_load_finished_callback
), xw
);
301 g_signal_connect (G_OBJECT (xw
->widget_osr
),
302 "download-requested",
303 G_CALLBACK (webkit_osr_download_callback
), xw
);
305 g_signal_connect (G_OBJECT (xw
->widget_osr
),
306 "mime-type-policy-decision-requested",
308 (webkit_osr_mime_type_policy_typedecision_requested_callback
),
311 g_signal_connect (G_OBJECT (xw
->widget_osr
),
312 "new-window-policy-decision-requested",
314 (webkit_osr_new_window_policy_decision_requested_callback
),
317 g_signal_connect (G_OBJECT (xw
->widget_osr
),
318 "navigation-policy-decision-requested",
320 (webkit_osr_navigation_policy_decision_requested_callback
),
324 if (EQ (xw
->type
, Qsocket_osr
))
326 send_xembed_ready_event (xw
,
327 gtk_socket_get_id (GTK_SOCKET
329 //gtk_widget_realize(xw->widget);
336 #endif /* HAVE_WEBKIT_OSR */
341 DEFUN ("get-buffer-xwidgets", Fget_buffer_xwidgets
, Sget_buffer_xwidgets
, 1, 1, 0, doc
:/* Return a list of xwidgets associated with BUFFER.
342 BUFFER may be a buffer or the name of one.
347 Lisp_Object xw
, tail
, xw_list
;
351 buffer
= Fget_buffer (buffer
);
357 for (tail
= Vxwidget_list
; CONSP (tail
); tail
= XCDR (tail
))
360 if (XWIDGETP (xw
) && EQ (Fxwidget_buffer (xw
), buffer
))
361 xw_list
= Fcons (xw
, xw_list
);
367 xwidget_hidden (struct xwidget_view
*xv
)
374 buttonclick_handler (GtkWidget
* widget
, gpointer data
)
376 Lisp_Object xwidget_view
, xwidget
;
377 XSETXWIDGET_VIEW (xwidget_view
, (struct xwidget_view
*) data
);
378 xwidget
= Fxwidget_view_model (xwidget_view
);
380 struct input_event event
;
381 Lisp_Object frame
= Fwindow_frame (Fxwidget_view_window (xwidget_view
));
383 event
.kind
= XWIDGET_EVENT
;
385 event
.frame_or_window
= frame
;
388 event
.arg
= Fcons (xwidget
, event
.arg
);
389 event
.arg
= Fcons (intern ("buttonclick"), event
.arg
);
391 kbd_buffer_store_event (&event
);
396 send_xembed_ready_event (struct xwidget
*xw
, int xembedid
)
399 XSETXWIDGET (xw_lo
, xw
);
400 struct input_event event
;
402 event
.kind
= XWIDGET_EVENT
;
403 event
.frame_or_window
= Qnil
; //frame; //how to get the frame here? //TODO i store it in the xwidget now
406 event
.arg
= Fcons (make_number (xembedid
), event
.arg
);
407 event
.arg
= Fcons (xw_lo
, event
.arg
);
408 event
.arg
= Fcons (intern ("xembed-ready"), event
.arg
);
411 kbd_buffer_store_event (&event
);
416 xwidget_show_view (struct xwidget_view
*xv
)
419 gtk_widget_show (xv
->widgetwindow
);
420 gtk_fixed_move (GTK_FIXED (xv
->emacswindow
), xv
->widgetwindow
, xv
->x
+ xv
->clip_left
, xv
->y
+ xv
->clip_top
); //TODO refactor
424 /* hide an xvidget view */
426 xwidget_hide_view (struct xwidget_view
*xv
)
429 //gtk_widget_hide(xw->widgetwindow);
430 gtk_fixed_move (GTK_FIXED (xv
->emacswindow
), xv
->widgetwindow
,
436 xwidget_plug_added (GtkSocket
* socket
, gpointer user_data
)
438 //hmm this doesnt seem to get called for foreign windows
439 printf ("xwidget_plug_added\n");
443 xwidget_plug_removed (GtkSocket
* socket
, gpointer user_data
)
445 printf ("xwidget_plug_removed\n");
446 return TRUE
; /* dont run the default handler because that kills the socket and we want to reuse it */
451 xwidget_slider_changed (GtkRange
* range
, gpointer user_data
)
453 //slider value changed. change value of siblings
454 //correspondingly. but remember that changing value will again
457 //TODO MVC view storage wont be an array futureish so the loop needs to change eventually
458 //TODO MVC it would be nice if this code could be reusable but, alas, C is not a functional language
460 // - the type of the controllers value (double, boolean etc)
461 // - the getter and setter (but they can be func pointers)
462 // a behemoth macro is always an option.
463 double v
= gtk_range_get_value (range
);
464 struct xwidget_view
*xvp
=
465 g_object_get_data (G_OBJECT (range
), XG_XWIDGET_VIEW
);
466 struct xwidget_view
*xv
;
468 printf ("slider changed val:%f\n", v
);
470 for (Lisp_Object tail
= Vxwidget_view_list
; CONSP (tail
);
473 if (XWIDGET_VIEW_P (XCAR (tail
)))
475 xv
= XXWIDGET_VIEW (XCAR (tail
));
476 if (EQ (xvp
->model
, xv
->model
))
478 //block sibling views signal handlers
479 g_signal_handler_block (xv
->widget
, xv
->handler_id
);
481 //set values of sibling views and unblock
482 gtk_range_set_value (GTK_RANGE (xv
->widget
), v
);
483 g_signal_handler_unblock (xv
->widget
, xv
->handler_id
);
490 /* when the off-screen webkit master view changes this signal is called.
491 it copies the bitmap from the off-screen webkit instance */
493 offscreen_damage_event (GtkWidget
* widget
, GdkEvent
* event
,
496 //queue a redraw of onscreen widget
497 if (GTK_IS_WIDGET (xv_widget
))
498 gtk_widget_queue_draw (GTK_WIDGET (xv_widget
));
501 ("Warning, offscreen_damage_event received invalid xv pointer:%p\n",
509 store_xwidget_event_string (struct xwidget
*xw
, const char *eventname
,
510 const char *eventstr
)
513 struct input_event event
;
515 XSETXWIDGET (xwl
, xw
);
517 event
.kind
= XWIDGET_EVENT
;
518 event
.frame_or_window
= Qnil
; //frame; //how to get the frame here? //TODO i store it in the xwidget now
521 event
.arg
= Fcons (build_string (eventstr
), event
.arg
); //string so dont intern
522 event
.arg
= Fcons (xwl
, event
.arg
); //TODO
523 event
.arg
= Fcons (intern (eventname
), event
.arg
); //interning should be ok
524 kbd_buffer_store_event (&event
);
528 //TODO deprecated, use load-status
530 webkit_osr_document_load_finished_callback (WebKitWebView
* webkitwebview
,
531 WebKitWebFrame
* arg1
,
534 //TODO this event sending code should be refactored
535 // struct xwidget *xw = (struct xwidget *) data;
537 (struct xwidget
*) g_object_get_data (G_OBJECT (webkitwebview
),
539 printf ("webkit finished loading\n");
541 store_xwidget_event_string (xw
, "document-load-finished", "");
545 webkit_osr_download_callback (WebKitWebView
* webkitwebview
,
546 WebKitDownload
* arg1
, gpointer data
)
549 (struct xwidget
*) g_object_get_data (G_OBJECT (webkitwebview
),
551 printf ("download requested %s\n", webkit_download_get_uri (arg1
));
554 printf ("webkit finished loading\n");
556 store_xwidget_event_string (xw
, "download-requested",
557 webkit_download_get_uri (arg1
));
563 webkit_osr_mime_type_policy_typedecision_requested_callback (WebKitWebView
*
570 WebKitWebPolicyDecision
576 printf ("mime policy requested\n");
577 // this function makes webkit send a download signal for all unknown mime types
578 // TODO defer the decision to lisp, so that its possible to make Emacs handle text mime for instance
579 if (!webkit_web_view_can_show_mime_type (webView
, mimetype
))
581 webkit_web_policy_decision_download (policy_decision
);
592 webkit_osr_new_window_policy_decision_requested_callback (WebKitWebView
*
598 WebKitWebNavigationAction
600 WebKitWebPolicyDecision
605 (struct xwidget
*) g_object_get_data (G_OBJECT (webView
), XG_XWIDGET
);
606 printf ("webkit_osr_new_window_policy_decision_requested_callback %s\n",
607 webkit_web_navigation_action_get_original_uri (navigation_action
));
609 store_xwidget_event_string (xw
, "new-window-policy-decision-requested",
610 webkit_web_navigation_action_get_original_uri
611 (navigation_action
));
616 webkit_osr_navigation_policy_decision_requested_callback (WebKitWebView
*
622 WebKitWebNavigationAction
624 WebKitWebPolicyDecision
629 (struct xwidget
*) g_object_get_data (G_OBJECT (webView
), XG_XWIDGET
);
630 printf ("webkit_osr_navigation_policy_decision_requested_callback %s\n",
631 webkit_web_navigation_action_get_original_uri (navigation_action
));
632 store_xwidget_event_string (xw
, "navigation-policy-decision-requested",
633 webkit_web_navigation_action_get_original_uri
634 (navigation_action
));
638 //for gtk3 offscreen rendered widgets
640 xwidget_osr_draw_callback (GtkWidget
* widget
, cairo_t
* cr
, gpointer data
)
643 (struct xwidget
*) g_object_get_data (G_OBJECT (widget
), XG_XWIDGET
);
644 struct xwidget_view
*xv
=
645 (struct xwidget_view
*) g_object_get_data (G_OBJECT (widget
),
648 cairo_rectangle (cr
, 0, 0, xv
->clip_right
, xv
->clip_bottom
); //xw->width, xw->height);
652 if (xw
->widgetscrolledwindow_osr
!= NULL
)
653 gtk_widget_draw (xw
->widgetscrolledwindow_osr
, cr
);
655 gtk_widget_draw (xw
->widget_osr
, cr
);
659 GtkWidget
*xwgir_create_debug
;
664 xwidget_osr_event_forward (GtkWidget
* widget
,
665 GdkEvent
* event
, gpointer user_data
)
667 /* copy events that arrive at the outer widget to the offscreen widget */
669 (struct xwidget
*) g_object_get_data (G_OBJECT (widget
), XG_XWIDGET
);
670 GdkEvent
*eventcopy
= gdk_event_copy (event
);
671 eventcopy
->any
.window
= gtk_widget_get_window (xw
->widget_osr
); // works
673 /* printf("xwidget_osr_event_forward redirect event to window:%d\n", ((GdkEventAny*)eventcopy)->window); */
674 /* printf("A type:%d x:%f y:%f \n", event->type, event->button.x, event->button.y); */
675 /* printf("B type:%d x:%f y:%f \n", eventcopy->type, eventcopy->button.x, eventcopy->button.y); */
676 //gtk_button_get_event_window(xwgir_create_debug);
677 gtk_main_do_event (eventcopy
); //TODO this will leak events. they should be deallocated later, perhaps in xwgir_event_callback
678 return TRUE
; //dont propagate this event furter
681 GIRepository
*girepository
;
683 DEFUN ("xwgir-require-namespace", Fxwgir_require_namespace
, Sxwgir_require_namespace
, 2, 2, 0, doc
: /* Require a GObject Introspection namespace.
684 This must be done for all namespaces we want to use, before using other xwgir functions. */ )
685 (Lisp_Object lnamespace
, Lisp_Object lnamespace_version
)
687 const gchar
*namespace = SSDATA (lnamespace
);
688 const gchar
*namespace_version
= SSDATA (lnamespace_version
);
689 GError
*error
= NULL
;
691 girepository
= g_irepository_get_default ();
692 g_irepository_require (girepository
, namespace, namespace_version
, 0,
696 g_error ("ERROR: %s\n", error
->message
);
703 xwgir_create (char *class, char *namespace)
705 //TODO this is more or less the same as xwgir-call-method, so should be refactored
706 //create a gtk widget, given its name
707 //find the constructor
709 //also figure out how to pass args
711 GIArgument return_value
;
713 GIObjectInfo
*obj_info
=
714 g_irepository_find_by_name (girepository
, namespace, class);
715 GIFunctionInfo
*f_info
= g_object_info_find_method (obj_info
, "new");
716 g_function_info_invoke (f_info
, NULL
, 0, NULL
, 0, &return_value
, NULL
);
717 xwgir_create_debug
= return_value
.v_pointer
;
718 return return_value
.v_pointer
;
723 xwgir_convert_lisp_to_gir_arg (GIArgument
* giarg
,
724 GIArgInfo
* arginfo
, Lisp_Object lisparg
)
728 tag
= g_type_info_get_tag (g_arg_info_get_type (arginfo
));
732 case GI_TYPE_TAG_BOOLEAN
:
733 giarg
->v_boolean
= XFASTINT (lisparg
);
735 case GI_TYPE_TAG_INT8
:
736 giarg
->v_int8
= XFASTINT (lisparg
);
738 case GI_TYPE_TAG_UINT8
:
739 giarg
->v_uint8
= XFASTINT (lisparg
);
741 case GI_TYPE_TAG_INT16
:
742 giarg
->v_int16
= XFASTINT (lisparg
);
744 case GI_TYPE_TAG_UINT16
:
745 giarg
->v_uint16
= XFASTINT (lisparg
);
747 case GI_TYPE_TAG_INT32
:
748 giarg
->v_int32
= XFASTINT (lisparg
);
750 case GI_TYPE_TAG_UINT32
:
751 giarg
->v_uint32
= XFASTINT (lisparg
);
754 case GI_TYPE_TAG_INT64
:
755 giarg
->v_int64
= XFASTINT (lisparg
);
757 case GI_TYPE_TAG_UINT64
:
758 giarg
->v_uint64
= XFASTINT (lisparg
);
762 case GI_TYPE_TAG_FLOAT
:
763 giarg
->v_float
= XFLOAT_DATA (lisparg
);
766 case GI_TYPE_TAG_DOUBLE
:
767 giarg
->v_double
= XFLOAT_DATA (lisparg
);
770 case GI_TYPE_TAG_UTF8
:
771 case GI_TYPE_TAG_FILENAME
:
772 //giarg->v_string = SDATA(lisparg);
773 giarg
->v_pointer
= SDATA (lisparg
);
776 case GI_TYPE_TAG_ARRAY
:
777 case GI_TYPE_TAG_GLIST
:
778 case GI_TYPE_TAG_GSLIST
:
779 case GI_TYPE_TAG_GHASH
:
780 case GI_TYPE_TAG_ERROR
:
781 case GI_TYPE_TAG_INTERFACE
:
782 case GI_TYPE_TAG_VOID
:
783 case GI_TYPE_TAG_UNICHAR
:
784 case GI_TYPE_TAG_GTYPE
:
785 //?? i dont know how to handle these yet TODO
786 printf ("failed in my lisp to gir arg conversion duties. sob!\n");
793 DEFUN ("xwgir-xwidget-call-method", Fxwgir_xwidget_call_method
, Sxwgir_xwidget_call_method
, 3, 3, 0, doc
: /* Call Xwidget object method using GObject Introspection.
794 XWIDGET is the xwidget instance to act upon.
795 METHOD is the Gobject intrsopsection method name.
796 ARGUMENTS is a list of arguments for the call. They will be converted to GObject types from Lisp types.
798 (Lisp_Object xwidget
, Lisp_Object method
, Lisp_Object arguments
)
800 CHECK_XWIDGET (xwidget
);
801 GError
*error
= NULL
;
802 GIArgument return_value
;
803 GIArgument in_args
[20];
809 printf ("ERROR xwidget nil\n");
812 xw
= XXWIDGET (xwidget
);
814 printf ("ERROR xw is 0\n");
815 char *namespace = SSDATA (Fcar (Fget (xw
->type
, QCxwgir_class
)));
816 //we need the concrete widget, which happens in 2 ways depending on OSR or not TODO
817 GtkWidget
*widget
= NULL
;
818 if (NULL
== xw
->widget_osr
)
821 xwidget_view_lookup (xw
,
822 XWINDOW (FRAME_SELECTED_WINDOW
823 (SELECTED_FRAME ())))->widget
;
827 widget
= xw
->widget_osr
;
830 //char* class = SDATA(SYMBOL_NAME(xw->type)); //this works but is unflexible
831 //figure out the class from the widget instead
832 /* printf("type class: %s %s\n", G_OBJECT_TYPE_NAME(widget), G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(widget))); */
833 /* char* class = G_OBJECT_TYPE_NAME(widget); //gives "GtkButton"(I want "Button") */
834 /* class += strlen(namespace); //TODO check for corresponding api method. but this seems to work. */
836 char *class = SSDATA (Fcar (Fcdr (Fget (xw
->type
, QCxwgir_class
))));
838 GIObjectInfo
*obj_info
=
839 g_irepository_find_by_name (girepository
, namespace, class);
840 GIFunctionInfo
*f_info
=
841 g_object_info_find_method (obj_info
, SSDATA (method
));
843 //loop over args, convert from lisp to primitive type, given arg introspection data
844 //TODO g_callable_info_get_n_args(f_info) should match
845 int argscount
= XFASTINT (Flength (arguments
));
846 if (argscount
!= g_callable_info_get_n_args (f_info
))
848 printf ("xwgir call method arg count doesn match! \n");
853 for (i
= 1; i
< argscount
+ 1; ++i
)
855 XSETFASTINT (n
, i
- 1);
856 xwgir_convert_lisp_to_gir_arg (&in_args
[i
],
857 g_callable_info_get_arg (f_info
, i
- 1),
858 Fnth (n
, arguments
));
861 in_args
[0].v_pointer
= widget
;
862 if (g_function_info_invoke (f_info
,
863 in_args
, argscount
+ 1,
864 NULL
, 0, &return_value
, &error
))
866 //g_error("ERROR: %s\n", error->message);
867 printf ("invokation error\n");
874 offscreen_pick_embedded_child (GdkWindow
* window
,
875 double x
, double y
, gpointer
* data
)
877 //in this simple case we assume the window contains a single widget. easy.
878 //but then we get the problem that the widget cant be embedded in several windows
879 return gtk_widget_get_window (GTK_WIDGET (data
));
883 offscreen_to_embedder (GdkWindow
* window
,
887 gpointer embedder_y
, gpointer data
)
889 *(gdouble
*) embedder_x
= offscreen_x
;
890 *(gdouble
*) embedder_y
= offscreen_y
;
894 offscreen_from_embedder (GdkWindow
* window
,
897 gpointer offscreen_x
,
898 gpointer offscreen_y
, gpointer user_data
)
900 *(gdouble
*) offscreen_x
= embedder_x
;
901 *(gdouble
*) offscreen_y
= embedder_y
;
905 xwidget_osr_event_set_embedder (GtkWidget
* widget
,
906 GdkEvent
* event
, gpointer data
)
908 struct xwidget_view
*xv
= (struct xwidget_view
*) data
;
909 struct xwidget
*xww
= XXWIDGET (xv
->model
);
910 printf ("gdk_offscreen_window_set_embedder %d %d\n",
911 GDK_IS_WINDOW (gtk_widget_get_window (xww
->widget_osr
)),
912 GDK_IS_WINDOW (gtk_widget_get_window (GTK_WIDGET (xv
->widget
))));
913 gdk_offscreen_window_set_embedder (gtk_widget_get_window
914 (xww
->widgetwindow_osr
),
915 gtk_widget_get_window (xv
->widget
));
920 /* initializes and does initial placement of an xwidget view on screen */
921 static struct xwidget_view
*
922 xwidget_init_view (struct xwidget
*xww
, struct glyph_string
*s
, int x
, int y
)
924 struct xwidget_view
*xv
= allocate_xwidget_view ();
927 XSETXWIDGET_VIEW (val
, xv
);
928 Vxwidget_view_list
= Fcons (val
, Vxwidget_view_list
);
930 XSETWINDOW (xv
->w
, s
->w
);
931 XSETXWIDGET (xv
->model
, xww
);
934 if (EQ (xww
->type
, Qbutton
))
936 xv
->widget
= gtk_button_new_with_label (SSDATA (xww
->title
));
937 g_signal_connect (G_OBJECT (xv
->widget
), "clicked", G_CALLBACK (buttonclick_handler
), xv
); // the view rather than the model
939 else if (EQ (xww
->type
, Qtoggle
))
941 xv
->widget
= gtk_toggle_button_new_with_label (SSDATA (xww
->title
));
942 //xv->widget = gtk_entry_new ();//temp hack to experiment with key propagation TODO entry widget is useful for testing
944 else if (EQ (xww
->type
, Qsocket
))
946 xv
->widget
= gtk_socket_new ();
947 g_signal_connect_after (xv
->widget
, "plug-added",
948 G_CALLBACK (xwidget_plug_added
),
949 gstr ("plug added"));
950 g_signal_connect_after (xv
->widget
, "plug-removed",
951 G_CALLBACK (xwidget_plug_removed
),
952 gstr ("plug removed"));
953 //TODO these doesnt help
954 gtk_widget_add_events (xv
->widget
, GDK_KEY_PRESS
);
955 gtk_widget_add_events (xv
->widget
, GDK_KEY_RELEASE
);
957 else if (EQ (xww
->type
, Qslider
))
960 //gtk_hscale_new (GTK_ADJUSTMENT(gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 10.0, 10.0)));
961 gtk_hscale_new_with_range (0.0, 100.0, 10.0);
962 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
964 g_signal_connect_after (xv
->widget
, "value-changed",
965 G_CALLBACK (xwidget_slider_changed
),
966 gstr ("slider changed"));
968 else if (EQ (xww
->type
, Qcairo
))
971 //uhm cairo is differentish in gtk 3.
972 //gdk_cairo_create (gtk_widget_get_window (FRAME_GTK_WIDGET (s->f)));
973 xv
->widget
= gtk_drawing_area_new ();
974 g_signal_connect (G_OBJECT (xv
->widget
), "draw",
975 G_CALLBACK (xwidget_osr_draw_callback
), NULL
);
978 else if (EQ (xww
->type
, Qwebkit_osr
) || EQ (xww
->type
, Qsocket_osr
) || (!NILP (Fget (xww
->type
, QCxwgir_class
)))) //xwgir widgets are OSR
980 printf ("osr init:%s\n", SDATA (SYMBOL_NAME (xww
->type
)));
981 xv
->widget
= gtk_drawing_area_new ();
982 gtk_widget_set_app_paintable (xv
->widget
, TRUE
); //because expose event handling
983 gtk_widget_add_events (xv
->widget
, GDK_ALL_EVENTS_MASK
);
985 /* Draw the view on damage-event */
986 g_signal_connect (G_OBJECT (xww
->widgetwindow_osr
), "damage-event",
987 G_CALLBACK (offscreen_damage_event
), xv
->widget
);
989 if (EQ (xww
->type
, Qwebkit_osr
))
992 /* //forward events. this isnt compatible with the set_embedded strategy */
993 g_signal_connect (G_OBJECT (xv
->widget
), "button-press-event",
994 G_CALLBACK (xwidget_osr_event_forward
), NULL
);
995 g_signal_connect (G_OBJECT (xv
->widget
), "button-release-event",
996 G_CALLBACK (xwidget_osr_event_forward
), NULL
);
997 g_signal_connect (G_OBJECT (xv
->widget
), "motion-notify-event",
998 G_CALLBACK (xwidget_osr_event_forward
), NULL
);
1002 //xwgir debug , orthogonal to forwarding
1003 g_signal_connect (G_OBJECT (xv
->widget
), "enter-notify-event",
1004 G_CALLBACK (xwidget_osr_event_set_embedder
), xv
);
1008 g_signal_connect (G_OBJECT (xv
->widget
), "draw",
1009 G_CALLBACK (xwidget_osr_draw_callback
), NULL
);
1014 //widget realization
1015 //make container widget 1st, and put the actual widget inside the container
1016 //later, drawing should crop container window if necessary to handle case where xwidget
1017 //is partially obscured by other emacs windows
1018 //other containers than gtk_fixed where explored, but gtk_fixed had the most predictable behaviour so far.
1019 xv
->emacswindow
= FRAME_GTK_WIDGET (s
->f
);
1020 xv
->widgetwindow
= gtk_fixed_new ();
1021 gtk_widget_set_has_window (xv
->widgetwindow
, TRUE
);
1022 gtk_container_add (GTK_CONTAINER (xv
->widgetwindow
), xv
->widget
);
1024 //store some xwidget data in the gtk widgets
1025 g_object_set_data (G_OBJECT (xv
->widget
), XG_FRAME_DATA
, (gpointer
) (s
->f
)); //the emacs frame
1026 g_object_set_data (G_OBJECT (xv
->widget
), XG_XWIDGET
, (gpointer
) (xww
)); //the xwidget
1027 g_object_set_data (G_OBJECT (xv
->widget
), XG_XWIDGET_VIEW
, (gpointer
) (xv
)); //the xwidget
1028 g_object_set_data (G_OBJECT (xv
->widgetwindow
), XG_XWIDGET
, (gpointer
) (xww
)); //the xwidget window
1029 g_object_set_data (G_OBJECT (xv
->widgetwindow
), XG_XWIDGET_VIEW
, (gpointer
) (xv
)); //the xwidget window
1032 gtk_widget_set_size_request (GTK_WIDGET (xv
->widget
), xww
->width
,
1034 gtk_widget_set_size_request (xv
->widgetwindow
, xww
->width
, xww
->height
);
1035 gtk_fixed_put (GTK_FIXED (FRAME_GTK_WIDGET (s
->f
)), xv
->widgetwindow
, x
, y
);
1038 gtk_widget_show_all (xv
->widgetwindow
);
1042 //widgettype specific initialization only possible after realization
1043 if (EQ (xww
->type
, Qsocket
))
1045 printf ("xwid:%p socket id:%p %p\n",
1047 (void *) gtk_socket_get_id (GTK_SOCKET (xv
->widget
)),
1048 (void *) gtk_socket_get_id (GTK_SOCKET (xv
->widget
)));
1049 send_xembed_ready_event (xww
,
1050 gtk_socket_get_id (GTK_SOCKET (xv
->widget
)));
1051 //gtk_widget_realize(xw->widget);
1054 //////////////////////////////////////////////////////////////
1056 if ( //EQ(xww->type, Qwebkit_osr)|| //TODO should be able to choose compile time which method to use with webkit
1057 EQ (xww
->type
, Qsocket_osr
) || (!NILP (Fget (xww
->type
, QCxwgir_class
)))) //xwgir widgets are OSR
1059 printf ("gdk_offscreen_window_set_embedder %d %d\n",
1060 GDK_IS_WINDOW (gtk_widget_get_window (xww
->widget_osr
)),
1061 GDK_IS_WINDOW (gtk_widget_get_window
1062 (GTK_WIDGET (xv
->widget
))));
1063 // set_embedder needs to be called after xv->widget realization
1064 gdk_offscreen_window_set_embedder (gtk_widget_get_window
1065 (xww
->widgetwindow_osr
),
1066 gtk_widget_get_window (xv
->widget
));
1067 g_signal_connect (gtk_widget_get_window (xv
->widget
),
1068 "pick-embedded-child",
1069 G_CALLBACK (offscreen_pick_embedded_child
),
1070 xww
->widgetwindow_osr
);
1072 g_signal_connect (gtk_widget_get_window (xww
->widgetwindow_osr
),
1073 "from-embedder", G_CALLBACK (offscreen_from_embedder
),
1075 g_signal_connect (gtk_widget_get_window (xww
->widgetwindow_osr
),
1076 "to-embedder", G_CALLBACK (offscreen_to_embedder
),
1079 ////////////////////////////////////////
1086 x_draw_xwidget_glyph_string (struct glyph_string
*s
)
1089 this method is called by the redisplay engine and places the xwidget on screen.
1090 moving and clipping is done here. also view init.
1093 struct xwidget
*xww
= s
->xwidget
;
1094 struct xwidget_view
*xv
= xwidget_view_lookup (xww
, s
->w
);
1101 int y
= s
->y
+ (s
->height
/ 2) - (xww
->height
/ 2);
1104 /* We do it here in the display loop because there is no other
1105 time to know things like window placement etc.
1107 xv
= xwidget_init_view (xww
, s
, x
, y
);
1109 //calculate clipping, which is used for all manner of onscreen xwidget views
1110 //each widget border can get clipped by other emacs objects so there are four clipping variables
1113 WINDOW_RIGHT_EDGE_X (s
->w
) - x
-
1114 WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s
->w
) -
1115 WINDOW_RIGHT_FRINGE_WIDTH (s
->w
));
1118 WINDOW_LEFT_EDGE_X (s
->w
) - x
+
1119 WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (s
->w
) +
1120 WINDOW_LEFT_FRINGE_WIDTH (s
->w
));
1124 WINDOW_BOTTOM_EDGE_Y (s
->w
) - WINDOW_MODE_LINE_HEIGHT (s
->w
) - y
);
1125 clip_top
= max (0, WINDOW_TOP_EDGE_Y (s
->w
) - y
);
1127 //we are conserned with movement of the onscreen area. the area might sit still when the widget actually moves
1128 //this happens when an emacs window border moves across a widget window
1129 //so, if any corner of the outer widget clippng window moves, that counts as movement here, even
1130 //if it looks like no movement happens because the widget sits still inside the clipping area.
1131 //the widget can also move inside the clipping area, which happens later
1132 moved
= (xv
->x
+ xv
->clip_left
!= x
+ clip_left
)
1133 || ((xv
->y
+ xv
->clip_top
) != (y
+ clip_top
));
1136 if (moved
) //has it moved?
1138 if (1) //!xwidget_hidden(xv)) //hidden equals not being seen during redisplay
1140 //TODO should be possible to use xwidget_show_view here
1141 gtk_fixed_move (GTK_FIXED (FRAME_GTK_WIDGET (s
->f
)),
1142 xv
->widgetwindow
, x
+ clip_left
, y
+ clip_top
);
1145 //clip the widget window if some parts happen to be outside drawable area
1146 //an emacs window is not a gtk window, a gtk window covers the entire frame
1147 //cliping might have changed even if we havent actualy moved, we try figure out when we need to reclip for real
1148 if ((xv
->clip_right
!= clip_right
)
1149 || (xv
->clip_bottom
!= clip_bottom
)
1150 || (xv
->clip_top
!= clip_top
) || (xv
->clip_left
!= clip_left
))
1152 gtk_widget_set_size_request (xv
->widgetwindow
, clip_right
+ clip_left
,
1153 clip_bottom
+ clip_top
);
1154 gtk_fixed_move (GTK_FIXED (xv
->widgetwindow
), xv
->widget
, -clip_left
,
1157 xv
->clip_right
= clip_right
;
1158 xv
->clip_bottom
= clip_bottom
;
1159 xv
->clip_top
= clip_top
;
1160 xv
->clip_left
= clip_left
;
1162 //if emacs wants to repaint the area where the widget lives, queue a redraw
1163 //TODO it seems its possible to get out of sync with emacs redraws so emacs bg sometimes shows up instead of xwidget
1164 //its just a visual glitch though
1165 if (!xwidget_hidden (xv
))
1167 gtk_widget_queue_draw (xv
->widgetwindow
);
1168 gtk_widget_queue_draw (xv
->widget
);
1173 #ifdef HAVE_WEBKIT_OSR
1175 //FUGLY macro that checks WEBKIT_IS_WEB_VIEW(xw->widget_osr) first
1176 #define WEBKIT_FN_INIT() \
1177 struct xwidget* xw; \
1178 CHECK_XWIDGET (xwidget); \
1179 if(NILP (xwidget)) {printf("ERROR xwidget nil\n"); return Qnil;}; \
1180 xw = XXWIDGET(xwidget); \
1181 if(NULL == xw) printf("ERROR xw is 0\n"); \
1182 if((NULL == xw->widget_osr) || !WEBKIT_IS_WEB_VIEW(xw->widget_osr)){ \
1183 printf("ERROR xw->widget_osr does not hold a webkit instance\n");\
1188 DEFUN ("xwidget-webkit-goto-uri", Fxwidget_webkit_goto_uri
, Sxwidget_webkit_goto_uri
, 2, 2, 0, doc
: /* Make the webkit instance referenced by XWIDGET browse URI. */
1190 (Lisp_Object xwidget
, Lisp_Object uri
)
1194 webkit_web_view_load_uri (WEBKIT_WEB_VIEW (xw
->widget_osr
), SSDATA (uri
));
1199 DEFUN ("xwidget-webkit-execute-script", Fxwidget_webkit_execute_script
, Sxwidget_webkit_execute_script
, 2, 2, 0, doc
: /* webkit exec js. */
1201 (Lisp_Object xwidget
, Lisp_Object script
)
1204 CHECK_STRING (script
);
1205 webkit_web_view_execute_script (WEBKIT_WEB_VIEW (xw
->widget_osr
),
1210 DEFUN ("xwidget-webkit-get-title", Fxwidget_webkit_get_title
, Sxwidget_webkit_get_title
, 1, 1, 0, doc
: /* Get the title from the Webkit instance in XWIDGET.
1211 This can be used to work around the lack of a return value from the exec method.
1213 (Lisp_Object xwidget
)
1215 //TODO support multibyte strings
1218 webkit_web_view_get_title (WEBKIT_WEB_VIEW (xw
->widget_osr
));
1219 //return make_string_from_bytes(str, wcslen((const wchar_t *)str), strlen(str));
1222 //TODO maybe return Qnil instead. I suppose webkit returns nullpointer when doc is not properly loaded or something
1223 printf ("xwidget-webkit-get-title null webkit title\n");
1224 return build_string ("");
1226 return build_string (str
);
1230 DEFUN ("xwidget-disable-plugin-for-mime", Fxwidget_disable_plugin_for_mime
, Sxwidget_disable_plugin_for_mime
, 1, 1, 0, doc
: /* */ )
1233 WebKitWebPlugin
*wp
= webkit_web_plugin_database_get_plugin_for_mimetype
1234 (webkit_get_web_plugin_database (), SSDATA (mime
));
1237 if (webkit_web_plugin_get_enabled (wp
))
1239 webkit_web_plugin_set_enabled (wp
, FALSE
);
1245 #ifdef HAVE_XLXW_DOMDUMP
1246 /* dom dumping is work in progress.
1247 2 of the methods used from webkit are deprecated nowm and replacements sought
1250 xwidget_webkit_dom_dump (WebKitDOMNode
* parent
)
1252 WebKitDOMNodeList
*list
;
1254 WebKitDOMNode
*attribute
;
1255 WebKitDOMNamedNodeMap
*attrs
;
1256 WebKitDOMNode
*child
;
1257 printf ("node:%d type:%d name:%s content:%s\n", parent
, webkit_dom_node_get_node_type (parent
), //1 element 3 text 8 comment 2 attribute
1258 webkit_dom_node_get_local_name (parent
),
1259 webkit_dom_node_get_text_content (parent
));
1261 if (webkit_dom_node_has_attributes (parent
))
1263 attrs
= webkit_dom_node_get_attributes (parent
);
1265 length
= webkit_dom_named_node_map_get_length (attrs
);
1266 for (int i
= 0; i
< length
; i
++)
1268 attribute
= webkit_dom_named_node_map_item (attrs
, i
);
1269 printf (" attr node:%d type:%d name:%s content:%s\n", attribute
, webkit_dom_node_get_node_type (attribute
), //1 element 3 text 8 comment
1270 webkit_dom_node_get_local_name (attribute
),
1271 webkit_dom_node_get_text_content (attribute
));
1274 list
= webkit_dom_node_get_child_nodes (parent
);
1275 length
= webkit_dom_node_list_get_length (list
);
1277 for (int i
= 0; i
< length
; i
++)
1279 child
= webkit_dom_node_list_item (list
, i
);
1280 //if(webkit_dom_node_has_child_nodes(child))
1281 xwidget_webkit_dom_dump (child
);
1286 DEFUN ("xwidget-webkit-dom-dump", Fxwidget_webkit_dom_dump
, Sxwidget_webkit_dom_dump
, 1, 1, 0, doc
: /*Dump the DOM contained in the webkit instance in XWIDGET. */
1288 (Lisp_Object xwidget
)
1291 xwidget_webkit_dom_dump (WEBKIT_DOM_NODE
1292 (webkit_web_view_get_dom_document
1293 (WEBKIT_WEB_VIEW (xw
->widget_osr
))));
1297 #endif /* HAVE_XLXW_DOMDUMP */
1299 #endif /* HAVE_WEBKIT_OSR */
1303 DEFUN ("xwidget-resize", Fxwidget_resize
, Sxwidget_resize
, 3, 3, 0, doc
:
1305 NEW_WIDTH NEW_HEIGHT defines the new size.)
1307 (Lisp_Object xwidget
, Lisp_Object new_width
, Lisp_Object new_height
)
1309 CHECK_XWIDGET (xwidget
);
1310 struct xwidget
*xw
= XXWIDGET (xwidget
);
1311 struct xwidget_view
*xv
;
1314 CHECK_NUMBER (new_width
);
1315 CHECK_NUMBER (new_height
);
1316 w
= XFASTINT (new_width
);
1317 h
= XFASTINT (new_height
);
1321 //if theres a osr resize it 1st
1324 gtk_widget_set_size_request (GTK_WIDGET (xw
->widget_osr
), xw
->width
, xw
->height
); //minimum size
1325 //gtk_window_resize( GTK_WINDOW(xw->widget_osr), xw->width, xw->height);
1326 gtk_window_resize (GTK_WINDOW (xw
->widgetwindow_osr
), xw
->width
,
1328 gtk_window_resize (GTK_WINDOW (xw
->widgetscrolledwindow_osr
), xw
->width
,
1330 gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW
1332 widgetscrolledwindow_osr
),
1334 gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW
1336 widgetscrolledwindow_osr
),
1339 //gtk_container_resize_children ( GTK_WINDOW(xw->widgetwindow_osr));
1340 gtk_container_resize_children (GTK_CONTAINER (xw
->widgetwindow_osr
));
1344 for (Lisp_Object tail
= Vxwidget_view_list
; CONSP (tail
); tail
= XCDR (tail
)) //TODO MVC refactor lazy linear search
1346 if (XWIDGET_VIEW_P (XCAR (tail
)))
1348 xv
= XXWIDGET_VIEW (XCAR (tail
));
1349 if (XXWIDGET (xv
->model
) == xw
)
1351 gtk_layout_set_size (GTK_LAYOUT (xv
->widgetwindow
), xw
->width
,
1353 gtk_widget_set_size_request (GTK_WIDGET (xv
->widget
), xw
->width
,
1364 DEFUN ("xwidget-set-adjustment", Fxwidget_set_adjustment
, Sxwidget_set_adjustment
, 4, 4, 0, doc
:
1367 (Lisp_Object xwidget
, Lisp_Object axis
, Lisp_Object relative
,
1370 CHECK_XWIDGET (xwidget
);
1371 struct xwidget
*xw
= XXWIDGET (xwidget
);
1372 GtkAdjustment
*adjustment
;
1373 float final_value
= 0.0;
1376 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW
1377 (xw
->widgetscrolledwindow_osr
));
1378 if (EQ (Qvertical
, axis
))
1381 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW
1382 (xw
->widgetscrolledwindow_osr
));
1384 if (EQ (Qhorizontal
, axis
))
1387 gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW
1388 (xw
->widgetscrolledwindow_osr
));
1391 if (EQ (Qt
, relative
))
1393 final_value
= gtk_adjustment_get_value (adjustment
) + XFASTINT (value
);
1397 final_value
= 0.0 + XFASTINT (value
);
1400 gtk_adjustment_set_value (adjustment
, final_value
);
1406 DEFUN ("xwidget-size-request", Fxwidget_size_request
, Sxwidget_size_request
, 1, 1, 0, doc
:
1407 /* Desired size of the XWIDGET.
1409 This can be used to read the xwidget desired size, and resizes the Emacs allocated area accordingly.
1411 (TODO crashes if arg not osr widget) */
1413 (Lisp_Object xwidget
)
1415 CHECK_XWIDGET (xwidget
);
1416 GtkRequisition requisition
;
1418 gtk_widget_size_request (XXWIDGET (xwidget
)->widget_osr
, &requisition
);
1420 rv
= Fcons (make_number (requisition
.height
), rv
);
1421 rv
= Fcons (make_number (requisition
.width
), rv
);
1426 DEFUN ("xwidgetp", Fxwidgetp
, Sxwidgetp
, 1, 1, 0, doc
: /* Return t if OBJECT is a xwidget. */
1428 (Lisp_Object object
)
1430 return XWIDGETP (object
) ? Qt
: Qnil
;
1433 DEFUN ("xwidget-view-p", Fxwidget_view_p
, Sxwidget_view_p
, 1, 1, 0, doc
:/* Return t if OBJECT is a xwidget-view. */
1435 (Lisp_Object object
)
1437 return XWIDGET_VIEW_P (object
) ? Qt
: Qnil
;
1440 DEFUN ("xwidget-info", Fxwidget_info
, Sxwidget_info
, 1, 1, 0, doc
: /* Get XWIDGET properties.
1441 Currently type, title, width, height. */ )
1442 (Lisp_Object xwidget
)
1444 CHECK_XWIDGET (xwidget
);
1445 Lisp_Object info
, n
;
1446 struct xwidget
*xw
= XXWIDGET (xwidget
);
1448 info
= Fmake_vector (make_number (4), Qnil
);
1449 ASET (info
, 0, xw
->type
);
1450 ASET (info
, 1, xw
->title
);
1451 XSETFASTINT (n
, xw
->width
);
1453 XSETFASTINT (n
, xw
->height
);
1459 DEFUN ("xwidget-view-info", Fxwidget_view_info
, Sxwidget_view_info
, 1, 1, 0, doc
:
1460 /* Get XWIDGET-VIEW properties.
1461 Currently x,y clip right, clip bottom, clip top, clip left */
1463 (Lisp_Object xwidget_view
)
1465 CHECK_XWIDGET_VIEW (xwidget_view
);
1466 struct xwidget_view
*xv
= XXWIDGET_VIEW (xwidget_view
);
1469 info
= Fmake_vector (make_number (6), Qnil
);
1470 ASET (info
, 0, make_number (xv
->x
));
1471 ASET (info
, 1, make_number (xv
->y
));
1472 ASET (info
, 2, make_number (xv
->clip_right
));
1473 ASET (info
, 3, make_number (xv
->clip_bottom
));
1474 ASET (info
, 4, make_number (xv
->clip_top
));
1475 ASET (info
, 5, make_number (xv
->clip_left
));
1480 DEFUN ("xwidget-view-model", Fxwidget_view_model
, Sxwidget_view_model
, 1, 1, 0, doc
: /* Get XWIDGET-VIEW model. */
1482 (Lisp_Object xwidget_view
)
1484 CHECK_XWIDGET_VIEW (xwidget_view
);
1485 return XXWIDGET_VIEW (xwidget_view
)->model
;
1488 DEFUN ("xwidget-view-window", Fxwidget_view_window
, Sxwidget_view_window
, 1, 1, 0, doc
:/* Get XWIDGET-VIEW window. */
1490 (Lisp_Object xwidget_view
)
1492 CHECK_XWIDGET_VIEW (xwidget_view
);
1493 return XXWIDGET_VIEW (xwidget_view
)->w
;
1496 DEFUN ("xwidget-send-keyboard-event", Fxwidget_send_keyboard_event
, Sxwidget_send_keyboard_event
, 2, 2, 0, doc
:/* Synthesize a kbd event for XWIDGET. TODO crashes atm.. */
1497 )(Lisp_Object xwidget
,
1498 Lisp_Object keydescriptor
)
1500 //TODO this code crashes for offscreen widgets and ive tried many different strategies
1501 //int keyval = 0x058; //X
1502 int keyval
= XFASTINT (keydescriptor
); //X
1505 GdkDeviceManager
*manager
;
1510 //popup_activated_flag = 1; //TODO just a hack
1511 gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), keyval
, &keys
,
1514 xw
= XXWIDGET (xwidget
);
1516 ev
= (GdkEventKey
*) gdk_event_new (GDK_KEY_PRESS
);
1519 //todo what about windowless widgets?
1521 window
= FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
1524 //TODO maybe we also need to special case sockets by picking up the plug rather than the socket
1526 widget
= xw
->widget_osr
;
1528 widget
= xwidget_view_lookup (xw
, XWINDOW (window
))->widget
;
1530 ev
->window
= gtk_widget_get_window (widget
);
1531 gtk_widget_grab_focus (widget
);
1532 ev
->send_event
= FALSE
;
1534 ev
->hardware_keycode
= keys
[0].keycode
;
1535 ev
->group
= keys
[0].group
;
1537 ev
->keyval
= keyval
;
1538 ev
->time
= GDK_CURRENT_TIME
;
1540 //ev->device = gdk_device_get_core_pointer();
1542 gdk_display_get_device_manager (gdk_window_get_display (ev
->window
));
1543 gdk_event_set_device ((GdkEvent
*) ev
,
1544 gdk_device_manager_get_client_pointer (manager
));
1545 gdk_event_put ((GdkEvent
*) ev
);
1546 //g_signal_emit_by_name(ev->window,"key-press-event", ev);
1548 ev
->type
= GDK_KEY_RELEASE
;
1549 gdk_event_put ((GdkEvent
*) ev
);
1550 //g_signal_emit_by_name(ev->window,"key-release-event", ev);
1551 //gtk_main_do_event(ev);
1554 //if I delete the event the receiving component eventually crashes.
1555 //it ough TDTRT since event_put is supposed to copy the event
1556 //so probably this leaks events now
1557 //gdk_event_free((GdkEvent*)ev);
1562 DEFUN ("delete-xwidget-view", Fdelete_xwidget_view
, Sdelete_xwidget_view
, 1, 1, 0, doc
:/* Delete the XWIDGET-VIEW. */
1564 (Lisp_Object xwidget_view
)
1566 CHECK_XWIDGET_VIEW (xwidget_view
);
1567 struct xwidget_view
*xv
= XXWIDGET_VIEW (xwidget_view
);
1568 gtk_widget_destroy (xv
->widgetwindow
);
1569 Vxwidget_view_list
= Fdelq (xwidget_view
, Vxwidget_view_list
);
1573 DEFUN ("xwidget-view-lookup", Fxwidget_view_lookup
, Sxwidget_view_lookup
, 1, 2, 0, doc
:/* Return the xwidget-view associated to XWIDGET in
1574 WINDOW if specified, otherwise it uses the selected window. */
1576 (Lisp_Object xwidget
, Lisp_Object window
)
1578 CHECK_XWIDGET (xwidget
);
1581 window
= Fselected_window ();
1582 CHECK_WINDOW (window
);
1584 for (Lisp_Object tail
= Vxwidget_view_list
; CONSP (tail
);
1587 Lisp_Object xwidget_view
= XCAR (tail
);
1588 if (EQ (Fxwidget_view_model (xwidget_view
), xwidget
)
1589 && EQ (Fxwidget_view_window (xwidget_view
), window
))
1590 return xwidget_view
;
1596 DEFUN ("set-frame-visible", Fset_frame_visible
, Sset_frame_visible
, 2, 2, 0, doc
: /* HACKY */
1598 (Lisp_Object frame
, Lisp_Object flag
)
1600 CHECK_FRAME (frame
);
1601 struct frame
*f
= XFRAME (frame
);
1602 SET_FRAME_VISIBLE (f
, !NILP (flag
));
1606 DEFUN ("xwidget-plist", Fxwidget_plist
, Sxwidget_plist
, 1, 1, 0, doc
: /* Return the plist of XWIDGET. */
1608 (register Lisp_Object xwidget
)
1610 CHECK_XWIDGET (xwidget
);
1611 return XXWIDGET (xwidget
)->plist
;
1614 DEFUN ("xwidget-buffer", Fxwidget_buffer
, Sxwidget_buffer
, 1, 1, 0, doc
:/* Return the buffer of XWIDGET. */
1616 (register Lisp_Object xwidget
)
1618 CHECK_XWIDGET (xwidget
);
1619 return XXWIDGET (xwidget
)->buffer
;
1622 DEFUN ("set-xwidget-plist", Fset_xwidget_plist
, Sset_xwidget_plist
, 2, 2, 0, doc
: /* Replace the plist of XWIDGET with PLIST. Returns PLIST. */
1624 (register Lisp_Object xwidget
, Lisp_Object plist
)
1626 CHECK_XWIDGET (xwidget
);
1629 XXWIDGET (xwidget
)->plist
= plist
;
1633 DEFUN ("set-xwidget-query-on-exit-flag", Fset_xwidget_query_on_exit_flag
, Sset_xwidget_query_on_exit_flag
, 2, 2, 0, doc
:
1634 /* Specify if query is needed for XWIDGET when Emacs is
1635 exited. If the second argument FLAG is non-nil, Emacs will query the
1636 user before exiting or killing a buffer if XWIDGET is running. This
1637 function returns FLAG. */
1639 (Lisp_Object xwidget
, Lisp_Object flag
)
1641 CHECK_XWIDGET (xwidget
);
1642 XXWIDGET (xwidget
)->kill_without_query
= NILP (flag
);
1646 DEFUN ("xwidget-query-on-exit-flag", Fxwidget_query_on_exit_flag
, Sxwidget_query_on_exit_flag
, 1, 1, 0, doc
: /* Return the current value of query-on-exit flag for XWIDGET. */
1648 (Lisp_Object xwidget
)
1650 CHECK_XWIDGET (xwidget
);
1651 return (XXWIDGET (xwidget
)->kill_without_query
? Qnil
: Qt
);
1655 syms_of_xwidget (void)
1658 defsubr (&Smake_xwidget
);
1659 defsubr (&Sxwidgetp
);
1660 DEFSYM (Qxwidgetp
, "xwidgetp");
1661 defsubr (&Sxwidget_view_p
);
1662 DEFSYM (Qxwidget_view_p
, "xwidget-view-p");
1663 defsubr (&Sxwidget_info
);
1664 defsubr (&Sxwidget_view_info
);
1665 defsubr (&Sxwidget_resize
);
1666 defsubr (&Sget_buffer_xwidgets
);
1667 defsubr (&Sxwidget_view_model
);
1668 defsubr (&Sxwidget_view_window
);
1669 defsubr (&Sxwidget_view_lookup
);
1670 defsubr (&Sxwidget_query_on_exit_flag
);
1671 defsubr (&Sset_xwidget_query_on_exit_flag
);
1672 defsubr (&Sset_frame_visible
);
1674 #ifdef HAVE_WEBKIT_OSR
1675 defsubr (&Sxwidget_webkit_goto_uri
);
1676 defsubr (&Sxwidget_webkit_execute_script
);
1677 defsubr (&Sxwidget_webkit_get_title
);
1678 DEFSYM (Qwebkit_osr
, "webkit-osr");
1681 defsubr (&Sxwgir_xwidget_call_method
);
1682 defsubr (&Sxwgir_require_namespace
);
1683 defsubr (&Sxwidget_size_request
);
1684 defsubr (&Sdelete_xwidget_view
);
1685 defsubr (&Sxwidget_disable_plugin_for_mime
);
1687 defsubr (&Sxwidget_send_keyboard_event
);
1688 #ifdef HAVE_XLXW_DOMDUMP
1689 defsubr (&Sxwidget_webkit_dom_dump
);
1692 defsubr (&Sxwidget_plist
);
1693 defsubr (&Sxwidget_buffer
);
1694 defsubr (&Sset_xwidget_plist
);
1696 defsubr (&Sxwidget_set_adjustment
);
1698 DEFSYM (Qxwidget
, "xwidget");
1700 DEFSYM (QCxwidget
, ":xwidget");
1701 DEFSYM (QCxwgir_class
, ":xwgir-class");
1702 DEFSYM (QCtitle
, ":title");
1704 /* Do not forget to update the docstring of make-xwidget if you add
1706 DEFSYM (Qbutton
, "Button"); //changed to match the gtk class because xwgir(experimental and not really needed)
1707 DEFSYM (Qtoggle
, "ToggleButton");
1708 DEFSYM (Qslider
, "slider");
1709 DEFSYM (Qsocket
, "socket");
1710 DEFSYM (Qsocket_osr
, "socket-osr");
1711 DEFSYM (Qcairo
, "cairo");
1713 DEFSYM (Qvertical
, "vertical");
1714 DEFSYM (Qhorizontal
, "horizontal");
1716 DEFSYM (QCplist
, ":plist");
1718 DEFVAR_LISP ("xwidget-list", Vxwidget_list
,
1719 doc
: /* xwidgets list. */);
1720 Vxwidget_list
= Qnil
;
1722 DEFVAR_LISP ("xwidget-view-list", Vxwidget_view_list
,
1723 doc
: /* xwidget views list. */);
1724 Vxwidget_view_list
= Qnil
;
1726 Fprovide (intern ("xwidget-internal"), Qnil
);
1731 /* Value is non-zero if OBJECT is a valid Lisp xwidget specification. A
1732 valid xwidget specification is a list whose car is the symbol
1733 `xwidget', and whose rest is a property list. The property list must
1734 contain a value for key `:type'. That value must be the name of a
1735 supported xwidget type. The rest of the property list depends on the
1739 valid_xwidget_spec_p (Lisp_Object object
)
1743 if (CONSP (object
) && EQ (XCAR (object
), Qxwidget
))
1745 /* Lisp_Object tem; */
1747 /* for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem)) */
1748 /* if (EQ (XCAR (tem), QCtype)) */
1750 /* tem = XCDR (tem); */
1751 /* if (CONSP (tem) && SYMBOLP (XCAR (tem))) */
1753 /* struct xwidget_type *type; */
1754 /* type = lookup_xwidget_type (XCAR (tem)); */
1756 /* valid_p = type->valid_p (object); */
1761 //never mind type support for now
1770 /* find a value associated with key in spec */
1772 xwidget_spec_value (Lisp_Object spec
, Lisp_Object key
, int *found
)
1776 eassert (valid_xwidget_spec_p (spec
));
1778 for (tail
= XCDR (spec
);
1779 CONSP (tail
) && CONSP (XCDR (tail
)); tail
= XCDR (XCDR (tail
)))
1781 if (EQ (XCAR (tail
), key
))
1785 return XCAR (XCDR (tail
));
1796 xwidget_view_delete_all_in_window (struct window
*w
)
1798 struct xwidget_view
*xv
= NULL
;
1799 for (Lisp_Object tail
= Vxwidget_view_list
; CONSP (tail
);
1802 if (XWIDGET_VIEW_P (XCAR (tail
)))
1804 xv
= XXWIDGET_VIEW (XCAR (tail
));
1805 if (XWINDOW (xv
->w
) == w
)
1807 gtk_widget_destroy (xv
->widgetwindow
);
1808 Vxwidget_view_list
= Fdelq (XCAR (tail
), Vxwidget_view_list
);
1814 struct xwidget_view
*
1815 xwidget_view_lookup (struct xwidget
*xw
, struct window
*w
)
1817 Lisp_Object xwidget
, window
, ret
;
1818 XSETXWIDGET (xwidget
, xw
);
1819 XSETWINDOW (window
, w
);
1821 ret
= Fxwidget_view_lookup (xwidget
, window
);
1823 return EQ (ret
, Qnil
) ? NULL
: XXWIDGET_VIEW (ret
);
1827 lookup_xwidget (Lisp_Object spec
)
1829 /* When a xwidget lisp spec is found initialize the C struct that is used in the C code.
1830 This is done by redisplay so values change if the spec changes.
1831 So, take special care of one-shot events
1833 TODO remove xwidget init from display spec. simply store an xwidget reference only and set
1834 size etc when creating the xwidget, which should happen before insertion into buffer
1840 value
= xwidget_spec_value (spec
, QCxwidget
, &found
);
1841 xw
= XXWIDGET (value
);
1846 /*set up detection of touched xwidget*/
1848 xwidget_start_redisplay (void)
1850 for (Lisp_Object tail
= Vxwidget_view_list
; CONSP (tail
);
1853 if (XWIDGET_VIEW_P (XCAR (tail
)))
1854 XXWIDGET_VIEW (XCAR (tail
))->redisplayed
= 0;
1858 /* the xwidget was touched during redisplay, so it isnt a candidate for hiding*/
1860 xwidget_touch (struct xwidget_view
*xv
)
1862 xv
->redisplayed
= 1;
1866 xwidget_touched (struct xwidget_view
*xv
)
1868 return xv
->redisplayed
;
1871 /* redisplay has ended, now we should hide untouched xwidgets
1874 xwidget_end_redisplay (struct window
*w
, struct glyph_matrix
*matrix
)
1881 xwidget_start_redisplay ();
1882 //iterate desired glyph matrix of window here, hide gtk widgets
1883 //not in the desired matrix.
1885 //this only takes care of xwidgets in active windows.
1886 //if a window goes away from screen xwidget views wust be deleted
1888 // dump_glyph_matrix(matrix, 2);
1889 for (i
= 0; i
< matrix
->nrows
; ++i
)
1891 // dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
1892 struct glyph_row
*row
;
1893 row
= MATRIX_ROW (matrix
, i
);
1894 if (row
->enabled_p
!= 0)
1896 for (area
= LEFT_MARGIN_AREA
; area
< LAST_AREA
; ++area
)
1898 struct glyph
*glyph
= row
->glyphs
[area
];
1899 struct glyph
*glyph_end
= glyph
+ row
->used
[area
];
1900 for (; glyph
< glyph_end
; ++glyph
)
1902 if (glyph
->type
== XWIDGET_GLYPH
)
1905 the only call to xwidget_end_redisplay is in dispnew
1906 xwidget_end_redisplay(w->current_matrix);
1908 xwidget_touch (xwidget_view_lookup (glyph
->u
.xwidget
,
1916 for (Lisp_Object tail
= Vxwidget_view_list
; CONSP (tail
);
1919 if (XWIDGET_VIEW_P (XCAR (tail
)))
1921 struct xwidget_view
*xv
= XXWIDGET_VIEW (XCAR (tail
));
1923 //"touched" is only meaningful for the current window, so disregard other views
1924 if (XWINDOW (xv
->w
) == w
)
1926 if (xwidget_touched (xv
))
1927 xwidget_show_view (xv
);
1929 xwidget_hide_view (xv
);
1935 /* Kill all xwidget in BUFFER. */
1937 kill_buffer_xwidgets (Lisp_Object buffer
)
1939 Lisp_Object tail
, xwidget
;
1940 for (tail
= Fget_buffer_xwidgets (buffer
); CONSP (tail
); tail
= XCDR (tail
))
1942 xwidget
= XCAR (tail
);
1943 Vxwidget_list
= Fdelq (xwidget
, Vxwidget_list
);
1944 /* TODO free the GTK things in xw */
1946 CHECK_XWIDGET (xwidget
);
1947 struct xwidget
*xw
= XXWIDGET (xwidget
);
1948 if (xw
->widget_osr
&& xw
->widgetwindow_osr
)
1950 gtk_widget_destroy (xw
->widget_osr
);
1951 gtk_widget_destroy (xw
->widgetwindow_osr
);
1957 #endif /* HAVE_XWIDGETS */