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, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Emacs 19 face widget ported by Fred Pierresteguy */
29 #include "dispextern.h"
32 #include <X11/StringDefs.h>
33 #include <X11/IntrinsicP.h>
34 #include <X11/cursorfont.h>
35 #include "widgetprv.h"
36 #include <X11/ObjectP.h>
37 #include <X11/Shell.h>
38 #include <X11/ShellP.h>
40 #define max(a, b) ((a) > (b) ? (a) : (b))
42 /* This sucks: this is the first default that x-faces.el tries. This won't
43 be used unless neither the "Emacs.EmacsFrame" resource nor the
44 "Emacs.EmacsFrame" resource is set; the frame
45 may have the wrong default size if this font doesn't exist, but some other
46 font that x-faces.el does. The workaround is to specify some font in the
47 resource database; I don't know a solution other than duplicating the font-
48 searching code from x-faces.el in this file.
50 This also means that if "Emacs.EmacsFrame" is specified as a non-
51 existent font, then Xt is going to substitute "XtDefaultFont" for it,
52 which is a different size than this one. The solution for this is to
53 make x-faces.el try to use XtDefaultFont. The problem with that is that
54 XtDefaultFont is almost certainly variable-width.
56 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
58 #define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
61 static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
62 static void EmacsFrameDestroy (/* Widget */);
63 static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
64 void EmacsFrameResize (/* Widget widget */);
65 static Boolean
EmacsFrameSetValues (/* Widget, Widget, Widget,
66 ArgList, Cardinal * */);
67 static XtGeometryResult
EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
68 XtWidgetGeometry* */);
72 #define XtOffset(p_type,field) \
73 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
74 #define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
76 static XtResource resources
[] = {
77 {XtNgeometry
, XtCGeometry
, XtRString
, sizeof(String
),
78 offset (geometry
), XtRString
, (XtPointer
) 0},
79 {XtNiconic
, XtCIconic
, XtRBoolean
, sizeof(Boolean
),
80 offset (iconic
), XtRImmediate
, (XtPointer
) False
},
82 {XtNemacsFrame
, XtCEmacsFrame
, XtRPointer
, sizeof (XtPointer
),
83 offset (frame
), XtRImmediate
, 0},
85 {XtNminibuffer
, XtCMinibuffer
, XtRInt
, sizeof (int),
86 offset (minibuffer
), XtRImmediate
, (XtPointer
)0},
87 {XtNunsplittable
, XtCUnsplittable
, XtRBoolean
, sizeof (Boolean
),
88 offset (unsplittable
), XtRImmediate
, (XtPointer
)0},
89 {XtNinternalBorderWidth
, XtCInternalBorderWidth
, XtRInt
, sizeof (int),
90 offset (internal_border_width
), XtRImmediate
, (XtPointer
)4},
91 {XtNinterline
, XtCInterline
, XtRInt
, sizeof (int),
92 offset (interline
), XtRImmediate
, (XtPointer
)0},
93 {XtNfont
, XtCFont
, XtRFontStruct
, sizeof(XFontStruct
*),
94 offset(font
),XtRString
, DEFAULT_FACE_FONT
},
95 {XtNforeground
, XtCForeground
, XtRPixel
, sizeof(Pixel
),
96 offset(foreground_pixel
), XtRString
, "XtDefaultForeground"},
97 {XtNcursorColor
, XtCForeground
, XtRPixel
, sizeof(Pixel
),
98 offset(cursor_color
), XtRString
, "XtDefaultForeground"},
99 {XtNbarCursor
, XtCBarCursor
, XtRBoolean
, sizeof (Boolean
),
100 offset (bar_cursor
), XtRImmediate
, (XtPointer
)0},
101 {XtNvisualBell
, XtCVisualBell
, XtRBoolean
, sizeof (Boolean
),
102 offset (visual_bell
), XtRImmediate
, (XtPointer
)0},
103 {XtNbellVolume
, XtCBellVolume
, XtRInt
, sizeof (int),
104 offset (bell_volume
), XtRImmediate
, (XtPointer
)0},
111 emacsFrameActionsTable [] = {
112 {"keypress", key_press},
113 {"focus_in", emacs_frame_focus_handler},
114 {"focus_out", emacs_frame_focus_handler},
118 emacsFrameTranslations [] = "\
119 <KeyPress>: keypress()\n\
120 <FocusIn>: focus_in()\n\
121 <FocusOut>: focus_out()\n\
125 EmacsFrameClassRec emacsFrameClassRec
= {
127 /* superclass */ &widgetClassRec
,
128 /* class_name */ "EmacsFrame",
129 /* widget_size */ sizeof(EmacsFrameRec
),
130 /* class_initialize */ 0,
131 /* class_part_initialize */ 0,
132 /* class_inited */ FALSE
,
133 /* initialize */ EmacsFrameInitialize
,
134 /* initialize_hook */ 0,
135 /* realize */ EmacsFrameRealize
,
136 /* actions */ 0, /*emacsFrameActionsTable*/
137 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
138 /* resources */ resources
,
139 /* resource_count */ XtNumber(resources
),
140 /* xrm_class */ NULLQUARK
,
141 /* compress_motion */ TRUE
,
142 /* compress_exposure */ TRUE
,
143 /* compress_enterleave */ TRUE
,
144 /* visible_interest */ FALSE
,
145 /* destroy */ EmacsFrameDestroy
,
146 /* resize */ EmacsFrameResize
,
147 /* expose */ XtInheritExpose
,
148 /* set_values */ EmacsFrameSetValues
,
149 /* set_values_hook */ 0,
150 /* set_values_almost */ XtInheritSetValuesAlmost
,
151 /* get_values_hook */ 0,
152 /* accept_focus */ XtInheritAcceptFocus
,
153 /* version */ XtVersion
,
154 /* callback_private */ 0,
155 /* tm_table */ 0, /*emacsFrameTranslations*/
156 /* query_geometry */ EmacsFrameQueryGeometry
,
157 /* display_accelerator */ XtInheritDisplayAccelerator
,
162 WidgetClass emacsFrameClass
= (WidgetClass
) &emacsFrameClassRec
;
165 get_default_char_pixel_size (ew
, pixel_width
, pixel_height
)
171 *pixel_width = XTextWidth (ew->emacs_frame.font, "n", 1);
173 ew->emacs_frame.font->ascent + ew->emacs_frame.font->descent;
175 struct frame
* f
= ew
->emacs_frame
.frame
;
176 *pixel_width
= FONT_WIDTH (f
->display
.x
->font
);
177 *pixel_height
= FONT_HEIGHT (f
->display
.x
->font
);
181 pixel_to_char_size (ew
, pixel_width
, pixel_height
, char_width
, char_height
)
183 Dimension pixel_width
;
184 Dimension pixel_height
;
188 struct frame
* f
= ew
->emacs_frame
.frame
;
189 *char_width
= PIXEL_TO_CHAR_WIDTH (f
, pixel_width
);
190 *char_height
= PIXEL_TO_CHAR_HEIGHT (f
, pixel_height
);
194 char_to_pixel_size (ew
, char_width
, char_height
, pixel_width
, pixel_height
)
198 Dimension
* pixel_width
;
199 Dimension
* pixel_height
;
201 struct frame
* f
= ew
->emacs_frame
.frame
;
202 *pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, char_width
);
203 *pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, char_height
);
207 round_size_to_char (ew
, in_width
, in_height
, out_width
, out_height
)
211 Dimension
* out_width
;
212 Dimension
* out_height
;
216 pixel_to_char_size (ew
, in_width
, in_height
, &char_width
, &char_height
);
217 char_to_pixel_size (ew
, char_width
, char_height
, out_width
, out_height
);
226 for (wmshell
= XtParent (w
);
227 wmshell
&& !XtIsWMShell (wmshell
);
228 wmshell
= XtParent (wmshell
));
234 mark_shell_size_user_specified (wmshell
)
237 if (! XtIsWMShell (wmshell
)) abort ();
238 /* This is kind of sleazy, but I can't see how else to tell it to make it
239 mark the WM_SIZE_HINTS size as user specified when appropriate. */
240 ((WMShellWidget
) wmshell
)->wm
.size_hints
.flags
|= USSize
;
244 /* Can't have static frame locals because of some broken compilers.
245 Normally, initializing a variable like this doesn't work in emacs,
246 but it's ok in this file because it must come after lastfile (and
247 thus have its data not go into text space) because Xt needs to
248 write to initialized data objects too.
250 static Boolean first_frame_p
= True
;
256 /* The widget hierarchy is
258 argv[0] emacsShell pane Frame-NAME
259 ApplicationShell EmacsShell Paned EmacsFrame
261 We accept geometry specs in this order:
267 Other possibilities for widget hierarchies might be
269 argv[0] frame pane Frame-NAME
270 ApplicationShell EmacsShell Paned EmacsFrame
272 argv[0] Frame-NAME pane Frame-NAME
273 ApplicationShell EmacsShell Paned EmacsFrame
275 argv[0] Frame-NAME pane emacsTextPane
276 ApplicationShell EmacsFrame Paned EmacsTextPane
278 With the current setup, the text-display-area is the part which is
279 an emacs "frame", since that's the only part managed by emacs proper
280 (the menubar and the parent of the menubar and all that sort of thing
281 are managed by lwlib.)
283 The EmacsShell widget is simply a replacement for the Shell widget
284 which is able to deal with using an externally-supplied window instead
285 of always creating its own. It is not actually emacs specific, and
286 should possibly have class "Shell" instead of "EmacsShell" to simplify
291 /* Geometry of the AppShell */
295 unsigned int app_w
= 0;
296 unsigned int app_h
= 0;
298 /* Geometry of the EmacsFrame */
302 unsigned int frame_w
= 0;
303 unsigned int frame_h
= 0;
305 /* Hairily merged geometry */
308 unsigned int w
= ew
->emacs_frame
.frame
->width
;
309 unsigned int h
= ew
->emacs_frame
.frame
->height
;
312 Widget wmshell
= get_wm_shell ((Widget
) ew
);
313 Widget app_shell
= XtParent ((Widget
) wmshell
);
316 if (! XtIsSubclass (wmshell
, shellWidgetClass
)) abort ();
317 if (! XtIsSubclass (app_shell
, shellWidgetClass
)) abort ();
319 /* If the EmacsFrame doesn't have a geometry but the shell does,
320 treat that as the geometry of the frame. (Is this bogus?
322 if (ew
->emacs_frame
.geometry
== 0)
323 XtVaGetValues (wmshell
, XtNgeometry
, &ew
->emacs_frame
.geometry
, 0);
325 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
326 this bogus? I'm not sure.) */
327 if (!ew
->emacs_frame
.iconic
)
328 XtVaGetValues (wmshell
, XtNiconic
, &ew
->emacs_frame
.iconic
, 0);
333 XtVaGetValues (app_shell
, XtNgeometry
, &geom
, 0);
335 app_flags
= XParseGeometry (geom
, &app_x
, &app_y
, &app_w
, &app_h
);
338 if (ew
->emacs_frame
.geometry
)
339 frame_flags
= XParseGeometry (ew
->emacs_frame
.geometry
,
345 /* If this is the first frame created:
346 ====================================
348 - Use the ApplicationShell's size/position, if specified.
349 (This is "Emacs.geometry", or the "-geometry" command line arg.)
350 - Else use the EmacsFrame's size/position.
351 (This is "*Frame-NAME.geometry")
353 - If the AppShell is iconic, the frame should be iconic.
355 AppShell comes first so that -geometry always applies to the first
356 frame created, even if there is an "every frame" entry in the
359 if (app_flags
& (XValue
| YValue
))
361 x
= app_x
; y
= app_y
;
362 flags
|= (app_flags
& (XValue
| YValue
| XNegative
| YNegative
));
364 else if (frame_flags
& (XValue
| YValue
))
366 x
= frame_x
; y
= frame_y
;
367 flags
|= (frame_flags
& (XValue
| YValue
| XNegative
| YNegative
));
370 if (app_flags
& (WidthValue
| HeightValue
))
372 w
= app_w
; h
= app_h
;
373 flags
|= (app_flags
& (WidthValue
| HeightValue
));
375 else if (frame_flags
& (WidthValue
| HeightValue
))
377 w
= frame_w
; h
= frame_h
;
378 flags
|= (frame_flags
& (WidthValue
| HeightValue
));
381 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
382 if (!ew
->emacs_frame
.iconic
)
383 XtVaGetValues (app_shell
, XtNiconic
, &ew
->emacs_frame
.iconic
, 0);
385 first_frame_p
= False
;
389 /* If this is not the first frame created:
390 ========================================
392 - use the EmacsFrame's size/position if specified
393 - Otherwise, use the ApplicationShell's size, but not position.
395 So that means that one can specify the position of the first frame
396 with "Emacs.geometry" or `-geometry'; but can only specify the
397 position of subsequent frames with "*Frame-NAME.geometry".
399 AppShell comes second so that -geometry does not apply to subsequent
400 frames when there is an "every frame" entry in the resource db,
401 but does apply to the first frame.
403 if (frame_flags
& (XValue
| YValue
))
405 x
= frame_x
; y
= frame_y
;
406 flags
|= (frame_flags
& (XValue
| YValue
| XNegative
| YNegative
));
409 if (frame_flags
& (WidthValue
| HeightValue
))
411 w
= frame_w
; h
= frame_h
;
412 flags
|= (frame_flags
& (WidthValue
| HeightValue
));
414 else if (app_flags
& (WidthValue
| HeightValue
))
418 flags
|= (app_flags
& (WidthValue
| HeightValue
));
423 struct frame
* frame
= ew
->emacs_frame
.frame
;
424 Dimension pixel_width
, pixel_height
;
425 char shell_position
[32];
427 /* Take into account the size of the scrollbar */
428 frame
->display
.x
->vertical_scroll_bar_extra
429 = (FRAME_HAS_VERTICAL_SCROLL_BARS (frame
)
430 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (frame
)
434 change_frame_size (frame
, h
, w
, 1, 0);
435 char_to_pixel_size (ew
, w
, h
, &pixel_width
, &pixel_height
);
436 ew
->core
.width
= pixel_width
;
437 ew
->core
.height
= pixel_height
;
440 /* If a position was specified, assign it to the shell widget.
441 (Else WM won't do anything with it.)
443 if (flags
& (XValue
| YValue
))
445 /* the tricky things with the sign is to make sure that
449 sprintf (shell_position
, "=%c%d%c%d",
450 flags
& XNegative
? '-' : '+', x
< 0 ? -x
: x
,
451 flags
& YNegative
? '-' : '+', y
< 0 ? -y
: y
);
452 len
= strlen (shell_position
) + 1;
453 tem
= (char *) xmalloc (len
);
454 strncpy (tem
, shell_position
, len
);
455 XtVaSetValues (wmshell
, XtNgeometry
, tem
, 0);
457 else if (flags
& (WidthValue
| HeightValue
))
461 sprintf (shell_position
, "=%dx%d", pixel_width
, pixel_height
);
462 len
= strlen (shell_position
) + 1;
463 tem
= (char *) xmalloc (len
);
464 strncpy (tem
, shell_position
, len
);
465 XtVaSetValues (wmshell
, XtNgeometry
, tem
, 0);
468 /* If the geometry spec we're using has W/H components, mark the size
469 in the WM_SIZE_HINTS as user specified. */
470 if (flags
& (WidthValue
| HeightValue
))
471 mark_shell_size_user_specified (wmshell
);
473 /* Also assign the iconic status of the frame to the Shell, so that
475 XtVaSetValues (wmshell
, XtNiconic
, ew
->emacs_frame
.iconic
, 0);
484 Widget wmshell
= get_wm_shell ((Widget
)ew
);
487 Dimension rounded_width
;
488 Dimension rounded_height
;
493 int min_rows
= 0, min_cols
= 0;
495 check_frame_size (ew
->emacs_frame
.frame
, &min_rows
, &min_cols
);
497 pixel_to_char_size (ew
, ew
->core
.width
, ew
->core
.height
,
498 &char_width
, &char_height
);
499 char_to_pixel_size (ew
, char_width
, char_height
,
500 &rounded_width
, &rounded_height
);
501 get_default_char_pixel_size (ew
, &cw
, &ch
);
503 base_width
= (wmshell
->core
.width
- ew
->core
.width
504 + (rounded_width
- (char_width
* cw
)));
505 base_height
= (wmshell
->core
.height
- ew
->core
.height
506 + (rounded_height
- (char_height
* ch
)));
508 /* This is kind of sleazy, but I can't see how else to tell it to
509 make it mark the WM_SIZE_HINTS size as user specified.
511 /* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
513 XtVaSetValues (wmshell
,
514 XtNbaseWidth
, base_width
,
515 XtNbaseHeight
, base_height
,
518 XtNminWidth
, base_width
+ min_cols
* cw
,
519 XtNminHeight
, base_height
+ min_rows
* ch
,
524 create_frame_gcs (ew
)
527 struct frame
* s
= ew
->emacs_frame
.frame
;
529 s
->display
.x
->normal_gc
=
530 XCreateGC (XtDisplay (ew
), RootWindowOfScreen (XtScreen (ew
)), 0, 0);
531 s
->display
.x
->reverse_gc
=
532 XCreateGC (XtDisplay (ew
), RootWindowOfScreen (XtScreen (ew
)), 0, 0);
533 s
->display
.x
->cursor_gc
=
534 XCreateGC (XtDisplay (ew
), RootWindowOfScreen (XtScreen (ew
)), 0, 0);
542 struct frame
* s
= ew
->emacs_frame
.frame
;
543 Pixmap blank_stipple
, blank_tile
;
545 static char cursor_bits
[] =
547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
549 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
550 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
553 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
554 XGetGCValues returns uninitialized data when we query the stipple
555 (instead of None or something sensible) and it makes things hard.
557 This should be fixed for real by not querying the GCs but instead having
558 some GC-based cache instead of the current face-based cache which doesn't
559 effectively cache all of the GC settings we need to use.
563 XCreateBitmapFromData (XtDisplay (ew
), RootWindowOfScreen (XtScreen (ew
)),
566 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
567 never actually get used as a background tile!
570 XCreatePixmapFromBitmapData (XtDisplay(ew
),
571 RootWindowOfScreen (XtScreen (ew
)),
572 cursor_bits
, 2, 2, 0, 1, ew
->core
.depth
);
575 gc_values
.font
= ew
->emacs_frame
.font
->fid
;
576 gc_values
.foreground
= ew
->emacs_frame
.foreground_pixel
;
577 gc_values
.background
= ew
->core
.background_pixel
;
578 gc_values
.graphics_exposures
= False
;
579 gc_values
.stipple
= blank_stipple
;
580 gc_values
.tile
= blank_tile
;
581 XChangeGC (XtDisplay (ew
), s
->display
.x
->normal_gc
,
582 (GCFont
| GCForeground
| GCBackground
| GCGraphicsExposures
583 | GCStipple
| GCTile
),
586 /* Reverse video style. */
587 gc_values
.font
= ew
->emacs_frame
.font
->fid
;
588 gc_values
.foreground
= ew
->core
.background_pixel
;
589 gc_values
.background
= ew
->emacs_frame
.foreground_pixel
;
590 gc_values
.graphics_exposures
= False
;
591 gc_values
.stipple
= blank_stipple
;
592 gc_values
.tile
= blank_tile
;
593 XChangeGC (XtDisplay (ew
), s
->display
.x
->reverse_gc
,
594 (GCFont
| GCForeground
| GCBackground
| GCGraphicsExposures
595 | GCStipple
| GCTile
),
598 /* Cursor has to have an empty stipple. */
599 gc_values
.font
= ew
->emacs_frame
.font
->fid
;
600 gc_values
.foreground
= ew
->core
.background_pixel
;
601 gc_values
.background
= ew
->emacs_frame
.cursor_color
;
602 gc_values
.graphics_exposures
= False
;
603 gc_values
.tile
= blank_tile
;
605 XCreateBitmapFromData (XtDisplay (ew
),
606 RootWindowOfScreen (XtScreen (ew
)),
607 cursor_bits
, 16, 16);
608 XChangeGC (XtDisplay (ew
), s
->display
.x
->cursor_gc
,
609 (GCFont
| GCForeground
| GCBackground
| GCGraphicsExposures
610 | GCStipple
| GCTile
),
615 update_various_frame_slots (ew
)
618 struct x_display
* x
= ew
->emacs_frame
.frame
->display
.x
;
619 x
->pixel_height
= ew
->core
.height
;
620 x
->pixel_width
= ew
->core
.width
;
621 x
->internal_border_width
= ew
->emacs_frame
.internal_border_width
;
626 update_from_various_frame_slots (ew
)
629 struct x_display
* x
= ew
->emacs_frame
.frame
->display
.x
;
630 ew
->core
.height
= x
->pixel_height
;
631 ew
->core
.width
= x
->pixel_width
;
632 ew
->core
.background_pixel
= x
->background_pixel
;
633 ew
->emacs_frame
.internal_border_width
= x
->internal_border_width
;
634 ew
->emacs_frame
.font
= x
->font
;
635 ew
->emacs_frame
.foreground_pixel
= x
->foreground_pixel
;
636 ew
->emacs_frame
.cursor_color
= x
->cursor_pixel
;
637 ew
->core
.border_pixel
= x
->border_pixel
;
641 EmacsFrameInitialize (request
, new, dum1
, dum2
)
647 EmacsFrame ew
= (EmacsFrame
)new;
649 if (!ew
->emacs_frame
.frame
)
652 "can't create an emacs frame widget without a frame\n");
656 #if 0 /* done in xfns.c */
657 /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
658 resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
659 It's unfortunate that we have to do this, but we need to know the font
660 size for frame-sizing purposes before the faces get initialized. If
661 the "default.attributeFont" isn't set, then we use the font of this
662 EmacsFrame itself, defaulting to XtDefaultFont. Up in the lisp code,
663 the "default" face will use the frame's font if its own is not set,
664 so everything stays in sync -- it's not possible for the frame's font
665 and the default face's font to be different.
670 face_res
.resource_name
= "attributeFont";
671 face_res
.resource_class
= "AttributeFont";
672 face_res
.resource_type
= XtRFontStruct
;
673 face_res
.resource_size
= sizeof (XFontStruct
*);
674 face_res
.resource_offset
= 0;
675 face_res
.default_type
= XtRImmediate
;
676 face_res
.default_addr
= 0;
677 XtGetSubresources ((Widget
) ew
, (XtPointer
) &f
, "default", "Face",
678 &face_res
, 1, NULL
, 0);
681 ew
->emacs_frame
.font
= f
;
682 else if (! ew
->emacs_frame
.font
)
684 fprintf (stderr
, "emacs frame widget could not load a font\n");
689 /* Update the font field in frame */
690 ew
->emacs_frame
.frame
->display
.x
->font
= ew
->emacs_frame
.font
;
693 update_from_various_frame_slots (ew
);
695 /*create_frame_gcs (ew);
696 setup_frame_gcs (ew);
697 update_various_frame_slots (ew); */
702 EmacsFrameRealize (widget
, mask
, attrs
)
705 XSetWindowAttributes
*attrs
;
707 EmacsFrame ew
= (EmacsFrame
)widget
;
709 attrs
->event_mask
= (KeyPressMask
| ExposureMask
| ButtonPressMask
|
710 ButtonReleaseMask
| StructureNotifyMask
|
711 FocusChangeMask
| PointerMotionHintMask
|
712 PointerMotionMask
| LeaveWindowMask
| EnterWindowMask
|
713 VisibilityChangeMask
| PropertyChangeMask
|
714 StructureNotifyMask
| SubstructureNotifyMask
|
715 SubstructureRedirectMask
);
716 *mask
|= CWEventMask
;
717 XtCreateWindow (widget
, InputOutput
, (Visual
*)CopyFromParent
, *mask
,
719 update_wm_hints (ew
);
722 extern void free_frame_faces (/* struct frame * */);
725 EmacsFrameDestroy (widget
)
728 EmacsFrame ew
= (EmacsFrame
) widget
;
729 struct frame
* s
= ew
->emacs_frame
.frame
;
732 if (! s
->display
.x
) abort ();
733 if (! s
->display
.x
->normal_gc
) abort ();
735 /* this would be called from Fdelete_frame() but it needs to free some
736 stuff after the widget has been finalized but before the widget has
738 free_frame_faces (s
);
740 /* need to be careful that the face-freeing code doesn't free these too */
741 XFreeGC (XtDisplay (widget
), s
->display
.x
->normal_gc
);
742 XFreeGC (XtDisplay (widget
), s
->display
.x
->reverse_gc
);
743 XFreeGC (XtDisplay (widget
), s
->display
.x
->cursor_gc
);
747 EmacsFrameResize (widget
)
750 EmacsFrame ew
= (EmacsFrame
)widget
;
751 struct frame
*f
= ew
->emacs_frame
.frame
;
755 pixel_to_char_size (ew
, ew
->core
.width
, ew
->core
.height
, &columns
, &rows
);
756 change_frame_size (f
, rows
, columns
, 1, 0);
757 update_wm_hints (ew
);
758 update_various_frame_slots (ew
);
762 EmacsFrameSetValues (cur_widget
, req_widget
, new_widget
, dum1
, dum2
)
769 EmacsFrame cur
= (EmacsFrame
)cur_widget
;
770 EmacsFrame
new = (EmacsFrame
)new_widget
;
772 Boolean needs_a_refresh
= False
;
773 Boolean has_to_recompute_size
;
774 Boolean has_to_recompute_gcs
;
775 Boolean has_to_update_hints
;
777 int char_width
, char_height
;
778 Dimension pixel_width
;
779 Dimension pixel_height
;
781 has_to_recompute_gcs
= (cur
->emacs_frame
.font
!= new->emacs_frame
.font
782 || (cur
->emacs_frame
.foreground_pixel
783 != new->emacs_frame
.foreground_pixel
)
784 || (cur
->core
.background_pixel
785 != new->core
.background_pixel
)
788 has_to_recompute_size
= (cur
->emacs_frame
.font
!= new->emacs_frame
.font
789 && cur
->core
.width
== new->core
.width
790 && cur
->core
.height
== new->core
.height
);
792 has_to_update_hints
= (cur
->emacs_frame
.font
!= new->emacs_frame
.font
);
794 if (has_to_recompute_gcs
)
796 setup_frame_gcs (new);
797 needs_a_refresh
= True
;
800 if (has_to_recompute_size
)
802 pixel_width
= new->core
.width
;
803 pixel_height
= new->core
.height
;
804 pixel_to_char_size (new, pixel_width
, pixel_height
, &char_width
,
806 char_to_pixel_size (new, char_width
, char_height
, &pixel_width
,
808 new->core
.width
= pixel_width
;
809 new->core
.height
= pixel_height
;
811 change_frame_size (new->emacs_frame
.frame
, char_height
, char_width
,
813 needs_a_refresh
= True
;
816 if (has_to_update_hints
)
817 update_wm_hints (new);
819 update_various_frame_slots (new);
821 /* #### This doesn't work, I haven't been able to find ANY kludge that
822 will let (x-create-frame '((iconic . t))) work. It seems that changes
823 to wm_shell's iconic slot have no effect after it has been realized,
824 and calling XIconifyWindow doesn't work either (even thought the window
825 has been created.) Perhaps there is some property we could smash
826 directly, but I'm sick of this for now. Xt is a steaming pile of shit!
828 if (cur
->emacs_frame
.iconic
!= new->emacs_frame
.iconic
)
830 Widget wmshell
= get_wm_shell ((Widget
) cur
);
831 XtVaSetValues (wmshell
, XtNiconic
, new->emacs_frame
.iconic
, 0);
834 return needs_a_refresh
;
837 static XtGeometryResult
838 EmacsFrameQueryGeometry (widget
, request
, result
)
840 XtWidgetGeometry
* request
;
841 XtWidgetGeometry
* result
;
843 EmacsFrame ew
= (EmacsFrame
)widget
;
845 int mask
= request
->request_mode
;
846 Dimension ok_width
, ok_height
;
848 if (mask
& (CWWidth
| CWHeight
))
850 round_size_to_char (ew
,
851 (mask
& CWWidth
) ? request
->width
: ew
->core
.width
,
852 ((mask
& CWHeight
) ? request
->height
854 &ok_width
, &ok_height
);
855 if ((mask
& CWWidth
) && (ok_width
!= request
->width
))
857 result
->request_mode
|= CWWidth
;
858 result
->width
= ok_width
;
860 if ((mask
& CWHeight
) && (ok_height
!= request
->height
))
862 result
->request_mode
|= CWHeight
;
863 result
->height
= ok_height
;
866 return result
->request_mode
? XtGeometryAlmost
: XtGeometryYes
;
870 /* I don't know why this is necessary; Matthieu said he had to do
871 it to make the focus handlers work??
874 key_press (w
, event
, params
, n_params
)
883 emacs_frame_focus_handler (w
, event
, params
, n_params
)
889 emacs_Xt_focus_event_handler (event
, 0);
893 /* Special entrypoints */
895 EmacsFrameSetCharSize (widget
, columns
, rows
)
900 EmacsFrame ew
= (EmacsFrame
) widget
;
901 Dimension pixel_width
, pixel_height
, granted_width
, granted_height
;
902 XtGeometryResult result
;
903 if (columns
< 3) columns
= 3; /* no way buddy */
904 if (rows
< 3) rows
= 3;
906 char_to_pixel_size (ew
, columns
, rows
, &pixel_width
, &pixel_height
);
907 result
= XtMakeResizeRequest ((Widget
)ew
,
908 pixel_width
, pixel_height
,
909 &granted_width
, &granted_height
);
910 if (result
== XtGeometryAlmost
)
911 XtMakeResizeRequest ((Widget
) ew
, granted_width
, granted_height
,
913 /* damn Paned widget won't ever change its width. Force it. */
914 if (ew
->core
.width
!= pixel_width
)
916 XtVaSetValues (XtParent ((Widget
) ew
), XtNwidth
, pixel_width
, 0);
917 XtVaSetValues ((Widget
) ew
, XtNwidth
, pixel_width
, 0);