Comment change.
[emacs.git] / src / widget.c
blobde25e2da4850d078a33e29e4591a5eb1466728f1
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)
9 any later version.
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/
33 #include <config.h>
34 #include <stdio.h>
35 #include "lisp.h"
36 #include "xterm.h"
38 #include "frame.h"
40 #include "dispextern.h"
41 #include "blockinput.h"
43 #include <X11/StringDefs.h>
44 #include <X11/IntrinsicP.h>
45 #include <X11/cursorfont.h>
46 #include "widgetprv.h"
47 #include <X11/ObjectP.h>
48 #include <X11/Shell.h>
49 #include <X11/ShellP.h>
50 #include "../lwlib/lwlib.h"
52 #define max(a, b) ((a) > (b) ? (a) : (b))
54 /* This sucks: this is the first default that x-faces.el tries. This won't
55 be used unless neither the "Emacs.EmacsFrame" resource nor the
56 "Emacs.EmacsFrame" resource is set; the frame
57 may have the wrong default size if this font doesn't exist, but some other
58 font that x-faces.el does. The workaround is to specify some font in the
59 resource database; I don't know a solution other than duplicating the font-
60 searching code from x-faces.el in this file.
62 This also means that if "Emacs.EmacsFrame" is specified as a non-
63 existent font, then Xt is going to substitute "XtDefaultFont" for it,
64 which is a different size than this one. The solution for this is to
65 make x-faces.el try to use XtDefaultFont. The problem with that is that
66 XtDefaultFont is almost certainly variable-width.
68 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
70 #define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
73 static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
74 static void EmacsFrameDestroy (/* Widget */);
75 static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
76 void EmacsFrameResize (/* Widget widget */);
77 static Boolean EmacsFrameSetValues (/* Widget, Widget, Widget,
78 ArgList, Cardinal * */);
79 static XtGeometryResult EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
80 XtWidgetGeometry* */);
83 #undef XtOffset
84 #define XtOffset(p_type,field) \
85 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
86 #define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
88 static XtResource resources[] = {
89 {XtNgeometry, XtCGeometry, XtRString, sizeof(String),
90 offset (geometry), XtRString, (XtPointer) 0},
91 {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
92 offset (iconic), XtRImmediate, (XtPointer) False},
94 {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
95 offset (frame), XtRImmediate, 0},
97 {XtNminibuffer, XtCMinibuffer, XtRInt, sizeof (int),
98 offset (minibuffer), XtRImmediate, (XtPointer)0},
99 {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
100 offset (unsplittable), XtRImmediate, (XtPointer)0},
101 {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
102 offset (internal_border_width), XtRImmediate, (XtPointer)4},
103 {XtNinterline, XtCInterline, XtRInt, sizeof (int),
104 offset (interline), XtRImmediate, (XtPointer)0},
105 {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
106 offset(font),XtRString, DEFAULT_FACE_FONT},
107 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
108 offset(foreground_pixel), XtRString, "XtDefaultForeground"},
109 {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
110 offset(cursor_color), XtRString, "XtDefaultForeground"},
111 {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
112 offset (bar_cursor), XtRImmediate, (XtPointer)0},
113 {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
114 offset (visual_bell), XtRImmediate, (XtPointer)0},
115 {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
116 offset (bell_volume), XtRImmediate, (XtPointer)0},
119 #undef offset
122 static XtActionsRec
123 emacsFrameActionsTable [] = {
124 {"keypress", key_press},
125 {"focus_in", emacs_frame_focus_handler},
126 {"focus_out", emacs_frame_focus_handler},
129 static char
130 emacsFrameTranslations [] = "\
131 <KeyPress>: keypress()\n\
132 <FocusIn>: focus_in()\n\
133 <FocusOut>: focus_out()\n\
137 EmacsFrameClassRec emacsFrameClassRec = {
138 { /* core fields */
139 /* superclass */ &widgetClassRec,
140 /* class_name */ "EmacsFrame",
141 /* widget_size */ sizeof(EmacsFrameRec),
142 /* class_initialize */ 0,
143 /* class_part_initialize */ 0,
144 /* class_inited */ FALSE,
145 /* initialize */ EmacsFrameInitialize,
146 /* initialize_hook */ 0,
147 /* realize */ EmacsFrameRealize,
148 /* actions */ 0, /*emacsFrameActionsTable*/
149 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
150 /* resources */ resources,
151 /* resource_count */ XtNumber(resources),
152 /* xrm_class */ NULLQUARK,
153 /* compress_motion */ TRUE,
154 /* compress_exposure */ TRUE,
155 /* compress_enterleave */ TRUE,
156 /* visible_interest */ FALSE,
157 /* destroy */ EmacsFrameDestroy,
158 /* resize */ EmacsFrameResize,
159 /* expose */ XtInheritExpose,
160 /* set_values */ EmacsFrameSetValues,
161 /* set_values_hook */ 0,
162 /* set_values_almost */ XtInheritSetValuesAlmost,
163 /* get_values_hook */ 0,
164 /* accept_focus */ XtInheritAcceptFocus,
165 /* version */ XtVersion,
166 /* callback_private */ 0,
167 /* tm_table */ 0, /*emacsFrameTranslations*/
168 /* query_geometry */ EmacsFrameQueryGeometry,
169 /* display_accelerator */ XtInheritDisplayAccelerator,
170 /* extension */ 0
174 WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
176 static void
177 get_default_char_pixel_size (ew, pixel_width, pixel_height)
178 EmacsFrame ew;
179 int* pixel_width;
180 int* pixel_height;
182 struct frame* f = ew->emacs_frame.frame;
183 *pixel_width = FONT_WIDTH (f->output_data.x->font);
184 *pixel_height = f->output_data.x->line_height;
187 static void
188 pixel_to_char_size (ew, pixel_width, pixel_height, char_width, char_height)
189 EmacsFrame ew;
190 Dimension pixel_width;
191 Dimension pixel_height;
192 int* char_width;
193 int* char_height;
195 struct frame* f = ew->emacs_frame.frame;
196 *char_width = PIXEL_TO_CHAR_WIDTH (f, pixel_width);
197 *char_height = PIXEL_TO_CHAR_HEIGHT (f, pixel_height);
200 static void
201 char_to_pixel_size (ew, char_width, char_height, pixel_width, pixel_height)
202 EmacsFrame ew;
203 int char_width;
204 int char_height;
205 Dimension* pixel_width;
206 Dimension* pixel_height;
208 struct frame* f = ew->emacs_frame.frame;
209 *pixel_width = CHAR_TO_PIXEL_WIDTH (f, char_width);
210 *pixel_height = CHAR_TO_PIXEL_HEIGHT (f, char_height);
213 static void
214 round_size_to_char (ew, in_width, in_height, out_width, out_height)
215 EmacsFrame ew;
216 Dimension in_width;
217 Dimension in_height;
218 Dimension* out_width;
219 Dimension* out_height;
221 int char_width;
222 int char_height;
223 pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
224 char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
227 static Widget
228 get_wm_shell (w)
229 Widget w;
231 Widget wmshell;
233 for (wmshell = XtParent (w);
234 wmshell && !XtIsWMShell (wmshell);
235 wmshell = XtParent (wmshell));
237 return wmshell;
240 static void
241 mark_shell_size_user_specified (wmshell)
242 Widget wmshell;
244 if (! XtIsWMShell (wmshell)) abort ();
245 /* This is kind of sleazy, but I can't see how else to tell it to make it
246 mark the WM_SIZE_HINTS size as user specified when appropriate. */
247 ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
251 /* Can't have static frame locals because of some broken compilers.
252 Normally, initializing a variable like this doesn't work in emacs,
253 but it's ok in this file because it must come after lastfile (and
254 thus have its data not go into text space) because Xt needs to
255 write to initialized data objects too.
257 static Boolean first_frame_p = True;
259 static void
260 set_frame_size (ew)
261 EmacsFrame ew;
263 /* The widget hierarchy is
265 argv[0] emacsShell pane Frame-NAME
266 ApplicationShell EmacsShell Paned EmacsFrame
268 We accept geometry specs in this order:
270 *Frame-NAME.geometry
271 *EmacsFrame.geometry
272 Emacs.geometry
274 Other possibilities for widget hierarchies might be
276 argv[0] frame pane Frame-NAME
277 ApplicationShell EmacsShell Paned EmacsFrame
279 argv[0] Frame-NAME pane Frame-NAME
280 ApplicationShell EmacsShell Paned EmacsFrame
282 argv[0] Frame-NAME pane emacsTextPane
283 ApplicationShell EmacsFrame Paned EmacsTextPane
285 With the current setup, the text-display-area is the part which is
286 an emacs "frame", since that's the only part managed by emacs proper
287 (the menubar and the parent of the menubar and all that sort of thing
288 are managed by lwlib.)
290 The EmacsShell widget is simply a replacement for the Shell widget
291 which is able to deal with using an externally-supplied window instead
292 of always creating its own. It is not actually emacs specific, and
293 should possibly have class "Shell" instead of "EmacsShell" to simplify
294 the resources.
298 /* Geometry of the AppShell */
299 int app_flags = 0;
300 int app_x = 0;
301 int app_y = 0;
302 unsigned int app_w = 0;
303 unsigned int app_h = 0;
305 /* Geometry of the EmacsFrame */
306 int frame_flags = 0;
307 int frame_x = 0;
308 int frame_y = 0;
309 unsigned int frame_w = 0;
310 unsigned int frame_h = 0;
312 /* Hairily merged geometry */
313 int x = 0;
314 int y = 0;
315 unsigned int w = ew->emacs_frame.frame->width;
316 unsigned int h = ew->emacs_frame.frame->height;
317 int flags = 0;
319 Widget wmshell = get_wm_shell ((Widget) ew);
320 /* Each Emacs shell is now independent and top-level. */
321 Widget app_shell = wmshell;
323 if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
325 /* We don't need this for the moment. The geometry is computed in
326 xfns.c. */
327 #if 0
328 /* If the EmacsFrame doesn't have a geometry but the shell does,
329 treat that as the geometry of the frame. (Is this bogus?
330 I'm not sure.) */
331 if (ew->emacs_frame.geometry == 0)
332 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, 0);
334 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
335 this bogus? I'm not sure.) */
336 if (!ew->emacs_frame.iconic)
337 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, 0);
341 char *geom = 0;
342 XtVaGetValues (app_shell, XtNgeometry, &geom, 0);
343 if (geom)
344 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
347 if (ew->emacs_frame.geometry)
348 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
349 &frame_x, &frame_y,
350 &frame_w, &frame_h);
352 if (first_frame_p)
354 /* If this is the first frame created:
355 ====================================
357 - Use the ApplicationShell's size/position, if specified.
358 (This is "Emacs.geometry", or the "-geometry" command line arg.)
359 - Else use the EmacsFrame's size/position.
360 (This is "*Frame-NAME.geometry")
362 - If the AppShell is iconic, the frame should be iconic.
364 AppShell comes first so that -geometry always applies to the first
365 frame created, even if there is an "every frame" entry in the
366 resource database.
368 if (app_flags & (XValue | YValue))
370 x = app_x; y = app_y;
371 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
373 else if (frame_flags & (XValue | YValue))
375 x = frame_x; y = frame_y;
376 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
379 if (app_flags & (WidthValue | HeightValue))
381 w = app_w; h = app_h;
382 flags |= (app_flags & (WidthValue | HeightValue));
384 else if (frame_flags & (WidthValue | HeightValue))
386 w = frame_w; h = frame_h;
387 flags |= (frame_flags & (WidthValue | HeightValue));
390 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
391 if (!ew->emacs_frame.iconic)
392 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, 0);
394 first_frame_p = False;
396 else
398 /* If this is not the first frame created:
399 ========================================
401 - use the EmacsFrame's size/position if specified
402 - Otherwise, use the ApplicationShell's size, but not position.
404 So that means that one can specify the position of the first frame
405 with "Emacs.geometry" or `-geometry'; but can only specify the
406 position of subsequent frames with "*Frame-NAME.geometry".
408 AppShell comes second so that -geometry does not apply to subsequent
409 frames when there is an "every frame" entry in the resource db,
410 but does apply to the first frame.
412 if (frame_flags & (XValue | YValue))
414 x = frame_x; y = frame_y;
415 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
418 if (frame_flags & (WidthValue | HeightValue))
420 w = frame_w; h = frame_h;
421 flags |= (frame_flags & (WidthValue | HeightValue));
423 else if (app_flags & (WidthValue | HeightValue))
425 w = app_w;
426 h = app_h;
427 flags |= (app_flags & (WidthValue | HeightValue));
430 #endif /* 0 */
432 struct frame* frame = ew->emacs_frame.frame;
433 Dimension pixel_width, pixel_height;
434 char shell_position [32];
436 /* Take into account the size of the scrollbar */
437 frame->output_data.x->vertical_scroll_bar_extra
438 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (frame)
440 : FRAME_SCROLL_BAR_PIXEL_WIDTH (frame) > 0
441 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (frame)
442 : (FRAME_SCROLL_BAR_COLS (frame)
443 * FONT_WIDTH (frame->output_data.x->font)));
445 change_frame_size (frame, h, w, 1, 0);
446 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
447 ew->core.width = pixel_width;
448 ew->core.height = pixel_height;
450 #if 0 /* xfns.c takes care of this now. */
451 /* If a position was specified, assign it to the shell widget.
452 (Else WM won't do anything with it.)
454 if (flags & (XValue | YValue))
456 /* the tricky things with the sign is to make sure that
457 -0 is printed -0. */
458 int len;
459 char *tem;
460 sprintf (shell_position, "=%c%d%c%d",
461 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
462 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
463 len = strlen (shell_position) + 1;
464 tem = (char *) xmalloc (len);
465 strncpy (tem, shell_position, len);
466 XtVaSetValues (wmshell, XtNgeometry, tem, 0);
468 else if (flags & (WidthValue | HeightValue))
470 int len;
471 char *tem;
472 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
473 len = strlen (shell_position) + 1;
474 tem = (char *) xmalloc (len);
475 strncpy (tem, shell_position, len);
476 XtVaSetValues (wmshell, XtNgeometry, tem, 0);
479 /* If the geometry spec we're using has W/H components, mark the size
480 in the WM_SIZE_HINTS as user specified. */
481 if (flags & (WidthValue | HeightValue))
482 mark_shell_size_user_specified (wmshell);
484 /* Also assign the iconic status of the frame to the Shell, so that
485 the WM sees it. */
486 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, 0);
487 #endif /* 0 */
491 /* Nonzero tells update_wm_hints not to do anything
492 (the caller should call update_wm_hints explicitly later.) */
493 int update_hints_inhibit;
495 static void
496 update_wm_hints (ew)
497 EmacsFrame ew;
499 Widget wmshell = get_wm_shell ((Widget)ew);
500 int cw;
501 int ch;
502 Dimension rounded_width;
503 Dimension rounded_height;
504 int char_width;
505 int char_height;
506 int base_width;
507 int base_height;
508 int min_rows = 0, min_cols = 0;
510 if (update_hints_inhibit)
511 return;
513 #if 0
514 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
515 #endif
517 pixel_to_char_size (ew, ew->core.width, ew->core.height,
518 &char_width, &char_height);
519 char_to_pixel_size (ew, char_width, char_height,
520 &rounded_width, &rounded_height);
521 get_default_char_pixel_size (ew, &cw, &ch);
523 base_width = (wmshell->core.width - ew->core.width
524 + (rounded_width - (char_width * cw)));
525 base_height = (wmshell->core.height - ew->core.height
526 + (rounded_height - (char_height * ch)));
528 /* This is kind of sleazy, but I can't see how else to tell it to
529 make it mark the WM_SIZE_HINTS size as user specified.
531 /* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
533 XtVaSetValues (wmshell,
534 XtNbaseWidth, base_width,
535 XtNbaseHeight, base_height,
536 XtNwidthInc, cw,
537 XtNheightInc, ch,
538 XtNminWidth, base_width + min_cols * cw,
539 XtNminHeight, base_height + min_rows * ch,
543 static void
544 create_frame_gcs (ew)
545 EmacsFrame ew;
547 struct frame *s = ew->emacs_frame.frame;
549 s->output_data.x->normal_gc
550 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
551 (unsigned long)0, (XGCValues *)0);
552 s->output_data.x->reverse_gc
553 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
554 (unsigned long)0, (XGCValues *)0);
555 s->output_data.x->cursor_gc
556 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
557 (unsigned long)0, (XGCValues *)0);
560 static char setup_frame_cursor_bits[] =
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
568 static void
569 setup_frame_gcs (ew)
570 EmacsFrame ew;
572 XGCValues gc_values;
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.
585 blank_stipple
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!
593 blank_tile
594 = XCreatePixmapFromBitmapData (XtDisplay(ew),
595 RootWindowOfScreen (XtScreen (ew)),
596 setup_frame_cursor_bits, 2, 2,
597 (unsigned long)0, (unsigned long)1,
598 ew->core.depth);
600 /* Normal video */
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),
610 &gc_values);
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),
622 &gc_values);
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;
630 gc_values.stipple
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),
637 &gc_values);
640 static void
641 update_various_frame_slots (ew)
642 EmacsFrame ew;
644 struct x_output *x = ew->emacs_frame.frame->output_data.x;
645 x->pixel_height = ew->core.height;
646 x->pixel_width = ew->core.width;
647 x->internal_border_width = ew->emacs_frame.internal_border_width;
651 static void
652 update_from_various_frame_slots (ew)
653 EmacsFrame ew;
655 struct x_output *x = ew->emacs_frame.frame->output_data.x;
656 ew->core.height = x->pixel_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;
666 static void
667 EmacsFrameInitialize (request, new, dum1, dum2)
668 Widget request;
669 Widget new;
670 ArgList dum1;
671 Cardinal *dum2;
673 EmacsFrame ew = (EmacsFrame)new;
675 if (!ew->emacs_frame.frame)
677 fprintf (stderr,
678 "can't create an emacs frame widget without a frame\n");
679 exit (1);
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.
694 XFontStruct *f = 0;
695 XtResource face_res;
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);
706 if (f)
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");
711 exit (1);
715 /* Update the font field in frame */
716 ew->emacs_frame.frame->output_data.x->font = ew->emacs_frame.font;
717 #endif
719 update_from_various_frame_slots (ew);
720 set_frame_size (ew);
721 /*create_frame_gcs (ew);
722 setup_frame_gcs (ew);
723 update_various_frame_slots (ew); */
727 static void
728 EmacsFrameRealize (widget, mask, attrs)
729 Widget widget;
730 XtValueMask *mask;
731 XSetWindowAttributes *attrs;
733 EmacsFrame ew = (EmacsFrame)widget;
735 attrs->event_mask = (KeyPressMask | ExposureMask | ButtonPressMask |
736 ButtonReleaseMask | StructureNotifyMask |
737 FocusChangeMask | PointerMotionHintMask |
738 PointerMotionMask | LeaveWindowMask | EnterWindowMask |
739 VisibilityChangeMask | PropertyChangeMask |
740 StructureNotifyMask | SubstructureNotifyMask |
741 SubstructureRedirectMask);
742 *mask |= CWEventMask;
743 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
744 attrs);
745 update_wm_hints (ew);
748 extern void free_frame_faces (/* struct frame * */);
750 static void
751 EmacsFrameDestroy (widget)
752 Widget widget;
754 EmacsFrame ew = (EmacsFrame) widget;
755 struct frame* s = ew->emacs_frame.frame;
757 if (! s) abort ();
758 if (! s->output_data.x) abort ();
759 if (! s->output_data.x->normal_gc) abort ();
761 /* this would be called from Fdelete_frame() but it needs to free some
762 stuff after the widget has been finalized but before the widget has
763 been freed. */
764 free_frame_faces (s);
766 BLOCK_INPUT;
767 /* need to be careful that the face-freeing code doesn't free these too */
768 XFreeGC (XtDisplay (widget), s->output_data.x->normal_gc);
769 XFreeGC (XtDisplay (widget), s->output_data.x->reverse_gc);
770 XFreeGC (XtDisplay (widget), s->output_data.x->cursor_gc);
771 UNBLOCK_INPUT;
774 void
775 EmacsFrameResize (widget)
776 Widget widget;
778 EmacsFrame ew = (EmacsFrame)widget;
779 struct frame *f = ew->emacs_frame.frame;
780 int columns;
781 int rows;
783 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
784 change_frame_size (f, rows, columns, 1, 0);
785 update_wm_hints (ew);
786 update_various_frame_slots (ew);
789 static Boolean
790 EmacsFrameSetValues (cur_widget, req_widget, new_widget, dum1, dum2)
791 Widget cur_widget;
792 Widget req_widget;
793 Widget new_widget;
794 ArgList dum1;
795 Cardinal *dum2;
797 EmacsFrame cur = (EmacsFrame)cur_widget;
798 EmacsFrame new = (EmacsFrame)new_widget;
800 Boolean needs_a_refresh = False;
801 Boolean has_to_recompute_size;
802 Boolean has_to_recompute_gcs;
803 Boolean has_to_update_hints;
805 int char_width, char_height;
806 Dimension pixel_width;
807 Dimension pixel_height;
809 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
810 || (cur->emacs_frame.foreground_pixel
811 != new->emacs_frame.foreground_pixel)
812 || (cur->core.background_pixel
813 != new->core.background_pixel)
816 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
817 && cur->core.width == new->core.width
818 && cur->core.height == new->core.height);
820 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
822 if (has_to_recompute_gcs)
824 setup_frame_gcs (new);
825 needs_a_refresh = True;
828 if (has_to_recompute_size)
830 pixel_width = new->core.width;
831 pixel_height = new->core.height;
832 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
833 &char_height);
834 char_to_pixel_size (new, char_width, char_height, &pixel_width,
835 &pixel_height);
836 new->core.width = pixel_width;
837 new->core.height = pixel_height;
839 change_frame_size (new->emacs_frame.frame, char_height, char_width,
840 1, 0);
841 needs_a_refresh = True;
844 if (has_to_update_hints)
845 update_wm_hints (new);
847 update_various_frame_slots (new);
849 /* #### This doesn't work, I haven't been able to find ANY kludge that
850 will let (x-create-frame '((iconic . t))) work. It seems that changes
851 to wm_shell's iconic slot have no effect after it has been realized,
852 and calling XIconifyWindow doesn't work either (even thought the window
853 has been created.) Perhaps there is some property we could smash
854 directly, but I'm sick of this for now.
856 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
858 Widget wmshell = get_wm_shell ((Widget) cur);
859 XtVaSetValues (wmshell, XtNiconic, new->emacs_frame.iconic, 0);
862 return needs_a_refresh;
865 static XtGeometryResult
866 EmacsFrameQueryGeometry (widget, request, result)
867 Widget widget;
868 XtWidgetGeometry* request;
869 XtWidgetGeometry* result;
871 EmacsFrame ew = (EmacsFrame)widget;
873 int mask = request->request_mode;
874 Dimension ok_width, ok_height;
876 if (mask & (CWWidth | CWHeight))
878 round_size_to_char (ew,
879 (mask & CWWidth) ? request->width : ew->core.width,
880 ((mask & CWHeight) ? request->height
881 : ew->core.height),
882 &ok_width, &ok_height);
883 if ((mask & CWWidth) && (ok_width != request->width))
885 result->request_mode |= CWWidth;
886 result->width = ok_width;
888 if ((mask & CWHeight) && (ok_height != request->height))
890 result->request_mode |= CWHeight;
891 result->height = ok_height;
894 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
897 /* Special entrypoints */
898 void
899 EmacsFrameSetCharSize (widget, columns, rows)
900 Widget widget;
901 int columns;
902 int rows;
904 EmacsFrame ew = (EmacsFrame) widget;
905 Dimension pixel_width, pixel_height, granted_width, granted_height;
906 XtGeometryResult result;
907 struct frame *f = ew->emacs_frame.frame;
908 Arg al[2];
909 int ac = 0;
911 if (columns < 3) columns = 3; /* no way buddy */
913 check_frame_size (f, &rows, &columns);
914 f->output_data.x->vertical_scroll_bar_extra
915 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
917 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
918 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
919 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
921 char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
923 /* Manually change the height and width of all our widgets,
924 adjusting each widget by the same increments. */
925 if (ew->core.width != pixel_width || ew->core.height != pixel_height)
927 int hdelta = pixel_height - ew->core.height;
928 int wdelta = pixel_width - ew->core.width;
929 int column_widget_height = f->output_data.x->column_widget->core.height;
930 int column_widget_width = f->output_data.x->column_widget->core.width;
931 int outer_widget_height = f->output_data.x->widget->core.height;
932 int outer_widget_width = f->output_data.x->widget->core.width;
933 int old_left = f->output_data.x->widget->core.x;
934 int old_top = f->output_data.x->widget->core.y;
936 lw_refigure_widget (f->output_data.x->column_widget, False);
937 update_hints_inhibit = 1;
939 ac = 0;
940 XtSetArg (al[ac], XtNheight, pixel_height); ac++;
941 XtSetArg (al[ac], XtNwidth, pixel_width); ac++;
942 XtSetValues ((Widget) ew, al, ac);
944 ac = 0;
945 XtSetArg (al[ac], XtNheight, column_widget_height + hdelta); ac++;
946 XtSetArg (al[ac], XtNwidth, column_widget_width + wdelta); ac++;
947 XtSetValues (f->output_data.x->column_widget, al, ac);
949 ac = 0;
950 XtSetArg (al[ac], XtNheight, outer_widget_height + hdelta); ac++;
951 XtSetArg (al[ac], XtNwidth, outer_widget_width + wdelta); ac++;
952 XtSetValues (f->output_data.x->widget, al, ac);
954 lw_refigure_widget (f->output_data.x->column_widget, True);
956 update_hints_inhibit = 0;
957 update_wm_hints (ew);
959 /* These seem to get clobbered. I don't know why. - rms. */
960 f->output_data.x->widget->core.x = old_left;
961 f->output_data.x->widget->core.y = old_top;
964 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
965 receive in the ConfigureNotify event; if we get what we asked
966 for, then the event won't cause the screen to become garbaged, so
967 we have to make sure to do it here. */
968 SET_FRAME_GARBAGED (f);