Index: src/console.h =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/console.h,v retrieving revision 1.24.2.1.2.1 diff -u -r1.24.2.1.2.1 console.h --- src/console.h 2002/06/04 02:18:01 1.24.2.1.2.1 +++ src/console.h 2002/06/25 04:20:00 @@ -286,6 +286,7 @@ #ifdef HAVE_TOOLBARS /* toolbar methods */ void (*output_frame_toolbars_method) (struct frame *); + void (*clear_frame_toolbars_method) (struct frame *); void (*initialize_frame_toolbars_method) (struct frame *); void (*free_frame_toolbars_method) (struct frame *); void (*output_toolbar_button_method) (struct frame *, Lisp_Object); Index: src/device.h =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/device.h,v retrieving revision 1.9.2.1 diff -u -r1.9.2.1 device.h --- src/device.h 2001/10/23 08:35:31 1.9.2.1 +++ src/device.h 2002/06/25 04:20:00 @@ -167,6 +167,8 @@ unsigned int extents_changed :1; unsigned int faces_changed :1; unsigned int frame_changed :1; + unsigned int frame_layout_changed :1; /* The layout of frame + elements has changed. */ unsigned int glyphs_changed :1; unsigned int subwindows_changed :1; unsigned int subwindows_state_changed :1; @@ -424,6 +426,9 @@ #define MARK_DEVICE_FRAME_CHANGED(d) \ ((void) (frame_changed = (d)->frame_changed = 1)) + +#define MARK_DEVICE_FRAME_LAYOUT_CHANGED(d) \ + ((void) (frame_layout_changed = (d)->frame_layout_changed = 1)) #define MARK_DEVICE_WINDOWS_CHANGED(d) \ ((void) (windows_changed = (d)->windows_changed = 1)) Index: src/frame.h =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/frame.h,v retrieving revision 1.20 diff -u -r1.20 frame.h --- src/frame.h 2001/04/12 18:23:47 1.20 +++ src/frame.h 2002/06/25 04:20:00 @@ -188,6 +188,8 @@ unsigned int extents_changed :1; unsigned int faces_changed :1; unsigned int frame_changed :1; + unsigned int frame_layout_changed :1; /* The layout of frame + elements has changed. */ unsigned int subwindows_changed :1; unsigned int subwindows_state_changed :1; unsigned int glyphs_changed :1; @@ -455,6 +457,19 @@ } \ else \ frame_changed = 1; \ +} while (0) + +#define MARK_FRAME_LAYOUT_CHANGED(f) do { \ + struct frame *mfc_f = (f); \ + mfc_f->frame_layout_changed = 1; \ + mfc_f->modiff++; \ + if (!NILP (mfc_f->device)) \ + { \ + struct device *mfc_d = XDEVICE (mfc_f->device); \ + MARK_DEVICE_FRAME_LAYOUT_CHANGED (mfc_d); \ + } \ + else \ + frame_layout_changed = 1; \ } while (0) #define MARK_FRAME_WINDOWS_CHANGED(f) do { \ Index: src/gutter.c =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/gutter.c,v retrieving revision 1.2 diff -u -r1.2 gutter.c --- src/gutter.c 2001/04/12 18:23:55 1.2 +++ src/gutter.c 2002/06/25 04:20:01 @@ -585,6 +585,7 @@ pixel_to_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f), &width, &height); change_frame_size (f, height, width, 0); + MARK_FRAME_LAYOUT_CHANGED (f); } /* Mark sizes as up-to-date. */ @@ -594,7 +595,9 @@ void update_frame_gutter_geometry (struct frame *f) { - if (f->gutter_changed || f->windows_structure_changed) + if (f->gutter_changed + || f->frame_layout_changed + || f->windows_structure_changed) { enum gutter_pos pos; @@ -616,7 +619,7 @@ f->gutter_changed || f->glyphs_changed || f->size_changed || f->subwindows_changed || f->windows_changed || f->windows_structure_changed || - f->extents_changed) + f->extents_changed || f->frame_layout_changed) { enum gutter_pos pos; Index: src/redisplay.c =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/redisplay.c,v retrieving revision 1.62.2.1.2.5 diff -u -r1.62.2.1.2.5 redisplay.c --- src/redisplay.c 2002/04/25 16:08:11 1.62.2.1.2.5 +++ src/redisplay.c 2002/06/25 04:20:03 @@ -414,6 +414,10 @@ int toolbar_changed; int toolbar_changed_set; +/* Nonzero if some frame has changed the layout of internal elements + (gutters or toolbars). */ +int frame_layout_changed; + /* non-nil if any gutter has changed */ int gutter_changed; int gutter_changed_set; @@ -6511,8 +6515,13 @@ update_frame_menubars (f); #endif /* HAVE_MENUBARS */ #ifdef HAVE_TOOLBARS - /* Update the toolbars. */ - update_frame_toolbars (f); + /* Update the toolbars geometry. We don't update the toolbars + themselves at this point since the space they are trying to + occupy may currently by occupied by gutter elements. Instead we + update the geometry, then update the gutter geometry, then update + the gutters - which will cause mapped windows to be repositioned + - and finally update the toolbars. */ + update_frame_toolbars_geometry (f); #endif /* HAVE_TOOLBARS */ /* Gutter update proper has to be done inside display when no frame size changes can occur, thus we separately update the gutter @@ -6592,6 +6601,14 @@ update_frame_title (f); +#ifdef HAVE_TOOLBARS + /* Finally update the toolbars. It seems its possible to get in a + cycle between updating the gutter and the toolbars. Basically we + want to end up with both being up-to-date and this doesn't seem + possible in a single pass. */ + update_frame_toolbars (f); +#endif /* HAVE_TOOLBARS */ + CLASS_RESET_CHANGED_FLAGS (f); f->window_face_cache_reset = 0; f->echo_area_garbaged = 0; @@ -6606,6 +6623,7 @@ #### what happens if changes to other frames happen? */ unhold_one_frame_size_changes (f); + map_windows (f, call_redisplay_end_triggers, 0); return 0; Index: src/redisplay.h =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/redisplay.h,v retrieving revision 1.8.10.1 diff -u -r1.8.10.1 redisplay.h --- src/redisplay.h 2002/04/23 18:20:23 1.8.10.1 +++ src/redisplay.h 2002/06/25 04:20:04 @@ -480,6 +480,10 @@ /* Nonzero if some device has signaled that it wants to change size. */ extern int asynch_device_change_pending; +/* Nonzero if some frame has changed the layout of internal elements + (gutters or toolbars). */ +extern int frame_layout_changed; + /* Nonzero if any toolbar has changed. */ extern int toolbar_changed; extern int toolbar_changed_set; @@ -539,6 +543,7 @@ (p)->extents_changed = 0; \ (p)->faces_changed = 0; \ (p)->frame_changed = 0; \ + (p)->frame_layout_changed = 0; \ (p)->icon_changed = 0; \ (p)->menubar_changed = 0; \ (p)->modeline_changed = 0; \ @@ -557,6 +562,7 @@ clip_changed = 0; \ extents_changed = 0; \ frame_changed = 0; \ + frame_layout_changed = 0; \ icon_changed = 0; \ menubar_changed = 0; \ modeline_changed = 0; \ @@ -576,6 +582,7 @@ (p)->extents_changed || \ (p)->faces_changed || \ (p)->frame_changed || \ + (p)->frame_layout_changed || \ (p)->icon_changed || \ (p)->menubar_changed || \ (p)->modeline_changed || \ @@ -595,6 +602,7 @@ extents_changed || \ faces_changed || \ frame_changed || \ + frame_layout_changed || \ icon_changed || \ menubar_changed || \ modeline_changed || \ Index: src/toolbar-gtk.c =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/toolbar-gtk.c,v retrieving revision 1.2 diff -u -r1.2 toolbar-gtk.c --- src/toolbar-gtk.c 2001/04/12 18:24:24 1.2 +++ src/toolbar-gtk.c 2002/06/25 04:20:04 @@ -336,7 +336,8 @@ || tb->y != y \ || tb->width != width \ || tb->height != height \ - || tb->dirty) \ + || tb->dirty \ + || f->clear) /* This is clearly necessary. */ \ { \ if (width && height) \ { \ @@ -542,22 +543,30 @@ if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f)) gtk_output_toolbar (f, TOP_TOOLBAR); - else if (f->top_toolbar_was_visible) - gtk_clear_toolbar (f, TOP_TOOLBAR, 0); - if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f)) gtk_output_toolbar (f, BOTTOM_TOOLBAR); - else if (f->bottom_toolbar_was_visible) - gtk_clear_toolbar (f, BOTTOM_TOOLBAR, 0); - if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f)) gtk_output_toolbar (f, LEFT_TOOLBAR); - else if (f->left_toolbar_was_visible) - gtk_clear_toolbar (f, LEFT_TOOLBAR, 0); - if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f)) gtk_output_toolbar (f, RIGHT_TOOLBAR); - else if (f->right_toolbar_was_visible) +} + +static void +gtk_clear_frame_toolbars (struct frame *f) +{ + assert (FRAME_GTK_P (f)); + + if (f->top_toolbar_was_visible + && !FRAME_REAL_TOP_TOOLBAR_VISIBLE (f)) + gtk_clear_toolbar (f, TOP_TOOLBAR, 0); + if (f->bottom_toolbar_was_visible + && !FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f)) + gtk_clear_toolbar (f, BOTTOM_TOOLBAR, 0); + if (f->left_toolbar_was_visible + && !FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f)) + gtk_clear_toolbar (f, LEFT_TOOLBAR, 0); + if (f->right_toolbar_was_visible + && !FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f)) gtk_clear_toolbar (f, RIGHT_TOOLBAR, 0); } @@ -663,6 +672,7 @@ console_type_create_toolbar_gtk (void) { CONSOLE_HAS_METHOD (gtk, output_frame_toolbars); + CONSOLE_HAS_METHOD (gtk, clear_frame_toolbars); CONSOLE_HAS_METHOD (gtk, initialize_frame_toolbars); CONSOLE_HAS_METHOD (gtk, free_frame_toolbars); CONSOLE_HAS_METHOD (gtk, output_toolbar_button); Index: src/toolbar-msw.c =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/toolbar-msw.c,v retrieving revision 1.14 diff -u -r1.14 toolbar-msw.c --- src/toolbar-msw.c 2001/04/12 18:24:24 1.14 +++ src/toolbar-msw.c 2002/06/25 04:20:04 @@ -22,7 +22,7 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* This implementation by Andy Piper , with bits +/* This implementation by Andy Piper , with bits borrowed from toolbar-x.c */ /* Synched up with: Not in FSF. */ @@ -544,22 +544,30 @@ if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f)) mswindows_output_toolbar (f, TOP_TOOLBAR); - else if (f->top_toolbar_was_visible) - mswindows_clear_toolbar (f, TOP_TOOLBAR, 0); - if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f)) mswindows_output_toolbar (f, BOTTOM_TOOLBAR); - else if (f->bottom_toolbar_was_visible) - mswindows_clear_toolbar (f, BOTTOM_TOOLBAR, 0); - if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f)) mswindows_output_toolbar (f, LEFT_TOOLBAR); - else if (f->left_toolbar_was_visible) - mswindows_clear_toolbar (f, LEFT_TOOLBAR, 0); - if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f)) mswindows_output_toolbar (f, RIGHT_TOOLBAR); - else if (f->right_toolbar_was_visible) +} + +static void +mswindows_clear_frame_toolbars (struct frame *f) +{ + assert (FRAME_MSWINDOWS_P (f)); + + if (f->top_toolbar_was_visible + && !FRAME_REAL_TOP_TOOLBAR_VISIBLE (f)) + mswindows_clear_toolbar (f, TOP_TOOLBAR, 0); + if (f->bottom_toolbar_was_visible + && !FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f)) + mswindows_clear_toolbar (f, BOTTOM_TOOLBAR, 0); + if (f->left_toolbar_was_visible + && !FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f)) + mswindows_clear_toolbar (f, LEFT_TOOLBAR, 0); + if (f->right_toolbar_was_visible + && !FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f)) mswindows_clear_toolbar (f, RIGHT_TOOLBAR, 0); } @@ -641,6 +649,7 @@ console_type_create_toolbar_mswindows (void) { CONSOLE_HAS_METHOD (mswindows, output_frame_toolbars); + CONSOLE_HAS_METHOD (mswindows, clear_frame_toolbars); CONSOLE_HAS_METHOD (mswindows, initialize_frame_toolbars); CONSOLE_HAS_METHOD (mswindows, free_frame_toolbars); CONSOLE_HAS_METHOD (mswindows, redraw_exposed_toolbars); Index: src/toolbar-x.c =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/toolbar-x.c,v retrieving revision 1.13 diff -u -r1.13 toolbar-x.c --- src/toolbar-x.c 2001/04/12 18:24:24 1.13 +++ src/toolbar-x.c 2002/06/25 04:20:04 @@ -348,7 +348,8 @@ || tb->y != y \ || tb->width != width \ || tb->height != height \ - || tb->dirty) \ + || tb->dirty \ + || f->clear) /* This is clearly necessary. */ \ { \ if (width && height) \ { \ @@ -557,22 +558,30 @@ if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f)) x_output_toolbar (f, TOP_TOOLBAR); - else if (f->top_toolbar_was_visible) - x_clear_toolbar (f, TOP_TOOLBAR, 0); - if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f)) x_output_toolbar (f, BOTTOM_TOOLBAR); - else if (f->bottom_toolbar_was_visible) - x_clear_toolbar (f, BOTTOM_TOOLBAR, 0); - if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f)) x_output_toolbar (f, LEFT_TOOLBAR); - else if (f->left_toolbar_was_visible) - x_clear_toolbar (f, LEFT_TOOLBAR, 0); - if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f)) x_output_toolbar (f, RIGHT_TOOLBAR); - else if (f->right_toolbar_was_visible) +} + +static void +x_clear_frame_toolbars (struct frame *f) +{ + assert (FRAME_X_P (f)); + + if (f->top_toolbar_was_visible + && !FRAME_REAL_TOP_TOOLBAR_VISIBLE (f)) + x_clear_toolbar (f, TOP_TOOLBAR, 0); + if (f->bottom_toolbar_was_visible + && !FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f)) + x_clear_toolbar (f, BOTTOM_TOOLBAR, 0); + if (f->left_toolbar_was_visible + && !FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f)) + x_clear_toolbar (f, LEFT_TOOLBAR, 0); + if (f->right_toolbar_was_visible + && !FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f)) x_clear_toolbar (f, RIGHT_TOOLBAR, 0); } @@ -793,6 +802,7 @@ console_type_create_toolbar_x (void) { CONSOLE_HAS_METHOD (x, output_frame_toolbars); + CONSOLE_HAS_METHOD (x, clear_frame_toolbars); CONSOLE_HAS_METHOD (x, initialize_frame_toolbars); CONSOLE_HAS_METHOD (x, free_frame_toolbars); CONSOLE_HAS_METHOD (x, output_toolbar_button); Index: src/toolbar.c =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/toolbar.c,v retrieving revision 1.19 diff -u -r1.19 toolbar.c --- src/toolbar.c 2001/04/12 18:24:25 1.19 +++ src/toolbar.c 2002/06/25 04:20:05 @@ -712,13 +712,26 @@ set_frame_toolbar (f, RIGHT_TOOLBAR); } +/* Update the toolbar geometry separately from actually displaying the + toolbar. This is necessary because both the gutter and the toolbar + are competing for redisplay cycles and, unfortunately, gutter + updates happen late in the game. Firstly they are done inside of + redisplay proper and secondly subcontrols may not get moved until + the next screen refresh. Only after subcontrols have been moved to + their final destinations can we be certain of updating the + toolbar. Under X this probably is exacerbated by the toolbar button + dirty flags which prevent updates happening when they possibly + should. */ void -update_frame_toolbars (struct frame *f) +update_frame_toolbars_geometry (struct frame *f) { struct device *d = XDEVICE (f->device); if (DEVICE_SUPPORTS_TOOLBARS_P (d) - && (f->toolbar_changed || f->frame_changed || f->clear)) + && (f->toolbar_changed + || f->frame_layout_changed + || f->frame_changed + || f->clear)) { int pos; @@ -738,18 +751,39 @@ pixel_to_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f), &width, &height); change_frame_size (f, height, width, 0); + MARK_FRAME_LAYOUT_CHANGED (f); break; } - for (pos = 0; pos < 4; pos++) + for (pos = 0; pos < 4; pos++) { f->current_toolbar_size[pos] = FRAME_REAL_TOOLBAR_SIZE (f, pos); + } /* Removed the check for the minibuffer here. We handle this more correctly now by consistently using FRAME_LAST_NONMINIBUF_WINDOW instead of FRAME_SELECTED_WINDOW throughout the toolbar code. */ compute_frame_toolbars_data (f); + + /* Clear the previous toolbar locations. If we do it later + (after redisplay) we end up clearing what we have just + displayed. */ + MAYBE_DEVMETH (d, clear_frame_toolbars, (f)); + } +} +/* Actually redisplay the toolbar buttons. */ +void +update_frame_toolbars (struct frame *f) +{ + struct device *d = XDEVICE (f->device); + + if (DEVICE_SUPPORTS_TOOLBARS_P (d) + && (f->toolbar_changed + || f->frame_layout_changed + || f->frame_changed + || f->clear)) + { DEVMETH (d, output_frame_toolbars, (f)); } Index: src/toolbar.h =================================================================== RCS file: /pack/xemacscvs/XEmacs/xemacs/src/toolbar.h,v retrieving revision 1.10 diff -u -r1.10 toolbar.h --- src/toolbar.h 2001/04/12 18:24:25 1.10 +++ src/toolbar.h 2002/06/25 04:20:05 @@ -100,6 +100,7 @@ extern Lisp_Object Vtoolbar_size[4]; extern Lisp_Object Vtoolbar_border_width[4]; void update_frame_toolbars (struct frame *f); +void update_frame_toolbars_geometry (struct frame *f); void init_frame_toolbars (struct frame *f); void init_device_toolbars (struct device *d); void init_global_toolbars (struct device *d);