/[emacs]/emacs/src/gtkutil.c
ViewVC logotype

Diff of /emacs/src/gtkutil.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.19 by jhd, Fri Mar 14 19:13:17 2003 UTC revision 1.20 by jhd, Mon Mar 17 23:03:53 2003 UTC
# Line 37  Boston, MA 02111-1307, USA.  */ Line 37  Boston, MA 02111-1307, USA.  */
37    (PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f))    (PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f))
38    
39    
 /* Key to save a struct xg_last_sb_pos in the scroll bars.  */  
 #define XG_LAST_SB_POS "emacs_last_sb_pos"  
   
   
 /*  Use this in scroll bars to keep track of when redraw is really needed.  */  
 struct xg_last_sb_pos  
 {  
   int portion, position, whole;  
 };  
   
   
40    
41  /***********************************************************************  /***********************************************************************
42                        Utility functions                        Utility functions
# Line 298  xg_resize_outer_widget (f, columns, rows Line 287  xg_resize_outer_widget (f, columns, rows
287    gdk_window_process_all_updates ();    gdk_window_process_all_updates ();
288  }  }
289    
 /* When the Emacs frame is resized, we must call this function for each  
    child of our GtkFixed widget.  The children are scroll bars and  
    we invalidate the last position data here so it will be properly  
    redrawn later when xg_update_scrollbar_pos is called.  
    W is the child widget.  
    CLIENT_DATA is not used.  */  
 static handle_fixed_child (w, client_data)  
      GtkWidget *w;  
      gpointer client_data;  
 {  
   struct xg_last_sb_pos *last_pos  
     = g_object_get_data (G_OBJECT (w), XG_LAST_SB_POS);  
   if (last_pos)  
     {  
       last_pos->portion = last_pos->position = last_pos->whole = .1;  
     }  
 }  
   
290  /* This gets called after the frame F has been cleared.  Since that is  /* This gets called after the frame F has been cleared.  Since that is
291     done with X calls, we need to redraw GTK widget (scroll bars).  */     done with X calls, we need to redraw GTK widget (scroll bars).  */
292  void  void
# Line 326  xg_frame_cleared (f) Line 297  xg_frame_cleared (f)
297    
298    if (wfixed)    if (wfixed)
299      {      {
       gtk_container_foreach (GTK_CONTAINER (wfixed),  
                              (GtkCallback) handle_fixed_child,  
                              NULL);  
300        gtk_container_set_reallocate_redraws (GTK_CONTAINER (wfixed), TRUE);        gtk_container_set_reallocate_redraws (GTK_CONTAINER (wfixed), TRUE);
301        gdk_window_process_all_updates ();        gdk_window_process_all_updates ();
302      }      }
# Line 2277  free_frame_menubar (f) Line 2245  free_frame_menubar (f)
2245     to indicate that callback should do nothing.  */     to indicate that callback should do nothing.  */
2246  int xg_ignore_gtk_scrollbar;  int xg_ignore_gtk_scrollbar;
2247    
 /* After we send a scroll bar event,  x_set_toolkit_scroll_bar_thumb will  
    be called.  For some reason that needs to be debugged, it gets called  
    with bad values.  Thus, we set this variable to ignore those calls.  */  
 int xg_ignore_next_thumb;  
   
