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/
41 #include "dispextern.h"
42 #include "blockinput.h"
44 #include <X11/StringDefs.h>
45 #include <X11/IntrinsicP.h>
46 #include <X11/cursorfont.h>
47 #include "widgetprv.h"
48 #include <X11/ObjectP.h>
49 #include <X11/Shell.h>
50 #include <X11/ShellP.h>
51 #include "../lwlib/lwlib.h"
53 #define max(a, b) ((a) > (b) ? (a) : (b))
55 /* This sucks: this is the first default that x-faces.el tries. This won't
56 be used unless neither the "Emacs.EmacsFrame" resource nor the
57 "Emacs.EmacsFrame" resource is set; the frame
58 may have the wrong default size if this font doesn't exist, but some other
59 font that x-faces.el does. The workaround is to specify some font in the
60 resource database; I don't know a solution other than duplicating the font-
61 searching code from x-faces.el in this file.
63 This also means that if "Emacs.EmacsFrame" is specified as a non-
64 existent font, then Xt is going to substitute "XtDefaultFont" for it,
65 which is a different size than this one. The solution for this is to
66 make x-faces.el try to use XtDefaultFont. The problem with that is that
67 XtDefaultFont is almost certainly variable-width.
69 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
71 #define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
74 static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
75 static void EmacsFrameDestroy (/* Widget */);
76 static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
77 void EmacsFrameResize (/* Widget widget */);
78 static Boolean
EmacsFrameSetValues (/* Widget, Widget, Widget,
79 ArgList, Cardinal * */);
80 static XtGeometryResult
EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
81 XtWidgetGeometry* */);
85 #define XtOffset(p_type,field) \
86 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
87 #define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
89 static XtResource resources
[] = {
90 {XtNgeometry
, XtCGeometry
, XtRString
, sizeof(String
),
91 offset (geometry
), XtRString
, (XtPointer
) 0},
92 {XtNiconic
, XtCIconic
, XtRBoolean
, sizeof(Boolean
),
93 offset (iconic
), XtRImmediate
, (XtPointer
) False
},
95 {XtNemacsFrame
, XtCEmacsFrame
, XtRPointer
, sizeof (XtPointer
),
96 offset (frame
), XtRImmediate
, 0},
98 {XtNminibuffer
, XtCMinibuffer
, XtRInt
, sizeof (int),
99 offset (minibuffer
), XtRImmediate
, (XtPointer
)0},
100 {XtNunsplittable
, XtCUnsplittable
, XtRBoolean
, sizeof (Boolean
),
101 offset (unsplittable
), XtRImmediate
, (XtPointer
)0},
102 {XtNinternalBorderWidth
, XtCInternalBorderWidth
, XtRInt
, sizeof (int),
103 offset (internal_border_width
), XtRImmediate
, (XtPointer
)4},
104 {XtNinterline
, XtCInterline
, XtRInt
, sizeof (int),
105 offset (interline
), XtRImmediate
, (XtPointer
)0},
106 {XtNfont
, XtCFont
, XtRFontStruct
, sizeof(XFontStruct
*),
107 offset(font
),XtRString
, DEFAULT_FACE_FONT
},
108 {XtNforeground
, XtCForeground
, XtRPixel
, sizeof(Pixel
),
109 offset(foreground_pixel
), XtRString
, "XtDefaultForeground"},
110 {XtNcursorColor
, XtCForeground
, XtRPixel
, sizeof(Pixel
),
111 offset(cursor_color
), XtRString
, "XtDefaultForeground"},
112 {XtNbarCursor
, XtCBarCursor
, XtRBoolean
, sizeof (Boolean
),
113 offset (bar_cursor
), XtRImmediate
, (XtPointer
)0},
114 {XtNvisualBell
, XtCVisualBell
, XtRBoolean
, sizeof (Boolean
),
115 offset (visual_bell
), XtRImmediate
, (XtPointer
)0},
116 {XtNbellVolume
, XtCBellVolume
, XtRInt
, sizeof (int),
117 offset (bell_volume
), XtRImmediate
, (XtPointer
)0},
124 emacsFrameActionsTable [] = {
125 {"keypress", key_press},
126 {"focus_in", emacs_frame_focus_handler},
127 {"focus_out", emacs_frame_focus_handler},
131 emacsFrameTranslations [] = "\
132 <KeyPress>: keypress()\n\
133 <FocusIn>: focus_in()\n\
134 <FocusOut>: focus_out()\n\
138 EmacsFrameClassRec emacsFrameClassRec
= {
140 /* superclass */ &widgetClassRec
,
141 /* class_name */ "EmacsFrame",
142 /* widget_size */ sizeof(EmacsFrameRec
),
143 /* class_initialize */ 0,
144 /* class_part_initialize */ 0,
145 /* class_inited */ FALSE
,
146 /* initialize */ EmacsFrameInitialize
,
147 /* initialize_hook */ 0,
148 /* realize */ EmacsFrameRealize
,
149 /* actions */ 0, /*emacsFrameActionsTable*/
150 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
151 /* resources */ resources
,
152 /* resource_count */ XtNumber(resources
),
153 /* xrm_class */ NULLQUARK
,
154 /* compress_motion */ TRUE
,
155 /* compress_exposure */ TRUE
,
156 /* compress_enterleave */ TRUE
,
157 /* visible_interest */ FALSE
,
158 /* destroy */ EmacsFrameDestroy
,
159 /* resize */ EmacsFrameResize
,
160 /* expose */ XtInheritExpose
,
161 /* set_values */ EmacsFrameSetValues
,
162 /* set_values_hook */ 0,
163 /* set_values_almost */ XtInheritSetValuesAlmost
,
164 /* get_values_hook */ 0,
165 /* accept_focus */ XtInheritAcceptFocus
,
166 /* version */ XtVersion
,
167 /* callback_private */ 0,
168 /* tm_table */ 0, /*emacsFrameTranslations*/
169 /* query_geometry */ EmacsFrameQueryGeometry
,
170 /* display_accelerator */ XtInheritDisplayAccelerator
,
175 WidgetClass emacsFrameClass
= (WidgetClass
) &emacsFrameClassRec
;
178 get_default_char_pixel_size (ew
, pixel_width
, pixel_height
)
183 struct frame
* f
= ew
->emacs_frame
.frame
;
184 *pixel_width
= FONT_WIDTH (f
->output_data
.x
->font
);
185 *pixel_height
= f
->output_data
.x
->line_height
;
189 pixel_to_char_size (ew
, pixel_width
, pixel_height
, char_width
, char_height
)
191 Dimension pixel_width
;
192 Dimension pixel_height
;
196 struct frame
* f
= ew
->emacs_frame
.frame
;
197 *char_width
= PIXEL_TO_CHAR_WIDTH (f
, (int) pixel_width
);
198 *char_height
= PIXEL_TO_CHAR_HEIGHT (f
, (int) pixel_height
);
202 char_to_pixel_size (ew
, char_width
, char_height
, pixel_width
, pixel_height
)
206 Dimension
* pixel_width
;
207 Dimension
* pixel_height
;
209 struct frame
* f
= ew
->emacs_frame
.frame
;
210 *pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, char_width
);
211 *pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, char_height
);
215 round_size_to_char (ew
, in_width
, in_height
, out_width
, out_height
)
219 Dimension
* out_width
;
220 Dimension
* out_height
;
224 pixel_to_char_size (ew
, in_width
, in_height
, &char_width
, &char_height
);
225 char_to_pixel_size (ew
, char_width
, char_height
, out_width
, out_height
);
234 for (wmshell
= XtParent (w
);
235 wmshell
&& !XtIsWMShell (wmshell
);
236 wmshell
= XtParent (wmshell
));
242 mark_shell_size_user_specified (wmshell
)
245 if (! XtIsWMShell (wmshell
)) abort ();
246 /* This is kind of sleazy, but I can't see how else to tell it to make it
247 mark the WM_SIZE_HINTS size as user specified when appropriate. */
248 ((WMShellWidget
) wmshell
)->wm
.size_hints
.flags
|= USSize
;
252 /* Can't have static frame locals because of some broken compilers.
253 Normally, initializing a variable like this doesn't work in emacs,
254 but it's ok in this file because it must come after lastfile (and
255 thus have its data not go into text space) because Xt needs to
256 write to initialized data objects too.
258 static Boolean first_frame_p
= True
;
264 /* The widget hierarchy is
266 argv[0] emacsShell pane Frame-NAME
267 ApplicationShell EmacsShell Paned EmacsFrame
269 We accept geometry specs in this order:
275 Other possibilities for widget hierarchies might be
277 argv[0] frame pane Frame-NAME
278 ApplicationShell EmacsShell Paned EmacsFrame
280 argv[0] Frame-NAME pane Frame-NAME
281 ApplicationShell EmacsShell Paned EmacsFrame
283 argv[0] Frame-NAME pane emacsTextPane
284 ApplicationShell EmacsFrame Paned EmacsTextPane
286 With the current setup, the text-display-area is the part which is
287 an emacs "frame", since that's the only part managed by emacs proper
288 (the menubar and the parent of the menubar and all that sort of thing
289 are managed by lwlib.)
291 The EmacsShell widget is simply a replacement for the Shell widget
292 which is able to deal with using an externally-supplied window instead
293 of always creating its own. It is not actually emacs specific, and
294 should possibly have class "Shell" instead of "EmacsShell" to simplify
299 /* Geometry of the AppShell */
303 unsigned int app_w
= 0;
304 unsigned int app_h
= 0;
306 /* Geometry of the EmacsFrame */
310 unsigned int frame_w
= 0;
311 unsigned int frame_h
= 0;
313 /* Hairily merged geometry */
316 unsigned int w
= ew
->emacs_frame
.frame
->width
;
317 unsigned int h
= ew
->emacs_frame
.frame
->height
;
320 Widget wmshell
= get_wm_shell ((Widget
) ew
);
321 /* Each Emacs shell is now independent and top-level. */
322 Widget app_shell
= wmshell
;
324 if (! XtIsSubclass (wmshell
, shellWidgetClass
)) abort ();
326 /* We don't need this for the moment. The geometry is computed in
329 /* If the EmacsFrame doesn't have a geometry but the shell does,
330 treat that as the geometry of the frame. (Is this bogus?
332 if (ew
->emacs_frame
.geometry
== 0)
333 XtVaGetValues (wmshell
, XtNgeometry
, &ew
->emacs_frame
.geometry
, 0);
335 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
336 this bogus? I'm not sure.) */
337 if (!ew
->emacs_frame
.iconic
)
338 XtVaGetValues (wmshell
, XtNiconic
, &ew
->emacs_frame
.iconic
, 0);
343 XtVaGetValues (app_shell
, XtNgeometry
, &geom
, 0);
345 app_flags
= XParseGeometry (geom
, &app_x
, &app_y
, &app_w
, &app_h
);
348 if (ew
->emacs_frame
.geometry
)
349 frame_flags
= XParseGeometry (ew
->emacs_frame
.geometry
,
355 /* If this is the first frame created:
356 ====================================
358 - Use the ApplicationShell's size/position, if specified.
359 (This is "Emacs.geometry", or the "-geometry" command line arg.)
360 - Else use the EmacsFrame's size/position.
361 (This is "*Frame-NAME.geometry")
363 - If the AppShell is iconic, the frame should be iconic.
365 AppShell comes first so that -geometry always applies to the first
366 frame created, even if there is an "every frame" entry in the
369 if (app_flags
& (XValue
| YValue
))
371 x
= app_x
; y
= app_y
;
372 flags
|= (app_flags
& (XValue
| YValue
| XNegative
| YNegative
));
374 else if (frame_flags
& (XValue
| YValue
))
376 x
= frame_x
; y
= frame_y
;
377 flags
|= (frame_flags
& (XValue
| YValue
| XNegative
| YNegative
));
380 if (app_flags
& (WidthValue
| HeightValue
))
382 w
= app_w
; h
= app_h
;
383 flags
|= (app_flags
& (WidthValue
| HeightValue
));
385 else if (frame_flags
& (WidthValue
| HeightValue
))
387 w
= frame_w
; h
= frame_h
;
388 flags
|= (frame_flags
& (WidthValue
| HeightValue
));
391 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
392 if (!ew
->emacs_frame
.iconic
)
393 XtVaGetValues (app_shell
, XtNiconic
, &ew
->emacs_frame
.iconic
, 0);
395 first_frame_p
= False
;
399 /* If this is not the first frame created:
400 ========================================
402 - use the EmacsFrame's size/position if specified
403 - Otherwise, use the ApplicationShell's size, but not position.
405 So that means that one can specify the position of the first frame
406 with "Emacs.geometry" or `-geometry'; but can only specify the
407 position of subsequent frames with "*Frame-NAME.geometry".
409 AppShell comes second so that -geometry does not apply to subsequent
410 frames when there is an "every frame" entry in the resource db,
411 but does apply to the first frame.
413 if (frame_flags
& (XValue
| YValue
))
415 x
= frame_x
; y
= frame_y
;
416 flags
|= (frame_flags
& (XValue
| YValue
| XNegative
| YNegative
));
419 if (frame_flags
& (WidthValue
| HeightValue
))
421 w
= frame_w
; h
= frame_h
;
422 flags
|= (frame_flags
& (WidthValue
| HeightValue
));
424 else if (app_flags
& (WidthValue
| HeightValue
))
428 flags
|= (app_flags
& (WidthValue
| HeightValue
));
433 struct frame
* frame
= ew
->emacs_frame
.frame
;
434 Dimension pixel_width
, pixel_height
;
435 char shell_position
[32];
437 /* Take into account the size of the scrollbar. Always use the
438 number of columns occupied by the scroll bar here otherwise we
439 might end up with a frame width that is not a multiple of the
440 frame's character width which is bad for vertically split
442 frame
->output_data
.x
->vertical_scroll_bar_extra
443 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (frame
)
445 : (FRAME_SCROLL_BAR_COLS (frame
)
446 * FONT_WIDTH (frame
->output_data
.x
->font
)));
448 frame
->output_data
.x
->flags_areas_extra
449 = 2 * FRAME_FLAGS_AREA_WIDTH (frame
);
451 change_frame_size (frame
, h
, w
, 1, 0);
452 char_to_pixel_size (ew
, w
, h
, &pixel_width
, &pixel_height
);
453 ew
->core
.width
= pixel_width
;
454 ew
->core
.height
= pixel_height
;
456 #if 0 /* xfns.c takes care of this now. */
457 /* If a position was specified, assign it to the shell widget.
458 (Else WM won't do anything with it.)
460 if (flags
& (XValue
| YValue
))
462 /* the tricky things with the sign is to make sure that
466 sprintf (shell_position
, "=%c%d%c%d",
467 flags
& XNegative
? '-' : '+', x
< 0 ? -x
: x
,
468 flags
& YNegative
? '-' : '+', y
< 0 ? -y
: y
);
469 len
= strlen (shell_position
) + 1;
470 tem
= (char *) xmalloc (len
);
471 strncpy (tem
, shell_position
, len
);
472 XtVaSetValues (wmshell
, XtNgeometry
, tem
, 0);
474 else if (flags
& (WidthValue
| HeightValue
))
478 sprintf (shell_position
, "=%dx%d", pixel_width
, pixel_height
);
479 len
= strlen (shell_position
) + 1;
480 tem
= (char *) xmalloc (len
);
481 strncpy (tem
, shell_position
, len
);
482 XtVaSetValues (wmshell
, XtNgeometry
, tem
, 0);
485 /* If the geometry spec we're using has W/H components, mark the size
486 in the WM_SIZE_HINTS as user specified. */
487 if (flags
& (WidthValue
| HeightValue
))
488 mark_shell_size_user_specified (wmshell
);
490 /* Also assign the iconic status of the frame to the Shell, so that
492 XtVaSetValues (wmshell
, XtNiconic
, ew
->emacs_frame
.iconic
, 0);
497 /* Nonzero tells update_wm_hints not to do anything
498 (the caller should call update_wm_hints explicitly later.) */
499 int update_hints_inhibit
;
505 Widget wmshell
= get_wm_shell ((Widget
)ew
);
508 Dimension rounded_width
;
509 Dimension rounded_height
;
514 int min_rows
= 0, min_cols
= 0;
516 if (update_hints_inhibit
)
520 check_frame_size (ew
->emacs_frame
.frame
, &min_rows
, &min_cols
);
523 pixel_to_char_size (ew
, ew
->core
.width
, ew
->core
.height
,
524 &char_width
, &char_height
);
525 char_to_pixel_size (ew
, char_width
, char_height
,
526 &rounded_width
, &rounded_height
);
527 get_default_char_pixel_size (ew
, &cw
, &ch
);
529 base_width
= (wmshell
->core
.width
- ew
->core
.width
530 + (rounded_width
- (char_width
* cw
)));
531 base_height
= (wmshell
->core
.height
- ew
->core
.height
532 + (rounded_height
- (char_height
* ch
)));
534 /* This is kind of sleazy, but I can't see how else to tell it to
535 make it mark the WM_SIZE_HINTS size as user specified.
537 /* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
539 XtVaSetValues (wmshell
,
540 XtNbaseWidth
, base_width
,
541 XtNbaseHeight
, base_height
,
544 XtNminWidth
, base_width
+ min_cols
* cw
,
545 XtNminHeight
, base_height
+ min_rows
* ch
,
550 create_frame_gcs (ew
)
553 struct frame
*s
= ew
->emacs_frame
.frame
;
555 s
->output_data
.x
->normal_gc
556 = XCreateGC (XtDisplay (ew
), RootWindowOfScreen (XtScreen (ew
)),
557 (unsigned long)0, (XGCValues
*)0);
558 s
->output_data
.x
->reverse_gc
559 = XCreateGC (XtDisplay (ew
), RootWindowOfScreen (XtScreen (ew
)),
560 (unsigned long)0, (XGCValues
*)0);
561 s
->output_data
.x
->cursor_gc
562 = XCreateGC (XtDisplay (ew
), RootWindowOfScreen (XtScreen (ew
)),
563 (unsigned long)0, (XGCValues
*)0);
564 s
->output_data
.x
->black_relief
.gc
= 0;
565 s
->output_data
.x
->white_relief
.gc
= 0;
568 static char setup_frame_cursor_bits
[] =
570 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
581 struct frame
* s
= ew
->emacs_frame
.frame
;
582 Pixmap blank_stipple
, blank_tile
;
584 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
585 XGetGCValues returns uninitialized data when we query the stipple
586 (instead of None or something sensible) and it makes things hard.
588 This should be fixed for real by not querying the GCs but instead having
589 some GC-based cache instead of the current face-based cache which doesn't
590 effectively cache all of the GC settings we need to use.
594 = XCreateBitmapFromData (XtDisplay (ew
),
595 RootWindowOfScreen (XtScreen (ew
)),
596 setup_frame_cursor_bits
, 2, 2);
598 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
599 never actually get used as a background tile!
602 = XCreatePixmapFromBitmapData (XtDisplay(ew
),
603 RootWindowOfScreen (XtScreen (ew
)),
604 setup_frame_cursor_bits
, 2, 2,
605 (unsigned long)0, (unsigned long)1,
609 gc_values
.font
= ew
->emacs_frame
.font
->fid
;
610 gc_values
.foreground
= ew
->emacs_frame
.foreground_pixel
;
611 gc_values
.background
= ew
->core
.background_pixel
;
612 gc_values
.graphics_exposures
= False
;
613 gc_values
.stipple
= blank_stipple
;
614 gc_values
.tile
= blank_tile
;
615 XChangeGC (XtDisplay (ew
), s
->output_data
.x
->normal_gc
,
616 (GCFont
| GCForeground
| GCBackground
| GCGraphicsExposures
617 | GCStipple
| GCTile
),
620 /* Reverse video style. */
621 gc_values
.font
= ew
->emacs_frame
.font
->fid
;
622 gc_values
.foreground
= ew
->core
.background_pixel
;
623 gc_values
.background
= ew
->emacs_frame
.foreground_pixel
;
624 gc_values
.graphics_exposures
= False
;
625 gc_values
.stipple
= blank_stipple
;
626 gc_values
.tile
= blank_tile
;
627 XChangeGC (XtDisplay (ew
), s
->output_data
.x
->reverse_gc
,
628 (GCFont
| GCForeground
| GCBackground
| GCGraphicsExposures
629 | GCStipple
| GCTile
),
632 /* Cursor has to have an empty stipple. */
633 gc_values
.font
= ew
->emacs_frame
.font
->fid
;
634 gc_values
.foreground
= ew
->core
.background_pixel
;
635 gc_values
.background
= ew
->emacs_frame
.cursor_color
;
636 gc_values
.graphics_exposures
= False
;
637 gc_values
.tile
= blank_tile
;
639 = XCreateBitmapFromData (XtDisplay (ew
),
640 RootWindowOfScreen (XtScreen (ew
)),
641 setup_frame_cursor_bits
, 16, 16);
642 XChangeGC (XtDisplay (ew
), s
->output_data
.x
->cursor_gc
,
643 (GCFont
| GCForeground
| GCBackground
| GCGraphicsExposures
644 | GCStipple
| GCTile
),
649 update_various_frame_slots (ew
)
652 struct x_output
*x
= ew
->emacs_frame
.frame
->output_data
.x
;
653 x
->pixel_height
= ew
->core
.height
+ x
->menubar_height
;
654 x
->pixel_width
= ew
->core
.width
;
655 x
->internal_border_width
= ew
->emacs_frame
.internal_border_width
;
660 update_from_various_frame_slots (ew
)
663 struct x_output
*x
= ew
->emacs_frame
.frame
->output_data
.x
;
664 ew
->core
.height
= x
->pixel_height
- x
->menubar_height
;
665 ew
->core
.width
= x
->pixel_width
;
666 ew
->core
.background_pixel
= x
->background_pixel
;
667 ew
->emacs_frame
.internal_border_width
= x
->internal_border_width
;
668 ew
->emacs_frame
.font
= x
->font
;
669 ew
->emacs_frame
.foreground_pixel
= x
->foreground_pixel
;
670 ew
->emacs_frame
.cursor_color
= x
->cursor_pixel
;
671 ew
->core
.border_pixel
= x
->border_pixel
;
675 EmacsFrameInitialize (request
, new, dum1
, dum2
)
681 EmacsFrame ew
= (EmacsFrame
)new;
683 if (!ew
->emacs_frame
.frame
)
686 "can't create an emacs frame widget without a frame\n");
690 #if 0 /* done in xfns.c */
691 /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
692 resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
693 It's unfortunate that we have to do this, but we need to know the font
694 size for frame-sizing purposes before the faces get initialized. If
695 the "default.attributeFont" isn't set, then we use the font of this
696 EmacsFrame itself, defaulting to XtDefaultFont. Up in the lisp code,
697 the "default" face will use the frame's font if its own is not set,
698 so everything stays in sync -- it's not possible for the frame's font
699 and the default face's font to be different.
704 face_res
.resource_name
= "attributeFont";
705 face_res
.resource_class
= "AttributeFont";
706 face_res
.resource_type
= XtRFontStruct
;
707 face_res
.resource_size
= sizeof (XFontStruct
*);
708 face_res
.resource_offset
= 0;
709 face_res
.default_type
= XtRImmediate
;
710 face_res
.default_addr
= 0;
711 XtGetSubresources ((Widget
) ew
, (XtPointer
) &f
, "default", "Face",
712 &face_res
, 1, NULL
, 0);
715 ew
->emacs_frame
.font
= f
;
716 else if (! ew
->emacs_frame
.font
)
718 fprintf (stderr
, "emacs frame widget could not load a font\n");
723 /* Update the font field in frame */
724 ew
->emacs_frame
.frame
->output_data
.x
->font
= ew
->emacs_frame
.font
;
727 update_from_various_frame_slots (ew
);
729 /*create_frame_gcs (ew);
730 setup_frame_gcs (ew);
731 update_various_frame_slots (ew); */
736 EmacsFrameRealize (widget
, mask
, attrs
)
739 XSetWindowAttributes
*attrs
;
741 EmacsFrame ew
= (EmacsFrame
)widget
;
743 attrs
->event_mask
= (STANDARD_EVENT_SET
| PropertyChangeMask
744 | SubstructureNotifyMask
| SubstructureRedirectMask
);
745 *mask
|= CWEventMask
;
746 XtCreateWindow (widget
, InputOutput
, (Visual
*)CopyFromParent
, *mask
,
748 update_wm_hints (ew
);
751 extern void free_frame_faces (/* struct frame * */);
754 EmacsFrameDestroy (widget
)
757 EmacsFrame ew
= (EmacsFrame
) widget
;
758 struct frame
* s
= ew
->emacs_frame
.frame
;
761 if (! s
->output_data
.x
) abort ();
762 if (! s
->output_data
.x
->normal_gc
) abort ();
765 /* need to be careful that the face-freeing code doesn't free these too */
766 XFreeGC (XtDisplay (widget
), s
->output_data
.x
->normal_gc
);
767 XFreeGC (XtDisplay (widget
), s
->output_data
.x
->reverse_gc
);
768 XFreeGC (XtDisplay (widget
), s
->output_data
.x
->cursor_gc
);
769 if (s
->output_data
.x
->white_relief
.gc
)
770 XFreeGC (XtDisplay (widget
), s
->output_data
.x
->white_relief
.gc
);
771 if (s
->output_data
.x
->black_relief
.gc
)
772 XFreeGC (XtDisplay (widget
), s
->output_data
.x
->black_relief
.gc
);
777 EmacsFrameResize (widget
)
780 EmacsFrame ew
= (EmacsFrame
)widget
;
781 struct frame
*f
= ew
->emacs_frame
.frame
;
785 pixel_to_char_size (ew
, ew
->core
.width
, ew
->core
.height
, &columns
, &rows
);
786 change_frame_size (f
, rows
, columns
, 0, 1);
787 update_wm_hints (ew
);
788 update_various_frame_slots (ew
);
790 cancel_mouse_face (f
);
794 EmacsFrameSetValues (cur_widget
, req_widget
, new_widget
, dum1
, dum2
)
801 EmacsFrame cur
= (EmacsFrame
)cur_widget
;
802 EmacsFrame
new = (EmacsFrame
)new_widget
;
804 Boolean needs_a_refresh
= False
;
805 Boolean has_to_recompute_size
;
806 Boolean has_to_recompute_gcs
;
807 Boolean has_to_update_hints
;
809 int char_width
, char_height
;
810 Dimension pixel_width
;
811 Dimension pixel_height
;
813 has_to_recompute_gcs
= (cur
->emacs_frame
.font
!= new->emacs_frame
.font
814 || (cur
->emacs_frame
.foreground_pixel
815 != new->emacs_frame
.foreground_pixel
)
816 || (cur
->core
.background_pixel
817 != new->core
.background_pixel
)
820 has_to_recompute_size
= (cur
->emacs_frame
.font
!= new->emacs_frame
.font
821 && cur
->core
.width
== new->core
.width
822 && cur
->core
.height
== new->core
.height
);
824 has_to_update_hints
= (cur
->emacs_frame
.font
!= new->emacs_frame
.font
);
826 if (has_to_recompute_gcs
)
828 setup_frame_gcs (new);
829 needs_a_refresh
= True
;
832 if (has_to_recompute_size
)
834 pixel_width
= new->core
.width
;
835 pixel_height
= new->core
.height
;
836 pixel_to_char_size (new, pixel_width
, pixel_height
, &char_width
,
838 char_to_pixel_size (new, char_width
, char_height
, &pixel_width
,
840 new->core
.width
= pixel_width
;
841 new->core
.height
= pixel_height
;
843 change_frame_size (new->emacs_frame
.frame
, char_height
, char_width
,
845 needs_a_refresh
= True
;
848 if (has_to_update_hints
)
849 update_wm_hints (new);
851 update_various_frame_slots (new);
853 /* #### This doesn't work, I haven't been able to find ANY kludge that
854 will let (x-create-frame '((iconic . t))) work. It seems that changes
855 to wm_shell's iconic slot have no effect after it has been realized,
856 and calling XIconifyWindow doesn't work either (even though the window
857 has been created.) Perhaps there is some property we could smash
858 directly, but I'm sick of this for now.
860 if (cur
->emacs_frame
.iconic
!= new->emacs_frame
.iconic
)
862 Widget wmshell
= get_wm_shell ((Widget
) cur
);
863 XtVaSetValues (wmshell
, XtNiconic
, new->emacs_frame
.iconic
, 0);
866 return needs_a_refresh
;
869 static XtGeometryResult
870 EmacsFrameQueryGeometry (widget
, request
, result
)
872 XtWidgetGeometry
* request
;
873 XtWidgetGeometry
* result
;
875 EmacsFrame ew
= (EmacsFrame
)widget
;
877 int mask
= request
->request_mode
;
878 Dimension ok_width
, ok_height
;
880 if (mask
& (CWWidth
| CWHeight
))
882 round_size_to_char (ew
,
883 (mask
& CWWidth
) ? request
->width
: ew
->core
.width
,
884 ((mask
& CWHeight
) ? request
->height
886 &ok_width
, &ok_height
);
887 if ((mask
& CWWidth
) && (ok_width
!= request
->width
))
889 result
->request_mode
|= CWWidth
;
890 result
->width
= ok_width
;
892 if ((mask
& CWHeight
) && (ok_height
!= request
->height
))
894 result
->request_mode
|= CWHeight
;
895 result
->height
= ok_height
;
898 return result
->request_mode
? XtGeometryAlmost
: XtGeometryYes
;
901 /* Special entrypoints */
903 EmacsFrameSetCharSize (widget
, columns
, rows
)
908 EmacsFrame ew
= (EmacsFrame
) widget
;
909 Dimension pixel_width
, pixel_height
, granted_width
, granted_height
;
910 XtGeometryResult result
;
911 struct frame
*f
= ew
->emacs_frame
.frame
;
914 Dimension border_width
;
916 if (columns
< 3) columns
= 3; /* no way buddy */
918 check_frame_size (f
, &rows
, &columns
);
919 f
->output_data
.x
->vertical_scroll_bar_extra
920 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
922 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
924 f
->output_data
.x
->flags_areas_extra
925 = 2 * FRAME_FLAGS_AREA_WIDTH (f
);
927 char_to_pixel_size (ew
, columns
, rows
, &pixel_width
, &pixel_height
);
929 #if 0 /* This doesn't seem to be right. The frame gets too wide. --gerd. */
930 /* Something is really strange here wrt to the border width:
931 Apparently, XtNwidth and XtNheight include the border, so we have
932 to add it here. But the XtNborderWidth set for the widgets has
933 no similarity to what f->output_data.x->border_width is set to. */
934 XtVaGetValues (widget
, XtNborderWidth
, &border_width
, NULL
);
935 pixel_height
+= 2 * border_width
;
936 pixel_width
+= 2 * border_width
;
939 /* Manually change the height and width of all our widgets,
940 adjusting each widget by the same increments. */
941 if (ew
->core
.width
!= pixel_width
942 || ew
->core
.height
!= pixel_height
)
944 int hdelta
= pixel_height
- ew
->core
.height
;
945 int wdelta
= pixel_width
- ew
->core
.width
;
946 int column_widget_height
= f
->output_data
.x
->column_widget
->core
.height
;
947 int column_widget_width
= f
->output_data
.x
->column_widget
->core
.width
;
948 int outer_widget_height
= f
->output_data
.x
->widget
->core
.height
;
949 int outer_widget_width
= f
->output_data
.x
->widget
->core
.width
;
950 int old_left
= f
->output_data
.x
->widget
->core
.x
;
951 int old_top
= f
->output_data
.x
->widget
->core
.y
;
953 lw_refigure_widget (f
->output_data
.x
->column_widget
, False
);
954 update_hints_inhibit
= 1;
957 XtSetArg (al
[ac
], XtNheight
, pixel_height
); ac
++;
958 XtSetArg (al
[ac
], XtNwidth
, pixel_width
); ac
++;
959 XtSetValues ((Widget
) ew
, al
, ac
);
962 XtSetArg (al
[ac
], XtNheight
, column_widget_height
+ hdelta
); ac
++;
963 XtSetArg (al
[ac
], XtNwidth
, column_widget_width
+ wdelta
); ac
++;
964 XtSetValues (f
->output_data
.x
->column_widget
, al
, ac
);
967 XtSetArg (al
[ac
], XtNheight
, outer_widget_height
+ hdelta
); ac
++;
968 XtSetArg (al
[ac
], XtNwidth
, outer_widget_width
+ wdelta
); ac
++;
969 XtSetValues (f
->output_data
.x
->widget
, al
, ac
);
971 lw_refigure_widget (f
->output_data
.x
->column_widget
, True
);
973 update_hints_inhibit
= 0;
974 update_wm_hints (ew
);
976 do_pending_window_change ();
978 /* These seem to get clobbered. I don't know why. - rms. */
979 f
->output_data
.x
->widget
->core
.x
= old_left
;
980 f
->output_data
.x
->widget
->core
.y
= old_top
;
983 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
984 receive in the ConfigureNotify event; if we get what we asked
985 for, then the event won't cause the screen to become garbaged, so
986 we have to make sure to do it here. */
987 SET_FRAME_GARBAGED (f
);
992 widget_store_internal_border (widget
)
995 EmacsFrame ew
= (EmacsFrame
) widget
;
996 FRAME_PTR f
= ew
->emacs_frame
.frame
;
998 ew
->emacs_frame
.internal_border_width
999 = f
->output_data
.x
->internal_border_width
;