aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJan Djärv2003-03-23 00:59:23 +0000
committerJan Djärv2003-03-23 00:59:23 +0000
commit7863d62580ba300daabda98db9f908ada25fd43b (patch)
tree187e97e400dafad8bd25959417c4d8aa40e0167b /src
parent56c806b77e709c1c64889e4ddf2c03603b4bf3c0 (diff)
downloademacs-7863d62580ba300daabda98db9f908ada25fd43b.tar.gz
emacs-7863d62580ba300daabda98db9f908ada25fd43b.zip
Finally (?) fix flicker in scroll bar.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog21
-rw-r--r--src/gtkutil.c190
-rw-r--r--src/gtkutil.h7
-rw-r--r--src/xterm.c8
4 files changed, 156 insertions, 70 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 0171759825a..bad3aee2925 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,24 @@
12003-03-23 Jan Dj,Ad(Brv <jan.h.d@swipnet.se>
2
3 * gtkutil.h: Take two more arguments to xg_update_scrollbar_pos.
4 (XG_SB_RANGE): New define.
5
6 * gtkutil.c (xg_fixed_handle_expose): New function.
7 (xg_create_frame_widgets): Call xg_fixed_handle_expose for
8 expose events.
9 (xg_update_scrollbar_pos): Take two more arguments, left and width
10 of scroll bar including borders.
11 Clear left and right part outside scroll bar separately as some
12 themes have bars that are not an even number of pixels.
13 Don't set reallocate_redraws, don't call
14 gdk_window_process_all_updates.
15 (xg_set_toolkit_scroll_bar_thumb): Upper value is fixed,
16 so no need to change it. Calculate size and value with XG_SB_RANGE.
17
18 * xterm.c (x_scroll_bar_create, XTset_vertical_scroll_bar): Pass
19 left and width of scroll bar including borders to
20 xg_update_scrollbar_pos.
21
12003-03-22 Thien-Thi Nguyen <ttn@gnu.org> 222003-03-22 Thien-Thi Nguyen <ttn@gnu.org>
2 23
3 * Makefile.in: Make sure space precedes end-of-line backslashes. 24 * Makefile.in: Make sure space precedes end-of-line backslashes.
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 61e79749354..dc054426d04 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -151,7 +151,7 @@ xg_process_timeouts (timer)
151 151
152/* Start the xg_timer with an interval of 0.1 seconds, if not already started. 152/* Start the xg_timer with an interval of 0.1 seconds, if not already started.
153 xg_process_timeouts is called when the timer expires. The timer 153 xg_process_timeouts is called when the timer expires. The timer
154 stared is continuous, i.e. runs until xg_stop_timer is called. */ 154 started is continuous, i.e. runs until xg_stop_timer is called. */
155static void 155static void
156xg_start_timer () 156xg_start_timer ()
157{ 157{
@@ -412,6 +412,54 @@ xg_pix_to_gcolor (w, pixel, c)
412 gdk_colormap_query_color (map, pixel, c); 412 gdk_colormap_query_color (map, pixel, c);
413} 413}
414 414
415/* Turning off double buffering for our GtkFixed widget has the side
416 effect of turning it off also for its children (scroll bars).
417 But we want those to be double buffered to not flicker so handle
418 expose manually here.
419 WIDGET is the GtkFixed widget that gets exposed.
420 EVENT is the expose event.
421 USER_DATA is unused.
422
423 Return TRUE to tell GTK that this expose event has been fully handeled
424 and that GTK shall do nothing more with it. */
425static gboolean
426xg_fixed_handle_expose(GtkWidget *widget,
427 GdkEventExpose *event,
428 gpointer user_data)
429{
430 GList *iter;
431
432 for (iter = GTK_FIXED (widget)->children; iter; iter = g_list_next (iter))
433 {
434 GtkFixedChild *child_data = (GtkFixedChild *) iter->data;
435 GtkWidget *child = child_data->widget;
436 GdkWindow *window = child->window;
437 GdkRegion *region = gtk_widget_region_intersect (child, event->region);
438
439 if (! gdk_region_empty (region))
440 {
441 GdkEvent child_event;
442 child_event.expose = *event;
443 child_event.expose.region = region;
444
445 /* Turn on double buffering, i.e. draw to an off screen area. */
446 gdk_window_begin_paint_region (window, region);
447
448 /* Tell child to redraw itself. */
449 gdk_region_get_clipbox (region, &child_event.expose.area);
450 gtk_widget_send_expose (child, &child_event);
451 gdk_window_process_updates (window, TRUE);
452
453 /* Copy off screen area to the window. */
454 gdk_window_end_paint (window);
455 }
456
457 gdk_region_destroy (region);
458 }
459
460 return TRUE;
461}
462
415/* Create and set up the GTK widgets for frame F. 463/* Create and set up the GTK widgets for frame F.
416 Return 0 if creation failed, non-zero otherwise. */ 464 Return 0 if creation failed, non-zero otherwise. */
417int 465int
@@ -478,9 +526,19 @@ xg_create_frame_widgets (f)
478 if (FRAME_EXTERNAL_TOOL_BAR (f) && FRAME_TOOLBAR_HEIGHT (f) == 0) 526 if (FRAME_EXTERNAL_TOOL_BAR (f) && FRAME_TOOLBAR_HEIGHT (f) == 0)
479 FRAME_TOOLBAR_HEIGHT (f) = 34; 527 FRAME_TOOLBAR_HEIGHT (f) = 34;
480 528
481 gtk_widget_set_double_buffered (wvbox, FALSE); 529
530 /* We don't want this widget double buffered, because we draw on it
531 with regular X drawing primitives, so from a GTK/GDK point of
532 view, the widget is totally blank. When an expose comes, this
533 will make the widget blank, and then Emacs redraws it. This flickers
534 a lot, so we turn off double buffering. */
482 gtk_widget_set_double_buffered (wfixed, FALSE); 535 gtk_widget_set_double_buffered (wfixed, FALSE);
483 gtk_widget_set_double_buffered (wtop, FALSE); 536
537 /* Turning off double buffering above has the side effect of turning
538 it off also for its children (scroll bars). But we want those
539 to be double buffered to not flicker so handle expose manually. */
540 g_signal_connect (G_OBJECT (wfixed), "expose-event",
541 G_CALLBACK (xg_fixed_handle_expose), 0);
484 542
485 /* GTK documents says use gtk_window_set_resizable. But then a user 543 /* GTK documents says use gtk_window_set_resizable. But then a user
486 can't shrink the window from its starting size. */ 544 can't shrink the window from its starting size. */
@@ -1159,6 +1217,7 @@ make_widget_for_menu_item (utf8_label, utf8_key)
1159 1217
1160 gtk_widget_set_name (wlbl, MENU_ITEM_NAME); 1218 gtk_widget_set_name (wlbl, MENU_ITEM_NAME);
1161 gtk_widget_set_name (wkey, MENU_ITEM_NAME); 1219 gtk_widget_set_name (wkey, MENU_ITEM_NAME);
1220 gtk_widget_set_name (wbox, MENU_ITEM_NAME);
1162 1221
1163 return wbox; 1222 return wbox;
1164} 1223}
@@ -2497,7 +2556,8 @@ xg_find_top_left_in_fixed (w, wfixed, left, top)
2497 TOP/LEFT are the new pixel positions where the bar shall appear. 2556 TOP/LEFT are the new pixel positions where the bar shall appear.
2498 WIDTH, HEIGHT is the size in pixels the bar shall have. */ 2557 WIDTH, HEIGHT is the size in pixels the bar shall have. */
2499void 2558void
2500xg_update_scrollbar_pos (f, scrollbar_id, top, left, width, height) 2559xg_update_scrollbar_pos (f, scrollbar_id, top, left, width, height,
2560 real_left, canon_width)
2501 FRAME_PTR f; 2561 FRAME_PTR f;
2502 int scrollbar_id; 2562 int scrollbar_id;
2503 int top; 2563 int top;
@@ -2507,19 +2567,18 @@ xg_update_scrollbar_pos (f, scrollbar_id, top, left, width, height)
2507{ 2567{
2508 2568
2509 GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id); 2569 GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id);
2510 2570
2511 if (wscroll) 2571 if (wscroll)
2512 { 2572 {
2513 GtkWidget *wfixed = f->output_data.x->edit_widget; 2573 GtkWidget *wfixed = f->output_data.x->edit_widget;
2514 int gheight = max (height, 1); 2574 int gheight = max (height, 1);
2515 int canon_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
2516 int winextra = canon_width > width ? (canon_width - width) / 2 : 0; 2575 int winextra = canon_width > width ? (canon_width - width) / 2 : 0;
2517 int bottom = top + gheight; 2576 int bottom = top + gheight;
2518 2577
2519 gint slider_width; 2578 gint slider_width;
2520 int oldtop, oldleft, oldbottom; 2579 int oldtop, oldleft, oldbottom;
2521 GtkRequisition req; 2580 GtkRequisition req;
2522 2581
2523 /* Get old values. */ 2582 /* Get old values. */
2524 xg_find_top_left_in_fixed (wscroll, wfixed, &oldleft, &oldtop); 2583 xg_find_top_left_in_fixed (wscroll, wfixed, &oldleft, &oldtop);
2525 gtk_widget_size_request (wscroll, &req); 2584 gtk_widget_size_request (wscroll, &req);
@@ -2547,49 +2606,57 @@ xg_update_scrollbar_pos (f, scrollbar_id, top, left, width, height)
2547 the remains of the mode line can be seen in these blank spaces. 2606 the remains of the mode line can be seen in these blank spaces.
2548 So we must clear them explicitly. 2607 So we must clear them explicitly.
2549 GTK scroll bars should do that, but they don't. 2608 GTK scroll bars should do that, but they don't.
2550 Also, the scroll bar canonical width may be wider than the width 2609 Also, the canonical width may be wider than the width for the
2551 passed in here. */ 2610 scroll bar so that there is some space (typically 1 pixel) between
2611 the scroll bar and the edge of the window and between the scroll
2612 bar and the fringe. */
2552 2613
2553 if (oldtop != -1 && oldleft != -1) 2614 if (oldtop != -1 && oldleft != -1)
2554 { 2615 {
2555 int gtkextra; 2616 int gtkextral, gtkextrah;
2556 int xl, xr, wblank; 2617 int xl, xr, wbl, wbr;
2557 int bottomdiff, topdiff; 2618 int bottomdiff, topdiff;
2558 2619
2559 gtk_widget_style_get (wscroll, "slider_width", &slider_width, NULL); 2620 gtk_widget_style_get (wscroll, "slider_width", &slider_width, NULL);
2560 gtkextra = width > slider_width ? (width - slider_width) / 2 : 0; 2621 gtkextral = width > slider_width ? (width - slider_width) / 2 : 0;
2561 2622 gtkextrah = gtkextral ? (width - slider_width - gtkextral) : 0;
2562 xl = left - winextra; 2623
2563 wblank = gtkextra + winextra; 2624 xl = real_left;
2564 xr = left + gtkextra + slider_width; 2625 wbl = gtkextral + winextra;
2626 wbr = gtkextrah + winextra;
2627 xr = left + gtkextral + slider_width;
2565 bottomdiff = abs (oldbottom - bottom); 2628 bottomdiff = abs (oldbottom - bottom);
2566 topdiff = abs (oldtop - top); 2629 topdiff = abs (oldtop - top);
2567 2630
2631 if (oldleft != left)
2632 {
2633 gdk_window_clear_area (wfixed->window, xl, top, wbl, gheight);
2634 gdk_window_clear_area (wfixed->window, xr, top, wbr, gheight);
2635 }
2636
2568 if (oldtop > top) 2637 if (oldtop > top)
2569 { 2638 {
2570 gdk_window_clear_area (wfixed->window, xl, top, wblank, topdiff); 2639 gdk_window_clear_area (wfixed->window, xl, top, wbl, topdiff);
2571 gdk_window_clear_area (wfixed->window, xr, top, wblank, topdiff); 2640 gdk_window_clear_area (wfixed->window, xr, top, wbr, topdiff);
2572 } 2641 }
2573 else if (oldtop < top) 2642 else if (oldtop < top)
2574 { 2643 {
2575 gdk_window_clear_area (wfixed->window, xl, oldtop, wblank, 2644 gdk_window_clear_area (wfixed->window, xl, oldtop, wbl, topdiff);
2576 topdiff); 2645 gdk_window_clear_area (wfixed->window, xr, oldtop, wbr, topdiff);
2577 gdk_window_clear_area (wfixed->window, xr, oldtop, wblank,
2578 topdiff);
2579 } 2646 }
2580 2647
2581 if (oldbottom > bottom) 2648 if (oldbottom > bottom)
2582 { 2649 {
2583 gdk_window_clear_area (wfixed->window, xl, bottom, wblank, 2650 gdk_window_clear_area (wfixed->window, xl, bottom, wbl,
2584 bottomdiff); 2651 bottomdiff);
2585 gdk_window_clear_area (wfixed->window, xr, bottom, wblank, 2652 gdk_window_clear_area (wfixed->window, xr, bottom, wbr,
2586 bottomdiff); 2653 bottomdiff);
2587 } 2654 }
2588 else if (oldbottom < bottom) 2655 else if (oldbottom < bottom)
2589 { 2656 {
2590 gdk_window_clear_area (wfixed->window, xl, oldbottom, wblank, 2657 gdk_window_clear_area (wfixed->window, xl, oldbottom, wbl,
2591 bottomdiff); 2658 bottomdiff);
2592 gdk_window_clear_area (wfixed->window, xr, oldbottom, wblank, 2659 gdk_window_clear_area (wfixed->window, xr, oldbottom, wbr,
2593 bottomdiff); 2660 bottomdiff);
2594 } 2661 }
2595 } 2662 }
@@ -2598,12 +2665,6 @@ xg_update_scrollbar_pos (f, scrollbar_id, top, left, width, height)
2598 gtk_fixed_move (GTK_FIXED (wfixed), wscroll, left, top); 2665 gtk_fixed_move (GTK_FIXED (wfixed), wscroll, left, top);
2599 gtk_widget_set_size_request (wscroll, width, gheight); 2666 gtk_widget_set_size_request (wscroll, width, gheight);
2600 2667
2601 gtk_container_set_reallocate_redraws (GTK_CONTAINER (wfixed), TRUE);
2602
2603 /* Make GTK draw the new sizes. We are not using a pure GTK event
2604 loop so we need to do this. */
2605 gdk_window_process_all_updates ();
2606
2607 SET_FRAME_GARBAGED (f); 2668 SET_FRAME_GARBAGED (f);
2608 cancel_mouse_face (f); 2669 cancel_mouse_face (f);
2609 } 2670 }
@@ -2620,15 +2681,14 @@ xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
2620 2681
2621 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); 2682 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2622 2683
2623 BLOCK_INPUT;
2624
2625 if (wscroll && NILP (bar->dragging)) 2684 if (wscroll && NILP (bar->dragging))
2626 { 2685 {
2627 GtkAdjustment *adj; 2686 GtkAdjustment *adj;
2628 gdouble shown; 2687 gdouble shown;
2629 gdouble top; 2688 gdouble top;
2630 int size, value; 2689 int size, value;
2631 int new_upper, new_step; 2690 int new_step;
2691 int changed = 0;
2632 2692
2633 adj = gtk_range_get_adjustment (GTK_RANGE (wscroll)); 2693 adj = gtk_range_get_adjustment (GTK_RANGE (wscroll));
2634 2694
@@ -2644,53 +2704,51 @@ xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
2644 top = 0, shown = 1; 2704 top = 0, shown = 1;
2645 else 2705 else
2646 { 2706 {
2647 shown = (gdouble) portion / whole;
2648 top = (gdouble) position / whole; 2707 top = (gdouble) position / whole;
2708 shown = (gdouble) portion / whole;
2649 } 2709 }
2650 2710
2651 size = shown * whole; 2711 size = shown * XG_SB_RANGE;
2652 size = min (size, whole); 2712 size = min (size, XG_SB_RANGE);
2653 size = max (size, 1); 2713 size = max (size, 1);
2654 2714
2655 value = top * whole; 2715 value = top * XG_SB_RANGE;
2656 value = min (value, whole - size); 2716 value = min (value, XG_SB_MAX - size);
2657 value = max (value, XG_SB_MIN); 2717 value = max (value, XG_SB_MIN);
2658 2718
2659 /* gtk_range_set_value invokes the callback. Set 2719 /* Assume all lines are of equal size. */
2660 ignore_gtk_scrollbar to make the callback do nothing */ 2720 new_step = size / max (1, FRAME_HEIGHT (f));
2661 xg_ignore_gtk_scrollbar = 1;
2662
2663 new_upper = max (whole, size);
2664 new_step = portion / max (1, FRAME_HEIGHT (f));
2665 2721
2666 if ((int) adj->page_size != size 2722 if ((int) adj->page_size != size
2667 || (int) adj->upper != new_upper
2668 || (int) adj->step_increment != new_step) 2723 || (int) adj->step_increment != new_step)
2669 { 2724 {
2670 adj->page_size = (int) size; 2725 adj->page_size = size;
2671 2726 adj->step_increment = new_step;
2672 gtk_range_set_range (GTK_RANGE (wscroll), adj->lower,
2673 (gdouble) new_upper);
2674
2675 /* Assume all lines are of equal size. */
2676 /* Assume a page increment is about 95% of the page size */ 2727 /* Assume a page increment is about 95% of the page size */
2677 gtk_range_set_increments (GTK_RANGE (wscroll), 2728 adj->page_increment = (int) (0.95*adj->page_size);
2678 portion / max (1, FRAME_HEIGHT (f)), 2729 changed = 1;
2679 (int) (0.95*adj->page_size));
2680
2681 } 2730 }
2682 2731
2683 if ((int) gtk_range_get_value (GTK_RANGE (wscroll)) != value) 2732 if (changed || (int) gtk_range_get_value (GTK_RANGE (wscroll)) != value)
2684 gtk_range_set_value (GTK_RANGE (wscroll), (gdouble)value); 2733 {
2734 GtkWidget *wfixed = f->output_data.x->edit_widget;
2685 2735
2686 xg_ignore_gtk_scrollbar = 0; 2736 BLOCK_INPUT;
2687 2737
2688 /* Make GTK draw the new thumb. We are not using a pure GTK event 2738 /* gtk_range_set_value invokes the callback. Set
2689 loop so we need to do this. */ 2739 ignore_gtk_scrollbar to make the callback do nothing */
2690 gdk_window_process_all_updates (); 2740 xg_ignore_gtk_scrollbar = 1;
2691 }
2692 2741
2693 UNBLOCK_INPUT; 2742 if ((int) gtk_range_get_value (GTK_RANGE (wscroll)) != value)
2743 gtk_range_set_value (GTK_RANGE (wscroll), (gdouble)value);
2744 else if (changed)
2745 gtk_adjustment_changed (adj);
2746
2747 xg_ignore_gtk_scrollbar = 0;
2748
2749 UNBLOCK_INPUT;
2750 }
2751 }
2694} 2752}
2695 2753
2696 2754
@@ -3098,7 +3156,7 @@ update_frame_tool_bar (f)
3098 3156
3099 /* Must force out update so changed images gets redrawn. */ 3157 /* Must force out update so changed images gets redrawn. */
3100 gdk_window_process_all_updates (); 3158 gdk_window_process_all_updates ();
3101 3159
3102 if (icon_list) g_list_free (icon_list); 3160 if (icon_list) g_list_free (icon_list);
3103 3161
3104 UNBLOCK_INPUT; 3162 UNBLOCK_INPUT;
diff --git a/src/gtkutil.h b/src/gtkutil.h
index 2284ff6e113..a53a3fd5bdc 100644
--- a/src/gtkutil.h
+++ b/src/gtkutil.h
@@ -30,8 +30,9 @@ Boston, MA 02111-1307, USA. */
30 30
31/* Minimum and maximum values used for GTK scroll bars */ 31/* Minimum and maximum values used for GTK scroll bars */
32 32
33#define XG_SB_MIN 0 33#define XG_SB_MIN 1
34#define XG_SB_MAX 10000000 34#define XG_SB_MAX 10000000
35#define XG_SB_RANGE (XG_SB_MAX-XG_SB_MIN)
35 36
36/* Key for data that is valid for menus in a frame */ 37/* Key for data that is valid for menus in a frame */
37#define XG_FRAME_DATA "emacs_frame" 38#define XG_FRAME_DATA "emacs_frame"
@@ -165,7 +166,9 @@ extern void xg_update_scrollbar_pos P_ ((FRAME_PTR f,
165 int top, 166 int top,
166 int left, 167 int left,
167 int width, 168 int width,
168 int height)); 169 int height,
170 int real_left,
171 int canon_width));
169 172
170extern void xg_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *bar, 173extern void xg_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *bar,
171 int portion, 174 int portion,
diff --git a/src/xterm.c b/src/xterm.c
index c8baf8ffe35..d414271091e 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -4780,7 +4780,9 @@ x_scroll_bar_create (w, top, left, width, height)
4780 top, 4780 top,
4781 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, 4781 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
4782 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, 4782 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4783 max (height, 1)); 4783 max (height, 1),
4784 left,
4785 width);
4784 xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar)); 4786 xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar));
4785#else /* not USE_GTK */ 4787#else /* not USE_GTK */
4786 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar); 4788 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
@@ -5030,7 +5032,9 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
5030 top, 5032 top,
5031 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, 5033 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5032 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, 5034 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
5033 max (height, 1)); 5035 max (height, 1),
5036 left,
5037 width);
5034#else /* not USE_GTK */ 5038#else /* not USE_GTK */
5035 5039
5036 /* Since toolkit scroll bars are smaller than the space reserved 5040 /* Since toolkit scroll bars are smaller than the space reserved