comparison src/toolbar-x.c @ 0:376386a54a3c r19-14

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