1 /* The emacs frame widget.
2 Copyright (C) 1992, 1993 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Emacs 19 face widget ported by Fred Pierresteguy */
23 /* This file has been censored by the Communications Decency Act.
24 That law was passed under the guise of a ban on pornography, but
25 it bans far more than that. This file did not contain pornography,
26 but it was censored nonetheless.
28 For information on US government censorship of the Internet, and
29 what you can do to bring back freedom of the press, see the web
30 site http://www.vtw.org/
40 #include "dispextern.h"
41 #include "blockinput.h"
43 #include <X11/StringDefs.h>
44 #include <X11/IntrinsicP.h>
45 #include <X11/cursorfont.h>
46 #include "widgetprv.h"
47 #include <X11/ObjectP.h>
48 #include <X11/Shell.h>
49 #include <X11/ShellP.h>
50 #include "../lwlib/lwlib.h"
52 #define max(a, b) ((a) > (b) ? (a) : (b))
54 /* This sucks: this is the first default that x-faces.el tries. This won't
55 be used unless neither the "Emacs.EmacsFrame" resource nor the
56 "Emacs.EmacsFrame" resource is set; the frame
57 may have the wrong default size if this font doesn't exist, but some other
58 font that x-faces.el does. The workaround is to specify some font in the
59 resource database; I don't know a solution other than duplicating the font-
60 searching code from x-faces.el in this file.
62 This also means that if "Emacs.EmacsFrame" is specified as a non-
63 existent font, then Xt is going to substitute "XtDefaultFont" for it,
64 which is a different size than this one. The solution for this is to
65 make x-faces.el try to use XtDefaultFont. The problem with that is that
66 XtDefaultFont is almost certainly variable-width.
68 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
70 #define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
73 static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
74 static void EmacsFrameDestroy (/* Widget */);
75 static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
76 void EmacsFrameResize (/* Widget widget */);
77 static Boolean
EmacsFrameSetValues (/* Widget, Widget, Widget,
78 ArgList, Cardinal * */);
79 static XtGeometryResult
EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
80 XtWidgetGeometry* */);
84 #define XtOffset(p_type,field) \
85 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
86 #define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
88 static XtResource resources
[] = {
89 {XtNgeometry
, XtCGeometry
, XtRString
, sizeof(String
),
90 offset (geometry
), XtRString
, (XtPointer
) 0},
91 {XtNiconic
, XtCIconic
, XtRBoolean
, sizeof(Boolean
),
92 offset (iconic
), XtRImmediate
, (XtPointer
) False
},
94 {XtNemacsFrame
, XtCEmacsFrame
, XtRPointer
, sizeof (XtPointer
),
95 offset (frame
), XtRImmediate
, 0},
97 {XtNminibuffer
, XtCMinibuffer
, XtRInt
, sizeof (int),
98 offset (minibuffer
), XtRImmediate
, (XtPointer
)0},
99 {XtNunsplittable
, XtCUnsplittable
, XtRBoolean
, sizeof (Boolean
),
100 offset (unsplittable
), XtRImmediate
, (XtPointer
)0},
101 {XtNinternalBorderWidth
, XtCInternalBorderWidth
, XtRInt
, sizeof (int),
102 offset (internal_border_width
), XtRImmediate
, (XtPointer
)4},
103 {XtNinterline
, XtCInterline
, XtRInt
, sizeof (int),
104 offset (interline
), XtRImmediate
, (XtPointer
)0},
105 {XtNfont
, XtCFont
, XtRFontStruct
, sizeof(XFontStruct
*),
106 offset(font
),XtRString
, DEFAULT_FACE_FONT
},
107 {XtNforeground
, XtCForeground
, XtRPixel
, sizeof(Pixel
),
108 offset(foreground_pixel
), XtRString
, "XtDefaultForeground"},
109 {XtNcursorColor
, XtCForeground
, XtRPixel
, sizeof(Pixel
),
110 offset(cursor_color
), XtRString
, "XtDefaultForeground"},
111 {XtNbarCursor
, XtCBarCursor
, XtRBoolean
, sizeof (Boolean
),
112 offset (bar_cursor
), XtRImmediate
, (XtPointer
)0},
113 {XtNvisualBell
, XtCVisualBell
, XtRBoolean
, sizeof (Boolean
),
114 offset (visual_bell
), XtRImmediate
, (XtPointer
)0},
115 {XtNbellVolume
, XtCBellVolume
, XtRInt
, sizeof (int),
116 offset (bell_volume
), XtRImmediate
, (XtPointer
)0},
123 emacsFrameActionsTable [] = {
124 {"keypress", key_press},
125 {"focus_in", emacs_frame_focus_handler},
126 {"focus_out", emacs_frame_focus_handler},
130 emacsFrameTranslations [] = "\
131 <KeyPress>: keypress()\n\
132 <FocusIn>: focus_in()\n\
133 <FocusOut>: focus_out()\n\
137 EmacsFrameClassRec emacsFrameClassRec
= {
139 /* superclass */ &widgetClassRec
,
140 /* class_name */ "EmacsFrame",
141 /* widget_size */ sizeof(EmacsFrameRec
),
142 /* class_initialize */ 0,
143 /* class_part_initialize */ 0,
144 /* class_inited */ FALSE
,
145 /* initialize */ EmacsFrameInitialize
,
146 /* initialize_hook */ 0,
147 /* realize */ EmacsFrameRealize
,
148 /* actions */ 0, /*emacsFrameActionsTable*/
149 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
150 /* resources */ resources
,
151 /* resource_count */ XtNumber(resources
),
152 /* xrm_class */ NULLQUARK
,
153 /* compress_motion */ TRUE
,
154 /* compress_exposure */ TRUE
,
155 /* compress_enterleave */ TRUE
,
156 /* visible_interest */ FALSE
,
157 /* destroy */ EmacsFrameDestroy
,
158 /* resize */ EmacsFrameResize
,
159 /* expose */ XtInheritExpose
,
160 /* set_values */ EmacsFrameSetValues
,
161 /* set_values_hook */ 0,
162 /* set_values_almost */ XtInheritSetValuesAlmost
,
163 /* get_values_hook */ 0,
164 /* accept_focus */ XtInheritAcceptFocus
,
165 /* version */ XtVersion
,
166 /* callback_private */ 0,
167 /* tm_table */ 0, /*emacsFrameTranslations*/
168 /* query_geometry */ EmacsFrameQueryGeometry
,
169 /* display_accelerator */ XtInheritDisplayAccelerator
,
174 WidgetClass emacsFrameClass
= (WidgetClass
) &emacsFrameClassRec
;
177 get_default_char_pixel_size (ew
, pixel_width
, pixel_height
)
182 struct frame
* f
= ew
->emacs_frame
.frame
;
183 *pixel_width
= FONT_WIDTH (f
->output_data
.x
->font
);
184 *pixel_height
= f
->output_data
.x
->line_height
;
188 pixel_to_char_size (ew
, pixel_width
, pixel_height
, char_width
, char_height
)
190 Dimension pixel_width
;
191 Dimension pixel_height
;
195 struct frame
* f
= ew
->emacs_frame
.frame
;
196 *char_width
= PIXEL_TO_CHAR_WIDTH (f
, (int) pixel_width
);
197 *char_height
= PIXEL_TO_CHAR_HEIGHT (f
, (int) pixel_height
);
201 char_to_pixel_size (ew
, char_width
, char_height
, pixel_width
, pixel_height
)
205 Dimension
* pixel_width
;
206 Dimension
* pixel_height
;
208 struct frame
* f
= ew
->emacs_frame
.frame
;
209 *pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, char_width
);
210 *pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, char_height
);
214 round_size_to_char (ew
, in_width
, in_height
, out_width
, out_height
)
218 Dimension
* out_width
;
219 Dimension
* out_height
;
223 pixel_to_char_size (ew
, in_width
, in_height
, &char_width
, &char_height
);
224 char_to_pixel_size (ew
, char_width
, char_height
, out_width
, out_height
);
233 for (wmshell
= XtParent (w
);
234 wmshell
&& !XtIsWMShell (wmshell
);
235 wmshell
= XtParent (wmshell
));
241 mark_shell_size_user_specified (wmshell
)
244 if (! XtIsWMShell (wmshell
)) abort ();
245 /* This is kind of sleazy, but I can't see how else to tell it to make it
246 mark the WM_SIZE_HINTS size as user specified when appropriate. */
247 ((WMShellWidget
) wmshell
)->wm
.size_hints
.flags
|= USSize
;
251 /* Can't have static frame locals because of some broken compilers.
252 Normally, initializing a variable like this doesn't work in emacs,
253 but it's ok in this file because it must come after lastfile (and
254 thus have its data not go into text space) because Xt needs to
255 write to initialized data objects too.
257 static Boolean first_frame_p
= True
;
263 /* The widget hierarchy is
265 argv[0] emacsShell pane Frame-NAME
266 ApplicationShell EmacsShell Paned EmacsFrame
268 We accept geometry specs in this order:
274 Other possibilities for widget hierarchies might be
276 argv[0] frame pane Frame-NAME
277 ApplicationShell EmacsShell Paned EmacsFrame
279 argv[0] Frame-NAME pane Frame-NAME
280 ApplicationShell EmacsShell Paned EmacsFrame
282 argv[0] Frame-NAME pane emacsTextPane
283 ApplicationShell EmacsFrame Paned EmacsTextPane
285 With the current setup, the text-display-area is the part which is
286 an emacs "frame", since that's the only part managed by emacs proper
287 (the menubar and the parent of the menubar and all that sort of thing
288 are managed by lwlib.)
290 The EmacsShell widget is simply a replacement for the Shell widget
291 which is able to deal with using an externally-supplied window instead
292 of always creating its own. It is not actually emacs specific, and
293 should possibly have class "Shell" instead of "EmacsShell" to simplify
298 /* Geometry of the AppShell */
302 unsigned int app_w
= 0;
303 unsigned int app_h
= 0;
305 /* Geometry of the EmacsFrame */
309 unsigned int frame_w
= 0;
310 unsigned int frame_h
= 0;
312 /* Hairily merged geometry */
315 unsigned int w
= ew
->emacs_frame
.frame
->width
;
316 unsigned int h
= ew
->emacs_frame
.frame
->height
;
319 Widget wmshell
= get_wm_shell ((Widget
) ew
);
320 /* Each Emacs shell is now independent and top-level. */
321 Widget app_shell
= wmshell
;
323 if (! XtIsSubclass (wmshell
, shellWidgetClass
)) abort ();
325 /* We don't need this for the moment. The geometry is computed in
328 /* If the EmacsFrame doesn't have a geometry but the shell does,
329 treat that as the geometry of the frame. (Is this bogus?
331 if (ew
->emacs_frame
.geometry
== 0)
332 XtVaGetValues (wmshell
, XtNgeometry
, &ew
->emacs_frame
.geometry
, 0);
334 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
335 this bogus? I'm not sure.) */
336 if (!ew
->emacs_frame
.iconic
)
337 XtVaGetValues (wmshell
, XtNiconic
, &ew
->emacs_frame
.iconic
, 0);
342 XtVaGetValues (app_shell
, XtNgeometry
, &geom
, 0);
344 app_flags
= XParseGeometry (geom
, &app_x
, &app_y
, &app_w
, &app_h
);
347 if (ew
->emacs_frame
.geometry
)
348 frame_flags
= XParseGeometry (ew
->emacs_frame
.geometry
,
354 /* If this is the first frame created:
355 ====================================
357 - Use the ApplicationShell's size/position, if specified.
358 (This is "Emacs.geometry", or the "-geometry" command line arg.)
359 - Else use the EmacsFrame's size/position.
360 (This is "*Frame-NAME.geometry")
362 - If the AppShell is iconic, the frame should be iconic.
364 AppShell comes first so that -geometry always applies to the first
365 frame created, even if there is an "every frame" entry in the
368 if (app_flags
& (XValue
| YValue
))
370 x
= app_x
; y
= app_y
;
371 flags
|= (app_flags
& (XValue
| YValue
| XNegative
| YNegative
));
373 else if (frame_flags
& (XValue
| YValue
))
375 x
= frame_x
; y
= frame_y
;
376 flags
|= (frame_flags
& (XValue
| YValue
| XNegative
| YNegative
));
379 if (app_flags
& (WidthValue
| HeightValue
))
381 w
= app_w
; h
= app_h
;
382 flags
|= (app_flags
& (WidthValue
| HeightValue
));
384 else if (frame_flags
& (WidthValue
| HeightValue
))
386 w
= frame_w
; h
= frame_h
;
387 flags
|= (frame_flags
& (WidthValue
| HeightValue
));
390 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
391 if (!ew
->emacs_frame
.iconic
)
392 XtVaGetValues (app_shell
, XtNiconic
, &ew
->emacs_frame
.iconic
, 0);
394 first_frame_p
= False
;
398 /* If this is not the first frame created:
399 ========================================
401 - use the EmacsFrame's size/position if specified
402 - Otherwise, use the ApplicationShell's size, but not position.
404 So that means that one can specify the position of the first frame
405 with "Emacs.geometry" or `-geometry'; but can only specify the
406 position of subsequent frames with "*Frame-NAME.geometry".
408 AppShell comes second so that -geometry does not apply to subsequent
409 frames when there is an "every frame" entry in the resource db,
410 but does apply to the first frame.
412 if (frame_flags
& (XValue
| YValue
))
414 x
= frame_x
; y
= frame_y
;
415 flags
|= (frame_flags
& (XValue
| YValue
| XNegative
| YNegative
));
418 if (frame_flags
& (WidthValue
| HeightValue
))
420 w
= frame_w
; h
= frame_h
;
421 flags
|= (frame_flags
& (WidthValue
| HeightValue
));
423 else if (app_flags
& (WidthValue
| HeightValue
))
427 flags
|= (app_flags
& (WidthValue
| HeightValue
));
432 struct frame
* frame
= ew
->emacs_frame
.frame
;
433 Dimension pixel_width
, pixel_height
;
434 char shell_position
[32];
436 /* Take into account the size of the scrollbar */
437 frame
->output_data
.x
->vertical_scroll_bar_extra
438 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (frame
)
440 : FRAME_SCROLL_BAR_PIXEL_WIDTH (frame
) > 0
441 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (frame
)
442 : (FRAME_SCROLL_BAR_COLS (frame
)
443 * FONT_WIDTH (frame
->output_data
.x
->font
)));
445 change_frame_size (frame
, h
, w
, 1, 0);
446 char_to_pixel_size (ew
, w
, h
, &pixel_width
, &pixel_height
);
447 ew
->core
.width
= pixel_width
;
448 ew
->core
.height
= pixel_height
;
450 #if 0 /* xfns.c takes care of this now. */
451 /* If a position was specified, assign it to the shell widget.
452 (Else WM won't do anything with it.)
454 if (flags
& (XValue
| YValue
))
456 /* the tricky things with the sign is to make sure that
460 sprintf (shell_position
, "=%c%d%c%d",
461 flags
& XNegative
? '-' : '+', x
< 0 ? -x
: x
,
462 flags
& YNegative
? '-' : '+', y
< 0 ? -y
: y
);
463 len
= strlen (shell_position
) + 1;
464 tem
= (char *) xmalloc (len
);
465 strncpy (tem
, shell_position
, len
);
466 XtVaSetValues (wmshell
, XtNgeometry
, tem
, 0);
468 else if (flags
& (WidthValue
| HeightValue
))
472 sprintf (shell_position
, "=%dx%d", pixel_width
, pixel_height
);
473 len
= strlen (shell_position
) + 1;
474 tem
= (char *) xmalloc (len
);
475 strncpy (tem
, shell_position
, len
);
476 XtVaSetValues (wmshell
, XtNgeometry
, tem
, 0);
479 /* If the geometry spec we're using has W/H components, mark the size
480 in the WM_SIZE_HINTS as user specified. */
481 if (flags
& (WidthValue
| HeightValue
))
482 mark_shell_size_user_specified (wmshell
);
484 /* Also assign the iconic status of the frame to the Shell, so that
486 XtVaSetValues (wmshell
, XtNiconic
, ew
->emacs_frame
.iconic
, 0);
491 /* Nonzero tells update_wm_hints not to do anything
492 (the caller should call update_wm_hints explicitly later.) */
493 int update_hints_inhibit
;
499 Widget wmshell
= get_wm_shell ((Widget
)ew
);
502 Dimension rounded_width
;
503 Dimension rounded_height
;
508 int min_rows
= 0, min_cols
= 0;
510 if (update_hints_inhibit
)
514 check_frame_size (ew
->emacs_frame
.frame
, &min_rows
, &min_cols
);
517 pixel_to_char_size (ew
, ew
->core
.width
, ew
->core
.height
,
518 &char_width
, &char_height
);
519 char_to_pixel_size (ew
, char_width
, char_height
,
520 &rounded_width
, &rounded_height
);
521 get_default_char_pixel_size (ew
, &cw
, &ch
);
523 base_width
= (wmshell
->core
.width
- ew
->core
.width
524 + (rounded_width
- (char_width
* cw
)));
525 base_height
= (wmshell
->core
.height
- ew
->core
.height
526 + (rounded_height
- (char_height
* ch
)));
528 /* This is kind of sleazy, but I can't see how else to tell it to
529 make it mark the WM_SIZE_HINTS size as user specified.
531 /* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
533 XtVaSetValues (wmshell
,
534 XtNbaseWidth
, base_width
,
535 XtNbaseHeight
, base_height
,
538 XtNminWidth
, base_width
+ min_cols
* cw
,
539 XtNminHeight
, base_height
+ min_rows
* ch
,
544 create_frame_gcs (ew
)
547 struct frame
*s
= ew
->emacs_frame
.frame
;
549 s
->output_data
.x
->normal_gc
550 = XCreateGC (XtDisplay (ew
), RootWindowOfScreen (XtScreen (ew
)),
551 (unsigned long)0, (XGCValues
*)0);
552 s
->output_data
.x
->reverse_gc
553 = XCreateGC (XtDisplay (ew
), RootWindowOfScreen (XtScreen (ew
)),
554 (unsigned long)0, (XGCValues
*)0);
555 s
->output_data
.x
->cursor_gc
556 = XCreateGC (XtDisplay (ew
), RootWindowOfScreen (XtScreen (ew
)),
557 (unsigned long)0, (XGCValues
*)0);
560 static char setup_frame_cursor_bits
[] =
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
573 struct frame
* s
= ew
->emacs_frame
.frame
;
574 Pixmap blank_stipple
, blank_tile
;
576 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
577 XGetGCValues returns uninitialized data when we query the stipple
578 (instead of None or something sensible) and it makes things hard.
580 This should be fixed for real by not querying the GCs but instead having
581 some GC-based cache instead of the current face-based cache which doesn't
582 effectively cache all of the GC settings we need to use.
586 = XCreateBitmapFromData (XtDisplay (ew
),
587 RootWindowOfScreen (XtScreen (ew
)),
588 setup_frame_cursor_bits
, 2, 2);
590 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
591 never actually get used as a background tile!
594 = XCreatePixmapFromBitmapData (XtDisplay(ew
),
595 RootWindowOfScreen (XtScreen (ew
)),
596 setup_frame_cursor_bits
, 2, 2,
597 (unsigned long)0, (unsigned long)1,
601 gc_values
.font
= ew
->emacs_frame
.font
->fid
;
602 gc_values
.foreground
= ew
->emacs_frame
.foreground_pixel
;
603 gc_values
.background
= ew
->core
.background_pixel
;
604 gc_values
.graphics_exposures
= False
;
605 gc_values
.stipple
= blank_stipple
;
606 gc_values
.tile
= blank_tile
;
607 XChangeGC (XtDisplay (ew
), s
->output_data
.x
->normal_gc
,
608 (GCFont
| GCForeground
| GCBackground
| GCGraphicsExposures
609 | GCStipple
| GCTile
),
612 /* Reverse video style. */
613 gc_values
.font
= ew
->emacs_frame
.font
->fid
;
614 gc_values
.foreground
= ew
->core
.background_pixel
;
615 gc_values
.background
= ew
->emacs_frame
.foreground_pixel
;
616 gc_values
.graphics_exposures
= False
;
617 gc_values
.stipple
= blank_stipple
;
618 gc_values
.tile
= blank_tile
;
619 XChangeGC (XtDisplay (ew
), s
->output_data
.x
->reverse_gc
,
620 (GCFont
| GCForeground
| GCBackground
| GCGraphicsExposures
621 | GCStipple
| GCTile
),
624 /* Cursor has to have an empty stipple. */
625 gc_values
.font
= ew
->emacs_frame
.font
->fid
;
626 gc_values
.foreground
= ew
->core
.background_pixel
;
627 gc_values
.background
= ew
->emacs_frame
.cursor_color
;
628 gc_values
.graphics_exposures
= False
;
629 gc_values
.tile
= blank_tile
;
631 = XCreateBitmapFromData (XtDisplay (ew
),
632 RootWindowOfScreen (XtScreen (ew
)),
633 setup_frame_cursor_bits
, 16, 16);
634 XChangeGC (XtDisplay (ew
), s
->output_data
.x
->cursor_gc
,
635 (GCFont
| GCForeground
| GCBackground
| GCGraphicsExposures
636 | GCStipple
| GCTile
),
641 update_various_frame_slots (ew
)
644 struct x_output
*x
= ew
->emacs_frame
.frame
->output_data
.x
;
645 x
->pixel_height
= ew
->core
.height
+ x
->menubar_height
;
646 x
->pixel_width
= ew
->core
.width
;
647 x
->internal_border_width
= ew
->emacs_frame
.internal_border_width
;
652 update_from_various_frame_slots (ew
)
655 struct x_output
*x
= ew
->emacs_frame
.frame
->output_data
.x
;
656 ew
->core
.height
= x
->pixel_height
- x
->menubar_height
;
657 ew
->core
.width
= x
->pixel_width
;
658 ew
->core
.background_pixel
= x
->background_pixel
;
659 ew
->emacs_frame
.internal_border_width
= x
->internal_border_width
;
660 ew
->emacs_frame
.font
= x
->font
;
661 ew
->emacs_frame
.foreground_pixel
= x
->foreground_pixel
;
662 ew
->emacs_frame
.cursor_color
= x
->cursor_pixel
;
663 ew
->core
.border_pixel
= x
->border_pixel
;
667 EmacsFrameInitialize (request
, new, dum1
, dum2
)
673 EmacsFrame ew
= (EmacsFrame
)new;
675 if (!ew
->emacs_frame
.frame
)
678 "can't create an emacs frame widget without a frame\n");
682 #if 0 /* done in xfns.c */
683 /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
684 resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
685 It's unfortunate that we have to do this, but we need to know the font
686 size for frame-sizing purposes before the faces get initialized. If
687 the "default.attributeFont" isn't set, then we use the font of this
688 EmacsFrame itself, defaulting to XtDefaultFont. Up in the lisp code,
689 the "default" face will use the frame's font if its own is not set,
690 so everything stays in sync -- it's not possible for the frame's font
691 and the default face's font to be different.
696 face_res
.resource_name
= "attributeFont";
697 face_res
.resource_class
= "AttributeFont";
698 face_res
.resource_type
= XtRFontStruct
;
699 face_res
.resource_size
= sizeof (XFontStruct
*);
700 face_res
.resource_offset
= 0;
701 face_res
.default_type
= XtRImmediate
;
702 face_res
.default_addr
= 0;
703 XtGetSubresources ((Widget
) ew
, (XtPointer
) &f
, "default", "Face",
704 &face_res
, 1, NULL
, 0);
707 ew
->emacs_frame
.font
= f
;
708 else if (! ew
->emacs_frame
.font
)
710 fprintf (stderr
, "emacs frame widget could not load a font\n");
715 /* Update the font field in frame */
716 ew
->emacs_frame
.frame
->output_data
.x
->font
= ew
->emacs_frame
.font
;
719 update_from_various_frame_slots (ew
);
721 /*create_frame_gcs (ew);
722 setup_frame_gcs (ew);
723 update_various_frame_slots (ew); */
728 EmacsFrameRealize (widget
, mask
, attrs
)
731 XSetWindowAttributes
*attrs
;
733 EmacsFrame ew
= (EmacsFrame
)widget
;
735 attrs
->event_mask
= (STANDARD_EVENT_SET
| PropertyChangeMask
736 | SubstructureNotifyMask
| SubstructureRedirectMask
);
737 *mask
|= CWEventMask
;
738 XtCreateWindow (widget
, InputOutput
, (Visual
*)CopyFromParent
, *mask
,
740 update_wm_hints (ew
);
743 extern void free_frame_faces (/* struct frame * */);
746 EmacsFrameDestroy (widget
)
749 EmacsFrame ew
= (EmacsFrame
) widget
;
750 struct frame
* s
= ew
->emacs_frame
.frame
;
753 if (! s
->output_data
.x
) abort ();
754 if (! s
->output_data
.x
->normal_gc
) abort ();
756 /* this would be called from Fdelete_frame() but it needs to free some
757 stuff after the widget has been finalized but before the widget has
759 free_frame_faces (s
);
762 /* need to be careful that the face-freeing code doesn't free these too */
763 XFreeGC (XtDisplay (widget
), s
->output_data
.x
->normal_gc
);
764 XFreeGC (XtDisplay (widget
), s
->output_data
.x
->reverse_gc
);
765 XFreeGC (XtDisplay (widget
), s
->output_data
.x
->cursor_gc
);
770 EmacsFrameResize (widget
)
773 EmacsFrame ew
= (EmacsFrame
)widget
;
774 struct frame
*f
= ew
->emacs_frame
.frame
;
778 pixel_to_char_size (ew
, ew
->core
.width
, ew
->core
.height
, &columns
, &rows
);
779 change_frame_size (f
, rows
, columns
, 0, 1);
780 update_wm_hints (ew
);
781 update_various_frame_slots (ew
);
785 EmacsFrameSetValues (cur_widget
, req_widget
, new_widget
, dum1
, dum2
)
792 EmacsFrame cur
= (EmacsFrame
)cur_widget
;
793 EmacsFrame
new = (EmacsFrame
)new_widget
;
795 Boolean needs_a_refresh
= False
;
796 Boolean has_to_recompute_size
;
797 Boolean has_to_recompute_gcs
;
798 Boolean has_to_update_hints
;
800 int char_width
, char_height
;
801 Dimension pixel_width
;
802 Dimension pixel_height
;
804 has_to_recompute_gcs
= (cur
->emacs_frame
.font
!= new->emacs_frame
.font
805 || (cur
->emacs_frame
.foreground_pixel
806 != new->emacs_frame
.foreground_pixel
)
807 || (cur
->core
.background_pixel
808 != new->core
.background_pixel
)
811 has_to_recompute_size
= (cur
->emacs_frame
.font
!= new->emacs_frame
.font
812 && cur
->core
.width
== new->core
.width
813 && cur
->core
.height
== new->core
.height
);
815 has_to_update_hints
= (cur
->emacs_frame
.font
!= new->emacs_frame
.font
);
817 if (has_to_recompute_gcs
)
819 setup_frame_gcs (new);
820 needs_a_refresh
= True
;
823 if (has_to_recompute_size
)
825 pixel_width
= new->core
.width
;
826 pixel_height
= new->core
.height
;
827 pixel_to_char_size (new, pixel_width
, pixel_height
, &char_width
,
829 char_to_pixel_size (new, char_width
, char_height
, &pixel_width
,
831 new->core
.width
= pixel_width
;
832 new->core
.height
= pixel_height
;
834 change_frame_size (new->emacs_frame
.frame
, char_height
, char_width
,
836 needs_a_refresh
= True
;
839 if (has_to_update_hints
)
840 update_wm_hints (new);
842 update_various_frame_slots (new);
844 /* #### This doesn't work, I haven't been able to find ANY kludge that
845 will let (x-create-frame '((iconic . t))) work. It seems that changes
846 to wm_shell's iconic slot have no effect after it has been realized,
847 and calling XIconifyWindow doesn't work either (even thought the window
848 has been created.) Perhaps there is some property we could smash
849 directly, but I'm sick of this for now.
851 if (cur
->emacs_frame
.iconic
!= new->emacs_frame
.iconic
)
853 Widget wmshell
= get_wm_shell ((Widget
) cur
);
854 XtVaSetValues (wmshell
, XtNiconic
, new->emacs_frame
.iconic
, 0);
857 return needs_a_refresh
;
860 static XtGeometryResult
861 EmacsFrameQueryGeometry (widget
, request
, result
)
863 XtWidgetGeometry
* request
;
864 XtWidgetGeometry
* result
;
866 EmacsFrame ew
= (EmacsFrame
)widget
;
868 int mask
= request
->request_mode
;
869 Dimension ok_width
, ok_height
;
871 if (mask
& (CWWidth
| CWHeight
))
873 round_size_to_char (ew
,
874 (mask
& CWWidth
) ? request
->width
: ew
->core
.width
,
875 ((mask
& CWHeight
) ? request
->height
877 &ok_width
, &ok_height
);
878 if ((mask
& CWWidth
) && (ok_width
!= request
->width
))
880 result
->request_mode
|= CWWidth
;
881 result
->width
= ok_width
;
883 if ((mask
& CWHeight
) && (ok_height
!= request
->height
))
885 result
->request_mode
|= CWHeight
;
886 result
->height
= ok_height
;
889 return result
->request_mode
? XtGeometryAlmost
: XtGeometryYes
;
892 /* Special entrypoints */
894 EmacsFrameSetCharSize (widget
, columns
, rows
)
899 EmacsFrame ew
= (EmacsFrame
) widget
;
900 Dimension pixel_width
, pixel_height
, granted_width
, granted_height
;
901 XtGeometryResult result
;
902 struct frame
*f
= ew
->emacs_frame
.frame
;
906 if (columns
< 3) columns
= 3; /* no way buddy */
908 check_frame_size (f
, &rows
, &columns
);
909 f
->output_data
.x
->vertical_scroll_bar_extra
910 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
912 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
913 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
914 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
916 char_to_pixel_size (ew
, columns
, rows
, &pixel_width
, &pixel_height
);
918 /* Manually change the height and width of all our widgets,
919 adjusting each widget by the same increments. */
920 if (ew
->core
.width
!= pixel_width
|| ew
->core
.height
!= pixel_height
)
922 int hdelta
= pixel_height
- ew
->core
.height
;
923 int wdelta
= pixel_width
- ew
->core
.width
;
924 int column_widget_height
= f
->output_data
.x
->column_widget
->core
.height
;
925 int column_widget_width
= f
->output_data
.x
->column_widget
->core
.width
;
926 int outer_widget_height
= f
->output_data
.x
->widget
->core
.height
;
927 int outer_widget_width
= f
->output_data
.x
->widget
->core
.width
;
928 int old_left
= f
->output_data
.x
->widget
->core
.x
;
929 int old_top
= f
->output_data
.x
->widget
->core
.y
;
931 lw_refigure_widget (f
->output_data
.x
->column_widget
, False
);
932 update_hints_inhibit
= 1;
935 XtSetArg (al
[ac
], XtNheight
, pixel_height
); ac
++;
936 XtSetArg (al
[ac
], XtNwidth
, pixel_width
); ac
++;
937 XtSetValues ((Widget
) ew
, al
, ac
);
940 XtSetArg (al
[ac
], XtNheight
, column_widget_height
+ hdelta
); ac
++;
941 XtSetArg (al
[ac
], XtNwidth
, column_widget_width
+ wdelta
); ac
++;
942 XtSetValues (f
->output_data
.x
->column_widget
, al
, ac
);
945 XtSetArg (al
[ac
], XtNheight
, outer_widget_height
+ hdelta
); ac
++;
946 XtSetArg (al
[ac
], XtNwidth
, outer_widget_width
+ wdelta
); ac
++;
947 XtSetValues (f
->output_data
.x
->widget
, al
, ac
);
949 lw_refigure_widget (f
->output_data
.x
->column_widget
, True
);
951 update_hints_inhibit
= 0;
952 update_wm_hints (ew
);
954 do_pending_window_change ();
956 /* These seem to get clobbered. I don't know why. - rms. */
957 f
->output_data
.x
->widget
->core
.x
= old_left
;
958 f
->output_data
.x
->widget
->core
.y
= old_top
;
961 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
962 receive in the ConfigureNotify event; if we get what we asked
963 for, then the event won't cause the screen to become garbaged, so
964 we have to make sure to do it here. */
965 SET_FRAME_GARBAGED (f
);