aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2021-11-05 21:01:12 +0800
committerLars Ingebrigtsen2021-11-07 02:59:41 +0100
commitf1fbf877750bb1b4741cd2b89b7d81ee1563fb97 (patch)
tree97e1e4cd812a84beb04d8d1b8c5eec51c96310c3 /src
parent8729ae29d8bbd6076d366ee4316f700fda7aeea3 (diff)
downloademacs-f1fbf877750bb1b4741cd2b89b7d81ee1563fb97.tar.gz
emacs-f1fbf877750bb1b4741cd2b89b7d81ee1563fb97.zip
Make the WebKit inspector available
* etc/NEWS: Document changes. * src/xwidget.c (find_widget_at_pos) (find_widget) (find_widget_cb): New functions. (struct widget_search_data): New structure. (Fmake_xwidget): Enable web inspector for WebKit widgets. (Fxwidget_perform_lispy_event): Use current focus instead of hard-coded widget. (xwidget_button_1, xwidget_button, xwidget_motion_or_crossing): Use window at event position instead of the default widget.
Diffstat (limited to 'src')
-rw-r--r--src/xwidget.c195
1 files changed, 184 insertions, 11 deletions
diff --git a/src/xwidget.c b/src/xwidget.c
index 41e4accb1a7..49645b8b6fd 100644
--- a/src/xwidget.c
+++ b/src/xwidget.c
@@ -82,6 +82,18 @@ webkit_decide_policy_cb (WebKitWebView *,
82 WebKitPolicyDecision *, 82 WebKitPolicyDecision *,
83 WebKitPolicyDecisionType, 83 WebKitPolicyDecisionType,
84 gpointer); 84 gpointer);
85static GtkWidget *find_widget_at_pos (GtkWidget *, int, int, int *, int *);
86
87struct widget_search_data
88{
89 int x;
90 int y;
91 bool foundp;
92 bool first;
93 GtkWidget *data;
94};
95
96static void find_widget (GtkWidget *t, struct widget_search_data *);
85#endif 97#endif
86 98
87 99
@@ -130,6 +142,7 @@ Returns the newly constructed xwidget, or nil if construction fails. */)
130 if (EQ (xw->type, Qwebkit)) 142 if (EQ (xw->type, Qwebkit))
131 { 143 {
132 block_input (); 144 block_input ();
145 WebKitSettings *settings;
133 WebKitWebContext *webkit_context = webkit_web_context_get_default (); 146 WebKitWebContext *webkit_context = webkit_web_context_get_default ();
134 147
135# if WEBKIT_CHECK_VERSION (2, 26, 0) 148# if WEBKIT_CHECK_VERSION (2, 26, 0)
@@ -145,6 +158,10 @@ Returns the newly constructed xwidget, or nil if construction fails. */)
145 { 158 {
146 xw->widget_osr = webkit_web_view_new (); 159 xw->widget_osr = webkit_web_view_new ();
147 160
161 /* Enable the developer extras */
162 settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW (xw->widget_osr));
163 g_object_set (G_OBJECT (settings), "enable-developer-extras", TRUE, NULL);
164
148 /* webkitgtk uses GSubprocess which sets sigaction causing 165 /* webkitgtk uses GSubprocess which sets sigaction causing
149 Emacs to not catch SIGCHLD with its usual handle setup in 166 Emacs to not catch SIGCHLD with its usual handle setup in
150 catch_child_signal(). This resets the SIGCHLD 167 catch_child_signal(). This resets the SIGCHLD
@@ -251,9 +268,12 @@ X-Windows frame. */)
251 else if (FRAME_X_P (SELECTED_FRAME ())) 268 else if (FRAME_X_P (SELECTED_FRAME ()))
252 f = SELECTED_FRAME (); 269 f = SELECTED_FRAME ();
253 270
254 widget = xw->widget_osr;
255
256#ifdef USE_GTK 271#ifdef USE_GTK
272 widget = gtk_window_get_focus (GTK_WINDOW (xw->widgetwindow_osr));
273
274 if (!widget)
275 widget = xw->widget_osr;
276
257 if (RANGED_FIXNUMP (0, event, INT_MAX)) 277 if (RANGED_FIXNUMP (0, event, INT_MAX))
258 { 278 {
259 character = XFIXNUM (event); 279 character = XFIXNUM (event);
@@ -324,7 +344,7 @@ X-Windows frame. */)
324 if (keycode > -1) 344 if (keycode > -1)
325 { 345 {
326 /* WebKitGTK internals abuse follows. */ 346 /* WebKitGTK internals abuse follows. */
327 if (EQ (xw->type, Qwebkit)) 347 if (WEBKIT_IS_WEB_VIEW (widget))
328 { 348 {
329 /* WebKitGTK relies on an internal GtkTextView object to 349 /* WebKitGTK relies on an internal GtkTextView object to
330 "translate" keys such as backspace. We must find that 350 "translate" keys such as backspace. We must find that
@@ -428,18 +448,149 @@ find_suitable_keyboard (struct frame *f)
428} 448}
429 449
430static void 450static void
451find_widget_cb (GtkWidget *widget, void *user)
452{
453 find_widget (widget, user);
454}
455
456static void
457find_widget (GtkWidget *widget,
458 struct widget_search_data *data)
459{
460 GtkAllocation new_allocation;
461 GdkWindow *window;
462 int x_offset = 0;
463 int y_offset = 0;
464
465 gtk_widget_get_allocation (widget, &new_allocation);
466
467 if (gtk_widget_get_has_window (widget))
468 {
469 new_allocation.x = 0;
470 new_allocation.y = 0;
471 }
472
473 if (gtk_widget_get_parent (widget) && !data->first)
474 {
475 window = gtk_widget_get_window (widget);
476 while (window != gtk_widget_get_window (gtk_widget_get_parent (widget)))
477 {
478 gint tx, ty, twidth, theight;
479
480 if (!window)
481 return;
482
483 twidth = gdk_window_get_width (window);
484 theight = gdk_window_get_height (window);
485
486 if (new_allocation.x < 0)
487 {
488 new_allocation.width += new_allocation.x;
489 new_allocation.x = 0;
490 }
491
492 if (new_allocation.y < 0)
493 {
494 new_allocation.height += new_allocation.y;
495 new_allocation.y = 0;
496 }
497
498 if (new_allocation.x + new_allocation.width > twidth)
499 new_allocation.width = twidth - new_allocation.x;
500 if (new_allocation.y + new_allocation.height > theight)
501 new_allocation.height = theight - new_allocation.y;
502
503 gdk_window_get_position (window, &tx, &ty);
504 new_allocation.x += tx;
505 x_offset += tx;
506 new_allocation.y += ty;
507 y_offset += ty;
508
509 window = gdk_window_get_parent (window);
510 }
511 }
512
513 if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
514 (data->x < new_allocation.x + new_allocation.width) &&
515 (data->y < new_allocation.y + new_allocation.height))
516 {
517 /* First, check if the drag is in a valid drop site in
518 * one of our children
519 */
520 if (GTK_IS_CONTAINER (widget))
521 {
522 struct widget_search_data new_data = *data;
523
524 new_data.x -= x_offset;
525 new_data.y -= y_offset;
526 new_data.foundp = false;
527 new_data.first = false;
528
529 gtk_container_forall (GTK_CONTAINER (widget),
530 find_widget_cb, &new_data);
531
532 data->foundp = new_data.foundp;
533 if (data->foundp)
534 data->data = new_data.data;
535 }
536
537 /* If not, and this widget is registered as a drop site, check to
538 * emit "drag_motion" to check if we are actually in
539 * a drop site.
540 */
541 if (!data->foundp)
542 {
543 data->foundp = true;
544 data->data = widget;
545 }
546 }
547}
548
549static GtkWidget *
550find_widget_at_pos (GtkWidget *w, int x, int y,
551 int *new_x, int *new_y)
552{
553 struct widget_search_data data;
554
555 data.x = x;
556 data.y = y;
557 data.foundp = false;
558 data.first = true;
559
560 find_widget (w, &data);
561
562 if (data.foundp)
563 {
564 gtk_widget_translate_coordinates (w, data.data, x,
565 y, new_x, new_y);
566 return data.data;
567 }
568
569 *new_x = x;
570 *new_y = y;
571
572 return NULL;
573}
574
575static void
431xwidget_button_1 (struct xwidget_view *view, 576xwidget_button_1 (struct xwidget_view *view,
432 bool down_p, int x, int y, int button, 577 bool down_p, int x, int y, int button,
433 int modifier_state, Time time) 578 int modifier_state, Time time)
434{ 579{
435 GdkEvent *xg_event = gdk_event_new (down_p ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE); 580 GdkEvent *xg_event = gdk_event_new (down_p ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE);
436 struct xwidget *model = XXWIDGET (view->model); 581 struct xwidget *model = XXWIDGET (view->model);
582 GtkWidget *target;
437 583
438 /* X and Y should be relative to the origin of view->wdesc. */ 584 /* X and Y should be relative to the origin of view->wdesc. */
439 x += view->clip_left; 585 x += view->clip_left;
440 y += view->clip_top; 586 y += view->clip_top;
441 587
442 xg_event->any.window = gtk_widget_get_window (model->widget_osr); 588 target = find_widget_at_pos (model->widgetwindow_osr, x, y, &x, &y);
589
590 if (!target)
591 target = model->widget_osr;
592
593 xg_event->any.window = gtk_widget_get_window (target);
443 g_object_ref (xg_event->any.window); /* The window will be unrefed 594 g_object_ref (xg_event->any.window); /* The window will be unrefed
444 later by gdk_event_free. */ 595 later by gdk_event_free. */
445 596
@@ -467,8 +618,17 @@ xwidget_button (struct xwidget_view *view,
467 { 618 {
468 GdkEvent *xg_event = gdk_event_new (GDK_SCROLL); 619 GdkEvent *xg_event = gdk_event_new (GDK_SCROLL);
469 struct xwidget *model = XXWIDGET (view->model); 620 struct xwidget *model = XXWIDGET (view->model);
621 GtkWidget *target;
622
623 x += view->clip_left;
624 y += view->clip_top;
470 625
471 xg_event->any.window = gtk_widget_get_window (model->widget_osr); 626 target = find_widget_at_pos (model->widgetwindow_osr, x, y, &x, &y);
627
628 if (!target)
629 target = model->widget_osr;
630
631 xg_event->any.window = gtk_widget_get_window (target);
472 g_object_ref (xg_event->any.window); /* The window will be unrefed 632 g_object_ref (xg_event->any.window); /* The window will be unrefed
473 later by gdk_event_free. */ 633 later by gdk_event_free. */
474 if (button == 4) 634 if (button == 4)
@@ -504,15 +664,28 @@ xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event)
504 (event->type == LeaveNotify ? GDK_LEAVE_NOTIFY : 664 (event->type == LeaveNotify ? GDK_LEAVE_NOTIFY :
505 GDK_ENTER_NOTIFY)); 665 GDK_ENTER_NOTIFY));
506 struct xwidget *model = XXWIDGET (view->model); 666 struct xwidget *model = XXWIDGET (view->model);
507 667 int x;
508 xg_event->any.window = gtk_widget_get_window (model->widget_osr); 668 int y;
669 GtkWidget *target = find_widget_at_pos (model->widgetwindow_osr,
670 (event->type == MotionNotify
671 ? event->xmotion.x + view->clip_left
672 : event->xmotion.y + view->clip_top),
673 (event->type == MotionNotify
674 ? event->xmotion.y + view->clip_left
675 : event->xcrossing.y + view->clip_top),
676 &x, &y);
677
678 if (!target)
679 target = model->widgetwindow_osr;
680
681 xg_event->any.window = gtk_widget_get_window (target);
509 g_object_ref (xg_event->any.window); /* The window will be unrefed 682 g_object_ref (xg_event->any.window); /* The window will be unrefed
510 later by gdk_event_free. */ 683 later by gdk_event_free. */
511 684
512 if (event->type == MotionNotify) 685 if (event->type == MotionNotify)
513 { 686 {
514 xg_event->motion.x = event->xmotion.x + view->clip_left; 687 xg_event->motion.x = x;
515 xg_event->motion.y = event->xmotion.y + view->clip_top; 688 xg_event->motion.y = y;
516 xg_event->motion.x_root = event->xmotion.x_root; 689 xg_event->motion.x_root = event->xmotion.x_root;
517 xg_event->motion.y_root = event->xmotion.y_root; 690 xg_event->motion.y_root = event->xmotion.y_root;
518 xg_event->motion.time = event->xmotion.time; 691 xg_event->motion.time = event->xmotion.time;
@@ -523,8 +696,8 @@ xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event)
523 { 696 {
524 xg_event->crossing.detail = min (5, event->xcrossing.detail); 697 xg_event->crossing.detail = min (5, event->xcrossing.detail);
525 xg_event->crossing.time = event->xcrossing.time; 698 xg_event->crossing.time = event->xcrossing.time;
526 xg_event->crossing.x = event->xcrossing.x + view->clip_left; 699 xg_event->crossing.x = x;
527 xg_event->crossing.y = event->xcrossing.y + view->clip_top; 700 xg_event->crossing.y = y;
528 xg_event->crossing.x_root = event->xcrossing.x_root; 701 xg_event->crossing.x_root = event->xcrossing.x_root;
529 xg_event->crossing.y_root = event->xcrossing.y_root; 702 xg_event->crossing.y_root = event->xcrossing.y_root;
530 gdk_event_set_device (xg_event, find_suitable_pointer (view->frame)); 703 gdk_event_set_device (xg_event, find_suitable_pointer (view->frame));