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