2248  /* SET_SCROLL_BAR_X_WINDOW assumes the second argument fits in  /* SET_SCROLL_BAR_X_WINDOW assumes the second argument fits in
2249     32 bits.  But we want to store pointers, and they may be larger     32 bits.  But we want to store pointers, and they may be larger
2250     than 32 bits.  Keep a mapping from integer index to widget pointers     than 32 bits.  Keep a mapping from integer index to widget pointers
# Line 2391  xg_gtk_scroll_destroy (widget, data) Line 2354  xg_gtk_scroll_destroy (widget, data)
2354    
2355    p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA);    p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA);
2356    if (p) xfree (p);    if (p) xfree (p);
   p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_POS);  
   if (p) xfree (p);  
2357    xg_remove_widget_from_map (id);    xg_remove_widget_from_map (id);
2358  }  }
2359    
2360  /* Callback for button press/release events.  Used to start timer so that  /* Callback for button press/release events.  Used to start timer so that
2361     the scroll bar repetition timer in GTK gets handeled.     the scroll bar repetition timer in GTK gets handeled.
2362       Also, sets bar->dragging to Qnil when dragging (button release) is done.
2363     WIDGET is the scroll bar widget the event is for (not used).     WIDGET is the scroll bar widget the event is for (not used).
2364     EVENT contains the event.     EVENT contains the event.
2365     USER_DATA is 0 (not used).     USER_DATA points to the struct scrollbar structure.
2366    
2367     Returns FALSE to tell GTK that it shall continue propagate the event     Returns FALSE to tell GTK that it shall continue propagate the event
2368     to widgets.  */     to widgets.  */
# Line 2412  scroll_bar_button_cb (widget, event, use Line 2374  scroll_bar_button_cb (widget, event, use
2374  {  {
2375    if (event->type == GDK_BUTTON_PRESS && ! xg_timer)    if (event->type == GDK_BUTTON_PRESS && ! xg_timer)
2376      xg_start_timer ();      xg_start_timer ();
2377    else if (event->type == GDK_BUTTON_RELEASE && xg_timer)    else if (event->type == GDK_BUTTON_RELEASE)
2378      xg_stop_timer ();      {
2379          struct scroll_bar *bar = (struct scroll_bar *) user_data;
2380          if (xg_timer) xg_stop_timer ();
2381          bar->dragging = Qnil;
2382        }
2383      
2384    return FALSE;    return FALSE;
2385  }  }
2386    
# Line 2460  xg_create_scroll_bar (f, bar, scroll_cal Line 2426  xg_create_scroll_bar (f, bar, scroll_cal
2426    g_signal_connect (G_OBJECT (wscroll),    g_signal_connect (G_OBJECT (wscroll),
2427                      "button-press-event",                      "button-press-event",
2428                      G_CALLBACK (scroll_bar_button_cb),                      G_CALLBACK (scroll_bar_button_cb),
2429                      0);                      (gpointer)bar);
2430    g_signal_connect (G_OBJECT (wscroll),    g_signal_connect (G_OBJECT (wscroll),
2431                      "button-release-event",                      "button-release-event",
2432                      G_CALLBACK (scroll_bar_button_cb),                      G_CALLBACK (scroll_bar_button_cb),
2433                      0);                      (gpointer)bar);
2434    
2435    gtk_fixed_put (GTK_FIXED (f->output_data.x->edit_widget),    gtk_fixed_put (GTK_FIXED (f->output_data.x->edit_widget),
2436                   wscroll, 0, 0);                   wscroll, -1, -1);
2437    
2438    /* Set the cursor to an arrow.  */    /* Set the cursor to an arrow.  */
2439    xg_set_cursor (wscroll, &xg_left_ptr_cursor);    xg_set_cursor (wscroll, &xg_left_ptr_cursor);
2440    
   /* Allocate a place to hold the last scollbar size.  GTK redraw for  
      scroll bars is basically clear all, and then redraw.  This flickers  
      a lot since xg_update_scrollbar_pos gets called on every cursor move  
      and a lot more places.  So we have this to check if a redraw really  
      is needed.  */  
   struct xg_last_sb_pos *last_pos  
     = (struct xg_last_sb_pos *) xmalloc (sizeof (struct xg_last_sb_pos));  
   last_pos->portion = last_pos->position = last_pos->whole = -1;  
   g_object_set_data (G_OBJECT (wscroll), XG_LAST_SB_POS, last_pos);  
     
