Mercurial > emacs
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 |