(print): Use current_perdisplay, not get_perdisplay.
[emacs.git] / src / widget.c
blob48810928493c3493fcbacd04b0e0be865ab0c303
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Emacs 19 face widget ported by Fred Pierresteguy */
22 #include <config.h>
23 #include <stdio.h>
24 #include "lisp.h"
25 #include "xterm.h"
27 #include "frame.h"
29 #include "dispextern.h"
32 #include <X11/StringDefs.h>
33 #include <X11/IntrinsicP.h>
34 #include <X11/cursorfont.h>
35 #include "widgetprv.h"
36 #include <X11/ObjectP.h>
37 #include <X11/Shell.h>
38 #include <X11/ShellP.h>
39 #include "../lwlib/lwlib.h"
41 #define max(a, b) ((a) > (b) ? (a) : (b))
43 /* This sucks: this is the first default that x-faces.el tries. This won't
44 be used unless neither the "Emacs.EmacsFrame" resource nor the
45 "Emacs.EmacsFrame" resource is set; the frame
46 may have the wrong default size if this font doesn't exist, but some other
47 font that x-faces.el does. The workaround is to specify some font in the
48 resource database; I don't know a solution other than duplicating the font-
49 searching code from x-faces.el in this file.
51 This also means that if "Emacs.EmacsFrame" is specified as a non-
52 existent font, then Xt is going to substitute "XtDefaultFont" for it,
53 which is a different size than this one. The solution for this is to
54 make x-faces.el try to use XtDefaultFont. The problem with that is that
55 XtDefaultFont is almost certainly variable-width.
57 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
59 #define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
62 static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
63 static void EmacsFrameDestroy (/* Widget */);
64 static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
65 void EmacsFrameResize (/* Widget widget */);
66 static Boolean EmacsFrameSetValues (/* Widget, Widget, Widget,
67 ArgList, Cardinal * */);
68 static XtGeometryResult EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
69 XtWidgetGeometry* */);
72 #undef XtOffset
73 #define XtOffset(p_type,field) \
74 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
75 #define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
77 static XtResource resources[] = {
78 {XtNgeometry, XtCGeometry, XtRString, sizeof(String),
79 offset (geometry), XtRString, (XtPointer) 0},
80 {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
81 offset (iconic), XtRImmediate, (XtPointer) False},
83 {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
84 offset (frame), XtRImmediate, 0},
86 {XtNminibuffer, XtCMinibuffer, XtRInt, sizeof (int),
87 offset (minibuffer), XtRImmediate, (XtPointer)0},
88 {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
89 offset (unsplittable), XtRImmediate, (XtPointer)0},
90 {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
91 offset (internal_border_width), XtRImmediate, (XtPointer)4},
92 {XtNinterline, XtCInterline, XtRInt, sizeof (int),
93 offset (interline), XtRImmediate, (XtPointer)0},
94 {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
95 offset(font),XtRString, DEFAULT_FACE_FONT},
96 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
97 offset(foreground_pixel), XtRString, "XtDefaultForeground"},
98 {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
99 offset(cursor_color), XtRString, "XtDefaultForeground"},
100 {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
101 offset (bar_cursor), XtRImmediate, (XtPointer)0},
102 {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
103 offset (visual_bell), XtRImmediate, (XtPointer)0},
104 {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
105 offset (bell_volume), XtRImmediate, (XtPointer)0},
108 #undef offset
111 static XtActionsRec
112 emacsFrameActionsTable [] = {
113 {"keypress", key_press},
114 {"focus_in", emacs_frame_focus_handler},
115 {"focus_out", emacs_frame_focus_handler},
118 static char
119 emacsFrameTranslations [] = "\
120 <KeyPress>: keypress()\n\
121 <FocusIn>: focus_in()\n\
122 <FocusOut>: focus_out()\n\
126 EmacsFrameClassRec emacsFrameClassRec = {
127 { /* core fields */
128 /* superclass */ &widgetClassRec,
129 /* class_name */ "EmacsFrame",
130 /* widget_size */ sizeof(EmacsFrameRec),
131 /* class_initialize */ 0,
132 /* class_part_initialize */ 0,
133 /* class_inited */ FALSE,
134 /* initialize */ EmacsFrameInitialize,
135 /* initialize_hook */ 0,
136 /* realize */ EmacsFrameRealize,
137 /* actions */ 0, /*emacsFrameActionsTable*/
138 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
139 /* resources */ resources,
140 /* resource_count */ XtNumber(resources),
141 /* xrm_class */ NULLQUARK,
142 /* compress_motion */ TRUE,
143 /* compress_exposure */ TRUE,
144 /* compress_enterleave */ TRUE,
145 /* visible_interest */ FALSE,
146 /* destroy */ EmacsFrameDestroy,
147 /* resize */ EmacsFrameResize,
148 /* expose */ XtInheritExpose,
149 /* set_values */ EmacsFrameSetValues,
150 /* set_values_hook */ 0,
151 /* set_values_almost */ XtInheritSetValuesAlmost,
152 /* get_values_hook */ 0,
153 /* accept_focus */ XtInheritAcceptFocus,
154 /* version */ XtVersion,
155 /* callback_private */ 0,
156 /* tm_table */ 0, /*emacsFrameTranslations*/
157 /* query_geometry */ EmacsFrameQueryGeometry,
158 /* display_accelerator */ XtInheritDisplayAccelerator,
159 /* extension */ 0
163 WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
165 static void
166 get_default_char_pixel_size (ew, pixel_width, pixel_height)
167 EmacsFrame ew;
168 int* pixel_width;
169 int* pixel_height;
171 struct frame* f = ew->emacs_frame.frame;
172 *pixel_width = FONT_WIDTH (f->display.x->font);
173 *pixel_height = f->display.x->line_height;
176 static void
177 pixel_to_char_size (ew, pixel_width, pixel_height, char_width, char_height)
178 EmacsFrame ew;
179 Dimension pixel_width;
180 Dimension pixel_height;
181 int* char_width;
182 int* char_height;
184 struct frame* f = ew->emacs_frame.frame;
185 *char_width = PIXEL_TO_CHAR_WIDTH (f, pixel_width);
186 *char_height = PIXEL_TO_CHAR_HEIGHT (f, pixel_height);
189 static void
190 char_to_pixel_size (ew, char_width, char_height, pixel_width, pixel_height)
191 EmacsFrame ew;
192 int char_width;
193 int char_height;
194 Dimension* pixel_width;
195 Dimension* pixel_height;
197 struct frame* f = ew->emacs_frame.frame;
198 *pixel_width = CHAR_TO_PIXEL_WIDTH (f, char_width);
199 *pixel_height = CHAR_TO_PIXEL_HEIGHT (f, char_height);
202 static void
203 round_size_to_char (ew, in_width, in_height, out_width, out_height)
204 EmacsFrame ew;
205 Dimension in_width;
206 Dimension in_height;
207 Dimension* out_width;
208 Dimension* out_height;
210 int char_width;
211 int char_height;
212 pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
213 char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
216 static Widget
217 get_wm_shell (w)
218 Widget w;
220 Widget wmshell;
222 for (wmshell = XtParent (w);
223 wmshell && !XtIsWMShell (wmshell);
224 wmshell = XtParent (wmshell));
226 return wmshell;
229 static void
230 mark_shell_size_user_specified (wmshell)
231 Widget wmshell;
233 if (! XtIsWMShell (wmshell)) abort ();
234 /* This is kind of sleazy, but I can't see how else to tell it to make it
235 mark the WM_SIZE_HINTS size as user specified when appropriate. */
236 ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
240 /* Can't have static frame locals because of some broken compilers.
241 Normally, initializing a variable like this doesn't work in emacs,
242 but it's ok in this file because it must come after lastfile (and
243 thus have its data not go into text space) because Xt needs to
244 write to initialized data objects too.
246 static Boolean first_frame_p = True;
248 static void
249 set_frame_size (ew)
250 EmacsFrame ew;
252 /* The widget hierarchy is
254 argv[0] emacsShell pane Frame-NAME
255 ApplicationShell EmacsShell Paned EmacsFrame
257 We accept geometry specs in this order:
259 *Frame-NAME.geometry
260 *EmacsFrame.geometry
261 Emacs.geometry
263 Other possibilities for widget hierarchies might be
265 argv[0] frame pane Frame-NAME
266 ApplicationShell EmacsShell Paned EmacsFrame
268 argv[0] Frame-NAME pane Frame-NAME
269 ApplicationShell EmacsShell Paned EmacsFrame
271 argv[0] Frame-NAME pane emacsTextPane
272 ApplicationShell EmacsFrame Paned EmacsTextPane
274 With the current setup, the text-display-area is the part which is
275 an emacs "frame", since that's the only part managed by emacs proper
276 (the menubar and the parent of the menubar and all that sort of thing
277 are managed by lwlib.)
279 The EmacsShell widget is simply a replacement for the Shell widget
280 which is able to deal with using an externally-supplied window instead
281 of always creating its own. It is not actually emacs specific, and
282 should possibly have class "Shell" instead of "EmacsShell" to simplify
283 the resources.
287 /* Geometry of the AppShell */
288 int app_flags = 0;
289 int app_x = 0;
290 int app_y = 0;
291 unsigned int app_w = 0;
292 unsigned int app_h = 0;
294 /* Geometry of the EmacsFrame */
295 int frame_flags = 0;
296 int frame_x = 0;
297 int frame_y = 0;
298 unsigned int frame_w = 0;
299 unsigned int frame_h = 0;
301 /* Hairily merged geometry */
302 int x = 0;
303 int y = 0;
304 unsigned int w = ew->emacs_frame.frame->width;
305 unsigned int h = ew->emacs_frame.frame->height;
306 int flags = 0;
308 Widget wmshell = get_wm_shell ((Widget) ew);
309 /* Each Emacs shell is now independent and top-level. */
310 Widget app_shell = wmshell;
312 if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
314 /* We don't need this for the momment. The geometry is computed in
315 xfns.c. */
316 #if 0
317 /* If the EmacsFrame doesn't have a geometry but the shell does,
318 treat that as the geometry of the frame. (Is this bogus?
319 I'm not sure.) */
320 if (ew->emacs_frame.geometry == 0)
321 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, 0);
323 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
324 this bogus? I'm not sure.) */
325 if (!ew->emacs_frame.iconic)
326 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, 0);
330 char *geom = 0;
331 XtVaGetValues (app_shell, XtNgeometry, &geom, 0);
332 if (geom)
333 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
336 if (ew->emacs_frame.geometry)
337 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
338 &frame_x, &frame_y,
339 &frame_w, &frame_h);
341 if (first_frame_p)
343 /* If this is the first frame created:
344 ====================================
346 - Use the ApplicationShell's size/position, if specified.
347 (This is "Emacs.geometry", or the "-geometry" command line arg.)
348 - Else use the EmacsFrame's size/position.
349 (This is "*Frame-NAME.geometry")
351 - If the AppShell is iconic, the frame should be iconic.
353 AppShell comes first so that -geometry always applies to the first
354 frame created, even if there is an "every frame" entry in the
355 resource database.
357 if (app_flags & (XValue | YValue))
359 x = app_x; y = app_y;
360 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
362 else if (frame_flags & (XValue | YValue))
364 x = frame_x; y = frame_y;
365 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
368 if (app_flags & (WidthValue | HeightValue))
370 w = app_w; h = app_h;
371 flags |= (app_flags & (WidthValue | HeightValue));
373 else if (frame_flags & (WidthValue | HeightValue))
375 w = frame_w; h = frame_h;
376 flags |= (frame_flags & (WidthValue | HeightValue));
379 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
380 if (!ew->emacs_frame.iconic)
381 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, 0);
383 first_frame_p = False;
385 else
387 /* If this is not the first frame created:
388 ========================================
390 - use the EmacsFrame's size/position if specified
391 - Otherwise, use the ApplicationShell's size, but not position.
393 So that means that one can specify the position of the first frame
394 with "Emacs.geometry" or `-geometry'; but can only specify the
395 position of subsequent frames with "*Frame-NAME.geometry".
397 AppShell comes second so that -geometry does not apply to subsequent
398 frames when there is an "every frame" entry in the resource db,
399 but does apply to the first frame.
401 if (frame_flags & (XValue | YValue))
403 x = frame_x; y = frame_y;
404 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
407 if (frame_flags & (WidthValue | HeightValue))
409 w = frame_w; h = frame_h;
410 flags |= (frame_flags & (WidthValue | HeightValue));
412 else if (app_flags & (WidthValue | HeightValue))
414 w = app_w;
415 h = app_h;
416 flags |= (app_flags & (WidthValue | HeightValue));
419 #endif /* 0 */
421 struct frame* frame = ew->emacs_frame.frame;
422 Dimension pixel_width, pixel_height;
423 char shell_position [32];
425 /* Take into account the size of the scrollbar */
426 frame->display.x->vertical_scroll_bar_extra
427 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (frame)
429 : FRAME_SCROLL_BAR_PIXEL_WIDTH (frame) > 0
430 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (frame)
431 : (FRAME_SCROLL_BAR_COLS (frame)
432 * FONT_WIDTH (frame->display.x->font)));
434 change_frame_size (frame, h, w, 1, 0);
435 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
436 ew->core.width = pixel_width;
437 ew->core.height = pixel_height;
439 #if 0 /* xfns.c takes care of this now. */
440 /* If a position was specified, assign it to the shell widget.
441 (Else WM won't do anything with it.)
443 if (flags & (XValue | YValue))
445 /* the tricky things with the sign is to make sure that
446 -0 is printed -0. */
447 int len;
448 char *tem;
449 sprintf (shell_position, "=%c%d%c%d",
450 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
451 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
452 len = strlen (shell_position) + 1;
453 tem = (char *) xmalloc (len);
454 strncpy (tem, shell_position, len);
455 XtVaSetValues (wmshell, XtNgeometry, tem, 0);
457 else if (flags & (WidthValue | HeightValue))
459 int len;
460 char *tem;
461 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
462 len = strlen (shell_position) + 1;
463 tem = (char *) xmalloc (len);
464 strncpy (tem, shell_position, len);
465 XtVaSetValues (wmshell, XtNgeometry, tem, 0);
468 /* If the geometry spec we're using has W/H components, mark the size
469 in the WM_SIZE_HINTS as user specified. */
470 if (flags & (WidthValue | HeightValue))
471 mark_shell_size_user_specified (wmshell);
473 /* Also assign the iconic status of the frame to the Shell, so that
474 the WM sees it. */
475 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, 0);
476 #endif /* 0 */
481 static void
482 update_wm_hints (ew)
483 EmacsFrame ew;
485 Widget wmshell = get_wm_shell ((Widget)ew);
486 int cw;
487 int ch;
488 Dimension rounded_width;
489 Dimension rounded_height;
490 int char_width;
491 int char_height;
492 int base_width;
493 int base_height;
494 int min_rows = 0, min_cols = 0;
496 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
498 pixel_to_char_size (ew, ew->core.width, ew->core.height,
499 &char_width, &char_height);
500 char_to_pixel_size (ew, char_width, char_height,
501 &rounded_width, &rounded_height);
502 get_default_char_pixel_size (ew, &cw, &ch);
504 base_width = (wmshell->core.width - ew->core.width
505 + (rounded_width - (char_width * cw)));
506 base_height = (wmshell->core.height - ew->core.height
507 + (rounded_height - (char_height * ch)));
509 /* This is kind of sleazy, but I can't see how else to tell it to
510 make it mark the WM_SIZE_HINTS size as user specified.
512 /* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
514 XtVaSetValues (wmshell,
515 XtNbaseWidth, base_width,
516 XtNbaseHeight, base_height,
517 XtNwidthInc, cw,
518 XtNheightInc, ch,
519 XtNminWidth, base_width + min_cols * cw,
520 XtNminHeight, base_height + min_rows * ch,
524 static void
525 create_frame_gcs (ew)
526 EmacsFrame ew;
528 struct frame* s = ew->emacs_frame.frame;
530 s->display.x->normal_gc =
531 XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
532 s->display.x->reverse_gc =
533 XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
534 s->display.x->cursor_gc =
535 XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
538 static char setup_frame_cursor_bits[] =
540 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
546 static void
547 setup_frame_gcs (ew)
548 EmacsFrame ew;
550 XGCValues gc_values;
551 struct frame* s = ew->emacs_frame.frame;
552 Pixmap blank_stipple, blank_tile;
554 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
555 XGetGCValues returns uninitialized data when we query the stipple
556 (instead of None or something sensible) and it makes things hard.
558 This should be fixed for real by not querying the GCs but instead having
559 some GC-based cache instead of the current face-based cache which doesn't
560 effectively cache all of the GC settings we need to use.
563 blank_stipple =
564 XCreateBitmapFromData (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
565 setup_frame_cursor_bits, 2, 2);
567 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
568 never actually get used as a background tile!
570 blank_tile =
571 XCreatePixmapFromBitmapData (XtDisplay(ew),
572 RootWindowOfScreen (XtScreen (ew)),
573 setup_frame_cursor_bits, 2, 2, 0, 1,
574 ew->core.depth);
576 /* Normal video */
577 gc_values.font = ew->emacs_frame.font->fid;
578 gc_values.foreground = ew->emacs_frame.foreground_pixel;
579 gc_values.background = ew->core.background_pixel;
580 gc_values.graphics_exposures = False;
581 gc_values.stipple = blank_stipple;
582 gc_values.tile = blank_tile;
583 XChangeGC (XtDisplay (ew), s->display.x->normal_gc,
584 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
585 | GCStipple | GCTile),
586 &gc_values);
588 /* Reverse video style. */
589 gc_values.font = ew->emacs_frame.font->fid;
590 gc_values.foreground = ew->core.background_pixel;
591 gc_values.background = ew->emacs_frame.foreground_pixel;
592 gc_values.graphics_exposures = False;
593 gc_values.stipple = blank_stipple;
594 gc_values.tile = blank_tile;
595 XChangeGC (XtDisplay (ew), s->display.x->reverse_gc,
596 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
597 | GCStipple | GCTile),
598 &gc_values);
600 /* Cursor has to have an empty stipple. */
601 gc_values.font = ew->emacs_frame.font->fid;
602 gc_values.foreground = ew->core.background_pixel;
603 gc_values.background = ew->emacs_frame.cursor_color;
604 gc_values.graphics_exposures = False;
605 gc_values.tile = blank_tile;
606 gc_values.stipple =
607 XCreateBitmapFromData (XtDisplay (ew),
608 RootWindowOfScreen (XtScreen (ew)),
609 setup_frame_cursor_bits, 16, 16);
610 XChangeGC (XtDisplay (ew), s->display.x->cursor_gc,
611 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
612 | GCStipple | GCTile),
613 &gc_values);
616 static void
617 update_various_frame_slots (ew)
618 EmacsFrame ew;
620 struct x_display* x = ew->emacs_frame.frame->display.x;
621 x->pixel_height = ew->core.height;
622 x->pixel_width = ew->core.width;
623 x->internal_border_width = ew->emacs_frame.internal_border_width;
627 static void
628 update_from_various_frame_slots (ew)
629 EmacsFrame ew;
631 struct x_display* x = ew->emacs_frame.frame->display.x;
632 ew->core.height = x->pixel_height;
633 ew->core.width = x->pixel_width;
634 ew->core.background_pixel = x->background_pixel;
635 ew->emacs_frame.internal_border_width = x->internal_border_width;
636 ew->emacs_frame.font = x->font;
637 ew->emacs_frame.foreground_pixel = x->foreground_pixel;
638 ew->emacs_frame.cursor_color = x->cursor_pixel;
639 ew->core.border_pixel = x->border_pixel;
642 static void
643 EmacsFrameInitialize (request, new, dum1, dum2)
644 Widget request;
645 Widget new;
646 ArgList dum1;
647 Cardinal *dum2;
649 EmacsFrame ew = (EmacsFrame)new;
651 if (!ew->emacs_frame.frame)
653 fprintf (stderr,
654 "can't create an emacs frame widget without a frame\n");
655 exit (1);
658 #if 0 /* done in xfns.c */
659 /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
660 resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
661 It's unfortunate that we have to do this, but we need to know the font
662 size for frame-sizing purposes before the faces get initialized. If
663 the "default.attributeFont" isn't set, then we use the font of this
664 EmacsFrame itself, defaulting to XtDefaultFont. Up in the lisp code,
665 the "default" face will use the frame's font if its own is not set,
666 so everything stays in sync -- it's not possible for the frame's font
667 and the default face's font to be different.
670 XFontStruct *f = 0;
671 XtResource face_res;
672 face_res.resource_name = "attributeFont";
673 face_res.resource_class = "AttributeFont";
674 face_res.resource_type = XtRFontStruct;
675 face_res.resource_size = sizeof (XFontStruct *);
676 face_res.resource_offset = 0;
677 face_res.default_type = XtRImmediate;
678 face_res.default_addr = 0;
679 XtGetSubresources ((Widget) ew, (XtPointer) &f, "default", "Face",
680 &face_res, 1, NULL, 0);
682 if (f)
683 ew->emacs_frame.font = f;
684 else if (! ew->emacs_frame.font)
686 fprintf (stderr, "emacs frame widget could not load a font\n");
687 exit (1);
691 /* Update the font field in frame */
692 ew->emacs_frame.frame->display.x->font = ew->emacs_frame.font;
693 #endif
695 update_from_various_frame_slots (ew);
696 set_frame_size (ew);
697 /*create_frame_gcs (ew);
698 setup_frame_gcs (ew);
699 update_various_frame_slots (ew); */
703 static void
704 EmacsFrameRealize (widget, mask, attrs)
705 Widget widget;
706 XtValueMask *mask;
707 XSetWindowAttributes *attrs;
709 EmacsFrame ew = (EmacsFrame)widget;
711 attrs->event_mask = (KeyPressMask | ExposureMask | ButtonPressMask |
712 ButtonReleaseMask | StructureNotifyMask |
713 FocusChangeMask | PointerMotionHintMask |
714 PointerMotionMask | LeaveWindowMask | EnterWindowMask |
715 VisibilityChangeMask | PropertyChangeMask |
716 StructureNotifyMask | SubstructureNotifyMask |
717 SubstructureRedirectMask);
718 *mask |= CWEventMask;
719 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
720 attrs);
721 update_wm_hints (ew);
724 extern void free_frame_faces (/* struct frame * */);
726 static void
727 EmacsFrameDestroy (widget)
728 Widget widget;
730 EmacsFrame ew = (EmacsFrame) widget;
731 struct frame* s = ew->emacs_frame.frame;
733 if (! s) abort ();
734 if (! s->display.x) abort ();
735 if (! s->display.x->normal_gc) abort ();
737 /* this would be called from Fdelete_frame() but it needs to free some
738 stuff after the widget has been finalized but before the widget has
739 been freed. */
740 free_frame_faces (s);
742 /* need to be careful that the face-freeing code doesn't free these too */
743 XFreeGC (XtDisplay (widget), s->display.x->normal_gc);
744 XFreeGC (XtDisplay (widget), s->display.x->reverse_gc);
745 XFreeGC (XtDisplay (widget), s->display.x->cursor_gc);
748 void
749 EmacsFrameResize (widget)
750 Widget widget;
752 EmacsFrame ew = (EmacsFrame)widget;
753 struct frame *f = ew->emacs_frame.frame;
754 int columns;
755 int rows;
757 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
758 change_frame_size (f, rows, columns, 1, 0);
759 update_wm_hints (ew);
760 update_various_frame_slots (ew);
763 static Boolean
764 EmacsFrameSetValues (cur_widget, req_widget, new_widget, dum1, dum2)
765 Widget cur_widget;
766 Widget req_widget;
767 Widget new_widget;
768 ArgList dum1;
769 Cardinal *dum2;
771 EmacsFrame cur = (EmacsFrame)cur_widget;
772 EmacsFrame new = (EmacsFrame)new_widget;
774 Boolean needs_a_refresh = False;
775 Boolean has_to_recompute_size;
776 Boolean has_to_recompute_gcs;
777 Boolean has_to_update_hints;
779 int char_width, char_height;
780 Dimension pixel_width;
781 Dimension pixel_height;
783 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
784 || (cur->emacs_frame.foreground_pixel
785 != new->emacs_frame.foreground_pixel)
786 || (cur->core.background_pixel
787 != new->core.background_pixel)
790 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
791 && cur->core.width == new->core.width
792 && cur->core.height == new->core.height);
794 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
796 if (has_to_recompute_gcs)
798 setup_frame_gcs (new);
799 needs_a_refresh = True;
802 if (has_to_recompute_size)
804 pixel_width = new->core.width;
805 pixel_height = new->core.height;
806 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
807 &char_height);
808 char_to_pixel_size (new, char_width, char_height, &pixel_width,
809 &pixel_height);
810 new->core.width = pixel_width;
811 new->core.height = pixel_height;
813 change_frame_size (new->emacs_frame.frame, char_height, char_width,
814 1, 0);
815 needs_a_refresh = True;
818 if (has_to_update_hints)
819 update_wm_hints (new);
821 update_various_frame_slots (new);
823 /* #### This doesn't work, I haven't been able to find ANY kludge that
824 will let (x-create-frame '((iconic . t))) work. It seems that changes
825 to wm_shell's iconic slot have no effect after it has been realized,
826 and calling XIconifyWindow doesn't work either (even thought the window
827 has been created.) Perhaps there is some property we could smash
828 directly, but I'm sick of this for now. Xt is a steaming pile of shit!
830 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
832 Widget wmshell = get_wm_shell ((Widget) cur);
833 XtVaSetValues (wmshell, XtNiconic, new->emacs_frame.iconic, 0);
836 return needs_a_refresh;
839 static XtGeometryResult
840 EmacsFrameQueryGeometry (widget, request, result)
841 Widget widget;
842 XtWidgetGeometry* request;
843 XtWidgetGeometry* result;
845 EmacsFrame ew = (EmacsFrame)widget;
847 int mask = request->request_mode;
848 Dimension ok_width, ok_height;
850 if (mask & (CWWidth | CWHeight))
852 round_size_to_char (ew,
853 (mask & CWWidth) ? request->width : ew->core.width,
854 ((mask & CWHeight) ? request->height
855 : ew->core.height),
856 &ok_width, &ok_height);
857 if ((mask & CWWidth) && (ok_width != request->width))
859 result->request_mode |= CWWidth;
860 result->width = ok_width;
862 if ((mask & CWHeight) && (ok_height != request->height))
864 result->request_mode |= CWHeight;
865 result->height = ok_height;
868 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
871 /* Special entrypoints */
872 void
873 EmacsFrameSetCharSize (widget, columns, rows)
874 Widget widget;
875 int columns;
876 int rows;
878 EmacsFrame ew = (EmacsFrame) widget;
879 Dimension pixel_width, pixel_height, granted_width, granted_height;
880 XtGeometryResult result;
881 struct frame *f = ew->emacs_frame.frame;
882 Arg al[2];
883 int ac = 0;
885 if (columns < 3) columns = 3; /* no way buddy */
887 check_frame_size (f, &rows, &columns);
888 f->display.x->vertical_scroll_bar_extra
889 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
891 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
892 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
893 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->display.x->font)));
895 char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
897 /* Recompute the entire geometry management. */
898 if (ew->core.width != pixel_width || ew->core.height != pixel_height)
900 int hdelta = pixel_height - ew->core.height;
901 int column_widget_height = f->display.x->column_widget->core.height;
902 int old_left = f->display.x->widget->core.x;
903 int old_top = f->display.x->widget->core.y;
905 lw_refigure_widget (f->display.x->column_widget, False);
906 ac = 0;
907 XtSetArg (al[ac], XtNheight, pixel_height); ac++;
908 XtSetArg (al[ac], XtNwidth, pixel_width); ac++;
909 XtSetValues ((Widget) ew, al, ac);
911 ac = 0;
912 XtSetArg (al[ac], XtNheight, column_widget_height + hdelta); ac++;
913 XtSetArg (al[ac], XtNwidth, pixel_width); ac++;
914 XtSetValues (f->display.x->column_widget, al, ac);
915 lw_refigure_widget (f->display.x->column_widget, True);
917 /* These seem to get clobbered. I don't know why. - rms. */
918 f->display.x->widget->core.x = old_left;
919 f->display.x->widget->core.y = old_top;
922 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
923 receive in the ConfigureNotify event; if we get what we asked
924 for, then the event won't cause the screen to become garbaged, so
925 we have to make sure to do it here. */
926 SET_FRAME_GARBAGED (f);