2441    SET_SCROLL_BAR_X_WINDOW (bar, scroll_id);    SET_SCROLL_BAR_X_WINDOW (bar, scroll_id);
2442  }  }
2443    
# Line 2509  xg_remove_scroll_bar (f, scrollbar_id) Line 2465  xg_remove_scroll_bar (f, scrollbar_id)
2465      }      }
2466  }  }
2467    
2468    /* Find left/top for widget W in GtkFixed widget WFIXED.  */
2469    static void
2470    xg_find_top_left_in_fixed (w, wfixed, left, top)
2471         GtkWidget *w, *wfixed;
2472         int *left, *top;
2473    {
2474      GList *iter;
2475    
2476      for (iter = GTK_FIXED (wfixed)->children; iter; iter = g_list_next (iter))
2477        {
2478          GtkFixedChild *child = (GtkFixedChild *) iter->data;
2479    
2480          if (child->widget == w)
2481            {
2482              *left = child->x;
2483              *top = child->y;
2484              return;
2485            }
2486        }
2487    
2488      /* Shall never end up here.  */
2489      abort ();
2490    }
2491    
2492  /* Update the position of the vertical scroll bar represented by SCROLLBAR_ID  /* Update the position of the vertical scroll bar represented by SCROLLBAR_ID
2493     in frame F.     in frame F.
# Line 2525  xg_update_scrollbar_pos (f, scrollbar_id Line 2504  xg_update_scrollbar_pos (f, scrollbar_id
2504  {  {
2505    
2506    GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id);    GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id);
2507      
2508    if (wscroll)    if (wscroll)
2509      {      {
       int gheight = max (height, 1);  
       struct xg_last_sb_pos *last_pos  
         = g_object_get_data (G_OBJECT (wscroll), XG_LAST_SB_POS);  
2510        GtkWidget *wfixed = f->output_data.x->edit_widget;        GtkWidget *wfixed = f->output_data.x->edit_widget;
2511          int gheight = max (height, 1);
2512          int canon_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
2513          int winextra = canon_width > width ? (canon_width - width) / 2 : 0;
2514          int bottom = top + gheight;
2515    
2516        last_pos->portion = last_pos->position = last_pos->whole = -1;        gint slider_width;
2517        xg_ignore_next_thumb = 0;        int oldtop, oldleft, oldbottom;
2518          GtkRequisition req;
2519          
2520          /* Get old values.  */
2521          xg_find_top_left_in_fixed (wscroll, wfixed, &oldleft, &oldtop);
2522          gtk_widget_size_request (wscroll, &req);
2523          oldbottom = oldtop + req.height;
2524    
2525          /* Scroll bars in GTK has a fixed width, so if we say width 16, it
2526             will only be its fixed width (14 is default) anyway, the rest is
2527             blank.  We are drawing the mode line across scroll bars when
2528             the frame is split:
2529                                   |bar| |fringe|
2530                                  ----------------
2531                                  mode line
2532                                  ----------------
2533                                   |bar| |fringe|
2534    
2535             When we "unsplit" the frame:
2536    
2537                                   |bar| |fringe|
2538                                  -|   |-|      |
2539                                  m¦   |i|      |
2540                                  -|   |-|      |
2541                                   |   | |      |
2542    
2543    
2544             the remains of the mode line can be seen in these blank spaces.
2545             So we must clear them explicitly.
2546             GTK scroll bars should do that, but they don't.
2547             Also, the scroll bar canonical width may be wider than the width
2548             passed in here.  */
2549    
2550          if (oldtop != -1 && oldleft != -1)
2551            {
2552              int gtkextra;
2553              int xl, xr, wblank;
2554              int bottomdiff, topdiff;
2555    
2556              gtk_widget_style_get (wscroll, "slider_width", &slider_width, NULL);
2557              gtkextra = width > slider_width ? (width - slider_width) / 2 : 0;
2558            
2559              xl = left - winextra;
2560              wblank = gtkextra + winextra;
2561              xr = left + gtkextra + slider_width;
2562              bottomdiff = abs (oldbottom - bottom);
2563              topdiff = abs (oldtop - top);
2564    
2565              if (oldtop > top)
2566                {
2567                  gdk_window_clear_area (wfixed->window, xl, top, wblank, topdiff);
2568                  gdk_window_clear_area (wfixed->window, xr, top, wblank, topdiff);
2569                }
2570              else if (oldtop < top)
2571                {
2572                  gdk_window_clear_area (wfixed->window, xl, oldtop, wblank,
2573                                         topdiff);
2574                  gdk_window_clear_area (wfixed->window, xr, oldtop, wblank,
2575                                         topdiff);
2576                }
2577    
2578              if (oldbottom > bottom)
2579                {
2580                  gdk_window_clear_area (wfixed->window, xl, bottom, wblank,
2581                                         bottomdiff);
2582                  gdk_window_clear_area (wfixed->window, xr, bottom, wblank,
2583                                         bottomdiff);
2584                }
2585              else if (oldbottom < bottom)
2586                {
2587                  gdk_window_clear_area (wfixed->window, xl, oldbottom, wblank,
2588                                         bottomdiff);
2589                  gdk_window_clear_area (wfixed->window, xr, oldbottom, wblank,
2590                                         bottomdiff);
2591                }
2592            }
2593    
2594          /* Move and resize to new values.  */
2595        gtk_fixed_move (GTK_FIXED (wfixed), wscroll, left, top);        gtk_fixed_move (GTK_FIXED (wfixed), wscroll, left, top);
2596        gtk_widget_set_size_request (wscroll, width, gheight);        gtk_widget_set_size_request (wscroll, width, gheight);
2597    
2598        gtk_container_set_reallocate_redraws (GTK_CONTAINER (wfixed), TRUE);        gtk_container_set_reallocate_redraws (GTK_CONTAINER (wfixed), TRUE);
2599    
2600        /* Must force out update so wscroll gets the resize.        /* Make GTK draw the new sizes.  We are not using a pure GTK event
2601           Otherwise, the gdk_window_clear clears the old window size.  */           loop so we need to do this.  */
       gdk_window_process_all_updates ();  
   
       /* The scroll bar doesn't explicitly redraw the whole window  
          when a resize occurs.  Since the scroll bar seems to be fixed  
          in width it doesn't fill the space reserved, so we must clear  
          the whole window.  */  
       gdk_window_clear (wscroll->window);  
   
       /* Since we are not using a pure gtk event loop, we must force out  
          pending update events with this call.  */  
