diff options
| author | Jan Djärv | 2003-03-14 18:34:18 +0000 |
|---|---|---|
| committer | Jan Djärv | 2003-03-14 18:34:18 +0000 |
| commit | cea9be546103f4ab47fb4a18bc3db06bbd49efe5 (patch) | |
| tree | cf0ba8a8dd55bd0b902525ac8bad539ea047d24c | |
| parent | 7c928b8f67452391dbc5e8fec46dc0193dae07e5 (diff) | |
| download | emacs-cea9be546103f4ab47fb4a18bc3db06bbd49efe5.tar.gz emacs-cea9be546103f4ab47fb4a18bc3db06bbd49efe5.zip | |
Reduce flicker in GTK scrollbars.
| -rw-r--r-- | src/ChangeLog | 14 | ||||
| -rw-r--r-- | src/gtkutil.c | 82 |
2 files changed, 90 insertions, 6 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 36cd7d86f9f..c962b2b6f63 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,17 @@ | |||
| 1 | 2003-03-14 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> | ||
| 2 | |||
| 3 | * gtkutil.c (struct xg_last_sb_pos): New structure. | ||
| 4 | (handle_fixed_child): New function. | ||
| 5 | (xg_resize_widgets): Call handle_fixed_child on all scroll bar widgets | ||
| 6 | and force a redraw on them. | ||
| 7 | (xg_gtk_scroll_destroy): Free struct xg_last_sb_pos also. | ||
| 8 | (xg_create_scroll_bar): Add struct xg_last_sb_pos to scroll bar | ||
| 9 | so we can avoid unneeded redraws. | ||
| 10 | (xg_update_scrollbar_pos): Invalidate data in xg_last_sb_pos | ||
| 11 | and force a redraw on the scroll bar. | ||
| 12 | (xg_set_toolkit_scroll_bar_thumb): Do not change/redraw scroll bar | ||
| 13 | if xg_last_sb_pos shows the positions are up to date. | ||
| 14 | |||
| 1 | 2003-03-13 Kenichi Handa <handa@m17n.org> | 15 | 2003-03-13 Kenichi Handa <handa@m17n.org> |
| 2 | 16 | ||
| 3 | * coding.c (Fdetect_coding_region): Fix docstring. | 17 | * coding.c (Fdetect_coding_region): Fix docstring. |
diff --git a/src/gtkutil.c b/src/gtkutil.c index cb7bb1d869a..51cc2f1cf1b 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c | |||
| @@ -35,6 +35,19 @@ Boston, MA 02111-1307, USA. */ | |||
| 35 | 35 | ||
| 36 | #define FRAME_TOTAL_PIXEL_HEIGHT(f) \ | 36 | #define FRAME_TOTAL_PIXEL_HEIGHT(f) \ |
| 37 | (PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f)) | 37 | (PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f)) |
| 38 | |||
| 39 | |||
| 40 | /* Key to save a struct xg_last_sb_pos in the scroll bars. */ | ||
| 41 | #define XG_LAST_SB_POS "emacs_last_sb_pos" | ||
| 42 | |||
| 43 | |||
| 44 | /* Use this in scroll bars to keep track of when redraw is really needed. */ | ||
| 45 | struct xg_last_sb_pos | ||
| 46 | { | ||
| 47 | int portion, position, whole; | ||
| 48 | }; | ||
| 49 | |||
| 50 | |||
| 38 | 51 | ||
| 39 | /*********************************************************************** | 52 | /*********************************************************************** |
| 40 | Utility functions | 53 | Utility functions |
| @@ -285,6 +298,24 @@ xg_resize_outer_widget (f, columns, rows) | |||
| 285 | gdk_window_process_all_updates (); | 298 | gdk_window_process_all_updates (); |
| 286 | } | 299 | } |
| 287 | 300 | ||
| 301 | /* When the Emacs frame is resized, we must call this function for each | ||
| 302 | child of our GtkFixed widget. The children are scroll bars and | ||
| 303 | we invalidate the last position data here so it will be properly | ||
| 304 | redrawn later when xg_update_scrollbar_pos is called. | ||
| 305 | W is the child widget. | ||
| 306 | CLIENT_DATA is not used. */ | ||
| 307 | static handle_fixed_child (w, client_data) | ||
| 308 | GtkWidget *w; | ||
| 309 | gpointer client_data; | ||
| 310 | { | ||
| 311 | struct xg_last_sb_pos *last_pos | ||
| 312 | = g_object_get_data (G_OBJECT (w), XG_LAST_SB_POS); | ||
| 313 | if (last_pos) | ||
| 314 | { | ||
| 315 | last_pos->portion = last_pos->position = last_pos->whole = .1; | ||
| 316 | } | ||
| 317 | } | ||
| 318 | |||
| 288 | /* Function to handle resize of our widgets. Since Emacs has some layouts | 319 | /* Function to handle resize of our widgets. Since Emacs has some layouts |
| 289 | that does not fit well with GTK standard containers, we do most layout | 320 | that does not fit well with GTK standard containers, we do most layout |
| 290 | manually. | 321 | manually. |
| @@ -314,6 +345,12 @@ xg_resize_widgets (f, pixelwidth, pixelheight) | |||
| 314 | all.height = pixelheight - mbheight - tbheight; | 345 | all.height = pixelheight - mbheight - tbheight; |
| 315 | 346 | ||
| 316 | gtk_widget_size_allocate (x->edit_widget, &all); | 347 | gtk_widget_size_allocate (x->edit_widget, &all); |
| 348 | |||
| 349 | gtk_container_foreach (GTK_CONTAINER (x->edit_widget), | ||
| 350 | (GtkCallback) handle_fixed_child, | ||
| 351 | NULL); | ||
| 352 | gtk_container_set_reallocate_redraws (GTK_CONTAINER (x->edit_widget), | ||
| 353 | TRUE); | ||
| 317 | gdk_window_process_all_updates (); | 354 | gdk_window_process_all_updates (); |
| 318 | 355 | ||
| 319 | change_frame_size (f, rows, columns, 0, 1, 0); | 356 | change_frame_size (f, rows, columns, 0, 1, 0); |
| @@ -2330,7 +2367,7 @@ xg_get_scroll_id_for_window (wid) | |||
| 2330 | 2367 | ||
| 2331 | /* Callback invoked when scroll bar WIDGET is destroyed. | 2368 | /* Callback invoked when scroll bar WIDGET is destroyed. |
| 2332 | DATA is the index into id_to_widget for WIDGET. | 2369 | DATA is the index into id_to_widget for WIDGET. |
| 2333 | We free pointer to last scroll bar value here and remove the index. */ | 2370 | We free pointer to last scroll bar values here and remove the index. */ |
| 2334 | static void | 2371 | static void |
| 2335 | xg_gtk_scroll_destroy (widget, data) | 2372 | xg_gtk_scroll_destroy (widget, data) |
| 2336 | GtkWidget *widget; | 2373 | GtkWidget *widget; |
| @@ -2341,6 +2378,8 @@ xg_gtk_scroll_destroy (widget, data) | |||
| 2341 | 2378 | ||
| 2342 | p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA); | 2379 | p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA); |
| 2343 | if (p) xfree (p); | 2380 | if (p) xfree (p); |
| 2381 | p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_POS); | ||
| 2382 | if (p) xfree (p); | ||
| 2344 | xg_remove_widget_from_map (id); | 2383 | xg_remove_widget_from_map (id); |
| 2345 | } | 2384 | } |
| 2346 | 2385 | ||
| @@ -2420,6 +2459,16 @@ xg_create_scroll_bar (f, bar, scroll_callback, scroll_bar_name) | |||
| 2420 | /* Set the cursor to an arrow. */ | 2459 | /* Set the cursor to an arrow. */ |
| 2421 | xg_set_cursor (wscroll, &xg_left_ptr_cursor); | 2460 | xg_set_cursor (wscroll, &xg_left_ptr_cursor); |
| 2422 | 2461 | ||
| 2462 | /* Allocate a place to hold the last scollbar size. GTK redraw for | ||
| 2463 | scroll bars is basically clear all, and then redraw. This flickers | ||
| 2464 | a lot since xg_update_scrollbar_pos gets called on every cursor move | ||
| 2465 | and a lot more places. So we have this to check if a redraw really | ||
| 2466 | is needed. */ | ||
| 2467 | struct xg_last_sb_pos *last_pos | ||
| 2468 | = (struct xg_last_sb_pos *) xmalloc (sizeof (struct xg_last_sb_pos)); | ||
| 2469 | last_pos->portion = last_pos->position = last_pos->whole = -1; | ||
| 2470 | g_object_set_data (G_OBJECT (wscroll), XG_LAST_SB_POS, last_pos); | ||
| 2471 | |||
| 2423 | SET_SCROLL_BAR_X_WINDOW (bar, scroll_id); | 2472 | SET_SCROLL_BAR_X_WINDOW (bar, scroll_id); |
| 2424 | } | 2473 | } |
| 2425 | 2474 | ||
| @@ -2467,12 +2516,18 @@ xg_update_scrollbar_pos (f, scrollbar_id, top, left, width, height) | |||
| 2467 | if (wscroll) | 2516 | if (wscroll) |
| 2468 | { | 2517 | { |
| 2469 | int gheight = max (height, 1); | 2518 | int gheight = max (height, 1); |
| 2519 | struct xg_last_sb_pos *last_pos | ||
| 2520 | = g_object_get_data (G_OBJECT (wscroll), XG_LAST_SB_POS); | ||
| 2521 | GtkWidget *wfixed = f->output_data.x->edit_widget; | ||
| 2470 | 2522 | ||
| 2471 | gtk_fixed_move (GTK_FIXED (f->output_data.x->edit_widget), | 2523 | last_pos->portion = last_pos->position = last_pos->whole = -1; |
| 2472 | wscroll, left, top); | 2524 | xg_ignore_next_thumb = 0; |
| 2473 | 2525 | ||
| 2526 | gtk_fixed_move (GTK_FIXED (wfixed), wscroll, left, top); | ||
| 2474 | gtk_widget_set_size_request (wscroll, width, gheight); | 2527 | gtk_widget_set_size_request (wscroll, width, gheight); |
| 2475 | 2528 | ||
| 2529 | gtk_container_set_reallocate_redraws (GTK_CONTAINER (wfixed), TRUE); | ||
| 2530 | |||
| 2476 | /* Must force out update so wscroll gets the resize. | 2531 | /* Must force out update so wscroll gets the resize. |
| 2477 | Otherwise, the gdk_window_clear clears the old window size. */ | 2532 | Otherwise, the gdk_window_clear clears the old window size. */ |
| 2478 | gdk_window_process_all_updates (); | 2533 | gdk_window_process_all_updates (); |
| @@ -2502,9 +2557,16 @@ xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole) | |||
| 2502 | GtkWidget *wscroll = xg_get_widget_from_map (SCROLL_BAR_X_WINDOW (bar)); | 2557 | GtkWidget *wscroll = xg_get_widget_from_map (SCROLL_BAR_X_WINDOW (bar)); |
| 2503 | 2558 | ||
| 2504 | FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); | 2559 | FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); |
| 2560 | struct xg_last_sb_pos *last_pos | ||
| 2561 | = (wscroll ? g_object_get_data (G_OBJECT (wscroll), XG_LAST_SB_POS) : 0); | ||
| 2505 | 2562 | ||
| 2506 | BLOCK_INPUT; | 2563 | BLOCK_INPUT; |
| 2507 | if (wscroll && ! xg_ignore_next_thumb) | 2564 | if (wscroll |
| 2565 | && ! xg_ignore_next_thumb | ||
| 2566 | && last_pos | ||
| 2567 | && (last_pos->portion != portion | ||
| 2568 | || last_pos->position != position | ||
| 2569 | || last_pos->whole != whole)) | ||
| 2508 | { | 2570 | { |
| 2509 | GtkAdjustment *adj; | 2571 | GtkAdjustment *adj; |
| 2510 | gdouble shown; | 2572 | gdouble shown; |
| @@ -2538,15 +2600,23 @@ xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole) | |||
| 2538 | /* Assume all lines are equal. */ | 2600 | /* Assume all lines are equal. */ |
| 2539 | adj->step_increment = portion / max (1, FRAME_HEIGHT (f)); | 2601 | adj->step_increment = portion / max (1, FRAME_HEIGHT (f)); |
| 2540 | 2602 | ||
| 2603 | if (last_pos) | ||
| 2604 | { | ||
| 2605 | last_pos->portion = portion; | ||
| 2606 | last_pos->position = position; | ||
| 2607 | last_pos->whole = whole; | ||
| 2608 | } | ||
| 2609 | |||
| 2541 | /* gtk_range_set_value invokes the callback. Set | 2610 | /* gtk_range_set_value invokes the callback. Set |
| 2542 | ignore_gtk_scrollbar to make the callback do nothing */ | 2611 | ignore_gtk_scrollbar to make the callback do nothing */ |
| 2543 | xg_ignore_gtk_scrollbar = 1; | 2612 | xg_ignore_gtk_scrollbar = 1; |
| 2544 | gtk_range_set_value (GTK_RANGE (wscroll), (gdouble)value); | 2613 | gtk_range_set_value (GTK_RANGE (wscroll), (gdouble)value); |
| 2545 | xg_ignore_gtk_scrollbar = 0; | 2614 | xg_ignore_gtk_scrollbar = 0; |
| 2615 | |||
| 2616 | /* Make sure the scroll bar is redrawn with new thumb */ | ||
| 2617 | gtk_widget_queue_draw (wscroll); | ||
| 2546 | } | 2618 | } |
| 2547 | 2619 | ||
| 2548 | /* Make sure the scroll bar is redrawn with new thumb */ | ||
| 2549 | gtk_widget_queue_draw (wscroll); | ||
| 2550 | gdk_window_process_all_updates (); | 2620 | gdk_window_process_all_updates (); |
| 2551 | xg_ignore_next_thumb = 0; | 2621 | xg_ignore_next_thumb = 0; |
| 2552 | UNBLOCK_INPUT; | 2622 | UNBLOCK_INPUT; |