comparison src/toolbar-x.c @ 744:8ae895c67ce7

[xemacs-hg @ 2002-02-04 15:44:37 by wmperry] Enable generic toolbar support for X11. Added new toolbar-shadow-thickness specifier.
author wmperry
date Mon, 04 Feb 2002 15:44:52 +0000
parents fdefd0186b75
children 79c6ff3eef26
comparison
equal deleted inserted replaced
743:968a715e8c6f 744:8ae895c67ce7
37 #include "faces.h" 37 #include "faces.h"
38 #include "frame.h" 38 #include "frame.h"
39 #include "toolbar.h" 39 #include "toolbar.h"
40 #include "window.h" 40 #include "window.h"
41 41
42 static void 42 #include "toolbar-common.h"
43 x_draw_blank_toolbar_button (struct frame *f, int x, int y, int width,
44 int height, int threed, int border_width,
45 int vertical)
46 {
47 struct device *d = XDEVICE (f->device);
48 EmacsFrame ef = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
49 int shadow_thickness = ef->emacs_frame.toolbar_shadow_thickness;
50 int sx = x, sy = y, swidth = width, sheight = height;
51 43
52 Display *dpy = DEVICE_X_DISPLAY (d); 44 /* We should really create a 'common' console type and fill it with
53 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f)); 45 ** all the shared code. We would then just use
54 GC top_shadow_gc, bottom_shadow_gc, background_gc; 46 ** CONSOLE_INHERITS_METHOD(x,common,blah)
55 47 */
56 background_gc = FRAME_X_TOOLBAR_BLANK_BACKGROUND_GC (f); 48 #define x_output_frame_toolbars common_output_frame_toolbars
57 49 #define x_output_toolbar_button common_output_toolbar_button
58 if (threed) 50 #define x_redraw_exposed_toolbars common_redraw_exposed_toolbars
59 { 51 #define x_redraw_frame_toolbars common_redraw_frame_toolbars
60 top_shadow_gc = FRAME_X_TOOLBAR_TOP_SHADOW_GC (f);
61 bottom_shadow_gc = FRAME_X_TOOLBAR_BOTTOM_SHADOW_GC (f);
62 }
63 else
64 {
65 top_shadow_gc = background_gc;
66 bottom_shadow_gc = background_gc;
67 }
68
69 if (vertical)
70 {
71 sx += border_width;
72 swidth -= 2 * border_width;
73 }
74 else
75 {
76 sy += border_width;
77 sheight -= 2 * border_width;
78 }
79
80 /* Draw the outline. */
81 x_output_shadows (f, sx, sy, swidth, sheight, top_shadow_gc,
82 bottom_shadow_gc, background_gc, shadow_thickness,
83 EDGE_ALL);
84
85 /* Blank the middle. */
86 XFillRectangle (dpy, x_win, background_gc, sx + shadow_thickness,
87 sy + shadow_thickness, swidth - shadow_thickness * 2,
88 sheight - shadow_thickness * 2);
89
90 /* Do the border */
91 XFillRectangle (dpy, x_win, background_gc, x, y,
92 (vertical ? border_width : width),
93 (vertical ? height : border_width));
94 XFillRectangle (dpy, x_win, background_gc,
95 (vertical ? sx + swidth : x),
96 (vertical ? y : sy + sheight),
97 (vertical ? border_width : width),
98 (vertical ? height : border_width));
99 }
100
101 static void
102 x_output_toolbar_button (struct frame *f, Lisp_Object button)
103 {
104 struct device *d = XDEVICE (f->device);
105 EmacsFrame ef = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
106 int shadow_thickness = ef->emacs_frame.toolbar_shadow_thickness;
107 int x_adj, y_adj, width_adj, height_adj;
108
109 Display *dpy = DEVICE_X_DISPLAY (d);
110 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f));
111 GC top_shadow_gc, bottom_shadow_gc, background_gc;
112 Lisp_Object instance, frame, window, glyph;
113 struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
114 Lisp_Image_Instance *p;
115 struct window *w;
116 int vertical = tb->vertical;
117 int border_width = tb->border_width;
118
119 if (vertical)
120 {
121 x_adj = border_width;
122 width_adj = - 2 * border_width;
123 y_adj = 0;
124 height_adj = 0;
125 }
126 else
127 {
128 x_adj = 0;
129 width_adj = 0;
130 y_adj = border_width;
131 height_adj = - 2 * border_width;
132 }
133
134 XSETFRAME (frame, f);
135 window = FRAME_LAST_NONMINIBUF_WINDOW (f);
136 w = XWINDOW (window);
137
138 glyph = get_toolbar_button_glyph (w, tb);
139
140 if (tb->enabled)
141 {
142 if (tb->down)
143 {
144 top_shadow_gc = FRAME_X_TOOLBAR_BOTTOM_SHADOW_GC (f);
145 bottom_shadow_gc = FRAME_X_TOOLBAR_TOP_SHADOW_GC (f);
146 }
147 else
148 {
149 top_shadow_gc = FRAME_X_TOOLBAR_TOP_SHADOW_GC (f);
150 bottom_shadow_gc = FRAME_X_TOOLBAR_BOTTOM_SHADOW_GC (f);
151 }
152 }
153 else
154 {
155 top_shadow_gc = FRAME_X_TOOLBAR_BLANK_BACKGROUND_GC (f);
156 bottom_shadow_gc = FRAME_X_TOOLBAR_BLANK_BACKGROUND_GC (f);
157 }
158 background_gc = FRAME_X_TOOLBAR_BLANK_BACKGROUND_GC (f);
159
160 /* Draw the outline. */
161 x_output_shadows (f, tb->x + x_adj, tb->y + y_adj,
162 tb->width + width_adj, tb->height + height_adj,
163 top_shadow_gc,
164 bottom_shadow_gc, background_gc, shadow_thickness,
165 EDGE_ALL);
166
167 /* Clear the pixmap area. */
168 XFillRectangle (dpy, x_win, background_gc, tb->x + x_adj + shadow_thickness,
169 tb->y + y_adj + shadow_thickness,
170 tb->width + width_adj - shadow_thickness * 2,
171 tb->height + height_adj - shadow_thickness * 2);
172
173 /* Do the border. */
174 XFillRectangle (dpy, x_win, background_gc, tb->x, tb->y,
175 (vertical ? border_width : tb->width),
176 (vertical ? tb->height : border_width));
177
178 XFillRectangle (dpy, x_win, background_gc,
179 (vertical ? tb->x + tb->width - border_width : tb->x),
180 (vertical ? tb->y : tb->y + tb->height - border_width),
181 (vertical ? border_width : tb->width),
182 (vertical ? tb->height : border_width));
183
184 background_gc = FRAME_X_TOOLBAR_PIXMAP_BACKGROUND_GC (f);
185
186 /* #### It is currently possible for users to trash us by directly
187 changing the toolbar glyphs. Avoid crashing in that case. */
188 if (GLYPHP (glyph))
189 instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1);
190 else
191 instance = Qnil;
192
193 if (IMAGE_INSTANCEP (instance))
194 {
195 int width = tb->width + width_adj - shadow_thickness * 2;
196 int height = tb->height + height_adj - shadow_thickness * 2;
197 int x_offset = x_adj + shadow_thickness;
198 int y_offset = y_adj + shadow_thickness;
199
200 p = XIMAGE_INSTANCE (instance);
201
202 if (IMAGE_INSTANCE_PIXMAP_TYPE_P (p))
203 {
204 if (width > (int) IMAGE_INSTANCE_PIXMAP_WIDTH (p))
205 {
206 x_offset += ((int) (width - IMAGE_INSTANCE_PIXMAP_WIDTH (p))
207 / 2);
208 width = IMAGE_INSTANCE_PIXMAP_WIDTH (p);
209 }
210 if (height > (int) IMAGE_INSTANCE_PIXMAP_HEIGHT (p))
211 {
212 y_offset += ((int) (height - IMAGE_INSTANCE_PIXMAP_HEIGHT (p))
213 / 2);
214 height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p);
215 }
216
217 x_output_x_pixmap (f, XIMAGE_INSTANCE (instance), tb->x + x_offset,
218 tb->y + y_offset, 0, 0, width, height,
219 0, 0, background_gc);
220 }
221 else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_TEXT)
222 {
223 /* #### We need to make the face used configurable. */
224 struct face_cachel *cachel =
225 WINDOW_FACE_CACHEL (w, DEFAULT_INDEX);
226 struct display_line dl;
227 Lisp_Object string = IMAGE_INSTANCE_TEXT_STRING (p);
228 unsigned char charsets[NUM_LEADING_BYTES];
229 Emchar_dynarr *buf;
230 struct font_metric_info fm;
231
232 /* This could be true if we were called via the Expose event
233 handler. Mark the button as dirty and return
234 immediately. */
235 if (f->window_face_cache_reset)
236 {
237 tb->dirty = 1;
238 MARK_TOOLBAR_CHANGED;
239 return;
240 }
241 buf = Dynarr_new (Emchar);
242 convert_intbyte_string_into_emchar_dynarr
243 (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
244 find_charsets_in_emchar_string (charsets, Dynarr_atp (buf, 0),
245 Dynarr_length (buf));
246 ensure_face_cachel_complete (cachel, window, charsets);
247 face_cachel_charset_font_metric_info (cachel, charsets, &fm);
248
249 dl.ascent = fm.ascent;
250 dl.descent = fm.descent;
251 dl.ypos = tb->y + y_offset + fm.ascent;
252
253 if (fm.ascent + fm.descent <= height)
254 {
255 dl.ypos += (height - fm.ascent - fm.descent) / 2;
256 dl.clip = 0;
257 }
258 else
259 {
260 dl.clip = fm.ascent + fm.descent - height;
261 }
262
263 x_output_string (w, &dl, buf, tb->x + x_offset, 0, 0, width,
264 DEFAULT_INDEX, 0, 0, 0, 0);
265 Dynarr_free (buf);
266 }
267
268 /* We silently ignore the image if it isn't a pixmap or text. */
269 }
270
271 tb->dirty = 0;
272 }
273
274 static int
275 x_get_button_size (struct frame *f, Lisp_Object window,
276 struct toolbar_button *tb, int vert, int pos)
277 {
278 EmacsFrame ef = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
279 int shadow_thickness = ef->emacs_frame.toolbar_shadow_thickness;
280 int size;
281
282 if (tb->blank)
283 {
284 if (!NILP (tb->down_glyph))
285 size = XINT (tb->down_glyph);
286 else
287 size = DEFAULT_TOOLBAR_BLANK_SIZE;
288 }
289 else
290 {
291 struct window *w = XWINDOW (window);
292 Lisp_Object glyph = get_toolbar_button_glyph (w, tb);
293
294 /* Unless, of course, the user has done something stupid like
295 change the glyph out from under us. Use a blank placeholder
296 in that case. */
297 if (NILP (glyph))
298 return XINT (f->toolbar_size[pos]);
299
300 if (vert)
301 size = glyph_height (glyph, window);
302 else
303 size = glyph_width (glyph, window);
304 }
305
306 if (!size)
307 {
308 /* If the glyph doesn't have a size we'll insert a blank
309 placeholder instead. */
310 return XINT (f->toolbar_size[pos]);
311 }
312
313 size += shadow_thickness * 2;
314
315 return (size);
316 }
317
318 #define X_OUTPUT_BUTTONS_LOOP(left) \
319 do { \
320 while (!NILP (button)) \
321 { \
322 struct toolbar_button *tb = XTOOLBAR_BUTTON (button); \
323 int size, height, width; \
324 \
325 if (left && tb->pushright) \
326 break; \
327 \
328 size = x_get_button_size (f, window, tb, vert, pos); \
329 \
330 if (vert) \
331 { \
332 width = bar_width; \
333 if (y + size > max_pixpos) \
334 height = max_pixpos - y; \
335 else \
336 height = size; \
337 } \
338 else \
339 { \
340 if (x + size > max_pixpos) \
341 width = max_pixpos - x; \
342 else \
343 width = size; \
344 height = bar_height; \
345 } \
346 \
347 if (tb->x != x \
348 || tb->y != y \
349 || tb->width != width \
350 || tb->height != height \
351 || tb->dirty) \
352 { \
353 if (width && height) \
354 { \
355 tb->x = x; \
356 tb->y = y; \
357 tb->width = width; \
358 tb->height = height; \
359 tb->border_width = border_width; \
360 tb->vertical = vert; \
361 \
362 if (tb->blank || NILP (tb->up_glyph)) \
363 { \
364 int threed = (EQ (Qt, tb->up_glyph) ? 1 : 0); \
365 x_draw_blank_toolbar_button (f, x, y, width, \
366 height, threed, \
367 border_width, vert); \
368 } \
369 else \
370 x_output_toolbar_button (f, button); \
371 } \
372 } \
373 \
374 if (vert) \
375 y += height; \
376 else \
377 x += width; \
378 \
379 if ((vert && y == max_pixpos) || (!vert && x == max_pixpos)) \
380 button = Qnil; \
381 else \
382 button = tb->next; \
383 } \
384 } while (0)
385
386 #define SET_TOOLBAR_WAS_VISIBLE_FLAG(frame, pos, flag) \
387 do { \
388 switch (pos) \
389 { \
390 case TOP_TOOLBAR: \
391 (frame)->top_toolbar_was_visible = flag; \
392 break; \
393 case BOTTOM_TOOLBAR: \
394 (frame)->bottom_toolbar_was_visible = flag; \
395 break; \
396 case LEFT_TOOLBAR: \
397 (frame)->left_toolbar_was_visible = flag; \
398 break; \
399 case RIGHT_TOOLBAR: \
400 (frame)->right_toolbar_was_visible = flag; \
401 break; \
402 default: \
403 abort (); \
404 } \
405 } while (0)
406
407 static void
408 x_output_toolbar (struct frame *f, enum toolbar_pos pos)
409 {
410 struct device *d = XDEVICE (f->device);
411 int x, y, bar_width, bar_height, vert;
412 int max_pixpos, right_size, right_start, blank_size;
413 int border_width = FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, pos);
414 Lisp_Object button, window;
415 Display *dpy = DEVICE_X_DISPLAY (d);
416 Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f));
417 GC background_gc = FRAME_X_TOOLBAR_BLANK_BACKGROUND_GC (f);
418
419 get_toolbar_coords (f, pos, &x, &y, &bar_width, &bar_height, &vert, 1);
420 window = FRAME_LAST_NONMINIBUF_WINDOW (f);
421
422 /* Do the border */
423 XFillRectangle (dpy, x_win, background_gc, x, y,
424 (vert ? bar_width : border_width),
425 (vert ? border_width : bar_height));
426 XFillRectangle (dpy, x_win, background_gc,
427 (vert ? x : x + bar_width - border_width),
428 (vert ? y + bar_height - border_width : y),
429 (vert ? bar_width : border_width),
430 (vert ? border_width : bar_height));
431
432 if (vert)
433 {
434 max_pixpos = y + bar_height - border_width;
435 y += border_width;
436 }
437 else
438 {
439 max_pixpos = x + bar_width - border_width;
440 x += border_width;
441 }
442
443 button = FRAME_TOOLBAR_BUTTONS (f, pos);
444 right_size = 0;
445
446 /* First loop over all of the buttons to determine how much room we
447 need for left hand and right hand buttons. This loop will also
448 make sure that all instances are instantiated so when we actually
449 output them they will come up immediately. */
450 while (!NILP (button))
451 {
452 struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
453 int size = x_get_button_size (f, window, tb, vert, pos);
454
455 if (tb->pushright)
456 right_size += size;
457
458 button = tb->next;
459 }
460
461 button = FRAME_TOOLBAR_BUTTONS (f, pos);
462
463 /* Loop over the left buttons, updating and outputting them. */
464 X_OUTPUT_BUTTONS_LOOP (1);
465
466 /* Now determine where the right buttons start. */
467 right_start = max_pixpos - right_size;
468 if (right_start < (vert ? y : x))
469 right_start = (vert ? y : x);
470
471 /* Output the blank which goes from the end of the left buttons to
472 the start of the right. */
473 blank_size = right_start - (vert ? y : x);
474 if (blank_size)
475 {
476 int height, width;
477
478 if (vert)
479 {
480 width = bar_width;
481 height = blank_size;
482 }
483 else
484 {
485 width = blank_size;
486 height = bar_height;
487 }
488
489 /*
490 * Use a 3D pushright separator only if there isn't a toolbar
491 * border. A flat separator meshes with the border and looks
492 * better.
493 */
494 x_draw_blank_toolbar_button (f, x, y, width, height, !border_width,
495 border_width, vert);
496
497 if (vert)
498 y += height;
499 else
500 x += width;
501 }
502
503 /* Loop over the right buttons, updating and outputting them. */
504 X_OUTPUT_BUTTONS_LOOP (0);
505
506 if (!vert)
507 {
508 Lisp_Object frame;
509
510 XSETFRAME (frame, f);
511 redisplay_clear_region (frame,
512 DEFAULT_INDEX, FRAME_PIXWIDTH (f) - 1, y, 1,
513 bar_height);
514 }
515
516 SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 1);
517
518 XFlush (DEVICE_X_DISPLAY (d));
519 }
520
521 static void
522 x_clear_toolbar (struct frame *f, enum toolbar_pos pos, int thickness_change)
523 {
524 Lisp_Object frame;
525 struct device *d = XDEVICE (f->device);
526 int x, y, width, height, vert;
527
528 get_toolbar_coords (f, pos, &x, &y, &width, &height, &vert, 1);
529 XSETFRAME (frame, f);
530
531 /* The thickness_change parameter is used by the toolbar resize routines
532 to clear any excess toolbar if the size shrinks. */
533 if (thickness_change < 0)
534 {
535 if (pos == LEFT_TOOLBAR || pos == RIGHT_TOOLBAR)
536 {
537 x = x + width + thickness_change;
538 width = -thickness_change;
539 }
540 else
541 {
542 y = y + height + thickness_change;
543 height = -thickness_change;
544 }
545 }
546
547 SET_TOOLBAR_WAS_VISIBLE_FLAG (f, pos, 0);
548
549 redisplay_clear_region (frame, DEFAULT_INDEX, x, y, width, height);
550 XFlush (DEVICE_X_DISPLAY (d));
551 }
552
553 static void
554 x_output_frame_toolbars (struct frame *f)
555 {
556 assert (FRAME_X_P (f));
557
558 if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f))
559 x_output_toolbar (f, TOP_TOOLBAR);
560 else if (f->top_toolbar_was_visible)
561 x_clear_toolbar (f, TOP_TOOLBAR, 0);
562
563 if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f))
564 x_output_toolbar (f, BOTTOM_TOOLBAR);
565 else if (f->bottom_toolbar_was_visible)
566 x_clear_toolbar (f, BOTTOM_TOOLBAR, 0);
567
568 if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f))
569 x_output_toolbar (f, LEFT_TOOLBAR);
570 else if (f->left_toolbar_was_visible)
571 x_clear_toolbar (f, LEFT_TOOLBAR, 0);
572
573 if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f))
574 x_output_toolbar (f, RIGHT_TOOLBAR);
575 else if (f->right_toolbar_was_visible)
576 x_clear_toolbar (f, RIGHT_TOOLBAR, 0);
577 }
578
579 static void
580 x_redraw_exposed_toolbar (struct frame *f, enum toolbar_pos pos, int x, int y,
581 int width, int height)
582 {
583 int bar_x, bar_y, bar_width, bar_height, vert;
584 Lisp_Object button = FRAME_TOOLBAR_BUTTONS (f, pos);
585
586 get_toolbar_coords (f, pos, &bar_x, &bar_y, &bar_width, &bar_height,
587 &vert, 1);
588
589 if (((y + height) < bar_y) || (y > (bar_y + bar_height)))
590 return;
591 if (((x + width) < bar_x) || (x > (bar_x + bar_width)))
592 return;
593
594 while (!NILP (button))
595 {
596 struct toolbar_button *tb = XTOOLBAR_BUTTON (button);
597
598 if (vert)
599 {
600 if (((tb->y + tb->height) > y) && (tb->y < (y + height)))
601 tb->dirty = 1;
602
603 /* If this is true we have gone past the exposed region. */
604 if (tb->y > (y + height))
605 break;
606 }
607 else
608 {
609 if (((tb->x + tb->width) > x) && (tb->x < (x + width)))
610 tb->dirty = 1;
611
612 /* If this is true we have gone past the exposed region. */
613 if (tb->x > (x + width))
614 break;
615 }
616
617 button = tb->next;
618 }
619
620 /* Even if none of the buttons is in the area, the blank region at
621 the very least must be because the first thing we did is verify
622 that some portion of the toolbar is in the exposed region. */
623 x_output_toolbar (f, pos);
624 }
625
626 static void
627 x_redraw_exposed_toolbars (struct frame *f, int x, int y, int width,
628 int height)
629 {
630 assert (FRAME_X_P (f));
631
632 if (FRAME_REAL_TOP_TOOLBAR_VISIBLE (f))
633 x_redraw_exposed_toolbar (f, TOP_TOOLBAR, x, y, width, height);
634
635 if (FRAME_REAL_BOTTOM_TOOLBAR_VISIBLE (f))
636 x_redraw_exposed_toolbar (f, BOTTOM_TOOLBAR, x, y, width, height);
637
638 if (FRAME_REAL_LEFT_TOOLBAR_VISIBLE (f))
639 x_redraw_exposed_toolbar (f, LEFT_TOOLBAR, x, y, width, height);
640
641 if (FRAME_REAL_RIGHT_TOOLBAR_VISIBLE (f))
642 x_redraw_exposed_toolbar (f, RIGHT_TOOLBAR, x, y, width, height);
643 }
644
645 static void
646 x_redraw_frame_toolbars (struct frame *f)
647 {
648 /* There are certain startup paths that lead to update_EmacsFrame in
649 faces.c being called before a new frame is fully initialized. In
650 particular before we have actually mapped it. That routine can
651 call this one. So, we need to make sure that the frame is
652 actually ready before we try and draw all over it. */
653
654 if (XtIsRealized (FRAME_X_SHELL_WIDGET (f)))
655 x_redraw_exposed_toolbars (f, 0, 0, FRAME_PIXWIDTH (f),
656 FRAME_PIXHEIGHT (f));
657 }
658
659
660 static void
661 x_initialize_frame_toolbar_gcs (struct frame *f)
662 {
663 EmacsFrame ef = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
664 EmacsFramePart *efp = &(ef->emacs_frame);
665 XGCValues gcv;
666 unsigned long flags = (GCForeground | GCBackground | GCGraphicsExposures);
667
668 /*
669 * If backgroundToolBarColor is specified, use it.
670 * Otherwise use the background resource.
671 */
672 if (efp->background_toolbar_pixel == (Pixel) (-1))
673 efp->background_toolbar_pixel = efp->background_pixel;
674
675 /*
676 * ####
677 * If foregroundToolBarColor is specified, use it.
678 * Otherwise use the foreground resource.
679 *
680 * The foreground pixel is currently unused, but will likely be
681 * used when toolbar captions are generated by the toolbar code
682 * instead being incorporated into the icon image.
683 */
684 if (efp->foreground_toolbar_pixel == (Pixel) (-1))
685 efp->foreground_toolbar_pixel = efp->foreground_pixel;
686
687 gcv.foreground = efp->background_toolbar_pixel;
688 gcv.background = ef->core.background_pixel;
689 gcv.graphics_exposures = False;
690 FRAME_X_TOOLBAR_BLANK_BACKGROUND_GC (f) =
691 XtGetGC ((Widget) ef, flags, &gcv);
692
693 if (efp->top_toolbar_shadow_pixel == efp->bottom_toolbar_shadow_pixel)
694 {
695 efp->top_toolbar_shadow_pixel = efp->background_toolbar_pixel;
696 efp->bottom_toolbar_shadow_pixel = efp->background_toolbar_pixel;
697 }
698
699 x_generate_shadow_pixels (f, &efp->top_toolbar_shadow_pixel,
700 &efp->bottom_toolbar_shadow_pixel,
701 efp->background_toolbar_pixel,
702 ef->core.background_pixel);
703
704 gcv.foreground = efp->top_toolbar_shadow_pixel;
705 gcv.background = ef->core.background_pixel;
706 gcv.graphics_exposures = False;
707 flags = GCForeground | GCBackground | GCGraphicsExposures;
708 if (efp->top_toolbar_shadow_pixmap)
709 {
710 gcv.fill_style = FillOpaqueStippled;
711 gcv.stipple = efp->top_toolbar_shadow_pixmap;
712 flags |= GCStipple | GCFillStyle;
713 }
714 FRAME_X_TOOLBAR_TOP_SHADOW_GC (f) = XtGetGC ((Widget) ef, flags, &gcv);
715
716 gcv.foreground = efp->bottom_toolbar_shadow_pixel;
717 gcv.background = ef->core.background_pixel;
718 gcv.graphics_exposures = False;
719 flags = GCForeground | GCBackground | GCGraphicsExposures;
720 if (efp->bottom_toolbar_shadow_pixmap)
721 {
722 gcv.fill_style = FillOpaqueStippled;
723 gcv.stipple = efp->bottom_toolbar_shadow_pixmap;
724 flags |= GCStipple | GCFillStyle;
725 }
726 FRAME_X_TOOLBAR_BOTTOM_SHADOW_GC (f) = XtGetGC ((Widget) ef, flags, &gcv);
727
728 #ifdef HAVE_XPM
729 FRAME_X_TOOLBAR_PIXMAP_BACKGROUND_GC (f) =
730 FRAME_X_TOOLBAR_BLANK_BACKGROUND_GC (f);
731 #else
732 {
733 struct device *d = XDEVICE (f->device);
734 Display *dpy = DEVICE_X_DISPLAY (d);
735
736 gcv.background = WhitePixelOfScreen (DefaultScreenOfDisplay (dpy));
737 gcv.foreground = BlackPixelOfScreen (DefaultScreenOfDisplay (dpy));
738 gcv.graphics_exposures = False;
739 flags = GCForeground | GCBackground | GCGraphicsExposures;
740 FRAME_X_TOOLBAR_PIXMAP_BACKGROUND_GC (f) =
741 XtGetGC ((Widget) ef, flags, &gcv);
742 }
743 #endif
744 }
745
746 static void
747 x_release_frame_toolbar_gcs (struct frame *f)
748 {
749 Widget ew = (Widget) FRAME_X_TEXT_WIDGET (f);
750 XtReleaseGC (ew, FRAME_X_TOOLBAR_BLANK_BACKGROUND_GC (f));
751 /* If compiled with XPM support, this is a pointer to the same GC as
752 FRAME_X_BLANK_BACKGROUND_GC so we need to make sure we don't
753 release it twice. */
754 #ifndef HAVE_XPM
755 XtReleaseGC (ew, FRAME_X_TOOLBAR_PIXMAP_BACKGROUND_GC (f));
756 #endif
757 XtReleaseGC (ew, FRAME_X_TOOLBAR_TOP_SHADOW_GC (f));
758 XtReleaseGC (ew, FRAME_X_TOOLBAR_BOTTOM_SHADOW_GC (f));
759
760 /* Seg fault if we try and use these again. */
761 FRAME_X_TOOLBAR_BLANK_BACKGROUND_GC (f) = (GC) - 1;
762 FRAME_X_TOOLBAR_PIXMAP_BACKGROUND_GC (f) = (GC) - 1;
763 FRAME_X_TOOLBAR_TOP_SHADOW_GC (f) = (GC) - 1;
764 FRAME_X_TOOLBAR_BOTTOM_SHADOW_GC (f) = (GC) - 1;
765 }
766 52
767 static void 53 static void
768 x_initialize_frame_toolbars (struct frame *f) 54 x_initialize_frame_toolbars (struct frame *f)
769 { 55 {
770 EmacsFrame ef = (EmacsFrame) FRAME_X_TEXT_WIDGET (f); 56 EmacsFrame ef = (EmacsFrame) FRAME_X_TEXT_WIDGET (f);
771 57
772 if (ef->emacs_frame.toolbar_shadow_thickness < MINIMUM_SHADOW_THICKNESS) 58 if (ef->emacs_frame.toolbar_shadow_thickness < MINIMUM_SHADOW_THICKNESS)
773 Xt_SET_VALUE (FRAME_X_TEXT_WIDGET (f), 59 Xt_SET_VALUE (FRAME_X_TEXT_WIDGET (f),
774 XtNtoolBarShadowThickness, MINIMUM_SHADOW_THICKNESS); 60 XtNtoolBarShadowThickness, MINIMUM_SHADOW_THICKNESS);
775
776 x_initialize_frame_toolbar_gcs (f);
777 } 61 }
778 62
779 /* This only calls one function but we go ahead and create this in 63 /* This only calls one function but we go ahead and create this in
780 case we ever do decide that we need to do more work. */ 64 case we ever do decide that we need to do more work. */
781 static void 65 static void
782 x_free_frame_toolbars (struct frame *f) 66 x_free_frame_toolbars (struct frame *f)
783 { 67 {
784 x_release_frame_toolbar_gcs (f);
785 } 68 }
786 69
787 70
788 /************************************************************************/ 71 /************************************************************************/
789 /* initialization */ 72 /* initialization */