Mercurial > hg > xemacs-beta
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 */ |