*** empty log message ***
[emacs.git] / src / widget.c
blobc96405e020526cd20380270af8f38cb8cb88c613
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 #include <config.h>
24 #include <stdio.h>
25 #include "lisp.h"
26 #include "xterm.h"
28 #include "frame.h"
30 #include "dispextern.h"
31 #include "blockinput.h"
33 #include <X11/StringDefs.h>
34 #include <X11/IntrinsicP.h>
35 #include <X11/cursorfont.h>
36 #include "widgetprv.h"
37 #include <X11/ObjectP.h>
38 #include <X11/Shell.h>
39 #include <X11/ShellP.h>
40 #include "../lwlib/lwlib.h"
42 #define max(a, b) ((a) > (b) ? (a) : (b))
44 /* This sucks: this is the first default that x-faces.el tries. This won't
45 be used unless neither the "Emacs.EmacsFrame" resource nor the
46 "Emacs.EmacsFrame" resource is set; the frame
47 may have the wrong default size if this font doesn't exist, but some other
48 font that x-faces.el does. The workaround is to specify some font in the
49 resource database; I don't know a solution other than duplicating the font-
50 searching code from x-faces.el in this file.
52 This also means that if "Emacs.EmacsFrame" is specified as a non-
53 existent font, then Xt is going to substitute "XtDefaultFont" for it,
54 which is a different size than this one. The solution for this is to
55 make x-faces.el try to use XtDefaultFont. The problem with that is that
56 XtDefaultFont is almost certainly variable-width.
58 #### Perhaps we could have this code explicitly set XtDefaultFont to this?
60 #define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
63 static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
64 static void EmacsFrameDestroy (/* Widget */);
65 static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
66 void EmacsFrameResize (/* Widget widget */);
67 static Boolean EmacsFrameSetValues (/* Widget, Widget, Widget,
68 ArgList, Cardinal * */);
69 static XtGeometryResult EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
70 XtWidgetGeometry* */);
73 #undef XtOffset
74 #define XtOffset(p_type,field) \
75 ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
76 #define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
78 static XtResource resources[] = {
79 {XtNgeometry, XtCGeometry, XtRString, sizeof(String),
80 offset (geometry), XtRString, (XtPointer) 0},
81 {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
82 offset (iconic), XtRImmediate, (XtPointer) False},
84 {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
85 offset (frame), XtRImmediate, 0},
87 {XtNminibuffer, XtCMinibuffer, XtRInt, sizeof (int),
88 offset (minibuffer), XtRImmediate, (XtPointer)0},
89 {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
90 offset (unsplittable), XtRImmediate, (XtPointer)0},
91 {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
92 offset (internal_border_width), XtRImmediate, (XtPointer)4},
93 {XtNinterline, XtCInterline, XtRInt, sizeof (int),
94 offset (interline), XtRImmediate, (XtPointer)0},
95 {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
96 offset(font),XtRString, DEFAULT_FACE_FONT},
97 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
98 offset(foreground_pixel), XtRString, "XtDefaultForeground"},
99 {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
100 offset(cursor_color), XtRString, "XtDefaultForeground"},
101 {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
102 offset (bar_cursor), XtRImmediate, (XtPointer)0},
103 {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
104 offset (visual_bell), XtRImmediate, (XtPointer)0},
105 {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
106 offset (bell_volume), XtRImmediate, (XtPointer)0},
109 #undef offset
112 static XtActionsRec
113 emacsFrameActionsTable [] = {
114 {"keypress", key_press},
115 {"focus_in", emacs_frame_focus_handler},
116 {"focus_out", emacs_frame_focus_handler},
119 static char
120 emacsFrameTranslations [] = "\
121 <KeyPress>: keypress()\n\
122 <FocusIn>: focus_in()\n\
123 <FocusOut>: focus_out()\n\
127 EmacsFrameClassRec emacsFrameClassRec = {
128 { /* core fields */
129 /* superclass */ &widgetClassRec,
130 /* class_name */ "EmacsFrame",
131 /* widget_size */ sizeof(EmacsFrameRec),
132 /* class_initialize */ 0,
133 /* class_part_initialize */ 0,
134 /* class_inited */ FALSE,
135 /* initialize */ EmacsFrameInitialize,
136 /* initialize_hook */ 0,
137 /* realize */ EmacsFrameRealize,
138 /* actions */ 0, /*emacsFrameActionsTable*/
139 /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/
140 /* resources */ resources,
141 /* resource_count */ XtNumber(resources),
142 /* xrm_class */ NULLQUARK,
143 /* compress_motion */ TRUE,
144 /* compress_exposure */ TRUE,
145 /* compress_enterleave */ TRUE,
146 /* visible_interest */ FALSE,
147 /* destroy */ EmacsFrameDestroy,
148 /* resize */ EmacsFrameResize,
149 /* expose */ XtInheritExpose,
150 /* set_values */ EmacsFrameSetValues,
151 /* set_values_hook */ 0,
152 /* set_values_almost */ XtInheritSetValuesAlmost,
153 /* get_values_hook */ 0,
154 /* accept_focus */ XtInheritAcceptFocus,
155 /* version */ XtVersion,
156 /* callback_private */ 0,
157 /* tm_table */ 0, /*emacsFrameTranslations*/
158 /* query_geometry */ EmacsFrameQueryGeometry,
159 /* display_accelerator */ XtInheritDisplayAccelerator,
160 /* extension */ 0
164 WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
166 static void
167 get_default_char_pixel_size (ew, pixel_width, pixel_height)
168 EmacsFrame ew;
169 int* pixel_width;
170 int* pixel_height;
172 struct frame* f = ew->emacs_frame.frame;
173 *pixel_width = FONT_WIDTH (f->output_data.x->font);
174 *pixel_height = f->output_data.x->line_height;
177 static void
178 pixel_to_char_size (ew, pixel_width, pixel_height, char_width, char_height)
179 EmacsFrame ew;
180 Dimension pixel_width;
181 Dimension pixel_height;
182 int* char_width;
183 int* char_height;
185 struct frame* f = ew->emacs_frame.frame;
186 *char_width = PIXEL_TO_CHAR_WIDTH (f, pixel_width);
187 *char_height = PIXEL_TO_CHAR_HEIGHT (f, pixel_height);
190 static void
191 char_to_pixel_size (ew, char_width, char_height, pixel_width, pixel_height)
192 EmacsFrame ew;
193 int char_width;
194 int char_height;
195 Dimension* pixel_width;
196 Dimension* pixel_height;
198 struct frame* f = ew->emacs_frame.frame;
199 *pixel_width = CHAR_TO_PIXEL_WIDTH (f, char_width);
200 *pixel_height = CHAR_TO_PIXEL_HEIGHT (f, char_height);
203 static void
204 round_size_to_char (ew, in_width, in_height, out_width, out_height)
205 EmacsFrame ew;
206 Dimension in_width;
207 Dimension in_height;
208 Dimension* out_width;
209 Dimension* out_height;
211 int char_width;
212 int char_height;
213 pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
214 char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
217 static Widget
218 get_wm_shell (w)
219 Widget w;
221 Widget wmshell;
223 for (wmshell = XtParent (w);
224 wmshell && !XtIsWMShell (wmshell);
225 wmshell = XtParent (wmshell));
227 return wmshell;
230 static void
231 mark_shell_size_user_specified (wmshell)
232 Widget wmshell;
234 if (! XtIsWMShell (wmshell)) abort ();
235 /* This is kind of sleazy, but I can't see how else to tell it to make it
236 mark the WM_SIZE_HINTS size as user specified when appropriate. */
237 ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
241 /* Can't have static frame locals because of some broken compilers.
242 Normally, initializing a variable like this doesn't work in emacs,
243 but it's ok in this file because it must come after lastfile (and
244 thus have its data not go into text space) because Xt needs to
245 write to initialized data objects too.
247 static Boolean first_frame_p = True;
249 static void
250 set_frame_size (ew)
251 EmacsFrame ew;
253 /* The widget hierarchy is
255 argv[0] emacsShell pane Frame-NAME
256 ApplicationShell EmacsShell Paned EmacsFrame
258 We accept geometry specs in this order:
260 *Frame-NAME.geometry
261 *EmacsFrame.geometry
262 Emacs.geometry
264 Other possibilities for widget hierarchies might be
266 argv[0] frame pane Frame-NAME
267 ApplicationShell EmacsShell Paned EmacsFrame
269 argv[0] Frame-NAME pane Frame-NAME
270 ApplicationShell EmacsShell Paned EmacsFrame
272 argv[0] Frame-NAME pane emacsTextPane
273 ApplicationShell EmacsFrame Paned EmacsTextPane
275 With the current setup, the text-display-area is the part which is
276 an emacs "frame", since that's the only part managed by emacs proper
277 (the menubar and the parent of the menubar and all that sort of thing
278 are managed by lwlib.)
280 The EmacsShell widget is simply a replacement for the Shell widget
281 which is able to deal with using an externally-supplied window instead
282 of always creating its own. It is not actually emacs specific, and
283 should possibly have class "Shell" instead of "EmacsShell" to simplify
284 the resources.
288 /* Geometry of the AppShell */
289 int app_flags = 0;
290 int app_x = 0;
291 int app_y = 0;
292 unsigned int app_w = 0;
293 unsigned int app_h = 0;
295 /* Geometry of the EmacsFrame */
296 int frame_flags = 0;
297 int frame_x = 0;
298 int frame_y = 0;
299 unsigned int frame_w = 0;
300 unsigned int frame_h = 0;
302 /* Hairily merged geometry */
303 int x = 0;
304 int y = 0;
305 unsigned int w = ew->emacs_frame.frame->width;
306 unsigned int h = ew->emacs_frame.frame->height;
307 int flags = 0;
309 Widget wmshell = get_wm_shell ((Widget) ew);
310 /* Each Emacs shell is now independent and top-level. */
311 Widget app_shell = wmshell;
313 if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
315 /* We don't need this for the moment. The geometry is computed in
316 xfns.c. */
317 #if 0
318 /* If the EmacsFrame doesn't have a geometry but the shell does,
319 treat that as the geometry of the frame. (Is this bogus?
320 I'm not sure.) */
321 if (ew->emacs_frame.geometry == 0)
322 XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, 0);
324 /* If the Shell is iconic, then the EmacsFrame is iconic. (Is
325 this bogus? I'm not sure.) */
326 if (!ew->emacs_frame.iconic)
327 XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, 0);
331 char *geom = 0;
332 XtVaGetValues (app_shell, XtNgeometry, &geom, 0);
333 if (geom)
334 app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
337 if (ew->emacs_frame.geometry)
338 frame_flags = XParseGeometry (ew->emacs_frame.geometry,
339 &frame_x, &frame_y,
340 &frame_w, &frame_h);
342 if (first_frame_p)
344 /* If this is the first frame created:
345 ====================================
347 - Use the ApplicationShell's size/position, if specified.
348 (This is "Emacs.geometry", or the "-geometry" command line arg.)
349 - Else use the EmacsFrame's size/position.
350 (This is "*Frame-NAME.geometry")
352 - If the AppShell is iconic, the frame should be iconic.
354 AppShell comes first so that -geometry always applies to the first
355 frame created, even if there is an "every frame" entry in the
356 resource database.
358 if (app_flags & (XValue | YValue))
360 x = app_x; y = app_y;
361 flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
363 else if (frame_flags & (XValue | YValue))
365 x = frame_x; y = frame_y;
366 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
369 if (app_flags & (WidthValue | HeightValue))
371 w = app_w; h = app_h;
372 flags |= (app_flags & (WidthValue | HeightValue));
374 else if (frame_flags & (WidthValue | HeightValue))
376 w = frame_w; h = frame_h;
377 flags |= (frame_flags & (WidthValue | HeightValue));
380 /* If the AppShell is iconic, then the EmacsFrame is iconic. */
381 if (!ew->emacs_frame.iconic)
382 XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, 0);
384 first_frame_p = False;
386 else
388 /* If this is not the first frame created:
389 ========================================
391 - use the EmacsFrame's size/position if specified
392 - Otherwise, use the ApplicationShell's size, but not position.
394 So that means that one can specify the position of the first frame
395 with "Emacs.geometry" or `-geometry'; but can only specify the
396 position of subsequent frames with "*Frame-NAME.geometry".
398 AppShell comes second so that -geometry does not apply to subsequent
399 frames when there is an "every frame" entry in the resource db,
400 but does apply to the first frame.
402 if (frame_flags & (XValue | YValue))
404 x = frame_x; y = frame_y;
405 flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
408 if (frame_flags & (WidthValue | HeightValue))
410 w = frame_w; h = frame_h;
411 flags |= (frame_flags & (WidthValue | HeightValue));
413 else if (app_flags & (WidthValue | HeightValue))
415 w = app_w;
416 h = app_h;
417 flags |= (app_flags & (WidthValue | HeightValue));
420 #endif /* 0 */
422 struct frame* frame = ew->emacs_frame.frame;
423 Dimension pixel_width, pixel_height;
424 char shell_position [32];
426 /* Take into account the size of the scrollbar */
427 frame->output_data.x->vertical_scroll_bar_extra
428 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (frame)
430 : FRAME_SCROLL_BAR_PIXEL_WIDTH (frame) > 0
431 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (frame)
432 : (FRAME_SCROLL_BAR_COLS (frame)
433 * FONT_WIDTH (frame->output_data.x->font)));
435 change_frame_size (frame, h, w, 1, 0);
436 char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
437 ew->core.width = pixel_width;
438 ew->core.height = pixel_height;
440 #if 0 /* xfns.c takes care of this now. */
441 /* If a position was specified, assign it to the shell widget.
442 (Else WM won't do anything with it.)
444 if (flags & (XValue | YValue))
446 /* the tricky things with the sign is to make sure that
447 -0 is printed -0. */
448 int len;
449 char *tem;
450 sprintf (shell_position, "=%c%d%c%d",
451 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
452 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
453 len = strlen (shell_position) + 1;
454 tem = (char *) xmalloc (len);
455 strncpy (tem, shell_position, len);
456 XtVaSetValues (wmshell, XtNgeometry, tem, 0);
458 else if (flags & (WidthValue | HeightValue))
460 int len;
461 char *tem;
462 sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
463 len = strlen (shell_position) + 1;
464 tem = (char *) xmalloc (len);
465 strncpy (tem, shell_position, len);
466 XtVaSetValues (wmshell, XtNgeometry, tem, 0);
469 /* If the geometry spec we're using has W/H components, mark the size
470 in the WM_SIZE_HINTS as user specified. */
471 if (flags & (WidthValue | HeightValue))
472 mark_shell_size_user_specified (wmshell);
474 /* Also assign the iconic status of the frame to the Shell, so that
475 the WM sees it. */
476 XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, 0);
477 #endif /* 0 */
481 /* Nonzero tells update_wm_hints not to do anything
482 (the caller should call update_wm_hints explicitly later.) */
483 int update_hints_inhibit;
485 static void
486 update_wm_hints (ew)
487 EmacsFrame ew;
489 Widget wmshell = get_wm_shell ((Widget)ew);
490 int cw;
491 int ch;
492 Dimension rounded_width;
493 Dimension rounded_height;
494 int char_width;
495 int char_height;
496 int base_width;
497 int base_height;
498 int min_rows = 0, min_cols = 0;
500 if (update_hints_inhibit)
501 return;
503 #if 0
504 check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
505 #endif
507 pixel_to_char_size (ew, ew->core.width, ew->core.height,
508 &char_width, &char_height);
509 char_to_pixel_size (ew, char_width, char_height,
510 &rounded_width, &rounded_height);
511 get_default_char_pixel_size (ew, &cw, &ch);
513 base_width = (wmshell->core.width - ew->core.width
514 + (rounded_width - (char_width * cw)));
515 base_height = (wmshell->core.height - ew->core.height
516 + (rounded_height - (char_height * ch)));
518 /* This is kind of sleazy, but I can't see how else to tell it to
519 make it mark the WM_SIZE_HINTS size as user specified.
521 /* ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
523 XtVaSetValues (wmshell,
524 XtNbaseWidth, base_width,
525 XtNbaseHeight, base_height,
526 XtNwidthInc, cw,
527 XtNheightInc, ch,
528 XtNminWidth, base_width + min_cols * cw,
529 XtNminHeight, base_height + min_rows * ch,
533 static void
534 create_frame_gcs (ew)
535 EmacsFrame ew;
537 struct frame *s = ew->emacs_frame.frame;
539 s->output_data.x->normal_gc
540 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
541 (unsigned long)0, (XGCValues *)0);
542 s->output_data.x->reverse_gc
543 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
544 (unsigned long)0, (XGCValues *)0);
545 s->output_data.x->cursor_gc
546 = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
547 (unsigned long)0, (XGCValues *)0);
550 static char setup_frame_cursor_bits[] =
552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
553 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
558 static void
559 setup_frame_gcs (ew)
560 EmacsFrame ew;
562 XGCValues gc_values;
563 struct frame* s = ew->emacs_frame.frame;
564 Pixmap blank_stipple, blank_tile;
566 /* We have to initialize all of our GCs to have a stipple/tile, otherwise
567 XGetGCValues returns uninitialized data when we query the stipple
568 (instead of None or something sensible) and it makes things hard.
570 This should be fixed for real by not querying the GCs but instead having
571 some GC-based cache instead of the current face-based cache which doesn't
572 effectively cache all of the GC settings we need to use.
575 blank_stipple
576 = XCreateBitmapFromData (XtDisplay (ew),
577 RootWindowOfScreen (XtScreen (ew)),
578 setup_frame_cursor_bits, 2, 2);
580 /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
581 never actually get used as a background tile!
583 blank_tile
584 = XCreatePixmapFromBitmapData (XtDisplay(ew),
585 RootWindowOfScreen (XtScreen (ew)),
586 setup_frame_cursor_bits, 2, 2,
587 (unsigned long)0, (unsigned long)1,
588 ew->core.depth);
590 /* Normal video */
591 gc_values.font = ew->emacs_frame.font->fid;
592 gc_values.foreground = ew->emacs_frame.foreground_pixel;
593 gc_values.background = ew->core.background_pixel;
594 gc_values.graphics_exposures = False;
595 gc_values.stipple = blank_stipple;
596 gc_values.tile = blank_tile;
597 XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
598 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
599 | GCStipple | GCTile),
600 &gc_values);
602 /* Reverse video style. */
603 gc_values.font = ew->emacs_frame.font->fid;
604 gc_values.foreground = ew->core.background_pixel;
605 gc_values.background = ew->emacs_frame.foreground_pixel;
606 gc_values.graphics_exposures = False;
607 gc_values.stipple = blank_stipple;
608 gc_values.tile = blank_tile;
609 XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
610 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
611 | GCStipple | GCTile),
612 &gc_values);
614 /* Cursor has to have an empty stipple. */
615 gc_values.font = ew->emacs_frame.font->fid;
616 gc_values.foreground = ew->core.background_pixel;
617 gc_values.background = ew->emacs_frame.cursor_color;
618 gc_values.graphics_exposures = False;
619 gc_values.tile = blank_tile;
620 gc_values.stipple
621 = XCreateBitmapFromData (XtDisplay (ew),
622 RootWindowOfScreen (XtScreen (ew)),
623 setup_frame_cursor_bits, 16, 16);
624 XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
625 (GCFont | GCForeground | GCBackground | GCGraphicsExposures
626 | GCStipple | GCTile),
627 &gc_values);
630 static void
631 update_various_frame_slots (ew)
632 EmacsFrame ew;
634 struct x_output *x = ew->emacs_frame.frame->output_data.x;
635 x->pixel_height = ew->core.height;
636 x->pixel_width = ew->core.width;
637 x->internal_border_width = ew->emacs_frame.internal_border_width;
641 static void
642 update_from_various_frame_slots (ew)
643 EmacsFrame ew;
645 struct x_output *x = ew->emacs_frame.frame->output_data.x;
646 ew->core.height = x->pixel_height;
647 ew->core.width = x->pixel_width;
648 ew->core.background_pixel = x->background_pixel;
649 ew->emacs_frame.internal_border_width = x->internal_border_width;
650 ew->emacs_frame.font = x->font;
651 ew->emacs_frame.foreground_pixel = x->foreground_pixel;
652 ew->emacs_frame.cursor_color = x->cursor_pixel;
653 ew->core.border_pixel = x->border_pixel;
656 static void
657 EmacsFrameInitialize (request, new, dum1, dum2)
658 Widget request;
659 Widget new;
660 ArgList dum1;
661 Cardinal *dum2;
663 EmacsFrame ew = (EmacsFrame)new;
665 if (!ew->emacs_frame.frame)
667 fprintf (stderr,
668 "can't create an emacs frame widget without a frame\n");
669 exit (1);
672 #if 0 /* done in xfns.c */
673 /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
674 resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
675 It's unfortunate that we have to do this, but we need to know the font
676 size for frame-sizing purposes before the faces get initialized. If
677 the "default.attributeFont" isn't set, then we use the font of this
678 EmacsFrame itself, defaulting to XtDefaultFont. Up in the lisp code,
679 the "default" face will use the frame's font if its own is not set,
680 so everything stays in sync -- it's not possible for the frame's font
681 and the default face's font to be different.
684 XFontStruct *f = 0;
685 XtResource face_res;
686 face_res.resource_name = "attributeFont";
687 face_res.resource_class = "AttributeFont";
688 face_res.resource_type = XtRFontStruct;
689 face_res.resource_size = sizeof (XFontStruct *);
690 face_res.resource_offset = 0;
691 face_res.default_type = XtRImmediate;
692 face_res.default_addr = 0;
693 XtGetSubresources ((Widget) ew, (XtPointer) &f, "default", "Face",
694 &face_res, 1, NULL, 0);
696 if (f)
697 ew->emacs_frame.font = f;
698 else if (! ew->emacs_frame.font)
700 fprintf (stderr, "emacs frame widget could not load a font\n");
701 exit (1);
705 /* Update the font field in frame */
706 ew->emacs_frame.frame->output_data.x->font = ew->emacs_frame.font;
707 #endif
709 update_from_various_frame_slots (ew);
710 set_frame_size (ew);
711 /*create_frame_gcs (ew);
712 setup_frame_gcs (ew);
713 update_various_frame_slots (ew); */
717 static void
718 EmacsFrameRealize (widget, mask, attrs)
719 Widget widget;
720 XtValueMask *mask;
721 XSetWindowAttributes *attrs;
723 EmacsFrame ew = (EmacsFrame)widget;
725 attrs->event_mask = (KeyPressMask | ExposureMask | ButtonPressMask |
726 ButtonReleaseMask | StructureNotifyMask |
727 FocusChangeMask | PointerMotionHintMask |
728 PointerMotionMask | LeaveWindowMask | EnterWindowMask |
729 VisibilityChangeMask | PropertyChangeMask |
730 StructureNotifyMask | SubstructureNotifyMask |
731 SubstructureRedirectMask);
732 *mask |= CWEventMask;
733 XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
734 attrs);
735 update_wm_hints (ew);
738 extern void free_frame_faces (/* struct frame * */);
740 static void
741 EmacsFrameDestroy (widget)
742 Widget widget;
744 EmacsFrame ew = (EmacsFrame) widget;
745 struct frame* s = ew->emacs_frame.frame;
747 if (! s) abort ();
748 if (! s->output_data.x) abort ();
749 if (! s->output_data.x->normal_gc) abort ();
751 /* this would be called from Fdelete_frame() but it needs to free some
752 stuff after the widget has been finalized but before the widget has
753 been freed. */
754 free_frame_faces (s);
756 BLOCK_INPUT;
757 /* need to be careful that the face-freeing code doesn't free these too */
758 XFreeGC (XtDisplay (widget), s->output_data.x->normal_gc);
759 XFreeGC (XtDisplay (widget), s->output_data.x->reverse_gc);
760 XFreeGC (XtDisplay (widget), s->output_data.x->cursor_gc);
761 UNBLOCK_INPUT;
764 void
765 EmacsFrameResize (widget)
766 Widget widget;
768 EmacsFrame ew = (EmacsFrame)widget;
769 struct frame *f = ew->emacs_frame.frame;
770 int columns;
771 int rows;
773 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
774 change_frame_size (f, rows, columns, 1, 0);
775 update_wm_hints (ew);
776 update_various_frame_slots (ew);
779 static Boolean
780 EmacsFrameSetValues (cur_widget, req_widget, new_widget, dum1, dum2)
781 Widget cur_widget;
782 Widget req_widget;
783 Widget new_widget;
784 ArgList dum1;
785 Cardinal *dum2;
787 EmacsFrame cur = (EmacsFrame)cur_widget;
788 EmacsFrame new = (EmacsFrame)new_widget;
790 Boolean needs_a_refresh = False;
791 Boolean has_to_recompute_size;
792 Boolean has_to_recompute_gcs;
793 Boolean has_to_update_hints;
795 int char_width, char_height;
796 Dimension pixel_width;
797 Dimension pixel_height;
799 has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
800 || (cur->emacs_frame.foreground_pixel
801 != new->emacs_frame.foreground_pixel)
802 || (cur->core.background_pixel
803 != new->core.background_pixel)
806 has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
807 && cur->core.width == new->core.width
808 && cur->core.height == new->core.height);
810 has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
812 if (has_to_recompute_gcs)
814 setup_frame_gcs (new);
815 needs_a_refresh = True;
818 if (has_to_recompute_size)
820 pixel_width = new->core.width;
821 pixel_height = new->core.height;
822 pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
823 &char_height);
824 char_to_pixel_size (new, char_width, char_height, &pixel_width,
825 &pixel_height);
826 new->core.width = pixel_width;
827 new->core.height = pixel_height;
829 change_frame_size (new->emacs_frame.frame, char_height, char_width,
830 1, 0);
831 needs_a_refresh = True;
834 if (has_to_update_hints)
835 update_wm_hints (new);
837 update_various_frame_slots (new);
839 /* #### This doesn't work, I haven't been able to find ANY kludge that
840 will let (x-create-frame '((iconic . t))) work. It seems that changes
841 to wm_shell's iconic slot have no effect after it has been realized,
842 and calling XIconifyWindow doesn't work either (even thought the window
843 has been created.) Perhaps there is some property we could smash
844 directly, but I'm sick of this for now. Xt is a steaming pile of shit!
846 if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
848 Widget wmshell = get_wm_shell ((Widget) cur);
849 XtVaSetValues (wmshell, XtNiconic, new->emacs_frame.iconic, 0);
852 return needs_a_refresh;
855 static XtGeometryResult
856 EmacsFrameQueryGeometry (widget, request, result)
857 Widget widget;
858 XtWidgetGeometry* request;
859 XtWidgetGeometry* result;
861 EmacsFrame ew = (EmacsFrame)widget;
863 int mask = request->request_mode;
864 Dimension ok_width, ok_height;
866 if (mask & (CWWidth | CWHeight))
868 round_size_to_char (ew,
869 (mask & CWWidth) ? request->width : ew->core.width,
870 ((mask & CWHeight) ? request->height
871 : ew->core.height),
872 &ok_width, &ok_height);
873 if ((mask & CWWidth) && (ok_width != request->width))
875 result->request_mode |= CWWidth;
876 result->width = ok_width;
878 if ((mask & CWHeight) && (ok_height != request->height))
880 result->request_mode |= CWHeight;
881 result->height = ok_height;
884 return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
887 /* Special entrypoints */
888 void
889 EmacsFrameSetCharSize (widget, columns, rows)
890 Widget widget;
891 int columns;
892 int rows;
894 EmacsFrame ew = (EmacsFrame) widget;
895 Dimension pixel_width, pixel_height, granted_width, granted_height;
896 XtGeometryResult result;
897 struct frame *f = ew->emacs_frame.frame;
898 Arg al[2];
899 int ac = 0;
901 if (columns < 3) columns = 3; /* no way buddy */
903 check_frame_size (f, &rows, &columns);
904 f->output_data.x->vertical_scroll_bar_extra
905 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
907 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
908 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
909 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
911 char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
913 /* Manually change the height and width of all our widgets,
914 adjusting each widget by the same increments. */
915 if (ew->core.width != pixel_width || ew->core.height != pixel_height)
917 int hdelta = pixel_height - ew->core.height;
918 int wdelta = pixel_width - ew->core.width;
919 int column_widget_height = f->output_data.x->column_widget->core.height;
920 int column_widget_width = f->output_data.x->column_widget->core.width;
921 int outer_widget_height = f->output_data.x->widget->core.height;
922 int outer_widget_width = f->output_data.x->widget->core.width;
923 int old_left = f->output_data.x->widget->core.x;
924 int old_top = f->output_data.x->widget->core.y;
926 lw_refigure_widget (f->output_data.x->column_widget, False);
927 update_hints_inhibit = 1;
929 ac = 0;
930 XtSetArg (al[ac], XtNheight, pixel_height); ac++;
931 XtSetArg (al[ac], XtNwidth, pixel_width); ac++;
932 XtSetValues ((Widget) ew, al, ac);
934 ac = 0;
935 XtSetArg (al[ac], XtNheight, column_widget_height + hdelta); ac++;
936 XtSetArg (al[ac], XtNwidth, column_widget_width + wdelta); ac++;
937 XtSetValues (f->output_data.x->column_widget, al, ac);
939 ac = 0;
940 XtSetArg (al[ac], XtNheight, outer_widget_height + hdelta); ac++;
941 XtSetArg (al[ac], XtNwidth, outer_widget_width + wdelta); ac++;
942 XtSetValues (f->output_data.x->widget, al, ac);
944 lw_refigure_widget (f->output_data.x->column_widget, True);
946 update_hints_inhibit = 0;
947 update_wm_hints (ew);
949 /* These seem to get clobbered. I don't know why. - rms. */
950 f->output_data.x->widget->core.x = old_left;
951 f->output_data.x->widget->core.y = old_top;
954 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
955 receive in the ConfigureNotify event; if we get what we asked
956 for, then the event won't cause the screen to become garbaged, so
957 we have to make sure to do it here. */
958 SET_FRAME_GARBAGED (f);