comparison src/gtkutil.c @ 50129:d0142038feaa

Reduce flicker in GTK scrollbars.
author Jan Djärv <jan.h.d@swipnet.se>
date Fri, 14 Mar 2003 18:34:18 +0000
parents 50df9e41f1a3
children 66a7f2850b56
comparison
equal deleted inserted replaced
50128:96cf90eadf8a 50129:d0142038feaa
33 #include "termhooks.h" 33 #include "termhooks.h"
34 #include <gdk/gdkkeysyms.h> 34 #include <gdk/gdkkeysyms.h>
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
41 ***********************************************************************/ 54 ***********************************************************************/
42 /* The timer for scroll bar repetition and menu bar timeouts. 55 /* The timer for scroll bar repetition and menu bar timeouts.
283 296
284 xg_frame_set_char_size (f, columns, rows); 297 xg_frame_set_char_size (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.
291 F is the frame to resize. 322 F is the frame to resize.
292 PIXELWIDTH, PIXELHEIGHT is the new size in pixels. */ 323 PIXELWIDTH, PIXELHEIGHT is the new size in pixels. */
312 343
313 all.width = pixelwidth; 344 all.width = pixelwidth;
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);
320 SET_FRAME_GARBAGED (f); 357 SET_FRAME_GARBAGED (f);
321 cancel_mouse_face (f); 358 cancel_mouse_face (f);
2328 return -1; 2365 return -1;
2329 } 2366 }
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;
2337 gpointer data; 2374 gpointer data;
2338 { 2375 {
2339 gpointer p; 2376 gpointer p;
2340 int id = (int)data; 2377 int id = (int)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);
2380 if (p) xfree (p);
2381 p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_POS);
2343 if (p) xfree (p); 2382 if (p) xfree (p);
2344 xg_remove_widget_from_map (id); 2383 xg_remove_widget_from_map (id);
2345 } 2384 }
2346 2385
2347 /* Callback for button press/release events. Used to start timer so that 2386 /* Callback for button press/release events. Used to start timer so that
2418 wscroll, 0, 0); 2457 wscroll, 0, 0);
2419 2458
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
2426 /* Make the scroll bar represented by SCROLLBAR_ID visible. */ 2475 /* Make the scroll bar represented by SCROLLBAR_ID visible. */
2427 void 2476 void
2465 GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id); 2514 GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id);
2466 2515
2467 if (wscroll) 2516 if (wscroll)
2468 { 2517 {
2469 int gheight = max (height, 1); 2518 int gheight = max (height, 1);
2470 2519 struct xg_last_sb_pos *last_pos
2471 gtk_fixed_move (GTK_FIXED (f->output_data.x->edit_widget), 2520 = g_object_get_data (G_OBJECT (wscroll), XG_LAST_SB_POS);
2472 wscroll, left, top); 2521 GtkWidget *wfixed = f->output_data.x->edit_widget;
2473 2522
2523 last_pos->portion = last_pos->position = last_pos->whole = -1;
2524 xg_ignore_next_thumb = 0;
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);
2528
2529 gtk_container_set_reallocate_redraws (GTK_CONTAINER (wfixed), TRUE);
2475 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 ();
2479 2534
2500 int portion, position, whole; 2555 int portion, position, whole;
2501 { 2556 {
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;
2511 gdouble top; 2573 gdouble top;
2512 int size, value; 2574 int size, value;
2536 adj->page_increment = (int) (0.95*adj->page_size); 2598 adj->page_increment = (int) (0.95*adj->page_size);
2537 2599
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;
2546 } 2615
2547 2616 /* Make sure the scroll bar is redrawn with new thumb */
2548 /* Make sure the scroll bar is redrawn with new thumb */ 2617 gtk_widget_queue_draw (wscroll);
2549 gtk_widget_queue_draw (wscroll); 2618 }
2619
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;
2553 } 2623 }
2554 2624