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"
55 #include "syssignal.h"
57 /* This sucks: this is the first default that x-faces.el tries. This won't
58 be used unless neither the "Emacs.EmacsFrame" resource nor the
59 "Emacs.EmacsFrame" resource is set; the frame
60 may have the wrong default size if this font doesn't exist, but some other
61 font that x-faces.el does. The workaround is to specify some font in the
62 resource database; I don't know a solution other than duplicating the font-
63 searching code from x-faces.el in this file.
65 This also means that if "Emacs.EmacsFrame" is specified as a non-
66 existent font, then Xt is going to substitute "XtDefaultFont" for it,
67 which is a different size than this one. The solution for this is to
68 make x-faces.el try to use XtDefaultFont. The problem with that is that
69 XtDefaultFont is almost certainly variable-width.
71 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
73 #define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
76 static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
77 static void EmacsFrameDestroy (/* Widget */);
78 static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
79 void EmacsFrameResize (/* Widget widget */);
80 static Boolean
EmacsFrameSetValues (/* Widget, Widget, Widget,
81 ArgList, Cardinal * */);
82 static XtGeometryResult
EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
83 XtWidgetGeometry* */);
87 #define XtOffset(p_type,field) \
88 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
89 #define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
91 static XtResource resources
[] = {
92 {XtNgeometry
, XtCGeometry
, XtRString
, sizeof(String
),
93 offset (geometry
), XtRString
, (XtPointer
) 0},
94 {XtNiconic
, XtCIconic
, XtRBoolean
, sizeof(Boolean
),
95 offset (iconic
), XtRImmediate
, (XtPointer
) False
},
97 {XtNemacsFrame
, XtCEmacsFrame
, XtRPointer
, sizeof (XtPointer
),
98 offset (frame
), XtRImmediate
, 0},
100 {XtNminibuffer
, XtCMinibuffer
, XtRInt
, sizeof (int),
101 offset (minibuffer
), XtRImmediate
, (XtPointer
)0},
102 {XtNunsplittable
, XtCUnsplittable
, XtRBoolean
, sizeof (Boolean
),
103 offset (unsplittable
), XtRImmediate
, (XtPointer
)0},
104 {XtNinternalBorderWidth
, XtCInternalBorderWidth
, XtRInt
, sizeof (int),
105 offset (internal_border_width
), XtRImmediate
, (XtPointer
)4},
106 {XtNinterline
, XtCInterline
, XtRInt
, sizeof (int),
107 offset (interline
), XtRImmediate
, (XtPointer
)0},
108 {XtNfont
, XtCFont
, XtRFontStruct
, sizeof(XFontStruct
*),
109 offset(font
),XtRString
, DEFAULT_FACE_FONT
},
110 {XtNforeground
, XtCForeground
, XtRPixel
, sizeof(Pixel
),
111 offset(foreground_pixel
), XtRString
, "XtDefaultForeground"},
112 {XtNcursorColor
, XtCForeground
, XtRPixel
, sizeof(Pixel
),
113 offset(cursor_color
), XtRString
, "XtDefaultForeground"},
114 {XtNbarCursor
, XtCBarCursor
, XtRBoolean
, sizeof (Boolean
),
115 offset (bar_cursor
), XtRImmediate
, (XtPointer
)0},
116 {XtNvisualBell
, XtCVisualBell
, XtRBoolean
, sizeof (Boolean
),
117 offset (visual_bell
), XtRImmediate
, (XtPointer
)0},
118 {XtNbellVolume
, XtCBellVolume
, XtRInt
, sizeof (int),
119 offset (bell_volume
), XtRImmediate
, (XtPointer
)0},
126 emacsFrameActionsTable [] = {
127 {"keypress", key_press},
128 {"focus_in", emacs_frame_focus_handler},
129 {"focus_out", emacs_frame_focus_handler},
133 emacsFrameTranslations [] = "\
134 <KeyPress>: keypress()\n\
135 <FocusIn>: focus_in()\n\
136 <FocusOut>: focus_out()\n\
140 EmacsFrameClassRec emacsFrameClassRec
= {
142 /* superclass */ &widgetClassRec
,
143 /* class_name */ "EmacsFrame",
144 /* widget_size */ sizeof(EmacsFrameRec
),
145 /* class_initialize */ 0,
146 /* class_part_initialize */ 0,
147 /* class_inited */ FALSE
,
148 /* initialize */ EmacsFrameInitialize
,
149 /* initialize_hook */ 0,
150 /* realize */ EmacsFrameRealize
,
151 /* actions */ 0, /*emacsFrameActionsTable*/
152 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
153 /* resources */ resources
,
154 /* resource_count */ XtNumber(resources
),
155 /* xrm_class */ NULLQUARK
,
156 /* compress_motion */ TRUE
,
157 /* compress_exposure */ TRUE
,
158 /* compress_enterleave */ TRUE
,
159 /* visible_interest */ FALSE
,
160 /* destroy */ EmacsFrameDestroy
,
161 /* resize */ EmacsFrameResize
,
162 /* expose */ XtInheritExpose
,
163 /* set_values */ EmacsFrameSetValues
,
164 /* set_values_hook */ 0,
165 /* set_values_almost */ XtInheritSetValuesAlmost
,
166 /* get_values_hook */ 0,
167 /* accept_focus */ XtInheritAcceptFocus
,
168 /* version */ XtVersion
,
169 /* callback_private */ 0,
170 /* tm_table */ 0, /*emacsFrameTranslations*/
171 /* query_geometry */ EmacsFrameQueryGeometry
,
172 /* display_accelerator */ XtInheritDisplayAccelerator
,
177 WidgetClass emacsFrameClass
= (WidgetClass
) &emacsFrameClassRec
;
180 get_default_char_pixel_size (ew
, pixel_width
, pixel_height
)
185 struct frame
* f
= ew
->emacs_frame
.frame
;
186 *pixel_width
= FONT_WIDTH (f
->output_data
.x
->font
);
187 *pixel_height
= f
->output_data
.x
->line_height
;
191 pixel_to_char_size (ew
, pixel_width
, pixel_height
, char_width
, char_height
)
193 Dimension pixel_width
;
194 Dimension pixel_height
;
198 struct frame
* f
= ew
->emacs_frame
.frame
;
199 *char_width
= PIXEL_TO_CHAR_WIDTH (f
, (int) pixel_width
);
200 *char_height
= PIXEL_TO_CHAR_HEIGHT (f
, (int) pixel_height
);
204 char_to_pixel_size (ew
, char_width
, char_height
, pixel_width
, pixel_height
)
208 Dimension
* pixel_width
;
209 Dimension
* pixel_height
;
211 struct frame
* f
= ew
->emacs_frame
.frame
;
212 *pixel_width
= CHAR_TO_PIXEL_WIDTH (f
, char_width
);
213 *pixel_height
= CHAR_TO_PIXEL_HEIGHT (f
, char_height
);
217 round_size_to_char (ew
, in_width
, in_height
, out_width
, out_height
)
221 Dimension
* out_width
;
222 Dimension
* out_height
;
226 pixel_to_char_size (ew
, in_width
, in_height
, &char_width
, &char_height
);
227 char_to_pixel_size (ew
, char_width
, char_height
, out_width
, out_height
);
236 for (wmshell
= XtParent (w
);
237 wmshell
&& !XtIsWMShell (wmshell
);
238 wmshell
= XtParent (wmshell
));
243 #if 0 /* Currently not used. */
246 mark_shell_size_user_specified (wmshell
)
249 if (! XtIsWMShell (wmshell
)) abort ();
250 /* This is kind of sleazy, but I can't see how else to tell it to make it
251 mark the WM_SIZE_HINTS size as user specified when appropriate. */
252 ((WMShellWidget
) wmshell
)->wm
.size_hints
.flags
|= USSize
;
258 /* Can't have static frame locals because of some broken compilers.
259 Normally, initializing a variable like this doesn't work in emacs,
260 but it's ok in this file because it must come after lastfile (and
261 thus have its data not go into text space) because Xt needs to
262 write to initialized data objects too.
265 static Boolean first_frame_p
= True
;
272 /* The widget hierarchy is
274 argv[0] emacsShell pane Frame-NAME
275 ApplicationShell EmacsShell Paned EmacsFrame
277 We accept geometry specs in this order:
283 Other possibilities for widget hierarchies might be
285 argv[0] frame pane Frame-NAME
286 ApplicationShell EmacsShell Paned EmacsFrame
288 argv[0] Frame-NAME pane Frame-NAME
289 ApplicationShell EmacsShell Paned EmacsFrame
291 argv[0] Frame-NAME pane emacsTextPane
292 ApplicationShell EmacsFrame Paned EmacsTextPane
294 With the current setup, the text-display-area is the part which is
295 an emacs "frame", since that's the only part managed by emacs proper
296 (the menubar and the parent of the menubar and all that sort of thing
297 are managed by lwlib.)
299 The EmacsShell widget is simply a replacement for the Shell widget
300 which is able to deal with using an externally-supplied window instead
301 of always creating its own. It is not actually emacs specific, and
302 should possibly have class "Shell" instead of "EmacsShell" to simplify
307 /* Hairily merged geometry */
308 unsigned int w
= ew
->emacs_frame
.frame
->width
;
309 unsigned int h
= ew
->emacs_frame
.frame
->height
;
311 Widget wmshell
= get_wm_shell ((Widget
) ew
);
312 /* Each Emacs shell is now independent and top-level. */
314 if (! XtIsSubclass (wmshell
, shellWidgetClass
)) abort ();
316 /* We don't need this for the moment. The geometry is computed in
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
, NULL
);
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
, NULL
);
333 XtVaGetValues (app_shell
, XtNgeometry
, &geom
, NULL
);
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
, NULL
);
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
;
426 /* Take into account the size of the scrollbar. Always use the
427 number of columns occupied by the scroll bar here otherwise we
428 might end up with a frame width that is not a multiple of the
429 frame's character width which is bad for vertically split
431 frame
->output_data
.x
->vertical_scroll_bar_extra
432 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (frame
)
434 : (FRAME_SCROLL_BAR_COLS (frame
)
435 * FONT_WIDTH (frame
->output_data
.x
->font
)));
437 frame
->output_data
.x
->flags_areas_extra
438 = FRAME_FLAGS_AREA_WIDTH (frame
);
440 change_frame_size (frame
, h
, w
, 1, 0, 0);
441 char_to_pixel_size (ew
, w
, h
, &pixel_width
, &pixel_height
);
442 ew
->core
.width
= pixel_width
;
443 ew
->core
.height
= pixel_height
;
445 #if 0 /* xfns.c takes care of this now. */
446 /* If a position was specified, assign it to the shell widget.
447 (Else WM won't do anything with it.)
449 if (flags
& (XValue
| YValue
))
451 /* the tricky things with the sign is to make sure that
455 sprintf (shell_position
, "=%c%d%c%d",
456 flags
& XNegative
? '-' : '+', x
< 0 ? -x
: x
,
457 flags
& YNegative
? '-' : '+', y
< 0 ? -y
: y
);
458 len
= strlen (shell_position
) + 1;
459 tem
= (char *) xmalloc (len
);
460 strncpy (tem
, shell_position
, len
);
461 XtVaSetValues (wmshell
, XtNgeometry
, tem
, NULL
);
463 else if (flags
& (WidthValue
| HeightValue
))
467 sprintf (shell_position
, "=%dx%d", pixel_width
, pixel_height
);
468 len
= strlen (shell_position
) + 1;
469 tem
= (char *) xmalloc (len
);
470 strncpy (tem
, shell_position
, len
);
471 XtVaSetValues (wmshell
, XtNgeometry
, tem
, NULL
);
474 /* If the geometry spec we're using has W/H components, mark the size
475 in the WM_SIZE_HINTS as user specified. */
476 if (flags
& (WidthValue
| HeightValue
))
477 mark_shell_size_user_specified (wmshell
);
479 /* Also assign the iconic status of the frame to the Shell, so that
481 XtVaSetValues (wmshell
, XtNiconic
, ew
->emacs_frame
.iconic
, NULL
);
486 /* Nonzero tells update_wm_hints not to do anything
487 (the caller should call update_wm_hints explicitly later.) */
488 int update_hints_inhibit
;
494 Widget wmshell
= get_wm_shell ((Widget
)ew
);
497 Dimension rounded_width
;
498 Dimension rounded_height
;
503 int min_rows
= 0, min_cols
= 0;
505 if (update_hints_inhibit
)
509 check_frame_size (ew
->emacs_frame
.frame
, &min_rows
, &min_cols
);
512 pixel_to_char_size (ew
, ew
->core
.width
, ew
->core
.height
,
513 &char_width
, &char_height
);
514 char_to_pixel_size (ew
, char_width
, char_height
,
515 &rounded_width
, &rounded_height
);
516 get_default_char_pixel_size (ew
, &cw
, &ch
);
518 base_width
= (wmshell
->core
.width
- ew
->core
.width
519 + (rounded_width
- (char_width
* cw
)));
520 base_height
= (wmshell
->core
.height
- ew
->core
.height
521 + (rounded_height
- (char_height
* ch
)));
523 /* This is kind of sleazy, but I can't see how else to tell it to
524 make it mark the WM_SIZE_HINTS size as user specified.
526 /* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
528 XtVaSetValues (wmshell
,
529 XtNbaseWidth
, (XtArgVal
) base_width
,
530 XtNbaseHeight
, (XtArgVal
) base_height
,
531 XtNwidthInc
, (XtArgVal
) cw
,
532 XtNheightInc
, (XtArgVal
) ch
,
533 XtNminWidth
, (XtArgVal
) (base_width
+ min_cols
* cw
),
534 XtNminHeight
, (XtArgVal
) (base_height
+ min_rows
* ch
),
541 create_frame_gcs (ew
)
544 struct frame
*s
= ew
->emacs_frame
.frame
;
546 s
->output_data
.x
->normal_gc
547 = XCreateGC (XtDisplay (ew
), RootWindowOfScreen (XtScreen (ew
)),
548 (unsigned long)0, (XGCValues
*)0);
549 s
->output_data
.x
->reverse_gc
550 = XCreateGC (XtDisplay (ew
), RootWindowOfScreen (XtScreen (ew
)),
551 (unsigned long)0, (XGCValues
*)0);
552 s
->output_data
.x
->cursor_gc
553 = XCreateGC (XtDisplay (ew
), RootWindowOfScreen (XtScreen (ew
)),
554 (unsigned long)0, (XGCValues
*)0);
555 s
->output_data
.x
->black_relief
.gc
= 0;
556 s
->output_data
.x
->white_relief
.gc
= 0;
561 static char setup_frame_cursor_bits
[] =
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,
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
574 struct frame
* s
= ew
->emacs_frame
.frame
;
575 Pixmap blank_stipple
, blank_tile
;
577 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
578 XGetGCValues returns uninitialized data when we query the stipple
579 (instead of None or something sensible) and it makes things hard.
581 This should be fixed for real by not querying the GCs but instead having
582 some GC-based cache instead of the current face-based cache which doesn't
583 effectively cache all of the GC settings we need to use.
587 = XCreateBitmapFromData (XtDisplay (ew
),
588 RootWindowOfScreen (XtScreen (ew
)),
589 setup_frame_cursor_bits
, 2, 2);
591 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
592 never actually get used as a background tile!
595 = XCreatePixmapFromBitmapData (XtDisplay(ew
),
596 RootWindowOfScreen (XtScreen (ew
)),
597 setup_frame_cursor_bits
, 2, 2,
598 (unsigned long)0, (unsigned long)1,
602 gc_values
.font
= ew
->emacs_frame
.font
->fid
;
603 gc_values
.foreground
= ew
->emacs_frame
.foreground_pixel
;
604 gc_values
.background
= ew
->core
.background_pixel
;
605 gc_values
.graphics_exposures
= False
;
606 gc_values
.stipple
= blank_stipple
;
607 gc_values
.tile
= blank_tile
;
608 XChangeGC (XtDisplay (ew
), s
->output_data
.x
->normal_gc
,
609 (GCFont
| GCForeground
| GCBackground
| GCGraphicsExposures
610 | GCStipple
| GCTile
),
613 /* Reverse video style. */
614 gc_values
.font
= ew
->emacs_frame
.font
->fid
;
615 gc_values
.foreground
= ew
->core
.background_pixel
;
616 gc_values
.background
= ew
->emacs_frame
.foreground_pixel
;
617 gc_values
.graphics_exposures
= False
;
618 gc_values
.stipple
= blank_stipple
;
619 gc_values
.tile
= blank_tile
;
620 XChangeGC (XtDisplay (ew
), s
->output_data
.x
->reverse_gc
,
621 (GCFont
| GCForeground
| GCBackground
| GCGraphicsExposures
622 | GCStipple
| GCTile
),
625 /* Cursor has to have an empty stipple. */
626 gc_values
.font
= ew
->emacs_frame
.font
->fid
;
627 gc_values
.foreground
= ew
->core
.background_pixel
;
628 gc_values
.background
= ew
->emacs_frame
.cursor_color
;
629 gc_values
.graphics_exposures
= False
;
630 gc_values
.tile
= blank_tile
;
632 = XCreateBitmapFromData (XtDisplay (ew
),
633 RootWindowOfScreen (XtScreen (ew
)),
634 setup_frame_cursor_bits
, 16, 16);
635 XChangeGC (XtDisplay (ew
), s
->output_data
.x
->cursor_gc
,
636 (GCFont
| GCForeground
| GCBackground
| GCGraphicsExposures
637 | GCStipple
| GCTile
),
642 update_various_frame_slots (ew
)
645 struct x_output
*x
= ew
->emacs_frame
.frame
->output_data
.x
;
646 x
->pixel_height
= ew
->core
.height
+ x
->menubar_height
;
647 x
->pixel_width
= ew
->core
.width
;
648 x
->internal_border_width
= ew
->emacs_frame
.internal_border_width
;
653 update_from_various_frame_slots (ew
)
656 struct x_output
*x
= ew
->emacs_frame
.frame
->output_data
.x
;
657 ew
->core
.height
= x
->pixel_height
- x
->menubar_height
;
658 ew
->core
.width
= x
->pixel_width
;
659 ew
->core
.background_pixel
= x
->background_pixel
;
660 ew
->emacs_frame
.internal_border_width
= x
->internal_border_width
;
661 ew
->emacs_frame
.font
= x
->font
;
662 ew
->emacs_frame
.foreground_pixel
= x
->foreground_pixel
;
663 ew
->emacs_frame
.cursor_color
= x
->cursor_pixel
;
664 ew
->core
.border_pixel
= x
->border_pixel
;
668 EmacsFrameInitialize (request
, new, dum1
, dum2
)
674 EmacsFrame ew
= (EmacsFrame
)new;
676 if (!ew
->emacs_frame
.frame
)
679 "can't create an emacs frame widget without a frame\n");
683 #if 0 /* done in xfns.c */
684 /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
685 resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
686 It's unfortunate that we have to do this, but we need to know the font
687 size for frame-sizing purposes before the faces get initialized. If
688 the "default.attributeFont" isn't set, then we use the font of this
689 EmacsFrame itself, defaulting to XtDefaultFont. Up in the lisp code,
690 the "default" face will use the frame's font if its own is not set,
691 so everything stays in sync -- it's not possible for the frame's font
692 and the default face's font to be different.
697 face_res
.resource_name
= "attributeFont";
698 face_res
.resource_class
= "AttributeFont";
699 face_res
.resource_type
= XtRFontStruct
;
700 face_res
.resource_size
= sizeof (XFontStruct
*);
701 face_res
.resource_offset
= 0;
702 face_res
.default_type
= XtRImmediate
;
703 face_res
.default_addr
= 0;
704 XtGetSubresources ((Widget
) ew
, (XtPointer
) &f
, "default", "Face",
705 &face_res
, 1, NULL
, 0);
708 ew
->emacs_frame
.font
= f
;
709 else if (! ew
->emacs_frame
.font
)
711 fprintf (stderr
, "emacs frame widget could not load a font\n");
716 /* Update the font field in frame */
717 ew
->emacs_frame
.frame
->output_data
.x
->font
= ew
->emacs_frame
.font
;
720 update_from_various_frame_slots (ew
);
722 /*create_frame_gcs (ew);
723 setup_frame_gcs (ew);
724 update_various_frame_slots (ew); */
729 EmacsFrameRealize (widget
, mask
, attrs
)
732 XSetWindowAttributes
*attrs
;
734 EmacsFrame ew
= (EmacsFrame
)widget
;
736 /* This used to contain SubstructureRedirectMask, but this turns out
737 to be a problem with XIM on Solaris, and events from that mask
738 don't seem to be used. Let's check that. */
739 attrs
->event_mask
= (STANDARD_EVENT_SET
741 | SubstructureNotifyMask
);
742 *mask
|= CWEventMask
;
743 XtCreateWindow (widget
, InputOutput
, (Visual
*)CopyFromParent
, *mask
,
745 update_wm_hints (ew
);
748 extern void free_frame_faces (/* struct frame * */);
751 EmacsFrameDestroy (widget
)
754 EmacsFrame ew
= (EmacsFrame
) widget
;
755 struct frame
* s
= ew
->emacs_frame
.frame
;
758 if (! s
->output_data
.x
) abort ();
759 if (! s
->output_data
.x
->normal_gc
) abort ();
763 if (s
->output_data
.x
->white_relief
.gc
)
764 XFreeGC (XtDisplay (widget
), s
->output_data
.x
->white_relief
.gc
);
765 if (s
->output_data
.x
->black_relief
.gc
)
766 XFreeGC (XtDisplay (widget
), s
->output_data
.x
->black_relief
.gc
);
771 EmacsFrameResize (widget
)
774 EmacsFrame ew
= (EmacsFrame
)widget
;
775 struct frame
*f
= ew
->emacs_frame
.frame
;
779 pixel_to_char_size (ew
, ew
->core
.width
, ew
->core
.height
, &columns
, &rows
);
780 change_frame_size (f
, rows
, columns
, 0, 1, 0);
781 update_wm_hints (ew
);
782 update_various_frame_slots (ew
);
784 cancel_mouse_face (f
);
788 EmacsFrameSetValues (cur_widget
, req_widget
, new_widget
, dum1
, dum2
)
795 EmacsFrame cur
= (EmacsFrame
)cur_widget
;
796 EmacsFrame
new = (EmacsFrame
)new_widget
;
798 Boolean needs_a_refresh
= False
;
799 Boolean has_to_recompute_size
;
800 Boolean has_to_recompute_gcs
;
801 Boolean has_to_update_hints
;
803 int char_width
, char_height
;
804 Dimension pixel_width
;
805 Dimension pixel_height
;
807 has_to_recompute_gcs
= (cur
->emacs_frame
.font
!= new->emacs_frame
.font
808 || (cur
->emacs_frame
.foreground_pixel
809 != new->emacs_frame
.foreground_pixel
)
810 || (cur
->core
.background_pixel
811 != new->core
.background_pixel
)
814 has_to_recompute_size
= (cur
->emacs_frame
.font
!= new->emacs_frame
.font
815 && cur
->core
.width
== new->core
.width
816 && cur
->core
.height
== new->core
.height
);
818 has_to_update_hints
= (cur
->emacs_frame
.font
!= new->emacs_frame
.font
);
820 if (has_to_recompute_gcs
)
822 setup_frame_gcs (new);
823 needs_a_refresh
= True
;
826 if (has_to_recompute_size
)
828 pixel_width
= new->core
.width
;
829 pixel_height
= new->core
.height
;
830 pixel_to_char_size (new, pixel_width
, pixel_height
, &char_width
,
832 char_to_pixel_size (new, char_width
, char_height
, &pixel_width
,
834 new->core
.width
= pixel_width
;
835 new->core
.height
= pixel_height
;
837 change_frame_size (new->emacs_frame
.frame
, char_height
, char_width
,
839 needs_a_refresh
= True
;
842 if (has_to_update_hints
)
843 update_wm_hints (new);
845 update_various_frame_slots (new);
847 /* #### This doesn't work, I haven't been able to find ANY kludge that
848 will let (x-create-frame '((iconic . t))) work. It seems that changes
849 to wm_shell's iconic slot have no effect after it has been realized,
850 and calling XIconifyWindow doesn't work either (even though the window
851 has been created.) Perhaps there is some property we could smash
852 directly, but I'm sick of this for now.
854 if (cur
->emacs_frame
.iconic
!= new->emacs_frame
.iconic
)
856 Widget wmshell
= get_wm_shell ((Widget
) cur
);
857 XtVaSetValues (wmshell
, XtNiconic
,
858 (XtArgVal
) new->emacs_frame
.iconic
, NULL
);
861 return needs_a_refresh
;
864 static XtGeometryResult
865 EmacsFrameQueryGeometry (widget
, request
, result
)
867 XtWidgetGeometry
* request
;
868 XtWidgetGeometry
* result
;
870 EmacsFrame ew
= (EmacsFrame
)widget
;
872 int mask
= request
->request_mode
;
873 Dimension ok_width
, ok_height
;
875 if (mask
& (CWWidth
| CWHeight
))
877 round_size_to_char (ew
,
878 (mask
& CWWidth
) ? request
->width
: ew
->core
.width
,
879 ((mask
& CWHeight
) ? request
->height
881 &ok_width
, &ok_height
);
882 if ((mask
& CWWidth
) && (ok_width
!= request
->width
))
884 result
->request_mode
|= CWWidth
;
885 result
->width
= ok_width
;
887 if ((mask
& CWHeight
) && (ok_height
!= request
->height
))
889 result
->request_mode
|= CWHeight
;
890 result
->height
= ok_height
;
893 return result
->request_mode
? XtGeometryAlmost
: XtGeometryYes
;
896 /* Special entrypoints */
898 EmacsFrameSetCharSize (widget
, columns
, rows
)
903 EmacsFrame ew
= (EmacsFrame
) widget
;
904 Dimension pixel_width
, pixel_height
;
905 struct frame
*f
= ew
->emacs_frame
.frame
;
907 if (columns
< 3) columns
= 3; /* no way buddy */
909 check_frame_size (f
, &rows
, &columns
);
910 f
->output_data
.x
->vertical_scroll_bar_extra
911 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
913 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
915 f
->output_data
.x
->flags_areas_extra
916 = FRAME_FLAGS_AREA_WIDTH (f
);
918 char_to_pixel_size (ew
, columns
, rows
, &pixel_width
, &pixel_height
);
920 #if 0 /* This doesn't seem to be right. The frame gets too wide. --gerd. */
921 /* Something is really strange here wrt to the border width:
922 Apparently, XtNwidth and XtNheight include the border, so we have
923 to add it here. But the XtNborderWidth set for the widgets has
924 no similarity to what f->output_data.x->border_width is set to. */
925 XtVaGetValues (widget
, XtNborderWidth
, &border_width
, NULL
);
926 pixel_height
+= 2 * border_width
;
927 pixel_width
+= 2 * border_width
;
930 /* Manually change the height and width of all our widgets,
931 adjusting each widget by the same increments. */
932 if (ew
->core
.width
!= pixel_width
933 || ew
->core
.height
!= pixel_height
)
935 int hdelta
= pixel_height
- ew
->core
.height
;
936 int wdelta
= pixel_width
- ew
->core
.width
;
937 int column_widget_height
= f
->output_data
.x
->column_widget
->core
.height
;
938 int column_widget_width
= f
->output_data
.x
->column_widget
->core
.width
;
939 int outer_widget_height
= f
->output_data
.x
->widget
->core
.height
;
940 int outer_widget_width
= f
->output_data
.x
->widget
->core
.width
;
941 int old_left
= f
->output_data
.x
->widget
->core
.x
;
942 int old_top
= f
->output_data
.x
->widget
->core
.y
;
944 /* Input is blocked here, and Xt waits for some event to
947 lw_refigure_widget (f
->output_data
.x
->column_widget
, False
);
948 update_hints_inhibit
= 1;
950 /* Xt waits for a ConfigureNotify event from the window manager
951 in EmacsFrameSetCharSize when the shell widget is resized.
952 For some window managers like fvwm2 2.2.5 and KDE 2.1 this
953 event doesn't arrive for an unknown reason and Emacs hangs in
954 Xt when the default font is changed. Tell Xt not to wait,
955 depending on the value of the frame parameter
957 XtVaSetValues (f
->output_data
.x
->widget
,
958 XtNwaitForWm
, (XtArgVal
) f
->output_data
.x
->wait_for_wm
,
961 /* Workaround: When a SIGIO or SIGALRM occurs while Xt is
962 waiting for a ConfigureNotify event (see above), this leads
963 to Xt waiting indefinitely instead of using its default
964 timeout (5 seconds). */
967 sigblock (sigmask (SIGIO
));
970 /* Do parents first, otherwise LessTif's geometry management
971 enters an infinite loop (as of 2000-01-15). This is fixed in
972 later versions of LessTif (as of 2001-03-13); I'll leave it
973 as is because I think it can't do any harm. */
974 XtVaSetValues (f
->output_data
.x
->widget
,
975 XtNheight
, (XtArgVal
) (outer_widget_height
+ hdelta
),
976 XtNwidth
, (XtArgVal
) (outer_widget_width
+ wdelta
),
978 XtVaSetValues (f
->output_data
.x
->column_widget
,
979 XtNheight
, (XtArgVal
) (column_widget_height
+ hdelta
),
980 XtNwidth
, (XtArgVal
) column_widget_width
+ wdelta
,
982 XtVaSetValues ((Widget
) ew
,
983 XtNheight
, (XtArgVal
) pixel_height
,
984 XtNwidth
, (XtArgVal
) pixel_width
,
987 sigunblock (sigmask (SIGIO
));
991 lw_refigure_widget (f
->output_data
.x
->column_widget
, True
);
993 update_hints_inhibit
= 0;
994 update_wm_hints (ew
);
996 /* These seem to get clobbered. I don't know why. - rms. */
997 f
->output_data
.x
->widget
->core
.x
= old_left
;
998 f
->output_data
.x
->widget
->core
.y
= old_top
;
1001 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
1002 receive in the ConfigureNotify event; if we get what we asked
1003 for, then the event won't cause the screen to become garbaged, so
1004 we have to make sure to do it here. */
1005 SET_FRAME_GARBAGED (f
);
1010 widget_store_internal_border (widget
)
1013 EmacsFrame ew
= (EmacsFrame
) widget
;
1014 FRAME_PTR f
= ew
->emacs_frame
.frame
;
1016 ew
->emacs_frame
.internal_border_width
1017 = f
->output_data
.x
->internal_border_width
;