comparison src/toolbar-xlike.c @ 4917:fce43cb76a1c

xlike cleanup, documentation -------------------- ChangeLog entries follow: -------------------- man/ChangeLog addition: 2010-02-03 Ben Wing <ben@xemacs.org> * internals/internals.texi (Top): * internals/internals.texi (Evaluation; Stack Frames; Bindings): * internals/internals.texi (Ben's README): * internals/internals.texi (Consoles; Devices; Frames; Windows): * internals/internals.texi (Window Hierarchy): * internals/internals.texi (The Window Object): * internals/internals.texi (Modules for the Basic Displayable Lisp Objects): * internals/internals.texi (Window-System Support): * internals/internals.texi (Creating a Window-System Type): * internals/internals.texi (Discussion -- Garbage Collection): Update the part at the top about how to maintain the file with more tips. Add a chapter on "window-system support" describing in a general way how the support for different window systems/device types works, including the separation between device-independent and device-dependent parts, device methods, the specific device types and the "xlike" pseudo-type. src/ChangeLog addition: 2010-02-03 Ben Wing <ben@xemacs.org> * Makefile.in.in: * Makefile.in.in (x_objs): * Makefile.in.in (gtk_gui_objs): * console-xlike-inc.h: * depend: * device-x.c: * emacs.c: * gccache-gtk.h: * gccache-gtk.h (gc_cache_lookup): * gccache-x.c: * gccache-x.c (GCCACHE_HASH): * gccache-x.h: * toolbar-gtk.c: * toolbar-gtk.c (gtk_initialize_frame_toolbars): * toolbar-x.c: * toolbar-x.c (x_initialize_frame_toolbars): * toolbar-xlike.c: * toolbar-xlike.c (xlike_draw_blank_toolbar_button): * toolbar-xlike.c (xlike_output_toolbar_button): * toolbar-xlike.c (xlike_get_button_size): * toolbar-xlike.c (XLIKE_OUTPUT_BUTTONS_LOOP): * toolbar-xlike.c (xlike_output_toolbar): * toolbar-xlike.c (xlike_clear_toolbar): * toolbar-xlike.c (xlike_output_frame_toolbars): * toolbar-xlike.c (xlike_clear_frame_toolbars): * toolbar-xlike.c (xlike_redraw_exposed_toolbar): * toolbar-xlike.c (xlike_redraw_exposed_toolbars): * toolbar-xlike.c (xlike_redraw_frame_toolbars): * toolbar-xlike.h: * toolbar-xlike.h (xlike_clear_frame_toolbars): Rename some files to make them consistent with general naming rules: xgccache.c -> gccache-x.c xgccache.h -> gccache-x.h toolbar-common.c -> toolbar-xlike.c toolbar-common.h -> toolbar-xlike.h Fix include-file references. Also change the names of functions in now-named toolbar-xlike.c to be xlike_foo() instead of common_foo(). Add a longish comment in console-xlike-inc.h describing the "xlike" system, how it works and what the various files are used for.
author Ben Wing <ben@xemacs.org>
date Wed, 03 Feb 2010 02:46:50 -0600
parents src/toolbar-common.c@ad2f4ae9895b
children cbe181529c34
comparison
equal deleted inserted replaced
4916:a6c778975d7d 4917:fce43cb76a1c
1 /* toolbar implementation -- "Generic" (X or GTK) redisplay interface.
2 Copyright (C) 1995 Board of Trustees, University of Illinois.
3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 1995, 1996, 2002, 2010 Ben Wing.
5 Copyright (C) 1996 Chuck Thompson.
6
7 This file is part of XEmacs.
8
9 XEmacs is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
12 later version.
13
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with XEmacs; see the file COPYING. If not, write to
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
23
24 /* Synched up with: Not in FSF. */
25
26 #include <config.h>
27 #include "lisp.h"
28
29 #include "device-impl.h"
30 #include "faces.h"
31 #include "frame-impl.h"
32 #include "glyphs.h"
33 #include "toolbar.h"
34 #include "window.h"
35
36 /* This is used when we need to draw the toolbars ourselves -- on X or GTK.
37 On MS Windows, we use the built-in toolbar controls. */
38
39 /* Only a very few things need to differ based on the toolkit used.
40 **
41 ** Some of the routines used assert(FRAME_yyy_P(f)) checks, this is
42 ** now abstracted into __INTERNAL_APPROPRIATENESS_CHECK(). When we
43 ** add new window systems that use this code, we should either add a
44 ** new case here, or just remove the checks completely.
45 **
46 ** At least for X & GTK redraw_frame_toolbars() might end up getting
47 ** called before we are completely initialized. To avoid this, we use
48 ** the __INTERNAL_MAPPED_P(f) macro, that should return 0 if we should
49 ** not draw the toolbars yet. When we add new window systems that use
50 ** this code, we should add a new case here, if they need it.
51 **
52 ** When clearing the toolbar, it is nice to flush the drawing queue.
53 ** Use __INTERNAL_FLUSH to do this. It is passed a device.
54 */
55 #if defined(HAVE_GTK)
56 #include "console-gtk-impl.h"
57 #define __INTERNAL_MAPPED_P(f) GTK_WIDGET_REALIZED (FRAME_GTK_TEXT_WIDGET (f))
58 #define __INTERNAL_FLUSH(d) gdk_flush()
59 #define __INTERNAL_APPROPRIATENESS_CHECK(f) assert(FRAME_GTK_P (f))
60 #elif defined(HAVE_X_WINDOWS)
61 #include "console-x-impl.h"
62 #define __INTERNAL_MAPPED_P(f) XtIsRealized (FRAME_X_SHELL_WIDGET (f))
63 #define __INTERNAL_APPROPRIATENESS_CHECK(f) assert(FRAME_X_P (f))
64 #define __INTERNAL_FLUSH(d) XFlush (DEVICE_X_DISPLAY (d))
65 #else
66 #define __INTERNAL_MAPPED_P(f) ABORT()
67 #define __INTERNAL_APPROPRIATENESS_CHECK(f) ABORT()
68 #define __INTERNAL_FLUSH(f) ABORT()
69 #endif
70
71 #include "toolbar-xlike.h"
72
73 extern Lisp_Object Vtoolbar_shadow_thickness;
74
75 static void __prepare_button_area (struct frame *f,
76 struct toolbar_button *tb)
77 {
78 int sx = tb->x;
79 int sy = tb->y;
80 int swidth = tb->width;
81 int sheight = tb->height;
82 int border_width = tb->border_width;
83 int x_adj, width_adj, y_adj, height_adj;
84 struct device *d = XDEVICE (f->device);
85 Lisp_Object window = FRAME_LAST_NONMINIBUF_WINDOW (f);
86 struct window *w = XWINDOW (window);
87 int shadow_thickness;
88 int def_shadow_thickness = XINT (Fspecifier_instance(Vtoolbar_shadow_thickness, window, Qnil, Qnil));
89 face_index toolbar_findex;
90
91 if (tb->vertical)
92 {
93 x_adj = border_width;
94 width_adj = - 2 * border_width;
95 y_adj = height_adj = 0;
96 }
97 else
98 {
99 x_adj = width_adj = 0;
100 y_adj = border_width;
101 height_adj = - 2 * border_width;
102 }
103
104 toolbar_findex = get_builtin_face_cache_index (w, Vtoolbar_face);
105
106 /* Blank toolbar buttons that should be 3d will have EQ(tb->up_glyph, Qt)
107 ** Blank toolbar buttons that should be flat will have NILP (tb->up_glyph)
108 **
109 ** Real toolbar buttons will check tb->enabled && tb->down
110 */
111 if (EQ (Qt, tb->up_glyph))
112 {
113 shadow_thickness = def_shadow_thickness;
114 }
115 else if (NILP (tb->up_glyph))
116 {
117 shadow_thickness = 0;
118 }
119 else
120 {
121 if (tb->enabled)
122 {
123 if (tb->down)
124 shadow_thickness = -def_shadow_thickness;
125 else
126 shadow_thickness = def_shadow_thickness;
127 }
128 else
129 {
130 shadow_thickness = 0;
131 }
132 }
133
134 /* Blank the entire area. */
135 redisplay_clear_region (window, toolbar_findex,
136 sx + x_adj, sy + y_adj,
137 swidth + width_adj,
138 sheight + height_adj);
139
140 /* Draw the outline. */
141 if (shadow_thickness)
142 {
143 MAYBE_DEVMETH (d, bevel_area,
144 (w, toolbar_findex, sx + x_adj,
145 sy + y_adj, swidth + width_adj,
146 sheight + height_adj, abs(shadow_thickness),
147 EDGE_ALL, (shadow_thickness < 0) ? EDGE_BEVEL_IN
148 : EDGE_BEVEL_OUT));
149 }
150
151 /* Handle the borders... */
152 redisplay_clear_region (window, toolbar_findex,
153 sx, sy,
154 (tb->vertical ? border_width : swidth),
155 (tb->vertical ? sheight : border_width));
156 redisplay_clear_region (window, toolbar_findex,
157 (tb->vertical ? sx + swidth : sx),
158 (tb->vertical ? sy : sy + sheight),
159 (tb->vertical ? border_width : swidth),
160 (tb->vertical ? sheight : border_width));
161 }
162
163 #define xlike_draw_blank_toolbar_button(f,tb) __prepare_button_area (f,tb)
164
165 void
166 xlike_output_toolbar_button (struct frame *f, Lisp_Object button)
167 {
168 int shadow_thickness = 2;
169 int x_adj, y_adj, width_adj, height_adj;
170 struct device *d = XDEVICE (f->device);
171 Lisp_Object instance, window, glyph;
172 struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
173 struct Lisp_Image_Instance *p;
174 struct window *w;
175 int vertical = tb->vertical;
176 int border_width = tb->border_width;
177 face_index button_findex;
178
179 if (vertical)
180 {
181 x_adj = border_width;
182 width_adj = - 2 * border_width;
183 y_adj = 0;
184 height_adj = 0;
185 }
186 else
187 {
188 x_adj = 0;
189 width_adj = 0;
190 y_adj = border_width;
191 height_adj = - 2 * border_width;
192 }
193
194 window = FRAME_LAST_NONMINIBUF_WINDOW (f);
195 w = XWINDOW (window);
196
197 glyph = get_toolbar_button_glyph (w, tb);
198
199 if (tb->enabled)
200 {
201 if (tb->down)
202 {
203 shadow_thickness = -2;
204 }
205 else
206 {
207 shadow_thickness = 2;
208 }
209 }
210 else
211 {
212 shadow_thickness = 0;
213 }
214
215 /* #### It is currently possible for users to trash us by directly
216 changing the toolbar glyphs. Avoid crashing in that case. */
217 if (GLYPHP (glyph))
218 {
219 /* WARNING: this interface may change */
220 Lisp_Object face_list[2] = { XGLYPH_FACE (glyph), Vtoolbar_face };
221
222 button_findex = merge_face_list_to_cache_index (w, face_list, 2);
223 instance = glyph_image_instance (glyph, window, ERROR_ME_DEBUG_WARN, 1);
224 }
225 else
226 {
227 button_findex = get_builtin_face_cache_index (w, Vtoolbar_face);
228 instance = Qnil;
229 }
230
231 __prepare_button_area (f, tb);
232
233 if (IMAGE_INSTANCEP (instance))
234 {
235 int width = tb->width + width_adj - shadow_thickness * 2;
236 int height = tb->height + height_adj - shadow_thickness * 2;
237 int x_offset = x_adj + shadow_thickness;
238 int y_offset = y_adj + shadow_thickness;
239
240 p = XIMAGE_INSTANCE (instance);
241
242 if (IMAGE_INSTANCE_PIXMAP_TYPE_P (p))
243 {
244 struct display_box db;
245 struct display_glyph_area dga;
246
247 if (width > (int) IMAGE_INSTANCE_PIXMAP_WIDTH (p))
248 {
249 x_offset += ((int) (width - IMAGE_INSTANCE_PIXMAP_WIDTH (p))
250 / 2);
251 width = IMAGE_INSTANCE_PIXMAP_WIDTH (p);
252 }
253 if (height > (int) IMAGE_INSTANCE_PIXMAP_HEIGHT (p))
254 {
255 y_offset += ((int) (height - IMAGE_INSTANCE_PIXMAP_HEIGHT (p))
256 / 2);
257 height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p);
258 }
259
260 /* Draw exactly in the area specified... */
261 db.xpos = tb->x + x_offset;
262 db.ypos = tb->y + y_offset;
263 db.width = width;
264 db.height = height;
265
266 /* Display the whole glyph */
267 dga.xoffset = 0;
268 dga.yoffset = 0;
269 dga.width = width;
270 dga.height = height;
271
272 redisplay_output_pixmap (w, instance,
273 &db, &dga,
274 button_findex, 0, 0, 0, 0);
275 }
276 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_TEXT)
277 {
278 /* #### We need to make the face used configurable. */
279 struct face_cachel *cachel =
280 WINDOW_FACE_CACHEL (w, DEFAULT_INDEX);
281 struct display_line dl;
282 Lisp_Object string = IMAGE_INSTANCE_TEXT_STRING (p);
283 unsigned char charsets[NUM_LEADING_BYTES];
284 Ichar_dynarr *buf;
285 struct font_metric_info fm;
286
287 /* This could be true if we were called via the Expose event
288 handler. Mark the button as dirty and return
289 immediately. */
290 if (f->window_face_cache_reset)
291 {
292 tb->dirty = 1;
293 MARK_TOOLBAR_CHANGED;
294 return;
295 }
296 buf = Dynarr_new (Ichar);
297 convert_ibyte_string_into_ichar_dynarr
298 (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
299 find_charsets_in_ichar_string (charsets, Dynarr_atp (buf, 0),
300 Dynarr_length (buf));
301 ensure_face_cachel_complete (cachel, window, charsets);
302 face_cachel_charset_font_metric_info (cachel, charsets, &fm);
303
304 dl.ascent = fm.ascent;
305 dl.descent = fm.descent;
306 dl.ypos = tb->y + y_offset + fm.ascent;
307
308 if (fm.ascent + fm.descent <= height)
309 {
310 dl.ypos += (height - fm.ascent - fm.descent) / 2;
311 dl.clip = 0;
312 }
313 else
314 {
315 dl.clip = fm.ascent + fm.descent - height;
316 }
317
318 MAYBE_DEVMETH (d, output_string,
319 (w, &dl, buf, tb->x + x_offset, 0, 0, width,
320 button_findex, 0, 0, 0, 0));
321 Dynarr_free (buf);
322 }
323
324 /* We silently ignore the image if it isn't a pixmap or text. */
325 }
326
327 tb->dirty = 0;
328 }
329
330 static int
331 xlike_get_button_size (struct frame *f, Lisp_Object window,
332 struct toolbar_button *tb, int vert, int pos)
333 {
334 int shadow_thickness = 2;
335 int size;
336
337 if (tb->blank)
338 {
339 if (!NILP (tb->down_glyph))
340 size = XINT (tb->down_glyph);
341 else
342 size = DEFAULT_TOOLBAR_BLANK_SIZE;
343 }
344 else
345 {
346 struct window *w = XWINDOW (window);
347 Lisp_Object glyph = get_toolbar_button_glyph (w, tb);
348
349 /* Unless, of course, the user has done something stupid like
350 change the glyph out from under us. Use a blank placeholder
351 in that case. */
352 if (NILP (glyph))
353 return XINT (f->toolbar_size[pos]);
354
355 if (vert)
356 size = glyph_height (glyph, window);
357 else
358 size = glyph_width (glyph, window);
359 }
360
361 if (!size)
362 {
363 /* If the glyph doesn't have a size we'll insert a blank
364 placeholder instead. */
365 return XINT (f->toolbar_size[pos]);
366 }
367
368 size += shadow_thickness * 2;
369
370 return (size);
371 }
372
373 #define XLIKE_OUTPUT_BUTTONS_LOOP(left) \
374 do { \
375 while (!NILP (button)) \
376 { \
377 struct toolbar_button *tb = XTOOLBAR_BUTTON (button); \
378 int size, height, width; \
379 \
380 if (left && tb->pushright) \
381 break; \
382 \
383 size = xlike_get_button_size (f, window, tb, vert, pos); \
384 \
385 if (vert) \
386 { \
387 width = bar_width; \
388 if (y + size > max_pixpos) \
389 height = max_pixpos - y; \
390 else \
391 height = size; \
392 } \
393 else \
394 { \
395 if (x + size > max_pixpos) \
396 width = max_pixpos - x; \
397 else \
398 width = size; \
399 height = bar_height; \
400 } \
401 \
402 if (tb->x != x \
403 || tb->y != y \
404 || tb->width != width \
405 || tb->height != height \
406 || tb->dirty \
407 || f->clear) /* This is clearly necessary. */ \
408 { \
409 if (width && height) \
410 { \
411 tb->x = x; \
412 tb->y = y; \
413 tb->width = width; \
414 tb->height = height; \
415 tb->border_width = border_width; \
416 tb->vertical = vert; \
417 \
418 if (tb->blank || NILP (tb->up_glyph)) \
419 { \
420 xlike_draw_blank_toolbar_button (f, tb); \
421 } \
422 else \
423 xlike_output_toolbar_button (f, button); \
424 } \
425 } \
426 \
427 if (vert) \
428 y += height; \
429 else \
430 x += width; \
431 \
432 if ((vert && y == max_pixpos) || (!vert && x == max_pixpos)) \
433 button = Qnil; \
434 else \
435 button = tb->next; \
436 } \
437 } while (0)
438
439 #define SET_TOOLBAR_WAS_VISIBLE_FLAG(frame, pos, flag) \
440 do { \
441 switch (pos) \
442 { \
443 case TOP_TOOLBAR: \
444 (frame)->top_toolbar_was_visible = flag; \
445 break; \
446 case BOTTOM_TOOLBAR: \
447 (frame)->bottom_toolbar_was_visible = flag; \
448 break; \
449 case LEFT_TOOLBAR: \
450 (frame)->left_toolbar_was_visible = flag; \
451 break; \
452 case RIGHT_TOOLBAR: \
453 (frame)->right_toolbar_was_visible = flag; \
454 break; \
455 default: \
456 ABORT (); \
457 } \
458 } while (0)
459
460 static void
461 xlike_output_toolbar (struct frame *f, enum toolbar_pos pos)
462 {
463 int x, y, bar_width, bar_height, vert;
464 int max_pixpos, right_size, right_start, blank_size;
465 int border_width = FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, pos);
466 Lisp_Object button, window;
467 face_index toolbar_findex;
468
469 get_toolbar_coords (f, pos, &x, &y, &bar_width, &bar_height, &vert, 1);
470 window = FRAME_LAST_NONMINIBUF_WINDOW (f);
471 toolbar_findex = get_builtin_face_cache_index (XWINDOW (window), Vtoolbar_face);
472
473 /* Do the border */
474 redisplay_clear_region (window, toolbar_findex,
475 x, y,
476 (vert ? bar_width : border_width),
477 (vert ? border_width : bar_height));
478 redisplay_clear_region (window, toolbar_findex,
479 (vert ? x : x + bar_width - border_width),
480 (vert ? y + bar_height - border_width : y),
481 (vert ? bar_width : border_width),
482 (vert ? border_width : bar_height));
483
484 if (vert)
485 {
486 max_pixpos = y + bar_height - border_width;
487 y += border_width;
488 }
489 else
490 {
491 max_pixpos = x + bar_width - border_width;
492 x += border_width;
493 }
494
495 button = FRAME_TOOLBAR_BUTTONS (f, pos);
496 right_size = 0;
497
498 /* First loop over all of the buttons to determine how much room we
499 need for left hand and right hand buttons. This loop will also
500 make sure that all instances are instantiated so when we actually
501 output them they will come up immediately. */
502 while (!NILP (button))
503 {
504 struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
505 int size = xlike_get_button_size (f, window, tb, vert, pos);
506
507 if (tb->pushright)
508 right_size += size;
509
510 button = tb->next;
511 }
512
513 button = FRAME_TOOLBAR_BUTTONS (f, pos);
514
515 /* Loop over the left buttons, updating and outputting them. */
516 XLIKE_OUTPUT_BUTTONS_LOOP (1);
517
518 /* Now determine where the right buttons start. */
519 right_start = max_pixpos - right_size;
520 if (right_start < (vert ? y : x))
521 right_start = (vert ? y : x);
522
523 /* Output the blank which goes from the end of the left buttons to
524 the start of the right. */
525 blank_size = right_start - (vert ? y : x);
526 if (blank_size)
527 {
528 int height, width;
529
530 if (vert)
531 {
532 width = bar_width;
533 height = blank_size;
534 }
535 else
536 {
537 width = blank_size;
538 height = bar_height;
539 }
540
541 /*
542 * Use a 3D pushright separator only if there isn't a toolbar
543 * border. A flat separator meshes with the border and looks
544 * better.
545 */
546 if (1)
547 {
548 struct toolbar_button tb;
549
550 tb.x = x;
551 tb.y = y;
552 tb.width = width;
553 tb.height = height;
554 tb.border_width = border_width;
555 tb.vertical = vert;
556 tb.enabled = 1;
557 tb.up_glyph = border_width ? Qt : Qnil;
558
559 __prepare_button_area (f, &tb);
560 }
561
562 if (vert)
563 y += height;
564 else
565 x += width;
566 }
567
568 /* Loop over the right buttons, updating and outputting them. */
569 XLIKE_OUTPUT_BUTTONS_LOOP (0);
570
571 if (!vert)
572 {
573 Lisp_Object frame = wrap_frame (f);
574
575 redisplay_clear_region (frame,
576 DEFAULT_INDEX, FRAME_PIXWIDTH (f) - 1, y, 1,
577 bar_height);
578 }
579
580 SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 1);
581 __INTERNAL_FLUSH (XDEVICE (f->device));
582 }
583
584 static void
585 xlike_clear_toolbar (struct frame *f, enum toolbar_pos pos, int thickness_change)
586 {
587 Lisp_Object frame;
588 int x, y, width, height, vert;
589
590 get_toolbar_coords (f, pos, &x, &y, &width, &height, &vert, 1);
591 frame = wrap_frame (f);
592
593 /* The thickness_change parameter is used by the toolbar resize routines
594 to clear any excess toolbar if the size shrinks. */
595 if (thickness_change < 0)
596 {
597 if (pos == LEFT_TOOLBAR || pos == RIGHT_TOOLBAR)
598 {
599 x = x + width + thickness_change;
600 width = -thickness_change;
601 }
602 else
603 {
604 y = y + height + thickness_change;
605 height = -thickness_change;
606 }
607 }
608
609 SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 0);
610
611 redisplay_clear_region (frame, DEFAULT_INDEX, x, y, width, height);
612
613 __INTERNAL_FLUSH (XDEVICE (f->device));
614 }
615
616 void
617 xlike_output_frame_toolbars (struct frame *f)
618 {
619 __INTERNAL_APPROPRIATENESS_CHECK(f);
620
621 if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f))
622 xlike_output_toolbar (f, TOP_TOOLBAR);
623
624 if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f))
625 xlike_output_toolbar (f, BOTTOM_TOOLBAR);
626
627 if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f))
628 xlike_output_toolbar (f, LEFT_TOOLBAR);
629
630 if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f))
631 xlike_output_toolbar (f, RIGHT_TOOLBAR);
632 }
633
634 void
635 xlike_clear_frame_toolbars (struct frame *f)
636 {
637 __INTERNAL_APPROPRIATENESS_CHECK(f);
638
639 if (f->top_toolbar_was_visible
640 && !FRAME_REAL_TOP_TOOLBAR_VISIBLE (f))
641 xlike_clear_toolbar (f, TOP_TOOLBAR, 0);
642 if (f->bottom_toolbar_was_visible
643 && !FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f))
644 xlike_clear_toolbar (f, BOTTOM_TOOLBAR, 0);
645 if (f->left_toolbar_was_visible
646 && !FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f))
647 xlike_clear_toolbar (f, LEFT_TOOLBAR, 0);
648 if (f->right_toolbar_was_visible
649 && !FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f))
650 xlike_clear_toolbar (f, RIGHT_TOOLBAR, 0);
651 }
652
653 static void
654 xlike_redraw_exposed_toolbar (struct frame *f, enum toolbar_pos pos, int x, int y,
655 int width, int height)
656 {
657 int bar_x, bar_y, bar_width, bar_height, vert;
658 Lisp_Object button = FRAME_TOOLBAR_BUTTONS (f, pos);
659
660 get_toolbar_coords (f, pos, &bar_x, &bar_y, &bar_width, &bar_height,
661 &vert, 1);
662
663 if (((y + height) < bar_y) || (y > (bar_y + bar_height)))
664 return;
665 if (((x + width) < bar_x) || (x > (bar_x + bar_width)))
666 return;
667
668 while (!NILP (button))
669 {
670 struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
671
672 if (vert)
673 {
674 if (((tb->y + tb->height) > y) && (tb->y < (y + height)))
675 tb->dirty = 1;
676
677 /* If this is true we have gone past the exposed region. */
678 if (tb->y > (y + height))
679 break;
680 }
681 else
682 {
683 if (((tb->x + tb->width) > x) && (tb->x < (x + width)))
684 tb->dirty = 1;
685
686 /* If this is true we have gone past the exposed region. */
687 if (tb->x > (x + width))
688 break;
689 }
690
691 button = tb->next;
692 }
693
694 /* Even if none of the buttons is in the area, the blank region at
695 the very least must be because the first thing we did is verify
696 that some portion of the toolbar is in the exposed region. */
697 xlike_output_toolbar (f, pos);
698 }
699
700 void
701 xlike_redraw_exposed_toolbars (struct frame *f, int x, int y, int width,
702 int height)
703 {
704 __INTERNAL_APPROPRIATENESS_CHECK(f);
705
706 if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f))
707 xlike_redraw_exposed_toolbar (f, TOP_TOOLBAR, x, y, width, height);
708
709 if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f))
710 xlike_redraw_exposed_toolbar (f, BOTTOM_TOOLBAR, x, y, width, height);
711
712 if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f))
713 xlike_redraw_exposed_toolbar (f, LEFT_TOOLBAR, x, y, width, height);
714
715 if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f))
716 xlike_redraw_exposed_toolbar (f, RIGHT_TOOLBAR, x, y, width, height);
717 }
718
719 void
720 xlike_redraw_frame_toolbars (struct frame *f)
721 {
722 /* There are certain startup paths that lead to update_EmacsFrame in
723 faces.c being called before a new frame is fully initialized. In
724 particular before we have actually mapped it. That routine can
725 call this one. So, we need to make sure that the frame is
726 actually ready before we try and draw all over it. */
727 if (__INTERNAL_MAPPED_P(f))
728 xlike_redraw_exposed_toolbars (f, 0, 0, FRAME_PIXWIDTH (f),
729 FRAME_PIXHEIGHT (f));
730 }