1 /* The emacs frame widget.
2 Copyright (C) 1992, 1993, 2000 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/
42 #include "dispextern.h"
43 #include "blockinput.h"
45 #include <X11/StringDefs.h>
46 #include <X11/IntrinsicP.h>
47 #include <X11/cursorfont.h>
48 #include "widgetprv.h"
49 #include <X11/ObjectP.h>
50 #include <X11/Shell.h>
51 #include <X11/ShellP.h>
52 #include "../lwlib/lwlib.h"
54 #define max(a, b) ((a) > (b) ? (a) : (b))
56 /* This sucks: this is the first default that x-faces.el tries. This won't
57 be used unless neither the "Emacs.EmacsFrame" resource nor the
58 "Emacs.EmacsFrame" resource is set; the frame
59 may have the wrong default size if this font doesn't exist, but some other
60 font that x-faces.el does. The workaround is to specify some font in the
61 resource database; I don't know a solution other than duplicating the font-
62 searching code from x-faces.el in this file.
64 This also means that if "Emacs.EmacsFrame" is specified as a non-
65 existent font, then Xt is going to substitute "XtDefaultFont" for it,
66 which is a different size than this one. The solution for this is to
67 make x-faces.el try to use XtDefaultFont. The problem with that is that
68 XtDefaultFont is almost certainly variable-width.
70 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
72 #define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
75 static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
76 static void EmacsFrameDestroy (/* Widget */);
77 static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
78 void EmacsFrameResize (/* Widget widget */);
79 static Boolean
EmacsFrameSetValues (/* Widget, Widget, Widget,
80 ArgList, Cardinal * */);
81 static XtGeometryResult
EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
82 XtWidgetGeometry* */);
86 #define XtOffset(p_type,field) \
87 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
88 #define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
90 static XtResource resources
[] = {
91 {XtNgeometry
, XtCGeometry
, XtRString
, sizeof(String
),
92 offset (geometry
), XtRString
, (XtPointer
) 0},
93 {XtNiconic
, XtCIconic
, XtRBoolean
, sizeof(Boolean
),
94 offset (iconic
), XtRImmediate
, (XtPointer
) False
},
96 {XtNemacsFrame
, XtCEmacsFrame
, XtRPointer
, sizeof (XtPointer
),
97 offset (frame
), XtRImmediate
, 0},
99 {XtNminibuffer
, XtCMinibuffer
, XtRInt
, sizeof (int),
100 offset (minibuffer
), XtRImmediate
, (XtPointer
)0},
101 {XtNunsplittable
, XtCUnsplittable
, XtRBoolean
, sizeof (Boolean
),
102 offset (unsplittable
), XtRImmediate
, (XtPointer
)0},
103 {XtNinternalBorderWidth
, XtCInternalBorderWidth
, XtRInt
, sizeof (int),
104 offset (internal_border_width
), XtRImmediate
, (XtPointer
)4},
105 {XtNinterline
, XtCInterline
, XtRInt
, sizeof (int),
106 offset (interline
), XtRImmediate
, (XtPointer
)0},
107 {XtNfont
, XtCFont
, XtRFontStruct
, sizeof(XFontStruct
*),
108 offset(font
),XtRString
, DEFAULT_FACE_FONT
},
109 {XtNforeground
, XtCForeground
, XtRPixel
, sizeof(Pixel
),
110 offset(foreground_pixel
), XtRString
, "XtDefaultForeground"},
111 {XtNcursorColor
, XtCForeground
, XtRPixel
, sizeof(Pixel
),
112 offset(cursor_color
), XtRString
, "XtDefaultForeground"},
113 {XtNbarCursor
, XtCBarCursor
, XtRBoolean
, sizeof (Boolean
),
114 offset (bar_cursor
), XtRImmediate
, (XtPointer
)0},
115 {XtNvisualBell
, XtCVisualBell
, XtRBoolean
, sizeof (Boolean
),
116 offset (visual_bell
), XtRImmediate
, (XtPointer
)0},
117 {XtNbellVolume
, XtCBellVolume
, XtRInt
, sizeof (int),
118 offset (bell_volume
), XtRImmediate
, (XtPointer
)0},
125 emacsFrameActionsTable [] = {
126 {"keypress", key_press},
127 {"focus_in", emacs_frame_focus_handler},
128 {"focus_out", emacs_frame_focus_handler},
132 emacsFrameTranslations [] = "\
133 <KeyPress>: keypress()\n\
134 <FocusIn>: focus_in()\n\
135 <FocusOut>: focus_out()\n\
139 EmacsFrameClassRec emacsFrameClassRec
= {
141 /* superclass */ &widgetClassRec
,
142 /* class_name */ "EmacsFrame",
143 /* widget_size */ sizeof(EmacsFrameRec
),
144 /* class_initialize */ 0,
145 /* class_part_initialize */ 0,
146 /* class_inited */ FALSE
,
147 /* initialize */ EmacsFrameInitialize
,
148 /* initialize_hook */ 0,
149 /* realize */ EmacsFrameRealize
,
150 /* actions */ 0, /*emacsFrameActionsTable*/
151 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
152 /* resources */ resources
,
153 /* resource_count */ XtNumber(resources
),
154 /* xrm_class */ NULLQUARK
,
155 /* compress_motion */ TRUE
,
156 /* compress_exposure */ TRUE
,
157 /* compress_enterleave */ TRUE
,
158 /* visible_interest */ FALSE
,
159 /* destroy */ EmacsFrameDestroy
,
160 /* resize */ EmacsFrameResize
,
161 /* expose */ XtInheritExpose
,
162 /* set_values */ EmacsFrameSetValues
,
163 /* set_values_hook */ 0,
164 /* set_values_almost */ XtInheritSetValuesAlmost
,
165 /* get_values_hook */ 0,
166 /* accept_focus */ XtInheritAcceptFocus
,
167 /* version */ XtVersion
,
168 /* callback_private */ 0,
169 /* tm_table */ 0, /*emacsFrameTranslations*/
170 /* query_geometry */ EmacsFrameQueryGeometry
,
171 /* display_accelerator */ XtInheritDisplayAccelerator
,
176 WidgetClass emacsFrameClass
= (WidgetClass
) &emacsFrameClassRec
;
179 get_default_char_pixel_size (ew
, pixel_width
, pixel_height
)
184 struct frame
* f
= ew
->emacs_frame
.frame
;
185 *pixel_width
= FONT_WIDTH (f
->output_data
.x
->font
);
186 *pixel_height
= f
->output_data
.x
->line_height
;
190 pixel_to_char_size (ew
, pixel_width
, pixel_height
, char_width
, char_height
)
192 Dimension pixel_width
;
193 Dimension pixel_height
;
197 struct frame
* f
= ew
->emacs_frame
.frame
;
198 *char_width
= PIXEL_TO_CHAR_WIDTH (f
, (int) pixel_width
);
199 *char_height
= PIXEL_TO_CHAR_HEIGHT (f
, (int) pixel_height
);
203 char_to_pixel_size (ew
, char_width
, char_height
, pixel_width
, pixel_height
)
207 Dimension
* pixel_width
;
208 Dimension
* pixel_height
;
210 struct frame
* f
= ew
->emacs_frame
.frame
;
211 *pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, char_width
);
212 *pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, char_height
);
216 round_size_to_char (ew
, in_width
, in_height
, out_width
, out_height
)
220 Dimension
* out_width
;
221 Dimension
* out_height
;
225 pixel_to_char_size (ew
, in_width
, in_height
, &char_width
, &char_height
);
226 char_to_pixel_size (ew
, char_width
, char_height
, out_width
, out_height
);
235 for (wmshell
= XtParent (w
);
236 wmshell
&& !XtIsWMShell (wmshell
);
237 wmshell
= XtParent (wmshell
));
242 #if 0 /* Currently not used. */
245 mark_shell_size_user_specified (wmshell
)
248 if (! XtIsWMShell (wmshell
)) abort ();
249 /* This is kind of sleazy, but I can't see how else to tell it to make it
250 mark the WM_SIZE_HINTS size as user specified when appropriate. */
251 ((WMShellWidget
) wmshell
)->wm
.size_hints
.flags
|= USSize
;
257 /* Can't have static frame locals because of some broken compilers.
258 Normally, initializing a variable like this doesn't work in emacs,
259 but it's ok in this file because it must come after lastfile (and
260 thus have its data not go into text space) because Xt needs to
261 write to initialized data objects too.
264 static Boolean first_frame_p
= True
;
271 /* The widget hierarchy is
273 argv[0] emacsShell pane Frame-NAME
274 ApplicationShell EmacsShell Paned EmacsFrame
276 We accept geometry specs in this order:
282 Other possibilities for widget hierarchies might be
284 argv[0] frame pane Frame-NAME
285 ApplicationShell EmacsShell Paned EmacsFrame
287 argv[0] Frame-NAME pane Frame-NAME
288 ApplicationShell EmacsShell Paned EmacsFrame
290 argv[0] Frame-NAME pane emacsTextPane
291 ApplicationShell EmacsFrame Paned EmacsTextPane
293 With the current setup, the text-display-area is the part which is
294 an emacs "frame", since that's the only part managed by emacs proper
295 (the menubar and the parent of the menubar and all that sort of thing
296 are managed by lwlib.)
298 The EmacsShell widget is simply a replacement for the Shell widget
299 which is able to deal with using an externally-supplied window instead
300 of always creating its own. It is not actually emacs specific, and
301 should possibly have class "Shell" instead of "EmacsShell" to simplify
306 /* Hairily merged geometry */
307 unsigned int w
= ew
->emacs_frame
.frame
->width
;
308 unsigned int h
= ew
->emacs_frame
.frame
->height
;
310 Widget wmshell
= get_wm_shell ((Widget
) ew
);
311 /* Each Emacs shell is now independent and top-level. */
313 if (! XtIsSubclass (wmshell
, shellWidgetClass
)) abort ();
315 /* We don't need this for the moment. The geometry is computed in
318 /* If the EmacsFrame doesn't have a geometry but the shell does,
319 treat that as the geometry of the frame. (Is this bogus?
321 if (ew
->emacs_frame
.geometry
== 0)
322 XtVaGetValues (wmshell
, XtNgeometry
, &ew
->emacs_frame
.geometry
, NULL
);
324 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
325 this bogus? I'm not sure.) */
326 if (!ew
->emacs_frame
.iconic
)
327 XtVaGetValues (wmshell
, XtNiconic
, &ew
->emacs_frame
.iconic
, NULL
);
332 XtVaGetValues (app_shell
, XtNgeometry
, &geom
, NULL
);
334 app_flags
= XParseGeometry (geom
, &app_x
, &app_y
, &app_w
, &app_h
);
337 if (ew
->emacs_frame
.geometry
)
338 frame_flags
= XParseGeometry (ew
->emacs_frame
.geometry
,
344 /* If this is the first frame created:
345 ====================================
347 - Use the ApplicationShell's size/position, if specified.
348 (This is "Emacs.geometry", or the "-geometry" command line arg.)
349 - Else use the EmacsFrame's size/position.
350 (This is "*Frame-NAME.geometry")
352 - If the AppShell is iconic, the frame should be iconic.
354 AppShell comes first so that -geometry always applies to the first
355 frame created, even if there is an "every frame" entry in the
358 if (app_flags
& (XValue
| YValue
))
360 x
= app_x
; y
= app_y
;
361 flags
|= (app_flags
& (XValue
| YValue
| XNegative
| YNegative
));
363 else if (frame_flags
& (XValue
| YValue
))
365 x
= frame_x
; y
= frame_y
;
366 flags
|= (frame_flags
& (XValue
| YValue
| XNegative
| YNegative
));
369 if (app_flags
& (WidthValue
| HeightValue
))
371 w
= app_w
; h
= app_h
;
372 flags
|= (app_flags
& (WidthValue
| HeightValue
));
374 else if (frame_flags
& (WidthValue
| HeightValue
))
376 w
= frame_w
; h
= frame_h
;
377 flags
|= (frame_flags
& (WidthValue
| HeightValue
));
380 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
381 if (!ew
->emacs_frame
.iconic
)
382 XtVaGetValues (app_shell
, XtNiconic
, &ew
->emacs_frame
.iconic
, NULL
);
384 first_frame_p
= False
;
388 /* If this is not the first frame created:
389 ========================================
391 - use the EmacsFrame's size/position if specified
392 - Otherwise, use the ApplicationShell's size, but not position.
394 So that means that one can specify the position of the first frame
395 with "Emacs.geometry" or `-geometry'; but can only specify the
396 position of subsequent frames with "*Frame-NAME.geometry".
398 AppShell comes second so that -geometry does not apply to subsequent
399 frames when there is an "every frame" entry in the resource db,
400 but does apply to the first frame.
402 if (frame_flags
& (XValue
| YValue
))
404 x
= frame_x
; y
= frame_y
;
405 flags
|= (frame_flags
& (XValue
| YValue
| XNegative
| YNegative
));
408 if (frame_flags
& (WidthValue
| HeightValue
))
410 w
= frame_w
; h
= frame_h
;
411 flags
|= (frame_flags
& (WidthValue
| HeightValue
));
413 else if (app_flags
& (WidthValue
| HeightValue
))
417 flags
|= (app_flags
& (WidthValue
| HeightValue
));
422 struct frame
* frame
= ew
->emacs_frame
.frame
;
423 Dimension pixel_width
, pixel_height
;
425 /* Take into account the size of the scrollbar. Always use the
426 number of columns occupied by the scroll bar here otherwise we
427 might end up with a frame width that is not a multiple of the
428 frame's character width which is bad for vertically split
430 frame
->output_data
.x
->vertical_scroll_bar_extra
431 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (frame
)
433 : (FRAME_SCROLL_BAR_COLS (frame
)
434 * FONT_WIDTH (frame
->output_data
.x
->font
)));
436 frame
->output_data
.x
->flags_areas_extra
437 = FRAME_FLAGS_AREA_WIDTH (frame
);
439 change_frame_size (frame
, h
, w
, 1, 0, 0);
440 char_to_pixel_size (ew
, w
, h
, &pixel_width
, &pixel_height
);
441 ew
->core
.width
= pixel_width
;
442 ew
->core
.height
= pixel_height
;
444 #if 0 /* xfns.c takes care of this now. */
445 /* If a position was specified, assign it to the shell widget.
446 (Else WM won't do anything with it.)
448 if (flags
& (XValue
| YValue
))
450 /* the tricky things with the sign is to make sure that
454 sprintf (shell_position
, "=%c%d%c%d",
455 flags
& XNegative
? '-' : '+', x
< 0 ? -x
: x
,
456 flags
& YNegative
? '-' : '+', y
< 0 ? -y
: y
);
457 len
= strlen (shell_position
) + 1;
458 tem
= (char *) xmalloc (len
);
459 strncpy (tem
, shell_position
, len
);
460 XtVaSetValues (wmshell
, XtNgeometry
, tem
, NULL
);
462 else if (flags
& (WidthValue
| HeightValue
))
466 sprintf (shell_position
, "=%dx%d", pixel_width
, pixel_height
);
467 len
= strlen (shell_position
) + 1;
468 tem
= (char *) xmalloc (len
);
469 strncpy (tem
, shell_position
, len
);
470 XtVaSetValues (wmshell
, XtNgeometry
, tem
, NULL
);
473 /* If the geometry spec we're using has W/H components, mark the size
474 in the WM_SIZE_HINTS as user specified. */
475 if (flags
& (WidthValue
| HeightValue
))
476 mark_shell_size_user_specified (wmshell
);
478 /* Also assign the iconic status of the frame to the Shell, so that
480 XtVaSetValues (wmshell
, XtNiconic
, ew
->emacs_frame
.iconic
, NULL
);
485 /* Nonzero tells update_wm_hints not to do anything
486 (the caller should call update_wm_hints explicitly later.) */
487 int update_hints_inhibit
;
493 Widget wmshell
= get_wm_shell ((Widget
)ew
);
496 Dimension rounded_width
;
497 Dimension rounded_height
;
502 int min_rows
= 0, min_cols
= 0;
504 if (update_hints_inhibit
)
508 check_frame_size (ew
->emacs_frame
.frame
, &min_rows
, &min_cols
);
511 pixel_to_char_size (ew
, ew
->core
.width
, ew
->core
.height
,
512 &char_width
, &char_height
);
513 char_to_pixel_size (ew
, char_width
, char_height
,
514 &rounded_width
, &rounded_height
);
515 get_default_char_pixel_size (ew
, &cw
, &ch
);
517 base_width
= (wmshell
->core
.width
- ew
->core
.width
518 + (rounded_width
- (char_width
* cw
)));
519 base_height
= (wmshell
->core
.height
- ew
->core
.height
520 + (rounded_height
- (char_height
* ch
)));
522 /* This is kind of sleazy, but I can't see how else to tell it to
523 make it mark the WM_SIZE_HINTS size as user specified.
525 /* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
527 XtVaSetValues (wmshell
,
528 XtNbaseWidth
, base_width
,
529 XtNbaseHeight
, base_height
,
532 XtNminWidth
, base_width
+ min_cols
* cw
,
533 XtNminHeight
, base_height
+ min_rows
* ch
,
540 create_frame_gcs (ew
)
543 struct frame
*s
= ew
->emacs_frame
.frame
;
545 s
->output_data
.x
->normal_gc
546 = XCreateGC (XtDisplay (ew
), RootWindowOfScreen (XtScreen (ew
)),
547 (unsigned long)0, (XGCValues
*)0);
548 s
->output_data
.x
->reverse_gc
549 = XCreateGC (XtDisplay (ew
), RootWindowOfScreen (XtScreen (ew
)),
550 (unsigned long)0, (XGCValues
*)0);
551 s
->output_data
.x
->cursor_gc
552 = XCreateGC (XtDisplay (ew
), RootWindowOfScreen (XtScreen (ew
)),
553 (unsigned long)0, (XGCValues
*)0);
554 s
->output_data
.x
->black_relief
.gc
= 0;
555 s
->output_data
.x
->white_relief
.gc
= 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 /* This used to contain SubstructureRedirectMask, but this turns out
736 to be a problem with XIM on Solaris, and events from that mask
737 don't seem to be used. Let's check that. */
738 attrs
->event_mask
= (STANDARD_EVENT_SET
740 | SubstructureNotifyMask
);
741 *mask
|= CWEventMask
;
742 XtCreateWindow (widget
, InputOutput
, (Visual
*)CopyFromParent
, *mask
,
744 update_wm_hints (ew
);
747 extern void free_frame_faces (/* struct frame * */);
750 EmacsFrameDestroy (widget
)
753 EmacsFrame ew
= (EmacsFrame
) widget
;
754 struct frame
* s
= ew
->emacs_frame
.frame
;
757 if (! s
->output_data
.x
) abort ();
758 if (! s
->output_data
.x
->normal_gc
) abort ();
762 if (s
->output_data
.x
->white_relief
.gc
)
763 XFreeGC (XtDisplay (widget
), s
->output_data
.x
->white_relief
.gc
);
764 if (s
->output_data
.x
->black_relief
.gc
)
765 XFreeGC (XtDisplay (widget
), s
->output_data
.x
->black_relief
.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, 0);
780 update_wm_hints (ew
);
781 update_various_frame_slots (ew
);
783 cancel_mouse_face (f
);
787 EmacsFrameSetValues (cur_widget
, req_widget
, new_widget
, dum1
, dum2
)
794 EmacsFrame cur
= (EmacsFrame
)cur_widget
;
795 EmacsFrame
new = (EmacsFrame
)new_widget
;
797 Boolean needs_a_refresh
= False
;
798 Boolean has_to_recompute_size
;
799 Boolean has_to_recompute_gcs
;
800 Boolean has_to_update_hints
;
802 int char_width
, char_height
;
803 Dimension pixel_width
;
804 Dimension pixel_height
;
806 has_to_recompute_gcs
= (cur
->emacs_frame
.font
!= new->emacs_frame
.font
807 || (cur
->emacs_frame
.foreground_pixel
808 != new->emacs_frame
.foreground_pixel
)
809 || (cur
->core
.background_pixel
810 != new->core
.background_pixel
)
813 has_to_recompute_size
= (cur
->emacs_frame
.font
!= new->emacs_frame
.font
814 && cur
->core
.width
== new->core
.width
815 && cur
->core
.height
== new->core
.height
);
817 has_to_update_hints
= (cur
->emacs_frame
.font
!= new->emacs_frame
.font
);
819 if (has_to_recompute_gcs
)
821 setup_frame_gcs (new);
822 needs_a_refresh
= True
;
825 if (has_to_recompute_size
)
827 pixel_width
= new->core
.width
;
828 pixel_height
= new->core
.height
;
829 pixel_to_char_size (new, pixel_width
, pixel_height
, &char_width
,
831 char_to_pixel_size (new, char_width
, char_height
, &pixel_width
,
833 new->core
.width
= pixel_width
;
834 new->core
.height
= pixel_height
;
836 change_frame_size (new->emacs_frame
.frame
, char_height
, char_width
,
838 needs_a_refresh
= True
;
841 if (has_to_update_hints
)
842 update_wm_hints (new);
844 update_various_frame_slots (new);
846 /* #### This doesn't work, I haven't been able to find ANY kludge that
847 will let (x-create-frame '((iconic . t))) work. It seems that changes
848 to wm_shell's iconic slot have no effect after it has been realized,
849 and calling XIconifyWindow doesn't work either (even though the window
850 has been created.) Perhaps there is some property we could smash
851 directly, but I'm sick of this for now.
853 if (cur
->emacs_frame
.iconic
!= new->emacs_frame
.iconic
)
855 Widget wmshell
= get_wm_shell ((Widget
) cur
);
856 XtVaSetValues (wmshell
, XtNiconic
, new->emacs_frame
.iconic
, NULL
);
859 return needs_a_refresh
;
862 static XtGeometryResult
863 EmacsFrameQueryGeometry (widget
, request
, result
)
865 XtWidgetGeometry
* request
;
866 XtWidgetGeometry
* result
;
868 EmacsFrame ew
= (EmacsFrame
)widget
;
870 int mask
= request
->request_mode
;
871 Dimension ok_width
, ok_height
;
873 if (mask
& (CWWidth
| CWHeight
))
875 round_size_to_char (ew
,
876 (mask
& CWWidth
) ? request
->width
: ew
->core
.width
,
877 ((mask
& CWHeight
) ? request
->height
879 &ok_width
, &ok_height
);
880 if ((mask
& CWWidth
) && (ok_width
!= request
->width
))
882 result
->request_mode
|= CWWidth
;
883 result
->width
= ok_width
;
885 if ((mask
& CWHeight
) && (ok_height
!= request
->height
))
887 result
->request_mode
|= CWHeight
;
888 result
->height
= ok_height
;
891 return result
->request_mode
? XtGeometryAlmost
: XtGeometryYes
;
894 /* Special entrypoints */
896 EmacsFrameSetCharSize (widget
, columns
, rows
)
901 EmacsFrame ew
= (EmacsFrame
) widget
;
902 Dimension pixel_width
, pixel_height
;
903 struct frame
*f
= ew
->emacs_frame
.frame
;
905 if (columns
< 3) columns
= 3; /* no way buddy */
907 check_frame_size (f
, &rows
, &columns
);
908 f
->output_data
.x
->vertical_scroll_bar_extra
909 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
911 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
913 f
->output_data
.x
->flags_areas_extra
914 = FRAME_FLAGS_AREA_WIDTH (f
);
916 char_to_pixel_size (ew
, columns
, rows
, &pixel_width
, &pixel_height
);
918 #if 0 /* This doesn't seem to be right. The frame gets too wide. --gerd. */
919 /* Something is really strange here wrt to the border width:
920 Apparently, XtNwidth and XtNheight include the border, so we have
921 to add it here. But the XtNborderWidth set for the widgets has
922 no similarity to what f->output_data.x->border_width is set to. */
923 XtVaGetValues (widget
, XtNborderWidth
, &border_width
, NULL
);
924 pixel_height
+= 2 * border_width
;
925 pixel_width
+= 2 * border_width
;
928 /* Manually change the height and width of all our widgets,
929 adjusting each widget by the same increments. */
930 if (ew
->core
.width
!= pixel_width
931 || ew
->core
.height
!= pixel_height
)
933 int hdelta
= pixel_height
- ew
->core
.height
;
934 int wdelta
= pixel_width
- ew
->core
.width
;
935 int column_widget_height
= f
->output_data
.x
->column_widget
->core
.height
;
936 int column_widget_width
= f
->output_data
.x
->column_widget
->core
.width
;
937 int outer_widget_height
= f
->output_data
.x
->widget
->core
.height
;
938 int outer_widget_width
= f
->output_data
.x
->widget
->core
.width
;
939 int old_left
= f
->output_data
.x
->widget
->core
.x
;
940 int old_top
= f
->output_data
.x
->widget
->core
.y
;
942 lw_refigure_widget (f
->output_data
.x
->column_widget
, False
);
943 update_hints_inhibit
= 1;
945 /* Do parents first, otherwise LessTif's geometry management
946 enters an infinite loop (as of 2000-01-15). This is fixed in
947 later versions of LessTif (as of 2001-03-13); I'll leave it
948 as is because I think it can't do any harm. */
949 XtVaSetValues (f
->output_data
.x
->widget
,
950 XtNheight
, outer_widget_height
+ hdelta
,
951 XtNwidth
, outer_widget_width
+ wdelta
, NULL
);
952 XtVaSetValues (f
->output_data
.x
->column_widget
,
953 XtNheight
, column_widget_height
+ hdelta
,
954 XtNwidth
, column_widget_width
+ wdelta
, NULL
);
955 XtVaSetValues ((Widget
) ew
,
956 XtNheight
, pixel_height
,
957 XtNwidth
, pixel_width
, NULL
);
959 lw_refigure_widget (f
->output_data
.x
->column_widget
, True
);
961 update_hints_inhibit
= 0;
962 update_wm_hints (ew
);
964 /* These seem to get clobbered. I don't know why. - rms. */
965 f
->output_data
.x
->widget
->core
.x
= old_left
;
966 f
->output_data
.x
->widget
->core
.y
= old_top
;
969 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
970 receive in the ConfigureNotify event; if we get what we asked
971 for, then the event won't cause the screen to become garbaged, so
972 we have to make sure to do it here. */
973 SET_FRAME_GARBAGED (f
);
978 widget_store_internal_border (widget
)
981 EmacsFrame ew
= (EmacsFrame
) widget
;
982 FRAME_PTR f
= ew
->emacs_frame
.frame
;
984 ew
->emacs_frame
.internal_border_width
985 = f
->output_data
.x
->internal_border_width
;