550 |
gdk_window_process_all_updates (); |
gdk_window_process_all_updates (); |
551 |
} |
} |
552 |
|
|
|
/* This gets called after the frame F has been cleared. Since that is |
|
|
done with X calls, we need to redraw GTK widget (scroll bars). */ |
|
|
void |
|
|
xg_frame_cleared (f) |
|
|
FRAME_PTR f; |
|
|
{ |
|
|
GtkWidget *w = f->output_data.x->widget; |
|
|
|
|
|
if (w) |
|
|
{ |
|
|
gtk_container_set_reallocate_redraws (GTK_CONTAINER (w), TRUE); |
|
|
gtk_container_foreach (GTK_CONTAINER (w), |
|
|
(GtkCallback) gtk_widget_queue_draw, |
|
|
0); |
|
|
gdk_window_process_all_updates (); |
|
|
} |
|
|
} |
|
|
|
|
553 |
/* Function to handle resize of our widgets. Since Emacs has some layouts |
/* Function to handle resize of our widgets. Since Emacs has some layouts |
554 |
that does not fit well with GTK standard containers, we do most layout |
that does not fit well with GTK standard containers, we do most layout |
555 |
manually. |
manually. |
567 |
int columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth); |
int columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth); |
568 |
|
|
569 |
if (FRAME_GTK_WIDGET (f) |
if (FRAME_GTK_WIDGET (f) |
570 |
&& (columns != FRAME_COLS (f) || rows != FRAME_LINES (f) |
&& (columns != FRAME_COLS (f) |
571 |
|| pixelwidth != FRAME_PIXEL_WIDTH (f) || pixelheight != FRAME_PIXEL_HEIGHT (f))) |
|| rows != FRAME_LINES (f) |
572 |
|
|| pixelwidth != FRAME_PIXEL_WIDTH (f) |
573 |
|
|| pixelheight != FRAME_PIXEL_HEIGHT (f))) |
574 |
{ |
{ |
575 |
struct x_output *x = f->output_data.x; |
struct x_output *x = f->output_data.x; |
576 |
GtkAllocation all; |
GtkAllocation all; |
665 |
gdk_colormap_query_color (map, pixel, c); |
gdk_colormap_query_color (map, pixel, c); |
666 |
} |
} |
667 |
|
|
|
/* Turning off double buffering for our GtkFixed widget has the side |
|
|
effect of turning it off also for its children (scroll bars). |
|
|
But we want those to be double buffered to not flicker so handle |
|
|
expose manually here. |
|
|
WIDGET is the GtkFixed widget that gets exposed. |
|
|
EVENT is the expose event. |
|
|
USER_DATA is unused. |
|
|
|
|
|
Return TRUE to tell GTK that this expose event has been fully handeled |
|
|
and that GTK shall do nothing more with it. */ |
|
|
static gboolean |
|
|
xg_fixed_handle_expose (GtkWidget *widget, |
|
|
GdkEventExpose *event, |
|
|
gpointer user_data) |
|
|
{ |
|
|
GList *iter; |
|
|
|
|
|
for (iter = GTK_FIXED (widget)->children; iter; iter = g_list_next (iter)) |
|
|
{ |
|
|
GtkFixedChild *child_data = (GtkFixedChild *) iter->data; |
|
|
GtkWidget *child = child_data->widget; |
|
|
GdkWindow *window = child->window; |
|
|
GdkRegion *region = gtk_widget_region_intersect (child, event->region); |
|
|
|
|
|
if (! gdk_region_empty (region)) |
|
|
{ |
|
|
GdkEvent child_event; |
|
|
child_event.expose = *event; |
|
|
child_event.expose.region = region; |
|
|
|
|
|
/* Turn on double buffering, i.e. draw to an off screen area. */ |
|
|
gdk_window_begin_paint_region (window, region); |
|
|
|
|
|
/* Tell child to redraw itself. */ |
|
|
gdk_region_get_clipbox (region, &child_event.expose.area); |
|
|
gtk_widget_send_expose (child, &child_event); |
|
|
gdk_window_process_updates (window, TRUE); |
|
|
|
|
|
/* Copy off screen area to the window. */ |
|
|
gdk_window_end_paint (window); |
|
|
} |
|
|
|
|
|
gdk_region_destroy (region); |
|
|
} |
|
|
|
|
|
return TRUE; |
|
|
} |
|
|
|
|
668 |
/* Create and set up the GTK widgets for frame F. |
/* Create and set up the GTK widgets for frame F. |
669 |
Return 0 if creation failed, non-zero otherwise. */ |
Return 0 if creation failed, non-zero otherwise. */ |
670 |
int |
int |
740 |
a lot, so we turn off double buffering. */ |
a lot, so we turn off double buffering. */ |
741 |
gtk_widget_set_double_buffered (wfixed, FALSE); |
gtk_widget_set_double_buffered (wfixed, FALSE); |
742 |
|
|
|
/* Turning off double buffering above has the side effect of turning |
|
|
it off also for its children (scroll bars). But we want those |
|
|
to be double buffered to not flicker so handle expose manually. */ |
|
|
g_signal_connect (G_OBJECT (wfixed), "expose-event", |
|
|
G_CALLBACK (xg_fixed_handle_expose), 0); |
|
|
|
|
743 |
/* GTK documents says use gtk_window_set_resizable. But then a user |
/* GTK documents says use gtk_window_set_resizable. But then a user |
744 |
can't shrink the window from its starting size. */ |
can't shrink the window from its starting size. */ |
745 |
gtk_window_set_policy (GTK_WINDOW (wtop), TRUE, TRUE, TRUE); |
gtk_window_set_policy (GTK_WINDOW (wtop), TRUE, TRUE, TRUE); |
2700 |
char *scroll_bar_name; |
char *scroll_bar_name; |
2701 |
{ |
{ |
2702 |
GtkWidget *wscroll; |
GtkWidget *wscroll; |
2703 |
|
GtkWidget *webox; |
2704 |
GtkObject *vadj; |
GtkObject *vadj; |
2705 |
int scroll_id; |
int scroll_id; |
2706 |
|
|
2710 |
0.1, 0.1, 0.1); |
0.1, 0.1, 0.1); |
2711 |
|
|
2712 |
wscroll = gtk_vscrollbar_new (GTK_ADJUSTMENT (vadj)); |
wscroll = gtk_vscrollbar_new (GTK_ADJUSTMENT (vadj)); |
2713 |
|
webox = gtk_event_box_new (); |
2714 |
gtk_widget_set_name (wscroll, scroll_bar_name); |
gtk_widget_set_name (wscroll, scroll_bar_name); |
2715 |
gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS); |
gtk_range_set_update_policy (GTK_RANGE (wscroll), GTK_UPDATE_CONTINUOUS); |
2716 |
|
|
2736 |
G_CALLBACK (scroll_bar_button_cb), |
G_CALLBACK (scroll_bar_button_cb), |
2737 |
(gpointer) bar); |
(gpointer) bar); |
2738 |
|
|
2739 |
gtk_fixed_put (GTK_FIXED (f->output_data.x->edit_widget), |
/* The scroll bar widget does not draw on a window of its own. Instead |
2740 |
wscroll, -1, -1); |
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 |
|
|
2748 |
|
|
2749 |
/* Set the cursor to an arrow. */ |
/* Set the cursor to an arrow. */ |
2750 |
xg_set_cursor (wscroll, FRAME_X_DISPLAY_INFO (f)->xg_cursor); |
xg_set_cursor (webox, FRAME_X_DISPLAY_INFO (f)->xg_cursor); |
2751 |
|
|
2752 |
SET_SCROLL_BAR_X_WINDOW (bar, scroll_id); |
SET_SCROLL_BAR_X_WINDOW (bar, scroll_id); |
2753 |
} |
} |
2759 |
{ |
{ |
2760 |
GtkWidget *w = xg_get_widget_from_map (scrollbar_id); |
GtkWidget *w = xg_get_widget_from_map (scrollbar_id); |
2761 |
if (w) |
if (w) |
2762 |
gtk_widget_show (w); |
gtk_widget_show_all (gtk_widget_get_parent (w)); |
2763 |
} |
} |
2764 |
|
|
2765 |
/* Remove the scroll bar represented by SCROLLBAR_ID from the frame F. */ |
/* Remove the scroll bar represented by SCROLLBAR_ID from the frame F. */ |
2771 |
GtkWidget *w = xg_get_widget_from_map (scrollbar_id); |
GtkWidget *w = xg_get_widget_from_map (scrollbar_id); |
2772 |
if (w) |
if (w) |
2773 |
{ |
{ |
2774 |
|
GtkWidget *wparent = gtk_widget_get_parent (w); |
2775 |
gtk_widget_destroy (w); |
gtk_widget_destroy (w); |
2776 |
|
gtk_widget_destroy (wparent); |
2777 |
SET_FRAME_GARBAGED (f); |
SET_FRAME_GARBAGED (f); |
2778 |
} |
} |
2779 |
} |
} |
2780 |
|
|
|
/* Find left/top for widget W in GtkFixed widget WFIXED. */ |
|
|
static void |
|
|
xg_find_top_left_in_fixed (w, wfixed, left, top) |
|
|
GtkWidget *w, *wfixed; |
|
|
int *left, *top; |
|
|
{ |
|
|
GList *iter; |
|
|
|
|
|
for (iter = GTK_FIXED (wfixed)->children; iter; iter = g_list_next (iter)) |
|
|
{ |
|
|
GtkFixedChild *child = (GtkFixedChild *) iter->data; |
|
|
|
|
|
if (child->widget == w) |
|
|
{ |
|
|
*left = child->x; |
|
|
*top = child->y; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
/* Shall never end up here. */ |
|
|
abort (); |
|
|
} |
|
|
|
|
2781 |
/* Update the position of the vertical scroll bar represented by SCROLLBAR_ID |
/* Update the position of the vertical scroll bar represented by SCROLLBAR_ID |
2782 |
in frame F. |
in frame F. |
2783 |
TOP/LEFT are the new pixel positions where the bar shall appear. |
TOP/LEFT are the new pixel positions where the bar shall appear. |
2784 |
WIDTH, HEIGHT is the size in pixels the bar shall have. */ |
WIDTH, HEIGHT is the size in pixels the bar shall have. */ |
2785 |
void |
void |
2786 |
xg_update_scrollbar_pos (f, scrollbar_id, top, left, width, height, |
xg_update_scrollbar_pos (f, scrollbar_id, top, left, width, height) |
|
real_left, canon_width) |
|
2787 |
FRAME_PTR f; |
FRAME_PTR f; |
2788 |
int scrollbar_id; |
int scrollbar_id; |
2789 |
int top; |
int top; |
2797 |
if (wscroll) |
if (wscroll) |
2798 |
{ |
{ |
2799 |
GtkWidget *wfixed = f->output_data.x->edit_widget; |
GtkWidget *wfixed = f->output_data.x->edit_widget; |
2800 |
|
GtkWidget *wparent = gtk_widget_get_parent (wscroll); |
|
gtk_container_set_reallocate_redraws (GTK_CONTAINER (wfixed), TRUE); |
|
2801 |
|
|
2802 |
/* Move and resize to new values. */ |
/* Move and resize to new values. */ |
|
gtk_fixed_move (GTK_FIXED (wfixed), wscroll, left, top); |
|
2803 |
gtk_widget_set_size_request (wscroll, width, height); |
gtk_widget_set_size_request (wscroll, width, height); |
2804 |
|
gtk_fixed_move (GTK_FIXED (wfixed), wparent, left, top); |
|
/* Must force out update so changed scroll bars gets redrawn. */ |
|
|
gdk_window_process_all_updates (); |
|
|
|
|
|
/* Scroll bars in GTK has a fixed width, so if we say width 16, it |
|
|
will only be its fixed width (14 is default) anyway, the rest is |
|
|
blank. We are drawing the mode line across scroll bars when |
|
|
the frame is split: |
|
|
|bar| |fringe| |
|
|
---------------- |
|
|
mode line |
|
|
---------------- |
|
|
|bar| |fringe| |
|
|
|
|
|
When we "unsplit" the frame: |
|
|
|
|
|
|bar| |fringe| |
|
|
-| |-| | |
|
|
m¦ |i| | |
|
|
-| |-| | |
|
|
| | | | |
|
|
|
|
|
|
|
|
the remains of the mode line can be seen in these blank spaces. |
|
|
So we must clear them explicitly. |
|
|
GTK scroll bars should do that, but they don't. |
|
|
Also, the canonical width may be wider than the width for the |
|
|
scroll bar so that there is some space (typically 1 pixel) between |
|
|
the scroll bar and the edge of the window and between the scroll |
|
|
bar and the fringe. */ |
|
|
|
|
|
XClearWindow (FRAME_X_DISPLAY (f), GTK_WIDGET_TO_X_WIN (wscroll)); |
|
2805 |
|
|
2806 |
SET_FRAME_GARBAGED (f); |
SET_FRAME_GARBAGED (f); |
2807 |
cancel_mouse_face (f); |
cancel_mouse_face (f); |