2602        gdk_window_process_all_updates ();        gdk_window_process_all_updates ();
2603    
2604        SET_FRAME_GARBAGED (f);        SET_FRAME_GARBAGED (f);
# Line 2570  xg_set_toolkit_scroll_bar_thumb (bar, po Line 2616  xg_set_toolkit_scroll_bar_thumb (bar, po
2616    GtkWidget *wscroll = xg_get_widget_from_map (SCROLL_BAR_X_WINDOW (bar));    GtkWidget *wscroll = xg_get_widget_from_map (SCROLL_BAR_X_WINDOW (bar));
2617    
2618    FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));    FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
   struct xg_last_sb_pos *last_pos  
     = (wscroll ? g_object_get_data (G_OBJECT (wscroll), XG_LAST_SB_POS) : 0);  
2619    
2620    BLOCK_INPUT;    BLOCK_INPUT;
2621    if (wscroll  
2622        && ! xg_ignore_next_thumb    if (wscroll && NILP (bar->dragging))
       && last_pos  
       && (last_pos->portion != portion  
           || last_pos->position != position  
           || last_pos->whole != whole))  
2623      {      {
2624        GtkAdjustment *adj;        GtkAdjustment *adj;
2625        gdouble shown;        gdouble shown;
# Line 2588  xg_set_toolkit_scroll_bar_thumb (bar, po Line 2628  xg_set_toolkit_scroll_bar_thumb (bar, po
2628    
2629        adj = gtk_range_get_adjustment (GTK_RANGE (wscroll));        adj = gtk_range_get_adjustment (GTK_RANGE (wscroll));
2630    
2631          /* We do the same as for MOTIF in xterm.c, assume 30 chars per line
2632             rather than the real portion value.  This makes the thumb less likely
2633             to resize and that looks better.  */
2634          portion = XFASTINT (XWINDOW (bar->window)->height) * 30;
2635          /* When the thumb is at the bottom, position == whole.
2636             So we need to increase `whole' to make space for the thumb.  */
2637          whole += portion;
2638    
2639        if (whole <= 0)        if (whole <= 0)
2640          top = 0, shown = 1;          top = 0, shown = 1;
2641        else        else
# Line 2604  xg_set_toolkit_scroll_bar_thumb (bar, po Line 2652  xg_set_toolkit_scroll_bar_thumb (bar, po
2652        value = min (value, whole - size);        value = min (value, whole - size);
2653        value = max (value, XG_SB_MIN);        value = max (value, XG_SB_MIN);
2654    
       adj->upper = max (whole, size);  
2655        adj->page_size = (int)size;        adj->page_size = (int)size;
2656    
       /* Assume a page increment is about 95% of the page size  */  
       adj->page_increment = (int) (0.95*adj->page_size);  
   
       /* Assume all lines are equal.  */  
       adj->step_increment = portion / max (1, FRAME_HEIGHT (f));  
   
       if (last_pos)  
         {  
           last_pos->portion = portion;  
           last_pos->position = position;  
           last_pos->whole = whole;  
         }  
   
2657        /* gtk_range_set_value invokes the callback.  Set        /* gtk_range_set_value invokes the callback.  Set
2658           ignore_gtk_scrollbar to make the callback do nothing  */           ignore_gtk_scrollbar to make the callback do nothing  */
2659        xg_ignore_gtk_scrollbar = 1;        xg_ignore_gtk_scrollbar = 1;
2660    
2661          gtk_range_set_range (GTK_RANGE (wscroll), adj->lower, max (whole, size));
2662    
2663          /* Assume all lines are of equal size.  */
2664          /* Assume a page increment is about 95% of the page size  */
2665          gtk_range_set_increments (GTK_RANGE (wscroll),
2666                                    portion / max (1, FRAME_HEIGHT (f)),
2667                                    (int) (0.95*adj->page_size));
2668    
2669        gtk_range_set_value (GTK_RANGE (wscroll), (gdouble)value);        gtk_range_set_value (GTK_RANGE (wscroll), (gdouble)value);
2670        xg_ignore_gtk_scrollbar = 0;        xg_ignore_gtk_scrollbar = 0;
2671    
2672        /* Make sure the scroll bar is redrawn with new thumb  */        /* Make GTK draw the new thumb.  We are not using a pure GTK event
2673        gtk_widget_queue_draw (wscroll);           loop so we need to do this.  */
2674          gdk_window_process_all_updates ();
2675      }      }
2676    
   gdk_window_process_all_updates ();  
   xg_ignore_next_thumb = 0;  
2677    UNBLOCK_INPUT;    UNBLOCK_INPUT;
2678  }  }
2679    
# Line 3079  void Line 3121  void
3121  xg_initialize ()  xg_initialize ()
3122  {  {
3123    xg_ignore_gtk_scrollbar = 0;    xg_ignore_gtk_scrollbar = 0;
   xg_ignore_next_thumb = 0;  
3124    xg_left_ptr_cursor = 0;    xg_left_ptr_cursor = 0;
3125    xg_did_tearoff = 0;    xg_did_tearoff = 0;
3126    

Legend:
Removed from v.1.19  
changed lines
  Added in v.1.20

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26