diff options
| -rw-r--r-- | src/gtkutil.c | 160 |
1 files changed, 22 insertions, 138 deletions
diff --git a/src/gtkutil.c b/src/gtkutil.c index 4d166a4d01e..8182ff45766 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c | |||
| @@ -550,24 +550,6 @@ xg_resize_outer_widget (f, columns, rows) | |||
| 550 | gdk_window_process_all_updates (); | 550 | gdk_window_process_all_updates (); |
| 551 | } | 551 | } |
| 552 | 552 | ||
| 553 | /* This gets called after the frame F has been cleared. Since that is | ||
| 554 | done with X calls, we need to redraw GTK widget (scroll bars). */ | ||
| 555 | void | ||
| 556 | xg_frame_cleared (f) | ||
| 557 | FRAME_PTR f; | ||
| 558 | { | ||
| 559 | GtkWidget *w = f->output_data.x->widget; | ||
| 560 | |||
| 561 | if (w) | ||
| 562 | { | ||
| 563 | gtk_container_set_reallocate_redraws (GTK_CONTAINER (w), TRUE); | ||
| 564 | gtk_container_foreach (GTK_CONTAINER (w), | ||
| 565 | (GtkCallback) gtk_widget_queue_draw, | ||
| 566 | 0); | ||
| 567 | gdk_window_process_all_updates (); | ||
| 568 | } | ||
| 569 | } | ||
| 570 | |||
| 571 | /* Function to handle resize of our widgets. Since Emacs has some layouts | 553 | /* Function to handle resize of our widgets. Since Emacs has some layouts |
| 572 | that does not fit well with GTK standard containers, we do most layout | 554 | that does not fit well with GTK standard containers, we do most layout |
| 573 | manually. | 555 | manually. |
| @@ -585,8 +567,10 @@ xg_resize_widgets (f, pixelwidth, pixelheight) | |||
| 585 | int columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth); | 567 | int columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth); |
| 586 | 568 | ||
| 587 | if (FRAME_GTK_WIDGET (f) | 569 | if (FRAME_GTK_WIDGET (f) |
| 588 | && (columns != FRAME_COLS (f) || rows != FRAME_LINES (f) | 570 | && (columns != FRAME_COLS (f) |
| 589 | || pixelwidth != FRAME_PIXEL_WIDTH (f) || pixelheight != FRAME_PIXEL_HEIGHT (f))) | 571 | || rows != FRAME_LINES (f) |
| 572 | || pixelwidth != FRAME_PIXEL_WIDTH (f) | ||
| 573 | || pixelheight != FRAME_PIXEL_HEIGHT (f))) | ||
| 590 | { | 574 | { |
| 591 | struct x_output *x = f->output_data.x; | 575 | struct x_output *x = f->output_data.x; |
| 592 | GtkAllocation all; | 576 | GtkAllocation all; |
| @@ -681,54 +665,6 @@ xg_pix_to_gcolor (w, pixel, c) | |||
| 681 | gdk_colormap_query_color (map, pixel, c); | 665 | gdk_colormap_query_color (map, pixel, c); |
| 682 | } | 666 | } |
| 683 | 667 | ||
| 684 | /* Turning off double buffering for our GtkFixed widget has the side | ||
| 685 | effect of turning it off also for its children (scroll bars). | ||
| 686 | But we want those to be double buffered to not flicker so handle | ||
| 687 | expose manually here. | ||
| 688 | WIDGET is the GtkFixed widget that gets exposed. | ||
| 689 | EVENT is the expose event. | ||
| 690 | USER_DATA is unused. | ||
| 691 | |||
| 692 | Return TRUE to tell GTK that this expose event has been fully handeled | ||
| 693 | and that GTK shall do nothing more with it. */ | ||
| 694 | static gboolean | ||
| 695 | xg_fixed_handle_expose (GtkWidget *widget, | ||
| 696 | GdkEventExpose *event, | ||
| 697 | gpointer user_data) | ||
| 698 | { | ||
| 699 | GList *iter; | ||
| 700 | |||
| 701 | for (iter = GTK_FIXED (widget)->children; iter; iter = g_list_next (iter)) | ||
| 702 | { | ||
| 703 | GtkFixedChild *child_data = (GtkFixedChild *) iter->data; | ||
| 704 | GtkWidget *child = child_data->widget; | ||
| 705 | GdkWindow *window = child->window; | ||
| 706 | GdkRegion *region = gtk_widget_region_intersect (child, event->region); | ||
| 707 | |||
| 708 | if (! gdk_region_empty (region)) | ||
| 709 | { | ||
| 710 | GdkEvent child_event; | ||
| 711 | child_event.expose = *event; | ||
| 712 | child_event.expose.region = region; | ||
| 713 | |||
| 714 | /* Turn on double buffering, i.e. draw to an off screen area. */ | ||
| 715 | gdk_window_begin_paint_region (window, region); | ||
| 716 | |||
| 717 | /* Tell child to redraw itself. */ | ||
| 718 | gdk_region_get_clipbox (region, &child_event.expose.area); | ||
| 719 | gtk_widget_send_expose (child, &child_event); | ||
| 720 | gdk_window_process_updates (window, TRUE); | ||
| 721 | |||
| 722 | /* Copy off screen area to the window. */ | ||
| 723 | gdk_window_end_paint (window); | ||
| 724 | } | ||
| 725 | |||
| 726 | gdk_region_destroy (region); | ||
| 727 | } | ||
| 728 | |||
| 729 | return TRUE; | ||
| 730 | } | ||
| 731 | |||
| 732 | /* Create and set up the GTK widgets for frame F. | 668 | /* Create and set up the GTK widgets for frame F. |
| 733 | Return 0 if creation failed, non-zero otherwise. */ | 669 | Return 0 if creation failed, non-zero otherwise. */ |
| 734 | int | 670 | int |
| @@ -804,12 +740,6 @@ xg_create_frame_widgets (f) | |||
| 804 | a lot, so we turn off double buffering. */ | 740 | a lot, so we turn off double buffering. */ |
| 805 | gtk_widget_set_double_buffered (wfixed, FALSE); | 741 | gtk_widget_set_double_buffered (wfixed, FALSE); |
| 806 | 742 | ||
| 807 | /* Turning off double buffering above has the side effect of turning | ||
| 808 | it off also for its children (scroll bars). But we want those | ||
| 809 | to be double buffered to not flicker so handle expose manually. */ | ||
| 810 | g_signal_connect (G_OBJECT (wfixed), "expose-event", | ||
| 811 | G_CALLBACK (xg_fixed_handle_expose), 0); | ||
| 812 | |||
| 813 | /* GTK documents says use gtk_window_set_resizable. But then a user | 743 | /* GTK documents says use gtk_window_set_resizable. But then a user |
| 814 | can't shrink the window from its starting size. */ | 744 | can't shrink the window from its starting size. */ |
| 815 | gtk_window_set_policy (GTK_WINDOW (wtop), TRUE, TRUE, TRUE); | 745 | gtk_window_set_policy (GTK_WINDOW (wtop), TRUE, TRUE, TRUE); |
| @@ -2770,6 +2700,7 @@ xg_create_scroll_bar (f, bar, scroll_callback, scroll_bar_name) | |||
| 2770 | char *scroll_bar_name; | 2700 | char *scroll_bar_name; |
| 2771 | { | 2701 | { |
| 2772 | GtkWidget *wscroll; | 2702 | GtkWidget *wscroll; |
| 2703 | GtkWidget *webox; | ||
| 2773 | GtkObject *vadj; | 2704 | GtkObject *vadj; |
| 2774 | int scroll_id; | 2705 | int scroll_id; |
| 2775 | 2706 | ||
| @@ -2779,6 +2710,7 @@ xg_create_scroll_bar (f, bar, scroll_callback, scroll_bar_name) | |||
| 2779 | 0.1, 0.1, 0.1); | 2710 | 0.1, 0.1, 0.1); |
| 2780 | 2711 | ||
| 2781 | wscroll = gtk_vscrollbar_new (GTK_ADJUSTMENT (vadj)); | 2712 | wscroll = gtk_vscrollbar_new (GTK_ADJUSTMENT (vadj)); |
| 2713 | webox = gtk_event_box_new (); | ||
| 2782 | gtk_widget_set_name (wscroll, scroll_bar_name); | 2714 | gtk_widget_set_name (wscroll, scroll_bar_name); |
| 2783 | gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS); | 2715 | gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS); |
| 2784 | 2716 | ||
| @@ -2804,11 +2736,18 @@ xg_create_scroll_bar (f, bar, scroll_callback, scroll_bar_name) | |||
| 2804 | G_CALLBACK (scroll_bar_button_cb), | 2736 | G_CALLBACK (scroll_bar_button_cb), |
| 2805 | (gpointer) bar); | 2737 | (gpointer) bar); |
| 2806 | 2738 | ||
| 2807 | gtk_fixed_put (GTK_FIXED (f->output_data.x->edit_widget), | 2739 | /* The scroll bar widget does not draw on a window of its own. Instead |
| 2808 | wscroll, -1, -1); | 2740 | it draws on the parent window, in this case the edit widget. So |
| 2741 | whenever the edit widget is cleared, the scroll bar needs to redraw | ||
| 2742 | also, which causes flicker. Put an event box between the edit widget | ||
| 2743 | and the scroll bar, so the scroll bar instead draws itself on the | ||
| 2744 | event box window. */ | ||
| 2745 | gtk_fixed_put (GTK_FIXED (f->output_data.x->edit_widget), webox, -1, -1); | ||
| 2746 | gtk_container_add (GTK_CONTAINER (webox), wscroll); | ||
| 2747 | |||
| 2809 | 2748 | ||
| 2810 | /* Set the cursor to an arrow. */ | 2749 | /* Set the cursor to an arrow. */ |
| 2811 | xg_set_cursor (wscroll, FRAME_X_DISPLAY_INFO (f)->xg_cursor); | 2750 | xg_set_cursor (webox, FRAME_X_DISPLAY_INFO (f)->xg_cursor); |
| 2812 | 2751 | ||
| 2813 | SET_SCROLL_BAR_X_WINDOW (bar, scroll_id); | 2752 | SET_SCROLL_BAR_X_WINDOW (bar, scroll_id); |
| 2814 | } | 2753 | } |
| @@ -2820,7 +2759,7 @@ xg_show_scroll_bar (scrollbar_id) | |||
| 2820 | { | 2759 | { |
| 2821 | GtkWidget *w = xg_get_widget_from_map (scrollbar_id); | 2760 | GtkWidget *w = xg_get_widget_from_map (scrollbar_id); |
| 2822 | if (w) | 2761 | if (w) |
| 2823 | gtk_widget_show (w); | 2762 | gtk_widget_show_all (gtk_widget_get_parent (w)); |
| 2824 | } | 2763 | } |
| 2825 | 2764 | ||
| 2826 | /* Remove the scroll bar represented by SCROLLBAR_ID from the frame F. */ | 2765 | /* Remove the scroll bar represented by SCROLLBAR_ID from the frame F. */ |
| @@ -2832,42 +2771,19 @@ xg_remove_scroll_bar (f, scrollbar_id) | |||
| 2832 | GtkWidget *w = xg_get_widget_from_map (scrollbar_id); | 2771 | GtkWidget *w = xg_get_widget_from_map (scrollbar_id); |
| 2833 | if (w) | 2772 | if (w) |
| 2834 | { | 2773 | { |
| 2774 | GtkWidget *wparent = gtk_widget_get_parent (w); | ||
| 2835 | gtk_widget_destroy (w); | 2775 | gtk_widget_destroy (w); |
| 2776 | gtk_widget_destroy (wparent); | ||
| 2836 | SET_FRAME_GARBAGED (f); | 2777 | SET_FRAME_GARBAGED (f); |
| 2837 | } | 2778 | } |
| 2838 | } | 2779 | } |
| 2839 | 2780 | ||
| 2840 | /* Find left/top for widget W in GtkFixed widget WFIXED. */ | ||
| 2841 | static void | ||
| 2842 | xg_find_top_left_in_fixed (w, wfixed, left, top) | ||
| 2843 | GtkWidget *w, *wfixed; | ||
| 2844 | int *left, *top; | ||
| 2845 | { | ||
| 2846 | GList *iter; | ||
| 2847 | |||
| 2848 | for (iter = GTK_FIXED (wfixed)->children; iter; iter = g_list_next (iter)) | ||
| 2849 | { | ||
| 2850 | GtkFixedChild *child = (GtkFixedChild *) iter->data; | ||
| 2851 | |||
| 2852 | if (child->widget == w) | ||
| 2853 | { | ||
| 2854 | *left = child->x; | ||
| 2855 | *top = child->y; | ||
| 2856 | return; | ||
| 2857 | } | ||
| 2858 | } | ||
| 2859 | |||
| 2860 | /* Shall never end up here. */ | ||
| 2861 | abort (); | ||
| 2862 | } | ||
| 2863 | |||
| 2864 | /* Update the position of the vertical scroll bar represented by SCROLLBAR_ID | 2781 | /* Update the position of the vertical scroll bar represented by SCROLLBAR_ID |
| 2865 | in frame F. | 2782 | in frame F. |
| 2866 | TOP/LEFT are the new pixel positions where the bar shall appear. | 2783 | TOP/LEFT are the new pixel positions where the bar shall appear. |
| 2867 | WIDTH, HEIGHT is the size in pixels the bar shall have. */ | 2784 | WIDTH, HEIGHT is the size in pixels the bar shall have. */ |
| 2868 | void | 2785 | void |
| 2869 | xg_update_scrollbar_pos (f, scrollbar_id, top, left, width, height, | 2786 | xg_update_scrollbar_pos (f, scrollbar_id, top, left, width, height) |
| 2870 | real_left, canon_width) | ||
| 2871 | FRAME_PTR f; | 2787 | FRAME_PTR f; |
| 2872 | int scrollbar_id; | 2788 | int scrollbar_id; |
| 2873 | int top; | 2789 | int top; |
| @@ -2881,44 +2797,12 @@ xg_update_scrollbar_pos (f, scrollbar_id, top, left, width, height, | |||
| 2881 | if (wscroll) | 2797 | if (wscroll) |
| 2882 | { | 2798 | { |
| 2883 | GtkWidget *wfixed = f->output_data.x->edit_widget; | 2799 | GtkWidget *wfixed = f->output_data.x->edit_widget; |
| 2884 | 2800 | GtkWidget *wparent = gtk_widget_get_parent (wscroll); | |
| 2885 | gtk_container_set_reallocate_redraws (GTK_CONTAINER (wfixed), TRUE); | ||
| 2886 | 2801 | ||
| 2887 | /* Move and resize to new values. */ | 2802 | /* Move and resize to new values. */ |
| 2888 | gtk_fixed_move (GTK_FIXED (wfixed), wscroll, left, top); | ||
| 2889 | gtk_widget_set_size_request (wscroll, width, height); | 2803 | gtk_widget_set_size_request (wscroll, width, height); |
| 2804 | gtk_fixed_move (GTK_FIXED (wfixed), wparent, left, top); | ||
| 2890 | 2805 | ||
| 2891 | /* Scroll bars in GTK has a fixed width, so if we say width 16, it | ||
| 2892 | will only be its fixed width (14 is default) anyway, the rest is | ||
| 2893 | blank. We are drawing the mode line across scroll bars when | ||
| 2894 | the frame is split: | ||
| 2895 | |bar| |fringe| | ||
| 2896 | ---------------- | ||
| 2897 | mode line | ||
| 2898 | ---------------- | ||
| 2899 | |bar| |fringe| | ||
| 2900 | |||
| 2901 | When we "unsplit" the frame: | ||
| 2902 | |||
| 2903 | |bar| |fringe| | ||
| 2904 | -| |-| | | ||
| 2905 | m¦ |i| | | ||
| 2906 | -| |-| | | ||
| 2907 | | | | | | ||
| 2908 | |||
| 2909 | |||
| 2910 | the remains of the mode line can be seen in these blank spaces. | ||
| 2911 | So we must clear them explicitly. | ||
| 2912 | GTK scroll bars should do that, but they don't. | ||
| 2913 | Also, the canonical width may be wider than the width for the | ||
| 2914 | scroll bar so that there is some space (typically 1 pixel) between | ||
| 2915 | the scroll bar and the edge of the window and between the scroll | ||
| 2916 | bar and the fringe. */ | ||
| 2917 | gdk_window_clear (wscroll->window); | ||
| 2918 | |||
| 2919 | /* Must force out update so changed scroll bars gets redrawn. */ | ||
| 2920 | gdk_window_process_all_updates (); | ||
| 2921 | |||
| 2922 | SET_FRAME_GARBAGED (f); | 2806 | SET_FRAME_GARBAGED (f); |
| 2923 | cancel_mouse_face (f); | 2807 | cancel_mouse_face (f); |
| 2924 | } | 2808 | } |