(Excursions): Replace arg `forms' with `body' in `save-excursion'.
[emacs.git] / src / widget.c
blob0386890d93be822d73ba78b851d5d8d100d20bec
1 /* The emacs frame widget.
2 Copyright (C) 1992, 1993, 2000, 2002, 2003, 2004,
3 2005 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Emacs 19 face widget ported by Fred Pierresteguy */
24 /* This file has been censored by the Communications Decency Act.
25 That law was passed under the guise of a ban on pornography, but
26 it bans far more than that. This file did not contain pornography,
27 but it was censored nonetheless.
29 For information on US government censorship of the Internet, and
30 what you can do to bring back freedom of the press, see the web
31 site http://www.vtw.org/
34 #include <config.h>
35 #include <stdio.h>
36 #include "lisp.h"
37 #include "xterm.h"
39 #include "keyboard.h"
40 #include "frame.h"
41 #include "window.h"
43 #include "dispextern.h"
44 #include "blockinput.h"
46 #include <X11/StringDefs.h>
47 #include <X11/IntrinsicP.h>
48 #include <X11/cursorfont.h>
49 #include "widgetprv.h"
50 #include <X11/ObjectP.h>
51 #include <X11/Shell.h>
52 #include <X11/ShellP.h>
53 #include "../lwlib/lwlib.h"
55 #include <signal.h>
56 #include "syssignal.h"
58 /* This sucks: this is the first default that x-faces.el tries. This won't
59 be used unless neither the "Emacs.EmacsFrame" resource nor the
60 "Emacs.EmacsFrame" resource is set; the frame
61 may have the wrong default size if this font doesn't exist, but some other
62 font that x-faces.el does. The workaround is to specify some font in the
63 resource database; I don't know a solution other than duplicating the font-
64 searching code from x-faces.el in this file.
66 This also means that if "Emacs.EmacsFrame" is specified as a non-
67 existent font, then Xt is going to substitute "XtDefaultFont" for it,
68 which is a different size than this one. The solution for this is to
69 make x-faces.el try to use XtDefaultFont. The problem with that is that
70 XtDefaultFont is almost certainly variable-width.
72 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
74 #define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
77 static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
78 static void EmacsFrameDestroy (/* Widget */);
79 static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
80 void EmacsFrameResize (/* Widget widget */);
81 static Boolean EmacsFrameSetValues (/* Widget, Widget, Widget,
82 ArgList, Cardinal * */);
83 static XtGeometryResult EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
84 XtWidgetGeometry* */);
87 #undef XtOffset
88 #define XtOffset(p_type,field) \
89 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
90 #define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
92 static XtResource resources[] = {
93 {XtNgeometry, XtCGeometry, XtRString, sizeof(String),
94 offset (geometry), XtRString, (XtPointer) 0},
95 {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
96 offset (iconic), XtRImmediate, (XtPointer) False},
98 {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
99 offset (frame), XtRImmediate, 0},
101 {XtNminibuffer, XtCMinibuffer, XtRInt, sizeof (int),
102 offset (minibuffer), XtRImmediate, (XtPointer)0},
103 {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
104 offset (unsplittable), XtRImmediate, (XtPointer)0},
105 {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
106 offset (internal_border_width), XtRImmediate, (XtPointer)4},
107 {XtNinterline, XtCInterline, XtRInt, sizeof (int),
108 offset (interline), XtRImmediate, (XtPointer)0},
109 {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
110 offset(font),XtRString, DEFAULT_FACE_FONT},
111 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
112 offset(foreground_pixel), XtRString, "XtDefaultForeground"},
113 {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
114 offset(cursor_color), XtRString, "XtDefaultForeground"},
115 {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
116 offset (bar_cursor), XtRImmediate, (XtPointer)0},
117 {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
118 offset (visual_bell), XtRImmediate, (XtPointer)0},
119 {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
120 offset (bell_volume), XtRImmediate, (XtPointer)0},
123 #undef offset
126 static XtActionsRec
127 emacsFrameActionsTable [] = {
128 {"keypress", key_press},
129 {"focus_in", emacs_frame_focus_handler},
130 {"focus_out", emacs_frame_focus_handler},
133 static char
134 emacsFrameTranslations [] = "\
135 <KeyPress>: keypress()\n\
136 <FocusIn>: focus_in()\n\
137 <FocusOut>: focus_out()\n\
141 EmacsFrameClassRec emacsFrameClassRec = {
142 { /* core fields */
143 /* superclass */ &widgetClassRec,
144 /* class_name */ "EmacsFrame",
145 /* widget_size */ sizeof(EmacsFrameRec),
146 /* class_initialize */ 0,
147 /* class_part_initialize */ 0,
148 /* class_inited */ FALSE,
149 /* initialize */ EmacsFrameInitialize,
150 /* initialize_hook */ 0,
151 /* realize */ EmacsFrameRealize,
152 /* actions */ 0, /*emacsFrameActionsTable*/
153 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
154 /* resources */ resources,
155 /* resource_count */ XtNumber(resources),
156 /* xrm_class */ NULLQUARK,
157 /* compress_motion */ TRUE,
158 /* compress_exposure */ TRUE,
159 /* compress_enterleave */ TRUE,
160 /* visible_interest */ FALSE,
161 /* destroy */ EmacsFrameDestroy,
162 /* resize */ EmacsFrameResize,
163 /* expose */ XtInheritExpose,
164 /* set_values */ EmacsFrameSetValues,
165 /* set_values_hook */ 0,
166 /* set_values_almost */ XtInheritSetValuesAlmost,
167 /* get_values_hook */ 0,
168 /* accept_focus */ XtInheritAcceptFocus,
169 /* version */ XtVersion,
170 /* callback_private */ 0,
171 /* tm_table */ 0, /*emacsFrameTranslations*/
172 /* query_geometry */ EmacsFrameQueryGeometry,
173 /* display_accelerator */ XtInheritDisplayAccelerator,
174 /* extension */ 0
178 WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
180 static void
181 get_default_char_pixel_size (ew, pixel_width, pixel_height)
182 EmacsFrame ew;
183 int* pixel_width;
184 int* pixel_height;
186 struct frame* f = ew->emacs_frame.frame;
187 *pixel_width = FRAME_COLUMN_WIDTH (f);
188 *pixel_height = FRAME_LINE_HEIGHT (f);
191 static void
192 pixel_to_char_size (ew, pixel_width, pixel_height, char_width, char_height)
193 EmacsFrame ew;
194 Dimension pixel_width;
195 Dimension pixel_height;
196 int* char_width;
197 int* char_height;
199 struct frame* f = ew->emacs_frame.frame;
200 *char_width = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, (int) pixel_width);
201 *char_height = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, (int) pixel_height);
204 static void
205 char_to_pixel_size (ew, char_width, char_height, pixel_width, pixel_height)
206 EmacsFrame ew;
207 int char_width;
208 int char_height;
209 Dimension* pixel_width;
210 Dimension* pixel_height;
212 struct frame* f = ew->emacs_frame.frame;
213 *pixel_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, char_width);
214 *pixel_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, char_height);
217 static void
218 round_size_to_char (ew, in_width, in_height, out_width, out_height)
219 EmacsFrame ew;
220 Dimension in_width;
221 Dimension in_height;
222 Dimension* out_width;
223 Dimension* out_height;
225 int char_width;
226 int char_height;
227 pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
228 char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
231 static Widget
232 get_wm_shell (w)
233 Widget w;
235 Widget wmshell;
237 for (wmshell = XtParent (w);
238 wmshell && !XtIsWMShell (wmshell);
239 wmshell = XtParent (wmshell));
241 return wmshell;
244 #if 0 /* Currently not used. */
246 static void
247 mark_shell_size_user_specified (wmshell)
248 Widget wmshell;
250 if (! XtIsWMShell (wmshell)) abort ();
251 /* This is kind of sleazy, but I can't see how else to tell it to make it
252 mark the WM_SIZE_HINTS size as user specified when appropriate. */
253 ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
256 #endif
259 /* Can't have static frame locals because of some broken compilers.
260 Normally, initializing a variable like this doesn't work in emacs,
261 but it's ok in this file because it must come after lastfile (and
262 thus have its data not go into text space) because Xt needs to
263 write to initialized data objects too.
265 #if 0
266 static Boolean first_frame_p = True;
267 #endif
269 static void
270 set_frame_size (ew)
271 EmacsFrame ew;
273 /* The widget hierarchy is
275 argv[0] emacsShell pane Frame-NAME
276 ApplicationShell EmacsShell Paned EmacsFrame
278 We accept geometry specs in this order:
280 *Frame-NAME.geometry
281 *EmacsFrame.geometry
282 Emacs.geometry
284 Other possibilities for widget hierarchies might be
286 argv[0] frame pane Frame-NAME
287 ApplicationShell EmacsShell Paned EmacsFrame
289 argv[0] Frame-NAME pane Frame-NAME
290 ApplicationShell EmacsShell Paned EmacsFrame
292 argv[0] Frame-NAME pane emacsTextPane
293 ApplicationShell EmacsFrame Paned EmacsTextPane
295 With the current setup, the text-display-area is the part which is
296 an emacs "frame", since that's the only part managed by emacs proper
297 (the menubar and the parent of the menubar and all that sort of thing
298 are managed by lwlib.)
300 The EmacsShell widget is simply a replacement for the Shell widget
301 which is able to deal with using an externally-supplied window instead
302 of always creating its own. It is not actually emacs specific, and
303 should possibly have class "Shell" instead of "EmacsShell" to simplify
304 the resources.
308 /* Hairily merged geometry */
309 unsigned int w = FRAME_COLS (ew->emacs_frame.frame);
310 unsigned int h = FRAME_LINES (ew->emacs_frame.frame);
312 Widget wmshell = get_wm_shell ((Widget) ew);
313 /* Each Emacs shell is now independent and top-level. */
315 if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
317 /* We don't need this for the moment. The geometry is computed in
318 xfns.c. */
319 #if 0
320 /* If the EmacsFrame doesn't have a geometry but the shell does,
321 treat that as the geometry of the frame. (Is this bogus?
322 I'm not sure.) */
323 if (ew->emacs_frame.geometry == 0)
324 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, NULL);
326 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
327 this bogus? I'm not sure.) */
328 if (!ew->emacs_frame.iconic)
329 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, NULL);
333 char *geom = 0;
334 XtVaGetValues (app_shell, XtNgeometry, &geom, NULL);
335 if (geom)
336 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
339 if (ew->emacs_frame.geometry)
340 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
341 &frame_x, &frame_y,
342 &frame_w, &frame_h);
344 if (first_frame_p)
346 /* If this is the first frame created:
347 ====================================
349 - Use the ApplicationShell's size/position, if specified.
350 (This is "Emacs.geometry", or the "-geometry" command line arg.)
351 - Else use the EmacsFrame's size/position.
352 (This is "*Frame-NAME.geometry")
354 - If the AppShell is iconic, the frame should be iconic.
356 AppShell comes first so that -geometry always applies to the first
357 frame created, even if there is an "every frame" entry in the
358 resource database.
360 if (app_flags & (XValue | YValue))
362 x = app_x; y = app_y;
363 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
365 else if (frame_flags & (XValue | YValue))
367 x = frame_x; y = frame_y;
368 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
371 if (app_flags & (WidthValue | HeightValue))
373 w = app_w; h = app_h;
374 flags |= (app_flags & (WidthValue | HeightValue));
376 else if (frame_flags & (WidthValue | HeightValue))
378 w = frame_w; h = frame_h;
379 flags |= (frame_flags & (WidthValue | HeightValue));
382 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
383 if (!ew->emacs_frame.iconic)
384 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, NULL);
386 first_frame_p = False;
388 else
390 /* If this is not the first frame created:
391 ========================================
393 - use the EmacsFrame's size/position if specified
394 - Otherwise, use the ApplicationShell's size, but not position.
396 So that means that one can specify the position of the first frame
397 with "Emacs.geometry" or `-geometry'; but can only specify the
398 position of subsequent frames with "*Frame-NAME.geometry".
400 AppShell comes second so that -geometry does not apply to subsequent
401 frames when there is an "every frame" entry in the resource db,
402 but does apply to the first frame.
404 if (frame_flags & (XValue | YValue))
406 x = frame_x; y = frame_y;
407 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
410 if (frame_flags & (WidthValue | HeightValue))
412 w = frame_w; h = frame_h;
413 flags |= (frame_flags & (WidthValue | HeightValue));
415 else if (app_flags & (WidthValue | HeightValue))
417 w = app_w;
418 h = app_h;
419 flags |= (app_flags & (WidthValue | HeightValue));
422 #endif /* 0 */
424 struct frame *f = ew->emacs_frame.frame;
425 Dimension pixel_width, pixel_height;
427 /* Take into account the size of the scrollbar. Always use the
428 number of columns occupied by the scroll bar here otherwise we
429 might end up with a frame width that is not a multiple of the
430 frame's character width which is bad for vertically split
431 windows. */
432 f->scroll_bar_actual_width
433 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
435 compute_fringe_widths (f, 0);
437 #if 0 /* This can run Lisp code, and it is dangerous to give
438 out the frame to Lisp code before it officially exists.
439 This is handled in Fx_create_frame so not needed here. */
440 change_frame_size (f, h, w, 1, 0, 0);
441 #endif
442 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
443 ew->core.width = pixel_width;
444 ew->core.height = pixel_height;
446 #if 0 /* xfns.c takes care of this now. */
447 /* If a position was specified, assign it to the shell widget.
448 (Else WM won't do anything with it.)
450 if (flags & (XValue | YValue))
452 /* the tricky things with the sign is to make sure that
453 -0 is printed -0. */
454 int len;
455 char *tem;
456 sprintf (shell_position, "=%c%d%c%d",
457 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
458 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
459 len = strlen (shell_position) + 1;
460 tem = (char *) xmalloc (len);
461 strncpy (tem, shell_position, len);
462 XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
464 else if (flags & (WidthValue | HeightValue))
466 int len;
467 char *tem;
468 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
469 len = strlen (shell_position) + 1;
470 tem = (char *) xmalloc (len);
471 strncpy (tem, shell_position, len);
472 XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
475 /* If the geometry spec we're using has W/H components, mark the size
476 in the WM_SIZE_HINTS as user specified. */
477 if (flags & (WidthValue | HeightValue))
478 mark_shell_size_user_specified (wmshell);
480 /* Also assign the iconic status of the frame to the Shell, so that
481 the WM sees it. */
482 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, NULL);
483 #endif /* 0 */
487 /* Nonzero tells update_wm_hints not to do anything
488 (the caller should call update_wm_hints explicitly later.) */
489 int update_hints_inhibit;
491 static void
492 update_wm_hints (ew)
493 EmacsFrame ew;
495 Widget wmshell = get_wm_shell ((Widget)ew);
496 int cw;
497 int ch;
498 Dimension rounded_width;
499 Dimension rounded_height;
500 int char_width;
501 int char_height;
502 int base_width;
503 int base_height;
504 int min_rows = 0, min_cols = 0;
506 if (update_hints_inhibit)
507 return;
509 #if 0
510 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
511 #endif
513 pixel_to_char_size (ew, ew->core.width, ew->core.height,
514 &char_width, &char_height);
515 char_to_pixel_size (ew, char_width, char_height,
516 &rounded_width, &rounded_height);
517 get_default_char_pixel_size (ew, &cw, &ch);
519 base_width = (wmshell->core.width - ew->core.width
520 + (rounded_width - (char_width * cw)));
521 base_height = (wmshell->core.height - ew->core.height
522 + (rounded_height - (char_height * ch)));
524 /* This is kind of sleazy, but I can't see how else to tell it to
525 make it mark the WM_SIZE_HINTS size as user specified.
527 /* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
529 XtVaSetValues (wmshell,
530 XtNbaseWidth, (XtArgVal) base_width,
531 XtNbaseHeight, (XtArgVal) base_height,
532 XtNwidthInc, (XtArgVal) cw,
533 XtNheightInc, (XtArgVal) ch,
534 XtNminWidth, (XtArgVal) (base_width + min_cols * cw),
535 XtNminHeight, (XtArgVal) (base_height + min_rows * ch),
536 NULL);
539 #if 0
541 static void
542 create_frame_gcs (ew)
543 EmacsFrame ew;
545 struct frame *s = ew->emacs_frame.frame;
547 s->output_data.x->normal_gc
548 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
549 (unsigned long)0, (XGCValues *)0);
550 s->output_data.x->reverse_gc
551 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
552 (unsigned long)0, (XGCValues *)0);
553 s->output_data.x->cursor_gc
554 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
555 (unsigned long)0, (XGCValues *)0);
556 s->output_data.x->black_relief.gc = 0;
557 s->output_data.x->white_relief.gc = 0;
560 #endif /* 0 */
562 static char setup_frame_cursor_bits[] =
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
570 static void
571 setup_frame_gcs (ew)
572 EmacsFrame ew;
574 XGCValues gc_values;
575 struct frame* s = ew->emacs_frame.frame;
576 Pixmap blank_stipple, blank_tile;
578 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
579 XGetGCValues returns uninitialized data when we query the stipple
580 (instead of None or something sensible) and it makes things hard.
582 This should be fixed for real by not querying the GCs but instead having
583 some GC-based cache instead of the current face-based cache which doesn't
584 effectively cache all of the GC settings we need to use.
587 blank_stipple
588 = XCreateBitmapFromData (XtDisplay (ew),
589 RootWindowOfScreen (XtScreen (ew)),
590 setup_frame_cursor_bits, 2, 2);
592 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
593 never actually get used as a background tile!
595 blank_tile
596 = XCreatePixmapFromBitmapData (XtDisplay(ew),
597 RootWindowOfScreen (XtScreen (ew)),
598 setup_frame_cursor_bits, 2, 2,
599 (unsigned long)0, (unsigned long)1,
600 ew->core.depth);
602 /* Normal video */
603 gc_values.font = ew->emacs_frame.font->fid;
604 gc_values.foreground = ew->emacs_frame.foreground_pixel;
605 gc_values.background = ew->core.background_pixel;
606 gc_values.graphics_exposures = False;
607 gc_values.stipple = blank_stipple;
608 gc_values.tile = blank_tile;
609 XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
610 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
611 | GCStipple | GCTile),
612 &gc_values);
614 /* Reverse video style. */
615 gc_values.font = ew->emacs_frame.font->fid;
616 gc_values.foreground = ew->core.background_pixel;
617 gc_values.background = ew->emacs_frame.foreground_pixel;
618 gc_values.graphics_exposures = False;
619 gc_values.stipple = blank_stipple;
620 gc_values.tile = blank_tile;
621 XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
622 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
623 | GCStipple | GCTile),
624 &gc_values);
626 /* Cursor has to have an empty stipple. */
627 gc_values.font = ew->emacs_frame.font->fid;
628 gc_values.foreground = ew->core.background_pixel;
629 gc_values.background = ew->emacs_frame.cursor_color;
630 gc_values.graphics_exposures = False;
631 gc_values.tile = blank_tile;
632 gc_values.stipple
633 = XCreateBitmapFromData (XtDisplay (ew),
634 RootWindowOfScreen (XtScreen (ew)),
635 setup_frame_cursor_bits, 16, 16);
636 XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
637 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
638 | GCStipple | GCTile),
639 &gc_values);
642 static void
643 update_various_frame_slots (ew)
644 EmacsFrame ew;
646 struct frame *f = ew->emacs_frame.frame;
647 struct x_output *x = f->output_data.x;
648 FRAME_PIXEL_HEIGHT (f) = ew->core.height + x->menubar_height;
649 FRAME_PIXEL_WIDTH (f) = ew->core.width;
650 f->internal_border_width = ew->emacs_frame.internal_border_width;
654 static void
655 update_from_various_frame_slots (ew)
656 EmacsFrame ew;
658 struct frame *f = ew->emacs_frame.frame;
659 struct x_output *x = f->output_data.x;
660 ew->core.height = FRAME_PIXEL_HEIGHT (f) - x->menubar_height;
661 ew->core.width = FRAME_PIXEL_WIDTH (f);
662 ew->core.background_pixel = x->background_pixel;
663 ew->emacs_frame.internal_border_width = f->internal_border_width;
664 ew->emacs_frame.font = x->font;
665 ew->emacs_frame.foreground_pixel = x->foreground_pixel;
666 ew->emacs_frame.cursor_color = x->cursor_pixel;
667 ew->core.border_pixel = x->border_pixel;
670 static void
671 EmacsFrameInitialize (request, new, dum1, dum2)
672 Widget request;
673 Widget new;
674 ArgList dum1;
675 Cardinal *dum2;
677 EmacsFrame ew = (EmacsFrame)new;
679 if (!ew->emacs_frame.frame)
681 fprintf (stderr,
682 "can't create an emacs frame widget without a frame\n");
683 exit (1);
686 #if 0 /* done in xfns.c */
687 /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
688 resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
689 It's unfortunate that we have to do this, but we need to know the font
690 size for frame-sizing purposes before the faces get initialized. If
691 the "default.attributeFont" isn't set, then we use the font of this
692 EmacsFrame itself, defaulting to XtDefaultFont. Up in the lisp code,
693 the "default" face will use the frame's font if its own is not set,
694 so everything stays in sync -- it's not possible for the frame's font
695 and the default face's font to be different.
698 XFontStruct *f = 0;
699 XtResource face_res;
700 face_res.resource_name = "attributeFont";
701 face_res.resource_class = "AttributeFont";
702 face_res.resource_type = XtRFontStruct;
703 face_res.resource_size = sizeof (XFontStruct *);
704 face_res.resource_offset = 0;
705 face_res.default_type = XtRImmediate;
706 face_res.default_addr = 0;
707 XtGetSubresources ((Widget) ew, (XtPointer) &f, "default", "Face",
708 &face_res, 1, NULL, 0);
710 if (f)
711 ew->emacs_frame.font = f;
712 else if (! ew->emacs_frame.font)
714 fprintf (stderr, "emacs frame widget could not load a font\n");
715 exit (1);
719 /* Update the font field in frame */
720 FRAME_FONT (ew->emacs_frame.frame) = ew->emacs_frame.font;
721 #endif
723 update_from_various_frame_slots (ew);
724 set_frame_size (ew);
725 /*create_frame_gcs (ew);
726 setup_frame_gcs (ew);
727 update_various_frame_slots (ew); */
731 static void
732 EmacsFrameRealize (widget, mask, attrs)
733 Widget widget;
734 XtValueMask *mask;
735 XSetWindowAttributes *attrs;
737 EmacsFrame ew = (EmacsFrame)widget;
739 /* This used to contain SubstructureRedirectMask, but this turns out
740 to be a problem with XIM on Solaris, and events from that mask
741 don't seem to be used. Let's check that. */
742 attrs->event_mask = (STANDARD_EVENT_SET
743 | PropertyChangeMask
744 | SubstructureNotifyMask);
745 *mask |= CWEventMask;
746 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
747 attrs);
748 update_wm_hints (ew);
751 extern void free_frame_faces (/* struct frame * */);
753 static void
754 EmacsFrameDestroy (widget)
755 Widget widget;
757 EmacsFrame ew = (EmacsFrame) widget;
758 struct frame* s = ew->emacs_frame.frame;
760 if (! s) abort ();
761 if (! s->output_data.x) abort ();
763 BLOCK_INPUT;
764 x_free_gcs (s);
765 if (s->output_data.x->white_relief.gc)
766 XFreeGC (XtDisplay (widget), s->output_data.x->white_relief.gc);
767 if (s->output_data.x->black_relief.gc)
768 XFreeGC (XtDisplay (widget), s->output_data.x->black_relief.gc);
769 UNBLOCK_INPUT;
772 void
773 EmacsFrameResize (widget)
774 Widget widget;
776 EmacsFrame ew = (EmacsFrame)widget;
777 struct frame *f = ew->emacs_frame.frame;
778 int columns;
779 int rows;
781 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
782 change_frame_size (f, rows, columns, 0, 1, 0);
783 update_wm_hints (ew);
784 update_various_frame_slots (ew);
786 cancel_mouse_face (f);
789 static Boolean
790 EmacsFrameSetValues (cur_widget, req_widget, new_widget, dum1, dum2)
791 Widget cur_widget;
792 Widget req_widget;
793 Widget new_widget;
794 ArgList dum1;
795 Cardinal *dum2;
797 EmacsFrame cur = (EmacsFrame)cur_widget;
798 EmacsFrame new = (EmacsFrame)new_widget;
800 Boolean needs_a_refresh = False;
801 Boolean has_to_recompute_size;
802 Boolean has_to_recompute_gcs;
803 Boolean has_to_update_hints;
805 int char_width, char_height;
806 Dimension pixel_width;
807 Dimension pixel_height;
809 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
810 || (cur->emacs_frame.foreground_pixel
811 != new->emacs_frame.foreground_pixel)
812 || (cur->core.background_pixel
813 != new->core.background_pixel)
816 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
817 && cur->core.width == new->core.width
818 && cur->core.height == new->core.height);
820 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
822 if (has_to_recompute_gcs)
824 setup_frame_gcs (new);
825 needs_a_refresh = True;
828 if (has_to_recompute_size)
830 pixel_width = new->core.width;
831 pixel_height = new->core.height;
832 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
833 &char_height);
834 char_to_pixel_size (new, char_width, char_height, &pixel_width,
835 &pixel_height);
836 new->core.width = pixel_width;
837 new->core.height = pixel_height;
839 change_frame_size (new->emacs_frame.frame, char_height, char_width,
840 1, 0, 0);
841 needs_a_refresh = True;
844 if (has_to_update_hints)
845 update_wm_hints (new);
847 update_various_frame_slots (new);
849 /* #### This doesn't work, I haven't been able to find ANY kludge that
850 will let (x-create-frame '((iconic . t))) work. It seems that changes
851 to wm_shell's iconic slot have no effect after it has been realized,
852 and calling XIconifyWindow doesn't work either (even though the window
853 has been created.) Perhaps there is some property we could smash
854 directly, but I'm sick of this for now.
856 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
858 Widget wmshell = get_wm_shell ((Widget) cur);
859 XtVaSetValues (wmshell, XtNiconic,
860 (XtArgVal) new->emacs_frame.iconic, NULL);
863 return needs_a_refresh;
866 static XtGeometryResult
867 EmacsFrameQueryGeometry (widget, request, result)
868 Widget widget;
869 XtWidgetGeometry* request;
870 XtWidgetGeometry* result;
872 EmacsFrame ew = (EmacsFrame)widget;
874 int mask = request->request_mode;
875 Dimension ok_width, ok_height;
877 if (mask & (CWWidth | CWHeight))
879 round_size_to_char (ew,
880 (mask & CWWidth) ? request->width : ew->core.width,
881 ((mask & CWHeight) ? request->height
882 : ew->core.height),
883 &ok_width, &ok_height);
884 if ((mask & CWWidth) && (ok_width != request->width))
886 result->request_mode |= CWWidth;
887 result->width = ok_width;
889 if ((mask & CWHeight) && (ok_height != request->height))
891 result->request_mode |= CWHeight;
892 result->height = ok_height;
895 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
898 /* Special entrypoints */
899 void
900 EmacsFrameSetCharSize (widget, columns, rows)
901 Widget widget;
902 int columns;
903 int rows;
905 EmacsFrame ew = (EmacsFrame) widget;
906 Dimension pixel_width, pixel_height;
907 struct frame *f = ew->emacs_frame.frame;
909 if (columns < 3) columns = 3; /* no way buddy */
911 check_frame_size (f, &rows, &columns);
912 f->scroll_bar_actual_width
913 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
915 compute_fringe_widths (f, 0);
917 char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
919 #if 0 /* This doesn't seem to be right. The frame gets too wide. --gerd. */
920 /* Something is really strange here wrt to the border width:
921 Apparently, XtNwidth and XtNheight include the border, so we have
922 to add it here. But the XtNborderWidth set for the widgets has
923 no similarity to what f->border_width is set to. */
924 XtVaGetValues (widget, XtNborderWidth, &border_width, NULL);
925 pixel_height += 2 * border_width;
926 pixel_width += 2 * border_width;
927 #endif
929 /* Manually change the height and width of all our widgets,
930 adjusting each widget by the same increments. */
931 if (ew->core.width != pixel_width
932 || ew->core.height != pixel_height)
934 int hdelta = pixel_height - ew->core.height;
935 int wdelta = pixel_width - ew->core.width;
936 int column_widget_height = f->output_data.x->column_widget->core.height;
937 int column_widget_width = f->output_data.x->column_widget->core.width;
938 int outer_widget_height = f->output_data.x->widget->core.height;
939 int outer_widget_width = f->output_data.x->widget->core.width;
940 int old_left = f->output_data.x->widget->core.x;
941 int old_top = f->output_data.x->widget->core.y;
943 /* Input is blocked here, and Xt waits for some event to
944 occur. */
946 lw_refigure_widget (f->output_data.x->column_widget, False);
947 update_hints_inhibit = 1;
949 /* Xt waits for a ConfigureNotify event from the window manager
950 in EmacsFrameSetCharSize when the shell widget is resized.
951 For some window managers like fvwm2 2.2.5 and KDE 2.1 this
952 event doesn't arrive for an unknown reason and Emacs hangs in
953 Xt when the default font is changed. Tell Xt not to wait,
954 depending on the value of the frame parameter
955 `wait-for-wm'. */
956 XtVaSetValues (f->output_data.x->widget,
957 XtNwaitForWm, (XtArgVal) f->output_data.x->wait_for_wm,
958 NULL);
960 /* Workaround: When a SIGIO or SIGALRM occurs while Xt is
961 waiting for a ConfigureNotify event (see above), this leads
962 to Xt waiting indefinitely instead of using its default
963 timeout (5 seconds). */
964 turn_on_atimers (0);
965 #ifdef SIGIO
966 sigblock (sigmask (SIGIO));
967 #endif
969 /* Do parents first, otherwise LessTif's geometry management
970 enters an infinite loop (as of 2000-01-15). This is fixed in
971 later versions of LessTif (as of 2001-03-13); I'll leave it
972 as is because I think it can't do any harm. */
973 /* In April 2002, simon.marshall@misys.com reports the problem
974 seems not to occur any longer. */
975 XtVaSetValues (f->output_data.x->widget,
976 XtNheight, (XtArgVal) (outer_widget_height + hdelta),
977 XtNwidth, (XtArgVal) (outer_widget_width + wdelta),
978 NULL);
979 XtVaSetValues (f->output_data.x->column_widget,
980 XtNheight, (XtArgVal) (column_widget_height + hdelta),
981 XtNwidth, (XtArgVal) column_widget_width + wdelta,
982 NULL);
983 XtVaSetValues ((Widget) ew,
984 XtNheight, (XtArgVal) pixel_height,
985 XtNwidth, (XtArgVal) pixel_width,
986 NULL);
987 #ifdef SIGIO
988 sigunblock (sigmask (SIGIO));
989 #endif
990 turn_on_atimers (1);
992 lw_refigure_widget (f->output_data.x->column_widget, True);
994 update_hints_inhibit = 0;
995 update_wm_hints (ew);
997 /* These seem to get clobbered. I don't know why. - rms. */
998 f->output_data.x->widget->core.x = old_left;
999 f->output_data.x->widget->core.y = old_top;
1002 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
1003 receive in the ConfigureNotify event; if we get what we asked
1004 for, then the event won't cause the screen to become garbaged, so
1005 we have to make sure to do it here. */
1006 SET_FRAME_GARBAGED (f);
1010 void
1011 widget_store_internal_border (widget)
1012 Widget widget;
1014 EmacsFrame ew = (EmacsFrame) widget;
1015 FRAME_PTR f = ew->emacs_frame.frame;
1017 ew->emacs_frame.internal_border_width = f->internal_border_width;
1020 /* arch-tag: 931d28e5-0d59-405a-8325-7d475d0a13d9
1021 (do not change this comment) */